@cursorpool-dev/cli 0.5.6 → 0.5.8

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 (108) hide show
  1. package/node_modules/@cursor-pool/extension/dist/extension.js +116 -46
  2. package/node_modules/@cursor-pool/extension/package.json +3 -3
  3. package/node_modules/@cursor-pool/extension/src/api.ts +17 -2
  4. package/node_modules/@cursor-pool/extension/src/panel.ts +26 -3
  5. package/node_modules/@cursor-pool/extension/test/panel.test.ts +34 -1
  6. package/node_modules/@cursor-pool/patcher/package.json +2 -2
  7. package/node_modules/@cursor-pool/patcher/src/marker.ts +5 -1
  8. package/node_modules/@cursor-pool/patcher/src/workbenchAuthGateMarker.ts +58 -7
  9. package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +20 -0
  10. package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +193 -2
  11. package/node_modules/@cursor-pool/service/package.json +2 -2
  12. package/node_modules/@cursor-pool/service/src/platformSession.ts +30 -7
  13. package/node_modules/@cursor-pool/service/src/server.ts +1 -0
  14. package/node_modules/@cursor-pool/service/test/platformSession.test.ts +5 -4
  15. package/node_modules/@cursor-pool/service/test/server.test.ts +130 -0
  16. package/node_modules/@cursor-pool/shared/package.json +1 -1
  17. package/node_modules/@cursor-pool/shared/src/manifest.ts +35 -0
  18. package/node_modules/@cursor-pool/shared/test/manifest.test.ts +43 -9
  19. package/node_modules/@cursor-pool/takeover-plans/package.json +12 -0
  20. package/node_modules/@cursor-pool/takeover-plans/src/index.ts +22 -0
  21. package/node_modules/@cursor-pool/takeover-plans/src/plans.ts +37 -0
  22. package/node_modules/@cursor-pool/takeover-plans/src/types.ts +9 -0
  23. package/node_modules/@cursor-pool/takeover-plans/test/registry.test.ts +23 -0
  24. package/node_modules/@esbuild/linux-x64/README.md +3 -0
  25. package/node_modules/@esbuild/linux-x64/bin/esbuild +0 -0
  26. package/node_modules/@esbuild/linux-x64/package.json +20 -0
  27. package/node_modules/esbuild/LICENSE.md +21 -0
  28. package/node_modules/esbuild/README.md +3 -0
  29. package/node_modules/esbuild/bin/esbuild +223 -0
  30. package/node_modules/esbuild/install.js +300 -0
  31. package/node_modules/esbuild/lib/main.d.ts +716 -0
  32. package/node_modules/esbuild/lib/main.js +2532 -0
  33. package/node_modules/esbuild/package.json +74 -0
  34. package/node_modules/tsx/LICENSE +21 -0
  35. package/node_modules/tsx/README.md +32 -0
  36. package/node_modules/tsx/dist/cjs/api/index.cjs +1 -0
  37. package/node_modules/tsx/dist/cjs/api/index.d.cts +35 -0
  38. package/node_modules/tsx/dist/cjs/api/index.d.mts +35 -0
  39. package/node_modules/tsx/dist/cjs/api/index.mjs +1 -0
  40. package/node_modules/tsx/dist/cjs/index.cjs +1 -0
  41. package/node_modules/tsx/dist/cjs/index.mjs +1 -0
  42. package/node_modules/tsx/dist/cli.cjs +54 -0
  43. package/node_modules/tsx/dist/cli.mjs +55 -0
  44. package/node_modules/tsx/dist/client-D3mGB526.cjs +1 -0
  45. package/node_modules/tsx/dist/client-D_mPDF5S.mjs +1 -0
  46. package/node_modules/tsx/dist/esm/api/index.cjs +1 -0
  47. package/node_modules/tsx/dist/esm/api/index.d.cts +35 -0
  48. package/node_modules/tsx/dist/esm/api/index.d.mts +35 -0
  49. package/node_modules/tsx/dist/esm/api/index.mjs +1 -0
  50. package/node_modules/tsx/dist/esm/index.cjs +1 -0
  51. package/node_modules/tsx/dist/esm/index.mjs +1 -0
  52. package/node_modules/tsx/dist/get-pipe-path-D4YM6rQt.cjs +1 -0
  53. package/node_modules/tsx/dist/get-pipe-path-_tAJyU_v.mjs +1 -0
  54. package/node_modules/tsx/dist/index-BWFBUo6r.cjs +1 -0
  55. package/node_modules/tsx/dist/index-D9F1FXzN.cjs +14 -0
  56. package/node_modules/tsx/dist/index-XurvG3JN.mjs +14 -0
  57. package/node_modules/tsx/dist/index-gbaejti9.mjs +1 -0
  58. package/node_modules/tsx/dist/lexer-DQCqS3nf.mjs +3 -0
  59. package/node_modules/tsx/dist/lexer-DgIbo0BU.cjs +3 -0
  60. package/node_modules/tsx/dist/loader.cjs +1 -0
  61. package/node_modules/tsx/dist/loader.mjs +1 -0
  62. package/node_modules/tsx/dist/node-features-B9BBLzwu.mjs +1 -0
  63. package/node_modules/tsx/dist/node-features-CQLdkVE6.cjs +1 -0
  64. package/node_modules/tsx/dist/package-CGdS2_oX.cjs +1 -0
  65. package/node_modules/tsx/dist/package-DyJMwVU5.mjs +1 -0
  66. package/node_modules/tsx/dist/patch-repl.cjs +1 -0
  67. package/node_modules/tsx/dist/patch-repl.mjs +1 -0
  68. package/node_modules/tsx/dist/preflight.cjs +1 -0
  69. package/node_modules/tsx/dist/preflight.mjs +1 -0
  70. package/node_modules/tsx/dist/register-BOkp8V6j.cjs +10 -0
  71. package/node_modules/tsx/dist/register-BnTWPeIB.mjs +10 -0
  72. package/node_modules/tsx/dist/register-CHVGxKtC.cjs +2 -0
  73. package/node_modules/tsx/dist/register-D_B8UL5H.mjs +2 -0
  74. package/node_modules/tsx/dist/repl.cjs +3 -0
  75. package/node_modules/tsx/dist/repl.mjs +3 -0
  76. package/node_modules/tsx/dist/require-CjvaJWEr.cjs +1 -0
  77. package/node_modules/tsx/dist/require-DzmC1hVr.mjs +1 -0
  78. package/node_modules/tsx/dist/suppress-warnings.cjs +1 -0
  79. package/node_modules/tsx/dist/suppress-warnings.mjs +1 -0
  80. package/node_modules/tsx/dist/temporary-directory-B83uKxJF.cjs +1 -0
  81. package/node_modules/tsx/dist/temporary-directory-BDDVQOvU.mjs +1 -0
  82. package/node_modules/tsx/dist/types-Cxp8y2TL.d.ts +5 -0
  83. package/node_modules/tsx/package.json +67 -0
  84. package/package.json +11 -6
  85. package/src/autostart.ts +5 -1
  86. package/src/compat.ts +193 -47
  87. package/src/cursor.ts +59 -3
  88. package/src/extensionBundle.ts +1 -1
  89. package/src/extensionLink.ts +28 -7
  90. package/src/install.ts +176 -24
  91. package/src/installRecord.ts +2 -0
  92. package/src/patchSet.ts +12 -6
  93. package/src/platform.ts +3 -3
  94. package/src/repair.ts +10 -1
  95. package/src/restore.ts +12 -4
  96. package/src/serviceProcess.ts +2 -1
  97. package/src/status.ts +6 -0
  98. package/src/trial.ts +1 -0
  99. package/test/autostart.test.ts +23 -2
  100. package/test/compat.test.ts +238 -3
  101. package/test/cursor-pool-bin.test.ts +1 -0
  102. package/test/cursor.test.ts +60 -1
  103. package/test/e2e-install.test.ts +53 -0
  104. package/test/extensionLink.test.ts +48 -2
  105. package/test/install.test.ts +191 -6
  106. package/test/repair.test.ts +1 -0
  107. package/test/serviceProcess.test.ts +10 -1
  108. package/test/status.test.ts +1 -0
