@camstack/addon-post-analysis 1.2.660 → 1.2.662

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 (16) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{clip-model-registry-DAKPBZfa.js → clip-model-registry-C3N1NpST.js} +274 -36
  3. package/dist/{clip-model-registry-D9BbIQ-h.mjs → clip-model-registry-ELaSS9jq.mjs} +269 -37
  4. package/dist/embedding-encoder/index.js +1 -1
  5. package/dist/embedding-encoder/index.mjs +1 -1
  6. package/dist/pipeline-analytics/_stub.js +2 -2
  7. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-CvrKdp_8.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-BvOlyiL9.mjs} +2 -2
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D4zkNcgf.mjs +26 -0
  9. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-vaatUWY6.mjs +26 -0
  10. package/dist/pipeline-analytics/{hostInit--CbMNXQy.mjs → hostInit-BjZchMMh.mjs} +2 -2
  11. package/dist/pipeline-analytics/index.js +506 -172
  12. package/dist/pipeline-analytics/index.mjs +506 -172
  13. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  14. package/package.json +2 -2
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BDKliSzv.mjs +0 -26
  16. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BwWOFFOc.mjs +0 -26
package/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.662] - 2026-11-01
11
+
12
+ ### Changed
13
+
14
+ - An appliance that finishes its cycle now notifies by default as "<Device> ha terminato dopo N minuti", and the text can carry the energy used
15
+ - The appliance finish notification reads the recorded run, so duration and energy survive a restart.
16
+
17
+ ## [1.2.661] - 2026-11-01
18
+
19
+ ### Changed
20
+
21
+ - A capture request now expires exactly at its deadline instead of one millisecond after, so an abandoned confirmation crop no longer holds the head of the lane and sheds key frames.
22
+ - Notification templates: {{camera}} is now {{device}}. Your saved rules, timelapse captions and text overrides are rewritten once at the first start; {{camera}} keeps rendering in a template an older app still writes
23
+
10
24
  ## [1.2.660] - 2026-11-01
11
25
 
12
26
  ### Changed
@@ -30,7 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  }) : target, mod));
31
31
  //#endregion
32
32
  let node_crypto = require("node:crypto");
33
- //#region ../types/dist/event-category-CaURIwQA.mjs
33
+ //#region ../types/dist/event-category-BmPm98n0.mjs
34
34
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
35
35
  EventCategory["SystemBoot"] = "system.boot";
36
36
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -514,6 +514,10 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
514
514
  EventCategory["RunningStarted"] = "running.started";
515
515
  /** Mirrors `runningStateCapability.events.onFinished`. */
516
516
  EventCategory["RunningFinished"] = "running.finished";
