pi-cursor-bridge 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursor-bridge",
3
- "version": "6.0.6",
3
+ "version": "6.0.8",
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.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.
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.8";
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
  }
@@ -23458,21 +23481,45 @@ function exprClickBoundComposerStop(agentId) {
23458
23481
  }
23459
23482
  var EXPR_FIND_NEWAGENT = `(function(){const b=[...document.querySelectorAll('button,[role=button],a.action-label,.codicon')].find(e=>{if(e.offsetParent===null||e.closest('.glass-sidebar-agent-menu-btn'))return false;const s=(e.getAttribute('aria-label')||'')+' '+(e.getAttribute('title')||'')+' '+(e.innerText||'');return /(?:^|\\s)New (?:Agent|Chat)(?:\\s|$)/i.test(s);});if(!b)return '';const r=b.getBoundingClientRect();return JSON.stringify({x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)});})()`;
23460
23483
  var MODEL_PICKER_VISIBLE_BODY = `
23484
+ ${INPUT_PICKER_BODY}
23461
23485
  const visible=(node)=>!!(node&&(node.offsetParent!==null||(node.getClientRects&&node.getClientRects().length>0)));
23462
- const composers=[...document.querySelectorAll('.composer-bar[data-composer-id],.composer-bar,.ui-prompt-input-root,.agent-prompt-input-root,.ui-prompt-input')].filter(visible);
23463
- const composer=composers[composers.length-1]||document;
23486
+ const inputs=inputCandidates();
23487
+ const ownerSelector='.composer-bar[data-composer-id],.composer-bar,.ui-prompt-input-root,.agent-prompt-input-root,.ui-prompt-input';
23488
+ const composer=inputs.length===1?inputs[0].closest(ownerSelector):null;
23489
+ const triggerSelector='.ui-model-picker__trigger,.vscode-model-picker__trigger';
23490
+ const candidates=composer?[...composer.querySelectorAll(triggerSelector)]
23491
+ .filter(node=>visible(node)&&node.closest(ownerSelector)===composer):[];
23492
+ const trigger=candidates.length===1?candidates[0]:null;
23493
+ const shell=inputs.length===1?inputs[0].closest('[data-agent-panel-conversation-shell][data-glass-agent-id]'):null;
23494
+ const owner=trigger?{triggerId:trigger.getAttribute('id'),composerId:composer.getAttribute('data-composer-id'),agentId:shell&&shell.getAttribute('data-glass-agent-id')}:null;
23464
23495
  `;
23465
23496
  var EXPR_MODEL_PICKER_TRIGGER = `(function(){
23466
23497
  ${MODEL_PICKER_VISIBLE_BODY}
23467
- const triggerSelector='.ui-model-picker__trigger,.vscode-model-picker__trigger';
23468
- const candidates=[...composer.querySelectorAll(triggerSelector)].filter(visible);
23469
- const trigger=candidates[candidates.length-1]||[...document.querySelectorAll(triggerSelector)].filter(visible).pop();
23470
- if(!trigger)return JSON.stringify({found:false,state:'trigger_missing'});
23498
+ if(!trigger)return JSON.stringify({found:false,state:inputs.length!==1?'input_ambiguous':!composer?'composer_missing':candidates.length>1?'trigger_ambiguous':'trigger_missing',inputCount:inputs.length,triggerCount:candidates.length});
23471
23499
  const rect=trigger.getBoundingClientRect();
23472
23500
  const text=String(trigger.querySelector('.ui-model-picker__trigger-text,.vscode-model-picker__trigger-text')?.innerText||trigger.innerText||'').replace(/\\s+/g,' ').trim();
23473
23501
  const detail=String(trigger.querySelector('.ui-model-picker__trigger-variant-suffix,.vscode-model-picker__trigger-variant-suffix')?.innerText||'').replace(/\\s+/g,' ').trim();
23474
- return JSON.stringify({found:true,state:'ready',text,detail,x:Math.round(rect.x+rect.width/2),y:Math.round(rect.y+rect.height/2)});
23502
+ const x=Math.round(rect.x+rect.width/2),y=Math.round(rect.y+rect.height/2);
23503
+ let state='ready';
23504
+ if(trigger.disabled||trigger.getAttribute('aria-disabled')==='true'||trigger.closest('[inert]')||getComputedStyle(trigger).pointerEvents==='none')state='trigger_disabled';
23505
+ 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});
23475
23508
  })()`;
