@camstack/types 1.1.32 → 1.1.33

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 (52) 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 +36 -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 +21 -3
  13. package/dist/capabilities/model-distributor.cap.d.ts +36 -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 +135 -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/encode-profile.d.ts +2 -2
  25. package/dist/enums/event-category.d.ts +12 -0
  26. package/dist/generated/addon-api.d.ts +746 -636
  27. package/dist/generated/capability-router-map.d.ts +4 -16
  28. package/dist/generated/device-proxy.d.ts +0 -2
  29. package/dist/generated/method-access-map.d.ts +1 -1
  30. package/dist/generated/system-proxy.d.ts +2 -2
  31. package/dist/index.d.ts +1 -3
  32. package/dist/index.js +416 -348
  33. package/dist/index.mjs +403 -342
  34. package/dist/interfaces/capability.d.ts +0 -7
  35. package/dist/interfaces/event-bus.d.ts +9 -0
  36. package/dist/interfaces/pipeline-executor-capability.d.ts +14 -1
  37. package/dist/interfaces/pipeline-runner-capability.d.ts +11 -11
  38. package/dist/interfaces/recording-config.d.ts +2 -2
  39. package/dist/{sleep-CZDdRBua.mjs → sleep-Cc14_yxc.mjs} +12 -4
  40. package/dist/{sleep-Dirr8nGw.js → sleep-DmP-uxoe.js} +12 -4
  41. package/dist/types/agent-pipeline-settings.d.ts +18 -6
  42. package/dist/types/camera-pipeline.d.ts +17 -3
  43. package/dist/types/model-variant-groups.d.ts +90 -0
  44. package/dist/types/models.d.ts +60 -3
  45. package/package.json +1 -1
  46. package/dist/capabilities/restreamer.cap.d.ts +0 -54
  47. package/dist/capabilities/snapshot-provider.cap.d.ts +0 -43
  48. package/dist/capabilities/streaming-engine.cap.d.ts +0 -61
  49. package/dist/capabilities/webrtc.cap.d.ts +0 -75
  50. package/dist/interfaces/restreamer.d.ts +0 -23
  51. package/dist/interfaces/streaming.d.ts +0 -28
  52. 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,90 @@
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
+ };
37
+ readonly formats: Readonly<Record<string, {
38
+ readonly sizeMB: number;
39
+ } | undefined>>;
40
+ }
41
+ /** One selectable variant of a tier (a single flat catalog entry). */
42
+ export interface ModelVariantOption {
43
+ readonly modelId: string;
44
+ readonly precision: VariantPrecision;
45
+ readonly optimization: VariantOptimization;
46
+ /** Short chip label: `Standard` | `Int8` | `Fast` | `Fast · Int8`. */
47
+ readonly label: string;
48
+ /** Formats this variant ships (drives per-node availability). */
49
+ readonly formats: readonly ModelFormat[];
50
+ /** Smallest declared build size (MB) — a rough size hint for the chip. */
51
+ readonly sizeMB: number;
52
+ }
53
+ /** One size tier within a family (e.g. YOLO26 "Small"), with its variants. */
54
+ export interface ModelVariantTier {
55
+ readonly tier: string;
56
+ readonly label: string;
57
+ /** The fp32/standard base model id — the tier's canonical selection. */
58
+ readonly baseModelId: string;
59
+ readonly options: readonly ModelVariantOption[];
60
+ }
61
+ /** One model family (e.g. YOLO26), with its size tiers. */
62
+ export interface ModelVariantFamily {
63
+ readonly family: string;
64
+ readonly label: string;
65
+ readonly tiers: readonly ModelVariantTier[];
66
+ }
67
+ /**
68
+ * Fold a flat catalog into the `family → tier → variant` tree. Deterministic
69
+ * ordering: tiers by the canonical size ladder (unknown tiers appended
70
+ * alphabetically), variants standard-before-int8 and fast last.
71
+ */
72
+ export declare function buildModelVariantGroups(models: readonly ModelVariantSource[]): readonly ModelVariantFamily[];
73
+ /**
74
+ * Map a grouped selection back to a flat catalog model id. Returns `null` when
75
+ * no entry matches (the UI then falls back to the tier base / format default).
76
+ * `precision`/`optimization` default to `fp32`/`standard` (the base build).
77
+ */
78
+ export declare function resolveVariantModelId(models: readonly ModelVariantSource[], selection: {
79
+ readonly family: string;
80
+ readonly tier: string;
81
+ readonly precision?: VariantPrecision;
82
+ readonly optimization?: VariantOptimization;
83
+ }): string | null;
84
+ /** Inverse: describe a flat model id as a grouped selection, or `null`. */
85
+ export declare function describeModelVariant(models: readonly ModelVariantSource[], modelId: string): {
86
+ readonly family: string;
87
+ readonly tier: string;
88
+ readonly precision: VariantPrecision;
89
+ readonly optimization: VariantOptimization;
90
+ } | null;
@@ -94,6 +94,27 @@ 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
+ }, z.core.$strip>;
117
+ export type ModelVariantGroup = z.infer<typeof ModelVariantGroupSchema>;
97
118
  export declare const ModelCatalogEntrySchema: z.ZodObject<{
98
119
  id: z.ZodString;
99
120
  name: z.ZodString;
@@ -180,6 +201,24 @@ export declare const ModelCatalogEntrySchema: z.ZodObject<{
180
201
  filename: z.ZodString;
181
202
  sizeMB: z.ZodNumber;
182
203
  }, z.core.$strip>>>>;
204
+ legacy: z.ZodOptional<z.ZodBoolean>;
205
+ metrics: z.ZodOptional<z.ZodObject<{
206
+ map50: z.ZodOptional<z.ZodNumber>;
207
+ p95LatencyMs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
208
+ }, z.core.$strip>>;
209
+ license: z.ZodOptional<z.ZodString>;
210
+ group: z.ZodOptional<z.ZodObject<{
211
+ family: z.ZodString;
212
+ tier: z.ZodString;
213
+ precision: z.ZodOptional<z.ZodEnum<{
214
+ fp32: "fp32";
215
+ int8: "int8";
216
+ }>>;
217
+ optimization: z.ZodOptional<z.ZodEnum<{
218
+ standard: "standard";
219
+ fast: "fast";
220
+ }>>;
221
+ }, z.core.$strip>>;
183
222
  }, z.core.$strip>;
