@rama_nigg/open-cursor 2.3.3 → 2.3.5

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.
@@ -13614,41 +13614,46 @@ function extractAllowedToolNames(tools) {
13614
13614
  }
13615
13615
  function extractOpenAiToolCall(event, allowedToolNames) {
13616
13616
  if (allowedToolNames.size === 0) {
13617
- return null;
13617
+ return { action: "skip", skipReason: "no_allowed_tools" };
13618
13618
  }
13619
13619
  const { name, args, skipped } = extractToolNameAndArgs(event);
13620
13620
  if (skipped) {
13621
- return null;
13621
+ return { action: "skip", skipReason: "event_skipped" };
13622
13622
  }
13623
13623
  if (!name) {
13624
- return null;
13624
+ return { action: "skip", skipReason: "no_name" };
13625
13625
  }
13626
13626
  const resolvedName = resolveAllowedToolName(name, allowedToolNames);
13627
- if (!resolvedName) {
13628
- log5.debug("Tool call name not allowed; skipping interception", {
13629
- name,
13630
- normalized: normalizeAliasKey(name),
13631
- allowedToolCount: allowedToolNames.size,
13632
- aliasTarget: TOOL_NAME_ALIASES.get(normalizeAliasKey(name)) ?? null
13633
- });
13634
- return null;
13635
- }
13636
- if (args === undefined && event.subtype === "started") {
13637
- log5.debug("Tool call args extraction returned undefined", {
13638
- toolName: name,
13639
- subtype: event.subtype ?? "none",
13640
- payloadKeys: Object.entries(event.tool_call || {}).map(([k, v]) => `${k}:[${isRecord(v) ? Object.keys(v).join(",") : typeof v}]`),
13641
- hasCallId: Boolean(event.call_id)
13642
- });
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
+ };
13643
13648
  }
13644
- 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
+ });
13645
13654
  return {
13646
- id: callId,
13647
- type: "function",
13648
- function: {
13649
- name: resolvedName,
13650
- arguments: toOpenAiArguments(args)
13651
- }
13655
+ action: "passthrough",
13656
+ passthroughName: name
13652
13657
  };
13653
13658
  }
