@rama_nigg/open-cursor 2.3.2 → 2.3.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.
package/dist/index.js CHANGED
@@ -1,20 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
- var __create = Object.create;
3
- var __getProtoOf = Object.getPrototypeOf;
4
2
  var __defProp = Object.defineProperty;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __toESM = (mod, isNodeMode, target) => {
8
- target = mod != null ? __create(__getProtoOf(mod)) : {};
9
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
- for (let key of __getOwnPropNames(mod))
11
- if (!__hasOwnProp.call(to, key))
12
- __defProp(to, key, {
13
- get: () => mod[key],
14
- enumerable: true
15
- });
16
- return to;
17
- };
18
3
  var __export = (target, all) => {
19
4
  for (var name in all)
20
5
  __defProp(target, name, {
@@ -13629,41 +13614,46 @@ function extractAllowedToolNames(tools) {
13629
13614
  }
13630
13615
  function extractOpenAiToolCall(event, allowedToolNames) {
13631
13616
  if (allowedToolNames.size === 0) {
13632
- return null;
13617
+ return { action: "skip", skipReason: "no_allowed_tools" };
13633
13618
  }
13634
13619
  const { name, args, skipped } = extractToolNameAndArgs(event);
13635
13620
  if (skipped) {
13636
- return null;
13621
+ return { action: "skip", skipReason: "event_skipped" };
13637
13622
  }
13638
13623
  if (!name) {
13639
- return null;
13624
+ return { action: "skip", skipReason: "no_name" };
13640
13625
  }
13641
13626
  const resolvedName = resolveAllowedToolName(name, allowedToolNames);
13642
- if (!resolvedName) {
13643
- log5.debug("Tool call name not allowed; skipping interception", {
13644
- name,
13645
- normalized: normalizeAliasKey(name),
13646
- allowedToolCount: allowedToolNames.size,
13647
- aliasTarget: TOOL_NAME_ALIASES.get(normalizeAliasKey(name)) ?? null
13648
- });
13649
- return null;
13650
- }
13651
- if (args === undefined && event.subtype === "started") {
13652
- log5.debug("Tool call args extraction returned undefined", {
13653
- toolName: name,
13654
- subtype: event.subtype ?? "none",
13655
- payloadKeys: Object.entries(event.tool_call || {}).map(([k, v]) => `${k}:[${isRecord(v) ? Object.keys(v).join(",") : typeof v}]`),
13656
- hasCallId: Boolean(event.call_id)
13657
- });
13627
+ if (resolvedName) {
13628
+ if (args === undefined && event.subtype === "started") {
13629
+ log5.debug("Tool call args extraction returned undefined", {
13630
+ toolName: name,
13631
+ subtype: event.subtype ?? "none",
13632
+ payloadKeys: Object.entries(event.tool_call || {}).map(([k, v]) => `${k}:[${isRecord(v) ? Object.keys(v).join(",") : typeof v}]`),
13633
+ hasCallId: Boolean(event.call_id)
13634
+ });
13635
+ }
13636
+ const callId = event.call_id || event.tool_call_id || "call_unknown";
13637
+ return {
13638
+ action: "intercept",
13639
+ toolCall: {
13640
+ id: callId,
13641
+ type: "function",
13642
+ function: {
13643
+ name: resolvedName,
13644
+ arguments: toOpenAiArguments(args)
13645
+ }
13646
+ }
13647
+ };
13658
13648
  }
13659
- const callId = event.call_id || event.tool_call_id || "call_unknown";
13649
+ log5.debug("Tool call not in allowlist; passing through to cursor-agent", {
13650
+ name,
13651
+ normalized: normalizeAliasKey(name),
13652
+ allowedToolCount: allowedToolNames.size
13653
+ });
13660
13654
  return {
13661
- id: callId,
13662
- type: "function",
13663
- function: {
13664
- name: resolvedName,
13665
- arguments: toOpenAiArguments(args)
13666
- }
13655
+ action: "passthrough",
13656
+ passthroughName: name
13667
13657
  };
13668
13658
  }
13669
13659
  function createToolCallCompletionResponse(meta, toolCall) {
@@ -16403,7 +16393,7 @@ function createSharedBoundary(providerId) {
16403
16393
  },
16404
16394
  maybeExtractToolCall(event, allowedToolNames, toolLoopMode) {
16405
16395
  if (toolLoopMode !== "opencode") {
16406
- return null;
16396
+ return { action: "skip", skipReason: "tool_loop_mode_not_opencode" };
16407
16397
  }
16408
16398
  return extractOpenAiToolCall(event, allowedToolNames);
16409
16399
  },
@@ -16830,9 +16820,33 @@ async function handleToolLoopEventLegacy(options) {
16830
16820
  responseMeta,
16831
16821
  onToolUpdate,
16832
16822
  onToolResult,
16833
- onInterceptedToolCall
16823
+ onInterceptedToolCall,
16824
+ passThroughTracker
16834
16825
  } = options;
16835
- const interceptedToolCall = toolLoopMode === "opencode" ? extractOpenAiToolCall(event, allowedToolNames) : null;
16826
+ const extraction = toolLoopMode === "opencode" ? extractOpenAiToolCall(event, allowedToolNames) : { action: "skip", skipReason: "tool_loop_mode_not_opencode" };
16827
+ if (extraction.action === "passthrough") {
16828
+ passThroughTracker?.trackTool(extraction.passthroughName);
16829
+ log13.debug("MCP tool passed through to cursor-agent (legacy)", {
16830
+ tool: extraction.passthroughName
16831
+ });
16832
+ return { intercepted: false, skipConverter: false };
16833
+ }
16834
+ if (extraction.action === "skip" || !extraction.toolCall) {
16835
+ const updates2 = await toolMapper.mapCursorEventToAcp(event, event.session_id ?? toolSessionId);
16836
+ if (shouldEmitToolUpdates) {
16837
+ for (const update of updates2) {
16838
+ await onToolUpdate(update);
16839
+ }
16840
+ }
16841
+ if (toolRouter && proxyExecuteToolCalls) {
16842
+ const toolResult = await toolRouter.handleToolCall(event, responseMeta);
16843
+ if (toolResult) {
16844
+ await onToolResult(toolResult);
16845
+ }
16846
+ }
16847
+ return { intercepted: false, skipConverter: suppressConverterToolEvents };
16848
+ }
16849
+ const interceptedToolCall = extraction.toolCall;
16836
16850
  if (interceptedToolCall) {
16837
16851
  const compat2 = applyToolSchemaCompat(interceptedToolCall, toolSchemaMap);
16838
16852
  let normalizedToolCall = compat2.toolCall;
@@ -16909,118 +16923,125 @@ async function handleToolLoopEventV1(options) {
16909
16923
  responseMeta,
16910
16924
  onToolUpdate,
16911
16925
  onToolResult,
16912
- onInterceptedToolCall
16926
+ onInterceptedToolCall,
16927
+ passThroughTracker
16913
16928
  } = options;
16914
- let interceptedToolCall;
16929
+ let extraction;
16915
16930
  try {
16916
- interceptedToolCall = boundary.maybeExtractToolCall(event, allowedToolNames, toolLoopMode);
16931
+ extraction = boundary.maybeExtractToolCall(event, allowedToolNames, toolLoopMode);
16917
16932
  } catch (error45) {
16918
16933
  throw new ToolBoundaryExtractionError("Boundary tool extraction failed", error45);
16919
16934
  }
16920
- if (interceptedToolCall) {
16921
- const compat2 = applyToolSchemaCompat(interceptedToolCall, toolSchemaMap);
16922
- interceptedToolCall = compat2.toolCall;
16923
- const editDiag = interceptedToolCall.function.name.toLowerCase() === "edit" ? {
16924
- rawArgs: safeArgTypeSummary(event),
16925
- normalizedArgs: compat2.normalizedArgs
16926
- } : undefined;
16927
- log13.debug("Applied tool schema compatibility", {
16928
- tool: interceptedToolCall.function.name,
16929
- originalArgKeys: compat2.originalArgKeys,
16930
- normalizedArgKeys: compat2.normalizedArgKeys,
16931
- collisionKeys: compat2.collisionKeys,
16932
- validationOk: compat2.validation.ok,
16933
- ...editDiag ? { editDiag } : {}
16935
+ if (extraction.action === "passthrough") {
16936
+ passThroughTracker?.trackTool(extraction.passthroughName);
16937
+ log13.debug("MCP tool passed through to cursor-agent (v1)", {
16938
+ tool: extraction.passthroughName
16934
16939
  });
16935
- if (compat2.validation.hasSchema && !compat2.validation.ok) {
16936
- log13.debug("Tool schema compatibility validation failed", {
16937
- tool: interceptedToolCall.function.name,
16940
+ return { intercepted: false, skipConverter: false };
16941
+ }
16942
+ if (extraction.action === "skip" || !extraction.toolCall) {
16943
+ const updates = await toolMapper.mapCursorEventToAcp(event, event.session_id ?? toolSessionId);
16944
+ if (shouldEmitToolUpdates) {
16945
+ for (const update of updates) {
16946
+ await onToolUpdate(update);
16947
+ }
16948
+ }
16949
+ if (toolRouter && proxyExecuteToolCalls) {
16950
+ const toolResult = await toolRouter.handleToolCall(event, responseMeta);
16951
+ if (toolResult) {
16952
+ await onToolResult(toolResult);
16953
+ }
16954
+ }
16955
+ return { intercepted: false, skipConverter: suppressConverterToolEvents };
16956
+ }
16957
+ const interceptedToolCall = extraction.toolCall;
16958
+ const compat2 = applyToolSchemaCompat(interceptedToolCall, toolSchemaMap);
16959
+ let normalizedToolCall = compat2.toolCall;
16960
+ const editDiag = normalizedToolCall.function.name.toLowerCase() === "edit" ? {
16961
+ rawArgs: safeArgTypeSummary(event),
16962
+ normalizedArgs: compat2.normalizedArgs
16963
+ } : undefined;
16964
+ log13.debug("Applied tool schema compatibility", {
16965
+ tool: normalizedToolCall.function.name,
16966
+ originalArgKeys: compat2.originalArgKeys,
16967
+ normalizedArgKeys: compat2.normalizedArgKeys,
16968
+ collisionKeys: compat2.collisionKeys,
16969
+ validationOk: compat2.validation.ok,
16970
+ ...editDiag ? { editDiag } : {}
16971
+ });
16972
+ if (compat2.validation.hasSchema && !compat2.validation.ok) {
16973
+ log13.debug("Tool schema compatibility validation failed", {
16974
+ tool: normalizedToolCall.function.name,
16975
+ missing: compat2.validation.missing,
16976
+ unexpected: compat2.validation.unexpected,
16977
+ typeErrors: compat2.validation.typeErrors,
16978
+ repairHint: compat2.validation.repairHint
16979
+ });
16980
+ const validationTermination = evaluateSchemaValidationLoopGuard(toolLoopGuard, normalizedToolCall, compat2.validation);
16981
+ if (validationTermination) {
16982
+ return { intercepted: false, skipConverter: true, terminate: validationTermination };
16983
+ }
16984
+ const termination2 = evaluateToolLoopGuard(toolLoopGuard, normalizedToolCall);
16985
+ if (termination2) {
16986
+ return { intercepted: false, skipConverter: true, terminate: termination2 };
16987
+ }
16988
+ const reroutedWrite = tryRerouteEditToWrite(normalizedToolCall, compat2.normalizedArgs, allowedToolNames, toolSchemaMap);
16989
+ if (reroutedWrite) {
16990
+ log13.debug("Rerouting malformed edit call to write", {
16991
+ path: reroutedWrite.path,
16938
16992
  missing: compat2.validation.missing,
16939
- unexpected: compat2.validation.unexpected,
16940
- typeErrors: compat2.validation.typeErrors,
16941
- repairHint: compat2.validation.repairHint
16993
+ typeErrors: compat2.validation.typeErrors
16942
16994
  });
16943
- const validationTermination = evaluateSchemaValidationLoopGuard(toolLoopGuard, interceptedToolCall, compat2.validation);
16944
- if (validationTermination) {
16945
- return { intercepted: false, skipConverter: true, terminate: validationTermination };
16946
- }
16947
- const termination2 = evaluateToolLoopGuard(toolLoopGuard, interceptedToolCall);
16948
- if (termination2) {
16949
- return { intercepted: false, skipConverter: true, terminate: termination2 };
16950
- }
16951
- const reroutedWrite = tryRerouteEditToWrite(interceptedToolCall, compat2.normalizedArgs, allowedToolNames, toolSchemaMap);
16952
- if (reroutedWrite) {
16953
- log13.debug("Rerouting malformed edit call to write", {
16954
- path: reroutedWrite.path,
16955
- missing: compat2.validation.missing,
16956
- typeErrors: compat2.validation.typeErrors
16957
- });
16958
- await onInterceptedToolCall(reroutedWrite.toolCall);
16959
- return {
16960
- intercepted: true,
16961
- skipConverter: true
16962
- };
16963
- }
16964
- if (schemaValidationFailureMode === "pass_through" && shouldTerminateOnSchemaValidation(interceptedToolCall, compat2.validation)) {
16965
- return {
16966
- intercepted: false,
16967
- skipConverter: true,
16968
- terminate: createSchemaValidationTermination(interceptedToolCall, compat2.validation)
16969
- };
16970
- }
16971
- if (schemaValidationFailureMode === "pass_through" && shouldEmitNonFatalSchemaValidationHint(interceptedToolCall, compat2.validation)) {
16972
- const hintChunk = createNonFatalSchemaValidationHintChunk(responseMeta, interceptedToolCall, compat2.validation);
16973
- log13.debug("Emitting non-fatal schema validation hint and skipping malformed tool execution", {
16974
- tool: interceptedToolCall.function.name,
16975
- missing: compat2.validation.missing,
16976
- typeErrors: compat2.validation.typeErrors
16977
- });
16978
- await onToolResult(hintChunk);
16979
- return {
16980
- intercepted: false,
16981
- skipConverter: true
16982
- };
16983
- }
16984
- if (schemaValidationFailureMode === "terminate") {
16985
- return {
16986
- intercepted: false,
16987
- skipConverter: true,
16988
- terminate: createSchemaValidationTermination(interceptedToolCall, compat2.validation)
16989
- };
16990
- }
16991
- log13.debug("Forwarding schema-invalid tool call to OpenCode loop", {
16992
- tool: interceptedToolCall.function.name,
16993
- repairHint: compat2.validation.repairHint
16994
- });
16995
- await onInterceptedToolCall(interceptedToolCall);
16995
+ await onInterceptedToolCall(reroutedWrite.toolCall);
16996
16996
  return {
16997
16997
  intercepted: true,
16998
16998
  skipConverter: true
16999
16999
  };
17000
17000
  }
17001
- const termination = evaluateToolLoopGuard(toolLoopGuard, interceptedToolCall);
17002
- if (termination) {
17003
- return { intercepted: false, skipConverter: true, terminate: termination };
17001
+ if (schemaValidationFailureMode === "pass_through" && shouldTerminateOnSchemaValidation(normalizedToolCall, compat2.validation)) {
17002
+ return {
17003
+ intercepted: false,
17004
+ skipConverter: true,
17005
+ terminate: createSchemaValidationTermination(normalizedToolCall, compat2.validation)
17006
+ };
17004
17007
  }
17005
- await onInterceptedToolCall(interceptedToolCall);
17006
- return { intercepted: true, skipConverter: true };
17007
- }
17008
- const updates = await toolMapper.mapCursorEventToAcp(event, event.session_id ?? toolSessionId);
17009
- if (shouldEmitToolUpdates) {
17010
- for (const update of updates) {
17011
- await onToolUpdate(update);
17008
+ if (schemaValidationFailureMode === "pass_through" && shouldEmitNonFatalSchemaValidationHint(normalizedToolCall, compat2.validation)) {
17009
+ const hintChunk = createNonFatalSchemaValidationHintChunk(responseMeta, normalizedToolCall, compat2.validation);
17010
+ log13.debug("Emitting non-fatal schema validation hint and skipping malformed tool execution", {
17011
+ tool: normalizedToolCall.function.name,
17012
+ missing: compat2.validation.missing,
17013
+ typeErrors: compat2.validation.typeErrors
17014
+ });
17015
+ await onToolResult(hintChunk);
17016
+ return {
17017
+ intercepted: false,
17018
+ skipConverter: true
17019
+ };
17012
17020
  }
17013
- }
17014
- if (toolRouter && proxyExecuteToolCalls) {
17015
- const toolResult = await toolRouter.handleToolCall(event, responseMeta);
17016
- if (toolResult) {
17017
- await onToolResult(toolResult);
17021
+ if (schemaValidationFailureMode === "terminate") {
17022
+ return {
17023
+ intercepted: false,
17024
+ skipConverter: true,
17025
+ terminate: createSchemaValidationTermination(normalizedToolCall, compat2.validation)
17026
+ };
17018
17027
  }
17028
+ log13.debug("Forwarding schema-invalid tool call to OpenCode loop", {
17029
+ tool: normalizedToolCall.function.name,
17030
+ repairHint: compat2.validation.repairHint
17031
+ });
17032
+ await onInterceptedToolCall(normalizedToolCall);
17033
+ return {
17034
+ intercepted: true,
17035
+ skipConverter: true
17036
+ };
17019
17037
  }
17020
- return {
17021
- intercepted: false,
17022
- skipConverter: suppressConverterToolEvents
17023
- };
17038
+ const termination = evaluateToolLoopGuard(toolLoopGuard, normalizedToolCall);
17039
+ if (termination) {
17040
+ return { intercepted: false, skipConverter: true, terminate: termination };
17041
+ }
17042
+ await onInterceptedToolCall(normalizedToolCall);
17043
+ return { intercepted: true, skipConverter: true };
17044
+ return { intercepted: false, skipConverter: suppressConverterToolEvents };
17024
17045
  }
17025
17046
  async function handleToolLoopEventWithFallback(options) {
17026
17047
  const {
@@ -17301,6 +17322,80 @@ var init_runtime_interception = __esm(() => {
17301
17322
  };
17302
17323
  });
17303
17324
 
17325
+ // src/provider/passthrough-tracker.ts
17326
+ class PassThroughTracker {
17327
+ tools = new Set;
17328
+ errors = [];
17329
+ trackTool(name) {
17330
+ this.tools.add(name);
17331
+ }
17332
+ trackError(toolName, message) {
17333
+ this.errors.push(`${toolName}: ${message}`);
17334
+ }
17335
+ getSummary() {
17336
+ return {
17337
+ tools: Array.from(this.tools),
17338
+ errors: [...this.errors],
17339
+ hasActivity: this.tools.size > 0
17340
+ };
17341
+ }
17342
+ reset() {
17343
+ this.tools.clear();
17344
+ this.errors.length = 0;
17345
+ }
17346
+ }
17347
+
17348
+ // src/services/toast-service.ts
17349
+ class ToastService {
17350
+ client = null;
17351
+ setClient(client3) {
17352
+ this.client = client3;
17353
+ }
17354
+ async show(options) {
17355
+ if (!this.client?.tui?.showToast) {
17356
+ log14.debug("Toast not available; client.tui.showToast missing", { message: options.message });
17357
+ return;
17358
+ }
17359
+ try {
17360
+ await this.client.tui.showToast({
17361
+ body: {
17362
+ title: options.title,
17363
+ message: options.message,
17364
+ variant: options.variant
17365
+ }
17366
+ });
17367
+ } catch (error45) {
17368
+ log14.debug("Toast failed", { error: error45, message: options.message });
17369
+ }
17370
+ }
17371
+ async showPassThroughSummary(tools) {
17372
+ if (tools.length === 0)
17373
+ return;
17374
+ const toolList = tools.length <= 3 ? tools.join(", ") : `${tools.slice(0, 3).join(", ")} +${tools.length - 3} more`;
17375
+ await this.show({
17376
+ title: "MCP Tools",
17377
+ message: `\uD83C\uDFAD ${tools.length} tool${tools.length > 1 ? "s" : ""} handled by cursor-agent: ${toolList}`,
17378
+ variant: "info"
17379
+ });
17380
+ }
17381
+ async showErrorSummary(errors3) {
17382
+ if (errors3.length === 0)
17383
+ return;
17384
+ const errorList = errors3.length <= 2 ? errors3.join("; ") : `${errors3.slice(0, 2).join("; ")} +${errors3.length - 2} more`;
17385
+ await this.show({
17386
+ title: "MCP Errors",
17387
+ message: `⚠️ ${errors3.length} MCP tool${errors3.length > 1 ? "s" : ""} failed: ${errorList}`,
17388
+ variant: "warning"
17389
+ });
17390
+ }
17391
+ }
17392
+ var log14, toastService;
17393
+ var init_toast_service = __esm(() => {
17394
+ init_logger();
17395
+ log14 = createLogger("services:toast");
17396
+ toastService = new ToastService;
17397
+ });
17398
+
17304
17399
  // src/provider/tool-loop-guard.ts
17305
17400
  function parseToolLoopMaxRepeat(value) {
17306
17401
  if (value === undefined) {
@@ -17443,25 +17538,6 @@ function indexToolLoopHistory(messages) {
17443
17538
  incrementCount(initialValidationCounts, `${call.name}|schema:${schemaSignature}|validation`);
17444
17539
  incrementCount(initialValidationCoarseCounts, `${call.name}|validation`);
17445
17540
  }
17446
- const strippedRounds = countStrippedAssistantRounds(messages);
17447
- if (strippedRounds > 0 && assistantCalls.length > 0) {
17448
- for (const call of assistantCalls) {
17449
- const errorClass = normalizeErrorClassForTool(call.name, byCallId.get(call.id) ?? latestByToolName.get(call.name) ?? latest ?? "unknown");
17450
- if (errorClass !== "success") {
17451
- continue;
17452
- }
17453
- const coarseSuccessFP = deriveSuccessCoarseFingerprint(call.name, call.rawArguments);
17454
- if (coarseSuccessFP) {
17455
- for (let i = 0;i < strippedRounds; i++) {
17456
- incrementCount(initialCoarseCounts, coarseSuccessFP);
17457
- }
17458
- }
17459
- const successFP = `${call.name}|values:${call.argValueSignature}|success`;
17460
- for (let i = 0;i < strippedRounds; i++) {
17461
- incrementCount(initialCounts, successFP);
17462
- }
17463
- }
17464
- }
17465
17541
  return {
17466
17542
  byCallId,
17467
17543
  latest,
@@ -17684,23 +17760,6 @@ function normalizeErrorClassForTool(toolName, errorClass) {
17684
17760
  }
17685
17761
  return errorClass;
17686
17762
  }
17687
- function countStrippedAssistantRounds(messages) {
17688
- let count = 0;
17689
- for (const message of messages) {
17690
- if (!isRecord4(message) || message.role !== "assistant") {
17691
- continue;
17692
- }
17693
- if (Array.isArray(message.tool_calls) && message.tool_calls.length > 0) {
17694
- continue;
17695
- }
17696
- const content = message.content;
17697
- const hasContent = typeof content === "string" && content.trim().length > 0 || Array.isArray(content) && content.length > 0;
17698
- if (!hasContent) {
17699
- count++;
17700
- }
17701
- }
17702
- return count;
17703
- }
17704
17763
  function toLowerText(content) {
17705
17764
  const rendered = renderContent(content);
17706
17765
  return rendered.trim().toLowerCase();
@@ -17785,9 +17844,9 @@ async function ensurePluginDirectory() {
17785
17844
  const pluginDir = join4(configHome, "opencode", "plugin");
17786
17845
  try {
17787
17846
  await mkdir(pluginDir, { recursive: true });
17788
- log14.debug("Plugin directory ensured", { path: pluginDir });
17847
+ log15.debug("Plugin directory ensured", { path: pluginDir });
17789
17848
  } catch (error45) {
17790
- log14.warn("Failed to create plugin directory", { error: String(error45) });
17849
+ log15.warn("Failed to create plugin directory", { error: String(error45) });
17791
17850
  }
17792
17851
  }
17793
17852
  function shouldProcessModel(model) {
@@ -17975,9 +18034,9 @@ function createBoundaryRuntimeContext(scope) {
17975
18034
  error: toErrorMessage(error45)
17976
18035
  };
17977
18036
  if (!fallbackActive) {
17978
- log14.warn("Provider boundary v1 failed; switching to legacy for this request", details);
18037
+ log15.warn("Provider boundary v1 failed; switching to legacy for this request", details);
17979
18038
  } else {
17980
- log14.debug("Provider boundary fallback already active", details);
18039
+ log15.debug("Provider boundary fallback already active", details);
17981
18040
  }
17982
18041
  fallbackActive = true;
17983
18042
  return true;
@@ -18115,7 +18174,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18115
18174
  headers: { "Content-Type": "application/json" }
18116
18175
  });
18117
18176
  } catch (err) {
18118
- log14.error("Failed to list models", { error: String(err) });
18177
+ log15.error("Failed to list models", { error: String(err) });
18119
18178
  return new Response(JSON.stringify({ error: "Failed to fetch models from cursor-agent" }), {
18120
18179
  status: 500,
18121
18180
  headers: { "Content-Type": "application/json" }
@@ -18128,7 +18187,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18128
18187
  headers: { "Content-Type": "application/json" }
18129
18188
  });
18130
18189
  }
18131
- log14.debug("Proxy request (bun)", { method: req.method, path: url2.pathname });
18190
+ log15.debug("Proxy request (bun)", { method: req.method, path: url2.pathname });
18132
18191
  const body = await req.json().catch(() => ({}));
18133
18192
  const messages = Array.isArray(body?.messages) ? body.messages : [];
18134
18193
  const stream = body?.stream === true;
@@ -18155,7 +18214,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18155
18214
  const clen = typeof m?.content === "string" ? m.content.length : Array.isArray(m?.content) ? `arr${m.content.length}` : typeof m?.content;
18156
18215
  return `${i}:${role}${hasTc ? `(tc:${hasTc})` : ""}(clen:${clen})`;
18157
18216
  });
18158
- log14.debug("Proxy chat request (bun)", {
18217
+ log15.debug("Proxy chat request (bun)", {
18159
18218
  stream,
18160
18219
  model,
18161
18220
  messages: messages.length,
@@ -18201,7 +18260,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18201
18260
  const stdout = (stdoutText || "").trim();
18202
18261
  const stderr = (stderrText || "").trim();
18203
18262
  const exitCode = await child.exited;
18204
- log14.debug("cursor-agent completed (bun non-stream)", {
18263
+ log15.debug("cursor-agent completed (bun non-stream)", {
18205
18264
  exitCode,
18206
18265
  stdoutChars: stdout.length,
18207
18266
  stderrChars: stderr.length
@@ -18227,7 +18286,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18227
18286
  });
18228
18287
  }
18229
18288
  if (intercepted.toolCall) {
18230
- log14.debug("Intercepted OpenCode tool call (non-stream)", {
18289
+ log15.debug("Intercepted OpenCode tool call (non-stream)", {
18231
18290
  name: intercepted.toolCall.function.name,
18232
18291
  callId: intercepted.toolCall.id
18233
18292
  });
@@ -18241,7 +18300,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18241
18300
  const errSource = stderr || stdout || `cursor-agent exited with code ${String(exitCode ?? "unknown")} and no output`;
18242
18301
  const parsed = parseAgentError(errSource);
18243
18302
  const userError = formatErrorForUser(parsed);
18244
- log14.error("cursor-cli failed", {
18303
+ log15.error("cursor-cli failed", {
18245
18304
  type: parsed.type,
18246
18305
  message: parsed.message,
18247
18306
  code: exitCode
@@ -18265,6 +18324,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18265
18324
  const perf = new RequestPerf(id);
18266
18325
  const toolMapper = new ToolMapper;
18267
18326
  const toolSessionId = id;
18327
+ const passThroughTracker = new PassThroughTracker;
18268
18328
  perf.mark("spawn");
18269
18329
  const sse = new ReadableStream({
18270
18330
  async start(controller) {
@@ -18275,7 +18335,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18275
18335
  const converter = new StreamToSseConverter(model, { id, created });
18276
18336
  const lineBuffer = new LineBuffer;
18277
18337
  const emitToolCallAndTerminate = (toolCall) => {
18278
- log14.debug("Intercepted OpenCode tool call (stream)", {
18338
+ log15.debug("Intercepted OpenCode tool call (stream)", {
18279
18339
  name: toolCall.function.name,
18280
18340
  callId: toolCall.id
18281
18341
  });
@@ -18342,6 +18402,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18342
18402
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18343
18403
  toolRouter,
18344
18404
  responseMeta: { id, created, model },
18405
+ passThroughTracker,
18345
18406
  onToolUpdate: (update) => {
18346
18407
  controller.enqueue(encoder.encode(formatToolUpdateEvent(update)));
18347
18408
  },
@@ -18408,6 +18469,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18408
18469
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18409
18470
  toolRouter,
18410
18471
  responseMeta: { id, created, model },
18472
+ passThroughTracker,
18411
18473
  onToolUpdate: (update) => {
18412
18474
  controller.enqueue(encoder.encode(formatToolUpdateEvent(update)));
18413
18475
  },
@@ -18455,7 +18517,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18455
18517
  const errSource = (stderrText || "").trim() || `cursor-agent exited with code ${String(exitCode ?? "unknown")} and no output`;
18456
18518
  const parsed = parseAgentError(errSource);
18457
18519
  const msg = formatErrorForUser(parsed);
18458
- log14.error("cursor-cli streaming failed", {
18520
+ log15.error("cursor-cli streaming failed", {
18459
18521
  type: parsed.type,
18460
18522
  code: exitCode
18461
18523
  });
@@ -18466,9 +18528,16 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18466
18528
  controller.enqueue(encoder.encode(formatSseDone()));
18467
18529
  return;
18468
18530
  }
18469
- log14.debug("cursor-agent completed (bun stream)", {
18531
+ log15.debug("cursor-agent completed (bun stream)", {
18470
18532
  exitCode
18471
18533
  });
18534
+ const passThroughSummary = passThroughTracker.getSummary();
18535
+ if (passThroughSummary.hasActivity) {
18536
+ await toastService.showPassThroughSummary(passThroughSummary.tools);
18537
+ }
18538
+ if (passThroughSummary.errors.length > 0) {
18539
+ await toastService.showErrorSummary(passThroughSummary.errors);
18540
+ }
18472
18541
  const doneChunk = createChatCompletionChunk(id, created, model, "", true);
18473
18542
  controller.enqueue(encoder.encode(`data: ${JSON.stringify(doneChunk)}
18474
18543
 
@@ -18541,7 +18610,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18541
18610
  res.writeHead(200, { "Content-Type": "application/json" });
18542
18611
  res.end(JSON.stringify({ object: "list", data: models }));
18543
18612
  } catch (err) {
18544
- log14.error("Failed to list models", { error: String(err) });
18613
+ log15.error("Failed to list models", { error: String(err) });
18545
18614
  res.writeHead(500, { "Content-Type": "application/json" });
18546
18615
  res.end(JSON.stringify({ error: "Failed to fetch models" }));
18547
18616
  }
@@ -18552,7 +18621,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18552
18621
  res.end(JSON.stringify({ error: `Unsupported path: ${url2.pathname}` }));
18553
18622
  return;
18554
18623
  }
18555
- log14.debug("Proxy request (node)", { method: req.method, path: url2.pathname });
18624
+ log15.debug("Proxy request (node)", { method: req.method, path: url2.pathname });
18556
18625
  let body = "";
18557
18626
  for await (const chunk of req) {
18558
18627
  body += chunk;
@@ -18575,7 +18644,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18575
18644
  const contentLen = typeof m?.content === "string" ? m.content.length : Array.isArray(m?.content) ? `arr${m.content.length}` : typeof m?.content;
18576
18645
  return `${i}:${role}${hasTc ? `(tc:${hasTc})` : ""}${role === "tool" ? `(tcid:${tcId},name:${tcName},clen:${contentLen})` : `(clen:${contentLen})`}`;
18577
18646
  });
18578
- log14.debug("Proxy chat request (node)", {
18647
+ log15.debug("Proxy chat request (node)", {
18579
18648
  stream,
18580
18649
  model,
18581
18650
  messages: messages.length,
@@ -18606,14 +18675,14 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18606
18675
  let spawnErrorText = null;
18607
18676
  child.on("error", (error45) => {
18608
18677
  spawnErrorText = String(error45?.message || error45);
18609
- log14.error("Failed to spawn cursor-agent", { error: spawnErrorText, model });
18678
+ log15.error("Failed to spawn cursor-agent", { error: spawnErrorText, model });
18610
18679
  });
18611
18680
  child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
18612
18681
  child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
18613
18682
  child.on("close", async (code) => {
18614
18683
  const stdout = Buffer.concat(stdoutChunks).toString().trim();
18615
18684
  const stderr = Buffer.concat(stderrChunks).toString().trim();
18616
- log14.debug("cursor-agent completed (node non-stream)", {
18685
+ log15.debug("cursor-agent completed (node non-stream)", {
18617
18686
  code,
18618
18687
  stdoutChars: stdout.length,
18619
18688
  stderrChars: stderr.length,
@@ -18639,7 +18708,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18639
18708
  return;
18640
18709
  }
18641
18710
  if (intercepted.toolCall) {
18642
- log14.debug("Intercepted OpenCode tool call (non-stream)", {
18711
+ log15.debug("Intercepted OpenCode tool call (non-stream)", {
18643
18712
  name: intercepted.toolCall.function.name,
18644
18713
  callId: intercepted.toolCall.id
18645
18714
  });
@@ -18653,7 +18722,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18653
18722
  const errSource = stderr || stdout || spawnErrorText || `cursor-agent exited with code ${String(code ?? "unknown")} and no output`;
18654
18723
  const parsed = parseAgentError(errSource);
18655
18724
  const userError = formatErrorForUser(parsed);
18656
- log14.error("cursor-cli failed", {
18725
+ log15.error("cursor-cli failed", {
18657
18726
  type: parsed.type,
18658
18727
  message: parsed.message,
18659
18728
  code
@@ -18681,6 +18750,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18681
18750
  const lineBuffer = new LineBuffer;
18682
18751
  const toolMapper = new ToolMapper;
18683
18752
  const toolSessionId = id;
18753
+ const passThroughTracker = new PassThroughTracker;
18684
18754
  const stderrChunks = [];
18685
18755
  let streamTerminated = false;
18686
18756
  let firstTokenReceived = false;
@@ -18692,7 +18762,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18692
18762
  return;
18693
18763
  }
18694
18764
  const errSource = String(error45?.message || error45);
18695
- log14.error("Failed to spawn cursor-agent (stream)", { error: errSource, model });
18765
+ log15.error("Failed to spawn cursor-agent (stream)", { error: errSource, model });
18696
18766
  const parsed = parseAgentError(errSource);
18697
18767
  const msg = formatErrorForUser(parsed);
18698
18768
  const errChunk = createChatCompletionChunk(id, created, model, msg, true);
@@ -18707,7 +18777,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18707
18777
  if (streamTerminated || res.writableEnded) {
18708
18778
  return;
18709
18779
  }
18710
- log14.debug("Intercepted OpenCode tool call (stream)", {
18780
+ log15.debug("Intercepted OpenCode tool call (stream)", {
18711
18781
  name: toolCall.function.name,
18712
18782
  callId: toolCall.id
18713
18783
  });
@@ -18773,6 +18843,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18773
18843
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18774
18844
  toolRouter,
18775
18845
  responseMeta: { id, created, model },
18846
+ passThroughTracker,
18776
18847
  onToolUpdate: (update) => {
18777
18848
  res.write(formatToolUpdateEvent(update));
18778
18849
  },
@@ -18843,6 +18914,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18843
18914
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18844
18915
  toolRouter,
18845
18916
  responseMeta: { id, created, model },
18917
+ passThroughTracker,
18846
18918
  onToolUpdate: (update) => {
18847
18919
  res.write(formatToolUpdateEvent(update));
18848
18920
  },
@@ -18889,7 +18961,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18889
18961
  perf.mark("request:done");
18890
18962
  perf.summarize();
18891
18963
  const stderrText = Buffer.concat(stderrChunks).toString().trim();
18892
- log14.debug("cursor-agent completed (node stream)", {
18964
+ log15.debug("cursor-agent completed (node stream)", {
18893
18965
  code,
18894
18966
  stderrChars: stderrText.length
18895
18967
  });
@@ -18906,6 +18978,13 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18906
18978
  res.end();
18907
18979
  return;
18908
18980
  }
18981
+ const passThroughSummary = passThroughTracker.getSummary();
18982
+ if (passThroughSummary.hasActivity) {
18983
+ await toastService.showPassThroughSummary(passThroughSummary.tools);
18984
+ }
18985
+ if (passThroughSummary.errors.length > 0) {
18986
+ await toastService.showErrorSummary(passThroughSummary.errors);
18987
+ }
18909
18988
  const doneChunk = {
18910
18989
  id,
18911
18990
  object: "chat.completion.chunk",
@@ -19110,7 +19189,7 @@ function buildToolHookEntries(registry2, fallbackBaseDir) {
19110
19189
  const normalizedArgs = applyToolContextDefaults(toolName, args, context, fallbackBaseDir, sessionWorkspaceBySession);
19111
19190
  return await handler(normalizedArgs);
19112
19191
  } catch (error45) {
19113
- log14.debug("Tool hook execution failed", { tool: toolName, error: String(error45?.message || error45) });
19192
+ log15.debug("Tool hook execution failed", { tool: toolName, error: String(error45?.message || error45) });
19114
19193
  throw error45;
19115
19194
  }
19116
19195
  }
@@ -19122,9 +19201,9 @@ function buildToolHookEntries(registry2, fallbackBaseDir) {
19122
19201
  }
19123
19202
  return entries;
19124
19203
  }
19125
- var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", CURSOR_PROVIDER_PREFIX, CURSOR_PROXY_HOST = "127.0.0.1", CURSOR_PROXY_DEFAULT_PORT = 32124, CURSOR_PROXY_DEFAULT_BASE_URL, REUSE_EXISTING_PROXY, SESSION_WORKSPACE_CACHE_LIMIT = 200, FORCE_TOOL_MODE, EMIT_TOOL_UPDATES, FORWARD_TOOL_CALLS, TOOL_LOOP_MODE_RAW, TOOL_LOOP_MODE, TOOL_LOOP_MODE_VALID, PROVIDER_BOUNDARY_MODE_RAW, PROVIDER_BOUNDARY_MODE, PROVIDER_BOUNDARY_MODE_VALID, LEGACY_PROVIDER_BOUNDARY, PROVIDER_BOUNDARY, ENABLE_PROVIDER_BOUNDARY_AUTOFALLBACK, TOOL_LOOP_MAX_REPEAT_RAW, TOOL_LOOP_MAX_REPEAT, TOOL_LOOP_MAX_REPEAT_VALID, PROXY_EXECUTE_TOOL_CALLS, SUPPRESS_CONVERTER_TOOL_EVENTS, SHOULD_EMIT_TOOL_UPDATES, CursorPlugin = async ({ $, directory, worktree, client: client3, serverUrl }) => {
19204
+ var log15, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", CURSOR_PROVIDER_PREFIX, CURSOR_PROXY_HOST = "127.0.0.1", CURSOR_PROXY_DEFAULT_PORT = 32124, CURSOR_PROXY_DEFAULT_BASE_URL, REUSE_EXISTING_PROXY, SESSION_WORKSPACE_CACHE_LIMIT = 200, FORCE_TOOL_MODE, EMIT_TOOL_UPDATES, FORWARD_TOOL_CALLS, TOOL_LOOP_MODE_RAW, TOOL_LOOP_MODE, TOOL_LOOP_MODE_VALID, PROVIDER_BOUNDARY_MODE_RAW, PROVIDER_BOUNDARY_MODE, PROVIDER_BOUNDARY_MODE_VALID, LEGACY_PROVIDER_BOUNDARY, PROVIDER_BOUNDARY, ENABLE_PROVIDER_BOUNDARY_AUTOFALLBACK, TOOL_LOOP_MAX_REPEAT_RAW, TOOL_LOOP_MAX_REPEAT, TOOL_LOOP_MAX_REPEAT_VALID, PROXY_EXECUTE_TOOL_CALLS, SUPPRESS_CONVERTER_TOOL_EVENTS, SHOULD_EMIT_TOOL_UPDATES, CursorPlugin = async ({ $, directory, worktree, client: client3, serverUrl }) => {
19126
19205
  const workspaceDirectory = resolveWorkspaceDirectory(worktree, directory);
19127
- log14.debug("Plugin initializing", {
19206
+ log15.debug("Plugin initializing", {
19128
19207
  directory,
19129
19208
  worktree,
19130
19209
  workspaceDirectory,
@@ -19132,22 +19211,22 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", C
19132
19211
  serverUrl: serverUrl?.toString()
19133
19212
  });
19134
19213
  if (!TOOL_LOOP_MODE_VALID) {
19135
- log14.warn("Invalid CURSOR_ACP_TOOL_LOOP_MODE; defaulting to opencode", { value: TOOL_LOOP_MODE_RAW });
19214
+ log15.warn("Invalid CURSOR_ACP_TOOL_LOOP_MODE; defaulting to opencode", { value: TOOL_LOOP_MODE_RAW });
19136
19215
  }
19137
19216
  if (!PROVIDER_BOUNDARY_MODE_VALID) {
19138
- log14.warn("Invalid CURSOR_ACP_PROVIDER_BOUNDARY; defaulting to v1", {
19217
+ log15.warn("Invalid CURSOR_ACP_PROVIDER_BOUNDARY; defaulting to v1", {
19139
19218
  value: PROVIDER_BOUNDARY_MODE_RAW
19140
19219
  });
19141
19220
  }
19142
19221
  if (!TOOL_LOOP_MAX_REPEAT_VALID) {
19143
- log14.warn("Invalid CURSOR_ACP_TOOL_LOOP_MAX_REPEAT; defaulting to 3", {
19222
+ log15.warn("Invalid CURSOR_ACP_TOOL_LOOP_MAX_REPEAT; defaulting to 3", {
19144
19223
  value: TOOL_LOOP_MAX_REPEAT_RAW
19145
19224
  });
19146
19225
  }
19147
19226
  if (ENABLE_PROVIDER_BOUNDARY_AUTOFALLBACK && PROVIDER_BOUNDARY.mode !== "v1") {
19148
- log14.debug("Provider boundary auto-fallback is enabled but inactive unless mode=v1");
19227
+ log15.debug("Provider boundary auto-fallback is enabled but inactive unless mode=v1");
19149
19228
  }
19150
- log14.info("Tool loop mode configured", {
19229
+ log15.info("Tool loop mode configured", {
19151
19230
  mode: TOOL_LOOP_MODE,
19152
19231
  providerBoundary: PROVIDER_BOUNDARY.mode,
19153
19232
  proxyExecToolCalls: PROXY_EXECUTE_TOOL_CALLS,
@@ -19155,12 +19234,14 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", C
19155
19234
  toolLoopMaxRepeat: TOOL_LOOP_MAX_REPEAT
19156
19235
  });
19157
19236
  await ensurePluginDirectory();
19237
+ toastService.setClient(client3);
19238
+ toastService.setClient(client3);
19158
19239
  const toolsEnabled = process.env.CURSOR_ACP_ENABLE_OPENCODE_TOOLS !== "false";
19159
19240
  const legacyProxyToolPathsEnabled = toolsEnabled && TOOL_LOOP_MODE === "proxy-exec";
19160
19241
  if (toolsEnabled && TOOL_LOOP_MODE === "opencode") {
19161
- log14.debug("OpenCode mode active; skipping legacy SDK/MCP discovery and proxy-side tool execution");
19242
+ log15.debug("OpenCode mode active; skipping legacy SDK/MCP discovery and proxy-side tool execution");
19162
19243
  } else if (toolsEnabled && TOOL_LOOP_MODE === "off") {
19163
- log14.debug("Tool loop mode off; proxy-side tool execution disabled");
19244
+ log15.debug("Tool loop mode off; proxy-side tool execution disabled");
19164
19245
  }
19165
19246
  const serverClient = legacyProxyToolPathsEnabled ? createOpencodeClient({ baseUrl: serverUrl.toString(), directory: workspaceDirectory }) : null;
19166
19247
  const discovery = legacyProxyToolPathsEnabled ? new OpenCodeToolDiscovery(serverClient ?? client3) : null;
@@ -19212,7 +19293,7 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", C
19212
19293
  discoveredList = await discovery.listTools();
19213
19294
  discoveredList.forEach((t) => toolsByName.set(t.name, t));
19214
19295
  } catch (err) {
19215
- log14.debug("Tool discovery failed, using local tools only", { error: String(err) });
19296
+ log15.debug("Tool discovery failed, using local tools only", { error: String(err) });
19216
19297
  }
19217
19298
  }
19218
19299
  const allTools = [...localTools, ...discoveredList];
@@ -19242,11 +19323,11 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", C
19242
19323
  }
19243
19324
  lastToolNames = toolEntries.map((e) => e.function.name);
19244
19325
  lastToolMap = allTools.map((t) => ({ id: t.id, name: t.name }));
19245
- log14.debug("Tools refreshed", { local: localTools.length, discovered: discoveredList.length, total: toolEntries.length });
19326
+ log15.debug("Tools refreshed", { local: localTools.length, discovered: discoveredList.length, total: toolEntries.length });
19246
19327
  return toolEntries;
19247
19328
  }
19248
19329
  const proxyBaseURL = await ensureCursorProxyServer(workspaceDirectory, router);
19249
- log14.debug("Proxy server started", { baseURL: proxyBaseURL });
19330
+ log15.debug("Proxy server started", { baseURL: proxyBaseURL });
19250
19331
  const toolHookEntries = buildToolHookEntries(localRegistry, workspaceDirectory);
19251
19332
  return {
19252
19333
  tool: toolHookEntries,
@@ -19261,9 +19342,9 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", C
19261
19342
  type: "oauth",
19262
19343
  async authorize() {
19263
19344
  try {
19264
- log14.info("Starting OAuth flow");
19345
+ log15.info("Starting OAuth flow");
19265
19346
  const { url: url2, instructions, callback } = await startCursorOAuth();
19266
- log14.debug("Got OAuth URL", { url: url2.substring(0, 50) + "..." });
19347
+ log15.debug("Got OAuth URL", { url: url2.substring(0, 50) + "..." });
19267
19348
  return {
19268
19349
  url: url2,
19269
19350
  instructions,
@@ -19271,7 +19352,7 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", C
19271
19352
  callback
19272
19353
  };
19273
19354
  } catch (error45) {
19274
- log14.error("OAuth error", { error: error45 });
19355
+ log15.error("OAuth error", { error: error45 });
19275
19356
  throw error45;
19276
19357
  }
19277
19358
  }
@@ -19295,10 +19376,10 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID = "cursor-acp", C
19295
19376
  output.options.tools = resolved.tools;
19296
19377
  } else if (resolved.action === "preserve") {
19297
19378
  const count = Array.isArray(existingTools) ? existingTools.length : 0;
19298
- log14.debug("Using OpenCode-provided tools from chat.params", { count });
19379
+ log15.debug("Using OpenCode-provided tools from chat.params", { count });
19299
19380
  }
19300
19381
  } catch (err) {
19301
- log14.debug("Failed to refresh tools", { error: String(err) });
19382
+ log15.debug("Failed to refresh tools", { error: String(err) });
19302
19383
  }
19303
19384
  }
19304
19385
  },
@@ -19331,9 +19412,10 @@ var init_plugin = __esm(() => {
19331
19412
  init_executor();
19332
19413
  init_boundary();
19333
19414
  init_runtime_interception();
19415
+ init_toast_service();
19334
19416
  init_tool_schema_compat();
19335
19417
  init_tool_loop_guard();
19336
- log14 = createLogger("plugin");
19418
+ log15 = createLogger("plugin");
19337
19419
  DEBUG_LOG_DIR2 = join4(homedir4(), ".config", "opencode", "logs");
19338
19420
  DEBUG_LOG_FILE2 = join4(DEBUG_LOG_DIR2, "tool-loop-debug.log");
19339
19421
  CURSOR_PROVIDER_PREFIX = `${CURSOR_PROVIDER_ID}/`;
@@ -19577,7 +19659,7 @@ init_logger();
19577
19659
  import { execSync } from "node:child_process";
19578
19660
  import { createServer } from "node:net";
19579
19661
  import { platform as platform2 } from "node:os";
19580
- var log15 = createLogger("proxy-server");
19662
+ var log16 = createLogger("proxy-server");
19581
19663
  var DEFAULT_PORT = 32124;
19582
19664
  var PORT_RANGE_SIZE = 256;
19583
19665
  async function isPortAvailable(port, host) {
@@ -19624,11 +19706,11 @@ function getUsedPortsInRange(minPort, maxPort) {
19624
19706
  }
19625
19707
  }
19626
19708
  } else {
19627
- log15.debug(`Port detection not supported on ${os2}. Using probe-based discovery.`);
19709
+ log16.debug(`Port detection not supported on ${os2}. Using probe-based discovery.`);
19628
19710
  }
19629
19711
  } catch (error45) {
19630
19712
  const msg = error45 instanceof Error ? error45.message : String(error45);
19631
- log15.debug(`Port detection failed: ${msg}. Using probe-based discovery.`);
19713
+ log16.debug(`Port detection failed: ${msg}. Using probe-based discovery.`);
19632
19714
  }
19633
19715
  return used;
19634
19716
  }
@@ -19679,7 +19761,7 @@ function createProxyServer(config2) {
19679
19761
  const err = error45 instanceof Error ? error45 : new Error(String(error45));
19680
19762
  const isPortInUse = err.message.includes("EADDRINUSE") || err.message.includes("address already in use") || err.message.includes("port is already in use");
19681
19763
  if (!isPortInUse) {
19682
- log15.debug(`Unexpected error starting on port ${port}: ${err.message}`);
19764
+ log16.debug(`Unexpected error starting on port ${port}: ${err.message}`);
19683
19765
  }
19684
19766
  return { success: false, error: err };
19685
19767
  }
@@ -19695,13 +19777,13 @@ function createProxyServer(config2) {
19695
19777
  if (result.success) {
19696
19778
  port = requestedPort;
19697
19779
  } else {
19698
- log15.debug(`Requested port ${requestedPort} unavailable: ${result.error?.message ?? "unknown"}. Falling back to automatic port selection.`);
19780
+ log16.debug(`Requested port ${requestedPort} unavailable: ${result.error?.message ?? "unknown"}. Falling back to automatic port selection.`);
19699
19781
  port = await findAvailablePort(host);
19700
19782
  const fallbackResult = tryStart(port);
19701
19783
  if (!fallbackResult.success) {
19702
19784
  throw new Error(`Failed to start server on port ${requestedPort} (${result.error?.message ?? "unknown"}) ` + `and fallback port ${port} (${fallbackResult.error?.message ?? "unknown"})`);
19703
19785
  }
19704
- log15.debug(`Server started on fallback port ${port} instead of requested port ${requestedPort}`);
19786
+ log16.debug(`Server started on fallback port ${port} instead of requested port ${requestedPort}`);
19705
19787
  }
19706
19788
  } else {
19707
19789
  port = await findAvailablePort(host);
@@ -20047,11 +20129,11 @@ init_auth();
20047
20129
  init_auth();
20048
20130
  init_logger();
20049
20131
  import { existsSync as existsSync5 } from "fs";
20050
- var log16 = createLogger("status");
20132
+ var log17 = createLogger("status");
20051
20133
  function checkAuthStatus() {
20052
20134
  const authFilePath = getAuthFilePath();
20053
20135
  const exists = existsSync5(authFilePath);
20054
- log16.debug("Checking auth status", { path: authFilePath });
20136
+ log17.debug("Checking auth status", { path: authFilePath });
20055
20137
  if (exists) {
20056
20138
  return {
20057
20139
  authenticated: true,