@camstack/types 1.2.260 → 1.2.261

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 (48) hide show
  1. package/dist/addon/base-addon.d.ts +9 -1
  2. package/dist/addon.js +4 -6
  3. package/dist/addon.mjs +4 -6
  4. package/dist/capabilities/capability-definition.d.ts +9 -0
  5. package/dist/capabilities/custom-model-registry.cap.d.ts +18 -0
  6. package/dist/capabilities/device-extension.cap.d.ts +370 -0
  7. package/dist/capabilities/device-manager.cap.d.ts +45 -5
  8. package/dist/capabilities/doorbell.cap.d.ts +41 -0
  9. package/dist/capabilities/embedding-encoder.cap.d.ts +175 -0
  10. package/dist/capabilities/index.d.ts +15 -12
  11. package/dist/capabilities/llm-runtime.cap.d.ts +4 -4
  12. package/dist/capabilities/llm-shared.d.ts +6 -6
  13. package/dist/capabilities/llm.cap.d.ts +6 -6
  14. package/dist/capabilities/model-convert.cap.d.ts +9 -0
  15. package/dist/capabilities/model-distributor.cap.d.ts +18 -0
  16. package/dist/capabilities/notification-rules.cap.d.ts +32 -14
  17. package/dist/capabilities/osd-manager.cap.d.ts +6 -6
  18. package/dist/capabilities/pipeline-analytics.cap.d.ts +80 -2
  19. package/dist/capabilities/pipeline-orchestrator.cap.d.ts +62 -1
  20. package/dist/capabilities/pipeline-runner.cap.d.ts +24 -0
  21. package/dist/capabilities/vector-store.cap.d.ts +14 -0
  22. package/dist/device-extension/index.d.ts +3 -0
  23. package/dist/device-extension/slot-descriptor.d.ts +62 -0
  24. package/dist/device-extension/slot-provider.d.ts +68 -0
  25. package/dist/generated/addon-api.d.ts +50 -0
  26. package/dist/generated/capability-router-map.d.ts +5 -2
  27. package/dist/generated/collection-array-methods.d.ts +1 -1
  28. package/dist/generated/device-proxy.d.ts +7 -7
  29. package/dist/generated/device-scoped-caps.d.ts +1 -1
  30. package/dist/generated/extension-slots.d.ts +39 -0
  31. package/dist/generated/method-access-map.d.ts +1 -1
  32. package/dist/generated/method-device-selectors.d.ts +1 -1
  33. package/dist/generated/system-proxy.d.ts +4 -2
  34. package/dist/index.d.ts +4 -1
  35. package/dist/index.js +1439 -475
  36. package/dist/index.mjs +1379 -476
  37. package/dist/interfaces/addon.d.ts +41 -0
  38. package/dist/interfaces/event-bus.d.ts +10 -0
  39. package/dist/node.d.ts +1 -0
  40. package/dist/node.js +73 -7
  41. package/dist/node.mjs +73 -8
  42. package/dist/pipeline/cluster-model-scope.d.ts +59 -3
  43. package/dist/{sleep-BaRu0bS5.mjs → sleep-BXv0ZcRa.mjs} +49 -33
  44. package/dist/{sleep-BDYxE1ax.js → sleep-QxyLiUId.js} +54 -32
  45. package/dist/storage/atomic-write.d.ts +25 -0
  46. package/dist/types/clip-model.d.ts +64 -0
  47. package/dist/types/models.d.ts +18 -0
  48. package/package.json +1 -1
@@ -917,6 +917,40 @@ var BaseAddon = class {
917
917
  const node = normalizeNodeId(nodeId ?? this._ctx?.kernel?.localNodeId);
918
918
  return keys.size > 0 ? projectStore(raw, keys, node) : raw;
919
919
  }
