@camstack/types 1.1.32 → 1.1.34

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 (54) hide show
  1. package/dist/addon.js +1 -1
  2. package/dist/addon.mjs +1 -1
  3. package/dist/capabilities/addons.cap.d.ts +1 -1
  4. package/dist/capabilities/alerts.cap.d.ts +5 -5
  5. package/dist/capabilities/camera-streams.cap.d.ts +5 -5
  6. package/dist/capabilities/cap-router-predicates.d.ts +32 -0
  7. package/dist/capabilities/capability-definition.d.ts +18 -13
  8. package/dist/capabilities/consumables.cap.d.ts +1 -1
  9. package/dist/capabilities/custom-model-registry.cap.d.ts +38 -0
  10. package/dist/capabilities/index.d.ts +8 -15
  11. package/dist/capabilities/integrations.cap.d.ts +1 -1
  12. package/dist/capabilities/model-convert.cap.d.ts +22 -3
  13. package/dist/capabilities/model-distributor.cap.d.ts +38 -0
  14. package/dist/capabilities/network-quality.cap.d.ts +1 -1
  15. package/dist/capabilities/nodes.cap.d.ts +1 -1
  16. package/dist/capabilities/pipeline-executor.cap.d.ts +161 -8
  17. package/dist/capabilities/pipeline-orchestrator.cap.d.ts +87 -44
  18. package/dist/capabilities/pipeline-runner.cap.d.ts +10 -69
  19. package/dist/capabilities/snapshot.cap.d.ts +3 -3
  20. package/dist/capabilities/stream-broker.cap.d.ts +9 -1
  21. package/dist/capabilities/system.cap.d.ts +1 -1
  22. package/dist/capabilities/toast.cap.d.ts +1 -1
  23. package/dist/capabilities/webrtc-session.cap.d.ts +15 -1
  24. package/dist/device/index.d.ts +2 -0
  25. package/dist/device/reachability-poll.d.ts +90 -0
  26. package/dist/encode-profile.d.ts +2 -2
  27. package/dist/enums/event-category.d.ts +12 -0
  28. package/dist/generated/addon-api.d.ts +771 -643
  29. package/dist/generated/capability-router-map.d.ts +4 -16
  30. package/dist/generated/device-proxy.d.ts +0 -2
  31. package/dist/generated/method-access-map.d.ts +1 -1
  32. package/dist/generated/system-proxy.d.ts +2 -2
  33. package/dist/index.d.ts +3 -3
  34. package/dist/index.js +568 -350
  35. package/dist/index.mjs +551 -344
  36. package/dist/interfaces/capability.d.ts +0 -7
  37. package/dist/interfaces/event-bus.d.ts +9 -0
  38. package/dist/interfaces/pipeline-executor-capability.d.ts +14 -1
  39. package/dist/interfaces/pipeline-runner-capability.d.ts +11 -11
  40. package/dist/interfaces/recording-config.d.ts +2 -2
  41. package/dist/{sleep-CZDdRBua.mjs → sleep-Cc14_yxc.mjs} +12 -4
  42. package/dist/{sleep-Dirr8nGw.js → sleep-DmP-uxoe.js} +12 -4
  43. package/dist/types/agent-pipeline-settings.d.ts +18 -6
  44. package/dist/types/camera-pipeline.d.ts +17 -3
  45. package/dist/types/model-variant-groups.d.ts +100 -0
  46. package/dist/types/models.d.ts +63 -3
  47. package/package.json +1 -1
  48. package/dist/capabilities/restreamer.cap.d.ts +0 -54
  49. package/dist/capabilities/snapshot-provider.cap.d.ts +0 -43
  50. package/dist/capabilities/streaming-engine.cap.d.ts +0 -61
  51. package/dist/capabilities/webrtc.cap.d.ts +0 -75
  52. package/dist/interfaces/restreamer.d.ts +0 -23
  53. package/dist/interfaces/streaming.d.ts +0 -28
  54. package/dist/interfaces/webrtc-provider.d.ts +0 -34
@@ -11,10 +11,7 @@ import type { ILogDestination } from './logging.js';
11
11
  import type { IPipelineExecutorProvider } from './pipeline-executor-capability.js';
12
12
  import type { IPipelineOrchestratorProvider } from './pipeline-orchestrator-capability.js';
13
13
  import type { IPipelineRunnerProvider } from './pipeline-runner-capability.js';
14
- import type { IRestreamer } from './restreamer.js';
15
14
  import type { IEmbeddingsBackend, ISettingsBackend } from './storage.js';