517
+ /** Mirrors `deviceRunsCapability.events.onRunOpened` - a durable run record opened. */
518
+ EventCategory["DeviceRunOpened"] = "device-run.opened";
519
+ /** Mirrors `deviceRunsCapability.events.onRunClosed` - a durable run record closed. */
520
+ EventCategory["DeviceRunClosed"] = "device-run.closed";
517
521
  /**
518
522
  * Cap event fired by every device that registers the `event-emitter`
519
523
  * capability. Mirrors `eventEmitterCapability.events.onEvent`. Carries
@@ -6052,7 +6056,7 @@ var ZodIssueCode = {
6052
6056
  var ZodFirstPartyTypeKind;
6053
6057
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6054
6058
  //#endregion
6055
- //#region ../types/dist/sleep-CSYuxssh.mjs
6059
+ //#region ../types/dist/sleep-BKzhQTSm.mjs
6056
6060
  /**
6057
6061
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6058
6062
  * window to float samples (D455).
@@ -6568,6 +6572,53 @@ function emitReadiness(bus, params) {
6568
6572
  ts
6569
6573
  }));
6570
6574
  }
6575
+ /** Why a catalogue entry is not a runnable body of its declared kind. */
6576
+ var AddonMigrationDefinitionError = class extends Error {
6577
+ id;
6578
+ constructor(id, message) {
6579
+ super(`${id}: ${message}`);
6580
+ this.id = id;
6581
+ this.name = "AddonMigrationDefinitionError";
6582
+ }
6583
+ };
6584
+ /**
6585
+ * Bind a catalogue to the addon's ports. Throws {@link AddonMigrationDefinitionError} when
6586
+ * an entry's `bodyKind` does not match the body it carries, or is `sql` (a hub-only
6587
+ * body). A throwing body never escapes `execute`: it is reported as a failed result.
6588
+ */
6589
+ function defineAddonMigrations(catalogue, ports) {
6590
+ return catalogue.map((entry) => {
6591
+ const { meta } = entry;
6592
+ if ("plan" in entry) {
6593
+ if (meta.bodyKind !== "plan") throw new AddonMigrationDefinitionError(meta.id, `carries a plan body but declares "${meta.bodyKind}"`);
6594
+ return {
6595
+ meta,
6596
+ execute: () => guarded(async () => ({
6597
+ kind: "plan",
6598
+ plan: await entry.plan(ports)
6599
+ }))
6600
+ };
6601
+ }
6602
+ if (meta.bodyKind !== "procedure") throw new AddonMigrationDefinitionError(meta.id, `carries a procedure body but declares "${meta.bodyKind}"`);
6603
+ return {
6604
+ meta,
6605
+ execute: () => guarded(async () => ({
6606
+ kind: "procedure",
6607
+ result: await entry.procedure(ports)
6608
+ }))
6609
+ };
6610
+ });
6611
+ }
6612
+ async function guarded(work) {
6613
+ try {
6614
+ return await work();
6615
+ } catch (err) {
6616
+ return {
6617
+ kind: "failed",
6618
+ error: errMsg(err)
6619
+ };
6620
+ }
6621
+ }
6571
6622
  var NOT_RUN = {
6572
6623
  declared: false,
6573
6624
  snapshot: null,
@@ -9771,6 +9822,7 @@ var CAP_NAMES = Object.freeze([
9771
9822
  "device-ops",
9772
9823
  "device-provider",
9773
9824
  "device-removal-hook",
9825
+ "device-runs",
9774
9826
  "device-state",
9775
9827
  "device-status",
9776
9828
  "dishwasher",
@@ -11717,7 +11769,7 @@ Object.freeze({
11717
11769
  * can answer "may a rule actuate this?" without importing the schema barrel
11718
11770
  * (~144MB RSS per runner, D28).
11719
11771
  *
11720
- * Coverage: 98 device-scoped capabilities.
11772
+ * Coverage: 99 device-scoped capabilities.
11721
11773
  */
11722
11774
  var DEVICE_SCOPED_CAPS = new Set([
11723
11775
  "accessories",
@@ -11749,6 +11801,7 @@ var DEVICE_SCOPED_CAPS = new Set([
11749
11801
  "device-discovery",
11750
11802
  "device-extension",
11751
11803
  "device-ops",
11804
+ "device-runs",
11752
11805
  "device-status",
11753
11806
  "dishwasher",
11754
11807
  "doorbell",
@@ -14489,7 +14542,13 @@ var MigrationLedgerEntrySchema = object({
14489
14542
  /** Why it is `blocked` or `held` (`dependency-failed`, `snapshot-refused`, …). */
14490
14543
  reason: string().nullable(),
14491
14544
  nodeId: string().nullable(),
14492
- bootId: string().nullable()
14545
+ bootId: string().nullable(),
14546
+ /**
14547
+ * The catalogued meta of this id (description, body kind, store, `dependsOn`…),
14548
+ * joined by the engine from the catalogues it knows this boot. Absent when no
14549
+ * catalogue lists the id (a newer database).
14550
+ */
14551
+ meta: MigrationMetaSchema.optional()
14493
14552
  });
14494
14553
  /** A catalogued migration that is not applied, with where it stands. */
14495
14554
  var MigrationPendingEntrySchema = object({
@@ -20929,6 +20988,14 @@ var APPLIANCE_CAP_VOCABULARY = {
20929
20988
  }
20930
20989
  } }
20931
20990
  },
20991
+ "device-runs": {
20992
+ scope: "device",
20993
+ noun: t("Runs", "Esecuzioni"),
20994
+ events: {
20995
+ onRunOpened: { notOperatorFacing: "the durable record of a run that the running-state start flip already announces" },
20996
+ onRunClosed: { notOperatorFacing: "the durable record of a run that the running-state finish flip already announces" }
20997
+ }
20998
+ },
20932
20999
  update: {
20933
21000
  scope: "device",
20934
21001
  noun: t("Firmware update", "Aggiornamento firmware"),
@@ -49299,6 +49366,101 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
49299
49366
  kind: "mutation",
49300
49367
  auth: "admin"
49301
49368
  });
49369
+ /**
49370
+ * device-runs - the durable record of ONE run of a device: a washing cycle, a
49371
+ * dishwasher cycle, later a mow or a clean (D992).
49372
+ *
49373
+ * A run is a DOCUMENT (opened at one instant, closed at another, carrying what
49374
+ * was measured over it), never a sample - device-history keeps the numbers over
49375
+ * time and its `device-runs` provider keeps these documents beside them, because
49376
+ * the energy of a run is a question about device-history's own series. The
49377
+ * record is written from the `running-state` flip on `DeviceStateChanged`; it
49378
+ * survives a restart (the open row is on disk) and a missed flip (boot compares
49379
+ * the open rows against the live snapshots).
49380
+ *
49381
+ * Every measurement is `number | null` and `null` means "could not be
49382
+ * measured", never `0` (D393). A run closed by the boot reconcile because the
49383
+ * device stopped while nobody was watching has `outcome: 'unknown'`.
49384
+ */
49385
+ var DeviceRunKindSchema = _enum([
49386
+ "appliance",
49387
+ "mower",
49388
+ "vacuum"
49389
+ ]);
49390
+ var DeviceRunStateSchema = _enum(["open", "closed"]);
49391
+ var DeviceRunOutcomeSchema = _enum([
49392
+ "completed",
49393
+ "aborted",
49394
+ "error",
49395
+ "unknown"
49396
+ ]);
49397
+ /** What opened or closed the run. `reconcile` is the boot comparison against live state. */
49398
+ var DeviceRunSourceSchema = _enum([
49399
+ "running-state",
49400
+ "activity",
49401
+ "reconcile"
49402
+ ]);
49403
+ /** How the energy of a run was obtained; `null` when it could not be. */
49404
+ var DeviceRunEnergyMethodSchema = _enum(["counter-delta", "history-integral"]);
49405
+ var DeviceRunPhaseSchema = object({
49406
+ phase: string(),
49407
+ at: number()
49408
+ });
49409
+ /** The kind-specific block; a later phase adds a branch, nothing else changes. */
49410
+ var DeviceRunDetailSchema = discriminatedUnion("kind", [object({
49411
+ kind: literal("appliance"),
49412
+ /** kWh used over the run. */
49413
+ energyKwh: number().nullable().meta(readingMeta("energy")),
49414
+ energyMethod: DeviceRunEnergyMethodSchema.nullable(),
49415
+ /** Highest power seen while the run was open. */
49416
+ peakW: number().nullable().meta(readingMeta("power")),
49417
+ /** Time-weighted mean power while the run was open. */
49418
+ avgW: number().nullable().meta(readingMeta("power")),
49419
+ /** The program the appliance said it ran when the run opened. */
49420
+ program: string().nullable(),
49421
+ remainingAtStartSec: number().nullable().meta(readingMeta("duration")),
49422
+ /** The last phase the device reported before the run closed. */
49423
+ finalPhase: string().nullable(),
49424
+ /**
49425
+ * The meter's energy counter when the run opened; `null` when the meter had
49426
+ * not said (or the run was opened late, by the boot reconcile). It lives in
49427
+ * the row so a run that outlives a restart still ends with `end - start`.
49428
+ */
49429
+ energyStartKwh: number().nullable().meta(readingMeta("energy")),
49430
+ /** Milliseconds of power readings behind `avgW` - the weight a restart resumes the mean with. */
49431
+ powerObservedMs: number()
49432
+ })]);
49433
+ var DeviceRunSchema = object({
49434
+ /** `${deviceId}:${startedAt}`. */
49435
+ runId: string(),
49436
+ deviceId: number().int(),
49437
+ kind: DeviceRunKindSchema,
49438
+ state: DeviceRunStateSchema,
49439
+ startedAt: number(),
49440
+ endedAt: number().nullable(),
49441
+ durationMs: number().nullable(),
49442
+ outcome: DeviceRunOutcomeSchema.nullable(),
49443
+ startSource: DeviceRunSourceSchema,
49444
+ endSource: DeviceRunSourceSchema.nullable(),
49445
+ /** Where the device's running bit came from (`running-state.source`); `null` when it did not say. */
49446
+ runningSource: _enum(["native", "assigned"]).nullable(),
49447
+ phases: array(DeviceRunPhaseSchema),
49448
+ detail: DeviceRunDetailSchema
49449
+ });
49450
+ DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, method(object({
49451
+ deviceId: number().int(),
49452
+ outcome: DeviceRunOutcomeSchema.optional(),
49453
+ atFrom: number().optional(),
49454
+ atTo: number().optional(),
49455
+ limit: number().int().positive().max(200).default(50),
49456
+ cursor: string().optional()
49457
+ }), object({
49458
+ runs: array(DeviceRunSchema).readonly(),
49459
+ nextCursor: string().nullable()
49460
+ })), method(object({
49461
+ deviceId: number().int(),
49462
+ runId: string()
49463
+ }), DeviceRunSchema.nullable()), method(object({ deviceId: number().int() }), DeviceRunSchema.nullable());
49302
49464
  var DeviceCaStatusSchema = discriminatedUnion("state", [
49303
49465
  object({ state: literal("absent") }),
49304
49466
  object({
@@ -49434,8 +49596,8 @@ method(object({}), object({
49434
49596
  });
49435
49597
  var KeychainKeySourceSchema = object({
49436
49598
  kind: _enum([
49437
- "config-file",
49438
- "previous-config-file",
49599
+ "mounted-file",
49600
+ "previous-mounted-file",
49439
49601
  "platform",
49440
49602
  "default-file"
49441
49603
  ]),
@@ -67944,10 +68106,7 @@ method(object({ nodeId: string().optional() }).optional(), array(AddonListItemSc
67944
68106
  }), InstallPackageResultSchema, {
67945
68107
  kind: "mutation",
67946
68108
  auth: "admin"
67947
- }), method(object({ packageName: string() }), InstallPackageResultSchema, {
67948
- kind: "mutation",
67949
- auth: "admin"
67950
- }), method(_void(), boolean()), method(_void(), array(unknown()).readonly()), method(object({
68109
+ }), method(object({
67951
68110
  packageName: string().min(1),
67952
68111
  nodeId: string().optional(),
67953
68112
  everywhere: boolean().optional()
@@ -80661,7 +80820,7 @@ var ExternalIdentityKeySchema = object({
80661
80820
  provider: string().min(1),
80662
80821
  subject: string().min(1)
80663
80822
  });
80664
- method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
80823
+ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(_void(), object({ defaultPasswordInUse: boolean() }), { auth: "admin" }), method(CreateUserInputSchema, UserSummarySchema, {
80665
80824
  kind: "mutation",
80666
80825
  auth: "admin",
80667
80826
  access: "create"
@@ -83559,13 +83718,6 @@ Object.freeze({
83559
83718
  access: "view",
83560
83719
  role: "admin"
83561
83720
  },
83562
- "addons.installFromWorkspace": {
83563
- capName: "addons",
83564
- capScope: "system",
83565
- addonId: null,
83566
- access: "create",
83567
- role: "admin"
83568
- },
83569
83721
  "addons.installPackage": {
83570
83722
  capName: "addons",
83571
83723
  capScope: "system",
@@ -83573,13 +83725,6 @@ Object.freeze({
83573
83725
  access: "create",
83574
83726
  role: "admin"
83575
83727
  },
83576
- "addons.isWorkspaceAvailable": {
83577
- capName: "addons",
83578
- capScope: "system",
83579
- addonId: null,
83580
- access: "view",
83581
- role: "admin"
83582
- },
83583
83728
  "addons.list": {
83584
83729
  capName: "addons",
83585
83730
  capScope: "system",
@@ -83629,13 +83774,6 @@ Object.freeze({
83629
83774
  access: "view",
83630
83775
  role: "admin"
83631
83776
  },
83632
- "addons.listWorkspacePackages": {
83633
- capName: "addons",
83634
- capScope: "system",
83635
- addonId: null,
83636
- access: "view",
83637
- role: "admin"
83638
- },
83639
83777
  "addons.onAddonLogs": {
83640
83778
  capName: "addons",
83641
83779
  capScope: "system",
@@ -86303,6 +86441,27 @@ Object.freeze({
86303
86441
  access: "create",
86304
86442
  role: "admin"
86305
86443
  },
86444
+ "deviceRuns.getCurrentRun": {
86445
+ capName: "device-runs",
86446
+ capScope: "device",
86447
+ addonId: null,
86448
+ access: "view",
86449
+ role: "viewer"
86450
+ },
86451
+ "deviceRuns.getRun": {
86452
+ capName: "device-runs",
86453
+ capScope: "device",
86454
+ addonId: null,
86455
+ access: "view",
86456
+ role: "viewer"
86457
+ },
86458
+ "deviceRuns.listRuns": {
86459
+ capName: "device-runs",
86460
+ capScope: "device",
86461
+ addonId: null,
86462
+ access: "view",
86463
+ role: "viewer"
86464
+ },
86306
86465
  "deviceState.claimFields": {
86307
86466
  capName: "device-state",
86308
86467
  capScope: "system",
@@ -93016,6 +93175,13 @@ Object.freeze({
93016
93175
  access: "view",
93017
93176
  role: "admin"
93018
93177
  },
93178
+ "userManagement.getAdminBootstrapStatus": {
93179
+ capName: "user-management",
93180
+ capScope: "system",
93181
+ addonId: null,
93182
+ access: "view",
93183
+ role: "admin"
93184
+ },
93019
93185
  "userManagement.getTotpStatus": {
93020
93186
  capName: "user-management",
93021
93187
  capScope: "system",
@@ -94501,6 +94667,21 @@ Object.freeze({
94501
94667
  form: "single",
94502
94668
  optional: false
94503
94669
  }],
94670
+ "deviceRuns.getCurrentRun": [{
94671
+ name: "deviceId",
94672
+ form: "single",
94673
+ optional: false
94674
+ }],
94675
+ "deviceRuns.getRun": [{
94676
+ name: "deviceId",
94677
+ form: "single",
94678
+ optional: false
94679
+ }],
94680
+ "deviceRuns.listRuns": [{
94681
+ name: "deviceId",
94682
+ form: "single",
94683
+ optional: false
94684
+ }],
94504
94685
  "deviceState.claimFields": [{
94505
94686
  name: "deviceId",
94506
94687
  form: "single",
@@ -98789,8 +98970,9 @@ var STATE_SUMMARY_VARS = [
98789
98970
  ];
98790
98971
  var NC_TEMPLATE_VARS = [
98791
98972
  {
98792
- name: "camera",
98793
- label: "Camera",
98973
+ name: "device",
98974
+ label: "Device",
98975
+ description: "The device the event is about: the camera for a track, the appliance or sensor for a device event.",
98794
98976
  example: "Front door",
98795
98977
  group: "subject",
98796
98978
  families: ["rule", "timelapse"],
@@ -99037,6 +99219,46 @@ var NC_TEMPLATE_VARS = [
99037
99219
  fields: [...RULE_TEXT],
99038
99220
  kinds: ["sensor"]
99039
99221
  },
99222
+ {
99223
+ name: "duration",
99224
+ label: "Cycle duration",
99225
+ description: "How long a finished appliance cycle ran, e.g. \"52 minutes\" or \"1 h 12 min\"; empty when the start is unknown.",
99226
+ example: "52 minuti",
99227
+ group: "sensor",
99228
+ families: ["rule"],
99229
+ fields: [...RULE_TEXT],
99230
+ kinds: ["sensor"]
99231
+ },
99232
+ {
99233
+ name: "energy",
99234
+ label: "Cycle energy",
99235
+ description: "Energy an appliance used over its finished cycle, e.g. \"0.84 kWh\"; empty without a power meter.",
99236
+ example: "0,84 kWh",
99237
+ group: "sensor",
99238
+ families: ["rule"],
99239
+ fields: [...RULE_TEXT],
99240
+ kinds: ["sensor"]
99241
+ },
99242
+ {
99243
+ name: "afterDuration",
99244
+ label: "\"after <duration>\" fragment",
99245
+ description: "Leading space included; empty when the cycle duration is unknown.",
99246
+ example: " dopo 52 minuti",
99247
+ group: "sensor",
99248
+ families: ["rule"],
99249
+ fields: [...RULE_TEXT],
99250
+ kinds: ["sensor"]
99251
+ },
99252
+ {
99253
+ name: "usedEnergy",
99254
+ label: "\"used <energy>\" fragment",
99255
+ description: "Leading space included; empty when the energy is unknown.",
99256
+ example: " e ha consumato 0,84 kWh",
99257
+ group: "sensor",
99258
+ families: ["rule"],
99259
+ fields: [...RULE_TEXT],
99260
+ kinds: ["sensor"]
99261
+ },
99040
99262
  {
99041
99263
  name: "ai",
99042
99264
  label: "AI sentence",
@@ -99175,6 +99397,16 @@ var NC_TEMPLATE_VARS = [
99175
99397
  kinds: ["system"],
99176
99398
  systemEventKinds: ["node-online", "node-offline"]
99177
99399
  },
99400
+ {
99401
+ name: "graceMin",
99402
+ label: "Update grace (minutes)",
99403
+ example: "10",
99404
+ group: "system",
99405
+ families: ["rule"],
99406
+ fields: [...RULE_TEXT],
99407
+ kinds: ["system"],
99408
+ systemEventKinds: ["node-offline"]
99409
+ },
99178
99410
  {
99179
99411
  name: "offlineFor",
99180
99412
  label: "Offline for",
@@ -99807,7 +100039,7 @@ function templateVarDeliveryApplies(d, ctx) {
99807
100039
  * descriptor so the whole rule stays in one line of code. */
99808
100040
  var CAPTION_VARS = {
99809
100041
  previewText: [
99810
- "camera",
100042
+ "device",
99811
100043
  "rule",
99812
100044
  "from",
99813
100045
  "to"
@@ -100757,7 +100989,7 @@ var TimelapseRuleInputSchema = object({
100757
100989
  * before this field existed still reads "Timelapse Camera front door" and
100758
100990
  * not the literal braces.
100759
100991
  */
100760
- var DEFAULT_TIMELAPSE_PREVIEW_TEXT = "Timelapse {{camera}}";
100992
+ var DEFAULT_TIMELAPSE_PREVIEW_TEXT = "Timelapse {{device}}";
100761
100993
  /**
100762
100994
  * Partial patch for an update — any subset of the INPUT fields, with NO
100763
100995
  * defaults (an absent key means "leave unchanged", never "reset to default").
@@ -102991,6 +103223,12 @@ Object.defineProperty(exports, "customAction", {
102991
103223
  return customAction;
102992
103224
  }
102993
103225
  });
103226
+ Object.defineProperty(exports, "defineAddonMigrations", {
103227
+ enumerable: true,
103228
+ get: function() {
103229
+ return defineAddonMigrations;
103230
+ }
103231
+ });
102994
103232
  Object.defineProperty(exports, "defineCustomActions", {
102995
103233
  enumerable: true,
102996
103234
  get: function() {