pi-cursor-bridge 0.2.6 → 0.2.7

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.6",
3
+ "version": "6.0.7",
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.6 embeds Cursor Bridge 6.0.6, 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.7 embeds Cursor Bridge 6.0.7, 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)
@@ -12907,6 +12907,11 @@ async function ensureCursorViaSupervisor(options = {}) {
12907
12907
  ok: !!response.ok,
12908
12908
  status: response.status,
12909
12909
  message: response.message,
12910
+ needsAction: response.needsAction || null,
12911
+ nextStep: response.nextStep || null,
12912
+ retryable: response.retryable === true,
12913
+ cursorExecutable: response.cursorExecutable || null,
12914
+ cursorExecutableSource: response.cursorExecutableSource || null,
12910
12915
  port: response.port,
12911
12916
  exe: response.exe,
12912
12917
  cursorPid: response.cursorPid || null,
@@ -22985,7 +22990,7 @@ function updateCursorSessionRegistry(filePath, mutator, options = {}) {
22985
22990
  // server.mjs
22986
22991
  init_cursor_ensure_core();
22987
22992
  init_lifecycle_paths();
22988
- var PLUGIN_VERSION = "6.0.6";
22993
+ var PLUGIN_VERSION = "6.0.7";
22989
22994
  var CDP_PORT2 = Number(process.env.CURSOR_BRIDGE_CDP_PORT || 9223);
22990
22995
  var ORIGIN = `http://localhost:${CDP_PORT2}`;
22991
22996
  var QUERY_TIMEOUT = Number(process.env.CURSOR_BRIDGE_TIMEOUT || 3e5);
@@ -23373,6 +23378,24 @@ var EXPR_PROVIDER_ERROR = `(function(){
23373
23378
  const signature=[title,message,requestId||''].join('|');
23374
23379
  return JSON.stringify({found:true,title,message,requestId,retryAvailable,signature});
23375
23380
  })()`;
23381
+ var STOP_COMPOSER_BODY = `
23382
+ const findStopComposers=(rawId)=>{
23383
+ const legacy=[...document.querySelectorAll('.composer-bar[data-composer-id]')]
23384
+ .filter(e=>e.offsetParent!==null&&e.dataset.composerId&&(!rawId||e.dataset.composerId===rawId));
23385
+ if(legacy.length)return {modern:false,composers:legacy};
23386
+ return {modern:true,composers:[...document.querySelectorAll('[data-agent-panel-conversation-shell][data-glass-agent-id]')]
23387
+ .filter(e=>e.offsetParent!==null&&e.dataset.glassAgentId&&(!rawId||e.dataset.glassAgentId===rawId))};
23388
+ };
23389
+ const modernComposerStatus=(composer,entries)=>{
23390
+ const ownStatus=composer.dataset.composerStatus;
23391
+ if(ownStatus)return ownStatus;
23392
+ const matches=entries.filter(e=>e&&e.id==='local:'+composer.dataset.glassAgentId);
23393
+ if(matches.length!==1)return null;
23394
+ const entry=matches[0];
23395
+ if(entry.showSpinner||entry.icon==='loading')return 'generating';
23396
+ return ({'check-circled':'completed','circle-slash':'cancelled',warning:'failed','needs-attention':'needs_attention'})[entry.icon]||null;
23397
+ };
23398
+ `;
23376
23399
  function exprClickSelectedAgentStop(agentId) {
23377
23400
  const expected = JSON.stringify(String(agentId));
23378
23401
  return `(function(){
@@ -23385,52 +23408,52 @@ function exprClickSelectedAgentStop(agentId) {
23385
23408
  if(!selected||selected.id!==${expected}){
23386
23409
  return JSON.stringify({clicked:false,state:'selected_agent_mismatch',selectedId:selected&&selected.id||null,selectedCount:selectedEntries.length});
23387
23410
  }
23411
+ ${STOP_COMPOSER_BODY}
23388
23412
  const expectedComposerId=String(${expected}).replace(/^local:/,'');
23389
- const composers=[...document.querySelectorAll('.composer-bar[data-composer-id]')]
23390
- .filter(e=>e.offsetParent!==null&&e.dataset.composerId===expectedComposerId);
23413
+ const {modern,composers}=findStopComposers(expectedComposerId);
23391
23414
  if(composers.length!==1){
23392
23415
  return JSON.stringify({clicked:false,state:'composer_identity_mismatch',selectedId:selected.id,count:composers.length});
23393
23416
  }
23394
23417
  const composer=composers[0];
23395
- if(composer.dataset.composerStatus!=='generating'){
23396
- return JSON.stringify({clicked:false,state:'composer_not_generating',selectedId:selected.id,status:composer.dataset.composerStatus||null});
23418
+ const status=modern?modernComposerStatus(composer,entries):composer.dataset.composerStatus||null;
23419
+ if(status!=='generating'){
23420
+ return JSON.stringify({clicked:false,state:'composer_not_generating',selectedId:selected.id,status});
23397
23421
  }
23398
- const generationButtons=[...composer.querySelectorAll('button.ui-prompt-input-submit-button[data-state="stop"][aria-label="Stop generation"]')]
23399
- .filter(button=>button.offsetParent!==null&&!button.disabled&&button.closest('.composer-bar')===composer);
23422
+ const belongs=button=>button.offsetParent!==null&&!button.disabled&&button.closest(modern?'[data-glass-agent-id]':'.composer-bar')===composer;
23423
+ const generationButtons=[...composer.querySelectorAll(modern?'button.ui-prompt-input-submit-button[aria-label="Stop generation"]':'button.ui-prompt-input-submit-button[data-state="stop"][aria-label="Stop generation"]')]
23424
+ .filter(belongs);
23400
23425
  const commandButtons=[...composer.querySelectorAll('button.ui-shell-tool-call__glass-stop[aria-label="Stop command"]')]
23401
- .filter(button=>button.offsetParent!==null&&!button.disabled&&button.closest('.composer-bar')===composer);
23426
+ .filter(belongs);
23402
23427
  const buttons=[...generationButtons,...commandButtons];
23403
23428
  if(buttons.length!==1){
23404
23429
  return JSON.stringify({clicked:false,state:buttons.length?'ambiguous_stop_controls':'stop_control_missing',selectedId:selected.id,count:buttons.length});
23405
23430
  }
23406
23431
  buttons[0].click();
23407
- return JSON.stringify({clicked:true,state:'clicked',selectedId:selected.id,composerId:composer.dataset.composerId,control:generationButtons.length?'stop_generation':'stop_command'});
23432
+ return JSON.stringify({clicked:true,state:'clicked',selectedId:selected.id,composerId:expectedComposerId,control:generationButtons.length?'stop_generation':'stop_command'});
23408
23433
  })()`;
23409
23434
  }
23410
- var EXPR_VISIBLE_COMPOSER = `(function(){
23411
- const composers=[...document.querySelectorAll('.composer-bar[data-composer-id]')]
23412
- .filter(e=>e.offsetParent!==null&&e.dataset.composerId);
23413
- if(composers.length!==1){
23414
- return JSON.stringify({ok:false,state:composers.length?'ambiguous_composers':'composer_missing',count:composers.length});
23415
- }
23416
- const composer=composers[0];
23417
- return JSON.stringify({
23418
- ok:true,
23419
- id:'local:'+composer.dataset.composerId,
23420
- composerId:composer.dataset.composerId,
23421
- status:composer.dataset.composerStatus||null
23422
- });
23423
- })()`;
23424
23435
  function exprClickBoundComposerStop(agentId) {
23425
23436
  const expected = JSON.stringify(String(agentId));
23426
23437
  return `(function(){
23438
+ ${STOP_COMPOSER_BODY}
23427
23439
  const expectedComposerId=String(${expected}).replace(/^local:/,'');
23428
- const composers=[...document.querySelectorAll('.composer-bar[data-composer-id]')]
23429
- .filter(e=>e.offsetParent!==null&&e.dataset.composerId===expectedComposerId);
23440
+ const {modern,composers}=findStopComposers(expectedComposerId);
23430
23441
  if(composers.length!==1){
23431
23442
  return JSON.stringify({clicked:false,state:'composer_identity_mismatch',count:composers.length});
23432
23443
  }
23433
23444
  const composer=composers[0];
23445
+ if(modern){
23446
+ ${REACT_ADAPTER_BODY}
23447
+ const status=modernComposerStatus(composer,a?a.entries():[]);
23448
+ if(status!=='generating')return JSON.stringify({clicked:false,state:'composer_not_generating',status,composerId:expectedComposerId});
23449
+ const belongs=button=>button.offsetParent!==null&&!button.disabled&&button.closest('[data-glass-agent-id]')===composer;
23450
+ const generationButtons=[...composer.querySelectorAll('button.ui-prompt-input-submit-button[aria-label="Stop generation"]')].filter(belongs);
23451
+ const commandButtons=[...composer.querySelectorAll('button.ui-shell-tool-call__glass-stop[aria-label="Stop command"]')].filter(belongs);
23452
+ const buttons=[...generationButtons,...commandButtons];
23453
+ if(buttons.length!==1)return JSON.stringify({clicked:false,state:buttons.length?'ambiguous_stop_controls':'stop_control_missing',count:buttons.length,composerId:expectedComposerId});
23454
+ buttons[0].click();
23455
+ return JSON.stringify({clicked:true,state:'clicked',composerId:expectedComposerId,control:generationButtons.length?'stop_generation':'stop_command'});
23456
+ }
23434
23457
  if(composer.dataset.composerStatus!=='generating'){
23435
23458
  return JSON.stringify({clicked:false,state:'composer_not_generating',status:composer.dataset.composerStatus||null,composerId:composer.dataset.composerId});
23436
23459
  }
@@ -23540,12 +23563,90 @@ var EXPR_SELECTED_AGENT_MODEL_CONFIG = `(function(){
23540
23563
  if(data&&data.modelConfig&&!configs.includes(data.modelConfig))configs.push(data.modelConfig);
23541
23564
  }
23542
23565
  }
23543
- if(configs.length!==1)return JSON.stringify({found:false,state:'model_config_ambiguous',configCount:configs.length});
23544
- const config=configs[0];
23545
- return JSON.stringify({found:true,modelName:String(config.modelName||''),selectedModels:(config.selectedModels||[]).map(model=>({
23546
- modelId:String(model&&model.modelId||''),
23547
- parameters:Object.fromEntries((model&&model.parameters||[]).map(parameter=>[String(parameter&&parameter.id||''),String(parameter&&parameter.value||'')]))
23548
- }))});
23566
+ if(configs.length>1)return JSON.stringify({found:false,state:'model_config_ambiguous',configCount:configs.length});
23567
+ if(configs.length===1){
23568
+ const config=configs[0];
23569
+ return JSON.stringify({found:true,modelName:String(config.modelName||''),selectedModels:(config.selectedModels||[]).map(model=>({
23570
+ modelId:String(model&&model.modelId||''),
23571
+ parameters:Object.fromEntries((model&&model.parameters||[]).map(parameter=>[String(parameter&&parameter.id||''),String(parameter&&parameter.value||'')]))
23572
+ }))});
23573
+ }
23574
+ // Cursor 3.23's IDE input is Solid; its model trigger is a mounted React
23575
+ // picker whose initialSelections/initialAutoMode come from this composer.
23576
+ const source='legacy_composer_model_trigger';
23577
+ const fail=(state)=>JSON.stringify({found:false,state,source});
23578
+ const input=inputs[0],composer=input.closest('.composer-bar[data-composer-id]');
23579
+ if(!composer||input.closest('.composer-bar')!==composer
23580
+ ||composer.parentElement&&composer.parentElement.closest('.composer-bar')
23581
+ ||composer.querySelectorAll('.composer-bar').length)return fail('legacy_composer_ambiguous');
23582
+ const composerId=composer.getAttribute('data-composer-id');
23583
+ const owners=[...document.querySelectorAll('.composer-bar[data-composer-id]')]
23584
+ .filter(node=>node.getAttribute('data-composer-id')===composerId);
23585
+ if(typeof composerId!=='string'||!composerId.trim()||owners.length!==1||owners[0]!==composer)return fail('legacy_composer_ambiguous');
23586
+ const triggers=[...composer.querySelectorAll('.vscode-model-picker__trigger')];
23587
+ if(triggers.length!==1||!triggers[0].classList.contains('vscode-model-picker__trigger')
23588
+ ||triggers[0].closest('.composer-bar')!==composer)return fail('legacy_model_trigger_ambiguous');
23589
+ const trigger=triggers[0],keys=Object.keys(trigger).filter(key=>key.startsWith('__reactFiber$'));
23590
+ if(keys.length!==1)return fail('legacy_model_tree_unconfirmed');
23591
+ const levels=[],visited=new Set();
23592
+ let root=null,currentRoot=null;
23593
+ for(let fiber=trigger[keys[0]];fiber;fiber=fiber.return){
23594
+ if(levels.length>=256||visited.has(fiber))return fail('legacy_model_tree_unconfirmed');
23595
+ const alternate=fiber.alternate||null;
23596
+ if(alternate&&(alternate===fiber||alternate.alternate!==fiber||visited.has(alternate)))return fail('legacy_model_tree_unconfirmed');
23597
+ visited.add(fiber);if(alternate)visited.add(alternate);
23598
+ const pair=alternate?[fiber,alternate]:[fiber];
23599
+ levels.push(pair);
23600
+ const state=fiber.stateNode;
23601
+ if(state&&state.current){
23602
+ if(fiber.tag!==3||fiber.return||!pair.includes(state.current)||alternate&&(alternate.tag!==3||alternate.stateNode!==state))return fail('legacy_model_tree_unconfirmed');
23603
+ root=state;currentRoot=state.current;break;
23604
+ }
23605
+ }
23606
+ if(!root)return fail('legacy_model_tree_unconfirmed');
23607
+ // DOM expandos may retain an old fiber or a borrowed return chain. Each
23608
+ // edge must belong to the committed parent's actual child/sibling list.
23609
+ const currentPath=[currentRoot],currentVisited=new Set(currentPath);
23610
+ let parent=currentRoot,nodeBudget=2048;
23611
+ for(let depth=levels.length-2;depth>=0;depth--){
23612
+ const candidates=[],siblings=new Set();
23613
+ for(let child=parent.child;child;child=child.sibling){
23614
+ if(--nodeBudget<0||siblings.has(child))return fail('legacy_model_tree_unconfirmed');
23615
+ siblings.add(child);
23616
+ if(levels[depth].includes(child))candidates.push(child);
23617
+ }
23618
+ if(candidates.length!==1||currentVisited.has(candidates[0]))return fail('legacy_model_tree_unconfirmed');
23619
+ parent=candidates[0];currentVisited.add(parent);currentPath.push(parent);
23620
+ }
23621
+ if(parent.stateNode!==trigger)return fail('legacy_model_tree_unconfirmed');
23622
+ const snapshots=new Set();
23623
+ for(const fiber of currentPath){
23624
+ const props=fiber.memoizedProps;
23625
+ if(!props||!Object.prototype.hasOwnProperty.call(props,'initialSelections')
23626
+ &&!Object.prototype.hasOwnProperty.call(props,'initialAutoMode'))continue;
23627
+ if(!Object.prototype.hasOwnProperty.call(props,'initialSelections')||!Object.prototype.hasOwnProperty.call(props,'initialAutoMode')
23628
+ ||!Array.isArray(props.initialSelections)||typeof props.initialAutoMode!=='boolean')return fail('legacy_model_schema_unconfirmed');
23629
+ // Auto is never evidence for a named model, even if stale selections remain.
23630
+ if(props.initialAutoMode)return fail('legacy_model_auto');
23631
+ if(props.initialSelections.length!==1)return fail('legacy_model_selection_ambiguous');
23632
+ const selected=props.initialSelections[0];
23633
+ if(!selected||typeof selected.modelId!=='string'||!selected.modelId.trim()
23634
+ ||selected.modelId!==selected.modelId.trim()||selected.count!==1||!Array.isArray(selected.parameters))return fail('legacy_model_schema_unconfirmed');
23635
+ if(selected.modelId.toLowerCase()==='default')return fail('legacy_model_auto');
23636
+ const parameters=[];
23637
+ for(const parameter of selected.parameters){
23638
+ if(!parameter||typeof parameter.id!=='string'||!parameter.id.trim()||parameter.id!==parameter.id.trim()
23639
+ ||typeof parameter.value!=='string'||!parameter.value.length||parameters.some(entry=>entry[0]===parameter.id))return fail('legacy_model_schema_unconfirmed');
23640
+ parameters.push([parameter.id,parameter.value]);
23641
+ }
23642
+ parameters.sort((a,b)=>a[0]<b[0]?-1:a[0]>b[0]?1:0);
23643
+ snapshots.add(JSON.stringify({modelName:selected.modelId,selectedModels:[{modelId:selected.modelId,parameters:Object.fromEntries(parameters)}]}));
23644
+ }
23645
+ if(!snapshots.size)return fail('legacy_model_schema_unconfirmed');
23646
+ if(snapshots.size!==1)return fail('legacy_model_config_ambiguous');
23647
+ const snapshot=JSON.parse([...snapshots][0]);
23648
+ if(root.current!==currentRoot)return fail('legacy_model_tree_unconfirmed');
23649
+ return JSON.stringify({found:true,...snapshot,source});
23549
23650
  })()`;
23550
23651
  function normalizeModelPickerText(value) {
23551
23652
  return String(value || "").trim().toLowerCase().replace(/extra[\s_-]*high/g, "xhigh").replace(/[^a-z0-9]+/g, "");
@@ -23709,30 +23810,93 @@ function matchSelectedAgentModelConfig(snapshot, requestedModel, requestedEffort
23709
23810
  return { modelId: match.modelId, effort: effort || null };
23710
23811
  }
23711
23812
  function exprSelectAgentWorkspace(projectPath) {
23712
- return `(async function(){
23713
- const wanted=String(${JSON.stringify(String(projectPath || ""))}).replace(/\\\\/g,'/').replace(/^\\/([a-z]:\\/)/i,'$1').replace(/\\/+$/,'').toLowerCase();
23714
- const normalize=value=>String(value||'').replace(/\\\\/g,'/').replace(/^\\/([a-z]:\\/)/i,'$1').replace(/\\/+$/,'').toLowerCase();
23813
+ return String.raw`(async function(){
23814
+ const normalize=value=>String(value||'').replace(/\\/g,'/').replace(/^\/([a-z]:\/)/i,'$1').replace(/\/+$/,'').toLowerCase();
23815
+ const wanted=normalize(${JSON.stringify(String(projectPath || ""))});
23715
23816
  const visible=node=>!!(node&&(node.offsetParent!==null||(node.getClientRects&&node.getClientRects().length>0)));
23716
23817
  const pathTriggers=()=>[...document.querySelectorAll('button.ui-select-trigger,button[aria-haspopup="menu"]')]
23717
- .filter(visible).filter(node=>/^[a-z]:\\//i.test(normalize(node.innerText||node.textContent)));
23818
+ .filter(visible).filter(node=>/^[a-z]:\//i.test(normalize(node.innerText||node.textContent)));
23718
23819
  const triggers=pathTriggers();
23719
23820
  const fail=(state,extra={})=>JSON.stringify({ok:false,state,wanted,...extra,
23720
23821
  nextStep:'Select the exact local workspace '+${JSON.stringify(String(projectPath || ""))}+' in the new Agent project picker before retrying.'});
23721
23822
  if(triggers.length!==1)return fail(triggers.length?'workspace_project_selector_ambiguous':'workspace_project_selector_unavailable',{triggerCount:triggers.length});
23722
23823
  triggers[0].click();
23723
23824
  await new Promise(resolve=>setTimeout(resolve,350));
23724
- const menus=[...document.querySelectorAll('[data-component="menu-popup"],[role="menu"]')].filter(visible)
23725
- .filter(menu=>String(menu.getAttribute('aria-label')||'')==='Select a project'||menu.querySelector('[aria-label="Select a project"]'));
23825
+ const menus=[...new Set([...document.querySelectorAll('[data-component="menu-popup"],[role="menu"]')].filter(visible)
23826
+ .map(menu=>menu.getAttribute('role')==='menu'&&menu.getAttribute('aria-label')==='Select a project'
23827
+ ?menu:menu.querySelector('[role="menu"][aria-label="Select a project"]')).filter(visible))];
23828
+ if(menus.length!==1)return fail(menus.length?'workspace_project_option_ambiguous':'workspace_project_option_unavailable',{menuCount:menus.length});
23726
23829
  const rows=[];const seen=new Set();
23727
23830
  for(const menu of menus){
23728
23831
  for(const row of menu.querySelectorAll('[data-component="menu-row"][role="menuitem"],[role="option"]')){
23729
23832
  if(!visible(row)||seen.has(row))continue;seen.add(row);rows.push(row);
23730
23833
  }
23731
23834
  }
23732
- const available=rows.map(row=>String(row.innerText||row.textContent||'').replace(/\\s+/g,' ').trim());
23733
- const matches=rows.filter(row=>normalize(row.innerText||row.textContent)===wanted);
23835
+ const available=rows.map(row=>String(row.innerText||row.textContent||'').replace(/\s+/g,' ').trim());
23836
+ const rowWorkspace=row=>{
23837
+ const key=Object.keys(row).find(key=>key.startsWith('__reactFiber$'));
23838
+ const levels=[];const visited=new Set();
23839
+ let root=null,currentRoot=null,hasProject=false,belowMenu=true;
23840
+ for(let fiber=key&&row[key];fiber;fiber=fiber.return){
23841
+ if(levels.length>=256||visited.has(fiber))return null;
23842
+ visited.add(fiber);
23843
+ const alternate=fiber.alternate||null;
23844
+ if(alternate&&(alternate===fiber||alternate.alternate!==fiber||visited.has(alternate)))return null;
23845
+ const pair=alternate?[fiber,alternate]:[fiber];
23846
+ levels.push(pair);
23847
+ if(pair.some(node=>node.stateNode===menus[0]))belowMenu=false;
23848
+ if(belowMenu&&pair.some(node=>node.memoizedProps&&Object.prototype.hasOwnProperty.call(node.memoizedProps,'project')))hasProject=true;
23849
+ const state=fiber.stateNode;
23850
+ if(state&&state.current){
23851
+ if(!pair.includes(state.current)||alternate&&alternate.stateNode!==state)return null;
23852
+ root=state;currentRoot=state.current;break;
23853
+ }
23854
+ }
23855
+ // Older pickers expose the complete path as row text without project metadata.
23856
+ if(!hasProject)return {path:normalize(row.innerText||row.textContent)};
23857
+ if(!root)return null;
23858
+ // A DOM expando can retain an old fiber, including a borrowed current return
23859
+ // chain. Prove every edge through the committed parent's child/sibling list.
23860
+ const currentPath=[currentRoot];const currentVisited=new Set(currentPath);
23861
+ let parent=currentRoot,nodeBudget=2048;
23862
+ for(let depth=levels.length-2;depth>=0;depth--){
23863
+ const candidates=[];const siblings=new Set();
23864
+ for(let child=parent.child;child;child=child.sibling){
23865
+ if(--nodeBudget<0||siblings.has(child))return null;
23866
+ siblings.add(child);
23867
+ if(levels[depth].includes(child))candidates.push(child);
23868
+ }
23869
+ if(candidates.length!==1||currentVisited.has(candidates[0]))return null;
23870
+ parent=candidates[0];currentVisited.add(parent);currentPath.push(parent);
23871
+ }
23872
+ if(parent.stateNode!==row)return null;
23873
+ const menuIndexes=currentPath.flatMap((node,index)=>node.stateNode===menus[0]?[index]:[]);
23874
+ if(menuIndexes.length!==1)return null;
23875
+ const projects=new Set();
23876
+ for(const fiber of currentPath.slice(menuIndexes[0]+1)){
23877
+ const props=fiber.memoizedProps;
23878
+ if(props&&Object.prototype.hasOwnProperty.call(props,'project'))projects.add(props.project);
23879
+ }
23880
+ if(!projects.size)return null;
23881
+ const identities=new Set();
23882
+ for(const project of projects){
23883
+ const identifier=project&&project.workspaceIdentifier;
23884
+ const uri=identifier&&(identifier.uri||identifier.configPath);
23885
+ if(!project||project.remoteAuthority||!identifier||identifier.remoteAuthority||typeof identifier.id!=='string'||!identifier.id.trim()
23886
+ ||!uri||uri.scheme!=='file'||uri.authority||uri.remoteAuthority)return null;
23887
+ const paths=[uri.fsPath,uri._fsPath,uri.path].filter(value=>typeof value==='string'&&value.length).map(normalize);
23888
+ if(!paths.length||paths.some(path=>path!==paths[0]))return null;
23889
+ identities.add(JSON.stringify([identifier.id,paths[0]]));
23890
+ }
23891
+ if(identities.size!==1)return null;
23892
+ const [workspaceId,path]=JSON.parse([...identities][0]);
23893
+ return {path,workspaceId,root,currentRoot};
23894
+ };
23895
+ const matches=rows.map(row=>({row,identity:rowWorkspace(row)})).filter(match=>match.identity&&match.identity.path===wanted);
23734
23896
  if(matches.length!==1)return fail(matches.length?'workspace_project_option_ambiguous':'workspace_project_option_unavailable',{available});
23735
- matches[0].click();
23897
+ const selected=matches[0];
23898
+ if(selected.identity.root&&selected.identity.root.current!==selected.identity.currentRoot)return fail('workspace_project_option_unavailable',{available});
23899
+ selected.row.click();
23736
23900
  await new Promise(resolve=>setTimeout(resolve,350));
23737
23901
  return JSON.stringify({ok:true,state:'workspace_project_selection_requested',workspace:wanted,available});
23738
23902
  })()`;
@@ -23902,7 +24066,11 @@ var REACT_ADAPTER_BODY = `
23902
24066
  let globalSelectAgent=null;
23903
24067
  let globalSelectedAgentId=null;
23904
24068
  let sectionIdByAgentId=null;
23905
- for(const root of document.querySelectorAll('.glass-sidebar-agent-list-container')){
24069
+ const roots=new Set([
24070
+ ...document.querySelectorAll('.glass-sidebar-agent-list-container'),
24071
+ ...document.querySelectorAll('.ui-sidebar-section-head')
24072
+ ]);
24073
+ for(const root of roots){
23906
24074
  const nodes=[]; let n=root;
23907
24075
  for(let i=0;n&&i<24;i++,n=n.parentElement)nodes.push(n);
23908
24076
  for(const node of nodes){
@@ -24021,6 +24189,26 @@ var REACT_ADAPTER_BODY = `
24021
24189
  };
24022
24190
  };
24023
24191
  const a=findAdapter();`;
24192
+ var EXPR_VISIBLE_COMPOSER = `(function(){
24193
+ ${STOP_COMPOSER_BODY}
24194
+ const {modern,composers}=findStopComposers(null);
24195
+ if(composers.length!==1){
24196
+ return JSON.stringify({ok:false,state:composers.length?'ambiguous_composers':'composer_missing',count:composers.length});
24197
+ }
24198
+ const composer=composers[0];
24199
+ let status=composer.dataset.composerStatus||null;
24200
+ if(modern){
24201
+ ${REACT_ADAPTER_BODY}
24202
+ status=modernComposerStatus(composer,a?a.entries():[]);
24203
+ }
24204
+ const composerId=modern?composer.dataset.glassAgentId:composer.dataset.composerId;
24205
+ return JSON.stringify({
24206
+ ok:true,
24207
+ id:'local:'+composerId,
24208
+ composerId,
24209
+ status
24210
+ });
24211
+ })()`;
24024
24212
  var EXPR_AGENT_ADAPTER_READY = `(function(){${REACT_ADAPTER_BODY}return !!a;})()`;
24025
24213
  var EXPR_PAGE_CAPABILITIES = `(function(){${INPUT_PICKER_BODY}
24026
24214
  const visible=node=>!!(node&&(node.offsetParent!==null||(typeof node.getClientRects==='function'&&node.getClientRects().length>0)));
@@ -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.6",
13
+ packageVersion: "0.2.7",
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.6",
3
+ "version": "0.2.7",
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.6"
50
+ "embeddedProductVersion": "6.0.7"
51
51
  }
52
52
  }