@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.
- package/README.md +2 -1
- package/dist/cjs/server.cjs +232 -222
- package/dist/cjs/server.cjs.map +4 -4
- package/dist/cursor-sdk/auth-exchange-cache.d.ts +23 -0
- package/dist/cursor-sdk/events-to-sse.d.ts +3 -3
- package/dist/cursor-sdk/lifecycle-planner.d.ts +21 -4
- package/dist/cursor-sdk/prompt.d.ts +10 -0
- package/dist/cursor-sdk/session.d.ts +44 -0
- package/dist/cursor-sdk/shared.d.ts +7 -0
- package/dist/cursor-sdk/turn-output.d.ts +3 -0
- package/dist/cursor-sdk/usage.d.ts +27 -3
- package/dist/esm/server.mjs +232 -222
- package/dist/esm/server.mjs.map +4 -4
- package/dist/routing/protocol-endpoints.d.ts +14 -0
- package/dist/server.d.ts +1 -1
- package/dist/session-registry.d.ts +36 -0
- package/dist/tests/anthropic.message-start-usage.test.d.ts +1 -0
- package/dist/tests/cache-outcome.d.ts +1 -0
- package/dist/tests/cross-protocol.matrix.d.ts +1 -0
- package/dist/tests/cursor-sdk.auth-exchange-cache.d.ts +1 -0
- package/dist/tests/cursor-sdk.shared.d.ts +1 -0
- package/dist/tests/cursor-sdk.tool-id-alias.d.ts +1 -0
- package/dist/tests/responses.encrypted-content-cache.d.ts +1 -0
- package/dist/tests/session-registry.d.ts +1 -0
- package/dist/tests/tool-content.multimodal.d.ts +1 -0
- package/dist/tests/wire-keep.d.ts +1 -0
- package/dist/transformer/codex.transformer.d.ts +20 -34
- package/dist/transformer/openai.responses.transformer.d.ts +1 -1
- package/dist/transformer/opencode-headers.transformer.d.ts +1 -2
- package/dist/utils/cache-outcome.d.ts +79 -0
- package/dist/utils/cache-prefix-debug.d.ts +21 -1
- package/dist/utils/cacheControl.d.ts +8 -0
- package/dist/utils/deepseek.util.d.ts +1 -1
- package/dist/utils/message-debug.d.ts +32 -4
- package/dist/utils/nested-agent.d.ts +26 -0
- package/dist/utils/openai.responses.util.d.ts +11 -0
- package/dist/utils/request-latency.d.ts +4 -0
- package/dist/utils/responses.encrypted-content-cache.d.ts +42 -0
- package/dist/utils/sse-debug-tap.d.ts +12 -2
- package/dist/utils/stream-peek.d.ts +20 -0
- package/dist/utils/tool-content.d.ts +54 -0
- package/dist/utils/transformer-plan.d.ts +9 -0
- package/dist/utils/vertex-claude.util.d.ts +1 -1
- 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
|
-
|
|
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:
|
|
67
|
+
reason: CursorLifecycleIncrementalReason;
|
|
61
68
|
} | CursorLifecycleRetirementPlan;
|
|
62
69
|
/**
|
|
63
|
-
*
|
|
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
|
|
23
|
-
* usage.
|
|
24
|
-
*
|
|
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;
|