@camstack/types 1.2.319 → 1.2.321
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/addon.js +13 -4
- package/dist/addon.mjs +13 -4
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +89 -81
- package/dist/client.js +1 -0
- package/dist/client.mjs +1 -0
- package/dist/generated/addon-api.d.ts +7 -0
- package/dist/generated/device-proxy.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +612 -378
- package/dist/index.mjs +593 -374
- package/dist/interfaces/config-ui.d.ts +2 -59
- package/dist/pipeline/auto-tune/index.d.ts +3 -4
- package/dist/pipeline/auto-tune/plan-schemas.d.ts +59 -151
- package/dist/pipeline/auto-tune/recommend.d.ts +18 -8
- package/dist/pipeline/load-balancing/capacity-shares.d.ts +37 -0
- package/dist/pipeline/load-balancing/effective-shares.d.ts +8 -3
- package/dist/pipeline/load-balancing/index.d.ts +3 -2
- package/dist/pipeline/load-balancing/schemas.d.ts +81 -12
- package/dist/pipeline/step-settings-layers.d.ts +69 -0
- package/dist/{sleep-DyF95STh.js → sleep-AalHiRYL.js} +1 -0
- package/dist/{sleep-C16NCZR2.mjs → sleep-DAJ9Er57.mjs} +1 -0
- package/dist/types/agent-pipeline-settings.d.ts +11 -0
- package/package.json +1 -1
- package/dist/pipeline/auto-tune/demand.d.ts +0 -75
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
2
|
+
const require_sleep = require("./sleep-AalHiRYL.js");
|
|
3
3
|
const require_event_category = require("./event-category-DmS_tLsU.js");
|
|
4
4
|
const require_composition = require("./composition-BLWAivB2.js");
|
|
5
5
|
const require_err_msg = require("./err-msg-Dx2Kor0g.js");
|
|
@@ -27242,175 +27242,21 @@ var pipelineExecutorCapability = {
|
|
|
27242
27242
|
}
|
|
27243
27243
|
};
|
|
27244
27244
|
//#endregion
|
|
27245
|
-
//#region src/pipeline/load-balancing/schemas.ts
|
|
27246
|
-
/**
|
|
27247
|
-
* Wire shapes of the Load balancing surface (D748): the session placement
|
|
27248
|
-
* policy, the atomic share write, the observed placement statistics, the
|
|
27249
|
-
* hardware share suggestion and the stale device pins.
|
|
27250
|
-
*/
|
|
27251
|
-
/**
|
|
27252
|
-
* How a new detection session picks its node and device.
|
|
27253
|
-
* - `least-loaded` — the historical rule: lowest `attached / weight`, a
|
|
27254
|
-
* constant node order at a tie (D37). An idle node always ties at 0, so a
|
|
27255
|
-
* weight only bites once a node already holds a session.
|
|
27256
|
-
* - `share` — the share of PARALLEL sessions is held to the weights, and a
|
|
27257
|
-
* full or drowning node yields to a free one (D748).
|
|
27258
|
-
*/
|
|
27259
|
-
var SessionPlacementPolicySchema = zod.z.enum(["least-loaded", "share"]);
|
|
27260
|
-
/**
|
|
27261
|
-
* `share` since D750: the percentages are held by default. `least-loaded` stays
|
|
27262
|
-
* selectable.
|
|
27263
|
-
*/
|
|
27264
|
-
var DEFAULT_SESSION_PLACEMENT_POLICY = "share";
|
|
27265
|
-
/** The global-settings key the policy is stored under (orchestrator `load` section). */
|
|
27266
|
-
var SESSION_PLACEMENT_SETTING_KEY = "sessionPlacement";
|
|
27267
|
-
/** Parse a stored value; anything unknown is the default. */
|
|
27268
|
-
function parseSessionPlacementPolicy(value) {
|
|
27269
|
-
const parsed = SessionPlacementPolicySchema.safeParse(value);
|
|
27270
|
-
return parsed.success ? parsed.data : DEFAULT_SESSION_PLACEMENT_POLICY;
|
|
27271
|
-
}
|
|
27272
|
-
var LoadBalancingSharesInputSchema = zod.z.object({
|
|
27273
|
-
/** nodeId → share (> 0). A node left out keeps its weight. */
|
|
27274
|
-
nodes: zod.z.record(zod.z.string(), zod.z.number().positive()).default({}),
|
|
27275
|
-
/** nodeId → deviceKey → share (> 0). A device left out keeps its weight. */
|
|
27276
|
-
devices: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.number().positive())).default({})
|
|
27277
|
-
});
|
|
27278
|
-
var PlacementStatsInputSchema = zod.z.object({
|
|
27279
|
-
/** Window the observed shares are averaged over (default 1 h, max 24 h). */
|
|
27280
|
-
windowMs: zod.z.number().int().min(6e4).max(1440 * 60 * 1e3).default(3600 * 1e3) });
|
|
27281
|
-
var PlacementDeviceStatsSchema = zod.z.object({
|
|
27282
|
-
deviceKey: zod.z.string(),
|
|
27283
|
-
/** Sessions running on this device now. */
|
|
27284
|
-
sessionsNow: zod.z.number(),
|
|
27285
|
-
/** Sessions started on this device inside the window. */
|
|
27286
|
-
sessionsStarted: zod.z.number(),
|
|
27287
|
-
/** Time-weighted share of the node's parallel sessions over the window (0–1); null = no session ran. */
|
|
27288
|
-
observedShare: zod.z.number().nullable()
|
|
27289
|
-
});
|
|
27290
|
-
var PlacementNodeStatsSchema = zod.z.object({
|
|
27291
|
-
nodeId: zod.z.string(),
|
|
27292
|
-
sessionsNow: zod.z.number(),
|
|
27293
|
-
sessionsStarted: zod.z.number(),
|
|
27294
|
-
/** Time-weighted share of the cluster's parallel sessions over the window (0–1); null = none ran. */
|
|
27295
|
-
observedShare: zod.z.number().nullable(),
|
|
27296
|
-
/** Most sessions this node ran at once inside the window. */
|
|
27297
|
-
peakSessions: zod.z.number(),
|
|
27298
|
-
/** Sessions a share election handed elsewhere because this node was full or drowning. */
|
|
27299
|
-
yieldsAway: zod.z.number(),
|
|
27300
|
-
devices: zod.z.array(PlacementDeviceStatsSchema).readonly()
|
|
27301
|
-
});
|
|
27302
|
-
/** A camera's device pin that the session path cannot honour. */
|
|
27303
|
-
var StaleDevicePinSchema = zod.z.object({
|
|
27304
|
-
deviceId: zod.z.number(),
|
|
27305
|
-
deviceKey: zod.z.string(),
|
|
27306
|
-
/** `disabled` — the key exists on some node but is not enabled anywhere; `absent` — no node has it. */
|
|
27307
|
-
reason: zod.z.enum(["disabled", "absent"])
|
|
27308
|
-
});
|
|
27309
|
-
var PlacementStatsSchema = zod.z.object({
|
|
27310
|
-
policy: SessionPlacementPolicySchema,
|
|
27311
|
-
windowMs: zod.z.number(),
|
|
27312
|
-
/** How much of the window was actually observed (the hub keeps it in memory). */
|
|
27313
|
-
observedForMs: zod.z.number(),
|
|
27314
|
-
sessionsNow: zod.z.number(),
|
|
27315
|
-
/** Most parallel sessions across the cluster inside the window. */
|
|
27316
|
-
clusterPeakSessions: zod.z.number(),
|
|
27317
|
-
nodes: zod.z.array(PlacementNodeStatsSchema).readonly(),
|
|
27318
|
-
stalePins: zod.z.array(StaleDevicePinSchema).readonly()
|
|
27319
|
-
});
|
|
27320
|
-
var SuggestSharesInputSchema = zod.z.object({ headroom: zod.z.number().min(.3).max(.5).default(.4) });
|
|
27321
|
-
var SuggestedDeviceShareSchema = zod.z.object({
|
|
27322
|
-
deviceKey: zod.z.string(),
|
|
27323
|
-
/** Share of the node (0–100, rounded). */
|
|
27324
|
-
share: zod.z.number(),
|
|
27325
|
-
modelId: zod.z.string().nullable(),
|
|
27326
|
-
/** Inferences per second at that model, from the measured table. */
|
|
27327
|
-
fps: zod.z.number().nullable(),
|
|
27328
|
-
measured: zod.z.boolean(),
|
|
27329
|
-
/** Advisory session cap: ⌊fps × (1 − headroom) / camera fps⌋. Never enforced. */
|
|
27330
|
-
suggestedMaxSessions: zod.z.number().nullable()
|
|
27331
|
-
});
|
|
27332
|
-
var SuggestedNodeShareSchema = zod.z.object({
|
|
27333
|
-
nodeId: zod.z.string(),
|
|
27334
|
-
/** Share of the cluster (0–100, rounded); null = node skipped (offline, unknown hardware). */
|
|
27335
|
-
share: zod.z.number().nullable(),
|
|
27336
|
-
/** Parallel sessions the node sustains at the suggested models with the headroom kept free. */
|
|
27337
|
-
capacitySessions: zod.z.number(),
|
|
27338
|
-
devices: zod.z.array(SuggestedDeviceShareSchema).readonly(),
|
|
27339
|
-
skippedReason: zod.z.string().nullable()
|
|
27340
|
-
});
|
|
27341
|
-
var SuggestSharesResultSchema = zod.z.object({
|
|
27342
|
-
headroom: zod.z.number(),
|
|
27343
|
-
/** Camera detection rate the capacity is counted in (the fastest camera's fps). */
|
|
27344
|
-
cameraFps: zod.z.number(),
|
|
27345
|
-
/** How many share → model → capacity rounds ran before the shares stopped moving (≤ 3). */
|
|
27346
|
-
iterations: zod.z.number(),
|
|
27347
|
-
nodes: zod.z.array(SuggestedNodeShareSchema).readonly()
|
|
27348
|
-
});
|
|
27349
|
-
/**
|
|
27350
|
-
* Where the node and device shares come from (D750).
|
|
27351
|
-
* - `auto` — computed by the system from the cluster's measured capacity at
|
|
27352
|
-
* the Auto tune models, and recomputed whenever a node or device joins,
|
|
27353
|
-
* leaves, is switched on or off, or changes model.
|
|
27354
|
-
* - `manual` — the operator's stored sliders. A node or device that cannot
|
|
27355
|
-
* take sessions gives its share to the others in proportion; the stored
|
|
27356
|
-
* values are never rewritten for that.
|
|
27357
|
-
*/
|
|
27358
|
-
var ShareSourceSchema = zod.z.enum(["auto", "manual"]);
|
|
27359
|
-
var DEFAULT_SHARE_SOURCE = "auto";
|
|
27360
|
-
/** Headroom the automatic shares are computed at (Auto tune's default). */
|
|
27361
|
-
var AUTO_SHARE_HEADROOM = .4;
|
|
27362
|
-
/** The global-settings key the share source is stored under (orchestrator `load` section). */
|
|
27363
|
-
var SHARE_SOURCE_SETTING_KEY = "shareSource";
|
|
27364
|
-
/** Parse a stored value; anything unknown is the default. */
|
|
27365
|
-
function parseShareSource(value) {
|
|
27366
|
-
const parsed = ShareSourceSchema.safeParse(value);
|
|
27367
|
-
return parsed.success ? parsed.data : DEFAULT_SHARE_SOURCE;
|
|
27368
|
-
}
|
|
27369
|
-
var SetShareSourceInputSchema = zod.z.object({ source: ShareSourceSchema });
|
|
27370
|
-
/** Raw relative weights (any scale) per node and per node's device. */
|
|
27371
|
-
var ShareWeightsSchema = zod.z.object({
|
|
27372
|
-
nodes: zod.z.record(zod.z.string(), zod.z.number()),
|
|
27373
|
-
devices: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.number()))
|
|
27374
|
-
});
|
|
27375
|
-
var EffectiveDeviceShareSchema = zod.z.object({
|
|
27376
|
-
deviceKey: zod.z.string(),
|
|
27377
|
-
/** Can take sessions now (enabled, available, can run the root). */
|
|
27378
|
-
eligible: zod.z.boolean(),
|
|
27379
|
-
/** The share the source assigns, as a percentage of the node's devices. */
|
|
27380
|
-
configuredPct: zod.z.number(),
|
|
27381
|
-
/** The share actually used, after an ineligible device's share went to the others. */
|
|
27382
|
-
effectivePct: zod.z.number()
|
|
27383
|
-
});
|
|
27384
|
-
var EffectiveNodeShareSchema = zod.z.object({
|
|
27385
|
-
nodeId: zod.z.string(),
|
|
27386
|
-
eligible: zod.z.boolean(),
|
|
27387
|
-
configuredPct: zod.z.number(),
|
|
27388
|
-
effectivePct: zod.z.number(),
|
|
27389
|
-
devices: zod.z.array(EffectiveDeviceShareSchema).readonly()
|
|
27390
|
-
});
|
|
27391
|
-
var EffectiveSharesSchema = zod.z.object({
|
|
27392
|
-
source: ShareSourceSchema,
|
|
27393
|
-
policy: SessionPlacementPolicySchema,
|
|
27394
|
-
/** `auto` with no computed answer yet: the stored sliders are used meanwhile. */
|
|
27395
|
-
autoPending: zod.z.boolean(),
|
|
27396
|
-
/** When the automatic shares were last computed (ms epoch); null = never. */
|
|
27397
|
-
computedAt: zod.z.number().nullable(),
|
|
27398
|
-
/** What made the system recompute them last. */
|
|
27399
|
-
trigger: zod.z.string().nullable(),
|
|
27400
|
-
nodes: zod.z.array(EffectiveNodeShareSchema).readonly(),
|
|
27401
|
-
/** The relative weights the election reads (before eligibility). */
|
|
27402
|
-
nodeWeights: zod.z.record(zod.z.string(), zod.z.number()),
|
|
27403
|
-
deviceWeights: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.number()))
|
|
27404
|
-
});
|
|
27405
|
-
//#endregion
|
|
27406
27245
|
//#region src/pipeline/auto-tune/plan-schemas.ts
|
|
27407
27246
|
/**
|
|
27408
27247
|
* The wire shapes of the Auto tune plan and apply (D745), used by the
|
|
27409
27248
|
* `pipeline-orchestrator` cap. The recommender's own types
|
|
27410
|
-
* (`recommend.ts
|
|
27249
|
+
* (`recommend.ts`) are the TS face of the same data; these
|
|
27411
27250
|
* schemas are what crosses the cap boundary.
|
|
27412
27251
|
*/
|
|
27413
27252
|
var ModelFormatSchema$1 = zod.z.enum(MODEL_FORMATS);
|
|
27253
|
+
/** Default least number of parallel sessions per device Auto tune keeps (D755). */
|
|
27254
|
+
var DEFAULT_MIN_SESSIONS_PER_DEVICE = 2;
|
|
27255
|
+
/** The operator's range for it. */
|
|
27256
|
+
var MIN_SESSIONS_PER_DEVICE_RANGE = {
|
|
27257
|
+
min: 1,
|
|
27258
|
+
max: 8
|
|
27259
|
+
};
|
|
27414
27260
|
var HardwareClassIdSchema = zod.z.enum([
|
|
27415
27261
|
"intel-core-ultra",
|
|
27416
27262
|
"intel-n-series",
|
|
@@ -27428,8 +27274,9 @@ var AcceleratorKindSchema = zod.z.enum([
|
|
|
27428
27274
|
]);
|
|
27429
27275
|
var RecommendationReasonSchema = zod.z.discriminatedUnion("kind", [
|
|
27430
27276
|
zod.z.object({
|
|
27431
|
-
kind: zod.z.literal("
|
|
27432
|
-
|
|
27277
|
+
kind: zod.z.literal("capacity"),
|
|
27278
|
+
sessions: zod.z.number(),
|
|
27279
|
+
minSessions: zod.z.number()
|
|
27433
27280
|
}),
|
|
27434
27281
|
zod.z.object({
|
|
27435
27282
|
kind: zod.z.literal("tie-faster"),
|
|
@@ -27444,16 +27291,13 @@ var RecommendationReasonSchema = zod.z.discriminatedUnion("kind", [
|
|
|
27444
27291
|
}),
|
|
27445
27292
|
zod.z.object({
|
|
27446
27293
|
kind: zod.z.literal("no-fit-lightest"),
|
|
27447
|
-
|
|
27294
|
+
sessions: zod.z.number(),
|
|
27295
|
+
minSessions: zod.z.number()
|
|
27448
27296
|
}),
|
|
27449
27297
|
zod.z.object({
|
|
27450
27298
|
kind: zod.z.literal("derived-latency"),
|
|
27451
27299
|
modelId: zod.z.string()
|
|
27452
27300
|
}),
|
|
27453
|
-
zod.z.object({
|
|
27454
|
-
kind: zod.z.literal("estimated-load"),
|
|
27455
|
-
observedForMs: zod.z.number().nullable()
|
|
27456
|
-
}),
|
|
27457
27301
|
zod.z.object({ kind: zod.z.literal("cpu-device") }),
|
|
27458
27302
|
zod.z.object({ kind: zod.z.literal("coral-untouched") }),
|
|
27459
27303
|
zod.z.object({ kind: zod.z.literal("device-disabled") }),
|
|
@@ -27469,28 +27313,13 @@ var RecommendationReasonSchema = zod.z.discriminatedUnion("kind", [
|
|
|
27469
27313
|
format: ModelFormatSchema$1
|
|
27470
27314
|
})
|
|
27471
27315
|
]);
|
|
27472
|
-
var DeviceDemandSchema = zod.z.object({
|
|
27473
|
-
nodeId: zod.z.string(),
|
|
27474
|
-
deviceKey: zod.z.string(),
|
|
27475
|
-
demandFps: zod.z.number(),
|
|
27476
|
-
maxCameraFps: zod.z.number(),
|
|
27477
|
-
alwaysOnCameras: zod.z.number(),
|
|
27478
|
-
onMotionSessions: zod.z.number(),
|
|
27479
|
-
onMotionSource: zod.z.enum([
|
|
27480
|
-
"observed-24h",
|
|
27481
|
-
"estimate",
|
|
27482
|
-
"none"
|
|
27483
|
-
]),
|
|
27484
|
-
observedForMs: zod.z.number().nullable(),
|
|
27485
|
-
/** How on-motion sessions were charged: per-device observation, or split by share (D748). */
|
|
27486
|
-
placement: SessionPlacementPolicySchema
|
|
27487
|
-
});
|
|
27488
27316
|
var DeviceModelChoiceSchema = zod.z.object({
|
|
27489
27317
|
modelId: zod.z.string(),
|
|
27490
27318
|
p50Ms: zod.z.number(),
|
|
27491
27319
|
fps: zod.z.number(),
|
|
27492
27320
|
measured: zod.z.boolean(),
|
|
27493
|
-
|
|
27321
|
+
/** Parallel sessions at the camera rate with the headroom kept free: ⌊fps × (1 − headroom) / camera fps⌋. */
|
|
27322
|
+
capacitySessions: zod.z.number(),
|
|
27494
27323
|
personRecall: zod.z.number()
|
|
27495
27324
|
});
|
|
27496
27325
|
var DeviceRecommendationSchema = zod.z.object({
|
|
@@ -27498,7 +27327,6 @@ var DeviceRecommendationSchema = zod.z.object({
|
|
|
27498
27327
|
accelerator: AcceleratorKindSchema.nullable(),
|
|
27499
27328
|
enabled: zod.z.boolean(),
|
|
27500
27329
|
available: zod.z.boolean(),
|
|
27501
|
-
demand: DeviceDemandSchema.nullable(),
|
|
27502
27330
|
chosen: DeviceModelChoiceSchema.nullable(),
|
|
27503
27331
|
reasons: zod.z.array(RecommendationReasonSchema).readonly()
|
|
27504
27332
|
});
|
|
@@ -27559,20 +27387,20 @@ var AutoTuneOptionsSchema = zod.z.object({
|
|
|
27559
27387
|
/** Share of each accelerator's throughput kept free (0.3–0.5). */
|
|
27560
27388
|
headroom: zod.z.number().min(.3).max(.5).default(.4),
|
|
27561
27389
|
/**
|
|
27562
|
-
*
|
|
27563
|
-
*
|
|
27564
|
-
*
|
|
27565
|
-
* is stored.
|
|
27390
|
+
* The least number of parallel sessions every device must sustain at the
|
|
27391
|
+
* camera rate with the headroom kept free (D755). The most accurate model
|
|
27392
|
+
* that reaches it wins.
|
|
27566
27393
|
*/
|
|
27567
|
-
|
|
27394
|
+
minSessionsPerDevice: zod.z.number().int().min(MIN_SESSIONS_PER_DEVICE_RANGE.min).max(MIN_SESSIONS_PER_DEVICE_RANGE.max).default(2)
|
|
27568
27395
|
});
|
|
27569
27396
|
var AutoTunePlanSchema = zod.z.object({
|
|
27570
27397
|
/** Hash of everything the apply will write — the apply refuses a different one. */
|
|
27571
27398
|
planHash: zod.z.string(),
|
|
27572
27399
|
family: zod.z.literal("yolov9"),
|
|
27573
27400
|
headroom: zod.z.number(),
|
|
27574
|
-
|
|
27575
|
-
|
|
27401
|
+
minSessionsPerDevice: zod.z.number(),
|
|
27402
|
+
/** The detection rate a session is counted at (the fastest camera running the pipeline root). */
|
|
27403
|
+
cameraFps: zod.z.number(),
|
|
27576
27404
|
generatedAt: zod.z.number(),
|
|
27577
27405
|
nodes: zod.z.array(NodeRecommendationSchema).readonly(),
|
|
27578
27406
|
nodeChanges: zod.z.array(NodeDeviceChangeSchema).readonly(),
|
|
@@ -27582,7 +27410,8 @@ var AutoTunePlanSchema = zod.z.object({
|
|
|
27582
27410
|
});
|
|
27583
27411
|
var AutoTuneApplyInputSchema = zod.z.object({
|
|
27584
27412
|
planHash: zod.z.string(),
|
|
27585
|
-
headroom: zod.z.number().min(.3).max(.5).default(.4)
|
|
27413
|
+
headroom: zod.z.number().min(.3).max(.5).default(.4),
|
|
27414
|
+
minSessionsPerDevice: zod.z.number().int().min(MIN_SESSIONS_PER_DEVICE_RANGE.min).max(MIN_SESSIONS_PER_DEVICE_RANGE.max).default(2)
|
|
27586
27415
|
});
|
|
27587
27416
|
var AutoTunePhaseResultSchema = zod.z.object({
|
|
27588
27417
|
phase: zod.z.enum([
|
|
@@ -27615,6 +27444,209 @@ var AutoTuneApplyResultSchema = zod.z.discriminatedUnion("kind", [
|
|
|
27615
27444
|
})
|
|
27616
27445
|
]);
|
|
27617
27446
|
//#endregion
|
|
27447
|
+
//#region src/pipeline/load-balancing/schemas.ts
|
|
27448
|
+
/**
|
|
27449
|
+
* Wire shapes of the Load balancing surface (D748): the session placement
|
|
27450
|
+
* policy, the atomic share write, the observed placement statistics, the
|
|
27451
|
+
* hardware share suggestion and the stale device pins.
|
|
27452
|
+
*/
|
|
27453
|
+
/**
|
|
27454
|
+
* How a new detection session picks its node and device.
|
|
27455
|
+
* - `least-loaded` — the historical rule: lowest `attached / weight`, a
|
|
27456
|
+
* constant node order at a tie (D37). An idle node always ties at 0, so a
|
|
27457
|
+
* weight only bites once a node already holds a session.
|
|
27458
|
+
* - `share` — the share of PARALLEL sessions is held to the weights, and a
|
|
27459
|
+
* full or drowning node yields to a free one (D748).
|
|
27460
|
+
*/
|
|
27461
|
+
var SessionPlacementPolicySchema = zod.z.enum(["least-loaded", "share"]);
|
|
27462
|
+
/**
|
|
27463
|
+
* `share` since D750: the percentages are held by default. `least-loaded` stays
|
|
27464
|
+
* selectable.
|
|
27465
|
+
*/
|
|
27466
|
+
var DEFAULT_SESSION_PLACEMENT_POLICY = "share";
|
|
27467
|
+
/** The global-settings key the policy is stored under (orchestrator `load` section). */
|
|
27468
|
+
var SESSION_PLACEMENT_SETTING_KEY = "sessionPlacement";
|
|
27469
|
+
/** Parse a stored value; anything unknown is the default. */
|
|
27470
|
+
function parseSessionPlacementPolicy(value) {
|
|
27471
|
+
const parsed = SessionPlacementPolicySchema.safeParse(value);
|
|
27472
|
+
return parsed.success ? parsed.data : DEFAULT_SESSION_PLACEMENT_POLICY;
|
|
27473
|
+
}
|
|
27474
|
+
var LoadBalancingSharesInputSchema = zod.z.object({
|
|
27475
|
+
/** nodeId → share (> 0). A node left out keeps its weight. */
|
|
27476
|
+
nodes: zod.z.record(zod.z.string(), zod.z.number().positive()).default({}),
|
|
27477
|
+
/** nodeId → deviceKey → share (> 0). A device left out keeps its weight. */
|
|
27478
|
+
devices: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.number().positive())).default({})
|
|
27479
|
+
});
|
|
27480
|
+
var PlacementStatsInputSchema = zod.z.object({
|
|
27481
|
+
/** Window the observed shares are averaged over (default 1 h, max 24 h). */
|
|
27482
|
+
windowMs: zod.z.number().int().min(6e4).max(1440 * 60 * 1e3).default(3600 * 1e3) });
|
|
27483
|
+
var PlacementDeviceStatsSchema = zod.z.object({
|
|
27484
|
+
deviceKey: zod.z.string(),
|
|
27485
|
+
/** Sessions running on this device now. */
|
|
27486
|
+
sessionsNow: zod.z.number(),
|
|
27487
|
+
/** Sessions started on this device inside the window. */
|
|
27488
|
+
sessionsStarted: zod.z.number(),
|
|
27489
|
+
/** Time-weighted share of the node's parallel sessions over the window (0–1); null = no session ran. */
|
|
27490
|
+
observedShare: zod.z.number().nullable()
|
|
27491
|
+
});
|
|
27492
|
+
var PlacementNodeStatsSchema = zod.z.object({
|
|
27493
|
+
nodeId: zod.z.string(),
|
|
27494
|
+
sessionsNow: zod.z.number(),
|
|
27495
|
+
sessionsStarted: zod.z.number(),
|
|
27496
|
+
/** Time-weighted share of the cluster's parallel sessions over the window (0–1); null = none ran. */
|
|
27497
|
+
observedShare: zod.z.number().nullable(),
|
|
27498
|
+
/** Most sessions this node ran at once inside the window. */
|
|
27499
|
+
peakSessions: zod.z.number(),
|
|
27500
|
+
/** Sessions a share election handed elsewhere because this node was full or drowning. */
|
|
27501
|
+
yieldsAway: zod.z.number(),
|
|
27502
|
+
devices: zod.z.array(PlacementDeviceStatsSchema).readonly()
|
|
27503
|
+
});
|
|
27504
|
+
/** A camera's device pin that the session path cannot honour. */
|
|
27505
|
+
var StaleDevicePinSchema = zod.z.object({
|
|
27506
|
+
deviceId: zod.z.number(),
|
|
27507
|
+
deviceKey: zod.z.string(),
|
|
27508
|
+
/** `disabled` — the key exists on some node but is not enabled anywhere; `absent` — no node has it. */
|
|
27509
|
+
reason: zod.z.enum(["disabled", "absent"])
|
|
27510
|
+
});
|
|
27511
|
+
var PlacementStatsSchema = zod.z.object({
|
|
27512
|
+
policy: SessionPlacementPolicySchema,
|
|
27513
|
+
windowMs: zod.z.number(),
|
|
27514
|
+
/** How much of the window was actually observed (the hub keeps it in memory). */
|
|
27515
|
+
observedForMs: zod.z.number(),
|
|
27516
|
+
sessionsNow: zod.z.number(),
|
|
27517
|
+
/** Most parallel sessions across the cluster inside the window. */
|
|
27518
|
+
clusterPeakSessions: zod.z.number(),
|
|
27519
|
+
nodes: zod.z.array(PlacementNodeStatsSchema).readonly(),
|
|
27520
|
+
stalePins: zod.z.array(StaleDevicePinSchema).readonly()
|
|
27521
|
+
});
|
|
27522
|
+
/**
|
|
27523
|
+
* Where an automatic share's capacity comes from (D755).
|
|
27524
|
+
* - `hardware` — the static capacity of each device at its Auto tune model:
|
|
27525
|
+
* the measured latency table for the node's hardware class.
|
|
27526
|
+
* - `benchmark` — the node's own measured capacity (node benchmark results).
|
|
27527
|
+
* A node with no results falls back to `hardware`, and says so.
|
|
27528
|
+
*/
|
|
27529
|
+
var CapacitySourceSchema = zod.z.enum(["hardware", "benchmark"]);
|
|
27530
|
+
/** Why a node under the `benchmark` source was sized from hardware instead. */
|
|
27531
|
+
var CapacityFallbackSchema = zod.z.enum(["no-benchmark-results", "partial-benchmark-results"]);
|
|
27532
|
+
var SuggestSharesInputSchema = zod.z.object({
|
|
27533
|
+
headroom: zod.z.number().min(.3).max(.5).default(.4),
|
|
27534
|
+
/** Default `hardware`. */
|
|
27535
|
+
source: CapacitySourceSchema.default("hardware")
|
|
27536
|
+
});
|
|
27537
|
+
var SuggestedDeviceShareSchema = zod.z.object({
|
|
27538
|
+
deviceKey: zod.z.string(),
|
|
27539
|
+
/** Share of the node (0–100, rounded). */
|
|
27540
|
+
share: zod.z.number(),
|
|
27541
|
+
modelId: zod.z.string().nullable(),
|
|
27542
|
+
/** Inferences per second at that model, from the measured table; null when sized by a benchmark. */
|
|
27543
|
+
fps: zod.z.number().nullable(),
|
|
27544
|
+
/** False for a table cell derived from another chip; true for a measured cell or a benchmark. */
|
|
27545
|
+
measured: zod.z.boolean(),
|
|
27546
|
+
/**
|
|
27547
|
+
* Advisory session cap: ⌊fps × (1 − headroom) / camera fps⌋ from the table,
|
|
27548
|
+
* or the benchmark's measured max sessions. Never enforced.
|
|
27549
|
+
*/
|
|
27550
|
+
suggestedMaxSessions: zod.z.number().nullable()
|
|
27551
|
+
});
|
|
27552
|
+
var SuggestedNodeShareSchema = zod.z.object({
|
|
27553
|
+
nodeId: zod.z.string(),
|
|
27554
|
+
/** Share of the cluster (0–100, rounded); null = node skipped (offline, unknown hardware). */
|
|
27555
|
+
share: zod.z.number().nullable(),
|
|
27556
|
+
/** Parallel sessions the node sustains at the suggested models with the headroom kept free. */
|
|
27557
|
+
capacitySessions: zod.z.number(),
|
|
27558
|
+
devices: zod.z.array(SuggestedDeviceShareSchema).readonly(),
|
|
27559
|
+
skippedReason: zod.z.string().nullable(),
|
|
27560
|
+
/** What this node's capacity was read from; null when the node is skipped. */
|
|
27561
|
+
capacitySource: CapacitySourceSchema.nullable(),
|
|
27562
|
+
/** Set when the `benchmark` source was asked for and this node used `hardware`. */
|
|
27563
|
+
capacityFallback: CapacityFallbackSchema.nullable()
|
|
27564
|
+
});
|
|
27565
|
+
var SuggestSharesResultSchema = zod.z.object({
|
|
27566
|
+
headroom: zod.z.number(),
|
|
27567
|
+
/** The source asked for; each node says what it actually used. */
|
|
27568
|
+
source: CapacitySourceSchema,
|
|
27569
|
+
/** Camera detection rate the capacity is counted in (the fastest camera's fps). */
|
|
27570
|
+
cameraFps: zod.z.number(),
|
|
27571
|
+
/** The Auto tune capacity floor the models were picked at. */
|
|
27572
|
+
minSessionsPerDevice: zod.z.number(),
|
|
27573
|
+
nodes: zod.z.array(SuggestedNodeShareSchema).readonly()
|
|
27574
|
+
});
|
|
27575
|
+
/**
|
|
27576
|
+
* Where the node and device shares come from (D750, D755).
|
|
27577
|
+
* - `hardware` (default) — computed by the system from each node's static
|
|
27578
|
+
* capacity (its accelerators at their Auto tune models, from the measured
|
|
27579
|
+
* latency table), recomputed whenever a node or device joins, leaves, is
|
|
27580
|
+
* switched on or off, or changes model. No load input.
|
|
27581
|
+
* - `benchmark` — the same, from each node's measured capacity (node
|
|
27582
|
+
* benchmark results); a node without results falls back to `hardware`.
|
|
27583
|
+
* - `manual` — the operator's stored sliders.
|
|
27584
|
+
* Either way a node or device that cannot take sessions gives its share to
|
|
27585
|
+
* the others in proportion; the stored values are never rewritten for that.
|
|
27586
|
+
*/
|
|
27587
|
+
var ShareSourceSchema = zod.z.enum([
|
|
27588
|
+
"hardware",
|
|
27589
|
+
"benchmark",
|
|
27590
|
+
"manual"
|
|
27591
|
+
]);
|
|
27592
|
+
var DEFAULT_SHARE_SOURCE = "hardware";
|
|
27593
|
+
/** `hardware` or `benchmark`: the system computes the shares. */
|
|
27594
|
+
function isAutomaticShareSource(source) {
|
|
27595
|
+
return source !== "manual";
|
|
27596
|
+
}
|
|
27597
|
+
/** Headroom the automatic shares are computed at (Auto tune's default). */
|
|
27598
|
+
var AUTO_SHARE_HEADROOM = .4;
|
|
27599
|
+
/** The global-settings key the share source is stored under (orchestrator `load` section). */
|
|
27600
|
+
var SHARE_SOURCE_SETTING_KEY = "shareSource";
|
|
27601
|
+
/**
|
|
27602
|
+
* Parse a stored value; anything unknown is the default. `auto` (D750, before
|
|
27603
|
+
* D755 split it) reads as `hardware` — that is what it computed.
|
|
27604
|
+
*/
|
|
27605
|
+
function parseShareSource(value) {
|
|
27606
|
+
const parsed = ShareSourceSchema.safeParse(value);
|
|
27607
|
+
return parsed.success ? parsed.data : DEFAULT_SHARE_SOURCE;
|
|
27608
|
+
}
|
|
27609
|
+
var SetShareSourceInputSchema = zod.z.object({ source: ShareSourceSchema });
|
|
27610
|
+
/** Raw relative weights (any scale) per node and per node's device. */
|
|
27611
|
+
var ShareWeightsSchema = zod.z.object({
|
|
27612
|
+
nodes: zod.z.record(zod.z.string(), zod.z.number()),
|
|
27613
|
+
devices: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.number()))
|
|
27614
|
+
});
|
|
27615
|
+
var EffectiveDeviceShareSchema = zod.z.object({
|
|
27616
|
+
deviceKey: zod.z.string(),
|
|
27617
|
+
/** Can take sessions now (enabled, available, can run the root). */
|
|
27618
|
+
eligible: zod.z.boolean(),
|
|
27619
|
+
/** The share the source assigns, as a percentage of the node's devices. */
|
|
27620
|
+
configuredPct: zod.z.number(),
|
|
27621
|
+
/** The share actually used, after an ineligible device's share went to the others. */
|
|
27622
|
+
effectivePct: zod.z.number()
|
|
27623
|
+
});
|
|
27624
|
+
var EffectiveNodeShareSchema = zod.z.object({
|
|
27625
|
+
nodeId: zod.z.string(),
|
|
27626
|
+
eligible: zod.z.boolean(),
|
|
27627
|
+
configuredPct: zod.z.number(),
|
|
27628
|
+
effectivePct: zod.z.number(),
|
|
27629
|
+
/** Automatic sources: what this node's share was computed from; null under `manual` or before the first answer. */
|
|
27630
|
+
capacitySource: CapacitySourceSchema.nullable(),
|
|
27631
|
+
/** Automatic `benchmark`: why this node used `hardware` instead. */
|
|
27632
|
+
capacityFallback: CapacityFallbackSchema.nullable(),
|
|
27633
|
+
devices: zod.z.array(EffectiveDeviceShareSchema).readonly()
|
|
27634
|
+
});
|
|
27635
|
+
var EffectiveSharesSchema = zod.z.object({
|
|
27636
|
+
source: ShareSourceSchema,
|
|
27637
|
+
policy: SessionPlacementPolicySchema,
|
|
27638
|
+
/** An automatic source with no computed answer yet: the stored sliders are used meanwhile. */
|
|
27639
|
+
autoPending: zod.z.boolean(),
|
|
27640
|
+
/** When the automatic shares were last computed (ms epoch); null = never. */
|
|
27641
|
+
computedAt: zod.z.number().nullable(),
|
|
27642
|
+
/** What made the system recompute them last. */
|
|
27643
|
+
trigger: zod.z.string().nullable(),
|
|
27644
|
+
nodes: zod.z.array(EffectiveNodeShareSchema).readonly(),
|
|
27645
|
+
/** The relative weights the election reads (before eligibility). */
|
|
27646
|
+
nodeWeights: zod.z.record(zod.z.string(), zod.z.number()),
|
|
27647
|
+
deviceWeights: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.number()))
|
|
27648
|
+
});
|
|
27649
|
+
//#endregion
|
|
27618
27650
|
//#region src/capabilities/schemas/orchestrator-metrics.ts
|
|
27619
27651
|
/** Shared Zod schemas for the runtime pipeline orchestrator metrics. */
|
|
27620
27652
|
var OrchestratorMetricsSchema = zod.z.object({
|
|
@@ -29227,8 +29259,10 @@ var CameraStepOverridePatchSchema = zod.z.object({
|
|
|
29227
29259
|
modelId: zod.z.string().optional(),
|
|
29228
29260
|
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly().optional()
|
|
29229
29261
|
});
|
|
29262
|
+
var CameraStepSettingsSchema = zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.unknown()).readonly());
|
|
29230
29263
|
var CameraPipelineSettingsSchema = zod.z.object({
|
|
29231
29264
|
stepToggles: zod.z.record(zod.z.string(), zod.z.boolean()).optional(),
|
|
29265
|
+
stepSettings: CameraStepSettingsSchema.optional(),
|
|
29232
29266
|
stepOverridesByDevice: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), CameraStepOverridePatchSchema))).optional(),
|
|
29233
29267
|
pipelineByAgent: zod.z.record(zod.z.string(), CameraPipelineForAgentSchema).optional()
|
|
29234
29268
|
});
|
|
@@ -30040,9 +30074,11 @@ var pipelineOrchestratorCapability = {
|
|
|
30040
30074
|
auth: "admin"
|
|
30041
30075
|
}),
|
|
30042
30076
|
/**
|
|
30043
|
-
* Auto tune (D745) — DRY RUN. Recommends ONE detector family
|
|
30044
|
-
* for the whole cluster from each node's static hardware class
|
|
30045
|
-
* measured latency table
|
|
30077
|
+
* Auto tune (D745, D755) — DRY RUN. Recommends ONE detector family
|
|
30078
|
+
* (YOLOv9) for the whole cluster from each node's static hardware class
|
|
30079
|
+
* and the measured latency table: per device, the most accurate model
|
|
30080
|
+
* that sustains at least `minSessionsPerDevice` parallel sessions at the
|
|
30081
|
+
* camera rate with the headroom kept free (no load input), and lists every write
|
|
30046
30082
|
* the apply would make: the node model pins set, the enrichment pins and
|
|
30047
30083
|
* model-bound thresholds removed (node level and per camera), and the
|
|
30048
30084
|
* per-camera detector thresholds cleared. Writes nothing. Step
|
|
@@ -30081,10 +30117,12 @@ var pipelineOrchestratorCapability = {
|
|
|
30081
30117
|
*/
|
|
30082
30118
|
getPlacementStats: require_sleep.method(PlacementStatsInputSchema, PlacementStatsSchema, { auth: "admin" }),
|
|
30083
30119
|
/**
|
|
30084
|
-
* Load balancing (D748) — shares proportional to each node's
|
|
30085
|
-
* capacity
|
|
30086
|
-
*
|
|
30087
|
-
*
|
|
30120
|
+
* Load balancing (D748, D755) — shares proportional to each node's
|
|
30121
|
+
* capacity in parallel sessions: from the latency table at the models
|
|
30122
|
+
* Auto tune picks (`hardware`), or from node benchmark results
|
|
30123
|
+
* (`benchmark`, each node without results falling back to `hardware` and
|
|
30124
|
+
* saying so). The automatic shares are exactly this answer. Per device,
|
|
30125
|
+
* an ADVISORY session cap. Writes nothing.
|
|
30088
30126
|
*/
|
|
30089
30127
|
suggestShares: require_sleep.method(SuggestSharesInputSchema, SuggestSharesResultSchema, { auth: "admin" }),
|
|
30090
30128
|
/**
|
|
@@ -30095,9 +30133,11 @@ var pipelineOrchestratorCapability = {
|
|
|
30095
30133
|
*/
|
|
30096
30134
|
getEffectiveShares: require_sleep.method(zod.z.void(), EffectiveSharesSchema, { auth: "admin" }),
|
|
30097
30135
|
/**
|
|
30098
|
-
* Load balancing (D750) — switch
|
|
30099
|
-
*
|
|
30100
|
-
*
|
|
30136
|
+
* Load balancing (D750, D755) — switch the share source: `hardware`
|
|
30137
|
+
* (automatic, from static capacity), `benchmark` (automatic, from node
|
|
30138
|
+
* benchmark results) or `manual`. Going manual seeds the sliders with the
|
|
30139
|
+
* current automatic shares (one atomic write), so nothing jumps; going
|
|
30140
|
+
* to an automatic source recomputes at once.
|
|
30101
30141
|
*/
|
|
30102
30142
|
setShareSource: require_sleep.method(SetShareSourceInputSchema, zod.z.object({ success: zod.z.literal(true) }), {
|
|
30103
30143
|
kind: "mutation",
|
|
@@ -30132,6 +30172,22 @@ var pipelineOrchestratorCapability = {
|
|
|
30132
30172
|
kind: "mutation",
|
|
30133
30173
|
auth: "admin"
|
|
30134
30174
|
}),
|
|
30175
|
+
/**
|
|
30176
|
+
* Write or clear one step's CAMERA-WIDE settings (D754) — the fields this
|
|
30177
|
+
* camera overrides on every accelerator it runs on. `settings` is the
|
|
30178
|
+
* whole field-level bag for that step (only the overridden keys; a
|
|
30179
|
+
* model-bound field travels with its binding key); `null` or `{}` clears
|
|
30180
|
+
* it. Merged at dispatch between the node base and the per-(node,device)
|
|
30181
|
+
* override, key by key.
|
|
30182
|
+
*/
|
|
30183
|
+
setCameraStepSettings: require_sleep.method(zod.z.object({
|
|
30184
|
+
deviceId: zod.z.number(),
|
|
30185
|
+
addonId: zod.z.string(),
|
|
30186
|
+
settings: zod.z.record(zod.z.string(), zod.z.unknown()).nullable()
|
|
30187
|
+
}), zod.z.object({ success: zod.z.literal(true) }), {
|
|
30188
|
+
kind: "mutation",
|
|
30189
|
+
auth: "admin"
|
|
30190
|
+
}),
|
|
30135
30191
|
/** Write or clear the wholesale per-agent pipeline override. Pass `pipeline: null` to drop the override. */
|
|
30136
30192
|
setCameraPipelineForAgent: require_sleep.method(zod.z.object({
|
|
30137
30193
|
deviceId: zod.z.number(),
|
|
@@ -56701,6 +56757,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56701
56757
|
addonId: null,
|
|
56702
56758
|
access: "create"
|
|
56703
56759
|
},
|
|
56760
|
+
"pipelineOrchestrator.setCameraStepSettings": {
|
|
56761
|
+
capName: "pipeline-orchestrator",
|
|
56762
|
+
capScope: "system",
|
|
56763
|
+
addonId: null,
|
|
56764
|
+
access: "create"
|
|
56765
|
+
},
|
|
56704
56766
|
"pipelineOrchestrator.setCameraStepToggle": {
|
|
56705
56767
|
capName: "pipeline-orchestrator",
|
|
56706
56768
|
capScope: "system",
|
|
@@ -65501,6 +65563,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
|
|
|
65501
65563
|
form: "single",
|
|
65502
65564
|
optional: false
|
|
65503
65565
|
}],
|
|
65566
|
+
"pipelineOrchestrator.setCameraStepSettings": [{
|
|
65567
|
+
name: "deviceId",
|
|
65568
|
+
form: "single",
|
|
65569
|
+
optional: false
|
|
65570
|
+
}],
|
|
65504
65571
|
"pipelineOrchestrator.setCameraStepToggle": [{
|
|
65505
65572
|
name: "deviceId",
|
|
65506
65573
|
form: "single",
|
|
@@ -66485,6 +66552,7 @@ var SYSTEM_SCOPE_DEVICE_METHODS = [
|
|
|
66485
66552
|
"pipelineOrchestrator.setCameraPipelineForAgent",
|
|
66486
66553
|
"pipelineOrchestrator.setCameraSensors",
|
|
66487
66554
|
"pipelineOrchestrator.setCameraStepOverride",
|
|
66555
|
+
"pipelineOrchestrator.setCameraStepSettings",
|
|
66488
66556
|
"pipelineOrchestrator.setCameraStepToggle",
|
|
66489
66557
|
"pipelineOrchestrator.setCameraSwitch",
|
|
66490
66558
|
"pipelineOrchestrator.setPipelineDevicePin",
|
|
@@ -72482,6 +72550,135 @@ function collectModelBoundKeys(fields) {
|
|
|
72482
72550
|
});
|
|
72483
72551
|
}
|
|
72484
72552
|
//#endregion
|
|
72553
|
+
//#region src/pipeline/step-settings-layers.ts
|
|
72554
|
+
/**
|
|
72555
|
+
* The layers of a detection step's settings, and the field-level edits on them
|
|
72556
|
+
* (D754).
|
|
72557
|
+
*
|
|
72558
|
+
* A step's settings reach a session through up to three stored layers, merged
|
|
72559
|
+
* key by key — a key in a higher layer wins:
|
|
72560
|
+
*
|
|
72561
|
+
* node the node's folded base (`inferenceDevices[node][*].steps`)
|
|
72562
|
+
* camera `cameraSettings[cam].stepSettings[step]` — every accelerator
|
|
72563
|
+
* accelerator `cameraSettings[cam].stepOverridesByDevice[node][key][step].settings`
|
|
72564
|
+
*
|
|
72565
|
+
* Below them sits the default: the running model's (D738) or the field's own.
|
|
72566
|
+
*
|
|
72567
|
+
* Every layer is SPARSE and FIELD-LEVEL. A key present in a layer is an
|
|
72568
|
+
* override; an absent key inherits. Two consequences that every editor must
|
|
72569
|
+
* respect, and why this module exists:
|
|
72570
|
+
*
|
|
72571
|
+
* - A model-bound field (D738) occupies TWO keys, its value and
|
|
72572
|
+
* `<key>ModelId`. They are written, compared and removed as one unit — a
|
|
72573
|
+
* value without its binding over a lower layer's binding would be judged
|
|
72574
|
+
* against the wrong model.
|
|
72575
|
+
* - An editor writes a DIFF against the merged layers below, never a copy of
|
|
72576
|
+
* them. A copy pins every field at the value it had that day, so later
|
|
72577
|
+
* edits below never reach it (the full-copy "Override" this replaced).
|
|
72578
|
+
*/
|
|
72579
|
+
/** Top-down order of the stored layers. */
|
|
72580
|
+
var LAYER_ORDER = [
|
|
72581
|
+
"accelerator",
|
|
72582
|
+
"camera",
|
|
72583
|
+
"node"
|
|
72584
|
+
];
|
|
72585
|
+
/**
|
|
72586
|
+
* The keys one field occupies in a bag: its own, plus its binding key when it
|
|
72587
|
+
* binds to a model. `boundKeys` = `collectModelBoundKeys(schema)`.
|
|
72588
|
+
*/
|
|
72589
|
+
function fieldUnitKeys(key, boundKeys) {
|
|
72590
|
+
return boundKeys.includes(key) ? [key, modelBindingKey(key)] : [key];
|
|
72591
|
+
}
|
|
72592
|
+
/** The field a stored key belongs to (`minConfidencePersonModelId` → `minConfidencePerson`). */
|
|
72593
|
+
function unitOf(storedKey, boundKeys) {
|
|
72594
|
+
return boundKeys.find((k) => modelBindingKey(k) === storedKey) ?? storedKey;
|
|
72595
|
+
}
|
|
72596
|
+
/** Structural equality for stored values (numbers, strings, booleans, arrays, plain objects). */
|
|
72597
|
+
function settingValuesEqual(a, b) {
|
|
72598
|
+
if (Object.is(a, b)) return true;
|
|
72599
|
+
if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((v, i) => settingValuesEqual(v, b[i]));
|
|
72600
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
72601
|
+
const ka = Object.keys(a);
|
|
72602
|
+
const kb = Object.keys(b);
|
|
72603
|
+
return ka.length === kb.length && ka.every((k) => settingValuesEqual(a[k], b[k]));
|
|
72604
|
+
}
|
|
72605
|
+
return false;
|
|
72606
|
+
}
|
|
72607
|
+
function isPlainObject(v) {
|
|
72608
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
72609
|
+
}
|
|
72610
|
+
/** Merge bags bottom-up (later wins, per key). Fresh object. */
|
|
72611
|
+
function mergeSettingsBags(...bags) {
|
|
72612
|
+
return bags.reduce((acc, bag) => ({
|
|
72613
|
+
...acc,
|
|
72614
|
+
...bag
|
|
72615
|
+
}), {});
|
|
72616
|
+
}
|
|
72617
|
+
/** The merged value of the layers BELOW `layer` (what removing a key from `layer` falls back to). */
|
|
72618
|
+
function settingsBelow(layers, layer) {
|
|
72619
|
+
return mergeSettingsBags(...LAYER_ORDER.slice(LAYER_ORDER.indexOf(layer) + 1).toReversed().map((id) => layers[id]));
|
|
72620
|
+
}
|
|
72621
|
+
/** The effective bag: every stored layer merged. */
|
|
72622
|
+
function effectiveStepSettings(layers) {
|
|
72623
|
+
return mergeSettingsBags(layers.node, layers.camera, layers.accelerator);
|
|
72624
|
+
}
|
|
72625
|
+
/** The highest stored layer that holds any key of `key`'s unit, or `default`. */
|
|
72626
|
+
function stepSettingSource(layers, key, boundKeys) {
|
|
72627
|
+
const unit = fieldUnitKeys(key, boundKeys);
|
|
72628
|
+
for (const id of LAYER_ORDER) {
|
|
72629
|
+
const bag = layers[id];
|
|
72630
|
+
if (bag !== void 0 && unit.some((k) => bag[k] !== void 0)) return id;
|
|
72631
|
+
}
|
|
72632
|
+
return "default";
|
|
72633
|
+
}
|
|
72634
|
+
/**
|
|
72635
|
+
* `layer` with `key`'s unit set from `values` (a bag carrying the unit's new
|
|
72636
|
+
* value — e.g. the editor's whole next settings bag). A unit key that `values`
|
|
72637
|
+
* does not carry is removed from the layer. Fresh object.
|
|
72638
|
+
*/
|
|
72639
|
+
function withFieldFrom(layer, key, values, boundKeys) {
|
|
72640
|
+
const out = { ...layer };
|
|
72641
|
+
for (const k of fieldUnitKeys(key, boundKeys)) if (values[k] === void 0) delete out[k];
|
|
72642
|
+
else out[k] = values[k];
|
|
72643
|
+
return out;
|
|
72644
|
+
}
|
|
72645
|
+
/** `layer` without `key`'s unit — "reset to the next level". Fresh object. */
|
|
72646
|
+
function withoutField(layer, key, boundKeys) {
|
|
72647
|
+
const out = { ...layer };
|
|
72648
|
+
for (const k of fieldUnitKeys(key, boundKeys)) delete out[k];
|
|
72649
|
+
return out;
|
|
72650
|
+
}
|
|
72651
|
+
/** Every field unit stored in `layer`, by its field key. */
|
|
72652
|
+
function unitsIn(layer, boundKeys) {
|
|
72653
|
+
return [...new Set(Object.keys(layer).map((k) => unitOf(k, boundKeys)))];
|
|
72654
|
+
}
|
|
72655
|
+
/** True when every key of `key`'s unit has the same value in `layer` as in `below`. */
|
|
72656
|
+
function unitEqualsBelow(layer, below, key, boundKeys) {
|
|
72657
|
+
return fieldUnitKeys(key, boundKeys).every((k) => settingValuesEqual(layer[k], below[k]));
|
|
72658
|
+
}
|
|
72659
|
+
/**
|
|
72660
|
+
* `layer` reduced to the fields that DIFFER from `below` — what an editor
|
|
72661
|
+
* stores. A unit is kept or dropped whole. `undefined` when nothing is left.
|
|
72662
|
+
*/
|
|
72663
|
+
function diffStepSettings(layer, below, boundKeys) {
|
|
72664
|
+
if (layer === void 0) return void 0;
|
|
72665
|
+
const out = {};
|
|
72666
|
+
for (const unit of unitsIn(layer, boundKeys)) {
|
|
72667
|
+
if (unitEqualsBelow(layer, below, unit, boundKeys)) continue;
|
|
72668
|
+
for (const k of fieldUnitKeys(unit, boundKeys)) if (layer[k] !== void 0) out[k] = layer[k];
|
|
72669
|
+
}
|
|
72670
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
72671
|
+
}
|
|
72672
|
+
/**
|
|
72673
|
+
* The fields `layer` stores at exactly the value of the layers below — a
|
|
72674
|
+
* legacy full copy's leftovers. They change nothing today and stop every
|
|
72675
|
+
* later edit below from reaching this layer. Sorted.
|
|
72676
|
+
*/
|
|
72677
|
+
function fieldsPinnedAtValueBelow(layer, below, boundKeys) {
|
|
72678
|
+
if (layer === void 0) return [];
|
|
72679
|
+
return unitsIn(layer, boundKeys).filter((unit) => unitEqualsBelow(layer, below, unit, boundKeys)).toSorted();
|
|
72680
|
+
}
|
|
72681
|
+
//#endregion
|
|
72485
72682
|
//#region src/pipeline/auto-tune/hardware-class.ts
|
|
72486
72683
|
var APPLE_CHIP = /^Apple M(\d+)(?:\s+(Pro|Max|Ultra))?\b/i;
|
|
72487
72684
|
var INTEL_CORE_ULTRA = /Core\(TM\)\s+Ultra|Core Ultra/i;
|
|
@@ -72970,129 +73167,6 @@ var DETECTOR_ACCURACY = {
|
|
|
72970
73167
|
}
|
|
72971
73168
|
};
|
|
72972
73169
|
//#endregion
|
|
72973
|
-
//#region src/pipeline/auto-tune/demand.ts
|
|
72974
|
-
var DEFAULT_DEMAND_OPTIONS = {
|
|
72975
|
-
onMotionConcurrency: .25,
|
|
72976
|
-
onMotionMinConcurrent: 2
|
|
72977
|
-
};
|
|
72978
|
-
/** A full observation window. */
|
|
72979
|
-
var OBSERVATION_WINDOW_MS = 1440 * 60 * 1e3;
|
|
72980
|
-
function deviceId(nodeId, deviceKey) {
|
|
72981
|
-
return `${nodeId}\u0000${deviceKey}`;
|
|
72982
|
-
}
|
|
72983
|
-
function charges(load) {
|
|
72984
|
-
return load.mode !== "disabled" && load.runsPipelineRoot && load.fps > 0;
|
|
72985
|
-
}
|
|
72986
|
-
/** The highest `count` rates, summed. */
|
|
72987
|
-
function topRatesSum(rates, count) {
|
|
72988
|
-
return rates.toSorted((a, b) => b - a).slice(0, Math.max(0, count)).reduce((sum, r) => sum + r, 0);
|
|
72989
|
-
}
|
|
72990
|
-
/** Concurrent on-motion sessions assumed cluster-wide without an observation. */
|
|
72991
|
-
function estimatedConcurrentSessions(cameraCount, options) {
|
|
72992
|
-
if (cameraCount <= 0) return 0;
|
|
72993
|
-
const share = Math.ceil(options.onMotionConcurrency * cameraCount);
|
|
72994
|
-
return Math.min(cameraCount, Math.max(share, Math.min(cameraCount, options.onMotionMinConcurrent)));
|
|
72995
|
-
}
|
|
72996
|
-
/**
|
|
72997
|
-
* Demand on every eligible device of the cluster.
|
|
72998
|
-
*/
|
|
72999
|
-
function estimateDeviceDemand(input) {
|
|
73000
|
-
const options = input.options ?? DEFAULT_DEMAND_OPTIONS;
|
|
73001
|
-
const placement = input.shares ? "share" : "least-loaded";
|
|
73002
|
-
const eligibleById = new Map(input.eligible.map((d) => [deviceId(d.nodeId, d.deviceKey), d]));
|
|
73003
|
-
const peakById = new Map(input.peaks.map((p) => [deviceId(p.nodeId, p.deviceKey), p]));
|
|
73004
|
-
const weightByNode = /* @__PURE__ */ new Map();
|
|
73005
|
-
const eligibleCountByNode = /* @__PURE__ */ new Map();
|
|
73006
|
-
for (const d of input.eligible) {
|
|
73007
|
-
weightByNode.set(d.nodeId, (weightByNode.get(d.nodeId) ?? 0) + Math.max(d.weight, 0));
|
|
73008
|
-
eligibleCountByNode.set(d.nodeId, (eligibleCountByNode.get(d.nodeId) ?? 0) + 1);
|
|
73009
|
-
}
|
|
73010
|
-
const pinnedFps = /* @__PURE__ */ new Map();
|
|
73011
|
-
const alwaysOnFps = /* @__PURE__ */ new Map();
|
|
73012
|
-
const alwaysOnCount = /* @__PURE__ */ new Map();
|
|
73013
|
-
const maxFps = /* @__PURE__ */ new Map();
|
|
73014
|
-
const onMotionRates = [];
|
|
73015
|
-
const bump = (map, key, by) => {
|
|
73016
|
-
map.set(key, (map.get(key) ?? 0) + by);
|
|
73017
|
-
};
|
|
73018
|
-
const noteMax = (key, fps) => {
|
|
73019
|
-
maxFps.set(key, Math.max(maxFps.get(key) ?? 0, fps));
|
|
73020
|
-
};
|
|
73021
|
-
const pinNodeOf = (pin) => {
|
|
73022
|
-
if (pin.nodeId !== null) return pin.nodeId;
|
|
73023
|
-
const holders = input.eligible.filter((d) => d.deviceKey === pin.deviceKey);
|
|
73024
|
-
return holders.length === 1 ? holders[0].nodeId : null;
|
|
73025
|
-
};
|
|
73026
|
-
let alwaysOnTotal = 0;
|
|
73027
|
-
for (const cam of input.cameras) {
|
|
73028
|
-
if (!charges(cam)) continue;
|
|
73029
|
-
const pinNode = cam.devicePin !== null ? pinNodeOf(cam.devicePin) : null;
|
|
73030
|
-
if (cam.devicePin !== null && pinNode !== null) {
|
|
73031
|
-
const key = deviceId(pinNode, cam.devicePin.deviceKey);
|
|
73032
|
-
if (!eligibleById.has(key)) continue;
|
|
73033
|
-
bump(pinnedFps, key, cam.fps);
|
|
73034
|
-
noteMax(key, cam.fps);
|
|
73035
|
-
continue;
|
|
73036
|
-
}
|
|
73037
|
-
const standing = cam.mode === "always-on" && cam.standingNodeId !== null ? cam.standingNodeId : cam.nodePinId;
|
|
73038
|
-
if (standing !== null) {
|
|
73039
|
-
if (cam.mode === "always-on") alwaysOnTotal += 1;
|
|
73040
|
-
const nodeWeight = weightByNode.get(standing) ?? 0;
|
|
73041
|
-
for (const d of input.eligible) {
|
|
73042
|
-
if (d.nodeId !== standing || nodeWeight <= 0) continue;
|
|
73043
|
-
const key = deviceId(d.nodeId, d.deviceKey);
|
|
73044
|
-
const share = Math.max(d.weight, 0) / nodeWeight;
|
|
73045
|
-
bump(alwaysOnFps, key, cam.fps * share);
|
|
73046
|
-
bump(alwaysOnCount, key, share);
|
|
73047
|
-
noteMax(key, cam.fps);
|
|
73048
|
-
}
|
|
73049
|
-
continue;
|
|
73050
|
-
}
|
|
73051
|
-
onMotionRates.push(cam.fps);
|
|
73052
|
-
}
|
|
73053
|
-
const fastestOnMotion = onMotionRates.reduce((m, r) => Math.max(m, r), 0);
|
|
73054
|
-
const nodeCount = weightByNode.size;
|
|
73055
|
-
const estimatedTotal = estimatedConcurrentSessions(onMotionRates.length, options);
|
|
73056
|
-
const clusterPeak = input.shares?.clusterPeak ?? null;
|
|
73057
|
-
const clusterObserved = clusterPeak !== null && clusterPeak.observedForMs >= 864e5;
|
|
73058
|
-
const clusterSessions = clusterObserved ? Math.max(0, clusterPeak.peakSessions - alwaysOnTotal) : estimatedTotal;
|
|
73059
|
-
const shareSum = [...weightByNode.keys()].reduce((sum, nodeId) => sum + Math.max(input.shares?.nodes[nodeId] ?? 0, 0), 0);
|
|
73060
|
-
return input.eligible.map((d) => {
|
|
73061
|
-
const key = deviceId(d.nodeId, d.deviceKey);
|
|
73062
|
-
const peak = peakById.get(key) ?? (eligibleCountByNode.get(d.nodeId) === 1 ? peakById.get(deviceId(d.nodeId, "")) : void 0);
|
|
73063
|
-
const alwaysOn = alwaysOnCount.get(key) ?? 0;
|
|
73064
|
-
let onMotionSessions = 0;
|
|
73065
|
-
let onMotionSource = "none";
|
|
73066
|
-
if (onMotionRates.length > 0 && input.shares !== void 0) {
|
|
73067
|
-
const nodeWeight = weightByNode.get(d.nodeId) ?? 0;
|
|
73068
|
-
const nodeShare = shareSum > 0 ? Math.max(input.shares.nodes[d.nodeId] ?? 0, 0) / shareSum : 0;
|
|
73069
|
-
const deviceShare = nodeWeight > 0 ? Math.max(d.weight, 0) / nodeWeight : 0;
|
|
73070
|
-
onMotionSessions = Math.max(0, Math.ceil(clusterSessions * nodeShare * deviceShare - 1e-9));
|
|
73071
|
-
onMotionSource = clusterObserved ? "observed-24h" : "estimate";
|
|
73072
|
-
} else if (onMotionRates.length > 0) if (peak !== void 0 && peak.observedForMs >= 864e5) {
|
|
73073
|
-
onMotionSessions = Math.max(0, Math.round(peak.peakSessions - alwaysOn));
|
|
73074
|
-
onMotionSource = "observed-24h";
|
|
73075
|
-
} else {
|
|
73076
|
-
const nodeWeight = weightByNode.get(d.nodeId) ?? 0;
|
|
73077
|
-
const share = nodeCount > 0 && nodeWeight > 0 ? Math.max(d.weight, 0) / nodeWeight / nodeCount : 0;
|
|
73078
|
-
onMotionSessions = Math.ceil(estimatedTotal * share);
|
|
73079
|
-
onMotionSource = "estimate";
|
|
73080
|
-
}
|
|
73081
|
-
const demandFps = (pinnedFps.get(key) ?? 0) + (alwaysOnFps.get(key) ?? 0) + topRatesSum(onMotionRates, onMotionSessions);
|
|
73082
|
-
return {
|
|
73083
|
-
nodeId: d.nodeId,
|
|
73084
|
-
deviceKey: d.deviceKey,
|
|
73085
|
-
demandFps: Math.round(demandFps * 100) / 100,
|
|
73086
|
-
maxCameraFps: Math.max(maxFps.get(key) ?? 0, fastestOnMotion),
|
|
73087
|
-
alwaysOnCameras: Math.round(alwaysOn * 100) / 100,
|
|
73088
|
-
onMotionSessions,
|
|
73089
|
-
onMotionSource,
|
|
73090
|
-
observedForMs: input.shares !== void 0 ? clusterPeak?.observedForMs ?? null : peak?.observedForMs ?? null,
|
|
73091
|
-
placement
|
|
73092
|
-
};
|
|
73093
|
-
}).toSorted((a, b) => a.nodeId === b.nodeId ? a.deviceKey.localeCompare(b.deviceKey) : a.nodeId.localeCompare(b.nodeId));
|
|
73094
|
-
}
|
|
73095
|
-
//#endregion
|
|
73096
73170
|
//#region src/pipeline/auto-tune/recommend.ts
|
|
73097
73171
|
/** The family the cluster runs. */
|
|
73098
73172
|
var AUTO_TUNE_FAMILY = "yolov9";
|
|
@@ -73100,16 +73174,22 @@ var AUTO_TUNE_FAMILY = "yolov9";
|
|
|
73100
73174
|
var RECALL_TIE = .02;
|
|
73101
73175
|
/** Default share of an accelerator's throughput kept free. */
|
|
73102
73176
|
var DEFAULT_HEADROOM = .4;
|
|
73177
|
+
/** Detection rate a session is counted at when no camera says otherwise. */
|
|
73178
|
+
var DEFAULT_CAMERA_FPS = 10;
|
|
73179
|
+
/** Parallel sessions one device sustains at `fps` with `headroom` kept free. */
|
|
73180
|
+
function capacitySessionsOf(fps, headroom, cameraFps) {
|
|
73181
|
+
if (!(fps > 0) || !(cameraFps > 0)) return 0;
|
|
73182
|
+
return Math.max(0, Math.floor(fps * (1 - headroom) / cameraFps + 1e-9));
|
|
73183
|
+
}
|
|
73103
73184
|
function round(value, digits = 3) {
|
|
73104
73185
|
const f = 10 ** digits;
|
|
73105
73186
|
return Math.round(value * f) / f;
|
|
73106
73187
|
}
|
|
73107
|
-
function
|
|
73108
|
-
return cell
|
|
73188
|
+
function sessionsOn(cell, sizing) {
|
|
73189
|
+
return cell === void 0 ? 0 : capacitySessionsOf(cell.fps, sizing.headroom, sizing.cameraFps);
|
|
73109
73190
|
}
|
|
73110
|
-
function fitsOn(cell,
|
|
73111
|
-
|
|
73112
|
-
return budget >= (demand?.demandFps ?? 0) && budget >= (demand?.maxCameraFps ?? 0);
|
|
73191
|
+
function fitsOn(cell, sizing) {
|
|
73192
|
+
return sessionsOn(cell, sizing) >= sizing.minSessions;
|
|
73113
73193
|
}
|
|
73114
73194
|
function candidatesFor(contexts, formatsByModel) {
|
|
73115
73195
|
return Object.keys(DETECTOR_ACCURACY).filter((id) => id.startsWith(AUTO_TUNE_FAMILY)).filter((id) => contexts.every((c) => c.column[id] !== void 0 && (formatsByModel[id] ?? []).includes(c.device.format))).map((id) => ({
|
|
@@ -73120,28 +73200,24 @@ function candidatesFor(contexts, formatsByModel) {
|
|
|
73120
73200
|
function totalLatency(contexts, modelId) {
|
|
73121
73201
|
return contexts.reduce((sum, c) => sum + (c.column[modelId]?.p50Ms ?? Number.POSITIVE_INFINITY), 0);
|
|
73122
73202
|
}
|
|
73123
|
-
|
|
73124
|
-
|
|
73125
|
-
|
|
73126
|
-
return Math.max(worst, cell ? utilisationOf(cell, c.demand) : Number.POSITIVE_INFINITY);
|
|
73127
|
-
}, 0);
|
|
73203
|
+
/** The fewest sessions any device of the group sustains with this model. */
|
|
73204
|
+
function worstSessions(contexts, modelId, sizing) {
|
|
73205
|
+
return contexts.reduce((worst, c) => Math.min(worst, sessionsOn(c.column[modelId], sizing)), Number.POSITIVE_INFINITY);
|
|
73128
73206
|
}
|
|
73129
73207
|
/** One model for a group of devices that must agree (step 2–4 of the header). */
|
|
73130
|
-
function pickForGroup(contexts, formatsByModel,
|
|
73208
|
+
function pickForGroup(contexts, formatsByModel, sizing) {
|
|
73131
73209
|
const candidates = candidatesFor(contexts, formatsByModel);
|
|
73132
73210
|
if (candidates.length === 0) return null;
|
|
73133
|
-
const fitting = candidates.filter((c) => contexts.every((ctx) =>
|
|
73134
|
-
const cell = ctx.column[c.modelId];
|
|
73135
|
-
return cell !== void 0 && fitsOn(cell, ctx.demand, headroom);
|
|
73136
|
-
}));
|
|
73211
|
+
const fitting = candidates.filter((c) => contexts.every((ctx) => fitsOn(ctx.column[c.modelId], sizing)));
|
|
73137
73212
|
if (fitting.length === 0) {
|
|
73138
|
-
const lightest = candidates.toSorted((a, b) =>
|
|
73213
|
+
const lightest = candidates.toSorted((a, b) => worstSessions(contexts, b.modelId, sizing) - worstSessions(contexts, a.modelId, sizing) || totalLatency(contexts, a.modelId) - totalLatency(contexts, b.modelId))[0];
|
|
73139
73214
|
if (lightest === void 0) return null;
|
|
73140
73215
|
return {
|
|
73141
73216
|
modelId: lightest.modelId,
|
|
73142
73217
|
reasons: [{
|
|
73143
73218
|
kind: "no-fit-lightest",
|
|
73144
|
-
|
|
73219
|
+
sessions: worstSessions(contexts, lightest.modelId, sizing),
|
|
73220
|
+
minSessions: sizing.minSessions
|
|
73145
73221
|
}]
|
|
73146
73222
|
};
|
|
73147
73223
|
}
|
|
@@ -73151,10 +73227,7 @@ function pickForGroup(contexts, formatsByModel, headroom) {
|
|
|
73151
73227
|
const reasons = [];
|
|
73152
73228
|
const mostAccurate = candidates[0];
|
|
73153
73229
|
if (mostAccurate !== void 0 && mostAccurate.modelId !== best.modelId) {
|
|
73154
|
-
const limitedBy = contexts.find((ctx) =>
|
|
73155
|
-
const cell = ctx.column[mostAccurate.modelId];
|
|
73156
|
-
return cell === void 0 || !fitsOn(cell, ctx.demand, headroom);
|
|
73157
|
-
})?.device.key ?? "";
|
|
73230
|
+
const limitedBy = contexts.find((ctx) => !fitsOn(ctx.column[mostAccurate.modelId], sizing))?.device.key ?? "";
|
|
73158
73231
|
reasons.push({
|
|
73159
73232
|
kind: "stepped-down",
|
|
73160
73233
|
from: mostAccurate.modelId,
|
|
@@ -73172,7 +73245,7 @@ function pickForGroup(contexts, formatsByModel, headroom) {
|
|
|
73172
73245
|
reasons
|
|
73173
73246
|
};
|
|
73174
73247
|
}
|
|
73175
|
-
function choiceOn(ctx, modelId) {
|
|
73248
|
+
function choiceOn(ctx, modelId, sizing) {
|
|
73176
73249
|
const cell = ctx.column[modelId];
|
|
73177
73250
|
if (cell === void 0) return null;
|
|
73178
73251
|
return {
|
|
@@ -73180,23 +73253,20 @@ function choiceOn(ctx, modelId) {
|
|
|
73180
73253
|
p50Ms: cell.p50Ms,
|
|
73181
73254
|
fps: cell.fps,
|
|
73182
73255
|
measured: cell.measured,
|
|
73183
|
-
|
|
73256
|
+
capacitySessions: sessionsOn(cell, sizing),
|
|
73184
73257
|
personRecall: DETECTOR_ACCURACY[modelId]?.personRecall ?? 0
|
|
73185
73258
|
};
|
|
73186
73259
|
}
|
|
73187
|
-
function deviceReasonsFor(
|
|
73260
|
+
function deviceReasonsFor(choice, sizing) {
|
|
73188
73261
|
const out = [{
|
|
73189
|
-
kind: "
|
|
73190
|
-
|
|
73262
|
+
kind: "capacity",
|
|
73263
|
+
sessions: choice.capacitySessions,
|
|
73264
|
+
minSessions: sizing.minSessions
|
|
73191
73265
|
}];
|
|
73192
73266
|
if (!choice.measured) out.push({
|
|
73193
73267
|
kind: "derived-latency",
|
|
73194
73268
|
modelId: choice.modelId
|
|
73195
73269
|
});
|
|
73196
|
-
if (ctx.demand?.onMotionSource === "estimate") out.push({
|
|
73197
|
-
kind: "estimated-load",
|
|
73198
|
-
observedForMs: ctx.demand.observedForMs
|
|
73199
|
-
});
|
|
73200
73270
|
return out;
|
|
73201
73271
|
}
|
|
73202
73272
|
function skippedNode(node, reason, hardwareClass) {
|
|
@@ -73212,7 +73282,6 @@ function skippedNode(node, reason, hardwareClass) {
|
|
|
73212
73282
|
accelerator: node.hardware ? acceleratorKindOf(d.key, node.hardware) : null,
|
|
73213
73283
|
enabled: d.enabled,
|
|
73214
73284
|
available: d.available,
|
|
73215
|
-
demand: null,
|
|
73216
73285
|
chosen: null,
|
|
73217
73286
|
reasons: []
|
|
73218
73287
|
})),
|
|
@@ -73222,7 +73291,11 @@ function skippedNode(node, reason, hardwareClass) {
|
|
|
73222
73291
|
/** Recommend one node. See the module header. */
|
|
73223
73292
|
function recommendNode(input) {
|
|
73224
73293
|
const { node } = input;
|
|
73225
|
-
const
|
|
73294
|
+
const sizing = {
|
|
73295
|
+
headroom: input.headroom ?? .4,
|
|
73296
|
+
cameraFps: input.cameraFps ?? 10,
|
|
73297
|
+
minSessions: input.minSessionsPerDevice ?? 2
|
|
73298
|
+
};
|
|
73226
73299
|
const perf = input.perf ?? DETECTOR_PERF;
|
|
73227
73300
|
if (!node.reachable) return skippedNode(node, { kind: "node-offline" }, null);
|
|
73228
73301
|
if (node.hardware === null) return skippedNode(node, { kind: "no-hardware-facts" }, null);
|
|
@@ -73233,7 +73306,6 @@ function recommendNode(input) {
|
|
|
73233
73306
|
kind: "no-measured-data",
|
|
73234
73307
|
hardwareClass
|
|
73235
73308
|
}, hardwareClass);
|
|
73236
|
-
const demandByKey = new Map(input.demand.filter((d) => d.nodeId === node.nodeId).map((d) => [d.deviceKey, d]));
|
|
73237
73309
|
const devices = node.devices.toSorted((a, b) => a.key.localeCompare(b.key));
|
|
73238
73310
|
const contexts = /* @__PURE__ */ new Map();
|
|
73239
73311
|
const early = /* @__PURE__ */ new Map();
|
|
@@ -73262,8 +73334,7 @@ function recommendNode(input) {
|
|
|
73262
73334
|
contexts.set(device.key, {
|
|
73263
73335
|
device,
|
|
73264
73336
|
accelerator,
|
|
73265
|
-
column
|
|
73266
|
-
demand: demandByKey.get(device.key) ?? null
|
|
73337
|
+
column
|
|
73267
73338
|
});
|
|
73268
73339
|
}
|
|
73269
73340
|
const isCpu = (a) => a === "x86-cpu" || a === "arm-cpu";
|
|
@@ -73273,23 +73344,23 @@ function recommendNode(input) {
|
|
|
73273
73344
|
const reasonsByKey = /* @__PURE__ */ new Map();
|
|
73274
73345
|
const nodeReasons = [];
|
|
73275
73346
|
let acceleratorModelId = null;
|
|
73276
|
-
const groupPick = accelerators.length > 0 ? pickForGroup(accelerators, node.formatsByModel,
|
|
73347
|
+
const groupPick = accelerators.length > 0 ? pickForGroup(accelerators, node.formatsByModel, sizing) : null;
|
|
73277
73348
|
if (groupPick !== null) {
|
|
73278
73349
|
acceleratorModelId = groupPick.modelId;
|
|
73279
73350
|
nodeReasons.push(...groupPick.reasons);
|
|
73280
73351
|
for (const ctx of accelerators) {
|
|
73281
|
-
const choice = choiceOn(ctx, groupPick.modelId);
|
|
73352
|
+
const choice = choiceOn(ctx, groupPick.modelId, sizing);
|
|
73282
73353
|
if (choice === null) continue;
|
|
73283
73354
|
chosenByKey.set(ctx.device.key, choice);
|
|
73284
|
-
reasonsByKey.set(ctx.device.key, deviceReasonsFor(
|
|
73355
|
+
reasonsByKey.set(ctx.device.key, deviceReasonsFor(choice, sizing));
|
|
73285
73356
|
}
|
|
73286
73357
|
} else for (const ctx of accelerators) reasonsByKey.set(ctx.device.key, [{
|
|
73287
73358
|
kind: "no-family-build",
|
|
73288
73359
|
format: ctx.device.format
|
|
73289
73360
|
}]);
|
|
73290
73361
|
for (const ctx of cpus) {
|
|
73291
|
-
const pick = pickForGroup([ctx], node.formatsByModel,
|
|
73292
|
-
const choice = pick === null ? null : choiceOn(ctx, pick.modelId);
|
|
73362
|
+
const pick = pickForGroup([ctx], node.formatsByModel, sizing);
|
|
73363
|
+
const choice = pick === null ? null : choiceOn(ctx, pick.modelId, sizing);
|
|
73293
73364
|
if (pick === null || choice === null) {
|
|
73294
73365
|
reasonsByKey.set(ctx.device.key, [{
|
|
73295
73366
|
kind: "no-family-build",
|
|
@@ -73301,7 +73372,7 @@ function recommendNode(input) {
|
|
|
73301
73372
|
reasonsByKey.set(ctx.device.key, [
|
|
73302
73373
|
{ kind: "cpu-device" },
|
|
73303
73374
|
...pick.reasons,
|
|
73304
|
-
...deviceReasonsFor(
|
|
73375
|
+
...deviceReasonsFor(choice, sizing)
|
|
73305
73376
|
]);
|
|
73306
73377
|
}
|
|
73307
73378
|
return {
|
|
@@ -73316,7 +73387,6 @@ function recommendNode(input) {
|
|
|
73316
73387
|
accelerator: acceleratorKindOf(device.key, hardware),
|
|
73317
73388
|
enabled: device.enabled,
|
|
73318
73389
|
available: device.available,
|
|
73319
|
-
demand: demandByKey.get(device.key) ?? null,
|
|
73320
73390
|
chosen: chosenByKey.get(device.key) ?? null,
|
|
73321
73391
|
reasons: early.get(device.key) ?? reasonsByKey.get(device.key) ?? []
|
|
73322
73392
|
})),
|
|
@@ -73367,6 +73437,18 @@ function electByShare(candidates) {
|
|
|
73367
73437
|
}
|
|
73368
73438
|
//#endregion
|
|
73369
73439
|
//#region src/pipeline/load-balancing/effective-shares.ts
|
|
73440
|
+
/**
|
|
73441
|
+
* The shares a session election actually reads, and the view the Load
|
|
73442
|
+
* balancing tab shows (D750). Pure.
|
|
73443
|
+
*
|
|
73444
|
+
* The SOURCE decides the configured weights: the automatic capacity shares
|
|
73445
|
+
* (`hardware` or `benchmark`, D755), or the operator's stored sliders. Eligibility decides the effective ones: a
|
|
73446
|
+
* node or device that cannot take a session now (offline, switched off, no
|
|
73447
|
+
* detect capability, unable to run the root) contributes nothing, and the
|
|
73448
|
+
* others split its share in proportion to their own. That redistribution is
|
|
73449
|
+
* exactly what `electByShare` does over its candidate set, so the view and
|
|
73450
|
+
* the election cannot disagree; the stored values are never rewritten for it.
|
|
73451
|
+
*/
|
|
73370
73452
|
/** Weight a node or device has when its source names none (the balancer's own default). */
|
|
73371
73453
|
var DEFAULT_WEIGHT = 1;
|
|
73372
73454
|
function positive(value) {
|
|
@@ -73377,7 +73459,8 @@ function percentages(keys, weightOf, counts) {
|
|
|
73377
73459
|
return new Map(keys.map((k) => [k, total > 0 && counts(k) ? Math.round(weightOf(k) / total * 1e3) / 10 : 0]));
|
|
73378
73460
|
}
|
|
73379
73461
|
function resolveEffectiveShares(input) {
|
|
73380
|
-
const
|
|
73462
|
+
const useAuto = isAutomaticShareSource(input.source) && input.auto !== null;
|
|
73463
|
+
const weights = useAuto && input.auto !== null ? input.auto : input.stored;
|
|
73381
73464
|
const nodeWeights = {};
|
|
73382
73465
|
for (const nodeId of input.nodeIds) nodeWeights[nodeId] = positive(weights.nodes[nodeId]);
|
|
73383
73466
|
const eligibleNodes = new Set(input.eligibleNodes);
|
|
@@ -73399,18 +73482,21 @@ function resolveEffectiveShares(input) {
|
|
|
73399
73482
|
configuredPct: devConfigured.get(deviceKey) ?? 0,
|
|
73400
73483
|
effectivePct: devEffective.get(deviceKey) ?? 0
|
|
73401
73484
|
}));
|
|
73485
|
+
const capacity = useAuto ? input.autoCapacity?.[nodeId] : void 0;
|
|
73402
73486
|
return {
|
|
73403
73487
|
nodeId,
|
|
73404
73488
|
eligible: eligibleNodes.has(nodeId),
|
|
73405
73489
|
configuredPct: configured.get(nodeId) ?? 0,
|
|
73406
73490
|
effectivePct: effective.get(nodeId) ?? 0,
|
|
73491
|
+
capacitySource: capacity?.source ?? null,
|
|
73492
|
+
capacityFallback: capacity?.fallback ?? null,
|
|
73407
73493
|
devices
|
|
73408
73494
|
};
|
|
73409
73495
|
});
|
|
73410
73496
|
return {
|
|
73411
73497
|
source: input.source,
|
|
73412
73498
|
policy: input.policy ?? "share",
|
|
73413
|
-
autoPending: input.source
|
|
73499
|
+
autoPending: isAutomaticShareSource(input.source) && input.auto === null,
|
|
73414
73500
|
computedAt: input.computedAt ?? null,
|
|
73415
73501
|
trigger: input.trigger ?? null,
|
|
73416
73502
|
nodes,
|
|
@@ -73419,6 +73505,139 @@ function resolveEffectiveShares(input) {
|
|
|
73419
73505
|
};
|
|
73420
73506
|
}
|
|
73421
73507
|
//#endregion
|
|
73508
|
+
//#region src/pipeline/load-balancing/capacity-shares.ts
|
|
73509
|
+
/**
|
|
73510
|
+
* Automatic shares from CAPACITY (D755). Pure.
|
|
73511
|
+
*
|
|
73512
|
+
* A node's share is its capacity in parallel sessions over the cluster's; a
|
|
73513
|
+
* device's share inside its node follows its throughput. There is no load
|
|
73514
|
+
* input: nothing here depends on how many sessions ran, only on what each
|
|
73515
|
+
* node can carry.
|
|
73516
|
+
*
|
|
73517
|
+
* Two places a capacity can come from:
|
|
73518
|
+
* - `hardware` — each enabled accelerator at its Auto tune model, from the
|
|
73519
|
+
* measured latency table: ⌊fps × (1 − headroom) / camera fps⌋ sessions;
|
|
73520
|
+
* - `benchmark` — the node's own measured max sessions per device, read
|
|
73521
|
+
* through a {@link NodeCapacitySource}. A node whose results do not cover
|
|
73522
|
+
* every enabled device it would be sized on is sized from `hardware`
|
|
73523
|
+
* instead, and the answer says so per node — never a silent mix.
|
|
73524
|
+
*/
|
|
73525
|
+
/** A source that has no results — the benchmark store before it exists. */
|
|
73526
|
+
var NO_MEASURED_CAPACITY = { readMeasuredCapacity: async () => /* @__PURE__ */ new Map() };
|
|
73527
|
+
/** Integer shares summing to 100 (largest remainder); ties broken by key. */
|
|
73528
|
+
function toPercentShares(weights) {
|
|
73529
|
+
const total = [...weights.values()].reduce((a, b) => a + b, 0);
|
|
73530
|
+
const out = /* @__PURE__ */ new Map();
|
|
73531
|
+
if (total <= 0) return out;
|
|
73532
|
+
const raw = [...weights].map(([k, w]) => ({
|
|
73533
|
+
k,
|
|
73534
|
+
exact: w / total * 100
|
|
73535
|
+
}));
|
|
73536
|
+
let assigned = 0;
|
|
73537
|
+
for (const r of raw) {
|
|
73538
|
+
out.set(r.k, Math.floor(r.exact));
|
|
73539
|
+
assigned += Math.floor(r.exact);
|
|
73540
|
+
}
|
|
73541
|
+
const remainder = (exact) => Math.round((exact - Math.floor(exact)) * 1e6);
|
|
73542
|
+
const byRemainder = raw.toSorted((a, b) => remainder(b.exact) - remainder(a.exact) || a.k.localeCompare(b.k));
|
|
73543
|
+
for (let i = 0; i < 100 - assigned; i++) {
|
|
73544
|
+
const r = byRemainder[i % byRemainder.length];
|
|
73545
|
+
if (r === void 0) break;
|
|
73546
|
+
out.set(r.k, (out.get(r.k) ?? 0) + 1);
|
|
73547
|
+
}
|
|
73548
|
+
return out;
|
|
73549
|
+
}
|
|
73550
|
+
function hardwareDevices(rec, headroom, cameraFps) {
|
|
73551
|
+
return rec.devices.filter((d) => d.enabled && d.available && d.chosen !== null).map((d) => {
|
|
73552
|
+
const fps = d.chosen?.fps ?? 0;
|
|
73553
|
+
return {
|
|
73554
|
+
deviceKey: d.deviceKey,
|
|
73555
|
+
sessions: capacitySessionsOf(fps, headroom, cameraFps),
|
|
73556
|
+
weight: Math.max(fps, 0),
|
|
73557
|
+
modelId: d.chosen?.modelId ?? null,
|
|
73558
|
+
fps: d.chosen?.fps ?? null,
|
|
73559
|
+
measured: d.chosen?.measured ?? false
|
|
73560
|
+
};
|
|
73561
|
+
});
|
|
73562
|
+
}
|
|
73563
|
+
function sizeNode(rec, input) {
|
|
73564
|
+
const fromHardware = (fallback) => {
|
|
73565
|
+
const devices = rec.skipped ? [] : hardwareDevices(rec, input.headroom, input.cameraFps);
|
|
73566
|
+
const capacity = devices.reduce((sum, d) => sum + d.sessions, 0);
|
|
73567
|
+
return {
|
|
73568
|
+
rec,
|
|
73569
|
+
devices,
|
|
73570
|
+
capacitySource: rec.skipped ? null : "hardware",
|
|
73571
|
+
capacityFallback: rec.skipped ? null : fallback,
|
|
73572
|
+
skippedReason: rec.skipped ? rec.reasons[0]?.kind ?? "skipped" : capacity > 0 ? null : "no-capacity"
|
|
73573
|
+
};
|
|
73574
|
+
};
|
|
73575
|
+
if (input.source === "hardware") return fromHardware(null);
|
|
73576
|
+
if (!rec.reachable) return fromHardware(null);
|
|
73577
|
+
const results = input.measured.get(rec.nodeId);
|
|
73578
|
+
const byKey = new Map((results?.devices ?? []).map((d) => [d.deviceKey, d]));
|
|
73579
|
+
const usable = rec.devices.filter((d) => d.enabled && d.available);
|
|
73580
|
+
const mustCover = rec.devices.filter((d) => d.enabled && d.available && d.chosen !== null);
|
|
73581
|
+
const covered = usable.filter((d) => byKey.has(d.deviceKey));
|
|
73582
|
+
if (covered.length === 0) return fromHardware("no-benchmark-results");
|
|
73583
|
+
if (mustCover.some((d) => !byKey.has(d.deviceKey))) return fromHardware("partial-benchmark-results");
|
|
73584
|
+
const devices = covered.map((d) => {
|
|
73585
|
+
const row = byKey.get(d.deviceKey);
|
|
73586
|
+
const sessions = Math.max(0, Math.floor(row?.maxSessions ?? 0));
|
|
73587
|
+
return {
|
|
73588
|
+
deviceKey: d.deviceKey,
|
|
73589
|
+
sessions,
|
|
73590
|
+
weight: sessions,
|
|
73591
|
+
modelId: row?.modelId ?? null,
|
|
73592
|
+
fps: null,
|
|
73593
|
+
measured: true
|
|
73594
|
+
};
|
|
73595
|
+
});
|
|
73596
|
+
return {
|
|
73597
|
+
rec,
|
|
73598
|
+
devices,
|
|
73599
|
+
capacitySource: "benchmark",
|
|
73600
|
+
capacityFallback: null,
|
|
73601
|
+
skippedReason: devices.reduce((sum, d) => sum + d.sessions, 0) > 0 ? null : "no-capacity"
|
|
73602
|
+
};
|
|
73603
|
+
}
|
|
73604
|
+
/** Shares proportional to capacity — the automatic shares and the suggestion are this. */
|
|
73605
|
+
function computeCapacityShares(input) {
|
|
73606
|
+
const sized = input.recommendations.map((rec) => sizeNode(rec, input));
|
|
73607
|
+
const capacityByNode = /* @__PURE__ */ new Map();
|
|
73608
|
+
for (const node of sized) {
|
|
73609
|
+
const capacity = node.devices.reduce((sum, d) => sum + d.sessions, 0);
|
|
73610
|
+
if (node.skippedReason === null && capacity > 0) capacityByNode.set(node.rec.nodeId, capacity);
|
|
73611
|
+
}
|
|
73612
|
+
const nodePct = toPercentShares(capacityByNode);
|
|
73613
|
+
const nodes = sized.map((node) => {
|
|
73614
|
+
const devicePct = toPercentShares(new Map(node.devices.map((d) => [d.deviceKey, d.weight])));
|
|
73615
|
+
return {
|
|
73616
|
+
nodeId: node.rec.nodeId,
|
|
73617
|
+
share: nodePct.get(node.rec.nodeId) ?? null,
|
|
73618
|
+
capacitySessions: node.devices.reduce((sum, d) => sum + d.sessions, 0),
|
|
73619
|
+
skippedReason: node.skippedReason,
|
|
73620
|
+
capacitySource: node.capacitySource,
|
|
73621
|
+
capacityFallback: node.capacityFallback,
|
|
73622
|
+
devices: node.devices.map((d) => ({
|
|
73623
|
+
deviceKey: d.deviceKey,
|
|
73624
|
+
share: devicePct.get(d.deviceKey) ?? 0,
|
|
73625
|
+
modelId: d.modelId,
|
|
73626
|
+
fps: d.fps,
|
|
73627
|
+
measured: d.measured,
|
|
73628
|
+
suggestedMaxSessions: d.sessions
|
|
73629
|
+
}))
|
|
73630
|
+
};
|
|
73631
|
+
});
|
|
73632
|
+
return {
|
|
73633
|
+
headroom: input.headroom,
|
|
73634
|
+
source: input.source,
|
|
73635
|
+
cameraFps: input.cameraFps,
|
|
73636
|
+
minSessionsPerDevice: input.minSessionsPerDevice,
|
|
73637
|
+
nodes
|
|
73638
|
+
};
|
|
73639
|
+
}
|
|
73640
|
+
//#endregion
|
|
73422
73641
|
//#region src/pipeline/root-face-crop.ts
|
|
73423
73642
|
/** Side of the square, as a multiple of the face box's longer side. */
|
|
73424
73643
|
var ROOT_FACE_REFINE_SCALE = 1.6;
|
|
@@ -75796,6 +76015,8 @@ exports.CameraSwitchWarningSchema = CameraSwitchWarningSchema;
|
|
|
75796
76015
|
exports.CandidateQueryFilterSchema = CandidateQueryFilterSchema;
|
|
75797
76016
|
exports.CapScopeSchema = CapScopeSchema;
|
|
75798
76017
|
exports.CapabilityBindingsSchema = CapabilityBindingsSchema;
|
|
76018
|
+
exports.CapacityFallbackSchema = CapacityFallbackSchema;
|
|
76019
|
+
exports.CapacitySourceSchema = CapacitySourceSchema;
|
|
75799
76020
|
exports.CarbonMonoxideStatusSchema = CarbonMonoxideStatusSchema;
|
|
75800
76021
|
exports.ChargingStatus = require_err_msg.ChargingStatus;
|
|
75801
76022
|
exports.ClaimOutcomeSchema = ClaimOutcomeSchema;
|
|
@@ -75920,12 +76141,12 @@ exports.DECLARED_DEVICE_SWEEP_LIMIT = DECLARED_DEVICE_SWEEP_LIMIT;
|
|
|
75920
76141
|
exports.DECLARED_INTEGRATION_FIXED_KEY = DECLARED_INTEGRATION_FIXED_KEY;
|
|
75921
76142
|
exports.DEFAULT_ADDON_PLACEMENT = DEFAULT_ADDON_PLACEMENT;
|
|
75922
76143
|
exports.DEFAULT_AUDIO_ANALYZER_CONFIG = DEFAULT_AUDIO_ANALYZER_CONFIG;
|
|
76144
|
+
exports.DEFAULT_CAMERA_FPS = DEFAULT_CAMERA_FPS;
|
|
75923
76145
|
exports.DEFAULT_CAMERA_SENSOR_MODE = DEFAULT_CAMERA_SENSOR_MODE;
|
|
75924
76146
|
exports.DEFAULT_CLUSTER_STEP_MODELS = DEFAULT_CLUSTER_STEP_MODELS;
|
|
75925
76147
|
exports.DEFAULT_CLUSTER_STEP_SETTINGS = DEFAULT_CLUSTER_STEP_SETTINGS;
|
|
75926
76148
|
exports.DEFAULT_CORE_BLOCK_ENTRY = DEFAULT_CORE_BLOCK_ENTRY;
|
|
75927
76149
|
exports.DEFAULT_DECODER_HWACCEL_CONFIG = DEFAULT_DECODER_HWACCEL_CONFIG;
|
|
75928
|
-
exports.DEFAULT_DEMAND_OPTIONS = DEFAULT_DEMAND_OPTIONS;
|
|
75929
76150
|
exports.DEFAULT_DETAIL_CROP_CONVENTION = DEFAULT_DETAIL_CROP_CONVENTION;
|
|
75930
76151
|
exports.DEFAULT_EVENTS_BAND_BUFFER_SEC = DEFAULT_EVENTS_BAND_BUFFER_SEC;
|
|
75931
76152
|
exports.DEFAULT_EVENT_COLOR = DEFAULT_EVENT_COLOR;
|
|
@@ -75933,6 +76154,7 @@ exports.DEFAULT_FEATURES = DEFAULT_FEATURES;
|
|
|
75933
76154
|
exports.DEFAULT_FIRST_SIGHTING_FRESHNESS_MS = require_composition.DEFAULT_FIRST_SIGHTING_FRESHNESS_MS;
|
|
75934
76155
|
exports.DEFAULT_HEADROOM = DEFAULT_HEADROOM;
|
|
75935
76156
|
exports.DEFAULT_MIN_LANDMARK_FACE_SIZE_PX = DEFAULT_MIN_LANDMARK_FACE_SIZE_PX;
|
|
76157
|
+
exports.DEFAULT_MIN_SESSIONS_PER_DEVICE = DEFAULT_MIN_SESSIONS_PER_DEVICE;
|
|
75936
76158
|
exports.DEFAULT_NATIVE_LEASE_SETTINGS = DEFAULT_NATIVE_LEASE_SETTINGS;
|
|
75937
76159
|
exports.DEFAULT_OVERLAY_LAYERS = DEFAULT_OVERLAY_LAYERS;
|
|
75938
76160
|
exports.DEFAULT_POOL_MEMORY_POLICY = DEFAULT_POOL_MEMORY_POLICY;
|
|
@@ -75993,7 +76215,6 @@ exports.DetectorStoreClearSchema = DetectorStoreClearSchema;
|
|
|
75993
76215
|
exports.DeviceAdminLinkSchema = DeviceAdminLinkSchema;
|
|
75994
76216
|
exports.DeviceCodeSeveritySchema = DeviceCodeSeveritySchema;
|
|
75995
76217
|
exports.DeviceConfig = DeviceConfig;
|
|
75996
|
-
exports.DeviceDemandSchema = DeviceDemandSchema;
|
|
75997
76218
|
exports.DeviceDiscoveryStatusSchema = DeviceDiscoveryStatusSchema;
|
|
75998
76219
|
exports.DeviceExportExposeInputSchema = ExposeInputSchema;
|
|
75999
76220
|
exports.DeviceExportStatusSchema = DeviceExportStatusSchema;
|
|
@@ -76301,6 +76522,7 @@ exports.MEDIA_PRESENCE_OWNER_KINDS = MEDIA_PRESENCE_OWNER_KINDS;
|
|
|
76301
76522
|
exports.METHOD_ACCESS_MAP = METHOD_ACCESS_MAP;
|
|
76302
76523
|
exports.METHOD_DEVICE_SELECTORS = METHOD_DEVICE_SELECTORS;
|
|
76303
76524
|
exports.MINUTES_PER_DAY = MINUTES_PER_DAY;
|
|
76525
|
+
exports.MIN_SESSIONS_PER_DEVICE_RANGE = MIN_SESSIONS_PER_DEVICE_RANGE;
|
|
76304
76526
|
exports.MODEL_FORMATS = MODEL_FORMATS;
|
|
76305
76527
|
exports.MODEL_HOSTING = MODEL_HOSTING;
|
|
76306
76528
|
exports.MODEL_PROVIDER_IDS = MODEL_PROVIDER_IDS;
|
|
@@ -76463,6 +76685,7 @@ exports.NC_TEMPLATE_VARS = NC_TEMPLATE_VARS;
|
|
|
76463
76685
|
exports.NC_UPDATE_EVENT_PACKAGE_NAMES = NC_UPDATE_EVENT_PACKAGE_NAMES;
|
|
76464
76686
|
exports.NETWORK_LINK_TYPES = NETWORK_LINK_TYPES;
|
|
76465
76687
|
exports.NETWORK_LINK_UNKNOWN = NETWORK_LINK_UNKNOWN;
|
|
76688
|
+
exports.NO_MEASURED_CAPACITY = NO_MEASURED_CAPACITY;
|
|
76466
76689
|
exports.NativeCropBboxSchema = NativeCropBboxSchema;
|
|
76467
76690
|
exports.NativeCropRefSchema = NativeCropRefSchema;
|
|
76468
76691
|
exports.NativeCropResultSchema = NativeCropResultSchema;
|
|
@@ -76593,7 +76816,6 @@ exports.NotificationFormatSchema = NotificationFormatSchema;
|
|
|
76593
76816
|
exports.NotificationSchema = NotificationSchema;
|
|
76594
76817
|
exports.NotifierStatusSchema = NotifierStatusSchema;
|
|
76595
76818
|
exports.NumericSensorStatusSchema = NumericSensorStatusSchema;
|
|
76596
|
-
exports.OBSERVATION_WINDOW_MS = OBSERVATION_WINDOW_MS;
|
|
76597
76819
|
exports.OPERATOR_WRITTEN_STALE_MS = OPERATOR_WRITTEN_STALE_MS;
|
|
76598
76820
|
exports.OPS_LOG_DEFAULT_LIMIT = OPS_LOG_DEFAULT_LIMIT;
|
|
76599
76821
|
exports.OPS_LOG_RING_DEFAULT_MAX = OPS_LOG_RING_DEFAULT_MAX;
|
|
@@ -77199,6 +77421,7 @@ exports.cameraSensorRefKey = cameraSensorRefKey;
|
|
|
77199
77421
|
exports.cameraStreamsCapability = cameraStreamsCapability;
|
|
77200
77422
|
exports.canConvertUnit = canConvertUnit;
|
|
77201
77423
|
exports.canonicalEgressPlan = canonicalEgressPlan;
|
|
77424
|
+
exports.capacitySessionsOf = capacitySessionsOf;
|
|
77202
77425
|
exports.carbonMonoxideCapability = carbonMonoxideCapability;
|
|
77203
77426
|
exports.cellsToRects = cellsToRects;
|
|
77204
77427
|
exports.checkRoleAddress = checkRoleAddress;
|
|
@@ -77240,6 +77463,7 @@ exports.compositionReadKey = require_composition.compositionReadKey;
|
|
|
77240
77463
|
exports.compositionSliceKey = require_composition.compositionSliceKey;
|
|
77241
77464
|
exports.compositionSourceKey = require_composition.compositionSourceKey;
|
|
77242
77465
|
exports.compositionSourceRefs = compositionSourceRefs;
|
|
77466
|
+
exports.computeCapacityShares = computeCapacityShares;
|
|
77243
77467
|
exports.conditionDepth = conditionDepth;
|
|
77244
77468
|
exports.conditionExclusionReason = conditionExclusionReason;
|
|
77245
77469
|
exports.conditionVisibleForKind = conditionVisibleForKind;
|
|
@@ -77326,6 +77550,7 @@ exports.deviceProviderCapability = deviceProviderCapability;
|
|
|
77326
77550
|
exports.deviceSelectorMatches = deviceSelectorMatches;
|
|
77327
77551
|
exports.deviceStateCapability = deviceStateCapability;
|
|
77328
77552
|
exports.deviceStatusCapability = deviceStatusCapability;
|
|
77553
|
+
exports.diffStepSettings = diffStepSettings;
|
|
77329
77554
|
exports.disarmRoseMemory = require_composition.disarmRoseMemory;
|
|
77330
77555
|
exports.displayIconEntry = displayIconEntry;
|
|
77331
77556
|
exports.displayIconsInGroup = displayIconsInGroup;
|
|
@@ -77333,6 +77558,7 @@ exports.doActionSelectValue = doActionSelectValue;
|
|
|
77333
77558
|
exports.doorbellCapability = doorbellCapability;
|
|
77334
77559
|
exports.doorbellFeatureSources = doorbellFeatureSources;
|
|
77335
77560
|
exports.droppedConditionsForKind = droppedConditionsForKind;
|
|
77561
|
+
exports.effectiveStepSettings = effectiveStepSettings;
|
|
77336
77562
|
exports.egressTranscodeSharingKey = egressTranscodeSharingKey;
|
|
77337
77563
|
exports.egressTransportFromRequest = egressTransportFromRequest;
|
|
77338
77564
|
exports.electByShare = electByShare;
|
|
@@ -77353,8 +77579,6 @@ exports.enumerateInferenceDevices = enumerateInferenceDevices;
|
|
|
77353
77579
|
exports.enumerateItemArrayFields = enumerateItemArrayFields;
|
|
77354
77580
|
exports.enumerateSchemaFields = enumerateSchemaFields;
|
|
77355
77581
|
exports.errMsg = require_err_msg.errMsg;
|
|
77356
|
-
exports.estimateDeviceDemand = estimateDeviceDemand;
|
|
77357
|
-
exports.estimatedConcurrentSessions = estimatedConcurrentSessions;
|
|
77358
77582
|
exports.evaluateAst = require_composition.evaluateAst;
|
|
77359
77583
|
exports.evaluateCompositionField = evaluateCompositionField;
|
|
77360
77584
|
exports.evaluateCount = require_composition.evaluateCount;
|
|
@@ -77390,6 +77614,8 @@ exports.feederCustomizationExample = feederCustomizationExample;
|
|
|
77390
77614
|
exports.feederExampleSources = feederExampleSources;
|
|
77391
77615
|
exports.ffmpegRate = ffmpegRate;
|
|
77392
77616
|
exports.fieldReads = require_composition.fieldReads;
|
|
77617
|
+
exports.fieldUnitKeys = fieldUnitKeys;
|
|
77618
|
+
exports.fieldsPinnedAtValueBelow = fieldsPinnedAtValueBelow;
|
|
77393
77619
|
exports.filesystemBrowseCapability = filesystemBrowseCapability;
|
|
77394
77620
|
exports.findCandidateCycles = findCandidateCycles;
|
|
77395
77621
|
exports.findCompositionCycles = findCompositionCycles;
|
|
@@ -77441,6 +77667,7 @@ exports.isAudioChunkFormat = require_sleep.isAudioChunkFormat;
|
|
|
77441
77667
|
exports.isAudioClassName = isAudioClassName;
|
|
77442
77668
|
exports.isAudioLabelSelected = isAudioLabelSelected;
|
|
77443
77669
|
exports.isAudioRule = isAudioRule;
|
|
77670
|
+
exports.isAutomaticShareSource = isAutomaticShareSource;
|
|
77444
77671
|
exports.isBaseConditionKey = isBaseConditionKey;
|
|
77445
77672
|
exports.isBatteryPresenceFault = isBatteryPresenceFault;
|
|
77446
77673
|
exports.isClusterScopedStep = isClusterScopedStep;
|
|
@@ -77527,6 +77754,7 @@ exports.mayReadLocation = mayReadLocation;
|
|
|
77527
77754
|
exports.mayWriteToLocation = mayWriteToLocation;
|
|
77528
77755
|
exports.mediaPlayerCapability = mediaPlayerCapability;
|
|
77529
77756
|
exports.memoizePinnedFfmpeg = memoizePinnedFfmpeg;
|
|
77757
|
+
exports.mergeSettingsBags = mergeSettingsBags;
|
|
77530
77758
|
exports.mergeSourceInfo = mergeSourceInfo;
|
|
77531
77759
|
exports.meshNetworkCapability = meshNetworkCapability;
|
|
77532
77760
|
exports.method = require_sleep.method;
|
|
@@ -77733,6 +77961,8 @@ exports.sensorTransitionOffered = sensorTransitionOffered;
|
|
|
77733
77961
|
exports.servedTemplateVars = servedTemplateVars;
|
|
77734
77962
|
exports.serverManagementCapability = serverManagementCapability;
|
|
77735
77963
|
exports.setByPath = setByPath;
|
|
77964
|
+
exports.settingValuesEqual = settingValuesEqual;
|
|
77965
|
+
exports.settingsBelow = settingsBelow;
|
|
77736
77966
|
exports.settingsStoreCapability = settingsStoreCapability;
|
|
77737
77967
|
exports.signalPercentFromBars = signalPercentFromBars;
|
|
77738
77968
|
exports.signalPercentFromRssi = signalPercentFromRssi;
|
|
@@ -77749,6 +77979,7 @@ exports.startReachabilityPoll = startReachabilityPoll;
|
|
|
77749
77979
|
exports.stateLabel = stateLabel;
|
|
77750
77980
|
exports.stateVocabularyFor = stateVocabularyFor;
|
|
77751
77981
|
exports.stepModelRunsOnFormat = stepModelRunsOnFormat;
|
|
77982
|
+
exports.stepSettingSource = stepSettingSource;
|
|
77752
77983
|
exports.storageCapability = storageCapability;
|
|
77753
77984
|
exports.storageEvictableCapability = storageEvictableCapability;
|
|
77754
77985
|
exports.storageMigrationCapability = storageMigrationCapability;
|
|
@@ -77800,6 +78031,7 @@ exports.toAppLinkHubOrigin = toAppLinkHubOrigin;
|
|
|
77800
78031
|
exports.toDeviceSummary = toDeviceSummary;
|
|
77801
78032
|
exports.toExpressionValue = require_composition.toExpressionValue;
|
|
77802
78033
|
exports.toNodeId = require_sleep.toNodeId;
|
|
78034
|
+
exports.toPercentShares = toPercentShares;
|
|
77803
78035
|
exports.toStreamSourceEntry = toStreamSourceEntry;
|
|
77804
78036
|
exports.toastCapability = toastCapability;
|
|
77805
78037
|
exports.toggleAudioLabel = toggleAudioLabel;
|
|
@@ -77840,7 +78072,9 @@ exports.wiringHealthSnapshotSchema = wiringHealthSnapshotSchema;
|
|
|
77840
78072
|
exports.wiringNodeHealthSchema = wiringNodeHealthSchema;
|
|
77841
78073
|
exports.wiringProbeKindSchema = wiringProbeKindSchema;
|
|
77842
78074
|
exports.wiringProbeResultSchema = wiringProbeResultSchema;
|
|
78075
|
+
exports.withFieldFrom = withFieldFrom;
|
|
77843
78076
|
exports.withLocationMode = withLocationMode;
|
|
78077
|
+
exports.withoutField = withoutField;
|
|
77844
78078
|
exports.writeModelBoundSetting = writeModelBoundSetting;
|
|
77845
78079
|
exports.zodEntriesToConfigUI = zodEntriesToConfigUI;
|
|
77846
78080
|
exports.zoneAnalyticsCapability = zoneAnalyticsCapability;
|