@orkestrel/browser 0.0.21 → 0.0.22

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.
@@ -448,9 +448,9 @@ export declare type BrowserLaunchFunction = (options: BrowserOptions) => Browser
448
448
  * the Model Context Protocol on stdio, and launches Chromium on the first tool call.
449
449
  *
450
450
  * @remarks
451
- * The server's own manager holds one dispatcher per name of the vocabulary — `look`, `read`,
451
+ * The server's own manager holds one dispatcher per name of the vocabulary — `look`, `read`, `plain`,
452
452
  * `click`, `type`, `press`, `navigate`, `wait`, `dialog`, `tabs`, `switch`, `record`, `save`,
453
- * `journeys`, `edit`, and `replay` — each carrying the description, parameters, and annotations
453
+ * `journeys`, `edit`, `replay`, and `forget` — each carrying the description, parameters, and annotations
454
454
  * `BROWSER_TOOL_COPY` gives, so `tools/list` answers before Chromium starts and with Chromium
455
455
  * absent. After the launch, a tool the toolset's manager adds under another name, such as a page
456
456
  * tool it adopts, is mirrored as a dispatcher with that tool's definition, and the mirror is
@@ -448,9 +448,9 @@ export declare type BrowserLaunchFunction = (options: BrowserOptions) => Browser
448
448
  * the Model Context Protocol on stdio, and launches Chromium on the first tool call.
449
449
  *
450
450
  * @remarks
451
- * The server's own manager holds one dispatcher per name of the vocabulary — `look`, `read`,
451
+ * The server's own manager holds one dispatcher per name of the vocabulary — `look`, `read`, `plain`,
452
452
  * `click`, `type`, `press`, `navigate`, `wait`, `dialog`, `tabs`, `switch`, `record`, `save`,
453
- * `journeys`, `edit`, and `replay` — each carrying the description, parameters, and annotations
453
+ * `journeys`, `edit`, `replay`, and `forget` — each carrying the description, parameters, and annotations
454
454
  * `BROWSER_TOOL_COPY` gives, so `tools/list` answers before Chromium starts and with Chromium
455
455
  * absent. After the launch, a tool the toolset's manager adds under another name, such as a page
456
456
  * tool it adopts, is mirrored as a dispatcher with that tool's definition, and the mirror is
@@ -867,7 +867,7 @@ var FileBrowserWriter = class {
867
867
  };
868
868
  //#endregion
869
869
  //#region package.json
870
- var version = "0.0.21";
870
+ var version = "0.0.22";
871
871
  //#endregion
872
872
  //#region src/server/BrowserMCPServer.ts
873
873
  /**
@@ -875,9 +875,9 @@ var version = "0.0.21";
875
875
  * the Model Context Protocol on stdio, and launches Chromium on the first tool call.
876
876
  *
877
877
  * @remarks
878
- * The server's own manager holds one dispatcher per name of the vocabulary — `look`, `read`,
878
+ * The server's own manager holds one dispatcher per name of the vocabulary — `look`, `read`, `plain`,
879
879
  * `click`, `type`, `press`, `navigate`, `wait`, `dialog`, `tabs`, `switch`, `record`, `save`,
880
- * `journeys`, `edit`, and `replay` — each carrying the description, parameters, and annotations
880
+ * `journeys`, `edit`, `replay`, and `forget` — each carrying the description, parameters, and annotations
881
881
  * `BROWSER_TOOL_COPY` gives, so `tools/list` answers before Chromium starts and with Chromium
882
882
  * absent. After the launch, a tool the toolset's manager adds under another name, such as a page
883
883
  * tool it adopts, is mirrored as a dispatcher with that tool's definition, and the mirror is
@@ -1227,7 +1227,13 @@ var FileBrowserStore = class {
1227
1227
  await this.check(path, options);
1228
1228
  await this.check(temporary, options);
1229
1229
  options?.signal?.throwIfAborted();
1230
- await rename(temporary, path);
1230
+ try {
1231
+ await rename(temporary, path);
1232
+ } catch (error) {
1233
+ const target = await lstat(path).catch(() => void 0);
1234
+ if (error instanceof Error && "code" in error && (error.code === "EISDIR" || error.code === "EPERM") && target?.isDirectory()) throw new BrowserError(`Cannot replace directory: ${path}`, "BROWSER_JOURNEY_FILE", { path });
1235
+ throw error;
1236
+ }
1231
1237
  owned = false;
1232
1238
  } catch (error) {
1233
1239
  options?.signal?.throwIfAborted();
@@ -1428,7 +1434,14 @@ var FileBrowserStore = class {
1428
1434
  try {
1429
1435
  await rmdir(path);
1430
1436
  } catch (error) {
1431
- if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTEMPTY")) return;
1437
+ if (error instanceof Error && "code" in error) {
1438
+ if (error.code === "ENOTEMPTY") return;
1439
+ if (error.code === "ENOENT" || error.code === "EPERM") try {
1440
+ if ((await lstat(path)).isDirectory()) return;
1441
+ } catch (cause) {
1442
+ if (cause instanceof Error && "code" in cause && cause.code === "ENOENT") return;
1443
+ }
1444
+ }
1432
1445
  throw new BrowserError(`Cannot remove lock directory: ${path}`, "BROWSER_JOURNEY_ACCESS", { path });
1433
1446
  }
1434
1447
  }
@@ -2353,6 +2366,7 @@ var Browser = class {
2353
2366
  const process = this.#process;
2354
2367
  if (process !== void 0) {
2355
2368
  if (!await this.#waitForTerminationWithin(process, 3e3)) await this.#terminate(process);
2369
+ await this.#closeProcessPipe(process);
2356
2370
  }
2357
2371
  this.#process = void 0;
2358
2372
  this.#servingPid = void 0;
@@ -2524,12 +2538,23 @@ var Browser = class {
2524
2538
  return results[0] && (results[1] === true || final && results[1] === void 0);
2525
2539
  }
2526
2540
  async #terminate(process) {
2527
- if (process === void 0 || (process.exitCode !== null || process.signalCode !== null) && this.#inspectRemainder(process) === false) return;
2528
- if (this.#signalProcess(process, "SIGTERM") === false) return;
2529
- if (await this.#waitForTerminationWithin(process, 3e3)) return;
2530
- if (this.#signalProcess(process, "SIGKILL") === false) return;
2531
- if (await this.#waitForTerminationWithin(process, 3e3, true)) return;
2532
- throw new BrowserConnectionError("Browser process did not exit after SIGKILL", { pid: this.#servingPid ?? process.pid });
2541
+ try {
2542
+ if (process === void 0 || (process.exitCode !== null || process.signalCode !== null) && this.#inspectRemainder(process) === false) return;
2543
+ if (this.#signalProcess(process, "SIGTERM") === false) return;
2544
+ if (await this.#waitForTerminationWithin(process, 3e3)) return;
2545
+ if (this.#signalProcess(process, "SIGKILL") === false) return;
2546
+ if (await this.#waitForTerminationWithin(process, 3e3, true)) return;
2547
+ throw new BrowserConnectionError("Browser process did not exit after SIGKILL", { pid: this.#servingPid ?? process.pid });
2548
+ } finally {
2549
+ await this.#closeProcessPipe(process);
2550
+ }
2551
+ }
2552
+ async #closeProcessPipe(process) {
2553
+ const stream = process?.stderr;
2554
+ if (stream === void 0 || stream === null || stream.closed) return;
2555
+ const closed = once(stream, "close");
2556
+ stream.destroy();
2557
+ await closed;
2533
2558
  }
2534
2559
  #finish() {
2535
2560
  this.#unbindTransport();