pi-cursor-sdk 0.4.0 → 0.5.0

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 (125) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +65 -13
  3. package/dist/context-window-cache.js +0 -6
  4. package/dist/context.js +8 -0
  5. package/dist/cursor-cloud-lifecycle.js +122 -98
  6. package/dist/cursor-durable-fs.js +97 -3
  7. package/dist/cursor-fallback-models.generated.js +288 -1
  8. package/dist/cursor-fallback-warning.js +2 -2
  9. package/dist/cursor-http1.js +8 -8
  10. package/dist/cursor-live-run-coordinator.js +9 -13
  11. package/dist/cursor-native-replay-routing.js +1 -1
  12. package/dist/cursor-native-tool-display-registration.js +46 -22
  13. package/dist/cursor-native-tool-display-state.js +57 -22
  14. package/dist/cursor-native-tool-display-tools.js +5 -6
  15. package/dist/cursor-pi-tool-bridge-constants.js +23 -2
  16. package/dist/cursor-pi-tool-bridge-run.js +7 -3
  17. package/dist/cursor-pi-tool-bridge-snapshot.js +1 -1
  18. package/dist/cursor-pi-tool-bridge.js +31 -9
  19. package/dist/cursor-provider-binding.js +58 -0
  20. package/dist/cursor-provider-errors.js +28 -7
  21. package/dist/cursor-provider-lazy.js +23 -11
  22. package/dist/cursor-provider-live-run-drain.js +15 -12
  23. package/dist/cursor-provider-run-finalizer.js +19 -8
  24. package/dist/cursor-provider-turn-coordinator.js +1 -0
  25. package/dist/cursor-provider-turn-display-router.js +4 -0
  26. package/dist/cursor-provider-turn-emit.js +1 -0
  27. package/dist/cursor-provider-turn-finalize.js +29 -20
  28. package/dist/cursor-provider-turn-prepare.js +24 -11
  29. package/dist/cursor-provider-turn-runner.js +37 -11
  30. package/dist/cursor-provider-turn-send.js +22 -9
  31. package/dist/cursor-provider-turn-summary.js +89 -0
  32. package/dist/cursor-provider.js +9 -3
  33. package/dist/cursor-request-provenance.js +42 -0
  34. package/dist/cursor-ripgrep-path.js +14 -3
  35. package/dist/cursor-runtime-state.js +50 -43
  36. package/dist/cursor-sdk-billed-usage.js +54 -75
  37. package/dist/cursor-sdk-event-debug-session.js +5 -6
  38. package/dist/cursor-sdk-event-debug.js +9 -6
  39. package/dist/cursor-sdk-process-error-guard.js +8 -7
  40. package/dist/cursor-sdk-runtime.js +13 -0
  41. package/dist/cursor-session-agent-cleanup.js +2 -2
  42. package/dist/cursor-session-agent-lifecycle.js +18 -9
  43. package/dist/cursor-session-agent-lineage.js +28 -12
  44. package/dist/cursor-session-agent-resume.js +51 -35
  45. package/dist/cursor-session-agent.js +9 -9
  46. package/dist/cursor-session-compaction-prep.js +2 -7
  47. package/dist/cursor-session-scope.js +71 -39
  48. package/dist/cursor-session-settings.js +61 -0
  49. package/dist/cursor-skill-tool.js +32 -49
  50. package/dist/cursor-state.js +72 -62
  51. package/dist/cursor-usage-accounting.js +13 -70
  52. package/dist/cursor-usage-command.js +89 -0
  53. package/dist/cursor-usage-ledger.js +512 -0
  54. package/dist/index.js +11 -19
  55. package/dist/model-discovery.js +11 -19
  56. package/docs/cursor-dogfood-checklist.md +3 -3
  57. package/docs/cursor-live-smoke-checklist.md +15 -15
  58. package/docs/cursor-model-ux-spec.md +59 -18
  59. package/docs/cursor-native-tool-replay.md +5 -3
  60. package/docs/cursor-native-tool-visual-audit.md +8 -8
  61. package/docs/cursor-testing-lessons.md +47 -23
  62. package/docs/cursor-tool-surfaces.md +1 -1
  63. package/docs/platform-smoke-implementation.md +10 -6
  64. package/docs/platform-smoke.md +35 -46
  65. package/package.json +6 -6
  66. package/scripts/cloud-runtime-smoke.mjs +4 -2
  67. package/scripts/local-resume-smoke.mjs +1 -1
  68. package/scripts/platform-smoke/card-detect.mjs +2 -8
  69. package/scripts/platform-smoke/targets.mjs +8 -15
  70. package/scripts/platform-smoke/visual-evidence.mjs +7 -2
  71. package/scripts/tmux-live-smoke.sh +57 -90
  72. package/src/context-window-cache.ts +0 -6
  73. package/src/context.ts +8 -0
  74. package/src/cursor-cloud-lifecycle.ts +124 -98
  75. package/src/cursor-durable-fs.ts +65 -3
  76. package/src/cursor-fallback-models.generated.ts +288 -1
  77. package/src/cursor-fallback-warning.ts +2 -2
  78. package/src/cursor-http1.ts +8 -8
  79. package/src/cursor-live-run-coordinator.ts +12 -13
  80. package/src/cursor-native-replay-routing.ts +2 -1
  81. package/src/cursor-native-tool-display-registration.ts +48 -24
  82. package/src/cursor-native-tool-display-state.ts +65 -21
  83. package/src/cursor-native-tool-display-tools.ts +7 -4
  84. package/src/cursor-pi-tool-bridge-constants.ts +27 -2
  85. package/src/cursor-pi-tool-bridge-run.ts +11 -3
  86. package/src/cursor-pi-tool-bridge-snapshot.ts +1 -1
  87. package/src/cursor-pi-tool-bridge.ts +26 -9
  88. package/src/cursor-provider-binding.ts +62 -0
  89. package/src/cursor-provider-errors.ts +27 -7
  90. package/src/cursor-provider-lazy.ts +21 -15
  91. package/src/cursor-provider-live-run-drain.ts +20 -13
  92. package/src/cursor-provider-run-finalizer.ts +24 -15
  93. package/src/cursor-provider-turn-coordinator.ts +2 -0
  94. package/src/cursor-provider-turn-display-router.ts +5 -0
  95. package/src/cursor-provider-turn-emit.ts +3 -1
  96. package/src/cursor-provider-turn-finalize.ts +38 -23
  97. package/src/cursor-provider-turn-prepare.ts +23 -14
  98. package/src/cursor-provider-turn-runner.ts +40 -13
  99. package/src/cursor-provider-turn-send.ts +23 -15
  100. package/src/cursor-provider-turn-summary.ts +94 -0
  101. package/src/cursor-provider-turn-types.ts +37 -4
  102. package/src/cursor-provider.ts +25 -3
  103. package/src/cursor-request-provenance.ts +64 -0
  104. package/src/cursor-ripgrep-path.ts +15 -5
  105. package/src/cursor-runtime-state.ts +53 -48
  106. package/src/cursor-sdk-billed-usage.ts +54 -102
  107. package/src/cursor-sdk-event-debug-session.ts +5 -5
  108. package/src/cursor-sdk-event-debug.ts +10 -6
  109. package/src/cursor-sdk-process-error-guard.ts +7 -7
  110. package/src/cursor-sdk-runtime.ts +14 -0
  111. package/src/cursor-session-agent-cleanup.ts +2 -2
  112. package/src/cursor-session-agent-lifecycle.ts +14 -9
  113. package/src/cursor-session-agent-lineage.ts +26 -12
  114. package/src/cursor-session-agent-resume.ts +49 -36
  115. package/src/cursor-session-agent.ts +13 -10
  116. package/src/cursor-session-compaction-prep.ts +2 -7
  117. package/src/cursor-session-scope.ts +87 -39
  118. package/src/cursor-session-settings.ts +72 -0
  119. package/src/cursor-skill-tool.ts +37 -61
  120. package/src/cursor-state.ts +74 -67
  121. package/src/cursor-usage-accounting.ts +17 -82
  122. package/src/cursor-usage-command.ts +76 -0
  123. package/src/cursor-usage-ledger.ts +500 -0
  124. package/src/index.ts +14 -23
  125. package/src/model-discovery.ts +14 -22
