repowise 0.1.91 → 0.1.92
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/dist/bin/repowise.js +315 -74
- package/package.json +1 -1
package/dist/bin/repowise.js
CHANGED
|
@@ -3015,7 +3015,7 @@ var init_telemetry = __esm({
|
|
|
3015
3015
|
// bin/repowise.ts
|
|
3016
3016
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3017
3017
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3018
|
-
import { dirname as
|
|
3018
|
+
import { dirname as dirname21, join as join60 } from "path";
|
|
3019
3019
|
import { Command } from "commander";
|
|
3020
3020
|
|
|
3021
3021
|
// ../listener/dist/main.js
|
|
@@ -10986,6 +10986,40 @@ async function startListener() {
|
|
|
10986
10986
|
pollCycleCount++;
|
|
10987
10987
|
const shouldReconcile = pollCycleCount % RECONCILE_EVERY_N_CYCLES === 0;
|
|
10988
10988
|
let latestCliVersion;
|
|
10989
|
+
try {
|
|
10990
|
+
const freshRepos = (await getListenerConfig()).repos;
|
|
10991
|
+
const known = /* @__PURE__ */ new Set();
|
|
10992
|
+
for (const g of groups) {
|
|
10993
|
+
for (const id of g.repoLocalPaths.keys())
|
|
10994
|
+
known.add(id);
|
|
10995
|
+
}
|
|
10996
|
+
const newRepos = freshRepos.filter((r) => r.localPath && !known.has(r.repoId));
|
|
10997
|
+
if (newRepos.length > 0) {
|
|
10998
|
+
config2.repos = freshRepos;
|
|
10999
|
+
for (const g of groups) {
|
|
11000
|
+
g.repoIds = freshRepos.filter((r) => (r.apiUrl ?? config2.defaultApiUrl) === g.apiUrl).map((r) => r.repoId);
|
|
11001
|
+
g.repoLocalPaths.clear();
|
|
11002
|
+
for (const r of freshRepos) {
|
|
11003
|
+
if ((r.apiUrl ?? config2.defaultApiUrl) === g.apiUrl) {
|
|
11004
|
+
g.repoLocalPaths.set(r.repoId, r.localPath);
|
|
11005
|
+
}
|
|
11006
|
+
}
|
|
11007
|
+
}
|
|
11008
|
+
if (mcpRuntime) {
|
|
11009
|
+
mcpRuntime.updateRepos(freshRepos.map((r) => ({
|
|
11010
|
+
repoId: r.repoId,
|
|
11011
|
+
apiUrl: r.apiUrl ?? config2.defaultApiUrl,
|
|
11012
|
+
...r.localPath ? { localPath: r.localPath } : {}
|
|
11013
|
+
})));
|
|
11014
|
+
}
|
|
11015
|
+
console.log(`[config-sync] wired ${newRepos.length} newly-registered repo(s)`);
|
|
11016
|
+
if (config2.lspEnabled !== false && config2.lspAutoWarm !== false && mcpRuntime?.lspWorkspaces) {
|
|
11017
|
+
void warmReposLsp(newRepos, mcpRuntime.lspWorkspaces, config2.lspOverrides).catch(() => {
|
|
11018
|
+
});
|
|
11019
|
+
}
|
|
11020
|
+
}
|
|
11021
|
+
} catch {
|
|
11022
|
+
}
|
|
10989
11023
|
for (const group of groups) {
|
|
10990
11024
|
if (!running)
|
|
10991
11025
|
break;
|
|
@@ -11161,6 +11195,20 @@ async function startListener() {
|
|
|
11161
11195
|
} catch (err) {
|
|
11162
11196
|
console.warn("[mcp-config] Reconciliation failed:", err instanceof Error ? err.message : String(err));
|
|
11163
11197
|
}
|
|
11198
|
+
if (mcpRuntime) {
|
|
11199
|
+
try {
|
|
11200
|
+
const polled = await mcpRuntime.pollDownloads();
|
|
11201
|
+
for (const r of polled) {
|
|
11202
|
+
if (r.state === "downloaded") {
|
|
11203
|
+
console.log(`[mcp] Refreshed graph for ${r.repoId} (periodic safety-net)`);
|
|
11204
|
+
} else if (r.state === "error") {
|
|
11205
|
+
console.warn(`[mcp] Periodic graph fetch failed for ${r.repoId}: ${r.message ?? ""}`);
|
|
11206
|
+
}
|
|
11207
|
+
}
|
|
11208
|
+
} catch (err) {
|
|
11209
|
+
console.warn("[mcp] Periodic graph safety-net poll failed:", err instanceof Error ? err.message : String(err));
|
|
11210
|
+
}
|
|
11211
|
+
}
|
|
11164
11212
|
}
|
|
11165
11213
|
if (latestCliVersion && currentVersion && !config2.noAutoUpdate && (state.crashCount ?? 0) < CRASH_LOOP_THRESHOLD) {
|
|
11166
11214
|
if (latestCliVersion !== state.lastUpdateTargetVersion) {
|
|
@@ -11399,8 +11447,8 @@ async function showWelcome(currentVersion) {
|
|
|
11399
11447
|
}
|
|
11400
11448
|
|
|
11401
11449
|
// src/commands/create.ts
|
|
11402
|
-
import { mkdirSync, writeFileSync as
|
|
11403
|
-
import { dirname as
|
|
11450
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
11451
|
+
import { dirname as dirname17, join as join48 } from "path";
|
|
11404
11452
|
init_src();
|
|
11405
11453
|
import chalk8 from "chalk";
|
|
11406
11454
|
import ora from "ora";
|
|
@@ -11818,6 +11866,130 @@ function ensureGitignore(repoRoot, entry) {
|
|
|
11818
11866
|
}
|
|
11819
11867
|
}
|
|
11820
11868
|
|
|
11869
|
+
// src/lib/graph-cache.ts
|
|
11870
|
+
init_config_dir();
|
|
11871
|
+
import { mkdirSync, writeFileSync as writeFileSync2, renameSync, unlinkSync } from "fs";
|
|
11872
|
+
import { dirname as dirname16, join as join45 } from "path";
|
|
11873
|
+
var SAFE_REPO_ID = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
11874
|
+
function assertSafeRepoId2(repoId) {
|
|
11875
|
+
if (!repoId || typeof repoId !== "string" || !SAFE_REPO_ID.test(repoId) || repoId === "." || repoId === ".." || repoId.startsWith(".")) {
|
|
11876
|
+
throw new Error(`invalid repoId: ${String(repoId)}`);
|
|
11877
|
+
}
|
|
11878
|
+
}
|
|
11879
|
+
function graphCachePath(repoId) {
|
|
11880
|
+
assertSafeRepoId2(repoId);
|
|
11881
|
+
return join45(getConfigDir(), "graphs", `${repoId}.json`);
|
|
11882
|
+
}
|
|
11883
|
+
function isUsableGraph(parsed) {
|
|
11884
|
+
if (typeof parsed !== "object" || parsed === null) return false;
|
|
11885
|
+
const g = parsed;
|
|
11886
|
+
if (typeof g.commitSha !== "string" || g.commitSha.length === 0) return false;
|
|
11887
|
+
const nodeCount = Array.isArray(g.nodes) ? g.nodes.length : 0;
|
|
11888
|
+
const edgeCount = Array.isArray(g.edges) ? g.edges.length : 0;
|
|
11889
|
+
return nodeCount > 0 || edgeCount > 0;
|
|
11890
|
+
}
|
|
11891
|
+
function readErrorCode(body) {
|
|
11892
|
+
try {
|
|
11893
|
+
const parsed = JSON.parse(body);
|
|
11894
|
+
return parsed.code ?? parsed.error?.code;
|
|
11895
|
+
} catch {
|
|
11896
|
+
return void 0;
|
|
11897
|
+
}
|
|
11898
|
+
}
|
|
11899
|
+
async function ensureGraphDownloaded(opts) {
|
|
11900
|
+
const fetchFn = opts.fetchFn ?? fetch;
|
|
11901
|
+
const timeoutMs = opts.timeoutMs ?? 1e4;
|
|
11902
|
+
const maxRetries = opts.maxRetries ?? 3;
|
|
11903
|
+
const sleep2 = opts.sleepFn ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
11904
|
+
let targetPath;
|
|
11905
|
+
try {
|
|
11906
|
+
targetPath = graphCachePath(opts.repoId);
|
|
11907
|
+
} catch (err) {
|
|
11908
|
+
return { status: "error", message: err instanceof Error ? err.message : String(err) };
|
|
11909
|
+
}
|
|
11910
|
+
const url = `${opts.apiUrl.replace(/\/+$/, "")}/v1/repos/${encodeURIComponent(opts.repoId)}/graph`;
|
|
11911
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
11912
|
+
const ctrl = new AbortController();
|
|
11913
|
+
const timer = setTimeout(() => {
|
|
11914
|
+
ctrl.abort();
|
|
11915
|
+
}, timeoutMs);
|
|
11916
|
+
let res;
|
|
11917
|
+
try {
|
|
11918
|
+
res = await fetchFn(url, {
|
|
11919
|
+
headers: { Authorization: `Bearer ${opts.accessToken}` },
|
|
11920
|
+
signal: ctrl.signal
|
|
11921
|
+
});
|
|
11922
|
+
} catch (err) {
|
|
11923
|
+
clearTimeout(timer);
|
|
11924
|
+
if (attempt < maxRetries) {
|
|
11925
|
+
await sleep2(2e3 * attempt);
|
|
11926
|
+
continue;
|
|
11927
|
+
}
|
|
11928
|
+
return { status: "error", message: err instanceof Error ? err.message : String(err) };
|
|
11929
|
+
}
|
|
11930
|
+
clearTimeout(timer);
|
|
11931
|
+
if (res.status === 404) {
|
|
11932
|
+
let code = "GRAPH_NOT_FOUND";
|
|
11933
|
+
try {
|
|
11934
|
+
const c = readErrorCode(await res.text());
|
|
11935
|
+
if (c) code = c;
|
|
11936
|
+
} catch {
|
|
11937
|
+
}
|
|
11938
|
+
return { status: "not_found", message: code };
|
|
11939
|
+
}
|
|
11940
|
+
if (res.status >= 500) {
|
|
11941
|
+
let code;
|
|
11942
|
+
try {
|
|
11943
|
+
code = readErrorCode(await res.text());
|
|
11944
|
+
} catch {
|
|
11945
|
+
}
|
|
11946
|
+
if (code === "NO_BUCKET" || code === "REPO_NOT_FOUND" || code === "RepoNotFound") {
|
|
11947
|
+
return { status: "misconfig", message: code };
|
|
11948
|
+
}
|
|
11949
|
+
if (attempt < maxRetries) {
|
|
11950
|
+
await sleep2(2e3 * attempt);
|
|
11951
|
+
continue;
|
|
11952
|
+
}
|
|
11953
|
+
return { status: "error", message: `HTTP ${String(res.status)}` };
|
|
11954
|
+
}
|
|
11955
|
+
if (!res.ok) {
|
|
11956
|
+
return { status: "error", message: `HTTP ${String(res.status)}` };
|
|
11957
|
+
}
|
|
11958
|
+
const body = await res.text();
|
|
11959
|
+
let parsed;
|
|
11960
|
+
try {
|
|
11961
|
+
parsed = JSON.parse(body);
|
|
11962
|
+
} catch {
|
|
11963
|
+
if (attempt < maxRetries) {
|
|
11964
|
+
await sleep2(2e3 * attempt);
|
|
11965
|
+
continue;
|
|
11966
|
+
}
|
|
11967
|
+
return { status: "error", message: "graph parse failed" };
|
|
11968
|
+
}
|
|
11969
|
+
if (!isUsableGraph(parsed)) {
|
|
11970
|
+
return { status: "not_found", message: "EMPTY_GRAPH" };
|
|
11971
|
+
}
|
|
11972
|
+
try {
|
|
11973
|
+
mkdirSync(dirname16(targetPath), { recursive: true });
|
|
11974
|
+
const tmp = `${targetPath}.${String(process.pid)}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
11975
|
+
try {
|
|
11976
|
+
writeFileSync2(tmp, body, { encoding: "utf-8", mode: 384 });
|
|
11977
|
+
renameSync(tmp, targetPath);
|
|
11978
|
+
} catch (e) {
|
|
11979
|
+
try {
|
|
11980
|
+
unlinkSync(tmp);
|
|
11981
|
+
} catch {
|
|
11982
|
+
}
|
|
11983
|
+
throw e;
|
|
11984
|
+
}
|
|
11985
|
+
} catch (err) {
|
|
11986
|
+
return { status: "error", message: err instanceof Error ? err.message : String(err) };
|
|
11987
|
+
}
|
|
11988
|
+
return { status: "downloaded", bytes: Buffer.byteLength(body) };
|
|
11989
|
+
}
|
|
11990
|
+
return { status: "error", message: "exhausted retries" };
|
|
11991
|
+
}
|
|
11992
|
+
|
|
11821
11993
|
// src/lib/git.ts
|
|
11822
11994
|
import { execSync as execSync2 } from "child_process";
|
|
11823
11995
|
function detectRepoRoot() {
|
|
@@ -12371,7 +12543,7 @@ import chalk6 from "chalk";
|
|
|
12371
12543
|
|
|
12372
12544
|
// src/lib/dep-installer.ts
|
|
12373
12545
|
import { promises as fs21 } from "fs";
|
|
12374
|
-
import { join as
|
|
12546
|
+
import { join as join46 } from "path";
|
|
12375
12547
|
var SUPPORTED_DEP_LANGUAGES = /* @__PURE__ */ new Set([
|
|
12376
12548
|
"typescript",
|
|
12377
12549
|
"javascript",
|
|
@@ -12388,7 +12560,7 @@ var exists = async (p) => {
|
|
|
12388
12560
|
}
|
|
12389
12561
|
};
|
|
12390
12562
|
async function fileExists16(repoRoot, name) {
|
|
12391
|
-
return exists(
|
|
12563
|
+
return exists(join46(repoRoot, name));
|
|
12392
12564
|
}
|
|
12393
12565
|
async function detectNodePackageManager(repoRoot) {
|
|
12394
12566
|
if (await fileExists16(repoRoot, "pnpm-lock.yaml")) {
|
|
@@ -12466,11 +12638,11 @@ async function detectMissingDeps(repoRoot, scopedLanguages) {
|
|
|
12466
12638
|
import { spawn as spawn11 } from "child_process";
|
|
12467
12639
|
import { createWriteStream as createWriteStream3 } from "fs";
|
|
12468
12640
|
import { promises as fs22 } from "fs";
|
|
12469
|
-
import { join as
|
|
12641
|
+
import { join as join47 } from "path";
|
|
12470
12642
|
var DEFAULT_INSTALL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
12471
12643
|
async function runMissingDepInstalls(opts) {
|
|
12472
12644
|
const safeRepoId = opts.repoId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
12473
|
-
const logPath2 =
|
|
12645
|
+
const logPath2 = join47(getConfigDir2(), `install-log.${safeRepoId}.txt`);
|
|
12474
12646
|
await fs22.mkdir(getConfigDir2(), { recursive: true });
|
|
12475
12647
|
const stream = opts.logStream ?? createWriteStream3(logPath2, { flags: "a" });
|
|
12476
12648
|
stream.on("error", () => {
|
|
@@ -12517,7 +12689,7 @@ async function runOne2(dep, repoRoot, stream, timeoutMs) {
|
|
|
12517
12689
|
}
|
|
12518
12690
|
async function runPipFlow(repoRoot, stream, timeoutMs) {
|
|
12519
12691
|
await runSimple(["python3", "-m", "venv", ".venv"], repoRoot, stream, timeoutMs);
|
|
12520
|
-
const venvPip = process.platform === "win32" ?
|
|
12692
|
+
const venvPip = process.platform === "win32" ? join47(".venv", "Scripts", "pip.exe") : join47(".venv", "bin", "pip");
|
|
12521
12693
|
await runSimple([venvPip, "install", "-r", "requirements.txt"], repoRoot, stream, timeoutMs);
|
|
12522
12694
|
}
|
|
12523
12695
|
function runSimple(cmd, repoRoot, stream, timeoutMs) {
|
|
@@ -12684,6 +12856,17 @@ function formatElapsed(ms) {
|
|
|
12684
12856
|
var POLL_INTERVAL_MS = 3e3;
|
|
12685
12857
|
var MAX_POLL_ATTEMPTS = 7200;
|
|
12686
12858
|
var DEFAULT_CONTEXT_FOLDER = "repowise-context";
|
|
12859
|
+
function buildWatchedRepoEntry(args) {
|
|
12860
|
+
const entry = {
|
|
12861
|
+
repoId: args.repoId,
|
|
12862
|
+
localPath: args.localPath,
|
|
12863
|
+
apiUrl: getEnvConfig().apiUrl
|
|
12864
|
+
};
|
|
12865
|
+
if (args.platform) entry.platform = args.platform;
|
|
12866
|
+
if (args.externalId) entry.externalId = args.externalId;
|
|
12867
|
+
if (args.autoInstallDeps !== void 0) entry.autoInstallDeps = args.autoInstallDeps;
|
|
12868
|
+
return entry;
|
|
12869
|
+
}
|
|
12687
12870
|
async function create() {
|
|
12688
12871
|
const startTime = Date.now();
|
|
12689
12872
|
const spinner = ora("Checking authentication...").start();
|
|
@@ -12834,6 +13017,26 @@ async function create() {
|
|
|
12834
13017
|
)
|
|
12835
13018
|
);
|
|
12836
13019
|
}
|
|
13020
|
+
if (repoRoot) {
|
|
13021
|
+
try {
|
|
13022
|
+
const earlyConfig = {
|
|
13023
|
+
aiTools: tools,
|
|
13024
|
+
contextFolder: DEFAULT_CONTEXT_FOLDER,
|
|
13025
|
+
repos: [
|
|
13026
|
+
buildWatchedRepoEntry({
|
|
13027
|
+
repoId,
|
|
13028
|
+
localPath: repoRoot,
|
|
13029
|
+
platform: repoPlatform,
|
|
13030
|
+
externalId: repoExternalId
|
|
13031
|
+
})
|
|
13032
|
+
]
|
|
13033
|
+
};
|
|
13034
|
+
await mergeAndSaveConfig(earlyConfig);
|
|
13035
|
+
await ensureListenerRunning().catch(() => {
|
|
13036
|
+
});
|
|
13037
|
+
} catch {
|
|
13038
|
+
}
|
|
13039
|
+
}
|
|
12837
13040
|
const contextStorage = "server";
|
|
12838
13041
|
spinner.start("Starting context generation pipeline...");
|
|
12839
13042
|
let syncId = "";
|
|
@@ -13028,8 +13231,8 @@ async function create() {
|
|
|
13028
13231
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
13029
13232
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
13030
13233
|
if (files.length > 0) {
|
|
13031
|
-
const contextDir =
|
|
13032
|
-
|
|
13234
|
+
const contextDir = join48(repoRoot, DEFAULT_CONTEXT_FOLDER);
|
|
13235
|
+
mkdirSync2(contextDir, { recursive: true });
|
|
13033
13236
|
let downloadedCount = 0;
|
|
13034
13237
|
let failedCount = 0;
|
|
13035
13238
|
for (const file of files) {
|
|
@@ -13042,9 +13245,9 @@ async function create() {
|
|
|
13042
13245
|
const response = await fetch(presignedUrl);
|
|
13043
13246
|
if (response.ok) {
|
|
13044
13247
|
const content = await response.text();
|
|
13045
|
-
const filePath =
|
|
13046
|
-
|
|
13047
|
-
|
|
13248
|
+
const filePath = join48(contextDir, file.fileName);
|
|
13249
|
+
mkdirSync2(dirname17(filePath), { recursive: true });
|
|
13250
|
+
writeFileSync3(filePath, content, "utf-8");
|
|
13048
13251
|
downloadedCount++;
|
|
13049
13252
|
} else {
|
|
13050
13253
|
failedCount++;
|
|
@@ -13074,6 +13277,44 @@ Files are stored on our servers (not in git). Retry when online.`
|
|
|
13074
13277
|
);
|
|
13075
13278
|
}
|
|
13076
13279
|
}
|
|
13280
|
+
if (repoRoot) {
|
|
13281
|
+
spinner.start("Downloading code graph...");
|
|
13282
|
+
const graphCreds = await getValidCredentials2();
|
|
13283
|
+
if (!graphCreds) {
|
|
13284
|
+
spinner.warn(chalk8.yellow("Skipped code graph \u2014 run `repowise login` and retry."));
|
|
13285
|
+
} else {
|
|
13286
|
+
const graphResult = await ensureGraphDownloaded({
|
|
13287
|
+
repoId,
|
|
13288
|
+
accessToken: graphCreds.accessToken,
|
|
13289
|
+
apiUrl: getEnvConfig().apiUrl
|
|
13290
|
+
});
|
|
13291
|
+
if (graphResult.status === "downloaded") {
|
|
13292
|
+
spinner.succeed("Code graph ready \u2014 MCP enabled.");
|
|
13293
|
+
} else if (graphResult.status === "not_found") {
|
|
13294
|
+
if (graphOnly) {
|
|
13295
|
+
spinner.warn(
|
|
13296
|
+
chalk8.yellow(
|
|
13297
|
+
"Code graph not ready yet \u2014 run `repowise sync` shortly to finish setup."
|
|
13298
|
+
)
|
|
13299
|
+
);
|
|
13300
|
+
} else {
|
|
13301
|
+
spinner.info("Code graph still finishing \u2014 the listener will fetch it shortly.");
|
|
13302
|
+
}
|
|
13303
|
+
} else if (graphResult.status === "misconfig") {
|
|
13304
|
+
spinner.warn(
|
|
13305
|
+
chalk8.yellow(
|
|
13306
|
+
"Code graph unavailable (server configuration). Contact support if this persists."
|
|
13307
|
+
)
|
|
13308
|
+
);
|
|
13309
|
+
} else {
|
|
13310
|
+
spinner.warn(
|
|
13311
|
+
chalk8.yellow(
|
|
13312
|
+
"Could not download the code graph now; the listener will fetch it when ready."
|
|
13313
|
+
)
|
|
13314
|
+
);
|
|
13315
|
+
}
|
|
13316
|
+
}
|
|
13317
|
+
}
|
|
13077
13318
|
const contextFolder = DEFAULT_CONTEXT_FOLDER;
|
|
13078
13319
|
let contextFiles = [];
|
|
13079
13320
|
if (repoRoot) {
|
|
@@ -13127,15 +13368,15 @@ Files are stored on our servers (not in git). Retry when online.`
|
|
|
13127
13368
|
const priorAutoInstall = await getPriorConsent(repoId);
|
|
13128
13369
|
const updatedRepos = [];
|
|
13129
13370
|
if (repoRoot) {
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13371
|
+
updatedRepos.push(
|
|
13372
|
+
buildWatchedRepoEntry({
|
|
13373
|
+
repoId,
|
|
13374
|
+
localPath: repoRoot,
|
|
13375
|
+
platform: repoPlatform,
|
|
13376
|
+
externalId: repoExternalId,
|
|
13377
|
+
autoInstallDeps: priorAutoInstall
|
|
13378
|
+
})
|
|
13379
|
+
);
|
|
13139
13380
|
}
|
|
13140
13381
|
const configUpdate = { aiTools: tools, contextFolder };
|
|
13141
13382
|
if (updatedRepos.length > 0) configUpdate.repos = updatedRepos;
|
|
@@ -13244,8 +13485,8 @@ Files are stored on our servers (not in git). Retry when online.`
|
|
|
13244
13485
|
}
|
|
13245
13486
|
|
|
13246
13487
|
// src/commands/member.ts
|
|
13247
|
-
import { mkdirSync as
|
|
13248
|
-
import { dirname as
|
|
13488
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
13489
|
+
import { dirname as dirname18, join as join49, resolve, sep } from "path";
|
|
13249
13490
|
import chalk9 from "chalk";
|
|
13250
13491
|
import ora2 from "ora";
|
|
13251
13492
|
var DEFAULT_CONTEXT_FOLDER2 = "repowise-context";
|
|
@@ -13399,8 +13640,8 @@ async function member() {
|
|
|
13399
13640
|
spinner.succeed(`Found ${chalk9.bold(files.length)} context files on server`);
|
|
13400
13641
|
const { tools } = await selectAiTools();
|
|
13401
13642
|
spinner.start("Downloading context files...");
|
|
13402
|
-
const contextDir =
|
|
13403
|
-
|
|
13643
|
+
const contextDir = join49(repoRoot, DEFAULT_CONTEXT_FOLDER2);
|
|
13644
|
+
mkdirSync3(contextDir, { recursive: true });
|
|
13404
13645
|
let downloadedCount = 0;
|
|
13405
13646
|
let failedCount = 0;
|
|
13406
13647
|
const resolvedContextDir = resolve(contextDir);
|
|
@@ -13420,8 +13661,8 @@ async function member() {
|
|
|
13420
13661
|
const response = await fetch(presignedUrl);
|
|
13421
13662
|
if (response.ok) {
|
|
13422
13663
|
const content = await response.text();
|
|
13423
|
-
|
|
13424
|
-
|
|
13664
|
+
mkdirSync3(dirname18(safePath), { recursive: true });
|
|
13665
|
+
writeFileSync4(safePath, content, "utf-8");
|
|
13425
13666
|
downloadedCount++;
|
|
13426
13667
|
} else {
|
|
13427
13668
|
failedCount++;
|
|
@@ -13599,9 +13840,9 @@ import ora3 from "ora";
|
|
|
13599
13840
|
// src/lib/tenant-graph-purge.ts
|
|
13600
13841
|
import { promises as fs23 } from "fs";
|
|
13601
13842
|
import { homedir as homedir7 } from "os";
|
|
13602
|
-
import { join as
|
|
13843
|
+
import { join as join50 } from "path";
|
|
13603
13844
|
async function purgeForeignGraphs(validRepoIds, home = homedir7()) {
|
|
13604
|
-
const graphsDir =
|
|
13845
|
+
const graphsDir = join50(home, ".repowise", "graphs");
|
|
13605
13846
|
const result = { kept: [], removed: [] };
|
|
13606
13847
|
let entries;
|
|
13607
13848
|
try {
|
|
@@ -13619,7 +13860,7 @@ async function purgeForeignGraphs(validRepoIds, home = homedir7()) {
|
|
|
13619
13860
|
result.kept.push(entry);
|
|
13620
13861
|
continue;
|
|
13621
13862
|
}
|
|
13622
|
-
const path =
|
|
13863
|
+
const path = join50(graphsDir, entry);
|
|
13623
13864
|
try {
|
|
13624
13865
|
const stat8 = await fs23.lstat(path);
|
|
13625
13866
|
if (stat8.isSymbolicLink()) {
|
|
@@ -13712,11 +13953,11 @@ async function logout() {
|
|
|
13712
13953
|
|
|
13713
13954
|
// src/commands/status.ts
|
|
13714
13955
|
import { readFile as readFile16 } from "fs/promises";
|
|
13715
|
-
import { basename as basename4, join as
|
|
13956
|
+
import { basename as basename4, join as join51 } from "path";
|
|
13716
13957
|
async function status() {
|
|
13717
13958
|
const configDir = getConfigDir2();
|
|
13718
|
-
const STATE_PATH =
|
|
13719
|
-
const CONFIG_PATH =
|
|
13959
|
+
const STATE_PATH = join51(configDir, "listener-state.json");
|
|
13960
|
+
const CONFIG_PATH = join51(configDir, "config.json");
|
|
13720
13961
|
let state = null;
|
|
13721
13962
|
try {
|
|
13722
13963
|
const data = await readFile16(STATE_PATH, "utf-8");
|
|
@@ -13763,8 +14004,8 @@ async function status() {
|
|
|
13763
14004
|
}
|
|
13764
14005
|
|
|
13765
14006
|
// src/commands/sync.ts
|
|
13766
|
-
import { mkdirSync as
|
|
13767
|
-
import { dirname as
|
|
14007
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
14008
|
+
import { dirname as dirname19, join as join52 } from "path";
|
|
13768
14009
|
import chalk12 from "chalk";
|
|
13769
14010
|
import ora4 from "ora";
|
|
13770
14011
|
var POLL_INTERVAL_MS2 = 3e3;
|
|
@@ -13913,8 +14154,8 @@ async function sync() {
|
|
|
13913
14154
|
const listResult = await apiRequest(`/v1/repos/${repoId}/context`);
|
|
13914
14155
|
const files = listResult.data?.files ?? listResult.files ?? [];
|
|
13915
14156
|
if (files.length > 0) {
|
|
13916
|
-
const contextDir =
|
|
13917
|
-
|
|
14157
|
+
const contextDir = join52(repoRoot, DEFAULT_CONTEXT_FOLDER3);
|
|
14158
|
+
mkdirSync4(contextDir, { recursive: true });
|
|
13918
14159
|
let downloadedCount = 0;
|
|
13919
14160
|
let failedCount = 0;
|
|
13920
14161
|
for (const file of files) {
|
|
@@ -13927,9 +14168,9 @@ async function sync() {
|
|
|
13927
14168
|
const response = await fetch(presignedUrl);
|
|
13928
14169
|
if (response.ok) {
|
|
13929
14170
|
const content = await response.text();
|
|
13930
|
-
const filePath =
|
|
13931
|
-
|
|
13932
|
-
|
|
14171
|
+
const filePath = join52(contextDir, file.fileName);
|
|
14172
|
+
mkdirSync4(dirname19(filePath), { recursive: true });
|
|
14173
|
+
writeFileSync5(filePath, content, "utf-8");
|
|
13933
14174
|
downloadedCount++;
|
|
13934
14175
|
} else {
|
|
13935
14176
|
failedCount++;
|
|
@@ -14180,7 +14421,7 @@ async function config() {
|
|
|
14180
14421
|
// src/commands/mcp-log.ts
|
|
14181
14422
|
import { createDecipheriv as createDecipheriv2 } from "crypto";
|
|
14182
14423
|
import { mkdir as mkdir19, readFile as readFile17, stat as stat7, writeFile as writeFile18 } from "fs/promises";
|
|
14183
|
-
import { dirname as
|
|
14424
|
+
import { dirname as dirname20, join as join53 } from "path";
|
|
14184
14425
|
var FLAG_FILE = "mcp-log.flag";
|
|
14185
14426
|
var LOG_FILE = "mcp-log.jsonl.enc";
|
|
14186
14427
|
var KEY_FILE = "mcp-log.key";
|
|
@@ -14188,14 +14429,14 @@ var ENDPOINT_FILE = "listener.endpoint";
|
|
|
14188
14429
|
var IV_BYTES2 = 12;
|
|
14189
14430
|
var TAG_BYTES2 = 16;
|
|
14190
14431
|
function flagPath() {
|
|
14191
|
-
return
|
|
14432
|
+
return join53(getConfigDir2(), FLAG_FILE);
|
|
14192
14433
|
}
|
|
14193
14434
|
function logPath() {
|
|
14194
|
-
return
|
|
14435
|
+
return join53(getConfigDir2(), LOG_FILE);
|
|
14195
14436
|
}
|
|
14196
14437
|
async function writeFlag(flag) {
|
|
14197
14438
|
const path = flagPath();
|
|
14198
|
-
await mkdir19(
|
|
14439
|
+
await mkdir19(dirname20(path), { recursive: true });
|
|
14199
14440
|
await writeFile18(path, JSON.stringify(flag, null, 2), { encoding: "utf-8", mode: 384 });
|
|
14200
14441
|
}
|
|
14201
14442
|
async function mcpLogOn() {
|
|
@@ -14232,14 +14473,14 @@ async function trySendConsentToServer() {
|
|
|
14232
14473
|
let apiUrl = null;
|
|
14233
14474
|
let token = null;
|
|
14234
14475
|
try {
|
|
14235
|
-
const body = await readFile17(
|
|
14476
|
+
const body = await readFile17(join53(getConfigDir2(), "config.json"), "utf-8");
|
|
14236
14477
|
const parsed = JSON.parse(body);
|
|
14237
14478
|
apiUrl = parsed.repos?.find((r) => Boolean(r.apiUrl))?.apiUrl ?? parsed.defaultApiUrl ?? null;
|
|
14238
14479
|
} catch {
|
|
14239
14480
|
return false;
|
|
14240
14481
|
}
|
|
14241
14482
|
try {
|
|
14242
|
-
const body = await readFile17(
|
|
14483
|
+
const body = await readFile17(join53(getConfigDir2(), "credentials.json"), "utf-8");
|
|
14243
14484
|
const parsed = JSON.parse(body);
|
|
14244
14485
|
token = parsed.idToken ?? null;
|
|
14245
14486
|
} catch {
|
|
@@ -14309,7 +14550,7 @@ async function mcpLogStatus() {
|
|
|
14309
14550
|
process.stderr.write("Log size: no file yet\n");
|
|
14310
14551
|
}
|
|
14311
14552
|
try {
|
|
14312
|
-
const endpointBody = await readFile17(
|
|
14553
|
+
const endpointBody = await readFile17(join53(getConfigDir2(), ENDPOINT_FILE), "utf-8");
|
|
14313
14554
|
const match = /endpoint=([^\n]+)/.exec(endpointBody);
|
|
14314
14555
|
process.stderr.write(`MCP endpoint: ${match?.[1] ?? "(malformed endpoint file)"}
|
|
14315
14556
|
`);
|
|
@@ -14340,7 +14581,7 @@ async function mcpLogViewingFlags(flags = {}) {
|
|
|
14340
14581
|
const key = await readKey();
|
|
14341
14582
|
if (!key) {
|
|
14342
14583
|
process.stderr.write(
|
|
14343
|
-
`No encryption key at ${
|
|
14584
|
+
`No encryption key at ${join53(getConfigDir2(), KEY_FILE)} \u2014 listener may not have started yet.
|
|
14344
14585
|
`
|
|
14345
14586
|
);
|
|
14346
14587
|
return;
|
|
@@ -14416,7 +14657,7 @@ async function mcpLogViewingFlags(flags = {}) {
|
|
|
14416
14657
|
}
|
|
14417
14658
|
async function readKey() {
|
|
14418
14659
|
try {
|
|
14419
|
-
const body = await readFile17(
|
|
14660
|
+
const body = await readFile17(join53(getConfigDir2(), KEY_FILE), "utf-8");
|
|
14420
14661
|
const parsed = Buffer.from(body.trim(), "base64");
|
|
14421
14662
|
if (parsed.length !== 32) return null;
|
|
14422
14663
|
return parsed;
|
|
@@ -14460,7 +14701,7 @@ import chalk14 from "chalk";
|
|
|
14460
14701
|
|
|
14461
14702
|
// src/lib/graph-loader.ts
|
|
14462
14703
|
import { promises as fs24 } from "fs";
|
|
14463
|
-
import { join as
|
|
14704
|
+
import { join as join54, resolve as resolve2 } from "path";
|
|
14464
14705
|
import { gunzipSync } from "zlib";
|
|
14465
14706
|
var RELATIVE_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json";
|
|
14466
14707
|
var GZIPPED_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json.gz";
|
|
@@ -14477,8 +14718,8 @@ var GraphNotFoundError = class extends Error {
|
|
|
14477
14718
|
var cache = /* @__PURE__ */ new Map();
|
|
14478
14719
|
async function loadGraph(repoRoot = process.cwd()) {
|
|
14479
14720
|
const root = resolve2(repoRoot);
|
|
14480
|
-
const gzPath =
|
|
14481
|
-
const plainPath =
|
|
14721
|
+
const gzPath = join54(root, GZIPPED_GRAPH_PATH);
|
|
14722
|
+
const plainPath = join54(root, RELATIVE_GRAPH_PATH);
|
|
14482
14723
|
const cached = cache.get(root);
|
|
14483
14724
|
if (cached) {
|
|
14484
14725
|
return { graph: cached, path: plainPath, bytes: 0, parseMs: 0, fromCache: true };
|
|
@@ -14894,12 +15135,12 @@ function registerQueryCommand(program2) {
|
|
|
14894
15135
|
// src/commands/uninstall.ts
|
|
14895
15136
|
import { promises as fs28 } from "fs";
|
|
14896
15137
|
import { homedir as homedir9 } from "os";
|
|
14897
|
-
import { join as
|
|
15138
|
+
import { join as join58 } from "path";
|
|
14898
15139
|
import chalk15 from "chalk";
|
|
14899
15140
|
|
|
14900
15141
|
// src/lib/cleanup/marker-blocks.ts
|
|
14901
15142
|
import { promises as fs25 } from "fs";
|
|
14902
|
-
import { join as
|
|
15143
|
+
import { join as join55 } from "path";
|
|
14903
15144
|
var MARKER_START = "<!-- repowise-start -->";
|
|
14904
15145
|
var MARKER_END = "<!-- repowise-end -->";
|
|
14905
15146
|
var CONTEXT_FILES = [
|
|
@@ -14939,7 +15180,7 @@ async function stripMarkerBlock(filePath) {
|
|
|
14939
15180
|
async function stripAllMarkerBlocks(repoRoot) {
|
|
14940
15181
|
const out = [];
|
|
14941
15182
|
for (const relative of CONTEXT_FILES) {
|
|
14942
|
-
const full =
|
|
15183
|
+
const full = join55(repoRoot, relative);
|
|
14943
15184
|
const result = await stripMarkerBlock(full).catch((err) => ({
|
|
14944
15185
|
path: full,
|
|
14945
15186
|
status: "untouched",
|
|
@@ -14952,18 +15193,18 @@ async function stripAllMarkerBlocks(repoRoot) {
|
|
|
14952
15193
|
|
|
14953
15194
|
// src/lib/cleanup/mcp-configs.ts
|
|
14954
15195
|
import { promises as fs26 } from "fs";
|
|
14955
|
-
import { join as
|
|
15196
|
+
import { join as join56 } from "path";
|
|
14956
15197
|
function mcpConfigPaths(repoRoot, home) {
|
|
14957
15198
|
return [
|
|
14958
|
-
|
|
14959
|
-
|
|
14960
|
-
|
|
14961
|
-
|
|
14962
|
-
|
|
14963
|
-
|
|
14964
|
-
|
|
14965
|
-
|
|
14966
|
-
|
|
15199
|
+
join56(repoRoot, ".mcp.json"),
|
|
15200
|
+
join56(repoRoot, ".cursor", "mcp.json"),
|
|
15201
|
+
join56(repoRoot, ".vscode", "mcp.json"),
|
|
15202
|
+
join56(repoRoot, ".roo", "mcp.json"),
|
|
15203
|
+
join56(home, ".cline", "mcp.json"),
|
|
15204
|
+
join56(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
15205
|
+
join56(home, ".gemini", "settings.json"),
|
|
15206
|
+
join56(home, ".codex", "mcp.json"),
|
|
15207
|
+
join56(home, ".roo", "mcp.json")
|
|
14967
15208
|
];
|
|
14968
15209
|
}
|
|
14969
15210
|
async function removeRepowiseFromConfig(path, serverName) {
|
|
@@ -15004,10 +15245,10 @@ async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
|
15004
15245
|
// src/lib/cleanup/local-state.ts
|
|
15005
15246
|
import { promises as fs27 } from "fs";
|
|
15006
15247
|
import { homedir as homedir8 } from "os";
|
|
15007
|
-
import { join as
|
|
15248
|
+
import { join as join57, resolve as resolve3 } from "path";
|
|
15008
15249
|
async function clearLocalState(homeOverride) {
|
|
15009
15250
|
const home = homeOverride ?? homedir8();
|
|
15010
|
-
const target = resolve3(
|
|
15251
|
+
const target = resolve3(join57(home, ".repowise"));
|
|
15011
15252
|
if (target === resolve3(home) || !target.startsWith(resolve3(home))) {
|
|
15012
15253
|
return { path: target, status: "error", error: "refused: not under home" };
|
|
15013
15254
|
}
|
|
@@ -15051,7 +15292,7 @@ async function uninstall2(opts = {}) {
|
|
|
15051
15292
|
else if (svc.error) report.skipped.push({ path: "listener service", reason: svc.error });
|
|
15052
15293
|
if (tier === "stop") return report;
|
|
15053
15294
|
try {
|
|
15054
|
-
await fs28.unlink(
|
|
15295
|
+
await fs28.unlink(join58(home, ".repowise", "credentials.json"));
|
|
15055
15296
|
report.removed.push("credentials");
|
|
15056
15297
|
} catch (err) {
|
|
15057
15298
|
if (err.code !== "ENOENT") {
|
|
@@ -15090,7 +15331,7 @@ async function uninstall2(opts = {}) {
|
|
|
15090
15331
|
}
|
|
15091
15332
|
async function defaultLoadRepoIds(home) {
|
|
15092
15333
|
try {
|
|
15093
|
-
const raw = await fs28.readFile(
|
|
15334
|
+
const raw = await fs28.readFile(join58(home, ".repowise", "config.json"), "utf-8");
|
|
15094
15335
|
const parsed = JSON.parse(raw);
|
|
15095
15336
|
return (parsed.repos ?? []).map((r) => r.repoId);
|
|
15096
15337
|
} catch {
|
|
@@ -15139,10 +15380,10 @@ Done \u2014 ${report.removed.length} removed, ${report.skipped.length} skipped.
|
|
|
15139
15380
|
init_config_dir();
|
|
15140
15381
|
import { promises as fs29 } from "fs";
|
|
15141
15382
|
import { createInterface as createInterface2 } from "readline";
|
|
15142
|
-
import { join as
|
|
15383
|
+
import { join as join59 } from "path";
|
|
15143
15384
|
var DEFAULT_MAX = 200 * 1024;
|
|
15144
15385
|
async function mcpShim(opts) {
|
|
15145
|
-
const endpointPath = opts.endpointFile ??
|
|
15386
|
+
const endpointPath = opts.endpointFile ?? join59(getConfigDir(), "listener.endpoint");
|
|
15146
15387
|
const stdin = opts.stdin ?? process.stdin;
|
|
15147
15388
|
const stdout = opts.stdout ?? process.stdout;
|
|
15148
15389
|
const stderr = opts.stderr ?? process.stderr;
|
|
@@ -15890,8 +16131,8 @@ async function lspOn() {
|
|
|
15890
16131
|
|
|
15891
16132
|
// bin/repowise.ts
|
|
15892
16133
|
var __filename = fileURLToPath4(import.meta.url);
|
|
15893
|
-
var __dirname =
|
|
15894
|
-
var pkg = JSON.parse(readFileSync3(
|
|
16134
|
+
var __dirname = dirname21(__filename);
|
|
16135
|
+
var pkg = JSON.parse(readFileSync3(join60(__dirname, "..", "..", "package.json"), "utf-8"));
|
|
15895
16136
|
var program = new Command();
|
|
15896
16137
|
program.name(getPackageName()).description("AI-optimized codebase context generator").version(pkg.version).hook("preAction", async () => {
|
|
15897
16138
|
await showWelcome(pkg.version);
|