@camstack/addon-ai 0.4.17 → 0.4.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon.js +184 -34
- package/dist/addon.mjs +184 -34
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -5964,6 +5964,13 @@ var BaseAddon = class {
|
|
|
5964
5964
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
5965
5965
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
5966
5966
|
_registeredCapNames = [];
|
|
5967
|
+
/**
|
|
5968
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
5969
|
+
* defaults look like stored config when the store is down — a forked
|
|
5970
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
5971
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
5972
|
+
*/
|
|
5973
|
+
settingsStoreReady = false;
|
|
5967
5974
|
/** Default config values. Provided via constructor. */
|
|
5968
5975
|
defaults;
|
|
5969
5976
|
constructor(defaults) {
|
|
@@ -6364,7 +6371,9 @@ var BaseAddon = class {
|
|
|
6364
6371
|
];
|
|
6365
6372
|
let lastErr;
|
|
6366
6373
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
6367
|
-
|
|
6374
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
6375
|
+
this.settingsStoreReady = true;
|
|
6376
|
+
return stored;
|
|
6368
6377
|
} catch (err) {
|
|
6369
6378
|
lastErr = err;
|
|
6370
6379
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6372,6 +6381,7 @@ var BaseAddon = class {
|
|
|
6372
6381
|
if (attempt === delaysMs.length) break;
|
|
6373
6382
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
6374
6383
|
}
|
|
6384
|
+
this.settingsStoreReady = false;
|
|
6375
6385
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
6376
6386
|
return {};
|
|
6377
6387
|
}
|
|
@@ -8318,6 +8328,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8318
8328
|
*/
|
|
8319
8329
|
resolution: number$1().int().positive().optional()
|
|
8320
8330
|
});
|
|
8331
|
+
var ModelProviderIdSchema = _enum([
|
|
8332
|
+
"camstack",
|
|
8333
|
+
"frigate",
|
|
8334
|
+
"scrypted",
|
|
8335
|
+
"custom"
|
|
8336
|
+
]);
|
|
8321
8337
|
var ModelCatalogEntrySchema = object({
|
|
8322
8338
|
id: string(),
|
|
8323
8339
|
name: string(),
|
|
@@ -8415,6 +8431,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
8415
8431
|
*/
|
|
8416
8432
|
group: ModelVariantGroupSchema.optional(),
|
|
8417
8433
|
/**
|
|
8434
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
8435
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
8436
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
8437
|
+
*/
|
|
8438
|
+
provider: ModelProviderIdSchema.optional(),
|
|
8439
|
+
/**
|
|
8418
8440
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
8419
8441
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8420
8442
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -11942,6 +11964,27 @@ var LinkedDeviceSchema = object({
|
|
|
11942
11964
|
features: array(string()),
|
|
11943
11965
|
producesTrackedEvents: boolean().optional()
|
|
11944
11966
|
});
|
|
11967
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
11968
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
11969
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
11970
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
11971
|
+
deviceId: number$1(),
|
|
11972
|
+
mode: LinkedDevicesModeSchema,
|
|
11973
|
+
devices: array(LinkedDeviceSchema)
|
|
11974
|
+
});
|
|
11975
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
11976
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
11977
|
+
* object literal is exactly how the three drift apart. */
|
|
11978
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
11979
|
+
deviceId: number$1(),
|
|
11980
|
+
entries: array(object({
|
|
11981
|
+
capName: string(),
|
|
11982
|
+
kind: _enum(["native", "wrapped"]),
|
|
11983
|
+
providerAddonId: string(),
|
|
11984
|
+
providerNodeId: string(),
|
|
11985
|
+
nativeAddonId: string()
|
|
11986
|
+
}))
|
|
11987
|
+
});
|
|
11945
11988
|
var SavedDeviceRowSchema = object({
|
|
11946
11989
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
11947
11990
|
id: number$1(),
|
|
@@ -12167,11 +12210,25 @@ method(object({
|
|
|
12167
12210
|
projection: _enum(["full", "slim"]).optional(),
|
|
12168
12211
|
/** Return only camera devices. Filtering server-side instead of
|
|
12169
12212
|
* shipping 293 rows to find 12. */
|
|
12170
|
-
isCamera: boolean().optional()
|
|
12213
|
+
isCamera: boolean().optional(),
|
|
12214
|
+
/**
|
|
12215
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
12216
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
12217
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
12218
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
12219
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
12220
|
+
* refetches on the reconcile interval, on a phone.
|
|
12221
|
+
*
|
|
12222
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
12223
|
+
* keys rather than rejecting them (verified against the live hub
|
|
12224
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
12225
|
+
* it answers today and the caller filters as it already does.
|
|
12226
|
+
*/
|
|
12227
|
+
deviceIds: array(number$1()).optional()
|
|
12171
12228
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), object({
|
|
12172
12229
|
mode: LinkedDevicesModeSchema,
|
|
12173
12230
|
devices: array(LinkedDeviceSchema)
|
|
12174
|
-
})), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
|
|
12231
|
+
})), method(object({ deviceIds: array(number$1()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
|
|
12175
12232
|
deviceId: number$1(),
|
|
12176
12233
|
values: record(string(), unknown())
|
|
12177
12234
|
}), object({ success: literal(true) }), {
|
|
@@ -12198,25 +12255,7 @@ method(object({
|
|
|
12198
12255
|
}), method(object({ deviceId: number$1() }), array(StreamProbeResultSchema), {
|
|
12199
12256
|
kind: "mutation",
|
|
12200
12257
|
auth: "admin"
|
|
12201
|
-
}), method(object({ deviceId: number$1() }), object({
|
|
12202
|
-
deviceId: number$1(),
|
|
12203
|
-
entries: array(object({
|
|
12204
|
-
capName: string(),
|
|
12205
|
-
kind: _enum(["native", "wrapped"]),
|
|
12206
|
-
providerAddonId: string(),
|
|
12207
|
-
providerNodeId: string(),
|
|
12208
|
-
nativeAddonId: string()
|
|
12209
|
-
}))
|
|
12210
|
-
})), method(object({}), array(object({
|
|
12211
|
-
deviceId: number$1(),
|
|
12212
|
-
entries: array(object({
|
|
12213
|
-
capName: string(),
|
|
12214
|
-
kind: _enum(["native", "wrapped"]),
|
|
12215
|
-
providerAddonId: string(),
|
|
12216
|
-
providerNodeId: string(),
|
|
12217
|
-
nativeAddonId: string()
|
|
12218
|
-
}))
|
|
12219
|
-
}))), method(object({
|
|
12258
|
+
}), method(object({ deviceId: number$1() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number$1()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
12220
12259
|
deviceId: number$1(),
|
|
12221
12260
|
capName: string(),
|
|
12222
12261
|
wrapperAddonId: string(),
|
|
@@ -14669,12 +14708,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
14669
14708
|
* there is no second switch that can disagree with the first and every rule
|
|
14670
14709
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
14671
14710
|
*
|
|
14672
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
14673
|
-
*
|
|
14674
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
14675
|
-
*
|
|
14676
|
-
*
|
|
14677
|
-
*
|
|
14711
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
14712
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
14713
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
14714
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
14715
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
14716
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
14717
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
14718
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
14719
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
14678
14720
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14679
14721
|
* the condition: at least `hitPercent`% of the samples over
|
|
14680
14722
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -14701,14 +14743,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
14701
14743
|
* an operator who typed `dog` mean the same thing.
|
|
14702
14744
|
*/
|
|
14703
14745
|
var NcAudioConditionSchema = object({
|
|
14704
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
14746
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
14705
14747
|
labels: array(string().min(1)).min(1).optional(),
|
|
14706
14748
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14707
14749
|
dbThreshold: number$1().min(-96).max(0).optional(),
|
|
14708
14750
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14709
14751
|
hitPercent: number$1().int().min(1).max(100).default(60),
|
|
14710
14752
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14711
|
-
samplingSeconds: number$1().int().min(1).max(300).default(10)
|
|
14753
|
+
samplingSeconds: number$1().int().min(1).max(300).default(10),
|
|
14754
|
+
/**
|
|
14755
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
14756
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
14757
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
14758
|
+
*/
|
|
14759
|
+
confirmHits: number$1().int().min(1).max(20).optional(),
|
|
14760
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
14761
|
+
confirmWindowSec: number$1().int().min(1).max(60).optional()
|
|
14712
14762
|
});
|
|
14713
14763
|
/**
|
|
14714
14764
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -17082,6 +17132,46 @@ var RecentTracksPageSchema = object({
|
|
|
17082
17132
|
/** Cursor for the next page, or null when this page is the last. */
|
|
17083
17133
|
nextCursor: string().nullable()
|
|
17084
17134
|
});
|
|
17135
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
17136
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
17137
|
+
var AnalyticsGroupRecordSchema = object({
|
|
17138
|
+
id: string(),
|
|
17139
|
+
deviceId: number$1().int(),
|
|
17140
|
+
openedAt: number$1().int(),
|
|
17141
|
+
closedAt: number$1().int(),
|
|
17142
|
+
timestamp: number$1().int(),
|
|
17143
|
+
memberCount: number$1().int(),
|
|
17144
|
+
memberTrackIds: array(string()).readonly(),
|
|
17145
|
+
className: string(),
|
|
17146
|
+
classes: array(string()).readonly(),
|
|
17147
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
17148
|
+
mediaUrl: string().nullable(),
|
|
17149
|
+
singleton: boolean()
|
|
17150
|
+
});
|
|
17151
|
+
var AnalyticsGroupMemberSchema = object({
|
|
17152
|
+
trackId: string(),
|
|
17153
|
+
deviceId: number$1().int(),
|
|
17154
|
+
className: string(),
|
|
17155
|
+
firstSeen: number$1().int(),
|
|
17156
|
+
lastSeen: number$1().int(),
|
|
17157
|
+
mediaUrl: string().nullable()
|
|
17158
|
+
});
|
|
17159
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
17160
|
+
var ListGroupsQueryInput = object({
|
|
17161
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
17162
|
+
deviceIds: array(number$1()),
|
|
17163
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
17164
|
+
since: number$1().optional(),
|
|
17165
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
17166
|
+
until: number$1().optional(),
|
|
17167
|
+
limit: number$1().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
17168
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
17169
|
+
cursor: string().optional()
|
|
17170
|
+
});
|
|
17171
|
+
var ListGroupsPageSchema = object({
|
|
17172
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
17173
|
+
nextCursor: string().nullable()
|
|
17174
|
+
});
|
|
17085
17175
|
var KeyEventQueryInput = object({
|
|
17086
17176
|
deviceId: number$1(),
|
|
17087
17177
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -17157,7 +17247,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
17157
17247
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
17158
17248
|
plates: number$1().int(),
|
|
17159
17249
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
17160
|
-
embeddings: number$1().int()
|
|
17250
|
+
embeddings: number$1().int(),
|
|
17251
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
17252
|
+
groups: number$1().int()
|
|
17161
17253
|
});
|
|
17162
17254
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
17163
17255
|
var DiskReconcileCountsSchema = object({
|
|
@@ -17303,7 +17395,10 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
17303
17395
|
* stationary registry). Default false: the timeline lists passages,
|
|
17304
17396
|
* not parking records (operator decision, 2026-08-15). */
|
|
17305
17397
|
includeStationary: boolean().optional()
|
|
17306
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
17398
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
17399
|
+
deviceId: number$1(),
|
|
17400
|
+
groupId: string().min(1)
|
|
17401
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number$1() }), _void(), {
|
|
17307
17402
|
kind: "mutation",
|
|
17308
17403
|
auth: "admin"
|
|
17309
17404
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number$1() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number$1()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -17613,7 +17708,8 @@ var PipelineModelOptionSchema = object({
|
|
|
17613
17708
|
sizeMB: number$1()
|
|
17614
17709
|
})),
|
|
17615
17710
|
group: ModelVariantGroupSchema.optional(),
|
|
17616
|
-
legacy: boolean().optional()
|
|
17711
|
+
legacy: boolean().optional(),
|
|
17712
|
+
provider: ModelProviderIdSchema.optional()
|
|
17617
17713
|
});
|
|
17618
17714
|
var ConfigFieldBridge = custom();
|
|
17619
17715
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -24197,7 +24293,12 @@ var PlateInfoSchema = object({
|
|
|
24197
24293
|
plateBbox: BoundingBoxSchema.optional(),
|
|
24198
24294
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
24199
24295
|
keyFrameMediaKey: string().optional(),
|
|
24200
|
-
base64: string().optional()
|
|
24296
|
+
base64: string().optional(),
|
|
24297
|
+
/**
|
|
24298
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
24299
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
24300
|
+
*/
|
|
24301
|
+
cropUrl: string().optional()
|
|
24201
24302
|
});
|
|
24202
24303
|
var MediaFileLiteSchema = object({
|
|
24203
24304
|
key: string(),
|
|
@@ -27837,6 +27938,12 @@ Object.freeze({
|
|
|
27837
27938
|
addonId: null,
|
|
27838
27939
|
access: "view"
|
|
27839
27940
|
},
|
|
27941
|
+
"deviceManager.getBindingsBatch": {
|
|
27942
|
+
capName: "device-manager",
|
|
27943
|
+
capScope: "system",
|
|
27944
|
+
addonId: null,
|
|
27945
|
+
access: "view"
|
|
27946
|
+
},
|
|
27840
27947
|
"deviceManager.getChildren": {
|
|
27841
27948
|
capName: "device-manager",
|
|
27842
27949
|
capScope: "system",
|
|
@@ -27897,6 +28004,12 @@ Object.freeze({
|
|
|
27897
28004
|
addonId: null,
|
|
27898
28005
|
access: "view"
|
|
27899
28006
|
},
|
|
28007
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
28008
|
+
capName: "device-manager",
|
|
28009
|
+
capScope: "system",
|
|
28010
|
+
addonId: null,
|
|
28011
|
+
access: "view"
|
|
28012
|
+
},
|
|
27900
28013
|
"deviceManager.getRoleDisplayDefaults": {
|
|
27901
28014
|
capName: "device-manager",
|
|
27902
28015
|
capScope: "system",
|
|
@@ -29667,6 +29780,12 @@ Object.freeze({
|
|
|
29667
29780
|
addonId: null,
|
|
29668
29781
|
access: "view"
|
|
29669
29782
|
},
|
|
29783
|
+
"pipelineAnalytics.getGroup": {
|
|
29784
|
+
capName: "pipeline-analytics",
|
|
29785
|
+
capScope: "device",
|
|
29786
|
+
addonId: null,
|
|
29787
|
+
access: "view"
|
|
29788
|
+
},
|
|
29670
29789
|
"pipelineAnalytics.getKeyEvents": {
|
|
29671
29790
|
capName: "pipeline-analytics",
|
|
29672
29791
|
capScope: "device",
|
|
@@ -29751,6 +29870,12 @@ Object.freeze({
|
|
|
29751
29870
|
addonId: null,
|
|
29752
29871
|
access: "view"
|
|
29753
29872
|
},
|
|
29873
|
+
"pipelineAnalytics.listGroups": {
|
|
29874
|
+
capName: "pipeline-analytics",
|
|
29875
|
+
capScope: "device",
|
|
29876
|
+
addonId: null,
|
|
29877
|
+
access: "view"
|
|
29878
|
+
},
|
|
29754
29879
|
"pipelineAnalytics.listOpsLog": {
|
|
29755
29880
|
capName: "pipeline-analytics",
|
|
29756
29881
|
capScope: "device",
|
|
@@ -32532,6 +32657,11 @@ Object.freeze({
|
|
|
32532
32657
|
form: "single",
|
|
32533
32658
|
optional: false
|
|
32534
32659
|
}],
|
|
32660
|
+
"deviceManager.getBindingsBatch": [{
|
|
32661
|
+
name: "deviceIds",
|
|
32662
|
+
form: "array",
|
|
32663
|
+
optional: false
|
|
32664
|
+
}],
|
|
32535
32665
|
"deviceManager.getChildren": [{
|
|
32536
32666
|
name: "parentDeviceId",
|
|
32537
32667
|
form: "single",
|
|
@@ -32577,6 +32707,11 @@ Object.freeze({
|
|
|
32577
32707
|
form: "single",
|
|
32578
32708
|
optional: false
|
|
32579
32709
|
}],
|
|
32710
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
32711
|
+
name: "deviceIds",
|
|
32712
|
+
form: "array",
|
|
32713
|
+
optional: false
|
|
32714
|
+
}],
|
|
32580
32715
|
"deviceManager.getSettingsSchema": [{
|
|
32581
32716
|
name: "deviceId",
|
|
32582
32717
|
form: "single",
|
|
@@ -32597,6 +32732,11 @@ Object.freeze({
|
|
|
32597
32732
|
form: "single",
|
|
32598
32733
|
optional: false
|
|
32599
32734
|
}],
|
|
32735
|
+
"deviceManager.listAll": [{
|
|
32736
|
+
name: "deviceIds",
|
|
32737
|
+
form: "array",
|
|
32738
|
+
optional: true
|
|
32739
|
+
}],
|
|
32600
32740
|
"deviceManager.loadConfig": [{
|
|
32601
32741
|
name: "deviceId",
|
|
32602
32742
|
form: "single",
|
|
@@ -33170,6 +33310,11 @@ Object.freeze({
|
|
|
33170
33310
|
form: "single",
|
|
33171
33311
|
optional: false
|
|
33172
33312
|
}],
|
|
33313
|
+
"pipelineAnalytics.getGroup": [{
|
|
33314
|
+
name: "deviceId",
|
|
33315
|
+
form: "single",
|
|
33316
|
+
optional: false
|
|
33317
|
+
}],
|
|
33173
33318
|
"pipelineAnalytics.getKeyEvents": [{
|
|
33174
33319
|
name: "deviceId",
|
|
33175
33320
|
form: "single",
|
|
@@ -33225,6 +33370,11 @@ Object.freeze({
|
|
|
33225
33370
|
form: "array",
|
|
33226
33371
|
optional: false
|
|
33227
33372
|
}],
|
|
33373
|
+
"pipelineAnalytics.listGroups": [{
|
|
33374
|
+
name: "deviceIds",
|
|
33375
|
+
form: "array",
|
|
33376
|
+
optional: false
|
|
33377
|
+
}],
|
|
33228
33378
|
"pipelineAnalytics.listOpsLog": [{
|
|
33229
33379
|
name: "deviceId",
|
|
33230
33380
|
form: "single",
|
package/dist/addon.mjs
CHANGED
|
@@ -5990,6 +5990,13 @@ var BaseAddon = class {
|
|
|
5990
5990
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
5991
5991
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
5992
5992
|
_registeredCapNames = [];
|
|
5993
|
+
/**
|
|
5994
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
5995
|
+
* defaults look like stored config when the store is down — a forked
|
|
5996
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
5997
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
5998
|
+
*/
|
|
5999
|
+
settingsStoreReady = false;
|
|
5993
6000
|
/** Default config values. Provided via constructor. */
|
|
5994
6001
|
defaults;
|
|
5995
6002
|
constructor(defaults) {
|
|
@@ -6390,7 +6397,9 @@ var BaseAddon = class {
|
|
|
6390
6397
|
];
|
|
6391
6398
|
let lastErr;
|
|
6392
6399
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
6393
|
-
|
|
6400
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
6401
|
+
this.settingsStoreReady = true;
|
|
6402
|
+
return stored;
|
|
6394
6403
|
} catch (err) {
|
|
6395
6404
|
lastErr = err;
|
|
6396
6405
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6398,6 +6407,7 @@ var BaseAddon = class {
|
|
|
6398
6407
|
if (attempt === delaysMs.length) break;
|
|
6399
6408
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
6400
6409
|
}
|
|
6410
|
+
this.settingsStoreReady = false;
|
|
6401
6411
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
6402
6412
|
return {};
|
|
6403
6413
|
}
|
|
@@ -8344,6 +8354,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8344
8354
|
*/
|
|
8345
8355
|
resolution: number$1().int().positive().optional()
|
|
8346
8356
|
});
|
|
8357
|
+
var ModelProviderIdSchema = _enum([
|
|
8358
|
+
"camstack",
|
|
8359
|
+
"frigate",
|
|
8360
|
+
"scrypted",
|
|
8361
|
+
"custom"
|
|
8362
|
+
]);
|
|
8347
8363
|
var ModelCatalogEntrySchema = object({
|
|
8348
8364
|
id: string(),
|
|
8349
8365
|
name: string(),
|
|
@@ -8441,6 +8457,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
8441
8457
|
*/
|
|
8442
8458
|
group: ModelVariantGroupSchema.optional(),
|
|
8443
8459
|
/**
|
|
8460
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
8461
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
8462
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
8463
|
+
*/
|
|
8464
|
+
provider: ModelProviderIdSchema.optional(),
|
|
8465
|
+
/**
|
|
8444
8466
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
8445
8467
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8446
8468
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -11968,6 +11990,27 @@ var LinkedDeviceSchema = object({
|
|
|
11968
11990
|
features: array(string()),
|
|
11969
11991
|
producesTrackedEvents: boolean().optional()
|
|
11970
11992
|
});
|
|
11993
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
11994
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
11995
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
11996
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
11997
|
+
deviceId: number$1(),
|
|
11998
|
+
mode: LinkedDevicesModeSchema,
|
|
11999
|
+
devices: array(LinkedDeviceSchema)
|
|
12000
|
+
});
|
|
12001
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
12002
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
12003
|
+
* object literal is exactly how the three drift apart. */
|
|
12004
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
12005
|
+
deviceId: number$1(),
|
|
12006
|
+
entries: array(object({
|
|
12007
|
+
capName: string(),
|
|
12008
|
+
kind: _enum(["native", "wrapped"]),
|
|
12009
|
+
providerAddonId: string(),
|
|
12010
|
+
providerNodeId: string(),
|
|
12011
|
+
nativeAddonId: string()
|
|
12012
|
+
}))
|
|
12013
|
+
});
|
|
11971
12014
|
var SavedDeviceRowSchema = object({
|
|
11972
12015
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
11973
12016
|
id: number$1(),
|
|
@@ -12193,11 +12236,25 @@ method(object({
|
|
|
12193
12236
|
projection: _enum(["full", "slim"]).optional(),
|
|
12194
12237
|
/** Return only camera devices. Filtering server-side instead of
|
|
12195
12238
|
* shipping 293 rows to find 12. */
|
|
12196
|
-
isCamera: boolean().optional()
|
|
12239
|
+
isCamera: boolean().optional(),
|
|
12240
|
+
/**
|
|
12241
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
12242
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
12243
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
12244
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
12245
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
12246
|
+
* refetches on the reconcile interval, on a phone.
|
|
12247
|
+
*
|
|
12248
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
12249
|
+
* keys rather than rejecting them (verified against the live hub
|
|
12250
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
12251
|
+
* it answers today and the caller filters as it already does.
|
|
12252
|
+
*/
|
|
12253
|
+
deviceIds: array(number$1()).optional()
|
|
12197
12254
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number$1() }), array(DeviceInfoSchema)), method(object({ deviceId: number$1() }), object({
|
|
12198
12255
|
mode: LinkedDevicesModeSchema,
|
|
12199
12256
|
devices: array(LinkedDeviceSchema)
|
|
12200
|
-
})), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
|
|
12257
|
+
})), method(object({ deviceIds: array(number$1()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number$1() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number$1() }), array(ConfigEntrySchema)), method(object({ deviceId: number$1() }), ConfigUISchemaOutput), method(object({
|
|
12201
12258
|
deviceId: number$1(),
|
|
12202
12259
|
values: record(string(), unknown())
|
|
12203
12260
|
}), object({ success: literal(true) }), {
|
|
@@ -12224,25 +12281,7 @@ method(object({
|
|
|
12224
12281
|
}), method(object({ deviceId: number$1() }), array(StreamProbeResultSchema), {
|
|
12225
12282
|
kind: "mutation",
|
|
12226
12283
|
auth: "admin"
|
|
12227
|
-
}), method(object({ deviceId: number$1() }), object({
|
|
12228
|
-
deviceId: number$1(),
|
|
12229
|
-
entries: array(object({
|
|
12230
|
-
capName: string(),
|
|
12231
|
-
kind: _enum(["native", "wrapped"]),
|
|
12232
|
-
providerAddonId: string(),
|
|
12233
|
-
providerNodeId: string(),
|
|
12234
|
-
nativeAddonId: string()
|
|
12235
|
-
}))
|
|
12236
|
-
})), method(object({}), array(object({
|
|
12237
|
-
deviceId: number$1(),
|
|
12238
|
-
entries: array(object({
|
|
12239
|
-
capName: string(),
|
|
12240
|
-
kind: _enum(["native", "wrapped"]),
|
|
12241
|
-
providerAddonId: string(),
|
|
12242
|
-
providerNodeId: string(),
|
|
12243
|
-
nativeAddonId: string()
|
|
12244
|
-
}))
|
|
12245
|
-
}))), method(object({
|
|
12284
|
+
}), method(object({ deviceId: number$1() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number$1()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
12246
12285
|
deviceId: number$1(),
|
|
12247
12286
|
capName: string(),
|
|
12248
12287
|
wrapperAddonId: string(),
|
|
@@ -14695,12 +14734,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
14695
14734
|
* there is no second switch that can disagree with the first and every rule
|
|
14696
14735
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
14697
14736
|
*
|
|
14698
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
14699
|
-
*
|
|
14700
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
14701
|
-
*
|
|
14702
|
-
*
|
|
14703
|
-
*
|
|
14737
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
14738
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
14739
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
14740
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
14741
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
14742
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
14743
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
14744
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
14745
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
14704
14746
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14705
14747
|
* the condition: at least `hitPercent`% of the samples over
|
|
14706
14748
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -14727,14 +14769,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
14727
14769
|
* an operator who typed `dog` mean the same thing.
|
|
14728
14770
|
*/
|
|
14729
14771
|
var NcAudioConditionSchema = object({
|
|
14730
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
14772
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
14731
14773
|
labels: array(string().min(1)).min(1).optional(),
|
|
14732
14774
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14733
14775
|
dbThreshold: number$1().min(-96).max(0).optional(),
|
|
14734
14776
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14735
14777
|
hitPercent: number$1().int().min(1).max(100).default(60),
|
|
14736
14778
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14737
|
-
samplingSeconds: number$1().int().min(1).max(300).default(10)
|
|
14779
|
+
samplingSeconds: number$1().int().min(1).max(300).default(10),
|
|
14780
|
+
/**
|
|
14781
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
14782
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
14783
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
14784
|
+
*/
|
|
14785
|
+
confirmHits: number$1().int().min(1).max(20).optional(),
|
|
14786
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
14787
|
+
confirmWindowSec: number$1().int().min(1).max(60).optional()
|
|
14738
14788
|
});
|
|
14739
14789
|
/**
|
|
14740
14790
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -17108,6 +17158,46 @@ var RecentTracksPageSchema = object({
|
|
|
17108
17158
|
/** Cursor for the next page, or null when this page is the last. */
|
|
17109
17159
|
nextCursor: string().nullable()
|
|
17110
17160
|
});
|
|
17161
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
17162
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
17163
|
+
var AnalyticsGroupRecordSchema = object({
|
|
17164
|
+
id: string(),
|
|
17165
|
+
deviceId: number$1().int(),
|
|
17166
|
+
openedAt: number$1().int(),
|
|
17167
|
+
closedAt: number$1().int(),
|
|
17168
|
+
timestamp: number$1().int(),
|
|
17169
|
+
memberCount: number$1().int(),
|
|
17170
|
+
memberTrackIds: array(string()).readonly(),
|
|
17171
|
+
className: string(),
|
|
17172
|
+
classes: array(string()).readonly(),
|
|
17173
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
17174
|
+
mediaUrl: string().nullable(),
|
|
17175
|
+
singleton: boolean()
|
|
17176
|
+
});
|
|
17177
|
+
var AnalyticsGroupMemberSchema = object({
|
|
17178
|
+
trackId: string(),
|
|
17179
|
+
deviceId: number$1().int(),
|
|
17180
|
+
className: string(),
|
|
17181
|
+
firstSeen: number$1().int(),
|
|
17182
|
+
lastSeen: number$1().int(),
|
|
17183
|
+
mediaUrl: string().nullable()
|
|
17184
|
+
});
|
|
17185
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
17186
|
+
var ListGroupsQueryInput = object({
|
|
17187
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
17188
|
+
deviceIds: array(number$1()),
|
|
17189
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
17190
|
+
since: number$1().optional(),
|
|
17191
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
17192
|
+
until: number$1().optional(),
|
|
17193
|
+
limit: number$1().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
17194
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
17195
|
+
cursor: string().optional()
|
|
17196
|
+
});
|
|
17197
|
+
var ListGroupsPageSchema = object({
|
|
17198
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
17199
|
+
nextCursor: string().nullable()
|
|
17200
|
+
});
|
|
17111
17201
|
var KeyEventQueryInput = object({
|
|
17112
17202
|
deviceId: number$1(),
|
|
17113
17203
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -17183,7 +17273,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
17183
17273
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
17184
17274
|
plates: number$1().int(),
|
|
17185
17275
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
17186
|
-
embeddings: number$1().int()
|
|
17276
|
+
embeddings: number$1().int(),
|
|
17277
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
17278
|
+
groups: number$1().int()
|
|
17187
17279
|
});
|
|
17188
17280
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
17189
17281
|
var DiskReconcileCountsSchema = object({
|
|
@@ -17329,7 +17421,10 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
|
|
|
17329
17421
|
* stationary registry). Default false: the timeline lists passages,
|
|
17330
17422
|
* not parking records (operator decision, 2026-08-15). */
|
|
17331
17423
|
includeStationary: boolean().optional()
|
|
17332
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
17424
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
17425
|
+
deviceId: number$1(),
|
|
17426
|
+
groupId: string().min(1)
|
|
17427
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number$1() }), _void(), {
|
|
17333
17428
|
kind: "mutation",
|
|
17334
17429
|
auth: "admin"
|
|
17335
17430
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number$1() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number$1()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -17639,7 +17734,8 @@ var PipelineModelOptionSchema = object({
|
|
|
17639
17734
|
sizeMB: number$1()
|
|
17640
17735
|
})),
|
|
17641
17736
|
group: ModelVariantGroupSchema.optional(),
|
|
17642
|
-
legacy: boolean().optional()
|
|
17737
|
+
legacy: boolean().optional(),
|
|
17738
|
+
provider: ModelProviderIdSchema.optional()
|
|
17643
17739
|
});
|
|
17644
17740
|
var ConfigFieldBridge = custom();
|
|
17645
17741
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -24223,7 +24319,12 @@ var PlateInfoSchema = object({
|
|
|
24223
24319
|
plateBbox: BoundingBoxSchema.optional(),
|
|
24224
24320
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
24225
24321
|
keyFrameMediaKey: string().optional(),
|
|
24226
|
-
base64: string().optional()
|
|
24322
|
+
base64: string().optional(),
|
|
24323
|
+
/**
|
|
24324
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
24325
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
24326
|
+
*/
|
|
24327
|
+
cropUrl: string().optional()
|
|
24227
24328
|
});
|
|
24228
24329
|
var MediaFileLiteSchema = object({
|
|
24229
24330
|
key: string(),
|
|
@@ -27863,6 +27964,12 @@ Object.freeze({
|
|
|
27863
27964
|
addonId: null,
|
|
27864
27965
|
access: "view"
|
|
27865
27966
|
},
|
|
27967
|
+
"deviceManager.getBindingsBatch": {
|
|
27968
|
+
capName: "device-manager",
|
|
27969
|
+
capScope: "system",
|
|
27970
|
+
addonId: null,
|
|
27971
|
+
access: "view"
|
|
27972
|
+
},
|
|
27866
27973
|
"deviceManager.getChildren": {
|
|
27867
27974
|
capName: "device-manager",
|
|
27868
27975
|
capScope: "system",
|
|
@@ -27923,6 +28030,12 @@ Object.freeze({
|
|
|
27923
28030
|
addonId: null,
|
|
27924
28031
|
access: "view"
|
|
27925
28032
|
},
|
|
28033
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
28034
|
+
capName: "device-manager",
|
|
28035
|
+
capScope: "system",
|
|
28036
|
+
addonId: null,
|
|
28037
|
+
access: "view"
|
|
28038
|
+
},
|
|
27926
28039
|
"deviceManager.getRoleDisplayDefaults": {
|
|
27927
28040
|
capName: "device-manager",
|
|
27928
28041
|
capScope: "system",
|
|
@@ -29693,6 +29806,12 @@ Object.freeze({
|
|
|
29693
29806
|
addonId: null,
|
|
29694
29807
|
access: "view"
|
|
29695
29808
|
},
|
|
29809
|
+
"pipelineAnalytics.getGroup": {
|
|
29810
|
+
capName: "pipeline-analytics",
|
|
29811
|
+
capScope: "device",
|
|
29812
|
+
addonId: null,
|
|
29813
|
+
access: "view"
|
|
29814
|
+
},
|
|
29696
29815
|
"pipelineAnalytics.getKeyEvents": {
|
|
29697
29816
|
capName: "pipeline-analytics",
|
|
29698
29817
|
capScope: "device",
|
|
@@ -29777,6 +29896,12 @@ Object.freeze({
|
|
|
29777
29896
|
addonId: null,
|
|
29778
29897
|
access: "view"
|
|
29779
29898
|
},
|
|
29899
|
+
"pipelineAnalytics.listGroups": {
|
|
29900
|
+
capName: "pipeline-analytics",
|
|
29901
|
+
capScope: "device",
|
|
29902
|
+
addonId: null,
|
|
29903
|
+
access: "view"
|
|
29904
|
+
},
|
|
29780
29905
|
"pipelineAnalytics.listOpsLog": {
|
|
29781
29906
|
capName: "pipeline-analytics",
|
|
29782
29907
|
capScope: "device",
|
|
@@ -32558,6 +32683,11 @@ Object.freeze({
|
|
|
32558
32683
|
form: "single",
|
|
32559
32684
|
optional: false
|
|
32560
32685
|
}],
|
|
32686
|
+
"deviceManager.getBindingsBatch": [{
|
|
32687
|
+
name: "deviceIds",
|
|
32688
|
+
form: "array",
|
|
32689
|
+
optional: false
|
|
32690
|
+
}],
|
|
32561
32691
|
"deviceManager.getChildren": [{
|
|
32562
32692
|
name: "parentDeviceId",
|
|
32563
32693
|
form: "single",
|
|
@@ -32603,6 +32733,11 @@ Object.freeze({
|
|
|
32603
32733
|
form: "single",
|
|
32604
32734
|
optional: false
|
|
32605
32735
|
}],
|
|
32736
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
32737
|
+
name: "deviceIds",
|
|
32738
|
+
form: "array",
|
|
32739
|
+
optional: false
|
|
32740
|
+
}],
|
|
32606
32741
|
"deviceManager.getSettingsSchema": [{
|
|
32607
32742
|
name: "deviceId",
|
|
32608
32743
|
form: "single",
|
|
@@ -32623,6 +32758,11 @@ Object.freeze({
|
|
|
32623
32758
|
form: "single",
|
|
32624
32759
|
optional: false
|
|
32625
32760
|
}],
|
|
32761
|
+
"deviceManager.listAll": [{
|
|
32762
|
+
name: "deviceIds",
|
|
32763
|
+
form: "array",
|
|
32764
|
+
optional: true
|
|
32765
|
+
}],
|
|
32626
32766
|
"deviceManager.loadConfig": [{
|
|
32627
32767
|
name: "deviceId",
|
|
32628
32768
|
form: "single",
|
|
@@ -33196,6 +33336,11 @@ Object.freeze({
|
|
|
33196
33336
|
form: "single",
|
|
33197
33337
|
optional: false
|
|
33198
33338
|
}],
|
|
33339
|
+
"pipelineAnalytics.getGroup": [{
|
|
33340
|
+
name: "deviceId",
|
|
33341
|
+
form: "single",
|
|
33342
|
+
optional: false
|
|
33343
|
+
}],
|
|
33199
33344
|
"pipelineAnalytics.getKeyEvents": [{
|
|
33200
33345
|
name: "deviceId",
|
|
33201
33346
|
form: "single",
|
|
@@ -33251,6 +33396,11 @@ Object.freeze({
|
|
|
33251
33396
|
form: "array",
|
|
33252
33397
|
optional: false
|
|
33253
33398
|
}],
|
|
33399
|
+
"pipelineAnalytics.listGroups": [{
|
|
33400
|
+
name: "deviceIds",
|
|
33401
|
+
form: "array",
|
|
33402
|
+
optional: false
|
|
33403
|
+
}],
|
|
33254
33404
|
"pipelineAnalytics.listOpsLog": [{
|
|
33255
33405
|
name: "deviceId",
|
|
33256
33406
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-ai",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.19",
|
|
4
4
|
"description": "AI addon for CamStack — the `llm` collection provider (cloud, LAN, and camstack-managed local llama.cpp profiles) plus the per-node `llm-runtime` managed executor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|