@camstack/addon-agent-ui 1.2.27 → 1.2.28

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 (2) hide show
  1. package/dist/addon.js +249 -17
  2. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -8014,6 +8014,15 @@ var LabelDefinitionSchema = object({
8014
8014
  description: string().optional(),
8015
8015
  icon: string().optional()
8016
8016
  });
8017
+ var ClassMapDefinitionSchema = object({
8018
+ mapping: record(string(), _enum([
8019
+ "person",
8020
+ "vehicle",
8021
+ "animal",
8022
+ "package"
8023
+ ])),
8024
+ preserveOriginal: boolean()
8025
+ });
8017
8026
  var MODEL_FORMATS = [
8018
8027
  "onnx",
8019
8028
  "coreml",
@@ -8192,7 +8201,13 @@ var ModelCatalogEntrySchema = object({
8192
8201
  * `id` stays the source of truth for resolution/download/persistence; grouping
8193
8202
  * is a presentation overlay resolved back to an `id`.
8194
8203
  */
8195
- group: ModelVariantGroupSchema.optional()
8204
+ group: ModelVariantGroupSchema.optional(),
8205
+ /**
8206
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8207
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8208
+ * labels already ARE the CamStack macros (Scrypted identity map).
8209
+ */
8210
+ classMap: ClassMapDefinitionSchema.optional()
8196
8211
  });
8197
8212
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8198
8213
  format: literal("openvino"),
@@ -8221,7 +8236,8 @@ var ModelConvertMetadataSchema = object({
8221
8236
  "ocr",
8222
8237
  "segmentation"
8223
8238
  ]),
8224
- faceAlignment: boolean().optional()
8239
+ faceAlignment: boolean().optional(),
8240
+ classMap: ClassMapDefinitionSchema.optional()
8225
8241
  });
8226
8242
  var ConvertResultSchema = object({
8227
8243
  entry: ModelCatalogEntrySchema,
@@ -17212,6 +17228,33 @@ var NativeCropRefSchema = object({
17212
17228
  h: number()
17213
17229
  })
17214
17230
  });
17231
+ object({
17232
+ crop: object({
17233
+ left: number(),
17234
+ top: number(),
17235
+ width: number().positive(),
17236
+ height: number().positive()
17237
+ }).optional(),
17238
+ content: object({
17239
+ width: number().int().positive(),
17240
+ height: number().int().positive()
17241
+ }),
17242
+ fit: _enum(["stretch", "contain"]),
17243
+ format: _enum([
17244
+ "rgb",
17245
+ "gray",
17246
+ "jpeg"
17247
+ ])
17248
+ });
17249
+ var FrameRefSchema = object({
17250
+ registryId: string().min(1),
17251
+ id: string().min(1),
17252
+ width: number().int().positive(),
17253
+ height: number().int().positive(),
17254
+ format: _enum(["rgb", "gray"]),
17255
+ timestamp: number(),
17256
+ capturedAt: number().optional()
17257
+ });
17215
17258
  var ModelFormatSchema$1 = _enum([
17216
17259
  "onnx",
17217
17260
  "coreml",
@@ -17456,6 +17499,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17456
17499
  steps: array(PipelineStepInputSchema).min(1),
17457
17500
  frame: FrameInputSchema.optional(),
17458
17501
  /**
17502
+ * Process-local lazy frame. Valid only when caller and provider resolve
17503
+ * in the same execution-group process; split/cross-node callers use
17504
+ * `frame`/`image` inline compatibility instead.
17505
+ */
17506
+ frameRef: FrameRefSchema.optional(),
17507
+ /**
17459
17508
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17460
17509
  * the decoded pixels live in. One more member of the one-of
17461
17510
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17711,7 +17760,10 @@ var NativeCropResultSchema = object({
17711
17760
  * Which source served this crop, so a quality-sensitive consumer (the native
17712
17761
  * `keyFrame`) can reject a degraded fallback:
17713
17762
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17714
- * quality path).
17763
+ * quality path). A subject-tile serve is also native-resolution and stays
17764
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17765
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17766
+ * internal crop result (`nativeHits` vs `tileHits`).
17715
17767
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17716
17768
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17717
17769
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18202,12 +18254,41 @@ var RunnerLocalLoadSchema = object({
18202
18254
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18203
18255
  * working unchanged when they switch to reading from the runner cap.
18204
18256
  */
18257
+ var FrameLazyCountersSchema = object({
18258
+ framesDecoded: number(),
18259
+ framesAdmitted: number(),
18260
+ framesDroppedPixelFree: number(),
18261
+ viewsMaterialized: number(),
18262
+ viewsSkipped: number(),
18263
+ workerToRunnerBytes: number(),
18264
+ runnerToPoolRawBytes: number(),
18265
+ runnerToPoolJpegBytes: number(),
18266
+ onDemandFullFrameRequests: number(),
18267
+ onDemandCropRequests: number(),
18268
+ nativeHits: number(),
18269
+ nativeMisses: number(),
18270
+ tileHits: number(),
18271
+ tileMisses: number(),
18272
+ fallbackHits: number(),
18273
+ fallbackMisses: number(),
18274
+ retainedWritesAvoided: number(),
18275
+ residentRefs: number(),
18276
+ residentBytes: number(),
18277
+ releases: number(),
18278
+ evictions: number(),
18279
+ staleMisses: number()
18280
+ });
18281
+ var FrameLazyMetricsSchema = object({
18282
+ node: FrameLazyCountersSchema,
18283
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18284
+ });
18205
18285
  var RunnerLocalMetricsSchema = object({
18206
18286
  nodeId: string(),
18207
18287
  activeCameras: number(),
18208
18288
  throttledCameras: number(),
18209
18289
  avgInferenceTimeMs: number(),
18210
- queueDepth: number()
18290
+ queueDepth: number(),
18291
+ frameLazy: FrameLazyMetricsSchema.optional()
18211
18292
  });
18212
18293
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
18213
18294
  handle: FrameHandleSchema,
@@ -19507,6 +19588,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19507
19588
  location: StorageLocationSchema,
19508
19589
  relativePath: string()
19509
19590
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
19591
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19592
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19593
+ var ProfileSettingsBagSchema = record(string(), unknown());
19510
19594
  /**
19511
19595
  * A live terminal session hosted by the provider addon. Output and input do
19512
19596
  * NOT flow through the capability — they use the addon data plane
@@ -19536,7 +19620,14 @@ var TerminalSessionInfoSchema = object({
19536
19620
  var TerminalProfileInfoSchema = object({
19537
19621
  profileId: string(),
19538
19622
  label: string(),
19539
- description: string().optional()
19623
+ description: string().optional(),
19624
+ /** Spawn defaults the instance form copies on create. */
19625
+ executable: string().optional(),
19626
+ args: array(string()).readonly().optional(),
19627
+ cwd: string().optional(),
19628
+ environment: array(string()).readonly().optional(),
19629
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19630
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19540
19631
  });
