livedesk 0.1.460 → 0.1.461
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/README.md +28 -5
- package/bin/livedesk.js +189 -1
- package/bootstrap/runtime-lock.js +6 -0
- package/client/package.json +9 -8
- package/client/src/runtime/windows-owned-process-manifest.js +181 -14
- package/diagnostics/livedesk-mac-physical-gate-core.mjs +214 -26
- package/diagnostics/livedesk-mode3-capture-smoke.mjs +406 -4
- package/diagnostics/livedesk-transport-physical-core.mjs +200 -1
- package/diagnostics/livedesk-transport-physical.mjs +60 -1
- package/hub/package.json +1 -1
- package/hub/src/remote-hub.js +364 -49
- package/hub/src/server.js +4 -0
- package/hub/src/transport/udp-hub-transport.js +29 -6
- package/package.json +10 -9
- package/scripts/sync-web-dist.js +127 -0
- package/web/dist/assets/index-l4YzRK9d.js +25 -0
- package/web/dist/index.html +1 -1
- package/web/dist/assets/index-JqqQ5DKN.js +0 -25
|
@@ -492,12 +492,13 @@ function check(id, ok, detail) {
|
|
|
492
492
|
}
|
|
493
493
|
|
|
494
494
|
export function classifyMacPhysicalGate(snapshot = {}) {
|
|
495
|
+
const schemaVersion = Math.floor(finite(snapshot.schemaVersion));
|
|
495
496
|
const requestedFps = Math.max(1, finite(snapshot.requestedFps, 30));
|
|
496
497
|
const minimumFps = requestedFps * 0.8;
|
|
497
|
-
const telemetry = snapshot.telemetry || {};
|
|
498
498
|
const helper = snapshot.helper || {};
|
|
499
499
|
const monitor = snapshot.monitor || {};
|
|
500
500
|
const modifier = snapshot.modifier || {};
|
|
501
|
+
const lifecycle = snapshot.lifecycle || {};
|
|
501
502
|
const transport = snapshot.transport || {};
|
|
502
503
|
const diagnostic = snapshot.diagnostic || {};
|
|
503
504
|
const abortedSignal = String(diagnostic.abortedSignal || '').trim();
|
|
@@ -510,18 +511,65 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
510
511
|
const cleanupErrors = Array.isArray(diagnostic.cleanupErrors)
|
|
511
512
|
? diagnostic.cleanupErrors.map(value => String(value || '').trim()).filter(Boolean)
|
|
512
513
|
: [];
|
|
513
|
-
const
|
|
514
|
-
const
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
&&
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
514
|
+
const captureStages = snapshot.stages || {};
|
|
515
|
+
const requiredStageNames = ['initial', 'switched'];
|
|
516
|
+
const stageEvidenceAvailable = requiredStageNames.every(name =>
|
|
517
|
+
captureStages[name]
|
|
518
|
+
&& typeof captureStages[name] === 'object'
|
|
519
|
+
&& captureStages[name].telemetry
|
|
520
|
+
&& typeof captureStages[name].telemetry === 'object'
|
|
521
|
+
&& Number.isFinite(Number(captureStages[name].deliveredFps))
|
|
522
|
+
);
|
|
523
|
+
const stageEvaluations = requiredStageNames.map(name => {
|
|
524
|
+
const stage = captureStages[name] || {};
|
|
525
|
+
const stageTelemetry = stage.telemetry || {};
|
|
526
|
+
const captureFps = Math.max(0, finite(stageTelemetry.captureFps));
|
|
527
|
+
const compressionFps = Math.max(0, finite(stageTelemetry.compressionFps));
|
|
528
|
+
const stdoutFps = Math.max(0, finite(stageTelemetry.stdoutFps));
|
|
529
|
+
const deliveredFps = Math.max(0, finite(stage.deliveredFps));
|
|
530
|
+
const idleSkipped = Math.max(0, finite(stageTelemetry.idleSkipped));
|
|
531
|
+
const backpressureSkipped = Math.max(0, finite(stageTelemetry.backpressureSkipped));
|
|
532
|
+
// One incidental idle skip must never mask a 3-4 fps regression. A static
|
|
533
|
+
// screen is treated as intentionally idle only when most of a current
|
|
534
|
+
// one-second capture window was suppressed and keepalive output remained.
|
|
535
|
+
const idleDominant = captureFps >= minimumFps
|
|
536
|
+
&& backpressureSkipped === 0
|
|
537
|
+
&& idleSkipped >= Math.max(10, captureFps * 0.6);
|
|
538
|
+
return {
|
|
539
|
+
name,
|
|
540
|
+
telemetry: stageTelemetry,
|
|
541
|
+
captureFps,
|
|
542
|
+
compressionFps,
|
|
543
|
+
stdoutFps,
|
|
544
|
+
deliveredFps,
|
|
545
|
+
idleSkipped,
|
|
546
|
+
backpressureSkipped,
|
|
547
|
+
idleDominant,
|
|
548
|
+
telemetryCurrent: finite(stageTelemetry.version) >= 2
|
|
549
|
+
&& Number.isFinite(Number(stageTelemetry.ageMs))
|
|
550
|
+
&& finite(stageTelemetry.ageMs) <= 3_000,
|
|
551
|
+
hardwareAccelerated: stageTelemetry.hardwareAccelerated === true,
|
|
552
|
+
captureAtTarget: captureFps >= minimumFps,
|
|
553
|
+
compressionKeepsUp: (idleDominant && compressionFps >= 1)
|
|
554
|
+
|| (captureFps > 0 && compressionFps >= captureFps * 0.8),
|
|
555
|
+
stdoutKeepsUp: (idleDominant && stdoutFps >= 1)
|
|
556
|
+
|| (compressionFps > 0 && stdoutFps >= compressionFps * 0.8),
|
|
557
|
+
deliveredAtTarget: (idleDominant && deliveredFps >= 1)
|
|
558
|
+
|| deliveredFps >= minimumFps
|
|
559
|
+
};
|
|
560
|
+
});
|
|
561
|
+
const stageMetricDetail = metric => stageEvaluations
|
|
562
|
+
.map(stage => `${stage.name}=${finite(stage[metric]).toFixed(1)}`)
|
|
563
|
+
.join(' ');
|
|
564
|
+
const idleOptimized = stageEvaluations.some(stage => stage.idleDominant);
|
|
565
|
+
const captureAtTarget = stageEvidenceAvailable
|
|
566
|
+
&& stageEvaluations.every(stage => stage.captureAtTarget);
|
|
567
|
+
const compressionKeepsUp = stageEvidenceAvailable
|
|
568
|
+
&& stageEvaluations.every(stage => stage.compressionKeepsUp);
|
|
569
|
+
const stdoutKeepsUp = stageEvidenceAvailable
|
|
570
|
+
&& stageEvaluations.every(stage => stage.stdoutKeepsUp);
|
|
571
|
+
const deliveredAtTarget = stageEvidenceAvailable
|
|
572
|
+
&& stageEvaluations.every(stage => stage.deliveredAtTarget);
|
|
525
573
|
const helperPids = Array.isArray(helper.observedPids)
|
|
526
574
|
? helper.observedPids.map(Number).filter(pid => Number.isInteger(pid) && pid > 1)
|
|
527
575
|
: [];
|
|
@@ -568,8 +616,53 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
568
616
|
cpuPercentPeak: Math.max(0, finite(processInfo?.cpuPercentPeak)),
|
|
569
617
|
rssBytesPeak: Math.max(0, Math.round(finite(processInfo?.rssBytesPeak)))
|
|
570
618
|
}));
|
|
571
|
-
const
|
|
619
|
+
const expectedModifierSteps = buildMacModifierProbeSteps(1).map(step => ({
|
|
620
|
+
inputSeq: step.inputSeq,
|
|
621
|
+
type: step.type,
|
|
622
|
+
code: step.code
|
|
623
|
+
}));
|
|
624
|
+
const modifierApplied = Array.isArray(modifier.applied) ? modifier.applied : [];
|
|
625
|
+
const modifierSequenceMatches = modifierApplied.length === expectedModifierSteps.length
|
|
626
|
+
&& modifierApplied.every((actual, index) => {
|
|
627
|
+
const expected = expectedModifierSteps[index];
|
|
628
|
+
return actual?.inputSeq === expected.inputSeq
|
|
629
|
+
&& actual?.type === expected.type
|
|
630
|
+
&& actual?.code === expected.code;
|
|
631
|
+
});
|
|
632
|
+
const lifecycleOrder = Array.isArray(lifecycle.order)
|
|
633
|
+
? lifecycle.order.map(value => String(value || '').trim()).filter(Boolean)
|
|
634
|
+
: [];
|
|
635
|
+
const expectedLifecycleOrder = [
|
|
636
|
+
'wall',
|
|
637
|
+
'control',
|
|
638
|
+
'paused',
|
|
639
|
+
'blocked',
|
|
640
|
+
'resumed',
|
|
641
|
+
'control-resumed',
|
|
642
|
+
'control-stopped',
|
|
643
|
+
'wall-restored',
|
|
644
|
+
'stopped'
|
|
645
|
+
];
|
|
646
|
+
const lifecycleHelperCounts = [
|
|
647
|
+
finite(lifecycle.wallHelperCount, -1),
|
|
648
|
+
finite(lifecycle.controlHelperCount, -1),
|
|
649
|
+
finite(lifecycle.pausedHelperCount, -1),
|
|
650
|
+
finite(lifecycle.resumedControlHelperCount, -1),
|
|
651
|
+
finite(lifecycle.controlStoppedHelperCount, -1),
|
|
652
|
+
finite(lifecycle.restoredWallHelperCount, -1),
|
|
653
|
+
finite(lifecycle.finalHelperCount, -1)
|
|
654
|
+
];
|
|
655
|
+
const lifecycleCompletedAtMs = Date.parse(String(lifecycle.completedAt || ''));
|
|
656
|
+
const registrySampledAtMs = Date.parse(String(lifecycle.registrySampledAt || ''));
|
|
657
|
+
const lifecycleRegistryFresh = Number.isFinite(lifecycleCompletedAtMs)
|
|
658
|
+
&& Number.isFinite(registrySampledAtMs)
|
|
659
|
+
&& registrySampledAtMs >= lifecycleCompletedAtMs;
|
|
572
660
|
const checks = [
|
|
661
|
+
check(
|
|
662
|
+
'report-schema',
|
|
663
|
+
schemaVersion === 3,
|
|
664
|
+
`v${schemaVersion || 'missing'}`
|
|
665
|
+
),
|
|
573
666
|
check(
|
|
574
667
|
'diagnostic-run',
|
|
575
668
|
!runError,
|
|
@@ -580,6 +673,51 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
580
673
|
cleanupErrors.length === 0,
|
|
581
674
|
cleanupErrors.length === 0 ? 'completed' : cleanupErrors.join('; ')
|
|
582
675
|
),
|
|
676
|
+
check(
|
|
677
|
+
'capture-lifecycle-order',
|
|
678
|
+
lifecycleOrder.join('>') === expectedLifecycleOrder.join('>'),
|
|
679
|
+
lifecycleOrder.join(' -> ') || 'missing'
|
|
680
|
+
),
|
|
681
|
+
check(
|
|
682
|
+
'capture-lifecycle-generation',
|
|
683
|
+
finite(lifecycle.wallGeneration) > 0
|
|
684
|
+
&& finite(lifecycle.controlGeneration) > finite(lifecycle.wallGeneration)
|
|
685
|
+
&& finite(lifecycle.resumedControlGeneration) > finite(lifecycle.controlGeneration)
|
|
686
|
+
&& finite(lifecycle.restoredWallGeneration) > finite(lifecycle.resumedControlGeneration),
|
|
687
|
+
`${finite(lifecycle.wallGeneration)} -> ${finite(lifecycle.controlGeneration)}`
|
|
688
|
+
+ ` -> ${finite(lifecycle.resumedControlGeneration)}`
|
|
689
|
+
+ ` -> ${finite(lifecycle.restoredWallGeneration)}`
|
|
690
|
+
),
|
|
691
|
+
check(
|
|
692
|
+
'capture-lifecycle-pause',
|
|
693
|
+
lifecycle.pauseStopConfirmed === true
|
|
694
|
+
&& lifecycle.pauseStopAcknowledged === true
|
|
695
|
+
&& lifecycle.blockedWhilePaused === true
|
|
696
|
+
&& lifecycle.resumeAccepted === true,
|
|
697
|
+
`stop=${lifecycle.pauseStopConfirmed === true}/${lifecycle.pauseStopAcknowledged === true} `
|
|
698
|
+
+ `blocked=${lifecycle.blockedWhilePaused === true} resume=${lifecycle.resumeAccepted === true}`
|
|
699
|
+
),
|
|
700
|
+
check(
|
|
701
|
+
'capture-lifecycle-helper',
|
|
702
|
+
lifecycleHelperCounts.join(',') === '1,1,0,1,0,1,0',
|
|
703
|
+
lifecycleHelperCounts.join(' -> ')
|
|
704
|
+
),
|
|
705
|
+
check(
|
|
706
|
+
'capture-lifecycle-registry',
|
|
707
|
+
lifecycleRegistryFresh
|
|
708
|
+
&& finite(lifecycle.registryMaxConcurrent, -1) === 1
|
|
709
|
+
&& finite(lifecycle.registryFinalHelperCount, -1) === 0,
|
|
710
|
+
`completed=${String(lifecycle.completedAt || '-')} `
|
|
711
|
+
+ `sampled=${String(lifecycle.registrySampledAt || '-')} `
|
|
712
|
+
+ `max=${finite(lifecycle.registryMaxConcurrent, -1)} `
|
|
713
|
+
+ `final=${finite(lifecycle.registryFinalHelperCount, -1)}`
|
|
714
|
+
),
|
|
715
|
+
check(
|
|
716
|
+
'capture-lifecycle-stop',
|
|
717
|
+
lifecycle.controlStopConfirmed === true
|
|
718
|
+
&& lifecycle.finalStopConfirmed === true,
|
|
719
|
+
`control=${lifecycle.controlStopConfirmed === true} final=${lifecycle.finalStopConfirmed === true}`
|
|
720
|
+
),
|
|
583
721
|
check(
|
|
584
722
|
'first-frame',
|
|
585
723
|
finite(snapshot.firstFrameMs) > 0 && finite(snapshot.firstFrameMs) < 8_000,
|
|
@@ -591,6 +729,11 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
591
729
|
&& finite(snapshot.monitorSwitchFirstFrameMs) < 8_000,
|
|
592
730
|
`${Math.round(finite(snapshot.monitorSwitchFirstFrameMs))}ms`
|
|
593
731
|
),
|
|
732
|
+
check(
|
|
733
|
+
'capture-stage-evidence',
|
|
734
|
+
stageEvidenceAvailable,
|
|
735
|
+
stageEvidenceAvailable ? requiredStageNames.join(',') : 'initial and switched stages required'
|
|
736
|
+
),
|
|
594
737
|
check(
|
|
595
738
|
'native-profile',
|
|
596
739
|
snapshot.platformProfile === 'macos-screencapturekit-nv12-videotoolbox',
|
|
@@ -598,31 +741,57 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
598
741
|
),
|
|
599
742
|
check(
|
|
600
743
|
'telemetry-current',
|
|
601
|
-
|
|
602
|
-
&&
|
|
603
|
-
|
|
604
|
-
|
|
744
|
+
stageEvidenceAvailable
|
|
745
|
+
&& stageEvaluations.every(stage => stage.telemetryCurrent),
|
|
746
|
+
stageEvaluations
|
|
747
|
+
.map(stage =>
|
|
748
|
+
`${stage.name}=v${finite(stage.telemetry.version)}`
|
|
749
|
+
+ `/age=${Number.isFinite(Number(stage.telemetry.ageMs))
|
|
750
|
+
? Math.round(finite(stage.telemetry.ageMs))
|
|
751
|
+
: '-'}ms`
|
|
752
|
+
)
|
|
753
|
+
.join(' ')
|
|
605
754
|
),
|
|
606
755
|
check(
|
|
607
756
|
'hardware-videotoolbox',
|
|
608
|
-
|
|
609
|
-
|
|
757
|
+
stageEvidenceAvailable
|
|
758
|
+
&& stageEvaluations.every(stage => stage.hardwareAccelerated),
|
|
759
|
+
stageEvaluations
|
|
760
|
+
.map(stage => `${stage.name}=${stage.hardwareAccelerated ? 'hardware' : 'not-confirmed'}`)
|
|
761
|
+
.join(' ')
|
|
762
|
+
),
|
|
763
|
+
check(
|
|
764
|
+
'screencapturekit-fps',
|
|
765
|
+
captureAtTarget,
|
|
766
|
+
`${stageMetricDetail('captureFps')} target=${requestedFps}`
|
|
610
767
|
),
|
|
611
|
-
check('screencapturekit-fps', captureAtTarget, `${captureFps.toFixed(1)}/${requestedFps}`),
|
|
612
768
|
check(
|
|
613
769
|
'videotoolbox-fps',
|
|
614
770
|
compressionKeepsUp,
|
|
615
|
-
|
|
771
|
+
stageEvaluations
|
|
772
|
+
.map(stage =>
|
|
773
|
+
`${stage.name}=${stage.compressionFps.toFixed(1)}`
|
|
774
|
+
+ `/${stage.captureFps.toFixed(1)}`
|
|
775
|
+
+ `${stage.idleDominant ? ' idle-dominant' : ''}`
|
|
776
|
+
)
|
|
777
|
+
.join(' ')
|
|
616
778
|
),
|
|
617
779
|
check(
|
|
618
780
|
'stdout-fps',
|
|
619
781
|
stdoutKeepsUp,
|
|
620
|
-
|
|
782
|
+
stageEvaluations
|
|
783
|
+
.map(stage =>
|
|
784
|
+
`${stage.name}=${stage.stdoutFps.toFixed(1)}`
|
|
785
|
+
+ `/${stage.compressionFps.toFixed(1)}`
|
|
786
|
+
+ `${stage.idleDominant ? ' idle-dominant' : ''}`
|
|
787
|
+
)
|
|
788
|
+
.join(' ')
|
|
621
789
|
),
|
|
622
790
|
check(
|
|
623
791
|
'delivered-fps',
|
|
624
792
|
deliveredAtTarget,
|
|
625
|
-
`${
|
|
793
|
+
`${stageMetricDetail('deliveredFps')} target=${requestedFps}`
|
|
794
|
+
+ `${idleOptimized ? ' idle-dominant-stage' : ''}`
|
|
626
795
|
),
|
|
627
796
|
check(
|
|
628
797
|
'single-helper',
|
|
@@ -656,6 +825,13 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
656
825
|
finite(monitor.nextGeneration) > finite(monitor.initialGeneration),
|
|
657
826
|
`${finite(monitor.initialGeneration)} -> ${finite(monitor.nextGeneration)}`
|
|
658
827
|
),
|
|
828
|
+
check(
|
|
829
|
+
'monitor-native-identity',
|
|
830
|
+
finite(monitor.initialDisplayId) > 0
|
|
831
|
+
&& finite(monitor.nextDisplayId) > 0
|
|
832
|
+
&& finite(monitor.initialDisplayId) !== finite(monitor.nextDisplayId),
|
|
833
|
+
`${finite(monitor.initialDisplayId)} -> ${finite(monitor.nextDisplayId)}`
|
|
834
|
+
),
|
|
659
835
|
check(
|
|
660
836
|
'monitor-pixels',
|
|
661
837
|
Boolean(monitor.initialHash)
|
|
@@ -665,9 +841,12 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
665
841
|
),
|
|
666
842
|
check(
|
|
667
843
|
'modifier-native-ack',
|
|
668
|
-
|
|
844
|
+
modifier.expectedAcks === expectedModifierSteps.length
|
|
845
|
+
&& modifier.appliedAcks === expectedModifierSteps.length
|
|
846
|
+
&& modifierSequenceMatches
|
|
669
847
|
&& (!Array.isArray(modifier.errors) || modifier.errors.length === 0),
|
|
670
|
-
`${finite(modifier.appliedAcks)}/${
|
|
848
|
+
`${finite(modifier.appliedAcks)}/${expectedModifierSteps.length} native ACK, `
|
|
849
|
+
+ `sequence=${modifierSequenceMatches ? 'exact' : 'invalid'}`
|
|
671
850
|
),
|
|
672
851
|
check(
|
|
673
852
|
'active-transport',
|
|
@@ -682,10 +861,18 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
682
861
|
|
|
683
862
|
const failed = checks.filter(item => !item.ok);
|
|
684
863
|
const bottleneckByCheck = {
|
|
864
|
+
'report-schema': 'report-schema',
|
|
685
865
|
'diagnostic-run': 'diagnostic-run',
|
|
686
866
|
'diagnostic-cleanup': 'diagnostic-cleanup',
|
|
867
|
+
'capture-lifecycle-order': 'capture-lifecycle-order',
|
|
868
|
+
'capture-lifecycle-generation': 'capture-generation',
|
|
869
|
+
'capture-lifecycle-pause': 'capture-pause-resume',
|
|
870
|
+
'capture-lifecycle-helper': 'capture-helper-lifecycle',
|
|
871
|
+
'capture-lifecycle-registry': 'capture-helper-registry',
|
|
872
|
+
'capture-lifecycle-stop': 'capture-stop',
|
|
687
873
|
'first-frame': 'capture-startup',
|
|
688
874
|
'monitor-first-frame': 'monitor-restart',
|
|
875
|
+
'capture-stage-evidence': 'capture-stage-evidence',
|
|
689
876
|
'native-profile': 'capture-fallback',
|
|
690
877
|
'telemetry-current': 'native-telemetry-stale',
|
|
691
878
|
'hardware-videotoolbox': 'videotoolbox-software',
|
|
@@ -700,6 +887,7 @@ export function classifyMacPhysicalGate(snapshot = {}) {
|
|
|
700
887
|
'resource-drained': 'resource-not-drained',
|
|
701
888
|
'two-monitors': 'monitor-topology',
|
|
702
889
|
'monitor-generation': 'monitor-generation',
|
|
890
|
+
'monitor-native-identity': 'monitor-binding',
|
|
703
891
|
'monitor-pixels': 'monitor-binding',
|
|
704
892
|
'modifier-native-ack': 'remote-input',
|
|
705
893
|
'active-transport': 'transport-telemetry'
|