@camstack/addon-ai 0.4.104 → 0.4.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +131 -50
  2. package/dist/addon.mjs +131 -50
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -12,7 +12,7 @@ let _camstack_system_addon_utils = require("@camstack/system/addon-utils");
12
12
  let node_fs_promises = require("node:fs/promises");
13
13
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
14
14
  let node_child_process = require("node:child_process");
15
- //#region ../types/dist/event-category-DAXzJeTX.mjs
15
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
16
16
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
17
17
  EventCategory["SystemBoot"] = "system.boot";
18
18
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -573,7 +573,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
573
573
  * a package zone — a newly-appeared stationary object of a package class
574
574
  * that cleared the class / zone / dwell / size gates. Payload:
575
575
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
576
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
576
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
577
577
  * Telemetry (D8): the durable record is the `package-events` store row;
578
578
  * this bus topic drives notifier rules + live UI. See
579
579
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -5506,7 +5506,7 @@ function number(params) {
5506
5506
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
5507
5507
  }
5508
5508
  //#endregion
5509
- //#region ../types/dist/sleep-BnujYGPe.mjs
5509
+ //#region ../types/dist/sleep-CnLyvg3w.mjs
5510
5510
  /**
5511
5511
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5512
5512
  * window to float samples (D455).
@@ -7516,13 +7516,30 @@ new Set([
7516
7516
  "scene",
7517
7517
  "motion",
7518
7518
  "object",
7519
- "audio"
7519
+ "audio",
7520
+ "mosaic"
7520
7521
  ]);
7521
- new Set([
7522
+ /**
7523
+ * The owner types that are event tables, in the order the event-media resolver
7524
+ * should consider them. Exported so a consumer asking "is this key an event?"
7525
+ * does not re-spell the list and drift from it.
7526
+ */
7527
+ var EVENT_OWNER_TYPES = [
7522
7528
  "motion",
7523
7529
  "object",
7524
7530
  "audio"
7525
- ]);
7531
+ ];
7532
+ /**
7533
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
7534
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
7535
+ * `(table, id)`).
7536
+ *
7537
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
7538
+ * table would otherwise be accepted by the codec and refused at the door, with
7539
+ * nothing failing until a caller asked.
7540
+ */
7541
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
7542
+ new Set(EVENT_OWNER_TYPES);
7526
7543
  var EncodeProfileSchema = object({
7527
7544
  video: object({
7528
7545
  codec: _enum([
@@ -12619,6 +12636,16 @@ method(object({
12619
12636
  filter: QueryFilterSchema.optional(),
12620
12637
  columns: array(string()).readonly().optional()
12621
12638
  }), array(SettingsRecordSchema).readonly()), method(object({
12639
+ namespace: string().optional(),
12640
+ collection: string(),
12641
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
12642
+ * index on the collection. Never empty. */
12643
+ conflict: array(string()).readonly(),
12644
+ record: BulkRecordSchema
12645
+ }), object({
12646
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
12647
+ * row's own id on an update. */
12648
+ id: union([string(), number$1()]) }), { kind: "mutation" }), method(object({
12622
12649
  namespace: string().optional(),
12623
12650
  collection: string(),
12624
12651
  record: object({
@@ -12753,6 +12780,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12753
12780
  id: union([string(), number$1()]) }), {
12754
12781
  kind: "mutation",
12755
12782
  auth: "admin"
12783
+ }), method(object({
12784
+ namespace: string().optional(),
12785
+ collection: string(),
12786
+ conflict: array(string()).readonly(),
12787
+ record: BulkRecordSchema
12788
+ }), object({ id: union([string(), number$1()]) }), {
12789
+ kind: "mutation",
12790
+ auth: "admin"
12756
12791
  }), method(object({
12757
12792
  namespace: string().optional(),
12758
12793
  collection: string(),
@@ -19063,8 +19098,8 @@ var TrackPositionSchema = object({
19063
19098
  var TrackSnapshotSchema = object({
19064
19099
  timestamp: number$1(),
19065
19100
  position: TrackPositionSchema,
19066
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19067
- mediaKey: string()
19101
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
19102
+ mediaId: number$1().int()
19068
19103
  });
19069
19104
  /**
19070
19105
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -19668,14 +19703,14 @@ var ObjectEventSchema = object({
19668
19703
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
19669
19704
  frameWidth: number$1().optional(),
19670
19705
  frameHeight: number$1().optional(),
19671
- /** MediaStore key for the crop attached to this event (if any). */
19672
- mediaKey: string().optional(),
19673
- /** Design B: MediaStore key of the track's native-resolution key frame (the
19706
+ /** Media row id of the crop attached to this event (if any) — D482. */
19707
+ mediaId: number$1().int().optional(),
19708
+ /** Design B: media row id of the track's native-resolution key frame (the
19674
19709
  * best-detection full frame). Resolve via the event-media data-plane
19675
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
19710
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
19676
19711
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
19677
- * sources — consumers fall back to `mediaKey` (the tight crop). */
19678
- keyFrameMediaKey: string().optional(),
19712
+ * sources — consumers fall back to `mediaId` (the tight crop). */
19713
+ keyFrameMediaId: number$1().int().optional(),
19679
19714
  /** Populated by B5 (recording playback URL for this event). */
19680
19715
  mediaUrl: string().optional(),
19681
19716
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -19725,7 +19760,7 @@ var MediaFileKindEnum = _enum([
19725
19760
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
19726
19761
  *
19727
19762
  * `url` points at the `event-media` data plane
19728
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
19763
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
19729
19764
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
19730
19765
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
19731
19766
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -19733,10 +19768,13 @@ var MediaFileKindEnum = _enum([
19733
19768
  * `data-plane-access.ts` for the rule and the one gap it does not close
19734
19769
  * (per-device scoping).
19735
19770
  *
19736
- * The URL is built from the row's **stored** key, which is not always its
19737
- * published `kind`: a track's face/plate crop is stored as `crop` under
19771
+ * The URL is built from the row's own id, which since D482 says nothing about
19772
+ * the row's owner or kind — and that is the point. The published `kind` is not
19773
+ * the stored one (a track's face/plate crop is stored as `crop` under
19738
19774
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
19739
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
19775
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
19776
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
19777
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
19740
19778
  *
19741
19779
  * ## `base64` is TRANSITIONAL and is going away
19742
19780
  *
@@ -19749,7 +19787,19 @@ var MediaFileKindEnum = _enum([
19749
19787
  * `analytics-query-facade.ts`; nothing else reads it.
19750
19788
  */
19751
19789
  var MediaFileSchema = object({
19752
- key: string(),
19790
+ /**
19791
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
19792
+ *
19793
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
19794
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
19795
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
19796
+ * different rows that spell the same number, and a track whose
19797
+ * `bestEventId` was an object event was served a motion event's snapshot —
19798
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
19799
+ * surrogate id cannot name the wrong row's owner, because it names no owner
19800
+ * at all.
19801
+ */
19802
+ mediaId: number$1().int(),
19753
19803
  kind: MediaFileKindEnum,
19754
19804
  sizeBytes: number$1(),
19755
19805
  timestamp: number$1()
@@ -19857,7 +19907,7 @@ var RetrainTrackSchema = object({
19857
19907
  });
19858
19908
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
19859
19909
  var RetrainFrameCandidateSchema = object({
19860
- mediaKey: string(),
19910
+ mediaId: number$1().int(),
19861
19911
  kind: MediaFileKindEnum,
19862
19912
  timestamp: number$1(),
19863
19913
  sizeBytes: number$1().int(),
@@ -19871,7 +19921,7 @@ var RetrainFrameSchema = object({
19871
19921
  deviceId: number$1(),
19872
19922
  trackId: string(),
19873
19923
  /** Provenance only. It may already point at nothing — that is expected. */
19874
- sourceMediaKey: string(),
19924
+ sourceMediaId: number$1().int(),
19875
19925
  sourceKind: MediaFileKindEnum,
19876
19926
  sizeBytes: number$1().int(),
19877
19927
  width: number$1().int(),
@@ -19887,7 +19937,7 @@ var RetrainCopyRefusalSchema = _enum([
19887
19937
  var RetrainFrameSelectionSchema = object({
19888
19938
  copied: array(RetrainFrameSchema).readonly(),
19889
19939
  refused: array(object({
19890
- sourceMediaKey: string(),
19940
+ sourceMediaId: number$1().int(),
19891
19941
  reason: RetrainCopyRefusalSchema
19892
19942
  })).readonly()
19893
19943
  });
@@ -19895,7 +19945,7 @@ var RetrainFrameListSchema = object({
19895
19945
  candidates: array(RetrainFrameCandidateSchema).readonly(),
19896
19946
  copies: array(RetrainFrameSchema).readonly(),
19897
19947
  /** What the page pre-selects — the native key frame when one survives. */
19898
- autoPickMediaKey: string().optional()
19948
+ autoPickMediaId: number$1().int().optional()
19899
19949
  });
19900
19950
  /** What the operator asked the assist to look for. */
19901
19951
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -19990,9 +20040,11 @@ var RecentTracksQueryInput = object({
19990
20040
  });
19991
20041
  /**
19992
20042
  * A Summary (D359): the per-camera session envelope that references tracks.
19993
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
19994
- * served by the event-media plane by key), null until the first frame with a
19995
- * member visible has been materialised.
20043
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20044
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20045
+ * first frame with a member visible has been materialised (D482 — it was the
20046
+ * row's composite key, which embedded the owner and could name another table's
20047
+ * row once event ids became per-table rowids).
19996
20048
  */
19997
20049
  var SummarySchema = object({
19998
20050
  id: string(),
@@ -20001,7 +20053,7 @@ var SummarySchema = object({
20001
20053
  lastActiveAt: number$1(),
20002
20054
  sealedAt: number$1().nullable(),
20003
20055
  memberCount: number$1().int().nonnegative(),
20004
- groupShotKey: string().nullable()
20056
+ groupShotMediaId: number$1().int().nullable()
20005
20057
  });
20006
20058
  var SummariesQueryInput = object({
20007
20059
  deviceIds: array(number$1()).min(1),
@@ -20555,7 +20607,7 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
20555
20607
  }), method(object({
20556
20608
  deviceId: number$1(),
20557
20609
  trackId: string(),
20558
- mediaKeys: array(string()).min(1)
20610
+ mediaIds: array(number$1().int()).min(1)
20559
20611
  }), RetrainFrameSelectionSchema, {
20560
20612
  kind: "mutation",
20561
20613
  auth: "admin"
@@ -20623,7 +20675,10 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
20623
20675
  kind: "query",
20624
20676
  auth: "admin"
20625
20677
  }), method(object({
20626
- eventId: string(),
20678
+ /** Which of the three event tables owns the row. */
20679
+ ownerType: EventOwnerTypeSchema,
20680
+ /** The event's rowid in that table (D474: an event id is a number). */
20681
+ eventId: number$1().int(),
20627
20682
  kind: MediaFileKindEnum.optional(),
20628
20683
  deviceId: number$1()
20629
20684
  }), array(MediaFileSchema).readonly()), method(object({
@@ -20634,7 +20689,8 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
20634
20689
  trackId: string(),
20635
20690
  deviceId: number$1()
20636
20691
  }), array(MediaFileInfoSchema).readonly()), method(object({
20637
- eventId: string(),
20692
+ ownerType: EventOwnerTypeSchema,
20693
+ eventId: number$1().int(),
20638
20694
  deviceId: number$1()
20639
20695
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
20640
20696
  kind: "mutation",
@@ -25097,8 +25153,8 @@ var IdentitySchema = object({
25097
25153
  id: string(),
25098
25154
  name: string(),
25099
25155
  sampleCount: number$1().int().nonnegative(),
25100
- coverMediaKey: string().optional(),
25101
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
25156
+ coverMediaId: number$1().int().optional(),
25157
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
25102
25158
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
25103
25159
  coverBase64: string().optional()
25104
25160
  });
@@ -25124,8 +25180,8 @@ var IdentitySampleAuditRowSchema = object({
25124
25180
  enrolledAt: number$1().int(),
25125
25181
  deviceId: number$1().int().optional(),
25126
25182
  source: _enum(["detected", "photo"]),
25127
- /** The enrolled crop's media key, so the panel can show the evidence. */
25128
- mediaKey: string().optional(),
25183
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
25184
+ mediaId: number$1().int().optional(),
25129
25185
  /**
25130
25186
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
25131
25187
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -25194,15 +25250,15 @@ var FaceInfoSchema = object({
25194
25250
  */
25195
25251
  cropUrl: string().optional(),
25196
25252
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
25197
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
25253
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
25198
25254
  * legacy rows written before design B. */
25199
25255
  faceBbox: BoundingBoxSchema.optional(),
25200
25256
  /** Design B: MediaStore key of the track's native-resolution key frame.
25201
25257
  * Fetch the native JPEG via the event-media data-plane
25202
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
25258
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
25203
25259
  * track produced no key frame (e.g. native/onboard source) — the UI falls
25204
25260
  * back to the inline `base64` face crop. */
25205
- keyFrameMediaKey: string().optional(),
25261
+ keyFrameMediaId: number$1().int().optional(),
25206
25262
  /** Winning identity-match cosine (0..1) for this face's track, when an
25207
25263
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
25208
25264
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -25271,11 +25327,14 @@ var FaceClusterSchema = object({
25271
25327
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
25272
25328
  * dialog already rendering its key FRAME from the `event-media` plane.
25273
25329
  *
25274
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
25275
- * media key directly, so this needed no new plane and no new access decision.
25330
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
25331
+ * resolves a media row by its own id, so this needed no new plane and no new
25332
+ * access decision.
25276
25333
  */
25277
25334
  var MediaFileLiteSchema$1 = object({
25278
- key: string(),
25335
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
25336
+ * (D482). It was the row's composite key, which embedded the owner. */
25337
+ mediaId: number$1().int(),
25279
25338
  kind: string(),
25280
25339
  url: string(),
25281
25340
  sizeBytes: number$1(),
@@ -25292,7 +25351,7 @@ method(object({
25292
25351
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
25293
25352
  * four times and the viewer holds at `staleTime: 30_000`.
25294
25353
  *
25295
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
25354
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
25296
25355
  * the `event-media` plane serves that key `immutable` with an ETag.
25297
25356
  *
25298
25357
  * **This is an INPUT field, so it does not reach the addon until the
@@ -27760,8 +27819,8 @@ var VehicleSchema = object({
27760
27819
  id: string(),
27761
27820
  name: string(),
27762
27821
  sampleCount: number$1().int().nonnegative(),
27763
- coverMediaKey: string().optional(),
27764
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
27822
+ coverMediaId: number$1().int().optional(),
27823
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
27765
27824
  coverBase64: string().optional()
27766
27825
  });
27767
27826
  var VehicleSampleInfoSchema = object({
@@ -27794,7 +27853,7 @@ var PlateInfoSchema = object({
27794
27853
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
27795
27854
  plateBbox: BoundingBoxSchema.optional(),
27796
27855
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
27797
- keyFrameMediaKey: string().optional(),
27856
+ keyFrameMediaId: number$1().int().optional(),
27798
27857
  base64: string().optional(),
27799
27858
  /**
27800
27859
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -27815,11 +27874,14 @@ var PlateInfoSchema = object({
27815
27874
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
27816
27875
  * dialog already rendering its key FRAME from the `event-media` plane.
27817
27876
  *
27818
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
27819
- * media key directly, so this needed no new plane and no new access decision.
27877
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
27878
+ * resolves a media row by its own id, so this needed no new plane and no new
27879
+ * access decision.
27820
27880
  */
27821
27881
  var MediaFileLiteSchema = object({
27822
- key: string(),
27882
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
27883
+ * (D482). It was the row's composite key, which embedded the owner. */
27884
+ mediaId: number$1().int(),
27823
27885
  kind: string(),
27824
27886
  url: string(),
27825
27887
  sizeBytes: number$1(),
@@ -27878,7 +27940,7 @@ method(object({
27878
27940
  }), method(object({
27879
27941
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
27880
27942
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
27881
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
27943
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
27882
27944
  * INPUT field: stripped by the hub router until the train ships, which
27883
27945
  * resolves to `false` and is exactly the intended default. */
27884
27946
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
@@ -29202,7 +29264,14 @@ var SceneReferenceSchema = object({
29202
29264
  modelId: string(),
29203
29265
  condition: SceneConditionSchema,
29204
29266
  capturedAt: number$1(),
29205
- thumbnailMediaId: string().optional(),
29267
+ /**
29268
+ * The reference thumbnail's media ROW id (D482).
29269
+ *
29270
+ * The name already said `mediaId` while the value was the row's composite
29271
+ * key — a leftover that read as done and was not. It is the row's own id
29272
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
29273
+ */
29274
+ thumbnailMediaId: number$1().int().optional(),
29206
29275
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
29207
29276
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
29208
29277
  * normalized rect frame a different piece of world, and the scene would
@@ -30650,7 +30719,7 @@ var StationaryObjectSchema = object({
30650
30719
  /** Enrichment label carried from the source track (identity / plate). */
30651
30720
  label: string().optional(),
30652
30721
  /** Native-resolution key-frame media key for the parked object's best image. */
30653
- keyFrameMediaKey: string().optional()
30722
+ keyFrameMediaId: number$1().int().optional()
30654
30723
  });
30655
30724
  var CameraOccupancySnapshotSchema = object({
30656
30725
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -31806,6 +31875,12 @@ Object.freeze({
31806
31875
  addonId: null,
31807
31876
  access: "create"
31808
31877
  },
31878
+ "dataStoreProvider.upsert": {
31879
+ capName: "data-store-provider",
31880
+ capScope: "system",
31881
+ addonId: null,
31882
+ access: "create"
31883
+ },
31809
31884
  "dayNight.getOptions": {
31810
31885
  capName: "day-night",
31811
31886
  capScope: "device",
@@ -35670,6 +35745,12 @@ Object.freeze({
35670
35745
  addonId: null,
35671
35746
  access: "create"
35672
35747
  },
35748
+ "settingsStore.upsert": {
35749
+ capName: "settings-store",
35750
+ capScope: "system",
35751
+ addonId: null,
35752
+ access: "create"
35753
+ },
35673
35754
  "smtpProvider.getStatus": {
35674
35755
  capName: "smtp-provider",
35675
35756
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -39,7 +39,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
39
39
  }) : target, mod));
40
40
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
41
41
  //#endregion
42
- //#region ../types/dist/event-category-DAXzJeTX.mjs
42
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
43
43
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
44
44
  EventCategory["SystemBoot"] = "system.boot";
45
45
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -600,7 +600,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
600
600
  * a package zone — a newly-appeared stationary object of a package class
601
601
  * that cleared the class / zone / dwell / size gates. Payload:
602
602
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
603
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
603
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
604
604
  * Telemetry (D8): the durable record is the `package-events` store row;
605
605
  * this bus topic drives notifier rules + live UI. See
606
606
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -5533,7 +5533,7 @@ function number(params) {
5533
5533
  return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
5534
5534
  }
5535
5535
  //#endregion
5536
- //#region ../types/dist/sleep-BnujYGPe.mjs
5536
+ //#region ../types/dist/sleep-CnLyvg3w.mjs
5537
5537
  /**
5538
5538
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5539
5539
  * window to float samples (D455).
@@ -7543,13 +7543,30 @@ new Set([
7543
7543
  "scene",
7544
7544
  "motion",
7545
7545
  "object",
7546
- "audio"
7546
+ "audio",
7547
+ "mosaic"
7547
7548
  ]);
7548
- new Set([
7549
+ /**
7550
+ * The owner types that are event tables, in the order the event-media resolver
7551
+ * should consider them. Exported so a consumer asking "is this key an event?"
7552
+ * does not re-spell the list and drift from it.
7553
+ */
7554
+ var EVENT_OWNER_TYPES = [
7549
7555
  "motion",
7550
7556
  "object",
7551
7557
  "audio"
7552
- ]);
7558
+ ];
7559
+ /**
7560
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
7561
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
7562
+ * `(table, id)`).
7563
+ *
7564
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
7565
+ * table would otherwise be accepted by the codec and refused at the door, with
7566
+ * nothing failing until a caller asked.
7567
+ */
7568
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
7569
+ new Set(EVENT_OWNER_TYPES);
7553
7570
  var EncodeProfileSchema = object({
7554
7571
  video: object({
7555
7572
  codec: _enum([
@@ -12646,6 +12663,16 @@ method(object({
12646
12663
  filter: QueryFilterSchema.optional(),
12647
12664
  columns: array(string()).readonly().optional()
12648
12665
  }), array(SettingsRecordSchema).readonly()), method(object({
12666
+ namespace: string().optional(),
12667
+ collection: string(),
12668
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
12669
+ * index on the collection. Never empty. */
12670
+ conflict: array(string()).readonly(),
12671
+ record: BulkRecordSchema
12672
+ }), object({
12673
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
12674
+ * row's own id on an update. */
12675
+ id: union([string(), number$1()]) }), { kind: "mutation" }), method(object({
12649
12676
  namespace: string().optional(),
12650
12677
  collection: string(),
12651
12678
  record: object({
@@ -12780,6 +12807,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12780
12807
  id: union([string(), number$1()]) }), {
12781
12808
  kind: "mutation",
12782
12809
  auth: "admin"
12810
+ }), method(object({
12811
+ namespace: string().optional(),
12812
+ collection: string(),
12813
+ conflict: array(string()).readonly(),
12814
+ record: BulkRecordSchema
12815
+ }), object({ id: union([string(), number$1()]) }), {
12816
+ kind: "mutation",
12817
+ auth: "admin"
12783
12818
  }), method(object({
12784
12819
  namespace: string().optional(),
12785
12820
  collection: string(),
@@ -19090,8 +19125,8 @@ var TrackPositionSchema = object({
19090
19125
  var TrackSnapshotSchema = object({
19091
19126
  timestamp: number$1(),
19092
19127
  position: TrackPositionSchema,
19093
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19094
- mediaKey: string()
19128
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
19129
+ mediaId: number$1().int()
19095
19130
  });
19096
19131
  /**
19097
19132
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -19695,14 +19730,14 @@ var ObjectEventSchema = object({
19695
19730
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
19696
19731
  frameWidth: number$1().optional(),
19697
19732
  frameHeight: number$1().optional(),
19698
- /** MediaStore key for the crop attached to this event (if any). */
19699
- mediaKey: string().optional(),
19700
- /** Design B: MediaStore key of the track's native-resolution key frame (the
19733
+ /** Media row id of the crop attached to this event (if any) — D482. */
19734
+ mediaId: number$1().int().optional(),
19735
+ /** Design B: media row id of the track's native-resolution key frame (the
19701
19736
  * best-detection full frame). Resolve via the event-media data-plane
19702
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
19737
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
19703
19738
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
19704
- * sources — consumers fall back to `mediaKey` (the tight crop). */
19705
- keyFrameMediaKey: string().optional(),
19739
+ * sources — consumers fall back to `mediaId` (the tight crop). */
19740
+ keyFrameMediaId: number$1().int().optional(),
19706
19741
  /** Populated by B5 (recording playback URL for this event). */
19707
19742
  mediaUrl: string().optional(),
19708
19743
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -19752,7 +19787,7 @@ var MediaFileKindEnum = _enum([
19752
19787
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
19753
19788
  *
19754
19789
  * `url` points at the `event-media` data plane
19755
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
19790
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
19756
19791
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
19757
19792
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
19758
19793
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -19760,10 +19795,13 @@ var MediaFileKindEnum = _enum([
19760
19795
  * `data-plane-access.ts` for the rule and the one gap it does not close
19761
19796
  * (per-device scoping).
19762
19797
  *
19763
- * The URL is built from the row's **stored** key, which is not always its
19764
- * published `kind`: a track's face/plate crop is stored as `crop` under
19798
+ * The URL is built from the row's own id, which since D482 says nothing about
19799
+ * the row's owner or kind — and that is the point. The published `kind` is not
19800
+ * the stored one (a track's face/plate crop is stored as `crop` under
19765
19801
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
19766
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
19802
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
19803
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
19804
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
19767
19805
  *
19768
19806
  * ## `base64` is TRANSITIONAL and is going away
19769
19807
  *
@@ -19776,7 +19814,19 @@ var MediaFileKindEnum = _enum([
19776
19814
  * `analytics-query-facade.ts`; nothing else reads it.
19777
19815
  */
19778
19816
  var MediaFileSchema = object({
19779
- key: string(),
19817
+ /**
19818
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
19819
+ *
19820
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
19821
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
19822
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
19823
+ * different rows that spell the same number, and a track whose
19824
+ * `bestEventId` was an object event was served a motion event's snapshot —
19825
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
19826
+ * surrogate id cannot name the wrong row's owner, because it names no owner
19827
+ * at all.
19828
+ */
19829
+ mediaId: number$1().int(),
19780
19830
  kind: MediaFileKindEnum,
19781
19831
  sizeBytes: number$1(),
19782
19832
  timestamp: number$1()
@@ -19884,7 +19934,7 @@ var RetrainTrackSchema = object({
19884
19934
  });
19885
19935
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
19886
19936
  var RetrainFrameCandidateSchema = object({
19887
- mediaKey: string(),
19937
+ mediaId: number$1().int(),
19888
19938
  kind: MediaFileKindEnum,
19889
19939
  timestamp: number$1(),
19890
19940
  sizeBytes: number$1().int(),
@@ -19898,7 +19948,7 @@ var RetrainFrameSchema = object({
19898
19948
  deviceId: number$1(),
19899
19949
  trackId: string(),
19900
19950
  /** Provenance only. It may already point at nothing — that is expected. */
19901
- sourceMediaKey: string(),
19951
+ sourceMediaId: number$1().int(),
19902
19952
  sourceKind: MediaFileKindEnum,
19903
19953
  sizeBytes: number$1().int(),
19904
19954
  width: number$1().int(),
@@ -19914,7 +19964,7 @@ var RetrainCopyRefusalSchema = _enum([
19914
19964
  var RetrainFrameSelectionSchema = object({
19915
19965
  copied: array(RetrainFrameSchema).readonly(),
19916
19966
  refused: array(object({
19917
- sourceMediaKey: string(),
19967
+ sourceMediaId: number$1().int(),
19918
19968
  reason: RetrainCopyRefusalSchema
19919
19969
  })).readonly()
19920
19970
  });
@@ -19922,7 +19972,7 @@ var RetrainFrameListSchema = object({
19922
19972
  candidates: array(RetrainFrameCandidateSchema).readonly(),
19923
19973
  copies: array(RetrainFrameSchema).readonly(),
19924
19974
  /** What the page pre-selects — the native key frame when one survives. */
19925
- autoPickMediaKey: string().optional()
19975
+ autoPickMediaId: number$1().int().optional()
19926
19976
  });
19927
19977
  /** What the operator asked the assist to look for. */
19928
19978
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -20017,9 +20067,11 @@ var RecentTracksQueryInput = object({
20017
20067
  });
20018
20068
  /**
20019
20069
  * A Summary (D359): the per-camera session envelope that references tracks.
20020
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
20021
- * served by the event-media plane by key), null until the first frame with a
20022
- * member visible has been materialised.
20070
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20071
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20072
+ * first frame with a member visible has been materialised (D482 — it was the
20073
+ * row's composite key, which embedded the owner and could name another table's
20074
+ * row once event ids became per-table rowids).
20023
20075
  */
20024
20076
  var SummarySchema = object({
20025
20077
  id: string(),
@@ -20028,7 +20080,7 @@ var SummarySchema = object({
20028
20080
  lastActiveAt: number$1(),
20029
20081
  sealedAt: number$1().nullable(),
20030
20082
  memberCount: number$1().int().nonnegative(),
20031
- groupShotKey: string().nullable()
20083
+ groupShotMediaId: number$1().int().nullable()
20032
20084
  });
20033
20085
  var SummariesQueryInput = object({
20034
20086
  deviceIds: array(number$1()).min(1),
@@ -20582,7 +20634,7 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
20582
20634
  }), method(object({
20583
20635
  deviceId: number$1(),
20584
20636
  trackId: string(),
20585
- mediaKeys: array(string()).min(1)
20637
+ mediaIds: array(number$1().int()).min(1)
20586
20638
  }), RetrainFrameSelectionSchema, {
20587
20639
  kind: "mutation",
20588
20640
  auth: "admin"
@@ -20650,7 +20702,10 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
20650
20702
  kind: "query",
20651
20703
  auth: "admin"
20652
20704
  }), method(object({
20653
- eventId: string(),
20705
+ /** Which of the three event tables owns the row. */
20706
+ ownerType: EventOwnerTypeSchema,
20707
+ /** The event's rowid in that table (D474: an event id is a number). */
20708
+ eventId: number$1().int(),
20654
20709
  kind: MediaFileKindEnum.optional(),
20655
20710
  deviceId: number$1()
20656
20711
  }), array(MediaFileSchema).readonly()), method(object({
@@ -20661,7 +20716,8 @@ DeviceType.Camera, method(object({ deviceId: number$1() }), array(TrackSchema).r
20661
20716
  trackId: string(),
20662
20717
  deviceId: number$1()
20663
20718
  }), array(MediaFileInfoSchema).readonly()), method(object({
20664
- eventId: string(),
20719
+ ownerType: EventOwnerTypeSchema,
20720
+ eventId: number$1().int(),
20665
20721
  deviceId: number$1()
20666
20722
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
20667
20723
  kind: "mutation",
@@ -25124,8 +25180,8 @@ var IdentitySchema = object({
25124
25180
  id: string(),
25125
25181
  name: string(),
25126
25182
  sampleCount: number$1().int().nonnegative(),
25127
- coverMediaKey: string().optional(),
25128
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
25183
+ coverMediaId: number$1().int().optional(),
25184
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
25129
25185
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
25130
25186
  coverBase64: string().optional()
25131
25187
  });
@@ -25151,8 +25207,8 @@ var IdentitySampleAuditRowSchema = object({
25151
25207
  enrolledAt: number$1().int(),
25152
25208
  deviceId: number$1().int().optional(),
25153
25209
  source: _enum(["detected", "photo"]),
25154
- /** The enrolled crop's media key, so the panel can show the evidence. */
25155
- mediaKey: string().optional(),
25210
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
25211
+ mediaId: number$1().int().optional(),
25156
25212
  /**
25157
25213
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
25158
25214
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -25221,15 +25277,15 @@ var FaceInfoSchema = object({
25221
25277
  */
25222
25278
  cropUrl: string().optional(),
25223
25279
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
25224
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
25280
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
25225
25281
  * legacy rows written before design B. */
25226
25282
  faceBbox: BoundingBoxSchema.optional(),
25227
25283
  /** Design B: MediaStore key of the track's native-resolution key frame.
25228
25284
  * Fetch the native JPEG via the event-media data-plane
25229
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
25285
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
25230
25286
  * track produced no key frame (e.g. native/onboard source) — the UI falls
25231
25287
  * back to the inline `base64` face crop. */
25232
- keyFrameMediaKey: string().optional(),
25288
+ keyFrameMediaId: number$1().int().optional(),
25233
25289
  /** Winning identity-match cosine (0..1) for this face's track, when an
25234
25290
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
25235
25291
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -25298,11 +25354,14 @@ var FaceClusterSchema = object({
25298
25354
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
25299
25355
  * dialog already rendering its key FRAME from the `event-media` plane.
25300
25356
  *
25301
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
25302
- * media key directly, so this needed no new plane and no new access decision.
25357
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
25358
+ * resolves a media row by its own id, so this needed no new plane and no new
25359
+ * access decision.
25303
25360
  */
25304
25361
  var MediaFileLiteSchema$1 = object({
25305
- key: string(),
25362
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
25363
+ * (D482). It was the row's composite key, which embedded the owner. */
25364
+ mediaId: number$1().int(),
25306
25365
  kind: string(),
25307
25366
  url: string(),
25308
25367
  sizeBytes: number$1(),
@@ -25319,7 +25378,7 @@ method(object({
25319
25378
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
25320
25379
  * four times and the viewer holds at `staleTime: 30_000`.
25321
25380
  *
25322
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
25381
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
25323
25382
  * the `event-media` plane serves that key `immutable` with an ETag.
25324
25383
  *
25325
25384
  * **This is an INPUT field, so it does not reach the addon until the
@@ -27787,8 +27846,8 @@ var VehicleSchema = object({
27787
27846
  id: string(),
27788
27847
  name: string(),
27789
27848
  sampleCount: number$1().int().nonnegative(),
27790
- coverMediaKey: string().optional(),
27791
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
27849
+ coverMediaId: number$1().int().optional(),
27850
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
27792
27851
  coverBase64: string().optional()
27793
27852
  });
27794
27853
  var VehicleSampleInfoSchema = object({
@@ -27821,7 +27880,7 @@ var PlateInfoSchema = object({
27821
27880
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
27822
27881
  plateBbox: BoundingBoxSchema.optional(),
27823
27882
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
27824
- keyFrameMediaKey: string().optional(),
27883
+ keyFrameMediaId: number$1().int().optional(),
27825
27884
  base64: string().optional(),
27826
27885
  /**
27827
27886
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -27842,11 +27901,14 @@ var PlateInfoSchema = object({
27842
27901
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
27843
27902
  * dialog already rendering its key FRAME from the `event-media` plane.
27844
27903
  *
27845
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
27846
- * media key directly, so this needed no new plane and no new access decision.
27904
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
27905
+ * resolves a media row by its own id, so this needed no new plane and no new
27906
+ * access decision.
27847
27907
  */
27848
27908
  var MediaFileLiteSchema = object({
27849
- key: string(),
27909
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
27910
+ * (D482). It was the row's composite key, which embedded the owner. */
27911
+ mediaId: number$1().int(),
27850
27912
  kind: string(),
27851
27913
  url: string(),
27852
27914
  sizeBytes: number$1(),
@@ -27905,7 +27967,7 @@ method(object({
27905
27967
  }), method(object({
27906
27968
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
27907
27969
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
27908
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
27970
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
27909
27971
  * INPUT field: stripped by the hub router until the train ships, which
27910
27972
  * resolves to `false` and is exactly the intended default. */
27911
27973
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
@@ -29229,7 +29291,14 @@ var SceneReferenceSchema = object({
29229
29291
  modelId: string(),
29230
29292
  condition: SceneConditionSchema,
29231
29293
  capturedAt: number$1(),
29232
- thumbnailMediaId: string().optional(),
29294
+ /**
29295
+ * The reference thumbnail's media ROW id (D482).
29296
+ *
29297
+ * The name already said `mediaId` while the value was the row's composite
29298
+ * key — a leftover that read as done and was not. It is the row's own id
29299
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
29300
+ */
29301
+ thumbnailMediaId: number$1().int().optional(),
29233
29302
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
29234
29303
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
29235
29304
  * normalized rect frame a different piece of world, and the scene would
@@ -30677,7 +30746,7 @@ var StationaryObjectSchema = object({
30677
30746
  /** Enrichment label carried from the source track (identity / plate). */
30678
30747
  label: string().optional(),
30679
30748
  /** Native-resolution key-frame media key for the parked object's best image. */
30680
- keyFrameMediaKey: string().optional()
30749
+ keyFrameMediaId: number$1().int().optional()
30681
30750
  });
30682
30751
  var CameraOccupancySnapshotSchema = object({
30683
30752
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -31833,6 +31902,12 @@ Object.freeze({
31833
31902
  addonId: null,
31834
31903
  access: "create"
31835
31904
  },
31905
+ "dataStoreProvider.upsert": {
31906
+ capName: "data-store-provider",
31907
+ capScope: "system",
31908
+ addonId: null,
31909
+ access: "create"
31910
+ },
31836
31911
  "dayNight.getOptions": {
31837
31912
  capName: "day-night",
31838
31913
  capScope: "device",
@@ -35697,6 +35772,12 @@ Object.freeze({
35697
35772
  addonId: null,
35698
35773
  access: "create"
35699
35774
  },
35775
+ "settingsStore.upsert": {
35776
+ capName: "settings-store",
35777
+ capScope: "system",
35778
+ addonId: null,
35779
+ access: "create"
35780
+ },
35700
35781
  "smtpProvider.getStatus": {
35701
35782
  capName: "smtp-provider",
35702
35783
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-ai",
3
- "version": "0.4.104",
3
+ "version": "0.4.105",
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",