@camstack/addon-provider-unifi 0.2.130 → 0.2.132

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
@@ -5414,7 +5414,7 @@ var ZodIssueCode = {
5414
5414
  var ZodFirstPartyTypeKind;
5415
5415
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5416
5416
  //#endregion
5417
- //#region ../types/dist/sleep-BxjU_fJM.mjs
5417
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
5418
5418
  /**
5419
5419
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5420
5420
  * window to float samples (D455).
@@ -7797,9 +7797,9 @@ function normalizeAddonInitResult(result) {
7797
7797
  return result;
7798
7798
  }
7799
7799
  /**
7800
- * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7801
- * and validates them (`share-token.service.ts` builds its enum from this
7802
- * list); a data plane names the kinds it ACCEPTS in `share`.
7800
+ * The share-view scope kinds a share-link token can carry. The hub mints
7801
+ * and validates them (`ShareViewGrantSchema` builds its
7802
+ * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
7803
7803
  */
7804
7804
  var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7805
7805
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
@@ -12503,7 +12503,7 @@ var ConvertResultSchema = object({
12503
12503
  * `super_admin` — collapsed onto the single boolean because every
12504
12504
  * non-admin caller is governed by the same scope-check rules; the
12505
12505
  * distinction was only ever used to route role-specific procedures
12506
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12506
+ * which we no longer have. CLI / webhook integrations are tokens (`auth.mintToken`)
12507
12507
  * with `isAdmin: false` + an explicit scope list.
12508
12508
  */
12509
12509
  /** Per-method access flavour. Materialised on every cap method via codegen. */
@@ -12692,10 +12692,12 @@ var AddonRoutesScopeSchema = object({
12692
12692
  type: literal("addon-routes"),
12693
12693
  access: array(MethodAccessSchema).min(1)
12694
12694
  });
12695
+ var PreferencesSelfScopeSchema = object({ type: literal("preferences-self") });
12695
12696
  var CredentialScopeSchema = union([
12696
12697
  literal("*"),
12697
12698
  ShareViewScopeSchema,
12698
12699
  AddonRoutesScopeSchema,
12700
+ PreferencesSelfScopeSchema,
12699
12701
  TokenScopeSchema
12700
12702
  ]);
12701
12703
  object({
@@ -12704,6 +12706,55 @@ object({
12704
12706
  jti: string().min(16),
12705
12707
  scopes: array(CredentialScopeSchema).min(1)
12706
12708
  });
12709
+ var PreferenceNamespaceSchema = string().regex(/^[a-z][a-z0-9.-]{0,63}$/);
12710
+ /** A namespace's value: a JSON object, opaque to the hub. */
12711
+ var PreferenceValueSchema = record(string(), unknown());
12712
+ var PreferenceDeviceIdSchema = string().min(1).max(64);
12713
+ /** A stored row, as the owner reads it. */
12714
+ var PreferenceRowSchema = object({
12715
+ namespace: PreferenceNamespaceSchema,
12716
+ value: PreferenceValueSchema,
12717
+ /** Starts at 1, +1 on every write of this namespace. A delete ends the row and its count. */
12718
+ revision: number().int().positive(),
12719
+ updatedAt: number().int(),
12720
+ /** The client id the last writer sent; `null` when it sent none. */
12721
+ updatedByDevice: PreferenceDeviceIdSchema.nullable()
12722
+ });
12723
+ object({
12724
+ /** Absent: every namespace the caller holds. */
12725
+ namespaces: array(PreferenceNamespaceSchema).max(32).optional() });
12726
+ object({ rows: array(PreferenceRowSchema) });
12727
+ object({
12728
+ namespace: PreferenceNamespaceSchema,
12729
+ value: PreferenceValueSchema,
12730
+ /**
12731
+ * The revision the edit was based on. Absent: last write wins. `0`: the
12732
+ * namespace must not exist yet. Any other value that is not the current
12733
+ * revision answers `conflict` and writes nothing.
12734
+ */
12735
+ baseRevision: number().int().nonnegative().optional(),
12736
+ deviceId: PreferenceDeviceIdSchema.optional()
12737
+ });
12738
+ discriminatedUnion("status", [object({
12739
+ status: literal("saved"),
12740
+ row: PreferenceRowSchema
12741
+ }), object({
12742
+ status: literal("conflict"),
12743
+ current: PreferenceRowSchema.nullable()
12744
+ })]);
12745
+ object({ namespace: PreferenceNamespaceSchema });
12746
+ object({
12747
+ /** `false` when the namespace did not exist. */
12748
+ deleted: boolean() });
12749
+ object({
12750
+ /** The revision the client holds per namespace; a namespace it does not list is new to it. */
12751
+ revisionByNamespace: record(PreferenceNamespaceSchema, number().int().nonnegative()).refine((map) => Object.keys(map).length <= 32, { message: `at most 32 namespaces` }) });
12752
+ object({
12753
+ /** Every row whose revision differs from the client's, and every row it did not list. */
12754
+ rows: array(PreferenceRowSchema),
12755
+ /** Namespaces the client listed that no longer exist. */
12756
+ deleted: array(PreferenceNamespaceSchema)
12757
+ });
12707
12758
  _enum(["new-session", "step-up"]);
12708
12759
  /** The languages the hub's app landing pages are written in (D858). */
12709
12760
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -16957,7 +17008,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
16957
17008
  kind: literal("node"),
16958
17009
  nodeId: string().min(1)
16959
17010
  })]);
17011
+ /**
17012
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17013
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17014
+ * meaning); a rollup keeps the time spent in each state (`states`).
17015
+ */
16960
17016
  var DeviceHistoryKindSchema = _enum([
17017
+ "gauge",
17018
+ "counter",
17019
+ "boolean",
17020
+ "enum"
17021
+ ]);
17022
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17023
+ var DeviceHistoryProducerKindSchema = _enum([
16961
17024
  "gauge",
16962
17025
  "counter",
16963
17026
  "boolean"
@@ -16994,7 +17057,13 @@ var SeriesInfoSchema = object({
16994
17057
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
16995
17058
  unit: string().nullable(),
16996
17059
  displayName: string(),
16997
- source: _enum(["cap", "addon"]),
17060
+ source: _enum([
17061
+ "cap",
17062
+ "addon",
17063
+ "derived"
17064
+ ]),
17065
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17066
+ values: array(string()).readonly().nullable(),
16998
17067
  firstTs: number(),
16999
17068
  lastTs: number()
17000
17069
  });
@@ -17008,17 +17077,31 @@ var QueryPointSchema = object({
17008
17077
  twMean: number().nullable(),
17009
17078
  min: number(),
17010
17079
  max: number(),
17011
- /** `null` is unknown, never zero (D393). */
17012
- last: number().nullable()
17080
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17081
+ last: number().nullable(),
17082
+ /**
17083
+ * The increase over the point: a `counter`'s growth since the previous point
17084
+ * or bucket (a drop is a reset, counted from zero), and for
17085
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17086
+ * every other kind, and when it cannot be known.
17087
+ */
17088
+ delta: number().nullable(),
17089
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17090
+ state: string().nullable(),
17091
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17092
+ states: record(string(), number()).nullable()
17013
17093
  });
17014
17094
  var QuerySeriesSchema = object({
17015
17095
  scope: string(),
17016
17096
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17017
17097
  before: object({
17018
17098
  t: number(),
17019
- value: number().nullable()
17099
+ value: number().nullable(),
17100
+ state: string().nullable()
17020
17101
  }).nullable(),
17021
- points: array(QueryPointSchema).readonly()
17102
+ points: array(QueryPointSchema).readonly(),
17103
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17104
+ derivedFrom: string().nullable()
17022
17105
  });
17023
17106
  /** The window part of a query, shared by the device and node forms. */
17024
17107
  var QueryWindowShape = {
@@ -17034,6 +17117,23 @@ var QueryResultSchema = object({
17034
17117
  series: array(QuerySeriesSchema).readonly(),
17035
17118
  truncated: boolean()
17036
17119
  });
17120
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17121
+ var QueryManyItemSchema = union([object({
17122
+ deviceId: number().int(),
17123
+ key: string(),
17124
+ scope: string().optional()
17125
+ }), object({
17126
+ forNodeId: string().min(1),
17127
+ key: string(),
17128
+ scope: string().optional()
17129
+ })]);
17130
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
17131
+ ok: literal(true),
17132
+ result: QueryResultSchema
17133
+ }), object({
17134
+ ok: literal(false),
17135
+ error: string()
17136
+ })]);
17037
17137
  var TierStatusSchema = object({
17038
17138
  tier: DeviceHistoryResolutionSchema,
17039
17139
  /** `null` until the first background count answered. */
@@ -17089,16 +17189,22 @@ var DeviceHistoryStatusSchema = object({
17089
17189
  lastRefreshAt: number().nullable()
17090
17190
  })
17091
17191
  });
