@camstack/addon-post-analysis 1.2.610 → 1.2.612

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 (15) hide show
  1. package/dist/{clip-model-registry-B1BMbjlk.js → clip-model-registry-C7WMvftu.js} +729 -141
  2. package/dist/{clip-model-registry-CHMOaqp1.mjs → clip-model-registry-JH4cTI06.mjs} +706 -142
  3. package/dist/embedding-encoder/index.js +1 -1
  4. package/dist/embedding-encoder/index.mjs +1 -1
  5. package/dist/pipeline-analytics/_stub.js +2 -2
  6. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-Cv1RqnQj.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DQE_Wu6_.mjs} +3 -3
  7. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-7dLQKt_H.mjs +26 -0
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DbUPeg6m.mjs +26 -0
  9. package/dist/pipeline-analytics/{hostInit-vT2SQQV2.mjs → hostInit-Bl6Zvb1p.mjs} +3 -3
  10. package/dist/pipeline-analytics/index.js +68007 -67085
  11. package/dist/pipeline-analytics/index.mjs +77067 -76144
  12. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  13. package/package.json +1 -1
  14. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DyXzqvY7.mjs +0 -26
  15. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Cm7pZeMH.mjs +0 -26
@@ -5643,7 +5643,7 @@ var ZodIssueCode = {
5643
5643
  var ZodFirstPartyTypeKind;
5644
5644
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5645
5645
  //#endregion
5646
- //#region ../types/dist/sleep-BxjU_fJM.mjs
5646
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
5647
5647
  /**
5648
5648
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5649
5649
  * window to float samples (D455).
@@ -8026,9 +8026,9 @@ function normalizeAddonInitResult(result) {
8026
8026
  return result;
8027
8027
  }
8028
8028
  /**
8029
- * The share-view scope kinds a `csv_*` share token can carry. The hub mints
8030
- * and validates them (`share-token.service.ts` builds its enum from this
8031
- * list); a data plane names the kinds it ACCEPTS in `share`.
8029
+ * The share-view scope kinds a share-link token can carry. The hub mints
8030
+ * and validates them (`ShareViewGrantSchema` builds its
8031
+ * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
8032
8032
  */
8033
8033
  var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
8034
8034
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
@@ -14006,7 +14006,7 @@ var ConvertResultSchema = object({
14006
14006
  * `super_admin` — collapsed onto the single boolean because every
14007
14007
  * non-admin caller is governed by the same scope-check rules; the
14008
14008
  * distinction was only ever used to route role-specific procedures
14009
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
14009
+ * which we no longer have. CLI / webhook integrations are tokens (`auth.mintToken`)
14010
14010
  * with `isAdmin: false` + an explicit scope list.
14011
14011
  */
14012
14012
  /** Per-method access flavour. Materialised on every cap method via codegen. */
@@ -14195,10 +14195,12 @@ var AddonRoutesScopeSchema = object({
14195
14195
  type: literal("addon-routes"),
14196
14196
  access: array(MethodAccessSchema).min(1)
14197
14197
  });
14198
+ var PreferencesSelfScopeSchema = object({ type: literal("preferences-self") });
14198
14199
  var CredentialScopeSchema = union([
14199
14200
  literal("*"),
14200
14201
  ShareViewScopeSchema,
14201
14202
  AddonRoutesScopeSchema,
14203
+ PreferencesSelfScopeSchema,
14202
14204
  TokenScopeSchema
14203
14205
  ]);
14204
14206
  object({
@@ -14207,6 +14209,55 @@ object({
14207
14209
  jti: string().min(16),
14208
14210
  scopes: array(CredentialScopeSchema).min(1)
14209
14211
  });
14212
+ var PreferenceNamespaceSchema = string().regex(/^[a-z][a-z0-9.-]{0,63}$/);
14213
+ /** A namespace's value: a JSON object, opaque to the hub. */
14214
+ var PreferenceValueSchema = record(string(), unknown());
14215
+ var PreferenceDeviceIdSchema = string().min(1).max(64);
14216
+ /** A stored row, as the owner reads it. */
14217
+ var PreferenceRowSchema = object({
14218
+ namespace: PreferenceNamespaceSchema,
14219
+ value: PreferenceValueSchema,
14220
+ /** Starts at 1, +1 on every write of this namespace. A delete ends the row and its count. */
14221
+ revision: number().int().positive(),
14222
+ updatedAt: number().int(),
14223
+ /** The client id the last writer sent; `null` when it sent none. */
14224
+ updatedByDevice: PreferenceDeviceIdSchema.nullable()
14225
+ });
14226
+ object({
14227
+ /** Absent: every namespace the caller holds. */
14228
+ namespaces: array(PreferenceNamespaceSchema).max(32).optional() });
14229
+ object({ rows: array(PreferenceRowSchema) });
14230
+ object({
14231
+ namespace: PreferenceNamespaceSchema,
14232
+ value: PreferenceValueSchema,
14233
+ /**
14234
+ * The revision the edit was based on. Absent: last write wins. `0`: the
14235
+ * namespace must not exist yet. Any other value that is not the current
14236
+ * revision answers `conflict` and writes nothing.
14237
+ */
14238
+ baseRevision: number().int().nonnegative().optional(),
14239
+ deviceId: PreferenceDeviceIdSchema.optional()
14240
+ });
14241
+ discriminatedUnion("status", [object({
14242
+ status: literal("saved"),
14243
+ row: PreferenceRowSchema
14244
+ }), object({
14245
+ status: literal("conflict"),
14246
+ current: PreferenceRowSchema.nullable()
14247
+ })]);
14248
+ object({ namespace: PreferenceNamespaceSchema });
14249
+ object({
14250
+ /** `false` when the namespace did not exist. */
14251
+ deleted: boolean() });
14252
+ object({
14253
+ /** The revision the client holds per namespace; a namespace it does not list is new to it. */
14254
+ revisionByNamespace: record(PreferenceNamespaceSchema, number().int().nonnegative()).refine((map) => Object.keys(map).length <= 32, { message: `at most 32 namespaces` }) });
14255
+ object({
14256
+ /** Every row whose revision differs from the client's, and every row it did not list. */
14257
+ rows: array(PreferenceRowSchema),
14258
+ /** Namespaces the client listed that no longer exist. */
14259
+ deleted: array(PreferenceNamespaceSchema)
14260
+ });
14210
14261
  _enum(["new-session", "step-up"]);
14211
14262
  /** The languages the hub's app landing pages are written in (D858). */
14212
14263
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -18490,7 +18541,19 @@ var DeviceHistorySubjectSchema = discriminatedUnion("kind", [object({
18490
18541
  kind: literal("node"),
18491
18542
  nodeId: string().min(1)
18492
18543
  })]);
18544
+ /**
18545
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
18546
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
18547
+ * meaning); a rollup keeps the time spent in each state (`states`).
18548
+ */
18493
18549
  var DeviceHistoryKindSchema = _enum([
18550
+ "gauge",
18551
+ "counter",
18552
+ "boolean",
18553
+ "enum"
18554
+ ]);
18555
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
18556
+ var DeviceHistoryProducerKindSchema = _enum([
18494
18557
  "gauge",
18495
18558
  "counter",
18496
18559
  "boolean"
@@ -18527,7 +18590,13 @@ var SeriesInfoSchema = object({
18527
18590
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
18528
18591
  unit: string().nullable(),
18529
18592
  displayName: string(),
18530
- source: _enum(["cap", "addon"]),
18593
+ source: _enum([
18594
+ "cap",
18595
+ "addon",
18596
+ "derived"
18597
+ ]),
18598
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
18599
+ values: array(string()).readonly().nullable(),
18531
18600
  firstTs: number(),
18532
18601
  lastTs: number()
18533
18602
  });
@@ -18541,17 +18610,31 @@ var QueryPointSchema = object({
18541
18610
  twMean: number().nullable(),
18542
18611
  min: number(),
18543
18612
  max: number(),
18544
- /** `null` is unknown, never zero (D393). */
18545
- last: number().nullable()
18613
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
18614
+ last: number().nullable(),
18615
+ /**
18616
+ * The increase over the point: a `counter`'s growth since the previous point
18617
+ * or bucket (a drop is a reset, counted from zero), and for
18618
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
18619
+ * every other kind, and when it cannot be known.
18620
+ */
18621
+ delta: number().nullable(),
18622
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
18623
+ state: string().nullable(),
18624
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
18625
+ states: record(string(), number()).nullable()
18546
18626
  });
18547
18627
  var QuerySeriesSchema = object({
18548
18628
  scope: string(),
18549
18629
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
18550
18630
  before: object({
18551
18631
  t: number(),
18552
- value: number().nullable()
18632
+ value: number().nullable(),
18633
+ state: string().nullable()
18553
18634
  }).nullable(),
18554
- points: array(QueryPointSchema).readonly()
18635
+ points: array(QueryPointSchema).readonly(),
18636
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
18637
+ derivedFrom: string().nullable()
18555
18638
  });
18556
18639
  /** The window part of a query, shared by the device and node forms. */
18557
18640
  var QueryWindowShape = {
@@ -18567,6 +18650,23 @@ var QueryResultSchema = object({
18567
18650
  series: array(QuerySeriesSchema).readonly(),
18568
18651
  truncated: boolean()
18569
18652
  });
18653
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
18654
+ var QueryManyItemSchema = union([object({
18655
+ deviceId: number().int(),
18656
+ key: string(),
18657
+ scope: string().optional()
18658
+ }), object({
18659
+ forNodeId: string().min(1),
18660
+ key: string(),
18661
+ scope: string().optional()
18662
+ })]);
18663
+ var QueryManyEntrySchema = discriminatedUnion("ok", [object({
18664
+ ok: literal(true),
18665
+ result: QueryResultSchema
18666
+ }), object({
18667
+ ok: literal(false),
18668
+ error: string()
18669
+ })]);
18570
18670
  var TierStatusSchema = object({
18571
18671
  tier: DeviceHistoryResolutionSchema,
18572
18672
  /** `null` until the first background count answered. */
@@ -18622,16 +18722,22 @@ var DeviceHistoryStatusSchema = object({
18622
18722
  lastRefreshAt: number().nullable()
18623
18723
  })
18624
18724
  });
18625
- method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ nodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
18725
+ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly()), method(object({ forNodeId: string().min(1) }), array(SeriesInfoSchema).readonly(), { auth: "admin" }), method(object({
18626
18726
  deviceId: number().int(),
18627
18727
  ...QueryWindowShape
18628
18728
  }), QueryResultSchema), method(object({
18629
- nodeId: string().min(1),
18729
+ forNodeId: string().min(1),
18630
18730
  ...QueryWindowShape
18631
18731
  }), QueryResultSchema, { auth: "admin" }), method(object({
18732
+ items: array(QueryManyItemSchema).min(1).max(24),
18733
+ from: QueryWindowShape.from,
18734
+ to: QueryWindowShape.to,
18735
+ resolution: QueryWindowShape.resolution,
18736
+ maxPoints: QueryWindowShape.maxPoints
18737
+ }), object({ results: array(QueryManyEntrySchema).readonly() }), { auth: "admin" }), method(object({
18632
18738
  name: string().regex(/^[a-z0-9-]+$/),
18633
18739
  subjectKind: _enum(["device", "node"]),
18634
- kind: DeviceHistoryKindSchema,
18740
+ kind: DeviceHistoryProducerKindSchema,
18635
18741
  unit: string().optional(),
18636
18742
  displayName: string().min(1),
18637
18743
  ingest: _enum(["points", "buckets"])
@@ -41529,38 +41635,37 @@ method(LlmRuntimeCompleteInputSchema, LlmGenerateResultSchema, {
41529
41635
  auth: "admin",
41530
41636
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
41531
41637
  });
41638
+ var LlmProfileKindSchema = string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "a kind id is lower-case letters, digits and dashes");
41639
+ /** What a model (or, by default, every model of a kind) can do. */
41640
+ var LlmModelFeaturesSchema = object({
41641
+ vision: boolean(),
41642
+ tools: boolean(),
41643
+ streaming: boolean()
41644
+ });
41645
+ /** One model a provider offers. `features` overrides the kind's defaults, per field. */
41646
+ var LlmModelInfoSchema = object({
41647
+ id: string(),
41648
+ label: string().optional(),
41649
+ contextLength: number().int().positive().optional(),
41650
+ features: LlmModelFeaturesSchema.partial().optional()
41651
+ });
41532
41652
  /**
41533
- * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
41534
- * methods concat-fan across providers; single-row methods route to ONE
41535
- * provider by the `addonId` in the call input (the notification-output
41536
- * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
41537
- * (hub-placed); the cap stays open for future providers.
41538
- *
41539
- * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
41540
- * `apiKey` is a password field — providers REDACT it on read and merge on
41541
- * write; a stored key NEVER round-trips to a client.
41653
+ * The provider-specific part of a profile, validated by the provider that owns
41654
+ * the kind (`upsertProfile` refuses what it does not accept). A field its
41655
+ * `connectionSchema` declares `type: 'password'` is a secret: it is held in the
41656
+ * keychain, never in the row, and reads back as the redaction marker.
41542
41657
  */
41543
- var LlmProfileKindSchema = _enum([
41544
- "openai-compatible",
41545
- "openai",
41546
- "anthropic",
41547
- "google",
41548
- "managed-local",
41549
- "apple-foundation"
41550
- ]);
41658
+ var LlmProviderConfigSchema = record(string(), unknown());
41551
41659
  var LlmProfileSchema = object({
41552
41660
  id: string(),
41553
41661
  name: string(),
41662
+ /** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
41554
41663
  kind: LlmProfileKindSchema,
41555
41664
  /** Stamped by the provider — keeps the fanned catalog routable. */
41556
41665
  addonId: string(),
41557
41666
  enabled: boolean(),
41558
41667
  /** Vendor model id, or the managed runtime's loaded model. */
41559
41668
  model: string(),
41560
- /** Required for openai-compatible; override for cloud kinds. */
41561
- baseUrl: string().optional(),
41562
- /** ConfigUISchema type:'password' — never round-trips (spec §5). */
41563
- apiKey: string().optional(),
41564
41669
  /** Vision on/off. A vision call against a `false` profile is REFUSED, never
41565
41670
  * degraded to text — that shipped once and produced a confident answer to a
41566
41671
  * question about a picture nobody sent. */
@@ -41568,15 +41673,11 @@ var LlmProfileSchema = object({
41568
41673
  temperature: number().min(0).max(2).optional(),
41569
41674
  /** Nucleus sampling. Every wire we speak has it. */
41570
41675
  topP: number().min(0).max(1).optional(),
41571
- /** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
41572
- * wire does, and the client drops it there (measured: the request body gets
41573
- * `top_p` and no `top_k`). The profile editor hides the field wherever it
41574
- * would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
41676
+ /** Top-k sampling. Carried only by the wires that have it — a kind offers the
41677
+ * field in its editor only when its descriptor lists it in `profileFields`. */
41575
41678
  topK: number().int().positive().optional(),
41576
41679
  maxTokens: number().int().positive().optional(),
41577
- /** Prompt context window. Advisory for cloud kinds (they enforce their own);
41578
- * for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
41579
- * the model with, so it is the one field that changes a PROCESS. */
41680
+ /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
41580
41681
  contextLength: number().int().positive().optional(),
41581
41682
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
41582
41683
  * two system prompts fighting is worse than either alone). */
@@ -41602,16 +41703,37 @@ var LlmProfileSchema = object({
41602
41703
  * library; the REGISTRY of callable tools is ours and is empty in v1, so a
41603
41704
  * `true` here buys the wiring, not behaviour, until tools are registered. */
41604
41705
  toolsEnabled: boolean().default(false),
41605
- extraHeaders: record(string(), string()).optional(),
41606
- /** kind === 'managed-local' only (spec §4). */
41607
- runtime: ManagedRuntimeConfigSchema.optional(),
41608
- /**
41609
- * kind === 'apple-foundation' only: WHERE it runs — the only thing there is
41610
- * to configure (no key, no URL, no download; `model` is `apple-system`).
41611
- * `supportsVision` on such a row is stamped by the provider from the node's
41612
- * reported `imageInput`, never taken from the operator (D62).
41613
- */
41614
- appleFoundation: object({ nodeId: string() }).optional()
41706
+ /** Everything the kind's provider owns (endpoint, key, node, runtime…). */
41707
+ providerConfig: LlmProviderConfigSchema.default({})
41708
+ });
41709
+ /**
41710
+ * The common profile fields a kind's editor offers. The editor owns how each
41711
+ * one is drawn; the provider says which of them mean something on its wire.
41712
+ */
41713
+ var LlmProfileFieldSchema = _enum([
41714
+ "temperature",
41715
+ "topP",
41716
+ "topK",
41717
+ "maxTokens",
41718
+ "contextLength",
41719
+ "systemPrompt",
41720
+ "timeoutMs",
41721
+ "connectTimeoutMs",
41722
+ "firstTokenTimeoutMs",
41723
+ "idleTimeoutMs",
41724
+ "retry",
41725
+ "toolsEnabled"
41726
+ ]);
41727
+ /**
41728
+ * A provider-drawn part of the editor, by a generic widget id the admin UI
41729
+ * registers (`ai/apple-node`). `placement: 'model'` replaces the generic model
41730
+ * picker: that widget owns the model choice.
41731
+ */
41732
+ var LlmProviderWidgetSchema = object({
41733
+ id: string(),
41734
+ placement: _enum(["connection", "model"]),
41735
+ /** `providerConfig` keys this widget must fill before the profile can be saved. */
41736
+ requires: array(string()).optional()
41615
41737
  });
41616
41738
  /** ConfigUISchema tree passed through untyped on the wire (the
41617
41739
  * notification-output `ConfigSchemaPassthrough` precedent at
@@ -41620,11 +41742,56 @@ var ConfigSchemaPassthrough$3 = unknown();
41620
41742
  var LlmProfileKindDescriptorSchema = object({
41621
41743
  kind: LlmProfileKindSchema,
41622
41744
  label: string(),
41745
+ /** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
41623
41746
  icon: string(),
41624
41747
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
41625
41748
  addonId: string(),
41626
- configSchema: ConfigSchemaPassthrough$3
41749
+ /** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
41750
+ connectionSchema: ConfigSchemaPassthrough$3,
41751
+ /** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
41752
+ advancedSchema: ConfigSchemaPassthrough$3.optional(),
41753
+ /** The kind's defaults; a model from `listModels` may override any of them. */
41754
+ features: LlmModelFeaturesSchema,
41755
+ /** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
41756
+ visionEditable: boolean(),
41757
+ /** Where the model list comes from: `listModels`, `staticModels`, or nowhere. */
41758
+ modelCatalog: _enum([
41759
+ "fetch",
41760
+ "static",
41761
+ "none"
41762
+ ]),
41763
+ staticModels: array(LlmModelInfoSchema).optional(),
41764
+ /** The common fields that mean something on this kind's wire. */
41765
+ profileFields: array(LlmProfileFieldSchema),
41766
+ providerWidgets: array(LlmProviderWidgetSchema).optional()
41627
41767
  });
41768
+ /**
41769
+ * `listModels` input. `connection` is an UNSAVED draft of `providerConfig`
41770
+ * (the editor's form); with `profileId` too, a secret the draft leaves
41771
+ * untouched (absent or the redaction marker) is resolved server-side from the
41772
+ * stored profile — the browser never receives it.
41773
+ */
41774
+ var LlmListModelsInputSchema = object({
41775
+ addonId: string(),
41776
+ kind: LlmProfileKindSchema,
41777
+ profileId: string().optional(),
41778
+ connection: LlmProviderConfigSchema.optional()
41779
+ });
41780
+ var LlmListModelsErrorCodeSchema = _enum([
41781
+ "auth",
41782
+ "network",
41783
+ "unsupported",
41784
+ "invalid"
41785
+ ]);
41786
+ /** A RESULT, never a throw: "wrong key" is an answer the editor renders inline. */
41787
+ var LlmListModelsResultSchema = discriminatedUnion("ok", [object({
41788
+ ok: literal(true),
41789
+ models: array(LlmModelInfoSchema)
41790
+ }), object({
41791
+ ok: literal(false),
41792
+ code: LlmListModelsErrorCodeSchema,
41793
+ message: string()
41794
+ })]);
41628
41795
  var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
41629
41796
  var LlmDefaultSchema = object({
41630
41797
  selector: LlmDefaultSelectorSchema,
@@ -41724,7 +41891,10 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
41724
41891
  kind: "mutation",
41725
41892
  auth: "admin",
41726
41893
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
41727
- }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
41894
+ }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
41895
+ kind: "mutation",
41896
+ auth: "admin"
41897
+ }), method(object({}), array(LlmDefaultSchema)), method(object({
41728
41898
  selector: LlmDefaultSelectorSchema,
41729
41899
  profileId: string().nullable()
41730
41900
  }), _void(), {
@@ -41892,14 +42062,106 @@ var LogEntrySchema = object({
41892
42062
  meta: record(string(), unknown()).optional(),
41893
42063
  tags: record(string(), string()).optional()
41894
42064
  });
41895
- method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
41896
- scope: array(string()).optional(),
42065
+ /**
42066
+ * A history READ against one destination (D898).
42067
+ *
42068
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
42069
+ * browser applied after the limit is what made a rare device's lines
42070
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
42071
+ * minted (opaque to everyone else): a file position for the rotated files, a
42072
+ * nanosecond timestamp for Loki.
42073
+ *
42074
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
42075
+ * store answers `done: false` with the cursor it reached and the bytes it
42076
+ * scanned, and the caller decides whether to go on. That is what makes a long
42077
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
42078
+ * flight, and not asking for the next slice ends the scan.
42079
+ */
42080
+ var LogReadQuerySchema = object({
42081
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
42082
+ requestId: string().min(1).max(64).optional(),
42083
+ /** The device the line is about (`tags.deviceId`, numeric). */
42084
+ deviceId: number().int().optional(),
42085
+ /**
42086
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
42087
+ * match. Not `addonId`: a cap router reads that name as "which provider".
42088
+ */
42089
+ fromAddonId: string().min(1).max(200).optional(),
42090
+ /**
42091
+ * The emitting node: matches the agent that emitted the line, the node
42092
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
42093
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
42094
+ * name as "which node's provider".
42095
+ */
42096
+ fromNodeId: string().min(1).max(200).optional(),
42097
+ /** Any other tag, exact match (AND). */
42098
+ tags: record(string(), union([string(), number()])).optional(),
42099
+ /** Severity FLOOR: this level and above. */
41897
42100
  level: LogLevelSchema.optional(),
41898
- since: date().optional(),
41899
- until: date().optional(),
41900
- limit: number().optional(),
41901
- tags: record(string(), string()).optional()
41902
- }), array(LogEntrySchema).readonly());
42101
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
42102
+ text: string().min(1).max(200).optional(),
42103
+ /** Epoch ms, inclusive. */
42104
+ since: number().optional(),
42105
+ /** Epoch ms, inclusive. */
42106
+ until: number().optional(),
42107
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
42108
+ before: string().min(1).max(1024).optional(),
42109
+ /** Newer than this cursor (exclusive). */
42110
+ after: string().min(1).max(1024).optional(),
42111
+ limit: number().int().min(1).max(1e3).optional(),
42112
+ /** Wall-clock bound of this slice. The provider caps it. */
42113
+ budgetMs: number().int().min(50).max(1e4).optional()
42114
+ });
42115
+ var LogReadResultSchema = object({
42116
+ /** Newest first. */
42117
+ entries: array(object({
42118
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
42119
+ id: string().optional(),
42120
+ /** Epoch ms. */
42121
+ timestamp: number(),
42122
+ level: LogLevelSchema,
42123
+ scope: string().optional(),
42124
+ message: string(),
42125
+ tags: record(string(), union([string(), number()])).optional(),
42126
+ meta: record(string(), unknown()).optional()
42127
+ })),
42128
+ /** Pass as `before` for the next older page; null when nothing older exists. */
42129
+ nextBefore: string().nullable(),
42130
+ /** Pass as `after` to read what arrived since; null when unknown. */
42131
+ nextAfter: string().nullable(),
42132
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
42133
+ scannedBytes: number().int().nonnegative(),
42134
+ /**
42135
+ * True when the scan in this direction reached the end of the store.
42136
+ * False with fewer than `limit` entries means the budget ran out first —
42137
+ * call again with `nextBefore` to go on.
42138
+ */
42139
+ done: boolean(),
42140
+ /** True when `cancelRead` ended this slice early. */
42141
+ cancelled: boolean().optional()
42142
+ });
42143
+ var LogReadCapabilitiesSchema = object({
42144
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
42145
+ readable: boolean(),
42146
+ /** Why not, when `readable` is false — rendered next to the source. */
42147
+ reason: string().nullable(),
42148
+ /** Filters the provider applies itself. A false one is applied by nobody. */
42149
+ filters: object({
42150
+ deviceId: boolean(),
42151
+ addonId: boolean(),
42152
+ nodeId: boolean(),
42153
+ tags: boolean(),
42154
+ level: boolean(),
42155
+ text: boolean(),
42156
+ timeRange: boolean()
42157
+ }),
42158
+ /** How far back the store reaches, when the provider knows (days). */
42159
+ retentionDays: number().nullable()
42160
+ });
42161
+ 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() }), {
42162
+ kind: "mutation",
42163
+ auth: "admin"
42164
+ });
41903
42165
  /**
41904
42166
  * `login-method` — collection cap through which auth addons contribute
41905
42167
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -43648,9 +43910,11 @@ var alarmPanelCapability = {
43648
43910
  */
43649
43911
  durability: "restored",
43650
43912
  /**
43651
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
43913
+ * History (D850): the panel's lifecycle state as an `enum` series —
43914
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
43915
+ * few seconds keeps every step. Who armed it stays in the events ledger.
43652
43916
  */
43653
- history: "none",
43917
+ history: { fields: { state: { kind: "enum" } } },
43654
43918
  /** Clock fields: written, but excluded from the compare that decides
43655
43919
  * whether persisting is worth a SQLite commit. */
43656
43920
  volatileStateFields: ["lastChangedAt"]
@@ -44572,6 +44836,33 @@ var NcRuleTargetSchema = object({
44572
44836
  params: record(string(), unknown()).optional()
44573
44837
  });
44574
44838
  /**
44839
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
44840
+ *
44841
+ * Every mode starts from the same CLEAN source frame of the trigger moment
44842
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
44843
+ * to the zone that fired the rule) and renders it once at send time:
44844
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
44845
+ * colour and every OTHER track visible at that instant outlined thin, each
44846
+ * labelled with class and confidence ("dog 87%").
44847
+ * - `crop` — the subject cut out of that frame around its box at that instant.
44848
+ * - `clean` — the whole scene with nothing drawn on it.
44849
+ * - `none` — no picture.
44850
+ *
44851
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
44852
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
44853
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
44854
+ * ship a crop on one event and a boxed scene on the next depending on which
44855
+ * stored kind had landed.
44856
+ */
44857
+ var NcMediaImageSchema = _enum([
44858
+ "scene-boxes",
44859
+ "crop",
44860
+ "clean",
44861
+ "none"
44862
+ ]);
44863
+ /**
44864
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
44865
+ *
44575
44866
  * Media attachment policy (P1 still-image subset).
44576
44867
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
44577
44868
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -44585,6 +44876,8 @@ var NcRuleTargetSchema = object({
44585
44876
  * - `none` — no attachment.
44586
44877
  */
44587
44878
  /**
44879
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
44880
+ *
44588
44881
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
44589
44882
  * conflate it with the selection strategy and betray the request: asking for
44590
44883
  * the clean scene frame on an object-event owner used to start at
@@ -44631,16 +44924,29 @@ var NcLinkedCameraModeSchema = _enum(["mosaic", "each"]);
44631
44924
  var NC_CLIP_PRE_ROLL_DEFAULT_SEC = 4;
44632
44925
  var NC_CLIP_POST_ROLL_DEFAULT_SEC = 6;
44633
44926
  var NcMediaPolicySchema = object({
44927
+ /**
44928
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
44929
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
44930
+ * triple below, at load and at every write, and the store keeps only this.
44931
+ */
44932
+ image: NcMediaImageSchema.optional(),
44933
+ /**
44934
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
44935
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
44936
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
44937
+ * Replaces `zoneCrop`.
44938
+ */
44939
+ showTriggerZone: boolean().optional(),
44940
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
44634
44941
  attach: _enum([
44635
44942
  "best",
44636
44943
  "best-matching",
44637
44944
  "keyFrame",
44638
44945
  "none"
44639
- ]).default("best"),
44640
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
44946
+ ]).optional(),
44947
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
44641
44948
  frame: NcMediaFrameSchema.optional(),
44642
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
44643
- * "show me the ZONE", not the whole scene or the subject crop. */
44949
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
44644
44950
  zoneCrop: boolean().optional(),
44645
44951
  /**
44646
44952
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -44826,7 +45132,9 @@ var NcRuleInputSchema = object({
44826
45132
  * targets.
44827
45133
  */
44828
45134
  targetUsers: array(string()).optional(),
44829
- media: NcMediaPolicySchema.default({ attach: "best" }),
45135
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
45136
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
45137
+ media: NcMediaPolicySchema.default({}),
44830
45138
  throttle: NcThrottleSchema.default({
44831
45139
  cooldownSec: 60,
44832
45140
  scope: "rule-device"
@@ -46361,13 +46669,37 @@ var NcAlarmModeOpeningsSchema = object({
46361
46669
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
46362
46670
  unknown: array(number().int())
46363
46671
  });
46672
+ /**
46673
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
46674
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
46675
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
46676
+ * never looks fully armed (D62: off must never look like broken).
46677
+ */
46678
+ var NcAlarmInputBypassViewSchema = object({
46679
+ ruleId: string(),
46680
+ /** The rule's current name (its frozen name when the rule is gone). */
46681
+ ruleName: string(),
46682
+ /** The input: the sensor of the match, else its camera. */
46683
+ deviceId: number().int(),
46684
+ /** The input's current name. */
46685
+ name: string(),
46686
+ /** When it was bypassed (ms epoch). */
46687
+ since: number(),
46688
+ /** Triggers from this input dropped since. */
46689
+ dropped: number().int().min(0)
46690
+ });
46364
46691
  var NcAlarmLiveSchema = object({
46365
46692
  state: AlarmStateSchema,
46366
46693
  /** The mode being armed into (exit delay) or held; null when disarmed. */
46367
46694
  targetMode: AlarmArmModeSchema.nullable(),
46368
46695
  availableModes: array(AlarmArmModeSchema),
46369
46696
  openings: array(NcAlarmModeOpeningsSchema),
46370
- exclusions: array(NcAlarmExclusionViewSchema)
46697
+ exclusions: array(NcAlarmExclusionViewSchema),
46698
+ /**
46699
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
46700
+ * Defaulted so an older hub answer still parses (as "none known").
46701
+ */
46702
+ bypassedInputs: array(NcAlarmInputBypassViewSchema).default([])
46371
46703
  });
46372
46704
  var NcAlarmConfigSchema = object({
46373
46705
  /**
@@ -58277,9 +58609,11 @@ var connectivityCapability = {
58277
58609
  */
58278
58610
  durability: "restored",
58279
58611
  /**
58280
- * History (D850): none — duplicates device-status.online (one authority for availability).
58612
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
58613
+ * is the upstream entity's own link (a HA connectivity sensor), not the
58614
+ * device's reachability, which stays `device-status.online`.
58281
58615
  */
58282
- history: "none",
58616
+ history: { fields: { connected: { kind: "boolean" } } },
58283
58617
  /** Clock fields: written, but excluded from the compare that decides
58284
58618
  * whether persisting is worth a SQLite commit. */
58285
58619
  volatileStateFields: ["lastChangedAt"]
@@ -59125,11 +59459,22 @@ var dishwasherCapability = {
59125
59459
  },
59126
59460
  runtimeState: DishwasherStatusSchema,
59127
59461
  durability: "session",
59128
- history: { fields: { progressPercent: {
59129
- kind: "gauge",
59130
- unit: "%",
59131
- deadband: 2
59132
- } } }
59462
+ history: { fields: {
59463
+ progressPercent: {
59464
+ kind: "gauge",
59465
+ unit: "%",
59466
+ deadband: 2
59467
+ },
59468
+ state: { kind: "enum" },
59469
+ operationState: { kind: "enum" },
59470
+ remainingSeconds: {
59471
+ kind: "gauge",
59472
+ unit: "s",
59473
+ minIntervalMs: 6e4
59474
+ },
59475
+ doorOpen: { kind: "boolean" },
59476
+ powerOn: { kind: "boolean" }
59477
+ } }
59133
59478
  };
59134
59479
  var DoorbellStatusSchema = object({
59135
59480
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -59246,9 +59591,15 @@ var enumSensorCapability = {
59246
59591
  */
59247
59592
  durability: "restored",
59248
59593
  /**
59249
- * History (D850): none — text/enum state has no history (non-goal).
59594
+ * History (D850): the value as an `enum` series (an appliance's program or
59595
+ * operation state, an HVAC action). The option set is per device, so the
59596
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
59597
+ * `format` carries a timestamp, not a state, and is not recorded.
59250
59598
  */
59251
- history: "none",
59599
+ history: { fields: { value: {
59600
+ kind: "enum",
59601
+ skipWhenSet: "format"
59602
+ } } },
59252
59603
  /** Clock fields: written, but excluded from the compare that decides
59253
59604
  * whether persisting is worth a SQLite commit. */
59254
59605
  volatileStateFields: ["lastFetchedAt"]
@@ -61282,9 +61633,10 @@ var lockControlCapability = {
61282
61633
  */
61283
61634
  durability: "restored",
61284
61635
  /**
61285
- * History (D850): none — enum state; lock events belong in the events ledger.
61636
+ * History (D850): the lock's state as an `enum` series — change-only, no
61637
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
61286
61638
  */
61287
- history: "none",
61639
+ history: { fields: { state: { kind: "enum" } } },
61288
61640
  /** Clock fields: written, but excluded from the compare that decides
61289
61641
  * whether persisting is worth a SQLite commit. */
61290
61642
  volatileStateFields: ["lastChangedAt"]
@@ -61458,9 +61810,18 @@ var mediaPlayerCapability = {
61458
61810
  */
61459
61811
  durability: "session",
61460
61812
  /**
61461
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
61813
+ * History (D850): volume (a level an operator or an automation sets; the
61814
+ * default 10 s floor folds a slider drag into its end value) and mute.
61815
+ * `positionMs` is not recorded: it moves continuously while playing.
61462
61816
  */
61463
- history: "none"
61817
+ history: { fields: {
61818
+ volumeLevel: {
61819
+ kind: "gauge",
61820
+ unit: "%",
61821
+ deadband: 1
61822
+ },
61823
+ isMuted: { kind: "boolean" }
61824
+ } }
61464
61825
  };
61465
61826
  /**
61466
61827
  * mesh-network — collection cap for mesh-VPN providers.
@@ -66862,9 +67223,29 @@ var streamParamsCapability = {
66862
67223
  */
66863
67224
  durability: "restored",
66864
67225
  /**
66865
- * History (D850): none — encoder configuration.
67226
+ * History (D850): the configured bitrate and frame rate of the main and sub
67227
+ * profiles. Configuration, so change-only on the default floor: a point is an
67228
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
67229
+ * quality over time must show.
66866
67230
  */
66867
- history: "none",
67231
+ history: { fields: {
67232
+ "main.bitrate": {
67233
+ kind: "gauge",
67234
+ unit: "kbps"
67235
+ },
67236
+ "main.framerate": {
67237
+ kind: "gauge",
67238
+ unit: "fps"
67239
+ },
67240
+ "sub.bitrate": {
67241
+ kind: "gauge",
67242
+ unit: "kbps"
67243
+ },
67244
+ "sub.framerate": {
67245
+ kind: "gauge",
67246
+ unit: "fps"
67247
+ }
67248
+ } },
66868
67249
  /** Clock fields: written, but excluded from the compare that decides
66869
67250
  * whether persisting is worth a SQLite commit. */
66870
67251
  volatileStateFields: ["lastFetchedAt"]
@@ -67699,26 +68080,6 @@ var ApiKeySummarySchema = object({
67699
68080
  createdAt: number(),
67700
68081
  lastUsedAt: number().optional()
67701
68082
  });
67702
- var ScopedTokenSummarySchema = object({
67703
- id: string(),
67704
- userId: string(),
67705
- name: string(),
67706
- tokenPrefix: string(),
67707
- scopes: array(TokenScopeSchema),
67708
- expiresAt: number().nullish(),
67709
- lastUsedAt: number().nullish(),
67710
- createdAt: number()
67711
- });
67712
- var CreateScopedTokenInputSchema = object({
67713
- userId: string(),
67714
- name: string(),
67715
- scopes: array(TokenScopeSchema),
67716
- expiresAt: number().optional()
67717
- });
67718
- var CreateScopedTokenResultSchema = object({
67719
- token: string(),
67720
- record: ScopedTokenSummarySchema
67721
- });
67722
68083
  var OauthSessionSummarySchema = object({
67723
68084
  id: string(),
67724
68085
  userId: string(),
@@ -67740,11 +68101,11 @@ var TotpStatusSchema = object({
67740
68101
  confirmedAt: number().nullable()
67741
68102
  });
67742
68103
  /**
67743
- * user-management — singleton capability for user accounts, API keys,
67744
- * and scoped tokens.
68104
+ * user-management — singleton capability for user accounts and the
68105
+ * legacy API-key rows.
67745
68106
  *
67746
68107
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
67747
- * — the subset check on `setUserScopes` / `createScopedToken` is moot
68108
+ * — the subset check on `setUserScopes` is moot
67748
68109
  * because non-admins never reach these. If/when we open non-admin
67749
68110
  * delegation, structural caller-scope subset check goes inside the
67750
68111
  * provider.
@@ -67801,15 +68162,7 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
67801
68162
  kind: "mutation",
67802
68163
  auth: "admin",
67803
68164
  access: "delete"
67804
- }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
67805
- kind: "mutation",
67806
- auth: "admin",
67807
- access: "create"
67808
- }), method(object({ id: string() }), object({ success: literal(true) }), {
67809
- kind: "mutation",
67810
- auth: "admin",
67811
- access: "delete"
67812
- }), method(object({ token: string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }), method(object({ userId: string() }), array(ScopedTokenSummarySchema), { auth: "admin" }), method(object({ userId: string() }), TotpSetupResultSchema, {
68165
+ }), method(object({ userId: string() }), TotpSetupResultSchema, {
67813
68166
  kind: "mutation",
67814
68167
  auth: "admin",
67815
68168
  access: "create"
@@ -70123,6 +70476,15 @@ var BaseDevice = class {
70123
70476
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
70124
70477
  * with a typed cast.
70125
70478
  *
70479
+ * Answer what you KNOW. A plain array is read as the complete list only
70480
+ * while this device is `online` and probed; return
70481
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
70482
+ * now (no credentials, parent not connected, a failed or partial read) —
70483
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
70484
+ * to say "connected, and this is the complete list" explicitly. A shrink is
70485
+ * deleted only after a second agreeing complete read on a later probe (D49;
70486
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
70487
+ *
70126
70488
  * Default: no children.
70127
70489
  */
70128
70490
  getAccessoryChildren() {
@@ -73469,7 +73831,7 @@ Object.freeze({
73469
73831
  capName: "llm",
73470
73832
  capScope: "system",
73471
73833
  addonId: null,
73472
- access: "view"
73834
+ access: "create"
73473
73835
  },
73474
73836
  "llm.listNodeModels": {
73475
73837
  capName: "llm",
@@ -73771,7 +74133,19 @@ Object.freeze({
73771
74133
  addonId: null,
73772
74134
  access: "view"
73773
74135
  },
73774
- "logDestination.query": {
74136
+ "logDestination.cancelRead": {
74137
+ capName: "log-destination",
74138
+ capScope: "system",
74139
+ addonId: null,
74140
+ access: "create"
74141
+ },
74142
+ "logDestination.describeRead": {
74143
+ capName: "log-destination",
74144
+ capScope: "system",
74145
+ addonId: null,
74146
+ access: "view"
74147
+ },
74148
+ "logDestination.read": {
73775
74149
  capName: "log-destination",
73776
74150
  capScope: "system",
73777
74151
  addonId: null,
@@ -78133,12 +78507,6 @@ Object.freeze({
78133
78507
  addonId: null,
78134
78508
  access: "create"
78135
78509
  },
78136
- "userManagement.createScopedToken": {
78137
- capName: "user-management",
78138
- capScope: "system",
78139
- addonId: null,
78140
- access: "create"
78141
- },
78142
78510
  "userManagement.createUser": {
78143
78511
  capName: "user-management",
78144
78512
  capScope: "system",
@@ -78187,12 +78555,6 @@ Object.freeze({
78187
78555
  addonId: null,
78188
78556
  access: "view"
78189
78557
  },
78190
- "userManagement.listScopedTokens": {
78191
- capName: "user-management",
78192
- capScope: "system",
78193
- addonId: null,
78194
- access: "view"
78195
- },
78196
78558
  "userManagement.listUsers": {
78197
78559
  capName: "user-management",
78198
78560
  capScope: "system",
@@ -78247,12 +78609,6 @@ Object.freeze({
78247
78609
  addonId: null,
78248
78610
  access: "delete"
78249
78611
  },
78250
- "userManagement.revokeScopedToken": {
78251
- capName: "user-management",
78252
- capScope: "system",
78253
- addonId: null,
78254
- access: "delete"
78255
- },
78256
78612
  "userManagement.setupTotp": {
78257
78613
  capName: "user-management",
78258
78614
  capScope: "system",
@@ -78283,12 +78639,6 @@ Object.freeze({
78283
78639
  addonId: null,
78284
78640
  access: "view"
78285
78641
  },
78286
- "userManagement.validateScopedToken": {
78287
- capName: "user-management",
78288
- capScope: "system",
78289
- addonId: null,
78290
- access: "view"
78291
- },
78292
78642
  "userManagement.verifyTotp": {
78293
78643
  capName: "user-management",
78294
78644
  capScope: "system",
@@ -79802,6 +80152,11 @@ Object.freeze({
79802
80152
  form: "single",
79803
80153
  optional: false
79804
80154
  }],
80155
+ "logDestination.read": [{
80156
+ name: "deviceId",
80157
+ form: "single",
80158
+ optional: true
80159
+ }],
79805
80160
  "mediaPlayer.getStatus": [{
79806
80161
  name: "deviceId",
79807
80162
  form: "single",
@@ -82051,6 +82406,123 @@ function isSystemRuleKind(kind) {
82051
82406
  function systemFamilyOfKind(kind) {
82052
82407
  return isSystemEventFamily(kind) ? kind : void 0;
82053
82408
  }
82409
+ /**
82410
+ * Reasons, written once. Each names the SUBJECT FIELD the engine reads and
82411
+ * finds absent — that is what makes the exclusion checkable against the engine
82412
+ * rather than an opinion about tidiness.
82413
+ */
82414
+ var NO_SENSOR_KIND = "An occupancy edge is not a sensor event: it carries no sensor kind, so this condition can never match one.";
82415
+ var NO_EVENT_TOKEN = "An occupancy edge carries no device event-type token — that comes from an event-emitter slice, which a count crossing has none of.";
82416
+ var NO_SENSOR_EDGE = "An occupancy edge is a count crossing, not a sensor reading: it has no raise or clear, so this choice could never narrow it.";
82417
+ var OCCUPANCY_SOURCE = "An occupancy edge is always produced by the pipeline, so any other source can never match and “pipeline” narrows nothing.";
82418
+ var AUDIO_SOURCE = "A confirmed sound window is always stamped as an audio subject, so any other source can never match.";
82419
+ var SOUND_NOT_A_PICTURE = "A sound rule fires on what the camera HEARD. Its subject carries no detection, so this condition can never match one — name the sounds in the Sound condition instead.";
82420
+ var SOUND_NO_CONFIDENCE = "A sound window’s evidence is a percentage of samples, not a detector score, so a confidence threshold can never be satisfied.";
82421
+ var SOUND_NO_GEOMETRY = "A sound has no position in the frame, so a zone or a drawn polygon can never match it.";
82422
+ var NC_RULE_KIND_SPECS = [
82423
+ {
82424
+ kind: "detection",
82425
+ label: "Conditions",
82426
+ excluded: { audio: "A detection rule fires on what the camera SAW. Sounds are a Sound rule of their own — adding one here turned the rule into a sound rule and dropped every detection condition." },
82427
+ editable: true,
82428
+ carriesMedia: true,
82429
+ carriesSubjectCrop: true
82430
+ },
82431
+ {
82432
+ kind: "sensor",
82433
+ label: "Conditions",
82434
+ /** `occupancy` is still offered here: authoring it converts a sensor rule into an occupancy rule. */
82435
+ excluded: {},
82436
+ editable: true,
82437
+ carriesMedia: true,
82438
+ carriesSubjectCrop: true,
82439
+ blurb: "A doorbell press or a linked sensor changing state. The picture comes from the camera the sensor is attributed to."
82440
+ },
82441
+ {
82442
+ kind: "occupancy",
82443
+ label: "Occupancy",
82444
+ discriminator: "occupancy",
82445
+ excluded: {
82446
+ sensorKinds: NO_SENSOR_KIND,
82447
+ eventTypeTokens: NO_EVENT_TOKEN,
82448
+ sensorTransition: NO_SENSOR_EDGE,
82449
+ source: OCCUPANCY_SOURCE
82450
+ },
82451
+ editable: true,
82452
+ carriesMedia: true,
82453
+ carriesSubjectCrop: true,
82454
+ blurb: "Fires when the count in a camera frame or a zone crosses your threshold and holds. Pick the camera first — the zone list is that camera’s."
82455
+ },
82456
+ {
82457
+ kind: "sound",
82458
+ label: "Sound",
82459
+ discriminator: "audio",
82460
+ excluded: {
82461
+ classes: SOUND_NOT_A_PICTURE,
82462
+ classesExclude: SOUND_NOT_A_PICTURE,
82463
+ minConfidence: SOUND_NO_CONFIDENCE,
82464
+ zones: SOUND_NO_GEOMETRY,
82465
+ zonesExclude: SOUND_NO_GEOMETRY,
82466
+ customZones: SOUND_NO_GEOMETRY,
82467
+ crossing: SOUND_NO_GEOMETRY,
82468
+ labelEquals: SOUND_NOT_A_PICTURE,
82469
+ identities: SOUND_NOT_A_PICTURE,
82470
+ identitiesExclude: SOUND_NOT_A_PICTURE,
82471
+ plates: SOUND_NOT_A_PICTURE,
82472
+ source: AUDIO_SOURCE
82473
+ },
82474
+ editable: true,
82475
+ carriesMedia: true,
82476
+ carriesSubjectCrop: false,
82477
+ blurb: "Fires on a confirmed sampling window of audio, never on a picture. Name the sounds and/or keep a level threshold — with neither it can never match.",
82478
+ mediaBlurb: "A sound owns no frame, so the picture is a photograph of the camera taken at the moment of the match — the whole scene, never a crop. The GIF and the clip are cut around the same instant, from the camera."
82479
+ },
82480
+ {
82481
+ kind: "device-events",
82482
+ label: "Device events",
82483
+ discriminator: "systemEvent",
82484
+ excluded: {},
82485
+ editable: true,
82486
+ carriesMedia: false,
82487
+ carriesSubjectCrop: false,
82488
+ blurb: "A device or its stream going away or coming back, switched off or on, a battery or consumable running low, a camera detecting nothing. There is no frame to attach."
82489
+ },
82490
+ {
82491
+ kind: "system",
82492
+ label: "System events",
82493
+ discriminator: "systemEvent",
82494
+ excluded: {},
82495
+ editable: true,
82496
+ carriesMedia: false,
82497
+ carriesSubjectCrop: false,
82498
+ blurb: "The installation itself: a node leaving, an addon crash-looping, an update available or installed, a backup or an export finishing."
82499
+ },
82500
+ {
82501
+ kind: "alarm",
82502
+ label: "Alarm",
82503
+ discriminator: "systemEvent",
82504
+ excluded: {},
82505
+ editable: true,
82506
+ carriesMedia: false,
82507
+ carriesSubjectCrop: false,
82508
+ blurb: "The alarm panel: refused, arming, armed, entry delay, triggered, re-armed, sensor bypass, disarmed.",
82509
+ mediaBlurb: "An alarm set off by a rule arrives with THAT rule's pictures, combined into one notification. This rule adds none of its own."
82510
+ },
82511
+ {
82512
+ kind: "mixed",
82513
+ label: "To recreate",
82514
+ discriminator: "systemEvent",
82515
+ excluded: {},
82516
+ editable: false,
82517
+ carriesMedia: false,
82518
+ carriesSubjectCrop: false,
82519
+ blurb: "This rule mixes events from more than one family (device events, system, alarm). It keeps firing as it is, but it can no longer be edited: create one rule per family, then delete this one."
82520
+ }
82521
+ ];
82522
+ /** The spec for a kind. Total by construction — every member has an entry. */
82523
+ function ruleKindSpec(kind) {
82524
+ return NC_RULE_KIND_SPECS.find((s) => s.kind === kind) ?? NC_RULE_KIND_SPECS[0];
82525
+ }
82054
82526
  /** The delivery a system rule rides — named once, compared everywhere. */
82055
82527
  var NC_SYSTEM_DELIVERY = "system-event";
82056
82528
  /**
@@ -82168,6 +82640,98 @@ function systemRuleKindOf(condition) {
82168
82640
  return verdict.kind === "family" ? verdict.family : "mixed";
82169
82641
  }
82170
82642
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
82643
+ /** Every mode, in the order an editor offers them. */
82644
+ var NC_MEDIA_IMAGE_MODES = [
82645
+ "scene-boxes",
82646
+ "crop",
82647
+ "clean",
82648
+ "none"
82649
+ ];
82650
+ /**
82651
+ * The modes a rule of this kind can honour. A kind that carries no media gets
82652
+ * none (its row ships text, or — an alarm — its SOURCE rule's picture); a kind
82653
+ * whose subject has no region of the frame (a sound) is never offered `crop`.
82654
+ */
82655
+ function imageModesForKind(kind) {
82656
+ const spec = ruleKindSpec(kind);
82657
+ if (!spec.carriesMedia) return [];
82658
+ return spec.carriesSubjectCrop ? NC_MEDIA_IMAGE_MODES : NC_MEDIA_IMAGE_MODES.filter((mode) => mode !== "crop");
82659
+ }
82660
+ /**
82661
+ * The zone ids that FIRE a rule: its `zones` condition, or an occupancy rule's
82662
+ * own scoped zone. Empty when the trigger is not a zone — and then
82663
+ * `showTriggerZone` has nothing to draw and is refused on save.
82664
+ */
82665
+ function ruleTriggerZoneIds(conditions) {
82666
+ if (conditions.zones !== void 0) return conditions.zones.ids;
82667
+ const zoneId = conditions.occupancy?.zoneId;
82668
+ return zoneId !== void 0 ? [zoneId] : [];
82669
+ }
82670
+ /**
82671
+ * What the legacy triple MEANT, as a mode. `zoneCrop` forced the clean
82672
+ * keyFrame ladder and dropped `frame`, so it is `clean` whatever else was set;
82673
+ * `frame` decided over `attach` when present; `keyFrame` was the clean scene;
82674
+ * every other still (`best`, `best-matching`, the default) was the subject.
82675
+ */
82676
+ function legacyImageMode(media) {
82677
+ if (media.attach === "none") return "none";
82678
+ if (media.zoneCrop === true) return "clean";
82679
+ if (media.frame === "full") return "clean";
82680
+ if (media.frame === "boxed") return "scene-boxes";
82681
+ if (media.frame === "cropped") return "crop";
82682
+ if (media.attach === "keyFrame") return "clean";
82683
+ return "crop";
82684
+ }
82685
+ /** A mode the kind cannot honour, mapped to the nearest one it can. */
82686
+ function clampToKind(mode, kind) {
82687
+ const offered = imageModesForKind(kind);
82688
+ if (offered.length === 0 || offered.includes(mode)) return mode;
82689
+ return mode === "crop" ? "clean" : mode;
82690
+ }
82691
+ /**
82692
+ * The mode a rule's picture is rendered in. `image` when stored; else what the
82693
+ * legacy triple meant — and, for a SENSOR rule written before D897, `clean`
82694
+ * whatever it stored (even `attach: 'none'`), because its stored triple was
82695
+ * ignored and one plain snapshot always shipped (operator ruling, 2026-10-01):
82696
+ * the migration keeps what the rule actually DID. Clamped to what the kind can
82697
+ * honour.
82698
+ */
82699
+ function resolveNcMediaImage(media, kind) {
82700
+ if (media.image !== void 0) return clampToKind(media.image, kind);
82701
+ if (kind === "sensor") return "clean";
82702
+ return clampToKind(legacyImageMode(media), kind);
82703
+ }
82704
+ /**
82705
+ * The stored shape of a media policy: `image` set, the legacy triple gone.
82706
+ * `showTriggerZone` survives only where it can be drawn — a zone trigger and a
82707
+ * mode other than `crop`/`none`; a legacy `zoneCrop` on a zone rule becomes it.
82708
+ * Every other field (gif, clip, rolls, speed, profile, linked cameras) is
82709
+ * carried through untouched. Pure; never throws.
82710
+ */
82711
+ function normalizeNcMediaPolicy(media, rule) {
82712
+ const image = resolveNcMediaImage(media, ruleKindOf(rule));
82713
+ const { attach: _attach, frame: _frame, zoneCrop, showTriggerZone, image: _image, ...rest } = media;
82714
+ const drawable = (showTriggerZone === true || media.image === void 0 && zoneCrop === true) && image !== "crop" && image !== "none" && ruleTriggerZoneIds(rule.conditions).length > 0;
82715
+ return {
82716
+ ...rest,
82717
+ image,
82718
+ ...drawable ? { showTriggerZone: true } : {}
82719
+ };
82720
+ }
82721
+ /**
82722
+ * Why a media policy cannot be SAVED on this rule, or null. Server-side and
82723
+ * editor alike: `showTriggerZone` on a rule whose trigger is not a zone, and a
82724
+ * mode the rule's kind cannot honour.
82725
+ */
82726
+ function ncMediaPolicyError(media, rule) {
82727
+ const kind = ruleKindOf(rule);
82728
+ if (media.image !== void 0) {
82729
+ const offered = imageModesForKind(kind);
82730
+ if (offered.length > 0 && !offered.includes(media.image)) return `media.image '${media.image}' is not available for a ${kind} rule (offered: ${offered.join(", ")})`;
82731
+ }
82732
+ if (media.showTriggerZone === true && ruleTriggerZoneIds(rule.conditions).length === 0) return "media.showTriggerZone needs a rule triggered by a zone (a zones condition or an occupancy zone)";
82733
+ return null;
82734
+ }
82171
82735
  var WEEKDAY_TO_DAY = {
82172
82736
  Sun: 0,
82173
82737
  Mon: 1,
@@ -86537,6 +87101,12 @@ Object.defineProperty(exports, "RECORD_MAX_DATA_BYTES", {
86537
87101
  return RECORD_MAX_DATA_BYTES;
86538
87102
  }
86539
87103
  });
87104
+ Object.defineProperty(exports, "RECORD_QUERY_MAX", {
87105
+ enumerable: true,
87106
+ get: function() {
87107
+ return RECORD_QUERY_MAX;
87108
+ }
87109
+ });
86540
87110
  Object.defineProperty(exports, "RebuildObjectEmbeddingsRefusalSchema", {
86541
87111
  enumerable: true,
86542
87112
  get: function() {
@@ -87209,12 +87779,24 @@ Object.defineProperty(exports, "memoizePinnedFfmpeg", {
87209
87779
  return memoizePinnedFfmpeg;
87210
87780
  }
87211
87781
  });
87782
+ Object.defineProperty(exports, "ncMediaPolicyError", {
87783
+ enumerable: true,
87784
+ get: function() {
87785
+ return ncMediaPolicyError;
87786
+ }
87787
+ });
87212
87788
  Object.defineProperty(exports, "nodePin", {
87213
87789
  enumerable: true,
87214
87790
  get: function() {
87215
87791
  return nodePin;
87216
87792
  }
87217
87793
  });
87794
+ Object.defineProperty(exports, "normalizeNcMediaPolicy", {
87795
+ enumerable: true,
87796
+ get: function() {
87797
+ return normalizeNcMediaPolicy;
87798
+ }
87799
+ });
87218
87800
  Object.defineProperty(exports, "normalizeNodeId", {
87219
87801
  enumerable: true,
87220
87802
  get: function() {
@@ -87347,6 +87929,12 @@ Object.defineProperty(exports, "resolveModeNotifyPolicy", {
87347
87929
  return resolveModeNotifyPolicy;
87348
87930
  }
87349
87931
  });
87932
+ Object.defineProperty(exports, "resolveNcMediaImage", {
87933
+ enumerable: true,
87934
+ get: function() {
87935
+ return resolveNcMediaImage;
87936
+ }
87937
+ });
87350
87938
  Object.defineProperty(exports, "resolvePoolMemoryPolicy", {
87351
87939
  enumerable: true,
87352
87940
  get: function() {