opendevbrowser 0.0.25 → 0.0.26

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.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-Z6ENAZUN.js → chunk-AVQL6WAS.js} +9 -2
  3. package/dist/chunk-AVQL6WAS.js.map +1 -0
  4. package/dist/{chunk-7U63PZ4W.js → chunk-GTTYIAI7.js} +369 -175
  5. package/dist/chunk-GTTYIAI7.js.map +1 -0
  6. package/dist/cli/commands/daemon.d.ts +25 -0
  7. package/dist/cli/commands/daemon.d.ts.map +1 -1
  8. package/dist/cli/commands/serve.d.ts +10 -13
  9. package/dist/cli/commands/serve.d.ts.map +1 -1
  10. package/dist/cli/commands/status.d.ts.map +1 -1
  11. package/dist/cli/daemon-client.d.ts.map +1 -1
  12. package/dist/cli/daemon-status-policy.d.ts +6 -0
  13. package/dist/cli/daemon-status-policy.d.ts.map +1 -0
  14. package/dist/cli/daemon-status.d.ts +1 -0
  15. package/dist/cli/daemon-status.d.ts.map +1 -1
  16. package/dist/cli/daemon.d.ts +5 -0
  17. package/dist/cli/daemon.d.ts.map +1 -1
  18. package/dist/cli/index.js +175 -96
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/cli/utils/http.d.ts.map +1 -1
  21. package/dist/daemon-fingerprint.json +3 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +109 -28
  24. package/dist/index.js.map +1 -1
  25. package/dist/opendevbrowser.d.ts.map +1 -1
  26. package/dist/opendevbrowser.js +109 -28
  27. package/dist/opendevbrowser.js.map +1 -1
  28. package/dist/providers/inspiredesign-capture.d.ts.map +1 -1
  29. package/dist/providers/workflows.d.ts.map +1 -1
  30. package/dist/{providers-CYEJZVXB.js → providers-T2FQJCF6.js} +2 -2
  31. package/dist/tools/index.d.ts.map +1 -1
  32. package/dist/tools/status.d.ts.map +1 -1
  33. package/extension/manifest.json +1 -1
  34. package/package.json +1 -1
  35. package/dist/chunk-7U63PZ4W.js.map +0 -1
  36. package/dist/chunk-Z6ENAZUN.js.map +0 -1
  37. /package/dist/{providers-CYEJZVXB.js.map → providers-T2FQJCF6.js.map} +0 -0
@@ -7,6 +7,13 @@ type DaemonResult = {
7
7
  autostart?: ReturnType<typeof getAutostartStatus>;
8
8
  status?: Awaited<ReturnType<typeof fetchDaemonStatusFromMetadata>>;
9
9
  };
