dsh-openai-subscription 0.1.0 → 0.1.2
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/README.md +44 -15
- package/README.zh.md +45 -16
- package/dist/client.d.ts +40 -29
- package/dist/client.js +565 -167
- package/dist/host.d.ts +23 -13
- package/dist/host.js +331 -72
- package/dist/models.d.ts +51 -0
- package/dist/models.js +370 -0
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
-
Use a ChatGPT subscription in [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) through OpenAI device authorization. No API key
|
|
5
|
+
Use a ChatGPT subscription with Codex access in [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) through OpenAI device authorization. No API key or manual declaration of newly available account models is required.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
9
|
+
- Connect DSH to a ChatGPT plan that includes Codex access
|
|
10
|
+
- Dynamically read account-visible models from the ChatGPT Codex backend
|
|
11
|
+
- Safely merge live models with the `openai-codex` catalog from DSH's installed adapter version
|
|
12
|
+
- Preserve user-added models, field edits, and deletion choices across later syncs
|
|
13
|
+
- Provide focused actions for connecting, model sync, authorization recovery, and local disconnect
|
|
14
|
+
- Follow the current DSH locale in Chinese and English
|
|
12
15
|
- Keep access and refresh tokens in the local DSH credential store
|
|
13
16
|
|
|
14
17
|
## Requirements
|
|
@@ -33,37 +36,63 @@ Install the plugin into the Web profile:
|
|
|
33
36
|
dsh plugin --profile web add dsh-openai-subscription
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
Restart `dsh web`, then refresh the page. DSH registers the plugin automatically; no profile edits are required.
|
|
39
|
+
Restart `dsh web`, then refresh the existing page. DSH registers the plugin automatically; no profile edits are required.
|
|
37
40
|
|
|
38
41
|
## Usage
|
|
39
42
|
|
|
40
|
-
1. Open **Settings → ChatGPT
|
|
41
|
-
2. Select
|
|
42
|
-
3. Open the
|
|
43
|
-
4. Return to DSH after authorization completes
|
|
43
|
+
1. Open **Settings → ChatGPT Subscription**.
|
|
44
|
+
2. Select **Connect ChatGPT**.
|
|
45
|
+
3. Open the verification page and enter the displayed one-time device code with your ChatGPT account.
|
|
46
|
+
4. Return to DSH after authorization completes; the plugin fetches and syncs models automatically.
|
|
47
|
+
5. Select an available model from the DSH model picker.
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
`llm-pi-ai` automatically renews refreshable OAuth credentials during model requests. **Refresh authorization** in this settings page is primarily a manual recovery action.
|
|
50
|
+
|
|
51
|
+
### Model synchronization rules
|
|
52
|
+
|
|
53
|
+
DSH treats `openai-codex.models` as a complete replacement list, not an additive list. Adding one model manually therefore hides the previous implicit built-in catalog. This plugin writes a complete, owned snapshot instead:
|
|
54
|
+
|
|
55
|
+
- Models returned by the account endpoint with `visibility=list` are the dynamic source.
|
|
56
|
+
- Built-in model IDs from DSH's currently installed `llm-pi-ai` adapter supplement IDs the account response does not mention at all.
|
|
57
|
+
- An ID explicitly marked hidden by the account endpoint is never resurrected from the built-in catalog.
|
|
58
|
+
- Account metadata wins for the same ID. Built-in-only rows are written as `{ id }` so `llm-pi-ai` continues supplying their complete capabilities.
|
|
59
|
+
- Later syncs use a field-level three-way merge. User-edited fields, local additions, and models removed from a non-empty explicit list remain preserved.
|
|
60
|
+
- Fetch, parse, or settings-write failures never replace current settings with a partial result.
|
|
61
|
+
|
|
62
|
+
If an explicit `models` list already exists in either the user layer or a profile base layer before the first sync, the plugin cannot safely infer whether it is an intentional allow-list or a list of additions. Automatic sign-in sync leaves it untouched. The settings page then shows that syncing is needed; selecting **Sync models** and confirming explicitly opts into merging the existing entries as local configuration.
|
|
63
|
+
|
|
64
|
+
### Disconnecting
|
|
65
|
+
|
|
66
|
+
**Disconnect** removes only locally stored authorization and unchanged model rows managed by this plugin. It preserves locally customized models and provider fields, and it neither signs out of nor deletes the ChatGPT account. A confirmation is shown first.
|
|
67
|
+
|
|
68
|
+
Disconnect before changing accounts or uninstalling the plugin.
|
|
46
69
|
|
|
47
70
|
## Uninstallation
|
|
48
71
|
|
|
49
|
-
|
|
72
|
+
Select **Disconnect** in the settings page first, then run:
|
|
50
73
|
|
|
51
74
|
```sh
|
|
52
75
|
dsh plugin --profile web remove dsh-openai-subscription
|
|
53
76
|
```
|
|
54
77
|
|
|
55
|
-
Restart the Web profile afterward.
|
|
78
|
+
Restart the Web profile and refresh the page afterward.
|
|
56
79
|
|
|
57
80
|
## Troubleshooting
|
|
58
81
|
|
|
59
82
|
- **The settings entry is missing:** confirm the plugin is installed in the `web` profile with `dsh plugin --profile web why dsh-openai-subscription`, then restart DSH and refresh the page.
|
|
60
83
|
- **Authorization cannot start:** update DSH, confirm `node --version` meets the requirement, and check access to the OpenAI authentication service.
|
|
61
|
-
- **The device code is rejected:** enable device-code authorization in
|
|
62
|
-
- **
|
|
84
|
+
- **The device code is rejected:** enable device-code authorization in ChatGPT security settings and start a new connection.
|
|
85
|
+
- **Models need syncing:** select **Sync models**. If an explicit list already exists, review the confirmation and continue; local edits are preserved.
|
|
86
|
+
- **Model sync fails:** existing settings remain unchanged. Check access to `chatgpt.com` and authorization status, then retry; refresh authorization first if needed.
|
|
87
|
+
- **Authorization cannot recover:** disconnect and complete device authorization again.
|
|
88
|
+
|
|
89
|
+
## Compatibility notes
|
|
90
|
+
|
|
91
|
+
Dynamic discovery uses the backend endpoint used by the official ChatGPT Codex client, but that endpoint is not a public, stability-guaranteed OpenAI API and may change. It does not provide complete output-limit, cost, or wire-compatibility metadata. `llm-pi-ai` fills metadata for known models; unknown models use adapter defaults. Catalog presence also does not guarantee that an older adapter supports every new model capability, so update DSH first when calls reveal compatibility problems.
|
|
63
92
|
|
|
64
93
|
## Security and privacy
|
|
65
94
|
|
|
66
|
-
Your password is entered only on OpenAI's website; the plugin never receives it. OAuth credentials
|
|
95
|
+
Your password is entered only on OpenAI's website; the plugin never receives it. OAuth credentials remain in the local DSH credential store. The settings status API returns only semantic facts such as connection, refresh capability, model-sync state, and model count. It does not return tokens, internal account IDs, or exact token-expiry timestamps. Do not share the temporary device code.
|
|
67
96
|
|
|
68
97
|
OpenAI's terms, privacy policy, model availability, and usage limits still apply. This is an independent community plugin and is not affiliated with or endorsed by OpenAI or DeepSeek.
|
|
69
98
|
|
package/README.zh.md
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
-
通过 OpenAI 设备授权,在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
5
|
+
通过 OpenAI 设备授权,在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 中使用包含 Codex 权限的 ChatGPT 订阅。无需 API 密钥,也无需手动声明新出现的账号模型。
|
|
6
6
|
|
|
7
7
|
## 功能
|
|
8
8
|
|
|
9
|
-
- 使用包含 Codex 权限的 ChatGPT
|
|
10
|
-
-
|
|
11
|
-
-
|
|
9
|
+
- 使用包含 Codex 权限的 ChatGPT 套餐连接 DSH
|
|
10
|
+
- 从 ChatGPT Codex 后端动态读取当前账号可见的模型
|
|
11
|
+
- 将动态模型与 DSH 实际安装版本的 `openai-codex` 内置目录安全合并
|
|
12
|
+
- 在后续同步中保留用户新增模型、字段编辑和删除选择
|
|
13
|
+
- 提供连接、模型同步、授权恢复和本机断开操作
|
|
14
|
+
- 根据 DSH 当前语言显示中文或英文界面
|
|
12
15
|
- 将访问令牌和刷新令牌保存在本机 DSH 凭证库中
|
|
13
16
|
|
|
14
17
|
## 使用要求
|
|
@@ -33,37 +36,63 @@ npm install -g pnpm @deepseek-ai/dsh@next
|
|
|
33
36
|
dsh plugin --profile web add dsh-openai-subscription
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
重启 `dsh web
|
|
39
|
+
重启 `dsh web`,然后刷新现有页面。DSH 会自动注册插件,无需手动修改 profile。
|
|
37
40
|
|
|
38
41
|
## 使用
|
|
39
42
|
|
|
40
|
-
1. 打开 **设置 → ChatGPT
|
|
41
|
-
2. 点击
|
|
42
|
-
3.
|
|
43
|
-
4. 授权完成后返回 DSH
|
|
43
|
+
1. 打开 **设置 → ChatGPT 订阅**。
|
|
44
|
+
2. 点击 **连接 ChatGPT**。
|
|
45
|
+
3. 打开验证页面,使用 ChatGPT 账号输入页面中的一次性设备码。
|
|
46
|
+
4. 授权完成后返回 DSH;插件会自动获取并同步模型。
|
|
47
|
+
5. 在 DSH 的模型选择器中选择可用模型。
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
`llm-pi-ai` 会在模型请求期间自动续期可刷新的 OAuth 凭证。设置页中的 **刷新授权** 主要用于授权异常时的手动恢复。
|
|
50
|
+
|
|
51
|
+
### 模型同步规则
|
|
52
|
+
|
|
53
|
+
DSH 的 `openai-codex.models` 是完整替代列表,而不是可追加列表;只手动添加一个模型会遮蔽原来的隐式内置目录。此插件因此写入一份完整、可追踪的快照:
|
|
54
|
+
|
|
55
|
+
- 账号端返回且 `visibility=list` 的模型作为动态来源。
|
|
56
|
+
- DSH 当前安装的 `llm-pi-ai` 内置模型会补充账号响应中完全未提及的 ID。
|
|
57
|
+
- 账号端明确标记为隐藏的 ID 不会被内置目录重新加入。
|
|
58
|
+
- 同一 ID 的账号端元数据优先于内置元数据;内置专属条目只写 `{ id }`,其余能力仍由 `llm-pi-ai` 补全。
|
|
59
|
+
- 后续同步执行字段级三方合并:用户改过的字段、本地新增条目以及从非空列表中删除的模型都会保留。
|
|
60
|
+
- 获取、解析或设置写入失败时,不会用不完整结果覆盖现有模型设置。
|
|
61
|
+
|
|
62
|
+
如果登录前已经存在用户层或 profile 基础层的显式 `models` 列表,插件不会在首次自动同步时推断它是“额外模型”还是有意的 allow-list。此时设置页会显示需要同步;点击 **同步模型** 并确认,才会把现有条目作为本地配置合并进去。
|
|
63
|
+
|
|
64
|
+
### 断开连接
|
|
65
|
+
|
|
66
|
+
**断开连接** 只删除本机保存的授权,以及仍未被用户修改的插件管理模型项。它会保留本地自定义模型和 provider 字段,也不会注销或删除 ChatGPT 账号。操作前会显示确认提示。
|
|
67
|
+
|
|
68
|
+
更换账号或卸载插件前,建议先断开连接。
|
|
46
69
|
|
|
47
70
|
## 卸载
|
|
48
71
|
|
|
49
|
-
|
|
72
|
+
先在设置页点击 **断开连接**,再执行:
|
|
50
73
|
|
|
51
74
|
```sh
|
|
52
75
|
dsh plugin --profile web remove dsh-openai-subscription
|
|
53
76
|
```
|
|
54
77
|
|
|
55
|
-
随后重启 Web profile
|
|
78
|
+
随后重启 Web profile 并刷新页面。
|
|
56
79
|
|
|
57
80
|
## 故障排查
|
|
58
81
|
|
|
59
|
-
-
|
|
82
|
+
- **设置中没有入口:** 使用 `dsh plugin --profile web why dsh-openai-subscription` 确认插件已安装到 `web` profile,然后重启 DSH 并刷新页面。
|
|
60
83
|
- **无法开始授权:** 更新 DSH,确认 `node --version` 满足要求,并检查 OpenAI 登录服务是否可访问。
|
|
61
|
-
- **设备码被拒绝:** 在 ChatGPT
|
|
62
|
-
-
|
|
84
|
+
- **设备码被拒绝:** 在 ChatGPT 安全设置中启用设备码授权,然后重新连接。
|
|
85
|
+
- **模型需要同步:** 点击 **同步模型**。若已有显式模型列表,请阅读确认提示后继续;插件会保留本地编辑。
|
|
86
|
+
- **模型同步失败:** 现有设置会保持不变。检查 `chatgpt.com` 的网络访问和授权状态,稍后重试;必要时先刷新授权。
|
|
87
|
+
- **授权无法恢复:** 断开连接后重新完成设备授权。
|
|
88
|
+
|
|
89
|
+
## 兼容性说明
|
|
90
|
+
|
|
91
|
+
动态目录使用 ChatGPT 官方 Codex 客户端所使用的后端接口,但它不是公开、稳定承诺的 OpenAI API,未来可能变化。接口不提供完整的输出上限、费用或 wire compatibility 元数据;已知模型由 `llm-pi-ai` 补全,未知模型使用适配器默认值。目录中出现模型也不保证旧版适配器支持其所有新能力,遇到调用兼容问题时请先更新 DSH。
|
|
63
92
|
|
|
64
93
|
## 安全与隐私
|
|
65
94
|
|
|
66
|
-
密码只在 OpenAI 官方页面输入,本插件不会接触密码。OAuth 凭证保存在本机 DSH
|
|
95
|
+
密码只在 OpenAI 官方页面输入,本插件不会接触密码。OAuth 凭证保存在本机 DSH 凭证库中。设置页状态接口只返回“是否连接、是否可刷新、模型是否同步、模型数量”等语义信息,不返回令牌、内部账号 ID 或精确令牌到期时间。设备验证码在有效期内属于敏感信息,请勿分享。
|
|
67
96
|
|
|
68
97
|
使用过程仍受 OpenAI 的条款、隐私政策、模型可用性和用量限制约束。本项目是独立的社区插件,与 OpenAI 或 DeepSeek 无隶属或背书关系。
|
|
69
98
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
/** Notice queued by the host during an authorization attempt. */
|
|
2
1
|
interface FlowNotice {
|
|
3
|
-
|
|
4
|
-
url?: string
|
|
5
|
-
code?: string
|
|
2
|
+
kind?: 'requesting-code' | 'enter-code' | 'refreshing' | 'models-synced' | 'models-sync-failed';
|
|
3
|
+
url?: string;
|
|
4
|
+
code?: string;
|
|
6
5
|
}
|
|
7
|
-
/** `openaiSubscription/status` reply. */
|
|
8
6
|
interface StatusInfo {
|
|
9
|
-
configured
|
|
10
|
-
ready
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
configured: boolean;
|
|
8
|
+
ready: boolean;
|
|
9
|
+
refreshable: boolean;
|
|
10
|
+
modelsSynced: boolean;
|
|
11
|
+
modelCount: number;
|
|
13
12
|
}
|
|
14
|
-
/** `openaiSubscription/poll` reply. */
|
|
15
13
|
interface PollInfo {
|
|
16
|
-
status
|
|
17
|
-
notices
|
|
18
|
-
outcome
|
|
19
|
-
error?: string | null;
|
|
14
|
+
status: 'idle' | 'pending' | 'done';
|
|
15
|
+
notices: FlowNotice[];
|
|
16
|
+
outcome: 'authorized' | 'cancelled' | 'failed' | null;
|
|
20
17
|
}
|
|
21
|
-
/** `openaiSubscription/authorize` reply. */
|
|
22
18
|
interface AuthorizeInfo {
|
|
23
|
-
started
|
|
24
|
-
|
|
19
|
+
started: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface ModelSyncInfo {
|
|
22
|
+
synced: true;
|
|
23
|
+
count: number;
|
|
25
24
|
}
|
|
26
|
-
/** Envelope of `connection.rpc.call`. */
|
|
27
25
|
interface RemoteResult<T> {
|
|
28
26
|
ok?: boolean;
|
|
29
27
|
error?: {
|
|
28
|
+
code?: string;
|
|
30
29
|
message?: string;
|
|
31
30
|
} | null;
|
|
32
31
|
value?: T;
|
|
@@ -42,22 +41,30 @@ interface ConnectionService {
|
|
|
42
41
|
interface ClientTimer {
|
|
43
42
|
interval(callback: () => void, delay: number): () => void;
|
|
44
43
|
}
|
|
45
|
-
|
|
44
|
+
type Translate = (key: string, params?: Record<string, string | number>) => string;
|
|
45
|
+
interface LocaleService {
|
|
46
|
+
register(namespace: string, dictionaries: Record<string, Record<string, string>>): () => void;
|
|
47
|
+
bind(namespace: string): Translate;
|
|
48
|
+
}
|
|
46
49
|
interface ClientContext {
|
|
47
50
|
get(name: string): unknown;
|
|
48
51
|
connection: ConnectionService;
|
|
49
52
|
timer: ClientTimer | undefined;
|
|
53
|
+
locale?: LocaleService;
|
|
54
|
+
effect?(setup: () => void | (() => void), label?: string): unknown;
|
|
55
|
+
on?(event: string, listener: () => void): () => void;
|
|
56
|
+
}
|
|
57
|
+
interface SettingsSectionMeta {
|
|
58
|
+
name: string;
|
|
59
|
+
id: string;
|
|
60
|
+
order: number;
|
|
61
|
+
label: string | (() => string);
|
|
62
|
+
locale?: string;
|
|
50
63
|
}
|
|
51
64
|
interface SlotsService {
|
|
52
65
|
inject(name: string, setup: () => void): unknown;
|
|
53
|
-
register(meta:
|
|
54
|
-
|
|
55
|
-
id: string;
|
|
56
|
-
order: number;
|
|
57
|
-
label: string;
|
|
58
|
-
}, render: () => unknown): unknown;
|
|
59
|
-
}
|
|
60
|
-
/** Exports the web module table expects from a `dsh.client` bundle. */
|
|
66
|
+
register(meta: SettingsSectionMeta, render: () => unknown): unknown;
|
|
67
|
+
}
|
|
61
68
|
interface ClientModuleExports {
|
|
62
69
|
apply(ctx: ClientContext): void;
|
|
63
70
|
inject: string[];
|
|
@@ -81,6 +88,8 @@ interface ReactElement {
|
|
|
81
88
|
interface SectionProps {
|
|
82
89
|
connection: ConnectionService;
|
|
83
90
|
timer: ClientTimer | undefined;
|
|
91
|
+
t: Translate;
|
|
92
|
+
subscribeReset?: (listener: () => void) => () => void;
|
|
84
93
|
}
|
|
85
94
|
type SectionComponent = (props: SectionProps) => ReactElement;
|
|
86
95
|
interface ReactModule {
|
|
@@ -91,5 +100,7 @@ interface ReactModule {
|
|
|
91
100
|
current: T;
|
|
92
101
|
};
|
|
93
102
|
}
|
|
94
|
-
|
|
95
|
-
declare
|
|
103
|
+
declare const NS = "settings.openaiSubscription";
|
|
104
|
+
declare const ZH: Record<string, string>;
|
|
105
|
+
declare const EN: Record<string, string>;
|
|
106
|
+
declare function fallbackTranslate(key: string, params?: Record<string, string | number>): string;
|