@53able/pi-agent-browser 0.4.2 → 0.6.0

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.ja-JP.md CHANGED
@@ -177,7 +177,9 @@ https://example.com をブラウザ経由で読み、outputs/browser/example.md
177
177
  agent-browser doctor
178
178
  ```
179
179
 
180
- または Pi に `agent_browser_doctor` を実行させてください。
180
+ または Pi に `agent_browser_doctor` を実行させてください。インストール、Chrome、daemon、security、provider、network、launch test を確認します。`agent_browser_login_handoff` で作ったセッションでまだ開いているログインブラウザも報告し、期限切れ追跡データを自動削除します。
181
+
182
+ `agent_browser_login_handoff` で作ったセッションの中で、まだ生存しているログインブラウザがあれば、`agent_browser_doctor` がそれらを報告します(セッション名、プロセス ID、デバッグポート、最後に開いていた URL を表示)。終わったら各セッションに対して `agent_browser_close` を呼んでください — これらのセッションはブラウザを閉じるまでリモートデバッグポートが開いたままです。期限切れエントリ(実行中でなくなったプロセスの追跡データ)は、何も通知することなく自動削除されます。`agent_browser_login_handoff` 自身も、成功メッセージの中でほかに生存中のログインブラウザ(セッション名とプロセス ID)を教えてくれるので、`agent_browser_doctor` を別途呼ばなくても気づけます。
181
183
 
182
184
  よくある修正:
183
185
 
package/README.md CHANGED
@@ -179,7 +179,9 @@ Run:
179
179
  agent-browser doctor
180
180
  ```
181
181
 
182
- Or ask Pi to run `agent_browser_doctor`.
182
+ Or ask Pi to run `agent_browser_doctor`. This verifies installation, Chrome, daemon, security, providers, network, and launch tests. It also reports any live login-handoff browsers left open and cleans up stale tracking entries.
183
+
184
+ If you have sessions created with `agent_browser_login_handoff`, `agent_browser_doctor` will report any that still have live login browsers running, showing the session name, process ID, debugging port, and last known URL. Call `agent_browser_close` for each session when done — these hold an open remote-debugging port until closed. Stale entries (tracking data for processes no longer running) are cleaned up automatically with no notification. `agent_browser_login_handoff` itself also names any *other* sessions still running a live login browser in its success message, so you notice without a separate `agent_browser_doctor` call.
183
185
 
184
186
  Common fixes:
185
187
 
package/index.ts CHANGED
@@ -275,6 +275,15 @@ function killPidBestEffort(pid?: number): void {
275
275
  try { process.kill(pid); } catch { /* already gone / not ours */ }
276
276
  }
277
277
 
