pi-cursor-sdk 0.1.55 → 0.1.57

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 (88) hide show
  1. package/CHANGELOG.md +60 -2
  2. package/README.md +100 -28
  3. package/docs/cursor-live-smoke-checklist.md +7 -7
  4. package/docs/cursor-model-ux-spec.md +48 -41
  5. package/docs/cursor-native-tool-replay.md +4 -4
  6. package/docs/cursor-native-tool-visual-audit.md +1 -1
  7. package/docs/cursor-testing-lessons.md +20 -7
  8. package/docs/cursor-tool-surfaces.md +13 -2
  9. package/docs/platform-smoke-implementation.md +220 -0
  10. package/docs/platform-smoke.md +183 -247
  11. package/package.json +39 -7
  12. package/platform-smoke.config.mjs +5 -1
  13. package/scripts/cloud-runtime-smoke.d.mts +3 -0
  14. package/scripts/cloud-runtime-smoke.mjs +502 -0
  15. package/scripts/debug-provider-events.mjs +7 -2
  16. package/scripts/isolated-cursor-smoke.sh +4 -6
  17. package/scripts/lib/cursor-child-process.d.mts +1 -0
  18. package/scripts/lib/cursor-child-process.mjs +137 -7
  19. package/scripts/lib/local-resume-smoke-harness.mjs +543 -0
  20. package/scripts/local-resume-cleanup-smoke.mjs +108 -0
  21. package/scripts/local-resume-smoke.d.mts +1 -0
  22. package/scripts/local-resume-smoke.mjs +642 -0
  23. package/scripts/platform-smoke/artifact-anchored-extract.d.mts +10 -0
  24. package/scripts/platform-smoke/artifact-anchored-extract.mjs +111 -0
  25. package/scripts/platform-smoke/artifact-bundle-chunk.mjs +57 -0
  26. package/scripts/platform-smoke/artifact-bundle-contract.mjs +34 -0
  27. package/scripts/platform-smoke/artifact-fs-safety.mjs +311 -0
  28. package/scripts/platform-smoke/artifact-openat-extract.c +335 -0
  29. package/scripts/platform-smoke/artifact-secrets.mjs +155 -0
  30. package/scripts/platform-smoke/artifacts.mjs +293 -65
  31. package/scripts/platform-smoke/card-detect.mjs +16 -4
  32. package/scripts/platform-smoke/crabbox-runner.mjs +45 -3
  33. package/scripts/platform-smoke/doctor.mjs +20 -10
  34. package/scripts/platform-smoke/live-suite-runner.mjs +18 -57
  35. package/scripts/platform-smoke/local-resume-runner.mjs +252 -0
  36. package/scripts/platform-smoke/local-resume-suites.d.mts +15 -0
  37. package/scripts/platform-smoke/local-resume-suites.mjs +104 -0
  38. package/scripts/platform-smoke/scenarios.mjs +16 -2
  39. package/scripts/platform-smoke/target-runtime.mjs +206 -0
  40. package/scripts/platform-smoke/targets.mjs +33 -141
  41. package/scripts/platform-smoke/visual-evidence.mjs +6 -7
  42. package/scripts/platform-smoke/wrapped-line-match.mjs +9 -0
  43. package/scripts/platform-smoke.mjs +40 -27
  44. package/scripts/refresh-cursor-model-snapshots.mjs +18 -6
  45. package/scripts/steering-rpc-smoke.mjs +12 -2
  46. package/scripts/tmux-live-smoke.sh +3 -5
  47. package/shared/cursor-cloud-lifecycle-constants.d.mts +3 -0
  48. package/shared/cursor-cloud-lifecycle-constants.mjs +7 -0
  49. package/shared/cursor-sensitive-text.mjs +7 -1
  50. package/src/context.ts +5 -2
  51. package/src/cursor-agents-context-registration.ts +7 -0
  52. package/src/cursor-agents-context.ts +3 -1
  53. package/src/cursor-api-key.ts +15 -1
  54. package/src/cursor-bridge-contract.ts +3 -0
  55. package/src/cursor-cloud-lifecycle.ts +733 -0
  56. package/src/cursor-cloud-options.ts +206 -0
  57. package/src/cursor-cloud-reporting.ts +246 -0
  58. package/src/cursor-config.ts +659 -0
  59. package/src/cursor-display-only-trace.ts +14 -0
  60. package/src/cursor-display-text.ts +8 -2
  61. package/src/cursor-durable-fs.ts +49 -0
  62. package/src/cursor-fallback-models.generated.ts +2045 -485
  63. package/src/cursor-live-run-accounting.ts +7 -1
  64. package/src/cursor-live-run-coordinator.ts +1 -0
  65. package/src/cursor-pi-tool-bridge-run.ts +14 -4
  66. package/src/cursor-provider-errors.ts +31 -5
  67. package/src/cursor-provider-live-run-drain.ts +5 -0
  68. package/src/cursor-provider-run-finalizer.ts +37 -28
  69. package/src/cursor-provider-run-outcome.ts +7 -2
  70. package/src/cursor-provider-turn-finalize.ts +77 -7
  71. package/src/cursor-provider-turn-prepare.ts +228 -12
  72. package/src/cursor-provider-turn-runner.ts +42 -13
  73. package/src/cursor-provider-turn-send.ts +59 -16
  74. package/src/cursor-provider-turn-types.ts +44 -10
  75. package/src/cursor-runtime-state.ts +478 -0
  76. package/src/cursor-sdk-event-debug.ts +46 -6
  77. package/src/cursor-sdk-process-error-guard.ts +101 -30
  78. package/src/cursor-session-agent-cleanup.ts +328 -0
  79. package/src/cursor-session-agent-resume.ts +439 -0
  80. package/src/cursor-session-agent.ts +109 -13
  81. package/src/cursor-session-scope.ts +35 -2
  82. package/src/cursor-session-send-policy.ts +1 -1
  83. package/src/cursor-skill-tool.ts +30 -11
  84. package/src/cursor-state.ts +112 -69
  85. package/src/cursor-tool-manifest.ts +1 -1
  86. package/src/cursor-usage-accounting.ts +14 -4
  87. package/src/index.ts +11 -2
  88. package/src/model-discovery.ts +10 -56