19541
19632
  /**
19542
19633
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19549,7 +19640,12 @@ var TerminalInstanceInfoSchema = object({
19549
19640
  profileId: string(),
19550
19641
  profileLabel: string(),
19551
19642
  name: string(),
19552
- enabled: boolean()
19643
+ enabled: boolean(),
19644
+ executable: string(),
19645
+ args: array(string()).readonly(),
19646
+ cwd: string(),
19647
+ environment: array(string()).readonly(),
19648
+ profileSettings: ProfileSettingsBagSchema
19553
19649
  });
19554
19650
  var TerminalLegacyCameraSchema = object({
19555
19651
  stableId: string(),
@@ -19579,7 +19675,23 @@ var TerminalOutputBatchSchema = object({
19579
19675
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19580
19676
  targetNodeId: string().min(1),
19581
19677
  profileId: string().min(1),
19582
- name: string().trim().min(1).max(160).optional()
19678
+ name: string().trim().min(1).max(160).optional(),
19679
+ executable: string().max(1024).optional(),
19680
+ args: array(string().max(2048)).max(64).optional(),
19681
+ cwd: string().max(1024).optional(),
19682
+ environment: array(string().max(4096)).max(64).optional(),
19683
+ profileSettings: ProfileSettingsBagSchema.optional()
19684
+ }), TerminalInstanceInfoSchema, {
19685
+ kind: "mutation",
19686
+ auth: "admin"
19687
+ }), method(object({
19688
+ instanceId: string().min(1),
19689
+ name: string().trim().min(1).max(160).optional(),
19690
+ executable: string().max(1024).optional(),
19691
+ args: array(string().max(2048)).max(64).optional(),
19692
+ cwd: string().max(1024).optional(),
19693
+ environment: array(string().max(4096)).max(64).optional(),
19694
+ profileSettings: ProfileSettingsBagSchema.optional()
19583
19695
  }), TerminalInstanceInfoSchema, {
19584
19696
  kind: "mutation",
19585
19697
  auth: "admin"
@@ -19601,7 +19713,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19601
19713
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19602
19714
  profileId: string(),
19603
19715
  cols: number().int().positive(),
19604
- rows: number().int().positive()
19716
+ rows: number().int().positive(),
19717
+ executable: string().max(1024).optional(),
19718
+ args: array(string().max(2048)).max(64).optional(),
19719
+ cwd: string().max(1024).optional(),
19720
+ environment: array(string().max(4096)).max(64).optional()
19605
19721
  }), TerminalSessionInfoSchema, {
19606
19722
  kind: "mutation",
19607
19723
  auth: "admin"
@@ -22383,10 +22499,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22383
22499
  *
22384
22500
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22385
22501
  * to receive an ordered list of candidate base URLs it should race
22386
- * on connect — LAN IPv4 first (lowest latency when on same network),
22387
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22388
- * race them with short timeouts and stick with the winner for the
22389
- * session.
22502
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22503
+ * when on the same network), then public hostname (if a tunnel is
22504
+ * up). The SDK can race them with short timeouts and stick with the
22505
+ * winner for the session.
22390
22506
  *
22391
22507
  * Why hub-only: agents are not directly addressable by the operator's
22392
22508
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22541,6 +22657,17 @@ var NotificationEndpointSchema = object({
22541
22657
  /** What the ranking currently resolves to (null when nothing is reachable). */