13654
13659
  function createToolCallCompletionResponse(meta, toolCall) {
@@ -16388,7 +16393,7 @@ function createSharedBoundary(providerId) {
16388
16393
  },
16389
16394
  maybeExtractToolCall(event, allowedToolNames, toolLoopMode) {
16390
16395
  if (toolLoopMode !== "opencode") {
16391
- return null;
16396
+ return { action: "skip", skipReason: "tool_loop_mode_not_opencode" };
16392
16397
  }
16393
16398
  return extractOpenAiToolCall(event, allowedToolNames);
16394
16399
  },
@@ -16815,9 +16820,33 @@ async function handleToolLoopEventLegacy(options) {
16815
16820
  responseMeta,
16816
16821
  onToolUpdate,
16817
16822
  onToolResult,
16818
- onInterceptedToolCall
16823
+ onInterceptedToolCall,
16824
+ passThroughTracker
16819
16825
  } = options;
16820
- 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;
16821
16850
  if (interceptedToolCall) {
16822
16851
  const compat2 = applyToolSchemaCompat(interceptedToolCall, toolSchemaMap);
16823
16852
  let normalizedToolCall = compat2.toolCall;
@@ -16894,118 +16923,125 @@ async function handleToolLoopEventV1(options) {
16894
16923
  responseMeta,
16895
16924
  onToolUpdate,
16896
16925
  onToolResult,
16897
- onInterceptedToolCall
16926
+ onInterceptedToolCall,
16927
+ passThroughTracker
16898
16928
  } = options;
16899
- let interceptedToolCall;
16929
+ let extraction;
16900
16930
  try {
16901
- interceptedToolCall = boundary.maybeExtractToolCall(event, allowedToolNames, toolLoopMode);
16931
+ extraction = boundary.maybeExtractToolCall(event, allowedToolNames, toolLoopMode);
16902
16932
  } catch (error45) {
16903
16933
  throw new ToolBoundaryExtractionError("Boundary tool extraction failed", error45);
16904
16934
  }
16905
- if (interceptedToolCall) {
16906
- const compat2 = applyToolSchemaCompat(interceptedToolCall, toolSchemaMap);
16907
- interceptedToolCall = compat2.toolCall;
16908
- const editDiag = interceptedToolCall.function.name.toLowerCase() === "edit" ? {
16909
- rawArgs: safeArgTypeSummary(event),
16910
- normalizedArgs: compat2.normalizedArgs
16911
- } : undefined;
16912
- log13.debug("Applied tool schema compatibility", {
16913
- tool: interceptedToolCall.function.name,
16914
- originalArgKeys: compat2.originalArgKeys,
16915
- normalizedArgKeys: compat2.normalizedArgKeys,
16916
- collisionKeys: compat2.collisionKeys,
16917
- validationOk: compat2.validation.ok,
16918
- ...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
16919
16939
  });
16920
- if (compat2.validation.hasSchema && !compat2.validation.ok) {
16921
- log13.debug("Tool schema compatibility validation failed", {
16922
- 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,
16923
16992
  missing: compat2.validation.missing,
16924
- unexpected: compat2.validation.unexpected,
16925
- typeErrors: compat2.validation.typeErrors,
16926
- repairHint: compat2.validation.repairHint
16993
+ typeErrors: compat2.validation.typeErrors
16927
16994
  });
16928
- const validationTermination = evaluateSchemaValidationLoopGuard(toolLoopGuard, interceptedToolCall, compat2.validation);
16929
- if (validationTermination) {
16930
- return { intercepted: false, skipConverter: true, terminate: validationTermination };
16931
- }
16932
- const termination2 = evaluateToolLoopGuard(toolLoopGuard, interceptedToolCall);
16933
- if (termination2) {
16934
- return { intercepted: false, skipConverter: true, terminate: termination2 };
16935
- }
16936
- const reroutedWrite = tryRerouteEditToWrite(interceptedToolCall, compat2.normalizedArgs, allowedToolNames, toolSchemaMap);
16937
- if (reroutedWrite) {
16938
- log13.debug("Rerouting malformed edit call to write", {
16939
- path: reroutedWrite.path,
16940
- missing: compat2.validation.missing,
16941
- typeErrors: compat2.validation.typeErrors
16942
- });
16943
- await onInterceptedToolCall(reroutedWrite.toolCall);
16944
- return {
16945
- intercepted: true,
16946
- skipConverter: true
16947
- };
16948
- }
16949
- if (schemaValidationFailureMode === "pass_through" && shouldTerminateOnSchemaValidation(interceptedToolCall, compat2.validation)) {
16950
- return {
16951
- intercepted: false,
16952
- skipConverter: true,
16953
- terminate: createSchemaValidationTermination(interceptedToolCall, compat2.validation)
16954
- };
16955
- }
16956
- if (schemaValidationFailureMode === "pass_through" && shouldEmitNonFatalSchemaValidationHint(interceptedToolCall, compat2.validation)) {
16957
- const hintChunk = createNonFatalSchemaValidationHintChunk(responseMeta, interceptedToolCall, compat2.validation);
16958
- log13.debug("Emitting non-fatal schema validation hint and skipping malformed tool execution", {
16959
- tool: interceptedToolCall.function.name,
16960
- missing: compat2.validation.missing,
16961
- typeErrors: compat2.validation.typeErrors
16962
- });
16963
- await onToolResult(hintChunk);
16964
- return {
16965
- intercepted: false,
16966
- skipConverter: true
16967
- };
16968
- }
16969
- if (schemaValidationFailureMode === "terminate") {
16970
- return {
16971
- intercepted: false,
16972
- skipConverter: true,
16973
- terminate: createSchemaValidationTermination(interceptedToolCall, compat2.validation)
16974
- };
16975
- }
16976
- log13.debug("Forwarding schema-invalid tool call to OpenCode loop", {
16977
- tool: interceptedToolCall.function.name,
16978
- repairHint: compat2.validation.repairHint
16979
- });
16980
- await onInterceptedToolCall(interceptedToolCall);
16995
+ await onInterceptedToolCall(reroutedWrite.toolCall);
16981
16996
  return {
16982
16997
  intercepted: true,
16983
16998
  skipConverter: true
16984
16999
  };
16985
17000
  }
16986
- const termination = evaluateToolLoopGuard(toolLoopGuard, interceptedToolCall);
16987
- if (termination) {
16988
- 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
+ };
16989
17007
  }
16990
- await onInterceptedToolCall(interceptedToolCall);
16991
- return { intercepted: true, skipConverter: true };
16992
- }
16993
- const updates = await toolMapper.mapCursorEventToAcp(event, event.session_id ?? toolSessionId);
16994
- if (shouldEmitToolUpdates) {
16995
- for (const update of updates) {
16996
- 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
+ };
16997
17020
  }
16998
- }
16999
- if (toolRouter && proxyExecuteToolCalls) {
17000
- const toolResult = await toolRouter.handleToolCall(event, responseMeta);
17001
- if (toolResult) {
17002
- await onToolResult(toolResult);
17021
+ if (schemaValidationFailureMode === "terminate") {
17022
+ return {
17023
+ intercepted: false,
17024
+ skipConverter: true,
17025
+ terminate: createSchemaValidationTermination(normalizedToolCall, compat2.validation)
17026
+ };
17003
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
+ };
17004
17037
  }
17005
- return {
17006
- intercepted: false,
17007
- skipConverter: suppressConverterToolEvents
17008
- };
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 };
17009
17045
  }
