@camstack/addon-provider-reolink 1.2.191 → 1.2.193

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 +496 -141
  2. package/dist/addon.mjs +496 -141
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -5451,7 +5451,7 @@ var ZodIssueCode = {
5451
5451
  var ZodFirstPartyTypeKind;
5452
5452
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5453
5453
  //#endregion
5454
- //#region ../types/dist/sleep-BxjU_fJM.mjs
5454
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
5455
5455
  /**
5456
5456
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5457
5457
  * window to float samples (D455).
@@ -7838,9 +7838,9 @@ function normalizeAddonInitResult(result) {
7838
7838
  return result;
7839
7839
  }
7840
7840
  /**
7841
- * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7842
- * and validates them (`share-token.service.ts` builds its enum from this
7843
- * list); a data plane names the kinds it ACCEPTS in `share`.
7841
+ * The share-view scope kinds a share-link token can carry. The hub mints
7842
+ * and validates them (`ShareViewGrantSchema` builds its
7843
+ * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
7844
7844
  */
7845
7845
  var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7846
7846
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
@@ -13144,7 +13144,7 @@ var ConvertResultSchema = object({
13144
13144
  * `super_admin` — collapsed onto the single boolean because every
13145
13145
  * non-admin caller is governed by the same scope-check rules; the
13146
13146
  * distinction was only ever used to route role-specific procedures
13147
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
13147
+ * which we no longer have. CLI / webhook integrations are tokens (`auth.mintToken`)
13148
13148
  * with `isAdmin: false` + an explicit scope list.
13149
13149
  */
13150
13150
  /** Per-method access flavour. Materialised on every cap method via codegen. */
@@ -13333,10 +13333,12 @@ var AddonRoutesScopeSchema = object({
13333
13333
  type: literal("addon-routes"),
13334
13334
  access: array(MethodAccessSchema).min(1)
13335
13335
  });
13336
+ var PreferencesSelfScopeSchema = object({ type: literal("preferences-self") });
13336
13337
  var CredentialScopeSchema = union([
13337
13338
  literal("*"),
13338
13339
  ShareViewScopeSchema,
13339
13340
  AddonRoutesScopeSchema,
13341
+ PreferencesSelfScopeSchema,
13340
13342
  TokenScopeSchema
13341
13343
  ]);
13342
13344
  object({
@@ -13345,6 +13347,55 @@ object({
13345
13347
  jti: string().min(16),
13346
13348
  scopes: array(CredentialScopeSchema).min(1)
13347
13349
  });
13350
+ var PreferenceNamespaceSchema = string().regex(/^[a-z][a-z0-9.-]{0,63}$/);
13351
+ /** A namespace's value: a JSON object, opaque to the hub. */
13352
+ var PreferenceValueSchema = record(string(), unknown());
13353
+ var PreferenceDeviceIdSchema = string().min(1).max(64);
13354
+ /** A stored row, as the owner reads it. */
13355
+ var PreferenceRowSchema = object({
13356
+ namespace: PreferenceNamespaceSchema,
13357
+ value: PreferenceValueSchema,
13358
+ /** Starts at 1, +1 on every write of this namespace. A delete ends the row and its count. */
13359
+ revision: number().int().positive(),
13360
+ updatedAt: number().int(),
13361
+ /** The client id the last writer sent; `null` when it sent none. */
13362
+ updatedByDevice: PreferenceDeviceIdSchema.nullable()
13363
+ });
13364
+ object({
13365
+ /** Absent: every namespace the caller holds. */
13366
+ namespaces: array(PreferenceNamespaceSchema).max(32).optional() });
13367
+ object({ rows: array(PreferenceRowSchema) });
13368
+ object({
13369
+ namespace: PreferenceNamespaceSchema,
13370
+ value: PreferenceValueSchema,
13371
+ /**
13372
+ * The revision the edit was based on. Absent: last write wins. `0`: the
13373
+ * namespace must not exist yet. Any other value that is not the current
13374
+ * revision answers `conflict` and writes nothing.
13375
+ */
13376
+ baseRevision: number().int().nonnegative().optional(),
13377
+ deviceId: PreferenceDeviceIdSchema.optional()
13378
+ });
13379
+ discriminatedUnion("status", [object({
13380
+ status: literal("saved"),
13381
+ row: PreferenceRowSchema
13382
+ }), object({
13383
+ status: literal("conflict"),
13384
+ current: PreferenceRowSchema.nullable()
13385
+ })]);
13386
+ object({ namespace: PreferenceNamespaceSchema });
13387
+ object({
13388
+ /** `false` when the namespace did not exist. */
13389
+ deleted: boolean() });
13390
+ object({
13391
+ /** The revision the client holds per namespace; a namespace it does not list is new to it. */
13392
+ revisionByNamespace: record(PreferenceNamespaceSchema, number().int().nonnegative()).refine((map) => Object.keys(map).length <= 32, { message: `at most 32 namespaces` }) });
13393
+ object({
13394
+ /** Every row whose revision differs from the client's, and every row it did not list. */
13395
+ rows: array(PreferenceRowSchema),
13396
+ /** Namespaces the client listed that no longer exist. */
13397
+ deleted: array(PreferenceNamespaceSchema)
13398
+ });
13348
13399
  _enum(["new-session", "step-up"]);
13349
13400
  /** The languages the hub's app landing pages are written in (D858). */
13350
13401
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -17598,7 +17649,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
17598
17649
  kind: literal("node"),
17599
17650
  nodeId: string().min(1)
17600
17651
  })]);
17652
+ /**
17653
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17654
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17655
+ * meaning); a rollup keeps the time spent in each state (`states`).
17656
+ */
17601
17657
  var DeviceHistoryKindSchema = _enum([
17658
+ "gauge",
17659
+ "counter",
17660
+ "boolean",
17661
+ "enum"
17662
+ ]);
17663
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17664
+ var DeviceHistoryProducerKindSchema = _enum([
17602
17665
  "gauge",
17603
17666
  "counter",
17604
17667
  "boolean"
@@ -17635,7 +17698,13 @@ var SeriesInfoSchema = object({
17635
17698
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17636
17699
  unit: string().nullable(),
17637
17700
  displayName: string(),
17638
- source: _enum(["cap", "addon"]),
17701
+ source: _enum([
17702
+ "cap",
17703
+ "addon",
17704
+ "derived"
17705
+ ]),
17706
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17707
+ values: array(string()).readonly().nullable(),
17639
17708
  firstTs: number(),
17640
17709
  lastTs: number()
17641
17710
  });
@@ -17649,17 +17718,31 @@ var QueryPointSchema = object({
17649
17718
  twMean: number().nullable(),
17650
17719
  min: number(),
17651
17720
  max: number(),
17652
- /** `null` is unknown, never zero (D393). */
17653
- last: number().nullable()
17721
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17722
+ last: number().nullable(),
17723
+ /**
17724
+ * The increase over the point: a `counter`'s growth since the previous point
17725
+ * or bucket (a drop is a reset, counted from zero), and for
17726
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17727
+ * every other kind, and when it cannot be known.
17728
+ */
17729
+ delta: number().nullable(),
17730
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17731
+ state: string().nullable(),
17732
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17733
+ states: record(string(), number()).nullable()
17654
17734
  });
17655
17735
  var QuerySeriesSchema = object({
17656
17736
  scope: string(),
17657
17737
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17658
17738
  before: object({
17659
17739
  t: number(),
17660
- value: number().nullable()
17740
+ value: number().nullable(),
17741
+ state: string().nullable()
17661
17742
  }).nullable(),
17662
- points: array(QueryPointSchema).readonly()
17743
+ points: array(QueryPointSchema).readonly(),
17744
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17745
+ derivedFrom: string().nullable()
17663
17746
  });
17664
17747
  /** The window part of a query, shared by the device and node forms. */
17665
17748
  var QueryWindowShape = {
@@ -17675,6 +17758,23 @@ var QueryResultSchema = object({
17675
17758
  series: array(QuerySeriesSchema).readonly(),
17676
17759
  truncated: boolean()
17677
17760
  });
17761
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17762
+ var QueryManyItemSchema = union([object({
17763
+ deviceId: number().int(),
17764
+ key: string(),
17765
+ scope: string().optional()
17766
+ }), object({
17767
+ forNodeId: string().min(1),
17768
+ key: string(),
17769
+ scope: string().optional()
17770
+ })]);
17771
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
17772
+ ok: literal(true),
17773
+ result: QueryResultSchema
17774
+ }), object({
17775
+ ok: literal(false),
17776
+ error: string()
17777
+ })]);
17678
17778
  var TierStatusSchema = object({
17679
17779
  tier: DeviceHistoryResolutionSchema,
17680
17780
  /** `null` until the first background count answered. */
@@ -17730,16 +17830,22 @@ var DeviceHistoryStatusSchema = object({
17730
17830
  lastRefreshAt: number().nullable()
17731
17831
  })
17732
17832
  });
