| Age | Commit message (Collapse) | Author |
|
Removes file-header banners and comments that restate the code. Keeps
one-line notes at the optional-sharp dynamic import, the sharp .default
probe, the `never` contravariance trick, the sanctioned renderCall cast,
and safeJs's interpolation rule.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
The tool gate ran access() on DAEMON_SOCKET_PATH, which on Windows is the named
pipe \\.\pipe\pi-browser-daemon. Named pipes are not filesystem entries, so
access() always fails there and every browser_* call returned "Browser harness
not initialized" no matter how healthy the daemon was. spawn.ts already skipped
the identical check for this reason; that knowledge is now one shared
daemonSocketMayExist() used by both call sites, with platform and path as
parameters so the branch is testable off-platform.
Report: docs/superpowers/reports/2026-07-26-bug-audit.md#f1
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Types the event-queue iterator's TReturn as undefined so the terminal
result needs no cast; declares the isError field the pi runtime reads by
duck-typing; binds socket to a local const in the daemon transport;
replaces the @ts-ignore on the optional sharp import with a non-literal
specifier so src/ still typechecks where sharp was not installed.
Adds src/util/guards.ts as the single home for narrowing over unknown —
isRecord plus scalar/array readers — and converts the two private
isObject copies in cdp/types.ts and daemon/protocol.ts along with every
inline `as Record<string, unknown>` in domains/js.ts and domains/render.ts.
Gives Accessibility.getFullAXTree a real result schema, closing the last
unvalidated CDP boundary: only nodeId is required, every object carries
additionalProperties, and each AX value stays Unknown, so the tree
decodes as a whole or fails as a whole rather than being filtered.
Guards the five tool-result `details` readers, the daemon attach
response, the persisted session state, the browser-namespace flag, and
the fs errno narrowing, each feeding an already-present failure path.
The daemon-transport socket binding is not a bug fix: send() runs
synchronously inside sendWithTimeout's promise executor, so socket cannot
be reassigned between the check and the write. It removes the assertion
and makes the write immune to a later refactor that adds an await.
Two assertions survive by design and are documented in the task report:
the never->unknown re-widening in util/tool.ts, which the type-erased
tool registry makes unavoidable, and the AsyncFunction constructor lookup
in domains/js.ts, which JavaScript exposes no typed binding for.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
serialized: true was applied in registry.ts, away from the tools it
describes. Now a required concurrency field on each definition, with a
test pinning the serialized set so the classes cannot drift.
The lock check defaults to taking the mutex for any class that is not
explicitly "parallel", so a definition that bypasses defineBrowserTool at
runtime fails safe rather than racing on shared CDP state.
The test script gains --conditions=import: pi-coding-agent publishes no
"require" condition, so importing any tool definition from a CJS-loaded
test could not resolve it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
* feat: Unix socket daemon with auto-reconnect for persistent Chrome CDP
Eliminates the 'Allow Remote Debugging' Chrome prompt that appeared on
every pi session by multiplexing pi instances through a single persistent
daemon process.
Key additions:
- Unix socket IPC (net.createServer + readline JSON framing)
- CdpBridge with ID multiplexer + event router
- DaemonTransport implementing CdpTransport interface
- Auto-spawn with ensureDaemon() (lazy, checks socket)
Fixes since initial implementation:
- Bridge auto-reconnects to Chrome with exponential backoff (1s-60s).
Previously the bridge tried once at startup and permanently failed
if Chrome wasn't ready — causing 'Chrome not connected' on every
browser tool call.
- Daemon spawn uses project-local tsx binary instead of global --import
flag, fixing silent spawn failure (ERR_MODULE_NOT_FOUND).
- Stale ctx crash: persistState in onOwnershipChange wrapped in
try/catch to prevent CDP event consumer crashes.
49 test assertions across 4 test files. Zero TypeScript errors.
* feat: on-demand browser initialization
Browser daemon no longer auto-starts on session_start. Instead:
- session_start creates the client lazily but does NOT connect or spawn
the daemon. Zero Chrome prompts for non-browser pi sessions.
- Browser tool wrapper checks for daemon socket before each call.
Socket missing → clear error: 'Run /browser-setup first'.
Socket exists → proceeds silently (daemon already running).
- /browser-setup is the explicit, one-time init point. It spawns
the daemon and connects to Chrome only when the user opts in.
- SKILL.md updated with Connection Setup instructions telling agents
to direct users to /browser-setup when socket is missing.
* fix: checkChromeRunning on macOS — match by substring not exact
ps -A -o comm= returns full executable paths on modern macOS
(e.g. /Applications/Google Chrome.app/Contents/MacOS/Google Chrome),
not the basename. The old exact-match check (browserProcesses.includes(l))
never matched, causing false 'No browser instance running' errors.
Changed to substring includes() with helper/renderer/crashpad filtering.
* feat: browser_setup as agent-callable tool
The agent can now self-recover from 'Browser harness not initialized'
errors by calling browser_setup directly — no user mediation needed.
- Extracted shared performSetup() from the slash command into setup.ts
- Created src/domains/setup.ts with ensureAlive:false to bypass the
socket guard (this tool IS the setup, can't require itself)
- Registered browser_setup in the tool registry
- Updated SKILL.md: agent calls browser_setup directly, not ask user
- Removed stale test/manual/spawn-test.ts
* release: v0.6.0 — per-tab isolation, Unix socket daemon, on-demand init
|
|
- Add lightweight async mutex (src/util/mutex.ts) for FIFO serialization
- Add serialized?: boolean to BrowserToolDefinition
- Wire mutex acquisition into registerBrowserTool execute wrapper
- Expose mutationMutex() on BrowserClient
- Mark all mutation tools (click, type, scroll, navigate, switch_tab, etc.) as serialized
- Leave observation tools (screenshot, page_info, execute_js, http_get, etc.) unguarded
- Update prompt and skill docs to reflect parallel-safe behavior
- Fix scroll tool: add Page.bringToFront, explicit button:none/buttons:0/pointerType:mouse
- Update .gitignore to ignore scripts/ and data/ folders
|
|
Implements Task 9: adds src/domains/click.ts with the new architecture,
updates registry.ts to register clickTool, removes the legacy browser_click
block from tools.ts, and wires BrowserClient alongside BrowserDaemon in
index.ts so both systems coexist during migration.
Also fixes AnyBrowserToolDefinition variance: uses never-arg renderCall in
the erased type and a boundary cast in registerBrowserTool so concrete tool
definitions (with specific Static<S> args) are assignable to the registry
array without widening.
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|