16
- import type { IStreamingEngine } from './streaming.js';
17
- import type { IWebRtcProvider } from './webrtc-provider.js';
18
15
  /**
19
16
  * Pipeline step capability — each step is a separate capability
20
17
  * named `pipeline-step:{stepId}` (e.g., `pipeline-step:object-detection`).
@@ -119,8 +116,6 @@ export interface CapabilityInfo {
119
116
  export interface CapabilityProviderMap {
120
117
  storage: InferProvider<typeof import('../capabilities/storage.cap.js').storageCapability>;
121
118
  'log-destination': ILogDestination;
122
- restreamer: IRestreamer;
123
- webrtc: IWebRtcProvider;
124
119
  'stream-broker': InferProvider<typeof streamBrokerCapability>;
125
120
  'addon-pages': InferProvider<typeof import('../capabilities/addon-pages.cap.js').addonPagesCapability>;
126
121
  'addon-pages-source': IAddonPageProvider;
@@ -143,7 +138,6 @@ export interface CapabilityProviderMap {
143
138
  alerts: InferProvider<typeof import('../capabilities/alerts.cap.js').alertsCapability>;
144
139
  backup: InferProvider<typeof import('../capabilities/backup.cap.js').backupCapability>;
145
140
  'network-access': InferProvider<typeof import('../capabilities/network-access.cap.js').networkAccessCapability>;
146
- 'streaming-engine': IStreamingEngine;
147
141
  'advanced-notifier': InferProvider<typeof import('../capabilities/advanced-notifier.cap.js').advancedNotifierCapability>;
148
142
  'pipeline-executor': IPipelineExecutorProvider;
149
143
  'detection-pipeline': InferProvider<typeof import('../capabilities/detection-pipeline.cap.js').detectionPipelineCapability>;
@@ -159,7 +153,6 @@ export interface CapabilityProviderMap {
159
153
  'settings-store': ISettingsBackend;
160
154
  embeddings: IEmbeddingsBackend;
161
155
  snapshot: ISnapshotOrchestrator;
162
- 'snapshot-provider': InferProvider<typeof import('../capabilities/snapshot-provider.cap.js').snapshotProviderCapability>;
163
156
  'metrics-provider': InferProvider<typeof import('../capabilities/metrics-provider.cap.js').metricsProviderCapability>;
164
157
  'camera-streams': InferProvider<typeof import('../capabilities/camera-streams.cap.js').cameraStreamsCapability>;
165
158
  'webrtc-session': InferProvider<typeof import('../capabilities/webrtc-session.cap.js').webrtcSessionCapability>;
@@ -662,6 +662,15 @@ export interface EventCatalog {
662
662
  readonly deviceId: number;
663
663
  readonly config: CameraPipelineConfig;
664
664
  };
665
+ /**
666
+ * Cluster camera-source owner (`clusterRoles.ingestNode`) resolved/changed.
667
+ * Pushed by addon-pipeline-orchestrator on every node-capability refresh so
668
+ * the stream-broker gates physical-broker creation on the current owner
669
+ * without a per-`ensureBroker` `getIngestOwner` query.
670
+ */
671
+ 'pipeline.ingest-owner-changed': {
672
+ readonly ownerNodeId: string;
673
+ };
665
674
  /**
666
675
  * Periodic per-runner load snapshot (~1 Hz). Replaces UI polling on
667
676
  * `pipelineRunner.getLocalLoad`. UI subscribes per agent node.
@@ -7,7 +7,7 @@ import type { FrameResult, DetectorOutput } from '../types/detection.js';
7
7
  import type { ConfigUISchema } from './config-ui.js';
8
8
  import type { InferenceCapabilities } from './inference-capabilities.js';
9
9
  import type { IAddonResolver } from './pipeline-runner.js';
10
- import type { EngineProvisioning } from '../capabilities/pipeline-executor.cap.js';
10
+ import type { EngineProvisioning, PipelineValidationResult } from '../capabilities/pipeline-executor.cap.js';
11
11
  /**
12
12
  * Step configuration for pipeline execution — no runtime/backend (comes
13
13
  * from engine). Phase 7 (settings redesign) removed the generic
@@ -81,6 +81,19 @@ export interface IPipelineExecutorProvider {
81
81
  getGlobalSteps(): Promise<PipelineDefaultStep[] | null>;
82
82
  /** Get the runner-ready pipeline config */
83
83
  getGlobalPipelineConfig(): Promise<PipelineConfig | null>;
84
+ /**
85
+ * Gate B (pre-init config-correctness gate). PURE COMPUTE against this
86
+ * node's `currentEngine.format` — resolves `steps` the same way the
87
+ * runtime dispatch path would and reports what WOULD happen, WITHOUT
88
+ * writing any node-global state (the node-default `modelSubstitutions`
89
+ * map stays owned exclusively by the node-default tree resolver).
90
+ * Called by the orchestrator at attach time, node-pinned to the target
91
+ * node, so config problems surface before `pipelineRunner.attachCamera`
92
+ * rather than at the first per-frame resolve. Never throws.
93
+ */
94
+ validatePipeline(input: {
95
+ readonly steps: readonly PipelineStepInput[];
96
+ }): Promise<PipelineValidationResult>;
84
97
  /** Get the currently selected engine (bootstrap default on the node). */