10
+ type StopDaemonResult = {
11
+ outcome: "stopped" | "not_running" | "fingerprint_rejected" | "failed";
12
+ pid?: number;
13
+ port?: number;
14
+ status?: number;
15
+ error?: string;
16
+ };
10
17
  export declare function runDaemonCommand(args: ParsedArgs): Promise<{
11
18
  success: boolean;
12
19
  message: string;
@@ -22,6 +29,24 @@ export declare function runDaemonCommand(args: ParsedArgs): Promise<{
22
29
  message: string;
23
30
  data: import("../daemon-autostart").AutostartStatus;
24
31
  exitCode?: undefined;
32
+ } | {
33
+ success: boolean;
34
+ message: string;
35
+ data: {
36
+ stop: StopDaemonResult;
37
+ platform: NodeJS.Platform;
38
+ supported: boolean;
39
+ installed: boolean;
40
+ health: import("../daemon-autostart").AutostartHealth;
41
+ needsRepair: boolean;
42
+ location?: string;
43
+ taskName?: string;
44
+ command?: string;
45
+ expectedCommand?: string;
46
+ label?: string;
47
+ reason?: import("../daemon-autostart").AutostartReason;
48
+ };
49
+ exitCode: number;
25
50
  } | {
26
51
  success: boolean;
27
52
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAGjE,OAAO,EACL,kBAAkB,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,KAAK,YAAY,GAAG;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,6BAA6B,CAAC,CAAC,CAAC;CACpE,CAAC;AAwEF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;mBA5E1C,OAAO;iBACT,OAAO;oBACJ,UAAU,CAAC,OAAO,kBAAkB,CAAC;;;GAoJlD"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAIjE,OAAO,EACL,kBAAkB,EAKnB,MAAM,qBAAqB,CAAC;AAI7B,KAAK,YAAY,GAAG;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,6BAA6B,CAAC,CAAC,CAAC;CACpE,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,SAAS,GAAG,aAAa,GAAG,sBAAsB,GAAG,QAAQ,CAAC;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAmGF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA/G1C,OAAO;iBACT,OAAO;oBACJ,UAAU,CAAC,OAAO,kBAAkB,CAAC;;;GA+LlD"}
@@ -1,15 +1,5 @@
1
1
  import type { ParsedArgs } from "../args";
2
2
  export declare function runServe(args: ParsedArgs): Promise<{
3
- success: boolean;
4
- message: string;
5
- exitCode?: undefined;
6
- data?: undefined;
7
- } | {
8
- success: boolean;
9
- message: string;
10
- exitCode: number;
11
- data?: undefined;
12
- } | {
13
3
  success: boolean;
14
4
  message: string;
15
5
  data: {
@@ -19,9 +9,18 @@ export declare function runServe(args: ParsedArgs): Promise<{
19
9
  alreadyRunning: boolean;
20
10
  staleDaemonsCleared: number;
21
11
  relay: import("../../relay/relay-server").RelayStatus;
22
- native?: undefined;
23
12
  };
24
13
  exitCode: null;
14
+ } | {
15
+ success: boolean;
16
+ message: string;
17
+ exitCode?: undefined;
18
+ data?: undefined;
19
+ } | {
20
+ success: boolean;
21
+ message: string;
22
+ exitCode: number;
23
+ data?: undefined;
25
24
  } | {
26
25
  success: boolean;
27
26
  message: string;
@@ -31,8 +30,6 @@ export declare function runServe(args: ParsedArgs): Promise<{
31
30
  relayPort: number;
32
31
  native: import("./native").NativeStatus;
33
32
  staleDaemonsCleared: number;
34
- alreadyRunning?: undefined;
35
- relay?: undefined;
36
33
  };
37
34
  exitCode: null;
38
35
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AA+O1C,wBAAsB,QAAQ,CAAC,IAAI,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0L9C"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAwU1C,wBAAsB,QAAQ,CAAC,IAAI,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiK9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAwC1C,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU;;;;;;;;;GA8D/C"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAmC1C,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU;;;;;;;;;GAkE/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-client.d.ts","sourceRoot":"","sources":["../../src/cli/daemon-client.ts"],"names":[],"mappings":"AAgGA,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAyHF,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,aAAa,CAA6B;gBAEtC,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO;IAa9D,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IA0BlG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;YAcvB,eAAe;IAc7B,OAAO,CAAC,eAAe;YAqBT,aAAa;YAUb,mBAAmB;YAgBnB,YAAY;IAS1B,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,eAAe;YAOT,OAAO;CAgDtB;AAgFD,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAE3H;AAED,eAAO,MAAM,QAAQ;uCA3BX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,sBACX,MAAM,KACzB,MAAM,GAAG,SAAS;qCAvRmB,OAAO,KAAG,OAAO;;kCAoT3B,IAAI;CAGjC,CAAC;AAOF,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAOF,KAAK,kCAAkC,GAAG;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC,CAAC;AAkNF,iBAAS,2BAA2B,CAClC,OAAO,GAAE,kCAAuC,GAC/C,oBAAoB,CAwBtB"}
1
+ {"version":3,"file":"daemon-client.d.ts","sourceRoot":"","sources":["../../src/cli/daemon-client.ts"],"names":[],"mappings":"AAkGA,KAAK,WAAW,GAAG;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAiIF,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;IACpC,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,aAAa,CAA6B;gBAEtC,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAO;IAa9D,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,CAAC,CAAC;IA0BlG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;YAcvB,eAAe;IAc7B,OAAO,CAAC,eAAe;YAqBT,aAAa;YAUb,mBAAmB;YAgBnB,YAAY;IAS1B,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,eAAe;YAOT,OAAO;CAkDtB;AAgFD,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAE3H;AAED,eAAO,MAAM,QAAQ;uCA3BX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,sBACX,MAAM,KACzB,MAAM,GAAG,SAAS;qCAzRmB,OAAO,KAAG,OAAO;;kCAsT3B,IAAI;CAGjC,CAAC;AAOF,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAWF,KAAK,kCAAkC,GAAG;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC,CAAC;AAoOF,iBAAS,2BAA2B,CAClC,OAAO,GAAE,kCAAuC,GAC/C,oBAAoB,CAwBtB"}
@@ -0,0 +1,6 @@
1
+ export declare const DEFAULT_DAEMON_STATUS_FETCH_OPTIONS: {
2
+ readonly timeoutMs: 5000;
3
+ readonly retryAttempts: 5;
4
+ readonly retryDelayMs: 250;
5
+ };
6
+ //# sourceMappingURL=daemon-status-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-status-policy.d.ts","sourceRoot":"","sources":["../../src/cli/daemon-status-policy.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mCAAmC;;;;CAItC,CAAC"}
@@ -5,6 +5,7 @@ export type DaemonStatusPayload = {
5
5
  ok: true;
6
6
  pid: number;
7
7
  fingerprint?: string;
8
+ fingerprintCurrent?: boolean;
8
9
  hub: {
9
10
  instanceId: string;
10
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-status.d.ts","sourceRoot":"","sources":["../../src/cli/daemon-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,kBAAkB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;AAqBjD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAsBrC;AAED,wBAAsB,6BAA6B,CACjD,MAAM,CAAC,EAAE,oBAAoB,EAC7B,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAqCrC;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,mBAAmB,EAC3B,MAAM,CAAC,EAAE,oBAAoB,GAC5B,IAAI,CAaN"}
1
+ {"version":3,"file":"daemon-status.d.ts","sourceRoot":"","sources":["../../src/cli/daemon-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,UAAU,CAAC;AAIlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,GAAG,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,kBAAkB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;AA4EjD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA+BrC;AAED,wBAAsB,6BAA6B,CACjD,MAAM,CAAC,EAAE,oBAAoB,EAC7B,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAsCrC;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,mBAAmB,EAC3B,MAAM,CAAC,EAAE,oBAAoB,GAC5B,IAAI,CAaN"}
@@ -1,4 +1,8 @@
1
1
  import { type OpenDevBrowserConfig } from "../config";
2
+ export declare const DAEMON_STOP_DEBUG_ENV = "OPDEVBROWSER_DEBUG_DAEMON_STOP";
3
+ export declare const DAEMON_STOP_REASON_HEADER = "x-opendevbrowser-stop-reason";
4
+ export declare const DAEMON_STOP_CLIENT_PID_HEADER = "x-opendevbrowser-stop-client-pid";
5
+ export declare const DAEMON_STOP_FINGERPRINT_HEADER = "x-opendevbrowser-stop-fingerprint";
2
6
  export type DaemonState = {
3
7
  port: number;
4
8
  token: string;
@@ -30,6 +34,7 @@ export declare function clearDaemonMetadata(): void;
30
34
  export declare function resolveCurrentDaemonEntrypointPath(options?: ResolveDaemonEntrypointOptions): string;
31
35
  export declare function getCurrentDaemonFingerprint(options?: ResolveDaemonEntrypointOptions): string;
32
36
  export declare function isCurrentDaemonFingerprint(fingerprint?: string | null): boolean;
37
+ export declare function createDaemonStopHeaders(token: string, reason: string): Record<string, string>;
33
38
  export declare function resolveDaemonFingerprint(...candidates: Array<string | null | undefined>): string;
34
39
  export declare function isRecoverablePlaywrightTransportError(error: unknown): boolean;
35
40
  export declare function startDaemon(options?: DaemonOptions): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"AAQA,OAAO,EAAmC,KAAK,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAYvF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,KAAK,8BAA8B,GAAG;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC,CAAC;AAEF,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,kBAAkB,IAAI,WAAW,GAAG,IAAI,CAWvD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAI5D;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAO1C;AAED,wBAAgB,kCAAkC,CAChD,OAAO,GAAE,8BAAmC,GAC3C,MAAM,CAYR;AAUD,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,8BAAmC,GAAG,MAAM,CAiBhG;AAED,wBAAgB,0BAA0B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAE/E;AAED,wBAAgB,wBAAwB,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAOhG;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG7E;AA8CD,wBAAsB,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CA2JzH"}
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"AAQA,OAAO,EAAmC,KAAK,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAKvF,eAAO,MAAM,qBAAqB,mCAAmC,CAAC;AAEtE,eAAO,MAAM,yBAAyB,iCAAiC,CAAC;AACxE,eAAO,MAAM,6BAA6B,qCAAqC,CAAC;AAChF,eAAO,MAAM,8BAA8B,sCAAsC,CAAC;AAQlF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,KAAK,8BAA8B,GAAG;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC,CAAC;AAEF,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,kBAAkB,IAAI,WAAW,GAAG,IAAI,CAWvD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAI5D;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAO1C;AAED,wBAAgB,kCAAkC,CAChD,OAAO,GAAE,8BAAmC,GAC3C,MAAM,CAYR;AA0CD,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,8BAAmC,GAAG,MAAM,CAWhG;AAED,wBAAgB,0BAA0B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAE/E;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU7F;AAED,wBAAgB,wBAAwB,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAOhG;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAG7E;AA8DD,wBAAsB,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAyKzH"}
package/dist/cli/index.js CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  CLI_COMMANDS,
4
4
  CLI_COMMAND_HELP_DETAILS,
5
5
  DEFAULT_CLICK_TRANSPORT_TIMEOUT_MS,
6
+ DEFAULT_DAEMON_STATUS_FETCH_OPTIONS,
6
7
  DEFAULT_DIALOG_TRANSPORT_TIMEOUT_MS,
7
8
  DEFAULT_REVIEW_TRANSPORT_TIMEOUT_MS,
8
9
  DEFAULT_SCREENSHOT_TRANSPORT_TIMEOUT_MS,
@@ -19,6 +20,8 @@ import {
19
20
  VALID_FLAGS,
20
21
  buildAnnotateResult,
21
22
  callDaemon,
23
+ createDaemonStopHeaders,
24
+ createDisconnectedError,
22
25
  createOpenDevBrowserCore,
23
26
  createUsageError,
24
27
  extractExtension,
@@ -28,9 +31,9 @@ import {
28
31
  formatErrorPayload,
29
32
  generateSecureToken,
30
33
  getChromeUserDataRoots,
31
- getCurrentDaemonFingerprint,
32
34
  getExtensionPath,
33
35
  getProfileDirs,
36
+ isCurrentDaemonFingerprint,
34
37
  loadGlobalConfig,
35
38
  onboarding_metadata_default,
36
39
  readDaemonMetadata,
@@ -38,7 +41,7 @@ import {
38
41
  resolveExitCode,
39
42
  startDaemon,
40
43
  toCliError
41
- } from "../chunk-7U63PZ4W.js";
44
+ } from "../chunk-GTTYIAI7.js";
42
45
  import "../chunk-STGGGVYT.js";
43
46
  import {
44
47
  createNoOpSkillRemovalResult,
@@ -71,7 +74,7 @@ import {
71
74
  setDefaultLogSink,
72
75
  stderrSink,
73
76
  summarizePrimaryProviderIssue
74
- } from "../chunk-Z6ENAZUN.js";
77
+ } from "../chunk-AVQL6WAS.js";
75
78
  import "../chunk-FUSXMW3G.js";
76
79
 
77
80
  // src/cli/args.ts
@@ -1526,7 +1529,15 @@ async function runNativeCommand(args) {
1526
1529
  // src/cli/commands/serve.ts
1527
1530
  var daemonHandle = null;
1528
1531
  var PS_MAX_BUFFER = 8 * 1024 * 1024;
1532
+ var DAEMON_SHUTDOWN_POLL_ATTEMPTS = 10;
1533
+ var DAEMON_SHUTDOWN_POLL_DELAY_MS = 100;
1534
+ var DAEMON_SHUTDOWN_STATUS_TIMEOUT_MS = 250;
1535
+ var DAEMON_STOP_TIMEOUT_MS = 1e3;
1536
+ var MIN_PORT = 1;
1537
+ var MAX_PORT = 65535;
1529
1538
  var SERVE_COMMAND_PATTERN = /(?:^|\s)(?:\S*[\\/])?(?:opendevbrowser|dist[\\/]+cli[\\/]+index\.js)(?=\s|$).*?\bserve\b/;
1539
+ var SERVE_PORT_SPLIT_PATTERN = /(?:^|\s)--port\s+(\d+)(?=\s|$)/;
1540
+ var SERVE_PORT_EQUALS_PATTERN = /(?:^|\s)--port=(\d+)(?=\s|$)/;
1530
1541
  var SERVE_STOP_PATTERN = /(?:^|\s)--stop(?:\s|$)/;
1531
1542
  var CURRENT_UID = typeof process.getuid === "function" ? process.getuid() : null;
1532
1543
  var CURRENT_EXECUTABLE = process.execPath;
@@ -1545,29 +1556,6 @@ async function resolveExistingDaemon(port, tokens) {
1545
1556
  function isPositivePid(value) {
1546
1557
  return typeof value === "number" && Number.isInteger(value) && value > 0;
1547
1558
  }
1548
- function rememberStalePid(staleDaemonPids, pid) {
1549
- if (isPositivePid(pid)) {
1550
- staleDaemonPids.add(pid);
1551
- }
1552
- }
1553
- async function stopDaemonOnPort(port, token) {
1554
- try {
1555
- const response = await fetchWithTimeout(`http://127.0.0.1:${port}/stop`, {
1556
- method: "POST",
1557
- headers: { Authorization: `Bearer ${token}` }
1558
- });
1559
- return response.ok;
1560
- } catch {
1561
- return false;
1562
- }
1563
- }
1564
- async function stopStaleDaemon(port, daemon, staleDaemonPids) {
1565
- rememberStalePid(staleDaemonPids, daemon.status.pid);
1566
- const stopped = await stopDaemonOnPort(port, daemon.token);
1567
- if (!stopped && isPositivePid(daemon.status.pid)) {
1568
- terminateProcess(daemon.status.pid);
1569
- }
1570
- }
1571
1559
  function parseServeArgs(rawArgs) {
1572
1560
  const parsed = { stop: false };
1573
1561
  for (let i = 0; i < rawArgs.length; i += 1) {
@@ -1581,7 +1569,7 @@ function parseServeArgs(rawArgs) {
1581
1569
  if (!value) {
1582
1570
  throw createUsageError("Missing value for --port");
1583
1571
  }
1584
- parsed.port = parseNumberFlag(value, "--port", { min: 1, max: 65535 });
1572
+ parsed.port = parseNumberFlag(value, "--port", { min: MIN_PORT, max: MAX_PORT });
1585
1573
  i += 1;
1586
1574
  continue;
1587
1575
  }
@@ -1590,7 +1578,7 @@ function parseServeArgs(rawArgs) {
1590
1578
  if (!value) {
1591
1579
  throw createUsageError("Missing value for --port");
1592
1580
  }
1593
- parsed.port = parseNumberFlag(value, "--port", { min: 1, max: 65535 });
1581
+ parsed.port = parseNumberFlag(value, "--port", { min: MIN_PORT, max: MAX_PORT });
1594
1582
  continue;
1595
1583
  }
1596
1584
  if (arg === "--token") {
@@ -1638,6 +1626,14 @@ function parseServeProcessSnapshot(line) {
1638
1626
  command
1639
1627
  };
1640
1628
  }
1629
+ function parseServeCommandPort(command) {
1630
+ const rawPort = command.match(SERVE_PORT_EQUALS_PATTERN)?.[1] ?? command.match(SERVE_PORT_SPLIT_PATTERN)?.[1];
1631
+ if (!rawPort) {
1632
+ return null;
1633
+ }
1634
+ const port = Number.parseInt(rawPort, 10);
1635
+ return Number.isInteger(port) && port >= MIN_PORT && port <= MAX_PORT ? port : null;
1636
+ }
1641
1637
  function listServeProcessSnapshots() {
1642
1638
  const result = spawnSync("ps", ["-axww", "-o", "pid=,uid=,command="], {
1643
1639
  encoding: "utf-8",
@@ -1660,6 +1656,9 @@ function isCurrentExecutableServeProcess(snapshot) {
1660
1656
  }
1661
1657
  return !SERVE_STOP_PATTERN.test(snapshot.command);
1662
1658
  }
1659
+ function isRequestedPortServeProcess(snapshot, requestedPort) {
1660
+ return isCurrentExecutableServeProcess(snapshot) && parseServeCommandPort(snapshot.command) === requestedPort;
1661
+ }
1663
1662
  function terminateProcess(pid) {
1664
1663
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid || pid === process.ppid) {
1665
1664
  return false;
@@ -1675,9 +1674,9 @@ function terminateProcess(pid) {
1675
1674
  }
1676
1675
  return true;
1677
1676
  }
1678
- function cleanupCompetingServeProcesses(keepPid) {
1677
+ function cleanupCompetingServeProcesses(requestedPort, keepPid) {
1679
1678
  const candidates = listServeProcessSnapshots().filter((snapshot) => {
1680
- if (!isCurrentExecutableServeProcess(snapshot)) {
1679
+ if (!isRequestedPortServeProcess(snapshot, requestedPort)) {
1681
1680
  return false;
1682
1681
  }
1683
1682
  if (snapshot.pid === process.pid || snapshot.pid === process.ppid) {
@@ -1699,6 +1698,85 @@ function cleanupCompetingServeProcesses(keepPid) {
1699
1698
  }
1700
1699
  return clearedPids;
1701
1700
  }
1701
+ function terminateServeProcessByPid(pid) {
1702
+ if (!isPositivePid(pid)) {
1703
+ return false;
1704
+ }
1705
+ const snapshot = listServeProcessSnapshots().find((item) => item.pid === pid);
1706
+ return snapshot ? isCurrentExecutableServeProcess(snapshot) && terminateProcess(pid) : false;
1707
+ }
1708
+ function buildStaleStopMessage(metadata) {
1709
+ const pid = isPositivePid(metadata.pid) ? ` pid=${metadata.pid}` : "";
1710
+ return `Daemon rejected stale stop request for 127.0.0.1:${metadata.port}${pid}. Run \`opendevbrowser status --daemon\` to inspect the active daemon, then restart from the current install if needed.`;
1711
+ }
1712
+ function buildProtectedMismatchMessage(port, status) {
1713
+ return `Daemon on 127.0.0.1:${port} pid=${status.pid} is protected by a different opendevbrowser build. Run \`opendevbrowser status --daemon\` to inspect it, then restart from the current install.`;
1714
+ }
1715
+ async function waitForDaemonShutdown(port, token) {
1716
+ for (let attempt = 0; attempt < DAEMON_SHUTDOWN_POLL_ATTEMPTS; attempt += 1) {
1717
+ const status = await fetchDaemonStatus(port, token, { timeoutMs: DAEMON_SHUTDOWN_STATUS_TIMEOUT_MS });
1718
+ if (!status?.ok) {
1719
+ return true;
1720
+ }
1721
+ await new Promise((resolve5) => setTimeout(resolve5, DAEMON_SHUTDOWN_POLL_DELAY_MS));
1722
+ }
1723
+ return false;
1724
+ }
1725
+ async function stopMismatchedDaemon(port, daemon) {
1726
+ let response;
1727
+ try {
1728
+ response = await fetchWithTimeout(`http://127.0.0.1:${port}/stop`, {
1729
+ method: "POST",
1730
+ headers: createDaemonStopHeaders(daemon.token, "serve.upgrade")
1731
+ }, DAEMON_STOP_TIMEOUT_MS);
1732
+ } catch (error) {
1733
+ const status = await fetchDaemonStatus(port, daemon.token, {
1734
+ timeoutMs: DAEMON_SHUTDOWN_STATUS_TIMEOUT_MS
1735
+ });
1736
+ if (!status?.ok) {
1737
+ return null;
1738
+ }
1739
+ const message = error instanceof Error ? error.message : String(error);
1740
+ return `Failed to stop mismatched daemon on 127.0.0.1:${port}: ${message}.`;
1741
+ }
1742
+ if (response.status === 409) {
1743
+ return buildProtectedMismatchMessage(port, daemon.status);
1744
+ }
1745
+ if (!response.ok) {
1746
+ return `Failed to stop mismatched daemon on 127.0.0.1:${port}: stop returned ${response.status}.`;
1747
+ }
1748
+ if (await waitForDaemonShutdown(port, daemon.token)) {
1749
+ return null;
1750
+ }
1751
+ if (terminateServeProcessByPid(daemon.status.pid)) {
1752
+ return null;
1753
+ }
1754
+ return `Timed out waiting for mismatched daemon on 127.0.0.1:${port} to stop.`;
1755
+ }
1756
+ async function prepareExistingDaemon(port, daemon) {
1757
+ if (isCurrentDaemonFingerprint(daemon.status.fingerprint)) {
1758
+ return null;
1759
+ }
1760
+ return await stopMismatchedDaemon(port, daemon);
1761
+ }
1762
+ function buildAlreadyRunningResult(port, status, fallbackRelayPort, clearedCount) {
1763
+ const relayPort = status.relay.port ?? fallbackRelayPort;
1764
+ const staleNote = clearedCount > 0 ? `
1765
+ Cleared ${clearedCount} stale daemon process${clearedCount === 1 ? "" : "es"}.` : "";
1766
+ return {
1767
+ success: true,
1768
+ message: `Daemon already running on 127.0.0.1:${port} (pid=${status.pid}, relay ${relayPort}).${staleNote}`,
1769
+ data: {
1770
+ port,
1771
+ pid: status.pid,
1772
+ relayPort,
1773
+ alreadyRunning: true,
1774
+ staleDaemonsCleared: clearedCount,
1775
+ relay: status.relay
1776
+ },
1777
+ exitCode: null
1778
+ };
1779
+ }
1702
1780
  async function runServe(args) {
1703
1781
  const serveArgs = parseServeArgs(args.rawArgs);
1704
1782
  if (serveArgs.stop) {
@@ -1714,8 +1792,11 @@ async function runServe(args) {
1714
1792
  try {
1715
1793
  const response = await fetchWithTimeout(`http://127.0.0.1:${metadata2.port}/stop`, {
1716
1794
  method: "POST",
1717
- headers: { Authorization: `Bearer ${metadata2.token}` }
1795
+ headers: createDaemonStopHeaders(metadata2.token, "serve.stop")
1718
1796
  });
1797
+ if (response.status === 409) {
1798
+ return { success: false, message: buildStaleStopMessage(metadata2), exitCode: EXIT_EXECUTION };
1799
+ }
1719
1800
  if (!response.ok) {
1720
1801
  throw new Error(`Stop failed (${response.status})`);
1721
1802
  }
@@ -1730,34 +1811,23 @@ async function runServe(args) {
1730
1811
  const metadata = readDaemonMetadata();
1731
1812
  const metadataToken = metadata?.port === requestedPort ? metadata.token : void 0;
1732
1813
  const tokenCandidates = resolveTokenCandidates(serveArgs.token, metadataToken, config.daemonToken);
1733
- const currentFingerprint = getCurrentDaemonFingerprint();
1734
1814
  const existingDaemon = await resolveExistingDaemon(requestedPort, tokenCandidates);
1735
- const staleDaemonPids = new Set(cleanupCompetingServeProcesses(existingDaemon?.status.pid));
1815
+ const staleDaemonPids = /* @__PURE__ */ new Set();
1736
1816
  const staleCleared = () => staleDaemonPids.size;
1737
- let replacedStaleFingerprint = false;
1738
1817
  if (existingDaemon) {
1739
- const fingerprintMatches = existingDaemon.status.fingerprint === currentFingerprint;
1740
- if (fingerprintMatches) {
1741
- const relayPort = existingDaemon.status.relay.port ?? config.relayPort;
1742
- const clearedCount2 = staleCleared();
1743
- const staleNote2 = clearedCount2 > 0 ? `
1744
- Cleared ${clearedCount2} stale daemon process${clearedCount2 === 1 ? "" : "es"}.` : "";
1745
- return {
1746
- success: true,
1747
- message: `Daemon already running on 127.0.0.1:${requestedPort} (pid=${existingDaemon.status.pid}, relay ${relayPort}).${staleNote2}`,
1748
- data: {
1749
- port: requestedPort,
1750
- pid: existingDaemon.status.pid,
1751
- relayPort,
1752
- alreadyRunning: true,
1753
- staleDaemonsCleared: clearedCount2,
1754
- relay: existingDaemon.status.relay
1755
- },
1756
- exitCode: null
1757
- };
1818
+ const mismatchMessage = await prepareExistingDaemon(requestedPort, existingDaemon);
1819
+ if (mismatchMessage) {
1820
+ return { success: false, message: mismatchMessage, exitCode: EXIT_EXECUTION };
1821
+ }
1822
+ if (isCurrentDaemonFingerprint(existingDaemon.status.fingerprint)) {
1823
+ for (const pid of cleanupCompetingServeProcesses(requestedPort, existingDaemon.status.pid)) {
1824
+ staleDaemonPids.add(pid);
1825
+ }
1826
+ return buildAlreadyRunningResult(requestedPort, existingDaemon.status, config.relayPort, staleCleared());
1758
1827
  }
1759
- await stopStaleDaemon(requestedPort, existingDaemon, staleDaemonPids);
1760
- replacedStaleFingerprint = true;
1828
+ }
1829
+ for (const pid of cleanupCompetingServeProcesses(requestedPort)) {
1830
+ staleDaemonPids.add(pid);
1761
1831
  }
1762
1832
  let nativeStatus = getNativeStatusSnapshot();
1763
1833
  let nativeMessage = null;
@@ -1800,35 +1870,17 @@ Cleared ${clearedCount2} stale daemon process${clearedCount2 === 1 ? "" : "es"}.
1800
1870
  }
1801
1871
  const runningDaemon = await resolveExistingDaemon(requestedPort, tokenCandidates);
1802
1872
  if (runningDaemon) {
1803
- const fingerprintMatches = runningDaemon.status.fingerprint === currentFingerprint;
1804
- if (fingerprintMatches) {
1805
- const relayPort = runningDaemon.status.relay.port ?? config.relayPort;
1806
- const clearedCount2 = staleCleared();
1807
- const staleNote2 = clearedCount2 > 0 ? `
1808
- Cleared ${clearedCount2} stale daemon process${clearedCount2 === 1 ? "" : "es"}.` : "";
1809
- return {
1810
- success: true,
1811
- message: `Daemon already running on 127.0.0.1:${requestedPort} (pid=${runningDaemon.status.pid}, relay ${relayPort}).${staleNote2}`,
1812
- data: {
1813
- port: requestedPort,
1814
- pid: runningDaemon.status.pid,
1815
- relayPort,
1816
- alreadyRunning: true,
1817
- staleDaemonsCleared: clearedCount2,
1818
- relay: runningDaemon.status.relay
1819
- },
1820
- exitCode: null
1821
- };
1873
+ const mismatchMessage = await prepareExistingDaemon(requestedPort, runningDaemon);
1874
+ if (mismatchMessage) {
1875
+ return { success: false, message: mismatchMessage, exitCode: EXIT_EXECUTION };
1822
1876
  }
1823
- await stopStaleDaemon(requestedPort, runningDaemon, staleDaemonPids);
1824
- replacedStaleFingerprint = true;
1825
- if (attempt === 0) {
1826
- continue;
1877
+ if (isCurrentDaemonFingerprint(runningDaemon.status.fingerprint)) {
1878
+ return buildAlreadyRunningResult(requestedPort, runningDaemon.status, config.relayPort, staleCleared());
1827
1879
  }
1828
1880
  }
1829
1881
  if (attempt === 0) {
1830
1882
  let clearedNewPid = false;
1831
- for (const pid of cleanupCompetingServeProcesses()) {
1883
+ for (const pid of cleanupCompetingServeProcesses(requestedPort)) {
1832
1884
  const previousSize = staleDaemonPids.size;
1833
1885
  staleDaemonPids.add(pid);
1834
1886
  if (staleDaemonPids.size > previousSize) {
@@ -1863,9 +1915,8 @@ Cleared ${clearedCount2} stale daemon process${clearedCount2 === 1 ? "" : "es"}.
1863
1915
  const clearedCount = staleCleared();
1864
1916
  const staleNote = clearedCount > 0 ? `
1865
1917
  Cleared ${clearedCount} stale daemon process${clearedCount === 1 ? "" : "es"}.` : "";
1866
- const fingerprintNote = replacedStaleFingerprint ? "\nReplaced stale daemon fingerprint." : "";
1867
1918
  const message = nativeMessage ? `${baseMessage}
1868
- ${nativeMessage}${fingerprintNote}${staleNote}` : `${baseMessage}${fingerprintNote}${staleNote}`;
1919
+ ${nativeMessage}${staleNote}` : `${baseMessage}${staleNote}`;
1869
1920
  return {
1870
1921
  success: true,
1871
1922
  message,
@@ -2433,17 +2484,40 @@ var parseDaemonArgs = (rawArgs) => {
2433
2484
  var stopDaemonIfRunning = async () => {
2434
2485
  const metadata = readDaemonMetadata();
2435
2486
  if (!metadata) {
2436
- return false;
2487
+ return { outcome: "not_running" };
2437
2488
  }
2438
2489
  try {
2439
2490
  const response = await fetchWithTimeout(`http://127.0.0.1:${metadata.port}/stop`, {
2440
2491
  method: "POST",
2441
- headers: { Authorization: `Bearer ${metadata.token}` }
2492
+ headers: createDaemonStopHeaders(metadata.token, "daemon.uninstall")
2442
2493
  });
2443
- return response.ok;
2444
- } catch {
2494
+ if (response.status === 409) {
2495
+ return { outcome: "fingerprint_rejected", pid: metadata.pid, port: metadata.port };
2496
+ }
2497
+ return response.ok ? { outcome: "stopped", pid: metadata.pid, port: metadata.port } : { outcome: "failed", pid: metadata.pid, port: metadata.port, status: response.status };
2498
+ } catch (error) {
2499
+ return {
2500
+ outcome: "failed",
2501
+ pid: metadata.pid,
2502
+ port: metadata.port,
2503
+ error: error instanceof Error ? error.message : String(error)
2504
+ };
2505
+ }
2506
+ };
2507
+ var buildStopFailureMessage = (stop) => {
2508
+ const target = stop.port ? `127.0.0.1:${stop.port}` : "recorded daemon";
2509
+ const pid = stop.pid ? ` pid=${stop.pid}` : "";
2510
+ if (stop.outcome === "fingerprint_rejected") {
2511
+ return `Daemon autostart removed, but the running daemon at ${target}${pid} rejected the stop request as stale. Run \`opendevbrowser status --daemon\` to inspect it and restart from the current install if needed.`;
2512
+ }
2513
+ const reason = stop.error ?? (stop.status ? `HTTP ${stop.status}` : "unknown error");
2514
+ return `Daemon autostart removed, but stopping ${target}${pid} failed (${reason}).`;
2515
+ };
2516
+ var shouldFailUninstallStop = (stop) => {
2517
+ if (stop.outcome === "stopped" || stop.outcome === "not_running") {
2445
2518
  return false;
2446
2519
  }
2520
+ return true;
2447
2521
  };
2448
2522
  var formatReason = (reason) => {
2449
2523
  return reason ? reason.replace(/_/g, " ") : "unknown reason";
@@ -2518,7 +2592,15 @@ async function runDaemonCommand(args) {
2518
2592
  exitCode: EXIT_EXECUTION
2519
2593
  };
2520
2594
  }
2521
- await stopDaemonIfRunning();
2595
+ const stop = await stopDaemonIfRunning();
2596
+ if (shouldFailUninstallStop(stop)) {
2597
+ return {
2598
+ success: false,
2599
+ message: buildStopFailureMessage(stop),
2600
+ data: { ...result, stop },
2601
+ exitCode: EXIT_EXECUTION
2602
+ };
2603
+ }
2522
2604
  return {
2523
2605
  success: true,
2524
2606
  message: `Daemon autostart removed (${result.platform}).`,
@@ -2526,7 +2608,7 @@ async function runDaemonCommand(args) {
2526
2608
  };
2527
2609
  }
2528
2610
  const autostart = getAutostartStatus();
2529
- const daemonStatus = await fetchDaemonStatusFromMetadata();
2611
+ const daemonStatus = await fetchDaemonStatusFromMetadata(void 0, DEFAULT_DAEMON_STATUS_FETCH_OPTIONS);
2530
2612
  const running = Boolean(daemonStatus);
2531
2613
  const message = buildStatusMessage(autostart, running);
2532
2614
  const data = {
@@ -3574,11 +3656,6 @@ async function runSessionStatus(args) {
3574
3656
  }
3575
3657
 
3576
3658
  // src/cli/commands/status.ts
3577
- var DAEMON_STATUS_READ_OPTIONS = {
3578
- timeoutMs: 5e3,
3579
- retryAttempts: 5,
3580
- retryDelayMs: 250
3581
- };
3582
3659
  var parseStatusArgs2 = (rawArgs) => {
3583
3660
  const parsed = { daemon: false };
3584
3661
  for (let i = 0; i < rawArgs.length; i += 1) {
@@ -3619,21 +3696,23 @@ async function runStatus(args) {
3619
3696
  exitCode: assessment.exitCode ?? void 0
3620
3697
  };
3621
3698
  }
3622
- const daemonStatus = await fetchDaemonStatusFromMetadata(void 0, DAEMON_STATUS_READ_OPTIONS);
3699
+ const daemonStatus = await fetchDaemonStatusFromMetadata(void 0, DEFAULT_DAEMON_STATUS_FETCH_OPTIONS);
3623
3700
  if (!daemonStatus) {
3624
- throw createUsageError("Daemon not running. Start with `opendevbrowser serve`.");
3701
+ throw createDisconnectedError("Daemon not running. Start with `opendevbrowser serve`.");
3625
3702
  }
3626
3703
  const nativeStatus = getNativeStatusSnapshot();
3627
3704
  const nativeAssessment = assessNativeStatus(nativeStatus);
3705
+ const fingerprintLine = daemonStatus.fingerprintCurrent === false ? "Daemon fingerprint: mismatch with current build" : "Daemon fingerprint: current";
3628
3706
  const baseLines = [
3629
3707
  `Daemon OK (pid=${daemonStatus.pid})`,
3708
+ fingerprintLine,
3630
3709
  `Relay: port=${daemonStatus.relay.port ?? "n/a"} ext=${daemonStatus.relay.extensionConnected ? "on" : "off"} handshake=${daemonStatus.relay.extensionHandshakeComplete ? "on" : "off"} cdp=${daemonStatus.relay.cdpConnected ? "on" : "off"} annotate=${daemonStatus.relay.annotationConnected ? "on" : "off"} ops=${daemonStatus.relay.opsConnected ? "on" : "off"} canvas=${daemonStatus.relay.canvasConnected ? "on" : "off"} pairing=${daemonStatus.relay.pairingRequired ? "on" : "off"} health=${daemonStatus.relay.health?.reason ?? "n/a"}`,
3631
3710
  `Native: ${nativeAssessment.summary}`,
3632
3711
  daemonStatus.relay.lastHandshakeError ? `Relay last handshake error: ${daemonStatus.relay.lastHandshakeError.code} (${daemonStatus.relay.lastHandshakeError.message})` : "Relay last handshake error: none",
3633
3712
  "Legend: ext=extension websocket, handshake=extension handshake, cdp=active /cdp client, annotate=annotation channel, ops=ops clients, canvas=canvas clients, pairing=token required, health=relay status"
3634
3713
  ];
3635
3714
  if (!nativeAssessment.success) {
3636
- baseLines.splice(3, 0, `Native detail: ${nativeAssessment.message}`);
3715
+ baseLines.splice(4, 0, `Native detail: ${nativeAssessment.message}`);
3637
3716
  }
3638
3717
  const baseMessage = baseLines.join("\n");
3639
3718
  const message = daemon || args.outputFormat !== "text" ? baseMessage : [
@@ -7415,7 +7494,7 @@ async function runInspiredesignCommand(args) {
7415
7494
  // package.json
7416
7495
  var package_default = {
7417
7496
  name: "opendevbrowser",
7418
- version: "0.0.25",
7497
+ version: "0.0.26",
7419
7498
  description: "Browser automation runtime with snapshot-refs-actions, browser replay screencasts, public read-only desktop observation, and browser-scoped computer-use orchestration",
7420
7499
  type: "module",
7421
7500
  main: "dist/index.js",