17092
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17192
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17093
17193
  deviceId: number().int(),
17094
17194
  ...QueryWindowShape
17095
17195
  }), QueryResultSchema), method(object({
17096
- nodeId: string().min(1),
17196
+ forNodeId: string().min(1),
17097
17197
  ...QueryWindowShape
17098
17198
  }), QueryResultSchema, { auth: "admin" }), method(object({
17199
+ items: array(QueryManyItemSchema).min(1).max(24),
17200
+ from: QueryWindowShape.from,
17201
+ to: QueryWindowShape.to,
17202
+ resolution: QueryWindowShape.resolution,
17203
+ maxPoints: QueryWindowShape.maxPoints
17204
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
17099
17205
  name: string().regex(/^[a-z0-9-]+$/),
17100
17206
  subjectKind: _enum(["device", "node"]),
17101
- kind: DeviceHistoryKindSchema,
17207
+ kind: DeviceHistoryProducerKindSchema,
17102
17208
  unit: string().optional(),
17103
17209
  displayName: string().min(1),
17104
17210
  ingest: _enum(["points", "buckets"])
@@ -39993,38 +40099,37 @@ method(LlmRuntimeCompleteInputSchema, LlmGenerateResultSchema, {
39993
40099
  auth: "admin",
39994
40100
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
39995
40101
  });
40102
+ var LlmProfileKindSchema = string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "a kind id is lower-case letters, digits and dashes");
40103
+ /** What a model (or, by default, every model of a kind) can do. */
40104
+ var LlmModelFeaturesSchema = object({
40105
+ vision: boolean(),
40106
+ tools: boolean(),
40107
+ streaming: boolean()
40108
+ });
40109
+ /** One model a provider offers. `features` overrides the kind's defaults, per field. */
40110
+ var LlmModelInfoSchema = object({
40111
+ id: string(),
40112
+ label: string().optional(),
40113
+ contextLength: number().int().positive().optional(),
40114
+ features: LlmModelFeaturesSchema.partial().optional()
40115
+ });
39996
40116
  /**
39997
- * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
39998
- * methods concat-fan across providers; single-row methods route to ONE
39999
- * provider by the `addonId` in the call input (the notification-output
40000
- * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
40001
- * (hub-placed); the cap stays open for future providers.
40002
- *
40003
- * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
40004
- * `apiKey` is a password field — providers REDACT it on read and merge on
40005
- * write; a stored key NEVER round-trips to a client.
40117
+ * The provider-specific part of a profile, validated by the provider that owns
40118
+ * the kind (`upsertProfile` refuses what it does not accept). A field its
40119
+ * `connectionSchema` declares `type: 'password'` is a secret: it is held in the
40120
+ * keychain, never in the row, and reads back as the redaction marker.
40006
40121
  */
40007
- var LlmProfileKindSchema = _enum([
40008
- "openai-compatible",
40009
- "openai",
40010
- "anthropic",
40011
- "google",
40012
- "managed-local",
40013
- "apple-foundation"
40014
- ]);
40122
+ var LlmProviderConfigSchema = record(string(), unknown());
40015
40123
  var LlmProfileSchema = object({
40016
40124
  id: string(),
40017
40125
  name: string(),
40126
+ /** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
40018
40127
  kind: LlmProfileKindSchema,
40019
40128
  /** Stamped by the provider — keeps the fanned catalog routable. */
40020
40129
  addonId: string(),
40021
40130
  enabled: boolean(),
40022
40131
  /** Vendor model id, or the managed runtime's loaded model. */
40023
40132
  model: string(),
40024
- /** Required for openai-compatible; override for cloud kinds. */
40025
- baseUrl: string().optional(),
40026
- /** ConfigUISchema type:'password' — never round-trips (spec §5). */
40027
- apiKey: string().optional(),
40028
40133
  /** Vision on/off. A vision call against a `false` profile is REFUSED, never
40029
40134
  * degraded to text — that shipped once and produced a confident answer to a
40030
40135
  * question about a picture nobody sent. */
@@ -40032,15 +40137,11 @@ var LlmProfileSchema = object({
40032
40137
  temperature: number().min(0).max(2).optional(),
40033
40138
  /** Nucleus sampling. Every wire we speak has it. */
40034
40139
  topP: number().min(0).max(1).optional(),
40035
- /** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
40036
- * wire does, and the client drops it there (measured: the request body gets
40037
- * `top_p` and no `top_k`). The profile editor hides the field wherever it
40038
- * would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
40140
+ /** Top-k sampling. Carried only by the wires that have it — a kind offers the
40141
+ * field in its editor only when its descriptor lists it in `profileFields`. */
40039
40142
  topK: number().int().positive().optional(),
40040
40143
  maxTokens: number().int().positive().optional(),
40041
- /** Prompt context window. Advisory for cloud kinds (they enforce their own);
40042
- * for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
40043
- * the model with, so it is the one field that changes a PROCESS. */
40144
+ /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
40044
40145
  contextLength: number().int().positive().optional(),
40045
40146
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
40046
40147
  * two system prompts fighting is worse than either alone). */
@@ -40066,16 +40167,37 @@ var LlmProfileSchema = object({
40066
40167
  * library; the REGISTRY of callable tools is ours and is empty in v1, so a
40067
40168
  * `true` here buys the wiring, not behaviour, until tools are registered. */
40068
40169
  toolsEnabled: boolean().default(false),
40069
- extraHeaders: record(string(), string()).optional(),
40070
- /** kind === 'managed-local' only (spec §4). */
40071
- runtime: ManagedRuntimeConfigSchema.optional(),
40072
- /**
40073
- * kind === 'apple-foundation' only: WHERE it runs — the only thing there is
40074
- * to configure (no key, no URL, no download; `model` is `apple-system`).
40075
- * `supportsVision` on such a row is stamped by the provider from the node's
40076
- * reported `imageInput`, never taken from the operator (D62).
40077
- */
40078
- appleFoundation: object({ nodeId: string() }).optional()
40170
+ /** Everything the kind's provider owns (endpoint, key, node, runtime…). */
40171
+ providerConfig: LlmProviderConfigSchema.default({})
40172
+ });
40173
+ /**
40174
+ * The common profile fields a kind's editor offers. The editor owns how each
40175
+ * one is drawn; the provider says which of them mean something on its wire.
40176
+ */
40177
+ var LlmProfileFieldSchema = _enum([
40178
+ "temperature",
40179
+ "topP",
40180
+ "topK",
40181
+ "maxTokens",
40182
+ "contextLength",
40183
+ "systemPrompt",
40184
+ "timeoutMs",
40185
+ "connectTimeoutMs",
40186
+ "firstTokenTimeoutMs",
40187
+ "idleTimeoutMs",
40188
+ "retry",
40189
+ "toolsEnabled"
40190
+ ]);
40191
+ /**
40192
+ * A provider-drawn part of the editor, by a generic widget id the admin UI
40193
+ * registers (`ai/apple-node`). `placement: 'model'` replaces the generic model
40194
+ * picker: that widget owns the model choice.
40195
+ */
40196
+ var LlmProviderWidgetSchema = object({
40197
+ id: string(),
40198
+ placement: _enum(["connection", "model"]),
40199
+ /** `providerConfig` keys this widget must fill before the profile can be saved. */
40200
+ requires: array(string()).optional()
40079
40201
  });
40080
40202
  /** ConfigUISchema tree passed through untyped on the wire (the
40081
40203
  * notification-output `ConfigSchemaPassthrough` precedent at
@@ -40084,11 +40206,56 @@ var ConfigSchemaPassthrough$3 = unknown();
40084
40206
  var LlmProfileKindDescriptorSchema = object({
40085
40207
  kind: LlmProfileKindSchema,
40086
40208
  label: string(),
40209
+ /** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
40087
40210
  icon: string(),
40088
40211
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
40089
40212
  addonId: string(),
40090
- configSchema: ConfigSchemaPassthrough$3
40213
+ /** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
40214
+ connectionSchema: ConfigSchemaPassthrough$3,
40215
+ /** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
40216
+ advancedSchema: ConfigSchemaPassthrough$3.optional(),
40217
+ /** The kind's defaults; a model from `listModels` may override any of them. */
40218
+ features: LlmModelFeaturesSchema,
40219
+ /** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
40220
+ visionEditable: boolean(),
40221
+ /** Where the model list comes from: `listModels`, `staticModels`, or nowhere. */
40222
+ modelCatalog: _enum([
40223
+ "fetch",
40224
+ "static",
40225
+ "none"
40226
+ ]),
40227
+ staticModels: array(LlmModelInfoSchema).optional(),
40228
+ /** The common fields that mean something on this kind's wire. */
40229
+ profileFields: array(LlmProfileFieldSchema),
40230
+ providerWidgets: array(LlmProviderWidgetSchema).optional()
40091
40231
  });
40232
+ /**
40233
+ * `listModels` input. `connection` is an UNSAVED draft of `providerConfig`
40234
+ * (the editor's form); with `profileId` too, a secret the draft leaves
40235
+ * untouched (absent or the redaction marker) is resolved server-side from the
40236
+ * stored profile — the browser never receives it.
40237
+ */
40238
+ var LlmListModelsInputSchema = object({
40239
+ addonId: string(),
40240
+ kind: LlmProfileKindSchema,
40241
+ profileId: string().optional(),
40242
+ connection: LlmProviderConfigSchema.optional()
40243
+ });
40244
+ var LlmListModelsErrorCodeSchema = _enum([
40245
+ "auth",
40246
+ "network",
40247
+ "unsupported",
40248
+ "invalid"
40249
+ ]);
40250
+ /** A RESULT, never a throw: "wrong key" is an answer the editor renders inline. */
40251
+ var LlmListModelsResultSchema = discriminatedUnion("ok", [object({
40252
+ ok: literal(true),
40253
+ models: array(LlmModelInfoSchema)
40254
+ }), object({
40255
+ ok: literal(false),
40256
+ code: LlmListModelsErrorCodeSchema,
40257
+ message: string()
40258
+ })]);
40092
40259
  var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
40093
40260
  var LlmDefaultSchema = object({
40094
40261
  selector: LlmDefaultSelectorSchema,
@@ -40188,7 +40355,10 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
40188
40355
  kind: "mutation",
40189
40356
  auth: "admin",
40190
40357
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
40191
- }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
40358
+ }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
40359
+ kind: "mutation",
40360
+ auth: "admin"
40361
+ }), method(object({}), array(LlmDefaultSchema)), method(object({
40192
40362
  selector: LlmDefaultSelectorSchema,
40193
40363
  profileId: string().nullable()
40194
40364
  }), _void(), {
@@ -40356,14 +40526,106 @@ var LogEntrySchema = object({
40356
40526
  meta: record(string(), unknown()).optional(),
40357
40527
  tags: record(string(), string()).optional()
40358
40528
  });
40359
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
40360
- scope: array(string()).optional(),
40529
+ /**
40530
+ * A history READ against one destination (D898).
40531
+ *
40532
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
40533
+ * browser applied after the limit is what made a rare device's lines
40534
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
40535
+ * minted (opaque to everyone else): a file position for the rotated files, a
40536
+ * nanosecond timestamp for Loki.
40537
+ *
40538
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
40539
+ * store answers `done: false` with the cursor it reached and the bytes it
40540
+ * scanned, and the caller decides whether to go on. That is what makes a long
40541
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
40542
+ * flight, and not asking for the next slice ends the scan.
40543
+ */
40544
+ var LogReadQuerySchema = object({
40545
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
40546
+ requestId: string().min(1).max(64).optional(),
40547
+ /** The device the line is about (`tags.deviceId`, numeric). */
40548
+ deviceId: number().int().optional(),
40549
+ /**
40550
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
40551
+ * match. Not `addonId`: a cap router reads that name as "which provider".
40552
+ */
40553
+ fromAddonId: string().min(1).max(200).optional(),
40554
+ /**
40555
+ * The emitting node: matches the agent that emitted the line, the node
40556
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
40557
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
40558
+ * name as "which node's provider".
40559
+ */
40560
+ fromNodeId: string().min(1).max(200).optional(),
40561
+ /** Any other tag, exact match (AND). */
40562
+ tags: record(string(), union([string(), number()])).optional(),
40563
+ /** Severity FLOOR: this level and above. */
40361
40564
  level: LogLevelSchema.optional(),
40362
- since: date().optional(),
40363
- until: date().optional(),
40364
- limit: number().optional(),
40365
- tags: record(string(), string()).optional()
40366
- }), array(LogEntrySchema).readonly());
40565
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
40566
+ text: string().min(1).max(200).optional(),
40567
+ /** Epoch ms, inclusive. */
40568
+ since: number().optional(),
40569
+ /** Epoch ms, inclusive. */
40570
+ until: number().optional(),
40571
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
40572
+ before: string().min(1).max(1024).optional(),
40573
+ /** Newer than this cursor (exclusive). */
40574
+ after: string().min(1).max(1024).optional(),
40575
+ limit: number().int().min(1).max(1e3).optional(),
40576
+ /** Wall-clock bound of this slice. The provider caps it. */
40577
+ budgetMs: number().int().min(50).max(1e4).optional()
40578
+ });
40579
+ var LogReadResultSchema = object({
40580
+ /** Newest first. */
40581
+ entries: array(object({
40582
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
40583
+ id: string().optional(),
40584
+ /** Epoch ms. */
40585
+ timestamp: number(),
40586
+ level: LogLevelSchema,
40587
+ scope: string().optional(),
40588
+ message: string(),
40589
+ tags: record(string(), union([string(), number()])).optional(),
40590
+ meta: record(string(), unknown()).optional()
40591
+ })),
40592
+ /** Pass as `before` for the next older page; null when nothing older exists. */
40593
+ nextBefore: string().nullable(),
40594
+ /** Pass as `after` to read what arrived since; null when unknown. */
40595
+ nextAfter: string().nullable(),
40596
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
40597
+ scannedBytes: number().int().nonnegative(),
40598
+ /**
40599
+ * True when the scan in this direction reached the end of the store.
40600
+ * False with fewer than `limit` entries means the budget ran out first —
40601
+ * call again with `nextBefore` to go on.
40602
+ */
40603
+ done: boolean(),
40604
+ /** True when `cancelRead` ended this slice early. */
40605
+ cancelled: boolean().optional()
40606
+ });
40607
+ var LogReadCapabilitiesSchema = object({
40608
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
40609
+ readable: boolean(),
40610
+ /** Why not, when `readable` is false — rendered next to the source. */
40611
+ reason: string().nullable(),
40612
+ /** Filters the provider applies itself. A false one is applied by nobody. */
40613
+ filters: object({
40614
+ deviceId: boolean(),
40615
+ addonId: boolean(),
40616
+ nodeId: boolean(),
40617
+ tags: boolean(),
40618
+ level: boolean(),
40619
+ text: boolean(),
40620
+ timeRange: boolean()
40621
+ }),
40622
+ /** How far back the store reaches, when the provider knows (days). */
40623
+ retentionDays: number().nullable()
40624
+ });
40625
+ 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() }), {
40626
+ kind: "mutation",
40627
+ auth: "admin"
40628
+ });
40367
40629
  /**
40368
40630
  * `login-method` — collection cap through which auth addons contribute
40369
40631
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -42081,9 +42343,11 @@ var alarmPanelCapability = {
42081
42343
  */
