dsh-coding-subscription-oauth 0.6.2 → 0.6.4
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 +51 -27
- package/CONTRIBUTING.md +17 -8
- package/INSTALL.md +45 -44
- package/README.de.md +20 -20
- package/README.es.md +20 -20
- package/README.fr.md +20 -20
- package/README.ja.md +20 -20
- package/README.ko.md +20 -20
- package/README.md +23 -23
- package/README.pt-BR.md +20 -20
- package/README.ru.md +20 -20
- package/README.zh-CN.md +23 -23
- package/compatibility/dsh-bom.json +30 -30
- package/docs/00-project-rules.md +17 -0
- package/docs/02-architecture.md +11 -11
- package/docs/02-architecture.zh-CN.md +11 -11
- package/lib/bin.js +1333 -569
- package/lib/bin.js.map +4 -4
- 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 +3 -3
- package/lib/codex-images.d.ts +8 -0
- package/lib/codex-images.d.ts.map +1 -1
- package/lib/index.js +721 -25499
- package/lib/index.js.map +4 -4
- package/package.json +77 -77
- package/src/adapter.ts +75 -75
- package/src/alias-adapter.ts +17 -17
- package/src/capability-runtime.ts +1 -0
- package/src/capability-settings.ts +14 -1
- package/src/capability-tools.ts +23 -4
- package/src/client/GrokBuildSettings.tsx +3 -2
- package/src/client/constants.ts +7 -1
- package/src/client/locales.ts +5 -0
- package/src/client/parsers.ts +2 -0
- package/src/client/types.ts +2 -0
- package/src/codex-images.ts +19 -1
- package/src/compatibility.ts +14 -14
- package/src/index.ts +26 -26
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.4",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -39,18 +39,18 @@
|
|
|
39
39
|
"dsh-coding-oauth": "lib/bin.js",
|
|
40
40
|
"dsh-grok-build": "lib/bin.js"
|
|
41
41
|
},
|
|
42
|
-
"scripts": {
|
|
43
|
-
"check:bom": "node build/verify-dsh-bom.mjs",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"check:bom": "node build/verify-dsh-bom.mjs",
|
|
44
44
|
"clean": "node build/clean.mjs",
|
|
45
45
|
"typecheck": "tsc -b tsconfig.host.json tsconfig.client.json",
|
|
46
46
|
"build:server": "tsc -p tsconfig.build.json && tsc -p tsconfig.dts-bin.json && node build/build-server.mjs",
|
|
47
47
|
"build:client": "node build/build-client.mjs",
|
|
48
|
-
"build:artifacts": "pnpm run check:bom && pnpm run clean && pnpm run typecheck && pnpm run build:server && pnpm run build:client",
|
|
48
|
+
"build:artifacts": "pnpm run check:bom && pnpm run clean && pnpm run typecheck && pnpm run build:server && pnpm run build:client",
|
|
49
49
|
"build": "pnpm run release:build",
|
|
50
50
|
"test": "vitest run",
|
|
51
51
|
"test:watch": "vitest",
|
|
52
52
|
"lint": "biome check",
|
|
53
|
-
"check:next": "pnpm run check:bom && pnpm run lint && pnpm run typecheck && pnpm run test",
|
|
53
|
+
"check:next": "pnpm run check:bom && pnpm run lint && pnpm run typecheck && pnpm run test",
|
|
54
54
|
"check": "pnpm run lint && pnpm run release:build && pnpm run test",
|
|
55
55
|
"release:promote": "node build/promote-release.mjs",
|
|
56
56
|
"release:verify": "node build/verify-release.mjs",
|
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
"CHANGELOG.md",
|
|
84
84
|
"CONTRIBUTING.md",
|
|
85
85
|
"docs/00-project-rules.md",
|
|
86
|
-
"docs/02-architecture.md",
|
|
87
|
-
"docs/02-architecture.zh-CN.md",
|
|
88
|
-
"compatibility/dsh-bom.json",
|
|
86
|
+
"docs/02-architecture.md",
|
|
87
|
+
"docs/02-architecture.zh-CN.md",
|
|
88
|
+
"compatibility/dsh-bom.json",
|
|
89
89
|
"README.zh-CN.md",
|
|
90
90
|
"README.ja.md",
|
|
91
91
|
"README.ko.md",
|
|
@@ -102,34 +102,34 @@
|
|
|
102
102
|
"NOTICE"
|
|
103
103
|
],
|
|
104
104
|
"license": "Apache-2.0",
|
|
105
|
-
"dsh": {
|
|
106
|
-
"compatibility": {
|
|
107
|
-
"coreAbi": "dsh-coding-oauth-core/v1",
|
|
108
|
-
"verifiedBom": "./compatibility/dsh-bom.json",
|
|
109
|
-
"participant": "coding-subscription-oauth",
|
|
110
|
-
"diagnostics": "standalone",
|
|
111
|
-
"bom": {
|
|
112
|
-
"@deepseek-ai/cordis": "4.0.1",
|
|
113
|
-
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
114
|
-
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
115
|
-
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
116
|
-
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
117
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
|
|
118
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
119
|
-
"@deepseek-ai/dsh-client-web": "0.1.1-rc.2",
|
|
120
|
-
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
121
|
-
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
122
|
-
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
123
|
-
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
124
|
-
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
125
|
-
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
126
|
-
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
127
|
-
"@deepseek-ai/schemastery": "3.18.1",
|
|
128
|
-
"@earendil-works/pi-ai": "0.84.2",
|
|
129
|
-
"react": "18.3.1",
|
|
130
|
-
"react-dom": "18.3.1"
|
|
131
|
-
}
|
|
132
|
-
},
|
|
105
|
+
"dsh": {
|
|
106
|
+
"compatibility": {
|
|
107
|
+
"coreAbi": "dsh-coding-oauth-core/v1",
|
|
108
|
+
"verifiedBom": "./compatibility/dsh-bom.json",
|
|
109
|
+
"participant": "coding-subscription-oauth",
|
|
110
|
+
"diagnostics": "standalone",
|
|
111
|
+
"bom": {
|
|
112
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
113
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
114
|
+
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
115
|
+
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
116
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
117
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
|
|
118
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
119
|
+
"@deepseek-ai/dsh-client-web": "0.1.1-rc.2",
|
|
120
|
+
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
121
|
+
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
122
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
123
|
+
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
124
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
125
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
126
|
+
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
127
|
+
"@deepseek-ai/schemastery": "3.18.1",
|
|
128
|
+
"@earendil-works/pi-ai": "0.84.2",
|
|
129
|
+
"react": "18.3.1",
|
|
130
|
+
"react-dom": "18.3.1"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
133
|
"bundle": {
|
|
134
134
|
"patch": "./cordis.patch.yml"
|
|
135
135
|
},
|
|
@@ -142,25 +142,25 @@
|
|
|
142
142
|
"platform": "web"
|
|
143
143
|
}
|
|
144
144
|
},
|
|
145
|
-
"dependencies": {
|
|
146
|
-
|
|
147
|
-
"undici": "
|
|
148
|
-
},
|
|
145
|
+
"dependencies": {
|
|
146
|
+
"dsh-coding-oauth-core": "0.1.1",
|
|
147
|
+
"undici": "7.29.0"
|
|
148
|
+
},
|
|
149
149
|
"peerDependencies": {
|
|
150
|
-
"@deepseek-ai/cordis": "4.0.1",
|
|
151
|
-
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
152
|
-
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
153
|
-
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
154
|
-
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
155
|
-
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
156
|
-
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
157
|
-
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
158
|
-
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
159
|
-
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
150
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
151
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
152
|
+
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
153
|
+
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
154
|
+
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
155
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
156
|
+
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
157
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
158
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
159
|
+
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
160
160
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
161
161
|
"@earendil-works/pi-ai": "0.84.2",
|
|
162
|
-
"react": "18.3.1",
|
|
163
|
-
"react-dom": "18.3.1"
|
|
162
|
+
"react": "18.3.1",
|
|
163
|
+
"react-dom": "18.3.1"
|
|
164
164
|
},
|
|
165
165
|
"peerDependenciesMeta": {
|
|
166
166
|
"@deepseek-ai/cordis": {
|
|
@@ -181,40 +181,40 @@
|
|
|
181
181
|
"@deepseek-ai/dsh-tools": {
|
|
182
182
|
"optional": true
|
|
183
183
|
},
|
|
184
|
-
"react": {
|
|
185
|
-
"optional": true
|
|
186
|
-
},
|
|
187
|
-
"react-dom": {
|
|
188
|
-
"optional": true
|
|
184
|
+
"react": {
|
|
185
|
+
"optional": true
|
|
186
|
+
},
|
|
187
|
+
"react-dom": {
|
|
188
|
+
"optional": true
|
|
189
189
|
}
|
|
190
190
|
},
|
|
191
191
|
"devDependencies": {
|
|
192
192
|
"@biomejs/biome": "^2.5.8",
|
|
193
|
-
"@deepseek-ai/cordis": "4.0.1",
|
|
194
|
-
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
195
|
-
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
196
|
-
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
197
|
-
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
198
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
|
|
199
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
200
|
-
"@deepseek-ai/dsh-client-web": "0.1.1-rc.2",
|
|
201
|
-
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
202
|
-
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
203
|
-
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
204
|
-
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
205
|
-
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
206
|
-
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
207
|
-
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
193
|
+
"@deepseek-ai/cordis": "4.0.1",
|
|
194
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
|
|
195
|
+
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
196
|
+
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
197
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
198
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
|
|
199
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
|
|
200
|
+
"@deepseek-ai/dsh-client-web": "0.1.1-rc.2",
|
|
201
|
+
"@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
|
|
202
|
+
"@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
|
|
203
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
|
|
204
|
+
"@deepseek-ai/dsh-invariants": "0.1.1-rc.2",
|
|
205
|
+
"@deepseek-ai/dsh-llm": "0.1.1-rc.2",
|
|
206
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.1.1-rc.2",
|
|
207
|
+
"@deepseek-ai/dsh-tools": "0.1.1-rc.2",
|
|
208
208
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
209
209
|
"@earendil-works/pi-ai": "0.84.2",
|
|
210
210
|
"@types/node": "^22.20.0",
|
|
211
|
-
"@types/react": "~18.3.1",
|
|
212
|
-
"@types/react-dom": "18.3.7",
|
|
211
|
+
"@types/react": "~18.3.1",
|
|
212
|
+
"@types/react-dom": "18.3.7",
|
|
213
213
|
"esbuild": "^0.28.2",
|
|
214
|
-
"react": "18.3.1",
|
|
215
|
-
"react-dom": "18.3.1",
|
|
214
|
+
"react": "18.3.1",
|
|
215
|
+
"react-dom": "18.3.1",
|
|
216
216
|
"typescript": "^6.0.3",
|
|
217
|
-
"undici": "
|
|
217
|
+
"undici": "7.29.0",
|
|
218
218
|
"vitest": "^4.1.8"
|
|
219
219
|
},
|
|
220
220
|
"overrides": {
|
package/src/adapter.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import type { AttachmentStore } from "@deepseek-ai/dsh-attachment";
|
|
4
4
|
import type { RetryPolicyConfig } from "@deepseek-ai/dsh-llm";
|
|
5
5
|
import { type LlmAdapter, LlmError, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
6
|
-
import type { PiAiAdapterOptions, ResolvedPiAiProviderProfile } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
6
|
+
import type { PiAiAdapterOptions, ResolvedPiAiProviderProfile } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
7
7
|
import { PiAiAdapter } from "@deepseek-ai/dsh-llm-pi-ai";
|
|
8
8
|
import type { AliasLlmRoutePolicy } from "./alias-adapter.ts";
|
|
9
9
|
import { AliasLlmAdapter } from "./alias-adapter.ts";
|
|
@@ -25,60 +25,60 @@ import {
|
|
|
25
25
|
import type { OAuthProviderSession } from "./oauth-session.ts";
|
|
26
26
|
import { grokBuildBaselineModels, grokBuildFingerprintHeaders } from "./provider.ts";
|
|
27
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
|
-
}
|
|
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
82
|
|
|
83
83
|
/** Prefer grok-4.6 when the current (live or baseline) list has it. */
|
|
84
84
|
export function preferredGrokBuildModel(models: readonly { id: string }[] = grokBuildBaselineModels()): string {
|
|
@@ -139,8 +139,8 @@ function profile(
|
|
|
139
139
|
retryPolicy ?? CODING_OAUTH_RETRY_POLICY,
|
|
140
140
|
"dsh-coding-subscription-oauth retryPolicy",
|
|
141
141
|
),
|
|
142
|
-
configuredMaxTokens: new Map(),
|
|
143
|
-
...REQUEST_IMAGE_POLICY,
|
|
142
|
+
configuredMaxTokens: new Map(),
|
|
143
|
+
...REQUEST_IMAGE_POLICY,
|
|
144
144
|
...(headers === undefined ? {} : { headers }),
|
|
145
145
|
piProvider,
|
|
146
146
|
};
|
|
@@ -151,7 +151,7 @@ export function createGrokBuildAdapter(
|
|
|
151
151
|
session: GrokBuildSession,
|
|
152
152
|
resolveAttachments: () => AttachmentStore | undefined,
|
|
153
153
|
): PiAiAdapter {
|
|
154
|
-
return new PiAiAdapter({
|
|
154
|
+
return new PiAiAdapter({
|
|
155
155
|
profiles: () =>
|
|
156
156
|
new Map<string, ResolvedPiAiProviderProfile>([
|
|
157
157
|
[
|
|
@@ -159,13 +159,13 @@ export function createGrokBuildAdapter(
|
|
|
159
159
|
profile(GROK_BUILD_ROUTE, "xAI Grok Build", session.provider(), undefined, grokBuildFingerprintHeaders()),
|
|
160
160
|
],
|
|
161
161
|
]),
|
|
162
|
-
resolveApiKey: async () =>
|
|
162
|
+
resolveApiKey: async () =>
|
|
163
163
|
resolveOAuthToken("Grok Build", async () => {
|
|
164
164
|
const auth = await session.models.getAuth(XAI_PI_PROVIDER, { minOAuthValidityMs: MIN_OAUTH_VALIDITY_MS });
|
|
165
165
|
return auth?.auth.apiKey;
|
|
166
|
-
}),
|
|
167
|
-
auth: oauthAuthInjection(session, []),
|
|
168
|
-
resolveAttachments,
|
|
166
|
+
}),
|
|
167
|
+
auth: oauthAuthInjection(session, []),
|
|
168
|
+
resolveAttachments,
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
171
|
|
|
@@ -256,7 +256,7 @@ export function createCodingOAuthAdapter(
|
|
|
256
256
|
});
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
const inner = new PiAiAdapter({
|
|
259
|
+
const inner = new PiAiAdapter({
|
|
260
260
|
profiles: () => {
|
|
261
261
|
const profiles = new Map<string, ResolvedPiAiProviderProfile>();
|
|
262
262
|
profiles.set(
|
|
@@ -299,7 +299,7 @@ export function createCodingOAuthAdapter(
|
|
|
299
299
|
}
|
|
300
300
|
return profiles;
|
|
301
301
|
},
|
|
302
|
-
resolveApiKey: async (provider) => {
|
|
302
|
+
resolveApiKey: async (provider) => {
|
|
303
303
|
if (provider === GROK_BUILD_ROUTE) {
|
|
304
304
|
return resolveOAuthToken("Grok Build", async () => {
|
|
305
305
|
const auth = await grok.models.getAuth(XAI_PI_PROVIDER, { minOAuthValidityMs: MIN_OAUTH_VALIDITY_MS });
|
|
@@ -309,19 +309,19 @@ export function createCodingOAuthAdapter(
|
|
|
309
309
|
const session =
|
|
310
310
|
provider === CODEX_OAUTH_FAST_ROUTE ? byNativeId.get(CODEX_PI_PROVIDER) : byNativeId.get(provider);
|
|
311
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,
|
|
312
|
+
return resolveOAuthToken(session.definition.displayName, () => session.resolveAccessToken());
|
|
313
|
+
},
|
|
314
|
+
auth: oauthAuthInjection(grok, subscriptions),
|
|
315
|
+
resolveAttachments,
|
|
316
316
|
});
|
|
317
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
|
-
}
|
|
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
325
|
|
|
326
326
|
/**
|
|
327
327
|
* Resolve an OAuth access token for one route, translating a failed refresh
|
package/src/alias-adapter.ts
CHANGED
|
@@ -36,10 +36,10 @@ export interface AliasLlmRoutePolicy {
|
|
|
36
36
|
onAuthFailure?: () => Promise<void>;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export function normalizeReplayForRoute(
|
|
40
|
-
message: GenerateOptions["messages"][number],
|
|
41
|
-
route: string,
|
|
42
|
-
nativeReplayProvider: string,
|
|
39
|
+
export function normalizeReplayForRoute(
|
|
40
|
+
message: GenerateOptions["messages"][number],
|
|
41
|
+
route: string,
|
|
42
|
+
nativeReplayProvider: string,
|
|
43
43
|
): GenerateOptions["messages"][number] {
|
|
44
44
|
if (message.role !== "assistant" || message.source.kind !== "model") return message;
|
|
45
45
|
if (message.source.provider !== route) {
|
|
@@ -47,10 +47,10 @@ export function normalizeReplayForRoute(
|
|
|
47
47
|
const { replayState: _foreignReplay, ...source } = message.source;
|
|
48
48
|
return { ...message, source };
|
|
49
49
|
}
|
|
50
|
-
// The rc.2 envelope stays entirely opaque. PiAiAdapter only keys replay
|
|
51
|
-
// validation from source.provider, so restore the native provider identity
|
|
52
|
-
// without inspecting or changing replayState.
|
|
53
|
-
return { ...message, source: { ...message.source, provider: nativeReplayProvider } };
|
|
50
|
+
// The rc.2 envelope stays entirely opaque. PiAiAdapter only keys replay
|
|
51
|
+
// validation from source.provider, so restore the native provider identity
|
|
52
|
+
// without inspecting or changing replayState.
|
|
53
|
+
return { ...message, source: { ...message.source, provider: nativeReplayProvider } };
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -58,11 +58,11 @@ export function normalizeReplayForRoute(
|
|
|
58
58
|
* Harness route names. Every public operation translates exactly once.
|
|
59
59
|
*/
|
|
60
60
|
export class AliasLlmAdapter extends LlmAdapter {
|
|
61
|
-
constructor(
|
|
62
|
-
private readonly inner: LlmAdapter,
|
|
63
|
-
private readonly aliases: ReadonlyMap<string, string>,
|
|
64
|
-
private readonly policies: ReadonlyMap<string, AliasLlmRoutePolicy> = new Map(),
|
|
65
|
-
private readonly replayProviders: ReadonlyMap<string, string> = aliases,
|
|
61
|
+
constructor(
|
|
62
|
+
private readonly inner: LlmAdapter,
|
|
63
|
+
private readonly aliases: ReadonlyMap<string, string>,
|
|
64
|
+
private readonly policies: ReadonlyMap<string, AliasLlmRoutePolicy> = new Map(),
|
|
65
|
+
private readonly replayProviders: ReadonlyMap<string, string> = aliases,
|
|
66
66
|
) {
|
|
67
67
|
super();
|
|
68
68
|
}
|
|
@@ -109,9 +109,9 @@ export class AliasLlmAdapter extends LlmAdapter {
|
|
|
109
109
|
async *stream(options: GenerateOptions): AsyncIterable<StreamChunk> {
|
|
110
110
|
const route = options.provider;
|
|
111
111
|
const native = this.nativeProvider(route);
|
|
112
|
-
const messages = options.messages.map((message) =>
|
|
113
|
-
normalizeReplayForRoute(message, route, this.replayProviders.get(route) ?? native),
|
|
114
|
-
);
|
|
112
|
+
const messages = options.messages.map((message) =>
|
|
113
|
+
normalizeReplayForRoute(message, route, this.replayProviders.get(route) ?? native),
|
|
114
|
+
);
|
|
115
115
|
let authFailureNotified = false;
|
|
116
116
|
for await (const raw of this.inner.stream({ ...options, provider: native, messages })) {
|
|
117
117
|
const chunk =
|
|
@@ -141,7 +141,7 @@ export class AliasLlmAdapter extends LlmAdapter {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
-
yield chunk;
|
|
144
|
+
yield chunk;
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -302,6 +302,7 @@ function sameSettings(left: CapabilitySettings, right: CapabilitySettings): bool
|
|
|
302
302
|
left.codexSearch === right.codexSearch &&
|
|
303
303
|
left.codexImages === right.codexImages &&
|
|
304
304
|
left.codexImageEdits === right.codexImageEdits &&
|
|
305
|
+
left.codexImagesAnyModel === right.codexImagesAnyModel &&
|
|
305
306
|
left.codexUsage === right.codexUsage &&
|
|
306
307
|
left.codexFast === right.codexFast &&
|
|
307
308
|
left.grokImagineImage === right.grokImagineImage &&
|
|
@@ -18,6 +18,7 @@ export const CAPABILITY_FLAG_KEYS = [
|
|
|
18
18
|
"codexSearch",
|
|
19
19
|
"codexImages",
|
|
20
20
|
"codexImageEdits",
|
|
21
|
+
"codexImagesAnyModel",
|
|
21
22
|
"codexUsage",
|
|
22
23
|
"codexFast",
|
|
23
24
|
"grokImagineImage",
|
|
@@ -39,6 +40,8 @@ export interface CapabilitySettings {
|
|
|
39
40
|
readonly codexSearch: boolean;
|
|
40
41
|
readonly codexImages: boolean;
|
|
41
42
|
readonly codexImageEdits: boolean;
|
|
43
|
+
/** Allow non-Codex-route models to use the Codex image generate/edit tools. */
|
|
44
|
+
readonly codexImagesAnyModel: boolean;
|
|
42
45
|
readonly codexUsage: boolean;
|
|
43
46
|
readonly codexFast: boolean;
|
|
44
47
|
readonly grokImagineImage: boolean;
|
|
@@ -67,6 +70,7 @@ export const DEFAULT_CAPABILITY_SETTINGS: CapabilitySettings = Object.freeze({
|
|
|
67
70
|
codexSearch: false,
|
|
68
71
|
codexImages: false,
|
|
69
72
|
codexImageEdits: false,
|
|
73
|
+
codexImagesAnyModel: false,
|
|
70
74
|
codexUsage: false,
|
|
71
75
|
codexFast: false,
|
|
72
76
|
grokImagineImage: false,
|
|
@@ -84,6 +88,7 @@ export const CapabilitySettingsSchema = Schema.object({
|
|
|
84
88
|
codexSearch: Schema.boolean().default(false),
|
|
85
89
|
codexImages: Schema.boolean().default(false),
|
|
86
90
|
codexImageEdits: Schema.boolean().default(false),
|
|
91
|
+
codexImagesAnyModel: Schema.boolean().default(false),
|
|
87
92
|
codexUsage: Schema.boolean().default(false),
|
|
88
93
|
codexFast: Schema.boolean().default(false),
|
|
89
94
|
grokImagineImage: Schema.boolean().default(false),
|
|
@@ -238,6 +243,7 @@ export function capabilityFlags(settings: CapabilitySettings): Pick<CapabilitySe
|
|
|
238
243
|
codexSearch: settings.codexSearch,
|
|
239
244
|
codexImages: settings.codexImages,
|
|
240
245
|
codexImageEdits: settings.codexImageEdits,
|
|
246
|
+
codexImagesAnyModel: settings.codexImagesAnyModel,
|
|
241
247
|
codexUsage: settings.codexUsage,
|
|
242
248
|
codexFast: settings.codexFast,
|
|
243
249
|
grokImagineImage: settings.grokImagineImage,
|
|
@@ -272,10 +278,15 @@ export function resolveCapabilitySettings(
|
|
|
272
278
|
*/
|
|
273
279
|
export function normalizeCapabilitySettings(input?: unknown): CapabilitySettings {
|
|
274
280
|
const patch = normalizeCapabilitySettingsPatch(input);
|
|
281
|
+
const codexImages = patch.codexImages ?? DEFAULT_CAPABILITY_SETTINGS.codexImages;
|
|
275
282
|
return Object.freeze({
|
|
276
283
|
codexSearch: patch.codexSearch ?? DEFAULT_CAPABILITY_SETTINGS.codexSearch,
|
|
277
|
-
codexImages
|
|
284
|
+
codexImages,
|
|
278
285
|
codexImageEdits: patch.codexImageEdits ?? DEFAULT_CAPABILITY_SETTINGS.codexImageEdits,
|
|
286
|
+
// any-model is meaningless without images; clear at admit so UI cascade alone cannot leave it on
|
|
287
|
+
codexImagesAnyModel: codexImages
|
|
288
|
+
? (patch.codexImagesAnyModel ?? DEFAULT_CAPABILITY_SETTINGS.codexImagesAnyModel)
|
|
289
|
+
: false,
|
|
279
290
|
codexUsage: patch.codexUsage ?? DEFAULT_CAPABILITY_SETTINGS.codexUsage,
|
|
280
291
|
codexFast: patch.codexFast ?? DEFAULT_CAPABILITY_SETTINGS.codexFast,
|
|
281
292
|
grokImagineImage: patch.grokImagineImage ?? DEFAULT_CAPABILITY_SETTINGS.grokImagineImage,
|
|
@@ -296,6 +307,7 @@ export function normalizeCapabilitySettingsPatch(input?: unknown): CapabilitySet
|
|
|
296
307
|
codexSearch?: boolean;
|
|
297
308
|
codexImages?: boolean;
|
|
298
309
|
codexImageEdits?: boolean;
|
|
310
|
+
codexImagesAnyModel?: boolean;
|
|
299
311
|
codexUsage?: boolean;
|
|
300
312
|
codexFast?: boolean;
|
|
301
313
|
grokImagineImage?: boolean;
|
|
@@ -308,6 +320,7 @@ export function normalizeCapabilitySettingsPatch(input?: unknown): CapabilitySet
|
|
|
308
320
|
assignFlag(patch, "codexSearch", flags["codexSearch"]);
|
|
309
321
|
assignFlag(patch, "codexImages", flags["codexImages"]);
|
|
310
322
|
assignFlag(patch, "codexImageEdits", flags["codexImageEdits"]);
|
|
323
|
+
assignFlag(patch, "codexImagesAnyModel", flags["codexImagesAnyModel"]);
|
|
311
324
|
assignFlag(patch, "codexUsage", flags["codexUsage"]);
|
|
312
325
|
assignFlag(patch, "codexFast", flags["codexFast"]);
|
|
313
326
|
assignFlag(patch, "grokImagineImage", flags["grokImagineImage"]);
|
package/src/capability-tools.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
type CodexImageQuality,
|
|
23
23
|
type CodexImageResult,
|
|
24
24
|
type CodexImageRoute,
|
|
25
|
+
type CodexImageRoutePolicy,
|
|
25
26
|
type CodexImageSessionContext,
|
|
26
27
|
type CodexImageSize,
|
|
27
28
|
createCodexImageController,
|
|
@@ -72,7 +73,18 @@ const IMAGINE_MEDIA_PREFIX = "/plugins/dsh-grok-build/imagine/media/";
|
|
|
72
73
|
export type CapabilityImagineClient = Pick<GrokImagineClient, "generateImage" | "startVideo" | "videoStatus">;
|
|
73
74
|
|
|
74
75
|
/** Per-exec Codex controller factory. Tests inject a fake; production binds auth + attachments. */
|
|
75
|
-
export type CreateCodexImageController = (
|
|
76
|
+
export type CreateCodexImageController = (
|
|
77
|
+
session: CodexImageSessionContext,
|
|
78
|
+
routePolicy: CodexImageRoutePolicy,
|
|
79
|
+
) => CodexImageController;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Route gate for the Codex image tools. `codexImagesAnyModel` relaxes the
|
|
83
|
+
* Codex-route requirement; otherwise the gate stays `codex-capable`.
|
|
84
|
+
*/
|
|
85
|
+
export function codexImageRoutePolicy(settings: CapabilitySettings): CodexImageRoutePolicy {
|
|
86
|
+
return settings.codexImagesAnyModel ? "any" : "codex-capable";
|
|
87
|
+
}
|
|
76
88
|
|
|
77
89
|
/** Resolve authoritative host model metadata for the calling route. */
|
|
78
90
|
export type ResolveCodexImageRoute = (exec: ToolRunContext) => Promise<CodexImageRoute | undefined>;
|
|
@@ -390,11 +402,12 @@ export async function createCapabilityTools(options: CapabilityToolsOptions): Pr
|
|
|
390
402
|
const { defineTool } = await import("@deepseek-ai/dsh-tools");
|
|
391
403
|
const createController: CreateCodexImageController =
|
|
392
404
|
options.createCodexController ??
|
|
393
|
-
((session) =>
|
|
405
|
+
((session, routePolicy) =>
|
|
394
406
|
createCodexImageController({
|
|
395
407
|
auth: options.auth,
|
|
396
408
|
attachments: options.attachments,
|
|
397
409
|
session,
|
|
410
|
+
routePolicy,
|
|
398
411
|
}));
|
|
399
412
|
|
|
400
413
|
const generate = defineTool({
|
|
@@ -438,7 +451,10 @@ export async function createCapabilityTools(options: CapabilityToolsOptions): Pr
|
|
|
438
451
|
const settings = options.current();
|
|
439
452
|
if (!settings.codexImages) disabled(CODEX_IMAGE_GENERATE_TOOL);
|
|
440
453
|
const n = resolveImageCount(args.n, settings);
|
|
441
|
-
const result = await createController(
|
|
454
|
+
const result = await createController(
|
|
455
|
+
await generateSession(exec, options.resolveCodexImageRoute),
|
|
456
|
+
codexImageRoutePolicy(settings),
|
|
457
|
+
).generate(
|
|
442
458
|
{
|
|
443
459
|
prompt: args.prompt,
|
|
444
460
|
n,
|
|
@@ -499,7 +515,10 @@ export async function createCapabilityTools(options: CapabilityToolsOptions): Pr
|
|
|
499
515
|
const settings = options.current();
|
|
500
516
|
if (!settings.codexImageEdits || !settings.codexImages) disabled(CODEX_IMAGE_EDIT_TOOL);
|
|
501
517
|
const n = resolveImageCount(args.n, settings);
|
|
502
|
-
const result = await createController(
|
|
518
|
+
const result = await createController(
|
|
519
|
+
await requireEditSession(exec, options.resolveCodexImageRoute),
|
|
520
|
+
codexImageRoutePolicy(settings),
|
|
521
|
+
).edit(
|
|
503
522
|
{
|
|
504
523
|
prompt: args.prompt,
|
|
505
524
|
imageIds: args.imageIds,
|
|
@@ -416,9 +416,10 @@ export function GrokBuildSettings({ t }: GrokBuildSettingsProps) {
|
|
|
416
416
|
const patchCapability = async (key: CapabilitySettingKey, value: boolean | number): Promise<boolean> => {
|
|
417
417
|
if (capabilities === undefined || !capabilities.writable) return false;
|
|
418
418
|
if (key === "codexImageEdits" && value === true && !capabilities.value.codexImages) return false;
|
|
419
|
+
if (key === "codexImagesAnyModel" && value === true && !capabilities.value.codexImages) return false;
|
|
419
420
|
const patch: Partial<CapabilitySettingsView> =
|
|
420
|
-
key === "codexImages" && value === false
|
|
421
|
-
? { codexImages: false, codexImageEdits: false }
|
|
421
|
+
key === "codexImages" && value === false
|
|
422
|
+
? { codexImages: false, codexImageEdits: false, codexImagesAnyModel: false }
|
|
422
423
|
: ({ [key]: value } as Partial<CapabilitySettingsView>);
|
|
423
424
|
setCapabilitiesBusy(true);
|
|
424
425
|
try {
|