pi-cursor-sdk 0.1.37 → 0.1.38

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 (73) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/docs/cursor-native-tool-replay.md +3 -3
  3. package/package.json +1 -1
  4. package/scripts/platform-smoke/card-detect.mjs +1 -1
  5. package/src/context-window-cache.ts +10 -14
  6. package/src/context.ts +1 -1
  7. package/src/cursor-agent-message-web-tools.ts +2 -1
  8. package/src/cursor-agents-context-registration.ts +18 -0
  9. package/src/cursor-agents-context.ts +21 -30
  10. package/src/cursor-edit-diff.ts +4 -2
  11. package/src/cursor-fallback-warning.ts +22 -0
  12. package/src/cursor-incomplete-tool-visibility.ts +5 -10
  13. package/src/cursor-live-run-coordinator.ts +1 -1
  14. package/src/cursor-mcp-timeout-override.ts +0 -2
  15. package/src/cursor-model-lifecycle.ts +72 -0
  16. package/src/cursor-native-replay-routing.ts +1 -1
  17. package/src/cursor-native-replay-trace.ts +1 -1
  18. package/src/cursor-native-tool-display-registration.ts +16 -28
  19. package/src/cursor-native-tool-display-replay.ts +4 -21
  20. package/src/cursor-native-tool-display-state.ts +1 -1
  21. package/src/cursor-native-tool-display-tools.ts +10 -17
  22. package/src/cursor-native-tool-names.ts +16 -0
  23. package/src/cursor-pi-tool-bridge-env.ts +12 -0
  24. package/src/cursor-pi-tool-bridge-mcp.ts +16 -21
  25. package/src/cursor-pi-tool-bridge-run.ts +5 -5
  26. package/src/cursor-pi-tool-bridge-server.ts +8 -3
  27. package/src/cursor-pi-tool-bridge-snapshot.ts +7 -13
  28. package/src/cursor-pi-tool-bridge.ts +7 -7
  29. package/src/cursor-provider-lazy.ts +51 -0
  30. package/src/cursor-provider-live-run-drain.ts +1 -1
  31. package/src/cursor-provider-run-finalizer.ts +5 -5
  32. package/src/cursor-provider-run-outcome.ts +0 -1
  33. package/src/cursor-provider-turn-coordinator.ts +4 -5
  34. package/src/cursor-provider-turn-display-router.ts +5 -1
  35. package/src/cursor-provider-turn-emit.ts +1 -1
  36. package/src/cursor-provider-turn-lifecycle-emitter.ts +1 -5
  37. package/src/cursor-provider-turn-prepare.ts +13 -9
  38. package/src/cursor-provider-turn-runner.ts +3 -11
  39. package/src/cursor-provider-turn-sdk-normalizer.ts +28 -5
  40. package/src/cursor-provider-turn-send.ts +7 -2
  41. package/src/cursor-provider-turn-types.ts +1 -3
  42. package/src/cursor-provider.ts +3 -2
  43. package/src/cursor-question-tool.ts +5 -18
  44. package/src/cursor-record-utils.ts +42 -0
  45. package/src/cursor-replay-activity-builders.ts +16 -122
  46. package/src/cursor-replay-tool-details.ts +52 -80
  47. package/src/cursor-sdk-event-debug.ts +6 -6
  48. package/src/cursor-sensitive-text.ts +4 -4
  49. package/src/cursor-session-agent-lifecycle.ts +47 -0
  50. package/src/cursor-session-agent.ts +9 -47
  51. package/src/cursor-session-scope.ts +23 -4
  52. package/src/cursor-setting-sources.ts +8 -8
  53. package/src/cursor-skill-tool.ts +25 -32
  54. package/src/cursor-state.ts +66 -45
  55. package/src/cursor-tool-lifecycle.ts +16 -9
  56. package/src/cursor-tool-presentation-registry.ts +27 -18
  57. package/src/cursor-tool-result-display-readers.ts +185 -0
  58. package/src/cursor-tool-transcript.ts +17 -33
  59. package/src/cursor-tool-visibility.ts +9 -1
  60. package/src/cursor-transcript-tool-formatters.ts +23 -172
  61. package/src/cursor-transcript-tool-specs.ts +16 -41
  62. package/src/cursor-transcript-utils.ts +2 -34
  63. package/src/cursor-usage-accounting.ts +0 -6
  64. package/src/cursor-web-tool-activity.ts +4 -12
  65. package/src/cursor-web-tool-args.ts +1 -9
  66. package/src/index.ts +15 -16
  67. package/src/model-discovery.ts +5 -4
  68. package/src/model-list-cache.ts +37 -38
  69. package/src/cursor-native-tool-display.ts +0 -10
  70. package/src/cursor-provider-turn-api-key.ts +0 -1
  71. package/src/cursor-provider-turn-message-offset.ts +0 -15
  72. package/src/cursor-session-cwd.ts +0 -28
  73. package/src/cursor-tool-names.ts +0 -9
