@camstack/addon-cloudflare 1.2.26 → 1.2.28
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/{dist-DnohT9Id.mjs → dist-BmCe-liz.mjs} +184 -34
- package/dist/{dist-CbCaiEpw.js → dist-BvZr1B8F.js} +184 -34
- package/dist/tunnel/cloudflare-tunnel.addon.js +29 -3
- package/dist/tunnel/cloudflare-tunnel.addon.mjs +29 -3
- package/dist/turn/cloudflare-turn.addon.js +1 -1
- package/dist/turn/cloudflare-turn.addon.mjs +1 -1
- package/package.json +1 -1
|
@@ -5800,6 +5800,13 @@ var BaseAddon = class {
|
|
|
5800
5800
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
5801
5801
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
5802
5802
|
_registeredCapNames = [];
|
|
5803
|
+
/**
|
|
5804
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
5805
|
+
* defaults look like stored config when the store is down — a forked
|
|
5806
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
5807
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
5808
|
+
*/
|
|
5809
|
+
settingsStoreReady = false;
|
|
5803
5810
|
/** Default config values. Provided via constructor. */
|
|
5804
5811
|
defaults;
|
|
5805
5812
|
constructor(defaults) {
|
|
@@ -6200,7 +6207,9 @@ var BaseAddon = class {
|
|
|
6200
6207
|
];
|
|
6201
6208
|
let lastErr;
|
|
6202
6209
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
6203
|
-
|
|
6210
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
6211
|
+
this.settingsStoreReady = true;
|
|
6212
|
+
return stored;
|
|
6204
6213
|
} catch (err) {
|
|
6205
6214
|
lastErr = err;
|
|
6206
6215
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6208,6 +6217,7 @@ var BaseAddon = class {
|
|
|
6208
6217
|
if (attempt === delaysMs.length) break;
|
|
6209
6218
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
6210
6219
|
}
|
|
6220
|
+
this.settingsStoreReady = false;
|
|
6211
6221
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
6212
6222
|
return {};
|
|
6213
6223
|
}
|
|
@@ -8095,6 +8105,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8095
8105
|
*/
|
|
8096
8106
|
resolution: number().int().positive().optional()
|
|
8097
8107
|
});
|
|
8108
|
+
var ModelProviderIdSchema = _enum([
|
|
8109
|
+
"camstack",
|
|
8110
|
+
"frigate",
|
|
8111
|
+
"scrypted",
|
|
8112
|
+
"custom"
|
|
8113
|
+
]);
|
|
8098
8114
|
var ModelCatalogEntrySchema = object({
|
|
8099
8115
|
id: string(),
|
|
8100
8116
|
name: string(),
|
|
@@ -8192,6 +8208,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
8192
8208
|
*/
|
|
8193
8209
|
group: ModelVariantGroupSchema.optional(),
|
|
8194
8210
|
/**
|
|
8211
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
8212
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
8213
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
8214
|
+
*/
|
|
8215
|
+
provider: ModelProviderIdSchema.optional(),
|
|
8216
|
+
/**
|
|
8195
8217
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
8196
8218
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8197
8219
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -11741,6 +11763,27 @@ var LinkedDeviceSchema = object({
|
|
|
11741
11763
|
features: array(string()),
|
|
11742
11764
|
producesTrackedEvents: boolean().optional()
|
|
11743
11765
|
});
|
|
11766
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
11767
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
11768
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
11769
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
11770
|
+
deviceId: number(),
|
|
11771
|
+
mode: LinkedDevicesModeSchema,
|
|
11772
|
+
devices: array(LinkedDeviceSchema)
|
|
11773
|
+
});
|
|
11774
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
11775
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
11776
|
+
* object literal is exactly how the three drift apart. */
|
|
11777
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
11778
|
+
deviceId: number(),
|
|
11779
|
+
entries: array(object({
|
|
11780
|
+
capName: string(),
|
|
11781
|
+
kind: _enum(["native", "wrapped"]),
|
|
11782
|
+
providerAddonId: string(),
|
|
11783
|
+
providerNodeId: string(),
|
|
11784
|
+
nativeAddonId: string()
|
|
11785
|
+
}))
|
|
11786
|
+
});
|
|
11744
11787
|
var SavedDeviceRowSchema = object({
|
|
11745
11788
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
11746
11789
|
id: number(),
|
|
@@ -11966,11 +12009,25 @@ method(object({
|
|
|
11966
12009
|
projection: _enum(["full", "slim"]).optional(),
|
|
11967
12010
|
/** Return only camera devices. Filtering server-side instead of
|
|
11968
12011
|
* shipping 293 rows to find 12. */
|
|
11969
|
-
isCamera: boolean().optional()
|
|
12012
|
+
isCamera: boolean().optional(),
|
|
12013
|
+
/**
|
|
12014
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
12015
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
12016
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
12017
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
12018
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
12019
|
+
* refetches on the reconcile interval, on a phone.
|
|
12020
|
+
*
|
|
12021
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
12022
|
+
* keys rather than rejecting them (verified against the live hub
|
|
12023
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
12024
|
+
* it answers today and the caller filters as it already does.
|
|
12025
|
+
*/
|
|
12026
|
+
deviceIds: array(number()).optional()
|
|
11970
12027
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
11971
12028
|
mode: LinkedDevicesModeSchema,
|
|
11972
12029
|
devices: array(LinkedDeviceSchema)
|
|
11973
|
-
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
12030
|
+
})), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
11974
12031
|
deviceId: number(),
|
|
11975
12032
|
values: record(string(), unknown())
|
|
11976
12033
|
}), object({ success: literal(true) }), {
|
|
@@ -11997,25 +12054,7 @@ method(object({
|
|
|
11997
12054
|
}), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
|
|
11998
12055
|
kind: "mutation",
|
|
11999
12056
|
auth: "admin"
|
|
12000
|
-
}), method(object({ deviceId: number() }), object({
|
|
12001
|
-
deviceId: number(),
|
|
12002
|
-
entries: array(object({
|
|
12003
|
-
capName: string(),
|
|
12004
|
-
kind: _enum(["native", "wrapped"]),
|
|
12005
|
-
providerAddonId: string(),
|
|
12006
|
-
providerNodeId: string(),
|
|
12007
|
-
nativeAddonId: string()
|
|
12008
|
-
}))
|
|
12009
|
-
})), method(object({}), array(object({
|
|
12010
|
-
deviceId: number(),
|
|
12011
|
-
entries: array(object({
|
|
12012
|
-
capName: string(),
|
|
12013
|
-
kind: _enum(["native", "wrapped"]),
|
|
12014
|
-
providerAddonId: string(),
|
|
12015
|
-
providerNodeId: string(),
|
|
12016
|
-
nativeAddonId: string()
|
|
12017
|
-
}))
|
|
12018
|
-
}))), method(object({
|
|
12057
|
+
}), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
12019
12058
|
deviceId: number(),
|
|
12020
12059
|
capName: string(),
|
|
12021
12060
|
wrapperAddonId: string(),
|
|
@@ -14404,12 +14443,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
14404
14443
|
* there is no second switch that can disagree with the first and every rule
|
|
14405
14444
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
14406
14445
|
*
|
|
14407
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
14408
|
-
*
|
|
14409
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
14410
|
-
*
|
|
14411
|
-
*
|
|
14412
|
-
*
|
|
14446
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
14447
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
14448
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
14449
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
14450
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
14451
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
14452
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
14453
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
14454
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
14413
14455
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14414
14456
|
* the condition: at least `hitPercent`% of the samples over
|
|
14415
14457
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -14436,14 +14478,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
14436
14478
|
* an operator who typed `dog` mean the same thing.
|
|
14437
14479
|
*/
|
|
14438
14480
|
var NcAudioConditionSchema = object({
|
|
14439
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
14481
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
14440
14482
|
labels: array(string().min(1)).min(1).optional(),
|
|
14441
14483
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14442
14484
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
14443
14485
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14444
14486
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
14445
14487
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14446
|
-
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
14488
|
+
samplingSeconds: number().int().min(1).max(300).default(10),
|
|
14489
|
+
/**
|
|
14490
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
14491
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
14492
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
14493
|
+
*/
|
|
14494
|
+
confirmHits: number().int().min(1).max(20).optional(),
|
|
14495
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
14496
|
+
confirmWindowSec: number().int().min(1).max(60).optional()
|
|
14447
14497
|
});
|
|
14448
14498
|
/**
|
|
14449
14499
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -16817,6 +16867,46 @@ var RecentTracksPageSchema = object({
|
|
|
16817
16867
|
/** Cursor for the next page, or null when this page is the last. */
|
|
16818
16868
|
nextCursor: string().nullable()
|
|
16819
16869
|
});
|
|
16870
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
16871
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
16872
|
+
var AnalyticsGroupRecordSchema = object({
|
|
16873
|
+
id: string(),
|
|
16874
|
+
deviceId: number().int(),
|
|
16875
|
+
openedAt: number().int(),
|
|
16876
|
+
closedAt: number().int(),
|
|
16877
|
+
timestamp: number().int(),
|
|
16878
|
+
memberCount: number().int(),
|
|
16879
|
+
memberTrackIds: array(string()).readonly(),
|
|
16880
|
+
className: string(),
|
|
16881
|
+
classes: array(string()).readonly(),
|
|
16882
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
16883
|
+
mediaUrl: string().nullable(),
|
|
16884
|
+
singleton: boolean()
|
|
16885
|
+
});
|
|
16886
|
+
var AnalyticsGroupMemberSchema = object({
|
|
16887
|
+
trackId: string(),
|
|
16888
|
+
deviceId: number().int(),
|
|
16889
|
+
className: string(),
|
|
16890
|
+
firstSeen: number().int(),
|
|
16891
|
+
lastSeen: number().int(),
|
|
16892
|
+
mediaUrl: string().nullable()
|
|
16893
|
+
});
|
|
16894
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
16895
|
+
var ListGroupsQueryInput = object({
|
|
16896
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
16897
|
+
deviceIds: array(number()),
|
|
16898
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
16899
|
+
since: number().optional(),
|
|
16900
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
16901
|
+
until: number().optional(),
|
|
16902
|
+
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
16903
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
16904
|
+
cursor: string().optional()
|
|
16905
|
+
});
|
|
16906
|
+
var ListGroupsPageSchema = object({
|
|
16907
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
16908
|
+
nextCursor: string().nullable()
|
|
16909
|
+
});
|
|
16820
16910
|
var KeyEventQueryInput = object({
|
|
16821
16911
|
deviceId: number(),
|
|
16822
16912
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -16892,7 +16982,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
16892
16982
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
16893
16983
|
plates: number().int(),
|
|
16894
16984
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16895
|
-
embeddings: number().int()
|
|
16985
|
+
embeddings: number().int(),
|
|
16986
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
16987
|
+
groups: number().int()
|
|
16896
16988
|
});
|
|
16897
16989
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16898
16990
|
var DiskReconcileCountsSchema = object({
|
|
@@ -17038,7 +17130,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17038
17130
|
* stationary registry). Default false: the timeline lists passages,
|
|
17039
17131
|
* not parking records (operator decision, 2026-08-15). */
|
|
17040
17132
|
includeStationary: boolean().optional()
|
|
17041
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
17133
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
17134
|
+
deviceId: number(),
|
|
17135
|
+
groupId: string().min(1)
|
|
17136
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
17042
17137
|
kind: "mutation",
|
|
17043
17138
|
auth: "admin"
|
|
17044
17139
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -17348,7 +17443,8 @@ var PipelineModelOptionSchema = object({
|
|
|
17348
17443
|
sizeMB: number()
|
|
17349
17444
|
})),
|
|
17350
17445
|
group: ModelVariantGroupSchema.optional(),
|
|
17351
|
-
legacy: boolean().optional()
|
|
17446
|
+
legacy: boolean().optional(),
|
|
17447
|
+
provider: ModelProviderIdSchema.optional()
|
|
17352
17448
|
});
|
|
17353
17449
|
var ConfigFieldBridge = custom();
|
|
17354
17450
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -23955,7 +24051,12 @@ var PlateInfoSchema = object({
|
|
|
23955
24051
|
plateBbox: BoundingBoxSchema.optional(),
|
|
23956
24052
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
23957
24053
|
keyFrameMediaKey: string().optional(),
|
|
23958
|
-
base64: string().optional()
|
|
24054
|
+
base64: string().optional(),
|
|
24055
|
+
/**
|
|
24056
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
24057
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
24058
|
+
*/
|
|
24059
|
+
cropUrl: string().optional()
|
|
23959
24060
|
});
|
|
23960
24061
|
var MediaFileLiteSchema = object({
|
|
23961
24062
|
key: string(),
|
|
@@ -27595,6 +27696,12 @@ Object.freeze({
|
|
|
27595
27696
|
addonId: null,
|
|
27596
27697
|
access: "view"
|
|
27597
27698
|
},
|
|
27699
|
+
"deviceManager.getBindingsBatch": {
|
|
27700
|
+
capName: "device-manager",
|
|
27701
|
+
capScope: "system",
|
|
27702
|
+
addonId: null,
|
|
27703
|
+
access: "view"
|
|
27704
|
+
},
|
|
27598
27705
|
"deviceManager.getChildren": {
|
|
27599
27706
|
capName: "device-manager",
|
|
27600
27707
|
capScope: "system",
|
|
@@ -27655,6 +27762,12 @@ Object.freeze({
|
|
|
27655
27762
|
addonId: null,
|
|
27656
27763
|
access: "view"
|
|
27657
27764
|
},
|
|
27765
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
27766
|
+
capName: "device-manager",
|
|
27767
|
+
capScope: "system",
|
|
27768
|
+
addonId: null,
|
|
27769
|
+
access: "view"
|
|
27770
|
+
},
|
|
27658
27771
|
"deviceManager.getRoleDisplayDefaults": {
|
|
27659
27772
|
capName: "device-manager",
|
|
27660
27773
|
capScope: "system",
|
|
@@ -29425,6 +29538,12 @@ Object.freeze({
|
|
|
29425
29538
|
addonId: null,
|
|
29426
29539
|
access: "view"
|
|
29427
29540
|
},
|
|
29541
|
+
"pipelineAnalytics.getGroup": {
|
|
29542
|
+
capName: "pipeline-analytics",
|
|
29543
|
+
capScope: "device",
|
|
29544
|
+
addonId: null,
|
|
29545
|
+
access: "view"
|
|
29546
|
+
},
|
|
29428
29547
|
"pipelineAnalytics.getKeyEvents": {
|
|
29429
29548
|
capName: "pipeline-analytics",
|
|
29430
29549
|
capScope: "device",
|
|
@@ -29509,6 +29628,12 @@ Object.freeze({
|
|
|
29509
29628
|
addonId: null,
|
|
29510
29629
|
access: "view"
|
|
29511
29630
|
},
|
|
29631
|
+
"pipelineAnalytics.listGroups": {
|
|
29632
|
+
capName: "pipeline-analytics",
|
|
29633
|
+
capScope: "device",
|
|
29634
|
+
addonId: null,
|
|
29635
|
+
access: "view"
|
|
29636
|
+
},
|
|
29512
29637
|
"pipelineAnalytics.listOpsLog": {
|
|
29513
29638
|
capName: "pipeline-analytics",
|
|
29514
29639
|
capScope: "device",
|
|
@@ -32290,6 +32415,11 @@ Object.freeze({
|
|
|
32290
32415
|
form: "single",
|
|
32291
32416
|
optional: false
|
|
32292
32417
|
}],
|
|
32418
|
+
"deviceManager.getBindingsBatch": [{
|
|
32419
|
+
name: "deviceIds",
|
|
32420
|
+
form: "array",
|
|
32421
|
+
optional: false
|
|
32422
|
+
}],
|
|
32293
32423
|
"deviceManager.getChildren": [{
|
|
32294
32424
|
name: "parentDeviceId",
|
|
32295
32425
|
form: "single",
|
|
@@ -32335,6 +32465,11 @@ Object.freeze({
|
|
|
32335
32465
|
form: "single",
|
|
32336
32466
|
optional: false
|
|
32337
32467
|
}],
|
|
32468
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
32469
|
+
name: "deviceIds",
|
|
32470
|
+
form: "array",
|
|
32471
|
+
optional: false
|
|
32472
|
+
}],
|
|
32338
32473
|
"deviceManager.getSettingsSchema": [{
|
|
32339
32474
|
name: "deviceId",
|
|
32340
32475
|
form: "single",
|
|
@@ -32355,6 +32490,11 @@ Object.freeze({
|
|
|
32355
32490
|
form: "single",
|
|
32356
32491
|
optional: false
|
|
32357
32492
|
}],
|
|
32493
|
+
"deviceManager.listAll": [{
|
|
32494
|
+
name: "deviceIds",
|
|
32495
|
+
form: "array",
|
|
32496
|
+
optional: true
|
|
32497
|
+
}],
|
|
32358
32498
|
"deviceManager.loadConfig": [{
|
|
32359
32499
|
name: "deviceId",
|
|
32360
32500
|
form: "single",
|
|
@@ -32928,6 +33068,11 @@ Object.freeze({
|
|
|
32928
33068
|
form: "single",
|
|
32929
33069
|
optional: false
|
|
32930
33070
|
}],
|
|
33071
|
+
"pipelineAnalytics.getGroup": [{
|
|
33072
|
+
name: "deviceId",
|
|
33073
|
+
form: "single",
|
|
33074
|
+
optional: false
|
|
33075
|
+
}],
|
|
32931
33076
|
"pipelineAnalytics.getKeyEvents": [{
|
|
32932
33077
|
name: "deviceId",
|
|
32933
33078
|
form: "single",
|
|
@@ -32983,6 +33128,11 @@ Object.freeze({
|
|
|
32983
33128
|
form: "array",
|
|
32984
33129
|
optional: false
|
|
32985
33130
|
}],
|
|
33131
|
+
"pipelineAnalytics.listGroups": [{
|
|
33132
|
+
name: "deviceIds",
|
|
33133
|
+
form: "array",
|
|
33134
|
+
optional: false
|
|
33135
|
+
}],
|
|
32986
33136
|
"pipelineAnalytics.listOpsLog": [{
|
|
32987
33137
|
name: "deviceId",
|
|
32988
33138
|
form: "single",
|
|
@@ -5800,6 +5800,13 @@ var BaseAddon = class {
|
|
|
5800
5800
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
5801
5801
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
5802
5802
|
_registeredCapNames = [];
|
|
5803
|
+
/**
|
|
5804
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
5805
|
+
* defaults look like stored config when the store is down — a forked
|
|
5806
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
5807
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
5808
|
+
*/
|
|
5809
|
+
settingsStoreReady = false;
|
|
5803
5810
|
/** Default config values. Provided via constructor. */
|
|
5804
5811
|
defaults;
|
|
5805
5812
|
constructor(defaults) {
|
|
@@ -6200,7 +6207,9 @@ var BaseAddon = class {
|
|
|
6200
6207
|
];
|
|
6201
6208
|
let lastErr;
|
|
6202
6209
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
6203
|
-
|
|
6210
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
6211
|
+
this.settingsStoreReady = true;
|
|
6212
|
+
return stored;
|
|
6204
6213
|
} catch (err) {
|
|
6205
6214
|
lastErr = err;
|
|
6206
6215
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6208,6 +6217,7 @@ var BaseAddon = class {
|
|
|
6208
6217
|
if (attempt === delaysMs.length) break;
|
|
6209
6218
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
6210
6219
|
}
|
|
6220
|
+
this.settingsStoreReady = false;
|
|
6211
6221
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
6212
6222
|
return {};
|
|
6213
6223
|
}
|
|
@@ -8095,6 +8105,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8095
8105
|
*/
|
|
8096
8106
|
resolution: number().int().positive().optional()
|
|
8097
8107
|
});
|
|
8108
|
+
var ModelProviderIdSchema = _enum([
|
|
8109
|
+
"camstack",
|
|
8110
|
+
"frigate",
|
|
8111
|
+
"scrypted",
|
|
8112
|
+
"custom"
|
|
8113
|
+
]);
|
|
8098
8114
|
var ModelCatalogEntrySchema = object({
|
|
8099
8115
|
id: string(),
|
|
8100
8116
|
name: string(),
|
|
@@ -8192,6 +8208,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
8192
8208
|
*/
|
|
8193
8209
|
group: ModelVariantGroupSchema.optional(),
|
|
8194
8210
|
/**
|
|
8211
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
8212
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
8213
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
8214
|
+
*/
|
|
8215
|
+
provider: ModelProviderIdSchema.optional(),
|
|
8216
|
+
/**
|
|
8195
8217
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
8196
8218
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8197
8219
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -11741,6 +11763,27 @@ var LinkedDeviceSchema = object({
|
|
|
11741
11763
|
features: array(string()),
|
|
11742
11764
|
producesTrackedEvents: boolean().optional()
|
|
11743
11765
|
});
|
|
11766
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
11767
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
11768
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
11769
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
11770
|
+
deviceId: number(),
|
|
11771
|
+
mode: LinkedDevicesModeSchema,
|
|
11772
|
+
devices: array(LinkedDeviceSchema)
|
|
11773
|
+
});
|
|
11774
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
11775
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
11776
|
+
* object literal is exactly how the three drift apart. */
|
|
11777
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
11778
|
+
deviceId: number(),
|
|
11779
|
+
entries: array(object({
|
|
11780
|
+
capName: string(),
|
|
11781
|
+
kind: _enum(["native", "wrapped"]),
|
|
11782
|
+
providerAddonId: string(),
|
|
11783
|
+
providerNodeId: string(),
|
|
11784
|
+
nativeAddonId: string()
|
|
11785
|
+
}))
|
|
11786
|
+
});
|
|
11744
11787
|
var SavedDeviceRowSchema = object({
|
|
11745
11788
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
11746
11789
|
id: number(),
|
|
@@ -11966,11 +12009,25 @@ method(object({
|
|
|
11966
12009
|
projection: _enum(["full", "slim"]).optional(),
|
|
11967
12010
|
/** Return only camera devices. Filtering server-side instead of
|
|
11968
12011
|
* shipping 293 rows to find 12. */
|
|
11969
|
-
isCamera: boolean().optional()
|
|
12012
|
+
isCamera: boolean().optional(),
|
|
12013
|
+
/**
|
|
12014
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
12015
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
12016
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
12017
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
12018
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
12019
|
+
* refetches on the reconcile interval, on a phone.
|
|
12020
|
+
*
|
|
12021
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
12022
|
+
* keys rather than rejecting them (verified against the live hub
|
|
12023
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
12024
|
+
* it answers today and the caller filters as it already does.
|
|
12025
|
+
*/
|
|
12026
|
+
deviceIds: array(number()).optional()
|
|
11970
12027
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
11971
12028
|
mode: LinkedDevicesModeSchema,
|
|
11972
12029
|
devices: array(LinkedDeviceSchema)
|
|
11973
|
-
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
12030
|
+
})), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
11974
12031
|
deviceId: number(),
|
|
11975
12032
|
values: record(string(), unknown())
|
|
11976
12033
|
}), object({ success: literal(true) }), {
|
|
@@ -11997,25 +12054,7 @@ method(object({
|
|
|
11997
12054
|
}), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
|
|
11998
12055
|
kind: "mutation",
|
|
11999
12056
|
auth: "admin"
|
|
12000
|
-
}), method(object({ deviceId: number() }), object({
|
|
12001
|
-
deviceId: number(),
|
|
12002
|
-
entries: array(object({
|
|
12003
|
-
capName: string(),
|
|
12004
|
-
kind: _enum(["native", "wrapped"]),
|
|
12005
|
-
providerAddonId: string(),
|
|
12006
|
-
providerNodeId: string(),
|
|
12007
|
-
nativeAddonId: string()
|
|
12008
|
-
}))
|
|
12009
|
-
})), method(object({}), array(object({
|
|
12010
|
-
deviceId: number(),
|
|
12011
|
-
entries: array(object({
|
|
12012
|
-
capName: string(),
|
|
12013
|
-
kind: _enum(["native", "wrapped"]),
|
|
12014
|
-
providerAddonId: string(),
|
|
12015
|
-
providerNodeId: string(),
|
|
12016
|
-
nativeAddonId: string()
|
|
12017
|
-
}))
|
|
12018
|
-
}))), method(object({
|
|
12057
|
+
}), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
12019
12058
|
deviceId: number(),
|
|
12020
12059
|
capName: string(),
|
|
12021
12060
|
wrapperAddonId: string(),
|
|
@@ -14404,12 +14443,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
14404
14443
|
* there is no second switch that can disagree with the first and every rule
|
|
14405
14444
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
14406
14445
|
*
|
|
14407
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
14408
|
-
*
|
|
14409
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
14410
|
-
*
|
|
14411
|
-
*
|
|
14412
|
-
*
|
|
14446
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
14447
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
14448
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
14449
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
14450
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
14451
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
14452
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
14453
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
14454
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
14413
14455
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14414
14456
|
* the condition: at least `hitPercent`% of the samples over
|
|
14415
14457
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -14436,14 +14478,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
14436
14478
|
* an operator who typed `dog` mean the same thing.
|
|
14437
14479
|
*/
|
|
14438
14480
|
var NcAudioConditionSchema = object({
|
|
14439
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
14481
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
14440
14482
|
labels: array(string().min(1)).min(1).optional(),
|
|
14441
14483
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14442
14484
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
14443
14485
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14444
14486
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
14445
14487
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14446
|
-
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
14488
|
+
samplingSeconds: number().int().min(1).max(300).default(10),
|
|
14489
|
+
/**
|
|
14490
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
14491
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
14492
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
14493
|
+
*/
|
|
14494
|
+
confirmHits: number().int().min(1).max(20).optional(),
|
|
14495
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
14496
|
+
confirmWindowSec: number().int().min(1).max(60).optional()
|
|
14447
14497
|
});
|
|
14448
14498
|
/**
|
|
14449
14499
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -16817,6 +16867,46 @@ var RecentTracksPageSchema = object({
|
|
|
16817
16867
|
/** Cursor for the next page, or null when this page is the last. */
|
|
16818
16868
|
nextCursor: string().nullable()
|
|
16819
16869
|
});
|
|
16870
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
16871
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
16872
|
+
var AnalyticsGroupRecordSchema = object({
|
|
16873
|
+
id: string(),
|
|
16874
|
+
deviceId: number().int(),
|
|
16875
|
+
openedAt: number().int(),
|
|
16876
|
+
closedAt: number().int(),
|
|
16877
|
+
timestamp: number().int(),
|
|
16878
|
+
memberCount: number().int(),
|
|
16879
|
+
memberTrackIds: array(string()).readonly(),
|
|
16880
|
+
className: string(),
|
|
16881
|
+
classes: array(string()).readonly(),
|
|
16882
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
16883
|
+
mediaUrl: string().nullable(),
|
|
16884
|
+
singleton: boolean()
|
|
16885
|
+
});
|
|
16886
|
+
var AnalyticsGroupMemberSchema = object({
|
|
16887
|
+
trackId: string(),
|
|
16888
|
+
deviceId: number().int(),
|
|
16889
|
+
className: string(),
|
|
16890
|
+
firstSeen: number().int(),
|
|
16891
|
+
lastSeen: number().int(),
|
|
16892
|
+
mediaUrl: string().nullable()
|
|
16893
|
+
});
|
|
16894
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
16895
|
+
var ListGroupsQueryInput = object({
|
|
16896
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
16897
|
+
deviceIds: array(number()),
|
|
16898
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
16899
|
+
since: number().optional(),
|
|
16900
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
16901
|
+
until: number().optional(),
|
|
16902
|
+
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
16903
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
16904
|
+
cursor: string().optional()
|
|
16905
|
+
});
|
|
16906
|
+
var ListGroupsPageSchema = object({
|
|
16907
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
16908
|
+
nextCursor: string().nullable()
|
|
16909
|
+
});
|
|
16820
16910
|
var KeyEventQueryInput = object({
|
|
16821
16911
|
deviceId: number(),
|
|
16822
16912
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -16892,7 +16982,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
16892
16982
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
16893
16983
|
plates: number().int(),
|
|
16894
16984
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16895
|
-
embeddings: number().int()
|
|
16985
|
+
embeddings: number().int(),
|
|
16986
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
16987
|
+
groups: number().int()
|
|
16896
16988
|
});
|
|
16897
16989
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16898
16990
|
var DiskReconcileCountsSchema = object({
|
|
@@ -17038,7 +17130,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17038
17130
|
* stationary registry). Default false: the timeline lists passages,
|
|
17039
17131
|
* not parking records (operator decision, 2026-08-15). */
|
|
17040
17132
|
includeStationary: boolean().optional()
|
|
17041
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
17133
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
17134
|
+
deviceId: number(),
|
|
17135
|
+
groupId: string().min(1)
|
|
17136
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
17042
17137
|
kind: "mutation",
|
|
17043
17138
|
auth: "admin"
|
|
17044
17139
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -17348,7 +17443,8 @@ var PipelineModelOptionSchema = object({
|
|
|
17348
17443
|
sizeMB: number()
|
|
17349
17444
|
})),
|
|
17350
17445
|
group: ModelVariantGroupSchema.optional(),
|
|
17351
|
-
legacy: boolean().optional()
|
|
17446
|
+
legacy: boolean().optional(),
|
|
17447
|
+
provider: ModelProviderIdSchema.optional()
|
|
17352
17448
|
});
|
|
17353
17449
|
var ConfigFieldBridge = custom();
|
|
17354
17450
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -23955,7 +24051,12 @@ var PlateInfoSchema = object({
|
|
|
23955
24051
|
plateBbox: BoundingBoxSchema.optional(),
|
|
23956
24052
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
23957
24053
|
keyFrameMediaKey: string().optional(),
|
|
23958
|
-
base64: string().optional()
|
|
24054
|
+
base64: string().optional(),
|
|
24055
|
+
/**
|
|
24056
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
24057
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
24058
|
+
*/
|
|
24059
|
+
cropUrl: string().optional()
|
|
23959
24060
|
});
|
|
23960
24061
|
var MediaFileLiteSchema = object({
|
|
23961
24062
|
key: string(),
|
|
@@ -27595,6 +27696,12 @@ Object.freeze({
|
|
|
27595
27696
|
addonId: null,
|
|
27596
27697
|
access: "view"
|
|
27597
27698
|
},
|
|
27699
|
+
"deviceManager.getBindingsBatch": {
|
|
27700
|
+
capName: "device-manager",
|
|
27701
|
+
capScope: "system",
|
|
27702
|
+
addonId: null,
|
|
27703
|
+
access: "view"
|
|
27704
|
+
},
|
|
27598
27705
|
"deviceManager.getChildren": {
|
|
27599
27706
|
capName: "device-manager",
|
|
27600
27707
|
capScope: "system",
|
|
@@ -27655,6 +27762,12 @@ Object.freeze({
|
|
|
27655
27762
|
addonId: null,
|
|
27656
27763
|
access: "view"
|
|
27657
27764
|
},
|
|
27765
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
27766
|
+
capName: "device-manager",
|
|
27767
|
+
capScope: "system",
|
|
27768
|
+
addonId: null,
|
|
27769
|
+
access: "view"
|
|
27770
|
+
},
|
|
27658
27771
|
"deviceManager.getRoleDisplayDefaults": {
|
|
27659
27772
|
capName: "device-manager",
|
|
27660
27773
|
capScope: "system",
|
|
@@ -29425,6 +29538,12 @@ Object.freeze({
|
|
|
29425
29538
|
addonId: null,
|
|
29426
29539
|
access: "view"
|
|
29427
29540
|
},
|
|
29541
|
+
"pipelineAnalytics.getGroup": {
|
|
29542
|
+
capName: "pipeline-analytics",
|
|
29543
|
+
capScope: "device",
|
|
29544
|
+
addonId: null,
|
|
29545
|
+
access: "view"
|
|
29546
|
+
},
|
|
29428
29547
|
"pipelineAnalytics.getKeyEvents": {
|
|
29429
29548
|
capName: "pipeline-analytics",
|
|
29430
29549
|
capScope: "device",
|
|
@@ -29509,6 +29628,12 @@ Object.freeze({
|
|
|
29509
29628
|
addonId: null,
|
|
29510
29629
|
access: "view"
|
|
29511
29630
|
},
|
|
29631
|
+
"pipelineAnalytics.listGroups": {
|
|
29632
|
+
capName: "pipeline-analytics",
|
|
29633
|
+
capScope: "device",
|
|
29634
|
+
addonId: null,
|
|
29635
|
+
access: "view"
|
|
29636
|
+
},
|
|
29512
29637
|
"pipelineAnalytics.listOpsLog": {
|
|
29513
29638
|
capName: "pipeline-analytics",
|
|
29514
29639
|
capScope: "device",
|
|
@@ -32290,6 +32415,11 @@ Object.freeze({
|
|
|
32290
32415
|
form: "single",
|
|
32291
32416
|
optional: false
|
|
32292
32417
|
}],
|
|
32418
|
+
"deviceManager.getBindingsBatch": [{
|
|
32419
|
+
name: "deviceIds",
|
|
32420
|
+
form: "array",
|
|
32421
|
+
optional: false
|
|
32422
|
+
}],
|
|
32293
32423
|
"deviceManager.getChildren": [{
|
|
32294
32424
|
name: "parentDeviceId",
|
|
32295
32425
|
form: "single",
|
|
@@ -32335,6 +32465,11 @@ Object.freeze({
|
|
|
32335
32465
|
form: "single",
|
|
32336
32466
|
optional: false
|
|
32337
32467
|
}],
|
|
32468
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
32469
|
+
name: "deviceIds",
|
|
32470
|
+
form: "array",
|
|
32471
|
+
optional: false
|
|
32472
|
+
}],
|
|
32338
32473
|
"deviceManager.getSettingsSchema": [{
|
|
32339
32474
|
name: "deviceId",
|
|
32340
32475
|
form: "single",
|
|
@@ -32355,6 +32490,11 @@ Object.freeze({
|
|
|
32355
32490
|
form: "single",
|
|
32356
32491
|
optional: false
|
|
32357
32492
|
}],
|
|
32493
|
+
"deviceManager.listAll": [{
|
|
32494
|
+
name: "deviceIds",
|
|
32495
|
+
form: "array",
|
|
32496
|
+
optional: true
|
|
32497
|
+
}],
|
|
32358
32498
|
"deviceManager.loadConfig": [{
|
|
32359
32499
|
name: "deviceId",
|
|
32360
32500
|
form: "single",
|
|
@@ -32928,6 +33068,11 @@ Object.freeze({
|
|
|
32928
33068
|
form: "single",
|
|
32929
33069
|
optional: false
|
|
32930
33070
|
}],
|
|
33071
|
+
"pipelineAnalytics.getGroup": [{
|
|
33072
|
+
name: "deviceId",
|
|
33073
|
+
form: "single",
|
|
33074
|
+
optional: false
|
|
33075
|
+
}],
|
|
32931
33076
|
"pipelineAnalytics.getKeyEvents": [{
|
|
32932
33077
|
name: "deviceId",
|
|
32933
33078
|
form: "single",
|
|
@@ -32983,6 +33128,11 @@ Object.freeze({
|
|
|
32983
33128
|
form: "array",
|
|
32984
33129
|
optional: false
|
|
32985
33130
|
}],
|
|
33131
|
+
"pipelineAnalytics.listGroups": [{
|
|
33132
|
+
name: "deviceIds",
|
|
33133
|
+
form: "array",
|
|
33134
|
+
optional: false
|
|
33135
|
+
}],
|
|
32986
33136
|
"pipelineAnalytics.listOpsLog": [{
|
|
32987
33137
|
name: "deviceId",
|
|
32988
33138
|
form: "single",
|
|
@@ -21,7 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
-
const require_dist = require("../dist-
|
|
24
|
+
const require_dist = require("../dist-BvZr1B8F.js");
|
|
25
25
|
let node_crypto = require("node:crypto");
|
|
26
26
|
let node_path = require("node:path");
|
|
27
27
|
node_path = __toESM(node_path);
|
|
@@ -758,6 +758,24 @@ var cloudflareTunnelActions = require_dist.defineCustomActions({
|
|
|
758
758
|
})).readonly() }))
|
|
759
759
|
});
|
|
760
760
|
//#endregion
|
|
761
|
+
//#region src/tunnel/auto-start.ts
|
|
762
|
+
/**
|
|
763
|
+
* Whether cloudflare-tunnel may spawn `cloudflared` at boot / config-reload.
|
|
764
|
+
*
|
|
765
|
+
* Constructor defaults are `mode: 'quick'`. A settings store that has not
|
|
766
|
+
* answered therefore looks exactly like "the operator wants a trycloudflare
|
|
767
|
+
* URL". Auto-starting that is how a named hostname (the one the notification
|
|
768
|
+
* centre still mints) went Cloudflare 530: the named tunnel never connected.
|
|
769
|
+
*
|
|
770
|
+
* An empty store that DID answer is a real choice — a fresh install still
|
|
771
|
+
* auto-starts quick. Only "never answered" is refused.
|
|
772
|
+
*/
|
|
773
|
+
function shouldAutoStartTunnel(input) {
|
|
774
|
+
if (!input.settingsStoreReady) return false;
|
|
775
|
+
if (input.mode === "quick") return true;
|
|
776
|
+
return input.hasCustomToken && input.hasCustomHostname;
|
|
777
|
+
}
|
|
778
|
+
//#endregion
|
|
761
779
|
//#region src/tunnel/cloudflare-tunnel.addon.ts
|
|
762
780
|
/**
|
|
763
781
|
* Cloudflare Tunnel — exposes CamStack via Cloudflare's network.
|
|
@@ -882,6 +900,10 @@ var CloudflareTunnelAddon = class extends require_dist.BaseAddon {
|
|
|
882
900
|
}
|
|
883
901
|
});
|
|
884
902
|
});
|
|
903
|
+
else if (!this.settingsStoreReady) this.ctx.logger.warn("boot auto-start skipped — settings store did not answer; defaults are not an operator choice", { tags: {
|
|
904
|
+
topic: "tunnel",
|
|
905
|
+
phase: "auto-start-skipped"
|
|
906
|
+
} });
|
|
885
907
|
return {
|
|
886
908
|
providers: [{
|
|
887
909
|
capability: require_dist.networkAccessCapability,
|
|
@@ -903,8 +925,12 @@ var CloudflareTunnelAddon = class extends require_dist.BaseAddon {
|
|
|
903
925
|
* auto-start and by `onConfigChanged` to decide whether a change
|
|
904
926
|
* warrants a respawn even when no instance was previously running. */
|
|
905
927
|
isRunCapable() {
|
|
906
|
-
|
|
907
|
-
|
|
928
|
+
return shouldAutoStartTunnel({
|
|
929
|
+
settingsStoreReady: this.settingsStoreReady,
|
|
930
|
+
mode: this.config.mode,
|
|
931
|
+
hasCustomToken: !!this.config.customTunnelToken,
|
|
932
|
+
hasCustomHostname: !!this.config.customHostname
|
|
933
|
+
});
|
|
908
934
|
}
|
|
909
935
|
async onShutdown() {
|
|
910
936
|
if (this.service) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as BaseAddon, c as boolean, d as number, f as object, m as EventCategory, n as defineCustomActions, o as _enum, p as string, r as networkAccessCapability, s as array, t as customAction, u as literal } from "../dist-
|
|
1
|
+
import { a as BaseAddon, c as boolean, d as number, f as object, m as EventCategory, n as defineCustomActions, o as _enum, p as string, r as networkAccessCapability, s as array, t as customAction, u as literal } from "../dist-BmCe-liz.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
@@ -731,6 +731,24 @@ var cloudflareTunnelActions = defineCustomActions({
|
|
|
731
731
|
})).readonly() }))
|
|
732
732
|
});
|
|
733
733
|
//#endregion
|
|
734
|
+
//#region src/tunnel/auto-start.ts
|
|
735
|
+
/**
|
|
736
|
+
* Whether cloudflare-tunnel may spawn `cloudflared` at boot / config-reload.
|
|
737
|
+
*
|
|
738
|
+
* Constructor defaults are `mode: 'quick'`. A settings store that has not
|
|
739
|
+
* answered therefore looks exactly like "the operator wants a trycloudflare
|
|
740
|
+
* URL". Auto-starting that is how a named hostname (the one the notification
|
|
741
|
+
* centre still mints) went Cloudflare 530: the named tunnel never connected.
|
|
742
|
+
*
|
|
743
|
+
* An empty store that DID answer is a real choice — a fresh install still
|
|
744
|
+
* auto-starts quick. Only "never answered" is refused.
|
|
745
|
+
*/
|
|
746
|
+
function shouldAutoStartTunnel(input) {
|
|
747
|
+
if (!input.settingsStoreReady) return false;
|
|
748
|
+
if (input.mode === "quick") return true;
|
|
749
|
+
return input.hasCustomToken && input.hasCustomHostname;
|
|
750
|
+
}
|
|
751
|
+
//#endregion
|
|
734
752
|
//#region src/tunnel/cloudflare-tunnel.addon.ts
|
|
735
753
|
/**
|
|
736
754
|
* Cloudflare Tunnel — exposes CamStack via Cloudflare's network.
|
|
@@ -855,6 +873,10 @@ var CloudflareTunnelAddon = class extends BaseAddon {
|
|
|
855
873
|
}
|
|
856
874
|
});
|
|
857
875
|
});
|
|
876
|
+
else if (!this.settingsStoreReady) this.ctx.logger.warn("boot auto-start skipped — settings store did not answer; defaults are not an operator choice", { tags: {
|
|
877
|
+
topic: "tunnel",
|
|
878
|
+
phase: "auto-start-skipped"
|
|
879
|
+
} });
|
|
858
880
|
return {
|
|
859
881
|
providers: [{
|
|
860
882
|
capability: networkAccessCapability,
|
|
@@ -876,8 +898,12 @@ var CloudflareTunnelAddon = class extends BaseAddon {
|
|
|
876
898
|
* auto-start and by `onConfigChanged` to decide whether a change
|
|
877
899
|
* warrants a respawn even when no instance was previously running. */
|
|
878
900
|
isRunCapable() {
|
|
879
|
-
|
|
880
|
-
|
|
901
|
+
return shouldAutoStartTunnel({
|
|
902
|
+
settingsStoreReady: this.settingsStoreReady,
|
|
903
|
+
mode: this.config.mode,
|
|
904
|
+
hasCustomToken: !!this.config.customTunnelToken,
|
|
905
|
+
hasCustomHostname: !!this.config.customHostname
|
|
906
|
+
});
|
|
881
907
|
}
|
|
882
908
|
async onShutdown() {
|
|
883
909
|
if (this.service) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dist = require("../dist-
|
|
2
|
+
const require_dist = require("../dist-BvZr1B8F.js");
|
|
3
3
|
//#region src/turn/cloudflare-turn.ts
|
|
4
4
|
/**
|
|
5
5
|
* Cloudflare returns ICE servers in several flavours depending on which
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as BaseAddon, c as boolean, d as number, f as object, i as turnProviderCapability, l as discriminatedUnion, n as defineCustomActions, p as string, t as customAction, u as literal } from "../dist-
|
|
1
|
+
import { a as BaseAddon, c as boolean, d as number, f as object, i as turnProviderCapability, l as discriminatedUnion, n as defineCustomActions, p as string, t as customAction, u as literal } from "../dist-BmCe-liz.mjs";
|
|
2
2
|
//#region src/turn/cloudflare-turn.ts
|
|
3
3
|
/**
|
|
4
4
|
* Cloudflare returns ICE servers in several flavours depending on which
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-cloudflare",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.28",
|
|
4
4
|
"description": "Cloudflare bundle — Tunnel (network-access) + TURN relay (turn-provider). Multi-entry npm package shipping 2 addons under a single bundle.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|