dsh-ssh-tui 0.3.6 → 0.3.8
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 +34 -18
- package/README.md +23 -8
- package/cordis.patch.yml +17 -3
- package/lib/index.js +58 -8
- package/lib/index.js.map +1 -1
- package/lib/route-memory.js +23 -4
- package/lib/route-memory.js.map +1 -1
- package/lib/subagent-model.js +37 -12
- package/lib/subagent-model.js.map +1 -1
- package/lib/supergrok-token.js +128 -0
- package/lib/supergrok-token.js.map +1 -0
- package/lib/tui.js +253 -105
- package/lib/tui.js.map +1 -1
- package/lib/types/route-memory.d.ts +10 -0
- package/lib/types/subagent-model.d.ts +4 -2
- package/lib/types/supergrok-token.d.ts +22 -0
- package/lib/types/tui.d.ts +24 -8
- package/package.json +29 -29
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read and refresh SuperGrok / xAI OAuth tokens from disk.
|
|
3
|
+
*
|
|
4
|
+
* dsh-ssh-tui does not depend on dsh-llm-xai-oauth. Keep this file's wire
|
|
5
|
+
* format identical to grok-bridge / that plugin: ~/.grok-bridge/auth.json
|
|
6
|
+
* with access_token, refresh_token, expires_at.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
import { dirname, join } from 'node:path';
|
|
11
|
+
export const SUPERGROK_AUTH_PATHS = [
|
|
12
|
+
join(homedir(), '.grok-bridge', 'auth.json'),
|
|
13
|
+
join(homedir(), '.grok', 'auth.json'),
|
|
14
|
+
];
|
|
15
|
+
export const SUPERGROK_REFRESH_SKEW_MS = 5 * 60 * 1000;
|
|
16
|
+
const DEFAULT_CLIENT_ID = 'b1a00492-073a-47ea-816f-4c329264a828';
|
|
17
|
+
const DEFAULT_TOKEN_URL = 'https://auth.x.ai/oauth2/token';
|
|
18
|
+
const DEFAULT_LIFETIME_SECONDS = 3600;
|
|
19
|
+
function stringField(record, key) {
|
|
20
|
+
const value = record[key];
|
|
21
|
+
return typeof value === 'string' && value.trim() !== '' ? value.trim() : undefined;
|
|
22
|
+
}
|
|
23
|
+
function expiresAtMs(record) {
|
|
24
|
+
const raw = record.expires_at ?? record.expiresAt;
|
|
25
|
+
if (typeof raw === 'string')
|
|
26
|
+
return Date.parse(raw) || null;
|
|
27
|
+
if (typeof raw === 'number' && Number.isFinite(raw))
|
|
28
|
+
return raw < 1e12 ? raw * 1000 : raw;
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
export function parseSuperGrokAuthFile(raw, path) {
|
|
32
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
|
|
33
|
+
return undefined;
|
|
34
|
+
const record = raw;
|
|
35
|
+
const accessToken = stringField(record, 'access_token') ?? stringField(record, 'accessToken');
|
|
36
|
+
if (accessToken === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
return {
|
|
39
|
+
accessToken,
|
|
40
|
+
refreshToken: stringField(record, 'refresh_token') ?? stringField(record, 'refreshToken') ?? null,
|
|
41
|
+
expiresAt: expiresAtMs(record),
|
|
42
|
+
clientId: stringField(record, 'oidc_client_id') ?? stringField(record, 'clientId') ?? null,
|
|
43
|
+
path,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function superGrokTokenNeedsRefresh(token, now = Date.now(), skewMs = SUPERGROK_REFRESH_SKEW_MS) {
|
|
47
|
+
if (token.refreshToken === null)
|
|
48
|
+
return false;
|
|
49
|
+
if (token.expiresAt === null)
|
|
50
|
+
return false;
|
|
51
|
+
return token.expiresAt - now < skewMs;
|
|
52
|
+
}
|
|
53
|
+
async function readTokenFile(path) {
|
|
54
|
+
try {
|
|
55
|
+
return parseSuperGrokAuthFile(JSON.parse(await readFile(path, 'utf8')), path);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export async function loadSuperGrokToken(paths = SUPERGROK_AUTH_PATHS) {
|
|
62
|
+
for (const path of paths) {
|
|
63
|
+
const token = await readTokenFile(path);
|
|
64
|
+
if (token !== undefined)
|
|
65
|
+
return token;
|
|
66
|
+
}
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
async function postRefresh(refreshToken, clientId) {
|
|
70
|
+
const response = await fetch(DEFAULT_TOKEN_URL, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: {
|
|
73
|
+
Accept: 'application/json',
|
|
74
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
75
|
+
},
|
|
76
|
+
body: new URLSearchParams({
|
|
77
|
+
grant_type: 'refresh_token',
|
|
78
|
+
refresh_token: refreshToken,
|
|
79
|
+
client_id: clientId,
|
|
80
|
+
}),
|
|
81
|
+
signal: AbortSignal.timeout(15_000),
|
|
82
|
+
});
|
|
83
|
+
const body = await response.json();
|
|
84
|
+
const access = stringField(body, 'access_token');
|
|
85
|
+
if (!response.ok || access === undefined) {
|
|
86
|
+
const error = stringField(body, 'error');
|
|
87
|
+
const description = stringField(body, 'error_description');
|
|
88
|
+
throw new Error(`SuperGrok token 刷新失败(HTTP ${response.status})${error || description ? `:${[error, description].filter(Boolean).join(': ')}` : ''}`);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
access_token: access,
|
|
92
|
+
...stringField(body, 'refresh_token') === undefined ? {} : { refresh_token: stringField(body, 'refresh_token') },
|
|
93
|
+
...typeof body.expires_in === 'number' ? { expires_in: body.expires_in } : {},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export async function persistSuperGrokToken(path, tokenResponse, previousRefreshToken, now = Date.now()) {
|
|
97
|
+
const record = {
|
|
98
|
+
access_token: tokenResponse.access_token,
|
|
99
|
+
refresh_token: tokenResponse.refresh_token ?? previousRefreshToken,
|
|
100
|
+
expires_at: now + (tokenResponse.expires_in ?? DEFAULT_LIFETIME_SECONDS) * 1000,
|
|
101
|
+
saved_at: new Date(now).toISOString(),
|
|
102
|
+
};
|
|
103
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
104
|
+
await writeFile(path, `${JSON.stringify(record, null, 2)}\n`, { mode: 0o600 });
|
|
105
|
+
const stored = parseSuperGrokAuthFile(record, path);
|
|
106
|
+
if (stored === undefined)
|
|
107
|
+
throw new Error(`无法写入 SuperGrok token(${path})`);
|
|
108
|
+
return stored;
|
|
109
|
+
}
|
|
110
|
+
export async function resolveFreshSuperGrokToken(options = {}) {
|
|
111
|
+
const current = await loadSuperGrokToken(options.paths);
|
|
112
|
+
if (current === undefined)
|
|
113
|
+
return undefined;
|
|
114
|
+
const now = options.now ?? Date.now();
|
|
115
|
+
if (options.force !== true && !superGrokTokenNeedsRefresh(current, now)) {
|
|
116
|
+
return current.accessToken;
|
|
117
|
+
}
|
|
118
|
+
if (current.refreshToken === null) {
|
|
119
|
+
if (options.force === true || superGrokTokenNeedsRefresh({ ...current, refreshToken: 'x' }, now)) {
|
|
120
|
+
throw new Error(`SuperGrok token 没有 refresh_token,请运行 dsh-llm-xai-oauth login --force`);
|
|
121
|
+
}
|
|
122
|
+
return current.accessToken;
|
|
123
|
+
}
|
|
124
|
+
const next = await postRefresh(current.refreshToken, current.clientId ?? DEFAULT_CLIENT_ID);
|
|
125
|
+
const saved = await persistSuperGrokToken(current.path, next, current.refreshToken, now);
|
|
126
|
+
return saved.accessToken;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=supergrok-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supergrok-token.js","sourceRoot":"","sources":["../src/supergrok-token.ts"],"names":[],"mappings":"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"}
|