dsh-grok-subscription 1.0.18 → 1.0.20
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.en.md +1 -1
- package/README.md +1 -1
- package/lib/client.js +4 -4
- package/lib/index.js +43 -179
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -209,7 +209,7 @@ npx -y @deepseek-ai/dsh@0.1.5-rc.2 plugin --profile web remove dsh-grok-subscrip
|
|
|
209
209
|
|
|
210
210
|
- **`dsh` is not recognized**: the official npm route never creates a global `dsh` command — use the full `npx -y @deepseek-ai/dsh@0.1.5-rc.2 ...` command above;
|
|
211
211
|
- **The model list is empty**: nothing is exposed while signed out. Finish signing in, then click **Pull from Grok CLI**;
|
|
212
|
-
- **Sign-in opens no browser / chat fails with `fetch failed` / usage says "Billing request timed out"**: all three have one cause — `accounts.x.ai` and `cli-chat-proxy.grok.com` need a tunnel on some networks.
|
|
212
|
+
- **Sign-in opens no browser / chat fails with `fetch failed` / usage says "Billing request timed out"**: all three have one cause — `accounts.x.ai` and `cli-chat-proxy.grok.com` need a tunnel on some networks. This plugin does not configure a proxy of its own. When a tunnel is required, set the standard `https_proxy` / `http_proxy` in the launching environment or in `~/.dsh/.env` (never in a project `.env`). `@deepseek-ai/dsh-http-proxy` then routes `fetch` and the `grok` CLI this plugin spawns. Restart the client afterwards; the sign-in link is handed to your browser and the panel also shows the one-time code and a clickable link.
|
|
213
213
|
- **Nothing changed after upgrading**: the plugin keeps running the old `lib/` — reinstall the plugin, restart `dsh web`, and hard-refresh (Ctrl+Shift+R);
|
|
214
214
|
- **It reports `auth.json` permissions**: apply the `chmod 600` above; the plugin refuses symlinks and group- or other-readable files;
|
|
215
215
|
- **"No reply" after sending a message**: upgrade to `1.0.1` or later. `1.0.0` had a defect where tool-calling turns aborted with a non-serializable stream chunk, leaving no reply in the UI at all.
|
package/README.md
CHANGED
|
@@ -209,7 +209,7 @@ npx -y @deepseek-ai/dsh@0.1.5-rc.2 plugin --profile web remove dsh-grok-subscrip
|
|
|
209
209
|
|
|
210
210
|
- **`dsh` 无法识别**:官方 npm 方式本来就不会创建全局 `dsh` 命令,请使用上面的完整 `npx -y @deepseek-ai/dsh@0.1.5-rc.2 ...` 命令;
|
|
211
211
|
- **模型列表是空的**:未登录时插件不暴露任何模型。先完成登录,再点 **从 Grok CLI 拉取**;
|
|
212
|
-
- **登录不弹浏览器 / 聊天报 `fetch failed` / 用量「Billing request timed out」**:这三件事都指向同一个原因——`accounts.x.ai` 与 `cli-chat-proxy.grok.com`
|
|
212
|
+
- **登录不弹浏览器 / 聊天报 `fetch failed` / 用量「Billing request timed out」**:这三件事都指向同一个原因——`accounts.x.ai` 与 `cli-chat-proxy.grok.com` 在部分网络里必须走隧道。插件不再自己配代理。需要隧道时,在启动环境或 `~/.dsh/.env` 里写标准变量 `https_proxy` / `http_proxy`(不要写进项目目录的 `.env`),宿主的 `@deepseek-ai/dsh-http-proxy` 会让 `fetch` 和本插件拉起的 `grok` CLI 一起走它。写好后重启客户端;登录链接会交给系统浏览器打开,面板里同时显示一次性验证码与可点链接。
|
|
213
213
|
- **升级后界面没变化**:插件会继续运行旧的 `lib/`,请重新安装插件并重启 `dsh web`,然后硬刷新(Ctrl+Shift+R);
|
|
214
214
|
- **提示 `auth.json` 权限不正确**:按上面的 `chmod 600` 处理;插件拒绝读取符号链接或组/其他用户可读的文件;
|
|
215
215
|
- **出现「没有回复」**:请升级到 `1.0.1` 或更高版本。`1.0.0` 存在一个缺陷:工具调用轮次会因流片段无法无损序列化而整轮中止,界面上完全没有回复。
|
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.0.
|
|
42
|
+
subtitle: "\u7528 SuperGrok / X Premium\uFF08Grok Build\uFF09\u4F1A\u8BDD\uFF0C\u800C\u4E0D\u662F XAI_API_KEY\u3002\xB7 1.0.20",
|
|
43
43
|
signedIn: "\u5DF2\u767B\u5F55",
|
|
44
44
|
signedOut: "\u672A\u767B\u5F55",
|
|
45
45
|
account: "\u8D26\u6237",
|
|
@@ -58,7 +58,7 @@ var zh = {
|
|
|
58
58
|
deviceHint: "\u8BBE\u5907\u7801\u767B\u5F55\u4F1A\u8BA9 CLI \u6253\u5370\u4E00\u6B21\u6027\u9A8C\u8BC1\u7801\u548C\u94FE\u63A5\u3002\u82E5\u6D4F\u89C8\u5668\u6CA1\u6709\u81EA\u52A8\u6253\u5F00\uFF0C\u70B9\u63D0\u793A\u91CC\u7684\u201C\u6253\u5F00\u767B\u5F55\u9875\u9762\u201D\u5E76\u786E\u8BA4\u9A8C\u8BC1\u7801\u3002",
|
|
59
59
|
loginWaiting: "\u7B49\u5F85\u6D4F\u89C8\u5668\u6388\u6743\u2026",
|
|
60
60
|
loginOpenBrowser: "\u6253\u5F00\u767B\u5F55\u9875\u9762",
|
|
61
|
-
loginNoUrl: "\u6CA1\u62FF\u5230\u767B\u5F55\u94FE\u63A5\uFF1A\u8BF7\u786E\u8BA4 grok CLI \u80FD\u8BBF\u95EE x.ai\
|
|
61
|
+
loginNoUrl: "\u6CA1\u62FF\u5230\u767B\u5F55\u94FE\u63A5\uFF1A\u8BF7\u786E\u8BA4 grok CLI \u80FD\u8BBF\u95EE x.ai\u3002\u684C\u9762\u7248\u9700\u8981\u4EE3\u7406\u65F6\uFF0C\u5728 ~/.dsh/.env \u8BBE\u7F6E https_proxy \u540E\u91CD\u542F\u3002",
|
|
62
62
|
loginTimeout: "\u7B49\u5F85\u6388\u6743\u8D85\u65F6\uFF0C\u8BF7\u91CD\u65B0\u70B9\u51FB\u767B\u5F55\u3002",
|
|
63
63
|
pullHint: "\u5B89\u5168\u8BFB\u53D6 ~/.grok/auth.json\uFF08\u62D2\u7EDD\u7B26\u53F7\u94FE\u63A5\u4E0E\u7EC4/\u5176\u4ED6\u4EBA\u53EF\u8BFB\uFF09\uFF0C\u53EA\u628A\u77ED\u671F access token \u5199\u5165 DSH\u3002",
|
|
64
64
|
loginHelp: "\u767B\u5F55\u65B9\u5F0F\u8BF4\u660E",
|
|
@@ -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.0.
|
|
122
|
+
subtitle: "Use a SuperGrok / X Premium (Grok Build) session, not XAI_API_KEY. \xB7 1.0.20",
|
|
123
123
|
signedIn: "Signed in",
|
|
124
124
|
signedOut: "Signed out",
|
|
125
125
|
account: "Account",
|
|
@@ -138,7 +138,7 @@ var en = {
|
|
|
138
138
|
deviceHint: "Device-code login makes the CLI print a one-time code and link. If no browser opened, use \u201COpen the sign-in page\u201D in the status line and confirm the code.",
|
|
139
139
|
loginWaiting: "Waiting for browser authorization\u2026",
|
|
140
140
|
loginOpenBrowser: "Open the sign-in page",
|
|
141
|
-
loginNoUrl: "No sign-in link was returned: make sure the grok CLI can reach x.ai
|
|
141
|
+
loginNoUrl: "No sign-in link was returned: make sure the grok CLI can reach x.ai. If the desktop app needs a proxy, set https_proxy in ~/.dsh/.env and restart.",
|
|
142
142
|
loginTimeout: "Timed out waiting for authorization; click sign-in again.",
|
|
143
143
|
pullHint: "Reads ~/.grok/auth.json securely (refuses symlinks and group/other-readable files) and stores only the short-lived access token in DSH.",
|
|
144
144
|
loginHelp: "How signing in works",
|
package/lib/index.js
CHANGED
|
@@ -42,9 +42,9 @@ var LOGIN_START_TIMEOUT_MS = 1e4;
|
|
|
42
42
|
var LOGIN_HANDLER_TIMEOUT_MS = 2e4;
|
|
43
43
|
|
|
44
44
|
// src/session.js
|
|
45
|
-
import { existsSync as
|
|
45
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
46
46
|
import { spawn } from "node:child_process";
|
|
47
|
-
import { join as
|
|
47
|
+
import { join as join3 } from "node:path";
|
|
48
48
|
|
|
49
49
|
// src/auth-file.js
|
|
50
50
|
import { lstatSync, openSync, readFileSync, closeSync, constants as fsConstants } from "node:fs";
|
|
@@ -322,100 +322,6 @@ async function readResponseJson(response, options = {}) {
|
|
|
322
322
|
return JSON.parse(await readResponseText(response, options));
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
-
// src/proxy.js
|
|
326
|
-
import { existsSync as existsSync2 } from "node:fs";
|
|
327
|
-
import { dirname, join as join2 } from "node:path";
|
|
328
|
-
import { pathToFileURL } from "node:url";
|
|
329
|
-
var GROK_API_HOSTS = Object.freeze(["cli-chat-proxy.grok.com"]);
|
|
330
|
-
var HTTP_PROXY_PATTERN = /^https?:\/\//iu;
|
|
331
|
-
var HOST_PROXY_PACKAGE = "@deepseek-ai/dsh-http-proxy";
|
|
332
|
-
var installed;
|
|
333
|
-
var dependencies = { undici: void 0, hostProxies: void 0 };
|
|
334
|
-
function apiProxyUrl(env = process.env) {
|
|
335
|
-
const named = [env?.GROK_API_PROXY, env?.GROK_PROXY];
|
|
336
|
-
for (const candidate of named) {
|
|
337
|
-
if (typeof candidate === "string" && candidate.trim()) return candidate.trim();
|
|
338
|
-
}
|
|
339
|
-
return void 0;
|
|
340
|
-
}
|
|
341
|
-
function hostOf(origin) {
|
|
342
|
-
try {
|
|
343
|
-
return new URL(origin).hostname;
|
|
344
|
-
} catch {
|
|
345
|
-
return "";
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
async function loadHostUndici() {
|
|
349
|
-
let dir = dirname(process.argv[1] ?? "");
|
|
350
|
-
for (let depth = 0; depth < 6 && dir && dir !== dirname(dir); depth++) {
|
|
351
|
-
const entry = join2(dir, "node_modules", "undici", "index.js");
|
|
352
|
-
if (existsSync2(entry)) {
|
|
353
|
-
try {
|
|
354
|
-
return await import(pathToFileURL(entry).href);
|
|
355
|
-
} catch {
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
dir = dirname(dir);
|
|
360
|
-
}
|
|
361
|
-
try {
|
|
362
|
-
return await import("undici");
|
|
363
|
-
} catch {
|
|
364
|
-
return void 0;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
async function hostProxiesGrok() {
|
|
368
|
-
if (typeof dependencies.hostProxies === "function") return dependencies.hostProxies();
|
|
369
|
-
try {
|
|
370
|
-
const mod = await import(HOST_PROXY_PACKAGE);
|
|
371
|
-
const route = mod?.proxyRouteFor?.(`https://${GROK_API_HOSTS[0]}/`);
|
|
372
|
-
return route?.proxied === true;
|
|
373
|
-
} catch {
|
|
374
|
-
return false;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
async function ensureApiRouting(env = process.env) {
|
|
378
|
-
const url = apiProxyUrl(env);
|
|
379
|
-
if (!url || !HTTP_PROXY_PATTERN.test(url)) return "direct";
|
|
380
|
-
if (installed?.url === url) return "plugin";
|
|
381
|
-
if (await hostProxiesGrok()) return "host";
|
|
382
|
-
const undici = dependencies.undici ?? await loadHostUndici();
|
|
383
|
-
const { Agent, Pool, ProxyAgent, getGlobalDispatcher, setGlobalDispatcher } = undici ?? {};
|
|
384
|
-
if (typeof Agent !== "function" || typeof setGlobalDispatcher !== "function") return "direct";
|
|
385
|
-
try {
|
|
386
|
-
const tunnel = new ProxyAgent(url);
|
|
387
|
-
const routing = new Agent({
|
|
388
|
-
factory(origin, options) {
|
|
389
|
-
return GROK_API_HOSTS.includes(hostOf(origin)) ? tunnel : new Pool(origin, options);
|
|
390
|
-
}
|
|
391
|
-
});
|
|
392
|
-
const previous = typeof getGlobalDispatcher === "function" ? getGlobalDispatcher() : void 0;
|
|
393
|
-
setGlobalDispatcher(routing);
|
|
394
|
-
installed = {
|
|
395
|
-
url,
|
|
396
|
-
dispatcher: routing,
|
|
397
|
-
restore: () => {
|
|
398
|
-
if (previous !== void 0) setGlobalDispatcher(previous);
|
|
399
|
-
installed = void 0;
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
return "plugin";
|
|
403
|
-
} catch {
|
|
404
|
-
return "direct";
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
function resetApiRouting() {
|
|
408
|
-
const current = installed;
|
|
409
|
-
installed = void 0;
|
|
410
|
-
if (!current) return false;
|
|
411
|
-
try {
|
|
412
|
-
current.restore();
|
|
413
|
-
return true;
|
|
414
|
-
} catch {
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
325
|
// src/catalog.js
|
|
420
326
|
var REASONING_LEVELS = Object.freeze(["low", "medium", "high", "xhigh"]);
|
|
421
327
|
function asId(value) {
|
|
@@ -538,7 +444,6 @@ function toLlmModels(models) {
|
|
|
538
444
|
});
|
|
539
445
|
}
|
|
540
446
|
async function fetchLiveCatalog(accessToken, options = {}) {
|
|
541
|
-
await ensureApiRouting(options.env);
|
|
542
447
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
543
448
|
const signal = options.signal ?? AbortSignal.timeout(options.timeoutMs ?? CATALOG_TIMEOUT_MS);
|
|
544
449
|
const response = await fetchImpl(MODELS_V2_URL, {
|
|
@@ -784,7 +689,6 @@ async function fetchBillingUsageOnce(accessToken, options = {}) {
|
|
|
784
689
|
}
|
|
785
690
|
let response;
|
|
786
691
|
try {
|
|
787
|
-
await ensureApiRouting(options.env);
|
|
788
692
|
const signal = options.signal ?? AbortSignal.timeout(options.timeoutMs ?? USAGE_TIMEOUT_MS);
|
|
789
693
|
response = await fetchImpl(BILLING_CREDITS_URL, {
|
|
790
694
|
method: "GET",
|
|
@@ -862,11 +766,11 @@ async function fetchBillingUsage(accessToken, options = {}) {
|
|
|
862
766
|
}
|
|
863
767
|
|
|
864
768
|
// src/adapter.js
|
|
865
|
-
import { existsSync as
|
|
769
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
|
|
866
770
|
import { createRequire } from "node:module";
|
|
867
771
|
import { homedir as homedir2 } from "node:os";
|
|
868
|
-
import { dirname
|
|
869
|
-
import { pathToFileURL
|
|
772
|
+
import { dirname, join as join2 } from "node:path";
|
|
773
|
+
import { pathToFileURL } from "node:url";
|
|
870
774
|
function withImportTimeout(promise, ms, message) {
|
|
871
775
|
let timer;
|
|
872
776
|
return Promise.race([
|
|
@@ -886,28 +790,28 @@ function hostModuleRoots(env = process.env, argv1 = process.argv[1]) {
|
|
|
886
790
|
const override = env.DSH_GROK_PEER_ROOT;
|
|
887
791
|
if (typeof override === "string" && override.trim()) push(override.trim());
|
|
888
792
|
if (typeof argv1 === "string" && argv1) {
|
|
889
|
-
let dir =
|
|
890
|
-
for (let depth = 0; depth < 6 && dir && dir !==
|
|
891
|
-
push(
|
|
892
|
-
dir =
|
|
793
|
+
let dir = dirname(argv1);
|
|
794
|
+
for (let depth = 0; depth < 6 && dir && dir !== dirname(dir); depth++) {
|
|
795
|
+
push(join2(dir, "node_modules"));
|
|
796
|
+
dir = dirname(dir);
|
|
893
797
|
}
|
|
894
798
|
}
|
|
895
799
|
const prefix = env.NPM_CONFIG_PREFIX;
|
|
896
|
-
if (typeof prefix === "string" && prefix.trim()) push(
|
|
800
|
+
if (typeof prefix === "string" && prefix.trim()) push(join2(prefix.trim(), "lib", "node_modules"));
|
|
897
801
|
if (typeof process.execPath === "string" && process.execPath) {
|
|
898
|
-
push(
|
|
802
|
+
push(join2(dirname(process.execPath), "..", "lib", "node_modules"));
|
|
899
803
|
}
|
|
900
|
-
push(
|
|
901
|
-
push(
|
|
804
|
+
push(join2("/opt/homebrew", "lib", "node_modules"));
|
|
805
|
+
push(join2("/usr/local", "lib", "node_modules"));
|
|
902
806
|
for (const segment of ["Library/pnpm", ".local/share/pnpm", ".pnpm-global"]) {
|
|
903
|
-
push(
|
|
807
|
+
push(join2(homedir2(), segment, "node_modules"));
|
|
904
808
|
}
|
|
905
809
|
if (typeof env.DSH_PORTABLE_HOME === "string" && env.DSH_PORTABLE_HOME.trim()) {
|
|
906
|
-
push(
|
|
810
|
+
push(join2(env.DSH_PORTABLE_HOME.trim(), "node_modules"));
|
|
907
811
|
}
|
|
908
|
-
push(
|
|
909
|
-
const dshHome = typeof env.DSH_HOME === "string" && env.DSH_HOME.trim() ? env.DSH_HOME.trim() :
|
|
910
|
-
push(
|
|
812
|
+
push(join2(homedir2(), ".local", "lib", "node_modules"));
|
|
813
|
+
const dshHome = typeof env.DSH_HOME === "string" && env.DSH_HOME.trim() ? env.DSH_HOME.trim() : join2(homedir2(), ".dsh");
|
|
814
|
+
push(join2(dshHome, "profiles", "node_modules"));
|
|
911
815
|
return roots;
|
|
912
816
|
}
|
|
913
817
|
function splitSpecifier(specifier) {
|
|
@@ -951,14 +855,14 @@ function resolveExportsTarget(exportsField, subpath) {
|
|
|
951
855
|
function resolveHostSpecifierManually(root, specifier) {
|
|
952
856
|
const { name: name2, subpath } = splitSpecifier(specifier);
|
|
953
857
|
const candidates = [
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
858
|
+
join2(root, name2),
|
|
859
|
+
join2(root, "node_modules", name2),
|
|
860
|
+
join2(root, "@deepseek-ai", "dsh", "node_modules", name2),
|
|
861
|
+
join2(root, "node_modules", "@deepseek-ai", "dsh", "node_modules", name2)
|
|
958
862
|
];
|
|
959
863
|
for (const pkgDir of candidates) {
|
|
960
|
-
const manifest =
|
|
961
|
-
if (!
|
|
864
|
+
const manifest = join2(pkgDir, "package.json");
|
|
865
|
+
if (!existsSync2(manifest)) continue;
|
|
962
866
|
let pkg;
|
|
963
867
|
try {
|
|
964
868
|
pkg = JSON.parse(readFileSync3(manifest, "utf8"));
|
|
@@ -967,15 +871,15 @@ function resolveHostSpecifierManually(root, specifier) {
|
|
|
967
871
|
}
|
|
968
872
|
const target = pkg.exports !== void 0 ? resolveExportsTarget(pkg.exports, subpath) : subpath === "." ? pkg.module ?? pkg.main ?? "index.js" : void 0;
|
|
969
873
|
if (typeof target !== "string" || !target) continue;
|
|
970
|
-
const file =
|
|
971
|
-
if (
|
|
874
|
+
const file = join2(pkgDir, target);
|
|
875
|
+
if (existsSync2(file)) return file;
|
|
972
876
|
}
|
|
973
877
|
return void 0;
|
|
974
878
|
}
|
|
975
879
|
function resolveHostSpecifier(specifier, roots = hostModuleRoots()) {
|
|
976
880
|
for (const root of roots) {
|
|
977
881
|
try {
|
|
978
|
-
const resolved = createRequire(
|
|
882
|
+
const resolved = createRequire(join2(root, "noop.js")).resolve(specifier);
|
|
979
883
|
if (typeof resolved === "string" && resolved) return resolved;
|
|
980
884
|
} catch {
|
|
981
885
|
}
|
|
@@ -991,7 +895,7 @@ async function optionalImport(specifier, options = {}) {
|
|
|
991
895
|
const candidates = [specifier];
|
|
992
896
|
if (!injected && !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("file:")) {
|
|
993
897
|
const resolved = resolveHostSpecifier(specifier, options.hostRoots ?? hostModuleRoots());
|
|
994
|
-
if (resolved) candidates.push(
|
|
898
|
+
if (resolved) candidates.push(pathToFileURL(resolved).href);
|
|
995
899
|
}
|
|
996
900
|
for (const candidate of candidates) {
|
|
997
901
|
try {
|
|
@@ -1206,7 +1110,6 @@ function jsonSafeChunk(value) {
|
|
|
1206
1110
|
return out;
|
|
1207
1111
|
}
|
|
1208
1112
|
async function* streamResponsesUnsafe(options, token) {
|
|
1209
|
-
await ensureApiRouting();
|
|
1210
1113
|
const headers = {
|
|
1211
1114
|
Accept: "text/event-stream",
|
|
1212
1115
|
"Content-Type": "application/json",
|
|
@@ -1642,7 +1545,6 @@ async function createGrokBuildAdapter(session, options = {}) {
|
|
|
1642
1545
|
if (!responsesApi) {
|
|
1643
1546
|
return { adapter: asHostAdapter(duck), kind: "custom-mvp", note: "openai-responses API module is unavailable; using the custom adapter." };
|
|
1644
1547
|
}
|
|
1645
|
-
await ensureApiRouting();
|
|
1646
1548
|
responsesApi = withEncryptedReasoningInclude(responsesApi);
|
|
1647
1549
|
const store = createStore(session);
|
|
1648
1550
|
const authModels = piAi.createModels({
|
|
@@ -1734,43 +1636,17 @@ async function createGrokBuildAdapter(session, options = {}) {
|
|
|
1734
1636
|
}
|
|
1735
1637
|
|
|
1736
1638
|
// src/session.js
|
|
1737
|
-
function resolveGrokBin(env = process.env, exists =
|
|
1639
|
+
function resolveGrokBin(env = process.env, exists = existsSync3) {
|
|
1738
1640
|
if (typeof env.DSH_GROK_BIN === "string" && env.DSH_GROK_BIN.trim()) return env.DSH_GROK_BIN.trim();
|
|
1739
|
-
const local =
|
|
1641
|
+
const local = join3(grokHome(env), "bin", "grok");
|
|
1740
1642
|
if (exists(local)) return local;
|
|
1741
1643
|
return "grok";
|
|
1742
1644
|
}
|
|
1743
|
-
function grokCliAvailable(env = process.env, exists =
|
|
1645
|
+
function grokCliAvailable(env = process.env, exists = existsSync3) {
|
|
1744
1646
|
const bin = resolveGrokBin(env, exists);
|
|
1745
1647
|
if (bin.includes("/") || bin.includes("\\")) return exists(bin);
|
|
1746
1648
|
const delimiter = process.platform === "win32" ? ";" : ":";
|
|
1747
|
-
return String(env.PATH ?? "").split(delimiter).some((dir) => dir && exists(
|
|
1748
|
-
}
|
|
1749
|
-
var STANDARD_PROXY_NAMES = [
|
|
1750
|
-
"http_proxy",
|
|
1751
|
-
"https_proxy",
|
|
1752
|
-
"all_proxy",
|
|
1753
|
-
"no_proxy",
|
|
1754
|
-
"HTTP_PROXY",
|
|
1755
|
-
"HTTPS_PROXY",
|
|
1756
|
-
"ALL_PROXY",
|
|
1757
|
-
"NO_PROXY"
|
|
1758
|
-
];
|
|
1759
|
-
function cliProxyEnv(env = process.env) {
|
|
1760
|
-
const base = env ?? process.env;
|
|
1761
|
-
const declared = STANDARD_PROXY_NAMES.some((name2) => typeof base[name2] === "string" && base[name2].trim() !== "");
|
|
1762
|
-
if (declared) return base;
|
|
1763
|
-
const named = [base.GROK_CLI_PROXY, base.GROK_PROXY].find((value) => typeof value === "string" && value.trim() !== "");
|
|
1764
|
-
const proxy = typeof named === "string" ? named.trim() : "";
|
|
1765
|
-
if (!proxy) return base;
|
|
1766
|
-
const bypass = typeof base.GROK_CLI_NO_PROXY === "string" && base.GROK_CLI_NO_PROXY.trim() ? base.GROK_CLI_NO_PROXY.trim() : "localhost,127.0.0.1,::1";
|
|
1767
|
-
const httpish = /^https?:\/\//iu.test(proxy);
|
|
1768
|
-
return {
|
|
1769
|
-
...base,
|
|
1770
|
-
...httpish ? { http_proxy: proxy, https_proxy: proxy } : {},
|
|
1771
|
-
all_proxy: proxy,
|
|
1772
|
-
no_proxy: bypass
|
|
1773
|
-
};
|
|
1649
|
+
return String(env.PATH ?? "").split(delimiter).some((dir) => dir && exists(join3(dir, bin)));
|
|
1774
1650
|
}
|
|
1775
1651
|
function openExternal(url, options = {}) {
|
|
1776
1652
|
const spawnFn = options.spawn ?? spawn;
|
|
@@ -1797,7 +1673,7 @@ function openExternal(url, options = {}) {
|
|
|
1797
1673
|
}
|
|
1798
1674
|
var LOGIN_URL_PATTERN = /https?:\/\/[^\s<>"'`\\]+/u;
|
|
1799
1675
|
var DEVICE_CODE_PATTERN = /\b([A-Z0-9]{4}-[A-Z0-9]{4})\b/u;
|
|
1800
|
-
function spawnGrokLogin(options = {}) {
|
|
1676
|
+
async function spawnGrokLogin(options = {}) {
|
|
1801
1677
|
const spawnFn = options.spawn ?? spawn;
|
|
1802
1678
|
const bin = resolveGrokBin(options.env, options.exists);
|
|
1803
1679
|
const args = options.device ? ["login", "--device-auth"] : ["login"];
|
|
@@ -1808,7 +1684,7 @@ function spawnGrokLogin(options = {}) {
|
|
|
1808
1684
|
try {
|
|
1809
1685
|
child = spawnFn(bin, args, {
|
|
1810
1686
|
stdio: options.stdio ?? ["ignore", "pipe", "pipe"],
|
|
1811
|
-
env:
|
|
1687
|
+
env: options.env ?? process.env
|
|
1812
1688
|
});
|
|
1813
1689
|
} catch (error) {
|
|
1814
1690
|
reject(new Error(`Could not start grok CLI (${bin})`, { cause: error }));
|
|
@@ -1871,7 +1747,7 @@ function spawnGrokLogin(options = {}) {
|
|
|
1871
1747
|
});
|
|
1872
1748
|
});
|
|
1873
1749
|
}
|
|
1874
|
-
function spawnGrokRefresh(options = {}) {
|
|
1750
|
+
async function spawnGrokRefresh(options = {}) {
|
|
1875
1751
|
const spawnFn = options.spawn ?? spawn;
|
|
1876
1752
|
const bin = resolveGrokBin(options.env, options.exists);
|
|
1877
1753
|
const timeoutMs = typeof options.timeoutMs === "number" && options.timeoutMs > 0 ? options.timeoutMs : CLI_REFRESH_TIMEOUT_MS;
|
|
@@ -1880,7 +1756,7 @@ function spawnGrokRefresh(options = {}) {
|
|
|
1880
1756
|
try {
|
|
1881
1757
|
child = spawnFn(bin, ["models"], {
|
|
1882
1758
|
stdio: options.stdio ?? "ignore",
|
|
1883
|
-
env:
|
|
1759
|
+
env: options.env ?? process.env
|
|
1884
1760
|
});
|
|
1885
1761
|
} catch (error) {
|
|
1886
1762
|
reject(new Error(`Could not start grok CLI (${bin})`, { cause: error }));
|
|
@@ -2247,7 +2123,7 @@ function createSessionService({
|
|
|
2247
2123
|
import { spawn as spawn2 } from "node:child_process";
|
|
2248
2124
|
import { readdir, readFile, realpath } from "node:fs/promises";
|
|
2249
2125
|
import { homedir as homedir3 } from "node:os";
|
|
2250
|
-
import { join as
|
|
2126
|
+
import { join as join4 } from "node:path";
|
|
2251
2127
|
import { fileURLToPath } from "node:url";
|
|
2252
2128
|
var PACKAGE_NAME = PLUGIN_ID;
|
|
2253
2129
|
var NPM_REGISTRY_LATEST_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
@@ -2296,21 +2172,21 @@ async function findInstall({ dshHome, ownPackageJsonUrl }) {
|
|
|
2296
2172
|
}
|
|
2297
2173
|
let entries = [];
|
|
2298
2174
|
try {
|
|
2299
|
-
entries = await readdir(
|
|
2175
|
+
entries = await readdir(join4(dshHome, "profiles"), { withFileTypes: true });
|
|
2300
2176
|
} catch {
|
|
2301
2177
|
entries = [];
|
|
2302
2178
|
}
|
|
2303
2179
|
const declared = [];
|
|
2304
2180
|
for (const entry of entries) {
|
|
2305
2181
|
if (!entry.isDirectory()) continue;
|
|
2306
|
-
const profileDir =
|
|
2307
|
-
const spec = (await readManifest(
|
|
2182
|
+
const profileDir = join4(dshHome, "profiles", entry.name);
|
|
2183
|
+
const spec = (await readManifest(join4(profileDir, "package.json")))?.dependencies?.[PACKAGE_NAME];
|
|
2308
2184
|
if (typeof spec !== "string") continue;
|
|
2309
2185
|
declared.push({ profile: entry.name, spec });
|
|
2310
2186
|
if (ownReal === void 0) continue;
|
|
2311
2187
|
try {
|
|
2312
|
-
const
|
|
2313
|
-
if (
|
|
2188
|
+
const installed = await realpath(join4(profileDir, "node_modules", PACKAGE_NAME, "package.json"));
|
|
2189
|
+
if (installed === ownReal) return { kind: classifySpec(spec), profile: entry.name };
|
|
2314
2190
|
} catch {
|
|
2315
2191
|
}
|
|
2316
2192
|
}
|
|
@@ -2376,7 +2252,7 @@ function createGrokPluginManager({
|
|
|
2376
2252
|
} = {}) {
|
|
2377
2253
|
if (typeof fetchImpl !== "function") throw new Error("Grok plugin manager requires fetch");
|
|
2378
2254
|
if (typeof runCommand !== "function") throw new Error("Grok plugin manager requires runCommand");
|
|
2379
|
-
const dshHome = typeof env.DSH_HOME === "string" && env.DSH_HOME !== "" ? env.DSH_HOME :
|
|
2255
|
+
const dshHome = typeof env.DSH_HOME === "string" && env.DSH_HOME !== "" ? env.DSH_HOME : join4(homedir3(), ".dsh");
|
|
2380
2256
|
let cached;
|
|
2381
2257
|
let inFlight;
|
|
2382
2258
|
let generation = 0;
|
|
@@ -2760,18 +2636,6 @@ function apply(ctx, options = {}) {
|
|
|
2760
2636
|
"grok-subscription: startup lifetime"
|
|
2761
2637
|
);
|
|
2762
2638
|
}
|
|
2763
|
-
void ensureApiRouting().then((mode) => {
|
|
2764
|
-
if (mode === "direct") return;
|
|
2765
|
-
ctx.logger?.debug?.("Grok subscription API route: %s", mode);
|
|
2766
|
-
}).catch((error) => {
|
|
2767
|
-
ctx.logger?.debug?.(
|
|
2768
|
-
"Grok subscription API route skipped: %s",
|
|
2769
|
-
error instanceof Error ? error.message : "unknown"
|
|
2770
|
-
);
|
|
2771
|
-
});
|
|
2772
|
-
if (typeof ctx.effect === "function") {
|
|
2773
|
-
ctx.effect(() => () => resetApiRouting(), "grok-subscription: API proxy route");
|
|
2774
|
-
}
|
|
2775
2639
|
const notifyCatalogChange = () => {
|
|
2776
2640
|
scheduleDeferred2(() => {
|
|
2777
2641
|
if (!active) return;
|