@camstack/ui-library 1.2.234 → 1.2.236
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/composites/adaptive-downlink.d.ts +33 -1
- package/dist/composites/agent-step-editor.d.ts +6 -0
- package/dist/composites/camera-stream-player.d.ts +10 -2
- package/dist/composites/index.d.ts +3 -1
- package/dist/composites/pipeline-matrix-shared.d.ts +5 -5
- package/dist/composites/root-model-source.d.ts +19 -0
- package/dist/composites/stream-panel.d.ts +4 -1
- package/dist/generated/system-hooks.d.ts +12 -0
- package/dist/hooks/use-device-webrtc.d.ts +17 -0
- package/dist/index.cjs +236 -16
- package/dist/index.js +231 -18
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7388,6 +7388,16 @@ var useLocalNetworkSetNotificationEndpoint = trpc.localNetwork.setNotificationEn
|
|
|
7388
7388
|
var useLocalNetworkGetViewerEndpoints = trpc.localNetwork.getViewerEndpoints.useQuery;
|
|
7389
7389
|
/** Generated alias around `trpc.localNetwork.setViewerEndpoints.useMutation`. */
|
|
7390
7390
|
var useLocalNetworkSetViewerEndpoints = trpc.localNetwork.setViewerEndpoints.useMutation;
|
|
7391
|
+
/** Generated alias around `trpc.localNetwork.getAddresses.useQuery`. */
|
|
7392
|
+
var useLocalNetworkGetAddresses = trpc.localNetwork.getAddresses.useQuery;
|
|
7393
|
+
/** Generated alias around `trpc.localNetwork.addCustomAddress.useMutation`. */
|
|
7394
|
+
var useLocalNetworkAddCustomAddress = trpc.localNetwork.addCustomAddress.useMutation;
|
|
7395
|
+
/** Generated alias around `trpc.localNetwork.removeCustomAddress.useMutation`. */
|
|
7396
|
+
var useLocalNetworkRemoveCustomAddress = trpc.localNetwork.removeCustomAddress.useMutation;
|
|
7397
|
+
/** Generated alias around `trpc.localNetwork.setAddressRole.useMutation`. */
|
|
7398
|
+
var useLocalNetworkSetAddressRole = trpc.localNetwork.setAddressRole.useMutation;
|
|
7399
|
+
/** Generated alias around `trpc.localNetwork.getHubAddresses.useQuery`. */
|
|
7400
|
+
var useLocalNetworkGetHubAddresses = trpc.localNetwork.getHubAddresses.useQuery;
|
|
7391
7401
|
/** Generated alias around `trpc.localNetwork.getAllowedAddresses.useQuery`. */
|
|
7392
7402
|
var useLocalNetworkGetAllowedAddresses = trpc.localNetwork.getAllowedAddresses.useQuery;
|
|
7393
7403
|
/** Generated alias around `trpc.localNetwork.setAllowedAddresses.useMutation`. */
|
|
@@ -8716,6 +8726,8 @@ var useWebrtcSessionCloseSession = trpc.webrtcSession.closeSession.useMutation;
|
|
|
8716
8726
|
var useWebrtcSessionHasAdaptiveBitrate = trpc.webrtcSession.hasAdaptiveBitrate.useQuery;
|
|
8717
8727
|
/** Generated alias around `trpc.webrtcSession.getSessionState.useQuery`. */
|
|
8718
8728
|
var useWebrtcSessionGetSessionState = trpc.webrtcSession.getSessionState.useQuery;
|
|
8729
|
+
/** Generated alias around `trpc.webrtcSession.applyDownlinkProbe.useMutation`. */
|
|
8730
|
+
var useWebrtcSessionApplyDownlinkProbe = trpc.webrtcSession.applyDownlinkProbe.useMutation;
|
|
8719
8731
|
/** Generated alias around `trpc.webrtcSession.getSessionDebug.useQuery`. */
|
|
8720
8732
|
var useWebrtcSessionGetSessionDebug = trpc.webrtcSession.getSessionDebug.useQuery;
|
|
8721
8733
|
/** Generated alias around `trpc.zoneAnalytics.getCurrentSnapshot.useQuery`. */
|
|
@@ -29358,6 +29370,89 @@ function resolveEffectiveStepModel(input) {
|
|
|
29358
29370
|
return input.override ?? input.base ?? resolveEffectiveDefaultModel(input.catalog, input.device);
|
|
29359
29371
|
}
|
|
29360
29372
|
//#endregion
|
|
29373
|
+
//#region src/composites/root-model-source.tsx
|
|
29374
|
+
/**
|
|
29375
|
+
* "Use the root model" — the step editor's control for a step the camera's
|
|
29376
|
+
* ROOT detection model can supply (D730).
|
|
29377
|
+
*
|
|
29378
|
+
* The flag (`useRootModel`, in the step's own settings) is an operator INTENT
|
|
29379
|
+
* kept beside the step's model: checking it never changes the model, and a
|
|
29380
|
+
* root that cannot supply the step leaves the step running its own model while
|
|
29381
|
+
* the flag waits, inactive, for a root that can. Whether it is in force is
|
|
29382
|
+
* `resolveRootSupply` — the same function the runner decides with.
|
|
29383
|
+
*/
|
|
29384
|
+
/** The editor's view of the flag for one step, or `null` for a step no root can supply. */
|
|
29385
|
+
function rootSourceState(stepId, settings, rootModel) {
|
|
29386
|
+
if (!(0, _camstack_types.isRootSuppliableStepId)(stepId)) return null;
|
|
29387
|
+
return (0, _camstack_types.resolveRootSupply)(stepId, settings, rootModel?.supplies);
|
|
29388
|
+
}
|
|
29389
|
+
/** The settings bag with the flag set — every other key untouched. */
|
|
29390
|
+
function withUseRootModel(settings, value) {
|
|
29391
|
+
return {
|
|
29392
|
+
...settings,
|
|
29393
|
+
[_camstack_types.USE_ROOT_MODEL_SETTING_KEY]: value
|
|
29394
|
+
};
|
|
29395
|
+
}
|
|
29396
|
+
/** What the operator must know about a supply, beyond "it is on". */
|
|
29397
|
+
function supplyNotes(supply) {
|
|
29398
|
+
if (supply.kind === "label") {
|
|
29399
|
+
const notes = supply.uncovered.length > 0 ? [`Not produced by this model: ${supply.uncovered.join(", ")}.`] : [];
|
|
29400
|
+
if (supply.stepId === "package-detection") return [...notes, "The root model's own package boxes become the package result at this step's threshold; this step's zone-crop view is not used, so small parcels the full-frame model misses stay missed."];
|
|
29401
|
+
return [...notes, "This step's class list decides which of the root's labels become the fine class; a switched-off class stays at its macro."];
|
|
29402
|
+
}
|
|
29403
|
+
if (supply.stepId === "face-detection") return ["Face boxes come from the root model. Each is re-found by this step's face detector in a square around it before recognition, so only a face it finds is recognised; a box with no face in it is dropped."];
|
|
29404
|
+
return ["Plate boxes come from the root model and the plate reader reads them. The crop margin around a root plate box has not been measured for this model yet."];
|
|
29405
|
+
}
|
|
29406
|
+
/** The reason an intended supply is not in force, in the operator's words. */
|
|
29407
|
+
function inactiveText(state, rootModel) {
|
|
29408
|
+
switch (state.inactiveReason) {
|
|
29409
|
+
case "root-input-too-small": return `the current root model (${rootModel.name}) sees the frame too small to find faces reliably (it needs an input of 640 px or more).`;
|
|
29410
|
+
case "root-does-not-declare":
|
|
29411
|
+
case void 0: return `the current root model (${rootModel.name}) cannot supply this.`;
|
|
29412
|
+
}
|
|
29413
|
+
}
|
|
29414
|
+
function RootModelSourceControl({ stepId, settings, rootModel, disabled, onChange }) {
|
|
29415
|
+
if (rootModel === void 0) return null;
|
|
29416
|
+
const state = rootSourceState(stepId, settings, rootModel);
|
|
29417
|
+
if (state === null) return null;
|
|
29418
|
+
const inactiveNote = state.inactive ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
29419
|
+
className: "rounded bg-muted/40 px-3 py-2 text-[11px] text-foreground-subtle",
|
|
29420
|
+
"data-testid": "root-model-inactive",
|
|
29421
|
+
children: [
|
|
29422
|
+
"Use the root model: inactive — ",
|
|
29423
|
+
inactiveText(state, rootModel),
|
|
29424
|
+
" The step runs its own model."
|
|
29425
|
+
]
|
|
29426
|
+
}) : null;
|
|
29427
|
+
if (state.supply === void 0) return inactiveNote;
|
|
29428
|
+
const checked = state.intent;
|
|
29429
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
29430
|
+
className: "space-y-1",
|
|
29431
|
+
"data-testid": "root-model-source",
|
|
29432
|
+
children: [
|
|
29433
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
29434
|
+
className: "flex items-center gap-2 text-xs text-foreground",
|
|
29435
|
+
children: [
|
|
29436
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
29437
|
+
type: "checkbox",
|
|
29438
|
+
checked,
|
|
29439
|
+
disabled,
|
|
29440
|
+
onChange: (e) => onChange(e.target.checked)
|
|
29441
|
+
}),
|
|
29442
|
+
"Use the root model (",
|
|
29443
|
+
rootModel.name,
|
|
29444
|
+
")"
|
|
29445
|
+
]
|
|
29446
|
+
}),
|
|
29447
|
+
inactiveNote,
|
|
29448
|
+
state.effective && supplyNotes(state.supply).map((note) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
29449
|
+
className: "text-[10px] leading-snug text-foreground-subtle",
|
|
29450
|
+
children: note
|
|
29451
|
+
}, note))
|
|
29452
|
+
]
|
|
29453
|
+
});
|
|
29454
|
+
}
|
|
29455
|
+
//#endregion
|
|
29361
29456
|
//#region src/composites/agent-step-editor.tsx
|
|
29362
29457
|
/**
|
|
29363
29458
|
* Per-(node,device) and per-camera editors must not surface knobs that the
|
|
@@ -29389,6 +29484,25 @@ function buildDisplayStep(addon, cfg) {
|
|
|
29389
29484
|
settings: { ...cfg.settings }
|
|
29390
29485
|
};
|
|
29391
29486
|
}
|
|
29487
|
+
/**
|
|
29488
|
+
* Shown in place of the model picker while the root model supplies the step:
|
|
29489
|
+
* the step's own model is kept, not changed, for when the root cannot.
|
|
29490
|
+
*/
|
|
29491
|
+
function RootSuppliedModelNote({ rootModel, stepModelId }) {
|
|
29492
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
29493
|
+
className: "rounded bg-primary/10 px-3 py-2 text-[11px] text-foreground-subtle",
|
|
29494
|
+
"data-testid": "root-supplied-model",
|
|
29495
|
+
children: [
|
|
29496
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
29497
|
+
className: "font-semibold text-foreground",
|
|
29498
|
+
children: ["Model: ", rootModel.name]
|
|
29499
|
+
}),
|
|
29500
|
+
" (the root model). This step's own model",
|
|
29501
|
+
stepModelId !== void 0 ? ` (${stepModelId})` : "",
|
|
29502
|
+
" is kept and runs again whenever the root model cannot supply the step."
|
|
29503
|
+
]
|
|
29504
|
+
});
|
|
29505
|
+
}
|
|
29392
29506
|
function computeEffective(mode, agentDefault, patch) {
|
|
29393
29507
|
if (mode !== "device" || !patch) return agentDefault;
|
|
29394
29508
|
return {
|
|
@@ -29397,7 +29511,7 @@ function computeEffective(mode, agentDefault, patch) {
|
|
|
29397
29511
|
settings: patch.settings ?? agentDefault.settings
|
|
29398
29512
|
};
|
|
29399
29513
|
}
|
|
29400
|
-
function AgentModeEditor({ addon, agentDefault, modelsForFormat, engineFormat, effectiveModelId, onChangeAgentConfig }) {
|
|
29514
|
+
function AgentModeEditor({ addon, agentDefault, modelsForFormat, engineFormat, effectiveModelId, rootModel, onChangeAgentConfig }) {
|
|
29401
29515
|
const update = (patch) => {
|
|
29402
29516
|
onChangeAgentConfig?.({
|
|
29403
29517
|
...agentDefault,
|
|
@@ -29406,10 +29520,20 @@ function AgentModeEditor({ addon, agentDefault, modelsForFormat, engineFormat, e
|
|
|
29406
29520
|
};
|
|
29407
29521
|
const localSchema = nodeLocalConfigSchema(addon);
|
|
29408
29522
|
const formatDefault = addon.defaultModelIdByFormat?.[engineFormat] ?? addon.defaultModelId;
|
|
29523
|
+
const rootSupplied = rootSourceState(addon.id, agentDefault.settings, rootModel)?.effective === true;
|
|
29409
29524
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
29410
29525
|
className: "space-y-4 text-xs",
|
|
29411
29526
|
children: [
|
|
29412
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
29527
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RootModelSourceControl, {
|
|
29528
|
+
stepId: addon.id,
|
|
29529
|
+
settings: agentDefault.settings,
|
|
29530
|
+
rootModel,
|
|
29531
|
+
onChange: (v) => update({ settings: withUseRootModel(agentDefault.settings, v) })
|
|
29532
|
+
}),
|
|
29533
|
+
rootSupplied && rootModel !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RootSuppliedModelNote, {
|
|
29534
|
+
rootModel,
|
|
29535
|
+
stepModelId: agentDefault.modelId ?? effectiveModelId
|
|
29536
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
29413
29537
|
className: "text-[10px] uppercase tracking-widest text-foreground-subtle mb-1",
|
|
29414
29538
|
children: "Model"
|
|
29415
29539
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelPicker, {
|
|
@@ -29435,7 +29559,7 @@ function AgentModeEditor({ addon, agentDefault, modelsForFormat, engineFormat, e
|
|
|
29435
29559
|
]
|
|
29436
29560
|
});
|
|
29437
29561
|
}
|
|
29438
|
-
function DeviceModeEditor({ addon, agentDefault, agentNodeId, currentPatch, modelsForFormat, engineFormat, effectiveModelId, onChangePatch }) {
|
|
29562
|
+
function DeviceModeEditor({ addon, agentDefault, agentNodeId, currentPatch, modelsForFormat, engineFormat, effectiveModelId, rootModel, onChangePatch }) {
|
|
29439
29563
|
const effective = computeEffective("device", agentDefault, currentPatch);
|
|
29440
29564
|
const inheritedModelId = agentDefault.modelId ?? effectiveModelId;
|
|
29441
29565
|
const formatDefault = addon.defaultModelIdByFormat?.[engineFormat] ?? addon.defaultModelId;
|
|
@@ -29473,7 +29597,16 @@ function DeviceModeEditor({ addon, agentDefault, agentNodeId, currentPatch, mode
|
|
|
29473
29597
|
" — model + settings only. Whether this camera runs the step is set by its per-camera gate above."
|
|
29474
29598
|
]
|
|
29475
29599
|
}),
|
|
29476
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
29600
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RootModelSourceControl, {
|
|
29601
|
+
stepId: addon.id,
|
|
29602
|
+
settings: effective.settings,
|
|
29603
|
+
rootModel,
|
|
29604
|
+
onChange: (v) => setSettings(withUseRootModel(effective.settings, v))
|
|
29605
|
+
}),
|
|
29606
|
+
rootSourceState(addon.id, effective.settings, rootModel)?.effective === true && rootModel !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RootSuppliedModelNote, {
|
|
29607
|
+
rootModel,
|
|
29608
|
+
stepModelId: effective.modelId ?? inheritedModelId
|
|
29609
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
29477
29610
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
29478
29611
|
className: "flex items-center justify-between mb-1",
|
|
29479
29612
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -29558,7 +29691,7 @@ function DeviceModeEditor({ addon, agentDefault, agentNodeId, currentPatch, mode
|
|
|
29558
29691
|
});
|
|
29559
29692
|
}
|
|
29560
29693
|
function AgentStepEditor(props) {
|
|
29561
|
-
const { mode, addon, agentDefault, agentNodeId, currentPatch, onChangeAgentConfig, onChangePatch, engineFormat, effectiveModelId } = props;
|
|
29694
|
+
const { mode, addon, agentDefault, agentNodeId, currentPatch, onChangeAgentConfig, onChangePatch, engineFormat, effectiveModelId, rootModel } = props;
|
|
29562
29695
|
const modelsForFormat = (0, react$1.useMemo)(() => stepModelOptions(addon.models, engineFormat), [addon.models, engineFormat]);
|
|
29563
29696
|
if (mode === "agent") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AgentModeEditor, {
|
|
29564
29697
|
addon,
|
|
@@ -29566,6 +29699,7 @@ function AgentStepEditor(props) {
|
|
|
29566
29699
|
modelsForFormat,
|
|
29567
29700
|
engineFormat,
|
|
29568
29701
|
effectiveModelId,
|
|
29702
|
+
...rootModel !== void 0 ? { rootModel } : {},
|
|
29569
29703
|
onChangeAgentConfig
|
|
29570
29704
|
});
|
|
29571
29705
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceModeEditor, {
|
|
@@ -29576,6 +29710,7 @@ function AgentStepEditor(props) {
|
|
|
29576
29710
|
modelsForFormat,
|
|
29577
29711
|
engineFormat,
|
|
29578
29712
|
effectiveModelId,
|
|
29713
|
+
...rootModel !== void 0 ? { rootModel } : {},
|
|
29579
29714
|
onChangePatch
|
|
29580
29715
|
});
|
|
29581
29716
|
}
|
|
@@ -31088,7 +31223,8 @@ function adaptiveHintsKey(report) {
|
|
|
31088
31223
|
rung,
|
|
31089
31224
|
report.prefersTier ?? "-",
|
|
31090
31225
|
report.probeOrigin ?? "unreachable",
|
|
31091
|
-
report.probeStatus ?? "-"
|
|
31226
|
+
report.probeStatus ?? "-",
|
|
31227
|
+
report.probeAnswer ?? "-"
|
|
31092
31228
|
].join("|");
|
|
31093
31229
|
}
|
|
31094
31230
|
function mbpsOf(bytes, elapsedMs) {
|
|
@@ -31203,6 +31339,38 @@ function createDownlinkProbe(deps) {
|
|
|
31203
31339
|
}
|
|
31204
31340
|
};
|
|
31205
31341
|
}
|
|
31342
|
+
/**
|
|
31343
|
+
* Hand a probe to the session it was measured on (D733).
|
|
31344
|
+
*
|
|
31345
|
+
* The probe climb used to be a SECOND session: a make-before-break reconnect
|
|
31346
|
+
* carrying `downlinkMbps`, so every adaptive live open cost two sessions. The
|
|
31347
|
+
* hub now moves the open session to the probed rung itself. `answered` means
|
|
31348
|
+
* the hub owns the climb, WHATEVER it answered — `held` included: a reconnect
|
|
31349
|
+
* after a `held` would buy the second session for a rung the hub just refused.
|
|
31350
|
+
* Only `unsupported` (no host wiring, no session id yet, or a hub that does not
|
|
31351
|
+
* know the method) leaves the caller its legacy reconnect climb.
|
|
31352
|
+
*/
|
|
31353
|
+
async function handProbeToSession(apply, sessionId, downlinkMbps) {
|
|
31354
|
+
if (apply === void 0) return {
|
|
31355
|
+
kind: "unsupported",
|
|
31356
|
+
why: "no-wiring"
|
|
31357
|
+
};
|
|
31358
|
+
if (sessionId === null) return {
|
|
31359
|
+
kind: "unsupported",
|
|
31360
|
+
why: "no-session"
|
|
31361
|
+
};
|
|
31362
|
+
try {
|
|
31363
|
+
return {
|
|
31364
|
+
kind: "answered",
|
|
31365
|
+
answer: await apply(sessionId, downlinkMbps)
|
|
31366
|
+
};
|
|
31367
|
+
} catch {
|
|
31368
|
+
return {
|
|
31369
|
+
kind: "unsupported",
|
|
31370
|
+
why: "call-failed"
|
|
31371
|
+
};
|
|
31372
|
+
}
|
|
31373
|
+
}
|
|
31206
31374
|
//#endregion
|
|
31207
31375
|
//#region src/composites/client-network-sample.ts
|
|
31208
31376
|
/** Schema bound of `estimatedBandwidthKbps` / `packetLossPercent`. */
|
|
@@ -31958,7 +32126,7 @@ function mergePlayerHints(autoHints, override, downlinkMbps, coldStart) {
|
|
|
31958
32126
|
return coldStart ? stripDownlinkForColdStart(merged) : merged;
|
|
31959
32127
|
}
|
|
31960
32128
|
var FIRST_FRAME_TIMEOUT_MS = 8e3;
|
|
31961
|
-
function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, muted: initialMuted = true, showControls = true, showStats = false, onDebugStats, onPlaybackStats, onClientNetworkSample, probeAuthToken, onConnectTiming, className = "", onStateChange, onError, onReconnectAttempt, overlay, createSession, sendAnswer, handleOffer, getIceServers, addIceCandidate, getIceCandidates, closeSession, getSessionState, getSessionDebug, reoffer, posterUrl, hintsOverride, onAdaptiveHints, reconnectSignal, onControlChannel, onVideoElement }) {
|
|
32129
|
+
function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, muted: initialMuted = true, showControls = true, showStats = false, onDebugStats, onPlaybackStats, onClientNetworkSample, probeAuthToken, onConnectTiming, className = "", onStateChange, onError, onReconnectAttempt, overlay, createSession, sendAnswer, handleOffer, getIceServers, addIceCandidate, getIceCandidates, closeSession, getSessionState, getSessionDebug, applyDownlinkProbe, reoffer, posterUrl, hintsOverride, onAdaptiveHints, reconnectSignal, onControlChannel, onVideoElement }) {
|
|
31962
32130
|
const videoRef = (0, react$1.useRef)(null);
|
|
31963
32131
|
const containerRef = (0, react$1.useRef)(null);
|
|
31964
32132
|
const pcRef = (0, react$1.useRef)(null);
|
|
@@ -32012,6 +32180,29 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
32012
32180
|
* — once per origin app-wide (`firstRefusal`), so a missing `probeAuthToken`
|
|
32013
32181
|
* is visible instead of reading like a failed probe (review N3).
|
|
32014
32182
|
*/
|
|
32183
|
+
/** A ref so wiring it never rebuilds the connect callbacks (same as `onAdaptiveHints`). */
|
|
32184
|
+
const applyDownlinkProbeRef = (0, react$1.useRef)(applyDownlinkProbe);
|
|
32185
|
+
applyDownlinkProbeRef.current = applyDownlinkProbe;
|
|
32186
|
+
/**
|
|
32187
|
+
* After a cold start's probe justifies a higher rung: hand it to the session
|
|
32188
|
+
* it was measured on (D733). Only when the hub cannot take it does the
|
|
32189
|
+
* legacy climb run — `reconnect`, a second make-before-break session.
|
|
32190
|
+
*/
|
|
32191
|
+
const climbAfterProbe = (0, react$1.useCallback)(async (sessionId, mbps, reconnect) => {
|
|
32192
|
+
const handoff = await handProbeToSession(applyDownlinkProbeRef.current, sessionId, mbps);
|
|
32193
|
+
if (!mountedRef.current) return;
|
|
32194
|
+
if (handoff.kind === "unsupported") {
|
|
32195
|
+
reconnect();
|
|
32196
|
+
return;
|
|
32197
|
+
}
|
|
32198
|
+
const { outcome, tier, reason } = handoff.answer;
|
|
32199
|
+
onAdaptiveHintsRef.current?.({
|
|
32200
|
+
phase: "probe-in-session",
|
|
32201
|
+
probeOrigin: probeOriginFor(serverUrl),
|
|
32202
|
+
downlinkMbps: mbps,
|
|
32203
|
+
probeAnswer: `${outcome}:${tier ?? "-"}:${reason}`
|
|
32204
|
+
});
|
|
32205
|
+
}, [serverUrl]);
|
|
32015
32206
|
const reportProbeRefused = (0, react$1.useCallback)((origin, status) => {
|
|
32016
32207
|
onAdaptiveHintsRef.current?.({
|
|
32017
32208
|
phase: "probe-refused",
|
|
@@ -32175,7 +32366,10 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
32175
32366
|
if (!mountedRef.current || abort.signal.aborted) return;
|
|
32176
32367
|
if (probeUpgradeRef.current) return;
|
|
32177
32368
|
probeUpgradeRef.current = true;
|
|
32178
|
-
|
|
32369
|
+
climbAfterProbe(sessionId, mbps, () => {
|
|
32370
|
+
if (!mountedRef.current || abort.signal.aborted) return;
|
|
32371
|
+
connectServerOffer(true, true, mbps);
|
|
32372
|
+
});
|
|
32179
32373
|
});
|
|
32180
32374
|
let swappedIn = false;
|
|
32181
32375
|
const swapInOnce = () => {
|
|
@@ -32278,7 +32472,8 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
32278
32472
|
hintsOverride,
|
|
32279
32473
|
reportAdaptiveHints,
|
|
32280
32474
|
probeAuthToken,
|
|
32281
|
-
reportProbeRefused
|
|
32475
|
+
reportProbeRefused,
|
|
32476
|
+
climbAfterProbe
|
|
32282
32477
|
]);
|
|
32283
32478
|
const connectWhep = (0, react$1.useCallback)(async () => {
|
|
32284
32479
|
if (!mountedRef.current) return;
|
|
@@ -32360,6 +32555,9 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
32360
32555
|
const pc = new RTCPeerConnection({ iceServers: [...iceServers ?? [], { urls: "stun:stun.l.google.com:19302" }] });
|
|
32361
32556
|
if (!seamless) pcRef.current = pc;
|
|
32362
32557
|
const combinedStream = new MediaStream();
|
|
32558
|
+
/** This connect's server session — known once `handleOffer` answers,
|
|
32559
|
+
* which is before the first frame the probe waits for. */
|
|
32560
|
+
let probeSessionId = null;
|
|
32363
32561
|
if (!withDownlink) probeAfterThisStreamsFirstFrame({
|
|
32364
32562
|
video: () => videoRef.current,
|
|
32365
32563
|
stream: combinedStream,
|
|
@@ -32372,7 +32570,10 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
32372
32570
|
if (!mountedRef.current || abort.signal.aborted) return;
|
|
32373
32571
|
if (probeUpgradeRef.current) return;
|
|
32374
32572
|
probeUpgradeRef.current = true;
|
|
32375
|
-
|
|
32573
|
+
climbAfterProbe(probeSessionId, mbps, () => {
|
|
32574
|
+
if (!mountedRef.current || abort.signal.aborted) return;
|
|
32575
|
+
connectClientOffer(true, true, mbps);
|
|
32576
|
+
});
|
|
32376
32577
|
});
|
|
32377
32578
|
let swappedIn = false;
|
|
32378
32579
|
const swapInOnce = () => {
|
|
@@ -32482,6 +32683,7 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
32482
32683
|
const { sessionId: sid, sdpAnswer } = await handleOffer(pc.localDescription?.sdp ?? offer.sdp ?? "", void 0, clientOfferHints);
|
|
32483
32684
|
timing.signalingRttMs = ms() - signalingStart;
|
|
32484
32685
|
sessionId = sid;
|
|
32686
|
+
probeSessionId = sid;
|
|
32485
32687
|
sessionIdsRef.current.add(sid);
|
|
32486
32688
|
activeSessionIdRef.current = sid;
|
|
32487
32689
|
if (!mountedRef.current || abort.signal.aborted) {
|
|
@@ -32545,7 +32747,8 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
32545
32747
|
hintsOverride,
|
|
32546
32748
|
reportAdaptiveHints,
|
|
32547
32749
|
probeAuthToken,
|
|
32548
|
-
reportProbeRefused
|
|
32750
|
+
reportProbeRefused,
|
|
32751
|
+
climbAfterProbe
|
|
32549
32752
|
]);
|
|
32550
32753
|
renegotiateRef.current = (0, react$1.useCallback)(async (sessionId, target) => {
|
|
32551
32754
|
const reofferFn = reoffer;
|
|
@@ -53136,10 +53339,10 @@ function renderCellContent(state) {
|
|
|
53136
53339
|
className: "font-mono text-foreground truncate",
|
|
53137
53340
|
children: state.modelId
|
|
53138
53341
|
}),
|
|
53139
|
-
state.
|
|
53140
|
-
className: "ml-auto shrink-0 truncate rounded bg-primary/10 px-1 text-[8px] font-semibold text-primary",
|
|
53141
|
-
title: `
|
|
53142
|
-
children:
|
|
53342
|
+
state.suppliedByRoot !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
53343
|
+
className: "ml-auto shrink-0 truncate rounded bg-primary/10 px-1 text-[8px] font-semibold uppercase text-primary",
|
|
53344
|
+
title: `Uses the root model ${state.suppliedByRoot} — this step's own model does not run here`,
|
|
53345
|
+
children: "root"
|
|
53143
53346
|
}),
|
|
53144
53347
|
state.clusterWide === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
53145
53348
|
className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-primary",
|
|
@@ -56181,7 +56384,7 @@ function ImageOffIcon({ className }) {
|
|
|
56181
56384
|
]
|
|
56182
56385
|
});
|
|
56183
56386
|
}
|
|
56184
|
-
function StreamPanel({ serverUrl, createSession, sendAnswer, handleOffer, getIceServers, addIceCandidate, getIceCandidates, closeSession, getSessionState, getSessionDebug, playbackUrl, playbackFormat, playbackAuthToken, onExitPlayback, posterUrl, streams, activeStreamId: controlledStreamId, onStreamChange, deviceName, phase, pipelineMetrics, detections, stationaryObjects, defaultShowDetections = true, defaultShowMotion = false, streamStats, autoPlay = false, showPlayStop = false, snapshotSrc, snapshotLoading = false, onRefreshSnapshot, showStreamStats = false, children, extraOverlay, ptzAvailable = false, ptzShown = false, ptzOverlay, onPtzToggle, intercomAvailable = false, intercomShown = false, onIntercomToggle, chromeless = false, className }) {
|
|
56387
|
+
function StreamPanel({ serverUrl, createSession, sendAnswer, handleOffer, getIceServers, addIceCandidate, getIceCandidates, closeSession, getSessionState, getSessionDebug, applyDownlinkProbe, playbackUrl, playbackFormat, playbackAuthToken, onExitPlayback, posterUrl, streams, activeStreamId: controlledStreamId, onStreamChange, deviceName, phase, pipelineMetrics, detections, stationaryObjects, defaultShowDetections = true, defaultShowMotion = false, streamStats, autoPlay = false, showPlayStop = false, snapshotSrc, snapshotLoading = false, onRefreshSnapshot, showStreamStats = false, children, extraOverlay, ptzAvailable = false, ptzShown = false, ptzOverlay, onPtzToggle, intercomAvailable = false, intercomShown = false, onIntercomToggle, chromeless = false, className }) {
|
|
56185
56388
|
const registeredButtons = usePlayerToolbarButtons();
|
|
56186
56389
|
const recordedPlayback = useRecordedPlayback();
|
|
56187
56390
|
const [isPlaying, setIsPlaying] = (0, react$1.useState)(autoPlay);
|
|
@@ -56501,6 +56704,7 @@ function StreamPanel({ serverUrl, createSession, sendAnswer, handleOffer, getIce
|
|
|
56501
56704
|
reoffer: playerReoffer,
|
|
56502
56705
|
getSessionState,
|
|
56503
56706
|
...getSessionDebug ? { getSessionDebug } : {},
|
|
56707
|
+
...applyDownlinkProbe ? { applyDownlinkProbe } : {},
|
|
56504
56708
|
getIceServers,
|
|
56505
56709
|
addIceCandidate,
|
|
56506
56710
|
getIceCandidates,
|
|
@@ -58723,6 +58927,15 @@ function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
|
|
|
58723
58927
|
deviceId,
|
|
58724
58928
|
sessionId
|
|
58725
58929
|
});
|
|
58930
|
+
}, [trpc, deviceId]),
|
|
58931
|
+
applyDownlinkProbe: (0, react$1.useCallback)(async (sessionId, downlinkMbps) => {
|
|
58932
|
+
const mutate = trpc.webrtcSession.applyDownlinkProbe;
|
|
58933
|
+
if (deviceId === null || mutate === void 0) throw new Error("applyDownlinkProbe: not available for this player");
|
|
58934
|
+
return mutate.mutate({
|
|
58935
|
+
deviceId,
|
|
58936
|
+
sessionId,
|
|
58937
|
+
downlinkMbps
|
|
58938
|
+
});
|
|
58726
58939
|
}, [trpc, deviceId])
|
|
58727
58940
|
};
|
|
58728
58941
|
}
|
|
@@ -59452,6 +59665,7 @@ exports.resolveStepDefaultModel = resolveStepDefaultModel;
|
|
|
59452
59665
|
exports.resolveTableLayout = resolveTableLayout;
|
|
59453
59666
|
exports.roiTooLarge = roiTooLarge;
|
|
59454
59667
|
exports.roiTooLarge$1 = roiTooLarge;
|
|
59668
|
+
exports.rootSourceState = rootSourceState;
|
|
59455
59669
|
exports.routerBasename = routerBasename;
|
|
59456
59670
|
exports.scrubReducer = scrubReducer;
|
|
59457
59671
|
exports.selectPickerGroup = selectPickerGroup;
|
|
@@ -59948,17 +60162,22 @@ exports.useLlmStartRuntime = useLlmStartRuntime;
|
|
|
59948
60162
|
exports.useLlmStopRuntime = useLlmStopRuntime;
|
|
59949
60163
|
exports.useLlmTestProfile = useLlmTestProfile;
|
|
59950
60164
|
exports.useLlmUpsertProfile = useLlmUpsertProfile;
|
|
60165
|
+
exports.useLocalNetworkAddCustomAddress = useLocalNetworkAddCustomAddress;
|
|
59951
60166
|
exports.useLocalNetworkDownloadCa = useLocalNetworkDownloadCa;
|
|
60167
|
+
exports.useLocalNetworkGetAddresses = useLocalNetworkGetAddresses;
|
|
59952
60168
|
exports.useLocalNetworkGetAllowedAddresses = useLocalNetworkGetAllowedAddresses;
|
|
59953
60169
|
exports.useLocalNetworkGetConnectionEndpoints = useLocalNetworkGetConnectionEndpoints;
|
|
60170
|
+
exports.useLocalNetworkGetHubAddresses = useLocalNetworkGetHubAddresses;
|
|
59954
60171
|
exports.useLocalNetworkGetNotificationEndpoint = useLocalNetworkGetNotificationEndpoint;
|
|
59955
60172
|
exports.useLocalNetworkGetPreferred = useLocalNetworkGetPreferred;
|
|
59956
60173
|
exports.useLocalNetworkGetTlsStatus = useLocalNetworkGetTlsStatus;
|
|
59957
60174
|
exports.useLocalNetworkGetViewerEndpoints = useLocalNetworkGetViewerEndpoints;
|
|
59958
60175
|
exports.useLocalNetworkList = useLocalNetworkList;
|
|
59959
60176
|
exports.useLocalNetworkRegenerateCertificate = useLocalNetworkRegenerateCertificate;
|
|
60177
|
+
exports.useLocalNetworkRemoveCustomAddress = useLocalNetworkRemoveCustomAddress;
|
|
59960
60178
|
exports.useLocalNetworkResetAllowlistToBestMatch = useLocalNetworkResetAllowlistToBestMatch;
|
|
59961
60179
|
exports.useLocalNetworkRevertToGeneratedCertificate = useLocalNetworkRevertToGeneratedCertificate;
|
|
60180
|
+
exports.useLocalNetworkSetAddressRole = useLocalNetworkSetAddressRole;
|
|
59962
60181
|
exports.useLocalNetworkSetAllowedAddresses = useLocalNetworkSetAllowedAddresses;
|
|
59963
60182
|
exports.useLocalNetworkSetNotificationEndpoint = useLocalNetworkSetNotificationEndpoint;
|
|
59964
60183
|
exports.useLocalNetworkSetViewerEndpoints = useLocalNetworkSetViewerEndpoints;
|
|
@@ -60635,6 +60854,7 @@ exports.useWaterHeaterSetOperationMode = useWaterHeaterSetOperationMode;
|
|
|
60635
60854
|
exports.useWaterHeaterSetTargetTemp = useWaterHeaterSetTargetTemp;
|
|
60636
60855
|
exports.useWeatherGetStatus = useWeatherGetStatus;
|
|
60637
60856
|
exports.useWebrtcSessionAddIceCandidate = useWebrtcSessionAddIceCandidate;
|
|
60857
|
+
exports.useWebrtcSessionApplyDownlinkProbe = useWebrtcSessionApplyDownlinkProbe;
|
|
60638
60858
|
exports.useWebrtcSessionCloseSession = useWebrtcSessionCloseSession;
|
|
60639
60859
|
exports.useWebrtcSessionCreateSession = useWebrtcSessionCreateSession;
|
|
60640
60860
|
exports.useWebrtcSessionGetIceCandidates = useWebrtcSessionGetIceCandidates;
|