@cursorpool-dev/cli 0.5.8 → 0.5.10

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 (49) hide show
  1. package/node_modules/@cursor-pool/extension/dist/extension.js +46 -116
  2. package/node_modules/@cursor-pool/extension/package.json +3 -3
  3. package/node_modules/@cursor-pool/extension/src/api.ts +2 -17
  4. package/node_modules/@cursor-pool/extension/src/panel.ts +3 -26
  5. package/node_modules/@cursor-pool/extension/test/panel.test.ts +1 -34
  6. package/node_modules/@cursor-pool/patcher/package.json +2 -2
  7. package/node_modules/@cursor-pool/patcher/src/marker.ts +72 -7
  8. package/node_modules/@cursor-pool/patcher/src/workbenchAuthGateMarker.ts +102 -19
  9. package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +88 -13
  10. package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +162 -149
  11. package/node_modules/@cursor-pool/service/package.json +2 -2
  12. package/node_modules/@cursor-pool/service/src/platformSession.ts +7 -30
  13. package/node_modules/@cursor-pool/service/src/server.ts +1 -1
  14. package/node_modules/@cursor-pool/service/test/platformSession.test.ts +4 -5
  15. package/node_modules/@cursor-pool/service/test/server.test.ts +1 -130
  16. package/node_modules/@cursor-pool/shared/package.json +1 -1
  17. package/node_modules/@cursor-pool/shared/src/manifest.ts +0 -35
  18. package/node_modules/@cursor-pool/shared/test/manifest.test.ts +9 -43
  19. package/package.json +5 -7
  20. package/src/compat.ts +201 -194
  21. package/src/cursor.ts +45 -4
  22. package/src/extensionBundle.ts +1 -1
  23. package/src/extensionLink.ts +8 -29
  24. package/src/install.ts +10 -62
  25. package/src/installRecord.ts +0 -2
  26. package/src/patchSet.ts +49 -13
  27. package/src/platform.ts +3 -3
  28. package/src/repair.ts +9 -13
  29. package/src/restore.ts +11 -12
  30. package/src/status.ts +5 -9
  31. package/src/target.ts +12 -0
  32. package/src/trial.ts +2 -3
  33. package/src/uninstall.ts +6 -2
  34. package/test/compat.test.ts +146 -192
  35. package/test/cursor.test.ts +54 -0
  36. package/test/e2e-install.test.ts +29 -46
  37. package/test/extensionLink.test.ts +26 -49
  38. package/test/install.test.ts +4 -64
  39. package/test/patchSet.test.ts +71 -0
  40. package/test/repair.test.ts +131 -1
  41. package/test/restore.test.ts +59 -3
  42. package/test/status.test.ts +0 -1
  43. package/test/target.test.ts +28 -0
  44. package/test/trial.test.ts +15 -1
  45. package/node_modules/@cursor-pool/takeover-plans/package.json +0 -12
  46. package/node_modules/@cursor-pool/takeover-plans/src/index.ts +0 -22
  47. package/node_modules/@cursor-pool/takeover-plans/src/plans.ts +0 -37
  48. package/node_modules/@cursor-pool/takeover-plans/src/types.ts +0 -9
  49. package/node_modules/@cursor-pool/takeover-plans/test/registry.test.ts +0 -23
