mirror of
https://github.com/harivansh-afk/clanker-agent.git
synced 2026-04-15 07:04:45 +00:00
Merge pull request #293 from getcompanion-ai/rename
refactor: finish companion rename migration
This commit is contained in:
commit
cf2bb61383
304 changed files with 3815 additions and 3695 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -23,13 +23,13 @@ packages/*/dist-firefox/
|
||||||
.npm/
|
.npm/
|
||||||
coverage/
|
coverage/
|
||||||
.nyc_output/
|
.nyc_output/
|
||||||
.pi_config/
|
.companion_config/
|
||||||
tui-debug.log
|
tui-debug.log
|
||||||
compaction-results/
|
compaction-results/
|
||||||
.opencode/
|
.opencode/
|
||||||
syntax.jsonl
|
syntax.jsonl
|
||||||
out.jsonl
|
out.jsonl
|
||||||
pi-*.html
|
companion-*.html
|
||||||
out.html
|
out.html
|
||||||
packages/coding-agent/binaries/
|
packages/coding-agent/binaries/
|
||||||
todo.md
|
todo.md
|
||||||
|
|
|
||||||
24
AGENTS.md
24
AGENTS.md
|
|
@ -71,29 +71,29 @@ When closing issues via commit:
|
||||||
- GitHub CLI for issues/PRs
|
- GitHub CLI for issues/PRs
|
||||||
- Add package labels to issues/PRs: pkg:agent, pkg:ai, pkg:coding-agent, pkg:mom, pkg:pods, pkg:tui, pkg:web-ui
|
- Add package labels to issues/PRs: pkg:agent, pkg:ai, pkg:coding-agent, pkg:mom, pkg:pods, pkg:tui, pkg:web-ui
|
||||||
|
|
||||||
## Testing pi Interactive Mode with tmux
|
## Testing companion Interactive Mode with tmux
|
||||||
|
|
||||||
To test pi's TUI in a controlled terminal environment:
|
To test companion's TUI in a controlled terminal environment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create tmux session with specific dimensions
|
# Create tmux session with specific dimensions
|
||||||
tmux new-session -d -s pi-test -x 80 -y 24
|
tmux new-session -d -s companion-test -x 80 -y 24
|
||||||
|
|
||||||
# Start pi from source
|
# Start companion from source
|
||||||
tmux send-keys -t pi-test "cd /Users/badlogic/workspaces/pi-mono && ./pi-test.sh" Enter
|
tmux send-keys -t companion-test "cd /Users/badlogic/workspaces/companion-mono && ./companion-test.sh" Enter
|
||||||
|
|
||||||
# Wait for startup, then capture output
|
# Wait for startup, then capture output
|
||||||
sleep 3 && tmux capture-pane -t pi-test -p
|
sleep 3 && tmux capture-pane -t companion-test -p
|
||||||
|
|
||||||
# Send input
|
# Send input
|
||||||
tmux send-keys -t pi-test "your prompt here" Enter
|
tmux send-keys -t companion-test "your prompt here" Enter
|
||||||
|
|
||||||
# Send special keys
|
# Send special keys
|
||||||
tmux send-keys -t pi-test Escape
|
tmux send-keys -t companion-test Escape
|
||||||
tmux send-keys -t pi-test C-o # ctrl+o
|
tmux send-keys -t companion-test C-o # ctrl+o
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
tmux kill-session -t pi-test
|
tmux kill-session -t companion-test
|
||||||
```
|
```
|
||||||
|
|
||||||
## Style
|
## Style
|
||||||
|
|
@ -127,8 +127,8 @@ Use these sections under `## [Unreleased]`:
|
||||||
|
|
||||||
### Attribution
|
### Attribution
|
||||||
|
|
||||||
- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/badlogic/pi-mono/issues/123))`
|
- **Internal changes (from issues)**: `Fixed foo bar ([#123](https://github.com/badlogic/companion-mono/issues/123))`
|
||||||
- **External contributions**: `Added feature X ([#456](https://github.com/badlogic/pi-mono/pull/456) by [@username](https://github.com/username))`
|
- **External contributions**: `Added feature X ([#456](https://github.com/badlogic/companion-mono/pull/456) by [@username](https://github.com/username))`
|
||||||
|
|
||||||
## Adding a New LLM Provider (packages/ai)
|
## Adding a New LLM Provider (packages/ai)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Contributing to pi
|
# Contributing to companion
|
||||||
|
|
||||||
Thanks for wanting to contribute! This guide exists to save both of us time.
|
Thanks for wanting to contribute! This guide exists to save both of us time.
|
||||||
|
|
||||||
|
|
@ -8,7 +8,7 @@ Thanks for wanting to contribute! This guide exists to save both of us time.
|
||||||
|
|
||||||
Using AI to write code is fine. You can gain understanding by interrogating an agent with access to the codebase until you grasp all edge cases and effects of your changes. What's not fine is submitting agent-generated slop without that understanding.
|
Using AI to write code is fine. You can gain understanding by interrogating an agent with access to the codebase until you grasp all edge cases and effects of your changes. What's not fine is submitting agent-generated slop without that understanding.
|
||||||
|
|
||||||
If you use an agent, run it from the `pi` root directory so it picks up `AGENTS.md` automatically. Your agent must follow the rules and guidelines in that file.
|
If you use an agent, run it from the `companion` root directory so it picks up `AGENTS.md` automatically. Your agent must follow the rules and guidelines in that file.
|
||||||
|
|
||||||
## First-Time Contributors
|
## First-Time Contributors
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ If you're adding a new provider to `packages/ai`, see `AGENTS.md` for required t
|
||||||
|
|
||||||
## Philosophy
|
## Philosophy
|
||||||
|
|
||||||
pi's core is minimal. If your feature doesn't belong in the core, it should be an extension. PRs that bloat the core will likely be rejected.
|
companion's core is minimal. If your feature doesn't belong in the core, it should be an extension. PRs that bloat the core will likely be rejected.
|
||||||
|
|
||||||
## Questions?
|
## Questions?
|
||||||
|
|
||||||
|
|
|
||||||
48
README.md
48
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://shittycodingagent.ai">
|
<a href="https://shittycodingagent.ai">
|
||||||
<img src="https://shittycodingagent.ai/logo.svg" alt="pi logo" width="128">
|
<img src="https://shittycodingagent.ai/logo.svg" alt="companion logo" width="128">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|
@ -8,26 +8,26 @@
|
||||||
<a href="https://github.com/getcompanion-ai/co-mono/actions/workflows/ci.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/getcompanion-ai/co-mono/ci.yml?style=flat-square&branch=main" /></a>
|
<a href="https://github.com/getcompanion-ai/co-mono/actions/workflows/ci.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/getcompanion-ai/co-mono/ci.yml?style=flat-square&branch=main" /></a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://pi.dev">pi.dev</a> domain graciously donated by
|
<a href="https://companion.dev">companion.dev</a> domain graciously donated by
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a href="https://exe.dev"><img src="packages/coding-agent/docs/images/exy.png" alt="Exy mascot" width="48" /><br />exe.dev</a>
|
<a href="https://exe.dev"><img src="packages/coding-agent/docs/images/exy.png" alt="Exy mascot" width="48" /><br />exe.dev</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# pi
|
# companion
|
||||||
|
|
||||||
> **Looking for the pi coding agent?** See **[packages/coding-agent](packages/coding-agent)** for installation and usage.
|
> **Looking for the companion coding agent?** See **[packages/coding-agent](packages/coding-agent)** for installation and usage.
|
||||||
|
|
||||||
Tools for building AI agents and running the pi coding agent.
|
Tools for building AI agents and running the companion coding agent.
|
||||||
|
|
||||||
## Packages
|
## Packages
|
||||||
|
|
||||||
| Package | Description |
|
| Package | Description |
|
||||||
| ---------------------------------------------------------- | ---------------------------------------------------------------- |
|
| ---------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||||
| **[@mariozechner/pi-ai](packages/ai)** | Unified multi-provider LLM API (OpenAI, Anthropic, Google, etc.) |
|
| **[@mariozechner/companion-ai](packages/ai)** | Unified multi-provider LLM API (OpenAI, Anthropic, Google, etc.) |
|
||||||
| **[@mariozechner/pi-agent-core](packages/agent)** | Agent runtime with tool calling and state management |
|
| **[@mariozechner/companion-agent-core](packages/agent)** | Agent runtime with tool calling and state management |
|
||||||
| **[@mariozechner/pi-coding-agent](packages/coding-agent)** | Interactive coding agent CLI |
|
| **[@mariozechner/companion-coding-agent](packages/coding-agent)** | Interactive coding agent CLI |
|
||||||
| **[@mariozechner/pi-tui](packages/tui)** | Terminal UI library with differential rendering |
|
| **[@mariozechner/companion-tui](packages/tui)** | Terminal UI library with differential rendering |
|
||||||
| **[@mariozechner/pi-web-ui](packages/web-ui)** | Web components for AI chat interfaces |
|
| **[@mariozechner/companion-web-ui](packages/web-ui)** | Web components for AI chat interfaces |
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
@ -52,15 +52,15 @@ curl -fsSL https://raw.githubusercontent.com/getcompanion-ai/co-mono/main/public
|
||||||
This installer:
|
This installer:
|
||||||
|
|
||||||
- Downloads the latest release (or falls back to source when needed),
|
- Downloads the latest release (or falls back to source when needed),
|
||||||
- writes `~/.local/bin/pi` launcher,
|
- writes `~/.local/bin/companion` launcher,
|
||||||
- populates `~/.pi/agent/settings.json` with package list,
|
- populates `~/.companion/agent/settings.json` with package list,
|
||||||
- installs packages (if `npm` is available),
|
- installs packages (if `npm` is available),
|
||||||
- and can install a user service for `pi daemon` so it stays alive (`systemd` on Linux, `launchd` on macOS).
|
- and can install a user service for `companion daemon` so it stays alive (`systemd` on Linux, `launchd` on macOS).
|
||||||
|
|
||||||
Preinstalled package sources are:
|
Preinstalled package sources are:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
["npm:@e9n/pi-channels", "npm:pi-teams"]
|
["npm:@e9n/companion-channels", "npm:companion-teams"]
|
||||||
```
|
```
|
||||||
|
|
||||||
If `npm` is available, it also installs these packages during install.
|
If `npm` is available, it also installs these packages during install.
|
||||||
|
|
@ -68,7 +68,7 @@ If `npm` is available, it also installs these packages during install.
|
||||||
If no release asset is found, the installer falls back to source.
|
If no release asset is found, the installer falls back to source.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
PI_FALLBACK_TO_SOURCE=0 \
|
COMPANION_FALLBACK_TO_SOURCE=0 \
|
||||||
curl -fsSL https://raw.githubusercontent.com/getcompanion-ai/co-mono/main/public-install.sh | bash -s -- --daemon --start
|
curl -fsSL https://raw.githubusercontent.com/getcompanion-ai/co-mono/main/public-install.sh | bash -s -- --daemon --start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -89,27 +89,27 @@ cd co-mono
|
||||||
Run:
|
Run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./pi
|
./companion
|
||||||
```
|
```
|
||||||
|
|
||||||
Run in background with extensions active:
|
Run in background with extensions active:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./pi daemon
|
./companion daemon
|
||||||
```
|
```
|
||||||
|
|
||||||
For a user systemd setup, create `~/.config/systemd/user/pi.service` with:
|
For a user systemd setup, create `~/.config/systemd/user/companion.service` with:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=pi daemon
|
Description=companion daemon
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
Environment=CO_MONO_AGENT_DIR=%h/.pi/agent
|
Environment=CO_MONO_AGENT_DIR=%h/.companion/agent
|
||||||
Environment=PI_CODING_AGENT_DIR=%h/.pi/agent
|
Environment=COMPANION_CODING_AGENT_DIR=%h/.companion/agent
|
||||||
ExecStart=/absolute/path/to/repo/pi daemon
|
ExecStart=/absolute/path/to/repo/companion daemon
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ Then enable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
systemctl --user daemon-reload
|
systemctl --user daemon-reload
|
||||||
systemctl --user enable --now pi
|
systemctl --user enable --now companion
|
||||||
```
|
```
|
||||||
|
|
||||||
On macOS, `public-install.sh --daemon --start` now provisions a per-user `launchd` agent automatically.
|
On macOS, `public-install.sh --daemon --start` now provisions a per-user `launchd` agent automatically.
|
||||||
|
|
@ -140,7 +140,7 @@ npm install # Install all dependencies
|
||||||
npm run build # Build all packages
|
npm run build # Build all packages
|
||||||
npm run check # Lint, format, and type check
|
npm run check # Lint, format, and type check
|
||||||
./test.sh # Run tests (skips LLM-dependent tests without API keys)
|
./test.sh # Run tests (skips LLM-dependent tests without API keys)
|
||||||
./pi-test.sh # Run pi from sources (must be run from repo root)
|
./companion-test.sh # Run companion from sources (must be run from repo root)
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note:** `npm run check` requires `npm run build` to be run first. The web-ui package uses `tsc` which needs compiled `.d.ts` files from dependencies.
|
> **Note:** `npm run check` requires `npm run build` to be run first. The web-ui package uses `tsc` which needs compiled `.d.ts` files from dependencies.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"folders": [
|
"folders": [
|
||||||
{
|
{
|
||||||
"name": "pi",
|
"name": "companion",
|
||||||
"path": "."
|
"path": "."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
14
install.sh
14
install.sh
|
|
@ -24,12 +24,12 @@ need npm
|
||||||
|
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
if [[ "${PI_SKIP_INSTALL:-${CO_MONO_SKIP_INSTALL:-0}}" != "1" ]]; then
|
if [[ "${COMPANION_SKIP_INSTALL:-${CO_MONO_SKIP_INSTALL:-0}}" != "1" ]]; then
|
||||||
log "Installing workspace dependencies"
|
log "Installing workspace dependencies"
|
||||||
npm install
|
npm install
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${PI_SKIP_BUILD:-${CO_MONO_SKIP_BUILD:-0}}" != "1" ]]; then
|
if [[ "${COMPANION_SKIP_BUILD:-${CO_MONO_SKIP_BUILD:-0}}" != "1" ]]; then
|
||||||
log "Building core packages"
|
log "Building core packages"
|
||||||
BUILD_FAILED=0
|
BUILD_FAILED=0
|
||||||
for pkg in packages/tui packages/ai packages/agent packages/coding-agent; do
|
for pkg in packages/tui packages/ai packages/agent packages/coding-agent; do
|
||||||
|
|
@ -46,7 +46,7 @@ if [[ "$BUILD_FAILED" == "1" ]] && [[ ! -f "$ROOT_DIR/packages/coding-agent/src/
|
||||||
fail "No usable coding-agent CLI source found for source launch fallback."
|
fail "No usable coding-agent CLI source found for source launch fallback."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
LAUNCHER="$ROOT_DIR/pi"
|
LAUNCHER="$ROOT_DIR/companion"
|
||||||
cat > "$LAUNCHER" <<'EOF'
|
cat > "$LAUNCHER" <<'EOF'
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
@ -54,8 +54,8 @@ set -euo pipefail
|
||||||
|
|
||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
if [[ -x "$ROOT_DIR/packages/coding-agent/dist/pi" ]]; then
|
if [[ -x "$ROOT_DIR/packages/coding-agent/dist/companion" ]]; then
|
||||||
exec "$ROOT_DIR/packages/coding-agent/dist/pi" "$@"
|
exec "$ROOT_DIR/packages/coding-agent/dist/companion" "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "$ROOT_DIR/packages/coding-agent/dist/cli.js" ]]; then
|
if [[ -f "$ROOT_DIR/packages/coding-agent/dist/cli.js" ]]; then
|
||||||
|
|
@ -66,10 +66,10 @@ if [[ -x "$ROOT_DIR/node_modules/.bin/tsx" ]] && [[ -f "$ROOT_DIR/packages/codin
|
||||||
exec "$ROOT_DIR/node_modules/.bin/tsx" "$ROOT_DIR/packages/coding-agent/src/cli.ts" "$@"
|
exec "$ROOT_DIR/node_modules/.bin/tsx" "$ROOT_DIR/packages/coding-agent/src/cli.ts" "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "ERROR: no runnable pi binary found and tsx fallback is unavailable." >&2
|
echo "ERROR: no runnable companion binary found and tsx fallback is unavailable." >&2
|
||||||
exit 1
|
exit 1
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chmod +x "$LAUNCHER"
|
chmod +x "$LAUNCHER"
|
||||||
log "Created launcher: $LAUNCHER"
|
log "Created launcher: $LAUNCHER"
|
||||||
log "Run with: ./pi"
|
log "Run with: ./companion"
|
||||||
|
|
|
||||||
208
package-lock.json
generated
208
package-lock.json
generated
|
|
@ -1,18 +1,18 @@
|
||||||
{
|
{
|
||||||
"name": "pi",
|
"name": "companion",
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pi",
|
"name": "companion",
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mariozechner/companion-coding-agent": "^0.30.2",
|
||||||
"@mariozechner/jiti": "^2.6.5",
|
"@mariozechner/jiti": "^2.6.5",
|
||||||
"@mariozechner/pi-coding-agent": "^0.30.2",
|
|
||||||
"get-east-asian-width": "^1.4.0"
|
"get-east-asian-width": "^1.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -948,8 +948,8 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@e9n/pi-channels": {
|
"node_modules/@e9n/companion-channels": {
|
||||||
"resolved": "packages/pi-channels",
|
"resolved": "packages/companion-channels",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
|
|
@ -1613,6 +1613,22 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mariozechner/companion-agent-core": {
|
||||||
|
"resolved": "packages/agent",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
|
"node_modules/@mariozechner/companion-ai": {
|
||||||
|
"resolved": "packages/ai",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
|
"node_modules/@mariozechner/companion-coding-agent": {
|
||||||
|
"resolved": "packages/coding-agent",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
|
"node_modules/@mariozechner/companion-tui": {
|
||||||
|
"resolved": "packages/tui",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@mariozechner/jiti": {
|
"node_modules/@mariozechner/jiti": {
|
||||||
"version": "2.6.5",
|
"version": "2.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/@mariozechner/jiti/-/jiti-2.6.5.tgz",
|
"resolved": "https://registry.npmjs.org/@mariozechner/jiti/-/jiti-2.6.5.tgz",
|
||||||
|
|
@ -1626,22 +1642,6 @@
|
||||||
"jiti": "lib/jiti-cli.mjs"
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@mariozechner/pi-agent-core": {
|
|
||||||
"resolved": "packages/agent",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/@mariozechner/pi-ai": {
|
|
||||||
"resolved": "packages/ai",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/@mariozechner/pi-coding-agent": {
|
|
||||||
"resolved": "packages/coding-agent",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/@mariozechner/pi-tui": {
|
|
||||||
"resolved": "packages/tui",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/@mistralai/mistralai": {
|
"node_modules/@mistralai/mistralai": {
|
||||||
"version": "1.14.1",
|
"version": "1.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.14.1.tgz",
|
||||||
|
|
@ -3709,6 +3709,14 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/companion-grind": {
|
||||||
|
"resolved": "packages/companion-grind",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
|
"node_modules/companion-teams": {
|
||||||
|
"resolved": "packages/companion-teams",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/concurrently": {
|
"node_modules/concurrently": {
|
||||||
"version": "9.2.1",
|
"version": "9.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz",
|
||||||
|
|
@ -5819,14 +5827,6 @@
|
||||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/pi-grind": {
|
|
||||||
"resolved": "packages/pi-grind",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/pi-teams": {
|
|
||||||
"resolved": "packages/pi-teams",
|
|
||||||
"link": true
|
|
||||||
},
|
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
|
|
@ -7381,11 +7381,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/agent": {
|
"packages/agent": {
|
||||||
"name": "@mariozechner/pi-agent-core",
|
"name": "@mariozechner/companion-agent-core",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mariozechner/pi-ai": "^0.56.2"
|
"@mariozechner/companion-ai": "^0.56.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.3.0",
|
"@types/node": "^24.3.0",
|
||||||
|
|
@ -7414,7 +7414,7 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"packages/ai": {
|
"packages/ai": {
|
||||||
"name": "@mariozechner/pi-ai",
|
"name": "@mariozechner/companion-ai",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -7433,7 +7433,7 @@
|
||||||
"zod-to-json-schema": "^3.24.6"
|
"zod-to-json-schema": "^3.24.6"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"pi-ai": "dist/cli.js"
|
"companion-ai": "dist/cli.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.3.0",
|
"@types/node": "^24.3.0",
|
||||||
|
|
@ -7462,14 +7462,14 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"packages/coding-agent": {
|
"packages/coding-agent": {
|
||||||
"name": "@mariozechner/pi-coding-agent",
|
"name": "@mariozechner/companion-coding-agent",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mariozechner/companion-agent-core": "^0.56.2",
|
||||||
|
"@mariozechner/companion-ai": "^0.56.2",
|
||||||
|
"@mariozechner/companion-tui": "^0.56.2",
|
||||||
"@mariozechner/jiti": "^2.6.2",
|
"@mariozechner/jiti": "^2.6.2",
|
||||||
"@mariozechner/pi-agent-core": "^0.56.2",
|
|
||||||
"@mariozechner/pi-ai": "^0.56.2",
|
|
||||||
"@mariozechner/pi-tui": "^0.56.2",
|
|
||||||
"@silvia-odwyer/photon-node": "^0.3.4",
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
||||||
"chalk": "^5.5.0",
|
"chalk": "^5.5.0",
|
||||||
"cli-highlight": "^2.1.11",
|
"cli-highlight": "^2.1.11",
|
||||||
|
|
@ -7487,7 +7487,7 @@
|
||||||
"yaml": "^2.8.2"
|
"yaml": "^2.8.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"pi": "dist/cli.js"
|
"companion": "dist/cli.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/diff": "^7.0.2",
|
"@types/diff": "^7.0.2",
|
||||||
|
|
@ -7507,7 +7507,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/coding-agent/examples/extensions/custom-provider-anthropic": {
|
"packages/coding-agent/examples/extensions/custom-provider-anthropic": {
|
||||||
"name": "pi-extension-custom-provider-anthropic",
|
"name": "companion-extension-custom-provider-anthropic",
|
||||||
"version": "1.7.2",
|
"version": "1.7.2",
|
||||||
"extraneous": true,
|
"extraneous": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -7515,17 +7515,17 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/coding-agent/examples/extensions/custom-provider-gitlab-duo": {
|
"packages/coding-agent/examples/extensions/custom-provider-gitlab-duo": {
|
||||||
"name": "pi-extension-custom-provider-gitlab-duo",
|
"name": "companion-extension-custom-provider-gitlab-duo",
|
||||||
"version": "1.7.2",
|
"version": "1.7.2",
|
||||||
"extraneous": true
|
"extraneous": true
|
||||||
},
|
},
|
||||||
"packages/coding-agent/examples/extensions/custom-provider-qwen-cli": {
|
"packages/coding-agent/examples/extensions/custom-provider-qwen-cli": {
|
||||||
"name": "pi-extension-custom-provider-qwen-cli",
|
"name": "companion-extension-custom-provider-qwen-cli",
|
||||||
"version": "1.6.2",
|
"version": "1.6.2",
|
||||||
"extraneous": true
|
"extraneous": true
|
||||||
},
|
},
|
||||||
"packages/coding-agent/examples/extensions/with-deps": {
|
"packages/coding-agent/examples/extensions/with-deps": {
|
||||||
"name": "pi-extension-with-deps",
|
"name": "companion-extension-with-deps",
|
||||||
"version": "1.20.2",
|
"version": "1.20.2",
|
||||||
"extraneous": true,
|
"extraneous": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -7552,37 +7552,8 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"packages/mom": {
|
"packages/companion-channels": {
|
||||||
"name": "@mariozechner/pi-mom",
|
"name": "@e9n/companion-channels",
|
||||||
"version": "0.56.2",
|
|
||||||
"extraneous": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@anthropic-ai/sandbox-runtime": "^0.0.16",
|
|
||||||
"@mariozechner/pi-agent-core": "^0.56.2",
|
|
||||||
"@mariozechner/pi-ai": "^0.56.2",
|
|
||||||
"@mariozechner/pi-coding-agent": "^0.56.2",
|
|
||||||
"@sinclair/typebox": "^0.34.0",
|
|
||||||
"@slack/socket-mode": "^2.0.0",
|
|
||||||
"@slack/web-api": "^7.0.0",
|
|
||||||
"chalk": "^5.6.2",
|
|
||||||
"croner": "^9.1.0",
|
|
||||||
"diff": "^8.0.2"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"mom": "dist/main.js"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/diff": "^7.0.2",
|
|
||||||
"@types/node": "^24.3.0",
|
|
||||||
"typescript": "^5.7.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"packages/pi-channels": {
|
|
||||||
"name": "@e9n/pi-channels",
|
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -7594,12 +7565,12 @@
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mariozechner/pi-ai": "*",
|
"@mariozechner/companion-ai": "*",
|
||||||
"@mariozechner/pi-coding-agent": "*",
|
"@mariozechner/companion-coding-agent": "*",
|
||||||
"@sinclair/typebox": "*"
|
"@sinclair/typebox": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-grind": {
|
"packages/companion-grind": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -7608,11 +7579,11 @@
|
||||||
"vitest": "^3.2.4"
|
"vitest": "^3.2.4"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mariozechner/pi-agent-core": "*",
|
"@mariozechner/companion-agent-core": "*",
|
||||||
"@mariozechner/pi-coding-agent": "*"
|
"@mariozechner/companion-coding-agent": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-grind/node_modules/@types/node": {
|
"packages/companion-grind/node_modules/@types/node": {
|
||||||
"version": "24.12.0",
|
"version": "24.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
|
||||||
"integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
|
"integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
|
||||||
|
|
@ -7622,26 +7593,26 @@
|
||||||
"undici-types": "~7.16.0"
|
"undici-types": "~7.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-grind/node_modules/undici-types": {
|
"packages/companion-grind/node_modules/undici-types": {
|
||||||
"version": "7.16.0",
|
"version": "7.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"packages/pi-runtime-daemon": {
|
"packages/companion-runtime-daemon": {
|
||||||
"name": "@local/pi-runtime-daemon",
|
"name": "@local/companion-runtime-daemon",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"extraneous": true,
|
"extraneous": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"pi-runtime-daemon": "bin/pi-runtime-daemon.mjs"
|
"companion-runtime-daemon": "bin/companion-runtime-daemon.mjs"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams": {
|
"packages/companion-teams": {
|
||||||
"version": "0.8.6",
|
"version": "0.8.6",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -7654,11 +7625,11 @@
|
||||||
"vitest": "^4.0.18"
|
"vitest": "^4.0.18"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@mariozechner/pi-coding-agent": "*",
|
"@mariozechner/companion-coding-agent": "*",
|
||||||
"@sinclair/typebox": "*"
|
"@sinclair/typebox": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@types/node": {
|
"packages/companion-teams/node_modules/@types/node": {
|
||||||
"version": "25.3.5",
|
"version": "25.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz",
|
||||||
"integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==",
|
"integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==",
|
||||||
|
|
@ -7668,7 +7639,7 @@
|
||||||
"undici-types": "~7.18.0"
|
"undici-types": "~7.18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@vitest/expect": {
|
"packages/companion-teams/node_modules/@vitest/expect": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz",
|
||||||
"integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==",
|
"integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==",
|
||||||
|
|
@ -7686,7 +7657,7 @@
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@vitest/mocker": {
|
"packages/companion-teams/node_modules/@vitest/mocker": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz",
|
||||||
"integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==",
|
"integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==",
|
||||||
|
|
@ -7713,7 +7684,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@vitest/pretty-format": {
|
"packages/companion-teams/node_modules/@vitest/pretty-format": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz",
|
||||||
"integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==",
|
"integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==",
|
||||||
|
|
@ -7726,7 +7697,7 @@
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@vitest/runner": {
|
"packages/companion-teams/node_modules/@vitest/runner": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz",
|
||||||
"integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==",
|
"integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==",
|
||||||
|
|
@ -7740,7 +7711,7 @@
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@vitest/snapshot": {
|
"packages/companion-teams/node_modules/@vitest/snapshot": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz",
|
||||||
"integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==",
|
"integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==",
|
||||||
|
|
@ -7755,7 +7726,7 @@
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@vitest/spy": {
|
"packages/companion-teams/node_modules/@vitest/spy": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz",
|
||||||
"integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==",
|
"integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==",
|
||||||
|
|
@ -7765,7 +7736,7 @@
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/@vitest/utils": {
|
"packages/companion-teams/node_modules/@vitest/utils": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz",
|
||||||
"integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==",
|
"integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==",
|
||||||
|
|
@ -7779,7 +7750,7 @@
|
||||||
"url": "https://opencollective.com/vitest"
|
"url": "https://opencollective.com/vitest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/chai": {
|
"packages/companion-teams/node_modules/chai": {
|
||||||
"version": "6.2.2",
|
"version": "6.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
|
||||||
"integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
|
"integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
|
||||||
|
|
@ -7789,7 +7760,7 @@
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/picomatch": {
|
"packages/companion-teams/node_modules/picomatch": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
|
|
@ -7802,7 +7773,7 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/tinyexec": {
|
"packages/companion-teams/node_modules/tinyexec": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",
|
||||||
"integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
|
"integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==",
|
||||||
|
|
@ -7812,7 +7783,7 @@
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/tinyrainbow": {
|
"packages/companion-teams/node_modules/tinyrainbow": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz",
|
||||||
"integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==",
|
"integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==",
|
||||||
|
|
@ -7822,14 +7793,14 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/undici-types": {
|
"packages/companion-teams/node_modules/undici-types": {
|
||||||
"version": "7.18.2",
|
"version": "7.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||||
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"packages/pi-teams/node_modules/vitest": {
|
"packages/companion-teams/node_modules/vitest": {
|
||||||
"version": "4.0.18",
|
"version": "4.0.18",
|
||||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz",
|
||||||
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
|
"integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==",
|
||||||
|
|
@ -7907,17 +7878,46 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/pods": {
|
"packages/mom": {
|
||||||
"name": "@mariozechner/pi",
|
"name": "@mariozechner/companion-mom",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"extraneous": true,
|
"extraneous": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mariozechner/pi-agent-core": "^0.56.2",
|
"@anthropic-ai/sandbox-runtime": "^0.0.16",
|
||||||
|
"@mariozechner/companion-agent-core": "^0.56.2",
|
||||||
|
"@mariozechner/companion-ai": "^0.56.2",
|
||||||
|
"@mariozechner/companion-coding-agent": "^0.56.2",
|
||||||
|
"@sinclair/typebox": "^0.34.0",
|
||||||
|
"@slack/socket-mode": "^2.0.0",
|
||||||
|
"@slack/web-api": "^7.0.0",
|
||||||
|
"chalk": "^5.6.2",
|
||||||
|
"croner": "^9.1.0",
|
||||||
|
"diff": "^8.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"mom": "dist/main.js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/diff": "^7.0.2",
|
||||||
|
"@types/node": "^24.3.0",
|
||||||
|
"typescript": "^5.7.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"packages/pods": {
|
||||||
|
"name": "@mariozechner/companion",
|
||||||
|
"version": "0.56.2",
|
||||||
|
"extraneous": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@mariozechner/companion-agent-core": "^0.56.2",
|
||||||
"chalk": "^5.5.0"
|
"chalk": "^5.5.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"pi-pods": "dist/cli.js"
|
"companion-pods": "dist/cli.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -7925,7 +7925,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/tui": {
|
"packages/tui": {
|
||||||
"name": "@mariozechner/pi-tui",
|
"name": "@mariozechner/companion-tui",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "pi",
|
"name": "companion",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"homepage": "https://github.com/getcompanion-ai/co-mono#readme",
|
"homepage": "https://github.com/getcompanion-ai/co-mono#readme",
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
"dev": "concurrently --names \"ai,agent,coding-agent,tui\" --prefix-colors \"cyan,yellow,red,magenta\" \"cd packages/ai && npm run dev\" \"cd packages/agent && npm run dev\" \"cd packages/coding-agent && npm run dev\" \"cd packages/tui && npm run dev\"",
|
"dev": "concurrently --names \"ai,agent,coding-agent,tui\" --prefix-colors \"cyan,yellow,red,magenta\" \"cd packages/ai && npm run dev\" \"cd packages/agent && npm run dev\" \"cd packages/coding-agent && npm run dev\" \"cd packages/tui && npm run dev\"",
|
||||||
"dev:tsc": "cd packages/ai && npm run dev:tsc",
|
"dev:tsc": "cd packages/ai && npm run dev:tsc",
|
||||||
"check": "biome lint --error-on-warnings . && tsgo --noEmit && npm run check:browser-smoke",
|
"check": "biome lint --error-on-warnings . && tsgo --noEmit && npm run check:browser-smoke",
|
||||||
"check:browser-smoke": "sh -c 'esbuild scripts/browser-smoke-entry.ts --bundle --platform=browser --format=esm --log-limit=0 --outfile=/tmp/pi-browser-smoke.js > /tmp/pi-browser-smoke-errors.log 2>&1 || { echo \"Browser smoke check failed. See /tmp/pi-browser-smoke-errors.log\"; exit 1; }'",
|
"check:browser-smoke": "sh -c 'esbuild scripts/browser-smoke-entry.ts --bundle --platform=browser --format=esm --log-limit=0 --outfile=/tmp/companion-browser-smoke.js > /tmp/companion-browser-smoke-errors.log 2>&1 || { echo \"Browser smoke check failed. See /tmp/companion-browser-smoke-errors.log\"; exit 1; }'",
|
||||||
"test": "npm run test --workspaces --if-present",
|
"test": "npm run test --workspaces --if-present",
|
||||||
"version:patch": "npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install",
|
"version:patch": "npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install",
|
||||||
"version:minor": "npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install",
|
"version:minor": "npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install",
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mariozechner/jiti": "^2.6.5",
|
"@mariozechner/jiti": "^2.6.5",
|
||||||
"@mariozechner/pi-coding-agent": "^0.30.2",
|
"@mariozechner/companion-coding-agent": "^0.30.2",
|
||||||
"get-east-asian-width": "^1.4.0"
|
"get-east-asian-width": "^1.4.0"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed `continue()` to resume queued steering/follow-up messages when context currently ends in an assistant message, and preserved one-at-a-time steering ordering during assistant-tail resumes ([#1312](https://github.com/badlogic/pi-mono/pull/1312) by [@ferologics](https://github.com/ferologics))
|
- Fixed `continue()` to resume queued steering/follow-up messages when context currently ends in an assistant message, and preserved one-at-a-time steering ordering during assistant-tail resumes ([#1312](https://github.com/badlogic/companion-mono/pull/1312) by [@ferologics](https://github.com/ferologics))
|
||||||
|
|
||||||
## [0.52.6] - 2026-02-05
|
## [0.52.6] - 2026-02-05
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `maxRetryDelayMs` option to `AgentOptions` to cap server-requested retry delays. Passed through to the underlying stream function. ([#1123](https://github.com/badlogic/pi-mono/issues/1123))
|
- Added `maxRetryDelayMs` option to `AgentOptions` to cap server-requested retry delays. Passed through to the underlying stream function. ([#1123](https://github.com/badlogic/companion-mono/issues/1123))
|
||||||
|
|
||||||
## [0.50.7] - 2026-01-31
|
## [0.50.7] - 2026-01-31
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `thinkingBudgets` option on `Agent` and `AgentOptions` to customize token budgets per thinking level ([#529](https://github.com/badlogic/pi-mono/pull/529) by [@melihmucuk](https://github.com/melihmucuk))
|
- `thinkingBudgets` option on `Agent` and `AgentOptions` to customize token budgets per thinking level ([#529](https://github.com/badlogic/companion-mono/pull/529) by [@melihmucuk](https://github.com/melihmucuk))
|
||||||
|
|
||||||
## [0.37.8] - 2026-01-07
|
## [0.37.8] - 2026-01-07
|
||||||
|
|
||||||
|
|
@ -208,7 +208,7 @@
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- **Queue API replaced with steer/followUp**: The `queueMessage()` method has been split into two methods with different delivery semantics ([#403](https://github.com/badlogic/pi-mono/issues/403)):
|
- **Queue API replaced with steer/followUp**: The `queueMessage()` method has been split into two methods with different delivery semantics ([#403](https://github.com/badlogic/companion-mono/issues/403)):
|
||||||
- `steer(msg)`: Interrupts the agent mid-run. Delivered after current tool execution, skips remaining tools.
|
- `steer(msg)`: Interrupts the agent mid-run. Delivered after current tool execution, skips remaining tools.
|
||||||
- `followUp(msg)`: Waits until the agent finishes. Delivered only when there are no more tool calls or steering messages.
|
- `followUp(msg)`: Waits until the agent finishes. Delivered only when there are no more tool calls or steering messages.
|
||||||
- **Queue mode renamed**: `queueMode` option renamed to `steeringMode`. Added new `followUpMode` option. Both control whether messages are delivered one-at-a-time or all at once.
|
- **Queue mode renamed**: `queueMode` option renamed to `steeringMode`. Added new `followUpMode` option. Both control whether messages are delivered one-at-a-time or all at once.
|
||||||
|
|
@ -241,11 +241,11 @@
|
||||||
|
|
||||||
- **`UserMessageWithAttachments` and `Attachment` types removed**: Attachment handling is now the responsibility of the `convertToLlm` function.
|
- **`UserMessageWithAttachments` and `Attachment` types removed**: Attachment handling is now the responsibility of the `convertToLlm` function.
|
||||||
|
|
||||||
- **Agent loop moved from `@mariozechner/pi-ai`**: The `agentLoop`, `agentLoopContinue`, and related types have moved to this package. Import from `@mariozechner/pi-agent-core` instead.
|
- **Agent loop moved from `@mariozechner/companion-ai`**: The `agentLoop`, `agentLoopContinue`, and related types have moved to this package. Import from `@mariozechner/companion-agent-core` instead.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `streamFn` option on `Agent` for custom stream implementations. Default uses `streamSimple` from pi-ai.
|
- `streamFn` option on `Agent` for custom stream implementations. Default uses `streamSimple` from companion-ai.
|
||||||
|
|
||||||
- `streamProxy()` utility function for browser apps that need to proxy LLM calls through a backend server. Replaces the removed `AppTransport`.
|
- `streamProxy()` utility function for browser apps that need to proxy LLM calls through a backend server. Replaces the removed `AppTransport`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
# @mariozechner/pi-agent-core
|
# @mariozechner/companion-agent-core
|
||||||
|
|
||||||
Stateful agent with tool execution and event streaming. Built on `@mariozechner/pi-ai`.
|
Stateful agent with tool execution and event streaming. Built on `@mariozechner/companion-ai`.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @mariozechner/pi-agent-core
|
npm install @mariozechner/companion-agent-core
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Agent } from "@mariozechner/pi-agent-core";
|
import { Agent } from "@mariozechner/companion-agent-core";
|
||||||
import { getModel } from "@mariozechner/pi-ai";
|
import { getModel } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
const agent = new Agent({
|
const agent = new Agent({
|
||||||
initialState: {
|
initialState: {
|
||||||
|
|
@ -298,7 +298,7 @@ Follow-up messages are checked only when there are no more tool calls and no ste
|
||||||
Extend `AgentMessage` via declaration merging:
|
Extend `AgentMessage` via declaration merging:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
declare module "@mariozechner/pi-agent-core" {
|
declare module "@mariozechner/companion-agent-core" {
|
||||||
interface CustomAgentMessages {
|
interface CustomAgentMessages {
|
||||||
notification: { role: "notification"; text: string; timestamp: number };
|
notification: { role: "notification"; text: string; timestamp: number };
|
||||||
}
|
}
|
||||||
|
|
@ -378,7 +378,7 @@ Thrown errors are caught by the agent and reported to the LLM as tool errors wit
|
||||||
For browser apps that proxy through a backend:
|
For browser apps that proxy through a backend:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Agent, streamProxy } from "@mariozechner/pi-agent-core";
|
import { Agent, streamProxy } from "@mariozechner/companion-agent-core";
|
||||||
|
|
||||||
const agent = new Agent({
|
const agent = new Agent({
|
||||||
streamFn: (model, context, options) =>
|
streamFn: (model, context, options) =>
|
||||||
|
|
@ -395,7 +395,7 @@ const agent = new Agent({
|
||||||
For direct control without the Agent class:
|
For direct control without the Agent class:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { agentLoop, agentLoopContinue } from "@mariozechner/pi-agent-core";
|
import { agentLoop, agentLoopContinue } from "@mariozechner/companion-agent-core";
|
||||||
|
|
||||||
const context: AgentContext = {
|
const context: AgentContext = {
|
||||||
systemPrompt: "You are helpful.",
|
systemPrompt: "You are helpful.",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@mariozechner/pi-agent-core",
|
"name": "@mariozechner/companion-agent-core",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
"prepublishOnly": "npm run clean && npm run build"
|
"prepublishOnly": "npm run clean && npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mariozechner/pi-ai": "^0.56.2"
|
"@mariozechner/companion-ai": "^0.56.2"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ai",
|
"ai",
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
streamSimple,
|
streamSimple,
|
||||||
type ToolResultMessage,
|
type ToolResultMessage,
|
||||||
validateToolArguments,
|
validateToolArguments,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import type {
|
import type {
|
||||||
AgentContext,
|
AgentContext,
|
||||||
AgentEvent,
|
AgentEvent,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import {
|
||||||
type TextContent,
|
type TextContent,
|
||||||
type ThinkingBudgets,
|
type ThinkingBudgets,
|
||||||
type Transport,
|
type Transport,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import { agentLoop, agentLoopContinue } from "./agent-loop.js";
|
import { agentLoop, agentLoopContinue } from "./agent-loop.js";
|
||||||
import type {
|
import type {
|
||||||
AgentContext,
|
AgentContext,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import {
|
||||||
type SimpleStreamOptions,
|
type SimpleStreamOptions,
|
||||||
type StopReason,
|
type StopReason,
|
||||||
type ToolCall,
|
type ToolCall,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Create stream class matching ProxyMessageEventStream
|
// Create stream class matching ProxyMessageEventStream
|
||||||
class ProxyMessageEventStream extends EventStream<
|
class ProxyMessageEventStream extends EventStream<
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import type {
|
||||||
TextContent,
|
TextContent,
|
||||||
Tool,
|
Tool,
|
||||||
ToolResultMessage,
|
ToolResultMessage,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import type { Static, TSchema } from "@sinclair/typebox";
|
import type { Static, TSchema } from "@sinclair/typebox";
|
||||||
|
|
||||||
/** Stream function - can return sync or Promise for async config lookup */
|
/** Stream function - can return sync or Promise for async config lookup */
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
type Message,
|
type Message,
|
||||||
type Model,
|
type Model,
|
||||||
type UserMessage,
|
type UserMessage,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import { Type } from "@sinclair/typebox";
|
import { Type } from "@sinclair/typebox";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { agentLoop, agentLoopContinue } from "../src/agent-loop.js";
|
import { agentLoop, agentLoopContinue } from "../src/agent-loop.js";
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import {
|
||||||
type AssistantMessageEvent,
|
type AssistantMessageEvent,
|
||||||
EventStream,
|
EventStream,
|
||||||
getModel,
|
getModel,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { Agent } from "../src/index.js";
|
import { Agent } from "../src/index.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
* You can run this test suite with:
|
* You can run this test suite with:
|
||||||
* ```bash
|
* ```bash
|
||||||
* $ AWS_REGION=us-east-1 BEDROCK_EXTENSIVE_MODEL_TEST=1 AWS_PROFILE=pi npm test -- ./test/bedrock-models.test.ts
|
* $ AWS_REGION=us-east-1 BEDROCK_EXTENSIVE_MODEL_TEST=1 AWS_PROFILE=companion npm test -- ./test/bedrock-models.test.ts
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* ## Known Issues by Category
|
* ## Known Issues by Category
|
||||||
|
|
@ -21,8 +21,8 @@
|
||||||
* 5. **Invalid Signature Format**: Model validates signature format (Anthropic newer models).
|
* 5. **Invalid Signature Format**: Model validates signature format (Anthropic newer models).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
import type { AssistantMessage } from "@mariozechner/companion-ai";
|
||||||
import { getModels } from "@mariozechner/pi-ai";
|
import { getModels } from "@mariozechner/companion-ai";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { Agent } from "../src/index.js";
|
import { Agent } from "../src/index.js";
|
||||||
import { hasBedrockCredentials } from "./bedrock-utils.js";
|
import { hasBedrockCredentials } from "./bedrock-utils.js";
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import type {
|
||||||
Model,
|
Model,
|
||||||
ToolResultMessage,
|
ToolResultMessage,
|
||||||
UserMessage,
|
UserMessage,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import { getModel } from "@mariozechner/pi-ai";
|
import { getModel } from "@mariozechner/companion-ai";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { Agent } from "../src/index.js";
|
import { Agent } from "../src/index.js";
|
||||||
import { hasBedrockCredentials } from "./bedrock-utils.js";
|
import { hasBedrockCredentials } from "./bedrock-utils.js";
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,16 @@
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `gpt-5.4` model support for `openai`, `openai-codex`, `azure-openai-responses`, and `opencode` providers, with GPT-5.4 treated as xhigh-capable and capped to a 272000 context window in built-in metadata.
|
- Added `gpt-5.4` model support for `openai`, `openai-codex`, `azure-openai-responses`, and `opencode` providers, with GPT-5.4 treated as xhigh-capable and capped to a 272000 context window in built-in metadata.
|
||||||
- Added `gpt-5.3-codex` fallback model availability for `github-copilot` until upstream model catalogs include it ([#1853](https://github.com/badlogic/pi-mono/issues/1853)).
|
- Added `gpt-5.3-codex` fallback model availability for `github-copilot` until upstream model catalogs include it ([#1853](https://github.com/badlogic/companion-mono/issues/1853)).
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Preserved OpenAI Responses assistant `phase` metadata (`commentary`, `final_answer`) across turns by encoding `id` and `phase` in `textSignature` for session persistence and replay, with backward compatibility for legacy plain signatures ([#1819](https://github.com/badlogic/pi-mono/issues/1819)).
|
- Preserved OpenAI Responses assistant `phase` metadata (`commentary`, `final_answer`) across turns by encoding `id` and `phase` in `textSignature` for session persistence and replay, with backward compatibility for legacy plain signatures ([#1819](https://github.com/badlogic/companion-mono/issues/1819)).
|
||||||
- Fixed OpenAI Responses replay to omit empty thinking blocks, avoiding invalid no-op reasoning items in follow-up turns.
|
- Fixed OpenAI Responses replay to omit empty thinking blocks, avoiding invalid no-op reasoning items in follow-up turns.
|
||||||
- Switched the Mistral provider from the OpenAI-compatible completions path to Mistral's native SDK and conversations API, preserving native thinking blocks and Mistral-specific message semantics across turns ([#1716](https://github.com/badlogic/pi-mono/issues/1716)).
|
- Switched the Mistral provider from the OpenAI-compatible completions path to Mistral's native SDK and conversations API, preserving native thinking blocks and Mistral-specific message semantics across turns ([#1716](https://github.com/badlogic/companion-mono/issues/1716)).
|
||||||
- Fixed Antigravity endpoint fallback: 403/404 responses now cascade to the next endpoint instead of throwing immediately, added `autopush-cloudcode-pa.sandbox` endpoint to the fallback list, and removed extra fingerprint headers (`X-Goog-Api-Client`, `Client-Metadata`) from Antigravity requests ([#1830](https://github.com/badlogic/pi-mono/issues/1830)).
|
- Fixed Antigravity endpoint fallback: 403/404 responses now cascade to the next endpoint instead of throwing immediately, added `autopush-cloudcode-pa.sandbox` endpoint to the fallback list, and removed extra fingerprint headers (`X-Goog-Api-Client`, `Client-Metadata`) from Antigravity requests ([#1830](https://github.com/badlogic/companion-mono/issues/1830)).
|
||||||
- Fixed `@mariozechner/pi-ai/oauth` package exports to point directly at built `dist` files, avoiding broken TypeScript resolution through unpublished wrapper targets ([#1856](https://github.com/badlogic/pi-mono/issues/1856)).
|
- Fixed `@mariozechner/companion-ai/oauth` package exports to point directly at built `dist` files, avoiding broken TypeScript resolution through unpublished wrapper targets ([#1856](https://github.com/badlogic/companion-mono/issues/1856)).
|
||||||
- Fixed Gemini 3 unsigned tool call replay: use `skip_thought_signature_validator` sentinel instead of converting function calls to text, preserving structured tool call context across multi-turn conversations ([#1829](https://github.com/badlogic/pi-mono/issues/1829)).
|
- Fixed Gemini 3 unsigned tool call replay: use `skip_thought_signature_validator` sentinel instead of converting function calls to text, preserving structured tool call context across multi-turn conversations ([#1829](https://github.com/badlogic/companion-mono/issues/1829)).
|
||||||
|
|
||||||
## [0.56.1] - 2026-03-05
|
## [0.56.1] - 2026-03-05
|
||||||
|
|
||||||
|
|
@ -24,12 +24,12 @@
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- Moved Node OAuth runtime exports off the top-level package entry. Import OAuth login/refresh functions from `@mariozechner/pi-ai/oauth` instead of `@mariozechner/pi-ai` ([#1814](https://github.com/badlogic/pi-mono/issues/1814))
|
- Moved Node OAuth runtime exports off the top-level package entry. Import OAuth login/refresh functions from `@mariozechner/companion-ai/oauth` instead of `@mariozechner/companion-ai` ([#1814](https://github.com/badlogic/companion-mono/issues/1814))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `gemini-3.1-flash-lite-preview` fallback model entry for the `google` provider so it remains selectable until upstream model catalogs include it ([#1785](https://github.com/badlogic/pi-mono/issues/1785), thanks [@n-WN](https://github.com/n-WN)).
|
- Added `gemini-3.1-flash-lite-preview` fallback model entry for the `google` provider so it remains selectable until upstream model catalogs include it ([#1785](https://github.com/badlogic/companion-mono/issues/1785), thanks [@n-WN](https://github.com/n-WN)).
|
||||||
- Added OpenCode Go provider support with `opencode-go` model catalog entries and `OPENCODE_API_KEY` environment variable support ([#1757](https://github.com/badlogic/pi-mono/issues/1757)).
|
- Added OpenCode Go provider support with `opencode-go` model catalog entries and `OPENCODE_API_KEY` environment variable support ([#1757](https://github.com/badlogic/companion-mono/issues/1757)).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
@ -37,11 +37,11 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed Gemini 3.1 thinking-level detection in `google` and `google-vertex` providers so `gemini-3.1-*` models use Gemini 3 level-based thinking config instead of budget fallback ([#1785](https://github.com/badlogic/pi-mono/issues/1785), thanks [@n-WN](https://github.com/n-WN)).
|
- Fixed Gemini 3.1 thinking-level detection in `google` and `google-vertex` providers so `gemini-3.1-*` models use Gemini 3 level-based thinking config instead of budget fallback ([#1785](https://github.com/badlogic/companion-mono/issues/1785), thanks [@n-WN](https://github.com/n-WN)).
|
||||||
- Fixed browser bundling failures by lazy-loading the Bedrock provider and removing Node-only side effects from the default browser import graph ([#1814](https://github.com/badlogic/pi-mono/issues/1814)).
|
- Fixed browser bundling failures by lazy-loading the Bedrock provider and removing Node-only side effects from the default browser import graph ([#1814](https://github.com/badlogic/companion-mono/issues/1814)).
|
||||||
- Fixed `ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING` failures by replacing `Function`-based dynamic imports with module dynamic imports in browser-safe provider loading paths ([#1814](https://github.com/badlogic/pi-mono/issues/1814)).
|
- Fixed `ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING` failures by replacing `Function`-based dynamic imports with module dynamic imports in browser-safe provider loading paths ([#1814](https://github.com/badlogic/companion-mono/issues/1814)).
|
||||||
- Fixed Bedrock region resolution for `AWS_PROFILE` by honoring `region` from the selected profile when present ([#1800](https://github.com/badlogic/pi-mono/issues/1800)).
|
- Fixed Bedrock region resolution for `AWS_PROFILE` by honoring `region` from the selected profile when present ([#1800](https://github.com/badlogic/companion-mono/issues/1800)).
|
||||||
- Fixed Groq Qwen3 reasoning effort mapping by translating unsupported effort values to provider-supported values ([#1745](https://github.com/badlogic/pi-mono/issues/1745)).
|
- Fixed Groq Qwen3 reasoning effort mapping by translating unsupported effort values to provider-supported values ([#1745](https://github.com/badlogic/companion-mono/issues/1745)).
|
||||||
|
|
||||||
## [0.55.4] - 2026-03-02
|
## [0.55.4] - 2026-03-02
|
||||||
|
|
||||||
|
|
@ -52,23 +52,23 @@
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Restored built-in OAuth providers when unregistering dynamically registered provider IDs and added `resetOAuthProviders()` for registry reset flows.
|
- Restored built-in OAuth providers when unregistering dynamically registered provider IDs and added `resetOAuthProviders()` for registry reset flows.
|
||||||
- Fixed Z.ai thinking control using wrong parameter name (`thinking` instead of `enable_thinking`), causing thinking to always be enabled and wasting tokens/latency ([#1674](https://github.com/badlogic/pi-mono/pull/1674) by [@okuyam2y](https://github.com/okuyam2y))
|
- Fixed Z.ai thinking control using wrong parameter name (`thinking` instead of `enable_thinking`), causing thinking to always be enabled and wasting tokens/latency ([#1674](https://github.com/badlogic/companion-mono/pull/1674) by [@okuyam2y](https://github.com/okuyam2y))
|
||||||
- Fixed `redacted_thinking` blocks being silently dropped during Anthropic streaming. They are now captured as `ThinkingContent` with `redacted: true`, passed back to the API in multi-turn conversations, and handled in cross-model message transformation ([#1665](https://github.com/badlogic/pi-mono/pull/1665) by [@tctev](https://github.com/tctev))
|
- Fixed `redacted_thinking` blocks being silently dropped during Anthropic streaming. They are now captured as `ThinkingContent` with `redacted: true`, passed back to the API in multi-turn conversations, and handled in cross-model message transformation ([#1665](https://github.com/badlogic/companion-mono/pull/1665) by [@tctev](https://github.com/tctev))
|
||||||
- Fixed `interleaved-thinking-2025-05-14` beta header being sent for adaptive thinking models (Opus 4.6, Sonnet 4.6) where the header is deprecated or redundant ([#1665](https://github.com/badlogic/pi-mono/pull/1665) by [@tctev](https://github.com/tctev))
|
- Fixed `interleaved-thinking-2025-05-14` beta header being sent for adaptive thinking models (Opus 4.6, Sonnet 4.6) where the header is deprecated or redundant ([#1665](https://github.com/badlogic/companion-mono/pull/1665) by [@tctev](https://github.com/tctev))
|
||||||
- Fixed temperature being sent alongside extended thinking, which is incompatible with both adaptive and budget-based thinking modes ([#1665](https://github.com/badlogic/pi-mono/pull/1665) by [@tctev](https://github.com/tctev))
|
- Fixed temperature being sent alongside extended thinking, which is incompatible with both adaptive and budget-based thinking modes ([#1665](https://github.com/badlogic/companion-mono/pull/1665) by [@tctev](https://github.com/tctev))
|
||||||
- Fixed `(external, cli)` user-agent flag causing 401 errors on Anthropic setup-token endpoint ([#1677](https://github.com/badlogic/pi-mono/pull/1677) by [@LazerLance777](https://github.com/LazerLance777))
|
- Fixed `(external, cli)` user-agent flag causing 401 errors on Anthropic setup-token endpoint ([#1677](https://github.com/badlogic/companion-mono/pull/1677) by [@LazerLance777](https://github.com/LazerLance777))
|
||||||
- Fixed crash when OpenAI-compatible provider returns a chunk with no `choices` array by adding optional chaining ([#1671](https://github.com/badlogic/pi-mono/issues/1671))
|
- Fixed crash when OpenAI-compatible provider returns a chunk with no `choices` array by adding optional chaining ([#1671](https://github.com/badlogic/companion-mono/issues/1671))
|
||||||
|
|
||||||
## [0.55.1] - 2026-02-26
|
## [0.55.1] - 2026-02-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `gemini-3.1-pro-preview` model support to the `google-gemini-cli` provider ([#1599](https://github.com/badlogic/pi-mono/pull/1599) by [@audichuang](https://github.com/audichuang))
|
- Added `gemini-3.1-pro-preview` model support to the `google-gemini-cli` provider ([#1599](https://github.com/badlogic/companion-mono/pull/1599) by [@audichuang](https://github.com/audichuang))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed adaptive thinking for Claude Sonnet 4.6 in Anthropic and Bedrock providers, and clamped unsupported `xhigh` effort values to supported levels ([#1548](https://github.com/badlogic/pi-mono/pull/1548) by [@tctev](https://github.com/tctev))
|
- Fixed adaptive thinking for Claude Sonnet 4.6 in Anthropic and Bedrock providers, and clamped unsupported `xhigh` effort values to supported levels ([#1548](https://github.com/badlogic/companion-mono/pull/1548) by [@tctev](https://github.com/tctev))
|
||||||
- Fixed Vertex ADC credential detection race by avoiding caching a false negative during async import initialization ([#1550](https://github.com/badlogic/pi-mono/pull/1550) by [@jeremiahgaylord-web](https://github.com/jeremiahgaylord-web))
|
- Fixed Vertex ADC credential detection race by avoiding caching a false negative during async import initialization ([#1550](https://github.com/badlogic/companion-mono/pull/1550) by [@jeremiahgaylord-web](https://github.com/jeremiahgaylord-web))
|
||||||
|
|
||||||
## [0.55.0] - 2026-02-24
|
## [0.55.0] - 2026-02-24
|
||||||
|
|
||||||
|
|
@ -108,16 +108,16 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added optional `metadata` field to `StreamOptions` for passing provider-specific metadata (e.g. Anthropic `user_id` for abuse tracking/rate limiting) ([#1384](https://github.com/badlogic/pi-mono/pull/1384) by [@7Sageer](https://github.com/7Sageer))
|
- Added optional `metadata` field to `StreamOptions` for passing provider-specific metadata (e.g. Anthropic `user_id` for abuse tracking/rate limiting) ([#1384](https://github.com/badlogic/companion-mono/pull/1384) by [@7Sageer](https://github.com/7Sageer))
|
||||||
- Added `gpt-5.3-codex-spark` model definition for OpenAI and OpenAI Codex providers (128k context, text-only, research preview). Not yet functional, may become available in the next few hours or days.
|
- Added `gpt-5.3-codex-spark` model definition for OpenAI and OpenAI Codex providers (128k context, text-only, research preview). Not yet functional, may become available in the next few hours or days.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Routed GitHub Copilot Claude 4.x models through Anthropic Messages API, centralized Copilot dynamic header handling, and added Copilot Claude Anthropic stream coverage ([#1353](https://github.com/badlogic/pi-mono/pull/1353) by [@NateSmyth](https://github.com/NateSmyth))
|
- Routed GitHub Copilot Claude 4.x models through Anthropic Messages API, centralized Copilot dynamic header handling, and added Copilot Claude Anthropic stream coverage ([#1353](https://github.com/badlogic/companion-mono/pull/1353) by [@NateSmyth](https://github.com/NateSmyth))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI completions and responses streams to tolerate malformed trailing tool-call JSON without failing parsing ([#1424](https://github.com/badlogic/pi-mono/issues/1424))
|
- Fixed OpenAI completions and responses streams to tolerate malformed trailing tool-call JSON without failing parsing ([#1424](https://github.com/badlogic/companion-mono/issues/1424))
|
||||||
|
|
||||||
## [0.52.9] - 2026-02-08
|
## [0.52.9] - 2026-02-08
|
||||||
|
|
||||||
|
|
@ -127,31 +127,31 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Use `parametersJsonSchema` for Google provider tool declarations to support full JSON Schema (anyOf, oneOf, const, etc.) ([#1398](https://github.com/badlogic/pi-mono/issues/1398) by [@jarib](https://github.com/jarib))
|
- Use `parametersJsonSchema` for Google provider tool declarations to support full JSON Schema (anyOf, oneOf, const, etc.) ([#1398](https://github.com/badlogic/companion-mono/issues/1398) by [@jarib](https://github.com/jarib))
|
||||||
- Reverted incorrect Antigravity model change: `claude-opus-4-6-thinking` back to `claude-opus-4-5-thinking` (model doesn't exist on Antigravity endpoint)
|
- Reverted incorrect Antigravity model change: `claude-opus-4-6-thinking` back to `claude-opus-4-5-thinking` (model doesn't exist on Antigravity endpoint)
|
||||||
- Corrected opencode context windows for Claude Sonnet 4 and 4.5 ([#1383](https://github.com/badlogic/pi-mono/issues/1383))
|
- Corrected opencode context windows for Claude Sonnet 4 and 4.5 ([#1383](https://github.com/badlogic/companion-mono/issues/1383))
|
||||||
|
|
||||||
## [0.52.8] - 2026-02-07
|
## [0.52.8] - 2026-02-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added OpenRouter `auto` model alias for automatic model routing ([#1361](https://github.com/badlogic/pi-mono/pull/1361) by [@yogasanas](https://github.com/yogasanas))
|
- Added OpenRouter `auto` model alias for automatic model routing ([#1361](https://github.com/badlogic/companion-mono/pull/1361) by [@yogasanas](https://github.com/yogasanas))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Replaced Claude Opus 4.5 with Opus 4.6 in model definitions ([#1345](https://github.com/badlogic/pi-mono/pull/1345) by [@calvin-hpnet](https://github.com/calvin-hpnet))
|
- Replaced Claude Opus 4.5 with Opus 4.6 in model definitions ([#1345](https://github.com/badlogic/companion-mono/pull/1345) by [@calvin-hpnet](https://github.com/calvin-hpnet))
|
||||||
|
|
||||||
## [0.52.7] - 2026-02-06
|
## [0.52.7] - 2026-02-06
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `AWS_BEDROCK_SKIP_AUTH` and `AWS_BEDROCK_FORCE_HTTP1` environment variables for connecting to unauthenticated Bedrock proxies ([#1320](https://github.com/badlogic/pi-mono/pull/1320) by [@virtuald](https://github.com/virtuald))
|
- Added `AWS_BEDROCK_SKIP_AUTH` and `AWS_BEDROCK_FORCE_HTTP1` environment variables for connecting to unauthenticated Bedrock proxies ([#1320](https://github.com/badlogic/companion-mono/pull/1320) by [@virtuald](https://github.com/virtuald))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Set OpenAI Responses API requests to `store: false` by default to avoid server-side history logging ([#1308](https://github.com/badlogic/pi-mono/issues/1308))
|
- Set OpenAI Responses API requests to `store: false` by default to avoid server-side history logging ([#1308](https://github.com/badlogic/companion-mono/issues/1308))
|
||||||
- Re-exported TypeBox `Type`, `Static`, and `TSchema` from `@mariozechner/pi-ai` to match documentation and avoid duplicate TypeBox type identity issues in pnpm setups ([#1338](https://github.com/badlogic/pi-mono/issues/1338))
|
- Re-exported TypeBox `Type`, `Static`, and `TSchema` from `@mariozechner/companion-ai` to match documentation and avoid duplicate TypeBox type identity issues in pnpm setups ([#1338](https://github.com/badlogic/companion-mono/issues/1338))
|
||||||
- Fixed Bedrock adaptive thinking handling for Claude Opus 4.6 with interleaved thinking beta responses ([#1323](https://github.com/badlogic/pi-mono/pull/1323) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- Fixed Bedrock adaptive thinking handling for Claude Opus 4.6 with interleaved thinking beta responses ([#1323](https://github.com/badlogic/companion-mono/pull/1323) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
- Fixed `AWS_BEDROCK_SKIP_AUTH` environment detection to avoid `process` access in non-Node.js environments
|
- Fixed `AWS_BEDROCK_SKIP_AUTH` environment detection to avoid `process` access in non-Node.js environments
|
||||||
|
|
||||||
## [0.52.6] - 2026-02-05
|
## [0.52.6] - 2026-02-05
|
||||||
|
|
@ -201,13 +201,13 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI Codex Responses provider to respect configured baseUrl ([#1244](https://github.com/badlogic/pi-mono/issues/1244))
|
- Fixed OpenAI Codex Responses provider to respect configured baseUrl ([#1244](https://github.com/badlogic/companion-mono/issues/1244))
|
||||||
|
|
||||||
## [0.51.5] - 2026-02-04
|
## [0.51.5] - 2026-02-04
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Changed Bedrock model generation to drop legacy workarounds now handled upstream ([#1239](https://github.com/badlogic/pi-mono/pull/1239) by [@unexge](https://github.com/unexge))
|
- Changed Bedrock model generation to drop legacy workarounds now handled upstream ([#1239](https://github.com/badlogic/companion-mono/pull/1239) by [@unexge](https://github.com/unexge))
|
||||||
|
|
||||||
## [0.51.4] - 2026-02-03
|
## [0.51.4] - 2026-02-03
|
||||||
|
|
||||||
|
|
@ -215,7 +215,7 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed xhigh thinking level support check to accept gpt-5.2 model IDs ([#1209](https://github.com/badlogic/pi-mono/issues/1209))
|
- Fixed xhigh thinking level support check to accept gpt-5.2 model IDs ([#1209](https://github.com/badlogic/companion-mono/issues/1209))
|
||||||
|
|
||||||
## [0.51.2] - 2026-02-03
|
## [0.51.2] - 2026-02-03
|
||||||
|
|
||||||
|
|
@ -229,23 +229,23 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed `cacheRetention` option not being passed through in `buildBaseOptions` ([#1154](https://github.com/badlogic/pi-mono/issues/1154))
|
- Fixed `cacheRetention` option not being passed through in `buildBaseOptions` ([#1154](https://github.com/badlogic/companion-mono/issues/1154))
|
||||||
- Fixed OAuth login/refresh not using HTTP proxy settings (`HTTP_PROXY`, `HTTPS_PROXY` env vars) ([#1132](https://github.com/badlogic/pi-mono/issues/1132))
|
- Fixed OAuth login/refresh not using HTTP proxy settings (`HTTP_PROXY`, `HTTPS_PROXY` env vars) ([#1132](https://github.com/badlogic/companion-mono/issues/1132))
|
||||||
- Fixed OpenAI-compatible completions to omit unsupported `strict` tool fields for providers that reject them ([#1172](https://github.com/badlogic/pi-mono/issues/1172))
|
- Fixed OpenAI-compatible completions to omit unsupported `strict` tool fields for providers that reject them ([#1172](https://github.com/badlogic/companion-mono/issues/1172))
|
||||||
|
|
||||||
## [0.50.9] - 2026-02-01
|
## [0.50.9] - 2026-02-01
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `PI_AI_ANTIGRAVITY_VERSION` environment variable to override the Antigravity User-Agent version when Google updates their version requirements ([#1129](https://github.com/badlogic/pi-mono/issues/1129))
|
- Added `COMPANION_AI_ANTIGRAVITY_VERSION` environment variable to override the Antigravity User-Agent version when Google updates their version requirements ([#1129](https://github.com/badlogic/companion-mono/issues/1129))
|
||||||
- Added `cacheRetention` stream option with provider-specific mappings for prompt cache controls, defaulting to short retention ([#1134](https://github.com/badlogic/pi-mono/issues/1134))
|
- Added `cacheRetention` stream option with provider-specific mappings for prompt cache controls, defaulting to short retention ([#1134](https://github.com/badlogic/companion-mono/issues/1134))
|
||||||
|
|
||||||
## [0.50.8] - 2026-02-01
|
## [0.50.8] - 2026-02-01
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `maxRetryDelayMs` option to `StreamOptions` to cap server-requested retry delays. When a provider (e.g., Google Gemini CLI) requests a delay longer than this value, the request fails immediately with an informative error instead of waiting silently. Default: 60000ms (60 seconds). Set to 0 to disable the cap. ([#1123](https://github.com/badlogic/pi-mono/issues/1123))
|
- Added `maxRetryDelayMs` option to `StreamOptions` to cap server-requested retry delays. When a provider (e.g., Google Gemini CLI) requests a delay longer than this value, the request fails immediately with an informative error instead of waiting silently. Default: 60000ms (60 seconds). Set to 0 to disable the cap. ([#1123](https://github.com/badlogic/companion-mono/issues/1123))
|
||||||
- Added Qwen thinking format support for OpenAI-compatible completions via `enable_thinking`. ([#940](https://github.com/badlogic/pi-mono/pull/940) by [@4h9fbZ](https://github.com/4h9fbZ))
|
- Added Qwen thinking format support for OpenAI-compatible completions via `enable_thinking`. ([#940](https://github.com/badlogic/companion-mono/pull/940) by [@4h9fbZ](https://github.com/4h9fbZ))
|
||||||
|
|
||||||
## [0.50.7] - 2026-01-31
|
## [0.50.7] - 2026-01-31
|
||||||
|
|
||||||
|
|
@ -257,12 +257,12 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added Vercel AI Gateway routing support via `vercelGatewayRouting` option in model config ([#1051](https://github.com/badlogic/pi-mono/pull/1051) by [@ben-vargas](https://github.com/ben-vargas))
|
- Added Vercel AI Gateway routing support via `vercelGatewayRouting` option in model config ([#1051](https://github.com/badlogic/companion-mono/pull/1051) by [@ben-vargas](https://github.com/ben-vargas))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Updated Antigravity User-Agent from 1.11.5 to 1.15.8 to fix rejected requests ([#1079](https://github.com/badlogic/pi-mono/issues/1079))
|
- Updated Antigravity User-Agent from 1.11.5 to 1.15.8 to fix rejected requests ([#1079](https://github.com/badlogic/companion-mono/issues/1079))
|
||||||
- Fixed tool call argument defaults for Anthropic and Google history conversion when providers omit inputs ([#1065](https://github.com/badlogic/pi-mono/issues/1065))
|
- Fixed tool call argument defaults for Anthropic and Google history conversion when providers omit inputs ([#1065](https://github.com/badlogic/companion-mono/issues/1065))
|
||||||
|
|
||||||
## [0.50.3] - 2026-01-29
|
## [0.50.3] - 2026-01-29
|
||||||
|
|
||||||
|
|
@ -274,31 +274,31 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added Hugging Face provider support via OpenAI-compatible Inference Router ([#994](https://github.com/badlogic/pi-mono/issues/994))
|
- Added Hugging Face provider support via OpenAI-compatible Inference Router ([#994](https://github.com/badlogic/companion-mono/issues/994))
|
||||||
- Added `PI_CACHE_RETENTION` environment variable to control cache TTL for Anthropic (5m vs 1h) and OpenAI (in-memory vs 24h). Set to `long` for extended retention. Only applies to direct API calls (api.anthropic.com, api.openai.com). ([#967](https://github.com/badlogic/pi-mono/issues/967))
|
- Added `COMPANION_CACHE_RETENTION` environment variable to control cache TTL for Anthropic (5m vs 1h) and OpenAI (in-memory vs 24h). Set to `long` for extended retention. Only applies to direct API calls (api.anthropic.com, api.openai.com). ([#967](https://github.com/badlogic/companion-mono/issues/967))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI completions `toolChoice` handling to correctly set `type: "function"` wrapper ([#998](https://github.com/badlogic/pi-mono/pull/998) by [@williamtwomey](https://github.com/williamtwomey))
|
- Fixed OpenAI completions `toolChoice` handling to correctly set `type: "function"` wrapper ([#998](https://github.com/badlogic/companion-mono/pull/998) by [@williamtwomey](https://github.com/williamtwomey))
|
||||||
- Fixed cross-provider handoff failing when switching from OpenAI Responses API providers (github-copilot, openai-codex) to other providers due to pipe-separated tool call IDs not being normalized, and trailing underscores in truncated IDs being rejected by OpenAI Codex ([#1022](https://github.com/badlogic/pi-mono/issues/1022))
|
- Fixed cross-provider handoff failing when switching from OpenAI Responses API providers (github-copilot, openai-codex) to other providers due to pipe-separated tool call IDs not being normalized, and trailing underscores in truncated IDs being rejected by OpenAI Codex ([#1022](https://github.com/badlogic/companion-mono/issues/1022))
|
||||||
- Fixed 429 rate limit errors incorrectly triggering auto-compaction instead of retry with backoff ([#1038](https://github.com/badlogic/pi-mono/issues/1038))
|
- Fixed 429 rate limit errors incorrectly triggering auto-compaction instead of retry with backoff ([#1038](https://github.com/badlogic/companion-mono/issues/1038))
|
||||||
- Fixed Anthropic provider to handle `sensitive` stop_reason returned by API ([#978](https://github.com/badlogic/pi-mono/issues/978))
|
- Fixed Anthropic provider to handle `sensitive` stop_reason returned by API ([#978](https://github.com/badlogic/companion-mono/issues/978))
|
||||||
- Fixed DeepSeek API compatibility by detecting `deepseek.com` URLs and disabling unsupported `developer` role ([#1048](https://github.com/badlogic/pi-mono/issues/1048))
|
- Fixed DeepSeek API compatibility by detecting `deepseek.com` URLs and disabling unsupported `developer` role ([#1048](https://github.com/badlogic/companion-mono/issues/1048))
|
||||||
- Fixed Anthropic provider to preserve input token counts when proxies omit them in `message_delta` events ([#1045](https://github.com/badlogic/pi-mono/issues/1045))
|
- Fixed Anthropic provider to preserve input token counts when proxies omit them in `message_delta` events ([#1045](https://github.com/badlogic/companion-mono/issues/1045))
|
||||||
|
|
||||||
## [0.50.1] - 2026-01-26
|
## [0.50.1] - 2026-01-26
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenCode Zen model generation to exclude deprecated models ([#970](https://github.com/badlogic/pi-mono/pull/970) by [@DanielTatarkin](https://github.com/DanielTatarkin))
|
- Fixed OpenCode Zen model generation to exclude deprecated models ([#970](https://github.com/badlogic/companion-mono/pull/970) by [@DanielTatarkin](https://github.com/DanielTatarkin))
|
||||||
|
|
||||||
## [0.50.0] - 2026-01-26
|
## [0.50.0] - 2026-01-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added OpenRouter provider routing support for custom models via `openRouterRouting` compat field ([#859](https://github.com/badlogic/pi-mono/pull/859) by [@v01dpr1mr0s3](https://github.com/v01dpr1mr0s3))
|
- Added OpenRouter provider routing support for custom models via `openRouterRouting` compat field ([#859](https://github.com/badlogic/companion-mono/pull/859) by [@v01dpr1mr0s3](https://github.com/v01dpr1mr0s3))
|
||||||
- Added `azure-openai-responses` provider support for Azure OpenAI Responses API. ([#890](https://github.com/badlogic/pi-mono/pull/890) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- Added `azure-openai-responses` provider support for Azure OpenAI Responses API. ([#890](https://github.com/badlogic/companion-mono/pull/890) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
- Added HTTP proxy environment variable support for API requests ([#942](https://github.com/badlogic/pi-mono/pull/942) by [@haoqixu](https://github.com/haoqixu))
|
- Added HTTP proxy environment variable support for API requests ([#942](https://github.com/badlogic/companion-mono/pull/942) by [@haoqixu](https://github.com/haoqixu))
|
||||||
- Added `createAssistantMessageEventStream()` factory function for use in extensions.
|
- Added `createAssistantMessageEventStream()` factory function for use in extensions.
|
||||||
- Added `resetApiProviders()` to clear and re-register built-in API providers.
|
- Added `resetApiProviders()` to clear and re-register built-in API providers.
|
||||||
|
|
||||||
|
|
@ -310,13 +310,13 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed Bun runtime detection for dynamic imports in browser-compatible modules (stream.ts, openai-codex-responses.ts, openai-codex.ts) ([#922](https://github.com/badlogic/pi-mono/pull/922) by [@dannote](https://github.com/dannote))
|
- Fixed Bun runtime detection for dynamic imports in browser-compatible modules (stream.ts, openai-codex-responses.ts, openai-codex.ts) ([#922](https://github.com/badlogic/companion-mono/pull/922) by [@dannote](https://github.com/dannote))
|
||||||
- Fixed streaming functions to use `model.api` instead of hardcoded API types
|
- Fixed streaming functions to use `model.api` instead of hardcoded API types
|
||||||
- Fixed Google providers to default tool call arguments to an empty object when omitted
|
- Fixed Google providers to default tool call arguments to an empty object when omitted
|
||||||
- Fixed OpenAI Responses streaming to handle `arguments.done` events on OpenAI-compatible endpoints ([#917](https://github.com/badlogic/pi-mono/pull/917) by [@williballenthin](https://github.com/williballenthin))
|
- Fixed OpenAI Responses streaming to handle `arguments.done` events on OpenAI-compatible endpoints ([#917](https://github.com/badlogic/companion-mono/pull/917) by [@williballenthin](https://github.com/williballenthin))
|
||||||
- Fixed OpenAI Codex Responses tool strictness handling after the shared responses refactor
|
- Fixed OpenAI Codex Responses tool strictness handling after the shared responses refactor
|
||||||
- Fixed Azure OpenAI Responses streaming to guard deltas before content parts and correct metadata and handoff gating
|
- Fixed Azure OpenAI Responses streaming to guard deltas before content parts and correct metadata and handoff gating
|
||||||
- Fixed OpenAI completions tool-result image batching after consecutive tool results ([#902](https://github.com/badlogic/pi-mono/pull/902) by [@terrorobe](https://github.com/terrorobe))
|
- Fixed OpenAI completions tool-result image batching after consecutive tool results ([#902](https://github.com/badlogic/companion-mono/pull/902) by [@terrorobe](https://github.com/terrorobe))
|
||||||
|
|
||||||
## [0.49.3] - 2026-01-22
|
## [0.49.3] - 2026-01-22
|
||||||
|
|
||||||
|
|
@ -324,21 +324,21 @@
|
||||||
|
|
||||||
- Added `headers` option to `StreamOptions` for custom HTTP headers in API requests. Supported by all providers except Amazon Bedrock (which uses AWS SDK auth). Headers are merged with provider defaults and `model.headers`, with `options.headers` taking precedence.
|
- Added `headers` option to `StreamOptions` for custom HTTP headers in API requests. Supported by all providers except Amazon Bedrock (which uses AWS SDK auth). Headers are merged with provider defaults and `model.headers`, with `options.headers` taking precedence.
|
||||||
- Added `originator` option to `loginOpenAICodex()` for custom OAuth client identification
|
- Added `originator` option to `loginOpenAICodex()` for custom OAuth client identification
|
||||||
- Browser compatibility for pi-ai: replaced top-level Node.js imports with dynamic imports for browser environments ([#873](https://github.com/badlogic/pi-mono/issues/873))
|
- Browser compatibility for companion-ai: replaced top-level Node.js imports with dynamic imports for browser environments ([#873](https://github.com/badlogic/companion-mono/issues/873))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI Responses API 400 error "function_call without required reasoning item" when switching between models (same provider, different model). The fix omits the `id` field for function_calls from different models to avoid triggering OpenAI's reasoning/function_call pairing validation ([#886](https://github.com/badlogic/pi-mono/issues/886))
|
- Fixed OpenAI Responses API 400 error "function_call without required reasoning item" when switching between models (same provider, different model). The fix omits the `id` field for function_calls from different models to avoid triggering OpenAI's reasoning/function_call pairing validation ([#886](https://github.com/badlogic/companion-mono/issues/886))
|
||||||
|
|
||||||
## [0.49.2] - 2026-01-19
|
## [0.49.2] - 2026-01-19
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added AWS credential detection for ECS/Kubernetes environments: `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`, `AWS_CONTAINER_CREDENTIALS_FULL_URI`, `AWS_WEB_IDENTITY_TOKEN_FILE` ([#848](https://github.com/badlogic/pi-mono/issues/848))
|
- Added AWS credential detection for ECS/Kubernetes environments: `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`, `AWS_CONTAINER_CREDENTIALS_FULL_URI`, `AWS_WEB_IDENTITY_TOKEN_FILE` ([#848](https://github.com/badlogic/companion-mono/issues/848))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI Responses 400 error "reasoning without following item" by skipping errored/aborted assistant messages entirely in transform-messages.ts ([#838](https://github.com/badlogic/pi-mono/pull/838))
|
- Fixed OpenAI Responses 400 error "reasoning without following item" by skipping errored/aborted assistant messages entirely in transform-messages.ts ([#838](https://github.com/badlogic/companion-mono/pull/838))
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
@ -348,7 +348,7 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `OpenAIResponsesCompat` interface with `strictResponsesPairing` option for Azure OpenAI Responses API, which requires strict reasoning/message pairing in history replay ([#768](https://github.com/badlogic/pi-mono/pull/768) by [@prateekmedia](https://github.com/prateekmedia))
|
- Added `OpenAIResponsesCompat` interface with `strictResponsesPairing` option for Azure OpenAI Responses API, which requires strict reasoning/message pairing in history replay ([#768](https://github.com/badlogic/companion-mono/pull/768) by [@prateekmedia](https://github.com/prateekmedia))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
@ -356,7 +356,7 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed tool call ID normalization for cross-provider handoffs (e.g., Codex to Antigravity Claude) ([#821](https://github.com/badlogic/pi-mono/issues/821))
|
- Fixed tool call ID normalization for cross-provider handoffs (e.g., Codex to Antigravity Claude) ([#821](https://github.com/badlogic/companion-mono/issues/821))
|
||||||
|
|
||||||
## [0.49.0] - 2026-01-17
|
## [0.49.0] - 2026-01-17
|
||||||
|
|
||||||
|
|
@ -366,45 +366,45 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed orphaned tool results after errored assistant messages causing Codex API errors. When an assistant message has `stopReason: "error"`, its tool calls are now excluded from pending tool tracking, preventing synthetic tool results from being generated for calls that will be dropped by provider-specific converters. ([#812](https://github.com/badlogic/pi-mono/issues/812))
|
- Fixed orphaned tool results after errored assistant messages causing Codex API errors. When an assistant message has `stopReason: "error"`, its tool calls are now excluded from pending tool tracking, preventing synthetic tool results from being generated for calls that will be dropped by provider-specific converters. ([#812](https://github.com/badlogic/companion-mono/issues/812))
|
||||||
- Fixed Bedrock Claude max_tokens handling to always exceed thinking budget tokens, preventing compaction failures. ([#797](https://github.com/badlogic/pi-mono/pull/797) by [@pjtf93](https://github.com/pjtf93))
|
- Fixed Bedrock Claude max_tokens handling to always exceed thinking budget tokens, preventing compaction failures. ([#797](https://github.com/badlogic/companion-mono/pull/797) by [@pjtf93](https://github.com/pjtf93))
|
||||||
- Fixed Claude Code tool name normalization to match the Claude Code tool list case-insensitively and remove invalid mappings.
|
- Fixed Claude Code tool name normalization to match the Claude Code tool list case-insensitively and remove invalid mappings.
|
||||||
|
|
||||||
## [0.48.0] - 2026-01-16
|
## [0.48.0] - 2026-01-16
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI-compatible provider feature detection to use `model.provider` in addition to URL, allowing custom base URLs (e.g., proxies) to work correctly with provider-specific settings ([#774](https://github.com/badlogic/pi-mono/issues/774))
|
- Fixed OpenAI-compatible provider feature detection to use `model.provider` in addition to URL, allowing custom base URLs (e.g., proxies) to work correctly with provider-specific settings ([#774](https://github.com/badlogic/companion-mono/issues/774))
|
||||||
- Fixed Gemini 3 context loss when switching from providers without thought signatures: unsigned tool calls are now converted to text with anti-mimicry notes instead of being skipped
|
- Fixed Gemini 3 context loss when switching from providers without thought signatures: unsigned tool calls are now converted to text with anti-mimicry notes instead of being skipped
|
||||||
- Fixed string numbers in tool arguments not being coerced to numbers during validation ([#786](https://github.com/badlogic/pi-mono/pull/786) by [@dannote](https://github.com/dannote))
|
- Fixed string numbers in tool arguments not being coerced to numbers during validation ([#786](https://github.com/badlogic/companion-mono/pull/786) by [@dannote](https://github.com/dannote))
|
||||||
- Fixed Bedrock tool call IDs to use only alphanumeric characters, avoiding API errors from invalid characters ([#781](https://github.com/badlogic/pi-mono/pull/781) by [@pjtf93](https://github.com/pjtf93))
|
- Fixed Bedrock tool call IDs to use only alphanumeric characters, avoiding API errors from invalid characters ([#781](https://github.com/badlogic/companion-mono/pull/781) by [@pjtf93](https://github.com/pjtf93))
|
||||||
- Fixed empty error assistant messages (from 429/500 errors) breaking the tool_use to tool_result chain by filtering them in `transformMessages`
|
- Fixed empty error assistant messages (from 429/500 errors) breaking the tool_use to tool_result chain by filtering them in `transformMessages`
|
||||||
|
|
||||||
## [0.47.0] - 2026-01-16
|
## [0.47.0] - 2026-01-16
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenCode provider's `/v1` endpoint to use `system` role instead of `developer` role, fixing `400 Incorrect role information` error for models using `openai-completions` API ([#755](https://github.com/badlogic/pi-mono/pull/755) by [@melihmucuk](https://github.com/melihmucuk))
|
- Fixed OpenCode provider's `/v1` endpoint to use `system` role instead of `developer` role, fixing `400 Incorrect role information` error for models using `openai-completions` API ([#755](https://github.com/badlogic/companion-mono/pull/755) by [@melihmucuk](https://github.com/melihmucuk))
|
||||||
- Added retry logic to OpenAI Codex provider for transient errors (429, 5xx, connection failures). Uses exponential backoff with up to 3 retries. ([#733](https://github.com/badlogic/pi-mono/issues/733))
|
- Added retry logic to OpenAI Codex provider for transient errors (429, 5xx, connection failures). Uses exponential backoff with up to 3 retries. ([#733](https://github.com/badlogic/companion-mono/issues/733))
|
||||||
|
|
||||||
## [0.46.0] - 2026-01-15
|
## [0.46.0] - 2026-01-15
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added MiniMax China (`minimax-cn`) provider support ([#725](https://github.com/badlogic/pi-mono/pull/725) by [@tallshort](https://github.com/tallshort))
|
- Added MiniMax China (`minimax-cn`) provider support ([#725](https://github.com/badlogic/companion-mono/pull/725) by [@tallshort](https://github.com/tallshort))
|
||||||
- Added `gpt-5.2-codex` models for GitHub Copilot and OpenCode Zen providers ([#734](https://github.com/badlogic/pi-mono/pull/734) by [@aadishv](https://github.com/aadishv))
|
- Added `gpt-5.2-codex` models for GitHub Copilot and OpenCode Zen providers ([#734](https://github.com/badlogic/companion-mono/pull/734) by [@aadishv](https://github.com/aadishv))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Avoid unsigned Gemini 3 tool calls ([#741](https://github.com/badlogic/pi-mono/pull/741) by [@roshanasingh4](https://github.com/roshanasingh4))
|
- Avoid unsigned Gemini 3 tool calls ([#741](https://github.com/badlogic/companion-mono/pull/741) by [@roshanasingh4](https://github.com/roshanasingh4))
|
||||||
- Fixed signature support for non-Anthropic models in Amazon Bedrock provider ([#727](https://github.com/badlogic/pi-mono/pull/727) by [@unexge](https://github.com/unexge))
|
- Fixed signature support for non-Anthropic models in Amazon Bedrock provider ([#727](https://github.com/badlogic/companion-mono/pull/727) by [@unexge](https://github.com/unexge))
|
||||||
|
|
||||||
## [0.45.7] - 2026-01-13
|
## [0.45.7] - 2026-01-13
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI Responses timeout option handling ([#706](https://github.com/badlogic/pi-mono/pull/706) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- Fixed OpenAI Responses timeout option handling ([#706](https://github.com/badlogic/companion-mono/pull/706) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
- Fixed Bedrock tool call conversion to apply message transforms ([#707](https://github.com/badlogic/pi-mono/pull/707) by [@pjtf93](https://github.com/pjtf93))
|
- Fixed Bedrock tool call conversion to apply message transforms ([#707](https://github.com/badlogic/companion-mono/pull/707) by [@pjtf93](https://github.com/pjtf93))
|
||||||
|
|
||||||
## [0.45.6] - 2026-01-13
|
## [0.45.6] - 2026-01-13
|
||||||
|
|
||||||
|
|
@ -418,11 +418,11 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added Vercel AI Gateway provider with model discovery and `AI_GATEWAY_API_KEY` env support ([#689](https://github.com/badlogic/pi-mono/pull/689) by [@timolins](https://github.com/timolins))
|
- Added Vercel AI Gateway provider with model discovery and `AI_GATEWAY_API_KEY` env support ([#689](https://github.com/badlogic/companion-mono/pull/689) by [@timolins](https://github.com/timolins))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed z.ai thinking/reasoning: z.ai uses `thinking: { type: "enabled" }` instead of OpenAI's `reasoning_effort`. Added `thinkingFormat` compat flag to handle this. ([#688](https://github.com/badlogic/pi-mono/issues/688))
|
- Fixed z.ai thinking/reasoning: z.ai uses `thinking: { type: "enabled" }` instead of OpenAI's `reasoning_effort`. Added `thinkingFormat` compat flag to handle this. ([#688](https://github.com/badlogic/companion-mono/issues/688))
|
||||||
|
|
||||||
## [0.45.3] - 2026-01-13
|
## [0.45.3] - 2026-01-13
|
||||||
|
|
||||||
|
|
@ -434,11 +434,11 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- MiniMax provider support with M2 and M2.1 models via Anthropic-compatible API ([#656](https://github.com/badlogic/pi-mono/pull/656) by [@dannote](https://github.com/dannote))
|
- MiniMax provider support with M2 and M2.1 models via Anthropic-compatible API ([#656](https://github.com/badlogic/companion-mono/pull/656) by [@dannote](https://github.com/dannote))
|
||||||
- Add Amazon Bedrock provider with prompt caching for Claude models (experimental, tested with Anthropic Claude models only) ([#494](https://github.com/badlogic/pi-mono/pull/494) by [@unexge](https://github.com/unexge))
|
- Add Amazon Bedrock provider with prompt caching for Claude models (experimental, tested with Anthropic Claude models only) ([#494](https://github.com/badlogic/companion-mono/pull/494) by [@unexge](https://github.com/unexge))
|
||||||
- Added `serviceTier` option for OpenAI Responses requests ([#672](https://github.com/badlogic/pi-mono/pull/672) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- Added `serviceTier` option for OpenAI Responses requests ([#672](https://github.com/badlogic/companion-mono/pull/672) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
- **Anthropic caching on OpenRouter**: Interactions with Anthropic models via OpenRouter now set a 5-minute cache point using Anthropic-style `cache_control` breakpoints on the last assistant or user message. ([#584](https://github.com/badlogic/pi-mono/pull/584) by [@nathyong](https://github.com/nathyong))
|
- **Anthropic caching on OpenRouter**: Interactions with Anthropic models via OpenRouter now set a 5-minute cache point using Anthropic-style `cache_control` breakpoints on the last assistant or user message. ([#584](https://github.com/badlogic/companion-mono/pull/584) by [@nathyong](https://github.com/nathyong))
|
||||||
- **Google Gemini CLI provider improvements**: Added Antigravity endpoint fallback (tries daily sandbox then prod when `baseUrl` is unset), header-based retry delay parsing (`Retry-After`, `x-ratelimit-reset`, `x-ratelimit-reset-after`), stable `sessionId` derivation from first user message for cache affinity, empty SSE stream retry with backoff, and `anthropic-beta` header for Claude thinking models ([#670](https://github.com/badlogic/pi-mono/pull/670) by [@kim0](https://github.com/kim0))
|
- **Google Gemini CLI provider improvements**: Added Antigravity endpoint fallback (tries daily sandbox then prod when `baseUrl` is unset), header-based retry delay parsing (`Retry-After`, `x-ratelimit-reset`, `x-ratelimit-reset-after`), stable `sessionId` derivation from first user message for cache affinity, empty SSE stream retry with backoff, and `anthropic-beta` header for Claude thinking models ([#670](https://github.com/badlogic/companion-mono/pull/670) by [@kim0](https://github.com/kim0))
|
||||||
|
|
||||||
## [0.44.0] - 2026-01-12
|
## [0.44.0] - 2026-01-12
|
||||||
|
|
||||||
|
|
@ -446,7 +446,7 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed Google provider thinking detection: `isThinkingPart()` now only checks `thought === true`, not `thoughtSignature`. Per Google docs, `thoughtSignature` is for context replay and can appear on any part type. Also removed `id` field from `functionCall`/`functionResponse` (rejected by Vertex AI and Cloud Code Assist), and added `textSignature` round-trip for multi-turn reasoning context. ([#631](https://github.com/badlogic/pi-mono/pull/631) by [@theBucky](https://github.com/theBucky))
|
- Fixed Google provider thinking detection: `isThinkingPart()` now only checks `thought === true`, not `thoughtSignature`. Per Google docs, `thoughtSignature` is for context replay and can appear on any part type. Also removed `id` field from `functionCall`/`functionResponse` (rejected by Vertex AI and Cloud Code Assist), and added `textSignature` round-trip for multi-turn reasoning context. ([#631](https://github.com/badlogic/companion-mono/pull/631) by [@theBucky](https://github.com/theBucky))
|
||||||
|
|
||||||
## [0.42.5] - 2026-01-11
|
## [0.42.5] - 2026-01-11
|
||||||
|
|
||||||
|
|
@ -456,21 +456,21 @@
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- OpenAI Codex: switched to bundled system prompt matching opencode, changed originator to "pi", simplified prompt handling
|
- OpenAI Codex: switched to bundled system prompt matching opencode, changed originator to "companion", simplified prompt handling
|
||||||
|
|
||||||
## [0.42.2] - 2026-01-10
|
## [0.42.2] - 2026-01-10
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `GOOGLE_APPLICATION_CREDENTIALS` env var support for Vertex AI credential detection (standard for CI/production).
|
- Added `GOOGLE_APPLICATION_CREDENTIALS` env var support for Vertex AI credential detection (standard for CI/production).
|
||||||
- Added `supportsUsageInStreaming` compatibility flag for OpenAI-compatible providers that reject `stream_options: { include_usage: true }`. Defaults to `true`. Set to `false` in model config for providers like gatewayz.ai. ([#596](https://github.com/badlogic/pi-mono/pull/596) by [@XesGaDeus](https://github.com/XesGaDeus))
|
- Added `supportsUsageInStreaming` compatibility flag for OpenAI-compatible providers that reject `stream_options: { include_usage: true }`. Defaults to `true`. Set to `false` in model config for providers like gatewayz.ai. ([#596](https://github.com/badlogic/companion-mono/pull/596) by [@XesGaDeus](https://github.com/XesGaDeus))
|
||||||
- Improved Google model pricing info ([#588](https://github.com/badlogic/pi-mono/pull/588) by [@aadishv](https://github.com/aadishv))
|
- Improved Google model pricing info ([#588](https://github.com/badlogic/companion-mono/pull/588) by [@aadishv](https://github.com/aadishv))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed `os.homedir()` calls at module load time; now resolved lazily when needed.
|
- Fixed `os.homedir()` calls at module load time; now resolved lazily when needed.
|
||||||
- Fixed OpenAI Responses tool strict flag to use a boolean for LM Studio compatibility ([#598](https://github.com/badlogic/pi-mono/pull/598) by [@gnattu](https://github.com/gnattu))
|
- Fixed OpenAI Responses tool strict flag to use a boolean for LM Studio compatibility ([#598](https://github.com/badlogic/companion-mono/pull/598) by [@gnattu](https://github.com/gnattu))
|
||||||
- Fixed Google Cloud Code Assist OAuth for paid subscriptions: properly handles long-running operations for project provisioning, supports `GOOGLE_CLOUD_PROJECT` / `GOOGLE_CLOUD_PROJECT_ID` env vars for paid tiers, and handles VPC-SC affected users ([#582](https://github.com/badlogic/pi-mono/pull/582) by [@cmf](https://github.com/cmf))
|
- Fixed Google Cloud Code Assist OAuth for paid subscriptions: properly handles long-running operations for project provisioning, supports `GOOGLE_CLOUD_PROJECT` / `GOOGLE_CLOUD_PROJECT_ID` env vars for paid tiers, and handles VPC-SC affected users ([#582](https://github.com/badlogic/companion-mono/pull/582) by [@cmf](https://github.com/cmf))
|
||||||
|
|
||||||
## [0.42.1] - 2026-01-09
|
## [0.42.1] - 2026-01-09
|
||||||
|
|
||||||
|
|
@ -492,24 +492,24 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed Gemini CLI abort handling: detect native `AbortError` in retry catch block, cancel SSE reader when abort signal fires ([#568](https://github.com/badlogic/pi-mono/pull/568) by [@tmustier](https://github.com/tmustier))
|
- Fixed Gemini CLI abort handling: detect native `AbortError` in retry catch block, cancel SSE reader when abort signal fires ([#568](https://github.com/badlogic/companion-mono/pull/568) by [@tmustier](https://github.com/tmustier))
|
||||||
- Fixed Antigravity provider 429 errors by aligning request payload with CLIProxyAPI v6.6.89: inject Antigravity system instruction with `role: "user"`, set `requestType: "agent"`, and use `antigravity` userAgent. Added bridge prompt to override Antigravity behavior (identity, paths, web dev guidelines) with Pi defaults. ([#571](https://github.com/badlogic/pi-mono/pull/571) by [@ben-vargas](https://github.com/ben-vargas))
|
- Fixed Antigravity provider 429 errors by aligning request payload with CLIProxyAPI v6.6.89: inject Antigravity system instruction with `role: "user"`, set `requestType: "agent"`, and use `antigravity` userAgent. Added bridge prompt to override Antigravity behavior (identity, paths, web dev guidelines) with companion defaults. ([#571](https://github.com/badlogic/companion-mono/pull/571) by [@ben-vargas](https://github.com/ben-vargas))
|
||||||
- Fixed thinking block handling for cross-model conversations: thinking blocks are now converted to plain text (no `<thinking>` tags) when switching models. Previously, `<thinking>` tags caused models to mimic the pattern and output literal tags. Also fixed empty thinking blocks causing API errors. ([#561](https://github.com/badlogic/pi-mono/issues/561))
|
- Fixed thinking block handling for cross-model conversations: thinking blocks are now converted to plain text (no `<thinking>` tags) when switching models. Previously, `<thinking>` tags caused models to mimic the pattern and output literal tags. Also fixed empty thinking blocks causing API errors. ([#561](https://github.com/badlogic/companion-mono/issues/561))
|
||||||
|
|
||||||
## [0.38.0] - 2026-01-08
|
## [0.38.0] - 2026-01-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `thinkingBudgets` option in `SimpleStreamOptions` for customizing token budgets per thinking level on token-based providers ([#529](https://github.com/badlogic/pi-mono/pull/529) by [@melihmucuk](https://github.com/melihmucuk))
|
- `thinkingBudgets` option in `SimpleStreamOptions` for customizing token budgets per thinking level on token-based providers ([#529](https://github.com/badlogic/companion-mono/pull/529) by [@melihmucuk](https://github.com/melihmucuk))
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- Removed OpenAI Codex model aliases (`gpt-5`, `gpt-5-mini`, `gpt-5-nano`, `codex-mini-latest`, `gpt-5-codex`, `gpt-5.1-codex`, `gpt-5.1-chat-latest`). Use canonical model IDs: `gpt-5.1`, `gpt-5.1-codex-max`, `gpt-5.1-codex-mini`, `gpt-5.2`, `gpt-5.2-codex`. ([#536](https://github.com/badlogic/pi-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))
|
- Removed OpenAI Codex model aliases (`gpt-5`, `gpt-5-mini`, `gpt-5-nano`, `codex-mini-latest`, `gpt-5-codex`, `gpt-5.1-codex`, `gpt-5.1-chat-latest`). Use canonical model IDs: `gpt-5.1`, `gpt-5.1-codex-max`, `gpt-5.1-codex-mini`, `gpt-5.2`, `gpt-5.2-codex`. ([#536](https://github.com/badlogic/companion-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed OpenAI Codex context window from 400,000 to 272,000 tokens to match Codex CLI defaults and prevent 400 errors. ([#536](https://github.com/badlogic/pi-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))
|
- Fixed OpenAI Codex context window from 400,000 to 272,000 tokens to match Codex CLI defaults and prevent 400 errors. ([#536](https://github.com/badlogic/companion-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))
|
||||||
- Fixed Codex SSE error events to surface message, code, and status. ([#551](https://github.com/badlogic/pi-mono/pull/551) by [@tmustier](https://github.com/tmustier))
|
- Fixed Codex SSE error events to surface message, code, and status. ([#551](https://github.com/badlogic/companion-mono/pull/551) by [@tmustier](https://github.com/tmustier))
|
||||||
- Fixed context overflow detection for `context_length_exceeded` error codes.
|
- Fixed context overflow detection for `context_length_exceeded` error codes.
|
||||||
|
|
||||||
## [0.37.8] - 2026-01-07
|
## [0.37.8] - 2026-01-07
|
||||||
|
|
@ -520,7 +520,7 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Exported OpenAI Codex utilities: `CacheMetadata`, `getCodexInstructions`, `getModelFamily`, `ModelFamily`, `buildCodexPiBridge`, `buildCodexSystemPrompt`, `CodexSystemPrompt` ([#510](https://github.com/badlogic/pi-mono/pull/510) by [@mitsuhiko](https://github.com/mitsuhiko))
|
- Exported OpenAI Codex utilities: `CacheMetadata`, `getCodexInstructions`, `getModelFamily`, `ModelFamily`, `buildCodexPiBridge`, `buildCodexSystemPrompt`, `CodexSystemPrompt` ([#510](https://github.com/badlogic/companion-mono/pull/510) by [@mitsuhiko](https://github.com/mitsuhiko))
|
||||||
|
|
||||||
## [0.37.5] - 2026-01-06
|
## [0.37.5] - 2026-01-06
|
||||||
|
|
||||||
|
|
@ -536,7 +536,7 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Codex provider now always includes `reasoning.encrypted_content` even when custom `include` options are passed ([#484](https://github.com/badlogic/pi-mono/pull/484) by [@kim0](https://github.com/kim0))
|
- Codex provider now always includes `reasoning.encrypted_content` even when custom `include` options are passed ([#484](https://github.com/badlogic/companion-mono/pull/484) by [@kim0](https://github.com/kim0))
|
||||||
|
|
||||||
## [0.37.1] - 2026-01-05
|
## [0.37.1] - 2026-01-05
|
||||||
|
|
||||||
|
|
@ -544,22 +544,22 @@
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- OpenAI Codex models no longer have per-thinking-level variants (e.g., `gpt-5.2-codex-high`). Use the base model ID and set thinking level separately. The Codex provider clamps reasoning effort to what each model supports internally. (initial implementation by [@ben-vargas](https://github.com/ben-vargas) in [#472](https://github.com/badlogic/pi-mono/pull/472))
|
- OpenAI Codex models no longer have per-thinking-level variants (e.g., `gpt-5.2-codex-high`). Use the base model ID and set thinking level separately. The Codex provider clamps reasoning effort to what each model supports internally. (initial implementation by [@ben-vargas](https://github.com/ben-vargas) in [#472](https://github.com/badlogic/companion-mono/pull/472))
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Headless OAuth support for all callback-server providers (Google Gemini CLI, Antigravity, OpenAI Codex): paste redirect URL when browser callback is unreachable ([#428](https://github.com/badlogic/pi-mono/pull/428) by [@ben-vargas](https://github.com/ben-vargas), [#468](https://github.com/badlogic/pi-mono/pull/468) by [@crcatala](https://github.com/crcatala))
|
- Headless OAuth support for all callback-server providers (Google Gemini CLI, Antigravity, OpenAI Codex): paste redirect URL when browser callback is unreachable ([#428](https://github.com/badlogic/companion-mono/pull/428) by [@ben-vargas](https://github.com/ben-vargas), [#468](https://github.com/badlogic/companion-mono/pull/468) by [@crcatala](https://github.com/crcatala))
|
||||||
- Cancellable GitHub Copilot device code polling via AbortSignal
|
- Cancellable GitHub Copilot device code polling via AbortSignal
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Codex requests now omit the `reasoning` field entirely when thinking is off, letting the backend use its default instead of forcing a value. ([#472](https://github.com/badlogic/pi-mono/pull/472))
|
- Codex requests now omit the `reasoning` field entirely when thinking is off, letting the backend use its default instead of forcing a value. ([#472](https://github.com/badlogic/companion-mono/pull/472))
|
||||||
|
|
||||||
## [0.36.0] - 2026-01-05
|
## [0.36.0] - 2026-01-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- OpenAI Codex OAuth provider with Responses API streaming support: `openai-codex-responses` streaming provider with SSE parsing, tool-call handling, usage/cost tracking, and PKCE OAuth flow ([#451](https://github.com/badlogic/pi-mono/pull/451) by [@kim0](https://github.com/kim0))
|
- OpenAI Codex OAuth provider with Responses API streaming support: `openai-codex-responses` streaming provider with SSE parsing, tool-call handling, usage/cost tracking, and PKCE OAuth flow ([#451](https://github.com/badlogic/companion-mono/pull/451) by [@kim0](https://github.com/kim0))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
@ -589,11 +589,11 @@
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Vertex AI provider with ADC (Application Default Credentials) support. Authenticate with `gcloud auth application-default login`, set `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, and access Gemini models via Vertex AI. ([#300](https://github.com/badlogic/pi-mono/pull/300) by [@default-anton](https://github.com/default-anton))
|
- Vertex AI provider with ADC (Application Default Credentials) support. Authenticate with `gcloud auth application-default login`, set `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, and access Gemini models via Vertex AI. ([#300](https://github.com/badlogic/companion-mono/pull/300) by [@default-anton](https://github.com/default-anton))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **Gemini CLI rate limit handling**: Added automatic retry with server-provided delay for 429 errors. Parses delay from error messages like "Your quota will reset after 39s" and waits accordingly. Falls back to exponential backoff for other transient errors. ([#370](https://github.com/badlogic/pi-mono/issues/370))
|
- **Gemini CLI rate limit handling**: Added automatic retry with server-provided delay for 429 errors. Parses delay from error messages like "Your quota will reset after 39s" and waits accordingly. Falls back to exponential backoff for other transient errors. ([#370](https://github.com/badlogic/companion-mono/issues/370))
|
||||||
|
|
||||||
## [0.31.1] - 2026-01-02
|
## [0.31.1] - 2026-01-02
|
||||||
|
|
||||||
|
|
@ -601,7 +601,7 @@
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- **Agent API moved**: All agent functionality (`agentLoop`, `agentLoopContinue`, `AgentContext`, `AgentEvent`, `AgentTool`, `AgentToolResult`, etc.) has moved to `@mariozechner/pi-agent-core`. Import from that package instead of `@mariozechner/pi-ai`.
|
- **Agent API moved**: All agent functionality (`agentLoop`, `agentLoopContinue`, `AgentContext`, `AgentEvent`, `AgentTool`, `AgentToolResult`, etc.) has moved to `@mariozechner/companion-agent-core`. Import from that package instead of `@mariozechner/companion-ai`.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
@ -612,19 +612,19 @@
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **OAuth uses Web Crypto API**: PKCE generation and OAuth flows now use Web Crypto API (`crypto.subtle`) instead of Node.js `crypto` module. This improves browser compatibility while still working in Node.js 20+.
|
- **OAuth uses Web Crypto API**: PKCE generation and OAuth flows now use Web Crypto API (`crypto.subtle`) instead of Node.js `crypto` module. This improves browser compatibility while still working in Node.js 20+.
|
||||||
- **Deterministic model generation**: `generate-models.ts` now sorts providers and models alphabetically for consistent output across runs. ([#332](https://github.com/badlogic/pi-mono/pull/332) by [@mrexodia](https://github.com/mrexodia))
|
- **Deterministic model generation**: `generate-models.ts` now sorts providers and models alphabetically for consistent output across runs. ([#332](https://github.com/badlogic/companion-mono/pull/332) by [@mrexodia](https://github.com/mrexodia))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **OpenAI completions empty content blocks**: Empty text or thinking blocks in assistant messages are now filtered out before sending to the OpenAI completions API, preventing validation errors. ([#344](https://github.com/badlogic/pi-mono/pull/344) by [@default-anton](https://github.com/default-anton))
|
- **OpenAI completions empty content blocks**: Empty text or thinking blocks in assistant messages are now filtered out before sending to the OpenAI completions API, preventing validation errors. ([#344](https://github.com/badlogic/companion-mono/pull/344) by [@default-anton](https://github.com/default-anton))
|
||||||
- **Thinking token duplication**: Fixed thinking content duplication with chutes.ai provider. The provider was returning thinking content in both `reasoning_content` and `reasoning` fields, causing each chunk to be processed twice. Now only the first non-empty reasoning field is used.
|
- **Thinking token duplication**: Fixed thinking content duplication with chutes.ai provider. The provider was returning thinking content in both `reasoning_content` and `reasoning` fields, causing each chunk to be processed twice. Now only the first non-empty reasoning field is used.
|
||||||
- **zAi provider API mapping**: Fixed zAi models to use `openai-completions` API with correct base URL (`https://api.z.ai/api/coding/paas/v4`) instead of incorrect Anthropic API mapping. ([#344](https://github.com/badlogic/pi-mono/pull/344), [#358](https://github.com/badlogic/pi-mono/pull/358) by [@default-anton](https://github.com/default-anton))
|
- **zAi provider API mapping**: Fixed zAi models to use `openai-completions` API with correct base URL (`https://api.z.ai/api/coding/paas/v4`) instead of incorrect Anthropic API mapping. ([#344](https://github.com/badlogic/companion-mono/pull/344), [#358](https://github.com/badlogic/companion-mono/pull/358) by [@default-anton](https://github.com/default-anton))
|
||||||
|
|
||||||
## [0.28.0] - 2025-12-25
|
## [0.28.0] - 2025-12-25
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
- **OAuth storage removed** ([#296](https://github.com/badlogic/pi-mono/issues/296)): All storage functions (`loadOAuthCredentials`, `saveOAuthCredentials`, `setOAuthStorage`, etc.) removed. Callers are responsible for storing credentials.
|
- **OAuth storage removed** ([#296](https://github.com/badlogic/companion-mono/issues/296)): All storage functions (`loadOAuthCredentials`, `saveOAuthCredentials`, `setOAuthStorage`, etc.) removed. Callers are responsible for storing credentials.
|
||||||
- **OAuth login functions**: `loginAnthropic`, `loginGitHubCopilot`, `loginGeminiCli`, `loginAntigravity` now return `OAuthCredentials` instead of saving to disk.
|
- **OAuth login functions**: `loginAnthropic`, `loginGitHubCopilot`, `loginGeminiCli`, `loginAntigravity` now return `OAuthCredentials` instead of saving to disk.
|
||||||
- **refreshOAuthToken**: Now takes `(provider, credentials)` and returns new `OAuthCredentials` instead of saving.
|
- **refreshOAuthToken**: Now takes `(provider, credentials)` and returns new `OAuthCredentials` instead of saving.
|
||||||
- **getOAuthApiKey**: Now takes `(provider, credentials)` and returns `{ newCredentials, apiKey }` or null.
|
- **getOAuthApiKey**: Now takes `(provider, credentials)` and returns `{ newCredentials, apiKey }` or null.
|
||||||
|
|
@ -636,13 +636,13 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **Thinking tag leakage**: Fixed Claude mimicking literal `</thinking>` tags in responses. Unsigned thinking blocks (from aborted streams) are now converted to plain text without `<thinking>` tags. The TUI still displays them as thinking blocks. ([#302](https://github.com/badlogic/pi-mono/pull/302) by [@nicobailon](https://github.com/nicobailon))
|
- **Thinking tag leakage**: Fixed Claude mimicking literal `</thinking>` tags in responses. Unsigned thinking blocks (from aborted streams) are now converted to plain text without `<thinking>` tags. The TUI still displays them as thinking blocks. ([#302](https://github.com/badlogic/companion-mono/pull/302) by [@nicobailon](https://github.com/nicobailon))
|
||||||
|
|
||||||
## [0.25.1] - 2025-12-21
|
## [0.25.1] - 2025-12-21
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **xhigh thinking level support**: Added `supportsXhigh()` function to check if a model supports xhigh reasoning level. Also clamps xhigh to high for OpenAI models that don't support it. ([#236](https://github.com/badlogic/pi-mono/pull/236) by [@theBucky](https://github.com/theBucky))
|
- **xhigh thinking level support**: Added `supportsXhigh()` function to check if a model supports xhigh reasoning level. Also clamps xhigh to high for OpenAI models that don't support it. ([#236](https://github.com/badlogic/companion-mono/pull/236) by [@theBucky](https://github.com/theBucky))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
@ -650,37 +650,37 @@
|
||||||
|
|
||||||
- **Queued message steering**: When `getQueuedMessages` is provided, the agent loop now checks for queued user messages after each tool call and skips remaining tool calls in the current assistant message when a queued message arrives (emitting error tool results).
|
- **Queued message steering**: When `getQueuedMessages` is provided, the agent loop now checks for queued user messages after each tool call and skips remaining tool calls in the current assistant message when a queued message arrives (emitting error tool results).
|
||||||
|
|
||||||
- **Double API version path in Google provider URL**: Fixed Gemini API calls returning 404 after baseUrl support was added. The SDK was appending its default apiVersion to baseUrl which already included the version path. ([#251](https://github.com/badlogic/pi-mono/pull/251) by [@shellfyred](https://github.com/shellfyred))
|
- **Double API version path in Google provider URL**: Fixed Gemini API calls returning 404 after baseUrl support was added. The SDK was appending its default apiVersion to baseUrl which already included the version path. ([#251](https://github.com/badlogic/companion-mono/pull/251) by [@shellfyred](https://github.com/shellfyred))
|
||||||
|
|
||||||
- **Anthropic SDK retries disabled**: Re-enabled SDK-level retries (default 2) for transient HTTP failures. ([#252](https://github.com/badlogic/pi-mono/issues/252))
|
- **Anthropic SDK retries disabled**: Re-enabled SDK-level retries (default 2) for transient HTTP failures. ([#252](https://github.com/badlogic/companion-mono/issues/252))
|
||||||
|
|
||||||
## [0.23.5] - 2025-12-19
|
## [0.23.5] - 2025-12-19
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **Gemini 3 Flash thinking support**: Extended thinking level support for Gemini 3 Flash models (MINIMAL, LOW, MEDIUM, HIGH) to match Pro models' capabilities. ([#212](https://github.com/badlogic/pi-mono/pull/212) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- **Gemini 3 Flash thinking support**: Extended thinking level support for Gemini 3 Flash models (MINIMAL, LOW, MEDIUM, HIGH) to match Pro models' capabilities. ([#212](https://github.com/badlogic/companion-mono/pull/212) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
|
|
||||||
- **GitHub Copilot thinking models**: Added thinking support for additional Copilot models (o3-mini, o1-mini, o1-preview). ([#234](https://github.com/badlogic/pi-mono/pull/234) by [@aadishv](https://github.com/aadishv))
|
- **GitHub Copilot thinking models**: Added thinking support for additional Copilot models (o3-mini, o1-mini, o1-preview). ([#234](https://github.com/badlogic/companion-mono/pull/234) by [@aadishv](https://github.com/aadishv))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **Gemini tool result format**: Fixed tool result format for Gemini 3 Flash Preview which strictly requires `{ output: value }` for success and `{ error: value }` for errors. Previous format using `{ result, isError }` was rejected by newer Gemini models. Also improved type safety by removing `as any` casts. ([#213](https://github.com/badlogic/pi-mono/issues/213), [#220](https://github.com/badlogic/pi-mono/pull/220))
|
- **Gemini tool result format**: Fixed tool result format for Gemini 3 Flash Preview which strictly requires `{ output: value }` for success and `{ error: value }` for errors. Previous format using `{ result, isError }` was rejected by newer Gemini models. Also improved type safety by removing `as any` casts. ([#213](https://github.com/badlogic/companion-mono/issues/213), [#220](https://github.com/badlogic/companion-mono/pull/220))
|
||||||
|
|
||||||
- **Google baseUrl configuration**: Google provider now respects `baseUrl` configuration for custom endpoints or API proxies. ([#216](https://github.com/badlogic/pi-mono/issues/216), [#221](https://github.com/badlogic/pi-mono/pull/221) by [@theBucky](https://github.com/theBucky))
|
- **Google baseUrl configuration**: Google provider now respects `baseUrl` configuration for custom endpoints or API proxies. ([#216](https://github.com/badlogic/companion-mono/issues/216), [#221](https://github.com/badlogic/companion-mono/pull/221) by [@theBucky](https://github.com/theBucky))
|
||||||
|
|
||||||
- **GitHub Copilot vision requests**: Added `Copilot-Vision-Request` header when sending images to GitHub Copilot models. ([#222](https://github.com/badlogic/pi-mono/issues/222))
|
- **GitHub Copilot vision requests**: Added `Copilot-Vision-Request` header when sending images to GitHub Copilot models. ([#222](https://github.com/badlogic/companion-mono/issues/222))
|
||||||
|
|
||||||
- **GitHub Copilot X-Initiator header**: Fixed X-Initiator logic to check last message role instead of any message in history. This ensures proper billing when users send follow-up messages. ([#209](https://github.com/badlogic/pi-mono/issues/209))
|
- **GitHub Copilot X-Initiator header**: Fixed X-Initiator logic to check last message role instead of any message in history. This ensures proper billing when users send follow-up messages. ([#209](https://github.com/badlogic/companion-mono/issues/209))
|
||||||
|
|
||||||
## [0.22.3] - 2025-12-16
|
## [0.22.3] - 2025-12-16
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **Image limits test suite**: Added comprehensive tests for provider-specific image limitations (max images, max size, max dimensions). Discovered actual limits: Anthropic (100 images, 5MB, 8000px), OpenAI (500 images, ≥25MB), Gemini (~2500 images, ≥40MB), Mistral (8 images, ~15MB), OpenRouter (~40 images context-limited, ~15MB). ([#120](https://github.com/badlogic/pi-mono/pull/120))
|
- **Image limits test suite**: Added comprehensive tests for provider-specific image limitations (max images, max size, max dimensions). Discovered actual limits: Anthropic (100 images, 5MB, 8000px), OpenAI (500 images, ≥25MB), Gemini (~2500 images, ≥40MB), Mistral (8 images, ~15MB), OpenRouter (~40 images context-limited, ~15MB). ([#120](https://github.com/badlogic/companion-mono/pull/120))
|
||||||
|
|
||||||
- **Tool result streaming**: Added `tool_execution_update` event and optional `onUpdate` callback to `AgentTool.execute()` for streaming tool output during execution. Tools can now emit partial results (e.g., bash stdout) that are forwarded to subscribers. ([#44](https://github.com/badlogic/pi-mono/issues/44))
|
- **Tool result streaming**: Added `tool_execution_update` event and optional `onUpdate` callback to `AgentTool.execute()` for streaming tool output during execution. Tools can now emit partial results (e.g., bash stdout) that are forwarded to subscribers. ([#44](https://github.com/badlogic/companion-mono/issues/44))
|
||||||
|
|
||||||
- **X-Initiator header for GitHub Copilot**: Added X-Initiator header handling for GitHub Copilot provider to ensure correct call accounting (agent calls are not deducted from quota). Sets initiator based on last message role. ([#200](https://github.com/badlogic/pi-mono/pull/200) by [@kim0](https://github.com/kim0))
|
- **X-Initiator header for GitHub Copilot**: Added X-Initiator header handling for GitHub Copilot provider to ensure correct call accounting (agent calls are not deducted from quota). Sets initiator based on last message role. ([#200](https://github.com/badlogic/companion-mono/pull/200) by [@kim0](https://github.com/kim0))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
@ -688,7 +688,7 @@
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **Reasoning disabled by default**: When `reasoning` option is not specified, thinking is now explicitly disabled for all providers. Previously, some providers like Gemini with "dynamic thinking" would use their default (thinking ON), causing unexpected token usage. This was the original intended behavior. ([#180](https://github.com/badlogic/pi-mono/pull/180) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- **Reasoning disabled by default**: When `reasoning` option is not specified, thinking is now explicitly disabled for all providers. Previously, some providers like Gemini with "dynamic thinking" would use their default (thinking ON), causing unexpected token usage. This was the original intended behavior. ([#180](https://github.com/badlogic/companion-mono/pull/180) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
|
|
||||||
## [0.22.2] - 2025-12-15
|
## [0.22.2] - 2025-12-15
|
||||||
|
|
||||||
|
|
@ -708,21 +708,21 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **GitHub Copilot provider**: Added `github-copilot` as a known provider with models sourced from models.dev. Includes Claude, GPT, Gemini, Grok, and other models available through GitHub Copilot. ([#191](https://github.com/badlogic/pi-mono/pull/191) by [@cau1k](https://github.com/cau1k))
|
- **GitHub Copilot provider**: Added `github-copilot` as a known provider with models sourced from models.dev. Includes Claude, GPT, Gemini, Grok, and other models available through GitHub Copilot. ([#191](https://github.com/badlogic/companion-mono/pull/191) by [@cau1k](https://github.com/cau1k))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- **GitHub Copilot gpt-5 models**: Fixed API selection for gpt-5 models to use `openai-responses` instead of `openai-completions` (gpt-5 models are not accessible via completions endpoint)
|
- **GitHub Copilot gpt-5 models**: Fixed API selection for gpt-5 models to use `openai-responses` instead of `openai-completions` (gpt-5 models are not accessible via completions endpoint)
|
||||||
|
|
||||||
- **GitHub Copilot cross-model context handoff**: Fixed context handoff failing when switching between GitHub Copilot models using different APIs (e.g., gpt-5 to claude-sonnet-4). Tool call IDs from OpenAI Responses API were incompatible with other models. ([#198](https://github.com/badlogic/pi-mono/issues/198))
|
- **GitHub Copilot cross-model context handoff**: Fixed context handoff failing when switching between GitHub Copilot models using different APIs (e.g., gpt-5 to claude-sonnet-4). Tool call IDs from OpenAI Responses API were incompatible with other models. ([#198](https://github.com/badlogic/companion-mono/issues/198))
|
||||||
|
|
||||||
- **Gemini 3 Pro thinking levels**: Thinking level configuration now works correctly for Gemini 3 Pro models. Previously all levels mapped to -1 (minimal thinking). Now LOW/MEDIUM/HIGH properly control test-time computation. ([#176](https://github.com/badlogic/pi-mono/pull/176) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
- **Gemini 3 Pro thinking levels**: Thinking level configuration now works correctly for Gemini 3 Pro models. Previously all levels mapped to -1 (minimal thinking). Now LOW/MEDIUM/HIGH properly control test-time computation. ([#176](https://github.com/badlogic/companion-mono/pull/176) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
||||||
|
|
||||||
## [0.18.2] - 2025-12-11
|
## [0.18.2] - 2025-12-11
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Anthropic SDK retries disabled**: Set `maxRetries: 0` on Anthropic client to allow application-level retry handling. The SDK's built-in retries were interfering with coding-agent's retry logic. ([#157](https://github.com/badlogic/pi-mono/issues/157))
|
- **Anthropic SDK retries disabled**: Set `maxRetries: 0` on Anthropic client to allow application-level retry handling. The SDK's built-in retries were interfering with coding-agent's retry logic. ([#157](https://github.com/badlogic/companion-mono/issues/157))
|
||||||
|
|
||||||
## [0.18.1] - 2025-12-10
|
## [0.18.1] - 2025-12-10
|
||||||
|
|
||||||
|
|
@ -732,11 +732,11 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed Mistral 400 errors after aborted assistant messages by skipping empty assistant messages (no content, no tool calls) ([#165](https://github.com/badlogic/pi-mono/issues/165))
|
- Fixed Mistral 400 errors after aborted assistant messages by skipping empty assistant messages (no content, no tool calls) ([#165](https://github.com/badlogic/companion-mono/issues/165))
|
||||||
|
|
||||||
- Removed synthetic assistant bridge message after tool results for Mistral (no longer required as of Dec 2025) ([#165](https://github.com/badlogic/pi-mono/issues/165))
|
- Removed synthetic assistant bridge message after tool results for Mistral (no longer required as of Dec 2025) ([#165](https://github.com/badlogic/companion-mono/issues/165))
|
||||||
|
|
||||||
- Fixed bug where `ANTHROPIC_API_KEY` environment variable was deleted globally after first OAuth token usage, causing subsequent prompts to fail ([#164](https://github.com/badlogic/pi-mono/pull/164))
|
- Fixed bug where `ANTHROPIC_API_KEY` environment variable was deleted globally after first OAuth token usage, causing subsequent prompts to fail ([#164](https://github.com/badlogic/companion-mono/pull/164))
|
||||||
|
|
||||||
## [0.17.0] - 2025-12-09
|
## [0.17.0] - 2025-12-09
|
||||||
|
|
||||||
|
|
@ -752,9 +752,9 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
||||||
|
|
||||||
- Added `validateToolCall(tools, toolCall)` helper that finds the tool by name and validates arguments.
|
- Added `validateToolCall(tools, toolCall)` helper that finds the tool by name and validates arguments.
|
||||||
|
|
||||||
- **OpenAI compatibility overrides**: Added `compat` field to `Model` for `openai-completions` API, allowing explicit configuration of provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`, `maxTokensField`). Falls back to URL-based detection if not set. Useful for LiteLLM, custom proxies, and other non-standard endpoints. ([#133](https://github.com/badlogic/pi-mono/issues/133), thanks @fink-andreas for the initial idea and PR)
|
- **OpenAI compatibility overrides**: Added `compat` field to `Model` for `openai-completions` API, allowing explicit configuration of provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`, `maxTokensField`). Falls back to URL-based detection if not set. Useful for LiteLLM, custom proxies, and other non-standard endpoints. ([#133](https://github.com/badlogic/companion-mono/issues/133), thanks @fink-andreas for the initial idea and PR)
|
||||||
|
|
||||||
- **xhigh reasoning level**: Added `xhigh` to `ReasoningEffort` type for OpenAI codex-max models. For non-OpenAI providers (Anthropic, Google), `xhigh` is automatically mapped to `high`. ([#143](https://github.com/badlogic/pi-mono/issues/143))
|
- **xhigh reasoning level**: Added `xhigh` to `ReasoningEffort` type for OpenAI codex-max models. For non-OpenAI providers (Anthropic, Google), `xhigh` is automatically mapped to `high`. ([#143](https://github.com/badlogic/companion-mono/issues/143))
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# @mariozechner/pi-ai
|
# @mariozechner/companion-ai
|
||||||
|
|
||||||
Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and simple context persistence and hand-off to other models mid-session.
|
Unified LLM API with automatic model discovery, provider configuration, token and cost tracking, and simple context persistence and hand-off to other models mid-session.
|
||||||
|
|
||||||
|
|
@ -72,10 +72,10 @@ Unified LLM API with automatic model discovery, provider configuration, token an
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @mariozechner/pi-ai
|
npm install @mariozechner/companion-ai
|
||||||
```
|
```
|
||||||
|
|
||||||
TypeBox exports are re-exported from `@mariozechner/pi-ai`: `Type`, `Static`, and `TSchema`.
|
TypeBox exports are re-exported from `@mariozechner/companion-ai`: `Type`, `Static`, and `TSchema`.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ import {
|
||||||
Context,
|
Context,
|
||||||
Tool,
|
Tool,
|
||||||
StringEnum,
|
StringEnum,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Fully typed with auto-complete support for both providers and models
|
// Fully typed with auto-complete support for both providers and models
|
||||||
const model = getModel("openai", "gpt-4o-mini");
|
const model = getModel("openai", "gpt-4o-mini");
|
||||||
|
|
@ -223,7 +223,7 @@ Tools enable LLMs to interact with external systems. This library uses TypeBox s
|
||||||
### Defining Tools
|
### Defining Tools
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Type, Tool, StringEnum } from "@mariozechner/pi-ai";
|
import { Type, Tool, StringEnum } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Define tool parameters with TypeBox
|
// Define tool parameters with TypeBox
|
||||||
const weatherTool: Tool = {
|
const weatherTool: Tool = {
|
||||||
|
|
@ -356,7 +356,7 @@ When using `agentLoop`, tool arguments are automatically validated against your
|
||||||
When implementing your own tool execution loop with `stream()` or `complete()`, use `validateToolCall` to validate arguments before passing them to your tools:
|
When implementing your own tool execution loop with `stream()` or `complete()`, use `validateToolCall` to validate arguments before passing them to your tools:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { stream, validateToolCall, Tool } from "@mariozechner/pi-ai";
|
import { stream, validateToolCall, Tool } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
const tools: Tool[] = [weatherTool, calculatorTool];
|
const tools: Tool[] = [weatherTool, calculatorTool];
|
||||||
const s = stream(model, { messages, tools });
|
const s = stream(model, { messages, tools });
|
||||||
|
|
@ -410,7 +410,7 @@ Models with vision capabilities can process images. You can check if a model sup
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { getModel, complete } from "@mariozechner/pi-ai";
|
import { getModel, complete } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
const model = getModel("openai", "gpt-4o-mini");
|
const model = getModel("openai", "gpt-4o-mini");
|
||||||
|
|
||||||
|
|
@ -449,7 +449,7 @@ Many models support thinking/reasoning capabilities where they can show their in
|
||||||
### Unified Interface (streamSimple/completeSimple)
|
### Unified Interface (streamSimple/completeSimple)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel, streamSimple, completeSimple } from "@mariozechner/pi-ai";
|
import { getModel, streamSimple, completeSimple } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Many models across providers support thinking/reasoning
|
// Many models across providers support thinking/reasoning
|
||||||
const model = getModel("anthropic", "claude-sonnet-4-20250514");
|
const model = getModel("anthropic", "claude-sonnet-4-20250514");
|
||||||
|
|
@ -491,7 +491,7 @@ for (const block of response.content) {
|
||||||
For fine-grained control, use the provider-specific options:
|
For fine-grained control, use the provider-specific options:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel, complete } from "@mariozechner/pi-ai";
|
import { getModel, complete } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// OpenAI Reasoning (o1, o3, gpt-5)
|
// OpenAI Reasoning (o1, o3, gpt-5)
|
||||||
const openaiModel = getModel("openai", "gpt-5-mini");
|
const openaiModel = getModel("openai", "gpt-5-mini");
|
||||||
|
|
@ -578,7 +578,7 @@ if (message.stopReason === "error" || message.stopReason === "aborted") {
|
||||||
The abort signal allows you to cancel in-progress requests. Aborted requests have `stopReason === 'aborted'`:
|
The abort signal allows you to cancel in-progress requests. Aborted requests have `stopReason === 'aborted'`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel, stream } from "@mariozechner/pi-ai";
|
import { getModel, stream } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
const model = getModel("openai", "gpt-4o-mini");
|
const model = getModel("openai", "gpt-4o-mini");
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
|
@ -682,7 +682,7 @@ A **provider** offers models through a specific API. For example:
|
||||||
### Querying Providers and Models
|
### Querying Providers and Models
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getProviders, getModels, getModel } from "@mariozechner/pi-ai";
|
import { getProviders, getModels, getModel } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Get all available providers
|
// Get all available providers
|
||||||
const providers = getProviders();
|
const providers = getProviders();
|
||||||
|
|
@ -708,7 +708,7 @@ console.log(`Using ${model.name} via ${model.api} API`);
|
||||||
You can create custom models for local inference servers or custom endpoints:
|
You can create custom models for local inference servers or custom endpoints:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Model, stream } from "@mariozechner/pi-ai";
|
import { Model, stream } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Example: Ollama using OpenAI-compatible API
|
// Example: Ollama using OpenAI-compatible API
|
||||||
const ollamaModel: Model<"openai-completions"> = {
|
const ollamaModel: Model<"openai-completions"> = {
|
||||||
|
|
@ -802,7 +802,7 @@ If `compat` is not set, the library falls back to URL-based detection. If `compa
|
||||||
Models are typed by their API, which keeps the model metadata accurate. Provider-specific option types are enforced when you call the provider functions directly. The generic `stream` and `complete` functions accept `StreamOptions` with additional provider fields.
|
Models are typed by their API, which keeps the model metadata accurate. Provider-specific option types are enforced when you call the provider functions directly. The generic `stream` and `complete` functions accept `StreamOptions` with additional provider fields.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { streamAnthropic, type AnthropicOptions } from "@mariozechner/pi-ai";
|
import { streamAnthropic, type AnthropicOptions } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// TypeScript knows this is an Anthropic model
|
// TypeScript knows this is an Anthropic model
|
||||||
const claude = getModel("anthropic", "claude-sonnet-4-20250514");
|
const claude = getModel("anthropic", "claude-sonnet-4-20250514");
|
||||||
|
|
@ -831,7 +831,7 @@ When messages from one provider are sent to a different provider, the library au
|
||||||
### Example: Multi-Provider Conversation
|
### Example: Multi-Provider Conversation
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel, complete, Context } from "@mariozechner/pi-ai";
|
import { getModel, complete, Context } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Start with Claude
|
// Start with Claude
|
||||||
const claude = getModel("anthropic", "claude-sonnet-4-20250514");
|
const claude = getModel("anthropic", "claude-sonnet-4-20250514");
|
||||||
|
|
@ -884,7 +884,7 @@ This enables flexible workflows where you can:
|
||||||
The `Context` object can be easily serialized and deserialized using standard JSON methods, making it simple to persist conversations, implement chat history, or transfer contexts between services:
|
The `Context` object can be easily serialized and deserialized using standard JSON methods, making it simple to persist conversations, implement chat history, or transfer contexts between services:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Context, getModel, complete } from "@mariozechner/pi-ai";
|
import { Context, getModel, complete } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Create and use a context
|
// Create and use a context
|
||||||
const context: Context = {
|
const context: Context = {
|
||||||
|
|
@ -922,7 +922,7 @@ const continuation = await complete(newModel, restored);
|
||||||
The library supports browser environments. You must pass the API key explicitly since environment variables are not available in browsers:
|
The library supports browser environments. You must pass the API key explicitly since environment variables are not available in browsers:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel, complete } from "@mariozechner/pi-ai";
|
import { getModel, complete } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// API key must be passed explicitly in browser
|
// API key must be passed explicitly in browser
|
||||||
const model = getModel("anthropic", "claude-3-5-haiku-20241022");
|
const model = getModel("anthropic", "claude-3-5-haiku-20241022");
|
||||||
|
|
@ -943,7 +943,7 @@ const response = await complete(
|
||||||
### Browser Compatibility Notes
|
### Browser Compatibility Notes
|
||||||
|
|
||||||
- Amazon Bedrock (`bedrock-converse-stream`) is not supported in browser environments.
|
- Amazon Bedrock (`bedrock-converse-stream`) is not supported in browser environments.
|
||||||
- OAuth login flows are not supported in browser environments. Use the `@mariozechner/pi-ai/oauth` entry point in Node.js.
|
- OAuth login flows are not supported in browser environments. Use the `@mariozechner/companion-ai/oauth` entry point in Node.js.
|
||||||
- In browser builds, Bedrock can still appear in model lists. Calls to Bedrock models fail at runtime.
|
- In browser builds, Bedrock can still appear in model lists. Calls to Bedrock models fail at runtime.
|
||||||
- Use a server-side proxy or backend service if you need Bedrock or OAuth-based auth from a web app.
|
- Use a server-side proxy or backend service if you need Bedrock or OAuth-based auth from a web app.
|
||||||
|
|
||||||
|
|
@ -985,17 +985,17 @@ const response = await complete(model, context, {
|
||||||
|
|
||||||
#### Antigravity Version Override
|
#### Antigravity Version Override
|
||||||
|
|
||||||
Set `PI_AI_ANTIGRAVITY_VERSION` to override the Antigravity User-Agent version when Google updates their requirements:
|
Set `COMPANION_AI_ANTIGRAVITY_VERSION` to override the Antigravity User-Agent version when Google updates their requirements:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export PI_AI_ANTIGRAVITY_VERSION="1.23.0"
|
export COMPANION_AI_ANTIGRAVITY_VERSION="1.23.0"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Cache Retention
|
#### Cache Retention
|
||||||
|
|
||||||
Set `PI_CACHE_RETENTION=long` to extend prompt cache retention:
|
Set `COMPANION_CACHE_RETENTION=long` to extend prompt cache retention:
|
||||||
|
|
||||||
| Provider | Default | With `PI_CACHE_RETENTION=long` |
|
| Provider | Default | With `COMPANION_CACHE_RETENTION=long` |
|
||||||
| --------- | --------- | ------------------------------ |
|
| --------- | --------- | ------------------------------ |
|
||||||
| Anthropic | 5 minutes | 1 hour |
|
| Anthropic | 5 minutes | 1 hour |
|
||||||
| OpenAI | in-memory | 24 hours |
|
| OpenAI | in-memory | 24 hours |
|
||||||
|
|
@ -1007,7 +1007,7 @@ This only affects direct API calls to `api.anthropic.com` and `api.openai.com`.
|
||||||
### Checking Environment Variables
|
### Checking Environment Variables
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getEnvApiKey } from "@mariozechner/pi-ai";
|
import { getEnvApiKey } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// Check if an API key is set in environment variables
|
// Check if an API key is set in environment variables
|
||||||
const key = getEnvApiKey("openai"); // checks OPENAI_API_KEY
|
const key = getEnvApiKey("openai"); // checks OPENAI_API_KEY
|
||||||
|
|
@ -1047,7 +1047,7 @@ export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
|
||||||
```
|
```
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel, complete } from "@mariozechner/pi-ai";
|
import { getModel, complete } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const model = getModel("google-vertex", "gemini-2.5-flash");
|
const model = getModel("google-vertex", "gemini-2.5-flash");
|
||||||
|
|
@ -1068,16 +1068,16 @@ Official docs: [Application Default Credentials](https://cloud.google.com/docs/a
|
||||||
The quickest way to authenticate:
|
The quickest way to authenticate:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx @mariozechner/pi-ai login # interactive provider selection
|
npx @mariozechner/companion-ai login # interactive provider selection
|
||||||
npx @mariozechner/pi-ai login anthropic # login to specific provider
|
npx @mariozechner/companion-ai login anthropic # login to specific provider
|
||||||
npx @mariozechner/pi-ai list # list available providers
|
npx @mariozechner/companion-ai list # list available providers
|
||||||
```
|
```
|
||||||
|
|
||||||
Credentials are saved to `auth.json` in the current directory.
|
Credentials are saved to `auth.json` in the current directory.
|
||||||
|
|
||||||
### Programmatic OAuth
|
### Programmatic OAuth
|
||||||
|
|
||||||
The library provides login and token refresh functions via the `@mariozechner/pi-ai/oauth` entry point. Credential storage is the caller's responsibility.
|
The library provides login and token refresh functions via the `@mariozechner/companion-ai/oauth` entry point. Credential storage is the caller's responsibility.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import {
|
import {
|
||||||
|
|
@ -1095,13 +1095,13 @@ import {
|
||||||
// Types
|
// Types
|
||||||
type OAuthProvider, // 'anthropic' | 'openai-codex' | 'github-copilot' | 'google-gemini-cli' | 'google-antigravity'
|
type OAuthProvider, // 'anthropic' | 'openai-codex' | 'github-copilot' | 'google-gemini-cli' | 'google-antigravity'
|
||||||
type OAuthCredentials,
|
type OAuthCredentials,
|
||||||
} from "@mariozechner/pi-ai/oauth";
|
} from "@mariozechner/companion-ai/oauth";
|
||||||
```
|
```
|
||||||
|
|
||||||
### Login Flow Example
|
### Login Flow Example
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { loginGitHubCopilot } from "@mariozechner/pi-ai/oauth";
|
import { loginGitHubCopilot } from "@mariozechner/companion-ai/oauth";
|
||||||
import { writeFileSync } from "fs";
|
import { writeFileSync } from "fs";
|
||||||
|
|
||||||
const credentials = await loginGitHubCopilot({
|
const credentials = await loginGitHubCopilot({
|
||||||
|
|
@ -1125,8 +1125,8 @@ writeFileSync("auth.json", JSON.stringify(auth, null, 2));
|
||||||
Use `getOAuthApiKey()` to get an API key, automatically refreshing if expired:
|
Use `getOAuthApiKey()` to get an API key, automatically refreshing if expired:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel, complete } from "@mariozechner/pi-ai";
|
import { getModel, complete } from "@mariozechner/companion-ai";
|
||||||
import { getOAuthApiKey } from "@mariozechner/pi-ai/oauth";
|
import { getOAuthApiKey } from "@mariozechner/companion-ai/oauth";
|
||||||
import { readFileSync, writeFileSync } from "fs";
|
import { readFileSync, writeFileSync } from "fs";
|
||||||
|
|
||||||
// Load your stored credentials
|
// Load your stored credentials
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@mariozechner/pi-ai",
|
"name": "@mariozechner/companion-ai",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"pi-ai": "./dist/cli.js"
|
"companion-ai": "./dist/cli.js"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ async function main(): Promise<void> {
|
||||||
const providerList = PROVIDERS.map(
|
const providerList = PROVIDERS.map(
|
||||||
(p) => ` ${p.id.padEnd(20)} ${p.name}`,
|
(p) => ` ${p.id.padEnd(20)} ${p.name}`,
|
||||||
).join("\n");
|
).join("\n");
|
||||||
console.log(`Usage: npx @mariozechner/pi-ai <command> [provider]
|
console.log(`Usage: npx @mariozechner/companion-ai <command> [provider]
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
login [provider] Login to an OAuth provider
|
login [provider] Login to an OAuth provider
|
||||||
|
|
@ -88,9 +88,9 @@ Providers:
|
||||||
${providerList}
|
${providerList}
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
npx @mariozechner/pi-ai login # interactive provider selection
|
npx @mariozechner/companion-ai login # interactive provider selection
|
||||||
npx @mariozechner/pi-ai login anthropic # login to specific provider
|
npx @mariozechner/companion-ai login anthropic # login to specific provider
|
||||||
npx @mariozechner/pi-ai list # list providers
|
npx @mariozechner/companion-ai list # list providers
|
||||||
`);
|
`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +131,7 @@ Examples:
|
||||||
if (!PROVIDERS.some((p) => p.id === provider)) {
|
if (!PROVIDERS.some((p) => p.id === provider)) {
|
||||||
console.error(`Unknown provider: ${provider}`);
|
console.error(`Unknown provider: ${provider}`);
|
||||||
console.error(
|
console.error(
|
||||||
`Use 'npx @mariozechner/pi-ai list' to see available providers`,
|
`Use 'npx @mariozechner/companion-ai list' to see available providers`,
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +142,7 @@ Examples:
|
||||||
}
|
}
|
||||||
|
|
||||||
console.error(`Unknown command: ${command}`);
|
console.error(`Unknown command: ${command}`);
|
||||||
console.error(`Use 'npx @mariozechner/pi-ai --help' for usage`);
|
console.error(`Use 'npx @mariozechner/companion-ai --help' for usage`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -889,6 +889,23 @@ export const MODELS = {
|
||||||
contextWindow: 204800,
|
contextWindow: 204800,
|
||||||
maxTokens: 131072,
|
maxTokens: 131072,
|
||||||
} satisfies Model<"bedrock-converse-stream">,
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
|
"mistral.devstral-2-123b": {
|
||||||
|
id: "mistral.devstral-2-123b",
|
||||||
|
name: "Devstral 2 135B",
|
||||||
|
api: "bedrock-converse-stream",
|
||||||
|
provider: "amazon-bedrock",
|
||||||
|
baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.4,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 256000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
} satisfies Model<"bedrock-converse-stream">,
|
||||||
"mistral.ministral-3-14b-instruct": {
|
"mistral.ministral-3-14b-instruct": {
|
||||||
id: "mistral.ministral-3-14b-instruct",
|
id: "mistral.ministral-3-14b-instruct",
|
||||||
name: "Ministral 14B 3.0",
|
name: "Ministral 14B 3.0",
|
||||||
|
|
@ -3393,9 +3410,9 @@ export const MODELS = {
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 0,
|
input: 0.5,
|
||||||
output: 0,
|
output: 3,
|
||||||
cacheRead: 0,
|
cacheRead: 0.05,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 1048576,
|
contextWindow: 1048576,
|
||||||
|
|
@ -4714,7 +4731,7 @@ export const MODELS = {
|
||||||
mistral: {
|
mistral: {
|
||||||
"codestral-latest": {
|
"codestral-latest": {
|
||||||
id: "codestral-latest",
|
id: "codestral-latest",
|
||||||
name: "Codestral",
|
name: "Codestral (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -4765,7 +4782,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"devstral-medium-latest": {
|
"devstral-medium-latest": {
|
||||||
id: "devstral-medium-latest",
|
id: "devstral-medium-latest",
|
||||||
name: "Devstral 2",
|
name: "Devstral 2 (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -4833,7 +4850,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"magistral-medium-latest": {
|
"magistral-medium-latest": {
|
||||||
id: "magistral-medium-latest",
|
id: "magistral-medium-latest",
|
||||||
name: "Magistral Medium",
|
name: "Magistral Medium (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -4867,7 +4884,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"ministral-3b-latest": {
|
"ministral-3b-latest": {
|
||||||
id: "ministral-3b-latest",
|
id: "ministral-3b-latest",
|
||||||
name: "Ministral 3B",
|
name: "Ministral 3B (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -4884,7 +4901,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"ministral-8b-latest": {
|
"ministral-8b-latest": {
|
||||||
id: "ministral-8b-latest",
|
id: "ministral-8b-latest",
|
||||||
name: "Ministral 8B",
|
name: "Ministral 8B (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -4935,7 +4952,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"mistral-large-latest": {
|
"mistral-large-latest": {
|
||||||
id: "mistral-large-latest",
|
id: "mistral-large-latest",
|
||||||
name: "Mistral Large",
|
name: "Mistral Large (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -4986,7 +5003,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"mistral-medium-latest": {
|
"mistral-medium-latest": {
|
||||||
id: "mistral-medium-latest",
|
id: "mistral-medium-latest",
|
||||||
name: "Mistral Medium",
|
name: "Mistral Medium (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -5037,7 +5054,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"mistral-small-latest": {
|
"mistral-small-latest": {
|
||||||
id: "mistral-small-latest",
|
id: "mistral-small-latest",
|
||||||
name: "Mistral Small",
|
name: "Mistral Small (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -5122,7 +5139,7 @@ export const MODELS = {
|
||||||
} satisfies Model<"mistral-conversations">,
|
} satisfies Model<"mistral-conversations">,
|
||||||
"pixtral-large-latest": {
|
"pixtral-large-latest": {
|
||||||
id: "pixtral-large-latest",
|
id: "pixtral-large-latest",
|
||||||
name: "Pixtral Large",
|
name: "Pixtral Large (latest)",
|
||||||
api: "mistral-conversations",
|
api: "mistral-conversations",
|
||||||
provider: "mistral",
|
provider: "mistral",
|
||||||
baseUrl: "https://api.mistral.ai",
|
baseUrl: "https://api.mistral.ai",
|
||||||
|
|
@ -6401,6 +6418,23 @@ export const MODELS = {
|
||||||
contextWindow: 262144,
|
contextWindow: 262144,
|
||||||
maxTokens: 65536,
|
maxTokens: 65536,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"mimo-v2-flash-free": {
|
||||||
|
id: "mimo-v2-flash-free",
|
||||||
|
name: "MiMo V2 Flash Free",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "opencode",
|
||||||
|
baseUrl: "https://opencode.ai/zen/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 65536,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"minimax-m2.1": {
|
"minimax-m2.1": {
|
||||||
id: "minimax-m2.1",
|
id: "minimax-m2.1",
|
||||||
name: "MiniMax M2.1",
|
name: "MiniMax M2.1",
|
||||||
|
|
@ -7017,6 +7051,23 @@ export const MODELS = {
|
||||||
contextWindow: 262144,
|
contextWindow: 262144,
|
||||||
maxTokens: 32768,
|
maxTokens: 32768,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"bytedance-seed/seed-2.0-lite": {
|
||||||
|
id: "bytedance-seed/seed-2.0-lite",
|
||||||
|
name: "ByteDance Seed: Seed-2.0-Lite",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "openrouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.25,
|
||||||
|
output: 2,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 131072,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"bytedance-seed/seed-2.0-mini": {
|
"bytedance-seed/seed-2.0-mini": {
|
||||||
id: "bytedance-seed/seed-2.0-mini",
|
id: "bytedance-seed/seed-2.0-mini",
|
||||||
name: "ByteDance Seed: Seed-2.0-Mini",
|
name: "ByteDance Seed: Seed-2.0-Mini",
|
||||||
|
|
@ -7096,11 +7147,11 @@ export const MODELS = {
|
||||||
cost: {
|
cost: {
|
||||||
input: 0.19999999999999998,
|
input: 0.19999999999999998,
|
||||||
output: 0.77,
|
output: 0.77,
|
||||||
cacheRead: 0.13,
|
cacheRead: 0.135,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 163840,
|
contextWindow: 163840,
|
||||||
maxTokens: 163840,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"deepseek/deepseek-chat-v3.1": {
|
"deepseek/deepseek-chat-v3.1": {
|
||||||
id: "deepseek/deepseek-chat-v3.1",
|
id: "deepseek/deepseek-chat-v3.1",
|
||||||
|
|
@ -7468,9 +7519,9 @@ export const MODELS = {
|
||||||
reasoning: false,
|
reasoning: false,
|
||||||
input: ["text", "image"],
|
input: ["text", "image"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 0.04,
|
input: 0.03,
|
||||||
output: 0.15,
|
output: 0.11,
|
||||||
cacheRead: 0.02,
|
cacheRead: 0.015,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 128000,
|
contextWindow: 128000,
|
||||||
|
|
@ -7774,13 +7825,13 @@ export const MODELS = {
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
input: ["text"],
|
input: ["text"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 0.295,
|
input: 0.27,
|
||||||
output: 1.2,
|
output: 0.95,
|
||||||
cacheRead: 0.03,
|
cacheRead: 0.0299999997,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 196608,
|
contextWindow: 196608,
|
||||||
maxTokens: 196608,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"mistralai/codestral-2508": {
|
"mistralai/codestral-2508": {
|
||||||
id: "mistralai/codestral-2508",
|
id: "mistralai/codestral-2508",
|
||||||
|
|
@ -9836,7 +9887,7 @@ export const MODELS = {
|
||||||
cacheRead: 0,
|
cacheRead: 0,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 262144,
|
contextWindow: 131072,
|
||||||
maxTokens: 4096,
|
maxTokens: 4096,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"qwen/qwen3-next-80b-a3b-instruct:free": {
|
"qwen/qwen3-next-80b-a3b-instruct:free": {
|
||||||
|
|
@ -10060,6 +10111,23 @@ export const MODELS = {
|
||||||
contextWindow: 262144,
|
contextWindow: 262144,
|
||||||
maxTokens: 65536,
|
maxTokens: 65536,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"qwen/qwen3.5-9b": {
|
||||||
|
id: "qwen/qwen3.5-9b",
|
||||||
|
name: "Qwen: Qwen3.5-9B",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "openrouter",
|
||||||
|
baseUrl: "https://openrouter.ai/api/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 0.09999999999999999,
|
||||||
|
output: 0.15,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 262144,
|
||||||
|
maxTokens: 4096,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"qwen/qwen3.5-flash-02-23": {
|
"qwen/qwen3.5-flash-02-23": {
|
||||||
id: "qwen/qwen3.5-flash-02-23",
|
id: "qwen/qwen3.5-flash-02-23",
|
||||||
name: "Qwen: Qwen3.5-Flash",
|
name: "Qwen: Qwen3.5-Flash",
|
||||||
|
|
@ -10154,13 +10222,13 @@ export const MODELS = {
|
||||||
reasoning: false,
|
reasoning: false,
|
||||||
input: ["text"],
|
input: ["text"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 0.65,
|
input: 0.85,
|
||||||
output: 0.75,
|
output: 0.85,
|
||||||
cacheRead: 0,
|
cacheRead: 0,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 32768,
|
contextWindow: 131072,
|
||||||
maxTokens: 32768,
|
maxTokens: 16384,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
"stepfun/step-3.5-flash": {
|
"stepfun/step-3.5-flash": {
|
||||||
id: "stepfun/step-3.5-flash",
|
id: "stepfun/step-3.5-flash",
|
||||||
|
|
@ -10731,7 +10799,7 @@ export const MODELS = {
|
||||||
api: "anthropic-messages",
|
api: "anthropic-messages",
|
||||||
provider: "vercel-ai-gateway",
|
provider: "vercel-ai-gateway",
|
||||||
baseUrl: "https://ai-gateway.vercel.sh",
|
baseUrl: "https://ai-gateway.vercel.sh",
|
||||||
reasoning: true,
|
reasoning: false,
|
||||||
input: ["text"],
|
input: ["text"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 0.5,
|
input: 0.5,
|
||||||
|
|
@ -11915,23 +11983,6 @@ export const MODELS = {
|
||||||
contextWindow: 131072,
|
contextWindow: 131072,
|
||||||
maxTokens: 131072,
|
maxTokens: 131072,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
"openai/codex-mini": {
|
|
||||||
id: "openai/codex-mini",
|
|
||||||
name: "Codex Mini",
|
|
||||||
api: "anthropic-messages",
|
|
||||||
provider: "vercel-ai-gateway",
|
|
||||||
baseUrl: "https://ai-gateway.vercel.sh",
|
|
||||||
reasoning: true,
|
|
||||||
input: ["text", "image"],
|
|
||||||
cost: {
|
|
||||||
input: 1.5,
|
|
||||||
output: 6,
|
|
||||||
cacheRead: 0.375,
|
|
||||||
cacheWrite: 0,
|
|
||||||
},
|
|
||||||
contextWindow: 200000,
|
|
||||||
maxTokens: 100000,
|
|
||||||
} satisfies Model<"anthropic-messages">,
|
|
||||||
"openai/gpt-4-turbo": {
|
"openai/gpt-4-turbo": {
|
||||||
id: "openai/gpt-4-turbo",
|
id: "openai/gpt-4-turbo",
|
||||||
name: "GPT-4 Turbo",
|
name: "GPT-4 Turbo",
|
||||||
|
|
@ -12337,7 +12388,7 @@ export const MODELS = {
|
||||||
cacheRead: 0.25,
|
cacheRead: 0.25,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 1050000,
|
contextWindow: 200000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
"openai/gpt-5.4-pro": {
|
"openai/gpt-5.4-pro": {
|
||||||
|
|
@ -12354,7 +12405,7 @@ export const MODELS = {
|
||||||
cacheRead: 0,
|
cacheRead: 0,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 1050000,
|
contextWindow: 200000,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
"openai/gpt-oss-120b": {
|
"openai/gpt-oss-120b": {
|
||||||
|
|
@ -12918,6 +12969,23 @@ export const MODELS = {
|
||||||
contextWindow: 202752,
|
contextWindow: 202752,
|
||||||
maxTokens: 120000,
|
maxTokens: 120000,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
|
"zai/glm-4.7-flash": {
|
||||||
|
id: "zai/glm-4.7-flash",
|
||||||
|
name: "GLM 4.7 Flash",
|
||||||
|
api: "anthropic-messages",
|
||||||
|
provider: "vercel-ai-gateway",
|
||||||
|
baseUrl: "https://ai-gateway.vercel.sh",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: {
|
||||||
|
input: 0.07,
|
||||||
|
output: 0.39999999999999997,
|
||||||
|
cacheRead: 0,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 200000,
|
||||||
|
maxTokens: 131000,
|
||||||
|
} satisfies Model<"anthropic-messages">,
|
||||||
"zai/glm-4.7-flashx": {
|
"zai/glm-4.7-flashx": {
|
||||||
id: "zai/glm-4.7-flashx",
|
id: "zai/glm-4.7-flashx",
|
||||||
name: "GLM 4.7 FlashX",
|
name: "GLM 4.7 FlashX",
|
||||||
|
|
@ -12937,20 +13005,20 @@ export const MODELS = {
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
"zai/glm-5": {
|
"zai/glm-5": {
|
||||||
id: "zai/glm-5",
|
id: "zai/glm-5",
|
||||||
name: "GLM-5",
|
name: "GLM 5",
|
||||||
api: "anthropic-messages",
|
api: "anthropic-messages",
|
||||||
provider: "vercel-ai-gateway",
|
provider: "vercel-ai-gateway",
|
||||||
baseUrl: "https://ai-gateway.vercel.sh",
|
baseUrl: "https://ai-gateway.vercel.sh",
|
||||||
reasoning: true,
|
reasoning: true,
|
||||||
input: ["text"],
|
input: ["text"],
|
||||||
cost: {
|
cost: {
|
||||||
input: 1,
|
input: 0.7999999999999999,
|
||||||
output: 3.1999999999999997,
|
output: 2.56,
|
||||||
cacheRead: 0.19999999999999998,
|
cacheRead: 0.16,
|
||||||
cacheWrite: 0,
|
cacheWrite: 0,
|
||||||
},
|
},
|
||||||
contextWindow: 202800,
|
contextWindow: 202800,
|
||||||
maxTokens: 131072,
|
maxTokens: 131100,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} satisfies Model<"anthropic-messages">,
|
||||||
},
|
},
|
||||||
xai: {
|
xai: {
|
||||||
|
|
@ -13277,6 +13345,57 @@ export const MODELS = {
|
||||||
contextWindow: 2000000,
|
contextWindow: 2000000,
|
||||||
maxTokens: 30000,
|
maxTokens: 30000,
|
||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-4.20-experimental-beta-0304-non-reasoning": {
|
||||||
|
id: "grok-4.20-experimental-beta-0304-non-reasoning",
|
||||||
|
name: "Grok 4.20 (Experimental, Non-Reasoning)",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 6,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 2000000,
|
||||||
|
maxTokens: 30000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-4.20-experimental-beta-0304-reasoning": {
|
||||||
|
id: "grok-4.20-experimental-beta-0304-reasoning",
|
||||||
|
name: "Grok 4.20 (Experimental, Reasoning)",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 6,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 2000000,
|
||||||
|
maxTokens: 30000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
|
"grok-4.20-multi-agent-experimental-beta-0304": {
|
||||||
|
id: "grok-4.20-multi-agent-experimental-beta-0304",
|
||||||
|
name: "Grok 4.20 Multi-Agent (Experimental)",
|
||||||
|
api: "openai-completions",
|
||||||
|
provider: "xai",
|
||||||
|
baseUrl: "https://api.x.ai/v1",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text", "image"],
|
||||||
|
cost: {
|
||||||
|
input: 2,
|
||||||
|
output: 6,
|
||||||
|
cacheRead: 0.2,
|
||||||
|
cacheWrite: 0,
|
||||||
|
},
|
||||||
|
contextWindow: 2000000,
|
||||||
|
maxTokens: 30000,
|
||||||
|
} satisfies Model<"openai-completions">,
|
||||||
"grok-beta": {
|
"grok-beta": {
|
||||||
id: "grok-beta",
|
id: "grok-beta",
|
||||||
name: "Grok Beta",
|
name: "Grok Beta",
|
||||||
|
|
|
||||||
|
|
@ -514,7 +514,7 @@ function mapThinkingLevelToEffort(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve cache retention preference.
|
* Resolve cache retention preference.
|
||||||
* Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
|
* Defaults to "short" and uses COMPANION_CACHE_RETENTION for backward compatibility.
|
||||||
*/
|
*/
|
||||||
function resolveCacheRetention(
|
function resolveCacheRetention(
|
||||||
cacheRetention?: CacheRetention,
|
cacheRetention?: CacheRetention,
|
||||||
|
|
@ -524,7 +524,7 @@ function resolveCacheRetention(
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
typeof process !== "undefined" &&
|
typeof process !== "undefined" &&
|
||||||
process.env.PI_CACHE_RETENTION === "long"
|
process.env.COMPANION_CACHE_RETENTION === "long"
|
||||||
) {
|
) {
|
||||||
return "long";
|
return "long";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import { transformMessages } from "./transform-messages.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve cache retention preference.
|
* Resolve cache retention preference.
|
||||||
* Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
|
* Defaults to "short" and uses COMPANION_CACHE_RETENTION for backward compatibility.
|
||||||
*/
|
*/
|
||||||
function resolveCacheRetention(
|
function resolveCacheRetention(
|
||||||
cacheRetention?: CacheRetention,
|
cacheRetention?: CacheRetention,
|
||||||
|
|
@ -50,7 +50,7 @@ function resolveCacheRetention(
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
typeof process !== "undefined" &&
|
typeof process !== "undefined" &&
|
||||||
process.env.PI_CACHE_RETENTION === "long"
|
process.env.COMPANION_CACHE_RETENTION === "long"
|
||||||
) {
|
) {
|
||||||
return "long";
|
return "long";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ const DEFAULT_ANTIGRAVITY_VERSION = "1.18.3";
|
||||||
|
|
||||||
function getAntigravityHeaders() {
|
function getAntigravityHeaders() {
|
||||||
const version =
|
const version =
|
||||||
process.env.PI_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION;
|
process.env.COMPANION_AI_ANTIGRAVITY_VERSION || DEFAULT_ANTIGRAVITY_VERSION;
|
||||||
return {
|
return {
|
||||||
"User-Agent": `antigravity/${version} darwin/arm64`,
|
"User-Agent": `antigravity/${version} darwin/arm64`,
|
||||||
};
|
};
|
||||||
|
|
@ -1040,8 +1040,8 @@ export function buildRequest(
|
||||||
model: model.id,
|
model: model.id,
|
||||||
request,
|
request,
|
||||||
...(isAntigravity ? { requestType: "agent" } : {}),
|
...(isAntigravity ? { requestType: "agent" } : {}),
|
||||||
userAgent: isAntigravity ? "antigravity" : "pi-coding-agent",
|
userAgent: isAntigravity ? "antigravity" : "companion-coding-agent",
|
||||||
requestId: `${isAntigravity ? "agent" : "pi"}-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
|
requestId: `${isAntigravity ? "agent" : "companion"}-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -997,10 +997,10 @@ function buildHeaders(
|
||||||
headers.set("Authorization", `Bearer ${token}`);
|
headers.set("Authorization", `Bearer ${token}`);
|
||||||
headers.set("chatgpt-account-id", accountId);
|
headers.set("chatgpt-account-id", accountId);
|
||||||
headers.set("OpenAI-Beta", "responses=experimental");
|
headers.set("OpenAI-Beta", "responses=experimental");
|
||||||
headers.set("originator", "pi");
|
headers.set("originator", "companion");
|
||||||
const userAgent = _os
|
const userAgent = _os
|
||||||
? `pi (${_os.platform()} ${_os.release()}; ${_os.arch()})`
|
? `companion (${_os.platform()} ${_os.release()}; ${_os.arch()})`
|
||||||
: "pi (browser)";
|
: "companion (browser)";
|
||||||
headers.set("User-Agent", userAgent);
|
headers.set("User-Agent", userAgent);
|
||||||
headers.set("accept", "text/event-stream");
|
headers.set("accept", "text/event-stream");
|
||||||
headers.set("content-type", "application/json");
|
headers.set("content-type", "application/json");
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ const OPENAI_TOOL_CALL_PROVIDERS = new Set([
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve cache retention preference.
|
* Resolve cache retention preference.
|
||||||
* Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
|
* Defaults to "short" and uses COMPANION_CACHE_RETENTION for backward compatibility.
|
||||||
*/
|
*/
|
||||||
function resolveCacheRetention(
|
function resolveCacheRetention(
|
||||||
cacheRetention?: CacheRetention,
|
cacheRetention?: CacheRetention,
|
||||||
|
|
@ -43,7 +43,7 @@ function resolveCacheRetention(
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
typeof process !== "undefined" &&
|
typeof process !== "undefined" &&
|
||||||
process.env.PI_CACHE_RETENTION === "long"
|
process.env.COMPANION_CACHE_RETENTION === "long"
|
||||||
) {
|
) {
|
||||||
return "long";
|
return "long";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ export interface OpenAICompletionsCompat {
|
||||||
supportsDeveloperRole?: boolean;
|
supportsDeveloperRole?: boolean;
|
||||||
/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */
|
/** Whether the provider supports `reasoning_effort`. Default: auto-detected from URL. */
|
||||||
supportsReasoningEffort?: boolean;
|
supportsReasoningEffort?: boolean;
|
||||||
/** Optional mapping from pi-ai reasoning levels to provider/model-specific `reasoning_effort` values. */
|
/** Optional mapping from companion-ai reasoning levels to provider/model-specific `reasoning_effort` values. */
|
||||||
reasoningEffortMap?: Partial<Record<ThinkingLevel, string>>;
|
reasoningEffortMap?: Partial<Record<ThinkingLevel, string>>;
|
||||||
/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */
|
/** Whether the provider supports `stream_options: { include_usage: true }` for token usage in streaming responses. Default: true. */
|
||||||
supportsUsageInStreaming?: boolean;
|
supportsUsageInStreaming?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ async function refreshAccessToken(refreshToken: string): Promise<TokenResult> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createAuthorizationFlow(
|
async function createAuthorizationFlow(
|
||||||
originator: string = "pi",
|
originator: string = "companion",
|
||||||
): Promise<{ verifier: string; state: string; url: string }> {
|
): Promise<{ verifier: string; state: string; url: string }> {
|
||||||
const { verifier, challenge } = await generatePKCE();
|
const { verifier, challenge } = await generatePKCE();
|
||||||
const state = createState();
|
const state = createState();
|
||||||
|
|
@ -337,7 +337,7 @@ function getAccountId(accessToken: string): string | null {
|
||||||
* @param options.onManualCodeInput - Optional promise that resolves with user-pasted code.
|
* @param options.onManualCodeInput - Optional promise that resolves with user-pasted code.
|
||||||
* Races with browser callback - whichever completes first wins.
|
* Races with browser callback - whichever completes first wins.
|
||||||
* Useful for showing paste input immediately alongside browser flow.
|
* Useful for showing paste input immediately alongside browser flow.
|
||||||
* @param options.originator - OAuth originator parameter (defaults to "pi")
|
* @param options.originator - OAuth originator parameter (defaults to "companion")
|
||||||
*/
|
*/
|
||||||
export async function loginOpenAICodex(options: {
|
export async function loginOpenAICodex(options: {
|
||||||
onAuth: (info: { url: string; instructions?: string }) => void;
|
onAuth: (info: { url: string; instructions?: string }) => void;
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ describe.skipIf(!oauthToken)("Anthropic OAuth tool name normalization", () => {
|
||||||
expect(toolCallName).toBe("todowrite");
|
expect(toolCallName).toBe("todowrite");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should handle pi's built-in tools (read, write, edit, bash)", async () => {
|
it("should handle companion's built-in tools (read, write, edit, bash)", async () => {
|
||||||
// Pi's tools use lowercase names, CC uses PascalCase
|
// Companion's tools use lowercase names, CC uses PascalCase
|
||||||
const readTool: Tool = {
|
const readTool: Tool = {
|
||||||
name: "read",
|
name: "read",
|
||||||
description: "Read a file",
|
description: "Read a file",
|
||||||
|
|
@ -116,7 +116,7 @@ describe.skipIf(!oauthToken)("Anthropic OAuth tool name normalization", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should NOT map find to Glob - find is not a CC tool name", async () => {
|
it("should NOT map find to Glob - find is not a CC tool name", async () => {
|
||||||
// Pi has a "find" tool, CC has "Glob" - these are DIFFERENT tools
|
// Companion has a "find" tool, CC has "Glob" - these are DIFFERENT tools
|
||||||
// The old code incorrectly mapped find -> Glob, which broke the round-trip
|
// The old code incorrectly mapped find -> Glob, which broke the round-trip
|
||||||
// because there's no tool named "glob" in context.tools
|
// because there's no tool named "glob" in context.tools
|
||||||
const findTool: Tool = {
|
const findTool: Tool = {
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,18 @@ import { getModel } from "../src/models.js";
|
||||||
import { stream } from "../src/stream.js";
|
import { stream } from "../src/stream.js";
|
||||||
import type { Context } from "../src/types.js";
|
import type { Context } from "../src/types.js";
|
||||||
|
|
||||||
describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
describe("Cache Retention (COMPANION_CACHE_RETENTION)", () => {
|
||||||
const originalEnv = process.env.PI_CACHE_RETENTION;
|
const originalEnv = process.env.COMPANION_CACHE_RETENTION;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
delete process.env.PI_CACHE_RETENTION;
|
delete process.env.COMPANION_CACHE_RETENTION;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
if (originalEnv !== undefined) {
|
if (originalEnv !== undefined) {
|
||||||
process.env.PI_CACHE_RETENTION = originalEnv;
|
process.env.COMPANION_CACHE_RETENTION = originalEnv;
|
||||||
} else {
|
} else {
|
||||||
delete process.env.PI_CACHE_RETENTION;
|
delete process.env.COMPANION_CACHE_RETENTION;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||||
|
|
||||||
describe("Anthropic Provider", () => {
|
describe("Anthropic Provider", () => {
|
||||||
it.skipIf(!process.env.ANTHROPIC_API_KEY)(
|
it.skipIf(!process.env.ANTHROPIC_API_KEY)(
|
||||||
"should use default cache TTL (no ttl field) when PI_CACHE_RETENTION is not set",
|
"should use default cache TTL (no ttl field) when COMPANION_CACHE_RETENTION is not set",
|
||||||
async () => {
|
async () => {
|
||||||
const model = getModel("anthropic", "claude-3-5-haiku-20241022");
|
const model = getModel("anthropic", "claude-3-5-haiku-20241022");
|
||||||
let capturedPayload: any = null;
|
let capturedPayload: any = null;
|
||||||
|
|
@ -51,9 +51,9 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!process.env.ANTHROPIC_API_KEY)(
|
it.skipIf(!process.env.ANTHROPIC_API_KEY)(
|
||||||
"should use 1h cache TTL when PI_CACHE_RETENTION=long",
|
"should use 1h cache TTL when COMPANION_CACHE_RETENTION=long",
|
||||||
async () => {
|
async () => {
|
||||||
process.env.PI_CACHE_RETENTION = "long";
|
process.env.COMPANION_CACHE_RETENTION = "long";
|
||||||
const model = getModel("anthropic", "claude-3-5-haiku-20241022");
|
const model = getModel("anthropic", "claude-3-5-haiku-20241022");
|
||||||
let capturedPayload: any = null;
|
let capturedPayload: any = null;
|
||||||
|
|
||||||
|
|
@ -79,7 +79,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it("should not add ttl when baseUrl is not api.anthropic.com", async () => {
|
it("should not add ttl when baseUrl is not api.anthropic.com", async () => {
|
||||||
process.env.PI_CACHE_RETENTION = "long";
|
process.env.COMPANION_CACHE_RETENTION = "long";
|
||||||
|
|
||||||
// Create a model with a different baseUrl (simulating a proxy)
|
// Create a model with a different baseUrl (simulating a proxy)
|
||||||
const baseModel = getModel("anthropic", "claude-3-5-haiku-20241022");
|
const baseModel = getModel("anthropic", "claude-3-5-haiku-20241022");
|
||||||
|
|
@ -210,7 +210,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||||
|
|
||||||
describe("OpenAI Responses Provider", () => {
|
describe("OpenAI Responses Provider", () => {
|
||||||
it.skipIf(!process.env.OPENAI_API_KEY)(
|
it.skipIf(!process.env.OPENAI_API_KEY)(
|
||||||
"should not set prompt_cache_retention when PI_CACHE_RETENTION is not set",
|
"should not set prompt_cache_retention when COMPANION_CACHE_RETENTION is not set",
|
||||||
async () => {
|
async () => {
|
||||||
const model = getModel("openai", "gpt-4o-mini");
|
const model = getModel("openai", "gpt-4o-mini");
|
||||||
let capturedPayload: any = null;
|
let capturedPayload: any = null;
|
||||||
|
|
@ -232,9 +232,9 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it.skipIf(!process.env.OPENAI_API_KEY)(
|
it.skipIf(!process.env.OPENAI_API_KEY)(
|
||||||
"should set prompt_cache_retention to 24h when PI_CACHE_RETENTION=long",
|
"should set prompt_cache_retention to 24h when COMPANION_CACHE_RETENTION=long",
|
||||||
async () => {
|
async () => {
|
||||||
process.env.PI_CACHE_RETENTION = "long";
|
process.env.COMPANION_CACHE_RETENTION = "long";
|
||||||
const model = getModel("openai", "gpt-4o-mini");
|
const model = getModel("openai", "gpt-4o-mini");
|
||||||
let capturedPayload: any = null;
|
let capturedPayload: any = null;
|
||||||
|
|
||||||
|
|
@ -255,7 +255,7 @@ describe("Cache Retention (PI_CACHE_RETENTION)", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it("should not set prompt_cache_retention when baseUrl is not api.openai.com", async () => {
|
it("should not set prompt_cache_retention when baseUrl is not api.openai.com", async () => {
|
||||||
process.env.PI_CACHE_RETENTION = "long";
|
process.env.COMPANION_CACHE_RETENTION = "long";
|
||||||
|
|
||||||
// Create a model with a different baseUrl (simulating a proxy)
|
// Create a model with a different baseUrl (simulating a proxy)
|
||||||
const baseModel = getModel("openai", "gpt-4o-mini");
|
const baseModel = getModel("openai", "gpt-4o-mini");
|
||||||
|
|
|
||||||
|
|
@ -683,7 +683,7 @@ describe("Context overflow error handling", () => {
|
||||||
|
|
||||||
// Check if ollama is installed and local LLM tests are enabled
|
// Check if ollama is installed and local LLM tests are enabled
|
||||||
let ollamaInstalled = false;
|
let ollamaInstalled = false;
|
||||||
if (!process.env.PI_NO_LOCAL_LLM) {
|
if (!process.env.COMPANION_NO_LOCAL_LLM) {
|
||||||
try {
|
try {
|
||||||
execSync("which ollama", { stdio: "ignore" });
|
execSync("which ollama", { stdio: "ignore" });
|
||||||
ollamaInstalled = true;
|
ollamaInstalled = true;
|
||||||
|
|
@ -785,7 +785,7 @@ describe("Context overflow error handling", () => {
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
let lmStudioRunning = false;
|
let lmStudioRunning = false;
|
||||||
if (!process.env.PI_NO_LOCAL_LLM) {
|
if (!process.env.COMPANION_NO_LOCAL_LLM) {
|
||||||
try {
|
try {
|
||||||
execSync(
|
execSync(
|
||||||
"curl -s --max-time 1 http://localhost:1234/v1/models > /dev/null",
|
"curl -s --max-time 1 http://localhost:1234/v1/models > /dev/null",
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ function dumpFailurePayload(params: {
|
||||||
payload?: unknown;
|
payload?: unknown;
|
||||||
messages: Message[];
|
messages: Message[];
|
||||||
}): void {
|
}): void {
|
||||||
const filename = `/tmp/pi-handoff-${params.label}-${Date.now()}.json`;
|
const filename = `/tmp/companion-handoff-${params.label}-${Date.now()}.json`;
|
||||||
const body = {
|
const body = {
|
||||||
label: params.label,
|
label: params.label,
|
||||||
error: params.error,
|
error: params.error,
|
||||||
|
|
|
||||||
|
|
@ -765,7 +765,7 @@ describe("AI Providers Empty Message Tests", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// OAuth-based providers (credentials from ~/.pi/agent/oauth.json)
|
// OAuth-based providers (credentials from ~/.companion/agent/oauth.json)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
describe("Anthropic OAuth Provider Empty Messages", () => {
|
describe("Anthropic OAuth Provider Empty Messages", () => {
|
||||||
|
|
|
||||||
|
|
@ -476,7 +476,7 @@ describe("Tool Results with Images", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// OAuth-based providers (credentials from ~/.pi/agent/oauth.json)
|
// OAuth-based providers (credentials from ~/.companion/agent/oauth.json)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
describe("Anthropic OAuth Provider (claude-sonnet-4-5)", () => {
|
describe("Anthropic OAuth Provider (claude-sonnet-4-5)", () => {
|
||||||
|
|
@ -584,7 +584,7 @@ describe("Tool Results with Images", () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/** These two don't work, the model simply won't call the tool, works in pi
|
/** These two don't work, the model simply won't call the tool, works in companion
|
||||||
it.skipIf(!antigravityToken)(
|
it.skipIf(!antigravityToken)(
|
||||||
"claude-sonnet-4-5 - should handle tool result with only image",
|
"claude-sonnet-4-5 - should handle tool result with only image",
|
||||||
{ retry: 3, timeout: 30000 },
|
{ retry: 3, timeout: 30000 },
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Test helper for resolving API keys from ~/.pi/agent/auth.json
|
* Test helper for resolving API keys from ~/.companion/agent/auth.json
|
||||||
*
|
*
|
||||||
* Supports both API key and OAuth credentials.
|
* Supports both API key and OAuth credentials.
|
||||||
* OAuth tokens are automatically refreshed if expired and saved back to auth.json.
|
* OAuth tokens are automatically refreshed if expired and saved back to auth.json.
|
||||||
|
|
@ -20,7 +20,7 @@ import type {
|
||||||
OAuthProvider,
|
OAuthProvider,
|
||||||
} from "../src/utils/oauth/types.js";
|
} from "../src/utils/oauth/types.js";
|
||||||
|
|
||||||
const AUTH_PATH = join(homedir(), ".pi", "agent", "auth.json");
|
const AUTH_PATH = join(homedir(), ".companion", "agent", "auth.json");
|
||||||
|
|
||||||
type ApiKeyCredential = {
|
type ApiKeyCredential = {
|
||||||
type: "api_key";
|
type: "api_key";
|
||||||
|
|
@ -57,7 +57,7 @@ function saveAuthStorage(storage: AuthStorage): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve API key for a provider from ~/.pi/agent/auth.json
|
* Resolve API key for a provider from ~/.companion/agent/auth.json
|
||||||
*
|
*
|
||||||
* For API key credentials, returns the key directly.
|
* For API key credentials, returns the key directly.
|
||||||
* For OAuth credentials, returns the access token (refreshing if expired and saving back).
|
* For OAuth credentials, returns the access token (refreshing if expired and saving back).
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,22 @@ import { streamOpenAICodexResponses } from "../src/providers/openai-codex-respon
|
||||||
import type { Context, Model } from "../src/types.js";
|
import type { Context, Model } from "../src/types.js";
|
||||||
|
|
||||||
const originalFetch = global.fetch;
|
const originalFetch = global.fetch;
|
||||||
const originalAgentDir = process.env.PI_CODING_AGENT_DIR;
|
const originalAgentDir = process.env.COMPANION_CODING_AGENT_DIR;
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
global.fetch = originalFetch;
|
global.fetch = originalFetch;
|
||||||
if (originalAgentDir === undefined) {
|
if (originalAgentDir === undefined) {
|
||||||
delete process.env.PI_CODING_AGENT_DIR;
|
delete process.env.COMPANION_CODING_AGENT_DIR;
|
||||||
} else {
|
} else {
|
||||||
process.env.PI_CODING_AGENT_DIR = originalAgentDir;
|
process.env.COMPANION_CODING_AGENT_DIR = originalAgentDir;
|
||||||
}
|
}
|
||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("openai-codex streaming", () => {
|
describe("openai-codex streaming", () => {
|
||||||
it("streams SSE responses into AssistantMessageEventStream", async () => {
|
it("streams SSE responses into AssistantMessageEventStream", async () => {
|
||||||
const tempDir = mkdtempSync(join(tmpdir(), "pi-codex-stream-"));
|
const tempDir = mkdtempSync(join(tmpdir(), "companion-codex-stream-"));
|
||||||
process.env.PI_CODING_AGENT_DIR = tempDir;
|
process.env.COMPANION_CODING_AGENT_DIR = tempDir;
|
||||||
|
|
||||||
const payload = Buffer.from(
|
const payload = Buffer.from(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
@ -95,7 +95,7 @@ describe("openai-codex streaming", () => {
|
||||||
expect(headers?.get("Authorization")).toBe(`Bearer ${token}`);
|
expect(headers?.get("Authorization")).toBe(`Bearer ${token}`);
|
||||||
expect(headers?.get("chatgpt-account-id")).toBe("acc_test");
|
expect(headers?.get("chatgpt-account-id")).toBe("acc_test");
|
||||||
expect(headers?.get("OpenAI-Beta")).toBe("responses=experimental");
|
expect(headers?.get("OpenAI-Beta")).toBe("responses=experimental");
|
||||||
expect(headers?.get("originator")).toBe("pi");
|
expect(headers?.get("originator")).toBe("companion");
|
||||||
expect(headers?.get("accept")).toBe("text/event-stream");
|
expect(headers?.get("accept")).toBe("text/event-stream");
|
||||||
expect(headers?.has("x-api-key")).toBe(false);
|
expect(headers?.has("x-api-key")).toBe(false);
|
||||||
return new Response(stream, {
|
return new Response(stream, {
|
||||||
|
|
@ -149,8 +149,8 @@ describe("openai-codex streaming", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets conversation_id/session_id headers and prompt_cache_key when sessionId is provided", async () => {
|
it("sets conversation_id/session_id headers and prompt_cache_key when sessionId is provided", async () => {
|
||||||
const tempDir = mkdtempSync(join(tmpdir(), "pi-codex-stream-"));
|
const tempDir = mkdtempSync(join(tmpdir(), "companion-codex-stream-"));
|
||||||
process.env.PI_CODING_AGENT_DIR = tempDir;
|
process.env.COMPANION_CODING_AGENT_DIR = tempDir;
|
||||||
|
|
||||||
const payload = Buffer.from(
|
const payload = Buffer.from(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
@ -272,8 +272,8 @@ describe("openai-codex streaming", () => {
|
||||||
it.each(["gpt-5.3-codex", "gpt-5.4"])(
|
it.each(["gpt-5.3-codex", "gpt-5.4"])(
|
||||||
"clamps %s minimal reasoning effort to low",
|
"clamps %s minimal reasoning effort to low",
|
||||||
async (modelId) => {
|
async (modelId) => {
|
||||||
const tempDir = mkdtempSync(join(tmpdir(), "pi-codex-stream-"));
|
const tempDir = mkdtempSync(join(tmpdir(), "companion-codex-stream-"));
|
||||||
process.env.PI_CODING_AGENT_DIR = tempDir;
|
process.env.COMPANION_CODING_AGENT_DIR = tempDir;
|
||||||
|
|
||||||
const payload = Buffer.from(
|
const payload = Buffer.from(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
@ -393,8 +393,8 @@ describe("openai-codex streaming", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it("does not set conversation_id/session_id headers when sessionId is not provided", async () => {
|
it("does not set conversation_id/session_id headers when sessionId is not provided", async () => {
|
||||||
const tempDir = mkdtempSync(join(tmpdir(), "pi-codex-stream-"));
|
const tempDir = mkdtempSync(join(tmpdir(), "companion-codex-stream-"));
|
||||||
process.env.PI_CODING_AGENT_DIR = tempDir;
|
process.env.COMPANION_CODING_AGENT_DIR = tempDir;
|
||||||
|
|
||||||
const payload = Buffer.from(
|
const payload = Buffer.from(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
|
||||||
|
|
@ -1048,7 +1048,7 @@ describe("Generate E2E Tests", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// OAuth-based providers (credentials from ~/.pi/agent/oauth.json)
|
// OAuth-based providers (credentials from ~/.companion/agent/oauth.json)
|
||||||
// Tokens are resolved at module level (see oauthTokens above)
|
// Tokens are resolved at module level (see oauthTokens above)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
|
|
@ -1800,7 +1800,7 @@ describe("Generate E2E Tests", () => {
|
||||||
|
|
||||||
// Check if ollama is installed and local LLM tests are enabled
|
// Check if ollama is installed and local LLM tests are enabled
|
||||||
let ollamaInstalled = false;
|
let ollamaInstalled = false;
|
||||||
if (!process.env.PI_NO_LOCAL_LLM) {
|
if (!process.env.COMPANION_NO_LOCAL_LLM) {
|
||||||
try {
|
try {
|
||||||
execSync("which ollama", { stdio: "ignore" });
|
execSync("which ollama", { stdio: "ignore" });
|
||||||
ollamaInstalled = true;
|
ollamaInstalled = true;
|
||||||
|
|
|
||||||
|
|
@ -294,7 +294,7 @@ describe("Token Statistics on Abort", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// OAuth-based providers (credentials from ~/.pi/agent/oauth.json)
|
// OAuth-based providers (credentials from ~/.companion/agent/oauth.json)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
describe("Anthropic OAuth Provider", () => {
|
describe("Anthropic OAuth Provider", () => {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
* OpenAI Responses API generates IDs in format: {call_id}|{id}
|
* OpenAI Responses API generates IDs in format: {call_id}|{id}
|
||||||
* where {id} can be 400+ chars with special characters (+, /, =).
|
* where {id} can be 400+ chars with special characters (+, /, =).
|
||||||
*
|
*
|
||||||
* Regression test for: https://github.com/badlogic/pi-mono/issues/1022
|
* Regression test for: https://github.com/badlogic/companion-mono/issues/1022
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Type } from "@sinclair/typebox";
|
import { Type } from "@sinclair/typebox";
|
||||||
|
|
|
||||||
|
|
@ -324,7 +324,7 @@ describe("Tool Call Without Result Tests", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// OAuth-based providers (credentials from ~/.pi/agent/oauth.json)
|
// OAuth-based providers (credentials from ~/.companion/agent/oauth.json)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
describe("Anthropic OAuth Provider", () => {
|
describe("Anthropic OAuth Provider", () => {
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,7 @@ describe("AI Providers Unicode Surrogate Pair Tests", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// OAuth-based providers (credentials from ~/.pi/agent/oauth.json)
|
// OAuth-based providers (credentials from ~/.companion/agent/oauth.json)
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
describe("Anthropic OAuth Provider Unicode Handling", () => {
|
describe("Anthropic OAuth Provider Unicode Handling", () => {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,24 +1,24 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://shittycodingagent.ai">
|
<a href="https://shittycodingagent.ai">
|
||||||
<img src="https://shittycodingagent.ai/logo.svg" alt="pi logo" width="128">
|
<img src="https://shittycodingagent.ai/logo.svg" alt="companion logo" width="128">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://discord.com/invite/3cU7Bz4UPx"><img alt="Discord" src="https://img.shields.io/badge/discord-community-5865F2?style=flat-square&logo=discord&logoColor=white" /></a>
|
<a href="https://discord.com/invite/3cU7Bz4UPx"><img alt="Discord" src="https://img.shields.io/badge/discord-community-5865F2?style=flat-square&logo=discord&logoColor=white" /></a>
|
||||||
<a href="https://www.npmjs.com/package/@mariozechner/pi-coding-agent"><img alt="npm" src="https://img.shields.io/npm/v/@mariozechner/pi-coding-agent?style=flat-square" /></a>
|
<a href="https://www.npmjs.com/package/@mariozechner/companion-coding-agent"><img alt="npm" src="https://img.shields.io/npm/v/@mariozechner/companion-coding-agent?style=flat-square" /></a>
|
||||||
<a href="https://github.com/getcompanion-ai/co-mono/actions/workflows/ci.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/getcompanion-ai/co-mono/ci.yml?style=flat-square&branch=main" /></a>
|
<a href="https://github.com/getcompanion-ai/co-mono/actions/workflows/ci.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/getcompanion-ai/co-mono/ci.yml?style=flat-square&branch=main" /></a>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://pi.dev">pi.dev</a> domain graciously donated by
|
<a href="https://companion.dev">companion.dev</a> domain graciously donated by
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a href="https://exe.dev"><img src="docs/images/exy.png" alt="Exy mascot" width="48" /><br />exe.dev</a>
|
<a href="https://exe.dev"><img src="docs/images/exy.png" alt="Exy mascot" width="48" /><br />exe.dev</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Pi is a minimal terminal coding harness. Adapt pi to your workflows, not the other way around, without having to fork and modify pi internals. Extend it with TypeScript [Extensions](#extensions), [Skills](#skills), [Prompt Templates](#prompt-templates), and [Themes](#themes). Put your extensions, skills, prompt templates, and themes in [Pi Packages](#pi-packages) and share them with others via npm or git.
|
Companion is a minimal terminal coding harness. Adapt companion to your workflows, not the other way around, without having to fork and modify companion internals. Extend it with TypeScript [Extensions](#extensions), [Skills](#skills), [Prompt Templates](#prompt-templates), and [Themes](#themes). Put your extensions, skills, prompt templates, and themes in [Companion Packages](#companion-packages) and share them with others via npm or git.
|
||||||
|
|
||||||
Pi ships with powerful defaults but skips features like sub agents and plan mode. Instead, you can ask pi to build what you want or install a third party pi package that matches your workflow.
|
Companion ships with powerful defaults but skips features like sub agents and plan mode. Instead, you can ask companion to build what you want or install a third party companion package that matches your workflow.
|
||||||
|
|
||||||
Pi runs in four modes: interactive, print or JSON, RPC for process integration, and an SDK for embedding in your own apps. See [openclaw/openclaw](https://github.com/openclaw/openclaw) for a real-world SDK integration.
|
Companion runs in four modes: interactive, print or JSON, RPC for process integration, and an SDK for embedding in your own apps. See [openclaw/openclaw](https://github.com/openclaw/openclaw) for a real-world SDK integration.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ Pi runs in four modes: interactive, print or JSON, RPC for process integration,
|
||||||
- [Skills](#skills)
|
- [Skills](#skills)
|
||||||
- [Extensions](#extensions)
|
- [Extensions](#extensions)
|
||||||
- [Themes](#themes)
|
- [Themes](#themes)
|
||||||
- [Pi Packages](#pi-packages)
|
- [Companion Packages](#companion-packages)
|
||||||
- [Programmatic Usage](#programmatic-usage)
|
- [Programmatic Usage](#programmatic-usage)
|
||||||
- [Philosophy](#philosophy)
|
- [Philosophy](#philosophy)
|
||||||
- [CLI Reference](#cli-reference)
|
- [CLI Reference](#cli-reference)
|
||||||
|
|
@ -49,24 +49,24 @@ Pi runs in four modes: interactive, print or JSON, RPC for process integration,
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install -g @mariozechner/pi-coding-agent
|
npm install -g @mariozechner/companion-coding-agent
|
||||||
```
|
```
|
||||||
|
|
||||||
Authenticate with an API key:
|
Authenticate with an API key:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export ANTHROPIC_API_KEY=sk-ant-...
|
export ANTHROPIC_API_KEY=sk-ant-...
|
||||||
pi
|
companion
|
||||||
```
|
```
|
||||||
|
|
||||||
Or use your existing subscription:
|
Or use your existing subscription:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi
|
companion
|
||||||
/login # Then select provider
|
/login # Then select provider
|
||||||
```
|
```
|
||||||
|
|
||||||
Then just talk to pi. By default, pi gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [pi packages](#pi-packages).
|
Then just talk to companion. By default, companion gives the model four tools: `read`, `write`, `edit`, and `bash`. The model uses these to fulfill your requests. Add capabilities via [skills](#skills), [prompt templates](#prompt-templates), [extensions](#extensions), or [companion packages](#companion-packages).
|
||||||
|
|
||||||
**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
|
**Platform notes:** [Windows](docs/windows.md) | [Termux (Android)](docs/termux.md) | [Terminal setup](docs/terminal-setup.md) | [Shell aliases](docs/shell-aliases.md)
|
||||||
|
|
||||||
|
|
@ -74,7 +74,7 @@ Then just talk to pi. By default, pi gives the model four tools: `read`, `write`
|
||||||
|
|
||||||
## Providers & Models
|
## Providers & Models
|
||||||
|
|
||||||
For each built-in provider, pi maintains a list of tool-capable models, updated with every release. Authenticate via subscription (`/login`) or API key, then select any model from that provider via `/model` (or Ctrl+L).
|
For each built-in provider, companion maintains a list of tool-capable models, updated with every release. Authenticate via subscription (`/login`) or API key, then select any model from that provider via `/model` (or Ctrl+L).
|
||||||
|
|
||||||
**Subscriptions:**
|
**Subscriptions:**
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ For each built-in provider, pi maintains a list of tool-capable models, updated
|
||||||
|
|
||||||
See [docs/providers.md](docs/providers.md) for detailed setup instructions.
|
See [docs/providers.md](docs/providers.md) for detailed setup instructions.
|
||||||
|
|
||||||
**Custom providers & models:** Add providers via `~/.pi/agent/models.json` if they speak a supported API (OpenAI, Anthropic, Google). For custom APIs or OAuth, use extensions. See [docs/models.md](docs/models.md) and [docs/custom-provider.md](docs/custom-provider.md).
|
**Custom providers & models:** Add providers via `~/.companion/agent/models.json` if they speak a supported API (OpenAI, Anthropic, Google). For custom APIs or OAuth, use extensions. See [docs/models.md](docs/models.md) and [docs/custom-provider.md](docs/custom-provider.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -159,11 +159,11 @@ Type `/` in the editor to trigger commands. [Extensions](#extensions) can regist
|
||||||
| `/reload` | Reload extensions, skills, prompts, context files (themes hot-reload automatically) |
|
| `/reload` | Reload extensions, skills, prompts, context files (themes hot-reload automatically) |
|
||||||
| `/hotkeys` | Show all keyboard shortcuts |
|
| `/hotkeys` | Show all keyboard shortcuts |
|
||||||
| `/changelog` | Display version history |
|
| `/changelog` | Display version history |
|
||||||
| `/quit`, `/exit` | Quit pi |
|
| `/quit`, `/exit` | Quit companion |
|
||||||
|
|
||||||
### Keyboard Shortcuts
|
### Keyboard Shortcuts
|
||||||
|
|
||||||
See `/hotkeys` for the full list. Customize via `~/.pi/agent/keybindings.json`. See [docs/keybindings.md](docs/keybindings.md).
|
See `/hotkeys` for the full list. Customize via `~/.companion/agent/keybindings.json`. See [docs/keybindings.md](docs/keybindings.md).
|
||||||
|
|
||||||
**Commonly used:**
|
**Commonly used:**
|
||||||
|
|
||||||
|
|
@ -198,13 +198,13 @@ Sessions are stored as JSONL files with a tree structure. Each entry has an `id`
|
||||||
|
|
||||||
### Management
|
### Management
|
||||||
|
|
||||||
Sessions auto-save to `~/.pi/agent/sessions/` organized by working directory.
|
Sessions auto-save to `~/.companion/agent/sessions/` organized by working directory.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi -c # Continue most recent session
|
companion -c # Continue most recent session
|
||||||
pi -r # Browse and select from past sessions
|
companion -r # Browse and select from past sessions
|
||||||
pi --no-session # Ephemeral mode (don't save)
|
companion --no-session # Ephemeral mode (don't save)
|
||||||
pi --session <path> # Use specific session file or ID
|
companion --session <path> # Use specific session file or ID
|
||||||
```
|
```
|
||||||
|
|
||||||
### Branching
|
### Branching
|
||||||
|
|
@ -237,8 +237,8 @@ Use `/settings` to modify common options, or edit JSON files directly:
|
||||||
|
|
||||||
| Location | Scope |
|
| Location | Scope |
|
||||||
| --------------------------- | -------------------------- |
|
| --------------------------- | -------------------------- |
|
||||||
| `~/.pi/agent/settings.json` | Global (all projects) |
|
| `~/.companion/agent/settings.json` | Global (all projects) |
|
||||||
| `.pi/settings.json` | Project (overrides global) |
|
| `.companion/settings.json` | Project (overrides global) |
|
||||||
|
|
||||||
See [docs/settings.md](docs/settings.md) for all options.
|
See [docs/settings.md](docs/settings.md) for all options.
|
||||||
|
|
||||||
|
|
@ -246,9 +246,9 @@ See [docs/settings.md](docs/settings.md) for all options.
|
||||||
|
|
||||||
## Context Files
|
## Context Files
|
||||||
|
|
||||||
Pi loads `AGENTS.md` (or `CLAUDE.md`) at startup from:
|
Companion loads `AGENTS.md` (or `CLAUDE.md`) at startup from:
|
||||||
|
|
||||||
- `~/.pi/agent/AGENTS.md` (global)
|
- `~/.companion/agent/AGENTS.md` (global)
|
||||||
- Parent directories (walking up from cwd)
|
- Parent directories (walking up from cwd)
|
||||||
- Current directory
|
- Current directory
|
||||||
|
|
||||||
|
|
@ -256,7 +256,7 @@ Use for project instructions, conventions, common commands. All matching files a
|
||||||
|
|
||||||
### System Prompt
|
### System Prompt
|
||||||
|
|
||||||
Replace the default system prompt with `.pi/SYSTEM.md` (project) or `~/.pi/agent/SYSTEM.md` (global). Append without replacing via `APPEND_SYSTEM.md`.
|
Replace the default system prompt with `.companion/SYSTEM.md` (project) or `~/.companion/agent/SYSTEM.md` (global). Append without replacing via `APPEND_SYSTEM.md`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -267,20 +267,20 @@ Replace the default system prompt with `.pi/SYSTEM.md` (project) or `~/.pi/agent
|
||||||
Reusable prompts as Markdown files. Type `/name` to expand.
|
Reusable prompts as Markdown files. Type `/name` to expand.
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
<!-- ~/.pi/agent/prompts/review.md -->
|
<!-- ~/.companion/agent/prompts/review.md -->
|
||||||
|
|
||||||
Review this code for bugs, security issues, and performance problems.
|
Review this code for bugs, security issues, and performance problems.
|
||||||
Focus on: {{focus}}
|
Focus on: {{focus}}
|
||||||
```
|
```
|
||||||
|
|
||||||
Place in `~/.pi/agent/prompts/`, `.pi/prompts/`, or a [pi package](#pi-packages) to share with others. See [docs/prompt-templates.md](docs/prompt-templates.md).
|
Place in `~/.companion/agent/prompts/`, `.companion/prompts/`, or a [companion package](#companion-packages) to share with others. See [docs/prompt-templates.md](docs/prompt-templates.md).
|
||||||
|
|
||||||
### Skills
|
### Skills
|
||||||
|
|
||||||
On-demand capability packages following the [Agent Skills standard](https://agentskills.io). Invoke via `/skill:name` or let the agent load them automatically.
|
On-demand capability packages following the [Agent Skills standard](https://agentskills.io). Invoke via `/skill:name` or let the agent load them automatically.
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
<!-- ~/.pi/agent/skills/my-skill/SKILL.md -->
|
<!-- ~/.companion/agent/skills/my-skill/SKILL.md -->
|
||||||
|
|
||||||
# My Skill
|
# My Skill
|
||||||
|
|
||||||
|
|
@ -292,19 +292,19 @@ Use this skill when the user asks about X.
|
||||||
2. Then that
|
2. Then that
|
||||||
```
|
```
|
||||||
|
|
||||||
Place in `~/.pi/agent/skills/`, `~/.agents/skills/`, `.pi/skills/`, or `.agents/skills/` (from `cwd` up through parent directories) or a [pi package](#pi-packages) to share with others. See [docs/skills.md](docs/skills.md).
|
Place in `~/.companion/agent/skills/`, `~/.agents/skills/`, `.companion/skills/`, or `.agents/skills/` (from `cwd` up through parent directories) or a [companion package](#companion-packages) to share with others. See [docs/skills.md](docs/skills.md).
|
||||||
|
|
||||||
### Extensions
|
### Extensions
|
||||||
|
|
||||||
<p align="center"><img src="docs/images/doom-extension.png" alt="Doom Extension" width="600"></p>
|
<p align="center"><img src="docs/images/doom-extension.png" alt="Doom Extension" width="600"></p>
|
||||||
|
|
||||||
TypeScript modules that extend pi with custom tools, commands, keyboard shortcuts, event handlers, and UI components.
|
TypeScript modules that extend companion with custom tools, commands, keyboard shortcuts, event handlers, and UI components.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export default function (pi: ExtensionAPI) {
|
export default function (companion: ExtensionAPI) {
|
||||||
pi.registerTool({ name: "deploy", ... });
|
companion.registerTool({ name: "deploy", ... });
|
||||||
pi.registerCommand("stats", { ... });
|
companion.registerCommand("stats", { ... });
|
||||||
pi.on("tool_call", async (event, ctx) => { ... });
|
companion.on("tool_call", async (event, ctx) => { ... });
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -319,50 +319,50 @@ export default function (pi: ExtensionAPI) {
|
||||||
- Git checkpointing and auto-commit
|
- Git checkpointing and auto-commit
|
||||||
- SSH and sandbox execution
|
- SSH and sandbox execution
|
||||||
- MCP server integration
|
- MCP server integration
|
||||||
- Make pi look like Claude Code
|
- Make companion look like Claude Code
|
||||||
- Games while waiting (yes, Doom runs)
|
- Games while waiting (yes, Doom runs)
|
||||||
- ...anything you can dream up
|
- ...anything you can dream up
|
||||||
|
|
||||||
Place in `~/.pi/agent/extensions/`, `.pi/extensions/`, or a [pi package](#pi-packages) to share with others. See [docs/extensions.md](docs/extensions.md).
|
Place in `~/.companion/agent/extensions/`, `.companion/extensions/`, or a [companion package](#companion-packages) to share with others. See [docs/extensions.md](docs/extensions.md).
|
||||||
|
|
||||||
### Themes
|
### Themes
|
||||||
|
|
||||||
Built-in: `dark`, `light`. Themes hot-reload: modify the active theme file and pi immediately applies changes.
|
Built-in: `dark`, `light`. Themes hot-reload: modify the active theme file and companion immediately applies changes.
|
||||||
|
|
||||||
Place in `~/.pi/agent/themes/`, `.pi/themes/`, or a [pi package](#pi-packages) to share with others. See [docs/themes.md](docs/themes.md).
|
Place in `~/.companion/agent/themes/`, `.companion/themes/`, or a [companion package](#companion-packages) to share with others. See [docs/themes.md](docs/themes.md).
|
||||||
|
|
||||||
### Pi Packages
|
### Companion Packages
|
||||||
|
|
||||||
Bundle and share extensions, skills, prompts, and themes via npm or git. Find packages on [npmjs.com](https://www.npmjs.com/search?q=keywords%3Api-package) or [Discord](https://discord.com/channels/1456806362351669492/1457744485428629628).
|
Bundle and share extensions, skills, prompts, and themes via npm or git. Find packages on [npmjs.com](https://www.npmjs.com/search?q=keywords%3Acompanion-package) or [Discord](https://discord.com/channels/1456806362351669492/1457744485428629628).
|
||||||
|
|
||||||
> **Security:** Pi packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
> **Security:** Companion packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi install npm:@foo/pi-tools
|
companion install npm:@foo/companion-tools
|
||||||
pi install npm:@foo/pi-tools@1.2.3 # pinned version
|
companion install npm:@foo/companion-tools@1.2.3 # pinned version
|
||||||
pi install git:github.com/user/repo
|
companion install git:github.com/user/repo
|
||||||
pi install git:github.com/user/repo@v1 # tag or commit
|
companion install git:github.com/user/repo@v1 # tag or commit
|
||||||
pi install git:git@github.com:user/repo
|
companion install git:git@github.com:user/repo
|
||||||
pi install git:git@github.com:user/repo@v1 # tag or commit
|
companion install git:git@github.com:user/repo@v1 # tag or commit
|
||||||
pi install https://github.com/user/repo
|
companion install https://github.com/user/repo
|
||||||
pi install https://github.com/user/repo@v1 # tag or commit
|
companion install https://github.com/user/repo@v1 # tag or commit
|
||||||
pi install ssh://git@github.com/user/repo
|
companion install ssh://git@github.com/user/repo
|
||||||
pi install ssh://git@github.com/user/repo@v1 # tag or commit
|
companion install ssh://git@github.com/user/repo@v1 # tag or commit
|
||||||
pi remove npm:@foo/pi-tools
|
companion remove npm:@foo/companion-tools
|
||||||
pi list
|
companion list
|
||||||
pi update # skips pinned packages
|
companion update # skips pinned packages
|
||||||
pi config # enable/disable extensions, skills, prompts, themes
|
companion config # enable/disable extensions, skills, prompts, themes
|
||||||
```
|
```
|
||||||
|
|
||||||
Packages install to `~/.pi/agent/git/` (git) or global npm. Use `-l` for project-local installs (`.pi/git/`, `.pi/npm/`).
|
Packages install to `~/.companion/agent/git/` (git) or global npm. Use `-l` for project-local installs (`.companion/git/`, `.companion/npm/`).
|
||||||
|
|
||||||
Create a package by adding a `pi` key to `package.json`:
|
Create a package by adding a `companion` key to `package.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "my-pi-package",
|
"name": "my-companion-package",
|
||||||
"keywords": ["pi-package"],
|
"keywords": ["companion-package"],
|
||||||
"pi": {
|
"companion": {
|
||||||
"extensions": ["./extensions"],
|
"extensions": ["./extensions"],
|
||||||
"skills": ["./skills"],
|
"skills": ["./skills"],
|
||||||
"prompts": ["./prompts"],
|
"prompts": ["./prompts"],
|
||||||
|
|
@ -371,7 +371,7 @@ Create a package by adding a `pi` key to `package.json`:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Without a `pi` manifest, pi auto-discovers from conventional directories (`extensions/`, `skills/`, `prompts/`, `themes/`).
|
Without a `companion` manifest, companion auto-discovers from conventional directories (`extensions/`, `skills/`, `prompts/`, `themes/`).
|
||||||
|
|
||||||
See [docs/packages.md](docs/packages.md).
|
See [docs/packages.md](docs/packages.md).
|
||||||
|
|
||||||
|
|
@ -387,7 +387,7 @@ import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
ModelRegistry,
|
ModelRegistry,
|
||||||
SessionManager,
|
SessionManager,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const { session } = await createAgentSession({
|
const { session } = await createAgentSession({
|
||||||
sessionManager: SessionManager.inMemory(),
|
sessionManager: SessionManager.inMemory(),
|
||||||
|
|
@ -405,7 +405,7 @@ See [docs/sdk.md](docs/sdk.md).
|
||||||
For non-Node.js integrations, use RPC mode over stdin/stdout:
|
For non-Node.js integrations, use RPC mode over stdin/stdout:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi --mode rpc
|
companion --mode rpc
|
||||||
```
|
```
|
||||||
|
|
||||||
See [docs/rpc.md](docs/rpc.md) for the protocol.
|
See [docs/rpc.md](docs/rpc.md) for the protocol.
|
||||||
|
|
@ -414,11 +414,11 @@ See [docs/rpc.md](docs/rpc.md) for the protocol.
|
||||||
|
|
||||||
## Philosophy
|
## Philosophy
|
||||||
|
|
||||||
Pi is aggressively extensible so it doesn't have to dictate your workflow. Features that other tools bake in can be built with [extensions](#extensions), [skills](#skills), or installed from third-party [pi packages](#pi-packages). This keeps the core minimal while letting you shape pi to fit how you work.
|
Companion is aggressively extensible so it doesn't have to dictate your workflow. Features that other tools bake in can be built with [extensions](#extensions), [skills](#skills), or installed from third-party [companion packages](#companion-packages). This keeps the core minimal while letting you shape companion to fit how you work.
|
||||||
|
|
||||||
**No MCP.** Build CLI tools with READMEs (see [Skills](#skills)), or build an extension that adds MCP support. [Why?](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)
|
**No MCP.** Build CLI tools with READMEs (see [Skills](#skills)), or build an extension that adds MCP support. [Why?](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)
|
||||||
|
|
||||||
**No sub-agents.** There's many ways to do this. Spawn pi instances via tmux, or build your own with [extensions](#extensions), or install a package that does it your way.
|
**No sub-agents.** There's many ways to do this. Spawn companion instances via tmux, or build your own with [extensions](#extensions), or install a package that does it your way.
|
||||||
|
|
||||||
**No permission popups.** Run in a container, or build your own confirmation flow with [extensions](#extensions) inline with your environment and security requirements.
|
**No permission popups.** Run in a container, or build your own confirmation flow with [extensions](#extensions) inline with your environment and security requirements.
|
||||||
|
|
||||||
|
|
@ -428,24 +428,24 @@ Pi is aggressively extensible so it doesn't have to dictate your workflow. Featu
|
||||||
|
|
||||||
**No background bash.** Use tmux. Full observability, direct interaction.
|
**No background bash.** Use tmux. Full observability, direct interaction.
|
||||||
|
|
||||||
Read the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/) for the full rationale.
|
Read the [blog post](https://mariozechner.at/posts/2025-11-30-companion-coding-agent/) for the full rationale.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## CLI Reference
|
## CLI Reference
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi [options] [@files...] [messages...]
|
companion [options] [@files...] [messages...]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Package Commands
|
### Package Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi install <source> [-l] # Install package, -l for project-local
|
companion install <source> [-l] # Install package, -l for project-local
|
||||||
pi remove <source> [-l] # Remove package
|
companion remove <source> [-l] # Remove package
|
||||||
pi update [source] # Update packages (skips pinned)
|
companion update [source] # Update packages (skips pinned)
|
||||||
pi list # List installed packages
|
companion list # List installed packages
|
||||||
pi config # Enable/disable package resources
|
companion config # Enable/disable package resources
|
||||||
```
|
```
|
||||||
|
|
||||||
### Modes
|
### Modes
|
||||||
|
|
@ -519,47 +519,47 @@ Combine `--no-*` with explicit flags to load exactly what you need, ignoring set
|
||||||
Prefix files with `@` to include in the message:
|
Prefix files with `@` to include in the message:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi @prompt.md "Answer this"
|
companion @prompt.md "Answer this"
|
||||||
pi -p @screenshot.png "What's in this image?"
|
companion -p @screenshot.png "What's in this image?"
|
||||||
pi @code.ts @test.ts "Review these files"
|
companion @code.ts @test.ts "Review these files"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Interactive with initial prompt
|
# Interactive with initial prompt
|
||||||
pi "List all .ts files in src/"
|
companion "List all .ts files in src/"
|
||||||
|
|
||||||
# Non-interactive
|
# Non-interactive
|
||||||
pi -p "Summarize this codebase"
|
companion -p "Summarize this codebase"
|
||||||
|
|
||||||
# Different model
|
# Different model
|
||||||
pi --provider openai --model gpt-4o "Help me refactor"
|
companion --provider openai --model gpt-4o "Help me refactor"
|
||||||
|
|
||||||
# Model with provider prefix (no --provider needed)
|
# Model with provider prefix (no --provider needed)
|
||||||
pi --model openai/gpt-4o "Help me refactor"
|
companion --model openai/gpt-4o "Help me refactor"
|
||||||
|
|
||||||
# Model with thinking level shorthand
|
# Model with thinking level shorthand
|
||||||
pi --model sonnet:high "Solve this complex problem"
|
companion --model sonnet:high "Solve this complex problem"
|
||||||
|
|
||||||
# Limit model cycling
|
# Limit model cycling
|
||||||
pi --models "claude-*,gpt-4o"
|
companion --models "claude-*,gpt-4o"
|
||||||
|
|
||||||
# Read-only mode
|
# Read-only mode
|
||||||
pi --tools read,grep,find,ls -p "Review the code"
|
companion --tools read,grep,find,ls -p "Review the code"
|
||||||
|
|
||||||
# High thinking level
|
# High thinking level
|
||||||
pi --thinking high "Solve this complex problem"
|
companion --thinking high "Solve this complex problem"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
| Variable | Description |
|
| Variable | Description |
|
||||||
| ----------------------- | ---------------------------------------------------------------------------------- |
|
| ----------------------- | ---------------------------------------------------------------------------------- |
|
||||||
| `PI_CODING_AGENT_DIR` | Override config directory (default: `~/.pi/agent`) |
|
| `COMPANION_CODING_AGENT_DIR` | Override config directory (default: `~/.companion/agent`) |
|
||||||
| `PI_PACKAGE_DIR` | Override package directory (useful for Nix/Guix where store paths tokenize poorly) |
|
| `COMPANION_PACKAGE_DIR` | Override package directory (useful for Nix/Guix where store paths tokenize poorly) |
|
||||||
| `PI_SKIP_VERSION_CHECK` | Skip version check at startup |
|
| `COMPANION_SKIP_VERSION_CHECK` | Skip version check at startup |
|
||||||
| `PI_CACHE_RETENTION` | Set to `long` for extended prompt cache (Anthropic: 1h, OpenAI: 24h) |
|
| `COMPANION_CACHE_RETENTION` | Set to `long` for extended prompt cache (Anthropic: 1h, OpenAI: 24h) |
|
||||||
| `VISUAL`, `EDITOR` | External editor for Ctrl+G |
|
| `VISUAL`, `EDITOR` | External editor for Ctrl+G |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -576,6 +576,6 @@ MIT
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [@mariozechner/pi-ai](https://www.npmjs.com/package/@mariozechner/pi-ai): Core LLM toolkit
|
- [@mariozechner/companion-ai](https://www.npmjs.com/package/@mariozechner/companion-ai): Core LLM toolkit
|
||||||
- [@mariozechner/pi-agent](https://www.npmjs.com/package/@mariozechner/pi-agent): Agent framework
|
- [@mariozechner/companion-agent](https://www.npmjs.com/package/@mariozechner/companion-agent): Agent framework
|
||||||
- [@mariozechner/pi-tui](https://www.npmjs.com/package/@mariozechner/pi-tui): Terminal UI components
|
- [@mariozechner/companion-tui](https://www.npmjs.com/package/@mariozechner/companion-tui): Terminal UI components
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,20 @@
|
||||||
# Compaction & Branch Summarization
|
# Compaction & Branch Summarization
|
||||||
|
|
||||||
LLMs have limited context windows. When conversations grow too long, pi uses compaction to summarize older content while preserving recent work. This page covers both auto-compaction and branch summarization.
|
LLMs have limited context windows. When conversations grow too long, companion uses compaction to summarize older content while preserving recent work. This page covers both auto-compaction and branch summarization.
|
||||||
|
|
||||||
**Source files** ([pi-mono](https://github.com/badlogic/pi-mono)):
|
**Source files** ([companion-mono](https://github.com/badlogic/companion-mono)):
|
||||||
|
|
||||||
- [`packages/coding-agent/src/core/compaction/compaction.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) - Auto-compaction logic
|
- [`packages/coding-agent/src/core/compaction/compaction.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) - Auto-compaction logic
|
||||||
- [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Branch summarization
|
- [`packages/coding-agent/src/core/compaction/branch-summarization.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) - Branch summarization
|
||||||
- [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Shared utilities (file tracking, serialization)
|
- [`packages/coding-agent/src/core/compaction/utils.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts) - Shared utilities (file tracking, serialization)
|
||||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Entry types (`CompactionEntry`, `BranchSummaryEntry`)
|
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Entry types (`CompactionEntry`, `BranchSummaryEntry`)
|
||||||
- [`packages/coding-agent/src/core/extensions/types.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) - Extension event types
|
- [`packages/coding-agent/src/core/extensions/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) - Extension event types
|
||||||
|
|
||||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/pi-coding-agent/dist/`.
|
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/companion-coding-agent/dist/`.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Pi has two summarization mechanisms:
|
Companion has two summarization mechanisms:
|
||||||
|
|
||||||
| Mechanism | Trigger | Purpose |
|
| Mechanism | Trigger | Purpose |
|
||||||
| -------------------- | ---------------------------------------- | ----------------------------------------- |
|
| -------------------- | ---------------------------------------- | ----------------------------------------- |
|
||||||
|
|
@ -33,13 +33,13 @@ Auto-compaction triggers when:
|
||||||
contextTokens > contextWindow - reserveTokens
|
contextTokens > contextWindow - reserveTokens
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, `reserveTokens` is 16384 tokens (configurable in `~/.pi/agent/settings.json` or `<project-dir>/.pi/settings.json`). This leaves room for the LLM's response.
|
By default, `reserveTokens` is 16384 tokens (configurable in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`). This leaves room for the LLM's response.
|
||||||
|
|
||||||
You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary.
|
You can also trigger manually with `/compact [instructions]`, where optional instructions focus the summary.
|
||||||
|
|
||||||
### How It Works
|
### How It Works
|
||||||
|
|
||||||
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.pi/agent/settings.json` or `<project-dir>/.pi/settings.json`) is reached
|
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`) is reached
|
||||||
2. **Extract messages**: Collect messages from previous compaction (or start) up to cut point
|
2. **Extract messages**: Collect messages from previous compaction (or start) up to cut point
|
||||||
3. **Generate summary**: Call LLM to summarize with structured format
|
3. **Generate summary**: Call LLM to summarize with structured format
|
||||||
4. **Append entry**: Save `CompactionEntry` with summary and `firstKeptEntryId`
|
4. **Append entry**: Save `CompactionEntry` with summary and `firstKeptEntryId`
|
||||||
|
|
@ -101,7 +101,7 @@ Split turn (one huge turn exceeds budget):
|
||||||
turnPrefixMessages = [usr, ass, tool, ass, tool, tool]
|
turnPrefixMessages = [usr, ass, tool, ass, tool, tool]
|
||||||
```
|
```
|
||||||
|
|
||||||
For split turns, pi generates two summaries and merges them:
|
For split turns, companion generates two summaries and merges them:
|
||||||
|
|
||||||
1. **History summary**: Previous context (if any)
|
1. **History summary**: Previous context (if any)
|
||||||
2. **Turn prefix summary**: The early part of the split turn
|
2. **Turn prefix summary**: The early part of the split turn
|
||||||
|
|
@ -119,7 +119,7 @@ Never cut at tool results (they must stay with their tool call).
|
||||||
|
|
||||||
### CompactionEntry Structure
|
### CompactionEntry Structure
|
||||||
|
|
||||||
Defined in [`session-manager.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
Defined in [`session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface CompactionEntry<T = unknown> {
|
interface CompactionEntry<T = unknown> {
|
||||||
|
|
@ -143,13 +143,13 @@ interface CompactionDetails {
|
||||||
|
|
||||||
Extensions can store any JSON-serializable data in `details`. The default compaction tracks file operations, but custom extension implementations can use their own structure.
|
Extensions can store any JSON-serializable data in `details`. The default compaction tracks file operations, but custom extension implementations can use their own structure.
|
||||||
|
|
||||||
See [`prepareCompaction()`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) and [`compact()`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) for the implementation.
|
See [`prepareCompaction()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) and [`compact()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/compaction.ts) for the implementation.
|
||||||
|
|
||||||
## Branch Summarization
|
## Branch Summarization
|
||||||
|
|
||||||
### When It Triggers
|
### When It Triggers
|
||||||
|
|
||||||
When you use `/tree` to navigate to a different branch, pi offers to summarize the work you're leaving. This injects context from the left branch into the new branch.
|
When you use `/tree` to navigate to a different branch, companion offers to summarize the work you're leaving. This injects context from the left branch into the new branch.
|
||||||
|
|
||||||
### How It Works
|
### How It Works
|
||||||
|
|
||||||
|
|
@ -178,7 +178,7 @@ After navigation with summary:
|
||||||
|
|
||||||
### Cumulative File Tracking
|
### Cumulative File Tracking
|
||||||
|
|
||||||
Both compaction and branch summarization track files cumulatively. When generating a summary, pi extracts file operations from:
|
Both compaction and branch summarization track files cumulatively. When generating a summary, companion extracts file operations from:
|
||||||
|
|
||||||
- Tool calls in the messages being summarized
|
- Tool calls in the messages being summarized
|
||||||
- Previous compaction or branch summary `details` (if any)
|
- Previous compaction or branch summary `details` (if any)
|
||||||
|
|
@ -187,7 +187,7 @@ This means file tracking accumulates across multiple compactions or nested branc
|
||||||
|
|
||||||
### BranchSummaryEntry Structure
|
### BranchSummaryEntry Structure
|
||||||
|
|
||||||
Defined in [`session-manager.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
Defined in [`session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts):
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface BranchSummaryEntry<T = unknown> {
|
interface BranchSummaryEntry<T = unknown> {
|
||||||
|
|
@ -210,7 +210,7 @@ interface BranchSummaryDetails {
|
||||||
|
|
||||||
Same as compaction, extensions can store custom data in `details`.
|
Same as compaction, extensions can store custom data in `details`.
|
||||||
|
|
||||||
See [`collectEntriesForBranchSummary()`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), [`prepareBranchEntries()`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), and [`generateBranchSummary()`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) for the implementation.
|
See [`collectEntriesForBranchSummary()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), [`prepareBranchEntries()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts), and [`generateBranchSummary()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/branch-summarization.ts) for the implementation.
|
||||||
|
|
||||||
## Summary Format
|
## Summary Format
|
||||||
|
|
||||||
|
|
@ -263,7 +263,7 @@ path/to/changed.ts
|
||||||
|
|
||||||
### Message Serialization
|
### Message Serialization
|
||||||
|
|
||||||
Before summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
|
Before summarization, messages are serialized to text via [`serializeConversation()`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/compaction/utils.ts):
|
||||||
|
|
||||||
```
|
```
|
||||||
[User]: What they said
|
[User]: What they said
|
||||||
|
|
@ -277,14 +277,14 @@ This prevents the model from treating it as a conversation to continue.
|
||||||
|
|
||||||
## Custom Summarization via Extensions
|
## Custom Summarization via Extensions
|
||||||
|
|
||||||
Extensions can intercept and customize both compaction and branch summarization. See [`extensions/types.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) for event type definitions.
|
Extensions can intercept and customize both compaction and branch summarization. See [`extensions/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/extensions/types.ts) for event type definitions.
|
||||||
|
|
||||||
### session_before_compact
|
### session_before_compact
|
||||||
|
|
||||||
Fired before auto-compaction or `/compact`. Can cancel or provide custom summary. See `SessionBeforeCompactEvent` and `CompactionPreparation` in the types file.
|
Fired before auto-compaction or `/compact`. Can cancel or provide custom summary. See `SessionBeforeCompactEvent` and `CompactionPreparation` in the types file.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
pi.on("session_before_compact", async (event, ctx) => {
|
companion.on("session_before_compact", async (event, ctx) => {
|
||||||
const { preparation, branchEntries, customInstructions, signal } = event;
|
const { preparation, branchEntries, customInstructions, signal } = event;
|
||||||
|
|
||||||
// preparation.messagesToSummarize - messages to summarize
|
// preparation.messagesToSummarize - messages to summarize
|
||||||
|
|
@ -323,9 +323,9 @@ To generate a summary with your own model, convert messages to text using `seria
|
||||||
import {
|
import {
|
||||||
convertToLlm,
|
convertToLlm,
|
||||||
serializeConversation,
|
serializeConversation,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
pi.on("session_before_compact", async (event, ctx) => {
|
companion.on("session_before_compact", async (event, ctx) => {
|
||||||
const { preparation } = event;
|
const { preparation } = event;
|
||||||
|
|
||||||
// Convert AgentMessage[] to Message[], then serialize to text
|
// Convert AgentMessage[] to Message[], then serialize to text
|
||||||
|
|
@ -359,7 +359,7 @@ See [custom-compaction.ts](../examples/extensions/custom-compaction.ts) for a co
|
||||||
Fired before `/tree` navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
|
Fired before `/tree` navigation. Always fires regardless of whether user chose to summarize. Can cancel navigation or provide custom summary.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
pi.on("session_before_tree", async (event, ctx) => {
|
companion.on("session_before_tree", async (event, ctx) => {
|
||||||
const { preparation, signal } = event;
|
const { preparation, signal } = event;
|
||||||
|
|
||||||
// preparation.targetId - where we're navigating to
|
// preparation.targetId - where we're navigating to
|
||||||
|
|
@ -389,7 +389,7 @@ See `SessionBeforeTreeEvent` and `TreePreparation` in the types file.
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
Configure compaction in `~/.pi/agent/settings.json` or `<project-dir>/.pi/settings.json`:
|
Configure compaction in `~/.companion/agent/settings.json` or `<project-dir>/.companion/settings.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Custom Providers
|
# Custom Providers
|
||||||
|
|
||||||
Extensions can register custom model providers via `pi.registerProvider()`. This enables:
|
Extensions can register custom model providers via `companion.registerProvider()`. This enables:
|
||||||
|
|
||||||
- **Proxies** - Route requests through corporate proxies or API gateways
|
- **Proxies** - Route requests through corporate proxies or API gateways
|
||||||
- **Custom endpoints** - Use self-hosted or private model deployments
|
- **Custom endpoints** - Use self-hosted or private model deployments
|
||||||
|
|
@ -22,16 +22,16 @@ Extensions can register custom model providers via `pi.registerProvider()`. This
|
||||||
## Quick Reference
|
## Quick Reference
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
import type { ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
export default function (pi: ExtensionAPI) {
|
export default function (companion: ExtensionAPI) {
|
||||||
// Override baseUrl for existing provider
|
// Override baseUrl for existing provider
|
||||||
pi.registerProvider("anthropic", {
|
companion.registerProvider("anthropic", {
|
||||||
baseUrl: "https://proxy.example.com",
|
baseUrl: "https://proxy.example.com",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register new provider with models
|
// Register new provider with models
|
||||||
pi.registerProvider("my-provider", {
|
companion.registerProvider("my-provider", {
|
||||||
baseUrl: "https://api.example.com",
|
baseUrl: "https://api.example.com",
|
||||||
apiKey: "MY_API_KEY",
|
apiKey: "MY_API_KEY",
|
||||||
api: "openai-completions",
|
api: "openai-completions",
|
||||||
|
|
@ -56,19 +56,19 @@ The simplest use case: redirect an existing provider through a proxy.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// All Anthropic requests now go through your proxy
|
// All Anthropic requests now go through your proxy
|
||||||
pi.registerProvider("anthropic", {
|
companion.registerProvider("anthropic", {
|
||||||
baseUrl: "https://proxy.example.com",
|
baseUrl: "https://proxy.example.com",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add custom headers to OpenAI requests
|
// Add custom headers to OpenAI requests
|
||||||
pi.registerProvider("openai", {
|
companion.registerProvider("openai", {
|
||||||
headers: {
|
headers: {
|
||||||
"X-Custom-Header": "value",
|
"X-Custom-Header": "value",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Both baseUrl and headers
|
// Both baseUrl and headers
|
||||||
pi.registerProvider("google", {
|
companion.registerProvider("google", {
|
||||||
baseUrl: "https://ai-gateway.corp.com/google",
|
baseUrl: "https://ai-gateway.corp.com/google",
|
||||||
headers: {
|
headers: {
|
||||||
"X-Corp-Auth": "CORP_AUTH_TOKEN", // env var or literal
|
"X-Corp-Auth": "CORP_AUTH_TOKEN", // env var or literal
|
||||||
|
|
@ -83,7 +83,7 @@ When only `baseUrl` and/or `headers` are provided (no `models`), all existing mo
|
||||||
To add a completely new provider, specify `models` along with the required configuration.
|
To add a completely new provider, specify `models` along with the required configuration.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
pi.registerProvider("my-llm", {
|
companion.registerProvider("my-llm", {
|
||||||
baseUrl: "https://api.my-llm.com/v1",
|
baseUrl: "https://api.my-llm.com/v1",
|
||||||
apiKey: "MY_LLM_API_KEY", // env var name or literal value
|
apiKey: "MY_LLM_API_KEY", // env var name or literal value
|
||||||
api: "openai-completions", // which streaming API to use
|
api: "openai-completions", // which streaming API to use
|
||||||
|
|
@ -110,11 +110,11 @@ When `models` is provided, it **replaces** all existing models for that provider
|
||||||
|
|
||||||
## Unregister Provider
|
## Unregister Provider
|
||||||
|
|
||||||
Use `pi.unregisterProvider(name)` to remove a provider that was previously registered via `pi.registerProvider(name, ...)`:
|
Use `companion.unregisterProvider(name)` to remove a provider that was previously registered via `companion.registerProvider(name, ...)`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Register
|
// Register
|
||||||
pi.registerProvider("my-llm", {
|
companion.registerProvider("my-llm", {
|
||||||
baseUrl: "https://api.my-llm.com/v1",
|
baseUrl: "https://api.my-llm.com/v1",
|
||||||
apiKey: "MY_LLM_API_KEY",
|
apiKey: "MY_LLM_API_KEY",
|
||||||
api: "openai-completions",
|
api: "openai-completions",
|
||||||
|
|
@ -132,7 +132,7 @@ pi.registerProvider("my-llm", {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Later, remove it
|
// Later, remove it
|
||||||
pi.unregisterProvider("my-llm");
|
companion.unregisterProvider("my-llm");
|
||||||
```
|
```
|
||||||
|
|
||||||
Unregistering removes that provider's dynamic models, API key fallback, OAuth provider registration, and custom stream handler registrations. Any built-in models or provider behavior that were overridden are restored.
|
Unregistering removes that provider's dynamic models, API key fallback, OAuth provider registration, and custom stream handler registrations. Any built-in models or provider behavior that were overridden are restored.
|
||||||
|
|
@ -167,7 +167,7 @@ models: [
|
||||||
supportsDeveloperRole: false, // use "system" instead of "developer"
|
supportsDeveloperRole: false, // use "system" instead of "developer"
|
||||||
supportsReasoningEffort: true,
|
supportsReasoningEffort: true,
|
||||||
reasoningEffortMap: {
|
reasoningEffortMap: {
|
||||||
// map pi-ai levels to provider values
|
// map companion-ai levels to provider values
|
||||||
minimal: "default",
|
minimal: "default",
|
||||||
low: "default",
|
low: "default",
|
||||||
medium: "default",
|
medium: "default",
|
||||||
|
|
@ -191,7 +191,7 @@ models: [
|
||||||
If your provider expects `Authorization: Bearer <key>` but doesn't use a standard API, set `authHeader: true`:
|
If your provider expects `Authorization: Bearer <key>` but doesn't use a standard API, set `authHeader: true`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
pi.registerProvider("custom-api", {
|
companion.registerProvider("custom-api", {
|
||||||
baseUrl: "https://api.example.com",
|
baseUrl: "https://api.example.com",
|
||||||
apiKey: "MY_API_KEY",
|
apiKey: "MY_API_KEY",
|
||||||
authHeader: true, // adds Authorization: Bearer header
|
authHeader: true, // adds Authorization: Bearer header
|
||||||
|
|
@ -205,9 +205,9 @@ pi.registerProvider("custom-api", {
|
||||||
Add OAuth/SSO authentication that integrates with `/login`:
|
Add OAuth/SSO authentication that integrates with `/login`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { OAuthCredentials, OAuthLoginCallbacks } from "@mariozechner/pi-ai";
|
import type { OAuthCredentials, OAuthLoginCallbacks } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
pi.registerProvider("corporate-ai", {
|
companion.registerProvider("corporate-ai", {
|
||||||
baseUrl: "https://ai.corp.com/v1",
|
baseUrl: "https://ai.corp.com/v1",
|
||||||
api: "openai-responses",
|
api: "openai-responses",
|
||||||
models: [...],
|
models: [...],
|
||||||
|
|
@ -283,7 +283,7 @@ interface OAuthLoginCallbacks {
|
||||||
|
|
||||||
### OAuthCredentials
|
### OAuthCredentials
|
||||||
|
|
||||||
Credentials are persisted in `~/.pi/agent/auth.json`:
|
Credentials are persisted in `~/.companion/agent/auth.json`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface OAuthCredentials {
|
interface OAuthCredentials {
|
||||||
|
|
@ -299,12 +299,12 @@ For providers with non-standard APIs, implement `streamSimple`. Study the existi
|
||||||
|
|
||||||
**Reference implementations:**
|
**Reference implementations:**
|
||||||
|
|
||||||
- [anthropic.ts](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/providers/anthropic.ts) - Anthropic Messages API
|
- [anthropic.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/anthropic.ts) - Anthropic Messages API
|
||||||
- [mistral.ts](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/providers/mistral.ts) - Mistral Conversations API
|
- [mistral.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/mistral.ts) - Mistral Conversations API
|
||||||
- [openai-completions.ts](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/providers/openai-completions.ts) - OpenAI Chat Completions
|
- [openai-completions.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/openai-completions.ts) - OpenAI Chat Completions
|
||||||
- [openai-responses.ts](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/providers/openai-responses.ts) - OpenAI Responses API
|
- [openai-responses.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/openai-responses.ts) - OpenAI Responses API
|
||||||
- [google.ts](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/providers/google.ts) - Google Generative AI
|
- [google.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/google.ts) - Google Generative AI
|
||||||
- [amazon-bedrock.ts](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/providers/amazon-bedrock.ts) - AWS Bedrock
|
- [amazon-bedrock.ts](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/providers/amazon-bedrock.ts) - AWS Bedrock
|
||||||
|
|
||||||
### Stream Pattern
|
### Stream Pattern
|
||||||
|
|
||||||
|
|
@ -319,7 +319,7 @@ import {
|
||||||
type SimpleStreamOptions,
|
type SimpleStreamOptions,
|
||||||
calculateCost,
|
calculateCost,
|
||||||
createAssistantMessageEventStream,
|
createAssistantMessageEventStream,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
function streamMyProvider(
|
function streamMyProvider(
|
||||||
model: Model<any>,
|
model: Model<any>,
|
||||||
|
|
@ -487,7 +487,7 @@ calculateCost(model, output.usage);
|
||||||
Register your stream function:
|
Register your stream function:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
pi.registerProvider("my-provider", {
|
companion.registerProvider("my-provider", {
|
||||||
baseUrl: "https://api.example.com",
|
baseUrl: "https://api.example.com",
|
||||||
apiKey: "MY_API_KEY",
|
apiKey: "MY_API_KEY",
|
||||||
api: "my-custom-api",
|
api: "my-custom-api",
|
||||||
|
|
@ -498,7 +498,7 @@ pi.registerProvider("my-provider", {
|
||||||
|
|
||||||
## Testing Your Implementation
|
## Testing Your Implementation
|
||||||
|
|
||||||
Test your provider against the same test suites used by built-in providers. Copy and adapt these test files from [packages/ai/test/](https://github.com/badlogic/pi-mono/tree/main/packages/ai/test):
|
Test your provider against the same test suites used by built-in providers. Copy and adapt these test files from [packages/ai/test/](https://github.com/badlogic/companion-mono/tree/main/packages/ai/test):
|
||||||
|
|
||||||
| Test | Purpose |
|
| Test | Purpose |
|
||||||
| ---------------------------------- | --------------------------------- |
|
| ---------------------------------- | --------------------------------- |
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ See [AGENTS.md](../../../AGENTS.md) for additional guidelines.
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/badlogic/pi-mono
|
git clone https://github.com/badlogic/companion-mono
|
||||||
cd pi-mono
|
cd companion-mono
|
||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
@ -14,7 +14,7 @@ npm run build
|
||||||
Run from source:
|
Run from source:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./pi-test.sh
|
./companion-test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Forking / Rebranding
|
## Forking / Rebranding
|
||||||
|
|
@ -23,9 +23,9 @@ Configure via `package.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"piConfig": {
|
"companionConfig": {
|
||||||
"name": "pi",
|
"name": "companion",
|
||||||
"configDir": ".pi"
|
"configDir": ".companion"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -46,7 +46,7 @@ Never use `__dirname` directly for package assets.
|
||||||
|
|
||||||
## Debug Command
|
## Debug Command
|
||||||
|
|
||||||
`/debug` (hidden) writes to `~/.pi/agent/pi-debug.log`:
|
`/debug` (hidden) writes to `~/.companion/agent/companion-debug.log`:
|
||||||
|
|
||||||
- Rendered TUI lines with ANSI codes
|
- Rendered TUI lines with ANSI codes
|
||||||
- Last messages sent to the LLM
|
- Last messages sent to the LLM
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,14 +1,14 @@
|
||||||
# JSON Event Stream Mode
|
# JSON Event Stream Mode
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi --mode json "Your prompt"
|
companion --mode json "Your prompt"
|
||||||
```
|
```
|
||||||
|
|
||||||
Outputs all session events as JSON lines to stdout. Useful for integrating pi into other tools or custom UIs.
|
Outputs all session events as JSON lines to stdout. Useful for integrating companion into other tools or custom UIs.
|
||||||
|
|
||||||
## Event Types
|
## Event Types
|
||||||
|
|
||||||
Events are defined in [`AgentSessionEvent`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/agent-session.ts#L102):
|
Events are defined in [`AgentSessionEvent`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/agent-session.ts#L102):
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
type AgentSessionEvent =
|
type AgentSessionEvent =
|
||||||
|
|
@ -36,7 +36,7 @@ type AgentSessionEvent =
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Base events from [`AgentEvent`](https://github.com/badlogic/pi-mono/blob/main/packages/agent/src/types.ts#L179):
|
Base events from [`AgentEvent`](https://github.com/badlogic/companion-mono/blob/main/packages/agent/src/types.ts#L179):
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
type AgentEvent =
|
type AgentEvent =
|
||||||
|
|
@ -83,13 +83,13 @@ type AgentEvent =
|
||||||
|
|
||||||
## Message Types
|
## Message Types
|
||||||
|
|
||||||
Base messages from [`packages/ai/src/types.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/types.ts#L134):
|
Base messages from [`packages/ai/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/types.ts#L134):
|
||||||
|
|
||||||
- `UserMessage` (line 134)
|
- `UserMessage` (line 134)
|
||||||
- `AssistantMessage` (line 140)
|
- `AssistantMessage` (line 140)
|
||||||
- `ToolResultMessage` (line 152)
|
- `ToolResultMessage` (line 152)
|
||||||
|
|
||||||
Extended messages from [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/messages.ts#L29):
|
Extended messages from [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/messages.ts#L29):
|
||||||
|
|
||||||
- `BashExecutionMessage` (line 29)
|
- `BashExecutionMessage` (line 29)
|
||||||
- `CustomMessage` (line 46)
|
- `CustomMessage` (line 46)
|
||||||
|
|
@ -125,5 +125,5 @@ Followed by events as they occur:
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'
|
companion --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Keybindings
|
# Keybindings
|
||||||
|
|
||||||
All keyboard shortcuts can be customized via `~/.pi/agent/keybindings.json`. Each action can be bound to one or more keys.
|
All keyboard shortcuts can be customized via `~/.companion/agent/keybindings.json`. Each action can be bound to one or more keys.
|
||||||
|
|
||||||
## Key Format
|
## Key Format
|
||||||
|
|
||||||
|
|
@ -132,7 +132,7 @@ Modifier combinations: `ctrl+shift+x`, `alt+ctrl+x`, `ctrl+shift+alt+x`, etc.
|
||||||
|
|
||||||
## Custom Configuration
|
## Custom Configuration
|
||||||
|
|
||||||
Create `~/.pi/agent/keybindings.json`:
|
Create `~/.companion/agent/keybindings.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Custom Models
|
# Custom Models
|
||||||
|
|
||||||
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.pi/agent/models.json`.
|
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.companion/agent/models.json`.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
> pi can help you create pi packages. Ask it to bundle your extensions, skills, prompt templates, or themes.
|
> companion can help you create companion packages. Ask it to bundle your extensions, skills, prompt templates, or themes.
|
||||||
|
|
||||||
# Pi Packages
|
# Companion Packages
|
||||||
|
|
||||||
Pi packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under the `pi` key, or use conventional directories.
|
Companion packages bundle extensions, skills, prompt templates, and themes so you can share them through npm or git. A package can declare resources in `package.json` under the `companion` key, or use conventional directories.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Install and Manage](#install-and-manage)
|
- [Install and Manage](#install-and-manage)
|
||||||
- [Package Sources](#package-sources)
|
- [Package Sources](#package-sources)
|
||||||
- [Creating a Pi Package](#creating-a-pi-package)
|
- [Creating a Companion Package](#creating-a-companion-package)
|
||||||
- [Package Structure](#package-structure)
|
- [Package Structure](#package-structure)
|
||||||
- [Dependencies](#dependencies)
|
- [Dependencies](#dependencies)
|
||||||
- [Package Filtering](#package-filtering)
|
- [Package Filtering](#package-filtering)
|
||||||
|
|
@ -17,32 +17,32 @@ Pi packages bundle extensions, skills, prompt templates, and themes so you can s
|
||||||
|
|
||||||
## Install and Manage
|
## Install and Manage
|
||||||
|
|
||||||
> **Security:** Pi packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
> **Security:** Companion packages run with full system access. Extensions execute arbitrary code, and skills can instruct the model to perform any action including running executables. Review source code before installing third-party packages.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi install npm:@foo/bar@1.0.0
|
companion install npm:@foo/bar@1.0.0
|
||||||
pi install git:github.com/user/repo@v1
|
companion install git:github.com/user/repo@v1
|
||||||
pi install https://github.com/user/repo # raw URLs work too
|
companion install https://github.com/user/repo # raw URLs work too
|
||||||
pi install /absolute/path/to/package
|
companion install /absolute/path/to/package
|
||||||
pi install ./relative/path/to/package
|
companion install ./relative/path/to/package
|
||||||
|
|
||||||
pi remove npm:@foo/bar
|
companion remove npm:@foo/bar
|
||||||
pi list # show installed packages from settings
|
companion list # show installed packages from settings
|
||||||
pi update # update all non-pinned packages
|
companion update # update all non-pinned packages
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, `install` and `remove` write to global settings (`~/.pi/agent/settings.json`). Use `-l` to write to project settings (`.pi/settings.json`) instead. Project settings can be shared with your team, and pi installs any missing packages automatically on startup.
|
By default, `install` and `remove` write to global settings (`~/.companion/agent/settings.json`). Use `-l` to write to project settings (`.companion/settings.json`) instead. Project settings can be shared with your team, and companion installs any missing packages automatically on startup.
|
||||||
|
|
||||||
To try a package without installing it, use `--extension` or `-e`. This installs to a temporary directory for the current run only:
|
To try a package without installing it, use `--extension` or `-e`. This installs to a temporary directory for the current run only:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi -e npm:@foo/bar
|
companion -e npm:@foo/bar
|
||||||
pi -e git:github.com/user/repo
|
companion -e git:github.com/user/repo
|
||||||
```
|
```
|
||||||
|
|
||||||
## Package Sources
|
## Package Sources
|
||||||
|
|
||||||
Pi accepts three source types in settings and `pi install`.
|
Companion accepts three source types in settings and `companion install`.
|
||||||
|
|
||||||
### npm
|
### npm
|
||||||
|
|
||||||
|
|
@ -51,9 +51,9 @@ npm:@scope/pkg@1.2.3
|
||||||
npm:pkg
|
npm:pkg
|
||||||
```
|
```
|
||||||
|
|
||||||
- Versioned specs are pinned and skipped by `pi update`.
|
- Versioned specs are pinned and skipped by `companion update`.
|
||||||
- Global installs use `npm install -g`.
|
- Global installs use `npm install -g`.
|
||||||
- Project installs go under `.pi/npm/`.
|
- Project installs go under `.companion/npm/`.
|
||||||
|
|
||||||
### git
|
### git
|
||||||
|
|
||||||
|
|
@ -69,21 +69,21 @@ ssh://git@github.com/user/repo@v1
|
||||||
- HTTPS and SSH URLs are both supported.
|
- HTTPS and SSH URLs are both supported.
|
||||||
- SSH URLs use your configured SSH keys automatically (respects `~/.ssh/config`).
|
- SSH URLs use your configured SSH keys automatically (respects `~/.ssh/config`).
|
||||||
- For non-interactive runs (for example CI), you can set `GIT_TERMINAL_PROMPT=0` to disable credential prompts and set `GIT_SSH_COMMAND` (for example `ssh -o BatchMode=yes -o ConnectTimeout=5`) to fail fast.
|
- For non-interactive runs (for example CI), you can set `GIT_TERMINAL_PROMPT=0` to disable credential prompts and set `GIT_SSH_COMMAND` (for example `ssh -o BatchMode=yes -o ConnectTimeout=5`) to fail fast.
|
||||||
- Refs pin the package and skip `pi update`.
|
- Refs pin the package and skip `companion update`.
|
||||||
- Cloned to `~/.pi/agent/git/<host>/<path>` (global) or `.pi/git/<host>/<path>` (project).
|
- Cloned to `~/.companion/agent/git/<host>/<path>` (global) or `.companion/git/<host>/<path>` (project).
|
||||||
- Runs `npm install` after clone or pull if `package.json` exists.
|
- Runs `npm install` after clone or pull if `package.json` exists.
|
||||||
|
|
||||||
**SSH examples:**
|
**SSH examples:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# git@host:path shorthand (requires git: prefix)
|
# git@host:path shorthand (requires git: prefix)
|
||||||
pi install git:git@github.com:user/repo
|
companion install git:git@github.com:user/repo
|
||||||
|
|
||||||
# ssh:// protocol format
|
# ssh:// protocol format
|
||||||
pi install ssh://git@github.com/user/repo
|
companion install ssh://git@github.com/user/repo
|
||||||
|
|
||||||
# With version ref
|
# With version ref
|
||||||
pi install git:git@github.com:user/repo@v1.0.0
|
companion install git:git@github.com:user/repo@v1.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Local Paths
|
### Local Paths
|
||||||
|
|
@ -93,17 +93,17 @@ pi install git:git@github.com:user/repo@v1.0.0
|
||||||
./relative/path/to/package
|
./relative/path/to/package
|
||||||
```
|
```
|
||||||
|
|
||||||
Local paths point to files or directories on disk and are added to settings without copying. Relative paths are resolved against the settings file they appear in. If the path is a file, it loads as a single extension. If it is a directory, pi loads resources using package rules.
|
Local paths point to files or directories on disk and are added to settings without copying. Relative paths are resolved against the settings file they appear in. If the path is a file, it loads as a single extension. If it is a directory, companion loads resources using package rules.
|
||||||
|
|
||||||
## Creating a Pi Package
|
## Creating a Companion Package
|
||||||
|
|
||||||
Add a `pi` manifest to `package.json` or use conventional directories. Include the `pi-package` keyword for discoverability.
|
Add a `companion` manifest to `package.json` or use conventional directories. Include the `companion-package` keyword for discoverability.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "my-package",
|
"name": "my-package",
|
||||||
"keywords": ["pi-package"],
|
"keywords": ["companion-package"],
|
||||||
"pi": {
|
"companion": {
|
||||||
"extensions": ["./extensions"],
|
"extensions": ["./extensions"],
|
||||||
"skills": ["./skills"],
|
"skills": ["./skills"],
|
||||||
"prompts": ["./prompts"],
|
"prompts": ["./prompts"],
|
||||||
|
|
@ -116,13 +116,13 @@ Paths are relative to the package root. Arrays support glob patterns and `!exclu
|
||||||
|
|
||||||
### Gallery Metadata
|
### Gallery Metadata
|
||||||
|
|
||||||
The [package gallery](https://shittycodingagent.ai/packages) displays packages tagged with `pi-package`. Add `video` or `image` fields to show a preview:
|
The [package gallery](https://shittycodingagent.ai/packages) displays packages tagged with `companion-package`. Add `video` or `image` fields to show a preview:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "my-package",
|
"name": "my-package",
|
||||||
"keywords": ["pi-package"],
|
"keywords": ["companion-package"],
|
||||||
"pi": {
|
"companion": {
|
||||||
"extensions": ["./extensions"],
|
"extensions": ["./extensions"],
|
||||||
"video": "https://example.com/demo.mp4",
|
"video": "https://example.com/demo.mp4",
|
||||||
"image": "https://example.com/screenshot.png"
|
"image": "https://example.com/screenshot.png"
|
||||||
|
|
@ -139,7 +139,7 @@ If both are set, video takes precedence.
|
||||||
|
|
||||||
### Convention Directories
|
### Convention Directories
|
||||||
|
|
||||||
If no `pi` manifest is present, pi auto-discovers resources from these directories:
|
If no `companion` manifest is present, companion auto-discovers resources from these directories:
|
||||||
|
|
||||||
- `extensions/` loads `.ts` and `.js` files
|
- `extensions/` loads `.ts` and `.js` files
|
||||||
- `skills/` recursively finds `SKILL.md` folders and loads top-level `.md` files as skills
|
- `skills/` recursively finds `SKILL.md` folders and loads top-level `.md` files as skills
|
||||||
|
|
@ -148,11 +148,11 @@ If no `pi` manifest is present, pi auto-discovers resources from these directori
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When pi installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically.
|
Third party runtime dependencies belong in `dependencies` in `package.json`. Dependencies that do not register extensions, skills, prompt templates, or themes also belong in `dependencies`. When companion installs a package from npm or git, it runs `npm install`, so those dependencies are installed automatically.
|
||||||
|
|
||||||
Pi bundles core packages for extensions and skills. If you import any of these, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@mariozechner/pi-ai`, `@mariozechner/pi-agent-core`, `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`, `@sinclair/typebox`.
|
Companion bundles core packages for extensions and skills. If you import any of these, list them in `peerDependencies` with a `"*"` range and do not bundle them: `@mariozechner/companion-ai`, `@mariozechner/companion-agent-core`, `@mariozechner/companion-coding-agent`, `@mariozechner/companion-tui`, `@sinclair/typebox`.
|
||||||
|
|
||||||
Other pi packages must be bundled in your tarball. Add them to `dependencies` and `bundledDependencies`, then reference their resources through `node_modules/` paths. Pi loads packages with separate module roots, so separate installs do not collide or share modules.
|
Other companion packages must be bundled in your tarball. Add them to `dependencies` and `bundledDependencies`, then reference their resources through `node_modules/` paths. Companion loads packages with separate module roots, so separate installs do not collide or share modules.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
@ -162,7 +162,7 @@ Example:
|
||||||
"shitty-extensions": "^1.0.1"
|
"shitty-extensions": "^1.0.1"
|
||||||
},
|
},
|
||||||
"bundledDependencies": ["shitty-extensions"],
|
"bundledDependencies": ["shitty-extensions"],
|
||||||
"pi": {
|
"companion": {
|
||||||
"extensions": ["extensions", "node_modules/shitty-extensions/extensions"],
|
"extensions": ["extensions", "node_modules/shitty-extensions/extensions"],
|
||||||
"skills": ["skills", "node_modules/shitty-extensions/skills"]
|
"skills": ["skills", "node_modules/shitty-extensions/skills"]
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +199,7 @@ Filter what a package loads using the object form in settings:
|
||||||
|
|
||||||
## Enable and Disable Resources
|
## Enable and Disable Resources
|
||||||
|
|
||||||
Use `pi config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. Works for both global (`~/.pi/agent`) and project (`.pi/`) scopes.
|
Use `companion config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. Works for both global (`~/.companion/agent`) and project (`.companion/`) scopes.
|
||||||
|
|
||||||
## Scope and Deduplication
|
## Scope and Deduplication
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
> pi can create prompt templates. Ask it to build one for your workflow.
|
> companion can create prompt templates. Ask it to build one for your workflow.
|
||||||
|
|
||||||
# Prompt Templates
|
# Prompt Templates
|
||||||
|
|
||||||
|
|
@ -6,11 +6,11 @@ Prompt templates are Markdown snippets that expand into full prompts. Type `/nam
|
||||||
|
|
||||||
## Locations
|
## Locations
|
||||||
|
|
||||||
Pi loads prompt templates from:
|
Companion loads prompt templates from:
|
||||||
|
|
||||||
- Global: `~/.pi/agent/prompts/*.md`
|
- Global: `~/.companion/agent/prompts/*.md`
|
||||||
- Project: `.pi/prompts/*.md`
|
- Project: `.companion/prompts/*.md`
|
||||||
- Packages: `prompts/` directories or `pi.prompts` entries in `package.json`
|
- Packages: `prompts/` directories or `companion.prompts` entries in `package.json`
|
||||||
- Settings: `prompts` array with files or directories
|
- Settings: `prompts` array with files or directories
|
||||||
- CLI: `--prompt-template <path>` (repeatable)
|
- CLI: `--prompt-template <path>` (repeatable)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Providers
|
# Providers
|
||||||
|
|
||||||
Pi supports subscription-based providers via OAuth and API key providers via environment variables or auth file. For each provider, pi knows all available models. The list is updated with every pi release.
|
Companion supports subscription-based providers via OAuth and API key providers via environment variables or auth file. For each provider, companion knows all available models. The list is updated with every companion release.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ Use `/login` in interactive mode, then select a provider:
|
||||||
- Google Gemini CLI
|
- Google Gemini CLI
|
||||||
- Google Antigravity
|
- Google Antigravity
|
||||||
|
|
||||||
Use `/logout` to clear credentials. Tokens are stored in `~/.pi/agent/auth.json` and auto-refresh when expired.
|
Use `/logout` to clear credentials. Tokens are stored in `~/.companion/agent/auth.json` and auto-refresh when expired.
|
||||||
|
|
||||||
### GitHub Copilot
|
### GitHub Copilot
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ Set via environment variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export ANTHROPIC_API_KEY=sk-ant-...
|
export ANTHROPIC_API_KEY=sk-ant-...
|
||||||
pi
|
companion
|
||||||
```
|
```
|
||||||
|
|
||||||
| Provider | Environment Variable | `auth.json` key |
|
| Provider | Environment Variable | `auth.json` key |
|
||||||
|
|
@ -71,11 +71,11 @@ pi
|
||||||
| MiniMax | `MINIMAX_API_KEY` | `minimax` |
|
| MiniMax | `MINIMAX_API_KEY` | `minimax` |
|
||||||
| MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
|
| MiniMax (China) | `MINIMAX_CN_API_KEY` | `minimax-cn` |
|
||||||
|
|
||||||
Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/env-api-keys.ts).
|
Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/env-api-keys.ts).
|
||||||
|
|
||||||
#### Auth File
|
#### Auth File
|
||||||
|
|
||||||
Store credentials in `~/.pi/agent/auth.json`:
|
Store credentials in `~/.companion/agent/auth.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -144,7 +144,7 @@ export AWS_REGION=us-west-2
|
||||||
Also supports ECS task roles (`AWS_CONTAINER_CREDENTIALS_*`) and IRSA (`AWS_WEB_IDENTITY_TOKEN_FILE`).
|
Also supports ECS task roles (`AWS_CONTAINER_CREDENTIALS_*`) and IRSA (`AWS_WEB_IDENTITY_TOKEN_FILE`).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
|
companion --provider amazon-bedrock --model us.anthropic.claude-sonnet-4-20250514-v1:0
|
||||||
```
|
```
|
||||||
|
|
||||||
If you are connecting to a Bedrock API proxy, the following environment variables can be used:
|
If you are connecting to a Bedrock API proxy, the following environment variables can be used:
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
|
|
||||||
RPC mode enables headless operation of the coding agent via a JSON protocol over stdin/stdout. This is useful for embedding the agent in other applications, IDEs, or custom UIs.
|
RPC mode enables headless operation of the coding agent via a JSON protocol over stdin/stdout. This is useful for embedding the agent in other applications, IDEs, or custom UIs.
|
||||||
|
|
||||||
**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@mariozechner/pi-coding-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts).
|
**Note for Node.js/TypeScript users**: If you're building a Node.js application, consider using `AgentSession` directly from `@mariozechner/companion-coding-agent` instead of spawning a subprocess. See [`src/core/agent-session.ts`](../src/core/agent-session.ts) for the API. For a subprocess-based TypeScript client, see [`src/modes/rpc/rpc-client.ts`](../src/modes/rpc/rpc-client.ts).
|
||||||
|
|
||||||
## Starting RPC Mode
|
## Starting RPC Mode
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi --mode rpc [options]
|
companion --mode rpc [options]
|
||||||
```
|
```
|
||||||
|
|
||||||
Common options:
|
Common options:
|
||||||
|
|
@ -60,7 +60,7 @@ With images:
|
||||||
|
|
||||||
If the agent is streaming and no `streamingBehavior` is specified, the command returns an error.
|
If the agent is streaming and no `streamingBehavior` is specified, the command returns an error.
|
||||||
|
|
||||||
**Extension commands**: If the message is an extension command (e.g., `/mycommand`), it executes immediately even during streaming. Extension commands manage their own LLM interaction via `pi.sendMessage()`.
|
**Extension commands**: If the message is an extension command (e.g., `/mycommand`), it executes immediately even during streaming. Extension commands manage their own LLM interaction via `companion.sendMessage()`.
|
||||||
|
|
||||||
**Input expansion**: Skill commands (`/skill:name`) and prompt templates (`/template`) are expanded before sending/queueing.
|
**Input expansion**: Skill commands (`/skill:name`) and prompt templates (`/template`) are expanded before sending/queueing.
|
||||||
|
|
||||||
|
|
@ -503,7 +503,7 @@ If output was truncated, includes `fullOutputPath`:
|
||||||
"exitCode": 0,
|
"exitCode": 0,
|
||||||
"cancelled": false,
|
"cancelled": false,
|
||||||
"truncated": true,
|
"truncated": true,
|
||||||
"fullOutputPath": "/tmp/pi-bash-abc123.log"
|
"fullOutputPath": "/tmp/companion-bash-abc123.log"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -752,21 +752,21 @@ Response:
|
||||||
"name": "session-name",
|
"name": "session-name",
|
||||||
"description": "Set or clear session name",
|
"description": "Set or clear session name",
|
||||||
"source": "extension",
|
"source": "extension",
|
||||||
"path": "/home/user/.pi/agent/extensions/session.ts"
|
"path": "/home/user/.companion/agent/extensions/session.ts"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fix-tests",
|
"name": "fix-tests",
|
||||||
"description": "Fix failing tests",
|
"description": "Fix failing tests",
|
||||||
"source": "prompt",
|
"source": "prompt",
|
||||||
"location": "project",
|
"location": "project",
|
||||||
"path": "/home/user/myproject/.pi/agent/prompts/fix-tests.md"
|
"path": "/home/user/myproject/.companion/agent/prompts/fix-tests.md"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "skill:brave-search",
|
"name": "skill:brave-search",
|
||||||
"description": "Web search via Brave API",
|
"description": "Web search via Brave API",
|
||||||
"source": "skill",
|
"source": "skill",
|
||||||
"location": "user",
|
"location": "user",
|
||||||
"path": "/home/user/.pi/agent/skills/brave-search/SKILL.md"
|
"path": "/home/user/.companion/agent/skills/brave-search/SKILL.md"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -778,12 +778,12 @@ Each command has:
|
||||||
- `name`: Command name (invoke with `/name`)
|
- `name`: Command name (invoke with `/name`)
|
||||||
- `description`: Human-readable description (optional for extension commands)
|
- `description`: Human-readable description (optional for extension commands)
|
||||||
- `source`: What kind of command:
|
- `source`: What kind of command:
|
||||||
- `"extension"`: Registered via `pi.registerCommand()` in an extension
|
- `"extension"`: Registered via `companion.registerCommand()` in an extension
|
||||||
- `"prompt"`: Loaded from a prompt template `.md` file
|
- `"prompt"`: Loaded from a prompt template `.md` file
|
||||||
- `"skill"`: Loaded from a skill directory (name is prefixed with `skill:`)
|
- `"skill"`: Loaded from a skill directory (name is prefixed with `skill:`)
|
||||||
- `location`: Where it was loaded from (optional, not present for extensions):
|
- `location`: Where it was loaded from (optional, not present for extensions):
|
||||||
- `"user"`: User-level (`~/.pi/agent/`)
|
- `"user"`: User-level (`~/.companion/agent/`)
|
||||||
- `"project"`: Project-level (`./.pi/agent/`)
|
- `"project"`: Project-level (`./.companion/agent/`)
|
||||||
- `"path"`: Explicit path via CLI or settings
|
- `"path"`: Explicit path via CLI or settings
|
||||||
- `path`: Absolute file path to the command source (optional)
|
- `path`: Absolute file path to the command source (optional)
|
||||||
|
|
||||||
|
|
@ -1173,7 +1173,7 @@ Set the terminal window/tab title. Fire-and-forget.
|
||||||
"type": "extension_ui_request",
|
"type": "extension_ui_request",
|
||||||
"id": "uuid-8",
|
"id": "uuid-8",
|
||||||
"method": "setTitle",
|
"method": "setTitle",
|
||||||
"title": "pi - my project"
|
"title": "companion - my project"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -1372,7 +1372,7 @@ import subprocess
|
||||||
import json
|
import json
|
||||||
|
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
["pi", "--mode", "rpc", "--no-session"],
|
["companion", "--mode", "rpc", "--no-session"],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
text=True
|
text=True
|
||||||
|
|
@ -1411,7 +1411,7 @@ For a complete example of handling the extension UI protocol, see [`examples/rpc
|
||||||
const { spawn } = require("child_process");
|
const { spawn } = require("child_process");
|
||||||
const readline = require("readline");
|
const readline = require("readline");
|
||||||
|
|
||||||
const agent = spawn("pi", ["--mode", "rpc", "--no-session"]);
|
const agent = spawn("companion", ["--mode", "rpc", "--no-session"]);
|
||||||
|
|
||||||
readline.createInterface({ input: agent.stdout }).on("line", (line) => {
|
readline.createInterface({ input: agent.stdout }).on("line", (line) => {
|
||||||
const event = JSON.parse(line);
|
const event = JSON.parse(line);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
> pi can help you use the SDK. Ask it to build an integration for your use case.
|
> companion can help you use the SDK. Ask it to build an integration for your use case.
|
||||||
|
|
||||||
# SDK
|
# SDK
|
||||||
|
|
||||||
The SDK provides programmatic access to pi's agent capabilities. Use it to embed pi in other applications, build custom interfaces, or integrate with automated workflows.
|
The SDK provides programmatic access to companion's agent capabilities. Use it to embed companion in other applications, build custom interfaces, or integrate with automated workflows.
|
||||||
|
|
||||||
**Example use cases:**
|
**Example use cases:**
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
ModelRegistry,
|
ModelRegistry,
|
||||||
SessionManager,
|
SessionManager,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// Set up credential storage and model registry
|
// Set up credential storage and model registry
|
||||||
const authStorage = AuthStorage.create();
|
const authStorage = AuthStorage.create();
|
||||||
|
|
@ -49,7 +49,7 @@ await session.prompt("What files are in the current directory?");
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @mariozechner/pi-coding-agent
|
npm install @mariozechner/companion-coding-agent
|
||||||
```
|
```
|
||||||
|
|
||||||
The SDK is included in the main package. No separate installation needed.
|
The SDK is included in the main package. No separate installation needed.
|
||||||
|
|
@ -63,7 +63,7 @@ The main factory function. Creates an `AgentSession` with configurable options.
|
||||||
`createAgentSession()` uses a `ResourceLoader` to supply extensions, skills, prompt templates, themes, and context files. If you do not provide one, it uses `DefaultResourceLoader` with standard discovery.
|
`createAgentSession()` uses a `ResourceLoader` to supply extensions, skills, prompt templates, themes, and context files. If you do not provide one, it uses `DefaultResourceLoader` with standard discovery.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { createAgentSession } from "@mariozechner/pi-coding-agent";
|
import { createAgentSession } from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// Minimal: defaults with DefaultResourceLoader
|
// Minimal: defaults with DefaultResourceLoader
|
||||||
const { session } = await createAgentSession();
|
const { session } = await createAgentSession();
|
||||||
|
|
@ -170,7 +170,7 @@ await session.prompt("After you're done, also check X", {
|
||||||
|
|
||||||
**Behavior:**
|
**Behavior:**
|
||||||
|
|
||||||
- **Extension commands** (e.g., `/mycommand`): Execute immediately, even during streaming. They manage their own LLM interaction via `pi.sendMessage()`.
|
- **Extension commands** (e.g., `/mycommand`): Execute immediately, even during streaming. They manage their own LLM interaction via `companion.sendMessage()`.
|
||||||
- **File-based prompt templates** (from `.md` files): Expanded to their content before sending/queueing.
|
- **File-based prompt templates** (from `.md` files): Expanded to their content before sending/queueing.
|
||||||
- **During streaming without `streamingBehavior`**: Throws an error. Use `steer()` or `followUp()` directly, or specify the option.
|
- **During streaming without `streamingBehavior`**: Throws an error. Use `steer()` or `followUp()` directly, or specify the option.
|
||||||
|
|
||||||
|
|
@ -188,7 +188,7 @@ Both `steer()` and `followUp()` expand file-based prompt templates but error on
|
||||||
|
|
||||||
### Agent and AgentState
|
### Agent and AgentState
|
||||||
|
|
||||||
The `Agent` class (from `@mariozechner/pi-agent-core`) handles the core LLM interaction. Access it via `session.agent`.
|
The `Agent` class (from `@mariozechner/companion-agent-core`) handles the core LLM interaction. Access it via `session.agent`.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// Access current state
|
// Access current state
|
||||||
|
|
@ -279,17 +279,17 @@ const { session } = await createAgentSession({
|
||||||
cwd: process.cwd(), // default
|
cwd: process.cwd(), // default
|
||||||
|
|
||||||
// Global config directory
|
// Global config directory
|
||||||
agentDir: "~/.pi/agent", // default (expands ~)
|
agentDir: "~/.companion/agent", // default (expands ~)
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
`cwd` is used by `DefaultResourceLoader` for:
|
`cwd` is used by `DefaultResourceLoader` for:
|
||||||
|
|
||||||
- Project extensions (`.pi/extensions/`)
|
- Project extensions (`.companion/extensions/`)
|
||||||
- Project skills:
|
- Project skills:
|
||||||
- `.pi/skills/`
|
- `.companion/skills/`
|
||||||
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
||||||
- Project prompts (`.pi/prompts/`)
|
- Project prompts (`.companion/prompts/`)
|
||||||
- Context files (`AGENTS.md` walking up from cwd)
|
- Context files (`AGENTS.md` walking up from cwd)
|
||||||
- Session directory naming
|
- Session directory naming
|
||||||
|
|
||||||
|
|
@ -297,7 +297,7 @@ const { session } = await createAgentSession({
|
||||||
|
|
||||||
- Global extensions (`extensions/`)
|
- Global extensions (`extensions/`)
|
||||||
- Global skills:
|
- Global skills:
|
||||||
- `skills/` under `agentDir` (for example `~/.pi/agent/skills/`)
|
- `skills/` under `agentDir` (for example `~/.companion/agent/skills/`)
|
||||||
- `~/.agents/skills/`
|
- `~/.agents/skills/`
|
||||||
- Global prompts (`prompts/`)
|
- Global prompts (`prompts/`)
|
||||||
- Global context file (`AGENTS.md`)
|
- Global context file (`AGENTS.md`)
|
||||||
|
|
@ -311,8 +311,8 @@ When you pass a custom `ResourceLoader`, `cwd` and `agentDir` no longer control
|
||||||
### Model
|
### Model
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel } from "@mariozechner/pi-ai";
|
import { getModel } from "@mariozechner/companion-ai";
|
||||||
import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
import { AuthStorage, ModelRegistry } from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const authStorage = AuthStorage.create();
|
const authStorage = AuthStorage.create();
|
||||||
const modelRegistry = new ModelRegistry(authStorage);
|
const modelRegistry = new ModelRegistry(authStorage);
|
||||||
|
|
@ -359,9 +359,9 @@ API key resolution priority (handled by AuthStorage):
|
||||||
4. Fallback resolver (for custom provider keys from `models.json`)
|
4. Fallback resolver (for custom provider keys from `models.json`)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
import { AuthStorage, ModelRegistry } from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// Default: uses ~/.pi/agent/auth.json and ~/.pi/agent/models.json
|
// Default: uses ~/.companion/agent/auth.json and ~/.companion/agent/models.json
|
||||||
const authStorage = AuthStorage.create();
|
const authStorage = AuthStorage.create();
|
||||||
const modelRegistry = new ModelRegistry(authStorage);
|
const modelRegistry = new ModelRegistry(authStorage);
|
||||||
|
|
||||||
|
|
@ -396,7 +396,7 @@ Use a `ResourceLoader` to override the system prompt:
|
||||||
import {
|
import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
DefaultResourceLoader,
|
DefaultResourceLoader,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const loader = new DefaultResourceLoader({
|
const loader = new DefaultResourceLoader({
|
||||||
systemPromptOverride: () => "You are a helpful assistant.",
|
systemPromptOverride: () => "You are a helpful assistant.",
|
||||||
|
|
@ -419,7 +419,7 @@ import {
|
||||||
grepTool,
|
grepTool,
|
||||||
findTool,
|
findTool,
|
||||||
lsTool,
|
lsTool,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// Use built-in tool set
|
// Use built-in tool set
|
||||||
const { session } = await createAgentSession({
|
const { session } = await createAgentSession({
|
||||||
|
|
@ -447,7 +447,7 @@ import {
|
||||||
createGrepTool,
|
createGrepTool,
|
||||||
createFindTool,
|
createFindTool,
|
||||||
createLsTool,
|
createLsTool,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const cwd = "/path/to/project";
|
const cwd = "/path/to/project";
|
||||||
|
|
||||||
|
|
@ -466,7 +466,7 @@ const { session } = await createAgentSession({
|
||||||
|
|
||||||
**When you don't need factories:**
|
**When you don't need factories:**
|
||||||
|
|
||||||
- If you omit `tools`, pi automatically creates them with the correct `cwd`
|
- If you omit `tools`, companion automatically creates them with the correct `cwd`
|
||||||
- If you use `process.cwd()` as your `cwd`, the pre-built instances work fine
|
- If you use `process.cwd()` as your `cwd`, the pre-built instances work fine
|
||||||
|
|
||||||
**When you must use factories:**
|
**When you must use factories:**
|
||||||
|
|
@ -480,7 +480,7 @@ import { Type } from "@sinclair/typebox";
|
||||||
import {
|
import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
type ToolDefinition,
|
type ToolDefinition,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// Inline custom tool
|
// Inline custom tool
|
||||||
const myTool: ToolDefinition = {
|
const myTool: ToolDefinition = {
|
||||||
|
|
@ -502,23 +502,23 @@ const { session } = await createAgentSession({
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `pi.registerTool()`.
|
Custom tools passed via `customTools` are combined with extension-registered tools. Extensions loaded by the ResourceLoader can also register tools via `companion.registerTool()`.
|
||||||
|
|
||||||
### Extensions
|
### Extensions
|
||||||
|
|
||||||
Extensions are loaded by the `ResourceLoader`. `DefaultResourceLoader` discovers extensions from `~/.pi/agent/extensions/`, `.pi/extensions/`, and settings.json extension sources.
|
Extensions are loaded by the `ResourceLoader`. `DefaultResourceLoader` discovers extensions from `~/.companion/agent/extensions/`, `.companion/extensions/`, and settings.json extension sources.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import {
|
import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
DefaultResourceLoader,
|
DefaultResourceLoader,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const loader = new DefaultResourceLoader({
|
const loader = new DefaultResourceLoader({
|
||||||
additionalExtensionPaths: ["/path/to/my-extension.ts"],
|
additionalExtensionPaths: ["/path/to/my-extension.ts"],
|
||||||
extensionFactories: [
|
extensionFactories: [
|
||||||
(pi) => {
|
(companion) => {
|
||||||
pi.on("agent_start", () => {
|
companion.on("agent_start", () => {
|
||||||
console.log("[Inline Extension] Agent starting");
|
console.log("[Inline Extension] Agent starting");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -531,13 +531,13 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
||||||
|
|
||||||
Extensions can register tools, subscribe to events, add commands, and more. See [extensions.md](extensions.md) for the full API.
|
Extensions can register tools, subscribe to events, add commands, and more. See [extensions.md](extensions.md) for the full API.
|
||||||
|
|
||||||
**Event Bus:** Extensions can communicate via `pi.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside:
|
**Event Bus:** Extensions can communicate via `companion.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import {
|
import {
|
||||||
createEventBus,
|
createEventBus,
|
||||||
DefaultResourceLoader,
|
DefaultResourceLoader,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const eventBus = createEventBus();
|
const eventBus = createEventBus();
|
||||||
const loader = new DefaultResourceLoader({
|
const loader = new DefaultResourceLoader({
|
||||||
|
|
@ -555,7 +555,7 @@ import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
DefaultResourceLoader,
|
DefaultResourceLoader,
|
||||||
type Skill,
|
type Skill,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const customSkill: Skill = {
|
const customSkill: Skill = {
|
||||||
name: "my-skill",
|
name: "my-skill",
|
||||||
|
|
@ -582,7 +582,7 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
||||||
import {
|
import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
DefaultResourceLoader,
|
DefaultResourceLoader,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const loader = new DefaultResourceLoader({
|
const loader = new DefaultResourceLoader({
|
||||||
agentsFilesOverride: (current) => ({
|
agentsFilesOverride: (current) => ({
|
||||||
|
|
@ -604,7 +604,7 @@ import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
DefaultResourceLoader,
|
DefaultResourceLoader,
|
||||||
type PromptTemplate,
|
type PromptTemplate,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const customCommand: PromptTemplate = {
|
const customCommand: PromptTemplate = {
|
||||||
name: "deploy",
|
name: "deploy",
|
||||||
|
|
@ -632,7 +632,7 @@ Sessions use a tree structure with `id`/`parentId` linking, enabling in-place br
|
||||||
import {
|
import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
SessionManager,
|
SessionManager,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// In-memory (no persistence)
|
// In-memory (no persistence)
|
||||||
const { session } = await createAgentSession({
|
const { session } = await createAgentSession({
|
||||||
|
|
@ -707,7 +707,7 @@ import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
SettingsManager,
|
SettingsManager,
|
||||||
SessionManager,
|
SessionManager,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// Default: loads from files (global + project merged)
|
// Default: loads from files (global + project merged)
|
||||||
const { session } = await createAgentSession({
|
const { session } = await createAgentSession({
|
||||||
|
|
@ -743,8 +743,8 @@ const { session } = await createAgentSession({
|
||||||
|
|
||||||
Settings load from two locations and merge:
|
Settings load from two locations and merge:
|
||||||
|
|
||||||
1. Global: `~/.pi/agent/settings.json`
|
1. Global: `~/.companion/agent/settings.json`
|
||||||
2. Project: `<cwd>/.pi/settings.json`
|
2. Project: `<cwd>/.companion/settings.json`
|
||||||
|
|
||||||
Project overrides global. Nested objects merge keys. Setters modify global settings by default.
|
Project overrides global. Nested objects merge keys. Setters modify global settings by default.
|
||||||
|
|
||||||
|
|
@ -763,7 +763,7 @@ Use `DefaultResourceLoader` to discover extensions, skills, prompts, themes, and
|
||||||
import {
|
import {
|
||||||
DefaultResourceLoader,
|
DefaultResourceLoader,
|
||||||
getAgentDir,
|
getAgentDir,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const loader = new DefaultResourceLoader({
|
const loader = new DefaultResourceLoader({
|
||||||
cwd,
|
cwd,
|
||||||
|
|
@ -804,7 +804,7 @@ interface LoadExtensionsResult {
|
||||||
## Complete Example
|
## Complete Example
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getModel } from "@mariozechner/pi-ai";
|
import { getModel } from "@mariozechner/companion-ai";
|
||||||
import { Type } from "@sinclair/typebox";
|
import { Type } from "@sinclair/typebox";
|
||||||
import {
|
import {
|
||||||
AuthStorage,
|
AuthStorage,
|
||||||
|
|
@ -816,7 +816,7 @@ import {
|
||||||
readTool,
|
readTool,
|
||||||
bashTool,
|
bashTool,
|
||||||
type ToolDefinition,
|
type ToolDefinition,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
// Set up auth storage (custom location)
|
// Set up auth storage (custom location)
|
||||||
const authStorage = AuthStorage.create("/custom/agent/auth.json");
|
const authStorage = AuthStorage.create("/custom/agent/auth.json");
|
||||||
|
|
@ -899,7 +899,7 @@ Full TUI interactive mode with editor, chat history, and all built-in commands:
|
||||||
import {
|
import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
InteractiveMode,
|
InteractiveMode,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const { session } = await createAgentSession({
|
const { session } = await createAgentSession({
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
@ -925,7 +925,7 @@ Single-shot mode: send prompts, output result, exit:
|
||||||
import {
|
import {
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
runPrintMode,
|
runPrintMode,
|
||||||
} from "@mariozechner/pi-coding-agent";
|
} from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const { session } = await createAgentSession({
|
const { session } = await createAgentSession({
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
@ -944,7 +944,7 @@ await runPrintMode(session, {
|
||||||
JSON-RPC mode for subprocess integration:
|
JSON-RPC mode for subprocess integration:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { createAgentSession, runRpcMode } from "@mariozechner/pi-coding-agent";
|
import { createAgentSession, runRpcMode } from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
const { session } = await createAgentSession({
|
const { session } = await createAgentSession({
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
@ -960,7 +960,7 @@ See [RPC documentation](rpc.md) for the JSON protocol.
|
||||||
For subprocess-based integration without building with the SDK, use the CLI directly:
|
For subprocess-based integration without building with the SDK, use the CLI directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pi --mode rpc --no-session
|
companion --mode rpc --no-session
|
||||||
```
|
```
|
||||||
|
|
||||||
See [RPC documentation](rpc.md) for the JSON protocol.
|
See [RPC documentation](rpc.md) for the JSON protocol.
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@ Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with
|
||||||
## File Location
|
## File Location
|
||||||
|
|
||||||
```
|
```
|
||||||
~/.pi/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
|
~/.companion/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `<path>` is the working directory with `/` replaced by `-`.
|
Where `<path>` is the working directory with `/` replaced by `-`.
|
||||||
|
|
||||||
## Deleting Sessions
|
## Deleting Sessions
|
||||||
|
|
||||||
Sessions can be removed by deleting their `.jsonl` files under `~/.pi/agent/sessions/`.
|
Sessions can be removed by deleting their `.jsonl` files under `~/.companion/agent/sessions/`.
|
||||||
|
|
||||||
Pi also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, pi uses the `trash` CLI to avoid permanent deletion.
|
Companion also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, companion uses the `trash` CLI to avoid permanent deletion.
|
||||||
|
|
||||||
## Session Version
|
## Session Version
|
||||||
|
|
||||||
|
|
@ -28,14 +28,14 @@ Existing sessions are automatically migrated to the current version (v3) when lo
|
||||||
|
|
||||||
## Source Files
|
## Source Files
|
||||||
|
|
||||||
Source on GitHub ([pi-mono](https://github.com/badlogic/pi-mono)):
|
Source on GitHub ([companion-mono](https://github.com/badlogic/companion-mono)):
|
||||||
|
|
||||||
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
|
- [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
|
||||||
- [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
|
- [`packages/coding-agent/src/core/messages.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
|
||||||
- [`packages/ai/src/types.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
|
- [`packages/ai/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
|
||||||
- [`packages/agent/src/types.ts`](https://github.com/badlogic/pi-mono/blob/main/packages/agent/src/types.ts) - AgentMessage union type
|
- [`packages/agent/src/types.ts`](https://github.com/badlogic/companion-mono/blob/main/packages/agent/src/types.ts) - AgentMessage union type
|
||||||
|
|
||||||
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/pi-coding-agent/dist/` and `node_modules/@mariozechner/pi-ai/dist/`.
|
For TypeScript definitions in your project, inspect `node_modules/@mariozechner/companion-coding-agent/dist/` and `node_modules/@mariozechner/companion-ai/dist/`.
|
||||||
|
|
||||||
## Message Types
|
## Message Types
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ interface ToolCall {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Base Message Types (from pi-ai)
|
### Base Message Types (from companion-ai)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface UserMessage {
|
interface UserMessage {
|
||||||
|
|
@ -117,7 +117,7 @@ interface Usage {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Extended Message Types (from pi-coding-agent)
|
### Extended Message Types (from companion-coding-agent)
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface BashExecutionMessage {
|
interface BashExecutionMessage {
|
||||||
|
|
@ -269,7 +269,7 @@ Created when context is compacted. Stores a summary of earlier messages.
|
||||||
Optional fields:
|
Optional fields:
|
||||||
|
|
||||||
- `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
|
- `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
|
||||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if pi-generated (legacy field name)
|
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if companion-generated (legacy field name)
|
||||||
|
|
||||||
### BranchSummaryEntry
|
### BranchSummaryEntry
|
||||||
|
|
||||||
|
|
@ -289,7 +289,7 @@ Created when switching branches via `/tree` with an LLM generated summary of the
|
||||||
Optional fields:
|
Optional fields:
|
||||||
|
|
||||||
- `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
|
- `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
|
||||||
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if pi-generated (legacy field name)
|
- `fromHook`: `true` if generated by an extension, `false`/`undefined` if companion-generated (legacy field name)
|
||||||
|
|
||||||
### CustomEntry
|
### CustomEntry
|
||||||
|
|
||||||
|
|
@ -349,7 +349,7 @@ Set `label` to `undefined` to clear a label.
|
||||||
|
|
||||||
### SessionInfoEntry
|
### SessionInfoEntry
|
||||||
|
|
||||||
Session metadata (e.g., user-defined display name). Set via `/name` command or `pi.setSessionName()` in extensions.
|
Session metadata (e.g., user-defined display name). Set via `/name` command or `companion.setSessionName()` in extensions.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# Settings
|
# Settings
|
||||||
|
|
||||||
Pi uses JSON settings files with project settings overriding global settings.
|
Companion uses JSON settings files with project settings overriding global settings.
|
||||||
|
|
||||||
| Location | Scope |
|
| Location | Scope |
|
||||||
| --------------------------- | --------------------------- |
|
| --------------------------- | --------------------------- |
|
||||||
| `~/.pi/agent/settings.json` | Global (all projects) |
|
| `~/.companion/agent/settings.json` | Global (all projects) |
|
||||||
| `.pi/settings.json` | Project (current directory) |
|
| `.companion/settings.json` | Project (current directory) |
|
||||||
|
|
||||||
Edit directly or use `/settings` for common options.
|
Edit directly or use `/settings` for common options.
|
||||||
|
|
||||||
|
|
@ -140,7 +140,7 @@ When a provider requests a retry delay longer than `maxDelayMs` (e.g., Google's
|
||||||
|
|
||||||
These settings define where to load extensions, skills, prompts, and themes from.
|
These settings define where to load extensions, skills, prompts, and themes from.
|
||||||
|
|
||||||
Paths in `~/.pi/agent/settings.json` resolve relative to `~/.pi/agent`. Paths in `.pi/settings.json` resolve relative to `.pi`. Absolute paths and `~` are supported.
|
Paths in `~/.companion/agent/settings.json` resolve relative to `~/.companion/agent`. Paths in `.companion/settings.json` resolve relative to `.companion`. Absolute paths and `~` are supported.
|
||||||
|
|
||||||
| Setting | Type | Default | Description |
|
| Setting | Type | Default | Description |
|
||||||
| --------------------- | -------- | ------- | ------------------------------------------ |
|
| --------------------- | -------- | ------- | ------------------------------------------ |
|
||||||
|
|
@ -159,7 +159,7 @@ String form loads all resources from a package:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"packages": ["pi-skills", "@org/my-extension"]
|
"packages": ["companion-skills", "@org/my-extension"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -169,7 +169,7 @@ Object form filters which resources to load:
|
||||||
{
|
{
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"source": "pi-skills",
|
"source": "companion-skills",
|
||||||
"skills": ["brave-search", "transcribe"],
|
"skills": ["brave-search", "transcribe"],
|
||||||
"extensions": []
|
"extensions": []
|
||||||
}
|
}
|
||||||
|
|
@ -197,22 +197,22 @@ See [packages.md](packages.md) for package management details.
|
||||||
"maxRetries": 3
|
"maxRetries": 3
|
||||||
},
|
},
|
||||||
"enabledModels": ["claude-*", "gpt-4o"],
|
"enabledModels": ["claude-*", "gpt-4o"],
|
||||||
"packages": ["pi-skills"]
|
"packages": ["companion-skills"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Overrides
|
## Project Overrides
|
||||||
|
|
||||||
Project settings (`.pi/settings.json`) override global settings. Nested objects are merged:
|
Project settings (`.companion/settings.json`) override global settings. Nested objects are merged:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
// ~/.pi/agent/settings.json (global)
|
// ~/.companion/agent/settings.json (global)
|
||||||
{
|
{
|
||||||
"theme": "dark",
|
"theme": "dark",
|
||||||
"compaction": { "enabled": true, "reserveTokens": 16384 }
|
"compaction": { "enabled": true, "reserveTokens": 16384 }
|
||||||
}
|
}
|
||||||
|
|
||||||
// .pi/settings.json (project)
|
// .companion/settings.json (project)
|
||||||
{
|
{
|
||||||
"compaction": { "reserveTokens": 8192 }
|
"compaction": { "reserveTokens": 8192 }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Shell Aliases
|
# Shell Aliases
|
||||||
|
|
||||||
Pi runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
|
Companion runs bash in non-interactive mode (`bash -c`), which doesn't expand aliases by default.
|
||||||
|
|
||||||
To enable your shell aliases, add to `~/.pi/agent/settings.json`:
|
To enable your shell aliases, add to `~/.companion/agent/settings.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
> pi can create skills. Ask it to build one for your use case.
|
> companion can create skills. Ask it to build one for your use case.
|
||||||
|
|
||||||
# Skills
|
# Skills
|
||||||
|
|
||||||
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
|
Skills are self-contained capability packages that the agent loads on-demand. A skill provides specialized workflows, setup instructions, helper scripts, and reference documentation for specific tasks.
|
||||||
|
|
||||||
Pi implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
Companion implements the [Agent Skills standard](https://agentskills.io/specification), warning about violations but remaining lenient.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
|
@ -21,15 +21,15 @@ Pi implements the [Agent Skills standard](https://agentskills.io/specification),
|
||||||
|
|
||||||
> **Security:** Skills can instruct the model to perform any action and may include executable code the model invokes. Review skill content before use.
|
> **Security:** Skills can instruct the model to perform any action and may include executable code the model invokes. Review skill content before use.
|
||||||
|
|
||||||
Pi loads skills from:
|
Companion loads skills from:
|
||||||
|
|
||||||
- Global:
|
- Global:
|
||||||
- `~/.pi/agent/skills/`
|
- `~/.companion/agent/skills/`
|
||||||
- `~/.agents/skills/`
|
- `~/.agents/skills/`
|
||||||
- Project:
|
- Project:
|
||||||
- `.pi/skills/`
|
- `.companion/skills/`
|
||||||
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
- `.agents/skills/` in `cwd` and ancestor directories (up to git repo root, or filesystem root when not in a repo)
|
||||||
- Packages: `skills/` directories or `pi.skills` entries in `package.json`
|
- Packages: `skills/` directories or `companion.skills` entries in `package.json`
|
||||||
- Settings: `skills` array with files or directories
|
- Settings: `skills` array with files or directories
|
||||||
- CLI: `--skill <path>` (repeatable, additive even with `--no-skills`)
|
- CLI: `--skill <path>` (repeatable, additive even with `--no-skills`)
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ To use skills from Claude Code or OpenAI Codex, add their directories to setting
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
For project-level Claude Code skills, add to `.pi/settings.json`:
|
For project-level Claude Code skills, add to `.companion/settings.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -60,7 +60,7 @@ For project-level Claude Code skills, add to `.pi/settings.json`:
|
||||||
|
|
||||||
## How Skills Work
|
## How Skills Work
|
||||||
|
|
||||||
1. At startup, pi scans skill locations and extracts names and descriptions
|
1. At startup, companion scans skill locations and extracts names and descriptions
|
||||||
2. The system prompt includes available skills in XML format per the [specification](https://agentskills.io/integrate-skills)
|
2. The system prompt includes available skills in XML format per the [specification](https://agentskills.io/integrate-skills)
|
||||||
3. When a task matches, the agent uses `read` to load the full SKILL.md (models don't always do this; use prompting or `/skill:name` to force it)
|
3. When a task matches, the agent uses `read` to load the full SKILL.md (models don't always do this; use prompting or `/skill:name` to force it)
|
||||||
4. The agent follows the instructions, using relative paths to reference scripts and assets
|
4. The agent follows the instructions, using relative paths to reference scripts and assets
|
||||||
|
|
@ -174,7 +174,7 @@ description: Helps with PDFs.
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
|
|
||||||
Pi validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
Companion validates skills against the Agent Skills standard. Most issues produce warnings but still load the skill:
|
||||||
|
|
||||||
- Name doesn't match parent directory
|
- Name doesn't match parent directory
|
||||||
- Name exceeds 64 characters or contains invalid characters
|
- Name exceeds 64 characters or contains invalid characters
|
||||||
|
|
@ -229,4 +229,4 @@ cd /path/to/brave-search && npm install
|
||||||
## Skill Repositories
|
## Skill Repositories
|
||||||
|
|
||||||
- [Anthropic Skills](https://github.com/anthropics/skills) - Document processing (docx, pdf, pptx, xlsx), web development
|
- [Anthropic Skills](https://github.com/anthropics/skills) - Document processing (docx, pdf, pptx, xlsx), web development
|
||||||
- [Pi Skills](https://github.com/badlogic/pi-skills) - Web search, browser automation, Google APIs, transcription
|
- [Companion Skills](https://github.com/badlogic/companion-skills) - Web search, browser automation, Google APIs, transcription
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Terminal Setup
|
# Terminal Setup
|
||||||
|
|
||||||
Pi uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
|
Companion uses the [Kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/) for reliable modifier key detection. Most modern terminals support this protocol, but some require configuration.
|
||||||
|
|
||||||
## Kitty, iTerm2
|
## Kitty, iTerm2
|
||||||
|
|
||||||
|
|
@ -66,6 +66,6 @@ If you already have an `actions` array, add the object to it.
|
||||||
|
|
||||||
The built-in terminal has limited escape sequence support. Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal.
|
The built-in terminal has limited escape sequence support. Shift+Enter cannot be distinguished from Enter in IntelliJ's terminal.
|
||||||
|
|
||||||
If you want the hardware cursor visible, set `PI_HARDWARE_CURSOR=1` before running pi (disabled by default for compatibility).
|
If you want the hardware cursor visible, set `COMPANION_HARDWARE_CURSOR=1` before running companion (disabled by default for compatibility).
|
||||||
|
|
||||||
Consider using a dedicated terminal emulator for the best experience.
|
Consider using a dedicated terminal emulator for the best experience.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Termux (Android) Setup
|
# Termux (Android) Setup
|
||||||
|
|
||||||
Pi runs on Android via [Termux](https://termux.dev/), a terminal emulator and Linux environment for Android.
|
Companion runs on Android via [Termux](https://termux.dev/), a terminal emulator and Linux environment for Android.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
|
@ -16,14 +16,14 @@ pkg update && pkg upgrade
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
pkg install nodejs termux-api git
|
pkg install nodejs termux-api git
|
||||||
|
|
||||||
# Install pi
|
# Install companion
|
||||||
npm install -g @mariozechner/pi-coding-agent
|
npm install -g @mariozechner/companion-coding-agent
|
||||||
|
|
||||||
# Create config directory
|
# Create config directory
|
||||||
mkdir -p ~/.pi/agent
|
mkdir -p ~/.companion/agent
|
||||||
|
|
||||||
# Run pi
|
# Run companion
|
||||||
pi
|
companion
|
||||||
```
|
```
|
||||||
|
|
||||||
## Clipboard Support
|
## Clipboard Support
|
||||||
|
|
@ -34,7 +34,7 @@ Image clipboard is not supported on Termux (the `ctrl+v` image paste feature wil
|
||||||
|
|
||||||
## Example AGENTS.md for Termux
|
## Example AGENTS.md for Termux
|
||||||
|
|
||||||
Create `~/.pi/agent/AGENTS.md` to help the agent understand the Termux environment:
|
Create `~/.companion/agent/AGENTS.md` to help the agent understand the Termux environment:
|
||||||
|
|
||||||
````markdown
|
````markdown
|
||||||
# Agent Environment: Termux on Android
|
# Agent Environment: Termux on Android
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
> pi can create themes. Ask it to build one for your setup.
|
> companion can create themes. Ask it to build one for your setup.
|
||||||
|
|
||||||
# Themes
|
# Themes
|
||||||
|
|
||||||
|
|
@ -16,12 +16,12 @@ Themes are JSON files that define colors for the TUI.
|
||||||
|
|
||||||
## Locations
|
## Locations
|
||||||
|
|
||||||
Pi loads themes from:
|
Companion loads themes from:
|
||||||
|
|
||||||
- Built-in: `dark`, `light`
|
- Built-in: `dark`, `light`
|
||||||
- Global: `~/.pi/agent/themes/*.json`
|
- Global: `~/.companion/agent/themes/*.json`
|
||||||
- Project: `.pi/themes/*.json`
|
- Project: `.companion/themes/*.json`
|
||||||
- Packages: `themes/` directories or `pi.themes` entries in `package.json`
|
- Packages: `themes/` directories or `companion.themes` entries in `package.json`
|
||||||
- Settings: `themes` array with files or directories
|
- Settings: `themes` array with files or directories
|
||||||
- CLI: `--theme <path>` (repeatable)
|
- CLI: `--theme <path>` (repeatable)
|
||||||
|
|
||||||
|
|
@ -37,22 +37,22 @@ Select a theme via `/settings` or in `settings.json`:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
On first run, pi detects your terminal background and defaults to `dark` or `light`.
|
On first run, companion detects your terminal background and defaults to `dark` or `light`.
|
||||||
|
|
||||||
## Creating a Custom Theme
|
## Creating a Custom Theme
|
||||||
|
|
||||||
1. Create a theme file:
|
1. Create a theme file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/.pi/agent/themes
|
mkdir -p ~/.companion/agent/themes
|
||||||
vim ~/.pi/agent/themes/my-theme.json
|
vim ~/.companion/agent/themes/my-theme.json
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Define the theme with all required colors (see [Color Tokens](#color-tokens)):
|
2. Define the theme with all required colors (see [Color Tokens](#color-tokens)):
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||||
"name": "my-theme",
|
"name": "my-theme",
|
||||||
"vars": {
|
"vars": {
|
||||||
"primary": "#00aaff",
|
"primary": "#00aaff",
|
||||||
|
|
@ -116,13 +116,13 @@ vim ~/.pi/agent/themes/my-theme.json
|
||||||
|
|
||||||
3. Select the theme via `/settings`.
|
3. Select the theme via `/settings`.
|
||||||
|
|
||||||
**Hot reload:** When you edit the currently active custom theme file, pi reloads it automatically for immediate visual feedback.
|
**Hot reload:** When you edit the currently active custom theme file, companion reloads it automatically for immediate visual feedback.
|
||||||
|
|
||||||
## Theme Format
|
## Theme Format
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
"$schema": "https://raw.githubusercontent.com/badlogic/companion-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
||||||
"name": "my-theme",
|
"name": "my-theme",
|
||||||
"vars": {
|
"vars": {
|
||||||
"blue": "#0066cc",
|
"blue": "#0066cc",
|
||||||
|
|
@ -268,7 +268,7 @@ Four formats are supported:
|
||||||
|
|
||||||
### Terminal Compatibility
|
### Terminal Compatibility
|
||||||
|
|
||||||
Pi uses 24-bit RGB colors. Most modern terminals support this (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). For older terminals with only 256-color support, pi falls back to the nearest approximation.
|
Companion uses 24-bit RGB colors. Most modern terminals support this (iTerm2, Kitty, WezTerm, Windows Terminal, VS Code). For older terminals with only 256-color support, companion falls back to the nearest approximation.
|
||||||
|
|
||||||
Check truecolor support:
|
Check truecolor support:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -209,8 +209,8 @@ interface SessionTreeEvent {
|
||||||
### Example: Custom Summarizer
|
### Example: Custom Summarizer
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
export default function (pi: HookAPI) {
|
export default function (companion: HookAPI) {
|
||||||
pi.on("session_before_tree", async (event, ctx) => {
|
companion.on("session_before_tree", async (event, ctx) => {
|
||||||
if (!event.preparation.userWantsSummary) return;
|
if (!event.preparation.userWantsSummary) return;
|
||||||
if (event.preparation.entriesToSummarize.length === 0) return;
|
if (event.preparation.entriesToSummarize.length === 0) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
> pi can create TUI components. Ask it to build one for your use case.
|
> companion can create TUI components. Ask it to build one for your use case.
|
||||||
|
|
||||||
# TUI Components
|
# TUI Components
|
||||||
|
|
||||||
Extensions and custom tools can render custom TUI components for interactive user interfaces. This page covers the component system and available building blocks.
|
Extensions and custom tools can render custom TUI components for interactive user interfaces. This page covers the component system and available building blocks.
|
||||||
|
|
||||||
**Source:** [`@mariozechner/pi-tui`](https://github.com/badlogic/pi-mono/tree/main/packages/tui)
|
**Source:** [`@mariozechner/companion-tui`](https://github.com/badlogic/companion-mono/tree/main/packages/tui)
|
||||||
|
|
||||||
## Component Interface
|
## Component Interface
|
||||||
|
|
||||||
|
|
@ -37,7 +37,7 @@ import {
|
||||||
CURSOR_MARKER,
|
CURSOR_MARKER,
|
||||||
type Component,
|
type Component,
|
||||||
type Focusable,
|
type Focusable,
|
||||||
} from "@mariozechner/pi-tui";
|
} from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
class MyInput implements Component, Focusable {
|
class MyInput implements Component, Focusable {
|
||||||
focused: boolean = false; // Set by TUI when focus changes
|
focused: boolean = false; // Set by TUI when focus changes
|
||||||
|
|
@ -66,7 +66,7 @@ This enables IME candidate windows to appear at the correct position for CJK inp
|
||||||
When a container component (dialog, selector, etc.) contains an `Input` or `Editor` child, the container must implement `Focusable` and propagate the focus state to the child. Otherwise, the hardware cursor won't be positioned correctly for IME input.
|
When a container component (dialog, selector, etc.) contains an `Input` or `Editor` child, the container must implement `Focusable` and propagate the focus state to the child. Otherwise, the hardware cursor won't be positioned correctly for IME input.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Container, type Focusable, Input } from "@mariozechner/pi-tui";
|
import { Container, type Focusable, Input } from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
class SearchDialog extends Container implements Focusable {
|
class SearchDialog extends Container implements Focusable {
|
||||||
private searchInput: Input;
|
private searchInput: Input;
|
||||||
|
|
@ -96,18 +96,18 @@ Without this propagation, typing with an IME (Chinese, Japanese, Korean, etc.) w
|
||||||
**In extensions** via `ctx.ui.custom()`:
|
**In extensions** via `ctx.ui.custom()`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
pi.on("session_start", async (_event, ctx) => {
|
companion.on("session_start", async (_event, ctx) => {
|
||||||
const handle = ctx.ui.custom(myComponent);
|
const handle = ctx.ui.custom(myComponent);
|
||||||
// handle.requestRender() - trigger re-render
|
// handle.requestRender() - trigger re-render
|
||||||
// handle.close() - restore normal UI
|
// handle.close() - restore normal UI
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
**In custom tools** via `pi.ui.custom()`:
|
**In custom tools** via `companion.ui.custom()`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
async execute(toolCallId, params, onUpdate, ctx, signal) {
|
||||||
const handle = pi.ui.custom(myComponent);
|
const handle = companion.ui.custom(myComponent);
|
||||||
// ...
|
// ...
|
||||||
handle.close();
|
handle.close();
|
||||||
}
|
}
|
||||||
|
|
@ -191,10 +191,10 @@ See [overlay-qa-tests.ts](../examples/extensions/overlay-qa-tests.ts) for compre
|
||||||
|
|
||||||
## Built-in Components
|
## Built-in Components
|
||||||
|
|
||||||
Import from `@mariozechner/pi-tui`:
|
Import from `@mariozechner/companion-tui`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Text, Box, Container, Spacer, Markdown } from "@mariozechner/pi-tui";
|
import { Text, Box, Container, Spacer, Markdown } from "@mariozechner/companion-tui";
|
||||||
```
|
```
|
||||||
|
|
||||||
### Text
|
### Text
|
||||||
|
|
@ -276,7 +276,7 @@ const image = new Image(
|
||||||
Use `matchesKey()` for key detection:
|
Use `matchesKey()` for key detection:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { matchesKey, Key } from "@mariozechner/pi-tui";
|
import { matchesKey, Key } from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
handleInput(data: string) {
|
handleInput(data: string) {
|
||||||
if (matchesKey(data, Key.up)) {
|
if (matchesKey(data, Key.up)) {
|
||||||
|
|
@ -303,7 +303,7 @@ handleInput(data: string) {
|
||||||
**Critical:** Each line from `render()` must not exceed the `width` parameter.
|
**Critical:** Each line from `render()` must not exceed the `width` parameter.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { visibleWidth, truncateToWidth } from "@mariozechner/pi-tui";
|
import { visibleWidth, truncateToWidth } from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
render(width: number): string[] {
|
render(width: number): string[] {
|
||||||
// Truncate long lines
|
// Truncate long lines
|
||||||
|
|
@ -327,7 +327,7 @@ import {
|
||||||
Key,
|
Key,
|
||||||
truncateToWidth,
|
truncateToWidth,
|
||||||
visibleWidth,
|
visibleWidth,
|
||||||
} from "@mariozechner/pi-tui";
|
} from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
class MySelector {
|
class MySelector {
|
||||||
private items: string[];
|
private items: string[];
|
||||||
|
|
@ -382,7 +382,7 @@ class MySelector {
|
||||||
Usage in an extension:
|
Usage in an extension:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
pi.registerCommand("pick", {
|
companion.registerCommand("pick", {
|
||||||
description: "Pick an item",
|
description: "Pick an item",
|
||||||
handler: async (args, ctx) => {
|
handler: async (args, ctx) => {
|
||||||
const items = ["Option A", "Option B", "Option C"];
|
const items = ["Option A", "Option B", "Option C"];
|
||||||
|
|
@ -444,8 +444,8 @@ renderResult(result, options, theme) {
|
||||||
**For Markdown**, use `getMarkdownTheme()`:
|
**For Markdown**, use `getMarkdownTheme()`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getMarkdownTheme } from "@mariozechner/pi-coding-agent";
|
import { getMarkdownTheme } from "@mariozechner/companion-coding-agent";
|
||||||
import { Markdown } from "@mariozechner/pi-tui";
|
import { Markdown } from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
renderResult(result, options, theme) {
|
renderResult(result, options, theme) {
|
||||||
const mdTheme = getMarkdownTheme();
|
const mdTheme = getMarkdownTheme();
|
||||||
|
|
@ -464,10 +464,10 @@ interface MyTheme {
|
||||||
|
|
||||||
## Debug logging
|
## Debug logging
|
||||||
|
|
||||||
Set `PI_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout.
|
Set `COMPANION_TUI_WRITE_LOG` to capture the raw ANSI stream written to stdout.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
PI_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts
|
COMPANION_TUI_WRITE_LOG=/tmp/tui-ansi.log npx tsx packages/tui/test/chat-simple.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
@ -606,19 +606,19 @@ These patterns cover the most common UI needs in extensions. **Copy these patter
|
||||||
|
|
||||||
### Pattern 1: Selection Dialog (SelectList)
|
### Pattern 1: Selection Dialog (SelectList)
|
||||||
|
|
||||||
For letting users pick from a list of options. Use `SelectList` from `@mariozechner/pi-tui` with `DynamicBorder` for framing.
|
For letting users pick from a list of options. Use `SelectList` from `@mariozechner/companion-tui` with `DynamicBorder` for framing.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
import type { ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||||
import { DynamicBorder } from "@mariozechner/pi-coding-agent";
|
import { DynamicBorder } from "@mariozechner/companion-coding-agent";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
type SelectItem,
|
type SelectItem,
|
||||||
SelectList,
|
SelectList,
|
||||||
Text,
|
Text,
|
||||||
} from "@mariozechner/pi-tui";
|
} from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
pi.registerCommand("pick", {
|
companion.registerCommand("pick", {
|
||||||
handler: async (_args, ctx) => {
|
handler: async (_args, ctx) => {
|
||||||
const items: SelectItem[] = [
|
const items: SelectItem[] = [
|
||||||
{ value: "opt1", label: "Option 1", description: "First option" },
|
{ value: "opt1", label: "Option 1", description: "First option" },
|
||||||
|
|
@ -691,9 +691,9 @@ pi.registerCommand("pick", {
|
||||||
For operations that take time and should be cancellable. `BorderedLoader` shows a spinner and handles escape to cancel.
|
For operations that take time and should be cancellable. `BorderedLoader` shows a spinner and handles escape to cancel.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { BorderedLoader } from "@mariozechner/pi-coding-agent";
|
import { BorderedLoader } from "@mariozechner/companion-coding-agent";
|
||||||
|
|
||||||
pi.registerCommand("fetch", {
|
companion.registerCommand("fetch", {
|
||||||
handler: async (_args, ctx) => {
|
handler: async (_args, ctx) => {
|
||||||
const result = await ctx.ui.custom<string | null>(
|
const result = await ctx.ui.custom<string | null>(
|
||||||
(tui, theme, _kb, done) => {
|
(tui, theme, _kb, done) => {
|
||||||
|
|
@ -722,18 +722,18 @@ pi.registerCommand("fetch", {
|
||||||
|
|
||||||
### Pattern 3: Settings/Toggles (SettingsList)
|
### Pattern 3: Settings/Toggles (SettingsList)
|
||||||
|
|
||||||
For toggling multiple settings. Use `SettingsList` from `@mariozechner/pi-tui` with `getSettingsListTheme()`.
|
For toggling multiple settings. Use `SettingsList` from `@mariozechner/companion-tui` with `getSettingsListTheme()`.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { getSettingsListTheme } from "@mariozechner/pi-coding-agent";
|
import { getSettingsListTheme } from "@mariozechner/companion-coding-agent";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
type SettingItem,
|
type SettingItem,
|
||||||
SettingsList,
|
SettingsList,
|
||||||
Text,
|
Text,
|
||||||
} from "@mariozechner/pi-tui";
|
} from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
pi.registerCommand("settings", {
|
companion.registerCommand("settings", {
|
||||||
handler: async (_args, ctx) => {
|
handler: async (_args, ctx) => {
|
||||||
const items: SettingItem[] = [
|
const items: SettingItem[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -854,8 +854,8 @@ Token stats available via `ctx.sessionManager.getBranch()` and `ctx.model`.
|
||||||
Replace the main input editor with a custom implementation. Useful for modal editing (vim), different keybindings (emacs), or specialized input handling.
|
Replace the main input editor with a custom implementation. Useful for modal editing (vim), different keybindings (emacs), or specialized input handling.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { CustomEditor, type ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
import { CustomEditor, type ExtensionAPI } from "@mariozechner/companion-coding-agent";
|
||||||
import { matchesKey, truncateToWidth } from "@mariozechner/pi-tui";
|
import { matchesKey, truncateToWidth } from "@mariozechner/companion-tui";
|
||||||
|
|
||||||
type Mode = "normal" | "insert";
|
type Mode = "normal" | "insert";
|
||||||
|
|
||||||
|
|
@ -917,8 +917,8 @@ class VimEditor extends CustomEditor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (pi: ExtensionAPI) {
|
export default function (companion: ExtensionAPI) {
|
||||||
pi.on("session_start", (_event, ctx) => {
|
companion.on("session_start", (_event, ctx) => {
|
||||||
// Factory receives theme and keybindings from the app
|
// Factory receives theme and keybindings from the app
|
||||||
ctx.ui.setEditorComponent(
|
ctx.ui.setEditorComponent(
|
||||||
(tui, theme, keybindings) => new VimEditor(theme, keybindings),
|
(tui, theme, keybindings) => new VimEditor(theme, keybindings),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# Windows Setup
|
# Windows Setup
|
||||||
|
|
||||||
Pi requires a bash shell on Windows. Checked locations (in order):
|
Companion requires a bash shell on Windows. Checked locations (in order):
|
||||||
|
|
||||||
1. Custom path from `~/.pi/agent/settings.json`
|
1. Custom path from `~/.companion/agent/settings.json`
|
||||||
2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
|
2. Git Bash (`C:\Program Files\Git\bin\bash.exe`)
|
||||||
3. `bash.exe` on PATH (Cygwin, MSYS2, WSL)
|
3. `bash.exe` on PATH (Cygwin, MSYS2, WSL)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
"name": "@mariozechner/pi-coding-agent",
|
"name": "@mariozechner/companion-coding-agent",
|
||||||
"version": "0.56.2",
|
"version": "0.56.2",
|
||||||
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"piConfig": {
|
"companionConfig": {
|
||||||
"name": "pi",
|
"name": "companion",
|
||||||
"configDir": ".pi"
|
"configDir": ".companion"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"pi": "dist/cli.js"
|
"companion": "dist/cli.js"
|
||||||
},
|
},
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
"clean": "shx rm -rf dist",
|
"clean": "shx rm -rf dist",
|
||||||
"dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
|
"dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
|
||||||
"build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && npm run copy-assets",
|
"build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && npm run copy-assets",
|
||||||
"build:binary": "npm --prefix ../tui run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/cli.js --outfile dist/pi && npm run copy-binary-assets",
|
"build:binary": "npm --prefix ../tui run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile ./dist/cli.js --outfile dist/companion && npm run copy-binary-assets",
|
||||||
"copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
|
"copy-assets": "shx mkdir -p dist/modes/interactive/theme && shx cp src/modes/interactive/theme/*.json dist/modes/interactive/theme/ && shx mkdir -p dist/core/export-html/vendor && shx cp src/core/export-html/template.html src/core/export-html/template.css src/core/export-html/template.js dist/core/export-html/ && shx cp src/core/export-html/vendor/*.js dist/core/export-html/vendor/",
|
||||||
"copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
|
"copy-binary-assets": "shx cp package.json dist/ && shx cp README.md dist/ && shx cp CHANGELOG.md dist/ && shx mkdir -p dist/theme && shx cp src/modes/interactive/theme/*.json dist/theme/ && shx mkdir -p dist/export-html/vendor && shx cp src/core/export-html/template.html dist/export-html/ && shx cp src/core/export-html/vendor/*.js dist/export-html/vendor/ && shx cp -r docs dist/ && shx cp -r examples dist/ && shx cp ../../node_modules/@silvia-odwyer/photon-node/photon_rs_bg.wasm dist/",
|
||||||
"test": "vitest --run",
|
"test": "vitest --run",
|
||||||
|
|
@ -40,9 +40,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mariozechner/jiti": "^2.6.2",
|
"@mariozechner/jiti": "^2.6.2",
|
||||||
"@mariozechner/pi-agent-core": "^0.56.2",
|
"@mariozechner/companion-agent-core": "^0.56.2",
|
||||||
"@mariozechner/pi-ai": "^0.56.2",
|
"@mariozechner/companion-ai": "^0.56.2",
|
||||||
"@mariozechner/pi-tui": "^0.56.2",
|
"@mariozechner/companion-tui": "^0.56.2",
|
||||||
"@silvia-odwyer/photon-node": "^0.3.4",
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
||||||
"chalk": "^5.5.0",
|
"chalk": "^5.5.0",
|
||||||
"cli-highlight": "^2.1.11",
|
"cli-highlight": "^2.1.11",
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.
|
# Migrate sessions from ~/.companion/agent/*.jsonl to proper session directories.
|
||||||
# This fixes sessions created by the bug in v0.30.0 where sessions were
|
# This fixes sessions created by the bug in v0.30.0 where sessions were
|
||||||
# saved to ~/.pi/agent/ instead of ~/.pi/agent/sessions/<encoded-cwd>/.
|
# saved to ~/.companion/agent/ instead of ~/.companion/agent/sessions/<encoded-cwd>/.
|
||||||
#
|
#
|
||||||
# Usage: ./migrate-sessions.sh [--dry-run]
|
# Usage: ./migrate-sessions.sh [--dry-run]
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
AGENT_DIR="${PI_AGENT_DIR:-$HOME/.pi/agent}"
|
AGENT_DIR="${COMPANION_AGENT_DIR:-$HOME/.companion/agent}"
|
||||||
DRY_RUN=false
|
DRY_RUN=false
|
||||||
|
|
||||||
if [[ "$1" == "--dry-run" ]]; then
|
if [[ "$1" == "--dry-run" ]]; then
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
*
|
*
|
||||||
* Test with: npx tsx src/cli-new.ts [args...]
|
* Test with: npx tsx src/cli-new.ts [args...]
|
||||||
*/
|
*/
|
||||||
process.title = "pi";
|
process.title = "companion";
|
||||||
|
|
||||||
import { bedrockProviderModule } from "@mariozechner/pi-ai/bedrock-provider";
|
import { bedrockProviderModule } from "@mariozechner/companion-ai/bedrock-provider";
|
||||||
import { setBedrockProviderModule } from "@mariozechner/pi-ai";
|
import { setBedrockProviderModule } from "@mariozechner/companion-ai";
|
||||||
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
|
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
|
||||||
import { main } from "./main.js";
|
import { main } from "./main.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* CLI argument parsing and help display
|
* CLI argument parsing and help display
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
|
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
|
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
|
||||||
import {
|
import {
|
||||||
|
|
@ -245,7 +245,7 @@ ${chalk.bold("Options:")}
|
||||||
--export <file> Export session file to HTML and exit
|
--export <file> Export session file to HTML and exit
|
||||||
--list-models [search] List available models (with optional fuzzy search)
|
--list-models [search] List available models (with optional fuzzy search)
|
||||||
--verbose Force verbose startup (overrides quietStartup setting)
|
--verbose Force verbose startup (overrides quietStartup setting)
|
||||||
--offline Disable startup network operations (same as PI_OFFLINE=1)
|
--offline Disable startup network operations (same as COMPANION_OFFLINE=1)
|
||||||
--help, -h Show this help
|
--help, -h Show this help
|
||||||
--version, -v Show version number
|
--version, -v Show version number
|
||||||
|
|
||||||
|
|
@ -324,10 +324,10 @@ ${chalk.bold("Environment Variables:")}
|
||||||
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
|
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
|
||||||
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
|
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
|
||||||
${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
||||||
PI_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
COMPANION_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
||||||
PI_OFFLINE - Disable startup network operations when set to 1/true/yes
|
COMPANION_OFFLINE - Disable startup network operations when set to 1/true/yes
|
||||||
PI_SHARE_VIEWER_URL - Base URL for /share command (default: https://pi.dev/session/)
|
COMPANION_SHARE_VIEWER_URL - Base URL for /share command (default: https://companion.dev/session/)
|
||||||
PI_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)
|
COMPANION_AI_ANTIGRAVITY_VERSION - Override Antigravity User-Agent version (e.g., 1.23.0)
|
||||||
|
|
||||||
${chalk.bold(`Available Tools (default: ${defaultToolsText}):`)}
|
${chalk.bold(`Available Tools (default: ${defaultToolsText}):`)}
|
||||||
read - Read file contents
|
read - Read file contents
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* TUI config selector for `pi config` command
|
* TUI config selector for `companion config` command
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ProcessTerminal, TUI } from "@mariozechner/pi-tui";
|
import { ProcessTerminal, TUI } from "@mariozechner/companion-tui";
|
||||||
import type { ResolvedPaths } from "../core/package-manager.js";
|
import type { ResolvedPaths } from "../core/package-manager.js";
|
||||||
import type { SettingsManager } from "../core/settings-manager.js";
|
import type { SettingsManager } from "../core/settings-manager.js";
|
||||||
import { ConfigSelectorComponent } from "../modes/interactive/components/config-selector.js";
|
import { ConfigSelectorComponent } from "../modes/interactive/components/config-selector.js";
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { access, readFile, stat } from "node:fs/promises";
|
import { access, readFile, stat } from "node:fs/promises";
|
||||||
import type { ImageContent } from "@mariozechner/pi-ai";
|
import type { ImageContent } from "@mariozechner/companion-ai";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
import { resolveReadPath } from "../core/tools/path-utils.js";
|
import { resolveReadPath } from "../core/tools/path-utils.js";
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
* List available models with optional fuzzy search
|
* List available models with optional fuzzy search
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Api, Model } from "@mariozechner/pi-ai";
|
import type { Api, Model } from "@mariozechner/companion-ai";
|
||||||
import { fuzzyFilter } from "@mariozechner/pi-tui";
|
import { fuzzyFilter } from "@mariozechner/companion-tui";
|
||||||
import type { ModelRegistry } from "../core/model-registry.js";
|
import type { ModelRegistry } from "../core/model-registry.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* TUI session selector for --resume flag
|
* TUI session selector for --resume flag
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ProcessTerminal, TUI } from "@mariozechner/pi-tui";
|
import { ProcessTerminal, TUI } from "@mariozechner/companion-tui";
|
||||||
import { KeybindingsManager } from "../core/keybindings.js";
|
import { KeybindingsManager } from "../core/keybindings.js";
|
||||||
import type {
|
import type {
|
||||||
SessionInfo,
|
SessionInfo,
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ export function getUpdateInstruction(packageName: string): string {
|
||||||
const method = detectInstallMethod();
|
const method = detectInstallMethod();
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case "bun-binary":
|
case "bun-binary":
|
||||||
return `Download from: https://github.com/badlogic/pi-mono/releases/latest`;
|
return `Download from: https://github.com/badlogic/companion-mono/releases/latest`;
|
||||||
case "pnpm":
|
case "pnpm":
|
||||||
return `Run: pnpm install -g ${packageName}`;
|
return `Run: pnpm install -g ${packageName}`;
|
||||||
case "yarn":
|
case "yarn":
|
||||||
|
|
@ -99,7 +99,7 @@ export function getUpdateInstruction(packageName: string): string {
|
||||||
*/
|
*/
|
||||||
export function getPackageDir(): string {
|
export function getPackageDir(): string {
|
||||||
// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)
|
// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)
|
||||||
const envDir = process.env.PI_PACKAGE_DIR;
|
const envDir = process.env.COMPANION_PACKAGE_DIR;
|
||||||
if (envDir) {
|
if (envDir) {
|
||||||
if (envDir === "~") return homedir();
|
if (envDir === "~") return homedir();
|
||||||
if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
|
if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
|
||||||
|
|
@ -174,31 +174,32 @@ export function getChangelogPath(): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// App Config (from package.json piConfig)
|
// App Config (from package.json companionConfig)
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
const pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
|
const pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
|
||||||
|
|
||||||
export const APP_NAME: string = pkg.piConfig?.name || "pi";
|
export const APP_NAME: string = pkg.companionConfig?.name || "companion";
|
||||||
export const CONFIG_DIR_NAME: string = pkg.piConfig?.configDir || ".pi";
|
export const CONFIG_DIR_NAME: string =
|
||||||
|
pkg.companionConfig?.configDir || ".companion";
|
||||||
export const VERSION: string = pkg.version;
|
export const VERSION: string = pkg.version;
|
||||||
|
|
||||||
// e.g., PI_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR
|
// e.g., COMPANION_CODING_AGENT_DIR or TAU_CODING_AGENT_DIR
|
||||||
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
|
export const ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`;
|
||||||
|
|
||||||
const DEFAULT_SHARE_VIEWER_URL = "https://pi.dev/session/";
|
const DEFAULT_SHARE_VIEWER_URL = "https://companion.dev/session/";
|
||||||
|
|
||||||
/** Get the share viewer URL for a gist ID */
|
/** Get the share viewer URL for a gist ID */
|
||||||
export function getShareViewerUrl(gistId: string): string {
|
export function getShareViewerUrl(gistId: string): string {
|
||||||
const baseUrl = process.env.PI_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;
|
const baseUrl = process.env.COMPANION_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;
|
||||||
return `${baseUrl}#${gistId}`;
|
return `${baseUrl}#${gistId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// User Config Paths (~/.pi/agent/*)
|
// User Config Paths (~/.companion/agent/*)
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
/** Get the agent config directory (e.g., ~/.pi/agent/) */
|
/** Get the agent config directory (e.g., ~/.companion/agent/) */
|
||||||
export function getAgentDir(): string {
|
export function getAgentDir(): string {
|
||||||
const envDir = process.env[ENV_AGENT_DIR];
|
const envDir = process.env[ENV_AGENT_DIR];
|
||||||
if (envDir) {
|
if (envDir) {
|
||||||
|
|
|
||||||
|
|
@ -22,20 +22,20 @@ import type {
|
||||||
AgentState,
|
AgentState,
|
||||||
AgentTool,
|
AgentTool,
|
||||||
ThinkingLevel,
|
ThinkingLevel,
|
||||||
} from "@mariozechner/pi-agent-core";
|
} from "@mariozechner/companion-agent-core";
|
||||||
import type {
|
import type {
|
||||||
AssistantMessage,
|
AssistantMessage,
|
||||||
ImageContent,
|
ImageContent,
|
||||||
Message,
|
Message,
|
||||||
Model,
|
Model,
|
||||||
TextContent,
|
TextContent,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import {
|
import {
|
||||||
isContextOverflow,
|
isContextOverflow,
|
||||||
modelsAreEqual,
|
modelsAreEqual,
|
||||||
resetApiProviders,
|
resetApiProviders,
|
||||||
supportsXhigh,
|
supportsXhigh,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import { getDocsPath } from "../config.js";
|
import { getDocsPath } from "../config.js";
|
||||||
import { theme } from "../modes/interactive/theme/theme.js";
|
import { theme } from "../modes/interactive/theme/theme.js";
|
||||||
import { stripFrontmatter } from "../utils/frontmatter.js";
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
||||||
|
|
@ -1023,7 +1023,7 @@ export class AgentSession {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a prompt to the agent.
|
* Send a prompt to the agent.
|
||||||
* - Handles extension commands (registered via pi.registerCommand) immediately, even during streaming
|
* - Handles extension commands (registered via companion.registerCommand) immediately, even during streaming
|
||||||
* - Expands file-based prompt templates by default
|
* - Expands file-based prompt templates by default
|
||||||
* - During streaming, queues via steer() or followUp() based on streamingBehavior option
|
* - During streaming, queues via steer() or followUp() based on streamingBehavior option
|
||||||
* - Validates model and API key before sending (when not streaming)
|
* - Validates model and API key before sending (when not streaming)
|
||||||
|
|
@ -1034,7 +1034,7 @@ export class AgentSession {
|
||||||
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
||||||
|
|
||||||
// Handle extension commands first (execute immediately, even during streaming)
|
// Handle extension commands first (execute immediately, even during streaming)
|
||||||
// Extension commands manage their own LLM interaction via pi.sendMessage()
|
// Extension commands manage their own LLM interaction via companion.sendMessage()
|
||||||
if (expandPromptTemplates && text.startsWith("/")) {
|
if (expandPromptTemplates && text.startsWith("/")) {
|
||||||
const handled = await this._tryExecuteExtensionCommand(text);
|
const handled = await this._tryExecuteExtensionCommand(text);
|
||||||
if (handled) {
|
if (handled) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* Credential storage for API keys and OAuth tokens.
|
* Credential storage for API keys and OAuth tokens.
|
||||||
* Handles loading, saving, and refreshing credentials from auth.json.
|
* Handles loading, saving, and refreshing credentials from auth.json.
|
||||||
*
|
*
|
||||||
* Uses file locking to prevent race conditions when multiple pi instances
|
* Uses file locking to prevent race conditions when multiple companion instances
|
||||||
* try to refresh tokens simultaneously.
|
* try to refresh tokens simultaneously.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -11,12 +11,12 @@ import {
|
||||||
type OAuthCredentials,
|
type OAuthCredentials,
|
||||||
type OAuthLoginCallbacks,
|
type OAuthLoginCallbacks,
|
||||||
type OAuthProviderId,
|
type OAuthProviderId,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import {
|
import {
|
||||||
getOAuthApiKey,
|
getOAuthApiKey,
|
||||||
getOAuthProvider,
|
getOAuthProvider,
|
||||||
getOAuthProviders,
|
getOAuthProviders,
|
||||||
} from "@mariozechner/pi-ai/oauth";
|
} from "@mariozechner/companion-ai/oauth";
|
||||||
import {
|
import {
|
||||||
chmodSync,
|
chmodSync,
|
||||||
existsSync,
|
existsSync,
|
||||||
|
|
@ -373,7 +373,7 @@ export class AuthStorage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh OAuth token with backend locking to prevent race conditions.
|
* Refresh OAuth token with backend locking to prevent race conditions.
|
||||||
* Multiple pi instances may try to refresh simultaneously when tokens expire.
|
* Multiple companion instances may try to refresh simultaneously when tokens expire.
|
||||||
*/
|
*/
|
||||||
private async refreshOAuthTokenWithLock(
|
private async refreshOAuthTokenWithLock(
|
||||||
providerId: OAuthProviderId,
|
providerId: OAuthProviderId,
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ export function executeBash(
|
||||||
// Start writing to temp file if exceeds threshold
|
// Start writing to temp file if exceeds threshold
|
||||||
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
|
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
|
||||||
const id = randomBytes(8).toString("hex");
|
const id = randomBytes(8).toString("hex");
|
||||||
tempFilePath = join(tmpdir(), `pi-bash-${id}.log`);
|
tempFilePath = join(tmpdir(), `companion-bash-${id}.log`);
|
||||||
tempFileStream = createWriteStream(tempFilePath);
|
tempFileStream = createWriteStream(tempFilePath);
|
||||||
// Write already-buffered chunks to temp file
|
// Write already-buffered chunks to temp file
|
||||||
for (const chunk of outputChunks) {
|
for (const chunk of outputChunks) {
|
||||||
|
|
@ -223,7 +223,7 @@ export async function executeBashWithOperations(
|
||||||
// Start writing to temp file if exceeds threshold
|
// Start writing to temp file if exceeds threshold
|
||||||
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
|
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
|
||||||
const id = randomBytes(8).toString("hex");
|
const id = randomBytes(8).toString("hex");
|
||||||
tempFilePath = join(tmpdir(), `pi-bash-${id}.log`);
|
tempFilePath = join(tmpdir(), `companion-bash-${id}.log`);
|
||||||
tempFileStream = createWriteStream(tempFilePath);
|
tempFileStream = createWriteStream(tempFilePath);
|
||||||
for (const chunk of outputChunks) {
|
for (const chunk of outputChunks) {
|
||||||
tempFileStream.write(chunk);
|
tempFileStream.write(chunk);
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
* a summary of the branch being left so context isn't lost.
|
* a summary of the branch being left so context isn't lost.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import type { Model } from "@mariozechner/pi-ai";
|
import type { Model } from "@mariozechner/companion-ai";
|
||||||
import { completeSimple } from "@mariozechner/pi-ai";
|
import { completeSimple } from "@mariozechner/companion-ai";
|
||||||
import {
|
import {
|
||||||
convertToLlm,
|
convertToLlm,
|
||||||
createBranchSummaryMessage,
|
createBranchSummaryMessage,
|
||||||
|
|
@ -206,7 +206,7 @@ export function prepareBranchEntries(
|
||||||
|
|
||||||
// First pass: collect file ops from ALL entries (even if they don't fit in token budget)
|
// First pass: collect file ops from ALL entries (even if they don't fit in token budget)
|
||||||
// This ensures we capture cumulative file tracking from nested branch summaries
|
// This ensures we capture cumulative file tracking from nested branch summaries
|
||||||
// Only extract from pi-generated summaries (fromHook !== true), not extension-generated ones
|
// Only extract from companion-generated summaries (fromHook !== true), not extension-generated ones
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.type === "branch_summary" && !entry.fromHook && entry.details) {
|
if (entry.type === "branch_summary" && !entry.fromHook && entry.details) {
|
||||||
const details = entry.details as BranchSummaryDetails;
|
const details = entry.details as BranchSummaryDetails;
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
* and after compaction the session is reloaded.
|
* and after compaction the session is reloaded.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import type { AssistantMessage, Model, Usage } from "@mariozechner/pi-ai";
|
import type { AssistantMessage, Model, Usage } from "@mariozechner/companion-ai";
|
||||||
import { completeSimple } from "@mariozechner/pi-ai";
|
import { completeSimple } from "@mariozechner/companion-ai";
|
||||||
import {
|
import {
|
||||||
convertToLlm,
|
convertToLlm,
|
||||||
createBranchSummaryMessage,
|
createBranchSummaryMessage,
|
||||||
|
|
@ -45,7 +45,7 @@ function extractFileOperations(
|
||||||
): FileOperations {
|
): FileOperations {
|
||||||
const fileOps = createFileOps();
|
const fileOps = createFileOps();
|
||||||
|
|
||||||
// Collect from previous compaction's details (if pi-generated)
|
// Collect from previous compaction's details (if companion-generated)
|
||||||
if (prevCompactionIndex >= 0) {
|
if (prevCompactionIndex >= 0) {
|
||||||
const prevCompaction = entries[prevCompactionIndex] as CompactionEntry;
|
const prevCompaction = entries[prevCompactionIndex] as CompactionEntry;
|
||||||
if (!prevCompaction.fromHook && prevCompaction.details) {
|
if (!prevCompaction.fromHook && prevCompaction.details) {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
* Shared utilities for compaction and branch summarization.
|
* Shared utilities for compaction and branch summarization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import type { Message } from "@mariozechner/pi-ai";
|
import type { Message } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// File Operation Tracking
|
// File Operation Tracking
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
|
import type { ThinkingLevel } from "@mariozechner/companion-agent-core";
|
||||||
|
|
||||||
export const DEFAULT_THINKING_LEVEL: ThinkingLevel = "medium";
|
export const DEFAULT_THINKING_LEVEL: ThinkingLevel = "medium";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { AgentState } from "@mariozechner/pi-agent-core";
|
import type { AgentState } from "@mariozechner/companion-agent-core";
|
||||||
import { existsSync, readFileSync, writeFileSync } from "fs";
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
||||||
import { basename, join } from "path";
|
import { basename, join } from "path";
|
||||||
import { APP_NAME, getExportTemplateDir } from "../../config.js";
|
import { APP_NAME, getExportTemplateDir } from "../../config.js";
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
// Parse URL parameters for deep linking: leafId and targetId
|
// Parse URL parameters for deep linking: leafId and targetId
|
||||||
// Check for injected params (when loaded in iframe via srcdoc) or use window.location
|
// Check for injected params (when loaded in iframe via srcdoc) or use window.location
|
||||||
const injectedParams = document.querySelector('meta[name="pi-url-params"]');
|
const injectedParams = document.querySelector('meta[name="companion-url-params"]');
|
||||||
const searchString = injectedParams
|
const searchString = injectedParams
|
||||||
? injectedParams.content
|
? injectedParams.content
|
||||||
: window.location.search.substring(1);
|
: window.location.search.substring(1);
|
||||||
|
|
@ -1227,7 +1227,7 @@
|
||||||
function buildShareUrl(entryId) {
|
function buildShareUrl(entryId) {
|
||||||
// Check for injected base URL (used when loaded in iframe via srcdoc)
|
// Check for injected base URL (used when loaded in iframe via srcdoc)
|
||||||
const baseUrlMeta = document.querySelector(
|
const baseUrlMeta = document.querySelector(
|
||||||
'meta[name="pi-share-base-url"]',
|
'meta[name="companion-share-base-url"]',
|
||||||
);
|
);
|
||||||
const baseUrl = baseUrlMeta
|
const baseUrl = baseUrlMeta
|
||||||
? baseUrlMeta.content
|
? baseUrlMeta.content
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* and converting the ANSI output to HTML.
|
* and converting the ANSI output to HTML.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ImageContent, TextContent } from "@mariozechner/pi-ai";
|
import type { ImageContent, TextContent } from "@mariozechner/companion-ai";
|
||||||
import type { Theme } from "../../modes/interactive/theme/theme.js";
|
import type { Theme } from "../../modes/interactive/theme/theme.js";
|
||||||
import type { ToolDefinition } from "../extensions/types.js";
|
import type { ToolDefinition } from "../extensions/types.js";
|
||||||
import { ansiLinesToHtml } from "./ansi-to-html.js";
|
import { ansiLinesToHtml } from "./ansi-to-html.js";
|
||||||
|
|
|
||||||
|
|
@ -4864,7 +4864,7 @@ var hljs = (function () {
|
||||||
keyword:
|
keyword:
|
||||||
"and break do else elseif end for goto if in local not or repeat return then until while",
|
"and break do else elseif end for goto if in local not or repeat return then until while",
|
||||||
built_in:
|
built_in:
|
||||||
"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove",
|
"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp companion cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove",
|
||||||
},
|
},
|
||||||
contains: i.concat([
|
contains: i.concat([
|
||||||
{
|
{
|
||||||
|
|
@ -6293,7 +6293,7 @@ var hljs = (function () {
|
||||||
literal:
|
literal:
|
||||||
"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10",
|
"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10",
|
||||||
built_in:
|
built_in:
|
||||||
"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm",
|
"LETTERS letters month.abb month.name companion T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm",
|
||||||
},
|
},
|
||||||
contains: [
|
contains: [
|
||||||
e.COMMENT(/#'/, /$/, {
|
e.COMMENT(/#'/, /$/, {
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,18 @@ import * as os from "node:os";
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { createJiti } from "@mariozechner/jiti";
|
import { createJiti } from "@mariozechner/jiti";
|
||||||
import * as _bundledPiAgentCore from "@mariozechner/pi-agent-core";
|
import * as _bundledPiAgentCore from "@mariozechner/companion-agent-core";
|
||||||
import * as _bundledPiAi from "@mariozechner/pi-ai";
|
import * as _bundledPiAi from "@mariozechner/companion-ai";
|
||||||
import * as _bundledPiAiOauth from "@mariozechner/pi-ai/oauth";
|
import * as _bundledPiAiOauth from "@mariozechner/companion-ai/oauth";
|
||||||
import type { KeyId } from "@mariozechner/pi-tui";
|
import type { KeyId } from "@mariozechner/companion-tui";
|
||||||
import * as _bundledPiTui from "@mariozechner/pi-tui";
|
import * as _bundledPiTui from "@mariozechner/companion-tui";
|
||||||
// Static imports of packages that extensions may use.
|
// Static imports of packages that extensions may use.
|
||||||
// These MUST be static so Bun bundles them into the compiled binary.
|
// These MUST be static so Bun bundles them into the compiled binary.
|
||||||
// The virtualModules option then makes them available to extensions.
|
// The virtualModules option then makes them available to extensions.
|
||||||
import * as _bundledTypebox from "@sinclair/typebox";
|
import * as _bundledTypebox from "@sinclair/typebox";
|
||||||
import { getAgentDir, isBunBinary } from "../../config.js";
|
import { getAgentDir, isBunBinary } from "../../config.js";
|
||||||
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
// NOTE: This import works because loader.ts exports are NOT re-exported from index.ts,
|
||||||
// avoiding a circular dependency. Extensions can import from @mariozechner/pi-coding-agent.
|
// avoiding a circular dependency. Extensions can import from @mariozechner/companion-coding-agent.
|
||||||
import * as _bundledPiCodingAgent from "../../index.js";
|
import * as _bundledPiCodingAgent from "../../index.js";
|
||||||
import { createEventBus, type EventBus } from "../event-bus.js";
|
import { createEventBus, type EventBus } from "../event-bus.js";
|
||||||
import type { ExecOptions } from "../exec.js";
|
import type { ExecOptions } from "../exec.js";
|
||||||
|
|
@ -41,11 +41,11 @@ import type {
|
||||||
/** Modules available to extensions via virtualModules (for compiled Bun binary) */
|
/** Modules available to extensions via virtualModules (for compiled Bun binary) */
|
||||||
const VIRTUAL_MODULES: Record<string, unknown> = {
|
const VIRTUAL_MODULES: Record<string, unknown> = {
|
||||||
"@sinclair/typebox": _bundledTypebox,
|
"@sinclair/typebox": _bundledTypebox,
|
||||||
"@mariozechner/pi-agent-core": _bundledPiAgentCore,
|
"@mariozechner/companion-agent-core": _bundledPiAgentCore,
|
||||||
"@mariozechner/pi-tui": _bundledPiTui,
|
"@mariozechner/companion-tui": _bundledPiTui,
|
||||||
"@mariozechner/pi-ai": _bundledPiAi,
|
"@mariozechner/companion-ai": _bundledPiAi,
|
||||||
"@mariozechner/pi-ai/oauth": _bundledPiAiOauth,
|
"@mariozechner/companion-ai/oauth": _bundledPiAiOauth,
|
||||||
"@mariozechner/pi-coding-agent": _bundledPiCodingAgent,
|
"@mariozechner/companion-coding-agent": _bundledPiCodingAgent,
|
||||||
};
|
};
|
||||||
|
|
||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
|
|
@ -80,22 +80,22 @@ function getAliases(): Record<string, string> {
|
||||||
};
|
};
|
||||||
|
|
||||||
_aliases = {
|
_aliases = {
|
||||||
"@mariozechner/pi-coding-agent": packageIndex,
|
"@mariozechner/companion-coding-agent": packageIndex,
|
||||||
"@mariozechner/pi-agent-core": resolveWorkspaceOrImport(
|
"@mariozechner/companion-agent-core": resolveWorkspaceOrImport(
|
||||||
"agent/dist/index.js",
|
"agent/dist/index.js",
|
||||||
"@mariozechner/pi-agent-core",
|
"@mariozechner/companion-agent-core",
|
||||||
),
|
),
|
||||||
"@mariozechner/pi-tui": resolveWorkspaceOrImport(
|
"@mariozechner/companion-tui": resolveWorkspaceOrImport(
|
||||||
"tui/dist/index.js",
|
"tui/dist/index.js",
|
||||||
"@mariozechner/pi-tui",
|
"@mariozechner/companion-tui",
|
||||||
),
|
),
|
||||||
"@mariozechner/pi-ai": resolveWorkspaceOrImport(
|
"@mariozechner/companion-ai": resolveWorkspaceOrImport(
|
||||||
"ai/dist/index.js",
|
"ai/dist/index.js",
|
||||||
"@mariozechner/pi-ai",
|
"@mariozechner/companion-ai",
|
||||||
),
|
),
|
||||||
"@mariozechner/pi-ai/oauth": resolveWorkspaceOrImport(
|
"@mariozechner/companion-ai/oauth": resolveWorkspaceOrImport(
|
||||||
"ai/dist/oauth.js",
|
"ai/dist/oauth.js",
|
||||||
"@mariozechner/pi-ai/oauth",
|
"@mariozechner/companion-ai/oauth",
|
||||||
),
|
),
|
||||||
"@sinclair/typebox": typeboxRoot,
|
"@sinclair/typebox": typeboxRoot,
|
||||||
};
|
};
|
||||||
|
|
@ -454,8 +454,8 @@ function readPiManifest(packageJsonPath: string): PiManifest | null {
|
||||||
try {
|
try {
|
||||||
const content = fs.readFileSync(packageJsonPath, "utf-8");
|
const content = fs.readFileSync(packageJsonPath, "utf-8");
|
||||||
const pkg = JSON.parse(content);
|
const pkg = JSON.parse(content);
|
||||||
if (pkg.pi && typeof pkg.pi === "object") {
|
if (pkg.companion && typeof pkg.companion === "object") {
|
||||||
return pkg.pi as PiManifest;
|
return pkg.companion as PiManifest;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} catch {
|
} catch {
|
||||||
|
|
@ -471,13 +471,13 @@ function isExtensionFile(name: string): boolean {
|
||||||
* Resolve extension entry points from a directory.
|
* Resolve extension entry points from a directory.
|
||||||
*
|
*
|
||||||
* Checks for:
|
* Checks for:
|
||||||
* 1. package.json with "pi.extensions" field -> returns declared paths
|
* 1. package.json with "companion.extensions" field -> returns declared paths
|
||||||
* 2. index.ts or index.js -> returns the index file
|
* 2. index.ts or index.js -> returns the index file
|
||||||
*
|
*
|
||||||
* Returns resolved paths or null if no entry points found.
|
* Returns resolved paths or null if no entry points found.
|
||||||
*/
|
*/
|
||||||
function resolveExtensionEntries(dir: string): string[] | null {
|
function resolveExtensionEntries(dir: string): string[] | null {
|
||||||
// Check for package.json with "pi" field first
|
// Check for package.json with "companion" field first
|
||||||
const packageJsonPath = path.join(dir, "package.json");
|
const packageJsonPath = path.join(dir, "package.json");
|
||||||
if (fs.existsSync(packageJsonPath)) {
|
if (fs.existsSync(packageJsonPath)) {
|
||||||
const manifest = readPiManifest(packageJsonPath);
|
const manifest = readPiManifest(packageJsonPath);
|
||||||
|
|
@ -514,7 +514,7 @@ function resolveExtensionEntries(dir: string): string[] | null {
|
||||||
* Discovery rules:
|
* Discovery rules:
|
||||||
* 1. Direct files: `extensions/*.ts` or `*.js` → load
|
* 1. Direct files: `extensions/*.ts` or `*.js` → load
|
||||||
* 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load
|
* 2. Subdirectory with index: `extensions/* /index.ts` or `index.js` → load
|
||||||
* 3. Subdirectory with package.json: `extensions/* /package.json` with "pi" field → load what it declares
|
* 3. Subdirectory with package.json: `extensions/* /package.json` with "companion" field → load what it declares
|
||||||
*
|
*
|
||||||
* No recursion beyond one level. Complex packages must use package.json manifest.
|
* No recursion beyond one level. Complex packages must use package.json manifest.
|
||||||
*/
|
*/
|
||||||
|
|
@ -577,8 +577,8 @@ export async function discoverAndLoadExtensions(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 1. Project-local extensions: cwd/.pi/extensions/
|
// 1. Project-local extensions: cwd/.companion/extensions/
|
||||||
const localExtDir = path.join(cwd, ".pi", "extensions");
|
const localExtDir = path.join(cwd, ".companion", "extensions");
|
||||||
addPaths(discoverExtensionsInDir(localExtDir));
|
addPaths(discoverExtensionsInDir(localExtDir));
|
||||||
|
|
||||||
// 2. Global extensions: agentDir/extensions/
|
// 2. Global extensions: agentDir/extensions/
|
||||||
|
|
@ -589,7 +589,7 @@ export async function discoverAndLoadExtensions(
|
||||||
for (const p of configuredPaths) {
|
for (const p of configuredPaths) {
|
||||||
const resolved = resolvePath(p, cwd);
|
const resolved = resolvePath(p, cwd);
|
||||||
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
|
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {
|
||||||
// Check for package.json with pi manifest or index.ts
|
// Check for package.json with companion manifest or index.ts
|
||||||
const entries = resolveExtensionEntries(resolved);
|
const entries = resolveExtensionEntries(resolved);
|
||||||
if (entries) {
|
if (entries) {
|
||||||
addPaths(entries);
|
addPaths(entries);
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
* Extension runner - executes extensions and manages their lifecycle.
|
* Extension runner - executes extensions and manages their lifecycle.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import type { ImageContent, Model } from "@mariozechner/pi-ai";
|
import type { ImageContent, Model } from "@mariozechner/companion-ai";
|
||||||
import type { KeyId } from "@mariozechner/pi-tui";
|
import type { KeyId } from "@mariozechner/companion-tui";
|
||||||
import { type Theme, theme } from "../../modes/interactive/theme/theme.js";
|
import { type Theme, theme } from "../../modes/interactive/theme/theme.js";
|
||||||
import type { ResourceDiagnostic } from "../diagnostics.js";
|
import type { ResourceDiagnostic } from "../diagnostics.js";
|
||||||
import type { KeyAction, KeybindingsConfig } from "../keybindings.js";
|
import type { KeyAction, KeybindingsConfig } from "../keybindings.js";
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import type {
|
||||||
AgentToolResult,
|
AgentToolResult,
|
||||||
AgentToolUpdateCallback,
|
AgentToolUpdateCallback,
|
||||||
ThinkingLevel,
|
ThinkingLevel,
|
||||||
} from "@mariozechner/pi-agent-core";
|
} from "@mariozechner/companion-agent-core";
|
||||||
import type {
|
import type {
|
||||||
Api,
|
Api,
|
||||||
AssistantMessageEvent,
|
AssistantMessageEvent,
|
||||||
|
|
@ -26,7 +26,7 @@ import type {
|
||||||
SimpleStreamOptions,
|
SimpleStreamOptions,
|
||||||
TextContent,
|
TextContent,
|
||||||
ToolResultMessage,
|
ToolResultMessage,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import type {
|
import type {
|
||||||
AutocompleteItem,
|
AutocompleteItem,
|
||||||
Component,
|
Component,
|
||||||
|
|
@ -36,7 +36,7 @@ import type {
|
||||||
OverlayHandle,
|
OverlayHandle,
|
||||||
OverlayOptions,
|
OverlayOptions,
|
||||||
TUI,
|
TUI,
|
||||||
} from "@mariozechner/pi-tui";
|
} from "@mariozechner/companion-tui";
|
||||||
import type { Static, TSchema } from "@sinclair/typebox";
|
import type { Static, TSchema } from "@sinclair/typebox";
|
||||||
import type { Theme } from "../../modes/interactive/theme/theme.js";
|
import type { Theme } from "../../modes/interactive/theme/theme.js";
|
||||||
import type { BashResult } from "../bash-executor.js";
|
import type { BashResult } from "../bash-executor.js";
|
||||||
|
|
@ -223,12 +223,12 @@ export interface ExtensionUIContext {
|
||||||
* - `keybindings`: KeybindingsManager for app-level keybindings
|
* - `keybindings`: KeybindingsManager for app-level keybindings
|
||||||
*
|
*
|
||||||
* For full app keybinding support (escape, ctrl+d, model switching, etc.),
|
* For full app keybinding support (escape, ctrl+d, model switching, etc.),
|
||||||
* extend `CustomEditor` from `@mariozechner/pi-coding-agent` and call
|
* extend `CustomEditor` from `@mariozechner/companion-coding-agent` and call
|
||||||
* `super.handleInput(data)` for keys you don't handle.
|
* `super.handleInput(data)` for keys you don't handle.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* import { CustomEditor } from "@mariozechner/pi-coding-agent";
|
* import { CustomEditor } from "@mariozechner/companion-coding-agent";
|
||||||
*
|
*
|
||||||
* class VimEditor extends CustomEditor {
|
* class VimEditor extends CustomEditor {
|
||||||
* private mode: "normal" | "insert" = "insert";
|
* private mode: "normal" | "insert" = "insert";
|
||||||
|
|
@ -316,7 +316,7 @@ export interface ExtensionContext {
|
||||||
abort(): void;
|
abort(): void;
|
||||||
/** Whether there are queued messages waiting */
|
/** Whether there are queued messages waiting */
|
||||||
hasPendingMessages(): boolean;
|
hasPendingMessages(): boolean;
|
||||||
/** Gracefully shutdown pi and exit. Available in all contexts. */
|
/** Gracefully shutdown companion and exit. Available in all contexts. */
|
||||||
shutdown(): void;
|
shutdown(): void;
|
||||||
/** Get current context usage for the active model. */
|
/** Get current context usage for the active model. */
|
||||||
getContextUsage(): ContextUsage | undefined;
|
getContextUsage(): ContextUsage | undefined;
|
||||||
|
|
@ -1251,7 +1251,7 @@ export interface ExtensionAPI {
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Register a new provider with custom models
|
* // Register a new provider with custom models
|
||||||
* pi.registerProvider("my-proxy", {
|
* companion.registerProvider("my-proxy", {
|
||||||
* baseUrl: "https://proxy.example.com",
|
* baseUrl: "https://proxy.example.com",
|
||||||
* apiKey: "PROXY_API_KEY",
|
* apiKey: "PROXY_API_KEY",
|
||||||
* api: "anthropic-messages",
|
* api: "anthropic-messages",
|
||||||
|
|
@ -1270,13 +1270,13 @@ export interface ExtensionAPI {
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Override baseUrl for an existing provider
|
* // Override baseUrl for an existing provider
|
||||||
* pi.registerProvider("anthropic", {
|
* companion.registerProvider("anthropic", {
|
||||||
* baseUrl: "https://proxy.example.com"
|
* baseUrl: "https://proxy.example.com"
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Register provider with OAuth support
|
* // Register provider with OAuth support
|
||||||
* pi.registerProvider("corporate-ai", {
|
* companion.registerProvider("corporate-ai", {
|
||||||
* baseUrl: "https://ai.corp.com",
|
* baseUrl: "https://ai.corp.com",
|
||||||
* api: "openai-responses",
|
* api: "openai-responses",
|
||||||
* models: [...],
|
* models: [...],
|
||||||
|
|
@ -1301,7 +1301,7 @@ export interface ExtensionAPI {
|
||||||
* the initial load phase.
|
* the initial load phase.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* pi.unregisterProvider("my-proxy");
|
* companion.unregisterProvider("my-proxy");
|
||||||
*/
|
*/
|
||||||
unregisterProvider(name: string): void;
|
unregisterProvider(name: string): void;
|
||||||
|
|
||||||
|
|
@ -1313,7 +1313,7 @@ export interface ExtensionAPI {
|
||||||
// Provider Registration Types
|
// Provider Registration Types
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
/** Configuration for registering a provider via pi.registerProvider(). */
|
/** Configuration for registering a provider via companion.registerProvider(). */
|
||||||
export interface ProviderConfig {
|
export interface ProviderConfig {
|
||||||
/** Base URL for the API endpoint. Required when defining models. */
|
/** Base URL for the API endpoint. Required when defining models. */
|
||||||
baseUrl?: string;
|
baseUrl?: string;
|
||||||
|
|
@ -1381,7 +1381,7 @@ export interface ProviderModelConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extension factory function type. Supports both sync and async initialization. */
|
/** Extension factory function type. Supports both sync and async initialization. */
|
||||||
export type ExtensionFactory = (pi: ExtensionAPI) => void | Promise<void>;
|
export type ExtensionFactory = (companion: ExtensionAPI) => void | Promise<void>;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Loaded Extension Types
|
// Loaded Extension Types
|
||||||
|
|
@ -1480,7 +1480,7 @@ export interface ExtensionRuntimeState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action implementations for pi.* API methods.
|
* Action implementations for companion.* API methods.
|
||||||
* Provided to runner.initialize(), copied into the shared runtime.
|
* Provided to runner.initialize(), copied into the shared runtime.
|
||||||
*/
|
*/
|
||||||
export interface ExtensionActions {
|
export interface ExtensionActions {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
import type {
|
import type {
|
||||||
AgentTool,
|
AgentTool,
|
||||||
AgentToolUpdateCallback,
|
AgentToolUpdateCallback,
|
||||||
} from "@mariozechner/pi-agent-core";
|
} from "@mariozechner/companion-agent-core";
|
||||||
import type { ExtensionRunner } from "./runner.js";
|
import type { ExtensionRunner } from "./runner.js";
|
||||||
import type { RegisteredTool, ToolCallEventResult } from "./types.js";
|
import type { RegisteredTool, ToolCallEventResult } from "./types.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import type { AgentSession } from "../agent-session.js";
|
import type { AgentSession } from "../agent-session.js";
|
||||||
import type {
|
import type {
|
||||||
GatewayMessageRequest,
|
GatewayMessageRequest,
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ let activeGatewayRuntime: GatewayRuntime | null = null;
|
||||||
|
|
||||||
type JsonRecord = Record<string, unknown>;
|
type JsonRecord = Record<string, unknown>;
|
||||||
|
|
||||||
type PiChannelsSettings = JsonRecord & {
|
type CompanionChannelsSettings = JsonRecord & {
|
||||||
adapters?: Record<string, JsonRecord>;
|
adapters?: Record<string, JsonRecord>;
|
||||||
bridge?: JsonRecord;
|
bridge?: JsonRecord;
|
||||||
slack?: JsonRecord;
|
slack?: JsonRecord;
|
||||||
|
|
@ -1031,7 +1031,7 @@ export class GatewayRuntime {
|
||||||
path.slice(this.config.webhook.basePath.length).replace(/^\/+/, "") ||
|
path.slice(this.config.webhook.basePath.length).replace(/^\/+/, "") ||
|
||||||
"default";
|
"default";
|
||||||
if (this.config.webhook.secret) {
|
if (this.config.webhook.secret) {
|
||||||
const presentedSecret = request.headers["x-pi-webhook-secret"];
|
const presentedSecret = request.headers["x-companion-webhook-secret"];
|
||||||
if (presentedSecret !== this.config.webhook.secret) {
|
if (presentedSecret !== this.config.webhook.secret) {
|
||||||
this.writeJson(response, 401, { error: "Invalid webhook secret" });
|
this.writeJson(response, 401, { error: "Invalid webhook secret" });
|
||||||
return;
|
return;
|
||||||
|
|
@ -1388,7 +1388,7 @@ export class GatewayRuntime {
|
||||||
this.primarySession.settingsManager.applyOverrides(patch as Settings);
|
this.primarySession.settingsManager.applyOverrides(patch as Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPiChannelsSettings(): PiChannelsSettings {
|
private getCompanionChannelsSettings(): CompanionChannelsSettings {
|
||||||
const globalSettings = this.primarySession.settingsManager.getGlobalSettings();
|
const globalSettings = this.primarySession.settingsManager.getGlobalSettings();
|
||||||
const projectSettings =
|
const projectSettings =
|
||||||
this.primarySession.settingsManager.getProjectSettings();
|
this.primarySession.settingsManager.getProjectSettings();
|
||||||
|
|
@ -1396,12 +1396,12 @@ export class GatewayRuntime {
|
||||||
isRecord(globalSettings) ? globalSettings : {},
|
isRecord(globalSettings) ? globalSettings : {},
|
||||||
isRecord(projectSettings) ? projectSettings : {},
|
isRecord(projectSettings) ? projectSettings : {},
|
||||||
);
|
);
|
||||||
const piChannels = mergedSettings["pi-channels"];
|
const piChannels = mergedSettings["companion-channels"];
|
||||||
return isRecord(piChannels) ? (piChannels as PiChannelsSettings) : {};
|
return isRecord(piChannels) ? (piChannels as CompanionChannelsSettings) : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildSlackChannelStatus(
|
private buildSlackChannelStatus(
|
||||||
config: PiChannelsSettings,
|
config: CompanionChannelsSettings,
|
||||||
bridgeEnabled: boolean,
|
bridgeEnabled: boolean,
|
||||||
): ChannelStatus {
|
): ChannelStatus {
|
||||||
const adapters = isRecord(config.adapters) ? config.adapters : {};
|
const adapters = isRecord(config.adapters) ? config.adapters : {};
|
||||||
|
|
@ -1419,13 +1419,13 @@ export class GatewayRuntime {
|
||||||
|
|
||||||
if (hasConfig) {
|
if (hasConfig) {
|
||||||
if (!adapter) {
|
if (!adapter) {
|
||||||
error = 'Slack requires `pi-channels.adapters.slack = { "type": "slack" }`.';
|
error = 'Slack requires `companion-channels.adapters.slack = { "type": "slack" }`.';
|
||||||
} else if (adapterType !== "slack") {
|
} else if (adapterType !== "slack") {
|
||||||
error = 'Slack adapter type must be "slack".';
|
error = 'Slack adapter type must be "slack".';
|
||||||
} else if (!appToken) {
|
} else if (!appToken) {
|
||||||
error = "Slack requires pi-channels.slack.appToken.";
|
error = "Slack requires companion-channels.slack.appToken.";
|
||||||
} else if (!botToken) {
|
} else if (!botToken) {
|
||||||
error = "Slack requires pi-channels.slack.botToken.";
|
error = "Slack requires companion-channels.slack.botToken.";
|
||||||
} else {
|
} else {
|
||||||
configured = true;
|
configured = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1433,7 +1433,7 @@ export class GatewayRuntime {
|
||||||
|
|
||||||
if (configured && !bridgeEnabled) {
|
if (configured && !bridgeEnabled) {
|
||||||
error =
|
error =
|
||||||
"Slack is configured, but pi-channels.bridge.enabled is false, so messages will not reach the agent.";
|
"Slack is configured, but companion-channels.bridge.enabled is false, so messages will not reach the agent.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -1447,7 +1447,7 @@ export class GatewayRuntime {
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildTelegramChannelStatus(
|
private buildTelegramChannelStatus(
|
||||||
config: PiChannelsSettings,
|
config: CompanionChannelsSettings,
|
||||||
bridgeEnabled: boolean,
|
bridgeEnabled: boolean,
|
||||||
): ChannelStatus {
|
): ChannelStatus {
|
||||||
const adapters = isRecord(config.adapters) ? config.adapters : {};
|
const adapters = isRecord(config.adapters) ? config.adapters : {};
|
||||||
|
|
@ -1464,14 +1464,14 @@ export class GatewayRuntime {
|
||||||
if (hasConfig) {
|
if (hasConfig) {
|
||||||
if (!adapter) {
|
if (!adapter) {
|
||||||
error =
|
error =
|
||||||
'Telegram requires `pi-channels.adapters.telegram = { "type": "telegram", "botToken": "...", "polling": true }`.';
|
'Telegram requires `companion-channels.adapters.telegram = { "type": "telegram", "botToken": "...", "polling": true }`.';
|
||||||
} else if (adapterType !== "telegram") {
|
} else if (adapterType !== "telegram") {
|
||||||
error = 'Telegram adapter type must be "telegram".';
|
error = 'Telegram adapter type must be "telegram".';
|
||||||
} else if (!botToken) {
|
} else if (!botToken) {
|
||||||
error = "Telegram requires pi-channels.adapters.telegram.botToken.";
|
error = "Telegram requires companion-channels.adapters.telegram.botToken.";
|
||||||
} else if (!pollingEnabled) {
|
} else if (!pollingEnabled) {
|
||||||
error =
|
error =
|
||||||
"Telegram requires pi-channels.adapters.telegram.polling = true.";
|
"Telegram requires companion-channels.adapters.telegram.polling = true.";
|
||||||
} else {
|
} else {
|
||||||
configured = true;
|
configured = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1479,7 +1479,7 @@ export class GatewayRuntime {
|
||||||
|
|
||||||
if (configured && !bridgeEnabled) {
|
if (configured && !bridgeEnabled) {
|
||||||
error =
|
error =
|
||||||
"Telegram is configured, but pi-channels.bridge.enabled is false, so messages will not reach the agent.";
|
"Telegram is configured, but companion-channels.bridge.enabled is false, so messages will not reach the agent.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
@ -1493,7 +1493,7 @@ export class GatewayRuntime {
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleGetChannelsStatus(): ChannelStatus[] {
|
private handleGetChannelsStatus(): ChannelStatus[] {
|
||||||
const config = this.getPiChannelsSettings();
|
const config = this.getCompanionChannelsSettings();
|
||||||
const bridgeEnabled = config.bridge?.enabled === true;
|
const bridgeEnabled = config.bridge?.enabled === true;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import type { HistoryMessage, HistoryPart } from "./types.js";
|
import type { HistoryMessage, HistoryPart } from "./types.js";
|
||||||
|
|
||||||
export interface GatewayTransientToolResult {
|
export interface GatewayTransientToolResult {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ImageContent } from "@mariozechner/pi-ai";
|
import type { ImageContent } from "@mariozechner/companion-ai";
|
||||||
import type { AgentSession } from "../agent-session.js";
|
import type { AgentSession } from "../agent-session.js";
|
||||||
|
|
||||||
export interface GatewayConfig {
|
export interface GatewayConfig {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {
|
||||||
type KeyId,
|
type KeyId,
|
||||||
matchesKey,
|
matchesKey,
|
||||||
setEditorKeybindings,
|
setEditorKeybindings,
|
||||||
} from "@mariozechner/pi-tui";
|
} from "@mariozechner/companion-tui";
|
||||||
import { existsSync, readFileSync } from "fs";
|
import { existsSync, readFileSync } from "fs";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { getAgentDir } from "../config.js";
|
import { getAgentDir } from "../config.js";
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,17 @@ import {
|
||||||
import { createRequire } from "node:module";
|
import { createRequire } from "node:module";
|
||||||
import { homedir } from "node:os";
|
import { homedir } from "node:os";
|
||||||
import { basename, join, resolve } from "node:path";
|
import { basename, join, resolve } from "node:path";
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import {
|
import {
|
||||||
completeSimple,
|
completeSimple,
|
||||||
type Model,
|
type Model,
|
||||||
type TextContent,
|
type TextContent,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import { parseFrontmatter } from "../../utils/frontmatter.js";
|
import { parseFrontmatter } from "../../utils/frontmatter.js";
|
||||||
import type { SettingsManager } from "../settings-manager.js";
|
import type { SettingsManager } from "../settings-manager.js";
|
||||||
import type { ReadonlySessionManager } from "../session-manager.js";
|
import type { ReadonlySessionManager } from "../session-manager.js";
|
||||||
|
|
||||||
const DEFAULT_STORAGE_DIR = join(homedir(), ".pi", "memory");
|
const DEFAULT_STORAGE_DIR = join(homedir(), ".companion", "memory");
|
||||||
const MAX_EPISODE_CHARS = 4_000;
|
const MAX_EPISODE_CHARS = 4_000;
|
||||||
const MAX_EPISODES = 5_000;
|
const MAX_EPISODES = 5_000;
|
||||||
const DEFAULT_CORE_TOKEN_BUDGET = 700;
|
const DEFAULT_CORE_TOKEN_BUDGET = 700;
|
||||||
|
|
@ -1487,9 +1487,9 @@ function resolveLegacyProjectDir(
|
||||||
cwd: string,
|
cwd: string,
|
||||||
): string | null {
|
): string | null {
|
||||||
const settings = asRecord(settingsManager.getGlobalSettings()) ?? {};
|
const settings = asRecord(settingsManager.getGlobalSettings()) ?? {};
|
||||||
const legacySettings = asRecord(settings["pi-memory-md"]) ?? {};
|
const legacySettings = asRecord(settings["companion-memory-md"]) ?? {};
|
||||||
const configuredRoot =
|
const configuredRoot =
|
||||||
asString(legacySettings.localPath) ?? join(homedir(), ".pi", "memory-md");
|
asString(legacySettings.localPath) ?? join(homedir(), ".companion", "memory-md");
|
||||||
const legacyRoot = expandHomePath(configuredRoot);
|
const legacyRoot = expandHomePath(configuredRoot);
|
||||||
const legacyProjectDir = join(legacyRoot, basename(cwd));
|
const legacyProjectDir = join(legacyRoot, basename(cwd));
|
||||||
if (existsSync(legacyProjectDir)) {
|
if (existsSync(legacyProjectDir)) {
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@
|
||||||
* and provides a transformer to convert them to LLM-compatible messages.
|
* and provides a transformer to convert them to LLM-compatible messages.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
import type { AgentMessage } from "@mariozechner/companion-agent-core";
|
||||||
import type { ImageContent, Message, TextContent } from "@mariozechner/pi-ai";
|
import type { ImageContent, Message, TextContent } from "@mariozechner/companion-ai";
|
||||||
|
|
||||||
export const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
|
export const COMPACTION_SUMMARY_PREFIX = `The conversation history before this point was compacted into the following summary:
|
||||||
|
|
||||||
|
|
@ -67,7 +67,7 @@ export interface CompactionSummaryMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extend CustomAgentMessages via declaration merging
|
// Extend CustomAgentMessages via declaration merging
|
||||||
declare module "@mariozechner/pi-agent-core" {
|
declare module "@mariozechner/companion-agent-core" {
|
||||||
interface CustomAgentMessages {
|
interface CustomAgentMessages {
|
||||||
bashExecution: BashExecutionMessage;
|
bashExecution: BashExecutionMessage;
|
||||||
custom: CustomMessage;
|
custom: CustomMessage;
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ import {
|
||||||
registerApiProvider,
|
registerApiProvider,
|
||||||
resetApiProviders,
|
resetApiProviders,
|
||||||
type SimpleStreamOptions,
|
type SimpleStreamOptions,
|
||||||
} from "@mariozechner/pi-ai";
|
} from "@mariozechner/companion-ai";
|
||||||
import {
|
import {
|
||||||
registerOAuthProvider,
|
registerOAuthProvider,
|
||||||
resetOAuthProviders,
|
resetOAuthProviders,
|
||||||
} from "@mariozechner/pi-ai/oauth";
|
} from "@mariozechner/companion-ai/oauth";
|
||||||
import { type Static, Type } from "@sinclair/typebox";
|
import { type Static, Type } from "@sinclair/typebox";
|
||||||
import AjvModule from "ajv";
|
import AjvModule from "ajv";
|
||||||
import { existsSync, readFileSync } from "fs";
|
import { existsSync, readFileSync } from "fs";
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue