pi-cursor-sdk 0.5.2 → 0.5.4

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 (114) hide show
  1. package/CHANGELOG.md +66 -1
  2. package/README.md +62 -795
  3. package/dist/context.js +13 -7
  4. package/dist/cursor-agents-context.js +6 -6
  5. package/dist/cursor-api-key.js +1 -1
  6. package/dist/cursor-bridge-contract.js +1 -13
  7. package/dist/cursor-cloud-local-state.js +0 -1
  8. package/dist/cursor-config.js +1 -17
  9. package/dist/cursor-custom-subagent-definitions.js +1 -1
  10. package/dist/cursor-fallback-models.generated.js +665 -1
  11. package/dist/cursor-live-run-coordinator.js +1 -0
  12. package/dist/cursor-local-agent-ownership.js +17 -0
  13. package/dist/cursor-mcp-timeout-override.js +7 -18
  14. package/dist/cursor-native-tool-display-replay.js +5 -5
  15. package/dist/cursor-native-tools.js +11 -0
  16. package/dist/cursor-pi-tool-bridge-diagnostics.js +4 -0
  17. package/dist/cursor-pi-tool-bridge-env.js +25 -2
  18. package/dist/cursor-pi-tool-bridge-run.js +10 -3
  19. package/dist/cursor-pi-tool-bridge-server.js +98 -48
  20. package/dist/cursor-pi-tool-bridge-snapshot.js +1 -1
  21. package/dist/cursor-pi-tool-bridge.js +4 -12
  22. package/dist/cursor-provider-errors.js +2 -8
  23. package/dist/cursor-provider-live-run-drain.js +8 -3
  24. package/dist/cursor-provider-overflow.js +7 -21
  25. package/dist/cursor-provider-turn-prepare.js +8 -1
  26. package/dist/cursor-provider-turn-runner.js +17 -6
  27. package/dist/cursor-provider-turn-summary.js +1 -1
  28. package/dist/cursor-provider.js +1 -4
  29. package/dist/cursor-runtime-state.js +3 -3
  30. package/dist/cursor-sdk-event-debug.js +2 -2
  31. package/dist/cursor-sdk-output-filter.js +1 -1
  32. package/dist/cursor-sdk-process-error-guard.js +1 -2
  33. package/dist/cursor-session-agent-cleanup.js +10 -1
  34. package/dist/cursor-session-agent-lifecycle.js +2 -2
  35. package/dist/cursor-session-agent-lineage.js +11 -7
  36. package/dist/cursor-session-agent-resume.js +15 -9
  37. package/dist/cursor-session-agent.js +28 -15
  38. package/dist/cursor-session-scope.js +28 -21
  39. package/dist/cursor-session-settings.js +3 -3
  40. package/dist/cursor-session-store.js +2 -2
  41. package/dist/cursor-state.js +26 -29
  42. package/dist/cursor-tool-lifecycle.js +0 -3
  43. package/dist/cursor-tool-manifest.js +3 -1
  44. package/dist/cursor-tool-presentation-registry.js +2 -4
  45. package/dist/cursor-tool-visibility.js +0 -3
  46. package/dist/cursor-transcript-tool-specs.js +1 -2
  47. package/dist/index.js +21 -0
  48. package/dist/model-discovery.js +8 -10
  49. package/dist/model-list-cache.js +4 -9
  50. package/docs/cursor-live-smoke-checklist.md +4 -4
  51. package/docs/cursor-model-ux-spec.md +36 -19
  52. package/docs/cursor-native-tool-replay.md +8 -5
  53. package/docs/cursor-native-tool-visual-audit.md +1 -1
  54. package/docs/cursor-testing-lessons.md +39 -9
  55. package/docs/cursor-tool-surfaces.md +48 -4
  56. package/docs/development.md +93 -0
  57. package/docs/platform-smoke-implementation.md +3 -2
  58. package/docs/reference.md +806 -0
  59. package/package.json +13 -11
  60. package/scripts/platform-smoke/artifact-secrets.mjs +13 -4
  61. package/scripts/platform-smoke/local-resume-runner.mjs +0 -1
  62. package/scripts/platform-smoke/target-runtime.mjs +4 -2
  63. package/scripts/platform-smoke/targets.mjs +0 -1
  64. package/shared/cursor-sdk-output-filter.d.mts +2 -0
  65. package/shared/cursor-sdk-output-filter.mjs +92 -28
  66. package/shared/cursor-sensitive-text.d.mts +1 -0
  67. package/shared/cursor-sensitive-text.mjs +7 -0
  68. package/src/context.ts +18 -11
  69. package/src/cursor-agents-context.ts +6 -6
  70. package/src/cursor-api-key.ts +1 -1
  71. package/src/cursor-bridge-contract.ts +1 -15
  72. package/src/cursor-cloud-local-state.ts +0 -2
  73. package/src/cursor-config.ts +1 -24
  74. package/src/cursor-custom-subagent-definitions.ts +1 -1
  75. package/src/cursor-fallback-models.generated.ts +665 -1
  76. package/src/cursor-live-run-coordinator.ts +5 -0
  77. package/src/cursor-local-agent-ownership.ts +18 -0
  78. package/src/cursor-mcp-timeout-override.ts +7 -31
  79. package/src/cursor-native-tool-display-replay.ts +4 -6
  80. package/src/cursor-native-tools.ts +14 -0
  81. package/src/cursor-pi-tool-bridge-diagnostics.ts +17 -0
  82. package/src/cursor-pi-tool-bridge-env.ts +31 -2
  83. package/src/cursor-pi-tool-bridge-run.ts +10 -3
  84. package/src/cursor-pi-tool-bridge-server.ts +89 -45
  85. package/src/cursor-pi-tool-bridge-snapshot.ts +0 -1
  86. package/src/cursor-pi-tool-bridge.ts +2 -18
  87. package/src/cursor-provider-errors.ts +2 -10
  88. package/src/cursor-provider-live-run-drain.ts +8 -2
  89. package/src/cursor-provider-overflow.ts +6 -24
  90. package/src/cursor-provider-turn-prepare.ts +10 -1
  91. package/src/cursor-provider-turn-runner.ts +17 -6
  92. package/src/cursor-provider-turn-summary.ts +1 -1
  93. package/src/cursor-provider.ts +0 -5
  94. package/src/cursor-runtime-state.ts +3 -3
  95. package/src/cursor-sdk-event-debug.ts +2 -2
  96. package/src/cursor-sdk-output-filter.ts +2 -1
  97. package/src/cursor-sdk-process-error-guard.ts +1 -3
  98. package/src/cursor-session-agent-cleanup.ts +6 -1
  99. package/src/cursor-session-agent-lifecycle.ts +2 -2
  100. package/src/cursor-session-agent-lineage.ts +10 -5
  101. package/src/cursor-session-agent-resume.ts +14 -7
  102. package/src/cursor-session-agent.ts +31 -15
  103. package/src/cursor-session-scope.ts +34 -20
  104. package/src/cursor-session-settings.ts +3 -3
  105. package/src/cursor-session-store.ts +2 -2
  106. package/src/cursor-state.ts +34 -41
  107. package/src/cursor-tool-lifecycle.ts +0 -4
  108. package/src/cursor-tool-manifest.ts +4 -1
  109. package/src/cursor-tool-presentation-registry.ts +3 -5
  110. package/src/cursor-tool-visibility.ts +0 -4
  111. package/src/cursor-transcript-tool-specs.ts +0 -3
  112. package/src/index.ts +18 -0
  113. package/src/model-discovery.ts +7 -9
  114. package/src/model-list-cache.ts +4 -10