85
98
  getSelectedEngine(): Promise<PipelineEngineChoice>;
86
99
  /**
@@ -1,5 +1,4 @@
1
1
  import type { OrchestratorMetrics, CameraMetrics } from './api-shared.js';
2
- import type { PipelineEngineChoice } from '../types/pipeline.js';
3
2
  import type { PipelineStepInputOutput } from '../capabilities/pipeline-executor.cap.js';
4
3
  import type { Zone } from '../capabilities/zones.cap.js';
5
4
  import type { PipelinePhaseMode } from '../device/device-profile.js';
@@ -8,11 +7,10 @@ import type { PipelinePhaseMode } from '../device/device-profile.js';
8
7
  * via `attachCamera`. Carries everything the runner needs to subscribe to
9
8
  * the local stream-broker and dispatch frames to motion / detection caps.
10
9
  *
11
- * Stateless-pipeline model: `engine`, `steps`, and `audio` travel with the
12
- * payload so the runner holds the full content in RAM for the lifetime of
13
- * the attach. Re-sent on rebalance, edit, or restart. The fields are
14
- * optional during the additive migration (Phase 1) — the runner treats
15
- * absent content as "no inference" until Phase 3 makes them required.
10
+ * Stateless-pipeline model: `steps` and `audio` travel with the payload so
11
+ * the runner holds the content in RAM for the lifetime of the attach.
12
+ * Re-sent on rebalance, edit, or restart. Engine is NOT carried: it is
13
+ * node-local, resolved by the executing runner at dispatch time.
16
14
  */
