@camstack/addon-terminal 0.1.136 → 0.1.138

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.mjs CHANGED
@@ -5423,7 +5423,7 @@ var ZodIssueCode = {
5423
5423
  var ZodFirstPartyTypeKind;
5424
5424
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5425
5425
  //#endregion
5426
- //#region ../types/dist/sleep-BxjU_fJM.mjs
5426
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
5427
5427
  /**
5428
5428
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5429
5429
  * window to float samples (D455).
@@ -7806,9 +7806,9 @@ function normalizeAddonInitResult(result) {
7806
7806
  return result;
7807
7807
  }
7808
7808
  /**
7809
- * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7810
- * and validates them (`share-token.service.ts` builds its enum from this
7811
- * list); a data plane names the kinds it ACCEPTS in `share`.
7809
+ * The share-view scope kinds a share-link token can carry. The hub mints
7810
+ * and validates them (`ShareViewGrantSchema` builds its
7811
+ * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
7812
7812
  */
7813
7813
  var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7814
7814
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
@@ -12589,7 +12589,7 @@ var ConvertResultSchema = object({
12589
12589
  * `super_admin` — collapsed onto the single boolean because every
12590
12590
  * non-admin caller is governed by the same scope-check rules; the
12591
12591
  * distinction was only ever used to route role-specific procedures
12592
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12592
+ * which we no longer have. CLI / webhook integrations are tokens (`auth.mintToken`)
12593
12593
  * with `isAdmin: false` + an explicit scope list.
12594
12594
  */
12595
12595
  /** Per-method access flavour. Materialised on every cap method via codegen. */
@@ -12778,10 +12778,12 @@ var AddonRoutesScopeSchema = object({
12778
12778
  type: literal("addon-routes"),
12779
12779
  access: array(MethodAccessSchema).min(1)
12780
12780
  });
12781
+ var PreferencesSelfScopeSchema = object({ type: literal("preferences-self") });
12781
12782
  var CredentialScopeSchema = union([
12782
12783
  literal("*"),
12783
12784
  ShareViewScopeSchema,
12784
12785
  AddonRoutesScopeSchema,
12786
+ PreferencesSelfScopeSchema,
12785
12787
  TokenScopeSchema
12786
12788
  ]);
12787
12789
  object({
@@ -12790,6 +12792,55 @@ object({
12790
12792
  jti: string().min(16),
12791
12793
  scopes: array(CredentialScopeSchema).min(1)
12792
12794
  });
12795
+ var PreferenceNamespaceSchema = string().regex(/^[a-z][a-z0-9.-]{0,63}$/);
12796
+ /** A namespace's value: a JSON object, opaque to the hub. */
12797
+ var PreferenceValueSchema = record(string(), unknown());
12798
+ var PreferenceDeviceIdSchema = string().min(1).max(64);
12799
+ /** A stored row, as the owner reads it. */
12800
+ var PreferenceRowSchema = object({
12801
+ namespace: PreferenceNamespaceSchema,
12802
+ value: PreferenceValueSchema,
12803
+ /** Starts at 1, +1 on every write of this namespace. A delete ends the row and its count. */
12804
+ revision: number().int().positive(),
12805
+ updatedAt: number().int(),
12806
+ /** The client id the last writer sent; `null` when it sent none. */
12807
+ updatedByDevice: PreferenceDeviceIdSchema.nullable()
12808
+ });
12809
+ object({
12810
+ /** Absent: every namespace the caller holds. */
12811
+ namespaces: array(PreferenceNamespaceSchema).max(32).optional() });
12812
+ object({ rows: array(PreferenceRowSchema) });
12813
+ object({
12814
+ namespace: PreferenceNamespaceSchema,
12815
+ value: PreferenceValueSchema,
12816
+ /**
12817
+ * The revision the edit was based on. Absent: last write wins. `0`: the
12818
+ * namespace must not exist yet. Any other value that is not the current
12819
+ * revision answers `conflict` and writes nothing.
12820
+ */
12821
+ baseRevision: number().int().nonnegative().optional(),
12822
+ deviceId: PreferenceDeviceIdSchema.optional()
12823
+ });
12824
+ discriminatedUnion("status", [object({
12825
+ status: literal("saved"),
12826
+ row: PreferenceRowSchema
12827
+ }), object({
12828
+ status: literal("conflict"),
12829
+ current: PreferenceRowSchema.nullable()
12830
+ })]);
12831
+ object({ namespace: PreferenceNamespaceSchema });
12832
+ object({
12833
+ /** `false` when the namespace did not exist. */
12834
+ deleted: boolean() });
12835
+ object({
12836
+ /** The revision the client holds per namespace; a namespace it does not list is new to it. */
12837
+ revisionByNamespace: record(PreferenceNamespaceSchema, number().int().nonnegative()).refine((map) => Object.keys(map).length <= 32, { message: `at most 32 namespaces` }) });
12838
+ object({
12839
+ /** Every row whose revision differs from the client's, and every row it did not list. */
12840
+ rows: array(PreferenceRowSchema),
12841
+ /** Namespaces the client listed that no longer exist. */
12842
+ deleted: array(PreferenceNamespaceSchema)
12843
+ });
12793
12844
  _enum(["new-session", "step-up"]);
12794
12845
  /** The languages the hub's app landing pages are written in (D858). */
12795
12846
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -17043,7 +17094,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
17043
17094
  kind: literal("node"),
17044
17095
  nodeId: string().min(1)
17045
17096
  })]);
17097
+ /**
17098
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17099
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17100
+ * meaning); a rollup keeps the time spent in each state (`states`).
17101
+ */
17046
17102
  var DeviceHistoryKindSchema = _enum([
17103
+ "gauge",
17104
+ "counter",
17105
+ "boolean",
17106
+ "enum"
17107
+ ]);
17108
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17109
+ var DeviceHistoryProducerKindSchema = _enum([
17047
17110
  "gauge",
17048
17111
  "counter",
17049
17112
  "boolean"
@@ -17080,7 +17143,13 @@ var SeriesInfoSchema = object({
17080
17143
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17081
17144
  unit: string().nullable(),
17082
17145
  displayName: string(),
17083
- source: _enum(["cap", "addon"]),
17146
+ source: _enum([
17147
+ "cap",
17148
+ "addon",
17149
+ "derived"
17150
+ ]),
17151
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17152
+ values: array(string()).readonly().nullable(),
17084
17153
  firstTs: number(),
17085
17154
  lastTs: number()
17086
17155
  });
@@ -17094,17 +17163,31 @@ var QueryPointSchema = object({
17094
17163
  twMean: number().nullable(),
17095
17164
  min: number(),
17096
17165
  max: number(),
17097
- /** `null` is unknown, never zero (D393). */
17098
- last: number().nullable()
17166
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17167
+ last: number().nullable(),
17168
+ /**
17169
+ * The increase over the point: a `counter`'s growth since the previous point
17170
+ * or bucket (a drop is a reset, counted from zero), and for
17171
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17172
+ * every other kind, and when it cannot be known.
17173
+ */
17174
+ delta: number().nullable(),
17175
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17176
+ state: string().nullable(),
17177
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17178
+ states: record(string(), number()).nullable()
17099
17179
  });
17100
17180
  var QuerySeriesSchema = object({
17101
17181
  scope: string(),
17102
17182
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17103
17183
  before: object({
17104
17184
  t: number(),
17105
- value: number().nullable()
17185
+ value: number().nullable(),
17186
+ state: string().nullable()
17106
17187
  }).nullable(),
17107
- points: array(QueryPointSchema).readonly()
17188
+ points: array(QueryPointSchema).readonly(),
17189
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17190
+ derivedFrom: string().nullable()
17108
17191
  });
17109
17192
  /** The window part of a query, shared by the device and node forms. */
17110
17193
  var QueryWindowShape = {
@@ -17120,6 +17203,23 @@ var QueryResultSchema = object({
17120
17203
  series: array(QuerySeriesSchema).readonly(),
17121
17204
  truncated: boolean()
17122
17205
  });
17206
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17207
+ var QueryManyItemSchema = union([object({
17208
+ deviceId: number().int(),
17209
+ key: string(),
17210
+ scope: string().optional()
17211
+ }), object({
17212
+ forNodeId: string().min(1),
17213
+ key: string(),
17214
+ scope: string().optional()
17215
+ })]);
17216
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
17217
+ ok: literal(true),
17218
+ result: QueryResultSchema
17219
+ }), object({
17220
+ ok: literal(false),
17221
+ error: string()
17222
+ })]);
17123
17223
  var TierStatusSchema = object({
17124
17224
  tier: DeviceHistoryResolutionSchema,
17125
17225
  /** `null` until the first background count answered. */
@@ -17175,16 +17275,22 @@ var DeviceHistoryStatusSchema = object({
17175
17275
  lastRefreshAt: number().nullable()
17176
17276
  })
17177
17277
  });