@@ -35,6 +35,10 @@ trap cleanup EXIT
35
35
  print_help() {
36
36
  printf '%s\n' 'Partial live smoke runner for pi-cursor-sdk (subset of docs/cursor-live-smoke-checklist.md).
37
37
 
38
+ Use offline checks and retained evidence first. This multi-check helper is optional;
39
+ prefer one meaningful changed-behavior check on a representative environment.
40
+ Every direct prompt is a single attempt; no automatic paid retries.
41
+
38
42
  Usage:
39
43
  ./scripts/tmux-live-smoke.sh
40
44
  SMOKE_DIR=/tmp/pi-cursor-smoke ./scripts/tmux-live-smoke.sh
@@ -51,7 +55,7 @@ Prerequisites:
51
55
 
52
56
  Coverage:
53
57
  - prereq model listing
54
- - basic non-interactive prompt (retry-empty-output; strict output assertion)
58
+ - basic non-interactive prompt (single attempt; no automatic paid retries)
55
59
  - default ambient settings prompt (strict; no retry)
56
60
  - simple non-interactive math prompt (strict; no retry)
57
61
  - interactive TUI math/footer polling with cleanup
@@ -68,7 +72,7 @@ Not covered here:
68
72
 
69
73
  Options:
70
74
  -h, --help Show this help.
71
- --self-test Run sealed PATH/env probes without live Cursor auth.
75
+ --self-test Run sealed PATH/env and single-attempt probes without live Cursor auth.
72
76
 
73
77
  Exit codes:
74
78
  0 all partial checks passed
@@ -110,103 +114,27 @@ assert_file_contains() {
110
114
  fi
111
115
  }
112
116
 
113
- is_empty_retryable_exit() {
114
- local code="$1"
115
- local stdout="$2"
116
- [[ ! -s "$stdout" && ( "$code" == "0" || "$code" == "124" || "$code" == "137" || "$code" == "143" ) ]]
117
- }
118
-
119
- run_direct_attempt() {
120
- local name="$1"
121
- local timeout_secs="$2"
122
- local stdout="$3"
123
- local stderr="$4"
124
- shift 4
125
- rm -f "$stdout" "$stderr"
126
-
127
- if run_with_timeout "$timeout_secs" "$@" </dev/null >"$stdout" 2>"$stderr"; then
128
- return 0
129
- fi
130
- return $?
131
- }
132
-
133
- run_direct_fail() {
134
- local name="$1"
135
- local code="$2"
136
- local stdout="$3"
137
- local stderr="$4"
138
- local label="$5"
139
- if [[ "$code" != "0" ]]; then
140
- cat "$stderr" >&2 || true
141
- fail "$name exited $code"
142
- fi
143
- printf '[smoke] %s missing %s in %s\n' "$name" "$label" "$stdout" >&2
144
- printf '[smoke] %s stdout tail:\n' "$name" >&2
145
- tail_file "$stdout" 120 >&2
146
- printf '[smoke] %s stderr tail:\n' "$name" >&2
147
- tail_file "$stderr" 80 >&2
148
- fail "$name missing ${label}"
149
- }
150
-
151
117
  run_direct() {
152
118
  local name="$1"
153
119
  local timeout_secs="$2"
154
- local policy="$3"
155
- local expected_pattern="$4"
156
- local expected_label="$5"
157
- shift 5
120
+ local expected_pattern="$3"
121
+ local expected_label="$4"
122
+ shift 4
158
123
  local stdout="$SMOKE_DIR/${name}.stdout.txt"
159
124
  local stderr="$SMOKE_DIR/${name}.stderr.txt"
160
125
  local code=0
161
126
 
162
- if run_direct_attempt "$name" "$timeout_secs" "$stdout" "$stderr" "$@"; then
127
+ if run_with_timeout "$timeout_secs" "$@" </dev/null >"$stdout" 2>"$stderr"; then
163
128
  code=0
164
129
  else
165
130
  code=$?
166
131
  fi
167
- if [[ "$code" == "0" ]] && "$RG_BIN" -q "$expected_pattern" "$stdout"; then
168
- log "$name PASS"
169
- return 0
132
+ if [[ "$code" != "0" ]]; then
133
+ cat "$stderr" >&2 || true
134
+ fail "$name exited $code"
170
135
  fi
171
-
172
- case "$policy" in
173
- strict)
174
- run_direct_fail "$name" "$code" "$stdout" "$stderr" "$expected_label"
175
- ;;
176
- retry-empty-output)
177
- local first_stdout="$SMOKE_DIR/${name}.attempt1.stdout.txt"
178
- local first_stderr="$SMOKE_DIR/${name}.attempt1.stderr.txt"
179
- if ! is_empty_retryable_exit "$code" "$stdout"; then
180
- run_direct_fail "$name" "$code" "$stdout" "$stderr" "$expected_label"
181
- fi
182
- mv "$stdout" "$first_stdout" 2>/dev/null || true
183
- mv "$stderr" "$first_stderr" 2>/dev/null || true
184
- log "$name retrying once after empty output with exit $code"
185
- if run_direct_attempt "$name" "$timeout_secs" "$stdout" "$stderr" "$@"; then
186
- local retry_code=0
187
- if "$RG_BIN" -q "$expected_pattern" "$stdout"; then
188
- log "$name PASS after retry (first exit $code; first stderr: $first_stderr)"
189
- return 0
190
- fi
191
- printf '[smoke] %s retry exited %s but still missed %s\n' "$name" "$retry_code" "$expected_label" >&2
192
- else
193
- local retry_code=$?
194
- printf '[smoke] %s retry exited %s after first empty output exit %s\n' "$name" "$retry_code" "$code" >&2
195
- fi
196
- printf '[smoke] %s first stdout tail:\n' "$name" >&2
197
- tail_file "$first_stdout" 80 >&2
198
- printf '[smoke] %s first stderr tail:\n' "$name" >&2
199
- tail_file "$first_stderr" 80 >&2
200
- printf '[smoke] %s retry stdout tail:\n' "$name" >&2
201
- tail_file "$stdout" 120 >&2
202
- printf '[smoke] %s retry stderr tail:\n' "$name" >&2
203
- tail_file "$stderr" 80 >&2
204
- fail "$name retry failed after empty output"
205
- ;;
206
- *)
207
- fail "$name unknown run_direct policy: $policy (expected strict or retry-empty-output)"
208
- ;;
209
- esac
136
+ assert_file_contains "$name" "$stdout" "$expected_pattern" "$expected_label"
137
+ log "$name PASS"
210
138
  }
