dsh-builtin-browser 0.4.10 → 0.4.11
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.
|
@@ -699,11 +699,38 @@ export class SystemBrowserViewHost {
|
|
|
699
699
|
// The port file is deliberately NOT deleted here, and that is a reversal.
|
|
700
700
|
//
|
|
701
701
|
// It used to be removed so the launch loop below could not read a previous browser's port. But
|
|
702
|
-
// the loop
|
|
703
|
-
//
|
|
704
|
-
//
|
|
705
|
-
//
|
|
706
|
-
//
|
|
702
|
+
// the loop judges freshness against a snapshot taken below, so the deletion never protected it
|
|
703
|
+
// — while it DID destroy the only record of a browser that may still be running for this
|
|
704
|
+
// profile. That record is what `adoptRunningBrowser` needs when the launch comes back as a
|
|
705
|
+
// hand-off: the browser was alive the whole time, and without the file there is no way to find
|
|
706
|
+
// it again.
|
|
707
|
+
const portFile = join(this.profileDir, 'DevToolsActivePort');
|
|
708
|
+
/**
|
|
709
|
+
* What the port file was like BEFORE this launch, so "fresh" is judged against a snapshot
|
|
710
|
+
* rather than against a clock.
|
|
711
|
+
*
|
|
712
|
+
* The test used to be `mtimeMs < spawnedAt` — a filesystem timestamp compared to `Date.now()`.
|
|
713
|
+
* Those are different clocks with different resolutions, and CI is where it showed: a file the
|
|
714
|
+
* fake browser had just written was rejected as stale, so the loop waited out its full 30s
|
|
715
|
+
* against a browser that was already listening, because the file's mtime had rounded down
|
|
716
|
+
* below the spawn time. That is not a test-only problem: on any filesystem whose mtime
|
|
717
|
+
* resolution is coarser than a millisecond, the plugin would fail to see the browser it had
|
|
718
|
+
* just launched, and report a CDP timeout for a browser that was up the whole time.
|
|
719
|
+
*
|
|
720
|
+
* `undefined` means there was no file, so any file that appears afterwards is fresh. When one
|
|
721
|
+
* existed, a later mtime OR different contents makes the new one fresh. Byte-identical contents
|
|
722
|
+
* with an unchanged mtime is the PREVIOUS browser's port, and adopting it is what this whole
|
|
723
|
+
* check exists to prevent: it may name a port that now belongs to something else entirely.
|
|
724
|
+
*/
|
|
725
|
+
const portFileBefore = (() => {
|
|
726
|
+
try {
|
|
727
|
+
return { mtimeMs: statSync(portFile).mtimeMs, contents: readFileSync(portFile, 'utf8') };
|
|
728
|
+
}
|
|
729
|
+
catch {
|
|
730
|
+
return undefined;
|
|
731
|
+
}
|
|
732
|
+
})();
|
|
733
|
+
// Kept for the failure message and for the exit listener's diagnostics; no longer a judgement.
|
|
707
734
|
const spawnedAt = Date.now();
|
|
708
735
|
let child;
|
|
709
736
|
try {
|
|
@@ -739,22 +766,28 @@ export class SystemBrowserViewHost {
|
|
|
739
766
|
// Clearing these is what makes the restart usable rather than merely alive.
|
|
740
767
|
this.forgetBrowserState();
|
|
741
768
|
});
|
|
742
|
-
const portFile = join(this.profileDir, 'DevToolsActivePort');
|
|
743
769
|
/**
|
|
744
770
|
* The port this launch wrote, or undefined while it has not written one yet.
|
|
745
771
|
*
|
|
746
|
-
* A file left by the PREVIOUS browser is not evidence about this one. Its contents
|
|
747
|
-
*
|
|
748
|
-
*
|
|
749
|
-
*
|
|
772
|
+
* A file left by the PREVIOUS browser is not evidence about this one. Its contents name a port
|
|
773
|
+
* that may now belong to something else entirely — another Chromium, a `node --inspect` — and
|
|
774
|
+
* connecting there publishes a client this host does not own and dispose() can never kill.
|
|
775
|
+
* Only a file that CHANGED across this launch counts, which is what `portFileBefore` records.
|
|
750
776
|
*/
|
|
751
777
|
const freshPort = () => {
|
|
752
778
|
try {
|
|
753
779
|
if (!existsSync(portFile))
|
|
754
780
|
return undefined;
|
|
755
|
-
|
|
781
|
+
const after = statSync(portFile);
|
|
782
|
+
const contents = readFileSync(portFile, 'utf8');
|
|
783
|
+
// Unchanged since before the launch: this is the previous browser's file, whatever its
|
|
784
|
+
// mtime says. Comparing against the snapshot rather than the spawn time is what keeps this
|
|
785
|
+
// correct on a filesystem whose timestamps are coarser than the clock behind spawnedAt.
|
|
786
|
+
if (portFileBefore !== undefined
|
|
787
|
+
&& after.mtimeMs <= portFileBefore.mtimeMs
|
|
788
|
+
&& contents === portFileBefore.contents)
|
|
756
789
|
return undefined;
|
|
757
|
-
const value = Number(
|
|
790
|
+
const value = Number(contents.split('\n')[0]?.trim() ?? '');
|
|
758
791
|
return Number.isInteger(value) && value > 0 ? value : undefined;
|
|
759
792
|
}
|
|
760
793
|
catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-builtin-browser",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.11",
|
|
4
4
|
"description": "Shared real browser plugin for DeepSeek Harness: install-and-use — a visible native browser the human can take over, driven by the agent over CDP. DOM-level interaction (React/Vue safe), per-task session isolation, cookie persistence (dsh_browser_auth), CAPTCHA detection, batch form fill (dsh_browser_fill), authenticated download, history/replay, action restriction",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -721,11 +721,37 @@ export class SystemBrowserViewHost implements ElectronBrowserViewHost {
|
|
|
721
721
|
// The port file is deliberately NOT deleted here, and that is a reversal.
|
|
722
722
|
//
|
|
723
723
|
// It used to be removed so the launch loop below could not read a previous browser's port. But
|
|
724
|
-
// the loop
|
|
725
|
-
//
|
|
726
|
-
//
|
|
727
|
-
//
|
|
728
|
-
//
|
|
724
|
+
// the loop judges freshness against a snapshot taken below, so the deletion never protected it
|
|
725
|
+
// — while it DID destroy the only record of a browser that may still be running for this
|
|
726
|
+
// profile. That record is what `adoptRunningBrowser` needs when the launch comes back as a
|
|
727
|
+
// hand-off: the browser was alive the whole time, and without the file there is no way to find
|
|
728
|
+
// it again.
|
|
729
|
+
const portFile = join(this.profileDir, 'DevToolsActivePort')
|
|
730
|
+
/**
|
|
731
|
+
* What the port file was like BEFORE this launch, so "fresh" is judged against a snapshot
|
|
732
|
+
* rather than against a clock.
|
|
733
|
+
*
|
|
734
|
+
* The test used to be `mtimeMs < spawnedAt` — a filesystem timestamp compared to `Date.now()`.
|
|
735
|
+
* Those are different clocks with different resolutions, and CI is where it showed: a file the
|
|
736
|
+
* fake browser had just written was rejected as stale, so the loop waited out its full 30s
|
|
737
|
+
* against a browser that was already listening, because the file's mtime had rounded down
|
|
738
|
+
* below the spawn time. That is not a test-only problem: on any filesystem whose mtime
|
|
739
|
+
* resolution is coarser than a millisecond, the plugin would fail to see the browser it had
|
|
740
|
+
* just launched, and report a CDP timeout for a browser that was up the whole time.
|
|
741
|
+
*
|
|
742
|
+
* `undefined` means there was no file, so any file that appears afterwards is fresh. When one
|
|
743
|
+
* existed, a later mtime OR different contents makes the new one fresh. Byte-identical contents
|
|
744
|
+
* with an unchanged mtime is the PREVIOUS browser's port, and adopting it is what this whole
|
|
745
|
+
* check exists to prevent: it may name a port that now belongs to something else entirely.
|
|
746
|
+
*/
|
|
747
|
+
const portFileBefore = ((): { mtimeMs: number; contents: string } | undefined => {
|
|
748
|
+
try {
|
|
749
|
+
return { mtimeMs: statSync(portFile).mtimeMs, contents: readFileSync(portFile, 'utf8') }
|
|
750
|
+
} catch {
|
|
751
|
+
return undefined
|
|
752
|
+
}
|
|
753
|
+
})()
|
|
754
|
+
// Kept for the failure message and for the exit listener's diagnostics; no longer a judgement.
|
|
729
755
|
const spawnedAt = Date.now()
|
|
730
756
|
let child: ReturnType<typeof spawn>
|
|
731
757
|
try {
|
|
@@ -759,20 +785,26 @@ export class SystemBrowserViewHost implements ElectronBrowserViewHost {
|
|
|
759
785
|
// Clearing these is what makes the restart usable rather than merely alive.
|
|
760
786
|
this.forgetBrowserState()
|
|
761
787
|
})
|
|
762
|
-
const portFile = join(this.profileDir, 'DevToolsActivePort')
|
|
763
788
|
/**
|
|
764
789
|
* The port this launch wrote, or undefined while it has not written one yet.
|
|
765
790
|
*
|
|
766
|
-
* A file left by the PREVIOUS browser is not evidence about this one. Its contents
|
|
767
|
-
*
|
|
768
|
-
*
|
|
769
|
-
*
|
|
791
|
+
* A file left by the PREVIOUS browser is not evidence about this one. Its contents name a port
|
|
792
|
+
* that may now belong to something else entirely — another Chromium, a `node --inspect` — and
|
|
793
|
+
* connecting there publishes a client this host does not own and dispose() can never kill.
|
|
794
|
+
* Only a file that CHANGED across this launch counts, which is what `portFileBefore` records.
|
|
770
795
|
*/
|
|
771
796
|
const freshPort = (): number | undefined => {
|
|
772
797
|
try {
|
|
773
798
|
if (!existsSync(portFile)) return undefined
|
|
774
|
-
|
|
775
|
-
const
|
|
799
|
+
const after = statSync(portFile)
|
|
800
|
+
const contents = readFileSync(portFile, 'utf8')
|
|
801
|
+
// Unchanged since before the launch: this is the previous browser's file, whatever its
|
|
802
|
+
// mtime says. Comparing against the snapshot rather than the spawn time is what keeps this
|
|
803
|
+
// correct on a filesystem whose timestamps are coarser than the clock behind spawnedAt.
|
|
804
|
+
if (portFileBefore !== undefined
|
|
805
|
+
&& after.mtimeMs <= portFileBefore.mtimeMs
|
|
806
|
+
&& contents === portFileBefore.contents) return undefined
|
|
807
|
+
const value = Number(contents.split('\n')[0]?.trim() ?? '')
|
|
776
808
|
return Number.isInteger(value) && value > 0 ? value : undefined
|
|
777
809
|
} catch {
|
|
778
810
|
return undefined
|