@emmaneugene/pi-cursor-sdk 0.3.7 → 0.4.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 +16 -0
- package/README.md +99 -126
- package/dist/cursor-agents-context-registration.js +1 -3
- package/dist/cursor-agents-context.js +2 -2
- package/dist/cursor-config.js +2 -290
- package/dist/cursor-provider-errors.js +3 -58
- package/dist/cursor-provider-live-run-drain.js +0 -3
- package/dist/cursor-provider-run-finalizer.js +4 -7
- package/dist/cursor-provider-run-outcome.js +1 -1
- package/dist/cursor-provider-turn-finalize.js +3 -55
- package/dist/cursor-provider-turn-prepare.js +8 -144
- package/dist/cursor-provider-turn-runner.js +9 -23
- package/dist/cursor-provider-turn-send.js +8 -35
- package/dist/cursor-runtime-state.js +6 -268
- package/dist/cursor-sdk-billed-usage.js +3 -18
- package/dist/cursor-sdk-platform-package.js +88 -0
- package/dist/cursor-session-agent.js +18 -14
- package/dist/cursor-skill-tool.js +12 -22
- package/dist/cursor-state.js +5 -8
- package/dist/cursor-usage-accounting.js +1 -1
- package/docs/cursor-dogfood-checklist.md +4 -4
- package/docs/cursor-live-smoke-checklist.md +23 -23
- package/docs/cursor-model-ux-spec.md +27 -30
- package/docs/cursor-native-tool-replay.md +4 -4
- package/docs/cursor-native-tool-visual-audit.md +7 -7
- package/docs/cursor-testing-lessons.md +23 -16
- package/docs/cursor-tool-surfaces.md +2 -4
- package/docs/platform-smoke-implementation.md +5 -5
- package/docs/platform-smoke.md +27 -72
- package/package.json +3 -17
- package/platform-smoke.config.mjs +2 -1
- package/scripts/lib/local-resume-smoke-harness.mjs +0 -18
- package/scripts/platform-smoke/card-detect.mjs +1 -1
- package/scripts/platform-smoke/local-resume-runner.mjs +1 -1
- package/scripts/platform-smoke/scenarios.mjs +1 -1
- package/scripts/platform-smoke/targets.mjs +14 -5
- package/src/cursor-agents-context-registration.ts +0 -5
- package/src/cursor-agents-context.ts +1 -3
- package/src/cursor-config.ts +8 -379
- package/src/cursor-provider-errors.ts +2 -62
- package/src/cursor-provider-live-run-drain.ts +0 -3
- package/src/cursor-provider-run-finalizer.ts +4 -12
- package/src/cursor-provider-run-outcome.ts +0 -3
- package/src/cursor-provider-turn-finalize.ts +3 -61
- package/src/cursor-provider-turn-prepare.ts +8 -165
- package/src/cursor-provider-turn-runner.ts +15 -31
- package/src/cursor-provider-turn-send.ts +7 -38
- package/src/cursor-provider-turn-types.ts +9 -30
- package/src/cursor-runtime-state.ts +6 -345
- package/src/cursor-sdk-billed-usage.ts +3 -24
- package/src/cursor-sdk-platform-package.ts +106 -0
- package/src/cursor-session-agent.ts +16 -12
- package/src/cursor-skill-tool.ts +10 -26
- package/src/cursor-state.ts +5 -10
- package/src/cursor-usage-accounting.ts +1 -3
- package/dist/cursor-cloud-lifecycle.js +0 -650
- package/dist/cursor-cloud-local-state.js +0 -460
- package/dist/cursor-cloud-options.js +0 -145
- package/dist/cursor-cloud-reporting.js +0 -222
- package/dist/cursor-ripgrep-path.js +0 -27
- package/scripts/cloud-runtime-smoke.d.mts +0 -42
- package/scripts/cloud-runtime-smoke.mjs +0 -623
- package/scripts/lib/cloud-smoke-artifacts.d.mts +0 -16
- package/scripts/lib/cloud-smoke-artifacts.mjs +0 -94
- package/scripts/lib/cloud-smoke-cleanup-evidence.d.mts +0 -209
- package/scripts/lib/cloud-smoke-cleanup-evidence.mjs +0 -585
- package/scripts/lib/cloud-smoke-github.d.mts +0 -78
- package/scripts/lib/cloud-smoke-github.mjs +0 -331
- package/scripts/lib/cloud-smoke-pi-runner.d.mts +0 -42
- package/scripts/lib/cloud-smoke-pi-runner.mjs +0 -214
- package/scripts/lib/cloud-smoke-shutdown.d.mts +0 -67
- package/scripts/lib/cloud-smoke-shutdown.mjs +0 -133
- package/shared/cursor-cloud-lifecycle-constants.d.mts +0 -3
- package/shared/cursor-cloud-lifecycle-constants.mjs +0 -7
- package/src/cursor-cloud-lifecycle.ts +0 -733
- package/src/cursor-cloud-local-state.ts +0 -536
- package/src/cursor-cloud-options.ts +0 -182
- package/src/cursor-cloud-reporting.ts +0 -267
- package/src/cursor-ripgrep-path.ts +0 -32
|
@@ -1,48 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CURSOR_AUTO_REVIEW_ENV, CURSOR_CLOUD_ACK_ENV, CURSOR_CLOUD_ALLOW_LOCAL_STATE_ENV, CURSOR_CLOUD_AUTO_CREATE_PR_ENV, CURSOR_CLOUD_BRANCH_ENV, CURSOR_CLOUD_CONTEXT_ENV, CURSOR_CLOUD_DIRECT_PUSH_ENV, CURSOR_CLOUD_ENV_ENV, CURSOR_CLOUD_ENV_FROM_FILES_ENV, CURSOR_CLOUD_ENV_NAME_ENV, CURSOR_CLOUD_ENV_TYPE_ENV, CURSOR_CLOUD_REPO_ENV, CURSOR_CLOUD_SKIP_REVIEWER_REQUEST_ENV, CURSOR_LOCAL_FORCE_ENV, CURSOR_LOCAL_RESUME_ENV, CURSOR_RUNTIME_ENV, CURSOR_SANDBOX_ENV, getCursorSdkProjectConfigPath, getCursorSdkUserConfigPath, loadCursorSdkConfig, mergeCursorSdkConfigForUpdate, parseExplicitCursorCloudEnvNames, resolveCursorSdkConfig, updateCursorSdkConfig, } from "./cursor-config.js";
|
|
3
|
-
import { asRecord } from "./cursor-record-utils.js";
|
|
1
|
+
import { CURSOR_AUTO_REVIEW_ENV, CURSOR_LOCAL_FORCE_ENV, CURSOR_LOCAL_RESUME_ENV, CURSOR_SANDBOX_ENV, loadCursorSdkConfig, resolveCursorSdkConfig, } from "./cursor-config.js";
|
|
4
2
|
import { getResolvedSessionCursorHttp1Enabled } from "./cursor-http1.js";
|
|
5
3
|
import { getCursorSessionCwd, getCursorSessionProjectTrusted } from "./cursor-session-scope.js";
|
|
6
|
-
export const CURSOR_RUNTIME_ENTRY_TYPE = "cursor-runtime-state";
|
|
7
|
-
export const CURSOR_CLOUD_ACK_DISCLOSURE = [
|
|
8
|
-
"Cursor Cloud executes this work remotely.",
|
|
9
|
-
"Fresh context is used by default; prior Pi context is included only with explicit bootstrap opt-in.",
|
|
10
|
-
"Pi-local tools and the Pi bridge are unavailable, and Pi environment variables are not forwarded.",
|
|
11
|
-
"Cursor may create branches, commit, push, and open pull requests.",
|
|
12
|
-
"Cloud agents remain until you archive or delete them.",
|
|
13
|
-
"Cloud Agents run in Max Mode, are billed at Cursor API pricing, and may require spend-limit setup.",
|
|
14
|
-
].join("\n\n");
|
|
15
4
|
let cliCursorSnapshot = { config: {} };
|
|
16
5
|
let cliLocalForceConsumed = false;
|
|
17
6
|
let envLocalForceConsumed = false;
|
|
18
|
-
let sessionCursorRuntime;
|
|
19
|
-
let sessionCursorCloudAcknowledged = false;
|
|
20
|
-
function isCursorRuntimeEntryData(value) {
|
|
21
|
-
const record = asRecord(value);
|
|
22
|
-
if (!record)
|
|
23
|
-
return false;
|
|
24
|
-
return (record.runtime === "local" || record.runtime === "cloud")
|
|
25
|
-
&& (record.cloudAcknowledged === undefined || typeof record.cloudAcknowledged === "boolean");
|
|
26
|
-
}
|
|
27
|
-
function stringFlagValue(value) {
|
|
28
|
-
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
29
|
-
}
|
|
30
7
|
export function getCursorCliConfig() {
|
|
31
|
-
|
|
32
|
-
const envNames = parseExplicitCursorCloudEnvNames(cliCursorSnapshot.cloudEnvNames, "--cursor-cloud-env");
|
|
33
|
-
if (envNames)
|
|
34
|
-
config.cloud = { ...config.cloud, envNames };
|
|
35
|
-
return config;
|
|
8
|
+
return structuredClone(cliCursorSnapshot.config);
|
|
36
9
|
}
|
|
37
10
|
export function getCursorSessionConfig() {
|
|
38
11
|
const useHttp1ForAgent = getResolvedSessionCursorHttp1Enabled();
|
|
39
12
|
return {
|
|
40
|
-
...(sessionCursorRuntime
|
|
41
|
-
? {
|
|
42
|
-
runtime: sessionCursorRuntime,
|
|
43
|
-
...(sessionCursorCloudAcknowledged ? { cloud: { acknowledged: true } } : {}),
|
|
44
|
-
}
|
|
45
|
-
: {}),
|
|
46
13
|
...(useHttp1ForAgent === undefined ? {} : { local: { useHttp1ForAgent } }),
|
|
47
14
|
};
|
|
48
15
|
}
|
|
@@ -66,7 +33,6 @@ export function resolveCursorStatusRuntime(ctx) {
|
|
|
66
33
|
const config = resolveEffectiveCursorConfigForContext(ctx);
|
|
67
34
|
return {
|
|
68
35
|
kind: "valid",
|
|
69
|
-
runtime: config.runtime,
|
|
70
36
|
useHttp1ForAgent: config.local.useHttp1ForAgent,
|
|
71
37
|
};
|
|
72
38
|
}
|
|
@@ -74,15 +40,9 @@ export function resolveCursorStatusRuntime(ctx) {
|
|
|
74
40
|
return { kind: "invalid", message: error instanceof Error ? error.message : String(error) };
|
|
75
41
|
}
|
|
76
42
|
}
|
|
77
|
-
export function
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
? `${runtime.value} (source: ${runtime.source} safety cap over ${cap.cappedSource} ${cap.cappedValue})`
|
|
81
|
-
: `${runtime.value} (source: ${runtime.source})`;
|
|
82
|
-
}
|
|
83
|
-
export function formatCursorStatus(runtime, fast, mode, useHttp1ForAgent = false) {
|
|
84
|
-
const parts = [`cursor:${runtime}`, fast === true ? "fast:on" : fast === false ? "fast:off" : "fast:n/a"];
|
|
85
|
-
if (runtime === "local" && useHttp1ForAgent)
|
|
43
|
+
export function formatCursorStatus(fast, mode, useHttp1ForAgent = false) {
|
|
44
|
+
const parts = ["cursor", fast === true ? "fast:on" : fast === false ? "fast:off" : "fast:n/a"];
|
|
45
|
+
if (useHttp1ForAgent)
|
|
86
46
|
parts.push("http1");
|
|
87
47
|
if (mode === "invalid")
|
|
88
48
|
parts.push("mode invalid");
|
|
@@ -107,40 +67,7 @@ export function consumeCursorLocalForceOverride(resolved) {
|
|
|
107
67
|
}
|
|
108
68
|
return false;
|
|
109
69
|
}
|
|
110
|
-
export function restoreSessionCursorRuntimeState(branch) {
|
|
111
|
-
sessionCursorRuntime = undefined;
|
|
112
|
-
sessionCursorCloudAcknowledged = false;
|
|
113
|
-
for (const entry of branch) {
|
|
114
|
-
if (entry.type !== "custom" || entry.customType !== CURSOR_RUNTIME_ENTRY_TYPE)
|
|
115
|
-
continue;
|
|
116
|
-
if (isCursorRuntimeEntryData(entry.data)) {
|
|
117
|
-
sessionCursorRuntime = entry.data.runtime;
|
|
118
|
-
sessionCursorCloudAcknowledged ||= entry.data.cloudAcknowledged === true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
70
|
export function restoreCursorCliState(pi) {
|
|
123
|
-
const runtime = stringFlagValue(pi.getFlag("cursor-runtime"));
|
|
124
|
-
const repo = stringFlagValue(pi.getFlag("cursor-cloud-repo"));
|
|
125
|
-
const branch = stringFlagValue(pi.getFlag("cursor-cloud-branch"));
|
|
126
|
-
const contextHandoff = stringFlagValue(pi.getFlag("cursor-cloud-context"));
|
|
127
|
-
const environmentType = stringFlagValue(pi.getFlag("cursor-cloud-env-type"));
|
|
128
|
-
const environmentName = stringFlagValue(pi.getFlag("cursor-cloud-env-name"));
|
|
129
|
-
const cloudEnvNames = stringFlagValue(pi.getFlag("cursor-cloud-env"));
|
|
130
|
-
const cloud = {
|
|
131
|
-
...(repo ? { repo } : {}),
|
|
132
|
-
...(branch ? { branch } : {}),
|
|
133
|
-
...(contextHandoff ? { contextHandoff } : {}),
|
|
134
|
-
...(pi.getFlag("cursor-cloud-direct-push") === true ? { directPush: true } : {}),
|
|
135
|
-
...(pi.getFlag("cursor-cloud-auto-create-pr") === true ? { autoCreatePR: true } : {}),
|
|
136
|
-
...(pi.getFlag("cursor-cloud-skip-reviewer-request") === true ? { skipReviewerRequest: true } : {}),
|
|
137
|
-
...(pi.getFlag("cursor-cloud-allow-local-state") === true ? { allowLocalState: true } : {}),
|
|
138
|
-
...(pi.getFlag("cursor-cloud-env-from-files") === true ? { envFromFiles: true } : {}),
|
|
139
|
-
...(environmentType || environmentName
|
|
140
|
-
? { environment: { ...(environmentType ? { type: environmentType } : {}), ...(environmentName ? { name: environmentName } : {}) } }
|
|
141
|
-
: {}),
|
|
142
|
-
...(pi.getFlag("cursor-cloud-ack") === true ? { acknowledged: true } : {}),
|
|
143
|
-
};
|
|
144
71
|
const local = {
|
|
145
72
|
...(pi.getFlag("cursor-auto-review") === true ? { autoReview: true } : {}),
|
|
146
73
|
...(pi.getFlag("cursor-sandbox") === true ? { sandboxOptions: { enabled: true } } : {}),
|
|
@@ -153,88 +80,11 @@ export function restoreCursorCliState(pi) {
|
|
|
153
80
|
};
|
|
154
81
|
cliCursorSnapshot = {
|
|
155
82
|
config: {
|
|
156
|
-
...(runtime ? { runtime } : {}),
|
|
157
|
-
...(Object.keys(cloud).length ? { cloud } : {}),
|
|
158
83
|
...(Object.keys(local).length ? { local } : {}),
|
|
159
84
|
},
|
|
160
|
-
...(cloudEnvNames ? { cloudEnvNames } : {}),
|
|
161
85
|
};
|
|
162
86
|
}
|
|
163
|
-
function
|
|
164
|
-
const acknowledged = sessionCursorCloudAcknowledged || cloudAcknowledged;
|
|
165
|
-
pi.appendEntry(CURSOR_RUNTIME_ENTRY_TYPE, {
|
|
166
|
-
runtime,
|
|
167
|
-
...(acknowledged ? { cloudAcknowledged: true } : {}),
|
|
168
|
-
});
|
|
169
|
-
sessionCursorRuntime = runtime;
|
|
170
|
-
sessionCursorCloudAcknowledged = acknowledged;
|
|
171
|
-
}
|
|
172
|
-
function registerCursorRuntimeFlags(pi) {
|
|
173
|
-
pi.registerFlag("cursor-runtime", {
|
|
174
|
-
description: `Select Cursor runtime for this run: local or cloud (or set ${CURSOR_RUNTIME_ENV})`,
|
|
175
|
-
type: "string",
|
|
176
|
-
default: "",
|
|
177
|
-
});
|
|
178
|
-
pi.registerFlag("cursor-cloud-repo", {
|
|
179
|
-
description: `Set Cursor cloud repository URL for this run (or set ${CURSOR_CLOUD_REPO_ENV})`,
|
|
180
|
-
type: "string",
|
|
181
|
-
default: "",
|
|
182
|
-
});
|
|
183
|
-
pi.registerFlag("cursor-cloud-branch", {
|
|
184
|
-
description: `Set Cursor cloud branch/ref for this run (or set ${CURSOR_CLOUD_BRANCH_ENV})`,
|
|
185
|
-
type: "string",
|
|
186
|
-
default: "",
|
|
187
|
-
});
|
|
188
|
-
pi.registerFlag("cursor-cloud-context", {
|
|
189
|
-
description: `Set Cursor cloud context handoff: never, fresh, or bootstrap (or set ${CURSOR_CLOUD_CONTEXT_ENV})`,
|
|
190
|
-
type: "string",
|
|
191
|
-
default: "",
|
|
192
|
-
});
|
|
193
|
-
pi.registerFlag("cursor-cloud-direct-push", {
|
|
194
|
-
description: `Allow Cursor cloud direct push for this run (or set ${CURSOR_CLOUD_DIRECT_PUSH_ENV}=1)`,
|
|
195
|
-
type: "boolean",
|
|
196
|
-
default: false,
|
|
197
|
-
});
|
|
198
|
-
pi.registerFlag("cursor-cloud-auto-create-pr", {
|
|
199
|
-
description: `Ask Cursor cloud to create a pull request for this run (or set ${CURSOR_CLOUD_AUTO_CREATE_PR_ENV}=1)`,
|
|
200
|
-
type: "boolean",
|
|
201
|
-
default: false,
|
|
202
|
-
});
|
|
203
|
-
pi.registerFlag("cursor-cloud-skip-reviewer-request", {
|
|
204
|
-
description: `Ask Cursor cloud not to request you as a reviewer for this run (or set ${CURSOR_CLOUD_SKIP_REVIEWER_REQUEST_ENV}=1)`,
|
|
205
|
-
type: "boolean",
|
|
206
|
-
default: false,
|
|
207
|
-
});
|
|
208
|
-
pi.registerFlag("cursor-cloud-allow-local-state", {
|
|
209
|
-
description: `Allow Cursor cloud to proceed with local-only state for this run (or set ${CURSOR_CLOUD_ALLOW_LOCAL_STATE_ENV}=1)`,
|
|
210
|
-
type: "boolean",
|
|
211
|
-
default: false,
|
|
212
|
-
});
|
|
213
|
-
pi.registerFlag("cursor-cloud-env", {
|
|
214
|
-
description: `Reserved Cursor cloud env var names; env forwarding is not implemented yet (or set ${CURSOR_CLOUD_ENV_ENV})`,
|
|
215
|
-
type: "string",
|
|
216
|
-
default: "",
|
|
217
|
-
});
|
|
218
|
-
pi.registerFlag("cursor-cloud-env-from-files", {
|
|
219
|
-
description: `Reserved Cursor cloud env-file forwarding flag; not implemented yet (or set ${CURSOR_CLOUD_ENV_FROM_FILES_ENV}=1)`,
|
|
220
|
-
type: "boolean",
|
|
221
|
-
default: false,
|
|
222
|
-
});
|
|
223
|
-
pi.registerFlag("cursor-cloud-env-type", {
|
|
224
|
-
description: `Select Cursor-managed cloud environment type: cloud, pool, or machine (or set ${CURSOR_CLOUD_ENV_TYPE_ENV})`,
|
|
225
|
-
type: "string",
|
|
226
|
-
default: "",
|
|
227
|
-
});
|
|
228
|
-
pi.registerFlag("cursor-cloud-env-name", {
|
|
229
|
-
description: `Select Cursor-managed cloud environment name (or set ${CURSOR_CLOUD_ENV_NAME_ENV})`,
|
|
230
|
-
type: "string",
|
|
231
|
-
default: "",
|
|
232
|
-
});
|
|
233
|
-
pi.registerFlag("cursor-cloud-ack", {
|
|
234
|
-
description: `Acknowledge first-use Cursor cloud runtime risks for this run (or set ${CURSOR_CLOUD_ACK_ENV}=1)`,
|
|
235
|
-
type: "boolean",
|
|
236
|
-
default: false,
|
|
237
|
-
});
|
|
87
|
+
export function registerCursorLocalRuntimeFlags(pi) {
|
|
238
88
|
pi.registerFlag("cursor-auto-review", {
|
|
239
89
|
description: `Enable Cursor SDK local Auto-review for this run (or set ${CURSOR_AUTO_REVIEW_ENV}=1)`,
|
|
240
90
|
type: "boolean",
|
|
@@ -261,120 +111,8 @@ function registerCursorRuntimeFlags(pi) {
|
|
|
261
111
|
default: false,
|
|
262
112
|
});
|
|
263
113
|
}
|
|
264
|
-
async function confirmCloudAcknowledgement(ctx, alreadyAcknowledged) {
|
|
265
|
-
if (alreadyAcknowledged)
|
|
266
|
-
return true;
|
|
267
|
-
if (!ctx.hasUI) {
|
|
268
|
-
ctx.ui.notify(`Cursor cloud runtime requires first-use acknowledgement. Pass --cursor-cloud-ack or set ${CURSOR_CLOUD_ACK_ENV}=1, then retry.`, "error");
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
const confirmed = await ctx.ui.confirm("Enable Cursor Cloud runtime?", CURSOR_CLOUD_ACK_DISCLOSURE);
|
|
272
|
-
if (!confirmed)
|
|
273
|
-
ctx.ui.notify("Cursor cloud runtime change cancelled; no settings were written.", "info");
|
|
274
|
-
return confirmed;
|
|
275
|
-
}
|
|
276
|
-
function registerCursorRuntimeCommand(pi, refreshStatus) {
|
|
277
|
-
pi.registerCommand("cursor-runtime", {
|
|
278
|
-
description: "Set Cursor runtime for this session: local or cloud",
|
|
279
|
-
handler: async (args, ctx) => {
|
|
280
|
-
const usage = "Usage: /cursor-runtime local|cloud [--save-user|--save-project]";
|
|
281
|
-
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
282
|
-
const raw = tokens[0];
|
|
283
|
-
const saveUser = tokens.includes("--save-user");
|
|
284
|
-
const saveProject = tokens.includes("--save-project");
|
|
285
|
-
const extra = tokens.slice(1).filter((token) => token !== "--save-user" && token !== "--save-project");
|
|
286
|
-
const currentResolution = resolveCursorStatusRuntime(ctx);
|
|
287
|
-
if (!raw) {
|
|
288
|
-
ctx.ui.notify(currentResolution.kind === "invalid"
|
|
289
|
-
? `${currentResolution.message} ${usage}`
|
|
290
|
-
: `Cursor runtime is ${formatResolvedCursorRuntime(currentResolution.runtime)}. ${usage}`, currentResolution.kind === "invalid" ? "error" : "info");
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
if ((raw !== "local" && raw !== "cloud") || extra.length > 0 || (saveUser && saveProject)) {
|
|
294
|
-
ctx.ui.notify(`Invalid Cursor runtime arguments. ${usage}`, "error");
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
if (currentResolution.kind === "invalid") {
|
|
298
|
-
ctx.ui.notify(`${currentResolution.message} Fix the explicit override before changing the session runtime.`, "error");
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
if (saveProject && (getCursorSessionCwd() !== ctx.cwd || !getCursorSessionProjectTrusted())) {
|
|
302
|
-
ctx.ui.notify("Cannot save Cursor project config without explicit project-trust provenance. Ensure .pi/settings.json or another Pi project resource exists, trust the project, then restart pi; or restart with --approve. Project-local package installs must use --approve on every run that reads or writes .pi/cursor-sdk.json.", "error");
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
const cloudAcknowledged = raw === "cloud" && await confirmCloudAcknowledgement(ctx, resolveEffectiveCursorConfigForContext(ctx).cloud.acknowledged.value);
|
|
306
|
-
if (raw === "cloud" && !cloudAcknowledged)
|
|
307
|
-
return;
|
|
308
|
-
if (saveUser || saveProject) {
|
|
309
|
-
try {
|
|
310
|
-
if (saveUser) {
|
|
311
|
-
updateCursorSdkConfig(getCursorSdkUserConfigPath(), (current) => mergeCursorSdkConfigForUpdate(current, {
|
|
312
|
-
runtime: raw,
|
|
313
|
-
...(cloudAcknowledged ? { cloud: { acknowledged: true } } : {}),
|
|
314
|
-
}), { newFileMode: 0o600 });
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
updateCursorSdkConfig(getCursorSdkProjectConfigPath(ctx.cwd), (current) => mergeCursorSdkConfigForUpdate(current, { runtime: raw }));
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
catch (error) {
|
|
321
|
-
const effectiveResolution = resolveCursorStatusRuntime(ctx);
|
|
322
|
-
refreshStatus(ctx);
|
|
323
|
-
const effective = effectiveResolution.kind === "valid"
|
|
324
|
-
? ` Effective runtime remains ${formatResolvedCursorRuntime(effectiveResolution.runtime)}.`
|
|
325
|
-
: ` ${effectiveResolution.message}`;
|
|
326
|
-
ctx.ui.notify(`Failed to save Cursor runtime preference to ${saveUser ? "user" : "project"} config: ${error instanceof Error ? error.message : String(error)}.${effective}`, "error");
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
try {
|
|
331
|
-
persistCursorRuntimePreference(pi, raw, cloudAcknowledged);
|
|
332
|
-
}
|
|
333
|
-
catch (error) {
|
|
334
|
-
const effectiveResolution = resolveCursorStatusRuntime(ctx);
|
|
335
|
-
refreshStatus(ctx);
|
|
336
|
-
const effective = effectiveResolution.kind === "valid"
|
|
337
|
-
? ` Effective runtime is ${formatResolvedCursorRuntime(effectiveResolution.runtime)}.`
|
|
338
|
-
: ` ${effectiveResolution.message}`;
|
|
339
|
-
const persisted = saveUser
|
|
340
|
-
? "User config was saved, but persisting the session runtime entry failed."
|
|
341
|
-
: saveProject
|
|
342
|
-
? "Project config was saved, but persisting the session runtime entry failed."
|
|
343
|
-
: "Persisting the session runtime entry failed.";
|
|
344
|
-
ctx.ui.notify(`${persisted} ${error instanceof Error ? error.message : String(error)}.${effective}`, "error");
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
const effectiveResolution = resolveCursorStatusRuntime(ctx);
|
|
348
|
-
refreshStatus(ctx);
|
|
349
|
-
const saved = saveUser
|
|
350
|
-
? " Saved to user config."
|
|
351
|
-
: saveProject
|
|
352
|
-
? " Saved to project config; cloud acknowledgement remains session/user-scoped."
|
|
353
|
-
: "";
|
|
354
|
-
const effective = effectiveResolution.kind === "valid"
|
|
355
|
-
? ` Effective runtime is ${formatResolvedCursorRuntime(effectiveResolution.runtime)}.`
|
|
356
|
-
: ` ${effectiveResolution.message}`;
|
|
357
|
-
ctx.ui.notify(raw === "cloud"
|
|
358
|
-
? `Cursor runtime request saved for this session and cloud risk acknowledged.${effective}${saved}`
|
|
359
|
-
: `Cursor runtime request saved for this session.${effective}${saved}`, "info");
|
|
360
|
-
},
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
export function registerCursorCloudRuntimeControls(pi, options) {
|
|
364
|
-
registerCursorCloudLifecycleLedger(pi);
|
|
365
|
-
registerCursorRuntimeFlags(pi);
|
|
366
|
-
registerCursorRuntimeCommand(pi, options.refreshStatus);
|
|
367
|
-
pi.registerCommand("cursor-cloud", {
|
|
368
|
-
description: "List, archive, or delete recorded Cursor cloud agents for this session branch",
|
|
369
|
-
handler: async (args, ctx) => {
|
|
370
|
-
await runCursorCloudLifecycleCommand(pi, args, ctx);
|
|
371
|
-
},
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
114
|
export function resetCursorRuntimeStateForTests() {
|
|
375
115
|
cliCursorSnapshot = { config: {} };
|
|
376
116
|
cliLocalForceConsumed = false;
|
|
377
117
|
envLocalForceConsumed = false;
|
|
378
|
-
sessionCursorRuntime = undefined;
|
|
379
|
-
sessionCursorCloudAcknowledged = false;
|
|
380
118
|
}
|
|
@@ -4,9 +4,6 @@ const BILLED_USAGE_TIMEOUT_MS = 5000;
|
|
|
4
4
|
// ponytail: process-lifetime watermark of billed usage UUIDs per agentId; reset on process exit.
|
|
5
5
|
// Upgrade to session-scoped storage if multi-day processes retain enough agent IDs to matter.
|
|
6
6
|
const seenBilledRunIdsByAgent = new Map();
|
|
7
|
-
export function isCursorSdkClientMintedRunId(runId) {
|
|
8
|
-
return runId.startsWith("run-");
|
|
9
|
-
}
|
|
10
7
|
export function sumCursorSdkTurnUsage(usages) {
|
|
11
8
|
if (usages.length === 0)
|
|
12
9
|
return undefined;
|
|
@@ -49,31 +46,19 @@ export function selectCursorBilledTurnUsage(agentUsage, options) {
|
|
|
49
46
|
const usage = readCursorSdkTurnUsage(record?.usage);
|
|
50
47
|
return runId && usage ? [{ runId, usage }] : [];
|
|
51
48
|
});
|
|
52
|
-
if (options.runtime === "cloud" && options.runId) {
|
|
53
|
-
const match = runs.find((run) => run.runId === options.runId);
|
|
54
|
-
return match ? { turn: match.usage, runIds: [match.runId] } : { runIds: [] };
|
|
55
|
-
}
|
|
56
49
|
const unseen = runs.filter((run) => !options.seenRunIds?.has(run.runId));
|
|
57
50
|
return { turn: sumCursorSdkTurnUsage(unseen.map((run) => run.usage)), runIds: unseen.map((run) => run.runId) };
|
|
58
51
|
}
|
|
59
|
-
export async function fetchCursorSdkAgentUsage(agent
|
|
52
|
+
export async function fetchCursorSdkAgentUsage(agent) {
|
|
60
53
|
if (typeof agent.getUsage !== "function")
|
|
61
54
|
return undefined;
|
|
62
|
-
|
|
63
|
-
? { runId: options.runId }
|
|
64
|
-
: undefined;
|
|
65
|
-
return withTimeout(Promise.resolve(agent.getUsage(query)));
|
|
55
|
+
return withTimeout(Promise.resolve(agent.getUsage()));
|
|
66
56
|
}
|
|
67
57
|
export async function attachCursorSdkBilledTurnUsage(options) {
|
|
68
|
-
const agentUsage = await fetchCursorSdkAgentUsage(options.agent
|
|
69
|
-
runtime: options.runtime,
|
|
70
|
-
runId: options.runId,
|
|
71
|
-
});
|
|
58
|
+
const agentUsage = await fetchCursorSdkAgentUsage(options.agent);
|
|
72
59
|
if (!agentUsage)
|
|
73
60
|
return {};
|
|
74
61
|
const selected = selectCursorBilledTurnUsage(agentUsage, {
|
|
75
|
-
runtime: options.runtime,
|
|
76
|
-
runId: options.runtime === "cloud" ? options.runId : undefined,
|
|
77
62
|
seenRunIds: peekCursorBilledUsageRunIds(options.agentId),
|
|
78
63
|
});
|
|
79
64
|
rememberCursorBilledUsageRunIds(options.agentId, selected.runIds);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { accessSync, constants, existsSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, isAbsolute, join } from "node:path";
|
|
4
|
+
const RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
5
|
+
const TREE_SITTER_VENDOR_ENV = "CURSOR_TREE_SITTER_VENDOR_DIR";
|
|
6
|
+
function cursorSdkPlatformPackageName() {
|
|
7
|
+
return `@cursor/sdk-${process.platform}-${process.arch}`;
|
|
8
|
+
}
|
|
9
|
+
function resolveCursorSdkPlatformPackageDir(fromModuleUrl = import.meta.url) {
|
|
10
|
+
try {
|
|
11
|
+
const require = createRequire(fromModuleUrl);
|
|
12
|
+
const sdkEntry = require.resolve("@cursor/sdk");
|
|
13
|
+
return dirname(require.resolve(`${cursorSdkPlatformPackageName()}/package.json`, {
|
|
14
|
+
paths: [dirname(sdkEntry)],
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function resolveCursorSdkPlatformBinary(binaryName, fromModuleUrl = import.meta.url) {
|
|
22
|
+
try {
|
|
23
|
+
const packageDirectory = resolveCursorSdkPlatformPackageDir(fromModuleUrl);
|
|
24
|
+
if (!packageDirectory)
|
|
25
|
+
return undefined;
|
|
26
|
+
const binaryPath = join(packageDirectory, "bin", binaryName);
|
|
27
|
+
accessSync(binaryPath, constants.X_OK);
|
|
28
|
+
return binaryPath;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function resolveBundledCursorRipgrepPath(fromModuleUrl = import.meta.url) {
|
|
35
|
+
return resolveCursorSdkPlatformBinary(process.platform === "win32" ? "rg.exe" : "rg", fromModuleUrl);
|
|
36
|
+
}
|
|
37
|
+
export function ensureCursorRipgrepPath() {
|
|
38
|
+
const configuredPath = process.env[RIPGREP_ENV];
|
|
39
|
+
if (configuredPath && isAbsolute(configuredPath))
|
|
40
|
+
return configuredPath;
|
|
41
|
+
const bundledPath = resolveBundledCursorRipgrepPath();
|
|
42
|
+
if (bundledPath)
|
|
43
|
+
process.env[RIPGREP_ENV] = bundledPath;
|
|
44
|
+
return bundledPath;
|
|
45
|
+
}
|
|
46
|
+
export function resolveBundledCursorTreeSitterVendorDir(fromModuleUrl = import.meta.url) {
|
|
47
|
+
const packageDirectory = resolveCursorSdkPlatformPackageDir(fromModuleUrl);
|
|
48
|
+
if (!packageDirectory)
|
|
49
|
+
return undefined;
|
|
50
|
+
const vendorDir = join(packageDirectory, "vendor");
|
|
51
|
+
if (!existsSync(join(vendorDir, "tree-sitter", "index.js")))
|
|
52
|
+
return undefined;
|
|
53
|
+
return vendorDir;
|
|
54
|
+
}
|
|
55
|
+
export function ensureCursorTreeSitterVendorDir() {
|
|
56
|
+
const configuredPath = process.env[TREE_SITTER_VENDOR_ENV];
|
|
57
|
+
if (configuredPath && isAbsolute(configuredPath))
|
|
58
|
+
return configuredPath;
|
|
59
|
+
const bundledPath = resolveBundledCursorTreeSitterVendorDir();
|
|
60
|
+
if (bundledPath)
|
|
61
|
+
process.env[TREE_SITTER_VENDOR_ENV] = bundledPath;
|
|
62
|
+
return bundledPath;
|
|
63
|
+
}
|
|
64
|
+
export function resolveBundledCursorSandboxPath(fromModuleUrl = import.meta.url) {
|
|
65
|
+
return resolveCursorSdkPlatformBinary(process.platform === "win32" ? "cursorsandbox.exe" : "cursorsandbox", fromModuleUrl);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The SDK finds `cursorsandbox` by walking from `process.argv[1]`, not from
|
|
69
|
+
* `require.resolve`. Point that walk at the installed platform package for the
|
|
70
|
+
* duration of local `Agent.create` / `Agent.resume`.
|
|
71
|
+
*/
|
|
72
|
+
export async function runWithCursorSdkPlatformPackageVisible(run, fromModuleUrl = import.meta.url) {
|
|
73
|
+
const packageDirectory = resolveCursorSdkPlatformPackageDir(fromModuleUrl);
|
|
74
|
+
if (!packageDirectory)
|
|
75
|
+
return run();
|
|
76
|
+
const hostEntry = join(packageDirectory, "package.json");
|
|
77
|
+
if (!existsSync(hostEntry))
|
|
78
|
+
return run();
|
|
79
|
+
const previousArgv1 = process.argv[1];
|
|
80
|
+
process.argv[1] = hostEntry;
|
|
81
|
+
try {
|
|
82
|
+
return await run();
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
if (process.argv[1] === hostEntry)
|
|
86
|
+
process.argv[1] = previousArgv1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -4,6 +4,7 @@ import { computeCursorContextFingerprint } from "./context.js";
|
|
|
4
4
|
import { getCursorSessionFile, getCursorSessionScopeGeneration, getCursorSessionScopeKey } from "./cursor-session-scope.js";
|
|
5
5
|
import { getMatchingCursorSessionAgentResumeHandle, persistCursorSessionAgentResumeHandle, } from "./cursor-session-agent-resume.js";
|
|
6
6
|
import { loadCursorSdk } from "./cursor-sdk-runtime.js";
|
|
7
|
+
import { runWithCursorSdkPlatformPackageVisible } from "./cursor-sdk-platform-package.js";
|
|
7
8
|
import { cursorSessionStoreIdentitiesEqual, openCursorSessionStore, openCursorSessionStoreForScope, } from "./cursor-session-store.js";
|
|
8
9
|
export const CURSOR_LOCAL_AGENT_IDLE_MS = 5 * 60 * 1000;
|
|
9
10
|
class SessionCursorAgentCreationSupersededError extends Error {
|
|
@@ -330,22 +331,25 @@ async function createSessionAgentEntry(scopeKey, persistentStore, instanceId, se
|
|
|
330
331
|
let agent;
|
|
331
332
|
let effectiveSendState = sendState;
|
|
332
333
|
let resumed = false;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
334
|
+
await runWithCursorSdkPlatformPackageVisible(async () => {
|
|
335
|
+
if (resumeHandle && resumeAttemptAllowed && resumeAgent) {
|
|
336
|
+
try {
|
|
337
|
+
agent = await resumeAgent(resumeHandle.agentId, buildAgentOptions());
|
|
338
|
+
effectiveSendState = { ...resumeHandle.sendState };
|
|
339
|
+
resumed = true;
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
if (persistentStore)
|
|
343
|
+
resumeNotice = LOCAL_RESUME_FALLBACK_NOTICE;
|
|
344
|
+
const currentStore = sessionStore;
|
|
345
|
+
if (currentStore && !cursorSessionStoreIdentitiesEqual(currentStore.identity, identities.sessionStore)) {
|
|
346
|
+
await currentStore.dispose().catch(() => undefined);
|
|
347
|
+
sessionStore = await openCursorSessionStore(params.cwd, identities.sessionStore);
|
|
348
|
+
}
|
|
345
349
|
}
|
|
346
350
|
}
|
|
347
|
-
|
|
348
|
-
|
|
351
|
+
agent ??= await createAgent(buildAgentOptions());
|
|
352
|
+
});
|
|
349
353
|
if (!agent)
|
|
350
354
|
throw new Error("Cursor SDK agent creation returned no agent");
|
|
351
355
|
if (!sessionStore)
|
|
@@ -5,7 +5,6 @@ import { arePiToolsDisabled } from "./cursor-active-tools.js";
|
|
|
5
5
|
import { isCursorModel } from "./cursor-model.js";
|
|
6
6
|
import { registerCursorModelLifecycle } from "./cursor-model-lifecycle.js";
|
|
7
7
|
import { resolveCursorPiToolBridgeEnabled } from "./cursor-pi-tool-bridge-env.js";
|
|
8
|
-
import { resolveEffectiveCursorConfigForContext } from "./cursor-runtime-state.js";
|
|
9
8
|
export const CURSOR_ACTIVATE_SKILL_TOOL_NAME = "cursor_activate_skill";
|
|
10
9
|
export const CURSOR_ACTIVATE_SKILL_MCP_NAME = "pi__cursor_activate_skill";
|
|
11
10
|
const AVAILABLE_SKILLS_SECTION_PATTERN = /\n\nThe following skills provide specialized instructions for specific tasks\.[\s\S]*?<\/available_skills>/;
|
|
@@ -29,15 +28,12 @@ function setCurrentSkills(skills) {
|
|
|
29
28
|
function getAvailableSkillNames() {
|
|
30
29
|
return [...currentSkillsByName.keys()].sort();
|
|
31
30
|
}
|
|
32
|
-
function
|
|
33
|
-
return
|
|
31
|
+
function shouldExposeSkillTool(model) {
|
|
32
|
+
return isCursorModel(model) && resolveCursorPiToolBridgeEnabled() && currentSkillsByName.size > 0;
|
|
34
33
|
}
|
|
35
|
-
function
|
|
36
|
-
return runtime === "local" && isCursorModel(model) && resolveCursorPiToolBridgeEnabled() && currentSkillsByName.size > 0;
|
|
37
|
-
}
|
|
38
|
-
function syncCursorSkillToolForModel(pi, model, runtime) {
|
|
34
|
+
function syncCursorSkillToolForModel(pi, model) {
|
|
39
35
|
const activeToolNames = new Set(pi.getActiveTools());
|
|
40
|
-
const shouldBeActive = !arePiToolsDisabled(pi) && shouldExposeSkillTool(model
|
|
36
|
+
const shouldBeActive = !arePiToolsDisabled(pi) && shouldExposeSkillTool(model);
|
|
41
37
|
const alreadyActive = activeToolNames.has(CURSOR_ACTIVATE_SKILL_TOOL_NAME);
|
|
42
38
|
if (shouldBeActive === alreadyActive)
|
|
43
39
|
return;
|
|
@@ -71,11 +67,9 @@ export function formatCursorSkillsForPrompt(skills) {
|
|
|
71
67
|
lines.push("</available_skills>");
|
|
72
68
|
return lines.join("\n");
|
|
73
69
|
}
|
|
74
|
-
export function resolveCursorSkillSystemPrompt(systemPrompt, model, systemPromptOptions
|
|
70
|
+
export function resolveCursorSkillSystemPrompt(systemPrompt, model, systemPromptOptions) {
|
|
75
71
|
if (!isCursorModel(model))
|
|
76
72
|
return systemPrompt;
|
|
77
|
-
if (runtime === "cloud")
|
|
78
|
-
return systemPrompt.replace(AVAILABLE_SKILLS_SECTION_PATTERN, "");
|
|
79
73
|
const skills = getVisibleSkills(systemPromptOptions?.skills);
|
|
80
74
|
if (skills.length === 0)
|
|
81
75
|
return systemPrompt;
|
|
@@ -186,9 +180,9 @@ export function registerCursorSkillTool(pi) {
|
|
|
186
180
|
}
|
|
187
181
|
},
|
|
188
182
|
});
|
|
189
|
-
const clearSkillsAndSync = (model
|
|
183
|
+
const clearSkillsAndSync = (model) => {
|
|
190
184
|
setCurrentSkills([]);
|
|
191
|
-
syncCursorSkillToolForModel(pi, model
|
|
185
|
+
syncCursorSkillToolForModel(pi, model);
|
|
192
186
|
};
|
|
193
187
|
registerCursorModelLifecycle(pi, {
|
|
194
188
|
sessionStart: (_event, ctx) => {
|
|
@@ -198,23 +192,19 @@ export function registerCursorSkillTool(pi) {
|
|
|
198
192
|
clearSkillsAndSync(event.model);
|
|
199
193
|
},
|
|
200
194
|
turnStart: (_event, ctx) => {
|
|
201
|
-
|
|
202
|
-
const runtime = resolveEffectiveRuntimeForSkillLifecycle(cursorModel, ctx);
|
|
203
|
-
if (!cursorModel || runtime === "cloud")
|
|
195
|
+
if (!isCursorModel(ctx.model))
|
|
204
196
|
setCurrentSkills([]);
|
|
205
|
-
syncCursorSkillToolForModel(pi, ctx.model
|
|
197
|
+
syncCursorSkillToolForModel(pi, ctx.model);
|
|
206
198
|
},
|
|
207
199
|
beforeAgentStart: (event, ctx) => {
|
|
208
|
-
|
|
209
|
-
const runtime = resolveEffectiveRuntimeForSkillLifecycle(cursorModel, ctx);
|
|
210
|
-
if (cursorModel && runtime === "local") {
|
|
200
|
+
if (isCursorModel(ctx.model)) {
|
|
211
201
|
setCurrentSkills(event.systemPromptOptions?.skills);
|
|
212
202
|
}
|
|
213
203
|
else {
|
|
214
204
|
setCurrentSkills([]);
|
|
215
205
|
}
|
|
216
|
-
syncCursorSkillToolForModel(pi, ctx.model
|
|
217
|
-
const resolved = resolveCursorSkillSystemPrompt(event.systemPrompt, ctx.model, event.systemPromptOptions
|
|
206
|
+
syncCursorSkillToolForModel(pi, ctx.model);
|
|
207
|
+
const resolved = resolveCursorSkillSystemPrompt(event.systemPrompt, ctx.model, event.systemPromptOptions);
|
|
218
208
|
if (resolved === event.systemPrompt)
|
|
219
209
|
return undefined;
|
|
220
210
|
return { systemPrompt: resolved };
|
package/dist/cursor-state.js
CHANGED
|
@@ -10,7 +10,7 @@ import { getCursorSessionScopeKey } from "./cursor-session-scope.js";
|
|
|
10
10
|
import { refreshSessionCursorAgentConfig } from "./cursor-session-agent.js";
|
|
11
11
|
import { getCursorModelMetadata } from "./model-discovery.js";
|
|
12
12
|
import { buildCursorBridgeExcludeToolNames, cursorFastDefaultsFromConfig, getCursorSdkUserConfigPath, loadCursorSdkUserConfig, mergeCursorSdkConfigForUpdate, resolveCursorFastDefault, updateCursorSdkConfig, } from "./cursor-config.js";
|
|
13
|
-
import {
|
|
13
|
+
import { formatCursorStatus, registerCursorLocalRuntimeFlags, resetCursorRuntimeStateForTests, resolveCursorStatusRuntime, resolveEffectiveCursorConfigForContext, restoreCursorCliState, } from "./cursor-runtime-state.js";
|
|
14
14
|
export { consumeCursorLocalForceOverride, getCursorCliConfig, getCursorSessionConfig, } from "./cursor-runtime-state.js";
|
|
15
15
|
const FAST_ENTRY_TYPE = "cursor-fast-state";
|
|
16
16
|
const MODE_ENTRY_TYPE = "cursor-mode-state";
|
|
@@ -88,7 +88,6 @@ function restoreSessionCursorMode(branch) {
|
|
|
88
88
|
}
|
|
89
89
|
function restoreSessionCursorPreferences(ctx) {
|
|
90
90
|
const branch = ctx.sessionManager.getBranch();
|
|
91
|
-
restoreSessionCursorRuntimeState(branch);
|
|
92
91
|
restoreSessionFastPreferences(branch);
|
|
93
92
|
restoreSessionCursorMode(branch);
|
|
94
93
|
restoreSessionCursorHttp1(branch);
|
|
@@ -160,12 +159,11 @@ function updateCursorStatus(ctx, model = ctx.model) {
|
|
|
160
159
|
const modeResolution = resolveCursorAgentMode();
|
|
161
160
|
const mode = modeResolution.kind === "invalid" ? "invalid" : modeResolution.mode;
|
|
162
161
|
if (resolution.kind === "invalid") {
|
|
163
|
-
ctx.ui.setStatus("cursor", formatCursorStatus("invalid"
|
|
162
|
+
ctx.ui.setStatus("cursor", formatCursorStatus(undefined, "invalid"));
|
|
164
163
|
return;
|
|
165
164
|
}
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
ctx.ui.setStatus("cursor", formatCursorStatus(runtime, fast, mode, resolution.useHttp1ForAgent.value));
|
|
165
|
+
const fast = metadata?.supportsFast ? getEffectiveFast(model.id) : undefined;
|
|
166
|
+
ctx.ui.setStatus("cursor", formatCursorStatus(fast, mode, resolution.useHttp1ForAgent.value));
|
|
169
167
|
}
|
|
170
168
|
function getCurrentCursorMetadata(ctx) {
|
|
171
169
|
const model = ctx.model;
|
|
@@ -307,7 +305,7 @@ export function getEffectiveFastForModelId(modelId) {
|
|
|
307
305
|
return getEffectiveFast(modelId);
|
|
308
306
|
}
|
|
309
307
|
export function registerCursorRuntimeControls(pi) {
|
|
310
|
-
|
|
308
|
+
registerCursorLocalRuntimeFlags(pi);
|
|
311
309
|
pi.registerFlag("cursor-fast", {
|
|
312
310
|
description: "Force Cursor fast mode for this run when the selected Cursor model supports it",
|
|
313
311
|
type: "boolean",
|
|
@@ -517,7 +515,6 @@ export const __testUtils = {
|
|
|
517
515
|
FAST_ENTRY_TYPE,
|
|
518
516
|
MODE_ENTRY_TYPE,
|
|
519
517
|
CURSOR_HTTP1_ENTRY_TYPE,
|
|
520
|
-
RUNTIME_ENTRY_TYPE: CURSOR_RUNTIME_ENTRY_TYPE,
|
|
521
518
|
DEFAULT_CURSOR_AGENT_MODE,
|
|
522
519
|
getConfigPath,
|
|
523
520
|
loadGlobalFastPreferences,
|
|
@@ -150,7 +150,7 @@ function applyResolvedCursorOccupancy(partial, model, context, localTurn) {
|
|
|
150
150
|
}
|
|
151
151
|
export function applyCursorUsage(partial, model, context, sessionInputTokens, sdkUsage) {
|
|
152
152
|
const billed = sdkUsage?.billed;
|
|
153
|
-
const localTurn = sdkUsage?.
|
|
153
|
+
const localTurn = sdkUsage?.turn;
|
|
154
154
|
if (billed && isCursorSdkUsagePartitionSafe(billed, model)) {
|
|
155
155
|
applyCursorSdkUsage(partial, billed);
|
|
156
156
|
applyResolvedCursorOccupancy(partial, model, context, localTurn);
|