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/alias-adapter.ts
CHANGED
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Harness route aliases over a native-id PiAiAdapter.
|
|
3
|
-
* @module dsh-coding-subscription-oauth/alias-adapter
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
GenerateOptions,
|
|
8
|
-
LlmModelInfo,
|
|
9
|
-
LlmProviderInfo,
|
|
10
|
-
LlmResolvedModelInfo,
|
|
11
|
-
ResolvedRetryPolicy,
|
|
12
|
-
StreamChunk,
|
|
13
|
-
} from "@deepseek-ai/dsh-llm";
|
|
14
|
-
import { LlmAdapter, LlmError } from "@deepseek-ai/dsh-llm";
|
|
15
|
-
import { remapXaiCapacityFailure } from "./grok-errors.ts";
|
|
16
|
-
import { remapAuthFailureIfContextOverflow } from "./kimi-errors.ts";
|
|
17
|
-
|
|
18
|
-
export interface AliasLlmRoutePolicy {
|
|
19
|
-
/** User-facing provider name shown above models in the model selector. */
|
|
20
|
-
displayName?: string;
|
|
21
|
-
/** Return false to hide every model for this route from discovery. */
|
|
22
|
-
isAuthenticated?: () => Promise<boolean>;
|
|
23
|
-
/**
|
|
24
|
-
* After authentication, keep only models this predicate accepts.
|
|
25
|
-
* Used by opt-in routes (e.g. Codex Fast) so ineligible ids stay hidden
|
|
26
|
-
* without hiding the whole authenticated catalog.
|
|
27
|
-
*/
|
|
28
|
-
includeModel?: (modelId: string) => boolean;
|
|
29
|
-
/**
|
|
30
|
-
* Called once when a stream for this route finishes with an AUTH failure
|
|
31
|
-
* (upstream rejected a locally-valid token). Implementations backdate the
|
|
32
|
-
* stored credential's expiry so the retried step refreshes before reuse.
|
|
33
|
-
* Awaiting it here keeps invalidation ordered before the retry executor
|
|
34
|
-
* reruns the step; failures are swallowed so the original AUTH surfaces.
|
|
35
|
-
*/
|
|
36
|
-
onAuthFailure?: () => Promise<void>;
|
|
37
|
-
}
|
|
38
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Harness route aliases over a native-id PiAiAdapter.
|
|
3
|
+
* @module dsh-coding-subscription-oauth/alias-adapter
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
GenerateOptions,
|
|
8
|
+
LlmModelInfo,
|
|
9
|
+
LlmProviderInfo,
|
|
10
|
+
LlmResolvedModelInfo,
|
|
11
|
+
ResolvedRetryPolicy,
|
|
12
|
+
StreamChunk,
|
|
13
|
+
} from "@deepseek-ai/dsh-llm";
|
|
14
|
+
import { LlmAdapter, LlmError } from "@deepseek-ai/dsh-llm";
|
|
15
|
+
import { remapXaiCapacityFailure } from "./grok-errors.ts";
|
|
16
|
+
import { remapAuthFailureIfContextOverflow } from "./kimi-errors.ts";
|
|
17
|
+
|
|
18
|
+
export interface AliasLlmRoutePolicy {
|
|
19
|
+
/** User-facing provider name shown above models in the model selector. */
|
|
20
|
+
displayName?: string;
|
|
21
|
+
/** Return false to hide every model for this route from discovery. */
|
|
22
|
+
isAuthenticated?: () => Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* After authentication, keep only models this predicate accepts.
|
|
25
|
+
* Used by opt-in routes (e.g. Codex Fast) so ineligible ids stay hidden
|
|
26
|
+
* without hiding the whole authenticated catalog.
|
|
27
|
+
*/
|
|
28
|
+
includeModel?: (modelId: string) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Called once when a stream for this route finishes with an AUTH failure
|
|
31
|
+
* (upstream rejected a locally-valid token). Implementations backdate the
|
|
32
|
+
* stored credential's expiry so the retried step refreshes before reuse.
|
|
33
|
+
* Awaiting it here keeps invalidation ordered before the retry executor
|
|
34
|
+
* reruns the step; failures are swallowed so the original AUTH surfaces.
|
|
35
|
+
*/
|
|
36
|
+
onAuthFailure?: () => Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
39
|
export function normalizeReplayForRoute(
|
|
40
40
|
message: GenerateOptions["messages"][number],
|
|
41
41
|
route: string,
|
|
42
42
|
nativeReplayProvider: string,
|
|
43
|
-
): GenerateOptions["messages"][number] {
|
|
44
|
-
if (message.role !== "assistant" || message.source.kind !== "model") return message;
|
|
45
|
-
if (message.source.provider !== route) {
|
|
46
|
-
if (message.source.replayState === undefined) return message;
|
|
47
|
-
const { replayState: _foreignReplay, ...source } = message.source;
|
|
48
|
-
return { ...message, source };
|
|
49
|
-
}
|
|
43
|
+
): GenerateOptions["messages"][number] {
|
|
44
|
+
if (message.role !== "assistant" || message.source.kind !== "model") return message;
|
|
45
|
+
if (message.source.provider !== route) {
|
|
46
|
+
if (message.source.replayState === undefined) return message;
|
|
47
|
+
const { replayState: _foreignReplay, ...source } = message.source;
|
|
48
|
+
return { ...message, source };
|
|
49
|
+
}
|
|
50
50
|
// The rc.2 envelope stays entirely opaque. PiAiAdapter only keys replay
|
|
51
51
|
// validation from source.provider, so restore the native provider identity
|
|
52
52
|
// without inspecting or changing replayState.
|
|
53
53
|
return { ...message, source: { ...message.source, provider: nativeReplayProvider } };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Keeps pi-ai model.provider identities native while exposing collision-free
|
|
58
|
-
* Harness route names. Every public operation translates exactly once.
|
|
59
|
-
*/
|
|
60
|
-
export class AliasLlmAdapter extends LlmAdapter {
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Keeps pi-ai model.provider identities native while exposing collision-free
|
|
58
|
+
* Harness route names. Every public operation translates exactly once.
|
|
59
|
+
*/
|
|
60
|
+
export class AliasLlmAdapter extends LlmAdapter {
|
|
61
61
|
constructor(
|
|
62
62
|
private readonly inner: LlmAdapter,
|
|
63
63
|
private readonly aliases: ReadonlyMap<string, string>,
|
|
64
64
|
private readonly policies: ReadonlyMap<string, AliasLlmRoutePolicy> = new Map(),
|
|
65
65
|
private readonly replayProviders: ReadonlyMap<string, string> = aliases,
|
|
66
|
-
) {
|
|
67
|
-
super();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
private nativeProvider(route: string): string {
|
|
71
|
-
const provider = this.aliases.get(route);
|
|
72
|
-
if (provider === undefined) throw new LlmError(`OAuth adapter does not own provider "${route}"`, "NO_ADAPTER");
|
|
73
|
-
return provider;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
providerInfo(provider: string): LlmProviderInfo {
|
|
77
|
-
const native = this.nativeProvider(provider);
|
|
78
|
-
const info = this.inner.providerInfo(native);
|
|
79
|
-
const displayName = this.policies.get(provider)?.displayName;
|
|
80
|
-
return { ...info, id: provider, ...(displayName === undefined ? {} : { name: displayName }) };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {
|
|
84
|
-
return this.inner.providerRetryPolicy(this.nativeProvider(provider));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async listModels(provider: string): Promise<readonly LlmModelInfo[]> {
|
|
88
|
-
const native = this.nativeProvider(provider);
|
|
89
|
-
const isAuthenticated = this.policies.get(provider)?.isAuthenticated;
|
|
90
|
-
if (isAuthenticated !== undefined) {
|
|
91
|
-
try {
|
|
92
|
-
if (!(await isAuthenticated())) return [];
|
|
93
|
-
} catch {
|
|
94
|
-
// A corrupt/unreadable credential must hide models instead of breaking
|
|
95
|
-
// the entire model picker or presenting a route that cannot be used.
|
|
96
|
-
return [];
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const listed = (await this.inner.listModels(native)).map((model) => ({ ...model, provider }));
|
|
100
|
-
const includeModel = this.policies.get(provider)?.includeModel;
|
|
101
|
-
return includeModel === undefined ? listed : listed.filter((model) => includeModel(model.id));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo> {
|
|
105
|
-
const native = this.nativeProvider(provider);
|
|
106
|
-
return { ...(await this.inner.resolveModel(native, model, signal)), provider };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
|
|
110
|
-
const route = options.provider;
|
|
111
|
-
const native = this.nativeProvider(route);
|
|
66
|
+
) {
|
|
67
|
+
super();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private nativeProvider(route: string): string {
|
|
71
|
+
const provider = this.aliases.get(route);
|
|
72
|
+
if (provider === undefined) throw new LlmError(`OAuth adapter does not own provider "${route}"`, "NO_ADAPTER");
|
|
73
|
+
return provider;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
providerInfo(provider: string): LlmProviderInfo {
|
|
77
|
+
const native = this.nativeProvider(provider);
|
|
78
|
+
const info = this.inner.providerInfo(native);
|
|
79
|
+
const displayName = this.policies.get(provider)?.displayName;
|
|
80
|
+
return { ...info, id: provider, ...(displayName === undefined ? {} : { name: displayName }) };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {
|
|
84
|
+
return this.inner.providerRetryPolicy(this.nativeProvider(provider));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async listModels(provider: string): Promise<readonly LlmModelInfo[]> {
|
|
88
|
+
const native = this.nativeProvider(provider);
|
|
89
|
+
const isAuthenticated = this.policies.get(provider)?.isAuthenticated;
|
|
90
|
+
if (isAuthenticated !== undefined) {
|
|
91
|
+
try {
|
|
92
|
+
if (!(await isAuthenticated())) return [];
|
|
93
|
+
} catch {
|
|
94
|
+
// A corrupt/unreadable credential must hide models instead of breaking
|
|
95
|
+
// the entire model picker or presenting a route that cannot be used.
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const listed = (await this.inner.listModels(native)).map((model) => ({ ...model, provider }));
|
|
100
|
+
const includeModel = this.policies.get(provider)?.includeModel;
|
|
101
|
+
return includeModel === undefined ? listed : listed.filter((model) => includeModel(model.id));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async resolveModel(provider: string, model: string, signal?: AbortSignal): Promise<LlmResolvedModelInfo> {
|
|
105
|
+
const native = this.nativeProvider(provider);
|
|
106
|
+
return { ...(await this.inner.resolveModel(native, model, signal)), provider };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
|
|
110
|
+
const route = options.provider;
|
|
111
|
+
const native = this.nativeProvider(route);
|
|
112
112
|
const messages = options.messages.map((message) =>
|
|
113
113
|
normalizeReplayForRoute(message, route, this.replayProviders.get(route) ?? native),
|
|
114
114
|
);
|
|
115
|
-
let authFailureNotified = false;
|
|
116
|
-
for await (const raw of this.inner.stream({ ...options, provider: native, messages })) {
|
|
117
|
-
const chunk =
|
|
118
|
-
raw.type === "finish" && raw.reason.kind === "error"
|
|
119
|
-
? {
|
|
120
|
-
...raw,
|
|
121
|
-
reason: {
|
|
122
|
-
...raw.reason,
|
|
123
|
-
failure: remapXaiCapacityFailure(remapAuthFailureIfContextOverflow(raw.reason.failure)),
|
|
124
|
-
},
|
|
125
|
-
}
|
|
126
|
-
: raw;
|
|
127
|
-
if (
|
|
128
|
-
!authFailureNotified &&
|
|
129
|
-
chunk.type === "finish" &&
|
|
130
|
-
chunk.reason.kind === "error" &&
|
|
131
|
-
chunk.reason.failure.code === "AUTH"
|
|
132
|
-
) {
|
|
133
|
-
authFailureNotified = true;
|
|
134
|
-
const onAuthFailure = this.policies.get(route)?.onAuthFailure;
|
|
135
|
-
if (onAuthFailure !== undefined) {
|
|
136
|
-
try {
|
|
137
|
-
await onAuthFailure();
|
|
138
|
-
} catch {
|
|
139
|
-
// Invalidation is best-effort: the original AUTH failure must
|
|
140
|
-
// surface unchanged even when the credential store is unreadable.
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
115
|
+
let authFailureNotified = false;
|
|
116
|
+
for await (const raw of this.inner.stream({ ...options, provider: native, messages })) {
|
|
117
|
+
const chunk =
|
|
118
|
+
raw.type === "finish" && raw.reason.kind === "error"
|
|
119
|
+
? {
|
|
120
|
+
...raw,
|
|
121
|
+
reason: {
|
|
122
|
+
...raw.reason,
|
|
123
|
+
failure: remapXaiCapacityFailure(remapAuthFailureIfContextOverflow(raw.reason.failure)),
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
: raw;
|
|
127
|
+
if (
|
|
128
|
+
!authFailureNotified &&
|
|
129
|
+
chunk.type === "finish" &&
|
|
130
|
+
chunk.reason.kind === "error" &&
|
|
131
|
+
chunk.reason.failure.code === "AUTH"
|
|
132
|
+
) {
|
|
133
|
+
authFailureNotified = true;
|
|
134
|
+
const onAuthFailure = this.policies.get(route)?.onAuthFailure;
|
|
135
|
+
if (onAuthFailure !== undefined) {
|
|
136
|
+
try {
|
|
137
|
+
await onAuthFailure();
|
|
138
|
+
} catch {
|
|
139
|
+
// Invalidation is best-effort: the original AUTH failure must
|
|
140
|
+
// surface unchanged even when the credential store is unreadable.
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
144
|
yield chunk;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|