pi-cursor-sdk 0.1.62 → 0.3.6

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.
Files changed (279) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +57 -53
  3. package/dist/bundled-context-windows.js +39 -0
  4. package/dist/context-window-cache.js +92 -0
  5. package/dist/context.js +338 -0
  6. package/dist/cursor-active-tools.js +3 -0
  7. package/dist/cursor-agent-message-web-tools.js +165 -0
  8. package/dist/cursor-agents-context-registration.js +17 -0
  9. package/dist/cursor-agents-context.js +113 -0
  10. package/dist/cursor-api-key.js +34 -0
  11. package/dist/cursor-bridge-contract.js +27 -0
  12. package/dist/cursor-cloud-lifecycle.js +650 -0
  13. package/dist/cursor-cloud-local-state.js +460 -0
  14. package/dist/cursor-cloud-options.js +145 -0
  15. package/dist/cursor-cloud-reporting.js +222 -0
  16. package/dist/cursor-compact-tool-summary.js +75 -0
  17. package/dist/cursor-config.js +613 -0
  18. package/dist/cursor-context-tools.js +4 -0
  19. package/dist/cursor-display-only-trace.js +11 -0
  20. package/dist/cursor-display-text.js +18 -0
  21. package/dist/cursor-durable-fs.js +53 -0
  22. package/dist/cursor-edit-diff.js +13 -0
  23. package/dist/cursor-env-boolean.js +19 -0
  24. package/dist/cursor-fallback-models.generated.js +7760 -0
  25. package/dist/cursor-fallback-warning.js +15 -0
  26. package/dist/cursor-http1.js +45 -0
  27. package/dist/cursor-incomplete-tool-visibility.js +83 -0
  28. package/dist/cursor-live-run-accounting.js +55 -0
  29. package/dist/cursor-live-run-coordinator.js +406 -0
  30. package/dist/cursor-mcp-timeout-override.js +116 -0
  31. package/dist/cursor-model-lifecycle.js +32 -0
  32. package/dist/cursor-model.js +5 -0
  33. package/dist/cursor-native-replay-routing.js +35 -0
  34. package/dist/cursor-native-replay-trace.js +28 -0
  35. package/dist/cursor-native-tool-display-registration.js +102 -0
  36. package/dist/cursor-native-tool-display-replay.js +428 -0
  37. package/dist/cursor-native-tool-display-state.js +70 -0
  38. package/dist/cursor-native-tool-display-tools.js +123 -0
  39. package/dist/cursor-native-tool-names.js +11 -0
  40. package/dist/cursor-partial-content-emitter.js +118 -0
  41. package/dist/cursor-pi-tool-bridge-abort.js +114 -0
  42. package/dist/cursor-pi-tool-bridge-constants.js +6 -0
  43. package/dist/cursor-pi-tool-bridge-diagnostics.js +125 -0
  44. package/dist/cursor-pi-tool-bridge-env.js +18 -0
  45. package/dist/cursor-pi-tool-bridge-mcp.js +100 -0
  46. package/dist/cursor-pi-tool-bridge-run.js +355 -0
  47. package/dist/cursor-pi-tool-bridge-server.js +163 -0
  48. package/dist/cursor-pi-tool-bridge-snapshot.js +63 -0
  49. package/dist/cursor-pi-tool-bridge-types.js +1 -0
  50. package/dist/cursor-pi-tool-bridge.js +123 -0
  51. package/dist/cursor-provider-errors.js +311 -0
  52. package/dist/cursor-provider-lazy.js +39 -0
  53. package/dist/cursor-provider-live-run-drain.js +412 -0
  54. package/dist/cursor-provider-overflow.js +90 -0
  55. package/dist/cursor-provider-run-finalizer.js +176 -0
  56. package/dist/cursor-provider-run-outcome.js +76 -0
  57. package/dist/cursor-provider-turn-coordinator.js +275 -0
  58. package/dist/cursor-provider-turn-display-router.js +158 -0
  59. package/dist/cursor-provider-turn-emit.js +35 -0
  60. package/dist/cursor-provider-turn-finalize.js +154 -0
  61. package/dist/cursor-provider-turn-lifecycle-emitter.js +126 -0
  62. package/dist/cursor-provider-turn-prepare.js +374 -0
  63. package/dist/cursor-provider-turn-runner.js +146 -0
  64. package/dist/cursor-provider-turn-sdk-normalizer.js +74 -0
  65. package/dist/cursor-provider-turn-send.js +138 -0
  66. package/dist/cursor-provider-turn-shell-output.js +117 -0
  67. package/dist/cursor-provider-turn-tool-ledger.js +99 -0
  68. package/dist/cursor-provider-turn-types.js +1 -0
  69. package/dist/cursor-provider.js +72 -0
  70. package/dist/cursor-question-tool.js +194 -0
  71. package/dist/cursor-record-utils.js +61 -0
  72. package/dist/cursor-replay-activity-builders.js +114 -0
  73. package/dist/cursor-replay-source-names.js +27 -0
  74. package/dist/cursor-replay-summary-args.js +105 -0
  75. package/dist/cursor-replay-tool-details.js +167 -0
  76. package/dist/cursor-ripgrep-path.js +27 -0
  77. package/dist/cursor-run-final-text.js +63 -0
  78. package/dist/cursor-runtime-state.js +380 -0
  79. package/dist/cursor-sdk-billed-usage.js +86 -0
  80. package/dist/cursor-sdk-event-debug-constants.js +33 -0
  81. package/dist/cursor-sdk-event-debug-session.js +107 -0
  82. package/dist/cursor-sdk-event-debug.js +461 -0
  83. package/dist/cursor-sdk-output-filter.js +1 -0
  84. package/dist/cursor-sdk-process-error-guard.js +221 -0
  85. package/dist/cursor-sdk-runtime.js +3 -0
  86. package/dist/cursor-sensitive-text.js +23 -0
  87. package/dist/cursor-session-agent-cleanup.js +311 -0
  88. package/dist/cursor-session-agent-lifecycle.js +32 -0
  89. package/dist/cursor-session-agent-lineage.js +103 -0
  90. package/dist/cursor-session-agent-resume.js +417 -0
  91. package/dist/cursor-session-agent.js +507 -0
  92. package/dist/cursor-session-compaction-prep.js +21 -0
  93. package/dist/cursor-session-scope.js +113 -0
  94. package/dist/cursor-session-send-policy.js +18 -0
  95. package/dist/cursor-session-store.js +105 -0
  96. package/dist/cursor-session-turn-queue.js +50 -0
  97. package/dist/cursor-setting-sources.js +15 -0
  98. package/dist/cursor-skill-tool.js +230 -0
  99. package/dist/cursor-state.js +519 -0
  100. package/dist/cursor-task-presentation.js +59 -0
  101. package/dist/cursor-tool-lifecycle.js +94 -0
  102. package/dist/cursor-tool-manifest.js +34 -0
  103. package/dist/cursor-tool-presentation-registry.js +305 -0
  104. package/dist/cursor-tool-result-display-readers.js +158 -0
  105. package/dist/cursor-tool-transcript.js +32 -0
  106. package/dist/cursor-tool-visibility.js +28 -0
  107. package/dist/cursor-transcript-tool-formatters.js +618 -0
  108. package/dist/cursor-transcript-tool-specs.js +284 -0
  109. package/dist/cursor-transcript-utils.js +170 -0
  110. package/dist/cursor-usage-accounting.js +166 -0
  111. package/dist/cursor-web-tool-activity.js +23 -0
  112. package/dist/cursor-web-tool-args.js +12 -0
  113. package/dist/index.js +82 -0
  114. package/dist/model-discovery.js +305 -0
  115. package/dist/model-list-cache.js +156 -0
  116. package/docs/cursor-dogfood-checklist.md +2 -1
  117. package/docs/cursor-live-smoke-checklist.md +15 -14
  118. package/docs/cursor-model-ux-spec.md +29 -8
  119. package/docs/cursor-native-tool-replay.md +13 -13
  120. package/docs/cursor-native-tool-visual-audit.md +6 -3
  121. package/docs/cursor-testing-lessons.md +7 -7
  122. package/docs/cursor-tool-surfaces.md +5 -5
  123. package/docs/platform-smoke.md +6 -6
  124. package/node_modules/fast-uri/index.js +37 -1
  125. package/node_modules/fast-uri/package.json +1 -1
  126. package/node_modules/fast-uri/test/security.test.js +136 -0
  127. package/node_modules/hono/dist/cjs/context.js +28 -13
  128. package/node_modules/hono/dist/cjs/helper/proxy/index.js +4 -0
  129. package/node_modules/hono/dist/cjs/helper/streaming/sse.js +1 -1
  130. package/node_modules/hono/dist/cjs/hono-base.js +3 -2
  131. package/node_modules/hono/dist/cjs/jsx/base.js +27 -23
  132. package/node_modules/hono/dist/cjs/jsx/hooks/index.js +16 -13
  133. package/node_modules/hono/dist/cjs/middleware/cache/index.js +103 -8
  134. package/node_modules/hono/dist/cjs/middleware/compress/index.js +5 -0
  135. package/node_modules/hono/dist/cjs/middleware/cors/index.js +2 -2
  136. package/node_modules/hono/dist/cjs/middleware/etag/index.js +1 -1
  137. package/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +9 -4
  138. package/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +9 -4
  139. package/node_modules/hono/dist/cjs/middleware/language/language.js +10 -6
  140. package/node_modules/hono/dist/cjs/middleware/method-not-allowed/index.js +90 -0
  141. package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +10 -4
  142. package/node_modules/hono/dist/cjs/request.js +7 -9
  143. package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +55 -56
  144. package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +64 -85
  145. package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +13 -5
  146. package/node_modules/hono/dist/cjs/router.js +1 -1
  147. package/node_modules/hono/dist/cjs/utils/accept.js +1 -1
  148. package/node_modules/hono/dist/cjs/utils/cookie.js +3 -2
  149. package/node_modules/hono/dist/cjs/utils/url.js +8 -8
  150. package/node_modules/hono/dist/context.js +28 -13
  151. package/node_modules/hono/dist/helper/proxy/index.js +4 -0
  152. package/node_modules/hono/dist/helper/streaming/sse.js +1 -1
  153. package/node_modules/hono/dist/hono-base.js +3 -2
  154. package/node_modules/hono/dist/jsx/base.js +27 -23
  155. package/node_modules/hono/dist/jsx/hooks/index.js +16 -13
  156. package/node_modules/hono/dist/middleware/cache/index.js +103 -8
  157. package/node_modules/hono/dist/middleware/compress/index.js +5 -0
  158. package/node_modules/hono/dist/middleware/cors/index.js +2 -2
  159. package/node_modules/hono/dist/middleware/etag/index.js +1 -1
  160. package/node_modules/hono/dist/middleware/jwk/jwk.js +9 -4
  161. package/node_modules/hono/dist/middleware/jwt/jwt.js +9 -4
  162. package/node_modules/hono/dist/middleware/language/language.js +10 -6
  163. package/node_modules/hono/dist/middleware/method-not-allowed/index.js +68 -0
  164. package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +10 -4
  165. package/node_modules/hono/dist/request.js +8 -10
  166. package/node_modules/hono/dist/router/reg-exp-router/node.js +55 -56
  167. package/node_modules/hono/dist/router/reg-exp-router/router.js +64 -85
  168. package/node_modules/hono/dist/router/reg-exp-router/trie.js +13 -5
  169. package/node_modules/hono/dist/router.js +1 -1
  170. package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
  171. package/node_modules/hono/dist/types/client/types.d.ts +1 -1
  172. package/node_modules/hono/dist/types/hono-base.d.ts +4 -3
  173. package/node_modules/hono/dist/types/jsx/base.d.ts +4 -2
  174. package/node_modules/hono/dist/types/jsx/dom/index.d.ts +5 -5
  175. package/node_modules/hono/dist/types/jsx/dom/intrinsic-element/components.d.ts +2 -2
  176. package/node_modules/hono/dist/types/jsx/dom/server.d.ts +5 -5
  177. package/node_modules/hono/dist/types/jsx/hooks/index.d.ts +8 -6
  178. package/node_modules/hono/dist/types/jsx/index.d.ts +5 -5
  179. package/node_modules/hono/dist/types/middleware/cache/index.d.ts +6 -4
  180. package/node_modules/hono/dist/types/middleware/cors/index.d.ts +1 -1
  181. package/node_modules/hono/dist/types/middleware/jsx-renderer/index.d.ts +2 -2
  182. package/node_modules/hono/dist/types/middleware/jwk/jwk.d.ts +2 -0
  183. package/node_modules/hono/dist/types/middleware/jwt/jwt.d.ts +2 -0
  184. package/node_modules/hono/dist/types/middleware/method-not-allowed/index.d.ts +49 -0
  185. package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +1 -1
  186. package/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +2 -1
  187. package/node_modules/hono/dist/types/router.d.ts +1 -1
  188. package/node_modules/hono/dist/types/utils/headers.d.ts +2 -2
  189. package/node_modules/hono/dist/types/utils/url.d.ts +1 -0
  190. package/node_modules/hono/dist/utils/accept.js +1 -1
  191. package/node_modules/hono/dist/utils/cookie.js +4 -3
  192. package/node_modules/hono/dist/utils/url.js +6 -7
  193. package/node_modules/hono/package.json +10 -3
  194. package/node_modules/ip-address/README.md +146 -126
  195. package/node_modules/ip-address/dist/common.d.ts +29 -0
  196. package/node_modules/ip-address/dist/common.js +44 -5
  197. package/node_modules/ip-address/dist/common.js.map +1 -1
  198. package/node_modules/ip-address/dist/ipv4.d.ts +8 -1
  199. package/node_modules/ip-address/dist/ipv4.js +24 -20
  200. package/node_modules/ip-address/dist/ipv4.js.map +1 -1
  201. package/node_modules/ip-address/dist/ipv6.d.ts +68 -3
  202. package/node_modules/ip-address/dist/ipv6.js +180 -53
  203. package/node_modules/ip-address/dist/ipv6.js.map +1 -1
  204. package/node_modules/ip-address/dist/v4/constants.js +5 -1
  205. package/node_modules/ip-address/dist/v4/constants.js.map +1 -1
  206. package/node_modules/ip-address/dist/v6/constants.js +3 -2
  207. package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
  208. package/node_modules/ip-address/package.json +6 -4
  209. package/package.json +23 -11
  210. package/platform-smoke.config.mjs +1 -1
  211. package/scripts/build.mjs +126 -0
  212. package/scripts/cloud-runtime-smoke.mjs +3 -1
  213. package/scripts/debug-provider-events.mjs +3 -1
  214. package/scripts/debug-sdk-events.mjs +1 -1
  215. package/scripts/isolated-cursor-smoke.sh +5 -4
  216. package/scripts/lib/cloud-smoke-cleanup-evidence.mjs +1 -1
  217. package/scripts/lib/cursor-visual-render.mjs +1 -1
  218. package/scripts/lib/ensure-built.mjs +16 -0
  219. package/scripts/lib/local-resume-smoke-harness.mjs +1 -1
  220. package/scripts/local-resume-smoke.mjs +3 -1
  221. package/scripts/platform-smoke/card-detect.mjs +1 -1
  222. package/scripts/platform-smoke/live-suite-runner.mjs +16 -40
  223. package/scripts/platform-smoke/platform-build-windows.ps1 +1 -1
  224. package/scripts/platform-smoke/render-ansi.mjs +1 -1
  225. package/scripts/platform-smoke/scenarios.mjs +1 -1
  226. package/scripts/platform-smoke/targets.mjs +2 -2
  227. package/scripts/platform-smoke.mjs +5 -5
  228. package/scripts/prepare.mjs +102 -0
  229. package/scripts/refresh-cursor-model-snapshots.mjs +16 -7
  230. package/scripts/steering-rpc-smoke.mjs +4 -2
  231. package/scripts/tmux-live-smoke.sh +11 -11
  232. package/scripts/visual-tui-smoke-self-test.mjs +4 -1
  233. package/scripts/visual-tui-smoke.mjs +51 -7
  234. package/shared/cursor-model-selection-identities.d.mts +21 -0
  235. package/shared/cursor-model-selection-identities.mjs +95 -0
  236. package/src/bundled-context-windows.ts +21 -12
  237. package/src/context.ts +1 -1
  238. package/src/cursor-agents-context-registration.ts +2 -2
  239. package/src/cursor-agents-context.ts +0 -2
  240. package/src/cursor-api-key.ts +5 -4
  241. package/src/cursor-cloud-reporting.ts +23 -2
  242. package/src/cursor-context-tools.ts +1 -1
  243. package/src/cursor-display-only-trace.ts +1 -1
  244. package/src/cursor-fallback-models.generated.ts +1726 -824
  245. package/src/cursor-live-run-accounting.ts +1 -1
  246. package/src/cursor-live-run-coordinator.ts +2 -1
  247. package/src/cursor-native-replay-routing.ts +1 -1
  248. package/src/cursor-native-tool-display-registration.ts +10 -11
  249. package/src/cursor-partial-content-emitter.ts +1 -1
  250. package/src/cursor-pi-tool-bridge-mcp.ts +1 -1
  251. package/src/cursor-pi-tool-bridge-run.ts +1 -1
  252. package/src/cursor-pi-tool-bridge-types.ts +1 -1
  253. package/src/cursor-provider-errors.ts +1 -1
  254. package/src/cursor-provider-lazy.ts +6 -5
  255. package/src/cursor-provider-live-run-drain.ts +2 -1
  256. package/src/cursor-provider-overflow.ts +1 -1
  257. package/src/cursor-provider-run-finalizer.ts +2 -1
  258. package/src/cursor-provider-turn-coordinator.ts +1 -1
  259. package/src/cursor-provider-turn-finalize.ts +12 -0
  260. package/src/cursor-provider-turn-lifecycle-emitter.ts +1 -1
  261. package/src/cursor-provider-turn-prepare.ts +1 -1
  262. package/src/cursor-provider-turn-types.ts +3 -1
  263. package/src/cursor-provider.ts +1 -1
  264. package/src/cursor-run-final-text.ts +1 -1
  265. package/src/cursor-sdk-billed-usage.ts +107 -0
  266. package/src/cursor-sdk-event-debug.ts +1 -1
  267. package/src/cursor-sdk-process-error-guard.ts +6 -4
  268. package/src/cursor-session-agent-lifecycle.ts +8 -9
  269. package/src/cursor-session-agent-resume.ts +23 -0
  270. package/src/cursor-session-agent.ts +1 -1
  271. package/src/cursor-session-compaction-prep.ts +4 -0
  272. package/src/cursor-session-send-policy.ts +1 -1
  273. package/src/cursor-tool-manifest.ts +1 -1
  274. package/src/cursor-usage-accounting.ts +71 -10
  275. package/src/index.ts +1 -1
  276. package/src/model-discovery.ts +32 -89
  277. package/tsconfig.build.json +8 -0
  278. package/tsconfig.json +16 -0
  279. package/node_modules/cross-spawn/node_modules/which/CHANGELOG.md +0 -166
