pi-plus 0.1.13 → 0.1.16
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 +3 -1
- package/README.md +46 -4
- package/api.d.ts +44 -0
- package/api.js +2367 -0
- package/github-copilot.js +1 -1
- package/package.json +13 -3
- package/pipi.js +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
### Added
|
|
12
12
|
|
|
13
|
+
- 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.
|
|
13
14
|
- 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.
|
|
14
15
|
- 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.
|
|
15
16
|
- A `<subagents>` system-prompt section (registered by the `pi-plus-subagent` extension on every agent start) nudging the model to delegate self-contained work units via the `subagent` tool — including complete, self-contained prompts and concurrent calls in one turn — and listing the agent types available in this session (built-in `worker`/`explore` plus user- and project-defined agents) with their source, tools, and model.
|
|
@@ -19,12 +20,13 @@
|
|
|
19
20
|
- Recompaction analytics (openclaude's `RecompactionInfo`) persisted in the compaction entry's `details`: whether the compaction continues a chain, turns consumed since the previous compaction, the previous pre-compact token count, and a `willRetriggerNextTurn` prediction; set `PI_COMPACT_ANALYTICS` for a stderr diagnostic line.
|
|
20
21
|
- `/settings` gains an "Auto-compact threshold" row (70%/80%/85%/90%/95%, default 80%), injected into the settings selector by the plus wrapper. The choice persists to `~/.pi/agent/pi-plus-settings.json` and applies as a percent of the effective context window, replacing the CC buffer math as the user-facing default — unlike `PI_AUTOCOMPACT_PCT_OVERRIDE`, which stays a session-scoped test knob capped at the CC buffer.
|
|
21
22
|
- `/settings` gains a "Context floor" row (13000–65536 tokens, default 13000) for the floor under the effective context window: the window used for auto-compact math never drops below the output reserve plus this many tokens, even for small-context models. The choice persists to `~/.pi/agent/pi-plus-settings.json` and can only raise the built-in 13k floor (the issue-#635 guarantee stays intact); `PI_CONTEXT_FLOOR_TOKENS` overrides it for the session.
|
|
23
|
+
- `/settings` gains a "Context window cap" row ("No cap"/131072/262144/524288/1048576, default "No cap") capping the context window used for auto-compact math and the footer fullness meter at min(model window, cap). The choice persists to `~/.pi/agent/pi-plus-settings.json`; `PI_AUTO_COMPACT_WINDOW` keeps its session-scoped can-only-lower semantics on top.
|
|
22
24
|
|
|
23
25
|
### Changed
|
|
24
26
|
|
|
25
27
|
- The `<tasks>` system-prompt section now spells out the TaskCreate/TaskUpdate/TaskList/TaskGet signatures (parameter names, optionality, status enum, numeric-string task ids) in an "Available tools:" block after the prose nudge. Extension tools have no snippet in the `<tools>` section, so the model previously had to discover them blind — flash-tier models in particular ignored the nudge and ran multi-step work as one tool call at a time with no task tracking.
|
|
26
28
|
|
|
27
|
-
- The window used for threshold math is
|
|
29
|
+
- The default context window used for threshold math is no longer ceilinged at 256K (`AUTOCOMPACT_MAX_WINDOW_TOKENS` is gone): with no "Context window cap" chosen in `/settings`, the model's advertised context window is used as-is, so a 1M-context model triggers auto-compaction at 80% of its full window (~784K) and the footer meter reads against full capacity. Choosing a cap restores the old behavior (e.g. 262144 reproduces the 242K effective window and the `14.4%/242K` meter). The floor logic and `PI_AUTO_COMPACT_WINDOW`'s session-scoped lowering are unchanged.
|
|
28
30
|
|
|
29
31
|
- The CC buffer math (ramped 13k–30k by effective window size, openclaude issue #1949; floored effective window for small-context models, issue #635) no longer sets the auto-compact threshold directly — it survives only as the cap for the `PI_AUTOCOMPACT_PCT_OVERRIDE` test knob. The user-facing threshold is now a percent of the effective window chosen in `/settings` (default 80%). `percentLeft` is computed against the raw context window so the displayed percentage reflects full model capacity.
|
|
30
32
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ All override/custom logic lives here. Direct updates to any other folder under `
|
|
|
6
6
|
|
|
7
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:
|
|
8
8
|
|
|
9
|
-
1. **Context usage detection** (`src/context/detection.ts`) — effective context window = `min(contextWindow,
|
|
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
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
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
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`.
|
|
@@ -46,7 +46,7 @@ source <(pipi completion bash) # add to ~/.bashrc
|
|
|
46
46
|
| Var | Values | Effect |
|
|
47
47
|
| ----------------------------- | ----------------------------------- | --------------------------------------------------------------- |
|
|
48
48
|
| `PI_MAX_CONTEXT_TOKENS` | number | Overrides `model.contextWindow` after model resolution |
|
|
49
|
-
| `PI_AUTO_COMPACT_WINDOW` | number |
|
|
49
|
+
| `PI_AUTO_COMPACT_WINDOW` | number | Session cap on the threshold-math window (lowers the persisted cap) |
|
|
50
50
|
| `PI_AUTOCOMPACT_PCT_OVERRIDE` | 1–100 | Auto-compact threshold as % of effective window (capped at default) |
|
|
51
51
|
| `PI_CONTEXT_FLOOR_TOKENS` | number ≥ 13000 | Context floor override (only raises the built-in 13k floor) |
|
|
52
52
|
| `PI_BLOCKING_LIMIT_OVERRIDE` | number | Blocking limit override |
|
|
@@ -88,14 +88,56 @@ npm publish --access public --ignore-scripts # in packages/plus/dist/npm
|
|
|
88
88
|
|
|
89
89
|
The bundle applies `loader/redirects.mjs` at bundle time (esbuild plugin) and keeps each
|
|
90
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
|
|
92
|
-
|
|
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");
|
|
116
|
+
```
|
|
117
|
+
|
|
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.
|
|
93
133
|
|
|
94
134
|
Known limitations of the compiled artifact:
|
|
95
135
|
|
|
96
136
|
- `pipi server` / `pipi client` experimental subcommands (`PI_EXPERIMENTAL=1`) spawn sibling JS
|
|
97
137
|
files that are not emitted next to the bundle; use source-mode `./pipi` for those.
|
|
98
138
|
- `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.
|
|
99
141
|
|
|
100
142
|
## Tests
|
|
101
143
|
|
package/api.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public type contract for the "pi-plus" npm package's programmatic entry
|
|
3
|
+
* (api.js). Hand-authored mirror of src/api.ts: the runtime is fully
|
|
4
|
+
* self-contained in api.js (built from this repo with the pi-plus override
|
|
5
|
+
* layer baked in), so this file only needs to re-export the upstream SDK
|
|
6
|
+
* types and declare the pi-plus additions. A vitest drift guard
|
|
7
|
+
* (test/api.test.ts) asserts every runtime export of src/api.ts appears here.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export * from "@earendil-works/pi-coding-agent";
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
CreateAgentSessionOptions,
|
|
14
|
+
CreateAgentSessionResult,
|
|
15
|
+
ExtensionCommandContextActions,
|
|
16
|
+
ExtensionError,
|
|
17
|
+
ExtensionUIContext,
|
|
18
|
+
InlineExtension,
|
|
19
|
+
} from "@earendil-works/pi-coding-agent";
|
|
20
|
+
|
|
21
|
+
export declare const plusSdkExtensionFactories: InlineExtension[];
|
|
22
|
+
|
|
23
|
+
export interface PlusUIDialogHandlers {
|
|
24
|
+
select(title: string, options: string[]): Promise<string | undefined>;
|
|
25
|
+
confirm(title: string, message: string): Promise<boolean>;
|
|
26
|
+
input(title: string, placeholder?: string): Promise<string | undefined>;
|
|
27
|
+
editor?(title: string, prefill?: string): Promise<string | undefined>;
|
|
28
|
+
notify?(message: string, type?: "info" | "warning" | "error"): void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export declare function createPlusUIContext(handlers: PlusUIDialogHandlers): ExtensionUIContext;
|
|
32
|
+
|
|
33
|
+
export interface CreatePlusAgentSessionOptions extends CreateAgentSessionOptions {
|
|
34
|
+
extensionFactories?: InlineExtension[];
|
|
35
|
+
ui?: PlusUIDialogHandlers;
|
|
36
|
+
commandContextActions?: ExtensionCommandContextActions;
|
|
37
|
+
abortHandler?: () => void;
|
|
38
|
+
shutdownHandler?: () => void;
|
|
39
|
+
onError?: (error: ExtensionError) => void;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export declare function createPlusAgentSession(
|
|
43
|
+
options?: CreatePlusAgentSessionOptions,
|
|
44
|
+
): Promise<CreateAgentSessionResult>;
|