docs: move documentation to the repository root
The docs cover more than the coding agent, so they move from packages/coding-agent/docs to docs/. Links into coding-agent files now use the repository layout (../packages/coding-agent/examples/...). The coding-agent build copies docs/ into packages/coding-agent/docs/ (generated, gitignored) with scripts/copy-docs.mjs and rewrites links into the package back to package-relative paths. npm, the release binaries, Nix and the evals image pack after the build, so releases keep shipping <package>/docs unchanged. getDocsPath() returns the repository docs/ in source checkouts.
2
.gitignore
vendored
|
|
@ -37,6 +37,8 @@ out.jsonl
|
|||
pi-*.html
|
||||
out.html
|
||||
packages/coding-agent/binaries/
|
||||
# Generated from docs/ by the coding-agent build (scripts/copy-docs.mjs)
|
||||
packages/coding-agent/docs/
|
||||
packages/env/bin/
|
||||
packages/env/daemon/target/
|
||||
todo.md
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ For each PR URL, do the following in order:
|
|||
3. Identify any linked issues referenced in the PR body, comments, commit messages, or cross links. Read each issue in full, including all comments.
|
||||
4. Analyze the PR diff without checking out or switching to the PR branch. Use `gh pr diff`, `gh pr view`, `gh api`, and local main-branch files; if PR file contents are needed, use fetched refs with `git show <ref>:<path>` or temporary files. Read all relevant code files in full with no truncation and compare against the diff. Do not fetch PR file blobs unless a file is missing on main or the diff context is insufficient. Include related code paths that are not in the diff but are required to validate behavior.
|
||||
5. Do not check for a changelog entry. Per CONTRIBUTING.md, contributor PRs must not edit `CHANGELOG.md` — the maintainer adds the entry when merging.
|
||||
6. Check if packages/coding-agent/README.md, packages/coding-agent/docs/*.md, packages/coding-agent/examples/**/*.md require modification. This is usually the case when existing features have been changed, or new features have been added.
|
||||
6. Check if packages/coding-agent/README.md, docs/*.md, packages/coding-agent/examples/**/*.md require modification. This is usually the case when existing features have been changed, or new features have been added.
|
||||
7. Provide a structured review with these sections:
|
||||
- What it does: one short paragraph describing the change and its intent.
|
||||
- Good: solid choices or improvements.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Create a provider file exporting:
|
|||
- `src/core/provider-display-names.ts`: add API-key login display name so `/login` and related UI show the provider for built-in API-key auth.
|
||||
- `src/cli/args.ts`: add env var documentation.
|
||||
- `README.md`: add provider setup instructions.
|
||||
- `docs/providers.md`: add setup instructions, env var, and `auth.json` key.
|
||||
- `docs/providers.md` (repository root): add setup instructions, env var, and `auth.json` key.
|
||||
|
||||
## 7. Documentation
|
||||
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
Pi is a minimal, extensible agent harness that you can make your own.
|
||||
|
||||
Adapt Pi to your workflows, not the other way around. Customize Pi with [extensions](packages/coding-agent/docs/extensions.md), [skills](packages/coding-agent/docs/skills.md), [prompt templates](packages/coding-agent/docs/prompt-templates.md), and [themes](packages/coding-agent/docs/themes.md). Bundle them as [Pi packages](packages/coding-agent/docs/packages.md) and share via npm or git.
|
||||
Adapt Pi to your workflows, not the other way around. Customize Pi with [extensions](docs/extensions.md), [skills](docs/skills.md), [prompt templates](docs/prompt-templates.md), and [themes](docs/themes.md). Bundle them as [Pi packages](docs/packages.md) and share via npm or git.
|
||||
|
||||
Pi ships with powerful defaults but skips features like sub-agents and plan mode. Ask Pi to build what you want, or install a package that does it your way.
|
||||
|
||||
Use Pi [interactively](packages/coding-agent/docs/usage.md), automate it in [print or JSON mode](packages/coding-agent/docs/cli.md), control it over [RPC](packages/coding-agent/docs/rpc.md), or build apps with the [Pi TypeScript SDK](packages/coding-agent/docs/sdk.md). See [OpenClaw](https://github.com/OpenClaw/OpenClaw) for a real-world integration.
|
||||
Use Pi [interactively](docs/usage.md), automate it in [print or JSON mode](docs/cli.md), control it over [RPC](docs/rpc.md), or build apps with the [Pi TypeScript SDK](docs/sdk.md). See [OpenClaw](https://github.com/OpenClaw/OpenClaw) for a real-world integration.
|
||||
|
||||
## Getting started
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ For Slack/chat automation and workflows see [earendil-works/pi-chat](https://git
|
|||
|
||||
Pi does not include a built-in permission system for restricting filesystem, process, network, or credential access. By default, it runs with the permissions of the user and process that launched it.
|
||||
|
||||
If you need stronger boundaries, containerize or sandbox Pi. See [packages/coding-agent/docs/containerization.md](packages/coding-agent/docs/containerization.md) for three patterns:
|
||||
If you need stronger boundaries, containerize or sandbox Pi. See [docs/containerization.md](docs/containerization.md) for three patterns:
|
||||
|
||||
- **Gondolin extension**: keep `pi` and provider auth on the host while routing built-in tools and `!` commands into a local Linux micro-VM.
|
||||
- **Plain Docker**: run the whole `pi` process in a local container for simple isolation.
|
||||
|
|
@ -202,5 +202,5 @@ MIT
|
|||
<p align="center">
|
||||
<a href="https://pi.dev">pi.dev</a> domain graciously donated by
|
||||
<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="docs/images/exy.png" alt="Exy mascot" width="48" /><br />exe.dev</a>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ Extension dialogs form a request-response subprotocol. Other extension UI update
|
|||
|
||||
For Node.js or TypeScript integrations, prefer `RpcClient` from `@earendil-works/pi-coding-agent`. It starts a Pi RPC child process, correlates requests, exposes typed command methods, and delivers session events to listeners.
|
||||
|
||||
The [RPC client example](../examples/rpc-client.ts) sends one prompt, streams text and tool activity, waits for `agent_settled`, and shuts down the child process. It is included in the repository’s TypeScript checks.
|
||||
The [RPC client example](../packages/coding-agent/examples/rpc-client.ts) sends one prompt, streams text and tool activity, waits for `agent_settled`, and shuts down the child process. It is included in the repository’s TypeScript checks.
|
||||
|
||||
`RpcClient.promptAndWait()` installs its event listener before sending the prompt, avoiding a race with fast completions. For separate operations, subscribe before calling `prompt()` and call `waitForIdle()` only while a run is active.
|
||||
|
||||
|
|
@ -96,11 +96,11 @@ Change the top-level `bin` field to set the executable name. These settings affe
|
|||
|
||||
## Examples and references
|
||||
|
||||
- [RPC client](../examples/rpc-client.ts): typed Node.js integration
|
||||
- [RPC extension UI](../examples/rpc-extension-ui.ts): custom terminal client with extension dialogs
|
||||
- [RPC client](../packages/coding-agent/examples/rpc-client.ts): typed Node.js integration
|
||||
- [RPC extension UI](../packages/coding-agent/examples/rpc-extension-ui.ts): custom terminal client with extension dialogs
|
||||
- [Command Line](cli.md): startup options and mode selection
|
||||
- [JSON Event Stream](json.md): JSON event reference
|
||||
- [RPC Protocol](rpc.md): RPC lifecycle, framing, errors, and shutdown
|
||||
- [RPC Commands](rpc-commands.md): command and response reference
|
||||
- [RPC Extension UI](rpc-extension-ui.md): extension interaction subprotocol
|
||||
- [SDK examples](../examples/sdk/): in-process TypeScript integrations
|
||||
- [SDK examples](../packages/coding-agent/examples/sdk/): in-process TypeScript integrations
|
||||
|
|
@ -365,7 +365,7 @@ pi.on("session_before_compact", async (event, ctx) => {
|
|||
});
|
||||
```
|
||||
|
||||
See [custom-compaction.ts](../examples/extensions/custom-compaction.ts) for a complete example using a different model.
|
||||
See [custom-compaction.ts](../packages/coding-agent/examples/extensions/custom-compaction.ts) for a complete example using a different model.
|
||||
|
||||
### session_compact_failed
|
||||
|
||||
|
|
@ -180,4 +180,4 @@ pi -e ~/.pi/agent/extensions/gondolin
|
|||
|
||||
The extension mounts the host working folder at `/workspace` in the VM and overrides `read`, `write`, `edit`, `bash`, `grep`, `find`, and `ls`. File changes under `/workspace` write through to the host.
|
||||
|
||||
Other extension tools still run on the host unless they explicitly delegate their operations. Review the [Gondolin example](../examples/extensions/gondolin/) before adding tools that could bypass the VM boundary.
|
||||
Other extension tools still run on the host unless they explicitly delegate their operations. Review the [Gondolin example](../packages/coding-agent/examples/extensions/gondolin/) before adding tools that could bypass the VM boundary.
|
||||
|
|
@ -121,7 +121,7 @@ Model-level `baseUrl` values take precedence over the provider endpoint. If no `
|
|||
|
||||
Calls made after initial extension loading take effect immediately. Use `pi.unregisterProvider()` to remove the dynamic provider and restore built-in behavior that it replaced.
|
||||
|
||||
See the checked [GitLab Duo provider](../examples/extensions/custom-provider-gitlab-duo/) for a complete registration that delegates streaming to built-in API implementations.
|
||||
See the checked [GitLab Duo provider](../packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/) for a complete registration that delegates streaming to built-in API implementations.
|
||||
|
||||
## Provide authentication
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ Notification handlers should not perform slow work on a streaming event. Transfo
|
|||
|
||||
`provider_stream_event` fires for each parsed provider stream event before Pi normalizes it. The event identifies the provider, API, and model; `event.data` is the earliest structured value available to Pi, not necessarily the original HTTP bytes or SSE frame. Treat it as read-only because mutation can affect normalization. The event is notification-only and is not persisted.
|
||||
|
||||
Handlers are awaited in stream order, so slow handlers delay stream consumption. Handler errors are reported without changing the provider response. See [`debug-provider.ts`](../examples/extensions/debug-provider.ts) for an opt-in viewer that groups raw events by assistant message.
|
||||
Handlers are awaited in stream order, so slow handlers delay stream consumption. Handler errors are reported without changing the provider response. See [`debug-provider.ts`](../packages/coding-agent/examples/extensions/debug-provider.ts) for an opt-in viewer that groups raw events by assistant message.
|
||||
|
||||
<a id="context_with_system"></a>
|
||||
|
||||
|
|
@ -243,7 +243,7 @@ Declare `outputSchema` and return a matching `structuredContent` when the result
|
|||
|
||||
A tool can run other tools with `ctx.executeTool(name, args, { signal, onUpdate })`. Nested calls go through argument validation and the `tool_call` and `tool_result` handlers like model-issued calls, and emit `tool_execution_start`, `tool_execution_update`, and `tool_execution_end`; all of these events carry `parentToolCallId`, and their `toolCallId` is assigned by pi as `<parent id>/<n>`. These ids do not appear as tool calls or tool results in the transcript. Nested calls do not add transcript entries: their results only reach the calling tool, which reports them itself, for example through `onUpdate` and `details`. The session keeps a bounded record of them (name, arguments, status, duration, error; never results) as `nestedCalls` on the calling tool's result message. It is used for compaction file lists and shown in HTML exports. Arguments over 8 KiB per call or 32 KiB per tool result are omitted, at most 256 calls are kept, and `complete: false` marks a record that lost anything. The `usage` of nested results, at every depth, is added to the calling tool's result `usage`, so a tool reports only its own usage, not that of the tools it called. `ctx.tools` lists the tools `ctx.executeTool()` can call. `tool_result` handlers that redact `content` should also replace `structuredContent`; replacing only `content` drops it.
|
||||
|
||||
See [`hello.ts`](../examples/extensions/hello.ts), [`todo.ts`](../examples/extensions/todo.ts), [`dynamic-tools.ts`](../examples/extensions/dynamic-tools.ts), and [`truncated-tool.ts`](../examples/extensions/truncated-tool.ts).
|
||||
See [`hello.ts`](../packages/coding-agent/examples/extensions/hello.ts), [`todo.ts`](../packages/coding-agent/examples/extensions/todo.ts), [`dynamic-tools.ts`](../packages/coding-agent/examples/extensions/dynamic-tools.ts), and [`truncated-tool.ts`](../packages/coding-agent/examples/extensions/truncated-tool.ts).
|
||||
|
||||
### Tool exposure
|
||||
|
||||
|
|
@ -366,18 +366,18 @@ Use `ctx.shutdown()` to request an orderly process shutdown.
|
|||
|
||||
## Examples and reference
|
||||
|
||||
The checked [extension examples](../examples/extensions/) are the implementation reference. Start with the smallest example matching the behavior you need:
|
||||
The checked [extension examples](../packages/coding-agent/examples/extensions/) are the implementation reference. Start with the smallest example matching the behavior you need:
|
||||
|
||||
| Goal | Start with | Why |
|
||||
|---|---|---|
|
||||
| Confirm or block tool calls | [`permission-gate.ts`](../examples/extensions/permission-gate.ts) | Combines `tool_call`, mode-aware UI, and fail-closed behavior. |
|
||||
| Modify prompt sections for a run | [`prompt-customizer.ts`](../examples/extensions/prompt-customizer.ts) | Uses structured prompt options instead of replacing the complete prompt. |
|
||||
| Keep branch-aware tool state | [`todo.ts`](../examples/extensions/todo.ts) | Reconstructs state from persisted entries and renders it in the TUI. |
|
||||
| Register tools after startup | [`dynamic-tools.ts`](../examples/extensions/dynamic-tools.ts) | Shares registration logic between lifecycle and command handlers. |
|
||||
| Run cancellable model work from a command | [`qna.ts`](../examples/extensions/qna.ts) | Combines nested model calls, cancellation, and custom UI. |
|
||||
| Replace the main editor | [`modal-editor.ts`](../examples/extensions/modal-editor.ts) | Extends `CustomEditor` while preserving application controls. |
|
||||
| Run finalization at shutdown | [`auto-commit-on-exit.ts`](../examples/extensions/auto-commit-on-exit.ts) | Uses the session shutdown hook for finalization work. |
|
||||
| Route built-in tools to another machine | [`ssh.ts`](../examples/extensions/ssh.ts) | Reuses tool operation interfaces instead of recreating tool contracts. |
|
||||
| Add OAuth and provider-specific streaming | [`custom-provider-gitlab-duo/`](../examples/extensions/custom-provider-gitlab-duo/) | Shows a complete provider integration while delegating supported protocols. |
|
||||
| Confirm or block tool calls | [`permission-gate.ts`](../packages/coding-agent/examples/extensions/permission-gate.ts) | Combines `tool_call`, mode-aware UI, and fail-closed behavior. |
|
||||
| Modify prompt sections for a run | [`prompt-customizer.ts`](../packages/coding-agent/examples/extensions/prompt-customizer.ts) | Uses structured prompt options instead of replacing the complete prompt. |
|
||||
| Keep branch-aware tool state | [`todo.ts`](../packages/coding-agent/examples/extensions/todo.ts) | Reconstructs state from persisted entries and renders it in the TUI. |
|
||||
| Register tools after startup | [`dynamic-tools.ts`](../packages/coding-agent/examples/extensions/dynamic-tools.ts) | Shares registration logic between lifecycle and command handlers. |
|
||||
| Run cancellable model work from a command | [`qna.ts`](../packages/coding-agent/examples/extensions/qna.ts) | Combines nested model calls, cancellation, and custom UI. |
|
||||
| Replace the main editor | [`modal-editor.ts`](../packages/coding-agent/examples/extensions/modal-editor.ts) | Extends `CustomEditor` while preserving application controls. |
|
||||
| Run finalization at shutdown | [`auto-commit-on-exit.ts`](../packages/coding-agent/examples/extensions/auto-commit-on-exit.ts) | Uses the session shutdown hook for finalization work. |
|
||||
| Route built-in tools to another machine | [`ssh.ts`](../packages/coding-agent/examples/extensions/ssh.ts) | Reuses tool operation interfaces instead of recreating tool contracts. |
|
||||
| Add OAuth and provider-specific streaming | [`custom-provider-gitlab-duo/`](../packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/) | Shows a complete provider integration while delegating supported protocols. |
|
||||
|
||||
Use [Custom Providers](custom-provider.md) for model-service integrations, [Terminal UI](tui.md) for custom components, and [Pi Packages](packages.md) to install or distribute extensions with other resources. Use the exported declarations for exact signatures, payloads, and result schemas; this guide focuses on lifecycle choices, composition, and durable implementation patterns.
|
||||
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 507 KiB After Width: | Height: | Size: 507 KiB |
|
Before Width: | Height: | Size: 275 KiB After Width: | Height: | Size: 275 KiB |
|
|
@ -195,6 +195,6 @@ Dismiss any dialog method. The extension receives `undefined` (for select/input/
|
|||
|
||||
## Example
|
||||
|
||||
See the checked [RPC extension UI client](../examples/rpc-extension-ui.ts) and its [demo extension](../examples/extensions/rpc-demo.ts).
|
||||
See the checked [RPC extension UI client](../packages/coding-agent/examples/rpc-extension-ui.ts) and its [demo extension](../packages/coding-agent/examples/extensions/rpc-demo.ts).
|
||||
|
||||
The exported request and response unions are defined in [`rpc-types.ts`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/modes/rpc/rpc-types.ts). See [Extensions](extensions.md#ui-and-modes) for mode-independent extension guidance.
|
||||
|
|
@ -129,7 +129,7 @@ process.stdin.close()
|
|||
process.wait()
|
||||
```
|
||||
|
||||
For maintained TypeScript clients, use the checked [RPC client example](../examples/rpc-client.ts). It requires a built Pi CLI because the repository example points to `dist/cli.js`.
|
||||
For maintained TypeScript clients, use the checked [RPC client example](../packages/coding-agent/examples/rpc-client.ts). It requires a built Pi CLI because the repository example points to `dist/cli.js`.
|
||||
|
||||
## Reference
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ try {
|
|||
|
||||
This uses the working directory, discovered resources, stored settings, and configured credentials. `prompt()` resolves when the run finishes.
|
||||
|
||||
The [complete minimal example](../examples/sdk/01-minimal.ts) also streams text events. All [SDK examples](../examples/sdk/) are typechecked with the repository.
|
||||
The [complete minimal example](../packages/coding-agent/examples/sdk/01-minimal.ts) also streams text events. All [SDK examples](../packages/coding-agent/examples/sdk/) are typechecked with the repository.
|
||||
|
||||
<a id="session-management"></a>
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ const { session } = await createAgentSession({
|
|||
});
|
||||
```
|
||||
|
||||
See the checked [sessions example](../examples/sdk/11-sessions.ts) for creating, opening, continuing, listing, and forking sessions. [Session File Format](session-format.md) defines the persisted JSONL contract, and [Message Types](message-types.md) defines transcript values. For exact methods and signatures, use the exported TypeScript declarations or [`session-manager.ts`](../src/core/session-manager.ts).
|
||||
See the checked [sessions example](../packages/coding-agent/examples/sdk/11-sessions.ts) for creating, opening, continuing, listing, and forking sessions. [Session File Format](session-format.md) defines the persisted JSONL contract, and [Message Types](message-types.md) defines transcript values. For exact methods and signatures, use the exported TypeScript declarations or [`session-manager.ts`](../packages/coding-agent/src/core/session-manager.ts).
|
||||
|
||||
`cwd` selects the workspace used for project resource discovery, context files, session grouping, and built-in tool paths. Pass it explicitly when the target differs from `process.cwd()`.
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ See the checked [sessions example](../examples/sdk/11-sessions.ts) for creating,
|
|||
|
||||
`AgentSessionRuntime` adds `newSession()`, `switchSession()`, `fork()`, and `importFromJsonl()`. Each operation replaces the active `AgentSession` and recreates services for the target working directory.
|
||||
|
||||
After a runtime replacement, subscriptions belong to the old `AgentSession` and must be rebound. See the [session runtime example](../examples/sdk/13-session-runtime.ts).
|
||||
After a runtime replacement, subscriptions belong to the old `AgentSession` and must be rebound. See the [session runtime example](../packages/coding-agent/examples/sdk/13-session-runtime.ts).
|
||||
|
||||
## Prompting
|
||||
|
||||
|
|
@ -113,28 +113,28 @@ Inline extension factories can be supplied through `DefaultResourceLoader`. Give
|
|||
|
||||
<a id="codemode-mcp"></a>
|
||||
|
||||
The CLI loads `codemode`, `tool_search`, and MCP as built-in extensions. SDK sessions do not; add `createCodemodeExtension()`, `createToolSearchExtension()`, and `createMcpExtension()` to the `extensionFactories` of `DefaultResourceLoader`. `codemode` and `tool_search` are registered inactive: enable them through the `defaultTools` setting (`["+codemode", "+tool_search"]` keeps the other default tools), or let the MCP extension activate them: `codemode` for servers with `codemode` exposure, `tool_search` for servers with `deferred` exposure. The MCP extension connects its servers on `session_start`, so call `session.bindExtensions()`. See [Codemode and MCP](../examples/sdk/14-codemode-mcp.ts).
|
||||
The CLI loads `codemode`, `tool_search`, and MCP as built-in extensions. SDK sessions do not; add `createCodemodeExtension()`, `createToolSearchExtension()`, and `createMcpExtension()` to the `extensionFactories` of `DefaultResourceLoader`. `codemode` and `tool_search` are registered inactive: enable them through the `defaultTools` setting (`["+codemode", "+tool_search"]` keeps the other default tools), or let the MCP extension activate them: `codemode` for servers with `codemode` exposure, `tool_search` for servers with `deferred` exposure. The MCP extension connects its servers on `session_start`, so call `session.bindExtensions()`. See [Codemode and MCP](../packages/coding-agent/examples/sdk/14-codemode-mcp.ts).
|
||||
|
||||
See the focused examples for [models](../examples/sdk/02-custom-model.ts), [tools](../examples/sdk/05-tools.ts), [extensions](../examples/sdk/06-extensions.ts), and [full control](../examples/sdk/12-full-control.ts).
|
||||
See the focused examples for [models](../packages/coding-agent/examples/sdk/02-custom-model.ts), [tools](../packages/coding-agent/examples/sdk/05-tools.ts), [extensions](../packages/coding-agent/examples/sdk/06-extensions.ts), and [full control](../packages/coding-agent/examples/sdk/12-full-control.ts).
|
||||
|
||||
## Examples
|
||||
|
||||
| Example | Purpose |
|
||||
|---|---|
|
||||
| [Minimal](../examples/sdk/01-minimal.ts) | Create, prompt, observe, and dispose a session |
|
||||
| [Custom model](../examples/sdk/02-custom-model.ts) | Select a model and thinking level |
|
||||
| [System prompt](../examples/sdk/03-custom-prompt.ts) | Replace or append to the system prompt |
|
||||
| [Skills](../examples/sdk/04-skills.ts) | Discover, filter, and add skills |
|
||||
| [Tools](../examples/sdk/05-tools.ts) | Select built-in tools and their working directory |
|
||||
| [Extensions](../examples/sdk/06-extensions.ts) | Load file-based and inline extensions |
|
||||
| [Context files](../examples/sdk/07-context-files.ts) | Add or replace project instructions |
|
||||
| [Prompt templates](../examples/sdk/08-prompt-templates.ts) | Add file-style prompt templates |
|
||||
| [Credentials](../examples/sdk/09-api-keys-and-oauth.ts) | Configure credential and model storage |
|
||||
| [Settings](../examples/sdk/10-settings.ts) | Supply file-backed or in-memory settings |
|
||||
| [Sessions](../examples/sdk/11-sessions.ts) | Control session persistence and restoration |
|
||||
| [Full control](../examples/sdk/12-full-control.ts) | Replace default discovery and state services |
|
||||
| [Session runtime](../examples/sdk/13-session-runtime.ts) | Replace the active session safely |
|
||||
| [Codemode and MCP](../examples/sdk/14-codemode-mcp.ts) | Add the `codemode`, `tool_search`, and MCP extensions |
|
||||
| [Minimal](../packages/coding-agent/examples/sdk/01-minimal.ts) | Create, prompt, observe, and dispose a session |
|
||||
| [Custom model](../packages/coding-agent/examples/sdk/02-custom-model.ts) | Select a model and thinking level |
|
||||
| [System prompt](../packages/coding-agent/examples/sdk/03-custom-prompt.ts) | Replace or append to the system prompt |
|
||||
| [Skills](../packages/coding-agent/examples/sdk/04-skills.ts) | Discover, filter, and add skills |
|
||||
| [Tools](../packages/coding-agent/examples/sdk/05-tools.ts) | Select built-in tools and their working directory |
|
||||
| [Extensions](../packages/coding-agent/examples/sdk/06-extensions.ts) | Load file-based and inline extensions |
|
||||
| [Context files](../packages/coding-agent/examples/sdk/07-context-files.ts) | Add or replace project instructions |
|
||||
| [Prompt templates](../packages/coding-agent/examples/sdk/08-prompt-templates.ts) | Add file-style prompt templates |
|
||||
| [Credentials](../packages/coding-agent/examples/sdk/09-api-keys-and-oauth.ts) | Configure credential and model storage |
|
||||
| [Settings](../packages/coding-agent/examples/sdk/10-settings.ts) | Supply file-backed or in-memory settings |
|
||||
| [Sessions](../packages/coding-agent/examples/sdk/11-sessions.ts) | Control session persistence and restoration |
|
||||
| [Full control](../packages/coding-agent/examples/sdk/12-full-control.ts) | Replace default discovery and state services |
|
||||
| [Session runtime](../packages/coding-agent/examples/sdk/13-session-runtime.ts) | Replace the active session safely |
|
||||
| [Codemode and MCP](../packages/coding-agent/examples/sdk/14-codemode-mcp.ts) | Add the `codemode`, `tool_search`, and MCP extensions |
|
||||
|
||||
<a id="exports"></a>
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ Treat each custom component instance as belonging to one interaction. Create a n
|
|||
|
||||
Finish the interaction with the completion callback supplied to the component factory. It resolves the `ctx.ui.custom()` promise and disposes the component. Do not call `OverlayHandle.hide()` on an overlay created by `ctx.ui.custom()`.
|
||||
|
||||
See [`overlay-qa-tests.ts`](../examples/extensions/overlay-qa-tests.ts) for positioning, stacking, focus, responsive visibility, and animation behavior.
|
||||
See [`overlay-qa-tests.ts`](../packages/coding-agent/examples/extensions/overlay-qa-tests.ts) for positioning, stacking, focus, responsive visibility, and animation behavior.
|
||||
|
||||
## Apply themes correctly
|
||||
|
||||
|
|
@ -185,11 +185,11 @@ Use `PI_TUI_WRITE_LOG` to capture the raw ANSI stream when diagnosing rendering
|
|||
|
||||
The checked extension examples cover the main patterns:
|
||||
|
||||
- [`preset.ts`](../examples/extensions/preset.ts) and [`tools.ts`](../examples/extensions/tools.ts) use selection and settings lists.
|
||||
- [`qna.ts`](../examples/extensions/qna.ts) uses cancellable asynchronous UI.
|
||||
- [`modal-editor.ts`](../examples/extensions/modal-editor.ts) replaces the editor.
|
||||
- [`custom-footer.ts`](../examples/extensions/custom-footer.ts) replaces the footer.
|
||||
- [`widget-placement.ts`](../examples/extensions/widget-placement.ts) places persistent content around the editor.
|
||||
- [`doom-overlay/`](../examples/extensions/doom-overlay/) demonstrates a continuously rendered overlay.
|
||||
- [`preset.ts`](../packages/coding-agent/examples/extensions/preset.ts) and [`tools.ts`](../packages/coding-agent/examples/extensions/tools.ts) use selection and settings lists.
|
||||
- [`qna.ts`](../packages/coding-agent/examples/extensions/qna.ts) uses cancellable asynchronous UI.
|
||||
- [`modal-editor.ts`](../packages/coding-agent/examples/extensions/modal-editor.ts) replaces the editor.
|
||||
- [`custom-footer.ts`](../packages/coding-agent/examples/extensions/custom-footer.ts) replaces the footer.
|
||||
- [`widget-placement.ts`](../packages/coding-agent/examples/extensions/widget-placement.ts) places persistent content around the editor.
|
||||
- [`doom-overlay/`](../packages/coding-agent/examples/extensions/doom-overlay/) demonstrates a continuously rendered overlay.
|
||||
|
||||
The public exports are defined in [`packages/tui/src/index.ts`](https://github.com/earendil-works/pi/blob/main/packages/tui/src/index.ts). See [Extensions](extensions.md) for extension lifecycle, state, tools, events, and mode behavior.
|
||||
|
|
@ -111,4 +111,4 @@ The transcript already records the selection and every dispatched model, and `ct
|
|||
|
||||
Routers can call other models through `ctx.modelRegistry`, for example `ctx.modelRegistry.classify()` with a classifier model from `ctx.modelRegistry.findOfType("classifier", provider, id)`. The call adds latency before the first token of the turn.
|
||||
|
||||
See [`jev-router.ts`](../examples/extensions/jev-router.ts) for a complete router. It plans on a strong OpenAI Codex model chosen by the Jev classifier, lets that model make the first edit, and then switches once to a cheaper model, accepting a single prompt-cache miss. It keeps the phase as router state.
|
||||
See [`jev-router.ts`](../packages/coding-agent/examples/extensions/jev-router.ts) for a complete router. It plans on a strong OpenAI Codex model chosen by the Jev classifier, lets that model make the first edit, and then switches once to a cheaper model, accepting a single prompt-cache miss. It keeps the phase as router state.
|
||||
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
Pi is a minimal, extensible agent harness that you can make your own.
|
||||
|
||||
Adapt Pi to your workflows, not the other way around. Customize Pi with [extensions](docs/extensions.md), [skills](docs/skills.md), [prompt templates](docs/prompt-templates.md), and [themes](docs/themes.md). Bundle them as [Pi packages](docs/packages.md) and share via npm or git.
|
||||
Adapt Pi to your workflows, not the other way around. Customize Pi with [extensions](../../docs/extensions.md), [skills](../../docs/skills.md), [prompt templates](../../docs/prompt-templates.md), and [themes](../../docs/themes.md). Bundle them as [Pi packages](../../docs/packages.md) and share via npm or git.
|
||||
|
||||
Pi ships with powerful defaults but skips features like sub-agents and plan mode. Ask Pi to build what you want, or install a package that does it your way.
|
||||
|
||||
Use Pi [interactively](docs/usage.md), automate it in [print or JSON mode](docs/cli.md), control it over [RPC](docs/rpc.md), or build apps with the [Pi TypeScript SDK](docs/sdk.md). See [OpenClaw](https://github.com/OpenClaw/OpenClaw) for a real-world integration.
|
||||
Use Pi [interactively](../../docs/usage.md), automate it in [print or JSON mode](../../docs/cli.md), control it over [RPC](../../docs/rpc.md), or build apps with the [Pi TypeScript SDK](../../docs/sdk.md). See [OpenClaw](https://github.com/OpenClaw/OpenClaw) for a real-world integration.
|
||||
|
||||
## Getting started
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ npm install -g --ignore-scripts @earendil-works/pi-coding-agent
|
|||
|
||||
Pi requires Node.js 22.19 or newer. The macOS, Linux, and Windows installers can install it if needed. Pi does not require dependency lifecycle scripts for a normal npm installation.
|
||||
|
||||
On macOS and Linux, Nix users can install the latest release with `nix profile add github:earendil-works/pi/stable`. See the [quickstart](docs/quickstart.md#1-install-pi) for updating and pinning releases.
|
||||
On macOS and Linux, Nix users can install the latest release with `nix profile add github:earendil-works/pi/stable`. See the [quickstart](../../docs/quickstart.md#1-install-pi) for updating and pinning releases.
|
||||
|
||||
Start Pi in the directory where you want it to work:
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ pi
|
|||
|
||||
For a built-in AI provider, run `/login` inside Pi to connect a subscription or API key. Then give Pi a task.
|
||||
|
||||
See the [documentation](docs/index.md) for full setup and usage instructions.
|
||||
See the [documentation](../../docs/index.md) for full setup and usage instructions.
|
||||
|
||||
## Share your OSS coding agent sessions
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@
|
|||
"scripts": {
|
||||
"clean": "shx rm -rf dist",
|
||||
"build": "npm run build:unbundled && node ../../scripts/build-coding-agent-bundle.mjs",
|
||||
"build:unbundled": "tsc -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets",
|
||||
"build:unbundled": "tsc -p tsconfig.build.json && shx chmod +x dist/cli.js dist/rpc-entry.js && npm run copy-assets && npm run copy-docs",
|
||||
"build:binary": "npm --prefix ../tui run build && npm --prefix ../telemetry run build && npm --prefix ../ai run build && npm --prefix ../agent run build && npm run build && bun build --compile --no-compile-autoload-bunfig --no-compile-autoload-dotenv ./dist/bun/cli.js ./src/utils/image-resize-worker.ts ./src/extensions/codemode/worker.ts --outfile dist/pi && 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/modes/interactive/assets && shx cp src/modes/interactive/assets/*.png dist/modes/interactive/assets/ && 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-docs": "node scripts/copy-docs.mjs",
|
||||
"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/assets && shx cp src/modes/interactive/assets/*.png dist/assets/ && 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",
|
||||
"generate:schemas": "node --import ./src/experimental/source-resolver.ts scripts/generate-schemas.ts",
|
||||
|
|
|
|||
43
packages/coding-agent/scripts/copy-docs.mjs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
// Copies the repository documentation (docs/) into this package (packages/coding-agent/docs/, gitignored)
|
||||
// so the npm package and the release binaries ship it. npm can only pack files inside the package, and
|
||||
// every release path packs after the build, so this runs as part of the build.
|
||||
//
|
||||
// The docs link to coding-agent files through the repository layout, e.g.
|
||||
// ../packages/coding-agent/examples/sdk/. The package has the same files at ../examples/sdk/ relative to
|
||||
// its docs/, so links that point into this package are rewritten to package-relative paths. Links to
|
||||
// other repository files are left unchanged.
|
||||
|
||||
import { cpSync, globSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { dirname, join, relative, resolve, sep } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const packageDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const sourceDir = resolve(packageDir, "../../docs");
|
||||
const targetDir = join(packageDir, "docs");
|
||||
|
||||
// Relative targets of inline Markdown links and HTML src attributes, without query or fragment.
|
||||
const RELATIVE_LINK_RE = /(\]\(|src=")(\.\.?\/[^)"\s?#]*)/g;
|
||||
|
||||
function toPackageRelativeLink(sourceFile, targetFile, link) {
|
||||
const linkedPath = resolve(dirname(sourceFile), link);
|
||||
const packageRelativePath = relative(packageDir, linkedPath);
|
||||
if (packageRelativePath.startsWith(`..${sep}`) || packageRelativePath === "..") return link;
|
||||
const rewritten = relative(dirname(targetFile), linkedPath).split(sep).join("/");
|
||||
return link.endsWith("/") ? `${rewritten}/` : rewritten;
|
||||
}
|
||||
|
||||
rmSync(targetDir, { recursive: true, force: true });
|
||||
cpSync(sourceDir, targetDir, { recursive: true });
|
||||
|
||||
for (const path of globSync("**/*.md", { cwd: sourceDir })) {
|
||||
const sourceFile = join(sourceDir, path);
|
||||
const targetFile = join(targetDir, path);
|
||||
const markdown = readFileSync(sourceFile, "utf8");
|
||||
const rewritten = markdown.replace(
|
||||
RELATIVE_LINK_RE,
|
||||
(_match, prefix, link) => `${prefix}${toPackageRelativeLink(sourceFile, targetFile, link)}`,
|
||||
);
|
||||
if (rewritten !== markdown) writeFileSync(targetFile, rewritten);
|
||||
}
|
||||
|
|
@ -445,9 +445,17 @@ export function getReadmePath(): string {
|
|||
return resolve(join(getPackageDir(), "README.md"));
|
||||
}
|
||||
|
||||
/** Get path to docs directory */
|
||||
/**
|
||||
* Get path to docs directory
|
||||
* - For source checkouts: the repository docs/ (the source of truth)
|
||||
* - For npm installs and the Bun binary: docs/ in the package, copied there by scripts/copy-docs.mjs
|
||||
*/
|
||||
export function getDocsPath(): string {
|
||||
return resolve(join(getPackageDir(), "docs"));
|
||||
const packageDir = getPackageDir();
|
||||
if (!isBunBinary && existsSync(join(packageDir, "src"))) {
|
||||
return resolve(packageDir, "..", "..", "docs");
|
||||
}
|
||||
return resolve(join(packageDir, "docs"));
|
||||
}
|
||||
|
||||
/** Get path to examples directory */
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
import { basename, dirname, isAbsolute, relative, resolve as resolvePath, sep } from "node:path";
|
||||
import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
|
||||
import { Text } from "@earendil-works/pi-tui";
|
||||
import { getReadmePath } from "../../../config.ts";
|
||||
import { getDocsPath, getReadmePath } from "../../../config.ts";
|
||||
import { keyHint, keyText } from "../../../modes/interactive/components/keybinding-hints.ts";
|
||||
import { getLanguageFromPath, highlightCode, type Theme } from "../../../modes/interactive/theme/theme.ts";
|
||||
import { formatPathRelativeToCwdOrAbsolute } from "../../../utils/paths.ts";
|
||||
|
|
@ -43,9 +43,8 @@ function trimTrailingEmptyLines(lines: string[]): string[] {
|
|||
function toPosixPath(filePath: string): string {
|
||||
return filePath.split(sep).join("/");
|
||||
}
|
||||
function getPiDocsClassification(absolutePath: string): CompactReadClassification | undefined {
|
||||
const packageRoot = dirname(getReadmePath());
|
||||
const relativePath = relative(resolvePath(packageRoot), resolvePath(absolutePath));
|
||||
function getContainedRelativePath(directory: string, absolutePath: string): string | undefined {
|
||||
const relativePath = relative(resolvePath(directory), resolvePath(absolutePath));
|
||||
if (
|
||||
relativePath === "" ||
|
||||
relativePath === ".." ||
|
||||
|
|
@ -54,9 +53,17 @@ function getPiDocsClassification(absolutePath: string): CompactReadClassificatio
|
|||
) {
|
||||
return undefined;
|
||||
}
|
||||
return toPosixPath(relativePath);
|
||||
}
|
||||
function getPiDocsClassification(absolutePath: string): CompactReadClassification | undefined {
|
||||
// Docs live outside the package root in source checkouts, so check them separately.
|
||||
const docsPath = getContainedRelativePath(getDocsPath(), absolutePath);
|
||||
if (docsPath) {
|
||||
return { kind: "docs", label: `docs/${docsPath}` };
|
||||
}
|
||||
|
||||
const label = toPosixPath(relativePath);
|
||||
if (label === "README.md" || label.startsWith("docs/") || label.startsWith("examples/")) {
|
||||
const label = getContainedRelativePath(dirname(getReadmePath()), absolutePath);
|
||||
if (label === "README.md" || label?.startsWith("examples/")) {
|
||||
return { kind: "docs", label };
|
||||
}
|
||||
return undefined;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { stripBom } from "./utils/text.ts";
|
|||
|
||||
const MIGRATION_GUIDE_URL =
|
||||
"https://github.com/earendil-works/pi/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration";
|
||||
const EXTENSIONS_DOC_URL = "https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md";
|
||||
const EXTENSIONS_DOC_URL = "https://github.com/earendil-works/pi/blob/main/docs/extensions.md";
|
||||
|
||||
/**
|
||||
* Migrate legacy oauth.json and settings.json apiKeys to auth.json.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ interface NavigationGroup {
|
|||
items: NavigationItem[];
|
||||
}
|
||||
|
||||
const docsRoot = resolve(import.meta.dirname, "../docs");
|
||||
const docsRoot = resolve(import.meta.dirname, "../../../docs");
|
||||
|
||||
function requireObject(value: unknown, location: string): Record<string, unknown> {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { resetCapabilitiesCache, setCapabilities, Text, type TUI, type TuiMouseE
|
|||
import { Type } from "typebox";
|
||||
import { afterEach, beforeAll, describe, expect, test, vi } from "vitest";
|
||||
|
||||
import { getReadmePath } from "../src/config.ts";
|
||||
import { getDocsPath, getReadmePath } from "../src/config.ts";
|
||||
import type { ToolDefinition } from "../src/core/extensions/types.ts";
|
||||
import { type BashOperations, createBashToolDefinition } from "../src/core/tools/bash.ts";
|
||||
import { createReadTool, createReadToolDefinition } from "../src/core/tools/read.ts";
|
||||
|
|
@ -672,6 +672,14 @@ describe("ToolExecutionComponent parity", () => {
|
|||
hidden: "Hidden docs content",
|
||||
absent: undefined,
|
||||
},
|
||||
{
|
||||
title: "Pi documentation page",
|
||||
path: join(getDocsPath(), "extensions.md"),
|
||||
content: "Hidden docs page content",
|
||||
compact: "read docs docs/extensions.md",
|
||||
hidden: "Hidden docs page content",
|
||||
absent: undefined,
|
||||
},
|
||||
] as const) {
|
||||
test(`renders ${scenario.title} read results compactly until expanded`, () => {
|
||||
const component = new ToolExecutionComponent(
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const submitAudit = defineTool({
|
|||
});
|
||||
|
||||
const repositoryRoot = resolve(import.meta.dirname, "../../..");
|
||||
const docsRoot = resolve(repositoryRoot, "packages/coding-agent/docs");
|
||||
const docsRoot = resolve(repositoryRoot, "docs");
|
||||
const pages = globSync("**/*.md", { cwd: docsRoot })
|
||||
.map((path) => ({ path: path.replaceAll("\\", "/") }))
|
||||
.sort((left, right) => left.path.localeCompare(right.path));
|
||||
|
|
|
|||