@@ -0,0 +1,154 @@
1
+ import { loadCursorTranscriptWebToolCallsAfterOffset } from "./cursor-agent-message-web-tools.js";
2
+ import { collectCursorCloudRunReport, formatCursorCloudRunReport, } from "./cursor-cloud-reporting.js";
3
+ import { recordCursorCloudLifecycleRun } from "./cursor-cloud-lifecycle.js";
4
+ import { getCheckpointContextWindow, saveCachedContextWindow } from "./context-window-cache.js";
5
+ import { scrubSensitiveText } from "./cursor-sensitive-text.js";
6
+ import { isCursorRunFinishedSuccessfully, resolveCursorRunOutcome, } from "./cursor-provider-run-outcome.js";
7
+ import { loadCursorSdk } from "./cursor-sdk-runtime.js";
8
+ import { attachCursorSdkBilledTurnUsage } from "./cursor-sdk-billed-usage.js";
9
+ export async function cacheSdkContextWindow(agentId, modelId, cwd, store) {
10
+ try {
11
+ const { createAgentPlatform } = await loadCursorSdk();
12
+ const platform = await createAgentPlatform(cwd || store
13
+ ? {
14
+ ...(cwd ? { workspaceRef: cwd, scopedWorkspaceRef: cwd } : {}),
15
+ ...(store ? { localStore: store } : {}),
16
+ }
17
+ : undefined);
18
+ const checkpoint = await platform.checkpointStore.loadLatest(agentId);
19
+ const contextWindow = getCheckpointContextWindow(checkpoint);
20
+ if (contextWindow)
21
+ saveCachedContextWindow(modelId, contextWindow);
22
+ }
23
+ catch {
24
+ // Context-window cache failures must not affect response streaming.
25
+ }
26
+ }
27
+ export function buildCursorRunOutcomeFromWait(params) {
28
+ const { waitResult, prepared } = params;
29
+ const { turnCoordinator, liveRun } = prepared.runtime;
30
+ const { textDeltas } = prepared;
31
+ return resolveCursorRunOutcome({
32
+ waitResult,
33
+ signalAborted: params.signal?.aborted,
34
+ textDeltas: liveRun?.textDeltas ?? textDeltas,
35
+ emittedText: liveRun?.emittedText ?? textDeltas.join(""),
36
+ planTextCandidate: turnCoordinator.planTextCandidate,
37
+ selectFinalTextOptions: liveRun ? undefined : { allowPartialPrefix: true },
38
+ runResultFallback: params.runResultFallback,
39
+ runErrorFallback: params.runErrorFallback,
40
+ resolvedApiKey: params.resolvedApiKey,
41
+ optionsApiKey: params.optionsApiKey,
42
+ runtimeTarget: prepared.runtimeTarget,
43
+ });
44
+ }
45
+ async function replayCursorTranscriptWebToolCalls(agentId, cwd, messageOffset, turnStore, turnCoordinator, sdkEventDebug) {
46
+ try {
47
+ const transcriptToolCalls = await loadCursorTranscriptWebToolCallsAfterOffset({
48
+ agentId,
49
+ cwd,
50
+ offset: messageOffset,
51
+ store: turnStore,
52
+ });
53
+ if (transcriptToolCalls.length === 0)
54
+ return;
55
+ sdkEventDebug?.recordCoordinatorEvent("cursor-transcript-web-tools", {
56
+ agentId,
57
+ messageOffset,
58
+ count: transcriptToolCalls.length,
59
+ });
60
+ turnCoordinator.handleTranscriptCompletedToolCalls(transcriptToolCalls);
61
+ }
62
+ catch (error) {
63
+ sdkEventDebug?.recordError("cursor_transcript_web_tools", error);
64
+ }
65
+ }
66
+ function scrubCursorCloudReportingError(error, apiKey) {
67
+ return new Error(scrubSensitiveText(error instanceof Error ? error.message : String(error), apiKey));
68
+ }
69
+ function recordCursorCloudReportingError(sdkEventDebug, error, apiKey) {
70
+ try {
71
+ sdkEventDebug?.recordError("cloud_run_report", scrubCursorCloudReportingError(error, apiKey));
72
+ }
73
+ catch {
74
+ // Debug reporting must never affect provider execution.
75
+ }
76
+ }
77
+ /** Single wait/finalize path for SDK runs: wait, debug capture, transcript replay, incomplete tools, artifacts, context cache. */
78
+ export async function awaitFinalizeCursorRunOutcome(params) {
79
+ const apiKey = params.resolvedApiKey ?? params.optionsApiKey;
80
+ const waitResult = params.waitResult ?? (await params.run.wait());
81
+ const outcome = buildCursorRunOutcomeFromWait({
82
+ waitResult,
83
+ prepared: params.prepared,
84
+ signal: params.signal,
85
+ runResultFallback: params.runResultFallback,
86
+ runErrorFallback: params.runErrorFallback,
87
+ resolvedApiKey: params.resolvedApiKey,
88
+ optionsApiKey: params.optionsApiKey,
89
+ });
90
+ const billed = await attachCursorSdkBilledTurnUsage({
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
+ }
100
+ let displayOnlyTraceBlock;
101
+ if (params.prepared.runtimeTarget === "cloud" && isCursorRunFinishedSuccessfully(outcome)) {
102
+ let report = { agentId: params.run.agentId, runId: params.run.id, branches: [] };
103
+ try {
104
+ report = await collectCursorCloudRunReport({
105
+ agent: params.prepared.agent,
106
+ run: params.run,
107
+ waitResult,
108
+ apiKey,
109
+ agentUsage: billed.agentUsage,
110
+ });
111
+ }
112
+ catch (error) {
113
+ recordCursorCloudReportingError(params.sdkEventDebug, error, apiKey);
114
+ }
115
+ try {
116
+ recordCursorCloudLifecycleRun(report, { apiKey });
117
+ }
118
+ catch (error) {
119
+ recordCursorCloudReportingError(params.sdkEventDebug, error, apiKey);
120
+ }
121
+ try {
122
+ params.sdkEventDebug?.recordProviderEvent("cloud_run_report", report);
123
+ }
124
+ catch (error) {
125
+ recordCursorCloudReportingError(params.sdkEventDebug, error, apiKey);
126
+ }
127
+ try {
128
+ displayOnlyTraceBlock = formatCursorCloudRunReport(report, { apiKey });
129
+ }
130
+ catch (error) {
131
+ recordCursorCloudReportingError(params.sdkEventDebug, error, apiKey);
132
+ }
133
+ }
134
+ try {
135
+ params.sdkEventDebug?.recordWaitResult(waitResult);
136
+ }
137
+ catch {
138
+ // Debug reporting must never affect provider execution.
139
+ }
140
+ if (params.prepared.runtimeTarget === "local" && isCursorRunFinishedSuccessfully(outcome)) {
141
+ await replayCursorTranscriptWebToolCalls(params.run.agentId, params.prepared.cwd, params.cursorAgentMessageOffset, params.prepared.sessionAgentLease.store, params.prepared.runtime.turnCoordinator, params.sdkEventDebug);
142
+ }
143
+ params.prepared.runtime.turnCoordinator.discardIncompleteStartedToolCalls(outcome.incompleteTools);
144
+ try {
145
+ await params.sdkEventDebug?.captureRunArtifacts(params.run);
146
+ }
147
+ catch {
148
+ // Debug artifact failures must never affect provider execution.
149
+ }
150
+ if (params.prepared.runtimeTarget === "local" && params.cacheContextWindow !== false) {
151
+ await cacheSdkContextWindow(params.contextWindowAgentId ?? params.run.agentId, params.modelId, params.prepared.cwd, params.prepared.sessionAgentLease.store);
152
+ }
153
+ return { outcome, displayOnlyTraceBlock };
154
+ }
@@ -0,0 +1,126 @@
1
+ import { cursorLiveRuns } from "./cursor-provider-live-run-drain.js";
2
+ import { CursorPartialContentEmitter } from "./cursor-partial-content-emitter.js";
3
+ import { CURSOR_TOOL_LIFECYCLE_DEFER_MS, formatCursorToolLifecycleProgressText, isCursorToolLifecycleEligible, } from "./cursor-tool-lifecycle.js";
4
+ import { getNormalizedCursorToolName } from "./cursor-tool-visibility.js";
5
+ import { getStartedToolCallFingerprint } from "./cursor-provider-turn-tool-ledger.js";
6
+ export class CursorToolLifecycleEmitter {
7
+ liveRun;
8
+ resolvedApiKey;
9
+ contentEmitter;
10
+ debugRecorder;
11
+ hasStartedToolCall;
12
+ isBridgeMcpToolCall;
13
+ emittedLifecycleCallIds = new Set();
14
+ lifecycleTimers = new Map();
15
+ activeLifecycleFingerprintOwners = new Map();
16
+ lifecycleFingerprintByCallId = new Map();
17
+ activeLifecycleProgressTextOwners = new Map();
18
+ lifecycleProgressTextByCallId = new Map();
19
+ constructor(options) {
20
+ this.liveRun = options.liveRun;
21
+ this.resolvedApiKey = options.resolvedApiKey;
22
+ this.contentEmitter = options.contentEmitter;
23
+ this.debugRecorder = options.debugRecorder;
24
+ this.hasStartedToolCall = options.hasStartedToolCall;
25
+ this.isBridgeMcpToolCall = options.isBridgeMcpToolCall;
26
+ }
27
+ maybeSchedule(callId, toolCall) {
28
+ if (typeof callId !== "string" || this.emittedLifecycleCallIds.has(callId))
29
+ return;
30
+ if (this.isBridgeMcpToolCall(toolCall))
31
+ return;
32
+ if (!isCursorToolLifecycleEligible(toolCall))
33
+ return;
34
+ const progressText = formatCursorToolLifecycleProgressText(toolCall, this.resolvedApiKey);
35
+ if (!progressText)
36
+ return;
37
+ const fingerprint = getStartedToolCallFingerprint(toolCall);
38
+ const existingOwner = this.activeLifecycleFingerprintOwners.get(fingerprint);
39
+ if (existingOwner && existingOwner !== callId) {
40
+ this.debugRecorder?.recordCoordinatorEvent("tool_lifecycle_skip", {
41
+ callId,
42
+ ownerCallId: existingOwner,
43
+ toolName: getNormalizedCursorToolName(toolCall),
44
+ reason: "duplicate-active-fingerprint",
45
+ });
46
+ return;
47
+ }
48
+ this.cancel(callId);
49
+ this.activeLifecycleFingerprintOwners.set(fingerprint, callId);
50
+ this.lifecycleFingerprintByCallId.set(callId, fingerprint);
51
+ if (!this.activeLifecycleProgressTextOwners.has(progressText)) {
52
+ this.activeLifecycleProgressTextOwners.set(progressText, callId);
53
+ }
54
+ this.lifecycleProgressTextByCallId.set(callId, progressText);
55
+ const timer = setTimeout(() => {
56
+ this.lifecycleTimers.delete(callId);
57
+ if (!this.hasStartedToolCall(callId)) {
58
+ this.clearLifecycleIdentity(callId);
59
+ return;
60
+ }
61
+ if (this.emittedLifecycleCallIds.has(callId))
62
+ return;
63
+ const progressOwner = this.activeLifecycleProgressTextOwners.get(progressText);
64
+ if (progressOwner && progressOwner !== callId && this.hasStartedToolCall(progressOwner)) {
65
+ this.debugRecorder?.recordCoordinatorEvent("tool_lifecycle_skip", {
66
+ callId,
67
+ ownerCallId: progressOwner,
68
+ toolName: getNormalizedCursorToolName(toolCall),
69
+ reason: "duplicate-active-progress-text",
70
+ });
71
+ return;
72
+ }
73
+ this.activeLifecycleProgressTextOwners.set(progressText, callId);
74
+ this.emit(callId, toolCall, progressText);
75
+ }, CURSOR_TOOL_LIFECYCLE_DEFER_MS);
76
+ timer.unref?.();
77
+ this.lifecycleTimers.set(callId, timer);
78
+ }
79
+ cancel(callId) {
80
+ const timer = this.lifecycleTimers.get(callId);
81
+ if (timer) {
82
+ clearTimeout(timer);
83
+ this.lifecycleTimers.delete(callId);
84
+ }
85
+ this.clearLifecycleIdentity(callId);
86
+ }
87
+ clear() {
88
+ this.emittedLifecycleCallIds.clear();
89
+ for (const timer of this.lifecycleTimers.values())
90
+ clearTimeout(timer);
91
+ this.lifecycleTimers.clear();
92
+ this.activeLifecycleFingerprintOwners.clear();
93
+ this.lifecycleFingerprintByCallId.clear();
94
+ this.activeLifecycleProgressTextOwners.clear();
95
+ this.lifecycleProgressTextByCallId.clear();
96
+ }
97
+ clearLifecycleIdentity(callId) {
98
+ const fingerprint = this.lifecycleFingerprintByCallId.get(callId);
99
+ if (fingerprint && this.activeLifecycleFingerprintOwners.get(fingerprint) === callId) {
100
+ this.activeLifecycleFingerprintOwners.delete(fingerprint);
101
+ }
102
+ this.lifecycleFingerprintByCallId.delete(callId);
103
+ const progressText = this.lifecycleProgressTextByCallId.get(callId);
104
+ if (progressText && this.activeLifecycleProgressTextOwners.get(progressText) === callId) {
105
+ this.activeLifecycleProgressTextOwners.delete(progressText);
106
+ }
107
+ this.lifecycleProgressTextByCallId.delete(callId);
108
+ }
109
+ emit(callId, toolCall, progressText) {
110
+ this.emittedLifecycleCallIds.add(callId);
111
+ this.debugRecorder?.recordCoordinatorEvent("tool_lifecycle", {
112
+ callId,
113
+ toolName: getNormalizedCursorToolName(toolCall),
114
+ progressText,
115
+ liveRun: this.liveRun !== undefined,
116
+ });
117
+ if (this.liveRun) {
118
+ cursorLiveRuns.queueEvent(this.liveRun, { type: "thinking-delta", text: progressText });
119
+ return;
120
+ }
121
+ this.contentEmitter.appendThinkingDelta(progressText);
122
+ }
123
+ }
124
+ export function createTurnCoordinatorContentEmitter(stream, partial) {
125
+ return new CursorPartialContentEmitter(stream, partial, undefined, false);
126
+ }
@@ -0,0 +1,374 @@
1
+ import { configureCursorSdkHttp1 } from "./cursor-http1.js";
2
+ import { installCursorMcpToolTimeoutOverride } from "./cursor-mcp-timeout-override.js";
3
+ import { ensureCursorRipgrepPath } from "./cursor-ripgrep-path.js";
4
+ import { installCursorSdkOutputFilter, suppressCursorSdkOutput } from "./cursor-sdk-output-filter.js";
5
+ import { acquireSessionCursorAgent, buildCursorSessionSendPrompt, planCursorSessionSend, resetSessionCursorAgent, } from "./cursor-session-agent.js";
6
+ import { buildCursorPrompt, estimateCursorPromptTokens } from "./context.js";
7
+ import { getCursorPromptOptions } from "./cursor-usage-accounting.js";
8
+ import { getActiveContextToolNames } from "./cursor-context-tools.js";
9
+ import { abandonSessionCursorAgent, createCursorNativeReplayId, cursorLiveRuns, getActiveCursorLiveRunForCurrentScope, getPendingCursorLiveRun, } from "./cursor-provider-live-run-drain.js";
10
+ import { getCursorProviderAgentModeOrThrow, getEffectiveFastForModelId, } from "./cursor-state.js";
11
+ import { resolveEffectiveCursorConfig } from "./cursor-runtime-state.js";
12
+ import { buildCursorModelSelection } from "./model-discovery.js";
13
+ import { getEffectiveCursorSettingSources } from "./cursor-setting-sources.js";
14
+ import { formatCursorCloudPreflightError, buildCursorCloudAgentOptions, preflightCursorCloudRuntime, } from "./cursor-cloud-options.js";
15
+ import { inspectCursorCloudLocalState } from "./cursor-cloud-local-state.js";
16
+ import { getCursorSessionName, getCursorSessionProjectTrusted } from "./cursor-session-scope.js";
17
+ import { resolveCursorPiToolBridgeEnabled } from "./cursor-pi-tool-bridge-env.js";
18
+ import { buildCursorToolManifestText, resolveCursorToolManifestEnabled, } from "./cursor-tool-manifest.js";
19
+ import { isCursorNativeToolDisplayRuntimeEnabled } from "./cursor-native-tool-display-state.js";
20
+ import { createCursorCloudLifecyclePersistenceError, recordCursorCloudLifecycleSafely, } from "./cursor-cloud-lifecycle.js";
21
+ import { MISSING_CURSOR_API_KEY_MESSAGE } from "./cursor-provider-errors.js";
22
+ import { CursorSdkTurnCoordinator } from "./cursor-provider-turn-coordinator.js";
23
+ import { resolveCursorApiKey } from "./cursor-api-key.js";
24
+ import { loadCursorSdk } from "./cursor-sdk-runtime.js";
25
+ function buildCursorCloudPromptContext(context, handoff) {
26
+ if (handoff === "bootstrap")
27
+ return context;
28
+ for (let index = context.messages.length - 1; index >= 0; index -= 1) {
29
+ const message = context.messages[index];
30
+ if (message.role === "user")
31
+ return { ...context, messages: [message] };
32
+ }
33
+ return { ...context, messages: context.messages.slice(-1) };
34
+ }
35
+ const CLOUD_SEND_PLAN = { mode: "bootstrap", resetAgent: false, reason: "initial" };
36
+ export function resolveCursorProviderTurnConfig(cwd) {
37
+ return resolveEffectiveCursorConfig({ cwd, projectTrusted: getCursorSessionProjectTrusted() });
38
+ }
39
+ function buildCloudCursorProviderTurnLifecycle(agent) {
40
+ return {
41
+ trackRunCompletion: () => { },
42
+ commitSend: () => { },
43
+ abandon: async () => { },
44
+ dispose: async () => {
45
+ await agent[Symbol.asyncDispose]?.();
46
+ },
47
+ };
48
+ }
49
+ function buildLocalCursorProviderTurnLifecycle(lease, scopeKey) {
50
+ return {
51
+ trackRunCompletion: (completion) => lease.trackRunCompletion(completion),
52
+ commitSend: (context, bootstrapped) => lease.commitSend(context, bootstrapped),
53
+ abandon: () => abandonSessionCursorAgent(scopeKey),
54
+ dispose: async () => { },
55
+ };
56
+ }
57
+ async function prepareCursorCloudProviderTurn(prepareParams) {
58
+ const { params, cwd, resolvedApiKey, sdkEventDebug, throwIfAborted, resolvedConfig, agentMode, selection, fastEnabled } = prepareParams;
59
+ const { model, context, options } = params;
60
+ let restoreCursorSdkOutputFilter;
61
+ let cloudAgentForCleanup;
62
+ let completed = false;
63
+ try {
64
+ const preflight = preflightCursorCloudRuntime({
65
+ resolvedConfig,
66
+ localState: resolvedConfig.cloud.allowLocalState.value
67
+ ? { insideGitRepo: false }
68
+ : inspectCursorCloudLocalState(cwd, {
69
+ repo: resolvedConfig.cloud.repo.value,
70
+ branch: resolvedConfig.cloud.branch.value,
71
+ }),
72
+ hasPriorContext: context.messages.length > 1,
73
+ });
74
+ if (!preflight.ok)
75
+ throw new Error(formatCursorCloudPreflightError(preflight));
76
+ if (getPendingCursorLiveRun(context) || getActiveCursorLiveRunForCurrentScope()) {
77
+ throw new Error("Cursor cloud runtime cannot start while a local Cursor live run is pending; finish or abort the local run, then retry.");
78
+ }
79
+ const { Agent } = await loadCursorSdk();
80
+ restoreCursorSdkOutputFilter = installCursorSdkOutputFilter();
81
+ const promptOptions = {
82
+ ...getCursorPromptOptions(model),
83
+ agentMode,
84
+ includePiBridgeGuidance: false,
85
+ includePiAskQuestionGuidance: false,
86
+ };
87
+ const prompt = buildCursorPrompt(buildCursorCloudPromptContext(context, resolvedConfig.cloud.contextHandoff.value), promptOptions);
88
+ const promptInputTokens = estimateCursorPromptTokens(prompt, promptOptions);
89
+ const agent = await suppressCursorSdkOutput(() => Agent.create(buildCursorCloudAgentOptions({
90
+ apiKey: resolvedApiKey,
91
+ modelSelection: selection,
92
+ agentMode,
93
+ resolvedConfig,
94
+ name: getCursorSessionName(),
95
+ })));
96
+ cloudAgentForCleanup = agent;
97
+ if (!recordCursorCloudLifecycleSafely({ agentId: agent.agentId }, resolvedApiKey)) {
98
+ throw createCursorCloudLifecyclePersistenceError(agent.agentId, "intent", undefined, resolvedApiKey);
99
+ }
100
+ sdkEventDebug?.recordProviderMeta({ runtime: "cloud", cloudAgentId: agent.agentId, phase: "agent_created" });
101
+ throwIfAborted();
102
+ const textDeltas = [];
103
+ const nativeReplayId = createCursorNativeReplayId();
104
+ const turnCoordinator = new CursorSdkTurnCoordinator({
105
+ stream: params.stream,
106
+ partial: params.partial,
107
+ cwd,
108
+ resolvedApiKey,
109
+ useNativeToolReplay: false,
110
+ nativeReplayId,
111
+ textDeltas,
112
+ debugRecorder: sdkEventDebug,
113
+ });
114
+ sdkEventDebug?.recordProviderMeta({
115
+ runtime: "cloud",
116
+ cloudAgentId: agent.agentId,
117
+ model: {
118
+ id: model.id,
119
+ provider: model.provider,
120
+ api: model.api,
121
+ reasoning: options?.reasoning ?? "off",
122
+ fastEnabled,
123
+ selection,
124
+ },
125
+ contextHandoff: resolvedConfig.cloud.contextHandoff.value,
126
+ sendPlan: CLOUD_SEND_PLAN,
127
+ promptOptions,
128
+ agentMode,
129
+ localForce: false,
130
+ });
131
+ completed = true;
132
+ cloudAgentForCleanup = undefined;
133
+ return {
134
+ runtimeTarget: "cloud",
135
+ agent,
136
+ cwd,
137
+ payload: {
138
+ text: prompt.text,
139
+ images: prompt.images.length > 0 ? prompt.images : undefined,
140
+ },
141
+ meta: {
142
+ sendPlan: CLOUD_SEND_PLAN,
143
+ prompt,
144
+ bootstrap: true,
145
+ promptInputTokens,
146
+ useNativeToolReplay: false,
147
+ bridgeEnabled: false,
148
+ nativeReplayId,
149
+ agentMode,
150
+ modelSelection: selection,
151
+ },
152
+ contextWindowAgentId: agent.agentId,
153
+ textDeltas,
154
+ restoreCursorSdkOutputFilter,
155
+ lifecycle: buildCloudCursorProviderTurnLifecycle(agent),
156
+ runtime: { kind: "direct", turnCoordinator },
157
+ };
158
+ }
159
+ finally {
160
+ if (!completed) {
161
+ await cloudAgentForCleanup?.[Symbol.asyncDispose]?.().catch(() => { });
162
+ restoreCursorSdkOutputFilter?.();
163
+ }
164
+ }
165
+ }
166
+ async function prepareCursorLocalProviderTurn(prepareParams) {
167
+ const { params, cwd, resolvedApiKey, sdkEventDebug, throwIfAborted, resolvedConfig, agentMode, selection, fastEnabled } = prepareParams;
168
+ const { model, context, options } = params;
169
+ let restoreCursorSdkOutputFilter;
170
+ let sessionAgentScopeKey;
171
+ let liveRun;
172
+ let completed = false;
173
+ try {
174
+ ensureCursorRipgrepPath();
175
+ const localSafety = {
176
+ autoReview: resolvedConfig.local.autoReview.value,
177
+ sandboxEnabled: resolvedConfig.local.sandboxEnabled.value,
178
+ };
179
+ const sdk = await loadCursorSdk();
180
+ const { Agent } = sdk;
181
+ const useHttp1ForAgent = configureCursorSdkHttp1(sdk, resolvedConfig.local.useHttp1ForAgent);
182
+ installCursorMcpToolTimeoutOverride();
183
+ restoreCursorSdkOutputFilter = installCursorSdkOutputFilter();
184
+ const settingSources = getEffectiveCursorSettingSources();
185
+ const queuedBridgeRequestsBeforeLiveRun = [];
186
+ let liveRunForBridgeQueue;
187
+ const sessionAgentAcquireParams = {
188
+ apiKey: resolvedApiKey,
189
+ agentMode,
190
+ cwd,
191
+ modelSelection: selection,
192
+ settingSources,
193
+ localSafety,
194
+ localResume: resolvedConfig.local.resume.value,
195
+ useHttp1ForAgent,
196
+ debugRecorder: sdkEventDebug,
197
+ onBridgeToolRequest: (request) => {
198
+ if (liveRunForBridgeQueue && !liveRunForBridgeQueue.disposed) {
199
+ cursorLiveRuns.queueEvent(liveRunForBridgeQueue, { type: "bridge-tool", request });
200
+ }
201
+ else {
202
+ queuedBridgeRequestsBeforeLiveRun.push(request);
203
+ }
204
+ },
205
+ createAgent: (createOptions) => suppressCursorSdkOutput(() => Agent.create(createOptions)),
206
+ };
207
+ let sessionAgentLease = await acquireSessionCursorAgent(sessionAgentAcquireParams);
208
+ sessionAgentScopeKey = sessionAgentLease.scopeKey;
209
+ throwIfAborted();
210
+ let bridgeToolNames = new Set(sessionAgentLease.bridgeRun?.snapshot.tools.map((tool) => tool.mcpToolName) ?? []);
211
+ let includePiBridgeGuidance = bridgeToolNames.size > 0;
212
+ const buildPromptOptions = (plan) => {
213
+ const promptOptions = {
214
+ ...getCursorPromptOptions(model),
215
+ agentMode,
216
+ includePiBridgeGuidance,
217
+ includePiAskQuestionGuidance: bridgeToolNames.has("pi__cursor_ask_question"),
218
+ };
219
+ if (plan.mode !== "bootstrap" || !resolveCursorToolManifestEnabled()) {
220
+ return promptOptions;
221
+ }
222
+ return {
223
+ ...promptOptions,
224
+ toolManifest: buildCursorToolManifestText({
225
+ bridgeSnapshot: sessionAgentLease.bridgeRun?.snapshot,
226
+ piBridgeEnabled: resolveCursorPiToolBridgeEnabled(),
227
+ includePiBridgeGuidance,
228
+ }),
229
+ };
230
+ };
231
+ let sendPlan = planCursorSessionSend(sessionAgentLease.sendState, context);
232
+ if (sessionAgentLease.created && sessionAgentLease.resumed && sendPlan.mode === "incremental") {
233
+ sendPlan = { mode: "bootstrap", resetAgent: false, reason: "process_resume" };
234
+ }
235
+ let promptOptions = buildPromptOptions(sendPlan);
236
+ let prompt = buildCursorSessionSendPrompt(context, promptOptions, sendPlan);
237
+ if (sendPlan.resetAgent) {
238
+ await resetSessionCursorAgent(sessionAgentScopeKey);
239
+ sessionAgentLease = await acquireSessionCursorAgent({ ...sessionAgentAcquireParams, forceCreate: true });
240
+ sessionAgentScopeKey = sessionAgentLease.scopeKey;
241
+ bridgeToolNames = new Set(sessionAgentLease.bridgeRun?.snapshot.tools.map((tool) => tool.mcpToolName) ?? []);
242
+ includePiBridgeGuidance = bridgeToolNames.size > 0;
243
+ sendPlan = planCursorSessionSend(sessionAgentLease.sendState, context);
244
+ promptOptions = buildPromptOptions(sendPlan);
245
+ prompt = buildCursorSessionSendPrompt(context, promptOptions, sendPlan);
246
+ }
247
+ const bootstrap = sendPlan.mode === "bootstrap";
248
+ const agent = sessionAgentLease.agent;
249
+ const bridgeRun = sessionAgentLease.bridgeRun;
250
+ const sendPayload = {
251
+ text: prompt.text,
252
+ images: prompt.images.length > 0 ? prompt.images : undefined,
253
+ };
254
+ const sessionBridgeRun = bridgeRun;
255
+ const promptInputTokens = estimateCursorPromptTokens(prompt, promptOptions);
256
+ const useNativeToolReplay = isCursorNativeToolDisplayRuntimeEnabled();
257
+ const activeToolNames = getActiveContextToolNames(context);
258
+ sdkEventDebug?.recordProviderMeta({
259
+ model: {
260
+ id: model.id,
261
+ provider: model.provider,
262
+ api: model.api,
263
+ reasoning: options?.reasoning ?? "off",
264
+ fastEnabled,
265
+ selection,
266
+ },
267
+ settingSources: settingSources ?? null,
268
+ sendState: sessionAgentLease.sendState,
269
+ sendPlan,
270
+ promptOptions,
271
+ toolManifestEnabled: resolveCursorToolManifestEnabled(),
272
+ agentMode,
273
+ localForce: resolvedConfig.local.force.value,
274
+ localResume: resolvedConfig.local.resume.value,
275
+ resumedAgent: sessionAgentLease.resumed,
276
+ activeToolNames: activeToolNames ? [...activeToolNames] : [],
277
+ sessionAgentScopeKey,
278
+ bridgeRunId: bridgeRun?.id,
279
+ });
280
+ const nativeReplayId = createCursorNativeReplayId();
281
+ const textDeltas = [];
282
+ const useLiveRun = useNativeToolReplay || bridgeRun !== undefined;
283
+ liveRun = useLiveRun
284
+ ? cursorLiveRuns.start({
285
+ id: useNativeToolReplay ? nativeReplayId : bridgeRun?.id ?? nativeReplayId,
286
+ agent,
287
+ bridgeRun,
288
+ sessionBridgeRun,
289
+ sessionAgentScopeKey,
290
+ promptInputTokens,
291
+ textDeltas,
292
+ debugRecorder: sdkEventDebug,
293
+ })
294
+ : undefined;
295
+ if (liveRun) {
296
+ liveRunForBridgeQueue = liveRun;
297
+ for (const request of queuedBridgeRequestsBeforeLiveRun.splice(0)) {
298
+ cursorLiveRuns.queueEvent(liveRun, { type: "bridge-tool", request });
299
+ }
300
+ }
301
+ const turnCoordinator = new CursorSdkTurnCoordinator({
302
+ stream: params.stream,
303
+ partial: params.partial,
304
+ cwd,
305
+ resolvedApiKey,
306
+ liveRun,
307
+ useNativeToolReplay,
308
+ activeToolNames,
309
+ nativeReplayId,
310
+ textDeltas,
311
+ debugRecorder: sdkEventDebug,
312
+ });
313
+ completed = true;
314
+ return {
315
+ runtimeTarget: "local",
316
+ agent,
317
+ cwd,
318
+ payload: sendPayload,
319
+ meta: {
320
+ sendPlan,
321
+ prompt,
322
+ bootstrap,
323
+ promptInputTokens,
324
+ useNativeToolReplay,
325
+ bridgeEnabled: bridgeRun !== undefined,
326
+ nativeReplayId,
327
+ agentMode,
328
+ modelSelection: selection,
329
+ ...(sessionAgentLease.resumeNotice ? { resumeNotice: sessionAgentLease.resumeNotice } : {}),
330
+ },
331
+ contextWindowAgentId: agent.agentId,
332
+ textDeltas,
333
+ sessionAgentScopeKey,
334
+ sessionAgentLease,
335
+ localForce: resolvedConfig.local.force,
336
+ restoreCursorSdkOutputFilter,
337
+ lifecycle: buildLocalCursorProviderTurnLifecycle(sessionAgentLease, sessionAgentScopeKey),
338
+ runtime: liveRun
339
+ ? { kind: "live", liveRun, turnCoordinator }
340
+ : { kind: "direct", turnCoordinator },
341
+ };
342
+ }
343
+ finally {
344
+ if (!completed) {
345
+ if (liveRun && !liveRun.disposed) {
346
+ await cursorLiveRuns
347
+ .release(liveRun)
348
+ .catch(() => abandonSessionCursorAgent(sessionAgentScopeKey).catch(() => { }));
349
+ }
350
+ else {
351
+ await abandonSessionCursorAgent(sessionAgentScopeKey).catch(() => { });
352
+ }
353
+ restoreCursorSdkOutputFilter?.();
354
+ }
355
+ }
356
+ }
357
+ /** Resolves the runtime target from the caller-supplied snapshot and dispatches to the owning branch. */
358
+ export async function prepareCursorProviderTurn(prepareParams) {
359
+ const { params, resolvedConfig } = prepareParams;
360
+ const { model, options } = params;
361
+ const agentMode = getCursorProviderAgentModeOrThrow();
362
+ const fastEnabled = resolvedConfig.runtime.value === "cloud" ? undefined : getEffectiveFastForModelId(model.id);
363
+ const selection = buildCursorModelSelection(model.id, options?.reasoning ?? "off", fastEnabled);
364
+ const context = { ...prepareParams, agentMode, selection, fastEnabled };
365
+ return resolvedConfig.runtime.value === "cloud"
366
+ ? prepareCursorCloudProviderTurn(context)
367
+ : prepareCursorLocalProviderTurn(context);
368
+ }
369
+ export function requireCursorApiKey(options) {
370
+ const apiKey = resolveCursorApiKey(options?.apiKey);
371
+ if (!apiKey)
372
+ throw new Error(MISSING_CURSOR_API_KEY_MESSAGE);
373
+ return apiKey;
374
+ }