opencode-deepseek-auth 1.0.3 → 2.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/README.md +65 -15
- package/dist/plugin.d.ts +2 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +106 -165
- package/dist/plugin.js.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.js +43 -0
- package/src/deepseek/auth.js +93 -0
- package/src/plugin.js +166 -0
- package/src/plugin.ts +152 -207
- package/src/types.js +5 -0
- package/src/types.ts +5 -1
- package/test_auth_flow.js +122 -0
- package/test_auth_flow.ts +142 -0
package/src/plugin.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeepSeekAuthPlugin = void 0;
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
const auth_1 = require("./deepseek/auth");
|
|
6
|
+
/**
|
|
7
|
+
* Prepares the request to DeepSeek API by setting appropriate headers and transforming the payload
|
|
8
|
+
*/
|
|
9
|
+
function prepareDeepSeekRequest(input, init, accessToken) {
|
|
10
|
+
// Clone the original init to avoid mutating it
|
|
11
|
+
const transformedInit = { ...init };
|
|
12
|
+
// Set authorization header
|
|
13
|
+
transformedInit.headers = {
|
|
14
|
+
...transformedInit.headers,
|
|
15
|
+
...constants_1.DEEPSEEK_BASE_HEADERS,
|
|
16
|
+
"authorization": `Bearer ${accessToken}`
|
|
17
|
+
};
|
|
18
|
+
// Construct the request
|
|
19
|
+
const request = new Request(input, transformedInit);
|
|
20
|
+
return { request, init: transformedInit };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Transforms the DeepSeek API response to match expected format
|
|
24
|
+
*/
|
|
25
|
+
async function transformDeepSeekResponse(response) {
|
|
26
|
+
// For now, just pass through the response
|
|
27
|
+
return response;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validates if this is a DeepSeek API request
|
|
31
|
+
*/
|
|
32
|
+
function isDeepSeekRequest(input) {
|
|
33
|
+
const urlString = typeof input === 'string' ? input :
|
|
34
|
+
input instanceof URL ? input.toString() :
|
|
35
|
+
input.url || '';
|
|
36
|
+
return urlString.includes('deepseek.com') || urlString.includes('/v1/chat/completions');
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Registers the DeepSeek simple API key provider for Opencode.
|
|
40
|
+
* Users can configure their credentials using `opencode connect` with format: email:password or phone:password
|
|
41
|
+
*/
|
|
42
|
+
const DeepSeekAuthPlugin = async ({ client }) => ({
|
|
43
|
+
auth: {
|
|
44
|
+
provider: constants_1.DEEPSEEK_PROVIDER_ID,
|
|
45
|
+
loader: async (getAuth, provider) => {
|
|
46
|
+
const auth = await getAuth();
|
|
47
|
+
// This plugin only handles API key authentication
|
|
48
|
+
if (!auth?.apiKey) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
// Determine if this is a DeepSeek-specific authentication by checking the auth metadata
|
|
52
|
+
const isDeepSeekAuth = auth.provider === 'deepseek' || auth.type === 'deepseek-email-password';
|
|
53
|
+
const apiKeyValue = auth.apiKey;
|
|
54
|
+
// If explicitly marked as DeepSeek auth, process as email:password
|
|
55
|
+
if (isDeepSeekAuth) {
|
|
56
|
+
const parts = apiKeyValue.split(':');
|
|
57
|
+
if (parts.length === 2) {
|
|
58
|
+
const [identifier, password] = parts;
|
|
59
|
+
// Convert credentials to DeepSeek access token
|
|
60
|
+
const result = await (0, auth_1.loginDeepSeek)(identifier, password);
|
|
61
|
+
if (result.type !== "success") {
|
|
62
|
+
console.error(`Failed to authenticate with provided credentials: ${result.error}`);
|
|
63
|
+
throw new Error(`Authentication failed: ${result.error}`);
|
|
64
|
+
}
|
|
65
|
+
// Successfully obtained access token from credentials
|
|
66
|
+
const accessToken = result.access;
|
|
67
|
+
// If models are defined in the provider, set cost to 0 to indicate free usage
|
|
68
|
+
if (provider.models) {
|
|
69
|
+
for (const model of Object.values(provider.models)) {
|
|
70
|
+
if (model) {
|
|
71
|
+
model.cost = { input: 0, output: 0 };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
apiKey: accessToken,
|
|
77
|
+
async fetch(input, init) {
|
|
78
|
+
// If this isn't a DeepSeek request, pass through normally
|
|
79
|
+
if (!isDeepSeekRequest(input)) {
|
|
80
|
+
return fetch(input, init);
|
|
81
|
+
}
|
|
82
|
+
// Prepare the request with proper headers
|
|
83
|
+
const { request, init: transformedInit } = prepareDeepSeekRequest(input, init, accessToken);
|
|
84
|
+
// Make the API call
|
|
85
|
+
const response = await fetch(request, transformedInit);
|
|
86
|
+
// Transform response if needed
|
|
87
|
+
return transformDeepSeekResponse(response);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// If explicitly marked as DeepSeek auth but not in correct format, throw error
|
|
93
|
+
throw new Error(`DeepSeek authentication requires email:password format`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Otherwise, check if this looks like email:password format but isn't explicitly marked
|
|
98
|
+
const parts = apiKeyValue.split(':');
|
|
99
|
+
if (parts.length === 2) {
|
|
100
|
+
const [potentialIdentifier, potentialPassword] = parts;
|
|
101
|
+
// Heuristic: Check if it looks like an email or phone number format, and password seems reasonable
|
|
102
|
+
const isEmailFormat = potentialIdentifier.includes('@');
|
|
103
|
+
const isPhoneFormat = /^[0-9+\-\s()]+$/.test(potentialIdentifier.trim());
|
|
104
|
+
const isPasswordReasonableLength = potentialPassword.length >= 6;
|
|
105
|
+
// Only attempt email:password processing if both parts seem valid
|
|
106
|
+
if ((isEmailFormat || isPhoneFormat) && isPasswordReasonableLength) {
|
|
107
|
+
try {
|
|
108
|
+
// Try to use as email:password
|
|
109
|
+
const result = await (0, auth_1.loginDeepSeek)(potentialIdentifier, potentialPassword);
|
|
110
|
+
if (result.type === "success") {
|
|
111
|
+
// Successfully authenticated with email:password
|
|
112
|
+
const accessToken = result.access;
|
|
113
|
+
// If models are defined in the provider, set cost to 0 to indicate free usage
|
|
114
|
+
if (provider.models) {
|
|
115
|
+
for (const model of Object.values(provider.models)) {
|
|
116
|
+
if (model) {
|
|
117
|
+
model.cost = { input: 0, output: 0 };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
apiKey: accessToken,
|
|
123
|
+
async fetch(input, init) {
|
|
124
|
+
// If this isn't a DeepSeek request, pass through normally
|
|
125
|
+
if (!isDeepSeekRequest(input)) {
|
|
126
|
+
return fetch(input, init);
|
|
127
|
+
}
|
|
128
|
+
// Prepare the request with proper headers
|
|
129
|
+
const { request, init: transformedInit } = prepareDeepSeekRequest(input, init, accessToken);
|
|
130
|
+
// Make the API call
|
|
131
|
+
const response = await fetch(request, transformedInit);
|
|
132
|
+
// Transform response if needed
|
|
133
|
+
return transformDeepSeekResponse(response);
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.warn("Email:password authentication failed, treating as regular API key:", error);
|
|
140
|
+
// Fall through to treat as regular API key
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Default: treat as direct DeepSeek access token or other API key
|
|
145
|
+
const accessToken = apiKeyValue;
|
|
146
|
+
return {
|
|
147
|
+
apiKey: accessToken,
|
|
148
|
+
async fetch(input, init) {
|
|
149
|
+
// If this isn't a DeepSeek request, pass through normally
|
|
150
|
+
if (!isDeepSeekRequest(input)) {
|
|
151
|
+
return fetch(input, init);
|
|
152
|
+
}
|
|
153
|
+
// Prepare the request with proper headers
|
|
154
|
+
const { request, init: transformedInit } = prepareDeepSeekRequest(input, init, accessToken);
|
|
155
|
+
// Make the API call
|
|
156
|
+
const response = await fetch(request, transformedInit);
|
|
157
|
+
// Transform response if needed
|
|
158
|
+
return transformDeepSeekResponse(response);
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
methods: [], // Empty methods array since we're using config-based auth
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
exports.DeepSeekAuthPlugin = DeepSeekAuthPlugin;
|
package/src/plugin.ts
CHANGED
|
@@ -2,8 +2,6 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
|
|
3
3
|
import { DEEPSEEK_PROVIDER_ID, DEEPSEEK_REDIRECT_URI, DEEPSEEK_BASE_HEADERS } from "./constants";
|
|
4
4
|
import {
|
|
5
|
-
authorizeDeepSeek,
|
|
6
|
-
exchangeDeepSeek,
|
|
7
5
|
loginDeepSeek
|
|
8
6
|
} from "./deepseek/auth";
|
|
9
7
|
import type { DeepSeekTokenExchangeResult } from "./deepseek/auth";
|
|
@@ -13,64 +11,9 @@ import type {
|
|
|
13
11
|
LoaderResult,
|
|
14
12
|
PluginContext,
|
|
15
13
|
PluginResult,
|
|
16
|
-
Provider
|
|
17
|
-
FormConfig
|
|
14
|
+
Provider
|
|
18
15
|
} from "./types";
|
|
19
16
|
|
|
20
|
-
// Keep track of active tokens
|
|
21
|
-
const tokenCache = new Map<string, { token: string, expires: number, email: string }>();
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Checks if an access token has expired
|
|
25
|
-
*/
|
|
26
|
-
function accessTokenExpired(authRecord: any): boolean {
|
|
27
|
-
const now = Date.now();
|
|
28
|
-
return !authRecord.expires || now >= authRecord.expires - 60000; // 1 minute before expiry
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Determines if the auth method is OAuth-based
|
|
33
|
-
*/
|
|
34
|
-
function isOAuthAuth(auth: any): boolean {
|
|
35
|
-
return auth && auth.type === "oauth";
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Refresh access token if expired
|
|
40
|
-
*/
|
|
41
|
-
async function refreshAccessToken(authRecord: any, client: any): Promise<any | null> {
|
|
42
|
-
// DeepSeek doesn't have refresh tokens, so a full re-login is required
|
|
43
|
-
const email = authRecord.email;
|
|
44
|
-
const password = authRecord.password;
|
|
45
|
-
|
|
46
|
-
if (!email || !password) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const result = await loginDeepSeek(email, password);
|
|
51
|
-
if (result.type === "success") {
|
|
52
|
-
// Update the stored credentials
|
|
53
|
-
const newAuth = {
|
|
54
|
-
type: "oauth",
|
|
55
|
-
access: result.access,
|
|
56
|
-
expires: result.expires,
|
|
57
|
-
email: result.email || email,
|
|
58
|
-
password: password // Store password for refresh
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// Update cache
|
|
62
|
-
tokenCache.set(email, {
|
|
63
|
-
token: result.access,
|
|
64
|
-
expires: result.expires,
|
|
65
|
-
email: result.email || email
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
return newAuth;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
17
|
/**
|
|
75
18
|
* Prepares the request to DeepSeek API by setting appropriate headers and transforming the payload
|
|
76
19
|
*/
|
|
@@ -102,7 +45,6 @@ async function transformDeepSeekResponse(
|
|
|
102
45
|
response: Response
|
|
103
46
|
): Promise<Response> {
|
|
104
47
|
// For now, just pass through the response
|
|
105
|
-
// If needed, we could transform to match OpenAI format
|
|
106
48
|
return response;
|
|
107
49
|
}
|
|
108
50
|
|
|
@@ -117,160 +59,163 @@ function isDeepSeekRequest(input: Parameters<typeof fetch>[0]): boolean {
|
|
|
117
59
|
}
|
|
118
60
|
|
|
119
61
|
/**
|
|
120
|
-
* Registers the DeepSeek
|
|
121
|
-
*
|
|
62
|
+
* Registers the DeepSeek simple API key provider for Opencode.
|
|
63
|
+
* Users can configure their credentials using `opencode connect` with format: email:password or phone:password
|
|
122
64
|
*/
|
|
123
65
|
export const DeepSeekAuthPlugin = async (
|
|
124
66
|
{ client }: PluginContext,
|
|
125
67
|
): Promise<PluginResult> => ({
|
|
126
68
|
auth: {
|
|
127
69
|
provider: DEEPSEEK_PROVIDER_ID,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
70
|
+
loader: async (getAuth: GetAuth, provider: Provider): Promise<LoaderResult | null> => {
|
|
71
|
+
const auth = await getAuth();
|
|
72
|
+
|
|
73
|
+
// This plugin only handles API key authentication
|
|
74
|
+
if (!auth?.apiKey) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Determine if this is a DeepSeek-specific authentication by checking the auth metadata
|
|
79
|
+
const isDeepSeekAuth = auth.provider === 'deepseek' || auth.type === 'deepseek-email-password';
|
|
80
|
+
const apiKeyValue = auth.apiKey;
|
|
81
|
+
|
|
82
|
+
// If explicitly marked as DeepSeek auth, process as email:password
|
|
83
|
+
if (isDeepSeekAuth) {
|
|
84
|
+
const parts = apiKeyValue.split(':');
|
|
85
|
+
if (parts.length === 2) {
|
|
86
|
+
const [identifier, password] = parts;
|
|
87
|
+
|
|
88
|
+
// Convert credentials to DeepSeek access token
|
|
89
|
+
const result = await loginDeepSeek(identifier, password);
|
|
90
|
+
if (result.type !== "success") {
|
|
91
|
+
console.error(`Failed to authenticate with provided credentials: ${result.error}`);
|
|
92
|
+
throw new Error(`Authentication failed: ${result.error}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Successfully obtained access token from credentials
|
|
96
|
+
const accessToken = result.access;
|
|
97
|
+
|
|
98
|
+
// If models are defined in the provider, set cost to 0 to indicate free usage
|
|
99
|
+
if (provider.models) {
|
|
100
|
+
for (const model of Object.values(provider.models)) {
|
|
101
|
+
if (model) {
|
|
102
|
+
model.cost = { input: 0, output: 0 };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
apiKey: accessToken,
|
|
109
|
+
async fetch(input: Parameters<typeof fetch>[0], init?: RequestInit) {
|
|
110
|
+
// If this isn't a DeepSeek request, pass through normally
|
|
111
|
+
if (!isDeepSeekRequest(input)) {
|
|
112
|
+
return fetch(input as RequestInfo, init);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Prepare the request with proper headers
|
|
116
|
+
const { request, init: transformedInit } = prepareDeepSeekRequest(
|
|
117
|
+
input,
|
|
118
|
+
init,
|
|
119
|
+
accessToken
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// Make the API call
|
|
123
|
+
const response = await fetch(request, transformedInit);
|
|
124
|
+
|
|
125
|
+
// Transform response if needed
|
|
126
|
+
return transformDeepSeekResponse(response);
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
} else {
|
|
130
|
+
// If explicitly marked as DeepSeek auth but not in correct format, throw error
|
|
131
|
+
throw new Error(`DeepSeek authentication requires email:password format`);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
// Otherwise, check if this looks like email:password format but isn't explicitly marked
|
|
135
|
+
const parts = apiKeyValue.split(':');
|
|
136
|
+
if (parts.length === 2) {
|
|
137
|
+
const [potentialIdentifier, potentialPassword] = parts;
|
|
138
|
+
|
|
139
|
+
// Heuristic: Check if it looks like an email or phone number format, and password seems reasonable
|
|
140
|
+
const isEmailFormat = potentialIdentifier.includes('@');
|
|
141
|
+
const isPhoneFormat = /^[0-9+\-\s()]+$/.test(potentialIdentifier.trim());
|
|
142
|
+
const isPasswordReasonableLength = potentialPassword.length >= 6;
|
|
143
|
+
|
|
144
|
+
// Only attempt email:password processing if both parts seem valid
|
|
145
|
+
if ((isEmailFormat || isPhoneFormat) && isPasswordReasonableLength) {
|
|
146
|
+
try {
|
|
147
|
+
// Try to use as email:password
|
|
148
|
+
const result = await loginDeepSeek(potentialIdentifier, potentialPassword);
|
|
149
|
+
if (result.type === "success") {
|
|
150
|
+
// Successfully authenticated with email:password
|
|
151
|
+
const accessToken = result.access;
|
|
152
|
+
|
|
153
|
+
// If models are defined in the provider, set cost to 0 to indicate free usage
|
|
154
|
+
if (provider.models) {
|
|
155
|
+
for (const model of Object.values(provider.models)) {
|
|
156
|
+
if (model) {
|
|
157
|
+
model.cost = { input: 0, output: 0 };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
apiKey: accessToken,
|
|
164
|
+
async fetch(input: Parameters<typeof fetch>[0], init?: RequestInit) {
|
|
165
|
+
// If this isn't a DeepSeek request, pass through normally
|
|
166
|
+
if (!isDeepSeekRequest(input)) {
|
|
167
|
+
return fetch(input as RequestInfo, init);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Prepare the request with proper headers
|
|
171
|
+
const { request, init: transformedInit } = prepareDeepSeekRequest(
|
|
172
|
+
input,
|
|
173
|
+
init,
|
|
174
|
+
accessToken
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Make the API call
|
|
178
|
+
const response = await fetch(request, transformedInit);
|
|
179
|
+
|
|
180
|
+
// Transform response if needed
|
|
181
|
+
return transformDeepSeekResponse(response);
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.warn("Email:password authentication failed, treating as regular API key:", error);
|
|
187
|
+
// Fall through to treat as regular API key
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Default: treat as direct DeepSeek access token or other API key
|
|
193
|
+
const accessToken = apiKeyValue;
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
apiKey: accessToken,
|
|
197
|
+
async fetch(input: Parameters<typeof fetch>[0], init?: RequestInit) {
|
|
198
|
+
// If this isn't a DeepSeek request, pass through normally
|
|
199
|
+
if (!isDeepSeekRequest(input)) {
|
|
200
|
+
return fetch(input as RequestInfo, init);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Prepare the request with proper headers
|
|
204
|
+
const { request, init: transformedInit } = prepareDeepSeekRequest(
|
|
205
|
+
input,
|
|
206
|
+
init,
|
|
207
|
+
accessToken
|
|
208
|
+
);
|
|
251
209
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return result;
|
|
265
|
-
},
|
|
266
|
-
};
|
|
267
|
-
},
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
provider: DEEPSEEK_PROVIDER_ID,
|
|
271
|
-
label: "Enter credentials (email:password or phone:password)",
|
|
272
|
-
type: "api",
|
|
273
|
-
},
|
|
274
|
-
],
|
|
210
|
+
// Make the API call
|
|
211
|
+
const response = await fetch(request, transformedInit);
|
|
212
|
+
|
|
213
|
+
// Transform response if needed
|
|
214
|
+
return transformDeepSeekResponse(response);
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
methods: [], // Empty methods array since we're using config-based auth
|
|
275
220
|
},
|
|
276
221
|
});
|
package/src/types.js
ADDED
package/src/types.ts
CHANGED
|
@@ -26,7 +26,11 @@ export interface PluginResult {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export interface GetAuth {
|
|
29
|
-
(): Promise<
|
|
29
|
+
(): Promise<{
|
|
30
|
+
apiKey?: string;
|
|
31
|
+
type?: string; // Additional field to specify the type of authentication
|
|
32
|
+
provider?: string; // Additional field to specify which provider this auth is for
|
|
33
|
+
}>;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
export interface LoaderResult {
|