@dosu/cli 0.49.0 → 0.49.2
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/bin/dosu.js +557 -276
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -2098,6 +2098,35 @@ var init_commander = __esm(() => {
|
|
|
2098
2098
|
program = new Command;
|
|
2099
2099
|
});
|
|
2100
2100
|
|
|
2101
|
+
// src/auth/session-errors.ts
|
|
2102
|
+
var SESSION_EXPIRED_CODE = "SESSION_EXPIRED", SESSION_PERSISTENCE_ERROR_CODE = "SESSION_PERSISTENCE_ERROR", SESSION_REFRESH_ERROR_CODE = "SESSION_REFRESH_ERROR", SessionExpiredError, SessionPersistenceError, SessionRefreshError;
|
|
2103
|
+
var init_session_errors = __esm(() => {
|
|
2104
|
+
SessionExpiredError = class SessionExpiredError extends Error {
|
|
2105
|
+
code = SESSION_EXPIRED_CODE;
|
|
2106
|
+
constructor(options) {
|
|
2107
|
+
super("Your Dosu session has expired. Run 'dosu login' to re-authenticate.", options);
|
|
2108
|
+
this.name = "SessionExpiredError";
|
|
2109
|
+
}
|
|
2110
|
+
};
|
|
2111
|
+
SessionPersistenceError = class SessionPersistenceError extends Error {
|
|
2112
|
+
code = SESSION_PERSISTENCE_ERROR_CODE;
|
|
2113
|
+
constructor(options) {
|
|
2114
|
+
super("Could not safely save refreshed Dosu credentials. Ensure the Dosu config directory is writable, then retry.", options);
|
|
2115
|
+
this.name = "SessionPersistenceError";
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2118
|
+
SessionRefreshError = class SessionRefreshError extends Error {
|
|
2119
|
+
code = SESSION_REFRESH_ERROR_CODE;
|
|
2120
|
+
status;
|
|
2121
|
+
constructor(options = {}) {
|
|
2122
|
+
const message = options.status ? `Could not refresh the Dosu session (authentication server returned status ${options.status}). Retry the command.` : "Could not reach the authentication server to refresh the Dosu session. Retry the command.";
|
|
2123
|
+
super(message, options);
|
|
2124
|
+
this.name = "SessionRefreshError";
|
|
2125
|
+
this.status = options.status;
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
});
|
|
2129
|
+
|
|
2101
2130
|
// src/config/identity.ts
|
|
2102
2131
|
function getAccessTokenClaim(accessToken, claim) {
|
|
2103
2132
|
try {
|
|
@@ -2330,6 +2359,160 @@ var init_config = __esm(() => {
|
|
|
2330
2359
|
init_config_v1_migration();
|
|
2331
2360
|
});
|
|
2332
2361
|
|
|
2362
|
+
// src/config/config-lock.ts
|
|
2363
|
+
import { randomUUID } from "node:crypto";
|
|
2364
|
+
import {
|
|
2365
|
+
closeSync,
|
|
2366
|
+
existsSync as existsSync2,
|
|
2367
|
+
linkSync,
|
|
2368
|
+
mkdirSync as mkdirSync2,
|
|
2369
|
+
openSync,
|
|
2370
|
+
readFileSync as readFileSync2,
|
|
2371
|
+
statSync,
|
|
2372
|
+
unlinkSync,
|
|
2373
|
+
writeFileSync as writeFileSync2
|
|
2374
|
+
} from "node:fs";
|
|
2375
|
+
import { join as join2 } from "node:path";
|
|
2376
|
+
async function withConfigRefreshLock(task, options = {}) {
|
|
2377
|
+
const release = await acquireConfigRefreshLock(options);
|
|
2378
|
+
try {
|
|
2379
|
+
return await task();
|
|
2380
|
+
} finally {
|
|
2381
|
+
release();
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
async function acquireConfigRefreshLock(options) {
|
|
2385
|
+
const now = options.now ?? Date.now;
|
|
2386
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
2387
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
2388
|
+
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
2389
|
+
const staleAgeMs = options.staleAgeMs ?? DEFAULT_STALE_AGE_MS;
|
|
2390
|
+
const isProcessAlive = options.isProcessAlive ?? defaultIsProcessAlive;
|
|
2391
|
+
const ownerId = options.ownerId ?? randomUUID();
|
|
2392
|
+
const configDir = getConfigDir();
|
|
2393
|
+
const lockPath = join2(configDir, CONFIG_REFRESH_LOCK_FILENAME);
|
|
2394
|
+
try {
|
|
2395
|
+
if (!existsSync2(configDir))
|
|
2396
|
+
mkdirSync2(configDir, { recursive: true, mode: 448 });
|
|
2397
|
+
} catch (cause) {
|
|
2398
|
+
throw new SessionPersistenceError({ cause });
|
|
2399
|
+
}
|
|
2400
|
+
const deadline = now() + Math.max(0, timeoutMs);
|
|
2401
|
+
while (true) {
|
|
2402
|
+
try {
|
|
2403
|
+
createLockFile(lockPath, { owner_id: ownerId, pid: process.pid, created_at: now() });
|
|
2404
|
+
return () => releaseOwnedLock(lockPath, ownerId);
|
|
2405
|
+
} catch (cause) {
|
|
2406
|
+
if (!hasErrorCode(cause, "EEXIST")) {
|
|
2407
|
+
throw new SessionPersistenceError({ cause });
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
if (claimAndRemoveStaleLock(lockPath, staleAgeMs, now(), isProcessAlive, ownerId)) {
|
|
2411
|
+
continue;
|
|
2412
|
+
}
|
|
2413
|
+
if (now() >= deadline) {
|
|
2414
|
+
throw new SessionPersistenceError({
|
|
2415
|
+
cause: new Error("Timed out waiting for another Dosu session refresh.")
|
|
2416
|
+
});
|
|
2417
|
+
}
|
|
2418
|
+
await sleep(Math.max(1, retryDelayMs));
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
function createLockFile(lockPath, metadata) {
|
|
2422
|
+
const fd = openSync(lockPath, "wx", 384);
|
|
2423
|
+
try {
|
|
2424
|
+
writeFileSync2(fd, JSON.stringify(metadata));
|
|
2425
|
+
} catch (cause) {
|
|
2426
|
+
try {
|
|
2427
|
+
closeSync(fd);
|
|
2428
|
+
} catch {}
|
|
2429
|
+
try {
|
|
2430
|
+
unlinkSync(lockPath);
|
|
2431
|
+
} catch {}
|
|
2432
|
+
throw cause;
|
|
2433
|
+
}
|
|
2434
|
+
try {
|
|
2435
|
+
closeSync(fd);
|
|
2436
|
+
} catch (cause) {
|
|
2437
|
+
try {
|
|
2438
|
+
unlinkSync(lockPath);
|
|
2439
|
+
} catch {}
|
|
2440
|
+
throw cause;
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
function releaseOwnedLock(lockPath, ownerId) {
|
|
2444
|
+
try {
|
|
2445
|
+
if (readLockMetadata(lockPath)?.owner_id === ownerId)
|
|
2446
|
+
unlinkSync(lockPath);
|
|
2447
|
+
} catch {}
|
|
2448
|
+
}
|
|
2449
|
+
function claimAndRemoveStaleLock(lockPath, staleAgeMs, now, isProcessAlive, ownerId) {
|
|
2450
|
+
const claimPath = `${lockPath}.stale.${process.pid}.${ownerId}`;
|
|
2451
|
+
try {
|
|
2452
|
+
linkSync(lockPath, claimPath);
|
|
2453
|
+
const metadata = readLockMetadata(claimPath);
|
|
2454
|
+
let stale = false;
|
|
2455
|
+
if (metadata && Number.isInteger(metadata.pid) && metadata.pid > 0) {
|
|
2456
|
+
stale = !isProcessAlive(metadata.pid);
|
|
2457
|
+
} else {
|
|
2458
|
+
stale = now - statSync(claimPath).mtimeMs >= staleAgeMs;
|
|
2459
|
+
}
|
|
2460
|
+
if (!stale)
|
|
2461
|
+
return false;
|
|
2462
|
+
const current = statSync(lockPath);
|
|
2463
|
+
const claimed = statSync(claimPath);
|
|
2464
|
+
if (current.dev !== claimed.dev || current.ino !== claimed.ino)
|
|
2465
|
+
return false;
|
|
2466
|
+
unlinkSync(lockPath);
|
|
2467
|
+
return true;
|
|
2468
|
+
} catch (cause) {
|
|
2469
|
+
return hasErrorCode(cause, "ENOENT");
|
|
2470
|
+
} finally {
|
|
2471
|
+
try {
|
|
2472
|
+
unlinkSync(claimPath);
|
|
2473
|
+
} catch {}
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
function readLockMetadata(lockPath) {
|
|
2477
|
+
try {
|
|
2478
|
+
const parsed = JSON.parse(readFileSync2(lockPath, "utf8"));
|
|
2479
|
+
if (!isRecord3(parsed))
|
|
2480
|
+
return;
|
|
2481
|
+
if (typeof parsed.owner_id !== "string" || typeof parsed.pid !== "number" || typeof parsed.created_at !== "number") {
|
|
2482
|
+
return;
|
|
2483
|
+
}
|
|
2484
|
+
return {
|
|
2485
|
+
owner_id: parsed.owner_id,
|
|
2486
|
+
pid: parsed.pid,
|
|
2487
|
+
created_at: parsed.created_at
|
|
2488
|
+
};
|
|
2489
|
+
} catch {
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
function defaultIsProcessAlive(pid) {
|
|
2494
|
+
try {
|
|
2495
|
+
process.kill(pid, 0);
|
|
2496
|
+
return true;
|
|
2497
|
+
} catch (cause) {
|
|
2498
|
+
return !hasErrorCode(cause, "ESRCH");
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
function defaultSleep(delayMs) {
|
|
2502
|
+
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2503
|
+
}
|
|
2504
|
+
function hasErrorCode(value, code) {
|
|
2505
|
+
return isRecord3(value) && value.code === code;
|
|
2506
|
+
}
|
|
2507
|
+
function isRecord3(value) {
|
|
2508
|
+
return typeof value === "object" && value !== null;
|
|
2509
|
+
}
|
|
2510
|
+
var CONFIG_REFRESH_LOCK_FILENAME = "session-refresh.lock", DEFAULT_TIMEOUT_MS = 5000, DEFAULT_RETRY_DELAY_MS = 25, DEFAULT_STALE_AGE_MS = 30000;
|
|
2511
|
+
var init_config_lock = __esm(() => {
|
|
2512
|
+
init_session_errors();
|
|
2513
|
+
init_config();
|
|
2514
|
+
});
|
|
2515
|
+
|
|
2333
2516
|
// src/config/constants.ts
|
|
2334
2517
|
function getWebAppURL() {
|
|
2335
2518
|
return process.env.DOSU_WEB_APP_URL_OVERRIDE ?? "https://app.dosu.dev" ?? "";
|
|
@@ -2359,12 +2542,12 @@ class Client {
|
|
|
2359
2542
|
if (isTokenExpired(this.config)) {
|
|
2360
2543
|
await this.refreshToken();
|
|
2361
2544
|
}
|
|
2545
|
+
const requestAccessToken = this.config.active_account?.session.access_token;
|
|
2362
2546
|
let resp = await this.doRequestOnce(method, path2, body);
|
|
2363
2547
|
if (resp.status === 401 || resp.status === 403) {
|
|
2364
|
-
|
|
2548
|
+
const currentAccessToken = this.config.active_account?.session.access_token;
|
|
2549
|
+
if (!currentAccessToken || currentAccessToken === requestAccessToken) {
|
|
2365
2550
|
await this.refreshToken();
|
|
2366
|
-
} catch {
|
|
2367
|
-
throw new SessionExpiredError;
|
|
2368
2551
|
}
|
|
2369
2552
|
resp = await this.doRequestOnce(method, path2, body);
|
|
2370
2553
|
}
|
|
@@ -2405,36 +2588,34 @@ class Client {
|
|
|
2405
2588
|
return this.doRequest("DELETE", path2);
|
|
2406
2589
|
}
|
|
2407
2590
|
async refreshToken() {
|
|
2408
|
-
this.
|
|
2409
|
-
if (!
|
|
2410
|
-
throw new
|
|
2411
|
-
}
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2591
|
+
const refreshTokenAtStart = this.config.active_account?.session.refresh_token;
|
|
2592
|
+
if (!refreshTokenAtStart) {
|
|
2593
|
+
throw new SessionExpiredError;
|
|
2594
|
+
}
|
|
2595
|
+
await withConfigRefreshLock(async () => {
|
|
2596
|
+
const disk = loadConfig();
|
|
2597
|
+
this.assertSameActiveAccount(disk);
|
|
2598
|
+
const diskRefreshToken = disk.active_account?.session.refresh_token;
|
|
2599
|
+
if (!diskRefreshToken)
|
|
2600
|
+
throw new SessionExpiredError;
|
|
2601
|
+
const diskHasNewerSession = diskRefreshToken !== refreshTokenAtStart;
|
|
2602
|
+
if (diskHasNewerSession && !isTokenExpired(disk)) {
|
|
2603
|
+
this.adoptConfig(disk);
|
|
2604
|
+
return;
|
|
2417
2605
|
}
|
|
2418
|
-
await this.refreshTokenOnce();
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
if (!diskSession?.refresh_token || !memorySession || diskSession.refresh_token === memorySession.refresh_token) {
|
|
2427
|
-
return false;
|
|
2428
|
-
}
|
|
2429
|
-
memorySession.access_token = diskSession.access_token;
|
|
2430
|
-
memorySession.refresh_token = diskSession.refresh_token;
|
|
2431
|
-
memorySession.expires_at = diskSession.expires_at;
|
|
2432
|
-
return true;
|
|
2606
|
+
const candidate = await this.refreshTokenOnce(disk);
|
|
2607
|
+
try {
|
|
2608
|
+
saveConfig(candidate);
|
|
2609
|
+
} catch (cause) {
|
|
2610
|
+
throw new SessionPersistenceError({ cause });
|
|
2611
|
+
}
|
|
2612
|
+
this.adoptConfig(candidate);
|
|
2613
|
+
});
|
|
2433
2614
|
}
|
|
2434
|
-
async refreshTokenOnce() {
|
|
2435
|
-
const session =
|
|
2615
|
+
async refreshTokenOnce(source) {
|
|
2616
|
+
const session = source.active_account?.session;
|
|
2436
2617
|
if (!session?.refresh_token)
|
|
2437
|
-
throw new
|
|
2618
|
+
throw new SessionExpiredError;
|
|
2438
2619
|
const supabaseURL = getSupabaseURL();
|
|
2439
2620
|
const oauthClientID = getAccessTokenOAuthClientID(session.access_token);
|
|
2440
2621
|
const endpoint = oauthClientID ? `${supabaseURL}/auth/v1/oauth/token` : `${supabaseURL}/auth/v1/token?grant_type=refresh_token`;
|
|
@@ -2444,20 +2625,54 @@ class Client {
|
|
|
2444
2625
|
refresh_token: session.refresh_token,
|
|
2445
2626
|
client_id: oauthClientID
|
|
2446
2627
|
}).toString() : JSON.stringify({ refresh_token: session.refresh_token });
|
|
2447
|
-
const
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2628
|
+
const controller = new AbortController;
|
|
2629
|
+
const timeout = setTimeout(() => controller.abort(), REFRESH_REQUEST_TIMEOUT_MS);
|
|
2630
|
+
let resp;
|
|
2631
|
+
try {
|
|
2632
|
+
resp = await fetch(endpoint, {
|
|
2633
|
+
method: "POST",
|
|
2634
|
+
headers,
|
|
2635
|
+
body,
|
|
2636
|
+
signal: controller.signal
|
|
2637
|
+
});
|
|
2638
|
+
} catch (cause) {
|
|
2639
|
+
clearTimeout(timeout);
|
|
2640
|
+
throw new SessionRefreshError({ cause });
|
|
2454
2641
|
}
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2642
|
+
let data;
|
|
2643
|
+
try {
|
|
2644
|
+
if (resp.status !== 200) {
|
|
2645
|
+
const errorCode = await readAuthErrorCode(resp);
|
|
2646
|
+
if (REAUTHENTICATION_ERROR_CODES.has(errorCode ?? "") || !oauthClientID && errorCode === "validation_failed") {
|
|
2647
|
+
throw new SessionExpiredError;
|
|
2648
|
+
}
|
|
2649
|
+
throw new SessionRefreshError({ status: resp.status });
|
|
2650
|
+
}
|
|
2651
|
+
data = await readRefreshResponse(resp);
|
|
2652
|
+
} finally {
|
|
2653
|
+
clearTimeout(timeout);
|
|
2654
|
+
}
|
|
2655
|
+
const latest = loadConfig();
|
|
2656
|
+
this.assertSameActiveAccount(latest);
|
|
2657
|
+
const latestSession = latest.active_account?.session;
|
|
2658
|
+
if (!latestSession?.refresh_token)
|
|
2659
|
+
throw new SessionExpiredError;
|
|
2660
|
+
if (latestSession.refresh_token !== session.refresh_token) {
|
|
2661
|
+
return latest;
|
|
2662
|
+
}
|
|
2663
|
+
return configWithSession(latest, {
|
|
2664
|
+
access_token: data.access_token,
|
|
2665
|
+
refresh_token: data.refresh_token,
|
|
2666
|
+
expires_at: Math.floor(Date.now() / 1000) + data.expires_in
|
|
2667
|
+
});
|
|
2668
|
+
}
|
|
2669
|
+
adoptConfig(source) {
|
|
2670
|
+
this.config.mode = source.mode;
|
|
2671
|
+
this.config.active_account = source.active_account ? {
|
|
2672
|
+
...source.active_account,
|
|
2673
|
+
session: { ...source.active_account.session },
|
|
2674
|
+
target: source.active_account.target ? { ...source.active_account.target } : undefined
|
|
2675
|
+
} : undefined;
|
|
2461
2676
|
}
|
|
2462
2677
|
assertSameActiveAccount(disk) {
|
|
2463
2678
|
const memoryUserID = getConfigUserID(this.config);
|
|
@@ -2514,6 +2729,49 @@ class Client {
|
|
|
2514
2729
|
return resp.json();
|
|
2515
2730
|
}
|
|
2516
2731
|
}
|
|
2732
|
+
async function readAuthErrorCode(resp) {
|
|
2733
|
+
try {
|
|
2734
|
+
const data = await resp.json();
|
|
2735
|
+
if (!isRecord4(data))
|
|
2736
|
+
return;
|
|
2737
|
+
const code = typeof data.error_code === "string" ? data.error_code : data.error;
|
|
2738
|
+
return typeof code === "string" ? code : undefined;
|
|
2739
|
+
} catch {
|
|
2740
|
+
return;
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
async function readRefreshResponse(resp) {
|
|
2744
|
+
let data;
|
|
2745
|
+
try {
|
|
2746
|
+
data = await resp.json();
|
|
2747
|
+
} catch (cause) {
|
|
2748
|
+
throw new SessionRefreshError({ cause, status: resp.status });
|
|
2749
|
+
}
|
|
2750
|
+
if (!isRecord4(data) || typeof data.access_token !== "string" || typeof data.refresh_token !== "string" || typeof data.expires_in !== "number" || !Number.isFinite(data.expires_in)) {
|
|
2751
|
+
throw new SessionRefreshError({ status: resp.status });
|
|
2752
|
+
}
|
|
2753
|
+
return {
|
|
2754
|
+
access_token: data.access_token,
|
|
2755
|
+
refresh_token: data.refresh_token,
|
|
2756
|
+
expires_in: data.expires_in
|
|
2757
|
+
};
|
|
2758
|
+
}
|
|
2759
|
+
function configWithSession(source, session) {
|
|
2760
|
+
const account = source.active_account;
|
|
2761
|
+
if (!account)
|
|
2762
|
+
throw new SessionExpiredError;
|
|
2763
|
+
return {
|
|
2764
|
+
...source,
|
|
2765
|
+
active_account: {
|
|
2766
|
+
...account,
|
|
2767
|
+
session,
|
|
2768
|
+
target: account.target ? { ...account.target } : undefined
|
|
2769
|
+
}
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
function isRecord4(value) {
|
|
2773
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2774
|
+
}
|
|
2517
2775
|
async function readErrorBody(resp) {
|
|
2518
2776
|
try {
|
|
2519
2777
|
const text = await resp.text();
|
|
@@ -2522,15 +2780,18 @@ async function readErrorBody(resp) {
|
|
|
2522
2780
|
return "";
|
|
2523
2781
|
}
|
|
2524
2782
|
}
|
|
2525
|
-
var
|
|
2783
|
+
var REFRESH_REQUEST_TIMEOUT_MS = 1e4, REAUTHENTICATION_ERROR_CODES;
|
|
2526
2784
|
var init_client = __esm(() => {
|
|
2785
|
+
init_session_errors();
|
|
2527
2786
|
init_config();
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2787
|
+
init_config_lock();
|
|
2788
|
+
REAUTHENTICATION_ERROR_CODES = new Set([
|
|
2789
|
+
"invalid_grant",
|
|
2790
|
+
"refresh_token_already_used",
|
|
2791
|
+
"refresh_token_not_found",
|
|
2792
|
+
"session_expired",
|
|
2793
|
+
"session_not_found"
|
|
2794
|
+
]);
|
|
2534
2795
|
});
|
|
2535
2796
|
|
|
2536
2797
|
// node_modules/picocolors/picocolors.js
|
|
@@ -4739,18 +5000,18 @@ function isNpxInvocation(channel = INSTALL_CHANNEL, env = process.env) {
|
|
|
4739
5000
|
function getVersionString() {
|
|
4740
5001
|
return `v${VERSION}`;
|
|
4741
5002
|
}
|
|
4742
|
-
var VERSION = "0.49.
|
|
5003
|
+
var VERSION = "0.49.2", INSTALL_CHANNEL = "npm";
|
|
4743
5004
|
|
|
4744
5005
|
// src/debug/logger.ts
|
|
4745
5006
|
import {
|
|
4746
5007
|
appendFileSync,
|
|
4747
|
-
existsSync as
|
|
4748
|
-
mkdirSync as
|
|
4749
|
-
readFileSync as
|
|
4750
|
-
statSync,
|
|
4751
|
-
writeFileSync as
|
|
5008
|
+
existsSync as existsSync3,
|
|
5009
|
+
mkdirSync as mkdirSync3,
|
|
5010
|
+
readFileSync as readFileSync3,
|
|
5011
|
+
statSync as statSync2,
|
|
5012
|
+
writeFileSync as writeFileSync3
|
|
4752
5013
|
} from "node:fs";
|
|
4753
|
-
import { join as
|
|
5014
|
+
import { join as join3 } from "node:path";
|
|
4754
5015
|
function redactSecrets(message) {
|
|
4755
5016
|
let redacted = message;
|
|
4756
5017
|
for (const key of SECRET_QUERY_KEYS) {
|
|
@@ -4770,29 +5031,29 @@ function ensureInit() {
|
|
|
4770
5031
|
function resolveLogPath() {
|
|
4771
5032
|
if (!logFilePath) {
|
|
4772
5033
|
const dir = getConfigDir();
|
|
4773
|
-
if (!
|
|
4774
|
-
|
|
5034
|
+
if (!existsSync3(dir)) {
|
|
5035
|
+
mkdirSync3(dir, { recursive: true, mode: 448 });
|
|
4775
5036
|
}
|
|
4776
|
-
logFilePath =
|
|
5037
|
+
logFilePath = join3(dir, LOG_FILENAME);
|
|
4777
5038
|
}
|
|
4778
5039
|
return logFilePath;
|
|
4779
5040
|
}
|
|
4780
5041
|
function truncateIfNeeded() {
|
|
4781
5042
|
try {
|
|
4782
5043
|
const path2 = resolveLogPath();
|
|
4783
|
-
if (!
|
|
5044
|
+
if (!existsSync3(path2))
|
|
4784
5045
|
return;
|
|
4785
|
-
const stat =
|
|
5046
|
+
const stat = statSync2(path2);
|
|
4786
5047
|
if (stat.size <= MAX_LOG_SIZE)
|
|
4787
5048
|
return;
|
|
4788
|
-
const content =
|
|
5049
|
+
const content = readFileSync3(path2);
|
|
4789
5050
|
const start = content.length - TRUNCATE_KEEP;
|
|
4790
5051
|
let lineStart = start;
|
|
4791
5052
|
while (lineStart < content.length && content[lineStart] !== 10) {
|
|
4792
5053
|
lineStart++;
|
|
4793
5054
|
}
|
|
4794
5055
|
lineStart = Math.min(lineStart + 1, content.length);
|
|
4795
|
-
|
|
5056
|
+
writeFileSync3(path2, content.subarray(lineStart), { mode: 384 });
|
|
4796
5057
|
} catch {}
|
|
4797
5058
|
}
|
|
4798
5059
|
function writeSessionHeader() {
|
|
@@ -4873,7 +5134,7 @@ var init_logger = __esm(() => {
|
|
|
4873
5134
|
});
|
|
4874
5135
|
|
|
4875
5136
|
// src/client/contract.ts
|
|
4876
|
-
var CLI_CONTRACT_HASH = "
|
|
5137
|
+
var CLI_CONTRACT_HASH = "de4d34216f45";
|
|
4877
5138
|
|
|
4878
5139
|
// src/client/trpc.ts
|
|
4879
5140
|
var exports_trpc = {};
|
|
@@ -4897,11 +5158,7 @@ function createTypedClient(config) {
|
|
|
4897
5158
|
async headers() {
|
|
4898
5159
|
if (isTokenExpired(config)) {
|
|
4899
5160
|
logger.debug("trpc", "token expired, refreshing before request");
|
|
4900
|
-
|
|
4901
|
-
await httpClient.refreshToken();
|
|
4902
|
-
} catch {
|
|
4903
|
-
throw new Error("session expired. Run 'dosu login' to re-authenticate");
|
|
4904
|
-
}
|
|
5161
|
+
await httpClient.refreshToken();
|
|
4905
5162
|
}
|
|
4906
5163
|
return {
|
|
4907
5164
|
"Supabase-Access-Token": config.active_account?.session.access_token ?? "",
|
|
@@ -4909,13 +5166,13 @@ function createTypedClient(config) {
|
|
|
4909
5166
|
};
|
|
4910
5167
|
},
|
|
4911
5168
|
async fetch(url, options) {
|
|
5169
|
+
const requestAccessToken = new Headers(options?.headers).get("Supabase-Access-Token");
|
|
4912
5170
|
const res = await globalThis.fetch(url, options);
|
|
4913
5171
|
if (res.status === 401 || res.status === 403) {
|
|
4914
5172
|
logger.debug("trpc", "got 401/403, attempting token refresh and retry");
|
|
4915
|
-
|
|
5173
|
+
const currentAccessToken = config.active_account?.session.access_token;
|
|
5174
|
+
if (!currentAccessToken || requestAccessToken === null || currentAccessToken === requestAccessToken) {
|
|
4916
5175
|
await httpClient.refreshToken();
|
|
4917
|
-
} catch {
|
|
4918
|
-
return res;
|
|
4919
5176
|
}
|
|
4920
5177
|
return globalThis.fetch(url, {
|
|
4921
5178
|
...options,
|
|
@@ -8401,17 +8658,17 @@ var init_errors = __esm(() => {
|
|
|
8401
8658
|
});
|
|
8402
8659
|
|
|
8403
8660
|
// src/version/skill-update-check.ts
|
|
8404
|
-
import { existsSync as
|
|
8405
|
-
import { join as
|
|
8661
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
|
|
8662
|
+
import { join as join6 } from "node:path";
|
|
8406
8663
|
function getCachePath2() {
|
|
8407
|
-
return
|
|
8664
|
+
return join6(getConfigDir(), CACHE_FILENAME2);
|
|
8408
8665
|
}
|
|
8409
8666
|
function readSkillCache() {
|
|
8410
8667
|
try {
|
|
8411
8668
|
const path3 = getCachePath2();
|
|
8412
|
-
if (!
|
|
8669
|
+
if (!existsSync6(path3))
|
|
8413
8670
|
return null;
|
|
8414
|
-
const data = JSON.parse(
|
|
8671
|
+
const data = JSON.parse(readFileSync7(path3, "utf-8"));
|
|
8415
8672
|
if (typeof data.lastCheck === "number" && typeof data.latestSha === "string" && typeof data.installedSha === "string") {
|
|
8416
8673
|
return data;
|
|
8417
8674
|
}
|
|
@@ -8423,10 +8680,10 @@ function readSkillCache() {
|
|
|
8423
8680
|
function writeSkillCache(cache) {
|
|
8424
8681
|
try {
|
|
8425
8682
|
const dir = getConfigDir();
|
|
8426
|
-
if (!
|
|
8427
|
-
|
|
8683
|
+
if (!existsSync6(dir)) {
|
|
8684
|
+
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
8428
8685
|
}
|
|
8429
|
-
|
|
8686
|
+
writeFileSync6(getCachePath2(), JSON.stringify(cache), { mode: 384 });
|
|
8430
8687
|
} catch {}
|
|
8431
8688
|
}
|
|
8432
8689
|
function clearInstalledSha() {
|
|
@@ -8500,7 +8757,7 @@ var init_skill_update_check = __esm(() => {
|
|
|
8500
8757
|
// src/commands/skill.ts
|
|
8501
8758
|
import { exec as exec2, execSync as execSync2 } from "node:child_process";
|
|
8502
8759
|
import { homedir } from "node:os";
|
|
8503
|
-
import { join as
|
|
8760
|
+
import { join as join7 } from "node:path";
|
|
8504
8761
|
function skillAgentIDsForProviders(providerIDs) {
|
|
8505
8762
|
return [
|
|
8506
8763
|
...new Set(providerIDs.map((providerID) => SKILL_AGENT_BY_PROVIDER[providerID]).filter((agent) => Boolean(agent)))
|
|
@@ -8511,17 +8768,17 @@ function skillInstallTargetForProvider(providerID) {
|
|
|
8511
8768
|
if (!agentID)
|
|
8512
8769
|
return null;
|
|
8513
8770
|
if (agentID === "claude-code") {
|
|
8514
|
-
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() ||
|
|
8515
|
-
return { path:
|
|
8771
|
+
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim() || join7(homedir(), ".claude");
|
|
8772
|
+
return { path: join7(claudeConfigDir, "skills", SKILL_NAME), symlink: true };
|
|
8516
8773
|
}
|
|
8517
8774
|
if (agentID === "windsurf") {
|
|
8518
8775
|
return {
|
|
8519
|
-
path:
|
|
8776
|
+
path: join7(homedir(), ".codeium", "windsurf", "skills", SKILL_NAME),
|
|
8520
8777
|
symlink: true
|
|
8521
8778
|
};
|
|
8522
8779
|
}
|
|
8523
8780
|
return {
|
|
8524
|
-
path:
|
|
8781
|
+
path: join7(homedir(), ".agents", "skills", SKILL_NAME),
|
|
8525
8782
|
symlink: false
|
|
8526
8783
|
};
|
|
8527
8784
|
}
|
|
@@ -8901,7 +9158,7 @@ var require_cjs = __commonJS((exports) => {
|
|
|
8901
9158
|
var require_lib = __commonJS((exports, module) => {
|
|
8902
9159
|
var __filename = "/home/runner/work/dosu-cli/dosu-cli/node_modules/write-file-atomic/lib/index.js";
|
|
8903
9160
|
module.exports = writeFile;
|
|
8904
|
-
module.exports.sync =
|
|
9161
|
+
module.exports.sync = writeFileSync7;
|
|
8905
9162
|
module.exports._getTmpname = getTmpname;
|
|
8906
9163
|
module.exports._cleanupOnExit = cleanupOnExit;
|
|
8907
9164
|
var fs7 = __require("fs");
|
|
@@ -9034,7 +9291,7 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
9034
9291
|
}
|
|
9035
9292
|
return promise;
|
|
9036
9293
|
}
|
|
9037
|
-
function
|
|
9294
|
+
function writeFileSync7(filename, data, options) {
|
|
9038
9295
|
if (typeof options === "string") {
|
|
9039
9296
|
options = { encoding: options };
|
|
9040
9297
|
} else if (!options) {
|
|
@@ -9110,7 +9367,7 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
9110
9367
|
});
|
|
9111
9368
|
|
|
9112
9369
|
// src/mcp/config-helpers.ts
|
|
9113
|
-
import { existsSync as
|
|
9370
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync8 } from "node:fs";
|
|
9114
9371
|
import { dirname as dirname2 } from "node:path";
|
|
9115
9372
|
function mcpURL(deploymentID) {
|
|
9116
9373
|
return `${getBackendURL()}/v1/mcp/deployments/${deploymentID}`;
|
|
@@ -9144,9 +9401,9 @@ function mcpRemoteServer(url, apiKey) {
|
|
|
9144
9401
|
};
|
|
9145
9402
|
}
|
|
9146
9403
|
function loadJSONConfig(path3) {
|
|
9147
|
-
if (!
|
|
9404
|
+
if (!existsSync7(path3))
|
|
9148
9405
|
return {};
|
|
9149
|
-
let data =
|
|
9406
|
+
let data = readFileSync8(path3, "utf-8").trim();
|
|
9150
9407
|
if (!data)
|
|
9151
9408
|
return {};
|
|
9152
9409
|
if (path3.endsWith(".jsonc")) {
|
|
@@ -9209,8 +9466,8 @@ function saveJSONConfig(path3, cfg) {
|
|
|
9209
9466
|
}
|
|
9210
9467
|
function writeSecureFile(path3, content) {
|
|
9211
9468
|
const dir = dirname2(path3);
|
|
9212
|
-
if (!
|
|
9213
|
-
|
|
9469
|
+
if (!existsSync7(dir)) {
|
|
9470
|
+
mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
9214
9471
|
}
|
|
9215
9472
|
writeFileAtomic.sync(path3, content, { mode: 384, chown: false });
|
|
9216
9473
|
}
|
|
@@ -9251,21 +9508,21 @@ var init_config_helpers = __esm(() => {
|
|
|
9251
9508
|
});
|
|
9252
9509
|
|
|
9253
9510
|
// src/mcp/detect.ts
|
|
9254
|
-
import { existsSync as
|
|
9511
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
9255
9512
|
import { homedir as homedir2, platform as platform2 } from "node:os";
|
|
9256
|
-
import { delimiter, dirname as dirname3, join as
|
|
9513
|
+
import { delimiter, dirname as dirname3, join as join8 } from "node:path";
|
|
9257
9514
|
function isInstalled(paths) {
|
|
9258
|
-
return paths.some((p2) =>
|
|
9515
|
+
return paths.some((p2) => existsSync8(expandHome(p2)));
|
|
9259
9516
|
}
|
|
9260
9517
|
function expandHome(path3) {
|
|
9261
9518
|
if (!path3.startsWith("~"))
|
|
9262
9519
|
return path3;
|
|
9263
|
-
return
|
|
9520
|
+
return join8(homedir2(), path3.slice(1));
|
|
9264
9521
|
}
|
|
9265
9522
|
function appSupportDir() {
|
|
9266
9523
|
switch (platform2()) {
|
|
9267
9524
|
case "darwin": {
|
|
9268
|
-
return
|
|
9525
|
+
return join8(homedir2(), "Library", "Application Support");
|
|
9269
9526
|
}
|
|
9270
9527
|
case "win32": {
|
|
9271
9528
|
return process.env.APPDATA ?? "";
|
|
@@ -9274,7 +9531,7 @@ function appSupportDir() {
|
|
|
9274
9531
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
9275
9532
|
if (xdg)
|
|
9276
9533
|
return xdg;
|
|
9277
|
-
return
|
|
9534
|
+
return join8(homedir2(), ".config");
|
|
9278
9535
|
}
|
|
9279
9536
|
}
|
|
9280
9537
|
}
|
|
@@ -9283,8 +9540,8 @@ function findNpx() {
|
|
|
9283
9540
|
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
9284
9541
|
if (!dir)
|
|
9285
9542
|
continue;
|
|
9286
|
-
const candidate =
|
|
9287
|
-
if (
|
|
9543
|
+
const candidate = join8(dir, bin);
|
|
9544
|
+
if (existsSync8(candidate))
|
|
9288
9545
|
return candidate;
|
|
9289
9546
|
}
|
|
9290
9547
|
throw new Error("npx not found on PATH — Node.js is required (the MCP entry runs `npx mcp-remote`).");
|
|
@@ -9369,7 +9626,7 @@ var init_antigravity = __esm(() => {
|
|
|
9369
9626
|
});
|
|
9370
9627
|
|
|
9371
9628
|
// src/mcp/providers/claude.ts
|
|
9372
|
-
import { join as
|
|
9629
|
+
import { join as join9 } from "node:path";
|
|
9373
9630
|
var ClaudeProvider = () => createJSONProvider({
|
|
9374
9631
|
providerName: "Claude Code",
|
|
9375
9632
|
providerID: "claude",
|
|
@@ -9378,24 +9635,24 @@ var ClaudeProvider = () => createJSONProvider({
|
|
|
9378
9635
|
paths: ["~/.claude"],
|
|
9379
9636
|
globalPath: "~/.claude.json",
|
|
9380
9637
|
topKey: "mcpServers",
|
|
9381
|
-
localConfigPath: (cwd) =>
|
|
9638
|
+
localConfigPath: (cwd) => join9(cwd, ".mcp.json")
|
|
9382
9639
|
});
|
|
9383
9640
|
var init_claude = __esm(() => {
|
|
9384
9641
|
init_base();
|
|
9385
9642
|
});
|
|
9386
9643
|
|
|
9387
9644
|
// src/mcp/providers/claude-desktop.ts
|
|
9388
|
-
import { join as
|
|
9645
|
+
import { join as join10 } from "node:path";
|
|
9389
9646
|
function configPath() {
|
|
9390
|
-
return
|
|
9647
|
+
return join10(appSupportDir(), "Claude", "claude_desktop_config.json");
|
|
9391
9648
|
}
|
|
9392
9649
|
var ClaudeDesktopProvider = () => ({
|
|
9393
9650
|
name: () => "Claude Desktop",
|
|
9394
9651
|
id: () => "claude-desktop",
|
|
9395
9652
|
supportsLocal: () => false,
|
|
9396
9653
|
priority: () => 2,
|
|
9397
|
-
detectPaths: () => [
|
|
9398
|
-
isInstalled: () => isInstalled([
|
|
9654
|
+
detectPaths: () => [join10(appSupportDir(), "Claude")],
|
|
9655
|
+
isInstalled: () => isInstalled([join10(appSupportDir(), "Claude")]),
|
|
9399
9656
|
globalConfigPath: () => configPath(),
|
|
9400
9657
|
isConfigured: () => isJSONKeyConfigured(configPath(), "mcpServers"),
|
|
9401
9658
|
install(cfg, global) {
|
|
@@ -9425,14 +9682,14 @@ var init_claude_desktop = __esm(() => {
|
|
|
9425
9682
|
});
|
|
9426
9683
|
|
|
9427
9684
|
// src/mcp/providers/cline.ts
|
|
9428
|
-
import { join as
|
|
9429
|
-
var extensionDir = () =>
|
|
9685
|
+
import { join as join11 } from "node:path";
|
|
9686
|
+
var extensionDir = () => join11(appSupportDir(), "Code", "User", "globalStorage", "saoudrizwan.claude-dev"), ClineProvider = () => createJSONProvider({
|
|
9430
9687
|
providerName: "Cline",
|
|
9431
9688
|
providerID: "cline",
|
|
9432
9689
|
local: false,
|
|
9433
9690
|
priorityValue: 11,
|
|
9434
9691
|
paths: [extensionDir()],
|
|
9435
|
-
globalPath:
|
|
9692
|
+
globalPath: join11(extensionDir(), "settings", "cline_mcp_settings.json"),
|
|
9436
9693
|
topKey: "mcpServers",
|
|
9437
9694
|
buildServer: (cfg) => ({
|
|
9438
9695
|
url: mcpURL(cfg.active_account.target.deployment_id),
|
|
@@ -9448,7 +9705,7 @@ var init_cline = __esm(() => {
|
|
|
9448
9705
|
});
|
|
9449
9706
|
|
|
9450
9707
|
// src/mcp/providers/cline-cli.ts
|
|
9451
|
-
import { join as
|
|
9708
|
+
import { join as join12 } from "node:path";
|
|
9452
9709
|
function clineDir() {
|
|
9453
9710
|
return process.env.CLINE_DIR ?? expandHome("~/.cline");
|
|
9454
9711
|
}
|
|
@@ -9458,7 +9715,7 @@ var ClineCliProvider = () => createJSONProvider({
|
|
|
9458
9715
|
local: false,
|
|
9459
9716
|
priorityValue: 12,
|
|
9460
9717
|
paths: [clineDir()],
|
|
9461
|
-
globalPath:
|
|
9718
|
+
globalPath: join12(clineDir(), "data", "settings", "cline_mcp_settings.json"),
|
|
9462
9719
|
topKey: "mcpServers",
|
|
9463
9720
|
buildServer: (cfg) => ({
|
|
9464
9721
|
url: mcpURL(cfg.active_account.target.deployment_id),
|
|
@@ -9474,20 +9731,20 @@ var init_cline_cli = __esm(() => {
|
|
|
9474
9731
|
});
|
|
9475
9732
|
|
|
9476
9733
|
// src/mcp/providers/codex.ts
|
|
9477
|
-
import { existsSync as
|
|
9478
|
-
import { join as
|
|
9734
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
|
|
9735
|
+
import { join as join13 } from "node:path";
|
|
9479
9736
|
function codexHome() {
|
|
9480
9737
|
return process.env.CODEX_HOME ?? expandHome("~/.codex");
|
|
9481
9738
|
}
|
|
9482
9739
|
function getConfigPath2(global) {
|
|
9483
9740
|
if (global)
|
|
9484
|
-
return
|
|
9485
|
-
return
|
|
9741
|
+
return join13(codexHome(), "config.toml");
|
|
9742
|
+
return join13(process.cwd(), ".codex", "config.toml");
|
|
9486
9743
|
}
|
|
9487
9744
|
function readTOML(path3) {
|
|
9488
|
-
if (!
|
|
9745
|
+
if (!existsSync9(path3))
|
|
9489
9746
|
return "";
|
|
9490
|
-
return
|
|
9747
|
+
return readFileSync9(path3, "utf-8");
|
|
9491
9748
|
}
|
|
9492
9749
|
function writeTOML(path3, content) {
|
|
9493
9750
|
writeSecureFile(path3, content);
|
|
@@ -9550,9 +9807,9 @@ var CodexProvider = () => ({
|
|
|
9550
9807
|
priority: () => 8,
|
|
9551
9808
|
detectPaths: () => ["~/.codex"],
|
|
9552
9809
|
isInstalled: () => isInstalled(["~/.codex"]),
|
|
9553
|
-
globalConfigPath: () =>
|
|
9810
|
+
globalConfigPath: () => join13(codexHome(), "config.toml"),
|
|
9554
9811
|
isConfigured: () => {
|
|
9555
|
-
const content = readTOML(
|
|
9812
|
+
const content = readTOML(join13(codexHome(), "config.toml"));
|
|
9556
9813
|
return content.includes("[mcp_servers.dosu]");
|
|
9557
9814
|
},
|
|
9558
9815
|
install(cfg, global) {
|
|
@@ -9574,10 +9831,10 @@ var init_codex = __esm(() => {
|
|
|
9574
9831
|
});
|
|
9575
9832
|
|
|
9576
9833
|
// src/mcp/providers/copilot.ts
|
|
9577
|
-
import { join as
|
|
9834
|
+
import { join as join14 } from "node:path";
|
|
9578
9835
|
function globalPath() {
|
|
9579
9836
|
if (process.env.XDG_CONFIG_HOME) {
|
|
9580
|
-
return
|
|
9837
|
+
return join14(process.env.XDG_CONFIG_HOME, "mcp-config.json");
|
|
9581
9838
|
}
|
|
9582
9839
|
return expandHome("~/.copilot/mcp-config.json");
|
|
9583
9840
|
}
|
|
@@ -9608,7 +9865,7 @@ var CopilotProvider = () => ({
|
|
|
9608
9865
|
};
|
|
9609
9866
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
9610
9867
|
} else {
|
|
9611
|
-
const configPath2 =
|
|
9868
|
+
const configPath2 = join14(process.cwd(), ".vscode", "mcp.json");
|
|
9612
9869
|
const server = {
|
|
9613
9870
|
type: "http",
|
|
9614
9871
|
url,
|
|
@@ -9621,7 +9878,7 @@ var CopilotProvider = () => ({
|
|
|
9621
9878
|
if (global) {
|
|
9622
9879
|
removeJSONServer(globalPath(), "mcpServers");
|
|
9623
9880
|
} else {
|
|
9624
|
-
const configPath2 =
|
|
9881
|
+
const configPath2 = join14(process.cwd(), ".vscode", "mcp.json");
|
|
9625
9882
|
removeJSONServer(configPath2, "servers");
|
|
9626
9883
|
}
|
|
9627
9884
|
}
|
|
@@ -9633,7 +9890,7 @@ var init_copilot = __esm(() => {
|
|
|
9633
9890
|
});
|
|
9634
9891
|
|
|
9635
9892
|
// src/mcp/providers/cursor.ts
|
|
9636
|
-
import { join as
|
|
9893
|
+
import { join as join15 } from "node:path";
|
|
9637
9894
|
var CursorProvider = () => createJSONProvider({
|
|
9638
9895
|
providerName: "Cursor",
|
|
9639
9896
|
providerID: "cursor",
|
|
@@ -9646,7 +9903,7 @@ var CursorProvider = () => createJSONProvider({
|
|
|
9646
9903
|
url: mcpURL(cfg.active_account.target.deployment_id),
|
|
9647
9904
|
headers: mcpHeaders(cfg.active_account.target.api_key)
|
|
9648
9905
|
}),
|
|
9649
|
-
localConfigPath: (cwd) =>
|
|
9906
|
+
localConfigPath: (cwd) => join15(cwd, ".cursor", "mcp.json")
|
|
9650
9907
|
});
|
|
9651
9908
|
var init_cursor = __esm(() => {
|
|
9652
9909
|
init_config_helpers();
|
|
@@ -9654,7 +9911,7 @@ var init_cursor = __esm(() => {
|
|
|
9654
9911
|
});
|
|
9655
9912
|
|
|
9656
9913
|
// src/mcp/providers/factory.ts
|
|
9657
|
-
import { join as
|
|
9914
|
+
import { join as join16 } from "node:path";
|
|
9658
9915
|
var FactoryProvider = () => createJSONProvider({
|
|
9659
9916
|
providerName: "Factory",
|
|
9660
9917
|
providerID: "factory",
|
|
@@ -9663,14 +9920,14 @@ var FactoryProvider = () => createJSONProvider({
|
|
|
9663
9920
|
paths: ["~/.factory"],
|
|
9664
9921
|
globalPath: "~/.factory/mcp.json",
|
|
9665
9922
|
topKey: "mcpServers",
|
|
9666
|
-
localConfigPath: (cwd) =>
|
|
9923
|
+
localConfigPath: (cwd) => join16(cwd, ".factory", "mcp.json")
|
|
9667
9924
|
});
|
|
9668
9925
|
var init_factory = __esm(() => {
|
|
9669
9926
|
init_base();
|
|
9670
9927
|
});
|
|
9671
9928
|
|
|
9672
9929
|
// src/mcp/providers/gemini.ts
|
|
9673
|
-
import { join as
|
|
9930
|
+
import { join as join17 } from "node:path";
|
|
9674
9931
|
var GeminiProvider = () => createJSONProvider({
|
|
9675
9932
|
providerName: "Gemini CLI",
|
|
9676
9933
|
providerID: "gemini",
|
|
@@ -9679,7 +9936,7 @@ var GeminiProvider = () => createJSONProvider({
|
|
|
9679
9936
|
paths: ["~/.gemini"],
|
|
9680
9937
|
globalPath: "~/.gemini/settings.json",
|
|
9681
9938
|
topKey: "mcpServers",
|
|
9682
|
-
localConfigPath: (cwd) =>
|
|
9939
|
+
localConfigPath: (cwd) => join17(cwd, ".gemini", "settings.json")
|
|
9683
9940
|
});
|
|
9684
9941
|
var init_gemini = __esm(() => {
|
|
9685
9942
|
init_base();
|
|
@@ -9729,14 +9986,14 @@ var init_manual = __esm(() => {
|
|
|
9729
9986
|
});
|
|
9730
9987
|
|
|
9731
9988
|
// src/mcp/providers/mcporter.ts
|
|
9732
|
-
import { existsSync as
|
|
9733
|
-
import { join as
|
|
9989
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
9990
|
+
import { join as join18 } from "node:path";
|
|
9734
9991
|
function resolveGlobalConfigPath() {
|
|
9735
9992
|
const jsonPath = expandHome("~/.mcporter/mcporter.json");
|
|
9736
|
-
if (
|
|
9993
|
+
if (existsSync10(jsonPath))
|
|
9737
9994
|
return jsonPath;
|
|
9738
9995
|
const jsoncPath = expandHome("~/.mcporter/mcporter.jsonc");
|
|
9739
|
-
if (
|
|
9996
|
+
if (existsSync10(jsoncPath))
|
|
9740
9997
|
return jsoncPath;
|
|
9741
9998
|
return jsonPath;
|
|
9742
9999
|
}
|
|
@@ -9757,7 +10014,7 @@ var MCPorterProvider = () => ({
|
|
|
9757
10014
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
9758
10015
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
9759
10016
|
install(cfg, global) {
|
|
9760
|
-
const configPath2 = global ? resolveGlobalConfigPath() :
|
|
10017
|
+
const configPath2 = global ? resolveGlobalConfigPath() : join18(process.cwd(), "config", "mcporter.json");
|
|
9761
10018
|
const server = {
|
|
9762
10019
|
type: "http",
|
|
9763
10020
|
url: mcpEndpoint4(cfg),
|
|
@@ -9766,7 +10023,7 @@ var MCPorterProvider = () => ({
|
|
|
9766
10023
|
installJSONServer(configPath2, "mcpServers", server);
|
|
9767
10024
|
},
|
|
9768
10025
|
remove(global) {
|
|
9769
|
-
const configPath2 = global ? resolveGlobalConfigPath() :
|
|
10026
|
+
const configPath2 = global ? resolveGlobalConfigPath() : join18(process.cwd(), "config", "mcporter.json");
|
|
9770
10027
|
removeJSONServer(configPath2, "mcpServers");
|
|
9771
10028
|
}
|
|
9772
10029
|
});
|
|
@@ -9777,7 +10034,7 @@ var init_mcporter = __esm(() => {
|
|
|
9777
10034
|
});
|
|
9778
10035
|
|
|
9779
10036
|
// src/mcp/providers/opencode.ts
|
|
9780
|
-
import { join as
|
|
10037
|
+
import { join as join19 } from "node:path";
|
|
9781
10038
|
var OpenCodeProvider = () => createJSONProvider({
|
|
9782
10039
|
providerName: "OpenCode",
|
|
9783
10040
|
providerID: "opencode",
|
|
@@ -9792,7 +10049,7 @@ var OpenCodeProvider = () => createJSONProvider({
|
|
|
9792
10049
|
enabled: true,
|
|
9793
10050
|
headers: mcpHeaders(cfg.active_account.target.api_key)
|
|
9794
10051
|
}),
|
|
9795
|
-
localConfigPath: (cwd) =>
|
|
10052
|
+
localConfigPath: (cwd) => join19(cwd, "opencode.json")
|
|
9796
10053
|
});
|
|
9797
10054
|
var init_opencode = __esm(() => {
|
|
9798
10055
|
init_config_helpers();
|
|
@@ -9800,16 +10057,16 @@ var init_opencode = __esm(() => {
|
|
|
9800
10057
|
});
|
|
9801
10058
|
|
|
9802
10059
|
// src/mcp/providers/vscode.ts
|
|
9803
|
-
import { join as
|
|
10060
|
+
import { join as join20 } from "node:path";
|
|
9804
10061
|
var VSCodeProvider = () => createJSONProvider({
|
|
9805
10062
|
providerName: "VS Code",
|
|
9806
10063
|
providerID: "vscode",
|
|
9807
10064
|
local: true,
|
|
9808
10065
|
priorityValue: 6,
|
|
9809
|
-
paths: [
|
|
9810
|
-
globalPath:
|
|
10066
|
+
paths: [join20(appSupportDir(), "Code")],
|
|
10067
|
+
globalPath: join20(appSupportDir(), "Code", "User", "mcp.json"),
|
|
9811
10068
|
topKey: "servers",
|
|
9812
|
-
localConfigPath: (cwd) =>
|
|
10069
|
+
localConfigPath: (cwd) => join20(cwd, ".vscode", "mcp.json")
|
|
9813
10070
|
});
|
|
9814
10071
|
var init_vscode = __esm(() => {
|
|
9815
10072
|
init_detect();
|
|
@@ -9818,14 +10075,14 @@ var init_vscode = __esm(() => {
|
|
|
9818
10075
|
|
|
9819
10076
|
// src/mcp/providers/windsurf.ts
|
|
9820
10077
|
import { homedir as homedir3 } from "node:os";
|
|
9821
|
-
import { join as
|
|
10078
|
+
import { join as join21 } from "node:path";
|
|
9822
10079
|
var WindsurfProvider = () => createJSONProvider({
|
|
9823
10080
|
providerName: "Windsurf",
|
|
9824
10081
|
providerID: "windsurf",
|
|
9825
10082
|
local: false,
|
|
9826
10083
|
priorityValue: 9,
|
|
9827
|
-
paths: [
|
|
9828
|
-
globalPath:
|
|
10084
|
+
paths: [join21(homedir3(), ".codeium", "windsurf")],
|
|
10085
|
+
globalPath: join21(homedir3(), ".codeium", "windsurf", "mcp_config.json"),
|
|
9829
10086
|
topKey: "mcpServers"
|
|
9830
10087
|
});
|
|
9831
10088
|
var init_windsurf = __esm(() => {
|
|
@@ -9834,12 +10091,12 @@ var init_windsurf = __esm(() => {
|
|
|
9834
10091
|
|
|
9835
10092
|
// src/mcp/providers/zed.ts
|
|
9836
10093
|
import { platform as platform3 } from "node:os";
|
|
9837
|
-
import { join as
|
|
10094
|
+
import { join as join22 } from "node:path";
|
|
9838
10095
|
function zedConfigDir() {
|
|
9839
10096
|
const os2 = platform3();
|
|
9840
10097
|
if (os2 === "darwin" || os2 === "win32")
|
|
9841
|
-
return
|
|
9842
|
-
return
|
|
10098
|
+
return join22(appSupportDir(), "Zed");
|
|
10099
|
+
return join22(appSupportDir(), "zed");
|
|
9843
10100
|
}
|
|
9844
10101
|
var ZedProvider = () => createJSONProvider({
|
|
9845
10102
|
providerName: "Zed",
|
|
@@ -9847,7 +10104,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
9847
10104
|
local: true,
|
|
9848
10105
|
priorityValue: 10,
|
|
9849
10106
|
paths: [zedConfigDir()],
|
|
9850
|
-
globalPath:
|
|
10107
|
+
globalPath: join22(zedConfigDir(), "settings.json"),
|
|
9851
10108
|
topKey: "context_servers",
|
|
9852
10109
|
buildServer: (cfg) => ({
|
|
9853
10110
|
source: "custom",
|
|
@@ -9855,7 +10112,7 @@ var ZedProvider = () => createJSONProvider({
|
|
|
9855
10112
|
url: mcpURL(cfg.active_account.target.deployment_id),
|
|
9856
10113
|
headers: mcpHeaders(cfg.active_account.target.api_key)
|
|
9857
10114
|
}),
|
|
9858
|
-
localConfigPath: (cwd) =>
|
|
10115
|
+
localConfigPath: (cwd) => join22(cwd, ".zed", "settings.json")
|
|
9859
10116
|
});
|
|
9860
10117
|
var init_zed = __esm(() => {
|
|
9861
10118
|
init_config_helpers();
|
|
@@ -9914,14 +10171,14 @@ var init_providers = __esm(() => {
|
|
|
9914
10171
|
});
|
|
9915
10172
|
|
|
9916
10173
|
// src/rules/installer.ts
|
|
9917
|
-
import { existsSync as
|
|
10174
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
9918
10175
|
import { homedir as homedir4 } from "node:os";
|
|
9919
|
-
import { dirname as dirname4, join as
|
|
10176
|
+
import { dirname as dirname4, join as join23 } from "node:path";
|
|
9920
10177
|
function claudeConfigDir() {
|
|
9921
|
-
return process.env.CLAUDE_CONFIG_DIR ||
|
|
10178
|
+
return process.env.CLAUDE_CONFIG_DIR || join23(homedir4(), ".claude");
|
|
9922
10179
|
}
|
|
9923
10180
|
function codexHome2() {
|
|
9924
|
-
return process.env.CODEX_HOME ||
|
|
10181
|
+
return process.env.CODEX_HOME || join23(homedir4(), ".codex");
|
|
9925
10182
|
}
|
|
9926
10183
|
function isRuleAgent(agent) {
|
|
9927
10184
|
return Object.hasOwn(RULE_TARGETS, agent);
|
|
@@ -9947,17 +10204,17 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
|
9947
10204
|
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
9948
10205
|
}
|
|
9949
10206
|
function ensureParent(path3) {
|
|
9950
|
-
|
|
10207
|
+
mkdirSync7(dirname4(path3), { recursive: true });
|
|
9951
10208
|
}
|
|
9952
10209
|
function writeIfChanged(path3, content) {
|
|
9953
|
-
if (!
|
|
10210
|
+
if (!existsSync11(path3)) {
|
|
9954
10211
|
ensureParent(path3);
|
|
9955
|
-
|
|
10212
|
+
writeFileSync7(path3, content, "utf-8");
|
|
9956
10213
|
return "created";
|
|
9957
10214
|
}
|
|
9958
|
-
if (
|
|
10215
|
+
if (readFileSync10(path3, "utf-8") === content)
|
|
9959
10216
|
return "unchanged";
|
|
9960
|
-
|
|
10217
|
+
writeFileSync7(path3, content, "utf-8");
|
|
9961
10218
|
return "updated";
|
|
9962
10219
|
}
|
|
9963
10220
|
function findSection(content) {
|
|
@@ -9983,14 +10240,14 @@ function buildSection(content, lineEnding = `
|
|
|
9983
10240
|
return `${DOSU_RULE_SECTION_START}${lineEnding}${body}${lineEnding}${DOSU_RULE_SECTION_END}`;
|
|
9984
10241
|
}
|
|
9985
10242
|
function upsertSection(path3, content) {
|
|
9986
|
-
if (!
|
|
10243
|
+
if (!existsSync11(path3)) {
|
|
9987
10244
|
const section2 = buildSection(content);
|
|
9988
10245
|
ensureParent(path3);
|
|
9989
|
-
|
|
10246
|
+
writeFileSync7(path3, `${section2}
|
|
9990
10247
|
`, "utf-8");
|
|
9991
10248
|
return "created";
|
|
9992
10249
|
}
|
|
9993
|
-
const existing =
|
|
10250
|
+
const existing = readFileSync10(path3, "utf-8");
|
|
9994
10251
|
const lineEnding = lineEndingFor(existing);
|
|
9995
10252
|
const section = buildSection(content, lineEnding);
|
|
9996
10253
|
const location = findSection(existing);
|
|
@@ -10003,7 +10260,7 @@ function upsertSection(path3, content) {
|
|
|
10003
10260
|
}
|
|
10004
10261
|
if (next === existing)
|
|
10005
10262
|
return "unchanged";
|
|
10006
|
-
|
|
10263
|
+
writeFileSync7(path3, next, "utf-8");
|
|
10007
10264
|
return "updated";
|
|
10008
10265
|
}
|
|
10009
10266
|
function installRuleForAgent(agent, content) {
|
|
@@ -10020,22 +10277,22 @@ function removeRuleForAgent(agent) {
|
|
|
10020
10277
|
return null;
|
|
10021
10278
|
const target = RULE_TARGETS[agent];
|
|
10022
10279
|
const path3 = target.path();
|
|
10023
|
-
if (!
|
|
10280
|
+
if (!existsSync11(path3))
|
|
10024
10281
|
return { agent, path: path3, action: "not_found" };
|
|
10025
10282
|
if (target.kind === "file") {
|
|
10026
|
-
|
|
10283
|
+
unlinkSync2(path3);
|
|
10027
10284
|
return { agent, path: path3, action: "removed" };
|
|
10028
10285
|
}
|
|
10029
|
-
const existing =
|
|
10286
|
+
const existing = readFileSync10(path3, "utf-8");
|
|
10030
10287
|
const lineEnding = lineEndingFor(existing);
|
|
10031
10288
|
const location = findSection(existing);
|
|
10032
10289
|
if (!location)
|
|
10033
10290
|
return { agent, path: path3, action: "not_found" };
|
|
10034
10291
|
const next = (existing.slice(0, location.start) + existing.slice(location.end + DOSU_RULE_SECTION_END.length)).replace(/(?:\r?\n){3,}/g, `${lineEnding}${lineEnding}`).replace(/^(?:\r?\n)+/, "").trimEnd();
|
|
10035
10292
|
if (!next) {
|
|
10036
|
-
|
|
10293
|
+
unlinkSync2(path3);
|
|
10037
10294
|
} else {
|
|
10038
|
-
|
|
10295
|
+
writeFileSync7(path3, `${next}${lineEnding}`, "utf-8");
|
|
10039
10296
|
}
|
|
10040
10297
|
return { agent, path: path3, action: "removed" };
|
|
10041
10298
|
}
|
|
@@ -10045,7 +10302,7 @@ alwaysApply: true
|
|
|
10045
10302
|
|
|
10046
10303
|
`, DOSU_RULE_URLS, FALLBACK_DOSU_RULE = `The team you are assisting maintains shared knowledge in Dosu: consult it to build on prior work, and contribute durable knowledge so future teammates and agents do not have to rediscover it. Always use only tools currently listed by the server.
|
|
10047
10304
|
|
|
10048
|
-
When \`read_knowledge\` is listed, call it before non-trivial code or documentation work involving architecture, conventions, prior decisions, gotchas, incidents, ownership, or branch history. **If unsure whether relevant context exists, read first.** Pass \`repo\` and \`branch\` when available. Skip generic questions, trivial or self-contained edits, and context already injected by Dosu.
|
|
10305
|
+
When \`read_knowledge\` is listed, call it before non-trivial code or documentation work involving architecture, conventions, prior decisions, gotchas, incidents, ownership, or branch history. **If unsure whether relevant context exists, read first.** Pass \`repo\` and \`branch\` when available. Skip generic questions, trivial or self-contained edits, and context already injected by Dosu.
|
|
10049
10306
|
|
|
10050
10307
|
When \`write_knowledge\` is listed, use it after the task for durable, non-obvious knowledge that future work would otherwise have to rediscover. Do not save task or PR summaries, progress, test results, obvious facts, speculation, duplicates, or sensitive data. **If nothing durable was learned, do not write.**
|
|
10051
10308
|
|
|
@@ -10063,36 +10320,36 @@ var init_installer = __esm(() => {
|
|
|
10063
10320
|
RULE_TARGETS = {
|
|
10064
10321
|
claude: {
|
|
10065
10322
|
kind: "file",
|
|
10066
|
-
path: () =>
|
|
10323
|
+
path: () => join23(claudeConfigDir(), "rules", "dosu.md")
|
|
10067
10324
|
},
|
|
10068
10325
|
cursor: {
|
|
10069
10326
|
kind: "file",
|
|
10070
|
-
path: () =>
|
|
10327
|
+
path: () => join23(homedir4(), ".cursor", "rules", "dosu.mdc"),
|
|
10071
10328
|
cursorFrontmatter: true
|
|
10072
10329
|
},
|
|
10073
10330
|
codex: {
|
|
10074
10331
|
kind: "section",
|
|
10075
|
-
path: () =>
|
|
10332
|
+
path: () => join23(codexHome2(), "AGENTS.md")
|
|
10076
10333
|
},
|
|
10077
10334
|
opencode: {
|
|
10078
10335
|
kind: "section",
|
|
10079
|
-
path: () =>
|
|
10336
|
+
path: () => join23(homedir4(), ".config", "opencode", "AGENTS.md")
|
|
10080
10337
|
},
|
|
10081
10338
|
gemini: {
|
|
10082
10339
|
kind: "section",
|
|
10083
|
-
path: () =>
|
|
10340
|
+
path: () => join23(homedir4(), ".gemini", "GEMINI.md")
|
|
10084
10341
|
},
|
|
10085
10342
|
antigravity: {
|
|
10086
10343
|
kind: "section",
|
|
10087
|
-
path: () =>
|
|
10344
|
+
path: () => join23(homedir4(), ".gemini", "GEMINI.md")
|
|
10088
10345
|
}
|
|
10089
10346
|
};
|
|
10090
10347
|
});
|
|
10091
10348
|
|
|
10092
10349
|
// src/setup/agents-md-step.ts
|
|
10093
10350
|
import { execSync as execSync3 } from "node:child_process";
|
|
10094
|
-
import { existsSync as
|
|
10095
|
-
import { join as
|
|
10351
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "node:fs";
|
|
10352
|
+
import { join as join24 } from "node:path";
|
|
10096
10353
|
function inGitWorkTree(cwd = process.cwd()) {
|
|
10097
10354
|
try {
|
|
10098
10355
|
const stdout2 = execSync3("git rev-parse --is-inside-work-tree", {
|
|
@@ -10130,14 +10387,14 @@ function findSection2(content) {
|
|
|
10130
10387
|
return { start, end };
|
|
10131
10388
|
}
|
|
10132
10389
|
function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RULE) {
|
|
10133
|
-
const path3 =
|
|
10134
|
-
if (!
|
|
10390
|
+
const path3 = join24(cwd, "AGENTS.md");
|
|
10391
|
+
if (!existsSync12(path3)) {
|
|
10135
10392
|
const section2 = buildDosuAgentsSection(content);
|
|
10136
|
-
|
|
10393
|
+
writeFileSync8(path3, `${section2}
|
|
10137
10394
|
`);
|
|
10138
10395
|
return { path: path3, action: "created" };
|
|
10139
10396
|
}
|
|
10140
|
-
const existing =
|
|
10397
|
+
const existing = readFileSync11(path3, "utf-8");
|
|
10141
10398
|
const lineEnding = lineEndingFor2(existing);
|
|
10142
10399
|
const section = renderDosuAgentsSection(content, lineEnding);
|
|
10143
10400
|
const location = findSection2(existing);
|
|
@@ -10149,7 +10406,7 @@ function upsertDosuAgentsSection(cwd = process.cwd(), content = FALLBACK_DOSU_RU
|
|
|
10149
10406
|
}
|
|
10150
10407
|
if (next === existing)
|
|
10151
10408
|
return { path: path3, action: "unchanged" };
|
|
10152
|
-
|
|
10409
|
+
writeFileSync8(path3, next);
|
|
10153
10410
|
return { path: path3, action: "updated" };
|
|
10154
10411
|
}
|
|
10155
10412
|
async function stepUpdateAgentsMd(cwd = process.cwd(), content) {
|
|
@@ -10178,19 +10435,19 @@ var init_agents_md_step = __esm(() => {
|
|
|
10178
10435
|
});
|
|
10179
10436
|
|
|
10180
10437
|
// src/telemetry/settings.ts
|
|
10181
|
-
import { randomUUID } from "node:crypto";
|
|
10438
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
10182
10439
|
import {
|
|
10183
|
-
existsSync as
|
|
10440
|
+
existsSync as existsSync13,
|
|
10184
10441
|
lstatSync,
|
|
10185
|
-
mkdirSync as
|
|
10186
|
-
readFileSync as
|
|
10442
|
+
mkdirSync as mkdirSync8,
|
|
10443
|
+
readFileSync as readFileSync12,
|
|
10187
10444
|
renameSync as renameSync2,
|
|
10188
|
-
unlinkSync as
|
|
10189
|
-
writeFileSync as
|
|
10445
|
+
unlinkSync as unlinkSync3,
|
|
10446
|
+
writeFileSync as writeFileSync9
|
|
10190
10447
|
} from "node:fs";
|
|
10191
|
-
import { join as
|
|
10448
|
+
import { join as join25 } from "node:path";
|
|
10192
10449
|
function getTelemetrySettingsPath() {
|
|
10193
|
-
return
|
|
10450
|
+
return join25(getConfigDir(), TELEMETRY_SETTINGS_FILENAME);
|
|
10194
10451
|
}
|
|
10195
10452
|
function loadTelemetrySettings() {
|
|
10196
10453
|
return readTelemetrySettings().settings;
|
|
@@ -10228,7 +10485,7 @@ function getOrCreateInstallID() {
|
|
|
10228
10485
|
}
|
|
10229
10486
|
if (current.status !== "current" && current.status !== "missing")
|
|
10230
10487
|
return;
|
|
10231
|
-
const installID =
|
|
10488
|
+
const installID = randomUUID2();
|
|
10232
10489
|
const settings2 = current.status === "current" ? current.settings : emptyTelemetrySettings();
|
|
10233
10490
|
settings2.install_id = installID;
|
|
10234
10491
|
return writeTelemetrySettings(settings2) ? installID : undefined;
|
|
@@ -10238,7 +10495,7 @@ function resetInstallID() {
|
|
|
10238
10495
|
if (current.status !== "current" && current.status !== "missing")
|
|
10239
10496
|
return;
|
|
10240
10497
|
const settings2 = current.status === "current" ? current.settings : emptyTelemetrySettings();
|
|
10241
|
-
const installID =
|
|
10498
|
+
const installID = randomUUID2();
|
|
10242
10499
|
settings2.install_id = installID;
|
|
10243
10500
|
return writeTelemetrySettings(settings2) ? installID : undefined;
|
|
10244
10501
|
}
|
|
@@ -10258,7 +10515,7 @@ function readTelemetrySettings() {
|
|
|
10258
10515
|
}
|
|
10259
10516
|
let content;
|
|
10260
10517
|
try {
|
|
10261
|
-
content =
|
|
10518
|
+
content = readFileSync12(path3, "utf-8");
|
|
10262
10519
|
} catch {
|
|
10263
10520
|
return { status: "error", settings: disabledTelemetrySettings() };
|
|
10264
10521
|
}
|
|
@@ -10268,7 +10525,7 @@ function readTelemetrySettings() {
|
|
|
10268
10525
|
} catch {
|
|
10269
10526
|
return { status: "invalid", settings: disabledTelemetrySettings() };
|
|
10270
10527
|
}
|
|
10271
|
-
if (!
|
|
10528
|
+
if (!isRecord5(raw))
|
|
10272
10529
|
return { status: "invalid", settings: disabledTelemetrySettings() };
|
|
10273
10530
|
if (raw.schema_version !== TELEMETRY_SCHEMA_VERSION) {
|
|
10274
10531
|
const status = "schema_version" in raw ? "unsupported" : "invalid";
|
|
@@ -10288,11 +10545,11 @@ function readTelemetrySettings() {
|
|
|
10288
10545
|
function writeTelemetrySettings(settings2) {
|
|
10289
10546
|
const path3 = getTelemetrySettingsPath();
|
|
10290
10547
|
const dir = getConfigDir();
|
|
10291
|
-
const temporaryPath = `${path3}.${process.pid}.${
|
|
10548
|
+
const temporaryPath = `${path3}.${process.pid}.${randomUUID2()}.tmp`;
|
|
10292
10549
|
try {
|
|
10293
|
-
if (!
|
|
10294
|
-
|
|
10295
|
-
|
|
10550
|
+
if (!existsSync13(dir))
|
|
10551
|
+
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
10552
|
+
writeFileSync9(temporaryPath, `${JSON.stringify(settings2, null, 2)}
|
|
10296
10553
|
`, {
|
|
10297
10554
|
flag: "wx",
|
|
10298
10555
|
mode: 384
|
|
@@ -10301,7 +10558,7 @@ function writeTelemetrySettings(settings2) {
|
|
|
10301
10558
|
return true;
|
|
10302
10559
|
} catch {
|
|
10303
10560
|
try {
|
|
10304
|
-
|
|
10561
|
+
unlinkSync3(temporaryPath);
|
|
10305
10562
|
} catch {}
|
|
10306
10563
|
return false;
|
|
10307
10564
|
}
|
|
@@ -10323,7 +10580,7 @@ function isEnabledEnvironmentFlag(value) {
|
|
|
10323
10580
|
function isUUID(value) {
|
|
10324
10581
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
|
10325
10582
|
}
|
|
10326
|
-
function
|
|
10583
|
+
function isRecord5(value) {
|
|
10327
10584
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10328
10585
|
}
|
|
10329
10586
|
function isErrorCode(error, code) {
|
|
@@ -10336,11 +10593,11 @@ var init_settings = __esm(() => {
|
|
|
10336
10593
|
});
|
|
10337
10594
|
|
|
10338
10595
|
// src/telemetry/debug-id.ts
|
|
10339
|
-
var BUNDLE_DEBUG_ID_PLACEHOLDER = "
|
|
10596
|
+
var BUNDLE_DEBUG_ID_PLACEHOLDER = "20790a5a-a63f-06a4-6475-6e2164756e21";
|
|
10340
10597
|
|
|
10341
10598
|
// src/telemetry/telemetry.ts
|
|
10342
|
-
import { randomUUID as
|
|
10343
|
-
import { existsSync as
|
|
10599
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
10600
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
10344
10601
|
import { request as httpRequest2 } from "node:http";
|
|
10345
10602
|
import { request as httpsRequest } from "node:https";
|
|
10346
10603
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
@@ -10479,7 +10736,7 @@ function parseOwnedStackLine(originalLine, packageRoot) {
|
|
|
10479
10736
|
return;
|
|
10480
10737
|
}
|
|
10481
10738
|
try {
|
|
10482
|
-
if (!
|
|
10739
|
+
if (!existsSync14(resolvedPath))
|
|
10483
10740
|
return;
|
|
10484
10741
|
} catch {
|
|
10485
10742
|
return;
|
|
@@ -10487,15 +10744,16 @@ function parseOwnedStackLine(originalLine, packageRoot) {
|
|
|
10487
10744
|
return { filename, lineno: Number(match[2]), colno: Number(match[3]) };
|
|
10488
10745
|
}
|
|
10489
10746
|
function sanitizeError(error) {
|
|
10490
|
-
const
|
|
10491
|
-
const
|
|
10492
|
-
const
|
|
10747
|
+
const normalizedError = domainErrorFromCauseChain(error) ?? error;
|
|
10748
|
+
const data = safeRead(normalizedError, "data");
|
|
10749
|
+
const typeCandidate = safeRead(normalizedError, "name");
|
|
10750
|
+
const codeCandidates = [safeRead(data, "code"), safeRead(normalizedError, "code")];
|
|
10493
10751
|
const statusCandidates = [
|
|
10494
10752
|
safeRead(data, "httpStatus"),
|
|
10495
|
-
safeRead(
|
|
10496
|
-
safeRead(
|
|
10753
|
+
safeRead(normalizedError, "status"),
|
|
10754
|
+
safeRead(normalizedError, "statusCode")
|
|
10497
10755
|
];
|
|
10498
|
-
const exitCodeCandidate = safeRead(
|
|
10756
|
+
const exitCodeCandidate = safeRead(normalizedError, "exitCode");
|
|
10499
10757
|
const code = codeCandidates.find(validErrorCode);
|
|
10500
10758
|
const status = statusCandidates.find(validStatus);
|
|
10501
10759
|
const exitCode = typeof exitCodeCandidate === "number" && Number.isFinite(exitCodeCandidate) ? normalizeExitCode(exitCodeCandidate) : undefined;
|
|
@@ -10503,10 +10761,25 @@ function sanitizeError(error) {
|
|
|
10503
10761
|
type: validErrorType(typeCandidate) ? typeCandidate : "Error",
|
|
10504
10762
|
...code ? { code } : {},
|
|
10505
10763
|
...status ? { status } : {},
|
|
10506
|
-
frames: parseStack(safeRead(
|
|
10764
|
+
frames: parseStack(safeRead(normalizedError, "stack")),
|
|
10507
10765
|
...exitCode === undefined ? {} : { exitCode }
|
|
10508
10766
|
};
|
|
10509
10767
|
}
|
|
10768
|
+
function domainErrorFromCauseChain(error) {
|
|
10769
|
+
const seen = new Set;
|
|
10770
|
+
let current = error;
|
|
10771
|
+
for (let depth = 0;depth < 5 && objectLike(current); depth += 1) {
|
|
10772
|
+
if (seen.has(current))
|
|
10773
|
+
return;
|
|
10774
|
+
seen.add(current);
|
|
10775
|
+
const code = safeRead(current, "code");
|
|
10776
|
+
if (code === "SESSION_EXPIRED" || code === "SESSION_PERSISTENCE_ERROR" || code === "SESSION_REFRESH_ERROR") {
|
|
10777
|
+
return current;
|
|
10778
|
+
}
|
|
10779
|
+
current = safeRead(current, "cause");
|
|
10780
|
+
}
|
|
10781
|
+
return;
|
|
10782
|
+
}
|
|
10510
10783
|
function durationBucket(durationMs) {
|
|
10511
10784
|
const duration = Number.isFinite(durationMs) ? Math.max(0, durationMs) : 0;
|
|
10512
10785
|
if (duration < 100)
|
|
@@ -10867,7 +11140,7 @@ function createCommandTelemetry(settings2, dependencies = {}) {
|
|
|
10867
11140
|
const env = dependencies.env ?? process.env;
|
|
10868
11141
|
const fetcher = dependencies.fetch;
|
|
10869
11142
|
const now = dependencies.now ?? Date.now;
|
|
10870
|
-
const generateUuid = dependencies.randomUUID ??
|
|
11143
|
+
const generateUuid = dependencies.randomUUID ?? randomUUID3;
|
|
10871
11144
|
const writeStderr = dependencies.stderr ?? ((payload) => process.stderr.write(`${payload}
|
|
10872
11145
|
`));
|
|
10873
11146
|
const webAppURL = dependencies.webAppURL ?? getWebAppURL;
|
|
@@ -10935,7 +11208,7 @@ function createCommandTelemetry(settings2, dependencies = {}) {
|
|
|
10935
11208
|
}
|
|
10936
11209
|
}
|
|
10937
11210
|
}
|
|
10938
|
-
if (!disabled && result === "failure" && error && sentryDsn) {
|
|
11211
|
+
if (!disabled && result === "failure" && error && shouldSendToSentry(error) && sentryDsn) {
|
|
10939
11212
|
const id = eventId(generateUuid);
|
|
10940
11213
|
const envelope = id ? buildSentryEnvelope({
|
|
10941
11214
|
dsn: sentryDsn,
|
|
@@ -10991,6 +11264,9 @@ function createCommandTelemetry(settings2, dependencies = {}) {
|
|
|
10991
11264
|
}
|
|
10992
11265
|
};
|
|
10993
11266
|
}
|
|
11267
|
+
function shouldSendToSentry(error) {
|
|
11268
|
+
return !["SESSION_EXPIRED", "SESSION_PERSISTENCE_ERROR"].includes(error.code ?? "");
|
|
11269
|
+
}
|
|
10994
11270
|
var REQUEST_TIMEOUT_MS = 500, MAX_RESPONSE_BYTES, MAX_STACK_FRAMES = 20, UNKNOWN_COMMAND = "unknown", FALLBACK_INSTALL_ID = "00000000-0000-4000-8000-000000000000", BUNDLE_CODE_FILE = "app:///bin/dosu.js", CLI_PACKAGE_ROOT, SAFE_ERROR_TYPES, SAFE_ERROR_CODES;
|
|
10995
11271
|
var init_telemetry = __esm(() => {
|
|
10996
11272
|
MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
@@ -11006,6 +11282,8 @@ var init_telemetry = __esm(() => {
|
|
|
11006
11282
|
"RangeError",
|
|
11007
11283
|
"ReferenceError",
|
|
11008
11284
|
"SessionExpiredError",
|
|
11285
|
+
"SessionPersistenceError",
|
|
11286
|
+
"SessionRefreshError",
|
|
11009
11287
|
"SyntaxError",
|
|
11010
11288
|
"TRPCClientError",
|
|
11011
11289
|
"TypeError"
|
|
@@ -11052,6 +11330,9 @@ var init_telemetry = __esm(() => {
|
|
|
11052
11330
|
"PAYMENT_REQUIRED",
|
|
11053
11331
|
"PRECONDITION_FAILED",
|
|
11054
11332
|
"SERVICE_UNAVAILABLE",
|
|
11333
|
+
"SESSION_EXPIRED",
|
|
11334
|
+
"SESSION_PERSISTENCE_ERROR",
|
|
11335
|
+
"SESSION_REFRESH_ERROR",
|
|
11055
11336
|
"TIMEOUT",
|
|
11056
11337
|
"TOO_MANY_REQUESTS",
|
|
11057
11338
|
"UNAUTHORIZED",
|
|
@@ -11363,11 +11644,11 @@ var init_agent_kickoff = __esm(() => {
|
|
|
11363
11644
|
});
|
|
11364
11645
|
|
|
11365
11646
|
// src/setup/logs-handoff.ts
|
|
11366
|
-
import { existsSync as
|
|
11647
|
+
import { existsSync as existsSync15, readdirSync, statSync as statSync3 } from "node:fs";
|
|
11367
11648
|
import { homedir as homedir5 } from "node:os";
|
|
11368
|
-
import { join as
|
|
11649
|
+
import { join as join26 } from "node:path";
|
|
11369
11650
|
function countJsonlFiles(root, cap = COUNT_CAP) {
|
|
11370
|
-
if (!
|
|
11651
|
+
if (!existsSync15(root))
|
|
11371
11652
|
return { count: 0, capped: false };
|
|
11372
11653
|
let count = 0;
|
|
11373
11654
|
const stack = [root];
|
|
@@ -11382,7 +11663,7 @@ function countJsonlFiles(root, cap = COUNT_CAP) {
|
|
|
11382
11663
|
continue;
|
|
11383
11664
|
}
|
|
11384
11665
|
for (const entry of entries) {
|
|
11385
|
-
const path3 =
|
|
11666
|
+
const path3 = join26(dir, entry.name);
|
|
11386
11667
|
if (entry.isDirectory()) {
|
|
11387
11668
|
stack.push(path3);
|
|
11388
11669
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -11396,23 +11677,23 @@ function countJsonlFiles(root, cap = COUNT_CAP) {
|
|
|
11396
11677
|
}
|
|
11397
11678
|
function detectLogSources(home = process.env.HOME || homedir5()) {
|
|
11398
11679
|
const roots = {
|
|
11399
|
-
cursor:
|
|
11400
|
-
claude:
|
|
11401
|
-
codex:
|
|
11680
|
+
cursor: join26(home, ".cursor", "projects"),
|
|
11681
|
+
claude: join26(home, ".claude", "projects"),
|
|
11682
|
+
codex: join26(home, ".codex", "sessions")
|
|
11402
11683
|
};
|
|
11403
11684
|
const hits = [];
|
|
11404
11685
|
for (const source of LOG_SOURCES) {
|
|
11405
11686
|
const root = roots[source];
|
|
11406
11687
|
if (source === "cursor") {
|
|
11407
|
-
if (!
|
|
11688
|
+
if (!existsSync15(root))
|
|
11408
11689
|
continue;
|
|
11409
11690
|
let count = 0;
|
|
11410
11691
|
let capped = false;
|
|
11411
11692
|
try {
|
|
11412
11693
|
for (const proj of readdirSync(root)) {
|
|
11413
|
-
const transcripts =
|
|
11694
|
+
const transcripts = join26(root, proj, "agent-transcripts");
|
|
11414
11695
|
try {
|
|
11415
|
-
if (!
|
|
11696
|
+
if (!statSync3(transcripts).isDirectory())
|
|
11416
11697
|
continue;
|
|
11417
11698
|
} catch {
|
|
11418
11699
|
continue;
|
|
@@ -11941,7 +12222,7 @@ async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}, onAuthUR
|
|
|
11941
12222
|
logger.debug("auth.flow", "Browser unavailable — returning to caller for fallback");
|
|
11942
12223
|
return { browserOpened: false };
|
|
11943
12224
|
}
|
|
11944
|
-
const timeoutMs = options.timeoutMs ??
|
|
12225
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
11945
12226
|
const timeoutMinutes = Math.round(timeoutMs / 60000);
|
|
11946
12227
|
const timeout = new Promise((_2, reject) => {
|
|
11947
12228
|
timeoutId = setTimeout(() => {
|
|
@@ -11969,11 +12250,11 @@ function buildAuthURL(callbackURL, path3, extraParams) {
|
|
|
11969
12250
|
const params = new URLSearchParams({ callback: callbackURL, ...extraParams });
|
|
11970
12251
|
return `${webAppURL}${path3}?${params}`;
|
|
11971
12252
|
}
|
|
11972
|
-
var
|
|
12253
|
+
var DEFAULT_TIMEOUT_MS2;
|
|
11973
12254
|
var init_flow = __esm(() => {
|
|
11974
12255
|
init_logger();
|
|
11975
12256
|
init_server();
|
|
11976
|
-
|
|
12257
|
+
DEFAULT_TIMEOUT_MS2 = 8 * 60 * 1000;
|
|
11977
12258
|
});
|
|
11978
12259
|
|
|
11979
12260
|
// src/setup/flow.ts
|
|
@@ -11986,12 +12267,12 @@ __export(exports_flow2, {
|
|
|
11986
12267
|
runInstallSkill: () => runInstallSkill,
|
|
11987
12268
|
cliAuthFailureReason: () => cliAuthFailureReason
|
|
11988
12269
|
});
|
|
11989
|
-
import { randomUUID as
|
|
12270
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
11990
12271
|
function trackInBackground(tracking) {
|
|
11991
12272
|
tracking.catch(() => {});
|
|
11992
12273
|
}
|
|
11993
12274
|
async function runSetup(opts = {}) {
|
|
11994
|
-
const onboardingRunID =
|
|
12275
|
+
const onboardingRunID = randomUUID4();
|
|
11995
12276
|
logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
|
|
11996
12277
|
intro("Dosu CLI Setup");
|
|
11997
12278
|
trackInBackground(trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_launch_attempted", {
|
|
@@ -12611,8 +12892,8 @@ var init_flow2 = __esm(() => {
|
|
|
12611
12892
|
});
|
|
12612
12893
|
|
|
12613
12894
|
// src/commands/insights.ts
|
|
12614
|
-
import { existsSync as
|
|
12615
|
-
import { dirname as dirname5, join as
|
|
12895
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readdirSync as readdirSync2, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
12896
|
+
import { dirname as dirname5, join as join27 } from "node:path";
|
|
12616
12897
|
function shuffled(arr) {
|
|
12617
12898
|
const copy2 = [...arr];
|
|
12618
12899
|
for (let i2 = copy2.length - 1;i2 > 0; i2--) {
|
|
@@ -12716,17 +12997,17 @@ function makeAskFn(cfg) {
|
|
|
12716
12997
|
};
|
|
12717
12998
|
}
|
|
12718
12999
|
function insightsDir() {
|
|
12719
|
-
return
|
|
13000
|
+
return join27(getConfigDir(), "insights");
|
|
12720
13001
|
}
|
|
12721
13002
|
function reportPath(timestamp) {
|
|
12722
13003
|
const dir = insightsDir();
|
|
12723
13004
|
if (!timestamp)
|
|
12724
|
-
return
|
|
13005
|
+
return join27(dir, "latest.html");
|
|
12725
13006
|
const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
|
|
12726
|
-
return
|
|
13007
|
+
return join27(dir, `report-${iso}Z.html`);
|
|
12727
13008
|
}
|
|
12728
13009
|
function pruneOldReports(dir, keepN) {
|
|
12729
|
-
if (!
|
|
13010
|
+
if (!existsSync16(dir))
|
|
12730
13011
|
return;
|
|
12731
13012
|
let entries;
|
|
12732
13013
|
try {
|
|
@@ -12738,7 +13019,7 @@ function pruneOldReports(dir, keepN) {
|
|
|
12738
13019
|
const reports = entries.filter((f2) => REPORT_FILE_PATTERN.test(f2)).sort().reverse();
|
|
12739
13020
|
for (const f2 of reports.slice(keepN)) {
|
|
12740
13021
|
try {
|
|
12741
|
-
|
|
13022
|
+
unlinkSync4(join27(dir, f2));
|
|
12742
13023
|
} catch (err) {
|
|
12743
13024
|
logger.debug("insights", `failed to prune ${f2}: ${err instanceof Error ? err.message : err}`);
|
|
12744
13025
|
}
|
|
@@ -12811,9 +13092,9 @@ function defaultRunner(cfg) {
|
|
|
12811
13092
|
render: renderHTML,
|
|
12812
13093
|
writeFile: (path3, content) => {
|
|
12813
13094
|
const dir = dirname5(path3);
|
|
12814
|
-
if (!
|
|
12815
|
-
|
|
12816
|
-
|
|
13095
|
+
if (!existsSync16(dir))
|
|
13096
|
+
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
13097
|
+
writeFileSync10(path3, content, { mode: 384 });
|
|
12817
13098
|
},
|
|
12818
13099
|
prune: pruneOldReports,
|
|
12819
13100
|
openInBrowser: async (path3) => {
|
|
@@ -13644,13 +13925,13 @@ var init_flow3 = __esm(() => {
|
|
|
13644
13925
|
init_commander();
|
|
13645
13926
|
init_client();
|
|
13646
13927
|
import {
|
|
13647
|
-
closeSync,
|
|
13928
|
+
closeSync as closeSync2,
|
|
13648
13929
|
constants,
|
|
13649
13930
|
fstatSync,
|
|
13650
|
-
openSync,
|
|
13651
|
-
readFileSync as
|
|
13931
|
+
openSync as openSync2,
|
|
13932
|
+
readFileSync as readFileSync15,
|
|
13652
13933
|
readSync,
|
|
13653
|
-
unlinkSync as
|
|
13934
|
+
unlinkSync as unlinkSync5
|
|
13654
13935
|
} from "node:fs";
|
|
13655
13936
|
|
|
13656
13937
|
// src/commands/analytics.ts
|
|
@@ -13874,8 +14155,8 @@ init_commander();
|
|
|
13874
14155
|
init_trpc();
|
|
13875
14156
|
init_logger();
|
|
13876
14157
|
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
13877
|
-
import { existsSync as
|
|
13878
|
-
import { dirname, join as
|
|
14158
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, rmSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
14159
|
+
import { dirname, join as join5 } from "node:path";
|
|
13879
14160
|
|
|
13880
14161
|
// src/setup/github-step.ts
|
|
13881
14162
|
init_dist8();
|
|
@@ -14743,20 +15024,20 @@ ${dim(`deployment ${deployment_id}`)}`);
|
|
|
14743
15024
|
init_config();
|
|
14744
15025
|
init_logger();
|
|
14745
15026
|
var import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
14746
|
-
import { existsSync as
|
|
14747
|
-
import { join as
|
|
15027
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
15028
|
+
import { join as join4 } from "node:path";
|
|
14748
15029
|
var CACHE_FILENAME = "pending-tasks.json";
|
|
14749
15030
|
var CHECK_INTERVAL_MS = 60000;
|
|
14750
15031
|
var FETCH_TIMEOUT_MS = 5000;
|
|
14751
15032
|
function getCachePath() {
|
|
14752
|
-
return
|
|
15033
|
+
return join4(getConfigDir(), CACHE_FILENAME);
|
|
14753
15034
|
}
|
|
14754
15035
|
function readPendingTasks() {
|
|
14755
15036
|
try {
|
|
14756
15037
|
const path3 = getCachePath();
|
|
14757
|
-
if (!
|
|
15038
|
+
if (!existsSync4(path3))
|
|
14758
15039
|
return { tasks: [] };
|
|
14759
|
-
const data = JSON.parse(
|
|
15040
|
+
const data = JSON.parse(readFileSync4(path3, "utf-8"));
|
|
14760
15041
|
if (Array.isArray(data?.tasks)) {
|
|
14761
15042
|
return { tasks: data.tasks };
|
|
14762
15043
|
}
|
|
@@ -14768,10 +15049,10 @@ function readPendingTasks() {
|
|
|
14768
15049
|
function writePendingTasks(cache) {
|
|
14769
15050
|
try {
|
|
14770
15051
|
const dir = getConfigDir();
|
|
14771
|
-
if (!
|
|
14772
|
-
|
|
15052
|
+
if (!existsSync4(dir)) {
|
|
15053
|
+
mkdirSync4(dir, { recursive: true, mode: 448 });
|
|
14773
15054
|
}
|
|
14774
|
-
|
|
15055
|
+
writeFileSync4(getCachePath(), JSON.stringify(cache), { mode: 384 });
|
|
14775
15056
|
} catch {}
|
|
14776
15057
|
}
|
|
14777
15058
|
function addPendingTask(task) {
|
|
@@ -15010,12 +15291,12 @@ function loadFindings(findingsPath) {
|
|
|
15010
15291
|
console.error(import_picocolors9.default.red("Run the Dosu audit in your coding agent first (it writes .dosu/audit.json)."));
|
|
15011
15292
|
process.exit(1);
|
|
15012
15293
|
};
|
|
15013
|
-
if (!
|
|
15294
|
+
if (!existsSync5(findingsPath)) {
|
|
15014
15295
|
fail();
|
|
15015
15296
|
}
|
|
15016
15297
|
let parsed;
|
|
15017
15298
|
try {
|
|
15018
|
-
parsed = JSON.parse(
|
|
15299
|
+
parsed = JSON.parse(readFileSync5(findingsPath, "utf-8"));
|
|
15019
15300
|
} catch {
|
|
15020
15301
|
fail();
|
|
15021
15302
|
}
|
|
@@ -15025,21 +15306,21 @@ function loadFindings(findingsPath) {
|
|
|
15025
15306
|
return parsed;
|
|
15026
15307
|
}
|
|
15027
15308
|
function cleanupFindings(findingsPath, cwd = process.cwd()) {
|
|
15028
|
-
const gitignorePath =
|
|
15309
|
+
const gitignorePath = join5(cwd, ".gitignore");
|
|
15029
15310
|
try {
|
|
15030
|
-
const content =
|
|
15311
|
+
const content = existsSync5(gitignorePath) ? readFileSync5(gitignorePath, "utf-8") : "";
|
|
15031
15312
|
const hasEntry = content.split(/\r?\n/).some((line) => /^\.dosu\/?$/.test(line.trim()));
|
|
15032
15313
|
if (!hasEntry) {
|
|
15033
15314
|
const sep = content === "" || content.endsWith(`
|
|
15034
15315
|
`) ? "" : `
|
|
15035
15316
|
`;
|
|
15036
|
-
|
|
15317
|
+
writeFileSync5(gitignorePath, `${content}${sep}.dosu/
|
|
15037
15318
|
`);
|
|
15038
15319
|
}
|
|
15039
15320
|
} catch (err) {
|
|
15040
15321
|
logger.warn("audit", `could not update .gitignore: ${errText(err)}`);
|
|
15041
15322
|
}
|
|
15042
|
-
const defaultDir =
|
|
15323
|
+
const defaultDir = join5(cwd, ".dosu");
|
|
15043
15324
|
if (dirname(findingsPath) !== defaultDir)
|
|
15044
15325
|
return;
|
|
15045
15326
|
try {
|
|
@@ -15082,7 +15363,7 @@ function auditCommand() {
|
|
|
15082
15363
|
const nonInteractive = Boolean(opts.tasks);
|
|
15083
15364
|
const client = createTypedClient(cfg);
|
|
15084
15365
|
const dataSourceId = await ensureSyncedRepo(cfg, client, detected, opts.dataSourceId, nonInteractive);
|
|
15085
|
-
const findingsPath = opts.findings ??
|
|
15366
|
+
const findingsPath = opts.findings ?? join5(process.cwd(), ".dosu", "audit.json");
|
|
15086
15367
|
const findings = loadFindings(findingsPath);
|
|
15087
15368
|
if (!opts.dataSourceId && findings.repo?.slug && findings.repo.slug !== detected.slug) {
|
|
15088
15369
|
console.error(import_picocolors9.default.red(`Audit was run on ${findings.repo.slug}, but the current repo is ${detected.slug}. ` + `Run 'dosu audit' from ${findings.repo.slug} so the PR targets the audited repo.`));
|
|
@@ -15257,7 +15538,7 @@ init_commander();
|
|
|
15257
15538
|
init_trpc();
|
|
15258
15539
|
init_logger();
|
|
15259
15540
|
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
15260
|
-
import { readFileSync as
|
|
15541
|
+
import { readFileSync as readFileSync6 } from "node:fs";
|
|
15261
15542
|
function requireConfig5() {
|
|
15262
15543
|
const cfg = requireLoginConfig();
|
|
15263
15544
|
if (!cfg.active_account?.target?.space_id) {
|
|
@@ -15278,7 +15559,7 @@ async function getKnowledgeStoreId(client, spaceId) {
|
|
|
15278
15559
|
}
|
|
15279
15560
|
function readBody(opts) {
|
|
15280
15561
|
if (opts.bodyFile)
|
|
15281
|
-
return
|
|
15562
|
+
return readFileSync6(opts.bodyFile, "utf-8");
|
|
15282
15563
|
return opts.body;
|
|
15283
15564
|
}
|
|
15284
15565
|
var IMPORT_ALREADY_IN_PROGRESS_CODE = "IMPORT_ALREADY_IN_PROGRESS";
|
|
@@ -16012,7 +16293,7 @@ init_dist();
|
|
|
16012
16293
|
init_commander();
|
|
16013
16294
|
init_trpc();
|
|
16014
16295
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
16015
|
-
import { readFileSync as
|
|
16296
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
16016
16297
|
function requireConfig10() {
|
|
16017
16298
|
return requireLoginConfig();
|
|
16018
16299
|
}
|
|
@@ -16188,7 +16469,7 @@ function reviewCommand() {
|
|
|
16188
16469
|
let body = opts.body;
|
|
16189
16470
|
if (opts.bodyFile) {
|
|
16190
16471
|
try {
|
|
16191
|
-
body =
|
|
16472
|
+
body = readFileSync13(opts.bodyFile, "utf-8");
|
|
16192
16473
|
} catch (err) {
|
|
16193
16474
|
console.error(import_picocolors19.default.red(`Failed to read --body-file: ${err.message}`));
|
|
16194
16475
|
process.exit(1);
|
|
@@ -16977,8 +17258,8 @@ init_skill_update_check();
|
|
|
16977
17258
|
init_config();
|
|
16978
17259
|
init_logger();
|
|
16979
17260
|
var import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
16980
|
-
import { existsSync as
|
|
16981
|
-
import { join as
|
|
17261
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
|
|
17262
|
+
import { join as join28 } from "node:path";
|
|
16982
17263
|
var CACHE_FILENAME3 = "update-check.json";
|
|
16983
17264
|
var CHECK_INTERVAL_MS3 = 6 * 60 * 60 * 1000;
|
|
16984
17265
|
var FETCH_TIMEOUT_MS3 = 1000;
|
|
@@ -17005,14 +17286,14 @@ function isNewerVersion(latest, current) {
|
|
|
17005
17286
|
return false;
|
|
17006
17287
|
}
|
|
17007
17288
|
function getCachePath3() {
|
|
17008
|
-
return
|
|
17289
|
+
return join28(getConfigDir(), CACHE_FILENAME3);
|
|
17009
17290
|
}
|
|
17010
17291
|
function readCache() {
|
|
17011
17292
|
try {
|
|
17012
17293
|
const path3 = getCachePath3();
|
|
17013
|
-
if (!
|
|
17294
|
+
if (!existsSync17(path3))
|
|
17014
17295
|
return null;
|
|
17015
|
-
const data = JSON.parse(
|
|
17296
|
+
const data = JSON.parse(readFileSync14(path3, "utf-8"));
|
|
17016
17297
|
if (typeof data.lastCheck === "number" && isValidVersion(data.latestVersion)) {
|
|
17017
17298
|
return data;
|
|
17018
17299
|
}
|
|
@@ -17024,10 +17305,10 @@ function readCache() {
|
|
|
17024
17305
|
function writeCache(cache) {
|
|
17025
17306
|
try {
|
|
17026
17307
|
const dir = getConfigDir();
|
|
17027
|
-
if (!
|
|
17028
|
-
|
|
17308
|
+
if (!existsSync17(dir)) {
|
|
17309
|
+
mkdirSync10(dir, { recursive: true, mode: 448 });
|
|
17029
17310
|
}
|
|
17030
|
-
|
|
17311
|
+
writeFileSync11(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
17031
17312
|
} catch {}
|
|
17032
17313
|
}
|
|
17033
17314
|
async function fetchLatestVersion() {
|
|
@@ -17162,7 +17443,7 @@ function loadConfigForTelemetry() {
|
|
|
17162
17443
|
let fd;
|
|
17163
17444
|
try {
|
|
17164
17445
|
const nonblocking = typeof constants.O_NONBLOCK === "number" ? constants.O_NONBLOCK : 0;
|
|
17165
|
-
fd =
|
|
17446
|
+
fd = openSync2(getConfigPath(), constants.O_RDONLY | nonblocking);
|
|
17166
17447
|
const file = fstatSync(fd);
|
|
17167
17448
|
if (!file.isFile() || file.size > MAX_TELEMETRY_CONFIG_BYTES)
|
|
17168
17449
|
return;
|
|
@@ -17176,7 +17457,7 @@ function loadConfigForTelemetry() {
|
|
|
17176
17457
|
} finally {
|
|
17177
17458
|
if (fd !== undefined) {
|
|
17178
17459
|
try {
|
|
17179
|
-
|
|
17460
|
+
closeSync2(fd);
|
|
17180
17461
|
} catch {}
|
|
17181
17462
|
}
|
|
17182
17463
|
}
|
|
@@ -17541,7 +17822,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
17541
17822
|
const logPath = logger.getLogPath();
|
|
17542
17823
|
if (opts.clear) {
|
|
17543
17824
|
try {
|
|
17544
|
-
|
|
17825
|
+
unlinkSync5(logPath);
|
|
17545
17826
|
console.log("Log file deleted.");
|
|
17546
17827
|
} catch {
|
|
17547
17828
|
console.log("No log file to delete.");
|
|
@@ -17551,7 +17832,7 @@ Use 'dosu mcp add <agent>' to add Dosu MCP to a tool.`);
|
|
|
17551
17832
|
if (opts.tail !== undefined) {
|
|
17552
17833
|
const n2 = typeof opts.tail === "string" ? parseInt(opts.tail, 10) || 50 : 50;
|
|
17553
17834
|
try {
|
|
17554
|
-
const content =
|
|
17835
|
+
const content = readFileSync15(logPath, "utf-8");
|
|
17555
17836
|
const lines = content.split(`
|
|
17556
17837
|
`);
|
|
17557
17838
|
console.log(lines.slice(-n2).join(`
|
|
@@ -17617,4 +17898,4 @@ execute().catch((err) => {
|
|
|
17617
17898
|
process.exit(1);
|
|
17618
17899
|
});
|
|
17619
17900
|
|
|
17620
|
-
//# debugId=
|
|
17901
|
+
//# debugId=20790a5a-a63f-06a4-6475-6e2164756e21
|