pi-plus 0.1.16 → 0.1.18

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.
Files changed (6) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +43 -119
  3. package/package.json +3 -10
  4. package/pipi.js +128 -127
  5. package/api.d.ts +0 -44
  6. package/api.js +0 -2367
package/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ### Changed
6
+
7
+ - **The repository split the pi-plus sources into three packages**: the shared override core (context/compaction/reasoning + the seven non-TUI extensions + the core redirect wrappers) stays in `packages/plus`, all CLI logic (hub dispatch, completion, usage print, banner/vim/tab-title/plain-tools/`/cd`, the main wrapper, the source-mode loader) moved to `packages/plus-cli`, and the programmatic entry moved to `packages/plus-api`. The published `pi-plus` package is now **CLI-only**: `api.js`/`api.d.ts` are gone from the artifact, the `exports` map has no `.` entry (so `import "pi-plus"` fails by design), and the `@earendil-works/pi-coding-agent` types dependency is dropped. Library hosts should depend on the new **`pi-plus-sdk`** package instead, published from `packages/plus-api`.
8
+ - Entries below this note predate the split and describe the combined `pi-plus` artifact.
9
+
5
10
  ### Fixed
6
11
 
7
12
  - Manual compactions no longer die silently and strand the TUI's "Compacting context..." spinner forever when a second compaction starts while one is already running (the classic sequence: answer "Compact now?" on resume, then type `/compact` while that compaction is still summarizing). Upstream keeps the manual compaction's abort controller in a singleton field that any overlapping compaction's cleanup resets to `undefined`; the overlap crashed the second compaction with `Cannot read properties of undefined (reading 'signal')` before it could emit `compaction_end`, so the indicator outlived the compaction. The `AgentSession` wrapper now serializes `compact()` calls through a per-session queue (`compaction/serialize.ts`): a `/compact` issued during an in-flight compaction waits its turn instead of interleaving, and each compaction's finally blocks complete before the next starts.
@@ -10,6 +15,7 @@
10
15
 
11
16
  ### Added
12
17
 
18
+ - `/cd <dir>` moves the session to a different working directory: the session file relocates to the target cwd's default session dir with only its header `cwd` rewritten (id, timestamp, and entries untouched — the same conversation, not a fork), the runtime then switches to it so tools, extensions, project settings, trust, and the system prompt re-bind to the new directory, and the old session file is removed once the switch completes. `/cd` with no argument shows the current cwd. A session that has not been persisted yet (no messages) starts directly in the target directory.
13
19
  - The published `pi-plus` package gains a programmatic library entry alongside the `pipi` CLI: `import { createPlusAgentSession, createPlusUIContext, plusSdkExtensionFactories } from "pi-plus"` lets a host application (e.g. a desktop app) embed pi with the full pi-plus layer in-process — the compaction/context/reasoning overrides are baked into `api.js` by the same bundle-time redirect plugin as the CLI, and the seven non-TUI pi-plus extensions (subagent, tasks, memory, plan, ask-user, hooks, context-guard) are registered the same way the CLI wrapper registers them. `createPlusAgentSession()` composes the upstream `createAgentSession` with a `DefaultResourceLoader` carrying those factories, reloads it, and binds extensions once (emitting `session_start`); hosts pass dialog handlers via the `ui` option to get working `ask_user` questions (select/confirm/input bridged to native UI), or omit it for a headless session. The staged package.json now has an `exports` map (deep imports are closed off), ships a hand-authored `api.d.ts` re-exporting `@earendil-works/pi-coding-agent` types (added as an exact-pinned dependency for type resolution only; the runtime stays self-contained), and builds `api.js` as a second esbuild entry, roughly doubling the artifact size. Hosts without a pi CLI on PATH should pass `excludeTools: ["subagent"]`: the subagent tool launches a pi subprocess and could otherwise relaunch the host app itself.
14
20
  - The tab-title spinner now also runs while context compaction is in progress (manual `/compact` when idle, or automatic/overflow compaction mid-run): `session_before_compact` marks compaction active and `session_compact`/`session_compact_failed` clear it, so a backgrounded tab shows at a glance that a long compaction is running. The spinner stops only when neither the agent run nor compaction is active, so mid-run compaction (which settles the run before retrying) no longer leaves the tab static.