package/dist/context.js CHANGED
@@ -11,7 +11,9 @@ export function getCursorPlanModeToolGuidanceText(agentMode, options = {}) {
11
11
  return undefined;
12
12
  return [
13
13
  "Cursor SDK mode is plan for this run. In pi-cursor-sdk, plan mode may still use available Cursor SDK/MCP tools for inspection when needed.",
14
- "Safe/read-only shell commands that inspect or print information are allowed when Cursor chooses to call Shell; do not say Shell is blocked by plan mode and then call it anyway.",
14
+ options.nativeToolsEnabled === false
15
+ ? "Only MCP tools exposed in this run are callable; native Shell and task/subagents are disabled."
16
+ : "Safe/read-only shell commands that inspect or print information are allowed when Cursor chooses to call Shell; do not say Shell is blocked by plan mode and then call it anyway.",
15
17
  options.includePiBridgeGuidance === false
16
18
  ? undefined
17
19
  : "Exposed pi__* bridge tools are also callable in plan mode when the user asks for them or they are needed to answer.",
@@ -19,14 +21,16 @@ export function getCursorPlanModeToolGuidanceText(agentMode, options = {}) {
19
21
  }
20
22
  export function getCursorToolTailGuardText(options = {}) {
21
23
  return [
22
- "Shell: use explicit `cd` to repo path for project commands; session cwd may differ from tool args.",
24
+ options.nativeToolsEnabled === false ? undefined : "Shell: use explicit `cd` to repo path for project commands; session cwd may differ from tool args.",
23
25
  options.includePlanModeGuidance === false
24
26
  ? undefined
25
- : getCursorPlanModeToolGuidanceText(options.agentMode, { includePiBridgeGuidance: options.includePiBridgeGuidance }),
27
+ : getCursorPlanModeToolGuidanceText(options.agentMode, { includePiBridgeGuidance: options.includePiBridgeGuidance, nativeToolsEnabled: options.nativeToolsEnabled }),
26
28
  "Exact-output requests: output exactly the requested text; no preamble or checks unless asked.",
27
29
  "Tools: call available Cursor SDK/MCP tools; never print tool cards as assistant text.",
28
30
  "Do not comment on GitHub issues or PRs unless the user asked.",
29
- options.includePiBridgeGuidance === false ? undefined : CURSOR_PI_BRIDGE_PREFERENCE_TEXT,
31
+ options.includePiBridgeGuidance === false ? undefined : options.nativeToolsEnabled === false
32
+ ? "Use only exposed pi__* MCP names for Pi work; native task/subagents are disabled."
33
+ : CURSOR_PI_BRIDGE_PREFERENCE_TEXT,
30
34
  ].filter((line) => line !== undefined).join("\n");
31
35
  }
32
36
  function getCursorToolBoundaryText(options = {}) {
@@ -35,12 +39,13 @@ function getCursorToolBoundaryText(options = {}) {
35
39
  const lines = [
36
40
  "Cursor SDK tool boundary:",
37
41
  "Call only Cursor SDK/MCP tools exposed in this run; pi history names, replay labels, and transcript names are not callable.",
42
+ options.nativeToolsEnabled === false ? "Cursor native tools (including task/subagents): disabled. Only exposed MCP tools are callable." : undefined,
38
43
  includePiBridgeGuidance
39
44
  ? "For exposed pi bridge tools, call pi__* MCP names, not pi card/history names."
40
45
  : undefined,
41
46
  "Do not claim pi-side or WebSearch/WebFetch tools unless Cursor ran an equivalent tool.",
42
47
  includePiAskQuestionGuidance ? "Use pi__cursor_ask_question only if the user asked to be prompted." : undefined,
43
- getCursorPlanModeToolGuidanceText(options.agentMode, { includePiBridgeGuidance }),
48
+ getCursorPlanModeToolGuidanceText(options.agentMode, { includePiBridgeGuidance, nativeToolsEnabled: options.nativeToolsEnabled }),
44
49
  "Images: only latest user images are sent; ask to reattach prior images.",
45
50
  ].filter((line) => line !== undefined);
46
51
  if (options.hasToolManifest) {
@@ -90,7 +95,7 @@ function formatContentBlocks(content) {
90
95
  }
91
96
  function formatToolCall(toolCall) {
92
97
  const args = JSON.stringify(toolCall.arguments) ?? "";
93
- return `Tool call (${getCursorReplayPromptLabel(toolCall.name)}, call ${toolCall.id}): ${args}`;
98
+ return `Historical tool request (${getCursorReplayPromptLabel(toolCall.name)}, call ${toolCall.id}): ${args}`;
94
99
  }
95
100
  function sanitizeSystemPromptForCursor(systemPrompt) {
96
101
  let sanitized = systemPrompt;
@@ -126,7 +131,7 @@ function formatMessage(msg) {
126
131
  }
127
132
  case "toolResult": {
128
133
  const text = formatContentBlocks(msg.content);
129
- const label = msg.isError ? "Tool error" : "Tool result";
134
+ const label = msg.isError ? "Historical tool error" : "Historical tool result";
130
135
  return `${label} (${getCursorReplayPromptLabel(msg.toolName)}, call ${msg.toolCallId}): ${text}`;
131
136
  }
132
137
  }
@@ -354,6 +359,7 @@ export function buildCursorPrompt(context, options = {}) {
354
359
  agentMode: options.agentMode,
355
360
  hasToolManifest: Boolean(options.toolManifest),
356
361
  includePiBridgeGuidance: options.includePiBridgeGuidance,
362
+ nativeToolsEnabled: options.nativeToolsEnabled,
357
363
  includePiAskQuestionGuidance: options.includePiAskQuestionGuidance,
358
364
  })];
359
365
  if (options.toolManifest) {
@@ -17,7 +17,7 @@ function normalizeDirPath(dirPath) {
17
17
  }
18
18
  /** Pi context filenames that can overlap Cursor project/user ambient rules. */
19
19
  const CURSOR_OVERLAPPING_CONTEXT_BASE_NAMES = new Set(["agents.md", "claude.md"]);
20
- export function getAgentsContextFileBaseName(filePath) {
20
+ function getAgentsContextFileBaseName(filePath) {
21
21
  const normalized = normalizeContextPath(filePath);
22
22
  return normalized.slice(normalized.lastIndexOf("/") + 1).toLowerCase();
23
23
  }
@@ -27,11 +27,11 @@ function isPiAgentDirContextFilePath(filePath, fileName, agentDir = getAgentDir(
27
27
  return normalized.toLowerCase() === expectedPath.toLowerCase();
28
28
  }
29
29
  /** Actual pi agent dir `AGENTS.md` — overlaps Cursor `user` setting source (global agent instructions). */
30
- export function isPiAgentDirAgentsMdPath(filePath, agentDir = getAgentDir()) {
30
+ function isPiAgentDirAgentsMdPath(filePath, agentDir = getAgentDir()) {
31
31
  return isPiAgentDirContextFilePath(filePath, "agents.md", agentDir);
32
32
  }
33
33
  /** Actual pi agent dir `CLAUDE.md` — kept because Cursor user rules use `~/.claude/CLAUDE.md`. */
34
- export function isPiAgentDirClaudeMdPath(filePath, agentDir = getAgentDir()) {
34
+ function isPiAgentDirClaudeMdPath(filePath, agentDir = getAgentDir()) {
35
35
  return isPiAgentDirContextFilePath(filePath, "claude.md", agentDir);
36
36
  }
37
37
  /**
@@ -40,7 +40,7 @@ export function isPiAgentDirClaudeMdPath(filePath, agentDir = getAgentDir()) {
40
40
  * Only the actual pi agent dir `AGENTS.md` overlaps Cursor `user`; agent-dir `CLAUDE.md` is kept
41
41
  * because Cursor user rules use `~/.claude/CLAUDE.md`, not pi's agent dir path.
42
42
  */
43
- export function classifyContextFileOverlap(filePath, agentDir = getAgentDir()) {
43
+ function classifyContextFileOverlap(filePath, agentDir = getAgentDir()) {
44
44
  const base = getAgentsContextFileBaseName(filePath);
45
45
  if (!CURSOR_OVERLAPPING_CONTEXT_BASE_NAMES.has(base))
46
46
  return "none";
@@ -50,7 +50,7 @@ export function classifyContextFileOverlap(filePath, agentDir = getAgentDir()) {
50
50
  return "none";
51
51
  return "cursor-project-rules";
52
52
  }
53
- export function shouldRemovePiAgentsContextFile(file, settingSources, agentDir) {
53
+ function shouldRemovePiAgentsContextFile(file, settingSources, agentDir) {
54
54
  switch (classifyContextFileOverlap(file.path, agentDir)) {
55
55
  case "cursor-user-agents":
56
56
  return cursorSettingSourcesIncludes(settingSources, "user");
@@ -60,7 +60,7 @@ export function shouldRemovePiAgentsContextFile(file, settingSources, agentDir)
60
60
  return false;
61
61
  }
62
62
  }
63
- export function shouldSuppressPiAgentsContext(model, contextFiles, settingSources, agentDir) {
63
+ function shouldSuppressPiAgentsContext(model, contextFiles, settingSources, agentDir) {
64
64
  if (!isCursorModel(model))
65
65
  return false;
66
66
  if (parseEnvBoolean(process.env[CURSOR_PRESERVE_PI_AGENTS_MD_ENV], false))
@@ -2,7 +2,7 @@ import { envApiKeyAuth } from "@earendil-works/pi-ai";
2
2
  import { parseEnvBoolean } from "./cursor-env-boolean.js";
3
3
  export const CURSOR_API_KEY_ENV_VAR = "CURSOR_API_KEY";
4
4
  // Legacy no-auth availability policy only; never a configured models.json key.
5
- export const CURSOR_API_KEY_CONFIG_VALUE = "pi-cursor-sdk-cursor-api-key-placeholder";
5
+ const CURSOR_API_KEY_CONFIG_VALUE = "pi-cursor-sdk-cursor-api-key-placeholder";
6
6
  const CURSOR_API_KEY_PLACEHOLDERS = new Set([
7
7
  CURSOR_API_KEY_ENV_VAR,
8
8
  `$${CURSOR_API_KEY_ENV_VAR}`,
@@ -1,17 +1,5 @@
1
1
  export const CURSOR_PI_BRIDGE_MCP_TOOL_PREFIX = "pi__";
2
- export const CURSOR_PI_BRIDGE_PREFERENCE_TEXT = "When exposed, prefer pi__mcp for MCP work and pi__subagent for delegation; use Cursor-configured MCP or Cursor-native subagents only when the matching pi__ tool is not exposed or unavailable.";
3
- const CURSOR_PI_BRIDGE_CONTRACT_LINES = [
4
- "Pi bridge contract:",
5
- `${CURSOR_PI_BRIDGE_MCP_TOOL_PREFIX}* names are live Cursor MCP bridge tool names only when exposed in the current run.`,
6
- `Call the ${CURSOR_PI_BRIDGE_MCP_TOOL_PREFIX}* MCP tool name, not the real pi tool name shown in pi history or transcripts.`,
7
- CURSOR_PI_BRIDGE_PREFERENCE_TEXT,
8
- "Bridged calls execute through normal pi tool flow, so pi shows the real pi tool name and returns a normal pi tool result.",
9
- "Replay IDs, replay labels, and transcript tool names are display-only/context-only, not callable tools.",
10
- "Cursor-native host tools, settings, plugins, and configured MCP servers are separate from the pi bridge.",
11
- ];
12
- export function getCursorPiBridgeContractText() {
13
- return CURSOR_PI_BRIDGE_CONTRACT_LINES.join("\n");
14
- }
2
+ export const CURSOR_PI_BRIDGE_PREFERENCE_TEXT = "For MCP work and delegation, prefer matching exposed pi__* tools using their listed names, schemas, and prompt guidelines; use Cursor-configured MCP or Cursor-native subagents only when the matching pi tool is not exposed or unavailable.";
15
3
  function formatPromptGuidelines(promptGuidelines) {
16
4
  const guidelines = promptGuidelines?.map((guideline) => guideline.trim()).filter(Boolean) ?? [];
17
5
  if (guidelines.length === 0)
@@ -457,4 +457,3 @@ export function inspectCursorCloudLocalState(cwd, target = {}, runGit = runCurso
457
457
  }
458
458
  return { insideGitRepo: true, dirty: dirty, comparison: aheadCount > 0 ? "unpushed" : "contains_head" };
459
459
  }
460
- export const __testUtils = { sourceForDestination };
@@ -231,7 +231,7 @@ function readCursorSdkConfigFile(path) {
231
231
  return {};
232
232
  }
233
233
  }
234
- export function loadCursorSdkConfigForUpdate(path) {
234
+ function loadCursorSdkConfigForUpdate(path) {
235
235
  if (!existsSync(path))
236
236
  return {};
237
237
  let source;
@@ -342,16 +342,6 @@ export function updateCursorSdkConfig(path, update, options = {}) {
342
342
  return updated;
343
343
  });
344
344
  }
345
- export function saveCursorSdkUserConfig(config, path = getCursorSdkUserConfigPath()) {
346
- updateCursorSdkConfig(path, () => ({ ...config }), { newFileMode: 0o600 });
347
- }
348
- export function saveCursorSdkProjectConfig(cwd, config, configDirName = CONFIG_DIR_NAME) {
349
- const path = getCursorSdkProjectConfigPath(cwd, configDirName);
350
- updateCursorSdkConfig(path, () => ({ ...config }));
351
- }
352
- export function mergeCursorSdkConfig(base, patch) {
353
- return mergeCursorSdkConfigForUpdate({ ...base }, patch);
354
- }
355
345
  export function mergeCursorSdkConfigForUpdate(base, patch) {
356
346
  const baseCloud = asRecord(base.cloud);
357
347
  const baseLocal = asRecord(base.local);
@@ -378,12 +368,6 @@ export function mergeCursorSdkConfigForUpdate(base, patch) {
378
368
  export function cursorFastDefaultsFromConfig(config) {
379
369
  return new Map(Object.entries(config?.fastDefaults ?? {}));
380
370
  }
381
- export function withCursorFastDefaults(config, fastDefaults) {
382
- return {
383
- ...config,
384
- fastDefaults: Object.fromEntries([...fastDefaults.entries()].sort(([a], [b]) => a.localeCompare(b))),
385
- };
386
- }
387
371
  function resolved(source, value, cappedBy) {
388
372
  return { value, source, trustLevel: TRUST_LEVELS[source], ...(cappedBy ? { cappedBy } : {}) };
389
373
  }
@@ -10,5 +10,5 @@ export function buildCursorCustomSubagentDefinitions(config) {
10
10
  }),
11
11
  }]));
12
12
  }
13
- // ponytail: SDK 1.0.36 LOCAL conversion keeps only model ID/inherit; it drops params.
13
+ // ponytail: SDK 1.0.37 LOCAL conversion keeps only model ID/inherit; it drops params.
14
14
  // Upgrade this claim only after the installed public converter preserves them.