17178
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17278
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
17179
17279
  deviceId: number().int(),
17180
17280
  ...QueryWindowShape
17181
17281
  }), QueryResultSchema), method(object({
17182
- nodeId: string().min(1),
17282
+ forNodeId: string().min(1),
17183
17283
  ...QueryWindowShape
17184
17284
  }), QueryResultSchema, { auth: "admin" }), method(object({
17285
+ items: array(QueryManyItemSchema).min(1).max(24),
17286
+ from: QueryWindowShape.from,
17287
+ to: QueryWindowShape.to,
17288
+ resolution: QueryWindowShape.resolution,
17289
+ maxPoints: QueryWindowShape.maxPoints
17290
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
17185
17291
  name: string().regex(/^[a-z0-9-]+$/),
17186
17292
  subjectKind: _enum(["device", "node"]),
17187
- kind: DeviceHistoryKindSchema,
17293
+ kind: DeviceHistoryProducerKindSchema,
17188
17294
  unit: string().optional(),
17189
17295
  displayName: string().min(1),
17190
17296
  ingest: _enum(["points", "buckets"])
@@ -39885,38 +39991,37 @@ method(LlmRuntimeCompleteInputSchema, LlmGenerateResultSchema, {
39885
39991
  auth: "admin",
39886
39992
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
39887
39993
  });
39994
+ var LlmProfileKindSchema = string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "a kind id is lower-case letters, digits and dashes");
39995
+ /** What a model (or, by default, every model of a kind) can do. */
39996
+ var LlmModelFeaturesSchema = object({
39997
+ vision: boolean(),
39998
+ tools: boolean(),
39999
+ streaming: boolean()
40000
+ });
40001
+ /** One model a provider offers. `features` overrides the kind's defaults, per field. */
40002
+ var LlmModelInfoSchema = object({
40003
+ id: string(),
40004
+ label: string().optional(),
40005
+ contextLength: number().int().positive().optional(),
40006
+ features: LlmModelFeaturesSchema.partial().optional()
40007
+ });
39888
40008
  /**
39889
- * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
39890
- * methods concat-fan across providers; single-row methods route to ONE
39891
- * provider by the `addonId` in the call input (the notification-output
39892
- * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
39893
- * (hub-placed); the cap stays open for future providers.
39894
- *
39895
- * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
39896
- * `apiKey` is a password field — providers REDACT it on read and merge on
39897
- * write; a stored key NEVER round-trips to a client.
40009
+ * The provider-specific part of a profile, validated by the provider that owns
40010
+ * the kind (`upsertProfile` refuses what it does not accept). A field its
40011
+ * `connectionSchema` declares `type: 'password'` is a secret: it is held in the
40012
+ * keychain, never in the row, and reads back as the redaction marker.
39898
40013
  */
39899
- var LlmProfileKindSchema = _enum([
39900
- "openai-compatible",
39901
- "openai",
39902
- "anthropic",
39903
- "google",
39904
- "managed-local",
39905
- "apple-foundation"
39906
- ]);
40014
+ var LlmProviderConfigSchema = record(string(), unknown());
39907
40015
  var LlmProfileSchema = object({
39908
40016
  id: string(),
39909
40017
  name: string(),
40018
+ /** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
39910
40019
  kind: LlmProfileKindSchema,
39911
40020
  /** Stamped by the provider — keeps the fanned catalog routable. */
39912
40021
  addonId: string(),
39913
40022
  enabled: boolean(),
39914
40023
  /** Vendor model id, or the managed runtime's loaded model. */
39915
40024
  model: string(),
39916
- /** Required for openai-compatible; override for cloud kinds. */
39917
- baseUrl: string().optional(),
39918
- /** ConfigUISchema type:'password' — never round-trips (spec §5). */
39919
- apiKey: string().optional(),
39920
40025
  /** Vision on/off. A vision call against a `false` profile is REFUSED, never
39921
40026
  * degraded to text — that shipped once and produced a confident answer to a
39922
40027
  * question about a picture nobody sent. */
@@ -39924,15 +40029,11 @@ var LlmProfileSchema = object({
39924
40029
  temperature: number().min(0).max(2).optional(),
39925
40030
  /** Nucleus sampling. Every wire we speak has it. */
39926
40031
  topP: number().min(0).max(1).optional(),
39927
- /** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
39928
- * wire does, and the client drops it there (measured: the request body gets
39929
- * `top_p` and no `top_k`). The profile editor hides the field wherever it
39930
- * would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
40032
+ /** Top-k sampling. Carried only by the wires that have it — a kind offers the
40033
+ * field in its editor only when its descriptor lists it in `profileFields`. */
39931
40034
  topK: number().int().positive().optional(),
39932
40035
  maxTokens: number().int().positive().optional(),
39933
- /** Prompt context window. Advisory for cloud kinds (they enforce their own);
39934
- * for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
39935
- * the model with, so it is the one field that changes a PROCESS. */
40036
+ /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
39936
40037
  contextLength: number().int().positive().optional(),
39937
40038
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
39938
40039
  * two system prompts fighting is worse than either alone). */
@@ -39958,16 +40059,37 @@ var LlmProfileSchema = object({
39958
40059
  * library; the REGISTRY of callable tools is ours and is empty in v1, so a
39959
40060
  * `true` here buys the wiring, not behaviour, until tools are registered. */
39960
40061
  toolsEnabled: boolean().default(false),
39961
- extraHeaders: record(string(), string()).optional(),
39962
- /** kind === 'managed-local' only (spec §4). */
39963
- runtime: ManagedRuntimeConfigSchema.optional(),
39964
- /**
39965
- * kind === 'apple-foundation' only: WHERE it runs — the only thing there is
39966
- * to configure (no key, no URL, no download; `model` is `apple-system`).
39967
- * `supportsVision` on such a row is stamped by the provider from the node's
39968
- * reported `imageInput`, never taken from the operator (D62).
39969
- */
39970
- appleFoundation: object({ nodeId: string() }).optional()
40062
+ /** Everything the kind's provider owns (endpoint, key, node, runtime…). */
40063
+ providerConfig: LlmProviderConfigSchema.default({})
40064
+ });
40065
+ /**
40066
+ * The common profile fields a kind's editor offers. The editor owns how each
40067
+ * one is drawn; the provider says which of them mean something on its wire.
40068
+ */
40069
+ var LlmProfileFieldSchema = _enum([
40070
+ "temperature",
40071
+ "topP",
40072
+ "topK",
40073
+ "maxTokens",
40074
+ "contextLength",
40075
+ "systemPrompt",
40076
+ "timeoutMs",
40077
+ "connectTimeoutMs",
40078
+ "firstTokenTimeoutMs",
40079
+ "idleTimeoutMs",
40080
+ "retry",
40081
+ "toolsEnabled"
40082
+ ]);
40083
+ /**
40084
+ * A provider-drawn part of the editor, by a generic widget id the admin UI
40085
+ * registers (`ai/apple-node`). `placement: 'model'` replaces the generic model
40086
+ * picker: that widget owns the model choice.
40087
+ */
40088
+ var LlmProviderWidgetSchema = object({
40089
+ id: string(),
40090
+ placement: _enum(["connection", "model"]),
40091
+ /** `providerConfig` keys this widget must fill before the profile can be saved. */
40092
+ requires: array(string()).optional()
39971
40093
  });
39972
40094
  /** ConfigUISchema tree passed through untyped on the wire (the
39973
40095
  * notification-output `ConfigSchemaPassthrough` precedent at
@@ -39976,11 +40098,56 @@ var ConfigSchemaPassthrough$3 = unknown();
39976
40098
  var LlmProfileKindDescriptorSchema = object({
39977
40099
  kind: LlmProfileKindSchema,
39978
40100
  label: string(),
40101
+ /** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
39979
40102
  icon: string(),
39980
40103
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
39981
40104
  addonId: string(),
39982
- configSchema: ConfigSchemaPassthrough$3
40105
+ /** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
40106
+ connectionSchema: ConfigSchemaPassthrough$3,
40107
+ /** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
40108
+ advancedSchema: ConfigSchemaPassthrough$3.optional(),
40109
+ /** The kind's defaults; a model from `listModels` may override any of them. */
40110
+ features: LlmModelFeaturesSchema,
40111
+ /** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
40112
+ visionEditable: boolean(),
40113
+ /** Where the model list comes from: `listModels`, `staticModels`, or nowhere. */
40114
+ modelCatalog: _enum([
40115
+ "fetch",
40116
+ "static",
40117
+ "none"
40118
+ ]),
40119
+ staticModels: array(LlmModelInfoSchema).optional(),
40120
+ /** The common fields that mean something on this kind's wire. */
40121
+ profileFields: array(LlmProfileFieldSchema),
40122
+ providerWidgets: array(LlmProviderWidgetSchema).optional()
39983
40123
  });
40124
+ /**
40125
+ * `listModels` input. `connection` is an UNSAVED draft of `providerConfig`
40126
+ * (the editor's form); with `profileId` too, a secret the draft leaves
40127
+ * untouched (absent or the redaction marker) is resolved server-side from the
40128
+ * stored profile — the browser never receives it.
40129
+ */
40130
+ var LlmListModelsInputSchema = object({
40131
+ addonId: string(),
40132
+ kind: LlmProfileKindSchema,
40133
+ profileId: string().optional(),
40134
+ connection: LlmProviderConfigSchema.optional()
40135
+ });
40136
+ var LlmListModelsErrorCodeSchema = _enum([
40137
+ "auth",
40138
+ "network",
40139
+ "unsupported",
40140
+ "invalid"
40141
+ ]);
40142
+ /** A RESULT, never a throw: "wrong key" is an answer the editor renders inline. */
40143
+ var LlmListModelsResultSchema = discriminatedUnion("ok", [object({
40144
+ ok: literal(true),
40145
+ models: array(LlmModelInfoSchema)
40146
+ }), object({
40147
+ ok: literal(false),
40148
+ code: LlmListModelsErrorCodeSchema,
40149
+ message: string()
40150
+ })]);
39984
40151
  var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
39985
40152
  var LlmDefaultSchema = object({
39986
40153
  selector: LlmDefaultSelectorSchema,
@@ -40080,7 +40247,10 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
40080
40247
  kind: "mutation",
40081
40248
  auth: "admin",
40082
40249
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
40083
- }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
40250
+ }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
40251
+ kind: "mutation",
40252
+ auth: "admin"
40253
+ }), method(object({}), array(LlmDefaultSchema)), method(object({
40084
40254
  selector: LlmDefaultSelectorSchema,
40085
40255
  profileId: string().nullable()
40086
40256
  }), _void(), {
@@ -40248,14 +40418,106 @@ var LogEntrySchema = object({
40248
40418
  meta: record(string(), unknown()).optional(),
40249
40419
  tags: record(string(), string()).optional()
40250
40420
  });
40251
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
40252
- scope: array(string()).optional(),
40421
+ /**
40422
+ * A history READ against one destination (D898).
40423
+ *
40424
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
40425
+ * browser applied after the limit is what made a rare device's lines
40426
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
40427
+ * minted (opaque to everyone else): a file position for the rotated files, a
40428
+ * nanosecond timestamp for Loki.
40429
+ *
40430
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
40431
+ * store answers `done: false` with the cursor it reached and the bytes it
40432
+ * scanned, and the caller decides whether to go on. That is what makes a long
40433
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
40434
+ * flight, and not asking for the next slice ends the scan.
40435
+ */
40436
+ var LogReadQuerySchema = object({
40437
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
40438
+ requestId: string().min(1).max(64).optional(),
40439
+ /** The device the line is about (`tags.deviceId`, numeric). */
40440
+ deviceId: number().int().optional(),
40441
+ /**
40442
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
40443
+ * match. Not `addonId`: a cap router reads that name as "which provider".
40444
+ */
40445
+ fromAddonId: string().min(1).max(200).optional(),
40446
+ /**
40447
+ * The emitting node: matches the agent that emitted the line, the node
40448
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
40449
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
40450
+ * name as "which node's provider".
40451
+ */
40452
+ fromNodeId: string().min(1).max(200).optional(),
40453
+ /** Any other tag, exact match (AND). */
40454
+ tags: record(string(), union([string(), number()])).optional(),
40455
+ /** Severity FLOOR: this level and above. */
40253
40456
  level: LogLevelSchema.optional(),
40254
- since: date().optional(),
40255
- until: date().optional(),
40256
- limit: number().optional(),
40257
- tags: record(string(), string()).optional()
40258
- }), array(LogEntrySchema).readonly());
40457
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
40458
+ text: string().min(1).max(200).optional(),
40459
+ /** Epoch ms, inclusive. */
40460
+ since: number().optional(),
40461
+ /** Epoch ms, inclusive. */
40462
+ until: number().optional(),
40463
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
40464
+ before: string().min(1).max(1024).optional(),
40465
+ /** Newer than this cursor (exclusive). */
40466
+ after: string().min(1).max(1024).optional(),
40467
+ limit: number().int().min(1).max(1e3).optional(),
40468
+ /** Wall-clock bound of this slice. The provider caps it. */
40469
+ budgetMs: number().int().min(50).max(1e4).optional()
40470
+ });
40471
+ var LogReadResultSchema = object({
40472
+ /** Newest first. */
40473
+ entries: array(object({
40474
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
40475
+ id: string().optional(),
40476
+ /** Epoch ms. */
40477
+ timestamp: number(),
40478
+ level: LogLevelSchema,
40479
+ scope: string().optional(),
40480
+ message: string(),
40481
+ tags: record(string(), union([string(), number()])).optional(),
40482
+ meta: record(string(), unknown()).optional()
40483
+ })),
40484
+ /** Pass as `before` for the next older page; null when nothing older exists. */
40485
+ nextBefore: string().nullable(),
40486
+ /** Pass as `after` to read what arrived since; null when unknown. */
40487
+ nextAfter: string().nullable(),
40488
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
40489
+ scannedBytes: number().int().nonnegative(),
40490
+ /**
40491
+ * True when the scan in this direction reached the end of the store.
40492
+ * False with fewer than `limit` entries means the budget ran out first —
40493
+ * call again with `nextBefore` to go on.
40494
+ */
40495
+ done: boolean(),
40496
+ /** True when `cancelRead` ended this slice early. */
40497
+ cancelled: boolean().optional()
40498
+ });
40499
+ var LogReadCapabilitiesSchema = object({
40500
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
40501
+ readable: boolean(),
40502
+ /** Why not, when `readable` is false — rendered next to the source. */
40503
+ reason: string().nullable(),
40504
+ /** Filters the provider applies itself. A false one is applied by nobody. */
40505
+ filters: object({
40506
+ deviceId: boolean(),
40507
+ addonId: boolean(),
40508
+ nodeId: boolean(),
40509
+ tags: boolean(),
40510
+ level: boolean(),
40511
+ text: boolean(),
40512
+ timeRange: boolean()
40513
+ }),
40514
+ /** How far back the store reaches, when the provider knows (days). */
40515
+ retentionDays: number().nullable()
40516
+ });
40517
+ 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() }), {
40518
+ kind: "mutation",
40519
+ auth: "admin"
40520
+ });
40259
40521
  /**
40260
40522
  * `login-method` — collection cap through which auth addons contribute
40261
40523
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -41973,9 +42235,11 @@ var alarmPanelCapability = {
41973
42235
  */
