فهرست منبع

fix: log suppressed prompt rejections (#906)

Ulises Millan Guerrero 3 هفته پیش
والد
کامیت
8d1641b8c1
2فایلهای تغییر یافته به همراه52 افزوده شده و 1 حذف شده
  1. 45 0
      src/utils/session.test.ts
  2. 7 1
      src/utils/session.ts

+ 45 - 0
src/utils/session.test.ts

@@ -115,4 +115,49 @@ describe('session utilities', () => {
       'Session abort timed out after 5ms',
     );
   });
+
+  test('promptWithTimeout handles late prompt rejection without unhandled rejection', async () => {
+    let deferredReject: ((error: Error) => void) | undefined;
+    const prompt = mock(
+      () =>
+        new Promise<never>((_resolve, reject) => {
+          deferredReject = reject;
+        }),
+    );
+    const abort = mock(async () => ({}));
+    const client = {
+      session: { abort, prompt },
+    } as any;
+
+    let unhandledRejection: Error | null = null;
+    const handler = (err: Error) => {
+      unhandledRejection = err;
+    };
+    process.on('unhandledRejection', handler);
+    try {
+      await expect(
+        promptWithTimeout(
+          client,
+          { path: { id: 's1' }, body: { parts: [] } },
+          5,
+        ),
+      ).rejects.toThrow('Prompt timed out after 5ms');
+
+      // Timeout behavior is unchanged — abort is called
+      expect(abort).toHaveBeenCalledWith({ path: { id: 's1' } });
+
+      // Simulate a late provider response arriving after timeout
+      if (deferredReject) {
+        deferredReject(new Error('provider error after timeout'));
+      }
+
+      // Yield to the microtask queue so the catch handler runs
+      await new Promise<void>((resolve) => setTimeout(resolve, 0));
+
+      // No unhandled rejection should surface
+      expect(unhandledRejection).toBeNull();
+    } finally {
+      process.off('unhandledRejection', handler);
+    }
+  });
 });

+ 7 - 1
src/utils/session.ts

@@ -3,6 +3,7 @@
  */
 
 import type { PluginInput } from '@opencode-ai/plugin';
+import { log } from './logger';
 
 type OpencodeClient = PluginInput['client'];
 
@@ -109,7 +110,12 @@ export async function promptWithTimeout(
 
   try {
     const promptPromise = client.session.prompt(args);
-    promptPromise.catch(() => {});
+    promptPromise.catch((error) => {
+      log('[session] suppressed prompt rejection (race loser)', {
+        sessionId,
+        error: String(error),
+      });
+    });
 
     const racers: Array<Promise<unknown>> = [promptPromise];