pi-cursor-sdk 0.1.62 → 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 +85 -0
- package/README.md +57 -53
- 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 +15 -14
- package/docs/cursor-model-ux-spec.md +29 -8
- 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 +6 -6
- package/node_modules/fast-uri/index.js +37 -1
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/security.test.js +136 -0
- package/node_modules/hono/dist/cjs/context.js +28 -13
- package/node_modules/hono/dist/cjs/helper/proxy/index.js +4 -0
- package/node_modules/hono/dist/cjs/helper/streaming/sse.js +1 -1
- package/node_modules/hono/dist/cjs/hono-base.js +3 -2
- package/node_modules/hono/dist/cjs/jsx/base.js +27 -23
- package/node_modules/hono/dist/cjs/jsx/hooks/index.js +16 -13
- package/node_modules/hono/dist/cjs/middleware/cache/index.js +103 -8
- package/node_modules/hono/dist/cjs/middleware/compress/index.js +5 -0
- package/node_modules/hono/dist/cjs/middleware/cors/index.js +2 -2
- package/node_modules/hono/dist/cjs/middleware/etag/index.js +1 -1
- package/node_modules/hono/dist/cjs/middleware/jwk/jwk.js +9 -4
- package/node_modules/hono/dist/cjs/middleware/jwt/jwt.js +9 -4
- package/node_modules/hono/dist/cjs/middleware/language/language.js +10 -6
- package/node_modules/hono/dist/cjs/middleware/method-not-allowed/index.js +90 -0
- package/node_modules/hono/dist/cjs/middleware/secure-headers/secure-headers.js +10 -4
- package/node_modules/hono/dist/cjs/request.js +7 -9
- package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +55 -56
- package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +64 -85
- package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +13 -5
- package/node_modules/hono/dist/cjs/router.js +1 -1
- package/node_modules/hono/dist/cjs/utils/accept.js +1 -1
- package/node_modules/hono/dist/cjs/utils/cookie.js +3 -2
- package/node_modules/hono/dist/cjs/utils/url.js +8 -8
- package/node_modules/hono/dist/context.js +28 -13
- package/node_modules/hono/dist/helper/proxy/index.js +4 -0
- package/node_modules/hono/dist/helper/streaming/sse.js +1 -1
- package/node_modules/hono/dist/hono-base.js +3 -2
- package/node_modules/hono/dist/jsx/base.js +27 -23
- package/node_modules/hono/dist/jsx/hooks/index.js +16 -13
- package/node_modules/hono/dist/middleware/cache/index.js +103 -8
- package/node_modules/hono/dist/middleware/compress/index.js +5 -0
- package/node_modules/hono/dist/middleware/cors/index.js +2 -2
- package/node_modules/hono/dist/middleware/etag/index.js +1 -1
- package/node_modules/hono/dist/middleware/jwk/jwk.js +9 -4
- package/node_modules/hono/dist/middleware/jwt/jwt.js +9 -4
- package/node_modules/hono/dist/middleware/language/language.js +10 -6
- package/node_modules/hono/dist/middleware/method-not-allowed/index.js +68 -0
- package/node_modules/hono/dist/middleware/secure-headers/secure-headers.js +10 -4
- package/node_modules/hono/dist/request.js +8 -10
- package/node_modules/hono/dist/router/reg-exp-router/node.js +55 -56
- package/node_modules/hono/dist/router/reg-exp-router/router.js +64 -85
- package/node_modules/hono/dist/router/reg-exp-router/trie.js +13 -5
- package/node_modules/hono/dist/router.js +1 -1
- package/node_modules/hono/dist/types/adapter/aws-lambda/types.d.ts +9 -0
- package/node_modules/hono/dist/types/client/types.d.ts +1 -1
- package/node_modules/hono/dist/types/hono-base.d.ts +4 -3
- package/node_modules/hono/dist/types/jsx/base.d.ts +4 -2
- package/node_modules/hono/dist/types/jsx/dom/index.d.ts +5 -5
- package/node_modules/hono/dist/types/jsx/dom/intrinsic-element/components.d.ts +2 -2
- package/node_modules/hono/dist/types/jsx/dom/server.d.ts +5 -5
- package/node_modules/hono/dist/types/jsx/hooks/index.d.ts +8 -6
- package/node_modules/hono/dist/types/jsx/index.d.ts +5 -5
- package/node_modules/hono/dist/types/middleware/cache/index.d.ts +6 -4
- package/node_modules/hono/dist/types/middleware/cors/index.d.ts +1 -1
- package/node_modules/hono/dist/types/middleware/jsx-renderer/index.d.ts +2 -2
- package/node_modules/hono/dist/types/middleware/jwk/jwk.d.ts +2 -0
- package/node_modules/hono/dist/types/middleware/jwt/jwt.d.ts +2 -0
- package/node_modules/hono/dist/types/middleware/method-not-allowed/index.d.ts +49 -0
- package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +1 -1
- package/node_modules/hono/dist/types/router/reg-exp-router/trie.d.ts +2 -1
- package/node_modules/hono/dist/types/router.d.ts +1 -1
- package/node_modules/hono/dist/types/utils/headers.d.ts +2 -2
- package/node_modules/hono/dist/types/utils/url.d.ts +1 -0
- package/node_modules/hono/dist/utils/accept.js +1 -1
- package/node_modules/hono/dist/utils/cookie.js +4 -3
- package/node_modules/hono/dist/utils/url.js +6 -7
- package/node_modules/hono/package.json +10 -3
- package/node_modules/ip-address/README.md +146 -126
- package/node_modules/ip-address/dist/common.d.ts +29 -0
- package/node_modules/ip-address/dist/common.js +44 -5
- package/node_modules/ip-address/dist/common.js.map +1 -1
- package/node_modules/ip-address/dist/ipv4.d.ts +8 -1
- package/node_modules/ip-address/dist/ipv4.js +24 -20
- package/node_modules/ip-address/dist/ipv4.js.map +1 -1
- package/node_modules/ip-address/dist/ipv6.d.ts +68 -3
- package/node_modules/ip-address/dist/ipv6.js +180 -53
- package/node_modules/ip-address/dist/ipv6.js.map +1 -1
- package/node_modules/ip-address/dist/v4/constants.js +5 -1
- package/node_modules/ip-address/dist/v4/constants.js.map +1 -1
- package/node_modules/ip-address/dist/v6/constants.js +3 -2
- package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
- package/node_modules/ip-address/package.json +6 -4
- package/package.json +23 -11
- 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 +16 -40
- package/scripts/platform-smoke/platform-build-windows.ps1 +1 -1
- package/scripts/platform-smoke/render-ansi.mjs +1 -1
- package/scripts/platform-smoke/scenarios.mjs +1 -1
- package/scripts/platform-smoke/targets.mjs +2 -2
- package/scripts/platform-smoke.mjs +5 -5
- package/scripts/prepare.mjs +102 -0
- package/scripts/refresh-cursor-model-snapshots.mjs +16 -7
- 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/shared/cursor-model-selection-identities.d.mts +21 -0
- package/shared/cursor-model-selection-identities.mjs +95 -0
- package/src/bundled-context-windows.ts +21 -12
- package/src/context.ts +1 -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-context-tools.ts +1 -1
- package/src/cursor-display-only-trace.ts +1 -1
- package/src/cursor-fallback-models.generated.ts +1726 -824
- package/src/cursor-live-run-accounting.ts +1 -1
- package/src/cursor-live-run-coordinator.ts +2 -1
- package/src/cursor-native-replay-routing.ts +1 -1
- package/src/cursor-native-tool-display-registration.ts +10 -11
- package/src/cursor-partial-content-emitter.ts +1 -1
- package/src/cursor-pi-tool-bridge-mcp.ts +1 -1
- package/src/cursor-pi-tool-bridge-run.ts +1 -1
- package/src/cursor-pi-tool-bridge-types.ts +1 -1
- package/src/cursor-provider-errors.ts +1 -1
- package/src/cursor-provider-lazy.ts +6 -5
- package/src/cursor-provider-live-run-drain.ts +2 -1
- package/src/cursor-provider-overflow.ts +1 -1
- package/src/cursor-provider-run-finalizer.ts +2 -1
- package/src/cursor-provider-turn-coordinator.ts +1 -1
- package/src/cursor-provider-turn-finalize.ts +12 -0
- package/src/cursor-provider-turn-lifecycle-emitter.ts +1 -1
- package/src/cursor-provider-turn-prepare.ts +1 -1
- package/src/cursor-provider-turn-types.ts +3 -1
- package/src/cursor-provider.ts +1 -1
- package/src/cursor-run-final-text.ts +1 -1
- package/src/cursor-sdk-billed-usage.ts +107 -0
- package/src/cursor-sdk-event-debug.ts +1 -1
- 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-agent.ts +1 -1
- package/src/cursor-session-compaction-prep.ts +4 -0
- package/src/cursor-session-send-policy.ts +1 -1
- package/src/cursor-tool-manifest.ts +1 -1
- package/src/cursor-usage-accounting.ts +71 -10
- package/src/index.ts +1 -1
- package/src/model-discovery.ts +32 -89
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +16 -0
- package/node_modules/cross-spawn/node_modules/which/CHANGELOG.md +0 -166
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseEnvBoolean } from "./cursor-env-boolean.js";
|
|
2
|
+
export const CURSOR_TOOL_MANIFEST_ENV = "PI_CURSOR_TOOL_MANIFEST";
|
|
3
|
+
/**
|
|
4
|
+
* Representative @cursor/sdk@1.0.27 local-agent ToolType values; actual exposure can vary by run.
|
|
5
|
+
* See docs/cursor-native-tool-replay.md#sdk-tooltype-replay-matrix.
|
|
6
|
+
*/
|
|
7
|
+
export const CURSOR_HOST_TOOL_MANIFEST_SUMMARY = "read/shell/search/edit/write and other host tools when Cursor exposes them";
|
|
8
|
+
export function resolveCursorToolManifestEnabled(env = process.env) {
|
|
9
|
+
return parseEnvBoolean(env[CURSOR_TOOL_MANIFEST_ENV], true);
|
|
10
|
+
}
|
|
11
|
+
export function buildCursorToolManifestText(options = {}) {
|
|
12
|
+
const piBridgeEnabled = options.piBridgeEnabled ?? true;
|
|
13
|
+
const includePiBridgeGuidance = options.includePiBridgeGuidance !== false;
|
|
14
|
+
const lines = [
|
|
15
|
+
"Callable tool surfaces this run:",
|
|
16
|
+
`- Cursor host/MCP: ${CURSOR_HOST_TOOL_MANIFEST_SUMMARY}; configured MCP depends on Cursor settings.`,
|
|
17
|
+
"- Pi tool toggles affect pi tools/bridge exposure only; they do not disable Cursor host/configured MCP tools.",
|
|
18
|
+
];
|
|
19
|
+
const bridgeTools = includePiBridgeGuidance ? options.bridgeSnapshot?.tools ?? [] : [];
|
|
20
|
+
if (includePiBridgeGuidance) {
|
|
21
|
+
if (!piBridgeEnabled) {
|
|
22
|
+
lines.push("- Pi bridge: disabled (PI_CURSOR_PI_TOOL_BRIDGE=0).");
|
|
23
|
+
}
|
|
24
|
+
else if (bridgeTools.length === 0) {
|
|
25
|
+
lines.push("- Pi bridge: no pi__* tools exposed this run.");
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const names = [...bridgeTools.map((tool) => tool.mcpToolName)].sort().join(", ");
|
|
29
|
+
lines.push(`- Pi bridge: call exposed pi__* MCP names (${names}); pi shows real pi names.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
lines.push("- Not callable: cursor-replay-* IDs, pi history names, transcript labels.");
|
|
33
|
+
return lines.join("\n");
|
|
34
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical Cursor tool presentation metadata.
|
|
3
|
+
* Names, labels, visibility, replay, lifecycle, web remapping, and alias normalization
|
|
4
|
+
* derive from this registry — do not duplicate tool lists in sibling modules.
|
|
5
|
+
*/
|
|
6
|
+
import { formatReplaySemSearchQuery, readCursorReplaySummaryString, summarizeReplayGenericActivity, summarizeReplayMcp, summarizeReplayPath, summarizeReplayPlan, summarizeReplayReadLints, summarizeReplayRecordScreen, summarizeReplayTask, summarizeReplayTodoCount, withActivitySummaryFallback, } from "./cursor-replay-summary-args.js";
|
|
7
|
+
import { truncateCursorDisplayLine } from "./cursor-display-text.js";
|
|
8
|
+
import { getCursorTaskActivityTitle } from "./cursor-task-presentation.js";
|
|
9
|
+
import { buildCreatePlanReplaySummaryArgs, buildDeleteReplayDetailFields, buildDeleteReplaySummaryArgs, buildGenerateImageReplayDetailFields, buildGenerateImageReplaySummaryArgs, buildMcpReplaySummaryArgs, buildReadLintsReplaySummaryArgs, buildRecordScreenReplaySummaryArgs, buildSemSearchReplaySummaryArgs, buildTaskReplaySummaryArgs, buildTodoReplaySummaryArgs, buildWebFetchReplaySummaryArgs, buildWebSearchReplaySummaryArgs, } from "./cursor-replay-activity-builders.js";
|
|
10
|
+
import { CURSOR_REPLAY_SOURCE_TOOL_NAMES } from "./cursor-replay-source-names.js";
|
|
11
|
+
export const CURSOR_REPLAY_ACTIVITY_TOOL_NAME = "cursor";
|
|
12
|
+
const EMPTY_REPLAY_DETAIL_FIELDS = () => ({});
|
|
13
|
+
const COLLAPSED_REPLAY_DETAIL_FIELDS = () => ({ collapseDetailsByDefault: true });
|
|
14
|
+
const WEB_SEARCH_NAME_PATTERN = /^(?:web[-_ ]?search|search[-_ ]?web|websearch|browser[-_ ]?search)$/i;
|
|
15
|
+
const WEB_FETCH_NAME_PATTERN = /^(?:web[-_ ]?fetch|fetch[-_ ]?web|webfetch|browser[-_ ]?fetch|fetch[-_ ]?url)$/i;
|
|
16
|
+
export const CURSOR_TOOL_PRESENTATION_SPECS = [
|
|
17
|
+
{
|
|
18
|
+
normalizedName: "read",
|
|
19
|
+
nameAliases: ["read_file"],
|
|
20
|
+
displayLabel: "read",
|
|
21
|
+
visibility: { incompleteTitle: "Cursor read", fastLocalDiscovery: true },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
normalizedName: "grep",
|
|
25
|
+
nameAliases: ["grep_search", "search"],
|
|
26
|
+
displayLabel: "grep",
|
|
27
|
+
visibility: { incompleteTitle: "Cursor grep", fastLocalDiscovery: true },
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
normalizedName: "glob",
|
|
31
|
+
nameAliases: ["file_search"],
|
|
32
|
+
displayLabel: "glob",
|
|
33
|
+
visibility: { incompleteTitle: "Cursor find", fastLocalDiscovery: true },
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
normalizedName: "ls",
|
|
37
|
+
nameAliases: ["list_dir"],
|
|
38
|
+
displayLabel: "ls",
|
|
39
|
+
visibility: { incompleteTitle: "Cursor ls", fastLocalDiscovery: true },
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
normalizedName: "shell",
|
|
43
|
+
nameAliases: ["run_terminal_cmd", "terminal", "bash"],
|
|
44
|
+
displayLabel: "shell",
|
|
45
|
+
visibility: {
|
|
46
|
+
incompleteTitle: "Cursor shell",
|
|
47
|
+
lifecycleTitle: "Cursor shell",
|
|
48
|
+
lifecycleEligible: true,
|
|
49
|
+
},
|
|
50
|
+
lifecycleLabelKind: "shell",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
normalizedName: "edit",
|
|
54
|
+
nameAliases: [
|
|
55
|
+
"strreplace",
|
|
56
|
+
"str_replace",
|
|
57
|
+
"str-replace",
|
|
58
|
+
"edit_file",
|
|
59
|
+
"editfile",
|
|
60
|
+
"edit_notebook",
|
|
61
|
+
"editnotebook",
|
|
62
|
+
"notebook_edit",
|
|
63
|
+
"notebookedit",
|
|
64
|
+
],
|
|
65
|
+
displayLabel: "Cursor edit",
|
|
66
|
+
visibility: {},
|
|
67
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayPath),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
normalizedName: "write",
|
|
71
|
+
nameAliases: ["write_file", "writefile"],
|
|
72
|
+
displayLabel: "Cursor write",
|
|
73
|
+
visibility: {},
|
|
74
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayPath),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
normalizedName: "delete",
|
|
78
|
+
displayLabel: "Cursor delete",
|
|
79
|
+
visibility: {},
|
|
80
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayPath),
|
|
81
|
+
activityReplay: {
|
|
82
|
+
buildActivityArgs: buildDeleteReplaySummaryArgs,
|
|
83
|
+
buildDetails: buildDeleteReplayDetailFields,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
normalizedName: "readLints",
|
|
88
|
+
displayLabel: "Cursor diagnostics",
|
|
89
|
+
visibility: {},
|
|
90
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayReadLints),
|
|
91
|
+
activityReplay: {
|
|
92
|
+
buildActivityArgs: buildReadLintsReplaySummaryArgs,
|
|
93
|
+
buildDetails: EMPTY_REPLAY_DETAIL_FIELDS,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
normalizedName: "updateTodos",
|
|
98
|
+
displayLabel: "Cursor todos",
|
|
99
|
+
visibility: { lifecycleEligible: true },
|
|
100
|
+
lifecycleLabelKind: "updateTodos",
|
|
101
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayTodoCount),
|
|
102
|
+
activityReplay: {
|
|
103
|
+
buildActivityArgs: ({ args, result }) => buildTodoReplaySummaryArgs(args, result),
|
|
104
|
+
buildDetails: EMPTY_REPLAY_DETAIL_FIELDS,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
normalizedName: "createPlan",
|
|
109
|
+
displayLabel: "Cursor plan",
|
|
110
|
+
visibility: { lifecycleEligible: true },
|
|
111
|
+
lifecycleLabelKind: "createPlan",
|
|
112
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayPlan),
|
|
113
|
+
activityReplay: {
|
|
114
|
+
buildActivityArgs: buildCreatePlanReplaySummaryArgs,
|
|
115
|
+
buildDetails: EMPTY_REPLAY_DETAIL_FIELDS,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
normalizedName: "task",
|
|
120
|
+
displayLabel: "Cursor subagent",
|
|
121
|
+
getActivityTitle: getCursorTaskActivityTitle,
|
|
122
|
+
visibility: { lifecycleEligible: true },
|
|
123
|
+
replayDisplay: { showCollapsedExpandHint: true },
|
|
124
|
+
lifecycleLabelKind: "task",
|
|
125
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayTask),
|
|
126
|
+
activityReplay: {
|
|
127
|
+
buildActivityArgs: buildTaskReplaySummaryArgs,
|
|
128
|
+
buildDetails: EMPTY_REPLAY_DETAIL_FIELDS,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
normalizedName: "generateImage",
|
|
133
|
+
displayLabel: "Cursor image generation",
|
|
134
|
+
visibility: { lifecycleEligible: true },
|
|
135
|
+
lifecycleLabelKind: "generateImage",
|
|
136
|
+
replayCallSummary: withActivitySummaryFallback((args) => readCursorReplaySummaryString(args, "path") ?? readCursorReplaySummaryString(args, "prompt")),
|
|
137
|
+
generateImageReplay: {
|
|
138
|
+
buildActivityArgs: buildGenerateImageReplaySummaryArgs,
|
|
139
|
+
buildDetails: buildGenerateImageReplayDetailFields,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
normalizedName: "mcp",
|
|
144
|
+
displayLabel: "Cursor MCP",
|
|
145
|
+
visibility: { lifecycleEligible: true },
|
|
146
|
+
lifecycleLabelKind: "mcp",
|
|
147
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayMcp),
|
|
148
|
+
activityReplay: {
|
|
149
|
+
buildActivityArgs: buildMcpReplaySummaryArgs,
|
|
150
|
+
buildDetails: EMPTY_REPLAY_DETAIL_FIELDS,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
normalizedName: "semSearch",
|
|
155
|
+
displayLabel: "Cursor semantic search",
|
|
156
|
+
visibility: { lifecycleEligible: true },
|
|
157
|
+
lifecycleLabelKind: "semSearch",
|
|
158
|
+
replayCallSummary: withActivitySummaryFallback(formatReplaySemSearchQuery),
|
|
159
|
+
activityReplay: {
|
|
160
|
+
buildActivityArgs: buildSemSearchReplaySummaryArgs,
|
|
161
|
+
buildDetails: EMPTY_REPLAY_DETAIL_FIELDS,
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
normalizedName: "recordScreen",
|
|
166
|
+
displayLabel: "Cursor screen recording",
|
|
167
|
+
visibility: { lifecycleEligible: true },
|
|
168
|
+
lifecycleLabelKind: "recordScreen",
|
|
169
|
+
replayCallSummary: withActivitySummaryFallback(summarizeReplayRecordScreen),
|
|
170
|
+
activityReplay: {
|
|
171
|
+
buildActivityArgs: buildRecordScreenReplaySummaryArgs,
|
|
172
|
+
buildDetails: EMPTY_REPLAY_DETAIL_FIELDS,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
normalizedName: "webSearch",
|
|
177
|
+
nameAliases: ["websearch", "web_search", "web-search"],
|
|
178
|
+
displayLabel: "Cursor web search",
|
|
179
|
+
visibility: { lifecycleEligible: true },
|
|
180
|
+
webKind: "webSearch",
|
|
181
|
+
webNamePatterns: [WEB_SEARCH_NAME_PATTERN],
|
|
182
|
+
lifecycleLabelKind: "webSearch",
|
|
183
|
+
replayCallSummary: withActivitySummaryFallback((args) => readCursorReplaySummaryString(args, "query")),
|
|
184
|
+
activityReplay: {
|
|
185
|
+
buildActivityArgs: buildWebSearchReplaySummaryArgs,
|
|
186
|
+
buildDetails: COLLAPSED_REPLAY_DETAIL_FIELDS,
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
normalizedName: "webFetch",
|
|
191
|
+
nameAliases: ["webfetch", "web_fetch", "web-fetch"],
|
|
192
|
+
displayLabel: "Cursor web fetch",
|
|
193
|
+
visibility: { lifecycleEligible: true },
|
|
194
|
+
webKind: "webFetch",
|
|
195
|
+
webNamePatterns: [WEB_FETCH_NAME_PATTERN],
|
|
196
|
+
lifecycleLabelKind: "webFetch",
|
|
197
|
+
replayCallSummary: withActivitySummaryFallback((args) => readCursorReplaySummaryString(args, "url")),
|
|
198
|
+
activityReplay: {
|
|
199
|
+
buildActivityArgs: buildWebFetchReplaySummaryArgs,
|
|
200
|
+
buildDetails: COLLAPSED_REPLAY_DETAIL_FIELDS,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
function hasNeutralActivityTitle(spec) {
|
|
205
|
+
return Boolean(spec.activityReplay || spec.generateImageReplay || spec.normalizedName === "edit" || spec.normalizedName === "write");
|
|
206
|
+
}
|
|
207
|
+
const SPECS_BY_NORMALIZED_NAME = new Map(CURSOR_TOOL_PRESENTATION_SPECS.map((spec) => [spec.normalizedName, spec]));
|
|
208
|
+
const SPECS_BY_NORMALIZED_KEY = new Map(CURSOR_TOOL_PRESENTATION_SPECS.map((spec) => [spec.normalizedName.toLowerCase(), spec]));
|
|
209
|
+
const ALIAS_TO_NORMALIZED_NAME = new Map(CURSOR_TOOL_PRESENTATION_SPECS.flatMap((spec) => {
|
|
210
|
+
const aliases = "nameAliases" in spec ? spec.nameAliases : undefined;
|
|
211
|
+
return (aliases ?? []).map((alias) => [alias.toLowerCase(), spec.normalizedName]);
|
|
212
|
+
}));
|
|
213
|
+
const WEB_KIND_BY_PATTERN = CURSOR_TOOL_PRESENTATION_SPECS.flatMap((spec) => {
|
|
214
|
+
if (!("webKind" in spec) || !("webNamePatterns" in spec))
|
|
215
|
+
return [];
|
|
216
|
+
const { webKind, webNamePatterns } = spec;
|
|
217
|
+
if (!webKind || !webNamePatterns)
|
|
218
|
+
return [];
|
|
219
|
+
return webNamePatterns.map((pattern) => ({ pattern, webKind }));
|
|
220
|
+
});
|
|
221
|
+
export const CURSOR_KNOWN_NORMALIZED_TOOL_NAMES = CURSOR_REPLAY_SOURCE_TOOL_NAMES;
|
|
222
|
+
export function getCursorToolPresentationSpec(name) {
|
|
223
|
+
const trimmed = name.trim();
|
|
224
|
+
if (!trimmed)
|
|
225
|
+
return undefined;
|
|
226
|
+
return SPECS_BY_NORMALIZED_NAME.get(trimmed) ?? SPECS_BY_NORMALIZED_KEY.get(trimmed.toLowerCase());
|
|
227
|
+
}
|
|
228
|
+
export function normalizeCursorToolName(name) {
|
|
229
|
+
const normalized = name.replace(/\s+/g, " ").trim();
|
|
230
|
+
if (!normalized)
|
|
231
|
+
return "unknown";
|
|
232
|
+
const aliasTarget = ALIAS_TO_NORMALIZED_NAME.get(normalized.toLowerCase());
|
|
233
|
+
if (aliasTarget)
|
|
234
|
+
return aliasTarget;
|
|
235
|
+
const spec = getCursorToolPresentationSpec(normalized);
|
|
236
|
+
if (spec)
|
|
237
|
+
return spec.normalizedName;
|
|
238
|
+
return normalized;
|
|
239
|
+
}
|
|
240
|
+
export function classifyCursorWebToolKind(name) {
|
|
241
|
+
if (!name)
|
|
242
|
+
return undefined;
|
|
243
|
+
const normalized = name.replace(/\s+/g, " ").trim().toLowerCase();
|
|
244
|
+
for (const { pattern, webKind } of WEB_KIND_BY_PATTERN) {
|
|
245
|
+
if (pattern.test(normalized))
|
|
246
|
+
return webKind;
|
|
247
|
+
}
|
|
248
|
+
const spec = getCursorToolPresentationSpec(name);
|
|
249
|
+
return spec?.webKind;
|
|
250
|
+
}
|
|
251
|
+
export function isCursorReplayToolName(toolName) {
|
|
252
|
+
return toolName === CURSOR_REPLAY_ACTIVITY_TOOL_NAME;
|
|
253
|
+
}
|
|
254
|
+
export function isExcludedFromCursorBridgeExposure(toolName) {
|
|
255
|
+
return toolName === CURSOR_REPLAY_ACTIVITY_TOOL_NAME;
|
|
256
|
+
}
|
|
257
|
+
export function getCursorReplayPromptLabel(toolName) {
|
|
258
|
+
return toolName === CURSOR_REPLAY_ACTIVITY_TOOL_NAME ? "Cursor activity" : toolName;
|
|
259
|
+
}
|
|
260
|
+
export function getCursorReplayActivityTitle(toolName) {
|
|
261
|
+
const spec = getCursorToolPresentationSpec(toolName);
|
|
262
|
+
if (!spec || !hasNeutralActivityTitle(spec))
|
|
263
|
+
return undefined;
|
|
264
|
+
return spec.getActivityTitle?.() ?? spec.displayLabel;
|
|
265
|
+
}
|
|
266
|
+
function buildCursorGenericActivityTitle(displayName) {
|
|
267
|
+
if (!displayName || displayName === "unknown")
|
|
268
|
+
return "Cursor tool";
|
|
269
|
+
return `Cursor ${truncateCursorDisplayLine(displayName, 120)}`;
|
|
270
|
+
}
|
|
271
|
+
/** Canonical activity title: registry label when known, otherwise neutral fallback. */
|
|
272
|
+
export function getCursorToolActivityTitle(toolName) {
|
|
273
|
+
const normalized = normalizeCursorToolName(toolName);
|
|
274
|
+
const known = getCursorReplayActivityTitle(normalized);
|
|
275
|
+
if (known)
|
|
276
|
+
return known;
|
|
277
|
+
const label = toolName.trim() || normalized;
|
|
278
|
+
return buildCursorGenericActivityTitle(label);
|
|
279
|
+
}
|
|
280
|
+
function getCursorToolPresentationSpecByNormalizedKey(normalizedKey) {
|
|
281
|
+
return SPECS_BY_NORMALIZED_KEY.get(normalizedKey.toLowerCase());
|
|
282
|
+
}
|
|
283
|
+
export function getCursorToolVisibilityPolicy(normalizedKey) {
|
|
284
|
+
return getCursorToolPresentationSpecByNormalizedKey(normalizedKey)?.visibility;
|
|
285
|
+
}
|
|
286
|
+
export function getCursorToolLifecycleLabelKind(normalizedKey) {
|
|
287
|
+
return getCursorToolPresentationSpecByNormalizedKey(normalizedKey)?.lifecycleLabelKind;
|
|
288
|
+
}
|
|
289
|
+
export function getCursorToolActivityReplaySpec(normalizedKey) {
|
|
290
|
+
return getCursorToolPresentationSpecByNormalizedKey(normalizedKey)?.activityReplay;
|
|
291
|
+
}
|
|
292
|
+
export function getCursorToolGenerateImageReplaySpec(normalizedKey) {
|
|
293
|
+
return getCursorToolPresentationSpecByNormalizedKey(normalizedKey)?.generateImageReplay;
|
|
294
|
+
}
|
|
295
|
+
export function shouldShowCursorReplayCollapsedExpandHint(normalizedKey) {
|
|
296
|
+
if (!normalizedKey)
|
|
297
|
+
return false;
|
|
298
|
+
return getCursorToolPresentationSpecByNormalizedKey(normalizedKey)?.replayDisplay?.showCollapsedExpandHint === true;
|
|
299
|
+
}
|
|
300
|
+
export function getCursorReplayCallSummary(toolName, args) {
|
|
301
|
+
if (toolName === CURSOR_REPLAY_ACTIVITY_TOOL_NAME) {
|
|
302
|
+
return readCursorReplaySummaryString(args, "activitySummary") ?? summarizeReplayGenericActivity(args);
|
|
303
|
+
}
|
|
304
|
+
return getCursorToolPresentationSpec(toolName)?.replayCallSummary?.(args);
|
|
305
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { asRecord, getArray, getNumber, getRecord, getString, stringifyUnknown } from "./cursor-record-utils.js";
|
|
2
|
+
import { summarizeCursorCompactConversationToolCall } from "./cursor-compact-tool-summary.js";
|
|
3
|
+
import { scrubSensitiveText } from "./cursor-sensitive-text.js";
|
|
4
|
+
import { firstNonEmptyLine, formatDisplayPath, truncateArg } from "./cursor-transcript-utils.js";
|
|
5
|
+
export function getReadLintPaths(args, result, options) {
|
|
6
|
+
const explicitPaths = Array.isArray(args.paths)
|
|
7
|
+
? args.paths.filter((entry) => typeof entry === "string")
|
|
8
|
+
: typeof args.path === "string"
|
|
9
|
+
? [args.path]
|
|
10
|
+
: [];
|
|
11
|
+
const resultPaths = (getArray(asRecord(result.value), "fileDiagnostics") ?? [])
|
|
12
|
+
.map((file) => getString(asRecord(file), "path"))
|
|
13
|
+
.filter((entry) => Boolean(entry));
|
|
14
|
+
return [...new Set([...explicitPaths, ...resultPaths].map((entry) => formatDisplayPath(entry, options.cwd)))];
|
|
15
|
+
}
|
|
16
|
+
export function getReadLintDiagnostics(result, options) {
|
|
17
|
+
const value = asRecord(result.value);
|
|
18
|
+
const files = getArray(value, "fileDiagnostics") ?? [];
|
|
19
|
+
const lines = [];
|
|
20
|
+
for (const file of files) {
|
|
21
|
+
const fileRecord = asRecord(file);
|
|
22
|
+
const pathValue = getString(fileRecord, "path");
|
|
23
|
+
const path = pathValue ? formatDisplayPath(pathValue, options.cwd) : "unknown";
|
|
24
|
+
const diagnostics = getArray(fileRecord, "diagnostics") ?? [];
|
|
25
|
+
for (const diagnostic of diagnostics) {
|
|
26
|
+
const diagnosticRecord = asRecord(diagnostic);
|
|
27
|
+
const severity = getString(diagnosticRecord, "severity") ?? "diagnostic";
|
|
28
|
+
const message = getString(diagnosticRecord, "message") ?? "";
|
|
29
|
+
const source = getString(diagnosticRecord, "source");
|
|
30
|
+
lines.push(`${path}: ${severity}${source ? ` ${source}` : ""}: ${message}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return lines;
|
|
34
|
+
}
|
|
35
|
+
export function getTodoItems(args, result) {
|
|
36
|
+
const value = asRecord(result.value);
|
|
37
|
+
const rawTodos = getArray(value, "todos") ?? getArray(args, "todos") ?? [];
|
|
38
|
+
const todos = [];
|
|
39
|
+
for (const todo of rawTodos) {
|
|
40
|
+
const record = asRecord(todo);
|
|
41
|
+
const content = getString(record, "content");
|
|
42
|
+
if (!content)
|
|
43
|
+
continue;
|
|
44
|
+
const status = getString(record, "status");
|
|
45
|
+
todos.push(status ? { content, status } : { content });
|
|
46
|
+
}
|
|
47
|
+
return todos;
|
|
48
|
+
}
|
|
49
|
+
export function getTodoTotalCount(args, result, todos) {
|
|
50
|
+
return getNumber(asRecord(result.value), "totalCount") ?? getNumber(args, "totalCount") ?? todos.length;
|
|
51
|
+
}
|
|
52
|
+
function getNestedRecord(record, ...keys) {
|
|
53
|
+
let current = record;
|
|
54
|
+
for (const key of keys) {
|
|
55
|
+
current = getRecord(current, key);
|
|
56
|
+
if (!current)
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return current;
|
|
60
|
+
}
|
|
61
|
+
function readConversationStepAssistantText(step) {
|
|
62
|
+
const record = asRecord(step);
|
|
63
|
+
const legacyText = getString(getRecord(record, "assistantMessage"), "text");
|
|
64
|
+
if (legacyText)
|
|
65
|
+
return legacyText;
|
|
66
|
+
if (getString(record, "type") !== "assistantMessage")
|
|
67
|
+
return undefined;
|
|
68
|
+
return getString(getRecord(record, "message"), "text");
|
|
69
|
+
}
|
|
70
|
+
export function collectTaskText(result, options = {}) {
|
|
71
|
+
const value = asRecord(result.value);
|
|
72
|
+
const success = getNestedRecord(value, "result", "success");
|
|
73
|
+
const command = getString(success, "command");
|
|
74
|
+
const stdout = getString(success, "stdout");
|
|
75
|
+
const interleavedOutput = getString(success, "interleavedOutput");
|
|
76
|
+
const conversationParts = (getArray(value, "conversationSteps") ?? [])
|
|
77
|
+
.map((step) => summarizeCursorCompactConversationToolCall(step, options) ?? readConversationStepAssistantText(step))
|
|
78
|
+
.filter((entry) => Boolean(entry));
|
|
79
|
+
const parts = [command ? `$ ${command}` : undefined, stdout || interleavedOutput, ...conversationParts].filter((part) => Boolean(part));
|
|
80
|
+
return parts.join("\n");
|
|
81
|
+
}
|
|
82
|
+
export function getGenerateImagePath(args, result) {
|
|
83
|
+
const value = asRecord(result.value);
|
|
84
|
+
return getString(value, "filePath") ?? getString(args, "filePath") ?? getString(args, "path");
|
|
85
|
+
}
|
|
86
|
+
export function getGenerateImageDisplayPath(args, result, options) {
|
|
87
|
+
const path = getGenerateImagePath(args, result);
|
|
88
|
+
return path ? formatDisplayPath(path, options.cwd) : undefined;
|
|
89
|
+
}
|
|
90
|
+
export function inferImageMimeType(path) {
|
|
91
|
+
const lower = path?.toLowerCase();
|
|
92
|
+
if (!lower)
|
|
93
|
+
return undefined;
|
|
94
|
+
if (lower.endsWith(".png"))
|
|
95
|
+
return "image/png";
|
|
96
|
+
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg"))
|
|
97
|
+
return "image/jpeg";
|
|
98
|
+
if (lower.endsWith(".gif"))
|
|
99
|
+
return "image/gif";
|
|
100
|
+
if (lower.endsWith(".webp"))
|
|
101
|
+
return "image/webp";
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
function getMcpContentText(entry) {
|
|
105
|
+
const record = asRecord(entry);
|
|
106
|
+
const directText = getString(record, "text");
|
|
107
|
+
if (directText)
|
|
108
|
+
return directText;
|
|
109
|
+
const nestedText = getRecord(record, "text");
|
|
110
|
+
return getString(nestedText, "text");
|
|
111
|
+
}
|
|
112
|
+
function describeNonTextMcpContent(entry) {
|
|
113
|
+
const record = asRecord(entry);
|
|
114
|
+
const type = getString(record, "type") ?? "content";
|
|
115
|
+
if (type === "image") {
|
|
116
|
+
const mimeType = getString(record, "mimeType") ?? getString(record, "mime") ?? getString(record, "mediaType");
|
|
117
|
+
return `[image${mimeType ? ` ${mimeType}` : ""} omitted]`;
|
|
118
|
+
}
|
|
119
|
+
if (type === "audio")
|
|
120
|
+
return "[audio omitted]";
|
|
121
|
+
if (type === "resource")
|
|
122
|
+
return "[resource omitted]";
|
|
123
|
+
return `[${type} omitted]`;
|
|
124
|
+
}
|
|
125
|
+
export function readMcpDisplayResult(result) {
|
|
126
|
+
if (result.status === "error") {
|
|
127
|
+
return { isToolError: false, text: "", nonTextSummary: "", body: "" };
|
|
128
|
+
}
|
|
129
|
+
const value = asRecord(result.value);
|
|
130
|
+
const isToolError = value?.isError === true;
|
|
131
|
+
const content = getArray(value, "content") ?? [];
|
|
132
|
+
const textParts = [];
|
|
133
|
+
const nonTextParts = [];
|
|
134
|
+
let preview;
|
|
135
|
+
for (const entry of content) {
|
|
136
|
+
const text = getMcpContentText(entry);
|
|
137
|
+
if (text) {
|
|
138
|
+
textParts.push(text);
|
|
139
|
+
const line = firstNonEmptyLine(text);
|
|
140
|
+
if (!preview && line)
|
|
141
|
+
preview = truncateArg(scrubSensitiveText(line), 120);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
nonTextParts.push(describeNonTextMcpContent(entry));
|
|
145
|
+
}
|
|
146
|
+
if (!preview)
|
|
147
|
+
preview = nonTextParts[0];
|
|
148
|
+
const text = textParts.join("\n");
|
|
149
|
+
const nonTextSummary = nonTextParts.join("\n");
|
|
150
|
+
const body = text || nonTextSummary || scrubSensitiveText(stringifyUnknown(result.value), undefined);
|
|
151
|
+
return {
|
|
152
|
+
isToolError,
|
|
153
|
+
text,
|
|
154
|
+
nonTextSummary,
|
|
155
|
+
body: `${isToolError ? "[tool error]\n" : ""}${body}`.trim(),
|
|
156
|
+
...(preview ? { preview } : {}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { asRecord, getString } from "./cursor-record-utils.js";
|
|
2
|
+
import { normalizeCursorToolName } from "./cursor-tool-presentation-registry.js";
|
|
3
|
+
import { buildCursorPiToolDisplayFromSpec, formatCursorToolTranscriptFromSpec, } from "./cursor-transcript-tool-specs.js";
|
|
4
|
+
import { getToolArgs, getToolName, getToolResult, normalizeResult, } from "./cursor-transcript-utils.js";
|
|
5
|
+
import { resolveTranscriptToolName } from "./cursor-web-tool-activity.js";
|
|
6
|
+
function buildToolDisplayContext(toolCall, options = {}) {
|
|
7
|
+
const rawName = getToolName(toolCall);
|
|
8
|
+
const args = getToolArgs(toolCall);
|
|
9
|
+
return {
|
|
10
|
+
rawName,
|
|
11
|
+
name: resolveTranscriptToolName(rawName, args),
|
|
12
|
+
args,
|
|
13
|
+
result: normalizeResult(getToolResult(toolCall)),
|
|
14
|
+
options,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function formatCursorToolTranscript(toolCall, options = {}) {
|
|
18
|
+
return formatCursorToolTranscriptFromSpec(buildToolDisplayContext(toolCall, options));
|
|
19
|
+
}
|
|
20
|
+
export function buildCursorPiToolDisplay(toolCall, options = {}) {
|
|
21
|
+
return buildCursorPiToolDisplayFromSpec(buildToolDisplayContext(toolCall, options));
|
|
22
|
+
}
|
|
23
|
+
export function getCursorCreatePlanText(toolCall) {
|
|
24
|
+
const name = normalizeCursorToolName(getToolName(toolCall));
|
|
25
|
+
if (name !== "createPlan")
|
|
26
|
+
return undefined;
|
|
27
|
+
const args = getToolArgs(toolCall);
|
|
28
|
+
const result = normalizeResult(getToolResult(toolCall));
|
|
29
|
+
const plan = getString(args, "plan") ?? getString(asRecord(result.value), "plan");
|
|
30
|
+
const trimmed = plan?.trim();
|
|
31
|
+
return trimmed || undefined;
|
|
32
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getCursorReplayActivityTitle, getCursorToolVisibilityPolicy, normalizeCursorToolName as normalizeToolName, } from "./cursor-tool-presentation-registry.js";
|
|
2
|
+
import { getToolArgs, getToolName } from "./cursor-transcript-utils.js";
|
|
3
|
+
import { resolveTranscriptToolName } from "./cursor-web-tool-activity.js";
|
|
4
|
+
export function getNormalizedCursorToolName(toolCall) {
|
|
5
|
+
return classifyCursorToolVisibility(toolCall).normalizedName;
|
|
6
|
+
}
|
|
7
|
+
export function classifyCursorToolVisibility(toolCall) {
|
|
8
|
+
const args = getToolArgs(toolCall);
|
|
9
|
+
const displayName = resolveTranscriptToolName(getToolName(toolCall), args);
|
|
10
|
+
const normalizedName = normalizeToolName(displayName);
|
|
11
|
+
const normalizedKey = normalizedName.toLowerCase();
|
|
12
|
+
const config = getCursorToolVisibilityPolicy(normalizedKey);
|
|
13
|
+
const replayActivityTitle = getCursorReplayActivityTitle(normalizedName);
|
|
14
|
+
return {
|
|
15
|
+
args,
|
|
16
|
+
displayName,
|
|
17
|
+
normalizedName,
|
|
18
|
+
normalizedKey,
|
|
19
|
+
activityTitle: replayActivityTitle ?? config?.incompleteTitle ?? config?.lifecycleTitle,
|
|
20
|
+
incompleteTitle: replayActivityTitle ?? config?.incompleteTitle,
|
|
21
|
+
lifecycleTitle: replayActivityTitle ?? config?.lifecycleTitle,
|
|
22
|
+
lifecycleEligible: config?.lifecycleEligible ?? false,
|
|
23
|
+
fastLocalDiscovery: config?.fastLocalDiscovery ?? false,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function isFastLocalDiscoveryTool(toolCall) {
|
|
27
|
+
return classifyCursorToolVisibility(toolCall).fastLocalDiscovery;
|
|
28
|
+
}
|