@caeliq/llms 1.0.66 → 1.0.68

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 (44) hide show
  1. package/README.md +2 -1
  2. package/dist/cjs/server.cjs +232 -222
  3. package/dist/cjs/server.cjs.map +4 -4
  4. package/dist/cursor-sdk/auth-exchange-cache.d.ts +23 -0
  5. package/dist/cursor-sdk/events-to-sse.d.ts +3 -3
  6. package/dist/cursor-sdk/lifecycle-planner.d.ts +21 -4
  7. package/dist/cursor-sdk/prompt.d.ts +10 -0
  8. package/dist/cursor-sdk/session.d.ts +44 -0
  9. package/dist/cursor-sdk/shared.d.ts +7 -0
  10. package/dist/cursor-sdk/turn-output.d.ts +3 -0
  11. package/dist/cursor-sdk/usage.d.ts +27 -3
  12. package/dist/esm/server.mjs +232 -222
  13. package/dist/esm/server.mjs.map +4 -4
  14. package/dist/routing/protocol-endpoints.d.ts +14 -0
  15. package/dist/server.d.ts +1 -1
  16. package/dist/session-registry.d.ts +36 -0
  17. package/dist/tests/anthropic.message-start-usage.test.d.ts +1 -0
  18. package/dist/tests/cache-outcome.d.ts +1 -0
  19. package/dist/tests/cross-protocol.matrix.d.ts +1 -0
  20. package/dist/tests/cursor-sdk.auth-exchange-cache.d.ts +1 -0
  21. package/dist/tests/cursor-sdk.shared.d.ts +1 -0
  22. package/dist/tests/cursor-sdk.tool-id-alias.d.ts +1 -0
  23. package/dist/tests/responses.encrypted-content-cache.d.ts +1 -0
  24. package/dist/tests/session-registry.d.ts +1 -0
  25. package/dist/tests/tool-content.multimodal.d.ts +1 -0
  26. package/dist/tests/wire-keep.d.ts +1 -0
  27. package/dist/transformer/codex.transformer.d.ts +20 -34
  28. package/dist/transformer/openai.responses.transformer.d.ts +1 -1
  29. package/dist/transformer/opencode-headers.transformer.d.ts +1 -2
  30. package/dist/utils/cache-outcome.d.ts +79 -0
  31. package/dist/utils/cache-prefix-debug.d.ts +21 -1
  32. package/dist/utils/cacheControl.d.ts +8 -0
  33. package/dist/utils/deepseek.util.d.ts +1 -1
  34. package/dist/utils/message-debug.d.ts +32 -4
  35. package/dist/utils/nested-agent.d.ts +26 -0
  36. package/dist/utils/openai.responses.util.d.ts +11 -0
  37. package/dist/utils/request-latency.d.ts +4 -0
  38. package/dist/utils/responses.encrypted-content-cache.d.ts +42 -0
  39. package/dist/utils/sse-debug-tap.d.ts +12 -2
  40. package/dist/utils/stream-peek.d.ts +20 -0
  41. package/dist/utils/tool-content.d.ts +54 -0
  42. package/dist/utils/transformer-plan.d.ts +9 -0
  43. package/dist/utils/vertex-claude.util.d.ts +1 -1
  44. package/package.json +5 -5
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @cursor/sdk POSTs /auth/exchange_user_api_key on every Agent.create and
3
+ * models.list. Subagent turns mint new session keys, so Agent.create runs
4
+ * again and the SDK does not cache the access token across those calls.
5
+ *
6
+ * Wrap global fetch: coalesce in-flight exchanges per crsr_ key, reuse the
7
+ * access token until a Cursor request with that token returns 401.
8
+ *
9
+ * Critical: never forward a caller's AbortSignal onto the shared exchange.
10
+ * Agent.create often cancels while another waiter still needs the token; if
11
+ * the first caller's signal aborts the shared fetch, every waiter rejects
12
+ * with AbortError and Node surfaces unhandledRejection / late-handled
13
+ * PromiseRejectionHandledWarning.
14
+ */
15
+ /**
16
+ * Drop a cached exchanged token for a dashboard API key (crsr_... or Bearer).
17
+ * Call when Cursor reports auth failure via run status / AuthenticationError —
18
+ * those paths often never surface as an HTTP 401 on the wrapped fetch.
19
+ */
20
+ export declare function invalidateCursorAuthExchange(crsrApiKey: string): void;
21
+ /** Re-wrap if tests or other code replaced globalThis.fetch. */
22
+ export declare function installCursorAuthExchangeCache(): void;
23
+ export declare function __resetCursorAuthExchangeCacheForTests(): void;
@@ -95,12 +95,12 @@ export declare function createSseHelpers(model: string, encoder: TextEncoder): {
95
95
  finish_reason: "stop" | "tool_calls";
96
96
  }[];
