@cursorpool-dev/cli 0.5.8 → 0.5.9

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 (42) 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 +80 -17
  9. package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +88 -13
  10. package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +151 -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 +124 -196
  21. package/src/extensionBundle.ts +1 -1
  22. package/src/extensionLink.ts +8 -29
  23. package/src/install.ts +9 -62
  24. package/src/installRecord.ts +0 -2
  25. package/src/patchSet.ts +6 -12
  26. package/src/platform.ts +3 -3
  27. package/src/repair.ts +2 -10
  28. package/src/restore.ts +4 -12
  29. package/src/status.ts +0 -6
  30. package/src/trial.ts +2 -3
  31. package/test/compat.test.ts +59 -195
  32. package/test/e2e-install.test.ts +0 -53
  33. package/test/extensionLink.test.ts +26 -49
  34. package/test/install.test.ts +4 -64
  35. package/test/repair.test.ts +0 -1
  36. package/test/status.test.ts +0 -1
  37. package/test/trial.test.ts +15 -1
  38. package/node_modules/@cursor-pool/takeover-plans/package.json +0 -12
  39. package/node_modules/@cursor-pool/takeover-plans/src/index.ts +0 -22
  40. package/node_modules/@cursor-pool/takeover-plans/src/plans.ts +0 -37
  41. package/node_modules/@cursor-pool/takeover-plans/src/types.ts +0 -9
  42. 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,38 @@ 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 agentLoopRunAnchor = 'await this.agentClientService.run(te,H,$e,Ne,Ce,T,ze,me,we,[],ct)';
61
+ const buildFlagsLocalModeAnchor = 'localMode:!1';
62
+ const localProviderConfigAnchor =
63
+ '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"}';
64
+ const agentClientRunLocalModeAnchor =
65
+ '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
66
 
