dsh-codex-subscription 1.1.2 → 1.1.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/AGENTS.md +5 -5
- package/README.en.md +3 -3
- package/README.md +3 -3
- package/THIRD_PARTY_NOTICES.md +1 -0
- package/lib/client.js +364 -59
- package/lib/index.js +1 -1
- package/package.json +2 -1
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ Use this guide when a user asks an Agent to install, update, verify, or remove
|
|
|
6
6
|
## Safety
|
|
7
7
|
|
|
8
8
|
- Confirm the target DSH installation and profile. Use `web` only when it is the user's target.
|
|
9
|
-
- Use the exact `1.1.
|
|
9
|
+
- Use the exact `1.1.4` package below; do not install a moving branch.
|
|
10
10
|
- Never print OAuth credentials, account IDs, authorization callbacks, or credential-store contents.
|
|
11
11
|
- Preserve the DSH profile, unrelated plugins, sessions, and saved sign-in.
|
|
12
12
|
- Do not start, stop, or restart DSH without explicit permission.
|
|
@@ -38,19 +38,19 @@ For an official DSH installation run through npm, keep the complete `npx` prefix
|
|
|
38
38
|
run command does not create a global `dsh` command:
|
|
39
39
|
|
|
40
40
|
```sh
|
|
41
|
-
npx -y @deepseek-ai/dsh@0.1.0-rc.8 plugin --profile web add dsh-codex-subscription@1.1.
|
|
41
|
+
npx -y @deepseek-ai/dsh@0.1.0-rc.8 plugin --profile web add dsh-codex-subscription@1.1.4
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
With an existing global `dsh` command:
|
|
45
45
|
|
|
46
46
|
```sh
|
|
47
|
-
dsh plugin --profile web add dsh-codex-subscription@1.1.
|
|
47
|
+
dsh plugin --profile web add dsh-codex-subscription@1.1.4
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
From a DSH-Portable folder:
|
|
51
51
|
|
|
52
52
|
```powershell
|
|
53
|
-
.\dsh.exe plugin --profile web add dsh-codex-subscription@1.1.
|
|
53
|
+
.\dsh.exe plugin --profile web add dsh-codex-subscription@1.1.4
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Use the same `add` command to update or repair. This is the complete package-changing operation.
|
|
@@ -70,7 +70,7 @@ For DSH-Portable, replace `dsh` with `.\dsh.exe`. Static acceptance requires:
|
|
|
70
70
|
|
|
71
71
|
For the official npm route, run the same checks with `npx -y @deepseek-ai/dsh@0.1.0-rc.8` in place of `dsh`.
|
|
72
72
|
|
|
73
|
-
1. `dsh-codex-subscription` version `1.1.
|
|
73
|
+
1. `dsh-codex-subscription` version `1.1.4` appears exactly once.
|
|
74
74
|
2. `codex-subscription` appears exactly once in the composed config.
|
|
75
75
|
3. No unrelated plugin or profile was changed and DSH was not restarted.
|
|
76
76
|
|
package/README.en.md
CHANGED
|
@@ -138,8 +138,8 @@ window returned by the service; Spark uses its independent quota. The plugin doe
|
|
|
138
138
|
|
|
139
139
|
### Composer speed (Beta)
|
|
140
140
|
|
|
141
|
-
With a supported Codex model selected,
|
|
142
|
-
|
|
141
|
+
With a supported Codex model selected, open the composer's model menu to choose Standard or Fast.
|
|
142
|
+
Standard adds no icon; only Fast shows a lightning icon before the model name. Spark does not show the speed entry. Fast mode increases speed and uses more Credits;
|
|
143
143
|
see the [OpenAI Codex Speed documentation](https://learn.chatgpt.com/docs/agent-configuration/speed) for the current rules.
|
|
144
144
|
|
|
145
145
|
## Update and uninstall
|
|
@@ -174,7 +174,7 @@ From a DSH-Portable folder, replace `dsh` above with `.\dsh.exe`.
|
|
|
174
174
|
- **`dsh` is not recognized:** the official npm route does not create a global `dsh` command; use the complete `npx -y @deepseek-ai/dsh@0.1.0-rc.8 ...` command above;
|
|
175
175
|
- **`dsh.exe` is not recognized:** that file is not in the current folder; enter the DSH-Portable folder first or use the one-line Windows setup;
|
|
176
176
|
- **DSH-Portable is not found:** enter its folder and rerun setup, or run `.\dsh.exe plugin --profile web add dsh-codex-subscription` directly;
|
|
177
|
-
- **More than one DSH exists:** the one-line setup
|
|
177
|
+
- **More than one DSH exists:** the one-line setup combines running copies with Portable folders detected in common locations; enter its number. For an Agent, use the intended folder or pass `-DshPath` explicitly;
|
|
178
178
|
- **Setup still fails:** send the Agent guide above to an Agent. Do not delete the profile or change the system PATH to force an install.
|
|
179
179
|
|
|
180
180
|
The ChatGPT Codex backend and DSH can change independently. This community project is not affiliated with or endorsed by DeepSeek or OpenAI.
|
package/README.md
CHANGED
|
@@ -137,8 +137,8 @@ Spark 使用独立额度。插件不会写死“5 小时 + 每周”,也不会
|
|
|
137
137
|
|
|
138
138
|
### 输入框速度(Beta)
|
|
139
139
|
|
|
140
|
-
选择支持的 Codex
|
|
141
|
-
Spark
|
|
140
|
+
选择支持的 Codex 模型后,可在输入框的模型菜单中切换标准与高速。标准模式不增加图标,
|
|
141
|
+
只有高速模式会在模型名称左侧显示闪电;Spark 不显示速度入口。高速模式会提高速度,也会消耗更多 Credits;具体规则见
|
|
142
142
|
[OpenAI Codex Speed 文档](https://learn.chatgpt.com/docs/agent-configuration/speed)。
|
|
143
143
|
|
|
144
144
|
## 更新与卸载
|
|
@@ -173,7 +173,7 @@ DSH-Portable 在其目录中把上述 `dsh` 换成 `.\dsh.exe`。
|
|
|
173
173
|
- **`dsh` 无法识别**:官方 npm 方式本来就不会创建全局 `dsh` 命令,请使用上面的完整 `npx -y @deepseek-ai/dsh@0.1.0-rc.8 ...` 命令;
|
|
174
174
|
- **`dsh.exe` 无法识别**:当前目录没有该文件。请先进入 DSH-Portable 目录,或使用 Windows 单行助手;
|
|
175
175
|
- **找不到 DSH-Portable**:进入它的目录后重新执行安装命令,或直接运行 `.\dsh.exe plugin --profile web add dsh-codex-subscription`;
|
|
176
|
-
- **电脑上有多个 DSH
|
|
176
|
+
- **电脑上有多个 DSH**:单行助手会合并正在运行的副本与常用目录内检测到的 Portable,输入对应编号即可;交给 Agent 时让它进入目标目录,或明确传入 `-DshPath`;
|
|
177
177
|
- **安装仍然失败**:把上面的 Agent 文档链接发给 Agent,不要删除 profile 或随意修改系统 PATH。
|
|
178
178
|
|
|
179
179
|
## 边界与支持
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -7,6 +7,7 @@ This project depends on software distributed under its own terms. The dependency
|
|
|
7
7
|
| DeepSeek Harness packages | Plugin host, client slots, credential and LLM interfaces | MIT | https://github.com/deepseek-ai/deepseek-harness |
|
|
8
8
|
| `@earendil-works/pi-ai` 0.82.1 | OpenAI Codex OAuth, model catalog, Responses transport, and WebSocket continuation | MIT | https://github.com/earendil-works/pi |
|
|
9
9
|
| React | DSH settings component runtime | MIT | https://github.com/facebook/react |
|
|
10
|
+
| Heroicons | Composer speed icon | MIT | https://github.com/tailwindlabs/heroicons |
|
|
10
11
|
| tsdown | Development-time bundler | MIT | https://github.com/rolldown/tsdown |
|
|
11
12
|
|
|
12
13
|
No third-party project endorses this community plugin. See each installed package for its complete license text and transitive dependency notices.
|
package/lib/client.js
CHANGED
|
@@ -4,9 +4,50 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
//#region \0rolldown/runtime.js
|
|
8
|
+
var __create = Object.create;
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
16
|
+
key = keys[i];
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
18
|
+
get: ((k) => from[k]).bind(null, key),
|
|
19
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
25
|
+
value: mod,
|
|
26
|
+
enumerable: true
|
|
27
|
+
}) : target, mod));
|
|
28
|
+
//#endregion
|
|
7
29
|
let react = require("react");
|
|
30
|
+
react = __toESM(react, 1);
|
|
8
31
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
32
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
33
|
+
//#region node_modules/.pnpm/@heroicons+react@2.2.0_react@18.3.1/node_modules/@heroicons/react/16/solid/esm/BoltIcon.js
|
|
34
|
+
function BoltIcon({ title, titleId, ...props }, svgRef) {
|
|
35
|
+
return /*#__PURE__*/ react.createElement("svg", Object.assign({
|
|
36
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
37
|
+
viewBox: "0 0 16 16",
|
|
38
|
+
fill: "currentColor",
|
|
39
|
+
"aria-hidden": "true",
|
|
40
|
+
"data-slot": "icon",
|
|
41
|
+
ref: svgRef,
|
|
42
|
+
"aria-labelledby": titleId
|
|
43
|
+
}, props), title ? /*#__PURE__*/ react.createElement("title", { id: titleId }, title) : null, /*#__PURE__*/ react.createElement("path", {
|
|
44
|
+
fillRule: "evenodd",
|
|
45
|
+
d: "M9.58 1.077a.75.75 0 0 1 .405.82L9.165 6h4.085a.75.75 0 0 1 .567 1.241l-6.5 7.5a.75.75 0 0 1-1.302-.638L6.835 10H2.75a.75.75 0 0 1-.567-1.241l6.5-7.5a.75.75 0 0 1 .897-.182Z",
|
|
46
|
+
clipRule: "evenodd"
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
const ForwardRef = /*#__PURE__*/ react.forwardRef(BoltIcon);
|
|
50
|
+
//#endregion
|
|
10
51
|
//#region src/settings-contract.js
|
|
11
52
|
const SETTINGS_NAMESPACE = "codex-subscription";
|
|
12
53
|
const QUICK_QUOTA_FIELD = "quickQuotaVisible";
|
|
@@ -46,7 +87,8 @@ window.__ModuleLoader__.load({
|
|
|
46
87
|
"remote",
|
|
47
88
|
"settingsScope",
|
|
48
89
|
"modelDirectories",
|
|
49
|
-
"conversation"
|
|
90
|
+
"conversation",
|
|
91
|
+
"sessions"
|
|
50
92
|
];
|
|
51
93
|
const NS = "settings.codexSubscription";
|
|
52
94
|
const CHANNEL = "/codex-subscription";
|
|
@@ -112,6 +154,17 @@ window.__ModuleLoader__.load({
|
|
|
112
154
|
speedStandardHint: "标准速度",
|
|
113
155
|
speedFast: "高速",
|
|
114
156
|
speedFastHint: "1.5 倍,消耗更多 Credits",
|
|
157
|
+
modelMenuAria: "模型、推理等级与速度",
|
|
158
|
+
modelLabel: "模型",
|
|
159
|
+
effortLabel: "推理等级",
|
|
160
|
+
providerDefault: "Default",
|
|
161
|
+
selectModel: "选择模型",
|
|
162
|
+
modelsLoading: "正在读取模型…",
|
|
163
|
+
modelsEmpty: "没有可用模型。",
|
|
164
|
+
effortsEmpty: "当前模型未提供推理等级。",
|
|
165
|
+
modelRetry: "重试",
|
|
166
|
+
modelFailed: "模型目录加载失败:{value}",
|
|
167
|
+
groupFailed: "{name}:{value}",
|
|
115
168
|
imageGenerate: "生成图片",
|
|
116
169
|
imageGenerating: "正在生成…",
|
|
117
170
|
imageGenerated: "已生成",
|
|
@@ -184,6 +237,17 @@ window.__ModuleLoader__.load({
|
|
|
184
237
|
speedStandardHint: "Standard speed",
|
|
185
238
|
speedFast: "Fast",
|
|
186
239
|
speedFastHint: "1.5x; higher Credits use",
|
|
240
|
+
modelMenuAria: "Model, effort, and speed",
|
|
241
|
+
modelLabel: "Model",
|
|
242
|
+
effortLabel: "Effort",
|
|
243
|
+
providerDefault: "Default",
|
|
244
|
+
selectModel: "Select model",
|
|
245
|
+
modelsLoading: "Loading models…",
|
|
246
|
+
modelsEmpty: "No models available.",
|
|
247
|
+
effortsEmpty: "This model provides no reasoning effort levels.",
|
|
248
|
+
modelRetry: "Retry",
|
|
249
|
+
modelFailed: "Could not load models: {value}",
|
|
250
|
+
groupFailed: "{name}: {value}",
|
|
187
251
|
imageGenerate: "Generate image",
|
|
188
252
|
imageGenerating: "Generating…",
|
|
189
253
|
imageGenerated: "Generated",
|
|
@@ -222,8 +286,10 @@ window.__ModuleLoader__.load({
|
|
|
222
286
|
.codexSubscriptionCreditSection{display:flex;flex-direction:column;gap:7px}.codexSubscriptionCreditNote{font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary)}.codexSubscriptionCreditRows{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px}.codexSubscriptionCreditBalance,.codexSubscriptionSpendLimit{min-width:0;border-radius:10px;padding:12px 14px;background:var(--dsw-alias-bg-module-platform)}
|
|
223
287
|
.codexSubscriptionCreditBalance{display:flex;flex-direction:column;gap:6px}.codexSubscriptionCreditBalance span,.codexSubscriptionCreditLabel{font-size:12px;line-height:18px;color:var(--dsw-alias-label-secondary)}.codexSubscriptionCreditBalance strong{font:600 18px/24px ui-monospace,SFMono-Regular,Consolas,monospace;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
|
|
224
288
|
.codexSubscriptionSpendLimit{display:flex;flex-direction:column;gap:8px}.codexSubscriptionSpendTop{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.codexSubscriptionSpendTop strong{font:600 16px/22px ui-monospace,SFMono-Regular,Consolas,monospace;font-variant-numeric:tabular-nums}.codexSubscriptionSpendLimit progress{width:100%;height:6px;border:0;border-radius:999px;overflow:hidden;background:var(--dsw-alias-border-l3);accent-color:var(--dsw-alias-brand-primary,#3964fe);-webkit-appearance:none;appearance:none}.codexSubscriptionSpendLimit progress::-webkit-progress-bar{background:var(--dsw-alias-border-l3);border-radius:999px}.codexSubscriptionSpendLimit progress::-webkit-progress-value{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}.codexSubscriptionSpendLimit progress::-moz-progress-bar{background:var(--dsw-alias-brand-primary,#3964fe);border-radius:999px}
|
|
225
|
-
.codexComposerQuota{display:inline-flex;align-items:center;flex:0 0 auto;height:28px;box-sizing:border-box;
|
|
226
|
-
.
|
|
289
|
+
.codexComposerQuota{display:inline-flex;align-items:center;flex:0 0 auto;height:28px;box-sizing:border-box;padding:0;color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;line-height:20px;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;user-select:none}
|
|
290
|
+
.codexModelSelect{position:relative;min-width:0}.codexModelSelectTrigger{display:flex;align-items:center;gap:4px;min-width:0;max-width:min(360px,45cqw);height:28px;padding:0 4px 0 8px;border:0;border-radius:24px;outline:0;background:transparent;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:500;line-height:20px;cursor:pointer}.codexModelSelectTrigger:hover:not(:disabled),.codexModelSelectTrigger[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover)}.codexModelSelectTrigger:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}.codexModelSelectTrigger:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectBolt{display:block;flex:none;width:14px;height:14px;color:var(--dsw-alias-label-primary)}.codexModelSelectLabel{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectEffort{flex:none;color:var(--dsw-alias-label-caption)}.codexModelSelectChevron{flex:none;color:var(--dsw-alias-label-caption);transition:transform 120ms}.codexModelSelectTrigger[aria-expanded=true] .codexModelSelectChevron{transform:rotate(180deg)}
|
|
291
|
+
.codexModelSelectMenu,.codexModelSelectSubmenu{position:absolute;z-index:30;box-sizing:border-box;width:max-content;min-width:min(240px,calc(100vw - 32px));max-width:min(420px,calc(100vw - 32px));max-height:min(360px,calc(100vh - 96px));padding:4px;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);overflow:hidden}.codexModelSelectMenu{right:0;bottom:calc(100% + 8px)}.codexModelSelectSubmenu{right:calc(100% + 8px);bottom:0;min-width:min(230px,calc(100vw - 32px))}.codexModelSelectCell{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;height:40px;box-sizing:border-box;padding:0 10px;border:0;border-radius:10px;background:transparent;color:inherit;font-size:14px;line-height:22px;text-align:left;cursor:pointer}.codexModelSelectCell:hover,.codexModelSelectCell:focus-visible,.codexModelSelectCell[data-open=true]{background:var(--dsw-alias-interactive-bg-hover);outline:0}.codexModelSelectCell:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectCellLabel{flex:none;white-space:nowrap}.codexModelSelectCellValue{flex:auto;min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary);text-align:right;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectCellChevron{flex:none;color:var(--dsw-alias-label-tertiary)}.codexModelSelectGroups{min-height:0;max-height:352px;overflow-y:auto}.codexModelSelectGroup+.codexModelSelectGroup{margin-top:4px}.codexModelSelectGroupTitle{position:sticky;top:0;z-index:1;padding:5px 8px 3px;background:var(--dsw-specific-menu);color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:500;line-height:18px}.codexModelSelectOption{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;min-height:38px;box-sizing:border-box;padding:6px 8px;border:0;border-radius:10px;outline:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.codexModelSelectOption:hover:not(:disabled),.codexModelSelectOption:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}.codexModelSelectOption:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.codexModelSelectOptionCopy{display:flex;flex:1;min-width:0;flex-direction:column}.codexModelSelectOptionName{overflow:hidden;color:inherit;font-size:14px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectOptionDescription{overflow:hidden;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap}.codexModelSelectCheck{display:grid;place-items:center;flex:0 0 18px;color:var(--dsw-alias-label-primary)}.codexModelSelectStatus,.codexModelSelectEmpty{padding:10px;color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.codexModelSelectError,.codexModelSelectWarning{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:4px;padding:7px 8px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}.codexModelSelectWarning{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-state-warn-label)}.codexModelSelectRetry{flex:none;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-weight:600;cursor:pointer}
|
|
292
|
+
.codexModelSelectMenu{overflow:visible}
|
|
227
293
|
.codexImageTool{display:flex;flex-direction:column;gap:8px;margin:4px 0;color:var(--dsw-alias-label-primary)}.codexImageToolRow{display:flex;align-items:center;min-height:24px;gap:8px;font-size:13px;line-height:20px}.codexImageToolIcon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--dsw-alias-label-secondary)}.codexImageToolIcon::before{content:'';width:8px;height:8px;border:1.5px solid currentColor;border-radius:3px}.codexImageTool[data-state=running] .codexImageToolIcon::before{border-radius:50%;border-right-color:transparent;animation:codexImageSpin 800ms linear infinite}.codexImageTool[data-state=error] .codexImageToolIcon::before{border-color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-state-error-primary)}.codexImageToolTitle{font-weight:500}.codexImageToolState{color:var(--dsw-alias-label-tertiary)}.codexImageToolError{margin:0 0 0 24px;font-size:12px;line-height:18px;color:var(--dsw-alias-state-error-primary)}.codexImageToolGallery{margin-left:24px}.codexGeneratedImageFrame{display:flex;align-items:center;justify-content:center;width:min(240px,100%);min-height:120px;padding:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-tertiary);cursor:pointer}.codexGeneratedImageFrame img{display:block;width:100%;max-height:240px;object-fit:contain}.codexGeneratedImageRetry{min-height:36px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);cursor:pointer}.codexGeneratedImageLightbox{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;padding:32px;border:0;background:rgba(0,0,0,.72)}.codexGeneratedImageLightbox img{display:block;max-width:min(1100px,calc(100vw - 64px));max-height:calc(100vh - 64px);object-fit:contain}.codexGeneratedImageClose{position:absolute;top:16px;right:16px;width:36px;height:36px;border:1px solid rgba(255,255,255,.35);border-radius:50%;background:rgba(0,0,0,.48);color:#fff;font-size:20px;line-height:1;cursor:pointer}@keyframes codexImageSpin{to{transform:rotate(360deg)}}
|
|
228
294
|
@container (max-width:560px){.codexSubscriptionCreditRows{grid-template-columns:1fr}}
|
|
229
295
|
@container (max-width:480px){.codexSubscriptionAccountRow,.codexSubscriptionSectionHead{align-items:flex-start;flex-direction:column}.codexSubscriptionActions{width:100%}.codexSubscriptionSearchChoices{grid-template-columns:1fr}}
|
|
@@ -622,68 +688,288 @@ window.__ModuleLoader__.load({
|
|
|
622
688
|
]
|
|
623
689
|
});
|
|
624
690
|
}
|
|
625
|
-
function
|
|
626
|
-
const [speedOpen, setSpeedOpen] = (0, react.useState)(false);
|
|
691
|
+
function CodexComposerQuota({ preference, rpc, t, directory }) {
|
|
627
692
|
const preferenceSnapshot = usePreferenceSnapshot(preference);
|
|
628
693
|
const current = (0, react.useSyncExternalStore)((listener) => directory.subscribe(listener), () => directory.getSnapshot()).current;
|
|
629
694
|
const codex = current?.provider === "openai-codex";
|
|
630
|
-
const speedSupported = codex && supportsCodexFastMode(current?.model);
|
|
631
|
-
const speedWritable = preferenceSnapshot.status === "ready" && preferenceSnapshot.writable === true;
|
|
632
|
-
const fast = preferenceSnapshot.speedMode === SPEED_MODE_FAST;
|
|
633
695
|
const quotaEnabled = preferenceSnapshot.status === "ready" && preferenceSnapshot.visible && codex;
|
|
634
696
|
const quota = useQuickQuota(rpc, quotaEnabled, current?.model);
|
|
635
|
-
if (!
|
|
636
|
-
const
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
697
|
+
if (!quotaEnabled || quota === void 0) return null;
|
|
698
|
+
const value = percent(quota.remainingPercent);
|
|
699
|
+
const label = fill(t("quickQuotaStatus"), { value });
|
|
700
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
701
|
+
className: "codexComposerQuota",
|
|
702
|
+
role: "status",
|
|
703
|
+
"aria-label": label,
|
|
704
|
+
title: label,
|
|
705
|
+
children: [value, "%"]
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
function CodexModelSelect({ locked, available, directory, load, select, preference, t }) {
|
|
709
|
+
const state = (0, react.useSyncExternalStore)(directory.subscribe, directory.getSnapshot);
|
|
710
|
+
const preferenceSnapshot = usePreferenceSnapshot(preference);
|
|
711
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
712
|
+
const [pane, setPane] = (0, react.useState)("root");
|
|
713
|
+
const rootRef = (0, react.useRef)(null);
|
|
714
|
+
const triggerRef = (0, react.useRef)(null);
|
|
715
|
+
const id = (0, react.useId)();
|
|
716
|
+
const choices = (0, react.useMemo)(() => state.groups.flatMap((group) => group.models.map((model) => ({
|
|
717
|
+
group,
|
|
718
|
+
model,
|
|
719
|
+
selection: {
|
|
720
|
+
provider: group.id,
|
|
721
|
+
model: model.id,
|
|
722
|
+
...model.reasoning?.defaultEffort === void 0 ? {} : { reasoningEffort: model.reasoning.defaultEffort }
|
|
723
|
+
}
|
|
724
|
+
}))), [state.groups]);
|
|
725
|
+
const currentChoice = choices.find((choice) => choice.selection.provider === state.current?.provider && choice.selection.model === state.current?.model);
|
|
726
|
+
const reasoning = currentChoice?.model.reasoning;
|
|
727
|
+
const effectiveEffort = state.current?.reasoningEffort ?? reasoning?.defaultEffort;
|
|
728
|
+
const effortLabel = reasoning === void 0 ? void 0 : effectiveEffort === void 0 ? t("providerDefault") : reasoning.efforts.find((level) => level.id === effectiveEffort)?.name ?? effectiveEffort;
|
|
729
|
+
const effortChoices = (0, react.useMemo)(() => reasoning === void 0 ? [] : [...reasoning.defaultEffort === void 0 ? [{
|
|
730
|
+
key: "provider-default",
|
|
731
|
+
effort: void 0,
|
|
732
|
+
label: t("providerDefault")
|
|
733
|
+
}] : [], ...reasoning.efforts.map((effort) => ({
|
|
734
|
+
key: `effort:${effort.id}`,
|
|
735
|
+
effort: effort.id,
|
|
736
|
+
label: effort.name,
|
|
737
|
+
...effort.description === void 0 ? {} : { description: effort.description }
|
|
738
|
+
}))], [reasoning, t]);
|
|
739
|
+
const modelLabel = currentChoice?.model.name ?? t("selectModel");
|
|
740
|
+
const speedSupported = state.current?.provider === "openai-codex" && supportsCodexFastMode(state.current?.model);
|
|
741
|
+
const speedWritable = preferenceSnapshot.status === "ready" && preferenceSnapshot.writable === true;
|
|
742
|
+
const fast = speedSupported && preferenceSnapshot.speedMode === "fast";
|
|
743
|
+
const busy = state.status === "selecting";
|
|
744
|
+
(0, react.useEffect)(() => {
|
|
745
|
+
if (available) load();
|
|
746
|
+
}, [available, load]);
|
|
747
|
+
(0, react.useEffect)(() => {
|
|
748
|
+
if (!open) return void 0;
|
|
749
|
+
const closeOutside = (event) => {
|
|
750
|
+
if (!rootRef.current?.contains(event.target)) {
|
|
751
|
+
setOpen(false);
|
|
752
|
+
setPane("root");
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
document.addEventListener("mousedown", closeOutside);
|
|
756
|
+
return () => document.removeEventListener("mousedown", closeOutside);
|
|
757
|
+
}, [open]);
|
|
758
|
+
(0, react.useEffect)(() => {
|
|
759
|
+
if (!speedSupported && pane === "speed") setPane("root");
|
|
760
|
+
}, [pane, speedSupported]);
|
|
761
|
+
if (!available) return null;
|
|
762
|
+
const close = (restoreFocus = false) => {
|
|
763
|
+
setOpen(false);
|
|
764
|
+
setPane("root");
|
|
765
|
+
if (restoreFocus) queueMicrotask(() => triggerRef.current?.focus());
|
|
766
|
+
};
|
|
767
|
+
const settleSelection = (accepted) => {
|
|
768
|
+
if (accepted) close(true);
|
|
769
|
+
};
|
|
770
|
+
const chooseModel = (selection) => {
|
|
771
|
+
if (state.current?.provider === selection.provider && state.current.model === selection.model) {
|
|
772
|
+
close(true);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
select(selection).then(settleSelection);
|
|
776
|
+
};
|
|
777
|
+
const chooseEffort = (effort) => {
|
|
778
|
+
if (state.current === null) return;
|
|
779
|
+
if (effectiveEffort === effort) {
|
|
780
|
+
close(true);
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
select({
|
|
784
|
+
provider: state.current.provider,
|
|
785
|
+
model: state.current.model,
|
|
786
|
+
...effort === void 0 ? {} : { reasoningEffort: effort }
|
|
787
|
+
}).then(settleSelection);
|
|
788
|
+
};
|
|
789
|
+
const chooseSpeed = (speedMode) => {
|
|
790
|
+
close(true);
|
|
791
|
+
preference.set({ [SPEED_MODE_FIELD]: speedMode });
|
|
792
|
+
};
|
|
793
|
+
const option = ({ key, label, description, selected, disabled, onClick }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
794
|
+
type: "button",
|
|
795
|
+
role: "menuitemradio",
|
|
796
|
+
"aria-checked": selected,
|
|
797
|
+
className: "codexModelSelectOption",
|
|
798
|
+
disabled,
|
|
799
|
+
onClick,
|
|
800
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
801
|
+
className: "codexModelSelectOptionCopy",
|
|
802
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
803
|
+
className: "codexModelSelectOptionName",
|
|
804
|
+
children: label
|
|
805
|
+
}), description === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
806
|
+
className: "codexModelSelectOptionDescription",
|
|
807
|
+
children: description
|
|
808
|
+
})]
|
|
809
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
810
|
+
className: "codexModelSelectCheck",
|
|
811
|
+
children: selected ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutline16, {}) : null
|
|
812
|
+
})]
|
|
813
|
+
}, key);
|
|
814
|
+
const cell = (target, label, value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
815
|
+
type: "button",
|
|
816
|
+
role: "menuitem",
|
|
817
|
+
className: "codexModelSelectCell",
|
|
818
|
+
"data-open": pane === target,
|
|
819
|
+
"aria-haspopup": "menu",
|
|
820
|
+
"aria-expanded": pane === target,
|
|
821
|
+
onClick: () => setPane((current) => current === target ? "root" : target),
|
|
822
|
+
children: [
|
|
823
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
824
|
+
className: "codexModelSelectCellLabel",
|
|
825
|
+
children: label
|
|
826
|
+
}),
|
|
827
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
828
|
+
className: "codexModelSelectCellValue",
|
|
829
|
+
children: value
|
|
830
|
+
}),
|
|
831
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutline14, { className: "codexModelSelectCellChevron" })
|
|
832
|
+
]
|
|
833
|
+
});
|
|
834
|
+
let submenu = null;
|
|
835
|
+
if (pane === "model") submenu = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
836
|
+
className: "codexModelSelectSubmenu",
|
|
837
|
+
role: "menu",
|
|
838
|
+
"aria-label": t("modelLabel"),
|
|
839
|
+
children: [
|
|
840
|
+
state.status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
841
|
+
className: "codexModelSelectStatus",
|
|
842
|
+
children: t("modelsLoading")
|
|
843
|
+
}) : null,
|
|
844
|
+
state.error === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
845
|
+
className: "codexModelSelectError",
|
|
846
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: fill(t("modelFailed"), { value: state.error }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
847
|
+
className: "codexModelSelectRetry",
|
|
848
|
+
type: "button",
|
|
849
|
+
onClick: load,
|
|
850
|
+
children: t("modelRetry")
|
|
851
|
+
})]
|
|
852
|
+
}),
|
|
853
|
+
state.failures.map((failure) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
854
|
+
className: "codexModelSelectWarning",
|
|
855
|
+
children: fill(t("groupFailed"), {
|
|
856
|
+
name: failure.name,
|
|
857
|
+
value: failure.message
|
|
858
|
+
})
|
|
859
|
+
}, failure.id)),
|
|
860
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
861
|
+
className: "codexModelSelectGroups scrollable",
|
|
862
|
+
children: state.groups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
863
|
+
className: "codexModelSelectGroup",
|
|
864
|
+
role: "group",
|
|
865
|
+
"aria-labelledby": `${id}-${group.id}`,
|
|
866
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
867
|
+
className: "codexModelSelectGroupTitle",
|
|
868
|
+
id: `${id}-${group.id}`,
|
|
869
|
+
children: group.name
|
|
870
|
+
}), group.models.map((model) => option({
|
|
871
|
+
key: model.id,
|
|
872
|
+
label: model.name,
|
|
873
|
+
description: model.description,
|
|
874
|
+
selected: state.current?.provider === group.id && state.current.model === model.id,
|
|
875
|
+
disabled: busy,
|
|
876
|
+
onClick: () => chooseModel({
|
|
877
|
+
provider: group.id,
|
|
878
|
+
model: model.id
|
|
879
|
+
})
|
|
880
|
+
}))]
|
|
881
|
+
}, group.id))
|
|
882
|
+
}),
|
|
883
|
+
state.status === "ready" && choices.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
884
|
+
className: "codexModelSelectEmpty",
|
|
885
|
+
children: t("modelsEmpty")
|
|
886
|
+
}) : null
|
|
887
|
+
]
|
|
888
|
+
});
|
|
889
|
+
else if (pane === "effort") submenu = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
890
|
+
className: "codexModelSelectSubmenu",
|
|
891
|
+
role: "menu",
|
|
892
|
+
"aria-label": t("effortLabel"),
|
|
893
|
+
children: effortChoices.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
894
|
+
className: "codexModelSelectEmpty",
|
|
895
|
+
children: t("effortsEmpty")
|
|
896
|
+
}) : effortChoices.map((level) => option({
|
|
897
|
+
key: level.key,
|
|
898
|
+
label: level.label,
|
|
899
|
+
description: level.description,
|
|
900
|
+
selected: effectiveEffort === level.effort,
|
|
901
|
+
disabled: busy,
|
|
902
|
+
onClick: () => chooseEffort(level.effort)
|
|
903
|
+
}))
|
|
904
|
+
});
|
|
905
|
+
else if (pane === "speed") submenu = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
906
|
+
className: "codexModelSelectSubmenu",
|
|
907
|
+
role: "menu",
|
|
908
|
+
"aria-label": t("speedTitle"),
|
|
909
|
+
children: [option({
|
|
910
|
+
key: SPEED_MODE_STANDARD,
|
|
911
|
+
label: t("speedStandard"),
|
|
912
|
+
description: t("speedStandardHint"),
|
|
913
|
+
selected: !fast,
|
|
656
914
|
disabled: !speedWritable,
|
|
657
|
-
onClick: () =>
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
915
|
+
onClick: () => chooseSpeed(SPEED_MODE_STANDARD)
|
|
916
|
+
}), option({
|
|
917
|
+
key: SPEED_MODE_FAST,
|
|
918
|
+
label: t("speedFast"),
|
|
919
|
+
description: t("speedFastHint"),
|
|
920
|
+
selected: fast,
|
|
921
|
+
disabled: !speedWritable,
|
|
922
|
+
onClick: () => chooseSpeed(SPEED_MODE_FAST)
|
|
923
|
+
})]
|
|
924
|
+
});
|
|
925
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
926
|
+
className: "codexModelSelect",
|
|
927
|
+
ref: rootRef,
|
|
928
|
+
onKeyDown: (event) => {
|
|
929
|
+
if (event.key !== "Escape" || !open) return;
|
|
930
|
+
event.preventDefault();
|
|
931
|
+
if (pane === "root") close(true);
|
|
932
|
+
else setPane("root");
|
|
665
933
|
},
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
934
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
935
|
+
ref: triggerRef,
|
|
936
|
+
type: "button",
|
|
937
|
+
className: "codexModelSelectTrigger",
|
|
938
|
+
"aria-label": modelLabel,
|
|
939
|
+
"aria-haspopup": "menu",
|
|
940
|
+
"aria-expanded": open,
|
|
941
|
+
"aria-controls": open ? `${id}-menu` : void 0,
|
|
942
|
+
title: modelLabel,
|
|
943
|
+
disabled: locked,
|
|
944
|
+
onClick: () => open ? close() : (setPane("root"), setOpen(true), load()),
|
|
945
|
+
children: [
|
|
946
|
+
fast && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ForwardRef, {
|
|
947
|
+
className: "codexModelSelectBolt",
|
|
948
|
+
"aria-hidden": "true"
|
|
949
|
+
}),
|
|
950
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
951
|
+
className: "codexModelSelectLabel",
|
|
952
|
+
children: modelLabel
|
|
953
|
+
}),
|
|
954
|
+
effortLabel === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
955
|
+
className: "codexModelSelectEffort",
|
|
956
|
+
children: effortLabel
|
|
957
|
+
}),
|
|
958
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: "codexModelSelectChevron" })
|
|
959
|
+
]
|
|
960
|
+
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
961
|
+
className: "codexModelSelectMenu",
|
|
962
|
+
id: `${id}-menu`,
|
|
963
|
+
role: "menu",
|
|
964
|
+
"aria-label": t("modelMenuAria"),
|
|
965
|
+
"aria-busy": state.status === "loading" || busy,
|
|
966
|
+
children: [
|
|
967
|
+
cell("model", t("modelLabel"), modelLabel),
|
|
968
|
+
reasoning === void 0 ? null : cell("effort", t("effortLabel"), effortLabel),
|
|
969
|
+
speedSupported && cell("speed", t("speedTitle"), t(fast ? "speedFast" : "speedStandard")),
|
|
970
|
+
submenu
|
|
971
|
+
]
|
|
972
|
+
}) : null]
|
|
687
973
|
});
|
|
688
974
|
}
|
|
689
975
|
function AccountCard({ rpc, t, account, setAccount, onSignedOut }) {
|
|
@@ -1149,7 +1435,26 @@ window.__ModuleLoader__.load({
|
|
|
1149
1435
|
t,
|
|
1150
1436
|
directory: ctx.modelDirectories.directoryFor(sessionId).store
|
|
1151
1437
|
})
|
|
1152
|
-
},
|
|
1438
|
+
}, CodexComposerQuota));
|
|
1439
|
+
const sessions = ctx.get("sessions");
|
|
1440
|
+
ctx.slots.inject("conversation.input.model", () => ctx.slots.register({
|
|
1441
|
+
name: "conversation.input.model",
|
|
1442
|
+
priority: -10,
|
|
1443
|
+
locale: NS,
|
|
1444
|
+
inject: (sessionId) => {
|
|
1445
|
+
const directory = ctx.modelDirectories.directoryFor(sessionId);
|
|
1446
|
+
const available = sessions.subagentAddress(sessionId) === void 0;
|
|
1447
|
+
return {
|
|
1448
|
+
available,
|
|
1449
|
+
directory: directory.store,
|
|
1450
|
+
load: () => {
|
|
1451
|
+
if (available) directory.load();
|
|
1452
|
+
},
|
|
1453
|
+
select: (selection) => available ? directory.select(selection).then(() => true, () => false) : Promise.resolve(false),
|
|
1454
|
+
preference
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
}, CodexModelSelect));
|
|
1153
1458
|
const conversation = ctx.get("conversation");
|
|
1154
1459
|
ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({
|
|
1155
1460
|
name: "tool.call.toolview",
|
package/lib/index.js
CHANGED
|
@@ -494,7 +494,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0 } = {
|
|
|
494
494
|
streamSimple: (model, context, options) => provider.streamSimple(model, context, withSpeed(model, options))
|
|
495
495
|
});
|
|
496
496
|
}
|
|
497
|
-
const USER_AGENT = `dsh-codex-subscription/1.1.
|
|
497
|
+
const USER_AGENT = `dsh-codex-subscription/1.1.4`;
|
|
498
498
|
//#endregion
|
|
499
499
|
//#region src/codex-search.js
|
|
500
500
|
const CODEX_SEARCH_PROVIDER_ID = "codex-subscription";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-codex-subscription",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"packageManager": "pnpm@11.19.0",
|
|
5
5
|
"description": "ChatGPT and Codex subscriptions for DeepSeek Harness with OAuth login, image generation, quota, and subscription web search",
|
|
6
6
|
"type": "module",
|
|
@@ -119,6 +119,7 @@
|
|
|
119
119
|
"@deepseek-ai/dsh-web": "0.1.0-rc.8",
|
|
120
120
|
"@deepseek-ai/schemastery": "3.18.1",
|
|
121
121
|
"@earendil-works/pi-ai": "0.82.1",
|
|
122
|
+
"@heroicons/react": "2.2.0",
|
|
122
123
|
"react": "18.3.1",
|
|
123
124
|
"tsdown": "0.22.2"
|
|
124
125
|
}
|