41974
42236
  durability: "restored",
41975
42237
  /**
41976
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
42238
+ * History (D850): the panel's lifecycle state as an `enum` series —
42239
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
42240
+ * few seconds keeps every step. Who armed it stays in the events ledger.
41977
42241
  */
41978
- history: "none",
42242
+ history: { fields: { state: { kind: "enum" } } },
41979
42243
  /** Clock fields: written, but excluded from the compare that decides
41980
42244
  * whether persisting is worth a SQLite commit. */
41981
42245
  volatileStateFields: ["lastChangedAt"]
@@ -42853,6 +43117,33 @@ var NcRuleTargetSchema = object({
42853
43117
  params: record(string(), unknown()).optional()
42854
43118
  });
42855
43119
  /**
43120
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
43121
+ *
43122
+ * Every mode starts from the same CLEAN source frame of the trigger moment
43123
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
43124
+ * to the zone that fired the rule) and renders it once at send time:
43125
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
43126
+ * colour and every OTHER track visible at that instant outlined thin, each
43127
+ * labelled with class and confidence ("dog 87%").
43128
+ * - `crop` — the subject cut out of that frame around its box at that instant.
43129
+ * - `clean` — the whole scene with nothing drawn on it.
43130
+ * - `none` — no picture.
43131
+ *
43132
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
43133
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
43134
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
43135
+ * ship a crop on one event and a boxed scene on the next depending on which
43136
+ * stored kind had landed.
43137
+ */
43138
+ var NcMediaImageSchema = _enum([
43139
+ "scene-boxes",
43140
+ "crop",
43141
+ "clean",
43142
+ "none"
43143
+ ]);
43144
+ /**
43145
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43146
+ *
42856
43147
  * Media attachment policy (P1 still-image subset).
42857
43148
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
42858
43149
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -42866,6 +43157,8 @@ var NcRuleTargetSchema = object({
42866
43157
  * - `none` — no attachment.
42867
43158
  */