@@ -4,6 +4,7 @@ import { dirname, join } from "node:path";
4
4
  import { getAgentDir } from "@earendil-works/pi-coding-agent";
5
5
  import type { ModelListItem } from "@cursor/sdk";
6
6
  import { parseEnvBoolean } from "./cursor-env-boolean.js";
7
+ import { asRecord } from "./cursor-record-utils.js";
7
8
 
8
9
  const MODEL_LIST_CACHE_FILE = "cursor-sdk-model-list.json";
9
10
  const MODEL_LIST_CACHE_VERSION = 1;
@@ -46,52 +47,53 @@ export function fingerprintApiKey(apiKey: string): string {
46
47
  return createHash("sha256").update(apiKey).digest("hex").slice(0, 16);
47
48
  }
48
49
 
49
- function isRecord(value: unknown): value is Record<string, unknown> {
50
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
51
- }
52
-
53
50
  function isStringArray(value: unknown): value is string[] {
54
51
  return Array.isArray(value) && value.every((entry) => typeof entry === "string");
55
52
  }
56
53
 
57
54
  function isModelParameterValue(value: unknown): value is NonNullable<ModelListItem["variants"]>[number]["params"][number] {
58
- return isRecord(value) && typeof value.id === "string" && typeof value.value === "string";
55
+ const record = asRecord(value);
56
+ return record !== undefined && typeof record.id === "string" && typeof record.value === "string";
59
57
  }
60
58
 
61
59
  function isModelParameterDefinitionValue(value: unknown): value is NonNullable<ModelListItem["parameters"]>[number]["values"][number] {
62
- return isRecord(value) && typeof value.value === "string" && (value.displayName === undefined || typeof value.displayName === "string");
60
+ const record = asRecord(value);
61
+ return record !== undefined && typeof record.value === "string" && (record.displayName === undefined || typeof record.displayName === "string");
63
62
  }
64
63
 
65
64
  function isModelParameterDefinition(value: unknown): value is NonNullable<ModelListItem["parameters"]>[number] {
66
- if (!isRecord(value)) return false;
65
+ const record = asRecord(value);
66
+ if (!record) return false;
67
67
  return (
68
- typeof value.id === "string" &&
69
- (value.displayName === undefined || typeof value.displayName === "string") &&
70
- Array.isArray(value.values) &&
71
- value.values.every(isModelParameterDefinitionValue)
68
+ typeof record.id === "string" &&
69
+ (record.displayName === undefined || typeof record.displayName === "string") &&
70
+ Array.isArray(record.values) &&
71
+ record.values.every(isModelParameterDefinitionValue)
72
72
  );
73
73
  }
74
74
 
75
75
  function isModelVariant(value: unknown): value is NonNullable<ModelListItem["variants"]>[number] {
76
- if (!isRecord(value)) return false;
76
+ const record = asRecord(value);
77
+ if (!record) return false;
77
78
  return (
78
- Array.isArray(value.params) &&
79
- value.params.every(isModelParameterValue) &&
80
- typeof value.displayName === "string" &&
81
- (value.description === undefined || typeof value.description === "string") &&
82
- (value.isDefault === undefined || typeof value.isDefault === "boolean")
79
+ Array.isArray(record.params) &&
80
+ record.params.every(isModelParameterValue) &&
81
+ typeof record.displayName === "string" &&
82
+ (record.description === undefined || typeof record.description === "string") &&
83
+ (record.isDefault === undefined || typeof record.isDefault === "boolean")
83
84
  );
84
85
  }
85
86
 
86
87
  function isModelListItem(value: unknown): value is ModelListItem {
87
- if (!isRecord(value)) return false;
88
+ const record = asRecord(value);
89
+ if (!record) return false;
88
90
  return (
89
- typeof value.id === "string" &&
90
- typeof value.displayName === "string" &&
91
- (value.description === undefined || typeof value.description === "string") &&
92
- (value.aliases === undefined || isStringArray(value.aliases)) &&
93
- (value.parameters === undefined || (Array.isArray(value.parameters) && value.parameters.every(isModelParameterDefinition))) &&
94
- (value.variants === undefined || (Array.isArray(value.variants) && value.variants.every(isModelVariant)))
91
+ typeof record.id === "string" &&
92
+ typeof record.displayName === "string" &&
93
+ (record.description === undefined || typeof record.description === "string") &&
94
+ (record.aliases === undefined || isStringArray(record.aliases)) &&
95
+ (record.parameters === undefined || (Array.isArray(record.parameters) && record.parameters.every(isModelParameterDefinition))) &&
96
+ (record.variants === undefined || (Array.isArray(record.variants) && record.variants.every(isModelVariant)))
95
97
  );
96
98
  }
97
99
 
@@ -100,21 +102,22 @@ function isValidFetchedAt(value: unknown): value is number {
100
102
  }
101
103
 