@@ -8,7 +8,8 @@ import type { ProviderModelConfig } from "@earendil-works/pi-coding-agent";
8
8
  import type { ModelThinkingLevel, ThinkingLevelMap } from "@earendil-works/pi-ai/compat";
9
9
  import { loadContextWindowCache } from "./context-window-cache.js";
10
10
  import { loadCursorSdk } from "./cursor-sdk-runtime.js";
11
- import { resolveCursorApiKey } from "./cursor-api-key.js";
11
+ import { resolveCursorApiKey, resolveCursorRuntimeApiKey } from "./cursor-api-key.js";
12
+ import { scrubSensitiveText } from "./cursor-sensitive-text.js";
12
13
  import {
13
14
  fingerprintApiKey,
14
15
  loadAnyCachedModelCatalog,
@@ -16,12 +17,11 @@ import {
16
17
  saveModelListCache,
17
18
  } from "./model-list-cache.js";
18
19
 
19
- const CURSOR_PROVIDER_ID = "cursor";
20
20
  const FALLBACK_CONTEXT_WINDOW = 128000;
21
21
  const FALLBACK_MAX_TOKENS = 16384;
22
22
  const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
23
23
  const TEXT_AND_IMAGE_INPUT: ProviderModelConfig["input"] = ["text", "image"];
24
- const AUTH_SETUP_HINT = "/login (Use an API key -> Cursor), CURSOR_API_KEY, or --api-key with a Cursor SDK API key; Cursor Agent CLI/Desktop login is not reused";
24
+ const AUTH_SETUP_HINT = "/login (Use an API key -> Cursor) or CURSOR_API_KEY; startup discovery does not parse Pi CLI arguments, and Cursor Agent CLI/Desktop login is not reused";
25
25
  const CATALOG_REFRESH_HINT =
26
26
  "After adding auth to an already-started pi session, run /cursor-refresh-models to refresh the full live Cursor model catalog without restarting pi.";
27
27
 
@@ -35,47 +35,15 @@ export interface CursorModelFallbackIssue {
35
35
 
36
36
  export interface DiscoverModelsOptions {
37
37
  onFallback?: (issue: CursorModelFallbackIssue) => void;
38
+ apiKey?: string;
38
39
  // Bypass the on-disk model cache and always hit the live catalog. Used by the
39
40
  // /cursor-refresh-models command; the startup path leaves this false so warm
40
41
  // boots skip the slow network round-trip.
41
42
  forceRefresh?: boolean;
42
43
  }
43
44
 
44
- function getCliApiKeyFromArgv(argv: string[] = process.argv): string | undefined {
45
- for (let index = 0; index < argv.length; index++) {
46
- const arg = argv[index];
47
- if (arg === "--api-key") {
48
- const value = argv[index + 1];
49
- if (!value || value.startsWith("--")) return undefined;
50
- const trimmed = value.trim();
51
- return trimmed || undefined;
52
- }
53
- const prefix = "--api-key=";
54
- if (arg.startsWith(prefix)) {
55
- const trimmed = arg.slice(prefix.length).trim();
56
- return trimmed || undefined;
57
- }
58
- }
59
- return undefined;
60
- }
61
-
62
- async function getStoredCursorApiKey(): Promise<string | undefined> {
63
- try {
64
- const { AuthStorage } = await import("@earendil-works/pi-coding-agent");
65
- return resolveCursorApiKey(await AuthStorage.create().getApiKey(CURSOR_PROVIDER_ID, { includeFallback: false }));
66
- } catch {
67
- return undefined;
68
- }
69
- }
70
-
71
- async function getDiscoveryApiKey(): Promise<string | undefined> {
72
- const cliApiKey = resolveCursorApiKey(getCliApiKeyFromArgv());
73
- if (cliApiKey) return cliApiKey;
74
-
75
- const storedApiKey = await getStoredCursorApiKey();
76
- if (storedApiKey) return storedApiKey;
77
-
78
- return resolveCursorApiKey(process.env.CURSOR_API_KEY);
45
+ async function getDiscoveryApiKey(apiKey?: string): Promise<string | undefined> {
46
+ return resolveCursorApiKey(apiKey) ?? resolveCursorRuntimeApiKey();
79
47
  }
80
48
 
81
49
  export interface CursorModelMetadata {
@@ -444,22 +412,9 @@ export function buildCursorModelSelection(
444
412
  return params.length > 0 ? { id: metadata.selectionModelId, params } : { id: metadata.selectionModelId };
445
413
  }
446
414
 
447
- function scrubDiscoveryErrorText(text: string, apiKey: string): string {
448
- let scrubbed = text.replace(new RegExp(apiKey.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), "[redacted]");
449
- return scrubbed
450
- .replace(/Bearer\s+[A-Za-z0-9._~+/=-]+/gi, "Bearer [redacted]")
451
- .replace(/((?:^|[\s,{])cookie["']?\s*[:=]\s*["']?)[^\n]+/gi, "$1[redacted]")
452
- .replace(
453
- /((?:authorization|api[_-]?key|apiKey|token|session(?:[_-]?id)?)["']?\s*[:=]\s*["']?)[^"'\s,;}]+/gi,
454
- "$1[redacted]",
455
- )
456
- .trim();
457
- }
458
-
459
415
  function sanitizeDiscoveryError(error: unknown, apiKey: string): string | undefined {
460
416
  const message = error instanceof Error ? error.message : typeof error === "string" ? error : "";
461
- const scrubbed = scrubDiscoveryErrorText(message, apiKey);
462
- return scrubbed || undefined;
417
+ return scrubSensitiveText(message, apiKey).trim() || undefined;
463
418
  }
464
419
 
465
420
  async function useFallbackModels(options: DiscoverModelsOptions, issue: CursorModelFallbackIssue): Promise<ProviderModelConfig[]> {
@@ -469,7 +424,7 @@ async function useFallbackModels(options: DiscoverModelsOptions, issue: CursorMo
469
424
  }
470
425
 
471
426
  export async function discoverModels(options: DiscoverModelsOptions = {}): Promise<ProviderModelConfig[]> {
472
- const apiKey = await getDiscoveryApiKey();
427
+ const apiKey = await getDiscoveryApiKey(options.apiKey);
473
428
  if (!apiKey) {
474
429
  return useFallbackModels(options, {
475
430
  reason: "missing-api-key",
@@ -506,8 +461,8 @@ export async function discoverModels(options: DiscoverModelsOptions = {}): Promi
506
461
  if (cachedCatalog && cachedCatalog.models.length > 0) {
507
462
  options.onFallback?.({
508
463
  reason: "cached-after-error",
509
- message: `Cursor model discovery failed; using cached Cursor model catalog from ${new Date(cachedCatalog.fetchedAt).toISOString()}. ${errorMessage}`,
510
- errorMessage,
464
+ message: `Cursor model discovery failed; using cached Cursor model catalog from ${new Date(cachedCatalog.fetchedAt).toISOString()}.${errorMessage ? ` ${errorMessage}` : ""}`,
465
+ ...(errorMessage ? { errorMessage } : {}),
511
466
  });
512
467
  return registerModelItems(cachedCatalog.models);
513
468
  }
@@ -522,6 +477,5 @@ export async function discoverModels(options: DiscoverModelsOptions = {}): Promi
522
477
  export const __testUtils = {
523
478
  parseContextWindow,
524
479
  registerModelItems,
525
- getCliApiKeyFromArgv,
526
480
  normalizeApiKey: resolveCursorApiKey,
527
481
  };