184
223
  export type ModelCatalogEntry = z.infer<typeof ModelCatalogEntrySchema>;
185
224
  export interface DetectionModel {
@@ -219,8 +258,8 @@ export interface CustomModelMetadata {
219
258
  export declare const ConvertTargetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
220
259
  format: z.ZodLiteral<"openvino">;
221
260
  precisions: z.ZodReadonly<z.ZodArray<z.ZodEnum<{
222
- fp16: "fp16";
223
261
  int8: "int8";
262
+ fp16: "fp16";
224
263
  }>>>;
225
264
  }, z.core.$strip>, z.ZodObject<{
226
265
  format: z.ZodLiteral<"coreml">;
@@ -273,8 +312,8 @@ export declare const ConvertArtifactSchema: z.ZodObject<{
273
312
  pt: "pt";
274
313
  }>;
275
314
  precision: z.ZodOptional<z.ZodEnum<{
276
- fp16: "fp16";
277
315
  int8: "int8";
316
+ fp16: "fp16";
278
317
  }>>;
279
318
  sizeMB: z.ZodNumber;
280
319
  validated: z.ZodBoolean;
@@ -368,6 +407,24 @@ export declare const ConvertResultSchema: z.ZodObject<{
368
407
  filename: z.ZodString;
369
408
  sizeMB: z.ZodNumber;
370
409
  }, z.core.$strip>>>>;
410
+ legacy: z.ZodOptional<z.ZodBoolean>;
411
+ metrics: z.ZodOptional<z.ZodObject<{
412
+ map50: z.ZodOptional<z.ZodNumber>;
413
+ p95LatencyMs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNumber>>;
414
+ }, z.core.$strip>>;
415
+ license: z.ZodOptional<z.ZodString>;
416
+ group: z.ZodOptional<z.ZodObject<{
417
+ family: z.ZodString;
418
+ tier: z.ZodString;
419
+ precision: z.ZodOptional<z.ZodEnum<{
420
+ fp32: "fp32";
421
+ int8: "int8";
422
+ }>>;
423
+ optimization: z.ZodOptional<z.ZodEnum<{
424
+ standard: "standard";
425
+ fast: "fast";
426
+ }>>;
427
+ }, z.core.$strip>>;
371
428
  }, z.core.$strip>;
372
429
  artifacts: z.ZodReadonly<z.ZodArray<z.ZodObject<{
373
430
  format: z.ZodEnum<{
@@ -378,8 +435,8 @@ export declare const ConvertResultSchema: z.ZodObject<{
378
435
  pt: "pt";
379
436
  }>;
380
437
  precision: z.ZodOptional<z.ZodEnum<{
381
- fp16: "fp16";
382
438
  int8: "int8";
439
+ fp16: "fp16";
383
440
  }>>;
384
441
  sizeMB: z.ZodNumber;
385
442
  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.33",
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
- };
@@ -1,61 +0,0 @@
1
- import { z } from 'zod';
2
- import { type InferProvider } from './capability-definition.js';
3
- declare const StreamFormatSchema: z.ZodEnum<{
4
- rtsp: "rtsp";
5
- webrtc: "webrtc";
6
- hls: "hls";
7
- mjpeg: "mjpeg";
8
- }>;
9
- declare const StreamInfoSchema: z.ZodObject<{
10
- streamId: z.ZodString;
11
- format: z.ZodEnum<{
12
- rtsp: "rtsp";
13
- webrtc: "webrtc";
14
- hls: "hls";
15
- mjpeg: "mjpeg";
16
- }>;
17
- url: z.ZodNullable<z.ZodString>;
18
- active: z.ZodBoolean;
19
- }, z.core.$strip>;
20
- export declare const streamingEngineCapability: {
21
- readonly name: "streaming-engine";
22
- readonly scope: "system";
23
- readonly mode: "singleton";
24
- readonly internal: true;
25
- readonly methods: {
26
- readonly registerStream: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
27
- streamId: z.ZodString;
28
- sourceUrl: z.ZodString;
29
- codec: z.ZodOptional<z.ZodString>;
30
- }, z.core.$strip>, z.ZodVoid, "mutation">;
31
- readonly unregisterStream: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
32
- streamId: z.ZodString;
33
- }, z.core.$strip>, z.ZodVoid, "mutation">;
34
- readonly getStreamUrl: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
35
- streamId: z.ZodString;
36
- format: z.ZodEnum<{
37
- rtsp: "rtsp";
38
- webrtc: "webrtc";
39
- hls: "hls";
40
- mjpeg: "mjpeg";
41
- }>;
42
- }, z.core.$strip>, z.ZodNullable<z.ZodString>, import("./capability-definition.js").CapabilityMethodKind>;
43
- readonly listStreams: import("./capability-definition.js").CapabilityMethodSchema<z.ZodVoid, z.ZodArray<z.ZodObject<{
44
- streamId: z.ZodString;
45
- format: z.ZodEnum<{
46
- rtsp: "rtsp";
47
- webrtc: "webrtc";
48
- hls: "hls";
49
- mjpeg: "mjpeg";
50
- }>;
51
- url: z.ZodNullable<z.ZodString>;
52
- active: z.ZodBoolean;
53
- }, z.core.$strip>>, import("./capability-definition.js").CapabilityMethodKind>;
54
- };
55
- /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
56
- readonly mount: {
57
- readonly kind: "skip";
58
- };
59
- };
60
- export type IStreamingEngineProvider = InferProvider<typeof streamingEngineCapability>;
61
- export { StreamFormatSchema, StreamInfoSchema };