102
104
  function parseModelListCacheFile(value: unknown): ModelListCacheFile | undefined {
103
- if (!isRecord(value)) return undefined;
105
+ const record = asRecord(value);
106
+ if (!record) return undefined;
104
107
  if (
105
- value.version !== MODEL_LIST_CACHE_VERSION ||
106
- !isValidFetchedAt(value.fetchedAt) ||
107
- typeof value.keyFingerprint !== "string" ||
108
- !Array.isArray(value.models) ||
109
- !value.models.every(isModelListItem)
108
+ record.version !== MODEL_LIST_CACHE_VERSION ||
109
+ !isValidFetchedAt(record.fetchedAt) ||
110
+ typeof record.keyFingerprint !== "string" ||
111
+ !Array.isArray(record.models) ||
112
+ !record.models.every(isModelListItem)
110
113
  ) {
111
114
  return undefined;
112
115
  }
113
116
  return {
114
- version: value.version,
115
- fetchedAt: value.fetchedAt,
116
- keyFingerprint: value.keyFingerprint,
117
- models: value.models,
117
+ version: record.version,
118
+ fetchedAt: record.fetchedAt,
119
+ keyFingerprint: record.keyFingerprint,
120
+ models: record.models,
118
121
  };
119
122
  }
120
123
 
@@ -149,10 +152,6 @@ export function loadAnyCachedModelCatalog(keyFingerprint: string): CachedModelLi
149
152
  return { fetchedAt: cache.fetchedAt, models: cache.models };
150
153
  }
151
154
 
152
- export function loadAnyCachedModels(keyFingerprint: string): ModelListItem[] | undefined {
153
- return loadAnyCachedModelCatalog(keyFingerprint)?.models;
154
- }
155
-
156
155
  export function saveModelListCache(keyFingerprint: string, models: ModelListItem[]): boolean {
157
156
  if (isModelCacheDisabled()) return false;
158
157
  try {
@@ -1,10 +0,0 @@
1
- export type { CursorNativeToolDisplayItem } from "./cursor-native-tool-display-state.js";
2
- export {
3
- canRenderCursorToolNatively,
4
- deleteCursorNativeToolDisplay,
5
- isCursorNativeToolDisplayEnabled,
6
- isCursorNativeToolDisplayRuntimeEnabled,
7
- recordCursorNativeToolDisplay,
8
- __testUtils,
9
- } from "./cursor-native-tool-display-state.js";
10
- export { registerCursorNativeToolDisplay } from "./cursor-native-tool-display-registration.js";
@@ -1 +0,0 @@
1
- export { resolveCursorApiKey } from "./cursor-api-key.js";
@@ -1,15 +0,0 @@
1
- import { countCursorAgentMessages } from "./cursor-agent-message-web-tools.js";
2
- import type { CursorSdkEventDebugSink } from "./cursor-sdk-event-debug.js";
3
-
4
- export async function getCursorAgentMessageOffset(
5
- agentId: string,
6
- cwd: string,
7
- sdkEventDebug: CursorSdkEventDebugSink | undefined,
8
- ): Promise<number | undefined> {
9
- try {
10
- return await countCursorAgentMessages(agentId, cwd);
11
- } catch (error) {
12
- sdkEventDebug?.recordError("cursor_agent_message_count", error);
13
- return undefined;
14
- }
15
- }
@@ -1,28 +0,0 @@
1
- import {
2
- getCursorSessionCwdFromScope,
3
- registerCursorSessionScope,
4
- __testUtils as cursorSessionScopeTestUtils,
5
- } from "./cursor-session-scope.js";
6
- import type { ExtensionHandler, SessionStartEvent } from "@earendil-works/pi-coding-agent";
7
-
8
- interface CursorSessionCwdExtensionApi {
9
- on(event: "session_start", handler: ExtensionHandler<SessionStartEvent>): void;
10
- }
11
-
12
- /**
13
- * Pi session cwd when known; falls back to process.cwd() before session_start.
14
- * Updated on session_start only until pi threads cwd into streamSimple—mid-session cwd
15
- * changes without a new session_start event are not reflected here.
16
- */
17
- export function getCursorSessionCwd(): string {
18
- return getCursorSessionCwdFromScope();
19
- }
20
-
21
- export function registerCursorSessionCwd(pi: CursorSessionCwdExtensionApi): void {
22
- registerCursorSessionScope(pi);
23
- }
24
-
25
- export const __testUtils = {
26
- set: cursorSessionScopeTestUtils.set,
27
- reset: cursorSessionScopeTestUtils.reset,
28
- };
@@ -1,9 +0,0 @@
1
- export {
2
- CURSOR_REPLAY_ACTIVITY_TOOL_NAME,
3
- getCursorReplayActivityTitle,
4
- getCursorReplayPromptLabel,
5
- isCursorReplayToolName,
6
- isExcludedFromCursorBridgeExposure,
7
- type CursorReplayActivityToolName,
8
- type CursorReplayToolName,
9
- } from "./cursor-tool-presentation-registry.js";