dsh-coding-subscription-oauth 0.6.2 → 0.6.3
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/CHANGELOG.md +222 -206
- package/CONTRIBUTING.md +129 -120
- package/INSTALL.md +218 -218
- package/LICENSE +19 -19
- package/NOTICE +11 -11
- package/README.de.md +289 -289
- package/README.es.md +290 -290
- package/README.fr.md +290 -290
- package/README.ja.md +290 -290
- package/README.ko.md +290 -290
- package/README.md +304 -304
- package/README.pt-BR.md +290 -290
- package/README.ru.md +290 -290
- package/README.zh-CN.md +302 -302
- package/compatibility/dsh-bom.json +0 -0
- package/cordis.patch.yml +13 -13
- package/docs/00-project-rules.md +212 -195
- package/docs/02-architecture.md +130 -130
- package/docs/02-architecture.zh-CN.md +130 -130
- package/lib/bin.js.map +1 -1
- package/lib/capability-settings.d.ts +8 -2
- package/lib/capability-settings.d.ts.map +1 -1
- package/lib/capability-tools.d.ts +7 -2
- package/lib/capability-tools.d.ts.map +1 -1
- package/lib/client.js +3 -3
- package/lib/client.js.map +2 -2
- package/lib/codex-images.d.ts +8 -0
- package/lib/codex-images.d.ts.map +1 -1
- package/lib/index.js +32 -7
- package/lib/index.js.map +2 -2
- package/lib/invariant.js.map +1 -1
- package/media/en/settings_accounts.png +0 -0
- package/media/en/settings_capabilities.png +0 -0
- package/media/en/settings_gateway.png +0 -0
- package/media/settings_accounts.png +0 -0
- package/media/settings_capabilities.png +0 -0
- package/media/settings_gateway.png +0 -0
- package/media/settings_overview.png +0 -0
- package/media/zh-CN/settings_accounts.png +0 -0
- package/media/zh-CN/settings_capabilities.png +0 -0
- package/media/zh-CN/settings_gateway.png +0 -0
- package/package.json +148 -148
- package/patches/dsh-agy@0.1.2.patch +25 -25
- package/scripts/release.mjs +186 -186
- package/scripts/smoke-deployed-routes.mjs +146 -146
- package/scripts/verify-deployed-catalog.mjs +87 -87
- package/src/adapter.ts +273 -273
- package/src/alias-adapter.ts +130 -130
- package/src/auth-routes.ts +921 -921
- package/src/auth.ts +67 -67
- package/src/bin.ts +350 -350
- package/src/capability-routes.ts +279 -279
- package/src/capability-runtime.ts +314 -313
- package/src/capability-settings.ts +671 -658
- package/src/capability-tools.ts +685 -666
- package/src/catalog.ts +271 -271
- package/src/client/GrokBuildSettings.tsx +771 -770
- package/src/client/api.ts +88 -88
- package/src/client/components/AboutTab.tsx +30 -30
- package/src/client/components/AccountsTab.tsx +241 -241
- package/src/client/components/Badge.tsx +33 -33
- package/src/client/components/CapabilitiesTab.tsx +265 -265
- package/src/client/components/CliPullPreview.tsx +116 -116
- package/src/client/components/CopyButton.tsx +57 -57
- package/src/client/components/GatewayTab.tsx +469 -469
- package/src/client/components/NoticeBanner.tsx +46 -46
- package/src/client/components/ProgressBar.tsx +53 -53
- package/src/client/components/ProviderCard.tsx +606 -606
- package/src/client/components/SettingsTabs.tsx +75 -75
- package/src/client/components/ToggleSwitch.tsx +71 -71
- package/src/client/constants.ts +230 -224
- package/src/client/display.ts +61 -61
- package/src/client/dshClientAdapter.ts +127 -127
- package/src/client/gatewaySnippets.ts +37 -37
- package/src/client/index.tsx +156 -156
- package/src/client/locales.ts +540 -535
- package/src/client/microStyles.ts +52 -52
- package/src/client/parsers.ts +398 -396
- package/src/client/styles.ts +325 -325
- package/src/client/types.ts +199 -197
- package/src/codex-http.ts +447 -447
- package/src/codex-images.ts +503 -485
- package/src/codex-model-capabilities.ts +320 -320
- package/src/codex-search.ts +245 -245
- package/src/codex-usage.ts +263 -263
- package/src/compatibility.ts +41 -41
- package/src/dsh-host-adapter.ts +173 -173
- package/src/gateway-anthropic-messages.ts +84 -84
- package/src/gateway-auth.ts +102 -102
- package/src/gateway-backend.ts +274 -274
- package/src/gateway-body.ts +49 -49
- package/src/gateway-config.ts +76 -76
- package/src/gateway-http.ts +104 -104
- package/src/gateway-openai-chat.ts +124 -124
- package/src/gateway-openai-responses.ts +53 -53
- package/src/gateway-parse.ts +224 -224
- package/src/gateway-protocol.ts +52 -52
- package/src/gateway-routes.ts +158 -158
- package/src/gateway.ts +258 -258
- package/src/grok-errors.ts +24 -24
- package/src/grok-imagine.ts +1627 -1627
- package/src/grok-import.ts +151 -151
- package/src/http-json.ts +82 -82
- package/src/ids.ts +59 -59
- package/src/imagine-routes.ts +463 -463
- package/src/index.ts +709 -709
- package/src/invariant.ts +17 -17
- package/src/kimi-errors.ts +26 -26
- package/src/media-store.ts +927 -927
- package/src/oauth-import-routes.ts +324 -324
- package/src/oauth-providers.ts +152 -152
- package/src/oauth-session.ts +183 -183
- package/src/oauth-sources.ts +1104 -1104
- package/src/oauth.ts +620 -620
- package/src/provider.ts +128 -128
- package/src/proxy.ts +11 -11
- package/src/redact.ts +72 -72
- package/src/session.ts +218 -218
- package/src/store.ts +217 -217
- package/src/web-origin.ts +296 -296
- package/src/web-routes.ts +38 -38
package/src/gateway-auth.ts
CHANGED
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Owner-only gateway API key file.
|
|
3
|
-
* @module dsh-coding-subscription-oauth/gateway-auth
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
7
|
-
import { mkdir } from "node:fs/promises";
|
|
8
|
-
import { dirname, join, resolve } from "node:path";
|
|
9
|
-
import { writeFileAtomic } from "@deepseek-ai/dsh-atomic-write";
|
|
10
|
-
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
11
|
-
import { GATEWAY_KEY_FILENAME } from "./ids.ts";
|
|
12
|
-
import { OAuthSourceError, readHardenedOAuthSourceFile } from "./oauth-sources.ts";
|
|
13
|
-
|
|
14
|
-
export { GATEWAY_KEY_FILENAME } from "./ids.ts";
|
|
15
|
-
|
|
16
|
-
const KEY_FORMAT_VERSION = 1;
|
|
17
|
-
|
|
18
|
-
export interface GatewayKeyDocument {
|
|
19
|
-
version: typeof KEY_FORMAT_VERSION;
|
|
20
|
-
apiKey: string;
|
|
21
|
-
enabled?: boolean;
|
|
22
|
-
port?: number;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function gatewayKeyPath(dshHome?: string): string {
|
|
26
|
-
return resolve(join(resolveDshHome(dshHome), GATEWAY_KEY_FILENAME));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function generateGatewayApiKey(): string {
|
|
30
|
-
return randomBytes(32).toString("base64url");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function gatewayKeysEqual(left: string, right: string): boolean {
|
|
34
|
-
const a = Buffer.from(left);
|
|
35
|
-
const b = Buffer.from(right);
|
|
36
|
-
return a.length === b.length && a.length > 0 && timingSafeEqual(a, b);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function maskGatewayApiKey(apiKey: string): string {
|
|
40
|
-
if (apiKey.length <= 4) return "****";
|
|
41
|
-
return `****${apiKey.slice(-4)}`;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function loadGatewayKeyDocument(path: string): Promise<GatewayKeyDocument | undefined> {
|
|
45
|
-
try {
|
|
46
|
-
const text = (await readHardenedOAuthSourceFile(path)).text;
|
|
47
|
-
const value = JSON.parse(text) as unknown;
|
|
48
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
49
|
-
throw new Error("gateway key file must contain an object");
|
|
50
|
-
}
|
|
51
|
-
const document = value as Record<string, unknown>;
|
|
52
|
-
if (
|
|
53
|
-
document["version"] !== KEY_FORMAT_VERSION ||
|
|
54
|
-
typeof document["apiKey"] !== "string" ||
|
|
55
|
-
document["apiKey"].length === 0
|
|
56
|
-
) {
|
|
57
|
-
throw new Error("gateway key file is invalid");
|
|
58
|
-
}
|
|
59
|
-
const port = document["port"];
|
|
60
|
-
return {
|
|
61
|
-
version: KEY_FORMAT_VERSION,
|
|
62
|
-
apiKey: document["apiKey"],
|
|
63
|
-
...(typeof document["enabled"] === "boolean" ? { enabled: document["enabled"] } : {}),
|
|
64
|
-
...(typeof port === "number" && Number.isSafeInteger(port) && port >= 1024 && port <= 65_535 ? { port } : {}),
|
|
65
|
-
};
|
|
66
|
-
} catch (error) {
|
|
67
|
-
if (error instanceof OAuthSourceError && error.code === "not_found") return undefined;
|
|
68
|
-
throw error;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export async function loadOrCreateGatewayApiKey(path: string, configured?: string): Promise<string> {
|
|
73
|
-
const existing = await loadGatewayKeyDocument(path);
|
|
74
|
-
if (configured !== undefined) {
|
|
75
|
-
await persistGatewayKeyDocument(path, {
|
|
76
|
-
version: KEY_FORMAT_VERSION,
|
|
77
|
-
apiKey: configured,
|
|
78
|
-
...(existing?.enabled === undefined ? {} : { enabled: existing.enabled }),
|
|
79
|
-
...(existing?.port === undefined ? {} : { port: existing.port }),
|
|
80
|
-
});
|
|
81
|
-
return configured;
|
|
82
|
-
}
|
|
83
|
-
if (existing !== undefined) return existing.apiKey;
|
|
84
|
-
const created = generateGatewayApiKey();
|
|
85
|
-
await persistGatewayKeyDocument(path, { version: KEY_FORMAT_VERSION, apiKey: created });
|
|
86
|
-
return created;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export async function persistGatewayApiKey(path: string, apiKey: string): Promise<void> {
|
|
90
|
-
const existing = await loadGatewayKeyDocument(path);
|
|
91
|
-
await persistGatewayKeyDocument(path, {
|
|
92
|
-
version: KEY_FORMAT_VERSION,
|
|
93
|
-
apiKey,
|
|
94
|
-
...(existing?.enabled === undefined ? {} : { enabled: existing.enabled }),
|
|
95
|
-
...(existing?.port === undefined ? {} : { port: existing.port }),
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export async function persistGatewayKeyDocument(path: string, document: GatewayKeyDocument): Promise<void> {
|
|
100
|
-
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
101
|
-
await writeFileAtomic(path, `${JSON.stringify(document)}\n`, { mode: 0o600 });
|
|
102
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Owner-only gateway API key file.
|
|
3
|
+
* @module dsh-coding-subscription-oauth/gateway-auth
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
7
|
+
import { mkdir } from "node:fs/promises";
|
|
8
|
+
import { dirname, join, resolve } from "node:path";
|
|
9
|
+
import { writeFileAtomic } from "@deepseek-ai/dsh-atomic-write";
|
|
10
|
+
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
11
|
+
import { GATEWAY_KEY_FILENAME } from "./ids.ts";
|
|
12
|
+
import { OAuthSourceError, readHardenedOAuthSourceFile } from "./oauth-sources.ts";
|
|
13
|
+
|
|
14
|
+
export { GATEWAY_KEY_FILENAME } from "./ids.ts";
|
|
15
|
+
|
|
16
|
+
const KEY_FORMAT_VERSION = 1;
|
|
17
|
+
|
|
18
|
+
export interface GatewayKeyDocument {
|
|
19
|
+
version: typeof KEY_FORMAT_VERSION;
|
|
20
|
+
apiKey: string;
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
port?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function gatewayKeyPath(dshHome?: string): string {
|
|
26
|
+
return resolve(join(resolveDshHome(dshHome), GATEWAY_KEY_FILENAME));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function generateGatewayApiKey(): string {
|
|
30
|
+
return randomBytes(32).toString("base64url");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function gatewayKeysEqual(left: string, right: string): boolean {
|
|
34
|
+
const a = Buffer.from(left);
|
|
35
|
+
const b = Buffer.from(right);
|
|
36
|
+
return a.length === b.length && a.length > 0 && timingSafeEqual(a, b);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function maskGatewayApiKey(apiKey: string): string {
|
|
40
|
+
if (apiKey.length <= 4) return "****";
|
|
41
|
+
return `****${apiKey.slice(-4)}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function loadGatewayKeyDocument(path: string): Promise<GatewayKeyDocument | undefined> {
|
|
45
|
+
try {
|
|
46
|
+
const text = (await readHardenedOAuthSourceFile(path)).text;
|
|
47
|
+
const value = JSON.parse(text) as unknown;
|
|
48
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
49
|
+
throw new Error("gateway key file must contain an object");
|
|
50
|
+
}
|
|
51
|
+
const document = value as Record<string, unknown>;
|
|
52
|
+
if (
|
|
53
|
+
document["version"] !== KEY_FORMAT_VERSION ||
|
|
54
|
+
typeof document["apiKey"] !== "string" ||
|
|
55
|
+
document["apiKey"].length === 0
|
|
56
|
+
) {
|
|
57
|
+
throw new Error("gateway key file is invalid");
|
|
58
|
+
}
|
|
59
|
+
const port = document["port"];
|
|
60
|
+
return {
|
|
61
|
+
version: KEY_FORMAT_VERSION,
|
|
62
|
+
apiKey: document["apiKey"],
|
|
63
|
+
...(typeof document["enabled"] === "boolean" ? { enabled: document["enabled"] } : {}),
|
|
64
|
+
...(typeof port === "number" && Number.isSafeInteger(port) && port >= 1024 && port <= 65_535 ? { port } : {}),
|
|
65
|
+
};
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error instanceof OAuthSourceError && error.code === "not_found") return undefined;
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function loadOrCreateGatewayApiKey(path: string, configured?: string): Promise<string> {
|
|
73
|
+
const existing = await loadGatewayKeyDocument(path);
|
|
74
|
+
if (configured !== undefined) {
|
|
75
|
+
await persistGatewayKeyDocument(path, {
|
|
76
|
+
version: KEY_FORMAT_VERSION,
|
|
77
|
+
apiKey: configured,
|
|
78
|
+
...(existing?.enabled === undefined ? {} : { enabled: existing.enabled }),
|
|
79
|
+
...(existing?.port === undefined ? {} : { port: existing.port }),
|
|
80
|
+
});
|
|
81
|
+
return configured;
|
|
82
|
+
}
|
|
83
|
+
if (existing !== undefined) return existing.apiKey;
|
|
84
|
+
const created = generateGatewayApiKey();
|
|
85
|
+
await persistGatewayKeyDocument(path, { version: KEY_FORMAT_VERSION, apiKey: created });
|
|
86
|
+
return created;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function persistGatewayApiKey(path: string, apiKey: string): Promise<void> {
|
|
90
|
+
const existing = await loadGatewayKeyDocument(path);
|
|
91
|
+
await persistGatewayKeyDocument(path, {
|
|
92
|
+
version: KEY_FORMAT_VERSION,
|
|
93
|
+
apiKey,
|
|
94
|
+
...(existing?.enabled === undefined ? {} : { enabled: existing.enabled }),
|
|
95
|
+
...(existing?.port === undefined ? {} : { port: existing.port }),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export async function persistGatewayKeyDocument(path: string, document: GatewayKeyDocument): Promise<void> {
|
|
100
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
101
|
+
await writeFileAtomic(path, `${JSON.stringify(document)}\n`, { mode: 0o600 });
|
|
102
|
+
}
|