From 91a7019fceb65f965f1d24248bf06d45d179b92f Mon Sep 17 00:00:00 2001 From: Christian Klotz Date: Wed, 14 Oct 2026 02:51:22 +0100 Subject: [PATCH] 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 /docs unchanged. getDocsPath() returns the repository docs/ in source checkouts. --- .gitignore | 2 + .pi/prompts/pr.md | 2 +- .pi/skills/add-llm-provider.md | 2 +- README.md | 8 ++-- .../docs => docs}/cli-integration.md | 8 ++-- {packages/coding-agent/docs => docs}/cli.md | 0 .../coding-agent/docs => docs}/codemode.md | 0 .../coding-agent/docs => docs}/compaction.md | 2 +- .../docs => docs}/configuration.md | 0 .../docs => docs}/containerization.md | 2 +- .../docs => docs}/custom-provider.md | 2 +- .../coding-agent/docs => docs}/docs.json | 0 .../docs => docs}/environment-variables.md | 0 .../coding-agent/docs => docs}/extensions.md | 24 +++++----- .../docs => docs}/how-pi-works.md | 0 .../docs => docs}/images/doom-extension.png | Bin .../coding-agent/docs => docs}/images/exy.png | Bin .../docs => docs}/images/interactive-mode.png | Bin .../docs => docs}/images/tree-view.png | Bin {packages/coding-agent/docs => docs}/index.md | 0 {packages/coding-agent/docs => docs}/json.md | 0 .../coding-agent/docs => docs}/keybindings.md | 0 .../coding-agent/docs => docs}/llama-cpp.md | 0 {packages/coding-agent/docs => docs}/mcp.md | 0 .../docs => docs}/message-types.md | 0 .../docs => docs}/models-configuration.md | 0 .../coding-agent/docs => docs}/models.md | 0 .../docs => docs}/nvidia-rtx-llama-cpp.md | 0 .../coding-agent/docs => docs}/packages.md | 0 .../docs => docs}/prompt-templates.md | 0 .../coding-agent/docs => docs}/providers.md | 0 .../coding-agent/docs => docs}/quickstart.md | 0 .../docs => docs}/rpc-commands.md | 0 .../docs => docs}/rpc-extension-ui.md | 2 +- {packages/coding-agent/docs => docs}/rpc.md | 2 +- {packages/coding-agent/docs => docs}/sdk.md | 38 ++++++++-------- .../coding-agent/docs => docs}/security.md | 0 .../docs => docs}/session-format.md | 0 .../coding-agent/docs => docs}/sessions.md | 0 .../coding-agent/docs => docs}/settings.md | 0 .../docs => docs}/shell-aliases.md | 0 .../coding-agent/docs => docs}/skills.md | 0 .../docs => docs}/slash-commands.md | 0 .../docs => docs}/terminal-setup.md | 0 .../coding-agent/docs => docs}/termux.md | 0 .../coding-agent/docs => docs}/themes.md | 0 {packages/coding-agent/docs => docs}/tmux.md | 0 {packages/coding-agent/docs => docs}/tui.md | 14 +++--- {packages/coding-agent/docs => docs}/usage.md | 0 .../docs => docs}/virtual-models.md | 2 +- .../coding-agent/docs => docs}/windows.md | 0 packages/coding-agent/README.md | 8 ++-- packages/coding-agent/package.json | 3 +- packages/coding-agent/scripts/copy-docs.mjs | 43 ++++++++++++++++++ packages/coding-agent/src/config.ts | 12 ++++- .../src/core/tools/renderers/read.ts | 19 +++++--- packages/coding-agent/src/migrations.ts | 2 +- .../coding-agent/test/documentation.test.ts | 2 +- .../test/tool-execution-component.test.ts | 10 +++- .../evals/evals/documentation-audit.eval.ts | 2 +- 60 files changed, 140 insertions(+), 71 deletions(-) rename {packages/coding-agent/docs => docs}/cli-integration.md (91%) rename {packages/coding-agent/docs => docs}/cli.md (100%) rename {packages/coding-agent/docs => docs}/codemode.md (100%) rename {packages/coding-agent/docs => docs}/compaction.md (99%) rename {packages/coding-agent/docs => docs}/configuration.md (100%) rename {packages/coding-agent/docs => docs}/containerization.md (97%) rename {packages/coding-agent/docs => docs}/custom-provider.md (98%) rename {packages/coding-agent/docs => docs}/docs.json (100%) rename {packages/coding-agent/docs => docs}/environment-variables.md (100%) rename {packages/coding-agent/docs => docs}/extensions.md (92%) rename {packages/coding-agent/docs => docs}/how-pi-works.md (100%) rename {packages/coding-agent/docs => docs}/images/doom-extension.png (100%) rename {packages/coding-agent/docs => docs}/images/exy.png (100%) rename {packages/coding-agent/docs => docs}/images/interactive-mode.png (100%) rename {packages/coding-agent/docs => docs}/images/tree-view.png (100%) rename {packages/coding-agent/docs => docs}/index.md (100%) rename {packages/coding-agent/docs => docs}/json.md (100%) rename {packages/coding-agent/docs => docs}/keybindings.md (100%) rename {packages/coding-agent/docs => docs}/llama-cpp.md (100%) rename {packages/coding-agent/docs => docs}/mcp.md (100%) rename {packages/coding-agent/docs => docs}/message-types.md (100%) rename {packages/coding-agent/docs => docs}/models-configuration.md (100%) rename {packages/coding-agent/docs => docs}/models.md (100%) rename {packages/coding-agent/docs => docs}/nvidia-rtx-llama-cpp.md (100%) rename {packages/coding-agent/docs => docs}/packages.md (100%) rename {packages/coding-agent/docs => docs}/prompt-templates.md (100%) rename {packages/coding-agent/docs => docs}/providers.md (100%) rename {packages/coding-agent/docs => docs}/quickstart.md (100%) rename {packages/coding-agent/docs => docs}/rpc-commands.md (100%) rename {packages/coding-agent/docs => docs}/rpc-extension-ui.md (97%) rename {packages/coding-agent/docs => docs}/rpc.md (98%) rename {packages/coding-agent/docs => docs}/sdk.md (74%) rename {packages/coding-agent/docs => docs}/security.md (100%) rename {packages/coding-agent/docs => docs}/session-format.md (100%) rename {packages/coding-agent/docs => docs}/sessions.md (100%) rename {packages/coding-agent/docs => docs}/settings.md (100%) rename {packages/coding-agent/docs => docs}/shell-aliases.md (100%) rename {packages/coding-agent/docs => docs}/skills.md (100%) rename {packages/coding-agent/docs => docs}/slash-commands.md (100%) rename {packages/coding-agent/docs => docs}/terminal-setup.md (100%) rename {packages/coding-agent/docs => docs}/termux.md (100%) rename {packages/coding-agent/docs => docs}/themes.md (100%) rename {packages/coding-agent/docs => docs}/tmux.md (100%) rename {packages/coding-agent/docs => docs}/tui.md (92%) rename {packages/coding-agent/docs => docs}/usage.md (100%) rename {packages/coding-agent/docs => docs}/virtual-models.md (95%) rename {packages/coding-agent/docs => docs}/windows.md (100%) create mode 100644 packages/coding-agent/scripts/copy-docs.mjs diff --git a/.gitignore b/.gitignore index 730658969..aba691312 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.pi/prompts/pr.md b/.pi/prompts/pr.md index 19ce8c51e..d8aef16ce 100644 --- a/.pi/prompts/pr.md +++ b/.pi/prompts/pr.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 :` 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. diff --git a/.pi/skills/add-llm-provider.md b/.pi/skills/add-llm-provider.md index 97cd9a3ec..044f9db1f 100644 --- a/.pi/skills/add-llm-provider.md +++ b/.pi/skills/add-llm-provider.md @@ -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 diff --git a/README.md b/README.md index 93184c10f..0745cd6d1 100644 --- a/README.md +++ b/README.md @@ -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

pi.dev domain graciously donated by

- Exy mascot
exe.dev
+ Exy mascot
exe.dev

diff --git a/packages/coding-agent/docs/cli-integration.md b/docs/cli-integration.md similarity index 91% rename from packages/coding-agent/docs/cli-integration.md rename to docs/cli-integration.md index e0ab57f01..4ccdad311 100644 --- a/packages/coding-agent/docs/cli-integration.md +++ b/docs/cli-integration.md @@ -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 diff --git a/packages/coding-agent/docs/cli.md b/docs/cli.md similarity index 100% rename from packages/coding-agent/docs/cli.md rename to docs/cli.md diff --git a/packages/coding-agent/docs/codemode.md b/docs/codemode.md similarity index 100% rename from packages/coding-agent/docs/codemode.md rename to docs/codemode.md diff --git a/packages/coding-agent/docs/compaction.md b/docs/compaction.md similarity index 99% rename from packages/coding-agent/docs/compaction.md rename to docs/compaction.md index 69c82e889..d9aada7b6 100644 --- a/packages/coding-agent/docs/compaction.md +++ b/docs/compaction.md @@ -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 diff --git a/packages/coding-agent/docs/configuration.md b/docs/configuration.md similarity index 100% rename from packages/coding-agent/docs/configuration.md rename to docs/configuration.md diff --git a/packages/coding-agent/docs/containerization.md b/docs/containerization.md similarity index 97% rename from packages/coding-agent/docs/containerization.md rename to docs/containerization.md index f65b94e8f..b20704afb 100644 --- a/packages/coding-agent/docs/containerization.md +++ b/docs/containerization.md @@ -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. diff --git a/packages/coding-agent/docs/custom-provider.md b/docs/custom-provider.md similarity index 98% rename from packages/coding-agent/docs/custom-provider.md rename to docs/custom-provider.md index 248d6d0cd..53e86a6b4 100644 --- a/packages/coding-agent/docs/custom-provider.md +++ b/docs/custom-provider.md @@ -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 diff --git a/packages/coding-agent/docs/docs.json b/docs/docs.json similarity index 100% rename from packages/coding-agent/docs/docs.json rename to docs/docs.json diff --git a/packages/coding-agent/docs/environment-variables.md b/docs/environment-variables.md similarity index 100% rename from packages/coding-agent/docs/environment-variables.md rename to docs/environment-variables.md diff --git a/packages/coding-agent/docs/extensions.md b/docs/extensions.md similarity index 92% rename from packages/coding-agent/docs/extensions.md rename to docs/extensions.md index c3836c81b..ae97ea00c 100644 --- a/packages/coding-agent/docs/extensions.md +++ b/docs/extensions.md @@ -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. @@ -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 `/`. 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. diff --git a/packages/coding-agent/docs/how-pi-works.md b/docs/how-pi-works.md similarity index 100% rename from packages/coding-agent/docs/how-pi-works.md rename to docs/how-pi-works.md diff --git a/packages/coding-agent/docs/images/doom-extension.png b/docs/images/doom-extension.png similarity index 100% rename from packages/coding-agent/docs/images/doom-extension.png rename to docs/images/doom-extension.png diff --git a/packages/coding-agent/docs/images/exy.png b/docs/images/exy.png similarity index 100% rename from packages/coding-agent/docs/images/exy.png rename to docs/images/exy.png diff --git a/packages/coding-agent/docs/images/interactive-mode.png b/docs/images/interactive-mode.png similarity index 100% rename from packages/coding-agent/docs/images/interactive-mode.png rename to docs/images/interactive-mode.png diff --git a/packages/coding-agent/docs/images/tree-view.png b/docs/images/tree-view.png similarity index 100% rename from packages/coding-agent/docs/images/tree-view.png rename to docs/images/tree-view.png diff --git a/packages/coding-agent/docs/index.md b/docs/index.md similarity index 100% rename from packages/coding-agent/docs/index.md rename to docs/index.md diff --git a/packages/coding-agent/docs/json.md b/docs/json.md similarity index 100% rename from packages/coding-agent/docs/json.md rename to docs/json.md diff --git a/packages/coding-agent/docs/keybindings.md b/docs/keybindings.md similarity index 100% rename from packages/coding-agent/docs/keybindings.md rename to docs/keybindings.md diff --git a/packages/coding-agent/docs/llama-cpp.md b/docs/llama-cpp.md similarity index 100% rename from packages/coding-agent/docs/llama-cpp.md rename to docs/llama-cpp.md diff --git a/packages/coding-agent/docs/mcp.md b/docs/mcp.md similarity index 100% rename from packages/coding-agent/docs/mcp.md rename to docs/mcp.md diff --git a/packages/coding-agent/docs/message-types.md b/docs/message-types.md similarity index 100% rename from packages/coding-agent/docs/message-types.md rename to docs/message-types.md diff --git a/packages/coding-agent/docs/models-configuration.md b/docs/models-configuration.md similarity index 100% rename from packages/coding-agent/docs/models-configuration.md rename to docs/models-configuration.md diff --git a/packages/coding-agent/docs/models.md b/docs/models.md similarity index 100% rename from packages/coding-agent/docs/models.md rename to docs/models.md diff --git a/packages/coding-agent/docs/nvidia-rtx-llama-cpp.md b/docs/nvidia-rtx-llama-cpp.md similarity index 100% rename from packages/coding-agent/docs/nvidia-rtx-llama-cpp.md rename to docs/nvidia-rtx-llama-cpp.md diff --git a/packages/coding-agent/docs/packages.md b/docs/packages.md similarity index 100% rename from packages/coding-agent/docs/packages.md rename to docs/packages.md diff --git a/packages/coding-agent/docs/prompt-templates.md b/docs/prompt-templates.md similarity index 100% rename from packages/coding-agent/docs/prompt-templates.md rename to docs/prompt-templates.md diff --git a/packages/coding-agent/docs/providers.md b/docs/providers.md similarity index 100% rename from packages/coding-agent/docs/providers.md rename to docs/providers.md diff --git a/packages/coding-agent/docs/quickstart.md b/docs/quickstart.md similarity index 100% rename from packages/coding-agent/docs/quickstart.md rename to docs/quickstart.md diff --git a/packages/coding-agent/docs/rpc-commands.md b/docs/rpc-commands.md similarity index 100% rename from packages/coding-agent/docs/rpc-commands.md rename to docs/rpc-commands.md diff --git a/packages/coding-agent/docs/rpc-extension-ui.md b/docs/rpc-extension-ui.md similarity index 97% rename from packages/coding-agent/docs/rpc-extension-ui.md rename to docs/rpc-extension-ui.md index bd489450d..72b883a13 100644 --- a/packages/coding-agent/docs/rpc-extension-ui.md +++ b/docs/rpc-extension-ui.md @@ -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. diff --git a/packages/coding-agent/docs/rpc.md b/docs/rpc.md similarity index 98% rename from packages/coding-agent/docs/rpc.md rename to docs/rpc.md index a39cc8da2..d48cca0e5 100644 --- a/packages/coding-agent/docs/rpc.md +++ b/docs/rpc.md @@ -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 diff --git a/packages/coding-agent/docs/sdk.md b/docs/sdk.md similarity index 74% rename from packages/coding-agent/docs/sdk.md rename to docs/sdk.md index 7d0883b3f..2869c7412 100644 --- a/packages/coding-agent/docs/sdk.md +++ b/docs/sdk.md @@ -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. @@ -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 -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 | diff --git a/packages/coding-agent/docs/security.md b/docs/security.md similarity index 100% rename from packages/coding-agent/docs/security.md rename to docs/security.md diff --git a/packages/coding-agent/docs/session-format.md b/docs/session-format.md similarity index 100% rename from packages/coding-agent/docs/session-format.md rename to docs/session-format.md diff --git a/packages/coding-agent/docs/sessions.md b/docs/sessions.md similarity index 100% rename from packages/coding-agent/docs/sessions.md rename to docs/sessions.md diff --git a/packages/coding-agent/docs/settings.md b/docs/settings.md similarity index 100% rename from packages/coding-agent/docs/settings.md rename to docs/settings.md diff --git a/packages/coding-agent/docs/shell-aliases.md b/docs/shell-aliases.md similarity index 100% rename from packages/coding-agent/docs/shell-aliases.md rename to docs/shell-aliases.md diff --git a/packages/coding-agent/docs/skills.md b/docs/skills.md similarity index 100% rename from packages/coding-agent/docs/skills.md rename to docs/skills.md diff --git a/packages/coding-agent/docs/slash-commands.md b/docs/slash-commands.md similarity index 100% rename from packages/coding-agent/docs/slash-commands.md rename to docs/slash-commands.md diff --git a/packages/coding-agent/docs/terminal-setup.md b/docs/terminal-setup.md similarity index 100% rename from packages/coding-agent/docs/terminal-setup.md rename to docs/terminal-setup.md diff --git a/packages/coding-agent/docs/termux.md b/docs/termux.md similarity index 100% rename from packages/coding-agent/docs/termux.md rename to docs/termux.md diff --git a/packages/coding-agent/docs/themes.md b/docs/themes.md similarity index 100% rename from packages/coding-agent/docs/themes.md rename to docs/themes.md diff --git a/packages/coding-agent/docs/tmux.md b/docs/tmux.md similarity index 100% rename from packages/coding-agent/docs/tmux.md rename to docs/tmux.md diff --git a/packages/coding-agent/docs/tui.md b/docs/tui.md similarity index 92% rename from packages/coding-agent/docs/tui.md rename to docs/tui.md index 704a78633..4d1d67b8c 100644 --- a/packages/coding-agent/docs/tui.md +++ b/docs/tui.md @@ -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. diff --git a/packages/coding-agent/docs/usage.md b/docs/usage.md similarity index 100% rename from packages/coding-agent/docs/usage.md rename to docs/usage.md diff --git a/packages/coding-agent/docs/virtual-models.md b/docs/virtual-models.md similarity index 95% rename from packages/coding-agent/docs/virtual-models.md rename to docs/virtual-models.md index ccd9a6451..948c29ba5 100644 --- a/packages/coding-agent/docs/virtual-models.md +++ b/docs/virtual-models.md @@ -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. diff --git a/packages/coding-agent/docs/windows.md b/docs/windows.md similarity index 100% rename from packages/coding-agent/docs/windows.md rename to docs/windows.md diff --git a/packages/coding-agent/README.md b/packages/coding-agent/README.md index db40c5e12..bda514f45 100644 --- a/packages/coding-agent/README.md +++ b/packages/coding-agent/README.md @@ -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 diff --git a/packages/coding-agent/package.json b/packages/coding-agent/package.json index 33ac1bcfd..289a9dc25 100644 --- a/packages/coding-agent/package.json +++ b/packages/coding-agent/package.json @@ -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", diff --git a/packages/coding-agent/scripts/copy-docs.mjs b/packages/coding-agent/scripts/copy-docs.mjs new file mode 100644 index 000000000..7e6ef48da --- /dev/null +++ b/packages/coding-agent/scripts/copy-docs.mjs @@ -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); +} diff --git a/packages/coding-agent/src/config.ts b/packages/coding-agent/src/config.ts index 61dd63f38..49f70d1e8 100644 --- a/packages/coding-agent/src/config.ts +++ b/packages/coding-agent/src/config.ts @@ -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 */ diff --git a/packages/coding-agent/src/core/tools/renderers/read.ts b/packages/coding-agent/src/core/tools/renderers/read.ts index f69b9f2a6..f1e636598 100644 --- a/packages/coding-agent/src/core/tools/renderers/read.ts +++ b/packages/coding-agent/src/core/tools/renderers/read.ts @@ -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; diff --git a/packages/coding-agent/src/migrations.ts b/packages/coding-agent/src/migrations.ts index 3f02ba659..903e94580 100644 --- a/packages/coding-agent/src/migrations.ts +++ b/packages/coding-agent/src/migrations.ts @@ -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. diff --git a/packages/coding-agent/test/documentation.test.ts b/packages/coding-agent/test/documentation.test.ts index b1ba3ea77..6e10609da 100644 --- a/packages/coding-agent/test/documentation.test.ts +++ b/packages/coding-agent/test/documentation.test.ts @@ -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 { if (!value || typeof value !== "object" || Array.isArray(value)) { diff --git a/packages/coding-agent/test/tool-execution-component.test.ts b/packages/coding-agent/test/tool-execution-component.test.ts index f334f7d6b..c026679eb 100644 --- a/packages/coding-agent/test/tool-execution-component.test.ts +++ b/packages/coding-agent/test/tool-execution-component.test.ts @@ -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( diff --git a/packages/evals/evals/documentation-audit.eval.ts b/packages/evals/evals/documentation-audit.eval.ts index dc2d6a582..283f35bfe 100644 --- a/packages/evals/evals/documentation-audit.eval.ts +++ b/packages/evals/evals/documentation-audit.eval.ts @@ -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));