dsh-grok-subscription 1.1.0 → 1.1.1
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 +8 -0
- package/README.en.md +2 -0
- package/README.md +2 -0
- package/docs/guide.en.md +10 -1
- package/docs/guide.zh-CN.md +10 -1
- package/lib/client.js +2 -2
- package/lib/index.js +61 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.1 — 2026-09-28
|
|
4
|
+
|
|
5
|
+
- Fix **Update plugin** failing in the desktop app. The update built its command from `process.argv[1]`, which is the entry script of whichever process loaded the plugin — the `dsh` CLI only when the host *is* the CLI. The desktop app loads plugins inside `@deepseek-ai/dsh-desktop-host`, so that argument was the desktop host entry and the update relaunched the application with `plugin …` as script arguments instead of installing anything. The version check kept working, so the update button appeared to run and then reported failure.
|
|
6
|
+
- Install updates into the owning profile with pnpm directly, because `dsh plugin --profile desktop` is refused outright: `profile "desktop" is managed exclusively by the Electron application`. The bundled pnpm entry is located by file name in the host's own launch arguments, with the runtime directory carrying the `@deepseek-ai/dsh` package as the fallback, so `PATH` never decides which package manager runs.
|
|
7
|
+
- Pin the install (`--save-exact`) and disable pnpm's release-age gate (`--config.minimumReleaseAge=0`), which would otherwise quietly keep the installed version for a release younger than 24 hours — exactly the release this button exists to fetch.
|
|
8
|
+
- Read the installed manifest back and compare it with the requested version before reporting success, so an update that installs nothing is reported as a failure rather than a success.
|
|
9
|
+
- No model-routing, authentication, proxy, or quota behavior changes. Restart DSH fully after updating so the new version loads.
|
|
10
|
+
|
|
3
11
|
## 1.1.0 — 2026-09-28
|
|
4
12
|
|
|
5
13
|
- Add the original Comet Navigator mascot and align the Chinese/English homepages around features, installation, daily use, screenshots, and maintenance.
|
package/README.en.md
CHANGED
|
@@ -130,6 +130,8 @@ dsh plugin --profile web add dsh-grok-subscription@latest
|
|
|
130
130
|
|
|
131
131
|
For a GitHub-source install, use `dsh plugin --profile web update dsh-grok-subscription`. For a local `link:` install, pull and rebuild the checkout instead of replacing its development link.
|
|
132
132
|
|
|
133
|
+
The desktop app owns its `desktop` profile exclusively, so `dsh plugin --profile desktop …` is refused there. The desktop **Update plugin** button therefore installs the exact version inside that profile directory with DSH's own bundled pnpm; before `1.1.1` that button always failed in the desktop app. Manual steps: [Updates and sign-out](docs/guide.en.md#updates-and-sign-out).
|
|
134
|
+
|
|
133
135
|
**Uninstall:**
|
|
134
136
|
|
|
135
137
|
```sh
|
package/README.md
CHANGED
|
@@ -130,6 +130,8 @@ dsh plugin --profile web add dsh-grok-subscription@latest
|
|
|
130
130
|
|
|
131
131
|
GitHub 来源安装可使用 `dsh plugin --profile web update dsh-grok-subscription`;本地 `link:` 安装应拉取对应仓库并重新构建,不要替换开发链接。
|
|
132
132
|
|
|
133
|
+
桌面版由 Electron 应用独占 `desktop` profile,`dsh plugin --profile desktop …` 会被拒绝,因此桌面版的「更新插件」由插件自己在该 profile 目录中用 DSH 自带的 pnpm 安装精确版本;`1.1.1` 之前该按钮在桌面版必然失败,手动步骤见[更新与登出](docs/guide.zh-CN.md#更新与登出)。
|
|
134
|
+
|
|
133
135
|
**卸载:**
|
|
134
136
|
|
|
135
137
|
```sh
|
package/docs/guide.en.md
CHANGED
|
@@ -18,7 +18,7 @@ dsh plugin --profile web list dsh-grok-subscription --depth 0
|
|
|
18
18
|
For reproducibility, pin a published version, for example:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
|
-
dsh plugin --profile web add dsh-grok-subscription@1.1.
|
|
21
|
+
dsh plugin --profile web add dsh-grok-subscription@1.1.1
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
**Install from GitHub:**
|
|
@@ -128,6 +128,15 @@ That task makes a real model request and uses the selected service's quota; it i
|
|
|
128
128
|
|
|
129
129
|
For npm installs, update in Settings or run `dsh plugin --profile web add dsh-grok-subscription@latest`. For GitHub-source installs, run `dsh plugin --profile web update dsh-grok-subscription`. For local links, pull, test, and rebuild the checkout. Restart DSH afterwards.
|
|
130
130
|
|
|
131
|
+
In the desktop app the `desktop` profile is owned exclusively by the Electron application, and `dsh plugin --profile desktop …` is refused outright (`profile "desktop" is managed exclusively by the Electron application`), so the desktop app can only be updated by the plugin itself. From 1.1.1 the **Update plugin** button installs the exact version inside that profile directory with DSH's own bundled pnpm. If you are still on an older version and the button reports an error, run the equivalent by hand (pnpm ≥ 11):
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
cd "$HOME/.dsh/profiles/desktop" # Windows: cd "$env:USERPROFILE\.dsh\profiles\desktop"
|
|
135
|
+
pnpm add --save-exact dsh-grok-subscription@1.1.1
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Then quit and restart the desktop app completely. After a successful update the profile's `package.json` dependency should show the target version while its `dsh.profile.bundles` entry is unchanged. Refreshing the browser is not enough: without a Host restart the old version keeps loading.
|
|
139
|
+
|
|
131
140
|
Uninstall with `dsh plugin --profile web remove dsh-grok-subscription`. This leaves the profile, other plugins, and the CLI's `auth.json` intact.
|
|
132
141
|
|
|
133
142
|
The Settings logout action clears plugin-side session state; it does not revoke the official CLI session. If the CLI file remains, a later pull or startup may sync it again. To end the official session, use the official CLI / account's sign-out and authorization-management flow. Do not delete an entire DSH profile to handle one account.
|
package/docs/guide.zh-CN.md
CHANGED
|
@@ -18,7 +18,7 @@ dsh plugin --profile web list dsh-grok-subscription --depth 0
|
|
|
18
18
|
需要可重复安装时,固定已发布版本,例如:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
|
-
dsh plugin --profile web add dsh-grok-subscription@1.1.
|
|
21
|
+
dsh plugin --profile web add dsh-grok-subscription@1.1.1
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
**GitHub 来源安装:**
|
|
@@ -128,6 +128,15 @@ dsh --profile headless "只回复:ok"
|
|
|
128
128
|
|
|
129
129
|
npm 安装可在设置页更新,或运行 `dsh plugin --profile web add dsh-grok-subscription@latest`。GitHub 来源安装可运行 `dsh plugin --profile web update dsh-grok-subscription`。本地链接安装则拉取对应 checkout、测试并构建。更新后手动重启 DSH。
|
|
130
130
|
|
|
131
|
+
桌面版的 `desktop` profile 由 Electron 应用独占,`dsh plugin --profile desktop …` 会被直接拒绝(`profile "desktop" is managed exclusively by the Electron application`),所以桌面版只能由插件自己更新。1.1.1 起「更新插件」会在该 profile 目录中用 DSH 自带的 pnpm 安装精确版本;若你仍停留在旧版本且按钮报错,可在终端手动执行(pnpm 需 ≥ 11):
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
cd "$HOME/.dsh/profiles/desktop" # Windows: cd "$env:USERPROFILE\.dsh\profiles\desktop"
|
|
135
|
+
pnpm add --save-exact dsh-grok-subscription@1.1.1
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
然后完全退出并重启桌面版。更新成功后该 profile 的 `package.json` 里依赖应变为目标版本,`dsh.profile.bundles` 条目保持不变。仅刷新网页不够:Host 未重启时仍会加载旧版本。
|
|
139
|
+
|
|
131
140
|
卸载使用 `dsh plugin --profile web remove dsh-grok-subscription`。这不删除整个 profile、其他插件或 Grok CLI 的 `auth.json`。
|
|
132
141
|
|
|
133
142
|
设置页「登出」清理的是插件侧会话状态,不等于撤销官方 CLI 会话。CLI 文件仍然存在时,之后重新拉取或启动可能再次同步登录;彻底结束官方会话应使用官方 CLI / 账号提供的登出与授权管理流程。不要靠删除整个 DSH profile 来处理一个账号。
|
package/lib/client.js
CHANGED
|
@@ -39,7 +39,7 @@ var import_react2 = require("react");
|
|
|
39
39
|
var zh = {
|
|
40
40
|
nav: "Grok \u8BA2\u9605",
|
|
41
41
|
title: "Grok \u8BA2\u9605",
|
|
42
|
-
subtitle: "\u7528 SuperGrok / X Premium\uFF08Grok Build\uFF09\u4F1A\u8BDD\uFF0C\u800C\u4E0D\u662F XAI_API_KEY\u3002\xB7 1.1.
|
|
42
|
+
subtitle: "\u7528 SuperGrok / X Premium\uFF08Grok Build\uFF09\u4F1A\u8BDD\uFF0C\u800C\u4E0D\u662F XAI_API_KEY\u3002\xB7 1.1.1",
|
|
43
43
|
signedIn: "\u5DF2\u767B\u5F55",
|
|
44
44
|
signedOut: "\u672A\u767B\u5F55",
|
|
45
45
|
account: "\u8D26\u6237",
|
|
@@ -119,7 +119,7 @@ var zh = {
|
|
|
119
119
|
var en = {
|
|
120
120
|
nav: "Grok Subscription",
|
|
121
121
|
title: "Grok Subscription",
|
|
122
|
-
subtitle: "Use a SuperGrok / X Premium (Grok Build) session, not XAI_API_KEY. \xB7 1.1.
|
|
122
|
+
subtitle: "Use a SuperGrok / X Premium (Grok Build) session, not XAI_API_KEY. \xB7 1.1.1",
|
|
123
123
|
signedIn: "Signed in",
|
|
124
124
|
signedOut: "Signed out",
|
|
125
125
|
account: "Account",
|
package/lib/index.js
CHANGED
|
@@ -2121,6 +2121,7 @@ function createSessionService({
|
|
|
2121
2121
|
|
|
2122
2122
|
// src/plugin-version.js
|
|
2123
2123
|
import { spawn as spawn2 } from "node:child_process";
|
|
2124
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
2124
2125
|
import { readdir, readFile, realpath } from "node:fs/promises";
|
|
2125
2126
|
import { homedir as homedir3 } from "node:os";
|
|
2126
2127
|
import { join as join4 } from "node:path";
|
|
@@ -2130,6 +2131,8 @@ var NPM_REGISTRY_LATEST_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest
|
|
|
2130
2131
|
var DEFAULT_VERSION_TTL_MS = 5 * 6e4;
|
|
2131
2132
|
var DEFAULT_VERSION_TIMEOUT_MS = 1e4;
|
|
2132
2133
|
var DEFAULT_UPDATE_TIMEOUT_MS = 18e4;
|
|
2134
|
+
var DEFAULT_SETTLE_DELAY_MS = 250;
|
|
2135
|
+
var UPDATE_RELEASE_AGE_MINUTES = 0;
|
|
2133
2136
|
var clone = (value) => structuredClone(value);
|
|
2134
2137
|
function parseSemver(value) {
|
|
2135
2138
|
if (typeof value !== "string") return void 0;
|
|
@@ -2163,6 +2166,16 @@ var readManifest = async (path) => {
|
|
|
2163
2166
|
return void 0;
|
|
2164
2167
|
}
|
|
2165
2168
|
};
|
|
2169
|
+
async function confirmInstalled({ profileDir, expected, settleDelayMs, attempts = 3 }) {
|
|
2170
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
2171
|
+
const installed = (await readManifest(join4(profileDir, "node_modules", PACKAGE_NAME, "package.json")))?.version;
|
|
2172
|
+
if (installed === expected) return;
|
|
2173
|
+
if (attempt < attempts) await new Promise((resolve) => {
|
|
2174
|
+
setTimeout(resolve, settleDelayMs);
|
|
2175
|
+
});
|
|
2176
|
+
}
|
|
2177
|
+
throw new Error("Grok plugin update did not install the requested version");
|
|
2178
|
+
}
|
|
2166
2179
|
async function findInstall({ dshHome, ownPackageJsonUrl }) {
|
|
2167
2180
|
let ownReal;
|
|
2168
2181
|
try {
|
|
@@ -2193,7 +2206,28 @@ async function findInstall({ dshHome, ownPackageJsonUrl }) {
|
|
|
2193
2206
|
if (declared.length === 1) return { kind: classifySpec(declared[0].spec), profile: declared[0].profile };
|
|
2194
2207
|
return { kind: "unknown" };
|
|
2195
2208
|
}
|
|
2196
|
-
|
|
2209
|
+
var isExistingPath = (value) => typeof value === "string" && value !== "" && existsSync4(value);
|
|
2210
|
+
var PNPM_SCRIPT = /[\\/]pnpm\.(?:mjs|cjs|js)$/u;
|
|
2211
|
+
var dshRuntimeRoot = (value) => isExistingPath(value) && existsSync4(join4(value, "node_modules", "@deepseek-ai", "dsh", "package.json")) ? value : void 0;
|
|
2212
|
+
function resolvePnpm({ argv } = {}) {
|
|
2213
|
+
const entries = Array.isArray(argv) ? argv : [];
|
|
2214
|
+
for (const entry of entries) {
|
|
2215
|
+
if (isExistingPath(entry) && PNPM_SCRIPT.test(entry)) return entry;
|
|
2216
|
+
}
|
|
2217
|
+
for (const entry of entries) {
|
|
2218
|
+
const root = dshRuntimeRoot(entry);
|
|
2219
|
+
if (root === void 0) continue;
|
|
2220
|
+
const script = join4(root, "..", "pnpm", "bin", "pnpm.mjs");
|
|
2221
|
+
if (existsSync4(script)) return script;
|
|
2222
|
+
}
|
|
2223
|
+
return void 0;
|
|
2224
|
+
}
|
|
2225
|
+
function resolveLauncher({ argv, execPath }) {
|
|
2226
|
+
const pnpm = resolvePnpm({ argv });
|
|
2227
|
+
if (pnpm === void 0) return { command: "pnpm", prefix: [] };
|
|
2228
|
+
return { command: execPath, prefix: [pnpm] };
|
|
2229
|
+
}
|
|
2230
|
+
function spawnRunCommand({ command, args, cwd }, { signal, timeoutMs }) {
|
|
2197
2231
|
return new Promise((resolve, reject) => {
|
|
2198
2232
|
if (signal?.aborted) {
|
|
2199
2233
|
reject(signal.reason instanceof Error ? signal.reason : new Error("Grok plugin update aborted"));
|
|
@@ -2213,7 +2247,11 @@ function spawnRunCommand(argv, { signal, timeoutMs }) {
|
|
|
2213
2247
|
};
|
|
2214
2248
|
let child;
|
|
2215
2249
|
try {
|
|
2216
|
-
child = spawn2(
|
|
2250
|
+
child = spawn2(command, args, {
|
|
2251
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
2252
|
+
signal: controller.signal,
|
|
2253
|
+
...cwd === void 0 ? {} : { cwd }
|
|
2254
|
+
});
|
|
2217
2255
|
} catch (error) {
|
|
2218
2256
|
settle(reject, error);
|
|
2219
2257
|
return;
|
|
@@ -2241,18 +2279,20 @@ function createGrokPluginManager({
|
|
|
2241
2279
|
fetchImpl = globalThis.fetch,
|
|
2242
2280
|
runCommand = spawnRunCommand,
|
|
2243
2281
|
execPath = process.execPath,
|
|
2244
|
-
|
|
2282
|
+
argv = process.argv,
|
|
2245
2283
|
env = process.env,
|
|
2246
2284
|
ownPackageJsonUrl = new URL("../package.json", import.meta.url),
|
|
2247
2285
|
registryUrl = NPM_REGISTRY_LATEST_URL,
|
|
2248
2286
|
now = Date.now,
|
|
2249
2287
|
ttlMs = DEFAULT_VERSION_TTL_MS,
|
|
2250
2288
|
timeoutMs = DEFAULT_VERSION_TIMEOUT_MS,
|
|
2251
|
-
updateTimeoutMs = DEFAULT_UPDATE_TIMEOUT_MS
|
|
2289
|
+
updateTimeoutMs = DEFAULT_UPDATE_TIMEOUT_MS,
|
|
2290
|
+
settleDelayMs = DEFAULT_SETTLE_DELAY_MS
|
|
2252
2291
|
} = {}) {
|
|
2253
2292
|
if (typeof fetchImpl !== "function") throw new Error("Grok plugin manager requires fetch");
|
|
2254
2293
|
if (typeof runCommand !== "function") throw new Error("Grok plugin manager requires runCommand");
|
|
2255
2294
|
const dshHome = typeof env.DSH_HOME === "string" && env.DSH_HOME !== "" ? env.DSH_HOME : join4(homedir3(), ".dsh");
|
|
2295
|
+
const launcher = resolveLauncher({ argv, execPath });
|
|
2256
2296
|
let cached;
|
|
2257
2297
|
let inFlight;
|
|
2258
2298
|
let generation = 0;
|
|
@@ -2341,15 +2381,30 @@ function createGrokPluginManager({
|
|
|
2341
2381
|
throw new Error("Grok plugin update could not find the owning profile");
|
|
2342
2382
|
}
|
|
2343
2383
|
const latest = await fetchLatest(signal);
|
|
2344
|
-
const
|
|
2384
|
+
const profileDir = join4(dshHome, "profiles", install.profile);
|
|
2345
2385
|
let result;
|
|
2346
2386
|
try {
|
|
2347
|
-
result = await runCommand(
|
|
2387
|
+
result = await runCommand({
|
|
2388
|
+
command: launcher.command,
|
|
2389
|
+
// `pnpm add <exact version>` is what `dsh plugin add` performs for a
|
|
2390
|
+
// registry spec. `--save-exact` keeps the profile dependency pinned,
|
|
2391
|
+
// and the release-age override stops a just-published version from
|
|
2392
|
+
// being skipped as too new (pnpm ≥ 10.16; unknown keys are ignored).
|
|
2393
|
+
args: [
|
|
2394
|
+
...launcher.prefix,
|
|
2395
|
+
"add",
|
|
2396
|
+
"--save-exact",
|
|
2397
|
+
`--config.minimumReleaseAge=${UPDATE_RELEASE_AGE_MINUTES}`,
|
|
2398
|
+
`${PACKAGE_NAME}@${latest}`
|
|
2399
|
+
],
|
|
2400
|
+
cwd: profileDir
|
|
2401
|
+
}, { signal, timeoutMs: updateTimeoutMs });
|
|
2348
2402
|
} catch (error) {
|
|
2349
2403
|
if (signal?.aborted) throw error;
|
|
2350
2404
|
throw new Error("Grok plugin update failed");
|
|
2351
2405
|
}
|
|
2352
2406
|
if (result.code !== 0) throw new Error("Grok plugin update failed");
|
|
2407
|
+
await confirmInstalled({ profileDir, expected: latest, settleDelayMs });
|
|
2353
2408
|
generation += 1;
|
|
2354
2409
|
cached = void 0;
|
|
2355
2410
|
return { version: latest, profile: install.profile };
|