97
97
  usage: {
98
+ prompt_tokens_details?: {
99
+ cached_tokens: number;
100
+ } | undefined;
98
101
  prompt_tokens: number;
99
102
  completion_tokens: number;
100
103
  total_tokens: number;
101
- prompt_tokens_details: {
102
- cached_tokens: number;
103
- };
104
104
  };
105
105
  id: string;
106
106
  object: string;
@@ -36,6 +36,11 @@ export type CursorLifecycleInput<TParked extends CursorParkedToolRef = CursorPar
36
36
  hasSentPrompt: boolean;
37
37
  poisoned: boolean;
38
38
  alignment: CursorContextAlignment;
39
+ /**
40
+ * False when agent/model/workspace/tool configuration changed since the
41
+ * transcript commit. Undefined preserves the legacy behavior (match).
42
+ */
43
+ compatibilityMatch?: boolean;
39
44
  run: CursorRunSnapshot<TParked>;
40
45
  };
41
46
  turn: {
@@ -43,7 +48,9 @@ export type CursorLifecycleInput<TParked extends CursorParkedToolRef = CursorPar
43
48
  toolResults: readonly TResult[];
44
49
  };
45
50
  };
46
- export type CursorLifecycleRetirementReason = "poisoned-session" | "inconsistent-unused-session" | "unknown-context-alignment" | "divergent-context-alignment" | "active-different-turn" | "dead-parked-run" | "parked-turn-has-steering" | "parked-tool-results-mismatch" | "orphaned-tool-results";
51
+ /** Hard remint only — soft alignment cases stay on the same agent. */
52
+ export type CursorLifecycleRetirementReason = "poisoned-session";
53
+ export type CursorLifecycleIncrementalReason = "strictly-aligned-idle-session" | "unknown-context-alignment" | "divergent-context-alignment" | "active-different-turn" | "dead-parked-run" | "parked-turn-has-steering" | "parked-tool-results-mismatch" | "orphaned-tool-results";
47
54
  export type CursorLifecycleRetirementPlan = {
48
55
  action: "retire-and-replay-full";
49
56
  reason: CursorLifecycleRetirementReason;
@@ -54,13 +61,23 @@ export type CursorLifecyclePlan<TParked extends CursorParkedToolRef = CursorPark
54
61
  matches: ExactParkedResultMatch<TParked, TResult>;
55
62
  } | {
56
63
  action: "send-full";
57
- reason: "unused-session";
64
+ reason: "unused-session" | "inconsistent-unused-session";
58
65
  } | {
59
66
  action: "send-incremental";
60
- reason: "strictly-aligned-idle-session";
67
+ reason: CursorLifecycleIncrementalReason;
61
68
  } | CursorLifecycleRetirementPlan;