@@ -9,6 +9,7 @@ import {
9
9
  CURSOR_POOL_WORKBENCH_AUTH_GATE_MARKER,
10
10
  CURSOR_POOL_WORKBENCH_AUTH_GATE_SIGNATURE,
11
11
  CURSOR_POOL_WORKBENCH_AGENT_LOOP_SIGNATURE,
12
+ CURSOR_POOL_WORKBENCH_AGENT_EDITOR_CURSOR_AI_LOGIN_SIGNATURE,
12
13
  CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE,
13
14
  CURSOR_POOL_WORKBENCH_SUBMIT_GATE_SIGNATURE,
14
15
  containsCursorWorkbenchAuthGateMarker,
@@ -30,28 +31,40 @@ const agentEditorSendButtonAuthGateAnchor =
30
31
  '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';
31
32
  const agentEditorSendButtonLoginAnchor =
32
33
  'if(!t()){e.cursorAuthenticationService.login();return}';
33
- const agentLoopRunAnchor = 'await this.agentClientService.run(te,H,$e,Ne,Ce,T,ze,me,we,[],ct)';
34
- const buildFlagsLocalModeAnchor = 'localMode:!1';
35
- const localProviderConfigAnchor =
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
- const agentClientRunLocalModeAnchor =
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)';
34
+ const agentEditorCursorAiLoginButtonAnchorLinux36 =
35
+ 'return ie(lo,{get keybinding(){return e()},onClick:()=>{n.cursorAuthenticationService.login()},hintText:"Log in to use Cursor AI features",variant:"secondary",style:{"margin-left":"auto"},children:"Log in"})';
36
+ const agentEditorBottomBarAuthGateAnchorLinux36 =
37
+ 'get when(){return h()&&!Xk1},get fallback(){return ie(X_1,{})},get children(){return ie(i01,';
38
+ const agentEditorBottomBarAuthGateAnchorMac37 =
39
+ 'get when(){return h()&&!rYT},get fallback(){return ie(CzT,{})},get children(){return ie(AVT,';
40
+ const agentEditorBottomBarAuthGateAnchorMac34 =
41
+ 'get when(){return v()&&!HG1},get fallback(){return re(s71,{})},get children(){return re(u$1,';
39
42
  const composerSendButtonAuthGateAnchorMac37 =
40
43
  '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
44
  const composerSubmitAuthGateAnchorMac37 =
42
45
  '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
46
  const composerSendButtonAuthGateAnchorMac34 =
48
47
  '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
48
  const composerSubmitAuthGateAnchorMac34 =
50
49
  'if(!t()){e.cursorAuthenticationService.login();return}';
50
+ const mainSubmitAuthGateAnchorMac34 =
51
+ 'if(!v()){e.cursorAuthenticationService.login(),e.commandService.executeCommand($6,"general");return}';
52
+ const localProviderConfigAnchorMac37 =
53
+ '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"}';
51
54
  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"}';
55
+ '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:"http://example.invalid",apiKey:a}}createDefaultLocalModel(e){return "default"}';
56
+ const agentClientRunLocalModeAnchorMac37 =
57
+ '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)';
53
58
  const agentClientRunLocalModeAnchorMac34 =
54
59
  '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)';
60
+ const loggedOutGlassRootAnchorMac37 =
61
+ 'Te=M?$(ETI,{alertDialogStackSize:H,isWindowFullScreen:V,renderRootErrorFallback:ne,useOpaqueSplashBackground:J,workspace:r,workspaceCollectionService:s}):$(swI,{workspace:r})';
62
+ const agentLoopRunAnchor = 'await this.agentClientService.run(te,H,$e,Ne,Ce,T,ze,me,we,[],ct)';
63
+ const buildFlagsLocalModeAnchor = 'localMode:!1';
64
+ const localProviderConfigAnchor =
65
+ '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"}';
66
+ const agentClientRunLocalModeAnchor =
67
+ '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)';
55
68
 