@@ -1,5 +1,5 @@
1
1
  export const CURSOR_POOL_WORKBENCH_AUTH_GATE_MARKER =
2
- 'CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V17_PLATFORM_PREFLIGHT';
2
+ 'CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V18_ROUTE_READY_GUARD';
3
3
  export const CURSOR_POOL_WORKBENCH_AUTH_GATE_BEGIN_MARKER =
4
4
  `/* ${CURSOR_POOL_WORKBENCH_AUTH_GATE_MARKER}: begin */`;
5
5
  export const CURSOR_POOL_WORKBENCH_AUTH_GATE_END_MARKER =
@@ -27,8 +27,16 @@ export const CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR =
27
27
  'if(!p()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(wV,"general");return}';
28
28
  export const CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_LINUX_3_6 =
29
29
  'if(!h()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(P5,"general");return}';
30
+ export const CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_MAC_3_7 =
31
+ 'if(!h()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(a6,"general");return}';
32
+ export const CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_MAC_3_4 =
33
+ 'if(!t()){e.cursorAuthenticationService.login();return}';
30
34
  export const CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_LINUX_3_6 =
31
35
  'get when(){return t()},get fallback(){return(()=>{var R=x81();return fe(R,ie(lo,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return';
36
+ export const CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_7 =
37
+ 'get when(){return t()},get fallback(){return(()=>{var R=Swx();return ge(R,ie(go,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return';
38
+ export const CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_4 =
39
+ 'get when(){return t()},get fallback(){return(()=>{var R=npC();return ke(R,re(ea,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return';
32
40
  export const CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_AUTH_GATE_ANCHOR =
33
41
  'get when(){return t()},get fallback(){return(()=>{var D=avx();return Pe(D,he(sl,{keybinding:" \\u23CE",onClick:T,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),D})()},get children(){return';
34
42
  export const CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_LOGIN_ANCHOR =
@@ -44,9 +52,13 @@ export const CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR =
44
52
  'if(L0.localMode){try{g.onNetworkPhaseStart?.()}catch(b){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",b)}return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,d,h,g)}return this.client.run(e,t,i,r,s,o,a,u,d,h,g)';
45
53
  export const CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR_LINUX_3_6 =
46
54
  'if(uv.localMode){try{h.onNetworkPhaseStart?.()}catch(f){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",f)}return this.runLocalAgentInExtensionHost(n,e,t,i,r,o,c,d,h)}return this.client.run(n,e,t,i,r,s,o,a,c,d,h)';
55
+ export const CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR_MAC_3_7 =
56
+ 'if(wv.localMode){try{h.onNetworkPhaseStart?.()}catch(f){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",f)}return this.runLocalAgentInExtensionHost(n,e,t,i,r,o,c,d,h)}return this.client.run(n,e,t,i,r,s,o,a,c,d,h)';
57
+ export const CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR_MAC_3_4 =
58
+ 'if(U0.localMode){try{f.onNetworkPhaseStart?.()}catch(v){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",v)}return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,u,d,f)}return this.client.run(e,t,i,r,s,o,a,l,u,d,f)';
47
59
 