278
+ function isPidAlive(pid: number): boolean {
279
+ try {
280
+ process.kill(pid, 0); // signal 0 = no-op existence/permission check, does not actually kill
281
+ return true;
282
+ } catch (err) {
283
+ return (err as NodeJS.ErrnoException).code !== "ESRCH"; // ESRCH = no such process (dead); any other error (e.g. EPERM) means it exists
284
+ }
285
+ }
286
+
278
287
  function abortableDelay(ms: number, signal?: AbortSignal): Promise<void> {
279
288
  return new Promise((resolveDelay) => {
280
289
  if (signal?.aborted) {
@@ -956,6 +965,18 @@ export default function agentBrowserExtension(pi: ExtensionAPI) {
956
965
  loginDebugPort: port,
957
966
  });
958
967
 
968
+ // Surface other still-live login browsers so they don't go unnoticed between
969
+ // agent_browser_doctor runs (same isPidAlive/cleanup semantics as doctor).
970
+ const otherLiveBrowsers: { session: string; pid: number }[] = [];
971
+ for (const [otherSession, otherState] of Object.entries(await readSessionStates(ctx.cwd))) {
972
+ if (otherSession === session || !otherState.loginBrowserPid) continue;
973
+ if (!isPidAlive(otherState.loginBrowserPid)) {
974
+ await writeSessionState(ctx.cwd, otherSession, { clearLoginBrowserPid: true });
975
+ continue;
976
+ }
977
+ otherLiveBrowsers.push({ session: otherSession === DEFAULT_SESSION_KEY ? "(default)" : otherSession, pid: otherState.loginBrowserPid });
978
+ }
979
+
959
980
  const multiTab = /\bt2\b/.test(tabResult.stdout) || (tabResult.stdout.match(/\[t\d+\]/g)?.length ?? 0) > 1;
960
981
  return {
961
982
  content: [{
@@ -966,6 +987,9 @@ export default function agentBrowserExtension(pi: ExtensionAPI) {
966
987
  multiTab ? `Note: multiple tabs are open — verify the active tab before acting:\n${tabResult.stdout.trim()}` : undefined,
967
988
  "The session drives this real browser window directly. Take a fresh agent_browser_snapshot before continuing.",
968
989
  "This login browser has an open remote-debugging port and will stay open until agent_browser_close is called for this session (or the window is closed manually).",
990
+ otherLiveBrowsers.length > 0
991
+ ? `Also still open: ${otherLiveBrowsers.map((b) => `${b.session} (pid ${b.pid})`).join(", ")}. Call agent_browser_close for each when done, or run agent_browser_doctor for full details.`
992
+ : undefined,
969
993
  ].filter(Boolean).join("\n"),
970
994
  }],
971
995
  details: { ...result, artifactPaths: [] },
@@ -1052,15 +1076,43 @@ export default function agentBrowserExtension(pi: ExtensionAPI) {
1052
1076
  pi.registerTool({
1053
1077
  name: "agent_browser_doctor",
1054
1078
  label: "Agent Browser Doctor",
1055
- description: "Run agent-browser doctor to verify installation, Chrome, daemon, security, providers, network, and launch tests.",
1056
- promptSnippet: "Use agent_browser_doctor when browser automation fails or before relying on agent-browser in a workflow.",
1079
+ description: "Run agent-browser doctor to verify installation, Chrome, daemon, security, providers, network, and launch tests. Also reports and cleans up tracked login-handoff browsers (see agent_browser_login_handoff).",
1080
+ promptSnippet: "Use agent_browser_doctor when browser automation fails or before relying on agent-browser in a workflow. It also flags any live login-handoff browsers left open and cleans up stale tracking entries.",
1057
1081
  parameters: DoctorSchema,
1058
1082
  async execute(_id, rawParams, signal, onUpdate, ctx) {
1059
1083
  const params = rawParams as JsonObject;
1060
1084
  const args = ["doctor"];
1061
1085
  if (params.fix === true) args.push("--fix");
1062
1086
  const result = await runAgentBrowser(args, { signal, timeoutMs: params.timeoutMs as number | undefined, cwd: ctx.cwd, onUpdate });
1063
- return buildTextResult(result);
1087
+ const textResult = buildTextResult(result);
1088
+
1089
+ const states = await readSessionStates(ctx.cwd);
1090
+ const liveBrowsers: { session: string; pid: number; port: number | undefined; lastUrl?: string }[] = [];
1091
+ for (const [session, state] of Object.entries(states)) {
1092
+ if (!state.loginBrowserPid) continue;
1093
+ if (!isPidAlive(state.loginBrowserPid)) {
1094
+ await writeSessionState(ctx.cwd, session, { clearLoginBrowserPid: true });
1095
+ continue;
1096
+ }
1097
+ liveBrowsers.push({
1098
+ session: session === DEFAULT_SESSION_KEY ? "(default)" : session,
1099
+ pid: state.loginBrowserPid,
1100
+ port: state.loginDebugPort,
1101
+ lastUrl: state.lastUrl,
1102
+ });
1103
+ }
1104
+
1105
+ if (liveBrowsers.length > 0) {
1106
+ const lines = [
1107
+ "",
1108
+ "Live login browsers (from agent_browser_login_handoff) still open:",
1109
+ ...liveBrowsers.map((b) => `- ${b.session}: pid ${b.pid}, debug port ${b.port ?? "?"}${b.lastUrl ? `, last url ${b.lastUrl}` : ""}`),
1110
+ "Call agent_browser_close for each session when done — these hold an open remote-debugging port until closed.",
1111
+ ];
1112
+ textResult.content[0].text += lines.join("\n");
1113
+ }
1114
+
1115
+ return textResult;
1064
1116
  },
1065
1117
  });
1066
1118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@53able/pi-agent-browser",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "Typed Pi tools for browser automation, rendered-page context extraction, screenshots, and saved session state via agent-browser.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -64,6 +64,10 @@ After the human confirms login is complete, subsequent `agent_browser_open`, `ag
64
64
 
65
65
  **Security note:** The login browser's `--remote-debugging-port` remains open on localhost for as long as the session is alive. This gives any local process full browser control — the same caveat agent-browser's own docs give about `--remote-debugging-port`. Call `agent_browser_close` when done with a session that went through login handoff, rather than leaving it open indefinitely. `agent_browser_close` will terminate the tracked login Chrome process and clean up its debugging port.
66
66
 
67
+ Run `agent_browser_doctor` to see which sessions still have live login browsers open. It reports any that are still running (session name, process ID, debugging port, and last known URL) with a reminder to call `agent_browser_close`. Stale tracking entries for processes no longer running are cleaned up silently with no user notification.
68
+
69
+ `agent_browser_login_handoff` also surfaces this automatically: its success message names any *other* sessions that still have a live login browser open (session name and process ID), so you don't have to run `agent_browser_doctor` separately just to notice one was left open.
70
+
67
71
  Re-running `agent_browser_login_handoff` for the same session name will terminate any previous live login browser for that session before spawning a new one.
68
72
 
69
73
  ## Common examples