pi-cursor-sdk 0.1.19 → 0.1.21

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +72 -11
  3. package/docs/cursor-dogfood-checklist.md +57 -0
  4. package/docs/cursor-live-smoke-checklist.md +116 -10
  5. package/docs/cursor-model-ux-spec.md +60 -19
  6. package/docs/cursor-native-tool-replay.md +21 -11
  7. package/docs/cursor-native-tool-visual-audit.md +104 -59
  8. package/docs/cursor-testing-lessons.md +10 -5
  9. package/docs/cursor-tool-surfaces.md +69 -0
  10. package/package.json +37 -11
  11. package/scripts/debug-provider-events.d.mts +59 -0
  12. package/scripts/debug-provider-events.mjs +70 -175
  13. package/scripts/debug-sdk-events.d.mts +90 -0
  14. package/scripts/debug-sdk-events.mjs +36 -98
  15. package/scripts/fixtures/plan-strip-shim/index.ts +12 -0
  16. package/scripts/isolated-cursor-smoke.sh +264 -102
  17. package/scripts/lib/cursor-child-process.d.mts +10 -0
  18. package/scripts/lib/cursor-child-process.mjs +50 -0
  19. package/scripts/lib/cursor-cli-args.d.mts +63 -0
  20. package/scripts/lib/cursor-cli-args.mjs +129 -0
  21. package/scripts/lib/cursor-script-fail.d.mts +1 -0
  22. package/scripts/lib/cursor-script-fail.mjs +13 -0
  23. package/scripts/lib/cursor-sdk-output-filter.d.mts +5 -0
  24. package/scripts/lib/cursor-smoke-env.d.mts +38 -0
  25. package/scripts/lib/cursor-smoke-env.mjs +81 -0
  26. package/scripts/lib/cursor-smoke-shell.sh +174 -0
  27. package/scripts/lib/cursor-visual-render.d.mts +15 -0
  28. package/scripts/lib/cursor-visual-render.mjs +131 -0
  29. package/scripts/probe-mcp-coldstart.mjs +226 -0
  30. package/scripts/refresh-cursor-model-snapshots.mjs +29 -65
  31. package/scripts/steering-rpc-smoke.mjs +170 -65
  32. package/scripts/tmux-live-smoke.sh +152 -98
  33. package/scripts/visual-tui-smoke.mjs +659 -0
  34. package/shared/cursor-sdk-event-debug-env.d.mts +12 -0
  35. package/shared/cursor-sdk-event-debug-env.mjs +13 -0
  36. package/shared/cursor-sensitive-text.d.mts +1 -0
  37. package/{scripts/lib/cursor-probe-utils.mjs → shared/cursor-sensitive-text.mjs} +1 -13
  38. package/shared/cursor-setting-sources.d.mts +5 -0
  39. package/shared/cursor-setting-sources.mjs +22 -0
  40. package/src/context.ts +21 -12
  41. package/src/cursor-bridge-contract.ts +1 -3
  42. package/src/cursor-incomplete-tool-visibility.ts +72 -49
  43. package/src/cursor-mcp-timeout-override.ts +66 -11
  44. package/src/cursor-native-tool-display-registration.ts +63 -27
  45. package/src/cursor-native-tool-display-replay.ts +246 -143
  46. package/src/cursor-native-tool-display-state.ts +2 -0
  47. package/src/cursor-native-tool-display-tools.ts +149 -41
  48. package/src/cursor-provider-live-run-drain.ts +1 -52
  49. package/src/cursor-provider-run-finalizer.ts +235 -0
  50. package/src/cursor-provider-run-outcome.ts +149 -0
  51. package/src/cursor-provider-turn-api-key.ts +8 -0
  52. package/src/cursor-provider-turn-coordinator.ts +113 -440
  53. package/src/cursor-provider-turn-display-router.ts +216 -0
  54. package/src/cursor-provider-turn-emit.ts +59 -0
  55. package/src/cursor-provider-turn-finalize.ts +119 -0
  56. package/src/cursor-provider-turn-lifecycle-emitter.ts +97 -0
  57. package/src/cursor-provider-turn-message-offset.ts +15 -0
  58. package/src/cursor-provider-turn-prepare.ts +216 -0
  59. package/src/cursor-provider-turn-runner.ts +138 -0
  60. package/src/cursor-provider-turn-sdk-normalizer.ts +88 -0
  61. package/src/cursor-provider-turn-send.ts +103 -0
  62. package/src/cursor-provider-turn-shell-output.ts +107 -0
  63. package/src/cursor-provider-turn-tool-ledger.ts +126 -0
  64. package/src/cursor-provider-turn-types.ts +87 -0
  65. package/src/cursor-provider.ts +16 -482
  66. package/src/cursor-replay-activity-builders.ts +276 -0
  67. package/src/cursor-replay-source-names.ts +33 -0
  68. package/src/cursor-replay-summary-args.ts +191 -0
  69. package/src/cursor-replay-tool-details.ts +464 -0
  70. package/src/cursor-run-final-text.ts +56 -0
  71. package/src/cursor-sdk-abort-error-guard.ts +4 -0
  72. package/src/cursor-sdk-event-debug-constants.ts +14 -5
  73. package/src/cursor-sdk-event-debug.ts +8 -2
  74. package/src/cursor-sensitive-text.ts +3 -36
  75. package/src/cursor-session-agent.ts +265 -88
  76. package/src/cursor-setting-sources.ts +7 -10
  77. package/src/cursor-state.ts +232 -28
  78. package/src/cursor-tool-lifecycle.ts +17 -42
  79. package/src/cursor-tool-manifest.ts +41 -0
  80. package/src/cursor-tool-names.ts +18 -79
  81. package/src/cursor-tool-presentation-registry.ts +556 -0
  82. package/src/cursor-tool-transcript.ts +1 -1
  83. package/src/cursor-tool-visibility.ts +39 -0
  84. package/src/cursor-transcript-tool-formatters.ts +0 -59
  85. package/src/cursor-transcript-tool-specs.ts +169 -232
  86. package/src/cursor-transcript-utils.ts +0 -44
  87. package/src/cursor-web-tool-activity.ts +10 -60
  88. package/src/cursor-web-tool-args.ts +39 -0
  89. package/src/index.ts +4 -10