56
67
  function workbenchFixture(extra = '') {
57
68
  return [
@@ -66,24 +77,28 @@ function workbenchFixture(extra = '') {
66
77
  ].join(';');
67
78
  }
68
79
 
69
- function workbenchFixtureMac37() {
80
+ function workbenchFixtureMac37(extra = '') {
70
81
  return [
71
82
  `function composer(){return ge(Mt,{${composerSendButtonAuthGateAnchorMac37}"controls"}})}`,
72
83
  `async function submit(){${composerSubmitAuthGateAnchorMac37};return "submitted";}`,
73
- `function agentEditorControls(){const E=()=>{${agentEditorSendButtonLoginAnchor};return n.handleSubmit()};return "controls"}`,
84
+ `function bottomBar(){return ie(ct,{${agentEditorBottomBarAuthGateAnchorMac37}{})}}`,
74
85
  `const flags={${buildFlagsLocalModeAnchor}}`,
75
86
  localProviderConfigAnchorMac37,
76
87
  `async function agentClientRun(){const h={...m,isRunningInTest:m.isRunningInTest??this.environmentService.enableSmokeTestDriver===!0,clientSupportsInlineImages:!0};${agentClientRunLocalModeAnchorMac37}}`,
88
+ extra,
77
89
  ].join(';');
78
90
  }
79
91
 
80
- function workbenchFixtureMac34() {
92
+ function workbenchFixtureMac34(extra = '') {
81
93
  return [
82
- `function composer(){const E=()=>{${composerSubmitAuthGateAnchorMac34};return n.handleSubmit()};return ke(Mt,{${composerSendButtonAuthGateAnchorMac34}"controls"}})}`,
83
- `function agentEditorControls(){return "controls"}`,
94
+ `function composer(){return ke(I,re(Ct,{${composerSendButtonAuthGateAnchorMac34}"controls"}})}`,
95
+ `async function submit(){${composerSubmitAuthGateAnchorMac34};return "submitted";}`,
96
+ `async function mainSubmit(){${mainSubmitAuthGateAnchorMac34};return "main-submitted";}`,
97
+ `function bottomBar(){return re(Ct,{${agentEditorBottomBarAuthGateAnchorMac34}{})}}`,
84
98
  `const flags={${buildFlagsLocalModeAnchor}}`,
85
99
  localProviderConfigAnchorMac34,
86
100
  `async function agentClientRun(){const f={...h,isRunningInTest:h.isRunningInTest??this.environmentService.enableSmokeTestDriver===!0,clientSupportsInlineImages:!0};${agentClientRunLocalModeAnchorMac34}}`,
101
+ extra,
87
102
  ].join(';');
88
103
  }
89
104
 
@@ -147,6 +162,102 @@ test('workbench auth gate patch lets the Agent Editor send controls render in pl
147
162
  );
148
163
  });
149
164
 
165
+ test('workbench auth gate patch lets the Cursor 3.6 Agent Editor login button render controls in platform mode', () => {
166
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture(
167
+ `function X_1(){const n=Jr(),e=De(()=>" \\u23CE");${agentEditorCursorAiLoginButtonAnchorLinux36}}function bottomBar(){return ie(ct,{${agentEditorBottomBarAuthGateAnchorLinux36}{})}}`,
168
+ ));
169
+
170
+ assert.equal(patched.includes(agentEditorBottomBarAuthGateAnchorLinux36), false);
171
+ assert.equal(patched.includes(CURSOR_POOL_WORKBENCH_AGENT_EDITOR_CURSOR_AI_LOGIN_SIGNATURE), true);
172
+ assert.equal(
173
+ patched.includes(
174
+ 'get when(){return (h()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{',
175
+ ),
176
+ true,
177
+ );
178
+ assert.equal(
179
+ patched.includes(
180
+ ')&&!Xk1},get fallback(){return ie(X_1,{})},get children(){return ie(i01,',
181
+ ),
182
+ true,
183
+ );
184
+ });
185
+
186
+ test('workbench auth gate patch supports Cursor 3.7 macOS composer and local agent anchors', () => {
187
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixtureMac37());
188
+
189
+ assert.equal(containsCursorWorkbenchAuthGateMarker(patched), true);
190
+ assert.equal(patched.includes(composerSendButtonAuthGateAnchorMac37), false);
191
+ assert.equal(patched.includes(composerSubmitAuthGateAnchorMac37), false);
192
+ assert.equal(patched.includes(agentEditorBottomBarAuthGateAnchorMac37), false);
193
+ assert.equal(patched.includes(localProviderConfigAnchorMac37), false);
194
+ assert.equal(patched.includes(agentClientRunLocalModeAnchorMac37), false);
195
+ assert.equal(
196
+ patched.includes('get when(){return t()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
197
+ true,
198
+ );
199
+ assert.equal(
200
+ patched.includes(
201
+ 'if(!h()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(a6,"general");return}',
202
+ ),
203
+ true,
204
+ );
205
+ assert.equal(
206
+ patched.includes('get when(){return (h()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
207
+ true,
208
+ );
209
+ assert.equal(
210
+ patched.includes(
211
+ ')&&!rYT},get fallback(){return ie(CzT,{})},get children(){return ie(AVT,',
212
+ ),
213
+ true,
214
+ );
215
+ assert.equal(patched.includes('||wv.localMode)'), true);
216
+ assert.equal(patched.includes('return this.runLocalAgentInExtensionHost(n,e,t,i,r,o,c,d,h)'), true);
217
+ assert.equal(patched.includes('return this.client.run(n,e,t,i,r,s,o,a,c,d,h)'), true);
218
+ });
219
+
220
+ test('workbench auth gate patch supports Cursor 3.4 macOS composer and local agent anchors', () => {
221
+ const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixtureMac34());
222
+
223
+ assert.equal(containsCursorWorkbenchAuthGateMarker(patched), true);
224
+ assert.equal(patched.includes(composerSendButtonAuthGateAnchorMac34), false);
225
+ assert.equal(patched.includes(composerSubmitAuthGateAnchorMac34), false);
226
+ assert.equal(patched.includes(mainSubmitAuthGateAnchorMac34), false);
227
+ assert.equal(patched.includes(agentEditorBottomBarAuthGateAnchorMac34), false);
228
+ assert.equal(patched.includes(localProviderConfigAnchorMac34), false);
229
+ assert.equal(patched.includes(agentClientRunLocalModeAnchorMac34), false);
230
+ assert.equal(
231
+ patched.includes('get when(){return t()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
232
+ true,
233
+ );
234
+ assert.equal(
235
+ patched.includes(
236
+ 'if(!t()&&!((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{',
237
+ ),
238
+ true,
239
+ );
240
+ assert.equal(
241
+ patched.includes(
242
+ 'if(!v()&&!globalThis.__cursorPoolIsPlatformModeActive?.()){e.cursorAuthenticationService.login(),e.commandService.executeCommand($6,"general");return}',
243
+ ),
244
+ true,
245
+ );
246
+ assert.equal(
247
+ patched.includes('get when(){return (v()||((globalThis.__cursorPoolEnsurePlatformModeGuard||(globalThis.__cursorPoolEnsurePlatformModeGuard=()=>{'),
248
+ true,
249
+ );
250
+ assert.equal(
251
+ patched.includes(
252
+ ')&&!HG1},get fallback(){return re(s71,{})},get children(){return re(u$1,',
253
+ ),
254
+ true,
255
+ );
256
+ assert.equal(patched.includes('||U0.localMode)'), true);
257
+ assert.equal(patched.includes('return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,u,d,f)'), true);
258
+ assert.equal(patched.includes('return this.client.run(e,t,i,r,s,o,a,l,u,d,f)'), true);
259
+ });
260
+
150
261
  test('workbench auth gate patch treats old V6 markers as legacy and reapplies Agent Editor gates', () => {
151
262
  const oldV6Patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture()).replaceAll(
152
263
  'CURSOR_POOL_MVP1_WORKBENCH_AUTH_GATE_PATCH_V9_ALWAYS_NATIVE_LOCAL',
@@ -210,48 +321,6 @@ test('patchCursorWorkbenchAuthGate upgrades old V9 always-active guard from clea
210
321
  }
211
322
  });
212
323
 
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
324
  test('workbench auth gate patch keeps the native agent loop instead of appending fake AI bubbles', () => {
256
325
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
257
326
 
@@ -286,50 +355,6 @@ test('workbench auth gate patch delegates agent turns to the local service only
286
355
  assert.equal(patched.includes('return this.client.run(e,t,i,r,s,o,a,u,d,h,g)'), true);
287
356
  });
288
357
 
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
358
  test('workbench auth gate patch reads the local service port from runtime json', () => {
334
359
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
335
360
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
@@ -407,10 +432,6 @@ test('workbench platform-mode guard self-bootstraps from the real session file s
407
432
  platformMode: 'active',
408
433
  activeProductId: 'prod_basic',
409
434
  platformModeStartedAt: '2026-06-04T03:10:06.880Z',
410
- routeToken: {
411
- token: 'rt_secret_value',
412
- expiresAt: '2999-06-04T03:25:06.880Z',
413
- },
414
435
  };
415
436
  const fakeRequire = (moduleName: string) => {
416
437
  if (moduleName === 'node:fs') {
@@ -610,15 +631,7 @@ test('workbench platform-mode runtime guard stores fetched active state and relo
610
631
  },
611
632
  fetch: async (url: string) => {
612
633
  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
- };
634
+ return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
622
635
  },
623
636
  setInterval(callback: () => unknown) {
624
637
  timers.push(callback);
@@ -668,13 +681,15 @@ test('workbench platform-mode runtime guard stores fetched active state and relo
668
681
  assert.equal(reloads, 1);
669
682
  });
670
683
 
671
- test('workbench platform-mode runtime guard does not accept active mode with expired route', async () => {
684
+ test('workbench platform-mode runtime guard falls back to the default local port without node require', async () => {
672
685
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
673
686
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
674
687
  const objectStart = patched.lastIndexOf('get when()', markerStart);
675
688
  const objectEnd = patched.indexOf('get fallback()', markerStart) + 'get fallback(){return he(DGC,{})}'.length;
676
689
  const objectLiteral = patched.slice(objectStart, objectEnd);
677
690
  const values = new Map([['cursorPoolPlatformModeActive', '0']]);
691
+ let fetchedUrl = '';
692
+ let reloads = 0;
678
693
  const sandboxGlobal = {
679
694
  localStorage: {
680
695
  getItem(key: string) {
@@ -684,15 +699,10 @@ test('workbench platform-mode runtime guard does not accept active mode with exp
684
699
  values.set(key, value);
685
700
  },
686
701
  },
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
- }),
702
+ fetch: async (url: string) => {
703
+ fetchedUrl = url;
704
+ return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
705
+ },
696
706
  setInterval() {
697
707
  return 1;
698
708
  },
@@ -701,7 +711,9 @@ test('workbench platform-mode runtime guard does not accept active mode with exp
701
711
  return 1;
702
712
  },
703
713
  location: {
704
- reload() {},
714
+ reload() {
715
+ reloads += 1;
716
+ },
705
717
  },
706
718
  } as { __cursorPoolIsPlatformModeActive?: () => boolean };
707
719
 
@@ -712,11 +724,13 @@ test('workbench platform-mode runtime guard does not accept active mode with exp
712
724
  })({ he: () => undefined, DGC: {}, globalThis: sandboxGlobal });
713
725
  await new Promise((resolve) => setTimeout(resolve, 0));
714
726
 
715
- assert.equal(values.get('cursorPoolPlatformModeActive'), '0');
716
- assert.equal(sandboxGlobal.__cursorPoolIsPlatformModeActive?.(), false);
727
+ assert.equal(fetchedUrl, 'http://127.0.0.1:56393/platform/status');
728
+ assert.equal(values.get('cursorPoolPlatformModeActive'), '1');
729
+ assert.equal(sandboxGlobal.__cursorPoolIsPlatformModeActive?.(), true);
730
+ assert.equal(reloads, 1);
717
731
  });
718
732
 
719
- test('workbench platform-mode runtime guard falls back to the default local port without node require', async () => {
733
+ test('workbench platform-mode runtime guard reads explicit runtime base URL without node require', async () => {
720
734
  const patched = injectCursorWorkbenchAuthGatePatch(workbenchFixture());
721
735
  const markerStart = patched.indexOf(CURSOR_POOL_WORKBENCH_NATIVE_LOCAL_AGENT_SIGNATURE);
722
736
  const objectStart = patched.lastIndexOf('get when()', markerStart);
@@ -724,7 +738,6 @@ test('workbench platform-mode runtime guard falls back to the default local port
724
738
  const objectLiteral = patched.slice(objectStart, objectEnd);
725
739
  const values = new Map([['cursorPoolPlatformModeActive', '0']]);
726
740
  let fetchedUrl = '';
727
- let reloads = 0;
728
741
  const sandboxGlobal = {
729
742
  localStorage: {
730
743
  getItem(key: string) {
@@ -736,15 +749,7 @@ test('workbench platform-mode runtime guard falls back to the default local port
736
749
  },
737
750
  fetch: async (url: string) => {
738
751
  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
- };
752
+ return { ok: true, json: async () => ({ mode: { state: 'active' } }) };
748
753
  },
749
754
  setInterval() {
750
755
  return 1;
@@ -754,23 +759,20 @@ test('workbench platform-mode runtime guard falls back to the default local port
754
759
  return 1;
755
760
  },
756
761
  location: {
757
- reload() {
758
- reloads += 1;
759
- },
762
+ reload() {},
760
763
  },
761
- } as { __cursorPoolIsPlatformModeActive?: () => boolean };
764
+ } as { __cursorPoolRuntimeBaseUrl?: () => string | null };
762
765
 
763
- new Script(`(({he,DGC,globalThis})=>({${objectLiteral}}))`).runInNewContext({
766
+ new Script(`(({he,DGC,globalThis,process})=>({${objectLiteral}}))`).runInNewContext({
764
767
  he: () => undefined,
765
768
  DGC: {},
766
769
  globalThis: sandboxGlobal,
767
- })({ he: () => undefined, DGC: {}, globalThis: sandboxGlobal });
770
+ process: { env: { CURSOR_POOL_RUNTIME_BASE_URL: 'http://127.0.0.1:61373' } },
771
+ })({ he: () => undefined, DGC: {}, globalThis: sandboxGlobal, process: { env: { CURSOR_POOL_RUNTIME_BASE_URL: 'http://127.0.0.1:61373' } } });
768
772
  await new Promise((resolve) => setTimeout(resolve, 0));
769
773
 
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);
774
+ assert.equal(sandboxGlobal.__cursorPoolRuntimeBaseUrl?.(), 'http://127.0.0.1:61373');
775
+ assert.equal(fetchedUrl, 'http://127.0.0.1:61373/platform/status');
774
776
  });
775
777
 
776
778
  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.9",
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.9"
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 {