42082
42344
  durability: "restored",
42083
42345
  /**
42084
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
42346
+ * History (D850): the panel's lifecycle state as an `enum` series —
42347
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
42348
+ * few seconds keeps every step. Who armed it stays in the events ledger.
42085
42349
  */
42086
- history: "none",
42350
+ history: { fields: { state: { kind: "enum" } } },
42087
42351
  /** Clock fields: written, but excluded from the compare that decides
42088
42352
  * whether persisting is worth a SQLite commit. */
42089
42353
  volatileStateFields: ["lastChangedAt"]
@@ -42961,6 +43225,33 @@ var NcRuleTargetSchema = object({
42961
43225
  params: record(string(), unknown()).optional()
42962
43226
  });
42963
43227
  /**
43228
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
43229
+ *
43230
+ * Every mode starts from the same CLEAN source frame of the trigger moment
43231
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
43232
+ * to the zone that fired the rule) and renders it once at send time:
43233
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
43234
+ * colour and every OTHER track visible at that instant outlined thin, each
43235
+ * labelled with class and confidence ("dog 87%").
43236
+ * - `crop` — the subject cut out of that frame around its box at that instant.
43237
+ * - `clean` — the whole scene with nothing drawn on it.
43238
+ * - `none` — no picture.
43239
+ *
43240
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
43241
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
43242
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
43243
+ * ship a crop on one event and a boxed scene on the next depending on which
43244
+ * stored kind had landed.
43245
+ */
43246
+ var NcMediaImageSchema = _enum([
43247
+ "scene-boxes",
43248
+ "crop",
43249
+ "clean",
43250
+ "none"
43251
+ ]);
43252
+ /**
43253
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43254
+ *
42964
43255
  * Media attachment policy (P1 still-image subset).
42965
43256
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
42966
43257
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -42974,6 +43265,8 @@ var NcRuleTargetSchema = object({
42974
43265
  * - `none` — no attachment.
42975
43266
  */
