pi-cursor-sdk 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +65 -13
- package/dist/context-window-cache.js +0 -6
- package/dist/context.js +8 -0
- package/dist/cursor-cloud-lifecycle.js +122 -98
- package/dist/cursor-durable-fs.js +97 -3
- package/dist/cursor-fallback-models.generated.js +288 -1
- package/dist/cursor-fallback-warning.js +2 -2
- package/dist/cursor-http1.js +8 -8
- package/dist/cursor-live-run-coordinator.js +9 -13
- package/dist/cursor-native-replay-routing.js +1 -1
- package/dist/cursor-native-tool-display-registration.js +46 -22
- package/dist/cursor-native-tool-display-state.js +57 -22
- package/dist/cursor-native-tool-display-tools.js +5 -6
- package/dist/cursor-pi-tool-bridge-constants.js +23 -2
- package/dist/cursor-pi-tool-bridge-run.js +7 -3
- package/dist/cursor-pi-tool-bridge-snapshot.js +1 -1
- package/dist/cursor-pi-tool-bridge.js +31 -9
- package/dist/cursor-provider-binding.js +58 -0
- package/dist/cursor-provider-errors.js +28 -7
- package/dist/cursor-provider-lazy.js +23 -11
- package/dist/cursor-provider-live-run-drain.js +15 -12
- package/dist/cursor-provider-run-finalizer.js +19 -8
- package/dist/cursor-provider-turn-coordinator.js +1 -0
- package/dist/cursor-provider-turn-display-router.js +4 -0
- package/dist/cursor-provider-turn-emit.js +1 -0
- package/dist/cursor-provider-turn-finalize.js +29 -20
- package/dist/cursor-provider-turn-prepare.js +24 -11
- package/dist/cursor-provider-turn-runner.js +37 -11
- package/dist/cursor-provider-turn-send.js +22 -9
- package/dist/cursor-provider-turn-summary.js +89 -0
- package/dist/cursor-provider.js +9 -3
- package/dist/cursor-request-provenance.js +42 -0
- package/dist/cursor-ripgrep-path.js +14 -3
- package/dist/cursor-runtime-state.js +50 -43
- package/dist/cursor-sdk-billed-usage.js +54 -75
- package/dist/cursor-sdk-event-debug-session.js +5 -6
- package/dist/cursor-sdk-event-debug.js +9 -6
- package/dist/cursor-sdk-process-error-guard.js +8 -7
- package/dist/cursor-sdk-runtime.js +13 -0
- package/dist/cursor-session-agent-cleanup.js +2 -2
- package/dist/cursor-session-agent-lifecycle.js +18 -9
- package/dist/cursor-session-agent-lineage.js +28 -12
- package/dist/cursor-session-agent-resume.js +51 -35
- package/dist/cursor-session-agent.js +9 -9
- package/dist/cursor-session-compaction-prep.js +2 -7
- package/dist/cursor-session-scope.js +71 -39
- package/dist/cursor-session-settings.js +61 -0
- package/dist/cursor-skill-tool.js +32 -49
- package/dist/cursor-state.js +72 -62
- package/dist/cursor-usage-accounting.js +13 -70
- package/dist/cursor-usage-command.js +89 -0
- package/dist/cursor-usage-ledger.js +512 -0
- package/dist/index.js +11 -19
- package/dist/model-discovery.js +11 -19
- package/docs/cursor-dogfood-checklist.md +3 -3
- package/docs/cursor-live-smoke-checklist.md +15 -15
- package/docs/cursor-model-ux-spec.md +59 -18
- package/docs/cursor-native-tool-replay.md +5 -3
- package/docs/cursor-native-tool-visual-audit.md +8 -8
- package/docs/cursor-testing-lessons.md +47 -23
- package/docs/cursor-tool-surfaces.md +1 -1
- package/docs/platform-smoke-implementation.md +10 -6
- package/docs/platform-smoke.md +35 -46
- package/package.json +6 -6
- package/scripts/cloud-runtime-smoke.mjs +4 -2
- package/scripts/local-resume-smoke.mjs +1 -1
- package/scripts/platform-smoke/card-detect.mjs +2 -8
- package/scripts/platform-smoke/targets.mjs +8 -15
- package/scripts/platform-smoke/visual-evidence.mjs +7 -2
- package/scripts/tmux-live-smoke.sh +57 -90
- package/src/context-window-cache.ts +0 -6
- package/src/context.ts +8 -0
- package/src/cursor-cloud-lifecycle.ts +124 -98
- package/src/cursor-durable-fs.ts +65 -3
- package/src/cursor-fallback-models.generated.ts +288 -1
- package/src/cursor-fallback-warning.ts +2 -2
- package/src/cursor-http1.ts +8 -8
- package/src/cursor-live-run-coordinator.ts +12 -13
- package/src/cursor-native-replay-routing.ts +2 -1
- package/src/cursor-native-tool-display-registration.ts +48 -24
- package/src/cursor-native-tool-display-state.ts +65 -21
- package/src/cursor-native-tool-display-tools.ts +7 -4
- package/src/cursor-pi-tool-bridge-constants.ts +27 -2
- package/src/cursor-pi-tool-bridge-run.ts +11 -3
- package/src/cursor-pi-tool-bridge-snapshot.ts +1 -1
- package/src/cursor-pi-tool-bridge.ts +26 -9
- package/src/cursor-provider-binding.ts +62 -0
- package/src/cursor-provider-errors.ts +27 -7
- package/src/cursor-provider-lazy.ts +21 -15
- package/src/cursor-provider-live-run-drain.ts +20 -13
- package/src/cursor-provider-run-finalizer.ts +24 -15
- package/src/cursor-provider-turn-coordinator.ts +2 -0
- package/src/cursor-provider-turn-display-router.ts +5 -0
- package/src/cursor-provider-turn-emit.ts +3 -1
- package/src/cursor-provider-turn-finalize.ts +38 -23
- package/src/cursor-provider-turn-prepare.ts +23 -14
- package/src/cursor-provider-turn-runner.ts +40 -13
- package/src/cursor-provider-turn-send.ts +23 -15
- package/src/cursor-provider-turn-summary.ts +94 -0
- package/src/cursor-provider-turn-types.ts +37 -4
- package/src/cursor-provider.ts +25 -3
- package/src/cursor-request-provenance.ts +64 -0
- package/src/cursor-ripgrep-path.ts +15 -5
- package/src/cursor-runtime-state.ts +53 -48
- package/src/cursor-sdk-billed-usage.ts +54 -102
- package/src/cursor-sdk-event-debug-session.ts +5 -5
- package/src/cursor-sdk-event-debug.ts +10 -6
- package/src/cursor-sdk-process-error-guard.ts +7 -7
- package/src/cursor-sdk-runtime.ts +14 -0
- package/src/cursor-session-agent-cleanup.ts +2 -2
- package/src/cursor-session-agent-lifecycle.ts +14 -9
- package/src/cursor-session-agent-lineage.ts +26 -12
- package/src/cursor-session-agent-resume.ts +49 -36
- package/src/cursor-session-agent.ts +13 -10
- package/src/cursor-session-compaction-prep.ts +2 -7
- package/src/cursor-session-scope.ts +87 -39
- package/src/cursor-session-settings.ts +72 -0
- package/src/cursor-skill-tool.ts +37 -61
- package/src/cursor-state.ts +74 -67
- package/src/cursor-usage-accounting.ts +17 -82
- package/src/cursor-usage-command.ts +76 -0
- package/src/cursor-usage-ledger.ts +500 -0
- package/src/index.ts +14 -23
- package/src/model-discovery.ts +14 -22
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { loadCursorTranscriptWebToolCallsAfterOffset } from "./cursor-agent-message-web-tools.js";
|
|
2
2
|
import { collectCursorCloudRunReport, formatCursorCloudRunReport, } from "./cursor-cloud-reporting.js";
|
|
3
|
-
import { recordCursorCloudLifecycleRun } from "./cursor-cloud-lifecycle.js";
|
|
4
3
|
import { getCheckpointContextWindow, saveCachedContextWindow } from "./context-window-cache.js";
|
|
5
4
|
import { scrubSensitiveText } from "./cursor-sensitive-text.js";
|
|
6
5
|
import { isCursorRunFinishedSuccessfully, resolveCursorRunOutcome, } from "./cursor-provider-run-outcome.js";
|
|
7
6
|
import { loadCursorSdk } from "./cursor-sdk-runtime.js";
|
|
8
|
-
import { attachCursorSdkBilledTurnUsage } from "./cursor-sdk-billed-usage.js";
|
|
9
7
|
export async function cacheSdkContextWindow(agentId, modelId, cwd, store) {
|
|
10
8
|
try {
|
|
11
9
|
const { createAgentPlatform } = await loadCursorSdk();
|
|
@@ -74,10 +72,30 @@ function recordCursorCloudReportingError(sdkEventDebug, error, apiKey) {
|
|
|
74
72
|
// Debug reporting must never affect provider execution.
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
|
-
|
|
75
|
+
export async function recordCursorProviderTerminalUsage(prepared, status, waitUsage) {
|
|
76
|
+
if (prepared.runtime.usageTerminalRecorded)
|
|
77
|
+
return undefined;
|
|
78
|
+
prepared.runtime.usageTerminalRecorded = true;
|
|
79
|
+
try {
|
|
80
|
+
return await prepared.usage.recordTerminal({ status, waitUsage, handleUsage: prepared.runtime.sdkRun?.usage });
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
prepared.usage.notePersistenceFailure(error);
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Single wait/finalize path for SDK runs: accounting, replay, incomplete tools, artifacts, context cache. */
|
|
78
88
|
export async function awaitFinalizeCursorRunOutcome(params) {
|
|
79
89
|
const apiKey = params.resolvedApiKey ?? params.optionsApiKey;
|
|
80
|
-
|
|
90
|
+
params.prepared.runtime.sdkRun = params.run;
|
|
91
|
+
let waitResult;
|
|
92
|
+
try {
|
|
93
|
+
waitResult = params.waitResult ?? (await params.run.wait());
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
await recordCursorProviderTerminalUsage(params.prepared, params.signal?.aborted ? "abort" : "error");
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
81
99
|
const outcome = buildCursorRunOutcomeFromWait({
|
|
82
100
|
waitResult,
|
|
83
101
|
prepared: params.prepared,
|
|
@@ -87,16 +105,7 @@ export async function awaitFinalizeCursorRunOutcome(params) {
|
|
|
87
105
|
resolvedApiKey: params.resolvedApiKey,
|
|
88
106
|
optionsApiKey: params.optionsApiKey,
|
|
89
107
|
});
|
|
90
|
-
const
|
|
91
|
-
agent: params.prepared.agent,
|
|
92
|
-
agentId: params.run.agentId,
|
|
93
|
-
runtime: params.prepared.runtimeTarget,
|
|
94
|
-
runId: params.run.id,
|
|
95
|
-
});
|
|
96
|
-
params.prepared.runtime.billedTurnUsage = billed.turn;
|
|
97
|
-
if (params.prepared.runtime.liveRun) {
|
|
98
|
-
params.prepared.runtime.liveRun.billedTurnUsage = billed.turn;
|
|
99
|
-
}
|
|
108
|
+
const billing = await recordCursorProviderTerminalUsage(params.prepared, outcome.kind === "finished" ? "success" : outcome.kind === "cancelled" ? "abort" : "error", waitResult.usage);
|
|
100
109
|
let displayOnlyTraceBlock;
|
|
101
110
|
if (params.prepared.runtimeTarget === "cloud" && isCursorRunFinishedSuccessfully(outcome)) {
|
|
102
111
|
let report = { agentId: params.run.agentId, runId: params.run.id, branches: [] };
|
|
@@ -106,14 +115,14 @@ export async function awaitFinalizeCursorRunOutcome(params) {
|
|
|
106
115
|
run: params.run,
|
|
107
116
|
waitResult,
|
|
108
117
|
apiKey,
|
|
109
|
-
agentUsage:
|
|
118
|
+
agentUsage: billing ? billing.status === "observed-pending-settlement" ? billing.snapshot : null : undefined,
|
|
110
119
|
});
|
|
111
120
|
}
|
|
112
121
|
catch (error) {
|
|
113
122
|
recordCursorCloudReportingError(params.sdkEventDebug, error, apiKey);
|
|
114
123
|
}
|
|
115
124
|
try {
|
|
116
|
-
|
|
125
|
+
params.prepared.recordCloudLifecycle(report, apiKey);
|
|
117
126
|
}
|
|
118
127
|
catch (error) {
|
|
119
128
|
recordCursorCloudReportingError(params.sdkEventDebug, error, apiKey);
|
|
@@ -137,8 +146,8 @@ export async function awaitFinalizeCursorRunOutcome(params) {
|
|
|
137
146
|
catch {
|
|
138
147
|
// Debug reporting must never affect provider execution.
|
|
139
148
|
}
|
|
140
|
-
if (params.prepared.runtimeTarget === "local" && isCursorRunFinishedSuccessfully(outcome)) {
|
|
141
|
-
await replayCursorTranscriptWebToolCalls(params.run.agentId, params.prepared.cwd, params.cursorAgentMessageOffset, params.prepared.
|
|
149
|
+
if (params.prepared.runtimeTarget === "local" && params.prepared.execution === "conversation" && isCursorRunFinishedSuccessfully(outcome)) {
|
|
150
|
+
await replayCursorTranscriptWebToolCalls(params.run.agentId, params.prepared.cwd, params.cursorAgentMessageOffset, params.prepared.store, params.prepared.runtime.turnCoordinator, params.sdkEventDebug);
|
|
142
151
|
}
|
|
143
152
|
params.prepared.runtime.turnCoordinator.discardIncompleteStartedToolCalls(outcome.incompleteTools);
|
|
144
153
|
try {
|
|
@@ -147,8 +156,8 @@ export async function awaitFinalizeCursorRunOutcome(params) {
|
|
|
147
156
|
catch {
|
|
148
157
|
// Debug artifact failures must never affect provider execution.
|
|
149
158
|
}
|
|
150
|
-
if (params.prepared.runtimeTarget === "local" && params.cacheContextWindow !== false) {
|
|
151
|
-
await cacheSdkContextWindow(params.contextWindowAgentId ?? params.run.agentId, params.modelId, params.prepared.cwd, params.prepared.
|
|
159
|
+
if (params.prepared.runtimeTarget === "local" && params.prepared.execution === "conversation" && params.cacheContextWindow !== false) {
|
|
160
|
+
await cacheSdkContextWindow(params.contextWindowAgentId ?? params.run.agentId, params.modelId, params.prepared.cwd, params.prepared.store);
|
|
152
161
|
}
|
|
153
162
|
return { outcome, displayOnlyTraceBlock };
|
|
154
163
|
}
|
|
@@ -7,22 +7,23 @@ import { acquireSessionCursorAgent, buildCursorSessionSendPrompt, planCursorSess
|
|
|
7
7
|
import { buildCursorPrompt, estimateCursorPromptTokens } from "./context.js";
|
|
8
8
|
import { getCursorPromptOptions } from "./cursor-usage-accounting.js";
|
|
9
9
|
import { getActiveContextToolNames } from "./cursor-context-tools.js";
|
|
10
|
-
import { abandonSessionCursorAgent, createCursorNativeReplayId, cursorLiveRuns, getActiveCursorLiveRunForCurrentScope,
|
|
10
|
+
import { abandonSessionCursorAgent, createCursorNativeReplayId, cursorLiveRuns, getActiveCursorLiveRunForCurrentScope, } from "./cursor-provider-live-run-drain.js";
|
|
11
11
|
import { getCursorProviderAgentModeOrThrow, getEffectiveFastForModelId, } from "./cursor-state.js";
|
|
12
12
|
import { resolveEffectiveCursorConfig } from "./cursor-runtime-state.js";
|
|
13
13
|
import { buildCursorModelSelection } from "./model-discovery.js";
|
|
14
14
|
import { getEffectiveCursorSettingSources } from "./cursor-setting-sources.js";
|
|
15
15
|
import { formatCursorCloudPreflightError, buildCursorCloudAgentOptions, preflightCursorCloudRuntime, } from "./cursor-cloud-options.js";
|
|
16
16
|
import { inspectCursorCloudLocalState } from "./cursor-cloud-local-state.js";
|
|
17
|
-
import {
|
|
17
|
+
import { getCursorSessionProjectTrusted } from "./cursor-session-scope.js";
|
|
18
18
|
import { resolveCursorPiToolBridgeEnabled } from "./cursor-pi-tool-bridge-env.js";
|
|
19
19
|
import { buildCursorToolManifestText, resolveCursorToolManifestEnabled, } from "./cursor-tool-manifest.js";
|
|
20
20
|
import { isCursorNativeToolDisplayRuntimeEnabled } from "./cursor-native-tool-display-state.js";
|
|
21
|
-
import { createCursorCloudLifecyclePersistenceError
|
|
21
|
+
import { createCursorCloudLifecyclePersistenceError } from "./cursor-cloud-lifecycle.js";
|
|
22
22
|
import { MISSING_CURSOR_API_KEY_MESSAGE } from "./cursor-provider-errors.js";
|
|
23
23
|
import { CursorSdkTurnCoordinator } from "./cursor-provider-turn-coordinator.js";
|
|
24
24
|
import { resolveCursorApiKey } from "./cursor-api-key.js";
|
|
25
25
|
import { loadCursorSdk } from "./cursor-sdk-runtime.js";
|
|
26
|
+
import { prepareCursorSummaryProviderTurn } from "./cursor-provider-turn-summary.js";
|
|
26
27
|
function buildCursorCloudPromptContext(context, handoff) {
|
|
27
28
|
if (handoff === "bootstrap")
|
|
28
29
|
return context;
|
|
@@ -38,8 +39,8 @@ function buildCursorCloudPromptContext(context, handoff) {
|
|
|
38
39
|
return { ...current, messages: messages.slice(-1) };
|
|
39
40
|
}
|
|
40
41
|
const CLOUD_SEND_PLAN = { mode: "bootstrap", resetAgent: false, reason: "initial" };
|
|
41
|
-
export function resolveCursorProviderTurnConfig(cwd) {
|
|
42
|
-
return resolveEffectiveCursorConfig({ cwd, projectTrusted
|
|
42
|
+
export function resolveCursorProviderTurnConfig(cwd, projectTrusted = getCursorSessionProjectTrusted(), scopeKey) {
|
|
43
|
+
return resolveEffectiveCursorConfig({ cwd, projectTrusted, scopeKey });
|
|
43
44
|
}
|
|
44
45
|
function buildCloudCursorProviderTurnLifecycle(agent) {
|
|
45
46
|
return {
|
|
@@ -78,7 +79,7 @@ async function prepareCursorCloudProviderTurn(prepareParams) {
|
|
|
78
79
|
});
|
|
79
80
|
if (!preflight.ok)
|
|
80
81
|
throw new Error(formatCursorCloudPreflightError(preflight));
|
|
81
|
-
if (
|
|
82
|
+
if (getActiveCursorLiveRunForCurrentScope(params.scope.scopeKey)) {
|
|
82
83
|
throw new Error("Cursor cloud runtime cannot start while a local Cursor live run is pending; finish or abort the local run, then retry.");
|
|
83
84
|
}
|
|
84
85
|
const { Agent } = await loadCursorSdk();
|
|
@@ -96,10 +97,10 @@ async function prepareCursorCloudProviderTurn(prepareParams) {
|
|
|
96
97
|
modelSelection: selection,
|
|
97
98
|
agentMode,
|
|
98
99
|
resolvedConfig,
|
|
99
|
-
name:
|
|
100
|
+
name: params.scope.sessionName,
|
|
100
101
|
})));
|
|
101
102
|
cloudAgentForCleanup = agent;
|
|
102
|
-
if (!
|
|
103
|
+
if (!params.recordCloudLifecycle({ agentId: agent.agentId }, resolvedApiKey)) {
|
|
103
104
|
throw createCursorCloudLifecyclePersistenceError(agent.agentId, "intent", undefined, resolvedApiKey);
|
|
104
105
|
}
|
|
105
106
|
sdkEventDebug?.recordProviderMeta({ runtime: "cloud", cloudAgentId: agent.agentId, phase: "agent_created" });
|
|
@@ -137,6 +138,8 @@ async function prepareCursorCloudProviderTurn(prepareParams) {
|
|
|
137
138
|
cloudAgentForCleanup = undefined;
|
|
138
139
|
return {
|
|
139
140
|
runtimeTarget: "cloud",
|
|
141
|
+
execution: "conversation",
|
|
142
|
+
recordCloudLifecycle: params.recordCloudLifecycle,
|
|
140
143
|
agent,
|
|
141
144
|
cwd,
|
|
142
145
|
payload: {
|
|
@@ -190,6 +193,8 @@ async function prepareCursorLocalProviderTurn(prepareParams) {
|
|
|
190
193
|
const queuedBridgeRequestsBeforeLiveRun = [];
|
|
191
194
|
let liveRunForBridgeQueue;
|
|
192
195
|
const sessionAgentAcquireParams = {
|
|
196
|
+
scope: params.scope,
|
|
197
|
+
bridge: params.bridge,
|
|
193
198
|
apiKey: resolvedApiKey,
|
|
194
199
|
agentMode,
|
|
195
200
|
cwd,
|
|
@@ -258,7 +263,7 @@ async function prepareCursorLocalProviderTurn(prepareParams) {
|
|
|
258
263
|
};
|
|
259
264
|
const sessionBridgeRun = bridgeRun;
|
|
260
265
|
const promptInputTokens = estimateCursorPromptTokens(prompt, promptOptions);
|
|
261
|
-
const useNativeToolReplay = isCursorNativeToolDisplayRuntimeEnabled();
|
|
266
|
+
const useNativeToolReplay = isCursorNativeToolDisplayRuntimeEnabled(params.nativeDisplay);
|
|
262
267
|
const activeToolNames = getActiveContextToolNames(context);
|
|
263
268
|
sdkEventDebug?.recordProviderMeta({
|
|
264
269
|
model: {
|
|
@@ -295,6 +300,7 @@ async function prepareCursorLocalProviderTurn(prepareParams) {
|
|
|
295
300
|
promptInputTokens,
|
|
296
301
|
textDeltas,
|
|
297
302
|
debugRecorder: sdkEventDebug,
|
|
303
|
+
nativeDisplay: params.nativeDisplay,
|
|
298
304
|
})
|
|
299
305
|
: undefined;
|
|
300
306
|
if (liveRun) {
|
|
@@ -311,6 +317,7 @@ async function prepareCursorLocalProviderTurn(prepareParams) {
|
|
|
311
317
|
liveRun,
|
|
312
318
|
useNativeToolReplay,
|
|
313
319
|
activeToolNames,
|
|
320
|
+
registeredToolNames: params.nativeDisplay ? new Set(params.nativeDisplay.registeredNativeToolSources.keys()) : undefined,
|
|
314
321
|
nativeReplayId,
|
|
315
322
|
textDeltas,
|
|
316
323
|
debugRecorder: sdkEventDebug,
|
|
@@ -318,6 +325,9 @@ async function prepareCursorLocalProviderTurn(prepareParams) {
|
|
|
318
325
|
completed = true;
|
|
319
326
|
return {
|
|
320
327
|
runtimeTarget: "local",
|
|
328
|
+
execution: "conversation",
|
|
329
|
+
store: sessionAgentLease.store,
|
|
330
|
+
storeIdentity: sessionAgentLease.storeIdentity,
|
|
321
331
|
agent,
|
|
322
332
|
cwd,
|
|
323
333
|
payload: sendPayload,
|
|
@@ -363,9 +373,12 @@ async function prepareCursorLocalProviderTurn(prepareParams) {
|
|
|
363
373
|
export async function prepareCursorProviderTurn(prepareParams) {
|
|
364
374
|
const { params, resolvedConfig } = prepareParams;
|
|
365
375
|
const { model, options } = params;
|
|
366
|
-
const
|
|
367
|
-
const fastEnabled = resolvedConfig.runtime.value === "cloud" ? undefined : getEffectiveFastForModelId(model.id);
|
|
376
|
+
const fastEnabled = resolvedConfig.runtime.value === "cloud" ? undefined : getEffectiveFastForModelId(model.id, params.scope.scopeKey);
|
|
368
377
|
const selection = buildCursorModelSelection(model.id, options?.reasoning ?? "off", fastEnabled);
|
|
378
|
+
if (resolvedConfig.runtime.value === "local" && params.request.purpose !== "normal") {
|
|
379
|
+
return prepareCursorSummaryProviderTurn(prepareParams, selection);
|
|
380
|
+
}
|
|
381
|
+
const agentMode = getCursorProviderAgentModeOrThrow(params.scope.scopeKey);
|
|
369
382
|
const context = { ...prepareParams, agentMode, selection, fastEnabled };
|
|
370
383
|
return resolvedConfig.runtime.value === "cloud"
|
|
371
384
|
? prepareCursorCloudProviderTurn(context)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CursorLiveRunAbortError } from "./cursor-live-run-coordinator.js";
|
|
2
2
|
import { drainExistingCursorLiveRunBeforeSend } from "./cursor-provider-live-run-drain.js";
|
|
3
|
-
import { getCursorSessionCwd } from "./cursor-session-scope.js";
|
|
4
3
|
import { installCursorSdkProcessErrorGuard } from "./cursor-sdk-process-error-guard.js";
|
|
5
4
|
import { CursorSdkEventDebugSink } from "./cursor-sdk-event-debug.js";
|
|
6
5
|
import { awaitFinalizeCursorRunOutcome } from "./cursor-provider-turn-finalize.js";
|
|
@@ -9,7 +8,7 @@ import { CursorRunFinalizer } from "./cursor-provider-run-finalizer.js";
|
|
|
9
8
|
import { prepareCursorProviderTurn, requireCursorApiKey, resolveCursorProviderTurnConfig, } from "./cursor-provider-turn-prepare.js";
|
|
10
9
|
import { sendCursorProviderTurn } from "./cursor-provider-turn-send.js";
|
|
11
10
|
function requireLocalLivePreparedTurn(prepared) {
|
|
12
|
-
if (prepared.runtimeTarget !== "local" || prepared.runtime.kind !== "live") {
|
|
11
|
+
if (prepared.runtimeTarget !== "local" || prepared.execution !== "conversation" || prepared.runtime.kind !== "live") {
|
|
13
12
|
throw new Error("Cursor live run requires a local live prepared turn");
|
|
14
13
|
}
|
|
15
14
|
return prepared;
|
|
@@ -32,6 +31,7 @@ export class CursorProviderTurnRunner {
|
|
|
32
31
|
async run(sdkProcessErrorGuard) {
|
|
33
32
|
const { stream, partial, model, context, options, sdkEventDebugRef } = this.params;
|
|
34
33
|
let prepared;
|
|
34
|
+
let started;
|
|
35
35
|
let sendResult;
|
|
36
36
|
let liveCompletion;
|
|
37
37
|
const runFinalizer = new CursorRunFinalizer({
|
|
@@ -43,20 +43,22 @@ export class CursorProviderTurnRunner {
|
|
|
43
43
|
});
|
|
44
44
|
try {
|
|
45
45
|
this.throwIfAborted();
|
|
46
|
-
const
|
|
46
|
+
const { scope } = this.params;
|
|
47
|
+
const cwd = scope.cwd;
|
|
47
48
|
this.sdkEventDebug = CursorSdkEventDebugSink.maybeCreate({
|
|
48
49
|
cwd,
|
|
49
50
|
modelId: model.id,
|
|
50
51
|
provider: model.provider,
|
|
52
|
+
scope,
|
|
51
53
|
});
|
|
52
54
|
sdkEventDebugRef.current = this.sdkEventDebug;
|
|
53
55
|
this.sdkEventDebug?.recordContextSnapshot(context);
|
|
54
56
|
// Resolved once here, before any drain await, so the drain decision and the
|
|
55
57
|
// prepare dispatch below always act on the same config snapshot.
|
|
56
|
-
const resolvedConfig = resolveCursorProviderTurnConfig(cwd);
|
|
58
|
+
const resolvedConfig = resolveCursorProviderTurnConfig(cwd, scope.projectTrusted, scope.scopeKey);
|
|
57
59
|
this.runtimeTarget = resolvedConfig.runtime.value;
|
|
58
|
-
if (resolvedConfig.runtime.value === "local") {
|
|
59
|
-
if ((await drainExistingCursorLiveRunBeforeSend(stream, partial, model, context, options?.signal, this.sdkEventDebug)) ===
|
|
60
|
+
if (resolvedConfig.runtime.value === "local" && this.params.request.purpose === "normal") {
|
|
61
|
+
if ((await drainExistingCursorLiveRunBeforeSend(stream, partial, model, context, options?.signal, this.sdkEventDebug, scope.scopeKey, this.params.request.occupancyFloor)) ===
|
|
60
62
|
"stream_ended") {
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
@@ -71,9 +73,33 @@ export class CursorProviderTurnRunner {
|
|
|
71
73
|
throwIfAborted: () => this.throwIfAborted(),
|
|
72
74
|
resolvedConfig,
|
|
73
75
|
});
|
|
76
|
+
const usage = await this.params.usageRecorder.start({
|
|
77
|
+
agent: prepared.agent,
|
|
78
|
+
runtime: prepared.runtimeTarget,
|
|
79
|
+
model: { id: model.id, provider: model.provider, cost: { ...model.cost } },
|
|
80
|
+
modelSelection: prepared.meta.modelSelection,
|
|
81
|
+
purpose: this.params.request.purpose,
|
|
82
|
+
...(prepared.runtimeTarget === "local" ? { storeIdentity: prepared.storeIdentity.stateRoot } : {}),
|
|
83
|
+
resumed: prepared.runtimeTarget === "local" && prepared.execution === "conversation" && prepared.sessionAgentLease.resumed === true,
|
|
84
|
+
newlyCreated: prepared.runtimeTarget !== "local" || prepared.execution === "summary" || (prepared.sessionAgentLease.created && !prepared.sessionAgentLease.resumed),
|
|
85
|
+
}).catch(error => {
|
|
86
|
+
this.params.usageRecorder.notePersistenceFailure(error);
|
|
87
|
+
throw error;
|
|
88
|
+
});
|
|
89
|
+
started = { ...prepared, usage };
|
|
90
|
+
if (started.runtime.liveRun) {
|
|
91
|
+
started.runtime.liveRun.onAbandon = async () => {
|
|
92
|
+
try {
|
|
93
|
+
await usage.recordTerminal({ status: "abandon" });
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
usage.notePersistenceFailure(error);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
74
100
|
sendResult = await sendCursorProviderTurn({
|
|
75
101
|
params: this.params,
|
|
76
|
-
prepared,
|
|
102
|
+
prepared: started,
|
|
77
103
|
sdkEventDebug: this.sdkEventDebug,
|
|
78
104
|
sdkProcessErrorGuard,
|
|
79
105
|
throwIfAborted: () => this.throwIfAborted(),
|
|
@@ -81,7 +107,7 @@ export class CursorProviderTurnRunner {
|
|
|
81
107
|
});
|
|
82
108
|
const { send } = sendResult;
|
|
83
109
|
if (prepared.runtime.kind === "live") {
|
|
84
|
-
const livePrepared = requireLocalLivePreparedTurn(
|
|
110
|
+
const livePrepared = requireLocalLivePreparedTurn(started);
|
|
85
111
|
liveCompletion = runFinalizer.startLiveRunCompletion({
|
|
86
112
|
send,
|
|
87
113
|
prepared: livePrepared,
|
|
@@ -98,7 +124,7 @@ export class CursorProviderTurnRunner {
|
|
|
98
124
|
}
|
|
99
125
|
const outcomePromise = awaitFinalizeCursorRunOutcome({
|
|
100
126
|
run: send.run,
|
|
101
|
-
prepared,
|
|
127
|
+
prepared: started,
|
|
102
128
|
cursorAgentMessageOffset: send.cursorAgentMessageOffset,
|
|
103
129
|
modelId: model.id,
|
|
104
130
|
signal: options?.signal,
|
|
@@ -113,13 +139,13 @@ export class CursorProviderTurnRunner {
|
|
|
113
139
|
const finalized = await outcomePromise;
|
|
114
140
|
await runFinalizer.applyTerminalEvent({
|
|
115
141
|
kind: "direct",
|
|
116
|
-
prepared,
|
|
142
|
+
prepared: started,
|
|
117
143
|
outcome: finalized.outcome,
|
|
118
144
|
displayOnlyTraceBlock: finalized.displayOnlyTraceBlock,
|
|
119
145
|
});
|
|
120
146
|
}
|
|
121
147
|
catch (error) {
|
|
122
|
-
await runFinalizer.applyTerminalEvent({ kind: "error", prepared, error });
|
|
148
|
+
await runFinalizer.applyTerminalEvent({ kind: "error", prepared: started ?? prepared, error });
|
|
123
149
|
}
|
|
124
150
|
finally {
|
|
125
151
|
await runFinalizer.cleanup(prepared, sendResult, liveCompletion);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { countCursorAgentMessages } from "./cursor-agent-message-web-tools.js";
|
|
2
|
-
import { createCursorCloudLifecyclePersistenceError
|
|
3
|
-
import { CursorLiveRunAbortError } from "./cursor-live-run-coordinator.js";
|
|
2
|
+
import { createCursorCloudLifecyclePersistenceError } from "./cursor-cloud-lifecycle.js";
|
|
4
3
|
import { cursorLiveRuns } from "./cursor-provider-live-run-drain.js";
|
|
5
4
|
import { consumeCursorLocalForceOverride } from "./cursor-runtime-state.js";
|
|
6
5
|
import { recordCursorSessionAgentLineage } from "./cursor-session-agent-lineage.js";
|
|
@@ -52,9 +51,9 @@ export async function sendCursorProviderTurn(sendParams) {
|
|
|
52
51
|
abortRegistration?.signal.addEventListener("abort", abortListener, { once: true });
|
|
53
52
|
throwIfAborted();
|
|
54
53
|
let cursorAgentMessageOffset;
|
|
55
|
-
if (prepared.runtimeTarget === "local") {
|
|
54
|
+
if (prepared.runtimeTarget === "local" && prepared.execution === "conversation") {
|
|
56
55
|
try {
|
|
57
|
-
cursorAgentMessageOffset = await countCursorAgentMessages(agent.agentId, cwd, prepared.
|
|
56
|
+
cursorAgentMessageOffset = await countCursorAgentMessages(agent.agentId, cwd, prepared.store);
|
|
58
57
|
}
|
|
59
58
|
catch (error) {
|
|
60
59
|
recordDebug(() => sdkEventDebug?.recordError("cursor_agent_message_count", error));
|
|
@@ -80,6 +79,14 @@ export async function sendCursorProviderTurn(sendParams) {
|
|
|
80
79
|
mode: meta.agentMode,
|
|
81
80
|
model: meta.modelSelection,
|
|
82
81
|
onDelta: (args) => {
|
|
82
|
+
if (args.update.type === "turn-ended") {
|
|
83
|
+
try {
|
|
84
|
+
prepared.usage.observeRawTurn(args.update.usage);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
params.usageRecorder.notePersistenceFailure(error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
83
90
|
recordDebug(() => sdkEventDebug?.recordOnDelta(args.update));
|
|
84
91
|
turnCoordinator.handleDelta(args.update);
|
|
85
92
|
},
|
|
@@ -89,17 +96,24 @@ export async function sendCursorProviderTurn(sendParams) {
|
|
|
89
96
|
},
|
|
90
97
|
};
|
|
91
98
|
throwIfAborted();
|
|
92
|
-
if (prepared.runtimeTarget === "local" && consumeCursorLocalForceOverride(prepared.localForce)) {
|
|
99
|
+
if (prepared.runtimeTarget === "local" && prepared.execution === "conversation" && consumeCursorLocalForceOverride(prepared.localForce, params.scope.scopeKey)) {
|
|
93
100
|
sendOptions.local = { force: true };
|
|
94
101
|
}
|
|
95
102
|
const runPromise = agent.send(payload, sendOptions);
|
|
96
103
|
// Record at send initiation (promise created), including later reject/cancel paths.
|
|
97
|
-
if (prepared.runtimeTarget === "local") {
|
|
98
|
-
recordCursorSessionAgentLineage(agent.agentId);
|
|
104
|
+
if (prepared.runtimeTarget === "local" && prepared.execution === "conversation") {
|
|
105
|
+
recordCursorSessionAgentLineage(agent.agentId, params.scope.scopeKey);
|
|
99
106
|
}
|
|
100
107
|
const run = await runPromise;
|
|
101
108
|
sdkRun = run;
|
|
102
|
-
|
|
109
|
+
runtime.sdkRun = run;
|
|
110
|
+
try {
|
|
111
|
+
await prepared.usage.recordRun({ runId: run.id, requestId: run.requestId });
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
params.usageRecorder.notePersistenceFailure(error);
|
|
115
|
+
}
|
|
116
|
+
if (prepared.runtimeTarget === "cloud" && !params.recordCloudLifecycle({ agentId: run.agentId, runId: run.id }, resolvedApiKey)) {
|
|
103
117
|
const cancellationConfirmed = await requestBoundedCloudRunCancellation(run);
|
|
104
118
|
throw createCursorCloudLifecyclePersistenceError(run.agentId, "run", cancellationConfirmed, resolvedApiKey);
|
|
105
119
|
}
|
|
@@ -122,7 +136,6 @@ export async function sendCursorProviderTurn(sendParams) {
|
|
|
122
136
|
sdkProcessErrorGuard.suppressAbortErrors();
|
|
123
137
|
liveRun?.bridgeRun?.cancel("Cursor SDK run aborted");
|
|
124
138
|
await run.cancel().catch(() => { });
|
|
125
|
-
throw new CursorLiveRunAbortError();
|
|
126
139
|
}
|
|
127
140
|
completed = true;
|
|
128
141
|
return {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { buildCursorSummaryPrompt, estimateCursorPromptTokens } from "./context.js";
|
|
2
|
+
import { configureCursorSdkHttp1 } from "./cursor-http1.js";
|
|
3
|
+
import { createCursorNativeReplayId } from "./cursor-provider-live-run-drain.js";
|
|
4
|
+
import { CursorSdkTurnCoordinator } from "./cursor-provider-turn-coordinator.js";
|
|
5
|
+
import { ensureCursorRipgrepPath } from "./cursor-ripgrep-path.js";
|
|
6
|
+
import { loadCursorSdk } from "./cursor-sdk-runtime.js";
|
|
7
|
+
import { installCursorSdkOutputFilter, suppressCursorSdkOutput } from "./cursor-sdk-output-filter.js";
|
|
8
|
+
import { buildCursorLocalAgentOptions } from "./cursor-session-agent.js";
|
|
9
|
+
import { openCursorSessionStoreForScope } from "./cursor-session-store.js";
|
|
10
|
+
import { getCursorPromptOptions } from "./cursor-usage-accounting.js";
|
|
11
|
+
function summaryLifecycle(agent, sessionStore) {
|
|
12
|
+
let disposal;
|
|
13
|
+
const dispose = () => disposal ??= (async () => {
|
|
14
|
+
try {
|
|
15
|
+
await agent[Symbol.asyncDispose]();
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
await sessionStore.dispose();
|
|
19
|
+
}
|
|
20
|
+
})();
|
|
21
|
+
return { trackRunCompletion: () => { }, commitSend: () => { }, abandon: dispose, dispose };
|
|
22
|
+
}
|
|
23
|
+
/** A native summary never enters the conversation pool or inherits its tool/mode/resume state. */
|
|
24
|
+
export async function prepareCursorSummaryProviderTurn(prepareParams, selection) {
|
|
25
|
+
const { params, cwd, resolvedApiKey, resolvedConfig, sdkEventDebug, throwIfAborted } = prepareParams;
|
|
26
|
+
let sessionStore;
|
|
27
|
+
let agent;
|
|
28
|
+
let restoreCursorSdkOutputFilter;
|
|
29
|
+
let completed = false;
|
|
30
|
+
try {
|
|
31
|
+
ensureCursorRipgrepPath();
|
|
32
|
+
const sdk = await loadCursorSdk();
|
|
33
|
+
configureCursorSdkHttp1(sdk, resolvedConfig.local.useHttp1ForAgent);
|
|
34
|
+
restoreCursorSdkOutputFilter = installCursorSdkOutputFilter();
|
|
35
|
+
sessionStore = (await openCursorSessionStoreForScope({
|
|
36
|
+
cwd, scopeKey: params.scope.scopeKey, persistent: false, hasResumeHandle: false,
|
|
37
|
+
})).sessionStore;
|
|
38
|
+
throwIfAborted();
|
|
39
|
+
agent = await suppressCursorSdkOutput(() => sdk.Agent.create({
|
|
40
|
+
apiKey: resolvedApiKey,
|
|
41
|
+
model: selection,
|
|
42
|
+
mode: "agent",
|
|
43
|
+
tools: [],
|
|
44
|
+
local: buildCursorLocalAgentOptions({ cwd, store: sessionStore.store, settingSources: [] }),
|
|
45
|
+
}));
|
|
46
|
+
throwIfAborted();
|
|
47
|
+
const prompt = buildCursorSummaryPrompt(params.context);
|
|
48
|
+
const promptInputTokens = estimateCursorPromptTokens(prompt, getCursorPromptOptions(params.model));
|
|
49
|
+
const nativeReplayId = createCursorNativeReplayId();
|
|
50
|
+
const textDeltas = [];
|
|
51
|
+
const turnCoordinator = new CursorSdkTurnCoordinator({
|
|
52
|
+
stream: params.stream, partial: params.partial, cwd, resolvedApiKey,
|
|
53
|
+
useNativeToolReplay: false, nativeReplayId, textDeltas, debugRecorder: sdkEventDebug,
|
|
54
|
+
});
|
|
55
|
+
sdkEventDebug?.recordProviderMeta({
|
|
56
|
+
purpose: params.request.purpose,
|
|
57
|
+
runtime: "local",
|
|
58
|
+
summaryAgentId: agent.agentId,
|
|
59
|
+
model: { id: params.model.id, provider: params.model.provider, selection },
|
|
60
|
+
agentMode: "agent", settingSources: [], tools: [], resumedAgent: false,
|
|
61
|
+
});
|
|
62
|
+
completed = true;
|
|
63
|
+
return {
|
|
64
|
+
runtimeTarget: "local", execution: "summary", agent, cwd,
|
|
65
|
+
store: sessionStore.store, storeIdentity: sessionStore.identity,
|
|
66
|
+
payload: { text: prompt.text },
|
|
67
|
+
meta: {
|
|
68
|
+
sendPlan: { mode: "bootstrap", resetAgent: false, reason: "initial" },
|
|
69
|
+
prompt, bootstrap: true, promptInputTokens,
|
|
70
|
+
useNativeToolReplay: false, bridgeEnabled: false, nativeReplayId,
|
|
71
|
+
agentMode: "agent", modelSelection: selection,
|
|
72
|
+
},
|
|
73
|
+
contextWindowAgentId: agent.agentId, textDeltas, restoreCursorSdkOutputFilter,
|
|
74
|
+
lifecycle: summaryLifecycle(agent, sessionStore),
|
|
75
|
+
runtime: { kind: "direct", turnCoordinator },
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
if (!completed) {
|
|
80
|
+
try {
|
|
81
|
+
await agent?.[Symbol.asyncDispose]().catch(() => { });
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
await sessionStore?.dispose().catch(() => { });
|
|
85
|
+
restoreCursorSdkOutputFilter?.();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
package/dist/cursor-provider.js
CHANGED
|
@@ -6,7 +6,6 @@ import { installCursorSdkProcessErrorGuard } from "./cursor-sdk-process-error-gu
|
|
|
6
6
|
import { sanitizeCursorProviderError } from "./cursor-provider-errors.js";
|
|
7
7
|
import { resolveCursorApiKey } from "./cursor-api-key.js";
|
|
8
8
|
import { CursorProviderTurnRunner } from "./cursor-provider-turn-runner.js";
|
|
9
|
-
import { getCursorSessionScopeKey } from "./cursor-session-scope.js";
|
|
10
9
|
import { runExclusiveCursorSessionTurn, __testUtils as cursorSessionTurnQueueTestUtils } from "./cursor-session-turn-queue.js";
|
|
11
10
|
function makeInitialMessage(model) {
|
|
12
11
|
return {
|
|
@@ -27,7 +26,8 @@ function makeInitialMessage(model) {
|
|
|
27
26
|
timestamp: Date.now(),
|
|
28
27
|
};
|
|
29
28
|
}
|
|
30
|
-
export function streamCursor(model, context, options) {
|
|
29
|
+
export function streamCursor(model, context, options, ownership) {
|
|
30
|
+
const { scope, bridge, nativeDisplay, recordCloudLifecycle, request, usageRecorder } = ownership;
|
|
31
31
|
const stream = createAssistantMessageEventStream();
|
|
32
32
|
const sdkEventDebugRef = {};
|
|
33
33
|
attachCursorSdkEventDebugPiStreamTap(stream, sdkEventDebugRef);
|
|
@@ -35,6 +35,12 @@ export function streamCursor(model, context, options) {
|
|
|
35
35
|
const partial = makeInitialMessage(model);
|
|
36
36
|
const runner = new CursorProviderTurnRunner({
|
|
37
37
|
model,
|
|
38
|
+
scope,
|
|
39
|
+
bridge,
|
|
40
|
+
nativeDisplay,
|
|
41
|
+
recordCloudLifecycle,
|
|
42
|
+
request,
|
|
43
|
+
usageRecorder,
|
|
38
44
|
context,
|
|
39
45
|
stream,
|
|
40
46
|
partial,
|
|
@@ -43,7 +49,7 @@ export function streamCursor(model, context, options) {
|
|
|
43
49
|
});
|
|
44
50
|
try {
|
|
45
51
|
stream.push({ type: "start", partial });
|
|
46
|
-
await runExclusiveCursorSessionTurn(
|
|
52
|
+
await runExclusiveCursorSessionTurn(scope.scopeKey, () => runner.run(installCursorSdkProcessErrorGuard()), options?.signal);
|
|
47
53
|
}
|
|
48
54
|
catch (error) {
|
|
49
55
|
await runner.handleOuterCatch(error);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { convertToLlm } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
function projectionDigest(messages) {
|
|
4
|
+
const hash = createHash("sha256");
|
|
5
|
+
for (const message of messages) {
|
|
6
|
+
// Stable value equivalence survives Pi's cloning and property insertion order.
|
|
7
|
+
hash.update(JSON.stringify(message, (_key, value) => {
|
|
8
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
9
|
+
return value;
|
|
10
|
+
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)));
|
|
11
|
+
}));
|
|
12
|
+
hash.update("\n");
|
|
13
|
+
}
|
|
14
|
+
return hash.digest("hex");
|
|
15
|
+
}
|
|
16
|
+
export function captureCursorRequestProjection(manager) {
|
|
17
|
+
const branch = manager.getBranch();
|
|
18
|
+
const projection = manager.buildSessionProjection();
|
|
19
|
+
const order = new Map(branch.map((entry, index) => [entry.id, index]));
|
|
20
|
+
const boundary = branch.findLastIndex((entry) => entry.type === "compaction" || entry.type === "context_edit");
|
|
21
|
+
const measurements = [];
|
|
22
|
+
// Raw branch chronology, not projected order or clocks, determines freshness.
|
|
23
|
+
for (const entry of [...projection.entries].sort((a, b) => (order.get(a.sourceEntry.id) ?? -1) - (order.get(b.sourceEntry.id) ?? -1))) {
|
|
24
|
+
if ((order.get(entry.sourceEntry.id) ?? -1) <= boundary)
|
|
25
|
+
continue;
|
|
26
|
+
for (const message of entry.messages) {
|
|
27
|
+
if (message.role !== "assistant" || message.stopReason === "error" || message.stopReason === "aborted")
|
|
28
|
+
continue;
|
|
29
|
+
const tokens = message.usage.totalTokens;
|
|
30
|
+
if (!Number.isFinite(tokens) || tokens <= 0)
|
|
31
|
+
continue;
|
|
32
|
+
measurements.push(Object.freeze({ api: message.api, provider: message.provider, model: message.model, tokens }));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return Object.freeze({ digest: projectionDigest(convertToLlm(projection.messages)), measurements: Object.freeze(measurements) });
|
|
36
|
+
}
|
|
37
|
+
export function resolveCursorRequestProvenance(snapshot, model, context, purpose) {
|
|
38
|
+
if (purpose !== "normal" || snapshot.digest !== projectionDigest(context.messages))
|
|
39
|
+
return Object.freeze({ purpose });
|
|
40
|
+
const measurement = snapshot.measurements.findLast((item) => item.api === model.api && item.provider === model.provider && item.model === model.id && item.tokens <= model.contextWindow);
|
|
41
|
+
return Object.freeze({ purpose, ...(measurement ? { occupancyFloor: measurement.tokens } : {}) });
|
|
42
|
+
}
|
|
@@ -2,12 +2,23 @@ import { accessSync, constants } from "node:fs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, isAbsolute, join } from "node:path";
|
|
4
4
|
const RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
5
|
-
export function
|
|
5
|
+
export function resolveCursorSdkPlatformPackageDirectory(fromModuleUrl = import.meta.url) {
|
|
6
6
|
try {
|
|
7
7
|
const require = createRequire(fromModuleUrl);
|
|
8
|
-
const platformPackage = `@cursor/sdk-${process.platform}-${process.arch}`;
|
|
9
8
|
const sdkEntry = require.resolve("@cursor/sdk");
|
|
10
|
-
|
|
9
|
+
return dirname(require.resolve(`@cursor/sdk-${process.platform}-${process.arch}/package.json`, {
|
|
10
|
+
paths: [dirname(sdkEntry)],
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function resolveBundledCursorRipgrepPath(fromModuleUrl = import.meta.url) {
|
|
18
|
+
const packageDirectory = resolveCursorSdkPlatformPackageDirectory(fromModuleUrl);
|
|
19
|
+
if (!packageDirectory)
|
|
20
|
+
return undefined;
|
|
21
|
+
try {
|
|
11
22
|
const ripgrepPath = join(packageDirectory, "bin", process.platform === "win32" ? "rg.exe" : "rg");
|
|
12
23
|
accessSync(ripgrepPath, constants.X_OK);
|
|
13
24
|
return ripgrepPath;
|