opencode-cursor-proxy 1.0.1
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/LICENSE +21 -0
- package/README.md +139 -0
- package/README.zh-CN.md +136 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api/agent-service.d.ts +136 -0
- package/dist/lib/api/agent-service.js +938 -0
- package/dist/lib/api/agent-service.js.map +1 -0
- package/dist/lib/api/ai-service.d.ts +26 -0
- package/dist/lib/api/ai-service.js +38 -0
- package/dist/lib/api/ai-service.js.map +1 -0
- package/dist/lib/api/cursor-client.d.ts +119 -0
- package/dist/lib/api/cursor-client.js +511 -0
- package/dist/lib/api/cursor-client.js.map +1 -0
- package/dist/lib/api/cursor-models.d.ts +13 -0
- package/dist/lib/api/cursor-models.js +34 -0
- package/dist/lib/api/cursor-models.js.map +1 -0
- package/dist/lib/api/openai-compat.d.ts +10 -0
- package/dist/lib/api/openai-compat.js +262 -0
- package/dist/lib/api/openai-compat.js.map +1 -0
- package/dist/lib/api/proto/agent-messages.d.ts +25 -0
- package/dist/lib/api/proto/agent-messages.js +132 -0
- package/dist/lib/api/proto/agent-messages.js.map +1 -0
- package/dist/lib/api/proto/bidi.d.ts +17 -0
- package/dist/lib/api/proto/bidi.js +24 -0
- package/dist/lib/api/proto/bidi.js.map +1 -0
- package/dist/lib/api/proto/decoding.d.ts +19 -0
- package/dist/lib/api/proto/decoding.js +118 -0
- package/dist/lib/api/proto/decoding.js.map +1 -0
- package/dist/lib/api/proto/encoding.d.ts +64 -0
- package/dist/lib/api/proto/encoding.js +180 -0
- package/dist/lib/api/proto/encoding.js.map +1 -0
- package/dist/lib/api/proto/exec.d.ts +12 -0
- package/dist/lib/api/proto/exec.js +383 -0
- package/dist/lib/api/proto/exec.js.map +1 -0
- package/dist/lib/api/proto/index.d.ts +13 -0
- package/dist/lib/api/proto/index.js +10 -0
- package/dist/lib/api/proto/index.js.map +1 -0
- package/dist/lib/api/proto/interaction.d.ts +15 -0
- package/dist/lib/api/proto/interaction.js +99 -0
- package/dist/lib/api/proto/interaction.js.map +1 -0
- package/dist/lib/api/proto/kv.d.ts +52 -0
- package/dist/lib/api/proto/kv.js +156 -0
- package/dist/lib/api/proto/kv.js.map +1 -0
- package/dist/lib/api/proto/tool-calls.d.ts +9 -0
- package/dist/lib/api/proto/tool-calls.js +144 -0
- package/dist/lib/api/proto/tool-calls.js.map +1 -0
- package/dist/lib/api/proto/types.d.ts +201 -0
- package/dist/lib/api/proto/types.js +10 -0
- package/dist/lib/api/proto/types.js.map +1 -0
- package/dist/lib/auth/helpers.d.ts +40 -0
- package/dist/lib/auth/helpers.js +103 -0
- package/dist/lib/auth/helpers.js.map +1 -0
- package/dist/lib/auth/index.d.ts +7 -0
- package/dist/lib/auth/index.js +10 -0
- package/dist/lib/auth/index.js.map +1 -0
- package/dist/lib/auth/login.d.ts +55 -0
- package/dist/lib/auth/login.js +184 -0
- package/dist/lib/auth/login.js.map +1 -0
- package/dist/lib/config.d.ts +153 -0
- package/dist/lib/config.js +182 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/openai-compat/handler.d.ts +40 -0
- package/dist/lib/openai-compat/handler.js +808 -0
- package/dist/lib/openai-compat/handler.js.map +1 -0
- package/dist/lib/openai-compat/index.d.ts +9 -0
- package/dist/lib/openai-compat/index.js +13 -0
- package/dist/lib/openai-compat/index.js.map +1 -0
- package/dist/lib/openai-compat/types.d.ts +127 -0
- package/dist/lib/openai-compat/types.js +6 -0
- package/dist/lib/openai-compat/types.js.map +1 -0
- package/dist/lib/openai-compat/utils.d.ts +143 -0
- package/dist/lib/openai-compat/utils.js +348 -0
- package/dist/lib/openai-compat/utils.js.map +1 -0
- package/dist/lib/session-reuse.d.ts +88 -0
- package/dist/lib/session-reuse.js +198 -0
- package/dist/lib/session-reuse.js.map +1 -0
- package/dist/lib/storage.d.ts +55 -0
- package/dist/lib/storage.js +159 -0
- package/dist/lib/storage.js.map +1 -0
- package/dist/lib/utils/cache.d.ts +131 -0
- package/dist/lib/utils/cache.js +297 -0
- package/dist/lib/utils/cache.js.map +1 -0
- package/dist/lib/utils/fetch.d.ts +84 -0
- package/dist/lib/utils/fetch.js +261 -0
- package/dist/lib/utils/fetch.js.map +1 -0
- package/dist/lib/utils/index.d.ts +13 -0
- package/dist/lib/utils/index.js +22 -0
- package/dist/lib/utils/index.js.map +1 -0
- package/dist/lib/utils/jwt.d.ts +40 -0
- package/dist/lib/utils/jwt.js +102 -0
- package/dist/lib/utils/jwt.js.map +1 -0
- package/dist/lib/utils/logger.d.ts +107 -0
- package/dist/lib/utils/logger.js +227 -0
- package/dist/lib/utils/logger.js.map +1 -0
- package/dist/lib/utils/model-resolver.d.ts +49 -0
- package/dist/lib/utils/model-resolver.js +503 -0
- package/dist/lib/utils/model-resolver.js.map +1 -0
- package/dist/lib/utils/request-pool.d.ts +38 -0
- package/dist/lib/utils/request-pool.js +105 -0
- package/dist/lib/utils/request-pool.js.map +1 -0
- package/dist/lib/utils/request-transformer.d.ts +87 -0
- package/dist/lib/utils/request-transformer.js +154 -0
- package/dist/lib/utils/request-transformer.js.map +1 -0
- package/dist/lib/utils/tokenizer.d.ts +14 -0
- package/dist/lib/utils/tokenizer.js +76 -0
- package/dist/lib/utils/tokenizer.js.map +1 -0
- package/dist/plugin/index.d.ts +8 -0
- package/dist/plugin/index.js +9 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/plugin.d.ts +21 -0
- package/dist/plugin/plugin.js +309 -0
- package/dist/plugin/plugin.js.map +1 -0
- package/dist/plugin/types.d.ts +120 -0
- package/dist/plugin/types.js +7 -0
- package/dist/plugin/types.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.js +95 -0
- package/dist/server.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
export declare enum AgentMode {
|
|
2
|
+
UNSPECIFIED = 0,
|
|
3
|
+
AGENT = 1,
|
|
4
|
+
ASK = 2,
|
|
5
|
+
PLAN = 3,
|
|
6
|
+
DEBUG = 4,
|
|
7
|
+
TRIAGE = 5
|
|
8
|
+
}
|
|
9
|
+
export interface OpenAIToolDefinition {
|
|
10
|
+
type: "function";
|
|
11
|
+
function: {
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
parameters?: Record<string, unknown>;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface McpExecRequest {
|
|
18
|
+
id: number;
|
|
19
|
+
execId?: string;
|
|
20
|
+
name: string;
|
|
21
|
+
args: Record<string, unknown>;
|
|
22
|
+
toolCallId: string;
|
|
23
|
+
providerIdentifier: string;
|
|
24
|
+
toolName: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ShellExecRequest {
|
|
27
|
+
type: 'shell';
|
|
28
|
+
id: number;
|
|
29
|
+
execId?: string;
|
|
30
|
+
command: string;
|
|
31
|
+
cwd?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface LsExecRequest {
|
|
34
|
+
type: 'ls';
|
|
35
|
+
id: number;
|
|
36
|
+
execId?: string;
|
|
37
|
+
path: string;
|
|
38
|
+
}
|
|
39
|
+
export interface RequestContextExecRequest {
|
|
40
|
+
type: 'request_context';
|
|
41
|
+
id: number;
|
|
42
|
+
execId?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface ReadExecRequest {
|
|
45
|
+
type: 'read';
|
|
46
|
+
id: number;
|
|
47
|
+
execId?: string;
|
|
48
|
+
path: string;
|
|
49
|
+
}
|
|
50
|
+
export interface GrepExecRequest {
|
|
51
|
+
type: 'grep';
|
|
52
|
+
id: number;
|
|
53
|
+
execId?: string;
|
|
54
|
+
pattern: string;
|
|
55
|
+
path?: string;
|
|
56
|
+
glob?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface WriteExecRequest {
|
|
59
|
+
type: 'write';
|
|
60
|
+
id: number;
|
|
61
|
+
execId?: string;
|
|
62
|
+
path: string;
|
|
63
|
+
fileText: string;
|
|
64
|
+
toolCallId?: string;
|
|
65
|
+
returnFileContentAfterWrite?: boolean;
|
|
66
|
+
fileBytes?: Uint8Array;
|
|
67
|
+
}
|
|
68
|
+
export type ExecRequest = (McpExecRequest & {
|
|
69
|
+
type: 'mcp';
|
|
70
|
+
}) | ShellExecRequest | LsExecRequest | RequestContextExecRequest | ReadExecRequest | GrepExecRequest | WriteExecRequest;
|
|
71
|
+
export interface KvServerMessage {
|
|
72
|
+
id: number;
|
|
73
|
+
messageType: 'get_blob_args' | 'set_blob_args' | 'unknown';
|
|
74
|
+
blobId?: Uint8Array;
|
|
75
|
+
blobData?: Uint8Array;
|
|
76
|
+
}
|
|
77
|
+
export interface ToolCallInfo {
|
|
78
|
+
callId: string;
|
|
79
|
+
modelCallId?: string;
|
|
80
|
+
toolType: string;
|
|
81
|
+
name: string;
|
|
82
|
+
arguments: string;
|
|
83
|
+
}
|
|
84
|
+
export interface ParsedToolCall {
|
|
85
|
+
toolType: string;
|
|
86
|
+
name: string;
|
|
87
|
+
arguments: Record<string, unknown>;
|
|
88
|
+
}
|
|
89
|
+
export interface ParsedToolCallStarted {
|
|
90
|
+
callId: string;
|
|
91
|
+
modelCallId: string;
|
|
92
|
+
toolCall: ParsedToolCall | null;
|
|
93
|
+
}
|
|
94
|
+
export interface ParsedPartialToolCall {
|
|
95
|
+
callId: string;
|
|
96
|
+
modelCallId: string;
|
|
97
|
+
argsTextDelta: string;
|
|
98
|
+
toolCall: ParsedToolCall | null;
|
|
99
|
+
}
|
|
100
|
+
export interface AgentStreamChunk {
|
|
101
|
+
type: "text" | "thinking" | "token" | "checkpoint" | "done" | "error" | "tool_call_started" | "tool_call_completed" | "partial_tool_call" | "exec_request" | "heartbeat" | "exec_server_abort" | "interaction_query" | "kv_blob_assistant";
|
|
102
|
+
content?: string;
|
|
103
|
+
error?: string;
|
|
104
|
+
toolCall?: ToolCallInfo;
|
|
105
|
+
partialArgs?: string;
|
|
106
|
+
execRequest?: ExecRequest;
|
|
107
|
+
queryId?: number;
|
|
108
|
+
queryType?: string;
|
|
109
|
+
blobContent?: string;
|
|
110
|
+
}
|
|
111
|
+
export interface ChatTimingMetrics {
|
|
112
|
+
requestStart: number;
|
|
113
|
+
messageBuildMs?: number;
|
|
114
|
+
sseConnectionMs?: number;
|
|
115
|
+
firstBidiAppendMs?: number;
|
|
116
|
+
firstChunkMs?: number;
|
|
117
|
+
firstTextMs?: number;
|
|
118
|
+
firstToolCallMs?: number;
|
|
119
|
+
turnEndedMs?: number;
|
|
120
|
+
totalMs?: number;
|
|
121
|
+
chunkCount: number;
|
|
122
|
+
textChunks: number;
|
|
123
|
+
toolCalls: number;
|
|
124
|
+
execRequests: number;
|
|
125
|
+
kvMessages: number;
|
|
126
|
+
heartbeats: number;
|
|
127
|
+
}
|
|
128
|
+
export interface AgentServiceOptions {
|
|
129
|
+
baseUrl?: string;
|
|
130
|
+
privacyMode?: boolean;
|
|
131
|
+
workspacePath?: string;
|
|
132
|
+
}
|
|
133
|
+
export interface AgentChatRequest {
|
|
134
|
+
message: string;
|
|
135
|
+
model?: string;
|
|
136
|
+
mode?: AgentMode;
|
|
137
|
+
conversationId?: string;
|
|
138
|
+
tools?: OpenAIToolDefinition[];
|
|
139
|
+
}
|
|
140
|
+
export interface McpResult {
|
|
141
|
+
success?: {
|
|
142
|
+
content: string;
|
|
143
|
+
isError?: boolean;
|
|
144
|
+
};
|
|
145
|
+
error?: string;
|
|
146
|
+
}
|
|
147
|
+
export interface ShellOutcome {
|
|
148
|
+
command: string;
|
|
149
|
+
cwd: string;
|
|
150
|
+
stdout: string;
|
|
151
|
+
stderr: string;
|
|
152
|
+
exitCode: number;
|
|
153
|
+
executionTimeMs?: number;
|
|
154
|
+
}
|
|
155
|
+
export interface WriteResult {
|
|
156
|
+
success?: {
|
|
157
|
+
path: string;
|
|
158
|
+
linesCreated: number;
|
|
159
|
+
fileSize: number;
|
|
160
|
+
fileContentAfterWrite?: string;
|
|
161
|
+
};
|
|
162
|
+
error?: {
|
|
163
|
+
path: string;
|
|
164
|
+
error: string;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export interface BlobAnalysis {
|
|
168
|
+
type: 'json' | 'text' | 'protobuf' | 'binary';
|
|
169
|
+
json?: unknown;
|
|
170
|
+
text?: string;
|
|
171
|
+
protoFields?: Array<{
|
|
172
|
+
num: number;
|
|
173
|
+
wire: number;
|
|
174
|
+
size: number;
|
|
175
|
+
text?: string;
|
|
176
|
+
}>;
|
|
177
|
+
}
|
|
178
|
+
export interface ParsedInteractionUpdate {
|
|
179
|
+
text: string | null;
|
|
180
|
+
thinking: string | null;
|
|
181
|
+
isComplete: boolean;
|
|
182
|
+
isHeartbeat: boolean;
|
|
183
|
+
toolCallStarted: {
|
|
184
|
+
callId: string;
|
|
185
|
+
modelCallId: string;
|
|
186
|
+
toolType: string;
|
|
187
|
+
name: string;
|
|
188
|
+
arguments: string;
|
|
189
|
+
} | null;
|
|
190
|
+
toolCallCompleted: {
|
|
191
|
+
callId: string;
|
|
192
|
+
modelCallId: string;
|
|
193
|
+
toolType: string;
|
|
194
|
+
name: string;
|
|
195
|
+
arguments: string;
|
|
196
|
+
} | null;
|
|
197
|
+
partialToolCall: {
|
|
198
|
+
callId: string;
|
|
199
|
+
argsTextDelta: string;
|
|
200
|
+
} | null;
|
|
201
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export var AgentMode;
|
|
2
|
+
(function (AgentMode) {
|
|
3
|
+
AgentMode[AgentMode["UNSPECIFIED"] = 0] = "UNSPECIFIED";
|
|
4
|
+
AgentMode[AgentMode["AGENT"] = 1] = "AGENT";
|
|
5
|
+
AgentMode[AgentMode["ASK"] = 2] = "ASK";
|
|
6
|
+
AgentMode[AgentMode["PLAN"] = 3] = "PLAN";
|
|
7
|
+
AgentMode[AgentMode["DEBUG"] = 4] = "DEBUG";
|
|
8
|
+
AgentMode[AgentMode["TRIAGE"] = 5] = "TRIAGE";
|
|
9
|
+
})(AgentMode || (AgentMode = {}));
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/lib/api/proto/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,SAOX;AAPD,WAAY,SAAS;IACnB,uDAAe,CAAA;IACf,2CAAS,CAAA;IACT,uCAAO,CAAA;IACP,yCAAQ,CAAA;IACR,2CAAS,CAAA;IACT,6CAAU,CAAA;AACZ,CAAC,EAPW,SAAS,KAAT,SAAS,QAOpB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Helper Functions
|
|
3
|
+
*
|
|
4
|
+
* Higher-level authentication functions that combine storage and login
|
|
5
|
+
* functionality for common auth operations.
|
|
6
|
+
*/
|
|
7
|
+
import { type CredentialManager, type StoredCredentials } from "../storage";
|
|
8
|
+
/**
|
|
9
|
+
* Refresh an access token using the refresh token
|
|
10
|
+
*/
|
|
11
|
+
export declare function refreshAccessToken(refreshToken: string, endpoint?: string): Promise<{
|
|
12
|
+
accessToken: string;
|
|
13
|
+
refreshToken: string;
|
|
14
|
+
} | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Get a valid access token, refreshing if necessary
|
|
17
|
+
*/
|
|
18
|
+
export declare function getValidAccessToken(credentialManager: CredentialManager, endpoint?: string): Promise<string | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Authenticate using an API key
|
|
21
|
+
*/
|
|
22
|
+
export declare function authenticateWithApiKey(credentialManager: CredentialManager, apiKey: string, options?: {
|
|
23
|
+
endpoint?: string;
|
|
24
|
+
}): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Authenticate using a direct token (no refresh token)
|
|
27
|
+
*/
|
|
28
|
+
export declare function authenticateWithToken(credentialManager: CredentialManager, token: string): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Check if the user is authenticated with a valid token
|
|
31
|
+
*/
|
|
32
|
+
export declare function isAuthenticated(credentialManager: CredentialManager): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Get stored credentials
|
|
35
|
+
*/
|
|
36
|
+
export declare function getStoredCredentials(credentialManager: CredentialManager): Promise<StoredCredentials>;
|
|
37
|
+
/**
|
|
38
|
+
* Clear all credentials
|
|
39
|
+
*/
|
|
40
|
+
export declare function clearCredentials(credentialManager: CredentialManager): Promise<void>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Helper Functions
|
|
3
|
+
*
|
|
4
|
+
* Higher-level authentication functions that combine storage and login
|
|
5
|
+
* functionality for common auth operations.
|
|
6
|
+
*/
|
|
7
|
+
import { isTokenExpiringSoon, isTokenExpired } from "../utils/jwt";
|
|
8
|
+
import {} from "../storage";
|
|
9
|
+
import { LoginManager, CURSOR_API_BASE_URL } from "./login";
|
|
10
|
+
// --- Token Refresh ---
|
|
11
|
+
const REFRESH_ENDPOINT = "/auth/refresh";
|
|
12
|
+
/**
|
|
13
|
+
* Refresh an access token using the refresh token
|
|
14
|
+
*/
|
|
15
|
+
export async function refreshAccessToken(refreshToken, endpoint = CURSOR_API_BASE_URL) {
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(`${endpoint}${REFRESH_ENDPOINT}`, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
Authorization: `Bearer ${refreshToken}`,
|
|
22
|
+
},
|
|
23
|
+
body: JSON.stringify({}),
|
|
24
|
+
});
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const result = await response.json();
|
|
29
|
+
if (typeof result === "object" &&
|
|
30
|
+
result !== null &&
|
|
31
|
+
"accessToken" in result &&
|
|
32
|
+
"refreshToken" in result) {
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Refresh failed
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
// --- High-Level Auth Functions ---
|
|
42
|
+
/**
|
|
43
|
+
* Get a valid access token, refreshing if necessary
|
|
44
|
+
*/
|
|
45
|
+
export async function getValidAccessToken(credentialManager, endpoint = CURSOR_API_BASE_URL) {
|
|
46
|
+
const accessToken = await credentialManager.getAccessToken();
|
|
47
|
+
// Check if we have a valid token
|
|
48
|
+
if (accessToken && !isTokenExpiringSoon(accessToken)) {
|
|
49
|
+
return accessToken;
|
|
50
|
+
}
|
|
51
|
+
// Try to refresh
|
|
52
|
+
const refreshToken = await credentialManager.getRefreshToken();
|
|
53
|
+
if (refreshToken) {
|
|
54
|
+
const refreshed = await refreshAccessToken(refreshToken, endpoint);
|
|
55
|
+
if (refreshed) {
|
|
56
|
+
await credentialManager.setAuthentication(refreshed.accessToken, refreshed.refreshToken);
|
|
57
|
+
return refreshed.accessToken;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Return possibly expired token (let the API reject if needed)
|
|
61
|
+
return accessToken ?? null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Authenticate using an API key
|
|
65
|
+
*/
|
|
66
|
+
export async function authenticateWithApiKey(credentialManager, apiKey, options) {
|
|
67
|
+
const loginManager = new LoginManager();
|
|
68
|
+
const result = await loginManager.loginWithApiKey(apiKey, options);
|
|
69
|
+
if (result) {
|
|
70
|
+
await credentialManager.setAuthentication(result.accessToken, result.refreshToken, apiKey);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Authenticate using a direct token (no refresh token)
|
|
77
|
+
*/
|
|
78
|
+
export async function authenticateWithToken(credentialManager, token) {
|
|
79
|
+
// Store token without refresh token
|
|
80
|
+
await credentialManager.setAuthentication(token, "");
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if the user is authenticated with a valid token
|
|
84
|
+
*/
|
|
85
|
+
export async function isAuthenticated(credentialManager) {
|
|
86
|
+
const token = await credentialManager.getAccessToken();
|
|
87
|
+
if (!token)
|
|
88
|
+
return false;
|
|
89
|
+
return !isTokenExpired(token);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get stored credentials
|
|
93
|
+
*/
|
|
94
|
+
export async function getStoredCredentials(credentialManager) {
|
|
95
|
+
return credentialManager.getAllCredentials();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Clear all credentials
|
|
99
|
+
*/
|
|
100
|
+
export async function clearCredentials(credentialManager) {
|
|
101
|
+
return credentialManager.clearAuthentication();
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/lib/auth/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Module
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all auth-related functionality
|
|
5
|
+
*/
|
|
6
|
+
export { refreshAccessToken, getValidAccessToken, authenticateWithApiKey, authenticateWithToken, isAuthenticated, getStoredCredentials, clearCredentials, } from "./helpers";
|
|
7
|
+
export { LoginManager, CURSOR_API_BASE_URL, CURSOR_WEBSITE_URL, POLLING_ENDPOINT, generateAuthParams, openBrowser, type AuthResult, type AuthParams, type LoginMetadata, } from "./login";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Module
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all auth-related functionality
|
|
5
|
+
*/
|
|
6
|
+
// Re-export helpers
|
|
7
|
+
export { refreshAccessToken, getValidAccessToken, authenticateWithApiKey, authenticateWithToken, isAuthenticated, getStoredCredentials, clearCredentials, } from "./helpers";
|
|
8
|
+
// Re-export login manager and related
|
|
9
|
+
export { LoginManager, CURSOR_API_BASE_URL, CURSOR_WEBSITE_URL, POLLING_ENDPOINT, generateAuthParams, openBrowser, } from "./login";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/auth/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oBAAoB;AACpB,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAEnB,sCAAsC;AACtC,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,GAIZ,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth PKCE login flow and API key authentication
|
|
5
|
+
* for Cursor's authentication system.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CURSOR_WEBSITE_URL = "https://cursor.com";
|
|
8
|
+
export declare const CURSOR_API_BASE_URL = "https://api2.cursor.sh";
|
|
9
|
+
export declare const POLLING_ENDPOINT = "https://api2.cursor.sh/auth/poll";
|
|
10
|
+
export interface AuthResult {
|
|
11
|
+
accessToken: string;
|
|
12
|
+
refreshToken: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AuthParams {
|
|
15
|
+
uuid: string;
|
|
16
|
+
challenge: string;
|
|
17
|
+
verifier: string;
|
|
18
|
+
loginUrl: string;
|
|
19
|
+
}
|
|
20
|
+
export interface LoginMetadata {
|
|
21
|
+
uuid: string;
|
|
22
|
+
verifier: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generate authentication parameters (PKCE flow)
|
|
26
|
+
*/
|
|
27
|
+
export declare function generateAuthParams(): AuthParams;
|
|
28
|
+
/**
|
|
29
|
+
* Open a URL in the default browser
|
|
30
|
+
*/
|
|
31
|
+
export declare function openBrowser(url: string): Promise<void>;
|
|
32
|
+
export declare class LoginManager {
|
|
33
|
+
/**
|
|
34
|
+
* Start the OAuth login flow
|
|
35
|
+
* Returns metadata needed for polling and the URL to open in browser
|
|
36
|
+
*/
|
|
37
|
+
startLogin(): {
|
|
38
|
+
metadata: LoginMetadata;
|
|
39
|
+
loginUrl: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Poll for authentication result
|
|
43
|
+
* This waits for the user to complete the browser login
|
|
44
|
+
*/
|
|
45
|
+
waitForResult(metadata: LoginMetadata, options?: {
|
|
46
|
+
maxAttempts?: number;
|
|
47
|
+
onProgress?: (attempt: number) => void;
|
|
48
|
+
}): Promise<AuthResult | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Exchange API key for access/refresh tokens
|
|
51
|
+
*/
|
|
52
|
+
loginWithApiKey(apiKey: string, options?: {
|
|
53
|
+
endpoint?: string;
|
|
54
|
+
}): Promise<AuthResult | null>;
|
|
55
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles the OAuth PKCE login flow and API key authentication
|
|
5
|
+
* for Cursor's authentication system.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
8
|
+
import { platform } from "node:os";
|
|
9
|
+
import { exec } from "node:child_process";
|
|
10
|
+
// --- Configuration ---
|
|
11
|
+
export const CURSOR_WEBSITE_URL = "https://cursor.com";
|
|
12
|
+
export const CURSOR_API_BASE_URL = "https://api2.cursor.sh";
|
|
13
|
+
export const POLLING_ENDPOINT = `${CURSOR_API_BASE_URL}/auth/poll`;
|
|
14
|
+
// --- Helper Functions ---
|
|
15
|
+
/**
|
|
16
|
+
* Base64 URL encode a buffer (RFC 4648)
|
|
17
|
+
*/
|
|
18
|
+
function base64URLEncode(buffer) {
|
|
19
|
+
return buffer
|
|
20
|
+
.toString("base64")
|
|
21
|
+
.replace(/\+/g, "-")
|
|
22
|
+
.replace(/\//g, "_")
|
|
23
|
+
.replace(/=/g, "");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate a SHA-256 hash of the input string
|
|
27
|
+
*/
|
|
28
|
+
function sha256(data) {
|
|
29
|
+
return createHash("sha256").update(data).digest();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate authentication parameters (PKCE flow)
|
|
33
|
+
*/
|
|
34
|
+
export function generateAuthParams() {
|
|
35
|
+
// Generate a 32-byte random verifier
|
|
36
|
+
const verifierArray = randomBytes(32);
|
|
37
|
+
const verifier = base64URLEncode(verifierArray);
|
|
38
|
+
// Generate challenge by SHA-256 hashing the verifier
|
|
39
|
+
const challengeHash = sha256(verifier);
|
|
40
|
+
const challenge = base64URLEncode(challengeHash);
|
|
41
|
+
// Generate a UUID
|
|
42
|
+
const uuid = randomUUID();
|
|
43
|
+
// Construct the login URL
|
|
44
|
+
const loginUrl = `${CURSOR_WEBSITE_URL}/loginDeepControl?challenge=${challenge}&uuid=${uuid}&mode=login&redirectTarget=cli`;
|
|
45
|
+
return {
|
|
46
|
+
uuid,
|
|
47
|
+
challenge,
|
|
48
|
+
verifier,
|
|
49
|
+
loginUrl,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Open a URL in the default browser
|
|
54
|
+
*/
|
|
55
|
+
export function openBrowser(url) {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const command = platform() === "darwin"
|
|
58
|
+
? `open "${url}"`
|
|
59
|
+
: platform() === "win32"
|
|
60
|
+
? `start "" "${url}"`
|
|
61
|
+
: `xdg-open "${url}"`;
|
|
62
|
+
exec(command, (error) => {
|
|
63
|
+
if (error) {
|
|
64
|
+
reject(error);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
resolve();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Sleep for a given number of milliseconds
|
|
74
|
+
*/
|
|
75
|
+
function sleep(ms) {
|
|
76
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
77
|
+
}
|
|
78
|
+
// --- LoginManager ---
|
|
79
|
+
export class LoginManager {
|
|
80
|
+
/**
|
|
81
|
+
* Start the OAuth login flow
|
|
82
|
+
* Returns metadata needed for polling and the URL to open in browser
|
|
83
|
+
*/
|
|
84
|
+
startLogin() {
|
|
85
|
+
const authParams = generateAuthParams();
|
|
86
|
+
return {
|
|
87
|
+
metadata: {
|
|
88
|
+
uuid: authParams.uuid,
|
|
89
|
+
verifier: authParams.verifier,
|
|
90
|
+
},
|
|
91
|
+
loginUrl: authParams.loginUrl,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Poll for authentication result
|
|
96
|
+
* This waits for the user to complete the browser login
|
|
97
|
+
*/
|
|
98
|
+
async waitForResult(metadata, options) {
|
|
99
|
+
const maxAttempts = options?.maxAttempts ?? 150;
|
|
100
|
+
const baseDelay = 1000; // 1 second base delay
|
|
101
|
+
const maxDelay = 10000; // 10 seconds maximum delay
|
|
102
|
+
const backoffMultiplier = 1.2; // Gentle exponential backoff
|
|
103
|
+
const maxConsecutiveErrors = 3;
|
|
104
|
+
let consecutiveErrors = 0;
|
|
105
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
106
|
+
try {
|
|
107
|
+
const url = `${POLLING_ENDPOINT}?uuid=${metadata.uuid}&verifier=${metadata.verifier}`;
|
|
108
|
+
const response = await fetch(url, {
|
|
109
|
+
headers: {
|
|
110
|
+
"Content-Type": "application/json",
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
// 404 means authentication is still pending
|
|
114
|
+
if (response.status === 404) {
|
|
115
|
+
consecutiveErrors = 0;
|
|
116
|
+
const delay = Math.min(baseDelay * Math.pow(backoffMultiplier, attempt), maxDelay);
|
|
117
|
+
options?.onProgress?.(attempt);
|
|
118
|
+
await sleep(delay);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
// Check for other error statuses
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
consecutiveErrors++;
|
|
124
|
+
if (consecutiveErrors >= maxConsecutiveErrors) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const delay = Math.min(baseDelay * Math.pow(backoffMultiplier, attempt), maxDelay);
|
|
128
|
+
await sleep(delay);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
// Success case
|
|
132
|
+
consecutiveErrors = 0;
|
|
133
|
+
const authResult = await response.json();
|
|
134
|
+
if (typeof authResult === "object" &&
|
|
135
|
+
authResult !== null &&
|
|
136
|
+
"accessToken" in authResult &&
|
|
137
|
+
"refreshToken" in authResult) {
|
|
138
|
+
return authResult;
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
consecutiveErrors++;
|
|
144
|
+
if (consecutiveErrors >= maxConsecutiveErrors) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const delay = Math.min(baseDelay * Math.pow(backoffMultiplier, attempt), maxDelay);
|
|
148
|
+
await sleep(delay);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Exchange API key for access/refresh tokens
|
|
155
|
+
*/
|
|
156
|
+
async loginWithApiKey(apiKey, options) {
|
|
157
|
+
const baseUrl = options?.endpoint ?? CURSOR_API_BASE_URL;
|
|
158
|
+
try {
|
|
159
|
+
const response = await fetch(`${baseUrl}/auth/exchange_user_api_key`, {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: {
|
|
162
|
+
"Content-Type": "application/json",
|
|
163
|
+
Authorization: `Bearer ${apiKey}`,
|
|
164
|
+
},
|
|
165
|
+
body: JSON.stringify({}),
|
|
166
|
+
});
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const authResult = await response.json();
|
|
171
|
+
if (typeof authResult === "object" &&
|
|
172
|
+
authResult !== null &&
|
|
173
|
+
"accessToken" in authResult &&
|
|
174
|
+
"refreshToken" in authResult) {
|
|
175
|
+
return authResult;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// API key exchange error
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/lib/auth/login.ts"],"names":[],"mappings":"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"}
|