920
+ /**
921
+ * Whether ONE global key of this addon's store was written, read three-way
922
+ * (D651). For a question a hydrated view cannot answer: `getGlobalSettings`
923
+ * reports `value ?? default`, so "the operator chose the default" and "nobody
924
+ * chose" look the same, and a failed read looks like both. A `perNode` key is
925
+ * not supported here: its stored name is scoped.
926
+ */
927
+ async readStoredGlobalKey(key) {
928
+ const read = this._ctx?.settings?.readAddonStoreResult;
929
+ if (read === void 0) return {
930
+ kind: "unreadable",
931
+ reason: "three-way-read-unavailable"
932
+ };
933
+ let result;
934
+ try {
935
+ result = await read.call(this._ctx?.settings);
936
+ } catch (err) {
937
+ return {
938
+ kind: "unreadable",
939
+ reason: "store-read-failed",
940
+ error: err instanceof Error ? err.message : String(err)
941
+ };
942
+ }
943
+ if (result.kind === "failed") return {
944
+ kind: "unreadable",
945
+ reason: "store-read-failed",
946
+ error: result.error
947
+ };
948
+ if (result.kind === "missing" || !Object.prototype.hasOwnProperty.call(result.value, key)) return { kind: "absent" };
949
+ return {
950
+ kind: "present",
951
+ value: result.value[key]
952
+ };
953
+ }
920
954
  async updateGlobalSettings(patch, nodeId) {
921
955
  const keys = this.perNodeKeys();
922
956
  const localNode = normalizeNodeId(this._ctx?.kernel?.localNodeId);
@@ -3560,6 +3594,11 @@ function createDeviceProxy(api, binding, opts) {
3560
3594
  getDeviceLiveContribution: (input) => dispatch("camera-grid-layout", "cameraGridLayout", "getDeviceLiveContribution", "query", input),
3561
3595
  applyDeviceSettingsPatch: (input) => dispatch("camera-grid-layout", "cameraGridLayout", "applyDeviceSettingsPatch", "mutation", input)
3562
3596
  },
3597
+ cameraPipelineConfig: {
3598
+ getDeviceSettingsContribution: (input) => dispatch("camera-pipeline-config", "cameraPipelineConfig", "getDeviceSettingsContribution", "query", input),
3599
+ getDeviceLiveContribution: (input) => dispatch("camera-pipeline-config", "cameraPipelineConfig", "getDeviceLiveContribution", "query", input),
3600
+ applyDeviceSettingsPatch: (input) => dispatch("camera-pipeline-config", "cameraPipelineConfig", "applyDeviceSettingsPatch", "mutation", input)
3601
+ },
3563
3602
  cameraStreams: {
3564
3603
  getCameraStreams: (input) => dispatch("camera-streams", "cameraStreams", "getCameraStreams", "query", input),
3565
3604
  getBrokerStreams: (input) => dispatch("camera-streams", "cameraStreams", "getBrokerStreams", "query", input),
@@ -3619,6 +3658,12 @@ function createDeviceProxy(api, binding, opts) {
3619
3658
  releaseDevice: (input) => dispatch("device-discovery", "deviceDiscovery", "releaseDevice", "mutation", input),
3620
3659
  getStatus: (input) => dispatch("device-discovery", "deviceDiscovery", "getStatus", "query", input)
3621
3660
  },
3661
+ deviceExtension: {
3662
+ listSources: (input) => dispatch("device-extension", "deviceExtension", "listSources", "query", input),
3663
+ listSlots: (input) => dispatch("device-extension", "deviceExtension", "listSlots", "query", input),
3664
+ listCandidates: (input) => dispatch("device-extension", "deviceExtension", "listCandidates", "query", input),
3665
+ setSlot: (input) => dispatch("device-extension", "deviceExtension", "setSlot", "mutation", input)
3666
+ },
3622
3667
  deviceOps: {
3623
3668
  getStreamSources: (input) => dispatch("device-ops", "deviceOps", "getStreamSources", "query", input),
3624
3669
  getConfigEntries: (input) => dispatch("device-ops", "deviceOps", "getConfigEntries", "query", input),
@@ -3737,30 +3782,6 @@ function createDeviceProxy(api, binding, opts) {
3737
3782
  getStatus: (input) => dispatch("navigation", "navigation", "getStatus", "query", input)
3738
3783
  },
3739
3784
  networkLink: { getStatus: (input) => dispatch("network-link", "networkLink", "getStatus", "query", input) },
3740
- notificationRules: {
3741
- listRules: (input) => dispatch("notification-rules", "notificationRules", "listRules", "query", input),
3742
- getRule: (input) => dispatch("notification-rules", "notificationRules", "getRule", "query", input),
3743
- createRule: (input) => dispatch("notification-rules", "notificationRules", "createRule", "mutation", input),
3744
- updateRule: (input) => dispatch("notification-rules", "notificationRules", "updateRule", "mutation", input),
3745
- deleteRule: (input) => dispatch("notification-rules", "notificationRules", "deleteRule", "mutation", input),
3746
- setRuleEnabled: (input) => dispatch("notification-rules", "notificationRules", "setRuleEnabled", "mutation", input),
3747
- getClipRetentionAsks: (input) => dispatch("notification-rules", "notificationRules", "getClipRetentionAsks", "query", input),
3748
- listDeviceMutes: (input) => dispatch("notification-rules", "notificationRules", "listDeviceMutes", "query", input),
3749
- setDeviceMuted: (input) => dispatch("notification-rules", "notificationRules", "setDeviceMuted", "mutation", input),
3750
- testRule: (input) => dispatch("notification-rules", "notificationRules", "testRule", "mutation", input),
3751
- previewStateSummary: (input) => dispatch("notification-rules", "notificationRules", "previewStateSummary", "mutation", input),
3752
- getConditionCatalog: (input) => dispatch("notification-rules", "notificationRules", "getConditionCatalog", "query", input),
3753
- getTemplateCatalog: (input) => dispatch("notification-rules", "notificationRules", "getTemplateCatalog", "query", input),
3754
- previewTemplate: (input) => dispatch("notification-rules", "notificationRules", "previewTemplate", "mutation", input),
3755
- getHistory: (input) => dispatch("notification-rules", "notificationRules", "getHistory", "query", input),
3756
- getRuleLastRuns: (input) => dispatch("notification-rules", "notificationRules", "getRuleLastRuns", "query", input),
3757
- resolveArtifactUrl: (input) => dispatch("notification-rules", "notificationRules", "resolveArtifactUrl", "query", input),
3758
- listSnoozes: (input) => dispatch("notification-rules", "notificationRules", "listSnoozes", "query", input),
3759
- createSnooze: (input) => dispatch("notification-rules", "notificationRules", "createSnooze", "mutation", input),
3760
- cancelSnooze: (input) => dispatch("notification-rules", "notificationRules", "cancelSnooze", "mutation", input),
3761
- getAlarmConfig: (input) => dispatch("notification-rules", "notificationRules", "getAlarmConfig", "query", input),
3762
- setAlarmConfig: (input) => dispatch("notification-rules", "notificationRules", "setAlarmConfig", "mutation", input)
3763
- },
3764
3785
  notifier: {
3765
3786
  send: (input) => dispatch("notifier", "notifier", "send", "mutation", input),
3766
3787
  cancel: (input) => dispatch("notifier", "notifier", "cancel", "mutation", input),
@@ -4018,11 +4039,6 @@ function createDeviceProxy(api, binding, opts) {
4018
4039
  updateDeviceSettings: (input) => dispatchSystem("addonSettings", "updateDeviceSettings", "mutation", input)
4019
4040
  },
4020
4041
  audioAnalyzer: { detachDevice: (input) => dispatchSystem("audioAnalyzer", "detachDevice", "mutation", input) },
4021
- cameraPipelineConfig: {
4022
- getDeviceSettingsContribution: (input) => dispatchSystem("cameraPipelineConfig", "getDeviceSettingsContribution", "query", input),
4023
- getDeviceLiveContribution: (input) => dispatchSystem("cameraPipelineConfig", "getDeviceLiveContribution", "query", input),
4024
- applyDeviceSettingsPatch: (input) => dispatchSystem("cameraPipelineConfig", "applyDeviceSettingsPatch", "mutation", input)
4025
- },
4026
4042
  deviceAdoption: { getStatus: (input) => dispatchSystem("deviceAdoption", "getStatus", "query", input) },
4027
4043
  deviceExport: {
4028
4044
  getDeviceSettingsContribution: (input) => dispatchSystem("deviceExport", "getDeviceSettingsContribution", "query", input),
@@ -4072,7 +4088,6 @@ function createDeviceProxy(api, binding, opts) {
4072
4088
  getDeviceLiveContribution: (input) => dispatchSystem("deviceManager", "getDeviceLiveContribution", "query", input),
4073
4089
  applyDeviceSettingsPatch: (input) => dispatchSystem("deviceManager", "applyDeviceSettingsPatch", "mutation", input)
4074
4090
  },
4075
- deviceProvider: { reloadDevice: (input) => dispatchSystem("deviceProvider", "reloadDevice", "mutation", input) },
4076
4091
  deviceState: {
4077
4092
  getSnapshot: (input) => dispatchSystem("deviceState", "getSnapshot", "query", input),
4078
4093
  getCapSlice: (input) => dispatchSystem("deviceState", "getCapSlice", "query", input),
@@ -4086,6 +4101,7 @@ function createDeviceProxy(api, binding, opts) {
4086
4101
  getDeviceStats: (input) => dispatchSystem("networkQuality", "getDeviceStats", "query", input),
4087
4102
  reportClientStats: (input) => dispatchSystem("networkQuality", "reportClientStats", "mutation", input)
4088
4103
  },
4104
+ notificationRules: { setDeviceMuted: (input) => dispatchSystem("notificationRules", "setDeviceMuted", "mutation", input) },
4089
4105
  osdManager: {
4090
4106
  getDeviceOsd: (input) => dispatchSystem("osdManager", "getDeviceOsd", "query", input),
4091
4107
  getSourceCatalog: (input) => dispatchSystem("osdManager", "getSourceCatalog", "query", input),
@@ -4108,7 +4124,6 @@ function createDeviceProxy(api, binding, opts) {
4108
4124
  assignAudio: (input) => dispatchSystem("pipelineOrchestrator", "assignAudio", "mutation", input),
4109
4125
  unassignAudio: (input) => dispatchSystem("pipelineOrchestrator", "unassignAudio", "mutation", input),
4110
4126
  getAudioAssignment: (input) => dispatchSystem("pipelineOrchestrator", "getAudioAssignment", "query", input),
4111
- getAudioAssignments: (input) => dispatchSystem("pipelineOrchestrator", "getAudioAssignments", "query", input),
4112
4127
  getCameraSettings: (input) => dispatchSystem("pipelineOrchestrator", "getCameraSettings", "query", input),
4113
4128
  setCameraStepToggle: (input) => dispatchSystem("pipelineOrchestrator", "setCameraStepToggle", "mutation", input),
4114
4129
  getCameraStepOverrides: (input) => dispatchSystem("pipelineOrchestrator", "getCameraStepOverrides", "query", input),
@@ -4180,7 +4195,7 @@ function createDeviceProxy(api, binding, opts) {
4180
4195
  * can answer "may a rule actuate this?" without importing the schema barrel
4181
4196
  * (~144MB RSS per runner, D28).
4182
4197
  *
4183
- * Coverage: 87 device-scoped capabilities.
4198
+ * Coverage: 88 device-scoped capabilities.
4184
4199
  */
4185
4200
  var DEVICE_SCOPED_CAPS = new Set([
4186
4201
  "accessories",
@@ -4210,6 +4225,7 @@ var DEVICE_SCOPED_CAPS = new Set([
4210
4225
  "detection-pipeline",
4211
4226
  "device-admin-link",
4212
4227
  "device-discovery",
4228
+ "device-extension",
4213
4229
  "device-ops",
4214
4230
  "device-status",
4215
4231
  "doorbell",
@@ -4949,6 +4965,12 @@ Object.defineProperty(exports, "normalizeAddonInitResult", {
4949
4965
  return normalizeAddonInitResult;
4950
4966
  }
4951
4967
  });
4968
+ Object.defineProperty(exports, "normalizeNodeId", {
4969
+ enumerable: true,
4970
+ get: function() {
4971
+ return normalizeNodeId;
4972
+ }
4973
+ });
4952
4974
  Object.defineProperty(exports, "optionalMethod", {
4953
4975
  enumerable: true,
4954
4976
  get: function() {
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Replace `filePath` with `data` so that a concurrent reader sees EITHER the
3
+ * old complete file OR the new complete file — never a prefix (D654).
4
+ *
5
+ * A plain `writeFile` truncates the target and then writes it in chunks, so a
6
+ * reader in between gets a torn file: a fixed-path single-instance media kind
7
+ * (`lastFrame`, `lastSceneFrame`) is overwritten every roll while a
8
+ * notification may be reading it. Here the bytes go to a temp file in the SAME
9
+ * directory (same filesystem, so the rename cannot degrade to a copy), and a
10
+ * `rename` swaps it in — atomic on POSIX. A reader that already opened the old
11
+ * file keeps reading the old inode to the end.
12
+ *
13
+ * The temp name is DOT-prefixed so every directory scan that skips dot entries
14
+ * (occupancy, D327) never counts it; it is removed on any failure. A process
15
+ * killed between the write and the rename leaves one `.<name>.<uuid>.tmp`.
16
+ *
17
+ * Windows: a rename over a file another process holds open can fail with
18
+ * EPERM/EACCES/EBUSY. It is retried briefly and then falls back to copying the
19
+ * temp over the target — non-atomic, exactly the pre-D654 behaviour, rather
20
+ * than losing the write.
21
+ *
22
+ * Cost: one extra `rename` (and, on failure, one `rm`) per write — a metadata
23
+ * operation, independent of the payload size.
24
+ */
25
+ export declare function writeFileAtomic(filePath: string, data: Uint8Array): Promise<void>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * A CLIP model's feature-space contract — what every consumer of its vectors
3
+ * must agree on, carried BY THE MODEL rather than re-derived by each consumer.
4
+ *
5
+ * ## Why this lives on the catalog entry
6
+ *
7
+ * Until 2026-09-26 each fact was hard-coded where it was used: the text window
8
+ * (77) and pad id (0) in `text_encoder_inference.py`, the index name
9
+ * (`object-clip`) in the object-embedding store, the "is this a CLIP vector"
10
+ * test as `embeddingModelId.startsWith('mobileclip-')`, the search floor (0.2)
11
+ * in the cap default, and the dimension (512) behind a `getModelMeta` that fell
12
+ * back to MobileCLIP for any id it did not know. Every one of those is wrong for
13
+ * the next model, and each one failed SILENTLY for SigLIP2 in the 2026-09-26
14
+ * spike: vectors dropped before the store with no log, 768-d queries truncated
15
+ * to 512 and ranked as garbage, 97% of true matches under the 0.2 floor (D649).
16
+ *
17
+ * A model now declares its own contract here, and a model with no `clip` block
18
+ * is not a CLIP model to any consumer. That is also the seam Model Studio uses
19
+ * for a user-supplied CLIP model: its registry row carries the same block.
20
+ */
21
+ import { z } from 'zod';
22
+ /**
23
+ * `object-clip` (the historical MobileCLIP index, 512-d) or
24
+ * `object-clip-<model>`. Lower-case and dash-only so the sqlite-vec table name
25
+ * derived from it (`vec_` + non-word → `_`) cannot collide with another index's.
26
+ */
27
+ export declare const CLIP_VECTOR_INDEX_PATTERN: RegExp;
28
+ export declare const ClipModelMetaSchema: z.ZodObject<{
29
+ textModelId: z.ZodString;
30
+ embeddingDim: z.ZodNumber;
31
+ vectorIndex: z.ZodString;
32
+ tokenizerFile: z.ZodString;
33
+ contextLength: z.ZodNumber;
34
+ padId: z.ZodNumber;
35
+ searchMinScore: z.ZodNumber;
36
+ }, z.core.$strip>;
37
+ export type ClipModelMeta = z.infer<typeof ClipModelMetaSchema>;
38
+ /**
39
+ * Model-relative search strictness. The operator picks how picky, the model
40
+ * says what that means in its own cosine band. On MobileCLIP (floor 0.2) these
41
+ * reproduce the admin UI's historical absolute presets 0.20 / 0.25 / 0.30.
42
+ */
43
+ export declare const CLIP_SEARCH_STRICTNESS: readonly ["loose", "balanced", "strict"];
44
+ export declare const ClipSearchStrictnessSchema: z.ZodEnum<{
45
+ loose: "loose";
46
+ balanced: "balanced";
47
+ strict: "strict";
48
+ }>;
49
+ export type ClipSearchStrictness = z.infer<typeof ClipSearchStrictnessSchema>;
50
+ export declare const CLIP_STRICTNESS_FACTOR: Readonly<Record<ClipSearchStrictness, number>>;
51
+ /** What a search asked for. Both absent ⇒ the model's own floor. */
52
+ export interface ClipSearchFloorRequest {
53
+ /** An ABSOLUTE cosine floor. Wins when present — the caller named a number. */
54
+ readonly minScore?: number;
55
+ readonly strictness?: ClipSearchStrictness;
56
+ }
57
+ /**
58
+ * The cosine floor a search runs with.
59
+ *
60
+ * An explicit `minScore` is honoured verbatim: it is a number a caller chose,
61
+ * and silently rescaling it would make the same URL mean different things on
62
+ * two installs. Everything else is relative to the model.
63
+ */
64
+ export declare function resolveClipSearchMinScore(meta: Pick<ClipModelMeta, 'searchMinScore'>, request: ClipSearchFloorRequest): number;
@@ -274,6 +274,15 @@ export declare const ModelCatalogEntrySchema: z.ZodObject<{
274
274
  }>>;
275
275
  preserveOriginal: z.ZodBoolean;
276
276
  }, z.core.$strip>>;
277
+ clip: z.ZodOptional<z.ZodObject<{
278
+ textModelId: z.ZodString;
279
+ embeddingDim: z.ZodNumber;
280
+ vectorIndex: z.ZodString;
281
+ tokenizerFile: z.ZodString;
282
+ contextLength: z.ZodNumber;
283
+ padId: z.ZodNumber;
284
+ searchMinScore: z.ZodNumber;
285
+ }, z.core.$strip>>;
277
286
  }, z.core.$strip>;
278
287
  export type ModelCatalogEntry = z.infer<typeof ModelCatalogEntrySchema>;
279
288
  export interface DetectionModel {
@@ -515,6 +524,15 @@ export declare const ConvertResultSchema: z.ZodObject<{
515
524
  }>>;
516
525
  preserveOriginal: z.ZodBoolean;
517
526
  }, z.core.$strip>>;
527
+ clip: z.ZodOptional<z.ZodObject<{
528
+ textModelId: z.ZodString;
529
+ embeddingDim: z.ZodNumber;
530
+ vectorIndex: z.ZodString;
531
+ tokenizerFile: z.ZodString;
532
+ contextLength: z.ZodNumber;
533
+ padId: z.ZodNumber;
534
+ searchMinScore: z.ZodNumber;
535
+ }, z.core.$strip>>;
518
536
  }, z.core.$strip>;
519
537
  artifacts: z.ZodReadonly<z.ZodArray<z.ZodObject<{
520
538
  format: z.ZodEnum<{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.260",
3
+ "version": "1.2.261",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",