23509
+ function exprActivateClosedModelPicker(expected) {
23510
+ return `(function(){
23511
+ const expected=${JSON.stringify(expected)};
23512
+ const current=JSON.parse(${EXPR_MODEL_PICKER_TRIGGER});
23513
+ if(!current.found||current.interactive!==true||current.expanded!=='false')return JSON.stringify({clicked:false,state:'trigger_not_closed_and_interactive'});
23514
+ if(!current.triggerId||['triggerId','composerId','agentId','x','y'].some(key=>(current[key]??null)!==(expected[key]??null)))return JSON.stringify({clicked:false,state:'trigger_changed'});
23515
+ ${MODEL_PICKER_VISIBLE_BODY}
23516
+ if(!trigger||trigger.getAttribute('id')!==current.triggerId)return JSON.stringify({clicked:false,state:'trigger_changed'});
23517
+ // Use the same button's normal click handler after a native click failed
23518
+ // to expand it. The closed-state and hit checks occur in this same turn.
23519
+ trigger.click();
23520
+ return JSON.stringify({clicked:true,state:'closed_trigger_activated',owner});
23521
+ })()`;
23522
+ }
23476
23523
  function classifyModelPickerRowKind(text, hasItemName, menuTestId, submenuTestId, ariaHaspopup, hasParamCheck, inSubmenu) {
23477
23524
  const menu = String(menuTestId || "").toLowerCase();
23478
23525
  const submenu = String(submenuTestId || "").toLowerCase();
@@ -23489,7 +23536,32 @@ function classifyModelPickerRowKind(text, hasItemName, menuTestId, submenuTestId
23489
23536
  var EXPR_MODEL_PICKER_ROWS = `(function(){
23490
23537
  ${MODEL_PICKER_VISIBLE_BODY}
23491
23538
  ${classifyModelPickerRowKind.toString()}
23492
- const menus=[...document.querySelectorAll('[data-testid="model-picker-menu"],[data-testid="selected-auto-menu"],[data-testid*="model-parameters"],[data-testid*="parameter-submenu"],[data-component="menu-popup"][data-submenu]')].filter(visible);
23539
+ const visibleMenus=[...document.querySelectorAll('[data-testid="model-picker-menu"],[data-testid="selected-auto-menu"],[data-testid*="model-parameters"],[data-testid*="parameter-submenu"],[data-component="menu-popup"][data-submenu]')].filter(visible);
23540
+ const menus=[];
23541
+ if(trigger){
23542
+ // Modern menus are portalled. Follow the exact trigger's accessibility
23543
+ // links, including submenu triggers, instead of adopting another picker.
23544
+ const ids=new Set(),controls=new Set();
23545
+ const link=node=>{
23546
+ const id=node.getAttribute('id');if(id)ids.add(id);
23547
+ for(const id of String(node.getAttribute('aria-controls')||'').split(/\\s+/).filter(Boolean))controls.add(id);
23548
+ };
23549
+ link(trigger);
23550
+ for(let pass=0;pass<visibleMenus.length;pass++){
23551
+ let changed=false;
23552
+ for(const menu of visibleMenus){
23553
+ if(menus.includes(menu))continue;
23554
+ const id=menu.getAttribute('id'),labelledBy=String(menu.getAttribute('aria-labelledby')||'').split(/\\s+/).filter(Boolean);
23555
+ if(!(id&&controls.has(id))&&!labelledBy.some(id=>ids.has(id)))continue;
23556
+ menus.push(menu);link(menu);
23557
+ for(const node of menu.querySelectorAll('[id],[aria-controls]'))link(node);
23558
+ changed=true;
23559
+ }
23560
+ if(!changed)break;
23561
+ }
23562
+ if(!ids.size&&!controls.size&&visibleMenus.length===1
23563
+ &&[...document.querySelectorAll(triggerSelector)].filter(visible).length===1)menus.push(visibleMenus[0]);
23564
+ }
23493
23565
  const rows=[];
23494
23566
  const seen=new Set();
23495
23567
  for(const menu of menus){
@@ -23524,8 +23596,11 @@ var EXPR_MODEL_PICKER_ROWS = `(function(){
23524
23596
  });
23525
23597
  }
23526
23598
  }
