pi-cursor-sdk 0.2.0 → 0.3.6
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 +62 -0
- package/README.md +54 -50
- package/dist/bundled-context-windows.js +39 -0
- package/dist/context-window-cache.js +92 -0
- package/dist/context.js +338 -0
- package/dist/cursor-active-tools.js +3 -0
- package/dist/cursor-agent-message-web-tools.js +165 -0
- package/dist/cursor-agents-context-registration.js +17 -0
- package/dist/cursor-agents-context.js +113 -0
- package/dist/cursor-api-key.js +34 -0
- package/dist/cursor-bridge-contract.js +27 -0
- package/dist/cursor-cloud-lifecycle.js +650 -0
- package/dist/cursor-cloud-local-state.js +460 -0
- package/dist/cursor-cloud-options.js +145 -0
- package/dist/cursor-cloud-reporting.js +222 -0
- package/dist/cursor-compact-tool-summary.js +75 -0
- package/dist/cursor-config.js +613 -0
- package/dist/cursor-context-tools.js +4 -0
- package/dist/cursor-display-only-trace.js +11 -0
- package/dist/cursor-display-text.js +18 -0
- package/dist/cursor-durable-fs.js +53 -0
- package/dist/cursor-edit-diff.js +13 -0
- package/dist/cursor-env-boolean.js +19 -0
- package/dist/cursor-fallback-models.generated.js +7760 -0
- package/dist/cursor-fallback-warning.js +15 -0
- package/dist/cursor-http1.js +45 -0
- package/dist/cursor-incomplete-tool-visibility.js +83 -0
- package/dist/cursor-live-run-accounting.js +55 -0
- package/dist/cursor-live-run-coordinator.js +406 -0
- package/dist/cursor-mcp-timeout-override.js +116 -0
- package/dist/cursor-model-lifecycle.js +32 -0
- package/dist/cursor-model.js +5 -0
- package/dist/cursor-native-replay-routing.js +35 -0
- package/dist/cursor-native-replay-trace.js +28 -0
- package/dist/cursor-native-tool-display-registration.js +102 -0
- package/dist/cursor-native-tool-display-replay.js +428 -0
- package/dist/cursor-native-tool-display-state.js +70 -0
- package/dist/cursor-native-tool-display-tools.js +123 -0
- package/dist/cursor-native-tool-names.js +11 -0
- package/dist/cursor-partial-content-emitter.js +118 -0
- package/dist/cursor-pi-tool-bridge-abort.js +114 -0
- package/dist/cursor-pi-tool-bridge-constants.js +6 -0
- package/dist/cursor-pi-tool-bridge-diagnostics.js +125 -0
- package/dist/cursor-pi-tool-bridge-env.js +18 -0
- package/dist/cursor-pi-tool-bridge-mcp.js +100 -0
- package/dist/cursor-pi-tool-bridge-run.js +355 -0
- package/dist/cursor-pi-tool-bridge-server.js +163 -0
- package/dist/cursor-pi-tool-bridge-snapshot.js +63 -0
- package/dist/cursor-pi-tool-bridge-types.js +1 -0
- package/dist/cursor-pi-tool-bridge.js +123 -0
- package/dist/cursor-provider-errors.js +311 -0
- package/dist/cursor-provider-lazy.js +39 -0
- package/dist/cursor-provider-live-run-drain.js +412 -0
- package/dist/cursor-provider-overflow.js +90 -0
- package/dist/cursor-provider-run-finalizer.js +176 -0
- package/dist/cursor-provider-run-outcome.js +76 -0
- package/dist/cursor-provider-turn-coordinator.js +275 -0
- package/dist/cursor-provider-turn-display-router.js +158 -0
- package/dist/cursor-provider-turn-emit.js +35 -0
- package/dist/cursor-provider-turn-finalize.js +154 -0
- package/dist/cursor-provider-turn-lifecycle-emitter.js +126 -0
- package/dist/cursor-provider-turn-prepare.js +374 -0
- package/dist/cursor-provider-turn-runner.js +146 -0
- package/dist/cursor-provider-turn-sdk-normalizer.js +74 -0
- package/dist/cursor-provider-turn-send.js +138 -0
- package/dist/cursor-provider-turn-shell-output.js +117 -0
- package/dist/cursor-provider-turn-tool-ledger.js +99 -0
- package/dist/cursor-provider-turn-types.js +1 -0
- package/dist/cursor-provider.js +72 -0
- package/dist/cursor-question-tool.js +194 -0
- package/dist/cursor-record-utils.js +61 -0
- package/dist/cursor-replay-activity-builders.js +114 -0
- package/dist/cursor-replay-source-names.js +27 -0
- package/dist/cursor-replay-summary-args.js +105 -0
- package/dist/cursor-replay-tool-details.js +167 -0
- package/dist/cursor-ripgrep-path.js +27 -0
- package/dist/cursor-run-final-text.js +63 -0
- package/dist/cursor-runtime-state.js +380 -0
- package/dist/cursor-sdk-billed-usage.js +86 -0
- package/dist/cursor-sdk-event-debug-constants.js +33 -0
- package/dist/cursor-sdk-event-debug-session.js +107 -0
- package/dist/cursor-sdk-event-debug.js +461 -0
- package/dist/cursor-sdk-output-filter.js +1 -0
- package/dist/cursor-sdk-process-error-guard.js +221 -0
- package/dist/cursor-sdk-runtime.js +3 -0
- package/dist/cursor-sensitive-text.js +23 -0
- package/dist/cursor-session-agent-cleanup.js +311 -0
- package/dist/cursor-session-agent-lifecycle.js +32 -0
- package/dist/cursor-session-agent-lineage.js +103 -0
- package/dist/cursor-session-agent-resume.js +417 -0
- package/dist/cursor-session-agent.js +507 -0
- package/dist/cursor-session-compaction-prep.js +21 -0
- package/dist/cursor-session-scope.js +113 -0
- package/dist/cursor-session-send-policy.js +18 -0
- package/dist/cursor-session-store.js +105 -0
- package/dist/cursor-session-turn-queue.js +50 -0
- package/dist/cursor-setting-sources.js +15 -0
- package/dist/cursor-skill-tool.js +230 -0
- package/dist/cursor-state.js +519 -0
- package/dist/cursor-task-presentation.js +59 -0
- package/dist/cursor-tool-lifecycle.js +94 -0
- package/dist/cursor-tool-manifest.js +34 -0
- package/dist/cursor-tool-presentation-registry.js +305 -0
- package/dist/cursor-tool-result-display-readers.js +158 -0
- package/dist/cursor-tool-transcript.js +32 -0
- package/dist/cursor-tool-visibility.js +28 -0
- package/dist/cursor-transcript-tool-formatters.js +618 -0
- package/dist/cursor-transcript-tool-specs.js +284 -0
- package/dist/cursor-transcript-utils.js +170 -0
- package/dist/cursor-usage-accounting.js +166 -0
- package/dist/cursor-web-tool-activity.js +23 -0
- package/dist/cursor-web-tool-args.js +12 -0
- package/dist/index.js +82 -0
- package/dist/model-discovery.js +305 -0
- package/dist/model-list-cache.js +156 -0
- package/docs/cursor-dogfood-checklist.md +2 -1
- package/docs/cursor-live-smoke-checklist.md +13 -12
- package/docs/cursor-model-ux-spec.md +25 -6
- package/docs/cursor-native-tool-replay.md +13 -13
- package/docs/cursor-native-tool-visual-audit.md +6 -3
- package/docs/cursor-testing-lessons.md +7 -7
- package/docs/cursor-tool-surfaces.md +5 -5
- package/docs/platform-smoke.md +3 -3
- package/package.json +19 -7
- package/platform-smoke.config.mjs +1 -1
- package/scripts/build.mjs +126 -0
- package/scripts/cloud-runtime-smoke.mjs +3 -1
- package/scripts/debug-provider-events.mjs +3 -1
- package/scripts/debug-sdk-events.mjs +1 -1
- package/scripts/isolated-cursor-smoke.sh +5 -4
- package/scripts/lib/cloud-smoke-cleanup-evidence.mjs +1 -1
- package/scripts/lib/cursor-visual-render.mjs +1 -1
- package/scripts/lib/ensure-built.mjs +16 -0
- package/scripts/lib/local-resume-smoke-harness.mjs +1 -1
- package/scripts/local-resume-smoke.mjs +3 -1
- package/scripts/platform-smoke/card-detect.mjs +1 -1
- package/scripts/platform-smoke/live-suite-runner.mjs +1 -1
- package/scripts/platform-smoke/render-ansi.mjs +1 -1
- package/scripts/platform-smoke/targets.mjs +2 -2
- package/scripts/prepare.mjs +102 -0
- package/scripts/steering-rpc-smoke.mjs +4 -2
- package/scripts/tmux-live-smoke.sh +11 -11
- package/scripts/visual-tui-smoke-self-test.mjs +4 -1
- package/scripts/visual-tui-smoke.mjs +51 -7
- package/src/bundled-context-windows.ts +4 -1
- package/src/cursor-agents-context-registration.ts +2 -2
- package/src/cursor-agents-context.ts +0 -2
- package/src/cursor-api-key.ts +5 -4
- package/src/cursor-cloud-reporting.ts +23 -2
- package/src/cursor-fallback-models.generated.ts +592 -204
- package/src/cursor-live-run-coordinator.ts +1 -0
- package/src/cursor-native-tool-display-registration.ts +10 -11
- package/src/cursor-provider-errors.ts +1 -1
- package/src/cursor-provider-lazy.ts +5 -4
- package/src/cursor-provider-live-run-drain.ts +1 -0
- package/src/cursor-provider-run-finalizer.ts +1 -0
- package/src/cursor-provider-turn-finalize.ts +12 -0
- package/src/cursor-provider-turn-types.ts +2 -0
- package/src/cursor-sdk-billed-usage.ts +107 -0
- package/src/cursor-sdk-process-error-guard.ts +6 -4
- package/src/cursor-session-agent-lifecycle.ts +8 -9
- package/src/cursor-session-agent-resume.ts +23 -0
- package/src/cursor-session-compaction-prep.ts +4 -0
- package/src/cursor-tool-manifest.ts +1 -1
- package/src/cursor-usage-accounting.ts +70 -9
- package/src/index.ts +1 -1
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS = 60_000;
|
|
2
|
+
const DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS = 3_600_000;
|
|
3
|
+
const DEFAULT_CURSOR_MCP_CONNECT_TIMEOUT_MS = 10_000;
|
|
4
|
+
const MIN_CURSOR_MCP_CONNECT_TIMEOUT_MS = 1_000;
|
|
5
|
+
const MAX_NODE_TIMER_DELAY_MS = 2_147_483_647;
|
|
6
|
+
const CURSOR_MCP_TOOL_TIMEOUT_MS_ENV = "PI_CURSOR_MCP_TOOL_TIMEOUT_MS";
|
|
7
|
+
const CURSOR_MCP_TOOL_TIMEOUT_SECONDS_ENV = "PI_CURSOR_MCP_TOOL_TIMEOUT_SECONDS";
|
|
8
|
+
const CURSOR_MCP_CONNECT_TIMEOUT_MS_ENV = "PI_CURSOR_MCP_CONNECT_TIMEOUT_MS";
|
|
9
|
+
const CURSOR_MCP_CONNECT_TIMEOUT_SECONDS_ENV = "PI_CURSOR_MCP_CONNECT_TIMEOUT_SECONDS";
|
|
10
|
+
let originalSetTimeout;
|
|
11
|
+
let installedToolTimeoutMs = DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
|
|
12
|
+
let installedConnectTimeoutMs = DEFAULT_CURSOR_MCP_CONNECT_TIMEOUT_MS;
|
|
13
|
+
function parsePositiveNumber(value) {
|
|
14
|
+
const trimmed = value?.trim();
|
|
15
|
+
if (!trimmed)
|
|
16
|
+
return undefined;
|
|
17
|
+
const parsed = Number(trimmed);
|
|
18
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
19
|
+
}
|
|
20
|
+
function normalizeOverrideTimeoutMs(timeoutMs) {
|
|
21
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
22
|
+
return DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
|
|
23
|
+
return Math.min(Math.max(Math.trunc(timeoutMs), CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS), MAX_NODE_TIMER_DELAY_MS);
|
|
24
|
+
}
|
|
25
|
+
export function resolveCursorMcpToolTimeoutMs(env = process.env) {
|
|
26
|
+
const explicitMs = parsePositiveNumber(env[CURSOR_MCP_TOOL_TIMEOUT_MS_ENV]);
|
|
27
|
+
if (explicitMs !== undefined)
|
|
28
|
+
return normalizeOverrideTimeoutMs(explicitMs);
|
|
29
|
+
const explicitSeconds = parsePositiveNumber(env[CURSOR_MCP_TOOL_TIMEOUT_SECONDS_ENV]);
|
|
30
|
+
if (explicitSeconds !== undefined)
|
|
31
|
+
return normalizeOverrideTimeoutMs(explicitSeconds * 1000);
|
|
32
|
+
return DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
|
|
33
|
+
}
|
|
34
|
+
function normalizeConnectTimeoutMs(timeoutMs) {
|
|
35
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
|
|
36
|
+
return DEFAULT_CURSOR_MCP_CONNECT_TIMEOUT_MS;
|
|
37
|
+
return Math.min(Math.max(Math.trunc(timeoutMs), MIN_CURSOR_MCP_CONNECT_TIMEOUT_MS), CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS);
|
|
38
|
+
}
|
|
39
|
+
export function resolveCursorMcpConnectTimeoutMs(env = process.env) {
|
|
40
|
+
const explicitMs = parsePositiveNumber(env[CURSOR_MCP_CONNECT_TIMEOUT_MS_ENV]);
|
|
41
|
+
if (explicitMs !== undefined)
|
|
42
|
+
return normalizeConnectTimeoutMs(explicitMs);
|
|
43
|
+
const explicitSeconds = parsePositiveNumber(env[CURSOR_MCP_CONNECT_TIMEOUT_SECONDS_ENV]);
|
|
44
|
+
if (explicitSeconds !== undefined)
|
|
45
|
+
return normalizeConnectTimeoutMs(explicitSeconds * 1000);
|
|
46
|
+
return DEFAULT_CURSOR_MCP_CONNECT_TIMEOUT_MS;
|
|
47
|
+
}
|
|
48
|
+
function isCursorSdkMcpProtocolTimeoutStack(stack) {
|
|
49
|
+
if (!stack)
|
|
50
|
+
return false;
|
|
51
|
+
return (/(?:node_modules[/\\]@cursor[/\\]sdk|node_modules\/\@cursor\/sdk|@cursor\/sdk\/dist)/.test(stack) &&
|
|
52
|
+
/\b_setupTimeout\b|\bProtocol\._setupTimeout\b/.test(stack));
|
|
53
|
+
}
|
|
54
|
+
export function isCursorSdkMcpToolTimeoutStack(stack) {
|
|
55
|
+
if (!stack)
|
|
56
|
+
return false;
|
|
57
|
+
return (isCursorSdkMcpProtocolTimeoutStack(stack) &&
|
|
58
|
+
/\bcallTool\b|\bClient\.callTool\b|\bMcpSdkClient\.callTool\b/.test(stack));
|
|
59
|
+
}
|
|
60
|
+
export function isCursorSdkMcpConnectTimeoutStack(stack) {
|
|
61
|
+
if (!stack || !isCursorSdkMcpProtocolTimeoutStack(stack))
|
|
62
|
+
return false;
|
|
63
|
+
return /\bClient\.(?:connect|listTools)\b|\bMcpSdkClient\.getTools\b/.test(stack);
|
|
64
|
+
}
|
|
65
|
+
function isCursorSdkDefaultMcpTimeout(delay) {
|
|
66
|
+
return typeof delay === "number" && delay === CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS;
|
|
67
|
+
}
|
|
68
|
+
function patchedSetTimeout(handler, delay, ...args) {
|
|
69
|
+
const delegate = originalSetTimeout;
|
|
70
|
+
if (!delegate)
|
|
71
|
+
throw new Error("Cursor MCP timeout override installed without original setTimeout");
|
|
72
|
+
let nextDelay = delay;
|
|
73
|
+
if (isCursorSdkDefaultMcpTimeout(delay)) {
|
|
74
|
+
const stack = new Error().stack;
|
|
75
|
+
if (isCursorSdkMcpToolTimeoutStack(stack)) {
|
|
76
|
+
nextDelay = installedToolTimeoutMs;
|
|
77
|
+
}
|
|
78
|
+
else if (isCursorSdkMcpConnectTimeoutStack(stack)) {
|
|
79
|
+
nextDelay = installedConnectTimeoutMs;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return Reflect.apply(delegate, globalThis, [handler, nextDelay, ...args]);
|
|
83
|
+
}
|
|
84
|
+
export function installCursorMcpToolTimeoutOverride(options = {}) {
|
|
85
|
+
installedToolTimeoutMs = normalizeOverrideTimeoutMs(options.timeoutMs ?? resolveCursorMcpToolTimeoutMs(options.env));
|
|
86
|
+
installedConnectTimeoutMs = normalizeConnectTimeoutMs(options.connectTimeoutMs ?? resolveCursorMcpConnectTimeoutMs(options.env));
|
|
87
|
+
if (!originalSetTimeout) {
|
|
88
|
+
originalSetTimeout = globalThis.setTimeout;
|
|
89
|
+
globalThis.setTimeout = patchedSetTimeout;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
installed: true,
|
|
93
|
+
timeoutMs: installedToolTimeoutMs,
|
|
94
|
+
connectTimeoutMs: installedConnectTimeoutMs,
|
|
95
|
+
sdkDefaultTimeoutMs: CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function restoreCursorMcpToolTimeoutOverride() {
|
|
99
|
+
if (originalSetTimeout) {
|
|
100
|
+
globalThis.setTimeout = originalSetTimeout;
|
|
101
|
+
originalSetTimeout = undefined;
|
|
102
|
+
}
|
|
103
|
+
installedToolTimeoutMs = DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS;
|
|
104
|
+
installedConnectTimeoutMs = DEFAULT_CURSOR_MCP_CONNECT_TIMEOUT_MS;
|
|
105
|
+
}
|
|
106
|
+
export const cursorMcpToolTimeoutOverrideDefaults = {
|
|
107
|
+
cursorSdkDefaultTimeoutMs: CURSOR_SDK_MCP_DEFAULT_TIMEOUT_MS,
|
|
108
|
+
defaultOverrideTimeoutMs: DEFAULT_CURSOR_MCP_TOOL_TIMEOUT_MS,
|
|
109
|
+
defaultConnectTimeoutMs: DEFAULT_CURSOR_MCP_CONNECT_TIMEOUT_MS,
|
|
110
|
+
minConnectTimeoutMs: MIN_CURSOR_MCP_CONNECT_TIMEOUT_MS,
|
|
111
|
+
maxNodeTimerDelayMs: MAX_NODE_TIMER_DELAY_MS,
|
|
112
|
+
timeoutMsEnv: CURSOR_MCP_TOOL_TIMEOUT_MS_ENV,
|
|
113
|
+
timeoutSecondsEnv: CURSOR_MCP_TOOL_TIMEOUT_SECONDS_ENV,
|
|
114
|
+
connectTimeoutMsEnv: CURSOR_MCP_CONNECT_TIMEOUT_MS_ENV,
|
|
115
|
+
connectTimeoutSecondsEnv: CURSOR_MCP_CONNECT_TIMEOUT_SECONDS_ENV,
|
|
116
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function normalizeLifecycleHandlers(handlerOrHandlers) {
|
|
2
|
+
return typeof handlerOrHandlers === "function" ? { sync: handlerOrHandlers } : handlerOrHandlers;
|
|
3
|
+
}
|
|
4
|
+
export function registerCursorModelLifecycle(pi, handlerOrHandlers) {
|
|
5
|
+
const handlers = normalizeLifecycleHandlers(handlerOrHandlers);
|
|
6
|
+
const sync = handlers.sync;
|
|
7
|
+
if (handlers.sessionStart || sync) {
|
|
8
|
+
pi.on("session_start", async (event, ctx) => {
|
|
9
|
+
await handlers.sessionStart?.(event, ctx);
|
|
10
|
+
await sync?.(ctx);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
if (handlers.modelSelect || sync) {
|
|
14
|
+
pi.on("model_select", async (event, ctx) => {
|
|
15
|
+
const effectiveCtx = { ...ctx, model: event.model };
|
|
16
|
+
await handlers.modelSelect?.(event, effectiveCtx);
|
|
17
|
+
await sync?.(effectiveCtx);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
if (handlers.turnStart || sync) {
|
|
21
|
+
pi.on("turn_start", async (event, ctx) => {
|
|
22
|
+
await handlers.turnStart?.(event, ctx);
|
|
23
|
+
await sync?.(ctx);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (handlers.beforeAgentStart || sync) {
|
|
27
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
28
|
+
await sync?.(ctx);
|
|
29
|
+
return await handlers.beforeAgentStart?.(event, ctx);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { canRenderCursorToolNatively } from "./cursor-native-tool-display-state.js";
|
|
2
|
+
import { getActiveContextToolNames } from "./cursor-context-tools.js";
|
|
3
|
+
export function isNativeToolActiveInContext(toolName, activeToolNames) {
|
|
4
|
+
return activeToolNames === undefined || activeToolNames.has(toolName);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Canonical native replay routing for coordinator and live-run drain.
|
|
8
|
+
* Extension resync (pi active tools) is separate; this uses context.tools snapshot only.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveNativeReplayDisposition(input) {
|
|
11
|
+
if (!input.useNativeToolReplay || !canRenderCursorToolNatively(input.toolName)) {
|
|
12
|
+
return "transcript_trace";
|
|
13
|
+
}
|
|
14
|
+
if (isNativeToolActiveInContext(input.toolName, input.activeToolNames) && input.hasLiveRun) {
|
|
15
|
+
return "queue_replay";
|
|
16
|
+
}
|
|
17
|
+
if (!isNativeToolActiveInContext(input.toolName, input.activeToolNames)) {
|
|
18
|
+
return "inactive_trace";
|
|
19
|
+
}
|
|
20
|
+
return "transcript_trace";
|
|
21
|
+
}
|
|
22
|
+
export function partitionNativeToolsByActiveContext(context, tools) {
|
|
23
|
+
const activeToolNames = getActiveContextToolNames(context);
|
|
24
|
+
if (!activeToolNames)
|
|
25
|
+
return { active: [...tools], inactive: [] };
|
|
26
|
+
const active = [];
|
|
27
|
+
const inactive = [];
|
|
28
|
+
for (const tool of tools) {
|
|
29
|
+
if (activeToolNames.has(tool.toolName))
|
|
30
|
+
active.push(tool);
|
|
31
|
+
else
|
|
32
|
+
inactive.push(tool);
|
|
33
|
+
}
|
|
34
|
+
return { active, inactive };
|
|
35
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { asRecord } from "./cursor-record-utils.js";
|
|
2
|
+
import { truncateCursorDisplayLine } from "./cursor-display-text.js";
|
|
3
|
+
function getCursorReplayResultText(display) {
|
|
4
|
+
for (const content of display.result.content) {
|
|
5
|
+
if (content.type !== "text")
|
|
6
|
+
continue;
|
|
7
|
+
const text = truncateCursorDisplayLine(content.text);
|
|
8
|
+
if (text)
|
|
9
|
+
return text;
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
/** Unified inactive native-replay fallback: `title: summary` in thinking trace. */
|
|
14
|
+
export function formatInactiveCursorReplayTrace(display) {
|
|
15
|
+
const details = asRecord(display.result.details);
|
|
16
|
+
const args = asRecord(display.args);
|
|
17
|
+
const title = typeof details?.title === "string" && details.title.trim()
|
|
18
|
+
? details.title.trim()
|
|
19
|
+
: typeof args?.activityTitle === "string" && args.activityTitle.trim()
|
|
20
|
+
? args.activityTitle.trim()
|
|
21
|
+
: `Cursor ${display.toolName}`;
|
|
22
|
+
const summary = typeof details?.summary === "string" && details.summary.trim()
|
|
23
|
+
? details.summary.trim()
|
|
24
|
+
: typeof args?.activitySummary === "string" && args.activitySummary.trim()
|
|
25
|
+
? args.activitySummary.trim()
|
|
26
|
+
: getCursorReplayResultText(display) ?? "completed";
|
|
27
|
+
return `${truncateCursorDisplayLine(title)}: ${truncateCursorDisplayLine(summary)}\n`;
|
|
28
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { arePiToolsDisabled } from "./cursor-active-tools.js";
|
|
2
|
+
import { CURSOR_MODEL_ACTIVE_REPLAY_TOOL_NAMES, isNativeCursorToolName, NATIVE_CURSOR_TOOL_NAMES, } from "./cursor-native-tool-names.js";
|
|
3
|
+
import { isCursorModel } from "./cursor-model.js";
|
|
4
|
+
import { registerCursorModelLifecycle } from "./cursor-model-lifecycle.js";
|
|
5
|
+
import { isCursorNativeToolDisplayRequested, isCursorNativeToolRegistrationRequested, NATIVE_CURSOR_TOOL_DISPLAY_ENV, readBooleanEnv, registeredNativeToolNames, setCursorNativeToolDisplayRuntimeRequested, skippedNativeToolNames, } from "./cursor-native-tool-display-state.js";
|
|
6
|
+
import { isCursorReplayToolName } from "./cursor-tool-presentation-registry.js";
|
|
7
|
+
import { registerNativeCursorTool } from "./cursor-native-tool-display-tools.js";
|
|
8
|
+
export const CURSOR_CORE_PI_REPLAY_TOOL_NAMES = ["read", "bash", "edit", "write"];
|
|
9
|
+
const CORE_PI_TOOL_NAMES = new Set(CURSOR_CORE_PI_REPLAY_TOOL_NAMES);
|
|
10
|
+
function isCursorCorePiReplayToolName(toolName) {
|
|
11
|
+
return CORE_PI_TOOL_NAMES.has(toolName);
|
|
12
|
+
}
|
|
13
|
+
function hasNonBuiltinTool(pi, toolName) {
|
|
14
|
+
const existingTool = pi.getAllTools().find((tool) => tool.name === toolName);
|
|
15
|
+
return existingTool !== undefined && existingTool.sourceInfo.source !== "builtin";
|
|
16
|
+
}
|
|
17
|
+
function registerNativeCursorToolsFromSet(pi, toolNames) {
|
|
18
|
+
const newlySkippedToolNames = [];
|
|
19
|
+
for (const toolName of toolNames) {
|
|
20
|
+
if (registeredNativeToolNames.has(toolName) || skippedNativeToolNames.has(toolName))
|
|
21
|
+
continue;
|
|
22
|
+
if (hasNonBuiltinTool(pi, toolName)) {
|
|
23
|
+
skippedNativeToolNames.add(toolName);
|
|
24
|
+
newlySkippedToolNames.push(toolName);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
registerNativeCursorTool(pi, toolName);
|
|
28
|
+
registeredNativeToolNames.add(toolName);
|
|
29
|
+
}
|
|
30
|
+
return newlySkippedToolNames;
|
|
31
|
+
}
|
|
32
|
+
function notifySkippedNativeCursorToolsIfNeeded(ctx, skippedToolNames) {
|
|
33
|
+
if (skippedToolNames.length === 0 || readBooleanEnv(NATIVE_CURSOR_TOOL_DISPLAY_ENV) !== true || ctx.mode !== "tui")
|
|
34
|
+
return;
|
|
35
|
+
ctx.ui.notify(`Cursor native tool replay skipped for ${skippedToolNames.join(", ")} because another extension already provides ${skippedToolNames.length === 1 ? "that tool" : "those tools"}. Cursor will use scrubbed activity transcripts for skipped tools.`, "warning");
|
|
36
|
+
}
|
|
37
|
+
function hasAttemptedNativeCursorToolRegistration() {
|
|
38
|
+
return registeredNativeToolNames.size > 0 || skippedNativeToolNames.size > 0;
|
|
39
|
+
}
|
|
40
|
+
function removeRegisteredNonCoreNativeCursorTools(pi) {
|
|
41
|
+
if (registeredNativeToolNames.size === 0)
|
|
42
|
+
return;
|
|
43
|
+
const activeToolNames = new Set(pi.getActiveTools());
|
|
44
|
+
let changed = false;
|
|
45
|
+
for (const toolName of registeredNativeToolNames) {
|
|
46
|
+
if (isCursorCorePiReplayToolName(toolName))
|
|
47
|
+
continue;
|
|
48
|
+
if (!activeToolNames.delete(toolName))
|
|
49
|
+
continue;
|
|
50
|
+
changed = true;
|
|
51
|
+
}
|
|
52
|
+
if (changed)
|
|
53
|
+
pi.setActiveTools([...activeToolNames]);
|
|
54
|
+
}
|
|
55
|
+
export function syncRegisteredNativeCursorToolsForModel(pi, model) {
|
|
56
|
+
if (registeredNativeToolNames.size === 0)
|
|
57
|
+
return;
|
|
58
|
+
if (!isCursorModel(model)) {
|
|
59
|
+
removeRegisteredNonCoreNativeCursorTools(pi);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (arePiToolsDisabled(pi))
|
|
63
|
+
return;
|
|
64
|
+
const activeToolNames = new Set(pi.getActiveTools());
|
|
65
|
+
let changed = false;
|
|
66
|
+
for (const toolName of registeredNativeToolNames) {
|
|
67
|
+
if (isCursorReplayToolName(toolName) && !CURSOR_MODEL_ACTIVE_REPLAY_TOOL_NAMES.some((activeReplayToolName) => activeReplayToolName === toolName))
|
|
68
|
+
continue;
|
|
69
|
+
if (activeToolNames.has(toolName))
|
|
70
|
+
continue;
|
|
71
|
+
activeToolNames.add(toolName);
|
|
72
|
+
changed = true;
|
|
73
|
+
}
|
|
74
|
+
if (changed)
|
|
75
|
+
pi.setActiveTools([...activeToolNames]);
|
|
76
|
+
}
|
|
77
|
+
function ensureNativeCursorToolsRegisteredForModel(pi, ctx) {
|
|
78
|
+
if (!isCursorModel(ctx.model) || hasAttemptedNativeCursorToolRegistration())
|
|
79
|
+
return;
|
|
80
|
+
const nonCoreToolNames = NATIVE_CURSOR_TOOL_NAMES.filter((toolName) => !isCursorCorePiReplayToolName(toolName));
|
|
81
|
+
const skippedToolNames = [
|
|
82
|
+
...registerNativeCursorToolsFromSet(pi, nonCoreToolNames),
|
|
83
|
+
...registerNativeCursorToolsFromSet(pi, CURSOR_CORE_PI_REPLAY_TOOL_NAMES),
|
|
84
|
+
];
|
|
85
|
+
notifySkippedNativeCursorToolsIfNeeded(ctx, skippedToolNames);
|
|
86
|
+
}
|
|
87
|
+
function ensureThenSyncNativeCursorToolsForModel(pi, ctx) {
|
|
88
|
+
const requested = isCursorNativeToolRegistrationRequested(ctx.mode);
|
|
89
|
+
setCursorNativeToolDisplayRuntimeRequested(requested);
|
|
90
|
+
if (!requested) {
|
|
91
|
+
removeRegisteredNonCoreNativeCursorTools(pi);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
ensureNativeCursorToolsRegisteredForModel(pi, ctx);
|
|
95
|
+
syncRegisteredNativeCursorToolsForModel(pi, ctx.model);
|
|
96
|
+
}
|
|
97
|
+
export function registerCursorNativeToolDisplay(pi) {
|
|
98
|
+
registerCursorModelLifecycle(pi, (ctx) => {
|
|
99
|
+
ensureThenSyncNativeCursorToolsForModel(pi, ctx);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
export { isNativeCursorToolName, isCursorNativeToolDisplayRequested };
|