pi-cursor-sdk 0.5.2 → 0.5.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +38 -17
  3. package/dist/context.js +2 -2
  4. package/dist/cursor-custom-subagent-definitions.js +1 -1
  5. package/dist/cursor-fallback-models.generated.js +402 -1
  6. package/dist/cursor-local-agent-ownership.js +17 -0
  7. package/dist/cursor-mcp-timeout-override.js +1 -1
  8. package/dist/cursor-pi-tool-bridge-diagnostics.js +4 -0
  9. package/dist/cursor-pi-tool-bridge-run.js +10 -3
  10. package/dist/cursor-provider-errors.js +2 -2
  11. package/dist/cursor-provider-turn-summary.js +1 -1
  12. package/dist/cursor-session-agent-cleanup.js +10 -1
  13. package/dist/cursor-session-agent-lifecycle.js +2 -2
  14. package/dist/cursor-session-agent-lineage.js +11 -7
  15. package/dist/cursor-session-agent-resume.js +15 -9
  16. package/dist/cursor-session-agent.js +22 -7
  17. package/dist/cursor-session-scope.js +27 -14
  18. package/dist/cursor-session-settings.js +3 -3
  19. package/dist/cursor-session-store.js +1 -1
  20. package/dist/cursor-state.js +17 -6
  21. package/dist/model-discovery.js +8 -9
  22. package/docs/cursor-live-smoke-checklist.md +2 -2
  23. package/docs/cursor-model-ux-spec.md +23 -14
  24. package/docs/cursor-native-tool-replay.md +6 -3
  25. package/docs/cursor-native-tool-visual-audit.md +1 -1
  26. package/docs/cursor-testing-lessons.md +24 -6
  27. package/docs/cursor-tool-surfaces.md +16 -1
  28. package/package.json +8 -8
  29. package/src/context.ts +2 -2
  30. package/src/cursor-custom-subagent-definitions.ts +1 -1
  31. package/src/cursor-fallback-models.generated.ts +402 -1
  32. package/src/cursor-local-agent-ownership.ts +18 -0
  33. package/src/cursor-mcp-timeout-override.ts +1 -1
  34. package/src/cursor-pi-tool-bridge-diagnostics.ts +17 -0
  35. package/src/cursor-pi-tool-bridge-run.ts +10 -3
  36. package/src/cursor-provider-errors.ts +2 -2
  37. package/src/cursor-provider-turn-summary.ts +1 -1
  38. package/src/cursor-session-agent-cleanup.ts +6 -1
  39. package/src/cursor-session-agent-lifecycle.ts +2 -2
  40. package/src/cursor-session-agent-lineage.ts +10 -5
  41. package/src/cursor-session-agent-resume.ts +14 -7
  42. package/src/cursor-session-agent.ts +23 -7
  43. package/src/cursor-session-scope.ts +33 -11
  44. package/src/cursor-session-settings.ts +3 -3
  45. package/src/cursor-session-store.ts +1 -1
  46. package/src/cursor-state.ts +25 -5
  47. package/src/model-discovery.ts +7 -8
@@ -49,7 +49,7 @@ PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1 pi --model cursor/grok-4.6
49
49
 
50
50
  Shell start/completion correlation accepts legacy shell aliases with identical arguments even if IDs differ, but only for a unique pending match. Multiple identical pending shells remain unmatched without an exact ID, which takes precedence. Unmatched shell starts remain visible; assistant text or stdout progress alone does not prove completion.
51
51
 
52
- This alias handling is an extension compatibility contract, not an observed alias-changing SDK callback pair. SDK 1.0.36's public started/completed updates carry `callId`, `modelCallId`, and a ToolCall with `type: "shell"`. The installed `run-interaction-accumulator` copies the completed ToolCall into `onStep({ step: { type: "toolCall", message: toolCall } })`, without adding `step.id`, before forwarding the completed delta. An offline provider contract executes that installed producer and checks reconciliation/deduplication; legacy alias tests separately check compatibility inputs. No retained alias-changing service capture establishes that this fixes the reported stale-shell symptom.
52
+ This alias handling is an extension compatibility contract, not an observed alias-changing SDK callback pair. SDK 1.0.37's public started/completed updates carry `callId`, `modelCallId`, and a ToolCall with `type: "shell"`. In retained SDK 1.0.36 installed-package evidence, `run-interaction-accumulator` copies the completed ToolCall into `onStep({ step: { type: "toolCall", message: toolCall } })`, without adding `step.id`, before forwarding the completed delta. The SDK 1.0.36 offline provider contract executes that producer and checks reconciliation/deduplication; legacy alias tests separately check compatibility inputs. No retained alias-changing service capture establishes that this fixes the reported stale-shell symptom.
53
53
 
54
54
  ## What gets replayed
55
55
 
@@ -74,13 +74,13 @@ When Cursor reports completed tool activity, the extension can display recorded
74
74
 
75
75
  Cursor `glob` activity is displayed through native `find` cards.
76
76
 