48
60
  function buildPlatformModeGuardBootstrapExpression() {
49
- return '((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{try{if(globalThis.__cursorPoolPlatformModeGuardReady)return;globalThis.__cursorPoolPlatformModeGuardReady=!0;globalThis.__cursorPoolRuntimeBaseUrl=()=>{try{const e="http://127.0.0.1:56393";if(typeof require!="function")return e;const t=require("node:fs"),r=require("node:os"),o=require("node:path"),n=process?.env?.CURSOR_POOL_RUNTIME_FILE||o.join(r.homedir(),".cursor-pool","runtime.json");if(!t.existsSync(n))return e;const i=JSON.parse(t.readFileSync(n,"utf8"));return i?.host==="127.0.0.1"&&Number.isInteger(i?.port)&&i.port>0&&i.port<65536?`http://127.0.0.1:${i.port}`:e}catch{return "http://127.0.0.1:56393"}};globalThis.__cursorPoolReadVerifiedPlatformModeCache=()=>{try{const e=Number(globalThis.localStorage?.getItem("cursorPoolPlatformModeCheckedAt")||"0");return Date.now()-e<3e5?globalThis.localStorage?.getItem("cursorPoolPlatformModeActive")==="1":!1}catch{return!1}};globalThis.__cursorPoolReadSessionPlatformModeActive=()=>{try{if(typeof require!="function")return null;const e=require("node:fs"),t=require("node:os"),r=require("node:path"),o=process?.env?.CURSOR_POOL_PLATFORM_SESSION_FILE||r.join(t.homedir(),".cursor-pool","session.json");if(!e.existsSync(o))return null;const n=JSON.parse(e.readFileSync(o,"utf8")),i=n?.session;return n?.device?.status==="active"&&n?.platformMode==="active"&&typeof n?.activeProductId==="string"&&typeof n?.platformModeStartedAt==="string"||i?.device?.status==="active"&&i?.mode?.state==="active"}catch{return null}};globalThis.__cursorPoolReadPlatformModeActive=()=>{try{return globalThis.__cursorPoolReadSessionPlatformModeActive?.()===!0||globalThis.__cursorPoolReadVerifiedPlatformModeCache?.()===!0}catch{return!1}};globalThis.__cursorPoolPlatformModeActiveCache=globalThis.__cursorPoolReadPlatformModeActive(),globalThis.__cursorPoolRefreshPlatformModeActive=()=>{try{if(globalThis.__cursorPoolPlatformModeRefreshInFlight||typeof globalThis.fetch!="function")return;const e=globalThis.__cursorPoolRuntimeBaseUrl?.();if(!e)return;globalThis.__cursorPoolPlatformModeRefreshInFlight=!0,globalThis.fetch(`${e}/platform/status`).then(e=>e.ok?e.json():null).then(e=>{const t=e?.mode?.state==="active",r=globalThis.__cursorPoolPlatformModeActiveCache===!0;globalThis.__cursorPoolPlatformModeActiveCache=t;try{globalThis.localStorage?.setItem("cursorPoolPlatformModeActive",t?"1":"0"),globalThis.localStorage?.setItem("cursorPoolPlatformModeCheckedAt",String(Date.now()))}catch{}t!==r&&typeof globalThis.setTimeout=="function"&&globalThis.setTimeout(()=>globalThis.location?.reload?.(),50)}).catch(()=>{const e=globalThis.__cursorPoolPlatformModeActiveCache===!0;globalThis.__cursorPoolPlatformModeActiveCache=globalThis.__cursorPoolReadPlatformModeActive?.()===!0;try{globalThis.localStorage?.setItem("cursorPoolPlatformModeActive",globalThis.__cursorPoolPlatformModeActiveCache?"1":"0")}catch{}e!==globalThis.__cursorPoolPlatformModeActiveCache&&typeof globalThis.setTimeout=="function"&&globalThis.setTimeout(()=>globalThis.location?.reload?.(),50)}).finally(()=>{globalThis.__cursorPoolPlatformModeRefreshInFlight=!1})}catch{}},globalThis.__cursorPoolIsPlatformModeActive=()=>{try{globalThis.__cursorPoolEnsurePlatformModeGuard?.();return globalThis.__cursorPoolPlatformModeActiveCache===!0}catch{return!1}},globalThis.__cursorPoolRefreshPlatformModeActive(),globalThis.__cursorPoolPlatformModeRefreshTimer||typeof globalThis.setInterval!="function"||(globalThis.__cursorPoolPlatformModeRefreshTimer=globalThis.setInterval(globalThis.__cursorPoolRefreshPlatformModeActive,1e3))}catch{}}))(),globalThis.__cursorPoolIsPlatformModeActive?.()===true)';
61
+ return '((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{try{if(globalThis.__cursorPoolPlatformModeGuardReady)return;globalThis.__cursorPoolPlatformModeGuardReady=!0;globalThis.__cursorPoolRuntimeBaseUrl=()=>{try{const e="http://127.0.0.1:56393";if(typeof require!="function")return e;const t=require("node:fs"),r=require("node:os"),o=require("node:path"),n=process?.env?.CURSOR_POOL_RUNTIME_FILE||o.join(r.homedir(),".cursor-pool","runtime.json");if(!t.existsSync(n))return e;const i=JSON.parse(t.readFileSync(n,"utf8"));return i?.host==="127.0.0.1"&&Number.isInteger(i?.port)&&i.port>0&&i.port<65536?`http://127.0.0.1:${i.port}`:e}catch{return "http://127.0.0.1:56393"}};globalThis.__cursorPoolStatusAllowsTakeover=e=>{try{return e?.mode?.state==="active"&&e?.mode?.route?.state==="ready"}catch{return!1}};globalThis.__cursorPoolReadVerifiedPlatformModeCache=()=>{try{const e=Number(globalThis.localStorage?.getItem("cursorPoolPlatformModeCheckedAt")||"0");return Date.now()-e<3e5?globalThis.localStorage?.getItem("cursorPoolPlatformModeActive")==="1":!1}catch{return!1}};globalThis.__cursorPoolReadSessionPlatformModeActive=()=>{try{if(typeof require!="function")return null;const e=require("node:fs"),t=require("node:os"),r=require("node:path"),o=process?.env?.CURSOR_POOL_PLATFORM_SESSION_FILE||r.join(t.homedir(),".cursor-pool","session.json");if(!e.existsSync(o))return null;const n=JSON.parse(e.readFileSync(o,"utf8")),i=n?.routeToken,a=i&&Date.parse(i.expiresAt)>Date.now();return n?.device?.status==="active"&&n?.platformMode==="active"&&typeof n?.activeProductId==="string"&&typeof n?.platformModeStartedAt==="string"&&a}catch{return null}};globalThis.__cursorPoolReadPlatformModeActive=()=>{try{return globalThis.__cursorPoolReadSessionPlatformModeActive?.()===!0||globalThis.__cursorPoolReadVerifiedPlatformModeCache?.()===!0}catch{return!1}};globalThis.__cursorPoolPlatformModeActiveCache=globalThis.__cursorPoolReadPlatformModeActive(),globalThis.__cursorPoolRefreshPlatformModeActive=()=>{try{if(globalThis.__cursorPoolPlatformModeRefreshInFlight||typeof globalThis.fetch!="function")return;const e=globalThis.__cursorPoolRuntimeBaseUrl?.();if(!e)return;globalThis.__cursorPoolPlatformModeRefreshInFlight=!0,globalThis.fetch(`${e}/platform/status`).then(e=>e.ok?e.json():null).then(e=>{const t=globalThis.__cursorPoolStatusAllowsTakeover?.(e)===!0,r=globalThis.__cursorPoolPlatformModeActiveCache===!0;globalThis.__cursorPoolPlatformModeActiveCache=t;try{globalThis.localStorage?.setItem("cursorPoolPlatformModeActive",t?"1":"0"),globalThis.localStorage?.setItem("cursorPoolPlatformModeCheckedAt",String(Date.now()))}catch{}t!==r&&typeof globalThis.setTimeout=="function"&&globalThis.setTimeout(()=>globalThis.location?.reload?.(),50)}).catch(()=>{const e=globalThis.__cursorPoolPlatformModeActiveCache===!0;globalThis.__cursorPoolPlatformModeActiveCache=globalThis.__cursorPoolReadPlatformModeActive?.()===!0;try{globalThis.localStorage?.setItem("cursorPoolPlatformModeActive",globalThis.__cursorPoolPlatformModeActiveCache?"1":"0")}catch{}e!==globalThis.__cursorPoolPlatformModeActiveCache&&typeof globalThis.setTimeout=="function"&&globalThis.setTimeout(()=>globalThis.location?.reload?.(),50)}).finally(()=>{globalThis.__cursorPoolPlatformModeRefreshInFlight=!1})}catch{}},globalThis.__cursorPoolIsPlatformModeActive=()=>{try{globalThis.__cursorPoolEnsurePlatformModeGuard?.();return globalThis.__cursorPoolPlatformModeActiveCache===!0}catch{return!1}},globalThis.__cursorPoolRefreshPlatformModeActive(),globalThis.__cursorPoolPlatformModeRefreshTimer||typeof globalThis.setInterval!="function"||(globalThis.__cursorPoolPlatformModeRefreshTimer=globalThis.setInterval(globalThis.__cursorPoolRefreshPlatformModeActive,1e3))}catch{}}))(),globalThis.__cursorPoolIsPlatformModeActive?.()===true)';
50
62
  }
51
63
 
52
64
  const CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION =
