@staff0rd/assist 0.239.1 → 0.241.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 +7 -2
- package/dist/index.js +506 -367
- 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.241.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -8207,8 +8207,8 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
8207
8207
|
(file) => ignorePaths.some((ignorePath) => file.startsWith(ignorePath))
|
|
8208
8208
|
);
|
|
8209
8209
|
}
|
|
8210
|
-
function printCommitsWithFiles(
|
|
8211
|
-
for (const commit2 of
|
|
8210
|
+
function printCommitsWithFiles(commits2, ignore2, verbose) {
|
|
8211
|
+
for (const commit2 of commits2) {
|
|
8212
8212
|
console.log(` ${chalk88.yellow(commit2.hash)} ${commit2.message}`);
|
|
8213
8213
|
if (verbose) {
|
|
8214
8214
|
const visibleFiles = commit2.files.filter(
|
|
@@ -8419,11 +8419,11 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
8419
8419
|
function logName(repoName) {
|
|
8420
8420
|
console.log(`${chalk91.bold("name:")} ${repoName}`);
|
|
8421
8421
|
}
|
|
8422
|
-
function displayNextEntry(ctx, targetDate,
|
|
8422
|
+
function displayNextEntry(ctx, targetDate, commits2) {
|
|
8423
8423
|
logName(ctx.repoName);
|
|
8424
|
-
printVersionInfo(ctx.config, ctx.lastInfo,
|
|
8424
|
+
printVersionInfo(ctx.config, ctx.lastInfo, commits2[0]?.hash);
|
|
8425
8425
|
console.log(chalk91.bold.blue(targetDate));
|
|
8426
|
-
printCommitsWithFiles(
|
|
8426
|
+
printCommitsWithFiles(commits2, ctx.ignore, ctx.verbose);
|
|
8427
8427
|
}
|
|
8428
8428
|
function logNoCommits(lastInfo) {
|
|
8429
8429
|
console.log(chalk91.dim(noCommitsMessage(!!lastInfo)));
|
|
@@ -9231,9 +9231,211 @@ function registerDotnet(program2) {
|
|
|
9231
9231
|
cmd.command("in-sln").description("Check whether a .csproj is referenced by any .sln file").argument("<csproj>", "Path to a .csproj file").action(inSln);
|
|
9232
9232
|
}
|
|
9233
9233
|
|
|
9234
|
+
// src/commands/github/aggregateCommitters.ts
|
|
9235
|
+
function aggregateCommitters(authorLists) {
|
|
9236
|
+
const totals = /* @__PURE__ */ new Map();
|
|
9237
|
+
for (const authors of authorLists) {
|
|
9238
|
+
for (const { author, commitCount } of authors) {
|
|
9239
|
+
totals.set(author, (totals.get(author) ?? 0) + commitCount);
|
|
9240
|
+
}
|
|
9241
|
+
}
|
|
9242
|
+
return [...totals].map(([author, commitCount]) => ({ author, commitCount })).sort((a, b) => b.commitCount - a.commitCount);
|
|
9243
|
+
}
|
|
9244
|
+
|
|
9245
|
+
// src/shared/runGhGraphql.ts
|
|
9246
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
9247
|
+
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync18 } from "fs";
|
|
9248
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
9249
|
+
import { join as join27 } from "path";
|
|
9250
|
+
function buildArgs2(queryFile, vars) {
|
|
9251
|
+
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
9252
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
9253
|
+
const flag = typeof value === "number" ? "-F" : "-f";
|
|
9254
|
+
args.push(flag, `${key}=${value}`);
|
|
9255
|
+
}
|
|
9256
|
+
return args;
|
|
9257
|
+
}
|
|
9258
|
+
function runGhGraphql(mutation, vars) {
|
|
9259
|
+
const queryFile = join27(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
9260
|
+
writeFileSync18(queryFile, mutation);
|
|
9261
|
+
try {
|
|
9262
|
+
const result = spawnSync2("gh", buildArgs2(queryFile, vars), {
|
|
9263
|
+
encoding: "utf-8"
|
|
9264
|
+
});
|
|
9265
|
+
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
9266
|
+
return result.stdout;
|
|
9267
|
+
} finally {
|
|
9268
|
+
unlinkSync6(queryFile);
|
|
9269
|
+
}
|
|
9270
|
+
}
|
|
9271
|
+
|
|
9272
|
+
// src/commands/github/fetchOrgRepoCommitCounts.ts
|
|
9273
|
+
var REPOS_QUERY = `query($org: String!, $since: GitTimestamp!, $cursor: String) { organization(login: $org) { repositories(first: 50, orderBy: { field: PUSHED_AT, direction: DESC }, after: $cursor) { pageInfo { hasNextPage endCursor } nodes { name pushedAt defaultBranchRef { target { ... on Commit { history(since: $since) { totalCount } } } } } } } }`;
|
|
9274
|
+
function fetchOrgRepoCommitCounts(org, since) {
|
|
9275
|
+
const results = [];
|
|
9276
|
+
let cursor;
|
|
9277
|
+
for (; ; ) {
|
|
9278
|
+
const vars = { org, since };
|
|
9279
|
+
if (cursor) vars.cursor = cursor;
|
|
9280
|
+
const response = JSON.parse(
|
|
9281
|
+
runGhGraphql(REPOS_QUERY, vars)
|
|
9282
|
+
);
|
|
9283
|
+
const repositories = response.data.organization?.repositories;
|
|
9284
|
+
if (!repositories) throw new Error(`Organisation not found: ${org}`);
|
|
9285
|
+
for (const node of repositories.nodes) {
|
|
9286
|
+
const history = node.defaultBranchRef?.target?.history;
|
|
9287
|
+
if (!history) continue;
|
|
9288
|
+
results.push({ name: node.name, commitCount: history.totalCount });
|
|
9289
|
+
}
|
|
9290
|
+
const lastNode = repositories.nodes[repositories.nodes.length - 1];
|
|
9291
|
+
const exhausted = lastNode && new Date(lastNode.pushedAt) < new Date(since);
|
|
9292
|
+
if (!repositories.pageInfo.hasNextPage || exhausted) break;
|
|
9293
|
+
cursor = repositories.pageInfo.endCursor ?? void 0;
|
|
9294
|
+
}
|
|
9295
|
+
return results;
|
|
9296
|
+
}
|
|
9297
|
+
|
|
9298
|
+
// src/commands/github/fetchRepoCommitAuthors.ts
|
|
9299
|
+
var HISTORY_QUERY = `query($org: String!, $repo: String!, $since: GitTimestamp!, $cursor: String) { repository(owner: $org, name: $repo) { defaultBranchRef { target { ... on Commit { history(since: $since, first: 100, after: $cursor) { pageInfo { hasNextPage endCursor } nodes { author { user { login } name } } } } } } } }`;
|
|
9300
|
+
function fetchRepoCommitAuthors(org, repo, since) {
|
|
9301
|
+
const counts = /* @__PURE__ */ new Map();
|
|
9302
|
+
let cursor;
|
|
9303
|
+
for (; ; ) {
|
|
9304
|
+
const vars = { org, repo, since };
|
|
9305
|
+
if (cursor) vars.cursor = cursor;
|
|
9306
|
+
const response = JSON.parse(
|
|
9307
|
+
runGhGraphql(HISTORY_QUERY, vars)
|
|
9308
|
+
);
|
|
9309
|
+
const history = response.data.repository?.defaultBranchRef?.target?.history;
|
|
9310
|
+
if (!history) break;
|
|
9311
|
+
for (const node of history.nodes) {
|
|
9312
|
+
const author = node.author?.user?.login ?? node.author?.name ?? "unknown";
|
|
9313
|
+
counts.set(author, (counts.get(author) ?? 0) + 1);
|
|
9314
|
+
}
|
|
9315
|
+
if (!history.pageInfo.hasNextPage) break;
|
|
9316
|
+
cursor = history.pageInfo.endCursor ?? void 0;
|
|
9317
|
+
}
|
|
9318
|
+
return [...counts].map(([author, commitCount]) => ({ author, commitCount })).sort((a, b) => b.commitCount - a.commitCount);
|
|
9319
|
+
}
|
|
9320
|
+
|
|
9321
|
+
// src/commands/github/printCountTable.ts
|
|
9322
|
+
import chalk105 from "chalk";
|
|
9323
|
+
function printCountTable(labelHeader, rows) {
|
|
9324
|
+
const labelWidth = Math.max(
|
|
9325
|
+
labelHeader.length,
|
|
9326
|
+
...rows.map((row) => row.label.length)
|
|
9327
|
+
);
|
|
9328
|
+
const header = `${labelHeader.padEnd(labelWidth)} Commits`;
|
|
9329
|
+
console.log(chalk105.dim(header));
|
|
9330
|
+
console.log(chalk105.dim("-".repeat(header.length)));
|
|
9331
|
+
for (const row of rows) {
|
|
9332
|
+
console.log(`${row.label.padEnd(labelWidth)} ${row.count}`);
|
|
9333
|
+
}
|
|
9334
|
+
}
|
|
9335
|
+
|
|
9336
|
+
// src/commands/github/printRepoAuthorBreakdown.ts
|
|
9337
|
+
import chalk106 from "chalk";
|
|
9338
|
+
function printRepoAuthorBreakdown(repos2) {
|
|
9339
|
+
for (const repo of repos2) {
|
|
9340
|
+
console.log(chalk106.bold(repo.name));
|
|
9341
|
+
const authorWidth = Math.max(
|
|
9342
|
+
0,
|
|
9343
|
+
...repo.authors.map((a) => a.author.length)
|
|
9344
|
+
);
|
|
9345
|
+
for (const { author, commitCount } of repo.authors) {
|
|
9346
|
+
console.log(` ${author.padEnd(authorWidth)} ${commitCount}`);
|
|
9347
|
+
}
|
|
9348
|
+
console.log();
|
|
9349
|
+
}
|
|
9350
|
+
}
|
|
9351
|
+
|
|
9352
|
+
// src/commands/github/printCommitsReport.ts
|
|
9353
|
+
function printCommitsReport(report) {
|
|
9354
|
+
const { org, since, totalRepos, repos: repos2, committers, repoAuthors } = report;
|
|
9355
|
+
const scope = repos2.length < totalRepos ? ` (top ${repos2.length} of ${totalRepos} repos)` : "";
|
|
9356
|
+
console.log(`Top repos by commits in ${org} since ${since}${scope}:
|
|
9357
|
+
`);
|
|
9358
|
+
printCountTable(
|
|
9359
|
+
"Repo",
|
|
9360
|
+
repos2.map((r) => ({ label: r.name, count: r.commitCount }))
|
|
9361
|
+
);
|
|
9362
|
+
console.log(`
|
|
9363
|
+
Top committers in ${org} since ${since}${scope}:
|
|
9364
|
+
`);
|
|
9365
|
+
printCountTable(
|
|
9366
|
+
"Committer",
|
|
9367
|
+
committers.map((c) => ({ label: c.author, count: c.commitCount }))
|
|
9368
|
+
);
|
|
9369
|
+
console.log("\nCommits by author per repo:\n");
|
|
9370
|
+
printRepoAuthorBreakdown(repoAuthors);
|
|
9371
|
+
}
|
|
9372
|
+
|
|
9373
|
+
// src/commands/github/commits.ts
|
|
9374
|
+
function commits(org, options2) {
|
|
9375
|
+
const since = options2.since ? `${options2.since}T00:00:00Z` : new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString();
|
|
9376
|
+
const sinceDate = since.slice(0, 10);
|
|
9377
|
+
const allRepos = fetchOrgRepoCommitCounts(org, since).filter((repo) => repo.commitCount > 0).sort((a, b) => b.commitCount - a.commitCount);
|
|
9378
|
+
const repos2 = options2.top ? allRepos.slice(0, options2.top) : allRepos;
|
|
9379
|
+
const repoAuthors = repos2.map((repo) => ({
|
|
9380
|
+
name: repo.name,
|
|
9381
|
+
authors: fetchRepoCommitAuthors(org, repo.name, since)
|
|
9382
|
+
}));
|
|
9383
|
+
const report = {
|
|
9384
|
+
org,
|
|
9385
|
+
since: sinceDate,
|
|
9386
|
+
totalRepos: allRepos.length,
|
|
9387
|
+
repos: repos2,
|
|
9388
|
+
committers: aggregateCommitters(repoAuthors.map((r) => r.authors)),
|
|
9389
|
+
repoAuthors
|
|
9390
|
+
};
|
|
9391
|
+
if (options2.json) {
|
|
9392
|
+
console.log(JSON.stringify(report, null, 2));
|
|
9393
|
+
} else if (repos2.length === 0) {
|
|
9394
|
+
console.log(`No commits found in ${org} since ${sinceDate}.`);
|
|
9395
|
+
} else {
|
|
9396
|
+
printCommitsReport(report);
|
|
9397
|
+
}
|
|
9398
|
+
}
|
|
9399
|
+
|
|
9400
|
+
// src/commands/github/parseSinceDate.ts
|
|
9401
|
+
import { InvalidArgumentError } from "commander";
|
|
9402
|
+
function parseSinceDate(value) {
|
|
9403
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
9404
|
+
throw new InvalidArgumentError("Expected a date in YYYY-MM-DD format.");
|
|
9405
|
+
}
|
|
9406
|
+
const date = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
|
|
9407
|
+
if (Number.isNaN(date.getTime()) || date.toISOString().slice(0, 10) !== value) {
|
|
9408
|
+
throw new InvalidArgumentError(`Not a valid calendar date: ${value}.`);
|
|
9409
|
+
}
|
|
9410
|
+
return value;
|
|
9411
|
+
}
|
|
9412
|
+
|
|
9413
|
+
// src/commands/github/parseTopCount.ts
|
|
9414
|
+
import { InvalidArgumentError as InvalidArgumentError2 } from "commander";
|
|
9415
|
+
function parseTopCount(value) {
|
|
9416
|
+
if (!/^\d+$/.test(value) || Number.parseInt(value, 10) < 1) {
|
|
9417
|
+
throw new InvalidArgumentError2("Expected a positive integer.");
|
|
9418
|
+
}
|
|
9419
|
+
return Number.parseInt(value, 10);
|
|
9420
|
+
}
|
|
9421
|
+
|
|
9422
|
+
// src/commands/registerGithub.ts
|
|
9423
|
+
function registerGithub(program2) {
|
|
9424
|
+
const githubCommand = program2.command("github").description("GitHub organisation utilities");
|
|
9425
|
+
githubCommand.command("commits <org>").description("Report commit activity across an organisation").option(
|
|
9426
|
+
"--since <date>",
|
|
9427
|
+
"start of the window as YYYY-MM-DD (default: 30 days ago)",
|
|
9428
|
+
parseSinceDate
|
|
9429
|
+
).option(
|
|
9430
|
+
"--top <n>",
|
|
9431
|
+
"only report the top <n> repos by commit count",
|
|
9432
|
+
parseTopCount
|
|
9433
|
+
).option("--json", "Output as JSON").action(commits);
|
|
9434
|
+
}
|
|
9435
|
+
|
|
9234
9436
|
// src/commands/handover/archive.ts
|
|
9235
9437
|
import { existsSync as existsSync30, mkdirSync as mkdirSync6, renameSync as renameSync2 } from "fs";
|
|
9236
|
-
import { join as
|
|
9438
|
+
import { join as join29 } from "path";
|
|
9237
9439
|
|
|
9238
9440
|
// src/commands/handover/formatArchiveTimestamp.ts
|
|
9239
9441
|
function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
@@ -9248,9 +9450,9 @@ function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
|
9248
9450
|
}
|
|
9249
9451
|
|
|
9250
9452
|
// src/commands/handover/getHandoverArchiveDir.ts
|
|
9251
|
-
import { join as
|
|
9453
|
+
import { join as join28 } from "path";
|
|
9252
9454
|
function getHandoverArchiveDir(cwd = process.cwd()) {
|
|
9253
|
-
return
|
|
9455
|
+
return join28(cwd, ".assist", "handovers", "archive");
|
|
9254
9456
|
}
|
|
9255
9457
|
|
|
9256
9458
|
// src/commands/handover/archive.ts
|
|
@@ -9260,11 +9462,11 @@ function buildArchiveFilename(timestamp, suffix) {
|
|
|
9260
9462
|
return `${base}.md`;
|
|
9261
9463
|
}
|
|
9262
9464
|
function resolveCollisionPath(archiveDir, timestamp, suffix) {
|
|
9263
|
-
const initial =
|
|
9465
|
+
const initial = join29(archiveDir, buildArchiveFilename(timestamp, suffix));
|
|
9264
9466
|
if (!existsSync30(initial)) return initial;
|
|
9265
9467
|
for (let i = 1; i <= MAX_COLLISION_SUFFIX; i++) {
|
|
9266
9468
|
const collisionSuffix = suffix ? `${suffix}-${i}` : `${i}`;
|
|
9267
|
-
const candidate =
|
|
9469
|
+
const candidate = join29(
|
|
9268
9470
|
archiveDir,
|
|
9269
9471
|
buildArchiveFilename(timestamp, collisionSuffix)
|
|
9270
9472
|
);
|
|
@@ -9460,7 +9662,7 @@ function registerHandover(program2) {
|
|
|
9460
9662
|
}
|
|
9461
9663
|
|
|
9462
9664
|
// src/commands/jira/acceptanceCriteria.ts
|
|
9463
|
-
import
|
|
9665
|
+
import chalk108 from "chalk";
|
|
9464
9666
|
|
|
9465
9667
|
// src/commands/jira/adfToText.ts
|
|
9466
9668
|
function renderInline(node) {
|
|
@@ -9521,7 +9723,7 @@ function adfToText(doc) {
|
|
|
9521
9723
|
|
|
9522
9724
|
// src/commands/jira/fetchIssue.ts
|
|
9523
9725
|
import { execSync as execSync26 } from "child_process";
|
|
9524
|
-
import
|
|
9726
|
+
import chalk107 from "chalk";
|
|
9525
9727
|
function fetchIssue(issueKey, fields) {
|
|
9526
9728
|
let result;
|
|
9527
9729
|
try {
|
|
@@ -9534,15 +9736,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
9534
9736
|
const stderr = error.stderr;
|
|
9535
9737
|
if (stderr.includes("unauthorized")) {
|
|
9536
9738
|
console.error(
|
|
9537
|
-
|
|
9739
|
+
chalk107.red("Jira authentication expired."),
|
|
9538
9740
|
"Run",
|
|
9539
|
-
|
|
9741
|
+
chalk107.cyan("assist jira auth"),
|
|
9540
9742
|
"to re-authenticate."
|
|
9541
9743
|
);
|
|
9542
9744
|
process.exit(1);
|
|
9543
9745
|
}
|
|
9544
9746
|
}
|
|
9545
|
-
console.error(
|
|
9747
|
+
console.error(chalk107.red(`Failed to fetch ${issueKey}.`));
|
|
9546
9748
|
process.exit(1);
|
|
9547
9749
|
}
|
|
9548
9750
|
return JSON.parse(result);
|
|
@@ -9556,7 +9758,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
9556
9758
|
const parsed = fetchIssue(issueKey, field);
|
|
9557
9759
|
const acValue = parsed?.fields?.[field];
|
|
9558
9760
|
if (!acValue) {
|
|
9559
|
-
console.log(
|
|
9761
|
+
console.log(chalk108.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
9560
9762
|
return;
|
|
9561
9763
|
}
|
|
9562
9764
|
if (typeof acValue === "string") {
|
|
@@ -9574,14 +9776,14 @@ function acceptanceCriteria(issueKey) {
|
|
|
9574
9776
|
import { execSync as execSync27 } from "child_process";
|
|
9575
9777
|
|
|
9576
9778
|
// src/shared/loadJson.ts
|
|
9577
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync7, readFileSync as readFileSync26, writeFileSync as
|
|
9779
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync7, readFileSync as readFileSync26, writeFileSync as writeFileSync19 } from "fs";
|
|
9578
9780
|
import { homedir as homedir8 } from "os";
|
|
9579
|
-
import { join as
|
|
9781
|
+
import { join as join30 } from "path";
|
|
9580
9782
|
function getStoreDir() {
|
|
9581
|
-
return
|
|
9783
|
+
return join30(homedir8(), ".assist");
|
|
9582
9784
|
}
|
|
9583
9785
|
function getStorePath(filename) {
|
|
9584
|
-
return
|
|
9786
|
+
return join30(getStoreDir(), filename);
|
|
9585
9787
|
}
|
|
9586
9788
|
function loadJson(filename) {
|
|
9587
9789
|
const path52 = getStorePath(filename);
|
|
@@ -9599,7 +9801,7 @@ function saveJson(filename, data) {
|
|
|
9599
9801
|
if (!existsSync32(dir)) {
|
|
9600
9802
|
mkdirSync7(dir, { recursive: true });
|
|
9601
9803
|
}
|
|
9602
|
-
|
|
9804
|
+
writeFileSync19(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
9603
9805
|
}
|
|
9604
9806
|
|
|
9605
9807
|
// src/shared/promptInput.ts
|
|
@@ -9651,14 +9853,14 @@ async function jiraAuth() {
|
|
|
9651
9853
|
}
|
|
9652
9854
|
|
|
9653
9855
|
// src/commands/jira/viewIssue.ts
|
|
9654
|
-
import
|
|
9856
|
+
import chalk109 from "chalk";
|
|
9655
9857
|
function viewIssue(issueKey) {
|
|
9656
9858
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
9657
9859
|
const fields = parsed?.fields;
|
|
9658
9860
|
const summary = fields?.summary;
|
|
9659
9861
|
const description = fields?.description;
|
|
9660
9862
|
if (summary) {
|
|
9661
|
-
console.log(
|
|
9863
|
+
console.log(chalk109.bold(summary));
|
|
9662
9864
|
}
|
|
9663
9865
|
if (description) {
|
|
9664
9866
|
if (summary) console.log();
|
|
@@ -9672,7 +9874,7 @@ function viewIssue(issueKey) {
|
|
|
9672
9874
|
}
|
|
9673
9875
|
if (!summary && !description) {
|
|
9674
9876
|
console.log(
|
|
9675
|
-
|
|
9877
|
+
chalk109.yellow(`No summary or description found on ${issueKey}.`)
|
|
9676
9878
|
);
|
|
9677
9879
|
}
|
|
9678
9880
|
}
|
|
@@ -9687,13 +9889,13 @@ function registerJira(program2) {
|
|
|
9687
9889
|
|
|
9688
9890
|
// src/commands/reviewComments.ts
|
|
9689
9891
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
9690
|
-
import
|
|
9892
|
+
import chalk110 from "chalk";
|
|
9691
9893
|
async function reviewComments(number) {
|
|
9692
9894
|
if (number) {
|
|
9693
9895
|
try {
|
|
9694
9896
|
execFileSync5("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
9695
9897
|
} catch {
|
|
9696
|
-
console.error(
|
|
9898
|
+
console.error(chalk110.red(`gh pr checkout ${number} failed; aborting.`));
|
|
9697
9899
|
process.exit(1);
|
|
9698
9900
|
}
|
|
9699
9901
|
}
|
|
@@ -9726,15 +9928,15 @@ function registerList(program2) {
|
|
|
9726
9928
|
// src/commands/mermaid/index.ts
|
|
9727
9929
|
import { mkdirSync as mkdirSync8, readdirSync as readdirSync5 } from "fs";
|
|
9728
9930
|
import { resolve as resolve10 } from "path";
|
|
9729
|
-
import
|
|
9931
|
+
import chalk113 from "chalk";
|
|
9730
9932
|
|
|
9731
9933
|
// src/commands/mermaid/exportFile.ts
|
|
9732
|
-
import { readFileSync as readFileSync27, writeFileSync as
|
|
9934
|
+
import { readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "fs";
|
|
9733
9935
|
import { basename as basename7, extname, resolve as resolve9 } from "path";
|
|
9734
|
-
import
|
|
9936
|
+
import chalk112 from "chalk";
|
|
9735
9937
|
|
|
9736
9938
|
// src/commands/mermaid/renderBlock.ts
|
|
9737
|
-
import
|
|
9939
|
+
import chalk111 from "chalk";
|
|
9738
9940
|
async function renderBlock(krokiUrl, source) {
|
|
9739
9941
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
9740
9942
|
method: "POST",
|
|
@@ -9743,7 +9945,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
9743
9945
|
});
|
|
9744
9946
|
if (!response.ok) {
|
|
9745
9947
|
console.error(
|
|
9746
|
-
|
|
9948
|
+
chalk111.red(
|
|
9747
9949
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
9748
9950
|
)
|
|
9749
9951
|
);
|
|
@@ -9761,27 +9963,27 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
9761
9963
|
if (onlyIndex !== void 0) {
|
|
9762
9964
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
9763
9965
|
console.error(
|
|
9764
|
-
|
|
9966
|
+
chalk112.red(
|
|
9765
9967
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
9766
9968
|
)
|
|
9767
9969
|
);
|
|
9768
9970
|
process.exit(1);
|
|
9769
9971
|
}
|
|
9770
9972
|
console.log(
|
|
9771
|
-
|
|
9973
|
+
chalk112.gray(
|
|
9772
9974
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
9773
9975
|
)
|
|
9774
9976
|
);
|
|
9775
9977
|
} else {
|
|
9776
|
-
console.log(
|
|
9978
|
+
console.log(chalk112.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
9777
9979
|
}
|
|
9778
9980
|
for (const [i, source] of blocks.entries()) {
|
|
9779
9981
|
const idx = i + 1;
|
|
9780
9982
|
if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
|
|
9781
9983
|
const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
|
|
9782
9984
|
const svg = await renderBlock(krokiUrl, source);
|
|
9783
|
-
|
|
9784
|
-
console.log(
|
|
9985
|
+
writeFileSync20(outPath, svg, "utf8");
|
|
9986
|
+
console.log(chalk112.green(` \u2192 ${outPath}`));
|
|
9785
9987
|
}
|
|
9786
9988
|
}
|
|
9787
9989
|
function extractMermaidBlocks(markdown) {
|
|
@@ -9797,18 +9999,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
9797
9999
|
if (options2.index !== void 0) {
|
|
9798
10000
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
9799
10001
|
console.error(
|
|
9800
|
-
|
|
10002
|
+
chalk113.red(`--index must be a positive integer (got ${options2.index})`)
|
|
9801
10003
|
);
|
|
9802
10004
|
process.exit(1);
|
|
9803
10005
|
}
|
|
9804
10006
|
if (!file) {
|
|
9805
|
-
console.error(
|
|
10007
|
+
console.error(chalk113.red("--index requires a file argument"));
|
|
9806
10008
|
process.exit(1);
|
|
9807
10009
|
}
|
|
9808
10010
|
}
|
|
9809
10011
|
const files = file ? [file] : readdirSync5(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
9810
10012
|
if (files.length === 0) {
|
|
9811
|
-
console.log(
|
|
10013
|
+
console.log(chalk113.gray("No markdown files found in current directory."));
|
|
9812
10014
|
return;
|
|
9813
10015
|
}
|
|
9814
10016
|
for (const f of files) {
|
|
@@ -9831,7 +10033,7 @@ function registerMermaid(program2) {
|
|
|
9831
10033
|
}
|
|
9832
10034
|
|
|
9833
10035
|
// src/commands/news/add/index.ts
|
|
9834
|
-
import
|
|
10036
|
+
import chalk114 from "chalk";
|
|
9835
10037
|
import enquirer8 from "enquirer";
|
|
9836
10038
|
async function add2(url) {
|
|
9837
10039
|
if (!url) {
|
|
@@ -9854,17 +10056,17 @@ async function add2(url) {
|
|
|
9854
10056
|
const news = config.news ?? {};
|
|
9855
10057
|
const feeds = news.feeds ?? [];
|
|
9856
10058
|
if (feeds.includes(url)) {
|
|
9857
|
-
console.log(
|
|
10059
|
+
console.log(chalk114.yellow("Feed already exists in config"));
|
|
9858
10060
|
return;
|
|
9859
10061
|
}
|
|
9860
10062
|
feeds.push(url);
|
|
9861
10063
|
config.news = { ...news, feeds };
|
|
9862
10064
|
saveGlobalConfig(config);
|
|
9863
|
-
console.log(
|
|
10065
|
+
console.log(chalk114.green(`Added feed: ${url}`));
|
|
9864
10066
|
}
|
|
9865
10067
|
|
|
9866
10068
|
// src/commands/news/web/handleRequest.ts
|
|
9867
|
-
import
|
|
10069
|
+
import chalk115 from "chalk";
|
|
9868
10070
|
|
|
9869
10071
|
// src/commands/news/web/shared.ts
|
|
9870
10072
|
import { decodeHTML } from "entities";
|
|
@@ -10000,17 +10202,17 @@ function prefetch() {
|
|
|
10000
10202
|
const config = loadConfig();
|
|
10001
10203
|
const total = config.news.feeds.length;
|
|
10002
10204
|
if (total === 0) return;
|
|
10003
|
-
process.stdout.write(
|
|
10205
|
+
process.stdout.write(chalk115.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
10004
10206
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
10005
10207
|
const width = 20;
|
|
10006
10208
|
const filled = Math.round(done2 / t * width);
|
|
10007
10209
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
10008
10210
|
process.stdout.write(
|
|
10009
|
-
`\r${
|
|
10211
|
+
`\r${chalk115.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
10010
10212
|
);
|
|
10011
10213
|
}).then((items2) => {
|
|
10012
10214
|
process.stdout.write(
|
|
10013
|
-
`\r${
|
|
10215
|
+
`\r${chalk115.green(`Fetched ${items2.length} items from ${total} feed(s)`)}
|
|
10014
10216
|
`
|
|
10015
10217
|
);
|
|
10016
10218
|
cachedItems = items2;
|
|
@@ -10055,7 +10257,7 @@ function registerNews(program2) {
|
|
|
10055
10257
|
}
|
|
10056
10258
|
|
|
10057
10259
|
// src/commands/prompts/printPromptsTable.ts
|
|
10058
|
-
import
|
|
10260
|
+
import chalk116 from "chalk";
|
|
10059
10261
|
function truncate(str, max) {
|
|
10060
10262
|
if (str.length <= max) return str;
|
|
10061
10263
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -10073,14 +10275,14 @@ function printPromptsTable(rows) {
|
|
|
10073
10275
|
"Command".padEnd(commandWidth),
|
|
10074
10276
|
"Repos"
|
|
10075
10277
|
].join(" ");
|
|
10076
|
-
console.log(
|
|
10077
|
-
console.log(
|
|
10278
|
+
console.log(chalk116.dim(header));
|
|
10279
|
+
console.log(chalk116.dim("-".repeat(header.length)));
|
|
10078
10280
|
for (const row of rows) {
|
|
10079
10281
|
const count6 = String(row.count).padStart(countWidth);
|
|
10080
10282
|
const tool = row.tool.padEnd(toolWidth);
|
|
10081
10283
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
10082
10284
|
console.log(
|
|
10083
|
-
`${
|
|
10285
|
+
`${chalk116.yellow(count6)} ${tool} ${command} ${chalk116.dim(row.repos)}`
|
|
10084
10286
|
);
|
|
10085
10287
|
}
|
|
10086
10288
|
}
|
|
@@ -10108,33 +10310,6 @@ function registerPrompts(program2) {
|
|
|
10108
10310
|
program2.command("prompts").description("Show top denied tool calls by frequency").action(prompts2);
|
|
10109
10311
|
}
|
|
10110
10312
|
|
|
10111
|
-
// src/commands/prs/runGhGraphql.ts
|
|
10112
|
-
import { spawnSync as spawnSync2 } from "child_process";
|
|
10113
|
-
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync20 } from "fs";
|
|
10114
|
-
import { tmpdir as tmpdir4 } from "os";
|
|
10115
|
-
import { join as join30 } from "path";
|
|
10116
|
-
function buildArgs2(queryFile, vars) {
|
|
10117
|
-
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
10118
|
-
for (const [key, value] of Object.entries(vars)) {
|
|
10119
|
-
const flag = typeof value === "number" ? "-F" : "-f";
|
|
10120
|
-
args.push(flag, `${key}=${value}`);
|
|
10121
|
-
}
|
|
10122
|
-
return args;
|
|
10123
|
-
}
|
|
10124
|
-
function runGhGraphql(mutation, vars) {
|
|
10125
|
-
const queryFile = join30(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
10126
|
-
writeFileSync20(queryFile, mutation);
|
|
10127
|
-
try {
|
|
10128
|
-
const result = spawnSync2("gh", buildArgs2(queryFile, vars), {
|
|
10129
|
-
encoding: "utf-8"
|
|
10130
|
-
});
|
|
10131
|
-
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
10132
|
-
return result.stdout;
|
|
10133
|
-
} finally {
|
|
10134
|
-
unlinkSync6(queryFile);
|
|
10135
|
-
}
|
|
10136
|
-
}
|
|
10137
|
-
|
|
10138
10313
|
// src/commands/prs/shared.ts
|
|
10139
10314
|
import { execSync as execSync29 } from "child_process";
|
|
10140
10315
|
|
|
@@ -10574,20 +10749,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
10574
10749
|
}
|
|
10575
10750
|
|
|
10576
10751
|
// src/commands/prs/listComments/printComments.ts
|
|
10577
|
-
import
|
|
10752
|
+
import chalk117 from "chalk";
|
|
10578
10753
|
function formatForHuman(comment3) {
|
|
10579
10754
|
if (comment3.type === "review") {
|
|
10580
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
10755
|
+
const stateColor = comment3.state === "APPROVED" ? chalk117.green : comment3.state === "CHANGES_REQUESTED" ? chalk117.red : chalk117.yellow;
|
|
10581
10756
|
return [
|
|
10582
|
-
`${
|
|
10757
|
+
`${chalk117.cyan("Review")} by ${chalk117.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
10583
10758
|
comment3.body,
|
|
10584
10759
|
""
|
|
10585
10760
|
].join("\n");
|
|
10586
10761
|
}
|
|
10587
10762
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
10588
10763
|
return [
|
|
10589
|
-
`${
|
|
10590
|
-
|
|
10764
|
+
`${chalk117.cyan("Line comment")} by ${chalk117.bold(comment3.user)} on ${chalk117.dim(`${comment3.path}${location}`)}`,
|
|
10765
|
+
chalk117.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
10591
10766
|
comment3.body,
|
|
10592
10767
|
""
|
|
10593
10768
|
].join("\n");
|
|
@@ -10677,13 +10852,13 @@ import { execSync as execSync35 } from "child_process";
|
|
|
10677
10852
|
import enquirer9 from "enquirer";
|
|
10678
10853
|
|
|
10679
10854
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
10680
|
-
import
|
|
10855
|
+
import chalk118 from "chalk";
|
|
10681
10856
|
var STATUS_MAP = {
|
|
10682
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
10683
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
10857
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk118.magenta("merged"), date: pr.mergedAt } : null,
|
|
10858
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk118.red("closed"), date: pr.closedAt } : null
|
|
10684
10859
|
};
|
|
10685
10860
|
function defaultStatus(pr) {
|
|
10686
|
-
return { label:
|
|
10861
|
+
return { label: chalk118.green("opened"), date: pr.createdAt };
|
|
10687
10862
|
}
|
|
10688
10863
|
function getStatus2(pr) {
|
|
10689
10864
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -10692,11 +10867,11 @@ function formatDate(dateStr) {
|
|
|
10692
10867
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
10693
10868
|
}
|
|
10694
10869
|
function formatPrHeader(pr, status2) {
|
|
10695
|
-
return `${
|
|
10870
|
+
return `${chalk118.cyan(`#${pr.number}`)} ${pr.title} ${chalk118.dim(`(${pr.author.login},`)} ${status2.label} ${chalk118.dim(`${formatDate(status2.date)})`)}`;
|
|
10696
10871
|
}
|
|
10697
10872
|
function logPrDetails(pr) {
|
|
10698
10873
|
console.log(
|
|
10699
|
-
|
|
10874
|
+
chalk118.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
10700
10875
|
);
|
|
10701
10876
|
console.log();
|
|
10702
10877
|
}
|
|
@@ -10884,10 +11059,10 @@ function registerPrs(program2) {
|
|
|
10884
11059
|
}
|
|
10885
11060
|
|
|
10886
11061
|
// src/commands/ravendb/ravendbAuth.ts
|
|
10887
|
-
import
|
|
11062
|
+
import chalk124 from "chalk";
|
|
10888
11063
|
|
|
10889
11064
|
// src/shared/createConnectionAuth.ts
|
|
10890
|
-
import
|
|
11065
|
+
import chalk119 from "chalk";
|
|
10891
11066
|
function listConnections(connections, format2) {
|
|
10892
11067
|
if (connections.length === 0) {
|
|
10893
11068
|
console.log("No connections configured.");
|
|
@@ -10900,7 +11075,7 @@ function listConnections(connections, format2) {
|
|
|
10900
11075
|
function removeConnection(connections, name, save) {
|
|
10901
11076
|
const filtered = connections.filter((c) => c.name !== name);
|
|
10902
11077
|
if (filtered.length === connections.length) {
|
|
10903
|
-
console.error(
|
|
11078
|
+
console.error(chalk119.red(`Connection "${name}" not found.`));
|
|
10904
11079
|
process.exit(1);
|
|
10905
11080
|
}
|
|
10906
11081
|
save(filtered);
|
|
@@ -10946,15 +11121,15 @@ function saveConnections(connections) {
|
|
|
10946
11121
|
}
|
|
10947
11122
|
|
|
10948
11123
|
// src/commands/ravendb/promptConnection.ts
|
|
10949
|
-
import
|
|
11124
|
+
import chalk122 from "chalk";
|
|
10950
11125
|
|
|
10951
11126
|
// src/commands/ravendb/selectOpSecret.ts
|
|
10952
|
-
import
|
|
11127
|
+
import chalk121 from "chalk";
|
|
10953
11128
|
import Enquirer2 from "enquirer";
|
|
10954
11129
|
|
|
10955
11130
|
// src/commands/ravendb/searchItems.ts
|
|
10956
11131
|
import { execSync as execSync37 } from "child_process";
|
|
10957
|
-
import
|
|
11132
|
+
import chalk120 from "chalk";
|
|
10958
11133
|
function opExec(args) {
|
|
10959
11134
|
return execSync37(`op ${args}`, {
|
|
10960
11135
|
encoding: "utf-8",
|
|
@@ -10967,7 +11142,7 @@ function searchItems(search2) {
|
|
|
10967
11142
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
10968
11143
|
} catch {
|
|
10969
11144
|
console.error(
|
|
10970
|
-
|
|
11145
|
+
chalk120.red(
|
|
10971
11146
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
10972
11147
|
)
|
|
10973
11148
|
);
|
|
@@ -10981,7 +11156,7 @@ function getItemFields(itemId) {
|
|
|
10981
11156
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
10982
11157
|
return item.fields.filter((f) => f.reference && f.label);
|
|
10983
11158
|
} catch {
|
|
10984
|
-
console.error(
|
|
11159
|
+
console.error(chalk120.red("Failed to get item details from 1Password."));
|
|
10985
11160
|
process.exit(1);
|
|
10986
11161
|
}
|
|
10987
11162
|
}
|
|
@@ -11000,7 +11175,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11000
11175
|
}).run();
|
|
11001
11176
|
const items2 = searchItems(search2);
|
|
11002
11177
|
if (items2.length === 0) {
|
|
11003
|
-
console.error(
|
|
11178
|
+
console.error(chalk121.red(`No items found matching "${search2}".`));
|
|
11004
11179
|
process.exit(1);
|
|
11005
11180
|
}
|
|
11006
11181
|
const itemId = await selectOne(
|
|
@@ -11009,7 +11184,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11009
11184
|
);
|
|
11010
11185
|
const fields = getItemFields(itemId);
|
|
11011
11186
|
if (fields.length === 0) {
|
|
11012
|
-
console.error(
|
|
11187
|
+
console.error(chalk121.red("No fields with references found on this item."));
|
|
11013
11188
|
process.exit(1);
|
|
11014
11189
|
}
|
|
11015
11190
|
const ref = await selectOne(
|
|
@@ -11023,7 +11198,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11023
11198
|
async function promptConnection(existingNames) {
|
|
11024
11199
|
const name = await promptInput("name", "Connection name:");
|
|
11025
11200
|
if (existingNames.includes(name)) {
|
|
11026
|
-
console.error(
|
|
11201
|
+
console.error(chalk122.red(`Connection "${name}" already exists.`));
|
|
11027
11202
|
process.exit(1);
|
|
11028
11203
|
}
|
|
11029
11204
|
const url = await promptInput(
|
|
@@ -11032,22 +11207,22 @@ async function promptConnection(existingNames) {
|
|
|
11032
11207
|
);
|
|
11033
11208
|
const database = await promptInput("database", "Database name:");
|
|
11034
11209
|
if (!name || !url || !database) {
|
|
11035
|
-
console.error(
|
|
11210
|
+
console.error(chalk122.red("All fields are required."));
|
|
11036
11211
|
process.exit(1);
|
|
11037
11212
|
}
|
|
11038
11213
|
const apiKeyRef = await selectOpSecret();
|
|
11039
|
-
console.log(
|
|
11214
|
+
console.log(chalk122.dim(`Using: ${apiKeyRef}`));
|
|
11040
11215
|
return { name, url, database, apiKeyRef };
|
|
11041
11216
|
}
|
|
11042
11217
|
|
|
11043
11218
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
11044
|
-
import
|
|
11219
|
+
import chalk123 from "chalk";
|
|
11045
11220
|
function ravendbSetConnection(name) {
|
|
11046
11221
|
const raw = loadGlobalConfigRaw();
|
|
11047
11222
|
const ravendb = raw.ravendb ?? {};
|
|
11048
11223
|
const connections = ravendb.connections ?? [];
|
|
11049
11224
|
if (!connections.some((c) => c.name === name)) {
|
|
11050
|
-
console.error(
|
|
11225
|
+
console.error(chalk123.red(`Connection "${name}" not found.`));
|
|
11051
11226
|
console.error(
|
|
11052
11227
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
11053
11228
|
);
|
|
@@ -11063,16 +11238,16 @@ function ravendbSetConnection(name) {
|
|
|
11063
11238
|
var ravendbAuth = createConnectionAuth({
|
|
11064
11239
|
load: loadConnections,
|
|
11065
11240
|
save: saveConnections,
|
|
11066
|
-
format: (c) => `${
|
|
11241
|
+
format: (c) => `${chalk124.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
11067
11242
|
promptNew: promptConnection,
|
|
11068
11243
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
11069
11244
|
});
|
|
11070
11245
|
|
|
11071
11246
|
// src/commands/ravendb/ravendbCollections.ts
|
|
11072
|
-
import
|
|
11247
|
+
import chalk128 from "chalk";
|
|
11073
11248
|
|
|
11074
11249
|
// src/commands/ravendb/ravenFetch.ts
|
|
11075
|
-
import
|
|
11250
|
+
import chalk126 from "chalk";
|
|
11076
11251
|
|
|
11077
11252
|
// src/commands/ravendb/getAccessToken.ts
|
|
11078
11253
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -11109,10 +11284,10 @@ ${errorText}`
|
|
|
11109
11284
|
|
|
11110
11285
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
11111
11286
|
import { execSync as execSync38 } from "child_process";
|
|
11112
|
-
import
|
|
11287
|
+
import chalk125 from "chalk";
|
|
11113
11288
|
function resolveOpSecret(reference) {
|
|
11114
11289
|
if (!reference.startsWith("op://")) {
|
|
11115
|
-
console.error(
|
|
11290
|
+
console.error(chalk125.red(`Invalid secret reference: must start with op://`));
|
|
11116
11291
|
process.exit(1);
|
|
11117
11292
|
}
|
|
11118
11293
|
try {
|
|
@@ -11122,7 +11297,7 @@ function resolveOpSecret(reference) {
|
|
|
11122
11297
|
}).trim();
|
|
11123
11298
|
} catch {
|
|
11124
11299
|
console.error(
|
|
11125
|
-
|
|
11300
|
+
chalk125.red(
|
|
11126
11301
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
11127
11302
|
)
|
|
11128
11303
|
);
|
|
@@ -11149,7 +11324,7 @@ async function ravenFetch(connection, path52) {
|
|
|
11149
11324
|
if (!response.ok) {
|
|
11150
11325
|
const body = await response.text();
|
|
11151
11326
|
console.error(
|
|
11152
|
-
|
|
11327
|
+
chalk126.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
11153
11328
|
);
|
|
11154
11329
|
console.error(body.substring(0, 500));
|
|
11155
11330
|
process.exit(1);
|
|
@@ -11158,7 +11333,7 @@ async function ravenFetch(connection, path52) {
|
|
|
11158
11333
|
}
|
|
11159
11334
|
|
|
11160
11335
|
// src/commands/ravendb/resolveConnection.ts
|
|
11161
|
-
import
|
|
11336
|
+
import chalk127 from "chalk";
|
|
11162
11337
|
function loadRavendb() {
|
|
11163
11338
|
const raw = loadGlobalConfigRaw();
|
|
11164
11339
|
const ravendb = raw.ravendb;
|
|
@@ -11172,7 +11347,7 @@ function resolveConnection(name) {
|
|
|
11172
11347
|
const connectionName = name ?? defaultConnection;
|
|
11173
11348
|
if (!connectionName) {
|
|
11174
11349
|
console.error(
|
|
11175
|
-
|
|
11350
|
+
chalk127.red(
|
|
11176
11351
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
11177
11352
|
)
|
|
11178
11353
|
);
|
|
@@ -11180,7 +11355,7 @@ function resolveConnection(name) {
|
|
|
11180
11355
|
}
|
|
11181
11356
|
const connection = connections.find((c) => c.name === connectionName);
|
|
11182
11357
|
if (!connection) {
|
|
11183
|
-
console.error(
|
|
11358
|
+
console.error(chalk127.red(`Connection "${connectionName}" not found.`));
|
|
11184
11359
|
console.error(
|
|
11185
11360
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
11186
11361
|
);
|
|
@@ -11211,15 +11386,15 @@ async function ravendbCollections(connectionName) {
|
|
|
11211
11386
|
return;
|
|
11212
11387
|
}
|
|
11213
11388
|
for (const c of collections) {
|
|
11214
|
-
console.log(`${
|
|
11389
|
+
console.log(`${chalk128.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
11215
11390
|
}
|
|
11216
11391
|
}
|
|
11217
11392
|
|
|
11218
11393
|
// src/commands/ravendb/ravendbQuery.ts
|
|
11219
|
-
import
|
|
11394
|
+
import chalk130 from "chalk";
|
|
11220
11395
|
|
|
11221
11396
|
// src/commands/ravendb/fetchAllPages.ts
|
|
11222
|
-
import
|
|
11397
|
+
import chalk129 from "chalk";
|
|
11223
11398
|
|
|
11224
11399
|
// src/commands/ravendb/buildQueryPath.ts
|
|
11225
11400
|
function buildQueryPath(opts) {
|
|
@@ -11257,7 +11432,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11257
11432
|
allResults.push(...results);
|
|
11258
11433
|
start3 += results.length;
|
|
11259
11434
|
process.stderr.write(
|
|
11260
|
-
`\r${
|
|
11435
|
+
`\r${chalk129.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
11261
11436
|
);
|
|
11262
11437
|
if (start3 >= totalResults) break;
|
|
11263
11438
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -11272,7 +11447,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11272
11447
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
11273
11448
|
const resolved = resolveArgs(connectionName, collection);
|
|
11274
11449
|
if (!resolved.collection && !options2.query) {
|
|
11275
|
-
console.error(
|
|
11450
|
+
console.error(chalk130.red("Provide a collection name or --query filter."));
|
|
11276
11451
|
process.exit(1);
|
|
11277
11452
|
}
|
|
11278
11453
|
const { collection: col } = resolved;
|
|
@@ -11310,7 +11485,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
11310
11485
|
import * as path29 from "path";
|
|
11311
11486
|
|
|
11312
11487
|
// src/commands/refactor/logViolations.ts
|
|
11313
|
-
import
|
|
11488
|
+
import chalk131 from "chalk";
|
|
11314
11489
|
var DEFAULT_MAX_LINES = 100;
|
|
11315
11490
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
11316
11491
|
if (violations.length === 0) {
|
|
@@ -11319,43 +11494,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
11319
11494
|
}
|
|
11320
11495
|
return;
|
|
11321
11496
|
}
|
|
11322
|
-
console.error(
|
|
11497
|
+
console.error(chalk131.red(`
|
|
11323
11498
|
Refactor check failed:
|
|
11324
11499
|
`));
|
|
11325
|
-
console.error(
|
|
11500
|
+
console.error(chalk131.red(` The following files exceed ${maxLines} lines:
|
|
11326
11501
|
`));
|
|
11327
11502
|
for (const violation of violations) {
|
|
11328
|
-
console.error(
|
|
11503
|
+
console.error(chalk131.red(` ${violation.file} (${violation.lines} lines)`));
|
|
11329
11504
|
}
|
|
11330
11505
|
console.error(
|
|
11331
|
-
|
|
11506
|
+
chalk131.yellow(
|
|
11332
11507
|
`
|
|
11333
11508
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
11334
11509
|
way to refactor it, ignore it with:
|
|
11335
11510
|
`
|
|
11336
11511
|
)
|
|
11337
11512
|
);
|
|
11338
|
-
console.error(
|
|
11513
|
+
console.error(chalk131.gray(` assist refactor ignore <file>
|
|
11339
11514
|
`));
|
|
11340
11515
|
if (process.env.CLAUDECODE) {
|
|
11341
|
-
console.error(
|
|
11516
|
+
console.error(chalk131.cyan(`
|
|
11342
11517
|
## Extracting Code to New Files
|
|
11343
11518
|
`));
|
|
11344
11519
|
console.error(
|
|
11345
|
-
|
|
11520
|
+
chalk131.cyan(
|
|
11346
11521
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
11347
11522
|
`
|
|
11348
11523
|
)
|
|
11349
11524
|
);
|
|
11350
11525
|
console.error(
|
|
11351
|
-
|
|
11526
|
+
chalk131.cyan(
|
|
11352
11527
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
11353
11528
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
11354
11529
|
`
|
|
11355
11530
|
)
|
|
11356
11531
|
);
|
|
11357
11532
|
console.error(
|
|
11358
|
-
|
|
11533
|
+
chalk131.cyan(
|
|
11359
11534
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
11360
11535
|
domains, move it to a common/shared folder.
|
|
11361
11536
|
`
|
|
@@ -11511,7 +11686,7 @@ async function check(pattern2, options2) {
|
|
|
11511
11686
|
|
|
11512
11687
|
// src/commands/refactor/extract/index.ts
|
|
11513
11688
|
import path36 from "path";
|
|
11514
|
-
import
|
|
11689
|
+
import chalk134 from "chalk";
|
|
11515
11690
|
|
|
11516
11691
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
11517
11692
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -12086,23 +12261,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
12086
12261
|
|
|
12087
12262
|
// src/commands/refactor/extract/displayPlan.ts
|
|
12088
12263
|
import path33 from "path";
|
|
12089
|
-
import
|
|
12264
|
+
import chalk132 from "chalk";
|
|
12090
12265
|
function section(title) {
|
|
12091
12266
|
return `
|
|
12092
|
-
${
|
|
12267
|
+
${chalk132.cyan(title)}`;
|
|
12093
12268
|
}
|
|
12094
12269
|
function displayImporters(plan2, cwd) {
|
|
12095
12270
|
if (plan2.importersToUpdate.length === 0) return;
|
|
12096
12271
|
console.log(section("Update importers:"));
|
|
12097
12272
|
for (const imp of plan2.importersToUpdate) {
|
|
12098
12273
|
const rel = path33.relative(cwd, imp.file.getFilePath());
|
|
12099
|
-
console.log(` ${
|
|
12274
|
+
console.log(` ${chalk132.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
12100
12275
|
}
|
|
12101
12276
|
}
|
|
12102
12277
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
12103
|
-
console.log(
|
|
12278
|
+
console.log(chalk132.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
12104
12279
|
`));
|
|
12105
|
-
console.log(` ${
|
|
12280
|
+
console.log(` ${chalk132.cyan("Functions to move:")}`);
|
|
12106
12281
|
for (const name of plan2.extractedNames) {
|
|
12107
12282
|
console.log(` ${name}`);
|
|
12108
12283
|
}
|
|
@@ -12136,7 +12311,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
12136
12311
|
|
|
12137
12312
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
12138
12313
|
import path35 from "path";
|
|
12139
|
-
import
|
|
12314
|
+
import chalk133 from "chalk";
|
|
12140
12315
|
import { Project as Project3 } from "ts-morph";
|
|
12141
12316
|
|
|
12142
12317
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -12196,7 +12371,7 @@ function loadProjectFile(file) {
|
|
|
12196
12371
|
});
|
|
12197
12372
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
12198
12373
|
if (!sourceFile) {
|
|
12199
|
-
console.log(
|
|
12374
|
+
console.log(chalk133.red(`File not found in project: ${file}`));
|
|
12200
12375
|
process.exit(1);
|
|
12201
12376
|
}
|
|
12202
12377
|
return { project, sourceFile };
|
|
@@ -12219,19 +12394,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
12219
12394
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
12220
12395
|
if (options2.apply) {
|
|
12221
12396
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
12222
|
-
console.log(
|
|
12397
|
+
console.log(chalk134.green("\nExtraction complete"));
|
|
12223
12398
|
} else {
|
|
12224
|
-
console.log(
|
|
12399
|
+
console.log(chalk134.dim("\nDry run. Use --apply to execute."));
|
|
12225
12400
|
}
|
|
12226
12401
|
}
|
|
12227
12402
|
|
|
12228
12403
|
// src/commands/refactor/ignore.ts
|
|
12229
12404
|
import fs21 from "fs";
|
|
12230
|
-
import
|
|
12405
|
+
import chalk135 from "chalk";
|
|
12231
12406
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
12232
12407
|
function ignore(file) {
|
|
12233
12408
|
if (!fs21.existsSync(file)) {
|
|
12234
|
-
console.error(
|
|
12409
|
+
console.error(chalk135.red(`Error: File does not exist: ${file}`));
|
|
12235
12410
|
process.exit(1);
|
|
12236
12411
|
}
|
|
12237
12412
|
const content = fs21.readFileSync(file, "utf-8");
|
|
@@ -12247,7 +12422,7 @@ function ignore(file) {
|
|
|
12247
12422
|
fs21.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
12248
12423
|
}
|
|
12249
12424
|
console.log(
|
|
12250
|
-
|
|
12425
|
+
chalk135.green(
|
|
12251
12426
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
12252
12427
|
)
|
|
12253
12428
|
);
|
|
@@ -12255,25 +12430,25 @@ function ignore(file) {
|
|
|
12255
12430
|
|
|
12256
12431
|
// src/commands/refactor/rename/index.ts
|
|
12257
12432
|
import path37 from "path";
|
|
12258
|
-
import
|
|
12433
|
+
import chalk136 from "chalk";
|
|
12259
12434
|
async function rename(source, destination, options2 = {}) {
|
|
12260
12435
|
const destPath = path37.resolve(destination);
|
|
12261
12436
|
const cwd = process.cwd();
|
|
12262
12437
|
const relSource = path37.relative(cwd, path37.resolve(source));
|
|
12263
12438
|
const relDest = path37.relative(cwd, destPath);
|
|
12264
12439
|
const { project, sourceFile } = loadProjectFile(source);
|
|
12265
|
-
console.log(
|
|
12440
|
+
console.log(chalk136.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
12266
12441
|
if (options2.apply) {
|
|
12267
12442
|
sourceFile.move(destPath);
|
|
12268
12443
|
await project.save();
|
|
12269
|
-
console.log(
|
|
12444
|
+
console.log(chalk136.green("Done"));
|
|
12270
12445
|
} else {
|
|
12271
|
-
console.log(
|
|
12446
|
+
console.log(chalk136.dim("Dry run. Use --apply to execute."));
|
|
12272
12447
|
}
|
|
12273
12448
|
}
|
|
12274
12449
|
|
|
12275
12450
|
// src/commands/refactor/renameSymbol/index.ts
|
|
12276
|
-
import
|
|
12451
|
+
import chalk137 from "chalk";
|
|
12277
12452
|
|
|
12278
12453
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
12279
12454
|
import { SyntaxKind as SyntaxKind14 } from "ts-morph";
|
|
@@ -12319,33 +12494,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
12319
12494
|
const { project, sourceFile } = loadProjectFile(file);
|
|
12320
12495
|
const symbol = findSymbol(sourceFile, oldName);
|
|
12321
12496
|
if (!symbol) {
|
|
12322
|
-
console.log(
|
|
12497
|
+
console.log(chalk137.red(`Symbol "${oldName}" not found in ${file}`));
|
|
12323
12498
|
process.exit(1);
|
|
12324
12499
|
}
|
|
12325
12500
|
const grouped = groupReferences(symbol, cwd);
|
|
12326
12501
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
12327
12502
|
console.log(
|
|
12328
|
-
|
|
12503
|
+
chalk137.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
12329
12504
|
`)
|
|
12330
12505
|
);
|
|
12331
12506
|
for (const [refFile, lines] of grouped) {
|
|
12332
12507
|
console.log(
|
|
12333
|
-
` ${
|
|
12508
|
+
` ${chalk137.dim(refFile)}: lines ${chalk137.cyan(lines.join(", "))}`
|
|
12334
12509
|
);
|
|
12335
12510
|
}
|
|
12336
12511
|
if (options2.apply) {
|
|
12337
12512
|
symbol.rename(newName);
|
|
12338
12513
|
await project.save();
|
|
12339
|
-
console.log(
|
|
12514
|
+
console.log(chalk137.green(`
|
|
12340
12515
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
12341
12516
|
} else {
|
|
12342
|
-
console.log(
|
|
12517
|
+
console.log(chalk137.dim("\nDry run. Use --apply to execute."));
|
|
12343
12518
|
}
|
|
12344
12519
|
}
|
|
12345
12520
|
|
|
12346
12521
|
// src/commands/refactor/restructure/index.ts
|
|
12347
12522
|
import path47 from "path";
|
|
12348
|
-
import
|
|
12523
|
+
import chalk140 from "chalk";
|
|
12349
12524
|
|
|
12350
12525
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
12351
12526
|
import path39 from "path";
|
|
@@ -12588,50 +12763,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
12588
12763
|
|
|
12589
12764
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
12590
12765
|
import path43 from "path";
|
|
12591
|
-
import
|
|
12766
|
+
import chalk138 from "chalk";
|
|
12592
12767
|
function relPath(filePath) {
|
|
12593
12768
|
return path43.relative(process.cwd(), filePath);
|
|
12594
12769
|
}
|
|
12595
12770
|
function displayMoves(plan2) {
|
|
12596
12771
|
if (plan2.moves.length === 0) return;
|
|
12597
|
-
console.log(
|
|
12772
|
+
console.log(chalk138.bold("\nFile moves:"));
|
|
12598
12773
|
for (const move of plan2.moves) {
|
|
12599
12774
|
console.log(
|
|
12600
|
-
` ${
|
|
12775
|
+
` ${chalk138.red(relPath(move.from))} \u2192 ${chalk138.green(relPath(move.to))}`
|
|
12601
12776
|
);
|
|
12602
|
-
console.log(
|
|
12777
|
+
console.log(chalk138.dim(` ${move.reason}`));
|
|
12603
12778
|
}
|
|
12604
12779
|
}
|
|
12605
12780
|
function displayRewrites(rewrites) {
|
|
12606
12781
|
if (rewrites.length === 0) return;
|
|
12607
12782
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
12608
|
-
console.log(
|
|
12783
|
+
console.log(chalk138.bold(`
|
|
12609
12784
|
Import rewrites (${affectedFiles.size} files):`));
|
|
12610
12785
|
for (const file of affectedFiles) {
|
|
12611
|
-
console.log(` ${
|
|
12786
|
+
console.log(` ${chalk138.cyan(relPath(file))}:`);
|
|
12612
12787
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
12613
12788
|
(r) => r.file === file
|
|
12614
12789
|
)) {
|
|
12615
12790
|
console.log(
|
|
12616
|
-
` ${
|
|
12791
|
+
` ${chalk138.red(`"${oldSpecifier}"`)} \u2192 ${chalk138.green(`"${newSpecifier}"`)}`
|
|
12617
12792
|
);
|
|
12618
12793
|
}
|
|
12619
12794
|
}
|
|
12620
12795
|
}
|
|
12621
12796
|
function displayPlan2(plan2) {
|
|
12622
12797
|
if (plan2.warnings.length > 0) {
|
|
12623
|
-
console.log(
|
|
12624
|
-
for (const w of plan2.warnings) console.log(
|
|
12798
|
+
console.log(chalk138.yellow("\nWarnings:"));
|
|
12799
|
+
for (const w of plan2.warnings) console.log(chalk138.yellow(` ${w}`));
|
|
12625
12800
|
}
|
|
12626
12801
|
if (plan2.newDirectories.length > 0) {
|
|
12627
|
-
console.log(
|
|
12802
|
+
console.log(chalk138.bold("\nNew directories:"));
|
|
12628
12803
|
for (const dir of plan2.newDirectories)
|
|
12629
|
-
console.log(
|
|
12804
|
+
console.log(chalk138.green(` ${dir}/`));
|
|
12630
12805
|
}
|
|
12631
12806
|
displayMoves(plan2);
|
|
12632
12807
|
displayRewrites(plan2.rewrites);
|
|
12633
12808
|
console.log(
|
|
12634
|
-
|
|
12809
|
+
chalk138.dim(
|
|
12635
12810
|
`
|
|
12636
12811
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
12637
12812
|
)
|
|
@@ -12641,18 +12816,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
12641
12816
|
// src/commands/refactor/restructure/executePlan.ts
|
|
12642
12817
|
import fs23 from "fs";
|
|
12643
12818
|
import path44 from "path";
|
|
12644
|
-
import
|
|
12819
|
+
import chalk139 from "chalk";
|
|
12645
12820
|
function executePlan(plan2) {
|
|
12646
12821
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
12647
12822
|
for (const [file, content] of updatedContents) {
|
|
12648
12823
|
fs23.writeFileSync(file, content, "utf-8");
|
|
12649
12824
|
console.log(
|
|
12650
|
-
|
|
12825
|
+
chalk139.cyan(` Rewrote imports in ${path44.relative(process.cwd(), file)}`)
|
|
12651
12826
|
);
|
|
12652
12827
|
}
|
|
12653
12828
|
for (const dir of plan2.newDirectories) {
|
|
12654
12829
|
fs23.mkdirSync(dir, { recursive: true });
|
|
12655
|
-
console.log(
|
|
12830
|
+
console.log(chalk139.green(` Created ${path44.relative(process.cwd(), dir)}/`));
|
|
12656
12831
|
}
|
|
12657
12832
|
for (const move of plan2.moves) {
|
|
12658
12833
|
const targetDir = path44.dirname(move.to);
|
|
@@ -12661,7 +12836,7 @@ function executePlan(plan2) {
|
|
|
12661
12836
|
}
|
|
12662
12837
|
fs23.renameSync(move.from, move.to);
|
|
12663
12838
|
console.log(
|
|
12664
|
-
|
|
12839
|
+
chalk139.white(
|
|
12665
12840
|
` Moved ${path44.relative(process.cwd(), move.from)} \u2192 ${path44.relative(process.cwd(), move.to)}`
|
|
12666
12841
|
)
|
|
12667
12842
|
);
|
|
@@ -12676,7 +12851,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
12676
12851
|
if (entries.length === 0) {
|
|
12677
12852
|
fs23.rmdirSync(dir);
|
|
12678
12853
|
console.log(
|
|
12679
|
-
|
|
12854
|
+
chalk139.dim(
|
|
12680
12855
|
` Removed empty directory ${path44.relative(process.cwd(), dir)}`
|
|
12681
12856
|
)
|
|
12682
12857
|
);
|
|
@@ -12809,22 +12984,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
12809
12984
|
const targetPattern = pattern2 ?? "src";
|
|
12810
12985
|
const files = findSourceFiles2(targetPattern);
|
|
12811
12986
|
if (files.length === 0) {
|
|
12812
|
-
console.log(
|
|
12987
|
+
console.log(chalk140.yellow("No files found matching pattern"));
|
|
12813
12988
|
return;
|
|
12814
12989
|
}
|
|
12815
12990
|
const tsConfigPath = path47.resolve("tsconfig.json");
|
|
12816
12991
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
12817
12992
|
if (plan2.moves.length === 0) {
|
|
12818
|
-
console.log(
|
|
12993
|
+
console.log(chalk140.green("No restructuring needed"));
|
|
12819
12994
|
return;
|
|
12820
12995
|
}
|
|
12821
12996
|
displayPlan2(plan2);
|
|
12822
12997
|
if (options2.apply) {
|
|
12823
|
-
console.log(
|
|
12998
|
+
console.log(chalk140.bold("\nApplying changes..."));
|
|
12824
12999
|
executePlan(plan2);
|
|
12825
|
-
console.log(
|
|
13000
|
+
console.log(chalk140.green("\nRestructuring complete"));
|
|
12826
13001
|
} else {
|
|
12827
|
-
console.log(
|
|
13002
|
+
console.log(chalk140.dim("\nDry run. Use --apply to execute."));
|
|
12828
13003
|
}
|
|
12829
13004
|
}
|
|
12830
13005
|
|
|
@@ -12863,6 +13038,9 @@ function registerRefactor(program2) {
|
|
|
12863
13038
|
registerRestructure(refactorCommand);
|
|
12864
13039
|
}
|
|
12865
13040
|
|
|
13041
|
+
// src/commands/review/review.ts
|
|
13042
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
13043
|
+
|
|
12866
13044
|
// src/commands/review/formatPriorComments.ts
|
|
12867
13045
|
function threadKey(c, byId) {
|
|
12868
13046
|
if (c.threadId) return c.threadId;
|
|
@@ -12936,23 +13114,6 @@ ${formatFiles(context.changedFiles)}
|
|
|
12936
13114
|
${priorBlock}
|
|
12937
13115
|
## Diff (PR #${context.prNumber}: ${context.baseSha}..${context.headSha})
|
|
12938
13116
|
|
|
12939
|
-
\`\`\`diff
|
|
12940
|
-
${context.diff.trimEnd()}
|
|
12941
|
-
\`\`\`
|
|
12942
|
-
`;
|
|
12943
|
-
}
|
|
12944
|
-
function buildShaRequest(context) {
|
|
12945
|
-
return `# Code review request
|
|
12946
|
-
|
|
12947
|
-
- Commit: \`${context.sha}\`
|
|
12948
|
-
- Parent: \`${context.parentSha}\`
|
|
12949
|
-
|
|
12950
|
-
## Changed files
|
|
12951
|
-
|
|
12952
|
-
${formatFiles(context.changedFiles)}
|
|
12953
|
-
|
|
12954
|
-
## Diff (commit ${context.sha}: ${context.parentSha}..${context.sha})
|
|
12955
|
-
|
|
12956
13117
|
\`\`\`diff
|
|
12957
13118
|
${context.diff.trimEnd()}
|
|
12958
13119
|
\`\`\`
|
|
@@ -13314,18 +13475,18 @@ async function postAndMaybeSubmit(lineBound, markdown, options2) {
|
|
|
13314
13475
|
}
|
|
13315
13476
|
|
|
13316
13477
|
// src/commands/review/warnUnlocated.ts
|
|
13317
|
-
import
|
|
13478
|
+
import chalk141 from "chalk";
|
|
13318
13479
|
function warnUnlocated(unlocated) {
|
|
13319
13480
|
if (unlocated.length === 0) return;
|
|
13320
13481
|
console.warn(
|
|
13321
|
-
|
|
13482
|
+
chalk141.yellow(
|
|
13322
13483
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
13323
13484
|
)
|
|
13324
13485
|
);
|
|
13325
13486
|
for (const finding of unlocated) {
|
|
13326
|
-
const where = finding.location ||
|
|
13487
|
+
const where = finding.location || chalk141.dim("missing");
|
|
13327
13488
|
console.warn(
|
|
13328
|
-
` ${
|
|
13489
|
+
` ${chalk141.yellow("\xB7")} ${finding.title} ${chalk141.dim(`(${where})`)}`
|
|
13329
13490
|
);
|
|
13330
13491
|
}
|
|
13331
13492
|
}
|
|
@@ -13465,6 +13626,29 @@ async function runApplySession(synthesisPath) {
|
|
|
13465
13626
|
await done2;
|
|
13466
13627
|
}
|
|
13467
13628
|
|
|
13629
|
+
// src/commands/review/runBacklogSession.ts
|
|
13630
|
+
function buildBacklogPrompt(synthesisPath) {
|
|
13631
|
+
return `/bug add each finding in ${synthesisPath} as a phase
|
|
13632
|
+
|
|
13633
|
+
Read ${synthesisPath}. It contains a list of findings under the \`## Findings\` heading, each in a \`### Finding:\` block with Severity, Source, Location, Impact, and Recommendation fields.
|
|
13634
|
+
|
|
13635
|
+
File ONE bug backlog item covering the review findings:
|
|
13636
|
+
- Include EVERY finding in the file as a phase on that single item \u2014 including findings whose Source is \`already-raised\`.
|
|
13637
|
+
- Each phase should be named after its finding's title and its tasks should capture the finding's Location, Impact, and Recommendation.
|
|
13638
|
+
- Use \`assist backlog add\` to create the item, then \`assist backlog add-phase\` for each finding.
|
|
13639
|
+
|
|
13640
|
+
Important constraints:
|
|
13641
|
+
- Do not edit ${synthesisPath} \u2014 leave it untouched.
|
|
13642
|
+
- Do not post anything to a PR.
|
|
13643
|
+
- Do not stage, commit, or push any changes.`;
|
|
13644
|
+
}
|
|
13645
|
+
async function runBacklogSession(synthesisPath) {
|
|
13646
|
+
const { done: done2 } = spawnClaude(buildBacklogPrompt(synthesisPath), {
|
|
13647
|
+
allowEdits: true
|
|
13648
|
+
});
|
|
13649
|
+
await done2;
|
|
13650
|
+
}
|
|
13651
|
+
|
|
13468
13652
|
// src/commands/review/cachedReviewerResult.ts
|
|
13469
13653
|
import { statSync as statSync2 } from "fs";
|
|
13470
13654
|
function cachedReviewerResult(name, outputPath) {
|
|
@@ -14381,6 +14565,10 @@ function setupReviewDir(repoRoot, context, force) {
|
|
|
14381
14565
|
return paths;
|
|
14382
14566
|
}
|
|
14383
14567
|
async function runPostSynthesis(synthesisPath, options2) {
|
|
14568
|
+
if (options2.backlog) {
|
|
14569
|
+
await runBacklogSession(synthesisPath);
|
|
14570
|
+
return;
|
|
14571
|
+
}
|
|
14384
14572
|
if (options2.apply) {
|
|
14385
14573
|
await runApplySession(synthesisPath);
|
|
14386
14574
|
return;
|
|
@@ -14401,58 +14589,6 @@ async function reviewPr(repoRoot, options2) {
|
|
|
14401
14589
|
console.log(`Done. Review folder: ${paths.reviewDir}`);
|
|
14402
14590
|
}
|
|
14403
14591
|
|
|
14404
|
-
// src/commands/review/gatherShaContext.ts
|
|
14405
|
-
import { execSync as execSync44 } from "child_process";
|
|
14406
|
-
function resolveSha(ref, format2) {
|
|
14407
|
-
const flag = format2 === "short" ? "--short=7 " : "";
|
|
14408
|
-
try {
|
|
14409
|
-
return execSync44(`git rev-parse --verify ${flag}${ref}^{commit}`, {
|
|
14410
|
-
encoding: "utf-8",
|
|
14411
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
14412
|
-
}).trim();
|
|
14413
|
-
} catch {
|
|
14414
|
-
console.error(`Error: could not resolve commit \`${ref}\`.`);
|
|
14415
|
-
process.exit(1);
|
|
14416
|
-
}
|
|
14417
|
-
}
|
|
14418
|
-
function gatherShaContext(ref) {
|
|
14419
|
-
const sha = resolveSha(ref, "long");
|
|
14420
|
-
const shortSha = resolveSha(sha, "short");
|
|
14421
|
-
const parentSha = resolveSha(`${sha}^`, "long");
|
|
14422
|
-
const range = `${parentSha}..${sha}`;
|
|
14423
|
-
const changedFiles = execSync44(`git diff --name-only ${range}`, {
|
|
14424
|
-
encoding: "utf-8",
|
|
14425
|
-
maxBuffer: 64 * 1024 * 1024
|
|
14426
|
-
}).trim().split("\n").filter(Boolean);
|
|
14427
|
-
const diff2 = execSync44(`git diff ${range}`, {
|
|
14428
|
-
encoding: "utf-8",
|
|
14429
|
-
maxBuffer: 256 * 1024 * 1024
|
|
14430
|
-
});
|
|
14431
|
-
return { sha, shortSha, parentSha, changedFiles, diff: diff2 };
|
|
14432
|
-
}
|
|
14433
|
-
|
|
14434
|
-
// src/commands/review/reviewSha.ts
|
|
14435
|
-
function gatherShaChangedContext(ref) {
|
|
14436
|
-
const context = gatherShaContext(ref);
|
|
14437
|
-
if (context.changedFiles.length > 0) return context;
|
|
14438
|
-
console.error(
|
|
14439
|
-
`Error: commit ${context.sha} has no changed files \u2014 nothing to review.`
|
|
14440
|
-
);
|
|
14441
|
-
process.exit(1);
|
|
14442
|
-
}
|
|
14443
|
-
function setupShaReviewDir(repoRoot, context, force) {
|
|
14444
|
-
const paths = buildReviewPaths(repoRoot, context.shortSha);
|
|
14445
|
-
prepareReviewDir(paths, buildShaRequest(context), force);
|
|
14446
|
-
console.log(`Review folder: ${paths.reviewDir}`);
|
|
14447
|
-
return paths;
|
|
14448
|
-
}
|
|
14449
|
-
async function reviewSha(repoRoot, options2) {
|
|
14450
|
-
const context = gatherShaChangedContext(options2.sha);
|
|
14451
|
-
const paths = setupShaReviewDir(repoRoot, context, options2.force ?? false);
|
|
14452
|
-
await runReviewPipeline(paths, { verbose: options2.verbose ?? false });
|
|
14453
|
-
console.log(`Done. Review folder: ${paths.reviewDir}`);
|
|
14454
|
-
}
|
|
14455
|
-
|
|
14456
14592
|
// src/commands/review/review.ts
|
|
14457
14593
|
function resolveRepoRoot() {
|
|
14458
14594
|
const repoRoot = findRepoRoot(process.cwd());
|
|
@@ -14460,41 +14596,40 @@ function resolveRepoRoot() {
|
|
|
14460
14596
|
console.error("Error: not inside a git repository.");
|
|
14461
14597
|
process.exit(1);
|
|
14462
14598
|
}
|
|
14463
|
-
function rejectShaFlag(flag) {
|
|
14464
|
-
console.error(`Error: ${flag} cannot be combined with a SHA argument.`);
|
|
14465
|
-
process.exit(1);
|
|
14466
|
-
}
|
|
14467
14599
|
function validateOptions(options2) {
|
|
14468
14600
|
if (options2.apply && options2.refine) {
|
|
14469
14601
|
console.error("Error: --apply cannot be combined with --refine.");
|
|
14470
14602
|
process.exit(1);
|
|
14471
14603
|
}
|
|
14472
|
-
if (
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
|
|
14604
|
+
if (options2.backlog && (options2.refine || options2.apply)) {
|
|
14605
|
+
console.error(
|
|
14606
|
+
"Error: --backlog cannot be combined with --refine or --apply."
|
|
14607
|
+
);
|
|
14608
|
+
process.exit(1);
|
|
14609
|
+
}
|
|
14610
|
+
}
|
|
14611
|
+
function checkoutPr(number) {
|
|
14612
|
+
try {
|
|
14613
|
+
execFileSync6("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
14614
|
+
} catch {
|
|
14615
|
+
console.error(`gh pr checkout ${number} failed; aborting.`);
|
|
14616
|
+
process.exit(1);
|
|
14617
|
+
}
|
|
14476
14618
|
}
|
|
14477
14619
|
async function review(options2 = {}) {
|
|
14478
14620
|
validateOptions(options2);
|
|
14479
14621
|
const repoRoot = resolveRepoRoot();
|
|
14480
|
-
if (options2.
|
|
14481
|
-
await reviewSha(repoRoot, {
|
|
14482
|
-
sha: options2.sha,
|
|
14483
|
-
force: options2.force,
|
|
14484
|
-
verbose: options2.verbose
|
|
14485
|
-
});
|
|
14486
|
-
return;
|
|
14487
|
-
}
|
|
14622
|
+
if (options2.number) checkoutPr(options2.number);
|
|
14488
14623
|
await reviewPr(repoRoot, options2);
|
|
14489
14624
|
}
|
|
14490
14625
|
|
|
14491
14626
|
// src/commands/registerReview.ts
|
|
14492
14627
|
function registerReview(program2) {
|
|
14493
14628
|
program2.command("review").description(
|
|
14494
|
-
"Run Claude and Codex in parallel to review the current branch, or a
|
|
14629
|
+
"Run Claude and Codex in parallel to review the current branch's PR, or check out a PR by number first when given"
|
|
14495
14630
|
).argument(
|
|
14496
|
-
"[
|
|
14497
|
-
"Optional
|
|
14631
|
+
"[number]",
|
|
14632
|
+
"Optional PR number; when provided, runs `gh pr checkout <number>` before reviewing"
|
|
14498
14633
|
).option(
|
|
14499
14634
|
"--no-prompt",
|
|
14500
14635
|
"Skip confirmation prompts; use flag defaults non-interactively"
|
|
@@ -14510,16 +14645,19 @@ function registerReview(program2) {
|
|
|
14510
14645
|
).option(
|
|
14511
14646
|
"--apply",
|
|
14512
14647
|
"After synthesis, launch an interactive Claude session to apply fixes for each finding; applied findings are removed from synthesis, skipped ones remain for a later post"
|
|
14648
|
+
).option(
|
|
14649
|
+
"--backlog",
|
|
14650
|
+
"After synthesis, launch an interactive Claude session running /bug to file all findings as a single backlog item with one phase per finding, instead of posting to the PR"
|
|
14513
14651
|
).option(
|
|
14514
14652
|
"--verbose",
|
|
14515
14653
|
"Disable spinner UI and use per-line log output (per-tool lines, starting/done lines)"
|
|
14516
14654
|
).action(
|
|
14517
|
-
(
|
|
14655
|
+
(number, options2) => review({ ...options2, number })
|
|
14518
14656
|
);
|
|
14519
14657
|
}
|
|
14520
14658
|
|
|
14521
14659
|
// src/commands/seq/seqAuth.ts
|
|
14522
|
-
import
|
|
14660
|
+
import chalk143 from "chalk";
|
|
14523
14661
|
|
|
14524
14662
|
// src/commands/seq/loadConnections.ts
|
|
14525
14663
|
function loadConnections2() {
|
|
@@ -14548,10 +14686,10 @@ function setDefaultConnection(name) {
|
|
|
14548
14686
|
}
|
|
14549
14687
|
|
|
14550
14688
|
// src/shared/assertUniqueName.ts
|
|
14551
|
-
import
|
|
14689
|
+
import chalk142 from "chalk";
|
|
14552
14690
|
function assertUniqueName(existingNames, name) {
|
|
14553
14691
|
if (existingNames.includes(name)) {
|
|
14554
|
-
console.error(
|
|
14692
|
+
console.error(chalk142.red(`Connection "${name}" already exists.`));
|
|
14555
14693
|
process.exit(1);
|
|
14556
14694
|
}
|
|
14557
14695
|
}
|
|
@@ -14569,16 +14707,16 @@ async function promptConnection2(existingNames) {
|
|
|
14569
14707
|
var seqAuth = createConnectionAuth({
|
|
14570
14708
|
load: loadConnections2,
|
|
14571
14709
|
save: saveConnections2,
|
|
14572
|
-
format: (c) => `${
|
|
14710
|
+
format: (c) => `${chalk143.bold(c.name)} ${c.url}`,
|
|
14573
14711
|
promptNew: promptConnection2,
|
|
14574
14712
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
14575
14713
|
});
|
|
14576
14714
|
|
|
14577
14715
|
// src/commands/seq/seqQuery.ts
|
|
14578
|
-
import
|
|
14716
|
+
import chalk147 from "chalk";
|
|
14579
14717
|
|
|
14580
14718
|
// src/commands/seq/fetchSeq.ts
|
|
14581
|
-
import
|
|
14719
|
+
import chalk144 from "chalk";
|
|
14582
14720
|
async function fetchSeq(conn, path52, params) {
|
|
14583
14721
|
const url = `${conn.url}${path52}?${params}`;
|
|
14584
14722
|
const response = await fetch(url, {
|
|
@@ -14589,7 +14727,7 @@ async function fetchSeq(conn, path52, params) {
|
|
|
14589
14727
|
});
|
|
14590
14728
|
if (!response.ok) {
|
|
14591
14729
|
const body = await response.text();
|
|
14592
|
-
console.error(
|
|
14730
|
+
console.error(chalk144.red(`Seq returned ${response.status}: ${body}`));
|
|
14593
14731
|
process.exit(1);
|
|
14594
14732
|
}
|
|
14595
14733
|
return response;
|
|
@@ -14644,23 +14782,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
14644
14782
|
}
|
|
14645
14783
|
|
|
14646
14784
|
// src/commands/seq/formatEvent.ts
|
|
14647
|
-
import
|
|
14785
|
+
import chalk145 from "chalk";
|
|
14648
14786
|
function levelColor(level) {
|
|
14649
14787
|
switch (level) {
|
|
14650
14788
|
case "Fatal":
|
|
14651
|
-
return
|
|
14789
|
+
return chalk145.bgRed.white;
|
|
14652
14790
|
case "Error":
|
|
14653
|
-
return
|
|
14791
|
+
return chalk145.red;
|
|
14654
14792
|
case "Warning":
|
|
14655
|
-
return
|
|
14793
|
+
return chalk145.yellow;
|
|
14656
14794
|
case "Information":
|
|
14657
|
-
return
|
|
14795
|
+
return chalk145.cyan;
|
|
14658
14796
|
case "Debug":
|
|
14659
|
-
return
|
|
14797
|
+
return chalk145.gray;
|
|
14660
14798
|
case "Verbose":
|
|
14661
|
-
return
|
|
14799
|
+
return chalk145.dim;
|
|
14662
14800
|
default:
|
|
14663
|
-
return
|
|
14801
|
+
return chalk145.white;
|
|
14664
14802
|
}
|
|
14665
14803
|
}
|
|
14666
14804
|
function levelAbbrev(level) {
|
|
@@ -14701,12 +14839,12 @@ function formatTimestamp(iso) {
|
|
|
14701
14839
|
function formatEvent(event) {
|
|
14702
14840
|
const color = levelColor(event.Level);
|
|
14703
14841
|
const abbrev = levelAbbrev(event.Level);
|
|
14704
|
-
const ts8 =
|
|
14842
|
+
const ts8 = chalk145.dim(formatTimestamp(event.Timestamp));
|
|
14705
14843
|
const msg = renderMessage(event);
|
|
14706
14844
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
14707
14845
|
if (event.Exception) {
|
|
14708
14846
|
for (const line of event.Exception.split("\n")) {
|
|
14709
|
-
lines.push(
|
|
14847
|
+
lines.push(chalk145.red(` ${line}`));
|
|
14710
14848
|
}
|
|
14711
14849
|
}
|
|
14712
14850
|
return lines.join("\n");
|
|
@@ -14739,11 +14877,11 @@ function rejectTimestampFilter(filter) {
|
|
|
14739
14877
|
}
|
|
14740
14878
|
|
|
14741
14879
|
// src/shared/resolveNamedConnection.ts
|
|
14742
|
-
import
|
|
14880
|
+
import chalk146 from "chalk";
|
|
14743
14881
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
14744
14882
|
if (connections.length === 0) {
|
|
14745
14883
|
console.error(
|
|
14746
|
-
|
|
14884
|
+
chalk146.red(
|
|
14747
14885
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
14748
14886
|
)
|
|
14749
14887
|
);
|
|
@@ -14752,7 +14890,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
14752
14890
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
14753
14891
|
const connection = connections.find((c) => c.name === target);
|
|
14754
14892
|
if (!connection) {
|
|
14755
|
-
console.error(
|
|
14893
|
+
console.error(chalk146.red(`${kind} connection "${target}" not found.`));
|
|
14756
14894
|
process.exit(1);
|
|
14757
14895
|
}
|
|
14758
14896
|
return connection;
|
|
@@ -14781,7 +14919,7 @@ async function seqQuery(filter, options2) {
|
|
|
14781
14919
|
new URLSearchParams({ filter, count: String(count6) })
|
|
14782
14920
|
);
|
|
14783
14921
|
if (events.length === 0) {
|
|
14784
|
-
console.log(
|
|
14922
|
+
console.log(chalk147.yellow("No events found."));
|
|
14785
14923
|
return;
|
|
14786
14924
|
}
|
|
14787
14925
|
if (options2.json) {
|
|
@@ -14792,11 +14930,11 @@ async function seqQuery(filter, options2) {
|
|
|
14792
14930
|
for (const event of chronological) {
|
|
14793
14931
|
console.log(formatEvent(event));
|
|
14794
14932
|
}
|
|
14795
|
-
console.log(
|
|
14933
|
+
console.log(chalk147.dim(`
|
|
14796
14934
|
${events.length} events`));
|
|
14797
14935
|
if (events.length >= count6) {
|
|
14798
14936
|
console.log(
|
|
14799
|
-
|
|
14937
|
+
chalk147.yellow(
|
|
14800
14938
|
`Results limited to ${count6}. Use --count to retrieve more.`
|
|
14801
14939
|
)
|
|
14802
14940
|
);
|
|
@@ -14804,10 +14942,10 @@ ${events.length} events`));
|
|
|
14804
14942
|
}
|
|
14805
14943
|
|
|
14806
14944
|
// src/shared/setNamedDefaultConnection.ts
|
|
14807
|
-
import
|
|
14945
|
+
import chalk148 from "chalk";
|
|
14808
14946
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
14809
14947
|
if (!connections.find((c) => c.name === name)) {
|
|
14810
|
-
console.error(
|
|
14948
|
+
console.error(chalk148.red(`Connection "${name}" not found.`));
|
|
14811
14949
|
process.exit(1);
|
|
14812
14950
|
}
|
|
14813
14951
|
setDefault(name);
|
|
@@ -14851,7 +14989,7 @@ function registerSignal(program2) {
|
|
|
14851
14989
|
}
|
|
14852
14990
|
|
|
14853
14991
|
// src/commands/sql/sqlAuth.ts
|
|
14854
|
-
import
|
|
14992
|
+
import chalk150 from "chalk";
|
|
14855
14993
|
|
|
14856
14994
|
// src/commands/sql/loadConnections.ts
|
|
14857
14995
|
function loadConnections3() {
|
|
@@ -14880,7 +15018,7 @@ function setDefaultConnection2(name) {
|
|
|
14880
15018
|
}
|
|
14881
15019
|
|
|
14882
15020
|
// src/commands/sql/promptConnection.ts
|
|
14883
|
-
import
|
|
15021
|
+
import chalk149 from "chalk";
|
|
14884
15022
|
async function promptConnection3(existingNames) {
|
|
14885
15023
|
const name = await promptInput("name", "Connection name:", "default");
|
|
14886
15024
|
assertUniqueName(existingNames, name);
|
|
@@ -14888,7 +15026,7 @@ async function promptConnection3(existingNames) {
|
|
|
14888
15026
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
14889
15027
|
const port = Number.parseInt(portStr, 10);
|
|
14890
15028
|
if (!Number.isFinite(port)) {
|
|
14891
|
-
console.error(
|
|
15029
|
+
console.error(chalk149.red(`Invalid port "${portStr}".`));
|
|
14892
15030
|
process.exit(1);
|
|
14893
15031
|
}
|
|
14894
15032
|
const user = await promptInput("user", "User:");
|
|
@@ -14901,13 +15039,13 @@ async function promptConnection3(existingNames) {
|
|
|
14901
15039
|
var sqlAuth = createConnectionAuth({
|
|
14902
15040
|
load: loadConnections3,
|
|
14903
15041
|
save: saveConnections3,
|
|
14904
|
-
format: (c) => `${
|
|
15042
|
+
format: (c) => `${chalk150.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
14905
15043
|
promptNew: promptConnection3,
|
|
14906
15044
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
14907
15045
|
});
|
|
14908
15046
|
|
|
14909
15047
|
// src/commands/sql/printTable.ts
|
|
14910
|
-
import
|
|
15048
|
+
import chalk151 from "chalk";
|
|
14911
15049
|
function formatCell(value) {
|
|
14912
15050
|
if (value === null || value === void 0) return "";
|
|
14913
15051
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -14916,7 +15054,7 @@ function formatCell(value) {
|
|
|
14916
15054
|
}
|
|
14917
15055
|
function printTable(rows) {
|
|
14918
15056
|
if (rows.length === 0) {
|
|
14919
|
-
console.log(
|
|
15057
|
+
console.log(chalk151.yellow("(no rows)"));
|
|
14920
15058
|
return;
|
|
14921
15059
|
}
|
|
14922
15060
|
const columns = Object.keys(rows[0]);
|
|
@@ -14924,13 +15062,13 @@ function printTable(rows) {
|
|
|
14924
15062
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
14925
15063
|
);
|
|
14926
15064
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
14927
|
-
console.log(
|
|
14928
|
-
console.log(
|
|
15065
|
+
console.log(chalk151.dim(header));
|
|
15066
|
+
console.log(chalk151.dim("-".repeat(header.length)));
|
|
14929
15067
|
for (const row of rows) {
|
|
14930
15068
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
14931
15069
|
console.log(line);
|
|
14932
15070
|
}
|
|
14933
|
-
console.log(
|
|
15071
|
+
console.log(chalk151.dim(`
|
|
14934
15072
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
14935
15073
|
}
|
|
14936
15074
|
|
|
@@ -14990,7 +15128,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
14990
15128
|
}
|
|
14991
15129
|
|
|
14992
15130
|
// src/commands/sql/sqlMutate.ts
|
|
14993
|
-
import
|
|
15131
|
+
import chalk152 from "chalk";
|
|
14994
15132
|
|
|
14995
15133
|
// src/commands/sql/isMutation.ts
|
|
14996
15134
|
var MUTATION_KEYWORDS = [
|
|
@@ -15024,7 +15162,7 @@ function isMutation(sql4) {
|
|
|
15024
15162
|
async function sqlMutate(query, connectionName) {
|
|
15025
15163
|
if (!isMutation(query)) {
|
|
15026
15164
|
console.error(
|
|
15027
|
-
|
|
15165
|
+
chalk152.red(
|
|
15028
15166
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
15029
15167
|
)
|
|
15030
15168
|
);
|
|
@@ -15034,18 +15172,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
15034
15172
|
const pool = await sqlConnect(conn);
|
|
15035
15173
|
try {
|
|
15036
15174
|
const result = await pool.request().query(query);
|
|
15037
|
-
console.log(
|
|
15175
|
+
console.log(chalk152.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
15038
15176
|
} finally {
|
|
15039
15177
|
await pool.close();
|
|
15040
15178
|
}
|
|
15041
15179
|
}
|
|
15042
15180
|
|
|
15043
15181
|
// src/commands/sql/sqlQuery.ts
|
|
15044
|
-
import
|
|
15182
|
+
import chalk153 from "chalk";
|
|
15045
15183
|
async function sqlQuery(query, connectionName) {
|
|
15046
15184
|
if (isMutation(query)) {
|
|
15047
15185
|
console.error(
|
|
15048
|
-
|
|
15186
|
+
chalk153.red(
|
|
15049
15187
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
15050
15188
|
)
|
|
15051
15189
|
);
|
|
@@ -15060,7 +15198,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
15060
15198
|
printTable(rows);
|
|
15061
15199
|
} else {
|
|
15062
15200
|
console.log(
|
|
15063
|
-
|
|
15201
|
+
chalk153.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
15064
15202
|
);
|
|
15065
15203
|
}
|
|
15066
15204
|
} finally {
|
|
@@ -15640,14 +15778,14 @@ import {
|
|
|
15640
15778
|
import { dirname as dirname22, join as join40 } from "path";
|
|
15641
15779
|
|
|
15642
15780
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
15643
|
-
import
|
|
15781
|
+
import chalk154 from "chalk";
|
|
15644
15782
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
15645
15783
|
function validateStagedContent(filename, content) {
|
|
15646
15784
|
const firstLine = content.split("\n")[0];
|
|
15647
15785
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
15648
15786
|
if (!match) {
|
|
15649
15787
|
console.error(
|
|
15650
|
-
|
|
15788
|
+
chalk154.red(
|
|
15651
15789
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
15652
15790
|
)
|
|
15653
15791
|
);
|
|
@@ -15656,7 +15794,7 @@ function validateStagedContent(filename, content) {
|
|
|
15656
15794
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
15657
15795
|
if (!contentAfterLink) {
|
|
15658
15796
|
console.error(
|
|
15659
|
-
|
|
15797
|
+
chalk154.red(
|
|
15660
15798
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
15661
15799
|
)
|
|
15662
15800
|
);
|
|
@@ -15859,7 +15997,7 @@ import { mkdirSync as mkdirSync14 } from "fs";
|
|
|
15859
15997
|
import { join as join45 } from "path";
|
|
15860
15998
|
|
|
15861
15999
|
// src/commands/voice/checkLockFile.ts
|
|
15862
|
-
import { execSync as
|
|
16000
|
+
import { execSync as execSync44 } from "child_process";
|
|
15863
16001
|
import { existsSync as existsSync44, mkdirSync as mkdirSync13, readFileSync as readFileSync34, writeFileSync as writeFileSync27 } from "fs";
|
|
15864
16002
|
import { join as join44 } from "path";
|
|
15865
16003
|
function isProcessAlive2(pid) {
|
|
@@ -15888,7 +16026,7 @@ function bootstrapVenv() {
|
|
|
15888
16026
|
if (existsSync44(getVenvPython())) return;
|
|
15889
16027
|
console.log("Setting up Python environment...");
|
|
15890
16028
|
const pythonDir = getPythonDir();
|
|
15891
|
-
|
|
16029
|
+
execSync44(
|
|
15892
16030
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
15893
16031
|
{
|
|
15894
16032
|
stdio: "inherit",
|
|
@@ -16052,14 +16190,14 @@ function registerVoice(program2) {
|
|
|
16052
16190
|
|
|
16053
16191
|
// src/commands/roam/auth.ts
|
|
16054
16192
|
import { randomBytes } from "crypto";
|
|
16055
|
-
import
|
|
16193
|
+
import chalk155 from "chalk";
|
|
16056
16194
|
|
|
16057
16195
|
// src/lib/openBrowser.ts
|
|
16058
|
-
import { execSync as
|
|
16196
|
+
import { execSync as execSync45 } from "child_process";
|
|
16059
16197
|
function tryExec(commands) {
|
|
16060
16198
|
for (const cmd of commands) {
|
|
16061
16199
|
try {
|
|
16062
|
-
|
|
16200
|
+
execSync45(cmd);
|
|
16063
16201
|
return true;
|
|
16064
16202
|
} catch {
|
|
16065
16203
|
}
|
|
@@ -16227,13 +16365,13 @@ async function auth() {
|
|
|
16227
16365
|
saveGlobalConfig(config);
|
|
16228
16366
|
const state = randomBytes(16).toString("hex");
|
|
16229
16367
|
console.log(
|
|
16230
|
-
|
|
16368
|
+
chalk155.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
16231
16369
|
);
|
|
16232
|
-
console.log(
|
|
16233
|
-
console.log(
|
|
16234
|
-
console.log(
|
|
16370
|
+
console.log(chalk155.white("http://localhost:14523/callback\n"));
|
|
16371
|
+
console.log(chalk155.blue("Opening browser for authorization..."));
|
|
16372
|
+
console.log(chalk155.dim("Waiting for authorization callback..."));
|
|
16235
16373
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
16236
|
-
console.log(
|
|
16374
|
+
console.log(chalk155.dim("Exchanging code for tokens..."));
|
|
16237
16375
|
const tokens = await exchangeToken({
|
|
16238
16376
|
code,
|
|
16239
16377
|
clientId,
|
|
@@ -16249,12 +16387,12 @@ async function auth() {
|
|
|
16249
16387
|
};
|
|
16250
16388
|
saveGlobalConfig(config);
|
|
16251
16389
|
console.log(
|
|
16252
|
-
|
|
16390
|
+
chalk155.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
16253
16391
|
);
|
|
16254
16392
|
}
|
|
16255
16393
|
|
|
16256
16394
|
// src/commands/roam/postRoamActivity.ts
|
|
16257
|
-
import { execFileSync as
|
|
16395
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
16258
16396
|
import { readdirSync as readdirSync7, readFileSync as readFileSync37, statSync as statSync4 } from "fs";
|
|
16259
16397
|
import { join as join47 } from "path";
|
|
16260
16398
|
function findPortFile(roamDir) {
|
|
@@ -16287,7 +16425,7 @@ function postRoamActivity(app, event) {
|
|
|
16287
16425
|
}
|
|
16288
16426
|
const url = `http://127.0.0.1:${port}/api/v1/activity/${app}/${event}?pid=${app === "codex" ? 99998 : 99999}`;
|
|
16289
16427
|
try {
|
|
16290
|
-
|
|
16428
|
+
execFileSync7("curl", ["-sf", "--max-time", "0.2", "-X", "POST", url], {
|
|
16291
16429
|
stdio: "ignore"
|
|
16292
16430
|
});
|
|
16293
16431
|
} catch {
|
|
@@ -16401,11 +16539,11 @@ function resolveParams(params, cliArgs) {
|
|
|
16401
16539
|
}
|
|
16402
16540
|
|
|
16403
16541
|
// src/commands/run/runPreCommands.ts
|
|
16404
|
-
import { execSync as
|
|
16542
|
+
import { execSync as execSync46 } from "child_process";
|
|
16405
16543
|
function runPreCommands(pre, cwd) {
|
|
16406
16544
|
for (const cmd of pre) {
|
|
16407
16545
|
try {
|
|
16408
|
-
|
|
16546
|
+
execSync46(cmd, { stdio: "inherit", cwd });
|
|
16409
16547
|
} catch (err) {
|
|
16410
16548
|
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
16411
16549
|
process.exit(code);
|
|
@@ -16414,13 +16552,13 @@ function runPreCommands(pre, cwd) {
|
|
|
16414
16552
|
}
|
|
16415
16553
|
|
|
16416
16554
|
// src/commands/run/spawnRunCommand.ts
|
|
16417
|
-
import { execFileSync as
|
|
16555
|
+
import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
|
|
16418
16556
|
import { existsSync as existsSync47 } from "fs";
|
|
16419
16557
|
import { dirname as dirname25, join as join48, resolve as resolve11 } from "path";
|
|
16420
16558
|
function resolveCommand2(command) {
|
|
16421
16559
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
16422
16560
|
try {
|
|
16423
|
-
const gitPath =
|
|
16561
|
+
const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
16424
16562
|
const gitRoot = resolve11(dirname25(gitPath), "..");
|
|
16425
16563
|
const gitBash = join48(gitRoot, "bin", "bash.exe");
|
|
16426
16564
|
if (existsSync47(gitBash)) return gitBash;
|
|
@@ -16668,11 +16806,11 @@ function registerRun(program2) {
|
|
|
16668
16806
|
}
|
|
16669
16807
|
|
|
16670
16808
|
// src/commands/screenshot/index.ts
|
|
16671
|
-
import { execSync as
|
|
16809
|
+
import { execSync as execSync47 } from "child_process";
|
|
16672
16810
|
import { existsSync as existsSync49, mkdirSync as mkdirSync17, unlinkSync as unlinkSync15, writeFileSync as writeFileSync30 } from "fs";
|
|
16673
16811
|
import { tmpdir as tmpdir7 } from "os";
|
|
16674
16812
|
import { join as join51, resolve as resolve13 } from "path";
|
|
16675
|
-
import
|
|
16813
|
+
import chalk156 from "chalk";
|
|
16676
16814
|
|
|
16677
16815
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
16678
16816
|
var captureWindowPs1 = `
|
|
@@ -16811,7 +16949,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
16811
16949
|
const scriptPath = join51(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
16812
16950
|
writeFileSync30(scriptPath, captureWindowPs1, "utf-8");
|
|
16813
16951
|
try {
|
|
16814
|
-
|
|
16952
|
+
execSync47(
|
|
16815
16953
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
16816
16954
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
16817
16955
|
);
|
|
@@ -16823,20 +16961,20 @@ function screenshot(processName) {
|
|
|
16823
16961
|
const config = loadConfig();
|
|
16824
16962
|
const outputDir = resolve13(config.screenshot.outputDir);
|
|
16825
16963
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
16826
|
-
console.log(
|
|
16964
|
+
console.log(chalk156.gray(`Capturing window for process "${processName}" ...`));
|
|
16827
16965
|
try {
|
|
16828
16966
|
runPowerShellScript(processName, outputPath);
|
|
16829
|
-
console.log(
|
|
16967
|
+
console.log(chalk156.green(`Screenshot saved: ${outputPath}`));
|
|
16830
16968
|
} catch (error) {
|
|
16831
16969
|
const msg = error instanceof Error ? error.message : String(error);
|
|
16832
|
-
console.error(
|
|
16970
|
+
console.error(chalk156.red(`Failed to capture screenshot: ${msg}`));
|
|
16833
16971
|
process.exit(1);
|
|
16834
16972
|
}
|
|
16835
16973
|
}
|
|
16836
16974
|
|
|
16837
16975
|
// src/commands/sessions/summarise/index.ts
|
|
16838
16976
|
import * as fs28 from "fs";
|
|
16839
|
-
import
|
|
16977
|
+
import chalk157 from "chalk";
|
|
16840
16978
|
|
|
16841
16979
|
// src/commands/sessions/summarise/shared.ts
|
|
16842
16980
|
import * as fs26 from "fs";
|
|
@@ -16852,7 +16990,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
16852
16990
|
}
|
|
16853
16991
|
|
|
16854
16992
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
16855
|
-
import { execFileSync as
|
|
16993
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
16856
16994
|
|
|
16857
16995
|
// src/commands/sessions/summarise/iterateUserMessages.ts
|
|
16858
16996
|
import * as fs27 from "fs";
|
|
@@ -16929,7 +17067,7 @@ function summariseSession(jsonlPath2) {
|
|
|
16929
17067
|
}
|
|
16930
17068
|
const prompt = buildPrompt2(firstMessage, backlogIds);
|
|
16931
17069
|
try {
|
|
16932
|
-
const output =
|
|
17070
|
+
const output = execFileSync9("claude", ["-p", "--model", "haiku", prompt], {
|
|
16933
17071
|
encoding: "utf8",
|
|
16934
17072
|
timeout: 3e4,
|
|
16935
17073
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -16963,22 +17101,22 @@ ${firstMessage}`);
|
|
|
16963
17101
|
async function summarise4(options2) {
|
|
16964
17102
|
const files = await discoverSessionJsonlPaths();
|
|
16965
17103
|
if (files.length === 0) {
|
|
16966
|
-
console.log(
|
|
17104
|
+
console.log(chalk157.yellow("No sessions found."));
|
|
16967
17105
|
return;
|
|
16968
17106
|
}
|
|
16969
17107
|
const toProcess = selectCandidates(files, options2);
|
|
16970
17108
|
if (toProcess.length === 0) {
|
|
16971
|
-
console.log(
|
|
17109
|
+
console.log(chalk157.green("All sessions already summarised."));
|
|
16972
17110
|
return;
|
|
16973
17111
|
}
|
|
16974
17112
|
console.log(
|
|
16975
|
-
|
|
17113
|
+
chalk157.cyan(
|
|
16976
17114
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
16977
17115
|
)
|
|
16978
17116
|
);
|
|
16979
17117
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
16980
17118
|
console.log(
|
|
16981
|
-
|
|
17119
|
+
chalk157.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk157.yellow(`, ${failed2} skipped`) : "")
|
|
16982
17120
|
);
|
|
16983
17121
|
}
|
|
16984
17122
|
function selectCandidates(files, options2) {
|
|
@@ -16998,16 +17136,16 @@ function processSessions(files) {
|
|
|
16998
17136
|
let failed2 = 0;
|
|
16999
17137
|
for (let i = 0; i < files.length; i++) {
|
|
17000
17138
|
const file = files[i];
|
|
17001
|
-
process.stdout.write(
|
|
17139
|
+
process.stdout.write(chalk157.dim(` [${i + 1}/${files.length}] `));
|
|
17002
17140
|
const summary = summariseSession(file);
|
|
17003
17141
|
if (summary) {
|
|
17004
17142
|
writeSummary(file, summary);
|
|
17005
17143
|
succeeded++;
|
|
17006
|
-
process.stdout.write(`${
|
|
17144
|
+
process.stdout.write(`${chalk157.green("\u2713")} ${summary}
|
|
17007
17145
|
`);
|
|
17008
17146
|
} else {
|
|
17009
17147
|
failed2++;
|
|
17010
|
-
process.stdout.write(` ${
|
|
17148
|
+
process.stdout.write(` ${chalk157.yellow("skip")}
|
|
17011
17149
|
`);
|
|
17012
17150
|
}
|
|
17013
17151
|
}
|
|
@@ -17022,10 +17160,10 @@ function registerSessions(program2) {
|
|
|
17022
17160
|
}
|
|
17023
17161
|
|
|
17024
17162
|
// src/commands/statusLine.ts
|
|
17025
|
-
import
|
|
17163
|
+
import chalk159 from "chalk";
|
|
17026
17164
|
|
|
17027
17165
|
// src/commands/buildLimitsSegment.ts
|
|
17028
|
-
import
|
|
17166
|
+
import chalk158 from "chalk";
|
|
17029
17167
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
17030
17168
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
17031
17169
|
function formatTimeLeft(resetsAt) {
|
|
@@ -17048,10 +17186,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
17048
17186
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
17049
17187
|
const label2 = `${Math.round(pct)}%`;
|
|
17050
17188
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
17051
|
-
if (projected == null) return
|
|
17052
|
-
if (projected > 100) return
|
|
17053
|
-
if (projected > 75) return
|
|
17054
|
-
return
|
|
17189
|
+
if (projected == null) return chalk158.green(label2);
|
|
17190
|
+
if (projected > 100) return chalk158.red(label2);
|
|
17191
|
+
if (projected > 75) return chalk158.yellow(label2);
|
|
17192
|
+
return chalk158.green(label2);
|
|
17055
17193
|
}
|
|
17056
17194
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
17057
17195
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -17077,14 +17215,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
17077
17215
|
}
|
|
17078
17216
|
|
|
17079
17217
|
// src/commands/statusLine.ts
|
|
17080
|
-
|
|
17218
|
+
chalk159.level = 3;
|
|
17081
17219
|
function formatNumber(num) {
|
|
17082
17220
|
return num.toLocaleString("en-US");
|
|
17083
17221
|
}
|
|
17084
17222
|
function colorizePercent(pct) {
|
|
17085
17223
|
const label2 = `${Math.round(pct)}%`;
|
|
17086
|
-
if (pct > 80) return
|
|
17087
|
-
if (pct > 40) return
|
|
17224
|
+
if (pct > 80) return chalk159.red(label2);
|
|
17225
|
+
if (pct > 40) return chalk159.yellow(label2);
|
|
17088
17226
|
return label2;
|
|
17089
17227
|
}
|
|
17090
17228
|
async function statusLine() {
|
|
@@ -17107,7 +17245,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
17107
17245
|
// src/commands/sync/syncClaudeMd.ts
|
|
17108
17246
|
import * as fs29 from "fs";
|
|
17109
17247
|
import * as path48 from "path";
|
|
17110
|
-
import
|
|
17248
|
+
import chalk160 from "chalk";
|
|
17111
17249
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
17112
17250
|
const source = path48.join(claudeDir, "CLAUDE.md");
|
|
17113
17251
|
const target = path48.join(targetBase, "CLAUDE.md");
|
|
@@ -17116,12 +17254,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
17116
17254
|
const targetContent = fs29.readFileSync(target, "utf-8");
|
|
17117
17255
|
if (sourceContent !== targetContent) {
|
|
17118
17256
|
console.log(
|
|
17119
|
-
|
|
17257
|
+
chalk160.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
17120
17258
|
);
|
|
17121
17259
|
console.log();
|
|
17122
17260
|
printDiff(targetContent, sourceContent);
|
|
17123
17261
|
const confirm = options2?.yes || await promptConfirm(
|
|
17124
|
-
|
|
17262
|
+
chalk160.red("Overwrite existing CLAUDE.md?"),
|
|
17125
17263
|
false
|
|
17126
17264
|
);
|
|
17127
17265
|
if (!confirm) {
|
|
@@ -17137,7 +17275,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
17137
17275
|
// src/commands/sync/syncSettings.ts
|
|
17138
17276
|
import * as fs30 from "fs";
|
|
17139
17277
|
import * as path49 from "path";
|
|
17140
|
-
import
|
|
17278
|
+
import chalk161 from "chalk";
|
|
17141
17279
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
17142
17280
|
const source = path49.join(claudeDir, "settings.json");
|
|
17143
17281
|
const target = path49.join(targetBase, "settings.json");
|
|
@@ -17153,14 +17291,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
17153
17291
|
if (mergedContent !== normalizedTarget) {
|
|
17154
17292
|
if (!options2?.yes) {
|
|
17155
17293
|
console.log(
|
|
17156
|
-
|
|
17294
|
+
chalk161.yellow(
|
|
17157
17295
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
17158
17296
|
)
|
|
17159
17297
|
);
|
|
17160
17298
|
console.log();
|
|
17161
17299
|
printDiff(targetContent, mergedContent);
|
|
17162
17300
|
const confirm = await promptConfirm(
|
|
17163
|
-
|
|
17301
|
+
chalk161.red("Overwrite existing settings.json?"),
|
|
17164
17302
|
false
|
|
17165
17303
|
);
|
|
17166
17304
|
if (!confirm) {
|
|
@@ -17199,7 +17337,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
17199
17337
|
}
|
|
17200
17338
|
|
|
17201
17339
|
// src/commands/update.ts
|
|
17202
|
-
import { execSync as
|
|
17340
|
+
import { execSync as execSync48 } from "child_process";
|
|
17203
17341
|
import * as path51 from "path";
|
|
17204
17342
|
function isGlobalNpmInstall(dir) {
|
|
17205
17343
|
try {
|
|
@@ -17207,7 +17345,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
17207
17345
|
if (resolved.split(path51.sep).includes("node_modules")) {
|
|
17208
17346
|
return true;
|
|
17209
17347
|
}
|
|
17210
|
-
const globalPrefix =
|
|
17348
|
+
const globalPrefix = execSync48("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
17211
17349
|
return resolved.toLowerCase().startsWith(path51.resolve(globalPrefix).toLowerCase());
|
|
17212
17350
|
} catch {
|
|
17213
17351
|
return false;
|
|
@@ -17218,18 +17356,18 @@ async function update2() {
|
|
|
17218
17356
|
console.log(`Assist is installed at: ${installDir}`);
|
|
17219
17357
|
if (isGitRepo(installDir)) {
|
|
17220
17358
|
console.log("Detected git repo installation, pulling latest...");
|
|
17221
|
-
|
|
17359
|
+
execSync48("git pull", { cwd: installDir, stdio: "inherit" });
|
|
17222
17360
|
console.log("Installing dependencies...");
|
|
17223
|
-
|
|
17361
|
+
execSync48("npm i", { cwd: installDir, stdio: "inherit" });
|
|
17224
17362
|
console.log("Building...");
|
|
17225
|
-
|
|
17363
|
+
execSync48("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
17226
17364
|
console.log("Syncing commands...");
|
|
17227
|
-
|
|
17365
|
+
execSync48("assist sync", { stdio: "inherit" });
|
|
17228
17366
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
17229
17367
|
console.log("Detected global npm installation, updating...");
|
|
17230
|
-
|
|
17368
|
+
execSync48("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
17231
17369
|
console.log("Syncing commands...");
|
|
17232
|
-
|
|
17370
|
+
execSync48("assist sync", { stdio: "inherit" });
|
|
17233
17371
|
} else {
|
|
17234
17372
|
console.error(
|
|
17235
17373
|
"Could not determine installation method. Expected a git repo or global npm install."
|
|
@@ -17260,6 +17398,7 @@ program.command("coverage").description("Print global statement coverage percent
|
|
|
17260
17398
|
program.command("screenshot").description("Capture a screenshot of a running application window").argument("<process>", "Name of the running process (e.g. notepad, code)").action(screenshot);
|
|
17261
17399
|
registerActivity(program);
|
|
17262
17400
|
registerCliHook(program);
|
|
17401
|
+
registerGithub(program);
|
|
17263
17402
|
registerHandover(program);
|
|
17264
17403
|
registerJira(program);
|
|
17265
17404
|
registerMermaid(program);
|