@rahularya01/pi-cursor 1.4.28 → 1.4.30

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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.4.30] - 2026-09-02
4
+
5
+ ### Fixed
6
+
7
+ - **Cursor 3.18.9 additive `agent.v1` envelope fields no longer report as wire-drift.** `InteractionUpdate.message_started_at_ms`, `ExecServerMessage.accept_hook_additional_contexts`, `ConversationStateStructure` start timestamp/timezone, and `AgentServerMessage.ttft_breakdown` are decoded so `/cursor.doctor` and Connect `internal` errors stop attaching this inventory. Fixes [#16](https://github.com/Rahularya01/pi-cursor/issues/16).
8
+ - **Tool-schema slimming no longer drops user-defined properties named `description`, `title`, or `default`.** Annotation keys are stripped only on schema nodes; named maps (`properties`, `$defs`, …) keep their keys. Prevents invalid schemas (dangling `required`) that Gemini rejected as `resource_exhausted`.
9
+ - **GetUsableModels `cursor-*` rows no longer keep a guessed 200K window when Cursor already published `contextTokenLimit`.** Parameterized discovery lists `grok-4.6` at 256K, but Pi also registers `cursor-grok-4.6` from GetUsableModels with `inferCursorContextWindow` (default 200K). Different ids meant both survived catalog merge, so compaction used the 200K alias. The parameterized window is now copied onto the `cursor-` prefixed twin. `inferCursorContextWindow` also treats Grok 4.5/4.6 as 256K when metadata is missing.
10
+ - **Cursor GPT-5.6 Luna/Sol/Terra no longer advertise a 1M window that OpenAI rejects at 500k.** Live `GetUsableModels` labels the 272k default "GPT-5.6 Luna 1M High", so Pi inferred `contextWindow: 1000000` and skipped auto-compaction until ~983k. OpenAI (via Cursor) then 400'd: `This model's maximum prompt length is 500000 but the request contains 503167 tokens.` Display-name "1M" is ignored unless the id has `-1m`; 1m variants are capped at 500k so threshold compaction fires first. Claude 1M rows are unchanged.
11
+
12
+ ## [1.4.29] - 2026-08-30
13
+
14
+ ### Changed
15
+
16
+ - **Bun is now the only supported runtime — Node.js is no longer required, anywhere.** The chat stream previously ran through a short-lived Node.js child process (`h2-bridge.mjs`) because Bun's `node:http2` client was believed unable to carry a bidirectional Connect stream reliably. It no longer does: all Cursor HTTP/2 transport (the streaming `Run` RPC and the unary discovery RPCs) now runs in-process via `node:http2`, which Bun implements natively — following the same pattern demonstrated by [can1357/oh-my-pi](https://github.com/can1357/oh-my-pi). `package.json` engines, `/cursor.doctor`, and the docs no longer claim or require a Node.js host.
17
+ - Toolchain migrated from npm/tsup/vitest to Bun end-to-end: `bun.lock` replaces `package-lock.json`, `scripts/build.ts` replaces `tsup.config.ts`, and `bun test` replaces `vitest.config.ts`.
18
+
19
+ ### Internal
20
+
21
+ - `src/client/h2-session.ts` replaces the subprocess bridge with a `BridgeHandle` implementation backed directly by an `http2.ClientHttp2Session`, reproducing the exact same exit-code/retry contract (`classifyBridgeExit()`) so the downstream recovery logic in `native-core.ts` needed no changes.
22
+
3
23
  ## [1.4.28] - 2026-08-27
4
24
 
5
25
  ### Security
package/README.md CHANGED
@@ -28,11 +28,11 @@ or CLI, it just works — no setup beyond installing the package.
28
28
 
29
29
  ## Requirements
30
30
 
31
- | | |
32
- | --------------------------- | ------------------------------------------------------------------------------------- |
33
- | **Pi Coding Agent / Pi AI** | version `0.80.0` or later |
34
- | **Node.js** | version `22.19.0` or later (needed for native HTTP/2 streaming and credential lookup) |
35
- | **A Cursor account** | with model access — signed in via the Cursor app, Cursor CLI, or browser login below |
31
+ | | |
32
+ | --------------------------- | ------------------------------------------------------------------------------------ |
33
+ | **Pi Coding Agent / Pi AI** | version `0.80.0` or later |
34
+ | **Bun** | version `1.4.0` or later the only supported runtime |
35
+ | **A Cursor account** | with model access — signed in via the Cursor app, Cursor CLI, or browser login below |
36
36
 
37
37
  ## Install
38
38
 
@@ -175,11 +175,11 @@ Usage statistics are fetched directly from Cursor's native Connect period usage
175
175
 
176
176
  ```text
177
177
  Pi Coding Agent → streamSimple (cursor-native)
178
- → h2-bridge.mjs (Node.js HTTP/2 child process)
178
+ → h2-session.ts (in-process HTTP/2 client)
179
179
  → agent.v1.AgentService/Run (Connect + Protobuf over HTTP/2)
180
180
  ```
181
181
 
182
- - **Transport:** Native Connect/protobuf streaming over HTTP/2 via `h2-bridge.mjs`.
182
+ - **Transport:** Native Connect/protobuf streaming over HTTP/2, in-process via `h2-session.ts` — no subprocess.
183
183
  - **Infrastructure Context Normalization:** Side-channel user messages (context-mode routing, post-compaction `<session_state>`, and explicit `[pi-lens automated … not a user request]` notices) are safely normalized into the system prompt so Cursor models stay focused on your primary task.
184
184
  - **Context-Efficient Tools:** MCP schemas are compacted without changing callable constraints, and exact conversational-only turns (`hi`, `thanks`, etc.) omit tools entirely. Actionable prompts always retain tools.
185
185
  - **Cross-Platform:** Tested and fully compatible with macOS, Linux, Windows, and WSL.
@@ -204,7 +204,7 @@ for tuning timeouts, debugging, and edge-case overrides.
204
204
  | `CURSOR_USAGE_SESSION_TOKEN` | Optional `WorkosCursorSessionToken` fallback cookie for `/cursor.usage`. |
205
205
  | `PI_OFFLINE` | Skip live model discovery entirely; always use the bundled fallback catalog. |
206
206
  | `PI_CURSOR_CACHE_DIR` | Where the model catalog and refresh back-off are cached (default: `$XDG_CACHE_HOME/pi-cursor` or `~/.cache/pi-cursor`). Delete it to force a full rediscovery. |
207
- | `PI_CURSOR_UNARY_BRIDGE` | `1` forces unary RPCs (model discovery) through the h2-bridge subprocess instead of the in-process HTTP/2 client. Diagnostic escape hatch. |
207
+ | `PI_CURSOR_UNARY_BRIDGE` | `1` forces unary RPCs (model discovery) through the general-purpose bridge transport instead of the dedicated one-shot in-process HTTP/2 client. Diagnostic escape hatch. |
208
208
  | `PI_CURSOR_STREAM_IDLE_TIMEOUT_MS` | Silence safety net: ms with **no upstream work** before recover/retry/error. **Default `180000` (3 min)**; `0` disables (turns run unbounded). Text/thinking/token deltas, tool-call events, and answered execs/queries reset it; heartbeats only prove the socket and do not hide an unanswered exec. It is paused during tool execution. On timeout, recovery continues from checkpoint even after partial output. |
209
209
  | `PI_CURSOR_RESUME_IDLE_TIMEOUT_MS` | Same silence safety net after tool-result resume. **Default `180000` (3 min)**; `0` disables. |
210
210
  | `PI_CURSOR_STREAM_IDLE_MAX_RETRIES` | Auto-recovery attempts after silence/transport loss. Blind restart is skipped once text/thinking streamed unless a checkpoint is available for continuation. **Default `5`**; `0` disables. |
@@ -258,12 +258,14 @@ catalog bundled in `src/models/catalog.json` on a first-ever launch. Live discov
258
258
  through pi's `refreshModels` hook — off the critical path, in the background, and again
259
259
  whenever `/model` is opened — then persists its result for the next launch.
260
260
 
261
- Unary RPCs (both discovery calls) use an in-process `node:http2` client. The h2-bridge
262
- subprocess is still used for the bidirectional chat stream, where Bun's `node:http2` is
263
- unusable, and remains the automatic fallback if the in-process client fails.
261
+ All Cursor HTTP/2 transport runs in-process via `node:http2`, which Bun implements natively — no
262
+ subprocess is spawned. Unary RPCs (both discovery calls) use a dedicated one-shot client
263
+ (`h2-unary.ts`); the bidirectional chat stream uses a persistent session (`h2-session.ts`) that
264
+ survives across turns. Unary calls fall back to the general-purpose bridge transport if the
265
+ one-shot client fails.
264
266
 
265
267
  `src/proto/agent_pb.ts` is a large generated Connect/protobuf surface used by the wire
266
- layer. Never hand-edit it — regenerate with `npm run proto:gen` (see
268
+ layer. Never hand-edit it — regenerate with `bun run proto:gen` (see
267
269
  [`proto/README.md`](proto/README.md)) when Cursor changes the agent schema.
268
270
 
269
271
  </details>
@@ -273,27 +275,47 @@ layer. Never hand-edit it — regenerate with `npm run proto:gen` (see
273
275
  - **`No API provider registered for api: cursor-native`:** Update to the latest `pi-cursor` (`pi update npm:@rahularya01/pi-cursor`) and restart Pi (or `/reload`). This means the Agent tried to stream via Pi's global `streamSimple` dispatcher before the Cursor transport was registered there. Current builds register `cursor-native` on that registry during extension load.
274
276
  - **Not logged in / 401:** Ensure Cursor CLI or app is logged in, or run `/login cursor` again. Check `/cursor.doctor` to verify your `tokenSource`. Tokens from CLI/IDE are re-resolved when near expiry; idle stream retries also force-refresh credentials.
275
277
  - **Empty / hung stream:** Cursor may have updated wire headers; verify network connectivity or bump `PI_CURSOR_CLIENT_VERSION`. `/cursor.doctor` prints the active `clientVersion`.
276
- - **Wire-protocol drift:** Cursor can change `agent.v1` at any time. Unrecognized server messages and unknown protobuf fields are no longer skipped silently — they are counted, written to the lifecycle log as `wire_drift`, appended to the failing turn's error message, and listed by `/cursor.doctor` under `wireDrift`. `wireDriftStranding=yes` means an unanswered message could have parked the turn, which is the difference between "our schema is a bit behind" and "this is why it hung". Run `CURSOR_ACCESS_TOKEN=... npm run smoke:wire` to check the handshake and schema against the live endpoint without starting a chat turn, then see [`proto/README.md`](proto/README.md) to resync the schema.
278
+ - **Wire-protocol drift:** Cursor can change `agent.v1` at any time. Unrecognized server messages and unknown protobuf fields are no longer skipped silently — they are counted, written to the lifecycle log as `wire_drift`, appended to the failing turn's error message, and listed by `/cursor.doctor` under `wireDrift`. `wireDriftStranding=yes` means an unanswered message could have parked the turn, which is the difference between "our schema is a bit behind" and "this is why it hung". Run `CURSOR_ACCESS_TOKEN=... bun run smoke:wire` to check the handshake and schema against the live endpoint without starting a chat turn, then see [`proto/README.md`](proto/README.md) to resync the schema.
277
279
  - **Stuck / dies after a few minutes of work:** Cursor `InteractionQuery` prompts are answered so the stream does not park. Web/search and unnamed proto fields are rejected (use Pi tools instead). Inspect `$TMPDIR/pi-cursor-lifecycle.jsonl` for `interaction_query` / `bridge_close` events, and `/cursor.doctor` for `lastStreamEvent`. Full debug: `PI_CURSOR_PROVIDER_DEBUG=1`.
278
280
  - **Tool continuation lost:** The provider now prefers full-history rebuild when checkpoints are stale/mismatched. If recovery still skips, `/cursor.doctor` shows `lastRecoverySkipReason`. Retry the turn or start a new chat.
279
281
  - **WSL credential detection:** Set `USERPROFILE` or `USERNAME` so the Windows home directory is known, and ensure `/mnt/c/Users/<you>/AppData/...` is readable. Disable with `PI_CURSOR_SYSTEM_CREDENTIALS=0` if undesired.
280
282
  - **Slow startup:** Activation should be a few milliseconds. `/cursor.doctor` reports `catalogCache` (`none(using bundled fallback)` means every launch is starting cold — check that `catalogCacheDir` is writable) and `unaryTransport`. A stale Cursor CLI keychain entry no longer blocks startup: a refresh token that fails is remembered for 10 minutes so it is not retried on the next launch, and any valid locally stored token is always preferred over a network exchange.
281
283
  - **Model list looks stale:** It is the last successfully discovered catalog. Open `/model` to trigger a background refresh, or delete `PI_CURSOR_CACHE_DIR` to force full rediscovery.
282
284
 
285
+ ## Runtime
286
+
287
+ `pi-cursor` targets **Bun only** — no Node.js binary is required or spawned at any point. All
288
+ Cursor HTTP/2 transport (the bidirectional chat stream and the unary discovery RPCs) runs
289
+ in-process via `node:http2`, which Bun implements natively.
290
+
291
+ Earlier versions proxied the chat stream through a short-lived Node subprocess, because Bun's
292
+ `node:http2` client was believed unable to carry a bidirectional Connect stream reliably. That
293
+ subprocess is gone: [oh-my-pi](https://github.com/can1357/oh-my-pi), a Bun-hosted fork of Pi that
294
+ talks to the same Cursor RPC, demonstrates the same bidirectional pattern working fine in-process
295
+ under Bun. Its only documented Bun/H2 caveat is ALPN negotiation failing behind an
296
+ ALPN-stripping TLS-intercepting proxy (e.g. Zscaler) — an environment issue, not a
297
+ bidirectional-streaming bug — and `/cursor.doctor`'s `lastStderr`/lifecycle log will name that
298
+ explicitly if it happens.
299
+
300
+ `/cursor.doctor` reports the runtime as `runtime=bun <version>`.
301
+
283
302
  ## Development
284
303
 
304
+ The toolchain is Bun — package manager, script runner, test runner, and bundler. `tsc` still does
305
+ the typechecking, and ESLint and Prettier are unchanged.
306
+
285
307
  ```bash
286
- npm install
287
- npm run check
308
+ bun install
309
+ bun run check
288
310
  ```
289
311
 
290
- `npm run check` runs TypeScript typechecking, ESLint, Prettier format verification, security checks, the protobuf staleness check, and unit tests.
312
+ `bun run check` runs TypeScript typechecking, ESLint, Prettier format verification, security checks, the protobuf staleness check, and unit tests.
291
313
 
292
314
  | Script | Purpose |
293
315
  | --------------------- | --------------------------------------------------------------------------------- |
294
- | `npm run proto:gen` | Regenerate `src/proto/agent_pb.ts` from `proto/agent.proto`. |
295
- | `npm run proto:sync` | Rebuild `proto/agent.proto` from an updated generated file obtained upstream. |
296
- | `npm run proto:check` | Fail if the generated protobuf is stale or hand-edited (part of `npm run check`). |
316
+ | `bun run proto:gen` | Regenerate `src/proto/agent_pb.ts` from `proto/agent.proto`. |
317
+ | `bun run proto:sync` | Rebuild `proto/agent.proto` from an updated generated file obtained upstream. |
318
+ | `bun run proto:check` | Fail if the generated protobuf is stale or hand-edited (part of `bun run check`). |
297
319
 
298
320
  ## Attributions
299
321