17
15
  export interface RunnerCameraConfig {
18
16
  readonly deviceId: number;
@@ -24,14 +22,16 @@ export interface RunnerCameraConfig {
24
22
  /** Motion sources that can activate the pipeline. At least one entry. */
25
23
  readonly motionSources: import('../capabilities/pipeline-runner.cap.js').MotionSources;
26
24
  readonly pipelineEnabled: boolean;
27
- /** Engine choice for video steps — Phase 1 optional, runner ignores until Phase 3. */
28
- readonly engine?: PipelineEngineChoice;
29
25
  /** Ordered tree of video steps — Phase 1 optional, runner ignores until Phase 3. */
30
26
  readonly steps?: readonly PipelineStepInputOutput[];
31
- /** Audio classification branch — Phase 1 optional, runner ignores until Phase 3. */
27
+ /**
28
+ * Audio classification branch — Phase 1 optional, runner ignores until
29
+ * Phase 3. `modelId` absent = model selection is data only; the
30
+ * executing node resolves its own format default at runtime
31
+ * (mirrors `CameraPipelineConfig.audio`).
32
+ */
32
33
  readonly audio?: {
33
- readonly engine: PipelineEngineChoice;
34
- readonly modelId: string;
34
+ readonly modelId?: string;
35
35
  readonly enabled: boolean;
36
36
  } | null;
37
37
  /**
@@ -42,8 +42,8 @@ export declare const RecordingModeSchema: z.ZodEnum<{
42
42
  }>;
43
43
  export type RecordingMode = z.infer<typeof RecordingModeSchema>;
44
44
  /**
45
- * First-class, authoritative per-camera storage mode — the netta choice the UI
46
- * reads directly (never inferred from `rules`):
45
+ * First-class, authoritative per-camera storage mode — the explicit choice the
46
+ * UI reads directly (never inferred from `rules`):
47
47
  * - `off` — not recording.
48
48
  * - `events` — record only around triggers (motion / audio threshold),
49
49
  * with pre/post-buffer.
@@ -250,6 +250,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
250
250
  */
251
251
  EventCategory["PipelineCameraUpdated"] = "pipeline.camera-updated";
252
252
  /**
253
+ * The cluster camera-source OWNER changed (`clusterRoles.ingestNode`).
254
+ * Emitted by addon-pipeline-orchestrator whenever it (re)derives node
255
+ * capabilities — at boot, on agent online/offline, and on an ingest-node
256
+ * flip. Carries the resolved `ownerNodeId`. The stream-broker consumes it to
257
+ * keep its ingest-owner-gate decision current WITHOUT a per-`ensureBroker`
258
+ * cross-process `getIngestOwner` query (push the authority's decision instead
259
+ * of polling it on the hot path). Idempotent state — re-emitted on every
260
+ * topology change, so a dropped event self-heals on the next one (plus the
261
+ * broker's long backstop reconcile query).
262
+ */
263
+ EventCategory["PipelineIngestOwnerChanged"] = "pipeline.ingest-owner-changed";
264
+ /**
253
265
  * Periodic snapshot of per-node pipeline-runner load
254
266
  * (`RunnerLocalLoad`). Emitted ~1Hz by every runner so UI dashboards
255
267
  * subscribe instead of polling `pipelineRunner.getLocalLoad`.
@@ -3566,10 +3578,6 @@ function createDeviceProxy(api, binding, opts) {
3566
3578
  getDeviceLiveContribution: (input) => dispatchSystem("recording", "getDeviceLiveContribution", "query", input),
3567
3579
  applyDeviceSettingsPatch: (input) => dispatchSystem("recording", "applyDeviceSettingsPatch", "mutation", input)
3568
3580
  },
3569
- snapshotProvider: {
3570
- supportsDevice: (input) => dispatchSystem("snapshotProvider", "supportsDevice", "query", input),
3571
- getSnapshot: (input) => dispatchSystem("snapshotProvider", "getSnapshot", "query", input)
3572
- },
3573
3581
  streamBroker: {
3574
3582
  publishCameraStream: (input) => dispatchSystem("streamBroker", "publishCameraStream", "mutation", input),
3575
3583
  retractCameraStream: (input) => dispatchSystem("streamBroker", "retractCameraStream", "mutation", input),
@@ -250,6 +250,18 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
250
250
  */
251
251
  EventCategory["PipelineCameraUpdated"] = "pipeline.camera-updated";
252
252
  /**
253
+ * The cluster camera-source OWNER changed (`clusterRoles.ingestNode`).
254
+ * Emitted by addon-pipeline-orchestrator whenever it (re)derives node
255
+ * capabilities — at boot, on agent online/offline, and on an ingest-node
256
+ * flip. Carries the resolved `ownerNodeId`. The stream-broker consumes it to
257
+ * keep its ingest-owner-gate decision current WITHOUT a per-`ensureBroker`
258
+ * cross-process `getIngestOwner` query (push the authority's decision instead
259
+ * of polling it on the hot path). Idempotent state — re-emitted on every
260
+ * topology change, so a dropped event self-heals on the next one (plus the
261
+ * broker's long backstop reconcile query).
262
+ */
263
+ EventCategory["PipelineIngestOwnerChanged"] = "pipeline.ingest-owner-changed";
264
+ /**
253
265
  * Periodic snapshot of per-node pipeline-runner load
254
266
  * (`RunnerLocalLoad`). Emitted ~1Hz by every runner so UI dashboards
255
267
  * subscribe instead of polling `pipelineRunner.getLocalLoad`.
@@ -3566,10 +3578,6 @@ function createDeviceProxy(api, binding, opts) {
3566
3578
  getDeviceLiveContribution: (input) => dispatchSystem("recording", "getDeviceLiveContribution", "query", input),
3567
3579
  applyDeviceSettingsPatch: (input) => dispatchSystem("recording", "applyDeviceSettingsPatch", "mutation", input)
3568
3580
  },
3569
- snapshotProvider: {
3570
- supportsDevice: (input) => dispatchSystem("snapshotProvider", "supportsDevice", "query", input),
3571
- getSnapshot: (input) => dispatchSystem("snapshotProvider", "getSnapshot", "query", input)
3572
- },
3573
3581
  streamBroker: {
3574
3582
  publishCameraStream: (input) => dispatchSystem("streamBroker", "publishCameraStream", "mutation", input),
3575
3583
  retractCameraStream: (input) => dispatchSystem("streamBroker", "retractCameraStream", "mutation", input),
@@ -23,10 +23,14 @@ import type { CameraPipelineConfig } from './camera-pipeline.js';
23
23
  * Every addon in the catalog gets one entry — whether enabled or not.
24
24
  * Operators edit these to pick models, tune settings, flip default
25
25
  * enabled state for their hardware.
26
+ *
27
+ * modelId present ONLY when the operator explicitly chose a model;
28
+ * absent = use this node's format default (resolved on-the-fly by the
29
+ * provider).
26
30
  */
27
31
  export interface AgentAddonConfig {
28
32
  readonly enabled: boolean;
29
- readonly modelId: string;
33
+ readonly modelId?: string;
30
34
  readonly settings: Readonly<Record<string, unknown>>;
31
35
  }
32
36
  /**
@@ -48,9 +52,9 @@ export interface CameraStepOverridePatch {
48
52
  * ownership moved to per-addon global settings (detection-pipeline,
49
53
  * decoder-nodeav/ffmpeg, audio-analyzer). What's left on the
50
54
  * orchestrator is the per-step defaults map (modelId / step settings)
51
- * consumed by the resolver. The authoritative engine triple is read
52
- * from the `detection-pipeline` addon's global settings via
53
- * `readDetectionPipelineEngine()`.
55
+ * consumed by the resolver. Engine is node-local each executing node
56
+ * resolves its own format default at dispatch time; it is never stored
57
+ * on these settings nor carried on the attach payload.
54
58
  */
55
59
  export interface AgentPipelineSettings {
56
60
  readonly addonDefaults: Readonly<Record<string, AgentAddonConfig>>;
@@ -81,6 +85,13 @@ export interface AgentPipelineSettings {
81
85
  readonly decode?: boolean;
82
86
  readonly audio?: boolean;
83
87
  readonly ingest?: boolean;
88
+ /**
89
+ * Operator override for the LAN host a cross-node decoder dials to reach
90
+ * THIS node's restream (Cluster UI). Absent → auto-detect: a remote runner
91
+ * falls back to its `CAMSTACK_HUB_URL`-derived host. Set only when the
92
+ * auto-detected address is wrong (multi-homed host, NAT, custom interface).
93
+ */
94
+ readonly reachableHost?: string;
84
95
  }
85
96
  /**
86
97
  * Per-camera pipeline settings. Sparse by design — a camera that has
@@ -108,12 +119,13 @@ export interface CameraPipelineSettings {
108
119
  * detection-pipeline addon's global settings. Operator picks steps
109
120
  * + audio model/enabled only. This keeps the override portable
110
121
  * across agent-moves and prevents a camera from being pinned to an
111
- * engine the agent doesn't host.
122
+ * engine the agent doesn't host. `modelId` absent = data-only model
123
+ * selection — the executing node resolves its own format default.
112
124
  */
113
125
  readonly pipelineByAgent?: Readonly<Record<string, {
114
126
  readonly steps: CameraPipelineConfig['steps'];
115
127
  readonly audio: {
116
- readonly modelId: string;
128
+ readonly modelId?: string;
117
129
  readonly enabled: boolean;
118
130
  } | null;
119
131
  }>>;
@@ -23,11 +23,25 @@ import type { PipelineEngineChoice } from './pipeline.js';
23
23
  * `audio-analyzer` not tied to this config.
24
24
  */
25
25
  export interface CameraPipelineConfig {
26
- readonly engine: PipelineEngineChoice;
26
+ /**
27
+ * Benchmark/template engine HINT ONLY — an explicit engine override the
28
+ * Image-Tester carries when saving a template. It is NEVER a live-dispatch
29
+ * field: the attach payload (`RunnerCameraConfig`) no longer carries an
30
+ * engine, so this value cannot reach a node. Engine is node-local — the
31
+ * executing runner resolves its own format default at dispatch time.
32
+ */
33
+ readonly engine?: PipelineEngineChoice;
27
34
  readonly steps: readonly PipelineStepInputOutput[];
28
35
  readonly audio?: {
29
- readonly engine: PipelineEngineChoice;
30
- readonly modelId: string;
36
+ /** Benchmark/template engine hint only — see `engine` above. Not dispatched. */
37
+ readonly engine?: PipelineEngineChoice;
38
+ /**
39
+ * Present ONLY when the operator explicitly chose an audio model;
40
+ * absent = use this node's format default (resolved on-the-fly by
41
+ * the provider). Mirrors `AgentAddonConfig.modelId` (Task 4/5 of the
42
+ * engine-node-local refactor — model selection is data only).
43
+ */
44
+ readonly modelId?: string;
31
45
  readonly enabled: boolean;
32
46
  /**
33
47
  * Audio-classifier step settings (`enabledAudioClasses`,
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Variant grouping for the model selector.
3
+ *
4
+ * The catalog is a FLAT list of `ModelCatalogEntry` (ids like `yolo26s`,
5
+ * `yolo26s-int8`) — that stays the source of truth for resolution, download and
6
+ * persistence. This module is a PRESENTATION overlay: it folds the flat list
7
+ * into a `family → tier → variant` tree so the UI can offer one grouped picker
8
+ * ("YOLO26" → "Small" → "Int8") instead of a flat dropdown of every
9
+ * size×quantization combination, and maps a grouped selection back to a flat
10
+ * model id.
11
+ *
12
+ * Only entries carrying `group` and NOT flagged `legacy` participate; legacy /
13
+ * ungrouped / custom models are never surfaced in the grouped selector (they
14
+ * stay reachable via the flat id when explicitly pinned).
15
+ */
16
+ import type { ModelFormat } from './models.js';
17
+ export type VariantPrecision = 'fp32' | 'int8';
18
+ export type VariantOptimization = 'standard' | 'fast';
19
+ /**
20
+ * Minimal structural shape the grouped selector needs. Both the full
21
+ * `ModelCatalogEntry` (config UI) and the reduced `PipelineModelOption`
22
+ * (pipeline/device steppers) satisfy it, so one grouped picker serves every
23
+ * surface. `formats` is read only for "which formats ship" + a size hint, so a
24
+ * loose `{ sizeMB }`-per-key map covers both the catalog's rich format entries
25
+ * and the schema's `{ downloaded, sizeMB }` entries.
26
+ */
27
+ export interface ModelVariantSource {
28
+ readonly id: string;
29
+ readonly name: string;
30
+ readonly legacy?: boolean;
31
+ readonly group?: {
32
+ readonly family: string;
33
+ readonly tier: string;
34
+ readonly precision?: VariantPrecision;
35
+ readonly optimization?: VariantOptimization;
36
+ readonly resolution?: number;
37
+ };
38
+ readonly formats: Readonly<Record<string, {
39
+ readonly sizeMB: number;
40
+ } | undefined>>;
41
+ }
42
+ /** One selectable variant of a tier (a single flat catalog entry). */
43
+ export interface ModelVariantOption {
44
+ readonly modelId: string;
45
+ readonly precision: VariantPrecision;
46
+ readonly optimization: VariantOptimization;
47
+ /**
48
+ * Input resolution (square side, px). `undefined` ⇒ the family's native
49
+ * resolution (640 for yolo26). Reduced values (320 / 256) are the reduced-
50
+ * input latency variants.
51
+ */
52
+ readonly resolution?: number;
53
+ /** Short chip label: `Standard` | `Int8` | `Fast` | `Fast · Int8`. */
54
+ readonly label: string;
55
+ /** Formats this variant ships (drives per-node availability). */
56
+ readonly formats: readonly ModelFormat[];
57
+ /** Smallest declared build size (MB) — a rough size hint for the chip. */
58
+ readonly sizeMB: number;
59
+ }
60
+ /** One size tier within a family (e.g. YOLO26 "Small"), with its variants. */
61
+ export interface ModelVariantTier {
62
+ readonly tier: string;
63
+ readonly label: string;
64
+ /** The fp32/standard base model id — the tier's canonical selection. */
65
+ readonly baseModelId: string;
66
+ readonly options: readonly ModelVariantOption[];
67
+ }
68
+ /** One model family (e.g. YOLO26), with its size tiers. */
69
+ export interface ModelVariantFamily {
70
+ readonly family: string;
71
+ readonly label: string;
72
+ readonly tiers: readonly ModelVariantTier[];
73
+ }
74
+ /**
75
+ * Fold a flat catalog into the `family → tier → variant` tree. Deterministic
76
+ * ordering: tiers by the canonical size ladder (unknown tiers appended
77
+ * alphabetically), variants standard-before-int8 and fast last.
78
+ */
79
+ export declare function buildModelVariantGroups(models: readonly ModelVariantSource[]): readonly ModelVariantFamily[];
80
+ /**
81
+ * Map a grouped selection back to a flat catalog model id. Returns `null` when
82
+ * no entry matches (the UI then falls back to the tier base / format default).
83
+ * `precision`/`optimization` default to `fp32`/`standard` (the base build).
84
+ */
85
+ export declare function resolveVariantModelId(models: readonly ModelVariantSource[], selection: {
86
+ readonly family: string;
87
+ readonly tier: string;
88
+ readonly precision?: VariantPrecision;
89
+ readonly optimization?: VariantOptimization;
90
+ /** `undefined` ⇒ the native-resolution build. */
91
+ readonly resolution?: number;
92
+ }): string | null;
93
+ /** Inverse: describe a flat model id as a grouped selection, or `null`. */
94
+ export declare function describeModelVariant(models: readonly ModelVariantSource[], modelId: string): {
95
+ readonly family: string;
96
+ readonly tier: string;
97
+ readonly precision: VariantPrecision;
98
+ readonly optimization: VariantOptimization;
99
+ readonly resolution?: number;
100
+ } | null;
@@ -94,6 +94,28 @@ export declare const ModelFormatsSchema: z.ZodObject<{
94
94
  }>>>>;
95
95
  }, z.core.$strip>>;
96
96
  }, z.core.$strip>;
97
+ /**
98
+ * Variant-selector grouping axes. Shared by the full `ModelCatalogEntry` and by
99
+ * the reduced `PipelineModelOption` returned in `pipeline.getSchema()` so the
100
+ * grouped Family→Tier→Variant picker renders identically in the config UI and
101
+ * in the pipeline/device steppers. The flat `id` stays the source of truth for
102
+ * resolution/download/persistence; this is a presentation overlay resolved back
103
+ * to an `id`.
104
+ */
105
+ export declare const ModelVariantGroupSchema: z.ZodObject<{
106
+ family: z.ZodString;
107
+ tier: z.ZodString;
108
+ precision: z.ZodOptional<z.ZodEnum<{
109
+ fp32: "fp32";
110
+ int8: "int8";
111
+ }>>;
112
+ optimization: z.ZodOptional<z.ZodEnum<{
113
+ standard: "standard";
114
+ fast: "fast";
115
+ }>>;
116
+ resolution: z.ZodOptional<z.ZodNumber>;
117
+ }, z.core.$strip>;
118
+ export type ModelVariantGroup = z.infer<typeof ModelVariantGroupSchema>;
97
119
  export declare const ModelCatalogEntrySchema: z.ZodObject<{
98
120
  id: z.ZodString;
99
121
  name: z.ZodString;
@@ -180,6 +202,25 @@ export declare const ModelCatalogEntrySchema: z.ZodObject<{
180
202
  filename: z.ZodString;
181
203
  sizeMB: z.ZodNumber;
182
204
  }, z.core.$strip>>>>;
205
+ legacy: z.ZodOptional<z.ZodBoolean>;
206
+ metrics: z.ZodOptional<z.ZodObject<{
207
+ map50: z.ZodOptional<z.ZodNumber>;
208
+ p95LatencyMs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
209
+ }, z.core.$strip>>;
210
+ license: z.ZodOptional<z.ZodString>;
211
+ group: z.ZodOptional<z.ZodObject<{
212
+ family: z.ZodString;
213
+ tier: z.ZodString;
214
+ precision: z.ZodOptional<z.ZodEnum<{
215
+ fp32: "fp32";
216
+ int8: "int8";
217
+ }>>;
218
+ optimization: z.ZodOptional<z.ZodEnum<{
219
+ standard: "standard";
220
+ fast: "fast";
221
+ }>>;
222
+ resolution: z.ZodOptional<z.ZodNumber>;
223
+ }, z.core.$strip>>;
183
224
  }, z.core.$strip>;
184
225
  export type ModelCatalogEntry = z.infer<typeof ModelCatalogEntrySchema>;
185
226
  export interface DetectionModel {
@@ -219,8 +260,8 @@ export interface CustomModelMetadata {
219
260
  export declare const ConvertTargetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
220
261
  format: z.ZodLiteral<"openvino">;
221
262
  precisions: z.ZodReadonly<z.ZodArray<z.ZodEnum<{
222
- fp16: "fp16";
223
263
  int8: "int8";
264
+ fp16: "fp16";
224
265
  }>>>;
225
266
  }, z.core.$strip>, z.ZodObject<{
226
267
  format: z.ZodLiteral<"coreml">;
@@ -273,8 +314,8 @@ export declare const ConvertArtifactSchema: z.ZodObject<{
273
314
  pt: "pt";
274
315
  }>;
275
316
  precision: z.ZodOptional<z.ZodEnum<{
276
- fp16: "fp16";
277
317
  int8: "int8";
318
+ fp16: "fp16";
278
319
  }>>;
279
320
  sizeMB: z.ZodNumber;
280
321
  validated: z.ZodBoolean;
@@ -368,6 +409,25 @@ export declare const ConvertResultSchema: z.ZodObject<{
368
409
  filename: z.ZodString;
369
410
  sizeMB: z.ZodNumber;
370
411
  }, z.core.$strip>>>>;
412
+ legacy: z.ZodOptional<z.ZodBoolean>;
413
+ metrics: z.ZodOptional<z.ZodObject<{
414
+ map50: z.ZodOptional<z.ZodNumber>;
415
+ p95LatencyMs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
416
+ }, z.core.$strip>>;
417
+ license: z.ZodOptional<z.ZodString>;
418
+ group: z.ZodOptional<z.ZodObject<{
419
+ family: z.ZodString;
420
+ tier: z.ZodString;
421
+ precision: z.ZodOptional<z.ZodEnum<{
422
+ fp32: "fp32";
423
+ int8: "int8";
424
+ }>>;
425
+ optimization: z.ZodOptional<z.ZodEnum<{
426
+ standard: "standard";
427
+ fast: "fast";
428
+ }>>;
429
+ resolution: z.ZodOptional<z.ZodNumber>;
430
+ }, z.core.$strip>>;
371
431
  }, z.core.$strip>;
372
432
  artifacts: z.ZodReadonly<z.ZodArray<z.ZodObject<{
373
433
  format: z.ZodEnum<{
@@ -378,8 +438,8 @@ export declare const ConvertResultSchema: z.ZodObject<{
378
438
  pt: "pt";
379
439
  }>;
380
440
  precision: z.ZodOptional<z.ZodEnum<{
381
- fp16: "fp16";
382
441
  int8: "int8";
442
+ fp16: "fp16";
383
443
  }>>;
384
444
  sizeMB: z.ZodNumber;
385
445
  validated: z.ZodBoolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.1.32",
3
+ "version": "1.1.34",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",
@@ -1,54 +0,0 @@
1
- import { z } from 'zod';
2
- import { type InferProvider } from './capability-definition.js';
3
- declare const RegisteredStreamSchema: z.ZodObject<{
4
- streamId: z.ZodString;
5
- label: z.ZodOptional<z.ZodString>;
6
- codec: z.ZodString;
7
- type: z.ZodEnum<{
8
- audio: "audio";
9
- video: "video";
10
- }>;
11
- sourceUrl: z.ZodString;
12
- }, z.core.$strip>;
13
- declare const ExposedResourceSchema: z.ZodObject<{
14
- streamId: z.ZodString;
15
- format: z.ZodString;
16
- value: z.ZodString;
17
- }, z.core.$strip>;
18
- export declare const restreamerCapability: {
19
- readonly name: "restreamer";
20
- readonly scope: "system";
21
- readonly mode: "collection";
22
- readonly internal: true;
23
- readonly methods: {
24
- readonly registerDevice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
25
- deviceId: z.ZodNumber;
26
- streams: z.ZodReadonly<z.ZodArray<z.ZodObject<{
27
- streamId: z.ZodString;
28
- label: z.ZodOptional<z.ZodString>;
29
- codec: z.ZodString;
30
- type: z.ZodEnum<{
31
- audio: "audio";
32
- video: "video";
33
- }>;
34
- sourceUrl: z.ZodString;
35
- }, z.core.$strip>>>;
36
- }, z.core.$strip>, z.ZodVoid, "mutation">;
37
- readonly unregisterDevice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
38
- deviceId: z.ZodNumber;
39
- }, z.core.$strip>, z.ZodVoid, "mutation">;
40
- readonly getExposedResources: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
41
- deviceId: z.ZodNumber;
42
- }, z.core.$strip>, z.ZodReadonly<z.ZodArray<z.ZodObject<{
43
- streamId: z.ZodString;
44
- format: z.ZodString;
45
- value: z.ZodString;
46
- }, z.core.$strip>>>, import("./capability-definition.js").CapabilityMethodKind>;
47
- };
48
- /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
49
- readonly mount: {
50
- readonly kind: "skip";
51
- };
52
- };
53
- export type IRestreamerProvider = InferProvider<typeof restreamerCapability>;
54
- export { RegisteredStreamSchema, ExposedResourceSchema };
@@ -1,43 +0,0 @@
1
- import { z } from 'zod';
2
- import { type InferProvider } from './capability-definition.js';
3
- /**
4
- * snapshot-provider — collection of native snapshot implementations.
5
- *
6
- * Device provider addons (ONVIF, Frigate, etc.) register here
7
- * when they can capture frames through a protocol-native path (e.g.
8
- * ONVIF GetSnapshotUri, Frigate /api/<cam>/latest.jpg). The `snapshot`
9
- * singleton orchestrator iterates over the collection, asking each
10
- * provider whether it supports the requested device, and calls the
11
- * first matching one.
12
- *
13
- * If no provider in the collection supports a device, the orchestrator
14
- * falls back to `stream-broker.grabFrame` (universal fallback).
15
- *
16
- * Public tRPC router (auto-mounted) so out-of-process addons, agents,
17
- * and advanced clients can bypass the orchestrator when needed.
18
- */
19
- export declare const snapshotProviderCapability: {
20
- readonly name: "snapshot-provider";
21
- readonly scope: "system";
22
- readonly mode: "collection";
23
- readonly methods: {
24
- readonly supportsDevice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
25
- deviceId: z.ZodNumber;
26
- }, z.core.$strip>, z.ZodBoolean, import("./capability-definition.js").CapabilityMethodKind>;
27
- readonly getSnapshot: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
28
- deviceId: z.ZodNumber;
29
- streamId: z.ZodOptional<z.ZodString>;
30
- }, z.core.$strip>, z.ZodNullable<z.ZodObject<{
31
- base64: z.ZodString;
32
- contentType: z.ZodString;
33
- }, z.core.$strip>>, import("./capability-definition.js").CapabilityMethodKind>;
34
- };
35
- /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
36
- readonly mount: {
37
- readonly kind: "custom";
38
- };
39
- };
40
- export type ISnapshotProvider = InferProvider<typeof snapshotProviderCapability> & {
41
- readonly id: string;
42
- readonly name: string;
43
- };