42976
43267
  /**
43268
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43269
+ *
42977
43270
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
42978
43271
  * conflate it with the selection strategy and betray the request: asking for
42979
43272
  * the clean scene frame on an object-event owner used to start at
@@ -43002,16 +43295,29 @@ var NcMediaFrameSchema = _enum([
43002
43295
  */
43003
43296
  var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
43004
43297
  var NcMediaPolicySchema = object({
43298
+ /**
43299
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
43300
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
43301
+ * triple below, at load and at every write, and the store keeps only this.
43302
+ */
43303
+ image: NcMediaImageSchema.optional(),
43304
+ /**
43305
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
43306
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
43307
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
43308
+ * Replaces `zoneCrop`.
43309
+ */
43310
+ showTriggerZone: boolean().optional(),
43311
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43005
43312
  attach: _enum([
43006
43313
  "best",
43007
43314
  "best-matching",
43008
43315
  "keyFrame",
43009
43316
  "none"
43010
- ]).default("best"),
43011
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
43317
+ ]).optional(),
43318
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
43012
43319
  frame: NcMediaFrameSchema.optional(),
43013
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
43014
- * "show me the ZONE", not the whole scene or the subject crop. */
43320
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
43015
43321
  zoneCrop: boolean().optional(),
43016
43322
  /**
43017
43323
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -43183,7 +43489,9 @@ var NcRuleInputSchema = object({
43183
43489
  * targets.
43184
43490
  */
