rush-ai 0.18.0 → 0.19.0
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 +21 -3
- package/dist/_codex-content-loader-Q7KBWZSB.js +16 -0
- package/dist/_codex-content-loader-Q7KBWZSB.js.map +1 -0
- package/dist/chunk-2AICQRQP.js +447 -0
- package/dist/chunk-2AICQRQP.js.map +1 -0
- package/dist/{chunk-YKZIRW26.js → chunk-E6OSONYW.js} +14 -332
- package/dist/chunk-E6OSONYW.js.map +1 -0
- package/dist/chunk-OIKYNVKO.js +291 -0
- package/dist/chunk-OIKYNVKO.js.map +1 -0
- package/dist/chunk-RLKEUPBP.js +992 -0
- package/dist/chunk-RLKEUPBP.js.map +1 -0
- package/dist/chunk-T5S6NCHZ.js +48 -0
- package/dist/chunk-T5S6NCHZ.js.map +1 -0
- package/dist/chunk-X45FKY3L.js +98 -0
- package/dist/chunk-X45FKY3L.js.map +1 -0
- package/dist/index.js +691 -2010
- package/dist/index.js.map +1 -1
- package/dist/{install-IH2VPYXH.js → install-JQN4BIHX.js} +6 -3
- package/dist/{install-IH2VPYXH.js.map → install-JQN4BIHX.js.map} +1 -1
- package/dist/mcp-UZYID3GG.js +20 -0
- package/dist/mcp-UZYID3GG.js.map +1 -0
- package/dist/mirror-IHLOSPAS.js +17 -0
- package/dist/mirror-IHLOSPAS.js.map +1 -0
- package/dist/{server-Y2CXHDCK.js → server-PGXKRIPY.js} +6 -3
- package/dist/{server-Y2CXHDCK.js.map → server-PGXKRIPY.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-YKZIRW26.js.map +0 -1
|
@@ -1,46 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
console.error(chalk.green("Success!"), message);
|
|
13
|
-
},
|
|
14
|
-
/** Error → stderr */
|
|
15
|
-
error(message) {
|
|
16
|
-
console.error(chalk.red("Error:"), message);
|
|
17
|
-
},
|
|
18
|
-
/** Warning → stderr */
|
|
19
|
-
warn(message) {
|
|
20
|
-
console.error(chalk.yellow("Warning:"), message);
|
|
21
|
-
},
|
|
22
|
-
/** Info → stderr */
|
|
23
|
-
info(message) {
|
|
24
|
-
console.error(chalk.cyan("Info:"), message);
|
|
25
|
-
},
|
|
26
|
-
/** Dim status → stderr */
|
|
27
|
-
dim(message) {
|
|
28
|
-
console.error(chalk.dim(message));
|
|
29
|
-
},
|
|
30
|
-
table(data) {
|
|
31
|
-
console.table(data);
|
|
32
|
-
},
|
|
33
|
-
/** Newline → stderr (status separator) */
|
|
34
|
-
newline() {
|
|
35
|
-
console.error();
|
|
36
|
-
},
|
|
37
|
-
link(text, url) {
|
|
38
|
-
return chalk.cyan.underline(url);
|
|
39
|
-
},
|
|
40
|
-
bold(text) {
|
|
41
|
-
return chalk.bold(text);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
2
|
+
import {
|
|
3
|
+
getAuthConfig,
|
|
4
|
+
getAuthToken,
|
|
5
|
+
getCasConfig,
|
|
6
|
+
getGlobalConfig,
|
|
7
|
+
setAuthConfig
|
|
8
|
+
} from "./chunk-OIKYNVKO.js";
|
|
9
|
+
import {
|
|
10
|
+
output
|
|
11
|
+
} from "./chunk-T5S6NCHZ.js";
|
|
44
12
|
|
|
45
13
|
// src/version.ts
|
|
46
14
|
import { readFileSync } from "fs";
|
|
@@ -66,274 +34,6 @@ function loadVersion() {
|
|
|
66
34
|
}
|
|
67
35
|
var VERSION = loadVersion();
|
|
68
36
|
|
|
69
|
-
// src/util/config.ts
|
|
70
|
-
import { homedir } from "os";
|
|
71
|
-
import { resolve as resolve2 } from "path";
|
|
72
|
-
import Conf from "conf";
|
|
73
|
-
var AUTH_CONFIG_DIR = resolve2(homedir(), ".rush");
|
|
74
|
-
var DEFAULT_API = "https://rush.zhenguanyu.com";
|
|
75
|
-
var AUTH_DEFAULTS = {
|
|
76
|
-
token: null,
|
|
77
|
-
expiresAt: null,
|
|
78
|
-
refreshToken: null,
|
|
79
|
-
method: null,
|
|
80
|
-
tokenId: null,
|
|
81
|
-
sourceUrl: null
|
|
82
|
-
};
|
|
83
|
-
var GLOBAL_DEFAULTS = {
|
|
84
|
-
currentTeam: null,
|
|
85
|
-
api: DEFAULT_API,
|
|
86
|
-
collectMetrics: true
|
|
87
|
-
};
|
|
88
|
-
function isEmptyAuthEntry(entry) {
|
|
89
|
-
if (!entry || typeof entry !== "object") return false;
|
|
90
|
-
const auth = entry;
|
|
91
|
-
return !auth.token && auth.expiresAt == null && !auth.refreshToken && auth.method == null && !auth.tokenId && !auth.sourceUrl;
|
|
92
|
-
}
|
|
93
|
-
var globalStore = new Conf({
|
|
94
|
-
projectName: "rush-ai",
|
|
95
|
-
cwd: AUTH_CONFIG_DIR,
|
|
96
|
-
configName: "config",
|
|
97
|
-
defaults: {}
|
|
98
|
-
});
|
|
99
|
-
var authStore = new Conf({
|
|
100
|
-
projectName: "rush-ai",
|
|
101
|
-
cwd: AUTH_CONFIG_DIR,
|
|
102
|
-
configName: "auth",
|
|
103
|
-
defaults: {}
|
|
104
|
-
});
|
|
105
|
-
function migrateGlobalStoreIfNeeded() {
|
|
106
|
-
const version = globalStore.get("_version");
|
|
107
|
-
if (version === 2) return;
|
|
108
|
-
const hasOldFormat = globalStore.has("api") && !globalStore.has("profiles");
|
|
109
|
-
const isEmpty = globalStore.size === 0;
|
|
110
|
-
if (hasOldFormat) {
|
|
111
|
-
const oldConfig = {
|
|
112
|
-
currentTeam: globalStore.get("currentTeam") ?? null,
|
|
113
|
-
api: globalStore.get("api") ?? DEFAULT_API,
|
|
114
|
-
collectMetrics: globalStore.get("collectMetrics") ?? true
|
|
115
|
-
};
|
|
116
|
-
globalStore.clear();
|
|
117
|
-
globalStore.set("_version", 2);
|
|
118
|
-
globalStore.set("activeProfile", "default");
|
|
119
|
-
globalStore.set("profiles", { default: oldConfig });
|
|
120
|
-
} else if (isEmpty || !globalStore.has("profiles")) {
|
|
121
|
-
globalStore.set("_version", 2);
|
|
122
|
-
if (!globalStore.has("activeProfile")) {
|
|
123
|
-
globalStore.set("activeProfile", "default");
|
|
124
|
-
}
|
|
125
|
-
if (!globalStore.has("profiles")) {
|
|
126
|
-
globalStore.set("profiles", { default: { ...GLOBAL_DEFAULTS } });
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function migrateAuthStoreIfNeeded() {
|
|
131
|
-
const version = authStore.get("_version");
|
|
132
|
-
if (version === 3) {
|
|
133
|
-
pruneEmptyAuthEntries();
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
const hasOldFormat = authStore.has("token") || authStore.has("method");
|
|
137
|
-
const isEmpty = authStore.size === 0;
|
|
138
|
-
if (hasOldFormat) {
|
|
139
|
-
const oldAuth = {
|
|
140
|
-
token: authStore.get("token") ?? null,
|
|
141
|
-
expiresAt: authStore.get("expiresAt") ?? null,
|
|
142
|
-
refreshToken: authStore.get("refreshToken") ?? null,
|
|
143
|
-
method: authStore.get("method") ?? null,
|
|
144
|
-
tokenId: authStore.get("tokenId") ?? null,
|
|
145
|
-
sourceUrl: null
|
|
146
|
-
};
|
|
147
|
-
authStore.clear();
|
|
148
|
-
authStore.set("_version", 3);
|
|
149
|
-
if (!isEmptyAuthEntry(oldAuth)) {
|
|
150
|
-
authStore.set("default", oldAuth);
|
|
151
|
-
}
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
if (isEmpty) {
|
|
155
|
-
authStore.set("_version", 3);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
if (version === 2) {
|
|
159
|
-
for (const key of Object.keys(authStore.store)) {
|
|
160
|
-
if (key === "_version") continue;
|
|
161
|
-
const entry = authStore.get(key);
|
|
162
|
-
if (!entry || typeof entry !== "object") continue;
|
|
163
|
-
const asAuth = entry;
|
|
164
|
-
if (!("sourceUrl" in asAuth)) {
|
|
165
|
-
authStore.set(key, { ...asAuth, sourceUrl: null });
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
authStore.set("_version", 3);
|
|
169
|
-
pruneEmptyAuthEntries();
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
function pruneEmptyAuthEntries() {
|
|
173
|
-
for (const key of Object.keys(authStore.store)) {
|
|
174
|
-
if (key === "_version") continue;
|
|
175
|
-
if (isEmptyAuthEntry(authStore.get(key))) {
|
|
176
|
-
authStore.delete(key);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
migrateGlobalStoreIfNeeded();
|
|
181
|
-
migrateAuthStoreIfNeeded();
|
|
182
|
-
function getActiveProfile() {
|
|
183
|
-
return process.env.RUSH_PROFILE ?? globalStore.get("activeProfile") ?? "default";
|
|
184
|
-
}
|
|
185
|
-
function setActiveProfile(name) {
|
|
186
|
-
const profiles = globalStore.get("profiles") ?? {};
|
|
187
|
-
if (!profiles[name]) {
|
|
188
|
-
throw new Error(
|
|
189
|
-
`Profile '${name}' does not exist. Available: ${Object.keys(profiles).join(", ")}`
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
globalStore.set("activeProfile", name);
|
|
193
|
-
}
|
|
194
|
-
function listProfiles() {
|
|
195
|
-
const profiles = globalStore.get("profiles") ?? {};
|
|
196
|
-
return Object.keys(profiles);
|
|
197
|
-
}
|
|
198
|
-
function createProfile(name, config) {
|
|
199
|
-
const profiles = globalStore.get("profiles") ?? {};
|
|
200
|
-
if (profiles[name]) {
|
|
201
|
-
throw new Error(`Profile '${name}' already exists.`);
|
|
202
|
-
}
|
|
203
|
-
const defaultConfig = profiles.default ?? GLOBAL_DEFAULTS;
|
|
204
|
-
profiles[name] = { ...defaultConfig, ...config };
|
|
205
|
-
globalStore.set("profiles", profiles);
|
|
206
|
-
}
|
|
207
|
-
function deleteProfile(name) {
|
|
208
|
-
if (name === "default") {
|
|
209
|
-
throw new Error("Cannot delete the 'default' profile.");
|
|
210
|
-
}
|
|
211
|
-
const active = getActiveProfile();
|
|
212
|
-
if (name === active) {
|
|
213
|
-
throw new Error(
|
|
214
|
-
`Cannot delete the active profile '${name}'. Switch to another profile first.`
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
const profiles = globalStore.get("profiles") ?? {};
|
|
218
|
-
if (!profiles[name]) {
|
|
219
|
-
throw new Error(`Profile '${name}' does not exist.`);
|
|
220
|
-
}
|
|
221
|
-
delete profiles[name];
|
|
222
|
-
globalStore.set("profiles", profiles);
|
|
223
|
-
authStore.delete(name);
|
|
224
|
-
}
|
|
225
|
-
function getAuthConfig() {
|
|
226
|
-
const profile = getActiveProfile();
|
|
227
|
-
const profileAuth = authStore.get(profile);
|
|
228
|
-
return {
|
|
229
|
-
token: profileAuth?.token ?? null,
|
|
230
|
-
expiresAt: profileAuth?.expiresAt ?? null,
|
|
231
|
-
refreshToken: profileAuth?.refreshToken ?? null,
|
|
232
|
-
method: profileAuth?.method ?? null,
|
|
233
|
-
tokenId: profileAuth?.tokenId ?? null,
|
|
234
|
-
sourceUrl: profileAuth?.sourceUrl ?? null
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
function setAuthConfig(config) {
|
|
238
|
-
const profile = getActiveProfile();
|
|
239
|
-
const current = authStore.get(profile) ?? {
|
|
240
|
-
...AUTH_DEFAULTS
|
|
241
|
-
};
|
|
242
|
-
authStore.set(profile, { ...current, ...config });
|
|
243
|
-
}
|
|
244
|
-
function clearAuthConfig() {
|
|
245
|
-
const profile = getActiveProfile();
|
|
246
|
-
authStore.delete(profile);
|
|
247
|
-
}
|
|
248
|
-
function getGlobalConfig() {
|
|
249
|
-
const profile = getActiveProfile();
|
|
250
|
-
const profiles = globalStore.get("profiles") ?? {};
|
|
251
|
-
const profileConfig = profiles[profile] ?? GLOBAL_DEFAULTS;
|
|
252
|
-
return {
|
|
253
|
-
currentTeam: profileConfig.currentTeam ?? null,
|
|
254
|
-
api: profileConfig.api ?? DEFAULT_API,
|
|
255
|
-
collectMetrics: profileConfig.collectMetrics ?? true
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
function setGlobalConfig(config) {
|
|
259
|
-
const profile = getActiveProfile();
|
|
260
|
-
const profiles = globalStore.get("profiles") ?? {};
|
|
261
|
-
const current = profiles[profile] ?? { ...GLOBAL_DEFAULTS };
|
|
262
|
-
profiles[profile] = { ...current, ...config };
|
|
263
|
-
globalStore.set("profiles", profiles);
|
|
264
|
-
}
|
|
265
|
-
function getConfigDir() {
|
|
266
|
-
return AUTH_CONFIG_DIR;
|
|
267
|
-
}
|
|
268
|
-
function isLoggedIn() {
|
|
269
|
-
const auth = getAuthConfig();
|
|
270
|
-
if (!auth.token) return false;
|
|
271
|
-
if (auth.expiresAt && Date.now() > auth.expiresAt) {
|
|
272
|
-
return auth.method === "cas" && Boolean(auth.refreshToken);
|
|
273
|
-
}
|
|
274
|
-
return true;
|
|
275
|
-
}
|
|
276
|
-
function normalizeApiUrl(url) {
|
|
277
|
-
return url.replace(/\/+$/, "").toLowerCase();
|
|
278
|
-
}
|
|
279
|
-
function checkAuthSourceMismatch(overrideCurrentUrl) {
|
|
280
|
-
const auth = getAuthConfig();
|
|
281
|
-
if (!auth.token || !auth.sourceUrl) return null;
|
|
282
|
-
const current = overrideCurrentUrl ?? getGlobalConfig().api;
|
|
283
|
-
if (normalizeApiUrl(auth.sourceUrl) === normalizeApiUrl(current)) return null;
|
|
284
|
-
return { stored: auth.sourceUrl, current };
|
|
285
|
-
}
|
|
286
|
-
function getProfileConfig(name) {
|
|
287
|
-
const profiles = globalStore.get("profiles") ?? {};
|
|
288
|
-
return profiles[name] ?? null;
|
|
289
|
-
}
|
|
290
|
-
function getProfileAuth(name) {
|
|
291
|
-
const profileAuth = authStore.get(name);
|
|
292
|
-
return {
|
|
293
|
-
token: profileAuth?.token ?? null,
|
|
294
|
-
expiresAt: profileAuth?.expiresAt ?? null,
|
|
295
|
-
refreshToken: profileAuth?.refreshToken ?? null,
|
|
296
|
-
method: profileAuth?.method ?? null,
|
|
297
|
-
tokenId: profileAuth?.tokenId ?? null,
|
|
298
|
-
sourceUrl: profileAuth?.sourceUrl ?? null
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// src/util/auth.ts
|
|
303
|
-
function getAuthMethod() {
|
|
304
|
-
if (process.env.RUSH_API_KEY) {
|
|
305
|
-
return "api_key";
|
|
306
|
-
}
|
|
307
|
-
const auth = getAuthConfig();
|
|
308
|
-
if (auth.token) {
|
|
309
|
-
if (auth.method === "api_key" || auth.token.startsWith("rush_sk_")) {
|
|
310
|
-
return "api_key";
|
|
311
|
-
}
|
|
312
|
-
if (auth.method === "platform_token") {
|
|
313
|
-
return "platform_token";
|
|
314
|
-
}
|
|
315
|
-
return auth.method ?? "cas";
|
|
316
|
-
}
|
|
317
|
-
return null;
|
|
318
|
-
}
|
|
319
|
-
function getAuthToken() {
|
|
320
|
-
if (process.env.RUSH_API_KEY) {
|
|
321
|
-
return process.env.RUSH_API_KEY;
|
|
322
|
-
}
|
|
323
|
-
const auth = getAuthConfig();
|
|
324
|
-
return auth.token;
|
|
325
|
-
}
|
|
326
|
-
function getCasConfig() {
|
|
327
|
-
const config = getGlobalConfig();
|
|
328
|
-
const baseUrl = process.env.RUSH_API_URL ?? config.api;
|
|
329
|
-
return {
|
|
330
|
-
authorizeEndpoint: process.env.RUSH_CAS_AUTHORIZE_ENDPOINT ?? `${baseUrl}/cas/oauth2/authorize`,
|
|
331
|
-
tokenEndpoint: process.env.RUSH_CAS_TOKEN_ENDPOINT ?? `${baseUrl}/cas/oauth2/token`,
|
|
332
|
-
revokeEndpoint: process.env.RUSH_CAS_REVOKE_ENDPOINT ?? `${baseUrl}/cas/oauth2/revoke`,
|
|
333
|
-
clientId: process.env.RUSH_CAS_CLIENT_ID ?? "rush-ai"
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
|
|
337
37
|
// src/util/errors.ts
|
|
338
38
|
var RushError = class extends Error {
|
|
339
39
|
code;
|
|
@@ -692,15 +392,15 @@ async function withRetry(fn, options = {}) {
|
|
|
692
392
|
}
|
|
693
393
|
const status = error instanceof ApiError ? error.status : void 0;
|
|
694
394
|
onRetry?.(attempt + 1, delayMs, status);
|
|
695
|
-
await new Promise((
|
|
696
|
-
const timer = setTimeout(
|
|
395
|
+
await new Promise((resolve2, reject) => {
|
|
396
|
+
const timer = setTimeout(resolve2, delayMs);
|
|
697
397
|
if (signal) {
|
|
698
398
|
const onAbort = () => {
|
|
699
399
|
clearTimeout(timer);
|
|
700
400
|
reject(lastError);
|
|
701
401
|
};
|
|
702
402
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
703
|
-
const origResolve =
|
|
403
|
+
const origResolve = resolve2;
|
|
704
404
|
setTimeout(() => {
|
|
705
405
|
signal.removeEventListener("abort", onAbort);
|
|
706
406
|
origResolve();
|
|
@@ -910,25 +610,7 @@ function createClient() {
|
|
|
910
610
|
}
|
|
911
611
|
|
|
912
612
|
export {
|
|
913
|
-
output,
|
|
914
613
|
VERSION,
|
|
915
|
-
getActiveProfile,
|
|
916
|
-
setActiveProfile,
|
|
917
|
-
listProfiles,
|
|
918
|
-
createProfile,
|
|
919
|
-
deleteProfile,
|
|
920
|
-
getAuthConfig,
|
|
921
|
-
setAuthConfig,
|
|
922
|
-
clearAuthConfig,
|
|
923
|
-
getGlobalConfig,
|
|
924
|
-
setGlobalConfig,
|
|
925
|
-
getConfigDir,
|
|
926
|
-
isLoggedIn,
|
|
927
|
-
checkAuthSourceMismatch,
|
|
928
|
-
getProfileConfig,
|
|
929
|
-
getProfileAuth,
|
|
930
|
-
getAuthMethod,
|
|
931
|
-
getAuthToken,
|
|
932
614
|
verifyCurrentAuthSession,
|
|
933
615
|
revokeCurrentSession,
|
|
934
616
|
RushError,
|
|
@@ -939,4 +621,4 @@ export {
|
|
|
939
621
|
setVerbosity,
|
|
940
622
|
createClient
|
|
941
623
|
};
|
|
942
|
-
//# sourceMappingURL=chunk-
|
|
624
|
+
//# sourceMappingURL=chunk-E6OSONYW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/util/errors.ts","../src/util/verbosity.ts","../src/util/auth-session.ts","../src/util/retry.ts","../src/util/client.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Dynamically read version from package.json.\n *\n * Path resolution:\n * - tsup bundle: dist/index.js → __dirname = dist/ → ../package.json\n * - vitest source: src/version.ts → __dirname = src/ → ../package.json\n */\nexport function loadVersion(): string {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n const candidates = [\n resolve(__dirname, '..', 'package.json'),\n resolve(__dirname, '..', '..', 'package.json'),\n ];\n\n for (const candidate of candidates) {\n try {\n const pkg = JSON.parse(readFileSync(candidate, 'utf-8'));\n if (pkg.name === 'rush-ai' && pkg.version) {\n return pkg.version;\n }\n } catch {\n // try next candidate\n }\n }\n console.error('[rush-ai] Warning: Could not read version from package.json');\n return '0.0.0-unknown';\n}\n\nexport const VERSION: string = loadVersion();\n","export class RushError extends Error {\n public code: string;\n public meta: Record<string, unknown>;\n public exitCode: number;\n\n constructor(\n message: string,\n meta: Record<string, unknown> = {},\n code = 'RUSH_ERROR',\n exitCode = 2\n ) {\n super(message);\n this.name = 'RushError';\n this.code = code;\n this.meta = meta;\n this.exitCode = exitCode;\n }\n}\n\nexport class AuthError extends RushError {\n constructor(message = 'Not authenticated. Run `rush-ai auth login` first.') {\n super(message, {}, 'AUTH_ERROR', 3);\n this.name = 'AuthError';\n }\n}\n\nexport class TaskFailedError extends RushError {\n constructor(message: string, meta: Record<string, unknown> = {}) {\n super(message, meta, 'TASK_FAILED', 1);\n this.name = 'TaskFailedError';\n }\n}\n\n/**\n * Generate a user-friendly error message based on HTTP status.\n * Server-provided error messages take priority.\n */\nfunction friendlyMessage(status: number, serverMessage?: string): string {\n if (serverMessage) return serverMessage;\n\n switch (status) {\n case 401:\n return 'Authentication expired. Run `rush-ai auth login` to re-authenticate.';\n case 403:\n return 'Permission denied. You may not have access to this resource.';\n case 404:\n return 'Resource not found.';\n case 429:\n return 'Rate limited. The server is busy, please try again later.';\n case 502:\n case 503:\n case 504:\n return 'Service temporarily unavailable. Please try again in a moment.';\n default:\n return `Request failed with status ${status}.`;\n }\n}\n\nexport class ApiError extends RushError {\n public status: number;\n public retryAfter?: string;\n\n constructor(\n message: string,\n status: number,\n body?: string,\n retryAfter?: string\n ) {\n // Try to extract server error message from body\n let serverMessage: string | undefined;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n if (parsed.error && typeof parsed.error === 'string') {\n serverMessage = parsed.error;\n }\n } catch {\n // Not JSON\n }\n }\n\n super(\n friendlyMessage(status, serverMessage),\n { status, body },\n 'API_ERROR'\n );\n this.name = 'ApiError';\n this.status = status;\n this.retryAfter = retryAfter;\n }\n}\n\nexport function isRushError(error: unknown): error is RushError {\n return error instanceof RushError;\n}\n","let _verbose = false;\nlet _debug = false;\n\nexport function setVerbosity(verbose: boolean, debug: boolean): void {\n _debug = debug;\n _verbose = verbose || debug;\n}\n\nexport const isVerbose = (): boolean => _verbose;\nexport const isDebug = (): boolean => _debug;\n","import { getAuthToken, getCasConfig } from './auth.js';\nimport { getAuthConfig, getGlobalConfig, setAuthConfig } from './config.js';\n\nconst VERIFY_PATH = '/api/skill-auth/me';\nconst REFRESH_SKEW_MS = 60_000;\nconst AUTH_REQUEST_TIMEOUT_MS = 8_000;\n\ninterface RefreshTokenResponse {\n access_token: string;\n expires_in?: number;\n refresh_token?: string;\n}\n\nexport interface AuthVerificationResult {\n valid: boolean;\n status: number | null;\n message?: string;\n}\n\nexport interface RefreshOptions {\n force?: boolean;\n refreshWindowMs?: number;\n}\n\nfunction getApiBaseUrl(): string {\n return process.env.RUSH_API_URL ?? getGlobalConfig().api;\n}\n\nfunction buildBearerHeaders(token: string): Record<string, string> {\n return {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': 'rush-ai/0.2.0',\n };\n}\n\nfunction shouldRefreshToken(options?: RefreshOptions): boolean {\n const auth = getAuthConfig();\n // Platform tokens don't support refresh; only CAS tokens do\n if (!auth.token || auth.method !== 'cas' || !auth.refreshToken) {\n return false;\n }\n if (options?.force) {\n return true;\n }\n if (!auth.expiresAt) {\n return false;\n }\n const refreshWindowMs = options?.refreshWindowMs ?? REFRESH_SKEW_MS;\n return Date.now() >= auth.expiresAt - refreshWindowMs;\n}\n\nexport async function refreshCasAccessToken(\n options?: RefreshOptions\n): Promise<boolean> {\n if (process.env.RUSH_API_KEY || !shouldRefreshToken(options)) {\n return false;\n }\n\n const auth = getAuthConfig();\n if (!auth.refreshToken) {\n return false;\n }\n\n const cas = getCasConfig();\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: auth.refreshToken,\n client_id: cas.clientId,\n }).toString();\n\n try {\n const response = await fetch(cas.tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body,\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n\n if (!response.ok) {\n return false;\n }\n\n const tokenData = (await response.json()) as RefreshTokenResponse;\n if (!tokenData.access_token) {\n return false;\n }\n\n const expiresAt = tokenData.expires_in\n ? Date.now() + tokenData.expires_in * 1000\n : auth.expiresAt;\n\n setAuthConfig({\n token: tokenData.access_token,\n expiresAt,\n refreshToken: tokenData.refresh_token ?? auth.refreshToken,\n method: 'cas',\n });\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function verifyTokenOnline(\n token: string\n): Promise<AuthVerificationResult> {\n const url = `${getApiBaseUrl()}${VERIFY_PATH}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: buildBearerHeaders(token),\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n\n if (response.ok) {\n return { valid: true, status: response.status };\n }\n\n const message = await response.text().catch(() => undefined);\n return {\n valid: false,\n status: response.status,\n message: message || `Server rejected token (${response.status})`,\n };\n } catch (error) {\n return {\n valid: false,\n status: null,\n message: `Network error: ${error instanceof Error ? error.message : 'unknown'}`,\n };\n }\n}\n\nexport async function verifyCurrentAuthSession(): Promise<AuthVerificationResult> {\n const token = getAuthToken();\n if (!token) {\n return {\n valid: false,\n status: null,\n message: 'Not authenticated',\n };\n }\n\n await refreshCasAccessToken();\n\n let activeToken = getAuthToken();\n if (!activeToken) {\n return {\n valid: false,\n status: null,\n message: 'Not authenticated',\n };\n }\n\n const result = await verifyTokenOnline(activeToken);\n if (result.valid || result.status !== 401 || process.env.RUSH_API_KEY) {\n return result;\n }\n\n const refreshed = await refreshCasAccessToken({ force: true });\n if (!refreshed) {\n return result;\n }\n\n activeToken = getAuthToken();\n if (!activeToken) {\n return result;\n }\n return verifyTokenOnline(activeToken);\n}\n\nasync function revokeToken(\n revokeEndpoint: string,\n clientId: string,\n token: string,\n tokenTypeHint: 'access_token' | 'refresh_token'\n): Promise<boolean> {\n const body = new URLSearchParams({\n token,\n token_type_hint: tokenTypeHint,\n client_id: clientId,\n }).toString();\n\n try {\n const response = await fetch(revokeEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body,\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport async function revokeCurrentSession(): Promise<boolean> {\n if (process.env.RUSH_API_KEY) {\n return false;\n }\n\n const auth = getAuthConfig();\n\n if (auth.method === 'platform_token') {\n return revokePlatformToken();\n }\n\n if (auth.method !== 'cas') {\n return false;\n }\n\n const cas = getCasConfig();\n const candidates: Array<{\n token: string;\n hint: 'access_token' | 'refresh_token';\n }> = [];\n if (auth.refreshToken) {\n candidates.push({ token: auth.refreshToken, hint: 'refresh_token' });\n }\n if (auth.token) {\n candidates.push({ token: auth.token, hint: 'access_token' });\n }\n\n if (candidates.length === 0) {\n return false;\n }\n\n let anyRevoked = false;\n for (const candidate of candidates) {\n const revoked = await revokeToken(\n cas.revokeEndpoint,\n cas.clientId,\n candidate.token,\n candidate.hint\n );\n if (revoked) {\n anyRevoked = true;\n }\n }\n\n return anyRevoked;\n}\n\n/** @deprecated Use revokeCurrentSession instead */\nexport const revokeCurrentCasSession = revokeCurrentSession;\n\nasync function revokePlatformToken(): Promise<boolean> {\n const auth = getAuthConfig();\n if (!auth.tokenId || !auth.token) {\n return false;\n }\n\n const baseUrl = getApiBaseUrl();\n const url = `${baseUrl}/api/platform-tokens?id=${encodeURIComponent(auth.tokenId)}`;\n\n try {\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${auth.token}`,\n 'User-Agent': 'rush-ai/0.2.0',\n },\n signal: AbortSignal.timeout(AUTH_REQUEST_TIMEOUT_MS),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n","import { ApiError, RushError } from './errors.js';\n\nexport interface RetryOptions {\n /** Maximum number of retries (default: 3, total attempts = maxRetries + 1) */\n maxRetries?: number;\n /** Base delay in ms for exponential backoff (default: 1000) */\n baseDelay?: number;\n /** Maximum delay in ms (default: 30000) */\n maxDelay?: number;\n /** HTTP status codes eligible for retry (default: [429, 502, 503, 504]) */\n retryableStatuses?: number[];\n /** AbortSignal to cancel retries */\n signal?: AbortSignal;\n /** Called before each retry with attempt number (1-based) and delay in ms */\n onRetry?: (attempt: number, delayMs: number, status?: number) => void;\n}\n\n/**\n * Parse the Retry-After HTTP header value.\n * Supports both seconds (integer) and HTTP-date formats.\n * Returns delay in milliseconds, or null if unparseable.\n */\nexport function parseRetryAfter(value: string): number | null {\n // Try as integer seconds first\n const seconds = Number(value);\n if (!Number.isNaN(seconds) && seconds >= 0) {\n return seconds * 1000;\n }\n\n // Try as HTTP-date\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) {\n const delayMs = date.getTime() - Date.now();\n return delayMs > 0 ? delayMs : 0;\n }\n\n return null;\n}\n\n/**\n * Calculate delay with exponential backoff and jitter.\n */\nfunction calculateDelay(\n attempt: number,\n baseDelay: number,\n maxDelay: number\n): number {\n const exponential = baseDelay * 2 ** attempt;\n const jitter = Math.random() * baseDelay * 0.5;\n return Math.min(exponential + jitter, maxDelay);\n}\n\nfunction isRetryableError(\n error: unknown,\n retryableStatuses: number[]\n): boolean {\n // Network errors (fetch failures) are retryable\n if (error instanceof RushError && error.code === 'NETWORK_ERROR') {\n return true;\n }\n\n // API errors with retryable status codes\n if (error instanceof ApiError && retryableStatuses.includes(error.status)) {\n return true;\n }\n\n return false;\n}\n\nfunction getRetryAfterFromError(error: unknown): number | null {\n if (error instanceof ApiError && error.status === 429) {\n // Use Retry-After HTTP header (propagated via ApiError.retryAfter)\n if (error.retryAfter) {\n return parseRetryAfter(error.retryAfter);\n }\n }\n return null;\n}\n\n/**\n * Wrap an async function with retry logic using exponential backoff.\n *\n * Important: This should only be used for idempotent operations.\n * The caller (RushClient) is responsible for only wrapping GET/HEAD/DELETE.\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const {\n maxRetries = 3,\n baseDelay = 1000,\n maxDelay = 30_000,\n retryableStatuses = [429, 502, 503, 504],\n signal,\n onRetry,\n } = options;\n\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n // Check abort before each attempt\n if (signal?.aborted) {\n throw lastError ?? new RushError('Request aborted', {}, 'ABORT_ERROR');\n }\n\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Don't retry if this is the last attempt\n if (attempt >= maxRetries) {\n throw error;\n }\n\n // Don't retry non-retryable errors\n if (!isRetryableError(error, retryableStatuses)) {\n throw error;\n }\n\n // Check abort before waiting\n if (signal?.aborted) {\n throw error;\n }\n\n // Calculate delay: use Retry-After if available (for 429), otherwise backoff\n let delayMs: number;\n const retryAfterMs = getRetryAfterFromError(error);\n if (retryAfterMs !== null) {\n // Cap Retry-After at 120 seconds\n delayMs = Math.min(retryAfterMs, 120_000);\n } else {\n delayMs = calculateDelay(attempt, baseDelay, maxDelay);\n }\n\n const status = error instanceof ApiError ? error.status : undefined;\n onRetry?.(attempt + 1, delayMs, status);\n\n // Wait with abort support\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, delayMs);\n if (signal) {\n const onAbort = () => {\n clearTimeout(timer);\n reject(lastError);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n // Clean up listener after timer fires\n const origResolve = resolve;\n setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n origResolve();\n }, delayMs);\n }\n });\n }\n }\n\n // Should never reach here, but TypeScript needs it\n throw lastError;\n}\n","import { output } from '../output/logger.js';\nimport { VERSION } from '../version.js';\nimport { getAuthToken } from './auth.js';\nimport { refreshCasAccessToken } from './auth-session.js';\nimport { getAuthConfig, getGlobalConfig } from './config.js';\nimport { ApiError, RushError } from './errors.js';\nimport { withRetry } from './retry.js';\nimport { isDebug, isVerbose } from './verbosity.js';\n\nconst SENSITIVE_HEADERS = [\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n];\n\nfunction maskSensitiveHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => {\n result[key] = SENSITIVE_HEADERS.includes(key.toLowerCase())\n ? '[REDACTED]'\n : value;\n });\n return result;\n}\n\nexport interface FetchOptions extends RequestInit {\n json?: boolean;\n}\n\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n status: number;\n data: T;\n}\n\nexport interface ApiErrorBody {\n error: string;\n code: string;\n retryable: boolean;\n}\n\nexport class RushClient {\n private baseUrl: string;\n\n constructor() {\n const config = getGlobalConfig();\n const raw = process.env.RUSH_API_URL ?? config.api;\n this.baseUrl = raw.replace(/\\/+$/, '');\n }\n\n private async getHeaders(): Promise<Record<string, string>> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'User-Agent': `rush-ai/${VERSION}`,\n };\n\n if (!process.env.RUSH_API_KEY) {\n await refreshCasAccessToken();\n }\n\n const token = getAuthToken();\n if (token) {\n // Both CAS token and service account API key (rush_sk_*) use Bearer.\n // Backend distinguishes by the rush_sk_ prefix.\n headers.Authorization = `Bearer ${token}`;\n }\n\n // Test mode: skip CAS auth in non-production environments\n if (process.env.RUSH_TEST_MODE === 'integration-test') {\n headers['X-Test-Mode'] = 'integration-test';\n }\n\n return headers;\n }\n\n /**\n * Merge default headers with per-request overrides. A `null` override value\n * drops the default entirely — used by multipart POSTs that need fetch to\n * synthesize its own Content-Type with a boundary. An empty string stays as\n * an empty-value header so callers can still send one intentionally.\n */\n private mergeHeaders(\n base: Record<string, string>,\n overrides: Record<string, string | null>\n ): Record<string, string> {\n const merged: Record<string, string> = { ...base };\n for (const [key, value] of Object.entries(overrides)) {\n if (value === null) {\n delete merged[key];\n } else {\n merged[key] = value;\n }\n }\n return merged;\n }\n\n private async performRequest(\n url: string,\n options: RequestInit,\n retryOnUnauthorized = true\n ): Promise<Response> {\n // Override headers may use `null` as a sentinel to drop a default\n // (see mergeHeaders). The public fetch signature doesn't know about this,\n // so we cast narrowly here.\n const requestHeaders =\n (options.headers as Record<string, string | null>) ?? {};\n const headers = await this.getHeaders();\n\n try {\n const response = await fetch(url, {\n ...options,\n headers: this.mergeHeaders(headers, requestHeaders),\n });\n\n if (\n response.status === 401 &&\n retryOnUnauthorized &&\n !process.env.RUSH_API_KEY\n ) {\n const auth = getAuthConfig();\n const canRefresh = auth.method === 'cas' && Boolean(auth.refreshToken);\n if (canRefresh && (await refreshCasAccessToken({ force: true }))) {\n const retryHeaders = await this.getHeaders();\n return await fetch(url, {\n ...options,\n headers: this.mergeHeaders(retryHeaders, requestHeaders),\n });\n }\n }\n\n return response;\n } catch (err) {\n throw new RushError(\n `Network error: ${err instanceof Error ? err.message : 'Failed to connect'}`,\n { url },\n 'NETWORK_ERROR'\n );\n }\n }\n\n /** Idempotent HTTP methods eligible for automatic retry */\n private static readonly RETRYABLE_METHODS = ['GET', 'HEAD', 'DELETE'];\n\n /**\n * Internal fetch with response parsing and error handling (no retry).\n */\n private async _doFetch<T = unknown>(\n path: string,\n options: FetchOptions = {}\n ): Promise<ApiResponse<T>> {\n const { json = true, ...fetchOptions } = options;\n const url = `${this.baseUrl}${path}`;\n const method = (fetchOptions.method ?? 'GET').toUpperCase();\n const startTime = Date.now();\n\n if (isVerbose()) {\n output.dim(`→ ${method} ${url}`);\n }\n\n const response = await this.performRequest(url, fetchOptions);\n\n if (isVerbose()) {\n output.dim(\n `← ${response.status} ${response.statusText} (${Date.now() - startTime}ms)`\n );\n }\n\n if (isDebug()) {\n output.dim(\n ` Response headers: ${JSON.stringify(maskSensitiveHeaders(response.headers))}`\n );\n }\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => 'Unknown error');\n const retryAfter = response.headers.get('retry-after') ?? undefined;\n\n throw new ApiError(\n `API request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorBody,\n retryAfter\n );\n }\n\n const data = json\n ? ((await response.json()) as T)\n : ((await response.text()) as T);\n\n return {\n ok: true,\n status: response.status,\n data,\n };\n }\n\n /**\n * Fetch with response parsing, error handling, and automatic retry\n * for idempotent methods (GET, HEAD, DELETE).\n */\n async fetch<T = unknown>(\n path: string,\n options: FetchOptions = {}\n ): Promise<ApiResponse<T>> {\n const method = (options.method ?? 'GET').toUpperCase();\n const isRetryable = RushClient.RETRYABLE_METHODS.includes(method);\n\n if (!isRetryable) {\n return this._doFetch<T>(path, options);\n }\n\n return withRetry(() => this._doFetch<T>(path, options), {\n signal: options.signal ?? undefined,\n onRetry: (attempt, delayMs, status) => {\n const statusInfo = status ? ` (${status})` : '';\n console.error(\n `\\u27F3 Retrying ${method} ${path}${statusInfo} (attempt ${attempt}) in ${(delayMs / 1000).toFixed(1)}s...`\n );\n },\n });\n }\n\n /**\n * Raw fetch for streaming (SSE) responses.\n * Returns the raw Response object.\n */\n async fetchRaw(path: string, options: RequestInit = {}): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n const response = await this.performRequest(url, options);\n\n if (!response.ok) {\n const errorBody = await response.text().catch(() => 'Unknown error');\n throw new ApiError(\n `API request failed: ${response.status} ${response.statusText}`,\n response.status,\n errorBody\n );\n }\n\n return response;\n }\n\n async get<T = unknown>(path: string): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, { method: 'GET' });\n }\n\n async post<T = unknown>(\n path: string,\n body?: unknown\n ): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, {\n method: 'POST',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /**\n * POST multipart/form-data. The default `Content-Type: application/json`\n * must be removed so fetch can set its own multipart boundary — passing\n * `null` as the header value tells mergeHeaders to drop the key.\n */\n async postFormData<T = unknown>(\n path: string,\n formData: FormData\n ): Promise<ApiResponse<T>> {\n return this._doFetch<T>(path, {\n method: 'POST',\n body: formData,\n // Cast: RequestInit.headers doesn't include null; mergeHeaders handles it.\n headers: { 'Content-Type': null } as unknown as HeadersInit,\n });\n }\n\n async put<T = unknown>(\n path: string,\n body?: unknown\n ): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, {\n method: 'PUT',\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n async delete<T = unknown>(path: string): Promise<ApiResponse<T>> {\n return this.fetch<T>(path, { method: 'DELETE' });\n }\n}\n\nexport function createClient(): RushClient {\n return new RushClient();\n}\n"],"mappings":"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","names":["resolve"]}
|