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.
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/cursor-bridge.mjs +114 -37
- package/dist/cursor-lifecycle-supervisor.mjs +40 -0
- package/extensions/index.ts +1 -1
- package/package.json +2 -2
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.
|
|
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)
|
package/dist/cursor-bridge.mjs
CHANGED
|
@@ -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 && !
|
|
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 &&
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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 {
|
|
23507
|
-
|
|
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
|
|
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
|
|
23882
|
-
|
|
23883
|
-
for(const
|
|
23884
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
package/extensions/index.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
50
|
+
"embeddedProductVersion": "6.0.9"
|
|
51
51
|
}
|
|
52
52
|
}
|