43185
43491
  targetUsers: array(string()).optional(),
43186
- media: NcMediaPolicySchema.default({ attach: "best" }),
43492
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
43493
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
43494
+ media: NcMediaPolicySchema.default({}),
43187
43495
  throttle: NcThrottleSchema.default({
43188
43496
  cooldownSec: 60,
43189
43497
  scope: "rule-device"
@@ -44120,13 +44428,37 @@ var NcAlarmModeOpeningsSchema = object({
44120
44428
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
44121
44429
  unknown: array(number().int())
44122
44430
  });
44431
+ /**
44432
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
44433
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
44434
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
44435
+ * never looks fully armed (D62: off must never look like broken).
44436
+ */
44437
+ var NcAlarmInputBypassViewSchema = object({
44438
+ ruleId: string(),
44439
+ /** The rule's current name (its frozen name when the rule is gone). */
44440
+ ruleName: string(),
44441
+ /** The input: the sensor of the match, else its camera. */
44442
+ deviceId: number().int(),
44443
+ /** The input's current name. */
44444
+ name: string(),
44445
+ /** When it was bypassed (ms epoch). */
44446
+ since: number(),
44447
+ /** Triggers from this input dropped since. */
44448
+ dropped: number().int().min(0)
44449
+ });
44123
44450
  var NcAlarmLiveSchema = object({
44124
44451
  state: AlarmStateSchema,
44125
44452
  /** The mode being armed into (exit delay) or held; null when disarmed. */
44126
44453
  targetMode: AlarmArmModeSchema.nullable(),
44127
44454
  availableModes: array(AlarmArmModeSchema),
44128
44455
  openings: array(NcAlarmModeOpeningsSchema),
44129
- exclusions: array(NcAlarmExclusionViewSchema)
44456
+ exclusions: array(NcAlarmExclusionViewSchema),
44457
+ /**
44458
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
44459
+ * Defaulted so an older hub answer still parses (as "none known").
44460
+ */
44461
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
44130
44462
  });
44131
44463
  var NcAlarmConfigSchema = object({
44132
44464
  /**
@@ -54862,9 +55194,11 @@ var connectivityCapability = {
54862
55194
  */
54863
55195
  durability: "restored",
54864
55196
  /**
54865
- * History (D850): none — duplicates device-status.online (one authority for availability).
55197
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55198
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55199
+ * device's reachability, which stays `device-status.online`.
54866
55200
  */
54867
- history: "none",
55201
+ history: { fields: { connected: { kind: "boolean" } } },
54868
55202
  /** Clock fields: written, but excluded from the compare that decides
54869
55203
  * whether persisting is worth a SQLite commit. */
54870
55204
  volatileStateFields: ["lastChangedAt"]
@@ -55688,11 +56022,22 @@ var dishwasherCapability = {
55688
56022
  },
55689
56023
  runtimeState: DishwasherStatusSchema,
55690
56024
  durability: "session",
55691
- history: { fields: { progressPercent: {
55692
- kind: "gauge",
55693
- unit: "%",
55694
- deadband: 2
55695
- } } }
56025
+ history: { fields: {
56026
+ progressPercent: {
56027
+ kind: "gauge",
56028
+ unit: "%",
56029
+ deadband: 2
56030
+ },
56031
+ state: { kind: "enum" },
56032
+ operationState: { kind: "enum" },
56033
+ remainingSeconds: {
56034
+ kind: "gauge",
56035
+ unit: "s",
56036
+ minIntervalMs: 6e4
56037
+ },
56038
+ doorOpen: { kind: "boolean" },
56039
+ powerOn: { kind: "boolean" }
56040
+ } }
55696
56041
  };
55697
56042
  var DoorbellStatusSchema = object({
55698
56043
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -55809,9 +56154,15 @@ var enumSensorCapability = {
55809
56154
  */
55810
56155
  durability: "restored",
55811
56156
  /**
55812
- * History (D850): none — text/enum state has no history (non-goal).
56157
+ * History (D850): the value as an `enum` series (an appliance's program or
56158
+ * operation state, an HVAC action). The option set is per device, so the
56159
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56160
+ * `format` carries a timestamp, not a state, and is not recorded.
55813
56161
  */
55814
- history: "none",
56162
+ history: { fields: { value: {
56163
+ kind: "enum",
56164
+ skipWhenSet: "format"
56165
+ } } },
55815
56166
  /** Clock fields: written, but excluded from the compare that decides
55816
56167
  * whether persisting is worth a SQLite commit. */
55817
56168
  volatileStateFields: ["lastFetchedAt"]
@@ -57785,9 +58136,10 @@ var lockControlCapability = {
57785
58136
  */
57786
58137
  durability: "restored",
57787
58138
  /**
57788
- * History (D850): none — enum state; lock events belong in the events ledger.
58139
+ * History (D850): the lock's state as an `enum` series — change-only, no
58140
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
57789
58141
  */
57790
- history: "none",
58142
+ history: { fields: { state: { kind: "enum" } } },
57791
58143
  /** Clock fields: written, but excluded from the compare that decides
57792
58144
  * whether persisting is worth a SQLite commit. */
57793
58145
  volatileStateFields: ["lastChangedAt"]
@@ -57961,9 +58313,18 @@ var mediaPlayerCapability = {
57961
58313
  */
57962
58314
  durability: "session",
57963
58315
  /**
57964
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
58316
+ * History (D850): volume (a level an operator or an automation sets; the
58317
+ * default 10 s floor folds a slider drag into its end value) and mute.
58318
+ * `positionMs` is not recorded: it moves continuously while playing.
57965
58319
  */
57966
- history: "none"
58320
+ history: { fields: {
58321
+ volumeLevel: {
58322
+ kind: "gauge",
58323
+ unit: "%",
58324
+ deadband: 1
58325
+ },
58326
+ isMuted: { kind: "boolean" }
58327
+ } }
57967
58328
  };
57968
58329
  /**
57969
58330
  * mesh-network — collection cap for mesh-VPN providers.
@@ -63256,9 +63617,29 @@ var streamParamsCapability = {
63256
63617
  */
63257
63618
  durability: "restored",
63258
63619
  /**
63259
- * History (D850): none — encoder configuration.
63620
+ * History (D850): the configured bitrate and frame rate of the main and sub
63621
+ * profiles. Configuration, so change-only on the default floor: a point is an
63622
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
63623
+ * quality over time must show.
63260
63624
  */
63261
- history: "none",
63625
+ history: { fields: {
63626
+ "main.bitrate": {
63627
+ kind: "gauge",
63628
+ unit: "kbps"
63629
+ },
63630
+ "main.framerate": {
63631
+ kind: "gauge",
63632
+ unit: "fps"
63633
+ },
63634
+ "sub.bitrate": {
63635
+ kind: "gauge",
63636
+ unit: "kbps"
63637
+ },
63638
+ "sub.framerate": {
63639
+ kind: "gauge",
63640
+ unit: "fps"
63641
+ }
63642
+ } },
63262
63643
  /** Clock fields: written, but excluded from the compare that decides
63263
63644
  * whether persisting is worth a SQLite commit. */
63264
63645
  volatileStateFields: ["lastFetchedAt"]
@@ -64093,26 +64474,6 @@ var ApiKeySummarySchema = object({
64093
64474
  createdAt: number(),
64094
64475
  lastUsedAt: number().optional()
64095
64476
  });
64096
- var ScopedTokenSummarySchema = object({
64097
- id: string(),
64098
- userId: string(),
64099
- name: string(),
64100
- tokenPrefix: string(),
64101
- scopes: array(TokenScopeSchema),
64102
- expiresAt: number().nullish(),
64103
- lastUsedAt: number().nullish(),
64104
- createdAt: number()
64105
- });
64106
- var CreateScopedTokenInputSchema = object({
64107
- userId: string(),
64108
- name: string(),
64109
- scopes: array(TokenScopeSchema),
64110
- expiresAt: number().optional()
64111
- });
64112
- var CreateScopedTokenResultSchema = object({
64113
- token: string(),
64114
- record: ScopedTokenSummarySchema
64115
- });
64116
64477
  var OauthSessionSummarySchema = object({
64117
64478
  id: string(),
64118
64479
  userId: string(),
@@ -64134,11 +64495,11 @@ var TotpStatusSchema = object({
64134
64495
  confirmedAt: number().nullable()
64135
64496
  });
64136
64497
  /**
64137
- * user-management — singleton capability for user accounts, API keys,
64138
- * and scoped tokens.
64498
+ * user-management — singleton capability for user accounts and the
64499
+ * legacy API-key rows.
64139
64500
  *
64140
64501
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64141
- * — the subset check on `setUserScopes` / `createScopedToken` is moot
64502
+ * — the subset check on `setUserScopes` is moot
64142
64503
  * because non-admins never reach these. If/when we open non-admin
64143
64504
  * delegation, structural caller-scope subset check goes inside the
64144
64505
  * provider.
@@ -64195,15 +64556,7 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64195
64556
  kind: "mutation",
64196
64557
  auth: "admin",
64197
64558
  access: "delete"
64198
- }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
64199
- kind: "mutation",
64200
- auth: "admin",
64201
- access: "create"
64202
- }), method(object({ id: string() }), object({ success: literal(true) }), {
64203
- kind: "mutation",
64204
- auth: "admin",
64205
- access: "delete"
64206
- }), method(object({ token: string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }), method(object({ userId: string() }), array(ScopedTokenSummarySchema), { auth: "admin" }), method(object({ userId: string() }), TotpSetupResultSchema, {
64559
+ }), method(object({ userId: string() }), TotpSetupResultSchema, {
64207
64560
  kind: "mutation",
64208
64561
  auth: "admin",
64209
64562
  access: "create"
@@ -66464,6 +66817,15 @@ var BaseDevice = class {
66464
66817
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
66465
66818
  * with a typed cast.
66466
66819
  *
66820
+ * Answer what you KNOW. A plain array is read as the complete list only
66821
+ * while this device is `online` and probed; return
66822
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
66823
+ * now (no credentials, parent not connected, a failed or partial read) —
66824
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
66825
+ * to say "connected, and this is the complete list" explicitly. A shrink is
66826
+ * deleted only after a second agreeing complete read on a later probe (D49;
66827
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
66828
+ *
66467
66829
  * Default: no children.
66468
66830
  */
66469
66831
  getAccessoryChildren() {
@@ -70293,7 +70655,7 @@ Object.freeze({
70293
70655
  capName: "llm",
70294
70656
  capScope: "system",
70295
70657
  addonId: null,
70296
- access: "view"
70658
+ access: "create"
70297
70659
  },
70298
70660
  "llm.listNodeModels": {
70299
70661
  capName: "llm",
@@ -70595,7 +70957,19 @@ Object.freeze({
70595
70957
  addonId: null,
70596
70958
  access: "view"
70597
70959
  },
70598
- "logDestination.query": {
70960
+ "logDestination.cancelRead": {
70961
+ capName: "log-destination",
70962
+ capScope: "system",
70963
+ addonId: null,
70964
+ access: "create"
70965
+ },
70966
+ "logDestination.describeRead": {
70967
+ capName: "log-destination",
70968
+ capScope: "system",
70969
+ addonId: null,
70970
+ access: "view"
70971
+ },
70972
+ "logDestination.read": {
70599
70973
  capName: "log-destination",
70600
70974
  capScope: "system",
70601
70975
  addonId: null,
@@ -74957,12 +75331,6 @@ Object.freeze({
74957
75331
  addonId: null,
74958
75332
  access: "create"
74959
75333
  },
74960
- "userManagement.createScopedToken": {
74961
- capName: "user-management",
74962
- capScope: "system",
74963
- addonId: null,
74964
- access: "create"
74965
- },
74966
75334
  "userManagement.createUser": {
74967
75335
  capName: "user-management",
74968
75336
  capScope: "system",
@@ -75011,12 +75379,6 @@ Object.freeze({
75011
75379
  addonId: null,
75012
75380
  access: "view"
75013
75381
  },
75014
- "userManagement.listScopedTokens": {
75015
- capName: "user-management",
75016
- capScope: "system",
75017
- addonId: null,
75018
- access: "view"
75019
- },
75020
75382
  "userManagement.listUsers": {
75021
75383
  capName: "user-management",
75022
75384
  capScope: "system",
@@ -75071,12 +75433,6 @@ Object.freeze({
75071
75433
  addonId: null,
75072
75434
  access: "delete"
75073
75435
  },
75074
- "userManagement.revokeScopedToken": {
75075
- capName: "user-management",
75076
- capScope: "system",
75077
- addonId: null,
75078
- access: "delete"
75079
- },
75080
75436
  "userManagement.setupTotp": {
75081
75437
  capName: "user-management",
75082
75438
  capScope: "system",
@@ -75107,12 +75463,6 @@ Object.freeze({
75107
75463
  addonId: null,
75108
75464
  access: "view"
75109
75465
  },
75110
- "userManagement.validateScopedToken": {
75111
- capName: "user-management",
75112
- capScope: "system",
75113
- addonId: null,
75114
- access: "view"
75115
- },
75116
75466
  "userManagement.verifyTotp": {
75117
75467
  capName: "user-management",
75118
75468
  capScope: "system",
@@ -76626,6 +76976,11 @@ Object.freeze({
76626
76976
  form: "single",
76627
76977
  optional: false
76628
76978
  }],
76979
+ "logDestination.read": [{
76980
+ name: "deviceId",
76981
+ form: "single",
76982
+ optional: true
76983
+ }],
76629
76984
  "mediaPlayer.getStatus": [{
76630
76985
  name: "deviceId",
76631
76986
  form: "single",