17733
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17833
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17734
17834
  deviceId: number().int(),
17735
17835
  ...QueryWindowShape
17736
17836
  }), QueryResultSchema), method(object({
17737
- nodeId: string().min(1),
17837
+ forNodeId: string().min(1),
17738
17838
  ...QueryWindowShape
17739
17839
  }), QueryResultSchema, { auth: "admin" }), method(object({
17840
+ items: array(QueryManyItemSchema).min(1).max(24),
17841
+ from: QueryWindowShape.from,
17842
+ to: QueryWindowShape.to,
17843
+ resolution: QueryWindowShape.resolution,
17844
+ maxPoints: QueryWindowShape.maxPoints
17845
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
17740
17846
  name: string().regex(/^[a-z0-9-]+$/),
17741
17847
  subjectKind: _enum(["device", "node"]),
17742
- kind: DeviceHistoryKindSchema,
17848
+ kind: DeviceHistoryProducerKindSchema,
17743
17849
  unit: string().optional(),
17744
17850
  displayName: string().min(1),
17745
17851
  ingest: _enum(["points", "buckets"])
@@ -40653,38 +40759,37 @@ method(LlmRuntimeCompleteInputSchema, LlmGenerateResultSchema, {
40653
40759
  auth: "admin",
40654
40760
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
40655
40761
  });
40762
+ var LlmProfileKindSchema = string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "a kind id is lower-case letters, digits and dashes");
40763
+ /** What a model (or, by default, every model of a kind) can do. */
40764
+ var LlmModelFeaturesSchema = object({
40765
+ vision: boolean(),
40766
+ tools: boolean(),
40767
+ streaming: boolean()
40768
+ });
40769
+ /** One model a provider offers. `features` overrides the kind's defaults, per field. */
40770
+ var LlmModelInfoSchema = object({
40771
+ id: string(),
40772
+ label: string().optional(),
40773
+ contextLength: number().int().positive().optional(),
40774
+ features: LlmModelFeaturesSchema.partial().optional()
40775
+ });
40656
40776
  /**
40657
- * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
40658
- * methods concat-fan across providers; single-row methods route to ONE
40659
- * provider by the `addonId` in the call input (the notification-output
40660
- * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
40661
- * (hub-placed); the cap stays open for future providers.
40662
- *
40663
- * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
40664
- * `apiKey` is a password field — providers REDACT it on read and merge on
40665
- * write; a stored key NEVER round-trips to a client.
40777
+ * The provider-specific part of a profile, validated by the provider that owns
40778
+ * the kind (`upsertProfile` refuses what it does not accept). A field its
40779
+ * `connectionSchema` declares `type: 'password'` is a secret: it is held in the
40780
+ * keychain, never in the row, and reads back as the redaction marker.
40666
40781
  */
40667
- var LlmProfileKindSchema = _enum([
40668
- "openai-compatible",
40669
- "openai",
40670
- "anthropic",
40671
- "google",
40672
- "managed-local",
40673
- "apple-foundation"
40674
- ]);
40782
+ var LlmProviderConfigSchema = record(string(), unknown());
40675
40783
  var LlmProfileSchema = object({
40676
40784
  id: string(),
40677
40785
  name: string(),
40786
+ /** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
40678
40787
  kind: LlmProfileKindSchema,
40679
40788
  /** Stamped by the provider — keeps the fanned catalog routable. */
40680
40789
  addonId: string(),
40681
40790
  enabled: boolean(),
40682
40791
  /** Vendor model id, or the managed runtime's loaded model. */
40683
40792
  model: string(),
40684
- /** Required for openai-compatible; override for cloud kinds. */
40685
- baseUrl: string().optional(),
40686
- /** ConfigUISchema type:'password' — never round-trips (spec §5). */
40687
- apiKey: string().optional(),
40688
40793
  /** Vision on/off. A vision call against a `false` profile is REFUSED, never
40689
40794
  * degraded to text — that shipped once and produced a confident answer to a
40690
40795
  * question about a picture nobody sent. */
@@ -40692,15 +40797,11 @@ var LlmProfileSchema = object({
40692
40797
  temperature: number().min(0).max(2).optional(),
40693
40798
  /** Nucleus sampling. Every wire we speak has it. */
40694
40799
  topP: number().min(0).max(1).optional(),
40695
- /** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
40696
- * wire does, and the client drops it there (measured: the request body gets
40697
- * `top_p` and no `top_k`). The profile editor hides the field wherever it
40698
- * would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
40800
+ /** Top-k sampling. Carried only by the wires that have it — a kind offers the
40801
+ * field in its editor only when its descriptor lists it in `profileFields`. */
40699
40802
  topK: number().int().positive().optional(),
40700
40803
  maxTokens: number().int().positive().optional(),
40701
- /** Prompt context window. Advisory for cloud kinds (they enforce their own);
40702
- * for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
40703
- * the model with, so it is the one field that changes a PROCESS. */
40804
+ /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
40704
40805
  contextLength: number().int().positive().optional(),
40705
40806
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
40706
40807
  * two system prompts fighting is worse than either alone). */
@@ -40726,16 +40827,37 @@ var LlmProfileSchema = object({
40726
40827
  * library; the REGISTRY of callable tools is ours and is empty in v1, so a
40727
40828
  * `true` here buys the wiring, not behaviour, until tools are registered. */
40728
40829
  toolsEnabled: boolean().default(false),
40729
- extraHeaders: record(string(), string()).optional(),
40730
- /** kind === 'managed-local' only (spec §4). */
40731
- runtime: ManagedRuntimeConfigSchema.optional(),
40732
- /**
40733
- * kind === 'apple-foundation' only: WHERE it runs — the only thing there is
40734
- * to configure (no key, no URL, no download; `model` is `apple-system`).
40735
- * `supportsVision` on such a row is stamped by the provider from the node's
40736
- * reported `imageInput`, never taken from the operator (D62).
40737
- */
40738
- appleFoundation: object({ nodeId: string() }).optional()
40830
+ /** Everything the kind's provider owns (endpoint, key, node, runtime…). */
40831
+ providerConfig: LlmProviderConfigSchema.default({})
40832
+ });
40833
+ /**
40834
+ * The common profile fields a kind's editor offers. The editor owns how each
40835
+ * one is drawn; the provider says which of them mean something on its wire.
40836
+ */
40837
+ var LlmProfileFieldSchema = _enum([
40838
+ "temperature",
40839
+ "topP",
40840
+ "topK",
40841
+ "maxTokens",
40842
+ "contextLength",
40843
+ "systemPrompt",
40844
+ "timeoutMs",
40845
+ "connectTimeoutMs",
40846
+ "firstTokenTimeoutMs",
40847
+ "idleTimeoutMs",
40848
+ "retry",
40849
+ "toolsEnabled"
40850
+ ]);
40851
+ /**
40852
+ * A provider-drawn part of the editor, by a generic widget id the admin UI
40853
+ * registers (`ai/apple-node`). `placement: 'model'` replaces the generic model
40854
+ * picker: that widget owns the model choice.
40855
+ */
40856
+ var LlmProviderWidgetSchema = object({
40857
+ id: string(),
40858
+ placement: _enum(["connection", "model"]),
40859
+ /** `providerConfig` keys this widget must fill before the profile can be saved. */
40860
+ requires: array(string()).optional()
40739
40861
  });
40740
40862
  /** ConfigUISchema tree passed through untyped on the wire (the
40741
40863
  * notification-output `ConfigSchemaPassthrough` precedent at
@@ -40744,11 +40866,56 @@ var ConfigSchemaPassthrough$3 = unknown();
40744
40866
  var LlmProfileKindDescriptorSchema = object({
40745
40867
  kind: LlmProfileKindSchema,
40746
40868
  label: string(),
40869
+ /** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
40747
40870
  icon: string(),
40748
40871
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
40749
40872
  addonId: string(),
40750
- configSchema: ConfigSchemaPassthrough$3
40873
+ /** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
40874
+ connectionSchema: ConfigSchemaPassthrough$3,
40875
+ /** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
40876
+ advancedSchema: ConfigSchemaPassthrough$3.optional(),
40877
+ /** The kind's defaults; a model from `listModels` may override any of them. */
40878
+ features: LlmModelFeaturesSchema,
40879
+ /** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
40880
+ visionEditable: boolean(),
40881
+ /** Where the model list comes from: `listModels`, `staticModels`, or nowhere. */
40882
+ modelCatalog: _enum([
40883
+ "fetch",
40884
+ "static",
40885
+ "none"
40886
+ ]),
40887
+ staticModels: array(LlmModelInfoSchema).optional(),
40888
+ /** The common fields that mean something on this kind's wire. */
40889
+ profileFields: array(LlmProfileFieldSchema),
40890
+ providerWidgets: array(LlmProviderWidgetSchema).optional()
40891
+ });
40892
+ /**
40893
+ * `listModels` input. `connection` is an UNSAVED draft of `providerConfig`
40894
+ * (the editor's form); with `profileId` too, a secret the draft leaves
40895
+ * untouched (absent or the redaction marker) is resolved server-side from the
40896
+ * stored profile — the browser never receives it.
40897
+ */
40898
+ var LlmListModelsInputSchema = object({
40899
+ addonId: string(),
40900
+ kind: LlmProfileKindSchema,
40901
+ profileId: string().optional(),
40902
+ connection: LlmProviderConfigSchema.optional()
40751
40903
  });
40904
+ var LlmListModelsErrorCodeSchema = _enum([
40905
+ "auth",
40906
+ "network",
40907
+ "unsupported",
40908
+ "invalid"
40909
+ ]);
40910
+ /** A RESULT, never a throw: "wrong key" is an answer the editor renders inline. */
40911
+ var LlmListModelsResultSchema = discriminatedUnion("ok", [object({
40912
+ ok: literal(true),
40913
+ models: array(LlmModelInfoSchema)
40914
+ }), object({
40915
+ ok: literal(false),
40916
+ code: LlmListModelsErrorCodeSchema,
40917
+ message: string()
40918
+ })]);
40752
40919
  var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
40753
40920
  var LlmDefaultSchema = object({
40754
40921
  selector: LlmDefaultSelectorSchema,
@@ -40848,7 +41015,10 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
40848
41015
  kind: "mutation",
40849
41016
  auth: "admin",
40850
41017
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
40851
- }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
41018
+ }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
41019
+ kind: "mutation",
41020
+ auth: "admin"
41021
+ }), method(object({}), array(LlmDefaultSchema)), method(object({
40852
41022
  selector: LlmDefaultSelectorSchema,
40853
41023
  profileId: string().nullable()
40854
41024
  }), _void(), {
@@ -41037,14 +41207,106 @@ var LogEntrySchema = object({
41037
41207
  meta: record(string(), unknown()).optional(),
41038
41208
  tags: record(string(), string()).optional()
41039
41209
  });
41040
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
41041
- scope: array(string()).optional(),
41210
+ /**
41211
+ * A history READ against one destination (D898).
41212
+ *
41213
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
41214
+ * browser applied after the limit is what made a rare device's lines
41215
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
41216
+ * minted (opaque to everyone else): a file position for the rotated files, a
41217
+ * nanosecond timestamp for Loki.
41218
+ *
41219
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
41220
+ * store answers `done: false` with the cursor it reached and the bytes it
41221
+ * scanned, and the caller decides whether to go on. That is what makes a long
41222
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
41223
+ * flight, and not asking for the next slice ends the scan.
41224
+ */
41225
+ var LogReadQuerySchema = object({
41226
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
41227
+ requestId: string().min(1).max(64).optional(),
41228
+ /** The device the line is about (`tags.deviceId`, numeric). */
41229
+ deviceId: number().int().optional(),
41230
+ /**
41231
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
41232
+ * match. Not `addonId`: a cap router reads that name as "which provider".
41233
+ */
41234
+ fromAddonId: string().min(1).max(200).optional(),
41235
+ /**
41236
+ * The emitting node: matches the agent that emitted the line, the node
41237
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
41238
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
41239
+ * name as "which node's provider".
41240
+ */
41241
+ fromNodeId: string().min(1).max(200).optional(),
41242
+ /** Any other tag, exact match (AND). */
41243
+ tags: record(string(), union([string(), number()])).optional(),
41244
+ /** Severity FLOOR: this level and above. */
41042
41245
  level: LogLevelSchema.optional(),
41043
- since: date().optional(),
41044
- until: date().optional(),
41045
- limit: number().optional(),
41046
- tags: record(string(), string()).optional()
41047
- }), array(LogEntrySchema).readonly());
41246
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
41247
+ text: string().min(1).max(200).optional(),
41248
+ /** Epoch ms, inclusive. */
41249
+ since: number().optional(),
41250
+ /** Epoch ms, inclusive. */
41251
+ until: number().optional(),
41252
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
41253
+ before: string().min(1).max(1024).optional(),
41254
+ /** Newer than this cursor (exclusive). */
41255
+ after: string().min(1).max(1024).optional(),
41256
+ limit: number().int().min(1).max(1e3).optional(),
41257
+ /** Wall-clock bound of this slice. The provider caps it. */
41258
+ budgetMs: number().int().min(50).max(1e4).optional()
41259
+ });
41260
+ var LogReadResultSchema = object({
41261
+ /** Newest first. */
41262
+ entries: array(object({
41263
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
41264
+ id: string().optional(),
41265
+ /** Epoch ms. */
41266
+ timestamp: number(),
41267
+ level: LogLevelSchema,
41268
+ scope: string().optional(),
41269
+ message: string(),
41270
+ tags: record(string(), union([string(), number()])).optional(),
41271
+ meta: record(string(), unknown()).optional()
41272
+ })),
41273
+ /** Pass as `before` for the next older page; null when nothing older exists. */
41274
+ nextBefore: string().nullable(),
41275
+ /** Pass as `after` to read what arrived since; null when unknown. */
41276
+ nextAfter: string().nullable(),
41277
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
41278
+ scannedBytes: number().int().nonnegative(),
41279
+ /**
41280
+ * True when the scan in this direction reached the end of the store.
41281
+ * False with fewer than `limit` entries means the budget ran out first —
41282
+ * call again with `nextBefore` to go on.
41283
+ */
41284
+ done: boolean(),
41285
+ /** True when `cancelRead` ended this slice early. */
41286
+ cancelled: boolean().optional()
41287
+ });
41288
+ var LogReadCapabilitiesSchema = object({
41289
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
41290
+ readable: boolean(),
41291
+ /** Why not, when `readable` is false — rendered next to the source. */
41292
+ reason: string().nullable(),
41293
+ /** Filters the provider applies itself. A false one is applied by nobody. */
41294
+ filters: object({
41295
+ deviceId: boolean(),
41296
+ addonId: boolean(),
41297
+ nodeId: boolean(),
41298
+ tags: boolean(),
41299
+ level: boolean(),
41300
+ text: boolean(),
41301
+ timeRange: boolean()
41302
+ }),
41303
+ /** How far back the store reaches, when the provider knows (days). */
41304
+ retentionDays: number().nullable()
41305
+ });
41306
+ method(LogEntrySchema, _void(), { kind: "mutation" }), optionalMethod(_void(), LogReadCapabilitiesSchema, { auth: "admin" }), optionalMethod(LogReadQuerySchema, LogReadResultSchema, { auth: "admin" }), optionalMethod(object({ requestId: string().min(1).max(64) }), object({ cancelled: boolean() }), {
41307
+ kind: "mutation",
41308
+ auth: "admin"
41309
+ });
41048
41310
  /**
41049
41311
  * `login-method` — collection cap through which auth addons contribute
41050
41312
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -42762,9 +43024,11 @@ var alarmPanelCapability = {
42762
43024
  */
