@staff0rd/assist 0.123.0 → 0.125.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 +1 -0
- package/dist/index.js +351 -233
- 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.125.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -4710,9 +4710,7 @@ async function inSln(csprojPath) {
|
|
|
4710
4710
|
}
|
|
4711
4711
|
|
|
4712
4712
|
// src/commands/dotnet/inspect.ts
|
|
4713
|
-
import
|
|
4714
|
-
import path26 from "path";
|
|
4715
|
-
import chalk55 from "chalk";
|
|
4713
|
+
import chalk57 from "chalk";
|
|
4716
4714
|
|
|
4717
4715
|
// src/shared/formatElapsed.ts
|
|
4718
4716
|
function formatElapsed(ms) {
|
|
@@ -4759,6 +4757,7 @@ ${issues.length} issue(s) found`));
|
|
|
4759
4757
|
|
|
4760
4758
|
// src/commands/dotnet/deadCodeRules.ts
|
|
4761
4759
|
var deadCodeRules = /* @__PURE__ */ new Set([
|
|
4760
|
+
// JetBrains ReSharper rules
|
|
4762
4761
|
"UnusedMember.Local",
|
|
4763
4762
|
"UnusedType.Local",
|
|
4764
4763
|
"UnusedParameter.Global",
|
|
@@ -4773,7 +4772,27 @@ var deadCodeRules = /* @__PURE__ */ new Set([
|
|
|
4773
4772
|
"UnusedMethodReturnValue.Global",
|
|
4774
4773
|
"UnusedMethodReturnValue.Local",
|
|
4775
4774
|
"UnusedVariable.Compiler",
|
|
4776
|
-
"RedundantUsingDirective"
|
|
4775
|
+
"RedundantUsingDirective",
|
|
4776
|
+
// Roslyn compiler diagnostics
|
|
4777
|
+
"CS0168",
|
|
4778
|
+
// Variable declared but never used
|
|
4779
|
+
"CS0169",
|
|
4780
|
+
// Field is never used
|
|
4781
|
+
"CS0219",
|
|
4782
|
+
// Variable assigned but never used
|
|
4783
|
+
"CS0414",
|
|
4784
|
+
// Field assigned but never read
|
|
4785
|
+
"CS8321",
|
|
4786
|
+
// Local function declared but never used
|
|
4787
|
+
// Roslyn IDE analyzers
|
|
4788
|
+
"IDE0051",
|
|
4789
|
+
// Private member is unused
|
|
4790
|
+
"IDE0052",
|
|
4791
|
+
// Private member can be removed (value never read)
|
|
4792
|
+
"IDE0059",
|
|
4793
|
+
// Unnecessary assignment
|
|
4794
|
+
"IDE0060"
|
|
4795
|
+
// Remove unused parameter
|
|
4777
4796
|
]);
|
|
4778
4797
|
|
|
4779
4798
|
// src/commands/dotnet/filterIssues.ts
|
|
@@ -4784,6 +4803,27 @@ function filterIssues(issues, all) {
|
|
|
4784
4803
|
);
|
|
4785
4804
|
}
|
|
4786
4805
|
|
|
4806
|
+
// src/commands/dotnet/getChangedCsFiles.ts
|
|
4807
|
+
import { execSync as execSync20 } from "child_process";
|
|
4808
|
+
function getChangedCsFiles(ref, base) {
|
|
4809
|
+
let cmd;
|
|
4810
|
+
if (base) {
|
|
4811
|
+
cmd = `git diff --name-only ${base}...HEAD`;
|
|
4812
|
+
} else if (ref) {
|
|
4813
|
+
cmd = `git diff --name-only ${ref}~1 ${ref}`;
|
|
4814
|
+
} else {
|
|
4815
|
+
cmd = "git diff --name-only HEAD";
|
|
4816
|
+
}
|
|
4817
|
+
const output = execSync20(cmd, { encoding: "utf-8" }).trim();
|
|
4818
|
+
if (output === "") return [];
|
|
4819
|
+
return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
|
|
4820
|
+
}
|
|
4821
|
+
|
|
4822
|
+
// src/commands/dotnet/resolveSolution.ts
|
|
4823
|
+
import { existsSync as existsSync22 } from "fs";
|
|
4824
|
+
import path25 from "path";
|
|
4825
|
+
import chalk54 from "chalk";
|
|
4826
|
+
|
|
4787
4827
|
// src/commands/dotnet/findSolution.ts
|
|
4788
4828
|
import { readdirSync as readdirSync4 } from "fs";
|
|
4789
4829
|
import { dirname as dirname16, join as join17 } from "path";
|
|
@@ -4817,20 +4857,27 @@ function findSolution() {
|
|
|
4817
4857
|
process.exit(1);
|
|
4818
4858
|
}
|
|
4819
4859
|
|
|
4820
|
-
// src/commands/dotnet/
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
cmd = "git diff --name-only HEAD";
|
|
4860
|
+
// src/commands/dotnet/resolveSolution.ts
|
|
4861
|
+
function resolveSolution(sln) {
|
|
4862
|
+
if (sln) {
|
|
4863
|
+
const resolved = path25.resolve(sln);
|
|
4864
|
+
if (!existsSync22(resolved)) {
|
|
4865
|
+
console.error(chalk54.red(`Solution file not found: ${resolved}`));
|
|
4866
|
+
process.exit(1);
|
|
4867
|
+
}
|
|
4868
|
+
return resolved;
|
|
4830
4869
|
}
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4870
|
+
return findSolution();
|
|
4871
|
+
}
|
|
4872
|
+
|
|
4873
|
+
// src/commands/dotnet/filterToChangedFiles.ts
|
|
4874
|
+
function filterToChangedFiles(issues, changedFiles) {
|
|
4875
|
+
const normalize = (f) => f.replace(/\\/g, "/").replace(/^file:\/\/\//, "");
|
|
4876
|
+
const changed = changedFiles.map(normalize);
|
|
4877
|
+
return issues.filter((i) => {
|
|
4878
|
+
const file = normalize(i.file);
|
|
4879
|
+
return changed.some((c) => file === c || file.endsWith(`/${c}`));
|
|
4880
|
+
});
|
|
4834
4881
|
}
|
|
4835
4882
|
|
|
4836
4883
|
// src/commands/dotnet/parseInspectReport.ts
|
|
@@ -4854,23 +4901,23 @@ function parseInspectReport(json) {
|
|
|
4854
4901
|
|
|
4855
4902
|
// src/commands/dotnet/runInspectCode.ts
|
|
4856
4903
|
import { execSync as execSync21 } from "child_process";
|
|
4857
|
-
import { existsSync as
|
|
4904
|
+
import { existsSync as existsSync23, readFileSync as readFileSync20, unlinkSync as unlinkSync3 } from "fs";
|
|
4858
4905
|
import { tmpdir as tmpdir2 } from "os";
|
|
4859
|
-
import
|
|
4860
|
-
import
|
|
4906
|
+
import path26 from "path";
|
|
4907
|
+
import chalk55 from "chalk";
|
|
4861
4908
|
function assertJbInstalled() {
|
|
4862
4909
|
try {
|
|
4863
4910
|
execSync21("jb inspectcode --version", { stdio: "pipe" });
|
|
4864
4911
|
} catch {
|
|
4865
|
-
console.error(
|
|
4912
|
+
console.error(chalk55.red("jb is not installed. Install with:"));
|
|
4866
4913
|
console.error(
|
|
4867
|
-
|
|
4914
|
+
chalk55.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
4868
4915
|
);
|
|
4869
4916
|
process.exit(1);
|
|
4870
4917
|
}
|
|
4871
4918
|
}
|
|
4872
4919
|
function runInspectCode(slnPath, include, swea) {
|
|
4873
|
-
const reportPath =
|
|
4920
|
+
const reportPath = path26.join(tmpdir2(), `inspect-${Date.now()}.xml`);
|
|
4874
4921
|
const sweaFlag = swea ? " --swea" : "";
|
|
4875
4922
|
try {
|
|
4876
4923
|
execSync21(
|
|
@@ -4881,11 +4928,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
4881
4928
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
4882
4929
|
process.stderr.write(err.stderr);
|
|
4883
4930
|
}
|
|
4884
|
-
console.error(
|
|
4931
|
+
console.error(chalk55.red("jb inspectcode failed"));
|
|
4885
4932
|
process.exit(1);
|
|
4886
4933
|
}
|
|
4887
|
-
if (!
|
|
4888
|
-
console.error(
|
|
4934
|
+
if (!existsSync23(reportPath)) {
|
|
4935
|
+
console.error(chalk55.red("Report file not generated"));
|
|
4889
4936
|
process.exit(1);
|
|
4890
4937
|
}
|
|
4891
4938
|
const xml = readFileSync20(reportPath, "utf-8");
|
|
@@ -4893,45 +4940,88 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
4893
4940
|
return xml;
|
|
4894
4941
|
}
|
|
4895
4942
|
|
|
4896
|
-
// src/commands/dotnet/
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4943
|
+
// src/commands/dotnet/runRoslynInspect.ts
|
|
4944
|
+
import { execSync as execSync22 } from "child_process";
|
|
4945
|
+
import chalk56 from "chalk";
|
|
4946
|
+
function resolveMsbuildPath() {
|
|
4947
|
+
const config = loadConfig();
|
|
4948
|
+
const buildConfig = config.run?.find((r) => r.name === "build");
|
|
4949
|
+
return buildConfig?.command ?? "msbuild";
|
|
4950
|
+
}
|
|
4951
|
+
function assertMsbuildInstalled() {
|
|
4952
|
+
const msbuild = resolveMsbuildPath();
|
|
4953
|
+
try {
|
|
4954
|
+
execSync22(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
4955
|
+
} catch {
|
|
4956
|
+
console.error(chalk56.red(`msbuild not found at: ${msbuild}`));
|
|
4957
|
+
console.error(
|
|
4958
|
+
chalk56.yellow(
|
|
4959
|
+
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
4960
|
+
)
|
|
4961
|
+
);
|
|
4962
|
+
process.exit(1);
|
|
4905
4963
|
}
|
|
4906
|
-
return findSolution();
|
|
4907
4964
|
}
|
|
4965
|
+
var DIAG_PATTERN = /^(.+?)\((\d+),\d+\):\s+(error|warning)\s+(\S+):\s+(.+?)(?:\s+\[.+\])?$/gm;
|
|
4966
|
+
function parseMsbuildOutput(output) {
|
|
4967
|
+
const normalized = output.replace(/\r\n/g, "\n");
|
|
4968
|
+
return [...normalized.matchAll(DIAG_PATTERN)].map((m) => ({
|
|
4969
|
+
file: m[1].replace(/\\/g, "/"),
|
|
4970
|
+
line: Number.parseInt(m[2], 10),
|
|
4971
|
+
severity: m[3] === "error" ? "ERROR" : "WARNING",
|
|
4972
|
+
typeId: m[4],
|
|
4973
|
+
message: m[5].trim()
|
|
4974
|
+
}));
|
|
4975
|
+
}
|
|
4976
|
+
function runRoslynInspect(slnPath) {
|
|
4977
|
+
const msbuild = resolveMsbuildPath();
|
|
4978
|
+
let output;
|
|
4979
|
+
try {
|
|
4980
|
+
output = execSync22(
|
|
4981
|
+
`"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
|
|
4982
|
+
{ encoding: "utf-8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
|
|
4983
|
+
);
|
|
4984
|
+
} catch (err) {
|
|
4985
|
+
const e = err;
|
|
4986
|
+
output = e.stdout ?? "";
|
|
4987
|
+
}
|
|
4988
|
+
return parseMsbuildOutput(output);
|
|
4989
|
+
}
|
|
4990
|
+
|
|
4991
|
+
// src/commands/dotnet/runEngine.ts
|
|
4992
|
+
function runEngine(resolved, changedFiles, options2) {
|
|
4993
|
+
if (options2.roslyn) {
|
|
4994
|
+
return filterToChangedFiles(runRoslynInspect(resolved), changedFiles);
|
|
4995
|
+
}
|
|
4996
|
+
return parseInspectReport(
|
|
4997
|
+
runInspectCode(resolved, changedFiles.join(";"), !!options2.swea)
|
|
4998
|
+
);
|
|
4999
|
+
}
|
|
5000
|
+
|
|
5001
|
+
// src/commands/dotnet/inspect.ts
|
|
4908
5002
|
function reportResults(issues, elapsed) {
|
|
4909
5003
|
if (issues.length > 0) displayIssues(issues);
|
|
4910
|
-
else console.log(
|
|
4911
|
-
console.log(
|
|
5004
|
+
else console.log(chalk57.green("No issues found"));
|
|
5005
|
+
console.log(chalk57.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
4912
5006
|
if (issues.length > 0) process.exit(1);
|
|
4913
5007
|
}
|
|
4914
5008
|
async function inspect(sln, options2) {
|
|
4915
5009
|
const resolved = resolveSolution(sln);
|
|
4916
5010
|
checkBuildLocks();
|
|
4917
|
-
|
|
5011
|
+
if (options2.roslyn) assertMsbuildInstalled();
|
|
5012
|
+
else assertJbInstalled();
|
|
4918
5013
|
const changedFiles = getChangedCsFiles(options2.ref, options2.base);
|
|
4919
5014
|
if (changedFiles.length === 0) {
|
|
4920
|
-
console.log(
|
|
5015
|
+
console.log(chalk57.green("No changed .cs files found"));
|
|
4921
5016
|
return;
|
|
4922
5017
|
}
|
|
4923
5018
|
console.log(
|
|
4924
|
-
|
|
5019
|
+
chalk57.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
4925
5020
|
);
|
|
4926
5021
|
const start3 = Date.now();
|
|
4927
|
-
const
|
|
4928
|
-
resolved,
|
|
4929
|
-
changedFiles.join(";"),
|
|
4930
|
-
!!options2.swea
|
|
4931
|
-
);
|
|
5022
|
+
const issues = runEngine(resolved, changedFiles, options2);
|
|
4932
5023
|
const elapsed = Date.now() - start3;
|
|
4933
|
-
|
|
4934
|
-
reportResults(issues, elapsed);
|
|
5024
|
+
reportResults(filterIssues(issues, !!options2.all), elapsed);
|
|
4935
5025
|
}
|
|
4936
5026
|
|
|
4937
5027
|
// src/commands/registerDotnet.ts
|
|
@@ -4942,14 +5032,14 @@ function registerDotnet(program2) {
|
|
|
4942
5032
|
).argument("[sln]", "Path to a .sln file (auto-detected if omitted)").option("--ref <ref>", "Git commit to inspect (default: working copy)").option(
|
|
4943
5033
|
"--base <ref>",
|
|
4944
5034
|
"Compare against a base ref using merge-base (e.g. main); inspects all PR changes"
|
|
4945
|
-
).option("--all", "Show all issues, not just dead code").option("--swea", "Enable solution-wide error analysis").action(inspect);
|
|
5035
|
+
).option("--all", "Show all issues, not just dead code").option("--swea", "Enable solution-wide error analysis").option("--roslyn", "Use Roslyn analyzers via msbuild instead of JetBrains").action(inspect);
|
|
4946
5036
|
cmd.command("check-locks").description("Check if build output files are locked by a debugger").action(checkBuildLocksCommand);
|
|
4947
5037
|
cmd.command("deps").description("Show .csproj project dependency tree and solution membership").argument("<csproj>", "Path to a .csproj file").option("--json", "Output as JSON").action(deps);
|
|
4948
5038
|
cmd.command("in-sln").description("Check whether a .csproj is referenced by any .sln file").argument("<csproj>", "Path to a .csproj file").action(inSln);
|
|
4949
5039
|
}
|
|
4950
5040
|
|
|
4951
5041
|
// src/commands/jira/acceptanceCriteria.ts
|
|
4952
|
-
import
|
|
5042
|
+
import chalk59 from "chalk";
|
|
4953
5043
|
|
|
4954
5044
|
// src/commands/jira/adfToText.ts
|
|
4955
5045
|
function renderInline(node) {
|
|
@@ -5009,12 +5099,12 @@ function adfToText(doc) {
|
|
|
5009
5099
|
}
|
|
5010
5100
|
|
|
5011
5101
|
// src/commands/jira/fetchIssue.ts
|
|
5012
|
-
import { execSync as
|
|
5013
|
-
import
|
|
5102
|
+
import { execSync as execSync23 } from "child_process";
|
|
5103
|
+
import chalk58 from "chalk";
|
|
5014
5104
|
function fetchIssue(issueKey, fields) {
|
|
5015
5105
|
let result;
|
|
5016
5106
|
try {
|
|
5017
|
-
result =
|
|
5107
|
+
result = execSync23(
|
|
5018
5108
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
5019
5109
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
5020
5110
|
);
|
|
@@ -5023,15 +5113,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
5023
5113
|
const stderr = error.stderr;
|
|
5024
5114
|
if (stderr.includes("unauthorized")) {
|
|
5025
5115
|
console.error(
|
|
5026
|
-
|
|
5116
|
+
chalk58.red("Jira authentication expired."),
|
|
5027
5117
|
"Run",
|
|
5028
|
-
|
|
5118
|
+
chalk58.cyan("assist jira auth"),
|
|
5029
5119
|
"to re-authenticate."
|
|
5030
5120
|
);
|
|
5031
5121
|
process.exit(1);
|
|
5032
5122
|
}
|
|
5033
5123
|
}
|
|
5034
|
-
console.error(
|
|
5124
|
+
console.error(chalk58.red(`Failed to fetch ${issueKey}.`));
|
|
5035
5125
|
process.exit(1);
|
|
5036
5126
|
}
|
|
5037
5127
|
return JSON.parse(result);
|
|
@@ -5045,7 +5135,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
5045
5135
|
const parsed = fetchIssue(issueKey, field);
|
|
5046
5136
|
const acValue = parsed?.fields?.[field];
|
|
5047
5137
|
if (!acValue) {
|
|
5048
|
-
console.log(
|
|
5138
|
+
console.log(chalk59.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
5049
5139
|
return;
|
|
5050
5140
|
}
|
|
5051
5141
|
if (typeof acValue === "string") {
|
|
@@ -5060,7 +5150,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
5060
5150
|
}
|
|
5061
5151
|
|
|
5062
5152
|
// src/commands/jira/jiraAuth.ts
|
|
5063
|
-
import { execSync as
|
|
5153
|
+
import { execSync as execSync24 } from "child_process";
|
|
5064
5154
|
import Enquirer from "enquirer";
|
|
5065
5155
|
|
|
5066
5156
|
// src/shared/loadJson.ts
|
|
@@ -5120,7 +5210,7 @@ async function jiraAuth() {
|
|
|
5120
5210
|
console.error("All fields are required.");
|
|
5121
5211
|
process.exit(1);
|
|
5122
5212
|
}
|
|
5123
|
-
|
|
5213
|
+
execSync24(`acli jira auth login --site ${site} --email "${email}" --token`, {
|
|
5124
5214
|
encoding: "utf-8",
|
|
5125
5215
|
input: token,
|
|
5126
5216
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -5136,14 +5226,14 @@ async function jiraAuth() {
|
|
|
5136
5226
|
}
|
|
5137
5227
|
|
|
5138
5228
|
// src/commands/jira/viewIssue.ts
|
|
5139
|
-
import
|
|
5229
|
+
import chalk60 from "chalk";
|
|
5140
5230
|
function viewIssue(issueKey) {
|
|
5141
5231
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
5142
5232
|
const fields = parsed?.fields;
|
|
5143
5233
|
const summary = fields?.summary;
|
|
5144
5234
|
const description = fields?.description;
|
|
5145
5235
|
if (summary) {
|
|
5146
|
-
console.log(
|
|
5236
|
+
console.log(chalk60.bold(summary));
|
|
5147
5237
|
}
|
|
5148
5238
|
if (description) {
|
|
5149
5239
|
if (summary) console.log();
|
|
@@ -5157,7 +5247,7 @@ function viewIssue(issueKey) {
|
|
|
5157
5247
|
}
|
|
5158
5248
|
if (!summary && !description) {
|
|
5159
5249
|
console.log(
|
|
5160
|
-
|
|
5250
|
+
chalk60.yellow(`No summary or description found on ${issueKey}.`)
|
|
5161
5251
|
);
|
|
5162
5252
|
}
|
|
5163
5253
|
}
|
|
@@ -5171,7 +5261,7 @@ function registerJira(program2) {
|
|
|
5171
5261
|
}
|
|
5172
5262
|
|
|
5173
5263
|
// src/commands/news/add/index.ts
|
|
5174
|
-
import
|
|
5264
|
+
import chalk61 from "chalk";
|
|
5175
5265
|
import enquirer5 from "enquirer";
|
|
5176
5266
|
async function add2(url) {
|
|
5177
5267
|
if (!url) {
|
|
@@ -5194,17 +5284,17 @@ async function add2(url) {
|
|
|
5194
5284
|
const news = config.news ?? {};
|
|
5195
5285
|
const feeds = news.feeds ?? [];
|
|
5196
5286
|
if (feeds.includes(url)) {
|
|
5197
|
-
console.log(
|
|
5287
|
+
console.log(chalk61.yellow("Feed already exists in config"));
|
|
5198
5288
|
return;
|
|
5199
5289
|
}
|
|
5200
5290
|
feeds.push(url);
|
|
5201
5291
|
config.news = { ...news, feeds };
|
|
5202
5292
|
saveGlobalConfig(config);
|
|
5203
|
-
console.log(
|
|
5293
|
+
console.log(chalk61.green(`Added feed: ${url}`));
|
|
5204
5294
|
}
|
|
5205
5295
|
|
|
5206
5296
|
// src/commands/news/web/handleRequest.ts
|
|
5207
|
-
import
|
|
5297
|
+
import chalk62 from "chalk";
|
|
5208
5298
|
|
|
5209
5299
|
// src/commands/news/web/shared.ts
|
|
5210
5300
|
import { decodeHTML } from "entities";
|
|
@@ -5340,17 +5430,17 @@ function prefetch() {
|
|
|
5340
5430
|
const config = loadConfig();
|
|
5341
5431
|
const total = config.news.feeds.length;
|
|
5342
5432
|
if (total === 0) return;
|
|
5343
|
-
process.stdout.write(
|
|
5433
|
+
process.stdout.write(chalk62.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
5344
5434
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
5345
5435
|
const width = 20;
|
|
5346
5436
|
const filled = Math.round(done2 / t * width);
|
|
5347
5437
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
5348
5438
|
process.stdout.write(
|
|
5349
|
-
`\r${
|
|
5439
|
+
`\r${chalk62.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
5350
5440
|
);
|
|
5351
5441
|
}).then((items) => {
|
|
5352
5442
|
process.stdout.write(
|
|
5353
|
-
`\r${
|
|
5443
|
+
`\r${chalk62.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
5354
5444
|
`
|
|
5355
5445
|
);
|
|
5356
5446
|
cachedItems = items;
|
|
@@ -5401,7 +5491,7 @@ import { tmpdir as tmpdir3 } from "os";
|
|
|
5401
5491
|
import { join as join19 } from "path";
|
|
5402
5492
|
|
|
5403
5493
|
// src/commands/prs/shared.ts
|
|
5404
|
-
import { execSync as
|
|
5494
|
+
import { execSync as execSync25 } from "child_process";
|
|
5405
5495
|
function isGhNotInstalled(error) {
|
|
5406
5496
|
if (error instanceof Error) {
|
|
5407
5497
|
const msg = error.message.toLowerCase();
|
|
@@ -5417,14 +5507,14 @@ function isNotFound(error) {
|
|
|
5417
5507
|
}
|
|
5418
5508
|
function getRepoInfo() {
|
|
5419
5509
|
const repoInfo = JSON.parse(
|
|
5420
|
-
|
|
5510
|
+
execSync25("gh repo view --json owner,name", { encoding: "utf-8" })
|
|
5421
5511
|
);
|
|
5422
5512
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
5423
5513
|
}
|
|
5424
5514
|
function getCurrentPrNumber() {
|
|
5425
5515
|
try {
|
|
5426
5516
|
const prInfo = JSON.parse(
|
|
5427
|
-
|
|
5517
|
+
execSync25("gh pr view --json number", { encoding: "utf-8" })
|
|
5428
5518
|
);
|
|
5429
5519
|
return prInfo.number;
|
|
5430
5520
|
} catch (error) {
|
|
@@ -5438,7 +5528,7 @@ function getCurrentPrNumber() {
|
|
|
5438
5528
|
function getCurrentPrNodeId() {
|
|
5439
5529
|
try {
|
|
5440
5530
|
const prInfo = JSON.parse(
|
|
5441
|
-
|
|
5531
|
+
execSync25("gh pr view --json id", { encoding: "utf-8" })
|
|
5442
5532
|
);
|
|
5443
5533
|
return prInfo.id;
|
|
5444
5534
|
} catch (error) {
|
|
@@ -5509,10 +5599,10 @@ function comment(path44, line, body) {
|
|
|
5509
5599
|
}
|
|
5510
5600
|
|
|
5511
5601
|
// src/commands/prs/fixed.ts
|
|
5512
|
-
import { execSync as
|
|
5602
|
+
import { execSync as execSync27 } from "child_process";
|
|
5513
5603
|
|
|
5514
5604
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
5515
|
-
import { execSync as
|
|
5605
|
+
import { execSync as execSync26 } from "child_process";
|
|
5516
5606
|
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync19 } from "fs";
|
|
5517
5607
|
import { tmpdir as tmpdir4 } from "os";
|
|
5518
5608
|
import { join as join21 } from "path";
|
|
@@ -5542,7 +5632,7 @@ function deleteCommentsCache(prNumber) {
|
|
|
5542
5632
|
|
|
5543
5633
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
5544
5634
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
5545
|
-
|
|
5635
|
+
execSync26(
|
|
5546
5636
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
|
|
5547
5637
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
5548
5638
|
);
|
|
@@ -5552,7 +5642,7 @@ function resolveThread(threadId) {
|
|
|
5552
5642
|
const queryFile = join21(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
|
|
5553
5643
|
writeFileSync19(queryFile, mutation);
|
|
5554
5644
|
try {
|
|
5555
|
-
|
|
5645
|
+
execSync26(
|
|
5556
5646
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
5557
5647
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
5558
5648
|
);
|
|
@@ -5604,7 +5694,7 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
5604
5694
|
// src/commands/prs/fixed.ts
|
|
5605
5695
|
function verifySha(sha) {
|
|
5606
5696
|
try {
|
|
5607
|
-
return
|
|
5697
|
+
return execSync27(`git rev-parse --verify ${sha}`, {
|
|
5608
5698
|
encoding: "utf-8"
|
|
5609
5699
|
}).trim();
|
|
5610
5700
|
} catch {
|
|
@@ -5618,7 +5708,7 @@ function fixed(commentId, sha) {
|
|
|
5618
5708
|
const { org, repo } = getRepoInfo();
|
|
5619
5709
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
5620
5710
|
const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
5621
|
-
|
|
5711
|
+
execSync27("git push", { stdio: "inherit" });
|
|
5622
5712
|
resolveCommentWithReply(commentId, message);
|
|
5623
5713
|
} catch (error) {
|
|
5624
5714
|
if (isGhNotInstalled(error)) {
|
|
@@ -5636,7 +5726,7 @@ import { join as join23 } from "path";
|
|
|
5636
5726
|
import { stringify } from "yaml";
|
|
5637
5727
|
|
|
5638
5728
|
// src/commands/prs/fetchThreadIds.ts
|
|
5639
|
-
import { execSync as
|
|
5729
|
+
import { execSync as execSync28 } from "child_process";
|
|
5640
5730
|
import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync20 } from "fs";
|
|
5641
5731
|
import { tmpdir as tmpdir5 } from "os";
|
|
5642
5732
|
import { join as join22 } from "path";
|
|
@@ -5645,7 +5735,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
5645
5735
|
const queryFile = join22(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
5646
5736
|
writeFileSync20(queryFile, THREAD_QUERY);
|
|
5647
5737
|
try {
|
|
5648
|
-
const result =
|
|
5738
|
+
const result = execSync28(
|
|
5649
5739
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
5650
5740
|
{ encoding: "utf-8" }
|
|
5651
5741
|
);
|
|
@@ -5667,9 +5757,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
5667
5757
|
}
|
|
5668
5758
|
|
|
5669
5759
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
5670
|
-
import { execSync as
|
|
5760
|
+
import { execSync as execSync29 } from "child_process";
|
|
5671
5761
|
function fetchJson(endpoint) {
|
|
5672
|
-
const result =
|
|
5762
|
+
const result = execSync29(`gh api --paginate ${endpoint}`, {
|
|
5673
5763
|
encoding: "utf-8"
|
|
5674
5764
|
});
|
|
5675
5765
|
if (!result.trim()) return [];
|
|
@@ -5711,20 +5801,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
5711
5801
|
}
|
|
5712
5802
|
|
|
5713
5803
|
// src/commands/prs/listComments/printComments.ts
|
|
5714
|
-
import
|
|
5804
|
+
import chalk63 from "chalk";
|
|
5715
5805
|
function formatForHuman(comment2) {
|
|
5716
5806
|
if (comment2.type === "review") {
|
|
5717
|
-
const stateColor = comment2.state === "APPROVED" ?
|
|
5807
|
+
const stateColor = comment2.state === "APPROVED" ? chalk63.green : comment2.state === "CHANGES_REQUESTED" ? chalk63.red : chalk63.yellow;
|
|
5718
5808
|
return [
|
|
5719
|
-
`${
|
|
5809
|
+
`${chalk63.cyan("Review")} by ${chalk63.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
5720
5810
|
comment2.body,
|
|
5721
5811
|
""
|
|
5722
5812
|
].join("\n");
|
|
5723
5813
|
}
|
|
5724
5814
|
const location = comment2.line ? `:${comment2.line}` : "";
|
|
5725
5815
|
return [
|
|
5726
|
-
`${
|
|
5727
|
-
|
|
5816
|
+
`${chalk63.cyan("Line comment")} by ${chalk63.bold(comment2.user)} on ${chalk63.dim(`${comment2.path}${location}`)}`,
|
|
5817
|
+
chalk63.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
5728
5818
|
comment2.body,
|
|
5729
5819
|
""
|
|
5730
5820
|
].join("\n");
|
|
@@ -5808,19 +5898,19 @@ async function listComments() {
|
|
|
5808
5898
|
}
|
|
5809
5899
|
|
|
5810
5900
|
// src/commands/prs/prs/index.ts
|
|
5811
|
-
import { execSync as
|
|
5901
|
+
import { execSync as execSync30 } from "child_process";
|
|
5812
5902
|
|
|
5813
5903
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
5814
5904
|
import enquirer6 from "enquirer";
|
|
5815
5905
|
|
|
5816
5906
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
5817
|
-
import
|
|
5907
|
+
import chalk64 from "chalk";
|
|
5818
5908
|
var STATUS_MAP = {
|
|
5819
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
5820
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
5909
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk64.magenta("merged"), date: pr.mergedAt } : null,
|
|
5910
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk64.red("closed"), date: pr.closedAt } : null
|
|
5821
5911
|
};
|
|
5822
5912
|
function defaultStatus(pr) {
|
|
5823
|
-
return { label:
|
|
5913
|
+
return { label: chalk64.green("opened"), date: pr.createdAt };
|
|
5824
5914
|
}
|
|
5825
5915
|
function getStatus2(pr) {
|
|
5826
5916
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -5829,11 +5919,11 @@ function formatDate(dateStr) {
|
|
|
5829
5919
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
5830
5920
|
}
|
|
5831
5921
|
function formatPrHeader(pr, status2) {
|
|
5832
|
-
return `${
|
|
5922
|
+
return `${chalk64.cyan(`#${pr.number}`)} ${pr.title} ${chalk64.dim(`(${pr.author.login},`)} ${status2.label} ${chalk64.dim(`${formatDate(status2.date)})`)}`;
|
|
5833
5923
|
}
|
|
5834
5924
|
function logPrDetails(pr) {
|
|
5835
5925
|
console.log(
|
|
5836
|
-
|
|
5926
|
+
chalk64.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
5837
5927
|
);
|
|
5838
5928
|
console.log();
|
|
5839
5929
|
}
|
|
@@ -5914,7 +6004,7 @@ async function displayPaginated(pullRequests) {
|
|
|
5914
6004
|
async function prs(options2) {
|
|
5915
6005
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
5916
6006
|
try {
|
|
5917
|
-
const result =
|
|
6007
|
+
const result = execSync30(
|
|
5918
6008
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
|
|
5919
6009
|
{ encoding: "utf-8" }
|
|
5920
6010
|
);
|
|
@@ -5937,7 +6027,7 @@ async function prs(options2) {
|
|
|
5937
6027
|
}
|
|
5938
6028
|
|
|
5939
6029
|
// src/commands/prs/wontfix.ts
|
|
5940
|
-
import { execSync as
|
|
6030
|
+
import { execSync as execSync31 } from "child_process";
|
|
5941
6031
|
function validateReason(reason) {
|
|
5942
6032
|
const lowerReason = reason.toLowerCase();
|
|
5943
6033
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -5954,7 +6044,7 @@ function validateShaReferences(reason) {
|
|
|
5954
6044
|
const invalidShas = [];
|
|
5955
6045
|
for (const sha of shas) {
|
|
5956
6046
|
try {
|
|
5957
|
-
|
|
6047
|
+
execSync31(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
5958
6048
|
} catch {
|
|
5959
6049
|
invalidShas.push(sha);
|
|
5960
6050
|
}
|
|
@@ -5999,7 +6089,7 @@ function registerPrs(program2) {
|
|
|
5999
6089
|
}
|
|
6000
6090
|
|
|
6001
6091
|
// src/commands/ravendb/ravendbAuth.ts
|
|
6002
|
-
import
|
|
6092
|
+
import chalk69 from "chalk";
|
|
6003
6093
|
|
|
6004
6094
|
// src/commands/ravendb/loadConnections.ts
|
|
6005
6095
|
function loadConnections() {
|
|
@@ -6016,18 +6106,18 @@ function saveConnections(connections) {
|
|
|
6016
6106
|
}
|
|
6017
6107
|
|
|
6018
6108
|
// src/commands/ravendb/promptConnection.ts
|
|
6019
|
-
import
|
|
6109
|
+
import chalk67 from "chalk";
|
|
6020
6110
|
import Enquirer3 from "enquirer";
|
|
6021
6111
|
|
|
6022
6112
|
// src/commands/ravendb/selectOpSecret.ts
|
|
6023
|
-
import
|
|
6113
|
+
import chalk66 from "chalk";
|
|
6024
6114
|
import Enquirer2 from "enquirer";
|
|
6025
6115
|
|
|
6026
6116
|
// src/commands/ravendb/searchItems.ts
|
|
6027
|
-
import { execSync as
|
|
6028
|
-
import
|
|
6117
|
+
import { execSync as execSync32 } from "child_process";
|
|
6118
|
+
import chalk65 from "chalk";
|
|
6029
6119
|
function opExec(args) {
|
|
6030
|
-
return
|
|
6120
|
+
return execSync32(`op ${args}`, {
|
|
6031
6121
|
encoding: "utf-8",
|
|
6032
6122
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6033
6123
|
}).trim();
|
|
@@ -6038,7 +6128,7 @@ function searchItems(search) {
|
|
|
6038
6128
|
items = JSON.parse(opExec("item list --format=json"));
|
|
6039
6129
|
} catch {
|
|
6040
6130
|
console.error(
|
|
6041
|
-
|
|
6131
|
+
chalk65.red(
|
|
6042
6132
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
6043
6133
|
)
|
|
6044
6134
|
);
|
|
@@ -6052,7 +6142,7 @@ function getItemFields(itemId) {
|
|
|
6052
6142
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
6053
6143
|
return item.fields.filter((f) => f.reference && f.label);
|
|
6054
6144
|
} catch {
|
|
6055
|
-
console.error(
|
|
6145
|
+
console.error(chalk65.red("Failed to get item details from 1Password."));
|
|
6056
6146
|
process.exit(1);
|
|
6057
6147
|
}
|
|
6058
6148
|
}
|
|
@@ -6071,7 +6161,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
6071
6161
|
}).run();
|
|
6072
6162
|
const items = searchItems(search);
|
|
6073
6163
|
if (items.length === 0) {
|
|
6074
|
-
console.error(
|
|
6164
|
+
console.error(chalk66.red(`No items found matching "${search}".`));
|
|
6075
6165
|
process.exit(1);
|
|
6076
6166
|
}
|
|
6077
6167
|
const itemId = await selectOne(
|
|
@@ -6080,7 +6170,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
6080
6170
|
);
|
|
6081
6171
|
const fields = getItemFields(itemId);
|
|
6082
6172
|
if (fields.length === 0) {
|
|
6083
|
-
console.error(
|
|
6173
|
+
console.error(chalk66.red("No fields with references found on this item."));
|
|
6084
6174
|
process.exit(1);
|
|
6085
6175
|
}
|
|
6086
6176
|
const ref = await selectOne(
|
|
@@ -6098,7 +6188,7 @@ async function promptConnection(existingNames) {
|
|
|
6098
6188
|
message: "Connection name:"
|
|
6099
6189
|
}).run();
|
|
6100
6190
|
if (existingNames.includes(name)) {
|
|
6101
|
-
console.error(
|
|
6191
|
+
console.error(chalk67.red(`Connection "${name}" already exists.`));
|
|
6102
6192
|
process.exit(1);
|
|
6103
6193
|
}
|
|
6104
6194
|
const url = await new Input2({
|
|
@@ -6110,22 +6200,22 @@ async function promptConnection(existingNames) {
|
|
|
6110
6200
|
message: "Database name:"
|
|
6111
6201
|
}).run();
|
|
6112
6202
|
if (!name || !url || !database) {
|
|
6113
|
-
console.error(
|
|
6203
|
+
console.error(chalk67.red("All fields are required."));
|
|
6114
6204
|
process.exit(1);
|
|
6115
6205
|
}
|
|
6116
6206
|
const apiKeyRef = await selectOpSecret();
|
|
6117
|
-
console.log(
|
|
6207
|
+
console.log(chalk67.dim(`Using: ${apiKeyRef}`));
|
|
6118
6208
|
return { name, url, database, apiKeyRef };
|
|
6119
6209
|
}
|
|
6120
6210
|
|
|
6121
6211
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
6122
|
-
import
|
|
6212
|
+
import chalk68 from "chalk";
|
|
6123
6213
|
function ravendbSetConnection(name) {
|
|
6124
6214
|
const raw = loadGlobalConfigRaw();
|
|
6125
6215
|
const ravendb = raw.ravendb ?? {};
|
|
6126
6216
|
const connections = ravendb.connections ?? [];
|
|
6127
6217
|
if (!connections.some((c) => c.name === name)) {
|
|
6128
|
-
console.error(
|
|
6218
|
+
console.error(chalk68.red(`Connection "${name}" not found.`));
|
|
6129
6219
|
console.error(
|
|
6130
6220
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
6131
6221
|
);
|
|
@@ -6147,7 +6237,7 @@ async function ravendbAuth(options2) {
|
|
|
6147
6237
|
}
|
|
6148
6238
|
for (const c of connections) {
|
|
6149
6239
|
console.log(
|
|
6150
|
-
`${
|
|
6240
|
+
`${chalk69.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`
|
|
6151
6241
|
);
|
|
6152
6242
|
}
|
|
6153
6243
|
return;
|
|
@@ -6155,7 +6245,7 @@ async function ravendbAuth(options2) {
|
|
|
6155
6245
|
if (options2.remove) {
|
|
6156
6246
|
const filtered = connections.filter((c) => c.name !== options2.remove);
|
|
6157
6247
|
if (filtered.length === connections.length) {
|
|
6158
|
-
console.error(
|
|
6248
|
+
console.error(chalk69.red(`Connection "${options2.remove}" not found.`));
|
|
6159
6249
|
process.exit(1);
|
|
6160
6250
|
}
|
|
6161
6251
|
saveConnections(filtered);
|
|
@@ -6173,10 +6263,10 @@ async function ravendbAuth(options2) {
|
|
|
6173
6263
|
}
|
|
6174
6264
|
|
|
6175
6265
|
// src/commands/ravendb/ravendbCollections.ts
|
|
6176
|
-
import
|
|
6266
|
+
import chalk73 from "chalk";
|
|
6177
6267
|
|
|
6178
6268
|
// src/commands/ravendb/ravenFetch.ts
|
|
6179
|
-
import
|
|
6269
|
+
import chalk71 from "chalk";
|
|
6180
6270
|
|
|
6181
6271
|
// src/commands/ravendb/getAccessToken.ts
|
|
6182
6272
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -6212,21 +6302,21 @@ ${errorText}`
|
|
|
6212
6302
|
}
|
|
6213
6303
|
|
|
6214
6304
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
6215
|
-
import { execSync as
|
|
6216
|
-
import
|
|
6305
|
+
import { execSync as execSync33 } from "child_process";
|
|
6306
|
+
import chalk70 from "chalk";
|
|
6217
6307
|
function resolveOpSecret(reference) {
|
|
6218
6308
|
if (!reference.startsWith("op://")) {
|
|
6219
|
-
console.error(
|
|
6309
|
+
console.error(chalk70.red(`Invalid secret reference: must start with op://`));
|
|
6220
6310
|
process.exit(1);
|
|
6221
6311
|
}
|
|
6222
6312
|
try {
|
|
6223
|
-
return
|
|
6313
|
+
return execSync33(`op read "${reference}"`, {
|
|
6224
6314
|
encoding: "utf-8",
|
|
6225
6315
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6226
6316
|
}).trim();
|
|
6227
6317
|
} catch {
|
|
6228
6318
|
console.error(
|
|
6229
|
-
|
|
6319
|
+
chalk70.red(
|
|
6230
6320
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
6231
6321
|
)
|
|
6232
6322
|
);
|
|
@@ -6253,7 +6343,7 @@ async function ravenFetch(connection, path44) {
|
|
|
6253
6343
|
if (!response.ok) {
|
|
6254
6344
|
const body = await response.text();
|
|
6255
6345
|
console.error(
|
|
6256
|
-
|
|
6346
|
+
chalk71.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
6257
6347
|
);
|
|
6258
6348
|
console.error(body.substring(0, 500));
|
|
6259
6349
|
process.exit(1);
|
|
@@ -6262,7 +6352,7 @@ async function ravenFetch(connection, path44) {
|
|
|
6262
6352
|
}
|
|
6263
6353
|
|
|
6264
6354
|
// src/commands/ravendb/resolveConnection.ts
|
|
6265
|
-
import
|
|
6355
|
+
import chalk72 from "chalk";
|
|
6266
6356
|
function loadRavendb() {
|
|
6267
6357
|
const raw = loadGlobalConfigRaw();
|
|
6268
6358
|
const ravendb = raw.ravendb;
|
|
@@ -6276,7 +6366,7 @@ function resolveConnection(name) {
|
|
|
6276
6366
|
const connectionName = name ?? defaultConnection;
|
|
6277
6367
|
if (!connectionName) {
|
|
6278
6368
|
console.error(
|
|
6279
|
-
|
|
6369
|
+
chalk72.red(
|
|
6280
6370
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
6281
6371
|
)
|
|
6282
6372
|
);
|
|
@@ -6284,7 +6374,7 @@ function resolveConnection(name) {
|
|
|
6284
6374
|
}
|
|
6285
6375
|
const connection = connections.find((c) => c.name === connectionName);
|
|
6286
6376
|
if (!connection) {
|
|
6287
|
-
console.error(
|
|
6377
|
+
console.error(chalk72.red(`Connection "${connectionName}" not found.`));
|
|
6288
6378
|
console.error(
|
|
6289
6379
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
6290
6380
|
);
|
|
@@ -6315,15 +6405,15 @@ async function ravendbCollections(connectionName) {
|
|
|
6315
6405
|
return;
|
|
6316
6406
|
}
|
|
6317
6407
|
for (const c of collections) {
|
|
6318
|
-
console.log(`${
|
|
6408
|
+
console.log(`${chalk73.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
6319
6409
|
}
|
|
6320
6410
|
}
|
|
6321
6411
|
|
|
6322
6412
|
// src/commands/ravendb/ravendbQuery.ts
|
|
6323
|
-
import
|
|
6413
|
+
import chalk75 from "chalk";
|
|
6324
6414
|
|
|
6325
6415
|
// src/commands/ravendb/fetchAllPages.ts
|
|
6326
|
-
import
|
|
6416
|
+
import chalk74 from "chalk";
|
|
6327
6417
|
|
|
6328
6418
|
// src/commands/ravendb/buildQueryPath.ts
|
|
6329
6419
|
function buildQueryPath(opts) {
|
|
@@ -6361,7 +6451,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
6361
6451
|
allResults.push(...results);
|
|
6362
6452
|
start3 += results.length;
|
|
6363
6453
|
process.stderr.write(
|
|
6364
|
-
`\r${
|
|
6454
|
+
`\r${chalk74.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
6365
6455
|
);
|
|
6366
6456
|
if (start3 >= totalResults) break;
|
|
6367
6457
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -6376,7 +6466,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
6376
6466
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
6377
6467
|
const resolved = resolveArgs(connectionName, collection);
|
|
6378
6468
|
if (!resolved.collection && !options2.query) {
|
|
6379
|
-
console.error(
|
|
6469
|
+
console.error(chalk75.red("Provide a collection name or --query filter."));
|
|
6380
6470
|
process.exit(1);
|
|
6381
6471
|
}
|
|
6382
6472
|
const { collection: col } = resolved;
|
|
@@ -6411,7 +6501,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
6411
6501
|
import * as path27 from "path";
|
|
6412
6502
|
|
|
6413
6503
|
// src/commands/refactor/logViolations.ts
|
|
6414
|
-
import
|
|
6504
|
+
import chalk76 from "chalk";
|
|
6415
6505
|
var DEFAULT_MAX_LINES = 100;
|
|
6416
6506
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
6417
6507
|
if (violations.length === 0) {
|
|
@@ -6420,43 +6510,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
6420
6510
|
}
|
|
6421
6511
|
return;
|
|
6422
6512
|
}
|
|
6423
|
-
console.error(
|
|
6513
|
+
console.error(chalk76.red(`
|
|
6424
6514
|
Refactor check failed:
|
|
6425
6515
|
`));
|
|
6426
|
-
console.error(
|
|
6516
|
+
console.error(chalk76.red(` The following files exceed ${maxLines} lines:
|
|
6427
6517
|
`));
|
|
6428
6518
|
for (const violation of violations) {
|
|
6429
|
-
console.error(
|
|
6519
|
+
console.error(chalk76.red(` ${violation.file} (${violation.lines} lines)`));
|
|
6430
6520
|
}
|
|
6431
6521
|
console.error(
|
|
6432
|
-
|
|
6522
|
+
chalk76.yellow(
|
|
6433
6523
|
`
|
|
6434
6524
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
6435
6525
|
way to refactor it, ignore it with:
|
|
6436
6526
|
`
|
|
6437
6527
|
)
|
|
6438
6528
|
);
|
|
6439
|
-
console.error(
|
|
6529
|
+
console.error(chalk76.gray(` assist refactor ignore <file>
|
|
6440
6530
|
`));
|
|
6441
6531
|
if (process.env.CLAUDECODE) {
|
|
6442
|
-
console.error(
|
|
6532
|
+
console.error(chalk76.cyan(`
|
|
6443
6533
|
## Extracting Code to New Files
|
|
6444
6534
|
`));
|
|
6445
6535
|
console.error(
|
|
6446
|
-
|
|
6536
|
+
chalk76.cyan(
|
|
6447
6537
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
6448
6538
|
`
|
|
6449
6539
|
)
|
|
6450
6540
|
);
|
|
6451
6541
|
console.error(
|
|
6452
|
-
|
|
6542
|
+
chalk76.cyan(
|
|
6453
6543
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
6454
6544
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
6455
6545
|
`
|
|
6456
6546
|
)
|
|
6457
6547
|
);
|
|
6458
6548
|
console.error(
|
|
6459
|
-
|
|
6549
|
+
chalk76.cyan(
|
|
6460
6550
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
6461
6551
|
domains, move it to a common/shared folder.
|
|
6462
6552
|
`
|
|
@@ -6466,7 +6556,7 @@ Refactor check failed:
|
|
|
6466
6556
|
}
|
|
6467
6557
|
|
|
6468
6558
|
// src/commands/refactor/check/getViolations/index.ts
|
|
6469
|
-
import { execSync as
|
|
6559
|
+
import { execSync as execSync34 } from "child_process";
|
|
6470
6560
|
import fs16 from "fs";
|
|
6471
6561
|
import { minimatch as minimatch4 } from "minimatch";
|
|
6472
6562
|
|
|
@@ -6516,7 +6606,7 @@ function getGitFiles(options2) {
|
|
|
6516
6606
|
}
|
|
6517
6607
|
const files = /* @__PURE__ */ new Set();
|
|
6518
6608
|
if (options2.staged || options2.modified) {
|
|
6519
|
-
const staged =
|
|
6609
|
+
const staged = execSync34("git diff --cached --name-only", {
|
|
6520
6610
|
encoding: "utf-8"
|
|
6521
6611
|
});
|
|
6522
6612
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -6524,7 +6614,7 @@ function getGitFiles(options2) {
|
|
|
6524
6614
|
}
|
|
6525
6615
|
}
|
|
6526
6616
|
if (options2.unstaged || options2.modified) {
|
|
6527
|
-
const unstaged =
|
|
6617
|
+
const unstaged = execSync34("git diff --name-only", { encoding: "utf-8" });
|
|
6528
6618
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
6529
6619
|
files.add(file);
|
|
6530
6620
|
}
|
|
@@ -6612,11 +6702,11 @@ async function check(pattern2, options2) {
|
|
|
6612
6702
|
|
|
6613
6703
|
// src/commands/refactor/ignore.ts
|
|
6614
6704
|
import fs17 from "fs";
|
|
6615
|
-
import
|
|
6705
|
+
import chalk77 from "chalk";
|
|
6616
6706
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
6617
6707
|
function ignore(file) {
|
|
6618
6708
|
if (!fs17.existsSync(file)) {
|
|
6619
|
-
console.error(
|
|
6709
|
+
console.error(chalk77.red(`Error: File does not exist: ${file}`));
|
|
6620
6710
|
process.exit(1);
|
|
6621
6711
|
}
|
|
6622
6712
|
const content = fs17.readFileSync(file, "utf-8");
|
|
@@ -6632,7 +6722,7 @@ function ignore(file) {
|
|
|
6632
6722
|
fs17.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
6633
6723
|
}
|
|
6634
6724
|
console.log(
|
|
6635
|
-
|
|
6725
|
+
chalk77.green(
|
|
6636
6726
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
6637
6727
|
)
|
|
6638
6728
|
);
|
|
@@ -6640,7 +6730,7 @@ function ignore(file) {
|
|
|
6640
6730
|
|
|
6641
6731
|
// src/commands/refactor/rename/index.ts
|
|
6642
6732
|
import path28 from "path";
|
|
6643
|
-
import
|
|
6733
|
+
import chalk78 from "chalk";
|
|
6644
6734
|
import { Project as Project2 } from "ts-morph";
|
|
6645
6735
|
async function rename(source, destination, options2 = {}) {
|
|
6646
6736
|
const sourcePath = path28.resolve(source);
|
|
@@ -6653,22 +6743,22 @@ async function rename(source, destination, options2 = {}) {
|
|
|
6653
6743
|
});
|
|
6654
6744
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
6655
6745
|
if (!sourceFile) {
|
|
6656
|
-
console.log(
|
|
6746
|
+
console.log(chalk78.red(`File not found in project: ${source}`));
|
|
6657
6747
|
process.exit(1);
|
|
6658
6748
|
}
|
|
6659
|
-
console.log(
|
|
6749
|
+
console.log(chalk78.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
6660
6750
|
if (options2.apply) {
|
|
6661
6751
|
sourceFile.move(destPath);
|
|
6662
6752
|
await project.save();
|
|
6663
|
-
console.log(
|
|
6753
|
+
console.log(chalk78.green("Done"));
|
|
6664
6754
|
} else {
|
|
6665
|
-
console.log(
|
|
6755
|
+
console.log(chalk78.dim("Dry run. Use --apply to execute."));
|
|
6666
6756
|
}
|
|
6667
6757
|
}
|
|
6668
6758
|
|
|
6669
6759
|
// src/commands/refactor/renameSymbol/index.ts
|
|
6670
6760
|
import path30 from "path";
|
|
6671
|
-
import
|
|
6761
|
+
import chalk79 from "chalk";
|
|
6672
6762
|
import { Project as Project3 } from "ts-morph";
|
|
6673
6763
|
|
|
6674
6764
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
@@ -6717,38 +6807,38 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
6717
6807
|
const project = new Project3({ tsConfigFilePath: tsConfigPath });
|
|
6718
6808
|
const sourceFile = project.getSourceFile(filePath);
|
|
6719
6809
|
if (!sourceFile) {
|
|
6720
|
-
console.log(
|
|
6810
|
+
console.log(chalk79.red(`File not found in project: ${file}`));
|
|
6721
6811
|
process.exit(1);
|
|
6722
6812
|
}
|
|
6723
6813
|
const symbol = findSymbol(sourceFile, oldName);
|
|
6724
6814
|
if (!symbol) {
|
|
6725
|
-
console.log(
|
|
6815
|
+
console.log(chalk79.red(`Symbol "${oldName}" not found in ${file}`));
|
|
6726
6816
|
process.exit(1);
|
|
6727
6817
|
}
|
|
6728
6818
|
const grouped = groupReferences(symbol, cwd);
|
|
6729
6819
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
6730
6820
|
console.log(
|
|
6731
|
-
|
|
6821
|
+
chalk79.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
6732
6822
|
`)
|
|
6733
6823
|
);
|
|
6734
6824
|
for (const [refFile, lines] of grouped) {
|
|
6735
6825
|
console.log(
|
|
6736
|
-
` ${
|
|
6826
|
+
` ${chalk79.dim(refFile)}: lines ${chalk79.cyan(lines.join(", "))}`
|
|
6737
6827
|
);
|
|
6738
6828
|
}
|
|
6739
6829
|
if (options2.apply) {
|
|
6740
6830
|
symbol.rename(newName);
|
|
6741
6831
|
await project.save();
|
|
6742
|
-
console.log(
|
|
6832
|
+
console.log(chalk79.green(`
|
|
6743
6833
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
6744
6834
|
} else {
|
|
6745
|
-
console.log(
|
|
6835
|
+
console.log(chalk79.dim("\nDry run. Use --apply to execute."));
|
|
6746
6836
|
}
|
|
6747
6837
|
}
|
|
6748
6838
|
|
|
6749
6839
|
// src/commands/refactor/restructure/index.ts
|
|
6750
6840
|
import path39 from "path";
|
|
6751
|
-
import
|
|
6841
|
+
import chalk82 from "chalk";
|
|
6752
6842
|
|
|
6753
6843
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
6754
6844
|
import path31 from "path";
|
|
@@ -6991,50 +7081,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
6991
7081
|
|
|
6992
7082
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
6993
7083
|
import path35 from "path";
|
|
6994
|
-
import
|
|
7084
|
+
import chalk80 from "chalk";
|
|
6995
7085
|
function relPath(filePath) {
|
|
6996
7086
|
return path35.relative(process.cwd(), filePath);
|
|
6997
7087
|
}
|
|
6998
7088
|
function displayMoves(plan) {
|
|
6999
7089
|
if (plan.moves.length === 0) return;
|
|
7000
|
-
console.log(
|
|
7090
|
+
console.log(chalk80.bold("\nFile moves:"));
|
|
7001
7091
|
for (const move of plan.moves) {
|
|
7002
7092
|
console.log(
|
|
7003
|
-
` ${
|
|
7093
|
+
` ${chalk80.red(relPath(move.from))} \u2192 ${chalk80.green(relPath(move.to))}`
|
|
7004
7094
|
);
|
|
7005
|
-
console.log(
|
|
7095
|
+
console.log(chalk80.dim(` ${move.reason}`));
|
|
7006
7096
|
}
|
|
7007
7097
|
}
|
|
7008
7098
|
function displayRewrites(rewrites) {
|
|
7009
7099
|
if (rewrites.length === 0) return;
|
|
7010
7100
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
7011
|
-
console.log(
|
|
7101
|
+
console.log(chalk80.bold(`
|
|
7012
7102
|
Import rewrites (${affectedFiles.size} files):`));
|
|
7013
7103
|
for (const file of affectedFiles) {
|
|
7014
|
-
console.log(` ${
|
|
7104
|
+
console.log(` ${chalk80.cyan(relPath(file))}:`);
|
|
7015
7105
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
7016
7106
|
(r) => r.file === file
|
|
7017
7107
|
)) {
|
|
7018
7108
|
console.log(
|
|
7019
|
-
` ${
|
|
7109
|
+
` ${chalk80.red(`"${oldSpecifier}"`)} \u2192 ${chalk80.green(`"${newSpecifier}"`)}`
|
|
7020
7110
|
);
|
|
7021
7111
|
}
|
|
7022
7112
|
}
|
|
7023
7113
|
}
|
|
7024
7114
|
function displayPlan(plan) {
|
|
7025
7115
|
if (plan.warnings.length > 0) {
|
|
7026
|
-
console.log(
|
|
7027
|
-
for (const w of plan.warnings) console.log(
|
|
7116
|
+
console.log(chalk80.yellow("\nWarnings:"));
|
|
7117
|
+
for (const w of plan.warnings) console.log(chalk80.yellow(` ${w}`));
|
|
7028
7118
|
}
|
|
7029
7119
|
if (plan.newDirectories.length > 0) {
|
|
7030
|
-
console.log(
|
|
7120
|
+
console.log(chalk80.bold("\nNew directories:"));
|
|
7031
7121
|
for (const dir of plan.newDirectories)
|
|
7032
|
-
console.log(
|
|
7122
|
+
console.log(chalk80.green(` ${dir}/`));
|
|
7033
7123
|
}
|
|
7034
7124
|
displayMoves(plan);
|
|
7035
7125
|
displayRewrites(plan.rewrites);
|
|
7036
7126
|
console.log(
|
|
7037
|
-
|
|
7127
|
+
chalk80.dim(
|
|
7038
7128
|
`
|
|
7039
7129
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
7040
7130
|
)
|
|
@@ -7044,18 +7134,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
7044
7134
|
// src/commands/refactor/restructure/executePlan.ts
|
|
7045
7135
|
import fs19 from "fs";
|
|
7046
7136
|
import path36 from "path";
|
|
7047
|
-
import
|
|
7137
|
+
import chalk81 from "chalk";
|
|
7048
7138
|
function executePlan(plan) {
|
|
7049
7139
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
7050
7140
|
for (const [file, content] of updatedContents) {
|
|
7051
7141
|
fs19.writeFileSync(file, content, "utf-8");
|
|
7052
7142
|
console.log(
|
|
7053
|
-
|
|
7143
|
+
chalk81.cyan(` Rewrote imports in ${path36.relative(process.cwd(), file)}`)
|
|
7054
7144
|
);
|
|
7055
7145
|
}
|
|
7056
7146
|
for (const dir of plan.newDirectories) {
|
|
7057
7147
|
fs19.mkdirSync(dir, { recursive: true });
|
|
7058
|
-
console.log(
|
|
7148
|
+
console.log(chalk81.green(` Created ${path36.relative(process.cwd(), dir)}/`));
|
|
7059
7149
|
}
|
|
7060
7150
|
for (const move of plan.moves) {
|
|
7061
7151
|
const targetDir = path36.dirname(move.to);
|
|
@@ -7064,7 +7154,7 @@ function executePlan(plan) {
|
|
|
7064
7154
|
}
|
|
7065
7155
|
fs19.renameSync(move.from, move.to);
|
|
7066
7156
|
console.log(
|
|
7067
|
-
|
|
7157
|
+
chalk81.white(
|
|
7068
7158
|
` Moved ${path36.relative(process.cwd(), move.from)} \u2192 ${path36.relative(process.cwd(), move.to)}`
|
|
7069
7159
|
)
|
|
7070
7160
|
);
|
|
@@ -7079,7 +7169,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
7079
7169
|
if (entries.length === 0) {
|
|
7080
7170
|
fs19.rmdirSync(dir);
|
|
7081
7171
|
console.log(
|
|
7082
|
-
|
|
7172
|
+
chalk81.dim(
|
|
7083
7173
|
` Removed empty directory ${path36.relative(process.cwd(), dir)}`
|
|
7084
7174
|
)
|
|
7085
7175
|
);
|
|
@@ -7212,22 +7302,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
7212
7302
|
const targetPattern = pattern2 ?? "src";
|
|
7213
7303
|
const files = findSourceFiles2(targetPattern);
|
|
7214
7304
|
if (files.length === 0) {
|
|
7215
|
-
console.log(
|
|
7305
|
+
console.log(chalk82.yellow("No files found matching pattern"));
|
|
7216
7306
|
return;
|
|
7217
7307
|
}
|
|
7218
7308
|
const tsConfigPath = path39.resolve("tsconfig.json");
|
|
7219
7309
|
const plan = buildPlan(files, tsConfigPath);
|
|
7220
7310
|
if (plan.moves.length === 0) {
|
|
7221
|
-
console.log(
|
|
7311
|
+
console.log(chalk82.green("No restructuring needed"));
|
|
7222
7312
|
return;
|
|
7223
7313
|
}
|
|
7224
7314
|
displayPlan(plan);
|
|
7225
7315
|
if (options2.apply) {
|
|
7226
|
-
console.log(
|
|
7316
|
+
console.log(chalk82.bold("\nApplying changes..."));
|
|
7227
7317
|
executePlan(plan);
|
|
7228
|
-
console.log(
|
|
7318
|
+
console.log(chalk82.green("\nRestructuring complete"));
|
|
7229
7319
|
} else {
|
|
7230
|
-
console.log(
|
|
7320
|
+
console.log(chalk82.dim("\nDry run. Use --apply to execute."));
|
|
7231
7321
|
}
|
|
7232
7322
|
}
|
|
7233
7323
|
|
|
@@ -7775,14 +7865,14 @@ import {
|
|
|
7775
7865
|
import { dirname as dirname20, join as join28 } from "path";
|
|
7776
7866
|
|
|
7777
7867
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
7778
|
-
import
|
|
7868
|
+
import chalk83 from "chalk";
|
|
7779
7869
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
7780
7870
|
function validateStagedContent(filename, content) {
|
|
7781
7871
|
const firstLine = content.split("\n")[0];
|
|
7782
7872
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
7783
7873
|
if (!match) {
|
|
7784
7874
|
console.error(
|
|
7785
|
-
|
|
7875
|
+
chalk83.red(
|
|
7786
7876
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
7787
7877
|
)
|
|
7788
7878
|
);
|
|
@@ -7791,7 +7881,7 @@ function validateStagedContent(filename, content) {
|
|
|
7791
7881
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
7792
7882
|
if (!contentAfterLink) {
|
|
7793
7883
|
console.error(
|
|
7794
|
-
|
|
7884
|
+
chalk83.red(
|
|
7795
7885
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
7796
7886
|
)
|
|
7797
7887
|
);
|
|
@@ -7991,7 +8081,7 @@ import { mkdirSync as mkdirSync10 } from "fs";
|
|
|
7991
8081
|
import { join as join33 } from "path";
|
|
7992
8082
|
|
|
7993
8083
|
// src/commands/voice/checkLockFile.ts
|
|
7994
|
-
import { execSync as
|
|
8084
|
+
import { execSync as execSync35 } from "child_process";
|
|
7995
8085
|
import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync26, writeFileSync as writeFileSync23 } from "fs";
|
|
7996
8086
|
import { join as join32 } from "path";
|
|
7997
8087
|
function isProcessAlive(pid) {
|
|
@@ -8020,7 +8110,7 @@ function bootstrapVenv() {
|
|
|
8020
8110
|
if (existsSync33(getVenvPython())) return;
|
|
8021
8111
|
console.log("Setting up Python environment...");
|
|
8022
8112
|
const pythonDir = getPythonDir();
|
|
8023
|
-
|
|
8113
|
+
execSync35(
|
|
8024
8114
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
8025
8115
|
{
|
|
8026
8116
|
stdio: "inherit",
|
|
@@ -8184,14 +8274,14 @@ function registerVoice(program2) {
|
|
|
8184
8274
|
|
|
8185
8275
|
// src/commands/roam/auth.ts
|
|
8186
8276
|
import { randomBytes } from "crypto";
|
|
8187
|
-
import
|
|
8277
|
+
import chalk84 from "chalk";
|
|
8188
8278
|
|
|
8189
8279
|
// src/lib/openBrowser.ts
|
|
8190
|
-
import { execSync as
|
|
8280
|
+
import { execSync as execSync36 } from "child_process";
|
|
8191
8281
|
function tryExec(commands) {
|
|
8192
8282
|
for (const cmd of commands) {
|
|
8193
8283
|
try {
|
|
8194
|
-
|
|
8284
|
+
execSync36(cmd);
|
|
8195
8285
|
return true;
|
|
8196
8286
|
} catch {
|
|
8197
8287
|
}
|
|
@@ -8359,13 +8449,13 @@ async function auth() {
|
|
|
8359
8449
|
saveGlobalConfig(config);
|
|
8360
8450
|
const state = randomBytes(16).toString("hex");
|
|
8361
8451
|
console.log(
|
|
8362
|
-
|
|
8452
|
+
chalk84.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
8363
8453
|
);
|
|
8364
|
-
console.log(
|
|
8365
|
-
console.log(
|
|
8366
|
-
console.log(
|
|
8454
|
+
console.log(chalk84.white("http://localhost:14523/callback\n"));
|
|
8455
|
+
console.log(chalk84.blue("Opening browser for authorization..."));
|
|
8456
|
+
console.log(chalk84.dim("Waiting for authorization callback..."));
|
|
8367
8457
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
8368
|
-
console.log(
|
|
8458
|
+
console.log(chalk84.dim("Exchanging code for tokens..."));
|
|
8369
8459
|
const tokens = await exchangeToken({
|
|
8370
8460
|
code,
|
|
8371
8461
|
clientId,
|
|
@@ -8381,7 +8471,7 @@ async function auth() {
|
|
|
8381
8471
|
};
|
|
8382
8472
|
saveGlobalConfig(config);
|
|
8383
8473
|
console.log(
|
|
8384
|
-
|
|
8474
|
+
chalk84.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
8385
8475
|
);
|
|
8386
8476
|
}
|
|
8387
8477
|
|
|
@@ -8392,7 +8482,7 @@ function registerRoam(program2) {
|
|
|
8392
8482
|
}
|
|
8393
8483
|
|
|
8394
8484
|
// src/commands/run/index.ts
|
|
8395
|
-
import { execSync as
|
|
8485
|
+
import { execSync as execSync37 } from "child_process";
|
|
8396
8486
|
|
|
8397
8487
|
// src/commands/run/resolveParams.ts
|
|
8398
8488
|
function resolveParams(params, cliArgs) {
|
|
@@ -8555,7 +8645,7 @@ function listRunConfigs() {
|
|
|
8555
8645
|
function runPreCommands(pre) {
|
|
8556
8646
|
for (const cmd of pre) {
|
|
8557
8647
|
try {
|
|
8558
|
-
|
|
8648
|
+
execSync37(cmd, { stdio: "inherit" });
|
|
8559
8649
|
} catch (err) {
|
|
8560
8650
|
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
8561
8651
|
process.exit(code);
|
|
@@ -8573,10 +8663,12 @@ function run2(name, args) {
|
|
|
8573
8663
|
}
|
|
8574
8664
|
|
|
8575
8665
|
// src/commands/statusLine.ts
|
|
8576
|
-
import
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8666
|
+
import chalk86 from "chalk";
|
|
8667
|
+
|
|
8668
|
+
// src/commands/buildLimitsSegment.ts
|
|
8669
|
+
import chalk85 from "chalk";
|
|
8670
|
+
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
8671
|
+
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
8580
8672
|
function formatTimeLeft(resetsAt) {
|
|
8581
8673
|
const seconds = Math.max(0, resetsAt - Math.floor(Date.now() / 1e3));
|
|
8582
8674
|
const days = Math.floor(seconds / 86400);
|
|
@@ -8586,29 +8678,55 @@ function formatTimeLeft(resetsAt) {
|
|
|
8586
8678
|
if (hours > 0) return `${hours}h ${minutes}m`;
|
|
8587
8679
|
return `${minutes}m`;
|
|
8588
8680
|
}
|
|
8589
|
-
function
|
|
8681
|
+
function projectUsage(pct, resetsAt, windowSeconds) {
|
|
8682
|
+
if (resetsAt == null) return void 0;
|
|
8683
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
8684
|
+
const timeRemaining = Math.max(0, resetsAt - now);
|
|
8685
|
+
const elapsed = Math.max(0, windowSeconds - timeRemaining) / windowSeconds;
|
|
8686
|
+
if (elapsed < 0.05) return void 0;
|
|
8687
|
+
return pct / elapsed;
|
|
8688
|
+
}
|
|
8689
|
+
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
8590
8690
|
const label2 = `${Math.round(pct)}%`;
|
|
8591
|
-
|
|
8592
|
-
if (
|
|
8593
|
-
return label2;
|
|
8691
|
+
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
8692
|
+
if (projected == null) return chalk85.green(label2);
|
|
8693
|
+
if (projected > 100) return chalk85.red(label2);
|
|
8694
|
+
if (projected > 75) return chalk85.yellow(label2);
|
|
8695
|
+
return chalk85.green(label2);
|
|
8594
8696
|
}
|
|
8595
|
-
function formatLimit(
|
|
8596
|
-
const
|
|
8597
|
-
return `${
|
|
8697
|
+
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
8698
|
+
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
8699
|
+
return `${colorizeRateLimit(pct, resetsAt, windowSeconds)} (${timeLabel})`;
|
|
8598
8700
|
}
|
|
8599
8701
|
function buildLimitsSegment(rateLimits) {
|
|
8600
8702
|
const fiveHrPct = rateLimits?.five_hour?.used_percentage;
|
|
8601
8703
|
const sevenDayPct = rateLimits?.seven_day?.used_percentage;
|
|
8602
8704
|
if (fiveHrPct == null || sevenDayPct == null) return "";
|
|
8603
|
-
const fiveHr =
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8705
|
+
const fiveHr = formatLimit(
|
|
8706
|
+
fiveHrPct,
|
|
8707
|
+
rateLimits?.five_hour?.resets_at,
|
|
8708
|
+
FIVE_HOUR_SECONDS,
|
|
8709
|
+
"5h"
|
|
8710
|
+
);
|
|
8711
|
+
const sevenDay = formatLimit(
|
|
8712
|
+
sevenDayPct,
|
|
8713
|
+
rateLimits?.seven_day?.resets_at,
|
|
8714
|
+
SEVEN_DAY_SECONDS,
|
|
8715
|
+
"7d"
|
|
8716
|
+
);
|
|
8717
|
+
return ` | Limits - ${fiveHr}, ${sevenDay}`;
|
|
8718
|
+
}
|
|
8719
|
+
|
|
8720
|
+
// src/commands/statusLine.ts
|
|
8721
|
+
chalk86.level = 3;
|
|
8722
|
+
function formatNumber(num) {
|
|
8723
|
+
return num.toLocaleString("en-US");
|
|
8724
|
+
}
|
|
8725
|
+
function colorizePercent(pct) {
|
|
8726
|
+
const label2 = `${Math.round(pct)}%`;
|
|
8727
|
+
if (pct > 80) return chalk86.red(label2);
|
|
8728
|
+
if (pct > 40) return chalk86.yellow(label2);
|
|
8729
|
+
return label2;
|
|
8612
8730
|
}
|
|
8613
8731
|
async function statusLine() {
|
|
8614
8732
|
const inputData = await readStdin();
|
|
@@ -8630,7 +8748,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
8630
8748
|
// src/commands/sync/syncClaudeMd.ts
|
|
8631
8749
|
import * as fs22 from "fs";
|
|
8632
8750
|
import * as path40 from "path";
|
|
8633
|
-
import
|
|
8751
|
+
import chalk87 from "chalk";
|
|
8634
8752
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
8635
8753
|
const source = path40.join(claudeDir, "CLAUDE.md");
|
|
8636
8754
|
const target = path40.join(targetBase, "CLAUDE.md");
|
|
@@ -8639,12 +8757,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
8639
8757
|
const targetContent = fs22.readFileSync(target, "utf-8");
|
|
8640
8758
|
if (sourceContent !== targetContent) {
|
|
8641
8759
|
console.log(
|
|
8642
|
-
|
|
8760
|
+
chalk87.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
8643
8761
|
);
|
|
8644
8762
|
console.log();
|
|
8645
8763
|
printDiff(targetContent, sourceContent);
|
|
8646
8764
|
const confirm = await promptConfirm(
|
|
8647
|
-
|
|
8765
|
+
chalk87.red("Overwrite existing CLAUDE.md?"),
|
|
8648
8766
|
false
|
|
8649
8767
|
);
|
|
8650
8768
|
if (!confirm) {
|
|
@@ -8660,7 +8778,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
8660
8778
|
// src/commands/sync/syncSettings.ts
|
|
8661
8779
|
import * as fs23 from "fs";
|
|
8662
8780
|
import * as path41 from "path";
|
|
8663
|
-
import
|
|
8781
|
+
import chalk88 from "chalk";
|
|
8664
8782
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
8665
8783
|
const source = path41.join(claudeDir, "settings.json");
|
|
8666
8784
|
const target = path41.join(targetBase, "settings.json");
|
|
@@ -8676,14 +8794,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
8676
8794
|
if (mergedContent !== normalizedTarget) {
|
|
8677
8795
|
if (!options2?.yes) {
|
|
8678
8796
|
console.log(
|
|
8679
|
-
|
|
8797
|
+
chalk88.yellow(
|
|
8680
8798
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
8681
8799
|
)
|
|
8682
8800
|
);
|
|
8683
8801
|
console.log();
|
|
8684
8802
|
printDiff(targetContent, mergedContent);
|
|
8685
8803
|
const confirm = await promptConfirm(
|
|
8686
|
-
|
|
8804
|
+
chalk88.red("Overwrite existing settings.json?"),
|
|
8687
8805
|
false
|
|
8688
8806
|
);
|
|
8689
8807
|
if (!confirm) {
|
|
@@ -8720,7 +8838,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
8720
8838
|
}
|
|
8721
8839
|
|
|
8722
8840
|
// src/commands/update.ts
|
|
8723
|
-
import { execSync as
|
|
8841
|
+
import { execSync as execSync38 } from "child_process";
|
|
8724
8842
|
import * as path43 from "path";
|
|
8725
8843
|
function isGlobalNpmInstall(dir) {
|
|
8726
8844
|
try {
|
|
@@ -8728,7 +8846,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
8728
8846
|
if (resolved.split(path43.sep).includes("node_modules")) {
|
|
8729
8847
|
return true;
|
|
8730
8848
|
}
|
|
8731
|
-
const globalPrefix =
|
|
8849
|
+
const globalPrefix = execSync38("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
8732
8850
|
return resolved.toLowerCase().startsWith(path43.resolve(globalPrefix).toLowerCase());
|
|
8733
8851
|
} catch {
|
|
8734
8852
|
return false;
|
|
@@ -8739,18 +8857,18 @@ async function update() {
|
|
|
8739
8857
|
console.log(`Assist is installed at: ${installDir}`);
|
|
8740
8858
|
if (isGitRepo(installDir)) {
|
|
8741
8859
|
console.log("Detected git repo installation, pulling latest...");
|
|
8742
|
-
|
|
8860
|
+
execSync38("git pull", { cwd: installDir, stdio: "inherit" });
|
|
8743
8861
|
console.log("Installing dependencies...");
|
|
8744
|
-
|
|
8862
|
+
execSync38("npm i", { cwd: installDir, stdio: "inherit" });
|
|
8745
8863
|
console.log("Building...");
|
|
8746
|
-
|
|
8864
|
+
execSync38("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
8747
8865
|
console.log("Syncing commands...");
|
|
8748
|
-
|
|
8866
|
+
execSync38("assist sync", { stdio: "inherit" });
|
|
8749
8867
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
8750
8868
|
console.log("Detected global npm installation, updating...");
|
|
8751
|
-
|
|
8869
|
+
execSync38("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
8752
8870
|
console.log("Syncing commands...");
|
|
8753
|
-
|
|
8871
|
+
execSync38("assist sync", { stdio: "inherit" });
|
|
8754
8872
|
} else {
|
|
8755
8873
|
console.error(
|
|
8756
8874
|
"Could not determine installation method. Expected a git repo or global npm install."
|