pi-chrome 0.15.22 → 0.15.24
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/CHANGELOG.md
CHANGED
|
@@ -2,8 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes to `pi-chrome`.
|
|
4
4
|
|
|
5
|
+
## 0.15.24 — 2026-05-16
|
|
6
|
+
|
|
7
|
+
- **Unload Chrome tools on lock.** `chrome_*` tools now deactivate when `/chrome revoke` runs or timed authorization expires, keeping the prompt/tool list small after Chrome control locks again.
|
|
8
|
+
|
|
9
|
+
## 0.15.23 — 2026-05-16
|
|
10
|
+
|
|
11
|
+
- **Attribution.** The 0.15.22 features below are pulled from Dani Bednarski's fork (`DaniBedz/pi-chrome`). Thank you, Dani.
|
|
12
|
+
|
|
5
13
|
## 0.15.22 — 2026-05-16
|
|
6
14
|
|
|
15
|
+
Features in this release are pulled from Dani Bednarski's fork (`DaniBedz/pi-chrome`). Thank you, Dani.
|
|
16
|
+
|
|
7
17
|
- **Earlier page-load capture.** Companion extension now injects console/network instrumentation at `document_start`, so initial React render errors and early API calls show up in `chrome_list_console_messages` / `chrome_list_network_requests`.
|
|
8
18
|
- **Quieter locked state.** Startup no longer shows a persistent Chrome bridge notification/status item before authorization; status bar appears only when Chrome control is authorized.
|
|
9
19
|
- **Lazy tool registration.** `chrome_*` tools and primer are registered only after `/chrome authorize`, reducing prompt/tool overhead while Chrome control is locked.
|
|
@@ -441,6 +441,28 @@ class ChromeProfileBridge {
|
|
|
441
441
|
const tabActionValues = ["list", "new", "activate", "close", "version"] as const;
|
|
442
442
|
const imageFormatValues = ["png", "jpeg"] as const;
|
|
443
443
|
const waitForValues = ["selector", "expression"] as const;
|
|
444
|
+
const CHROME_TOOL_NAMES = [
|
|
445
|
+
"chrome_launch",
|
|
446
|
+
"chrome_tab",
|
|
447
|
+
"chrome_snapshot",
|
|
448
|
+
"chrome_navigate",
|
|
449
|
+
"chrome_evaluate",
|
|
450
|
+
"chrome_click",
|
|
451
|
+
"chrome_type",
|
|
452
|
+
"chrome_fill",
|
|
453
|
+
"chrome_key",
|
|
454
|
+
"chrome_wait_for",
|
|
455
|
+
"chrome_list_console_messages",
|
|
456
|
+
"chrome_list_network_requests",
|
|
457
|
+
"chrome_get_network_request",
|
|
458
|
+
"chrome_screenshot",
|
|
459
|
+
"chrome_hover",
|
|
460
|
+
"chrome_drag",
|
|
461
|
+
"chrome_tap",
|
|
462
|
+
"chrome_scroll",
|
|
463
|
+
"chrome_upload_file",
|
|
464
|
+
] as const;
|
|
465
|
+
const CHROME_TOOL_NAME_SET = new Set<string>(CHROME_TOOL_NAMES);
|
|
444
466
|
|
|
445
467
|
function StringEnum<T extends readonly [string, ...string[]]>(values: T) {
|
|
446
468
|
return Type.Union(values.map((value) => Type.Literal(value)) as [ReturnType<typeof Type.Literal>, ...ReturnType<typeof Type.Literal>[]]);
|
|
@@ -464,6 +486,30 @@ export default function (pi: ExtensionAPI): void {
|
|
|
464
486
|
let backgroundDefault = false;
|
|
465
487
|
let chromeAuthorizedUntil: number | "indefinite" | undefined;
|
|
466
488
|
let chromeToolsRegistered = false;
|
|
489
|
+
let authExpiryTimer: NodeJS.Timeout | undefined;
|
|
490
|
+
|
|
491
|
+
const clearAuthExpiryTimer = (): void => {
|
|
492
|
+
if (!authExpiryTimer) return;
|
|
493
|
+
clearTimeout(authExpiryTimer);
|
|
494
|
+
authExpiryTimer = undefined;
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
const activeToolNamesWithoutChrome = (): string[] => pi.getActiveTools().filter((name) => !CHROME_TOOL_NAME_SET.has(name));
|
|
498
|
+
|
|
499
|
+
const activateChromeTools = (): void => {
|
|
500
|
+
registerChromeTools(pi);
|
|
501
|
+
pi.setActiveTools([...new Set([...pi.getActiveTools(), ...CHROME_TOOL_NAMES])]);
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
const deactivateChromeTools = (): void => {
|
|
505
|
+
pi.setActiveTools(activeToolNamesWithoutChrome());
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
const lockChromeControl = (): void => {
|
|
509
|
+
clearAuthExpiryTimer();
|
|
510
|
+
chromeAuthorizedUntil = undefined;
|
|
511
|
+
deactivateChromeTools();
|
|
512
|
+
};
|
|
467
513
|
|
|
468
514
|
const authSummary = (): string => {
|
|
469
515
|
if (chromeAuthorizedUntil === "indefinite") return "authorized indefinitely";
|
|
@@ -477,7 +523,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
477
523
|
const chromeControlAuthorized = (): boolean => {
|
|
478
524
|
if (chromeAuthorizedUntil === "indefinite") return true;
|
|
479
525
|
if (typeof chromeAuthorizedUntil === "number" && chromeAuthorizedUntil > Date.now()) return true;
|
|
480
|
-
chromeAuthorizedUntil
|
|
526
|
+
if (chromeAuthorizedUntil !== undefined) lockChromeControl();
|
|
481
527
|
return false;
|
|
482
528
|
};
|
|
483
529
|
|
|
@@ -495,6 +541,21 @@ export default function (pi: ExtensionAPI): void {
|
|
|
495
541
|
}
|
|
496
542
|
};
|
|
497
543
|
|
|
544
|
+
const scheduleAuthExpiry = (ctx: ExtensionContext, until: number | "indefinite"): void => {
|
|
545
|
+
clearAuthExpiryTimer();
|
|
546
|
+
if (until === "indefinite") return;
|
|
547
|
+
authExpiryTimer = setTimeout(() => {
|
|
548
|
+
if (chromeAuthorizedUntil !== until) return;
|
|
549
|
+
try {
|
|
550
|
+
lockChromeControl();
|
|
551
|
+
ctx.ui.notify("Chrome control authorization expired. Run /chrome authorize to allow chrome_* tools again.", "info");
|
|
552
|
+
updateChromeStatus(ctx);
|
|
553
|
+
} catch (error) {
|
|
554
|
+
console.warn(`Failed to expire pi-chrome authorization cleanly: ${(error as Error).message}`);
|
|
555
|
+
}
|
|
556
|
+
}, Math.max(0, until - Date.now()));
|
|
557
|
+
};
|
|
558
|
+
|
|
498
559
|
const authorizedBridgeSend = (action: string, params: Record<string, unknown>, timeoutMs = DEFAULT_TIMEOUT_MS, signal?: AbortSignal): Promise<unknown> => {
|
|
499
560
|
requireChromeControlAuthorized();
|
|
500
561
|
return bridge.send(action, params, timeoutMs, signal);
|
|
@@ -520,6 +581,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
520
581
|
});
|
|
521
582
|
|
|
522
583
|
pi.on("session_shutdown", () => {
|
|
584
|
+
clearAuthExpiryTimer();
|
|
523
585
|
bridge.stop();
|
|
524
586
|
if (globalState[PI_CHROME_GLOBAL_KEY]?.token === instanceToken) {
|
|
525
587
|
delete globalState[PI_CHROME_GLOBAL_KEY];
|
|
@@ -653,8 +715,9 @@ Usage rules:
|
|
|
653
715
|
ctx.ui.notify("Chrome control remains locked.", "info");
|
|
654
716
|
return;
|
|
655
717
|
}
|
|
656
|
-
registerChromeTools(pi);
|
|
657
718
|
chromeAuthorizedUntil = until;
|
|
719
|
+
activateChromeTools();
|
|
720
|
+
scheduleAuthExpiry(ctx, until);
|
|
658
721
|
ctx.ui.notify(`Chrome control authorized for ${label}.`, "info");
|
|
659
722
|
updateChromeStatus(ctx);
|
|
660
723
|
};
|
|
@@ -677,7 +740,7 @@ Usage rules:
|
|
|
677
740
|
};
|
|
678
741
|
|
|
679
742
|
const revokeHandler = (ctx: ExtensionContext) => {
|
|
680
|
-
|
|
743
|
+
lockChromeControl();
|
|
681
744
|
ctx.ui.notify("Chrome control locked. Run /chrome authorize to allow chrome_* tools again.", "info");
|
|
682
745
|
updateChromeStatus(ctx);
|
|
683
746
|
};
|