repowisestage 0.0.75 → 0.0.77
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 +388 -175
- package/package.json +1 -1
package/dist/bin/repowise.js
CHANGED
|
@@ -3133,13 +3133,13 @@ var init_telemetry = __esm({
|
|
|
3133
3133
|
// bin/repowise.ts
|
|
3134
3134
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3135
3135
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3136
|
-
import { dirname as
|
|
3136
|
+
import { dirname as dirname24, join as join63 } from "path";
|
|
3137
3137
|
import { Command } from "commander";
|
|
3138
3138
|
|
|
3139
3139
|
// ../listener/dist/main.js
|
|
3140
3140
|
init_config_dir();
|
|
3141
3141
|
import { readFile as readFile14, writeFile as writeFile16, mkdir as mkdir16, stat as fsStat } from "fs/promises";
|
|
3142
|
-
import { join as join42, dirname as
|
|
3142
|
+
import { join as join42, dirname as dirname18 } from "path";
|
|
3143
3143
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3144
3144
|
import lockfile5 from "proper-lockfile";
|
|
3145
3145
|
|
|
@@ -4535,21 +4535,38 @@ async function storeCredentials(credentials) {
|
|
|
4535
4535
|
}
|
|
4536
4536
|
}
|
|
4537
4537
|
var refreshInFlight = null;
|
|
4538
|
+
var refreshInFlightToken = null;
|
|
4539
|
+
var terminalRefreshTokens = /* @__PURE__ */ new Set();
|
|
4540
|
+
var lastSeenRefreshToken = null;
|
|
4538
4541
|
async function getValidCredentials(options) {
|
|
4539
4542
|
const creds = await getStoredCredentials();
|
|
4540
4543
|
if (!creds) {
|
|
4541
4544
|
lastRefreshOutcome = "no-creds";
|
|
4542
4545
|
return null;
|
|
4543
4546
|
}
|
|
4547
|
+
if (creds.refreshToken !== lastSeenRefreshToken) {
|
|
4548
|
+
terminalRefreshTokens.clear();
|
|
4549
|
+
lastSeenRefreshToken = creds.refreshToken;
|
|
4550
|
+
}
|
|
4544
4551
|
const now = Date.now();
|
|
4545
4552
|
const needsRefresh = options?.forceRefresh || now > creds.expiresAt - 5 * 60 * 1e3;
|
|
4546
4553
|
if (!needsRefresh) {
|
|
4547
4554
|
lastRefreshOutcome = "success";
|
|
4548
4555
|
return creds;
|
|
4549
4556
|
}
|
|
4550
|
-
if (
|
|
4551
|
-
|
|
4552
|
-
|
|
4557
|
+
if (terminalRefreshTokens.has(creds.refreshToken)) {
|
|
4558
|
+
lastRefreshOutcome = "terminal";
|
|
4559
|
+
return null;
|
|
4560
|
+
}
|
|
4561
|
+
if (!refreshInFlight || refreshInFlightToken !== creds.refreshToken) {
|
|
4562
|
+
const inflight = doRefresh(creds);
|
|
4563
|
+
refreshInFlight = inflight;
|
|
4564
|
+
refreshInFlightToken = creds.refreshToken;
|
|
4565
|
+
void inflight.finally(() => {
|
|
4566
|
+
if (refreshInFlight === inflight) {
|
|
4567
|
+
refreshInFlight = null;
|
|
4568
|
+
refreshInFlightToken = null;
|
|
4569
|
+
}
|
|
4553
4570
|
});
|
|
4554
4571
|
}
|
|
4555
4572
|
return refreshInFlight;
|
|
@@ -4566,6 +4583,7 @@ async function doRefresh(creds) {
|
|
|
4566
4583
|
const message = err instanceof Error ? err.message : String(err);
|
|
4567
4584
|
if (kind === "terminal") {
|
|
4568
4585
|
lastRefreshOutcome = "terminal";
|
|
4586
|
+
terminalRefreshTokens.add(creds.refreshToken);
|
|
4569
4587
|
console.warn(`Token refresh rejected (terminal): ${message}`);
|
|
4570
4588
|
return null;
|
|
4571
4589
|
}
|
|
@@ -6139,6 +6157,93 @@ function createGraphDownloader(options) {
|
|
|
6139
6157
|
|
|
6140
6158
|
// ../listener/dist/mcp/heartbeat.js
|
|
6141
6159
|
import { setTimeout as delay2 } from "timers/promises";
|
|
6160
|
+
|
|
6161
|
+
// ../listener/dist/mcp/heartbeat-queue.js
|
|
6162
|
+
import { promises as fs5 } from "fs";
|
|
6163
|
+
import { randomUUID } from "crypto";
|
|
6164
|
+
import { dirname as dirname11 } from "path";
|
|
6165
|
+
var DEFAULT_MAX_ENTRIES = 336;
|
|
6166
|
+
function createFileHeartbeatQueue(opts) {
|
|
6167
|
+
const maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
6168
|
+
const warn = opts.warn ?? ((m) => console.warn(m));
|
|
6169
|
+
let chain = Promise.resolve();
|
|
6170
|
+
async function read() {
|
|
6171
|
+
let raw;
|
|
6172
|
+
try {
|
|
6173
|
+
raw = await fs5.readFile(opts.path, "utf-8");
|
|
6174
|
+
} catch (err) {
|
|
6175
|
+
if (err.code === "ENOENT")
|
|
6176
|
+
return [];
|
|
6177
|
+
throw err;
|
|
6178
|
+
}
|
|
6179
|
+
const entries = [];
|
|
6180
|
+
for (const line of raw.split("\n")) {
|
|
6181
|
+
const trimmed = line.trim();
|
|
6182
|
+
if (!trimmed)
|
|
6183
|
+
continue;
|
|
6184
|
+
try {
|
|
6185
|
+
const e = JSON.parse(trimmed);
|
|
6186
|
+
if (e && typeof e.id === "string" && e.payload)
|
|
6187
|
+
entries.push(e);
|
|
6188
|
+
} catch {
|
|
6189
|
+
}
|
|
6190
|
+
}
|
|
6191
|
+
return entries;
|
|
6192
|
+
}
|
|
6193
|
+
async function write(entries) {
|
|
6194
|
+
await fs5.mkdir(dirname11(opts.path), { recursive: true });
|
|
6195
|
+
const tmp = `${opts.path}.tmp`;
|
|
6196
|
+
const body = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length ? "\n" : "");
|
|
6197
|
+
await fs5.writeFile(tmp, body, { mode: 384 });
|
|
6198
|
+
await fs5.rename(tmp, opts.path);
|
|
6199
|
+
}
|
|
6200
|
+
function mutate(fn) {
|
|
6201
|
+
const run = chain.then(async () => {
|
|
6202
|
+
const entries = await read();
|
|
6203
|
+
const { next, result } = fn(entries);
|
|
6204
|
+
await write(next);
|
|
6205
|
+
return result;
|
|
6206
|
+
});
|
|
6207
|
+
chain = run.then(() => void 0, () => void 0);
|
|
6208
|
+
return run;
|
|
6209
|
+
}
|
|
6210
|
+
return {
|
|
6211
|
+
enqueue(payload) {
|
|
6212
|
+
return mutate((entries) => {
|
|
6213
|
+
const next = [...entries, { id: randomUUID(), payload }];
|
|
6214
|
+
while (next.length > maxEntries) {
|
|
6215
|
+
next.shift();
|
|
6216
|
+
warn(`[heartbeat] queue full (${maxEntries.toString()}) \u2014 dropped the oldest un-sent bucket`);
|
|
6217
|
+
}
|
|
6218
|
+
return { next, result: void 0 };
|
|
6219
|
+
});
|
|
6220
|
+
},
|
|
6221
|
+
list() {
|
|
6222
|
+
return chain.then(() => read());
|
|
6223
|
+
},
|
|
6224
|
+
remove(id) {
|
|
6225
|
+
return mutate((entries) => ({ next: entries.filter((e) => e.id !== id), result: void 0 }));
|
|
6226
|
+
}
|
|
6227
|
+
};
|
|
6228
|
+
}
|
|
6229
|
+
function createInMemoryHeartbeatQueue() {
|
|
6230
|
+
let entries = [];
|
|
6231
|
+
return {
|
|
6232
|
+
enqueue(payload) {
|
|
6233
|
+
entries.push({ id: randomUUID(), payload });
|
|
6234
|
+
return Promise.resolve();
|
|
6235
|
+
},
|
|
6236
|
+
list() {
|
|
6237
|
+
return Promise.resolve([...entries]);
|
|
6238
|
+
},
|
|
6239
|
+
remove(id) {
|
|
6240
|
+
entries = entries.filter((e) => e.id !== id);
|
|
6241
|
+
return Promise.resolve();
|
|
6242
|
+
}
|
|
6243
|
+
};
|
|
6244
|
+
}
|
|
6245
|
+
|
|
6246
|
+
// ../listener/dist/mcp/heartbeat.js
|
|
6142
6247
|
var DEFAULT_WINDOW = 60 * 60 * 1e3;
|
|
6143
6248
|
function emptyStatusCounts() {
|
|
6144
6249
|
return { ok: 0, error: 0, timeout: 0, rejected: 0 };
|
|
@@ -6156,6 +6261,7 @@ function emptyHealthCounters() {
|
|
|
6156
6261
|
function createHeartbeatEmitter(opts) {
|
|
6157
6262
|
const windowMs = opts.windowMs ?? DEFAULT_WINDOW;
|
|
6158
6263
|
const now = opts.now ?? (() => Date.now());
|
|
6264
|
+
const queue = opts.queue ?? createInMemoryHeartbeatQueue();
|
|
6159
6265
|
let bucketStart = Math.floor(now() / windowMs) * windowMs;
|
|
6160
6266
|
let toolCounts = /* @__PURE__ */ new Map();
|
|
6161
6267
|
let missCounts = /* @__PURE__ */ new Map();
|
|
@@ -6190,16 +6296,60 @@ function createHeartbeatEmitter(opts) {
|
|
|
6190
6296
|
statusCounts = emptyStatusCounts();
|
|
6191
6297
|
healthCounters = emptyHealthCounters();
|
|
6192
6298
|
}
|
|
6299
|
+
const maxUnpersisted = opts.maxUnpersisted ?? 336;
|
|
6300
|
+
const unpersisted = [];
|
|
6301
|
+
let drainChain = Promise.resolve();
|
|
6302
|
+
function rollBucket(nextBucket) {
|
|
6303
|
+
const payload = buildPayload();
|
|
6304
|
+
bucketStart = nextBucket;
|
|
6305
|
+
clearCounters();
|
|
6306
|
+
return payload;
|
|
6307
|
+
}
|
|
6308
|
+
async function persist(payload) {
|
|
6309
|
+
try {
|
|
6310
|
+
await queue.enqueue(payload);
|
|
6311
|
+
} catch {
|
|
6312
|
+
unpersisted.push(payload);
|
|
6313
|
+
while (unpersisted.length > maxUnpersisted) {
|
|
6314
|
+
unpersisted.shift();
|
|
6315
|
+
console.warn("[heartbeat] in-memory hold full \u2014 dropped the oldest un-persisted bucket");
|
|
6316
|
+
}
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6193
6319
|
async function flushIfDue(currentBucket) {
|
|
6194
6320
|
if (currentBucket === bucketStart)
|
|
6195
6321
|
return;
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6322
|
+
await persist(rollBucket(currentBucket));
|
|
6323
|
+
}
|
|
6324
|
+
async function drainOnce() {
|
|
6325
|
+
while (unpersisted.length > 0) {
|
|
6326
|
+
try {
|
|
6327
|
+
await queue.enqueue(unpersisted[0]);
|
|
6328
|
+
unpersisted.shift();
|
|
6329
|
+
} catch {
|
|
6330
|
+
break;
|
|
6331
|
+
}
|
|
6332
|
+
}
|
|
6333
|
+
let pending;
|
|
6199
6334
|
try {
|
|
6200
|
-
await
|
|
6335
|
+
pending = await queue.list();
|
|
6201
6336
|
} catch {
|
|
6337
|
+
return;
|
|
6202
6338
|
}
|
|
6339
|
+
pending.sort((a, b) => a.payload.windowStartsAt < b.payload.windowStartsAt ? -1 : a.payload.windowStartsAt > b.payload.windowStartsAt ? 1 : 0);
|
|
6340
|
+
for (const entry of pending) {
|
|
6341
|
+
try {
|
|
6342
|
+
await opts.sink.post(entry.payload);
|
|
6343
|
+
} catch {
|
|
6344
|
+
return;
|
|
6345
|
+
}
|
|
6346
|
+
await queue.remove(entry.id).catch(() => void 0);
|
|
6347
|
+
}
|
|
6348
|
+
}
|
|
6349
|
+
function drain() {
|
|
6350
|
+
const run = drainChain.then(() => drainOnce());
|
|
6351
|
+
drainChain = run.then(() => void 0, () => void 0);
|
|
6352
|
+
return run;
|
|
6203
6353
|
}
|
|
6204
6354
|
return {
|
|
6205
6355
|
record(tool, outcome) {
|
|
@@ -6218,16 +6368,15 @@ function createHeartbeatEmitter(opts) {
|
|
|
6218
6368
|
async tick(nowOverride) {
|
|
6219
6369
|
const current = Math.floor((nowOverride ?? now()) / windowMs) * windowMs;
|
|
6220
6370
|
await flushIfDue(current);
|
|
6371
|
+
await drain();
|
|
6221
6372
|
},
|
|
6222
6373
|
async flush() {
|
|
6223
|
-
if (
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
try {
|
|
6228
|
-
await opts.sink.post(payload);
|
|
6229
|
-
} catch {
|
|
6374
|
+
if (hasData()) {
|
|
6375
|
+
const payload = buildPayload();
|
|
6376
|
+
clearCounters();
|
|
6377
|
+
await persist(payload);
|
|
6230
6378
|
}
|
|
6379
|
+
await drain();
|
|
6231
6380
|
}
|
|
6232
6381
|
};
|
|
6233
6382
|
}
|
|
@@ -6243,7 +6392,7 @@ async function runHeartbeatLoop(emitter, opts = {}) {
|
|
|
6243
6392
|
// ../listener/dist/mcp/log-encryption.js
|
|
6244
6393
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
6245
6394
|
import { mkdir as mkdir11, readFile as readFile11, stat as stat4, writeFile as writeFile12 } from "fs/promises";
|
|
6246
|
-
import { dirname as
|
|
6395
|
+
import { dirname as dirname12 } from "path";
|
|
6247
6396
|
var KEY_BYTES = 32;
|
|
6248
6397
|
var IV_BYTES = 12;
|
|
6249
6398
|
var TAG_BYTES = 16;
|
|
@@ -6290,7 +6439,7 @@ function createFileKeyStore(keyPath) {
|
|
|
6290
6439
|
return parsed;
|
|
6291
6440
|
}
|
|
6292
6441
|
const fresh = randomBytes(KEY_BYTES);
|
|
6293
|
-
await mkdir11(
|
|
6442
|
+
await mkdir11(dirname12(keyPath), { recursive: true });
|
|
6294
6443
|
const tmp = `${keyPath}.tmp`;
|
|
6295
6444
|
await writeFile12(tmp, fresh.toString("base64") + "\n", {
|
|
6296
6445
|
encoding: "utf-8",
|
|
@@ -6332,7 +6481,7 @@ function decryptLine(encoded, key) {
|
|
|
6332
6481
|
|
|
6333
6482
|
// ../listener/dist/mcp/mcp-logger.js
|
|
6334
6483
|
import { appendFile, mkdir as mkdir12, stat as stat5, unlink as unlink10, writeFile as writeFile13, readFile as readFile12 } from "fs/promises";
|
|
6335
|
-
import { dirname as
|
|
6484
|
+
import { dirname as dirname13 } from "path";
|
|
6336
6485
|
var DEFAULT_MAX_BYTES = 100 * 1024 * 1024;
|
|
6337
6486
|
function createMcpLogger(options) {
|
|
6338
6487
|
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
@@ -6355,7 +6504,7 @@ function createMcpLogger(options) {
|
|
|
6355
6504
|
await migrateLegacyPlaintext();
|
|
6356
6505
|
const key = await options.keyStore.getKey();
|
|
6357
6506
|
const encoded = encryptLine(JSON.stringify(entry), key) + "\n";
|
|
6358
|
-
await mkdir12(
|
|
6507
|
+
await mkdir12(dirname13(options.filePath), { recursive: true });
|
|
6359
6508
|
await appendFile(options.filePath, encoded, { encoding: "utf-8", mode: 384 });
|
|
6360
6509
|
try {
|
|
6361
6510
|
const s = await stat5(options.filePath);
|
|
@@ -6387,15 +6536,15 @@ async function rotate(path, size) {
|
|
|
6387
6536
|
}
|
|
6388
6537
|
|
|
6389
6538
|
// ../listener/dist/mcp/mcp-log-uploader.js
|
|
6390
|
-
import { randomUUID } from "crypto";
|
|
6539
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
6391
6540
|
import { readFile as readFile13, writeFile as writeFile14, mkdir as mkdir13 } from "fs/promises";
|
|
6392
|
-
import { dirname as
|
|
6541
|
+
import { dirname as dirname14 } from "path";
|
|
6393
6542
|
var MCP_LOG_UPLOAD_TIMEOUT_MS = 3e4;
|
|
6394
|
-
var
|
|
6543
|
+
var DEFAULT_MAX_ENTRIES2 = 5e3;
|
|
6395
6544
|
var DEFAULT_MAX_BYTES2 = 1 * 1024 * 1024;
|
|
6396
6545
|
function createMcpLogUploader(options) {
|
|
6397
6546
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
6398
|
-
const maxEntries = options.maxEntriesPerBatch ??
|
|
6547
|
+
const maxEntries = options.maxEntriesPerBatch ?? DEFAULT_MAX_ENTRIES2;
|
|
6399
6548
|
const maxBytes = options.maxBytesPerBatch ?? DEFAULT_MAX_BYTES2;
|
|
6400
6549
|
let consentRevoked = false;
|
|
6401
6550
|
return {
|
|
@@ -6473,7 +6622,7 @@ function createMcpLogUploader(options) {
|
|
|
6473
6622
|
const token = await options.getAuthToken();
|
|
6474
6623
|
let batchId = await readPendingBatch(options.watermarkFilePath);
|
|
6475
6624
|
if (!batchId) {
|
|
6476
|
-
batchId =
|
|
6625
|
+
batchId = randomUUID2();
|
|
6477
6626
|
await writePendingBatch(options.watermarkFilePath, batchId);
|
|
6478
6627
|
}
|
|
6479
6628
|
const uploadBody = JSON.stringify({
|
|
@@ -6542,7 +6691,7 @@ async function readPendingBatch(watermarkPath) {
|
|
|
6542
6691
|
}
|
|
6543
6692
|
}
|
|
6544
6693
|
async function writePendingBatch(watermarkPath, batchId) {
|
|
6545
|
-
await mkdir13(
|
|
6694
|
+
await mkdir13(dirname14(watermarkPath), { recursive: true });
|
|
6546
6695
|
await writeFile14(pendingPath(watermarkPath), batchId, { encoding: "utf-8", mode: 384 });
|
|
6547
6696
|
}
|
|
6548
6697
|
async function clearPendingBatch(watermarkPath) {
|
|
@@ -6564,7 +6713,7 @@ async function readWatermark(path) {
|
|
|
6564
6713
|
}
|
|
6565
6714
|
}
|
|
6566
6715
|
async function writeWatermark(path, offset) {
|
|
6567
|
-
await mkdir13(
|
|
6716
|
+
await mkdir13(dirname14(path), { recursive: true });
|
|
6568
6717
|
const tmp = `${path}.tmp`;
|
|
6569
6718
|
await writeFile14(tmp, offset.toString() + "\n", { encoding: "utf-8", mode: 384 });
|
|
6570
6719
|
const { rename: rename8 } = await import("fs/promises");
|
|
@@ -6584,8 +6733,8 @@ async function isLocallyConsented(flagPath2) {
|
|
|
6584
6733
|
init_config_dir();
|
|
6585
6734
|
import { createServer } from "http";
|
|
6586
6735
|
import { mkdir as mkdir14, writeFile as writeFile15, unlink as unlink11 } from "fs/promises";
|
|
6587
|
-
import { dirname as
|
|
6588
|
-
import { createHash as createHash4, randomUUID as
|
|
6736
|
+
import { dirname as dirname15, join as join23 } from "path";
|
|
6737
|
+
import { createHash as createHash4, randomUUID as randomUUID3 } from "crypto";
|
|
6589
6738
|
|
|
6590
6739
|
// ../listener/dist/mcp/sanitize.js
|
|
6591
6740
|
var MCP_RESPONSE_BYTE_CAP = 200 * 1024;
|
|
@@ -7657,7 +7806,20 @@ async function startMcpServer(options) {
|
|
|
7657
7806
|
throw err;
|
|
7658
7807
|
}
|
|
7659
7808
|
},
|
|
7660
|
-
resumeEndpoint: () =>
|
|
7809
|
+
resumeEndpoint: async () => {
|
|
7810
|
+
let lastErr;
|
|
7811
|
+
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
7812
|
+
try {
|
|
7813
|
+
await writeEndpointFile(endpointFilePath, endpoint, secretState.value.current);
|
|
7814
|
+
return;
|
|
7815
|
+
} catch (err) {
|
|
7816
|
+
lastErr = err;
|
|
7817
|
+
if (attempt < 3)
|
|
7818
|
+
await new Promise((r) => setTimeout(r, 100 * attempt));
|
|
7819
|
+
}
|
|
7820
|
+
}
|
|
7821
|
+
throw lastErr;
|
|
7822
|
+
}
|
|
7661
7823
|
};
|
|
7662
7824
|
}
|
|
7663
7825
|
function handleRequest(req, res, options, sessions, secretCtx) {
|
|
@@ -7697,7 +7859,7 @@ function handleRequest(req, res, options, sessions, secretCtx) {
|
|
|
7697
7859
|
if (!body?.repoId)
|
|
7698
7860
|
return sendJson(res, 400, { error: "missing_repoId" });
|
|
7699
7861
|
return options.graphCache.acquire(body.repoId).then(() => {
|
|
7700
|
-
const sessionId =
|
|
7862
|
+
const sessionId = randomUUID3();
|
|
7701
7863
|
sessions.set(sessionId, { repoId: body.repoId });
|
|
7702
7864
|
return sendJson(res, 200, { sessionId });
|
|
7703
7865
|
});
|
|
@@ -8190,7 +8352,7 @@ async function readJson(req) {
|
|
|
8190
8352
|
}
|
|
8191
8353
|
}
|
|
8192
8354
|
async function writeEndpointFile(path, endpoint, secret) {
|
|
8193
|
-
await mkdir14(
|
|
8355
|
+
await mkdir14(dirname15(path), { recursive: true });
|
|
8194
8356
|
await writeFile15(path, formatEndpointFile({ endpoint, secret }), {
|
|
8195
8357
|
encoding: "utf-8",
|
|
8196
8358
|
mode: 384
|
|
@@ -8272,7 +8434,11 @@ async function startMcp(options) {
|
|
|
8272
8434
|
getAuthToken: options.getAuthToken,
|
|
8273
8435
|
flagFilePath,
|
|
8274
8436
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}
|
|
8275
|
-
})
|
|
8437
|
+
}),
|
|
8438
|
+
// Durable delivery: a rolled bucket is persisted before the POST, so a
|
|
8439
|
+
// transient failure (network / auth gap / 5xx) is retried next tick and
|
|
8440
|
+
// survives a restart instead of dropping the hour's counts.
|
|
8441
|
+
queue: createFileHeartbeatQueue({ path: join24(mcpHome, "heartbeat-queue.jsonl") })
|
|
8276
8442
|
}) : null;
|
|
8277
8443
|
const heartbeatAbort = heartbeatEmitter ? new AbortController() : null;
|
|
8278
8444
|
const server = await startMcpServer({
|
|
@@ -8492,10 +8658,10 @@ async function ensureServerConsent(opts) {
|
|
|
8492
8658
|
});
|
|
8493
8659
|
if (!res.ok)
|
|
8494
8660
|
return;
|
|
8495
|
-
const
|
|
8661
|
+
const fs32 = await import("fs/promises");
|
|
8496
8662
|
const path = await import("path");
|
|
8497
|
-
await
|
|
8498
|
-
await
|
|
8663
|
+
await fs32.mkdir(path.dirname(opts.markerPath), { recursive: true });
|
|
8664
|
+
await fs32.writeFile(opts.markerPath, (/* @__PURE__ */ new Date()).toISOString() + "\n", {
|
|
8499
8665
|
encoding: "utf-8",
|
|
8500
8666
|
mode: 384
|
|
8501
8667
|
});
|
|
@@ -8508,12 +8674,15 @@ import { homedir as homedir6 } from "os";
|
|
|
8508
8674
|
import { basename as basename3 } from "path";
|
|
8509
8675
|
|
|
8510
8676
|
// ../listener/dist/mcp/auto-config/writers/claude-code.js
|
|
8511
|
-
import { promises as
|
|
8677
|
+
import { promises as fs7 } from "fs";
|
|
8512
8678
|
import { join as join25 } from "path";
|
|
8513
8679
|
|
|
8514
8680
|
// ../listener/dist/mcp/auto-config/markers.js
|
|
8515
|
-
import { promises as
|
|
8516
|
-
import { dirname as
|
|
8681
|
+
import { promises as fs6 } from "fs";
|
|
8682
|
+
import { dirname as dirname16 } from "path";
|
|
8683
|
+
function repoWiseServerName(ctx) {
|
|
8684
|
+
return `RepoWise MCP for ${ctx.repoName}${ctx.envSuffix ?? ""}`;
|
|
8685
|
+
}
|
|
8517
8686
|
async function writeMergedConfig(params) {
|
|
8518
8687
|
const current = await readConfig(params.path);
|
|
8519
8688
|
const servers = { ...current.mcpServers ?? {} };
|
|
@@ -8523,8 +8692,8 @@ async function writeMergedConfig(params) {
|
|
|
8523
8692
|
const existing = safeExistingContent(params.path, current);
|
|
8524
8693
|
if (existing === canonical)
|
|
8525
8694
|
return "unchanged";
|
|
8526
|
-
await
|
|
8527
|
-
await
|
|
8695
|
+
await fs6.mkdir(dirname16(params.path), { recursive: true });
|
|
8696
|
+
await fs6.writeFile(params.path, canonical, "utf-8");
|
|
8528
8697
|
return "written";
|
|
8529
8698
|
}
|
|
8530
8699
|
async function removeFromConfig(path, serverName) {
|
|
@@ -8537,11 +8706,11 @@ async function removeFromConfig(path, serverName) {
|
|
|
8537
8706
|
if (Object.keys(servers).length === 0) {
|
|
8538
8707
|
delete next.mcpServers;
|
|
8539
8708
|
}
|
|
8540
|
-
await
|
|
8709
|
+
await fs6.writeFile(path, canonicalize(next), "utf-8");
|
|
8541
8710
|
}
|
|
8542
8711
|
async function readConfig(path) {
|
|
8543
8712
|
try {
|
|
8544
|
-
const raw = await
|
|
8713
|
+
const raw = await fs6.readFile(path, "utf-8");
|
|
8545
8714
|
return JSON.parse(raw);
|
|
8546
8715
|
} catch (err) {
|
|
8547
8716
|
if (err.code === "ENOENT")
|
|
@@ -8596,20 +8765,20 @@ var claudeCodeWriter = {
|
|
|
8596
8765
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8597
8766
|
const status2 = await writeMergedConfig({
|
|
8598
8767
|
path,
|
|
8599
|
-
serverName:
|
|
8768
|
+
serverName: repoWiseServerName(ctx),
|
|
8600
8769
|
spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
|
|
8601
8770
|
});
|
|
8602
8771
|
return { status: status2, path };
|
|
8603
8772
|
},
|
|
8604
8773
|
async remove(ctx) {
|
|
8605
8774
|
const path = join25(ctx.repoRoot, ".mcp.json");
|
|
8606
|
-
await removeFromConfig(path,
|
|
8775
|
+
await removeFromConfig(path, repoWiseServerName(ctx));
|
|
8607
8776
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8608
8777
|
}
|
|
8609
8778
|
};
|
|
8610
8779
|
async function fileExists2(path) {
|
|
8611
8780
|
try {
|
|
8612
|
-
await
|
|
8781
|
+
await fs7.access(path);
|
|
8613
8782
|
return true;
|
|
8614
8783
|
} catch {
|
|
8615
8784
|
return false;
|
|
@@ -8620,7 +8789,7 @@ async function hasClaudeBinary(home) {
|
|
|
8620
8789
|
}
|
|
8621
8790
|
|
|
8622
8791
|
// ../listener/dist/mcp/auto-config/writers/claude-code-hooks.js
|
|
8623
|
-
import { promises as
|
|
8792
|
+
import { promises as fs8 } from "fs";
|
|
8624
8793
|
import { join as join26 } from "path";
|
|
8625
8794
|
var claudeCodeHooksWriter = {
|
|
8626
8795
|
tool: "claude-code-hooks",
|
|
@@ -8637,7 +8806,7 @@ var claudeCodeHooksWriter = {
|
|
|
8637
8806
|
};
|
|
8638
8807
|
async function fileExists3(path) {
|
|
8639
8808
|
try {
|
|
8640
|
-
await
|
|
8809
|
+
await fs8.access(path);
|
|
8641
8810
|
return true;
|
|
8642
8811
|
} catch {
|
|
8643
8812
|
return false;
|
|
@@ -8645,7 +8814,7 @@ async function fileExists3(path) {
|
|
|
8645
8814
|
}
|
|
8646
8815
|
|
|
8647
8816
|
// ../listener/dist/mcp/auto-config/writers/cline.js
|
|
8648
|
-
import { promises as
|
|
8817
|
+
import { promises as fs9 } from "fs";
|
|
8649
8818
|
import { join as join27 } from "path";
|
|
8650
8819
|
var clineWriter = {
|
|
8651
8820
|
tool: "cline",
|
|
@@ -8657,20 +8826,20 @@ var clineWriter = {
|
|
|
8657
8826
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8658
8827
|
const status2 = await writeMergedConfig({
|
|
8659
8828
|
path,
|
|
8660
|
-
serverName:
|
|
8829
|
+
serverName: repoWiseServerName(ctx),
|
|
8661
8830
|
spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
|
|
8662
8831
|
});
|
|
8663
8832
|
return { status: status2, path };
|
|
8664
8833
|
},
|
|
8665
8834
|
async remove(ctx) {
|
|
8666
8835
|
const path = join27(ctx.home, ".cline", "mcp.json");
|
|
8667
|
-
await removeFromConfig(path,
|
|
8836
|
+
await removeFromConfig(path, repoWiseServerName(ctx));
|
|
8668
8837
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8669
8838
|
}
|
|
8670
8839
|
};
|
|
8671
8840
|
async function fileExists4(path) {
|
|
8672
8841
|
try {
|
|
8673
|
-
await
|
|
8842
|
+
await fs9.access(path);
|
|
8674
8843
|
return true;
|
|
8675
8844
|
} catch {
|
|
8676
8845
|
return false;
|
|
@@ -8678,7 +8847,7 @@ async function fileExists4(path) {
|
|
|
8678
8847
|
}
|
|
8679
8848
|
|
|
8680
8849
|
// ../listener/dist/mcp/auto-config/writers/cline-hooks.js
|
|
8681
|
-
import { promises as
|
|
8850
|
+
import { promises as fs10 } from "fs";
|
|
8682
8851
|
import { join as join28 } from "path";
|
|
8683
8852
|
var SCRIPT_REL = ".clinerules/hooks/UserPromptSubmit";
|
|
8684
8853
|
var OWNERSHIP_MARKER = "managed by RepoWise";
|
|
@@ -8712,8 +8881,8 @@ var clineHooksWriter = {
|
|
|
8712
8881
|
await ensureExecutable(path);
|
|
8713
8882
|
return { status: "unchanged", path };
|
|
8714
8883
|
}
|
|
8715
|
-
await
|
|
8716
|
-
await
|
|
8884
|
+
await fs10.mkdir(join28(ctx.repoRoot, ".clinerules", "hooks"), { recursive: true });
|
|
8885
|
+
await fs10.writeFile(path, next, { encoding: "utf-8", mode: 493 });
|
|
8717
8886
|
await ensureExecutable(path);
|
|
8718
8887
|
await applyGitignoreChanges(ctx.repoRoot, { add: [SCRIPT_REL] });
|
|
8719
8888
|
return { status: "written", path };
|
|
@@ -8722,23 +8891,23 @@ var clineHooksWriter = {
|
|
|
8722
8891
|
const path = join28(ctx.repoRoot, SCRIPT_REL);
|
|
8723
8892
|
const existing = await readOrNull(path);
|
|
8724
8893
|
if (existing !== null && existing.includes(OWNERSHIP_MARKER)) {
|
|
8725
|
-
await
|
|
8894
|
+
await fs10.unlink(path);
|
|
8726
8895
|
}
|
|
8727
8896
|
await applyGitignoreChanges(ctx.repoRoot, { remove: [SCRIPT_REL] });
|
|
8728
8897
|
}
|
|
8729
8898
|
};
|
|
8730
8899
|
async function ensureExecutable(path) {
|
|
8731
8900
|
try {
|
|
8732
|
-
const stat8 = await
|
|
8901
|
+
const stat8 = await fs10.stat(path);
|
|
8733
8902
|
if ((stat8.mode & 73) === 0) {
|
|
8734
|
-
await
|
|
8903
|
+
await fs10.chmod(path, 493);
|
|
8735
8904
|
}
|
|
8736
8905
|
} catch {
|
|
8737
8906
|
}
|
|
8738
8907
|
}
|
|
8739
8908
|
async function fileExists5(path) {
|
|
8740
8909
|
try {
|
|
8741
|
-
await
|
|
8910
|
+
await fs10.access(path);
|
|
8742
8911
|
return true;
|
|
8743
8912
|
} catch {
|
|
8744
8913
|
return false;
|
|
@@ -8746,14 +8915,14 @@ async function fileExists5(path) {
|
|
|
8746
8915
|
}
|
|
8747
8916
|
async function readOrNull(path) {
|
|
8748
8917
|
try {
|
|
8749
|
-
return await
|
|
8918
|
+
return await fs10.readFile(path, "utf-8");
|
|
8750
8919
|
} catch {
|
|
8751
8920
|
return null;
|
|
8752
8921
|
}
|
|
8753
8922
|
}
|
|
8754
8923
|
|
|
8755
8924
|
// ../listener/dist/mcp/auto-config/writers/codex.js
|
|
8756
|
-
import { promises as
|
|
8925
|
+
import { promises as fs11 } from "fs";
|
|
8757
8926
|
import { join as join29 } from "path";
|
|
8758
8927
|
var codexWriter = {
|
|
8759
8928
|
tool: "codex",
|
|
@@ -8765,20 +8934,20 @@ var codexWriter = {
|
|
|
8765
8934
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8766
8935
|
const status2 = await writeMergedConfig({
|
|
8767
8936
|
path,
|
|
8768
|
-
serverName:
|
|
8937
|
+
serverName: repoWiseServerName(ctx),
|
|
8769
8938
|
spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
|
|
8770
8939
|
});
|
|
8771
8940
|
return { status: status2, path };
|
|
8772
8941
|
},
|
|
8773
8942
|
async remove(ctx) {
|
|
8774
8943
|
const path = join29(ctx.home, ".codex", "mcp.json");
|
|
8775
|
-
await removeFromConfig(path,
|
|
8944
|
+
await removeFromConfig(path, repoWiseServerName(ctx));
|
|
8776
8945
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8777
8946
|
}
|
|
8778
8947
|
};
|
|
8779
8948
|
async function fileExists6(path) {
|
|
8780
8949
|
try {
|
|
8781
|
-
await
|
|
8950
|
+
await fs11.access(path);
|
|
8782
8951
|
return true;
|
|
8783
8952
|
} catch {
|
|
8784
8953
|
return false;
|
|
@@ -8786,7 +8955,7 @@ async function fileExists6(path) {
|
|
|
8786
8955
|
}
|
|
8787
8956
|
|
|
8788
8957
|
// ../listener/dist/mcp/auto-config/writers/codex-hooks.js
|
|
8789
|
-
import { promises as
|
|
8958
|
+
import { promises as fs12 } from "fs";
|
|
8790
8959
|
import { join as join30 } from "path";
|
|
8791
8960
|
var HOOKS_REL = ".codex/hooks.json";
|
|
8792
8961
|
var codexHooksWriter = {
|
|
@@ -8817,8 +8986,8 @@ var codexHooksWriter = {
|
|
|
8817
8986
|
if (merged === existing) {
|
|
8818
8987
|
return { status: "unchanged", path };
|
|
8819
8988
|
}
|
|
8820
|
-
await
|
|
8821
|
-
await
|
|
8989
|
+
await fs12.mkdir(join30(ctx.repoRoot, ".codex"), { recursive: true });
|
|
8990
|
+
await fs12.writeFile(path, merged, "utf-8");
|
|
8822
8991
|
await applyGitignoreChanges(ctx.repoRoot, { add: [HOOKS_REL] });
|
|
8823
8992
|
return { status: "written", path };
|
|
8824
8993
|
},
|
|
@@ -8828,9 +8997,9 @@ var codexHooksWriter = {
|
|
|
8828
8997
|
if (existing !== null) {
|
|
8829
8998
|
const next = removeCodexHookSettings(existing);
|
|
8830
8999
|
if (next === null) {
|
|
8831
|
-
await
|
|
9000
|
+
await fs12.unlink(path);
|
|
8832
9001
|
} else if (next !== existing) {
|
|
8833
|
-
await
|
|
9002
|
+
await fs12.writeFile(path, next, "utf-8");
|
|
8834
9003
|
}
|
|
8835
9004
|
}
|
|
8836
9005
|
await applyGitignoreChanges(ctx.repoRoot, { remove: [HOOKS_REL] });
|
|
@@ -8838,7 +9007,7 @@ var codexHooksWriter = {
|
|
|
8838
9007
|
};
|
|
8839
9008
|
async function fileExists7(path) {
|
|
8840
9009
|
try {
|
|
8841
|
-
await
|
|
9010
|
+
await fs12.access(path);
|
|
8842
9011
|
return true;
|
|
8843
9012
|
} catch {
|
|
8844
9013
|
return false;
|
|
@@ -8846,14 +9015,14 @@ async function fileExists7(path) {
|
|
|
8846
9015
|
}
|
|
8847
9016
|
async function readOrNull2(path) {
|
|
8848
9017
|
try {
|
|
8849
|
-
return await
|
|
9018
|
+
return await fs12.readFile(path, "utf-8");
|
|
8850
9019
|
} catch {
|
|
8851
9020
|
return null;
|
|
8852
9021
|
}
|
|
8853
9022
|
}
|
|
8854
9023
|
|
|
8855
9024
|
// ../listener/dist/mcp/auto-config/writers/copilot.js
|
|
8856
|
-
import { promises as
|
|
9025
|
+
import { promises as fs13 } from "fs";
|
|
8857
9026
|
import { join as join31 } from "path";
|
|
8858
9027
|
var copilotWriter = {
|
|
8859
9028
|
tool: "copilot",
|
|
@@ -8865,20 +9034,20 @@ var copilotWriter = {
|
|
|
8865
9034
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8866
9035
|
const status2 = await writeMergedConfig({
|
|
8867
9036
|
path,
|
|
8868
|
-
serverName:
|
|
9037
|
+
serverName: repoWiseServerName(ctx),
|
|
8869
9038
|
spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
|
|
8870
9039
|
});
|
|
8871
9040
|
return { status: status2, path };
|
|
8872
9041
|
},
|
|
8873
9042
|
async remove(ctx) {
|
|
8874
9043
|
const path = join31(ctx.repoRoot, ".vscode", "mcp.json");
|
|
8875
|
-
await removeFromConfig(path,
|
|
9044
|
+
await removeFromConfig(path, repoWiseServerName(ctx));
|
|
8876
9045
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8877
9046
|
}
|
|
8878
9047
|
};
|
|
8879
9048
|
async function fileExists8(path) {
|
|
8880
9049
|
try {
|
|
8881
|
-
await
|
|
9050
|
+
await fs13.access(path);
|
|
8882
9051
|
return true;
|
|
8883
9052
|
} catch {
|
|
8884
9053
|
return false;
|
|
@@ -8886,7 +9055,7 @@ async function fileExists8(path) {
|
|
|
8886
9055
|
}
|
|
8887
9056
|
|
|
8888
9057
|
// ../listener/dist/mcp/auto-config/writers/copilot-hooks.js
|
|
8889
|
-
import { promises as
|
|
9058
|
+
import { promises as fs14 } from "fs";
|
|
8890
9059
|
import { join as join32 } from "path";
|
|
8891
9060
|
var HOOKS_REL2 = ".github/hooks/repowise.json";
|
|
8892
9061
|
var copilotHooksWriter = {
|
|
@@ -8915,8 +9084,8 @@ var copilotHooksWriter = {
|
|
|
8915
9084
|
if (existing === next) {
|
|
8916
9085
|
return { status: "unchanged", path };
|
|
8917
9086
|
}
|
|
8918
|
-
await
|
|
8919
|
-
await
|
|
9087
|
+
await fs14.mkdir(join32(ctx.repoRoot, ".github", "hooks"), { recursive: true });
|
|
9088
|
+
await fs14.writeFile(path, next, "utf-8");
|
|
8920
9089
|
const userSelected = ctx.selectedTools?.includes("copilot") ?? false;
|
|
8921
9090
|
await applyGitignoreChanges(ctx.repoRoot, userSelected ? { remove: [HOOKS_REL2] } : { add: [HOOKS_REL2] });
|
|
8922
9091
|
return { status: "written", path };
|
|
@@ -8924,7 +9093,7 @@ var copilotHooksWriter = {
|
|
|
8924
9093
|
async remove(ctx) {
|
|
8925
9094
|
const path = join32(ctx.repoRoot, HOOKS_REL2);
|
|
8926
9095
|
if (!await isGitTracked(ctx.repoRoot, HOOKS_REL2)) {
|
|
8927
|
-
await
|
|
9096
|
+
await fs14.unlink(path).catch(() => {
|
|
8928
9097
|
});
|
|
8929
9098
|
}
|
|
8930
9099
|
await applyGitignoreChanges(ctx.repoRoot, { remove: [HOOKS_REL2] });
|
|
@@ -8932,7 +9101,7 @@ var copilotHooksWriter = {
|
|
|
8932
9101
|
};
|
|
8933
9102
|
async function fileExists9(path) {
|
|
8934
9103
|
try {
|
|
8935
|
-
await
|
|
9104
|
+
await fs14.access(path);
|
|
8936
9105
|
return true;
|
|
8937
9106
|
} catch {
|
|
8938
9107
|
return false;
|
|
@@ -8940,14 +9109,14 @@ async function fileExists9(path) {
|
|
|
8940
9109
|
}
|
|
8941
9110
|
async function readOrNull3(path) {
|
|
8942
9111
|
try {
|
|
8943
|
-
return await
|
|
9112
|
+
return await fs14.readFile(path, "utf-8");
|
|
8944
9113
|
} catch {
|
|
8945
9114
|
return null;
|
|
8946
9115
|
}
|
|
8947
9116
|
}
|
|
8948
9117
|
|
|
8949
9118
|
// ../listener/dist/mcp/auto-config/writers/cursor.js
|
|
8950
|
-
import { promises as
|
|
9119
|
+
import { promises as fs15 } from "fs";
|
|
8951
9120
|
import { join as join33 } from "path";
|
|
8952
9121
|
var cursorWriter = {
|
|
8953
9122
|
tool: "cursor",
|
|
@@ -8959,20 +9128,20 @@ var cursorWriter = {
|
|
|
8959
9128
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8960
9129
|
const status2 = await writeMergedConfig({
|
|
8961
9130
|
path,
|
|
8962
|
-
serverName:
|
|
9131
|
+
serverName: repoWiseServerName(ctx),
|
|
8963
9132
|
spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
|
|
8964
9133
|
});
|
|
8965
9134
|
return { status: status2, path };
|
|
8966
9135
|
},
|
|
8967
9136
|
async remove(ctx) {
|
|
8968
9137
|
const path = join33(ctx.repoRoot, ".cursor", "mcp.json");
|
|
8969
|
-
await removeFromConfig(path,
|
|
9138
|
+
await removeFromConfig(path, repoWiseServerName(ctx));
|
|
8970
9139
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8971
9140
|
}
|
|
8972
9141
|
};
|
|
8973
9142
|
async function fileExists10(path) {
|
|
8974
9143
|
try {
|
|
8975
|
-
await
|
|
9144
|
+
await fs15.access(path);
|
|
8976
9145
|
return true;
|
|
8977
9146
|
} catch {
|
|
8978
9147
|
return false;
|
|
@@ -8980,7 +9149,7 @@ async function fileExists10(path) {
|
|
|
8980
9149
|
}
|
|
8981
9150
|
|
|
8982
9151
|
// ../listener/dist/mcp/auto-config/writers/gemini-cli.js
|
|
8983
|
-
import { promises as
|
|
9152
|
+
import { promises as fs16 } from "fs";
|
|
8984
9153
|
import { join as join34 } from "path";
|
|
8985
9154
|
var geminiCliWriter = {
|
|
8986
9155
|
tool: "gemini-cli",
|
|
@@ -8992,20 +9161,20 @@ var geminiCliWriter = {
|
|
|
8992
9161
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
8993
9162
|
const status2 = await writeMergedConfig({
|
|
8994
9163
|
path,
|
|
8995
|
-
serverName:
|
|
9164
|
+
serverName: repoWiseServerName(ctx),
|
|
8996
9165
|
spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
|
|
8997
9166
|
});
|
|
8998
9167
|
return { status: status2, path };
|
|
8999
9168
|
},
|
|
9000
9169
|
async remove(ctx) {
|
|
9001
9170
|
const path = join34(ctx.home, ".gemini", "settings.json");
|
|
9002
|
-
await removeFromConfig(path,
|
|
9171
|
+
await removeFromConfig(path, repoWiseServerName(ctx));
|
|
9003
9172
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
9004
9173
|
}
|
|
9005
9174
|
};
|
|
9006
9175
|
async function fileExists11(path) {
|
|
9007
9176
|
try {
|
|
9008
|
-
await
|
|
9177
|
+
await fs16.access(path);
|
|
9009
9178
|
return true;
|
|
9010
9179
|
} catch {
|
|
9011
9180
|
return false;
|
|
@@ -9013,7 +9182,7 @@ async function fileExists11(path) {
|
|
|
9013
9182
|
}
|
|
9014
9183
|
|
|
9015
9184
|
// ../listener/dist/mcp/auto-config/writers/gemini-hooks.js
|
|
9016
|
-
import { promises as
|
|
9185
|
+
import { promises as fs17 } from "fs";
|
|
9017
9186
|
import { join as join35 } from "path";
|
|
9018
9187
|
var SETTINGS_REL = ".gemini/settings.json";
|
|
9019
9188
|
var geminiHooksWriter = {
|
|
@@ -9044,8 +9213,8 @@ var geminiHooksWriter = {
|
|
|
9044
9213
|
if (merged === existing) {
|
|
9045
9214
|
return { status: "unchanged", path };
|
|
9046
9215
|
}
|
|
9047
|
-
await
|
|
9048
|
-
await
|
|
9216
|
+
await fs17.mkdir(join35(ctx.repoRoot, ".gemini"), { recursive: true });
|
|
9217
|
+
await fs17.writeFile(path, merged, "utf-8");
|
|
9049
9218
|
await applyGitignoreChanges(ctx.repoRoot, { add: [SETTINGS_REL] });
|
|
9050
9219
|
return { status: "written", path };
|
|
9051
9220
|
},
|
|
@@ -9055,9 +9224,9 @@ var geminiHooksWriter = {
|
|
|
9055
9224
|
if (existing !== null) {
|
|
9056
9225
|
const next = removeGeminiHookSettings(existing);
|
|
9057
9226
|
if (next === null) {
|
|
9058
|
-
await
|
|
9227
|
+
await fs17.unlink(path);
|
|
9059
9228
|
} else if (next !== existing) {
|
|
9060
|
-
await
|
|
9229
|
+
await fs17.writeFile(path, next, "utf-8");
|
|
9061
9230
|
}
|
|
9062
9231
|
}
|
|
9063
9232
|
await applyGitignoreChanges(ctx.repoRoot, { remove: [SETTINGS_REL] });
|
|
@@ -9065,7 +9234,7 @@ var geminiHooksWriter = {
|
|
|
9065
9234
|
};
|
|
9066
9235
|
async function fileExists12(path) {
|
|
9067
9236
|
try {
|
|
9068
|
-
await
|
|
9237
|
+
await fs17.access(path);
|
|
9069
9238
|
return true;
|
|
9070
9239
|
} catch {
|
|
9071
9240
|
return false;
|
|
@@ -9073,14 +9242,14 @@ async function fileExists12(path) {
|
|
|
9073
9242
|
}
|
|
9074
9243
|
async function readOrNull4(path) {
|
|
9075
9244
|
try {
|
|
9076
|
-
return await
|
|
9245
|
+
return await fs17.readFile(path, "utf-8");
|
|
9077
9246
|
} catch {
|
|
9078
9247
|
return null;
|
|
9079
9248
|
}
|
|
9080
9249
|
}
|
|
9081
9250
|
|
|
9082
9251
|
// ../listener/dist/mcp/auto-config/writers/roo.js
|
|
9083
|
-
import { promises as
|
|
9252
|
+
import { promises as fs18 } from "fs";
|
|
9084
9253
|
import { join as join36 } from "path";
|
|
9085
9254
|
var rooWriter = {
|
|
9086
9255
|
tool: "roo",
|
|
@@ -9102,7 +9271,7 @@ var rooWriter = {
|
|
|
9102
9271
|
const homeConfig = join36(ctx.home, ".roo", "mcp.json");
|
|
9103
9272
|
const homeSettings = join36(ctx.home, ".roo", "settings.json");
|
|
9104
9273
|
for (const path of [repoConfig, homeConfig, homeSettings]) {
|
|
9105
|
-
await removeFromConfig(path,
|
|
9274
|
+
await removeFromConfig(path, repoWiseServerName(ctx)).catch(() => {
|
|
9106
9275
|
});
|
|
9107
9276
|
await removeFromConfig(path, `repowise-${ctx.repoId}`).catch(() => {
|
|
9108
9277
|
});
|
|
@@ -9111,7 +9280,7 @@ var rooWriter = {
|
|
|
9111
9280
|
};
|
|
9112
9281
|
async function fileExists13(path) {
|
|
9113
9282
|
try {
|
|
9114
|
-
await
|
|
9283
|
+
await fs18.access(path);
|
|
9115
9284
|
return true;
|
|
9116
9285
|
} catch {
|
|
9117
9286
|
return false;
|
|
@@ -9119,14 +9288,14 @@ async function fileExists13(path) {
|
|
|
9119
9288
|
}
|
|
9120
9289
|
async function readOrNull5(path) {
|
|
9121
9290
|
try {
|
|
9122
|
-
return await
|
|
9291
|
+
return await fs18.readFile(path, "utf-8");
|
|
9123
9292
|
} catch {
|
|
9124
9293
|
return null;
|
|
9125
9294
|
}
|
|
9126
9295
|
}
|
|
9127
9296
|
|
|
9128
9297
|
// ../listener/dist/mcp/auto-config/writers/windsurf.js
|
|
9129
|
-
import { promises as
|
|
9298
|
+
import { promises as fs19 } from "fs";
|
|
9130
9299
|
import { join as join37 } from "path";
|
|
9131
9300
|
var windsurfWriter = {
|
|
9132
9301
|
tool: "windsurf",
|
|
@@ -9138,20 +9307,20 @@ var windsurfWriter = {
|
|
|
9138
9307
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
9139
9308
|
const status2 = await writeMergedConfig({
|
|
9140
9309
|
path,
|
|
9141
|
-
serverName:
|
|
9310
|
+
serverName: repoWiseServerName(ctx),
|
|
9142
9311
|
spec: { command: ctx.shimCmd, args: ["mcp-shim", "--repo-id", ctx.repoId] }
|
|
9143
9312
|
});
|
|
9144
9313
|
return { status: status2, path };
|
|
9145
9314
|
},
|
|
9146
9315
|
async remove(ctx) {
|
|
9147
9316
|
const path = join37(ctx.home, ".codeium", "windsurf", "mcp_config.json");
|
|
9148
|
-
await removeFromConfig(path,
|
|
9317
|
+
await removeFromConfig(path, repoWiseServerName(ctx));
|
|
9149
9318
|
await removeFromConfig(path, `repowise-${ctx.repoId}`);
|
|
9150
9319
|
}
|
|
9151
9320
|
};
|
|
9152
9321
|
async function fileExists14(path) {
|
|
9153
9322
|
try {
|
|
9154
|
-
await
|
|
9323
|
+
await fs19.access(path);
|
|
9155
9324
|
return true;
|
|
9156
9325
|
} catch {
|
|
9157
9326
|
return false;
|
|
@@ -9205,7 +9374,8 @@ async function runAutoConfig(opts) {
|
|
|
9205
9374
|
home,
|
|
9206
9375
|
contextFolder: opts.contextFolder,
|
|
9207
9376
|
selectedTools: opts.selectedTools,
|
|
9208
|
-
variant: opts.variant
|
|
9377
|
+
variant: opts.variant,
|
|
9378
|
+
envSuffix: opts.envSuffix
|
|
9209
9379
|
});
|
|
9210
9380
|
results.push({ tool: writer.tool, detected: true, outcome });
|
|
9211
9381
|
} catch (err) {
|
|
@@ -9225,7 +9395,7 @@ init_installer();
|
|
|
9225
9395
|
// ../listener/dist/lsp/warm.js
|
|
9226
9396
|
init_registry();
|
|
9227
9397
|
init_lsp_tools();
|
|
9228
|
-
import { promises as
|
|
9398
|
+
import { promises as fs20 } from "fs";
|
|
9229
9399
|
import { join as join38 } from "path";
|
|
9230
9400
|
async function collectRepresentativeFiles(repoRoot) {
|
|
9231
9401
|
const reps = /* @__PURE__ */ new Map();
|
|
@@ -9236,7 +9406,7 @@ async function collectRepresentativeFiles(repoRoot) {
|
|
|
9236
9406
|
return;
|
|
9237
9407
|
let entries;
|
|
9238
9408
|
try {
|
|
9239
|
-
entries = await
|
|
9409
|
+
entries = await fs20.readdir(dir);
|
|
9240
9410
|
} catch {
|
|
9241
9411
|
return;
|
|
9242
9412
|
}
|
|
@@ -9258,7 +9428,7 @@ async function collectRepresentativeFiles(repoRoot) {
|
|
|
9258
9428
|
await inspect(repoRoot, "");
|
|
9259
9429
|
let topEntries = [];
|
|
9260
9430
|
try {
|
|
9261
|
-
topEntries = await
|
|
9431
|
+
topEntries = await fs20.readdir(repoRoot);
|
|
9262
9432
|
} catch {
|
|
9263
9433
|
return reps;
|
|
9264
9434
|
}
|
|
@@ -9269,7 +9439,7 @@ async function collectRepresentativeFiles(repoRoot) {
|
|
|
9269
9439
|
continue;
|
|
9270
9440
|
const sub = join38(repoRoot, name);
|
|
9271
9441
|
try {
|
|
9272
|
-
const stat8 = await
|
|
9442
|
+
const stat8 = await fs20.stat(sub);
|
|
9273
9443
|
if (stat8.isDirectory())
|
|
9274
9444
|
await inspect(sub, name);
|
|
9275
9445
|
} catch {
|
|
@@ -9283,7 +9453,7 @@ async function warmReposLsp(repos, workspaces, lspOverrides, isAvailable) {
|
|
|
9283
9453
|
if (!repoRoot)
|
|
9284
9454
|
continue;
|
|
9285
9455
|
try {
|
|
9286
|
-
const stat8 = await
|
|
9456
|
+
const stat8 = await fs20.stat(repoRoot);
|
|
9287
9457
|
if (!stat8.isDirectory())
|
|
9288
9458
|
continue;
|
|
9289
9459
|
} catch {
|
|
@@ -9312,7 +9482,7 @@ async function warmReposLsp(repos, workspaces, lspOverrides, isAvailable) {
|
|
|
9312
9482
|
|
|
9313
9483
|
// ../listener/dist/lib/workspace-prep.js
|
|
9314
9484
|
init_config_dir();
|
|
9315
|
-
import { promises as
|
|
9485
|
+
import { promises as fs21 } from "fs";
|
|
9316
9486
|
import { spawn as spawn9, execFile as execFile5 } from "child_process";
|
|
9317
9487
|
import { createWriteStream as createWriteStream2 } from "fs";
|
|
9318
9488
|
import { join as join39 } from "path";
|
|
@@ -9369,7 +9539,7 @@ async function maybeWriteClangdStub(repoRoot, repoId) {
|
|
|
9369
9539
|
return;
|
|
9370
9540
|
let ents;
|
|
9371
9541
|
try {
|
|
9372
|
-
ents = await
|
|
9542
|
+
ents = await fs21.readdir(dir, { withFileTypes: true });
|
|
9373
9543
|
} catch {
|
|
9374
9544
|
return;
|
|
9375
9545
|
}
|
|
@@ -9405,9 +9575,9 @@ async function maybeWriteClangdStub(repoRoot, repoId) {
|
|
|
9405
9575
|
};
|
|
9406
9576
|
});
|
|
9407
9577
|
const outDir = join39(repoRoot, ".repowise");
|
|
9408
|
-
await
|
|
9578
|
+
await fs21.mkdir(outDir, { recursive: true });
|
|
9409
9579
|
const outPath = join39(outDir, "compile_commands.json");
|
|
9410
|
-
await
|
|
9580
|
+
await fs21.writeFile(outPath, JSON.stringify(entries, null, 2));
|
|
9411
9581
|
const capHit = sources.length >= MAX_STUB_SOURCES;
|
|
9412
9582
|
console.log(`[workspace-prep] ${repoId}: wrote ${entries.length.toString()}-entry compile_commands stub to .repowise/${capHit ? " (cap reached \u2014 additional sources truncated)" : ""}`);
|
|
9413
9583
|
return true;
|
|
@@ -9415,7 +9585,7 @@ async function maybeWriteClangdStub(repoRoot, repoId) {
|
|
|
9415
9585
|
var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
9416
9586
|
async function fileExists15(repoRoot, name) {
|
|
9417
9587
|
try {
|
|
9418
|
-
await
|
|
9588
|
+
await fs21.access(join39(repoRoot, name));
|
|
9419
9589
|
return true;
|
|
9420
9590
|
} catch {
|
|
9421
9591
|
return false;
|
|
@@ -9426,7 +9596,7 @@ async function detectWorkspaceDeps(repoRoot) {
|
|
|
9426
9596
|
if (await fileExists15(repoRoot, "package.json")) {
|
|
9427
9597
|
let pkgRaw = "";
|
|
9428
9598
|
try {
|
|
9429
|
-
pkgRaw = await
|
|
9599
|
+
pkgRaw = await fs21.readFile(join39(repoRoot, "package.json"), "utf8");
|
|
9430
9600
|
} catch {
|
|
9431
9601
|
}
|
|
9432
9602
|
if (pkgRaw) {
|
|
@@ -9530,7 +9700,7 @@ async function runWorkspacePreps(opts) {
|
|
|
9530
9700
|
return [];
|
|
9531
9701
|
const safeRepoId = opts.repoId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9532
9702
|
const logPath2 = join39(getConfigDir(), `install-log.${safeRepoId}.txt`);
|
|
9533
|
-
await
|
|
9703
|
+
await fs21.mkdir(getConfigDir(), { recursive: true });
|
|
9534
9704
|
const stream = opts.logStream ?? createWriteStream2(logPath2, { flags: "a" });
|
|
9535
9705
|
stream.on("error", () => {
|
|
9536
9706
|
});
|
|
@@ -9773,7 +9943,7 @@ async function ensureIndexable(indexRoot, language, options = {}) {
|
|
|
9773
9943
|
init_src();
|
|
9774
9944
|
init_registry();
|
|
9775
9945
|
import { execFile as execFileCb2 } from "child_process";
|
|
9776
|
-
import { dirname as
|
|
9946
|
+
import { dirname as dirname17 } from "path";
|
|
9777
9947
|
import { promisify as promisify5 } from "util";
|
|
9778
9948
|
init_daemon_path();
|
|
9779
9949
|
|
|
@@ -10261,7 +10431,7 @@ async function isCommandOnPath4(command) {
|
|
|
10261
10431
|
timeout: 5e3,
|
|
10262
10432
|
env: {
|
|
10263
10433
|
...process.env,
|
|
10264
|
-
PATH: buildLspSpawnPath(process.env.PATH,
|
|
10434
|
+
PATH: buildLspSpawnPath(process.env.PATH, dirname17(process.execPath), managedBinDirs())
|
|
10265
10435
|
}
|
|
10266
10436
|
});
|
|
10267
10437
|
return true;
|
|
@@ -10933,11 +11103,11 @@ function resolveAuditRoots() {
|
|
|
10933
11103
|
return override.split(":").map((s) => s.trim()).filter(Boolean);
|
|
10934
11104
|
}
|
|
10935
11105
|
const out = /* @__PURE__ */ new Set();
|
|
10936
|
-
let dir =
|
|
11106
|
+
let dir = dirname18(process.execPath);
|
|
10937
11107
|
for (let i = 0; i < 8; i += 1) {
|
|
10938
11108
|
out.add(join42(dir, "node_modules"));
|
|
10939
11109
|
out.add(join42(dir, "lib", "node_modules"));
|
|
10940
|
-
const parent =
|
|
11110
|
+
const parent = dirname18(dir);
|
|
10941
11111
|
if (parent === dir)
|
|
10942
11112
|
break;
|
|
10943
11113
|
dir = parent;
|
|
@@ -11003,8 +11173,8 @@ async function waitForCredentials(isRunning2) {
|
|
|
11003
11173
|
let changed = false;
|
|
11004
11174
|
let watcher = null;
|
|
11005
11175
|
try {
|
|
11006
|
-
const
|
|
11007
|
-
watcher =
|
|
11176
|
+
const fs32 = await import("fs");
|
|
11177
|
+
watcher = fs32.watch(getConfigDir(), (_event, filename) => {
|
|
11008
11178
|
if (!filename || filename === "credentials.json")
|
|
11009
11179
|
changed = true;
|
|
11010
11180
|
});
|
|
@@ -11030,8 +11200,8 @@ async function waitForCredentialsOrTerminal(isRunning2) {
|
|
|
11030
11200
|
let changed = false;
|
|
11031
11201
|
let watcher = null;
|
|
11032
11202
|
try {
|
|
11033
|
-
const
|
|
11034
|
-
watcher =
|
|
11203
|
+
const fs32 = await import("fs");
|
|
11204
|
+
watcher = fs32.watch(getConfigDir(), (_event, filename) => {
|
|
11035
11205
|
if (!filename || filename === "credentials.json")
|
|
11036
11206
|
changed = true;
|
|
11037
11207
|
});
|
|
@@ -11302,6 +11472,7 @@ function mcpAiToolsKey(aiTools) {
|
|
|
11302
11472
|
}
|
|
11303
11473
|
async function reconcileMcpConfigs(repos, packageName) {
|
|
11304
11474
|
const shimCmd = packageName;
|
|
11475
|
+
const envSuffix = getConfigDir().endsWith("-staging") ? " (staging)" : "";
|
|
11305
11476
|
const { contextFolder, aiTools, graphOnly } = await readRawToolConfig();
|
|
11306
11477
|
for (const repo of repos) {
|
|
11307
11478
|
if (!repo.localPath)
|
|
@@ -11322,7 +11493,8 @@ async function reconcileMcpConfigs(repos, packageName) {
|
|
|
11322
11493
|
shimCmd,
|
|
11323
11494
|
contextFolder,
|
|
11324
11495
|
selectedTools: aiTools,
|
|
11325
|
-
variant
|
|
11496
|
+
variant,
|
|
11497
|
+
envSuffix
|
|
11326
11498
|
});
|
|
11327
11499
|
const written = results.filter((r) => r.detected && r.outcome?.status === "written");
|
|
11328
11500
|
if (written.length > 0) {
|
|
@@ -11534,7 +11706,7 @@ async function startListener() {
|
|
|
11534
11706
|
const packageName = true ? "repowisestage" : "repowise";
|
|
11535
11707
|
let currentVersion = "";
|
|
11536
11708
|
try {
|
|
11537
|
-
const selfDir =
|
|
11709
|
+
const selfDir = dirname18(fileURLToPath3(import.meta.url));
|
|
11538
11710
|
const pkgJsonPath = join42(selfDir, "..", "..", "package.json");
|
|
11539
11711
|
const pkgJson = JSON.parse(await readFile14(pkgJsonPath, "utf-8"));
|
|
11540
11712
|
currentVersion = pkgJson.version;
|
|
@@ -11744,10 +11916,25 @@ async function startListener() {
|
|
|
11744
11916
|
proactiveRefreshTimer.unref();
|
|
11745
11917
|
}
|
|
11746
11918
|
let lastCycleAt = Date.now();
|
|
11919
|
+
let endpointResumeFailed = false;
|
|
11920
|
+
let endpointResumeRetries = 0;
|
|
11747
11921
|
while (running) {
|
|
11748
11922
|
const wakeDrift = Date.now() - lastCycleAt;
|
|
11749
11923
|
await maybeRefreshOnWake(wakeDrift, pollIntervalMs);
|
|
11750
11924
|
lastCycleAt = Date.now();
|
|
11925
|
+
if (endpointResumeFailed) {
|
|
11926
|
+
try {
|
|
11927
|
+
await mcpRuntime?.server?.resumeEndpoint();
|
|
11928
|
+
endpointResumeFailed = false;
|
|
11929
|
+
endpointResumeRetries = 0;
|
|
11930
|
+
console.log("[mcp] endpoint file restored on retry");
|
|
11931
|
+
} catch {
|
|
11932
|
+
endpointResumeRetries++;
|
|
11933
|
+
if (endpointResumeRetries % 12 === 0) {
|
|
11934
|
+
console.warn(`[mcp] endpoint file still not restored after ${endpointResumeRetries.toString()} retries \u2014 MCP remains unreachable`);
|
|
11935
|
+
}
|
|
11936
|
+
}
|
|
11937
|
+
}
|
|
11751
11938
|
let anyAuthError = null;
|
|
11752
11939
|
let authErrorGroup = null;
|
|
11753
11940
|
let minPollInterval = pollIntervalMs;
|
|
@@ -12097,7 +12284,9 @@ async function startListener() {
|
|
|
12097
12284
|
try {
|
|
12098
12285
|
await mcpRuntime?.server?.resumeEndpoint();
|
|
12099
12286
|
} catch (err) {
|
|
12100
|
-
console.warn("[mcp] resumeEndpoint failed:", err instanceof Error ? err.message : String(err));
|
|
12287
|
+
console.warn("[mcp] resumeEndpoint failed (will retry each poll cycle):", err instanceof Error ? err.message : String(err));
|
|
12288
|
+
endpointResumeFailed = true;
|
|
12289
|
+
endpointResumeRetries = 0;
|
|
12101
12290
|
}
|
|
12102
12291
|
}
|
|
12103
12292
|
continue;
|
|
@@ -12253,7 +12442,7 @@ async function showWelcome(currentVersion) {
|
|
|
12253
12442
|
|
|
12254
12443
|
// src/commands/create.ts
|
|
12255
12444
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
12256
|
-
import { dirname as
|
|
12445
|
+
import { dirname as dirname20, join as join51 } from "path";
|
|
12257
12446
|
init_src();
|
|
12258
12447
|
import chalk8 from "chalk";
|
|
12259
12448
|
import ora from "ora";
|
|
@@ -12785,7 +12974,7 @@ async function writeToolConfigsForRepo(opts) {
|
|
|
12785
12974
|
|
|
12786
12975
|
// src/lib/mcp-resolver.ts
|
|
12787
12976
|
import { basename as basename4, join as join46 } from "path";
|
|
12788
|
-
import { promises as
|
|
12977
|
+
import { promises as fs22 } from "fs";
|
|
12789
12978
|
var MCP_WRITER_TOOLS = /* @__PURE__ */ new Set([
|
|
12790
12979
|
"claude-code",
|
|
12791
12980
|
"cursor",
|
|
@@ -12826,7 +13015,7 @@ function mcpConfigTargetForTool(tool, opts) {
|
|
|
12826
13015
|
async function mcpConfigState(target) {
|
|
12827
13016
|
let raw;
|
|
12828
13017
|
try {
|
|
12829
|
-
raw = await
|
|
13018
|
+
raw = await fs22.readFile(target.path, "utf-8");
|
|
12830
13019
|
} catch {
|
|
12831
13020
|
return "absent";
|
|
12832
13021
|
}
|
|
@@ -12879,7 +13068,7 @@ function ensureGitignore(repoRoot, entry) {
|
|
|
12879
13068
|
// src/lib/graph-cache.ts
|
|
12880
13069
|
init_config_dir();
|
|
12881
13070
|
import { mkdirSync, writeFileSync as writeFileSync2, renameSync, unlinkSync } from "fs";
|
|
12882
|
-
import { dirname as
|
|
13071
|
+
import { dirname as dirname19, join as join48 } from "path";
|
|
12883
13072
|
var SAFE_REPO_ID = /^[A-Za-z0-9_.-]{1,128}$/;
|
|
12884
13073
|
function assertSafeRepoId2(repoId) {
|
|
12885
13074
|
if (!repoId || typeof repoId !== "string" || !SAFE_REPO_ID.test(repoId) || repoId === "." || repoId === ".." || repoId.startsWith(".")) {
|
|
@@ -13007,7 +13196,7 @@ async function ensureGraphDownloaded(opts) {
|
|
|
13007
13196
|
return { status: "not_found", message: "EMPTY_GRAPH" };
|
|
13008
13197
|
}
|
|
13009
13198
|
try {
|
|
13010
|
-
mkdirSync(
|
|
13199
|
+
mkdirSync(dirname19(targetPath), { recursive: true });
|
|
13011
13200
|
const tmp = `${targetPath}.${String(process.pid)}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
13012
13201
|
try {
|
|
13013
13202
|
writeFileSync2(tmp, body, { encoding: "utf-8", mode: 384 });
|
|
@@ -13625,7 +13814,7 @@ async function promptDepInstallConsent(missing, opts) {
|
|
|
13625
13814
|
import chalk6 from "chalk";
|
|
13626
13815
|
|
|
13627
13816
|
// src/lib/dep-installer.ts
|
|
13628
|
-
import { promises as
|
|
13817
|
+
import { promises as fs23 } from "fs";
|
|
13629
13818
|
import { join as join49 } from "path";
|
|
13630
13819
|
var SUPPORTED_DEP_LANGUAGES = /* @__PURE__ */ new Set([
|
|
13631
13820
|
"typescript",
|
|
@@ -13636,7 +13825,7 @@ var SUPPORTED_DEP_LANGUAGES = /* @__PURE__ */ new Set([
|
|
|
13636
13825
|
]);
|
|
13637
13826
|
var exists = async (p) => {
|
|
13638
13827
|
try {
|
|
13639
|
-
await
|
|
13828
|
+
await fs23.access(p);
|
|
13640
13829
|
return true;
|
|
13641
13830
|
} catch {
|
|
13642
13831
|
return false;
|
|
@@ -13720,13 +13909,13 @@ async function detectMissingDeps(repoRoot, scopedLanguages) {
|
|
|
13720
13909
|
// src/lib/dep-installer-runner.ts
|
|
13721
13910
|
import { spawn as spawn11 } from "child_process";
|
|
13722
13911
|
import { createWriteStream as createWriteStream3 } from "fs";
|
|
13723
|
-
import { promises as
|
|
13912
|
+
import { promises as fs24 } from "fs";
|
|
13724
13913
|
import { join as join50 } from "path";
|
|
13725
13914
|
var DEFAULT_INSTALL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
13726
13915
|
async function runMissingDepInstalls(opts) {
|
|
13727
13916
|
const safeRepoId = opts.repoId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
13728
13917
|
const logPath2 = join50(getConfigDir2(), `install-log.${safeRepoId}.txt`);
|
|
13729
|
-
await
|
|
13918
|
+
await fs24.mkdir(getConfigDir2(), { recursive: true });
|
|
13730
13919
|
const stream = opts.logStream ?? createWriteStream3(logPath2, { flags: "a" });
|
|
13731
13920
|
stream.on("error", () => {
|
|
13732
13921
|
});
|
|
@@ -14410,7 +14599,7 @@ async function create() {
|
|
|
14410
14599
|
if (response.ok) {
|
|
14411
14600
|
const content = await response.text();
|
|
14412
14601
|
const filePath = join51(contextDir, file.fileName);
|
|
14413
|
-
mkdirSync2(
|
|
14602
|
+
mkdirSync2(dirname20(filePath), { recursive: true });
|
|
14414
14603
|
writeFileSync3(filePath, content, "utf-8");
|
|
14415
14604
|
downloadedCount++;
|
|
14416
14605
|
} else {
|
|
@@ -14638,7 +14827,7 @@ Files are stored on our servers (not in git). Retry when online.`
|
|
|
14638
14827
|
|
|
14639
14828
|
// src/commands/member.ts
|
|
14640
14829
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
14641
|
-
import { dirname as
|
|
14830
|
+
import { dirname as dirname21, join as join52, resolve, sep } from "path";
|
|
14642
14831
|
import chalk9 from "chalk";
|
|
14643
14832
|
import ora2 from "ora";
|
|
14644
14833
|
var DEFAULT_CONTEXT_FOLDER2 = "repowise-context";
|
|
@@ -14813,7 +15002,7 @@ async function member() {
|
|
|
14813
15002
|
const response = await fetch(presignedUrl);
|
|
14814
15003
|
if (response.ok) {
|
|
14815
15004
|
const content = await response.text();
|
|
14816
|
-
mkdirSync3(
|
|
15005
|
+
mkdirSync3(dirname21(safePath), { recursive: true });
|
|
14817
15006
|
writeFileSync4(safePath, content, "utf-8");
|
|
14818
15007
|
downloadedCount++;
|
|
14819
15008
|
} else {
|
|
@@ -14970,7 +15159,7 @@ import chalk10 from "chalk";
|
|
|
14970
15159
|
import ora3 from "ora";
|
|
14971
15160
|
|
|
14972
15161
|
// src/lib/tenant-graph-purge.ts
|
|
14973
|
-
import { promises as
|
|
15162
|
+
import { promises as fs25 } from "fs";
|
|
14974
15163
|
import { homedir as homedir8 } from "os";
|
|
14975
15164
|
import { join as join53 } from "path";
|
|
14976
15165
|
async function purgeForeignGraphs(validRepoIds, home = homedir8()) {
|
|
@@ -14978,7 +15167,7 @@ async function purgeForeignGraphs(validRepoIds, home = homedir8()) {
|
|
|
14978
15167
|
const result = { kept: [], removed: [] };
|
|
14979
15168
|
let entries;
|
|
14980
15169
|
try {
|
|
14981
|
-
entries = await
|
|
15170
|
+
entries = await fs25.readdir(graphsDir);
|
|
14982
15171
|
} catch (err) {
|
|
14983
15172
|
if (err.code === "ENOENT") return result;
|
|
14984
15173
|
throw err;
|
|
@@ -14994,13 +15183,13 @@ async function purgeForeignGraphs(validRepoIds, home = homedir8()) {
|
|
|
14994
15183
|
}
|
|
14995
15184
|
const path = join53(graphsDir, entry);
|
|
14996
15185
|
try {
|
|
14997
|
-
const stat8 = await
|
|
15186
|
+
const stat8 = await fs25.lstat(path);
|
|
14998
15187
|
if (stat8.isSymbolicLink()) {
|
|
14999
|
-
await
|
|
15188
|
+
await fs25.unlink(path);
|
|
15000
15189
|
result.removed.push(entry);
|
|
15001
15190
|
continue;
|
|
15002
15191
|
}
|
|
15003
|
-
await
|
|
15192
|
+
await fs25.rm(path, { recursive: true, force: true });
|
|
15004
15193
|
result.removed.push(entry);
|
|
15005
15194
|
} catch {
|
|
15006
15195
|
}
|
|
@@ -15200,7 +15389,7 @@ async function status() {
|
|
|
15200
15389
|
|
|
15201
15390
|
// src/commands/sync.ts
|
|
15202
15391
|
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
15203
|
-
import { dirname as
|
|
15392
|
+
import { dirname as dirname22, join as join55 } from "path";
|
|
15204
15393
|
import chalk12 from "chalk";
|
|
15205
15394
|
import ora4 from "ora";
|
|
15206
15395
|
var POLL_INTERVAL_MS2 = 3e3;
|
|
@@ -15366,7 +15555,7 @@ async function sync() {
|
|
|
15366
15555
|
if (response.ok) {
|
|
15367
15556
|
const content = await response.text();
|
|
15368
15557
|
const filePath = join55(contextDir, file.fileName);
|
|
15369
|
-
mkdirSync4(
|
|
15558
|
+
mkdirSync4(dirname22(filePath), { recursive: true });
|
|
15370
15559
|
writeFileSync5(filePath, content, "utf-8");
|
|
15371
15560
|
downloadedCount++;
|
|
15372
15561
|
} else {
|
|
@@ -15769,7 +15958,7 @@ async function toolsList() {
|
|
|
15769
15958
|
// src/commands/mcp-log.ts
|
|
15770
15959
|
import { createDecipheriv as createDecipheriv2 } from "crypto";
|
|
15771
15960
|
import { mkdir as mkdir19, readFile as readFile18, stat as stat7, writeFile as writeFile19 } from "fs/promises";
|
|
15772
|
-
import { dirname as
|
|
15961
|
+
import { dirname as dirname23, join as join56 } from "path";
|
|
15773
15962
|
var FLAG_FILE = "mcp-log.flag";
|
|
15774
15963
|
var LOG_FILE = "mcp-log.jsonl.enc";
|
|
15775
15964
|
var KEY_FILE = "mcp-log.key";
|
|
@@ -15784,7 +15973,7 @@ function logPath() {
|
|
|
15784
15973
|
}
|
|
15785
15974
|
async function writeFlag(flag) {
|
|
15786
15975
|
const path = flagPath();
|
|
15787
|
-
await mkdir19(
|
|
15976
|
+
await mkdir19(dirname23(path), { recursive: true });
|
|
15788
15977
|
await writeFile19(path, JSON.stringify(flag, null, 2), { encoding: "utf-8", mode: 384 });
|
|
15789
15978
|
}
|
|
15790
15979
|
async function mcpLogOn() {
|
|
@@ -16049,7 +16238,7 @@ async function mcpLog(subcommand, flags = {}) {
|
|
|
16049
16238
|
import chalk15 from "chalk";
|
|
16050
16239
|
|
|
16051
16240
|
// src/lib/graph-loader.ts
|
|
16052
|
-
import { promises as
|
|
16241
|
+
import { promises as fs26 } from "fs";
|
|
16053
16242
|
import { join as join57, resolve as resolve2 } from "path";
|
|
16054
16243
|
import { gunzipSync } from "zlib";
|
|
16055
16244
|
var RELATIVE_GRAPH_PATH = "repowise-context/.meta/dependency-graph.json";
|
|
@@ -16076,14 +16265,14 @@ async function loadGraph(repoRoot = process.cwd()) {
|
|
|
16076
16265
|
let graphPath = null;
|
|
16077
16266
|
let raw = null;
|
|
16078
16267
|
try {
|
|
16079
|
-
raw = await
|
|
16268
|
+
raw = await fs26.readFile(gzPath);
|
|
16080
16269
|
graphPath = gzPath;
|
|
16081
16270
|
} catch (err) {
|
|
16082
16271
|
if (err.code !== "ENOENT") throw err;
|
|
16083
16272
|
}
|
|
16084
16273
|
if (!raw) {
|
|
16085
16274
|
try {
|
|
16086
|
-
raw = await
|
|
16275
|
+
raw = await fs26.readFile(plainPath);
|
|
16087
16276
|
graphPath = plainPath;
|
|
16088
16277
|
} catch (err) {
|
|
16089
16278
|
if (err.code === "ENOENT") {
|
|
@@ -16482,13 +16671,13 @@ function registerQueryCommand(program2) {
|
|
|
16482
16671
|
}
|
|
16483
16672
|
|
|
16484
16673
|
// src/commands/uninstall.ts
|
|
16485
|
-
import { promises as
|
|
16674
|
+
import { promises as fs30 } from "fs";
|
|
16486
16675
|
import { homedir as homedir12 } from "os";
|
|
16487
16676
|
import { join as join61 } from "path";
|
|
16488
16677
|
import chalk16 from "chalk";
|
|
16489
16678
|
|
|
16490
16679
|
// src/lib/cleanup/marker-blocks.ts
|
|
16491
|
-
import { promises as
|
|
16680
|
+
import { promises as fs27 } from "fs";
|
|
16492
16681
|
import { join as join58 } from "path";
|
|
16493
16682
|
var MARKER_START = "<!-- repowise-start -->";
|
|
16494
16683
|
var MARKER_END = "<!-- repowise-end -->";
|
|
@@ -16505,7 +16694,7 @@ var CONTEXT_FILES = [
|
|
|
16505
16694
|
async function stripMarkerBlock(filePath) {
|
|
16506
16695
|
let raw;
|
|
16507
16696
|
try {
|
|
16508
|
-
raw = await
|
|
16697
|
+
raw = await fs27.readFile(filePath, "utf-8");
|
|
16509
16698
|
} catch (err) {
|
|
16510
16699
|
if (err.code === "ENOENT")
|
|
16511
16700
|
return { path: filePath, status: "missing" };
|
|
@@ -16520,10 +16709,10 @@ async function stripMarkerBlock(filePath) {
|
|
|
16520
16709
|
const after = raw.slice(endIdx + MARKER_END.length).replace(/^\n+/, "");
|
|
16521
16710
|
const stripped = (before + (before && after ? "\n\n" : "") + after).trim();
|
|
16522
16711
|
if (stripped.length === 0) {
|
|
16523
|
-
await
|
|
16712
|
+
await fs27.unlink(filePath);
|
|
16524
16713
|
return { path: filePath, status: "deleted" };
|
|
16525
16714
|
}
|
|
16526
|
-
await
|
|
16715
|
+
await fs27.writeFile(filePath, stripped + "\n", "utf-8");
|
|
16527
16716
|
return { path: filePath, status: "stripped" };
|
|
16528
16717
|
}
|
|
16529
16718
|
async function stripAllMarkerBlocks(repoRoot) {
|
|
@@ -16541,7 +16730,7 @@ async function stripAllMarkerBlocks(repoRoot) {
|
|
|
16541
16730
|
}
|
|
16542
16731
|
|
|
16543
16732
|
// src/lib/cleanup/mcp-configs.ts
|
|
16544
|
-
import { promises as
|
|
16733
|
+
import { promises as fs28 } from "fs";
|
|
16545
16734
|
import { join as join59 } from "path";
|
|
16546
16735
|
function mcpConfigPaths(repoRoot, home) {
|
|
16547
16736
|
return [
|
|
@@ -16559,7 +16748,7 @@ function mcpConfigPaths(repoRoot, home) {
|
|
|
16559
16748
|
async function removeRepowiseFromConfig(path, serverName) {
|
|
16560
16749
|
let raw;
|
|
16561
16750
|
try {
|
|
16562
|
-
raw = await
|
|
16751
|
+
raw = await fs28.readFile(path, "utf-8");
|
|
16563
16752
|
} catch (err) {
|
|
16564
16753
|
if (err.code === "ENOENT") return { path, status: "not-found" };
|
|
16565
16754
|
return { path, status: "error", error: err.message };
|
|
@@ -16579,7 +16768,7 @@ async function removeRepowiseFromConfig(path, serverName) {
|
|
|
16579
16768
|
} else {
|
|
16580
16769
|
next.mcpServers = servers;
|
|
16581
16770
|
}
|
|
16582
|
-
await
|
|
16771
|
+
await fs28.writeFile(path, JSON.stringify(next, null, 2) + "\n", "utf-8");
|
|
16583
16772
|
return { path, status: "removed" };
|
|
16584
16773
|
}
|
|
16585
16774
|
async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
@@ -16592,7 +16781,7 @@ async function removeAllMcpEntries(repoRoot, home, repoId) {
|
|
|
16592
16781
|
}
|
|
16593
16782
|
|
|
16594
16783
|
// src/lib/cleanup/local-state.ts
|
|
16595
|
-
import { promises as
|
|
16784
|
+
import { promises as fs29 } from "fs";
|
|
16596
16785
|
import { homedir as homedir11 } from "os";
|
|
16597
16786
|
import { join as join60, resolve as resolve3 } from "path";
|
|
16598
16787
|
async function clearLocalState(homeOverride) {
|
|
@@ -16602,7 +16791,7 @@ async function clearLocalState(homeOverride) {
|
|
|
16602
16791
|
return { path: target, status: "error", error: "refused: not under home" };
|
|
16603
16792
|
}
|
|
16604
16793
|
try {
|
|
16605
|
-
await
|
|
16794
|
+
await fs29.rm(target, { recursive: true, force: false });
|
|
16606
16795
|
return { path: target, status: "removed" };
|
|
16607
16796
|
} catch (err) {
|
|
16608
16797
|
if (err.code === "ENOENT")
|
|
@@ -16641,7 +16830,7 @@ async function uninstall2(opts = {}) {
|
|
|
16641
16830
|
else if (svc.error) report.skipped.push({ path: "listener service", reason: svc.error });
|
|
16642
16831
|
if (tier === "stop") return report;
|
|
16643
16832
|
try {
|
|
16644
|
-
await
|
|
16833
|
+
await fs30.unlink(join61(home, ".repowise", "credentials.json"));
|
|
16645
16834
|
report.removed.push("credentials");
|
|
16646
16835
|
} catch (err) {
|
|
16647
16836
|
if (err.code !== "ENOENT") {
|
|
@@ -16668,7 +16857,7 @@ async function uninstall2(opts = {}) {
|
|
|
16668
16857
|
const allPaths = mcpConfigPaths(repoRoot, home);
|
|
16669
16858
|
for (const p of allPaths) {
|
|
16670
16859
|
try {
|
|
16671
|
-
await
|
|
16860
|
+
await fs30.access(p);
|
|
16672
16861
|
} catch {
|
|
16673
16862
|
}
|
|
16674
16863
|
}
|
|
@@ -16680,7 +16869,7 @@ async function uninstall2(opts = {}) {
|
|
|
16680
16869
|
}
|
|
16681
16870
|
async function defaultLoadRepoIds(home) {
|
|
16682
16871
|
try {
|
|
16683
|
-
const raw = await
|
|
16872
|
+
const raw = await fs30.readFile(join61(home, ".repowise", "config.json"), "utf-8");
|
|
16684
16873
|
const parsed = JSON.parse(raw);
|
|
16685
16874
|
return (parsed.repos ?? []).map((r) => r.repoId);
|
|
16686
16875
|
} catch {
|
|
@@ -16727,7 +16916,7 @@ Done \u2014 ${report.removed.length} removed, ${report.skipped.length} skipped.
|
|
|
16727
16916
|
|
|
16728
16917
|
// src/commands/mcp-shim.ts
|
|
16729
16918
|
init_config_dir();
|
|
16730
|
-
import { promises as
|
|
16919
|
+
import { promises as fs31 } from "fs";
|
|
16731
16920
|
import { createInterface as createInterface2 } from "readline";
|
|
16732
16921
|
import { join as join62 } from "path";
|
|
16733
16922
|
var DEFAULT_MAX = 200 * 1024;
|
|
@@ -16773,8 +16962,10 @@ async function mcpShim(opts) {
|
|
|
16773
16962
|
const message = authState === "logged-out" ? (
|
|
16774
16963
|
// Agent-directed: the calling LLM can run this itself for a smoother UX
|
|
16775
16964
|
// (it auto-opens the browser; the user still completes sign-in). The
|
|
16776
|
-
// command is a fixed, argument-free string (nothing injectable).
|
|
16777
|
-
|
|
16965
|
+
// command is a fixed, argument-free string (nothing injectable). Use the
|
|
16966
|
+
// build-flavor binary (`repowise` vs `repowisestage`) so staging users
|
|
16967
|
+
// get the command that matches their install.
|
|
16968
|
+
`RepoWise isn't authenticated (this is rare \u2014 the session lasts about a year). To fix it, run the shell command \`${getPackageName()} login\` on the user's behalf \u2014 it opens a browser for them to sign in and blocks until they finish. Run it once, wait for it to complete, then retry this request. Do not repeat the command.`
|
|
16778
16969
|
) : "listener endpoint unavailable \u2014 is the listener running?";
|
|
16779
16970
|
writeJson(stdout, {
|
|
16780
16971
|
jsonrpc: "2.0",
|
|
@@ -16796,16 +16987,24 @@ async function mcpShim(opts) {
|
|
|
16796
16987
|
);
|
|
16797
16988
|
writeJson(stdout, response);
|
|
16798
16989
|
} catch (err) {
|
|
16799
|
-
stderr.write(`mcp-shim: ${err.message}
|
|
16800
|
-
`);
|
|
16801
16990
|
const name = err.name;
|
|
16802
16991
|
const detail = err.message;
|
|
16803
16992
|
const isTimeout = name === "TimeoutError" || name === "AbortError" || /timeout|aborted|abort/i.test(detail);
|
|
16993
|
+
if (!isTimeout && isConnectionError(err)) {
|
|
16994
|
+
stderr.write(
|
|
16995
|
+
`mcp-shim: listener unreachable (${detail}) \u2014 exiting so the client respawns a fresh shim.
|
|
16996
|
+
`,
|
|
16997
|
+
() => process.exit(1)
|
|
16998
|
+
);
|
|
16999
|
+
return;
|
|
17000
|
+
}
|
|
17001
|
+
stderr.write(`mcp-shim: ${detail}
|
|
17002
|
+
`);
|
|
16804
17003
|
writeJson(stdout, {
|
|
16805
17004
|
jsonrpc: "2.0",
|
|
16806
17005
|
error: isTimeout ? {
|
|
16807
17006
|
code: -32001,
|
|
16808
|
-
message:
|
|
17007
|
+
message: `RepoWise listener did not respond in time \u2014 it may be stuck. Restart it with \`${getPackageName()} restart\`, then retry.`,
|
|
16809
17008
|
data: { detail }
|
|
16810
17009
|
} : {
|
|
16811
17010
|
code: -32001,
|
|
@@ -16816,9 +17015,23 @@ async function mcpShim(opts) {
|
|
|
16816
17015
|
}
|
|
16817
17016
|
}
|
|
16818
17017
|
}
|
|
17018
|
+
function isConnectionError(err) {
|
|
17019
|
+
const CONN_CODES = /* @__PURE__ */ new Set([
|
|
17020
|
+
"ECONNREFUSED",
|
|
17021
|
+
"ECONNRESET",
|
|
17022
|
+
"EHOSTUNREACH",
|
|
17023
|
+
"ENETUNREACH",
|
|
17024
|
+
"ECONNABORTED"
|
|
17025
|
+
]);
|
|
17026
|
+
const e = err;
|
|
17027
|
+
if (e && typeof e.code === "string" && CONN_CODES.has(e.code)) return true;
|
|
17028
|
+
if (e && e.cause && typeof e.cause.code === "string" && CONN_CODES.has(e.cause.code)) return true;
|
|
17029
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
17030
|
+
return /ECONNREFUSED|ECONNRESET|EHOSTUNREACH|ENETUNREACH|fetch failed|socket hang up/i.test(msg);
|
|
17031
|
+
}
|
|
16819
17032
|
async function readEndpoint(path) {
|
|
16820
17033
|
try {
|
|
16821
|
-
const raw = (await
|
|
17034
|
+
const raw = (await fs31.readFile(path, "utf-8")).trim();
|
|
16822
17035
|
if (!raw) return null;
|
|
16823
17036
|
if (raw.startsWith("http://") || raw.startsWith("https://")) {
|
|
16824
17037
|
return { endpoint: raw.split("\n")[0].trim(), secret: null };
|
|
@@ -16839,7 +17052,7 @@ async function readEndpoint(path) {
|
|
|
16839
17052
|
async function readAuthState(credsPath) {
|
|
16840
17053
|
let raw;
|
|
16841
17054
|
try {
|
|
16842
|
-
raw = await
|
|
17055
|
+
raw = await fs31.readFile(credsPath, "utf-8");
|
|
16843
17056
|
} catch (err) {
|
|
16844
17057
|
if (err.code === "ENOENT") return "logged-out";
|
|
16845
17058
|
return "unknown";
|
|
@@ -16866,7 +17079,7 @@ async function routeMessage(endpoint, repoId, message, postJson, getJson, header
|
|
|
16866
17079
|
id: rpcId,
|
|
16867
17080
|
result: {
|
|
16868
17081
|
protocolVersion: "2024-11-05",
|
|
16869
|
-
serverInfo: { name:
|
|
17082
|
+
serverInfo: { name: getPackageName(), version: "0.0.0" },
|
|
16870
17083
|
capabilities: { tools: { listChanged: false } }
|
|
16871
17084
|
}
|
|
16872
17085
|
};
|
|
@@ -17514,7 +17727,7 @@ async function lspOn() {
|
|
|
17514
17727
|
|
|
17515
17728
|
// bin/repowise.ts
|
|
17516
17729
|
var __filename = fileURLToPath4(import.meta.url);
|
|
17517
|
-
var __dirname =
|
|
17730
|
+
var __dirname = dirname24(__filename);
|
|
17518
17731
|
var pkg = JSON.parse(readFileSync3(join63(__dirname, "..", "..", "package.json"), "utf-8"));
|
|
17519
17732
|
var program = new Command();
|
|
17520
17733
|
program.name(getPackageName()).description("AI-optimized codebase context generator").version(pkg.version).hook("preAction", async () => {
|