Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ jobs:
- name: Agent unit tests
run: npm test --workspace @onkernel/cua-agent -- --exclude "**/*.live.test.ts"

pi-extension-unit:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build --workspace @onkernel/cua-ai
- run: npm run build --workspace @onkernel/cua-agent
- name: Pi extension unit tests
run: npm test --workspace @onkernel/cua-pi-extension

cli-unit:
runs-on: ubuntu-latest
timeout-minutes: 15
Expand Down
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,17 @@ All of them expect you to:

```
packages/
├── ai/ # @onkernel/cua-ai - model catalog, tool schemas, provider adapters
├── agent/ # @onkernel/cua-agent - Kernel-browser tool execution
├── cli/ # @onkernel/cua-cli - the `cua` binary
└── ptywright/ # @onkernel/ptywright - development-only PTY/TUI test infrastructure
├── ai/ # @onkernel/cua-ai - model catalog, tool schemas, provider adapters
├── agent/ # @onkernel/cua-agent - Kernel-browser tool execution
├── pi-extension/ # @onkernel/cua-pi-extension - Kernel browser tools inside pi's own session
├── cli/ # @onkernel/cua-cli - the `cua` binary
└── ptywright/ # @onkernel/ptywright - development-only PTY/TUI test infrastructure
```

**Using pi already?** [`packages/pi-extension`](packages/pi-extension) adds these
tools to a pi session without a second agent loop: `pi install` it, select tools
with `--cua-tools`, and pi keeps owning the session, UI, and model.

**Building your own agent? Start here:** [`packages/agent`](packages/agent)
(`@onkernel/cua-agent`) — `attach()` binds a Kernel browser and compiles a
(model, tools) pair into plain pi objects you drive yourself. It sits on
Expand All @@ -53,21 +58,27 @@ flowchart LR
ai[("@onkernel/cua-ai")]
agent[("@onkernel/cua-agent")]
cli[("@onkernel/cua-cli")]
ext[("@onkernel/cua-pi-extension")]
pi[("pi-agent-core / pi-ai / pi-tui / pi-coding-agent")]
sdk[("@onkernel/sdk")]
ai --> agent
agent --> cli
ai --> cli
agent --> ext
ai --> ext
pi --> agent
pi --> cli
pi --> ext
sdk --> agent
sdk --> cli
sdk --> ext
```

| Package | What it ships |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| [`@onkernel/cua-ai`](packages/ai) | Computer-use model catalog, tool factories/toolsets, compatibility checks, and provider adapters. |
| [`@onkernel/cua-agent`](packages/agent) | Agent and harness APIs that run selected computer-use tools against a Kernel browser. |
| [`@onkernel/cua-agent`](packages/agent) | `attach()`: binds a Kernel browser and compiles a (model, tools) pair into plain pi objects. |
| [`@onkernel/cua-pi-extension`](packages/pi-extension) | A pi extension contributing these tools to pi's own agent session. |
| [`@onkernel/cua-cli`](packages/cli) | The `cua` binary: argv parsing, sessions, skills, JSONL output, pi-tui front-end. |
| [`@onkernel/ptywright`](packages/ptywright) | Development-only PTY/TUI test infrastructure. |

Expand Down
11 changes: 8 additions & 3 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ both explicitly and may use pi's orchestration primitives directly.
`AgentTool` or materialization types and no `pi-agent-core` dependency.
- `@onkernel/cua-agent` is provider-neutral runtime glue around
`pi-agent-core`. It defines `CuaAgentTool`, materializes catalog specs
exactly once per shared resource pool against a Kernel browser, owns
implementation identity for replacement detection, owns shared execution
resources, and applies catalog plans supplied as data.
exactly once per shared resource pool against a Kernel browser, owns shared
execution resources, and applies catalog plans supplied as data.
- `@onkernel/cua-pi-extension` contributes these tools to a pi session that pi
itself owns. It is the one consumer that uses neither `attach()` nor the
harness: pi owns the model collection and the agent loop, so the extension
takes the two pieces that are not pi-shaped — the catalog compiler and
`CuaExecutionResources` — and applies headers and payload transforms through
pi's own `before_provider_headers` and `before_provider_request` hooks.
- `@onkernel/cua-cli` owns application policy: it chooses an explicit tool list
for each selected model, adds pi coding tools, supplies the system prompt,
resolves credentials/sessions/skills, and renders text, JSONL, or TUI output.
Expand Down
29 changes: 28 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"packages/ai",
"packages/agent",
"packages/ptywright",
"packages/cli"
"packages/cli",
"packages/pi-extension"
],
"scripts": {
"build": "npm run build --workspace @onkernel/cua-ai && npm run build --workspace @onkernel/cua-agent && tsc -b && npm run build --workspace @onkernel/cua-cli && npm run build:native --workspace @onkernel/ptywright --if-present",
Expand Down
21 changes: 21 additions & 0 deletions packages/pi-extension/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Changelog

## Unreleased

- Add `@onkernel/cua-pi-extension`, an installable pi extension that contributes
Kernel browser tools to pi's own agent session. Selectors cover the CDP browser
toolset, the canonical computer toolset, the batch and Playwright tools, and
every provider-native surface: Anthropic's computer and browser tools, OpenAI's
native computer tool, and Google's predefined browser action set.
- Provider-native surfaces work because the extension owns the stream for the
providers it registers, swapping pi's registry model for the compiled catalog's
model — which carries the transport the selected tools derive — and passing the
incoming native-call plan. Without that, `requiresApi` never takes effect and
native calls arrive unnormalized.
- A selection is validated by compiling it for the active model, so an
incompatible tool deactivates with the catalog compiler's own reason instead of
failing at request time. `/cua-tools` with no argument lists every selector for
the current model with those reasons.
- One browser is provisioned lazily per session on first tool execution and
deleted on shutdown if this session created it. Declaration compilation, header
generation, and payload transforms never provision a browser.
101 changes: 101 additions & 0 deletions packages/pi-extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# `@onkernel/cua-pi-extension`

An installable [pi](https://pi.dev) extension that adds Kernel browser tools to
pi's existing agent session. pi owns the agent loop, session, and UI; this
extension contributes the tools, the browser they run against, and the provider
wiring that provider-native surfaces need.

It does not start a second model loop, and it adds no implicit screenshots or
prompt instructions.

## Install

```sh
pi install ./packages/pi-extension
# or, once published
pi install npm:@onkernel/cua-pi-extension
```

`KERNEL_API_KEY` is required when a tool first executes, not at startup.
`KERNEL_BASE_URL` is honored. Neither is written to session entries or output.

## Use

No selector means no Kernel tool is active and no browser is provisioned.

```sh
pi -p --provider openai --model gpt-5.6-sol \
--cua-tools browser,browser-act "Open example.com and report its heading"