23527
- return JSON.stringify({open:menus.length>0,rows});
23599
+ return JSON.stringify({open:menus.length>0,rows,owner});
23528
23600
  })()`;
23601
+ function modelPickerOwnerKey(owner) {
23602
+ return owner && JSON.stringify([owner.triggerId || null, owner.composerId || null, owner.agentId || null]);
23603
+ }
23529
23604
  var EXPR_SELECTED_AGENT_MODEL_CONFIG = `(function(){
23530
23605
  ${INPUT_PICKER_BODY}
23531
23606
  const inputs=inputCandidates();
@@ -23540,12 +23615,90 @@ var EXPR_SELECTED_AGENT_MODEL_CONFIG = `(function(){
23540
23615
  if(data&&data.modelConfig&&!configs.includes(data.modelConfig))configs.push(data.modelConfig);
23541
23616
  }
23542
23617
  }
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
- }))});
23618
+ if(configs.length>1)return JSON.stringify({found:false,state:'model_config_ambiguous',configCount:configs.length});
23619
+ if(configs.length===1){
23620
+ const config=configs[0];
23621
+ return JSON.stringify({found:true,modelName:String(config.modelName||''),selectedModels:(config.selectedModels||[]).map(model=>({
23622
+ modelId:String(model&&model.modelId||''),
23623
+ parameters:Object.fromEntries((model&&model.parameters||[]).map(parameter=>[String(parameter&&parameter.id||''),String(parameter&&parameter.value||'')]))
23624
+ }))});
23625
+ }
23626
+ // Cursor 3.23's IDE input is Solid; its model trigger is a mounted React
23627
+ // picker whose initialSelections/initialAutoMode come from this composer.
23628
+ const source='legacy_composer_model_trigger';
23629
+ const fail=(state)=>JSON.stringify({found:false,state,source});
23630
+ const input=inputs[0],composer=input.closest('.composer-bar[data-composer-id]');
23631
+ if(!composer||input.closest('.composer-bar')!==composer
23632
+ ||composer.parentElement&&composer.parentElement.closest('.composer-bar')
23633
+ ||composer.querySelectorAll('.composer-bar').length)return fail('legacy_composer_ambiguous');
23634
+ const composerId=composer.getAttribute('data-composer-id');
23635
+ const owners=[...document.querySelectorAll('.composer-bar[data-composer-id]')]
23636
+ .filter(node=>node.getAttribute('data-composer-id')===composerId);
23637
+ if(typeof composerId!=='string'||!composerId.trim()||owners.length!==1||owners[0]!==composer)return fail('legacy_composer_ambiguous');
23638
+ const triggers=[...composer.querySelectorAll('.vscode-model-picker__trigger')];
23639
+ if(triggers.length!==1||!triggers[0].classList.contains('vscode-model-picker__trigger')
23640
+ ||triggers[0].closest('.composer-bar')!==composer)return fail('legacy_model_trigger_ambiguous');
23641
+ const trigger=triggers[0],keys=Object.keys(trigger).filter(key=>key.startsWith('__reactFiber$'));
23642
+ if(keys.length!==1)return fail('legacy_model_tree_unconfirmed');
23643
+ const levels=[],visited=new Set();
23644
+ let root=null,currentRoot=null;
23645
+ for(let fiber=trigger[keys[0]];fiber;fiber=fiber.return){
23646
+ if(levels.length>=256||visited.has(fiber))return fail('legacy_model_tree_unconfirmed');
23647
+ const alternate=fiber.alternate||null;
23648
+ if(alternate&&(alternate===fiber||alternate.alternate!==fiber||visited.has(alternate)))return fail('legacy_model_tree_unconfirmed');
23649
+ visited.add(fiber);if(alternate)visited.add(alternate);
23650
+ const pair=alternate?[fiber,alternate]:[fiber];
23651
+ levels.push(pair);
23652
+ const state=fiber.stateNode;
23653
+ if(state&&state.current){
23654
+ if(fiber.tag!==3||fiber.return||!pair.includes(state.current)||alternate&&(alternate.tag!==3||alternate.stateNode!==state))return fail('legacy_model_tree_unconfirmed');
23655
+ root=state;currentRoot=state.current;break;
23656
+ }
23657
+ }
23658
+ if(!root)return fail('legacy_model_tree_unconfirmed');
23659
+ // DOM expandos may retain an old fiber or a borrowed return chain. Each
23660
+ // edge must belong to the committed parent's actual child/sibling list.
23661
+ const currentPath=[currentRoot],currentVisited=new Set(currentPath);
23662
+ let parent=currentRoot,nodeBudget=2048;
23663
+ for(let depth=levels.length-2;depth>=0;depth--){
23664
+ const candidates=[],siblings=new Set();
23665
+ for(let child=parent.child;child;child=child.sibling){
23666
+ if(--nodeBudget<0||siblings.has(child))return fail('legacy_model_tree_unconfirmed');
23667
+ siblings.add(child);
23668
+ if(levels[depth].includes(child))candidates.push(child);
23669
+ }
23670
+ if(candidates.length!==1||currentVisited.has(candidates[0]))return fail('legacy_model_tree_unconfirmed');
23671
+ parent=candidates[0];currentVisited.add(parent);currentPath.push(parent);
23672
+ }
23673
+ if(parent.stateNode!==trigger)return fail('legacy_model_tree_unconfirmed');
23674
+ const snapshots=new Set();
23675
+ for(const fiber of currentPath){
23676
+ const props=fiber.memoizedProps;
23677
+ if(!props||!Object.prototype.hasOwnProperty.call(props,'initialSelections')
23678
+ &&!Object.prototype.hasOwnProperty.call(props,'initialAutoMode'))continue;
23679
+ if(!Object.prototype.hasOwnProperty.call(props,'initialSelections')||!Object.prototype.hasOwnProperty.call(props,'initialAutoMode')
23680
+ ||!Array.isArray(props.initialSelections)||typeof props.initialAutoMode!=='boolean')return fail('legacy_model_schema_unconfirmed');
23681
+ // Auto is never evidence for a named model, even if stale selections remain.
23682
+ if(props.initialAutoMode)return fail('legacy_model_auto');
23683
+ if(props.initialSelections.length!==1)return fail('legacy_model_selection_ambiguous');
23684
+ const selected=props.initialSelections[0];
23685
+ if(!selected||typeof selected.modelId!=='string'||!selected.modelId.trim()
23686
+ ||selected.modelId!==selected.modelId.trim()||selected.count!==1||!Array.isArray(selected.parameters))return fail('legacy_model_schema_unconfirmed');
23687
+ if(selected.modelId.toLowerCase()==='default')return fail('legacy_model_auto');
23688
+ const parameters=[];
23689
+ for(const parameter of selected.parameters){
23690
+ if(!parameter||typeof parameter.id!=='string'||!parameter.id.trim()||parameter.id!==parameter.id.trim()
23691
+ ||typeof parameter.value!=='string'||!parameter.value.length||parameters.some(entry=>entry[0]===parameter.id))return fail('legacy_model_schema_unconfirmed');
23692
+ parameters.push([parameter.id,parameter.value]);
23693
+ }
23694
+ parameters.sort((a,b)=>a[0]<b[0]?-1:a[0]>b[0]?1:0);
23695
+ snapshots.add(JSON.stringify({modelName:selected.modelId,selectedModels:[{modelId:selected.modelId,parameters:Object.fromEntries(parameters)}]}));
23696
+ }
23697
+ if(!snapshots.size)return fail('legacy_model_schema_unconfirmed');
23698
+ if(snapshots.size!==1)return fail('legacy_model_config_ambiguous');
23699
+ const snapshot=JSON.parse([...snapshots][0]);
23700
+ if(root.current!==currentRoot)return fail('legacy_model_tree_unconfirmed');
23701
+ return JSON.stringify({found:true,...snapshot,source});
23549
23702
  })()`;
23550
23703
  function normalizeModelPickerText(value) {
23551
23704
  return String(value || "").trim().toLowerCase().replace(/extra[\s_-]*high/g, "xhigh").replace(/[^a-z0-9]+/g, "");
@@ -23709,30 +23862,93 @@ function matchSelectedAgentModelConfig(snapshot, requestedModel, requestedEffort
23709
23862
  return { modelId: match.modelId, effort: effort || null };
23710
23863
  }
23711
23864
  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();
23865
+ return String.raw`(async function(){
23866
+ const normalize=value=>String(value||'').replace(/\\/g,'/').replace(/^\/([a-z]:\/)/i,'$1').replace(/\/+$/,'').toLowerCase();
23867
+ const wanted=normalize(${JSON.stringify(String(projectPath || ""))});
23715
23868
  const visible=node=>!!(node&&(node.offsetParent!==null||(node.getClientRects&&node.getClientRects().length>0)));
23716
23869
  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)));
23870
+ .filter(visible).filter(node=>/^[a-z]:\//i.test(normalize(node.innerText||node.textContent)));
23718
23871
  const triggers=pathTriggers();
23719
23872
  const fail=(state,extra={})=>JSON.stringify({ok:false,state,wanted,...extra,
23720
23873
  nextStep:'Select the exact local workspace '+${JSON.stringify(String(projectPath || ""))}+' in the new Agent project picker before retrying.'});
23721
23874
  if(triggers.length!==1)return fail(triggers.length?'workspace_project_selector_ambiguous':'workspace_project_selector_unavailable',{triggerCount:triggers.length});
23722
23875
  triggers[0].click();
23723
23876
  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"]'));
23877
+ const menus=[...new Set([...document.querySelectorAll('[data-component="menu-popup"],[role="menu"]')].filter(visible)
23878
+ .map(menu=>menu.getAttribute('role')==='menu'&&menu.getAttribute('aria-label')==='Select a project'
23879
+ ?menu:menu.querySelector('[role="menu"][aria-label="Select a project"]')).filter(visible))];
23880
+ if(menus.length!==1)return fail(menus.length?'workspace_project_option_ambiguous':'workspace_project_option_unavailable',{menuCount:menus.length});
23726
23881
  const rows=[];const seen=new Set();
23727
23882
  for(const menu of menus){
23728
23883
  for(const row of menu.querySelectorAll('[data-component="menu-row"][role="menuitem"],[role="option"]')){
23729
23884
  if(!visible(row)||seen.has(row))continue;seen.add(row);rows.push(row);
23730
23885
  }
23731
23886
  }
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);
23887
+ const available=rows.map(row=>String(row.innerText||row.textContent||'').replace(/\s+/g,' ').trim());
23888
+ const rowWorkspace=row=>{
23889
+ const key=Object.keys(row).find(key=>key.startsWith('__reactFiber$'));
23890
+ const levels=[];const visited=new Set();
23891
+ let root=null,currentRoot=null,hasProject=false,belowMenu=true;
23892
+ for(let fiber=key&&row[key];fiber;fiber=fiber.return){
23893
+ if(levels.length>=256||visited.has(fiber))return null;
23894
+ visited.add(fiber);
23895
+ const alternate=fiber.alternate||null;
23896
+ if(alternate&&(alternate===fiber||alternate.alternate!==fiber||visited.has(alternate)))return null;
23897
+ const pair=alternate?[fiber,alternate]:[fiber];
23898
+ levels.push(pair);
23899
+ if(pair.some(node=>node.stateNode===menus[0]))belowMenu=false;
23900
+ if(belowMenu&&pair.some(node=>node.memoizedProps&&Object.prototype.hasOwnProperty.call(node.memoizedProps,'project')))hasProject=true;
23901
+ const state=fiber.stateNode;
23902
+ if(state&&state.current){
23903
+ if(!pair.includes(state.current)||alternate&&alternate.stateNode!==state)return null;
23904
+ root=state;currentRoot=state.current;break;
23905
+ }
23906
+ }
23907
+ // Older pickers expose the complete path as row text without project metadata.
23908
+ if(!hasProject)return {path:normalize(row.innerText||row.textContent)};
23909
+ if(!root)return null;
23910
+ // A DOM expando can retain an old fiber, including a borrowed current return
23911
+ // chain. Prove every edge through the committed parent's child/sibling list.
23912
+ const currentPath=[currentRoot];const currentVisited=new Set(currentPath);
23913
+ let parent=currentRoot,nodeBudget=2048;
23914
+ for(let depth=levels.length-2;depth>=0;depth--){
23915
+ const candidates=[];const siblings=new Set();
23916
+ for(let child=parent.child;child;child=child.sibling){
23917
+ if(--nodeBudget<0||siblings.has(child))return null;
23918
+ siblings.add(child);
23919
+ if(levels[depth].includes(child))candidates.push(child);
23920
+ }
23921
+ if(candidates.length!==1||currentVisited.has(candidates[0]))return null;
23922
+ parent=candidates[0];currentVisited.add(parent);currentPath.push(parent);
23923
+ }
23924
+ if(parent.stateNode!==row)return null;
23925
+ const menuIndexes=currentPath.flatMap((node,index)=>node.stateNode===menus[0]?[index]:[]);
23926
+ if(menuIndexes.length!==1)return null;
23927
+ const projects=new Set();
23928
+ for(const fiber of currentPath.slice(menuIndexes[0]+1)){
23929
+ const props=fiber.memoizedProps;
23930
+ if(props&&Object.prototype.hasOwnProperty.call(props,'project'))projects.add(props.project);
23931
+ }
23932
+ if(!projects.size)return null;
23933
+ const identities=new Set();
23934
+ for(const project of projects){
23935
+ const identifier=project&&project.workspaceIdentifier;
23936
+ const uri=identifier&&(identifier.uri||identifier.configPath);
23937
+ if(!project||project.remoteAuthority||!identifier||identifier.remoteAuthority||typeof identifier.id!=='string'||!identifier.id.trim()
23938
+ ||!uri||uri.scheme!=='file'||uri.authority||uri.remoteAuthority)return null;
23939
+ const paths=[uri.fsPath,uri._fsPath,uri.path].filter(value=>typeof value==='string'&&value.length).map(normalize);
23940
+ if(!paths.length||paths.some(path=>path!==paths[0]))return null;
23941
+ identities.add(JSON.stringify([identifier.id,paths[0]]));
23942
+ }
23943
+ if(identities.size!==1)return null;
23944
+ const [workspaceId,path]=JSON.parse([...identities][0]);
23945
+ return {path,workspaceId,root,currentRoot};
23946
+ };
23947
+ const matches=rows.map(row=>({row,identity:rowWorkspace(row)})).filter(match=>match.identity&&match.identity.path===wanted);
23734
23948
  if(matches.length!==1)return fail(matches.length?'workspace_project_option_ambiguous':'workspace_project_option_unavailable',{available});
23735
- matches[0].click();
23949
+ const selected=matches[0];
23950
+ if(selected.identity.root&&selected.identity.root.current!==selected.identity.currentRoot)return fail('workspace_project_option_unavailable',{available});
23951
+ selected.row.click();
23736
23952
  await new Promise(resolve=>setTimeout(resolve,350));
23737
23953
  return JSON.stringify({ok:true,state:'workspace_project_selection_requested',workspace:wanted,available});
23738
23954
  })()`;
@@ -23902,7 +24118,11 @@ var REACT_ADAPTER_BODY = `
23902
24118
  let globalSelectAgent=null;
23903
24119
  let globalSelectedAgentId=null;
23904
24120
  let sectionIdByAgentId=null;
23905
- for(const root of document.querySelectorAll('.glass-sidebar-agent-list-container')){
24121
+ const roots=new Set([
24122
+ ...document.querySelectorAll('.glass-sidebar-agent-list-container'),
24123
+ ...document.querySelectorAll('.ui-sidebar-section-head')
24124
+ ]);
24125
+ for(const root of roots){
23906
24126
  const nodes=[]; let n=root;
23907
24127
  for(let i=0;n&&i<24;i++,n=n.parentElement)nodes.push(n);
23908
24128
  for(const node of nodes){
@@ -24021,6 +24241,26 @@ var REACT_ADAPTER_BODY = `
24021
24241
  };
24022
24242
  };
24023
24243
  const a=findAdapter();`;
24244
+ var EXPR_VISIBLE_COMPOSER = `(function(){
24245
+ ${STOP_COMPOSER_BODY}
24246
+ const {modern,composers}=findStopComposers(null);
24247
+ if(composers.length!==1){
24248
+ return JSON.stringify({ok:false,state:composers.length?'ambiguous_composers':'composer_missing',count:composers.length});
24249
+ }
24250
+ const composer=composers[0];
24251
+ let status=composer.dataset.composerStatus||null;
24252
+ if(modern){
24253
+ ${REACT_ADAPTER_BODY}
24254
+ status=modernComposerStatus(composer,a?a.entries():[]);
24255
+ }
24256
+ const composerId=modern?composer.dataset.glassAgentId:composer.dataset.composerId;
24257
+ return JSON.stringify({
24258
+ ok:true,
24259
+ id:'local:'+composerId,
24260
+ composerId,
24261
+ status
24262
+ });
24263
+ })()`;
24024
24264
  var EXPR_AGENT_ADAPTER_READY = `(function(){${REACT_ADAPTER_BODY}return !!a;})()`;
24025
24265
  var EXPR_PAGE_CAPABILITIES = `(function(){${INPUT_PICKER_BODY}
24026
24266
  const visible=node=>!!(node&&(node.offsetParent!==null||(typeof node.getClientRects==='function'&&node.getClientRects().length>0)));
@@ -25655,7 +25895,7 @@ var CursorBridge = class {
25655
25895
  }
25656
25896
  async _readModelPickerRows(c, options) {
25657
25897
  const snapshot = await this._readModelPickerValue(c, EXPR_MODEL_PICKER_ROWS, "rows", options);
25658
- return { open: snapshot.open === true, rows: Array.isArray(snapshot.rows) ? snapshot.rows : [] };
25898
+ return { open: snapshot.open === true, rows: Array.isArray(snapshot.rows) ? snapshot.rows : [], owner: snapshot.owner || null };
25659
25899
  }
25660
25900
  async _readSelectedAgentModelConfig(c, options) {
25661
25901
  return this._readModelPickerValue(c, EXPR_SELECTED_AGENT_MODEL_CONFIG, "selected_agent_model_config", options);
@@ -25673,19 +25913,67 @@ var CursorBridge = class {
25673
25913
  if (!point || !Number.isFinite(Number(point.x)) || !Number.isFinite(Number(point.y))) return;
25674
25914
  await c.send("Input.dispatchMouseEvent", { type: "mouseMoved", x: Number(point.x), y: Number(point.y) });
25675
25915
  }
25676
- async _openModelPicker(c) {
25677
- const trigger = await this._readModelPickerTrigger(c);
25678
- if (!trigger.found) {
25679
- throw new Error("Cursor model picker is unavailable in the active Agent composer");
25680
- }
25681
- let snapshot = await this._readModelPickerRows(c);
25682
- if (!snapshot.open) {
25683
- await this._clickModelPickerPoint(c, trigger);
25684
- await sleep2(450);
25685
- snapshot = await this._readModelPickerRows(c);
25686
- }
25687
- if (!snapshot.open) throw new Error("Cursor model picker did not open");
25688
- return { trigger, ...snapshot };
25916
+ async _activateClosedModelPicker(c, trigger, options) {
25917
+ return this._readModelPickerValue(c, exprActivateClosedModelPicker(trigger), "closed_trigger_activation", options);
25918
+ }
25919
+ async _openModelPicker(c, job = null, options = {}) {
25920
+ const timeoutMs = Math.max(0, Number(options.timeoutMs ?? 2e3));
25921
+ const pollMs = Math.max(10, Number(options.pollMs ?? 50));
25922
+ const stableMs = Math.max(0, Number(options.stableMs ?? 100));
25923
+ const recoveryDelayMs = Math.max(0, Number(options.recoveryDelayMs ?? 750));
25924
+ const deadline = Date.now() + timeoutMs;
25925
+ let trigger = null, snapshot = { open: false, rows: [] };
25926
+ let stableSignature = null, stableSince = 0, clicked = false, clickedOwner = null;
25927
+ let clickedAt = 0, recoveryAttempted = false, lastPollError = null;
25928
+ const attempts = [];
25929
+ do {
25930
+ this._throwIfCancelledBeforeSend(job);
25931
+ if (deadline - Date.now() < 10) break;
25932
+ try {
25933
+ snapshot = await this._readModelPickerRows(c, { timeoutMs: deadline - Date.now() });
25934
+ if (deadline - Date.now() < 10) break;
25935
+ trigger = await this._readModelPickerTrigger(c, { timeoutMs: deadline - Date.now() });
25936
+ } catch (error2) {
25937
+ if (error2.code !== "CDP_COMMAND_TIMEOUT" || Date.now() < deadline) throw error2;
25938
+ lastPollError = error2.pickerRead || { code: error2.code, message: error2.message };
25939
+ break;
25940
+ }
25941
+ this._throwIfCancelledBeforeSend(job);
25942
+ const sameOwner = modelPickerOwnerKey(snapshot.owner) === modelPickerOwnerKey(trigger);
25943
+ if (snapshot.open && trigger.found && sameOwner && (!clicked || clickedOwner === modelPickerOwnerKey(trigger))) return { trigger, ...snapshot };
25944
+ if (snapshot.open && !sameOwner && !attempts.includes("owner_changed")) attempts.push("owner_changed");
25945
+ if (!clicked) {
25946
+ const interactive = trigger.found && trigger.interactive !== false;
25947
+ const signature = interactive ? JSON.stringify([trigger.triggerId, trigger.composerId, trigger.agentId, trigger.x, trigger.y]) : null;
25948
+ if (!interactive || signature !== stableSignature) {
25949
+ stableSignature = signature;
25950
+ stableSince = Date.now();
25951
+ const state = trigger.state || (interactive ? "ready" : "trigger_missing");
25952
+ if (!attempts.includes(state)) attempts.push(state);
25953
+ }
25954
+ if (interactive && Date.now() - stableSince >= stableMs) {
25955
+ this._throwIfCancelledBeforeSend(job);
25956
+ await this._clickModelPickerPoint(c, trigger);
25957
+ clicked = true;
25958
+ clickedAt = Date.now();
25959
+ clickedOwner = modelPickerOwnerKey(trigger);
25960
+ attempts.push("click_once", "wait_menu");
25961
+ }
25962
+ } else if (!recoveryAttempted && !snapshot.open && sameOwner && clickedOwner === modelPickerOwnerKey(trigger) && trigger.interactive === true && trigger.expanded === "false" && Date.now() - clickedAt >= recoveryDelayMs && deadline - Date.now() >= 10) {
25963
+ this._throwIfCancelledBeforeSend(job);
25964
+ recoveryAttempted = true;
25965
+ const recovered = await this._activateClosedModelPicker(c, trigger, { timeoutMs: deadline - Date.now() });
25966
+ attempts.push(recovered.clicked ? "activate_confirmed_closed_trigger" : recovered.state || "activation_rejected");
25967
+ }
25968
+ if (Date.now() >= deadline) break;
25969
+ await sleep2(Math.min(pollMs, Math.max(0, deadline - Date.now())));
25970
+ } while (Date.now() < deadline);
25971
+ throw createModelSelectionError("Cursor model picker did not open", "picker_did_not_open", true, {
25972
+ attempts,
25973
+ trigger,
25974
+ lastPollError,
25975
+ menu: { open: snapshot.open, rows: (snapshot.rows || []).slice(0, 20) }
25976
+ });
25689
25977
  }
25690
25978
  async _closeModelPicker(c) {
25691
25979
  for (let attempt = 0; attempt < 3; attempt++) {
@@ -25697,24 +25985,29 @@ var CursorBridge = class {
25697
25985
  }
25698
25986
  if ((await this._readModelPickerRows(c)).open) throw new Error("Cursor model picker did not close after selection");
25699
25987
  }
25700
- async _openModelPickerControl(c, snapshot, controlKind) {
25988
+ async _openModelPickerControl(c, snapshot, controlKind, job = null) {
25989
+ this._throwIfCancelledBeforeSend(job);
25701
25990
  const control = (snapshot && snapshot.rows || []).find((row) => row.kind === controlKind && row.disabled !== true);
25702
25991
  if (!control) return snapshot;
25992
+ this._throwIfCancelledBeforeSend(job);
25703
25993
  await this._clickModelPickerPoint(c, control);
25704
25994
  await sleep2(400);
25705
25995
  let next = await this._readModelPickerRows(c);
25706
25996
  const expectedKind = controlKind === "model_control" ? "model" : "parameter";
25707
25997
  if (!next.rows.some((row) => row.kind === expectedKind)) {
25998
+ this._throwIfCancelledBeforeSend(job);
25708
25999
  await this._hoverModelPickerPoint(c, control);
25709
26000
  await sleep2(350);
25710
26001
  next = await this._readModelPickerRows(c);
25711
26002
  }
25712
26003
  return next;
25713
26004
  }
25714
- async _findModelPickerModel(c, snapshot, requestedModel) {
26005
+ async _findModelPickerModel(c, snapshot, requestedModel, job = null) {
26006
+ this._throwIfCancelledBeforeSend(job);
25715
26007
  let modelRow = selectModelPickerRow(snapshot && snapshot.rows, requestedModel, "model");
25716
26008
  if (modelRow) return { snapshot, modelRow };
25717
- const expanded = await this._openModelPickerControl(c, snapshot, "model_control");
26009
+ const expanded = await this._openModelPickerControl(c, snapshot, "model_control", job);
26010
+ this._throwIfCancelledBeforeSend(job);
25718
26011
  modelRow = selectModelPickerRow(expanded && expanded.rows, requestedModel, "model");
25719
26012
  return { snapshot: expanded, modelRow };
25720
26013
  }
@@ -25859,9 +26152,9 @@ var CursorBridge = class {
25859
26152
  if (job) job.modelSelection = result2;
25860
26153
  return result2;
25861
26154
  }
25862
- const opened = await this._openModelPicker(c);
26155
+ const opened = await this._openModelPicker(c, job);
25863
26156
  stage = "locate_model";
25864
- let located = await this._findModelPickerModel(c, opened, requestedModel);
26157
+ let located = await this._findModelPickerModel(c, opened, requestedModel, job);
25865
26158
  modelRow = located.modelRow;
25866
26159
  if (!modelRow) {
25867
26160
  throw createModelSelectionError(
@@ -25877,8 +26170,8 @@ var CursorBridge = class {
25877
26170
  if (!outcome.row && outcome.state === "not_rendered" && !effortPickerReopened) {
25878
26171
  effortPickerReopened = true;
25879
26172
  await this._closeModelPicker(c);
25880
- const reopened = await this._openModelPicker(c);
25881
- located = await this._findModelPickerModel(c, reopened, requestedModel);
26173
+ const reopened = await this._openModelPicker(c, job);
26174
+ located = await this._findModelPickerModel(c, reopened, requestedModel, job);
25882
26175
  modelRow = located.modelRow;
25883
26176
  if (!modelRow) {
25884
26177
  throw createModelSelectionError(
@@ -25921,8 +26214,8 @@ var CursorBridge = class {
25921
26214
  this._throwIfCancelledBeforeSend(job);
25922
26215
  await this._clickModelPickerPoint(c, modelRow);
25923
26216
  await sleep2(550);
25924
- const reopened = await this._openModelPicker(c);
25925
- located = await this._findModelPickerModel(c, reopened, requestedModel);
26217
+ const reopened = await this._openModelPicker(c, job);
26218
+ located = await this._findModelPickerModel(c, reopened, requestedModel, job);
25926
26219
  modelRow = located.modelRow;
25927
26220
  if (!modelRow) {
25928
26221
  throw createModelSelectionError(
@@ -25949,8 +26242,8 @@ var CursorBridge = class {
25949
26242
  stage = "verify_model";
25950
26243
  let trigger2 = await this._readModelPickerTrigger(c);
25951
26244
  if (!trigger2.found || !normalizeModelPickerModelText(trigger2.text).includes(normalizeModelPickerModelText(requestedModel))) {
25952
- const reopened = await this._openModelPicker(c);
25953
- located = await this._findModelPickerModel(c, reopened, requestedModel);
26245
+ const reopened = await this._openModelPicker(c, job);
26246
+ located = await this._findModelPickerModel(c, reopened, requestedModel, job);
25954
26247
  const selected = selectModelPickerRow(located.snapshot.rows.filter((row) => row.selected), requestedModel, "model");
25955
26248
  if (!selected) {
25956
26249
  throw createModelSelectionError(
@@ -25963,8 +26256,8 @@ var CursorBridge = class {
25963
26256
  }
25964
26257
  if (requestedEffort) {
25965
26258
  stage = "verify_effort";
25966
- const reopened = await this._openModelPicker(c);
25967
- located = await this._findModelPickerModel(c, reopened, requestedModel);
26259
+ const reopened = await this._openModelPicker(c, job);
26260
+ located = await this._findModelPickerModel(c, reopened, requestedModel, job);
25968
26261
  modelRow = located.modelRow;
25969
26262
  if (!modelRow) {
25970
26263
  throw createModelSelectionError(
@@ -26019,6 +26312,8 @@ var CursorBridge = class {
26019
26312
  errorCode: primaryError.code || `CURSOR_MODEL_${String(failure.failureClass).toUpperCase()}`,
26020
26313
  available: failure.available || [],
26021
26314
  attempts: failure.attempts || [],
26315
+ trigger: failure.trigger || null,
26316
+ lastPollError: failure.lastPollError || null,
26022
26317
  menu: failure.menu || null,
26023
26318
  runtimeMode: this.runtimeMode,
26024
26319
  lastError: primaryError.message,
@@ -28106,6 +28401,7 @@ export {
28106
28401
  createChatPanelUnavailableError,
28107
28402
  createProviderError,
28108
28403
  cursorStartupBehavior,
28404
+ exprActivateClosedModelPicker,
28109
28405
  exprClickBoundComposerStop,
28110
28406
  exprClickSelectedAgentStop,
28111
28407
  exprCreateAgentForWorkspace,
@@ -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.8",
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.8",
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.8"
51
51
  }
52
52
  }