pi-cursor-bridge 0.2.8 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursor-bridge",
3
- "version": "6.0.8",
3
+ "version": "6.0.9",
4
4
  "description": "Evidence-backed Cursor Context Engine search and bounded Cursor Agent execution, including a UI-suppressed minimal runtime.",
5
5
  "author": {
6
6
  "name": "Vanyangyang"
package/README.md CHANGED
@@ -12,6 +12,6 @@ pi install npm:pi-cursor-bridge
12
12
 
13
13
  Restart Pi after installation. Initialize the current project by asking Pi to initialize Cursor Bridge for the absolute project path, then use it normally. The package includes the `cce-routing` and `cursor-delegate` Skills and registers the native Cursor Bridge MCP tools directly in Pi.
14
14
 
15
- Pi wrapper 0.2.8 embeds Cursor Bridge 6.0.8, including Cursor 3.21 model-provider alias matching and `reasoning_effort` verification for Grok 4.7/high. Its result contract returns a compact receipt for background `cursor_do` work: poll `cursor_status(task_id)` normally, retrieve the terminal raw reply with `cursor_status(task_id, detail="result")`, check `isError` before using its content, and use `detail="full"` only when diagnostics are needed. Cursor must be installed and signed in. Current end-to-end compatibility claims remain scoped to the environments documented in the main repository.
15
+ Pi wrapper 0.2.9 embeds Cursor Bridge 6.0.9, including Cursor 3.21 model-provider alias matching and `reasoning_effort` verification for Grok 4.7/high. Its result contract returns a compact receipt for background `cursor_do` work: poll `cursor_status(task_id)` normally, retrieve the terminal raw reply with `cursor_status(task_id, detail="result")`, check `isError` before using its content, and use `detail="full"` only when diagnostics are needed. Cursor must be installed and signed in. Current end-to-end compatibility claims remain scoped to the environments documented in the main repository.
16
16
 
17
17
  Full documentation: [English](https://github.com/Vanyangyang/cursor-bridge#readme) · [简体中文](https://github.com/Vanyangyang/cursor-bridge/blob/main/README.zh-CN.md)
@@ -3115,7 +3115,6 @@ var require_utils = __commonJS({
3115
3115
  "use strict";
3116
3116
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
3117
3117
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
3118
- var isPort = RegExp.prototype.test.bind(/^\d*$/u);
3119
3118
  var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
3120
3119
  var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
3121
3120
  var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
@@ -3581,12 +3580,8 @@ var require_utils = __commonJS({
3581
3580
  uriTokens.push(host);
3582
3581
  }
3583
3582
  if (typeof component.port === "number" || typeof component.port === "string") {
3584
- const port = String(component.port);
3585
- if (!isPort(port)) {
3586
- throw new TypeError("URI port is malformed.");
3587
- }
3588
3583
  uriTokens.push(":");
3589
- uriTokens.push(port);
3584
+ uriTokens.push(String(component.port));
3590
3585
  }
3591
3586
  return uriTokens.length ? uriTokens.join("") : void 0;
3592
3587
  }
@@ -4029,15 +4024,12 @@ var require_fast_uri = __commonJS({
4029
4024
  }
4030
4025
  return false;
4031
4026
  }
4032
- function isIPLiteral(host) {
4033
- return host[0] === "[" && host[host.length - 1] === "]";
4034
- }
4035
4027
  function hasMalformedComponentPercentEncoding(matches) {
4036
4028
  const host = matches[4];
4037
- return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
4029
+ return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !(host[0] === "[" && host[host.length - 1] === "]") && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
4038
4030
  }
4039
4031
  function canonicalizeHost(parsed, options, schemeHandler, isIP) {
4040
- if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
4032
+ if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && parsed.host[0] !== "[" && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
4041
4033
  try {
4042
4034
  parsed.host = new URL("http://" + parsed.host).hostname;
4043
4035
  } catch (e) {
@@ -4124,11 +4116,10 @@ var require_fast_uri = __commonJS({
4124
4116
  if (parsed.host) {
4125
4117
  const ipv4result = isIPv4(parsed.host);
4126
4118
  if (ipv4result === false) {
4127
- const bracketedIPLiteral = isIPLiteral(parsed.host);
4128
- const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
4119
+ const bracketedIPLiteral = parsed.host[0] === "[" && parsed.host[parsed.host.length - 1] === "]";
4129
4120
  const ipv6result = normalizeIPv6(parsed.host);
4130
4121
  isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
4131
- malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
4122
+ malformedIPLiteral = bracketedIPLiteral && ipv6result.error === true;
4132
4123
  parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
4133
4124
  if (malformedIPLiteral) {
4134
4125
  parsed.error = parsed.error || "URI host is malformed.";
@@ -4151,17 +4142,14 @@ var require_fast_uri = __commonJS({
4151
4142
  parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
4152
4143
  }
4153
4144
  const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
4154
- if (!malformedIPLiteral) {
4155
- malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4156
- }
4157
- if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
4158
- let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4159
- if (!isIP) {
4160
- host = normalizePercentEncoding(host.toLowerCase());
4161
- }
4162
- parsed.host = reescapeHostDelimiters(host, isIP);
4163
- }
4145
+ malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4164
4146
  if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4147
+ if (uri.indexOf("%") !== -1) {
4148
+ if (parsed.host !== void 0 && !malformedIPLiteral) {
4149
+ const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4150
+ parsed.host = reescapeHostDelimiters(host, isIP);
4151
+ }
4152
+ }
4165
4153
  if (parsed.path) {
4166
4154
  parsed.path = normalizePathEncoding(parsed.path);
4167
4155
  }
@@ -11402,6 +11390,36 @@ import { mkdirSync as mkdirSync6, readFileSync as readFileSync5, renameSync as r
11402
11390
  import { createHash as createHash2 } from "node:crypto";
11403
11391
  import { homedir as homedir6 } from "node:os";
11404
11392
  import { dirname as dirname5, join as join6, resolve as resolve5 } from "node:path";
11393
+ import * as startupModule from "node:module";
11394
+ function readCursorStartupPreference(options = {}) {
11395
+ let database;
11396
+ try {
11397
+ const { DatabaseSync } = (options.requireImpl || requireOptional)("node:sqlite");
11398
+ const file = join6(dirname5(options.file || cursorWindowStatePath(options)), "state.vscdb");
11399
+ database = new DatabaseSync(file, { readOnly: true });
11400
+ const rows = database.prepare("SELECT key, value FROM ItemTable WHERE key IN (?, ?)").all(STARTUP_PREFERENCE_KEY, LEGACY_STARTUP_PREFERENCE_KEY);
11401
+ const values = new Map(rows.map(({ key, value }) => {
11402
+ try {
11403
+ return [key, JSON.parse(value)];
11404
+ } catch {
11405
+ return [key, value];
11406
+ }
11407
+ }));
11408
+ const preference = values.get(STARTUP_PREFERENCE_KEY);
11409
+ if (["default", "agentWindow", "lastUsedWindows"].includes(preference)) return preference;
11410
+ const legacy = values.get(LEGACY_STARTUP_PREFERENCE_KEY);
11411
+ if (legacy === true || legacy === "true" || legacy === "agentWindow") return "agentWindow";
11412
+ if (legacy === false || legacy === "false" || legacy === "lastUsedWindows") return "lastUsedWindows";
11413
+ return "default";
11414
+ } catch {
11415
+ return null;
11416
+ } finally {
11417
+ try {
11418
+ database?.close();
11419
+ } catch {
11420
+ }
11421
+ }
11422
+ }
11405
11423
  function cursorWindowStatePath(options = {}) {
11406
11424
  const env = options.env || process.env;
11407
11425
  const home = options.home || homedir6();
@@ -11431,6 +11449,12 @@ function stateSignature(last) {
11431
11449
  return createHash2("sha256").update(JSON.stringify(last)).digest("hex");
11432
11450
  }
11433
11451
  function readCursorStartupWindow(options = {}) {
11452
+ let preference = null;
11453
+ try {
11454
+ preference = (options.readStartupPreferenceImpl || readCursorStartupPreference)(options);
11455
+ } catch {
11456
+ }
11457
+ if (preference === "agentWindow") return { uiFlavor: "agents_v2", source: "cursor-startup-preference" };
11434
11458
  const file = options.file || cursorWindowStatePath(options);
11435
11459
  const last = nativeWindowState(options);
11436
11460
  try {
@@ -11449,8 +11473,12 @@ function cursorStartupWindowArgs(startupWindow, projectPath) {
11449
11473
  if (startupWindow.uiFlavor !== "legacy") return ["--glass"];
11450
11474
  return ["--classic", ...projectPath ? [projectPath] : ["--new-window"]];
11451
11475
  }
11476
+ var requireOptional, STARTUP_PREFERENCE_KEY, LEGACY_STARTUP_PREFERENCE_KEY;
11452
11477
  var init_cursor_startup_window = __esm({
11453
11478
  "cursor-startup-window.mjs"() {
11479
+ requireOptional = startupModule.createRequire(import.meta.url);
11480
+ STARTUP_PREFERENCE_KEY = "cursor/userWindowRestorationPreference";
11481
+ LEGACY_STARTUP_PREFERENCE_KEY = "cursor/userOpenAgentsWindowOnStartupPreference";
11454
11482
  }
11455
11483
  });
11456
11484
 
@@ -22990,7 +23018,7 @@ function updateCursorSessionRegistry(filePath, mutator, options = {}) {
22990
23018
  // server.mjs
22991
23019
  init_cursor_ensure_core();
22992
23020
  init_lifecycle_paths();
22993
- var PLUGIN_VERSION = "6.0.8";
23021
+ var PLUGIN_VERSION = "6.0.9";
22994
23022
  var CDP_PORT2 = Number(process.env.CURSOR_BRIDGE_CDP_PORT || 9223);
22995
23023
  var ORIGIN = `http://localhost:${CDP_PORT2}`;
22996
23024
  var QUERY_TIMEOUT = Number(process.env.CURSOR_BRIDGE_TIMEOUT || 3e5);
@@ -23500,11 +23528,20 @@ var EXPR_MODEL_PICKER_TRIGGER = `(function(){
23500
23528
  const text=String(trigger.querySelector('.ui-model-picker__trigger-text,.vscode-model-picker__trigger-text')?.innerText||trigger.innerText||'').replace(/\\s+/g,' ').trim();
23501
23529
  const detail=String(trigger.querySelector('.ui-model-picker__trigger-variant-suffix,.vscode-model-picker__trigger-variant-suffix')?.innerText||'').replace(/\\s+/g,' ').trim();
23502
23530
  const x=Math.round(rect.x+rect.width/2),y=Math.round(rect.y+rect.height/2);
23503
- let state='ready';
23531
+ let state='ready',occluder=null;
23504
23532
  if(trigger.disabled||trigger.getAttribute('aria-disabled')==='true'||trigger.closest('[inert]')||getComputedStyle(trigger).pointerEvents==='none')state='trigger_disabled';
23505
23533
  else if(!Number.isFinite(x)||!Number.isFinite(y)||rect.width<=0||rect.height<=0||x<0||y<0||x>=innerWidth||y>=innerHeight)state='trigger_offscreen';
23506
- else {const hit=document.elementFromPoint(x,y);if(!hit||hit!==trigger&&!trigger.contains(hit))state='trigger_occluded';}
23507
- return JSON.stringify({found:true,state,interactive:state==='ready',expanded:trigger.getAttribute('aria-expanded'),text,detail,x,y,...owner});
23534
+ else {
23535
+ const hit=document.elementFromPoint(x,y);
23536
+ if(!hit||hit!==trigger&&!trigger.contains(hit)){
23537
+ state='trigger_occluded';
23538
+ const menu=hit&&hit.closest('[data-component="menu-popup"]');
23539
+ // A transient Cursor menu can consume/block a click on the composer.
23540
+ // Never dismiss dialogs, arbitrary overlays, or offscreen controls.
23541
+ if(menu&&!hit.closest('[role="dialog"],[aria-modal="true"]'))occluder={kind:'menu',id:menu.getAttribute('id')||null};
23542
+ }
23543
+ }
23544
+ return JSON.stringify({found:true,state,interactive:state==='ready',expanded:trigger.getAttribute('aria-expanded'),occluder,text,detail,x,y,...owner});
23508
23545
  })()`;
23509
23546
  function exprActivateClosedModelPicker(expected) {
23510
23547
  return `(function(){
@@ -23872,19 +23909,24 @@ function exprSelectAgentWorkspace(projectPath) {
23872
23909
  const fail=(state,extra={})=>JSON.stringify({ok:false,state,wanted,...extra,
23873
23910
  nextStep:'Select the exact local workspace '+${JSON.stringify(String(projectPath || ""))}+' in the new Agent project picker before retrying.'});
23874
23911
  if(triggers.length!==1)return fail(triggers.length?'workspace_project_selector_ambiguous':'workspace_project_selector_unavailable',{triggerCount:triggers.length});
23875
- triggers[0].click();
23912
+ if(triggers[0].getAttribute?.('aria-expanded')!=='true')triggers[0].click();
23876
23913
  await new Promise(resolve=>setTimeout(resolve,350));
23877
- const menus=[...new Set([...document.querySelectorAll('[data-component="menu-popup"],[role="menu"]')].filter(visible)
23914
+ const readMenus=()=>[...new Set([...document.querySelectorAll('[data-component="menu-popup"],[role="menu"]')].filter(visible)
23878
23915
  .map(menu=>menu.getAttribute('role')==='menu'&&menu.getAttribute('aria-label')==='Select a project'
23879
23916
  ?menu:menu.querySelector('[role="menu"][aria-label="Select a project"]')).filter(visible))];
23917
+ let menus=readMenus();
23880
23918
  if(menus.length!==1)return fail(menus.length?'workspace_project_option_ambiguous':'workspace_project_option_unavailable',{menuCount:menus.length});
23881
- const rows=[];const seen=new Set();
23882
- for(const menu of menus){
23883
- for(const row of menu.querySelectorAll('[data-component="menu-row"][role="menuitem"],[role="option"]')){
23884
- if(!visible(row)||seen.has(row))continue;seen.add(row);rows.push(row);
23919
+ const readRows=()=>{
23920
+ const rows=[];const seen=new Set();
23921
+ for(const menu of menus){
23922
+ for(const row of menu.querySelectorAll('[data-component="menu-row"][role="menuitem"],[role="option"]')){
23923
+ if(!visible(row)||seen.has(row))continue;seen.add(row);rows.push(row);
23924
+ }
23885
23925
  }
23886
- }
23887
- const available=rows.map(row=>String(row.innerText||row.textContent||'').replace(/\s+/g,' ').trim());
23926
+ return rows;
23927
+ };
23928
+ let rows=readRows();
23929
+ let available=rows.map(row=>String(row.innerText||row.textContent||'').replace(/\s+/g,' ').trim());
23888
23930
  const rowWorkspace=row=>{
23889
23931
  const key=Object.keys(row).find(key=>key.startsWith('__reactFiber$'));
23890
23932
  const levels=[];const visited=new Set();
@@ -23944,7 +23986,26 @@ function exprSelectAgentWorkspace(projectPath) {
23944
23986
  const [workspaceId,path]=JSON.parse([...identities][0]);
23945
23987
  return {path,workspaceId,root,currentRoot};
23946
23988
  };
23947
- const matches=rows.map(row=>({row,identity:rowWorkspace(row)})).filter(match=>match.identity&&match.identity.path===wanted);
23989
+ const findMatches=()=>rows.map(row=>({row,identity:rowWorkspace(row)})).filter(match=>match.identity&&match.identity.path===wanted);
23990
+ let matches=findMatches();
23991
+ if(!matches.length){
23992
+ // Cursor's Recents view omits older registered workspaces. Search the
23993
+ // full path, then apply the same committed local-identity checks.
23994
+ const searches=[...menus[0].querySelectorAll('input[aria-label="Search menu items"]')].filter(visible);
23995
+ if(searches.length===1&&typeof HTMLInputElement!=='undefined'){
23996
+ const setter=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value')?.set;
23997
+ if(setter){
23998
+ setter.call(searches[0],${JSON.stringify(String(projectPath || ""))});
23999
+ searches[0].dispatchEvent(new Event('input',{bubbles:true}));
24000
+ await new Promise(resolve=>setTimeout(resolve,350));
24001
+ menus=readMenus();
24002
+ if(menus.length!==1)return fail(menus.length?'workspace_project_option_ambiguous':'workspace_project_option_unavailable',{menuCount:menus.length});
24003
+ rows=readRows();
24004
+ available=rows.map(row=>String(row.innerText||row.textContent||'').replace(/\s+/g,' ').trim());
24005
+ matches=findMatches();
24006
+ }
24007
+ }
24008
+ }
23948
24009
  if(matches.length!==1)return fail(matches.length?'workspace_project_option_ambiguous':'workspace_project_option_unavailable',{available});
23949
24010
  const selected=matches[0];
23950
24011
  if(selected.identity.root&&selected.identity.root.current!==selected.identity.currentRoot)return fail('workspace_project_option_unavailable',{available});
@@ -25925,6 +25986,7 @@ var CursorBridge = class {
25925
25986
  let trigger = null, snapshot = { open: false, rows: [] };
25926
25987
  let stableSignature = null, stableSince = 0, clicked = false, clickedOwner = null;
25927
25988
  let clickedAt = 0, recoveryAttempted = false, lastPollError = null;
25989
+ let dismissedMenus = 0, dismissalOwner = null;
25928
25990
  const attempts = [];
25929
25991
  do {
25930
25992
  this._throwIfCancelledBeforeSend(job);
@@ -25940,8 +26002,23 @@ var CursorBridge = class {
25940
26002
  }
25941
26003
  this._throwIfCancelledBeforeSend(job);
25942
26004
  const sameOwner = modelPickerOwnerKey(snapshot.owner) === modelPickerOwnerKey(trigger);
26005
+ if (dismissalOwner !== null && dismissalOwner !== modelPickerOwnerKey(trigger)) {
26006
+ attempts.push("owner_changed_after_menu_dismissal");
26007
+ break;
26008
+ }
25943
26009
  if (snapshot.open && trigger.found && sameOwner && (!clicked || clickedOwner === modelPickerOwnerKey(trigger))) return { trigger, ...snapshot };
25944
26010
  if (snapshot.open && !sameOwner && !attempts.includes("owner_changed")) attempts.push("owner_changed");
26011
+ if (!clicked && !snapshot.open && trigger.found && trigger.state === "trigger_occluded" && trigger.expanded === "false" && trigger.occluder?.kind === "menu" && dismissedMenus < 3) {
26012
+ this._throwIfCancelledBeforeSend(job);
26013
+ dismissalOwner = modelPickerOwnerKey(trigger);
26014
+ dismissedMenus++;
26015
+ attempts.push("dismiss_occluding_menu");
26016
+ await c.send("Input.dispatchKeyEvent", { type: "keyDown", key: "Escape", code: "Escape", windowsVirtualKeyCode: 27, nativeVirtualKeyCode: 27 });
26017
+ await c.send("Input.dispatchKeyEvent", { type: "keyUp", key: "Escape", code: "Escape", windowsVirtualKeyCode: 27, nativeVirtualKeyCode: 27 });
26018
+ stableSignature = null;
26019
+ await sleep2(Math.min(150, Math.max(0, deadline - Date.now())));
26020
+ continue;
26021
+ }
25945
26022
  if (!clicked) {
25946
26023
  const interactive = trigger.found && trigger.interactive !== false;
25947
26024
  const signature = interactive ? JSON.stringify([trigger.triggerId, trigger.composerId, trigger.agentId, trigger.x, trigger.y]) : null;
@@ -3713,6 +3713,36 @@ import { mkdirSync, readFileSync, renameSync, writeFileSync, rmSync } from "node
3713
3713
  import { createHash } from "node:crypto";
3714
3714
  import { homedir } from "node:os";
3715
3715
  import { dirname, join, resolve } from "node:path";
3716
+ import * as startupModule from "node:module";
3717
+ function readCursorStartupPreference(options = {}) {
3718
+ let database;
3719
+ try {
3720
+ const { DatabaseSync } = (options.requireImpl || requireOptional)("node:sqlite");
3721
+ const file = join(dirname(options.file || cursorWindowStatePath(options)), "state.vscdb");
3722
+ database = new DatabaseSync(file, { readOnly: true });
3723
+ const rows = database.prepare("SELECT key, value FROM ItemTable WHERE key IN (?, ?)").all(STARTUP_PREFERENCE_KEY, LEGACY_STARTUP_PREFERENCE_KEY);
3724
+ const values = new Map(rows.map(({ key, value }) => {
3725
+ try {
3726
+ return [key, JSON.parse(value)];
3727
+ } catch {
3728
+ return [key, value];
3729
+ }
3730
+ }));
3731
+ const preference = values.get(STARTUP_PREFERENCE_KEY);
3732
+ if (["default", "agentWindow", "lastUsedWindows"].includes(preference)) return preference;
3733
+ const legacy = values.get(LEGACY_STARTUP_PREFERENCE_KEY);
3734
+ if (legacy === true || legacy === "true" || legacy === "agentWindow") return "agentWindow";
3735
+ if (legacy === false || legacy === "false" || legacy === "lastUsedWindows") return "lastUsedWindows";
3736
+ return "default";
3737
+ } catch {
3738
+ return null;
3739
+ } finally {
3740
+ try {
3741
+ database?.close();
3742
+ } catch {
3743
+ }
3744
+ }
3745
+ }
3716
3746
  function cursorWindowStatePath(options = {}) {
3717
3747
  const env = options.env || process.env;
3718
3748
  const home = options.home || homedir();
@@ -3742,6 +3772,12 @@ function stateSignature(last) {
3742
3772
  return createHash("sha256").update(JSON.stringify(last)).digest("hex");
3743
3773
  }
3744
3774
  function readCursorStartupWindow(options = {}) {
3775
+ let preference = null;
3776
+ try {
3777
+ preference = (options.readStartupPreferenceImpl || readCursorStartupPreference)(options);
3778
+ } catch {
3779
+ }
3780
+ if (preference === "agentWindow") return { uiFlavor: "agents_v2", source: "cursor-startup-preference" };
3745
3781
  const file = options.file || cursorWindowStatePath(options);
3746
3782
  const last = nativeWindowState(options);
3747
3783
  try {
@@ -3779,8 +3815,12 @@ function cursorStartupWindowArgs(startupWindow, projectPath) {
3779
3815
  if (startupWindow.uiFlavor !== "legacy") return ["--glass"];
3780
3816
  return ["--classic", ...projectPath ? [projectPath] : ["--new-window"]];
3781
3817
  }
3818
+ var requireOptional, STARTUP_PREFERENCE_KEY, LEGACY_STARTUP_PREFERENCE_KEY;
3782
3819
  var init_cursor_startup_window = __esm({
3783
3820
  "cursor-startup-window.mjs"() {
3821
+ requireOptional = startupModule.createRequire(import.meta.url);
3822
+ STARTUP_PREFERENCE_KEY = "cursor/userWindowRestorationPreference";
3823
+ LEGACY_STARTUP_PREFERENCE_KEY = "cursor/userOpenAgentsWindowOnStartupPreference";
3784
3824
  }
3785
3825
  });
3786
3826
 
@@ -10,7 +10,7 @@ const hostWorkspaceId = hostCwd.replace(/\\/g, "/").toLowerCase();
10
10
  export default createStdioMcpExtension({
11
11
  label: "Cursor Bridge",
12
12
  clientName: "pi-cursor-bridge",
13
- packageVersion: "0.2.8",
13
+ packageVersion: "0.2.9",
14
14
  serverName: "cursor-bridge",
15
15
  serverScript: join(packageRoot, "dist", "cursor-bridge.mjs"),
16
16
  cwd: hostCwd,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cursor-bridge",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Windows only. Use Cursor Context Engine and bounded, explicitly continuous Cursor Agent execution from the Pi coding agent.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,6 +47,6 @@
47
47
  },
48
48
  "piPackage": {
49
49
  "embeddedProduct": "Cursor Bridge",
50
- "embeddedProductVersion": "6.0.8"
50
+ "embeddedProductVersion": "6.0.9"
51
51
  }
52
52
  }