42763
43025
  durability: "restored",
42764
43026
  /**
42765
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
43027
+ * History (D850): the panel's lifecycle state as an `enum` series —
43028
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
43029
+ * few seconds keeps every step. Who armed it stays in the events ledger.
42766
43030
  */
42767
- history: "none",
43031
+ history: { fields: { state: { kind: "enum" } } },
42768
43032
  /** Clock fields: written, but excluded from the compare that decides
42769
43033
  * whether persisting is worth a SQLite commit. */
42770
43034
  volatileStateFields: ["lastChangedAt"]
@@ -43642,6 +43906,33 @@ var NcRuleTargetSchema = object({
43642
43906
  params: record(string(), unknown()).optional()
43643
43907
  });
43644
43908
  /**
43909
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
43910
+ *
43911
+ * Every mode starts from the same CLEAN source frame of the trigger moment
43912
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
43913
+ * to the zone that fired the rule) and renders it once at send time:
43914
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
43915
+ * colour and every OTHER track visible at that instant outlined thin, each
43916
+ * labelled with class and confidence ("dog 87%").
43917
+ * - `crop` — the subject cut out of that frame around its box at that instant.
43918
+ * - `clean` — the whole scene with nothing drawn on it.
43919
+ * - `none` — no picture.
43920
+ *
43921
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
43922
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
43923
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
43924
+ * ship a crop on one event and a boxed scene on the next depending on which
43925
+ * stored kind had landed.
43926
+ */
43927
+ var NcMediaImageSchema = _enum([
43928
+ "scene-boxes",
43929
+ "crop",
43930
+ "clean",
43931
+ "none"
43932
+ ]);
43933
+ /**
43934
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43935
+ *
43645
43936
  * Media attachment policy (P1 still-image subset).
43646
43937
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
43647
43938
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -43655,6 +43946,8 @@ var NcRuleTargetSchema = object({
43655
43946
  * - `none` — no attachment.
43656
43947
  */
