pi-cursor-bridge 0.1.2 → 0.1.4

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.
@@ -11025,15 +11025,15 @@ function writeWorkspaceBinding(filePath, bindingKey, projectPath, options = {})
11025
11025
  const key = String(bindingKey || "").trim();
11026
11026
  if (!key) throw new Error("cursor_init could not identify the current Codex or Claude Code workspace session");
11027
11027
  if (!isAbsoluteWorkspacePath(projectPath)) {
11028
- throw new Error("\u8BF7\u63D0\u4F9B\u9879\u76EE\u7684\u5B8C\u6574\u8DEF\u5F84\uFF0C\u4F8B\u5982 C:\\Projects\\my-app \u6216 /Users/me/Projects/my-app");
11028
+ throw new Error("Provide an absolute project path, for example C:\\Projects\\my-app or /Users/me/Projects/my-app");
11029
11029
  }
11030
11030
  const normalized = normalizeWorkspacePath(projectPath);
11031
11031
  const existsImpl = options.existsImpl || existsSync;
11032
11032
  if (!normalized || !existsImpl(normalized)) {
11033
- throw new Error(`\u627E\u4E0D\u5230\u5DE5\u4F5C\u533A\uFF1A${normalized || projectPath}`);
11033
+ throw new Error(`Workspace not found: ${normalized || projectPath}`);
11034
11034
  }
11035
11035
  if (!isWorkspaceTarget(normalized, options)) {
11036
- throw new Error("\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u9879\u76EE\u6587\u4EF6\u5939\u6216 .code-workspace \u6587\u4EF6");
11036
+ throw new Error("The workspace must be a project directory or a .code-workspace file");
11037
11037
  }
11038
11038
  const state = readWorkspaceBindings(filePath);
11039
11039
  const updatedAt = options.updatedAt || (/* @__PURE__ */ new Date()).toISOString();
@@ -11351,8 +11351,8 @@ async function ensureCursorRunningLocal(options = {}) {
11351
11351
  windowGuard: windowGuard2,
11352
11352
  needsAction: "install_or_locate_cursor",
11353
11353
  retryable: true,
11354
- nextStep: "\u8BF7\u786E\u8BA4 Cursor \u5DF2\u5B89\u88C5\u5E76\u767B\u5F55\u3002\u82E5\u4F7F\u7528\u4FBF\u643A\u7248\u6216\u81EA\u5B9A\u4E49\u76EE\u5F55\uFF0C\u8BF7\u8BBE\u7F6E CURSOR_EXE \u540E\u91CD\u65B0\u6267\u884C\u540C\u4E00\u53E5\u521D\u59CB\u5316\u547D\u4EE4\u3002",
11355
- message: `CCE \u5DF2\u8FDE\u63A5 Cursor\uFF0C\u4F46\u8FD8\u4E0D\u80FD\u6253\u5F00\u5DE5\u4F5C\u533A ${projectPath}\uFF0C\u56E0\u4E3A\u6CA1\u6709\u627E\u5230 Cursor \u7A0B\u5E8F\u3002`
11354
+ nextStep: "Confirm that Cursor is installed and signed in. For a portable or custom installation, set CURSOR_EXE and run the same initialization command again.",
11355
+ message: `CCE connected to Cursor but cannot open workspace ${projectPath} because the Cursor executable was not found.`
11356
11356
  };
11357
11357
  }
11358
11358
  const beforeTargetIds = new Set(currentTargets.map((target2) => target2.id));
@@ -11379,8 +11379,8 @@ async function ensureCursorRunningLocal(options = {}) {
11379
11379
  cursorExecutableSource: cursorExecutable2.source,
11380
11380
  needsAction: "retry_initialization",
11381
11381
  retryable: true,
11382
- nextStep: "\u8BF7\u7B49\u5F85 Cursor \u5B8C\u6210\u6253\u5F00\u9879\u76EE\uFF0C\u7136\u540E\u91CD\u65B0\u6267\u884C\u540C\u4E00\u53E5\u521D\u59CB\u5316\u547D\u4EE4\u3002",
11383
- message: `Cursor \u5DF2\u6253\u5F00\u9879\u76EE\uFF0C\u4F46 CCE \u8FD8\u6CA1\u6709\u786E\u8BA4\u5DE5\u4F5C\u533A ${projectPath} \u5DF2\u51C6\u5907\u597D\uFF1B\u4E3A\u907F\u514D\u641C\u7D22\u9519\u9879\u76EE\uFF0C\u672C\u6B21\u521D\u59CB\u5316\u5DF2\u5B89\u5168\u505C\u6B62\u3002`
11382
+ nextStep: "Wait for Cursor to finish opening the project, then run the same initialization command again.",
11383
+ message: `Cursor opened the project, but CCE has not confirmed that workspace ${projectPath} is ready. Initialization stopped safely to avoid searching the wrong project.`
11384
11384
  };
11385
11385
  }
11386
11386
  targetId2 = openedTarget2.id;
@@ -11397,7 +11397,7 @@ async function ensureCursorRunningLocal(options = {}) {
11397
11397
  windowGuard: windowGuard2,
11398
11398
  targetId: targetId2,
11399
11399
  workspaceAction,
11400
- message: workspaceAction === "reused-agents-window" ? `CDP ${CDP_PORT} \u5DF2\u54CD\u5E94\u4E14\u662F Cursor\uFF1B\u5DF2\u590D\u7528 Agents Window\uFF08${targetId2}\uFF09\uFF0C\u4E0D\u4F1A\u518D\u6253\u5F00 IDE \u65B0\u7A97\u53E3\u3002` : `CDP ${CDP_PORT} \u5DF2\u54CD\u5E94\u4E14\u662F Cursor\uFF1B\u76EE\u6807\u5DE5\u4F5C\u533A\u5DF2\u7ED1\u5B9A\u5230 CDP target ${targetId2 || "default"}\u3002`
11400
+ message: workspaceAction === "reused-agents-window" ? `CDP ${CDP_PORT} responded as Cursor; Agents Window ${targetId2} was reused without opening another IDE window.` : `CDP ${CDP_PORT} responded as Cursor; the target workspace is bound to CDP target ${targetId2 || "default"}.`
11401
11401
  };
11402
11402
  }
11403
11403
  return {
@@ -11406,8 +11406,8 @@ async function ensureCursorRunningLocal(options = {}) {
11406
11406
  port: CDP_PORT,
11407
11407
  needsAction: "free_cce_port",
11408
11408
  retryable: true,
11409
- nextStep: `\u672C\u673A\u7AEF\u53E3 ${CDP_PORT} \u6B63\u88AB\u5176\u4ED6\u7A0B\u5E8F\u4F7F\u7528\u3002\u5173\u95ED\u5360\u7528\u5B83\u7684\u7A0B\u5E8F\u540E\uFF0C\u91CD\u65B0\u6267\u884C\u540C\u4E00\u53E5\u521D\u59CB\u5316\u547D\u4EE4\u3002`,
11410
- message: `CCE \u73B0\u5728\u65E0\u6CD5\u8FDE\u63A5 Cursor\uFF0C\u56E0\u4E3A\u6240\u9700\u7684\u672C\u673A\u7AEF\u53E3 ${CDP_PORT} \u6B63\u88AB\u5176\u4ED6\u7A0B\u5E8F\u5360\u7528\u3002`
11409
+ nextStep: `Local port ${CDP_PORT} is in use by another program. Close that program, then run the same initialization command again.`,
11410
+ message: `CCE cannot connect to Cursor because required local port ${CDP_PORT} is occupied by another program.`
11411
11411
  };
11412
11412
  }
11413
11413
  if (cursorRunningImpl()) {
@@ -11420,8 +11420,8 @@ async function ensureCursorRunningLocal(options = {}) {
11420
11420
  cursorExecutableSource: cursorExecutable2 && cursorExecutable2.source || null,
11421
11421
  needsAction: "close_cursor_and_retry",
11422
11422
  retryable: true,
11423
- nextStep: projectPath ? `\u4FDD\u5B58\u624B\u5934\u5185\u5BB9\u5E76\u6B63\u5E38\u9000\u51FA Cursor \u4E00\u6B21\uFF0C\u7136\u540E\u518D\u6B21\u8BF4\u201C\u521D\u59CB\u5316 CCE \u5DE5\u4F5C\u533A\u4E3A ${projectPath}\u201D\u3002` : "\u4FDD\u5B58\u624B\u5934\u5185\u5BB9\u5E76\u6B63\u5E38\u9000\u51FA Cursor \u4E00\u6B21\uFF0C\u7136\u540E\u91CD\u8BD5\u521A\u624D\u7684 CCE \u64CD\u4F5C\u3002",
11424
- message: "Cursor \u5DF2\u7ECF\u63D0\u524D\u6253\u5F00\uFF0CCCE \u65E0\u6CD5\u5728\u8FD0\u884C\u4E2D\u4E3A\u5B83\u8865\u4E0A\u8FDE\u63A5\u80FD\u529B\u3002\u4E3A\u4FDD\u62A4\u672A\u4FDD\u5B58\u5185\u5BB9\uFF0CCursor Bridge \u4E0D\u4F1A\u5F3A\u5236\u5173\u95ED\u5B83\u3002"
11423
+ nextStep: projectPath ? `Save your work, exit Cursor normally once, then initialize CCE for workspace ${projectPath} again.` : "Save your work, exit Cursor normally once, then retry the previous CCE operation.",
11424
+ message: "Cursor was already running, so CCE cannot add the required connection capability in place. Cursor Bridge will not force-close it, protecting unsaved work."
11425
11425
  };
11426
11426
  }
11427
11427
  const cursorExecutable = findCursorExeDetailsImpl();
@@ -11433,8 +11433,8 @@ async function ensureCursorRunningLocal(options = {}) {
11433
11433
  port: CDP_PORT,
11434
11434
  needsAction: "install_or_locate_cursor",
11435
11435
  retryable: true,
11436
- nextStep: "\u8BF7\u5148\u5B89\u88C5\u5E76\u767B\u5F55 Cursor\u3002\u82E5\u4F7F\u7528\u4FBF\u643A\u7248\u6216\u81EA\u5B9A\u4E49\u76EE\u5F55\uFF0C\u8BF7\u8BBE\u7F6E CURSOR_EXE \u540E\u91CD\u65B0\u6267\u884C\u540C\u4E00\u53E5\u521D\u59CB\u5316\u547D\u4EE4\u3002",
11437
- message: "\u6CA1\u6709\u627E\u5230 Cursor\u3002\u6807\u51C6 Windows \u4E0E macOS \u5B89\u88C5\u4F1A\u81EA\u52A8\u8BC6\u522B\uFF0C\u901A\u5E38\u4E0D\u9700\u8981\u586B\u5199\u7A0B\u5E8F\u8DEF\u5F84\u3002"
11436
+ nextStep: "Install and sign in to Cursor first. For a portable or custom installation, set CURSOR_EXE and run the same initialization command again.",
11437
+ message: "Cursor was not found. Standard Windows and macOS installations are detected automatically and normally do not require an explicit executable path."
11438
11438
  };
11439
11439
  }
11440
11440
  const launchPort = resolveCursorLaunchCdpPort(CDP_PORT);
@@ -11469,8 +11469,8 @@ async function ensureCursorRunningLocal(options = {}) {
11469
11469
  cursorExecutableSource: cursorExecutable.source,
11470
11470
  needsAction: "retry_initialization",
11471
11471
  retryable: true,
11472
- nextStep: "\u8BF7\u7A0D\u7B49\u7247\u523B\uFF0C\u7136\u540E\u91CD\u65B0\u6267\u884C\u540C\u4E00\u53E5\u521D\u59CB\u5316\u547D\u4EE4\u3002",
11473
- message: "Cursor \u5DF2\u7ECF\u542F\u52A8\uFF0C\u4F46 CCE \u8FD8\u6CA1\u51C6\u5907\u597D\uFF1B\u65E0\u9700\u4FEE\u6539\u4EFB\u4F55\u7AEF\u53E3\u8BBE\u7F6E\u3002"
11472
+ nextStep: "Wait a moment, then run the same initialization command again.",
11473
+ message: "Cursor started, but CCE is not ready yet. No port setting needs to be changed."
11474
11474
  };
11475
11475
  }
11476
11476
  const cursorPid = findCursorPidByPort(CDP_PORT) || child.pid || null;
