@kaitranntt/ccs 7.43.0 → 7.44.0-dev.1

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 (271) hide show
  1. package/README.md +49 -2
  2. package/config/base-codex.settings.json +4 -4
  3. package/dist/api/services/profile-reader.d.ts.map +1 -1
  4. package/dist/api/services/profile-reader.js +4 -1
  5. package/dist/api/services/profile-reader.js.map +1 -1
  6. package/dist/auth/profile-detector.d.ts +14 -3
  7. package/dist/auth/profile-detector.d.ts.map +1 -1
  8. package/dist/auth/profile-detector.js +35 -15
  9. package/dist/auth/profile-detector.js.map +1 -1
  10. package/dist/ccs.js +34 -4
  11. package/dist/ccs.js.map +1 -1
  12. package/dist/cliproxy/auth/auth-types.d.ts +28 -1
  13. package/dist/cliproxy/auth/auth-types.d.ts.map +1 -1
  14. package/dist/cliproxy/auth/auth-types.js +70 -4
  15. package/dist/cliproxy/auth/auth-types.js.map +1 -1
  16. package/dist/cliproxy/auth/oauth-handler.d.ts.map +1 -1
  17. package/dist/cliproxy/auth/oauth-handler.js +19 -4
  18. package/dist/cliproxy/auth/oauth-handler.js.map +1 -1
  19. package/dist/cliproxy/composite-validator.d.ts +20 -0
  20. package/dist/cliproxy/composite-validator.d.ts.map +1 -0
  21. package/dist/cliproxy/composite-validator.js +85 -0
  22. package/dist/cliproxy/composite-validator.js.map +1 -0
  23. package/dist/cliproxy/config/env-builder.d.ts +24 -0
  24. package/dist/cliproxy/config/env-builder.d.ts.map +1 -1
  25. package/dist/cliproxy/config/env-builder.js +72 -1
  26. package/dist/cliproxy/config/env-builder.js.map +1 -1
  27. package/dist/cliproxy/config/thinking-config.d.ts +19 -2
  28. package/dist/cliproxy/config/thinking-config.d.ts.map +1 -1
  29. package/dist/cliproxy/config/thinking-config.js +127 -27
  30. package/dist/cliproxy/config/thinking-config.js.map +1 -1
  31. package/dist/cliproxy/executor/env-resolver.d.ts +16 -0
  32. package/dist/cliproxy/executor/env-resolver.d.ts.map +1 -1
  33. package/dist/cliproxy/executor/env-resolver.js +82 -26
  34. package/dist/cliproxy/executor/env-resolver.js.map +1 -1
  35. package/dist/cliproxy/executor/index.d.ts.map +1 -1
  36. package/dist/cliproxy/executor/index.js +202 -67
  37. package/dist/cliproxy/executor/index.js.map +1 -1
  38. package/dist/cliproxy/executor/retry-handler.d.ts +11 -0
  39. package/dist/cliproxy/executor/retry-handler.d.ts.map +1 -1
  40. package/dist/cliproxy/executor/retry-handler.js +30 -1
  41. package/dist/cliproxy/executor/retry-handler.js.map +1 -1
  42. package/dist/cliproxy/executor/thinking-arg-parser.d.ts +27 -0
  43. package/dist/cliproxy/executor/thinking-arg-parser.d.ts.map +1 -0
  44. package/dist/cliproxy/executor/thinking-arg-parser.js +80 -0
  45. package/dist/cliproxy/executor/thinking-arg-parser.js.map +1 -0
  46. package/dist/cliproxy/model-catalog.d.ts.map +1 -1
  47. package/dist/cliproxy/model-catalog.js +14 -3
  48. package/dist/cliproxy/model-catalog.js.map +1 -1
  49. package/dist/cliproxy/model-config.d.ts.map +1 -1
  50. package/dist/cliproxy/model-config.js +27 -7
  51. package/dist/cliproxy/model-config.js.map +1 -1
  52. package/dist/cliproxy/provider-capabilities.d.ts +22 -0
  53. package/dist/cliproxy/provider-capabilities.d.ts.map +1 -0
  54. package/dist/cliproxy/provider-capabilities.js +95 -0
  55. package/dist/cliproxy/provider-capabilities.js.map +1 -0
  56. package/dist/cliproxy/quota-fetcher-codex.d.ts.map +1 -1
  57. package/dist/cliproxy/quota-fetcher-codex.js +106 -87
  58. package/dist/cliproxy/quota-fetcher-codex.js.map +1 -1
  59. package/dist/cliproxy/remote-auth-fetcher.d.ts.map +1 -1
  60. package/dist/cliproxy/remote-auth-fetcher.js +3 -26
  61. package/dist/cliproxy/remote-auth-fetcher.js.map +1 -1
  62. package/dist/cliproxy/service-manager.d.ts.map +1 -1
  63. package/dist/cliproxy/service-manager.js +3 -6
  64. package/dist/cliproxy/service-manager.js.map +1 -1
  65. package/dist/cliproxy/services/index.d.ts +2 -2
  66. package/dist/cliproxy/services/index.d.ts.map +1 -1
  67. package/dist/cliproxy/services/index.js +4 -1
  68. package/dist/cliproxy/services/index.js.map +1 -1
  69. package/dist/cliproxy/services/proxy-lifecycle-service.d.ts +15 -3
  70. package/dist/cliproxy/services/proxy-lifecycle-service.d.ts.map +1 -1
  71. package/dist/cliproxy/services/proxy-lifecycle-service.js +15 -6
  72. package/dist/cliproxy/services/proxy-lifecycle-service.js.map +1 -1
  73. package/dist/cliproxy/services/variant-config-adapter.d.ts +15 -0
  74. package/dist/cliproxy/services/variant-config-adapter.d.ts.map +1 -1
  75. package/dist/cliproxy/services/variant-config-adapter.js +84 -11
  76. package/dist/cliproxy/services/variant-config-adapter.js.map +1 -1
  77. package/dist/cliproxy/services/variant-service.d.ts +26 -0
  78. package/dist/cliproxy/services/variant-service.d.ts.map +1 -1
  79. package/dist/cliproxy/services/variant-service.js +164 -9
  80. package/dist/cliproxy/services/variant-service.js.map +1 -1
  81. package/dist/cliproxy/services/variant-settings.d.ts +19 -1
  82. package/dist/cliproxy/services/variant-settings.d.ts.map +1 -1
  83. package/dist/cliproxy/services/variant-settings.js +150 -12
  84. package/dist/cliproxy/services/variant-settings.js.map +1 -1
  85. package/dist/cliproxy/types.d.ts +13 -0
  86. package/dist/cliproxy/types.d.ts.map +1 -1
  87. package/dist/cliproxy/types.js.map +1 -1
  88. package/dist/commands/cliproxy/auth-subcommand.d.ts.map +1 -1
  89. package/dist/commands/cliproxy/auth-subcommand.js +2 -1
  90. package/dist/commands/cliproxy/auth-subcommand.js.map +1 -1
  91. package/dist/commands/cliproxy/help-subcommand.d.ts.map +1 -1
  92. package/dist/commands/cliproxy/help-subcommand.js +4 -0
  93. package/dist/commands/cliproxy/help-subcommand.js.map +1 -1
  94. package/dist/commands/cliproxy/index.d.ts.map +1 -1
  95. package/dist/commands/cliproxy/index.js +12 -0
  96. package/dist/commands/cliproxy/index.js.map +1 -1
  97. package/dist/commands/cliproxy/proxy-lifecycle-subcommand.d.ts +9 -0
  98. package/dist/commands/cliproxy/proxy-lifecycle-subcommand.d.ts.map +1 -1
  99. package/dist/commands/cliproxy/proxy-lifecycle-subcommand.js +92 -6
  100. package/dist/commands/cliproxy/proxy-lifecycle-subcommand.js.map +1 -1
  101. package/dist/commands/cliproxy/quota-subcommand.d.ts.map +1 -1
  102. package/dist/commands/cliproxy/quota-subcommand.js +106 -4
  103. package/dist/commands/cliproxy/quota-subcommand.js.map +1 -1
  104. package/dist/commands/cliproxy/variant-subcommand.d.ts +1 -0
  105. package/dist/commands/cliproxy/variant-subcommand.d.ts.map +1 -1
  106. package/dist/commands/cliproxy/variant-subcommand.js +307 -3
  107. package/dist/commands/cliproxy/variant-subcommand.js.map +1 -1
  108. package/dist/commands/command-execution-contract.d.ts +23 -0
  109. package/dist/commands/command-execution-contract.d.ts.map +1 -0
  110. package/dist/commands/command-execution-contract.js +21 -0
  111. package/dist/commands/command-execution-contract.js.map +1 -0
  112. package/dist/commands/cursor-command-display.d.ts +6 -0
  113. package/dist/commands/cursor-command-display.d.ts.map +1 -0
  114. package/dist/commands/cursor-command-display.js +100 -0
  115. package/dist/commands/cursor-command-display.js.map +1 -0
  116. package/dist/commands/cursor-command.d.ts +12 -0
  117. package/dist/commands/cursor-command.d.ts.map +1 -0
  118. package/dist/commands/cursor-command.js +222 -0
  119. package/dist/commands/cursor-command.js.map +1 -0
  120. package/dist/commands/help-command.d.ts.map +1 -1
  121. package/dist/commands/help-command.js +30 -3
  122. package/dist/commands/help-command.js.map +1 -1
  123. package/dist/commands/shell-completion-command.d.ts +20 -0
  124. package/dist/commands/shell-completion-command.d.ts.map +1 -1
  125. package/dist/commands/shell-completion-command.js +45 -30
  126. package/dist/commands/shell-completion-command.js.map +1 -1
  127. package/dist/config/reserved-names.d.ts +1 -1
  128. package/dist/config/reserved-names.d.ts.map +1 -1
  129. package/dist/config/reserved-names.js +2 -0
  130. package/dist/config/reserved-names.js.map +1 -1
  131. package/dist/config/unified-config-loader.d.ts +6 -1
  132. package/dist/config/unified-config-loader.d.ts.map +1 -1
  133. package/dist/config/unified-config-loader.js +63 -3
  134. package/dist/config/unified-config-loader.js.map +1 -1
  135. package/dist/config/unified-config-types.d.ts +79 -2
  136. package/dist/config/unified-config-types.d.ts.map +1 -1
  137. package/dist/config/unified-config-types.js +28 -2
  138. package/dist/config/unified-config-types.js.map +1 -1
  139. package/dist/cursor/cursor-auth.d.ts +58 -0
  140. package/dist/cursor/cursor-auth.d.ts.map +1 -0
  141. package/dist/cursor/cursor-auth.js +295 -0
  142. package/dist/cursor/cursor-auth.js.map +1 -0
  143. package/dist/cursor/cursor-daemon-entry.d.ts +14 -0
  144. package/dist/cursor/cursor-daemon-entry.d.ts.map +1 -0
  145. package/dist/cursor/cursor-daemon-entry.js +236 -0
  146. package/dist/cursor/cursor-daemon-entry.js.map +1 -0
  147. package/dist/cursor/cursor-daemon-pid.d.ts +4 -0
  148. package/dist/cursor/cursor-daemon-pid.d.ts.map +1 -0
  149. package/dist/cursor/cursor-daemon-pid.js +77 -0
  150. package/dist/cursor/cursor-daemon-pid.js.map +1 -0
  151. package/dist/cursor/cursor-daemon.d.ts +36 -0
  152. package/dist/cursor/cursor-daemon.d.ts.map +1 -0
  153. package/dist/cursor/cursor-daemon.js +315 -0
  154. package/dist/cursor/cursor-daemon.js.map +1 -0
  155. package/dist/cursor/cursor-executor.d.ts +81 -0
  156. package/dist/cursor/cursor-executor.d.ts.map +1 -0
  157. package/dist/cursor/cursor-executor.js +821 -0
  158. package/dist/cursor/cursor-executor.js.map +1 -0
  159. package/dist/cursor/cursor-models.d.ts +43 -0
  160. package/dist/cursor/cursor-models.d.ts.map +1 -0
  161. package/dist/cursor/cursor-models.js +288 -0
  162. package/dist/cursor/cursor-models.js.map +1 -0
  163. package/dist/cursor/cursor-protobuf-decoder.d.ts +52 -0
  164. package/dist/cursor/cursor-protobuf-decoder.d.ts.map +1 -0
  165. package/dist/cursor/cursor-protobuf-decoder.js +311 -0
  166. package/dist/cursor/cursor-protobuf-decoder.js.map +1 -0
  167. package/dist/cursor/cursor-protobuf-encoder.d.ts +54 -0
  168. package/dist/cursor/cursor-protobuf-encoder.d.ts.map +1 -0
  169. package/dist/cursor/cursor-protobuf-encoder.js +173 -0
  170. package/dist/cursor/cursor-protobuf-encoder.js.map +1 -0
  171. package/dist/cursor/cursor-protobuf-schema.d.ts +215 -0
  172. package/dist/cursor/cursor-protobuf-schema.d.ts.map +1 -0
  173. package/dist/cursor/cursor-protobuf-schema.js +120 -0
  174. package/dist/cursor/cursor-protobuf-schema.js.map +1 -0
  175. package/dist/cursor/cursor-protobuf.d.ts +21 -0
  176. package/dist/cursor/cursor-protobuf.d.ts.map +1 -0
  177. package/dist/cursor/cursor-protobuf.js +116 -0
  178. package/dist/cursor/cursor-protobuf.js.map +1 -0
  179. package/dist/cursor/cursor-stream-parser.d.ts +52 -0
  180. package/dist/cursor/cursor-stream-parser.d.ts.map +1 -0
  181. package/dist/cursor/cursor-stream-parser.js +142 -0
  182. package/dist/cursor/cursor-stream-parser.js.map +1 -0
  183. package/dist/cursor/cursor-translator.d.ts +39 -0
  184. package/dist/cursor/cursor-translator.d.ts.map +1 -0
  185. package/dist/cursor/cursor-translator.js +118 -0
  186. package/dist/cursor/cursor-translator.js.map +1 -0
  187. package/dist/cursor/daemon-process-ownership.d.ts +3 -0
  188. package/dist/cursor/daemon-process-ownership.d.ts.map +1 -0
  189. package/dist/cursor/daemon-process-ownership.js +96 -0
  190. package/dist/cursor/daemon-process-ownership.js.map +1 -0
  191. package/dist/cursor/index.d.ts +11 -0
  192. package/dist/cursor/index.d.ts.map +1 -0
  193. package/dist/cursor/index.js +55 -0
  194. package/dist/cursor/index.js.map +1 -0
  195. package/dist/cursor/types.d.ts +80 -0
  196. package/dist/cursor/types.d.ts.map +1 -0
  197. package/dist/cursor/types.js +8 -0
  198. package/dist/cursor/types.js.map +1 -0
  199. package/dist/management/oauth-port-diagnostics.d.ts +4 -7
  200. package/dist/management/oauth-port-diagnostics.d.ts.map +1 -1
  201. package/dist/management/oauth-port-diagnostics.js +12 -23
  202. package/dist/management/oauth-port-diagnostics.js.map +1 -1
  203. package/dist/types/index.d.ts +1 -1
  204. package/dist/types/index.d.ts.map +1 -1
  205. package/dist/types/index.js.map +1 -1
  206. package/dist/ui/assets/{accounts-CkN_roEn.js → accounts-Cr5UiSqw.js} +1 -1
  207. package/dist/ui/assets/{alert-dialog-Dy-8Z_Ud.js → alert-dialog-RKd6P34V.js} +1 -1
  208. package/dist/ui/assets/api-BjsYBaDO.js +1 -0
  209. package/dist/ui/assets/auth-section-DJjkM3Pc.js +1 -0
  210. package/dist/ui/assets/{backups-section-CDuqhiZo.js → backups-section-C3OoH74L.js} +1 -1
  211. package/dist/ui/assets/cliproxy-bUQ9JQSI.js +3 -0
  212. package/dist/ui/assets/{cliproxy-control-panel-DJd_zNR3.js → cliproxy-control-panel-bWG4j7j-.js} +1 -1
  213. package/dist/ui/assets/confirm-dialog-39RkxEsp.js +1 -0
  214. package/dist/ui/assets/copilot-CT5QKd7M.js +3 -0
  215. package/dist/ui/assets/cursor-CgHXk53L.js +1 -0
  216. package/dist/ui/assets/{globalenv-section-Cn5ufgRh.js → globalenv-section-JUD29aAr.js} +1 -1
  217. package/dist/ui/assets/{health-BsMhSeFz.js → health-P6WZCBRj.js} +1 -1
  218. package/dist/ui/assets/{icons-D5eAI-GR.js → icons-DGASzt3M.js} +1 -1
  219. package/dist/ui/assets/{index-CEF_VhSR.js → index-B-T25xBs.js} +1 -1
  220. package/dist/ui/assets/index-BZe6NG3v.js +1 -0
  221. package/dist/ui/assets/{index-B2GQ_Joi.js → index-Bikvb5yX.js} +1 -1
  222. package/dist/ui/assets/index-BteqkOAf.js +47 -0
  223. package/dist/ui/assets/index-ByiEOnlQ.css +1 -0
  224. package/dist/ui/assets/index-CIB-ESXC.js +1 -0
  225. package/dist/ui/assets/{proxy-status-widget-Cb7KfEqq.js → proxy-status-widget-BgJE3cHN.js} +1 -1
  226. package/dist/ui/assets/separator-yty7hz16.js +1 -0
  227. package/dist/ui/assets/{shared-BsWeldW8.js → shared-BxLyXLjd.js} +1 -1
  228. package/dist/ui/assets/sidebar/cursor.svg +1 -0
  229. package/dist/ui/assets/{switch-D6XSRTo_.js → switch-Dq8eo1UY.js} +1 -1
  230. package/dist/ui/index.html +3 -3
  231. package/dist/utils/config-manager.d.ts.map +1 -1
  232. package/dist/utils/config-manager.js +17 -6
  233. package/dist/utils/config-manager.js.map +1 -1
  234. package/dist/web-server/jsonl-parser.js +1 -1
  235. package/dist/web-server/jsonl-parser.js.map +1 -1
  236. package/dist/web-server/routes/account-routes.d.ts.map +1 -1
  237. package/dist/web-server/routes/account-routes.js +5 -11
  238. package/dist/web-server/routes/account-routes.js.map +1 -1
  239. package/dist/web-server/routes/cliproxy-auth-routes.d.ts +5 -0
  240. package/dist/web-server/routes/cliproxy-auth-routes.d.ts.map +1 -1
  241. package/dist/web-server/routes/cliproxy-auth-routes.js +73 -6
  242. package/dist/web-server/routes/cliproxy-auth-routes.js.map +1 -1
  243. package/dist/web-server/routes/cliproxy-stats-routes.d.ts.map +1 -1
  244. package/dist/web-server/routes/cliproxy-stats-routes.js +43 -4
  245. package/dist/web-server/routes/cliproxy-stats-routes.js.map +1 -1
  246. package/dist/web-server/routes/cursor-routes.d.ts +16 -0
  247. package/dist/web-server/routes/cursor-routes.d.ts.map +1 -0
  248. package/dist/web-server/routes/cursor-routes.js +171 -0
  249. package/dist/web-server/routes/cursor-routes.js.map +1 -0
  250. package/dist/web-server/routes/cursor-settings-routes.d.ts +6 -0
  251. package/dist/web-server/routes/cursor-settings-routes.d.ts.map +1 -0
  252. package/dist/web-server/routes/cursor-settings-routes.js +305 -0
  253. package/dist/web-server/routes/cursor-settings-routes.js.map +1 -0
  254. package/dist/web-server/routes/index.d.ts.map +1 -1
  255. package/dist/web-server/routes/index.js +3 -0
  256. package/dist/web-server/routes/index.js.map +1 -1
  257. package/dist/web-server/routes/variant-routes.d.ts.map +1 -1
  258. package/dist/web-server/routes/variant-routes.js +107 -6
  259. package/dist/web-server/routes/variant-routes.js.map +1 -1
  260. package/package.json +5 -2
  261. package/scripts/hardening-inventory.js +526 -0
  262. package/scripts/maintainability-baseline.js +309 -0
  263. package/dist/ui/assets/api-2TN7yVwm.js +0 -1
  264. package/dist/ui/assets/auth-section-CeKCNzzC.js +0 -1
  265. package/dist/ui/assets/cliproxy-626zUpA_.js +0 -3
  266. package/dist/ui/assets/confirm-dialog-DtYrWaa7.js +0 -1
  267. package/dist/ui/assets/copilot-DHdywZ9L.js +0 -4
  268. package/dist/ui/assets/index-Bmgylhgn.js +0 -1
  269. package/dist/ui/assets/index-Cr6iEc8x.js +0 -47
  270. package/dist/ui/assets/index-DkMR3J96.js +0 -1
  271. package/dist/ui/assets/index-QvMpU4Lc.css +0 -1
