@emmaneugene/pi-cursor-sdk 0.4.2 → 0.4.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.3 - 2026-09-11
4
+
5
+ ### Fixed
6
+
7
+ - Keep live Cursor runs open while bridged pi tools await results. Long `cursor_ask_question` waits and other bridge calls now use the bridge CallTool deadline instead of being cancelled by the five-minute inactive-run cleanup.
8
+
3
9
  ## 0.4.2 - 2026-09-07
4
10
 
5
11
  ### Fixed
@@ -11,6 +11,11 @@ function isPendingBridgeToolRequest(run, request) {
11
11
  const bridgeRun = [run.bridgeRun, run.sessionBridgeRun].find((candidate) => candidate?.id === request.runId);
12
12
  return bridgeRun?.hasPendingPiToolCallId(request.piToolCallId) === true;
13
13
  }
14
+ function hasPendingBridgeCalls(run) {
15
+ if (run.bridgeRun?.hasPendingCalls())
16
+ return true;
17
+ return run.sessionBridgeRun !== run.bridgeRun && run.sessionBridgeRun?.hasPendingCalls() === true;
18
+ }
14
19
  async function cancelCursorLiveSdkRun(run) {
15
20
  if (!run.sdkRun)
16
21
  return;
@@ -350,6 +355,12 @@ export function createCursorLiveRunCoordinator(deps) {
350
355
  return;
351
356
  state.idleDisposeRequested = false;
352
357
  state.idleDisposeTimer = setTimeout(() => {
358
+ if (hasPendingBridgeCalls(run)) {
359
+ // Bridge calls have their own deadline. Reuse the idle interval to avoid a hot
360
+ // polling loop if the SDK does not emit a terminal event after that deadline.
361
+ coordinator.requestIdleDispose(run);
362
+ return;
363
+ }
353
364
  void coordinator.release(run).catch(() => {
354
365
  // Idle dispose must not leave release failures as unhandled rejections.
355
366
  });
@@ -126,6 +126,9 @@ export class CursorPiToolBridgeRunImpl {
126
126
  async resolveToolResultsFromContext(context) {
127
127
  await this.resolveToolResults(context.messages.map(asToolResultMessage).filter((message) => message !== undefined));
128
128
  }
129
+ hasPendingCalls() {
130
+ return this.pendingCount() > 0;
131
+ }
129
132
  hasPendingPiToolCallId(piToolCallId) {
130
133
  return this.pendingByPiToolCallId.has(piToolCallId);
131
134
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emmaneugene/pi-cursor-sdk",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "pi provider extension backed by @cursor/sdk local agents",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -111,6 +111,11 @@ function isPendingBridgeToolRequest(run: CursorLiveRun, request: CursorPiBridgeT
111
111
  return bridgeRun?.hasPendingPiToolCallId(request.piToolCallId) === true;
112
112
  }
113
113
 
114
+ function hasPendingBridgeCalls(run: CursorLiveRun): boolean {
115
+ if (run.bridgeRun?.hasPendingCalls()) return true;
116
+ return run.sessionBridgeRun !== run.bridgeRun && run.sessionBridgeRun?.hasPendingCalls() === true;
117
+ }
118
+
114
119
  export interface CursorLiveRunRecord {
115
120
  id: string;
116
121
  disposed: boolean;
@@ -494,6 +499,12 @@ export function createCursorLiveRunCoordinator(deps: CursorLiveRunCoordinatorDep
494
499
  if (state.leased || state.leaseQueue.length > 0) return;
495
500
  state.idleDisposeRequested = false;
496
501
  state.idleDisposeTimer = setTimeout(() => {
502
+ if (hasPendingBridgeCalls(run)) {
503
+ // Bridge calls have their own deadline. Reuse the idle interval to avoid a hot
504
+ // polling loop if the SDK does not emit a terminal event after that deadline.
505
+ coordinator.requestIdleDispose(run);
506
+ return;
507
+ }
497
508
  void coordinator.release(run).catch(() => {
498
509
  // Idle dispose must not leave release failures as unhandled rejections.
499
510
  });
@@ -183,6 +183,10 @@ export class CursorPiToolBridgeRunImpl implements CursorPiToolBridgeRun {
183
183
  await this.resolveToolResults(context.messages.map(asToolResultMessage).filter((message): message is ToolResultMessage => message !== undefined));
184
184
  }
185
185
 
186
+ hasPendingCalls(): boolean {
187
+ return this.pendingCount() > 0;
188
+ }
189
+
186
190
  hasPendingPiToolCallId(piToolCallId: string): boolean {
187
191
  return this.pendingByPiToolCallId.has(piToolCallId);
188
192
  }
@@ -65,6 +65,7 @@ export interface CursorPiToolBridgeRun {
65
65
  takeQueuedToolRequests(): CursorPiBridgeToolRequest[];
66
66
  resolveToolResults(toolResults: readonly ToolResultMessage[]): Promise<void>;
67
67
  resolveToolResultsFromContext(context: Context): Promise<void>;
68
+ hasPendingCalls(): boolean;
68
69
  hasPendingPiToolCallId(piToolCallId: string): boolean;
69
70
  isBridgeMcpToolCall(toolCall: unknown): boolean;
70
71
  setOnToolRequest(handler?: (request: CursorPiBridgeToolRequest) => void): void;