56
69
  function workbenchFixture(extra = '') {
57
70
  return [
@@ -66,24 +79,29 @@ function workbenchFixture(extra = '') {
66
79
  ].join(';');
67
80
  }
68
81
 
69
- function workbenchFixtureMac37() {
82
+ function workbenchFixtureMac37(extra = '') {
70
83
  return [
71
84
  `function composer(){return ge(Mt,{${composerSendButtonAuthGateAnchorMac37}"controls"}})}`,
72
85
  `async function submit(){${composerSubmitAuthGateAnchorMac37};return "submitted";}`,
73
- `function agentEditorControls(){const E=()=>{${agentEditorSendButtonLoginAnchor};return n.handleSubmit()};return "controls"}`,
86
+ `function bottomBar(){return ie(ct,{${agentEditorBottomBarAuthGateAnchorMac37}{})}}`,
87
+ `function root(){let Te;${loggedOutGlassRootAnchorMac37};return Te}`,
74
88
  `const flags={${buildFlagsLocalModeAnchor}}`,
75
89
  localProviderConfigAnchorMac37,
76
90
  `async function agentClientRun(){const h={...m,isRunningInTest:m.isRunningInTest??this.environmentService.enableSmokeTestDriver===!0,clientSupportsInlineImages:!0};${agentClientRunLocalModeAnchorMac37}}`,
91
+ extra,
77
92
  ].join(';');
78
93
  }
79
94
 
80
- function workbenchFixtureMac34() {
95
+ function workbenchFixtureMac34(extra = '') {
81
96
  return [
82
- `function composer(){const E=()=>{${composerSubmitAuthGateAnchorMac34};return n.handleSubmit()};return ke(Mt,{${composerSendButtonAuthGateAnchorMac34}"controls"}})}`,
83
- `function agentEditorControls(){return "controls"}`,
97
+ `function composer(){return ke(I,re(Ct,{${composerSendButtonAuthGateAnchorMac34}"controls"}})}`,
98
+ `async function submit(){${composerSubmitAuthGateAnchorMac34};return "submitted";}`,
99
+ `async function mainSubmit(){${mainSubmitAuthGateAnchorMac34};return "main-submitted";}`,
100
+ `function bottomBar(){return re(Ct,{${agentEditorBottomBarAuthGateAnchorMac34}{})}}`,
84
101
  `const flags={${buildFlagsLocalModeAnchor}}`,
85
102
  localProviderConfigAnchorMac34,
86
103
  `async function agentClientRun(){const f={...h,isRunningInTest:h.isRunningInTest??this.environmentService.enableSmokeTestDriver===!0,clientSupportsInlineImages:!0};${agentClientRunLocalModeAnchorMac34}}`,
104
+ extra,
87
105
  ].join(';');
88
106
  }
89
107
 
@@ -147,6 +165,110 @@ test('workbench auth gate patch lets the Agent Editor send controls render in pl
147
165
  );
148
166
  });
149
167
 
168
+ test('workbench auth gate patch lets the Cursor 3.6 Agent Editor login button render controls in platform mode', () => {
169
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture(
170
+ `function X_1(){const n=Jr(),e=De(()=>" \\u23CE");${agentEditorCursorAiLoginButtonAnchorLinux36}}function bottomBar(){return ie(ct,{${agentEditorBottomBarAuthGateAnchorLinux36}{})}}`,
171
+ ));
172
+
173
+ assert.equal(patched.includes(agentEditorBottomBarAuthGateAnchorLinux36), false);
174
+ assert.equal(patched.includes(CURSOR_POOL_WORKBENCH_AGENT_EDITOR_CURSOR_AI_LOGIN_SIGNATURE), true);
175
+ assert.equal(
176
+ patched.includes(
177
+ 'get when(){return (h()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{',
178
+ ),
179
+ true,
180
+ );
181
+ assert.equal(
182
+ patched.includes(
183
+ ')&&!Xk1},get fallback(){return ie(X_1,{})},get children(){return ie(i01,',
184
+ ),
185
+ true,
186
+ );
187
+ });
188
+
189
+ test('workbench auth gate patch supports Cursor 3.7 macOS composer and local agent anchors', () => {
190
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixtureMac37());
191
+
192
+ assert.equal(containsCursorWorkbenchAuthGateMarker(patched), true);
193
+ assert.equal(patched.includes(composerSendButtonAuthGateAnchorMac37), false);
194
+ assert.equal(patched.includes(composerSubmitAuthGateAnchorMac37), false);
195
+ assert.equal(patched.includes(agentEditorBottomBarAuthGateAnchorMac37), false);
196
+ assert.equal(patched.includes(loggedOutGlassRootAnchorMac37), false);
197
+ assert.equal(patched.includes(localProviderConfigAnchorMac37), false);
198
+ assert.equal(patched.includes(agentClientRunLocalModeAnchorMac37), false);
199
+ assert.equal(
200
+ patched.includes('get when(){return t()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
201
+ true,
202
+ );
203
+ assert.equal(
204
+ patched.includes(
205
+ 'if(!h()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(a6,"general");return}',
206
+ ),
207
+ true,
208
+ );
209
+ assert.equal(
210
+ patched.includes('get when(){return (h()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
211
+ true,
212
+ );
213
+ assert.equal(
214
+ patched.includes(
215
+ ')&&!rYT},get fallback(){return ie(CzT,{})},get children(){return ie(AVT,',
216
+ ),
217
+ true,
218
+ );
219
+ assert.equal(
220
+ patched.includes(
221
+ 'Te=M||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{',
222
+ ),
223
+ true,
224
+ );
225
+ assert.equal(patched.includes(':$(swI,{workspace:r})'), true);
226
+ assert.equal(patched.includes('||wv.localMode)'), true);
227
+ assert.equal(patched.includes('return this.runLocalAgentInExtensionHost(n,e,t,i,r,o,c,d,h)'), true);
228
+ assert.equal(patched.includes('return this.client.run(n,e,t,i,r,s,o,a,c,d,h)'), true);
229
+ });
230
+
231
+ test('workbench auth gate patch supports Cursor 3.4 macOS composer and local agent anchors', () => {
232
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixtureMac34());
233
+
234
+ assert.equal(containsCursorWorkbenchAuthGateMarker(patched), true);
235
+ assert.equal(patched.includes(composerSendButtonAuthGateAnchorMac34), false);
236
+ assert.equal(patched.includes(composerSubmitAuthGateAnchorMac34), false);
237
+ assert.equal(patched.includes(mainSubmitAuthGateAnchorMac34), false);
238
+ assert.equal(patched.includes(agentEditorBottomBarAuthGateAnchorMac34), false);
239
+ assert.equal(patched.includes(localProviderConfigAnchorMac34), false);
240
+ assert.equal(patched.includes(agentClientRunLocalModeAnchorMac34), false);
241
+ assert.equal(
242
+ patched.includes('get when(){return t()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
243
+ true,
244
+ );
245
+ assert.equal(
246
+ patched.includes(
247
+ 'if(!t()&&!((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{',
248
+ ),
249
+ true,
250
+ );
251
+ assert.equal(
252
+ patched.includes(
253
+ 'if(!v()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand($6,"general");return}',
254
+ ),
255
+ true,
256
+ );
257
+ assert.equal(
258
+ patched.includes('get when(){return (v()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
259
+ true,
260
+ );
261
+ assert.equal(
262
+ patched.includes(
263
+ ')&&!HG1},get fallback(){return re(s71,{})},get children(){return re(u$1,',
264
+ ),
265
+ true,
266
+ );
267
+ assert.equal(patched.includes('||U0.localMode)'), true);
268
+ assert.equal(patched.includes('return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,u,d,f)'), true);
269
+ assert.equal(patched.includes('return this.client.run(e,t,i,r,s,o,a,l,u,d,f)'), true);
270
+ });
271
+
150
272
  test('workbench auth gate patch treats old V6 markers as legacy and reapplies Agent Editor gates', () => {
151
273
  const oldV6Patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture()).replaceAll(
152
274
  'CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V9_ALWAYS_NATIVE_LOCAL',
@@ -210,48 +332,6 @@ test('patchCursorWorkbenchAuthGate upgrades old V9 always-active guard from clea
210
332
  }
211
333
  });
212
334
 
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
-
255
335
  test('workbench auth gate patch keeps the native agent loop instead of appending fake AI bubbles', () => {
256
336
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
257
337
 
@@ -286,50 +366,6 @@ test('workbench auth gate patch delegates agent turns to the local service only
286
366
  assert.equal(patched.includes('return this.client.run(e,t,i,r,s,o,a,u,d,h,g)'), true);
287
367
  });
288
368
 
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
-
333
369
  test('workbench auth gate patch reads the local service port from runtime json', () => {
334
370
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
335
371
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
@@ -407,10 +443,6 @@ test('workbench platform-mode guard self-bootstraps from the real session file s
407
443
  platformMode: 'active',
408
444
  activeProductId: 'prod_basic',
409
445
  platformModeStartedAt: '2026-06-04T03:10:06.880Z',
410
- routeToken: {
411
- token: 'rt_secret_value',
412
- expiresAt: '2999-06-04T03:25:06.880Z',
413
- },
414
446
  };
415
447
  const fakeRequire = (moduleName: string) => {
416
448
  if (moduleName === 'node:fs') {
@@ -610,15 +642,7 @@ test('workbench platform-mode runtime guard stores fetched active state and relo
610
642
  },
611
643
  fetch: async (url: string) => {
612
644
  fetchedUrl = url;
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
- };
645
+ return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
622
646
  },
623
647
  setInterval(callback: () => unknown) {
624
648
  timers.push(callback);
@@ -668,13 +692,15 @@ test('workbench platform-mode runtime guard stores fetched active state and relo
668
692
  assert.equal(reloads, 1);
669
693
  });
670
694
 
671
- test('workbench platform-mode runtime guard does not accept active mode with expired route', async () => {
695
+ test('workbench platform-mode runtime guard falls back to the default local port without node require', async () => {
672
696
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
673
697
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
674
698
  const objectStart = patched.lastIndexOf('get when()', markerStart);
675
699
  const objectEnd = patched.indexOf('get fallback()', markerStart) + 'get fallback(){return he(DGC,{})}'.length;
676
700
  const objectLiteral = patched.slice(objectStart, objectEnd);
677
701
  const values = new Map([['cursorPoolPlatformModeActive', '0']]);
702
+ let fetchedUrl = '';
703
+ let reloads = 0;
678
704
  const sandboxGlobal = {
679
705
  localStorage: {
680
706
  getItem(key: string) {
@@ -684,15 +710,10 @@ test('workbench platform-mode runtime guard does not accept active mode with exp
684
710
  values.set(key, value);
685
711
  },
686
712
  },
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
- }),
713
+ fetch: async (url: string) => {
714
+ fetchedUrl = url;
715
+ return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
716
+ },
696
717
  setInterval() {
697
718
  return 1;
698
719
  },
@@ -701,7 +722,9 @@ test('workbench platform-mode runtime guard does not accept active mode with exp
701
722
  return 1;
702
723
  },
703
724
  location: {
704
- reload() {},
725
+ reload() {
726
+ reloads += 1;
727
+ },
705
728
  },
706
729
  } as { __cursorPoolIsPlatformModeActive?: () => boolean };
707
730
 
@@ -712,11 +735,13 @@ test('workbench platform-mode runtime guard does not accept active mode with exp
712
735
  })({ he: () => undefined, DGC: {}, globalThis: sandboxGlobal });
713
736
  await new Promise((resolve) => setTimeout(resolve, 0));
714
737
 
715
- assert.equal(values.get('cursorPoolPlatformModeActive'), '0');
716
- assert.equal(sandboxGlobal.__cursorPoolIsPlatformModeActive?.(), false);
738
+ assert.equal(fetchedUrl, 'http://127.0.0.1:56393/platform/status');
739
+ assert.equal(values.get('cursorPoolPlatformModeActive'), '1');
740
+ assert.equal(sandboxGlobal.__cursorPoolIsPlatformModeActive?.(), true);
741
+ assert.equal(reloads, 1);
717
742
  });
718
743
 
719
- test('workbench platform-mode runtime guard falls back to the default local port without node require', async () => {
744
+ test('workbench platform-mode runtime guard reads explicit runtime base URL without node require', async () => {
720
745
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
721
746
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
722
747
  const objectStart = patched.lastIndexOf('get when()', markerStart);
@@ -724,7 +749,6 @@ test('workbench platform-mode runtime guard falls back to the default local port
724
749
  const objectLiteral = patched.slice(objectStart, objectEnd);
725
750
  const values = new Map([['cursorPoolPlatformModeActive', '0']]);
726
751
  let fetchedUrl = '';
727
- let reloads = 0;
728
752
  const sandboxGlobal = {
729
753
  localStorage: {
730
754
  getItem(key: string) {
@@ -736,15 +760,7 @@ test('workbench platform-mode runtime guard falls back to the default local port
736
760
  },
737
761
  fetch: async (url: string) => {
738
762
  fetchedUrl = url;
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
- };
763
+ return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
748
764
  },
749
765
  setInterval() {
750
766
  return 1;
@@ -754,23 +770,20 @@ test('workbench platform-mode runtime guard falls back to the default local port
754
770
  return 1;
755
771
  },
756
772
  location: {
757
- reload() {
758
- reloads += 1;
759
- },
773
+ reload() {},
760
774
  },
761
- } as { __cursorPoolIsPlatformModeActive?: () => boolean };
775
+ } as { __cursorPoolRuntimeBaseUrl?: () => string | null };
762
776
 
763
- new Script(`(({he,DGC,globalThis})=>({${objectLiteral}}))`).runInNewContext({
777
+ new Script(`(({he,DGC,globalThis,process})=>({${objectLiteral}}))`).runInNewContext({
764
778
  he: () => undefined,
765
779
  DGC: {},
766
780
  globalThis: sandboxGlobal,
767
- })({ he: () => undefined, DGC: {}, globalThis: sandboxGlobal });
781
+ process: { env: { CURSOR_POOL_RUNTIME_BASE_URL: 'http://127.0.0.1:61373' } },
782
+ })({ he: () => undefined, DGC: {}, globalThis: sandboxGlobal, process: { env: { CURSOR_POOL_RUNTIME_BASE_URL: 'http://127.0.0.1:61373' } } });
768
783
  await new Promise((resolve) => setTimeout(resolve, 0));
769
784
 
770
- assert.equal(fetchedUrl, 'http://127.0.0.1:56393/platform/status');
771
- assert.equal(values.get('cursorPoolPlatformModeActive'), '1');
772
- assert.equal(sandboxGlobal.__cursorPoolIsPlatformModeActive?.(), true);
773
- assert.equal(reloads, 1);
785
+ assert.equal(sandboxGlobal.__cursorPoolRuntimeBaseUrl?.(), 'http://127.0.0.1:61373');
786
+ assert.equal(fetchedUrl, 'http://127.0.0.1:61373/platform/status');
774
787
  });
775
788
 
776
789
  test('workbench platform-mode runtime guard is renderer-safe without node require', () => {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor-pool/service",
3
- "version": "0.5.8",
3
+ "version": "0.5.10",
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.8"
12
+ "@cursor-pool/shared": "0.5.10"
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; route?: SafeRouteState };
64
+ | { state: 'active'; productId: string; startedAt: string };
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: statusModeFromSession(session),
349
+ mode: platformModeFromSession(session),
350
350
  };
351
351
  }
352
352
 
@@ -391,29 +391,6 @@ 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
-
417
394
  function clearPlatformMode(session: PlatformSession): PlatformSession {
418
395
  const {
419
396
  platformMode: _platformMode,
@@ -837,11 +814,11 @@ async function statusFromRequestError(
837
814
  const currentSession = await readPlatformSession(options) ?? session;
838
815
  const { mode } = options.releaseActiveModeOnUnauthorized
839
816
  ? await releaseActivePlatformMode(currentSession, 'invalid-token', options)
840
- : { mode: statusModeFromSession(currentSession) };
817
+ : { mode: platformModeFromSession(currentSession) };
841
818
  return { state: 'invalid-token', user: currentSession.user, device: currentSession.device, mode };
842
819
  }
843
820
 
844
- return { state: 'offline', user: session.user, device: session.device, mode: statusModeFromSession(session) };
821
+ return { state: 'offline', user: session.user, device: session.device, mode: platformModeFromSession(session) };
845
822
  }
846
823
 
847
824
  export async function loginWithCode(options: LoginWithCodeOptions): Promise<PlatformStatus> {
@@ -909,7 +886,7 @@ export async function platformStatus(options: PlatformSessionOptions = {}): Prom
909
886
  state: 'logged-in',
910
887
  user: released.session.user,
911
888
  device: released.session.device,
912
- mode: released.mode.state === 'active' ? statusModeFromSession(released.session) : released.mode,
889
+ mode: released.mode,
913
890
  };
914
891
  }
915
892
 
@@ -975,7 +952,7 @@ export async function platformCatalog(options: PlatformSessionOptions = {}): Pro
975
952
  return {
976
953
  state: 'logged-in',
977
954
  account: { credits: account.value.credits },
978
- mode: mode.state === 'active' ? statusModeFromSession(updatedSession) : mode,
955
+ mode,
979
956
  ...(selectedProductId ? { selectedProductId } : {}),
980
957
  products: catalogProducts,
981
958
  };
@@ -1182,7 +1159,7 @@ export async function sendHeartbeat(options: SendHeartbeatOptions = {}): Promise
1182
1159
  state: 'logged-in',
1183
1160
  user: released.session.user,
1184
1161
  device: released.session.device,
1185
- mode: released.mode.state === 'active' ? statusModeFromSession(released.session) : released.mode,
1162
+ mode: released.mode,
1186
1163
  };
1187
1164
  }
1188
1165
 
@@ -50,7 +50,6 @@ 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',
54
53
  ]);
55
54
 
56
55
  export type StartServerOptions = {
@@ -155,6 +154,7 @@ function applyCorsHeaders(request: IncomingMessage, response: ServerResponse) {
155
154
  response.setHeader('access-control-allow-origin', origin);
156
155
  response.setHeader('access-control-allow-methods', 'GET,POST,OPTIONS');
157
156
  response.setHeader('access-control-allow-headers', 'content-type,authorization');
157
+ response.setHeader('access-control-allow-private-network', 'true');
158
158
  return true;
159
159
  }
160
160
 
@@ -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: '2999-05-31T00:10:00.000Z',
340
+ routeTokenExpiresAt: '2026-05-31T00:10:00.000Z',
341
341
  routeStrategy: 'platform-gateway' as const,
342
342
  bannedModels: [],
343
343
  capabilities: {
@@ -1654,7 +1654,6 @@ 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' },
1658
1657
  });
1659
1658
 
1660
1659
  const stopped = await stopPlatformMode({ sessionFile });
@@ -1722,7 +1721,7 @@ test('startPlatformMode creates a pool session and stores route token', async ()
1722
1721
  assert.deepEqual(saved.poolSession, poolSession);
1723
1722
  assert.deepEqual(saved.routeToken, {
1724
1723
  token: 'rt_secret_value',
1725
- expiresAt: '2999-05-31T00:10:00.000Z',
1724
+ expiresAt: '2026-05-31T00:10:00.000Z',
1726
1725
  });
1727
1726
  } finally {
1728
1727
  await api.close();
@@ -1777,7 +1776,7 @@ test('startPlatformMode calls default pool session endpoint without body device
1777
1776
  assert.deepEqual(saved.poolSession, poolSession);
1778
1777
  assert.deepEqual(saved.routeToken, {
1779
1778
  token: 'rt_secret_value',
1780
- expiresAt: '2999-05-31T00:10:00.000Z',
1779
+ expiresAt: '2026-05-31T00:10:00.000Z',
1781
1780
  });
1782
1781
  } finally {
1783
1782
  await api.close();
@@ -1892,7 +1891,7 @@ test('startPlatformMode sanitizes pool session response before saving', async ()
1892
1891
  });
1893
1892
  assert.deepEqual(saved.routeToken, {
1894
1893
  token: 'rt_secret_value',
1895
- expiresAt: '2999-05-31T00:10:00.000Z',
1894
+ expiresAt: '2026-05-31T00:10:00.000Z',
1896
1895
  });
1897
1896
  assert.doesNotMatch(savedText, /discard-me|Bearer secret|rt_nested_secret|sk-secret-token|apiKey=secret/);
1898
1897
  } finally {