@phi-code-admin/phi-code 0.84.2 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/README.md +95 -126
- package/agents/code.md +1 -0
- package/agents/explore.md +11 -5
- package/agents/plan.md +18 -3
- package/agents/review.md +18 -7
- package/agents/test.md +1 -0
- package/config/routing.example.json +129 -0
- package/config/routing.schema.json +58 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -3
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +6 -6
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +1 -1
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +32 -30
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +9 -8
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts.map +1 -1
- package/dist/utils/pi-user-agent.js +4 -1
- package/dist/utils/pi-user-agent.js.map +1 -1
- package/dist/utils/version-check.d.ts +5 -5
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +13 -8
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +11 -11
- package/docs/custom-provider.md +4 -4
- package/docs/development.md +2 -2
- package/docs/extensions.md +47 -47
- package/docs/fork-policy.md +63 -0
- package/docs/index.md +7 -7
- package/docs/json.md +3 -3
- package/docs/keybindings.md +5 -5
- package/docs/models.md +6 -6
- package/docs/packages.md +37 -37
- package/docs/prompt-templates.md +4 -4
- package/docs/providers.md +9 -9
- package/docs/quickstart.md +25 -25
- package/docs/rpc.md +3 -3
- package/docs/sdk.md +34 -34
- package/docs/session-format.md +4 -4
- package/docs/sessions.md +11 -11
- package/docs/settings.md +11 -11
- package/docs/shell-aliases.md +2 -2
- package/docs/skills.md +9 -9
- package/docs/terminal-setup.md +7 -7
- package/docs/termux.md +6 -6
- package/docs/themes.md +9 -9
- package/docs/tmux.md +3 -3
- package/docs/tui.md +8 -8
- package/docs/usage.md +40 -40
- package/docs/windows.md +2 -2
- package/examples/sdk/12-full-control.ts +1 -1
- package/extensions/phi/agents.ts +5 -113
- package/extensions/phi/models.ts +170 -49
- package/extensions/phi/orchestrator.ts +44 -37
- package/extensions/phi/providers/agent-def.ts +128 -0
- package/extensions/phi/providers/live-models.ts +31 -1
- package/extensions/phi/providers/opencode-go.ts +7 -3
- package/extensions/phi/setup.ts +9 -0
- package/extensions/phi/skill-loader.ts +46 -25
- package/package.json +2 -1
package/docs/extensions.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
>
|
|
1
|
+
> phi can create extensions. Ask it to build one for your use case.
|
|
2
2
|
|
|
3
3
|
# Extensions
|
|
4
4
|
|
|
5
|
-
Extensions are TypeScript modules that extend
|
|
5
|
+
Extensions are TypeScript modules that extend phi's behavior. They can subscribe to lifecycle events, register custom tools callable by the LLM, add commands, and more.
|
|
6
6
|
|
|
7
|
-
> **Placement for /reload:** Put extensions in `~/.
|
|
7
|
+
> **Placement for /reload:** Put extensions in `~/.phi/agent/extensions/` (global) or `.phi/extensions/` (project-local) for auto-discovery. Use `phi -e ./path.ts` only for quick tests. Extensions in auto-discovered locations can be hot-reloaded with `/reload`.
|
|
8
8
|
|
|
9
9
|
**Key capabilities:**
|
|
10
10
|
- **Custom tools** - Register tools the LLM can call via `pi.registerTool()`
|
|
@@ -54,10 +54,10 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
|
54
54
|
|
|
55
55
|
## Quick Start
|
|
56
56
|
|
|
57
|
-
Create `~/.
|
|
57
|
+
Create `~/.phi/agent/extensions/my-extension.ts`:
|
|
58
58
|
|
|
59
59
|
```typescript
|
|
60
|
-
import type { ExtensionAPI } from "@
|
|
60
|
+
import type { ExtensionAPI } from "@phi-code-admin/phi-code";
|
|
61
61
|
import { Type } from "typebox";
|
|
62
62
|
|
|
63
63
|
export default function (pi: ExtensionAPI) {
|
|
@@ -102,7 +102,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
102
102
|
Test with `--extension` (or `-e`) flag:
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
|
-
|
|
105
|
+
phi -e ./my-extension.ts
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
## Extension Locations
|
|
@@ -113,10 +113,10 @@ Extensions are auto-discovered from:
|
|
|
113
113
|
|
|
114
114
|
| Location | Scope |
|
|
115
115
|
|----------|-------|
|
|
116
|
-
| `~/.
|
|
117
|
-
| `~/.
|
|
118
|
-
| `.
|
|
119
|
-
| `.
|
|
116
|
+
| `~/.phi/agent/extensions/*.ts` | Global (all projects) |
|
|
117
|
+
| `~/.phi/agent/extensions/*/index.ts` | Global (subdirectory) |
|
|
118
|
+
| `.phi/extensions/*.ts` | Project-local |
|
|
119
|
+
| `.phi/extensions/*/index.ts` | Project-local (subdirectory) |
|
|
120
120
|
|
|
121
121
|
Additional paths via `settings.json`:
|
|
122
122
|
|
|
@@ -133,20 +133,20 @@ Additional paths via `settings.json`:
|
|
|
133
133
|
}
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
To share extensions via npm or git as
|
|
136
|
+
To share extensions via npm or git as phi packages, see [packages.md](packages.md).
|
|
137
137
|
|
|
138
138
|
## Available Imports
|
|
139
139
|
|
|
140
140
|
| Package | Purpose |
|
|
141
141
|
|---------|---------|
|
|
142
|
-
| `@
|
|
142
|
+
| `@phi-code-admin/phi-code` | Extension types (`ExtensionAPI`, `ExtensionContext`, events) |
|
|
143
143
|
| `typebox` | Schema definitions for tool parameters |
|
|
144
144
|
| `@earendil-works/pi-ai` | AI utilities (`StringEnum` for Google-compatible enums) |
|
|
145
145
|
| `@earendil-works/pi-tui` | TUI components for custom rendering |
|
|
146
146
|
|
|
147
147
|
npm dependencies work too. Add a `package.json` next to your extension (or in a parent directory), run `npm install`, and imports from `node_modules/` are resolved automatically.
|
|
148
148
|
|
|
149
|
-
For distributed
|
|
149
|
+
For distributed phi packages installed with `phi install` (npm or git), runtime deps must be in `dependencies`. Package installation uses production installs (`npm install --omit=dev`) by default, so `devDependencies` are not available at runtime; when `npmCommand` is configured, git packages use plain `install` for compatibility with wrappers.
|
|
150
150
|
|
|
151
151
|
Node.js built-ins (`node:fs`, `node:path`, etc.) are also available.
|
|
152
152
|
|
|
@@ -155,7 +155,7 @@ Node.js built-ins (`node:fs`, `node:path`, etc.) are also available.
|
|
|
155
155
|
An extension exports a default factory function that receives `ExtensionAPI`. The factory can be synchronous or asynchronous:
|
|
156
156
|
|
|
157
157
|
```typescript
|
|
158
|
-
import type { ExtensionAPI } from "@
|
|
158
|
+
import type { ExtensionAPI } from "@phi-code-admin/phi-code";
|
|
159
159
|
|
|
160
160
|
export default function (pi: ExtensionAPI) {
|
|
161
161
|
// Subscribe to events
|
|
@@ -177,14 +177,14 @@ export default function (pi: ExtensionAPI) {
|
|
|
177
177
|
|
|
178
178
|
Extensions are loaded via [jiti](https://github.com/unjs/jiti), so TypeScript works without compilation.
|
|
179
179
|
|
|
180
|
-
If the factory returns a `Promise`,
|
|
180
|
+
If the factory returns a `Promise`, phi awaits it before continuing startup. That means async initialization completes before `session_start`, before `resources_discover`, and before provider registrations queued via `pi.registerProvider()` are flushed.
|
|
181
181
|
|
|
182
182
|
### Async factory functions
|
|
183
183
|
|
|
184
184
|
Use an async factory for one-time startup work such as fetching remote configuration or dynamically discovering available models.
|
|
185
185
|
|
|
186
186
|
```typescript
|
|
187
|
-
import type { ExtensionAPI } from "@
|
|
187
|
+
import type { ExtensionAPI } from "@phi-code-admin/phi-code";
|
|
188
188
|
|
|
189
189
|
export default async function (pi: ExtensionAPI) {
|
|
190
190
|
const response = await fetch("http://localhost:1234/v1/models");
|
|
@@ -214,21 +214,21 @@ export default async function (pi: ExtensionAPI) {
|
|
|
214
214
|
}
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
-
This pattern makes the fetched models available during normal startup and to `
|
|
217
|
+
This pattern makes the fetched models available during normal startup and to `phi --list-models`.
|
|
218
218
|
|
|
219
219
|
### Extension Styles
|
|
220
220
|
|
|
221
221
|
**Single file** - simplest, for small extensions:
|
|
222
222
|
|
|
223
223
|
```
|
|
224
|
-
~/.
|
|
224
|
+
~/.phi/agent/extensions/
|
|
225
225
|
└── my-extension.ts
|
|
226
226
|
```
|
|
227
227
|
|
|
228
228
|
**Directory with index.ts** - for multi-file extensions:
|
|
229
229
|
|
|
230
230
|
```
|
|
231
|
-
~/.
|
|
231
|
+
~/.phi/agent/extensions/
|
|
232
232
|
└── my-extension/
|
|
233
233
|
├── index.ts # Entry point (exports default function)
|
|
234
234
|
├── tools.ts # Helper module
|
|
@@ -238,7 +238,7 @@ This pattern makes the fetched models available during normal startup and to `pi
|
|
|
238
238
|
**Package with dependencies** - for extensions that need npm packages:
|
|
239
239
|
|
|
240
240
|
```
|
|
241
|
-
~/.
|
|
241
|
+
~/.phi/agent/extensions/
|
|
242
242
|
└── my-extension/
|
|
243
243
|
├── package.json # Declares dependencies and entry points
|
|
244
244
|
├── package-lock.json
|
|
@@ -268,7 +268,7 @@ Run `npm install` in the extension directory, then imports from `node_modules/`
|
|
|
268
268
|
### Lifecycle Overview
|
|
269
269
|
|
|
270
270
|
```
|
|
271
|
-
|
|
271
|
+
phi starts
|
|
272
272
|
│
|
|
273
273
|
├─► session_start { reason: "startup" }
|
|
274
274
|
└─► resources_discover { reason: "startup" }
|
|
@@ -385,7 +385,7 @@ pi.on("session_before_switch", async (event, ctx) => {
|
|
|
385
385
|
});
|
|
386
386
|
```
|
|
387
387
|
|
|
388
|
-
After a successful switch or new-session action,
|
|
388
|
+
After a successful switch or new-session action, phi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "new" | "resume"` and `previousSessionFile`.
|
|
389
389
|
Do cleanup work in `session_shutdown`, then reestablish any in-memory state in `session_start`.
|
|
390
390
|
|
|
391
391
|
#### session_before_fork
|
|
@@ -402,7 +402,7 @@ pi.on("session_before_fork", async (event, ctx) => {
|
|
|
402
402
|
});
|
|
403
403
|
```
|
|
404
404
|
|
|
405
|
-
After a successful fork or clone,
|
|
405
|
+
After a successful fork or clone, phi emits `session_shutdown` for the old extension instance, reloads and rebinds extensions for the new session, then emits `session_start` with `reason: "fork"` and `previousSessionFile`.
|
|
406
406
|
Do cleanup work in `session_shutdown`, then reestablish any in-memory state in `session_start`.
|
|
407
407
|
|
|
408
408
|
#### session_before_compact / session_compact
|
|
@@ -496,7 +496,7 @@ pi.on("before_agent_start", async (event, ctx) => {
|
|
|
496
496
|
});
|
|
497
497
|
```
|
|
498
498
|
|
|
499
|
-
The `systemPromptOptions` field gives extensions access to the same structured data
|
|
499
|
+
The `systemPromptOptions` field gives extensions access to the same structured data phi uses to build the system prompt. This lets you inspect what phi has loaded — custom prompts, guidelines, tool snippets, context files, skills — without re-discovering resources or re-parsing flags. Use it when your extension needs to make deep, informed changes to the system prompt while respecting user-provided configuration.
|
|
500
500
|
|
|
501
501
|
Inside `before_agent_start`, `event.systemPrompt` and `ctx.getSystemPrompt()` both reflect the chained system prompt as of the current handler. Later `before_agent_start` handlers can still modify it again.
|
|
502
502
|
|
|
@@ -602,7 +602,7 @@ pi.on("context", async (event, ctx) => {
|
|
|
602
602
|
|
|
603
603
|
Fired after the provider-specific payload is built, right before the request is sent. Handlers run in extension load order. Returning `undefined` keeps the payload unchanged. Returning any other value replaces the payload for later handlers and for the actual request.
|
|
604
604
|
|
|
605
|
-
This hook can rewrite provider-level system instructions or remove them entirely. Those payload-level changes are not reflected by `ctx.getSystemPrompt()`, which reports
|
|
605
|
+
This hook can rewrite provider-level system instructions or remove them entirely. Those payload-level changes are not reflected by `ctx.getSystemPrompt()`, which reports phi's system prompt string rather than the final serialized provider payload.
|
|
606
606
|
|
|
607
607
|
```typescript
|
|
608
608
|
pi.on("before_provider_request", (event, ctx) => {
|
|
@@ -675,7 +675,7 @@ Use this to update extension UI when `pi.setThinkingLevel()`, model changes, or
|
|
|
675
675
|
|
|
676
676
|
Fired after `tool_execution_start`, before the tool executes. **Can block.** Use `isToolCallEventType` to narrow and get typed inputs.
|
|
677
677
|
|
|
678
|
-
Before `tool_call` runs,
|
|
678
|
+
Before `tool_call` runs, phi waits for previously emitted Agent events to finish draining through `AgentSession`. This means `ctx.sessionManager` is up to date through the current assistant tool-calling message.
|
|
679
679
|
|
|
680
680
|
In the default parallel tool execution mode, sibling tool calls from the same assistant message are preflighted sequentially, then executed concurrently. `tool_call` is not guaranteed to see sibling tool results from that same assistant message in `ctx.sessionManager`.
|
|
681
681
|
|
|
@@ -688,7 +688,7 @@ Behavior guarantees:
|
|
|
688
688
|
- Return values from `tool_call` only control blocking via `{ block: true, reason?: string }`
|
|
689
689
|
|
|
690
690
|
```typescript
|
|
691
|
-
import { isToolCallEventType } from "@
|
|
691
|
+
import { isToolCallEventType } from "@phi-code-admin/phi-code";
|
|
692
692
|
|
|
693
693
|
pi.on("tool_call", async (event, ctx) => {
|
|
694
694
|
// event.toolName - "bash", "read", "write", "edit", etc.
|
|
@@ -724,7 +724,7 @@ export type MyToolInput = Static<typeof myToolSchema>;
|
|
|
724
724
|
Use `isToolCallEventType` with explicit type parameters:
|
|
725
725
|
|
|
726
726
|
```typescript
|
|
727
|
-
import { isToolCallEventType } from "@
|
|
727
|
+
import { isToolCallEventType } from "@phi-code-admin/phi-code";
|
|
728
728
|
import type { MyToolInput } from "my-extension";
|
|
729
729
|
|
|
730
730
|
pi.on("tool_call", (event) => {
|
|
@@ -748,7 +748,7 @@ In parallel tool mode, `tool_result` and `tool_execution_end` may interleave in
|
|
|
748
748
|
Use `ctx.signal` for nested async work inside the handler. This lets Esc cancel model calls, `fetch()`, and other abort-aware operations started by the extension.
|
|
749
749
|
|
|
750
750
|
```typescript
|
|
751
|
-
import { isBashToolResult } from "@
|
|
751
|
+
import { isBashToolResult } from "@phi-code-admin/phi-code";
|
|
752
752
|
|
|
753
753
|
pi.on("tool_result", async (event, ctx) => {
|
|
754
754
|
// event.toolName, event.toolCallId, event.input
|
|
@@ -776,7 +776,7 @@ pi.on("tool_result", async (event, ctx) => {
|
|
|
776
776
|
Fired when user executes `!` or `!!` commands. **Can intercept.**
|
|
777
777
|
|
|
778
778
|
```typescript
|
|
779
|
-
import { createLocalBashOperations } from "@
|
|
779
|
+
import { createLocalBashOperations } from "@phi-code-admin/phi-code";
|
|
780
780
|
|
|
781
781
|
pi.on("user_bash", (event, ctx) => {
|
|
782
782
|
// event.command - the bash command
|
|
@@ -891,7 +891,7 @@ Use this for abort-aware nested work started by extension handlers, for example:
|
|
|
891
891
|
- file or process helpers that accept `AbortSignal`
|
|
892
892
|
|
|
893
893
|
`ctx.signal` is typically defined during active turn events such as `tool_call`, `tool_result`, `message_update`, and `turn_end`.
|
|
894
|
-
It is usually `undefined` in idle or non-turn contexts such as session events, extension commands, and shortcuts fired while
|
|
894
|
+
It is usually `undefined` in idle or non-turn contexts such as session events, extension commands, and shortcuts fired while phi is idle.
|
|
895
895
|
|
|
896
896
|
```typescript
|
|
897
897
|
pi.on("tool_result", async (event, ctx) => {
|
|
@@ -957,7 +957,7 @@ ctx.compact({
|
|
|
957
957
|
|
|
958
958
|
### ctx.getSystemPrompt()
|
|
959
959
|
|
|
960
|
-
Returns
|
|
960
|
+
Returns phi's current system prompt string.
|
|
961
961
|
|
|
962
962
|
- During `before_agent_start`, this reflects chained system-prompt changes made so far for the current turn.
|
|
963
963
|
- It does not include later `context` message mutations.
|
|
@@ -1087,7 +1087,7 @@ Options:
|
|
|
1087
1087
|
To discover available sessions, use the static `SessionManager.list()` or `SessionManager.listAll()` methods:
|
|
1088
1088
|
|
|
1089
1089
|
```typescript
|
|
1090
|
-
import { SessionManager } from "@
|
|
1090
|
+
import { SessionManager } from "@phi-code-admin/phi-code";
|
|
1091
1091
|
|
|
1092
1092
|
pi.registerCommand("switch", {
|
|
1093
1093
|
description: "Switch to another session",
|
|
@@ -1181,7 +1181,7 @@ Tools run with `ExtensionContext`, so they cannot call `ctx.reload()` directly.
|
|
|
1181
1181
|
Example tool the LLM can call to trigger reload:
|
|
1182
1182
|
|
|
1183
1183
|
```typescript
|
|
1184
|
-
import type { ExtensionAPI } from "@
|
|
1184
|
+
import type { ExtensionAPI } from "@phi-code-admin/phi-code";
|
|
1185
1185
|
import { Type } from "typebox";
|
|
1186
1186
|
|
|
1187
1187
|
export default function (pi: ExtensionAPI) {
|
|
@@ -1373,7 +1373,7 @@ Labels persist in the session and survive restarts. Use them to mark important p
|
|
|
1373
1373
|
|
|
1374
1374
|
Register a command.
|
|
1375
1375
|
|
|
1376
|
-
If multiple extensions register the same command name,
|
|
1376
|
+
If multiple extensions register the same command name, phi keeps them all and assigns numeric invocation suffixes in load order, for example `/review:1` and `/review:2`.
|
|
1377
1377
|
|
|
1378
1378
|
```typescript
|
|
1379
1379
|
pi.registerCommand("stats", {
|
|
@@ -1544,7 +1544,7 @@ Register or override a model provider dynamically. Useful for proxies, custom en
|
|
|
1544
1544
|
|
|
1545
1545
|
Calls made during the extension factory function are queued and applied once the runner initialises. Calls made after that — for example from a command handler following a user setup flow — take effect immediately without requiring a `/reload`.
|
|
1546
1546
|
|
|
1547
|
-
If you need to discover models from a remote endpoint, prefer an async extension factory over deferring the fetch to `session_start`.
|
|
1547
|
+
If you need to discover models from a remote endpoint, prefer an async extension factory over deferring the fetch to `session_start`. phi waits for the factory before startup continues, so the registered models are available immediately, including to `phi --list-models`.
|
|
1548
1548
|
|
|
1549
1549
|
```typescript
|
|
1550
1550
|
// Register a new provider with custom models
|
|
@@ -1678,7 +1678,7 @@ Pass the real target file path to `withFileMutationQueue()`, not the raw user ar
|
|
|
1678
1678
|
Queue the entire mutation window on that target path. That includes read-modify-write logic, not just the final write.
|
|
1679
1679
|
|
|
1680
1680
|
```typescript
|
|
1681
|
-
import { withFileMutationQueue } from "@
|
|
1681
|
+
import { withFileMutationQueue } from "@phi-code-admin/phi-code";
|
|
1682
1682
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
1683
1683
|
import { dirname, resolve } from "node:path";
|
|
1684
1684
|
|
|
@@ -1774,7 +1774,7 @@ async execute(toolCallId, params) {
|
|
|
1774
1774
|
|
|
1775
1775
|
**Important:** Use `StringEnum` from `@earendil-works/pi-ai` for string enums. `Type.Union`/`Type.Literal` doesn't work with Google's API.
|
|
1776
1776
|
|
|
1777
|
-
**Argument preparation:** `prepareArguments(args)` is optional. If defined, it runs before schema validation and before `execute()`. Use it to mimic an older accepted input shape when
|
|
1777
|
+
**Argument preparation:** `prepareArguments(args)` is optional. If defined, it runs before schema validation and before `execute()`. Use it to mimic an older accepted input shape when phi resumes an older session whose stored tool call arguments no longer match the current schema. Return the object you want validated against `parameters`. Keep the public schema strict. Do not add deprecated compatibility fields to `parameters` just to keep old resumed sessions working.
|
|
1778
1778
|
|
|
1779
1779
|
Example: an older session may contain an `edit` tool call with top-level `oldText` and `newText`, while the current schema only accepts `edits: [{ oldText, newText }]`.
|
|
1780
1780
|
|
|
@@ -1827,13 +1827,13 @@ Extensions can override built-in tools (`read`, `bash`, `edit`, `write`, `grep`,
|
|
|
1827
1827
|
|
|
1828
1828
|
```bash
|
|
1829
1829
|
# Extension's read tool replaces built-in read
|
|
1830
|
-
|
|
1830
|
+
phi -e ./tool-override.ts
|
|
1831
1831
|
```
|
|
1832
1832
|
|
|
1833
1833
|
Alternatively, use `--no-builtin-tools` to start without any built-in tools while keeping extension tools enabled:
|
|
1834
1834
|
```bash
|
|
1835
1835
|
# No built-in tools, only extension tools
|
|
1836
|
-
|
|
1836
|
+
phi --no-builtin-tools -e ./my-extension.ts
|
|
1837
1837
|
```
|
|
1838
1838
|
|
|
1839
1839
|
See [examples/extensions/tool-override.ts](../examples/extensions/tool-override.ts) for a complete example that overrides `read` with logging and access control.
|
|
@@ -1858,7 +1858,7 @@ Built-in tool implementations:
|
|
|
1858
1858
|
Built-in tools support pluggable operations for delegating to remote systems (SSH, containers, etc.):
|
|
1859
1859
|
|
|
1860
1860
|
```typescript
|
|
1861
|
-
import { createReadTool, createBashTool, type ReadOperations } from "@
|
|
1861
|
+
import { createReadTool, createBashTool, type ReadOperations } from "@phi-code-admin/phi-code";
|
|
1862
1862
|
|
|
1863
1863
|
// Create tool with custom operations
|
|
1864
1864
|
const remoteRead = createReadTool(cwd, {
|
|
@@ -1884,12 +1884,12 @@ pi.registerTool({
|
|
|
1884
1884
|
|
|
1885
1885
|
**Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
|
|
1886
1886
|
|
|
1887
|
-
For `user_bash`, extensions can reuse
|
|
1887
|
+
For `user_bash`, extensions can reuse phi's local shell backend via `createLocalBashOperations()` instead of reimplementing local process spawning, shell resolution, and process-tree termination.
|
|
1888
1888
|
|
|
1889
1889
|
The bash tool also supports a spawn hook to adjust the command, cwd, or env before execution:
|
|
1890
1890
|
|
|
1891
1891
|
```typescript
|
|
1892
|
-
import { createBashTool } from "@
|
|
1892
|
+
import { createBashTool } from "@phi-code-admin/phi-code";
|
|
1893
1893
|
|
|
1894
1894
|
const bashTool = createBashTool(cwd, {
|
|
1895
1895
|
spawnHook: ({ command, cwd, env }) => ({
|
|
@@ -1919,7 +1919,7 @@ import {
|
|
|
1919
1919
|
formatSize, // Human-readable size (e.g., "50KB", "1.5MB")
|
|
1920
1920
|
DEFAULT_MAX_BYTES, // 50KB
|
|
1921
1921
|
DEFAULT_MAX_LINES, // 2000
|
|
1922
|
-
} from "@
|
|
1922
|
+
} from "@phi-code-admin/phi-code";
|
|
1923
1923
|
|
|
1924
1924
|
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
1925
1925
|
const output = await runCommand();
|
|
@@ -2055,7 +2055,7 @@ If a slot intentionally has no visible content, return an empty `Component` such
|
|
|
2055
2055
|
Use `keyHint()` to display keybinding hints that respect the active keybinding configuration:
|
|
2056
2056
|
|
|
2057
2057
|
```typescript
|
|
2058
|
-
import { keyHint } from "@
|
|
2058
|
+
import { keyHint } from "@phi-code-admin/phi-code";
|
|
2059
2059
|
|
|
2060
2060
|
renderResult(result, { expanded }, theme, context) {
|
|
2061
2061
|
let text = theme.fg("success", "✓ Done");
|
|
@@ -2387,7 +2387,7 @@ See [tui.md](tui.md) for the full `OverlayOptions` API and [overlay-qa-tests.ts]
|
|
|
2387
2387
|
Replace the main input editor with a custom implementation (vim mode, emacs mode, etc.):
|
|
2388
2388
|
|
|
2389
2389
|
```typescript
|
|
2390
|
-
import { CustomEditor, type ExtensionAPI } from "@
|
|
2390
|
+
import { CustomEditor, type ExtensionAPI } from "@phi-code-admin/phi-code";
|
|
2391
2391
|
import { matchesKey } from "@earendil-works/pi-tui";
|
|
2392
2392
|
|
|
2393
2393
|
class VimEditor extends CustomEditor {
|
|
@@ -2487,7 +2487,7 @@ theme.strikethrough(text)
|
|
|
2487
2487
|
For syntax highlighting in custom tool renderers:
|
|
2488
2488
|
|
|
2489
2489
|
```typescript
|
|
2490
|
-
import { highlightCode, getLanguageFromPath } from "@
|
|
2490
|
+
import { highlightCode, getLanguageFromPath } from "@phi-code-admin/phi-code";
|
|
2491
2491
|
|
|
2492
2492
|
// Highlight code with explicit language
|
|
2493
2493
|
const highlighted = highlightCode("const x = 1;", "typescript", theme);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Fork policy — staying mergeable with upstream Pi
|
|
2
|
+
|
|
3
|
+
phi-code is a fork of [pi-mono](https://github.com/earendil-works/pi-mono)
|
|
4
|
+
(`packages/coding-agent` = upstream's coding agent). This document defines
|
|
5
|
+
exactly **what is rebranded and what deliberately stays "pi"**, so upstream
|
|
6
|
+
updates can be merged with minimal conflicts and nobody "finishes" a rename
|
|
7
|
+
that would make every future merge painful.
|
|
8
|
+
|
|
9
|
+
## The one rule
|
|
10
|
+
|
|
11
|
+
> Rebrand **outputs** (what users see), keep **identifiers** (what code sees).
|
|
12
|
+
|
|
13
|
+
All branding flows from `packages/coding-agent/src/config.ts`, driven by
|
|
14
|
+
`package.json`'s `piConfig` block:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
"piConfig": { "name": "phi", "configDir": ".phi" }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
which resolves to `APP_NAME = "phi"`, `APP_TITLE`, `CONFIG_DIR_NAME = ".phi"`,
|
|
21
|
+
`PACKAGE_NAME = "@phi-code-admin/phi-code"`. **New user-facing strings must
|
|
22
|
+
use these constants, never a hardcoded "pi" or "phi".**
|
|
23
|
+
|
|
24
|
+
## Rebranded (must say phi)
|
|
25
|
+
|
|
26
|
+
| Surface | Where |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Binary, config dir | `phi`, `~/.phi/` (via `piConfig`) |
|
|
29
|
+
| Update check + `phi update` | npm registry `@phi-code-admin/phi-code` (`src/utils/version-check.ts`, `src/package-manager-cli.ts`) |
|
|
30
|
+
| Update notifications, changelog link | `uglyswap/phi-code` changelog (`interactive-mode.ts`) |
|
|
31
|
+
| HTTP User-Agent | `phi/<version>` — `APP_NAME`-driven (`src/utils/pi-user-agent.ts`) |
|
|
32
|
+
| OpenRouter attribution headers | `phi-code` (`src/core/sdk.ts`) |
|
|
33
|
+
| Telemetry | **removed** — phi-code sends no install pings |
|
|
34
|
+
| TUI messages, `--help`, docs examples | `phi` commands, `~/.phi/` paths |
|
|
35
|
+
| npm README / CHANGELOG | phi-code |
|
|
36
|
+
|
|
37
|
+
## Deliberately kept as-is (do NOT rename)
|
|
38
|
+
|
|
39
|
+
| Item | Why |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `PI_*` env vars (`PI_OFFLINE`, `PI_SKIP_VERSION_CHECK`, `PI_TELEMETRY`, …) | Backwards compat + documented everywhere; renaming breaks users and every upstream merge. `PHI_*` additions are fine as aliases. |
|
|
42
|
+
| Internal identifiers (`getPiUserAgent`, `piConfig`, `pi-user-agent.ts`, type names, comments) | Pure code-level names; renaming guarantees merge conflicts for zero user value. |
|
|
43
|
+
| `pi.dev/session/` share viewer (`DEFAULT_SHARE_VIEWER_URL`) | `/share` uploads a gist; the upstream viewer renders any pi-format session. Overridable via `PI_SHARE_VIEWER_URL`. |
|
|
44
|
+
| pi-mono links in `src/migrations.ts` | Historical migration guides that only exist upstream. |
|
|
45
|
+
| `examples/` referencing pi | Upstream examples; kept verbatim to merge cleanly. |
|
|
46
|
+
| `@mariozechner/*` deps (web-ui, jiti) | Upstream packages consumed as-is. |
|
|
47
|
+
|
|
48
|
+
## Merging upstream
|
|
49
|
+
|
|
50
|
+
1. `git remote add upstream https://github.com/earendil-works/pi-mono.git && git fetch upstream`
|
|
51
|
+
2. Merge/cherry-pick into a branch. Conflicts should concentrate in the few
|
|
52
|
+
rebranded files listed above — everything else is untouched by design.
|
|
53
|
+
3. After merging, run the guard-rails: `npm run check && npm test`. The test
|
|
54
|
+
suite pins the phi behaviors (registry-based update check, `phi/` UA,
|
|
55
|
+
phi-code attribution headers, routing example sync), so an upstream change
|
|
56
|
+
that silently reverts a rebrand point fails CI instead of shipping.
|
|
57
|
+
|
|
58
|
+
## Fork-owned additions (no upstream counterpart)
|
|
59
|
+
|
|
60
|
+
`extensions/phi/**` (orchestrator, models refresh, setup, memory, skills…),
|
|
61
|
+
`agents/`, `skills/`, `config/`, the `sigma-*` packages, and the browser and
|
|
62
|
+
camoufox packages are phi-code territory: normal engineering rules apply,
|
|
63
|
+
no merge constraints.
|
package/docs/index.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# phi Documentation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
phi is a minimal terminal coding harness. It is designed to stay small at the core while being extended through TypeScript extensions, skills, prompt templates, themes, and phi packages.
|
|
4
4
|
|
|
5
5
|
## Quick start
|
|
6
6
|
|
|
7
|
-
On linux or mac you can install
|
|
7
|
+
On linux or mac you can install phi with curl:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
curl -fsSL https://pi.dev/install.sh | sh
|
|
@@ -13,7 +13,7 @@ curl -fsSL https://pi.dev/install.sh | sh
|
|
|
13
13
|
Or alternatively with npm:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npm install -g @
|
|
16
|
+
npm install -g @phi-code-admin/phi-code
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Then run it in a project directory:
|
|
@@ -29,7 +29,7 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
29
29
|
## Start here
|
|
30
30
|
|
|
31
31
|
- [Quickstart](quickstart.md) - install, authenticate, and run a first session.
|
|
32
|
-
- [Using
|
|
32
|
+
- [Using phi](usage.md) - interactive mode, slash commands, context files, and CLI reference.
|
|
33
33
|
- [Providers](providers.md) - subscription and API-key setup for built-in providers.
|
|
34
34
|
- [Settings](settings.md) - global and project settings.
|
|
35
35
|
- [Keybindings](keybindings.md) - default shortcuts and custom keybindings.
|
|
@@ -42,13 +42,13 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
42
42
|
- [Skills](skills.md) - Agent Skills for reusable on-demand capabilities.
|
|
43
43
|
- [Prompt templates](prompt-templates.md) - reusable prompts that expand from slash commands.
|
|
44
44
|
- [Themes](themes.md) - built-in and custom terminal themes.
|
|
45
|
-
- [
|
|
45
|
+
- [phi packages](packages.md) - bundle and share extensions, skills, prompts, and themes.
|
|
46
46
|
- [Custom models](models.md) - add model entries for supported provider APIs.
|
|
47
47
|
- [Custom providers](custom-provider.md) - implement custom APIs and OAuth flows.
|
|
48
48
|
|
|
49
49
|
## Programmatic usage
|
|
50
50
|
|
|
51
|
-
- [SDK](sdk.md) - embed
|
|
51
|
+
- [SDK](sdk.md) - embed phi in Node.js applications.
|
|
52
52
|
- [RPC mode](rpc.md) - integrate over stdin/stdout JSONL.
|
|
53
53
|
- [JSON event stream mode](json.md) - print mode with structured events.
|
|
54
54
|
- [TUI components](tui.md) - build custom terminal UI for extensions.
|
package/docs/json.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# JSON Event Stream Mode
|
|
2
2
|
|
|
3
3
|
```bash
|
|
4
|
-
|
|
4
|
+
phi --mode json "Your prompt"
|
|
5
5
|
```
|
|
6
6
|
|
|
7
|
-
Outputs all session events as JSON lines to stdout. Useful for integrating
|
|
7
|
+
Outputs all session events as JSON lines to stdout. Useful for integrating phi into other tools or custom UIs.
|
|
8
8
|
|
|
9
9
|
## Event Types
|
|
10
10
|
|
|
@@ -78,5 +78,5 @@ Followed by events as they occur:
|
|
|
78
78
|
## Example
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
|
|
81
|
+
phi --mode json "List files" 2>/dev/null | jq -c 'select(.type == "message_end")'
|
|
82
82
|
```
|
package/docs/keybindings.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Keybindings
|
|
2
2
|
|
|
3
|
-
All keyboard shortcuts can be customized via `~/.
|
|
3
|
+
All keyboard shortcuts can be customized via `~/.phi/agent/keybindings.json`. Each action can be bound to one or more keys.
|
|
4
4
|
|
|
5
|
-
The config file uses the same namespaced keybinding ids that
|
|
5
|
+
The config file uses the same namespaced keybinding ids that phi uses internally and that extension authors use in `keyHint()` and injected `keybindings` managers.
|
|
6
6
|
|
|
7
7
|
Older configs using pre-namespaced ids such as `cursorUp` or `expandTools` are migrated automatically to the namespaced ids on startup.
|
|
8
8
|
|
|
9
|
-
After editing `keybindings.json`, run `/reload` in
|
|
9
|
+
After editing `keybindings.json`, run `/reload` in phi to apply the changes without restarting the session.
|
|
10
10
|
|
|
11
11
|
## Key Format
|
|
12
12
|
|
|
@@ -153,7 +153,7 @@ Used inside the scoped models selector (opened via `/scoped-models`).
|
|
|
153
153
|
|
|
154
154
|
## Custom Configuration
|
|
155
155
|
|
|
156
|
-
Create `~/.
|
|
156
|
+
Create `~/.phi/agent/keybindings.json`:
|
|
157
157
|
|
|
158
158
|
```json
|
|
159
159
|
{
|
|
@@ -165,7 +165,7 @@ Create `~/.pi/agent/keybindings.json`:
|
|
|
165
165
|
|
|
166
166
|
Each action can have a single key or an array of keys. User config overrides defaults.
|
|
167
167
|
|
|
168
|
-
On native Windows, `app.suspend` has no default binding because Windows terminals do not support Unix job control. If you bind it manually,
|
|
168
|
+
On native Windows, `app.suspend` has no default binding because Windows terminals do not support Unix job control. If you bind it manually, phi shows a status message instead of suspending. In WSL, the normal Linux `ctrl+z`/`fg` behavior still applies.
|
|
169
169
|
|
|
170
170
|
### Emacs Example
|
|
171
171
|
|
package/docs/models.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Custom Models
|
|
2
2
|
|
|
3
|
-
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.
|
|
3
|
+
Add custom providers and models (Ollama, vLLM, LM Studio, proxies) via `~/.phi/agent/models.json`.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
@@ -36,7 +36,7 @@ For local models (Ollama, LM Studio, vLLM), only `id` is required per model:
|
|
|
36
36
|
|
|
37
37
|
The `apiKey` is required but Ollama ignores it, so any value works.
|
|
38
38
|
|
|
39
|
-
Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so
|
|
39
|
+
Some OpenAI-compatible servers do not understand the `developer` role used for reasoning-capable models. For those providers, set `compat.supportsDeveloperRole` to `false` so phi sends the system prompt as a `system` message instead. If the server also does not support `reasoning_effort`, set `compat.supportsReasoningEffort` to `false` too.
|
|
40
40
|
|
|
41
41
|
You can set `compat` at the provider level to apply to all models, or at the model level to override a specific model. This commonly applies to Ollama, vLLM, SGLang, and similar OpenAI-compatible servers.
|
|
42
42
|
|
|
@@ -159,7 +159,7 @@ The `apiKey` and `headers` fields support three formats:
|
|
|
159
159
|
"apiKey": "sk-..."
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
For `models.json`, shell commands are resolved at request time.
|
|
162
|
+
For `models.json`, shell commands are resolved at request time. phi intentionally does not apply built-in TTL, stale reuse, or recovery logic for arbitrary commands. Different commands need different caching and failure strategies, and phi cannot infer the right one.
|
|
163
163
|
|
|
164
164
|
If your command is slow, expensive, rate-limited, or should keep using a previous value on transient failures, wrap it in your own script or command that implements the caching or TTL behavior you want.
|
|
165
165
|
|
|
@@ -192,7 +192,7 @@ If your command is slow, expensive, rate-limited, or should keep using a previou
|
|
|
192
192
|
| `name` | No | `id` | Human-readable model label. Used for matching (`--model` patterns) and shown in model details/status text. |
|
|
193
193
|
| `api` | No | provider's `api` | Override provider's API for this model |
|
|
194
194
|
| `reasoning` | No | `false` | Supports extended thinking |
|
|
195
|
-
| `thinkingLevelMap` | No | omitted | Maps
|
|
195
|
+
| `thinkingLevelMap` | No | omitted | Maps phi thinking levels to provider values and marks unsupported levels (see below) |
|
|
196
196
|
| `input` | No | `["text"]` | Input types: `["text"]` or `["text", "image"]` |
|
|
197
197
|
| `contextWindow` | No | `128000` | Context window size in tokens |
|
|
198
198
|
| `maxTokens` | No | `16384` | Maximum output tokens |
|
|
@@ -205,7 +205,7 @@ Current behavior:
|
|
|
205
205
|
|
|
206
206
|
### Thinking Level Map
|
|
207
207
|
|
|
208
|
-
Use `thinkingLevelMap` on a model to describe model-specific thinking controls. Keys are
|
|
208
|
+
Use `thinkingLevelMap` on a model to describe model-specific thinking controls. Keys are phi thinking levels: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`.
|
|
209
209
|
|
|
210
210
|
Values are tristate:
|
|
211
211
|
|
|
@@ -317,7 +317,7 @@ Behavior notes:
|
|
|
317
317
|
|
|
318
318
|
For providers or proxies using `api: "anthropic-messages"`, use `compat.supportsEagerToolInputStreaming` to control Anthropic fine-grained tool streaming compatibility.
|
|
319
319
|
|
|
320
|
-
By default
|
|
320
|
+
By default phi sends per-tool `eager_input_streaming: true`. If a proxy or Anthropic-compatible backend rejects that field, set `supportsEagerToolInputStreaming` to `false`. phi will omit `tools[].eager_input_streaming` and send the legacy `fine-grained-tool-streaming-2025-05-14` beta header for tool-enabled requests instead.
|
|
321
321
|
|
|
322
322
|
```json
|
|
323
323
|
{
|