livedesk 0.1.655 → 0.1.657
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/hub/src/remote-hub.js +47 -24
- package/hub/src/server.js +200 -13
- package/hub/src/shared-wall-profile-contract.mjs +40 -0
- package/hub/src/shared-wall-profile-contract.test.mjs +38 -0
- package/package.json +1 -1
- package/web/dist/app.html +3 -3
- package/web/dist/app.webmanifest +1 -1
- package/web/dist/assets/{AgentSettingsTab-7PWVlMXN.js → AgentSettingsTab-CU3kHssT.js} +1 -1
- package/web/dist/assets/{AgentsPage-DfmvWT29.js → AgentsPage-DcUy7xPU.js} +1 -1
- package/web/dist/assets/{App-DqucFaHW.js → App-ARrqCA9B.js} +13 -13
- package/web/dist/assets/{CaptureGallery-Cniuvvyq.js → CaptureGallery-BPKKxPej.js} +1 -1
- package/web/dist/assets/{DesktopUpdatePanel-Bn7N7m4V.js → DesktopUpdatePanel-C5wDB5zf.js} +1 -1
- package/web/dist/assets/{SettingsPage-es9HBQaT.js → SettingsPage-ChNfBaQo.js} +1 -1
- package/web/dist/assets/{SettingsTabs-qIgqY_Xj.js → SettingsTabs-B-uMhvwn.js} +1 -1
- package/web/dist/assets/{ShareFilesPage-Bd2fe_H4.js → ShareFilesPage-C9vhKzGp.js} +1 -1
- package/web/dist/assets/{SupportPage-D3n87Hpc.js → SupportPage-C-uQ-RTX.js} +1 -1
- package/web/dist/assets/{VuvoDeskApp-9GDuXg9F.js → VuvoDeskApp-BeeOb_MQ.js} +1 -1
- package/web/dist/assets/{app-C9DkE6HV.js → app-DhbXrOFp.js} +1 -1
- package/web/dist/assets/{main-SlpA0zpK.js → main-BTb7f--C.js} +2 -2
- package/web/dist/assets/styles-eZ2IzXEL.js +16 -0
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +2 -2
- package/web/dist/vuvodesk-build-evidence.json +50 -50
- package/web/dist/assets/styles-aOuztJQq.js +0 -16
package/hub/src/remote-hub.js
CHANGED
|
@@ -17,14 +17,15 @@ import {
|
|
|
17
17
|
BoundedSegmentedBuffer,
|
|
18
18
|
createBoundedAgentBinaryIngressLane
|
|
19
19
|
} from './transport/agent-binary-ingress.js';
|
|
20
|
-
import {
|
|
21
|
-
REMOTE_CLIPBOARD_FILE_ACTIONS,
|
|
20
|
+
import {
|
|
21
|
+
REMOTE_CLIPBOARD_FILE_ACTIONS,
|
|
22
22
|
REMOTE_CLIPBOARD_LIMITS,
|
|
23
23
|
REMOTE_CLIPBOARD_PROTOCOL,
|
|
24
24
|
normalizeRemoteClipboardCommandResult,
|
|
25
25
|
normalizeRemoteClipboardManifest,
|
|
26
26
|
remoteClipboardContentNeedsFileTransfer
|
|
27
|
-
} from './remote-clipboard-contract.mjs';
|
|
27
|
+
} from './remote-clipboard-contract.mjs';
|
|
28
|
+
import { liveProfileSatisfiesDemand } from './shared-wall-profile-contract.mjs';
|
|
28
29
|
|
|
29
30
|
const DEFAULT_REMOTE_HUB_PORT = 5197;
|
|
30
31
|
const DEFAULT_REMOTE_HUB_HOST = '0.0.0.0';
|
|
@@ -11276,8 +11277,22 @@ export function createRemoteHub(options = {}) {
|
|
|
11276
11277
|
=== normalized.streamPurpose;
|
|
11277
11278
|
}
|
|
11278
11279
|
|
|
11279
|
-
function sharedLiveProfileResult(
|
|
11280
|
-
|
|
11280
|
+
function sharedLiveProfileResult(
|
|
11281
|
+
device,
|
|
11282
|
+
activeLiveStream,
|
|
11283
|
+
normalized,
|
|
11284
|
+
extra = {},
|
|
11285
|
+
subscriberRequestedProfile = null
|
|
11286
|
+
) {
|
|
11287
|
+
const requested = subscriberRequestedProfile && typeof subscriberRequestedProfile === 'object'
|
|
11288
|
+
? {
|
|
11289
|
+
fps: clampNumber(subscriberRequestedProfile.fps, 1, normalized.streamPurpose === 'control' ? 60 : 30, normalized.fps),
|
|
11290
|
+
maxWidth: clampNumber(subscriberRequestedProfile.maxWidth, 320, 3840, normalized.maxWidth),
|
|
11291
|
+
maxHeight: clampNumber(subscriberRequestedProfile.maxHeight, 180, 2160, normalized.maxHeight),
|
|
11292
|
+
quality: clampNumber(subscriberRequestedProfile.quality, 20, 95, normalized.quality)
|
|
11293
|
+
}
|
|
11294
|
+
: normalized;
|
|
11295
|
+
return {
|
|
11281
11296
|
ok: true,
|
|
11282
11297
|
commandId: activeLiveStream.commandId,
|
|
11283
11298
|
sessionId: device.sessionId,
|
|
@@ -11290,12 +11305,12 @@ export function createRemoteHub(options = {}) {
|
|
|
11290
11305
|
captureGeneration: Number(activeLiveStream.captureGeneration || 0),
|
|
11291
11306
|
ready: liveStreamHasCurrentFrame(activeLiveStream),
|
|
11292
11307
|
reused: true,
|
|
11293
|
-
sharedProfileReused: true,
|
|
11294
|
-
requestedProfile: {
|
|
11295
|
-
fps:
|
|
11296
|
-
maxWidth:
|
|
11297
|
-
maxHeight:
|
|
11298
|
-
quality:
|
|
11308
|
+
sharedProfileReused: true,
|
|
11309
|
+
requestedProfile: {
|
|
11310
|
+
fps: requested.fps,
|
|
11311
|
+
maxWidth: requested.maxWidth,
|
|
11312
|
+
maxHeight: requested.maxHeight,
|
|
11313
|
+
quality: requested.quality
|
|
11299
11314
|
},
|
|
11300
11315
|
effectiveProfile: {
|
|
11301
11316
|
fps: Number(activeLiveStream.fps || normalized.fps),
|
|
@@ -11506,10 +11521,11 @@ export function createRemoteHub(options = {}) {
|
|
|
11506
11521
|
const pendingDescriptor = getPendingLiveStreamDescriptor(activeLiveStream);
|
|
11507
11522
|
if (pendingDescriptor?.commandId) {
|
|
11508
11523
|
const pendingMatchesRequest = liveStreamMatchesOptions(pendingDescriptor, normalized);
|
|
11509
|
-
const pendingMatchesSharedOwner = options.forceRestart !== true
|
|
11510
|
-
&& options.reuseExisting === true
|
|
11511
|
-
&& options.reuseSharedExisting === true
|
|
11512
|
-
&& liveStreamMatchesOwnerIdentity(pendingDescriptor, normalized)
|
|
11524
|
+
const pendingMatchesSharedOwner = options.forceRestart !== true
|
|
11525
|
+
&& options.reuseExisting === true
|
|
11526
|
+
&& options.reuseSharedExisting === true
|
|
11527
|
+
&& liveStreamMatchesOwnerIdentity(pendingDescriptor, normalized)
|
|
11528
|
+
&& liveProfileSatisfiesDemand(pendingDescriptor, normalized);
|
|
11513
11529
|
if ((pendingMatchesRequest || pendingMatchesSharedOwner)
|
|
11514
11530
|
&& liveStreamReplacementStillPending(activeLiveStream)) {
|
|
11515
11531
|
emitRemoteEvent('RemoteLiveStreamRestartPending', device, {
|
|
@@ -11519,10 +11535,10 @@ export function createRemoteHub(options = {}) {
|
|
|
11519
11535
|
reason: safeString(options.restartReason || 'duplicate-restart', 128)
|
|
11520
11536
|
});
|
|
11521
11537
|
if (pendingMatchesSharedOwner && !pendingMatchesRequest) {
|
|
11522
|
-
return sharedLiveProfileResult(device, pendingDescriptor, normalized, {
|
|
11523
|
-
ready: false,
|
|
11524
|
-
pending: true
|
|
11525
|
-
});
|
|
11538
|
+
return sharedLiveProfileResult(device, pendingDescriptor, normalized, {
|
|
11539
|
+
ready: false,
|
|
11540
|
+
pending: true
|
|
11541
|
+
}, options.subscriberRequestedProfile);
|
|
11526
11542
|
}
|
|
11527
11543
|
return {
|
|
11528
11544
|
ok: true,
|
|
@@ -11599,10 +11615,11 @@ export function createRemoteHub(options = {}) {
|
|
|
11599
11615
|
}
|
|
11600
11616
|
if (activeLiveStream
|
|
11601
11617
|
&& options.forceRestart !== true
|
|
11602
|
-
&& options.reuseExisting === true
|
|
11603
|
-
&& options.reuseSharedExisting === true
|
|
11604
|
-
&& liveStreamMatchesOwnerIdentity(activeLiveStream, normalized)
|
|
11605
|
-
&& liveStreamIsReusable(activeLiveStream)
|
|
11618
|
+
&& options.reuseExisting === true
|
|
11619
|
+
&& options.reuseSharedExisting === true
|
|
11620
|
+
&& liveStreamMatchesOwnerIdentity(activeLiveStream, normalized)
|
|
11621
|
+
&& liveStreamIsReusable(activeLiveStream)
|
|
11622
|
+
&& liveProfileSatisfiesDemand(activeLiveStream, normalized)) {
|
|
11606
11623
|
emitRemoteEvent('RemoteLiveStreamSharedProfileReused', device, {
|
|
11607
11624
|
streamId,
|
|
11608
11625
|
commandId: activeLiveStream.commandId,
|
|
@@ -11614,7 +11631,13 @@ export function createRemoteHub(options = {}) {
|
|
|
11614
11631
|
effectiveMaxWidth: Number(activeLiveStream.maxWidth || normalized.maxWidth),
|
|
11615
11632
|
effectiveMaxHeight: Number(activeLiveStream.maxHeight || normalized.maxHeight)
|
|
11616
11633
|
});
|
|
11617
|
-
return sharedLiveProfileResult(
|
|
11634
|
+
return sharedLiveProfileResult(
|
|
11635
|
+
device,
|
|
11636
|
+
activeLiveStream,
|
|
11637
|
+
normalized,
|
|
11638
|
+
{},
|
|
11639
|
+
options.subscriberRequestedProfile
|
|
11640
|
+
);
|
|
11618
11641
|
}
|
|
11619
11642
|
if (activeLiveStream
|
|
11620
11643
|
&& options.forceRestart !== true
|
package/hub/src/server.js
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
isReusedLiveStreamFrameReady
|
|
36
36
|
} from './live-stream-monitor-contract.js';
|
|
37
37
|
import { createLiveCaptureTransitionRetryCoordinator } from './live-capture-transition-retry.mjs';
|
|
38
|
+
import { selectSharedWallSourceProfile } from './shared-wall-profile-contract.mjs';
|
|
38
39
|
import {
|
|
39
40
|
createPlanDeviceAccessSnapshot,
|
|
40
41
|
partitionPlanDeviceIds,
|
|
@@ -449,6 +450,25 @@ function handleRemoteHubEvent(type, event) {
|
|
|
449
450
|
.scheduleAfterConfirmedStop(liveStreamEventDeviceId);
|
|
450
451
|
}
|
|
451
452
|
}
|
|
453
|
+
if (type === 'RemoteLiveStreamRestartFailed') {
|
|
454
|
+
const failedDeviceId = String(event?.deviceId || event?.device?.deviceId || '').trim();
|
|
455
|
+
const retainedOwner = event?.device?.activeLiveStream;
|
|
456
|
+
if (String(retainedOwner?.streamPurpose || '').trim().toLowerCase() === 'wall') {
|
|
457
|
+
rebindSharedWallSubscribersToOwner(failedDeviceId, {
|
|
458
|
+
...retainedOwner,
|
|
459
|
+
sessionId: event?.device?.sessionId || ''
|
|
460
|
+
}, {
|
|
461
|
+
effectiveProfile: {
|
|
462
|
+
fps: Number(retainedOwner?.fps || 0),
|
|
463
|
+
maxWidth: Number(retainedOwner?.maxWidth || 0),
|
|
464
|
+
maxHeight: Number(retainedOwner?.maxHeight || 0),
|
|
465
|
+
quality: Number(retainedOwner?.quality || 0)
|
|
466
|
+
},
|
|
467
|
+
readySent: true,
|
|
468
|
+
reason: 'shared-wall-profile-upgrade-failed'
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
452
472
|
if (type === 'RemoteDeviceConnected' || type === 'RemoteDeviceDisconnected') {
|
|
453
473
|
connectedDeviceCount = Number(remoteHub.getStatus({ includeSecrets: false }).connectedDeviceCount || 0);
|
|
454
474
|
refreshPlanDeviceAccess(type === 'RemoteDeviceConnected' ? 'device-connected' : 'device-disconnected');
|
|
@@ -2591,7 +2611,7 @@ function hasOtherFrameStreamOwner(ws, deviceId, streamId, streamPurpose = '') {
|
|
|
2591
2611
|
return false;
|
|
2592
2612
|
}
|
|
2593
2613
|
|
|
2594
|
-
function hasOtherFrameStreamDemand(ws, deviceId, streamPurpose = '') {
|
|
2614
|
+
function hasOtherFrameStreamDemand(ws, deviceId, streamPurpose = '') {
|
|
2595
2615
|
const normalizedPurpose = String(streamPurpose || '').trim().toLowerCase();
|
|
2596
2616
|
if (!deviceId || !normalizedPurpose) {
|
|
2597
2617
|
return false;
|
|
@@ -2608,8 +2628,135 @@ function hasOtherFrameStreamDemand(ws, deviceId, streamPurpose = '') {
|
|
|
2608
2628
|
return true;
|
|
2609
2629
|
}
|
|
2610
2630
|
}
|
|
2611
|
-
return false;
|
|
2612
|
-
}
|
|
2631
|
+
return false;
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
function frameClientMonitorIndex(ws, deviceId, liveOptions = ws?.liveDeskLiveOptions || {}) {
|
|
2635
|
+
return Object.prototype.hasOwnProperty.call(liveOptions.monitorSelections || {}, deviceId)
|
|
2636
|
+
? normalizeMonitorIndex(liveOptions.monitorSelections[deviceId])
|
|
2637
|
+
: normalizeMonitorIndex(liveOptions.monitorIndex);
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
function resolveSharedWallSourceDemand(ws, deviceId, liveOptions, monitorIndex) {
|
|
2641
|
+
const requestedMode = String(liveOptions?.frameMode || liveOptions?.mode || '').trim().toLowerCase();
|
|
2642
|
+
const requestedPurpose = String(liveOptions?.streamPurpose || '').trim().toLowerCase();
|
|
2643
|
+
const requestedMonitorIndex = normalizeMonitorIndex(monitorIndex);
|
|
2644
|
+
const demands = [{
|
|
2645
|
+
fps: liveOptions?.fps,
|
|
2646
|
+
maxWidth: liveOptions?.maxWidth,
|
|
2647
|
+
maxHeight: liveOptions?.maxHeight,
|
|
2648
|
+
quality: liveOptions?.quality
|
|
2649
|
+
}];
|
|
2650
|
+
if (requestedPurpose === 'wall') {
|
|
2651
|
+
for (const candidate of frameClients) {
|
|
2652
|
+
const candidateOptions = candidate?.liveDeskLiveOptions;
|
|
2653
|
+
if (candidate === ws
|
|
2654
|
+
|| candidate?.readyState !== candidate?.OPEN
|
|
2655
|
+
|| candidate?.liveDeskAutoStart !== true
|
|
2656
|
+
|| !(candidate.liveDeskDeviceIds instanceof Set)
|
|
2657
|
+
|| !candidate.liveDeskDeviceIds.has(deviceId)
|
|
2658
|
+
|| String(candidateOptions?.streamPurpose || '').trim().toLowerCase() !== 'wall'
|
|
2659
|
+
|| String(candidateOptions?.frameMode || candidateOptions?.mode || '').trim().toLowerCase()
|
|
2660
|
+
!== requestedMode
|
|
2661
|
+
|| frameClientMonitorIndex(candidate, deviceId, candidateOptions) !== requestedMonitorIndex) {
|
|
2662
|
+
continue;
|
|
2663
|
+
}
|
|
2664
|
+
demands.push({
|
|
2665
|
+
fps: candidateOptions.fps,
|
|
2666
|
+
maxWidth: candidateOptions.maxWidth,
|
|
2667
|
+
maxHeight: candidateOptions.maxHeight,
|
|
2668
|
+
quality: candidateOptions.quality
|
|
2669
|
+
});
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
return {
|
|
2673
|
+
...selectSharedWallSourceProfile(demands),
|
|
2674
|
+
// Keep the strongest healthy generation until the final Wall viewer
|
|
2675
|
+
// releases it. This prevents a lone late low-rate refresh from undoing a
|
|
2676
|
+
// 30 fps upgrade and makes start order irrelevant.
|
|
2677
|
+
preserveDominantProfile: requestedPurpose === 'wall'
|
|
2678
|
+
};
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
function rebindSharedWallSubscribersToOwner(deviceId, owner, {
|
|
2682
|
+
effectiveProfile = null,
|
|
2683
|
+
readySent = false,
|
|
2684
|
+
reason = 'shared-wall-profile-owner-changed'
|
|
2685
|
+
} = {}) {
|
|
2686
|
+
const normalizedDeviceId = String(deviceId || '').trim();
|
|
2687
|
+
const sessionId = String(owner?.sessionId || owner?.device?.sessionId || '').trim();
|
|
2688
|
+
const streamId = String(owner?.streamId || '').trim();
|
|
2689
|
+
const commandId = String(owner?.commandId || '').trim();
|
|
2690
|
+
const captureGeneration = Number(owner?.captureGeneration || 0);
|
|
2691
|
+
const monitorIndex = normalizeMonitorIndex(owner?.monitorIndex);
|
|
2692
|
+
const frameMode = String(owner?.frameMode || owner?.mode || '').trim().toLowerCase();
|
|
2693
|
+
const streamPurpose = String(owner?.streamPurpose || '').trim().toLowerCase();
|
|
2694
|
+
if (!normalizedDeviceId
|
|
2695
|
+
|| !sessionId
|
|
2696
|
+
|| !streamId
|
|
2697
|
+
|| !commandId
|
|
2698
|
+
|| !Number.isSafeInteger(captureGeneration)
|
|
2699
|
+
|| captureGeneration <= 0
|
|
2700
|
+
|| streamPurpose !== 'wall') {
|
|
2701
|
+
return 0;
|
|
2702
|
+
}
|
|
2703
|
+
let rebound = 0;
|
|
2704
|
+
const candidates = new Set([
|
|
2705
|
+
...(frameClientsByDeviceId.get(normalizedDeviceId) || []),
|
|
2706
|
+
...frameWildcardClients
|
|
2707
|
+
]);
|
|
2708
|
+
for (const candidate of candidates) {
|
|
2709
|
+
const candidateOptions = candidate?.liveDeskLiveOptions;
|
|
2710
|
+
if (candidate?.readyState !== candidate?.OPEN
|
|
2711
|
+
|| candidate?.liveDeskAutoStart !== true
|
|
2712
|
+
|| !(candidate.liveDeskDeviceIds instanceof Set)
|
|
2713
|
+
|| !candidate.liveDeskDeviceIds.has(normalizedDeviceId)
|
|
2714
|
+
|| String(candidateOptions?.streamPurpose || '').trim().toLowerCase() !== 'wall'
|
|
2715
|
+
|| String(candidateOptions?.frameMode || candidateOptions?.mode || '').trim().toLowerCase()
|
|
2716
|
+
!== frameMode
|
|
2717
|
+
|| frameClientMonitorIndex(candidate, normalizedDeviceId, candidateOptions) !== monitorIndex) {
|
|
2718
|
+
continue;
|
|
2719
|
+
}
|
|
2720
|
+
const previousBinding = candidate.liveDeskExpectedStreamBindingsByDeviceId instanceof Map
|
|
2721
|
+
? candidate.liveDeskExpectedStreamBindingsByDeviceId.get(normalizedDeviceId)
|
|
2722
|
+
: null;
|
|
2723
|
+
if (!previousBinding || previousBinding.readOnlyControlBorrow === true) continue;
|
|
2724
|
+
const nextBinding = {
|
|
2725
|
+
deviceId: normalizedDeviceId,
|
|
2726
|
+
sessionId,
|
|
2727
|
+
streamId,
|
|
2728
|
+
streamPurpose: 'wall',
|
|
2729
|
+
commandId,
|
|
2730
|
+
captureGeneration,
|
|
2731
|
+
monitorIndex,
|
|
2732
|
+
readOnlyControlBorrow: false,
|
|
2733
|
+
presentationPurpose: '',
|
|
2734
|
+
effectiveProfile,
|
|
2735
|
+
readySent: readySent === true
|
|
2736
|
+
};
|
|
2737
|
+
const previousIdentity = frameLaneBindingIdentity(previousBinding);
|
|
2738
|
+
const nextIdentity = replaceExpectedFrameBindingForClient(
|
|
2739
|
+
candidate,
|
|
2740
|
+
normalizedDeviceId,
|
|
2741
|
+
nextBinding
|
|
2742
|
+
);
|
|
2743
|
+
if (!nextIdentity || nextIdentity === previousIdentity) continue;
|
|
2744
|
+
candidate.liveDeskStreamIdsByDeviceId?.set?.(normalizedDeviceId, streamId);
|
|
2745
|
+
candidate.liveDeskSharedProfileUpgradeCount = Math.max(
|
|
2746
|
+
0,
|
|
2747
|
+
Number(candidate.liveDeskSharedProfileUpgradeCount || 0)
|
|
2748
|
+
) + 1;
|
|
2749
|
+
rebound += 1;
|
|
2750
|
+
}
|
|
2751
|
+
if (rebound > 0) {
|
|
2752
|
+
console.log(
|
|
2753
|
+
`[VuvoDesk Hub] rebound ${rebound} Wall browser lane(s) device=${normalizedDeviceId} `
|
|
2754
|
+
+ `generation=${captureGeneration} profile=${Number(effectiveProfile?.fps || owner?.fps || 0)}fps `
|
|
2755
|
+
+ `reason=${String(reason || 'shared-wall-profile-owner-changed')}`
|
|
2756
|
+
);
|
|
2757
|
+
}
|
|
2758
|
+
return rebound;
|
|
2759
|
+
}
|
|
2613
2760
|
|
|
2614
2761
|
function frameStreamStopKey(deviceId, streamId, streamPurpose) {
|
|
2615
2762
|
return `${deviceId}\u0000${streamId}\u0000${streamPurpose}`;
|
|
@@ -3004,8 +3151,9 @@ function snapshotFrameLaneResourceHealth() {
|
|
|
3004
3151
|
maxWidth: Math.max(0, Number(ws.liveDeskLiveOptions.maxWidth || 0)),
|
|
3005
3152
|
maxHeight: Math.max(0, Number(ws.liveDeskLiveOptions.maxHeight || 0)),
|
|
3006
3153
|
quality: Math.max(0, Number(ws.liveDeskLiveOptions.quality || 0))
|
|
3007
|
-
} : null,
|
|
3008
|
-
sharedProfileReuseCount: Math.max(0, Number(ws.liveDeskSharedProfileReuseCount || 0)),
|
|
3154
|
+
} : null,
|
|
3155
|
+
sharedProfileReuseCount: Math.max(0, Number(ws.liveDeskSharedProfileReuseCount || 0)),
|
|
3156
|
+
sharedProfileUpgradeCount: Math.max(0, Number(ws.liveDeskSharedProfileUpgradeCount || 0)),
|
|
3009
3157
|
queueDepth: Math.max(0, Number(lane?.queue?.length || 0)),
|
|
3010
3158
|
queueLimit: frameClientQueueLimit(ws),
|
|
3011
3159
|
queueHighWaterPackets: Math.max(0, Number(lane?.queuedPacketsHighWater || 0)),
|
|
@@ -3810,12 +3958,33 @@ function startFrameSubscriptionLive(
|
|
|
3810
3958
|
skipped.push({ deviceId, reason: device?.connected ? 'live-unavailable' : 'not-connected' });
|
|
3811
3959
|
continue;
|
|
3812
3960
|
}
|
|
3813
|
-
const monitorIndex = Object.prototype.hasOwnProperty.call(liveOptions.monitorSelections || {}, deviceId)
|
|
3814
|
-
? liveOptions.monitorSelections[deviceId]
|
|
3815
|
-
: liveOptions.monitorIndex;
|
|
3961
|
+
const monitorIndex = Object.prototype.hasOwnProperty.call(liveOptions.monitorSelections || {}, deviceId)
|
|
3962
|
+
? liveOptions.monitorSelections[deviceId]
|
|
3963
|
+
: liveOptions.monitorIndex;
|
|
3964
|
+
const sharedWallSourceProfile = resolveSharedWallSourceDemand(
|
|
3965
|
+
ws,
|
|
3966
|
+
deviceId,
|
|
3967
|
+
liveOptions,
|
|
3968
|
+
monitorIndex
|
|
3969
|
+
);
|
|
3970
|
+
const sourceLiveOptions = sharedWallSourceProfile.preserveDominantProfile
|
|
3971
|
+
? {
|
|
3972
|
+
...liveOptions,
|
|
3973
|
+
fps: sharedWallSourceProfile.fps,
|
|
3974
|
+
maxWidth: sharedWallSourceProfile.maxWidth,
|
|
3975
|
+
maxHeight: sharedWallSourceProfile.maxHeight,
|
|
3976
|
+
quality: sharedWallSourceProfile.quality
|
|
3977
|
+
}
|
|
3978
|
+
: liveOptions;
|
|
3816
3979
|
const result = remoteHub.startLiveStream(deviceId, {
|
|
3817
|
-
...
|
|
3980
|
+
...sourceLiveOptions,
|
|
3818
3981
|
monitorIndex,
|
|
3982
|
+
subscriberRequestedProfile: {
|
|
3983
|
+
fps: liveOptions.fps,
|
|
3984
|
+
maxWidth: liveOptions.maxWidth,
|
|
3985
|
+
maxHeight: liveOptions.maxHeight,
|
|
3986
|
+
quality: liveOptions.quality
|
|
3987
|
+
},
|
|
3819
3988
|
reuseExisting: liveOptions.forceRestart !== true
|
|
3820
3989
|
&& (liveOptions.reuseExisting === true || reason === 'subscribe' || reason === 'watchdog'),
|
|
3821
3990
|
// Wall capture is one shared native encoder per device. Two open browser
|
|
@@ -3825,7 +3994,8 @@ function startFrameSubscriptionLive(
|
|
|
3825
3994
|
// and forth every time either view refreshes its subscription.
|
|
3826
3995
|
reuseSharedExisting: liveOptions.forceRestart !== true
|
|
3827
3996
|
&& String(liveOptions.streamPurpose || '').trim().toLowerCase() === 'wall'
|
|
3828
|
-
&& hasOtherFrameStreamDemand(ws, deviceId, 'wall')
|
|
3997
|
+
&& (hasOtherFrameStreamDemand(ws, deviceId, 'wall')
|
|
3998
|
+
|| sharedWallSourceProfile.preserveDominantProfile === true),
|
|
3829
3999
|
silentReuse: reason === 'watchdog' && liveOptions.forceRestart !== true
|
|
3830
4000
|
});
|
|
3831
4001
|
if (liveOptions.forceRestart === true) {
|
|
@@ -3834,8 +4004,25 @@ function startFrameSubscriptionLive(
|
|
|
3834
4004
|
`[VuvoDesk Hub] browser frame recovery client=${String(ws.liveDeskFrameClientId || '-')} device=${deviceId} purpose=${String(liveOptions.streamPurpose || 'wall')} reason=${String(liveOptions.restartReason || reason || 'browser-stale')} token=${token ? token.slice(0, 12) : '-'} result=${result?.ok ? 'accepted' : String(result?.error || 'failed')} session=${String(result?.sessionId || device?.sessionId || '').slice(0, 8)} stream=${String(result?.streamId || '-')} generation=${Number(result?.captureGeneration || 0)} reused=${result?.reused === true}`
|
|
3835
4005
|
);
|
|
3836
4006
|
}
|
|
3837
|
-
if (result?.ok) {
|
|
3838
|
-
|
|
4007
|
+
if (result?.ok) {
|
|
4008
|
+
const effectiveWallProfile = String(result.streamPurpose || liveOptions.streamPurpose || '')
|
|
4009
|
+
.trim().toLowerCase() === 'wall'
|
|
4010
|
+
? {
|
|
4011
|
+
fps: Number(result.effectiveProfile?.fps || sourceLiveOptions.fps || result.fps || 0),
|
|
4012
|
+
maxWidth: Number(result.effectiveProfile?.maxWidth || sourceLiveOptions.maxWidth || 0),
|
|
4013
|
+
maxHeight: Number(result.effectiveProfile?.maxHeight || sourceLiveOptions.maxHeight || 0),
|
|
4014
|
+
quality: Number(result.effectiveProfile?.quality || sourceLiveOptions.quality || 0)
|
|
4015
|
+
}
|
|
4016
|
+
: result.effectiveProfile || null;
|
|
4017
|
+
if (result.reused !== true
|
|
4018
|
+
&& String(result.streamPurpose || '').trim().toLowerCase() === 'wall') {
|
|
4019
|
+
rebindSharedWallSubscribersToOwner(deviceId, result, {
|
|
4020
|
+
effectiveProfile: effectiveWallProfile,
|
|
4021
|
+
readySent: false,
|
|
4022
|
+
reason: 'shared-wall-profile-upgraded'
|
|
4023
|
+
});
|
|
4024
|
+
}
|
|
4025
|
+
if (result.sharedProfileReused === true) {
|
|
3839
4026
|
ws.liveDeskSharedProfileReuseCount = Math.max(
|
|
3840
4027
|
0,
|
|
3841
4028
|
Number(ws.liveDeskSharedProfileReuseCount || 0)
|
|
@@ -3852,7 +4039,7 @@ function startFrameSubscriptionLive(
|
|
|
3852
4039
|
monitorIndex: Number(result.monitorIndex || 0),
|
|
3853
4040
|
readOnlyControlBorrow: result.readOnlyControlBorrow === true,
|
|
3854
4041
|
presentationPurpose: result.presentationPurpose === 'wall' ? 'wall' : '',
|
|
3855
|
-
effectiveProfile:
|
|
4042
|
+
effectiveProfile: effectiveWallProfile,
|
|
3856
4043
|
readySent: false
|
|
3857
4044
|
};
|
|
3858
4045
|
const activeStream = device?.activeLiveStream;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function finiteProfileNumber(value, fallback = 0) {
|
|
2
|
+
const numeric = Number(value);
|
|
3
|
+
return Number.isFinite(numeric) && numeric > 0 ? numeric : fallback;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function selectSharedWallSourceProfile(demands = []) {
|
|
7
|
+
const profiles = Array.isArray(demands) ? demands.filter(Boolean) : [];
|
|
8
|
+
if (profiles.length === 0) {
|
|
9
|
+
return Object.freeze({
|
|
10
|
+
fps: 0,
|
|
11
|
+
maxWidth: 0,
|
|
12
|
+
maxHeight: 0,
|
|
13
|
+
quality: 0,
|
|
14
|
+
demandCount: 0
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const selected = profiles.reduce((profile, demand) => ({
|
|
18
|
+
fps: Math.max(profile.fps, finiteProfileNumber(demand.fps)),
|
|
19
|
+
maxWidth: Math.max(profile.maxWidth, finiteProfileNumber(demand.maxWidth)),
|
|
20
|
+
maxHeight: Math.max(profile.maxHeight, finiteProfileNumber(demand.maxHeight)),
|
|
21
|
+
quality: Math.max(profile.quality, finiteProfileNumber(demand.quality))
|
|
22
|
+
}), {
|
|
23
|
+
fps: 0,
|
|
24
|
+
maxWidth: 0,
|
|
25
|
+
maxHeight: 0,
|
|
26
|
+
quality: 0
|
|
27
|
+
});
|
|
28
|
+
return Object.freeze({
|
|
29
|
+
...selected,
|
|
30
|
+
demandCount: profiles.length
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function liveProfileSatisfiesDemand(activeProfile, requestedProfile) {
|
|
35
|
+
if (!activeProfile || !requestedProfile) return false;
|
|
36
|
+
return finiteProfileNumber(activeProfile.fps) >= finiteProfileNumber(requestedProfile.fps)
|
|
37
|
+
&& finiteProfileNumber(activeProfile.maxWidth) >= finiteProfileNumber(requestedProfile.maxWidth)
|
|
38
|
+
&& finiteProfileNumber(activeProfile.maxHeight) >= finiteProfileNumber(requestedProfile.maxHeight)
|
|
39
|
+
&& finiteProfileNumber(activeProfile.quality) >= finiteProfileNumber(requestedProfile.quality);
|
|
40
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
liveProfileSatisfiesDemand,
|
|
6
|
+
selectSharedWallSourceProfile
|
|
7
|
+
} from './shared-wall-profile-contract.mjs';
|
|
8
|
+
|
|
9
|
+
test('shared Wall source keeps the strongest field from every current viewer', () => {
|
|
10
|
+
assert.deepEqual(selectSharedWallSourceProfile([
|
|
11
|
+
{ fps: 5, maxWidth: 960, maxHeight: 540, quality: 68 },
|
|
12
|
+
{ fps: 30, maxWidth: 1920, maxHeight: 1080, quality: 75 }
|
|
13
|
+
]), {
|
|
14
|
+
fps: 30,
|
|
15
|
+
maxWidth: 1920,
|
|
16
|
+
maxHeight: 1080,
|
|
17
|
+
quality: 75,
|
|
18
|
+
demandCount: 2
|
|
19
|
+
});
|
|
20
|
+
assert.deepEqual(selectSharedWallSourceProfile([
|
|
21
|
+
{ fps: 5, maxWidth: 3840, maxHeight: 2160, quality: 70 },
|
|
22
|
+
{ fps: 30, maxWidth: 1920, maxHeight: 1080, quality: 80 }
|
|
23
|
+
]), {
|
|
24
|
+
fps: 30,
|
|
25
|
+
maxWidth: 3840,
|
|
26
|
+
maxHeight: 2160,
|
|
27
|
+
quality: 80,
|
|
28
|
+
demandCount: 2
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('a shared source is reused only when it satisfies every requested profile field', () => {
|
|
33
|
+
const high = { fps: 30, maxWidth: 1920, maxHeight: 1080, quality: 75 };
|
|
34
|
+
const low = { fps: 5, maxWidth: 960, maxHeight: 540, quality: 68 };
|
|
35
|
+
assert.equal(liveProfileSatisfiesDemand(high, low), true);
|
|
36
|
+
assert.equal(liveProfileSatisfiesDemand(low, high), false);
|
|
37
|
+
assert.equal(liveProfileSatisfiesDemand({ ...high, fps: 5 }, high), false);
|
|
38
|
+
});
|
package/package.json
CHANGED
package/web/dist/app.html
CHANGED
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
.vuvodesk-static-boot [hidden] { display: none; }
|
|
53
53
|
@keyframes vuvodesk-static-boot-spin { to { transform: rotate(360deg); } }
|
|
54
54
|
</style>
|
|
55
|
-
<script type="module" crossorigin src="/assets/app-
|
|
55
|
+
<script type="module" crossorigin src="/assets/app-DhbXrOFp.js" data-vuvodesk-entry></script>
|
|
56
56
|
<link rel="modulepreload" crossorigin href="/assets/icons-CacEbnZu.js">
|
|
57
57
|
<link rel="modulepreload" crossorigin href="/assets/react-Cfedt3N5.js">
|
|
58
|
-
<link rel="modulepreload" crossorigin href="/assets/styles-
|
|
58
|
+
<link rel="modulepreload" crossorigin href="/assets/styles-eZ2IzXEL.js">
|
|
59
59
|
<link rel="modulepreload" crossorigin href="/assets/supabase-C7qjtLN3.js">
|
|
60
60
|
<link rel="modulepreload" crossorigin href="/assets/frame-lifecycle-esOdP-EY.js">
|
|
61
|
-
<link rel="modulepreload" crossorigin href="/assets/App-
|
|
61
|
+
<link rel="modulepreload" crossorigin href="/assets/App-ARrqCA9B.js">
|
|
62
62
|
<link rel="stylesheet" crossorigin href="/assets/styles-DDKP4MTD.css">
|
|
63
63
|
<link rel="stylesheet" crossorigin href="/assets/App-DFLBNvIi.css">
|
|
64
64
|
</head>
|
package/web/dist/app.webmanifest
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{h as x,j as t}from"./styles-
|
|
1
|
+
import{h as x,j as t}from"./styles-eZ2IzXEL.js";import{a as c,a5 as A,k as q,a6 as I,a7 as z}from"./icons-CacEbnZu.js";import"./react-Cfedt3N5.js";const E={enabled:!0};function w(a){return{enabled:a?.enabled===!0}}async function L(a,p,f){let l=null;for(let s=0;s<2;s+=1){const g=await x("/api/settings",{signal:f},p);if(g.settings.agent?.enabled===a)return;try{await x("/api/settings",{method:"PATCH",signal:f,body:JSON.stringify({revision:g.revision,agent:{enabled:a}})},p);return}catch(i){if(l=i,s!==0||!String(i instanceof Error?i.message:i).startsWith("409 "))throw i}}throw l}function F({hubUrl:a,showToast:p}){const[f,l]=c.useState(E),[s,g]=c.useState(null),[i,m]=c.useState(""),[j,v]=c.useState(""),[y,d]=c.useState(""),b=c.useRef(0),u=c.useRef(null);c.useEffect(()=>{let e=!0;u.current?.abort();const n=new AbortController;u.current=n;const h=++b.current;return g(null),l(E),m(""),d(""),v(""),x("/api/settings/agent",{signal:n.signal},a).then(o=>{!e||n.signal.aborted||h!==b.current||(g(o.settings),l(w(o.settings)))}).catch(o=>{e&&!n.signal.aborted&&h===b.current&&d(o instanceof Error?o.message:String(o))}),()=>{e=!1,n.abort(),u.current===n&&(u.current=null)}},[a]);const k=(e,n)=>l(h=>({...h,[e]:n})),C=e=>{g(e),l(w(e))},S=()=>({generation:b.current,controller:u.current}),r=e=>e.generation===b.current&&e.controller!==null&&e.controller===u.current&&!e.controller.signal.aborted,R=async()=>{if(!s){d("Agent settings are not available yet.");return}const e=S();if(r(e)){m("save"),d(""),v("");try{if(await L(f.enabled,a,e.controller.signal),!r(e))return;const n=await x("/api/settings/agent",{signal:e.controller.signal},a);if(!r(e))return;C(n.settings),v("Codex Agent settings saved.")}catch(n){r(e)&&d(n instanceof Error?n.message:String(n))}finally{r(e)&&m("")}}},D=async()=>{const e=S();if(r(e)){m("test"),d(""),v("");try{const n=await x("/api/settings/agent/test",{method:"POST",signal:e.controller.signal,body:JSON.stringify({})},a);if(!r(e))return;const h=await x("/api/settings/agent",{signal:e.controller.signal},a);if(!r(e))return;C(h.settings);const o=Number.isFinite(n.connection?.latencyMs)?Math.max(0,Math.round(n.connection.latencyMs)):null;p(`Codex Agent connection verified${o!==null?` in ${o} ms.`:"."}`,"success")}catch(n){r(e)&&d(n instanceof Error?n.message:String(n))}finally{r(e)&&m("")}}},T=s?.codexInstallation==="installed"&&s.codexAuth==="signed-in",N=s!==null;return t.jsxs("div",{className:"settings-tab-content agent-settings-content",children:[t.jsxs("section",{className:"settings-section-card agent-enable-card",children:[t.jsxs("label",{className:"settings-toggle agent-enable-toggle",children:[t.jsx("input",{type:"checkbox",checked:f.enabled,onChange:e=>k("enabled",e.target.checked),disabled:!N||i!==""}),t.jsx("span",{children:"Enable Codex Agent"})]}),t.jsxs("p",{className:"settings-help",children:[t.jsx(A,{size:12})," Enabled by default. Agent commands use only the Codex account signed in on this Hub."]})]}),y&&t.jsx("div",{className:"agent-settings-alert error",role:"alert",children:y}),j&&t.jsx("div",{className:"agent-settings-alert success",role:"status",children:j}),t.jsxs("section",{className:"settings-section-card",children:[t.jsxs("div",{className:"settings-section-heading",children:[t.jsxs("div",{children:[t.jsx("span",{children:"Connection"}),t.jsx("h3",{children:"Codex SDK / CLI"})]}),t.jsx(q,{size:20})]}),t.jsxs("div",{className:"agent-connection-row",children:[t.jsx("span",{className:`agent-connection-dot ${T?"connected":s?.codexAuth==="not-signed-in"?"unavailable":""}`}),t.jsx("span",{children:s?.codexInstallation==="not-installed"?"Codex SDK not installed":s?.codexAuth==="signed-in"?"Codex CLI signed in":s?.codexAuth==="not-signed-in"?"Codex CLI sign-in required":"Codex status not tested"}),t.jsxs("button",{className:"settings-reset",onClick:()=>{D()},disabled:i!=="",type:"button",children:[t.jsx(I,{size:15})," ",i==="test"?"Testing":"Test connection"]})]}),t.jsxs("p",{className:"settings-help",children:[t.jsx(A,{size:12})," The Hub uses the installed Codex SDK / CLI to plan approved commands and run them through VuvoDesk Agent tools on selected computers. VuvoDesk never asks for separate credentials."]})]}),t.jsx("div",{className:"settings-action-row agent-settings-actions",children:t.jsxs("button",{className:"text-button primary",onClick:()=>{R()},disabled:!N||i!=="",type:"button",children:[t.jsx(z,{size:15})," ",i==="save"?"Saving":"Save Agent settings"]})})]})}export{F as AgentSettingsTab};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as t,e as ht,h as F}from"./styles-
|
|
1
|
+
import{j as t,e as ht,h as F}from"./styles-eZ2IzXEL.js";import{a as d,m as yt,n as Ce,o as vt,l as ee,X as xe,p as wt,q as kt,s as Je,B as bt,t as Ct,u as Se,S as H,v as xt,w as St,x as _e,b as jt,y as At,k as Ze,z as Rt,N as Nt,F as Pt,H as It,I as Tt,J as Et,U as ue,c as Xe}from"./icons-CacEbnZu.js";import"./react-Cfedt3N5.js";const Ot=d.forwardRef(function({value:s,onChange:n,onSubmit:r,onOpenSuggestedTasks:i,suggestedOpen:f=!1,suggestedTaskCount:c,disabled:v=!1,placeholder:S="Ask VuvoDesk to work across your machines...",compact:g=!1},x){return t.jsxs("form",{className:"agents-composer",onSubmit:w=>{w.preventDefault(),r()},children:[t.jsx("button",{className:`agents-suggested-trigger ${f?"active":""}`,type:"button","aria-label":c===void 0?"Open Suggested tasks":`Open Suggested tasks (${c} available)`,"aria-expanded":f,onClick:i,disabled:v,children:t.jsx(yt,{size:17})}),t.jsx("textarea",{ref:x,value:s,onChange:w=>n(w.target.value.slice(0,4e3)),placeholder:S,"aria-label":"Ask VuvoDesk",rows:g?1:2,disabled:v}),t.jsxs("button",{className:"agents-run-button",type:"submit",disabled:v||!s.trim(),children:[v?t.jsx(Ce,{className:"spin",size:16}):t.jsx(vt,{size:16}),v?"Running":"Run"]})]})}),$t=["read","processControl","serviceControl","applicationControl","fileRead","fileWrite","fileDelete","shell","script","softwareInstall","network","systemPower","systemConfiguration","userAccount"];function de(e){return e.deviceName?.trim()||e.hostname?.trim()||e.deviceId}function pe(e){return e.connected!==!0?!1:e.synthetic===!0?!0:!e.channels||e.channels.control===!0}function Dt(e){return e==="running"||e==="completed"||e==="failed"||e==="cancelled"?e:"queued"}function _t(e){switch(e){case"process.list":return"Process list";case"system.health":return"System health";case"gpu.status":return"GPU status";case"disk.status":return"Disk status";case"service.status":return"Service status";case"diagnostics.collect":return"Diagnostics";case"process.control":return"Process control";case"service.control":return"Service control";case"application.launch":return"Launch application";case"application.close":return"Close application";case"file.read":return"Read file";case"file.write":return"Write file";case"file.delete":return"Delete file";case"file.list":return"List directory";case"command.run":return"Run command";case"script.run":return"Run script";case"software.install":return"Install software";case"network.status":return"Network status";case"system.power":return"Power action";case"system.configure":return"System configuration";case"logs.collect":return"Collect logs"}}const zt=64*1024,ze="[Earlier log output hidden by PWA display limit.]",Qe=new TextEncoder,Mt=new TextDecoder("utf-8",{fatal:!0}),Me=16*1024,Lt=200,Le="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|authorization|api[_-]?key|private[_-]?key|connection[_-]?string|credential|password|passwd|secret|cookie|set-cookie)",Ft="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|token|authorization|api[_-]?key|private[_-]?key|connection[_-]?string|credential|password|passwd|secret|cookie|set-cookie)",Bt="(?:access[_-]?(?:token|key)|refresh[_-]?token|id[_-]?token|pair[_-]?(?:token|key)|token|authorization|api[_-]?key|credential|password|secret|cookie)",Ut=/\b(?:sk-(?:proj-|ant-)?[A-Za-z0-9_-]{8,}|gh[pousr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{8,}|(?:AKIA|ASIA)[A-Z0-9]{16}|AIza[A-Za-z0-9_-]{35}|npm_[A-Za-z0-9]{8,}|xox[a-z]-[A-Za-z0-9-]{8,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{8,})\b/g;function qt(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function Fe(e){return Qe.encode(e).byteLength}function Be(e,s){const n=Qe.encode(e);if(n.byteLength<=s)return{value:e,truncated:!1};let r=n.byteLength-s;for(;r<n.byteLength&&(n[r]&192)===128;)r+=1;let i=Mt.decode(n.subarray(r));const f=i.indexOf(`
|
|
2
2
|
`);return f>=0&&f<i.length-1&&(i=i.slice(f+1)),{value:i,truncated:!0}}function et(e){return e.replace(/-----BEGIN [^-\r\n]*PRIVATE KEY-----[\s\S]*?-----END [^-\r\n]*PRIVATE KEY-----/gi,"[REDACTED PRIVATE KEY]").replace(/\b(?:proxy-)?authorization\s*[:=]\s*[^\r\n]*|\b(?:set-)?cookie\s*[:=]\s*[^\r\n]*/gi,"credential-header=[REDACTED]").replace(/\bBearer\s+(?:"[^"]*"|'[^']*'|[^\s,;]+)/gi,"Bearer [REDACTED]").replace(new RegExp(`("${Le}"\\s*:\\s*")[^"\\r\\n]*(")`,"gi"),"$1[REDACTED]$2").replace(new RegExp(`('${Le}'\\s*:\\s*')[^'\\r\\n]*(')`,"gi"),"$1[REDACTED]$2").replace(new RegExp(`((?:[A-Za-z0-9.-]+[_-])?${Ft}\\s*[:=]\\s*)(?!\\[REDACTED\\])[^\\s,;&]+`,"gi"),"$1[REDACTED]").replace(new RegExp(`([?&]${Bt}=)[^&\\s]+`,"gi"),"$1[REDACTED]").replace(/\b(?:eyJ|[A-Za-z0-9_-]{8,}\.)[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g,"[REDACTED TOKEN]").replace(Ut,"[REDACTED KEY]")}function Gt(e){return typeof e!="string"?"source unknown":et(e).replace(/[\u0000-\u001f\u007f]/g," ").trim().slice(0,64)||"source unknown"}function Ue(e){return typeof e=="number"&&Number.isSafeInteger(e)&&e>=0?Math.floor(e):null}function Vt(e){if(typeof e!="string"||e.length===0)return{output:"",displayTruncated:!1};const s=Be(e.replace(/\r\n?/g,`
|
|
3
3
|
`),zt);let n=et(s.value).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g," ").trim(),r=s.truncated;const i=n?n.split(`
|
|
4
4
|
`):[];if(i.length>Lt-1&&(n=i.slice(-199).join(`
|