211
139
 
212
140
  quote_command() {
@@ -401,6 +329,45 @@ EOF_FAKE_LIST
401
329
  fail "self-test failed: large catalog was truncated before search"
402
330
  fi
403
331
 
332
+ # Exercise the real single-attempt path using an offline counting command.
333
+ local fake_direct="$bin_dir/direct" case_name exit_code output result
334
+ cat >"$fake_direct" <<'EOF_FAKE_DIRECT'
335
+ #!/usr/bin/env bash
336
+ printf 'called\n' >> "$1"
337
+ printf 'retained stderr\n' >&2
338
+ printf '%s' "$3"
339
+ exit "$2"
340
+ EOF_FAKE_DIRECT
341
+ chmod +x "$fake_direct"
342
+ for case_name in empty nonzero success; do
343
+ exit_code=0
344
+ output=""
345
+ [[ "$case_name" != "nonzero" ]] || exit_code=42
346
+ [[ "$case_name" == "empty" ]] || output="DIRECT_OK"
347
+ if ( SMOKE_DIR="$temp_dir" run_direct "$case_name" 10 DIRECT_OK DIRECT_OK "$fake_direct" "$temp_dir/$case_name.count" "$exit_code" "$output" ) >"$temp_dir/$case_name.result" 2>&1; then
348
+ result=0
349
+ else
350
+ result=$?
351
+ fi
352
+ [[ "$(wc -l <"$temp_dir/$case_name.count" | tr -d ' ')" == "1" ]] || fail "self-test failed: $case_name repeated the command"
353
+ [[ -f "$temp_dir/$case_name.stdout.txt" ]] || fail "self-test failed: $case_name lost stdout artifact"
354
+ grep -qx 'retained stderr' "$temp_dir/$case_name.stderr.txt" || fail "self-test failed: $case_name lost stderr artifact"
355
+ case "$case_name" in
356
+ empty)
357
+ [[ "$result" == "1" && ! -s "$temp_dir/$case_name.stdout.txt" ]] || fail "self-test failed: empty output did not fail"
358
+ grep -q 'missing DIRECT_OK' "$temp_dir/$case_name.result" || fail "self-test failed: empty output lost marker failure"
359
+ ;;
360
+ nonzero)
361
+ [[ "$result" == "1" ]] || fail "self-test failed: nonzero command did not fail"
362
+ grep -q 'exited 42' "$temp_dir/$case_name.result" || fail "self-test failed: command exit code was lost"
363
+ ;;
364
+ success)
365
+ [[ "$result" == "0" ]] || fail "self-test failed: valid output did not pass"
366
+ ;;
367
+ esac
368
+ [[ "$case_name" == "empty" ]] || grep -qx DIRECT_OK "$temp_dir/$case_name.stdout.txt" || fail "self-test failed: $case_name lost output"
369
+ done
370
+
404
371
  printf '[smoke] self-test PASS\n'