42868
43159
  /**
43160
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
43161
+ *
42869
43162
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
42870
43163
  * conflate it with the selection strategy and betray the request: asking for
42871
43164
  * the clean scene frame on an object-event owner used to start at
@@ -42894,16 +43187,29 @@ var NcMediaFrameSchema = _enum([
42894
43187
  */
42895
43188
  var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
42896
43189
  var NcMediaPolicySchema = object({
43190
+ /**
43191
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
43192
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
43193
+ * triple below, at load and at every write, and the store keeps only this.
43194
+ */
43195
+ image: NcMediaImageSchema.optional(),
43196
+ /**
43197
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
43198
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
43199
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
43200
+ * Replaces `zoneCrop`.
43201
+ */
43202
+ showTriggerZone: boolean().optional(),
43203
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
42897
43204
  attach: _enum([
42898
43205
  "best",
42899
43206
  "best-matching",
42900
43207
  "keyFrame",
42901
43208
  "none"
42902
- ]).default("best"),
42903
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
43209
+ ]).optional(),
43210
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
42904
43211
  frame: NcMediaFrameSchema.optional(),
42905
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
42906
- * "show me the ZONE", not the whole scene or the subject crop. */
43212
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
42907
43213
  zoneCrop: boolean().optional(),
42908
43214
  /**
42909
43215
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -43075,7 +43381,9 @@ var NcRuleInputSchema = object({
43075
43381
  * targets.
43076
43382
  */