22542
22658
  resolved: string().nullable()
22543
22659
  });
22660
+ /**
22661
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22662
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22663
+ * currently expands to, so the UI can show the effective set either way.
22664
+ */
22665
+ var ViewerEndpointsSchema = object({
22666
+ /** The operator's explicit race set, or empty for AUTO. */
22667
+ baseUrls: array(string()).readonly(),
22668
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22669
+ resolved: array(string()).readonly()
22670
+ });
22544
22671
  var AllowedAddressesSchema = object({
22545
22672
  /**
22546
22673
  * Allowlist of interface addresses operators have explicitly opted
@@ -22549,6 +22676,20 @@ var AllowedAddressesSchema = object({
22549
22676
  * Network Addresses admin page and persisted by the addon.
22550
22677
  */
22551
22678
  addresses: array(string()).readonly() });
22679
+ var TlsStatusSchema = object({
22680
+ mode: _enum([
22681
+ "generated",
22682
+ "uploaded",
22683
+ "disabled"
22684
+ ]),
22685
+ leafFingerprintSha256: string().nullable(),
22686
+ caFingerprintSha256: string().nullable(),
22687
+ validTo: string().nullable(),
22688
+ sans: array(string()),
22689
+ caCertPem: string().nullable(),
22690
+ reissueError: string().nullable(),
22691
+ restartRequired: boolean()
22692
+ });
22552
22693
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22553
22694
  /**
22554
22695
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22558,17 +22699,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22558
22699
  */
22559
22700
  port: number().int().min(1).max(65535).optional(),
22560
22701
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22561
- * candidate. Default `true`. */
22702
+ * candidate. Default `false` — loopback is not a client route. */
22562
22703
  includeLoopback: boolean().optional(),
22563
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22564
- * Default `false`. */
22704
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22705
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22706
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22565
22707
  ipv4Only: boolean().optional(),
22566
22708
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22567
22709
  * Pass `'https'` when the caller is itself loaded over HTTPS
22568
22710
  * to avoid mixed-content blocks in the browser. The public
22569
22711
  * tunnel always emits `https://` regardless. */
22570
22712
  scheme: _enum(["http", "https"]).optional()