15
21
  - A `<tasks>` system-prompt section (registered by the `pi-plus-tasks` extension on every agent start) nudging the model to break non-trivial multi-step work into TaskCreate tasks and update statuses as it goes, and listing the session's current tasks (with status and blockers) when non-empty so resumed sessions can pick up where they left off.
package/README.md CHANGED
@@ -1,147 +1,71 @@
1
- # plus
1
+ # plus-cli
2
2
 
3
- All override/custom logic lives here. Direct updates to any other folder under `packages/` are forbidden — upstream packages stay pristine so they can be synced/updated without merge conflicts.
3
+ The pi-plus CLI surface, on top of the shared override core in [`../plus`](../plus).
4
+ Direct updates to any other folder under `packages/` are forbidden — upstream packages
5
+ stay pristine so they can be synced/updated without merge conflicts.
4
6
 
5
- ## What this layer does
7
+ The published npm artifact is **`pi-plus`** (https://www.npmjs.com/package/pi-plus);
8
+ it installs a single global command, **`pipi`** — deliberately not `pi` (pi-plus must
9
+ not own pi's command). Library hosts embedding pi in-process use the separate
10
+ **`pi-plus-sdk`** package built from [`../plus-api`](../plus-api).
6
11
 
7
- Ports Claude Code semantics (reference: `../free-code/`, CC v2.1.87) onto pi's context detection, compaction, and reasoning — with pi-style env var names:
12
+ ## What this layer adds on top of the shared core
8
13
 
9
- 1. **Context usage detection** (`src/context/detection.ts`) — effective context window = `min(contextWindow, cap) − min(maxTokens, 20000)`, where the cap defaults to the model's advertised window and can be set in `/settings` ("Context window cap": "No cap"/131072/262144/524288/1048576, persisted in `~/.pi/agent/pi-plus-settings.json`). Capping below the model window gives a sane auto-compact threshold on huge-context models (e.g. the 1M-token DeepSeek V4.1 Flash capped at 262144 triggers at ~194K instead of ~800K that never fires); auto-compact threshold = a percent of the effective window (**default 80%**, adjustable 70–95% in `/settings`); warning/error = threshold ∓ 20k; blocking limit = effective window − 3k; 3-failure circuit breaker. When a cap shrinks the window, the footer's fullness percentage is also measured against the effective window (e.g. `14.4%/242K`), so the meter tracks the usable window instead of crawling against raw 1M capacity; with no cap the meter reads against full model capacity. The "Auto-compact threshold" row persists to `~/.pi/agent/pi-plus-settings.json` (`src/context/threshold-setting.ts`); `PI_AUTOCOMPACT_PCT_OVERRIDE` keeps its session-scoped, capped-at-the-CC-buffer test semantics. The effective window is also floored at the output reserve plus a context floor buffer (**default 13k**, adjustable 13000–65536 in `/settings`); the floor only ever raises the built-in 13k minimum so small-context models keep a usable (non-negative-threshold) window, and `PI_CONTEXT_FLOOR_TOKENS` overrides it for the session. `PI_AUTO_COMPACT_WINDOW` can only lower the (capped) window further for the session.
10
- 2. **Compaction** (`src/compaction/`) — single full-conversation summary using the CC 9-section prompt (`prompt.ts`); prompt-too-long retries drop the oldest turn (`compact.ts`); post-compact re-injection of up to 5 recently read files (50k token budget). Summarization never applies the session thinking level: the summary's output cap is `0.8 × reserveTokens` and reasoning tokens count against it, so a `high` session level on a reasoning model could truncate the summary mid-generation and fail compaction ("generation hit the token cap"). Summary requests carry a no-reasoning marker (`markNoReasoning` in `src/reasoning/effort.ts`) that `wrapStreamFn` honors by stripping reasoning/thinking budgets instead of re-applying the session level.
11
- 3. **Reasoning effort** (`src/reasoning/effort.ts`) — CC effort levels (`low`/`medium`/`high`/`max`, `max` → `xhigh` → `high` downgrading), adaptive thinking default, `ultrathink` keyword → high effort for that turn, thinking budgets from env.
12
- 4. **Hub profiles** (`src/coding-agent/main.ts` wrapper, backed by `@earendil-works/pi-hub` = `packages/hub`) — named pi profiles (provider/models/thinking/token/base URL) stored in `~/.pi/profiles.json`, materialized into isolated agent dirs under `~/.pi/pi-hub/profiles/<name>/`. Adds `pipi profile …`, `pipi use` / `pipi unuse`, and the `pipi --as <name>` flag. The wrapper resolves the profile, sets `PI_CODING_AGENT_DIR` in-process (read lazily by `getAgentDir()`), and delegates to the original `main`.
13
- 5. **CLI surface** (`src/completion/`, `src/coding-agent/cli/args.ts` wrapper) — `pipi --help` gains a "Profile commands (pi-plus)" section, and `pipi completion <bash|zsh>` prints a shell completion script covering the whole CLI: hub subcommands (with dynamic profile/model names from `~/.pi/profiles.json`) plus pi's native commands and flags.
14
- 6. **Welcome banner** (`src/coding-agent/ui/banner.ts`, registered as a hidden built-in extension from the `main.ts` wrapper) — pipi's TUI startup header becomes a CC-style banner (ported from better-claude-code-ui) with a block-character π+ mark: condensed logo by default, boxed variant with Extensions/Skills feeds on first run in a project or version change, compact/plain degradation on narrow terminals, `resumed <id> · <title>` on resume/fork. `setHeader` replaces pi's built-in header, so no settings changes are needed.
15
- 7. **Vim modal editing** (`src/coding-agent/ui/vim/`, core subset ported from [pi-vimmode](https://github.com/pekochan069/pi-vimmode), MIT, (c) 2026 pekochan069) — vim-style modal editing for the prompt input, as a hidden built-in extension replacing the editor component. Supported: insert/normal/visual (`v`)/visual-line (`V`) modes; motions `h j k l w b e 0 $ ^ f F t T` with counts; operators `d c y` over motions, linewise `dd cc yy`; `x s r J p P i a I A o O C`; `u`/Ctrl-r undo/redo; prompt search `/ ? n N`. Excluded (vs full pi-vimmode): ex commands, macros, marks, named registers, easymotion, visual-block, JS config, cursor-shape escapes. Enable with `"vim": true` in settings — project `.pi/settings.json` wins over the agent dir, which wins over `~/.pi/settings.json` — or toggle with `/vim`, which applies immediately and persists the new state to the agent dir `settings.json` (project settings still override per project).
16
- 8. **Subagent tool** (`src/extensions/subagent/`, ported from pi's subagent example, single mode only) — delegates a task to a specialized sub-agent in an isolated `pi -p --no-session` subprocess with its own context window. Agent types are markdown files with frontmatter (`name`, `description`, `tools`, `model`) in `<agent dir>/agents/` or the project's `.pi/agents/`; built-in types `worker` (full toolset) and `explore` (read-only) always exist. Parallel-safe (`executionMode: "parallel"`), abort propagates to the child, child usage/cost is reported, and sub-agents can't recurse unless their definition allows it.
17
- 9. **Task tools** (`src/extensions/tasks/`, openclaude V2 style) — `TaskCreate`/`TaskUpdate`/`TaskList`/`TaskGet` backed by one JSON file per task under `<agent dir>/tasks/<sessionId>/` (monotonic ids via `.highwatermark`, atomic tmp+rename writes), with per-task `owner` and `blocks`/`blockedBy` dependencies. `/tasks` or `ctrl+shift+t` opens a task-list overlay in the TUI.
18
- 10. **ask_user tool** (`src/extensions/ask-user/`, openclaude AskUserQuestion style) — the model can ask 1–4 structured questions per call (2–4 options with descriptions each, optional `multiSelect`, automatic "Other" free-text). In TUI mode a tabbed overlay dialog collects the answers; RPC mode falls back to sequential select/input dialogs; print/JSON mode makes the tool fail with an error result so the model proceeds with its own assumptions. Guardrails: unique question texts and option labels, no model-supplied "Other" option, header chips ≤ 12 chars.
19
- 11. **User command hooks** (`src/extensions/hooks/`) — fires command hooks declared in `settings.json` under a `"hooks"` key (per-event matcher groups of `{type:"command", command, async}` entries; hooks from `~/.pi`, the agent dir, and the project `.pi` settings files are merged) at CC-analogue moments: `PermissionRequest` when any blocking prompt opens (ask_user dialog, plan-mode entry/approval), `PreToolUse` per tool call (`ask_user` matches `AskUserQuestion` matchers), `Stop` when the agent settles. Fire-and-forget detached spawns; never blocks or fails the agent.
20
- 12. **Long-term memory** (`src/extensions/memory/`, openclaude memdir/extractMemories style) — per-project memories as markdown files with frontmatter (`name`, `description`, `type`: user/feedback/project/reference) under `<agent dir>/memory/<project-key>/`, indexed in `MEMORY.md` (200-line / 25 KB caps). The `memory_save`/`memory_recall` tools let the model persist and search durable facts; the index is injected as a `<memory>` system-prompt section each run; `/memory` browses/edits/adds/forgets. At `agent_settled` a background sub-agent restricted to the two memory tools reviews the conversation and saves noteworthy facts (skipped when the main agent already saved one, below `extractMinMessages` new messages, or within `extractCooldownMs`). Toggle via the `"memory"` key in settings.json (`enabled`, `autoExtract`, `extractMinMessages`, `extractCooldownMs`; project > agent dir > `~/.pi`).
21
- 13. **Tab title + busy spinner** (`src/extensions/tab-title/`) — the terminal window/tab title brands as `pi+ - [sessionName -] cwdBasename` (via the `config.ts` wrapper's `APP_TITLE`, which upstream's `updateTerminalTitle` also uses, so both paths agree). While the agent is working (`agent_start` until `agent_settled`/`turn_end`) or context compaction is running (`session_before_compact` until `session_compact`/`session_compact_failed`, covering manual `/compact` when idle and auto/overflow compaction mid-run), a braille spinner frame is prepended to the title and ticks every 120 ms, so a backgrounded tab shows at a glance that pi+ is busy. TUI mode only; the ticker is cleared on session shutdown.
22
- 14. **Plain tool blocks** (`src/extensions/plain-tools/`) — strips the background fills upstream paints on tool result blocks (`toolPendingBg` while running, `toolSuccessBg`/`toolErrorBg` on completion, including edit diff boxes), so tool status reads as text — words like `Command exited with code 3` and the subagent tool's `running` / `✓ done` / `✗ failed` — instead of colored blocks. Implemented as a one-time `Theme.prototype.bg` wrapper (idempotent, applied at extension registration), so it holds across theme switches and spares every other background token (selections, user message bubble).
14
+ The context-detection/compaction/reasoning overrides and the seven non-TUI extensions
15
+ (subagent, tasks, memory, plan, ask-user, hooks, context-guard) live in
16
+ [`../plus`](../plus) and are shared with the SDK. This package adds the CLI-only pieces:
23
17
 
24
- The CLI identifies as **`pipi`** (pi-plus) in CLI text via the `config.ts` wrapper's `APP_NAME` shadow; the terminal tab title brands as **`pi+`** via the `APP_TITLE` shadow. Scope is the display name only — config dir (`.pi`), `PI_`-prefixed env vars, and session layout stay pi's.
18
+ 1. **Hub profiles** (`src/coding-agent/main.ts` wrapper, backed by `@earendil-works/pi-hub` = [`../hub`](../hub)) — named pi profiles (provider/models/thinking/token/base URL) stored in `~/.pi/profiles.json`, materialized into isolated agent dirs under `~/.pi/pi-hub/profiles/<name>/`. Adds `pipi profile …`, `pipi use` / `pipi unuse`, and the `pipi --as <name>` flag. The wrapper resolves the profile, sets `PI_CODING_AGENT_DIR` in-process (read lazily by `getAgentDir()`), and delegates to the original `main`.
19
+ 2. **Shell completion** (`src/completion/`) — `pipi completion <bash|zsh>` prints a completion script covering the whole CLI: hub subcommands (with dynamic profile/model names from `~/.pi/profiles.json`) plus pi's native commands and flags.
20
+ 3. **Usage print** (`src/coding-agent/cli/args.ts` wrapper) — `pipi --help` gains a "Profile commands (pi-plus)" section.
21
+ 4. **Welcome banner** (`src/coding-agent/ui/banner.ts`) — pipi's TUI startup header is a CC-style banner with a block-character π+ mark: condensed logo by default, boxed variant with Extensions/Skills feeds, compact/plain degradation on narrow terminals, `resumed <id> · <title>` on resume/fork.
22
+ 5. **Vim modal editing** (`src/coding-agent/ui/vim/`, core subset ported from [pi-vimmode](https://github.com/pekochan069/pi-vimmode), MIT, (c) 2026 pekochan069) — insert/normal/visual/visual-line modes, motions with counts, `d c y` operators, undo/redo, prompt search. Enable with `"vim": true` in settings or toggle with `/vim`.
23
+ 6. **Settings selector rows** (`src/coding-agent/ui/settings-selector.ts` wrapper) — `/settings` gains "Auto-compact threshold", "Context floor", and "Context window cap" rows (persisted via the shared core's `context/threshold-setting.ts`).
24
+ 7. **Tab title + busy spinner** (`src/extensions/tab-title/`) — the terminal window/tab title brands as `pi+ - [sessionName -] cwdBasename` with a braille spinner while the agent or compaction is working. TUI mode only.
25
+ 8. **Plain tool blocks** (`src/extensions/plain-tools/`) — strips background fills from tool result blocks so tool status reads as text (words, never colored blocks).
26
+ 9. **`/cd` working-directory switch** (`src/extensions/cd/`) — `/cd <dir>` relocates the session to a different working directory (same conversation, re-bound project context).
25
27
 
26
- ## Mechanism
28
+ The CLI identifies as **`pipi`** (pi-plus) in CLI text via the shared config wrapper's
29
+ `APP_NAME` shadow; the terminal tab title brands as **`pi+`** via `APP_TITLE`.
27
30
 
28
- - `loader/hooks.mjs` — Node module customization hook. Two jobs: (a) map `@earendil-works/*` specifiers to `packages/*/src` (mirrors root tsconfig paths), (b) redirect selected upstream modules to the wrapper modules below. Importers inside `packages/plus/` are never redirected, so wrappers can import the true original via relative path without a loop.
29
- - `loader/run-plus.mjs` + `pipi` — entry point. Runs pi from TypeScript sources on Node's native type stripping (the repo is `erasableSyntaxOnly`). tsx is intentionally not used: its load hook silently produces empty modules when another customization hook is registered alongside it (Node 25).
30
- - `src/<upstream-path>.ts` — wrapper modules. Each does `export * from "<relative path to original>"` and redefines selected exports; per ESM spec, explicit named exports shadow star exports, so everything not overridden passes through untouched.
31
- - Redirect map: `loader/redirects.mjs` (10 modules: coding-agent compaction/agent-session/model-resolver/defaults/config/main/cli-args/settings-selector, agent agent.ts, agent harness compaction).
32
-
33
- ## Shell completion
34
-
35
- `pipi completion <bash|zsh>` prints a completion script for the whole CLI — hub subcommands
36
- (dynamic profile names and per-profile models from `~/.pi/profiles.json`, providers, thinking
37
- levels) plus pi's native commands and flags. Install with:
31
+ ## Running from sources
38
32
 
39
33
  ```bash
40
- source <(pipi completion zsh) # add to ~/.zshrc
41
- source <(pipi completion bash) # add to ~/.bashrc
34
+ ./pipi --no-env # pi (pi-plus) from TypeScript sources with the override layer active
42
35
  ```
43
36
 
44
- ## Env vars (pi-style names)
45
-
46
- | Var | Values | Effect |
47
- | ----------------------------- | ----------------------------------- | --------------------------------------------------------------- |
48
- | `PI_MAX_CONTEXT_TOKENS` | number | Overrides `model.contextWindow` after model resolution |
49
- | `PI_AUTO_COMPACT_WINDOW` | number | Session cap on the threshold-math window (lowers the persisted cap) |
50
- | `PI_AUTOCOMPACT_PCT_OVERRIDE` | 1–100 | Auto-compact threshold as % of effective window (capped at default) |
51
- | `PI_CONTEXT_FLOOR_TOKENS` | number ≥ 13000 | Context floor override (only raises the built-in 13k floor) |
52
- | `PI_BLOCKING_LIMIT_OVERRIDE` | number | Blocking limit override |
53
- | `PI_DISABLE_COMPACT` | truthy | Disables all compaction (incl. manual) |
54
- | `PI_DISABLE_AUTO_COMPACT` | truthy | Disables threshold-triggered auto-compaction |
55
- | `PI_AUTOCOMPACT_FAILURE_COOLDOWN_MS` | ms ≥ 10000 | Circuit-breaker cooldown after 3 consecutive auto-compact failures |
56
- | `PI_MAX_ACTIVE_MESSAGES` | number (`0`/invalid = off, default 1000) | Forces compaction when the active message count exceeds the cap |
57
- | `PI_PRUNE_TAIL_TURNS` | number ≥ 1 (default 3) | Recent turns preserved verbatim by relevance pruning |
58
- | `PI_MICROCOMPACT_IDLE_MINUTES` | minutes (default 60; ≤ 0 disables) | Idle gap that triggers clearing of stale tool-result content on session open |
59
- | `PI_MICROCOMPACT_KEEP_RECENT` | number (default 5) | Tool results preserved verbatim by idle micro-compact |
60
- | `PI_COMPACT_ANALYTICS` | truthy | Emits recompaction diagnostics to stderr after compaction |
61
- | `PI_COMPACT_DEBUG` | truthy | Stderr stage trace for compaction (prompt built, stream entered/settled, response stopReason, result) |
62
- | `PI_PLUS_SETTINGS_FILE` | path | Overrides `~/.pi/agent/pi-plus-settings.json` (test/debug knob) |
63
- | `PI_EFFORT_LEVEL` | `off`/`auto`/`low`/`medium`/`high`/`max` | Per-request reasoning effort override |
64
- | `PI_MAX_THINKING_TOKENS` | number (`0` disables) | Thinking budget (enables thinking at `high` when > 0) |
65
- | `PI_DISABLE_THINKING` | truthy | Disables thinking entirely |
66
- | `PI_DISABLE_ADAPTIVE_THINKING`| truthy | Forces the budget-based thinking path |
67
-
68
- ## Conventions
69
-
70
- - Mirror the upstream layout when overriding: e.g. logic overriding `packages/coding-agent/src/core/compaction/compaction.ts` lives in `src/coding-agent/core/compaction/compaction.ts`.
71
- - Prefer extension points over patching: pi's extension API (see `packages/coding-agent/docs/extensions.md`), prompt templates, skills, and settings come first; reach for behavior overrides only when those cannot express the change.
72
- - Each override module must re-export or wrap the upstream implementation instead of copying it, so upstream fixes propagate.
73
- - Overrides are wired in only through the loader; nothing under `packages/plus` may be imported by upstream code.
37
+ `loader/hooks.mjs` is a Node module-customization hook that maps `@earendil-works/*`
38
+ to `packages/*/src` and redirects the overridden upstream modules to the wrappers
39
+ (shared core redirects in `../plus/loader/redirects.mjs`, CLI redirects in
40
+ `loader/redirects.mjs`). Importers inside any `packages/plus*` dir are never
41
+ redirected, so wrappers can import the true original via relative path without a loop.
74
42
 
75
43
  ## Compiled artifact (npm)
76
44
 
77
- `build.mjs` bundles `pipi` into `dist/npm/` — a self-contained staging tree that `npm link` /
78
- `npm publish` operate on (this package itself stays private). The published artifact is
79
- **`pi-plus`** on npmjs; it installs a single global command, **`pipi`** — deliberately
80
- not `pi` (pi-plus must not own pi's command). The CLI identifies as `pipi` everywhere
81
- (help text, hub commands).
45
+ `build.mjs` bundles `pipi` into `dist/npm/` — a self-contained staging tree that
46
+ `npm link` / `npm publish` operate on (this package itself stays private). The bundle
47
+ applies the redirect tables at bundle time via the shared plugin in
48
+ `../plus/build/redirect-plugin.mjs` and funnels every `packages/*/src` import with a
49
+ compiled `dist/` counterpart to that dist file (singleton preservation). `--no-env`
50
+ is preserved via a banner scrub.
82
51
 
83
52
  ```bash
84
- npm run build # in packages/plus; requires `npm run build:offline` at the repo root first
85
- npm link # in packages/plus/dist/npm — global `pipi`
86
- npm publish --access public --ignore-scripts # in packages/plus/dist/npm
87
- ```
88
-
89
- The bundle applies `loader/redirects.mjs` at bundle time (esbuild plugin) and keeps each
90
- module a singleton by funneling every `packages/*/src/**` import with a compiled `dist/`
91
- counterpart to that dist file. `--no-env` is preserved via a banner scrub (inert for
92
- library imports: it only scrubs when `process.argv` contains a literal `--no-env`).
93
- Provider credentials, config dir (`~/.pi`), and session layout are identical to
94
- source-mode `pipi`.
95
-
96
- ### Programmatic API (library hosts)
97
-
98
- The same package also exposes a programmatic entry for hosts that embed pi-plus
99
- in-process (e.g. a desktop app) instead of running the `pipi` CLI:
100
-
101
- ```js
102
- import { createPlusAgentSession } from "pi-plus";
103
-
104
- const { session } = await createPlusAgentSession({
105
- cwd: projectDir,
106
- ui: {
107
- select: async (title, options) => showPicker(title, options),
108
- confirm: async (title, message) => showConfirm(title, message),
109
- input: async (title, placeholder) => showInput(title, placeholder),
110
- },
111
- // Hosts without a pi CLI on PATH should exclude the subagent tool: it
112
- // launches a pi subprocess and could otherwise relaunch the host app.
113
- excludeTools: ["subagent"],
114
- });
115
- await session.prompt("Review this repository");
53
+ npm run build:offline # at the repo root, first
54
+ npm run build # in packages/plus-cli
55
+ npm publish --access public --ignore-scripts # in packages/plus-cli/dist/npm
116
56
  ```
117
57
 
118
- - The full pi-plus layer is included: the compaction/context/reasoning overrides are
119
- baked into `api.js` by the same bundle-time redirect plugin as the CLI, and the seven
120
- non-TUI pi-plus extensions (subagent, tasks, memory, plan, ask-user, hooks,
121
- context-guard) are registered exactly as the CLI wrapper registers them.
122
- - `createPlusAgentSession()` extends the upstream `createAgentSession` (re-exported, with
123
- the whole upstream SDK surface) with those extension factories, and always binds
124
- extensions once — do not call `session.bindExtensions()` yourself. Pass `ui` dialog
125
- handlers to get working `ask_user` questions (bound with mode `"rpc"`, so the tool
126
- falls back to sequential select/input/confirm dialogs bridged to your UI); omit `ui`
127
- for a headless session.
128
- - The staged `package.json` has an `exports` map, so deep imports (e.g.
129
- `pi-plus/pipi.js`) are no longer reachable; `api.d.ts` re-exports the
130
- `@earendil-works/pi-coding-agent` types (exact-pinned dependency, type resolution
131
- only — the runtime is self-contained). Building `api.js` as a second esbuild entry
132
- roughly doubles the artifact size.
58
+ The staged package is CLI-only: a `pipi` bin and **no `.` export**, so
59
+ `import "pi-plus"` fails by design — library hosts use `pi-plus-sdk`.
133
60
 
134
61
  Known limitations of the compiled artifact:
135
62
 
136
63
  - `pipi server` / `pipi client` experimental subcommands (`PI_EXPERIMENTAL=1`) spawn sibling JS
137
64
  files that are not emitted next to the bundle; use source-mode `./pipi` for those.
138
65
  - `docs/` and `examples/` are not shipped, so `/docs`-style paths into them are absent.
139
- - Hub profile resolution (`pipi --as <name>`, `pipi profile …`) is CLI-launch logic and is
140
- not part of the programmatic entry; SDK hosts pass `cwd`/`agentDir` explicitly.
141
66
 
142
67
  ## Tests
143
68
 
144
- ```
145
- npx vitest run # from packages/plus; unit tests under test/ (faux streamFn, no real APIs)
146
- ./pipi --no-env # run pipi (pi-plus) from sources with the override layer active
69
+ ```bash
70
+ npx vitest run # from packages/plus-cli; unit tests under test/ (faux streamFn, no real APIs)
147
71
  ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-plus",
3
- "version": "0.1.16",
4
- "description": "pi coding agent with the pi-plus override layer (pipi CLI + programmatic API)",
3
+ "version": "0.1.18",
4
+ "description": "pi coding agent with the pi-plus override layer (pipi CLI)",
5
5
  "type": "module",
6
6
  "piConfig": {
7
7
  "configDir": ".pi"
@@ -10,16 +10,10 @@
10
10
  "pipi": "pipi.js"
11
11
  },
12
12
  "exports": {
13
- ".": {
14
- "types": "./api.d.ts",
15
- "default": "./api.js"
16
- },
17
13
  "./package.json": "./package.json"
18
14
  },
19
15
  "files": [
20
16
  "pipi.js",
21
- "api.js",
22
- "api.d.ts",
23
17
  "*.js",
24
18
  "modes/",
25
19
  "core/",
@@ -30,8 +24,7 @@
30
24
  "@earendil-works/chord": "^0.87.1",
31
25
  "@earendil-works/pi-tui": "^0.87.1",
32
26
  "@silvia-odwyer/photon-node": "0.3.4",
33
- "jiti": "2.7.0",
34
- "@earendil-works/pi-coding-agent": "0.87.1"
27
+ "jiti": "2.7.0"
35
28
  },
36
29
  "engines": {
37
30
  "node": ">=22.19.0"