@camstack/addon-provider-mqtt-ha 0.1.8 → 0.1.9

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 +165 -102
  2. package/dist/addon.mjs +165 -102
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -5448,7 +5448,7 @@ var ZodIssueCode = {
5448
5448
  var ZodFirstPartyTypeKind;
5449
5449
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5450
5450
  //#endregion
5451
- //#region ../types/dist/sleep-BxjU_fJM.mjs
5451
+ //#region ../types/dist/sleep-yKL5gfrH.mjs
5452
5452
  /**
5453
5453
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5454
5454
  * window to float samples (D455).
@@ -7831,9 +7831,9 @@ function normalizeAddonInitResult(result) {
7831
7831
  return result;
7832
7832
  }
7833
7833
  /**
7834
- * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7835
- * and validates them (`share-token.service.ts` builds its enum from this
7836
- * list); a data plane names the kinds it ACCEPTS in `share`.
7834
+ * The share-view scope kinds a share-link token can carry. The hub mints
7835
+ * and validates them (`ShareViewGrantSchema` builds its
7836
+ * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
7837
7837
  */
7838
7838
  var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7839
7839
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
@@ -12523,7 +12523,7 @@ var ConvertResultSchema = object({
12523
12523
  * `super_admin` — collapsed onto the single boolean because every
12524
12524
  * non-admin caller is governed by the same scope-check rules; the
12525
12525
  * distinction was only ever used to route role-specific procedures
12526
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12526
+ * which we no longer have. CLI / webhook integrations are tokens (`auth.mintToken`)
12527
12527
  * with `isAdmin: false` + an explicit scope list.
12528
12528
  */
12529
12529
  /** Per-method access flavour. Materialised on every cap method via codegen. */
@@ -12712,10 +12712,12 @@ var AddonRoutesScopeSchema = object({
12712
12712
  type: literal("addon-routes"),
12713
12713
  access: array(MethodAccessSchema).min(1)
12714
12714
  });
12715
+ var PreferencesSelfScopeSchema = object({ type: literal("preferences-self") });
12715
12716
  var CredentialScopeSchema = union([
12716
12717
  literal("*"),
12717
12718
  ShareViewScopeSchema,
12718
12719
  AddonRoutesScopeSchema,
12720
+ PreferencesSelfScopeSchema,
12719
12721
  TokenScopeSchema
12720
12722
  ]);
12721
12723
  object({
@@ -12724,6 +12726,55 @@ object({
12724
12726
  jti: string().min(16),
12725
12727
  scopes: array(CredentialScopeSchema).min(1)
12726
12728
  });
12729
+ var PreferenceNamespaceSchema = string().regex(/^[a-z][a-z0-9.-]{0,63}$/);
12730
+ /** A namespace's value: a JSON object, opaque to the hub. */
12731
+ var PreferenceValueSchema = record(string(), unknown());
12732
+ var PreferenceDeviceIdSchema = string().min(1).max(64);
12733
+ /** A stored row, as the owner reads it. */
12734
+ var PreferenceRowSchema = object({
12735
+ namespace: PreferenceNamespaceSchema,
12736
+ value: PreferenceValueSchema,
12737
+ /** Starts at 1, +1 on every write of this namespace. A delete ends the row and its count. */
12738
+ revision: number().int().positive(),
12739
+ updatedAt: number().int(),
12740
+ /** The client id the last writer sent; `null` when it sent none. */
12741
+ updatedByDevice: PreferenceDeviceIdSchema.nullable()
12742
+ });
12743
+ object({
12744
+ /** Absent: every namespace the caller holds. */
12745
+ namespaces: array(PreferenceNamespaceSchema).max(32).optional() });
12746
+ object({ rows: array(PreferenceRowSchema) });
12747
+ object({
12748
+ namespace: PreferenceNamespaceSchema,
12749
+ value: PreferenceValueSchema,
12750
+ /**
12751
+ * The revision the edit was based on. Absent: last write wins. `0`: the
12752
+ * namespace must not exist yet. Any other value that is not the current
12753
+ * revision answers `conflict` and writes nothing.
12754
+ */
12755
+ baseRevision: number().int().nonnegative().optional(),
12756
+ deviceId: PreferenceDeviceIdSchema.optional()
12757
+ });
12758
+ discriminatedUnion("status", [object({
12759
+ status: literal("saved"),
12760
+ row: PreferenceRowSchema
12761
+ }), object({
12762
+ status: literal("conflict"),
12763
+ current: PreferenceRowSchema.nullable()
12764
+ })]);
12765
+ object({ namespace: PreferenceNamespaceSchema });
12766
+ object({
12767
+ /** `false` when the namespace did not exist. */
12768
+ deleted: boolean() });
12769
+ object({
12770
+ /** The revision the client holds per namespace; a namespace it does not list is new to it. */
12771
+ revisionByNamespace: record(PreferenceNamespaceSchema, number().int().nonnegative()).refine((map) => Object.keys(map).length <= 32, { message: `at most 32 namespaces` }) });
12772
+ object({
12773
+ /** Every row whose revision differs from the client's, and every row it did not list. */
12774
+ rows: array(PreferenceRowSchema),
12775
+ /** Namespaces the client listed that no longer exist. */
12776
+ deleted: array(PreferenceNamespaceSchema)
12777
+ });
12727
12778
  _enum(["new-session", "step-up"]);
12728
12779
  /** The languages the hub's app landing pages are written in (D858). */
12729
12780
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -39917,38 +39968,37 @@ method(LlmRuntimeCompleteInputSchema, LlmGenerateResultSchema, {
39917
39968
  auth: "admin",
39918
39969
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
39919
39970
  });
39971
+ var LlmProfileKindSchema = string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "a kind id is lower-case letters, digits and dashes");
39972
+ /** What a model (or, by default, every model of a kind) can do. */
39973
+ var LlmModelFeaturesSchema = object({
39974
+ vision: boolean(),
39975
+ tools: boolean(),
39976
+ streaming: boolean()
39977
+ });
39978
+ /** One model a provider offers. `features` overrides the kind's defaults, per field. */
39979
+ var LlmModelInfoSchema = object({
39980
+ id: string(),
39981
+ label: string().optional(),
39982
+ contextLength: number().int().positive().optional(),
39983
+ features: LlmModelFeaturesSchema.partial().optional()
39984
+ });
39920
39985
  /**
39921
- * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
39922
- * methods concat-fan across providers; single-row methods route to ONE
39923
- * provider by the `addonId` in the call input (the notification-output
39924
- * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
39925
- * (hub-placed); the cap stays open for future providers.
39926
- *
39927
- * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
39928
- * `apiKey` is a password field — providers REDACT it on read and merge on
39929
- * write; a stored key NEVER round-trips to a client.
39986
+ * The provider-specific part of a profile, validated by the provider that owns
39987
+ * the kind (`upsertProfile` refuses what it does not accept). A field its
39988
+ * `connectionSchema` declares `type: 'password'` is a secret: it is held in the
39989
+ * keychain, never in the row, and reads back as the redaction marker.
39930
39990
  */
39931
- var LlmProfileKindSchema = _enum([
39932
- "openai-compatible",
39933
- "openai",
39934
- "anthropic",
39935
- "google",
39936
- "managed-local",
39937
- "apple-foundation"
39938
- ]);
39991
+ var LlmProviderConfigSchema = record(string(), unknown());
39939
39992
  var LlmProfileSchema = object({
39940
39993
  id: string(),
39941
39994
  name: string(),
39995
+ /** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
39942
39996
  kind: LlmProfileKindSchema,
39943
39997
  /** Stamped by the provider — keeps the fanned catalog routable. */
39944
39998
  addonId: string(),
39945
39999
  enabled: boolean(),
39946
40000
  /** Vendor model id, or the managed runtime's loaded model. */
39947
40001
  model: string(),
39948
- /** Required for openai-compatible; override for cloud kinds. */
39949
- baseUrl: string().optional(),
39950
- /** ConfigUISchema type:'password' — never round-trips (spec §5). */
39951
- apiKey: string().optional(),
39952
40002
  /** Vision on/off. A vision call against a `false` profile is REFUSED, never
39953
40003
  * degraded to text — that shipped once and produced a confident answer to a
39954
40004
  * question about a picture nobody sent. */
@@ -39956,15 +40006,11 @@ var LlmProfileSchema = object({
39956
40006
  temperature: number().min(0).max(2).optional(),
39957
40007
  /** Nucleus sampling. Every wire we speak has it. */
39958
40008
  topP: number().min(0).max(1).optional(),
39959
- /** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
39960
- * wire does, and the client drops it there (measured: the request body gets
39961
- * `top_p` and no `top_k`). The profile editor hides the field wherever it
39962
- * would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
40009
+ /** Top-k sampling. Carried only by the wires that have it — a kind offers the
40010
+ * field in its editor only when its descriptor lists it in `profileFields`. */
39963
40011
  topK: number().int().positive().optional(),
39964
40012
  maxTokens: number().int().positive().optional(),
39965
- /** Prompt context window. Advisory for cloud kinds (they enforce their own);
39966
- * for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
39967
- * the model with, so it is the one field that changes a PROCESS. */
40013
+ /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
39968
40014
  contextLength: number().int().positive().optional(),
39969
40015
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
39970
40016
  * two system prompts fighting is worse than either alone). */
@@ -39990,16 +40036,37 @@ var LlmProfileSchema = object({
39990
40036
  * library; the REGISTRY of callable tools is ours and is empty in v1, so a
39991
40037
  * `true` here buys the wiring, not behaviour, until tools are registered. */
39992
40038
  toolsEnabled: boolean().default(false),
39993
- extraHeaders: record(string(), string()).optional(),
39994
- /** kind === 'managed-local' only (spec §4). */
39995
- runtime: ManagedRuntimeConfigSchema.optional(),
39996
- /**
39997
- * kind === 'apple-foundation' only: WHERE it runs — the only thing there is
39998
- * to configure (no key, no URL, no download; `model` is `apple-system`).
39999
- * `supportsVision` on such a row is stamped by the provider from the node's
40000
- * reported `imageInput`, never taken from the operator (D62).
40001
- */
40002
- appleFoundation: object({ nodeId: string() }).optional()
40039
+ /** Everything the kind's provider owns (endpoint, key, node, runtime…). */
40040
+ providerConfig: LlmProviderConfigSchema.default({})
40041
+ });
40042
+ /**
40043
+ * The common profile fields a kind's editor offers. The editor owns how each
40044
+ * one is drawn; the provider says which of them mean something on its wire.
40045
+ */
40046
+ var LlmProfileFieldSchema = _enum([
40047
+ "temperature",
40048
+ "topP",
40049
+ "topK",
40050
+ "maxTokens",
40051
+ "contextLength",
40052
+ "systemPrompt",
40053
+ "timeoutMs",
40054
+ "connectTimeoutMs",
40055
+ "firstTokenTimeoutMs",
40056
+ "idleTimeoutMs",
40057
+ "retry",
40058
+ "toolsEnabled"
40059
+ ]);
40060
+ /**
40061
+ * A provider-drawn part of the editor, by a generic widget id the admin UI
40062
+ * registers (`ai/apple-node`). `placement: 'model'` replaces the generic model
40063
+ * picker: that widget owns the model choice.
40064
+ */
40065
+ var LlmProviderWidgetSchema = object({
40066
+ id: string(),
40067
+ placement: _enum(["connection", "model"]),
40068
+ /** `providerConfig` keys this widget must fill before the profile can be saved. */
40069
+ requires: array(string()).optional()
40003
40070
  });
40004
40071
  /** ConfigUISchema tree passed through untyped on the wire (the
40005
40072
  * notification-output `ConfigSchemaPassthrough` precedent at
@@ -40008,11 +40075,56 @@ var ConfigSchemaPassthrough$3 = unknown();
40008
40075
  var LlmProfileKindDescriptorSchema = object({
40009
40076
  kind: LlmProfileKindSchema,
40010
40077
  label: string(),
40078
+ /** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
40011
40079
  icon: string(),
40012
40080
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
40013
40081
  addonId: string(),
40014
- configSchema: ConfigSchemaPassthrough$3
40082
+ /** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
40083
+ connectionSchema: ConfigSchemaPassthrough$3,
40084
+ /** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
40085
+ advancedSchema: ConfigSchemaPassthrough$3.optional(),
40086
+ /** The kind's defaults; a model from `listModels` may override any of them. */
40087
+ features: LlmModelFeaturesSchema,
40088
+ /** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
40089
+ visionEditable: boolean(),
40090
+ /** Where the model list comes from: `listModels`, `staticModels`, or nowhere. */
40091
+ modelCatalog: _enum([
40092
+ "fetch",
40093
+ "static",
40094
+ "none"
40095
+ ]),
40096
+ staticModels: array(LlmModelInfoSchema).optional(),
40097
+ /** The common fields that mean something on this kind's wire. */
40098
+ profileFields: array(LlmProfileFieldSchema),
40099
+ providerWidgets: array(LlmProviderWidgetSchema).optional()
40015
40100
  });
40101
+ /**
40102
+ * `listModels` input. `connection` is an UNSAVED draft of `providerConfig`
40103
+ * (the editor's form); with `profileId` too, a secret the draft leaves
40104
+ * untouched (absent or the redaction marker) is resolved server-side from the
40105
+ * stored profile — the browser never receives it.
40106
+ */
40107
+ var LlmListModelsInputSchema = object({
40108
+ addonId: string(),
40109
+ kind: LlmProfileKindSchema,
40110
+ profileId: string().optional(),
40111
+ connection: LlmProviderConfigSchema.optional()
40112
+ });
40113
+ var LlmListModelsErrorCodeSchema = _enum([
40114
+ "auth",
40115
+ "network",
40116
+ "unsupported",
40117
+ "invalid"
40118
+ ]);
40119
+ /** A RESULT, never a throw: "wrong key" is an answer the editor renders inline. */
40120
+ var LlmListModelsResultSchema = discriminatedUnion("ok", [object({
40121
+ ok: literal(true),
40122
+ models: array(LlmModelInfoSchema)
40123
+ }), object({
40124
+ ok: literal(false),
40125
+ code: LlmListModelsErrorCodeSchema,
40126
+ message: string()
40127
+ })]);
40016
40128
  var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
40017
40129
  var LlmDefaultSchema = object({
40018
40130
  selector: LlmDefaultSelectorSchema,
@@ -40112,7 +40224,10 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
40112
40224
  kind: "mutation",
40113
40225
  auth: "admin",
40114
40226
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
40115
- }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
40227
+ }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
40228
+ kind: "mutation",
40229
+ auth: "admin"
40230
+ }), method(object({}), array(LlmDefaultSchema)), method(object({
40116
40231
  selector: LlmDefaultSelectorSchema,
40117
40232
  profileId: string().nullable()
40118
40233
  }), _void(), {
@@ -64000,26 +64115,6 @@ var ApiKeySummarySchema = object({
64000
64115
  createdAt: number(),
64001
64116
  lastUsedAt: number().optional()
64002
64117
  });
64003
- var ScopedTokenSummarySchema = object({
64004
- id: string(),
64005
- userId: string(),
64006
- name: string(),
64007
- tokenPrefix: string(),
64008
- scopes: array(TokenScopeSchema),
64009
- expiresAt: number().nullish(),
64010
- lastUsedAt: number().nullish(),
64011
- createdAt: number()
64012
- });
64013
- var CreateScopedTokenInputSchema = object({
64014
- userId: string(),
64015
- name: string(),
64016
- scopes: array(TokenScopeSchema),
64017
- expiresAt: number().optional()
64018
- });
64019
- var CreateScopedTokenResultSchema = object({
64020
- token: string(),
64021
- record: ScopedTokenSummarySchema
64022
- });
64023
64118
  var OauthSessionSummarySchema = object({
64024
64119
  id: string(),
64025
64120
  userId: string(),
@@ -64041,11 +64136,11 @@ var TotpStatusSchema = object({
64041
64136
  confirmedAt: number().nullable()
64042
64137
  });
64043
64138
  /**
64044
- * user-management — singleton capability for user accounts, API keys,
64045
- * and scoped tokens.
64139
+ * user-management — singleton capability for user accounts and the
64140
+ * legacy API-key rows.
64046
64141
  *
64047
64142
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64048
- * — the subset check on `setUserScopes` / `createScopedToken` is moot
64143
+ * — the subset check on `setUserScopes` is moot
64049
64144
  * because non-admins never reach these. If/when we open non-admin
64050
64145
  * delegation, structural caller-scope subset check goes inside the
64051
64146
  * provider.
@@ -64102,15 +64197,7 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64102
64197
  kind: "mutation",
64103
64198
  auth: "admin",
64104
64199
  access: "delete"
64105
- }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
64106
- kind: "mutation",
64107
- auth: "admin",
64108
- access: "create"
64109
- }), method(object({ id: string() }), object({ success: literal(true) }), {
64110
- kind: "mutation",
64111
- auth: "admin",
64112
- access: "delete"
64113
- }), method(object({ token: string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }), method(object({ userId: string() }), array(ScopedTokenSummarySchema), { auth: "admin" }), method(object({ userId: string() }), TotpSetupResultSchema, {
64200
+ }), method(object({ userId: string() }), TotpSetupResultSchema, {
64114
64201
  kind: "mutation",
64115
64202
  auth: "admin",
64116
64203
  access: "create"
@@ -70200,7 +70287,7 @@ Object.freeze({
70200
70287
  capName: "llm",
70201
70288
  capScope: "system",
70202
70289
  addonId: null,
70203
- access: "view"
70290
+ access: "create"
70204
70291
  },
70205
70292
  "llm.listNodeModels": {
70206
70293
  capName: "llm",
@@ -74864,12 +74951,6 @@ Object.freeze({
74864
74951
  addonId: null,
74865
74952
  access: "create"
74866
74953
  },
74867
- "userManagement.createScopedToken": {
74868
- capName: "user-management",
74869
- capScope: "system",
74870
- addonId: null,
74871
- access: "create"
74872
- },
74873
74954
  "userManagement.createUser": {
74874
74955
  capName: "user-management",
74875
74956
  capScope: "system",
@@ -74918,12 +74999,6 @@ Object.freeze({
74918
74999
  addonId: null,
74919
75000
  access: "view"
74920
75001
  },
74921
- "userManagement.listScopedTokens": {
74922
- capName: "user-management",
74923
- capScope: "system",
74924
- addonId: null,
74925
- access: "view"
74926
- },
74927
75002
  "userManagement.listUsers": {
74928
75003
  capName: "user-management",
74929
75004
  capScope: "system",
@@ -74978,12 +75053,6 @@ Object.freeze({
74978
75053
  addonId: null,
74979
75054
  access: "delete"
74980
75055
  },
74981
- "userManagement.revokeScopedToken": {
74982
- capName: "user-management",
74983
- capScope: "system",
74984
- addonId: null,
74985
- access: "delete"
74986
- },
74987
75056
  "userManagement.setupTotp": {
74988
75057
  capName: "user-management",
74989
75058
  capScope: "system",
@@ -75014,12 +75083,6 @@ Object.freeze({
75014
75083
  addonId: null,
75015
75084
  access: "view"
75016
75085
  },
75017
- "userManagement.validateScopedToken": {
75018
- capName: "user-management",
75019
- capScope: "system",
75020
- addonId: null,
75021
- access: "view"
75022
- },
75023
75086
  "userManagement.verifyTotp": {
75024
75087
  capName: "user-management",
75025
75088
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -5449,7 +5449,7 @@ var ZodIssueCode = {
5449
5449
  var ZodFirstPartyTypeKind;
5450
5450
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5451
5451
  //#endregion
5452
- //#region ../types/dist/sleep-BxjU_fJM.mjs
5452
+ //#region ../types/dist/sleep-yKL5gfrH.mjs
5453
5453
  /**
5454
5454
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5455
5455
  * window to float samples (D455).
@@ -7832,9 +7832,9 @@ function normalizeAddonInitResult(result) {
7832
7832
  return result;
7833
7833
  }
7834
7834
  /**
7835
- * The share-view scope kinds a `csv_*` share token can carry. The hub mints
7836
- * and validates them (`share-token.service.ts` builds its enum from this
7837
- * list); a data plane names the kinds it ACCEPTS in `share`.
7835
+ * The share-view scope kinds a share-link token can carry. The hub mints
7836
+ * and validates them (`ShareViewGrantSchema` builds its
7837
+ * enum from this list); a data plane names the kinds it ACCEPTS in `share`.
7838
7838
  */
7839
7839
  var SHARE_VIEW_KINDS = ["grid-view", "events-view"];
7840
7840
  /** The wire shape of {@link PeerBytesTicket} — see the type for what it is. */
@@ -12524,7 +12524,7 @@ var ConvertResultSchema = object({
12524
12524
  * `super_admin` — collapsed onto the single boolean because every
12525
12525
  * non-admin caller is governed by the same scope-check rules; the
12526
12526
  * distinction was only ever used to route role-specific procedures
12527
- * which we no longer have. CLI / webhook integrations are `cst_*` tokens
12527
+ * which we no longer have. CLI / webhook integrations are tokens (`auth.mintToken`)
12528
12528
  * with `isAdmin: false` + an explicit scope list.
12529
12529
  */
12530
12530
  /** Per-method access flavour. Materialised on every cap method via codegen. */
@@ -12713,10 +12713,12 @@ var AddonRoutesScopeSchema = object({
12713
12713
  type: literal("addon-routes"),
12714
12714
  access: array(MethodAccessSchema).min(1)
12715
12715
  });
12716
+ var PreferencesSelfScopeSchema = object({ type: literal("preferences-self") });
12716
12717
  var CredentialScopeSchema = union([
12717
12718
  literal("*"),
12718
12719
  ShareViewScopeSchema,
12719
12720
  AddonRoutesScopeSchema,
12721
+ PreferencesSelfScopeSchema,
12720
12722
  TokenScopeSchema
12721
12723
  ]);
12722
12724
  object({
@@ -12725,6 +12727,55 @@ object({
12725
12727
  jti: string().min(16),
12726
12728
  scopes: array(CredentialScopeSchema).min(1)
12727
12729
  });
12730
+ var PreferenceNamespaceSchema = string().regex(/^[a-z][a-z0-9.-]{0,63}$/);
12731
+ /** A namespace's value: a JSON object, opaque to the hub. */
12732
+ var PreferenceValueSchema = record(string(), unknown());
12733
+ var PreferenceDeviceIdSchema = string().min(1).max(64);
12734
+ /** A stored row, as the owner reads it. */
12735
+ var PreferenceRowSchema = object({
12736
+ namespace: PreferenceNamespaceSchema,
12737
+ value: PreferenceValueSchema,
12738
+ /** Starts at 1, +1 on every write of this namespace. A delete ends the row and its count. */
12739
+ revision: number().int().positive(),
12740
+ updatedAt: number().int(),
12741
+ /** The client id the last writer sent; `null` when it sent none. */
12742
+ updatedByDevice: PreferenceDeviceIdSchema.nullable()
12743
+ });
12744
+ object({
12745
+ /** Absent: every namespace the caller holds. */
12746
+ namespaces: array(PreferenceNamespaceSchema).max(32).optional() });
12747
+ object({ rows: array(PreferenceRowSchema) });
12748
+ object({
12749
+ namespace: PreferenceNamespaceSchema,
12750
+ value: PreferenceValueSchema,
12751
+ /**
12752
+ * The revision the edit was based on. Absent: last write wins. `0`: the
12753
+ * namespace must not exist yet. Any other value that is not the current
12754
+ * revision answers `conflict` and writes nothing.
12755
+ */
12756
+ baseRevision: number().int().nonnegative().optional(),
12757
+ deviceId: PreferenceDeviceIdSchema.optional()
12758
+ });
12759
+ discriminatedUnion("status", [object({
12760
+ status: literal("saved"),
12761
+ row: PreferenceRowSchema
12762
+ }), object({
12763
+ status: literal("conflict"),
12764
+ current: PreferenceRowSchema.nullable()
12765
+ })]);
12766
+ object({ namespace: PreferenceNamespaceSchema });
12767
+ object({
12768
+ /** `false` when the namespace did not exist. */
12769
+ deleted: boolean() });
12770
+ object({
12771
+ /** The revision the client holds per namespace; a namespace it does not list is new to it. */
12772
+ revisionByNamespace: record(PreferenceNamespaceSchema, number().int().nonnegative()).refine((map) => Object.keys(map).length <= 32, { message: `at most 32 namespaces` }) });
12773
+ object({
12774
+ /** Every row whose revision differs from the client's, and every row it did not list. */
12775
+ rows: array(PreferenceRowSchema),
12776
+ /** Namespaces the client listed that no longer exist. */
12777
+ deleted: array(PreferenceNamespaceSchema)
12778
+ });
12728
12779
  _enum(["new-session", "step-up"]);
12729
12780
  /** The languages the hub's app landing pages are written in (D858). */
12730
12781
  var AppPageLangSchema = _enum(["en", "it"]);
@@ -39918,38 +39969,37 @@ method(LlmRuntimeCompleteInputSchema, LlmGenerateResultSchema, {
39918
39969
  auth: "admin",
39919
39970
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
39920
39971
  });
39972
+ var LlmProfileKindSchema = string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "a kind id is lower-case letters, digits and dashes");
39973
+ /** What a model (or, by default, every model of a kind) can do. */
39974
+ var LlmModelFeaturesSchema = object({
39975
+ vision: boolean(),
39976
+ tools: boolean(),
39977
+ streaming: boolean()
39978
+ });
39979
+ /** One model a provider offers. `features` overrides the kind's defaults, per field. */
39980
+ var LlmModelInfoSchema = object({
39981
+ id: string(),
39982
+ label: string().optional(),
39983
+ contextLength: number().int().positive().optional(),
39984
+ features: LlmModelFeaturesSchema.partial().optional()
39985
+ });
39921
39986
  /**
39922
- * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
39923
- * methods concat-fan across providers; single-row methods route to ONE
39924
- * provider by the `addonId` in the call input (the notification-output
39925
- * posture, notification-output.cap.ts:215-250). Provided by `addon-ai`
39926
- * (hub-placed); the cap stays open for future providers.
39927
- *
39928
- * Profiles are ROWS (data), not addons: one row = one usable model endpoint.
39929
- * `apiKey` is a password field — providers REDACT it on read and merge on
39930
- * write; a stored key NEVER round-trips to a client.
39987
+ * The provider-specific part of a profile, validated by the provider that owns
39988
+ * the kind (`upsertProfile` refuses what it does not accept). A field its
39989
+ * `connectionSchema` declares `type: 'password'` is a secret: it is held in the
39990
+ * keychain, never in the row, and reads back as the redaction marker.
39931
39991
  */
39932
- var LlmProfileKindSchema = _enum([
39933
- "openai-compatible",
39934
- "openai",
39935
- "anthropic",
39936
- "google",
39937
- "managed-local",
39938
- "apple-foundation"
39939
- ]);
39992
+ var LlmProviderConfigSchema = record(string(), unknown());
39940
39993
  var LlmProfileSchema = object({
39941
39994
  id: string(),
39942
39995
  name: string(),
39996
+ /** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
39943
39997
  kind: LlmProfileKindSchema,
39944
39998
  /** Stamped by the provider — keeps the fanned catalog routable. */
39945
39999
  addonId: string(),
39946
40000
  enabled: boolean(),
39947
40001
  /** Vendor model id, or the managed runtime's loaded model. */
39948
40002
  model: string(),
39949
- /** Required for openai-compatible; override for cloud kinds. */
39950
- baseUrl: string().optional(),
39951
- /** ConfigUISchema type:'password' — never round-trips (spec §5). */
39952
- apiKey: string().optional(),
39953
40003
  /** Vision on/off. A vision call against a `false` profile is REFUSED, never
39954
40004
  * degraded to text — that shipped once and produced a confident answer to a
39955
40005
  * question about a picture nobody sent. */
@@ -39957,15 +40007,11 @@ var LlmProfileSchema = object({
39957
40007
  temperature: number().min(0).max(2).optional(),
39958
40008
  /** Nucleus sampling. Every wire we speak has it. */
39959
40009
  topP: number().min(0).max(1).optional(),
39960
- /** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
39961
- * wire does, and the client drops it there (measured: the request body gets
39962
- * `top_p` and no `top_k`). The profile editor hides the field wherever it
39963
- * would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
40010
+ /** Top-k sampling. Carried only by the wires that have it — a kind offers the
40011
+ * field in its editor only when its descriptor lists it in `profileFields`. */
39964
40012
  topK: number().int().positive().optional(),
39965
40013
  maxTokens: number().int().positive().optional(),
39966
- /** Prompt context window. Advisory for cloud kinds (they enforce their own);
39967
- * for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
39968
- * the model with, so it is the one field that changes a PROCESS. */
40014
+ /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
39969
40015
  contextLength: number().int().positive().optional(),
39970
40016
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
39971
40017
  * two system prompts fighting is worse than either alone). */
@@ -39991,16 +40037,37 @@ var LlmProfileSchema = object({
39991
40037
  * library; the REGISTRY of callable tools is ours and is empty in v1, so a
39992
40038
  * `true` here buys the wiring, not behaviour, until tools are registered. */
39993
40039
  toolsEnabled: boolean().default(false),
39994
- extraHeaders: record(string(), string()).optional(),
39995
- /** kind === 'managed-local' only (spec §4). */
39996
- runtime: ManagedRuntimeConfigSchema.optional(),
39997
- /**
39998
- * kind === 'apple-foundation' only: WHERE it runs — the only thing there is
39999
- * to configure (no key, no URL, no download; `model` is `apple-system`).
40000
- * `supportsVision` on such a row is stamped by the provider from the node's
40001
- * reported `imageInput`, never taken from the operator (D62).
40002
- */
40003
- appleFoundation: object({ nodeId: string() }).optional()
40040
+ /** Everything the kind's provider owns (endpoint, key, node, runtime…). */
40041
+ providerConfig: LlmProviderConfigSchema.default({})
40042
+ });
40043
+ /**
40044
+ * The common profile fields a kind's editor offers. The editor owns how each
40045
+ * one is drawn; the provider says which of them mean something on its wire.
40046
+ */
40047
+ var LlmProfileFieldSchema = _enum([
40048
+ "temperature",
40049
+ "topP",
40050
+ "topK",
40051
+ "maxTokens",
40052
+ "contextLength",
40053
+ "systemPrompt",
40054
+ "timeoutMs",
40055
+ "connectTimeoutMs",
40056
+ "firstTokenTimeoutMs",
40057
+ "idleTimeoutMs",
40058
+ "retry",
40059
+ "toolsEnabled"
40060
+ ]);
40061
+ /**
40062
+ * A provider-drawn part of the editor, by a generic widget id the admin UI
40063
+ * registers (`ai/apple-node`). `placement: 'model'` replaces the generic model
40064
+ * picker: that widget owns the model choice.
40065
+ */
40066
+ var LlmProviderWidgetSchema = object({
40067
+ id: string(),
40068
+ placement: _enum(["connection", "model"]),
40069
+ /** `providerConfig` keys this widget must fill before the profile can be saved. */
40070
+ requires: array(string()).optional()
40004
40071
  });
40005
40072
  /** ConfigUISchema tree passed through untyped on the wire (the
40006
40073
  * notification-output `ConfigSchemaPassthrough` precedent at
@@ -40009,11 +40076,56 @@ var ConfigSchemaPassthrough$3 = unknown();
40009
40076
  var LlmProfileKindDescriptorSchema = object({
40010
40077
  kind: LlmProfileKindSchema,
40011
40078
  label: string(),
40079
+ /** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
40012
40080
  icon: string(),
40013
40081
  /** Stamped by each provider so the concat-fanned catalog stays routable. */
40014
40082
  addonId: string(),
40015
- configSchema: ConfigSchemaPassthrough$3
40083
+ /** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
40084
+ connectionSchema: ConfigSchemaPassthrough$3,
40085
+ /** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
40086
+ advancedSchema: ConfigSchemaPassthrough$3.optional(),
40087
+ /** The kind's defaults; a model from `listModels` may override any of them. */
40088
+ features: LlmModelFeaturesSchema,
40089
+ /** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
40090
+ visionEditable: boolean(),
40091
+ /** Where the model list comes from: `listModels`, `staticModels`, or nowhere. */
40092
+ modelCatalog: _enum([
40093
+ "fetch",
40094
+ "static",
40095
+ "none"
40096
+ ]),
40097
+ staticModels: array(LlmModelInfoSchema).optional(),
40098
+ /** The common fields that mean something on this kind's wire. */
40099
+ profileFields: array(LlmProfileFieldSchema),
40100
+ providerWidgets: array(LlmProviderWidgetSchema).optional()
40016
40101
  });
40102
+ /**
40103
+ * `listModels` input. `connection` is an UNSAVED draft of `providerConfig`
40104
+ * (the editor's form); with `profileId` too, a secret the draft leaves
40105
+ * untouched (absent or the redaction marker) is resolved server-side from the
40106
+ * stored profile — the browser never receives it.
40107
+ */
40108
+ var LlmListModelsInputSchema = object({
40109
+ addonId: string(),
40110
+ kind: LlmProfileKindSchema,
40111
+ profileId: string().optional(),
40112
+ connection: LlmProviderConfigSchema.optional()
40113
+ });
40114
+ var LlmListModelsErrorCodeSchema = _enum([
40115
+ "auth",
40116
+ "network",
40117
+ "unsupported",
40118
+ "invalid"
40119
+ ]);
40120
+ /** A RESULT, never a throw: "wrong key" is an answer the editor renders inline. */
40121
+ var LlmListModelsResultSchema = discriminatedUnion("ok", [object({
40122
+ ok: literal(true),
40123
+ models: array(LlmModelInfoSchema)
40124
+ }), object({
40125
+ ok: literal(false),
40126
+ code: LlmListModelsErrorCodeSchema,
40127
+ message: string()
40128
+ })]);
40017
40129
  var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
40018
40130
  var LlmDefaultSchema = object({
40019
40131
  selector: LlmDefaultSelectorSchema,
@@ -40113,7 +40225,10 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
40113
40225
  kind: "mutation",
40114
40226
  auth: "admin",
40115
40227
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
40116
- }), method(ProfileRefInputSchema, array(string())), method(object({}), array(LlmDefaultSchema)), method(object({
40228
+ }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
40229
+ kind: "mutation",
40230
+ auth: "admin"
40231
+ }), method(object({}), array(LlmDefaultSchema)), method(object({
40117
40232
  selector: LlmDefaultSelectorSchema,
40118
40233
  profileId: string().nullable()
40119
40234
  }), _void(), {
@@ -64001,26 +64116,6 @@ var ApiKeySummarySchema = object({
64001
64116
  createdAt: number(),
64002
64117
  lastUsedAt: number().optional()
64003
64118
  });
64004
- var ScopedTokenSummarySchema = object({
64005
- id: string(),
64006
- userId: string(),
64007
- name: string(),
64008
- tokenPrefix: string(),
64009
- scopes: array(TokenScopeSchema),
64010
- expiresAt: number().nullish(),
64011
- lastUsedAt: number().nullish(),
64012
- createdAt: number()
64013
- });
64014
- var CreateScopedTokenInputSchema = object({
64015
- userId: string(),
64016
- name: string(),
64017
- scopes: array(TokenScopeSchema),
64018
- expiresAt: number().optional()
64019
- });
64020
- var CreateScopedTokenResultSchema = object({
64021
- token: string(),
64022
- record: ScopedTokenSummarySchema
64023
- });
64024
64119
  var OauthSessionSummarySchema = object({
64025
64120
  id: string(),
64026
64121
  userId: string(),
@@ -64042,11 +64137,11 @@ var TotpStatusSchema = object({
64042
64137
  confirmedAt: number().nullable()
64043
64138
  });
64044
64139
  /**
64045
- * user-management — singleton capability for user accounts, API keys,
64046
- * and scoped tokens.
64140
+ * user-management — singleton capability for user accounts and the
64141
+ * legacy API-key rows.
64047
64142
  *
64048
64143
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64049
- * — the subset check on `setUserScopes` / `createScopedToken` is moot
64144
+ * — the subset check on `setUserScopes` is moot
64050
64145
  * because non-admins never reach these. If/when we open non-admin
64051
64146
  * delegation, structural caller-scope subset check goes inside the
64052
64147
  * provider.
@@ -64103,15 +64198,7 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64103
64198
  kind: "mutation",
64104
64199
  auth: "admin",
64105
64200
  access: "delete"
64106
- }), method(CreateScopedTokenInputSchema, CreateScopedTokenResultSchema, {
64107
- kind: "mutation",
64108
- auth: "admin",
64109
- access: "create"
64110
- }), method(object({ id: string() }), object({ success: literal(true) }), {
64111
- kind: "mutation",
64112
- auth: "admin",
64113
- access: "delete"
64114
- }), method(object({ token: string() }), ScopedTokenSummarySchema.nullable(), { access: "view" }), method(object({ userId: string() }), array(ScopedTokenSummarySchema), { auth: "admin" }), method(object({ userId: string() }), TotpSetupResultSchema, {
64201
+ }), method(object({ userId: string() }), TotpSetupResultSchema, {
64115
64202
  kind: "mutation",
64116
64203
  auth: "admin",
64117
64204
  access: "create"
@@ -70201,7 +70288,7 @@ Object.freeze({
70201
70288
  capName: "llm",
70202
70289
  capScope: "system",
70203
70290
  addonId: null,
70204
- access: "view"
70291
+ access: "create"
70205
70292
  },
70206
70293
  "llm.listNodeModels": {
70207
70294
  capName: "llm",
@@ -74865,12 +74952,6 @@ Object.freeze({
74865
74952
  addonId: null,
74866
74953
  access: "create"
74867
74954
  },
74868
- "userManagement.createScopedToken": {
74869
- capName: "user-management",
74870
- capScope: "system",
74871
- addonId: null,
74872
- access: "create"
74873
- },
74874
74955
  "userManagement.createUser": {
74875
74956
  capName: "user-management",
74876
74957
  capScope: "system",
@@ -74919,12 +75000,6 @@ Object.freeze({
74919
75000
  addonId: null,
74920
75001
  access: "view"
74921
75002
  },
74922
- "userManagement.listScopedTokens": {
74923
- capName: "user-management",
74924
- capScope: "system",
74925
- addonId: null,
74926
- access: "view"
74927
- },
74928
75003
  "userManagement.listUsers": {
74929
75004
  capName: "user-management",
74930
75005
  capScope: "system",
@@ -74979,12 +75054,6 @@ Object.freeze({
74979
75054
  addonId: null,
74980
75055
  access: "delete"
74981
75056
  },
74982
- "userManagement.revokeScopedToken": {
74983
- capName: "user-management",
74984
- capScope: "system",
74985
- addonId: null,
74986
- access: "delete"
74987
- },
74988
75057
  "userManagement.setupTotp": {
74989
75058
  capName: "user-management",
74990
75059
  capScope: "system",
@@ -75015,12 +75084,6 @@ Object.freeze({
75015
75084
  addonId: null,
75016
75085
  access: "view"
75017
75086
  },
75018
- "userManagement.validateScopedToken": {
75019
- capName: "user-management",
75020
- capScope: "system",
75021
- addonId: null,
75022
- access: "view"
75023
- },
75024
75087
  "userManagement.verifyTotp": {
75025
75088
  capName: "user-management",
75026
75089
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-mqtt-ha",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Home Assistant MQTT discovery import provider for CamStack — adopts entities published on homeassistant/+/+/config",
5
5
  "keywords": [
6
6
  "camstack",