pi-cursor-sdk 0.2.0 → 0.3.7
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 +73 -0
- package/README.md +55 -51
- package/dist/bundled-context-windows.js +39 -0
- package/dist/context-window-cache.js +92 -0
- package/dist/context.js +353 -0
- package/dist/cursor-active-tools.js +3 -0
- package/dist/cursor-agent-message-web-tools.js +165 -0
- package/dist/cursor-agents-context-registration.js +17 -0
- package/dist/cursor-agents-context.js +127 -0
- package/dist/cursor-api-key.js +34 -0
- package/dist/cursor-bridge-contract.js +27 -0
- package/dist/cursor-cloud-lifecycle.js +650 -0
- package/dist/cursor-cloud-local-state.js +460 -0
- package/dist/cursor-cloud-options.js +145 -0
- package/dist/cursor-cloud-reporting.js +222 -0
- package/dist/cursor-compact-tool-summary.js +75 -0
- package/dist/cursor-config.js +613 -0
- package/dist/cursor-context-tools.js +6 -0
- package/dist/cursor-display-only-trace.js +11 -0
- package/dist/cursor-display-text.js +18 -0
- package/dist/cursor-durable-fs.js +53 -0
- package/dist/cursor-edit-diff.js +13 -0
- package/dist/cursor-env-boolean.js +19 -0
- package/dist/cursor-fallback-models.generated.js +7760 -0
- package/dist/cursor-fallback-warning.js +15 -0
- package/dist/cursor-http1.js +45 -0
- package/dist/cursor-incomplete-tool-visibility.js +83 -0
- package/dist/cursor-live-run-accounting.js +55 -0
- package/dist/cursor-live-run-coordinator.js +409 -0
- package/dist/cursor-mcp-timeout-override.js +116 -0
- package/dist/cursor-model-lifecycle.js +32 -0
- package/dist/cursor-model.js +5 -0
- package/dist/cursor-native-replay-routing.js +35 -0
- package/dist/cursor-native-replay-trace.js +28 -0
- package/dist/cursor-native-tool-display-registration.js +102 -0
- package/dist/cursor-native-tool-display-replay.js +428 -0
- package/dist/cursor-native-tool-display-state.js +70 -0
- package/dist/cursor-native-tool-display-tools.js +123 -0
- package/dist/cursor-native-tool-names.js +11 -0
- package/dist/cursor-partial-content-emitter.js +130 -0
- package/dist/cursor-pi-context.js +30 -0
- package/dist/cursor-pi-tool-bridge-abort.js +114 -0
- package/dist/cursor-pi-tool-bridge-constants.js +6 -0
- package/dist/cursor-pi-tool-bridge-diagnostics.js +125 -0
- package/dist/cursor-pi-tool-bridge-env.js +18 -0
- package/dist/cursor-pi-tool-bridge-mcp.js +100 -0
- package/dist/cursor-pi-tool-bridge-run.js +355 -0
- package/dist/cursor-pi-tool-bridge-server.js +163 -0
- package/dist/cursor-pi-tool-bridge-snapshot.js +63 -0
- package/dist/cursor-pi-tool-bridge-types.js +1 -0
- package/dist/cursor-pi-tool-bridge.js +123 -0
- package/dist/cursor-provider-errors.js +311 -0
- package/dist/cursor-provider-lazy.js +39 -0
- package/dist/cursor-provider-live-run-drain.js +420 -0
- package/dist/cursor-provider-overflow.js +90 -0
- package/dist/cursor-provider-run-finalizer.js +176 -0
- package/dist/cursor-provider-run-outcome.js +76 -0
- package/dist/cursor-provider-turn-coordinator.js +293 -0
- package/dist/cursor-provider-turn-display-router.js +158 -0
- package/dist/cursor-provider-turn-emit.js +41 -0
- package/dist/cursor-provider-turn-finalize.js +154 -0
- package/dist/cursor-provider-turn-lifecycle-emitter.js +126 -0
- package/dist/cursor-provider-turn-prepare.js +379 -0
- package/dist/cursor-provider-turn-runner.js +146 -0
- package/dist/cursor-provider-turn-sdk-normalizer.js +74 -0
- package/dist/cursor-provider-turn-send.js +138 -0
- package/dist/cursor-provider-turn-shell-output.js +117 -0
- package/dist/cursor-provider-turn-tool-ledger.js +99 -0
- package/dist/cursor-provider-turn-types.js +1 -0
- package/dist/cursor-provider.js +72 -0
- package/dist/cursor-question-tool.js +194 -0
- package/dist/cursor-record-utils.js +61 -0
- package/dist/cursor-replay-activity-builders.js +114 -0
- package/dist/cursor-replay-source-names.js +27 -0
- package/dist/cursor-replay-summary-args.js +105 -0
- package/dist/cursor-replay-tool-details.js +167 -0
- package/dist/cursor-ripgrep-path.js +27 -0
- package/dist/cursor-run-final-text.js +63 -0
- package/dist/cursor-runtime-state.js +380 -0
- package/dist/cursor-sdk-billed-usage.js +86 -0
- package/dist/cursor-sdk-event-debug-constants.js +33 -0
- package/dist/cursor-sdk-event-debug-session.js +107 -0
- package/dist/cursor-sdk-event-debug.js +461 -0
- package/dist/cursor-sdk-output-filter.js +1 -0
- package/dist/cursor-sdk-process-error-guard.js +221 -0
- package/dist/cursor-sdk-runtime.js +3 -0
- package/dist/cursor-sensitive-text.js +23 -0
- package/dist/cursor-session-agent-cleanup.js +311 -0
- package/dist/cursor-session-agent-lifecycle.js +32 -0
- package/dist/cursor-session-agent-lineage.js +103 -0
- package/dist/cursor-session-agent-resume.js +417 -0
- package/dist/cursor-session-agent.js +507 -0
- package/dist/cursor-session-compaction-prep.js +21 -0
- package/dist/cursor-session-scope.js +113 -0
- package/dist/cursor-session-send-policy.js +18 -0
- package/dist/cursor-session-store.js +105 -0
- package/dist/cursor-session-turn-queue.js +50 -0
- package/dist/cursor-setting-sources.js +15 -0
- package/dist/cursor-skill-tool.js +230 -0
- package/dist/cursor-state.js +519 -0
- package/dist/cursor-task-presentation.js +59 -0
- package/dist/cursor-tool-lifecycle.js +94 -0
- package/dist/cursor-tool-manifest.js +34 -0
- package/dist/cursor-tool-presentation-registry.js +305 -0
- package/dist/cursor-tool-result-display-readers.js +158 -0
- package/dist/cursor-tool-transcript.js +32 -0
- package/dist/cursor-tool-visibility.js +28 -0
- package/dist/cursor-transcript-tool-formatters.js +618 -0
- package/dist/cursor-transcript-tool-specs.js +284 -0
- package/dist/cursor-transcript-utils.js +170 -0
- package/dist/cursor-usage-accounting.js +166 -0
- package/dist/cursor-web-tool-activity.js +23 -0
- package/dist/cursor-web-tool-args.js +12 -0
- package/dist/index.js +82 -0
- package/dist/model-discovery.js +305 -0
- package/dist/model-list-cache.js +156 -0
- package/docs/cursor-dogfood-checklist.md +2 -1
- package/docs/cursor-live-smoke-checklist.md +13 -12
- package/docs/cursor-model-ux-spec.md +27 -6
- package/docs/cursor-native-tool-replay.md +13 -13
- package/docs/cursor-native-tool-visual-audit.md +6 -3
- package/docs/cursor-testing-lessons.md +14 -8
- package/docs/cursor-tool-surfaces.md +5 -5
- package/docs/platform-smoke.md +3 -3
- package/package.json +19 -7
- package/platform-smoke.config.mjs +1 -1
- package/scripts/build.mjs +126 -0
- package/scripts/cloud-runtime-smoke.mjs +3 -1
- package/scripts/debug-provider-events.mjs +3 -1
- package/scripts/debug-sdk-events.mjs +1 -1
- package/scripts/isolated-cursor-smoke.sh +5 -4
- package/scripts/lib/cloud-smoke-cleanup-evidence.mjs +1 -1
- package/scripts/lib/cursor-visual-render.mjs +1 -1
- package/scripts/lib/ensure-built.mjs +16 -0
- package/scripts/lib/local-resume-smoke-harness.mjs +1 -1
- package/scripts/local-resume-smoke.mjs +3 -1
- package/scripts/platform-smoke/card-detect.mjs +1 -1
- package/scripts/platform-smoke/live-suite-runner.mjs +1 -1
- package/scripts/platform-smoke/render-ansi.mjs +1 -1
- package/scripts/platform-smoke/targets.mjs +2 -2
- package/scripts/prepare.mjs +102 -0
- package/scripts/steering-rpc-smoke.mjs +4 -2
- package/scripts/tmux-live-smoke.sh +11 -11
- package/scripts/visual-tui-smoke-self-test.mjs +4 -1
- package/scripts/visual-tui-smoke.mjs +51 -7
- package/src/bundled-context-windows.ts +4 -1
- package/src/context.ts +27 -4
- package/src/cursor-agents-context-registration.ts +2 -2
- package/src/cursor-agents-context.ts +24 -10
- package/src/cursor-api-key.ts +5 -4
- package/src/cursor-cloud-reporting.ts +23 -2
- package/src/cursor-context-tools.ts +3 -1
- package/src/cursor-fallback-models.generated.ts +592 -204
- package/src/cursor-live-run-coordinator.ts +11 -6
- package/src/cursor-native-tool-display-registration.ts +10 -11
- package/src/cursor-partial-content-emitter.ts +13 -0
- package/src/cursor-pi-context.ts +44 -0
- package/src/cursor-provider-errors.ts +1 -1
- package/src/cursor-provider-lazy.ts +5 -4
- package/src/cursor-provider-live-run-drain.ts +14 -9
- package/src/cursor-provider-run-finalizer.ts +1 -0
- package/src/cursor-provider-turn-coordinator.ts +15 -0
- package/src/cursor-provider-turn-emit.ts +6 -0
- package/src/cursor-provider-turn-finalize.ts +12 -0
- package/src/cursor-provider-turn-prepare.ts +10 -5
- package/src/cursor-provider-turn-types.ts +2 -0
- package/src/cursor-sdk-billed-usage.ts +107 -0
- package/src/cursor-sdk-process-error-guard.ts +6 -4
- package/src/cursor-session-agent-lifecycle.ts +8 -9
- package/src/cursor-session-agent-resume.ts +23 -0
- package/src/cursor-session-compaction-prep.ts +4 -0
- package/src/cursor-skill-tool.ts +1 -1
- package/src/cursor-tool-manifest.ts +1 -1
- package/src/cursor-usage-accounting.ts +70 -9
- package/src/index.ts +1 -1
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +16 -0
|
@@ -10,6 +10,7 @@ import { tmpdir } from "node:os";
|
|
|
10
10
|
import { dirname, join, resolve } from "node:path";
|
|
11
11
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
12
12
|
import { terminateChild } from "./lib/cursor-child-process.mjs";
|
|
13
|
+
import { ensureBuilt } from "./lib/ensure-built.mjs";
|
|
13
14
|
import { buildCursorSmokeEnv } from "./lib/cursor-smoke-env.mjs";
|
|
14
15
|
import {
|
|
15
16
|
checkpointCloudSmokeShutdown,
|
|
@@ -50,7 +51,7 @@ import { scrubSensitiveText } from "../shared/cursor-sensitive-text.mjs";
|
|
|
50
51
|
|
|
51
52
|
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
52
53
|
const EVIDENCE_PATH = join(root, "docs", "evidence", "cursor-cloud-smoke-matrix-latest.json");
|
|
53
|
-
const MODEL = "cursor/
|
|
54
|
+
const MODEL = "cursor/grok-4.6";
|
|
54
55
|
const CLOUD_RUN_ID_PATTERN = /^run-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
55
56
|
const cloudSmokeShutdown = createCloudSmokeShutdownController((child) => terminateChild(child, { graceMs: 15_000 }));
|
|
56
57
|
const argv = process.argv.slice(2);
|
|
@@ -614,6 +615,7 @@ async function main() {
|
|
|
614
615
|
}
|
|
615
616
|
|
|
616
617
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
618
|
+
ensureBuilt();
|
|
617
619
|
main().catch((error) => {
|
|
618
620
|
reportFailure(error);
|
|
619
621
|
process.exit(1);
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from "./lib/cursor-child-process.mjs";
|
|
24
24
|
import { scrubSensitiveText } from "../shared/cursor-sensitive-text.mjs";
|
|
25
25
|
import { createScriptFail } from "./lib/cursor-script-fail.mjs";
|
|
26
|
+
import { ensureBuilt } from "./lib/ensure-built.mjs";
|
|
26
27
|
import { serializeCursorSettingSources } from "../shared/cursor-setting-sources.mjs";
|
|
27
28
|
|
|
28
29
|
function isMainModule() {
|
|
@@ -35,7 +36,7 @@ function isMainModule() {
|
|
|
35
36
|
const require = createRequire(import.meta.url);
|
|
36
37
|
const root = fileURLToPath(new URL("..", import.meta.url));
|
|
37
38
|
const packageJson = require("../package.json");
|
|
38
|
-
const DEFAULT_MODEL = "cursor/
|
|
39
|
+
const DEFAULT_MODEL = "cursor/grok-4.6";
|
|
39
40
|
const DEFAULT_OUT_BASE = ".debug/cursor-sdk-events";
|
|
40
41
|
const SDK_EVENT_DEBUG_LOG_PREFIX = "[pi-cursor-sdk:sdk-events]";
|
|
41
42
|
const PI_SESSION_SNAPSHOT_ARTIFACT = "pi-session-snapshot.jsonl";
|
|
@@ -301,6 +302,7 @@ async function main(argv = process.argv.slice(2), env = process.env) {
|
|
|
301
302
|
printHelp();
|
|
302
303
|
return;
|
|
303
304
|
}
|
|
305
|
+
ensureBuilt();
|
|
304
306
|
console.log(JSON.stringify(await runDebugProviderEvents(args, env)));
|
|
305
307
|
}
|
|
306
308
|
|
|
@@ -39,7 +39,7 @@ const ARTIFACTS = {
|
|
|
39
39
|
summary: "summary.json",
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
const DEFAULT_MODEL = "
|
|
42
|
+
const DEFAULT_MODEL = "grok-4.6";
|
|
43
43
|
const RAW_ARTIFACT_WARNING =
|
|
44
44
|
"Raw artifact files may contain local paths, project text, tool args/results, or secrets from the workspace. Do not commit or share them.";
|
|
45
45
|
|
|
@@ -134,7 +134,7 @@ run_self_test() {
|
|
|
134
134
|
env_capture="$temp_dir/fake-pi.env"
|
|
135
135
|
cat >"$fake_pi" <<EOF_SELFTEST_PI
|
|
136
136
|
#!/usr/bin/env node
|
|
137
|
-
|
|
137
|
+
import { writeFileSync } from "node:fs";
|
|
138
138
|
writeFileSync("$env_capture", Object.entries(process.env).map(([key, value]) => key + "=" + (value ?? "")).join("\\n") + "\\n", "utf8");
|
|
139
139
|
EOF_SELFTEST_PI
|
|
140
140
|
cat >"$fake_node" <<EOF_SELFTEST_NODE
|
|
@@ -359,13 +359,14 @@ log "check: list-models"
|
|
|
359
359
|
LIST_OUT="$ISOLATED/list-models.txt"
|
|
360
360
|
run_in_dir_capture_combined "list-models" 30 "$PROJECT_DIR" "$LIST_OUT" "${PI_CURSOR_ENV[@]}" \
|
|
361
361
|
"$PI_BIN" --approve --cursor-no-fast --list-models cursor
|
|
362
|
+
"$RG_BIN" -q "grok-4\\.6" "$LIST_OUT" || fail "grok-4.6 not listed (see $LIST_OUT)"
|
|
362
363
|
"$RG_BIN" -q "composer-2\\.5|composer-2-5" "$LIST_OUT" || fail "composer-2-5 not listed (see $LIST_OUT)"
|
|
363
364
|
|
|
364
365
|
log "check: basic provider prompt"
|
|
365
366
|
BASIC_DIR="$SESSION_ROOT/basic"
|
|
366
367
|
mkdir -p "$BASIC_DIR"
|
|
367
368
|
run_in_dir_capture_split "basic prompt" "$PI_LIVE_TIMEOUT" "$PROJECT_DIR" "$ISOLATED/basic.stdout.txt" "$ISOLATED/basic.stderr.txt" "${PI_CURSOR_ENV[@]}" \
|
|
368
|
-
"$PI_BIN" --approve --cursor-no-fast --model cursor/
|
|
369
|
+
"$PI_BIN" --approve --cursor-no-fast --model cursor/grok-4.6 --session-dir "$BASIC_DIR" --no-tools -p 'Reply exactly: PI_CURSOR_ISOLATED_OK'
|
|
369
370
|
"$RG_BIN" -q "PI_CURSOR_ISOLATED_OK" "$ISOLATED/basic.stdout.txt" || fail "basic prompt missing PI_CURSOR_ISOLATED_OK"
|
|
370
371
|
validate_replay_jsonl "$BASIC_DIR"
|
|
371
372
|
|
|
@@ -373,14 +374,14 @@ log "check: native replay"
|
|
|
373
374
|
REPLAY_DIR="$SESSION_ROOT/native-replay"
|
|
374
375
|
mkdir -p "$REPLAY_DIR"
|
|
375
376
|
run_in_dir_capture_split "native replay" "$PI_LIVE_TIMEOUT" "$PROJECT_DIR" "$ISOLATED/replay.stdout.txt" "$ISOLATED/replay.stderr.txt" "${PI_CURSOR_ENV[@]}" PI_CURSOR_NATIVE_TOOL_DISPLAY=1 \
|
|
376
|
-
"$PI_BIN" --approve --cursor-no-fast --model cursor/
|
|
377
|
+
"$PI_BIN" --approve --cursor-no-fast --model cursor/grok-4.6 --session-dir "$REPLAY_DIR" -p 'Read ./README.md briefly, then answer README_SEEN=yes if it mentions pi-cursor-sdk.'
|
|
377
378
|
validate_replay_jsonl "$REPLAY_DIR"
|
|
378
379
|
|
|
379
380
|
log "check: plan-strip shim (plan-mode execute reset)"
|
|
380
381
|
PLAN_DIR="$SESSION_ROOT/plan-strip"
|
|
381
382
|
mkdir -p "$PLAN_DIR"
|
|
382
383
|
run_in_dir_capture_split "plan-strip replay" "$PI_LIVE_TIMEOUT" "$PROJECT_DIR" "$ISOLATED/plan.stdout.txt" "$ISOLATED/plan.stderr.txt" "${PI_CURSOR_ENV[@]}" PI_CURSOR_NATIVE_TOOL_DISPLAY=1 \
|
|
383
|
-
"$PI_BIN" --approve -e "$SHIM_DIR" --cursor-no-fast --model cursor/
|
|
384
|
+
"$PI_BIN" --approve -e "$SHIM_DIR" --cursor-no-fast --model cursor/grok-4.6 --session-dir "$PLAN_DIR" -p 'After reset, read README.md and answer PLAN_STRIP_OK=yes.'
|
|
384
385
|
validate_replay_jsonl "$PLAN_DIR"
|
|
385
386
|
|
|
386
387
|
log "PASS isolated install smoke: $ISOLATED"
|
|
@@ -360,7 +360,7 @@ function buildCloudSmokeMatrixEvidence(input, laneProjector, allowDefaultTimesta
|
|
|
360
360
|
} = data;
|
|
361
361
|
const timestamp = data.timestamp ?? (allowDefaultTimestamp ? new Date().toISOString() : undefined);
|
|
362
362
|
if (schemaVersion !== 1) fail("cloud smoke evidence schemaVersion must be 1");
|
|
363
|
-
if (model !== "cursor/
|
|
363
|
+
if (model !== "cursor/grok-4.6") fail("cloud smoke evidence model must be cursor/grok-4.6");
|
|
364
364
|
if (!Array.isArray(lanes) || lanes.length !== LANE_NAMES.length) fail("cloud smoke evidence lanes must contain the complete required matrix");
|
|
365
365
|
if (!Array.isArray(cleanup) || cleanup.length === 0) fail("cloud smoke evidence cleanup must be a non-empty array");
|
|
366
366
|
const projectedLanes = lanes.map((lane, index) => laneProjector(lane, index));
|
|
@@ -66,7 +66,7 @@ header code { color: #d8dee9; }
|
|
|
66
66
|
<header>
|
|
67
67
|
<div><strong>pi-cursor-sdk visual smoke</strong> <code>${escapeHtml(options.label)}</code></div>
|
|
68
68
|
<div>model <code>${escapeHtml(options.model)}</code> · mode <code>${escapeHtml(options.mode)}</code> · cwd <code>${escapeHtml(options.cwd)}</code></div>
|
|
69
|
-
<div>session <code>${escapeHtml(options.sessionId)}</code> · captured ${new Date().toISOString()}</div>
|
|
69
|
+
<div>session <code>${escapeHtml(options.sessionId ?? "pi-assigned")}</code> · captured ${new Date().toISOString()}</div>
|
|
70
70
|
</header>
|
|
71
71
|
<div id="terminal"></div>
|
|
72
72
|
<noscript><pre class="fallback">${escapeHtml(plain)}</pre></noscript>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebuild dist/ before a launcher loads the repo-root extension, so direct
|
|
3
|
+
* `node scripts/<launcher>.mjs` invocations can never exercise stale code.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { execFileSync } from "node:child_process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
export function ensureBuilt() {
|
|
10
|
+
execFileSync(process.execPath, [fileURLToPath(new URL("../build.mjs", import.meta.url))], {
|
|
11
|
+
// build.mjs anchors tsc/dist/staging to its cwd; pin it to the repo root so
|
|
12
|
+
// direct launcher invocations work from any directory.
|
|
13
|
+
cwd: fileURLToPath(new URL("../..", import.meta.url)),
|
|
14
|
+
stdio: "inherit",
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -152,7 +152,7 @@ export function startRpc({
|
|
|
152
152
|
baseEnv = process.env,
|
|
153
153
|
}) {
|
|
154
154
|
const model =
|
|
155
|
-
process.env.CURSOR_LOCAL_RESUME_SMOKE_MODEL || "cursor/
|
|
155
|
+
process.env.CURSOR_LOCAL_RESUME_SMOKE_MODEL || "cursor/grok-4.6:slow";
|
|
156
156
|
const workspaceDir = join(artifactDir, "workspace");
|
|
157
157
|
mkdirSync(workspaceDir, { recursive: true });
|
|
158
158
|
const pi = findPiCommand();
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
withRpc,
|
|
27
27
|
writeTreeCommandExtension,
|
|
28
28
|
} from "./lib/local-resume-smoke-harness.mjs";
|
|
29
|
+
import { ensureBuilt } from "./lib/ensure-built.mjs";
|
|
29
30
|
import { runCleanupSmoke } from "./local-resume-cleanup-smoke.mjs";
|
|
30
31
|
import { writePlatformArtifactBundle } from "./platform-smoke/artifacts.mjs";
|
|
31
32
|
import { LOCAL_RESUME_SUITES } from "./platform-smoke/local-resume-suites.mjs";
|
|
@@ -45,7 +46,7 @@ ${npmUsage}
|
|
|
45
46
|
${nodeUsage}
|
|
46
47
|
|
|
47
48
|
Environment:
|
|
48
|
-
CURSOR_LOCAL_RESUME_SMOKE_MODEL Cursor model id (default: cursor/
|
|
49
|
+
CURSOR_LOCAL_RESUME_SMOKE_MODEL Cursor model id (default: cursor/grok-4.6:slow).
|
|
49
50
|
CURSOR_LOCAL_RESUME_SMOKE_TIMEOUT_MS Timeout in ms per model turn (default: 300000).
|
|
50
51
|
CURSOR_LOCAL_RESUME_SMOKE_KEEP_ARTIFACTS Keep temp artifacts when set to 1.
|
|
51
52
|
CURSOR_LOCAL_RESUME_SMOKE_EXTENSION_PATH Packed extension path override (platform runner only).
|
|
@@ -627,6 +628,7 @@ function selectedRun() {
|
|
|
627
628
|
}
|
|
628
629
|
|
|
629
630
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
631
|
+
ensureBuilt();
|
|
630
632
|
const run = selectedRun();
|
|
631
633
|
run()
|
|
632
634
|
.catch((error) => {
|
|
@@ -31,7 +31,7 @@ const CARD_PATTERNS = [
|
|
|
31
31
|
{ id: "bridge-read-failure", pattern: /^\s*(?:read \.\/definitely-missing-platform-smoke-file\.txt|ENOENT: no such file)\s*/i },
|
|
32
32
|
{ id: "bridge-shell-success", pattern: /^\s*bridge visual smoke\s*$/i },
|
|
33
33
|
{ id: "http1-status", pattern: /\bcursor:local\b.*\bhttp1\b/i },
|
|
34
|
-
{ id: "footer-status", pattern: /\bcomposer-2-5\b|\bcomposer-2\.5\b/i },
|
|
34
|
+
{ id: "footer-status", pattern: /\bgrok-4\.6\b|\bcomposer-2-5\b|\bcomposer-2\.5\b/i },
|
|
35
35
|
];
|
|
36
36
|
|
|
37
37
|
function cleanLine(line) {
|
|
@@ -17,7 +17,7 @@ import { redactSecrets, writePlatformArtifactBundle } from "./artifacts.mjs";
|
|
|
17
17
|
import { extractContentText, jsonlHasAssistantFinalTextMarker } from "./jsonl-text.mjs";
|
|
18
18
|
import { getScenario, renderPrompt } from "./scenarios.mjs";
|
|
19
19
|
|
|
20
|
-
const DEFAULT_MODEL = "cursor/
|
|
20
|
+
const DEFAULT_MODEL = "cursor/grok-4.6";
|
|
21
21
|
const DEFAULT_WAIT_MS = 240_000;
|
|
22
22
|
const SESSION_JSONL_WAIT_MS = 60_000;
|
|
23
23
|
const COLS = 150;
|
|
@@ -27,7 +27,7 @@ export async function renderHTML(ansiPath, htmlPath, options = {}) {
|
|
|
27
27
|
plain,
|
|
28
28
|
options: {
|
|
29
29
|
label: options.label ?? "platform-smoke",
|
|
30
|
-
model: options.model ?? "cursor/
|
|
30
|
+
model: options.model ?? "cursor/grok-4.6",
|
|
31
31
|
mode: options.mode ?? "agent",
|
|
32
32
|
cwd: options.cwd ?? process.cwd(),
|
|
33
33
|
sessionId: options.sessionId ?? "platform-smoke",
|
|
@@ -413,7 +413,7 @@ export function buildPlatformBuildCommand(targetName, packageName = "pi-cursor-s
|
|
|
413
413
|
lines.push(...posixSection("CHECK_PLATFORM_SMOKE_STDERR", 'cat "$PACK_DIR/check-platform-smoke.stderr.txt" 2>/dev/null || true'));
|
|
414
414
|
lines.push("");
|
|
415
415
|
lines.push('echo "=== npm test ==="');
|
|
416
|
-
lines.push('npm test >"$PACK_DIR/npm-test.stdout.txt" 2>"$PACK_DIR/npm-test.stderr.txt"');
|
|
416
|
+
lines.push('npm test -- --testTimeout=15000 >"$PACK_DIR/npm-test.stdout.txt" 2>"$PACK_DIR/npm-test.stderr.txt"');
|
|
417
417
|
lines.push("TEST_EXIT=$?");
|
|
418
418
|
lines.push('echo "PLATFORM_NPM_TEST_EXIT=$TEST_EXIT"');
|
|
419
419
|
lines.push(...posixSection("NPM_TEST_STDOUT", 'cat "$PACK_DIR/npm-test.stdout.txt" 2>/dev/null || true'));
|
|
@@ -662,7 +662,7 @@ async function executeLiveSuite(config, targetName, suiteName, suiteDir, slug, l
|
|
|
662
662
|
}
|
|
663
663
|
|
|
664
664
|
function buildLiveSuiteCommand(config, targetName, suiteName, prepDir) {
|
|
665
|
-
const model = config.cursorModel ?? "cursor/
|
|
665
|
+
const model = config.cursorModel ?? "cursor/grok-4.6";
|
|
666
666
|
const packageName = config.packageName ?? "pi-cursor-sdk";
|
|
667
667
|
const prepArgs = prepDir ? ` --prep-dir ${platformFor(targetName) === "powershell" ? prepDir : shellQuote(prepDir)}` : "";
|
|
668
668
|
if (platformFor(targetName) === "powershell") {
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Purpose: Build generated dist output for GitHub/source installs even when Pi invokes npm install --omit=dev.
|
|
4
|
+
* Responsibilities: Detect missing source-build dependencies via the local node_modules tree, install dev
|
|
5
|
+
* dependencies with lifecycle scripts disabled, run the canonical build, then prune the dev tree so installs
|
|
6
|
+
* keep a runtime-only footprint.
|
|
7
|
+
* Scope: Package install lifecycle only; runtime behavior remains owned by scripts/build.mjs.
|
|
8
|
+
* Usage: package.json prepare script.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { execFile as execFileCallback } from "node:child_process";
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import process from "node:process";
|
|
15
|
+
import { promisify } from "node:util";
|
|
16
|
+
|
|
17
|
+
const execFile = promisify(execFileCallback);
|
|
18
|
+
|
|
19
|
+
// Checked as literal node_modules paths: require.resolve() is unusable here because
|
|
20
|
+
// several @earendil-works packages expose import-only "exports" maps and throw
|
|
21
|
+
// ERR_PACKAGE_PATH_NOT_EXPORTED even when installed.
|
|
22
|
+
const REQUIRED_SOURCE_BUILD_MODULES = [
|
|
23
|
+
"typescript",
|
|
24
|
+
"typebox",
|
|
25
|
+
"@earendil-works/pi-ai",
|
|
26
|
+
"@earendil-works/pi-coding-agent",
|
|
27
|
+
"@earendil-works/pi-tui",
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
function hasBuildDependencies() {
|
|
31
|
+
return REQUIRED_SOURCE_BUILD_MODULES.every((moduleName) =>
|
|
32
|
+
existsSync(join(process.cwd(), "node_modules", ...moduleName.split("/"), "package.json")),
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function runNpm(args) {
|
|
37
|
+
const npmExecPath = process.env.npm_execpath;
|
|
38
|
+
if (!npmExecPath) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`npm_execpath is not set; run "npm ${args.join(" ")}" manually in ${process.cwd()} and retry.`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
// No shell: process.execPath runs npm's cli.js directly, which is safe for paths
|
|
44
|
+
// containing spaces on every platform (shell:true concatenates args unescaped).
|
|
45
|
+
await execFile(process.execPath, [npmExecPath, ...args], {
|
|
46
|
+
cwd: process.cwd(),
|
|
47
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function runBuild() {
|
|
52
|
+
const { stderr, stdout } = await execFile(process.execPath, [join(process.cwd(), "scripts", "build.mjs")], {
|
|
53
|
+
cwd: process.cwd(),
|
|
54
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
55
|
+
});
|
|
56
|
+
// Forward build output on success too: install-time diagnostics such as the
|
|
57
|
+
// concurrent-swap race-loss warning are otherwise swallowed.
|
|
58
|
+
if (stdout) process.stdout.write(stdout);
|
|
59
|
+
if (stderr) process.stderr.write(stderr);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function pruneDevDependencies() {
|
|
63
|
+
await runNpm(["prune", "--omit=dev", "--ignore-scripts"]);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function pruneQuietly() {
|
|
67
|
+
try {
|
|
68
|
+
await pruneDevDependencies();
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.warn(`npm prune failed after a failed build: ${error?.message ?? error}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function reportError(error) {
|
|
75
|
+
if (error?.stdout) process.stdout.write(error.stdout);
|
|
76
|
+
if (error?.stderr) process.stderr.write(error.stderr);
|
|
77
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function main() {
|
|
81
|
+
if (hasBuildDependencies()) {
|
|
82
|
+
await runBuild();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
await runNpm(["install", "--include=dev", "--ignore-scripts"]);
|
|
86
|
+
try {
|
|
87
|
+
await runBuild();
|
|
88
|
+
} catch (buildError) {
|
|
89
|
+
// Report the build first; cleanup can warn afterward but never mask it.
|
|
90
|
+
reportError(buildError);
|
|
91
|
+
await pruneQuietly();
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// A prune failure after a successful build still fails the install.
|
|
96
|
+
await pruneDevDependencies();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
main().catch((error) => {
|
|
100
|
+
reportError(error);
|
|
101
|
+
process.exitCode = 1;
|
|
102
|
+
});
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from "./lib/cursor-child-process.mjs";
|
|
17
17
|
import { apiKeySecretsFromProcess } from "./lib/cursor-cli-args.mjs";
|
|
18
18
|
import { buildCursorSmokeEnv, CURSOR_SDK_EVENT_DEBUG_ENV_NAMES } from "./lib/cursor-smoke-env.mjs";
|
|
19
|
+
import { ensureBuilt } from "./lib/ensure-built.mjs";
|
|
19
20
|
import { scrubSensitiveText } from "../shared/cursor-sensitive-text.mjs";
|
|
20
21
|
|
|
21
22
|
const root = fileURLToPath(new URL("..", import.meta.url));
|
|
@@ -170,7 +171,7 @@ function buildPiRpcEnv(baseEnv = process.env, nodePath = process.execPath) {
|
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
async function runPiRpcSmoke(sessionDir, piBin) {
|
|
173
|
-
const args = ["--approve", "-e", root, "--cursor-no-fast", "--model", "cursor/
|
|
174
|
+
const args = ["--approve", "-e", root, "--cursor-no-fast", "--model", "cursor/grok-4.6", "--mode", "rpc", "--session-dir", sessionDir];
|
|
174
175
|
const env = buildPiRpcEnv();
|
|
175
176
|
|
|
176
177
|
const child = spawn(piBin, args, {
|
|
@@ -263,7 +264,7 @@ async function runSelfTest() {
|
|
|
263
264
|
const envCapture = join(tempDir, "fake-pi.env");
|
|
264
265
|
writeFileSync(
|
|
265
266
|
fakePi,
|
|
266
|
-
`#!/usr/bin/env node\
|
|
267
|
+
`#!/usr/bin/env node\nimport { writeFileSync } from "node:fs";\nwriteFileSync(${JSON.stringify(envCapture)}, Object.entries(process.env).map(([key, value]) => key + "=" + (value ?? "")).join("\\n") + "\\n", "utf8");\n`,
|
|
267
268
|
"utf8",
|
|
268
269
|
);
|
|
269
270
|
writeFileSync(fakeNode, `#!/bin/sh\necho fake-node-used > ${JSON.stringify(fakeNodeMarker)}\nexit 99\n`, "utf8");
|
|
@@ -332,6 +333,7 @@ async function main() {
|
|
|
332
333
|
printHelp();
|
|
333
334
|
return;
|
|
334
335
|
}
|
|
336
|
+
ensureBuilt();
|
|
335
337
|
if (process.argv.includes("--self-test")) {
|
|
336
338
|
await runSelfTest();
|
|
337
339
|
return;
|
|
@@ -243,7 +243,7 @@ exec %s
|
|
|
243
243
|
"$TMUX_BIN" capture-pane -pt "$session" >"$capture" 2>/dev/null || true
|
|
244
244
|
missing=""
|
|
245
245
|
"$RG_BIN" -q "SUM=42" "$capture" || missing="${missing} SUM=42"
|
|
246
|
-
"$RG_BIN" -q "\\(cursor\\)
|
|
246
|
+
"$RG_BIN" -q "\\(cursor\\) grok-4\\.6" "$capture" || missing="${missing} footer (cursor) grok-4.6"
|
|
247
247
|
if [[ -z "$missing" ]]; then
|
|
248
248
|
"$TMUX_BIN" kill-session -t "$session" 2>/dev/null || true
|
|
249
249
|
log "$name PASS"
|
|
@@ -311,14 +311,14 @@ printf '\''%%s\n'\'' "$code" > %q
|
|
|
311
311
|
model_listed() {
|
|
312
312
|
local file="$1"
|
|
313
313
|
if [[ -n "${RG_BIN:-}" ]]; then
|
|
314
|
-
"$RG_BIN" -q "
|
|
314
|
+
"$RG_BIN" -q "grok-4\.6" "$file"
|
|
315
315
|
else
|
|
316
|
-
grep -q "
|
|
316
|
+
grep -q "grok-4\.6" "$file"
|
|
317
317
|
fi
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
# Capture full catalog then search. Never pipe list-models into rg -q under pipefail.
|
|
321
|
-
|
|
321
|
+
capture_and_require_default_model() {
|
|
322
322
|
local list_cmd=("$@")
|
|
323
323
|
local models_out="$SMOKE_DIR/prereq.models.txt"
|
|
324
324
|
local models_err="$SMOKE_DIR/prereq.stderr.txt"
|
|
@@ -326,7 +326,7 @@ capture_and_require_composer_model() {
|
|
|
326
326
|
fail "pi --list-models cursor failed"
|
|
327
327
|
fi
|
|
328
328
|
if ! model_listed "$models_out" && ! model_listed "$models_err"; then
|
|
329
|
-
fail "cursor/
|
|
329
|
+
fail "cursor/grok-4.6 not listed"
|
|
330
330
|
fi
|
|
331
331
|
}
|
|
332
332
|
|
|
@@ -343,7 +343,7 @@ run_self_test() {
|
|
|
343
343
|
env_capture="$temp_dir/fake-pi.env"
|
|
344
344
|
cat >"$fake_pi" <<EOF_SELFTEST_PI
|
|
345
345
|
#!/usr/bin/env node
|
|
346
|
-
|
|
346
|
+
import { writeFileSync } from "node:fs";
|
|
347
347
|
writeFileSync("$env_capture", Object.entries(process.env).map(([key, value]) => key + "=" + (value ?? "")).join("\\n") + "\\n", "utf8");
|
|
348
348
|
EOF_SELFTEST_PI
|
|
349
349
|
cat >"$fake_node" <<EOF_SELFTEST_NODE
|
|
@@ -383,7 +383,7 @@ EOF_SELFTEST_NODE
|
|
|
383
383
|
if grep -q '^PI_CURSOR_SETTING_SOURCES=' "$env_capture"; then
|
|
384
384
|
fail "self-test failed: default-settings env did not unset PI_CURSOR_SETTING_SOURCES"
|
|
385
385
|
fi
|
|
386
|
-
# Large-catalog prereq: exercise the same
|
|
386
|
+
# Large-catalog prereq: exercise the same capture_and_require_default_model helper.
|
|
387
387
|
fake_list_pi="$bin_dir/pi-list-models"
|
|
388
388
|
cat >"$fake_list_pi" <<'EOF_FAKE_LIST'
|
|
389
389
|
#!/usr/bin/env bash
|
|
@@ -392,11 +392,11 @@ while [[ $i -lt 20000 ]]; do
|
|
|
392
392
|
printf 'cursor/model-%s\n' "$i"
|
|
393
393
|
i=$((i + 1))
|
|
394
394
|
done
|
|
395
|
-
printf 'cursor/
|
|
395
|
+
printf 'cursor/grok-4.6\n'
|
|
396
396
|
exit 0
|
|
397
397
|
EOF_FAKE_LIST
|
|
398
398
|
chmod +x "$fake_list_pi"
|
|
399
|
-
SMOKE_DIR="$temp_dir"
|
|
399
|
+
SMOKE_DIR="$temp_dir" capture_and_require_default_model "$fake_list_pi"
|
|
400
400
|
if [[ "$(wc -l <"$temp_dir/prereq.models.txt" | tr -d ' ')" -lt 20000 ]]; then
|
|
401
401
|
fail "self-test failed: large catalog was truncated before search"
|
|
402
402
|
fi
|
|
@@ -428,7 +428,7 @@ fi
|
|
|
428
428
|
PI_BASE=(
|
|
429
429
|
"$PI_BIN" --approve -e "$ROOT"
|
|
430
430
|
--cursor-no-fast
|
|
431
|
-
--model cursor/
|
|
431
|
+
--model cursor/grok-4.6
|
|
432
432
|
)
|
|
433
433
|
|
|
434
434
|
if [[ -z "${CURSOR_API_KEY:-}" ]]; then
|
|
@@ -448,7 +448,7 @@ log "partial live smoke: prereq, basic, default-settings, noninteractive-math, t
|
|
|
448
448
|
"${BASE_ENV[@]}" "$PI_BIN" --version | tee "$SMOKE_DIR/prereq.pi-version.txt"
|
|
449
449
|
"${BASE_ENV[@]}" "$NPM_BIN" --prefix "$ROOT" ls @cursor/sdk @earendil-works/pi-coding-agent @earendil-works/pi-ai @earendil-works/pi-tui | tee "$SMOKE_DIR/prereq.npm-ls.txt"
|
|
450
450
|
|
|
451
|
-
|
|
451
|
+
capture_and_require_default_model "${NONE_ENV[@]}" "${PI_BASE[@]}" --list-models cursor
|
|
452
452
|
log "prereq PASS"
|
|
453
453
|
|
|
454
454
|
run_direct basic 600 retry-empty-output "PI_CURSOR_SMOKE_OK" "PI_CURSOR_SMOKE_OK" \
|
|
@@ -35,7 +35,7 @@ export function runVisualSmokeSelfTest(deps) {
|
|
|
35
35
|
const envCapture = join(tempDir, "fake-pi.env");
|
|
36
36
|
writeFileSync(
|
|
37
37
|
fakePi,
|
|
38
|
-
`#!/usr/bin/env node\
|
|
38
|
+
`#!/usr/bin/env node\nimport { writeFileSync } from "node:fs";\nwriteFileSync(${JSON.stringify(envCapture)}, Object.entries(process.env).map(([key, value]) => key + "=" + (value ?? "")).join("\\n") + "\\n", "utf8");\n`,
|
|
39
39
|
"utf8",
|
|
40
40
|
);
|
|
41
41
|
writeFileSync(fakeNode, `#!/bin/sh\necho fake-node-used > ${shellQuote(fakeNodeMarker)}\nexit 99\n`, "utf8");
|
|
@@ -89,6 +89,9 @@ export function runVisualSmokeSelfTest(deps) {
|
|
|
89
89
|
assertSelfTest(defaults.get("PI_CURSOR_SETTING_SOURCES") === "none", "setting sources must default to none");
|
|
90
90
|
assertSelfTest(defaults.get("PI_CURSOR_PI_TOOL_BRIDGE") === "0", "bridge must default off");
|
|
91
91
|
assertSelfTest(defaults.get("PI_CURSOR_EXPOSE_BUILTIN_TOOLS") === "0", "built-in exposure must default off");
|
|
92
|
+
assertSelfTest(defaults.get("PI_CODING_AGENT_DIR") === join(tempDir, "pi-agent"), "agent dir must be isolated under out-dir");
|
|
93
|
+
assertSelfTest(defaults.get("PI_OFFLINE") === "1", "startup network operations must be off");
|
|
94
|
+
assertSelfTest(defaults.get("PI_SKIP_VERSION_CHECK") === "1", "pi.dev version check must be off");
|
|
92
95
|
for (const name of DEBUG_ENV_NAMES) {
|
|
93
96
|
assertSelfTest(plan.clearEnvNames.includes(name), `${name} must be cleared by default`);
|
|
94
97
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
|
-
import { accessSync, constants, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { accessSync, chmodSync, constants, copyFileSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
4
5
|
import { delimiter, dirname, join, resolve } from "node:path";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
7
|
import { commonBooleanFlag, commonRepeatStringFlag, parseArgv } from "./lib/cursor-cli-args.mjs";
|
|
@@ -15,7 +16,7 @@ const DEFAULT_HEIGHT = 45;
|
|
|
15
16
|
const DEFAULT_WAIT_MS = 60_000;
|
|
16
17
|
const DEFAULT_STARTUP_MS = 5_000;
|
|
17
18
|
const DEFAULT_HISTORY_LINES = 3_000;
|
|
18
|
-
const DEFAULT_MODEL = "cursor/
|
|
19
|
+
const DEFAULT_MODEL = "cursor/grok-4.6";
|
|
19
20
|
const DEFAULT_MODE = "plan";
|
|
20
21
|
const DEFAULT_SETTING_SOURCES = "none";
|
|
21
22
|
const DEBUG_ENV_NAMES = CURSOR_SDK_EVENT_DEBUG_ENV_NAMES;
|
|
@@ -44,7 +45,7 @@ Common options:
|
|
|
44
45
|
--model MODEL Cursor model. Default: ${DEFAULT_MODEL}.
|
|
45
46
|
--mode agent|plan Cursor SDK mode. Default: ${DEFAULT_MODE}.
|
|
46
47
|
--session-dir PATH pi session directory. Default: <out-dir>/<label>.session.
|
|
47
|
-
--session-id ID pi session id. Default:
|
|
48
|
+
--session-id ID pi session id; pass to resume a prior capture session. Default: pi-assigned, so fresh captures avoid the new-session warning line.
|
|
48
49
|
--width N PTY columns. Default: ${DEFAULT_WIDTH}.
|
|
49
50
|
--height N PTY rows. Default: ${DEFAULT_HEIGHT}.
|
|
50
51
|
--history-lines N tmux capture history lines. Default: ${DEFAULT_HISTORY_LINES}.
|
|
@@ -63,7 +64,11 @@ Native replay isolation defaults:
|
|
|
63
64
|
PI_CURSOR_SETTING_SOURCES=none
|
|
64
65
|
PI_CURSOR_PI_TOOL_BRIDGE=0
|
|
65
66
|
PI_CURSOR_EXPOSE_BUILTIN_TOOLS=0
|
|
67
|
+
PI_CODING_AGENT_DIR=<out-dir>/pi-agent (seeded auth.json + quietStartup; host extensions stay out)
|
|
68
|
+
PI_OFFLINE=1
|
|
69
|
+
PI_SKIP_VERSION_CHECK=1
|
|
66
70
|
TERM=xterm-256color
|
|
71
|
+
tmux starts in --cwd with a non-login shell so a stale tmux-server cwd cannot print getcwd errors
|
|
67
72
|
Debug artifact env is cleared before each run; --event-debug sets a deterministic debug dir.
|
|
68
73
|
|
|
69
74
|
Artifacts written:
|
|
@@ -194,10 +199,26 @@ function parseArgs(argv) {
|
|
|
194
199
|
options.safeLabel = sanitizeLabel(options.label);
|
|
195
200
|
options.outDir ??= resolve(`/tmp/pi-cursor-sdk-visual-smoke-${timestamp()}`);
|
|
196
201
|
options.sessionDir ??= resolve(options.outDir, `${options.safeLabel}.session`);
|
|
197
|
-
options.
|
|
202
|
+
options.agentDir ??= resolve(options.outDir, "pi-agent");
|
|
198
203
|
return options;
|
|
199
204
|
}
|
|
200
205
|
|
|
206
|
+
function seedVisualAgentDir(agentDir) {
|
|
207
|
+
mkdirSync(agentDir, { recursive: true });
|
|
208
|
+
const srcAuth = join(homedir(), ".pi", "agent", "auth.json");
|
|
209
|
+
const destAuth = join(agentDir, "auth.json");
|
|
210
|
+
try {
|
|
211
|
+
copyFileSync(srcAuth, destAuth);
|
|
212
|
+
chmodSync(destAuth, 0o600);
|
|
213
|
+
} catch {
|
|
214
|
+
// CURSOR_API_KEY remains the fallback when host auth.json is absent.
|
|
215
|
+
}
|
|
216
|
+
writeFileSync(
|
|
217
|
+
join(agentDir, "settings.json"),
|
|
218
|
+
`${JSON.stringify({ quietStartup: true, enableInstallTelemetry: false })}\n`,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
201
222
|
function sanitizeLabel(label) {
|
|
202
223
|
const safe = label.trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
203
224
|
return safe || "visual-smoke";
|
|
@@ -359,7 +380,13 @@ function buildLaunchPlan(options, commands, shell) {
|
|
|
359
380
|
eventDebugDir: options.eventDebug ? resolve(options.outDir, `${options.safeLabel ?? "visual-smoke"}.cursor-sdk-events`) : undefined,
|
|
360
381
|
});
|
|
361
382
|
const sealedPath = commands.sealedPath ?? smokeEnvPlan.sealedPath;
|
|
362
|
-
const
|
|
383
|
+
const agentDir = options.agentDir ?? resolve(options.outDir, "pi-agent");
|
|
384
|
+
const envAssignments = [
|
|
385
|
+
...smokeEnvPlan.envEntries,
|
|
386
|
+
["PI_CODING_AGENT_DIR", agentDir],
|
|
387
|
+
["PI_OFFLINE", "1"],
|
|
388
|
+
["PI_SKIP_VERSION_CHECK", "1"],
|
|
389
|
+
];
|
|
363
390
|
const clearEnvNames = smokeEnvPlan.clearEnvNames;
|
|
364
391
|
const command = [
|
|
365
392
|
...envAssignments.map(([name, value]) => `${name}=${shellQuote(value)}`),
|
|
@@ -370,7 +397,7 @@ function buildLaunchPlan(options, commands, shell) {
|
|
|
370
397
|
"--cursor-no-fast",
|
|
371
398
|
"--cursor-mode", shellQuote(options.mode),
|
|
372
399
|
"--session-dir", shellQuote(options.sessionDir),
|
|
373
|
-
"--session-id", shellQuote(options.sessionId),
|
|
400
|
+
...(options.sessionId ? ["--session-id", shellQuote(options.sessionId)] : []),
|
|
374
401
|
"--model", shellQuote(options.model),
|
|
375
402
|
].join(" ");
|
|
376
403
|
const clearLines = clearEnvNames.map((name) => `unset ${name}`).join("\n");
|
|
@@ -397,6 +424,8 @@ function runVisualSmoke(options) {
|
|
|
397
424
|
|
|
398
425
|
mkdirSync(options.outDir, { recursive: true });
|
|
399
426
|
mkdirSync(options.sessionDir, { recursive: true });
|
|
427
|
+
options.agentDir ??= resolve(options.outDir, "pi-agent");
|
|
428
|
+
seedVisualAgentDir(options.agentDir);
|
|
400
429
|
|
|
401
430
|
const sessionName = `pi-visual-${options.safeLabel}-${process.pid}`;
|
|
402
431
|
const bufferName = `pi-visual-prompt-${process.pid}`;
|
|
@@ -418,7 +447,22 @@ function runVisualSmoke(options) {
|
|
|
418
447
|
const jsonlMtimesBeforeRun = snapshotJsonlMtimes(options.sessionDir);
|
|
419
448
|
const runStartedAtMs = Date.now();
|
|
420
449
|
try {
|
|
421
|
-
const start = run(commands.tmux, [
|
|
450
|
+
const start = run(commands.tmux, [
|
|
451
|
+
"new-session",
|
|
452
|
+
"-d",
|
|
453
|
+
"-s",
|
|
454
|
+
sessionName,
|
|
455
|
+
"-c",
|
|
456
|
+
options.cwd,
|
|
457
|
+
"-x",
|
|
458
|
+
String(options.width),
|
|
459
|
+
"-y",
|
|
460
|
+
String(options.height),
|
|
461
|
+
"--",
|
|
462
|
+
shell,
|
|
463
|
+
"-c",
|
|
464
|
+
script,
|
|
465
|
+
]);
|
|
422
466
|
if (start.status !== 0) throw new Error(`tmux new-session failed: ${start.stderr?.toString().trim() || start.status}`);
|
|
423
467
|
sessionStarted = true;
|
|
424
468
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated from Cursor SDK checkpoint tokenDetails.maxTokens on 2026-08-
|
|
1
|
+
// Generated from Cursor SDK checkpoint tokenDetails.maxTokens on 2026-08-18.
|
|
2
2
|
// Refresh with: npm run refresh:cursor-snapshots -- --write --context-windows ~/.pi/agent/cursor-sdk-context-windows.json
|
|
3
3
|
// Keys are current selectable model IDs. Equivalent default :fast/:slow selections
|
|
4
4
|
// collapse to one key; stale and ambiguous aliases are omitted. Values are observed
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// label when the completed SDK checkpoint reports a different effective limit.
|
|
7
7
|
export const BUNDLED_CONTEXT_WINDOWS = {
|
|
8
8
|
"default": 200000,
|
|
9
|
+
"auto-smart": 200000,
|
|
9
10
|
"claude-fable-5@300k": 300000,
|
|
10
11
|
"claude-haiku-4-5": 200000,
|
|
11
12
|
"claude-opus-4-5": 200000,
|
|
@@ -17,6 +18,7 @@ export const BUNDLED_CONTEXT_WINDOWS = {
|
|
|
17
18
|
"gemini-3.1-pro": 200000,
|
|
18
19
|
"gemini-3.5-flash": 200000,
|
|
19
20
|
"gemini-3.6-flash": 200000,
|
|
21
|
+
"gemini-3.7-flash": 200000,
|
|
20
22
|
"glm-5.2": 200000,
|
|
21
23
|
"gpt-5-5@272k": 272000,
|
|
22
24
|
"gpt-5-mini": 272000,
|
|
@@ -29,6 +31,7 @@ export const BUNDLED_CONTEXT_WINDOWS = {
|
|
|
29
31
|
"gpt-5.6@1m": 272000,
|
|
30
32
|
"grok-4.5": 256000,
|
|
31
33
|
"grok-4.5:slow": 256000,
|
|
34
|
+
"grok-4.6": 256000,
|
|
32
35
|
"kimi-k2.7-code": 200000,
|
|
33
36
|
"kimi-k3": 200000,
|
|
34
37
|
"opus-4.8@1m": 300000,
|