@@ -11490,13 +11490,13 @@ async function ensureCursorRunningLocal(options = {}) {
11490
11490
  cursorExecutableSource: cursorExecutable.source,
11491
11491
  needsAction: "retry_initialization",
11492
11492
  retryable: true,
11493
- nextStep: "\u8BF7\u7B49\u5F85 Cursor \u5B8C\u6210\u6253\u5F00\u9879\u76EE\uFF0C\u7136\u540E\u91CD\u65B0\u6267\u884C\u540C\u4E00\u53E5\u521D\u59CB\u5316\u547D\u4EE4\u3002",
11494
- message: `Cursor \u5DF2\u542F\u52A8\uFF0C\u4F46 CCE \u8FD8\u6CA1\u6709\u786E\u8BA4\u5DE5\u4F5C\u533A ${projectPath} \u5DF2\u51C6\u5907\u597D\uFF1B\u4E3A\u907F\u514D\u641C\u7D22\u9519\u9879\u76EE\uFF0C\u672C\u6B21\u521D\u59CB\u5316\u5DF2\u5B89\u5168\u505C\u6B62\u3002`
11493
+ nextStep: "Wait for Cursor to finish opening the project, then run the same initialization command again.",
11494
+ message: `Cursor started, but CCE has not confirmed that workspace ${projectPath} is ready. Initialization stopped safely to avoid searching the wrong project.`
11495
11495
  };
11496
11496
  }
11497
11497
  if (projectPath && targetId) PROJECT_TARGETS.set(normalizeProjectKey(projectPath), targetId);
11498
11498
  const windowGuard = effectiveRuntimeMode === "minimal" && cursorPid ? startMinimalWindowGuard(cursorPid) : null;
11499
- const target = projectPath ? `\u6253\u5F00 ${projectPath}` : "\u6062\u590D\u4E0A\u6B21\u5DE5\u4F5C\u533A";
11499
+ const target = projectPath ? `opening ${projectPath}` : "restoring the previous workspace";
11500
11500
  const presentation = effectiveRuntimeMode === "minimal" ? setCursorWindowPresentation({ action: "hide", port: CDP_PORT, pid: cursorPid }) : null;
11501
11501
  return {
11502
11502
  ok: true,
@@ -11513,7 +11513,7 @@ async function ensureCursorRunningLocal(options = {}) {
11513
11513
  cursorExecutableSource: cursorExecutable.source,
11514
11514
  targetId,
11515
11515
  workspaceAction: projectPath ? "launched-project" : "launched-last-workspace",
11516
- message: `\u5DF2\u542F\u52A8 Cursor\uFF08${exe}\uFF0C${target}\uFF09\uFF0CCDP ${CDP_PORT} \u5C31\u7EEA\u3002`
11516
+ message: `Cursor started (${exe}, ${target}); CDP ${CDP_PORT} is ready.`
11517
11517
  };
11518
11518
  }