77
- For the full `@cursor/sdk@1.0.36` `ToolType` set, disposition matrix, and runtime alias normalization, see [SDK ToolType replay matrix](#sdk-tooltype-replay-matrix) below. Official SDK reference: https://cursor.com/docs/sdk/typescript
77
+ For the full `@cursor/sdk@1.0.37` `ToolType` set, disposition matrix, and runtime alias normalization, see [SDK ToolType replay matrix](#sdk-tooltype-replay-matrix) below. Official SDK reference: https://cursor.com/docs/sdk/typescript
78
78
 
79
79
  Edit and write activity replays through pi-facing `edit` and `write` cards only when replay arguments truthfully satisfy the matching pi schema, but still uses recorded Cursor results only. The adapter passes through truthful Cursor paths, content when Cursor reported it, and recorded diff/details; it does not pretend Cursor's editing schema is pi's schema and it fails closed if a recorded replay result is missing. Cursor `StrReplace` with recorded replacement text displays as native-looking `edit`; path-only Cursor `edit` and notebook edit activity fall back to neutral Cursor activity so pi does not reject the replay before recorded-result handling. Cursor `write` displays as native-looking `write`. Diagnostics, delete, todos/plans, task/subagent, image, MCP, semantic search, screen recording, and web search/fetch activity use neutral Cursor activity cards with pi's default success/error tool shell. Cursor SDK `task` activity is labeled **Cursor subagent** by default because it represents Cursor-spawned child-agent work; `PI_CURSOR_TASK_PRESENTATION=task` keeps the older **Cursor task** wording for comparison. MCP completions whose `toolName` is `WebSearch` / `web_search` / `WebFetch` / similar are labeled **Cursor web search** or **Cursor web fetch** instead of generic **Cursor MCP**. Neutral Cursor activity cards carry display metadata such as `activityTitle` and `activitySummary`, so partial/collapsed cards can say `Cursor plan`, `Cursor todos`, `Cursor subagent`, `Cursor MCP`, `Cursor semantic search`, `Cursor screen recording`, `Cursor web search`, `Cursor web fetch`, or `Cursor edit` instead of only `Cursor activity`. These replay tools only display recorded Cursor results; they never mutate files or execute tool work directly. Replay paths are normalized to workspace-relative paths when possible. Most collapsed replay cards include bounded previews for diffs and text details so small edits, todos, task output, and MCP results are visible without expanding; web search/fetch activity stays summary-only while collapsed because those cards often arrive after final text and can otherwise bury the answer. Ctrl+O expansion shows the recorded details. Edit previews omit raw unified diff headers and show compact numbered changed/context lines using pi's native diff added/removed/context colors, and write previews use syntax highlighting when pi can infer a language from the path. Image generation replay cards show the saved image path in the collapsed summary and render the image inline when pi terminal image display is enabled and the generated file is still readable.
80
80
 
81
81
  ## SDK ToolType replay matrix
82
82
 
83
- Source of truth for SDK tool names: `@cursor/sdk@1.0.36` conversation `ToolType` values and https://cursor.com/docs/sdk/typescript
83
+ Source of truth for SDK tool names: `@cursor/sdk@1.0.37` public `ToolType = ToolCall["type"]` union and https://cursor.com/docs/sdk/typescript. All SDK 1.0.36 variants remain; SDK 1.0.37 adds `computerUse`.
84
84
 
85
85
  Implementation owners: `src/cursor-tool-presentation-registry.ts` (canonical names, labels, visibility, replay policy, bridge exclusions for internal replay wrappers, alias normalization, and display-spec key completeness), `src/cursor-transcript-tool-specs.ts` (registry-keyed display implementations for transcript formatting and pi display builders), `src/cursor-native-tool-display-replay.ts` (replay card rendering derived from registry replay metadata), and `src/cursor-web-tool-activity.ts` (MCP/web alias remapping before display lookup).
86
86
 
@@ -106,10 +106,13 @@ This matrix covers **Cursor native tool replay only**. It does not describe the
106
106
  | `mcp` | neutral activity | `cursor` | Collapsed label **Cursor MCP** for non-web MCP completions; web search/fetch MCP `toolName` values reclassify to the rows below |
107
107
  | `semSearch` | neutral activity | `cursor` | Collapsed label **Cursor semantic search**; semantic codebase search, not web search |
108
108
  | `recordScreen` | neutral activity | `cursor` | Collapsed label **Cursor screen recording** |
109
+ | `computerUse` | bounded generic activity/summary fallback | `cursor` | New SDK 1.0.37 public output variant; label **Cursor computerUse**. No dedicated action cards or screenshot presentation, and no new public local execution option |
109
110
  | *(host/MCP alias)* `WebSearch` / `web_search` / similar | neutral activity | `cursor` | Collapsed label **Cursor web search**; display-only Cursor web access reported by the SDK, not an executable pi web tool |
110
111
  | *(host/MCP alias)* `WebFetch` / `web_fetch` / similar | neutral activity | `cursor` | Collapsed label **Cursor web fetch**; display-only Cursor web access reported by the SDK, not an executable pi web tool |
111
112
  | _(no spec; future/unknown SDK name)_ | neutral activity | `cursor` | Collapsed label **Cursor** plus SDK tool name via `buildGenericPiToolDisplay()`; bounded fallback transcript only |
112
113
 
114
+ **SDK 1.0.37 `computerUse` ceiling:** The public completed payload uses `type: "computerUse"` with `args.actions`, `args.description` and a success/error result; `computerUseToolCall` is its protobuf discriminant, not a pi executable tool name. The existing generic fallback summarizes scrubbed arguments/results and preserves error status within bounds (up to eight argument entries, three array preview items, and default result/error limits of 240 characters/six lines). It does not provide dedicated action cards, screenshot-path previews or lossless action/result display. The output union addition does not add a public local computer-use executor/configuration option.
115
+
113
116
  **Unknown/future fallback path:** SDK tool names with no registry-backed display implementation entry (future or unknown types) use `buildGenericPiToolDisplay()` in `src/cursor-transcript-tool-specs.ts` with bounded `formatFallback()` content from `src/cursor-transcript-tool-formatters.ts`. Lookup uses `Object.hasOwn()` on the display implementation table so inherited object keys such as `constructor` or `toString` cannot accidentally match a registry spec. When native replay is enabled, those completions queue through neutral pi tool name `cursor` (not native pi `read`/`bash`/… cards). Collapsed labels read like **Cursor futureSemSearchWidget** (title `Cursor` plus the SDK tool name) with optional bounded `activitySummary` from scrubbed args/result lines. Errors keep `details.summary` undefined so unbounded raw errors do not leak into replay cards (#52). Known explicit specs still win over this path; real pi bridge tool names such as `edit` and `write` are not suppressed by internal replay-wrapper exclusions.
114
117
 
115
118
  **Replay detail disposition model:** `src/cursor-replay-tool-details.ts` stores replay card disposition separately from SDK source tool identity. Variants are `nativeEdit`, `nativeWrite`, `activity` (`sourceToolName` + display `title`), `generateImage`, and `genericFallback`. Path-only or notebook edit/write fallbacks produce `activity` details (neutral `cursor` cards) instead of structured edit/write variants with optional `title` escape hatches. Native edit/write cards use `nativeEdit` / `nativeWrite` only when pi-facing replay args satisfy the matching schema. The renderer dispatches on `variant` only.
@@ -6,7 +6,7 @@ This workflow is the canonical repo path for verifying Cursor SDK tool replay th
6
6
 
7
7
  Use it when changed replay-card behavior needs new visual proof not covered by offline rendering contracts or valid retained evidence. Text logs and JSONL are not enough for visual-parity claims: keep PNGs for the exact prompt, and before/after PNGs for a rendering comparison. Reuse a valid retained baseline instead of paying to recreate it.
8
8
 
9
- Current validation baseline: Node 24+, exact `@cursor/sdk@1.0.36`, official Pi 0.87.1/latest and current `fitchmultz/pi` main. Development Pi packages `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`, and `@earendil-works/pi-tui` are exact locked 1.0.4 snapshots, with host TypeBox 1.3.27. These locked development snapshots are not qualification targets; resolve latest stable official Pi and current `fitchmultz/pi` main once per workflow run. Optional published Pi and TypeBox peer dependencies use `"*"` ranges per Pi guidance.
9
+ Current validation baseline: Node 24+, exact `@cursor/sdk@1.0.37`, official Pi 0.87.1/latest and current `fitchmultz/pi` main. Development Pi packages `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`, and `@earendil-works/pi-tui` are exact locked 1.0.4 snapshots, with host TypeBox 1.3.27. These locked development snapshots are not qualification targets; resolve latest stable official Pi and current `fitchmultz/pi` main once per workflow run. Optional published Pi and TypeBox peer dependencies use `"*"` ranges per Pi guidance.
10
10
 
11
11
  ## Cursor SDK 1.0.17 / pi 0.79.0 cutover visual record
12
12
 
@@ -52,7 +52,25 @@ If resync runs but `context.tools` is still stale (e.g. only `read` listed), the
52
52
 
53
53
  `test/cursor-provider-pi-context.test.ts` drives real `ModelRuntime` / `ModelRegistry` requests into `streamCursor`, with only Cursor SDK execution mocked. Run it against each supported host with all Pi peer imports pinned to that host (including nested native imports); a top-level package version alone is not resolution evidence. Cover official Pi 0.87.1, official latest, and current `fitchmultz/pi` main. The direct development Pi packages are locked 1.0.4 snapshots, not qualification targets; resolve latest stable official Pi and current `fitchmultz/pi` main once per workflow run. Their actual nested resolution is recorded with each check, including host TypeBox 1.3.27.
54
54
 
55
- The test covers bootstrap/incremental prompts, empty-vs-absent request tools, native replay/drain, cloud fresh/bootstrap selection, and actual host prompt serialization for context files and skills. `test/native-cursor-flow.test.mjs` additionally exercises the compiled extension through the real loader and registered Cursor provider, substituting only the external SDK transport/storage. It verifies actual bridge tool execution, pending-work idle/abort/shutdown/deadline ownership, replay without file access, persisted usage/lineage, tree, compaction, queued steering, abort and reload/disposal. `test/native-cursor-prompt.test.mjs` owns genuine native input, hidden notices, required-budget input, current attachments, custom-only continuation, equivalent conversion, payload/order-changing rejection, and GitHub comment soft guidance across bootstrap/incremental/custom-only sends. Both owners use `test/helpers/native-cursor-harness.mjs` and run in the explicit `check:compat` list and manual official-host compatibility route; the native-platform Vitest job is not execution evidence for these Node test owners. Explicit `tools` is now an allowlist, not merely an initial active set; use `defaultTools` for a native fixture that allows replay wrappers to activate. `test/native-provider.test.mjs` additionally verifies canonical `SessionManager.appendContextEdit()` plus `refreshContext()`, unchanged raw history, and conversation filtering that preserves system instructions, the current tool declaration, and explicit tool removal (the focused native slice from #271). It is offline contract evidence. Add live proof only for changed behavior that still needs real-service evidence under the cost policy above; do not rerun unchanged live lanes or infer full live coverage from offline tests.
55
+ The test covers bootstrap/incremental prompts, empty-vs-absent request tools, native replay/drain, cloud fresh/bootstrap selection, and actual host prompt serialization for context files and skills. `test/native-cursor-flow.test.mjs` additionally exercises the compiled extension through the real loader and registered Cursor provider, substituting only the external SDK transport/storage. It verifies actual bridge tool execution, pending-work idle/abort/shutdown/deadline ownership, replay without file access, persisted usage/lineage, tree, compaction, queued steering, abort and reload/disposal. `test/native-cursor-prompt.test.mjs` owns genuine native input, hidden notices, required-budget input, current attachments, custom-only continuation, equivalent conversion, payload/order-changing rejection, and GitHub comment soft guidance across bootstrap/incremental/custom-only sends. `test/native-cursor-ownership.test.mjs` owns concurrent-session contracts, including independently reopened managers for the same file, pending bridge survival across sibling reload/tree/shutdown, durable-key stability and atomic live-handle exclusion. These owners use `test/helpers/native-cursor-harness.mjs` and run in the explicit `check:compat` list and manual official-host compatibility route; the native-platform Vitest job is not execution evidence for these Node test owners. Explicit `tools` is now an allowlist, not merely an initial active set; use `defaultTools` for a native fixture that allows replay wrappers to activate. `test/native-provider.test.mjs` additionally verifies canonical `SessionManager.appendContextEdit()` plus `refreshContext()`, unchanged raw history, and conversation filtering that preserves system instructions, the current tool declaration, and explicit tool removal (the focused native slice from #271). It is offline contract evidence. Add live proof only for changed behavior that still needs real-service evidence under the cost policy above; do not rerun unchanged live lanes or infer full live coverage from offline tests.
56
+
57
+ ## Installed SDK vs native host evidence
58
+
59
+ The native harness substitutes external Cursor SDK transport/storage. It qualifies Pi ownership, scheduling and persisted-session behavior, not real SDK request-time linking. `test/cursor-sdk-lazy-import.test.ts` separately drives public installed `Agent.create()` → `send()` → `run.wait()` with `JsonlLocalAgentStore`, an empty credential environment/private HOME, and pre-import Node network/process guards. The positive case reaches exactly one blocked key-exchange fetch; the negative case denies an SDK module only after creation and fails before network. This protects first-send linking beyond a successful static import. The guards are public Node API interception, not an OS sandbox, and neither case qualifies authenticated gRPC, compiled Pi or the original Windows embedded hosts.
60
+
61
+ For missing exports, inspect resolution **from the failing importer**, not a root-level import. The installed SDK 1.0.36 nested Connect 1.7.0 / Protobuf 1.10.0 graph links; forcing that import to root Protobuf 2.16.0 reproduces `protoBase64`'s absence. This establishes a mechanism, not #233's unnamed host mapping. SDK-declared ranges, installed dependency versions and vendored transport versions are distinct facts.
62
+
63
+ An installed-package research probe can isolate a mechanism but cannot certify the public runtime. Exact SDK 1.0.23 source already has settings-selected hook loading, config leases, and Shell/ShellStream `updated_input.command` rewriting. Its direct hook-payload transport depends on `hooks_stdin_transport` (false by default or if initialization fails); false still delivers JSON through a POSIX heredoc or Windows PowerShell here-string, not missing hooks or missing stdin payload. SDK 1.0.36 always selects the direct transport mode. These are source endpoints, not a verified change date or rtk repair. The retained SDK 1.0.36 Shell-hook canary used private lexical bindings and a permissive approval collaborator: it read user hooks, passed the invocation ID, applied `updated_input.command`, and observed rewritten file output, with both native parsing and `parsingFailed`. It is not execution evidence for SDK 1.0.23, Pi/rtk integration or security-policy enforcement and must not become production integration. Replay arguments may precede rewriting; require original input, hook decision and actual executed command for the same invocation before diagnosing #173. The parser-warning branch does not establish the emitter or SIGTERM sender in #339.
64
+
65
+ For #247, exact SDK 1.0.27 source caches the exchanged bearer until invalidation, without expiry-based refresh; SDK 1.0.36 adds JWT-aware refresh, a 30-minute fallback when expiry cannot be parsed, and raw-Unauthenticated stream invalidation without interceptor resend. These source endpoints establish neither a change date, backend TTL, the original failure cause nor service recovery. SDK 1.0.27 already distinguishes classified authentication errors from raw Connect retry, shares reference-counted executor leases, and limits `agent.reload()` to workspace reload—not an auth-reset API. Failed provider runs reset their owned pool, but disposing one agent need not dispose an executor leased elsewhere. Require the redacted error chain and agent/executor/run transitions around retry and reload; do not infer a safe resend or add a guessed TTL from sanitized text.
66
+
67
+ The integrity-verified [SDK 1.0.37 package](https://registry.npmjs.org/@cursor/sdk/-/sdk-1.0.37.tgz) source comparison retains those SDK 1.0.36 bearer, executor-lease, workspace-reload, Shell/ShellStream hook-rewrite and parser-warning mechanisms. Public `index.d.ts`, `options.d.ts` and `sdk-config.d.ts` are byte-identical: both commit/PR attribution controls remain absent, with no new auth-reset, hook-transport, MCP timeout/readiness or local GUI option. LOCAL custom-subagent conversion remains ID/inherit-only; inspected SQLite/checkpoint/default-root factories retain the same layouts and MD5-to-SHA256 migration. This comparison establishes bounded source equivalence, not executed SDK 1.0.37 hook-canary, SQLite-migration or platform qualification. Keep the retained SDK 1.0.36 canary and 2026-10-06 45-model catalog attributed to their actual version.
68
+
69
+ A subsequent authenticated SDK 1.0.37 catalog-only refresh on 2026-10-07 returned 46 models and regenerated `src/cursor-fallback-models.generated.ts`, adding Claude Haiku 5.5 (`claude-haiku-5-5`) while preserving all 45 prior records. Its 20 variants expose `thinking=false|true`, `context=300k|1m` and `reasoning_effort=low|medium|high|xhigh|max`, with defaults `true`, `1m` and `high`. No checkpoint input was supplied: all 33 bundled checkpoint-derived entries were retained unchanged. This is catalog metadata proof only; it started no Agent/model turn or Cloud run and does not qualify hook execution, effective checkpoint limits, SQLite migration or native/platform behavior.
70
+
71
+ SDK 1.0.37 does materially change its vendored transport/retry source: HTTP/2 ping verification gains bounded completion and listener cleanup, HTTP/1 and HTTP/2 response iteration awaits the iterator directly while preserving already-rejected sentinel errors, and local retry classification adds `UND_ERR_SOCKET` plus failure-kind budget selection. SDK-declared external ranges are unchanged; neither those ranges nor a new vendored patch identity proves the resolved host graph or service recovery. Requalify installed-source transport and first-send contracts against the actual package; none of this establishes #247's original auth cause, #339's signal sender, #173's rtk behavior, #233's Windows importer graph or #206's readiness.
72
+
73
+ The 60-second MCP protocol default and lack of a public timeout option remain. SDK 1.0.37's internal `setToolCallRequestOptions`, `setToolCallOutputSchemaPassthrough` and `setListingDeadline` each occur only as definitions in the inspected ESM JavaScript, with no invocation found. They are not supported public setters or proof of readiness; preserve the extension's verified timeout compatibility path rather than adding private patches. The new public `computerUse` output variant uses the existing bounded generic replay fallback, not dedicated action/screenshot rendering or a new local execution option; see the [canonical replay matrix](./cursor-native-tool-replay.md#sdk-tooltype-replay-matrix).
56
74
 
57
75
  ## Maintainer-only offline proof retention
58
76
 
@@ -85,7 +103,7 @@ offline node_modules/vitest/vitest.mjs run test/cursor-sdk-output-filter.test.ts
85
103
  test/cursor-provider-stream-usage.test.ts test/cursor-provider-replay-live-run.test.ts \
86
104
  test/cursor-session-agent-local-resume.test.ts
87
105
  offline --test test/native-provider.test.mjs test/native-cursor-flow.test.mjs \
88
- test/native-cursor-prompt.test.mjs
106
+ test/native-cursor-prompt.test.mjs test/native-cursor-ownership.test.mjs
89
107
  ```
90
108
 
91
109
  These artifacts may include prompts, tool arguments/results, local paths and private session facts. Never print, commit or publish them; never supply real keys to this offline workflow. Inspect persisted joins and bytes privately, then retain or remove only your owned proof directory. Offline artifacts establish the tested local SDK/native contracts, **not** all-host/backend qualification or paid-service acceptance.
@@ -256,7 +274,7 @@ Pass criteria:
256
274
 
257
275
  Run offline checks first, then reuse retained proof whose tested inputs are unchanged. If changed behavior still needs real-service proof, choose one existing meaningful check on a representative environment. Do not run every command below as a paid ladder; docs/metadata-only changes need zero paid runs.
258
276
 
259
- TypeScript 7 owns builds and type checks. `@typescript/typescript6` is dev-only for AST architecture and installed-SDK contract tests because TypeScript 7 has no stable compiler API. Vitest 5 defaults `clearMocks` to `true`.
277
+ TypeScript 7 owns builds and type checks. Build and typecheck commands invoke `node_modules/typescript/bin/tsc` explicitly to avoid npm's shared `tsc` shim selecting a different compiler. `@typescript/typescript6` is dev-only for AST architecture and installed-SDK contract tests because TypeScript 7 has no stable compiler API. Vitest 5 defaults `clearMocks` to `true`.
260
278
 
261
279
  ```bash
262
280
  npm test
@@ -325,7 +343,7 @@ The script writes timestamped artifacts under `--out` (default `/tmp/pi-cursor-s
325
343
 
326
344
  Stdout prints artifact paths and summary counts only. Raw payloads stay on disk and may contain local paths, project text, tool args/results, or secrets — do not commit or share them.
327
345
 
328
- Hard repo rule: Cursor SDK behavior claims must come from the installed `@cursor/sdk` package and/or https://cursor.com/docs/sdk/typescript, not from memory or ad-hoc probes alone. Current validation targets Node 24+, exact `@cursor/sdk@1.0.36`, official Pi 0.87.1/latest, and current `fitchmultz/pi` main.
346
+ Hard repo rule: Cursor SDK behavior claims must come from the installed `@cursor/sdk` package and/or https://cursor.com/docs/sdk/typescript, not from memory or ad-hoc probes alone. Current validation targets Node 24+, exact `@cursor/sdk@1.0.37`, official Pi 0.87.1/latest, and current `fitchmultz/pi` main.
329
347
 
330
348
  ## Pi provider SDK event capture
331
349
 
@@ -416,7 +434,7 @@ Stderr output for these records requires `PI_CURSOR_SDK_EVENT_DEBUG_STDERR=1`. T
416
434
 
417
435
  **Symptom:** Assistant output lists tool invocations (for example `Tool call`, `Cursor activity`, `call cursor-replay-…`, `toolName`, `browser_navigate`) instead of pi tool execution cards/results.
418
436
 
419
- **What the screenshot in [#40](https://github.com/fitchmultz/pi-cursor-sdk/issues/40) shows:** Plain assistant text that mirrors pi's **prompt transcript format** for replay tool calls (`Tool call (Cursor activity, call cursor-replay-…): …` from `src/context.ts`) rather than a rendered pi `toolCall` card. That pattern usually means the Cursor model **narrated** a tool call as text; it is not proof that pi failed to emit `toolcall_start` / `toolUse`.
437
+ **What the screenshot in [#40](https://github.com/fitchmultz/pi-cursor-sdk/issues/40) shows:** Plain assistant text that mirrors the old prompt transcript format (`Tool call (Cursor activity, call cursor-replay-…): …`) rather than a rendered pi `toolCall` card. That pattern is narration, not proof that pi failed to emit `toolcall_start` / `toolUse`. Structured tool history now uses `Historical tool request/result/error` in `src/context.ts`; an unmatched request remains a request. Regression coverage retains arguments, IDs, errors, raw messages/fingerprints, prose/code fences, prompt paths and coherent estimates. The change removes an imitable template, not prior assistant text or the underlying model behavior in #257.
420
438
 
421
439
  **Do not close #40 as duplicate of #55 without session JSONL.** #55 surfaces scrubbed SDK run failures and abort causes in the TUI. #40 can occur with no error toast when the model prints tool metadata as assistant text, when replay is display-only but the user expected real execution, when stale native replay routing or plan-strip resync gaps produce `Tool * not found` errors (see **#52**), or when started SDK tools were discarded at run end (see **#52** maintainer debug and [Discarded incomplete SDK tool calls](#discarded-incomplete-sdk-tool-calls) above). A hard **process exit** from uncaught `ConnectError` / `ETIMEDOUT` is **#43**, not #40 text echo.
422
440
 
@@ -490,7 +508,7 @@ Then inspect the failing assistant turn in `$SMOKE_DIR/session/*.jsonl`:
490
508
  3. **`content` is only `type: "text"` and text contains `Tool call (` / `cursor-replay-` / serialized arg keys** — model text echo of prompt transcript format; not #55, not #52 stale routing. Compare with `buildCursorPrompt()` output in the prior turn.
491
509
  4. **No `toolCall` blocks, no error toast, user expected real execution** — check whether names are replay-only (`cursor-replay-*`) or Cursor-native MCP; replay never re-runs work ([replay doc](./cursor-native-tool-replay.md)).
492
510
  5. **`stopReason: "error"` or scrubbed `errorMessage`** — classify under **#55**; check whether incomplete started tools were discarded (`discardIncompleteStartedToolCalls()`). Discarded starts with no completion and no model text echo: see `coordinator-events.jsonl` phase `discarded-incomplete-started-tool-call` ([Discarded incomplete SDK tool calls](#discarded-incomplete-sdk-tool-calls) above); route broader stale/inactive replay gaps to **#52**.
493
- 6. **Bridge expected (`pi__*` in Cursor MCP)** — inspect stderr `[pi-cursor-sdk:bridge]` JSONL with `PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1` for pending/unresolved bridge requests.
511
+ 6. **Bridge expected (`pi__*` in Cursor MCP)** — inspect stderr `[pi-cursor-sdk:bridge]` JSONL with `PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1`. Exposure records are not connection proof; `mcp_initialized` is a validated server notification receipt, `mcp_tools_list` is catalog-handler output, and request records establish actual call handling. None proves model consumption or ongoing health. See [bridge diagnostic boundaries](./cursor-tool-surfaces.md#diagnosing-advertised-but-unused-bridge-tools).
494
512
 
495
513
  Quick structural scan (no secrets):
496
514
 
@@ -19,7 +19,22 @@ Pi CLI tool toggles apply at the pi tool-registry boundary. `--no-tools`, `--too
19
19
  - **MCP `listTools`** (and pi's MCP catalog when present) lists **MCP servers only** — for example `pi_tools` with `pi__cursor_ask_question`. It does **not** enumerate Cursor SDK host tools such as `Read` or `Shell`.
20
20
  - **Bootstrap prompts** include a short **Cursor SDK tool boundary** block plus a compact **callable tool surfaces** manifest by default (disable manifest with `PI_CURSOR_TOOL_MANIFEST=0`). The manifest reminds the model that Cursor host/configured MCP tools are controlled by Cursor, while pi tool toggles only affect pi tools/bridge exposure; when bridge tools are exposed, it lists the current `pi__*` names. MCP `listTools` entries for bridged pi tools point back to the bootstrap prompt instead of repeating the full contract.
21
21
  - **Incremental prompts** omit the full boundary block but keep a short tail guard (including an explicit shell `cd` hint); the session agent retains prior bootstrap context. They also omit invariant Pi system instructions; a changed system prompt forces bootstrap with the new section.
22
- - **In-session debug:** `/cursor-tools` prints bridge enablement, manifest enablement, effective `PI_CURSOR_SETTING_SOURCES`, and the current callable-surface snapshot.
22
+ - **In-session debug:** `/cursor-tools` prints bridge/manifest enablement, effective `PI_CURSOR_SETTING_SOURCES`, and current-registry exposure eligibility, including the builtin-exposure setting. It is not a live-run catalog or health check.
23
+
24
+ ## Diagnosing advertised but unused bridge tools
25
+
26
+ Enable `PI_CURSOR_PI_TOOL_BRIDGE_DEBUG=1` before the turn. The existing scrubbed stderr records correlate observations by safe run ID:
27
+
28
+ | Record | What it establishes |
29
+ | --- | --- |
30
+ | `run_created` / `tools_exposed` | Run exposure and pi↔MCP name mapping, not connection |
31
+ | `mcp_initialized` | Server receipt of validated `notifications/initialized` |
32
+ | `mcp_tools_list` | Catalog-handler output after request validation, with `toolCount` |
33
+ | `request_queued` / `request_resolved` / `request_rejected` | Actual bridge call handling |
34
+
35
+ Initialization/catalog receipts are server observations, not Cursor-client identity, response delivery, model consumption or ongoing health. Absence does not explain why no request occurred. `/cursor-tools` reflects the registry now, not an earlier run's captured surface; exposure alone is not invocation proof. These diagnostics do not enumerate Cursor-configured MCP connections. Do not share logs where tool names are sensitive; endpoint credentials and raw args/results are excluded.
36
+
37
+ For an advertised-but-unused `pi__subagent`, first identify the active provider/version (especially with multiple Cursor providers installed), then compare the run's exposure, initialization/catalog and call records with persisted pi `toolCall`/`toolResult` rows. Bash-spawned Pi is not evidence of bridged `subagent` execution. The original Windows/two-provider report remains open in [#206](https://github.com/fitchmultz/pi-cursor-sdk/issues/206).
23
38
 
24
39
  ## Pi bridge vs Cursor native
25
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cursor-sdk",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "pi provider extension backed by @cursor/sdk local and cloud agents",
5
5
  "author": "Mitch Fultz (https://github.com/fitchmultz)",
6
6
  "license": "MIT",
@@ -120,13 +120,13 @@
120
120
  "node": ">=24"
121
121
  },
122
122
  "scripts": {
123
- "check:compat": "npm run build && npm run verify && node --test test/ci-compatibility.test.mjs test/native-provider.test.mjs test/native-cursor-flow.test.mjs test/native-cursor-prompt.test.mjs",
123
+ "check:compat": "npm run build && npm run verify && node --test test/ci-compatibility.test.mjs test/native-provider.test.mjs test/native-cursor-flow.test.mjs test/native-cursor-ownership.test.mjs test/native-cursor-prompt.test.mjs",
124
124
  "build": "node ./scripts/build.mjs",
125
125
  "prepare": "node ./scripts/prepare.mjs",
126
126
  "typecheck": "npm run typecheck:src && npm run typecheck:tests && npm run typecheck:replay-compile",
127
- "typecheck:src": "tsc --noEmit",
128
- "typecheck:tests": "tsc -p tsconfig.test.json --noEmit",
129
- "typecheck:replay-compile": "tsc --noEmit -p test/tsconfig.json",
127
+ "typecheck:src": "node ./node_modules/typescript/bin/tsc --noEmit",
128
+ "typecheck:tests": "node ./node_modules/typescript/bin/tsc -p tsconfig.test.json --noEmit",
129
+ "typecheck:replay-compile": "node ./node_modules/typescript/bin/tsc --noEmit -p test/tsconfig.json",
130
130
  "verify": "npm run check:platform-smoke && npm run typecheck && npm test",
131
131
  "test": "vitest run",
132
132
  "test:watch": "vitest",
@@ -161,7 +161,7 @@
161
161
  "smoke:platform:all": "npm run smoke:platform:doctor && node scripts/platform-smoke.mjs run --target macos,ubuntu,windows-native"
162
162
  },
163
163
  "dependencies": {
164
- "@cursor/sdk": "1.0.36",
164
+ "@cursor/sdk": "1.0.37",
165
165
  "@hono/node-server": "2.1.3",
166
166
  "@modelcontextprotocol/hono": "2.0.2",
167
167
  "@modelcontextprotocol/server": "2.3.1",
@@ -189,11 +189,11 @@
189
189
  "@typescript/typescript6": "6.0.2",
190
190
  "@xterm/xterm": "6.0.0",
191
191
  "node-pty": "1.1.0",
192
- "playwright": "1.63.0",
192
+ "playwright": "1.64.0",
193
193
  "typebox": "1.3.36",
194
194
  "typescript": "7.0.2",
195
195
  "vitest": "5.0.3",
196
- "yaml": "2.9.0"
196
+ "yaml": "2.9.1"
197
197
  },
198
198
  "pi": {
199
199
  "extensions": [
package/src/context.ts CHANGED
@@ -128,7 +128,7 @@ function formatContentBlocks(content: string | { type: string; text?: string; da
128
128
 
129
129
  function formatToolCall(toolCall: ToolCall): string {
130
130
  const args = JSON.stringify(toolCall.arguments) ?? "";
131
- return `Tool call (${getCursorReplayPromptLabel(toolCall.name)}, call ${toolCall.id}): ${args}`;
131
+ return `Historical tool request (${getCursorReplayPromptLabel(toolCall.name)}, call ${toolCall.id}): ${args}`;
132
132
  }
133
133
 
134
134
  function sanitizeSystemPromptForCursor(systemPrompt: string): string {
@@ -177,7 +177,7 @@ function formatMessage(msg: Message): string | undefined {
177
177
  }
178
178
  case "toolResult": {
179
179
  const text = formatContentBlocks(msg.content);
180
- const label = msg.isError ? "Tool error" : "Tool result";
180
+ const label = msg.isError ? "Historical tool error" : "Historical tool result";
181
181
  return `${label} (${getCursorReplayPromptLabel(msg.toolName)}, call ${msg.toolCallId}): ${text}`;
182
182
  }
183
183
  }
@@ -17,5 +17,5 @@ export function buildCursorCustomSubagentDefinitions(config: CursorCustomSubagen
17
17
  }]));
18
18
  }
19
19
 
20
- // ponytail: SDK 1.0.36 LOCAL conversion keeps only model ID/inherit; it drops params.
20
+ // ponytail: SDK 1.0.37 LOCAL conversion keeps only model ID/inherit; it drops params.
21
21
  // Upgrade this claim only after the installed public converter preserves them.
@@ -1,6 +1,6 @@
1
1
  import type { ModelListItem } from "@cursor/sdk";
2
2
 
3
- // Generated with @cursor/sdk@1.0.36 from 45 Cursor models.
3
+ // Generated with @cursor/sdk@1.0.37 from 46 Cursor models.
4
4
  // Refresh with: npm run refresh:cursor-snapshots -- --write
5
5
  // Do not add secrets; this file stores public model metadata only.
6
6
  export const FALLBACK_MODEL_ITEMS = [
@@ -913,6 +913,407 @@ export const FALLBACK_MODEL_ITEMS = [
913
913
  }
914
914
  ]
915
915
  },
916
+ {
917
+ id: "claude-haiku-5-5",
918
+ displayName: "Claude Haiku 5.5",
919
+ parameters: [
920
+ {
921
+ id: "thinking",
922
+ displayName: "Thinking",
923
+ values: [
924
+ {
925
+ value: "false"
926
+ },
927
+ {
928
+ value: "true"
929
+ }
930
+ ]
931
+ },
932
+ {
933
+ id: "context",
934
+ displayName: "Context",
935
+ values: [
936
+ {
937
+ value: "300k",
938
+ displayName: "300K"
939
+ },
940
+ {
941
+ value: "1m",
942
+ displayName: "1M"
943
+ }
944
+ ]
945
+ },
946
+ {
947
+ id: "reasoning_effort",
948
+ displayName: "Effort",
949
+ values: [
950
+ {
951
+ value: "low",
952
+ displayName: "Low"
953
+ },
954
+ {
955
+ value: "medium",
956
+ displayName: "Medium"
957
+ },
958
+ {
959
+ value: "high",
960
+ displayName: "High"
961
+ },
962
+ {
963
+ value: "xhigh",
964
+ displayName: "Extra High"
965
+ },
966
+ {
967
+ value: "max",
968
+ displayName: "Max"
969
+ }
970
+ ]
971
+ }
972
+ ],
973
+ variants: [
974
+ {
975
+ params: [
976
+ {
977
+ id: "thinking",
978
+ value: "false"
979
+ },
980
+ {
981
+ id: "context",
982
+ value: "300k"
983
+ },
984
+ {
985
+ id: "reasoning_effort",
986
+ value: "low"
987
+ }
988
+ ],
989
+ displayName: "Claude Haiku 5.5 Low No Thinking"
990
+ },
991
+ {
992
+ params: [
993
+ {
994
+ id: "thinking",
995
+ value: "false"
996
+ },
997
+ {
998
+ id: "context",
999
+ value: "300k"
1000
+ },
1001
+ {
1002
+ id: "reasoning_effort",
1003
+ value: "medium"
1004
+ }
1005
+ ],
1006
+ displayName: "Claude Haiku 5.5 Medium No Thinking"
1007
+ },
1008
+ {
1009
+ params: [
1010
+ {
1011
+ id: "thinking",
1012
+ value: "false"
1013
+ },
1014
+ {
1015
+ id: "context",
1016
+ value: "300k"
1017
+ },
1018
+ {
1019
+ id: "reasoning_effort",
1020
+ value: "high"
1021
+ }
1022
+ ],
1023
+ displayName: "Claude Haiku 5.5 High No Thinking"
1024
+ },
1025
+ {
1026
+ params: [
1027
+ {
1028
+ id: "thinking",
1029
+ value: "false"
1030
+ },
1031
+ {
1032
+ id: "context",
1033
+ value: "300k"
1034
+ },
1035
+ {
1036
+ id: "reasoning_effort",
1037
+ value: "xhigh"
1038
+ }
1039
+ ],
1040
+ displayName: "Claude Haiku 5.5 Extra High No Thinking"
1041
+ },
1042
+ {
1043
+ params: [
1044
+ {
1045
+ id: "thinking",
1046
+ value: "false"
1047
+ },
1048
+ {
1049
+ id: "context",
1050
+ value: "300k"
1051
+ },
1052
+ {
1053
+ id: "reasoning_effort",
1054
+ value: "max"
1055
+ }
1056
+ ],
1057
+ displayName: "Claude Haiku 5.5 Max No Thinking"
1058
+ },
1059
+ {
1060
+ params: [
1061
+ {
1062
+ id: "thinking",
1063
+ value: "false"
1064
+ },
1065
+ {
1066
+ id: "context",
1067
+ value: "1m"
1068
+ },
1069
+ {
1070
+ id: "reasoning_effort",
1071
+ value: "low"
1072
+ }
1073
+ ],
1074
+ displayName: "Claude Haiku 5.5 1M Low No Thinking"
1075
+ },
1076
+ {
1077
+ params: [
1078
+ {
1079
+ id: "thinking",
1080
+ value: "false"
1081
+ },
1082
+ {
1083
+ id: "context",
1084
+ value: "1m"
1085
+ },
1086
+ {
1087
+ id: "reasoning_effort",
1088
+ value: "medium"
1089
+ }
1090
+ ],
1091
+ displayName: "Claude Haiku 5.5 1M Medium No Thinking"
1092
+ },
1093
+ {
1094
+ params: [
1095
+ {
1096
+ id: "thinking",
1097
+ value: "false"
1098
+ },
1099
+ {
1100
+ id: "context",
1101
+ value: "1m"
1102
+ },
1103
+ {
1104
+ id: "reasoning_effort",
1105
+ value: "high"
1106
+ }
1107
+ ],
1108
+ displayName: "Claude Haiku 5.5 1M High No Thinking"
1109
+ },
1110
+ {
1111
+ params: [
1112
+ {
1113
+ id: "thinking",
1114
+ value: "false"
1115
+ },
1116
+ {
1117
+ id: "context",
1118
+ value: "1m"
1119
+ },
1120
+ {
1121
+ id: "reasoning_effort",
1122
+ value: "xhigh"
1123
+ }
1124
+ ],
1125
+ displayName: "Claude Haiku 5.5 1M Extra High No Thinking"
1126
+ },
1127
+ {
1128
+ params: [
1129
+ {
1130
+ id: "thinking",
1131
+ value: "false"
1132
+ },
1133
+ {
1134
+ id: "context",
1135
+ value: "1m"
1136
+ },
1137
+ {
1138
+ id: "reasoning_effort",
1139
+ value: "max"
1140
+ }
1141
+ ],
1142
+ displayName: "Claude Haiku 5.5 1M Max No Thinking"
1143
+ },
1144
+ {
1145
+ params: [
1146
+ {
1147
+ id: "thinking",
1148
+ value: "true"
1149
+ },
1150
+ {
1151
+ id: "context",
1152
+ value: "300k"
1153
+ },
1154
+ {
1155
+ id: "reasoning_effort",
1156
+ value: "low"
1157
+ }
1158
+ ],
1159
+ displayName: "Claude Haiku 5.5 Low"
1160
+ },
1161
+ {
1162
+ params: [
1163
+ {
1164
+ id: "thinking",
1165
+ value: "true"
1166
+ },
1167
+ {
1168
+ id: "context",
1169
+ value: "300k"
1170
+ },
1171
+ {
1172
+ id: "reasoning_effort",
1173
+ value: "medium"
1174
+ }
1175
+ ],
1176
+ displayName: "Claude Haiku 5.5 Medium"
1177
+ },
1178
+ {
1179
+ params: [
1180
+ {
1181
+ id: "thinking",
1182
+ value: "true"
1183
+ },
1184
+ {
1185
+ id: "context",
1186
+ value: "300k"
1187
+ },
1188
+ {
1189
+ id: "reasoning_effort",
1190
+ value: "high"
1191
+ }
1192
+ ],
1193
+ displayName: "Claude Haiku 5.5 High"
1194
+ },
1195
+ {
1196
+ params: [
1197
+ {
1198
+ id: "thinking",
1199
+ value: "true"
1200
+ },
1201
+ {
1202
+ id: "context",
1203
+ value: "300k"
1204
+ },
1205
+ {
1206
+ id: "reasoning_effort",
1207
+ value: "xhigh"
1208
+ }
1209
+ ],
1210
+ displayName: "Claude Haiku 5.5 Extra High"
1211
+ },
1212
+ {
1213
+ params: [
1214
+ {
1215
+ id: "thinking",
1216
+ value: "true"
1217
+ },
1218
+ {
1219
+ id: "context",
1220
+ value: "300k"
1221
+ },
1222
+ {
1223
+ id: "reasoning_effort",
1224
+ value: "max"
1225
+ }
1226
+ ],
1227
+ displayName: "Claude Haiku 5.5 Max"
1228
+ },
1229
+ {
1230
+ params: [
1231
+ {
1232
+ id: "thinking",
1233
+ value: "true"
1234
+ },
1235
+ {
1236
+ id: "context",
1237
+ value: "1m"
1238
+ },
1239
+ {
1240
+ id: "reasoning_effort",
1241
+ value: "low"
1242
+ }
1243
+ ],
1244
+ displayName: "Claude Haiku 5.5 1M Low"
1245
+ },
1246
+ {
1247
+ params: [
1248
+ {
1249
+ id: "thinking",
1250
+ value: "true"
1251
+ },
1252
+ {
1253
+ id: "context",
1254
+ value: "1m"
1255
+ },
1256
+ {
1257
+ id: "reasoning_effort",
1258
+ value: "medium"
1259
+ }
1260
+ ],
1261
+ displayName: "Claude Haiku 5.5 1M Medium"
1262
+ },
1263
+ {
1264
+ params: [
1265
+ {
1266
+ id: "thinking",
1267
+ value: "true"
1268
+ },
1269
+ {
1270
+ id: "context",
1271
+ value: "1m"
1272
+ },
1273
+ {
1274
+ id: "reasoning_effort",
1275
+ value: "high"
1276
+ }
1277
+ ],
1278
+ displayName: "Claude Haiku 5.5 1M High",
1279
+ isDefault: true
1280
+ },
1281
+ {
1282
+ params: [
1283
+ {
1284
+ id: "thinking",
1285
+ value: "true"
1286
+ },
1287
+ {
1288
+ id: "context",
1289
+ value: "1m"
1290
+ },
1291
+ {
1292
+ id: "reasoning_effort",
1293
+ value: "xhigh"
1294
+ }
1295
+ ],
1296
+ displayName: "Claude Haiku 5.5 1M Extra High"
1297
+ },
1298
+ {
1299
+ params: [
1300
+ {
1301
+ id: "thinking",
1302
+ value: "true"
1303
+ },
1304
+ {
1305
+ id: "context",
1306
+ value: "1m"
1307
+ },
1308
+ {
1309
+ id: "reasoning_effort",
1310
+ value: "max"
1311
+ }
1312
+ ],
1313
+ displayName: "Claude Haiku 5.5 1M Max"
1314
+ }
1315
+ ]
1316
+ },
916
1317
  {
917
1318
  id: "claude-opus-4-5",
918
1319
  displayName: "Claude Opus 4.5",