62
69
  /**
63
- * Choose the only safe lifecycle action for a new, non-coalesced host turn.
70
+ * Soft incremental reasons where the runner must cancel/abandon any prior
71
+ * active or parked run before `agent.send` — without reminting the agent.
72
+ */
73
+ export declare const CURSOR_SOFT_CANCEL_THEN_INCREMENTAL: Set<CursorLifecycleIncrementalReason>;
74
+ /**
75
+ * Choose the lifecycle action for a new, non-coalesced host turn.
76
+ *
77
+ * Soft transcript-alignment mismatches stay on the same Cursor agent via
78
+ * `send-incremental` (caller cancels parked/active runs when needed). Hard
79
+ * remint (`retire-and-replay-full`) is reserved for poisoned sessions; send/
80
+ * stream failure recovery remints in the runner, not here.
64
81
  *
65
82
  * This function is intentionally pure. It neither resolves parked tools nor
66
83
  * changes session state; the caller executes the returned plan under its
@@ -3,6 +3,11 @@ import { type UnifiedTurnIntent } from "../types/turn-intent";
3
3
  import type { SDKUserMessage } from "@cursor/sdk";
4
4
  import { type HostEnvironment } from "./host-env";
5
5
  export declare function buildBridgeSystemGuidance(request: UnifiedChatRequest, workspaceDir: string, hostEnv?: HostEnvironment): string;
6
+ /**
7
+ * Identity of the bridge preamble actually sent on an agent. Unchanged
8
+ * follow-ups skip re-sending it so Cursor history does not stack copies.
9
+ */
10
+ export declare function bridgePromptGuidanceFingerprint(request: UnifiedChatRequest, workspaceDir: string, hostEnv: HostEnvironment): string;
6
11
  /**
7
12
  * Short restatement appended after the transcript. The guidance above is far
8
13
  * from the generation point once history is flattened in; this is the last
@@ -37,6 +42,11 @@ export declare function toSdkPrompt(request: UnifiedChatRequest, options: {
37
42
  hostEnv?: HostEnvironment;
38
43
  /** Protocol semantics recovered before Anthropic content was flattened. */
39
44
  turnIntent?: UnifiedTurnIntent;
45
+ /**
46
+ * Bridge preamble + tail reminder. Default true. Set false on follow-ups
47
+ * whose tool catalog and host env already went out on this agent.
48
+ */
49
+ includeBridgeGuidance?: boolean;
40
50
  }): SDKUserMessage;
