dsh-coding-subscription-oauth 0.6.4 → 0.7.0
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 +291 -255
- package/CONTRIBUTING.md +138 -129
- package/INSTALL.md +261 -256
- package/LICENSE +19 -19
- package/NOTICE +11 -11
- package/README.de.md +303 -303
- package/README.es.md +304 -304
- package/README.fr.md +304 -304
- package/README.ja.md +304 -304
- package/README.ko.md +304 -304
- package/README.md +321 -320
- package/README.pt-BR.md +304 -304
- package/README.ru.md +304 -304
- package/README.zh-CN.md +319 -318
- package/compatibility/dsh-bom.json +36 -30
- package/cordis.patch.yml +13 -13
- package/docs/00-project-rules.md +213 -212
- package/docs/02-architecture.md +142 -138
- package/docs/02-architecture.zh-CN.md +142 -138
- package/lib/auth-routes.d.ts +10 -1
- package/lib/auth-routes.d.ts.map +1 -1
- package/lib/bin.js +483 -50
- package/lib/bin.js.map +4 -4
- package/lib/client.js +5 -5
- package/lib/client.js.map +4 -4
- package/lib/compatibility.d.ts +0 -1
- package/lib/compatibility.d.ts.map +1 -1
- 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/ids.d.ts +4 -0
- package/lib/ids.d.ts.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +730 -196
- package/lib/index.js.map +4 -4
- package/lib/invariant.js.map +1 -1
- package/lib/kimi-errors.d.ts +2 -12
- package/lib/kimi-errors.d.ts.map +1 -1
- package/lib/oauth-session.d.ts +2 -0
- package/lib/oauth-session.d.ts.map +1 -1
- package/lib/session.d.ts +2 -0
- package/lib/session.d.ts.map +1 -1
- package/lib/store.d.ts +73 -1
- package/lib/store.d.ts.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 +224 -221
- package/patches/dsh-agy@0.1.2.patch +25 -25
- package/scripts/release.mjs +187 -186
- package/scripts/smoke-deployed-routes.mjs +146 -146
- package/scripts/verify-deployed-catalog.mjs +87 -87
- 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/docs/02-architecture.md
CHANGED
|
@@ -1,138 +1,142 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
> [**中文版**](02-architecture.zh-CN.md) · English
|
|
4
|
-
|
|
5
|
-
This document describes the internal architecture of `dsh-coding-subscription-oauth`. It is the source for the technical notes in `README.md` and is intended for contributors and maintainers.
|
|
6
|
-
|
|
7
|
-
## 1. Routes and native providers
|
|
8
|
-
|
|
9
|
-
```text
|
|
10
|
-
Harness route pi-ai provider request authentication
|
|
11
|
-
────────────────────────────────────────────────────────────
|
|
12
|
-
grok-build grok-build xAI access token + Grok CLI headers
|
|
13
|
-
codex-oauth openai-codex OAuth token → apiKey override
|
|
14
|
-
kimi-code-oauth kimi-coding OAuth token → Authorization: Bearer
|
|
15
|
-
claude-code-oauth anthropic sk-ant-oat token → Claude Code headers
|
|
16
|
-
agy dsh-agy external dsh-agy own account pool
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
External routes and the pi-ai native ids are separated by `AliasLlmAdapter`. `PiAiAdapter` always sees the native provider id, so Codex tool-calls, Claude compatibility checks and the Kimi Anthropic transport do not break when a route is renamed.
|
|
20
|
-
|
|
21
|
-
"Authenticated" in model discovery is defined as an existing, structurally valid, refreshable OAuth credential; the selector does not probe upstream on every open. Credentials that upstream has revoked but are still locally valid are recognized during token refresh or inference, avoiding extra network requests on catalog load.
|
|
22
|
-
|
|
23
|
-
## 2. Host data flow
|
|
24
|
-
|
|
25
|
-
```text
|
|
26
|
-
Settings / CLI
|
|
27
|
-
│
|
|
28
|
-
├─ GrokBuildWebAuth ── Grok custom PKCE/device
|
|
29
|
-
│ └─ .grok-build-auth.json
|
|
30
|
-
│
|
|
31
|
-
├─ SubscriptionWebAuth ── pi-ai OAuth login/refresh
|
|
32
|
-
│ ├─ Codex ── .codex-oauth-auth.json
|
|
33
|
-
│ ├─ Kimi ── .kimi-code-oauth-auth.json
|
|
34
|
-
│ └─ Claude ── .claude-code-oauth-auth.json
|
|
35
|
-
│
|
|
36
|
-
└─ OAuthImportSession ── read-only allowlisted CLI discovery
|
|
37
|
-
└─ explicit one-way Pull (preview ticket → dest store)
|
|
38
|
-
official CLI files are never written
|
|
39
|
-
|
|
40
|
-
OAuthProviderSession.resolveAccessToken()
|
|
41
|
-
└─ Models.getAuth(native id) # refresh-under-lock
|
|
42
|
-
└─ OAuthCredentialFileStore # 0600 + atomic write + cross-process lock
|
|
43
|
-
|
|
44
|
-
CapabilitySettingsController (default-off, applies: live)
|
|
45
|
-
└─ CapabilityRuntimeState
|
|
46
|
-
├─ Codex search / usage / gpt-image-2 images
|
|
47
|
-
├─ codex-oauth-fast (only after a fresh priority catalog)
|
|
48
|
-
└─ Grok Imagine (api.x.ai + XAI_API_KEY via DSH credentials)
|
|
49
|
-
|
|
50
|
-
ctx.llm route
|
|
51
|
-
└─ AliasLlmAdapter
|
|
52
|
-
└─ PiAiAdapter
|
|
53
|
-
└─ native pi-ai Provider.streamSimple()
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## 3. Module responsibilities
|
|
57
|
-
|
|
58
|
-
- `store.ts`: one file owns one provider credential; keeps the legacy Grok store API; `invalidate()` backdates `expires` after an upstream AUTH rejection.
|
|
59
|
-
- `oauth-providers.ts`: Codex/Kimi/Claude definitions, route metadata, request token bridge.
|
|
60
|
-
- `oauth-session.ts`: login, refresh, static model catalog and model-selection cache.
|
|
61
|
-
- `oauth-sources.ts`: allowlisted official Grok/Codex/Kimi/Claude CLI discovery; hardened lstat/`O_NOFOLLOW`/owner/mode/regular-file/size reads; one-use preview tickets (five minutes, max 32); never writes official CLI files.
|
|
62
|
-
- `oauth-import-routes.ts`: same-origin Pull HTTP API (discover → preview → commit/cancel) into the destination store lock.
|
|
63
|
-
- `alias-adapter.ts`: translates Harness routes, does not modify pi-ai `model.provider`, and runs a credential gate before `listModels()`; unauthenticated or unreadable credentials return an empty catalog, and the provider group name is `(OAuth)`. On an AUTH finish it invalidates the stored token so the harness retry can refresh first. The finish pipeline also remaps Kimi misclassified AUTH context overflow and xAI capacity wording → `RATE_LIMIT`.
|
|
64
|
-
- `grok-errors.ts
|
|
65
|
-
- `adapter.ts`: composes Grok with the three subscription profiles; asks pi-ai for a 60 s remaining-validity floor and registers a retry policy that includes AUTH plus transient codes (default 5 retries, 5 s → 80 s stacked exponential). Optionally wraps `codex-oauth-fast` as **Fast requested**.
|
|
66
|
-
- `auth-routes.ts`: legacy Grok API + the unified `/plugins/dsh-grok-build/oauth/*`; JSON writes use a 64 KiB bounded reader and return 400/413 for malformed/oversized bodies.
|
|
67
|
-
- `capability-settings.ts`: default-off live flags and limits (search 1–20, image count 1–4, artifact TTL 1 h–7 d).
|
|
68
|
-
- `capability-routes.ts`: secret-free capability snapshot plus optional Codex usage and Imagine credential-status routes.
|
|
69
|
-
- `capability-runtime.ts`: live bind/unbind of search, tools, and the Fast route after a fresh priority catalog.
|
|
70
|
-
- `capability-tools.ts`: optional Codex / Grok Imagine tool definitions; flags re-read at execute time. The default-off any-model image policy relaxes only the calling-route gate and retains Codex auth, session, attachment ownership, and edit authorization.
|
|
71
|
-
- `codex-http.ts`: opt-in private `chatgpt.com/backend-api` client (HTTPS-only, first-party host).
|
|
72
|
-
- `codex-search.ts` / `codex-usage.ts` / `codex-images.ts`: opt-in search, quota, and fixed `gpt-image-2` generate/edit (edits require current-session top-level attachment ownership).
|
|
73
|
-
- `codex-model-capabilities.ts`: live Codex service-tier cache; fail-closed Fast eligibility; injects `service_tier: priority` and the routing hint.
|
|
74
|
-
- `grok-imagine.ts`: official `api.x.ai` Imagine client (`grok-imagine-image-2.0` / `grok-imagine-video-1.5`); `XAI_API_KEY` via DSH credentials only; MIME/size/time/redirect/DNS download controls; frozen hosts `imgen.x.ai`, `videogen.x.ai`, `vidgen.x.ai`.
|
|
75
|
-
- `imagine-routes.ts`: same-origin loopback GET routes for generated images and video artifacts.
|
|
76
|
-
- `media-store.ts`: owner-private artifact store (256 MiB per-object and aggregate unique-byte hard caps, seven days).
|
|
77
|
-
- `client/`: four native account cards, CLI Pull, capability switches, gateway controls, and the external Antigravity status card.
|
|
78
|
-
- `proxy.ts`: process-wide undici dispatcher, but proxies only a reviewed domain whitelist.
|
|
79
|
-
- `gateway*.ts`: opt-in isolated loopback OpenAI/Anthropic-compatible HTTP server (default off; independent of the DSH web port).
|
|
80
|
-
- `dsh-host-adapter.ts` / `web-origin.ts`: isolate the changing DSH service surface and prefer a host-native `ownerRequestPolicy`; the fallback constrains loopback/SSH Host and Origin, while HTTPS proxy access jointly verifies the real peer, exact Origin/Host, Fetch Metadata, owner proof, and independent CSRF. A throwing or malformed host policy is denied without escaping the route boundary.
|
|
81
|
-
|
|
82
|
-
## 4. Web API
|
|
83
|
-
|
|
84
|
-
Unified interface:
|
|
85
|
-
|
|
86
|
-
```text
|
|
87
|
-
GET /plugins/dsh-grok-build/oauth/status
|
|
88
|
-
POST /plugins/dsh-grok-build/oauth/login
|
|
89
|
-
POST /plugins/dsh-grok-build/oauth/code
|
|
90
|
-
POST /plugins/dsh-grok-build/oauth/cancel
|
|
91
|
-
POST /plugins/dsh-grok-build/oauth/logout
|
|
92
|
-
POST /plugins/dsh-grok-build/oauth/models
|
|
93
|
-
|
|
94
|
-
GET /plugins/dsh-grok-build/oauth/sources
|
|
95
|
-
POST /plugins/dsh-grok-build/oauth/sources/preview
|
|
96
|
-
POST /plugins/dsh-grok-build/oauth/sources/commit
|
|
97
|
-
POST /plugins/dsh-grok-build/oauth/sources/cancel
|
|
98
|
-
|
|
99
|
-
GET /plugins/dsh-grok-build/capabilities
|
|
100
|
-
PATCH /plugins/dsh-grok-build/capabilities
|
|
101
|
-
PUT /plugins/dsh-grok-build/capabilities
|
|
102
|
-
GET /plugins/dsh-grok-build/codex/usage
|
|
103
|
-
GET /plugins/dsh-grok-build/imagine/credential-status
|
|
104
|
-
GET /plugins/dsh-grok-build/imagine/images/<id>
|
|
105
|
-
GET /plugins/dsh-grok-build/imagine/media/<id>
|
|
106
|
-
GET /plugins/dsh-grok-build/gateway
|
|
107
|
-
PATCH /plugins/dsh-grok-build/gateway
|
|
108
|
-
POST /plugins/dsh-grok-build/gateway/rotate
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
Write endpoints take `provider: grok|codex|kimi|claude` in the body. Responses contain only status, authorization URL, device user code, model ids and a non-sensitive expiry; they never contain access/refresh tokens. JSON request bodies are capped at 64 KiB before parsing.
|
|
112
|
-
|
|
113
|
-
Every Settings route shares `OwnerRequestPolicy`. `X-Forwarded-*` is forwarding metadata, never owner proof; a fallback policy missing any independent signal rejects remote requests. Status responses carry the server-derived `accessMode`, so the client does not infer SSH or proxy access from the hostname.
|
|
114
|
-
|
|
115
|
-
`/oauth/sources` is read-only discovery. Preview/commit is the explicit one-way Pull (tickets one-use, five minutes, max 32). Capability writes are secret-free compare-and-swap snapshots in the `coding-subscription-oauth` settings section and apply live. Eight flags default off; `searchResults` is 1–20 (default 5), `imageCount` is 1–4 (default 1), and `videoArtifactTtlMs` is 1 hour–7 days (default 7 days; UI 1–168 hours); decreases rewrite/clean existing expiries immediately, while increases affect only new artifacts. Imagine download routes are same-origin loopback GETs; they never return a signed upstream URL.
|
|
116
|
-
|
|
117
|
-
The legacy `/plugins/dsh-grok-build/auth/*` endpoints remain registered and reuse the same Grok controller.
|
|
118
|
-
|
|
119
|
-
## 5. Antigravity
|
|
120
|
-
|
|
121
|
-
This project does not replicate the private Google Antigravity protocol. The profile separately installs `dsh-agy@0.1.2`, which provides the `agy` route. Because the `/agy` dashboard in that version includes an export API with no authentication of its own, trusted-host deployments should disable `dsh-agy-web` in the profile's final `cordis.patch.yml` (see `INSTALL.md`) and keep only the host adapter and CLI. The profile uses a pnpm patch with a lockfile hash: with no Google session, `listModels()` returns empty; after authentication the provider group name is `Google Antigravity (OAuth)`.
|
|
122
|
-
|
|
123
|
-
## 6. Compatibility
|
|
124
|
-
|
|
125
|
-
The canonical package and repository name is **`dsh-coding-subscription-oauth`**. The previous GitHub URL still resolves to the same `main`, so old `dsh plugin add github:lninghaha/dsh-grok-build` commands continue to install the renamed package. The first public npm/GitHub Release was **`0.4.1`**. The current release is **`0.
|
|
126
|
-
|
|
127
|
-
Stable on-disk / in-process identifiers (do not rename without a migration):
|
|
128
|
-
|
|
129
|
-
- Cordis id: `llm-grok-build-oauth`
|
|
130
|
-
- Settings HTTP API: `/plugins/dsh-grok-build/oauth/*`, `/plugins/dsh-grok-build/capabilities`, `/plugins/dsh-grok-build/codex/usage`, `/plugins/dsh-grok-build/imagine/*`, and legacy `/plugins/dsh-grok-build/auth/*`
|
|
131
|
-
- Credential files: `$DSH_HOME/.grok-build-auth.json` and the other `*-oauth-auth.json` files
|
|
132
|
-
- Imagine credential: DSH credentials reference `XAI_API_KEY` (never Grok OAuth, never process-env fallback)
|
|
133
|
-
- CLI: `dsh-coding-oauth` (primary) and `dsh-grok-build` (alias)
|
|
134
|
-
- LLM routes: `grok-build`, `codex-oauth`, `kimi-code-oauth`, `claude-code-oauth`; optional `codex-oauth-fast` (v0.4.0, advertised only when a fresh live catalog lists `priority`)
|
|
135
|
-
|
|
136
|
-
New routes use the `*-oauth` alias and do not occupy `openai`, `xai` or `kimi-coding`. In v0.3.0 the `grok-build` fallback/default advances to `grok-4.6`; saved user defaults still win.
|
|
137
|
-
|
|
138
|
-
Hub and this standalone participant pin the same `dsh-coding-oauth-core@0.1.
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
> [**中文版**](02-architecture.zh-CN.md) · English
|
|
4
|
+
|
|
5
|
+
This document describes the internal architecture of `dsh-coding-subscription-oauth`. It is the source for the technical notes in `README.md` and is intended for contributors and maintainers.
|
|
6
|
+
|
|
7
|
+
## 1. Routes and native providers
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Harness route pi-ai provider request authentication
|
|
11
|
+
────────────────────────────────────────────────────────────
|
|
12
|
+
grok-build grok-build xAI access token + Grok CLI headers
|
|
13
|
+
codex-oauth openai-codex OAuth token → apiKey override
|
|
14
|
+
kimi-code-oauth kimi-coding OAuth token → Authorization: Bearer
|
|
15
|
+
claude-code-oauth anthropic sk-ant-oat token → Claude Code headers
|
|
16
|
+
agy dsh-agy external dsh-agy own account pool
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
External routes and the pi-ai native ids are separated by `AliasLlmAdapter`. `PiAiAdapter` always sees the native provider id, so Codex tool-calls, Claude compatibility checks and the Kimi Anthropic transport do not break when a route is renamed.
|
|
20
|
+
|
|
21
|
+
"Authenticated" in model discovery is defined as an existing, structurally valid, refreshable OAuth credential; the selector does not probe upstream on every open. Credentials that upstream has revoked but are still locally valid are recognized during token refresh or inference, avoiding extra network requests on catalog load.
|
|
22
|
+
|
|
23
|
+
## 2. Host data flow
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
Settings / CLI
|
|
27
|
+
│
|
|
28
|
+
├─ GrokBuildWebAuth ── Grok custom PKCE/device
|
|
29
|
+
│ └─ .grok-build-auth.json
|
|
30
|
+
│
|
|
31
|
+
├─ SubscriptionWebAuth ── pi-ai OAuth login/refresh
|
|
32
|
+
│ ├─ Codex ── .codex-oauth-auth.json
|
|
33
|
+
│ ├─ Kimi ── .kimi-code-oauth-auth.json
|
|
34
|
+
│ └─ Claude ── .claude-code-oauth-auth.json
|
|
35
|
+
│
|
|
36
|
+
└─ OAuthImportSession ── read-only allowlisted CLI discovery
|
|
37
|
+
└─ explicit one-way Pull (preview ticket → dest store)
|
|
38
|
+
official CLI files are never written
|
|
39
|
+
|
|
40
|
+
OAuthProviderSession.resolveAccessToken()
|
|
41
|
+
└─ Models.getAuth(native id) # refresh-under-lock
|
|
42
|
+
└─ OAuthCredentialFileStore # 0600 + atomic write + cross-process lock
|
|
43
|
+
|
|
44
|
+
CapabilitySettingsController (default-off, applies: live)
|
|
45
|
+
└─ CapabilityRuntimeState
|
|
46
|
+
├─ Codex search / usage / gpt-image-2 images
|
|
47
|
+
├─ codex-oauth-fast (only after a fresh priority catalog)
|
|
48
|
+
└─ Grok Imagine (api.x.ai + XAI_API_KEY via DSH credentials)
|
|
49
|
+
|
|
50
|
+
ctx.llm route
|
|
51
|
+
└─ AliasLlmAdapter
|
|
52
|
+
└─ PiAiAdapter
|
|
53
|
+
└─ native pi-ai Provider.streamSimple()
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 3. Module responsibilities
|
|
57
|
+
|
|
58
|
+
- `store.ts`: one file owns one provider credential; keeps the legacy Grok store API; `invalidate()` backdates `expires` after an upstream AUTH rejection.
|
|
59
|
+
- `oauth-providers.ts`: Codex/Kimi/Claude definitions, route metadata, request token bridge.
|
|
60
|
+
- `oauth-session.ts`: login, refresh, static model catalog and model-selection cache.
|
|
61
|
+
- `oauth-sources.ts`: allowlisted official Grok/Codex/Kimi/Claude CLI discovery; hardened lstat/`O_NOFOLLOW`/owner/mode/regular-file/size reads; one-use preview tickets (five minutes, max 32); never writes official CLI files.
|
|
62
|
+
- `oauth-import-routes.ts`: same-origin Pull HTTP API (discover → preview → commit/cancel) into the destination store lock.
|
|
63
|
+
- `alias-adapter.ts`: translates Harness routes, does not modify pi-ai `model.provider`, and runs a credential gate before `listModels()`; unauthenticated or unreadable credentials return an empty catalog, and the provider group name is `(OAuth)`. On an AUTH finish it invalidates the stored token so the harness retry can refresh first. The finish pipeline also remaps Kimi misclassified AUTH context overflow and xAI capacity wording → `RATE_LIMIT`.
|
|
64
|
+
- `grok-errors.ts` (re-export of `dsh-coding-oauth-core/grok-errors`): detects xAI “at capacity / high demand / priority processing / overloaded” messages and rewrites them to `RATE_LIMIT` so they are not skipped as `PI_AI_ERROR`.
|
|
65
|
+
- `adapter.ts`: composes Grok with the three subscription profiles; asks pi-ai for a 60 s remaining-validity floor and registers a retry policy that includes AUTH plus transient codes (default 5 retries, 5 s → 80 s stacked exponential). Optionally wraps `codex-oauth-fast` as **Fast requested**.
|
|
66
|
+
- `auth-routes.ts`: legacy Grok API + the unified `/plugins/dsh-grok-build/oauth/*`; JSON writes use a 64 KiB bounded reader and return 400/413 for malformed/oversized bodies.
|
|
67
|
+
- `capability-settings.ts`: default-off live flags and limits (search 1–20, image count 1–4, artifact TTL 1 h–7 d).
|
|
68
|
+
- `capability-routes.ts`: secret-free capability snapshot plus optional Codex usage and Imagine credential-status routes.
|
|
69
|
+
- `capability-runtime.ts`: live bind/unbind of search, tools, and the Fast route after a fresh priority catalog.
|
|
70
|
+
- `capability-tools.ts`: optional Codex / Grok Imagine tool definitions; flags re-read at execute time. The default-off any-model image policy relaxes only the calling-route gate and retains Codex auth, session, attachment ownership, and edit authorization.
|
|
71
|
+
- `codex-http.ts`: opt-in private `chatgpt.com/backend-api` client (HTTPS-only, first-party host).
|
|
72
|
+
- `codex-search.ts` / `codex-usage.ts` / `codex-images.ts`: opt-in search, quota, and fixed `gpt-image-2` generate/edit (edits require current-session top-level attachment ownership).
|
|
73
|
+
- `codex-model-capabilities.ts`: live Codex service-tier cache; fail-closed Fast eligibility; injects `service_tier: priority` and the routing hint.
|
|
74
|
+
- `grok-imagine.ts`: official `api.x.ai` Imagine client (`grok-imagine-image-2.0` / `grok-imagine-video-1.5`); `XAI_API_KEY` via DSH credentials only; MIME/size/time/redirect/DNS download controls; frozen hosts `imgen.x.ai`, `videogen.x.ai`, `vidgen.x.ai`.
|
|
75
|
+
- `imagine-routes.ts`: same-origin loopback GET routes for generated images and video artifacts.
|
|
76
|
+
- `media-store.ts`: owner-private artifact store (256 MiB per-object and aggregate unique-byte hard caps, seven days).
|
|
77
|
+
- `client/`: four native account cards, CLI Pull, capability switches, gateway controls, and the external Antigravity status card.
|
|
78
|
+
- `proxy.ts`: process-wide undici dispatcher, but proxies only a reviewed domain whitelist.
|
|
79
|
+
- `gateway*.ts`: opt-in isolated loopback OpenAI/Anthropic-compatible HTTP server (default off; independent of the DSH web port).
|
|
80
|
+
- `dsh-host-adapter.ts` / `web-origin.ts`: isolate the changing DSH service surface and prefer a host-native `ownerRequestPolicy`; the fallback constrains loopback/SSH Host and Origin, while HTTPS proxy access jointly verifies the real peer, exact Origin/Host, Fetch Metadata, owner proof, and independent CSRF. A throwing or malformed host policy is denied without escaping the route boundary.
|
|
81
|
+
|
|
82
|
+
## 4. Web API
|
|
83
|
+
|
|
84
|
+
Unified interface:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
GET /plugins/dsh-grok-build/oauth/status
|
|
88
|
+
POST /plugins/dsh-grok-build/oauth/login
|
|
89
|
+
POST /plugins/dsh-grok-build/oauth/code
|
|
90
|
+
POST /plugins/dsh-grok-build/oauth/cancel
|
|
91
|
+
POST /plugins/dsh-grok-build/oauth/logout
|
|
92
|
+
POST /plugins/dsh-grok-build/oauth/models
|
|
93
|
+
|
|
94
|
+
GET /plugins/dsh-grok-build/oauth/sources
|
|
95
|
+
POST /plugins/dsh-grok-build/oauth/sources/preview
|
|
96
|
+
POST /plugins/dsh-grok-build/oauth/sources/commit
|
|
97
|
+
POST /plugins/dsh-grok-build/oauth/sources/cancel
|
|
98
|
+
|
|
99
|
+
GET /plugins/dsh-grok-build/capabilities
|
|
100
|
+
PATCH /plugins/dsh-grok-build/capabilities
|
|
101
|
+
PUT /plugins/dsh-grok-build/capabilities
|
|
102
|
+
GET /plugins/dsh-grok-build/codex/usage
|
|
103
|
+
GET /plugins/dsh-grok-build/imagine/credential-status
|
|
104
|
+
GET /plugins/dsh-grok-build/imagine/images/<id>
|
|
105
|
+
GET /plugins/dsh-grok-build/imagine/media/<id>
|
|
106
|
+
GET /plugins/dsh-grok-build/gateway
|
|
107
|
+
PATCH /plugins/dsh-grok-build/gateway
|
|
108
|
+
POST /plugins/dsh-grok-build/gateway/rotate
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Write endpoints take `provider: grok|codex|kimi|claude` in the body. Responses contain only status, authorization URL, device user code, model ids and a non-sensitive expiry; they never contain access/refresh tokens. JSON request bodies are capped at 64 KiB before parsing.
|
|
112
|
+
|
|
113
|
+
Every Settings route shares `OwnerRequestPolicy`. `X-Forwarded-*` is forwarding metadata, never owner proof; a fallback policy missing any independent signal rejects remote requests. Status responses carry the server-derived `accessMode`, so the client does not infer SSH or proxy access from the hostname.
|
|
114
|
+
|
|
115
|
+
`/oauth/sources` is read-only discovery. Preview/commit is the explicit one-way Pull (tickets one-use, five minutes, max 32). Capability writes are secret-free compare-and-swap snapshots in the `coding-subscription-oauth` settings section and apply live. Eight flags default off; `searchResults` is 1–20 (default 5), `imageCount` is 1–4 (default 1), and `videoArtifactTtlMs` is 1 hour–7 days (default 7 days; UI 1–168 hours); decreases rewrite/clean existing expiries immediately, while increases affect only new artifacts. Imagine download routes are same-origin loopback GETs; they never return a signed upstream URL.
|
|
116
|
+
|
|
117
|
+
The legacy `/plugins/dsh-grok-build/auth/*` endpoints remain registered and reuse the same Grok controller.
|
|
118
|
+
|
|
119
|
+
## 5. Antigravity
|
|
120
|
+
|
|
121
|
+
This project does not replicate the private Google Antigravity protocol. The profile separately installs `dsh-agy@0.1.2`, which provides the `agy` route. Because the `/agy` dashboard in that version includes an export API with no authentication of its own, trusted-host deployments should disable `dsh-agy-web` in the profile's final `cordis.patch.yml` (see `INSTALL.md`) and keep only the host adapter and CLI. The profile uses a pnpm patch with a lockfile hash: with no Google session, `listModels()` returns empty; after authentication the provider group name is `Google Antigravity (OAuth)`. Decision to **keep** `patches/dsh-agy@0.1.2.patch` (upstream not absorbed as of 0.2.4): [`docs/research/adr-dsh-agy-patch.md`](research/adr-dsh-agy-patch.md).
|
|
122
|
+
|
|
123
|
+
## 6. Compatibility
|
|
124
|
+
|
|
125
|
+
The canonical package and repository name is **`dsh-coding-subscription-oauth`**. The previous GitHub URL still resolves to the same `main`, so old `dsh plugin add github:lninghaha/dsh-grok-build` commands continue to install the renamed package. The first public npm/GitHub Release was **`0.4.1`**. The current release is **`0.7.0`** (`dsh plugin --profile web add dsh-coding-subscription-oauth@0.7.0`), verified against DSH **`0.1.1-rc.2`**. `0.1.5-rc.1` is recorded only as an unverified BOM candidate; client inject no longer requires `@deepseek-ai/dsh-client-runtime` (absent on that candidate). GitHub and local tarball installs remain valid.
|
|
126
|
+
|
|
127
|
+
Stable on-disk / in-process identifiers (do not rename without a migration):
|
|
128
|
+
|
|
129
|
+
- Cordis id: `llm-grok-build-oauth`
|
|
130
|
+
- Settings HTTP API: `/plugins/dsh-grok-build/oauth/*`, `/plugins/dsh-grok-build/capabilities`, `/plugins/dsh-grok-build/codex/usage`, `/plugins/dsh-grok-build/imagine/*`, and legacy `/plugins/dsh-grok-build/auth/*`
|
|
131
|
+
- Credential files: `$DSH_HOME/.grok-build-auth.json` and the other `*-oauth-auth.json` files
|
|
132
|
+
- Imagine credential: DSH credentials reference `XAI_API_KEY` (never Grok OAuth, never process-env fallback)
|
|
133
|
+
- CLI: `dsh-coding-oauth` (primary) and `dsh-grok-build` (alias)
|
|
134
|
+
- LLM routes: `grok-build`, `codex-oauth`, `kimi-code-oauth`, `claude-code-oauth`; optional `codex-oauth-fast` (v0.4.0, advertised only when a fresh live catalog lists `priority`)
|
|
135
|
+
|
|
136
|
+
New routes use the `*-oauth` alias and do not occupy `openai`, `xai` or `kimi-coding`. In v0.3.0 the `grok-build` fallback/default advances to `grok-4.6`; saved user defaults still win.
|
|
137
|
+
|
|
138
|
+
Hub and this standalone participant pin the same `dsh-coding-oauth-core@0.1.2` and `undici@7.29.0`. The core owns root-scoped owner election, reference-counted proxy policy, atomic registration helpers, provider/route/credential identifiers, the capability namespace, Gateway state filename, and all legacy/current management paths. Hub has priority while installed; this participant remains standby and resumes without renaming routes or resetting credentials after Hub unloads. Grok Imagine keeps its explicit pinned dispatcher and does not use the shared proxy lease.
|
|
139
|
+
|
|
140
|
+
### Shared runtime extract (first slice)
|
|
141
|
+
|
|
142
|
+
Hub and this participant share four pure helpers via published `dsh-coding-oauth-core@0.1.2`: `http-json`, `grok-errors`, `kimi-errors`, and `gateway-protocol`. Thin facades remain at the historical `src/*.ts` paths and re-export those subpaths. `pnpm run assert:oauth-core` pins the registry version and verifies the subpath exports resolve.
|
|
@@ -1,138 +1,142 @@
|
|
|
1
|
-
# 02 · 架构设计
|
|
2
|
-
|
|
3
|
-
> 中文版 · [**English**](02-architecture.md)
|
|
4
|
-
|
|
5
|
-
本文描述 `dsh-coding-subscription-oauth` 的内部架构,是 `README.md` 技术说明的来源,面向贡献者与维护者。
|
|
6
|
-
|
|
7
|
-
## 1. 路由与原生 provider
|
|
8
|
-
|
|
9
|
-
```text
|
|
10
|
-
Harness route pi-ai provider 请求认证
|
|
11
|
-
────────────────────────────────────────────────────────────
|
|
12
|
-
grok-build grok-build xAI access token + Grok CLI headers
|
|
13
|
-
codex-oauth openai-codex OAuth token → apiKey override
|
|
14
|
-
kimi-code-oauth kimi-coding OAuth token → Authorization: Bearer
|
|
15
|
-
claude-code-oauth anthropic sk-ant-oat token → Claude Code headers
|
|
16
|
-
agy dsh-agy external dsh-agy 自有账号池
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
外部 route 和 pi-ai 原生 id 由 `AliasLlmAdapter` 分隔。`PiAiAdapter` 始终看到原生 provider id,因此 Codex 工具调用、Claude compatibility 判断和 Kimi Anthropic transport 不因 route 改名而失效。
|
|
20
|
-
|
|
21
|
-
模型发现里的“已认证”定义为存在可读、结构有效且可刷新的 OAuth credential;不会在每次打开选择器时向上游做在线探测。已被上游撤销但本地仍有效的 credential 会在 token refresh 或推理时被识别,避免目录加载产生额外网络请求。
|
|
22
|
-
|
|
23
|
-
## 2. 主机数据流
|
|
24
|
-
|
|
25
|
-
```text
|
|
26
|
-
Settings / CLI
|
|
27
|
-
│
|
|
28
|
-
├─ GrokBuildWebAuth ── Grok custom PKCE/device
|
|
29
|
-
│ └─ .grok-build-auth.json
|
|
30
|
-
│
|
|
31
|
-
├─ SubscriptionWebAuth ── pi-ai OAuth login/refresh
|
|
32
|
-
│ ├─ Codex ── .codex-oauth-auth.json
|
|
33
|
-
│ ├─ Kimi ── .kimi-code-oauth-auth.json
|
|
34
|
-
│ └─ Claude ── .claude-code-oauth-auth.json
|
|
35
|
-
│
|
|
36
|
-
└─ OAuthImportSession ── 白名单 CLI 只读发现
|
|
37
|
-
└─ 显式单向拉取(预览票据 → 目标 store)
|
|
38
|
-
从不写入官方 CLI 文件
|
|
39
|
-
|
|
40
|
-
OAuthProviderSession.resolveAccessToken()
|
|
41
|
-
└─ Models.getAuth(native id) # refresh-under-lock
|
|
42
|
-
└─ OAuthCredentialFileStore # 0600 + atomic write + cross-process lock
|
|
43
|
-
|
|
44
|
-
CapabilitySettingsController(默认关闭,applies: live)
|
|
45
|
-
└─ CapabilityRuntimeState
|
|
46
|
-
├─ Codex 搜索 / 用量 / gpt-image-2 图像
|
|
47
|
-
├─ codex-oauth-fast(仅在最新 priority catalog 之后)
|
|
48
|
-
└─ Grok Imagine(api.x.ai + DSH 凭据 XAI_API_KEY)
|
|
49
|
-
|
|
50
|
-
ctx.llm route
|
|
51
|
-
└─ AliasLlmAdapter
|
|
52
|
-
└─ PiAiAdapter
|
|
53
|
-
└─ native pi-ai Provider.streamSimple()
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## 3. 模块职责
|
|
57
|
-
|
|
58
|
-
- `store.ts`:一个文件只拥有一个 provider credential;保留旧 Grok store API;`invalidate()` 在上游 AUTH 拒绝后把 `expires` 回写到过去。
|
|
59
|
-
- `oauth-providers.ts`:Codex/Kimi/Claude 定义、route metadata、请求 token bridge。
|
|
60
|
-
- `oauth-session.ts`:登录、刷新、静态模型目录和模型选择缓存。
|
|
61
|
-
- `oauth-sources.ts`:白名单官方 Grok/Codex/Kimi/Claude CLI 发现;加固的 lstat/`O_NOFOLLOW`/属主/权限/普通文件/大小读取;一次性预览票据(五分钟、最多 32 张);从不写入官方 CLI 文件。
|
|
62
|
-
- `oauth-import-routes.ts`:同源拉取 HTTP API(发现 → 预览 → 提交/取消),写入发生在目标 store 锁内。
|
|
63
|
-
- `alias-adapter.ts`:转换 Harness route、不修改 pi-ai model.provider,并在 `listModels()` 前执行 credential gate;未认证或凭据读取失败返回空目录,provider group 名使用 `(OAuth)`。AUTH finish 时作废本地令牌,让 harness 重试先刷新。finish 管道还会重映射 Kimi 误标 AUTH 的上下文溢出,以及 xAI capacity 文案 → `RATE_LIMIT`。
|
|
64
|
-
- `grok-errors.ts
|
|
65
|
-
- `adapter.ts`:组合 Grok 与三个 subscription profile;向 pi-ai 要求至少 60 秒剩余有效期,并注册包含 AUTH 与瞬时故障码的 retryPolicy(默认 5 次,5 s → 80 s 指数叠加)。可选包装 `codex-oauth-fast`,显示为 **已请求 Fast**。
|
|
66
|
-
- `auth-routes.ts`:旧 Grok API + 新统一 `/plugins/dsh-grok-build/oauth/*`;JSON 写请求使用 64 KiB 有界读取器,无效/超限 body 分别返回 400/413。
|
|
67
|
-
- `capability-settings.ts`:默认关闭、立即生效的开关与限制(搜索 1–20、图像 1–4、产物 TTL 1 小时–7 天)。
|
|
68
|
-
- `capability-routes.ts`:无密钥的能力快照,以及可选的 Codex 用量和 Imagine 凭据状态路由。
|
|
69
|
-
- `capability-runtime.ts`:按 live 开关绑定/解绑搜索、工具,以及仅在最新 priority catalog 后发布 Fast 路由。
|
|
70
|
-
- `capability-tools.ts`:可选 Codex / Grok Imagine 工具定义;执行时重新读取开关。默认关闭的任意模型图像策略只放宽调用路由门禁,Codex 登录、会话、附件归属和编辑授权保持不变。
|
|
71
|
-
- `codex-http.ts`:需打开的私有 `chatgpt.com/backend-api` 客户端(仅 HTTPS、仅第一方主机)。
|
|
72
|
-
- `codex-search.ts` / `codex-usage.ts` / `codex-images.ts`:可选搜索、配额,以及固定 `gpt-image-2` 生成/编辑(编辑要求当前会话顶层附件所有权)。
|
|
73
|
-
- `codex-model-capabilities.ts`:live Codex service-tier 缓存;Fast 资格失败关闭;注入 `service_tier: priority` 与路由提示。
|
|
74
|
-
- `grok-imagine.ts`:官方 `api.x.ai` Imagine 客户端(`grok-imagine-image-2.0` / `grok-imagine-video-1.5`);`XAI_API_KEY` 只通过 DSH 凭据;MIME/大小/超时/重定向/DNS 下载控制;冻结主机 `imgen.x.ai`、`videogen.x.ai`、`vidgen.x.ai`。
|
|
75
|
-
- `imagine-routes.ts`:生成图像与视频产物的同源 loopback GET 路由。
|
|
76
|
-
- `media-store.ts`:属主私有产物库(单件与唯一对象总量均硬限 256 MiB,最长七天)。
|
|
77
|
-
- `client/`:四个原生账号卡片、CLI 拉取、能力开关、网关控制,以及外部 Antigravity 状态卡片。
|
|
78
|
-
- `proxy.ts`:process-wide undici dispatcher,但只代理审核过的域名白名单。
|
|
79
|
-
- `gateway*.ts`:可选的隔离 loopback OpenAI/Anthropic 兼容 HTTP 服务(默认关;独立于 DSH web 端口)。
|
|
80
|
-
- `dsh-host-adapter.ts` / `web-origin.ts`:隔离可变 DSH 服务,并优先使用宿主 `ownerRequestPolicy`;fallback 对 loopback/SSH 做 Host/Origin 约束,对 HTTPS 反代同时核验真实 peer、精确 Origin/Host、Fetch Metadata、owner proof 与独立 CSRF。宿主策略抛错或返回畸形结果时安全拒绝,不让异常越过路由边界。
|
|
81
|
-
|
|
82
|
-
## 4. Web API
|
|
83
|
-
|
|
84
|
-
统一接口:
|
|
85
|
-
|
|
86
|
-
```text
|
|
87
|
-
GET /plugins/dsh-grok-build/oauth/status
|
|
88
|
-
POST /plugins/dsh-grok-build/oauth/login
|
|
89
|
-
POST /plugins/dsh-grok-build/oauth/code
|
|
90
|
-
POST /plugins/dsh-grok-build/oauth/cancel
|
|
91
|
-
POST /plugins/dsh-grok-build/oauth/logout
|
|
92
|
-
POST /plugins/dsh-grok-build/oauth/models
|
|
93
|
-
|
|
94
|
-
GET /plugins/dsh-grok-build/oauth/sources
|
|
95
|
-
POST /plugins/dsh-grok-build/oauth/sources/preview
|
|
96
|
-
POST /plugins/dsh-grok-build/oauth/sources/commit
|
|
97
|
-
POST /plugins/dsh-grok-build/oauth/sources/cancel
|
|
98
|
-
|
|
99
|
-
GET /plugins/dsh-grok-build/capabilities
|
|
100
|
-
PATCH /plugins/dsh-grok-build/capabilities
|
|
101
|
-
PUT /plugins/dsh-grok-build/capabilities
|
|
102
|
-
GET /plugins/dsh-grok-build/codex/usage
|
|
103
|
-
GET /plugins/dsh-grok-build/imagine/credential-status
|
|
104
|
-
GET /plugins/dsh-grok-build/imagine/images/<id>
|
|
105
|
-
GET /plugins/dsh-grok-build/imagine/media/<id>
|
|
106
|
-
GET /plugins/dsh-grok-build/gateway
|
|
107
|
-
PATCH /plugins/dsh-grok-build/gateway
|
|
108
|
-
POST /plugins/dsh-grok-build/gateway/rotate
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
写接口请求体带 `provider: grok|codex|kimi|claude`。响应只包含状态、授权 URL、device user code、模型 id 和非敏感 expiry;绝不包含 access/refresh token。JSON 请求体在解析前限制为 64 KiB。
|
|
112
|
-
|
|
113
|
-
所有 Settings 路由共用 `OwnerRequestPolicy`。`X-Forwarded-*` 只属于转发元数据,不能成为属主证明;fallback 配置缺少任一独立信号时拒绝远程请求。状态响应携带经服务端判定的 `accessMode`,客户端不根据 hostname 猜测 SSH 或反代环境。
|
|
114
|
-
|
|
115
|
-
`/oauth/sources` 是只读发现。预览/提交是显式单向拉取(票据一次性、五分钟、最多 32 张)。能力写入位于 `coding-subscription-oauth` 设置区,是无密钥的 compare-and-swap 快照并立即生效。八项开关默认关闭;`searchResults` 为 1–20(默认 5),`imageCount` 为 1–4(默认 1),`videoArtifactTtlMs` 为 1 小时–7 天(默认 7 天;界面显示 1–168 小时);降低时立即改写/清理已有 expiry,提高只影响新产物。Imagine 下载路由是同源 loopback GET,从不返回上游签名 URL。
|
|
116
|
-
|
|
117
|
-
旧 `/plugins/dsh-grok-build/auth/*` 继续注册并复用同一个 Grok 控制器。
|
|
118
|
-
|
|
119
|
-
## 5. Antigravity
|
|
120
|
-
|
|
121
|
-
本项目不复制 Google Antigravity 私有协议。profile 单独安装 `dsh-agy@0.1.2`,提供 `agy` route。由于该版本的 `/agy` dashboard 含无自身认证的 export API,trusted-host 部署应在 profile 最终 `cordis.patch.yml` 中禁用 `dsh-agy-web`(见 `INSTALL.md`),只保留 host adapter 和 CLI。profile 使用带 lockfile hash 的 pnpm patch:无 Google session 时 `listModels()` 返回空,认证后 provider group 名为 `Google Antigravity (OAuth)
|
|
122
|
-
|
|
123
|
-
## 6. 兼容性
|
|
124
|
-
|
|
125
|
-
正式包名与仓库名是 **`dsh-coding-subscription-oauth`**。旧 GitHub 地址仍指向同一条 `main`,因此旧的 `dsh plugin add github:lninghaha/dsh-grok-build` 仍会安装更名后的包。第一次公开 npm / GitHub Release 是 **`0.4.1`**。当前版本是 **`0.
|
|
126
|
-
|
|
127
|
-
以下标识保持稳定(无迁移方案前不要改名):
|
|
128
|
-
|
|
129
|
-
- Cordis id:`llm-grok-build-oauth`
|
|
130
|
-
- 设置页 HTTP API:`/plugins/dsh-grok-build/oauth/*`、`/plugins/dsh-grok-build/capabilities`、`/plugins/dsh-grok-build/codex/usage`、`/plugins/dsh-grok-build/imagine/*`,以及旧的 `/plugins/dsh-grok-build/auth/*`
|
|
131
|
-
- 凭据文件:`$DSH_HOME/.grok-build-auth.json` 及其他 `*-oauth-auth.json`
|
|
132
|
-
- Imagine 凭据:DSH 凭据引用 `XAI_API_KEY`(不用 Grok OAuth,不回退进程环境变量)
|
|
133
|
-
- CLI:`dsh-coding-oauth`(主命令)与 `dsh-grok-build`(别名)
|
|
134
|
-
- LLM 路由:`grok-build`、`codex-oauth`、`kimi-code-oauth`、`claude-code-oauth`;可选 `codex-oauth-fast`(v0.4.0,仅在最新 live catalog 列出 `priority` 后发布)
|
|
135
|
-
|
|
136
|
-
新 route 使用 `*-oauth` alias,不占用 `openai`、`xai`、`kimi-coding`。v0.3.0 将 `grok-build` fallback/default 更新为 `grok-4.6`,已有用户默认设置仍优先。
|
|
137
|
-
|
|
138
|
-
Hub 与本独立 participant 精确依赖同一个 `dsh-coding-oauth-core@0.1.
|
|
1
|
+
# 02 · 架构设计
|
|
2
|
+
|
|
3
|
+
> 中文版 · [**English**](02-architecture.md)
|
|
4
|
+
|
|
5
|
+
本文描述 `dsh-coding-subscription-oauth` 的内部架构,是 `README.md` 技术说明的来源,面向贡献者与维护者。
|
|
6
|
+
|
|
7
|
+
## 1. 路由与原生 provider
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Harness route pi-ai provider 请求认证
|
|
11
|
+
────────────────────────────────────────────────────────────
|
|
12
|
+
grok-build grok-build xAI access token + Grok CLI headers
|
|
13
|
+
codex-oauth openai-codex OAuth token → apiKey override
|
|
14
|
+
kimi-code-oauth kimi-coding OAuth token → Authorization: Bearer
|
|
15
|
+
claude-code-oauth anthropic sk-ant-oat token → Claude Code headers
|
|
16
|
+
agy dsh-agy external dsh-agy 自有账号池
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
外部 route 和 pi-ai 原生 id 由 `AliasLlmAdapter` 分隔。`PiAiAdapter` 始终看到原生 provider id,因此 Codex 工具调用、Claude compatibility 判断和 Kimi Anthropic transport 不因 route 改名而失效。
|
|
20
|
+
|
|
21
|
+
模型发现里的“已认证”定义为存在可读、结构有效且可刷新的 OAuth credential;不会在每次打开选择器时向上游做在线探测。已被上游撤销但本地仍有效的 credential 会在 token refresh 或推理时被识别,避免目录加载产生额外网络请求。
|
|
22
|
+
|
|
23
|
+
## 2. 主机数据流
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
Settings / CLI
|
|
27
|
+
│
|
|
28
|
+
├─ GrokBuildWebAuth ── Grok custom PKCE/device
|
|
29
|
+
│ └─ .grok-build-auth.json
|
|
30
|
+
│
|
|
31
|
+
├─ SubscriptionWebAuth ── pi-ai OAuth login/refresh
|
|
32
|
+
│ ├─ Codex ── .codex-oauth-auth.json
|
|
33
|
+
│ ├─ Kimi ── .kimi-code-oauth-auth.json
|
|
34
|
+
│ └─ Claude ── .claude-code-oauth-auth.json
|
|
35
|
+
│
|
|
36
|
+
└─ OAuthImportSession ── 白名单 CLI 只读发现
|
|
37
|
+
└─ 显式单向拉取(预览票据 → 目标 store)
|
|
38
|
+
从不写入官方 CLI 文件
|
|
39
|
+
|
|
40
|
+
OAuthProviderSession.resolveAccessToken()
|
|
41
|
+
└─ Models.getAuth(native id) # refresh-under-lock
|
|
42
|
+
└─ OAuthCredentialFileStore # 0600 + atomic write + cross-process lock
|
|
43
|
+
|
|
44
|
+
CapabilitySettingsController(默认关闭,applies: live)
|
|
45
|
+
└─ CapabilityRuntimeState
|
|
46
|
+
├─ Codex 搜索 / 用量 / gpt-image-2 图像
|
|
47
|
+
├─ codex-oauth-fast(仅在最新 priority catalog 之后)
|
|
48
|
+
└─ Grok Imagine(api.x.ai + DSH 凭据 XAI_API_KEY)
|
|
49
|
+
|
|
50
|
+
ctx.llm route
|
|
51
|
+
└─ AliasLlmAdapter
|
|
52
|
+
└─ PiAiAdapter
|
|
53
|
+
└─ native pi-ai Provider.streamSimple()
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 3. 模块职责
|
|
57
|
+
|
|
58
|
+
- `store.ts`:一个文件只拥有一个 provider credential;保留旧 Grok store API;`invalidate()` 在上游 AUTH 拒绝后把 `expires` 回写到过去。
|
|
59
|
+
- `oauth-providers.ts`:Codex/Kimi/Claude 定义、route metadata、请求 token bridge。
|
|
60
|
+
- `oauth-session.ts`:登录、刷新、静态模型目录和模型选择缓存。
|
|
61
|
+
- `oauth-sources.ts`:白名单官方 Grok/Codex/Kimi/Claude CLI 发现;加固的 lstat/`O_NOFOLLOW`/属主/权限/普通文件/大小读取;一次性预览票据(五分钟、最多 32 张);从不写入官方 CLI 文件。
|
|
62
|
+
- `oauth-import-routes.ts`:同源拉取 HTTP API(发现 → 预览 → 提交/取消),写入发生在目标 store 锁内。
|
|
63
|
+
- `alias-adapter.ts`:转换 Harness route、不修改 pi-ai model.provider,并在 `listModels()` 前执行 credential gate;未认证或凭据读取失败返回空目录,provider group 名使用 `(OAuth)`。AUTH finish 时作废本地令牌,让 harness 重试先刷新。finish 管道还会重映射 Kimi 误标 AUTH 的上下文溢出,以及 xAI capacity 文案 → `RATE_LIMIT`。
|
|
64
|
+
- `grok-errors.ts`(再导出 `dsh-coding-oauth-core/grok-errors`):识别 xAI「at capacity / high demand / priority processing / overloaded」并改为 `RATE_LIMIT`,避免 `PI_AI_ERROR` 跳过退避。
|
|
65
|
+
- `adapter.ts`:组合 Grok 与三个 subscription profile;向 pi-ai 要求至少 60 秒剩余有效期,并注册包含 AUTH 与瞬时故障码的 retryPolicy(默认 5 次,5 s → 80 s 指数叠加)。可选包装 `codex-oauth-fast`,显示为 **已请求 Fast**。
|
|
66
|
+
- `auth-routes.ts`:旧 Grok API + 新统一 `/plugins/dsh-grok-build/oauth/*`;JSON 写请求使用 64 KiB 有界读取器,无效/超限 body 分别返回 400/413。
|
|
67
|
+
- `capability-settings.ts`:默认关闭、立即生效的开关与限制(搜索 1–20、图像 1–4、产物 TTL 1 小时–7 天)。
|
|
68
|
+
- `capability-routes.ts`:无密钥的能力快照,以及可选的 Codex 用量和 Imagine 凭据状态路由。
|
|
69
|
+
- `capability-runtime.ts`:按 live 开关绑定/解绑搜索、工具,以及仅在最新 priority catalog 后发布 Fast 路由。
|
|
70
|
+
- `capability-tools.ts`:可选 Codex / Grok Imagine 工具定义;执行时重新读取开关。默认关闭的任意模型图像策略只放宽调用路由门禁,Codex 登录、会话、附件归属和编辑授权保持不变。
|
|
71
|
+
- `codex-http.ts`:需打开的私有 `chatgpt.com/backend-api` 客户端(仅 HTTPS、仅第一方主机)。
|
|
72
|
+
- `codex-search.ts` / `codex-usage.ts` / `codex-images.ts`:可选搜索、配额,以及固定 `gpt-image-2` 生成/编辑(编辑要求当前会话顶层附件所有权)。
|
|
73
|
+
- `codex-model-capabilities.ts`:live Codex service-tier 缓存;Fast 资格失败关闭;注入 `service_tier: priority` 与路由提示。
|
|
74
|
+
- `grok-imagine.ts`:官方 `api.x.ai` Imagine 客户端(`grok-imagine-image-2.0` / `grok-imagine-video-1.5`);`XAI_API_KEY` 只通过 DSH 凭据;MIME/大小/超时/重定向/DNS 下载控制;冻结主机 `imgen.x.ai`、`videogen.x.ai`、`vidgen.x.ai`。
|
|
75
|
+
- `imagine-routes.ts`:生成图像与视频产物的同源 loopback GET 路由。
|
|
76
|
+
- `media-store.ts`:属主私有产物库(单件与唯一对象总量均硬限 256 MiB,最长七天)。
|
|
77
|
+
- `client/`:四个原生账号卡片、CLI 拉取、能力开关、网关控制,以及外部 Antigravity 状态卡片。
|
|
78
|
+
- `proxy.ts`:process-wide undici dispatcher,但只代理审核过的域名白名单。
|
|
79
|
+
- `gateway*.ts`:可选的隔离 loopback OpenAI/Anthropic 兼容 HTTP 服务(默认关;独立于 DSH web 端口)。
|
|
80
|
+
- `dsh-host-adapter.ts` / `web-origin.ts`:隔离可变 DSH 服务,并优先使用宿主 `ownerRequestPolicy`;fallback 对 loopback/SSH 做 Host/Origin 约束,对 HTTPS 反代同时核验真实 peer、精确 Origin/Host、Fetch Metadata、owner proof 与独立 CSRF。宿主策略抛错或返回畸形结果时安全拒绝,不让异常越过路由边界。
|
|
81
|
+
|
|
82
|
+
## 4. Web API
|
|
83
|
+
|
|
84
|
+
统一接口:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
GET /plugins/dsh-grok-build/oauth/status
|
|
88
|
+
POST /plugins/dsh-grok-build/oauth/login
|
|
89
|
+
POST /plugins/dsh-grok-build/oauth/code
|
|
90
|
+
POST /plugins/dsh-grok-build/oauth/cancel
|
|
91
|
+
POST /plugins/dsh-grok-build/oauth/logout
|
|
92
|
+
POST /plugins/dsh-grok-build/oauth/models
|
|
93
|
+
|
|
94
|
+
GET /plugins/dsh-grok-build/oauth/sources
|
|
95
|
+
POST /plugins/dsh-grok-build/oauth/sources/preview
|
|
96
|
+
POST /plugins/dsh-grok-build/oauth/sources/commit
|
|
97
|
+
POST /plugins/dsh-grok-build/oauth/sources/cancel
|
|
98
|
+
|
|
99
|
+
GET /plugins/dsh-grok-build/capabilities
|
|
100
|
+
PATCH /plugins/dsh-grok-build/capabilities
|
|
101
|
+
PUT /plugins/dsh-grok-build/capabilities
|
|
102
|
+
GET /plugins/dsh-grok-build/codex/usage
|
|
103
|
+
GET /plugins/dsh-grok-build/imagine/credential-status
|
|
104
|
+
GET /plugins/dsh-grok-build/imagine/images/<id>
|
|
105
|
+
GET /plugins/dsh-grok-build/imagine/media/<id>
|
|
106
|
+
GET /plugins/dsh-grok-build/gateway
|
|
107
|
+
PATCH /plugins/dsh-grok-build/gateway
|
|
108
|
+
POST /plugins/dsh-grok-build/gateway/rotate
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
写接口请求体带 `provider: grok|codex|kimi|claude`。响应只包含状态、授权 URL、device user code、模型 id 和非敏感 expiry;绝不包含 access/refresh token。JSON 请求体在解析前限制为 64 KiB。
|
|
112
|
+
|
|
113
|
+
所有 Settings 路由共用 `OwnerRequestPolicy`。`X-Forwarded-*` 只属于转发元数据,不能成为属主证明;fallback 配置缺少任一独立信号时拒绝远程请求。状态响应携带经服务端判定的 `accessMode`,客户端不根据 hostname 猜测 SSH 或反代环境。
|
|
114
|
+
|
|
115
|
+
`/oauth/sources` 是只读发现。预览/提交是显式单向拉取(票据一次性、五分钟、最多 32 张)。能力写入位于 `coding-subscription-oauth` 设置区,是无密钥的 compare-and-swap 快照并立即生效。八项开关默认关闭;`searchResults` 为 1–20(默认 5),`imageCount` 为 1–4(默认 1),`videoArtifactTtlMs` 为 1 小时–7 天(默认 7 天;界面显示 1–168 小时);降低时立即改写/清理已有 expiry,提高只影响新产物。Imagine 下载路由是同源 loopback GET,从不返回上游签名 URL。
|
|
116
|
+
|
|
117
|
+
旧 `/plugins/dsh-grok-build/auth/*` 继续注册并复用同一个 Grok 控制器。
|
|
118
|
+
|
|
119
|
+
## 5. Antigravity
|
|
120
|
+
|
|
121
|
+
本项目不复制 Google Antigravity 私有协议。profile 单独安装 `dsh-agy@0.1.2`,提供 `agy` route。由于该版本的 `/agy` dashboard 含无自身认证的 export API,trusted-host 部署应在 profile 最终 `cordis.patch.yml` 中禁用 `dsh-agy-web`(见 `INSTALL.md`),只保留 host adapter 和 CLI。profile 使用带 lockfile hash 的 pnpm patch:无 Google session 时 `listModels()` 返回空,认证后 provider group 名为 `Google Antigravity (OAuth)`。**保留** `patches/dsh-agy@0.1.2.patch` 的结论见 [`docs/research/adr-dsh-agy-patch.md`](research/adr-dsh-agy-patch.md)(至 0.2.4 上游仍未等价吸收)。
|
|
122
|
+
|
|
123
|
+
## 6. 兼容性
|
|
124
|
+
|
|
125
|
+
正式包名与仓库名是 **`dsh-coding-subscription-oauth`**。旧 GitHub 地址仍指向同一条 `main`,因此旧的 `dsh plugin add github:lninghaha/dsh-grok-build` 仍会安装更名后的包。第一次公开 npm / GitHub Release 是 **`0.4.1`**。当前版本是 **`0.7.0`**(`dsh plugin --profile web add dsh-coding-subscription-oauth@0.7.0`),精确验证 DSH **`0.1.1-rc.2`**。`0.1.5-rc.1` 仅作为未验证 BOM 候选记录;客户端 inject 不再要求 `@deepseek-ai/dsh-client-runtime`(该候选宿主上不存在此包)。GitHub 与本地 tarball 安装仍然有效。
|
|
126
|
+
|
|
127
|
+
以下标识保持稳定(无迁移方案前不要改名):
|
|
128
|
+
|
|
129
|
+
- Cordis id:`llm-grok-build-oauth`
|
|
130
|
+
- 设置页 HTTP API:`/plugins/dsh-grok-build/oauth/*`、`/plugins/dsh-grok-build/capabilities`、`/plugins/dsh-grok-build/codex/usage`、`/plugins/dsh-grok-build/imagine/*`,以及旧的 `/plugins/dsh-grok-build/auth/*`
|
|
131
|
+
- 凭据文件:`$DSH_HOME/.grok-build-auth.json` 及其他 `*-oauth-auth.json`
|
|
132
|
+
- Imagine 凭据:DSH 凭据引用 `XAI_API_KEY`(不用 Grok OAuth,不回退进程环境变量)
|
|
133
|
+
- CLI:`dsh-coding-oauth`(主命令)与 `dsh-grok-build`(别名)
|
|
134
|
+
- LLM 路由:`grok-build`、`codex-oauth`、`kimi-code-oauth`、`claude-code-oauth`;可选 `codex-oauth-fast`(v0.4.0,仅在最新 live catalog 列出 `priority` 后发布)
|
|
135
|
+
|
|
136
|
+
新 route 使用 `*-oauth` alias,不占用 `openai`、`xai`、`kimi-coding`。v0.3.0 将 `grok-build` fallback/default 更新为 `grok-4.6`,已有用户默认设置仍优先。
|
|
137
|
+
|
|
138
|
+
Hub 与本独立 participant 精确依赖同一个 `dsh-coding-oauth-core@0.1.2` 与 `undici@7.29.0`。核心统一管理 root-scoped owner 选举、引用计数代理策略、原子注册、provider/route/credential 标识、能力设置命名空间、Gateway 状态文件名,以及全部新旧管理路径。Hub 安装时优先成为 owner;Hub 卸载后本插件从 standby 自动接管,不改路由名,也不重置凭据。Grok Imagine 保留显式 pinned dispatcher,不使用共享 proxy lease。
|
|
139
|
+
|
|
140
|
+
### 共享运行时抽取(第一刀)
|
|
141
|
+
|
|
142
|
+
Hub 与本 participant 通过已发布的 `dsh-coding-oauth-core@0.1.2` 共享四个纯辅助模块:`http-json`、`grok-errors`、`kimi-errors`、`gateway-protocol`。历史路径 `src/*.ts` 仍为薄 facade,从上述 subpath 再导出。`pnpm run assert:oauth-core` 会钉死 registry 版本并校验 subpath 可解析。
|