@@ -86,50 +86,6 @@ export function getToolResult(toolCall: unknown): unknown {
86
86
  return record?.result;
87
87
  }
88
88
 
89
- export function normalizeToolName(name: string): string {
90
- const normalized = name.replace(/\s+/g, " ").trim();
91
- const normalizedKey = normalized.toLowerCase();
92
- switch (normalizedKey) {
93
- case "read_file":
94
- return "read";
95
- case "list_dir":
96
- return "ls";
97
- case "run_terminal_cmd":
98
- case "terminal":
99
- case "bash":
100
- case "shell":
101
- return "shell";
102
- case "grep_search":
103
- case "search":
104
- return "grep";
105
- case "file_search":
106
- return "glob";
107
- case "write_file":
108
- case "writefile":
109
- return "write";
110
- case "strreplace":
111
- case "str_replace":
112
- case "str-replace":
113
- case "edit_file":
114
- case "editfile":
115
- case "edit_notebook":
116
- case "editnotebook":
117
- case "notebook_edit":
118
- case "notebookedit":
119
- return "edit";
120
- case "websearch":
121
- case "web_search":
122
- case "web-search":
123
- return "webSearch";
124
- case "webfetch":
125
- case "web_fetch":
126
- case "web-fetch":
127
- return "webFetch";
128
- default:
129
- return normalized || "unknown";
130
- }
131
- }
132
-
133
89
  export function normalizeResult(result: unknown): NormalizedResult {
134
90
  const record = asRecord(result);
135
91
  const status = getString(record, "status");
@@ -1,32 +1,12 @@
1
- import { normalizeToolName } from "./cursor-transcript-utils.js";
1
+ import {
2
+ classifyCursorWebToolKind as classifyCursorWebToolKindFromRegistry,
3
+ type CursorWebToolKind,
4
+ } from "./cursor-tool-presentation-registry.js";
5
+ import { normalizeCursorToolName as normalizeToolName } from "./cursor-tool-presentation-registry.js";
6
+ import { extractWebFetchTarget, extractWebSearchQuery } from "./cursor-web-tool-args.js";
2
7
 
3
- export type CursorWebToolKind = "webSearch" | "webFetch";
4
-
5
- const WEB_SEARCH_NAME_PATTERN =
6
- /^(?:web[-_ ]?search|search[-_ ]?web|websearch|browser[-_ ]?search|cursor[-_ ]?web[-_ ]?search)$/i;
7
- const WEB_FETCH_NAME_PATTERN =
8
- /^(?:web[-_ ]?fetch|fetch[-_ ]?web|webfetch|browser[-_ ]?fetch|fetch[-_ ]?url|cursor[-_ ]?web[-_ ]?fetch)$/i;
9
-
10
- function normalizeWebToolLookupName(name: string): string {
11
- return name.replace(/\s+/g, " ").trim().toLowerCase();
12
- }
13
-
14
- export function classifyCursorWebToolKind(name: string | undefined): CursorWebToolKind | undefined {
15
- if (!name) return undefined;
16
- const normalized = normalizeWebToolLookupName(name);
17
- if (WEB_SEARCH_NAME_PATTERN.test(normalized) || normalized === "websearch" || normalized === "web_search") {
18
- return "webSearch";
19
- }
20
- if (WEB_FETCH_NAME_PATTERN.test(normalized) || normalized === "webfetch" || normalized === "web_fetch") {
21
- return "webFetch";
22
- }
23
- return undefined;
24
- }
25
-
26
- function getNestedMcpArgs(args: Record<string, unknown>): Record<string, unknown> {
27
- const nested = args.args;
28
- return nested && typeof nested === "object" && !Array.isArray(nested) ? (nested as Record<string, unknown>) : {};
29
- }
8
+ export type { CursorWebToolKind } from "./cursor-tool-presentation-registry.js";
9
+ export { extractWebFetchTarget, extractWebSearchQuery } from "./cursor-web-tool-args.js";
30
10
 
31
11
  function getMcpToolName(args: Record<string, unknown>): string | undefined {
32
12
  const toolName = typeof args.toolName === "string" ? args.toolName : typeof args.tool_name === "string" ? args.tool_name : undefined;
@@ -34,38 +14,8 @@ function getMcpToolName(args: Record<string, unknown>): string | undefined {
34
14
  return trimmed || undefined;
35
15
  }
36
16
 
37
- function firstNonEmptyString(...values: Array<string | undefined>): string | undefined {
38
- for (const value of values) {
39
- const trimmed = value?.trim();
40
- if (trimmed) return trimmed;
41
- }
42
- return undefined;
43
- }
44
-
45
- export function extractWebSearchQuery(args: Record<string, unknown>): string | undefined {
46
- const nested = getNestedMcpArgs(args);
47
- return firstNonEmptyString(
48
- typeof args.search_term === "string" ? args.search_term : undefined,
49
- typeof args.searchTerm === "string" ? args.searchTerm : undefined,
50
- typeof args.query === "string" ? args.query : undefined,
51
- typeof args.q === "string" ? args.q : undefined,
52
- typeof nested.search_term === "string" ? nested.search_term : undefined,
53
- typeof nested.searchTerm === "string" ? nested.searchTerm : undefined,
54
- typeof nested.query === "string" ? nested.query : undefined,
55
- typeof nested.q === "string" ? nested.q : undefined,
56
- );
57
- }
58
-
59
- export function extractWebFetchTarget(args: Record<string, unknown>): string | undefined {
60
- const nested = getNestedMcpArgs(args);
61
- return firstNonEmptyString(
62
- typeof args.url === "string" ? args.url : undefined,
63
- typeof args.uri === "string" ? args.uri : undefined,
64
- typeof args.href === "string" ? args.href : undefined,
65
- typeof nested.url === "string" ? nested.url : undefined,
66
- typeof nested.uri === "string" ? nested.uri : undefined,
67
- typeof nested.href === "string" ? nested.href : undefined,
68
- );
17
+ export function classifyCursorWebToolKind(name: string | undefined): CursorWebToolKind | undefined {
18
+ return classifyCursorWebToolKindFromRegistry(name);
69
19
  }
70
20
 
71
21
  /**
@@ -0,0 +1,39 @@
1
+ import { asRecord } from "./cursor-record-utils.js";
2
+
3
+ function getNestedMcpArgs(args: Record<string, unknown>): Record<string, unknown> {
4
+ return asRecord(args.args) ?? {};
5
+ }
6
+
7
+ function firstNonEmptyString(...values: Array<string | undefined>): string | undefined {
8
+ for (const value of values) {
9
+ const trimmed = value?.trim();
10
+ if (trimmed) return trimmed;
11
+ }
12
+ return undefined;
13
+ }
14
+
15
+ export function extractWebSearchQuery(args: Record<string, unknown>): string | undefined {
16
+ const nested = getNestedMcpArgs(args);
17
+ return firstNonEmptyString(
18
+ typeof args.search_term === "string" ? args.search_term : undefined,
19
+ typeof args.searchTerm === "string" ? args.searchTerm : undefined,
20
+ typeof args.query === "string" ? args.query : undefined,
21
+ typeof args.q === "string" ? args.q : undefined,
22
+ typeof nested.search_term === "string" ? nested.search_term : undefined,
23
+ typeof nested.searchTerm === "string" ? nested.searchTerm : undefined,
24
+ typeof nested.query === "string" ? nested.query : undefined,
25
+ typeof nested.q === "string" ? nested.q : undefined,
26
+ );
27
+ }
28
+
29
+ export function extractWebFetchTarget(args: Record<string, unknown>): string | undefined {
30
+ const nested = getNestedMcpArgs(args);
31
+ return firstNonEmptyString(
32
+ typeof args.url === "string" ? args.url : undefined,
33
+ typeof args.uri === "string" ? args.uri : undefined,
34
+ typeof args.href === "string" ? args.href : undefined,
35
+ typeof nested.url === "string" ? nested.url : undefined,
36
+ typeof nested.uri === "string" ? nested.uri : undefined,
37
+ typeof nested.href === "string" ? nested.href : undefined,
38
+ );
39
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ExtensionAPI, ExtensionContext, ProviderConfig, ProviderModelConfig } from "@earendil-works/pi-coding-agent";
2
2
  import { discoverModels, type CursorModelFallbackIssue } from "./model-discovery.js";
3
- import { registerCursorFastControls } from "./cursor-state.js";
3
+ import { registerCursorRuntimeControls } from "./cursor-state.js";
4
4
  import { registerCursorNativeToolDisplay } from "./cursor-native-tool-display.js";
5
5
  import { registerCursorPiToolBridge } from "./cursor-pi-tool-bridge.js";
6
6
  import { registerCursorQuestionTool } from "./cursor-question-tool.js";
@@ -10,16 +10,10 @@ import { registerCursorSessionAgent } from "./cursor-session-agent.js";
10
10
  import { streamCursor } from "./cursor-provider.js";
11
11
 
12
12
  type CursorExtensionApi =
13
- & Pick<ExtensionAPI, "registerProvider">
14
- & {
15
- registerCommand(name: string, options: {
16
- description?: string;
17
- handler: (args: string, ctx: Pick<ExtensionContext, "hasUI"> & { ui: Pick<ExtensionContext["ui"], "notify"> }) => Promise<void> | void;
18
- }): void;
19
- }
13
+ & Pick<ExtensionAPI, "registerProvider" | "registerCommand">
20
14
  & Parameters<typeof registerCursorSessionCwd>[0]
21
15
  & Parameters<typeof registerCursorSessionAgent>[0]
22
- & Parameters<typeof registerCursorFastControls>[0]
16
+ & Parameters<typeof registerCursorRuntimeControls>[0]
23
17
  & Parameters<typeof registerCursorNativeToolDisplay>[0]
24
18
  & Parameters<typeof registerCursorQuestionTool>[0]
25
19
  & Parameters<typeof registerCursorPiToolBridge>[0]
@@ -44,7 +38,7 @@ export default async function (pi: CursorExtensionApi) {
44
38
  // Session cwd must register before other session_start listeners that depend on it.
45
39
  registerCursorSessionCwd(pi);
46
40
  registerCursorSessionAgent(pi);
47
- registerCursorFastControls(pi);
41
+ registerCursorRuntimeControls(pi);
48
42
  registerCursorNativeToolDisplay(pi);
49
43
  registerCursorQuestionTool(pi);
50
44
  registerCursorPiToolBridge(pi);