11519
11519
  function normalizeProjectKey(projectPath) {
@@ -20740,7 +20740,7 @@ init_cursor_ensure_core();
20740
20740
  init_lifecycle_paths();
20741
20741
  import http2 from "http";
20742
20742
  import { pathToFileURL as pathToFileURL2 } from "url";
20743
- var PLUGIN_VERSION = "5.4.2";
20743
+ var PLUGIN_VERSION = "5.5.0";
20744
20744
  var CDP_PORT2 = Number(process.env.CURSOR_BRIDGE_CDP_PORT || 9223);
20745
20745
  var ORIGIN = `http://localhost:${CDP_PORT2}`;
20746
20746
  var QUERY_TIMEOUT = Number(process.env.CURSOR_BRIDGE_TIMEOUT || 3e5);
@@ -20750,38 +20750,39 @@ function normalizeDelegationMode(value = process.env.CURSOR_BRIDGE_DELEGATION) {
20750
20750
  var DELEGATION_MODE = normalizeDelegationMode();
20751
20751
  function searchResultContract() {
20752
20752
  return [
20753
- "\u53EA\u8FD4\u56DE\u652F\u6491\u7ED3\u8BBA\u6240\u9700\u7684\u6700\u5C0F\u5145\u5206\u8BC1\u636E\u96C6\uFF0C\u6309\u8BC1\u636E\u5F3A\u5EA6\u6392\u5E8F\uFF1B\u4E0D\u8981\u4E3A\u4E86\u51D1\u6570\u91CF\u5806\u780C\u76F8\u4F3C\u7ED3\u679C\u3002",
20753
+ "Return only the minimum sufficient evidence set, ordered by evidence strength. Do not pad the result with similar matches.",
20754
20754
  "",
20755
- "\u8F93\u51FA\u683C\u5F0F\uFF08\u4FDD\u6301\u7D27\u51D1\uFF0C\u4E0D\u8981\u8FFD\u52A0\u957F\u7BC7\u89E3\u91CA\uFF09\uFF1A",
20755
+ "Output format (keep it compact; write narrative fields in the language of the user query and do not append a long explanation):",
20756
20756
  "CCE_SEARCH_RESULT",
20757
- "intent: <\u4E00\u53E5\u8BDD\u590D\u8FF0\u68C0\u7D22\u610F\u56FE>",
20758
- "coverage: <focused|extended> | <\u4E3A\u4EC0\u4E48\u91C7\u7528\u8BE5\u68C0\u7D22\u529B\u5EA6\uFF1B\u662F\u5426\u6269\u5C55\u8FC7\u4F18\u5148\u8303\u56F4>",
20757
+ "intent: <one-sentence restatement of the retrieval intent>",
20758
+ "coverage: <focused|extended> | <why this search depth was sufficient; whether the preferred scope was expanded>",
20759
20759
  "evidence:",
20760
- "- <workspace-relative-path>:<start>-<end> | <symbol \u6216\u951A\u70B9> | <\u76F8\u5173\u6027\u6216\u5DF2\u6838\u9A8C\u5173\u7CFB> | <semantic|exact|reference|source-read>",
20761
- "gaps: <\u6CA1\u6709\u786E\u8BA4\u7684\u90E8\u5206\uFF1B\u6CA1\u6709\u5219\u5199 none>",
20762
- "confidence: <high|medium|low>\uFF08\u53EA\u8BC4\u4EF7\u5B9A\u4F4D\u8BC1\u636E\uFF0C\u4E0D\u8BC4\u4EF7\u4EE3\u7801\u6B63\u786E\u6027\uFF09"
20760
+ "- <workspace-relative-path>:<start>-<end> | <symbol or anchor> | <relevance or verified relationship> | <semantic|exact|reference|source-read>",
20761
+ "gaps: <anything not confirmed; write none when empty>",
20762
+ "confidence: <high|medium|low> (rate retrieval evidence only, not code correctness)"
20763
20763
  ];
20764
20764
  }
20765
20765
  function buildContextEnginePrompt(query) {
20766
20766
  return [
20767
- "\u4F60\u73B0\u5728\u662F Cursor Context Engine\uFF08CCE\uFF09\uFF1A\u4E00\u4E2A\u53EA\u8BFB\u3001\u8BC1\u636E\u9A71\u52A8\u7684\u9879\u76EE\u7406\u89E3\u5F15\u64CE\u3002",
20768
- "\u76EE\u6807\u662F\u628A\u81EA\u7136\u8BED\u8A00\u610F\u56FE\u89E3\u6790\u6210\u53EF\u6838\u9A8C\u7684\u771F\u5B9E\u4EE3\u7801\u4E0A\u4E0B\u6587\uFF0C\u800C\u4E0D\u662F\u731C\u6D4B\u4EE3\u7801\u4F4D\u7F6E\u3001\u590D\u8FF0\u6846\u67B6\u60EF\u4F8B\u6216\u751F\u6210\u5B9E\u73B0\u65B9\u6848\u3002",
20769
- "\u5FC5\u987B\u5148\u68C0\u7D22\u518D\u56DE\u7B54\u3002\u6839\u636E\u95EE\u9898\u5F62\u72B6\u548C\u68C0\u7D22\u4E2D\u53D1\u73B0\u7684\u5173\u7CFB\uFF0C\u81EA\u4E3B\u51B3\u5B9A\u68C0\u7D22\u529B\u5EA6\uFF1A\u7B80\u5355\u5B9A\u4F4D\u5FEB\u901F\u6536\u655B\uFF1B\u8C03\u7528\u94FE\u3001\u6570\u636E\u6D41\u3001\u6CE8\u518C\u5173\u7CFB\u6216\u8DE8\u6A21\u5757\u95EE\u9898\u7EE7\u7EED\u8FFD\u8E2A\u5230\u6700\u5C0F\u5145\u5206\u8BC1\u636E\u3002",
20770
- "\u81EA\u884C\u9009\u62E9 Cursor \u5F53\u524D\u53EF\u7528\u7684\u6700\u4F73\u80FD\u529B\uFF0C\u5305\u62EC\u9879\u76EE\u7D22\u5F15\u8BED\u4E49\u68C0\u7D22\u3001\u7CBE\u786E\u6587\u672C\u641C\u7D22\u3001\u7B26\u53F7/\u5F15\u7528\u8FFD\u8E2A\u3001\u5B9A\u5411\u6E90\u7801\u8BFB\u53D6\uFF0C\u4EE5\u53CA\u786E\u6709\u6536\u76CA\u65F6\u7684 Explore/\u5B50\u4EE3\u7406\u3002\u8C03\u7528\u65B9\u53EA\u7EA6\u675F\u53EA\u8BFB\u3001\u8BC1\u636E\u548C\u505C\u6B62\u6761\u4EF6\uFF0C\u4E0D\u66FF Cursor \u7F16\u6392\u5185\u90E8 harness\u3002",
20771
- "\u6BCF\u6761\u5173\u7CFB\u90FD\u5FC5\u987B\u7531\u5B9E\u9645\u641C\u7D22\u3001\u5F15\u7528\u6216\u6E90\u7801\u8BFB\u53D6\u652F\u6491\uFF1B\u8BED\u4E49\u76F8\u4F3C\u4E0D\u80FD\u5192\u5145\u5DF2\u8BC1\u660E\u8C03\u7528\u8FB9\u3002\u8FBE\u5230\u6700\u5C0F\u5145\u5206\u4E0A\u4E0B\u6587\u540E\u7ACB\u5373\u505C\u6B62\uFF0C\u4E0D\u505A\u65E0\u5173\u5168\u4ED3\u5E93\u6F2B\u6E38\u3002",
20772
- "\u4E0D\u5F97\u4FEE\u6539\u3001\u521B\u5EFA\u6216\u5220\u9664\u6587\u4EF6\uFF0C\u4E0D\u5F97\u6267\u884C\u6539\u53D8\u5DE5\u4F5C\u533A\u72B6\u6001\u7684\u547D\u4EE4\u3002\u53EA\u8BFB\u53D6\u8DB3\u4EE5\u786E\u8BA4\u5B9A\u4F4D\u7684\u4E0A\u4E0B\u6587\u3002",
20773
- "\u6CA1\u6709\u8BC1\u636E\u65F6\u660E\u786E\u5199 NOT_FOUND\uFF0C\u5E76\u5728 gaps \u4E2D\u5217\u51FA\u5B9E\u9645\u641C\u7D22\u8FC7\u7684\u8BCD\u3001\u7B26\u53F7\u3001\u5F15\u7528\u6216\u8303\u56F4\uFF1B\u4E0D\u5F97\u8DF3\u8FC7\u641C\u7D22\u76F4\u63A5\u56DE\u7B54\u3002",
20774
- "\u68C0\u7D22\u8303\u56F4\u662F\u5F53\u524D Cursor \u5DF2\u6253\u5F00\u5E76\u5B8C\u6210\u7D22\u5F15\u7684\u6574\u4E2A\u5DE5\u4F5C\u533A\u3002\u82E5\u610F\u56FE\u70B9\u540D\u4E86\u6A21\u5757\u6216\u8DEF\u5F84\uFF0C\u628A\u5B83\u89C6\u4E3A\u7EBF\u7D22\u800C\u975E\u786C\u8FB9\u754C\u3002",
20767
+ "You are Cursor Context Engine (CCE), a read-only, evidence-driven project-understanding engine.",
20768
+ "Resolve natural-language intent into verifiable code context. Do not guess locations, repeat framework conventions, or propose an implementation.",
20769
+ "Search before answering. Choose the search depth from the question shape and discovered relationships: converge quickly for a simple location; trace call chains, data flow, registrations, or cross-module relationships until the minimum sufficient evidence is reached.",
20770
+ "Choose the best Cursor capabilities available, including indexed semantic retrieval, exact text search, symbol/reference tracing, targeted source reading, and Explore or subagents when they materially help. The caller defines the read-only, evidence, and stopping boundaries; it does not prescribe Cursor's internal harness.",
20771
+ "Support every claimed relationship with actual search, references, or source reading. Semantic similarity is not a proven call edge. Stop at minimum sufficient context and avoid unrelated repository-wide exploration.",
20772
+ "Do not modify, create, or delete files, and do not run commands that change workspace state. Read only the context needed to verify the location.",
20773
+ "When evidence is missing, write NOT_FOUND and list the terms, symbols, references, or scopes actually searched under gaps. Never answer without searching.",
20774
+ "The search scope is the complete workspace currently open and indexed by Cursor. Treat any module or path named in the intent as a clue, not a hard boundary.",
20775
+ "Write narrative output in the language of the user query unless the query explicitly requests another language. Never translate paths, symbols, identifiers, keys, enum values, or evidence-source markers.",
20775
20776
  ...searchResultContract(),
20776
20777
  "",
20777
- `\u68C0\u7D22\u610F\u56FE\uFF1A${String(query || "").trim()}`
20778
+ `Retrieval intent: ${String(query || "").trim()}`
20778
20779
  ].join("\n");
20779
20780
  }
20780
20781
  function normalizeCceSearchResult(value) {
20781
20782
  const text = String(value || "").trim();
20782
20783
  const marker = text.indexOf("CCE_SEARCH_RESULT");
20783
20784
  if (marker < 0) return text;
20784
- return text.slice(marker).replace(/^CCE_SEARCH_RESULT\s+(?=intent:)/, "CCE_SEARCH_RESULT\n").replace(/[^\S\r\n]+(?=(?:coverage|evidence|gaps|confidence):)/g, "\n");
20785
+ return text.slice(marker).replace(/^CCE_SEARCH_RESULT\s+(?=intent:)/, "CCE_SEARCH_RESULT\n").replace(/[^\S\r\n]+(?=(?:coverage|evidence|gaps|confidence):)/g, "\n").replace(/^(?!- )([^:\r\n]+:\d+(?:-\d+)?\s+\|)/gm, "- $1");
20785
20786
  }
20786
20787
  function isConfirmedCompletedReply({ answer, snapshot = {}, sawStop = false, baselineCount = 0 } = {}) {
20787
20788
  if (!String(answer || "").trim()) return false;
@@ -20792,7 +20793,8 @@ function isConfirmedCompletedReply({ answer, snapshot = {}, sawStop = false, bas
20792
20793
  const hasCompletionEvidence = sawStop || Number(snapshot.messageCount || 0) >= Number(baselineCount || 0) + 2;
20793
20794
  return hasAssistantEvidence && hasCompletionEvidence;
20794
20795
  }
20795
- var DO_DEFAULT_CONTRACT = "\n\n\u5B8C\u6210\u8981\u6C42\uFF1A\u5728\u5F53\u524D Cursor \u5DF2\u6253\u5F00\u7684\u5DE5\u4F5C\u533A\u5185\u76F4\u63A5\u5B8C\u6210\u4EFB\u52A1\uFF1B\u4E0D\u8981\u63A8\u9001\u8FDC\u7AEF\u3002\u7ED3\u675F\u524D\u68C0\u67E5\u5B9E\u9645\u6539\u52A8\u5E76\u8FD0\u884C\u4E0E\u98CE\u9669\u5339\u914D\u7684\u9A8C\u8BC1\u3002\u6700\u7EC8\u56DE\u590D\u5FC5\u987B\u5217\u51FA\uFF1A\u5B8C\u6210\u5185\u5BB9\u3001\u6539\u52A8\u6587\u4EF6\u3001\u9A8C\u8BC1\u7ED3\u679C\u3001\u4ECD\u6709\u98CE\u9669\u6216\u963B\u585E\u3002";
20796
+ var DO_DEFAULT_CONTRACT = "\n\nCompletion requirements: Work directly in the workspace currently open in Cursor; do not push to a remote. Before finishing, inspect the actual changes and run verification proportional to risk. The final reply must list completed work, changed files, verification results, and remaining risks or blockers.";
20797
+ var DO_LANGUAGE_CONTRACT = "\n\nResponse language: Reply in the language of the user task unless it explicitly requests another language. Never translate paths, commands, identifiers, keys, enum values, exact options, or error/status codes.";
20796
20798
  var CDP_HOST2 = "127.0.0.1";
20797
20799
  function httpJson(path) {
20798
20800
  return new Promise((resolve6, reject) => {
@@ -20803,12 +20805,12 @@ function httpJson(path) {
20803
20805
  try {
20804
20806
  resolve6(JSON.parse(d));
20805
20807
  } catch {
20806
- reject(new Error("CDP \u975E JSON \u54CD\u5E94"));
20808
+ reject(new Error("CDP returned a non-JSON response"));
20807
20809
  }
20808
20810
  });
20809
20811
  });
20810
20812
  req.on("error", reject);
20811
- req.setTimeout(4e3, () => req.destroy(new Error(`Cursor \u8C03\u8BD5\u53E3 ${CDP_PORT2} \u65E0\u54CD\u5E94\u2014\u2014Cursor \u662F\u5426\u5E26 --remote-debugging-port=${CDP_PORT2} \u542F\u52A8\uFF1F`)));
20813
+ req.setTimeout(4e3, () => req.destroy(new Error(`Cursor debug port ${CDP_PORT2} did not respond. Was Cursor started with --remote-debugging-port=${CDP_PORT2}?`)));
20812
20814
  });
20813
20815
  }
20814
20816
  function scoreCursorPageCandidate(candidate, purpose = "fifo") {
@@ -20832,7 +20834,7 @@ function selectCursorPageCandidate(candidates, options = {}) {
20832
20834
  const pages = Array.isArray(candidates) ? candidates.filter(Boolean) : [];
20833
20835
  if (options.targetId) {
20834
20836
  const exact = pages.find((page) => page.id === options.targetId);
20835
- if (!exact) throw new Error(`Cursor CDP target \u5DF2\u6D88\u5931\uFF1A${options.targetId}`);
20837
+ if (!exact) throw new Error(`Cursor CDP target disappeared: ${options.targetId}`);
20836
20838
  return exact;
20837
20839
  }
20838
20840
  const purpose = options.purpose || "fifo";
@@ -20880,11 +20882,11 @@ async function reloadPageTarget(page, timeoutMs = 5e3) {
20880
20882
  try {
20881
20883
  await Promise.race([
20882
20884
  c.ready,
20883
- new Promise((_, reject) => setTimeout(() => reject(new Error("CDP target \u8FDE\u63A5\u8D85\u65F6")), timeoutMs))
20885
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Timed out connecting to the CDP target")), timeoutMs))
20884
20886
  ]);
20885
20887
  await Promise.race([
20886
20888
  c.send("Page.reload", { ignoreCache: true }),
20887
- new Promise((_, reject) => setTimeout(() => reject(new Error("CDP reload \u8D85\u65F6")), timeoutMs))
20889
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Timed out reloading the CDP target")), timeoutMs))
20888
20890
  ]);
20889
20891
  return true;
20890
20892
  } catch {
@@ -20899,11 +20901,11 @@ async function inspectPageTarget(page) {
20899
20901
  try {
20900
20902
  await Promise.race([
20901
20903
  c.ready,
20902
- new Promise((_, reject) => setTimeout(() => reject(new Error("CDP target \u8FDE\u63A5\u8D85\u65F6")), probeMs))
20904
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Timed out connecting to the CDP target")), probeMs))
20903
20905
  ]);
20904
20906
  const raw = await Promise.race([
20905
20907
  evalJS(c, EXPR_PAGE_CAPABILITIES),
20906
- new Promise((_, reject) => setTimeout(() => reject(new Error("CDP target \u63A2\u6D4B\u8D85\u65F6")), probeMs))
20908
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Timed out probing the CDP target")), probeMs))
20907
20909
  ]);
20908
20910
  return { ...page, capabilities: JSON.parse(raw || "{}") };
20909
20911
  } catch (error2) {
@@ -20956,7 +20958,7 @@ function isAgentsWorkspaceBindError(error2) {
20956
20958
  async function findPage(options = {}) {
20957
20959
  const list = await httpJson("/json/list");
20958
20960
  const pages = list.filter((t) => t.type === "page" && t.webSocketDebuggerUrl);
20959
- if (!pages.length) throw new Error("\u672A\u627E\u5230 Cursor workbench page target");
20961
+ if (!pages.length) throw new Error("No Cursor workbench page target was found");
20960
20962
  if (options.targetId && options.preferAgentsV2 !== true && options.preferLegacy !== true) {
20961
20963
  return selectCursorPageCandidate(pages, options);
20962
20964
  }
@@ -20994,14 +20996,14 @@ function makeClient(wsUrl) {
20994
20996
  else res(m.result);
20995
20997
  }
20996
20998
  });
20997
- ws.on("close", () => failAll("CDP ws \u5DF2\u5173\u95ED\uFF08\u9875\u9762/\u6E32\u67D3\u8FDB\u7A0B\u6D88\u5931\uFF09"));
20998
- ws.on("error", (e) => failAll("CDP ws \u51FA\u9519: " + (e && e.message)));
20999
+ ws.on("close", () => failAll("CDP WebSocket closed because the page or renderer disappeared"));
21000
+ ws.on("error", (e) => failAll("CDP WebSocket error: " + (e && e.message)));
20999
21001
  const CMD_TIMEOUT = Number(process.env.CURSOR_BRIDGE_CMD_TIMEOUT || 3e4);
21000
21002
  const send = (method, params = {}) => {
21001
21003
  const myId = ++id;
21002
21004
  return new Promise((res, rej) => {
21003
21005
  const t = setTimeout(() => {
21004
- if (pending.delete(myId)) rej(new Error(`CDP \u547D\u4EE4\u8D85\u65F6 ${method} (${CMD_TIMEOUT}ms)`));
21006
+ if (pending.delete(myId)) rej(new Error(`CDP command timed out: ${method} (${CMD_TIMEOUT}ms)`));
21005
21007
  }, CMD_TIMEOUT);
21006
21008
  pending.set(myId, { res: (v) => {
21007
21009
  clearTimeout(t);
@@ -21029,7 +21031,7 @@ function makeClient(wsUrl) {
21029
21031
  var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
21030
21032
  async function evalJS(c, expr) {
21031
21033
  const r = await c.send("Runtime.evaluate", { expression: expr, returnByValue: true, includeCommandLineAPI: true });
21032
- if (r.exceptionDetails) throw new Error("\u9875\u9762\u5F02\u5E38: " + (r.exceptionDetails.exception && r.exceptionDetails.exception.description || r.exceptionDetails.text));
21034
+ if (r.exceptionDetails) throw new Error("Page exception: " + (r.exceptionDetails.exception && r.exceptionDetails.exception.description || r.exceptionDetails.text));
21033
21035
  return r.result && r.result.value;
21034
21036
  }
21035
21037
  async function chord(c, modifiers, key, code, vk) {
@@ -21268,7 +21270,8 @@ var REACT_ADAPTER_BODY = `
21268
21270
  id:String(e&&e.id||''),label:String(e&&e.label||''),searchText:String(e&&e.searchText||''),
21269
21271
  timestamp:normalizeTimestamp(e&&e.timestamp,index),isSelected:!!(e&&e.isSelected),
21270
21272
  showSpinner:!!(e&&e.showSpinner),
21271
- icon:String(typeof (e&&e.icon)==='string'?e.icon:(e&&e.icon&&((e.icon.id)||(e.icon.props&&e.icon.props.id)||(e.icon.type&&e.icon.type.id)))||'')
21273
+ icon:String(typeof (e&&e.icon)==='string'?e.icon:(e&&e.icon&&((e.icon.id)||(e.icon.props&&e.icon.props.id)||(e.icon.type&&e.icon.type.id)))||''),
21274
+ durable:true
21272
21275
  });
21273
21276
  const normalizeV2=(header,selectedId,index,section)=>{
21274
21277
  const rawId=String(readScalar(header&&header.id)||'').replace(/^local:/,'');
@@ -21286,7 +21289,8 @@ var REACT_ADAPTER_BODY = `
21286
21289
  timestamp:normalizeTimestamp(readScalar(header&&header.lastUpdatedAt)||readScalar(header&&header.createdAt),index),
21287
21290
  isSelected:!!rawId&&(String(selectedId||'')===rawId||String(selectedId||'')==='local:'+rawId),
21288
21291
  showSpinner:/in_progress|running|generating/.test(status),icon:icon||'draft',
21289
- workspaceId:String(readScalar(section&&section.id)||''),workspaceLabel:String(readScalar(section&&section.displayName)||'')
21292
+ workspaceId:String(readScalar(section&&section.id)||''),workspaceLabel:String(readScalar(section&&section.displayName)||''),
21293
+ durable:true
21290
21294
  };
21291
21295
  };
21292
21296
  const findLegacyAdapter=()=>{
@@ -21367,7 +21371,7 @@ var REACT_ADAPTER_BODY = `
21367
21371
  entries.push({
21368
21372
  id:selectedId,label:'',searchText:'',timestamp:0,isSelected:true,
21369
21373
  showSpinner:/in_progress|running|generating/.test(status),icon,
21370
- workspaceId:'',workspaceLabel:''
21374
+ workspaceId:'',workspaceLabel:'',durable:false
21371
21375
  });
21372
21376
  }
21373
21377
  }
@@ -21474,6 +21478,13 @@ function classifyParallelTerminalIcon(icon) {
21474
21478
  if (/check-circled|check/i.test(value)) return "completed";
21475
21479
  return "unknown";
21476
21480
  }
21481
+ function isDurablyRegisteredParallelEntry(entry) {
21482
+ return !!entry && entry.durable !== false && (entry.showSpinner || classifyParallelTerminalIcon(entry.icon) !== "unknown");
21483
+ }
21484
+ function uncertainSubmissionReservationScope(job, error2) {
21485
+ if (error2 && error2.requiresGlobalReservation) return "global";
21486
+ return job && job.readOnly ? "agent" : "paths";
21487
+ }
21477
21488
  function providerErrorSignature(info) {
21478
21489
  if (!info || info.found !== true) return "";
21479
21490
  return String(info.signature || [info.title, info.message, info.requestId].filter(Boolean).join("|"));
@@ -21503,7 +21514,7 @@ function promoteAgentsWorkspaceLifecycle(lifecycle, agentsWorkspace) {
21503
21514
  targetId: agentsWorkspace.targetId,
21504
21515
  targetUiFlavor: agentsWorkspace.targetUiFlavor,
21505
21516
  workspaceAction: "reused-agents-repository",
21506
- message: `CCE \u5DF2\u786E\u8BA4 Cursor Agents \u4E2D\u7684\u5DE5\u4F5C\u533A ${lifecycle.projectPath || agentsWorkspace.workspace || ""} \u53EF\u4EE5\u4F7F\u7528\u3002`,
21517
+ message: `CCE confirmed that workspace ${lifecycle.projectPath || agentsWorkspace.workspace || ""} is available in Cursor Agents.`,
21507
21518
  needsAction: null,
21508
21519
  nextStep: null,
21509
21520
  retryable: false
@@ -21590,8 +21601,8 @@ var CursorBridge = class {
21590
21601
  bindingPersisted: true,
21591
21602
  ready: false,
21592
21603
  status: lifecycle.status,
21593
- message: lifecycle.message || "CCE \u521D\u59CB\u5316\u5C1A\u672A\u5B8C\u6210\uFF0C\u4F46\u5DE5\u4F5C\u533A\u5DF2\u7ECF\u4FDD\u5B58\u3002",
21594
- nextStep: lifecycle.nextStep || "\u5904\u7406\u63D0\u793A\u540E\uFF0C\u91CD\u65B0\u6267\u884C\u540C\u4E00\u53E5\u521D\u59CB\u5316\u547D\u4EE4\u3002",
21604
+ message: lifecycle.message || "CCE initialization is not complete, but the workspace binding was saved.",
21605
+ nextStep: lifecycle.nextStep || "Resolve the reported condition, then run the same initialization command again.",
21595
21606
  retryable: lifecycle.retryable !== false,
21596
21607
  lifecycle
21597
21608
  };
@@ -21602,8 +21613,8 @@ var CursorBridge = class {
21602
21613
  bindingPersisted: true,
21603
21614
  ready: true,
21604
21615
  status: "ready",
21605
- message: `CCE \u5DF2\u51C6\u5907\u597D\u4F7F\u7528\u5DE5\u4F5C\u533A ${saved.projectPath}\u3002`,
21606
- nextStep: "\u73B0\u5728\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 cursor_context_engine \u6216 cursor_do\u3002",
21616
+ message: `CCE is ready to use workspace ${saved.projectPath}.`,
21617
+ nextStep: "You can now use cursor_context_engine or cursor_do directly.",
21607
21618
  lifecycle: this._lastLifecycle
21608
21619
  };
21609
21620
  }
@@ -21728,10 +21739,10 @@ var CursorBridge = class {
21728
21739
  }
21729
21740
  async contextEngine(query) {
21730
21741
  const text = String(query || "").trim();
21731
- if (!text) throw new Error("query \u4E0D\u80FD\u4E3A\u7A7A");
21732
- if (text.length > 2e4) throw new Error("query \u8FC7\u957F\uFF08\u6700\u5927 20000 \u5B57\u7B26\uFF09");
21742
+ if (!text) throw new Error("query must not be empty");
21743
+ if (text.length > 2e4) throw new Error("query exceeds the 20,000-character limit");
21733
21744
  if (this._hasGlobalReservation()) {
21734
- throw new Error("\u5B58\u5728 Stop \u672A\u786E\u8BA4\u7684\u5168\u5C40 Cursor \u5360\u7528\uFF1B\u8BF7\u5148\u5904\u7406 cursor_status \u4E2D\u7684 blockingTaskIds");
21745
+ throw new Error("A global Cursor reservation has an unconfirmed Stop state; resolve blockingTaskIds from cursor_status first");
21735
21746
  }
21736
21747
  await this._ensureCursor();
21737
21748
  const job = this._enqueue("context_engine", buildContextEnginePrompt(text), {
@@ -21755,36 +21766,36 @@ var CursorBridge = class {
21755
21766
  throw new Error("cursor_do is disabled by CURSOR_BRIDGE_DELEGATION=off; restart the MCP server without that setting to enable delegation");
21756
21767
  }
21757
21768
  const text = String(prompt || "").trim();
21758
- if (!text) throw new Error("prompt \u4E0D\u80FD\u4E3A\u7A7A");
21759
- if (text.length > 1e5) throw new Error("prompt \u8FC7\u957F\uFF08\u6700\u5927 100000 \u5B57\u7B26\uFF09");
21769
+ if (!text) throw new Error("prompt must not be empty");
21770
+ if (text.length > 1e5) throw new Error("prompt exceeds the 100,000-character limit");
21760
21771
  if (this._hasGlobalReservation()) {
21761
- throw new Error("\u5B58\u5728 Stop \u672A\u786E\u8BA4\u7684\u5168\u5C40 Cursor \u5360\u7528\uFF1B\u5728\u663E\u5F0F\u6062\u590D\u6216\u91CA\u653E\u524D\u7981\u6B62\u63D0\u4EA4\u65B0\u4EFB\u52A1");
21772
+ throw new Error("A global Cursor reservation has an unconfirmed Stop state; no new task may be submitted until it is explicitly recovered or released");
21762
21773
  }
21763
21774
  await this._ensureCursor();
21764
21775
  const execution = String(options.execution || "fifo");
21765
21776
  if (execution !== "fifo" && execution !== "parallel_agent") {
21766
- throw new Error(`execution \u4E0D\u652F\u6301 ${execution}\uFF1B\u53EA\u80FD\u662F fifo \u6216 parallel_agent`);
21777
+ throw new Error(`Unsupported execution value ${execution}; expected fifo or parallel_agent`);
21767
21778
  }
21768
21779
  const readOnly = options.readOnly === true;
21769
21780
  const timeoutMs = Math.max(3e4, Math.min(9e5, Number(options.timeoutMs || 6e5)));
21770
21781
  const allowedPaths = Array.isArray(options.allowedPaths) ? options.allowedPaths.map((x) => String(x).trim()).filter(Boolean) : [];
21771
21782
  if (readOnly && allowedPaths.length > 0) {
21772
- throw new Error("read_only=true \u4E0E allowed_paths \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\uFF1B\u53EA\u8BFB\u4EFB\u52A1\u4E0D\u5F97\u58F0\u660E\u5199\u5165\u8303\u56F4");
21783
+ throw new Error("read_only=true cannot be combined with allowed_paths because a read-only task cannot declare a write scope");
21773
21784
  }
21774
21785
  if (execution === "parallel_agent" && !readOnly && allowedPaths.length === 0) {
21775
- throw new Error("parallel_agent \u5199\u4EFB\u52A1\u5FC5\u987B\u63D0\u4F9B allowed_paths\uFF1B\u7EAF\u8BFB\u53D6\u4EFB\u52A1\u8BF7\u663E\u5F0F\u8BBE\u7F6E read_only=true");
21786
+ throw new Error("A parallel_agent write task must provide allowed_paths; set read_only=true explicitly for a read-only task");
21776
21787
  }
21777
21788
  if (execution === "parallel_agent" && !readOnly) {
21778
21789
  this._validateParallelAllowedPaths(allowedPaths);
21779
21790
  this._assertNoParallelPathConflict(allowedPaths);
21780
21791
  }
21781
21792
  const contract = String(options.completionContract || "").trim();
21782
- let fullPrompt = text;
21783
- if (readOnly) fullPrompt += "\n\n\u53EA\u8BFB\u8FB9\u754C\uFF1A\u4E0D\u5F97\u4FEE\u6539\u3001\u521B\u5EFA\u6216\u5220\u9664\u4EFB\u4F55\u6587\u4EF6\uFF0C\u4E0D\u5F97\u6267\u884C\u4F1A\u6539\u53D8\u5DE5\u4F5C\u533A\u72B6\u6001\u7684\u547D\u4EE4\u3002";
21793
+ let fullPrompt = text + DO_LANGUAGE_CONTRACT;
21794
+ if (readOnly) fullPrompt += "\n\nRead-only boundary: Do not modify, create, or delete files, and do not run commands that change workspace state.";
21784
21795
  if (allowedPaths.length > 0) {
21785
- fullPrompt += "\n\n\u5141\u8BB8\u4FEE\u6539\u8303\u56F4\uFF08\u4E0D\u5F97\u8D8A\u754C\uFF09\uFF1A\n" + allowedPaths.map((x) => "- " + x).join("\n");
21796
+ fullPrompt += "\n\nAllowed modification scope (do not cross this boundary):\n" + allowedPaths.map((x) => "- " + x).join("\n");
21786
21797
  }
21787
- fullPrompt += contract ? "\n\n\u9A8C\u6536\u4E0E\u56DE\u62A5\u5408\u540C\uFF1A\n" + contract : DO_DEFAULT_CONTRACT;
21798
+ fullPrompt += contract ? "\n\nAcceptance and reporting contract:\n" + contract : DO_DEFAULT_CONTRACT;
21788
21799
  const job = this._enqueue("do", fullPrompt, {
21789
21800
  timeoutMs,
21790
21801
  newChat: true,
@@ -21799,24 +21810,24 @@ var CursorBridge = class {
21799
21810
  }
21800
21811
  _assertNoParallelPathConflict(allowedPaths) {
21801
21812
  if (this._hasGlobalReservation()) {
21802
- throw new Error("\u5B58\u5728 Stop \u672A\u786E\u8BA4\u7684\u5168\u5C40 Cursor \u5360\u7528\uFF1B\u7981\u6B62\u63D0\u4EA4\u65B0\u7684 parallel_agent \u5199\u4EFB\u52A1");
21813
+ throw new Error("A global Cursor reservation has an unconfirmed Stop state; no new parallel_agent write task may be submitted");
21803
21814
  }
21804
21815
  const live = [...this.tasks.values()].filter((job) => job.execution === "parallel_agent" && !job.readOnly && !isTerminalTask(job));
21805
21816
  for (const job of live) {
21806
21817
  const overlap = allowedPaths.some((a) => job.allowedPaths.some((b) => pathsOverlap(a, b)));
21807
- if (overlap) throw new Error(`parallel_agent allowed_paths \u4E0E\u4EFB\u52A1 ${job.id} \u91CD\u53E0\uFF1B\u8BF7\u6539\u7528 fifo \u6216\u62C6\u6210\u4E0D\u91CD\u53E0\u8DEF\u5F84`);
21818
+ if (overlap) throw new Error(`parallel_agent allowed_paths overlap task ${job.id}; use fifo or split the work into non-overlapping paths`);
21808
21819
  }
21809
21820
  }
21810
21821
  _validateParallelAllowedPaths(allowedPaths) {
21811
21822
  for (const raw of allowedPaths) {
21812
21823
  const slash = String(raw).replace(/\\/g, "/");
21813
- if (/[*?\[\]{}!]/.test(slash)) throw new Error(`parallel_agent allowed_paths \u4E0D\u63A5\u53D7 glob\uFF1A${raw}`);
21824
+ if (/[*?\[\]{}!]/.test(slash)) throw new Error(`parallel_agent allowed_paths do not accept globs: ${raw}`);
21814
21825
  if (/^[a-zA-Z]:\//.test(slash) || slash.startsWith("/")) {
21815
- throw new Error(`parallel_agent allowed_paths \u5FC5\u987B\u4F7F\u7528\u5DE5\u4F5C\u533A\u76F8\u5BF9\u8DEF\u5F84\uFF1A${raw}`);
21826
+ throw new Error(`parallel_agent allowed_paths must use workspace-relative paths: ${raw}`);
21816
21827
  }
21817
21828
  const normalized = normalizeAllowedPath(slash);
21818
21829
  if (normalized === "." || normalized === ".." || normalized.startsWith("../")) {
21819
- throw new Error(`parallel_agent allowed_paths \u4E0D\u5F97\u4E3A\u7A7A\u6216\u8D8A\u51FA\u5DE5\u4F5C\u533A\uFF1A${raw}`);
21830
+ throw new Error(`parallel_agent allowed_paths must not be empty or escape the workspace: ${raw}`);
21820
21831
  }
21821
21832
  }
21822
21833
  }
@@ -21914,7 +21925,7 @@ var CursorBridge = class {
21914
21925
  }
21915
21926
  _cancelJob(job, reason, options = {}) {
21916
21927
  if (isTerminalTask(job)) return this._taskView(job, true);
21917
- const message = String(reason || "\u4EFB\u52A1\u5DF2\u53D6\u6D88").trim() || "\u4EFB\u52A1\u5DF2\u53D6\u6D88";
21928
+ const message = String(reason || "Task cancelled").trim() || "Task cancelled";
21918
21929
  this.queue = this.queue.filter((candidate) => candidate.id !== job.id);
21919
21930
  this.activeParallel.delete(job.id);
21920
21931
  this._invalidateParallelMonitor(job);
@@ -22040,9 +22051,9 @@ var CursorBridge = class {
22040
22051
  console.error("\u26A0\uFE0F " + rr.message + " | " + life);
22041
22052
  return;
22042
22053
  }
22043
- console.error("\u{1FA9F} cursor \u81EA\u6108\u62C9\u8D77\uFF1A" + (rr.message || rr.status) + " | " + life);
22054
+ console.error("\u{1FA9F} Cursor self-healing launch: " + (rr.message || rr.status) + " | " + life);
22044
22055
  } catch (e) {
22045
- console.error("\u26A0\uFE0F cursor \u81EA\u6108\u5931\u8D25\uFF08CCE/\u59D4\u6258\u5DF2\u4E2D\u6B62\uFF0C\u907F\u514D\u9A71\u52A8\u9519\u8BEF\u5DE5\u4F5C\u533A\uFF09\uFF1A", e.message);
22056
+ console.error("\u26A0\uFE0F Cursor self-healing failed; CCE or delegation was stopped to avoid driving the wrong workspace:", e.message);
22046
22057
  throw e;
22047
22058
  } finally {
22048
22059
  this._healing = null;
@@ -22105,7 +22116,7 @@ var CursorBridge = class {
22105
22116
  this._cancelJob(job, job.cancelReason, { underlyingStopConfirmed: true });
22106
22117
  } else {
22107
22118
  job.cancelRequested = false;
22108
- this._orphanParallelJob(job, new Error(`\u65E0\u6CD5\u786E\u8BA4 Cursor Agent \u5DF2\u505C\u6B62\uFF1A${stopped.error || stopped.state}`));
22119
+ this._orphanParallelJob(job, new Error(`Unable to confirm that the Cursor Agent stopped: ${stopped.error || stopped.state}`));
22109
22120
  job.recoveryState = "cancel_unconfirmed";
22110
22121
  }
22111
22122
  } else {
@@ -22120,19 +22131,19 @@ var CursorBridge = class {
22120
22131
  } catch (error2) {
22121
22132
  if (error2 && error2.cancelled || job.cancelRequested) {
22122
22133
  if (error2 && error2.stopConfirmed) {
22123
- this._cancelJob(job, job.cancelReason || error2.message || "\u4EFB\u52A1\u5DF2\u53D6\u6D88", {
22134
+ this._cancelJob(job, job.cancelReason || error2.message || "Task cancelled", {
22124
22135
  underlyingStopConfirmed: true
22125
22136
  });
22126
22137
  } else {
22127
22138
  job.cancelRequested = false;
22128
- this._orphanParallelJob(job, new Error("\u5DF2\u8BF7\u6C42\u53D6\u6D88\uFF0C\u4F46\u65E0\u6CD5\u786E\u8BA4 Cursor \u5DF2\u505C\u6B62\uFF1B\u5360\u7528\u7EE7\u7EED\u4FDD\u7559"));
22139
+ this._orphanParallelJob(job, new Error("Cancellation was requested, but Cursor could not be confirmed stopped; the reservation remains held"));
22129
22140
  job.recoveryState = "cancel_unconfirmed";
22130
22141
  }
22131
22142
  } else if (error2 && error2.confirmedTerminal) {
22132
22143
  this.activeParallel.delete(job.id);
22133
22144
  this._failJob(job, error2);
22134
22145
  } else if (error2 && error2.sent) {
22135
- job.error = `\u53D1\u9001\u72B6\u6001\u4E0D\u786E\u5B9A\uFF0C\u7EE7\u7EED\u6309 agentId \u76D1\u63A7\uFF1A${error2.message}`;
22146
+ job.error = `Submission state is uncertain; monitoring continues by agentId: ${error2.message}`;
22136
22147
  if (job.agentId) {
22137
22148
  job.phase = "running";
22138
22149
  job.reservationScope = job.readOnly ? "agent" : "paths";
@@ -22192,7 +22203,7 @@ var CursorBridge = class {
22192
22203
  await this._bindFifoComposerIdentity(c, options);
22193
22204
  this._throwIfCancelledBeforeSend(options);
22194
22205
  const filled = await evalJS(c, exprFill(prompt));
22195
- if (filled === "NO_INPUT" || filled === "EXEC_FAIL") throw new Error("\u586B\u5165\u67E5\u8BE2\u5931\u8D25\uFF08\u8F93\u5165\u6846\u72B6\u6001\u5F02\u5E38\uFF09");
22206
+ if (filled === "NO_INPUT" || filled === "EXEC_FAIL") throw new Error("Failed to enter the query because the input state was invalid");
22196
22207
  await sleep2(450);
22197
22208
  this._throwIfCancelledBeforeSend(options);
22198
22209
  let baseline = { messageCount: 0 };
@@ -22233,7 +22244,7 @@ var CursorBridge = class {
22233
22244
  }
22234
22245
  _throwIfCancelledBeforeSend(job) {
22235
22246
  if (!job || !job.cancelRequested || job.sendState === "dispatching" || job.sendState === "sent") return;
22236
- const error2 = new Error(job.cancelReason || "\u4EFB\u52A1\u5DF2\u53D6\u6D88");
22247
+ const error2 = new Error(job.cancelReason || "Task cancelled");
22237
22248
  error2.cancelled = true;
22238
22249
  error2.stopConfirmed = true;
22239
22250
  error2.preSend = true;
@@ -22251,7 +22262,7 @@ var CursorBridge = class {
22251
22262
  await sleep2(1300);
22252
22263
  vis = await evalJS(c, EXPR_VISIBLE);
22253
22264
  }
22254
- if (!vis) throw new Error("\u65E0\u6CD5\u6253\u5F00 Cursor chat/agent \u8F93\u5165\u9762\u677F\u3002Cursor \u662F\u5426\u767B\u5F55\u4E14\u7A97\u53E3\u6B63\u5E38\uFF1F");
22265
+ if (!vis) throw new Error("Unable to open the Cursor chat or agent input panel. Confirm that Cursor is signed in and its window is available.");
22255
22266
  }
22256
22267
  // 清空对话上下文:定位 "New Agent" 钮后【Alt+click】——Alt 修饰使其执行 Replace Agent(清空旧对话),
22257
22268
  // 而非新建(aria 标注 "New Agent (Ctrl+N) / [Alt] Replace Agent")。2026-06-08 实测回复区 markdown DOM 清空
@@ -22303,10 +22314,10 @@ var CursorBridge = class {
22303
22314
  }
22304
22315
  }
22305
22316
  async _readAgentEntries(c, keepOpen = false) {
22306
- if (!await this._ensureHistoryOpen(c)) throw new Error("Cursor Agent \u5217\u8868\u9002\u914D\u5668\u4E0D\u53EF\u7528");
22317
+ if (!await this._ensureHistoryOpen(c)) throw new Error("Cursor Agent list adapter is unavailable");
22307
22318
  try {
22308
22319
  const snapshot = JSON.parse(await evalJS(c, EXPR_HISTORY_ENTRIES));
22309
- if (!snapshot.ok) throw new Error(snapshot.error || "Agent History React adapter \u4E0D\u53EF\u7528");
22320
+ if (!snapshot.ok) throw new Error(snapshot.error || "Agent History React adapter is unavailable");
22310
22321
  return snapshot.entries || [];
22311
22322
  } finally {
22312
22323
  if (!keepOpen) await this._closeHistory(c);
@@ -22402,7 +22413,7 @@ var CursorBridge = class {
22402
22413
  if (await accepted()) return "button";
22403
22414
  }
22404
22415
  }
22405
- const error2 = new Error(`Cursor \u672A\u63A5\u53D7\u63D0\u4EA4\uFF08submit_not_accepted: ${clicked || "unknown"}\uFF09\uFF1B\u63D0\u793A\u4ECD\u5728\u8F93\u5165\u6846\u4E2D\uFF0C\u672A\u521B\u5EFA\u5B64\u513F\u4EFB\u52A1`);
22416
+ const error2 = new Error(`Cursor did not accept the submission (submit_not_accepted: ${clicked || "unknown"}); the prompt remains in the input and no orphan task was created`);
22406
22417
  error2.confirmedNotSent = true;
22407
22418
  throw error2;
22408
22419
  }
@@ -22439,7 +22450,7 @@ var CursorBridge = class {
22439
22450
  try {
22440
22451
  before = await this._readAgentEntries(c);
22441
22452
  } catch (e) {
22442
- return { fallbackReason: `parallel_agent \u524D\u7F6E\u80FD\u529B\u4E0D\u53EF\u7528\uFF1A${e.message}` };
22453
+ return { fallbackReason: `parallel_agent prerequisite is unavailable: ${e.message}` };
22443
22454
  }
22444
22455
  const previousSelectedId = (before.find((e) => e.isSelected) || {}).id || null;
22445
22456
  this._throwIfCancelledBeforeSend(job);
@@ -22448,12 +22459,12 @@ var CursorBridge = class {
22448
22459
  createdForWorkspace = job.targetUiFlavor === "agents_v2" && job.projectPath ? await this._newChat(c, { uiFlavor: job.targetUiFlavor, projectPath: job.projectPath }) : await this._clickNewAgent(c, false);
22449
22460
  } catch (error2) {
22450
22461
  if (isAgentsWorkspaceBindError(error2)) {
22451
- return { fallbackReason: "Agents Window \u65E0\u6CD5\u7ED1\u5B9A\u5F53\u524D\u4ED3\u5E93\uFF0C\u5DF2\u5728\u53D1\u9001\u524D\u964D\u7EA7 FIFO / workbench" };
22462
+ return { fallbackReason: "Agents Window could not bind the current repository; downgraded to FIFO/workbench before submission" };
22452
22463
  }
22453
22464
  throw error2;
22454
22465
  }
22455
22466
  if (!createdForWorkspace) {
22456
- return { fallbackReason: "\u627E\u4E0D\u5230 Cursor New Agent \u6309\u94AE\uFF0C\u5DF2\u5728\u53D1\u9001\u524D\u964D\u7EA7 FIFO" };
22467
+ return { fallbackReason: "Cursor New Agent button was not found; downgraded to FIFO before submission" };
22457
22468
  }
22458
22469
  let agent = null;
22459
22470
  for (let i = 0; i < 5 && !agent; i++) {
@@ -22471,7 +22482,7 @@ var CursorBridge = class {
22471
22482
  await this._ensureChatPanel(c);
22472
22483
  this._throwIfCancelledBeforeSend(job);
22473
22484
  const filled = await evalJS(c, exprFill(job.prompt));
22474
- if (filled === "NO_INPUT" || filled === "EXEC_FAIL") throw new Error("parallel_agent \u586B\u5165\u4EFB\u52A1\u5931\u8D25");
22485
+ if (filled === "NO_INPUT" || filled === "EXEC_FAIL") throw new Error("Failed to enter the parallel_agent task");
22475
22486
  await sleep2(350);
22476
22487
  this._throwIfCancelledBeforeSend(job);
22477
22488
  const providerErrorBaseline = providerErrorSignature(await this._readProviderError(c));
@@ -22487,18 +22498,26 @@ var CursorBridge = class {
22487
22498
  job.sendState = "sent";
22488
22499
  job.sentAt = (/* @__PURE__ */ new Date()).toISOString();
22489
22500
  agent = null;
22490
- for (let i = 0; i < 24 && !agent; i++) {
22501
+ let provisionalAgent = job.agentId ? { id: job.agentId, label: job.agentLabel } : null;
22502
+ for (let i = 0; i < 40 && !agent; i++) {
22491
22503
  await sleep2(350);
22492
22504
  await this._throwIfNewProviderError(c, providerErrorBaseline);
22493
22505
  try {
22494
22506
  const candidate = selectNewAgentEntry(before, await this._readAgentEntries(c));
22495
- if (candidate && (candidate.showSpinner || classifyParallelTerminalIcon(candidate.icon) !== "unknown")) agent = candidate;
22507
+ if (candidate && !provisionalAgent) {
22508
+ provisionalAgent = candidate;
22509
+ job.agentId = candidate.id;
22510
+ job.agentLabel = candidate.label || null;
22511
+ }
22512
+ if (isDurablyRegisteredParallelEntry(candidate)) agent = candidate;
22496
22513
  } catch {
22497
22514
  }
22498
22515
  }
22499
22516
  if (!agent) {
22500
- const e = new Error("\u4EFB\u52A1\u53EF\u80FD\u5DF2\u53D1\u9001\uFF0C\u4F46\u65E0\u6CD5\u4ECE Agent History \u6355\u83B7\u552F\u4E00 agentId\uFF1B\u5DF2\u4FDD\u7559\u5360\u7528\uFF0C\u7981\u6B62\u81EA\u52A8\u91CD\u53D1");
22517
+ const e = new Error(provisionalAgent ? `Cursor Agent ${provisionalAgent.id} was submitted but did not become a durable Agent History row; the reservation remains held and automatic resubmission is forbidden` : "The task may have been submitted, but a unique agentId could not be captured from Agent History; the reservation remains held and automatic resubmission is forbidden");
22501
22518
  e.sent = true;
22519
+ e.requiresGlobalReservation = !!provisionalAgent;
22520
+ e.recoveryState = provisionalAgent ? "awaiting_durable_history" : "unbound_agent";
22502
22521
  throw e;
22503
22522
  }
22504
22523
  job.agentId = agent.id;
@@ -22564,12 +22583,12 @@ var CursorBridge = class {
22564
22583
  transientErrors = 0;
22565
22584
  } catch (e) {
22566
22585
  transientErrors++;
22567
- if (transientErrors >= 45) throw new Error(`\u8FDE\u7EED\u65E0\u6CD5\u8BFB\u53D6 Agent History\uFF1A${e.message}`);
22586
+ if (transientErrors >= 45) throw new Error(`Agent History remained unreadable: ${e.message}`);
22568
22587
  continue;
22569
22588
  }
22570
22589
  if (!entry) {
22571
22590
  missingPolls++;
22572
- if (missingPolls >= 45) throw new Error(`Agent History \u4E2D\u6301\u7EED\u4E22\u5931 ${job.agentId}`);
22591
+ if (missingPolls >= 45) throw new Error(`Agent History continued to omit ${job.agentId}`);
22573
22592
  continue;
22574
22593
  }
22575
22594
  missingPolls = 0;
@@ -22588,19 +22607,19 @@ var CursorBridge = class {
22588
22607
  completedStable = 0;
22589
22608
  if (terminalErrorStable >= 2) {
22590
22609
  if (terminalClass === "needs_attention") {
22591
- throw new Error(`Cursor Agent ${job.agentId} \u6B63\u5728\u7B49\u5F85\u7528\u6237\u5904\u7406`);
22610
+ throw new Error(`Cursor Agent ${job.agentId} is waiting for user action`);
22592
22611
  }
22593
22612
  if (terminalClass === "cancelled") {
22594
22613
  await this._withJobLock(job, async () => {
22595
22614
  if (!this._monitorOwns(job, generation)) return;
22596
22615
  job.terminalEvidence = `stable_history_icon:${entry.icon}`;
22597
- this._cancelJob(job, `Cursor Agent ${job.agentId} \u5DF2\u663E\u793A\u7A33\u5B9A\u53D6\u6D88\u7EC8\u6001`, {
22616
+ this._cancelJob(job, `Cursor Agent ${job.agentId} reached a stable cancelled terminal state`, {
22598
22617
  underlyingStopConfirmed: true
22599
22618
  });
22600
22619
  });
22601
22620
  return;
22602
22621
  }
22603
- const error2 = new Error(`Cursor Agent ${job.agentId} \u663E\u793A\u7A33\u5B9A\u5931\u8D25\u72B6\u6001 ${entry.icon}`);
22622
+ const error2 = new Error(`Cursor Agent ${job.agentId} reached stable failure state ${entry.icon}`);
22604
22623
  error2.confirmedTerminal = true;
22605
22624
  throw error2;
22606
22625
  }
@@ -22629,7 +22648,7 @@ var CursorBridge = class {
22629
22648
  if (!this._monitorOwns(job, generation)) return "stale";
22630
22649
  collectionAttempts++;
22631
22650
  lastCollectionError = error2.message;
22632
- job.error = `\u7B2C ${collectionAttempts} \u6B21\u56DE\u6536\u672A\u5B8C\u6210\uFF0C\u7EE7\u7EED\u91CD\u8BD5\uFF1A${error2.message}`;
22651
+ job.error = `Result collection attempt ${collectionAttempts} did not complete; retrying: ${error2.message}`;
22633
22652
  job.phase = "running";
22634
22653
  return "retry";
22635
22654
  }
@@ -22644,8 +22663,8 @@ var CursorBridge = class {
22644
22663
  }
22645
22664
  }
22646
22665
  if (!this._monitorOwns(job, generation)) return;
22647
- const detail = lastCollectionError ? `\uFF1B\u6700\u540E\u56DE\u6536\u9519\u8BEF\uFF1A${lastCollectionError}` : "";
22648
- throw new Error(`Cursor parallel_agent \u4EFB\u52A1\u8D85\u65F6 (${job.timeoutMs}ms)${detail}`);
22666
+ const detail = lastCollectionError ? `; last collection error: ${lastCollectionError}` : "";
22667
+ throw new Error(`Cursor parallel_agent task timed out (${job.timeoutMs}ms)${detail}`);
22649
22668
  }
22650
22669
  async _waitForSelectedAgent(c, agentId, timeoutMs = 15e3) {
22651
22670
  const deadline = Date.now() + timeoutMs;
@@ -22655,7 +22674,7 @@ var CursorBridge = class {
22655
22674
  if (target && target.isSelected) return true;
22656
22675
  await sleep2(250);
22657
22676
  }
22658
- throw new Error(`\u6253\u5F00 ${agentId} \u540E\u672A\u786E\u8BA4\u5176\u6210\u4E3A\u5F53\u524D\u9009\u4E2D Agent`);
22677
+ throw new Error(`After opening ${agentId}, it could not be confirmed as the selected Agent`);
22659
22678
  }
22660
22679
  async _collectParallelAgent(job) {
22661
22680
  const page = await findPage({ targetId: job.targetId, purpose: "parallel_agent" });
@@ -22666,7 +22685,7 @@ var CursorBridge = class {
22666
22685
  const entries = await this._readAgentEntries(c, true);
22667
22686
  previousSelectedId = (entries.find((e) => e.isSelected) || {}).id || null;
22668
22687
  const opened = await evalJS(c, exprOpenAgent(job.agentId));
22669
- if (opened !== "OPENED") throw new Error(`\u65E0\u6CD5\u6253\u5F00 ${job.agentId}: ${opened}`);
22688
+ if (opened !== "OPENED") throw new Error(`Unable to open ${job.agentId}: ${opened}`);
22670
22689
  await this._closeHistory(c);
22671
22690
  await this._waitForSelectedAgent(c, job.agentId);
22672
22691
  let answer = "";
@@ -22693,7 +22712,7 @@ var CursorBridge = class {
22693
22712
  }
22694
22713
  await sleep2(300);
22695
22714
  }
22696
- if (!answer) throw new Error(`\u5DF2\u6253\u5F00 ${job.agentId}\uFF0C\u4F46\u672A\u627E\u5230\u52A9\u624B\u6700\u7EC8\u56DE\u590D`);
22715
+ if (!answer) throw new Error(`${job.agentId} was opened, but no final assistant reply was found`);
22697
22716
  if (previousSelectedId && previousSelectedId !== job.agentId) {
22698
22717
  if (await this._ensureHistoryOpen(c)) {
22699
22718
  await evalJS(c, exprOpenAgent(previousSelectedId));
@@ -22709,7 +22728,7 @@ var CursorBridge = class {
22709
22728
  }
22710
22729
  _reapWithoutResult(job, error2, evidence) {
22711
22730
  if (isTerminalTask(job)) return;
22712
- const message = error2 instanceof Error ? error2.message : String(error2 || "Cursor Agent \u5DF2\u7EC8\u6B62\uFF0C\u4F46\u6700\u7EC8\u56DE\u590D\u65E0\u6CD5\u56DE\u6536");
22731
+ const message = error2 instanceof Error ? error2.message : String(error2 || "The Cursor Agent terminated, but its final reply could not be collected");
22713
22732
  job.status = "needs_attention";
22714
22733
  job.phase = "orphaned";
22715
22734
  job.finishedAt = null;
@@ -22718,7 +22737,8 @@ var CursorBridge = class {
22718
22737
  job.resultUnavailable = true;
22719
22738
  job.terminalEvidence = evidence || "stable_completed_history_icon";
22720
22739
  job.recoveryState = "terminal_result_uncollected";
22721
- job.reservationScope = job.readOnly ? "agent" : "paths";
22740
+ job.reservationScope = uncertainSubmissionReservationScope(job, error2);
22741
+ job.recoveryState = error2.recoveryState || "monitoring_uncertain_submission";
22722
22742
  }
22723
22743
  _abandonJob(job, reason) {
22724
22744
  if (isTerminalTask(job)) return this._taskView(job, true);
@@ -22753,16 +22773,16 @@ var CursorBridge = class {
22753
22773
  } catch (error2) {
22754
22774
  job.lastRecoveryAt = (/* @__PURE__ */ new Date()).toISOString();
22755
22775
  job.recoveryState = "history_unavailable";
22756
- job.error = `\u91CD\u65B0\u68C0\u67E5 Agent History \u5931\u8D25\uFF1A${error2.message}`;
22776
+ job.error = `Failed to recheck Agent History: ${error2.message}`;
22757
22777
  return { stable: false, error: error2.message, entry: null };
22758
22778
  }
22759
22779
  job.lastRecoveryAt = (/* @__PURE__ */ new Date()).toISOString();
22760
22780
  if (!first || !second) {
22761
22781
  job.recoveryState = "agent_missing";
22762
- return { stable: false, error: "Agent History \u4E2D\u672A\u627E\u5230\u7ED1\u5B9A\u7684 agentId", entry: second || first || null };
22782
+ return { stable: false, error: "The bound agentId was not found in Agent History", entry: second || first || null };
22763
22783
  }
22764
22784
  const stable = first.id === second.id && first.showSpinner === second.showSpinner && String(first.icon || "") === String(second.icon || "");
22765
- return { stable, entry: second, error: stable ? null : "Agent History \u72B6\u6001\u5C1A\u672A\u7A33\u5B9A" };
22785
+ return { stable, entry: second, error: stable ? null : "Agent History state is not yet stable" };
22766
22786
  }
22767
22787
  async _reapParallelJob(job, options = {}) {
22768
22788
  if (!job) return { changed: false, state: "missing", task: null };
@@ -22796,11 +22816,11 @@ var CursorBridge = class {
22796
22816
  const terminalClass = classifyParallelTerminalIcon(icon);
22797
22817
  if (terminalClass === "cancelled") {
22798
22818
  job.terminalEvidence = `stable_history_icon:${icon || "cancelled"}`;
22799
- const task = this._cancelJob(job, `Cursor Agent ${job.agentId} \u5DF2\u663E\u793A\u53D6\u6D88\u7EC8\u6001`, { underlyingStopConfirmed: true });
22819
+ const task = this._cancelJob(job, `Cursor Agent ${job.agentId} reached a cancelled terminal state`, { underlyingStopConfirmed: true });
22800
22820
  return { changed: true, state: "cancelled", task };
22801
22821
  }
22802
22822
  if (terminalClass === "failed") {
22803
- const error2 = new Error(`Cursor Agent ${job.agentId} \u663E\u793A\u7A33\u5B9A\u5931\u8D25\u72B6\u6001 ${icon}`);
22823
+ const error2 = new Error(`Cursor Agent ${job.agentId} reached stable failure state ${icon}`);
22804
22824
  job.terminalEvidence = `stable_history_icon:${icon}`;
22805
22825
  this.activeParallel.delete(job.id);
22806
22826
  this._failJob(job, error2);
@@ -22825,7 +22845,7 @@ var CursorBridge = class {
22825
22845
  changed: false,
22826
22846
  state: "terminal_uncollected",
22827
22847
  error: error2.message,
22828
- next: "\u5E95\u5C42 Agent \u5DF2\u663E\u793A\u7A33\u5B9A\u5B8C\u6210\uFF0C\u4F46\u6700\u7EC8\u56DE\u590D\u5C1A\u672A\u53D6\u56DE\uFF1B\u53EF\u518D\u6B21 reap \u91CD\u8BD5\uFF0C\u6216\u5728\u63A5\u53D7\u4E22\u5931\u56DE\u590D\u65F6\u663E\u5F0F abandon\u3002",
22848
+ next: "The underlying Agent is stably complete, but its final reply has not been collected. Retry with reap, or explicitly abandon only if a missing reply is acceptable.",
22829
22849
  task: this._taskView(job, true)
22830
22850
  };
22831
22851
  }
@@ -22996,23 +23016,23 @@ var CursorBridge = class {
22996
23016
  }
22997
23017
  async taskControl(taskId, options = {}) {
22998
23018
  const id = String(taskId || "").trim();
22999
- if (!id) throw new Error("task_id \u4E0D\u80FD\u4E3A\u7A7A");
23019
+ if (!id) throw new Error("task_id must not be empty");
23000
23020
  const job = this.tasks.get(id);
23001
23021
  if (!job) return { found: false, taskId: id };
23002
23022
  const action = String(options.action || "reap").trim().toLowerCase();
23003
23023
  if (!["reap", "cancel", "abandon"].includes(action)) {
23004
- throw new Error(`\u4E0D\u652F\u6301 action=${action}\uFF1B\u53EA\u80FD\u662F reap\u3001cancel \u6216 abandon`);
23024
+ throw new Error(`Unsupported action=${action}; expected reap, cancel, or abandon`);
23005
23025
  }
23006
23026
  const reason = String(options.reason || "").trim();
23007
23027
  const expectedAgentId = String(options.expectedAgentId || "").trim();
23008
- if (action !== "reap" && options.confirm !== true) throw new Error(`${action} \u9700\u8981 confirm=true`);
23028
+ if (action !== "reap" && options.confirm !== true) throw new Error(`${action} requires confirm=true`);
23009
23029
  const submittingCancelWithoutPublishedId = action === "cancel" && job.phase === "submitting" && !expectedAgentId;
23010
23030
  if (job.agentId && action !== "reap" && !submittingCancelWithoutPublishedId && expectedAgentId !== job.agentId) {
23011
- throw new Error(`expected_agent_id \u4E0D\u5339\u914D\uFF1B\u4EFB\u52A1\u7ED1\u5B9A\u7684\u662F ${job.agentId}`);
23031
+ throw new Error(`expected_agent_id does not match; the task is bound to ${job.agentId}`);
23012
23032
  }
23013
23033
  if (action === "cancel" && !isTerminalTask(job)) {
23014
23034
  job.cancelRequested = true;
23015
- job.cancelReason = reason || (job.execution === "parallel_agent" ? "\u7528\u6237\u8BF7\u6C42\u53D6\u6D88 Cursor Agent" : "\u7528\u6237\u8BF7\u6C42\u53D6\u6D88 FIFO \u4EFB\u52A1");
23035
+ job.cancelReason = reason || (job.execution === "parallel_agent" ? "User requested Cursor Agent cancellation" : "User requested FIFO task cancellation");
23016
23036
  job.cancelRequestSeq = Number(job.cancelRequestSeq || 0) + 1;
23017
23037
  }
23018
23038
  return this._withJobLock(job, () => this._taskControlLocked(job, action, {
@@ -23025,7 +23045,7 @@ var CursorBridge = class {
23025
23045
  if (action === "reap") {
23026
23046
  const result = await this._reapParallelJobLocked(job, { reattach: true });
23027
23047
  if (result.state === "not_parallel_reservation" && job.phase === "orphaned") {
23028
- result.next = job.agentId ? "FIFO \u5DF2\u7ED1\u5B9A agentId\uFF0C\u4F46 reap \u53EA\u670D\u52A1 parallel_agent\uFF1B\u8BF7\u7528 cancel \u5B9A\u5411\u505C\u6B62\uFF0C\u6216\u5728\u786E\u8BA4\u540E abandon\u3002" : "FIFO \u5B64\u513F\u6CA1\u6709\u53EF\u5B89\u5168\u91CD\u7ED1\u7684 agentId\uFF1B\u8BF7\u5148\u5728 Cursor UI \u4EBA\u5DE5\u786E\u8BA4\u5DF2\u505C\u6B62\uFF0C\u518D\u663E\u5F0F abandon\u3002";
23048
+ result.next = job.agentId ? "FIFO is bound to an agentId, but reap applies only to parallel_agent. Use cancel for a targeted stop, or abandon after confirmation." : "The FIFO orphan has no agentId that can be safely rebound. Confirm that it stopped in the Cursor UI before explicitly abandoning it.";
23029
23049
  }
23030
23050
  return { found: true, action, ...result };
23031
23051
  }
@@ -23034,18 +23054,18 @@ var CursorBridge = class {
23034
23054
  }
23035
23055
  if (action === "abandon") {
23036
23056
  if (options.acknowledgeMayStillWrite !== true) {
23037
- throw new Error("abandon \u9700\u8981 acknowledge_may_still_write=true");
23057
+ throw new Error("abandon requires acknowledge_may_still_write=true");
23038
23058
  }
23039
- if (!options.reason) throw new Error("abandon \u5FC5\u987B\u63D0\u4F9B\u975E\u7A7A reason");
23059
+ if (!options.reason) throw new Error("abandon requires a non-empty reason");
23040
23060
  if (job.phase !== "orphaned" && job.phase !== "cancelling" && job.status !== "needs_attention") {
23041
- throw new Error("abandon \u53EA\u5141\u8BB8\u7528\u4E8E needs_attention/orphaned/cancelling \u4EFB\u52A1");
23061
+ throw new Error("abandon is allowed only for tasks in needs_attention, orphaned, or cancelling state");
23042
23062
  }
23043
23063
  return {
23044
23064
  found: true,
23045
23065
  action,
23046
23066
  changed: true,
23047
23067
  state: "abandoned",
23048
- warning: "Bridge \u5DF2\u91CA\u653E\u5360\u7528\uFF0C\u4F46\u65E0\u6CD5\u8BC1\u660E\u5E95\u5C42 Cursor Agent \u5DF2\u505C\u6B62\uFF1B\u5B83\u4ECD\u53EF\u80FD\u7EE7\u7EED\u5199\u6587\u4EF6\u3002",
23068
+ warning: "The Bridge released its reservation, but cannot prove that the underlying Cursor Agent stopped; it may still write files.",
23049
23069
  task: this._abandonJob(job, options.reason)
23050
23070
  };
23051
23071
  }
@@ -23055,7 +23075,7 @@ var CursorBridge = class {
23055
23075
  action,
23056
23076
  changed: true,
23057
23077
  state: "cancelled",
23058
- task: this._cancelJob(job, options.reason || "\u6392\u961F\u4EFB\u52A1\u5DF2\u53D6\u6D88", { underlyingStopConfirmed: true })
23078
+ task: this._cancelJob(job, options.reason || "Queued task cancelled", { underlyingStopConfirmed: true })
23059
23079
  };
23060
23080
  }
23061
23081
  if (job.phase === "orphaned" && !job.agentId) {
@@ -23065,7 +23085,7 @@ var CursorBridge = class {
23065
23085
  action,
23066
23086
  changed: false,
23067
23087
  state: "cancel_unconfirmed",
23068
- next: "\u4EFB\u52A1\u5DF2\u8FDB\u5165\u65E0\u53EF\u5B89\u5168\u5B9A\u5411\u8EAB\u4EFD\u7684\u5B64\u513F\u72B6\u6001\uFF0C\u5E76\u7EE7\u7EED\u4FDD\u7559\u5168\u5C40\u5360\u7528\u3002\u8BF7\u5148\u5728 Cursor UI \u4EBA\u5DE5\u786E\u8BA4\u5DF2\u505C\u6B62\uFF0C\u518D\u663E\u5F0F abandon\u3002",
23088
+ next: "The task is orphaned without a safely targetable identity and still holds the global reservation. Confirm that it stopped in the Cursor UI before explicitly abandoning it.",
23069
23089
  task: this._taskView(job, true)
23070
23090
  };
23071
23091
  }
@@ -23077,7 +23097,7 @@ var CursorBridge = class {
23077
23097
  action,
23078
23098
  changed: true,
23079
23099
  state: job.recoveryState,
23080
- next: "Bridge \u5DF2\u9501\u5B58\u53D6\u6D88\u8BF7\u6C42\uFF1B\u53D1\u9001\u524D\u4F1A\u4E2D\u6B62\uFF0C\u82E5\u6D88\u606F\u5DF2\u53D1\u51FA\u5219\u4F1A\u5148\u7ED1\u5B9A agentId \u518D\u5B9A\u5411\u505C\u6B62\u3002",
23100
+ next: "The Bridge latched the cancellation request. It will stop before submission, or bind the agentId and issue a targeted stop if the message was already sent.",
23081
23101
  task: this._taskView(job, true)
23082
23102
  };
23083
23103
  }
@@ -23121,14 +23141,14 @@ var CursorBridge = class {
23121
23141
  job.phase = "orphaned";
23122
23142
  job.cancelRequested = false;
23123
23143
  job.recoveryState = "cancel_unconfirmed";
23124
- job.error = `\u65E0\u6CD5\u786E\u8BA4 Cursor Agent \u5DF2\u505C\u6B62\uFF1A${stopped.error || stopped.state}`;
23144
+ job.error = `Unable to confirm that the Cursor Agent stopped: ${stopped.error || stopped.state}`;
23125
23145
  return {
23126
23146
  found: true,
23127
23147
  action,
23128
23148
  changed: false,
23129
23149
  state: "cancel_unconfirmed",
23130
23150
  stop: stopped,
23131
- next: "\u786E\u8BA4 Cursor UI \u5DF2\u505C\u6B62\u540E\uFF0C\u53EF\u518D\u6B21 cancel\uFF1B\u53EA\u6709\u660E\u786E\u627F\u62C5\u98CE\u9669\u65F6\u624D\u4F7F\u7528 abandon\u3002",
23151
+ next: "After confirming that the Cursor UI has stopped, retry cancel. Use abandon only when explicitly accepting the risk.",
23132
23152
  task: this._taskView(job, true)
23133
23153
  };
23134
23154
  }
@@ -23140,7 +23160,7 @@ var CursorBridge = class {
23140
23160
  action,
23141
23161
  changed: true,
23142
23162
  state: "cancel_pending_stop",
23143
- next: "Bridge \u5DF2\u9501\u5B58\u53D6\u6D88\u8BF7\u6C42\uFF1B\u8FD0\u884C\u4E2D\u7684 FIFO \u5C06\u6309\u5DF2\u7ED1\u5B9A\u7684 agentId \u5B9A\u5411\u505C\u6B62\uFF0C\u4E0D\u4F1A\u6A21\u7CCA\u70B9\u51FB Stop\u3002",
23163
+ next: "The Bridge latched the cancellation request. The running FIFO task will be stopped through its bound agentId without clicking an ambiguous Stop control.",
23144
23164
  task: this._taskView(job, true)
23145
23165
  };
23146
23166
  }
@@ -23151,7 +23171,7 @@ var CursorBridge = class {
23151
23171
  action,
23152
23172
  changed: true,
23153
23173
  state: "cancel_pending_fifo",
23154
- next: "FIFO \u6CA1\u6709\u53EF\u5B89\u5168\u5B9A\u5411\u7684 agentId\uFF1BBridge \u4E0D\u4F1A\u6A21\u7CCA\u70B9\u51FB Stop\u3002\u4EFB\u52A1\u4F1A\u8F6C\u4E3A\u5168\u5C40\u5B64\u513F\u5360\u7528\uFF0C\u4EBA\u5DE5\u786E\u8BA4\u505C\u6B62\u540E\u518D abandon\u3002",
23174
+ next: "FIFO has no safely targetable agentId, so the Bridge will not click an ambiguous Stop control. The task becomes a global orphan reservation; confirm that it stopped manually before abandoning it.",
23155
23175
  task: this._taskView(job, true)
23156
23176
  };
23157
23177
  }
@@ -23185,7 +23205,7 @@ var CursorBridge = class {
23185
23205
  await this._closeHistory(c);
23186
23206
  c.close();
23187
23207
  }
23188
- }).catch((e) => console.error("\u26A0\uFE0F \u6062\u590D\u539F Cursor Agent \u5931\u8D25\uFF1A" + e.message));
23208
+ }).catch((e) => console.error("\u26A0\uFE0F Failed to restore the original Cursor Agent: " + e.message));
23189
23209
  }
23190
23210
  async _waitComplete(c, timeoutMs = QUERY_TIMEOUT, baselineCount = 0, job = null, providerErrorBaseline = "") {
23191
23211
  const start = Date.now();
@@ -23203,14 +23223,14 @@ var CursorBridge = class {
23203
23223
  } catch (error2) {
23204
23224
  stopped = { confirmed: false, state: "stop_error", error: error2.message };
23205
23225
  }
23206
- const e2 = new Error(job.cancelReason || "\u4EFB\u52A1\u5DF2\u53D6\u6D88");
23226
+ const e2 = new Error(job.cancelReason || "Task cancelled");
23207
23227
  e2.cancelled = true;
23208
23228
  e2.stopConfirmed = stopped.confirmed === true;
23209
23229
  e2.stop = stopped;
23210
23230
  if (stopped.confirmed) job.terminalEvidence = `targeted_stop:${job.agentId}`;
23211
23231
  throw e2;
23212
23232
  }
23213
- const e = new Error(job.cancelReason || "\u4EFB\u52A1\u5DF2\u53D6\u6D88");
23233
+ const e = new Error(job.cancelReason || "Task cancelled");
23214
23234
  e.cancelled = true;
23215
23235
  e.stopConfirmed = false;
23216
23236
  throw e;
@@ -23254,8 +23274,8 @@ var CursorBridge = class {
23254
23274
  sawStop,
23255
23275
  baselineCount
23256
23276
  })) return ans;
23257
- const taskHint = job && job.id ? `\uFF1Btask_id=${job.id}\uFF0C\u8BF7\u7528 cursor_status(task_id) \u68C0\u67E5\u5E76\u6309\u6062\u590D\u6D41\u7A0B\u5904\u7406` : "";
23258
- throw new Error(`Cursor \u4EFB\u52A1\u8D85\u65F6 (${timeoutMs}ms)\uFF0C\u5C1A\u672A\u786E\u8BA4\u751F\u6210\u5DF2\u505C\u6B62\u5E76\u4EA7\u751F\u5B8C\u6574\u52A9\u624B\u56DE\u590D${taskHint}`);
23277
+ const taskHint = job && job.id ? `; task_id=${job.id}. Inspect it with cursor_status(task_id) and follow the recovery flow` : "";
23278
+ throw new Error(`Cursor task timed out (${timeoutMs}ms) before generation was confirmed stopped with a complete assistant reply${taskHint}`);
23259
23279
  }
23260
23280
  _taskView(job, includeResult = false) {
23261
23281
  const view = {
@@ -23298,9 +23318,9 @@ var CursorBridge = class {
23298
23318
  if (includeResult || isTerminalTask(job)) view.result = job.result;
23299
23319
  if (job.phase === "orphaned") {
23300
23320
  if (job.recoveryState === "terminal_result_uncollected") {
23301
- view.attention = "Agent History \u5DF2\u8BC1\u660E\u5E95\u5C42\u4EFB\u52A1\u7ED3\u675F\uFF0C\u4F46\u6700\u7EC8\u56DE\u590D\u5C1A\u672A\u53D6\u56DE\uFF1B\u518D\u6B21 reap \u91CD\u8BD5\uFF0C\u6216\u5728\u63A5\u53D7\u4E22\u5931\u56DE\u590D\u65F6\u663E\u5F0F abandon\u3002";
23321
+ view.attention = "Agent History proves that the underlying task ended, but its final reply has not been collected. Retry with reap, or explicitly abandon only if a missing reply is acceptable.";
23302
23322
  } else {
23303
- view.attention = job.agentId ? job.execution === "parallel_agent" ? "\u7528 cursor_task_control(action=reap) \u663E\u5F0F\u91CD\u67E5\u539F agentId\uFF1B\u9700\u8981\u505C\u6B62\u65F6\u7528 cancel\uFF1B\u53EA\u6709\u5DF2\u4EBA\u5DE5\u786E\u8BA4\u4E14\u63A5\u53D7\u6B8B\u4F59\u5199\u5165\u98CE\u9669\u65F6\u624D abandon\u3002" : "FIFO \u5DF2\u7ED1\u5B9A agentId\uFF1B\u7528 cursor_task_control(action=cancel) \u5E76\u4F20\u5165\u7CBE\u786E expected_agent_id \u5B9A\u5411\u505C\u6B62\u3002" : "\u8BE5\u5B64\u513F\u6CA1\u6709\u53EF\u5B89\u5168\u91CD\u7ED1\u7684 agentId\uFF0C\u5E76\u5168\u5C40\u963B\u65AD\u65B0\u59D4\u6258\uFF1B\u8BF7\u5148\u5728 Cursor UI \u4EBA\u5DE5\u786E\u8BA4\u5DF2\u505C\u6B62\uFF0C\u518D\u7528 cursor_task_control(action=abandon) \u663E\u5F0F\u91CA\u653E\u3002";
23323
+ view.attention = job.agentId ? job.execution === "parallel_agent" ? "Use cursor_task_control(action=reap) to recheck the original agentId. Use cancel when a stop is needed, and abandon only after manual confirmation while accepting residual write risk." : "FIFO is bound to an agentId. Use cursor_task_control(action=cancel) with the exact expected_agent_id for a targeted stop." : "This orphan has no agentId that can be safely rebound and globally blocks new delegation. Confirm that it stopped in the Cursor UI, then explicitly release it with cursor_task_control(action=abandon).";
23304
23324
  }
23305
23325
  }
23306
23326
  return view;
@@ -23441,7 +23461,7 @@ function buildToolDefinitions(bridgeInstance) {
23441
23461
  var ADAPTER_START_CWD = process.cwd();
23442
23462
  var bridge = new CursorBridge({ adapterStartCwd: ADAPTER_START_CWD });
23443
23463
  var server = new Server(
23444
- { name: "cursor-bridge", version: "5.4.2" },
23464
+ { name: "cursor-bridge", version: "5.5.0" },
23445
23465
  { capabilities: { tools: { listChanged: true } } }
23446
23466
  );
23447
23467
  async function ensureBridgeCursor(targetBridge, reason) {
@@ -23555,26 +23575,26 @@ server.setRequestHandler(CallToolRequestSchema, async (request2) => {
23555
23575
  const r = await ensureBridgeCursor(bridge, "cursor_launch");
23556
23576
  return { content: [{ type: "text", text: JSON.stringify(r, null, 2) }], isError: !r.ok };
23557
23577
  }
23558
- throw new Error(`\u672A\u77E5\u5DE5\u5177: ${name}`);
23578
+ throw new Error(`Unknown tool: ${name}`);
23559
23579
  } catch (error2) {
23560
- return { content: [{ type: "text", text: `\u9519\u8BEF: ${error2 instanceof Error ? error2.message : String(error2)}` }], isError: true };
23580
+ return { content: [{ type: "text", text: `Error: ${error2 instanceof Error ? error2.message : String(error2)}` }], isError: true };
23561
23581
  }
23562
23582
  });
23563
23583
  async function main() {
23564
- console.error("\u{1F680} \u542F\u52A8 cursor-bridge\uFF08CDP \u76F4\u9A71 :" + CDP_PORT2 + "\uFF09...");
23584
+ console.error("\u{1F680} Starting cursor-bridge (direct CDP on port " + CDP_PORT2 + ")...");
23565
23585
  const releasedCwd = releaseAdapterWorkingDirectory();
23566
- console.error(`\u{1F513} MCP \u5DE5\u4F5C\u76EE\u5F55\u5DF2\u79FB\u51FA\u63D2\u4EF6\u7F13\u5B58\uFF1A${releasedCwd}`);
23586
+ console.error(`\u{1F513} MCP working directory released from the plugin cache: ${releasedCwd}`);
23567
23587
  const startupEnsure = shouldAutoLaunchCursor() ? ensureBridgeCursor(bridge, "adapter-startup").then((r) => {
23568
23588
  console.error(
23569
- "\u{1FA9F} \u542F\u52A8\u5373\u786E\u4FDD Cursor\uFF1A" + (r.message || r.status) + " | adapterPid=" + bridge._lastLifecycle.adapterPid + " supervisorPid=" + bridge._lastLifecycle.supervisorPid + " reused=" + bridge._lastLifecycle.reusedSupervisor + " reason=" + bridge._lastLifecycle.launchReason
23589
+ "\u{1FA9F} Startup Cursor check: " + (r.message || r.status) + " | adapterPid=" + bridge._lastLifecycle.adapterPid + " supervisorPid=" + bridge._lastLifecycle.supervisorPid + " reused=" + bridge._lastLifecycle.reusedSupervisor + " reason=" + bridge._lastLifecycle.launchReason
23570
23590
  );
23571
23591
  return r;
23572
23592
  }).catch((error2) => {
23573
- console.error("\u26A0\uFE0F \u542F\u52A8\u5373\u62C9\u8D77 Cursor \u5931\u8D25\uFF08\u5FFD\u7565\uFF0C\u6309\u9700\u518D\u62C9\uFF09\uFF1A", error2.message);
23593
+ console.error("\u26A0\uFE0F Startup Cursor launch failed; continuing and retrying on demand:", error2.message);
23574
23594
  return null;
23575
23595
  }) : Promise.resolve(null);
23576
23596
  await server.connect(new StdioServerTransport());
23577
- console.error("\u2705 MCP \u5DF2\u8FDE\u63A5\u3002");
23597
+ console.error("\u2705 MCP connected.");
23578
23598
  void startupEnsure;
23579
23599
  }
23580
23600
  var isMain2 = import.meta.url === pathToFileURL2(process.argv[1] || "").href;
@@ -23582,7 +23602,7 @@ if (isMain2) {
23582
23602
  process.on("unhandledRejection", (r) => console.error("unhandledRejection:", r));
23583
23603
  process.on("SIGINT", () => process.exit(0));
23584
23604
  main().catch((e) => {
23585
- console.error("\u274C \u81F4\u547D\u9519\u8BEF:", e);
23605
+ console.error("\u274C Fatal error:", e);
23586
23606
  process.exit(1);
23587
23607
  });
23588
23608
  }
@@ -23611,6 +23631,7 @@ export {
23611
23631
  exprOpenAgent,
23612
23632
  isBlankAgentsWindow,
23613
23633
  isConfirmedCompletedReply,
23634
+ isDurablyRegisteredParallelEntry,
23614
23635
  isTargetedStopConfirmed,
23615
23636
  normalizeAllowedPath,
23616
23637
  normalizeCceSearchResult,
@@ -23627,5 +23648,6 @@ export {
23627
23648
  shouldAutoLaunchCursor,
23628
23649
  shouldRecoverNormalAgentsPresentation,
23629
23650
  summarizeCdpPages,
23651
+ uncertainSubmissionReservationScope,
23630
23652
  updateStableEntryObservation
23631
23653
  };