@@ -79,6 +91,7 @@ export function containsCursorWorkbenchAuthGateMarker(content: string) {
79
91
  export function containsAnyCursorWorkbenchAuthGateMarkerText(content: string) {
80
92
  return (
81
93
  content.includes(CURSOR_POOL_WORKBENCH_AUTH_GATE_MARKER) ||
94
+ content.includes('CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V17_PLATFORM_PREFLIGHT') ||
82
95
  content.includes('CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V16_SELF_BOOTSTRAP_PLATFORM_GUARD') ||
83
96
  content.includes('CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V15_RENDERER_STORAGE_GUARD') ||
84
97
  content.includes('CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V14_EXPLICIT_TAKEOVER_SWITCH') ||
@@ -112,7 +125,7 @@ ${CURSOR_POOL_WORKBENCH_AUTH_GATE_END_MARKER}`;
112
125
 
113
126
  function buildPlatformModePreflightSnippet() {
114
127
  return `/* ${CURSOR_POOL_WORKBENCH_PREFLIGHT_SIGNATURE}: begin */
115
- try{const e="http://127.0.0.1:56393/platform/status",t=await Promise.race([fetch(e).then(e=>e.ok?e.json():null),new Promise(e=>setTimeout(()=>e(null),500))]),r=t?.mode?.state==="active";localStorage?.setItem("cursorPoolPlatformModeActive",r?"1":"0"),localStorage?.setItem("cursorPoolPlatformModeCheckedAt",String(Date.now()))}catch{}
128
+ try{const e="http://127.0.0.1:56393/platform/status",t=await Promise.race([fetch(e).then(e=>e.ok?e.json():null),new Promise(e=>setTimeout(()=>e(null),500))]),r=t?.mode?.state==="active"&&t?.mode?.route?.state==="ready";localStorage?.setItem("cursorPoolPlatformModeActive",r?"1":"0"),localStorage?.setItem("cursorPoolPlatformModeCheckedAt",String(Date.now()))}catch{}
116
129
  /* ${CURSOR_POOL_WORKBENCH_PREFLIGHT_SIGNATURE}: end */
117
130
  `;
118
131
  }
@@ -144,6 +157,8 @@ function forceNativeLocalAgentMode(content: string) {
144
157
  const runBranchAnchor = [
145
158
  CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR,
146
159
  CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR_LINUX_3_6,
160
+ CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR_MAC_3_7,
161
+ CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR_MAC_3_4,
147
162
  ].find((anchor) => withProviderConfig.includes(anchor));
148
163
  const runBranchIndex = runBranchAnchor
149
164
  ? withProviderConfig.indexOf(runBranchAnchor)
@@ -152,10 +167,20 @@ function forceNativeLocalAgentMode(content: string) {
152
167
  throw new Error('Cursor Workbench agent client run localMode anchor was not found.');
153
168
  }
154
169
  const runBranchReplacement = runBranchAnchor!.replace(
155
- runBranchAnchor!.startsWith('if(uv.localMode)') ? 'if(uv.localMode)' : 'if(L0.localMode)',
170
+ runBranchAnchor!.startsWith('if(uv.localMode)')
171
+ ? 'if(uv.localMode)'
172
+ : runBranchAnchor!.startsWith('if(wv.localMode)')
173
+ ? 'if(wv.localMode)'
174
+ : runBranchAnchor!.startsWith('if(U0.localMode)')
175
+ ? 'if(U0.localMode)'
176
+ : 'if(L0.localMode)',
156
177
  runBranchAnchor!.startsWith('if(uv.localMode)')
157
178
  ? `if(${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}||uv.localMode)`
158
- : `if(${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}||L0.localMode)`,
179
+ : runBranchAnchor!.startsWith('if(wv.localMode)')
180
+ ? `if(${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}||wv.localMode)`
181
+ : runBranchAnchor!.startsWith('if(U0.localMode)')
182
+ ? `if(${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}||U0.localMode)`
183
+ : `if(${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}||L0.localMode)`,
159
184
  );
160
185
  return `${withProviderConfig.slice(0, runBranchIndex)}${runBranchReplacement}${withProviderConfig.slice(
161
186
  runBranchIndex + runBranchAnchor!.length,
@@ -171,7 +196,13 @@ export function injectCursorWorkbenchAuthGatePatch(content: string) {
171
196
  const linux36GateIndex = content.indexOf(
172
197
  CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_LINUX_3_6,
173
198
  );
174
- if (anchorIndex < 0 && linux36GateIndex < 0) {
199
+ const mac37GateIndex = content.indexOf(
200
+ CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_7,
201
+ );
202
+ const mac34GateIndex = content.indexOf(
203
+ CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_4,
204
+ );
205
+ if (anchorIndex < 0 && linux36GateIndex < 0 && mac37GateIndex < 0 && mac34GateIndex < 0) {
175
206
  throw new Error('Cursor Workbench composer auth gate anchor was not found.');
176
207
  }
177
208
 
@@ -184,11 +215,25 @@ export function injectCursorWorkbenchAuthGatePatch(content: string) {
184
215
  const linux36GateIndexWithPreflight = contentWithPreflight.indexOf(
185
216
  CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_LINUX_3_6,
186
217
  );
218
+ const mac37GateIndexWithPreflight = contentWithPreflight.indexOf(
219
+ CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_7,
220
+ );
221
+ const mac34GateIndexWithPreflight = contentWithPreflight.indexOf(
222
+ CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_4,
223
+ );
187
224
 
188
225
  const withUiGate = anchorIndexWithPreflight >= 0
189
226
  ? `${contentWithPreflight.slice(0, anchorIndexWithPreflight)}get when(){return (p()||${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION})&&!fzC},${buildCursorWorkbenchAuthGatePatchSnippet()}get fallback(){return he(DGC,{})}${contentWithPreflight.slice(
190
227
  anchorIndexWithPreflight + CURSOR_WORKBENCH_COMPOSER_AUTH_GATE_ANCHOR.length,
191
228
  )}`
229
+ : mac37GateIndexWithPreflight >= 0
230
+ ? `${contentWithPreflight.slice(0, mac37GateIndexWithPreflight)}get when(){return t()||${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}},${buildCursorWorkbenchAuthGatePatchSnippet()}get fallback(){return(()=>{var R=Swx();return ge(R,ie(go,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return${contentWithPreflight.slice(
231
+ mac37GateIndexWithPreflight + CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_7.length,
232
+ )}`
233
+ : mac34GateIndexWithPreflight >= 0
234
+ ? `${contentWithPreflight.slice(0, mac34GateIndexWithPreflight)}get when(){return t()||${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}},${buildCursorWorkbenchAuthGatePatchSnippet()}get fallback(){return(()=>{var R=npC();return ke(R,re(ea,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return${contentWithPreflight.slice(
235
+ mac34GateIndexWithPreflight + CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_MAC_3_4.length,
236
+ )}`
192
237
  : `${contentWithPreflight.slice(0, linux36GateIndexWithPreflight)}get when(){return h()||${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}},${buildCursorWorkbenchAuthGatePatchSnippet()}get fallback(){return(()=>{var R=x81();return fe(R,ie(lo,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return${contentWithPreflight.slice(
193
238
  linux36GateIndexWithPreflight + CURSOR_WORKBENCH_COMPOSER_SEND_BUTTON_AUTH_GATE_ANCHOR_LINUX_3_6.length,
194
239
  )}`;
@@ -204,7 +249,7 @@ export function injectCursorWorkbenchAuthGatePatch(content: string) {
204
249
 
205
250
  const withAgentEditorSubmitGate = withAgentEditorSendButtonGate.includes(
206
251
  CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_LOGIN_ANCHOR,
207
- )
252
+ ) && mac34GateIndexWithPreflight < 0
208
253
  ? withAgentEditorSendButtonGate.replace(
209
254
  CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_LOGIN_ANCHOR,
210
255
  `if(!t()&&!${CURSOR_POOL_PLATFORM_MODE_GUARD_EXPRESSION}){e.cursorAuthenticationService.login();return}`,
@@ -214,6 +259,8 @@ export function injectCursorWorkbenchAuthGatePatch(content: string) {
214
259
  const submitGateAnchor = [
215
260
  CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR,
216
261
  CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_LINUX_3_6,
262
+ CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_MAC_3_7,
263
+ CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_MAC_3_4,
217
264
  ].find((anchor) => withAgentEditorSubmitGate.includes(anchor));
218
265
  const submitGateIndex = submitGateAnchor ? withAgentEditorSubmitGate.indexOf(submitGateAnchor) : -1;
219
266
  if (submitGateIndex < 0) {
@@ -222,6 +269,10 @@ export function injectCursorWorkbenchAuthGatePatch(content: string) {
222
269
 
223
270
  const submitGateReplacement = submitGateAnchor === CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_LINUX_3_6
224
271
  ? 'if(!h()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(P5,"general");return}'
272
+ : submitGateAnchor === CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_MAC_3_7
273
+ ? 'if(!h()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(a6,"general");return}'
274
+ : submitGateAnchor === CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR_MAC_3_4
275
+ ? 'if(!t()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login();return}'
225
276
  : 'if(!p()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(wV,"general");return}';
226
277
  const withSubmitGate = `${withAgentEditorSubmitGate.slice(0, submitGateIndex)}${submitGateReplacement}${withAgentEditorSubmitGate.slice(
227
278
  submitGateIndex + submitGateAnchor!.length,
@@ -359,6 +359,26 @@ test('agent exec patch supports the Cursor 3.6 registerAgentExecProvider anchor'
359
359
  assert.ok(patched.indexOf(CURSOR_POOL_PATCH_SIGNATURE) < patched.indexOf(anchor));
360
360
  });
361
361
 
362
+ test('agent exec patch supports the Cursor 3.7 registerAgentExecProvider anchor', () => {
363
+ const anchor = 'const Et=c.cursor.registerAgentExecProvider(vt);';
364
+ assert.equal(CURSOR_POOL_AGENT_EXEC_PROVIDER_REGISTER_ANCHORS.includes(anchor), true);
365
+
366
+ const patched = injectCursorAgentExecPatchSnippet(`before();${anchor}after();`);
367
+
368
+ assert.equal(patched.includes(CURSOR_POOL_PATCH_SIGNATURE), true);
369
+ assert.ok(patched.indexOf(CURSOR_POOL_PATCH_SIGNATURE) < patched.indexOf(anchor));
370
+ });
371
+
372
+ test('agent exec patch supports the Cursor 3.4 registerAgentExecProvider anchor', () => {
373
+ const anchor = 'const dt=D.cursor.registerAgentExecProvider(ut);';
374
+ assert.equal(CURSOR_POOL_AGENT_EXEC_PROVIDER_REGISTER_ANCHORS.includes(anchor), true);
375
+
376
+ const patched = injectCursorAgentExecPatchSnippet(`before();${anchor}after();`);
377
+
378
+ assert.equal(patched.includes(CURSOR_POOL_PATCH_SIGNATURE), true);
379
+ assert.ok(patched.indexOf(CURSOR_POOL_PATCH_SIGNATURE) < patched.indexOf(anchor));
380
+ });
381
+
362
382
  test('agent exec provider wrapper works when Cursor API object is minified as c', async () => {
363
383
  const snippet = buildCursorAgentExecPatchSnippet();
364
384
  const registered: unknown[] = [];
@@ -36,6 +36,22 @@ const localProviderConfigAnchor =
36
36
  'async getLocalAgentProviderConfig(e){const t="[AgentClientService][getLocalAgentProviderConfig]",i=L0.localMode?await this.shellEnvironmentService.getShellEnv():{},r=e?.credentials,s=r?.case==="apiKeyCredentials"?r.value:void 0,o=this.reactiveStorageService.applicationUserPersistentStorage,a=o.useOpenAIKey===!0?this.cursorAuthenticationService.openAIKey()??void 0:void 0,u=xgS({apiKeyCandidates:[{value:s?.apiKey,source:"modelDetails.apiKeyCredentials.apiKey"},{value:a,source:"storage.openAIKey"}],baseUrlCandidates:[{value:s?.baseUrl,source:"modelDetails.apiKeyCredentials.baseUrl"},{value:o.openAIBaseUrl,source:"storage.openAIBaseUrl"}]});return{baseUrl:u.baseUrl,apiKey:u.apiKey}}createDefaultLocalModel(e){return "default"}';
37
37
  const agentClientRunLocalModeAnchor =
38
38
  'if(L0.localMode){try{g.onNetworkPhaseStart?.()}catch(b){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",b)}return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,d,h,g)}return this.client.run(e,t,i,r,s,o,a,u,d,h,g)';
39
+ const composerSendButtonAuthGateAnchorMac37 =
40
+ 'get when(){return t()},get fallback(){return(()=>{var R=Swx();return ge(R,ie(go,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return';
41
+ const composerSubmitAuthGateAnchorMac37 =
42
+ 'if(!h()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(a6,"general");return}';
43
+ const localProviderConfigAnchorMac37 =
44
+ 'async getLocalAgentProviderConfig(n){const e="[AgentClientService][getLocalAgentProviderConfig]",t=wv.localMode?await this.shellEnvironmentService.getShellEnv():{},i=n?.credentials,r=i?.case==="apiKeyCredentials"?i.value:void 0,s=this.reactiveStorageService.applicationUserPersistentStorage,o=s.useOpenAIKey===!0?this.cursorAuthenticationService.openAIKey()??void 0:void 0,c=xgS({apiKeyCandidates:[{value:r?.apiKey,source:"modelDetails.apiKeyCredentials.apiKey"},{value:o,source:"storage.openAIKey"}],baseUrlCandidates:[{value:r?.baseUrl,source:"modelDetails.apiKeyCredentials.baseUrl"},{value:s.openAIBaseUrl,source:"storage.openAIBaseUrl"}]});return{baseUrl:c.baseUrl,apiKey:c.apiKey}}createDefaultLocalModel(n){return "default"}';
45
+ const agentClientRunLocalModeAnchorMac37 =
46
+ 'if(wv.localMode){try{h.onNetworkPhaseStart?.()}catch(f){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",f)}return this.runLocalAgentInExtensionHost(n,e,t,i,r,o,c,d,h)}return this.client.run(n,e,t,i,r,s,o,a,c,d,h)';
47
+ const composerSendButtonAuthGateAnchorMac34 =
48
+ 'get when(){return t()},get fallback(){return(()=>{var R=npC();return ke(R,re(ea,{keybinding:" \\u23CE",onClick:E,hintText:"Log in to use Cloud Agents",variant:"secondary",children:"Log in"})),R})()},get children(){return';
49
+ const composerSubmitAuthGateAnchorMac34 =
50
+ 'if(!t()){e.cursorAuthenticationService.login();return}';
51
+ const localProviderConfigAnchorMac34 =
52
+ 'async getLocalAgentProviderConfig(e){const t="[AgentClientService][getLocalAgentProviderConfig]",i=U0.localMode?await this.shellEnvironmentService.getShellEnv():{},r=e?.credentials,s=r?.case==="apiKeyCredentials"?r.value:void 0,o=this.reactiveStorageService.applicationUserPersistentStorage,a=o.useOpenAIKey===!0?this.cursorAuthenticationService.openAIKey()??void 0:void 0;return{baseUrl:"https://api2.cursor.sh",apiKey:a}}createDefaultLocalModel(e){return "default"}';
53
+ const agentClientRunLocalModeAnchorMac34 =
54
+ 'if(U0.localMode){try{f.onNetworkPhaseStart?.()}catch(v){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",v)}return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,u,d,f)}return this.client.run(e,t,i,r,s,o,a,l,u,d,f)';
39
55
 
40
56
  function workbenchFixture(extra = '') {
41
57
  return [
@@ -50,6 +66,27 @@ function workbenchFixture(extra = '') {
50
66
  ].join(';');
51
67
  }
52
68
 
69
+ function workbenchFixtureMac37() {
70
+ return [
71
+ `function composer(){return ge(Mt,{${composerSendButtonAuthGateAnchorMac37}"controls"}})}`,
72
+ `async function submit(){${composerSubmitAuthGateAnchorMac37};return "submitted";}`,
73
+ `function agentEditorControls(){const E=()=>{${agentEditorSendButtonLoginAnchor};return n.handleSubmit()};return "controls"}`,
74
+ `const flags={${buildFlagsLocalModeAnchor}}`,
75
+ localProviderConfigAnchorMac37,
76
+ `async function agentClientRun(){const h={...m,isRunningInTest:m.isRunningInTest??this.environmentService.enableSmokeTestDriver===!0,clientSupportsInlineImages:!0};${agentClientRunLocalModeAnchorMac37}}`,
77
+ ].join(';');
78
+ }
79
+
80
+ function workbenchFixtureMac34() {
81
+ return [
82
+ `function composer(){const E=()=>{${composerSubmitAuthGateAnchorMac34};return n.handleSubmit()};return ke(Mt,{${composerSendButtonAuthGateAnchorMac34}"controls"}})}`,
83
+ `function agentEditorControls(){return "controls"}`,
84
+ `const flags={${buildFlagsLocalModeAnchor}}`,
85
+ localProviderConfigAnchorMac34,
86
+ `async function agentClientRun(){const f={...h,isRunningInTest:h.isRunningInTest??this.environmentService.enableSmokeTestDriver===!0,clientSupportsInlineImages:!0};${agentClientRunLocalModeAnchorMac34}}`,
87
+ ].join(';');
88
+ }
89
+
53
90
  async function createFixture(
54
91
  content = workbenchFixture(),
55
92
  ) {
@@ -173,6 +210,48 @@ test('patchCursorWorkbenchAuthGate upgrades old V9 always-active guard from clea
173
210
  }
174
211
  });
175
212
 
213
+ test('patchCursorWorkbenchAuthGate upgrades old V17 active-only preflight from clean backup', async () => {
214
+ const backupDir = join(tmpdir(), `cursor-pool-workbench-v17-upgrade-${Date.now()}-${Math.random()}`);
215
+ const fixture = await createFixture();
216
+
217
+ try {
218
+ const originalContent = await readFile(fixture.targetPath, 'utf8');
219
+ const backupPath = await backupPathForCursorWorkbenchAuthGate(
220
+ fixture.appPath,
221
+ fixture.targetPath,
222
+ backupDir,
223
+ );
224
+ await mkdir(dirname(backupPath), { recursive: true });
225
+ await writeFile(backupPath, originalContent, 'utf8');
226
+ const oldV17Patched = injectCursorWorkbenchAuthGatePatch(originalContent)
227
+ .replaceAll(
228
+ CURSOR_POOL_WORKBENCH_AUTH_GATE_MARKER,
229
+ 'CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V17_PLATFORM_PREFLIGHT',
230
+ )
231
+ .replaceAll(
232
+ 'e?.mode?.state==="active"&&e?.mode?.route?.state==="ready"',
233
+ 'e?.mode?.state==="active"',
234
+ )
235
+ .replaceAll(
236
+ 't?.mode?.state==="active"&&t?.mode?.route?.state==="ready"',
237
+ 't?.mode?.state==="active"',
238
+ );
239
+ await writeFile(fixture.targetPath, oldV17Patched, 'utf8');
240
+
241
+ const result = await patchCursorWorkbenchAuthGate(fixture.appPath, { backupDir });
242
+ const upgraded = await readFile(fixture.targetPath, 'utf8');
243
+
244
+ assert.notEqual(result.afterHash, result.beforeHash);
245
+ assert.equal(containsCursorWorkbenchAuthGateMarker(upgraded), true);
246
+ assert.equal(upgraded.includes('CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V17_PLATFORM_PREFLIGHT'), false);
247
+ assert.equal(upgraded.includes('mode?.state==="active"&&e?.mode?.route?.state==="ready'), true);
248
+ assert.equal(upgraded.includes('t?.mode?.state==="active"&&t?.mode?.route?.state==="ready"'), true);
249
+ } finally {
250
+ await rm(fixture.appPath, { recursive: true, force: true });
251
+ await rm(backupDir, { recursive: true, force: true });
252
+ }
253
+ });
254
+
176
255
  test('workbench auth gate patch keeps the native agent loop instead of appending fake AI bubbles', () => {
177
256
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
178
257
 
@@ -207,6 +286,50 @@ test('workbench auth gate patch delegates agent turns to the local service only
207
286
  assert.equal(patched.includes('return this.client.run(e,t,i,r,s,o,a,u,d,h,g)'), true);
208
287
  });
209
288
 
289
+ test('workbench auth gate patch supports Cursor 3.7 macOS workbench anchors', () => {
290
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixtureMac37());
291
+
292
+ assert.equal(containsCursorWorkbenchAuthGateMarker(patched), true);
293
+ assert.equal(patched.includes(composerSendButtonAuthGateAnchorMac37), false);
294
+ assert.equal(patched.includes(composerSubmitAuthGateAnchorMac37), false);
295
+ assert.equal(patched.includes(agentClientRunLocalModeAnchorMac37), false);
296
+ assert.equal(
297
+ patched.includes(
298
+ 'if(!h()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(a6,"general");return}',
299
+ ),
300
+ true,
301
+ );
302
+ assert.equal(
303
+ patched.includes('if(((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
304
+ true,
305
+ );
306
+ assert.equal(patched.includes('||wv.localMode'), true);
307
+ assert.equal(patched.includes('return this.runLocalAgentInExtensionHost(n,e,t,i,r,o,c,d,h)'), true);
308
+ assert.equal(patched.includes('return this.client.run(n,e,t,i,r,s,o,a,c,d,h)'), true);
309
+ });
310
+
311
+ test('workbench auth gate patch supports Cursor 3.4 macOS workbench anchors', () => {
312
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixtureMac34());
313
+
314
+ assert.equal(containsCursorWorkbenchAuthGateMarker(patched), true);
315
+ assert.equal(patched.includes(composerSendButtonAuthGateAnchorMac34), false);
316
+ assert.equal(patched.includes(composerSubmitAuthGateAnchorMac34), false);
317
+ assert.equal(patched.includes(agentClientRunLocalModeAnchorMac34), false);
318
+ assert.equal(
319
+ patched.includes(
320
+ 'if(!t()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login();return}',
321
+ ),
322
+ true,
323
+ );
324
+ assert.equal(
325
+ patched.includes('if(((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
326
+ true,
327
+ );
328
+ assert.equal(patched.includes('||U0.localMode'), true);
329
+ assert.equal(patched.includes('return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,u,d,f)'), true);
330
+ assert.equal(patched.includes('return this.client.run(e,t,i,r,s,o,a,l,u,d,f)'), true);
331
+ });
332
+
210
333
  test('workbench auth gate patch reads the local service port from runtime json', () => {
211
334
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
212
335
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
@@ -284,6 +407,10 @@ test('workbench platform-mode guard self-bootstraps from the real session file s
284
407
  platformMode: 'active',
285
408
  activeProductId: 'prod_basic',
286
409
  platformModeStartedAt: '2026-06-04T03:10:06.880Z',
410
+ routeToken: {
411
+ token: 'rt_secret_value',
412
+ expiresAt: '2999-06-04T03:25:06.880Z',
413
+ },
287
414
  };
288
415
  const fakeRequire = (moduleName: string) => {
289
416
  if (moduleName === 'node:fs') {
@@ -483,7 +610,15 @@ test('workbench platform-mode runtime guard stores fetched active state and relo
483
610
  },
484
611
  fetch: async (url: string) => {
485
612
  fetchedUrl = url;
486
- return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
613
+ return {
614
+ ok: true,
615
+ json: async () => ({
616
+ mode: {
617
+ state: 'active',
618
+ route: { state: 'ready', expiresAt: '2999-06-01T00:10:00.000Z' },
619
+ },
620
+ }),
621
+ };
487
622
  },
488
623
  setInterval(callback: () => unknown) {
489
624
  timers.push(callback);
@@ -533,6 +668,54 @@ test('workbench platform-mode runtime guard stores fetched active state and relo
533
668
  assert.equal(reloads, 1);
534
669
  });
535
670
 
671
+ test('workbench platform-mode runtime guard does not accept active mode with expired route', async () => {
672
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
673
+ const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
674
+ const objectStart = patched.lastIndexOf('get when()', markerStart);
675
+ const objectEnd = patched.indexOf('get fallback()', markerStart) + 'get fallback(){return he(DGC,{})}'.length;
676
+ const objectLiteral = patched.slice(objectStart, objectEnd);
677
+ const values = new Map([['cursorPoolPlatformModeActive', '0']]);
678
+ const sandboxGlobal = {
679
+ localStorage: {
680
+ getItem(key: string) {
681
+ return values.get(key) ?? null;
682
+ },
683
+ setItem(key: string, value: string) {
684
+ values.set(key, value);
685
+ },
686
+ },
687
+ fetch: async () => ({
688
+ ok: true,
689
+ json: async () => ({
690
+ mode: {
691
+ state: 'active',
692
+ route: { state: 'expired', expiresAt: '2026-06-01T00:10:00.000Z' },
693
+ },
694
+ }),
695
+ }),
696
+ setInterval() {
697
+ return 1;
698
+ },
699
+ setTimeout(callback: () => unknown) {
700
+ callback();
701
+ return 1;
702
+ },
703
+ location: {
704
+ reload() {},
705
+ },
706
+ } as { __cursorPoolIsPlatformModeActive?: () => boolean };
707
+
708
+ new Script(`(({he,DGC,globalThis})=>({${objectLiteral}}))`).runInNewContext({
709
+ he: () => undefined,
710
+ DGC: {},
711
+ globalThis: sandboxGlobal,
712
+ })({ he: () => undefined, DGC: {}, globalThis: sandboxGlobal });
713
+ await new Promise((resolve) => setTimeout(resolve, 0));
714
+
715
+ assert.equal(values.get('cursorPoolPlatformModeActive'), '0');
716
+ assert.equal(sandboxGlobal.__cursorPoolIsPlatformModeActive?.(), false);
717
+ });
718
+
536
719
  test('workbench platform-mode runtime guard falls back to the default local port without node require', async () => {
537
720
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
538
721
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
@@ -553,7 +736,15 @@ test('workbench platform-mode runtime guard falls back to the default local port
553
736
  },
554
737
  fetch: async (url: string) => {
555
738
  fetchedUrl = url;
556
- return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
739
+ return {
740
+ ok: true,
741
+ json: async () => ({
742
+ mode: {
743
+ state: 'active',
744
+ route: { state: 'ready', expiresAt: '2999-06-01T00:10:00.000Z' },
745
+ },
746
+ }),
747
+ };
557
748
  },
558
749
  setInterval() {
559
750
  return 1;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor-pool/service",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "exports": {
@@ -9,7 +9,7 @@
9
9
  "./platformSession": "./src/platformSession.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@cursor-pool/shared": "0.5.6"
12
+ "@cursor-pool/shared": "0.5.8"
13
13
  },
14
14
  "scripts": {
15
15
  "test": "tsx --test test/*.test.ts"
@@ -61,7 +61,7 @@ export type PlatformModeReleaseReason =
61
61
 
62
62
  export type PlatformModeSnapshot =
63
63
  | { state: 'inactive'; releaseReason?: PlatformModeReleaseReason; releasedAt?: string }
64
- | { state: 'active'; productId: string; startedAt: string };
64
+ | { state: 'active'; productId: string; startedAt: string; route?: SafeRouteState };
65
65
 
66
66
  export type PlatformModeResult =
67
67
  | PlatformModeSnapshot
@@ -346,7 +346,7 @@ function asStatus(session: PlatformSession): PlatformStatus {
346
346
  state: 'logged-in',
347
347
  user: session.user,
348
348
  device: session.device,
349
- mode: platformModeFromSession(session),
349
+ mode: statusModeFromSession(session),
350
350
  };
351
351
  }
352
352
 
@@ -391,6 +391,29 @@ function platformModeFromSession(session: PlatformSession | null): PlatformModeS
391
391
  return inactiveModeFromSession(session);
392
392
  }
393
393
 
394
+ function routeStateFromSession(session: PlatformSession | null): SafeRouteState {
395
+ const routeToken = session?.routeToken;
396
+ if (!routeToken) {
397
+ return { state: 'missing' };
398
+ }
399
+
400
+ const expiresAt = Date.parse(routeToken.expiresAt);
401
+ if (Number.isNaN(expiresAt)) {
402
+ return { state: 'missing' };
403
+ }
404
+
405
+ if (expiresAt <= Date.now()) {
406
+ return { state: 'expired', expiresAt: routeToken.expiresAt };
407
+ }
408
+
409
+ return { state: 'ready', expiresAt: routeToken.expiresAt };
410
+ }
411
+
412
+ function statusModeFromSession(session: PlatformSession | null): PlatformModeSnapshot {
413
+ const mode = platformModeFromSession(session);
414
+ return mode.state === 'active' ? { ...mode, route: routeStateFromSession(session) } : mode;
415
+ }
416
+
394
417
  function clearPlatformMode(session: PlatformSession): PlatformSession {
395
418
  const {
396
419
  platformMode: _platformMode,
@@ -814,11 +837,11 @@ async function statusFromRequestError(
814
837
  const currentSession = await readPlatformSession(options) ?? session;
815
838
  const { mode } = options.releaseActiveModeOnUnauthorized
816
839
  ? await releaseActivePlatformMode(currentSession, 'invalid-token', options)
817
- : { mode: platformModeFromSession(currentSession) };
840
+ : { mode: statusModeFromSession(currentSession) };
818
841
  return { state: 'invalid-token', user: currentSession.user, device: currentSession.device, mode };
819
842
  }
820
843
 
821
- return { state: 'offline', user: session.user, device: session.device, mode: platformModeFromSession(session) };
844
+ return { state: 'offline', user: session.user, device: session.device, mode: statusModeFromSession(session) };
822
845
  }
823
846
 
824
847
  export async function loginWithCode(options: LoginWithCodeOptions): Promise<PlatformStatus> {
@@ -886,7 +909,7 @@ export async function platformStatus(options: PlatformSessionOptions = {}): Prom
886
909
  state: 'logged-in',
887
910
  user: released.session.user,
888
911
  device: released.session.device,
889
- mode: released.mode,
912
+ mode: released.mode.state === 'active' ? statusModeFromSession(released.session) : released.mode,
890
913
  };
891
914
  }
892
915
 
@@ -952,7 +975,7 @@ export async function platformCatalog(options: PlatformSessionOptions = {}): Pro
952
975
  return {
953
976
  state: 'logged-in',
954
977
  account: { credits: account.value.credits },
955
- mode,
978
+ mode: mode.state === 'active' ? statusModeFromSession(updatedSession) : mode,
956
979
  ...(selectedProductId ? { selectedProductId } : {}),
957
980
  products: catalogProducts,
958
981
  };
@@ -1159,7 +1182,7 @@ export async function sendHeartbeat(options: SendHeartbeatOptions = {}): Promise
1159
1182
  state: 'logged-in',
1160
1183
  user: released.session.user,
1161
1184
  device: released.session.device,
1162
- mode: released.mode,
1185
+ mode: released.mode.state === 'active' ? statusModeFromSession(released.session) : released.mode,
1163
1186
  };
1164
1187
  }
1165
1188
 
@@ -50,6 +50,7 @@ const LOOPBACK_HOST = '127.0.0.1' as const;
50
50
  const DEFAULT_PORT = 56393;
51
51
  const TRUSTED_RENDERER_ORIGINS = new Set([
52
52
  'vscode-file://vscode-app',
53
+ 'null',
53
54
  ]);
54
55
 
55
56
  export type StartServerOptions = {
@@ -337,7 +337,7 @@ const poolSession = {
337
337
  status: 'active' as const,
338
338
  startedAt: '2026-05-31T00:00:00.000Z',
339
339
  expiresAt: '2026-05-31T01:00:00.000Z',
340
- routeTokenExpiresAt: '2026-05-31T00:10:00.000Z',
340
+ routeTokenExpiresAt: '2999-05-31T00:10:00.000Z',
341
341
  routeStrategy: 'platform-gateway' as const,
342
342
  bannedModels: [],
343
343
  capabilities: {
@@ -1654,6 +1654,7 @@ test('platform mode starts after selected available product and stops while pres
1654
1654
  state: 'active',
1655
1655
  productId: 'prod_basic',
1656
1656
  startedAt: started.startedAt,
1657
+ route: { state: 'ready', expiresAt: '2999-05-31T00:10:00.000Z' },
1657
1658
  });
1658
1659
 
1659
1660
  const stopped = await stopPlatformMode({ sessionFile });
@@ -1721,7 +1722,7 @@ test('startPlatformMode creates a pool session and stores route token', async ()
1721
1722
  assert.deepEqual(saved.poolSession, poolSession);
1722
1723
  assert.deepEqual(saved.routeToken, {
1723
1724
  token: 'rt_secret_value',
1724
- expiresAt: '2026-05-31T00:10:00.000Z',
1725
+ expiresAt: '2999-05-31T00:10:00.000Z',
1725
1726
  });
1726
1727
  } finally {
1727
1728
  await api.close();
@@ -1776,7 +1777,7 @@ test('startPlatformMode calls default pool session endpoint without body device
1776
1777
  assert.deepEqual(saved.poolSession, poolSession);
1777
1778
  assert.deepEqual(saved.routeToken, {
1778
1779
  token: 'rt_secret_value',
1779
- expiresAt: '2026-05-31T00:10:00.000Z',
1780
+ expiresAt: '2999-05-31T00:10:00.000Z',
1780
1781
  });
1781
1782
  } finally {
1782
1783
  await api.close();
@@ -1891,7 +1892,7 @@ test('startPlatformMode sanitizes pool session response before saving', async ()
1891
1892
  });
1892
1893
  assert.deepEqual(saved.routeToken, {
1893
1894
  token: 'rt_secret_value',
1894
- expiresAt: '2026-05-31T00:10:00.000Z',
1895
+ expiresAt: '2999-05-31T00:10:00.000Z',
1895
1896
  });
1896
1897
  assert.doesNotMatch(savedText, /discard-me|Bearer secret|rt_nested_secret|sk-secret-token|apiKey=secret/);
1897
1898
  } finally {