@camstack/types 1.2.317 → 1.2.319
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 +9 -3
- package/dist/addon.mjs +9 -3
- package/dist/capabilities/pipeline-executor.cap.d.ts +1 -1
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +146 -16
- package/dist/client.js +7 -3
- package/dist/client.mjs +7 -3
- package/dist/generated/addon-api.d.ts +41 -13
- package/dist/generated/cap-input-defaults.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +438 -65
- package/dist/index.mjs +406 -59
- package/dist/pipeline/{best-settings → auto-tune}/demand.d.ts +27 -30
- package/dist/pipeline/{best-settings → auto-tune}/hardware-class.d.ts +1 -1
- package/dist/pipeline/{best-settings → auto-tune}/index.d.ts +1 -1
- package/dist/pipeline/{best-settings → auto-tune}/plan-schemas.d.ts +41 -15
- package/dist/pipeline/{best-settings → auto-tune}/recommend.d.ts +6 -6
- package/dist/pipeline/load-balancing/effective-shares.d.ts +28 -0
- package/dist/pipeline/load-balancing/index.d.ts +8 -0
- package/dist/pipeline/load-balancing/schemas.d.ts +232 -0
- package/dist/pipeline/load-balancing/share-election.d.ts +54 -0
- package/dist/pipeline/model-bound-settings.d.ts +1 -1
- package/dist/types/agent-pipeline-settings.d.ts +0 -1
- package/package.json +1 -1
- /package/dist/pipeline/{best-settings → auto-tune}/detector-performance.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -26870,7 +26870,7 @@ var pipelineExecutorCapability = {
|
|
|
26870
26870
|
auth: "admin"
|
|
26871
26871
|
}),
|
|
26872
26872
|
/**
|
|
26873
|
-
*
|
|
26873
|
+
* Auto tune (D745): the MODEL-BOUND thresholds (`bindsToModel` keys of
|
|
26874
26874
|
* the object-detection root, and their binding keys) stored in THIS node's
|
|
26875
26875
|
* per-camera detector settings — and, unless `dryRun`, remove them so the
|
|
26876
26876
|
* running model's own defaults apply. Every other key of a camera's store
|
|
@@ -27242,9 +27242,170 @@ var pipelineExecutorCapability = {
|
|
|
27242
27242
|
}
|
|
27243
27243
|
};
|
|
27244
27244
|
//#endregion
|
|
27245
|
-
//#region src/pipeline/
|
|
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
|
+
//#region src/pipeline/auto-tune/plan-schemas.ts
|
|
27246
27407
|
/**
|
|
27247
|
-
* The wire shapes of the
|
|
27408
|
+
* The wire shapes of the Auto tune plan and apply (D745), used by the
|
|
27248
27409
|
* `pipeline-orchestrator` cap. The recommender's own types
|
|
27249
27410
|
* (`recommend.ts`, `demand.ts`) are the TS face of the same data; these
|
|
27250
27411
|
* schemas are what crosses the cap boundary.
|
|
@@ -27320,7 +27481,9 @@ var DeviceDemandSchema = zod.z.object({
|
|
|
27320
27481
|
"estimate",
|
|
27321
27482
|
"none"
|
|
27322
27483
|
]),
|
|
27323
|
-
observedForMs: zod.z.number().nullable()
|
|
27484
|
+
observedForMs: zod.z.number().nullable(),
|
|
27485
|
+
/** How on-motion sessions were charged: per-device observation, or split by share (D748). */
|
|
27486
|
+
placement: SessionPlacementPolicySchema
|
|
27324
27487
|
});
|
|
27325
27488
|
var DeviceModelChoiceSchema = zod.z.object({
|
|
27326
27489
|
modelId: zod.z.string(),
|
|
@@ -27377,7 +27540,7 @@ var DetectorStoreClearSchema = zod.z.object({
|
|
|
27377
27540
|
deviceId: zod.z.number(),
|
|
27378
27541
|
keys: zod.z.array(zod.z.string()).readonly()
|
|
27379
27542
|
});
|
|
27380
|
-
var
|
|
27543
|
+
var AutoTuneWarningSchema = zod.z.discriminatedUnion("kind", [
|
|
27381
27544
|
zod.z.object({
|
|
27382
27545
|
kind: zod.z.literal("detector-store-cluster-wide"),
|
|
27383
27546
|
skippedNodes: zod.z.array(zod.z.string()).readonly()
|
|
@@ -27392,26 +27555,36 @@ var BestSettingsWarningSchema = zod.z.discriminatedUnion("kind", [
|
|
|
27392
27555
|
deviceKey: zod.z.string()
|
|
27393
27556
|
})
|
|
27394
27557
|
]);
|
|
27395
|
-
var
|
|
27396
|
-
/** Share of each accelerator's throughput kept free (0.3–0.5). */
|
|
27397
|
-
headroom: zod.z.number().min(.3).max(.5).default(.4)
|
|
27398
|
-
|
|
27558
|
+
var AutoTuneOptionsSchema = zod.z.object({
|
|
27559
|
+
/** Share of each accelerator's throughput kept free (0.3–0.5). */
|
|
27560
|
+
headroom: zod.z.number().min(.3).max(.5).default(.4),
|
|
27561
|
+
/**
|
|
27562
|
+
* What-if shares (D748): plan as if these node/device shares were stored
|
|
27563
|
+
* and the policy were `share`. Absent = the stored shares under the stored
|
|
27564
|
+
* policy. A what-if plan is for display; apply always re-plans from what
|
|
27565
|
+
* is stored.
|
|
27566
|
+
*/
|
|
27567
|
+
shares: LoadBalancingSharesInputSchema.optional()
|
|
27568
|
+
});
|
|
27569
|
+
var AutoTunePlanSchema = zod.z.object({
|
|
27399
27570
|
/** Hash of everything the apply will write — the apply refuses a different one. */
|
|
27400
27571
|
planHash: zod.z.string(),
|
|
27401
27572
|
family: zod.z.literal("yolov9"),
|
|
27402
27573
|
headroom: zod.z.number(),
|
|
27574
|
+
/** Planned under what-if shares (D748): for display — apply refuses it as stale. */
|
|
27575
|
+
whatIf: zod.z.boolean(),
|
|
27403
27576
|
generatedAt: zod.z.number(),
|
|
27404
27577
|
nodes: zod.z.array(NodeRecommendationSchema).readonly(),
|
|
27405
27578
|
nodeChanges: zod.z.array(NodeDeviceChangeSchema).readonly(),
|
|
27406
27579
|
cameraClears: zod.z.array(CameraOverrideClearSchema).readonly(),
|
|
27407
27580
|
detectorStoreClears: zod.z.array(DetectorStoreClearSchema).readonly(),
|
|
27408
|
-
warnings: zod.z.array(
|
|
27581
|
+
warnings: zod.z.array(AutoTuneWarningSchema).readonly()
|
|
27409
27582
|
});
|
|
27410
|
-
var
|
|
27583
|
+
var AutoTuneApplyInputSchema = zod.z.object({
|
|
27411
27584
|
planHash: zod.z.string(),
|
|
27412
27585
|
headroom: zod.z.number().min(.3).max(.5).default(.4)
|
|
27413
27586
|
});
|
|
27414
|
-
var
|
|
27587
|
+
var AutoTunePhaseResultSchema = zod.z.object({
|
|
27415
27588
|
phase: zod.z.enum([
|
|
27416
27589
|
"download",
|
|
27417
27590
|
"camera-overrides",
|
|
@@ -27422,19 +27595,19 @@ var BestSettingsPhaseResultSchema = zod.z.object({
|
|
|
27422
27595
|
ok: zod.z.boolean(),
|
|
27423
27596
|
detail: zod.z.string()
|
|
27424
27597
|
});
|
|
27425
|
-
var
|
|
27598
|
+
var AutoTuneApplyResultSchema = zod.z.discriminatedUnion("kind", [
|
|
27426
27599
|
zod.z.object({
|
|
27427
27600
|
kind: zod.z.literal("applied"),
|
|
27428
27601
|
planHash: zod.z.string(),
|
|
27429
|
-
phases: zod.z.array(
|
|
27602
|
+
phases: zod.z.array(AutoTunePhaseResultSchema).readonly()
|
|
27430
27603
|
}),
|
|
27431
27604
|
zod.z.object({
|
|
27432
27605
|
kind: zod.z.literal("aborted"),
|
|
27433
|
-
phases: zod.z.array(
|
|
27606
|
+
phases: zod.z.array(AutoTunePhaseResultSchema).readonly()
|
|
27434
27607
|
}),
|
|
27435
27608
|
zod.z.object({
|
|
27436
27609
|
kind: zod.z.literal("stale"),
|
|
27437
|
-
plan:
|
|
27610
|
+
plan: AutoTunePlanSchema
|
|
27438
27611
|
}),
|
|
27439
27612
|
zod.z.object({
|
|
27440
27613
|
kind: zod.z.literal("refused"),
|
|
@@ -29055,7 +29228,6 @@ var CameraStepOverridePatchSchema = zod.z.object({
|
|
|
29055
29228
|
settings: zod.z.record(zod.z.string(), zod.z.unknown()).readonly().optional()
|
|
29056
29229
|
});
|
|
29057
29230
|
var CameraPipelineSettingsSchema = zod.z.object({
|
|
29058
|
-
pinnedAgentNodeId: zod.z.string().optional(),
|
|
29059
29231
|
stepToggles: zod.z.record(zod.z.string(), zod.z.boolean()).optional(),
|
|
29060
29232
|
stepOverridesByDevice: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), CameraStepOverridePatchSchema))).optional(),
|
|
29061
29233
|
pipelineByAgent: zod.z.record(zod.z.string(), CameraPipelineForAgentSchema).optional()
|
|
@@ -29749,18 +29921,6 @@ var pipelineOrchestratorCapability = {
|
|
|
29749
29921
|
auth: "admin"
|
|
29750
29922
|
}),
|
|
29751
29923
|
/**
|
|
29752
|
-
* Set a node's detection WEIGHT (relative share for the quota balancer).
|
|
29753
|
-
* `null` clears it (back to the implicit weight 1). Unpinned cameras
|
|
29754
|
-
* distribute proportionally to weight; `maxCameras` still clamps on top.
|
|
29755
|
-
*/
|
|
29756
|
-
setAgentDetectWeight: require_sleep.method(zod.z.object({
|
|
29757
|
-
agentNodeId: zod.z.string(),
|
|
29758
|
-
detectWeight: zod.z.number().positive().nullable()
|
|
29759
|
-
}), zod.z.object({ success: zod.z.literal(true) }), {
|
|
29760
|
-
kind: "mutation",
|
|
29761
|
-
auth: "admin"
|
|
29762
|
-
}),
|
|
29763
|
-
/**
|
|
29764
29924
|
* Set one node's placement CAPABILITIES — the per-node record that
|
|
29765
29925
|
* replaced the four flat orchestrator lists (`enabledNodes`,
|
|
29766
29926
|
* `enabledDecoderNodes`, `enabledAudioNodes`, `remoteSourcingNodes`).
|
|
@@ -29880,7 +30040,7 @@ var pipelineOrchestratorCapability = {
|
|
|
29880
30040
|
auth: "admin"
|
|
29881
30041
|
}),
|
|
29882
30042
|
/**
|
|
29883
|
-
*
|
|
30043
|
+
* Auto tune (D745) — DRY RUN. Recommends ONE detector family (YOLOv9)
|
|
29884
30044
|
* for the whole cluster from each node's static hardware class, the
|
|
29885
30045
|
* measured latency table and the detection demand, and lists every write
|
|
29886
30046
|
* the apply would make: the node model pins set, the enrichment pins and
|
|
@@ -29889,14 +30049,57 @@ var pipelineOrchestratorCapability = {
|
|
|
29889
30049
|
* enablement, device enablement, pins, recording, notifications, zones and
|
|
29890
30050
|
* rules are never part of it. `planHash` names exactly this diff.
|
|
29891
30051
|
*/
|
|
29892
|
-
|
|
30052
|
+
planAutoTune: require_sleep.method(AutoTuneOptionsSchema, AutoTunePlanSchema, { auth: "admin" }),
|
|
29893
30053
|
/**
|
|
29894
|
-
*
|
|
30054
|
+
* Auto tune (D745) — APPLY the plan the operator confirmed. Recomputes
|
|
29895
30055
|
* the plan and refuses (`stale`, with the fresh plan) when its hash is not
|
|
29896
30056
|
* `planHash`, so what is written is exactly the confirmed diff. Offline
|
|
29897
30057
|
* nodes are skipped; there is no undo.
|
|
29898
30058
|
*/
|
|
29899
|
-
|
|
30059
|
+
applyAutoTune: require_sleep.method(AutoTuneApplyInputSchema, AutoTuneApplyResultSchema, {
|
|
30060
|
+
kind: "mutation",
|
|
30061
|
+
auth: "admin"
|
|
30062
|
+
}),
|
|
30063
|
+
/**
|
|
30064
|
+
* Load balancing (D748) — write node shares (`detectWeight`) and per-node
|
|
30065
|
+
* device shares (inference-device `weight`) in ONE atomic read-modify-write
|
|
30066
|
+
* of the agent settings — the only writer of node shares (the per-node
|
|
30067
|
+
* `setAgentDetectWeight` it replaced raced its siblings, one RMW each).
|
|
30068
|
+
* A node or device left out keeps its weight. Never changes the
|
|
30069
|
+
* `sessionPlacement` policy.
|
|
30070
|
+
*/
|
|
30071
|
+
setLoadBalancingShares: require_sleep.method(LoadBalancingSharesInputSchema, zod.z.object({ success: zod.z.literal(true) }), {
|
|
30072
|
+
kind: "mutation",
|
|
30073
|
+
auth: "admin"
|
|
30074
|
+
}),
|
|
30075
|
+
/**
|
|
30076
|
+
* Load balancing (D748) — what placement actually did: per node and
|
|
30077
|
+
* device, sessions now, sessions started and the time-weighted share of
|
|
30078
|
+
* PARALLEL sessions over `windowMs`; the cluster's parallel peak; yields
|
|
30079
|
+
* a share election made; and every device pin the session path cannot
|
|
30080
|
+
* honour. In memory on the hub — a restart starts a new window.
|
|
30081
|
+
*/
|
|
30082
|
+
getPlacementStats: require_sleep.method(PlacementStatsInputSchema, PlacementStatsSchema, { auth: "admin" }),
|
|
30083
|
+
/**
|
|
30084
|
+
* Load balancing (D748) — shares proportional to each node's measured
|
|
30085
|
+
* capacity at the models Auto tune would pick, iterated (≤ 3 rounds)
|
|
30086
|
+
* until the shares stop moving; per device, an ADVISORY session cap.
|
|
30087
|
+
* Writes nothing.
|
|
30088
|
+
*/
|
|
30089
|
+
suggestShares: require_sleep.method(SuggestSharesInputSchema, SuggestSharesResultSchema, { auth: "admin" }),
|
|
30090
|
+
/**
|
|
30091
|
+
* Load balancing (D750) — the shares placement reads now: the source
|
|
30092
|
+
* (automatic capacity shares or the operator's sliders), each node's and
|
|
30093
|
+
* device's configured share, and the effective share after a node or
|
|
30094
|
+
* device that cannot take sessions gave its share to the others.
|
|
30095
|
+
*/
|
|
30096
|
+
getEffectiveShares: require_sleep.method(zod.z.void(), EffectiveSharesSchema, { auth: "admin" }),
|
|
30097
|
+
/**
|
|
30098
|
+
* Load balancing (D750) — switch between automatic and manual shares.
|
|
30099
|
+
* Going manual seeds the sliders with the current automatic shares (one
|
|
30100
|
+
* atomic write), so nothing jumps; going automatic recomputes at once.
|
|
30101
|
+
*/
|
|
30102
|
+
setShareSource: require_sleep.method(SetShareSourceInputSchema, zod.z.object({ success: zod.z.literal(true) }), {
|
|
29900
30103
|
kind: "mutation",
|
|
29901
30104
|
auth: "admin"
|
|
29902
30105
|
}),
|
|
@@ -56204,7 +56407,7 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56204
56407
|
addonId: null,
|
|
56205
56408
|
access: "view"
|
|
56206
56409
|
},
|
|
56207
|
-
"pipelineOrchestrator.
|
|
56410
|
+
"pipelineOrchestrator.applyAutoTune": {
|
|
56208
56411
|
capName: "pipeline-orchestrator",
|
|
56209
56412
|
capScope: "system",
|
|
56210
56413
|
addonId: null,
|
|
@@ -56324,6 +56527,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56324
56527
|
addonId: null,
|
|
56325
56528
|
access: "view"
|
|
56326
56529
|
},
|
|
56530
|
+
"pipelineOrchestrator.getEffectiveShares": {
|
|
56531
|
+
capName: "pipeline-orchestrator",
|
|
56532
|
+
capScope: "system",
|
|
56533
|
+
addonId: null,
|
|
56534
|
+
access: "view"
|
|
56535
|
+
},
|
|
56327
56536
|
"pipelineOrchestrator.getGlobalMetrics": {
|
|
56328
56537
|
capName: "pipeline-orchestrator",
|
|
56329
56538
|
capScope: "system",
|
|
@@ -56360,6 +56569,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56360
56569
|
addonId: null,
|
|
56361
56570
|
access: "view"
|
|
56362
56571
|
},
|
|
56572
|
+
"pipelineOrchestrator.getPlacementStats": {
|
|
56573
|
+
capName: "pipeline-orchestrator",
|
|
56574
|
+
capScope: "system",
|
|
56575
|
+
addonId: null,
|
|
56576
|
+
access: "view"
|
|
56577
|
+
},
|
|
56363
56578
|
"pipelineOrchestrator.getReconcileFromDiskStatus": {
|
|
56364
56579
|
capName: "pipeline-orchestrator",
|
|
56365
56580
|
capScope: "system",
|
|
@@ -56384,7 +56599,7 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56384
56599
|
addonId: null,
|
|
56385
56600
|
access: "create"
|
|
56386
56601
|
},
|
|
56387
|
-
"pipelineOrchestrator.
|
|
56602
|
+
"pipelineOrchestrator.planAutoTune": {
|
|
56388
56603
|
capName: "pipeline-orchestrator",
|
|
56389
56604
|
capScope: "system",
|
|
56390
56605
|
addonId: null,
|
|
@@ -56450,12 +56665,6 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56450
56665
|
addonId: null,
|
|
56451
56666
|
access: "create"
|
|
56452
56667
|
},
|
|
56453
|
-
"pipelineOrchestrator.setAgentDetectWeight": {
|
|
56454
|
-
capName: "pipeline-orchestrator",
|
|
56455
|
-
capScope: "system",
|
|
56456
|
-
addonId: null,
|
|
56457
|
-
access: "create"
|
|
56458
|
-
},
|
|
56459
56668
|
"pipelineOrchestrator.setAgentInferenceDevices": {
|
|
56460
56669
|
capName: "pipeline-orchestrator",
|
|
56461
56670
|
capScope: "system",
|
|
@@ -56510,12 +56719,30 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
56510
56719
|
addonId: null,
|
|
56511
56720
|
access: "create"
|
|
56512
56721
|
},
|
|
56722
|
+
"pipelineOrchestrator.setLoadBalancingShares": {
|
|
56723
|
+
capName: "pipeline-orchestrator",
|
|
56724
|
+
capScope: "system",
|
|
56725
|
+
addonId: null,
|
|
56726
|
+
access: "create"
|
|
56727
|
+
},
|
|
56513
56728
|
"pipelineOrchestrator.setPipelineDevicePin": {
|
|
56514
56729
|
capName: "pipeline-orchestrator",
|
|
56515
56730
|
capScope: "system",
|
|
56516
56731
|
addonId: null,
|
|
56517
56732
|
access: "create"
|
|
56518
56733
|
},
|
|
56734
|
+
"pipelineOrchestrator.setShareSource": {
|
|
56735
|
+
capName: "pipeline-orchestrator",
|
|
56736
|
+
capScope: "system",
|
|
56737
|
+
addonId: null,
|
|
56738
|
+
access: "create"
|
|
56739
|
+
},
|
|
56740
|
+
"pipelineOrchestrator.suggestShares": {
|
|
56741
|
+
capName: "pipeline-orchestrator",
|
|
56742
|
+
capScope: "system",
|
|
56743
|
+
addonId: null,
|
|
56744
|
+
access: "view"
|
|
56745
|
+
},
|
|
56519
56746
|
"pipelineOrchestrator.unassignAudio": {
|
|
56520
56747
|
capName: "pipeline-orchestrator",
|
|
56521
56748
|
capScope: "system",
|
|
@@ -67270,15 +67497,19 @@ function createSystemProxy(api) {
|
|
|
67270
67497
|
listAgentSettings: (input) => dispatch("pipelineOrchestrator", "listAgentSettings", "query", input),
|
|
67271
67498
|
removeAgentSettings: (input) => dispatch("pipelineOrchestrator", "removeAgentSettings", "mutation", input),
|
|
67272
67499
|
setAgentMaxCameras: (input) => dispatch("pipelineOrchestrator", "setAgentMaxCameras", "mutation", input),
|
|
67273
|
-
setAgentDetectWeight: (input) => dispatch("pipelineOrchestrator", "setAgentDetectWeight", "mutation", input),
|
|
67274
67500
|
setAgentCapabilities: (input) => dispatch("pipelineOrchestrator", "setAgentCapabilities", "mutation", input),
|
|
67275
67501
|
setAgentDecodeLimits: (input) => dispatch("pipelineOrchestrator", "setAgentDecodeLimits", "mutation", input),
|
|
67276
67502
|
setAgentReachableHost: (input) => dispatch("pipelineOrchestrator", "setAgentReachableHost", "mutation", input),
|
|
67277
67503
|
setAgentInferenceDevices: (input) => dispatch("pipelineOrchestrator", "setAgentInferenceDevices", "mutation", input),
|
|
67278
67504
|
getNodeInferenceDevices: (input) => dispatch("pipelineOrchestrator", "getNodeInferenceDevices", "query", input),
|
|
67279
67505
|
resetNodePipelineDefaults: (input) => dispatch("pipelineOrchestrator", "resetNodePipelineDefaults", "mutation", input),
|
|
67280
|
-
|
|
67281
|
-
|
|
67506
|
+
planAutoTune: (input) => dispatch("pipelineOrchestrator", "planAutoTune", "query", input),
|
|
67507
|
+
applyAutoTune: (input) => dispatch("pipelineOrchestrator", "applyAutoTune", "mutation", input),
|
|
67508
|
+
setLoadBalancingShares: (input) => dispatch("pipelineOrchestrator", "setLoadBalancingShares", "mutation", input),
|
|
67509
|
+
getPlacementStats: (input) => dispatch("pipelineOrchestrator", "getPlacementStats", "query", input),
|
|
67510
|
+
suggestShares: (input) => dispatch("pipelineOrchestrator", "suggestShares", "query", input),
|
|
67511
|
+
getEffectiveShares: (input) => dispatch("pipelineOrchestrator", "getEffectiveShares", "query", input),
|
|
67512
|
+
setShareSource: (input) => dispatch("pipelineOrchestrator", "setShareSource", "mutation", input),
|
|
67282
67513
|
getCameraStatuses: (input) => dispatch("pipelineOrchestrator", "getCameraStatuses", "query", input),
|
|
67283
67514
|
setCameraSensors: (input) => dispatch("pipelineOrchestrator", "setCameraSensors", "mutation", input),
|
|
67284
67515
|
reconcileFromDisk: (input) => dispatch("pipelineOrchestrator", "reconcileFromDisk", "mutation", input),
|
|
@@ -72242,7 +72473,7 @@ function clearModelBoundOverrides(settings, boundKeys, modelId) {
|
|
|
72242
72473
|
/**
|
|
72243
72474
|
* The keys of every `bindsToModel` field of a step's config schema, groups
|
|
72244
72475
|
* flattened (D738). One definition for the runner (which applies the binding)
|
|
72245
|
-
* and the orchestrator's
|
|
72476
|
+
* and the orchestrator's Auto tune (which clears those overrides, D745).
|
|
72246
72477
|
*/
|
|
72247
72478
|
function collectModelBoundKeys(fields) {
|
|
72248
72479
|
return fields.flatMap((field) => {
|
|
@@ -72251,7 +72482,7 @@ function collectModelBoundKeys(fields) {
|
|
|
72251
72482
|
});
|
|
72252
72483
|
}
|
|
72253
72484
|
//#endregion
|
|
72254
|
-
//#region src/pipeline/
|
|
72485
|
+
//#region src/pipeline/auto-tune/hardware-class.ts
|
|
72255
72486
|
var APPLE_CHIP = /^Apple M(\d+)(?:\s+(Pro|Max|Ultra))?\b/i;
|
|
72256
72487
|
var INTEL_CORE_ULTRA = /Core\(TM\)\s+Ultra|Core Ultra/i;
|
|
72257
72488
|
var INTEL_N_SERIES = /Intel\(R\)\s+N\d{2,3}\b|\bIntel\s+N\d{2,3}\b/i;
|
|
@@ -72307,7 +72538,7 @@ function acceleratorKindOf(deviceKey, hw) {
|
|
|
72307
72538
|
return null;
|
|
72308
72539
|
}
|
|
72309
72540
|
//#endregion
|
|
72310
|
-
//#region src/pipeline/
|
|
72541
|
+
//#region src/pipeline/auto-tune/detector-performance.ts
|
|
72311
72542
|
var DETECTOR_PERF = {
|
|
72312
72543
|
"intel-core-ultra": {
|
|
72313
72544
|
"intel-npu": {
|
|
@@ -72739,7 +72970,7 @@ var DETECTOR_ACCURACY = {
|
|
|
72739
72970
|
}
|
|
72740
72971
|
};
|
|
72741
72972
|
//#endregion
|
|
72742
|
-
//#region src/pipeline/
|
|
72973
|
+
//#region src/pipeline/auto-tune/demand.ts
|
|
72743
72974
|
var DEFAULT_DEMAND_OPTIONS = {
|
|
72744
72975
|
onMotionConcurrency: .25,
|
|
72745
72976
|
onMotionMinConcurrent: 2
|
|
@@ -72767,6 +72998,7 @@ function estimatedConcurrentSessions(cameraCount, options) {
|
|
|
72767
72998
|
*/
|
|
72768
72999
|
function estimateDeviceDemand(input) {
|
|
72769
73000
|
const options = input.options ?? DEFAULT_DEMAND_OPTIONS;
|
|
73001
|
+
const placement = input.shares ? "share" : "least-loaded";
|
|
72770
73002
|
const eligibleById = new Map(input.eligible.map((d) => [deviceId(d.nodeId, d.deviceKey), d]));
|
|
72771
73003
|
const peakById = new Map(input.peaks.map((p) => [deviceId(p.nodeId, p.deviceKey), p]));
|
|
72772
73004
|
const weightByNode = /* @__PURE__ */ new Map();
|
|
@@ -72786,19 +73018,28 @@ function estimateDeviceDemand(input) {
|
|
|
72786
73018
|
const noteMax = (key, fps) => {
|
|
72787
73019
|
maxFps.set(key, Math.max(maxFps.get(key) ?? 0, fps));
|
|
72788
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;
|
|
72789
73027
|
for (const cam of input.cameras) {
|
|
72790
73028
|
if (!charges(cam)) continue;
|
|
72791
|
-
|
|
72792
|
-
|
|
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);
|
|
72793
73032
|
if (!eligibleById.has(key)) continue;
|
|
72794
73033
|
bump(pinnedFps, key, cam.fps);
|
|
72795
73034
|
noteMax(key, cam.fps);
|
|
72796
73035
|
continue;
|
|
72797
73036
|
}
|
|
72798
|
-
|
|
72799
|
-
|
|
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;
|
|
72800
73041
|
for (const d of input.eligible) {
|
|
72801
|
-
if (d.nodeId !==
|
|
73042
|
+
if (d.nodeId !== standing || nodeWeight <= 0) continue;
|
|
72802
73043
|
const key = deviceId(d.nodeId, d.deviceKey);
|
|
72803
73044
|
const share = Math.max(d.weight, 0) / nodeWeight;
|
|
72804
73045
|
bump(alwaysOnFps, key, cam.fps * share);
|
|
@@ -72812,13 +73053,23 @@ function estimateDeviceDemand(input) {
|
|
|
72812
73053
|
const fastestOnMotion = onMotionRates.reduce((m, r) => Math.max(m, r), 0);
|
|
72813
73054
|
const nodeCount = weightByNode.size;
|
|
72814
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);
|
|
72815
73060
|
return input.eligible.map((d) => {
|
|
72816
73061
|
const key = deviceId(d.nodeId, d.deviceKey);
|
|
72817
73062
|
const peak = peakById.get(key) ?? (eligibleCountByNode.get(d.nodeId) === 1 ? peakById.get(deviceId(d.nodeId, "")) : void 0);
|
|
72818
73063
|
const alwaysOn = alwaysOnCount.get(key) ?? 0;
|
|
72819
73064
|
let onMotionSessions = 0;
|
|
72820
73065
|
let onMotionSource = "none";
|
|
72821
|
-
if (onMotionRates.length > 0
|
|
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) {
|
|
72822
73073
|
onMotionSessions = Math.max(0, Math.round(peak.peakSessions - alwaysOn));
|
|
72823
73074
|
onMotionSource = "observed-24h";
|
|
72824
73075
|
} else {
|
|
@@ -72836,14 +73087,15 @@ function estimateDeviceDemand(input) {
|
|
|
72836
73087
|
alwaysOnCameras: Math.round(alwaysOn * 100) / 100,
|
|
72837
73088
|
onMotionSessions,
|
|
72838
73089
|
onMotionSource,
|
|
72839
|
-
observedForMs: peak?.observedForMs ?? null
|
|
73090
|
+
observedForMs: input.shares !== void 0 ? clusterPeak?.observedForMs ?? null : peak?.observedForMs ?? null,
|
|
73091
|
+
placement
|
|
72840
73092
|
};
|
|
72841
73093
|
}).toSorted((a, b) => a.nodeId === b.nodeId ? a.deviceKey.localeCompare(b.deviceKey) : a.nodeId.localeCompare(b.nodeId));
|
|
72842
73094
|
}
|
|
72843
73095
|
//#endregion
|
|
72844
|
-
//#region src/pipeline/
|
|
73096
|
+
//#region src/pipeline/auto-tune/recommend.ts
|
|
72845
73097
|
/** The family the cluster runs. */
|
|
72846
|
-
var
|
|
73098
|
+
var AUTO_TUNE_FAMILY = "yolov9";
|
|
72847
73099
|
/** Recall within this of the best counts as a tie — the faster one wins. */
|
|
72848
73100
|
var RECALL_TIE = .02;
|
|
72849
73101
|
/** Default share of an accelerator's throughput kept free. */
|
|
@@ -72860,7 +73112,7 @@ function fitsOn(cell, demand, headroom) {
|
|
|
72860
73112
|
return budget >= (demand?.demandFps ?? 0) && budget >= (demand?.maxCameraFps ?? 0);
|
|
72861
73113
|
}
|
|
72862
73114
|
function candidatesFor(contexts, formatsByModel) {
|
|
72863
|
-
return Object.keys(DETECTOR_ACCURACY).filter((id) => id.startsWith(
|
|
73115
|
+
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) => ({
|
|
72864
73116
|
modelId: id,
|
|
72865
73117
|
personRecall: DETECTOR_ACCURACY[id]?.personRecall ?? 0
|
|
72866
73118
|
})).toSorted((a, b) => b.personRecall - a.personRecall || a.modelId.localeCompare(b.modelId));
|
|
@@ -73072,6 +73324,101 @@ function recommendNode(input) {
|
|
|
73072
73324
|
};
|
|
73073
73325
|
}
|
|
73074
73326
|
//#endregion
|
|
73327
|
+
//#region src/pipeline/load-balancing/share-election.ts
|
|
73328
|
+
/** Deficits equal up to float noise (0.7 × 2 − 1 is 0.3999…, not 0.4). */
|
|
73329
|
+
var DEFICIT_EPSILON = 1e-9;
|
|
73330
|
+
function byDeficit(a, b) {
|
|
73331
|
+
const diff = b.deficit - a.deficit;
|
|
73332
|
+
return (Math.abs(diff) < DEFICIT_EPSILON ? 0 : diff) || b.candidate.share - a.candidate.share || a.candidate.key.localeCompare(b.candidate.key);
|
|
73333
|
+
}
|
|
73334
|
+
function spareOf(c) {
|
|
73335
|
+
return c.spare ?? Number.POSITIVE_INFINITY;
|
|
73336
|
+
}
|
|
73337
|
+
function electByShare(candidates) {
|
|
73338
|
+
if (candidates.length === 0) return { kind: "none" };
|
|
73339
|
+
const shareSum = candidates.reduce((s, c) => s + Math.max(c.share, 0), 0);
|
|
73340
|
+
const running = candidates.reduce((s, c) => s + Math.max(c.running, 0), 0);
|
|
73341
|
+
const scored = candidates.map((candidate) => ({
|
|
73342
|
+
candidate,
|
|
73343
|
+
deficit: (shareSum > 0 ? Math.max(candidate.share, 0) / shareSum : 1 / candidates.length) * (running + 1) - candidate.running
|
|
73344
|
+
})).toSorted(byDeficit);
|
|
73345
|
+
const turn = scored[0].candidate;
|
|
73346
|
+
if (!turn.capped && !turn.saturated) return {
|
|
73347
|
+
kind: "elected",
|
|
73348
|
+
key: turn.key,
|
|
73349
|
+
reason: "share"
|
|
73350
|
+
};
|
|
73351
|
+
const free = scored.filter((s) => !s.candidate.capped && !s.candidate.saturated).toSorted((a, b) => spareOf(b.candidate) - spareOf(a.candidate) || byDeficit(a, b));
|
|
73352
|
+
const yieldReason = turn.capped ? "at-cap" : "saturated";
|
|
73353
|
+
if (free.length > 0) return {
|
|
73354
|
+
kind: "elected",
|
|
73355
|
+
key: free[0].candidate.key,
|
|
73356
|
+
reason: "yield",
|
|
73357
|
+
turnKey: turn.key,
|
|
73358
|
+
yieldReason
|
|
73359
|
+
};
|
|
73360
|
+
const uncapped = scored.find((s) => !s.candidate.capped);
|
|
73361
|
+
if (uncapped === void 0) return { kind: "none" };
|
|
73362
|
+
return {
|
|
73363
|
+
kind: "elected",
|
|
73364
|
+
key: uncapped.candidate.key,
|
|
73365
|
+
reason: "share"
|
|
73366
|
+
};
|
|
73367
|
+
}
|
|
73368
|
+
//#endregion
|
|
73369
|
+
//#region src/pipeline/load-balancing/effective-shares.ts
|
|
73370
|
+
/** Weight a node or device has when its source names none (the balancer's own default). */
|
|
73371
|
+
var DEFAULT_WEIGHT = 1;
|
|
73372
|
+
function positive(value) {
|
|
73373
|
+
return value !== void 0 && value > 0 ? value : DEFAULT_WEIGHT;
|
|
73374
|
+
}
|
|
73375
|
+
function percentages(keys, weightOf, counts) {
|
|
73376
|
+
const total = keys.reduce((sum, k) => sum + (counts(k) ? weightOf(k) : 0), 0);
|
|
73377
|
+
return new Map(keys.map((k) => [k, total > 0 && counts(k) ? Math.round(weightOf(k) / total * 1e3) / 10 : 0]));
|
|
73378
|
+
}
|
|
73379
|
+
function resolveEffectiveShares(input) {
|
|
73380
|
+
const weights = input.source === "auto" && input.auto !== null && input.auto !== null ? input.auto : input.stored;
|
|
73381
|
+
const nodeWeights = {};
|
|
73382
|
+
for (const nodeId of input.nodeIds) nodeWeights[nodeId] = positive(weights.nodes[nodeId]);
|
|
73383
|
+
const eligibleNodes = new Set(input.eligibleNodes);
|
|
73384
|
+
const configured = percentages(input.nodeIds, (k) => nodeWeights[k] ?? DEFAULT_WEIGHT, () => true);
|
|
73385
|
+
const effective = percentages(input.nodeIds, (k) => nodeWeights[k] ?? DEFAULT_WEIGHT, (k) => eligibleNodes.has(k));
|
|
73386
|
+
const deviceWeights = {};
|
|
73387
|
+
const nodes = input.nodeIds.map((nodeId) => {
|
|
73388
|
+
const eligibleKeys = new Set(input.eligibleDevices[nodeId] ?? []);
|
|
73389
|
+
const named = weights.devices[nodeId] ?? {};
|
|
73390
|
+
const keys = [...new Set([...Object.keys(named), ...eligibleKeys])].toSorted();
|
|
73391
|
+
const perDevice = {};
|
|
73392
|
+
for (const key of keys) perDevice[key] = positive(named[key]);
|
|
73393
|
+
if (keys.length > 0) deviceWeights[nodeId] = perDevice;
|
|
73394
|
+
const devConfigured = percentages(keys, (k) => perDevice[k] ?? DEFAULT_WEIGHT, () => true);
|
|
73395
|
+
const devEffective = percentages(keys, (k) => perDevice[k] ?? DEFAULT_WEIGHT, (k) => eligibleNodes.has(nodeId) && eligibleKeys.has(k));
|
|
73396
|
+
const devices = keys.map((deviceKey) => ({
|
|
73397
|
+
deviceKey,
|
|
73398
|
+
eligible: eligibleKeys.has(deviceKey),
|
|
73399
|
+
configuredPct: devConfigured.get(deviceKey) ?? 0,
|
|
73400
|
+
effectivePct: devEffective.get(deviceKey) ?? 0
|
|
73401
|
+
}));
|
|
73402
|
+
return {
|
|
73403
|
+
nodeId,
|
|
73404
|
+
eligible: eligibleNodes.has(nodeId),
|
|
73405
|
+
configuredPct: configured.get(nodeId) ?? 0,
|
|
73406
|
+
effectivePct: effective.get(nodeId) ?? 0,
|
|
73407
|
+
devices
|
|
73408
|
+
};
|
|
73409
|
+
});
|
|
73410
|
+
return {
|
|
73411
|
+
source: input.source,
|
|
73412
|
+
policy: input.policy ?? "share",
|
|
73413
|
+
autoPending: input.source === "auto" && input.auto === null,
|
|
73414
|
+
computedAt: input.computedAt ?? null,
|
|
73415
|
+
trigger: input.trigger ?? null,
|
|
73416
|
+
nodes,
|
|
73417
|
+
nodeWeights,
|
|
73418
|
+
deviceWeights
|
|
73419
|
+
};
|
|
73420
|
+
}
|
|
73421
|
+
//#endregion
|
|
73075
73422
|
//#region src/pipeline/root-face-crop.ts
|
|
73076
73423
|
/** Side of the square, as a multiple of the face box's longer side. */
|
|
73077
73424
|
var ROOT_FACE_REFINE_SCALE = 1.6;
|
|
@@ -75216,6 +75563,8 @@ exports.AUDIO_PRESETS = require_composition.AUDIO_PRESETS;
|
|
|
75216
75563
|
exports.AUDIO_SCALE_EPOCH_ISO = AUDIO_SCALE_EPOCH_ISO;
|
|
75217
75564
|
exports.AUDIO_SCALE_EPOCH_MS = AUDIO_SCALE_EPOCH_MS;
|
|
75218
75565
|
exports.AUTOMATIC_HUB_ADDRESS_FLAGS = AUTOMATIC_HUB_ADDRESS_FLAGS;
|
|
75566
|
+
exports.AUTO_SHARE_HEADROOM = AUTO_SHARE_HEADROOM;
|
|
75567
|
+
exports.AUTO_TUNE_FAMILY = AUTO_TUNE_FAMILY;
|
|
75219
75568
|
exports.AcceleratorKindSchema = AcceleratorKindSchema;
|
|
75220
75569
|
exports.AccessoriesStatusSchema = AccessoriesStatusSchema;
|
|
75221
75570
|
exports.AccessoryKind = AccessoryKind;
|
|
@@ -75283,6 +75632,12 @@ exports.AudioMetricsSnapshotSchema = AudioMetricsSnapshotSchema;
|
|
|
75283
75632
|
exports.AudioPcmChunkSchema = AudioPcmChunkSchema;
|
|
75284
75633
|
exports.AudioStreamPickSchema = require_sleep.AudioStreamPickSchema;
|
|
75285
75634
|
exports.AuthResultSchema = AuthResultSchema;
|
|
75635
|
+
exports.AutoTuneApplyInputSchema = AutoTuneApplyInputSchema;
|
|
75636
|
+
exports.AutoTuneApplyResultSchema = AutoTuneApplyResultSchema;
|
|
75637
|
+
exports.AutoTuneOptionsSchema = AutoTuneOptionsSchema;
|
|
75638
|
+
exports.AutoTunePhaseResultSchema = AutoTunePhaseResultSchema;
|
|
75639
|
+
exports.AutoTunePlanSchema = AutoTunePlanSchema;
|
|
75640
|
+
exports.AutoTuneWarningSchema = AutoTuneWarningSchema;
|
|
75286
75641
|
exports.AutoUpdateSettingsSchema = AutoUpdateSettingsSchema;
|
|
75287
75642
|
exports.AutomationActionSchema = AutomationActionSchema;
|
|
75288
75643
|
exports.AutomationConditionOperatorSchema = AutomationConditionOperatorSchema;
|
|
@@ -75295,7 +75650,6 @@ exports.BASE_DEVICE_CAPS = BASE_DEVICE_CAPS;
|
|
|
75295
75650
|
exports.BASE_LIVE_EGRESS_PROFILE = BASE_LIVE_EGRESS_PROFILE;
|
|
75296
75651
|
exports.BATTERY_DEVICE_PROFILE = BATTERY_DEVICE_PROFILE;
|
|
75297
75652
|
exports.BATTERY_UNREACHABLE_AFTER_MS = BATTERY_UNREACHABLE_AFTER_MS;
|
|
75298
|
-
exports.BEST_SETTINGS_FAMILY = BEST_SETTINGS_FAMILY;
|
|
75299
75653
|
exports.BIRTH_DECISION_DEFAULT_LIMIT = BIRTH_DECISION_DEFAULT_LIMIT;
|
|
75300
75654
|
exports.BOOT_RECOVERY_BACKOFF_MS = require_sleep.BOOT_RECOVERY_BACKOFF_MS;
|
|
75301
75655
|
exports.BUILTIN_RESULT_KINDS = BUILTIN_RESULT_KINDS;
|
|
@@ -75311,12 +75665,6 @@ exports.BaseAddon = require_sleep.BaseAddon;
|
|
|
75311
75665
|
exports.BaseDevice = BaseDevice;
|
|
75312
75666
|
exports.BaseDeviceProvider = BaseDeviceProvider;
|
|
75313
75667
|
exports.BatteryStatusSchema = BatteryStatusSchema;
|
|
75314
|
-
exports.BestSettingsApplyInputSchema = BestSettingsApplyInputSchema;
|
|
75315
|
-
exports.BestSettingsApplyResultSchema = BestSettingsApplyResultSchema;
|
|
75316
|
-
exports.BestSettingsOptionsSchema = BestSettingsOptionsSchema;
|
|
75317
|
-
exports.BestSettingsPhaseResultSchema = BestSettingsPhaseResultSchema;
|
|
75318
|
-
exports.BestSettingsPlanSchema = BestSettingsPlanSchema;
|
|
75319
|
-
exports.BestSettingsWarningSchema = BestSettingsWarningSchema;
|
|
75320
75668
|
exports.BinaryStatusSchema = BinaryStatusSchema;
|
|
75321
75669
|
exports.BirthDecisionQueryInputSchema = BirthDecisionQueryInputSchema;
|
|
75322
75670
|
exports.BirthDecisionRecordSchema = BirthDecisionRecordSchema;
|
|
@@ -75591,6 +75939,8 @@ exports.DEFAULT_POOL_MEMORY_POLICY = DEFAULT_POOL_MEMORY_POLICY;
|
|
|
75591
75939
|
exports.DEFAULT_RECORDING_PROFILES = DEFAULT_RECORDING_PROFILES;
|
|
75592
75940
|
exports.DEFAULT_RETENTION = DEFAULT_RETENTION;
|
|
75593
75941
|
exports.DEFAULT_RUNTIME_STATE_DURABILITY = require_sleep.DEFAULT_RUNTIME_STATE_DURABILITY;
|
|
75942
|
+
exports.DEFAULT_SESSION_PLACEMENT_POLICY = DEFAULT_SESSION_PLACEMENT_POLICY;
|
|
75943
|
+
exports.DEFAULT_SHARE_SOURCE = DEFAULT_SHARE_SOURCE;
|
|
75594
75944
|
exports.DEFAULT_TIMELAPSE_PREVIEW_TEXT = DEFAULT_TIMELAPSE_PREVIEW_TEXT;
|
|
75595
75945
|
exports.DEFAULT_TOKEN_EXPIRY = DEFAULT_TOKEN_EXPIRY;
|
|
75596
75946
|
exports.DERIVED_CAMERA_SILENCED_CAP_NAMES = DERIVED_CAMERA_SILENCED_CAP_NAMES;
|
|
@@ -75692,6 +76042,9 @@ exports.EXTENSION_SLOTS = EXTENSION_SLOTS;
|
|
|
75692
76042
|
exports.EXTENSION_SLOT_IDS = EXTENSION_SLOT_IDS;
|
|
75693
76043
|
exports.EXTENSION_SLOT_LISTING_METHOD = EXTENSION_SLOT_LISTING_METHOD;
|
|
75694
76044
|
exports.EXTENSION_SLOT_REF_SEPARATOR = EXTENSION_SLOT_REF_SEPARATOR;
|
|
76045
|
+
exports.EffectiveDeviceShareSchema = EffectiveDeviceShareSchema;
|
|
76046
|
+
exports.EffectiveNodeShareSchema = EffectiveNodeShareSchema;
|
|
76047
|
+
exports.EffectiveSharesSchema = EffectiveSharesSchema;
|
|
75695
76048
|
exports.EffectiveTuningSchema = EffectiveTuningSchema;
|
|
75696
76049
|
exports.EgressEncodeSchema = EgressEncodeSchema;
|
|
75697
76050
|
exports.EgressRateControlSchema = EgressRateControlSchema;
|
|
@@ -75887,6 +76240,7 @@ exports.LlmRuntimeStatusSchema = LlmRuntimeStatusSchema;
|
|
|
75887
76240
|
exports.LlmTimeoutDefaults = LlmTimeoutDefaults;
|
|
75888
76241
|
exports.LlmUsageRollupSchema = LlmUsageRollupSchema;
|
|
75889
76242
|
exports.LlmUsageSchema = LlmUsageSchema;
|
|
76243
|
+
exports.LoadBalancingSharesInputSchema = LoadBalancingSharesInputSchema;
|
|
75890
76244
|
exports.LoadContributionSchema = LoadContributionSchema;
|
|
75891
76245
|
exports.LocateSegmentResultSchema = LocateSegmentResultSchema;
|
|
75892
76246
|
exports.LocationDescriptionAssignmentSchema = LocationDescriptionAssignmentSchema;
|
|
@@ -76319,6 +76673,10 @@ exports.PipelineStepInputSchema = PipelineStepInputSchema;
|
|
|
76319
76673
|
exports.PipelineValidationIssueSchema = PipelineValidationIssueSchema;
|
|
76320
76674
|
exports.PipelineValidationResultSchema = PipelineValidationResultSchema;
|
|
76321
76675
|
exports.PlaceholderReasonSchema = PlaceholderReasonSchema;
|
|
76676
|
+
exports.PlacementDeviceStatsSchema = PlacementDeviceStatsSchema;
|
|
76677
|
+
exports.PlacementNodeStatsSchema = PlacementNodeStatsSchema;
|
|
76678
|
+
exports.PlacementStatsInputSchema = PlacementStatsInputSchema;
|
|
76679
|
+
exports.PlacementStatsSchema = PlacementStatsSchema;
|
|
76322
76680
|
exports.PolygonPointSchema = PolygonPointSchema;
|
|
76323
76681
|
exports.PoolMemoryWatchdog = PoolMemoryWatchdog;
|
|
76324
76682
|
exports.PowerMeterStatusSchema = PowerMeterStatusSchema;
|
|
@@ -76481,6 +76839,8 @@ exports.SCENE_RESET_RECAPTURES = SCENE_RESET_RECAPTURES;
|
|
|
76481
76839
|
exports.SCOPE_PRESETS = SCOPE_PRESETS;
|
|
76482
76840
|
exports.SENSOR_FEATURES = SENSOR_FEATURES;
|
|
76483
76841
|
exports.SENSOR_MAP = SENSOR_MAP;
|
|
76842
|
+
exports.SESSION_PLACEMENT_SETTING_KEY = SESSION_PLACEMENT_SETTING_KEY;
|
|
76843
|
+
exports.SHARE_SOURCE_SETTING_KEY = SHARE_SOURCE_SETTING_KEY;
|
|
76484
76844
|
exports.SHARE_VIEW_KINDS = require_sleep.SHARE_VIEW_KINDS;
|
|
76485
76845
|
exports.SINGLE_HUB_ADDRESS_ROLES = SINGLE_HUB_ADDRESS_ROLES;
|
|
76486
76846
|
exports.SOURCE_CAPS = require_composition.SOURCE_CAPS;
|
|
@@ -76526,9 +76886,11 @@ exports.ServerUpdateActionResultSchema = ServerUpdateActionResultSchema;
|
|
|
76526
76886
|
exports.ServerUpdateCheckResultSchema = ServerUpdateCheckResultSchema;
|
|
76527
76887
|
exports.ServerUpdateOutcomeSchema = ServerUpdateOutcomeSchema;
|
|
76528
76888
|
exports.ServerUpdateStateSchema = ServerUpdateStateSchema;
|
|
76889
|
+
exports.SessionPlacementPolicySchema = SessionPlacementPolicySchema;
|
|
76529
76890
|
exports.SessionTriggerSchema = SessionTriggerSchema;
|
|
76530
76891
|
exports.SetCameraSensorsInputSchema = SetCameraSensorsInputSchema;
|
|
76531
76892
|
exports.SetLoggingSettingsInputSchema = SetLoggingSettingsInputSchema;
|
|
76893
|
+
exports.SetShareSourceInputSchema = SetShareSourceInputSchema;
|
|
76532
76894
|
exports.SetSiteLocationInputSchema = SetSiteLocationInputSchema;
|
|
76533
76895
|
exports.SetTrackPurityInputSchema = SetTrackPurityInputSchema;
|
|
76534
76896
|
exports.SetTrackPurityResultSchema = SetTrackPurityResultSchema;
|
|
@@ -76537,6 +76899,8 @@ exports.SettingsPatchSchema = SettingsPatchSchema;
|
|
|
76537
76899
|
exports.SettingsRecordSchema = SettingsRecordSchema;
|
|
76538
76900
|
exports.SettingsSchemaWithValuesSchema = SettingsSchemaWithValuesSchema;
|
|
76539
76901
|
exports.SettingsUpdateResultSchema = SettingsUpdateResultSchema;
|
|
76902
|
+
exports.ShareSourceSchema = ShareSourceSchema;
|
|
76903
|
+
exports.ShareWeightsSchema = ShareWeightsSchema;
|
|
76540
76904
|
exports.ShmRingStatsSchema = ShmRingStatsSchema;
|
|
76541
76905
|
exports.SiteLocationSchema = SiteLocationSchema;
|
|
76542
76906
|
exports.SiteLocationSourceSchema = SiteLocationSourceSchema;
|
|
@@ -76548,6 +76912,7 @@ exports.SnapshotImageSchema = SnapshotImageSchema;
|
|
|
76548
76912
|
exports.SourceInfoSchema = SourceInfoSchema;
|
|
76549
76913
|
exports.SpatialDetectionSchema = SpatialDetectionSchema;
|
|
76550
76914
|
exports.SsoBridgeClaimsSchema = SsoBridgeClaimsSchema;
|
|
76915
|
+
exports.StaleDevicePinSchema = StaleDevicePinSchema;
|
|
76551
76916
|
exports.StartEmbeddedInputSchema = StartEmbeddedInputSchema;
|
|
76552
76917
|
exports.StationaryObjectSchema = StationaryObjectSchema;
|
|
76553
76918
|
exports.StorageAbortUploadInputSchema = AbortUploadInputSchema;
|
|
@@ -76611,6 +76976,10 @@ exports.SubscribeAudioChunksInputSchema = require_sleep.SubscribeAudioChunksInpu
|
|
|
76611
76976
|
exports.SubscribeAudioChunksResultSchema = require_sleep.SubscribeAudioChunksResultSchema;
|
|
76612
76977
|
exports.SubscribeFramesInputSchema = require_sleep.SubscribeFramesInputSchema;
|
|
76613
76978
|
exports.SubscribeFramesResultSchema = require_sleep.SubscribeFramesResultSchema;
|
|
76979
|
+
exports.SuggestSharesInputSchema = SuggestSharesInputSchema;
|
|
76980
|
+
exports.SuggestSharesResultSchema = SuggestSharesResultSchema;
|
|
76981
|
+
exports.SuggestedDeviceShareSchema = SuggestedDeviceShareSchema;
|
|
76982
|
+
exports.SuggestedNodeShareSchema = SuggestedNodeShareSchema;
|
|
76614
76983
|
exports.SuppliedRootOutputSchema = SuppliedRootOutputSchema;
|
|
76615
76984
|
exports.SwitchStatusSchema = SwitchStatusSchema;
|
|
76616
76985
|
exports.SystemMetricsSchema = SystemMetricsSchema;
|
|
@@ -76966,6 +77335,7 @@ exports.doorbellFeatureSources = doorbellFeatureSources;
|
|
|
76966
77335
|
exports.droppedConditionsForKind = droppedConditionsForKind;
|
|
76967
77336
|
exports.egressTranscodeSharingKey = egressTranscodeSharingKey;
|
|
76968
77337
|
exports.egressTransportFromRequest = egressTransportFromRequest;
|
|
77338
|
+
exports.electByShare = electByShare;
|
|
76969
77339
|
exports.embeddingEncoderCapability = embeddingEncoderCapability;
|
|
76970
77340
|
exports.embeddingModelFailedError = embeddingModelFailedError;
|
|
76971
77341
|
exports.embeddingModelFailedOf = embeddingModelFailedOf;
|
|
@@ -77216,6 +77586,8 @@ exports.parseOccupancyScope = parseOccupancyScope;
|
|
|
77216
77586
|
exports.parseProcStatus = parseProcStatus;
|
|
77217
77587
|
exports.parseProfileBrokerId = require_sleep.parseProfileBrokerId;
|
|
77218
77588
|
exports.parseRuleSection = parseRuleSection;
|
|
77589
|
+
exports.parseSessionPlacementPolicy = parseSessionPlacementPolicy;
|
|
77590
|
+
exports.parseShareSource = parseShareSource;
|
|
77219
77591
|
exports.parseStreamParamsFormPatch = parseStreamParamsFormPatch;
|
|
77220
77592
|
exports.patchAudio = patchAudio;
|
|
77221
77593
|
exports.petFeederCapability = petFeederCapability;
|
|
@@ -77296,6 +77668,7 @@ exports.resolveCoreBlockFiles = resolveCoreBlockFiles;
|
|
|
77296
77668
|
exports.resolveCreateExportSubject = resolveCreateExportSubject;
|
|
77297
77669
|
exports.resolveDeviceControlKind = resolveDeviceControlKind;
|
|
77298
77670
|
exports.resolveDeviceProfile = resolveDeviceProfile;
|
|
77671
|
+
exports.resolveEffectiveShares = resolveEffectiveShares;
|
|
77299
77672
|
exports.resolveEgressDecodeHwAccel = resolveEgressDecodeHwAccel;
|
|
77300
77673
|
exports.resolveExportProfiles = resolveExportProfiles;
|
|
77301
77674
|
exports.resolveFormat = resolveFormat;
|