@camstack/types 1.2.93 → 1.2.95
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.
- package/dist/capabilities/index.d.ts +3 -3
- package/dist/capabilities/local-network.cap.d.ts +41 -1
- package/dist/capabilities/pipeline-analytics.cap.d.ts +7 -1
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +38 -1
- package/dist/capabilities/pipeline-runner.cap.d.ts +3 -0
- package/dist/device/index.d.ts +2 -2
- package/dist/device/runtime-state-helpers.d.ts +63 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +456 -19
- package/dist/index.mjs +444 -20
- package/dist/interfaces/config-ui.d.ts +34 -0
- package/dist/interfaces/recording-config.d.ts +16 -3
- package/dist/pipeline/cluster-model-scope.d.ts +108 -0
- package/dist/pipeline/detail-crop.d.ts +19 -0
- package/dist/types/pipeline-step.d.ts +36 -1
- package/package.json +1 -1
|
@@ -81,6 +81,38 @@ export interface ConfigSection {
|
|
|
81
81
|
readonly fields: readonly ConfigField[];
|
|
82
82
|
}
|
|
83
83
|
export type ConfigField = ConfigTextField | ConfigNumberField | ConfigBooleanField | ConfigSelectField | ConfigMultiSelectField | ConfigTimezoneField | ConfigDateTimeField | ConfigColorField | ConfigPasswordField | ConfigTextAreaField | ConfigSliderField | ConfigTagsField | ConfigGroupField | ConfigSubTabsField | ConfigSeparatorField | ConfigInfoField | ConfigQrCodeField | ConfigObjectArrayField | ConfigEditableArrayField | ConfigModelSelectorField | ConfigStorageLocationField | ConfigProbeField | ConfigButtonField | ConfigPipelineEditorField | ConfigNodeSelectField | ConfigNodeMultiSelectField | ConfigDeviceSelectField | ConfigDeviceMultiSelectField | ConfigWidgetField | ConfigAddonActionSelectField | ConfigAddonActionButtonField | ConfigDeviceActionButtonField;
|
|
84
|
+
/**
|
|
85
|
+
* Per-MODEL applicability of a pipeline-step setting (D214).
|
|
86
|
+
*
|
|
87
|
+
* A step's config schema is static, but whether a knob has any effect depends
|
|
88
|
+
* on WHICH model the step runs: an NMS IoU threshold means nothing to a model
|
|
89
|
+
* whose export fuses NMS into the graph (Frigate YOLO-NAS, TFLite SSD), a
|
|
90
|
+
* per-macro confidence slider is moot for a macro the model's labelmap cannot
|
|
91
|
+
* produce, and a class allow-list must offer the MODEL's labels, not the
|
|
92
|
+
* catalog's. Computed server-side (`buildSchemaSlots` → the step's model
|
|
93
|
+
* union, static + custom registry) and consumed by the step editors, which
|
|
94
|
+
* disable an inapplicable knob WITH its reason instead of rendering a control
|
|
95
|
+
* that silently does nothing.
|
|
96
|
+
*
|
|
97
|
+
* COMPILE-TIME ONLY on the wire: `ConfigField` crosses the cap boundary via
|
|
98
|
+
* `z.custom<ConfigField>()` (no stripping), so an addon compiled against this
|
|
99
|
+
* field runs on hubs whose installed framework predates it — same pattern as
|
|
100
|
+
* the `yolonas` `PostprocessorType` member (D208).
|
|
101
|
+
*/
|
|
102
|
+
export interface ConfigFieldModelApplicability {
|
|
103
|
+
/**
|
|
104
|
+
* modelId → operator-readable reason this knob has NO effect with that
|
|
105
|
+
* model. The editor disables the control and shows the reason.
|
|
106
|
+
*/
|
|
107
|
+
readonly inapplicable?: Readonly<Record<string, string>>;
|
|
108
|
+
/**
|
|
109
|
+
* modelId → replacement options for select/multiselect fields whose offer
|
|
110
|
+
* derives from the model's own labelmap (custom models: a class allow-list
|
|
111
|
+
* must operate on THE MODEL's labels — options from another labelmap build
|
|
112
|
+
* a filter that can never match).
|
|
113
|
+
*/
|
|
114
|
+
readonly optionsByModel?: Readonly<Record<string, readonly ConfigOption[]>>;
|
|
115
|
+
}
|
|
84
116
|
export interface ConfigFieldBase {
|
|
85
117
|
readonly key: string;
|
|
86
118
|
readonly label: string;
|
|
@@ -92,6 +124,8 @@ export interface ConfigFieldBase {
|
|
|
92
124
|
readonly default?: unknown;
|
|
93
125
|
readonly span?: 1 | 2 | 3 | 4;
|
|
94
126
|
readonly showWhen?: ConfigCondition;
|
|
127
|
+
/** Per-model knob applicability — see {@link ConfigFieldModelApplicability}. */
|
|
128
|
+
readonly modelApplicability?: ConfigFieldModelApplicability;
|
|
95
129
|
/**
|
|
96
130
|
* Save behavior when value changes.
|
|
97
131
|
* - true: save immediately on change (toggles, selects, checkboxes)
|
|
@@ -111,12 +111,25 @@ export type RecordingBand = z.infer<typeof RecordingBandSchema>;
|
|
|
111
111
|
* segment is ever finalized and the camera records nothing anyway. At the 10 s
|
|
112
112
|
* default segment length, 30 s leaves room for two full segments. `preBufferSec`
|
|
113
113
|
* is retroactive only — it costs nothing at record time, it merely keeps
|
|
114
|
-
* already-written segments
|
|
114
|
+
* already-written segments.
|
|
115
115
|
*
|
|
116
|
-
*
|
|
116
|
+
* ## Why `preBufferSec` is 15 and not one segment length
|
|
117
|
+
*
|
|
118
|
+
* It has to cover the broker's RECORDING pre-roll, which is media handed to the
|
|
119
|
+
* writer from BEFORE the trigger (D192/D193). If this bound were narrower, the
|
|
120
|
+
* keep gate would delete the very seconds the ring just supplied — two
|
|
121
|
+
* authorities disagreeing about the same footage, which is the failure D191 was
|
|
122
|
+
* written against. It is therefore set to `RECORDING_PRE_ROLL_MAX_MS` (15 s),
|
|
123
|
+
* the widest window the broker can be configured to serve, so an operator
|
|
124
|
+
* raising the cluster pre-roll can never walk past the gate silently. The
|
|
125
|
+
* addon-side guard is
|
|
126
|
+
* `packages/addon-pipeline/src/recorder/addon/__tests__/band-decision.spec.ts`.
|
|
127
|
+
*
|
|
128
|
+
* An EXPLICIT `0` is left alone: that is an operator statement, not an omission,
|
|
129
|
+
* and it is excluded from that invariant by name.
|
|
117
130
|
*/
|
|
118
131
|
export declare const DEFAULT_EVENTS_BAND_BUFFER_SEC: {
|
|
119
|
-
readonly preBufferSec:
|
|
132
|
+
readonly preBufferSec: 15;
|
|
120
133
|
readonly postBufferSec: 30;
|
|
121
134
|
};
|
|
122
135
|
export type DefaultEventsBandBufferSec = typeof DEFAULT_EVENTS_BAND_BUFFER_SEC;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a step's model is chosen.
|
|
3
|
+
*
|
|
4
|
+
* - `'node'` — per (node, device). Free to differ across the fleet.
|
|
5
|
+
* - `'cluster'` — ONE value for the whole cluster. The step writes into a
|
|
6
|
+
* shared vector index, so two values would put two incomparable feature
|
|
7
|
+
* spaces in it with nothing in the data to show it.
|
|
8
|
+
*
|
|
9
|
+
* Absent on a {@link import('../types/pipeline-step.js').StepDefinition} means
|
|
10
|
+
* `'node'`, which is the safe reading: a step that never declared a scope has
|
|
11
|
+
* never had a cluster-wide row to read.
|
|
12
|
+
*/
|
|
13
|
+
export type StepModelScope = 'node' | 'cluster';
|
|
14
|
+
/** One selectable model for a cluster-scoped step. */
|
|
15
|
+
export interface ClusterModelOption {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly label: string;
|
|
18
|
+
}
|
|
19
|
+
/** One cluster-scoped step, as every non-pipeline package sees it. */
|
|
20
|
+
export interface ClusterModelScopedStep {
|
|
21
|
+
readonly stepId: string;
|
|
22
|
+
/** Operator-facing label for the settings row. */
|
|
23
|
+
readonly label: string;
|
|
24
|
+
/**
|
|
25
|
+
* The model in force when nobody has chosen — the step's catalog
|
|
26
|
+
* `defaultModelId`, so declaring the scope is behaviour-neutral.
|
|
27
|
+
*/
|
|
28
|
+
readonly defaultModelId: string;
|
|
29
|
+
/** The index a change invalidates, named in the operator-facing description. */
|
|
30
|
+
readonly indexName: string;
|
|
31
|
+
/**
|
|
32
|
+
* The choosable models, mirrored from the step's catalog (non-`legacy`
|
|
33
|
+
* entries) and guarded by `scripts/check-cluster-model-scope.ts`.
|
|
34
|
+
*
|
|
35
|
+
* Mirrored rather than derived because the orchestrator renders this dropdown
|
|
36
|
+
* and may not import an addon. A free-text field would have been less code
|
|
37
|
+
* and strictly worse: a typo there is not a validation error, it is a model
|
|
38
|
+
* that every node refuses, cluster-wide, and the symptom is "recognition
|
|
39
|
+
* stopped" with no bad value in sight.
|
|
40
|
+
*/
|
|
41
|
+
readonly options: readonly ClusterModelOption[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The cluster-scoped steps. Mirrored from the catalog's `modelScope: 'cluster'`
|
|
45
|
+
* declarations and guarded by `scripts/check-cluster-model-scope.ts`.
|
|
46
|
+
*/
|
|
47
|
+
export declare const CLUSTER_MODEL_SCOPED_STEPS: readonly ClusterModelScopedStep[];
|
|
48
|
+
/**
|
|
49
|
+
* Store identity of the cluster row inside `pipeline-orchestrator`'s GLOBAL
|
|
50
|
+
* (cluster-wide) settings — the same owner, and for the same reason, as the
|
|
51
|
+
* detail-crop convention: hub-resident and neutral between the addons that
|
|
52
|
+
* read it.
|
|
53
|
+
*/
|
|
54
|
+
export declare const CLUSTER_MODEL_SECTION_ID = "cluster-step-models";
|
|
55
|
+
/**
|
|
56
|
+
* The settings key holding one step's cluster model choice.
|
|
57
|
+
*
|
|
58
|
+
* Step-qualified so the keys stay unique across the addon's whole schema, which
|
|
59
|
+
* is what lets {@link pickClusterStepModels} walk every section instead of
|
|
60
|
+
* trusting the section id.
|
|
61
|
+
*/
|
|
62
|
+
export declare function clusterModelSettingKey(stepId: string): string;
|
|
63
|
+
/** True when this step's model is a cluster-wide choice rather than a per-node one. */
|
|
64
|
+
export declare function isClusterScopedStep(stepId: string): boolean;
|
|
65
|
+
/** `stepId → modelId` for every cluster-scoped step. Total: never missing a key. */
|
|
66
|
+
export type ClusterStepModels = Readonly<Record<string, string>>;
|
|
67
|
+
/** The cluster row when nobody has configured one — today's catalog defaults. */
|
|
68
|
+
export declare const DEFAULT_CLUSTER_STEP_MODELS: ClusterStepModels;
|
|
69
|
+
/**
|
|
70
|
+
* Narrow a FLAT settings record to the cluster row.
|
|
71
|
+
*
|
|
72
|
+
* Per-FIELD fallback, deliberately (same rule as `readDetailCropConvention`): a
|
|
73
|
+
* junk face model must not also discard a valid clip model. An absent, empty or
|
|
74
|
+
* non-string value resolves to the step's catalog default — the historical
|
|
75
|
+
* behaviour — never to a blank id, because a blank id downstream becomes
|
|
76
|
+
* "substitute the format default", which is precisely the substitution this
|
|
77
|
+
* scope exists to forbid.
|
|
78
|
+
*/
|
|
79
|
+
export declare function readClusterStepModels(config: Readonly<Record<string, unknown>>): ClusterStepModels;
|
|
80
|
+
/** One section of an `addon-settings.getGlobalSettings` payload. */
|
|
81
|
+
export interface HydratedClusterSection {
|
|
82
|
+
readonly fields: readonly unknown[];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Minimal structural view of `ConfigUISchemaWithValues` — only what this walk
|
|
86
|
+
* needs. Structural on purpose: the readers are addons that must not depend on
|
|
87
|
+
* the writer's schema type.
|
|
88
|
+
*/
|
|
89
|
+
export interface HydratedClusterView {
|
|
90
|
+
readonly sections: readonly HydratedClusterSection[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Extract the cluster row from an `addon-settings.getGlobalSettings` payload.
|
|
94
|
+
*
|
|
95
|
+
* Walks EVERY section rather than looking inside {@link CLUSTER_MODEL_SECTION_ID}
|
|
96
|
+
* alone: the keys are unique across the addon's schema, and a section rename
|
|
97
|
+
* must not silently revert the whole cluster to the defaults. A `null` payload
|
|
98
|
+
* (addon mid-boot) is the defaults.
|
|
99
|
+
*/
|
|
100
|
+
export declare function pickClusterStepModels(view: HydratedClusterView | null): ClusterStepModels;
|
|
101
|
+
/**
|
|
102
|
+
* The cluster model for `stepId`, or `null` when the step is node-scoped.
|
|
103
|
+
*
|
|
104
|
+
* `null` is the signal to LEAVE THE CALLER'S RESOLUTION ALONE — it is not "no
|
|
105
|
+
* model". Returning a default here for a node-scoped step would quietly
|
|
106
|
+
* override every per-(node,device) selection in the fleet.
|
|
107
|
+
*/
|
|
108
|
+
export declare function resolveClusterStepModelId(stepId: string, models: ClusterStepModels): string | null;
|
|
@@ -95,6 +95,25 @@ export interface HydratedSettingsView {
|
|
|
95
95
|
* (addon mid-boot) is the default convention.
|
|
96
96
|
*/
|
|
97
97
|
export declare function pickDetailCropConvention(view: HydratedSettingsView | null): DetailCropConvention;
|
|
98
|
+
/**
|
|
99
|
+
* The normalised box that means "the image IS the subject".
|
|
100
|
+
*
|
|
101
|
+
* Used when the stored pixels are ALREADY the model's input — the 112×112
|
|
102
|
+
* aligned face template a gallery sample carries. There is no rectangle left to
|
|
103
|
+
* choose, and the convention must not choose one: re-detecting and re-aligning
|
|
104
|
+
* over a template applies a SECOND warp, passes every gate, and produces a
|
|
105
|
+
* plausible useless vector (session 2026-08-20 §3).
|
|
106
|
+
*
|
|
107
|
+
* Sending it as the whole frame with this box is exact rather than merely
|
|
108
|
+
* convenient, and the reason is a property of {@link deriveDetailCropRect}, not
|
|
109
|
+
* a coincidence: padding a full-frame box can only push OUTSIDE the frame, and
|
|
110
|
+
* both edge modes bring it straight back — unsquared truncates, squared cannot
|
|
111
|
+
* exceed the frame's short side and then slides inside. So for a SQUARE image
|
|
112
|
+
* the derivation is the identity under every convention value, and an operator
|
|
113
|
+
* changing the crop margin cannot silently re-cut an enrolled template.
|
|
114
|
+
* `face-reembed-pass.spec.ts` asserts that identity against the real function.
|
|
115
|
+
*/
|
|
116
|
+
export declare const FULL_IMAGE_BBOX: DetailCropRect;
|
|
98
117
|
/** Slider bounds for the operator-facing padding knob (orchestrator settings UI). */
|
|
99
118
|
export declare const DETAIL_CROP_PADDING_FIELD: {
|
|
100
119
|
readonly min: 0;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ConfigField } from '../interfaces/config-ui.js';
|
|
2
|
+
import type { StepModelScope } from '../pipeline/cluster-model-scope.js';
|
|
2
3
|
import type { ClassMapDefinition } from './labels.js';
|
|
3
4
|
import type { ModelCatalogEntry } from './models.js';
|
|
4
5
|
import type { PipelineSlot } from './pipeline.js';
|
|
@@ -12,7 +13,7 @@ export interface IPipelineStep {
|
|
|
12
13
|
readonly definition: StepDefinition;
|
|
13
14
|
getConfigSchema(): readonly ConfigField[];
|
|
14
15
|
}
|
|
15
|
-
export type PostprocessorType = 'yolo' | 'ssd' | 'rfdetr' | 'yolo-seg' | 'scrfd' | 'arcface' | 'clip' | 'softmax' | 'ctc' | 'saliency' | 'yamnet';
|
|
16
|
+
export type PostprocessorType = 'yolo' | 'ssd' | 'rfdetr' | 'yolonas' | 'yolo-seg' | 'scrfd' | 'arcface' | 'clip' | 'softmax' | 'ctc' | 'plate-slots' | 'saliency' | 'yamnet';
|
|
16
17
|
export interface StepDefinition {
|
|
17
18
|
/** Unique step identifier (e.g., 'object-detection', 'face-detection') */
|
|
18
19
|
readonly id: string;
|
|
@@ -75,6 +76,27 @@ export interface StepDefinition {
|
|
|
75
76
|
* duplicating the step definition per engine.
|
|
76
77
|
*/
|
|
77
78
|
readonly defaultModelIdByFormat?: Readonly<Record<string, string>>;
|
|
79
|
+
/**
|
|
80
|
+
* WHOSE choice this step's model is — see
|
|
81
|
+
* [`pipeline/cluster-model-scope.ts`](../pipeline/cluster-model-scope.ts).
|
|
82
|
+
*
|
|
83
|
+
* - `'node'` (the default when absent) — per (node, device). Two nodes may
|
|
84
|
+
* answer differently because nothing compares their outputs: a box is a
|
|
85
|
+
* box.
|
|
86
|
+
* - `'cluster'` — ONE value for the whole cluster, stored in ONE
|
|
87
|
+
* `pipeline-orchestrator` global row. Declared by a step that writes into a
|
|
88
|
+
* SHARED VECTOR INDEX (`face-embedding` → the enrolled gallery,
|
|
89
|
+
* `clip-embedding` → `vec_object_clip`), where a second model does not
|
|
90
|
+
* degrade the ranking, it makes it meaningless — and nothing inside a
|
|
91
|
+
* vector can reveal which encoder produced it.
|
|
92
|
+
*
|
|
93
|
+
* A `'cluster'` declaration changes the RESOLUTION RULE, not just the storage:
|
|
94
|
+
* a node whose format ships no build of the chosen model REFUSES the step and
|
|
95
|
+
* logs it, where a node-scoped step would substitute that format's default
|
|
96
|
+
* ([D54](../../../../docs/decisions/adr-0056.md)). Substituting is what fills
|
|
97
|
+
* one index from several encoders.
|
|
98
|
+
*/
|
|
99
|
+
readonly modelScope?: StepModelScope;
|
|
78
100
|
/**
|
|
79
101
|
* Whether a newly-seeded agent has this addon enabled by default.
|
|
80
102
|
* Absent = `true`. Operators can always toggle this after boot; this
|
|
@@ -135,6 +157,14 @@ export interface StepDefinition {
|
|
|
135
157
|
* `DEFAULT_MIN_TEXT_CONFIDENCE` (0, disabled).
|
|
136
158
|
*/
|
|
137
159
|
readonly minTextConfidence?: number;
|
|
160
|
+
/**
|
|
161
|
+
* Plausibility gate for a FIXED-SLOT plate reader (`plate-slots`): the
|
|
162
|
+
* minimum probability the WEAKEST emitted character must carry. It replaces
|
|
163
|
+
* {@link minTextLength}, which carries no information for a reader that emits
|
|
164
|
+
* a full-length string on every input including a blank wall. Forwarded to
|
|
165
|
+
* the Python postprocessor; absent ⇒ its `DEFAULT_MIN_CHAR_PROBABILITY`.
|
|
166
|
+
*/
|
|
167
|
+
readonly minCharProbability?: number;
|
|
138
168
|
/** COCO-to-macro class mapping (e.g., 'car' → 'vehicle') */
|
|
139
169
|
readonly classMap?: ClassMapDefinition;
|
|
140
170
|
/** UI grouping label — steps with the same group are displayed together (e.g., 'Segmentation') */
|
|
@@ -234,6 +264,11 @@ export interface PoolModelConfig {
|
|
|
234
264
|
readonly minTextLength?: number;
|
|
235
265
|
/** Plate-OCR plausibility gate: confidence floor. */
|
|
236
266
|
readonly minTextConfidence?: number;
|
|
267
|
+
/**
|
|
268
|
+
* Fixed-slot plate-OCR gate: minimum per-character probability. See
|
|
269
|
+
* {@link StepDefinition.minCharProbability}.
|
|
270
|
+
*/
|
|
271
|
+
readonly minCharProbability?: number;
|
|
237
272
|
/** Number of classes (for YOLO: 80 COCO or 1 for plate) */
|
|
238
273
|
readonly numClasses?: number;
|
|
239
274
|
/** Anchor strides for SCRFD (default [8, 16, 32]) */
|