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