17010
17046
  async function handleToolLoopEventWithFallback(options) {
17011
17047
  const {
@@ -17286,6 +17322,80 @@ var init_runtime_interception = __esm(() => {
17286
17322
  };
17287
17323
  });
17288
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
+
17289
17399
  // src/provider/tool-loop-guard.ts
17290
17400
  function parseToolLoopMaxRepeat(value) {
17291
17401
  if (value === undefined) {
@@ -17298,6 +17408,7 @@ function parseToolLoopMaxRepeat(value) {
17298
17408
  return { value: Math.floor(parsed), valid: true };
17299
17409
  }
17300
17410
  function createToolLoopGuard(messages, maxRepeat) {
17411
+ const coarseMaxRepeat = maxRepeat * COARSE_LIMIT_MULTIPLIER;
17301
17412
  const {
17302
17413
  byCallId,
17303
17414
  latest,
@@ -17337,13 +17448,13 @@ function createToolLoopGuard(messages, maxRepeat) {
17337
17448
  }
17338
17449
  const strictFingerprint = `${toolCall.function.name}|${argShape}|${errorClass}`;
17339
17450
  const coarseFingerprint = `${toolCall.function.name}|${errorClass}`;
17340
- return evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, counts, coarseCounts, maxRepeat);
17451
+ return evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, counts, coarseCounts, maxRepeat, coarseMaxRepeat);
17341
17452
  },
17342
17453
  evaluateValidation(toolCall, validationSignature) {
17343
17454
  const normalizedSignature = normalizeValidationSignature(validationSignature);
17344
17455
  const strictFingerprint = `${toolCall.function.name}|schema:${normalizedSignature}|validation`;
17345
17456
  const coarseFingerprint = `${toolCall.function.name}|validation`;
17346
- return evaluateWithFingerprints("validation", strictFingerprint, coarseFingerprint, validationCounts, validationCoarseCounts, maxRepeat);
17457
+ return evaluateWithFingerprints("validation", strictFingerprint, coarseFingerprint, validationCounts, validationCoarseCounts, maxRepeat, coarseMaxRepeat);
17347
17458
  },
17348
17459
  resetFingerprint(fingerprint) {
17349
17460
  counts.delete(fingerprint);
@@ -17428,25 +17539,6 @@ function indexToolLoopHistory(messages) {
17428
17539
  incrementCount(initialValidationCounts, `${call.name}|schema:${schemaSignature}|validation`);
17429
17540
  incrementCount(initialValidationCoarseCounts, `${call.name}|validation`);
17430
17541
  }
17431
- const strippedRounds = countStrippedAssistantRounds(messages);
17432
- if (strippedRounds > 0 && assistantCalls.length > 0) {
17433
- for (const call of assistantCalls) {
17434
- const errorClass = normalizeErrorClassForTool(call.name, byCallId.get(call.id) ?? latestByToolName.get(call.name) ?? latest ?? "unknown");
17435
- if (errorClass !== "success") {
17436
- continue;
17437
- }
17438
- const coarseSuccessFP = deriveSuccessCoarseFingerprint(call.name, call.rawArguments);
17439
- if (coarseSuccessFP) {
17440
- for (let i = 0;i < strippedRounds; i++) {
17441
- incrementCount(initialCoarseCounts, coarseSuccessFP);
17442
- }
17443
- }
17444
- const successFP = `${call.name}|values:${call.argValueSignature}|success`;
17445
- for (let i = 0;i < strippedRounds; i++) {
17446
- incrementCount(initialCounts, successFP);
17447
- }
17448
- }
17449
- }
17450
17542
  return {
17451
17543
  byCallId,
17452
17544
  latest,
@@ -17593,7 +17685,7 @@ function normalizeValidationSignature(signature) {
17593
17685
  const normalized = signature.trim().toLowerCase();
17594
17686
  return normalized.length > 0 ? normalized : "invalid";
17595
17687
  }
17596
- function evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, strictCounts, coarseCounts, maxRepeat) {
17688
+ function evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerprint, strictCounts, coarseCounts, maxRepeat, coarseMaxRepeat) {
17597
17689
  if (errorClass === "success") {
17598
17690
  return {
17599
17691
  fingerprint: strictFingerprint,
@@ -17609,12 +17701,12 @@ function evaluateWithFingerprints(errorClass, strictFingerprint, coarseFingerpri
17609
17701
  const coarseRepeatCount = (coarseCounts.get(coarseFingerprint) ?? 0) + 1;
17610
17702
  coarseCounts.set(coarseFingerprint, coarseRepeatCount);
17611
17703
  const strictTriggered = strictRepeatCount > maxRepeat;
17612
- const coarseTriggered = coarseRepeatCount > maxRepeat;
17704
+ const coarseTriggered = coarseRepeatCount > coarseMaxRepeat;
17613
17705
  const preferCoarseFingerprint = coarseTriggered && !strictTriggered;
17614
17706
  return {
17615
17707
  fingerprint: preferCoarseFingerprint ? coarseFingerprint : strictFingerprint,
17616
17708
  repeatCount: preferCoarseFingerprint ? coarseRepeatCount : strictRepeatCount,
17617
- maxRepeat,
17709
+ maxRepeat: preferCoarseFingerprint ? coarseMaxRepeat : maxRepeat,
17618
17710
  errorClass,
17619
17711
  triggered: strictTriggered || coarseTriggered,
17620
17712
  tracked: true
@@ -17669,23 +17761,6 @@ function normalizeErrorClassForTool(toolName, errorClass) {
17669
17761
  }
17670
17762
  return errorClass;
17671
17763
  }
17672
- function countStrippedAssistantRounds(messages) {
17673
- let count = 0;
17674
- for (const message of messages) {
17675
- if (!isRecord4(message) || message.role !== "assistant") {
17676
- continue;
17677
- }
17678
- if (Array.isArray(message.tool_calls) && message.tool_calls.length > 0) {
17679
- continue;
17680
- }
17681
- const content = message.content;
17682
- const hasContent = typeof content === "string" && content.trim().length > 0 || Array.isArray(content) && content.length > 0;
17683
- if (!hasContent) {
17684
- count++;
17685
- }
17686
- }
17687
- return count;
17688
- }
17689
17764
  function toLowerText(content) {
17690
17765
  const rendered = renderContent(content);
17691
17766
  return rendered.trim().toLowerCase();
@@ -17716,7 +17791,7 @@ function containsAny(text, patterns) {
17716
17791
  function isRecord4(value) {
17717
17792
  return typeof value === "object" && value !== null && !Array.isArray(value);
17718
17793
  }
17719
- var UNKNOWN_AS_SUCCESS_TOOLS;
17794
+ var UNKNOWN_AS_SUCCESS_TOOLS, COARSE_LIMIT_MULTIPLIER = 3;
17720
17795
  var init_tool_loop_guard = __esm(() => {
17721
17796
  UNKNOWN_AS_SUCCESS_TOOLS = new Set([
17722
17797
  "bash",
@@ -17770,9 +17845,9 @@ async function ensurePluginDirectory() {
17770
17845
  const pluginDir = join5(configHome, "opencode", "plugin");
17771
17846
  try {
17772
17847
  await mkdir(pluginDir, { recursive: true });
17773
- log14.debug("Plugin directory ensured", { path: pluginDir });
17848
+ log15.debug("Plugin directory ensured", { path: pluginDir });
17774
17849
  } catch (error45) {
17775
- log14.warn("Failed to create plugin directory", { error: String(error45) });
17850
+ log15.warn("Failed to create plugin directory", { error: String(error45) });
17776
17851
  }
17777
17852
  }
17778
17853
  function shouldProcessModel(model) {
@@ -17960,9 +18035,9 @@ function createBoundaryRuntimeContext(scope) {
17960
18035
  error: toErrorMessage(error45)
17961
18036
  };
17962
18037
  if (!fallbackActive) {
17963
- log14.warn("Provider boundary v1 failed; switching to legacy for this request", details);
18038
+ log15.warn("Provider boundary v1 failed; switching to legacy for this request", details);
17964
18039
  } else {
17965
- log14.debug("Provider boundary fallback already active", details);
18040
+ log15.debug("Provider boundary fallback already active", details);
17966
18041
  }
17967
18042
  fallbackActive = true;
17968
18043
  return true;
@@ -18100,7 +18175,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18100
18175
  headers: { "Content-Type": "application/json" }
18101
18176
  });
18102
18177
  } catch (err) {
18103
- log14.error("Failed to list models", { error: String(err) });
18178
+ log15.error("Failed to list models", { error: String(err) });
18104
18179
  return new Response(JSON.stringify({ error: "Failed to fetch models from cursor-agent" }), {
18105
18180
  status: 500,
18106
18181
  headers: { "Content-Type": "application/json" }
@@ -18113,7 +18188,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18113
18188
  headers: { "Content-Type": "application/json" }
18114
18189
  });
18115
18190
  }
18116
- log14.debug("Proxy request (bun)", { method: req.method, path: url2.pathname });
18191
+ log15.debug("Proxy request (bun)", { method: req.method, path: url2.pathname });
18117
18192
  const body = await req.json().catch(() => ({}));
18118
18193
  const messages = Array.isArray(body?.messages) ? body.messages : [];
18119
18194
  const stream = body?.stream === true;
@@ -18140,7 +18215,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18140
18215
  const clen = typeof m?.content === "string" ? m.content.length : Array.isArray(m?.content) ? `arr${m.content.length}` : typeof m?.content;
18141
18216
  return `${i}:${role}${hasTc ? `(tc:${hasTc})` : ""}(clen:${clen})`;
18142
18217
  });
18143
- log14.debug("Proxy chat request (bun)", {
18218
+ log15.debug("Proxy chat request (bun)", {
18144
18219
  stream,
18145
18220
  model,
18146
18221
  messages: messages.length,
@@ -18186,7 +18261,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18186
18261
  const stdout = (stdoutText || "").trim();
18187
18262
  const stderr = (stderrText || "").trim();
18188
18263
  const exitCode = await child.exited;
18189
- log14.debug("cursor-agent completed (bun non-stream)", {
18264
+ log15.debug("cursor-agent completed (bun non-stream)", {
18190
18265
  exitCode,
18191
18266
  stdoutChars: stdout.length,
18192
18267
  stderrChars: stderr.length
@@ -18212,7 +18287,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18212
18287
  });
18213
18288
  }
18214
18289
  if (intercepted.toolCall) {
18215
- log14.debug("Intercepted OpenCode tool call (non-stream)", {
18290
+ log15.debug("Intercepted OpenCode tool call (non-stream)", {
18216
18291
  name: intercepted.toolCall.function.name,
18217
18292
  callId: intercepted.toolCall.id
18218
18293
  });
@@ -18226,7 +18301,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18226
18301
  const errSource = stderr || stdout || `cursor-agent exited with code ${String(exitCode ?? "unknown")} and no output`;
18227
18302
  const parsed = parseAgentError(errSource);
18228
18303
  const userError = formatErrorForUser(parsed);
18229
- log14.error("cursor-cli failed", {
18304
+ log15.error("cursor-cli failed", {
18230
18305
  type: parsed.type,
18231
18306
  message: parsed.message,
18232
18307
  code: exitCode
@@ -18250,6 +18325,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18250
18325
  const perf = new RequestPerf(id);
18251
18326
  const toolMapper = new ToolMapper;
18252
18327
  const toolSessionId = id;
18328
+ const passThroughTracker = new PassThroughTracker;
18253
18329
  perf.mark("spawn");
18254
18330
  const sse = new ReadableStream({
18255
18331
  async start(controller) {
@@ -18260,7 +18336,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18260
18336
  const converter = new StreamToSseConverter(model, { id, created });
18261
18337
  const lineBuffer = new LineBuffer;
18262
18338
  const emitToolCallAndTerminate = (toolCall) => {
18263
- log14.debug("Intercepted OpenCode tool call (stream)", {
18339
+ log15.debug("Intercepted OpenCode tool call (stream)", {
18264
18340
  name: toolCall.function.name,
18265
18341
  callId: toolCall.id
18266
18342
  });
@@ -18327,6 +18403,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18327
18403
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18328
18404
  toolRouter,
18329
18405
  responseMeta: { id, created, model },
18406
+ passThroughTracker,
18330
18407
  onToolUpdate: (update) => {
18331
18408
  controller.enqueue(encoder.encode(formatToolUpdateEvent(update)));
18332
18409
  },
@@ -18393,6 +18470,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18393
18470
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18394
18471
  toolRouter,
18395
18472
  responseMeta: { id, created, model },
18473
+ passThroughTracker,
18396
18474
  onToolUpdate: (update) => {
18397
18475
  controller.enqueue(encoder.encode(formatToolUpdateEvent(update)));
18398
18476
  },
@@ -18440,7 +18518,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18440
18518
  const errSource = (stderrText || "").trim() || `cursor-agent exited with code ${String(exitCode ?? "unknown")} and no output`;
18441
18519
  const parsed = parseAgentError(errSource);
18442
18520
  const msg = formatErrorForUser(parsed);
18443
- log14.error("cursor-cli streaming failed", {
18521
+ log15.error("cursor-cli streaming failed", {
18444
18522
  type: parsed.type,
18445
18523
  code: exitCode
18446
18524
  });
@@ -18451,9 +18529,16 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18451
18529
  controller.enqueue(encoder.encode(formatSseDone()));
18452
18530
  return;
18453
18531
  }
18454
- log14.debug("cursor-agent completed (bun stream)", {
18532
+ log15.debug("cursor-agent completed (bun stream)", {
18455
18533
  exitCode
18456
18534
  });
18535
+ const passThroughSummary = passThroughTracker.getSummary();
18536
+ if (passThroughSummary.hasActivity) {
18537
+ await toastService.showPassThroughSummary(passThroughSummary.tools);
18538
+ }
18539
+ if (passThroughSummary.errors.length > 0) {
18540
+ await toastService.showErrorSummary(passThroughSummary.errors);
18541
+ }
18457
18542
  const doneChunk = createChatCompletionChunk(id, created, model, "", true);
18458
18543
  controller.enqueue(encoder.encode(`data: ${JSON.stringify(doneChunk)}
18459
18544
 
@@ -18526,7 +18611,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18526
18611
  res.writeHead(200, { "Content-Type": "application/json" });
18527
18612
  res.end(JSON.stringify({ object: "list", data: models }));
18528
18613
  } catch (err) {
18529
- log14.error("Failed to list models", { error: String(err) });
18614
+ log15.error("Failed to list models", { error: String(err) });
18530
18615
  res.writeHead(500, { "Content-Type": "application/json" });
18531
18616
  res.end(JSON.stringify({ error: "Failed to fetch models" }));
18532
18617
  }
@@ -18537,7 +18622,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18537
18622
  res.end(JSON.stringify({ error: `Unsupported path: ${url2.pathname}` }));
18538
18623
  return;
18539
18624
  }
18540
- log14.debug("Proxy request (node)", { method: req.method, path: url2.pathname });
18625
+ log15.debug("Proxy request (node)", { method: req.method, path: url2.pathname });
18541
18626
  let body = "";
18542
18627
  for await (const chunk of req) {
18543
18628
  body += chunk;
@@ -18560,7 +18645,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18560
18645
  const contentLen = typeof m?.content === "string" ? m.content.length : Array.isArray(m?.content) ? `arr${m.content.length}` : typeof m?.content;
18561
18646
  return `${i}:${role}${hasTc ? `(tc:${hasTc})` : ""}${role === "tool" ? `(tcid:${tcId},name:${tcName},clen:${contentLen})` : `(clen:${contentLen})`}`;
18562
18647
  });
18563
- log14.debug("Proxy chat request (node)", {
18648
+ log15.debug("Proxy chat request (node)", {
18564
18649
  stream,
18565
18650
  model,
18566
18651
  messages: messages.length,
@@ -18591,14 +18676,14 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18591
18676
  let spawnErrorText = null;
18592
18677
  child.on("error", (error45) => {
18593
18678
  spawnErrorText = String(error45?.message || error45);
18594
- log14.error("Failed to spawn cursor-agent", { error: spawnErrorText, model });
18679
+ log15.error("Failed to spawn cursor-agent", { error: spawnErrorText, model });
18595
18680
  });
18596
18681
  child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
18597
18682
  child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
18598
18683
  child.on("close", async (code) => {
18599
18684
  const stdout = Buffer.concat(stdoutChunks).toString().trim();
18600
18685
  const stderr = Buffer.concat(stderrChunks).toString().trim();
18601
- log14.debug("cursor-agent completed (node non-stream)", {
18686
+ log15.debug("cursor-agent completed (node non-stream)", {
18602
18687
  code,
18603
18688
  stdoutChars: stdout.length,
18604
18689
  stderrChars: stderr.length,
@@ -18624,7 +18709,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18624
18709
  return;
18625
18710
  }
18626
18711
  if (intercepted.toolCall) {
18627
- log14.debug("Intercepted OpenCode tool call (non-stream)", {
18712
+ log15.debug("Intercepted OpenCode tool call (non-stream)", {
18628
18713
  name: intercepted.toolCall.function.name,
18629
18714
  callId: intercepted.toolCall.id
18630
18715
  });
@@ -18638,7 +18723,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18638
18723
  const errSource = stderr || stdout || spawnErrorText || `cursor-agent exited with code ${String(code ?? "unknown")} and no output`;
18639
18724
  const parsed = parseAgentError(errSource);
18640
18725
  const userError = formatErrorForUser(parsed);
18641
- log14.error("cursor-cli failed", {
18726
+ log15.error("cursor-cli failed", {
18642
18727
  type: parsed.type,
18643
18728
  message: parsed.message,
18644
18729
  code
@@ -18666,6 +18751,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18666
18751
  const lineBuffer = new LineBuffer;
18667
18752
  const toolMapper = new ToolMapper;
18668
18753
  const toolSessionId = id;
18754
+ const passThroughTracker = new PassThroughTracker;
18669
18755
  const stderrChunks = [];
18670
18756
  let streamTerminated = false;
18671
18757
  let firstTokenReceived = false;
@@ -18677,7 +18763,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18677
18763
  return;
18678
18764
  }
18679
18765
  const errSource = String(error45?.message || error45);
18680
- log14.error("Failed to spawn cursor-agent (stream)", { error: errSource, model });
18766
+ log15.error("Failed to spawn cursor-agent (stream)", { error: errSource, model });
18681
18767
  const parsed = parseAgentError(errSource);
18682
18768
  const msg = formatErrorForUser(parsed);
18683
18769
  const errChunk = createChatCompletionChunk(id, created, model, msg, true);
@@ -18692,7 +18778,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18692
18778
  if (streamTerminated || res.writableEnded) {
18693
18779
  return;
18694
18780
  }
18695
- log14.debug("Intercepted OpenCode tool call (stream)", {
18781
+ log15.debug("Intercepted OpenCode tool call (stream)", {
18696
18782
  name: toolCall.function.name,
18697
18783
  callId: toolCall.id
18698
18784
  });
@@ -18758,6 +18844,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18758
18844
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18759
18845
  toolRouter,
18760
18846
  responseMeta: { id, created, model },
18847
+ passThroughTracker,
18761
18848
  onToolUpdate: (update) => {
18762
18849
  res.write(formatToolUpdateEvent(update));
18763
18850
  },
@@ -18828,6 +18915,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18828
18915
  suppressConverterToolEvents: SUPPRESS_CONVERTER_TOOL_EVENTS,
18829
18916
  toolRouter,
18830
18917
  responseMeta: { id, created, model },
18918
+ passThroughTracker,
18831
18919
  onToolUpdate: (update) => {
18832
18920
  res.write(formatToolUpdateEvent(update));
18833
18921
  },
@@ -18874,7 +18962,7 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18874
18962
  perf.mark("request:done");
18875
18963
  perf.summarize();
18876
18964
  const stderrText = Buffer.concat(stderrChunks).toString().trim();
18877
- log14.debug("cursor-agent completed (node stream)", {
18965
+ log15.debug("cursor-agent completed (node stream)", {
18878
18966
  code,
18879
18967
  stderrChars: stderrText.length
18880
18968
  });
@@ -18891,6 +18979,13 @@ async function ensureCursorProxyServer(workspaceDirectory, toolRouter) {
18891
18979
  res.end();
18892
18980
  return;
18893
18981
  }
18982
+ const passThroughSummary = passThroughTracker.getSummary();
18983
+ if (passThroughSummary.hasActivity) {
18984
+ await toastService.showPassThroughSummary(passThroughSummary.tools);
18985
+ }
18986
+ if (passThroughSummary.errors.length > 0) {
18987
+ await toastService.showErrorSummary(passThroughSummary.errors);
18988
+ }
18894
18989
  const doneChunk = {
18895
18990
  id,
18896
18991
  object: "chat.completion.chunk",
@@ -19095,7 +19190,7 @@ function buildToolHookEntries(registry2, fallbackBaseDir) {
19095
19190
  const normalizedArgs = applyToolContextDefaults(toolName, args, context, fallbackBaseDir, sessionWorkspaceBySession);
19096
19191
  return await handler(normalizedArgs);
19097
19192
  } catch (error45) {
19098
- log14.debug("Tool hook execution failed", { tool: toolName, error: String(error45?.message || error45) });
19193
+ log15.debug("Tool hook execution failed", { tool: toolName, error: String(error45?.message || error45) });
19099
19194
  throw error45;
19100
19195
  }
19101
19196
  }
@@ -19107,9 +19202,9 @@ function buildToolHookEntries(registry2, fallbackBaseDir) {
19107
19202
  }
19108
19203
  return entries;
19109
19204
  }
19110
- var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "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 }) => {
19205
+ var log15, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "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 }) => {
19111
19206
  const workspaceDirectory = resolveWorkspaceDirectory(worktree, directory);
19112
- log14.debug("Plugin initializing", {
19207
+ log15.debug("Plugin initializing", {
19113
19208
  directory,
19114
19209
  worktree,
19115
19210
  workspaceDirectory,
@@ -19117,22 +19212,22 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp",
19117
19212
  serverUrl: serverUrl?.toString()
19118
19213
  });
19119
19214
  if (!TOOL_LOOP_MODE_VALID) {
19120
- log14.warn("Invalid CURSOR_ACP_TOOL_LOOP_MODE; defaulting to opencode", { value: TOOL_LOOP_MODE_RAW });
19215
+ log15.warn("Invalid CURSOR_ACP_TOOL_LOOP_MODE; defaulting to opencode", { value: TOOL_LOOP_MODE_RAW });
19121
19216
  }
19122
19217
  if (!PROVIDER_BOUNDARY_MODE_VALID) {
19123
- log14.warn("Invalid CURSOR_ACP_PROVIDER_BOUNDARY; defaulting to v1", {
19218
+ log15.warn("Invalid CURSOR_ACP_PROVIDER_BOUNDARY; defaulting to v1", {
19124
19219
  value: PROVIDER_BOUNDARY_MODE_RAW
19125
19220
  });
19126
19221
  }
19127
19222
  if (!TOOL_LOOP_MAX_REPEAT_VALID) {
19128
- log14.warn("Invalid CURSOR_ACP_TOOL_LOOP_MAX_REPEAT; defaulting to 3", {
19223
+ log15.warn("Invalid CURSOR_ACP_TOOL_LOOP_MAX_REPEAT; defaulting to 3", {
19129
19224
  value: TOOL_LOOP_MAX_REPEAT_RAW
19130
19225
  });
19131
19226
  }
19132
19227
  if (ENABLE_PROVIDER_BOUNDARY_AUTOFALLBACK && PROVIDER_BOUNDARY.mode !== "v1") {
19133
- log14.debug("Provider boundary auto-fallback is enabled but inactive unless mode=v1");
19228
+ log15.debug("Provider boundary auto-fallback is enabled but inactive unless mode=v1");
19134
19229
  }
19135
- log14.info("Tool loop mode configured", {
19230
+ log15.info("Tool loop mode configured", {
19136
19231
  mode: TOOL_LOOP_MODE,
19137
19232
  providerBoundary: PROVIDER_BOUNDARY.mode,
19138
19233
  proxyExecToolCalls: PROXY_EXECUTE_TOOL_CALLS,
@@ -19140,12 +19235,14 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp",
19140
19235
  toolLoopMaxRepeat: TOOL_LOOP_MAX_REPEAT
19141
19236
  });
19142
19237
  await ensurePluginDirectory();
19238
+ toastService.setClient(client3);
19239
+ toastService.setClient(client3);
19143
19240
  const toolsEnabled = process.env.CURSOR_ACP_ENABLE_OPENCODE_TOOLS !== "false";
19144
19241
  const legacyProxyToolPathsEnabled = toolsEnabled && TOOL_LOOP_MODE === "proxy-exec";
19145
19242
  if (toolsEnabled && TOOL_LOOP_MODE === "opencode") {
19146
- log14.debug("OpenCode mode active; skipping legacy SDK/MCP discovery and proxy-side tool execution");
19243
+ log15.debug("OpenCode mode active; skipping legacy SDK/MCP discovery and proxy-side tool execution");
19147
19244
  } else if (toolsEnabled && TOOL_LOOP_MODE === "off") {
19148
- log14.debug("Tool loop mode off; proxy-side tool execution disabled");
19245
+ log15.debug("Tool loop mode off; proxy-side tool execution disabled");
19149
19246
  }
19150
19247
  const serverClient = legacyProxyToolPathsEnabled ? createOpencodeClient({ baseUrl: serverUrl.toString(), directory: workspaceDirectory }) : null;
19151
19248
  const discovery = legacyProxyToolPathsEnabled ? new OpenCodeToolDiscovery(serverClient ?? client3) : null;
@@ -19197,7 +19294,7 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp",
19197
19294
  discoveredList = await discovery.listTools();
19198
19295
  discoveredList.forEach((t) => toolsByName.set(t.name, t));
19199
19296
  } catch (err) {
19200
- log14.debug("Tool discovery failed, using local tools only", { error: String(err) });
19297
+ log15.debug("Tool discovery failed, using local tools only", { error: String(err) });
19201
19298
  }
19202
19299
  }
19203
19300
  const allTools = [...localTools, ...discoveredList];
@@ -19227,11 +19324,11 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp",
19227
19324
  }
19228
19325
  lastToolNames = toolEntries.map((e) => e.function.name);
19229
19326
  lastToolMap = allTools.map((t) => ({ id: t.id, name: t.name }));
19230
- log14.debug("Tools refreshed", { local: localTools.length, discovered: discoveredList.length, total: toolEntries.length });
19327
+ log15.debug("Tools refreshed", { local: localTools.length, discovered: discoveredList.length, total: toolEntries.length });
19231
19328
  return toolEntries;
19232
19329
  }
19233
19330
  const proxyBaseURL = await ensureCursorProxyServer(workspaceDirectory, router);
19234
- log14.debug("Proxy server started", { baseURL: proxyBaseURL });
19331
+ log15.debug("Proxy server started", { baseURL: proxyBaseURL });
19235
19332
  const toolHookEntries = buildToolHookEntries(localRegistry, workspaceDirectory);
19236
19333
  return {
19237
19334
  tool: toolHookEntries,
@@ -19246,9 +19343,9 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp",
19246
19343
  type: "oauth",
19247
19344
  async authorize() {
19248
19345
  try {
19249
- log14.info("Starting OAuth flow");
19346
+ log15.info("Starting OAuth flow");
19250
19347
  const { url: url2, instructions, callback } = await startCursorOAuth();
19251
- log14.debug("Got OAuth URL", { url: url2.substring(0, 50) + "..." });
19348
+ log15.debug("Got OAuth URL", { url: url2.substring(0, 50) + "..." });
19252
19349
  return {
19253
19350
  url: url2,
19254
19351
  instructions,
@@ -19256,7 +19353,7 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp",
19256
19353
  callback
19257
19354
  };
19258
19355
  } catch (error45) {
19259
- log14.error("OAuth error", { error: error45 });
19356
+ log15.error("OAuth error", { error: error45 });
19260
19357
  throw error45;
19261
19358
  }
19262
19359
  }
@@ -19280,10 +19377,10 @@ var log14, DEBUG_LOG_DIR2, DEBUG_LOG_FILE2, CURSOR_PROVIDER_ID2 = "cursor-acp",
19280
19377
  output.options.tools = resolved.tools;
19281
19378
  } else if (resolved.action === "preserve") {
19282
19379
  const count = Array.isArray(existingTools) ? existingTools.length : 0;
19283
- log14.debug("Using OpenCode-provided tools from chat.params", { count });
19380
+ log15.debug("Using OpenCode-provided tools from chat.params", { count });
19284
19381
  }
19285
19382
  } catch (err) {
19286
- log14.debug("Failed to refresh tools", { error: String(err) });
19383
+ log15.debug("Failed to refresh tools", { error: String(err) });
19287
19384
  }
19288
19385
  }
19289
19386
  },
@@ -19316,9 +19413,10 @@ var init_plugin = __esm(() => {
19316
19413
  init_executor();
19317
19414
  init_boundary();
19318
19415
  init_runtime_interception();
19416
+ init_toast_service();
19319
19417
  init_tool_schema_compat();
19320
19418
  init_tool_loop_guard();
19321
- log14 = createLogger("plugin");
19419
+ log15 = createLogger("plugin");
19322
19420
  DEBUG_LOG_DIR2 = join5(homedir5(), ".config", "opencode", "logs");
19323
19421
  DEBUG_LOG_FILE2 = join5(DEBUG_LOG_DIR2, "tool-loop-debug.log");
19324
19422
  CURSOR_PROVIDER_PREFIX = `${CURSOR_PROVIDER_ID2}/`;
@@ -19411,11 +19509,11 @@ function shouldEnableCursorPlugin(env = process.env) {
19411
19509
 
19412
19510
  // src/plugin-entry.ts
19413
19511
  init_logger();
19414
- var log15 = createLogger("plugin-entry");
19512
+ var log16 = createLogger("plugin-entry");
19415
19513
  var CursorPluginEntry = async (input) => {
19416
19514
  const state = shouldEnableCursorPlugin();
19417
19515
  if (!state.enabled) {
19418
- log15.info("Plugin disabled in OpenCode config; skipping initialization", {
19516
+ log16.info("Plugin disabled in OpenCode config; skipping initialization", {
19419
19517
  configPath: state.configPath,
19420
19518
  reason: state.reason
19421
19519
  });