@@ -0,0 +1,821 @@
1
+ "use strict";
2
+ /**
3
+ * Cursor Executor
4
+ * Handles HTTP/2 requests to Cursor API with protobuf encoding/decoding
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || function (mod) {
23
+ if (mod && mod.__esModule) return mod;
24
+ var result = {};
25
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
26
+ __setModuleDefault(result, mod);
27
+ return result;
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.CursorExecutor = void 0;
31
+ const crypto = __importStar(require("crypto"));
32
+ const cursor_protobuf_js_1 = require("./cursor-protobuf.js");
33
+ const cursor_translator_js_1 = require("./cursor-translator.js");
34
+ const cursor_stream_parser_js_1 = require("./cursor-stream-parser.js");
35
+ /** Lazy import http2 */
36
+ let http2Module = null;
37
+ async function getHttp2() {
38
+ if (http2Module)
39
+ return http2Module;
40
+ try {
41
+ http2Module = await Promise.resolve().then(() => __importStar(require('http2')));
42
+ return http2Module;
43
+ }
44
+ catch (err) {
45
+ if (process.env.CCS_DEBUG) {
46
+ console.error('[cursor] http2 module not available, falling back to fetch:', err);
47
+ }
48
+ return null;
49
+ }
50
+ }
51
+ /**
52
+ * Create error response from JSON error
53
+ */
54
+ function createErrorResponse(jsonError) {
55
+ const errorMsg = jsonError?.error?.details?.[0]?.debug?.details?.title ||
56
+ jsonError?.error?.details?.[0]?.debug?.details?.detail ||
57
+ jsonError?.error?.message ||
58
+ 'API Error';
59
+ const isRateLimit = jsonError?.error?.code === 'resource_exhausted';
60
+ return new Response(JSON.stringify({
61
+ error: {
62
+ message: errorMsg,
63
+ type: isRateLimit ? 'rate_limit_error' : 'api_error',
64
+ code: jsonError?.error?.details?.[0]?.debug?.error || 'unknown',
65
+ },
66
+ }), {
67
+ status: isRateLimit ? 429 : 400,
68
+ headers: { 'Content-Type': 'application/json' },
69
+ });
70
+ }
71
+ class CursorExecutor {
72
+ constructor() {
73
+ this.baseUrl = 'https://api2.cursor.sh';
74
+ this.chatPath = '/aiserver.v1.AiService/StreamChat';
75
+ this.CURSOR_CLIENT_VERSION = '2.3.41';
76
+ this.CURSOR_USER_AGENT = 'connect-es/1.6.1';
77
+ }
78
+ buildUrl() {
79
+ return `${this.baseUrl}${this.chatPath}`;
80
+ }
81
+ /**
82
+ * Generate checksum using Jyh cipher (time-based XOR with rolling key seed=165)
83
+ */
84
+ generateChecksum(machineId) {
85
+ const timestamp = Math.floor(Date.now() / 1000000);
86
+ // JS bitwise shifts wrap modulo 32, so >>40 and >>32 give wrong results.
87
+ // Use Math.trunc division for upper bytes that exceed 32-bit range.
88
+ const byteArray = new Uint8Array([
89
+ Math.trunc(timestamp / 2 ** 40) & 0xff,
90
+ Math.trunc(timestamp / 2 ** 32) & 0xff,
91
+ (timestamp >>> 24) & 0xff,
92
+ (timestamp >>> 16) & 0xff,
93
+ (timestamp >>> 8) & 0xff,
94
+ timestamp & 0xff,
95
+ ]);
96
+ let t = 165;
97
+ for (let i = 0; i < byteArray.length; i++) {
98
+ byteArray[i] = ((byteArray[i] ^ t) + (i % 256)) & 0xff;
99
+ t = byteArray[i];
100
+ }
101
+ const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
102
+ let encoded = '';
103
+ for (let i = 0; i < byteArray.length; i += 3) {
104
+ const a = byteArray[i];
105
+ const b = i + 1 < byteArray.length ? byteArray[i + 1] : 0;
106
+ const c = i + 2 < byteArray.length ? byteArray[i + 2] : 0;
107
+ encoded += alphabet[a >> 2];
108
+ encoded += alphabet[((a & 3) << 4) | (b >> 4)];
109
+ if (i + 1 < byteArray.length) {
110
+ encoded += alphabet[((b & 15) << 2) | (c >> 6)];
111
+ }
112
+ if (i + 2 < byteArray.length) {
113
+ encoded += alphabet[c & 63];
114
+ }
115
+ }
116
+ return `${encoded}${machineId}`;
117
+ }
118
+ buildHeaders(credentials) {
119
+ const accessToken = credentials.accessToken;
120
+ const machineId = credentials.machineId;
121
+ const ghostMode = credentials.ghostMode !== false;
122
+ if (!machineId) {
123
+ throw new Error('Machine ID is required for Cursor API');
124
+ }
125
+ const delimIdx = accessToken.indexOf('::');
126
+ const cleanToken = delimIdx !== -1 ? accessToken.slice(delimIdx + 2) : accessToken;
127
+ if (!cleanToken) {
128
+ throw new Error('Access token is empty after parsing');
129
+ }
130
+ return {
131
+ authorization: `Bearer ${cleanToken}`,
132
+ 'connect-accept-encoding': 'gzip',
133
+ 'connect-protocol-version': '1',
134
+ 'content-type': 'application/connect+proto',
135
+ 'user-agent': this.CURSOR_USER_AGENT,
136
+ 'x-amzn-trace-id': `Root=${crypto.randomUUID()}`,
137
+ 'x-client-key': crypto.createHash('sha256').update(cleanToken).digest('hex'),
138
+ 'x-cursor-checksum': this.generateChecksum(machineId),
139
+ 'x-cursor-client-version': this.CURSOR_CLIENT_VERSION,
140
+ 'x-cursor-client-type': 'ide',
141
+ 'x-cursor-client-os': process.platform === 'win32'
142
+ ? 'windows'
143
+ : process.platform === 'darwin'
144
+ ? 'macos'
145
+ : 'linux',
146
+ 'x-cursor-client-arch': process.arch === 'arm64' ? 'aarch64' : 'x64',
147
+ 'x-cursor-client-device-type': 'desktop',
148
+ 'x-cursor-config-version': crypto.randomUUID(),
149
+ 'x-cursor-timezone': Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC',
150
+ 'x-ghost-mode': ghostMode ? 'true' : 'false',
151
+ 'x-request-id': crypto.randomUUID(),
152
+ 'x-session-id': crypto.createHash('sha256').update(cleanToken).digest('hex').substring(0, 36),
153
+ };
154
+ }
155
+ transformRequest(model, body, stream, credentials) {
156
+ const translatedBody = (0, cursor_translator_js_1.buildCursorRequest)(model, body, stream, credentials);
157
+ const messages = translatedBody.messages || [];
158
+ const tools = (translatedBody.tools || body.tools || []);
159
+ const reasoningEffort = body.reasoning_effort || null;
160
+ return (0, cursor_protobuf_js_1.generateCursorBody)(messages, model, tools, reasoningEffort);
161
+ }
162
+ async makeFetchRequest(url, headers, body, signal) {
163
+ const response = await fetch(url, {
164
+ method: 'POST',
165
+ headers,
166
+ body,
167
+ signal,
168
+ });
169
+ const responseHeaders = {};
170
+ response.headers.forEach((value, key) => {
171
+ responseHeaders[key] = value;
172
+ });
173
+ return {
174
+ status: response.status,
175
+ headers: responseHeaders,
176
+ body: Buffer.from(await response.arrayBuffer()),
177
+ };
178
+ }
179
+ async makeHttp2Request(url, headers, body, signal) {
180
+ const http2 = await getHttp2();
181
+ if (!http2) {
182
+ throw new Error('http2 module not available');
183
+ }
184
+ return new Promise((resolve, reject) => {
185
+ const urlObj = new URL(url);
186
+ const client = http2.connect(`https://${urlObj.host}`);
187
+ const chunks = [];
188
+ let responseHeaders = {};
189
+ client.on('error', (err) => {
190
+ client.close();
191
+ reject(err);
192
+ });
193
+ const req = client.request({
194
+ ':method': 'POST',
195
+ ':path': urlObj.pathname,
196
+ ':authority': urlObj.host,
197
+ ':scheme': 'https',
198
+ ...headers,
199
+ });
200
+ req.on('response', (hdrs) => {
201
+ responseHeaders = hdrs;
202
+ });
203
+ req.on('data', (chunk) => {
204
+ chunks.push(chunk);
205
+ });
206
+ req.on('end', () => {
207
+ client.close();
208
+ resolve({
209
+ status: Number(responseHeaders[':status']) || 500,
210
+ headers: responseHeaders,
211
+ body: Buffer.concat(chunks),
212
+ });
213
+ });
214
+ req.on('error', (err) => {
215
+ client.close();
216
+ reject(err);
217
+ });
218
+ if (signal) {
219
+ const onAbort = () => {
220
+ req.close();
221
+ client.close();
222
+ reject(new Error('Request aborted'));
223
+ };
224
+ signal.addEventListener('abort', onAbort, { once: true });
225
+ const cleanup = () => {
226
+ signal.removeEventListener('abort', onAbort);
227
+ };
228
+ req.on('end', cleanup);
229
+ req.on('error', cleanup);
230
+ }
231
+ req.write(body);
232
+ req.end();
233
+ });
234
+ }
235
+ async execute(params) {
236
+ const { model, body, stream, credentials, signal } = params;
237
+ const url = this.buildUrl();
238
+ const headers = this.buildHeaders(credentials);
239
+ const transformedBody = this.transformRequest(model, body, stream, credentials);
240
+ try {
241
+ // Streaming requests use incremental HTTP/2 → SSE pipeline
242
+ if (stream) {
243
+ const response = await this.executeStreaming(url, headers, transformedBody, model, body, signal);
244
+ return { response, url, headers, transformedBody: body };
245
+ }
246
+ // Non-streaming: buffer entire response then transform to JSON
247
+ const http2 = await getHttp2();
248
+ const response = http2
249
+ ? await this.makeHttp2Request(url, headers, transformedBody, signal)
250
+ : await this.makeFetchRequest(url, headers, transformedBody, signal);
251
+ if (response.status !== 200) {
252
+ const errorText = response.body?.toString() || 'Unknown error';
253
+ const errorResponse = new Response(JSON.stringify({
254
+ error: {
255
+ message: `[${response.status}]: ${errorText}`,
256
+ type: 'invalid_request_error',
257
+ code: '',
258
+ },
259
+ }), {
260
+ status: response.status,
261
+ headers: { 'Content-Type': 'application/json' },
262
+ });
263
+ return { response: errorResponse, url, headers, transformedBody: body };
264
+ }
265
+ const transformedResponse = this.transformProtobufToJSON(response.body, model, body);
266
+ return { response: transformedResponse, url, headers, transformedBody: body };
267
+ }
268
+ catch (error) {
269
+ const errorResponse = new Response(JSON.stringify({
270
+ error: {
271
+ message: error.message,
272
+ type: 'connection_error',
273
+ code: '',
274
+ },
275
+ }), {
276
+ status: 500,
277
+ headers: { 'Content-Type': 'application/json' },
278
+ });
279
+ return { response: errorResponse, url, headers, transformedBody: body };
280
+ }
281
+ }
282
+ /**
283
+ * Execute a streaming request, piping HTTP/2 data events through
284
+ * StreamingFrameParser for incremental SSE output.
285
+ * Falls back to buffered transformProtobufToSSE when http2 is unavailable.
286
+ */
287
+ async executeStreaming(url, headers, body, model, requestBody, signal) {
288
+ const http2 = await getHttp2();
289
+ if (!http2) {
290
+ const response = await this.makeFetchRequest(url, headers, body, signal);
291
+ if (response.status !== 200) {
292
+ const errorText = response.body?.toString() || 'Unknown error';
293
+ return new Response(JSON.stringify({
294
+ error: {
295
+ message: `[${response.status}]: ${errorText}`,
296
+ type: response.status === 429 ? 'rate_limit_error' : 'invalid_request_error',
297
+ code: '',
298
+ },
299
+ }), { status: response.status, headers: { 'Content-Type': 'application/json' } });
300
+ }
301
+ return this.transformProtobufToSSE(response.body, model, requestBody);
302
+ }
303
+ const responseId = `chatcmpl-cursor-${Date.now()}`;
304
+ const created = Math.floor(Date.now() / 1000);
305
+ return new Promise((resolve, reject) => {
306
+ const urlObj = new URL(url);
307
+ const client = http2.connect(`https://${urlObj.host}`);
308
+ client.on('error', (err) => {
309
+ client.close();
310
+ reject(err);
311
+ });
312
+ const req = client.request({
313
+ ':method': 'POST',
314
+ ':path': urlObj.pathname,
315
+ ':authority': urlObj.host,
316
+ ':scheme': 'https',
317
+ ...headers,
318
+ });
319
+ // Register abort before response headers arrive so cancellation works at all stages
320
+ let streamClosed = false;
321
+ let streamController = null;
322
+ if (signal) {
323
+ const onAbort = () => {
324
+ streamClosed = true;
325
+ // Close the ReadableStream controller so consumers don't hang on reader.read()
326
+ if (streamController) {
327
+ try {
328
+ streamController.close();
329
+ }
330
+ catch {
331
+ /* already closed */
332
+ }
333
+ }
334
+ req.close();
335
+ client.close();
336
+ };
337
+ signal.addEventListener('abort', onAbort, { once: true });
338
+ const cleanup = () => signal.removeEventListener('abort', onAbort);
339
+ req.on('end', cleanup);
340
+ req.on('error', cleanup);
341
+ }
342
+ req.on('response', (hdrs) => {
343
+ const status = Number(hdrs[':status']) || 500;
344
+ if (status !== 200) {
345
+ const errorChunks = [];
346
+ req.on('data', (c) => errorChunks.push(c));
347
+ req.on('end', () => {
348
+ client.close();
349
+ const errorText = Buffer.concat(errorChunks).toString();
350
+ resolve(new Response(JSON.stringify({
351
+ error: {
352
+ message: `[${status}]: ${errorText}`,
353
+ type: 'invalid_request_error',
354
+ code: '',
355
+ },
356
+ }), { status, headers: { 'Content-Type': 'application/json' } }));
357
+ });
358
+ return;
359
+ }
360
+ // Status 200: set up incremental streaming pipeline
361
+ const parser = new cursor_stream_parser_js_1.StreamingFrameParser();
362
+ const enc = new TextEncoder();
363
+ const toolCallsMap = new Map();
364
+ let chunkCount = 0;
365
+ let toolCallCount = 0;
366
+ const readable = new ReadableStream({
367
+ start(controller) {
368
+ streamController = controller;
369
+ const emitSSE = (data) => {
370
+ if (streamClosed)
371
+ return;
372
+ controller.enqueue(enc.encode(`data: ${data}\n\n`));
373
+ };
374
+ const closeStream = () => {
375
+ if (streamClosed)
376
+ return;
377
+ streamClosed = true;
378
+ try {
379
+ controller.close();
380
+ }
381
+ catch {
382
+ /* already closed */
383
+ }
384
+ client.close();
385
+ };
386
+ const buildChunk = (delta, finishReason) => JSON.stringify({
387
+ id: responseId,
388
+ object: 'chat.completion.chunk',
389
+ created,
390
+ model,
391
+ choices: [{ index: 0, delta, finish_reason: finishReason }],
392
+ });
393
+ req.on('data', (chunk) => {
394
+ if (streamClosed)
395
+ return;
396
+ for (const frame of parser.push(chunk)) {
397
+ if (frame.type === 'error') {
398
+ emitSSE(JSON.stringify({
399
+ error: { message: frame.message, type: frame.errorType, code: '' },
400
+ }));
401
+ emitSSE('[DONE]');
402
+ closeStream();
403
+ return;
404
+ }
405
+ if (frame.type === 'toolCall') {
406
+ const tc = frame.toolCall;
407
+ // Emit role chunk on first content
408
+ if (chunkCount === 0) {
409
+ emitSSE(buildChunk({ role: 'assistant', content: '' }, null));
410
+ chunkCount++;
411
+ }
412
+ if (toolCallsMap.has(tc.id)) {
413
+ const existing = toolCallsMap.get(tc.id);
414
+ if (!existing)
415
+ continue;
416
+ existing.function.arguments += tc.function.arguments;
417
+ existing.isLast = tc.isLast;
418
+ if (tc.function.arguments) {
419
+ emitSSE(buildChunk({
420
+ tool_calls: [
421
+ {
422
+ index: existing.index,
423
+ id: tc.id,
424
+ type: 'function',
425
+ function: {
426
+ name: tc.function.name,
427
+ arguments: tc.function.arguments,
428
+ },
429
+ },
430
+ ],
431
+ }, null));
432
+ chunkCount++;
433
+ }
434
+ }
435
+ else {
436
+ const idx = toolCallCount++;
437
+ toolCallsMap.set(tc.id, { ...tc, index: idx });
438
+ emitSSE(buildChunk({
439
+ tool_calls: [
440
+ {
441
+ index: idx,
442
+ id: tc.id,
443
+ type: 'function',
444
+ function: {
445
+ name: tc.function.name,
446
+ arguments: tc.function.arguments,
447
+ },
448
+ },
449
+ ],
450
+ }, null));
451
+ chunkCount++;
452
+ }
453
+ }
454
+ if (frame.type === 'text') {
455
+ const delta = chunkCount === 0 && toolCallCount === 0
456
+ ? { role: 'assistant', content: frame.text }
457
+ : { content: frame.text };
458
+ emitSSE(buildChunk(delta, null));
459
+ chunkCount++;
460
+ }
461
+ }
462
+ });
463
+ req.on('end', () => {
464
+ if (streamClosed)
465
+ return;
466
+ if (chunkCount === 0 && toolCallCount === 0) {
467
+ emitSSE(buildChunk({ role: 'assistant', content: '' }, null));
468
+ }
469
+ emitSSE(JSON.stringify({
470
+ id: responseId,
471
+ object: 'chat.completion.chunk',
472
+ created,
473
+ model,
474
+ choices: [
475
+ {
476
+ index: 0,
477
+ delta: {},
478
+ finish_reason: toolCallCount > 0 ? 'tool_calls' : 'stop',
479
+ },
480
+ ],
481
+ usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },
482
+ }));
483
+ emitSSE('[DONE]');
484
+ closeStream();
485
+ });
486
+ req.on('error', (err) => {
487
+ if (!streamClosed) {
488
+ try {
489
+ controller.error(err);
490
+ }
491
+ catch {
492
+ /* already closed */
493
+ }
494
+ }
495
+ client.close();
496
+ });
497
+ },
498
+ });
499
+ resolve(new Response(readable, {
500
+ status: 200,
501
+ headers: {
502
+ 'Content-Type': 'text/event-stream',
503
+ 'Cache-Control': 'no-cache',
504
+ Connection: 'keep-alive',
505
+ },
506
+ }));
507
+ });
508
+ req.on('error', (err) => {
509
+ client.close();
510
+ reject(err);
511
+ });
512
+ req.write(body);
513
+ req.end();
514
+ });
515
+ }
516
+ /**
517
+ * Parse protobuf buffer into frames and extract text/toolcalls.
518
+ * Shared logic between JSON and SSE transformers.
519
+ */
520
+ *parseProtobufFrames(buffer) {
521
+ let offset = 0;
522
+ while (offset < buffer.length) {
523
+ if (offset + 5 > buffer.length)
524
+ break;
525
+ const flags = buffer[offset];
526
+ const length = buffer.readUInt32BE(offset + 1);
527
+ if (offset + 5 + length > buffer.length)
528
+ break;
529
+ let payload = buffer.slice(offset + 5, offset + 5 + length);
530
+ offset += 5 + length;
531
+ payload = (0, cursor_stream_parser_js_1.decompressPayload)(payload, flags);
532
+ // Check for JSON error format
533
+ try {
534
+ const text = payload.toString('utf-8');
535
+ if (text.startsWith('{') && text.includes('"error"')) {
536
+ yield { type: 'error', response: createErrorResponse(JSON.parse(text)) };
537
+ return;
538
+ }
539
+ }
540
+ catch (err) {
541
+ if (process.env.CCS_DEBUG) {
542
+ console.error('[cursor] parseProtobufFrames error parsing failed:', err);
543
+ }
544
+ }
545
+ const result = (0, cursor_protobuf_js_1.extractTextFromResponse)(new Uint8Array(payload));
546
+ // Check for protobuf-decoded error
547
+ if (result.error) {
548
+ const errorLower = result.error.toLowerCase();
549
+ const isRateLimit = errorLower.includes('rate limit') ||
550
+ errorLower.includes('resource_exhausted') ||
551
+ errorLower.includes('too many requests');
552
+ yield {
553
+ type: 'error',
554
+ response: new Response(JSON.stringify({
555
+ error: {
556
+ message: result.error,
557
+ type: isRateLimit ? 'rate_limit_error' : 'server_error',
558
+ code: isRateLimit ? 'rate_limited' : 'cursor_error',
559
+ },
560
+ }), {
561
+ status: isRateLimit ? 429 : 400,
562
+ headers: { 'Content-Type': 'application/json' },
563
+ }),
564
+ };
565
+ return;
566
+ }
567
+ if (result.toolCall) {
568
+ yield { type: 'toolCall', toolCall: result.toolCall };
569
+ }
570
+ if (result.text) {
571
+ yield { type: 'text', text: result.text };
572
+ }
573
+ }
574
+ }
575
+ transformProtobufToJSON(buffer, model, _body) {
576
+ const responseId = `chatcmpl-cursor-${Date.now()}`;
577
+ const created = Math.floor(Date.now() / 1000);
578
+ let totalContent = '';
579
+ const toolCalls = [];
580
+ const toolCallsMap = new Map();
581
+ for (const frame of this.parseProtobufFrames(buffer)) {
582
+ if (frame.type === 'error') {
583
+ return frame.response;
584
+ }
585
+ if (frame.type === 'toolCall') {
586
+ const tc = frame.toolCall;
587
+ if (toolCallsMap.has(tc.id)) {
588
+ const existing = toolCallsMap.get(tc.id);
589
+ if (!existing)
590
+ continue;
591
+ existing.function.arguments += tc.function.arguments;
592
+ existing.isLast = tc.isLast;
593
+ }
594
+ else {
595
+ toolCallsMap.set(tc.id, {
596
+ ...tc,
597
+ index: toolCallsMap.size,
598
+ });
599
+ }
600
+ if (tc.isLast) {
601
+ const finalToolCall = toolCallsMap.get(tc.id);
602
+ if (!finalToolCall)
603
+ continue;
604
+ toolCalls.push({
605
+ id: finalToolCall.id,
606
+ type: finalToolCall.type,
607
+ function: {
608
+ name: finalToolCall.function.name,
609
+ arguments: finalToolCall.function.arguments,
610
+ },
611
+ });
612
+ }
613
+ }
614
+ if (frame.type === 'text') {
615
+ totalContent += frame.text;
616
+ }
617
+ }
618
+ // Finalize remaining tool calls
619
+ for (const id of Array.from(toolCallsMap.keys())) {
620
+ const tc = toolCallsMap.get(id);
621
+ if (!tc)
622
+ continue;
623
+ if (!toolCalls.find((t) => t.id === id)) {
624
+ toolCalls.push({
625
+ id: tc.id,
626
+ type: tc.type,
627
+ function: {
628
+ name: tc.function.name,
629
+ arguments: tc.function.arguments,
630
+ },
631
+ });
632
+ }
633
+ }
634
+ const message = {
635
+ role: 'assistant',
636
+ content: totalContent || null,
637
+ };
638
+ if (toolCalls.length > 0) {
639
+ message.tool_calls = toolCalls;
640
+ }
641
+ const completion = {
642
+ id: responseId,
643
+ object: 'chat.completion',
644
+ created,
645
+ model,
646
+ choices: [
647
+ {
648
+ index: 0,
649
+ message,
650
+ finish_reason: toolCalls.length > 0 ? 'tool_calls' : 'stop',
651
+ },
652
+ ],
653
+ usage: {
654
+ prompt_tokens: 0,
655
+ completion_tokens: 0,
656
+ total_tokens: 0,
657
+ },
658
+ };
659
+ return new Response(JSON.stringify(completion), {
660
+ status: 200,
661
+ headers: { 'Content-Type': 'application/json' },
662
+ });
663
+ }
664
+ /** @deprecated Use executeStreaming() for real-time SSE. Retained for fetch fallback. */
665
+ transformProtobufToSSE(buffer, model, _body) {
666
+ const responseId = `chatcmpl-cursor-${Date.now()}`;
667
+ const created = Math.floor(Date.now() / 1000);
668
+ const chunks = [];
669
+ const toolCalls = [];
670
+ const toolCallsMap = new Map();
671
+ for (const frame of this.parseProtobufFrames(buffer)) {
672
+ if (frame.type === 'error') {
673
+ return frame.response;
674
+ }
675
+ if (frame.type === 'toolCall') {
676
+ const tc = frame.toolCall;
677
+ if (chunks.length === 0) {
678
+ chunks.push(`data: ${JSON.stringify({
679
+ id: responseId,
680
+ object: 'chat.completion.chunk',
681
+ created,
682
+ model,
683
+ choices: [
684
+ {
685
+ index: 0,
686
+ delta: { role: 'assistant', content: '' },
687
+ finish_reason: null,
688
+ },
689
+ ],
690
+ })}\n\n`);
691
+ }
692
+ if (toolCallsMap.has(tc.id)) {
693
+ const existing = toolCallsMap.get(tc.id);
694
+ if (!existing)
695
+ continue;
696
+ existing.function.arguments += tc.function.arguments;
697
+ existing.isLast = tc.isLast;
698
+ if (tc.function.arguments) {
699
+ chunks.push(`data: ${JSON.stringify({
700
+ id: responseId,
701
+ object: 'chat.completion.chunk',
702
+ created,
703
+ model,
704
+ choices: [
705
+ {
706
+ index: 0,
707
+ delta: {
708
+ tool_calls: [
709
+ {
710
+ index: existing.index,
711
+ id: tc.id,
712
+ type: 'function',
713
+ function: {
714
+ name: tc.function.name,
715
+ arguments: tc.function.arguments,
716
+ },
717
+ },
718
+ ],
719
+ },
720
+ finish_reason: null,
721
+ },
722
+ ],
723
+ })}\n\n`);
724
+ }
725
+ }
726
+ else {
727
+ const toolCallIndex = toolCalls.length;
728
+ toolCalls.push({ ...tc, index: toolCallIndex });
729
+ toolCallsMap.set(tc.id, { ...tc, index: toolCallIndex });
730
+ chunks.push(`data: ${JSON.stringify({
731
+ id: responseId,
732
+ object: 'chat.completion.chunk',
733
+ created,
734
+ model,
735
+ choices: [
736
+ {
737
+ index: 0,
738
+ delta: {
739
+ tool_calls: [
740
+ {
741
+ index: toolCallIndex,
742
+ id: tc.id,
743
+ type: 'function',
744
+ function: {
745
+ name: tc.function.name,
746
+ arguments: tc.function.arguments,
747
+ },
748
+ },
749
+ ],
750
+ },
751
+ finish_reason: null,
752
+ },
753
+ ],
754
+ })}\n\n`);
755
+ }
756
+ }
757
+ if (frame.type === 'text') {
758
+ chunks.push(`data: ${JSON.stringify({
759
+ id: responseId,
760
+ object: 'chat.completion.chunk',
761
+ created,
762
+ model,
763
+ choices: [
764
+ {
765
+ index: 0,
766
+ delta: chunks.length === 0 && toolCalls.length === 0
767
+ ? { role: 'assistant', content: frame.text }
768
+ : { content: frame.text },
769
+ finish_reason: null,
770
+ },
771
+ ],
772
+ })}\n\n`);
773
+ }
774
+ }
775
+ if (chunks.length === 0 && toolCalls.length === 0) {
776
+ chunks.push(`data: ${JSON.stringify({
777
+ id: responseId,
778
+ object: 'chat.completion.chunk',
779
+ created,
780
+ model,
781
+ choices: [
782
+ {
783
+ index: 0,
784
+ delta: { role: 'assistant', content: '' },
785
+ finish_reason: null,
786
+ },
787
+ ],
788
+ })}\n\n`);
789
+ }
790
+ chunks.push(`data: ${JSON.stringify({
791
+ id: responseId,
792
+ object: 'chat.completion.chunk',
793
+ created,
794
+ model,
795
+ choices: [
796
+ {
797
+ index: 0,
798
+ delta: {},
799
+ finish_reason: toolCalls.length > 0 ? 'tool_calls' : 'stop',
800
+ },
801
+ ],
802
+ usage: {
803
+ prompt_tokens: 0,
804
+ completion_tokens: 0,
805
+ total_tokens: 0,
806
+ },
807
+ })}\n\n`);
808
+ chunks.push('data: [DONE]\n\n');
809
+ return new Response(chunks.join(''), {
810
+ status: 200,
811
+ headers: {
812
+ 'Content-Type': 'text/event-stream',
813
+ 'Cache-Control': 'no-cache',
814
+ Connection: 'keep-alive',
815
+ },
816
+ });
817
+ }
818
+ }
819
+ exports.CursorExecutor = CursorExecutor;
820
+ exports.default = CursorExecutor;
821
+ //# sourceMappingURL=cursor-executor.js.map