pi-cursor-sdk 0.5.2 → 0.5.4
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 +66 -1
- package/README.md +62 -795
- package/dist/context.js +13 -7
- package/dist/cursor-agents-context.js +6 -6
- package/dist/cursor-api-key.js +1 -1
- package/dist/cursor-bridge-contract.js +1 -13
- package/dist/cursor-cloud-local-state.js +0 -1
- package/dist/cursor-config.js +1 -17
- package/dist/cursor-custom-subagent-definitions.js +1 -1
- package/dist/cursor-fallback-models.generated.js +665 -1
- package/dist/cursor-live-run-coordinator.js +1 -0
- package/dist/cursor-local-agent-ownership.js +17 -0
- package/dist/cursor-mcp-timeout-override.js +7 -18
- package/dist/cursor-native-tool-display-replay.js +5 -5
- package/dist/cursor-native-tools.js +11 -0
- package/dist/cursor-pi-tool-bridge-diagnostics.js +4 -0
- package/dist/cursor-pi-tool-bridge-env.js +25 -2
- package/dist/cursor-pi-tool-bridge-run.js +10 -3
- package/dist/cursor-pi-tool-bridge-server.js +98 -48
- package/dist/cursor-pi-tool-bridge-snapshot.js +1 -1
- package/dist/cursor-pi-tool-bridge.js +4 -12
- package/dist/cursor-provider-errors.js +2 -8
- package/dist/cursor-provider-live-run-drain.js +8 -3
- package/dist/cursor-provider-overflow.js +7 -21
- package/dist/cursor-provider-turn-prepare.js +8 -1
- package/dist/cursor-provider-turn-runner.js +17 -6
- package/dist/cursor-provider-turn-summary.js +1 -1
- package/dist/cursor-provider.js +1 -4
- package/dist/cursor-runtime-state.js +3 -3
- package/dist/cursor-sdk-event-debug.js +2 -2
- package/dist/cursor-sdk-output-filter.js +1 -1
- package/dist/cursor-sdk-process-error-guard.js +1 -2
- package/dist/cursor-session-agent-cleanup.js +10 -1
- package/dist/cursor-session-agent-lifecycle.js +2 -2
- package/dist/cursor-session-agent-lineage.js +11 -7
- package/dist/cursor-session-agent-resume.js +15 -9
- package/dist/cursor-session-agent.js +28 -15
- package/dist/cursor-session-scope.js +28 -21
- package/dist/cursor-session-settings.js +3 -3
- package/dist/cursor-session-store.js +2 -2
- package/dist/cursor-state.js +26 -29
- package/dist/cursor-tool-lifecycle.js +0 -3
- package/dist/cursor-tool-manifest.js +3 -1
- package/dist/cursor-tool-presentation-registry.js +2 -4
- package/dist/cursor-tool-visibility.js +0 -3
- package/dist/cursor-transcript-tool-specs.js +1 -2
- package/dist/index.js +21 -0
- package/dist/model-discovery.js +8 -10
- package/dist/model-list-cache.js +4 -9
- package/docs/cursor-live-smoke-checklist.md +4 -4
- package/docs/cursor-model-ux-spec.md +36 -19
- package/docs/cursor-native-tool-replay.md +8 -5
- package/docs/cursor-native-tool-visual-audit.md +1 -1
- package/docs/cursor-testing-lessons.md +39 -9
- package/docs/cursor-tool-surfaces.md +48 -4
- package/docs/development.md +93 -0
- package/docs/platform-smoke-implementation.md +3 -2
- package/docs/reference.md +806 -0
- package/package.json +13 -11
- package/scripts/platform-smoke/artifact-secrets.mjs +13 -4
- package/scripts/platform-smoke/local-resume-runner.mjs +0 -1
- package/scripts/platform-smoke/target-runtime.mjs +4 -2
- package/scripts/platform-smoke/targets.mjs +0 -1
- package/shared/cursor-sdk-output-filter.d.mts +2 -0
- package/shared/cursor-sdk-output-filter.mjs +92 -28
- package/shared/cursor-sensitive-text.d.mts +1 -0
- package/shared/cursor-sensitive-text.mjs +7 -0
- package/src/context.ts +18 -11
- package/src/cursor-agents-context.ts +6 -6
- package/src/cursor-api-key.ts +1 -1
- package/src/cursor-bridge-contract.ts +1 -15
- package/src/cursor-cloud-local-state.ts +0 -2
- package/src/cursor-config.ts +1 -24
- package/src/cursor-custom-subagent-definitions.ts +1 -1
- package/src/cursor-fallback-models.generated.ts +665 -1
- package/src/cursor-live-run-coordinator.ts +5 -0
- package/src/cursor-local-agent-ownership.ts +18 -0
- package/src/cursor-mcp-timeout-override.ts +7 -31
- package/src/cursor-native-tool-display-replay.ts +4 -6
- package/src/cursor-native-tools.ts +14 -0
- package/src/cursor-pi-tool-bridge-diagnostics.ts +17 -0
- package/src/cursor-pi-tool-bridge-env.ts +31 -2
- package/src/cursor-pi-tool-bridge-run.ts +10 -3
- package/src/cursor-pi-tool-bridge-server.ts +89 -45
- package/src/cursor-pi-tool-bridge-snapshot.ts +0 -1
- package/src/cursor-pi-tool-bridge.ts +2 -18
- package/src/cursor-provider-errors.ts +2 -10
- package/src/cursor-provider-live-run-drain.ts +8 -2
- package/src/cursor-provider-overflow.ts +6 -24
- package/src/cursor-provider-turn-prepare.ts +10 -1
- package/src/cursor-provider-turn-runner.ts +17 -6
- package/src/cursor-provider-turn-summary.ts +1 -1
- package/src/cursor-provider.ts +0 -5
- package/src/cursor-runtime-state.ts +3 -3
- package/src/cursor-sdk-event-debug.ts +2 -2
- package/src/cursor-sdk-output-filter.ts +2 -1
- package/src/cursor-sdk-process-error-guard.ts +1 -3
- package/src/cursor-session-agent-cleanup.ts +6 -1
- package/src/cursor-session-agent-lifecycle.ts +2 -2
- package/src/cursor-session-agent-lineage.ts +10 -5
- package/src/cursor-session-agent-resume.ts +14 -7
- package/src/cursor-session-agent.ts +31 -15
- package/src/cursor-session-scope.ts +34 -20
- package/src/cursor-session-settings.ts +3 -3
- package/src/cursor-session-store.ts +2 -2
- package/src/cursor-state.ts +34 -41
- package/src/cursor-tool-lifecycle.ts +0 -4
- package/src/cursor-tool-manifest.ts +4 -1
- package/src/cursor-tool-presentation-registry.ts +3 -5
- package/src/cursor-tool-visibility.ts +0 -4
- package/src/cursor-transcript-tool-specs.ts +0 -3
- package/src/index.ts +18 -0
- package/src/model-discovery.ts +7 -9
- package/src/model-list-cache.ts +4 -10
package/dist/cursor-state.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CURSOR_HOST_TOOL_MANIFEST_SUMMARY, CURSOR_TOOL_MANIFEST_ENV, resolveCursorToolManifestEnabled, } from "./cursor-tool-manifest.js";
|
|
2
2
|
import { runCursorSessionAgentCleanupCommand } from "./cursor-session-agent-cleanup.js";
|
|
3
3
|
import { CURSOR_HTTP1_ENTRY_TYPE, getStoredCursorHttp1Enabled, isCursorHttp1EntryData, setCursorHttp1GlobalPreferenceAuthoritative, setStoredCursorHttp1Enabled, } from "./cursor-http1.js";
|
|
4
|
-
import { buildCursorPiToolBridgeSnapshot, CURSOR_PI_TOOL_BRIDGE_ENV, resolveCursorPiToolBridgeEnabled, } from "./cursor-pi-tool-bridge-snapshot.js";
|
|
4
|
+
import { buildCursorPiToolBridgeSnapshot, CURSOR_PI_TOOL_BRIDGE_ENV, resolveCursorPiToolBridgeBuiltinsEnabled, resolveCursorPiToolBridgeEnabled, } from "./cursor-pi-tool-bridge-snapshot.js";
|
|
5
|
+
import { CURSOR_PI_TOOL_BRIDGE_DEBUG_ENV } from "./cursor-pi-tool-bridge-diagnostics.js";
|
|
5
6
|
import { CURSOR_SETTING_SOURCES_ENV, DEFAULT_CURSOR_SETTING_SOURCES, resolveCursorSettingSources, } from "./cursor-setting-sources.js";
|
|
6
7
|
import { parseEnvBoolean } from "./cursor-env-boolean.js";
|
|
7
8
|
import { isCursorModel } from "./cursor-model.js";
|
|
@@ -12,8 +13,7 @@ import { cursorSettingsScopeForContext, getCursorSessionSettings, registerCursor
|
|
|
12
13
|
import { refreshSessionCursorAgentConfig } from "./cursor-session-agent.js";
|
|
13
14
|
import { getCursorModelMetadata } from "./model-discovery.js";
|
|
14
15
|
import { cursorFastDefaultsFromConfig, getCursorSdkUserConfigPath, loadCursorSdkUserConfig, mergeCursorSdkConfigForUpdate, resolveCursorFastDefault, resolveCursorLocalStoreRoot, updateCursorSdkConfig, } from "./cursor-config.js";
|
|
15
|
-
import {
|
|
16
|
-
export { consumeCursorLocalForceOverride, getCursorCliConfig, getCursorSessionConfig, } from "./cursor-runtime-state.js";
|
|
16
|
+
import { formatCursorStatus, registerCursorCloudRuntimeControls, resetCursorRuntimeStateForTests, resolveCursorStatusRuntime, restoreCursorCliState, restoreSessionCursorRuntimeState, } from "./cursor-runtime-state.js";
|
|
17
17
|
export const CURSOR_FOOTER_ENV = "PI_CURSOR_FOOTER";
|
|
18
18
|
const FAST_ENTRY_TYPE = "cursor-fast-state";
|
|
19
19
|
const MODE_ENTRY_TYPE = "cursor-mode-state";
|
|
@@ -21,10 +21,10 @@ const DEFAULT_CURSOR_AGENT_MODE = "agent";
|
|
|
21
21
|
const authoritativeGlobalFastPreferenceIds = new Set();
|
|
22
22
|
let globalFastPreferences = new Map();
|
|
23
23
|
const invalidCursorModeNotifiedSessionScopeKeys = new Set();
|
|
24
|
-
|
|
24
|
+
function isCursorAgentMode(value) {
|
|
25
25
|
return value === "agent" || value === "plan";
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
function parseCursorAgentMode(raw) {
|
|
28
28
|
if (typeof raw !== "string")
|
|
29
29
|
return undefined;
|
|
30
30
|
const mode = raw.trim();
|
|
@@ -42,14 +42,11 @@ function getCursorFastEntryModelId(data) {
|
|
|
42
42
|
function isCursorModeEntryData(value) {
|
|
43
43
|
return isCursorAgentMode(asRecord(value)?.mode);
|
|
44
44
|
}
|
|
45
|
-
function getConfigPath() {
|
|
46
|
-
return getCursorSdkUserConfigPath();
|
|
47
|
-
}
|
|
48
45
|
function loadGlobalFastPreferences() {
|
|
49
46
|
return cursorFastDefaultsFromConfig(loadCursorSdkUserConfig());
|
|
50
47
|
}
|
|
51
48
|
function saveGlobalFastPreference(modelId, fast) {
|
|
52
|
-
updateCursorSdkConfig(
|
|
49
|
+
updateCursorSdkConfig(getCursorSdkUserConfigPath(), (current) => {
|
|
53
50
|
const fastDefaults = { ...asRecord(current.fastDefaults), [modelId]: fast };
|
|
54
51
|
return {
|
|
55
52
|
...current,
|
|
@@ -58,7 +55,7 @@ function saveGlobalFastPreference(modelId, fast) {
|
|
|
58
55
|
}, { newFileMode: 0o600 });
|
|
59
56
|
}
|
|
60
57
|
function saveGlobalCursorHttp1Enabled(enabled) {
|
|
61
|
-
updateCursorSdkConfig(
|
|
58
|
+
updateCursorSdkConfig(getCursorSdkUserConfigPath(), (current) => mergeCursorSdkConfigForUpdate(current, {
|
|
62
59
|
local: { useHttp1ForAgent: enabled },
|
|
63
60
|
}), { newFileMode: 0o600 });
|
|
64
61
|
}
|
|
@@ -133,10 +130,10 @@ function getEffectiveFast(modelId, scopeKey) {
|
|
|
133
130
|
function formatInvalidCursorMode(raw) {
|
|
134
131
|
return `Invalid --cursor-mode "${raw}". Use "agent" or "plan".`;
|
|
135
132
|
}
|
|
136
|
-
|
|
133
|
+
function getStoredCursorAgentMode(scopeKey) {
|
|
137
134
|
return getCursorSessionSettings(scopeKey).mode ?? DEFAULT_CURSOR_AGENT_MODE;
|
|
138
135
|
}
|
|
139
|
-
|
|
136
|
+
function resolveCursorAgentMode(scopeKey) {
|
|
140
137
|
const cliCursorModeState = getCursorSessionSettings(scopeKey).cli.mode;
|
|
141
138
|
switch (cliCursorModeState.kind) {
|
|
142
139
|
case "valid":
|
|
@@ -270,11 +267,12 @@ function formatEffectiveCursorSettingSourcesLabel(raw = process.env[CURSOR_SETTI
|
|
|
270
267
|
const rawLabel = raw?.trim() ? raw.trim() : `(unset → ${DEFAULT_CURSOR_SETTING_SOURCES.join(",")})`;
|
|
271
268
|
return `${rawLabel} (effective: ${effectiveLabel})`;
|
|
272
269
|
}
|
|
273
|
-
|
|
270
|
+
function formatCursorToolsDebugReport(pi) {
|
|
271
|
+
const env = process.env;
|
|
274
272
|
const bridgeEnabled = resolveCursorPiToolBridgeEnabled(env);
|
|
275
273
|
const manifestEnabled = resolveCursorToolManifestEnabled(env);
|
|
276
274
|
const lines = [
|
|
277
|
-
"Cursor tool surfaces (current
|
|
275
|
+
"Cursor tool surfaces (current registry snapshot; not a live run):",
|
|
278
276
|
`${CURSOR_PI_TOOL_BRIDGE_ENV}: ${bridgeEnabled ? "enabled" : "disabled"}`,
|
|
279
277
|
`${CURSOR_TOOL_MANIFEST_ENV}: ${manifestEnabled ? "enabled" : "disabled"}`,
|
|
280
278
|
`${CURSOR_SETTING_SOURCES_ENV}: ${formatEffectiveCursorSettingSourcesLabel(env[CURSOR_SETTING_SOURCES_ENV])}`,
|
|
@@ -282,13 +280,23 @@ export function formatCursorToolsDebugReport(pi, env = process.env) {
|
|
|
282
280
|
let bridgeSnapshot;
|
|
283
281
|
if (bridgeEnabled) {
|
|
284
282
|
try {
|
|
285
|
-
bridgeSnapshot = buildCursorPiToolBridgeSnapshot(pi
|
|
283
|
+
bridgeSnapshot = buildCursorPiToolBridgeSnapshot(pi, {
|
|
284
|
+
exposeOverlappingBuiltins: resolveCursorPiToolBridgeBuiltinsEnabled(env),
|
|
285
|
+
});
|
|
286
286
|
}
|
|
287
287
|
catch {
|
|
288
288
|
lines.push("Pi bridge snapshot: unavailable (extension tool APIs required).");
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
|
-
lines.push(
|
|
291
|
+
lines.push(`Cursor host/MCP: ${CURSOR_HOST_TOOL_MANIFEST_SUMMARY}; configured MCP depends on Cursor settings.`, "Pi tool toggles affect pi tools/bridge exposure only; they do not disable Cursor host/configured MCP tools.");
|
|
292
|
+
if (!bridgeEnabled) {
|
|
293
|
+
lines.push("Pi bridge: disabled (PI_CURSOR_PI_TOOL_BRIDGE=0).");
|
|
294
|
+
}
|
|
295
|
+
else if (bridgeSnapshot) {
|
|
296
|
+
const names = bridgeSnapshot.tools.map((tool) => tool.mcpToolName).sort();
|
|
297
|
+
lines.push(`Pi bridge exposure eligibility: ${names.length ? names.join(", ") : "no eligible pi__* tools"}.`);
|
|
298
|
+
}
|
|
299
|
+
lines.push("This snapshot does not prove a run's endpoint attachment, MCP initialization, catalog fetch, or tool calls.", `For per-run observations, enable ${CURSOR_PI_TOOL_BRIDGE_DEBUG_ENV}=1 before the turn.`, "run_created/tools_exposed record exposure only; mcp_initialized records a validated notifications/initialized receipt; mcp_tools_list records catalog-handler output (toolCount), not client/model consumption or ongoing connection health.", "request_queued/resolved/rejected record actual bridge call handling; absent receipts do not diagnose why a client/model made no request.", "Not callable: cursor-replay-* IDs, pi history names, transcript labels.");
|
|
292
300
|
return lines.join("\n");
|
|
293
301
|
}
|
|
294
302
|
function emitCursorToolsDebugReport(pi, ctx) {
|
|
@@ -364,7 +372,7 @@ export function registerCursorRuntimeControls(pi) {
|
|
|
364
372
|
},
|
|
365
373
|
});
|
|
366
374
|
pi.registerCommand("cursor-tools", {
|
|
367
|
-
description: "Show
|
|
375
|
+
description: "Show current-registry Cursor tool exposure eligibility (maintainer debug)",
|
|
368
376
|
handler: async (_args, ctx) => {
|
|
369
377
|
emitCursorToolsDebugReport(pi, ctx);
|
|
370
378
|
},
|
|
@@ -517,16 +525,5 @@ function resetCursorModeStateForTests() {
|
|
|
517
525
|
authoritativeGlobalFastPreferenceIds.clear();
|
|
518
526
|
}
|
|
519
527
|
export const __testUtils = {
|
|
520
|
-
FAST_ENTRY_TYPE,
|
|
521
|
-
MODE_ENTRY_TYPE,
|
|
522
|
-
CURSOR_HTTP1_ENTRY_TYPE,
|
|
523
|
-
RUNTIME_ENTRY_TYPE: CURSOR_RUNTIME_ENTRY_TYPE,
|
|
524
|
-
DEFAULT_CURSOR_AGENT_MODE,
|
|
525
|
-
getConfigPath,
|
|
526
|
-
loadGlobalFastPreferences,
|
|
527
|
-
get sessionFastPreferences() { return getCursorSessionSettings().fast; },
|
|
528
|
-
getSessionCursorAgentMode: () => getCursorSessionSettings().mode,
|
|
529
|
-
getCliCursorAgentMode: () => { const mode = getCursorSessionSettings().cli.mode; return mode.kind === "valid" ? mode.mode : undefined; },
|
|
530
|
-
getCliCursorModeState: () => getCursorSessionSettings().cli.mode,
|
|
531
528
|
resetCursorModeStateForTests,
|
|
532
529
|
};
|
|
@@ -82,9 +82,6 @@ function buildCursorToolLifecycleLabelFromVisibility(visibility, apiKey) {
|
|
|
82
82
|
return undefined;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
export function buildCursorToolLifecycleLabel(toolCall, apiKey) {
|
|
86
|
-
return buildCursorToolLifecycleLabelFromVisibility(classifyCursorToolVisibility(toolCall), apiKey);
|
|
87
|
-
}
|
|
88
85
|
export function formatCursorToolLifecycleProgressText(toolCall, apiKey) {
|
|
89
86
|
const visibility = classifyCursorToolVisibility(toolCall);
|
|
90
87
|
const label = buildCursorToolLifecycleLabelFromVisibility(visibility, apiKey);
|
|
@@ -13,7 +13,9 @@ export function buildCursorToolManifestText(options = {}) {
|
|
|
13
13
|
const includePiBridgeGuidance = options.includePiBridgeGuidance !== false;
|
|
14
14
|
const lines = [
|
|
15
15
|
"Callable tool surfaces this run:",
|
|
16
|
-
|
|
16
|
+
options.nativeToolsEnabled === false
|
|
17
|
+
? "- Cursor native tools (including task/subagents): disabled (PI_CURSOR_NATIVE_TOOLS=0). MCP remains available; configured MCP depends on Cursor settings."
|
|
18
|
+
: `- Cursor host/MCP: ${CURSOR_HOST_TOOL_MANIFEST_SUMMARY}; configured MCP depends on Cursor settings.`,
|
|
17
19
|
"- Pi tool toggles affect pi tools/bridge exposure only; they do not disable Cursor host/configured MCP tools.",
|
|
18
20
|
];
|
|
19
21
|
const bridgeTools = includePiBridgeGuidance ? options.bridgeSnapshot?.tools ?? [] : [];
|
|
@@ -7,13 +7,12 @@ import { formatReplaySemSearchQuery, readCursorReplaySummaryString, summarizeRep
|
|
|
7
7
|
import { truncateCursorDisplayLine } from "./cursor-display-text.js";
|
|
8
8
|
import { getCursorTaskActivityTitle } from "./cursor-task-presentation.js";
|
|
9
9
|
import { buildCreatePlanReplaySummaryArgs, buildDeleteReplayDetailFields, buildDeleteReplaySummaryArgs, buildGenerateImageReplayDetailFields, buildGenerateImageReplaySummaryArgs, buildMcpReplaySummaryArgs, buildReadLintsReplaySummaryArgs, buildRecordScreenReplaySummaryArgs, buildSemSearchReplaySummaryArgs, buildTaskReplaySummaryArgs, buildTodoReplaySummaryArgs, buildWebFetchReplaySummaryArgs, buildWebSearchReplaySummaryArgs, } from "./cursor-replay-activity-builders.js";
|
|
10
|
-
import { CURSOR_REPLAY_SOURCE_TOOL_NAMES } from "./cursor-replay-source-names.js";
|
|
11
10
|
export const CURSOR_REPLAY_ACTIVITY_TOOL_NAME = "cursor";
|
|
12
11
|
const EMPTY_REPLAY_DETAIL_FIELDS = () => ({});
|
|
13
12
|
const COLLAPSED_REPLAY_DETAIL_FIELDS = () => ({ collapseDetailsByDefault: true });
|
|
14
13
|
const WEB_SEARCH_NAME_PATTERN = /^(?:web[-_ ]?search|search[-_ ]?web|websearch|browser[-_ ]?search)$/i;
|
|
15
14
|
const WEB_FETCH_NAME_PATTERN = /^(?:web[-_ ]?fetch|fetch[-_ ]?web|webfetch|browser[-_ ]?fetch|fetch[-_ ]?url)$/i;
|
|
16
|
-
|
|
15
|
+
const CURSOR_TOOL_PRESENTATION_SPECS = [
|
|
17
16
|
{
|
|
18
17
|
normalizedName: "read",
|
|
19
18
|
nameAliases: ["read_file"],
|
|
@@ -218,8 +217,7 @@ const WEB_KIND_BY_PATTERN = CURSOR_TOOL_PRESENTATION_SPECS.flatMap((spec) => {
|
|
|
218
217
|
return [];
|
|
219
218
|
return webNamePatterns.map((pattern) => ({ pattern, webKind }));
|
|
220
219
|
});
|
|
221
|
-
|
|
222
|
-
export function getCursorToolPresentationSpec(name) {
|
|
220
|
+
function getCursorToolPresentationSpec(name) {
|
|
223
221
|
const trimmed = name.trim();
|
|
224
222
|
if (!trimmed)
|
|
225
223
|
return undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CURSOR_REPLAY_ACTIVITY_TOOL_NAME, getCursorReplayCallSummary, getCursorToolActivityTitle, getCursorToolActivityReplaySpec, getCursorToolGenerateImageReplaySpec, } from "./cursor-tool-presentation-registry.js";
|
|
2
2
|
import { resolveCursorEditDiff } from "./cursor-edit-diff.js";
|
|
3
3
|
import { assembleCursorReplayActivityDetails, assembleCursorReplayGenerateImageDetails, CURSOR_REPLAY_UNREGISTERED_ACTIVITY_TOOL_NAME, } from "./cursor-replay-tool-details.js";
|
|
4
4
|
import { asRecord, getNumber, getString } from "./cursor-record-utils.js";
|
|
@@ -264,7 +264,6 @@ const TOOL_DISPLAY_IMPLEMENTATIONS = {
|
|
|
264
264
|
buildPiToolDisplay: (context) => buildActivityReplayDisplay("webFetch", context),
|
|
265
265
|
},
|
|
266
266
|
};
|
|
267
|
-
export const CURSOR_TOOL_DISPLAY_SPEC_KEYS = CURSOR_KNOWN_NORMALIZED_TOOL_NAMES;
|
|
268
267
|
function getToolDisplaySpec(name) {
|
|
269
268
|
if (Object.hasOwn(TOOL_DISPLAY_IMPLEMENTATIONS, name))
|
|
270
269
|
return TOOL_DISPLAY_IMPLEMENTATIONS[name];
|
package/dist/index.js
CHANGED
|
@@ -14,14 +14,35 @@ import { registerCursorFallbackIssueWarning } from "./cursor-fallback-warning.js
|
|
|
14
14
|
import { registerCursorAgentsContextDedup } from "./cursor-agents-context-registration.js";
|
|
15
15
|
import { registerCursorOverflowNormalization } from "./cursor-provider-overflow.js";
|
|
16
16
|
import { registerCursorSdkSessionProcessErrorGuard } from "./cursor-sdk-process-error-guard.js";
|
|
17
|
+
import { installCursorSdkProcessOutputFilter } from "./cursor-sdk-output-filter.js";
|
|
18
|
+
import { cursorLiveRuns } from "./cursor-provider-live-run-drain.js";
|
|
17
19
|
import { prepareCursorSessionForCompaction } from "./cursor-session-compaction-prep.js";
|
|
18
20
|
import { registerCursorUsageLedger } from "./cursor-usage-ledger.js";
|
|
19
21
|
import { registerCursorUsageCommand } from "./cursor-usage-command.js";
|
|
20
22
|
export default async function (pi) {
|
|
23
|
+
installCursorSdkProcessOutputFilter();
|
|
21
24
|
// Session cwd must register before other session_start listeners that depend on it.
|
|
22
25
|
registerCursorSessionScope(pi);
|
|
23
26
|
registerCursorUsageLedger(pi);
|
|
24
27
|
registerCursorUsageCommand(pi);
|
|
28
|
+
pi.registerCommand("cursor-abort", {
|
|
29
|
+
description: "Abort this session's pending local Cursor run without undoing completed work",
|
|
30
|
+
handler: async (_args, ctx) => {
|
|
31
|
+
const run = cursorLiveRuns.getActiveForScope(getCursorSessionScopeSnapshot(pi).scopeKey);
|
|
32
|
+
if (run && !run.disposed) {
|
|
33
|
+
if (!ctx.isIdle() && ctx.model?.provider === "cursor")
|
|
34
|
+
ctx.abort();
|
|
35
|
+
await cursorLiveRuns.release(run);
|
|
36
|
+
}
|
|
37
|
+
const message = run
|
|
38
|
+
? "Pending local Cursor run released. Retry under the current policy; already-executed work was not undone."
|
|
39
|
+
: "No pending local Cursor run in this session.";
|
|
40
|
+
if (ctx.hasUI)
|
|
41
|
+
ctx.ui.notify(message, "info");
|
|
42
|
+
else
|
|
43
|
+
process.stderr.write(`${message}\n`);
|
|
44
|
+
},
|
|
45
|
+
});
|
|
25
46
|
let fallbackIssue;
|
|
26
47
|
const registerCursorProvider = registerCursorProviderBinding(pi);
|
|
27
48
|
const setFallbackWarning = registerCursorFallbackIssueWarning(pi);
|
package/dist/model-discovery.js
CHANGED
|
@@ -41,9 +41,9 @@ function mapComparableLevel(parameter, level) {
|
|
|
41
41
|
}
|
|
42
42
|
function getThinkingLevelMap(item) {
|
|
43
43
|
const reasoningParameter = getParameter(item, "reasoning");
|
|
44
|
-
const effortParameter = getParameter(item, "effort");
|
|
44
|
+
const effortParameter = getParameter(item, "effort") ?? getParameter(item, "reasoning_effort");
|
|
45
45
|
const thinkingParameter = getParameter(item, "thinking");
|
|
46
|
-
const valueParameter = effortParameter ?? reasoningParameter ?? thinkingParameter
|
|
46
|
+
const valueParameter = effortParameter ?? reasoningParameter ?? thinkingParameter;
|
|
47
47
|
if (!valueParameter)
|
|
48
48
|
return undefined;
|
|
49
49
|
if (valueParameter.id === "thinking" && hasBooleanValues(valueParameter)) {
|
|
@@ -196,10 +196,12 @@ function applyThinkingLevel(metadata, params, level) {
|
|
|
196
196
|
const mapped = metadata.thinkingLevelMap?.[level];
|
|
197
197
|
if (mapped === undefined || mapped === null)
|
|
198
198
|
return;
|
|
199
|
+
const effortId = metadata.parameterIds.effort ? "effort" : metadata.parameterIds.reasoning_effort ? "reasoning_effort" : undefined;
|
|
199
200
|
if (level === "off") {
|
|
200
201
|
if (metadata.parameterIds.thinking && mapped === "false") {
|
|
201
202
|
setParam(params, "thinking", mapped);
|
|
202
|
-
|
|
203
|
+
if (effortId)
|
|
204
|
+
deleteParam(params, effortId);
|
|
203
205
|
return;
|
|
204
206
|
}
|
|
205
207
|
if (metadata.parameterIds.reasoning) {
|
|
@@ -207,10 +209,10 @@ function applyThinkingLevel(metadata, params, level) {
|
|
|
207
209
|
}
|
|
208
210
|
return;
|
|
209
211
|
}
|
|
210
|
-
if (
|
|
212
|
+
if (effortId) {
|
|
211
213
|
if (metadata.parameterIds.thinking)
|
|
212
214
|
setParam(params, "thinking", "true");
|
|
213
|
-
setParam(params,
|
|
215
|
+
setParam(params, effortId, mapped);
|
|
214
216
|
return;
|
|
215
217
|
}
|
|
216
218
|
if (metadata.parameterIds.reasoning) {
|
|
@@ -220,9 +222,6 @@ function applyThinkingLevel(metadata, params, level) {
|
|
|
220
222
|
if (metadata.parameterIds.thinking) {
|
|
221
223
|
setParam(params, "thinking", mapped);
|
|
222
224
|
}
|
|
223
|
-
else if (metadata.parameterIds.reasoning_effort) {
|
|
224
|
-
setParam(params, "reasoning_effort", mapped);
|
|
225
|
-
}
|
|
226
225
|
}
|
|
227
226
|
export function buildCursorModelSelection(modelId, thinkingLevel, fastEnabled) {
|
|
228
227
|
const metadata = getCursorModelMetadata(modelId);
|
|
@@ -291,7 +290,7 @@ export async function discoverModels(options = {}) {
|
|
|
291
290
|
try {
|
|
292
291
|
const { Cursor } = await loadCursorSdk();
|
|
293
292
|
options.signal?.throwIfAborted();
|
|
294
|
-
// SDK 1.0.
|
|
293
|
+
// SDK 1.0.37 CursorRequestOptions has no caller signal. A late response
|
|
295
294
|
// still cannot publish outside the native generation that requested it.
|
|
296
295
|
const models = await Cursor.models.list({ apiKey });
|
|
297
296
|
options.signal?.throwIfAborted();
|
|
@@ -325,6 +324,5 @@ export async function discoverModels(options = {}) {
|
|
|
325
324
|
}
|
|
326
325
|
}
|
|
327
326
|
export const __testUtils = {
|
|
328
|
-
parseContextWindow,
|
|
329
327
|
registerModelItems,
|
|
330
328
|
};
|
package/dist/model-list-cache.js
CHANGED
|
@@ -13,10 +13,10 @@ const TTL_ENV_VAR = "PI_CURSOR_SDK_MODEL_CACHE_TTL_MS";
|
|
|
13
13
|
function getCachePath() {
|
|
14
14
|
return join(getAgentDir(), MODEL_LIST_CACHE_FILE);
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
function isModelCacheDisabled() {
|
|
17
17
|
return parseEnvBoolean(process.env[DISABLE_ENV_VAR], false);
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
function getModelCacheTtlMs() {
|
|
20
20
|
const raw = process.env[TTL_ENV_VAR];
|
|
21
21
|
if (raw === undefined)
|
|
22
22
|
return DEFAULT_TTL_MS;
|
|
@@ -105,7 +105,8 @@ function readCacheFile() {
|
|
|
105
105
|
}
|
|
106
106
|
// Return cached models only when caching is enabled, the key matches, and the
|
|
107
107
|
// entry is within the TTL. Used on the hot startup path to skip the network.
|
|
108
|
-
export function loadFreshCachedModels(keyFingerprint
|
|
108
|
+
export function loadFreshCachedModels(keyFingerprint) {
|
|
109
|
+
const now = Date.now();
|
|
109
110
|
if (isModelCacheDisabled())
|
|
110
111
|
return undefined;
|
|
111
112
|
const ttlMs = getModelCacheTtlMs();
|
|
@@ -159,9 +160,3 @@ export function clearModelListCache() {
|
|
|
159
160
|
// Cache cleanup is best-effort; it must not break native logout.
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
|
-
export const __testUtils = {
|
|
163
|
-
getCachePath,
|
|
164
|
-
DEFAULT_TTL_MS,
|
|
165
|
-
DISABLE_ENV_VAR,
|
|
166
|
-
TTL_ENV_VAR,
|
|
167
|
-
};
|
|
@@ -71,7 +71,7 @@ Pass criteria:
|
|
|
71
71
|
|
|
72
72
|
- `node --version` reports Node 24+.
|
|
73
73
|
- `pi --version` reports official Pi 0.87.1 or the selected official-latest/current-`fitchmultz/pi` compatibility target.
|
|
74
|
-
- `npm ls` shows exact `@cursor/sdk@1.0.
|
|
74
|
+
- `npm ls` shows exact `@cursor/sdk@1.0.37`; development `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`, and `@earendil-works/pi-tui` 1.1.0 with matching lockfile-resolved Pi cohort, nested host TypeBox 1.3.27 and root validation TypeBox 1.3.36; and the bundled bridge runtime closure `@modelcontextprotocol/server@2.3.1`, `@modelcontextprotocol/hono@2.0.2`, `hono@4.13.13`, and `@hono/node-server@2.1.3`. These locked development snapshots are not qualification targets; resolve latest stable official Pi and current `fitchmultz/pi` main once per workflow run.
|
|
75
75
|
- `cursor/grok-4.6` appears in the model list.
|
|
76
76
|
- No Cursor key or auth token is printed.
|
|
77
77
|
- If neither `~/.pi/agent/auth.json` cursor auth nor `CURSOR_API_KEY` is available, stop and report the live smoke as blocked.
|
|
@@ -136,7 +136,7 @@ Pass criteria:
|
|
|
136
136
|
|
|
137
137
|
## 4. Focused visual card/color rendering check
|
|
138
138
|
|
|
139
|
-
This is a visual debug menu for changed card/color behavior requiring new live evidence. Select only the relevant category below, or reuse a batched existing platform suite; do not execute the entire list by default. It requires offscreen TUI visual inspection, not only JSONL or code review. Use Node 24+, official Pi 0.87.1 or another current compatibility target, exact `@cursor/sdk@1.0.
|
|
139
|
+
This is a visual debug menu for changed card/color behavior requiring new live evidence. Select only the relevant category below, or reuse a batched existing platform suite; do not execute the entire list by default. It requires offscreen TUI visual inspection, not only JSONL or code review. Use Node 24+, official Pi 0.87.1 or another current compatibility target, exact `@cursor/sdk@1.0.37`, a fresh temporary session dir, Cursor SDK `plan` mode, native replay enabled, and the checked-in visual runner. The runner resolves `pi` by directly walking the parent `PATH`, uses `process.execPath` for Node, and prepends that Node directory for both prereq checks and tmux launches so `#!/usr/bin/env node` shims use the validated Node. The default matrix is native replay only: native replay registration is forced on, settings sources are `none`, the pi bridge is off, overlapping built-in pi tools are not exposed, and inherited Cursor SDK event-debug artifact env is cleared. With `--event-debug`, debug capture writes to a deterministic directory under `VISUAL_DIR`.
|
|
140
140
|
|
|
141
141
|
```bash
|
|
142
142
|
VISUAL_DIR="$(mktemp -d /tmp/pi-cursor-sdk-1016-visual.XXXXXX)"
|
|
@@ -354,7 +354,7 @@ Script-enforced pass criteria:
|
|
|
354
354
|
Additional manual usage checks for provider/accounting changes:
|
|
355
355
|
|
|
356
356
|
- Each assistant message's disjoint input/cache/output components should sum to `totalTokens` and describe one coherent current context, not cumulative billed spend.
|
|
357
|
-
- In split runs, earlier tool results can remain in later current-context estimates. Fresh, attributable LOCAL SDK usage takes precedence; late raw and billed facts remain in the separate ledger without rewriting emitted messages. See [context, compaction, and Cursor usage](
|
|
357
|
+
- In split runs, earlier tool results can remain in later current-context estimates. Fresh, attributable LOCAL SDK usage takes precedence; late raw and billed facts remain in the separate ledger without rewriting emitted messages. See [context, compaction, and Cursor usage](reference.md#context-compaction-and-cursor-usage).
|
|
358
358
|
|
|
359
359
|
## 11. Standard local gates
|
|
360
360
|
|
|
@@ -391,7 +391,7 @@ Use this list to choose meaningful changed-behavior coverage, not to trigger a f
|
|
|
391
391
|
- Native replay cards beyond read, especially shell/edit/write cards, when those renderers change.
|
|
392
392
|
- Bridge question UI when `cursor_ask_question` changes.
|
|
393
393
|
- MCP timeout override behavior (3600s `callTool` default, 10s initialize/listTools default, and SDK-default unknown protocol stacks) when timeout code changes.
|
|
394
|
-
- SDK `semSearch` / `recordScreen` activity replay when those formatters change. There is no reliable local prompt that forces Cursor to call these built-in SDK tools on demand; regression is covered by `test/cursor-tool-transcript.test.ts`. Opportunistically confirm neutral `Cursor semantic search` / `Cursor screen recording` cards if a live run surfaces them.
|
|
394
|
+
- SDK `semSearch` / `recordScreen` activity replay when those formatters change. There is no reliable local prompt that forces Cursor to call these built-in SDK tools on demand; regression is covered by `test/cursor-tool-transcript-mcp-web.test.ts`. Opportunistically confirm neutral `Cursor semantic search` / `Cursor screen recording` cards if a live run surfaces them.
|
|
395
395
|
- Ambient Cursor setting-source behavior when startup filtering or local Cursor settings handling changes.
|
|
396
396
|
- Model discovery aliases/context variants when model-discovery code or Cursor SDK versions change.
|
|
397
397
|
|