405
372
  }
406
373
 
@@ -451,19 +418,19 @@ log "partial live smoke: prereq, basic, default-settings, noninteractive-math, t
451
418
  capture_and_require_default_model "${NONE_ENV[@]}" "${PI_BASE[@]}" --list-models cursor
452
419
  log "prereq PASS"
453
420
 
454
- run_direct basic 600 retry-empty-output "PI_CURSOR_SMOKE_OK" "PI_CURSOR_SMOKE_OK" \
421
+ run_direct basic 600 "PI_CURSOR_SMOKE_OK" "PI_CURSOR_SMOKE_OK" \
455
422
  "${NONE_ENV[@]}" "${PI_BASE[@]}" \
456
423
  --session-dir "$SMOKE_DIR/basic" \
457
424
  --no-tools \
458
425
  -p 'Live smoke. Reply exactly: PI_CURSOR_SMOKE_OK'
459
426
 
460
- run_direct default-settings 300 strict "PRODUCT=42" "PRODUCT=42" \
427
+ run_direct default-settings 300 "PRODUCT=42" "PRODUCT=42" \
461
428
  "${DEFAULT_ENV[@]}" "${PI_BASE[@]}" \
462
429
  --session-dir "$SMOKE_DIR/default-settings" \
463
430
  --no-tools \