43657
43948
  /**
43949
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43950
+ *
43658
43951
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
43659
43952
  * conflate it with the selection strategy and betray the request: asking for
43660
43953
  * the clean scene frame on an object-event owner used to start at
@@ -43683,16 +43976,29 @@ var NcMediaFrameSchema = _enum([
43683
43976
  */
43684
43977
  var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
43685
43978
  var NcMediaPolicySchema = object({
43979
+ /**
43980
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
43981
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
43982
+ * triple below, at load and at every write, and the store keeps only this.
43983
+ */
43984
+ image: NcMediaImageSchema.optional(),
43985
+ /**
43986
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
43987
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
43988
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
43989
+ * Replaces `zoneCrop`.
43990
+ */
43991
+ showTriggerZone: boolean().optional(),
43992
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43686
43993
  attach: _enum([
43687
43994
  "best",
43688
43995
  "best-matching",
43689
43996
  "keyFrame",
43690
43997
  "none"
43691
- ]).default("best"),
43692
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
43998
+ ]).optional(),
43999
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43693
44000
  frame: NcMediaFrameSchema.optional(),
43694
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
43695
- * "show me the ZONE", not the whole scene or the subject crop. */
44001
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
43696
44002
  zoneCrop: boolean().optional(),
43697
44003
  /**
43698
44004
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -43864,7 +44170,9 @@ var NcRuleInputSchema = object({
43864
44170
  * targets.
43865
44171
  */