22571
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
22713
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
22714
+ kind: "mutation",
22715
+ auth: "admin"
22716
+ }), method(object({
22717
+ certPem: string().min(1),
22718
+ keyPem: string().min(1),
22719
+ caPem: string().optional()
22720
+ }), TlsStatusSchema, {
22721
+ kind: "mutation",
22722
+ auth: "admin"
22723
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22724
+ kind: "mutation",
22725
+ auth: "admin"
22726
+ });
22572
22727
  object({
22573
22728
  /** Lifecycle state of the lock. `jammed` means the motor reported
22574
22729
  * failure to reach the target — operator intervention required. */
@@ -28331,6 +28486,12 @@ Object.freeze({
28331
28486
  addonId: null,
28332
28487
  access: "create"
28333
28488
  },
28489
+ "localNetwork.downloadCa": {
28490
+ capName: "local-network",
28491
+ capScope: "system",
28492
+ addonId: null,
28493
+ access: "view"
28494
+ },
28334
28495
  "localNetwork.getAllowedAddresses": {
28335
28496
  capName: "local-network",
28336
28497
  capScope: "system",
@@ -28355,18 +28516,42 @@ Object.freeze({
28355
28516
  addonId: null,
28356
28517
  access: "view"
28357
28518
  },
28519
+ "localNetwork.getTlsStatus": {
28520
+ capName: "local-network",
28521
+ capScope: "system",
28522
+ addonId: null,
28523
+ access: "view"
28524
+ },
28525
+ "localNetwork.getViewerEndpoints": {
28526
+ capName: "local-network",
28527
+ capScope: "system",
28528
+ addonId: null,
28529
+ access: "view"
28530
+ },
28358
28531
  "localNetwork.list": {
28359
28532
  capName: "local-network",
28360
28533
  capScope: "system",
28361
28534
  addonId: null,
28362
28535
  access: "view"
28363
28536
  },
28537
+ "localNetwork.regenerateCertificate": {
28538
+ capName: "local-network",
28539
+ capScope: "system",
28540
+ addonId: null,
28541
+ access: "create"
28542
+ },
28364
28543
  "localNetwork.resetAllowlistToBestMatch": {
28365
28544
  capName: "local-network",
28366
28545
  capScope: "system",
28367
28546
  addonId: null,
28368
28547
  access: "delete"
28369
28548
  },
28549
+ "localNetwork.revertToGeneratedCertificate": {
28550
+ capName: "local-network",
28551
+ capScope: "system",
28552
+ addonId: null,
28553
+ access: "create"
28554
+ },
28370
28555
  "localNetwork.setAllowedAddresses": {
28371
28556
  capName: "local-network",
28372
28557
  capScope: "system",
@@ -28379,6 +28564,18 @@ Object.freeze({
28379
28564
  addonId: null,
28380
28565
  access: "create"
28381
28566
  },
28567
+ "localNetwork.setViewerEndpoints": {
28568
+ capName: "local-network",
28569
+ capScope: "system",
28570
+ addonId: null,
28571
+ access: "create"
28572
+ },
28573
+ "localNetwork.uploadCertificate": {
28574
+ capName: "local-network",
28575
+ capScope: "system",
28576
+ addonId: null,
28577
+ access: "create"
28578
+ },
28382
28579
  "lockControl.lock": {
28383
28580
  capName: "lock-control",
28384
28581
  capScope: "device",
@@ -31259,6 +31456,12 @@ Object.freeze({
31259
31456
  addonId: null,
31260
31457
  access: "create"
31261
31458
  },
31459
+ "terminalSession.updateInstance": {
31460
+ capName: "terminal-session",
31461
+ capScope: "system",
31462
+ addonId: null,
31463
+ access: "create"
31464
+ },
31262
31465
  "terminalSession.writeInput": {
31263
31466
  capName: "terminal-session",
31264
31467
  capScope: "system",
@@ -33746,6 +33949,35 @@ Object.freeze(Object.fromEntries([{
33746
33949
  }]
33747
33950
  }].map((s) => [s.stepId, s.defaultModelId])));
33748
33951
  string().min(1);
33952
+ var CLUSTER_STEP_SETTING_FIELDS = [{
33953
+ stepId: "face-embedding",
33954
+ key: "minLandmarkFaceSize",
33955
+ label: "Min face size for recognition (detection px)",
33956
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
33957
+ type: "slider",
33958
+ min: 0,
33959
+ max: 64,
33960
+ step: 2,
33961
+ default: 24
33962
+ }];
33963
+ function clusterStepSettingKey(stepId, fieldKey) {
33964
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
33965
+ }
33966
+ var ClusterSettingNumberSchema = number().finite();
33967
+ function readClusterStepSettings(config) {
33968
+ const out = {};
33969
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
33970
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
33971
+ const value = parsed.success ? parsed.data : field.default;
33972
+ const existing = out[field.stepId] ?? {};
33973
+ out[field.stepId] = {
33974
+ ...existing,
33975
+ [field.key]: value
33976
+ };
33977
+ }
33978
+ return out;
33979
+ }
33980
+ readClusterStepSettings({});
33749
33981
  object({
33750
33982
  /**
33751
33983
  * Fraction of the box's own size added on EACH side before cutting.
@@ -33916,7 +34148,7 @@ var AgentUIAddon = class extends BaseAddon {
33916
34148
  capability: adminUiCapability,
33917
34149
  provider: {
33918
34150
  getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
33919
- getVersion: async () => ({ version: "1.2.27" })
34151
+ getVersion: async () => ({ version: "1.2.28" })
33920
34152
  }
33921
34153
  }];
33922
34154
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-agent-ui",
3
- "version": "1.2.27",
3
+ "version": "1.2.28",
4
4
  "description": "Agent UI — lightweight status dashboard served by every agent node",
5
5
  "keywords": [
6
6
  "camstack",