464
431
  -p 'Default settings smoke. Include PRODUCT=42 in the final answer.'
465
432
 
466
- run_direct noninteractive-math 300 strict "SUM=42" "SUM=42" \
433
+ run_direct noninteractive-math 300 "SUM=42" "SUM=42" \
467
434
  "${NONE_ENV[@]}" "${PI_BASE[@]}" \
468
435
  --session-dir "$SMOKE_DIR/noninteractive-math" \
469
436
  --no-tools \
@@ -5,7 +5,6 @@ import { BUNDLED_CONTEXT_WINDOWS } from "./bundled-context-windows.js";
5
5
  import { asRecord } from "./cursor-record-utils.js";
6
6
 
7
7
  const CONTEXT_WINDOW_CACHE_FILE = "cursor-sdk-context-windows.json";
8
- let userContextWindowOverrideLoadCount = 0;
9
8
 
10
9
  interface ContextWindowCacheFile {
11
10
  contextWindows?: Record<string, number>;
@@ -34,7 +33,6 @@ function parseContextWindowCacheFile(value: unknown): ContextWindowCacheFile | u
34
33
  }
35
34
 
36
35
  function loadUserContextWindowOverrides(): Map<string, number> {
37
- userContextWindowOverrideLoadCount += 1;
38
36
  const path = getCachePath();
39
37
  const overrides = new Map<string, number>();
40
38
  if (!existsSync(path)) return overrides;
@@ -94,8 +92,4 @@ export function saveCachedContextWindow(modelId: string, contextWindow: number):
94
92
 
95
93
  export const __testUtils = {
96
94
  getCachePath,
97
- getUserContextWindowOverrideLoadCount: () => userContextWindowOverrideLoadCount,
98
- resetUserContextWindowOverrideLoadCount: () => {
99
- userContextWindowOverrideLoadCount = 0;
100
- },
101
95
  };
package/src/context.ts CHANGED
@@ -427,6 +427,14 @@ export function buildCursorIncrementalPrompt(context: Context, options: CursorPr
427
427
  return { text: parts.join(SECTION_SEPARATOR), images };
428
428
  }
429
429
 
430
+ /** Native compaction/tree instructions are already a complete summarization request. */
431
+ export function buildCursorSummaryPrompt(context: Context): CursorPrompt {
432
+ const { systemPrompt } = resolveCursorPiContext(context);
433
+ const sections = normalizePiContextMessages(context.messages).map(formatMessage).filter((text): text is string => text !== undefined);
434
+ if (systemPrompt) sections.unshift(`System instructions from pi:\n${systemPrompt}`);
435
+ return { text: sections.join(SECTION_SEPARATOR), images: [] };
436
+ }
437
+
430
438
  export function buildCursorPrompt(context: Context, options: CursorPromptOptions = {}): CursorPrompt {
431
439
  const sectionsBeforeMessages: string[] = [getCursorToolBoundaryText({
432
440
  agentMode: options.agentMode,