dsh-coding-subscription-oauth 0.6.3 → 0.6.5
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 +33 -0
- package/CONTRIBUTING.md +13 -4
- package/INSTALL.md +7 -5
- package/README.de.md +6 -6
- package/README.es.md +6 -6
- package/README.fr.md +6 -6
- package/README.ja.md +6 -6
- package/README.ko.md +6 -6
- package/README.md +6 -6
- package/README.pt-BR.md +6 -6
- package/README.ru.md +6 -6
- package/README.zh-CN.md +6 -6
- package/docs/00-project-rules.md +4 -4
- package/docs/02-architecture.md +7 -3
- package/docs/02-architecture.zh-CN.md +7 -3
- package/lib/bin.js +1333 -569
- package/lib/bin.js.map +4 -4
- package/lib/client.js +1 -1
- package/lib/client.js.map +2 -2
- package/lib/gateway-protocol.d.ts +3 -46
- package/lib/gateway-protocol.d.ts.map +1 -1
- package/lib/gateway-routes.d.ts.map +1 -1
- package/lib/grok-errors.d.ts +2 -12
- package/lib/grok-errors.d.ts.map +1 -1
- package/lib/grok-imagine/client.d.ts +73 -0
- package/lib/grok-imagine/client.d.ts.map +1 -0
- package/lib/grok-imagine/index.d.ts +8 -0
- package/lib/grok-imagine/index.d.ts.map +1 -0
- package/lib/grok-imagine/net.d.ts +10 -0
- package/lib/grok-imagine/net.d.ts.map +1 -0
- package/lib/grok-imagine/parse.d.ts +20 -0
- package/lib/grok-imagine/parse.d.ts.map +1 -0
- package/lib/grok-imagine/types.d.ts +191 -0
- package/lib/grok-imagine/types.d.ts.map +1 -0
- package/lib/grok-imagine.d.ts +3 -263
- package/lib/grok-imagine.d.ts.map +1 -1
- package/lib/http-json.d.ts +2 -9
- package/lib/http-json.d.ts.map +1 -1
- package/lib/index.js +1395 -26178
- package/lib/index.js.map +4 -4
- package/lib/kimi-errors.d.ts +2 -12
- package/lib/kimi-errors.d.ts.map +1 -1
- package/lib/runtime/gateway-protocol.d.ts +47 -0
- package/lib/runtime/gateway-protocol.d.ts.map +1 -0
- package/lib/runtime/grok-errors.d.ts +13 -0
- package/lib/runtime/grok-errors.d.ts.map +1 -0
- package/lib/runtime/http-json.d.ts +10 -0
- package/lib/runtime/http-json.d.ts.map +1 -0
- package/lib/runtime/kimi-errors.d.ts +13 -0
- package/lib/runtime/kimi-errors.d.ts.map +1 -0
- package/package.json +12 -7
- package/scripts/release.mjs +1 -0
- package/src/adapter.ts +0 -348
- package/src/alias-adapter.ts +0 -147
- package/src/auth-routes.ts +0 -921
- package/src/auth.ts +0 -67
- package/src/bin.ts +0 -350
- package/src/capability-routes.ts +0 -279
- package/src/capability-runtime.ts +0 -314
- package/src/capability-settings.ts +0 -671
- package/src/capability-tools.ts +0 -685
- package/src/catalog.ts +0 -271
- package/src/client/GrokBuildSettings.tsx +0 -771
- package/src/client/api.ts +0 -88
- package/src/client/components/AboutTab.tsx +0 -30
- package/src/client/components/AccountsTab.tsx +0 -241
- package/src/client/components/Badge.tsx +0 -33
- package/src/client/components/CapabilitiesTab.tsx +0 -265
- package/src/client/components/CliPullPreview.tsx +0 -116
- package/src/client/components/CopyButton.tsx +0 -57
- package/src/client/components/GatewayTab.tsx +0 -469
- package/src/client/components/NoticeBanner.tsx +0 -46
- package/src/client/components/ProgressBar.tsx +0 -53
- package/src/client/components/ProviderCard.tsx +0 -606
- package/src/client/components/SettingsTabs.tsx +0 -75
- package/src/client/components/ToggleSwitch.tsx +0 -71
- package/src/client/constants.ts +0 -230
- package/src/client/display.ts +0 -61
- package/src/client/dshClientAdapter.ts +0 -127
- package/src/client/gatewaySnippets.ts +0 -37
- package/src/client/index.tsx +0 -156
- package/src/client/locales.ts +0 -540
- package/src/client/microStyles.ts +0 -52
- package/src/client/parsers.ts +0 -398
- package/src/client/styles.ts +0 -325
- package/src/client/types.ts +0 -199
- package/src/codex-http.ts +0 -447
- package/src/codex-images.ts +0 -503
- package/src/codex-model-capabilities.ts +0 -320
- package/src/codex-search.ts +0 -245
- package/src/codex-usage.ts +0 -263
- package/src/compatibility.ts +0 -55
- package/src/dsh-host-adapter.ts +0 -173
- package/src/gateway-anthropic-messages.ts +0 -84
- package/src/gateway-auth.ts +0 -102
- package/src/gateway-backend.ts +0 -274
- package/src/gateway-body.ts +0 -49
- package/src/gateway-config.ts +0 -76
- package/src/gateway-http.ts +0 -104
- package/src/gateway-openai-chat.ts +0 -124
- package/src/gateway-openai-responses.ts +0 -53
- package/src/gateway-parse.ts +0 -224
- package/src/gateway-protocol.ts +0 -52
- package/src/gateway-routes.ts +0 -158
- package/src/gateway.ts +0 -258
- package/src/grok-errors.ts +0 -24
- package/src/grok-imagine.ts +0 -1627
- package/src/grok-import.ts +0 -151
- package/src/http-json.ts +0 -82
- package/src/ids.ts +0 -59
- package/src/imagine-routes.ts +0 -463
- package/src/index.ts +0 -735
- package/src/invariant.ts +0 -17
- package/src/kimi-errors.ts +0 -26
- package/src/media-store.ts +0 -927
- package/src/oauth-import-routes.ts +0 -324
- package/src/oauth-providers.ts +0 -152
- package/src/oauth-session.ts +0 -183
- package/src/oauth-sources.ts +0 -1104
- package/src/oauth.ts +0 -620
- package/src/provider.ts +0 -128
- package/src/proxy.ts +0 -11
- package/src/redact.ts +0 -72
- package/src/session.ts +0 -218
- package/src/store.ts +0 -217
- package/src/web-origin.ts +0 -296
- package/src/web-routes.ts +0 -38
package/lib/kimi-errors.d.ts
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
* @module dsh-coding-subscription-oauth/kimi-errors
|
|
4
|
-
*/
|
|
5
|
-
export declare function isMisclassifiedContextWindowError(detail: string): boolean;
|
|
6
|
-
export declare function remapAuthFailureIfContextOverflow(failure: {
|
|
7
|
-
message: string;
|
|
8
|
-
code: string;
|
|
9
|
-
}): {
|
|
10
|
-
message: string;
|
|
11
|
-
code: string;
|
|
12
|
-
};
|
|
1
|
+
/** Compatibility facade — implementation lives in `src/runtime/` (mirrored from Hub vendor core). */
|
|
2
|
+
export { isMisclassifiedContextWindowError, remapAuthFailureIfContextOverflow, } from "./runtime/kimi-errors.js";
|
|
13
3
|
//# sourceMappingURL=kimi-errors.d.ts.map
|
package/lib/kimi-errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kimi-errors.d.ts","sourceRoot":"","sources":["../../src/kimi-errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"kimi-errors.d.ts","sourceRoot":"","sources":["../../src/kimi-errors.ts"],"names":[],"mappings":"AAAA,qGAAqG;AAErG,OAAO,EACN,iCAAiC,EACjC,iCAAiC,GACjC,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared request/stream types for the local coding-subscription gateway.
|
|
3
|
+
* @module dsh-coding-oauth-core/gateway-protocol
|
|
4
|
+
*/
|
|
5
|
+
export interface GatewayToolCall {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
arguments: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GatewayTool {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
parameters: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface GatewayChatMessage {
|
|
16
|
+
role: string;
|
|
17
|
+
content: string;
|
|
18
|
+
tool_calls?: readonly GatewayToolCall[];
|
|
19
|
+
reasoning_content?: string;
|
|
20
|
+
tool_call_id?: string;
|
|
21
|
+
tool_name?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface GatewayCompletionRequest {
|
|
24
|
+
model: string;
|
|
25
|
+
messages: readonly GatewayChatMessage[];
|
|
26
|
+
tools?: readonly GatewayTool[];
|
|
27
|
+
reasoning?: string;
|
|
28
|
+
}
|
|
29
|
+
export type GatewayStreamPart = {
|
|
30
|
+
type: "text";
|
|
31
|
+
text: string;
|
|
32
|
+
} | {
|
|
33
|
+
type: "thinking";
|
|
34
|
+
text: string;
|
|
35
|
+
} | {
|
|
36
|
+
type: "tool_call";
|
|
37
|
+
index: number;
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
arguments: string;
|
|
41
|
+
} | {
|
|
42
|
+
type: "done";
|
|
43
|
+
finish: "stop" | "tool_calls" | "length";
|
|
44
|
+
};
|
|
45
|
+
export type GatewayThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
46
|
+
export declare function isThinkingLevel(value: string): value is GatewayThinkingLevel;
|
|
47
|
+
//# sourceMappingURL=gateway-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-protocol.d.ts","sourceRoot":"","sources":["../../../src/runtime/gateway-protocol.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACxC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACxC,KAAK,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACjF;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAEnG,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,oBAAoB,CAU5E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xAI / Grok Build error remapping shared by Hub and Subscription.
|
|
3
|
+
* @module dsh-coding-oauth-core/grok-errors
|
|
4
|
+
*/
|
|
5
|
+
export declare function isXaiCapacityError(detail: string): boolean;
|
|
6
|
+
export declare function remapXaiCapacityFailure(failure: {
|
|
7
|
+
message: string;
|
|
8
|
+
code: string;
|
|
9
|
+
}): {
|
|
10
|
+
message: string;
|
|
11
|
+
code: string;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=grok-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grok-errors.d.ts","sourceRoot":"","sources":["../../../src/runtime/grok-errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IACpF,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb,CAGA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IncomingMessage } from "node:http";
|
|
2
|
+
export declare const JSON_BODY_LIMIT_BYTES: number;
|
|
3
|
+
export declare class JsonRequestError extends Error {
|
|
4
|
+
readonly statusCode: 400 | 413;
|
|
5
|
+
constructor(statusCode: 400 | 413, message: string);
|
|
6
|
+
}
|
|
7
|
+
/** Read one JSON request body with a strict in-memory ceiling. */
|
|
8
|
+
export declare function readJsonRequest(request: IncomingMessage, limit?: number): Promise<unknown>;
|
|
9
|
+
export declare function requestErrorStatus(error: unknown, fallback: number): number;
|
|
10
|
+
//# sourceMappingURL=http-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-json.d.ts","sourceRoot":"","sources":["../../../src/runtime/http-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAE/C,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,UAAU,EAAE,GAAG,GAAG,GAAG,CAAC;gBAEnB,UAAU,EAAE,GAAG,GAAG,GAAG,EAAE,OAAO,EAAE,MAAM;CAKlD;AASD,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,SAAwB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuDzG;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE3E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kimi Code error remapping shared by Hub and Subscription.
|
|
3
|
+
* @module dsh-coding-oauth-core/kimi-errors
|
|
4
|
+
*/
|
|
5
|
+
export declare function isMisclassifiedContextWindowError(detail: string): boolean;
|
|
6
|
+
export declare function remapAuthFailureIfContextOverflow(failure: {
|
|
7
|
+
message: string;
|
|
8
|
+
code: string;
|
|
9
|
+
}): {
|
|
10
|
+
message: string;
|
|
11
|
+
code: string;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=kimi-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kimi-errors.d.ts","sourceRoot":"","sources":["../../../src/runtime/kimi-errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAC9F,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb,CAGA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-coding-subscription-oauth",
|
|
3
3
|
"description": "DeepSeek Harness coding-subscription OAuth: SuperGrok/Grok Build, ChatGPT Plus Codex, Kimi Code, Claude Code. Fixes AUTH API key is invalid, INVALID_REPLAY_STATE, grok-4.6 xhigh, Kimi Bearer vs x-api-key.",
|
|
4
|
-
|
|
4
|
+
"version": "0.6.5",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"check:bom": "node build/verify-dsh-bom.mjs",
|
|
44
|
+
"assert:node": "node scripts/assert-node.mjs",
|
|
45
|
+
"assert:runtime-slice": "node scripts/assert-runtime-slice-sync.mjs",
|
|
44
46
|
"clean": "node build/clean.mjs",
|
|
45
47
|
"typecheck": "tsc -b tsconfig.host.json tsconfig.client.json",
|
|
46
48
|
"build:server": "tsc -p tsconfig.build.json && tsc -p tsconfig.dts-bin.json && node build/build-server.mjs",
|
|
@@ -49,14 +51,17 @@
|
|
|
49
51
|
"build": "pnpm run release:build",
|
|
50
52
|
"test": "vitest run",
|
|
51
53
|
"test:watch": "vitest",
|
|
54
|
+
"test:coverage": "vitest run --coverage",
|
|
52
55
|
"lint": "biome check",
|
|
53
|
-
"check:next": "pnpm run check:bom && pnpm run lint && pnpm run typecheck && pnpm run test",
|
|
54
|
-
"check": "pnpm run lint && pnpm run release:build && pnpm run test",
|
|
56
|
+
"check:next": "pnpm run assert:node && pnpm run assert:runtime-slice && pnpm run check:bom && pnpm run lint && pnpm run typecheck && pnpm run test",
|
|
57
|
+
"check": "pnpm run assert:node && pnpm run assert:runtime-slice && pnpm run lint && pnpm run release:build && pnpm run test",
|
|
55
58
|
"release:promote": "node build/promote-release.mjs",
|
|
56
59
|
"release:verify": "node build/verify-release.mjs",
|
|
57
60
|
"release:build": "pnpm run build:artifacts && pnpm run release:promote",
|
|
58
61
|
"release:dry": "node scripts/release.mjs --dry-run",
|
|
62
|
+
"release:inspect": "pnpm run assert:node && node scripts/release.mjs --dry-run",
|
|
59
63
|
"release:pack": "node scripts/release.mjs --pack",
|
|
64
|
+
"release:publish": "node scripts/release-publish.mjs",
|
|
60
65
|
"verify:deployed": "node scripts/verify-deployed-catalog.mjs",
|
|
61
66
|
"smoke:deployed": "node scripts/smoke-deployed-routes.mjs",
|
|
62
67
|
"prepack": "pnpm run release:build"
|
|
@@ -76,7 +81,6 @@
|
|
|
76
81
|
},
|
|
77
82
|
"files": [
|
|
78
83
|
"lib",
|
|
79
|
-
"src",
|
|
80
84
|
"media",
|
|
81
85
|
"cordis.patch.yml",
|
|
82
86
|
"INSTALL.md",
|
|
@@ -143,8 +147,8 @@
|
|
|
143
147
|
}
|
|
144
148
|
},
|
|
145
149
|
"dependencies": {
|
|
146
|
-
|
|
147
|
-
"undici": "
|
|
150
|
+
"dsh-coding-oauth-core": "0.1.1",
|
|
151
|
+
"undici": "7.29.0"
|
|
148
152
|
},
|
|
149
153
|
"peerDependencies": {
|
|
150
154
|
"@deepseek-ai/cordis": "4.0.1",
|
|
@@ -210,11 +214,12 @@
|
|
|
210
214
|
"@types/node": "^22.20.0",
|
|
211
215
|
"@types/react": "~18.3.1",
|
|
212
216
|
"@types/react-dom": "18.3.7",
|
|
217
|
+
"@vitest/coverage-v8": "4.1.10",
|
|
213
218
|
"esbuild": "^0.28.2",
|
|
214
219
|
"react": "18.3.1",
|
|
215
220
|
"react-dom": "18.3.1",
|
|
216
221
|
"typescript": "^6.0.3",
|
|
217
|
-
"undici": "
|
|
222
|
+
"undici": "7.29.0",
|
|
218
223
|
"vitest": "^4.1.8"
|
|
219
224
|
},
|
|
220
225
|
"overrides": {
|
package/scripts/release.mjs
CHANGED
package/src/adapter.ts
DELETED
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
/** Coding-subscription adapter assembled from public dsh-llm-pi-ai extension points. */
|
|
2
|
-
|
|
3
|
-
import type { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
4
|
-
import type { RetryPolicyConfig } from "@deepseek-ai/dsh-llm";
|
|
5
|
-
import { type LlmAdapter, LlmError, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
6
|
-
import type { PiAiAdapterOptions, ResolvedPiAiProviderProfile } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
7
|
-
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
8
|
-
import type { AliasLlmRoutePolicy } from "./alias-adapter.ts";
|
|
9
|
-
import { AliasLlmAdapter } from "./alias-adapter.ts";
|
|
10
|
-
import { preferredGrokBuildModelFrom } from "./catalog.ts";
|
|
11
|
-
import { withCodexFastRouting } from "./codex-model-capabilities.ts";
|
|
12
|
-
import {
|
|
13
|
-
CLAUDE_CODE_OAUTH_ROUTE,
|
|
14
|
-
CLAUDE_PI_PROVIDER,
|
|
15
|
-
CODEX_OAUTH_FAST_ROUTE,
|
|
16
|
-
CODEX_OAUTH_ROUTE,
|
|
17
|
-
CODEX_PI_PROVIDER,
|
|
18
|
-
DEFAULT_GROK_BUILD_MODEL,
|
|
19
|
-
GROK_BUILD_ROUTE,
|
|
20
|
-
GROK_BUILD_STREAM_IDLE_TIMEOUT_MS,
|
|
21
|
-
KIMI_CODE_OAUTH_ROUTE,
|
|
22
|
-
KIMI_PI_PROVIDER,
|
|
23
|
-
XAI_PI_PROVIDER,
|
|
24
|
-
} from "./ids.ts";
|
|
25
|
-
import type { OAuthProviderSession } from "./oauth-session.ts";
|
|
26
|
-
import { grokBuildBaselineModels, grokBuildFingerprintHeaders } from "./provider.ts";
|
|
27
|
-
import { safeMessage } from "./redact.ts";
|
|
28
|
-
import type { GrokBuildSession } from "./session.ts";
|
|
29
|
-
|
|
30
|
-
type PiAiAuthInjection = PiAiAdapterOptions["auth"];
|
|
31
|
-
type PiAiCredentialStore = PiAiAuthInjection["credentials"];
|
|
32
|
-
|
|
33
|
-
const REQUEST_IMAGE_POLICY = {
|
|
34
|
-
maxRequestImageBytes: 20 * 1024 * 1024,
|
|
35
|
-
requestImagePixelBudget: 2048 * 2048,
|
|
36
|
-
requestImageMaxBytes: 1024 * 1024,
|
|
37
|
-
} as const;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Route pi-ai credential operations to the already owner-locked OAuth files.
|
|
41
|
-
* The adapter may ask its collection about every profile, so an unknown id is
|
|
42
|
-
* never allowed to reach a writable store. Reads are empty and writes fail
|
|
43
|
-
* closed, preserving the existing per-provider refresh lock and file policy.
|
|
44
|
-
*/
|
|
45
|
-
function oauthAuthInjection(grok: GrokBuildSession, subscriptions: readonly OAuthProviderSession[]): PiAiAuthInjection {
|
|
46
|
-
const stores = new Map<string, PiAiCredentialStore>([
|
|
47
|
-
[XAI_PI_PROVIDER, grok.store],
|
|
48
|
-
...subscriptions.map((session) => [session.definition.nativeProviderId, session.store] as const),
|
|
49
|
-
]);
|
|
50
|
-
const storeFor = (providerId: string): PiAiCredentialStore | undefined => stores.get(providerId);
|
|
51
|
-
return {
|
|
52
|
-
credentials: {
|
|
53
|
-
async read(providerId, options) {
|
|
54
|
-
return storeFor(providerId)?.read(providerId, options);
|
|
55
|
-
},
|
|
56
|
-
async list(options) {
|
|
57
|
-
const entries = await Promise.all([...stores.values()].map((store) => store.list(options)));
|
|
58
|
-
return entries.flat();
|
|
59
|
-
},
|
|
60
|
-
async modify(providerId, fn, options) {
|
|
61
|
-
const store = storeFor(providerId);
|
|
62
|
-
if (store === undefined)
|
|
63
|
-
throw new Error(`refusing credential write for unknown OAuth provider "${providerId}"`);
|
|
64
|
-
return store.modify(providerId, fn, options);
|
|
65
|
-
},
|
|
66
|
-
async delete(providerId, options) {
|
|
67
|
-
const store = storeFor(providerId);
|
|
68
|
-
if (store === undefined)
|
|
69
|
-
throw new Error(`refusing credential deletion for unknown OAuth provider "${providerId}"`);
|
|
70
|
-
await store.delete(providerId, options);
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
authContext: {
|
|
74
|
-
// Subscription adapters obtain request credentials only from their
|
|
75
|
-
// owner-scoped stores. Do not let a foreign environment/file credential
|
|
76
|
-
// silently change a selected OAuth route.
|
|
77
|
-
env: async () => undefined,
|
|
78
|
-
fileExists: async () => false,
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Prefer grok-4.6 when the current (live or baseline) list has it. */
|
|
84
|
-
export function preferredGrokBuildModel(models: readonly { id: string }[] = grokBuildBaselineModels()): string {
|
|
85
|
-
return preferredGrokBuildModelFrom(models.length === 0 ? [{ id: DEFAULT_GROK_BUILD_MODEL }] : models);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function missingCredential(name: string): never {
|
|
89
|
-
throw new LlmError(
|
|
90
|
-
`${name} is not signed in. Open Settings → Coding OAuth and sign in with your subscription.`,
|
|
91
|
-
"MISSING_CREDENTIAL",
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Minimum remaining validity demanded of an exported OAuth access token.
|
|
97
|
-
* pi-ai 0.84+ already refreshes five minutes before the stored expiry; this
|
|
98
|
-
* explicit floor documents the plugin contract and hard-fails a refresh that
|
|
99
|
-
* returns an even-shorter-lived token instead of handing it to a request.
|
|
100
|
-
*/
|
|
101
|
-
const MIN_OAUTH_VALIDITY_MS = 60_000;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Provider retry policy for the coding-subscription routes. The harness
|
|
105
|
-
* default retryable set (EMPTY_RESPONSE/RATE_LIMIT/SERVER/TIMEOUT/TRANSPORT)
|
|
106
|
-
* deliberately excludes AUTH, so an upstream 401 — e.g. an access token the
|
|
107
|
-
* server revoked before its local expiry — used to kill the turn outright.
|
|
108
|
-
* AUTH is added here because {@link AliasLlmAdapter} invalidates the stored
|
|
109
|
-
* credential on every AUTH finish, so the retried step refreshes first and
|
|
110
|
-
* does not repeat the same rejected token. Quota exhaustion stays outside the
|
|
111
|
-
* set: retrying a billing-limit 403 cannot succeed and only delays the real
|
|
112
|
-
* message. Genuine credential death is converted to MISSING_CREDENTIAL (not
|
|
113
|
-
* retryable) by the resolver below, so it cannot loop either.
|
|
114
|
-
*
|
|
115
|
-
* Five stacked exponential delays (5s → 10s → 20s → 40s → 80s, ~155s total)
|
|
116
|
-
* pair with the xAI capacity remap in {@link AliasLlmAdapter}: "at capacity"
|
|
117
|
-
* finish errors become RATE_LIMIT so they enter this policy instead of failing
|
|
118
|
-
* as PI_AI_ERROR.
|
|
119
|
-
*/
|
|
120
|
-
const CODING_OAUTH_RETRY_POLICY = {
|
|
121
|
-
mode: "normal" as const,
|
|
122
|
-
maxRetries: 5,
|
|
123
|
-
retryableCodes: ["EMPTY_RESPONSE", "RATE_LIMIT", "SERVER", "TIMEOUT", "TRANSPORT", "AUTH"],
|
|
124
|
-
backoff: { initialDelayMs: 5_000, maxDelayMs: 80_000, jitterRatio: 0.1 },
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
function profile(
|
|
128
|
-
provider: string,
|
|
129
|
-
displayName: string,
|
|
130
|
-
piProvider: ResolvedPiAiProviderProfile["piProvider"],
|
|
131
|
-
retryPolicy?: RetryPolicyConfig | undefined,
|
|
132
|
-
headers?: Record<string, string> | undefined,
|
|
133
|
-
): ResolvedPiAiProviderProfile {
|
|
134
|
-
return {
|
|
135
|
-
provider,
|
|
136
|
-
displayName,
|
|
137
|
-
streamIdleTimeoutMs: GROK_BUILD_STREAM_IDLE_TIMEOUT_MS,
|
|
138
|
-
retryPolicy: resolveRetryPolicy(
|
|
139
|
-
retryPolicy ?? CODING_OAUTH_RETRY_POLICY,
|
|
140
|
-
"dsh-coding-subscription-oauth retryPolicy",
|
|
141
|
-
),
|
|
142
|
-
configuredMaxTokens: new Map(),
|
|
143
|
-
...REQUEST_IMAGE_POLICY,
|
|
144
|
-
...(headers === undefined ? {} : { headers }),
|
|
145
|
-
piProvider,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Existing Grok-only constructor retained for public API compatibility. */
|
|
150
|
-
export function createGrokBuildAdapter(
|
|
151
|
-
session: GrokBuildSession,
|
|
152
|
-
resolveAttachments: () => AttachmentStore | undefined,
|
|
153
|
-
): PiAiAdapter {
|
|
154
|
-
return new PiAiAdapter({
|
|
155
|
-
profiles: () =>
|
|
156
|
-
new Map<string, ResolvedPiAiProviderProfile>([
|
|
157
|
-
[
|
|
158
|
-
GROK_BUILD_ROUTE,
|
|
159
|
-
profile(GROK_BUILD_ROUTE, "xAI Grok Build", session.provider(), undefined, grokBuildFingerprintHeaders()),
|
|
160
|
-
],
|
|
161
|
-
]),
|
|
162
|
-
resolveApiKey: async () =>
|
|
163
|
-
resolveOAuthToken("Grok Build", async () => {
|
|
164
|
-
const auth = await session.models.getAuth(XAI_PI_PROVIDER, { minOAuthValidityMs: MIN_OAUTH_VALIDITY_MS });
|
|
165
|
-
return auth?.auth.apiKey;
|
|
166
|
-
}),
|
|
167
|
-
auth: oauthAuthInjection(session, []),
|
|
168
|
-
resolveAttachments,
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** Opt-in Codex Fast wiring; ordinary `codex-oauth` is unchanged when this is omitted. */
|
|
173
|
-
export interface CodingOAuthAdapterOptions {
|
|
174
|
-
retryPolicy?: RetryPolicyConfig;
|
|
175
|
-
codexFast?: { isEligible(modelId: string): boolean };
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function isRetryPolicyConfig(value: object): value is RetryPolicyConfig {
|
|
179
|
-
return "mode" in value;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function splitCodingOAuthAdapterArgs(
|
|
183
|
-
fourth?: RetryPolicyConfig | CodingOAuthAdapterOptions,
|
|
184
|
-
fifth?: CodingOAuthAdapterOptions,
|
|
185
|
-
): CodingOAuthAdapterOptions {
|
|
186
|
-
if (fifth !== undefined) {
|
|
187
|
-
return {
|
|
188
|
-
...(fourth !== undefined && isRetryPolicyConfig(fourth) ? { retryPolicy: fourth } : {}),
|
|
189
|
-
...fifth,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
if (fourth === undefined) return {};
|
|
193
|
-
if (isRetryPolicyConfig(fourth)) return { retryPolicy: fourth };
|
|
194
|
-
return {
|
|
195
|
-
...(fourth.retryPolicy === undefined ? {} : { retryPolicy: fourth.retryPolicy }),
|
|
196
|
-
...(fourth.codexFast === undefined ? {} : { codexFast: fourth.codexFast }),
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/** Create the four-route OAuth adapter while preserving each pi-ai native id. */
|
|
201
|
-
export function createCodingOAuthAdapter(
|
|
202
|
-
grok: GrokBuildSession,
|
|
203
|
-
subscriptions: readonly OAuthProviderSession[],
|
|
204
|
-
resolveAttachments: () => AttachmentStore | undefined,
|
|
205
|
-
retryPolicy?: RetryPolicyConfig,
|
|
206
|
-
options?: CodingOAuthAdapterOptions,
|
|
207
|
-
): LlmAdapter;
|
|
208
|
-
export function createCodingOAuthAdapter(
|
|
209
|
-
grok: GrokBuildSession,
|
|
210
|
-
subscriptions: readonly OAuthProviderSession[],
|
|
211
|
-
resolveAttachments: () => AttachmentStore | undefined,
|
|
212
|
-
options?: CodingOAuthAdapterOptions,
|
|
213
|
-
): LlmAdapter;
|
|
214
|
-
export function createCodingOAuthAdapter(
|
|
215
|
-
grok: GrokBuildSession,
|
|
216
|
-
subscriptions: readonly OAuthProviderSession[],
|
|
217
|
-
resolveAttachments: () => AttachmentStore | undefined,
|
|
218
|
-
retryPolicyOrOptions?: RetryPolicyConfig | CodingOAuthAdapterOptions,
|
|
219
|
-
options?: CodingOAuthAdapterOptions,
|
|
220
|
-
): LlmAdapter {
|
|
221
|
-
const { retryPolicy, codexFast } = splitCodingOAuthAdapterArgs(retryPolicyOrOptions, options);
|
|
222
|
-
const byNativeId = new Map(subscriptions.map((session) => [session.definition.nativeProviderId, session]));
|
|
223
|
-
const codexSession = byNativeId.get(CODEX_PI_PROVIDER);
|
|
224
|
-
const aliases = new Map<string, string>([
|
|
225
|
-
[GROK_BUILD_ROUTE, GROK_BUILD_ROUTE],
|
|
226
|
-
[CODEX_OAUTH_ROUTE, CODEX_PI_PROVIDER],
|
|
227
|
-
[KIMI_CODE_OAUTH_ROUTE, KIMI_PI_PROVIDER],
|
|
228
|
-
[CLAUDE_CODE_OAUTH_ROUTE, CLAUDE_PI_PROVIDER],
|
|
229
|
-
]);
|
|
230
|
-
if (codexFast !== undefined && codexSession !== undefined) {
|
|
231
|
-
aliases.set(CODEX_OAUTH_FAST_ROUTE, CODEX_OAUTH_FAST_ROUTE);
|
|
232
|
-
}
|
|
233
|
-
const policies = new Map<string, AliasLlmRoutePolicy>([
|
|
234
|
-
[
|
|
235
|
-
GROK_BUILD_ROUTE,
|
|
236
|
-
{
|
|
237
|
-
displayName: "xAI Grok Build (OAuth)",
|
|
238
|
-
isAuthenticated: async () => (await grok.store.read(XAI_PI_PROVIDER))?.type === "oauth",
|
|
239
|
-
onAuthFailure: () => grok.invalidateAccessToken(),
|
|
240
|
-
},
|
|
241
|
-
],
|
|
242
|
-
]);
|
|
243
|
-
for (const session of subscriptions) {
|
|
244
|
-
policies.set(session.definition.route, {
|
|
245
|
-
displayName: `${session.definition.displayName.replace(/\s*\([^)]*\)$/u, "")} (OAuth)`,
|
|
246
|
-
isAuthenticated: async () => (await session.status()).authenticated,
|
|
247
|
-
onAuthFailure: () => session.invalidateAccessToken(),
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
if (codexFast !== undefined && codexSession !== undefined) {
|
|
251
|
-
policies.set(CODEX_OAUTH_FAST_ROUTE, {
|
|
252
|
-
displayName: "OpenAI Codex Fast requested (OAuth)",
|
|
253
|
-
isAuthenticated: async () => (await codexSession.status()).authenticated,
|
|
254
|
-
includeModel: (modelId) => codexFast.isEligible(modelId),
|
|
255
|
-
onAuthFailure: () => codexSession.invalidateAccessToken(),
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const inner = new PiAiAdapter({
|
|
260
|
-
profiles: () => {
|
|
261
|
-
const profiles = new Map<string, ResolvedPiAiProviderProfile>();
|
|
262
|
-
profiles.set(
|
|
263
|
-
GROK_BUILD_ROUTE,
|
|
264
|
-
profile(GROK_BUILD_ROUTE, "xAI Grok Build", grok.provider(), retryPolicy, grokBuildFingerprintHeaders()),
|
|
265
|
-
);
|
|
266
|
-
for (const session of subscriptions) {
|
|
267
|
-
profiles.set(
|
|
268
|
-
session.definition.nativeProviderId,
|
|
269
|
-
profile(session.definition.nativeProviderId, session.definition.displayName, session.provider(), retryPolicy),
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
if (codexFast !== undefined && codexSession !== undefined) {
|
|
273
|
-
const wrapped = withCodexFastRouting(codexSession.provider(), {
|
|
274
|
-
isEligible: (modelId) => codexFast.isEligible(modelId),
|
|
275
|
-
profileProviderId: CODEX_OAUTH_FAST_ROUTE,
|
|
276
|
-
nativeProviderId: CODEX_PI_PROVIDER,
|
|
277
|
-
});
|
|
278
|
-
// Models.streamSimple dispatches on model.provider. Advertise the Fast
|
|
279
|
-
// profile id on the catalog so the wrapper runs, then restore native
|
|
280
|
-
// identity inside withCodexFastRouting before the wire call.
|
|
281
|
-
const fastProvider = {
|
|
282
|
-
...wrapped,
|
|
283
|
-
getModels: () =>
|
|
284
|
-
wrapped
|
|
285
|
-
.getModels()
|
|
286
|
-
.map((model) =>
|
|
287
|
-
model.provider === CODEX_OAUTH_FAST_ROUTE ? model : { ...model, provider: CODEX_OAUTH_FAST_ROUTE },
|
|
288
|
-
),
|
|
289
|
-
};
|
|
290
|
-
profiles.set(
|
|
291
|
-
CODEX_OAUTH_FAST_ROUTE,
|
|
292
|
-
profile(
|
|
293
|
-
CODEX_OAUTH_FAST_ROUTE,
|
|
294
|
-
"OpenAI Codex Fast requested",
|
|
295
|
-
fastProvider as unknown as ResolvedPiAiProviderProfile["piProvider"],
|
|
296
|
-
retryPolicy,
|
|
297
|
-
),
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
return profiles;
|
|
301
|
-
},
|
|
302
|
-
resolveApiKey: async (provider) => {
|
|
303
|
-
if (provider === GROK_BUILD_ROUTE) {
|
|
304
|
-
return resolveOAuthToken("Grok Build", async () => {
|
|
305
|
-
const auth = await grok.models.getAuth(XAI_PI_PROVIDER, { minOAuthValidityMs: MIN_OAUTH_VALIDITY_MS });
|
|
306
|
-
return auth?.auth.apiKey;
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
const session =
|
|
310
|
-
provider === CODEX_OAUTH_FAST_ROUTE ? byNativeId.get(CODEX_PI_PROVIDER) : byNativeId.get(provider);
|
|
311
|
-
if (session === undefined) throw new LlmError(`Unknown OAuth provider "${provider}"`, "NO_ADAPTER");
|
|
312
|
-
return resolveOAuthToken(session.definition.displayName, () => session.resolveAccessToken());
|
|
313
|
-
},
|
|
314
|
-
auth: oauthAuthInjection(grok, subscriptions),
|
|
315
|
-
resolveAttachments,
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
// The Fast wrapper restores wire/replay model identity to openai-codex.
|
|
319
|
-
// Keep the opaque envelope untouched and map public Fast source identity to
|
|
320
|
-
// that native replay provider before PiAiAdapter validates it.
|
|
321
|
-
const replayProviders = new Map(aliases);
|
|
322
|
-
replayProviders.set(CODEX_OAUTH_FAST_ROUTE, CODEX_PI_PROVIDER);
|
|
323
|
-
return new AliasLlmAdapter(inner, aliases, policies, replayProviders);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Resolve an OAuth access token for one route, translating a failed refresh
|
|
328
|
-
* (revoked refresh token, dead grant) into MISSING_CREDENTIAL so the failure
|
|
329
|
-
* is not retried and the user is told to sign in again rather than shown a
|
|
330
|
-
* bare upstream 401.
|
|
331
|
-
*/
|
|
332
|
-
async function resolveOAuthToken(
|
|
333
|
-
displayName: string,
|
|
334
|
-
getAccessToken: () => Promise<string | undefined>,
|
|
335
|
-
): Promise<string> {
|
|
336
|
-
let accessToken: string | undefined;
|
|
337
|
-
try {
|
|
338
|
-
accessToken = await getAccessToken();
|
|
339
|
-
} catch (error) {
|
|
340
|
-
throw new LlmError(
|
|
341
|
-
`${displayName} could not refresh its sign-in (${safeMessage(error)}).` +
|
|
342
|
-
" Open Settings → Coding OAuth and sign in again.",
|
|
343
|
-
"MISSING_CREDENTIAL",
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
if (accessToken === undefined || accessToken.length === 0) return missingCredential(displayName);
|
|
347
|
-
return accessToken;
|
|
348
|
-
}
|