@staff0rd/assist 0.324.1 → 0.325.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/claude/settings.json +1 -1
- package/dist/index.js +900 -647
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.325.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -6011,8 +6011,10 @@ function extractPath(rest) {
|
|
|
6011
6011
|
const arrow = rest.indexOf(" -> ");
|
|
6012
6012
|
return arrow === -1 ? rest : rest.slice(arrow + 4);
|
|
6013
6013
|
}
|
|
6014
|
+
var UNMERGED_STATES = /* @__PURE__ */ new Set(["DD", "AU", "UD", "UA", "DU", "AA", "UU"]);
|
|
6014
6015
|
function categorize(xy) {
|
|
6015
6016
|
if (xy === "??") return "new";
|
|
6017
|
+
if (UNMERGED_STATES.has(xy)) return "modified";
|
|
6016
6018
|
const codes = xy.replace(/ /g, "");
|
|
6017
6019
|
if (codes.includes("A")) return "new";
|
|
6018
6020
|
if (codes.includes("D")) return "deleted";
|
|
@@ -9295,16 +9297,180 @@ function registerCliHook(program2) {
|
|
|
9295
9297
|
registerDeny(cmd);
|
|
9296
9298
|
}
|
|
9297
9299
|
|
|
9300
|
+
// src/commands/codeComment/codeCommentConfirm.ts
|
|
9301
|
+
import { existsSync as existsSync27, readFileSync as readFileSync22, unlinkSync as unlinkSync8, writeFileSync as writeFileSync22 } from "fs";
|
|
9302
|
+
import chalk92 from "chalk";
|
|
9303
|
+
|
|
9304
|
+
// src/commands/codeComment/getRestrictedDir.ts
|
|
9305
|
+
import { homedir as homedir11 } from "os";
|
|
9306
|
+
import { join as join25 } from "path";
|
|
9307
|
+
function getRestrictedDir() {
|
|
9308
|
+
return join25(homedir11(), ".assist", "restricted");
|
|
9309
|
+
}
|
|
9310
|
+
function getPinStatePath(pin) {
|
|
9311
|
+
return join25(getRestrictedDir(), `code-comment-${pin}.json`);
|
|
9312
|
+
}
|
|
9313
|
+
|
|
9314
|
+
// src/commands/codeComment/sweepRestrictedDir.ts
|
|
9315
|
+
import { readdirSync, statSync as statSync2, unlinkSync as unlinkSync7 } from "fs";
|
|
9316
|
+
import { join as join26 } from "path";
|
|
9317
|
+
var STALE_AFTER_MS = 30 * 60 * 1e3;
|
|
9318
|
+
function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
9319
|
+
let entries;
|
|
9320
|
+
try {
|
|
9321
|
+
entries = readdirSync(dir);
|
|
9322
|
+
} catch {
|
|
9323
|
+
return;
|
|
9324
|
+
}
|
|
9325
|
+
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
9326
|
+
for (const entry of entries) {
|
|
9327
|
+
const path57 = join26(dir, entry);
|
|
9328
|
+
try {
|
|
9329
|
+
if (statSync2(path57).mtimeMs < cutoff) unlinkSync7(path57);
|
|
9330
|
+
} catch {
|
|
9331
|
+
continue;
|
|
9332
|
+
}
|
|
9333
|
+
}
|
|
9334
|
+
}
|
|
9335
|
+
|
|
9336
|
+
// src/commands/codeComment/codeCommentConfirm.ts
|
|
9337
|
+
function readPinState(pin) {
|
|
9338
|
+
const path57 = getPinStatePath(pin);
|
|
9339
|
+
if (!existsSync27(path57)) return void 0;
|
|
9340
|
+
try {
|
|
9341
|
+
const state = JSON.parse(readFileSync22(path57, "utf8"));
|
|
9342
|
+
if (state.pin !== pin) return void 0;
|
|
9343
|
+
return state;
|
|
9344
|
+
} catch {
|
|
9345
|
+
return void 0;
|
|
9346
|
+
}
|
|
9347
|
+
}
|
|
9348
|
+
function codeCommentConfirm(pin) {
|
|
9349
|
+
sweepRestrictedDir();
|
|
9350
|
+
const state = readPinState(pin);
|
|
9351
|
+
if (!state) {
|
|
9352
|
+
console.error(chalk92.red(`No pending comment for pin: ${pin}`));
|
|
9353
|
+
process.exitCode = 1;
|
|
9354
|
+
return;
|
|
9355
|
+
}
|
|
9356
|
+
if (!existsSync27(state.file)) {
|
|
9357
|
+
console.error(chalk92.red(`Target file no longer exists: ${state.file}`));
|
|
9358
|
+
process.exitCode = 1;
|
|
9359
|
+
return;
|
|
9360
|
+
}
|
|
9361
|
+
const original = readFileSync22(state.file, "utf8");
|
|
9362
|
+
const lines = original.split("\n");
|
|
9363
|
+
const index3 = state.line - 1;
|
|
9364
|
+
if (index3 > lines.length) {
|
|
9365
|
+
console.error(
|
|
9366
|
+
chalk92.red(
|
|
9367
|
+
`Line ${state.line} is beyond the end of ${state.file} (${lines.length} lines).`
|
|
9368
|
+
)
|
|
9369
|
+
);
|
|
9370
|
+
process.exitCode = 1;
|
|
9371
|
+
return;
|
|
9372
|
+
}
|
|
9373
|
+
const indentSource = lines[index3] ?? "";
|
|
9374
|
+
const indent2 = indentSource.match(/^\s*/)?.[0] ?? "";
|
|
9375
|
+
lines.splice(index3, 0, `${indent2}// ${state.text}`);
|
|
9376
|
+
writeFileSync22(state.file, lines.join("\n"));
|
|
9377
|
+
unlinkSync8(getPinStatePath(pin));
|
|
9378
|
+
console.log(
|
|
9379
|
+
chalk92.green(`Inserted "// ${state.text}" at ${state.file}:${state.line}`)
|
|
9380
|
+
);
|
|
9381
|
+
}
|
|
9382
|
+
|
|
9383
|
+
// src/commands/codeComment/codeCommentSet.ts
|
|
9384
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync23 } from "fs";
|
|
9385
|
+
import { randomBytes } from "crypto";
|
|
9386
|
+
import chalk93 from "chalk";
|
|
9387
|
+
|
|
9388
|
+
// src/commands/codeComment/validateCommentText.ts
|
|
9389
|
+
var MAX_COMMENT_LENGTH = 50;
|
|
9390
|
+
function validateCommentText(raw) {
|
|
9391
|
+
const text6 = raw.replace(/^\/\/\s?/, "");
|
|
9392
|
+
if (/[\r\n]/.test(text6)) {
|
|
9393
|
+
return {
|
|
9394
|
+
ok: false,
|
|
9395
|
+
reason: "Comment must be a single line \u2014 multi-line comments are not allowed."
|
|
9396
|
+
};
|
|
9397
|
+
}
|
|
9398
|
+
if (text6.includes("/*") || text6.includes("*/")) {
|
|
9399
|
+
return {
|
|
9400
|
+
ok: false,
|
|
9401
|
+
reason: "Block comments (/* */) are not allowed \u2014 only single-line // comments."
|
|
9402
|
+
};
|
|
9403
|
+
}
|
|
9404
|
+
if (text6.length > MAX_COMMENT_LENGTH) {
|
|
9405
|
+
return {
|
|
9406
|
+
ok: false,
|
|
9407
|
+
reason: `Comment text is ${text6.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
|
|
9408
|
+
};
|
|
9409
|
+
}
|
|
9410
|
+
return { ok: true, text: text6 };
|
|
9411
|
+
}
|
|
9412
|
+
|
|
9413
|
+
// src/commands/codeComment/codeCommentSet.ts
|
|
9414
|
+
function generatePin() {
|
|
9415
|
+
return randomBytes(4).toString("hex");
|
|
9416
|
+
}
|
|
9417
|
+
function codeCommentSet(file, line, text6) {
|
|
9418
|
+
const lineNumber = Number.parseInt(line, 10);
|
|
9419
|
+
if (!Number.isInteger(lineNumber) || lineNumber < 1) {
|
|
9420
|
+
console.error(chalk93.red(`Invalid line number: ${line}`));
|
|
9421
|
+
process.exitCode = 1;
|
|
9422
|
+
return;
|
|
9423
|
+
}
|
|
9424
|
+
const validation = validateCommentText(text6);
|
|
9425
|
+
if (!validation.ok) {
|
|
9426
|
+
console.error(chalk93.red(`Refused: ${validation.reason}`));
|
|
9427
|
+
console.error(chalk93.red("No pin issued."));
|
|
9428
|
+
process.exitCode = 1;
|
|
9429
|
+
return;
|
|
9430
|
+
}
|
|
9431
|
+
console.error(
|
|
9432
|
+
chalk93.yellow.bold(
|
|
9433
|
+
"Think hard. Comments are a last resort, not a habit.\nAlmost every comment you reach for is a sign the code should be clearer instead.\nBefore you confirm this pin, ask whether a better name, a smaller function, or a\ntest would make the comment redundant. If you are still sure this one line earns\nits keep, run the confirm step below."
|
|
9434
|
+
)
|
|
9435
|
+
);
|
|
9436
|
+
const pin = generatePin();
|
|
9437
|
+
mkdirSync11(getRestrictedDir(), { recursive: true });
|
|
9438
|
+
sweepRestrictedDir();
|
|
9439
|
+
writeFileSync23(
|
|
9440
|
+
getPinStatePath(pin),
|
|
9441
|
+
JSON.stringify({ pin, file, line: lineNumber, text: validation.text })
|
|
9442
|
+
);
|
|
9443
|
+
console.log(
|
|
9444
|
+
`${chalk93.green(`Pin issued: ${pin}`)}
|
|
9445
|
+
To insert "// ${validation.text}" at ${file}:${lineNumber}, run:
|
|
9446
|
+
${chalk93.cyan(` assist code-comment confirm ${pin}`)}`
|
|
9447
|
+
);
|
|
9448
|
+
}
|
|
9449
|
+
|
|
9450
|
+
// src/commands/registerCodeComment.ts
|
|
9451
|
+
function registerCodeComment(parent) {
|
|
9452
|
+
const codeComment = parent.command("code-comment").description(
|
|
9453
|
+
"Escape hatch for the rare code comment that genuinely belongs"
|
|
9454
|
+
);
|
|
9455
|
+
codeComment.command("set").description(
|
|
9456
|
+
"Validate a single-line comment and issue a pin to confirm its insertion"
|
|
9457
|
+
).argument("<file>", "File the comment belongs in").argument("<line>", "1-based line number to insert the comment at").argument(
|
|
9458
|
+
"<text>",
|
|
9459
|
+
"Single-line comment text (max 50 chars, no block comments)"
|
|
9460
|
+
).action(codeCommentSet);
|
|
9461
|
+
codeComment.command("confirm").description("Confirm a pin to insert its comment and clear the pin state").argument("<pin>", "Pin issued by 'code-comment set'").action(codeCommentConfirm);
|
|
9462
|
+
}
|
|
9463
|
+
|
|
9298
9464
|
// src/commands/complexity/analyze.ts
|
|
9299
|
-
import
|
|
9465
|
+
import chalk102 from "chalk";
|
|
9300
9466
|
|
|
9301
9467
|
// src/commands/complexity/cyclomatic.ts
|
|
9302
|
-
import
|
|
9468
|
+
import chalk95 from "chalk";
|
|
9303
9469
|
|
|
9304
9470
|
// src/commands/complexity/shared/index.ts
|
|
9305
9471
|
import fs16 from "fs";
|
|
9306
9472
|
import path21 from "path";
|
|
9307
|
-
import
|
|
9473
|
+
import chalk94 from "chalk";
|
|
9308
9474
|
import ts5 from "typescript";
|
|
9309
9475
|
|
|
9310
9476
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -9555,7 +9721,7 @@ function createSourceFromFile(filePath) {
|
|
|
9555
9721
|
function withSourceFiles(pattern2, callback, extraIgnore = []) {
|
|
9556
9722
|
const files = findSourceFiles2(pattern2, ".", extraIgnore);
|
|
9557
9723
|
if (files.length === 0) {
|
|
9558
|
-
console.log(
|
|
9724
|
+
console.log(chalk94.yellow("No files found matching pattern"));
|
|
9559
9725
|
return void 0;
|
|
9560
9726
|
}
|
|
9561
9727
|
return callback(files);
|
|
@@ -9588,11 +9754,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
9588
9754
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
9589
9755
|
for (const { file, name, complexity } of results) {
|
|
9590
9756
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
9591
|
-
const color = exceedsThreshold ?
|
|
9592
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
9757
|
+
const color = exceedsThreshold ? chalk95.red : chalk95.white;
|
|
9758
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk95.cyan(complexity)}`);
|
|
9593
9759
|
}
|
|
9594
9760
|
console.log(
|
|
9595
|
-
|
|
9761
|
+
chalk95.dim(
|
|
9596
9762
|
`
|
|
9597
9763
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
9598
9764
|
)
|
|
@@ -9604,7 +9770,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
9604
9770
|
}
|
|
9605
9771
|
|
|
9606
9772
|
// src/commands/complexity/halstead.ts
|
|
9607
|
-
import
|
|
9773
|
+
import chalk96 from "chalk";
|
|
9608
9774
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
9609
9775
|
withSourceFiles(pattern2, (files) => {
|
|
9610
9776
|
const results = [];
|
|
@@ -9619,13 +9785,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
9619
9785
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
9620
9786
|
for (const { file, name, metrics } of results) {
|
|
9621
9787
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
9622
|
-
const color = exceedsThreshold ?
|
|
9788
|
+
const color = exceedsThreshold ? chalk96.red : chalk96.white;
|
|
9623
9789
|
console.log(
|
|
9624
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
9790
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk96.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk96.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk96.magenta(metrics.effort.toFixed(1))}`
|
|
9625
9791
|
);
|
|
9626
9792
|
}
|
|
9627
9793
|
console.log(
|
|
9628
|
-
|
|
9794
|
+
chalk96.dim(
|
|
9629
9795
|
`
|
|
9630
9796
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
9631
9797
|
)
|
|
@@ -9637,27 +9803,27 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
9637
9803
|
}
|
|
9638
9804
|
|
|
9639
9805
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
9640
|
-
import
|
|
9806
|
+
import chalk99 from "chalk";
|
|
9641
9807
|
|
|
9642
9808
|
// src/commands/complexity/maintainability/formatResultLine.ts
|
|
9643
|
-
import
|
|
9809
|
+
import chalk97 from "chalk";
|
|
9644
9810
|
function formatResultLine(entry, failing) {
|
|
9645
9811
|
const { file, avgMaintainability, minMaintainability, override } = entry;
|
|
9646
|
-
const name = failing ?
|
|
9647
|
-
const suffix = override !== void 0 ?
|
|
9648
|
-
return `${name} \u2192 avg: ${
|
|
9812
|
+
const name = failing ? chalk97.red(file) : chalk97.white(file);
|
|
9813
|
+
const suffix = override !== void 0 ? chalk97.magenta(` (override: ${override})`) : "";
|
|
9814
|
+
return `${name} \u2192 avg: ${chalk97.cyan(avgMaintainability.toFixed(1))}, min: ${chalk97.yellow(minMaintainability.toFixed(1))}${suffix}`;
|
|
9649
9815
|
}
|
|
9650
9816
|
|
|
9651
9817
|
// src/commands/complexity/maintainability/printMaintainabilityFailure.ts
|
|
9652
|
-
import
|
|
9818
|
+
import chalk98 from "chalk";
|
|
9653
9819
|
function printMaintainabilityFailure(failingCount, threshold) {
|
|
9654
9820
|
const thresholdLabel = threshold !== void 0 ? ` ${threshold}` : "";
|
|
9655
9821
|
console.error(
|
|
9656
|
-
|
|
9822
|
+
chalk98.red(
|
|
9657
9823
|
`
|
|
9658
9824
|
Fail: ${failingCount} file(s) below threshold${thresholdLabel} (files marked "(override: N)" were judged against their own marker). Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
9659
9825
|
|
|
9660
|
-
\u26A0\uFE0F ${
|
|
9826
|
+
\u26A0\uFE0F ${chalk98.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel.
|
|
9661
9827
|
|
|
9662
9828
|
The score is a property of the whole file, not your diff: any existing logic counts, so the fix is to shrink the file \u2014 not to revert or micro-optimize the lines you just changed. Identify the largest cohesive responsibility (often the biggest function, or a related group of functions) and move it to a new file with 'assist refactor extract'. Run 'assist complexity <file>' for per-function metrics only to locate that responsibility, not to tweak individual lines.`
|
|
9663
9829
|
)
|
|
@@ -9669,7 +9835,7 @@ function displayMaintainabilityResults(results, threshold) {
|
|
|
9669
9835
|
const gating = threshold !== void 0 || results.some((r) => r.override !== void 0);
|
|
9670
9836
|
if (!gating) {
|
|
9671
9837
|
for (const entry of results) console.log(formatResultLine(entry, false));
|
|
9672
|
-
console.log(
|
|
9838
|
+
console.log(chalk99.dim(`
|
|
9673
9839
|
Analyzed ${results.length} files`));
|
|
9674
9840
|
return;
|
|
9675
9841
|
}
|
|
@@ -9678,7 +9844,7 @@ Analyzed ${results.length} files`));
|
|
|
9678
9844
|
return limit !== void 0 && r.minMaintainability < limit;
|
|
9679
9845
|
});
|
|
9680
9846
|
if (failing.length === 0) {
|
|
9681
|
-
console.log(
|
|
9847
|
+
console.log(chalk99.green("All files pass maintainability threshold"));
|
|
9682
9848
|
} else {
|
|
9683
9849
|
for (const entry of failing) console.log(formatResultLine(entry, true));
|
|
9684
9850
|
}
|
|
@@ -9687,7 +9853,7 @@ Analyzed ${results.length} files`));
|
|
|
9687
9853
|
);
|
|
9688
9854
|
for (const entry of passingOverrides)
|
|
9689
9855
|
console.log(formatResultLine(entry, false));
|
|
9690
|
-
console.log(
|
|
9856
|
+
console.log(chalk99.dim(`
|
|
9691
9857
|
Analyzed ${results.length} files`));
|
|
9692
9858
|
if (failing.length > 0) {
|
|
9693
9859
|
printMaintainabilityFailure(failing.length, threshold);
|
|
@@ -9696,10 +9862,10 @@ Analyzed ${results.length} files`));
|
|
|
9696
9862
|
}
|
|
9697
9863
|
|
|
9698
9864
|
// src/commands/complexity/maintainability/printMaintainabilityFormula.ts
|
|
9699
|
-
import
|
|
9865
|
+
import chalk100 from "chalk";
|
|
9700
9866
|
var MI_FORMULA = "171 - 5.2*ln(HalsteadVolume) - 0.23*CyclomaticComplexity - 16.2*ln(SLOC), clamped 0-100";
|
|
9701
9867
|
function printMaintainabilityFormula() {
|
|
9702
|
-
console.log(
|
|
9868
|
+
console.log(chalk100.dim(MI_FORMULA));
|
|
9703
9869
|
}
|
|
9704
9870
|
|
|
9705
9871
|
// src/commands/complexity/maintainability/collectFileMetrics.ts
|
|
@@ -9775,7 +9941,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
9775
9941
|
|
|
9776
9942
|
// src/commands/complexity/sloc.ts
|
|
9777
9943
|
import fs18 from "fs";
|
|
9778
|
-
import
|
|
9944
|
+
import chalk101 from "chalk";
|
|
9779
9945
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
9780
9946
|
withSourceFiles(pattern2, (files) => {
|
|
9781
9947
|
const results = [];
|
|
@@ -9791,12 +9957,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
9791
9957
|
results.sort((a, b) => b.lines - a.lines);
|
|
9792
9958
|
for (const { file, lines } of results) {
|
|
9793
9959
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
9794
|
-
const color = exceedsThreshold ?
|
|
9795
|
-
console.log(`${color(file)} \u2192 ${
|
|
9960
|
+
const color = exceedsThreshold ? chalk101.red : chalk101.white;
|
|
9961
|
+
console.log(`${color(file)} \u2192 ${chalk101.cyan(lines)} lines`);
|
|
9796
9962
|
}
|
|
9797
9963
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
9798
9964
|
console.log(
|
|
9799
|
-
|
|
9965
|
+
chalk101.dim(`
|
|
9800
9966
|
Total: ${total} lines across ${files.length} files`)
|
|
9801
9967
|
);
|
|
9802
9968
|
if (hasViolation) {
|
|
@@ -9810,25 +9976,25 @@ async function analyze(pattern2) {
|
|
|
9810
9976
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
9811
9977
|
const files = findSourceFiles2(searchPattern);
|
|
9812
9978
|
if (files.length === 0) {
|
|
9813
|
-
console.log(
|
|
9979
|
+
console.log(chalk102.yellow("No files found matching pattern"));
|
|
9814
9980
|
return;
|
|
9815
9981
|
}
|
|
9816
9982
|
if (files.length === 1) {
|
|
9817
9983
|
const file = files[0];
|
|
9818
|
-
console.log(
|
|
9984
|
+
console.log(chalk102.bold.underline("SLOC"));
|
|
9819
9985
|
await sloc(file);
|
|
9820
9986
|
console.log();
|
|
9821
|
-
console.log(
|
|
9987
|
+
console.log(chalk102.bold.underline("Cyclomatic Complexity"));
|
|
9822
9988
|
await cyclomatic(file);
|
|
9823
9989
|
console.log();
|
|
9824
|
-
console.log(
|
|
9990
|
+
console.log(chalk102.bold.underline("Halstead Metrics"));
|
|
9825
9991
|
await halstead(file);
|
|
9826
9992
|
console.log();
|
|
9827
|
-
console.log(
|
|
9993
|
+
console.log(chalk102.bold.underline("Maintainability Index"));
|
|
9828
9994
|
await maintainability(file);
|
|
9829
9995
|
console.log();
|
|
9830
9996
|
console.log(
|
|
9831
|
-
|
|
9997
|
+
chalk102.dim(
|
|
9832
9998
|
"To improve the maintainability index, extract functions and logic out of this file into separate, smaller modules. Collapsing whitespace or removing comments is not the goal."
|
|
9833
9999
|
)
|
|
9834
10000
|
);
|
|
@@ -9862,7 +10028,7 @@ function registerComplexity(program2) {
|
|
|
9862
10028
|
}
|
|
9863
10029
|
|
|
9864
10030
|
// src/commands/config/index.ts
|
|
9865
|
-
import
|
|
10031
|
+
import chalk103 from "chalk";
|
|
9866
10032
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
9867
10033
|
|
|
9868
10034
|
// src/commands/config/setNestedValue.ts
|
|
@@ -9925,7 +10091,7 @@ function formatIssuePath(issue, key) {
|
|
|
9925
10091
|
function printValidationErrors(issues, key) {
|
|
9926
10092
|
for (const issue of issues) {
|
|
9927
10093
|
console.error(
|
|
9928
|
-
|
|
10094
|
+
chalk103.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
9929
10095
|
);
|
|
9930
10096
|
}
|
|
9931
10097
|
}
|
|
@@ -9942,7 +10108,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
9942
10108
|
function assertNotGlobalOnly(key, global) {
|
|
9943
10109
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
9944
10110
|
console.error(
|
|
9945
|
-
|
|
10111
|
+
chalk103.red(
|
|
9946
10112
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
9947
10113
|
)
|
|
9948
10114
|
);
|
|
@@ -9965,7 +10131,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
9965
10131
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
9966
10132
|
const target = options2.global ? "global" : "project";
|
|
9967
10133
|
console.log(
|
|
9968
|
-
|
|
10134
|
+
chalk103.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
9969
10135
|
);
|
|
9970
10136
|
}
|
|
9971
10137
|
function configList() {
|
|
@@ -9974,7 +10140,7 @@ function configList() {
|
|
|
9974
10140
|
}
|
|
9975
10141
|
|
|
9976
10142
|
// src/commands/config/configGet.ts
|
|
9977
|
-
import
|
|
10143
|
+
import chalk104 from "chalk";
|
|
9978
10144
|
|
|
9979
10145
|
// src/commands/config/getNestedValue.ts
|
|
9980
10146
|
function isTraversable(value) {
|
|
@@ -10006,7 +10172,7 @@ function requireNestedValue(config, key) {
|
|
|
10006
10172
|
return value;
|
|
10007
10173
|
}
|
|
10008
10174
|
function exitKeyNotSet(key) {
|
|
10009
|
-
console.error(
|
|
10175
|
+
console.error(chalk104.red(`Key "${key}" is not set`));
|
|
10010
10176
|
process.exit(1);
|
|
10011
10177
|
}
|
|
10012
10178
|
|
|
@@ -10019,8 +10185,8 @@ function registerConfig(program2) {
|
|
|
10019
10185
|
}
|
|
10020
10186
|
|
|
10021
10187
|
// src/commands/deploy/redirect.ts
|
|
10022
|
-
import { existsSync as
|
|
10023
|
-
import
|
|
10188
|
+
import { existsSync as existsSync28, readFileSync as readFileSync23, writeFileSync as writeFileSync24 } from "fs";
|
|
10189
|
+
import chalk105 from "chalk";
|
|
10024
10190
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
10025
10191
|
if (!window.location.pathname.endsWith('/')) {
|
|
10026
10192
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -10028,24 +10194,24 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
10028
10194
|
</script>`;
|
|
10029
10195
|
function redirect() {
|
|
10030
10196
|
const indexPath = "index.html";
|
|
10031
|
-
if (!
|
|
10032
|
-
console.log(
|
|
10197
|
+
if (!existsSync28(indexPath)) {
|
|
10198
|
+
console.log(chalk105.yellow("No index.html found"));
|
|
10033
10199
|
return;
|
|
10034
10200
|
}
|
|
10035
|
-
const content =
|
|
10201
|
+
const content = readFileSync23(indexPath, "utf8");
|
|
10036
10202
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
10037
|
-
console.log(
|
|
10203
|
+
console.log(chalk105.dim("Trailing slash script already present"));
|
|
10038
10204
|
return;
|
|
10039
10205
|
}
|
|
10040
10206
|
const headCloseIndex = content.indexOf("</head>");
|
|
10041
10207
|
if (headCloseIndex === -1) {
|
|
10042
|
-
console.log(
|
|
10208
|
+
console.log(chalk105.red("Could not find </head> tag in index.html"));
|
|
10043
10209
|
return;
|
|
10044
10210
|
}
|
|
10045
10211
|
const newContent = `${content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT}
|
|
10046
10212
|
${content.slice(headCloseIndex)}`;
|
|
10047
|
-
|
|
10048
|
-
console.log(
|
|
10213
|
+
writeFileSync24(indexPath, newContent);
|
|
10214
|
+
console.log(chalk105.green("Added trailing slash redirect to index.html"));
|
|
10049
10215
|
}
|
|
10050
10216
|
|
|
10051
10217
|
// src/commands/registerDeploy.ts
|
|
@@ -10060,11 +10226,11 @@ import { execFileSync as execFileSync2 } from "child_process";
|
|
|
10060
10226
|
import { basename as basename4 } from "path";
|
|
10061
10227
|
|
|
10062
10228
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
10063
|
-
import { homedir as
|
|
10064
|
-
import { join as
|
|
10065
|
-
var BLOG_REPO_ROOT =
|
|
10229
|
+
import { homedir as homedir12 } from "os";
|
|
10230
|
+
import { join as join27 } from "path";
|
|
10231
|
+
var BLOG_REPO_ROOT = join27(homedir12(), "git/blog");
|
|
10066
10232
|
function loadBlogSkipDays(repoName) {
|
|
10067
|
-
const config = loadRawYaml(
|
|
10233
|
+
const config = loadRawYaml(join27(BLOG_REPO_ROOT, "assist.yml"));
|
|
10068
10234
|
const devlog = config.devlog;
|
|
10069
10235
|
const skip2 = devlog?.skip;
|
|
10070
10236
|
return new Set(skip2?.[repoName]);
|
|
@@ -10072,20 +10238,20 @@ function loadBlogSkipDays(repoName) {
|
|
|
10072
10238
|
|
|
10073
10239
|
// src/commands/devlog/shared.ts
|
|
10074
10240
|
import { execSync as execSync23 } from "child_process";
|
|
10075
|
-
import
|
|
10241
|
+
import chalk106 from "chalk";
|
|
10076
10242
|
|
|
10077
10243
|
// src/shared/getRepoName.ts
|
|
10078
|
-
import { existsSync as
|
|
10079
|
-
import { basename as basename3, join as
|
|
10244
|
+
import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
|
|
10245
|
+
import { basename as basename3, join as join28 } from "path";
|
|
10080
10246
|
function getRepoName() {
|
|
10081
10247
|
const config = loadConfig();
|
|
10082
10248
|
if (config.devlog?.name) {
|
|
10083
10249
|
return config.devlog.name;
|
|
10084
10250
|
}
|
|
10085
|
-
const packageJsonPath =
|
|
10086
|
-
if (
|
|
10251
|
+
const packageJsonPath = join28(process.cwd(), "package.json");
|
|
10252
|
+
if (existsSync29(packageJsonPath)) {
|
|
10087
10253
|
try {
|
|
10088
|
-
const content =
|
|
10254
|
+
const content = readFileSync24(packageJsonPath, "utf8");
|
|
10089
10255
|
const pkg = JSON.parse(content);
|
|
10090
10256
|
if (pkg.name) {
|
|
10091
10257
|
return pkg.name;
|
|
@@ -10097,9 +10263,9 @@ function getRepoName() {
|
|
|
10097
10263
|
}
|
|
10098
10264
|
|
|
10099
10265
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
10100
|
-
import { readdirSync, readFileSync as
|
|
10101
|
-
import { join as
|
|
10102
|
-
var DEVLOG_DIR =
|
|
10266
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync25 } from "fs";
|
|
10267
|
+
import { join as join29 } from "path";
|
|
10268
|
+
var DEVLOG_DIR = join29(BLOG_REPO_ROOT, "src/content/devlog");
|
|
10103
10269
|
function extractFrontmatter(content) {
|
|
10104
10270
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
10105
10271
|
return fm?.[1] ?? null;
|
|
@@ -10125,9 +10291,9 @@ function parseFrontmatter(content, filename) {
|
|
|
10125
10291
|
}
|
|
10126
10292
|
function readDevlogFiles(callback) {
|
|
10127
10293
|
try {
|
|
10128
|
-
const files =
|
|
10294
|
+
const files = readdirSync2(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
10129
10295
|
for (const file of files) {
|
|
10130
|
-
const content =
|
|
10296
|
+
const content = readFileSync25(join29(DEVLOG_DIR, file), "utf8");
|
|
10131
10297
|
const parsed = parseFrontmatter(content, file);
|
|
10132
10298
|
if (parsed) callback(parsed);
|
|
10133
10299
|
}
|
|
@@ -10181,13 +10347,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
10181
10347
|
}
|
|
10182
10348
|
function printCommitsWithFiles(commits2, ignore2, verbose) {
|
|
10183
10349
|
for (const commit2 of commits2) {
|
|
10184
|
-
console.log(` ${
|
|
10350
|
+
console.log(` ${chalk106.yellow(commit2.hash)} ${commit2.message}`);
|
|
10185
10351
|
if (verbose) {
|
|
10186
10352
|
const visibleFiles = commit2.files.filter(
|
|
10187
10353
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
10188
10354
|
);
|
|
10189
10355
|
for (const file of visibleFiles) {
|
|
10190
|
-
console.log(` ${
|
|
10356
|
+
console.log(` ${chalk106.dim(file)}`);
|
|
10191
10357
|
}
|
|
10192
10358
|
}
|
|
10193
10359
|
}
|
|
@@ -10212,15 +10378,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
10212
10378
|
}
|
|
10213
10379
|
|
|
10214
10380
|
// src/commands/devlog/list/printDateHeader.ts
|
|
10215
|
-
import
|
|
10381
|
+
import chalk107 from "chalk";
|
|
10216
10382
|
function printDateHeader(date, isSkipped, entries) {
|
|
10217
10383
|
if (isSkipped) {
|
|
10218
|
-
console.log(`${
|
|
10384
|
+
console.log(`${chalk107.bold.blue(date)} ${chalk107.dim("skipped")}`);
|
|
10219
10385
|
} else if (entries && entries.length > 0) {
|
|
10220
|
-
const entryInfo = entries.map((e) => `${
|
|
10221
|
-
console.log(`${
|
|
10386
|
+
const entryInfo = entries.map((e) => `${chalk107.green(e.version)} ${e.title}`).join(" | ");
|
|
10387
|
+
console.log(`${chalk107.bold.blue(date)} ${entryInfo}`);
|
|
10222
10388
|
} else {
|
|
10223
|
-
console.log(`${
|
|
10389
|
+
console.log(`${chalk107.bold.blue(date)} ${chalk107.red("\u26A0 devlog missing")}`);
|
|
10224
10390
|
}
|
|
10225
10391
|
}
|
|
10226
10392
|
|
|
@@ -10324,24 +10490,24 @@ function bumpVersion(version2, type) {
|
|
|
10324
10490
|
|
|
10325
10491
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
10326
10492
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
10327
|
-
import
|
|
10493
|
+
import chalk109 from "chalk";
|
|
10328
10494
|
|
|
10329
10495
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
10330
|
-
import
|
|
10496
|
+
import chalk108 from "chalk";
|
|
10331
10497
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
10332
10498
|
if (conventional && firstHash) {
|
|
10333
10499
|
const version2 = getVersionAtCommit(firstHash);
|
|
10334
10500
|
if (version2) {
|
|
10335
|
-
console.log(`${
|
|
10501
|
+
console.log(`${chalk108.bold("version:")} ${stripToMinor(version2)}`);
|
|
10336
10502
|
} else {
|
|
10337
|
-
console.log(`${
|
|
10503
|
+
console.log(`${chalk108.bold("version:")} ${chalk108.red("unknown")}`);
|
|
10338
10504
|
}
|
|
10339
10505
|
} else if (patchVersion && minorVersion) {
|
|
10340
10506
|
console.log(
|
|
10341
|
-
`${
|
|
10507
|
+
`${chalk108.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
10342
10508
|
);
|
|
10343
10509
|
} else {
|
|
10344
|
-
console.log(`${
|
|
10510
|
+
console.log(`${chalk108.bold("version:")} v0.1 (initial)`);
|
|
10345
10511
|
}
|
|
10346
10512
|
}
|
|
10347
10513
|
|
|
@@ -10389,16 +10555,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
10389
10555
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
10390
10556
|
}
|
|
10391
10557
|
function logName(repoName) {
|
|
10392
|
-
console.log(`${
|
|
10558
|
+
console.log(`${chalk109.bold("name:")} ${repoName}`);
|
|
10393
10559
|
}
|
|
10394
10560
|
function displayNextEntry(ctx, targetDate, commits2) {
|
|
10395
10561
|
logName(ctx.repoName);
|
|
10396
10562
|
printVersionInfo(ctx.config, ctx.lastInfo, commits2[0]?.hash);
|
|
10397
|
-
console.log(
|
|
10563
|
+
console.log(chalk109.bold.blue(targetDate));
|
|
10398
10564
|
printCommitsWithFiles(commits2, ctx.ignore, ctx.verbose);
|
|
10399
10565
|
}
|
|
10400
10566
|
function logNoCommits(lastInfo) {
|
|
10401
|
-
console.log(
|
|
10567
|
+
console.log(chalk109.dim(noCommitsMessage(!!lastInfo)));
|
|
10402
10568
|
}
|
|
10403
10569
|
|
|
10404
10570
|
// src/commands/devlog/next/index.ts
|
|
@@ -10439,11 +10605,11 @@ function next2(options2) {
|
|
|
10439
10605
|
import { execSync as execSync25 } from "child_process";
|
|
10440
10606
|
|
|
10441
10607
|
// src/commands/devlog/repos/printReposTable.ts
|
|
10442
|
-
import
|
|
10608
|
+
import chalk110 from "chalk";
|
|
10443
10609
|
function colorStatus(status2) {
|
|
10444
|
-
if (status2 === "missing") return
|
|
10445
|
-
if (status2 === "outdated") return
|
|
10446
|
-
return
|
|
10610
|
+
if (status2 === "missing") return chalk110.red(status2);
|
|
10611
|
+
if (status2 === "outdated") return chalk110.yellow(status2);
|
|
10612
|
+
return chalk110.green(status2);
|
|
10447
10613
|
}
|
|
10448
10614
|
function formatRow(row, nameWidth) {
|
|
10449
10615
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -10457,8 +10623,8 @@ function printReposTable(rows) {
|
|
|
10457
10623
|
"Last Devlog".padEnd(11),
|
|
10458
10624
|
"Status"
|
|
10459
10625
|
].join(" ");
|
|
10460
|
-
console.log(
|
|
10461
|
-
console.log(
|
|
10626
|
+
console.log(chalk110.dim(header));
|
|
10627
|
+
console.log(chalk110.dim("-".repeat(header.length)));
|
|
10462
10628
|
for (const row of rows) {
|
|
10463
10629
|
console.log(formatRow(row, nameWidth));
|
|
10464
10630
|
}
|
|
@@ -10514,16 +10680,16 @@ function repos(options2) {
|
|
|
10514
10680
|
}
|
|
10515
10681
|
|
|
10516
10682
|
// src/commands/devlog/skip.ts
|
|
10517
|
-
import { writeFileSync as
|
|
10518
|
-
import { join as
|
|
10519
|
-
import
|
|
10683
|
+
import { writeFileSync as writeFileSync25 } from "fs";
|
|
10684
|
+
import { join as join30 } from "path";
|
|
10685
|
+
import chalk111 from "chalk";
|
|
10520
10686
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
10521
10687
|
function getBlogConfigPath() {
|
|
10522
|
-
return
|
|
10688
|
+
return join30(BLOG_REPO_ROOT, "assist.yml");
|
|
10523
10689
|
}
|
|
10524
10690
|
function skip(date) {
|
|
10525
10691
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
10526
|
-
console.log(
|
|
10692
|
+
console.log(chalk111.red("Invalid date format. Use YYYY-MM-DD"));
|
|
10527
10693
|
process.exit(1);
|
|
10528
10694
|
}
|
|
10529
10695
|
const repoName = getRepoName();
|
|
@@ -10534,7 +10700,7 @@ function skip(date) {
|
|
|
10534
10700
|
const skipDays = skip2[repoName] ?? [];
|
|
10535
10701
|
if (skipDays.includes(date)) {
|
|
10536
10702
|
console.log(
|
|
10537
|
-
|
|
10703
|
+
chalk111.yellow(`${date} is already in skip list for ${repoName}`)
|
|
10538
10704
|
);
|
|
10539
10705
|
return;
|
|
10540
10706
|
}
|
|
@@ -10543,21 +10709,21 @@ function skip(date) {
|
|
|
10543
10709
|
skip2[repoName] = skipDays;
|
|
10544
10710
|
devlog.skip = skip2;
|
|
10545
10711
|
config.devlog = devlog;
|
|
10546
|
-
|
|
10547
|
-
console.log(
|
|
10712
|
+
writeFileSync25(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
10713
|
+
console.log(chalk111.green(`Added ${date} to skip list for ${repoName}`));
|
|
10548
10714
|
}
|
|
10549
10715
|
|
|
10550
10716
|
// src/commands/devlog/version.ts
|
|
10551
|
-
import
|
|
10717
|
+
import chalk112 from "chalk";
|
|
10552
10718
|
function version() {
|
|
10553
10719
|
const config = loadConfig();
|
|
10554
10720
|
const name = getRepoName();
|
|
10555
10721
|
const lastInfo = getLastVersionInfo(name, config);
|
|
10556
10722
|
const lastVersion = lastInfo?.version ?? null;
|
|
10557
10723
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
10558
|
-
console.log(`${
|
|
10559
|
-
console.log(`${
|
|
10560
|
-
console.log(`${
|
|
10724
|
+
console.log(`${chalk112.bold("name:")} ${name}`);
|
|
10725
|
+
console.log(`${chalk112.bold("last:")} ${lastVersion ?? chalk112.dim("none")}`);
|
|
10726
|
+
console.log(`${chalk112.bold("next:")} ${nextVersion ?? chalk112.dim("none")}`);
|
|
10561
10727
|
}
|
|
10562
10728
|
|
|
10563
10729
|
// src/commands/registerDevlog.ts
|
|
@@ -10579,17 +10745,17 @@ function registerDevlog(program2) {
|
|
|
10579
10745
|
}
|
|
10580
10746
|
|
|
10581
10747
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
10582
|
-
import { closeSync as closeSync2, openSync as openSync2, readdirSync as
|
|
10583
|
-
import { join as
|
|
10584
|
-
import
|
|
10748
|
+
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync3 } from "fs";
|
|
10749
|
+
import { join as join31 } from "path";
|
|
10750
|
+
import chalk113 from "chalk";
|
|
10585
10751
|
|
|
10586
10752
|
// src/shared/findRepoRoot.ts
|
|
10587
|
-
import { existsSync as
|
|
10753
|
+
import { existsSync as existsSync30 } from "fs";
|
|
10588
10754
|
import path22 from "path";
|
|
10589
10755
|
function findRepoRoot(dir) {
|
|
10590
10756
|
let current = dir;
|
|
10591
10757
|
while (current !== path22.dirname(current)) {
|
|
10592
|
-
if (
|
|
10758
|
+
if (existsSync30(path22.join(current, ".git"))) {
|
|
10593
10759
|
return current;
|
|
10594
10760
|
}
|
|
10595
10761
|
current = path22.dirname(current);
|
|
@@ -10602,13 +10768,13 @@ var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "packages"]);
|
|
|
10602
10768
|
function isLockedDll(debugDir) {
|
|
10603
10769
|
let files;
|
|
10604
10770
|
try {
|
|
10605
|
-
files =
|
|
10771
|
+
files = readdirSync3(debugDir, { recursive: true });
|
|
10606
10772
|
} catch {
|
|
10607
10773
|
return null;
|
|
10608
10774
|
}
|
|
10609
10775
|
for (const file of files) {
|
|
10610
10776
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
10611
|
-
const dllPath =
|
|
10777
|
+
const dllPath = join31(debugDir, file);
|
|
10612
10778
|
try {
|
|
10613
10779
|
const fd = openSync2(dllPath, "r+");
|
|
10614
10780
|
closeSync2(fd);
|
|
@@ -10621,18 +10787,18 @@ function isLockedDll(debugDir) {
|
|
|
10621
10787
|
function findFirstLockedDll(dir) {
|
|
10622
10788
|
let entries;
|
|
10623
10789
|
try {
|
|
10624
|
-
entries =
|
|
10790
|
+
entries = readdirSync3(dir);
|
|
10625
10791
|
} catch {
|
|
10626
10792
|
return null;
|
|
10627
10793
|
}
|
|
10628
10794
|
if (entries.includes("bin")) {
|
|
10629
|
-
const locked = isLockedDll(
|
|
10795
|
+
const locked = isLockedDll(join31(dir, "bin", "Debug"));
|
|
10630
10796
|
if (locked) return locked;
|
|
10631
10797
|
}
|
|
10632
10798
|
for (const entry of entries) {
|
|
10633
10799
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
10634
10800
|
continue;
|
|
10635
|
-
const found = findFirstLockedDll(
|
|
10801
|
+
const found = findFirstLockedDll(join31(dir, entry));
|
|
10636
10802
|
if (found) return found;
|
|
10637
10803
|
}
|
|
10638
10804
|
return null;
|
|
@@ -10644,22 +10810,22 @@ function checkBuildLocks(startDir) {
|
|
|
10644
10810
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
10645
10811
|
if (locked) {
|
|
10646
10812
|
console.error(
|
|
10647
|
-
|
|
10813
|
+
chalk113.red("Build output locked (is VS debugging?): ") + locked
|
|
10648
10814
|
);
|
|
10649
10815
|
process.exit(1);
|
|
10650
10816
|
}
|
|
10651
10817
|
}
|
|
10652
10818
|
async function checkBuildLocksCommand() {
|
|
10653
10819
|
checkBuildLocks();
|
|
10654
|
-
console.log(
|
|
10820
|
+
console.log(chalk113.green("No build locks detected"));
|
|
10655
10821
|
}
|
|
10656
10822
|
|
|
10657
10823
|
// src/commands/dotnet/buildTree.ts
|
|
10658
|
-
import { readFileSync as
|
|
10824
|
+
import { readFileSync as readFileSync26 } from "fs";
|
|
10659
10825
|
import path23 from "path";
|
|
10660
10826
|
var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
|
|
10661
10827
|
function getProjectRefs(csprojPath) {
|
|
10662
|
-
const content =
|
|
10828
|
+
const content = readFileSync26(csprojPath, "utf8");
|
|
10663
10829
|
const refs = [];
|
|
10664
10830
|
for (const match of content.matchAll(PROJECT_REF_RE)) {
|
|
10665
10831
|
refs.push(match[1].replace(/\\/g, "/"));
|
|
@@ -10676,7 +10842,7 @@ function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
|
|
|
10676
10842
|
for (const ref of getProjectRefs(abs)) {
|
|
10677
10843
|
const childAbs = path23.resolve(dir, ref);
|
|
10678
10844
|
try {
|
|
10679
|
-
|
|
10845
|
+
readFileSync26(childAbs);
|
|
10680
10846
|
node.children.push(buildTree(childAbs, repoRoot, visited));
|
|
10681
10847
|
} catch {
|
|
10682
10848
|
node.children.push({
|
|
@@ -10701,14 +10867,14 @@ function collectAllDeps(node) {
|
|
|
10701
10867
|
}
|
|
10702
10868
|
|
|
10703
10869
|
// src/commands/dotnet/findContainingSolutions.ts
|
|
10704
|
-
import { readdirSync as
|
|
10870
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync27, statSync as statSync3 } from "fs";
|
|
10705
10871
|
import path24 from "path";
|
|
10706
10872
|
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
10707
10873
|
if (depth > maxDepth) return [];
|
|
10708
10874
|
const results = [];
|
|
10709
10875
|
let entries;
|
|
10710
10876
|
try {
|
|
10711
|
-
entries =
|
|
10877
|
+
entries = readdirSync4(dir);
|
|
10712
10878
|
} catch {
|
|
10713
10879
|
return results;
|
|
10714
10880
|
}
|
|
@@ -10717,7 +10883,7 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
10717
10883
|
continue;
|
|
10718
10884
|
const full = path24.join(dir, entry);
|
|
10719
10885
|
try {
|
|
10720
|
-
const stat2 =
|
|
10886
|
+
const stat2 = statSync3(full);
|
|
10721
10887
|
if (stat2.isFile() && entry.endsWith(".sln")) {
|
|
10722
10888
|
results.push(full);
|
|
10723
10889
|
} else if (stat2.isDirectory()) {
|
|
@@ -10736,7 +10902,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
|
|
|
10736
10902
|
const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
|
|
10737
10903
|
for (const sln of slnFiles) {
|
|
10738
10904
|
try {
|
|
10739
|
-
const content =
|
|
10905
|
+
const content = readFileSync27(sln, "utf8");
|
|
10740
10906
|
if (pattern2.test(content)) {
|
|
10741
10907
|
matches.push(path24.relative(repoRoot, sln));
|
|
10742
10908
|
}
|
|
@@ -10750,30 +10916,30 @@ function escapeRegex(s) {
|
|
|
10750
10916
|
}
|
|
10751
10917
|
|
|
10752
10918
|
// src/commands/dotnet/printTree.ts
|
|
10753
|
-
import
|
|
10919
|
+
import chalk114 from "chalk";
|
|
10754
10920
|
function printNodes(nodes, prefix2) {
|
|
10755
10921
|
for (let i = 0; i < nodes.length; i++) {
|
|
10756
10922
|
const isLast = i === nodes.length - 1;
|
|
10757
10923
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
10758
10924
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
10759
10925
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
10760
|
-
const label2 = isMissing ?
|
|
10926
|
+
const label2 = isMissing ? chalk114.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
10761
10927
|
console.log(`${prefix2}${connector}${label2}`);
|
|
10762
10928
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
10763
10929
|
}
|
|
10764
10930
|
}
|
|
10765
10931
|
function printTree(tree, totalCount, solutions) {
|
|
10766
|
-
console.log(
|
|
10767
|
-
console.log(
|
|
10932
|
+
console.log(chalk114.bold("\nProject Dependency Tree"));
|
|
10933
|
+
console.log(chalk114.cyan(tree.relativePath));
|
|
10768
10934
|
printNodes(tree.children, "");
|
|
10769
|
-
console.log(
|
|
10935
|
+
console.log(chalk114.dim(`
|
|
10770
10936
|
${totalCount} projects total (including root)`));
|
|
10771
|
-
console.log(
|
|
10937
|
+
console.log(chalk114.bold("\nSolution Membership"));
|
|
10772
10938
|
if (solutions.length === 0) {
|
|
10773
|
-
console.log(
|
|
10939
|
+
console.log(chalk114.yellow(" Not found in any .sln"));
|
|
10774
10940
|
} else {
|
|
10775
10941
|
for (const sln of solutions) {
|
|
10776
|
-
console.log(` ${
|
|
10942
|
+
console.log(` ${chalk114.green(sln)}`);
|
|
10777
10943
|
}
|
|
10778
10944
|
}
|
|
10779
10945
|
console.log();
|
|
@@ -10800,18 +10966,18 @@ function printJson(tree, totalCount, solutions) {
|
|
|
10800
10966
|
}
|
|
10801
10967
|
|
|
10802
10968
|
// src/commands/dotnet/resolveCsproj.ts
|
|
10803
|
-
import { existsSync as
|
|
10969
|
+
import { existsSync as existsSync31 } from "fs";
|
|
10804
10970
|
import path25 from "path";
|
|
10805
|
-
import
|
|
10971
|
+
import chalk115 from "chalk";
|
|
10806
10972
|
function resolveCsproj(csprojPath) {
|
|
10807
10973
|
const resolved = path25.resolve(csprojPath);
|
|
10808
|
-
if (!
|
|
10809
|
-
console.error(
|
|
10974
|
+
if (!existsSync31(resolved)) {
|
|
10975
|
+
console.error(chalk115.red(`File not found: ${resolved}`));
|
|
10810
10976
|
process.exit(1);
|
|
10811
10977
|
}
|
|
10812
10978
|
const repoRoot = findRepoRoot(path25.dirname(resolved));
|
|
10813
10979
|
if (!repoRoot) {
|
|
10814
|
-
console.error(
|
|
10980
|
+
console.error(chalk115.red("Could not find git repository root"));
|
|
10815
10981
|
process.exit(1);
|
|
10816
10982
|
}
|
|
10817
10983
|
return { resolved, repoRoot };
|
|
@@ -10861,12 +11027,12 @@ function getChangedCsFiles(scope) {
|
|
|
10861
11027
|
}
|
|
10862
11028
|
|
|
10863
11029
|
// src/commands/dotnet/inSln.ts
|
|
10864
|
-
import
|
|
11030
|
+
import chalk116 from "chalk";
|
|
10865
11031
|
async function inSln(csprojPath) {
|
|
10866
11032
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
10867
11033
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
10868
11034
|
if (solutions.length === 0) {
|
|
10869
|
-
console.log(
|
|
11035
|
+
console.log(chalk116.yellow("Not found in any .sln file"));
|
|
10870
11036
|
process.exit(1);
|
|
10871
11037
|
}
|
|
10872
11038
|
for (const sln of solutions) {
|
|
@@ -10875,7 +11041,7 @@ async function inSln(csprojPath) {
|
|
|
10875
11041
|
}
|
|
10876
11042
|
|
|
10877
11043
|
// src/commands/dotnet/inspect.ts
|
|
10878
|
-
import
|
|
11044
|
+
import chalk122 from "chalk";
|
|
10879
11045
|
|
|
10880
11046
|
// src/shared/formatElapsed.ts
|
|
10881
11047
|
function formatElapsed(ms) {
|
|
@@ -10887,12 +11053,12 @@ function formatElapsed(ms) {
|
|
|
10887
11053
|
}
|
|
10888
11054
|
|
|
10889
11055
|
// src/commands/dotnet/displayIssues.ts
|
|
10890
|
-
import
|
|
11056
|
+
import chalk117 from "chalk";
|
|
10891
11057
|
var SEVERITY_COLOR = {
|
|
10892
|
-
ERROR:
|
|
10893
|
-
WARNING:
|
|
10894
|
-
SUGGESTION:
|
|
10895
|
-
HINT:
|
|
11058
|
+
ERROR: chalk117.red,
|
|
11059
|
+
WARNING: chalk117.yellow,
|
|
11060
|
+
SUGGESTION: chalk117.cyan,
|
|
11061
|
+
HINT: chalk117.dim
|
|
10896
11062
|
};
|
|
10897
11063
|
function groupByFile(issues) {
|
|
10898
11064
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -10908,15 +11074,15 @@ function groupByFile(issues) {
|
|
|
10908
11074
|
}
|
|
10909
11075
|
function displayIssues(issues) {
|
|
10910
11076
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
10911
|
-
console.log(
|
|
11077
|
+
console.log(chalk117.bold(file));
|
|
10912
11078
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
10913
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
11079
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk117.white;
|
|
10914
11080
|
console.log(
|
|
10915
|
-
` ${
|
|
11081
|
+
` ${chalk117.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
10916
11082
|
);
|
|
10917
11083
|
}
|
|
10918
11084
|
}
|
|
10919
|
-
console.log(
|
|
11085
|
+
console.log(chalk117.dim(`
|
|
10920
11086
|
${issues.length} issue(s) found`));
|
|
10921
11087
|
}
|
|
10922
11088
|
|
|
@@ -10973,17 +11139,17 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
10973
11139
|
}
|
|
10974
11140
|
|
|
10975
11141
|
// src/commands/dotnet/resolveSolution.ts
|
|
10976
|
-
import { existsSync as
|
|
11142
|
+
import { existsSync as existsSync32 } from "fs";
|
|
10977
11143
|
import path26 from "path";
|
|
10978
|
-
import
|
|
11144
|
+
import chalk119 from "chalk";
|
|
10979
11145
|
|
|
10980
11146
|
// src/commands/dotnet/findSolution.ts
|
|
10981
|
-
import { readdirSync as
|
|
10982
|
-
import { dirname as dirname18, join as
|
|
10983
|
-
import
|
|
11147
|
+
import { readdirSync as readdirSync5 } from "fs";
|
|
11148
|
+
import { dirname as dirname18, join as join32 } from "path";
|
|
11149
|
+
import chalk118 from "chalk";
|
|
10984
11150
|
function findSlnInDir(dir) {
|
|
10985
11151
|
try {
|
|
10986
|
-
return
|
|
11152
|
+
return readdirSync5(dir).filter((f) => f.endsWith(".sln")).map((f) => join32(dir, f));
|
|
10987
11153
|
} catch {
|
|
10988
11154
|
return [];
|
|
10989
11155
|
}
|
|
@@ -10996,17 +11162,17 @@ function findSolution() {
|
|
|
10996
11162
|
const slnFiles = findSlnInDir(current);
|
|
10997
11163
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
10998
11164
|
if (slnFiles.length > 1) {
|
|
10999
|
-
console.error(
|
|
11165
|
+
console.error(chalk118.red(`Multiple .sln files found in ${current}:`));
|
|
11000
11166
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
11001
11167
|
console.error(
|
|
11002
|
-
|
|
11168
|
+
chalk118.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
11003
11169
|
);
|
|
11004
11170
|
process.exit(1);
|
|
11005
11171
|
}
|
|
11006
11172
|
if (current === ceiling) break;
|
|
11007
11173
|
current = dirname18(current);
|
|
11008
11174
|
}
|
|
11009
|
-
console.error(
|
|
11175
|
+
console.error(chalk118.red("No .sln file found between cwd and repo root"));
|
|
11010
11176
|
process.exit(1);
|
|
11011
11177
|
}
|
|
11012
11178
|
|
|
@@ -11014,8 +11180,8 @@ function findSolution() {
|
|
|
11014
11180
|
function resolveSolution(sln) {
|
|
11015
11181
|
if (sln) {
|
|
11016
11182
|
const resolved = path26.resolve(sln);
|
|
11017
|
-
if (!
|
|
11018
|
-
console.error(
|
|
11183
|
+
if (!existsSync32(resolved)) {
|
|
11184
|
+
console.error(chalk119.red(`Solution file not found: ${resolved}`));
|
|
11019
11185
|
process.exit(1);
|
|
11020
11186
|
}
|
|
11021
11187
|
return resolved;
|
|
@@ -11054,17 +11220,17 @@ function parseInspectReport(json) {
|
|
|
11054
11220
|
|
|
11055
11221
|
// src/commands/dotnet/runInspectCode.ts
|
|
11056
11222
|
import { execSync as execSync27 } from "child_process";
|
|
11057
|
-
import { existsSync as
|
|
11223
|
+
import { existsSync as existsSync33, readFileSync as readFileSync28, unlinkSync as unlinkSync9 } from "fs";
|
|
11058
11224
|
import { tmpdir as tmpdir3 } from "os";
|
|
11059
11225
|
import path27 from "path";
|
|
11060
|
-
import
|
|
11226
|
+
import chalk120 from "chalk";
|
|
11061
11227
|
function assertJbInstalled() {
|
|
11062
11228
|
try {
|
|
11063
11229
|
execSync27("jb inspectcode --version", { stdio: "pipe" });
|
|
11064
11230
|
} catch {
|
|
11065
|
-
console.error(
|
|
11231
|
+
console.error(chalk120.red("jb is not installed. Install with:"));
|
|
11066
11232
|
console.error(
|
|
11067
|
-
|
|
11233
|
+
chalk120.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
11068
11234
|
);
|
|
11069
11235
|
process.exit(1);
|
|
11070
11236
|
}
|
|
@@ -11082,21 +11248,21 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
11082
11248
|
if (error && typeof error === "object" && "stderr" in error) {
|
|
11083
11249
|
process.stderr.write(error.stderr);
|
|
11084
11250
|
}
|
|
11085
|
-
console.error(
|
|
11251
|
+
console.error(chalk120.red("jb inspectcode failed"));
|
|
11086
11252
|
process.exit(1);
|
|
11087
11253
|
}
|
|
11088
|
-
if (!
|
|
11089
|
-
console.error(
|
|
11254
|
+
if (!existsSync33(reportPath)) {
|
|
11255
|
+
console.error(chalk120.red("Report file not generated"));
|
|
11090
11256
|
process.exit(1);
|
|
11091
11257
|
}
|
|
11092
|
-
const xml =
|
|
11093
|
-
|
|
11258
|
+
const xml = readFileSync28(reportPath, "utf8");
|
|
11259
|
+
unlinkSync9(reportPath);
|
|
11094
11260
|
return xml;
|
|
11095
11261
|
}
|
|
11096
11262
|
|
|
11097
11263
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
11098
11264
|
import { execSync as execSync28 } from "child_process";
|
|
11099
|
-
import
|
|
11265
|
+
import chalk121 from "chalk";
|
|
11100
11266
|
function resolveMsbuildPath() {
|
|
11101
11267
|
const { run: run4 } = loadConfig();
|
|
11102
11268
|
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
@@ -11108,9 +11274,9 @@ function assertMsbuildInstalled() {
|
|
|
11108
11274
|
try {
|
|
11109
11275
|
execSync28(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
11110
11276
|
} catch {
|
|
11111
|
-
console.error(
|
|
11277
|
+
console.error(chalk121.red(`msbuild not found at: ${msbuild}`));
|
|
11112
11278
|
console.error(
|
|
11113
|
-
|
|
11279
|
+
chalk121.yellow(
|
|
11114
11280
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
11115
11281
|
)
|
|
11116
11282
|
);
|
|
@@ -11157,17 +11323,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
11157
11323
|
// src/commands/dotnet/inspect.ts
|
|
11158
11324
|
function logScope(changedFiles) {
|
|
11159
11325
|
if (changedFiles === null) {
|
|
11160
|
-
console.log(
|
|
11326
|
+
console.log(chalk122.dim("Inspecting full solution..."));
|
|
11161
11327
|
} else {
|
|
11162
11328
|
console.log(
|
|
11163
|
-
|
|
11329
|
+
chalk122.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
11164
11330
|
);
|
|
11165
11331
|
}
|
|
11166
11332
|
}
|
|
11167
11333
|
function reportResults(issues, elapsed) {
|
|
11168
11334
|
if (issues.length > 0) displayIssues(issues);
|
|
11169
|
-
else console.log(
|
|
11170
|
-
console.log(
|
|
11335
|
+
else console.log(chalk122.green("No issues found"));
|
|
11336
|
+
console.log(chalk122.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
11171
11337
|
if (issues.length > 0) process.exit(1);
|
|
11172
11338
|
}
|
|
11173
11339
|
async function inspect(sln, options2) {
|
|
@@ -11178,7 +11344,7 @@ async function inspect(sln, options2) {
|
|
|
11178
11344
|
const scope = parseScope(options2.scope);
|
|
11179
11345
|
const changedFiles = getChangedCsFiles(scope);
|
|
11180
11346
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
11181
|
-
console.log(
|
|
11347
|
+
console.log(chalk122.green("No changed .cs files found"));
|
|
11182
11348
|
return;
|
|
11183
11349
|
}
|
|
11184
11350
|
logScope(changedFiles);
|
|
@@ -11206,8 +11372,94 @@ function registerDotnet(program2) {
|
|
|
11206
11372
|
// src/commands/editHook/index.ts
|
|
11207
11373
|
import fs19 from "fs";
|
|
11208
11374
|
|
|
11375
|
+
// src/commands/editHook/extractComments.ts
|
|
11376
|
+
var SOURCE_EXTENSIONS2 = [
|
|
11377
|
+
".ts",
|
|
11378
|
+
".tsx",
|
|
11379
|
+
".cts",
|
|
11380
|
+
".mts",
|
|
11381
|
+
".js",
|
|
11382
|
+
".jsx",
|
|
11383
|
+
".cjs",
|
|
11384
|
+
".mjs"
|
|
11385
|
+
];
|
|
11386
|
+
function isSourceFile(filePath) {
|
|
11387
|
+
if (!filePath) return false;
|
|
11388
|
+
return SOURCE_EXTENSIONS2.some((ext) => filePath.endsWith(ext));
|
|
11389
|
+
}
|
|
11390
|
+
function blankNonNewline(text6) {
|
|
11391
|
+
return text6.replace(/[^\n]/g, " ");
|
|
11392
|
+
}
|
|
11393
|
+
function extractComments(text6) {
|
|
11394
|
+
const comments3 = [];
|
|
11395
|
+
let work = text6.replace(
|
|
11396
|
+
/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`/g,
|
|
11397
|
+
blankNonNewline
|
|
11398
|
+
);
|
|
11399
|
+
work = work.replace(/\/\*[\s\S]*?\*\//g, (match) => {
|
|
11400
|
+
comments3.push(match);
|
|
11401
|
+
return blankNonNewline(match);
|
|
11402
|
+
});
|
|
11403
|
+
for (const match of work.matchAll(/\/\/.*/g)) {
|
|
11404
|
+
comments3.push(match[0]);
|
|
11405
|
+
}
|
|
11406
|
+
return comments3.map((comment3) => comment3.replace(/\s+/g, " ").trim()).filter((comment3) => comment3.length > 0).filter((comment3) => !isCommentExempt(comment3));
|
|
11407
|
+
}
|
|
11408
|
+
|
|
11409
|
+
// src/commands/editHook/decideCommentGuard.ts
|
|
11410
|
+
var DENY_REASON = 'This edit introduces a code comment, which is blocked by the comment gate. Comments are a last resort \u2014 prefer a clearer name, a smaller function, or a test that makes the comment unnecessary. The comment must not appear in your edit itself. If this one line genuinely earns its keep, use the escape hatch: run `assist code-comment set <file> <line> "<text>"` (single line, max 50 chars, no block comments) to get a pin, then `assist code-comment confirm <pin>` to insert it.';
|
|
11411
|
+
function defined(values) {
|
|
11412
|
+
return values.filter((value) => value != null);
|
|
11413
|
+
}
|
|
11414
|
+
function partitionStrings(input, existingContent) {
|
|
11415
|
+
const { tool_name, tool_input } = input;
|
|
11416
|
+
switch (tool_name) {
|
|
11417
|
+
case "Edit":
|
|
11418
|
+
return {
|
|
11419
|
+
added: defined([tool_input.new_string]),
|
|
11420
|
+
removed: defined([tool_input.old_string])
|
|
11421
|
+
};
|
|
11422
|
+
case "MultiEdit": {
|
|
11423
|
+
const edits = tool_input.edits ?? [];
|
|
11424
|
+
return {
|
|
11425
|
+
added: defined(edits.map((e) => e.new_string)),
|
|
11426
|
+
removed: defined(edits.map((e) => e.old_string))
|
|
11427
|
+
};
|
|
11428
|
+
}
|
|
11429
|
+
case "Write":
|
|
11430
|
+
return {
|
|
11431
|
+
added: defined([tool_input.content]),
|
|
11432
|
+
removed: defined([existingContent])
|
|
11433
|
+
};
|
|
11434
|
+
default:
|
|
11435
|
+
return { added: [], removed: [] };
|
|
11436
|
+
}
|
|
11437
|
+
}
|
|
11438
|
+
function introducedComments(added, removed) {
|
|
11439
|
+
const counts = /* @__PURE__ */ new Map();
|
|
11440
|
+
for (const comment3 of removed) {
|
|
11441
|
+
counts.set(comment3, (counts.get(comment3) ?? 0) + 1);
|
|
11442
|
+
}
|
|
11443
|
+
const introduced = [];
|
|
11444
|
+
for (const comment3 of added) {
|
|
11445
|
+
const remaining = counts.get(comment3) ?? 0;
|
|
11446
|
+
if (remaining > 0) counts.set(comment3, remaining - 1);
|
|
11447
|
+
else introduced.push(comment3);
|
|
11448
|
+
}
|
|
11449
|
+
return introduced;
|
|
11450
|
+
}
|
|
11451
|
+
function decideCommentGuard(input, existingContent) {
|
|
11452
|
+
if (!isSourceFile(input.tool_input.file_path)) return void 0;
|
|
11453
|
+
const { added, removed } = partitionStrings(input, existingContent);
|
|
11454
|
+
const introduced = introducedComments(
|
|
11455
|
+
added.flatMap(extractComments),
|
|
11456
|
+
removed.flatMap(extractComments)
|
|
11457
|
+
);
|
|
11458
|
+
return introduced.length > 0 ? DENY_REASON : void 0;
|
|
11459
|
+
}
|
|
11460
|
+
|
|
11209
11461
|
// src/commands/editHook/decideOverrideGuard.ts
|
|
11210
|
-
var
|
|
11462
|
+
var DENY_REASON2 = `Edits touching the '${MAINTAINABILITY_OVERRIDE_MARKER}' marker are blocked. This marker is a human-managed maintainability gate exception \u2014 an agent may not add, change, or remove it. If a file genuinely needs a different threshold, raise it with a human.`;
|
|
11211
11463
|
function candidateStrings(input, existingContent) {
|
|
11212
11464
|
const { tool_name, tool_input } = input;
|
|
11213
11465
|
switch (tool_name) {
|
|
@@ -11233,7 +11485,7 @@ function decideOverrideGuard(input, existingContent) {
|
|
|
11233
11485
|
const touchesMarker = candidateStrings(input, existingContent).some(
|
|
11234
11486
|
(s) => s.includes(MAINTAINABILITY_OVERRIDE_MARKER)
|
|
11235
11487
|
);
|
|
11236
|
-
return touchesMarker ?
|
|
11488
|
+
return touchesMarker ? DENY_REASON2 : void 0;
|
|
11237
11489
|
}
|
|
11238
11490
|
|
|
11239
11491
|
// src/commands/editHook/index.ts
|
|
@@ -11259,7 +11511,7 @@ async function editHook() {
|
|
|
11259
11511
|
const input = tryParseInput2(await readStdin());
|
|
11260
11512
|
if (!input) return;
|
|
11261
11513
|
const existing = input.tool_name === "Write" ? readExisting(input.tool_input.file_path) : void 0;
|
|
11262
|
-
const reason = decideOverrideGuard(input, existing);
|
|
11514
|
+
const reason = decideOverrideGuard(input, existing) ?? decideCommentGuard(input, existing);
|
|
11263
11515
|
if (!reason) return;
|
|
11264
11516
|
console.log(
|
|
11265
11517
|
JSON.stringify({
|
|
@@ -11275,7 +11527,7 @@ async function editHook() {
|
|
|
11275
11527
|
// src/commands/registerEditHook.ts
|
|
11276
11528
|
function registerEditHook(program2) {
|
|
11277
11529
|
program2.command("edit-hook").description(
|
|
11278
|
-
"PreToolUse hook that blocks edits to the maintainability override marker"
|
|
11530
|
+
"PreToolUse hook that blocks edits to the maintainability override marker and edits that introduce code comments"
|
|
11279
11531
|
).action(() => {
|
|
11280
11532
|
editHook();
|
|
11281
11533
|
});
|
|
@@ -11294,9 +11546,9 @@ function aggregateCommitters(authorLists) {
|
|
|
11294
11546
|
|
|
11295
11547
|
// src/shared/runGhGraphql.ts
|
|
11296
11548
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
11297
|
-
import { unlinkSync as
|
|
11549
|
+
import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync26 } from "fs";
|
|
11298
11550
|
import { tmpdir as tmpdir4 } from "os";
|
|
11299
|
-
import { join as
|
|
11551
|
+
import { join as join33 } from "path";
|
|
11300
11552
|
function buildArgs2(queryFile, vars) {
|
|
11301
11553
|
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
11302
11554
|
for (const [key, value] of Object.entries(vars)) {
|
|
@@ -11321,8 +11573,8 @@ function throwOnGraphqlErrors(stdout) {
|
|
|
11321
11573
|
throw new Error(messages || "GraphQL request returned errors");
|
|
11322
11574
|
}
|
|
11323
11575
|
function runGhGraphql(mutation, vars) {
|
|
11324
|
-
const queryFile =
|
|
11325
|
-
|
|
11576
|
+
const queryFile = join33(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
11577
|
+
writeFileSync26(queryFile, mutation);
|
|
11326
11578
|
try {
|
|
11327
11579
|
const result = spawnSync3("gh", buildArgs2(queryFile, vars), {
|
|
11328
11580
|
encoding: "utf8"
|
|
@@ -11331,7 +11583,7 @@ function runGhGraphql(mutation, vars) {
|
|
|
11331
11583
|
throwOnGraphqlErrors(result.stdout);
|
|
11332
11584
|
return result.stdout;
|
|
11333
11585
|
} finally {
|
|
11334
|
-
|
|
11586
|
+
unlinkSync10(queryFile);
|
|
11335
11587
|
}
|
|
11336
11588
|
}
|
|
11337
11589
|
|
|
@@ -11385,25 +11637,25 @@ function fetchRepoCommitAuthors(org, repo, since) {
|
|
|
11385
11637
|
}
|
|
11386
11638
|
|
|
11387
11639
|
// src/commands/github/printCountTable.ts
|
|
11388
|
-
import
|
|
11640
|
+
import chalk123 from "chalk";
|
|
11389
11641
|
function printCountTable(labelHeader, rows) {
|
|
11390
11642
|
const labelWidth = Math.max(
|
|
11391
11643
|
labelHeader.length,
|
|
11392
11644
|
...rows.map((row) => row.label.length)
|
|
11393
11645
|
);
|
|
11394
11646
|
const header = `${labelHeader.padEnd(labelWidth)} Commits`;
|
|
11395
|
-
console.log(
|
|
11396
|
-
console.log(
|
|
11647
|
+
console.log(chalk123.dim(header));
|
|
11648
|
+
console.log(chalk123.dim("-".repeat(header.length)));
|
|
11397
11649
|
for (const row of rows) {
|
|
11398
11650
|
console.log(`${row.label.padEnd(labelWidth)} ${row.count}`);
|
|
11399
11651
|
}
|
|
11400
11652
|
}
|
|
11401
11653
|
|
|
11402
11654
|
// src/commands/github/printRepoAuthorBreakdown.ts
|
|
11403
|
-
import
|
|
11655
|
+
import chalk124 from "chalk";
|
|
11404
11656
|
function printRepoAuthorBreakdown(repos2) {
|
|
11405
11657
|
for (const repo of repos2) {
|
|
11406
|
-
console.log(
|
|
11658
|
+
console.log(chalk124.bold(repo.name));
|
|
11407
11659
|
const authorWidth = Math.max(
|
|
11408
11660
|
0,
|
|
11409
11661
|
...repo.authors.map((a) => a.author.length)
|
|
@@ -11508,24 +11760,24 @@ async function countPendingHandovers(orm, origin) {
|
|
|
11508
11760
|
|
|
11509
11761
|
// src/commands/handover/migrateDiskHandovers.ts
|
|
11510
11762
|
import {
|
|
11511
|
-
existsSync as
|
|
11512
|
-
readdirSync as
|
|
11513
|
-
readFileSync as
|
|
11763
|
+
existsSync as existsSync34,
|
|
11764
|
+
readdirSync as readdirSync6,
|
|
11765
|
+
readFileSync as readFileSync29,
|
|
11514
11766
|
rmSync as rmSync2,
|
|
11515
|
-
statSync as
|
|
11767
|
+
statSync as statSync4
|
|
11516
11768
|
} from "fs";
|
|
11517
|
-
import { basename as basename5, join as
|
|
11769
|
+
import { basename as basename5, join as join36 } from "path";
|
|
11518
11770
|
|
|
11519
11771
|
// src/commands/handover/getHandoverPath.ts
|
|
11520
|
-
import { join as
|
|
11772
|
+
import { join as join34 } from "path";
|
|
11521
11773
|
function getHandoverPath(cwd = process.cwd()) {
|
|
11522
|
-
return
|
|
11774
|
+
return join34(cwd, ".assist", "HANDOVER.md");
|
|
11523
11775
|
}
|
|
11524
11776
|
|
|
11525
11777
|
// src/commands/handover/getHandoversDir.ts
|
|
11526
|
-
import { join as
|
|
11778
|
+
import { join as join35 } from "path";
|
|
11527
11779
|
function getHandoversDir(cwd = process.cwd()) {
|
|
11528
|
-
return
|
|
11780
|
+
return join35(cwd, ".assist", "handovers");
|
|
11529
11781
|
}
|
|
11530
11782
|
|
|
11531
11783
|
// src/commands/handover/parseArchiveTimestamp.ts
|
|
@@ -11563,17 +11815,17 @@ function summariseHandoverContent(content) {
|
|
|
11563
11815
|
|
|
11564
11816
|
// src/commands/handover/migrateDiskHandovers.ts
|
|
11565
11817
|
function collectMarkdown(dir) {
|
|
11566
|
-
if (!
|
|
11818
|
+
if (!existsSync34(dir)) return [];
|
|
11567
11819
|
const out = [];
|
|
11568
|
-
for (const entry of
|
|
11569
|
-
const full =
|
|
11820
|
+
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
11821
|
+
const full = join36(dir, entry.name);
|
|
11570
11822
|
if (entry.isDirectory()) out.push(...collectMarkdown(full));
|
|
11571
11823
|
else if (entry.isFile() && entry.name.endsWith(".md")) out.push(full);
|
|
11572
11824
|
}
|
|
11573
11825
|
return out;
|
|
11574
11826
|
}
|
|
11575
11827
|
async function migrateFile(orm, origin, file, createdAt) {
|
|
11576
|
-
const content =
|
|
11828
|
+
const content = readFileSync29(file, "utf8");
|
|
11577
11829
|
await saveHandover(orm, {
|
|
11578
11830
|
origin,
|
|
11579
11831
|
summary: summariseHandoverContent(content),
|
|
@@ -11585,13 +11837,13 @@ async function migrateFile(orm, origin, file, createdAt) {
|
|
|
11585
11837
|
async function migrateDiskHandovers(orm, origin, cwd = process.cwd()) {
|
|
11586
11838
|
let migrated = 0;
|
|
11587
11839
|
for (const file of collectMarkdown(getHandoversDir(cwd))) {
|
|
11588
|
-
const createdAt = parseArchiveTimestamp(basename5(file)) ??
|
|
11840
|
+
const createdAt = parseArchiveTimestamp(basename5(file)) ?? statSync4(file).mtime;
|
|
11589
11841
|
await migrateFile(orm, origin, file, createdAt);
|
|
11590
11842
|
migrated++;
|
|
11591
11843
|
}
|
|
11592
11844
|
const handoverPath = getHandoverPath(cwd);
|
|
11593
|
-
if (
|
|
11594
|
-
await migrateFile(orm, origin, handoverPath,
|
|
11845
|
+
if (existsSync34(handoverPath)) {
|
|
11846
|
+
await migrateFile(orm, origin, handoverPath, statSync4(handoverPath).mtime);
|
|
11595
11847
|
migrated++;
|
|
11596
11848
|
}
|
|
11597
11849
|
return migrated;
|
|
@@ -11721,7 +11973,7 @@ function registerHandover(program2) {
|
|
|
11721
11973
|
}
|
|
11722
11974
|
|
|
11723
11975
|
// src/commands/jira/acceptanceCriteria.ts
|
|
11724
|
-
import
|
|
11976
|
+
import chalk126 from "chalk";
|
|
11725
11977
|
|
|
11726
11978
|
// src/commands/jira/adfToText.ts
|
|
11727
11979
|
function renderInline(node) {
|
|
@@ -11782,7 +12034,7 @@ function adfToText(doc) {
|
|
|
11782
12034
|
|
|
11783
12035
|
// src/commands/jira/fetchIssue.ts
|
|
11784
12036
|
import { execSync as execSync29 } from "child_process";
|
|
11785
|
-
import
|
|
12037
|
+
import chalk125 from "chalk";
|
|
11786
12038
|
function fetchIssue(issueKey, fields) {
|
|
11787
12039
|
let result;
|
|
11788
12040
|
try {
|
|
@@ -11795,15 +12047,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
11795
12047
|
const stderr = error.stderr;
|
|
11796
12048
|
if (stderr.includes("unauthorized")) {
|
|
11797
12049
|
console.error(
|
|
11798
|
-
|
|
12050
|
+
chalk125.red("Jira authentication expired."),
|
|
11799
12051
|
"Run",
|
|
11800
|
-
|
|
12052
|
+
chalk125.cyan("assist jira auth"),
|
|
11801
12053
|
"to re-authenticate."
|
|
11802
12054
|
);
|
|
11803
12055
|
process.exit(1);
|
|
11804
12056
|
}
|
|
11805
12057
|
}
|
|
11806
|
-
console.error(
|
|
12058
|
+
console.error(chalk125.red(`Failed to fetch ${issueKey}.`));
|
|
11807
12059
|
process.exit(1);
|
|
11808
12060
|
}
|
|
11809
12061
|
return JSON.parse(result);
|
|
@@ -11817,7 +12069,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
11817
12069
|
const parsed = fetchIssue(issueKey, field);
|
|
11818
12070
|
const acValue = parsed?.fields?.[field];
|
|
11819
12071
|
if (!acValue) {
|
|
11820
|
-
console.log(
|
|
12072
|
+
console.log(chalk126.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
11821
12073
|
return;
|
|
11822
12074
|
}
|
|
11823
12075
|
if (typeof acValue === "string") {
|
|
@@ -11835,20 +12087,20 @@ function acceptanceCriteria(issueKey) {
|
|
|
11835
12087
|
import { execSync as execSync30 } from "child_process";
|
|
11836
12088
|
|
|
11837
12089
|
// src/shared/loadJson.ts
|
|
11838
|
-
import { existsSync as
|
|
11839
|
-
import { homedir as
|
|
11840
|
-
import { join as
|
|
12090
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync12, readFileSync as readFileSync30, writeFileSync as writeFileSync27 } from "fs";
|
|
12091
|
+
import { homedir as homedir13 } from "os";
|
|
12092
|
+
import { join as join37 } from "path";
|
|
11841
12093
|
function getStoreDir() {
|
|
11842
|
-
return
|
|
12094
|
+
return join37(homedir13(), ".assist");
|
|
11843
12095
|
}
|
|
11844
12096
|
function getStorePath(filename) {
|
|
11845
|
-
return
|
|
12097
|
+
return join37(getStoreDir(), filename);
|
|
11846
12098
|
}
|
|
11847
12099
|
function loadJson(filename) {
|
|
11848
12100
|
const path57 = getStorePath(filename);
|
|
11849
|
-
if (
|
|
12101
|
+
if (existsSync35(path57)) {
|
|
11850
12102
|
try {
|
|
11851
|
-
return JSON.parse(
|
|
12103
|
+
return JSON.parse(readFileSync30(path57, "utf8"));
|
|
11852
12104
|
} catch {
|
|
11853
12105
|
return {};
|
|
11854
12106
|
}
|
|
@@ -11857,10 +12109,10 @@ function loadJson(filename) {
|
|
|
11857
12109
|
}
|
|
11858
12110
|
function saveJson(filename, data) {
|
|
11859
12111
|
const dir = getStoreDir();
|
|
11860
|
-
if (!
|
|
11861
|
-
|
|
12112
|
+
if (!existsSync35(dir)) {
|
|
12113
|
+
mkdirSync12(dir, { recursive: true });
|
|
11862
12114
|
}
|
|
11863
|
-
|
|
12115
|
+
writeFileSync27(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
11864
12116
|
}
|
|
11865
12117
|
|
|
11866
12118
|
// src/shared/promptInput.ts
|
|
@@ -11912,14 +12164,14 @@ async function jiraAuth() {
|
|
|
11912
12164
|
}
|
|
11913
12165
|
|
|
11914
12166
|
// src/commands/jira/viewIssue.ts
|
|
11915
|
-
import
|
|
12167
|
+
import chalk127 from "chalk";
|
|
11916
12168
|
function viewIssue(issueKey) {
|
|
11917
12169
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
11918
12170
|
const fields = parsed?.fields;
|
|
11919
12171
|
const summary = fields?.summary;
|
|
11920
12172
|
const description = fields?.description;
|
|
11921
12173
|
if (summary) {
|
|
11922
|
-
console.log(
|
|
12174
|
+
console.log(chalk127.bold(summary));
|
|
11923
12175
|
}
|
|
11924
12176
|
if (description) {
|
|
11925
12177
|
if (summary) console.log();
|
|
@@ -11933,7 +12185,7 @@ function viewIssue(issueKey) {
|
|
|
11933
12185
|
}
|
|
11934
12186
|
if (!summary && !description) {
|
|
11935
12187
|
console.log(
|
|
11936
|
-
|
|
12188
|
+
chalk127.yellow(`No summary or description found on ${issueKey}.`)
|
|
11937
12189
|
);
|
|
11938
12190
|
}
|
|
11939
12191
|
}
|
|
@@ -11949,13 +12201,13 @@ function registerJira(program2) {
|
|
|
11949
12201
|
// src/commands/reviewComments.ts
|
|
11950
12202
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
11951
12203
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
11952
|
-
import
|
|
12204
|
+
import chalk128 from "chalk";
|
|
11953
12205
|
async function reviewComments(number) {
|
|
11954
12206
|
if (number) {
|
|
11955
12207
|
try {
|
|
11956
12208
|
execFileSync5("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
11957
12209
|
} catch {
|
|
11958
|
-
console.error(
|
|
12210
|
+
console.error(chalk128.red(`gh pr checkout ${number} failed; aborting.`));
|
|
11959
12211
|
process.exit(1);
|
|
11960
12212
|
}
|
|
11961
12213
|
}
|
|
@@ -11999,17 +12251,17 @@ function registerList(program2) {
|
|
|
11999
12251
|
}
|
|
12000
12252
|
|
|
12001
12253
|
// src/commands/mermaid/index.ts
|
|
12002
|
-
import { mkdirSync as
|
|
12254
|
+
import { mkdirSync as mkdirSync13, readdirSync as readdirSync7 } from "fs";
|
|
12003
12255
|
import { resolve as resolve11 } from "path";
|
|
12004
|
-
import
|
|
12256
|
+
import chalk131 from "chalk";
|
|
12005
12257
|
|
|
12006
12258
|
// src/commands/mermaid/exportFile.ts
|
|
12007
|
-
import { readFileSync as
|
|
12259
|
+
import { readFileSync as readFileSync31, writeFileSync as writeFileSync28 } from "fs";
|
|
12008
12260
|
import { basename as basename6, extname, resolve as resolve10 } from "path";
|
|
12009
|
-
import
|
|
12261
|
+
import chalk130 from "chalk";
|
|
12010
12262
|
|
|
12011
12263
|
// src/commands/mermaid/renderBlock.ts
|
|
12012
|
-
import
|
|
12264
|
+
import chalk129 from "chalk";
|
|
12013
12265
|
async function renderBlock(krokiUrl, source) {
|
|
12014
12266
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
12015
12267
|
method: "POST",
|
|
@@ -12018,7 +12270,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
12018
12270
|
});
|
|
12019
12271
|
if (!response.ok) {
|
|
12020
12272
|
console.error(
|
|
12021
|
-
|
|
12273
|
+
chalk129.red(
|
|
12022
12274
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
12023
12275
|
)
|
|
12024
12276
|
);
|
|
@@ -12030,33 +12282,33 @@ async function renderBlock(krokiUrl, source) {
|
|
|
12030
12282
|
|
|
12031
12283
|
// src/commands/mermaid/exportFile.ts
|
|
12032
12284
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
12033
|
-
const content =
|
|
12285
|
+
const content = readFileSync31(file, "utf8");
|
|
12034
12286
|
const blocks = extractMermaidBlocks(content);
|
|
12035
12287
|
const stem = basename6(file, extname(file));
|
|
12036
12288
|
if (onlyIndex !== void 0) {
|
|
12037
12289
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
12038
12290
|
console.error(
|
|
12039
|
-
|
|
12291
|
+
chalk130.red(
|
|
12040
12292
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
12041
12293
|
)
|
|
12042
12294
|
);
|
|
12043
12295
|
process.exit(1);
|
|
12044
12296
|
}
|
|
12045
12297
|
console.log(
|
|
12046
|
-
|
|
12298
|
+
chalk130.gray(
|
|
12047
12299
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
12048
12300
|
)
|
|
12049
12301
|
);
|
|
12050
12302
|
} else {
|
|
12051
|
-
console.log(
|
|
12303
|
+
console.log(chalk130.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
12052
12304
|
}
|
|
12053
12305
|
for (const [i, source] of blocks.entries()) {
|
|
12054
12306
|
const idx = i + 1;
|
|
12055
12307
|
if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
|
|
12056
12308
|
const outPath = resolve10(outDir, `${stem}-${idx}.svg`);
|
|
12057
12309
|
const svg = await renderBlock(krokiUrl, source);
|
|
12058
|
-
|
|
12059
|
-
console.log(
|
|
12310
|
+
writeFileSync28(outPath, svg, "utf8");
|
|
12311
|
+
console.log(chalk130.green(` \u2192 ${outPath}`));
|
|
12060
12312
|
}
|
|
12061
12313
|
}
|
|
12062
12314
|
function extractMermaidBlocks(markdown) {
|
|
@@ -12068,22 +12320,22 @@ function extractMermaidBlocks(markdown) {
|
|
|
12068
12320
|
async function mermaidExport(file, options2 = {}) {
|
|
12069
12321
|
const { mermaid } = loadConfig();
|
|
12070
12322
|
const outDir = resolve11(process.cwd(), options2.out ?? ".");
|
|
12071
|
-
|
|
12323
|
+
mkdirSync13(outDir, { recursive: true });
|
|
12072
12324
|
if (options2.index !== void 0) {
|
|
12073
12325
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
12074
12326
|
console.error(
|
|
12075
|
-
|
|
12327
|
+
chalk131.red(`--index must be a positive integer (got ${options2.index})`)
|
|
12076
12328
|
);
|
|
12077
12329
|
process.exit(1);
|
|
12078
12330
|
}
|
|
12079
12331
|
if (!file) {
|
|
12080
|
-
console.error(
|
|
12332
|
+
console.error(chalk131.red("--index requires a file argument"));
|
|
12081
12333
|
process.exit(1);
|
|
12082
12334
|
}
|
|
12083
12335
|
}
|
|
12084
|
-
const files = file ? [file] :
|
|
12336
|
+
const files = file ? [file] : readdirSync7(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
12085
12337
|
if (files.length === 0) {
|
|
12086
|
-
console.log(
|
|
12338
|
+
console.log(chalk131.gray("No markdown files found in current directory."));
|
|
12087
12339
|
return;
|
|
12088
12340
|
}
|
|
12089
12341
|
for (const f of files) {
|
|
@@ -12109,7 +12361,7 @@ function registerMermaid(program2) {
|
|
|
12109
12361
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
12110
12362
|
import { createServer as createServer2 } from "http";
|
|
12111
12363
|
import { dirname as dirname20 } from "path";
|
|
12112
|
-
import
|
|
12364
|
+
import chalk133 from "chalk";
|
|
12113
12365
|
|
|
12114
12366
|
// src/commands/netcap/corsHeaders.ts
|
|
12115
12367
|
var corsHeaders = {
|
|
@@ -12187,15 +12439,15 @@ function createNetcapHandler(options2) {
|
|
|
12187
12439
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
12188
12440
|
import { cp, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
12189
12441
|
import { networkInterfaces } from "os";
|
|
12190
|
-
import { join as
|
|
12191
|
-
import
|
|
12442
|
+
import { join as join39 } from "path";
|
|
12443
|
+
import chalk132 from "chalk";
|
|
12192
12444
|
|
|
12193
12445
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
12194
|
-
import { dirname as dirname19, join as
|
|
12446
|
+
import { dirname as dirname19, join as join38 } from "path";
|
|
12195
12447
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
12196
12448
|
var moduleDir = dirname19(fileURLToPath5(import.meta.url));
|
|
12197
12449
|
function netcapExtensionDir() {
|
|
12198
|
-
return
|
|
12450
|
+
return join38(moduleDir, "commands", "netcap", "netcap-extension");
|
|
12199
12451
|
}
|
|
12200
12452
|
|
|
12201
12453
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
@@ -12210,7 +12462,7 @@ function lanIPv4() {
|
|
|
12210
12462
|
return void 0;
|
|
12211
12463
|
}
|
|
12212
12464
|
async function configureBackground(dir, host, port, filter) {
|
|
12213
|
-
const file =
|
|
12465
|
+
const file = join39(dir, "background.js");
|
|
12214
12466
|
const source = await readFile2(file, "utf8");
|
|
12215
12467
|
await writeFile2(
|
|
12216
12468
|
file,
|
|
@@ -12232,7 +12484,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
12232
12484
|
const host = lanIPv4();
|
|
12233
12485
|
if (!host) {
|
|
12234
12486
|
console.log(
|
|
12235
|
-
|
|
12487
|
+
chalk132.yellow("could not determine the WSL IP for the extension")
|
|
12236
12488
|
);
|
|
12237
12489
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
12238
12490
|
return source;
|
|
@@ -12243,27 +12495,27 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
12243
12495
|
return WSL_WINDOWS_PATH;
|
|
12244
12496
|
} catch {
|
|
12245
12497
|
console.log(
|
|
12246
|
-
|
|
12498
|
+
chalk132.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
12247
12499
|
);
|
|
12248
12500
|
return source;
|
|
12249
12501
|
}
|
|
12250
12502
|
}
|
|
12251
12503
|
|
|
12252
12504
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
12253
|
-
import { isAbsolute, join as
|
|
12505
|
+
import { isAbsolute, join as join41, resolve as resolve12 } from "path";
|
|
12254
12506
|
|
|
12255
12507
|
// src/commands/netcap/defaultCapturePath.ts
|
|
12256
|
-
import { homedir as
|
|
12257
|
-
import { join as
|
|
12508
|
+
import { homedir as homedir14 } from "os";
|
|
12509
|
+
import { join as join40 } from "path";
|
|
12258
12510
|
function defaultCapturePath() {
|
|
12259
|
-
return
|
|
12511
|
+
return join40(homedir14(), ".assist", "netcap", "capture.jsonl");
|
|
12260
12512
|
}
|
|
12261
12513
|
|
|
12262
12514
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
12263
12515
|
function resolveNetcapOutPath(out) {
|
|
12264
12516
|
if (!out) return defaultCapturePath();
|
|
12265
12517
|
const dir = isAbsolute(out) ? out : resolve12(process.cwd(), out);
|
|
12266
|
-
return
|
|
12518
|
+
return join41(dir, "capture.jsonl");
|
|
12267
12519
|
}
|
|
12268
12520
|
|
|
12269
12521
|
// src/commands/netcap/netcap.ts
|
|
@@ -12276,30 +12528,30 @@ async function netcap(options2) {
|
|
|
12276
12528
|
let count6 = 0;
|
|
12277
12529
|
const handler = createNetcapHandler({
|
|
12278
12530
|
outPath,
|
|
12279
|
-
onPing: () => console.log(
|
|
12531
|
+
onPing: () => console.log(chalk133.dim("ping from extension")),
|
|
12280
12532
|
onCapture: (entry) => {
|
|
12281
12533
|
count6 += 1;
|
|
12282
12534
|
console.log(
|
|
12283
|
-
|
|
12284
|
-
|
|
12535
|
+
chalk133.green(`captured #${count6}`),
|
|
12536
|
+
chalk133.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
12285
12537
|
);
|
|
12286
12538
|
}
|
|
12287
12539
|
});
|
|
12288
12540
|
const server = createServer2(handler);
|
|
12289
12541
|
server.listen(port, () => {
|
|
12290
12542
|
console.log(
|
|
12291
|
-
|
|
12543
|
+
chalk133.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
12292
12544
|
);
|
|
12293
|
-
console.log(
|
|
12545
|
+
console.log(chalk133.dim(`appending captures to ${outPath}`));
|
|
12294
12546
|
if (filter)
|
|
12295
|
-
console.log(
|
|
12296
|
-
console.log(
|
|
12297
|
-
console.log(
|
|
12547
|
+
console.log(chalk133.dim(`forwarding only URLs matching "${filter}"`));
|
|
12548
|
+
console.log(chalk133.dim(`load the unpacked extension from ${extensionPath}`));
|
|
12549
|
+
console.log(chalk133.dim("press Ctrl-C to stop"));
|
|
12298
12550
|
});
|
|
12299
12551
|
process.on("SIGINT", () => {
|
|
12300
12552
|
server.close();
|
|
12301
12553
|
console.log(
|
|
12302
|
-
|
|
12554
|
+
chalk133.bold(
|
|
12303
12555
|
`
|
|
12304
12556
|
netcap stopped \u2014 captured ${count6} ${count6 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
12305
12557
|
)
|
|
@@ -12309,12 +12561,12 @@ netcap stopped \u2014 captured ${count6} ${count6 === 1 ? "entry" : "entries"} t
|
|
|
12309
12561
|
}
|
|
12310
12562
|
|
|
12311
12563
|
// src/commands/netcap/netcapExtract.ts
|
|
12312
|
-
import { writeFileSync as
|
|
12313
|
-
import { join as
|
|
12314
|
-
import
|
|
12564
|
+
import { writeFileSync as writeFileSync29 } from "fs";
|
|
12565
|
+
import { join as join42 } from "path";
|
|
12566
|
+
import chalk134 from "chalk";
|
|
12315
12567
|
|
|
12316
12568
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
12317
|
-
import { readFileSync as
|
|
12569
|
+
import { readFileSync as readFileSync32 } from "fs";
|
|
12318
12570
|
|
|
12319
12571
|
// src/commands/netcap/parseRscRows.ts
|
|
12320
12572
|
var isRscRef = (v) => typeof v === "string" && /^\$[0-9a-fL@]/.test(v);
|
|
@@ -12710,7 +12962,7 @@ function extractVoyagerPosts(body) {
|
|
|
12710
12962
|
|
|
12711
12963
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
12712
12964
|
function captureEntries(captureFile) {
|
|
12713
|
-
const lines =
|
|
12965
|
+
const lines = readFileSync32(captureFile, "utf8").split("\n").filter(Boolean);
|
|
12714
12966
|
const entries = [];
|
|
12715
12967
|
for (const line of lines) {
|
|
12716
12968
|
let entry;
|
|
@@ -12755,12 +13007,12 @@ function extractPostsFromCapture(captureFile) {
|
|
|
12755
13007
|
function netcapExtract(file) {
|
|
12756
13008
|
const captureFile = file ?? defaultCapturePath();
|
|
12757
13009
|
const posts = extractPostsFromCapture(captureFile);
|
|
12758
|
-
const outFile =
|
|
12759
|
-
|
|
13010
|
+
const outFile = join42(captureFile, "..", "posts.json");
|
|
13011
|
+
writeFileSync29(outFile, `${JSON.stringify(posts, null, 2)}
|
|
12760
13012
|
`);
|
|
12761
13013
|
console.log(
|
|
12762
|
-
|
|
12763
|
-
|
|
13014
|
+
chalk134.green(`extracted ${posts.length} posts`),
|
|
13015
|
+
chalk134.dim(`-> ${outFile}`)
|
|
12764
13016
|
);
|
|
12765
13017
|
}
|
|
12766
13018
|
|
|
@@ -12781,7 +13033,7 @@ function registerNetcap(program2) {
|
|
|
12781
13033
|
}
|
|
12782
13034
|
|
|
12783
13035
|
// src/commands/news/add/index.ts
|
|
12784
|
-
import
|
|
13036
|
+
import chalk135 from "chalk";
|
|
12785
13037
|
import enquirer8 from "enquirer";
|
|
12786
13038
|
async function add2(url) {
|
|
12787
13039
|
if (!url) {
|
|
@@ -12803,10 +13055,10 @@ async function add2(url) {
|
|
|
12803
13055
|
const { orm } = await getReady();
|
|
12804
13056
|
const added = await addFeed(orm, url);
|
|
12805
13057
|
if (!added) {
|
|
12806
|
-
console.log(
|
|
13058
|
+
console.log(chalk135.yellow("Feed already exists"));
|
|
12807
13059
|
return;
|
|
12808
13060
|
}
|
|
12809
|
-
console.log(
|
|
13061
|
+
console.log(chalk135.green(`Added feed: ${url}`));
|
|
12810
13062
|
}
|
|
12811
13063
|
|
|
12812
13064
|
// src/commands/registerNews.ts
|
|
@@ -12816,7 +13068,7 @@ function registerNews(program2) {
|
|
|
12816
13068
|
}
|
|
12817
13069
|
|
|
12818
13070
|
// src/commands/prompts/printPromptsTable.ts
|
|
12819
|
-
import
|
|
13071
|
+
import chalk136 from "chalk";
|
|
12820
13072
|
function truncate(str, max) {
|
|
12821
13073
|
if (str.length <= max) return str;
|
|
12822
13074
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -12834,14 +13086,14 @@ function printPromptsTable(rows) {
|
|
|
12834
13086
|
"Command".padEnd(commandWidth),
|
|
12835
13087
|
"Repos"
|
|
12836
13088
|
].join(" ");
|
|
12837
|
-
console.log(
|
|
12838
|
-
console.log(
|
|
13089
|
+
console.log(chalk136.dim(header));
|
|
13090
|
+
console.log(chalk136.dim("-".repeat(header.length)));
|
|
12839
13091
|
for (const row of rows) {
|
|
12840
13092
|
const count6 = String(row.count).padStart(countWidth);
|
|
12841
13093
|
const tool = row.tool.padEnd(toolWidth);
|
|
12842
13094
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
12843
13095
|
console.log(
|
|
12844
|
-
`${
|
|
13096
|
+
`${chalk136.yellow(count6)} ${tool} ${command} ${chalk136.dim(row.repos)}`
|
|
12845
13097
|
);
|
|
12846
13098
|
}
|
|
12847
13099
|
}
|
|
@@ -13189,29 +13441,29 @@ import { execSync as execSync35 } from "child_process";
|
|
|
13189
13441
|
|
|
13190
13442
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
13191
13443
|
import { execSync as execSync34 } from "child_process";
|
|
13192
|
-
import { unlinkSync as
|
|
13444
|
+
import { unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
|
|
13193
13445
|
import { tmpdir as tmpdir5 } from "os";
|
|
13194
|
-
import { join as
|
|
13446
|
+
import { join as join44 } from "path";
|
|
13195
13447
|
|
|
13196
13448
|
// src/commands/prs/loadCommentsCache.ts
|
|
13197
|
-
import { existsSync as
|
|
13198
|
-
import { join as
|
|
13449
|
+
import { existsSync as existsSync36, readFileSync as readFileSync33, unlinkSync as unlinkSync11 } from "fs";
|
|
13450
|
+
import { join as join43 } from "path";
|
|
13199
13451
|
import { parse as parse2 } from "yaml";
|
|
13200
13452
|
function getCachePath(prNumber) {
|
|
13201
|
-
return
|
|
13453
|
+
return join43(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
13202
13454
|
}
|
|
13203
13455
|
function loadCommentsCache(prNumber) {
|
|
13204
13456
|
const cachePath = getCachePath(prNumber);
|
|
13205
|
-
if (!
|
|
13457
|
+
if (!existsSync36(cachePath)) {
|
|
13206
13458
|
return null;
|
|
13207
13459
|
}
|
|
13208
|
-
const content =
|
|
13460
|
+
const content = readFileSync33(cachePath, "utf8");
|
|
13209
13461
|
return parse2(content);
|
|
13210
13462
|
}
|
|
13211
13463
|
function deleteCommentsCache(prNumber) {
|
|
13212
13464
|
const cachePath = getCachePath(prNumber);
|
|
13213
|
-
if (
|
|
13214
|
-
|
|
13465
|
+
if (existsSync36(cachePath)) {
|
|
13466
|
+
unlinkSync11(cachePath);
|
|
13215
13467
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
13216
13468
|
}
|
|
13217
13469
|
}
|
|
@@ -13228,15 +13480,15 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
13228
13480
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
13229
13481
|
function resolveThread(threadId) {
|
|
13230
13482
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
13231
|
-
const queryFile =
|
|
13232
|
-
|
|
13483
|
+
const queryFile = join44(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
|
|
13484
|
+
writeFileSync30(queryFile, mutation);
|
|
13233
13485
|
try {
|
|
13234
13486
|
execSync34(
|
|
13235
13487
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
13236
13488
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
13237
13489
|
);
|
|
13238
13490
|
} finally {
|
|
13239
|
-
|
|
13491
|
+
unlinkSync12(queryFile);
|
|
13240
13492
|
}
|
|
13241
13493
|
}
|
|
13242
13494
|
function requireCache(prNumber) {
|
|
@@ -13310,19 +13562,19 @@ function fixed(commentId, sha) {
|
|
|
13310
13562
|
}
|
|
13311
13563
|
|
|
13312
13564
|
// src/commands/prs/listComments/index.ts
|
|
13313
|
-
import { existsSync as
|
|
13314
|
-
import { join as
|
|
13565
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync14, writeFileSync as writeFileSync32 } from "fs";
|
|
13566
|
+
import { join as join46 } from "path";
|
|
13315
13567
|
import { stringify } from "yaml";
|
|
13316
13568
|
|
|
13317
13569
|
// src/commands/prs/fetchThreadIds.ts
|
|
13318
13570
|
import { execSync as execSync36 } from "child_process";
|
|
13319
|
-
import { unlinkSync as
|
|
13571
|
+
import { unlinkSync as unlinkSync13, writeFileSync as writeFileSync31 } from "fs";
|
|
13320
13572
|
import { tmpdir as tmpdir6 } from "os";
|
|
13321
|
-
import { join as
|
|
13573
|
+
import { join as join45 } from "path";
|
|
13322
13574
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
13323
13575
|
function fetchThreadIds(org, repo, prNumber) {
|
|
13324
|
-
const queryFile =
|
|
13325
|
-
|
|
13576
|
+
const queryFile = join45(tmpdir6(), `gh-query-${Date.now()}.graphql`);
|
|
13577
|
+
writeFileSync31(queryFile, THREAD_QUERY);
|
|
13326
13578
|
try {
|
|
13327
13579
|
const result = execSync36(
|
|
13328
13580
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -13341,7 +13593,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
13341
13593
|
}
|
|
13342
13594
|
return { threadMap, resolvedThreadIds };
|
|
13343
13595
|
} finally {
|
|
13344
|
-
|
|
13596
|
+
unlinkSync13(queryFile);
|
|
13345
13597
|
}
|
|
13346
13598
|
}
|
|
13347
13599
|
|
|
@@ -13390,20 +13642,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
13390
13642
|
}
|
|
13391
13643
|
|
|
13392
13644
|
// src/commands/prs/listComments/printComments.ts
|
|
13393
|
-
import
|
|
13645
|
+
import chalk137 from "chalk";
|
|
13394
13646
|
function formatForHuman(comment3) {
|
|
13395
13647
|
if (comment3.type === "review") {
|
|
13396
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
13648
|
+
const stateColor = comment3.state === "APPROVED" ? chalk137.green : comment3.state === "CHANGES_REQUESTED" ? chalk137.red : chalk137.yellow;
|
|
13397
13649
|
return [
|
|
13398
|
-
`${
|
|
13650
|
+
`${chalk137.cyan("Review")} by ${chalk137.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
13399
13651
|
comment3.body,
|
|
13400
13652
|
""
|
|
13401
13653
|
].join("\n");
|
|
13402
13654
|
}
|
|
13403
13655
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
13404
13656
|
return [
|
|
13405
|
-
`${
|
|
13406
|
-
|
|
13657
|
+
`${chalk137.cyan("Line comment")} by ${chalk137.bold(comment3.user)} on ${chalk137.dim(`${comment3.path}${location}`)}`,
|
|
13658
|
+
chalk137.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
13407
13659
|
comment3.body,
|
|
13408
13660
|
""
|
|
13409
13661
|
].join("\n");
|
|
@@ -13435,17 +13687,17 @@ function printComments2(result) {
|
|
|
13435
13687
|
|
|
13436
13688
|
// src/commands/prs/listComments/index.ts
|
|
13437
13689
|
function writeCommentsCache(prNumber, comments3) {
|
|
13438
|
-
const assistDir =
|
|
13439
|
-
if (!
|
|
13440
|
-
|
|
13690
|
+
const assistDir = join46(process.cwd(), ".assist");
|
|
13691
|
+
if (!existsSync37(assistDir)) {
|
|
13692
|
+
mkdirSync14(assistDir, { recursive: true });
|
|
13441
13693
|
}
|
|
13442
13694
|
const cacheData = {
|
|
13443
13695
|
prNumber,
|
|
13444
13696
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13445
13697
|
comments: comments3
|
|
13446
13698
|
};
|
|
13447
|
-
const cachePath =
|
|
13448
|
-
|
|
13699
|
+
const cachePath = join46(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
13700
|
+
writeFileSync32(cachePath, stringify(cacheData));
|
|
13449
13701
|
}
|
|
13450
13702
|
function handleKnownErrors(error) {
|
|
13451
13703
|
if (isGhNotInstalled(error)) {
|
|
@@ -13477,7 +13729,7 @@ async function listComments() {
|
|
|
13477
13729
|
];
|
|
13478
13730
|
updateCache(prNumber, allComments);
|
|
13479
13731
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
13480
|
-
const cachePath = hasLineComments ?
|
|
13732
|
+
const cachePath = hasLineComments ? join46(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
13481
13733
|
return { comments: allComments, cachePath };
|
|
13482
13734
|
} catch (error) {
|
|
13483
13735
|
const handled = handleKnownErrors(error);
|
|
@@ -13493,13 +13745,13 @@ import { execSync as execSync38 } from "child_process";
|
|
|
13493
13745
|
import enquirer9 from "enquirer";
|
|
13494
13746
|
|
|
13495
13747
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
13496
|
-
import
|
|
13748
|
+
import chalk138 from "chalk";
|
|
13497
13749
|
var STATUS_MAP = {
|
|
13498
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
13499
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
13750
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk138.magenta("merged"), date: pr.mergedAt } : null,
|
|
13751
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk138.red("closed"), date: pr.closedAt } : null
|
|
13500
13752
|
};
|
|
13501
13753
|
function defaultStatus(pr) {
|
|
13502
|
-
return { label:
|
|
13754
|
+
return { label: chalk138.green("opened"), date: pr.createdAt };
|
|
13503
13755
|
}
|
|
13504
13756
|
function getStatus2(pr) {
|
|
13505
13757
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -13508,11 +13760,11 @@ function formatDate(dateStr) {
|
|
|
13508
13760
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
13509
13761
|
}
|
|
13510
13762
|
function formatPrHeader(pr, status2) {
|
|
13511
|
-
return `${
|
|
13763
|
+
return `${chalk138.cyan(`#${pr.number}`)} ${pr.title} ${chalk138.dim(`(${pr.author.login},`)} ${status2.label} ${chalk138.dim(`${formatDate(status2.date)})`)}`;
|
|
13512
13764
|
}
|
|
13513
13765
|
function logPrDetails(pr) {
|
|
13514
13766
|
console.log(
|
|
13515
|
-
|
|
13767
|
+
chalk138.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
13516
13768
|
);
|
|
13517
13769
|
console.log();
|
|
13518
13770
|
}
|
|
@@ -13819,10 +14071,10 @@ function registerPrs(program2) {
|
|
|
13819
14071
|
}
|
|
13820
14072
|
|
|
13821
14073
|
// src/commands/ravendb/ravendbAuth.ts
|
|
13822
|
-
import
|
|
14074
|
+
import chalk144 from "chalk";
|
|
13823
14075
|
|
|
13824
14076
|
// src/shared/createConnectionAuth.ts
|
|
13825
|
-
import
|
|
14077
|
+
import chalk139 from "chalk";
|
|
13826
14078
|
function listConnections(connections, format2) {
|
|
13827
14079
|
if (connections.length === 0) {
|
|
13828
14080
|
console.log("No connections configured.");
|
|
@@ -13835,7 +14087,7 @@ function listConnections(connections, format2) {
|
|
|
13835
14087
|
function removeConnection(connections, name, save) {
|
|
13836
14088
|
const filtered = connections.filter((c) => c.name !== name);
|
|
13837
14089
|
if (filtered.length === connections.length) {
|
|
13838
|
-
console.error(
|
|
14090
|
+
console.error(chalk139.red(`Connection "${name}" not found.`));
|
|
13839
14091
|
process.exit(1);
|
|
13840
14092
|
}
|
|
13841
14093
|
save(filtered);
|
|
@@ -13881,15 +14133,15 @@ function saveConnections(connections) {
|
|
|
13881
14133
|
}
|
|
13882
14134
|
|
|
13883
14135
|
// src/commands/ravendb/promptConnection.ts
|
|
13884
|
-
import
|
|
14136
|
+
import chalk142 from "chalk";
|
|
13885
14137
|
|
|
13886
14138
|
// src/commands/ravendb/selectOpSecret.ts
|
|
13887
|
-
import
|
|
14139
|
+
import chalk141 from "chalk";
|
|
13888
14140
|
import Enquirer2 from "enquirer";
|
|
13889
14141
|
|
|
13890
14142
|
// src/commands/ravendb/searchItems.ts
|
|
13891
14143
|
import { execSync as execSync41 } from "child_process";
|
|
13892
|
-
import
|
|
14144
|
+
import chalk140 from "chalk";
|
|
13893
14145
|
function opExec(args) {
|
|
13894
14146
|
return execSync41(`op ${args}`, {
|
|
13895
14147
|
encoding: "utf8",
|
|
@@ -13902,7 +14154,7 @@ function searchItems(search2) {
|
|
|
13902
14154
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
13903
14155
|
} catch {
|
|
13904
14156
|
console.error(
|
|
13905
|
-
|
|
14157
|
+
chalk140.red(
|
|
13906
14158
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
13907
14159
|
)
|
|
13908
14160
|
);
|
|
@@ -13916,7 +14168,7 @@ function getItemFields(itemId) {
|
|
|
13916
14168
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
13917
14169
|
return item.fields.filter((f) => f.reference && f.label);
|
|
13918
14170
|
} catch {
|
|
13919
|
-
console.error(
|
|
14171
|
+
console.error(chalk140.red("Failed to get item details from 1Password."));
|
|
13920
14172
|
process.exit(1);
|
|
13921
14173
|
}
|
|
13922
14174
|
}
|
|
@@ -13935,7 +14187,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
13935
14187
|
}).run();
|
|
13936
14188
|
const items2 = searchItems(search2);
|
|
13937
14189
|
if (items2.length === 0) {
|
|
13938
|
-
console.error(
|
|
14190
|
+
console.error(chalk141.red(`No items found matching "${search2}".`));
|
|
13939
14191
|
process.exit(1);
|
|
13940
14192
|
}
|
|
13941
14193
|
const itemId = await selectOne(
|
|
@@ -13944,7 +14196,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
13944
14196
|
);
|
|
13945
14197
|
const fields = getItemFields(itemId);
|
|
13946
14198
|
if (fields.length === 0) {
|
|
13947
|
-
console.error(
|
|
14199
|
+
console.error(chalk141.red("No fields with references found on this item."));
|
|
13948
14200
|
process.exit(1);
|
|
13949
14201
|
}
|
|
13950
14202
|
const ref = await selectOne(
|
|
@@ -13958,7 +14210,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
13958
14210
|
async function promptConnection(existingNames) {
|
|
13959
14211
|
const name = await promptInput("name", "Connection name:");
|
|
13960
14212
|
if (existingNames.includes(name)) {
|
|
13961
|
-
console.error(
|
|
14213
|
+
console.error(chalk142.red(`Connection "${name}" already exists.`));
|
|
13962
14214
|
process.exit(1);
|
|
13963
14215
|
}
|
|
13964
14216
|
const url = await promptInput(
|
|
@@ -13967,22 +14219,22 @@ async function promptConnection(existingNames) {
|
|
|
13967
14219
|
);
|
|
13968
14220
|
const database = await promptInput("database", "Database name:");
|
|
13969
14221
|
if (!name || !url || !database) {
|
|
13970
|
-
console.error(
|
|
14222
|
+
console.error(chalk142.red("All fields are required."));
|
|
13971
14223
|
process.exit(1);
|
|
13972
14224
|
}
|
|
13973
14225
|
const apiKeyRef = await selectOpSecret();
|
|
13974
|
-
console.log(
|
|
14226
|
+
console.log(chalk142.dim(`Using: ${apiKeyRef}`));
|
|
13975
14227
|
return { name, url, database, apiKeyRef };
|
|
13976
14228
|
}
|
|
13977
14229
|
|
|
13978
14230
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
13979
|
-
import
|
|
14231
|
+
import chalk143 from "chalk";
|
|
13980
14232
|
function ravendbSetConnection(name) {
|
|
13981
14233
|
const raw = loadGlobalConfigRaw();
|
|
13982
14234
|
const ravendb = raw.ravendb ?? {};
|
|
13983
14235
|
const connections = ravendb.connections ?? [];
|
|
13984
14236
|
if (!connections.some((c) => c.name === name)) {
|
|
13985
|
-
console.error(
|
|
14237
|
+
console.error(chalk143.red(`Connection "${name}" not found.`));
|
|
13986
14238
|
console.error(
|
|
13987
14239
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
13988
14240
|
);
|
|
@@ -13998,16 +14250,16 @@ function ravendbSetConnection(name) {
|
|
|
13998
14250
|
var ravendbAuth = createConnectionAuth({
|
|
13999
14251
|
load: loadConnections,
|
|
14000
14252
|
save: saveConnections,
|
|
14001
|
-
format: (c) => `${
|
|
14253
|
+
format: (c) => `${chalk144.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
14002
14254
|
promptNew: promptConnection,
|
|
14003
14255
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
14004
14256
|
});
|
|
14005
14257
|
|
|
14006
14258
|
// src/commands/ravendb/ravendbCollections.ts
|
|
14007
|
-
import
|
|
14259
|
+
import chalk148 from "chalk";
|
|
14008
14260
|
|
|
14009
14261
|
// src/commands/ravendb/ravenFetch.ts
|
|
14010
|
-
import
|
|
14262
|
+
import chalk146 from "chalk";
|
|
14011
14263
|
|
|
14012
14264
|
// src/commands/ravendb/getAccessToken.ts
|
|
14013
14265
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -14044,10 +14296,10 @@ ${errorText}`
|
|
|
14044
14296
|
|
|
14045
14297
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
14046
14298
|
import { execSync as execSync42 } from "child_process";
|
|
14047
|
-
import
|
|
14299
|
+
import chalk145 from "chalk";
|
|
14048
14300
|
function resolveOpSecret(reference) {
|
|
14049
14301
|
if (!reference.startsWith("op://")) {
|
|
14050
|
-
console.error(
|
|
14302
|
+
console.error(chalk145.red(`Invalid secret reference: must start with op://`));
|
|
14051
14303
|
process.exit(1);
|
|
14052
14304
|
}
|
|
14053
14305
|
try {
|
|
@@ -14057,7 +14309,7 @@ function resolveOpSecret(reference) {
|
|
|
14057
14309
|
}).trim();
|
|
14058
14310
|
} catch {
|
|
14059
14311
|
console.error(
|
|
14060
|
-
|
|
14312
|
+
chalk145.red(
|
|
14061
14313
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
14062
14314
|
)
|
|
14063
14315
|
);
|
|
@@ -14084,7 +14336,7 @@ async function ravenFetch(connection, path57) {
|
|
|
14084
14336
|
if (!response.ok) {
|
|
14085
14337
|
const body = await response.text();
|
|
14086
14338
|
console.error(
|
|
14087
|
-
|
|
14339
|
+
chalk146.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
14088
14340
|
);
|
|
14089
14341
|
console.error(body.substring(0, 500));
|
|
14090
14342
|
process.exit(1);
|
|
@@ -14093,7 +14345,7 @@ async function ravenFetch(connection, path57) {
|
|
|
14093
14345
|
}
|
|
14094
14346
|
|
|
14095
14347
|
// src/commands/ravendb/resolveConnection.ts
|
|
14096
|
-
import
|
|
14348
|
+
import chalk147 from "chalk";
|
|
14097
14349
|
function loadRavendb() {
|
|
14098
14350
|
const raw = loadGlobalConfigRaw();
|
|
14099
14351
|
const ravendb = raw.ravendb;
|
|
@@ -14107,7 +14359,7 @@ function resolveConnection(name) {
|
|
|
14107
14359
|
const connectionName = name ?? defaultConnection;
|
|
14108
14360
|
if (!connectionName) {
|
|
14109
14361
|
console.error(
|
|
14110
|
-
|
|
14362
|
+
chalk147.red(
|
|
14111
14363
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
14112
14364
|
)
|
|
14113
14365
|
);
|
|
@@ -14115,7 +14367,7 @@ function resolveConnection(name) {
|
|
|
14115
14367
|
}
|
|
14116
14368
|
const connection = connections.find((c) => c.name === connectionName);
|
|
14117
14369
|
if (!connection) {
|
|
14118
|
-
console.error(
|
|
14370
|
+
console.error(chalk147.red(`Connection "${connectionName}" not found.`));
|
|
14119
14371
|
console.error(
|
|
14120
14372
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
14121
14373
|
);
|
|
@@ -14146,15 +14398,15 @@ async function ravendbCollections(connectionName) {
|
|
|
14146
14398
|
return;
|
|
14147
14399
|
}
|
|
14148
14400
|
for (const c of collections) {
|
|
14149
|
-
console.log(`${
|
|
14401
|
+
console.log(`${chalk148.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
14150
14402
|
}
|
|
14151
14403
|
}
|
|
14152
14404
|
|
|
14153
14405
|
// src/commands/ravendb/ravendbQuery.ts
|
|
14154
|
-
import
|
|
14406
|
+
import chalk150 from "chalk";
|
|
14155
14407
|
|
|
14156
14408
|
// src/commands/ravendb/fetchAllPages.ts
|
|
14157
|
-
import
|
|
14409
|
+
import chalk149 from "chalk";
|
|
14158
14410
|
|
|
14159
14411
|
// src/commands/ravendb/buildQueryPath.ts
|
|
14160
14412
|
function buildQueryPath(opts) {
|
|
@@ -14192,7 +14444,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
14192
14444
|
allResults.push(...results);
|
|
14193
14445
|
start3 += results.length;
|
|
14194
14446
|
process.stderr.write(
|
|
14195
|
-
`\r${
|
|
14447
|
+
`\r${chalk149.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
14196
14448
|
);
|
|
14197
14449
|
if (start3 >= totalResults) break;
|
|
14198
14450
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -14207,7 +14459,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
14207
14459
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
14208
14460
|
const resolved = resolveArgs(connectionName, collection);
|
|
14209
14461
|
if (!resolved.collection && !options2.query) {
|
|
14210
|
-
console.error(
|
|
14462
|
+
console.error(chalk150.red("Provide a collection name or --query filter."));
|
|
14211
14463
|
process.exit(1);
|
|
14212
14464
|
}
|
|
14213
14465
|
const { collection: col } = resolved;
|
|
@@ -14245,7 +14497,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
14245
14497
|
import * as path28 from "path";
|
|
14246
14498
|
|
|
14247
14499
|
// src/commands/refactor/logViolations.ts
|
|
14248
|
-
import
|
|
14500
|
+
import chalk151 from "chalk";
|
|
14249
14501
|
var DEFAULT_MAX_LINES = 100;
|
|
14250
14502
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
14251
14503
|
if (violations.length === 0) {
|
|
@@ -14254,43 +14506,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
14254
14506
|
}
|
|
14255
14507
|
return;
|
|
14256
14508
|
}
|
|
14257
|
-
console.error(
|
|
14509
|
+
console.error(chalk151.red(`
|
|
14258
14510
|
Refactor check failed:
|
|
14259
14511
|
`));
|
|
14260
|
-
console.error(
|
|
14512
|
+
console.error(chalk151.red(` The following files exceed ${maxLines} lines:
|
|
14261
14513
|
`));
|
|
14262
14514
|
for (const violation of violations) {
|
|
14263
|
-
console.error(
|
|
14515
|
+
console.error(chalk151.red(` ${violation.file} (${violation.lines} lines)`));
|
|
14264
14516
|
}
|
|
14265
14517
|
console.error(
|
|
14266
|
-
|
|
14518
|
+
chalk151.yellow(
|
|
14267
14519
|
`
|
|
14268
14520
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
14269
14521
|
way to refactor it, ignore it with:
|
|
14270
14522
|
`
|
|
14271
14523
|
)
|
|
14272
14524
|
);
|
|
14273
|
-
console.error(
|
|
14525
|
+
console.error(chalk151.gray(` assist refactor ignore <file>
|
|
14274
14526
|
`));
|
|
14275
14527
|
if (process.env.CLAUDECODE) {
|
|
14276
|
-
console.error(
|
|
14528
|
+
console.error(chalk151.cyan(`
|
|
14277
14529
|
## Extracting Code to New Files
|
|
14278
14530
|
`));
|
|
14279
14531
|
console.error(
|
|
14280
|
-
|
|
14532
|
+
chalk151.cyan(
|
|
14281
14533
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
14282
14534
|
`
|
|
14283
14535
|
)
|
|
14284
14536
|
);
|
|
14285
14537
|
console.error(
|
|
14286
|
-
|
|
14538
|
+
chalk151.cyan(
|
|
14287
14539
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
14288
14540
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
14289
14541
|
`
|
|
14290
14542
|
)
|
|
14291
14543
|
);
|
|
14292
14544
|
console.error(
|
|
14293
|
-
|
|
14545
|
+
chalk151.cyan(
|
|
14294
14546
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
14295
14547
|
domains, move it to a common/shared folder.
|
|
14296
14548
|
`
|
|
@@ -14446,7 +14698,7 @@ async function check(pattern2, options2) {
|
|
|
14446
14698
|
|
|
14447
14699
|
// src/commands/refactor/extract/index.ts
|
|
14448
14700
|
import path35 from "path";
|
|
14449
|
-
import
|
|
14701
|
+
import chalk154 from "chalk";
|
|
14450
14702
|
|
|
14451
14703
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
14452
14704
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -15021,23 +15273,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
15021
15273
|
|
|
15022
15274
|
// src/commands/refactor/extract/displayPlan.ts
|
|
15023
15275
|
import path32 from "path";
|
|
15024
|
-
import
|
|
15276
|
+
import chalk152 from "chalk";
|
|
15025
15277
|
function section(title) {
|
|
15026
15278
|
return `
|
|
15027
|
-
${
|
|
15279
|
+
${chalk152.cyan(title)}`;
|
|
15028
15280
|
}
|
|
15029
15281
|
function displayImporters(plan2, cwd) {
|
|
15030
15282
|
if (plan2.importersToUpdate.length === 0) return;
|
|
15031
15283
|
console.log(section("Update importers:"));
|
|
15032
15284
|
for (const imp of plan2.importersToUpdate) {
|
|
15033
15285
|
const rel = path32.relative(cwd, imp.file.getFilePath());
|
|
15034
|
-
console.log(` ${
|
|
15286
|
+
console.log(` ${chalk152.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
15035
15287
|
}
|
|
15036
15288
|
}
|
|
15037
15289
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
15038
|
-
console.log(
|
|
15290
|
+
console.log(chalk152.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
15039
15291
|
`));
|
|
15040
|
-
console.log(` ${
|
|
15292
|
+
console.log(` ${chalk152.cyan("Functions to move:")}`);
|
|
15041
15293
|
for (const name of plan2.extractedNames) {
|
|
15042
15294
|
console.log(` ${name}`);
|
|
15043
15295
|
}
|
|
@@ -15071,7 +15323,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
15071
15323
|
|
|
15072
15324
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
15073
15325
|
import path34 from "path";
|
|
15074
|
-
import
|
|
15326
|
+
import chalk153 from "chalk";
|
|
15075
15327
|
import { Project as Project4 } from "ts-morph";
|
|
15076
15328
|
|
|
15077
15329
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -15131,7 +15383,7 @@ function loadProjectFile(file) {
|
|
|
15131
15383
|
});
|
|
15132
15384
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
15133
15385
|
if (!sourceFile) {
|
|
15134
|
-
console.log(
|
|
15386
|
+
console.log(chalk153.red(`File not found in project: ${file}`));
|
|
15135
15387
|
process.exit(1);
|
|
15136
15388
|
}
|
|
15137
15389
|
return { project, sourceFile };
|
|
@@ -15154,19 +15406,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
15154
15406
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
15155
15407
|
if (options2.apply) {
|
|
15156
15408
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
15157
|
-
console.log(
|
|
15409
|
+
console.log(chalk154.green("\nExtraction complete"));
|
|
15158
15410
|
} else {
|
|
15159
|
-
console.log(
|
|
15411
|
+
console.log(chalk154.dim("\nDry run. Use --apply to execute."));
|
|
15160
15412
|
}
|
|
15161
15413
|
}
|
|
15162
15414
|
|
|
15163
15415
|
// src/commands/refactor/ignore.ts
|
|
15164
15416
|
import fs23 from "fs";
|
|
15165
|
-
import
|
|
15417
|
+
import chalk155 from "chalk";
|
|
15166
15418
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
15167
15419
|
function ignore(file) {
|
|
15168
15420
|
if (!fs23.existsSync(file)) {
|
|
15169
|
-
console.error(
|
|
15421
|
+
console.error(chalk155.red(`Error: File does not exist: ${file}`));
|
|
15170
15422
|
process.exit(1);
|
|
15171
15423
|
}
|
|
15172
15424
|
const content = fs23.readFileSync(file, "utf8");
|
|
@@ -15182,7 +15434,7 @@ function ignore(file) {
|
|
|
15182
15434
|
fs23.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
15183
15435
|
}
|
|
15184
15436
|
console.log(
|
|
15185
|
-
|
|
15437
|
+
chalk155.green(
|
|
15186
15438
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
15187
15439
|
)
|
|
15188
15440
|
);
|
|
@@ -15191,12 +15443,12 @@ function ignore(file) {
|
|
|
15191
15443
|
// src/commands/refactor/rename/index.ts
|
|
15192
15444
|
import fs26 from "fs";
|
|
15193
15445
|
import path40 from "path";
|
|
15194
|
-
import
|
|
15446
|
+
import chalk158 from "chalk";
|
|
15195
15447
|
|
|
15196
15448
|
// src/commands/refactor/rename/applyRename.ts
|
|
15197
15449
|
import fs25 from "fs";
|
|
15198
15450
|
import path37 from "path";
|
|
15199
|
-
import
|
|
15451
|
+
import chalk156 from "chalk";
|
|
15200
15452
|
|
|
15201
15453
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
15202
15454
|
import path36 from "path";
|
|
@@ -15301,13 +15553,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
15301
15553
|
const updatedContents = applyRewrites(rewrites);
|
|
15302
15554
|
for (const [file, content] of updatedContents) {
|
|
15303
15555
|
fs25.writeFileSync(file, content, "utf8");
|
|
15304
|
-
console.log(
|
|
15556
|
+
console.log(chalk156.cyan(` Updated imports in ${path37.relative(cwd, file)}`));
|
|
15305
15557
|
}
|
|
15306
15558
|
const destDir = path37.dirname(destPath);
|
|
15307
15559
|
if (!fs25.existsSync(destDir)) fs25.mkdirSync(destDir, { recursive: true });
|
|
15308
15560
|
fs25.renameSync(sourcePath, destPath);
|
|
15309
15561
|
console.log(
|
|
15310
|
-
|
|
15562
|
+
chalk156.white(
|
|
15311
15563
|
` Moved ${path37.relative(cwd, sourcePath)} \u2192 ${path37.relative(cwd, destPath)}`
|
|
15312
15564
|
)
|
|
15313
15565
|
);
|
|
@@ -15394,16 +15646,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
15394
15646
|
|
|
15395
15647
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
15396
15648
|
import path39 from "path";
|
|
15397
|
-
import
|
|
15649
|
+
import chalk157 from "chalk";
|
|
15398
15650
|
function printRenamePreview(rewrites, cwd) {
|
|
15399
15651
|
for (const rewrite of rewrites) {
|
|
15400
15652
|
console.log(
|
|
15401
|
-
|
|
15653
|
+
chalk157.dim(
|
|
15402
15654
|
` ${path39.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
15403
15655
|
)
|
|
15404
15656
|
);
|
|
15405
15657
|
}
|
|
15406
|
-
console.log(
|
|
15658
|
+
console.log(chalk157.dim("Dry run. Use --apply to execute."));
|
|
15407
15659
|
}
|
|
15408
15660
|
|
|
15409
15661
|
// src/commands/refactor/rename/index.ts
|
|
@@ -15414,20 +15666,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
15414
15666
|
const relSource = path40.relative(cwd, sourcePath);
|
|
15415
15667
|
const relDest = path40.relative(cwd, destPath);
|
|
15416
15668
|
if (!fs26.existsSync(sourcePath)) {
|
|
15417
|
-
console.log(
|
|
15669
|
+
console.log(chalk158.red(`File not found: ${source}`));
|
|
15418
15670
|
process.exit(1);
|
|
15419
15671
|
}
|
|
15420
15672
|
if (destPath !== sourcePath && fs26.existsSync(destPath)) {
|
|
15421
|
-
console.log(
|
|
15673
|
+
console.log(chalk158.red(`Destination already exists: ${destination}`));
|
|
15422
15674
|
process.exit(1);
|
|
15423
15675
|
}
|
|
15424
|
-
console.log(
|
|
15425
|
-
console.log(
|
|
15426
|
-
console.log(
|
|
15676
|
+
console.log(chalk158.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
15677
|
+
console.log(chalk158.dim("Loading project..."));
|
|
15678
|
+
console.log(chalk158.dim("Scanning imports across the project..."));
|
|
15427
15679
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
15428
15680
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
15429
15681
|
console.log(
|
|
15430
|
-
|
|
15682
|
+
chalk158.dim(
|
|
15431
15683
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
15432
15684
|
)
|
|
15433
15685
|
);
|
|
@@ -15436,11 +15688,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
15436
15688
|
return;
|
|
15437
15689
|
}
|
|
15438
15690
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
15439
|
-
console.log(
|
|
15691
|
+
console.log(chalk158.green("Done"));
|
|
15440
15692
|
}
|
|
15441
15693
|
|
|
15442
15694
|
// src/commands/refactor/renameSymbol/index.ts
|
|
15443
|
-
import
|
|
15695
|
+
import chalk159 from "chalk";
|
|
15444
15696
|
|
|
15445
15697
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
15446
15698
|
import { SyntaxKind as SyntaxKind14 } from "ts-morph";
|
|
@@ -15486,33 +15738,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
15486
15738
|
const { project, sourceFile } = loadProjectFile(file);
|
|
15487
15739
|
const symbol = findSymbol(sourceFile, oldName);
|
|
15488
15740
|
if (!symbol) {
|
|
15489
|
-
console.log(
|
|
15741
|
+
console.log(chalk159.red(`Symbol "${oldName}" not found in ${file}`));
|
|
15490
15742
|
process.exit(1);
|
|
15491
15743
|
}
|
|
15492
15744
|
const grouped = groupReferences(symbol, cwd);
|
|
15493
15745
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
15494
15746
|
console.log(
|
|
15495
|
-
|
|
15747
|
+
chalk159.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
15496
15748
|
`)
|
|
15497
15749
|
);
|
|
15498
15750
|
for (const [refFile, lines] of grouped) {
|
|
15499
15751
|
console.log(
|
|
15500
|
-
` ${
|
|
15752
|
+
` ${chalk159.dim(refFile)}: lines ${chalk159.cyan(lines.join(", "))}`
|
|
15501
15753
|
);
|
|
15502
15754
|
}
|
|
15503
15755
|
if (options2.apply) {
|
|
15504
15756
|
symbol.rename(newName);
|
|
15505
15757
|
await project.save();
|
|
15506
|
-
console.log(
|
|
15758
|
+
console.log(chalk159.green(`
|
|
15507
15759
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
15508
15760
|
} else {
|
|
15509
|
-
console.log(
|
|
15761
|
+
console.log(chalk159.dim("\nDry run. Use --apply to execute."));
|
|
15510
15762
|
}
|
|
15511
15763
|
}
|
|
15512
15764
|
|
|
15513
15765
|
// src/commands/refactor/restructure/index.ts
|
|
15514
15766
|
import path48 from "path";
|
|
15515
|
-
import
|
|
15767
|
+
import chalk162 from "chalk";
|
|
15516
15768
|
|
|
15517
15769
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
15518
15770
|
import path42 from "path";
|
|
@@ -15591,50 +15843,50 @@ function clusterFiles(graph) {
|
|
|
15591
15843
|
|
|
15592
15844
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
15593
15845
|
import path44 from "path";
|
|
15594
|
-
import
|
|
15846
|
+
import chalk160 from "chalk";
|
|
15595
15847
|
function relPath(filePath) {
|
|
15596
15848
|
return path44.relative(process.cwd(), filePath);
|
|
15597
15849
|
}
|
|
15598
15850
|
function displayMoves(plan2) {
|
|
15599
15851
|
if (plan2.moves.length === 0) return;
|
|
15600
|
-
console.log(
|
|
15852
|
+
console.log(chalk160.bold("\nFile moves:"));
|
|
15601
15853
|
for (const move of plan2.moves) {
|
|
15602
15854
|
console.log(
|
|
15603
|
-
` ${
|
|
15855
|
+
` ${chalk160.red(relPath(move.from))} \u2192 ${chalk160.green(relPath(move.to))}`
|
|
15604
15856
|
);
|
|
15605
|
-
console.log(
|
|
15857
|
+
console.log(chalk160.dim(` ${move.reason}`));
|
|
15606
15858
|
}
|
|
15607
15859
|
}
|
|
15608
15860
|
function displayRewrites(rewrites) {
|
|
15609
15861
|
if (rewrites.length === 0) return;
|
|
15610
15862
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
15611
|
-
console.log(
|
|
15863
|
+
console.log(chalk160.bold(`
|
|
15612
15864
|
Import rewrites (${affectedFiles.size} files):`));
|
|
15613
15865
|
for (const file of affectedFiles) {
|
|
15614
|
-
console.log(` ${
|
|
15866
|
+
console.log(` ${chalk160.cyan(relPath(file))}:`);
|
|
15615
15867
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
15616
15868
|
(r) => r.file === file
|
|
15617
15869
|
)) {
|
|
15618
15870
|
console.log(
|
|
15619
|
-
` ${
|
|
15871
|
+
` ${chalk160.red(`"${oldSpecifier}"`)} \u2192 ${chalk160.green(`"${newSpecifier}"`)}`
|
|
15620
15872
|
);
|
|
15621
15873
|
}
|
|
15622
15874
|
}
|
|
15623
15875
|
}
|
|
15624
15876
|
function displayPlan2(plan2) {
|
|
15625
15877
|
if (plan2.warnings.length > 0) {
|
|
15626
|
-
console.log(
|
|
15627
|
-
for (const w of plan2.warnings) console.log(
|
|
15878
|
+
console.log(chalk160.yellow("\nWarnings:"));
|
|
15879
|
+
for (const w of plan2.warnings) console.log(chalk160.yellow(` ${w}`));
|
|
15628
15880
|
}
|
|
15629
15881
|
if (plan2.newDirectories.length > 0) {
|
|
15630
|
-
console.log(
|
|
15882
|
+
console.log(chalk160.bold("\nNew directories:"));
|
|
15631
15883
|
for (const dir of plan2.newDirectories)
|
|
15632
|
-
console.log(
|
|
15884
|
+
console.log(chalk160.green(` ${dir}/`));
|
|
15633
15885
|
}
|
|
15634
15886
|
displayMoves(plan2);
|
|
15635
15887
|
displayRewrites(plan2.rewrites);
|
|
15636
15888
|
console.log(
|
|
15637
|
-
|
|
15889
|
+
chalk160.dim(
|
|
15638
15890
|
`
|
|
15639
15891
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
15640
15892
|
)
|
|
@@ -15644,18 +15896,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
15644
15896
|
// src/commands/refactor/restructure/executePlan.ts
|
|
15645
15897
|
import fs27 from "fs";
|
|
15646
15898
|
import path45 from "path";
|
|
15647
|
-
import
|
|
15899
|
+
import chalk161 from "chalk";
|
|
15648
15900
|
function executePlan(plan2) {
|
|
15649
15901
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
15650
15902
|
for (const [file, content] of updatedContents) {
|
|
15651
15903
|
fs27.writeFileSync(file, content, "utf8");
|
|
15652
15904
|
console.log(
|
|
15653
|
-
|
|
15905
|
+
chalk161.cyan(` Rewrote imports in ${path45.relative(process.cwd(), file)}`)
|
|
15654
15906
|
);
|
|
15655
15907
|
}
|
|
15656
15908
|
for (const dir of plan2.newDirectories) {
|
|
15657
15909
|
fs27.mkdirSync(dir, { recursive: true });
|
|
15658
|
-
console.log(
|
|
15910
|
+
console.log(chalk161.green(` Created ${path45.relative(process.cwd(), dir)}/`));
|
|
15659
15911
|
}
|
|
15660
15912
|
for (const move of plan2.moves) {
|
|
15661
15913
|
const targetDir = path45.dirname(move.to);
|
|
@@ -15664,7 +15916,7 @@ function executePlan(plan2) {
|
|
|
15664
15916
|
}
|
|
15665
15917
|
fs27.renameSync(move.from, move.to);
|
|
15666
15918
|
console.log(
|
|
15667
|
-
|
|
15919
|
+
chalk161.white(
|
|
15668
15920
|
` Moved ${path45.relative(process.cwd(), move.from)} \u2192 ${path45.relative(process.cwd(), move.to)}`
|
|
15669
15921
|
)
|
|
15670
15922
|
);
|
|
@@ -15679,7 +15931,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
15679
15931
|
if (entries.length === 0) {
|
|
15680
15932
|
fs27.rmdirSync(dir);
|
|
15681
15933
|
console.log(
|
|
15682
|
-
|
|
15934
|
+
chalk161.dim(
|
|
15683
15935
|
` Removed empty directory ${path45.relative(process.cwd(), dir)}`
|
|
15684
15936
|
)
|
|
15685
15937
|
);
|
|
@@ -15812,22 +16064,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
15812
16064
|
const targetPattern = pattern2 ?? "src";
|
|
15813
16065
|
const files = findSourceFiles2(targetPattern);
|
|
15814
16066
|
if (files.length === 0) {
|
|
15815
|
-
console.log(
|
|
16067
|
+
console.log(chalk162.yellow("No files found matching pattern"));
|
|
15816
16068
|
return;
|
|
15817
16069
|
}
|
|
15818
16070
|
const tsConfigPath = path48.resolve("tsconfig.json");
|
|
15819
16071
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
15820
16072
|
if (plan2.moves.length === 0) {
|
|
15821
|
-
console.log(
|
|
16073
|
+
console.log(chalk162.green("No restructuring needed"));
|
|
15822
16074
|
return;
|
|
15823
16075
|
}
|
|
15824
16076
|
displayPlan2(plan2);
|
|
15825
16077
|
if (options2.apply) {
|
|
15826
|
-
console.log(
|
|
16078
|
+
console.log(chalk162.bold("\nApplying changes..."));
|
|
15827
16079
|
executePlan(plan2);
|
|
15828
|
-
console.log(
|
|
16080
|
+
console.log(chalk162.green("\nRestructuring complete"));
|
|
15829
16081
|
} else {
|
|
15830
|
-
console.log(
|
|
16082
|
+
console.log(chalk162.dim("\nDry run. Use --apply to execute."));
|
|
15831
16083
|
}
|
|
15832
16084
|
}
|
|
15833
16085
|
|
|
@@ -15982,11 +16234,11 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
|
15982
16234
|
}
|
|
15983
16235
|
|
|
15984
16236
|
// src/commands/review/buildReviewPaths.ts
|
|
15985
|
-
import { homedir as
|
|
15986
|
-
import { basename as basename7, join as
|
|
16237
|
+
import { homedir as homedir15 } from "os";
|
|
16238
|
+
import { basename as basename7, join as join47 } from "path";
|
|
15987
16239
|
function buildReviewPaths(repoRoot, key) {
|
|
15988
|
-
const reviewDir =
|
|
15989
|
-
|
|
16240
|
+
const reviewDir = join47(
|
|
16241
|
+
homedir15(),
|
|
15990
16242
|
".assist",
|
|
15991
16243
|
"reviews",
|
|
15992
16244
|
basename7(repoRoot),
|
|
@@ -15994,10 +16246,10 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
15994
16246
|
);
|
|
15995
16247
|
return {
|
|
15996
16248
|
reviewDir,
|
|
15997
|
-
requestPath:
|
|
15998
|
-
claudePath:
|
|
15999
|
-
codexPath:
|
|
16000
|
-
synthesisPath:
|
|
16249
|
+
requestPath: join47(reviewDir, "request.md"),
|
|
16250
|
+
claudePath: join47(reviewDir, "claude.md"),
|
|
16251
|
+
codexPath: join47(reviewDir, "codex.md"),
|
|
16252
|
+
synthesisPath: join47(reviewDir, "synthesis.md")
|
|
16001
16253
|
};
|
|
16002
16254
|
}
|
|
16003
16255
|
|
|
@@ -16140,7 +16392,7 @@ function gatherContext() {
|
|
|
16140
16392
|
}
|
|
16141
16393
|
|
|
16142
16394
|
// src/commands/review/postReviewToPr.ts
|
|
16143
|
-
import { readFileSync as
|
|
16395
|
+
import { readFileSync as readFileSync34 } from "fs";
|
|
16144
16396
|
|
|
16145
16397
|
// src/commands/review/parseFindings.ts
|
|
16146
16398
|
var SEVERITIES = ["blocker", "major", "minor", "nit"];
|
|
@@ -16396,18 +16648,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
16396
16648
|
}
|
|
16397
16649
|
|
|
16398
16650
|
// src/commands/review/warnOutOfDiff.ts
|
|
16399
|
-
import
|
|
16651
|
+
import chalk163 from "chalk";
|
|
16400
16652
|
function warnOutOfDiff(outOfDiff) {
|
|
16401
16653
|
if (outOfDiff.length === 0) return;
|
|
16402
16654
|
console.warn(
|
|
16403
|
-
|
|
16655
|
+
chalk163.yellow(
|
|
16404
16656
|
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
16405
16657
|
)
|
|
16406
16658
|
);
|
|
16407
16659
|
for (const finding of outOfDiff) {
|
|
16408
16660
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
16409
16661
|
console.warn(
|
|
16410
|
-
` ${
|
|
16662
|
+
` ${chalk163.yellow("\xB7")} ${finding.title} ${chalk163.dim(
|
|
16411
16663
|
`(${finding.file}:${range})`
|
|
16412
16664
|
)}`
|
|
16413
16665
|
);
|
|
@@ -16426,18 +16678,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
16426
16678
|
}
|
|
16427
16679
|
|
|
16428
16680
|
// src/commands/review/warnUnlocated.ts
|
|
16429
|
-
import
|
|
16681
|
+
import chalk164 from "chalk";
|
|
16430
16682
|
function warnUnlocated(unlocated) {
|
|
16431
16683
|
if (unlocated.length === 0) return;
|
|
16432
16684
|
console.warn(
|
|
16433
|
-
|
|
16685
|
+
chalk164.yellow(
|
|
16434
16686
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
16435
16687
|
)
|
|
16436
16688
|
);
|
|
16437
16689
|
for (const finding of unlocated) {
|
|
16438
|
-
const where = finding.location ||
|
|
16690
|
+
const where = finding.location || chalk164.dim("missing");
|
|
16439
16691
|
console.warn(
|
|
16440
|
-
` ${
|
|
16692
|
+
` ${chalk164.yellow("\xB7")} ${finding.title} ${chalk164.dim(`(${where})`)}`
|
|
16441
16693
|
);
|
|
16442
16694
|
}
|
|
16443
16695
|
}
|
|
@@ -16450,7 +16702,7 @@ async function confirmPost(prNumber, count6, options2) {
|
|
|
16450
16702
|
async function postReviewToPr(synthesisPath, options2) {
|
|
16451
16703
|
const prInfo = fetchPrDiffInfo();
|
|
16452
16704
|
const prNumber = prInfo.prNumber;
|
|
16453
|
-
const markdown =
|
|
16705
|
+
const markdown = readFileSync34(synthesisPath, "utf8");
|
|
16454
16706
|
const findings = parseFindings(markdown);
|
|
16455
16707
|
if (findings.length === 0) {
|
|
16456
16708
|
console.log("Synthesis contains no findings; nothing to post.");
|
|
@@ -16532,16 +16784,16 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
16532
16784
|
}
|
|
16533
16785
|
|
|
16534
16786
|
// src/commands/review/prepareReviewDir.ts
|
|
16535
|
-
import { existsSync as
|
|
16787
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync15, unlinkSync as unlinkSync14, writeFileSync as writeFileSync33 } from "fs";
|
|
16536
16788
|
function clearReviewFiles(paths) {
|
|
16537
16789
|
for (const path57 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
16538
|
-
if (
|
|
16790
|
+
if (existsSync38(path57)) unlinkSync14(path57);
|
|
16539
16791
|
}
|
|
16540
16792
|
}
|
|
16541
16793
|
function prepareReviewDir(paths, requestBody, force) {
|
|
16542
|
-
|
|
16794
|
+
mkdirSync15(paths.reviewDir, { recursive: true });
|
|
16543
16795
|
if (force) clearReviewFiles(paths);
|
|
16544
|
-
|
|
16796
|
+
writeFileSync33(paths.requestPath, requestBody);
|
|
16545
16797
|
}
|
|
16546
16798
|
|
|
16547
16799
|
// src/commands/review/runApplySession.ts
|
|
@@ -16603,11 +16855,11 @@ async function runBacklogSession(synthesisPath) {
|
|
|
16603
16855
|
}
|
|
16604
16856
|
|
|
16605
16857
|
// src/commands/review/cachedReviewerResult.ts
|
|
16606
|
-
import { statSync as
|
|
16858
|
+
import { statSync as statSync5 } from "fs";
|
|
16607
16859
|
function cachedReviewerResult(name, outputPath) {
|
|
16608
16860
|
let size;
|
|
16609
16861
|
try {
|
|
16610
|
-
size =
|
|
16862
|
+
size = statSync5(outputPath).size;
|
|
16611
16863
|
} catch {
|
|
16612
16864
|
return null;
|
|
16613
16865
|
}
|
|
@@ -16820,7 +17072,7 @@ function printReviewerFailures(results) {
|
|
|
16820
17072
|
}
|
|
16821
17073
|
|
|
16822
17074
|
// src/commands/review/runAndSynthesise.ts
|
|
16823
|
-
import { existsSync as
|
|
17075
|
+
import { existsSync as existsSync40, unlinkSync as unlinkSync16 } from "fs";
|
|
16824
17076
|
|
|
16825
17077
|
// src/commands/review/buildReviewerStdin.ts
|
|
16826
17078
|
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in the request file whose absolute path is given below.
|
|
@@ -16886,7 +17138,7 @@ The review request is at: ${requestPath}
|
|
|
16886
17138
|
}
|
|
16887
17139
|
|
|
16888
17140
|
// src/commands/review/runClaudeReviewer.ts
|
|
16889
|
-
import { writeFileSync as
|
|
17141
|
+
import { writeFileSync as writeFileSync34 } from "fs";
|
|
16890
17142
|
|
|
16891
17143
|
// src/commands/review/finaliseReviewerSpinner.ts
|
|
16892
17144
|
var SUMMARY_MAX_LEN = 80;
|
|
@@ -17222,7 +17474,7 @@ async function runClaudeReviewer(spec) {
|
|
|
17222
17474
|
}
|
|
17223
17475
|
});
|
|
17224
17476
|
if (result.exitCode === 0 && finalText)
|
|
17225
|
-
|
|
17477
|
+
writeFileSync34(spec.outputPath, finalText);
|
|
17226
17478
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
17227
17479
|
}
|
|
17228
17480
|
|
|
@@ -17240,7 +17492,7 @@ function resolveClaude(args) {
|
|
|
17240
17492
|
}
|
|
17241
17493
|
|
|
17242
17494
|
// src/commands/review/runCodexReviewer.ts
|
|
17243
|
-
import { existsSync as
|
|
17495
|
+
import { existsSync as existsSync39, unlinkSync as unlinkSync15 } from "fs";
|
|
17244
17496
|
|
|
17245
17497
|
// src/commands/review/parseCodexEvent.ts
|
|
17246
17498
|
function isItemStarted(value) {
|
|
@@ -17292,8 +17544,8 @@ async function runCodexReviewer(spec) {
|
|
|
17292
17544
|
reportReviewerToolUse(spec.name, event, spinner);
|
|
17293
17545
|
}
|
|
17294
17546
|
});
|
|
17295
|
-
if (result.exitCode !== 0 &&
|
|
17296
|
-
|
|
17547
|
+
if (result.exitCode !== 0 && existsSync39(spec.outputPath)) {
|
|
17548
|
+
unlinkSync15(spec.outputPath);
|
|
17297
17549
|
}
|
|
17298
17550
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
17299
17551
|
}
|
|
@@ -17334,7 +17586,7 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
|
|
|
17334
17586
|
}
|
|
17335
17587
|
|
|
17336
17588
|
// src/commands/review/synthesise.ts
|
|
17337
|
-
import { readFileSync as
|
|
17589
|
+
import { readFileSync as readFileSync35 } from "fs";
|
|
17338
17590
|
|
|
17339
17591
|
// src/commands/review/buildSynthesisStdin.ts
|
|
17340
17592
|
var SYNTHESIS_PROMPT = `You are consolidating two independent code reviews of the same change. The original review request is in request.md. The two reviews are in claude.md and codex.md in the current working directory.
|
|
@@ -17390,7 +17642,7 @@ Files:
|
|
|
17390
17642
|
|
|
17391
17643
|
// src/commands/review/synthesise.ts
|
|
17392
17644
|
function printSummary2(synthesisPath) {
|
|
17393
|
-
const markdown =
|
|
17645
|
+
const markdown = readFileSync35(synthesisPath, "utf8");
|
|
17394
17646
|
console.log("");
|
|
17395
17647
|
console.log(buildReviewSummary(markdown));
|
|
17396
17648
|
console.log("");
|
|
@@ -17438,8 +17690,8 @@ async function runAndSynthesise(args) {
|
|
|
17438
17690
|
console.error("Both reviewers failed; skipping synthesis.");
|
|
17439
17691
|
return { ok: false, failures };
|
|
17440
17692
|
}
|
|
17441
|
-
if (anyFresh &&
|
|
17442
|
-
|
|
17693
|
+
if (anyFresh && existsSync40(paths.synthesisPath)) {
|
|
17694
|
+
unlinkSync16(paths.synthesisPath);
|
|
17443
17695
|
}
|
|
17444
17696
|
const synthesisResult = await synthesise(paths, { multi });
|
|
17445
17697
|
if (synthesisResult.exitCode !== 0) failures.push(synthesisResult);
|
|
@@ -17608,7 +17860,7 @@ function registerReview(program2) {
|
|
|
17608
17860
|
}
|
|
17609
17861
|
|
|
17610
17862
|
// src/commands/seq/seqAuth.ts
|
|
17611
|
-
import
|
|
17863
|
+
import chalk166 from "chalk";
|
|
17612
17864
|
|
|
17613
17865
|
// src/commands/seq/loadConnections.ts
|
|
17614
17866
|
function loadConnections2() {
|
|
@@ -17637,10 +17889,10 @@ function setDefaultConnection(name) {
|
|
|
17637
17889
|
}
|
|
17638
17890
|
|
|
17639
17891
|
// src/shared/assertUniqueName.ts
|
|
17640
|
-
import
|
|
17892
|
+
import chalk165 from "chalk";
|
|
17641
17893
|
function assertUniqueName(existingNames, name) {
|
|
17642
17894
|
if (existingNames.includes(name)) {
|
|
17643
|
-
console.error(
|
|
17895
|
+
console.error(chalk165.red(`Connection "${name}" already exists.`));
|
|
17644
17896
|
process.exit(1);
|
|
17645
17897
|
}
|
|
17646
17898
|
}
|
|
@@ -17658,16 +17910,16 @@ async function promptConnection2(existingNames) {
|
|
|
17658
17910
|
var seqAuth = createConnectionAuth({
|
|
17659
17911
|
load: loadConnections2,
|
|
17660
17912
|
save: saveConnections2,
|
|
17661
|
-
format: (c) => `${
|
|
17913
|
+
format: (c) => `${chalk166.bold(c.name)} ${c.url}`,
|
|
17662
17914
|
promptNew: promptConnection2,
|
|
17663
17915
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
17664
17916
|
});
|
|
17665
17917
|
|
|
17666
17918
|
// src/commands/seq/seqQuery.ts
|
|
17667
|
-
import
|
|
17919
|
+
import chalk170 from "chalk";
|
|
17668
17920
|
|
|
17669
17921
|
// src/commands/seq/fetchSeq.ts
|
|
17670
|
-
import
|
|
17922
|
+
import chalk167 from "chalk";
|
|
17671
17923
|
async function fetchSeq(conn, path57, params) {
|
|
17672
17924
|
const url = `${conn.url}${path57}?${params}`;
|
|
17673
17925
|
const response = await fetch(url, {
|
|
@@ -17678,7 +17930,7 @@ async function fetchSeq(conn, path57, params) {
|
|
|
17678
17930
|
});
|
|
17679
17931
|
if (!response.ok) {
|
|
17680
17932
|
const body = await response.text();
|
|
17681
|
-
console.error(
|
|
17933
|
+
console.error(chalk167.red(`Seq returned ${response.status}: ${body}`));
|
|
17682
17934
|
process.exit(1);
|
|
17683
17935
|
}
|
|
17684
17936
|
return response;
|
|
@@ -17737,23 +17989,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
17737
17989
|
}
|
|
17738
17990
|
|
|
17739
17991
|
// src/commands/seq/formatEvent.ts
|
|
17740
|
-
import
|
|
17992
|
+
import chalk168 from "chalk";
|
|
17741
17993
|
function levelColor(level) {
|
|
17742
17994
|
switch (level) {
|
|
17743
17995
|
case "Fatal":
|
|
17744
|
-
return
|
|
17996
|
+
return chalk168.bgRed.white;
|
|
17745
17997
|
case "Error":
|
|
17746
|
-
return
|
|
17998
|
+
return chalk168.red;
|
|
17747
17999
|
case "Warning":
|
|
17748
|
-
return
|
|
18000
|
+
return chalk168.yellow;
|
|
17749
18001
|
case "Information":
|
|
17750
|
-
return
|
|
18002
|
+
return chalk168.cyan;
|
|
17751
18003
|
case "Debug":
|
|
17752
|
-
return
|
|
18004
|
+
return chalk168.gray;
|
|
17753
18005
|
case "Verbose":
|
|
17754
|
-
return
|
|
18006
|
+
return chalk168.dim;
|
|
17755
18007
|
default:
|
|
17756
|
-
return
|
|
18008
|
+
return chalk168.white;
|
|
17757
18009
|
}
|
|
17758
18010
|
}
|
|
17759
18011
|
function levelAbbrev(level) {
|
|
@@ -17794,12 +18046,12 @@ function formatTimestamp(iso) {
|
|
|
17794
18046
|
function formatEvent(event) {
|
|
17795
18047
|
const color = levelColor(event.Level);
|
|
17796
18048
|
const abbrev = levelAbbrev(event.Level);
|
|
17797
|
-
const ts8 =
|
|
18049
|
+
const ts8 = chalk168.dim(formatTimestamp(event.Timestamp));
|
|
17798
18050
|
const msg = renderMessage(event);
|
|
17799
18051
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
17800
18052
|
if (event.Exception) {
|
|
17801
18053
|
for (const line of event.Exception.split("\n")) {
|
|
17802
|
-
lines.push(
|
|
18054
|
+
lines.push(chalk168.red(` ${line}`));
|
|
17803
18055
|
}
|
|
17804
18056
|
}
|
|
17805
18057
|
return lines.join("\n");
|
|
@@ -17832,11 +18084,11 @@ function rejectTimestampFilter(filter) {
|
|
|
17832
18084
|
}
|
|
17833
18085
|
|
|
17834
18086
|
// src/shared/resolveNamedConnection.ts
|
|
17835
|
-
import
|
|
18087
|
+
import chalk169 from "chalk";
|
|
17836
18088
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
17837
18089
|
if (connections.length === 0) {
|
|
17838
18090
|
console.error(
|
|
17839
|
-
|
|
18091
|
+
chalk169.red(
|
|
17840
18092
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
17841
18093
|
)
|
|
17842
18094
|
);
|
|
@@ -17845,7 +18097,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
17845
18097
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
17846
18098
|
const connection = connections.find((c) => c.name === target);
|
|
17847
18099
|
if (!connection) {
|
|
17848
|
-
console.error(
|
|
18100
|
+
console.error(chalk169.red(`${kind} connection "${target}" not found.`));
|
|
17849
18101
|
process.exit(1);
|
|
17850
18102
|
}
|
|
17851
18103
|
return connection;
|
|
@@ -17874,7 +18126,7 @@ async function seqQuery(filter, options2) {
|
|
|
17874
18126
|
new URLSearchParams({ filter, count: String(count6) })
|
|
17875
18127
|
);
|
|
17876
18128
|
if (events.length === 0) {
|
|
17877
|
-
console.log(
|
|
18129
|
+
console.log(chalk170.yellow("No events found."));
|
|
17878
18130
|
return;
|
|
17879
18131
|
}
|
|
17880
18132
|
if (options2.json) {
|
|
@@ -17885,11 +18137,11 @@ async function seqQuery(filter, options2) {
|
|
|
17885
18137
|
for (const event of chronological) {
|
|
17886
18138
|
console.log(formatEvent(event));
|
|
17887
18139
|
}
|
|
17888
|
-
console.log(
|
|
18140
|
+
console.log(chalk170.dim(`
|
|
17889
18141
|
${events.length} events`));
|
|
17890
18142
|
if (events.length >= count6) {
|
|
17891
18143
|
console.log(
|
|
17892
|
-
|
|
18144
|
+
chalk170.yellow(
|
|
17893
18145
|
`Results limited to ${count6}. Use --count to retrieve more.`
|
|
17894
18146
|
)
|
|
17895
18147
|
);
|
|
@@ -17897,10 +18149,10 @@ ${events.length} events`));
|
|
|
17897
18149
|
}
|
|
17898
18150
|
|
|
17899
18151
|
// src/shared/setNamedDefaultConnection.ts
|
|
17900
|
-
import
|
|
18152
|
+
import chalk171 from "chalk";
|
|
17901
18153
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
17902
18154
|
if (!connections.find((c) => c.name === name)) {
|
|
17903
|
-
console.error(
|
|
18155
|
+
console.error(chalk171.red(`Connection "${name}" not found.`));
|
|
17904
18156
|
process.exit(1);
|
|
17905
18157
|
}
|
|
17906
18158
|
setDefault(name);
|
|
@@ -17948,7 +18200,7 @@ function registerSignal(program2) {
|
|
|
17948
18200
|
}
|
|
17949
18201
|
|
|
17950
18202
|
// src/commands/sql/sqlAuth.ts
|
|
17951
|
-
import
|
|
18203
|
+
import chalk173 from "chalk";
|
|
17952
18204
|
|
|
17953
18205
|
// src/commands/sql/loadConnections.ts
|
|
17954
18206
|
function loadConnections3() {
|
|
@@ -17977,7 +18229,7 @@ function setDefaultConnection2(name) {
|
|
|
17977
18229
|
}
|
|
17978
18230
|
|
|
17979
18231
|
// src/commands/sql/promptConnection.ts
|
|
17980
|
-
import
|
|
18232
|
+
import chalk172 from "chalk";
|
|
17981
18233
|
async function promptConnection3(existingNames) {
|
|
17982
18234
|
const name = await promptInput("name", "Connection name:", "default");
|
|
17983
18235
|
assertUniqueName(existingNames, name);
|
|
@@ -17985,7 +18237,7 @@ async function promptConnection3(existingNames) {
|
|
|
17985
18237
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
17986
18238
|
const port = Number.parseInt(portStr, 10);
|
|
17987
18239
|
if (!Number.isFinite(port)) {
|
|
17988
|
-
console.error(
|
|
18240
|
+
console.error(chalk172.red(`Invalid port "${portStr}".`));
|
|
17989
18241
|
process.exit(1);
|
|
17990
18242
|
}
|
|
17991
18243
|
const user = await promptInput("user", "User:");
|
|
@@ -17998,13 +18250,13 @@ async function promptConnection3(existingNames) {
|
|
|
17998
18250
|
var sqlAuth = createConnectionAuth({
|
|
17999
18251
|
load: loadConnections3,
|
|
18000
18252
|
save: saveConnections3,
|
|
18001
|
-
format: (c) => `${
|
|
18253
|
+
format: (c) => `${chalk173.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
18002
18254
|
promptNew: promptConnection3,
|
|
18003
18255
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
18004
18256
|
});
|
|
18005
18257
|
|
|
18006
18258
|
// src/commands/sql/printTable.ts
|
|
18007
|
-
import
|
|
18259
|
+
import chalk174 from "chalk";
|
|
18008
18260
|
function formatCell(value) {
|
|
18009
18261
|
if (value === null || value === void 0) return "";
|
|
18010
18262
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -18013,7 +18265,7 @@ function formatCell(value) {
|
|
|
18013
18265
|
}
|
|
18014
18266
|
function printTable(rows) {
|
|
18015
18267
|
if (rows.length === 0) {
|
|
18016
|
-
console.log(
|
|
18268
|
+
console.log(chalk174.yellow("(no rows)"));
|
|
18017
18269
|
return;
|
|
18018
18270
|
}
|
|
18019
18271
|
const columns = Object.keys(rows[0]);
|
|
@@ -18021,13 +18273,13 @@ function printTable(rows) {
|
|
|
18021
18273
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
18022
18274
|
);
|
|
18023
18275
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
18024
|
-
console.log(
|
|
18025
|
-
console.log(
|
|
18276
|
+
console.log(chalk174.dim(header));
|
|
18277
|
+
console.log(chalk174.dim("-".repeat(header.length)));
|
|
18026
18278
|
for (const row of rows) {
|
|
18027
18279
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
18028
18280
|
console.log(line);
|
|
18029
18281
|
}
|
|
18030
|
-
console.log(
|
|
18282
|
+
console.log(chalk174.dim(`
|
|
18031
18283
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
18032
18284
|
}
|
|
18033
18285
|
|
|
@@ -18087,7 +18339,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
18087
18339
|
}
|
|
18088
18340
|
|
|
18089
18341
|
// src/commands/sql/sqlMutate.ts
|
|
18090
|
-
import
|
|
18342
|
+
import chalk175 from "chalk";
|
|
18091
18343
|
|
|
18092
18344
|
// src/commands/sql/isMutation.ts
|
|
18093
18345
|
var MUTATION_KEYWORDS = [
|
|
@@ -18121,7 +18373,7 @@ function isMutation(sql6) {
|
|
|
18121
18373
|
async function sqlMutate(query, connectionName) {
|
|
18122
18374
|
if (!isMutation(query)) {
|
|
18123
18375
|
console.error(
|
|
18124
|
-
|
|
18376
|
+
chalk175.red(
|
|
18125
18377
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
18126
18378
|
)
|
|
18127
18379
|
);
|
|
@@ -18131,18 +18383,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
18131
18383
|
const pool = await sqlConnect(conn);
|
|
18132
18384
|
try {
|
|
18133
18385
|
const result = await pool.request().query(query);
|
|
18134
|
-
console.log(
|
|
18386
|
+
console.log(chalk175.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
18135
18387
|
} finally {
|
|
18136
18388
|
await pool.close();
|
|
18137
18389
|
}
|
|
18138
18390
|
}
|
|
18139
18391
|
|
|
18140
18392
|
// src/commands/sql/sqlQuery.ts
|
|
18141
|
-
import
|
|
18393
|
+
import chalk176 from "chalk";
|
|
18142
18394
|
async function sqlQuery(query, connectionName) {
|
|
18143
18395
|
if (isMutation(query)) {
|
|
18144
18396
|
console.error(
|
|
18145
|
-
|
|
18397
|
+
chalk176.red(
|
|
18146
18398
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
18147
18399
|
)
|
|
18148
18400
|
);
|
|
@@ -18157,7 +18409,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
18157
18409
|
printTable(rows);
|
|
18158
18410
|
} else {
|
|
18159
18411
|
console.log(
|
|
18160
|
-
|
|
18412
|
+
chalk176.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
18161
18413
|
);
|
|
18162
18414
|
}
|
|
18163
18415
|
} finally {
|
|
@@ -18217,8 +18469,8 @@ function registerSql(program2) {
|
|
|
18217
18469
|
}
|
|
18218
18470
|
|
|
18219
18471
|
// src/commands/transcript/shared.ts
|
|
18220
|
-
import { existsSync as
|
|
18221
|
-
import { basename as basename8, join as
|
|
18472
|
+
import { existsSync as existsSync41, readdirSync as readdirSync8, statSync as statSync6 } from "fs";
|
|
18473
|
+
import { basename as basename8, join as join48, relative as relative2 } from "path";
|
|
18222
18474
|
import * as readline2 from "readline";
|
|
18223
18475
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
18224
18476
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -18233,11 +18485,11 @@ function isValidDatePrefix(filename) {
|
|
|
18233
18485
|
return DATE_PREFIX_REGEX.test(filename);
|
|
18234
18486
|
}
|
|
18235
18487
|
function collectFiles(dir, extension) {
|
|
18236
|
-
if (!
|
|
18488
|
+
if (!existsSync41(dir)) return [];
|
|
18237
18489
|
const results = [];
|
|
18238
|
-
for (const entry of
|
|
18239
|
-
const fullPath =
|
|
18240
|
-
if (
|
|
18490
|
+
for (const entry of readdirSync8(dir)) {
|
|
18491
|
+
const fullPath = join48(dir, entry);
|
|
18492
|
+
if (statSync6(fullPath).isDirectory()) {
|
|
18241
18493
|
results.push(...collectFiles(fullPath, extension));
|
|
18242
18494
|
} else if (entry.endsWith(extension)) {
|
|
18243
18495
|
results.push(fullPath);
|
|
@@ -18330,14 +18582,14 @@ async function configure() {
|
|
|
18330
18582
|
}
|
|
18331
18583
|
|
|
18332
18584
|
// src/commands/transcript/format/index.ts
|
|
18333
|
-
import { existsSync as
|
|
18585
|
+
import { existsSync as existsSync43 } from "fs";
|
|
18334
18586
|
|
|
18335
18587
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
18336
|
-
import { dirname as dirname22, join as
|
|
18588
|
+
import { dirname as dirname22, join as join50 } from "path";
|
|
18337
18589
|
|
|
18338
18590
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
18339
18591
|
import { renameSync as renameSync2 } from "fs";
|
|
18340
|
-
import { join as
|
|
18592
|
+
import { join as join49 } from "path";
|
|
18341
18593
|
async function resolveDate(rl, choice) {
|
|
18342
18594
|
if (choice === "1") return getDatePrefix(0);
|
|
18343
18595
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -18352,7 +18604,7 @@ async function resolveDate(rl, choice) {
|
|
|
18352
18604
|
}
|
|
18353
18605
|
function renameWithPrefix(vttDir, vttFile, prefix2) {
|
|
18354
18606
|
const newFilename = `${prefix2}.${vttFile}`;
|
|
18355
|
-
renameSync2(
|
|
18607
|
+
renameSync2(join49(vttDir, vttFile), join49(vttDir, newFilename));
|
|
18356
18608
|
console.log(`Renamed to: ${newFilename}`);
|
|
18357
18609
|
return newFilename;
|
|
18358
18610
|
}
|
|
@@ -18386,12 +18638,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
18386
18638
|
const vttFileDir = dirname22(vttFile.absolutePath);
|
|
18387
18639
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
18388
18640
|
if (newFilename) {
|
|
18389
|
-
const newRelativePath =
|
|
18641
|
+
const newRelativePath = join50(
|
|
18390
18642
|
dirname22(vttFile.relativePath),
|
|
18391
18643
|
newFilename
|
|
18392
18644
|
);
|
|
18393
18645
|
vttFiles[i] = {
|
|
18394
|
-
absolutePath:
|
|
18646
|
+
absolutePath: join50(vttFileDir, newFilename),
|
|
18395
18647
|
relativePath: newRelativePath,
|
|
18396
18648
|
filename: newFilename
|
|
18397
18649
|
};
|
|
@@ -18404,8 +18656,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
18404
18656
|
}
|
|
18405
18657
|
|
|
18406
18658
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
18407
|
-
import { existsSync as
|
|
18408
|
-
import { basename as basename9, dirname as dirname23, join as
|
|
18659
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync16, readFileSync as readFileSync36, writeFileSync as writeFileSync35 } from "fs";
|
|
18660
|
+
import { basename as basename9, dirname as dirname23, join as join51 } from "path";
|
|
18409
18661
|
|
|
18410
18662
|
// src/commands/transcript/cleanText.ts
|
|
18411
18663
|
function cleanText(text6) {
|
|
@@ -18615,22 +18867,22 @@ function toMdFilename(vttFilename) {
|
|
|
18615
18867
|
return `${basename9(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
18616
18868
|
}
|
|
18617
18869
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
18618
|
-
return relativeDir === "." ? transcriptsDir :
|
|
18870
|
+
return relativeDir === "." ? transcriptsDir : join51(transcriptsDir, relativeDir);
|
|
18619
18871
|
}
|
|
18620
18872
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
18621
18873
|
const mdFile = toMdFilename(vttFile.filename);
|
|
18622
18874
|
const relativeDir = dirname23(vttFile.relativePath);
|
|
18623
18875
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
18624
|
-
const outputPath =
|
|
18876
|
+
const outputPath = join51(outputDir, mdFile);
|
|
18625
18877
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
18626
18878
|
}
|
|
18627
18879
|
function logSkipped(relativeDir, mdFile) {
|
|
18628
|
-
console.log(`Skipping (already exists): ${
|
|
18880
|
+
console.log(`Skipping (already exists): ${join51(relativeDir, mdFile)}`);
|
|
18629
18881
|
return "skipped";
|
|
18630
18882
|
}
|
|
18631
18883
|
function ensureDirectory(dir, label2) {
|
|
18632
|
-
if (!
|
|
18633
|
-
|
|
18884
|
+
if (!existsSync42(dir)) {
|
|
18885
|
+
mkdirSync16(dir, { recursive: true });
|
|
18634
18886
|
console.log(`Created ${label2}: ${dir}`);
|
|
18635
18887
|
}
|
|
18636
18888
|
}
|
|
@@ -18652,10 +18904,10 @@ function logReduction(cueCount, messageCount) {
|
|
|
18652
18904
|
}
|
|
18653
18905
|
function readAndParseCues(inputPath) {
|
|
18654
18906
|
console.log(`Reading: ${inputPath}`);
|
|
18655
|
-
return processCues(
|
|
18907
|
+
return processCues(readFileSync36(inputPath, "utf8"));
|
|
18656
18908
|
}
|
|
18657
18909
|
function writeFormatted(outputPath, content) {
|
|
18658
|
-
|
|
18910
|
+
writeFileSync35(outputPath, content, "utf8");
|
|
18659
18911
|
console.log(`Written: ${outputPath}`);
|
|
18660
18912
|
}
|
|
18661
18913
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -18665,7 +18917,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
18665
18917
|
logReduction(cues.length, chatMessages.length);
|
|
18666
18918
|
}
|
|
18667
18919
|
function tryProcessVtt(vttFile, paths) {
|
|
18668
|
-
if (
|
|
18920
|
+
if (existsSync42(paths.outputPath))
|
|
18669
18921
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
18670
18922
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
18671
18923
|
return "processed";
|
|
@@ -18691,7 +18943,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
18691
18943
|
logSummary(counts);
|
|
18692
18944
|
}
|
|
18693
18945
|
function requireVttDir(vttDir) {
|
|
18694
|
-
if (!
|
|
18946
|
+
if (!existsSync43(vttDir)) {
|
|
18695
18947
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
18696
18948
|
process.exit(1);
|
|
18697
18949
|
}
|
|
@@ -18723,28 +18975,28 @@ async function format() {
|
|
|
18723
18975
|
}
|
|
18724
18976
|
|
|
18725
18977
|
// src/commands/transcript/summarise/index.ts
|
|
18726
|
-
import { existsSync as
|
|
18727
|
-
import { basename as basename10, dirname as dirname25, join as
|
|
18978
|
+
import { existsSync as existsSync45 } from "fs";
|
|
18979
|
+
import { basename as basename10, dirname as dirname25, join as join53, relative as relative3 } from "path";
|
|
18728
18980
|
|
|
18729
18981
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
18730
18982
|
import {
|
|
18731
|
-
existsSync as
|
|
18732
|
-
mkdirSync as
|
|
18733
|
-
readFileSync as
|
|
18983
|
+
existsSync as existsSync44,
|
|
18984
|
+
mkdirSync as mkdirSync17,
|
|
18985
|
+
readFileSync as readFileSync37,
|
|
18734
18986
|
renameSync as renameSync3,
|
|
18735
18987
|
rmSync as rmSync3
|
|
18736
18988
|
} from "fs";
|
|
18737
|
-
import { dirname as dirname24, join as
|
|
18989
|
+
import { dirname as dirname24, join as join52 } from "path";
|
|
18738
18990
|
|
|
18739
18991
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
18740
|
-
import
|
|
18992
|
+
import chalk177 from "chalk";
|
|
18741
18993
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
18742
18994
|
function validateStagedContent(filename, content) {
|
|
18743
18995
|
const firstLine = content.split("\n")[0];
|
|
18744
18996
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
18745
18997
|
if (!match) {
|
|
18746
18998
|
console.error(
|
|
18747
|
-
|
|
18999
|
+
chalk177.red(
|
|
18748
19000
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
18749
19001
|
)
|
|
18750
19002
|
);
|
|
@@ -18753,7 +19005,7 @@ function validateStagedContent(filename, content) {
|
|
|
18753
19005
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
18754
19006
|
if (!contentAfterLink) {
|
|
18755
19007
|
console.error(
|
|
18756
|
-
|
|
19008
|
+
chalk177.red(
|
|
18757
19009
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
18758
19010
|
)
|
|
18759
19011
|
);
|
|
@@ -18763,9 +19015,9 @@ function validateStagedContent(filename, content) {
|
|
|
18763
19015
|
}
|
|
18764
19016
|
|
|
18765
19017
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
18766
|
-
var STAGING_DIR =
|
|
19018
|
+
var STAGING_DIR = join52(process.cwd(), ".assist", "transcript");
|
|
18767
19019
|
function processStagedFile() {
|
|
18768
|
-
if (!
|
|
19020
|
+
if (!existsSync44(STAGING_DIR)) {
|
|
18769
19021
|
return false;
|
|
18770
19022
|
}
|
|
18771
19023
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -18774,7 +19026,7 @@ function processStagedFile() {
|
|
|
18774
19026
|
}
|
|
18775
19027
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
18776
19028
|
const stagedFile = stagedFiles[0];
|
|
18777
|
-
const content =
|
|
19029
|
+
const content = readFileSync37(stagedFile.absolutePath, "utf8");
|
|
18778
19030
|
validateStagedContent(stagedFile.filename, content);
|
|
18779
19031
|
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
18780
19032
|
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
@@ -18787,10 +19039,10 @@ function processStagedFile() {
|
|
|
18787
19039
|
);
|
|
18788
19040
|
process.exit(1);
|
|
18789
19041
|
}
|
|
18790
|
-
const destPath =
|
|
19042
|
+
const destPath = join52(summaryDir, matchingTranscript.relativePath);
|
|
18791
19043
|
const destDir = dirname24(destPath);
|
|
18792
|
-
if (!
|
|
18793
|
-
|
|
19044
|
+
if (!existsSync44(destDir)) {
|
|
19045
|
+
mkdirSync17(destDir, { recursive: true });
|
|
18794
19046
|
}
|
|
18795
19047
|
renameSync3(stagedFile.absolutePath, destPath);
|
|
18796
19048
|
const remaining = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -18803,7 +19055,7 @@ function processStagedFile() {
|
|
|
18803
19055
|
// src/commands/transcript/summarise/index.ts
|
|
18804
19056
|
function buildRelativeKey(relativePath, baseName) {
|
|
18805
19057
|
const relDir = dirname25(relativePath);
|
|
18806
|
-
return relDir === "." ? baseName :
|
|
19058
|
+
return relDir === "." ? baseName : join53(relDir, baseName);
|
|
18807
19059
|
}
|
|
18808
19060
|
function buildSummaryIndex(summaryDir) {
|
|
18809
19061
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -18816,7 +19068,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
18816
19068
|
function summarise2() {
|
|
18817
19069
|
processStagedFile();
|
|
18818
19070
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
18819
|
-
if (!
|
|
19071
|
+
if (!existsSync45(transcriptsDir)) {
|
|
18820
19072
|
console.log("No transcripts directory found.");
|
|
18821
19073
|
return;
|
|
18822
19074
|
}
|
|
@@ -18837,8 +19089,8 @@ function summarise2() {
|
|
|
18837
19089
|
}
|
|
18838
19090
|
const next3 = missing[0];
|
|
18839
19091
|
const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
|
|
18840
|
-
const outputPath =
|
|
18841
|
-
const summaryFileDir =
|
|
19092
|
+
const outputPath = join53(STAGING_DIR, outputFilename);
|
|
19093
|
+
const summaryFileDir = join53(summaryDir, dirname25(next3.relativePath));
|
|
18842
19094
|
const relativeTranscriptPath = encodeURI(
|
|
18843
19095
|
relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
|
|
18844
19096
|
);
|
|
@@ -18895,50 +19147,50 @@ function registerVerify(program2) {
|
|
|
18895
19147
|
|
|
18896
19148
|
// src/commands/voice/devices.ts
|
|
18897
19149
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
18898
|
-
import { join as
|
|
19150
|
+
import { join as join55 } from "path";
|
|
18899
19151
|
|
|
18900
19152
|
// src/commands/voice/shared.ts
|
|
18901
|
-
import { homedir as
|
|
18902
|
-
import { dirname as dirname26, join as
|
|
19153
|
+
import { homedir as homedir16 } from "os";
|
|
19154
|
+
import { dirname as dirname26, join as join54 } from "path";
|
|
18903
19155
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
18904
19156
|
var __dirname5 = dirname26(fileURLToPath6(import.meta.url));
|
|
18905
|
-
var VOICE_DIR =
|
|
19157
|
+
var VOICE_DIR = join54(homedir16(), ".assist", "voice");
|
|
18906
19158
|
var voicePaths = {
|
|
18907
19159
|
dir: VOICE_DIR,
|
|
18908
|
-
pid:
|
|
18909
|
-
log:
|
|
18910
|
-
venv:
|
|
18911
|
-
lock:
|
|
19160
|
+
pid: join54(VOICE_DIR, "voice.pid"),
|
|
19161
|
+
log: join54(VOICE_DIR, "voice.log"),
|
|
19162
|
+
venv: join54(VOICE_DIR, ".venv"),
|
|
19163
|
+
lock: join54(VOICE_DIR, "voice.lock")
|
|
18912
19164
|
};
|
|
18913
19165
|
function getPythonDir() {
|
|
18914
|
-
return
|
|
19166
|
+
return join54(__dirname5, "commands", "voice", "python");
|
|
18915
19167
|
}
|
|
18916
19168
|
function getVenvPython() {
|
|
18917
|
-
return process.platform === "win32" ?
|
|
19169
|
+
return process.platform === "win32" ? join54(voicePaths.venv, "Scripts", "python.exe") : join54(voicePaths.venv, "bin", "python");
|
|
18918
19170
|
}
|
|
18919
19171
|
function getLockDir() {
|
|
18920
19172
|
const config = loadConfig();
|
|
18921
19173
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
18922
19174
|
}
|
|
18923
19175
|
function getLockFile() {
|
|
18924
|
-
return
|
|
19176
|
+
return join54(getLockDir(), "voice.lock");
|
|
18925
19177
|
}
|
|
18926
19178
|
|
|
18927
19179
|
// src/commands/voice/devices.ts
|
|
18928
19180
|
function devices() {
|
|
18929
|
-
const script =
|
|
19181
|
+
const script = join55(getPythonDir(), "list_devices.py");
|
|
18930
19182
|
spawnSync5(getVenvPython(), [script], { stdio: "inherit" });
|
|
18931
19183
|
}
|
|
18932
19184
|
|
|
18933
19185
|
// src/commands/voice/logs.ts
|
|
18934
|
-
import { existsSync as
|
|
19186
|
+
import { existsSync as existsSync46, readFileSync as readFileSync38 } from "fs";
|
|
18935
19187
|
function logs(options2) {
|
|
18936
|
-
if (!
|
|
19188
|
+
if (!existsSync46(voicePaths.log)) {
|
|
18937
19189
|
console.log("No voice log file found");
|
|
18938
19190
|
return;
|
|
18939
19191
|
}
|
|
18940
19192
|
const count6 = Number.parseInt(options2.lines ?? "150", 10);
|
|
18941
|
-
const content =
|
|
19193
|
+
const content = readFileSync38(voicePaths.log, "utf8").trim();
|
|
18942
19194
|
if (!content) {
|
|
18943
19195
|
console.log("Voice log is empty");
|
|
18944
19196
|
return;
|
|
@@ -18960,13 +19212,13 @@ function logs(options2) {
|
|
|
18960
19212
|
|
|
18961
19213
|
// src/commands/voice/setup.ts
|
|
18962
19214
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
18963
|
-
import { mkdirSync as
|
|
18964
|
-
import { join as
|
|
19215
|
+
import { mkdirSync as mkdirSync19 } from "fs";
|
|
19216
|
+
import { join as join57 } from "path";
|
|
18965
19217
|
|
|
18966
19218
|
// src/commands/voice/checkLockFile.ts
|
|
18967
19219
|
import { execSync as execSync48 } from "child_process";
|
|
18968
|
-
import { existsSync as
|
|
18969
|
-
import { join as
|
|
19220
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync18, readFileSync as readFileSync39, writeFileSync as writeFileSync36 } from "fs";
|
|
19221
|
+
import { join as join56 } from "path";
|
|
18970
19222
|
function isProcessAlive2(pid) {
|
|
18971
19223
|
try {
|
|
18972
19224
|
process.kill(pid, 0);
|
|
@@ -18977,9 +19229,9 @@ function isProcessAlive2(pid) {
|
|
|
18977
19229
|
}
|
|
18978
19230
|
function checkLockFile() {
|
|
18979
19231
|
const lockFile = getLockFile();
|
|
18980
|
-
if (!
|
|
19232
|
+
if (!existsSync47(lockFile)) return;
|
|
18981
19233
|
try {
|
|
18982
|
-
const lock2 = JSON.parse(
|
|
19234
|
+
const lock2 = JSON.parse(readFileSync39(lockFile, "utf8"));
|
|
18983
19235
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
18984
19236
|
console.error(
|
|
18985
19237
|
`Voice daemon already running (PID ${lock2.pid}, env: ${lock2.env}). Stop it first with: assist voice stop`
|
|
@@ -18990,7 +19242,7 @@ function checkLockFile() {
|
|
|
18990
19242
|
}
|
|
18991
19243
|
}
|
|
18992
19244
|
function bootstrapVenv() {
|
|
18993
|
-
if (
|
|
19245
|
+
if (existsSync47(getVenvPython())) return;
|
|
18994
19246
|
console.log("Setting up Python environment...");
|
|
18995
19247
|
const pythonDir = getPythonDir();
|
|
18996
19248
|
execSync48(
|
|
@@ -19003,8 +19255,8 @@ function bootstrapVenv() {
|
|
|
19003
19255
|
}
|
|
19004
19256
|
function writeLockFile(pid) {
|
|
19005
19257
|
const lockFile = getLockFile();
|
|
19006
|
-
|
|
19007
|
-
|
|
19258
|
+
mkdirSync18(join56(lockFile, ".."), { recursive: true });
|
|
19259
|
+
writeFileSync36(
|
|
19008
19260
|
lockFile,
|
|
19009
19261
|
JSON.stringify({
|
|
19010
19262
|
pid,
|
|
@@ -19016,10 +19268,10 @@ function writeLockFile(pid) {
|
|
|
19016
19268
|
|
|
19017
19269
|
// src/commands/voice/setup.ts
|
|
19018
19270
|
function setup() {
|
|
19019
|
-
|
|
19271
|
+
mkdirSync19(voicePaths.dir, { recursive: true });
|
|
19020
19272
|
bootstrapVenv();
|
|
19021
19273
|
console.log("\nDownloading models...\n");
|
|
19022
|
-
const script =
|
|
19274
|
+
const script = join57(getPythonDir(), "setup_models.py");
|
|
19023
19275
|
const result = spawnSync6(getVenvPython(), [script], {
|
|
19024
19276
|
stdio: "inherit",
|
|
19025
19277
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -19032,8 +19284,8 @@ function setup() {
|
|
|
19032
19284
|
|
|
19033
19285
|
// src/commands/voice/start.ts
|
|
19034
19286
|
import { spawn as spawn7 } from "child_process";
|
|
19035
|
-
import { mkdirSync as
|
|
19036
|
-
import { join as
|
|
19287
|
+
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync37 } from "fs";
|
|
19288
|
+
import { join as join58 } from "path";
|
|
19037
19289
|
|
|
19038
19290
|
// src/commands/voice/buildDaemonEnv.ts
|
|
19039
19291
|
function buildDaemonEnv(options2) {
|
|
@@ -19061,17 +19313,17 @@ function spawnBackground(python, script, env) {
|
|
|
19061
19313
|
console.error("Failed to start voice daemon");
|
|
19062
19314
|
process.exit(1);
|
|
19063
19315
|
}
|
|
19064
|
-
|
|
19316
|
+
writeFileSync37(voicePaths.pid, String(pid));
|
|
19065
19317
|
writeLockFile(pid);
|
|
19066
19318
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
19067
19319
|
}
|
|
19068
19320
|
function start2(options2) {
|
|
19069
|
-
|
|
19321
|
+
mkdirSync20(voicePaths.dir, { recursive: true });
|
|
19070
19322
|
checkLockFile();
|
|
19071
19323
|
bootstrapVenv();
|
|
19072
19324
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
19073
19325
|
const env = buildDaemonEnv({ debug });
|
|
19074
|
-
const script =
|
|
19326
|
+
const script = join58(getPythonDir(), "voice_daemon.py");
|
|
19075
19327
|
const python = getVenvPython();
|
|
19076
19328
|
if (options2.foreground) {
|
|
19077
19329
|
spawnForeground(python, script, env);
|
|
@@ -19081,7 +19333,7 @@ function start2(options2) {
|
|
|
19081
19333
|
}
|
|
19082
19334
|
|
|
19083
19335
|
// src/commands/voice/status.ts
|
|
19084
|
-
import { existsSync as
|
|
19336
|
+
import { existsSync as existsSync48, readFileSync as readFileSync40 } from "fs";
|
|
19085
19337
|
function isProcessAlive3(pid) {
|
|
19086
19338
|
try {
|
|
19087
19339
|
process.kill(pid, 0);
|
|
@@ -19091,16 +19343,16 @@ function isProcessAlive3(pid) {
|
|
|
19091
19343
|
}
|
|
19092
19344
|
}
|
|
19093
19345
|
function readRecentLogs(count6) {
|
|
19094
|
-
if (!
|
|
19095
|
-
const lines =
|
|
19346
|
+
if (!existsSync48(voicePaths.log)) return [];
|
|
19347
|
+
const lines = readFileSync40(voicePaths.log, "utf8").trim().split("\n");
|
|
19096
19348
|
return lines.slice(-count6);
|
|
19097
19349
|
}
|
|
19098
19350
|
function status() {
|
|
19099
|
-
if (!
|
|
19351
|
+
if (!existsSync48(voicePaths.pid)) {
|
|
19100
19352
|
console.log("Voice daemon: not running (no PID file)");
|
|
19101
19353
|
return;
|
|
19102
19354
|
}
|
|
19103
|
-
const pid = Number.parseInt(
|
|
19355
|
+
const pid = Number.parseInt(readFileSync40(voicePaths.pid, "utf8").trim(), 10);
|
|
19104
19356
|
const alive = isProcessAlive3(pid);
|
|
19105
19357
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
19106
19358
|
const recent = readRecentLogs(5);
|
|
@@ -19119,13 +19371,13 @@ function status() {
|
|
|
19119
19371
|
}
|
|
19120
19372
|
|
|
19121
19373
|
// src/commands/voice/stop.ts
|
|
19122
|
-
import { existsSync as
|
|
19374
|
+
import { existsSync as existsSync49, readFileSync as readFileSync41, unlinkSync as unlinkSync17 } from "fs";
|
|
19123
19375
|
function stop2() {
|
|
19124
|
-
if (!
|
|
19376
|
+
if (!existsSync49(voicePaths.pid)) {
|
|
19125
19377
|
console.log("Voice daemon is not running (no PID file)");
|
|
19126
19378
|
return;
|
|
19127
19379
|
}
|
|
19128
|
-
const pid = Number.parseInt(
|
|
19380
|
+
const pid = Number.parseInt(readFileSync41(voicePaths.pid, "utf8").trim(), 10);
|
|
19129
19381
|
try {
|
|
19130
19382
|
process.kill(pid, "SIGTERM");
|
|
19131
19383
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -19133,12 +19385,12 @@ function stop2() {
|
|
|
19133
19385
|
console.log(`Voice daemon (PID ${pid}) is not running`);
|
|
19134
19386
|
}
|
|
19135
19387
|
try {
|
|
19136
|
-
|
|
19388
|
+
unlinkSync17(voicePaths.pid);
|
|
19137
19389
|
} catch {
|
|
19138
19390
|
}
|
|
19139
19391
|
try {
|
|
19140
19392
|
const lockFile = getLockFile();
|
|
19141
|
-
if (
|
|
19393
|
+
if (existsSync49(lockFile)) unlinkSync17(lockFile);
|
|
19142
19394
|
} catch {
|
|
19143
19395
|
}
|
|
19144
19396
|
console.log("Voice daemon stopped");
|
|
@@ -19156,8 +19408,8 @@ function registerVoice(program2) {
|
|
|
19156
19408
|
}
|
|
19157
19409
|
|
|
19158
19410
|
// src/commands/roam/auth.ts
|
|
19159
|
-
import { randomBytes } from "crypto";
|
|
19160
|
-
import
|
|
19411
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
19412
|
+
import chalk178 from "chalk";
|
|
19161
19413
|
|
|
19162
19414
|
// src/commands/roam/waitForCallback.ts
|
|
19163
19415
|
import { createServer as createServer3 } from "http";
|
|
@@ -19286,15 +19538,15 @@ async function auth() {
|
|
|
19286
19538
|
const existingRoam = config.roam ?? {};
|
|
19287
19539
|
config.roam = { ...existingRoam, clientId, clientSecret };
|
|
19288
19540
|
saveGlobalConfig(config);
|
|
19289
|
-
const state =
|
|
19541
|
+
const state = randomBytes2(16).toString("hex");
|
|
19290
19542
|
console.log(
|
|
19291
|
-
|
|
19543
|
+
chalk178.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
19292
19544
|
);
|
|
19293
|
-
console.log(
|
|
19294
|
-
console.log(
|
|
19295
|
-
console.log(
|
|
19545
|
+
console.log(chalk178.white("http://localhost:14523/callback\n"));
|
|
19546
|
+
console.log(chalk178.blue("Opening browser for authorization..."));
|
|
19547
|
+
console.log(chalk178.dim("Waiting for authorization callback..."));
|
|
19296
19548
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
19297
|
-
console.log(
|
|
19549
|
+
console.log(chalk178.dim("Exchanging code for tokens..."));
|
|
19298
19550
|
const tokens = await exchangeToken({
|
|
19299
19551
|
code,
|
|
19300
19552
|
clientId,
|
|
@@ -19310,25 +19562,25 @@ async function auth() {
|
|
|
19310
19562
|
};
|
|
19311
19563
|
saveGlobalConfig(config);
|
|
19312
19564
|
console.log(
|
|
19313
|
-
|
|
19565
|
+
chalk178.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
19314
19566
|
);
|
|
19315
19567
|
}
|
|
19316
19568
|
|
|
19317
19569
|
// src/commands/roam/postRoamActivity.ts
|
|
19318
19570
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
19319
|
-
import { readdirSync as
|
|
19320
|
-
import { join as
|
|
19571
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync42, statSync as statSync7 } from "fs";
|
|
19572
|
+
import { join as join59 } from "path";
|
|
19321
19573
|
function findPortFile(roamDir) {
|
|
19322
19574
|
let entries;
|
|
19323
19575
|
try {
|
|
19324
|
-
entries =
|
|
19576
|
+
entries = readdirSync9(roamDir);
|
|
19325
19577
|
} catch {
|
|
19326
19578
|
return void 0;
|
|
19327
19579
|
}
|
|
19328
19580
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
19329
|
-
const path57 =
|
|
19581
|
+
const path57 = join59(roamDir, name);
|
|
19330
19582
|
try {
|
|
19331
|
-
return { path: path57, mtimeMs:
|
|
19583
|
+
return { path: path57, mtimeMs: statSync7(path57).mtimeMs };
|
|
19332
19584
|
} catch {
|
|
19333
19585
|
return void 0;
|
|
19334
19586
|
}
|
|
@@ -19338,11 +19590,11 @@ function findPortFile(roamDir) {
|
|
|
19338
19590
|
function postRoamActivity(app, event) {
|
|
19339
19591
|
const appData = process.env.APPDATA;
|
|
19340
19592
|
if (!appData) return;
|
|
19341
|
-
const portFile = findPortFile(
|
|
19593
|
+
const portFile = findPortFile(join59(appData, "Roam"));
|
|
19342
19594
|
if (!portFile) return;
|
|
19343
19595
|
let port;
|
|
19344
19596
|
try {
|
|
19345
|
-
port =
|
|
19597
|
+
port = readFileSync42(portFile, "utf8").trim();
|
|
19346
19598
|
} catch {
|
|
19347
19599
|
return;
|
|
19348
19600
|
}
|
|
@@ -19484,15 +19736,15 @@ function runPreCommands(pre, cwd) {
|
|
|
19484
19736
|
|
|
19485
19737
|
// src/commands/run/spawnRunCommand.ts
|
|
19486
19738
|
import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
|
|
19487
|
-
import { existsSync as
|
|
19488
|
-
import { dirname as dirname27, join as
|
|
19739
|
+
import { existsSync as existsSync50 } from "fs";
|
|
19740
|
+
import { dirname as dirname27, join as join60, resolve as resolve13 } from "path";
|
|
19489
19741
|
function resolveCommand2(command) {
|
|
19490
19742
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
19491
19743
|
try {
|
|
19492
19744
|
const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
19493
19745
|
const gitRoot = resolve13(dirname27(gitPath), "..");
|
|
19494
|
-
const gitBash =
|
|
19495
|
-
if (
|
|
19746
|
+
const gitBash = join60(gitRoot, "bin", "bash.exe");
|
|
19747
|
+
if (existsSync50(gitBash)) return gitBash;
|
|
19496
19748
|
} catch {
|
|
19497
19749
|
}
|
|
19498
19750
|
return command;
|
|
@@ -19577,8 +19829,8 @@ async function run3(name, args) {
|
|
|
19577
19829
|
}
|
|
19578
19830
|
|
|
19579
19831
|
// src/commands/run/add.ts
|
|
19580
|
-
import { mkdirSync as
|
|
19581
|
-
import { join as
|
|
19832
|
+
import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync38 } from "fs";
|
|
19833
|
+
import { join as join61 } from "path";
|
|
19582
19834
|
|
|
19583
19835
|
// src/commands/run/extractOption.ts
|
|
19584
19836
|
function extractOption(args, flag) {
|
|
@@ -19639,16 +19891,16 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
19639
19891
|
saveConfig(config);
|
|
19640
19892
|
}
|
|
19641
19893
|
function createCommandFile(name) {
|
|
19642
|
-
const dir =
|
|
19643
|
-
|
|
19894
|
+
const dir = join61(".claude", "commands");
|
|
19895
|
+
mkdirSync21(dir, { recursive: true });
|
|
19644
19896
|
const content = `---
|
|
19645
19897
|
description: Run ${name}
|
|
19646
19898
|
---
|
|
19647
19899
|
|
|
19648
19900
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
19649
19901
|
`;
|
|
19650
|
-
const filePath =
|
|
19651
|
-
|
|
19902
|
+
const filePath = join61(dir, `${name}.md`);
|
|
19903
|
+
writeFileSync38(filePath, content);
|
|
19652
19904
|
console.log(`Created command file: ${filePath}`);
|
|
19653
19905
|
}
|
|
19654
19906
|
function add3() {
|
|
@@ -19703,8 +19955,8 @@ function link2() {
|
|
|
19703
19955
|
}
|
|
19704
19956
|
|
|
19705
19957
|
// src/commands/run/remove.ts
|
|
19706
|
-
import { existsSync as
|
|
19707
|
-
import { join as
|
|
19958
|
+
import { existsSync as existsSync51, unlinkSync as unlinkSync18 } from "fs";
|
|
19959
|
+
import { join as join62 } from "path";
|
|
19708
19960
|
function findRemoveIndex() {
|
|
19709
19961
|
const idx = process.argv.indexOf("remove");
|
|
19710
19962
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -19719,9 +19971,9 @@ function parseRemoveName() {
|
|
|
19719
19971
|
return process.argv[idx + 1];
|
|
19720
19972
|
}
|
|
19721
19973
|
function deleteCommandFile(name) {
|
|
19722
|
-
const filePath =
|
|
19723
|
-
if (
|
|
19724
|
-
|
|
19974
|
+
const filePath = join62(".claude", "commands", `${name}.md`);
|
|
19975
|
+
if (existsSync51(filePath)) {
|
|
19976
|
+
unlinkSync18(filePath);
|
|
19725
19977
|
console.log(`Deleted command file: ${filePath}`);
|
|
19726
19978
|
}
|
|
19727
19979
|
}
|
|
@@ -19759,10 +20011,10 @@ function registerRun(program2) {
|
|
|
19759
20011
|
|
|
19760
20012
|
// src/commands/screenshot/index.ts
|
|
19761
20013
|
import { execSync as execSync50 } from "child_process";
|
|
19762
|
-
import { existsSync as
|
|
20014
|
+
import { existsSync as existsSync52, mkdirSync as mkdirSync22, unlinkSync as unlinkSync19, writeFileSync as writeFileSync39 } from "fs";
|
|
19763
20015
|
import { tmpdir as tmpdir7 } from "os";
|
|
19764
|
-
import { join as
|
|
19765
|
-
import
|
|
20016
|
+
import { join as join63, resolve as resolve15 } from "path";
|
|
20017
|
+
import chalk179 from "chalk";
|
|
19766
20018
|
|
|
19767
20019
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
19768
20020
|
var captureWindowPs1 = `
|
|
@@ -19891,35 +20143,35 @@ Write-Output $OutputPath
|
|
|
19891
20143
|
|
|
19892
20144
|
// src/commands/screenshot/index.ts
|
|
19893
20145
|
function buildOutputPath(outputDir, processName) {
|
|
19894
|
-
if (!
|
|
19895
|
-
|
|
20146
|
+
if (!existsSync52(outputDir)) {
|
|
20147
|
+
mkdirSync22(outputDir, { recursive: true });
|
|
19896
20148
|
}
|
|
19897
20149
|
const timestamp4 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
19898
20150
|
return resolve15(outputDir, `${processName}-${timestamp4}.png`);
|
|
19899
20151
|
}
|
|
19900
20152
|
function runPowerShellScript(processName, outputPath) {
|
|
19901
|
-
const scriptPath =
|
|
19902
|
-
|
|
20153
|
+
const scriptPath = join63(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
20154
|
+
writeFileSync39(scriptPath, captureWindowPs1, "utf8");
|
|
19903
20155
|
try {
|
|
19904
20156
|
execSync50(
|
|
19905
20157
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
19906
20158
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
|
|
19907
20159
|
);
|
|
19908
20160
|
} finally {
|
|
19909
|
-
|
|
20161
|
+
unlinkSync19(scriptPath);
|
|
19910
20162
|
}
|
|
19911
20163
|
}
|
|
19912
20164
|
function screenshot(processName) {
|
|
19913
20165
|
const config = loadConfig();
|
|
19914
20166
|
const outputDir = resolve15(config.screenshot.outputDir);
|
|
19915
20167
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
19916
|
-
console.log(
|
|
20168
|
+
console.log(chalk179.gray(`Capturing window for process "${processName}" ...`));
|
|
19917
20169
|
try {
|
|
19918
20170
|
runPowerShellScript(processName, outputPath);
|
|
19919
|
-
console.log(
|
|
20171
|
+
console.log(chalk179.green(`Screenshot saved: ${outputPath}`));
|
|
19920
20172
|
} catch (error) {
|
|
19921
20173
|
const msg = error instanceof Error ? error.message : String(error);
|
|
19922
|
-
console.error(
|
|
20174
|
+
console.error(chalk179.red(`Failed to capture screenshot: ${msg}`));
|
|
19923
20175
|
process.exit(1);
|
|
19924
20176
|
}
|
|
19925
20177
|
}
|
|
@@ -19975,7 +20227,7 @@ function applyLine(result, pending, line) {
|
|
|
19975
20227
|
}
|
|
19976
20228
|
|
|
19977
20229
|
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
19978
|
-
import { readFileSync as
|
|
20230
|
+
import { readFileSync as readFileSync43 } from "fs";
|
|
19979
20231
|
function reportStolenSocket(socketPid) {
|
|
19980
20232
|
if (!socketPid) return;
|
|
19981
20233
|
const filePid = readPidFile();
|
|
@@ -19987,7 +20239,7 @@ function reportStolenSocket(socketPid) {
|
|
|
19987
20239
|
function readPidFile() {
|
|
19988
20240
|
try {
|
|
19989
20241
|
const pid = Number.parseInt(
|
|
19990
|
-
|
|
20242
|
+
readFileSync43(daemonPaths.pid, "utf8").trim(),
|
|
19991
20243
|
10
|
|
19992
20244
|
);
|
|
19993
20245
|
return Number.isInteger(pid) ? pid : void 0;
|
|
@@ -20152,7 +20404,7 @@ function requestDrain(socket) {
|
|
|
20152
20404
|
}
|
|
20153
20405
|
|
|
20154
20406
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
20155
|
-
import { mkdirSync as
|
|
20407
|
+
import { mkdirSync as mkdirSync24 } from "fs";
|
|
20156
20408
|
|
|
20157
20409
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
20158
20410
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -20329,7 +20581,7 @@ var ClientHub = class extends Set {
|
|
|
20329
20581
|
import * as pty from "node-pty";
|
|
20330
20582
|
|
|
20331
20583
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
20332
|
-
import { chmodSync, existsSync as
|
|
20584
|
+
import { chmodSync, existsSync as existsSync53, statSync as statSync8 } from "fs";
|
|
20333
20585
|
import { createRequire as createRequire3 } from "module";
|
|
20334
20586
|
import path49 from "path";
|
|
20335
20587
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -20344,8 +20596,8 @@ function ensureSpawnHelperExecutable() {
|
|
|
20344
20596
|
`${process.platform}-${process.arch}`,
|
|
20345
20597
|
"spawn-helper"
|
|
20346
20598
|
);
|
|
20347
|
-
if (!
|
|
20348
|
-
const mode =
|
|
20599
|
+
if (!existsSync53(helper)) return;
|
|
20600
|
+
const mode = statSync8(helper).mode;
|
|
20349
20601
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
20350
20602
|
}
|
|
20351
20603
|
|
|
@@ -20763,7 +21015,7 @@ function resumeSession(id2, sessionId, cwd, name) {
|
|
|
20763
21015
|
}
|
|
20764
21016
|
|
|
20765
21017
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
20766
|
-
import { existsSync as
|
|
21018
|
+
import { existsSync as existsSync54, mkdirSync as mkdirSync23, watch } from "fs";
|
|
20767
21019
|
import { dirname as dirname28 } from "path";
|
|
20768
21020
|
|
|
20769
21021
|
// src/commands/sessions/daemon/applyReviewPause.ts
|
|
@@ -20784,7 +21036,7 @@ function watchActivity(session, notify2) {
|
|
|
20784
21036
|
const path57 = activityPath(session.id);
|
|
20785
21037
|
const dir = dirname28(path57);
|
|
20786
21038
|
try {
|
|
20787
|
-
|
|
21039
|
+
mkdirSync23(dir, { recursive: true });
|
|
20788
21040
|
} catch {
|
|
20789
21041
|
return;
|
|
20790
21042
|
}
|
|
@@ -20805,7 +21057,7 @@ function watchActivity(session, notify2) {
|
|
|
20805
21057
|
if (timer) clearTimeout(timer);
|
|
20806
21058
|
timer = setTimeout(read, DEBOUNCE_MS);
|
|
20807
21059
|
});
|
|
20808
|
-
if (
|
|
21060
|
+
if (existsSync54(path57)) read();
|
|
20809
21061
|
}
|
|
20810
21062
|
function refreshActivity(session) {
|
|
20811
21063
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -21614,7 +21866,7 @@ var SessionManager = class {
|
|
|
21614
21866
|
};
|
|
21615
21867
|
|
|
21616
21868
|
// src/commands/sessions/daemon/startDaemonServer.ts
|
|
21617
|
-
import { unlinkSync as
|
|
21869
|
+
import { unlinkSync as unlinkSync21 } from "fs";
|
|
21618
21870
|
import * as net3 from "net";
|
|
21619
21871
|
|
|
21620
21872
|
// src/commands/sessions/daemon/handleConnection.ts
|
|
@@ -22021,10 +22273,10 @@ function handleConnection(socket, manager) {
|
|
|
22021
22273
|
}
|
|
22022
22274
|
|
|
22023
22275
|
// src/commands/sessions/daemon/onListening.ts
|
|
22024
|
-
import { unlinkSync as
|
|
22276
|
+
import { unlinkSync as unlinkSync20, writeFileSync as writeFileSync40 } from "fs";
|
|
22025
22277
|
|
|
22026
22278
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
22027
|
-
import { readFileSync as
|
|
22279
|
+
import { readFileSync as readFileSync44 } from "fs";
|
|
22028
22280
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
22029
22281
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
22030
22282
|
const timer = setInterval(() => {
|
|
@@ -22035,7 +22287,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
22035
22287
|
}
|
|
22036
22288
|
function ownsPidFile() {
|
|
22037
22289
|
try {
|
|
22038
|
-
return
|
|
22290
|
+
return readFileSync44(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
22039
22291
|
} catch {
|
|
22040
22292
|
return false;
|
|
22041
22293
|
}
|
|
@@ -22043,7 +22295,7 @@ function ownsPidFile() {
|
|
|
22043
22295
|
|
|
22044
22296
|
// src/commands/sessions/daemon/onListening.ts
|
|
22045
22297
|
function onListening(manager, checkAutoExit) {
|
|
22046
|
-
|
|
22298
|
+
writeFileSync40(daemonPaths.pid, String(process.pid));
|
|
22047
22299
|
startPidFileWatchdog(() => {
|
|
22048
22300
|
daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
|
|
22049
22301
|
manager.shutdown();
|
|
@@ -22062,12 +22314,12 @@ function onListening(manager, checkAutoExit) {
|
|
|
22062
22314
|
function cleanupOwnedFiles() {
|
|
22063
22315
|
if (!ownsPidFile()) return;
|
|
22064
22316
|
try {
|
|
22065
|
-
|
|
22317
|
+
unlinkSync20(daemonPaths.pid);
|
|
22066
22318
|
} catch {
|
|
22067
22319
|
}
|
|
22068
22320
|
if (process.platform !== "win32") {
|
|
22069
22321
|
try {
|
|
22070
|
-
|
|
22322
|
+
unlinkSync20(daemonPaths.socket);
|
|
22071
22323
|
} catch {
|
|
22072
22324
|
}
|
|
22073
22325
|
}
|
|
@@ -22110,7 +22362,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
22110
22362
|
daemonLog("removing stale socket left by a crashed daemon");
|
|
22111
22363
|
if (process.platform !== "win32") {
|
|
22112
22364
|
try {
|
|
22113
|
-
|
|
22365
|
+
unlinkSync21(daemonPaths.socket);
|
|
22114
22366
|
} catch {
|
|
22115
22367
|
}
|
|
22116
22368
|
}
|
|
@@ -22119,7 +22371,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
22119
22371
|
|
|
22120
22372
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
22121
22373
|
async function runDaemon() {
|
|
22122
|
-
|
|
22374
|
+
mkdirSync24(daemonPaths.dir, { recursive: true });
|
|
22123
22375
|
daemonLog(
|
|
22124
22376
|
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
22125
22377
|
);
|
|
@@ -22159,7 +22411,7 @@ function registerDaemon(program2) {
|
|
|
22159
22411
|
|
|
22160
22412
|
// src/commands/sessions/summarise/index.ts
|
|
22161
22413
|
import * as fs35 from "fs";
|
|
22162
|
-
import
|
|
22414
|
+
import chalk180 from "chalk";
|
|
22163
22415
|
|
|
22164
22416
|
// src/commands/sessions/summarise/shared.ts
|
|
22165
22417
|
import * as fs33 from "fs";
|
|
@@ -22313,22 +22565,22 @@ ${firstMessage}`);
|
|
|
22313
22565
|
async function summarise3(options2) {
|
|
22314
22566
|
const files = await discoverSessionFiles();
|
|
22315
22567
|
if (files.length === 0) {
|
|
22316
|
-
console.log(
|
|
22568
|
+
console.log(chalk180.yellow("No sessions found."));
|
|
22317
22569
|
return;
|
|
22318
22570
|
}
|
|
22319
22571
|
const toProcess = selectCandidates(files, options2);
|
|
22320
22572
|
if (toProcess.length === 0) {
|
|
22321
|
-
console.log(
|
|
22573
|
+
console.log(chalk180.green("All sessions already summarised."));
|
|
22322
22574
|
return;
|
|
22323
22575
|
}
|
|
22324
22576
|
console.log(
|
|
22325
|
-
|
|
22577
|
+
chalk180.cyan(
|
|
22326
22578
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
22327
22579
|
)
|
|
22328
22580
|
);
|
|
22329
22581
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
22330
22582
|
console.log(
|
|
22331
|
-
|
|
22583
|
+
chalk180.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk180.yellow(`, ${failed2} skipped`) : "")
|
|
22332
22584
|
);
|
|
22333
22585
|
}
|
|
22334
22586
|
function selectCandidates(files, options2) {
|
|
@@ -22348,16 +22600,16 @@ function processSessions(files) {
|
|
|
22348
22600
|
let failed2 = 0;
|
|
22349
22601
|
for (let i = 0; i < files.length; i++) {
|
|
22350
22602
|
const file = files[i];
|
|
22351
|
-
process.stdout.write(
|
|
22603
|
+
process.stdout.write(chalk180.dim(` [${i + 1}/${files.length}] `));
|
|
22352
22604
|
const summary = summariseSession(file);
|
|
22353
22605
|
if (summary) {
|
|
22354
22606
|
writeSummary(file, summary);
|
|
22355
22607
|
succeeded++;
|
|
22356
|
-
process.stdout.write(`${
|
|
22608
|
+
process.stdout.write(`${chalk180.green("\u2713")} ${summary}
|
|
22357
22609
|
`);
|
|
22358
22610
|
} else {
|
|
22359
22611
|
failed2++;
|
|
22360
|
-
process.stdout.write(` ${
|
|
22612
|
+
process.stdout.write(` ${chalk180.yellow("skip")}
|
|
22361
22613
|
`);
|
|
22362
22614
|
}
|
|
22363
22615
|
}
|
|
@@ -22375,10 +22627,10 @@ function registerSessions(program2) {
|
|
|
22375
22627
|
}
|
|
22376
22628
|
|
|
22377
22629
|
// src/commands/statusLine.ts
|
|
22378
|
-
import
|
|
22630
|
+
import chalk182 from "chalk";
|
|
22379
22631
|
|
|
22380
22632
|
// src/commands/buildLimitsSegment.ts
|
|
22381
|
-
import
|
|
22633
|
+
import chalk181 from "chalk";
|
|
22382
22634
|
|
|
22383
22635
|
// src/shared/rateLimitLevel.ts
|
|
22384
22636
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -22409,9 +22661,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
22409
22661
|
|
|
22410
22662
|
// src/commands/buildLimitsSegment.ts
|
|
22411
22663
|
var LEVEL_COLOR = {
|
|
22412
|
-
ok:
|
|
22413
|
-
warn:
|
|
22414
|
-
over:
|
|
22664
|
+
ok: chalk181.green,
|
|
22665
|
+
warn: chalk181.yellow,
|
|
22666
|
+
over: chalk181.red
|
|
22415
22667
|
};
|
|
22416
22668
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
22417
22669
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -22451,14 +22703,14 @@ async function relayRateLimits(rateLimits) {
|
|
|
22451
22703
|
}
|
|
22452
22704
|
|
|
22453
22705
|
// src/commands/statusLine.ts
|
|
22454
|
-
|
|
22706
|
+
chalk182.level = 3;
|
|
22455
22707
|
function formatNumber(num) {
|
|
22456
22708
|
return num.toLocaleString("en-US");
|
|
22457
22709
|
}
|
|
22458
22710
|
function colorizePercent(pct) {
|
|
22459
22711
|
const label2 = `${Math.round(pct)}%`;
|
|
22460
|
-
if (pct > 80) return
|
|
22461
|
-
if (pct > 40) return
|
|
22712
|
+
if (pct > 80) return chalk182.red(label2);
|
|
22713
|
+
if (pct > 40) return chalk182.yellow(label2);
|
|
22462
22714
|
return label2;
|
|
22463
22715
|
}
|
|
22464
22716
|
async function statusLine() {
|
|
@@ -22482,7 +22734,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
22482
22734
|
// src/commands/sync/syncClaudeMd.ts
|
|
22483
22735
|
import * as fs36 from "fs";
|
|
22484
22736
|
import * as path53 from "path";
|
|
22485
|
-
import
|
|
22737
|
+
import chalk183 from "chalk";
|
|
22486
22738
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
22487
22739
|
const source = path53.join(claudeDir, "CLAUDE.md");
|
|
22488
22740
|
const target = path53.join(targetBase, "CLAUDE.md");
|
|
@@ -22491,12 +22743,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
22491
22743
|
const targetContent = fs36.readFileSync(target, "utf8");
|
|
22492
22744
|
if (sourceContent !== targetContent) {
|
|
22493
22745
|
console.log(
|
|
22494
|
-
|
|
22746
|
+
chalk183.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
22495
22747
|
);
|
|
22496
22748
|
console.log();
|
|
22497
22749
|
printDiff(targetContent, sourceContent);
|
|
22498
22750
|
const confirm = options2?.yes || await promptConfirm(
|
|
22499
|
-
|
|
22751
|
+
chalk183.red("Overwrite existing CLAUDE.md?"),
|
|
22500
22752
|
false
|
|
22501
22753
|
);
|
|
22502
22754
|
if (!confirm) {
|
|
@@ -22512,7 +22764,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
22512
22764
|
// src/commands/sync/syncSettings.ts
|
|
22513
22765
|
import * as fs37 from "fs";
|
|
22514
22766
|
import * as path54 from "path";
|
|
22515
|
-
import
|
|
22767
|
+
import chalk184 from "chalk";
|
|
22516
22768
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
22517
22769
|
const source = path54.join(claudeDir, "settings.json");
|
|
22518
22770
|
const target = path54.join(targetBase, "settings.json");
|
|
@@ -22528,14 +22780,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
22528
22780
|
if (mergedContent !== normalizedTarget) {
|
|
22529
22781
|
if (!options2?.yes) {
|
|
22530
22782
|
console.log(
|
|
22531
|
-
|
|
22783
|
+
chalk184.yellow(
|
|
22532
22784
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
22533
22785
|
)
|
|
22534
22786
|
);
|
|
22535
22787
|
console.log();
|
|
22536
22788
|
printDiff(targetContent, mergedContent);
|
|
22537
22789
|
const confirm = await promptConfirm(
|
|
22538
|
-
|
|
22790
|
+
chalk184.red("Overwrite existing settings.json?"),
|
|
22539
22791
|
false
|
|
22540
22792
|
);
|
|
22541
22793
|
if (!confirm) {
|
|
@@ -22653,6 +22905,7 @@ program.command("screenshot").description("Capture a screenshot of a running app
|
|
|
22653
22905
|
registerActivity(program);
|
|
22654
22906
|
registerBackup(program);
|
|
22655
22907
|
registerCliHook(program);
|
|
22908
|
+
registerCodeComment(program);
|
|
22656
22909
|
registerEditHook(program);
|
|
22657
22910
|
registerGithub(program);
|
|
22658
22911
|
registerHandover(program);
|