43077
43383
  targetUsers: array(string()).optional(),
43078
- media: NcMediaPolicySchema.default({ attach: "best" }),
43384
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
43385
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
43386
+ media: NcMediaPolicySchema.default({}),
43079
43387
  throttle: NcThrottleSchema.default({
43080
43388
  cooldownSec: 60,
43081
43389
  scope: "rule-device"
@@ -44012,13 +44320,37 @@ var NcAlarmModeOpeningsSchema = object({
44012
44320
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
44013
44321
  unknown: array(number().int())
44014
44322
  });
44323
+ /**
44324
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
44325
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
44326
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
44327
+ * never looks fully armed (D62: off must never look like broken).
44328
+ */
44329
+ var NcAlarmInputBypassViewSchema = object({
44330
+ ruleId: string(),
44331
+ /** The rule's current name (its frozen name when the rule is gone). */
44332
+ ruleName: string(),
44333
+ /** The input: the sensor of the match, else its camera. */
44334
+ deviceId: number().int(),
44335
+ /** The input's current name. */
44336
+ name: string(),
44337
+ /** When it was bypassed (ms epoch). */
44338
+ since: number(),
44339
+ /** Triggers from this input dropped since. */
44340
+ dropped: number().int().min(0)
44341
+ });
44015
44342
  var NcAlarmLiveSchema = object({
44016
44343
  state: AlarmStateSchema,
44017
44344
  /** The mode being armed into (exit delay) or held; null when disarmed. */
44018
44345
  targetMode: AlarmArmModeSchema.nullable(),
44019
44346
  availableModes: array(AlarmArmModeSchema),
44020
44347
  openings: array(NcAlarmModeOpeningsSchema),
44021
- exclusions: array(NcAlarmExclusionViewSchema)
44348
+ exclusions: array(NcAlarmExclusionViewSchema),
44349
+ /**
44350
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
44351
+ * Defaulted so an older hub answer still parses (as "none known").
44352
+ */
44353
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
44022
44354
  });
44023
44355
  var NcAlarmConfigSchema = object({
44024
44356
  /**
@@ -54885,9 +55217,11 @@ var connectivityCapability = {
54885
55217
  */
54886
55218
  durability: "restored",
54887
55219
  /**
54888
- * History (D850): none — duplicates device-status.online (one authority for availability).
55220
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
55221
+ * is the upstream entity's own link (a HA connectivity sensor), not the
55222
+ * device's reachability, which stays `device-status.online`.
54889
55223
  */
54890
- history: "none",
55224
+ history: { fields: { connected: { kind: "boolean" } } },
54891
55225
  /** Clock fields: written, but excluded from the compare that decides
54892
55226
  * whether persisting is worth a SQLite commit. */
54893
55227
  volatileStateFields: ["lastChangedAt"]
@@ -55711,11 +56045,22 @@ var dishwasherCapability = {
55711
56045
  },
55712
56046
  runtimeState: DishwasherStatusSchema,
55713
56047
  durability: "session",
55714
- history: { fields: { progressPercent: {
55715
- kind: "gauge",
55716
- unit: "%",
55717
- deadband: 2
55718
- } } }
56048
+ history: { fields: {
56049
+ progressPercent: {
56050
+ kind: "gauge",
56051
+ unit: "%",
56052
+ deadband: 2
56053
+ },
56054
+ state: { kind: "enum" },
56055
+ operationState: { kind: "enum" },
56056
+ remainingSeconds: {
56057
+ kind: "gauge",
56058
+ unit: "s",
56059
+ minIntervalMs: 6e4
56060
+ },
56061
+ doorOpen: { kind: "boolean" },
56062
+ powerOn: { kind: "boolean" }
56063
+ } }
55719
56064
  };
55720
56065
  var DoorbellStatusSchema = object({
55721
56066
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -55832,9 +56177,15 @@ var enumSensorCapability = {
55832
56177
  */
55833
56178
  durability: "restored",
55834
56179
  /**
55835
- * History (D850): none — text/enum state has no history (non-goal).
56180
+ * History (D850): the value as an `enum` series (an appliance's program or
56181
+ * operation state, an HVAC action). The option set is per device, so the
56182
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
56183
+ * `format` carries a timestamp, not a state, and is not recorded.
55836
56184
  */
55837
- history: "none",
56185
+ history: { fields: { value: {
56186
+ kind: "enum",
56187
+ skipWhenSet: "format"
56188
+ } } },
55838
56189
  /** Clock fields: written, but excluded from the compare that decides
55839
56190
  * whether persisting is worth a SQLite commit. */
55840
56191
  volatileStateFields: ["lastFetchedAt"]
@@ -57808,9 +58159,10 @@ var lockControlCapability = {
57808
58159
  */
57809
58160
  durability: "restored",
57810
58161
  /**
57811
- * History (D850): none — enum state; lock events belong in the events ledger.
58162
+ * History (D850): the lock's state as an `enum` series — change-only, no
58163
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
57812
58164
  */
57813
- history: "none",
58165
+ history: { fields: { state: { kind: "enum" } } },
57814
58166
  /** Clock fields: written, but excluded from the compare that decides
57815
58167
  * whether persisting is worth a SQLite commit. */
57816
58168
  volatileStateFields: ["lastChangedAt"]
@@ -57984,9 +58336,18 @@ var mediaPlayerCapability = {
57984
58336
  */
57985
58337
  durability: "session",
57986
58338
  /**
57987
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
58339
+ * History (D850): volume (a level an operator or an automation sets; the
58340
+ * default 10 s floor folds a slider drag into its end value) and mute.
58341
+ * `positionMs` is not recorded: it moves continuously while playing.
57988
58342
  */
57989
- history: "none"
58343
+ history: { fields: {
58344
+ volumeLevel: {
58345
+ kind: "gauge",
58346
+ unit: "%",
58347
+ deadband: 1
58348
+ },
58349
+ isMuted: { kind: "boolean" }
58350
+ } }
57990
58351
  };
57991
58352
  /**
57992
58353
  * mesh-network — collection cap for mesh-VPN providers.
@@ -63279,9 +63640,29 @@ var streamParamsCapability = {
63279
63640
  */
63280
63641
  durability: "restored",
63281
63642
  /**
63282
- * History (D850): none — encoder configuration.
63643
+ * History (D850): the configured bitrate and frame rate of the main and sub
63644
+ * profiles. Configuration, so change-only on the default floor: a point is an
63645
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
63646
+ * quality over time must show.
63283
63647
  */
63284
- history: "none",
63648
+ history: { fields: {
63649
+ "main.bitrate": {
63650
+ kind: "gauge",
63651
+ unit: "kbps"
63652
+ },
63653
+ "main.framerate": {
63654
+ kind: "gauge",
63655
+ unit: "fps"
63656
+ },
63657
+ "sub.bitrate": {
63658
+ kind: "gauge",
63659
+ unit: "kbps"
63660
+ },
63661
+ "sub.framerate": {
63662
+ kind: "gauge",
63663
+ unit: "fps"
63664
+ }
63665
+ } },
63285
63666
  /** Clock fields: written, but excluded from the compare that decides
63286
63667
  * whether persisting is worth a SQLite commit. */
63287
63668
  volatileStateFields: ["lastFetchedAt"]
@@ -64116,26 +64497,6 @@ var ApiKeySummarySchema = object({
64116
64497
  createdAt: number(),
64117
64498
  lastUsedAt: number().optional()
64118
64499
  });
64119
- var ScopedTokenSummarySchema = object({
64120
- id: string(),
64121
- userId: string(),
64122
- name: string(),
64123
- tokenPrefix: string(),
64124
- scopes: array(TokenScopeSchema),
64125
- expiresAt: number().nullish(),
64126
- lastUsedAt: number().nullish(),
64127
- createdAt: number()
64128
- });
64129
- var CreateScopedTokenInputSchema = object({
64130
- userId: string(),
64131
- name: string(),
64132
- scopes: array(TokenScopeSchema),
64133
- expiresAt: number().optional()
64134
- });
64135
- var CreateScopedTokenResultSchema = object({
64136
- token: string(),
64137
- record: ScopedTokenSummarySchema
64138
- });
64139
64500
  var OauthSessionSummarySchema = object({
64140
64501
  id: string(),
64141
64502
  userId: string(),
@@ -64157,11 +64518,11 @@ var TotpStatusSchema = object({
64157
64518
  confirmedAt: number().nullable()
64158
64519
  });
64159
64520
  /**
64160
- * user-management — singleton capability for user accounts, API keys,
64161
- * and scoped tokens.
64521
+ * user-management — singleton capability for user accounts and the
64522
+ * legacy API-key rows.
64162
64523
  *
64163
64524
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64164
- * — the subset check on `setUserScopes` / `createScopedToken` is moot
64525
+ * — the subset check on `setUserScopes` is moot
64165
64526
  * because non-admins never reach these. If/when we open non-admin
64166
64527
  * delegation, structural caller-scope subset check goes inside the
64167
64528
  * provider.
@@ -64218,15 +64579,7 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64218
64579
  kind: "mutation",
64219
64580
  auth: "admin",
64220
64581
  access: "delete"
64221
- }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
64222
- kind: "mutation",
64223
- auth: "admin",
64224
- access: "create"
64225
- }), method(object({ id: string() }), object({ success: literal(true) }), {
64226
- kind: "mutation",
64227
- auth: "admin",
64228
- access: "delete"
64229
- }), method(object({ token: string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }), method(object({ userId: string() }), array(ScopedTokenSummarySchema), { auth: "admin" }), method(object({ userId: string() }), TotpSetupResultSchema, {
64582
+ }), method(object({ userId: string() }), TotpSetupResultSchema, {
64230
64583
  kind: "mutation",
64231
64584
  auth: "admin",
64232
64585
  access: "create"
@@ -66487,6 +66840,15 @@ var BaseDevice = class {
66487
66840
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
66488
66841
  * with a typed cast.
66489
66842
  *
66843
+ * Answer what you KNOW. A plain array is read as the complete list only
66844
+ * while this device is `online` and probed; return
66845
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
66846
+ * now (no credentials, parent not connected, a failed or partial read) —
66847
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
66848
+ * to say "connected, and this is the complete list" explicitly. A shrink is
66849
+ * deleted only after a second agreeing complete read on a later probe (D49;
66850
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
66851
+ *
66490
66852
  * Default: no children.
66491
66853
  */
66492
66854
  getAccessoryChildren() {
@@ -69833,7 +70195,7 @@ Object.freeze({
69833
70195
  capName: "llm",
69834
70196
  capScope: "system",
69835
70197
  addonId: null,
69836
- access: "view"
70198
+ access: "create"
69837
70199
  },
69838
70200
  "llm.listNodeModels": {
69839
70201
  capName: "llm",
@@ -70135,7 +70497,19 @@ Object.freeze({
70135
70497
  addonId: null,
70136
70498
  access: "view"
70137
70499
  },
70138
- "logDestination.query": {
70500
+ "logDestination.cancelRead": {
70501
+ capName: "log-destination",
70502
+ capScope: "system",
70503
+ addonId: null,
70504
+ access: "create"
70505
+ },
70506
+ "logDestination.describeRead": {
70507
+ capName: "log-destination",
70508
+ capScope: "system",
70509
+ addonId: null,
70510
+ access: "view"
70511
+ },
70512
+ "logDestination.read": {
70139
70513
  capName: "log-destination",
70140
70514
  capScope: "system",
70141
70515
  addonId: null,
@@ -74497,12 +74871,6 @@ Object.freeze({
74497
74871
  addonId: null,
74498
74872
  access: "create"
74499
74873
  },
74500
- "userManagement.createScopedToken": {
74501
- capName: "user-management",
74502
- capScope: "system",
74503
- addonId: null,
74504
- access: "create"
74505
- },
74506
74874
  "userManagement.createUser": {
74507
74875
  capName: "user-management",
74508
74876
  capScope: "system",
@@ -74551,12 +74919,6 @@ Object.freeze({
74551
74919
  addonId: null,
74552
74920
  access: "view"
74553
74921
  },
74554
- "userManagement.listScopedTokens": {
74555
- capName: "user-management",
74556
- capScope: "system",
74557
- addonId: null,
74558
- access: "view"
74559
- },
74560
74922
  "userManagement.listUsers": {
74561
74923
  capName: "user-management",
74562
74924
  capScope: "system",
@@ -74611,12 +74973,6 @@ Object.freeze({
74611
74973
  addonId: null,
74612
74974
  access: "delete"
74613
74975
  },
74614
- "userManagement.revokeScopedToken": {
74615
- capName: "user-management",
74616
- capScope: "system",
74617
- addonId: null,
74618
- access: "delete"
74619
- },
74620
74976
  "userManagement.setupTotp": {
74621
74977
  capName: "user-management",
74622
74978
  capScope: "system",
@@ -74647,12 +75003,6 @@ Object.freeze({
74647
75003
  addonId: null,
74648
75004
  access: "view"
74649
75005
  },
74650
- "userManagement.validateScopedToken": {
74651
- capName: "user-management",
74652
- capScope: "system",
74653
- addonId: null,
74654
- access: "view"
74655
- },
74656
75006
  "userManagement.verifyTotp": {
74657
75007
  capName: "user-management",
74658
75008
  capScope: "system",
@@ -76166,6 +76516,11 @@ Object.freeze({
76166
76516
  form: "single",
76167
76517
  optional: false
76168
76518
  }],
76519
+ "logDestination.read": [{
76520
+ name: "deviceId",
76521
+ form: "single",
76522
+ optional: true
76523
+ }],
76169
76524
  "mediaPlayer.getStatus": [{
76170
76525
  name: "deviceId",
76171
76526
  form: "single",