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.
- package/CHANGELOG.md +30 -0
- package/README.md +65 -13
- package/dist/context-window-cache.js +0 -6
- package/dist/context.js +8 -0
- package/dist/cursor-cloud-lifecycle.js +122 -98
- package/dist/cursor-durable-fs.js +97 -3
- package/dist/cursor-fallback-models.generated.js +288 -1
- package/dist/cursor-fallback-warning.js +2 -2
- package/dist/cursor-http1.js +8 -8
- package/dist/cursor-live-run-coordinator.js +9 -13
- package/dist/cursor-native-replay-routing.js +1 -1
- package/dist/cursor-native-tool-display-registration.js +46 -22
- package/dist/cursor-native-tool-display-state.js +57 -22
- package/dist/cursor-native-tool-display-tools.js +5 -6
- package/dist/cursor-pi-tool-bridge-constants.js +23 -2
- package/dist/cursor-pi-tool-bridge-run.js +7 -3
- package/dist/cursor-pi-tool-bridge-snapshot.js +1 -1
- package/dist/cursor-pi-tool-bridge.js +31 -9
- package/dist/cursor-provider-binding.js +58 -0
- package/dist/cursor-provider-errors.js +28 -7
- package/dist/cursor-provider-lazy.js +23 -11
- package/dist/cursor-provider-live-run-drain.js +15 -12
- package/dist/cursor-provider-run-finalizer.js +19 -8
- package/dist/cursor-provider-turn-coordinator.js +1 -0
- package/dist/cursor-provider-turn-display-router.js +4 -0
- package/dist/cursor-provider-turn-emit.js +1 -0
- package/dist/cursor-provider-turn-finalize.js +29 -20
- package/dist/cursor-provider-turn-prepare.js +24 -11
- package/dist/cursor-provider-turn-runner.js +37 -11
- package/dist/cursor-provider-turn-send.js +22 -9
- package/dist/cursor-provider-turn-summary.js +89 -0
- package/dist/cursor-provider.js +9 -3
- package/dist/cursor-request-provenance.js +42 -0
- package/dist/cursor-ripgrep-path.js +14 -3
- package/dist/cursor-runtime-state.js +50 -43
- package/dist/cursor-sdk-billed-usage.js +54 -75
- package/dist/cursor-sdk-event-debug-session.js +5 -6
- package/dist/cursor-sdk-event-debug.js +9 -6
- package/dist/cursor-sdk-process-error-guard.js +8 -7
- package/dist/cursor-sdk-runtime.js +13 -0
- package/dist/cursor-session-agent-cleanup.js +2 -2
- package/dist/cursor-session-agent-lifecycle.js +18 -9
- package/dist/cursor-session-agent-lineage.js +28 -12
- package/dist/cursor-session-agent-resume.js +51 -35
- package/dist/cursor-session-agent.js +9 -9
- package/dist/cursor-session-compaction-prep.js +2 -7
- package/dist/cursor-session-scope.js +71 -39
- package/dist/cursor-session-settings.js +61 -0
- package/dist/cursor-skill-tool.js +32 -49
- package/dist/cursor-state.js +72 -62
- package/dist/cursor-usage-accounting.js +13 -70
- package/dist/cursor-usage-command.js +89 -0
- package/dist/cursor-usage-ledger.js +512 -0
- package/dist/index.js +11 -19
- package/dist/model-discovery.js +11 -19
- package/docs/cursor-dogfood-checklist.md +3 -3
- package/docs/cursor-live-smoke-checklist.md +15 -15
- package/docs/cursor-model-ux-spec.md +59 -18
- package/docs/cursor-native-tool-replay.md +5 -3
- package/docs/cursor-native-tool-visual-audit.md +8 -8
- package/docs/cursor-testing-lessons.md +47 -23
- package/docs/cursor-tool-surfaces.md +1 -1
- package/docs/platform-smoke-implementation.md +10 -6
- package/docs/platform-smoke.md +35 -46
- package/package.json +6 -6
- package/scripts/cloud-runtime-smoke.mjs +4 -2
- package/scripts/local-resume-smoke.mjs +1 -1
- package/scripts/platform-smoke/card-detect.mjs +2 -8
- package/scripts/platform-smoke/targets.mjs +8 -15
- package/scripts/platform-smoke/visual-evidence.mjs +7 -2
- package/scripts/tmux-live-smoke.sh +57 -90
- package/src/context-window-cache.ts +0 -6
- package/src/context.ts +8 -0
- package/src/cursor-cloud-lifecycle.ts +124 -98
- package/src/cursor-durable-fs.ts +65 -3
- package/src/cursor-fallback-models.generated.ts +288 -1
- package/src/cursor-fallback-warning.ts +2 -2
- package/src/cursor-http1.ts +8 -8
- package/src/cursor-live-run-coordinator.ts +12 -13
- package/src/cursor-native-replay-routing.ts +2 -1
- package/src/cursor-native-tool-display-registration.ts +48 -24
- package/src/cursor-native-tool-display-state.ts +65 -21
- package/src/cursor-native-tool-display-tools.ts +7 -4
- package/src/cursor-pi-tool-bridge-constants.ts +27 -2
- package/src/cursor-pi-tool-bridge-run.ts +11 -3
- package/src/cursor-pi-tool-bridge-snapshot.ts +1 -1
- package/src/cursor-pi-tool-bridge.ts +26 -9
- package/src/cursor-provider-binding.ts +62 -0
- package/src/cursor-provider-errors.ts +27 -7
- package/src/cursor-provider-lazy.ts +21 -15
- package/src/cursor-provider-live-run-drain.ts +20 -13
- package/src/cursor-provider-run-finalizer.ts +24 -15
- package/src/cursor-provider-turn-coordinator.ts +2 -0
- package/src/cursor-provider-turn-display-router.ts +5 -0
- package/src/cursor-provider-turn-emit.ts +3 -1
- package/src/cursor-provider-turn-finalize.ts +38 -23
- package/src/cursor-provider-turn-prepare.ts +23 -14
- package/src/cursor-provider-turn-runner.ts +40 -13
- package/src/cursor-provider-turn-send.ts +23 -15
- package/src/cursor-provider-turn-summary.ts +94 -0
- package/src/cursor-provider-turn-types.ts +37 -4
- package/src/cursor-provider.ts +25 -3
- package/src/cursor-request-provenance.ts +64 -0
- package/src/cursor-ripgrep-path.ts +15 -5
- package/src/cursor-runtime-state.ts +53 -48
- package/src/cursor-sdk-billed-usage.ts +54 -102
- package/src/cursor-sdk-event-debug-session.ts +5 -5
- package/src/cursor-sdk-event-debug.ts +10 -6
- package/src/cursor-sdk-process-error-guard.ts +7 -7
- package/src/cursor-sdk-runtime.ts +14 -0
- package/src/cursor-session-agent-cleanup.ts +2 -2
- package/src/cursor-session-agent-lifecycle.ts +14 -9
- package/src/cursor-session-agent-lineage.ts +26 -12
- package/src/cursor-session-agent-resume.ts +49 -36
- package/src/cursor-session-agent.ts +13 -10
- package/src/cursor-session-compaction-prep.ts +2 -7
- package/src/cursor-session-scope.ts +87 -39
- package/src/cursor-session-settings.ts +72 -0
- package/src/cursor-skill-tool.ts +37 -61
- package/src/cursor-state.ts +74 -67
- package/src/cursor-usage-accounting.ts +17 -82
- package/src/cursor-usage-command.ts +76 -0
- package/src/cursor-usage-ledger.ts +500 -0
- package/src/index.ts +14 -23
- 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 (
|
|
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
|
|
155
|
-
local
|
|
156
|
-
|
|
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
|
|
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"
|
|
168
|
-
|
|
169
|
-
|
|
132
|
+
if [[ "$code" != "0" ]]; then
|
|
133
|
+
cat "$stderr" >&2 || true
|
|
134
|
+
fail "$name exited $code"
|
|
170
135
|
fi
|
|
171
|
-
|
|
172
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|