41
51
  export type TrailingCursorToolTurn = {
42
52
  toolResults: Array<{
@@ -4,6 +4,7 @@ import type { CursorTranscriptCommit } from "./turn-identity";
4
4
  import { type HostEnvironment } from "./host-env";
5
5
  import { type CursorSdkMode } from "./shared";
6
6
  export type ParkedTool = {
7
+ /** Original Cursor SDK tool-call id (never emitted to the client). */
7
8
  id: string;
8
9
  name: string;
9
10
  args: Record<string, unknown>;
@@ -30,8 +31,20 @@ export type CursorSdkSession = {
30
31
  streamNext?: Promise<IteratorResult<any>>;
31
32
  streamNextRunToken?: symbol;
32
33
  activeRunToken?: symbol;
34
+ /** Raw usage from the last completed SDK turn; never a parked CCR boundary. */
33
35
  lastSdkUsageRaw?: OpenAiUsage;
34
36
  parked: ParkedTool[];
37
+ /**
38
+ * Per-session bidirectional map between raw Cursor SDK tool-call ids
39
+ * (possibly newline-joined / overlong) and the host-safe aliases emitted
40
+ * to the client. Parked records keep originals; the wire carries aliases;
41
+ * incoming echoes are translated back before matching. Dies with the
42
+ * session; bounded below so long-lived agents cannot grow it forever.
43
+ */
44
+ toolIdAliases: {
45
+ byOriginal: Map<string, string>;
46
+ byAlias: Map<string, string>;
47
+ };
35
48
  /** Tool calls waiting to be emitted on the current SSE response. */
36
49
  pendingEmit: Array<{
37
50
  id: string;
@@ -63,6 +76,11 @@ export type CursorSdkSession = {
63
76
  compatibilityStamp?: string;
64
77
  /** Fingerprint of the host env baked into the workspace rules/deny hooks. */
65
78
  guidanceFingerprint?: string;
79
+ /**
80
+ * Bridge preamble last actually sent on this agent (host env + tool catalog).
81
+ * Unchanged follow-ups omit the preamble so history does not stack copies.
82
+ */
83
+ lastBridgePromptGuidanceFingerprint?: string;
66
84
  /**
67
85
  * Set when the local SDK handles are no longer trustworthy. The manager must
68
86
  * not hand this agent out for a future request.
@@ -98,6 +116,13 @@ export type CancelActiveRunResult = {
98
116
  failed: boolean;
99
117
  timedOut: boolean;
100
118
  };
119
+ export declare function aliasHostToolId(session: CursorSdkSession, original: unknown): string | undefined;
120
+ /**
121
+ * Translate a client-echoed tool-call id back to the parked SDK original.
122
+ * Unknown ids pass through unchanged so legacy / unmapped turns mismatch
123
+ * exactly as before instead of collapsing onto something unrelated.
124
+ */
125
+ export declare function resolveHostToolId(session: CursorSdkSession, echoed: unknown): string;
101
126
  export declare function markSessionPoisoned(session: CursorSdkSession, reason: string): void;
102
127
  /**
103
128
  * Drop local run handles and await SDK `run.cancel()` when needed.
@@ -138,11 +163,29 @@ export declare function shouldEnableCursorSandbox(requested?: boolean): boolean;
138
163
  * path correction) is updated here regardless.
139
164
  */
140
165
  export declare function refreshWorkspaceGuidance(session: CursorSdkSession, hostEnv: HostEnvironment): boolean;
166
+ /**
167
+ * Cursor SDK session directory key. Prefer explicit client conversation ids
168
+ * over hashing prompt text — never include system / harness version.
169
+ *
170
+ * Claude Code subagents share the parent session id. Mix first-user text so
171
+ * parallel Task agents each get their own Cursor Agent instead of collapsing
172
+ * onto one turn registry slot.
173
+ */
141
174
  export declare function buildSessionKey(input: {
142
175
  headerSession?: string;
176
+ /** Inbound-captured Claude/OpenCode session id (protocolContext / req). */
177
+ clientSessionId?: string;
143
178
  metadataUserId?: string;
144
179
  model?: string;
180
+ /** Anonymous clients only: first user text (not system). */
181
+ firstUserText?: string;
182
+ /** @deprecated Use firstUserText. Kept for call-site compatibility. */
145
183
  systemAndFirstUser?: string;
184
+ /**
185
+ * Claude Code Task / subagent turn. Parent session id alone is not unique
186
+ * across parallel subagents.
187
+ */
188
+ isSubagent?: boolean;
146
189
  }): string;
147
190
  /** True while a session has a live run, open stream, or unresolved host tools. */
148
191
  export declare function isSessionInFlight(session: CursorSdkSession): boolean;
@@ -187,6 +230,7 @@ export declare class SessionManager {
187
230
  dispose(key: string): Promise<void>;
188
231
  invalidate(sessionOrKey: CursorSdkSession | string, reason: string): Promise<void>;
189
232
  private disposeAgent;
233
+ private rehydratePersistedAgent;
190
234
  private createSessionRecord;
191
235
  private evictIfNeeded;
192
236
  private evictIdle;
@@ -26,3 +26,10 @@ export declare function contentToText(content: UnifiedMessage["content"]): strin
26
26
  export declare function hashSessionFingerprint(parts: string[]): string;
27
27
  export declare function coerceThinkingText(value: unknown): string;
28
28
  export declare function extractEffort(request: any): string | undefined;
29
+ /**
30
+ * Transient Cursor provider failures (throttling / overload) must not destroy
31
+ * the warm sticky agent: the retry reuses it instead of paying a cold start.
32
+ * Auth errors and client aborts are NOT transient — they keep the old
33
+ * retire-the-session behavior at the call site.
34
+ */
35
+ export declare function isCursorTransientProviderError(err: unknown): boolean;
@@ -71,6 +71,9 @@ export declare class CursorTurnRegistry {
71
71
  responseKind: "stream" | "json";
72
72
  signal?: AbortSignal;
73
73
  }): Promise<CursorTurnLease>;
74
+ peekActive(sessionKey: string): {
75
+ fingerprint: string;
76
+ } | undefined;
74
77
  clear(): void;
75
78
  }
76
79
  export declare const globalCursorTurnRegistry: CursorTurnRegistry;
@@ -7,6 +7,13 @@ export type OpenAiUsage = {
7
7
  cached_tokens?: number;
8
8
  };
9
9
  };
10
+ export type CursorUsageCounters = {
11
+ inputTokens: number;
12
+ outputTokens: number;
13
+ cacheRead: number;
14
+ cacheWrite: number;
15
+ reasoningTokens: number;
16
+ };
10
17
  /**
11
18
  * Rough char→token estimate for mid-turn usage before Cursor emits a usage
12
19
  * event (and as the host-facing request usage even when it does).
@@ -18,11 +25,28 @@ export declare function estimateTokens(chars: number): number;
18
25
  export declare function estimateRequestPromptTokens(request: UnifiedChatRequest): number;
19
26
  /** Build OpenAI-style usage for a single CCR request (not Cursor session totals). */
20
27
  export declare function requestUsageFromEstimate(promptTokens: number, outputChars: number, cacheReadTokens?: number): OpenAiUsage;
28
+ export declare function cursorUsageCountersFromSdk(raw: OpenAiUsage | undefined): CursorUsageCounters | undefined;
21
29
  /**
22
- * Cursor SDK usage is session-cumulative, while Claude Code needs per-request
23
- * usage. Use SDK usage only as a cache-read ratio and apply it to CCR's
24
- * current-request prompt estimate.
30
+ * Cursor SDK usage is per SDK turn, while Claude Code needs per-CCR-request
31
+ * usage. In bridge mode one SDK turn can span several parked host-tool request
32
+ * cycles. Use a terminal SDK witness only as a cache-read ratio for the CCR
33
+ * request that observes it; never attribute it to an earlier parked response.
34
+ *
35
+ * Kept for tests; prefer buildAccurateUsageFromSdk for turn-end reporting.
25
36
  */
26
37
  export declare function cacheReadFromSdkDelta(current: OpenAiUsage | undefined, previous: OpenAiUsage | undefined, promptTokens: number): number;
38
+ /**
39
+ * Build per-request OpenAI usage from the SDK turn-end usage message,
40
+ * normalized to the per-request prompt estimate but preserving Cursor's cache
41
+ * proportions (same math as cursor-opencode-provider
42
+ * buildLanguageModelV3UsageFromCounters). Falls back to chars/4-based
43
+ * completion tokens when SDK output is absent.
44
+ *
45
+ * When the runtime reports no usage for the turn (the SDK emits the usage
46
+ * message only "when the runtime reported usage"), prompt_tokens_details is
47
+ * omitted entirely so the cache-outcome tap reports "unknown" instead of a
48
+ * bogus "unexpected-miss" from a zero that was never measured.
49
+ */
50
+ export declare function buildAccurateUsageFromSdk(sdkRaw: OpenAiUsage | undefined, promptTokens: number, outputChars: number, priorRaw?: OpenAiUsage | undefined): OpenAiUsage;
27
51
  /** Map SDK TokenUsage / usage message into OpenAI shape (diagnostics only). */
28
52
  export declare function usageFromSdk(message: any): OpenAiUsage | undefined;