pi --mode rpc --no-session --provider openai --model gpt-5.6-sol --cua-tools browser

pi -p --provider anthropic --model claude-opus-5 --cua-tools anthropic-computer \
"Open example.com and report its heading"
```

### Selectors

| selector | tools |
| --- | --- |
| `browser` | the CDP browser toolset |
| `computer` | the canonical computer toolset |
| `mixed` | both, deduplicated |
| `browser-act` | `browser_act` alone, the verified-plan tool |
| `browser-batch`, `computer-batch` | one mechanical batch tool |
| `playwright` | `playwright_execute` |
| `anthropic-computer`, `anthropic-browser` | Anthropic's native surfaces |
| `openai-computer` | OpenAI's native computer tool |
| `google-browser` | Google's predefined browser action set |
| any individual tool name | that tool alone |

Provider-native surfaces work because the extension **owns the stream** for the
providers it registers. pi resolves and streams its own registry model, but the
transport a native surface needs is derived onto the *compiled* model — so the
registered provider swaps in `catalog.model` (the resolved model with only `api`
replaced, so cost and context window are untouched) and adds the incoming
native-call plan that normalizes `computer_call`-style items and drives
Anthropic's browser-beta fallback. pi's resolved credential rides along in
`options.apiKey`.

`--cua-coordinates` selects `pixels` (default) or `normalized-1000` for the
computer toolset's coordinate contract.

### Commands

- `/cua` — current selectors, active tools, and browser status.
- `/cua-tools` — with no argument, list every selector for the current model,
marking the selected ones and showing the compiler's own reason for any that
this model cannot take. With an argument, replace the selection. `none` clears
it.

A selection is checked by compiling it, so a model that cannot take a tool
deactivates it with a reason rather than failing at request time. Switching
models re-checks, and restores a previously forced-off selection when the new
model can take it.

### Browser

| flag | effect |
| --- | --- |
| `--cua-browser-session` | attach an existing session; never deleted on exit |
| `--cua-profile-id`, `--cua-profile-save-changes` | load and optionally persist a profile |
| `--cua-proxy-id` | route through a Kernel proxy |
| `--cua-browser-timeout` | owned-browser timeout in seconds (default 300) |

One browser is provisioned lazily per session, on first tool execution.
Compiling declarations, generating headers, and transforming a payload never
provision one. An owned browser is deleted on session shutdown.

## Development

```bash
npm run typecheck --workspace @onkernel/cua-pi-extension
npm test --workspace @onkernel/cua-pi-extension
```

The test suite includes an end-to-end run that spawns real `pi` in print and RPC
modes against a fake provider and Kernel server.

## License

MIT
56 changes: 56 additions & 0 deletions packages/pi-extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "@onkernel/cua-pi-extension",
"version": "0.10.0",
"description": "Kernel browser tools for pi",
"license": "MIT",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/kernel/cua.git",
"directory": "packages/pi-extension"
},
"homepage": "https://github.com/kernel/cua/tree/main/packages/pi-extension#readme",
"keywords": [
"pi-package",
"pi-extension",
"computer-use",
"kernel"
],
"pi": {
"extensions": [
"./src/index.ts"
]
},
"files": [
"src",
"README.md",
"CHANGELOG.md",
"package.json"
],
"publishConfig": {
"access": "public"
},
"engines": {
"node": ">=22.19.0"
},
"scripts": {
"build": "tsc -b",
"typecheck": "tsc -b",
"clean": "tsc -b --clean && rm -rf dist-tsc",
"test": "vitest --run"
},
"dependencies": {
"@onkernel/cua-agent": "0.10.0",
"@onkernel/cua-ai": "0.10.0",
"@onkernel/sdk": "0.49.0"
},
"peerDependencies": {
"@earendil-works/pi-agent-core": "*",
"@earendil-works/pi-ai": "*",
"@earendil-works/pi-coding-agent": "*",
"@earendil-works/pi-tui": "*"
},
"devDependencies": {
"vitest": "^3.2.4"
}
}
Loading
Loading