@astralyn/pi 0.82.1 → 0.82.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +71 -624
- package/dist/core/agent-session.d.ts +4 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +193 -43
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -13
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +13 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +19 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +7 -2
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +6 -0
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +10 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +53 -28
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/bundled/README.md +38 -0
- package/docs/bundled/extensions/README.md +18 -0
- package/docs/bundled/extensions/deepwiki.md +62 -0
- package/docs/bundled/extensions/question.md +48 -0
- package/docs/bundled/extensions/rewind.md +75 -0
- package/docs/bundled/extensions/router.md +126 -0
- package/docs/bundled/extensions/statusline.md +109 -0
- package/docs/bundled/extensions/subagent.md +95 -0
- package/docs/bundled/extensions/todo.md +28 -0
- package/docs/bundled/themes.md +51 -0
- package/docs/bundled/tool-presentation.md +85 -0
- package/docs/compaction.md +20 -14
- package/docs/containerization.md +1 -1
- package/docs/custom-provider.md +8 -8
- package/docs/docs.json +57 -9
- package/docs/extensions.md +14 -13
- package/docs/index.md +12 -7
- package/docs/json.md +4 -4
- package/docs/providers.md +1 -1
- package/docs/rpc.md +3 -9
- package/docs/session-format.md +5 -5
- package/docs/skills.md +1 -1
- package/docs/themes.md +4 -8
- package/docs/tui.md +1 -1
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +4 -4
- package/examples/extensions/custom-provider-anthropic/package-lock.json +3 -3
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +1 -1
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +0 -0
- package/examples/extensions/dynamic-resources/dynamic.json +1 -1
- package/examples/extensions/gondolin/index.ts +4 -6
- package/examples/extensions/message-renderer.ts +2 -2
- package/examples/extensions/overlay-qa-tests.ts +2 -2
- package/examples/extensions/project-trust.ts +2 -2
- package/examples/extensions/sandbox/package-lock.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/sdk/README.md +38 -44
- package/npm-shrinkwrap.json +3465 -624
- package/package.json +34 -18
- package/docs/development.md +0 -71
- package/examples/extensions/subagent/README.md +0 -175
- package/examples/extensions/subagent/agents/planner.md +0 -37
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
- package/examples/extensions/subagent/agents/scout.md +0 -50
- package/examples/extensions/subagent/agents/worker.md +0 -24
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -1009
- package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/examples/extensions/subagent/prompts/implement.md +0 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Bundled features
|
|
2
|
+
|
|
3
|
+
The installed `@astralyn/pi` package includes a small set of workflows and presentation choices on top of its coding-agent behavior. Upstream Pi release tags are synchronization input, not a separate user documentation set.
|
|
4
|
+
|
|
5
|
+
## Extensions
|
|
6
|
+
|
|
7
|
+
The following extensions are loaded as hidden built-ins. They use the same public Extension API available to external extensions.
|
|
8
|
+
|
|
9
|
+
| Extension | Tool or command | Purpose |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `llama.cpp` | `/llama` | Manage models served by the local llama.cpp router |
|
|
12
|
+
| `deepwiki` | `deepwiki` | Query indexed public GitHub repository documentation |
|
|
13
|
+
| `question` | `question` | Ask structured questions through native interactive UI |
|
|
14
|
+
| `rewind` | `/rewind` | Create and restore project snapshots around session lifecycle operations |
|
|
15
|
+
| `router` | `/router` | Configure and probe Codex-style routing endpoints |
|
|
16
|
+
| `statusline` | Footer status | Show concise extension-managed activity state |
|
|
17
|
+
| `subagent` | `subagent`, `/agents` | Delegate bounded work to isolated child Pi sessions |
|
|
18
|
+
| `todo` | `todo`, `/todos` | Track multi-step work with dependencies and status |
|
|
19
|
+
|
|
20
|
+
See the [bundled extension catalog](extensions/README.md) for configuration and behavior details.
|
|
21
|
+
|
|
22
|
+
## Context safety
|
|
23
|
+
|
|
24
|
+
Long tool loops are checked after a completed tool batch and before another provider request. When the active context crosses the configured auto-compaction threshold, Pi compacts and rebuilds the context before continuing the same run. Cancellation, compaction failure, an unavailable cut point, or retained context that remains unsafe stops before another provider request.
|
|
25
|
+
|
|
26
|
+
See [Compaction](../compaction.md).
|
|
27
|
+
|
|
28
|
+
## Tool presentation
|
|
29
|
+
|
|
30
|
+
Native tool calls use a consistent `●` call and `│` result shell with bounded collapsed output. Built-in semantic renderers remain responsible for paths, diffs, syntax highlighting, command output, and images.
|
|
31
|
+
|
|
32
|
+
See [Native tool presentation](tool-presentation.md).
|
|
33
|
+
|
|
34
|
+
## Themes
|
|
35
|
+
|
|
36
|
+
The package includes `ice-cream-dark` and `ice-cream-light` alongside the standard `dark` and `light` themes.
|
|
37
|
+
|
|
38
|
+
See [Bundled themes](themes.md) and [Theme authoring](../themes.md).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Bundled extensions
|
|
2
|
+
|
|
3
|
+
These are extensions shipped in the `@astralyn/pi` npm package. For the public API used to write external extensions, see the [Extension API documentation](../../extensions.md).
|
|
4
|
+
|
|
5
|
+
They are registered as hidden built-in extensions and use the same public Extension API available to external extensions. Their implementation details are internal to the package and are not required for installation or configuration.
|
|
6
|
+
|
|
7
|
+
| Extension | Tool or command | Documentation |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `llama.cpp` | `/llama` | [llama.cpp](../../llama-cpp.md) |
|
|
10
|
+
| `deepwiki` | `deepwiki` | [deepwiki.md](deepwiki.md) |
|
|
11
|
+
| `question` | `question` | [question.md](question.md) |
|
|
12
|
+
| `todo` | `todo`, `/todos` | [todo.md](todo.md) |
|
|
13
|
+
| `rewind` | `/rewind`, `/tree` lifecycle | [rewind.md](rewind.md) |
|
|
14
|
+
| `router` | `/router` | [router.md](router.md) |
|
|
15
|
+
| `statusline` | Footer | [statusline.md](statusline.md) |
|
|
16
|
+
| `subagent` | `subagent`, `/agents` | [subagent.md](subagent.md) |
|
|
17
|
+
|
|
18
|
+
The catalog documents installed-package behavior and configuration; it does not require access to the package's internal source.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# DeepWiki
|
|
2
|
+
|
|
3
|
+
`deepwiki` is a Pi-native tool for querying DeepWiki's generated documentation for GitHub repositories.
|
|
4
|
+
|
|
5
|
+
It is intentionally not a general MCP bridge. The extension exposes one dedicated tool with three fixed actions:
|
|
6
|
+
|
|
7
|
+
| Action | Behavior |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `structure` | List the generated wiki topics for a repository. |
|
|
10
|
+
| `contents` | Read the generated wiki — one page via `page` (recommended), or everything when `page` is omitted (truncated past ~120k chars). |
|
|
11
|
+
| `question` | Ask a focused question about a repository. |
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Parameters
|
|
16
|
+
|
|
17
|
+
- `action`: `structure`, `contents`, or `question`
|
|
18
|
+
- `repoName`: one `owner/repo` string for `structure` and `contents`; for `question`, one repo as a string, or 2–10 repos as an array (comma-separated string also accepted)
|
|
19
|
+
- `question`: required only for `action: "question"`
|
|
20
|
+
- `page`: optional, only for `action: "contents"` — 1-based index or page title from `structure` (plain titles such as `Extension System`, not numbered outline lines like `4.4 …`). Leading outline numbers on titles are stripped when matching. Unknown `page` fails with available titles listed.
|
|
21
|
+
|
|
22
|
+
`repoName` is normalized before validation (`owner/repo`, GitHub/DeepWiki URLs, JSON-array strings for multi-repo mistakes). `pageName`/`pageTitle` are accepted as `page` aliases. If `action` is omitted, defaults to `question` when a question is present, `contents` when `page` is present, else `structure`. Repositories not indexed on DeepWiki return repository-not-found errors — run `structure` first to detect that.
|
|
23
|
+
|
|
24
|
+
### Strategy
|
|
25
|
+
|
|
26
|
+
Recommended flow for studying a repo:
|
|
27
|
+
|
|
28
|
+
1. `structure` — get the page outline.
|
|
29
|
+
2. `contents` + `page` — read the specific pages you need, one at a time.
|
|
30
|
+
3. Avoid `contents` without `page` (the full wiki) unless the wiki is genuinely small; oversized output is truncated at ~120k chars.
|
|
31
|
+
4. `question` — when the wiki pages don't cover what you need, or directly for a quick answer without reading.
|
|
32
|
+
|
|
33
|
+
Use DeepWiki when generated docs for public repositories are useful context:
|
|
34
|
+
|
|
35
|
+
- Understanding an unfamiliar public repo's architecture, module layout, APIs, data flow, or extension points.
|
|
36
|
+
- Researching reference implementations while designing or building a new feature or project.
|
|
37
|
+
- Asking a focused question about how a public repo implements something.
|
|
38
|
+
- Comparing patterns or extension surfaces across multiple public repos with `question` and a repo array.
|
|
39
|
+
- Pulling a broad topic map with `structure` before deciding which part of a repo matters.
|
|
40
|
+
|
|
41
|
+
The prompt is model-facing: when these conditions apply, the model should call the tool itself instead of telling the user to open DeepWiki manually.
|
|
42
|
+
|
|
43
|
+
Avoid DeepWiki when the authoritative source is local or time-sensitive:
|
|
44
|
+
|
|
45
|
+
- Local workspace files, private code, uncommitted changes, or exact current checkout state.
|
|
46
|
+
- Latest releases, pricing, security advisories, schedules, or facts that need current primary-source verification.
|
|
47
|
+
- Package names without a known GitHub repo; resolve the repo first instead of guessing.
|
|
48
|
+
|
|
49
|
+
## Limits
|
|
50
|
+
|
|
51
|
+
- A repository may not be indexed. DeepWiki can return that as normal text, so the extension treats repository-not-found messages as tool errors.
|
|
52
|
+
- `contents` responses are truncated at a ~120k-character budget on `# Page:` boundaries (whole pages kept in order; at least the first page survives, cut mid-page if it alone exceeds the budget). A trailing notice reports shown/total pages, the full length, up to 20 omitted page titles, and points at `page` reads and `action: "question"` for the rest. Details carry `shownPages` / `truncatedChars` when this happens; `outputLength` always reflects the full untruncated response. Single-page reads set `requestedPage` / `pageIndex` instead and share the same budget.
|
|
53
|
+
- Network requests time out after 45 seconds and surface as Pi tool errors.
|
|
54
|
+
- Use local Pi tools (`read`, `grep`, `find`, `ls`) for workspace state. DeepWiki answers describe repository snapshots indexed by DeepWiki, not local uncommitted files.
|
|
55
|
+
|
|
56
|
+
## Implementation notes
|
|
57
|
+
|
|
58
|
+
DeepWiki's public MCP endpoint exposes exactly three operations: list a wiki's page titles, return the whole generated wiki as one document, and answer a question. There is no per-page fetch upstream — `page` is implemented by this extension: it fetches the full wiki (or reuses the 10-minute cache) and slices out the requested page locally. The first `contents` call for a repo pays the network cost; subsequent page reads within the cache window are instant and free.
|
|
59
|
+
|
|
60
|
+
DeepWiki may return generated explanations with source-file citations and "related pages" links. The TUI uses a local renderer (`render.ts`) for a one-line collapsed summary and Markdown when expanded; Pi's default fallback would dump the full (often large) `content` text.
|
|
61
|
+
|
|
62
|
+
Successful responses are cached in-process for 10 minutes, keyed by action, repo, and question. Failed, aborted, and timed-out requests are not cached. The cache stores the full response; `contents` truncation is recomputed per call, so cached and fresh calls return identical text.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# question — structured user questions
|
|
2
|
+
|
|
3
|
+
Adds a `question` tool for asking one to four multiple-choice questions when the agent needs a user decision. A Pi-native take on AskUserQuestion: a lightweight custom dialog with concise transcript summaries and a bounded model-facing result.
|
|
4
|
+
|
|
5
|
+
## Behavior
|
|
6
|
+
|
|
7
|
+
- Each option requires a concise description of its consequence or trade-off. Questions, labels, descriptions, and previews have input-length limits so the dialog stays usable.
|
|
8
|
+
- A single single-select question submits as soon as the user selects an option.
|
|
9
|
+
- A multi-question flow advances after each single-select answer; multi-select uses `Space` to toggle choices and Enter to continue. Once every question is answered, a **Review answers** view requires explicit submission.
|
|
10
|
+
- `←` / `→` switch between adjacent questions without wrapping. The tab bar marks answered questions and the Review state.
|
|
11
|
+
- `Chat about this` is available after the choices. It returns a `needs_clarification` outcome so the model explains or reformulates instead of treating the user as having declined.
|
|
12
|
+
- `Type something.` is appended automatically for custom answers. Authored options may not use reserved labels (`Other`, `Type something.`, `Chat about this`, `Next`).
|
|
13
|
+
- `Tab` opens a note editor for the focused option; in multi-select, the option must be selected first. On the custom-answer row, it opens custom-answer input.
|
|
14
|
+
- Multi-select custom answers stay on the `Type something.` row, are selected when saved, and can be toggled with `Space` without losing text.
|
|
15
|
+
- `preview` shows focused single-select content beside the choices on wide terminals and beneath them on narrow terminals. Preview height is capped and reports hidden lines.
|
|
16
|
+
- The dialog is available only in TUI mode. RPC, JSON, and print calls return a structured `no_ui` error rather than attempting a custom component.
|
|
17
|
+
|
|
18
|
+
## Result contract
|
|
19
|
+
|
|
20
|
+
`details` preserves structured state for rendering and session history:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
{
|
|
24
|
+
answers,
|
|
25
|
+
outcome: "answered" | "cancelled" | "needs_clarification" | "error",
|
|
26
|
+
cancelled,
|
|
27
|
+
error?,
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Only `content` reaches the model. Successful results are numbered, clearly identify single/custom/multi answers, retain notes, and state when a preview was selected without echoing its full source. Model-facing output is capped at 12,000 characters; if it is truncated, the result instructs the model to ask a focused follow-up question. Notes and custom answers are capped at 4,000 characters in the dialog.
|
|
32
|
+
|
|
33
|
+
The transcript uses a private `renderCall` / `renderResult` only to replace raw question JSON and model-oriented result text with concise user summaries. Pi retains its native tool shell, pending/error state, and collapsed/expanded behavior.
|
|
34
|
+
|
|
35
|
+
## Limits
|
|
36
|
+
|
|
37
|
+
- Questions, labels, descriptions, and previews have input-length limits so the dialog stays usable.
|
|
38
|
+
- Notes and custom answers are capped at 4,000 characters.
|
|
39
|
+
- Model-facing output is capped at 12,000 characters; if truncated, the result instructs the model to ask a focused follow-up question.
|
|
40
|
+
- Only available in TUI mode. RPC, JSON, and print calls return a structured `no_ui` error.
|
|
41
|
+
|
|
42
|
+
## Implementation notes
|
|
43
|
+
|
|
44
|
+
- Uses Pi's native `ctx.ui.custom()` lifecycle; no state is shared with another extension.
|
|
45
|
+
- The render cache is keyed by terminal width **and height**, because preview height depends on available rows and Pi resize only requests a render.
|
|
46
|
+
- `validateQuestions` enforces uniqueness, reserved-label rejection, and text budgets beyond what the JSON schema can express.
|
|
47
|
+
- Dialog navigation follows Pi's injected select/input keybindings where applicable; custom actions such as Space-to-toggle remain explicit in the footer.
|
|
48
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# rewind — checkpoints & rewind
|
|
2
|
+
|
|
3
|
+
Per-edit file backups plus a `/rewind` settings menu. Instead of snapshotting the
|
|
4
|
+
whole working tree, rewind backs up **only the files Pi's `edit`/`write` tools are
|
|
5
|
+
about to change** — one `copyFile` before each edit. Cost is proportional to how
|
|
6
|
+
many files Pi changed, never to project size, so it never blocks the session
|
|
7
|
+
lifecycle (the old shadow-git design froze the UI in large multi-project
|
|
8
|
+
directories) and storage stays tiny.
|
|
9
|
+
|
|
10
|
+
## Behavior
|
|
11
|
+
|
|
12
|
+
Per turn: `before_agent_start` opens a snapshot frame (re-recording every tracked
|
|
13
|
+
file at its turn-start state, reusing the latest backup when unchanged);
|
|
14
|
+
`tool_call(edit|write)` backs up each newly edited file *before* it lands;
|
|
15
|
+
`agent_settled` persists the frame to the session JSONL as a `pi-rewind-snapshot`
|
|
16
|
+
custom entry **only when files changed**. Using `agent_settled` (not `agent_end`)
|
|
17
|
+
keeps auto-retry, overflow compaction-retry, and queued follow-ups in one logical
|
|
18
|
+
turn — `agent_end` can fire while Pi still continues. Requires **Pi ≥ 0.80.4**
|
|
19
|
+
(when `agent_settled` was added); older hosts never fire that event, so frames
|
|
20
|
+
would not finalize. Entries survive `/reload` and compaction; the index is
|
|
21
|
+
rebuilt from them on `session_start`.
|
|
22
|
+
|
|
23
|
+
- **Scope (deliberate trade-off):** rewind covers edits made through Pi's built-in
|
|
24
|
+
`edit` and `write` tools. Files written by `bash` (redirects, codegen, `mv`) or
|
|
25
|
+
edited by hand outside Pi are **not** tracked — same boundary as Claude Code's
|
|
26
|
+
file-history. Rewind undoes *Pi's edits*, not arbitrary filesystem state.
|
|
27
|
+
- **Time-travel is via `/tree`.** Navigating to a node whose turn changed files
|
|
28
|
+
prompts to restore them, listing the affected files (cwd-relative, up to 8
|
|
29
|
+
then *"+N more"*) under *"Restore 3 files to this point? (+120 / −40)"*
|
|
30
|
+
when coarse line stats are available; choosing yes restores the work tree to
|
|
31
|
+
that turn's start state. Nodes with no file changes navigate silently. Only
|
|
32
|
+
files that actually differ are rewritten. Line totals are a bag-of-lines
|
|
33
|
+
estimate (capped at 1 MB per file), not a full Myers diff.
|
|
34
|
+
- **`/rewind` is a settings + storage menu**, not a restore picker:
|
|
35
|
+
- toggle rewind on/off,
|
|
36
|
+
- set the auto-clean retention window,
|
|
37
|
+
- inspect storage and prune (clean aged + orphaned / remove orphaned / remove
|
|
38
|
+
all except current).
|
|
39
|
+
- **New files** created by `write` are tracked with a "did not exist" marker, so
|
|
40
|
+
rewinding deletes them.
|
|
41
|
+
- **Resume/fork** hard-links the prior session's backup blobs into the new
|
|
42
|
+
session (falling back to copy), so rewind keeps working without duplicating
|
|
43
|
+
storage.
|
|
44
|
+
|
|
45
|
+
## Storage & cleanup
|
|
46
|
+
|
|
47
|
+
- **Layout:** `~/.pi/agent/rewind/`
|
|
48
|
+
- `config.json` — `{ enabled, retentionDays, maxSnapshots }`
|
|
49
|
+
- `backups/<sessionId>/<sha256(relpath)[:16]>@v<n>` — backup blobs (flat, hashed
|
|
50
|
+
names keep paths short on Windows; mode preserved)
|
|
51
|
+
- **Auto-clean:** at `session_start`, backup directories older than
|
|
52
|
+
`retentionDays` (default **30**, set in `/rewind`) are reclaimed, plus an
|
|
53
|
+
**orphan sweep** of directories whose session id has no session JSONL (crashed
|
|
54
|
+
sessions). The GC is time-boxed and deletion-capped so it never slows startup.
|
|
55
|
+
- The former `pi-config` storage layout is **not** read or migrated by this
|
|
56
|
+
engine. Remove any old `~/.pi/agent/pi-config/` data manually if it is no
|
|
57
|
+
longer needed.
|
|
58
|
+
|
|
59
|
+
## Limits
|
|
60
|
+
|
|
61
|
+
- Covers edits made through Pi's built-in `edit` and `write` tools only. Files written by `bash` or edited outside Pi are not tracked.
|
|
62
|
+
- A backup failure is swallowed — the edit proceeds without checkpointing rather than blocking the tool.
|
|
63
|
+
- `/rewind` on its own does not restore files. Restoration uses `/tree` — navigate to a turn and confirm the prompt.
|
|
64
|
+
- Restore is coarse: only files that differ are rewritten, but line totals are a bag-of-lines estimate (capped at 1 MB per file), not a full Myers diff.
|
|
65
|
+
|
|
66
|
+
## Implementation notes
|
|
67
|
+
|
|
68
|
+
- **Never blocks the edit.** Backup runs before the write lands; a backup failure is swallowed so the session never stalls.
|
|
69
|
+
- **Restore safety.** `applySnapshot` only rewrites files that differ and degrades gracefully on unreadable backups.
|
|
70
|
+
- **Change detection.** A file is re-backed-up only when its stat or content differs from the latest backup. Content comparison streams in 64 KiB chunks instead of buffering whole files up to the 25 MB cap.
|
|
71
|
+
- **Config is memory-cached.** `config.json` is re-read on `session_start` and updated in memory when `/rewind` saves.
|
|
72
|
+
- **Restore path is single-scan.** The `/tree` confirm pass caches changed absolute paths; IO is concurrency-capped (16).
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
Architecture informed by oh-my-pi (GPL-3.0) and Claude Code's file-history; independent implementation.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# `router` — Codex-style API relays
|
|
2
|
+
|
|
3
|
+
`/router` connects Pi to OpenAI-compatible API relays — self-hosted gateways such as sub2api, CPA, or codex2api, and any similar proxy — using a **Codex-shaped** Responses client.
|
|
4
|
+
|
|
5
|
+
Configuration lives at `~/.pi/agent/router.json`.
|
|
6
|
+
|
|
7
|
+
Providers are registered at extension load via `pi.registerProvider` (config form + `streamSimple`). They do **not** go through `models.json`. This follows Pi's documented custom-provider path ([providers.md](../../providers.md), [custom-provider.md](../../custom-provider.md)): the stream wraps the built-in `openAIResponsesApi()` from `@earendil-works/pi-ai/compat` (same approach as the GitLab Duo example), then reshapes the request for Codex-style relays.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/router Browse relays
|
|
15
|
+
/router add Add a relay
|
|
16
|
+
/router reload Re-register from disk
|
|
17
|
+
/router <id> Open a relay
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### UI map
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
API relays ← relays first; add / reload at bottom
|
|
24
|
+
└─ Relay · {id} ← models · base URL · API key · remove
|
|
25
|
+
└─ Models ← Fetch catalog + one row per configured model
|
|
26
|
+
└─ {model id} ← display name · thinking levels
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Edits **auto-save** to `router.json` and re-register the provider. There is no separate Save step — Back never discards committed field or model changes.
|
|
30
|
+
|
|
31
|
+
Nested multi-select (catalog) and the thinking-level editor require **Ctrl+S to apply** that screen's working set. If you press Esc with unsaved toggles, the footer warns once; pressing Esc again discards that screen only.
|
|
32
|
+
|
|
33
|
+
### Add flow
|
|
34
|
+
|
|
35
|
+
1. **Name** — provider id (e.g. `my-relay`); appears as `my-relay/gpt-5.6-sol` in `/model`
|
|
36
|
+
2. **Base URL** — usually ends with `/v1`
|
|
37
|
+
3. **API key** — literal `sk-…` or `$ENV_VAR`
|
|
38
|
+
4. **Fetch models** — `GET {baseUrl}/models`
|
|
39
|
+
5. **Select** — Space to toggle, Ctrl+S to apply (TUI); the relay is then written immediately
|
|
40
|
+
|
|
41
|
+
Each selected model gets these defaults:
|
|
42
|
+
|
|
43
|
+
| Field | Default |
|
|
44
|
+
|:-:|:-:|
|
|
45
|
+
| `name` | **Omitted** — `/model` shows the model **id** |
|
|
46
|
+
| `reasoning` | `true` |
|
|
47
|
+
| `input` | `text` + `image` |
|
|
48
|
+
| `contextWindow` | 272000 |
|
|
49
|
+
| `maxTokens` | 128000 |
|
|
50
|
+
| `thinkingLevelMap` | off…medium hidden; high / xhigh / max on |
|
|
51
|
+
|
|
52
|
+
### Customize models
|
|
53
|
+
|
|
54
|
+
Relay → **Models** → pick a model:
|
|
55
|
+
|
|
56
|
+
- **Display name** — optional label (e.g. `Luna`). Leave empty to show the id. Saved on confirm.
|
|
57
|
+
- **Thinking levels** — toggle each Pi level between **on** and **hidden** (`null`). Ctrl+S applies, then auto-saves the relay.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Config shape
|
|
62
|
+
|
|
63
|
+
```jsonc
|
|
64
|
+
{
|
|
65
|
+
"version": 1,
|
|
66
|
+
"relays": [
|
|
67
|
+
{
|
|
68
|
+
"id": "my-relay",
|
|
69
|
+
"baseUrl": "https://relay.example/v1",
|
|
70
|
+
"apiKey": "sk-…",
|
|
71
|
+
"models": [
|
|
72
|
+
{
|
|
73
|
+
"id": "gpt-5.6-sol",
|
|
74
|
+
"reasoning": true,
|
|
75
|
+
"input": ["text", "image"],
|
|
76
|
+
"contextWindow": 272000,
|
|
77
|
+
"maxTokens": 128000,
|
|
78
|
+
"thinkingLevelMap": {
|
|
79
|
+
"off": null,
|
|
80
|
+
"minimal": null,
|
|
81
|
+
"low": null,
|
|
82
|
+
"medium": null,
|
|
83
|
+
"high": "high",
|
|
84
|
+
"xhigh": "xhigh",
|
|
85
|
+
"max": "max"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "gpt-5.6-luna",
|
|
90
|
+
"name": "Luna",
|
|
91
|
+
"reasoning": true,
|
|
92
|
+
"input": ["text", "image"],
|
|
93
|
+
"contextWindow": 272000,
|
|
94
|
+
"maxTokens": 128000
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
There is **no migration** from any older models-manager config. Add relays with `/router add` (or edit `router.json` and run `/router reload`).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Limits
|
|
107
|
+
|
|
108
|
+
- SSE only — no Codex WebSocket or zstd-compressed request body.
|
|
109
|
+
- Catalog probe expects OpenAI-style `{ data: [{ id }] }` response format.
|
|
110
|
+
- Empty model list → provider is not registered (nothing appears in `/model`).
|
|
111
|
+
- Body is Codex-oriented for transparent gateways; auth and URL remain Platform Responses (`sk-` + `/responses`).
|
|
112
|
+
- Same relay + same model: tool/reasoning multi-turn matches Codex-style Responses. Switching model or provider mid-session may normalize tool-call ids more strictly (upstream allow-list); this is not worked around here.
|
|
113
|
+
- Interactive `/router` requires a TUI (`ctx.hasUI`); otherwise a warning is shown and no dialog opens.
|
|
114
|
+
- Catalog multi-select and thinking editor are apply-on-Ctrl+S screens; only those screens can be discarded with double Esc.
|
|
115
|
+
|
|
116
|
+
## Implementation notes
|
|
117
|
+
|
|
118
|
+
**Request shape.** `stream.ts` calls `openAIResponsesApi().streamSimple` with a model configured as Platform Responses (`api: "openai-responses"`). The `onPayload` callback reshapes the body toward Pi's built-in `openai-codex-responses` format, with `store: false`, system prompt as `instructions`, `parallel_tool_calls: true`, and rejected fields such as `prompt_cache_retention` and `temperature` dropped.
|
|
119
|
+
|
|
120
|
+
Session affinity headers use hyphenated form (`session-id`, `x-client-request-id`). Compat settings: `sessionAffinityFormat: "openai-nosession"`, `supportsLongCacheRetention: false`. Originator header: `codex`.
|
|
121
|
+
|
|
122
|
+
**Differences from ChatGPT Codex OAuth.** Auth uses Bearer `sk-…` (not OAuth JWT), endpoint is `{baseUrl}/responses` (not `/codex/responses`), transport is SSE only (no WebSocket or zstd), and `OpenAI-Beta` is not set. These match **sk- relays**, not the official ChatGPT backend.
|
|
123
|
+
|
|
124
|
+
**Multi-turn tool calls.** On a fixed relay + fixed model, tool-call ids preserve the Responses form and replay like Codex. Pi only rewrites ids across model boundaries. Staying on one model for long tool + reasoning sessions avoids id sanitization.
|
|
125
|
+
|
|
126
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# statusline — fixed two-line footer
|
|
2
|
+
|
|
3
|
+
Replaces Pi's built-in footer with a fixed, color-coded two-line status display
|
|
4
|
+
using a balanced left/right layout. It registers no tool or command and has no
|
|
5
|
+
configuration file. The footer auto-enables on `session_start` in TUI mode and
|
|
6
|
+
clears itself on `session_shutdown`.
|
|
7
|
+
|
|
8
|
+
## What it shows
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
DeepSeek V4 Pro (opencode-go) · xhigh ~/Projects · main
|
|
12
|
+
CTX 2.1%/1.0M ↑13k ↓13k R440k CH99.4% $0.074
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Line 1 — session identity (left) · location (right)
|
|
16
|
+
|
|
17
|
+
**Left**
|
|
18
|
+
|
|
19
|
+
- **Model:** human-readable model name, falling back to the model id.
|
|
20
|
+
- **Provider:** the model source in parentheses, such as `(deepseek)` or
|
|
21
|
+
`(opencode-go)`.
|
|
22
|
+
- **Effort:** the latest thinking level when the model supports reasoning and
|
|
23
|
+
the level is not `off`.
|
|
24
|
+
|
|
25
|
+
**Right**
|
|
26
|
+
|
|
27
|
+
- **Working directory:** full cwd shortened against the home directory with `~`.
|
|
28
|
+
- **Git branch:** appended when available.
|
|
29
|
+
|
|
30
|
+
### Line 2 — context (left) · usage (right)
|
|
31
|
+
|
|
32
|
+
**Left**
|
|
33
|
+
|
|
34
|
+
- **Context:** used percentage plus context-window size. The percentage uses
|
|
35
|
+
fixed semantic tiers: accent normally, warning above 70%, error above 90%.
|
|
36
|
+
|
|
37
|
+
**Right**
|
|
38
|
+
|
|
39
|
+
- `↑` cumulative input tokens.
|
|
40
|
+
- `↓` cumulative output tokens.
|
|
41
|
+
- `R` cumulative cache-read tokens.
|
|
42
|
+
- `W` cumulative cache-write tokens, omitted when zero.
|
|
43
|
+
- `CH` cache-hit percentage for the latest assistant request, calculated as
|
|
44
|
+
`cacheRead / (input + cacheRead + cacheWrite)` and shown only when that
|
|
45
|
+
request used cache.
|
|
46
|
+
- `$` cumulative cost; `(sub)` is appended when the current model uses an OAuth
|
|
47
|
+
subscription.
|
|
48
|
+
|
|
49
|
+
**Middle (optional)**
|
|
50
|
+
|
|
51
|
+
- Extension status text from `ctx.ui.setStatus()` is sorted by key and centered
|
|
52
|
+
in the gap between context and usage when space permits; otherwise it is
|
|
53
|
+
dropped so CTX and usage stay readable. Plain text is muted; strings that
|
|
54
|
+
already carry ANSI color are left unchanged.
|
|
55
|
+
|
|
56
|
+
Zero-value usage fields are omitted. Before the first assistant response, the
|
|
57
|
+
right side of line 2 is empty (or holds extension status only).
|
|
58
|
+
|
|
59
|
+
## Narrow-width drop order
|
|
60
|
+
|
|
61
|
+
When the terminal is too narrow for the full layout:
|
|
62
|
+
|
|
63
|
+
**Line 1** (first drop → last):
|
|
64
|
+
|
|
65
|
+
1. Drop the git branch.
|
|
66
|
+
2. Keep the full path alone on the right.
|
|
67
|
+
3. Shorten the path to `~/basename` (or bare basename).
|
|
68
|
+
4. Drop the provider parentheses.
|
|
69
|
+
5. Truncate the remaining left/right text.
|
|
70
|
+
|
|
71
|
+
**Line 2** (first drop → last):
|
|
72
|
+
|
|
73
|
+
1. Drop extension status from the middle gap.
|
|
74
|
+
2. Drop `W`, then `R`, from the usage cluster.
|
|
75
|
+
3. Truncate CTX / remaining usage as a last resort.
|
|
76
|
+
|
|
77
|
+
## Layout and colors
|
|
78
|
+
|
|
79
|
+
- Model name uses `toolTitle` and bold; provider uses `muted`.
|
|
80
|
+
- Effort uses Pi's thinking-level color.
|
|
81
|
+
- Context uses `accent`, `warning`, or `error` according to the fixed thresholds.
|
|
82
|
+
- Working directory uses `success`; Git branch uses `accent`.
|
|
83
|
+
- Usage statistics use `dim`; extension status text uses `muted`.
|
|
84
|
+
- Each line left-aligns its primary cluster and right-aligns the secondary
|
|
85
|
+
cluster, filling the gap with spaces so wide terminals stay balanced.
|
|
86
|
+
|
|
87
|
+
Pi does not expose auto-compaction state to extension footer factories, so the
|
|
88
|
+
native `(auto)` marker is intentionally not reproduced.
|
|
89
|
+
|
|
90
|
+
## Migration
|
|
91
|
+
|
|
92
|
+
The previous `/statusline` command and `~/.pi/agent/pi-config/statusline.json`
|
|
93
|
+
configuration are no longer used. An existing config file is left untouched and
|
|
94
|
+
may be removed manually.
|
|
95
|
+
|
|
96
|
+
## Limits
|
|
97
|
+
|
|
98
|
+
- Auto-enables only in TUI mode on `session_start`; RPC and print modes have no TUI footer.
|
|
99
|
+
- The native `(auto)` compaction marker is not reproduced because Pi does not expose that state to extensions.
|
|
100
|
+
|
|
101
|
+
## Implementation notes
|
|
102
|
+
|
|
103
|
+
Footer paint is hot (every TUI render). The extension caches:
|
|
104
|
+
|
|
105
|
+
- **Branch path** by current leaf id.
|
|
106
|
+
- **Branch stats** (thinking level + cumulative usage) by branch length, leaf entry identity, and a leaf usage fingerprint.
|
|
107
|
+
|
|
108
|
+
Both caches clear on footer `invalidate()`.
|
|
109
|
+
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# subagent — isolated foreground delegation
|
|
2
|
+
|
|
3
|
+
Adds the `subagent` tool and `/agents` profile settings command. It delegates a bounded task to an isolated in-process `AgentSession`; it is not a background worker or a fleet manager.
|
|
4
|
+
|
|
5
|
+
## Tool modes
|
|
6
|
+
|
|
7
|
+
Exactly one mode is required per call:
|
|
8
|
+
|
|
9
|
+
- **Single**: `agent`, `description`, and `prompt`.
|
|
10
|
+
- **Parallel**: `tasks`, an array of independent task objects.
|
|
11
|
+
- **Chain**: `chain`, an array of sequential task objects. `{previous}` in a later prompt is replaced by the previous worker's bounded final response.
|
|
12
|
+
|
|
13
|
+
Every task object has:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
agent? Agent profile name; defaults to general
|
|
17
|
+
description Short UI label
|
|
18
|
+
prompt Self-contained worker briefing
|
|
19
|
+
cwd? Relative directory inside the parent working directory
|
|
20
|
+
model? Temporary provider/model override
|
|
21
|
+
thinking? Temporary thinking-level override
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Parallel and chain batches allow at most eight tasks. A session-scoped gate runs at most three workers concurrently, including sibling `subagent` calls from the same parent session.
|
|
25
|
+
|
|
26
|
+
## Agent profiles
|
|
27
|
+
|
|
28
|
+
Profiles are Markdown files with YAML frontmatter:
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
---
|
|
32
|
+
name: reviewer
|
|
33
|
+
description: Read-only implementation reviewer
|
|
34
|
+
tools: read, grep, find, ls
|
|
35
|
+
model: anthropic/claude-sonnet-4-5
|
|
36
|
+
thinking: medium
|
|
37
|
+
backend: sdk
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
Review the delegated task independently and report exact evidence.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Sources and precedence are:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
built-in < ~/.pi/agent/agents/*.md < trusted-project/.pi/agents/*.md
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Project definitions are loaded only after Pi trusts the project. Invalid Markdown definitions appear as `/agents` diagnostics without hiding valid profiles.
|
|
50
|
+
|
|
51
|
+
Built-in profiles:
|
|
52
|
+
|
|
53
|
+
- `general`: read, bash, edit, write, grep, find, and ls.
|
|
54
|
+
- `explorer`: read-only `read`, `grep`, `find`, and `ls`, with low thinking by default.
|
|
55
|
+
|
|
56
|
+
A profile may only allow Pi built-in tools. Child sessions load no extensions, skills, or prompt templates, so a worker cannot recursively call `subagent` or inherit unrelated extension capabilities. Project context files such as `AGENTS.md` remain available.
|
|
57
|
+
|
|
58
|
+
## Model and thinking selection
|
|
59
|
+
|
|
60
|
+
The model/thinking resolution order is:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
per-call tool fields
|
|
64
|
+
> saved /agents profile override
|
|
65
|
+
> profile Markdown frontmatter
|
|
66
|
+
> current parent session
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Run `/agents` to choose a profile and set either field to:
|
|
70
|
+
|
|
71
|
+
- **inherit**: force the active parent-session value;
|
|
72
|
+
- **agent default**: clear the saved override and use Markdown/default inheritance;
|
|
73
|
+
- a configured `provider/model` or explicit supported thinking level.
|
|
74
|
+
|
|
75
|
+
Overrides are user-owned and saved atomically in:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
~/.pi/agent/subagent.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
They apply only to future subagent runs and never change the parent session's `/model` or thinking level.
|
|
82
|
+
|
|
83
|
+
## Lifecycle and output
|
|
84
|
+
|
|
85
|
+
- The parent tool call waits until every worker reaches a terminal state.
|
|
86
|
+
- Parent abort, `/reload`, `/new`, `/resume`, `/fork`, and session shutdown abort active child sessions. Queued workers do not survive the call.
|
|
87
|
+
- Parallel worker failures do not cancel other independent workers. A failed or aborted chain step skips its remaining steps.
|
|
88
|
+
- Progress is rendered in Pi's native tool transcript. The collapsed view shows status, recent activity, usage, and the configured expand hint; `Ctrl+O` shows bounded activities and final Markdown reports.
|
|
89
|
+
- Full child transcripts are not stored separately. Bounded run details remain in the parent tool result, so completed calls restore naturally in the parent session tree.
|
|
90
|
+
- Nested usage is returned with the tool result and included in parent session accounting.
|
|
91
|
+
|
|
92
|
+
## Deliberate non-features
|
|
93
|
+
|
|
94
|
+
There are no background agents, persistent worker IDs, unread state, fleet panel, statusline widget, send/stop/resume control plane, completion notifications, swarm/coordinator, worktree isolation, nested agents, MCP, hooks, or agent memory.
|
|
95
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# todo — task list overlay
|
|
2
|
+
|
|
3
|
+
Adds a `todo` tool plus `/todos` for multi-step work, with a live overlay above the editor.
|
|
4
|
+
|
|
5
|
+
## Behavior
|
|
6
|
+
|
|
7
|
+
- Actions: `create`, `update`, `list`, `get`, `delete`, `clear`. Statuses: `pending`, `in_progress`, `completed`, `deleted`. `list` accepts an optional `status` filter and `includeDeleted`; `status: "deleted"` includes tombstones directly.
|
|
8
|
+
- The live overlay renders above the editor and hides itself when there are no visible tasks.
|
|
9
|
+
- Creation always starts a task as `pending`; `blockedBy` dependencies are supported for sequencing, and missing dependencies, deleted dependencies, self-dependencies, and cycles are rejected. A task cannot move to `in_progress` or `completed` until every `blockedBy` dependency is `completed`.
|
|
10
|
+
- Deletion — via `delete` or `update` with `status: "deleted"` — leaves an immutable tombstone for branch history, removes that task from every dependent `blockedBy` list, and therefore releases dependents. `clear` empties the list without reusing ids.
|
|
11
|
+
- Newly completed tasks remain visible for 30 seconds, then drop from the overlay; historical completions loaded by `/reload` or `/tree` stay hidden so live work remains prominent.
|
|
12
|
+
- **Exactly one `in_progress`.** Moving a task to `in_progress` auto-demotes any other `in_progress` tasks to `pending`; the tool result lists demoted ids so the model sees the side effect.
|
|
13
|
+
- **Verification soft nudge.** When a completion leaves the list fully done with 3+ completed tasks and no subject/description matching `verif|test|check|review`, the tool result appends a short NOTE (text only — `details` schema unchanged).
|
|
14
|
+
|
|
15
|
+
## Limits
|
|
16
|
+
|
|
17
|
+
- `list` output is bounded at 50 items by default, with a trailing notice when truncated.
|
|
18
|
+
- The overlay body is capped at 10 rows; its truncation summary includes hidden status counts.
|
|
19
|
+
- Newly completed tasks remain visible for 30 seconds then drop from the overlay.
|
|
20
|
+
|
|
21
|
+
## Implementation notes
|
|
22
|
+
|
|
23
|
+
- **Conversation-backed state.** Every tool result stores a full snapshot in `details`; lifecycle handlers replay the current branch on `/reload`, compaction, and session-tree navigation. There is no separate disk database. Compaction-safe by design: `sessionManager.getBranch()` returns the full branch history — only `buildSessionContext` summarizes for the LLM. Replay walks the branch **tail → head** and stops at the latest todo `toolResult`.
|
|
24
|
+
- **State is keyed per session id.** Resume and `/tree` can switch sessions within one process; `execute` and the lifecycle handlers re-point the active bucket before touching state.
|
|
25
|
+
- **Status transitions are gated.** `completed` can be reopened to `in_progress` or `pending`, but a `deleted` tombstone is terminal. Single-active is enforced on demote (not hard-reject) so the model does not need a retry loop.
|
|
26
|
+
- **Tool execution is sequential** (`executionMode: "sequential"`) so parallel tool calls cannot race on in-memory state. Validation failures **throw** so Pi marks `isError: true` and the branch replays the last good snapshot.
|
|
27
|
+
- **Overlay paint is pure + width-cached.** Completion visibility bookkeeping runs in `update()` plus a disposable timeout, never during `render`. Same terminal width reuses the last line array.
|
|
28
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Bundled theme design
|
|
2
|
+
|
|
3
|
+
This document describes the themes shipped in the `@astralyn/pi` package. For theme discovery, JSON format, and custom theme authoring, see the [Theme API documentation](../themes.md).
|
|
4
|
+
|
|
5
|
+
The package bundles two Pi themes using the native theme schema and loader:
|
|
6
|
+
|
|
7
|
+
| Theme | Use |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `ice-cream-dark` | Cool sea-salt dark palette with warm cream tool titles. |
|
|
10
|
+
| `ice-cream-light` | Light counterpart with the same semantic mapping. |
|
|
11
|
+
|
|
12
|
+
Both themes are built into `@astralyn/pi`. They do not require the external `pi-config` package.
|
|
13
|
+
|
|
14
|
+
## Selecting a theme
|
|
15
|
+
|
|
16
|
+
Use `/settings`, or set a single theme:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"theme": "ice-cream-dark"
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For automatic terminal light/dark selection:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"theme": "ice-cream-light/ice-cream-dark"
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The left side is used for light terminals and the right side for dark terminals.
|
|
33
|
+
|
|
34
|
+
## Design intent
|
|
35
|
+
|
|
36
|
+
The palette keeps an ice-cream / sea-salt identity: cool cyan-blue accents with warm cream tooling on a calm neutral base.
|
|
37
|
+
|
|
38
|
+
- `accent` and borders use the sea-salt family;
|
|
39
|
+
- `toolTitle` uses cream/gold tones;
|
|
40
|
+
- `toolOutput`, `muted`, and `dim` form a readable text ladder;
|
|
41
|
+
- tool backgrounds remain transparent so the native `●` / `│` presentation stays light;
|
|
42
|
+
- `success`, `error`, and `warning` remain semantic pastel colors;
|
|
43
|
+
- thinking levels move from cool blue through green and gold to coral/red.
|
|
44
|
+
|
|
45
|
+
## Extension UI
|
|
46
|
+
|
|
47
|
+
Bundled dialogs, overlays, and the statusline use semantic theme helpers such as `theme.fg(...)` and `theme.bg(...)`. They do not hard-code ANSI colors or hex values.
|
|
48
|
+
|
|
49
|
+
## Theme assets
|
|
50
|
+
|
|
51
|
+
The built-in theme names are stable user-facing identifiers. In an installed package, the JSON assets are available under `dist/modes/interactive/theme/` if you need to inspect them; normal use does not require accessing those internal files.
|