pi-cursor-sdk 0.1.14 → 0.1.15

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.
@@ -0,0 +1,111 @@
1
+ const CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS = 60_000;
2
+ const DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS = 3_600_000;
3
+ const MAX_NODE_TIMER_DELAY_MS = 2_147_483_647;
4
+ const CURSOR_MCP_TOOL_TIMEOUT_MS_ENV = "PI_CURSOR_MCP_TOOL_TIMEOUT_MS";
5
+ const CURSOR_MCP_TOOL_TIMEOUT_SECONDS_ENV = "PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS";
6
+
7
+ interface CursorMcpToolTimeoutOverrideOptions {
8
+ timeoutMs?: number;
9
+ env?: Record<string, string | undefined>;
10
+ }
11
+
12
+ interface CursorMcpToolTimeoutOverrideState {
13
+ installed: boolean;
14
+ timeoutMs: number;
15
+ sdkDefaultTimeoutMs: number;
16
+ }
17
+
18
+ type GlobalSetTimeout = typeof globalThis.setTimeout;
19
+ type SetTimeoutHandler = Parameters<GlobalSetTimeout>[0];
20
+ type SetTimeoutDelay = Parameters<GlobalSetTimeout>[1];
21
+
22
+ let originalSetTimeout: GlobalSetTimeout | undefined;
23
+ let installedTimeoutMs = DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
24
+
25
+ function parsePositiveNumber(value: string | undefined): number | undefined {
26
+ const trimmed = value?.trim();
27
+ if (!trimmed) return undefined;
28
+ const parsed = Number(trimmed);
29
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
30
+ }
31
+
32
+ function normalizeOverrideTimeoutMs(timeoutMs: number): number {
33
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) return DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
34
+ return Math.min(Math.max(Math.trunc(timeoutMs), CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS), MAX_NODE_TIMER_DELAY_MS);
35
+ }
36
+
37
+ export function resolveCursorMcpToolTimeoutMs(
38
+ env: Record<string, string | undefined> = process.env,
39
+ ): number {
40
+ const explicitMs = parsePositiveNumber(env[CURSOR_MCP_TOOL_TIMEOUT_MS_ENV]);
41
+ if (explicitMs !== undefined) return normalizeOverrideTimeoutMs(explicitMs);
42
+
43
+ const explicitSeconds = parsePositiveNumber(env[CURSOR_MCP_TOOL_TIMEOUT_SECONDS_ENV]);
44
+ if (explicitSeconds !== undefined) return normalizeOverrideTimeoutMs(explicitSeconds * 1000);
45
+
46
+ return DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
47
+ }
48
+
49
+ export function isCursorSdkMcpToolTimeoutStack(stack: string | undefined): boolean {
50
+ if (!stack) return false;
51
+ return (
52
+ /(?:node_modules[/\\]@cursor[/\\]sdk|node_modules\/\@cursor\/sdk|@cursor\/sdk\/dist)/.test(stack) &&
53
+ /\b_setupTimeout\b|\bProtocol\._setupTimeout\b/.test(stack) &&
54
+ /\bcallTool\b|\bClient\.callTool\b|\bMcpSdkClient\.callTool\b/.test(stack)
55
+ );
56
+ }
57
+
58
+ function isCursorSdkDefaultMcpTimeout(delay: SetTimeoutDelay): boolean {
59
+ return typeof delay === "number" && delay === CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS;
60
+ }
61
+
62
+ function patchedSetTimeout(
63
+ handler: SetTimeoutHandler,
64
+ delay?: SetTimeoutDelay,
65
+ ...args: unknown[]
66
+ ): ReturnType<GlobalSetTimeout> {
67
+ const delegate = originalSetTimeout;
68
+ if (!delegate) throw new Error("Cursor MCP timeout override installed without original setTimeout");
69
+
70
+ const nextDelay =
71
+ isCursorSdkDefaultMcpTimeout(delay) && isCursorSdkMcpToolTimeoutStack(new Error().stack)
72
+ ? installedTimeoutMs
73
+ : delay;
74
+
75
+ return Reflect.apply(delegate, globalThis, [handler, nextDelay, ...args]) as ReturnType<GlobalSetTimeout>;
76
+ }
77
+
78
+ export function installCursorMcpToolTimeoutOverride(
79
+ options: CursorMcpToolTimeoutOverrideOptions = {},
80
+ ): CursorMcpToolTimeoutOverrideState {
81
+ installedTimeoutMs = normalizeOverrideTimeoutMs(
82
+ options.timeoutMs ?? resolveCursorMcpToolTimeoutMs(options.env),
83
+ );
84
+
85
+ if (!originalSetTimeout) {
86
+ originalSetTimeout = globalThis.setTimeout;
87
+ globalThis.setTimeout = patchedSetTimeout as GlobalSetTimeout;
88
+ }
89
+
90
+ return {
91
+ installed: true,
92
+ timeoutMs: installedTimeoutMs,
93
+ sdkDefaultTimeoutMs: CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS,
94
+ };
95
+ }
96
+
97
+ export function restoreCursorMcpToolTimeoutOverrideForTests(): void {
98
+ if (originalSetTimeout) {
99
+ globalThis.setTimeout = originalSetTimeout;
100
+ originalSetTimeout = undefined;
101
+ }
102
+ installedTimeoutMs = DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
103
+ }
104
+
105
+ export const cursorMcpToolTimeoutOverrideDefaults = {
106
+ cursorSdkDefaultTimeoutMs: CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS,
107
+ defaultOverrideTimeoutMs: DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS,
108
+ maxNodeTimerDelayMs: MAX_NODE_TIMER_DELAY_MS,
109
+ timeoutMsEnv: CURSOR_MCP_TOOL_TIMEOUT_MS_ENV,
110
+ timeoutSecondsEnv: CURSOR_MCP_TOOL_TIMEOUT_SECONDS_ENV,
111
+ } as const;