43866
44172
  targetUsers: array(string()).optional(),
43867
- media: NcMediaPolicySchema.default({ attach: "best" }),
44173
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
44174
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
44175
+ media: NcMediaPolicySchema.default({}),
43868
44176
  throttle: NcThrottleSchema.default({
43869
44177
  cooldownSec: 60,
43870
44178
  scope: "rule-device"
@@ -44801,13 +45109,37 @@ var NcAlarmModeOpeningsSchema = object({
44801
45109
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
44802
45110
  unknown: array(number().int())
44803
45111
  });
45112
+ /**
45113
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
45114
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
45115
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
45116
+ * never looks fully armed (D62: off must never look like broken).
45117
+ */
45118
+ var NcAlarmInputBypassViewSchema = object({
45119
+ ruleId: string(),
45120
+ /** The rule's current name (its frozen name when the rule is gone). */
45121
+ ruleName: string(),
45122
+ /** The input: the sensor of the match, else its camera. */
45123
+ deviceId: number().int(),
45124
+ /** The input's current name. */
45125
+ name: string(),
45126
+ /** When it was bypassed (ms epoch). */
45127
+ since: number(),
45128
+ /** Triggers from this input dropped since. */
45129
+ dropped: number().int().min(0)
45130
+ });
44804
45131
  var NcAlarmLiveSchema = object({
44805
45132
  state: AlarmStateSchema,
44806
45133
  /** The mode being armed into (exit delay) or held; null when disarmed. */
44807
45134
  targetMode: AlarmArmModeSchema.nullable(),
44808
45135
  availableModes: array(AlarmArmModeSchema),
44809
45136
  openings: array(NcAlarmModeOpeningsSchema),
44810
- exclusions: array(NcAlarmExclusionViewSchema)
45137
+ exclusions: array(NcAlarmExclusionViewSchema),
45138
+ /**
45139
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
45140
+ * Defaulted so an older hub answer still parses (as "none known").
45141
+ */
45142
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
44811
45143
  });
44812
45144
  var NcAlarmConfigSchema = object({
44813
45145
  /**
@@ -56048,9 +56380,11 @@ var connectivityCapability = {
56048
56380
  */
56049
56381
  durability: "restored",
56050
56382
  /**
56051
- * History (D850): none — duplicates device-status.online (one authority for availability).
56383
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
56384
+ * is the upstream entity's own link (a HA connectivity sensor), not the
56385
+ * device's reachability, which stays `device-status.online`.
56052
56386
  */
56053
- history: "none",
56387
+ history: { fields: { connected: { kind: "boolean" } } },
56054
56388
  /** Clock fields: written, but excluded from the compare that decides
56055
56389
  * whether persisting is worth a SQLite commit. */
56056
56390
  volatileStateFields: ["lastChangedAt"]
@@ -56874,11 +57208,22 @@ var dishwasherCapability = {
56874
57208
  },
56875
57209
  runtimeState: DishwasherStatusSchema,
56876
57210
  durability: "session",
56877
- history: { fields: { progressPercent: {
56878
- kind: "gauge",
56879
- unit: "%",
56880
- deadband: 2
56881
- } } }
57211
+ history: { fields: {
57212
+ progressPercent: {
57213
+ kind: "gauge",
57214
+ unit: "%",
57215
+ deadband: 2
57216
+ },
57217
+ state: { kind: "enum" },
57218
+ operationState: { kind: "enum" },
57219
+ remainingSeconds: {
57220
+ kind: "gauge",
57221
+ unit: "s",
57222
+ minIntervalMs: 6e4
57223
+ },
57224
+ doorOpen: { kind: "boolean" },
57225
+ powerOn: { kind: "boolean" }
57226
+ } }
56882
57227
  };
56883
57228
  var DoorbellStatusSchema = object({
56884
57229
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -56995,9 +57340,15 @@ var enumSensorCapability = {
56995
57340
  */
56996
57341
  durability: "restored",
56997
57342
  /**
56998
- * History (D850): none — text/enum state has no history (non-goal).
57343
+ * History (D850): the value as an `enum` series (an appliance's program or
57344
+ * operation state, an HVAC action). The option set is per device, so the
57345
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
57346
+ * `format` carries a timestamp, not a state, and is not recorded.
56999
57347
  */
57000
- history: "none",
57348
+ history: { fields: { value: {
57349
+ kind: "enum",
57350
+ skipWhenSet: "format"
57351
+ } } },
57001
57352
  /** Clock fields: written, but excluded from the compare that decides
57002
57353
  * whether persisting is worth a SQLite commit. */
57003
57354
  volatileStateFields: ["lastFetchedAt"]
@@ -58971,9 +59322,10 @@ var lockControlCapability = {
58971
59322
  */
58972
59323
  durability: "restored",
58973
59324
  /**
58974
- * History (D850): none — enum state; lock events belong in the events ledger.
59325
+ * History (D850): the lock's state as an `enum` series — change-only, no
59326
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
58975
59327
  */
58976
- history: "none",
59328
+ history: { fields: { state: { kind: "enum" } } },
58977
59329
  /** Clock fields: written, but excluded from the compare that decides
58978
59330
  * whether persisting is worth a SQLite commit. */
58979
59331
  volatileStateFields: ["lastChangedAt"]
@@ -59147,9 +59499,18 @@ var mediaPlayerCapability = {
59147
59499
  */
59148
59500
  durability: "session",
59149
59501
  /**
59150
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
59502
+ * History (D850): volume (a level an operator or an automation sets; the
59503
+ * default 10 s floor folds a slider drag into its end value) and mute.
59504
+ * `positionMs` is not recorded: it moves continuously while playing.
59151
59505
  */
59152
- history: "none"
59506
+ history: { fields: {
59507
+ volumeLevel: {
59508
+ kind: "gauge",
59509
+ unit: "%",
59510
+ deadband: 1
59511
+ },
59512
+ isMuted: { kind: "boolean" }
59513
+ } }
59153
59514
  };
59154
59515
  /**
59155
59516
  * mesh-network — collection cap for mesh-VPN providers.
@@ -64814,9 +65175,29 @@ var streamParamsCapability = {
64814
65175
  */
64815
65176
  durability: "restored",
64816
65177
  /**
64817
- * History (D850): none — encoder configuration.
65178
+ * History (D850): the configured bitrate and frame rate of the main and sub
65179
+ * profiles. Configuration, so change-only on the default floor: a point is an
65180
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
65181
+ * quality over time must show.
64818
65182
  */
64819
- history: "none",
65183
+ history: { fields: {
65184
+ "main.bitrate": {
65185
+ kind: "gauge",
65186
+ unit: "kbps"
65187
+ },
65188
+ "main.framerate": {
65189
+ kind: "gauge",
65190
+ unit: "fps"
65191
+ },
65192
+ "sub.bitrate": {
65193
+ kind: "gauge",
65194
+ unit: "kbps"
65195
+ },
65196
+ "sub.framerate": {
65197
+ kind: "gauge",
65198
+ unit: "fps"
65199
+ }
65200
+ } },
64820
65201
  /** Clock fields: written, but excluded from the compare that decides
64821
65202
  * whether persisting is worth a SQLite commit. */
64822
65203
  volatileStateFields: ["lastFetchedAt"]
@@ -65849,26 +66230,6 @@ var ApiKeySummarySchema = object({
65849
66230
  createdAt: number(),
65850
66231
  lastUsedAt: number().optional()
65851
66232
  });
65852
- var ScopedTokenSummarySchema = object({
65853
- id: string(),
65854
- userId: string(),
65855
- name: string(),
65856
- tokenPrefix: string(),
65857
- scopes: array(TokenScopeSchema),
65858
- expiresAt: number().nullish(),
65859
- lastUsedAt: number().nullish(),
65860
- createdAt: number()
65861
- });
65862
- var CreateScopedTokenInputSchema = object({
65863
- userId: string(),
65864
- name: string(),
65865
- scopes: array(TokenScopeSchema),
65866
- expiresAt: number().optional()
65867
- });
65868
- var CreateScopedTokenResultSchema = object({
65869
- token: string(),
65870
- record: ScopedTokenSummarySchema
65871
- });
65872
66233
  var OauthSessionSummarySchema = object({
65873
66234
  id: string(),
65874
66235
  userId: string(),
@@ -65890,11 +66251,11 @@ var TotpStatusSchema = object({
65890
66251
  confirmedAt: number().nullable()
65891
66252
  });
65892
66253
  /**
65893
- * user-management — singleton capability for user accounts, API keys,
65894
- * and scoped tokens.
66254
+ * user-management — singleton capability for user accounts and the
66255
+ * legacy API-key rows.
65895
66256
  *
65896
66257
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
65897
- * — the subset check on `setUserScopes` / `createScopedToken` is moot
66258
+ * — the subset check on `setUserScopes` is moot
65898
66259
  * because non-admins never reach these. If/when we open non-admin
65899
66260
  * delegation, structural caller-scope subset check goes inside the
65900
66261
  * provider.
@@ -65951,15 +66312,7 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
65951
66312
  kind: "mutation",
65952
66313
  auth: "admin",
65953
66314
  access: "delete"
65954
- }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
65955
- kind: "mutation",
65956
- auth: "admin",
65957
- access: "create"
65958
- }), method(object({ id: string() }), object({ success: literal(true) }), {
65959
- kind: "mutation",
65960
- auth: "admin",
65961
- access: "delete"
65962
- }), method(object({ token: string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }), method(object({ userId: string() }), array(ScopedTokenSummarySchema), { auth: "admin" }), method(object({ userId: string() }), TotpSetupResultSchema, {
66315
+ }), method(object({ userId: string() }), TotpSetupResultSchema, {
65963
66316
  kind: "mutation",
65964
66317
  auth: "admin",
65965
66318
  access: "create"
@@ -68235,6 +68588,15 @@ var BaseDevice = class {
68235
68588
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
68236
68589
  * with a typed cast.
68237
68590
  *
68591
+ * Answer what you KNOW. A plain array is read as the complete list only
68592
+ * while this device is `online` and probed; return
68593
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
68594
+ * now (no credentials, parent not connected, a failed or partial read) —
68595
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
68596
+ * to say "connected, and this is the complete list" explicitly. A shrink is
68597
+ * deleted only after a second agreeing complete read on a later probe (D49;
68598
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
68599
+ *
68238
68600
  * Default: no children.
68239
68601
  */
68240
68602
  getAccessoryChildren() {
@@ -72064,7 +72426,7 @@ Object.freeze({
72064
72426
  capName: "llm",
72065
72427
  capScope: "system",
72066
72428
  addonId: null,
72067
- access: "view"
72429
+ access: "create"
72068
72430
  },
72069
72431
  "llm.listNodeModels": {
72070
72432
  capName: "llm",
@@ -72366,7 +72728,19 @@ Object.freeze({
72366
72728
  addonId: null,
72367
72729
  access: "view"
72368
72730
  },
72369
- "logDestination.query": {
72731
+ "logDestination.cancelRead": {
72732
+ capName: "log-destination",
72733
+ capScope: "system",
72734
+ addonId: null,
72735
+ access: "create"
72736
+ },
72737
+ "logDestination.describeRead": {
72738
+ capName: "log-destination",
72739
+ capScope: "system",
72740
+ addonId: null,
72741
+ access: "view"
72742
+ },
72743
+ "logDestination.read": {
72370
72744
  capName: "log-destination",
72371
72745
  capScope: "system",
72372
72746
  addonId: null,
@@ -76728,12 +77102,6 @@ Object.freeze({
76728
77102
  addonId: null,
76729
77103
  access: "create"
76730
77104
  },
76731
- "userManagement.createScopedToken": {
76732
- capName: "user-management",
76733
- capScope: "system",
76734
- addonId: null,
76735
- access: "create"
76736
- },
76737
77105
  "userManagement.createUser": {
76738
77106
  capName: "user-management",
76739
77107
  capScope: "system",
@@ -76782,12 +77150,6 @@ Object.freeze({
76782
77150
  addonId: null,
76783
77151
  access: "view"
76784
77152
  },
76785
- "userManagement.listScopedTokens": {
76786
- capName: "user-management",
76787
- capScope: "system",
76788
- addonId: null,
76789
- access: "view"
76790
- },
76791
77153
  "userManagement.listUsers": {
76792
77154
  capName: "user-management",
76793
77155
  capScope: "system",
@@ -76842,12 +77204,6 @@ Object.freeze({
76842
77204
  addonId: null,
76843
77205
  access: "delete"
76844
77206
  },
76845
- "userManagement.revokeScopedToken": {
76846
- capName: "user-management",
76847
- capScope: "system",
76848
- addonId: null,
76849
- access: "delete"
76850
- },
76851
77207
  "userManagement.setupTotp": {
76852
77208
  capName: "user-management",
76853
77209
  capScope: "system",
@@ -76878,12 +77234,6 @@ Object.freeze({
76878
77234
  addonId: null,
76879
77235
  access: "view"
76880
77236
  },
76881
- "userManagement.validateScopedToken": {
76882
- capName: "user-management",
76883
- capScope: "system",
76884
- addonId: null,
76885
- access: "view"
76886
- },
76887
77237
  "userManagement.verifyTotp": {
76888
77238
  capName: "user-management",
76889
77239
  capScope: "system",
@@ -78549,6 +78899,11 @@ Object.freeze({
78549
78899
  form: "single",
78550
78900
  optional: false
78551
78901
  }],
78902
+ "logDestination.read": [{
78903
+ name: "deviceId",
78904
+ form: "single",
78905
+ optional: true
78906
+ }],
78552
78907
  "mediaPlayer.getStatus": [{
78553
78908
  name: "deviceId",
78554
78909
  form: "single",