@staff0rd/assist 0.265.0 → 0.267.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 +2 -2
- package/dist/commands/sessions/web/bundle.js +52 -51
- package/dist/index.js +243 -97
- package/package.json +2 -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.267.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -89,6 +89,7 @@ var package_default = {
|
|
|
89
89
|
"@types/ws": "^8.18.1",
|
|
90
90
|
"@vitest/coverage-v8": "^4.1.2",
|
|
91
91
|
"@xterm/addon-fit": "^0.11.0",
|
|
92
|
+
"@xterm/addon-web-links": "^0.12.0",
|
|
92
93
|
"@xterm/xterm": "^6.0.0",
|
|
93
94
|
esbuild: "^0.27.3",
|
|
94
95
|
jscpd: "^4.0.5",
|
|
@@ -9445,6 +9446,21 @@ function buildArgs2(queryFile, vars) {
|
|
|
9445
9446
|
}
|
|
9446
9447
|
return args;
|
|
9447
9448
|
}
|
|
9449
|
+
function throwOnGraphqlErrors(stdout) {
|
|
9450
|
+
let parsed;
|
|
9451
|
+
try {
|
|
9452
|
+
parsed = JSON.parse(stdout);
|
|
9453
|
+
} catch {
|
|
9454
|
+
return;
|
|
9455
|
+
}
|
|
9456
|
+
if (!parsed || typeof parsed !== "object") return;
|
|
9457
|
+
const errors = parsed.errors;
|
|
9458
|
+
if (!Array.isArray(errors) || errors.length === 0) return;
|
|
9459
|
+
const messages = errors.map(
|
|
9460
|
+
(entry) => entry && typeof entry === "object" && "message" in entry ? String(entry.message) : String(entry)
|
|
9461
|
+
).join("; ");
|
|
9462
|
+
throw new Error(messages || "GraphQL request returned errors");
|
|
9463
|
+
}
|
|
9448
9464
|
function runGhGraphql(mutation, vars) {
|
|
9449
9465
|
const queryFile = join28(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
9450
9466
|
writeFileSync19(queryFile, mutation);
|
|
@@ -9453,6 +9469,7 @@ function runGhGraphql(mutation, vars) {
|
|
|
9453
9469
|
encoding: "utf-8"
|
|
9454
9470
|
});
|
|
9455
9471
|
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
9472
|
+
throwOnGraphqlErrors(result.stdout);
|
|
9456
9473
|
return result.stdout;
|
|
9457
9474
|
} finally {
|
|
9458
9475
|
unlinkSync7(queryFile);
|
|
@@ -10596,13 +10613,24 @@ function validateLine(line) {
|
|
|
10596
10613
|
process.exit(1);
|
|
10597
10614
|
}
|
|
10598
10615
|
}
|
|
10616
|
+
function assertThreadCreated(stdout) {
|
|
10617
|
+
let parsed;
|
|
10618
|
+
try {
|
|
10619
|
+
parsed = JSON.parse(stdout);
|
|
10620
|
+
} catch {
|
|
10621
|
+
throw new Error(`GitHub returned an unparseable response: ${stdout}`);
|
|
10622
|
+
}
|
|
10623
|
+
const id = parsed.data?.addPullRequestReviewThread?.thread?.id;
|
|
10624
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
10625
|
+
throw new Error(
|
|
10626
|
+
"GitHub did not create a review thread (no thread id returned); the line is likely outside the PR diff."
|
|
10627
|
+
);
|
|
10628
|
+
}
|
|
10629
|
+
}
|
|
10599
10630
|
function postComment(vars) {
|
|
10600
10631
|
const { startLine, ...base } = vars;
|
|
10601
|
-
|
|
10602
|
-
|
|
10603
|
-
return;
|
|
10604
|
-
}
|
|
10605
|
-
runGhGraphql(MUTATION_MULTI, { ...base, startLine });
|
|
10632
|
+
const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
|
|
10633
|
+
assertThreadCreated(stdout);
|
|
10606
10634
|
}
|
|
10607
10635
|
function comment2(path53, line, body, startLine) {
|
|
10608
10636
|
validateBody(body);
|
|
@@ -13180,6 +13208,37 @@ function registerRefactor(program2) {
|
|
|
13180
13208
|
// src/commands/review/review.ts
|
|
13181
13209
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
13182
13210
|
|
|
13211
|
+
// src/commands/review/annotateDiffWithLineNumbers.ts
|
|
13212
|
+
var FILE_HEADER2 = /^\+\+\+ (?:b\/)?(.+)$/;
|
|
13213
|
+
var HUNK_HEADER2 = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
13214
|
+
var GUTTER_WIDTH = 6;
|
|
13215
|
+
function gutter(lineNumber) {
|
|
13216
|
+
const label2 = lineNumber === null ? "" : String(lineNumber);
|
|
13217
|
+
return `${label2.padStart(GUTTER_WIDTH, " ")} `;
|
|
13218
|
+
}
|
|
13219
|
+
function annotateDiffWithLineNumbers(diff2) {
|
|
13220
|
+
let inFile = false;
|
|
13221
|
+
let newLine = 0;
|
|
13222
|
+
return diff2.split("\n").map((line) => {
|
|
13223
|
+
if (FILE_HEADER2.test(line)) {
|
|
13224
|
+
inFile = true;
|
|
13225
|
+
return gutter(null) + line;
|
|
13226
|
+
}
|
|
13227
|
+
const hunkMatch = line.match(HUNK_HEADER2);
|
|
13228
|
+
if (hunkMatch) {
|
|
13229
|
+
newLine = Number(hunkMatch[1]);
|
|
13230
|
+
return gutter(null) + line;
|
|
13231
|
+
}
|
|
13232
|
+
if (!inFile) return gutter(null) + line;
|
|
13233
|
+
if (line.startsWith("+") || line.startsWith(" ")) {
|
|
13234
|
+
const annotated = gutter(newLine) + line;
|
|
13235
|
+
newLine++;
|
|
13236
|
+
return annotated;
|
|
13237
|
+
}
|
|
13238
|
+
return gutter(null) + line;
|
|
13239
|
+
}).join("\n");
|
|
13240
|
+
}
|
|
13241
|
+
|
|
13183
13242
|
// src/commands/review/formatPriorComments.ts
|
|
13184
13243
|
function threadKey(c, byId) {
|
|
13185
13244
|
if (c.threadId) return c.threadId;
|
|
@@ -13253,8 +13312,10 @@ ${formatFiles(context.changedFiles)}
|
|
|
13253
13312
|
${priorBlock}
|
|
13254
13313
|
## Diff (PR #${context.prNumber}: ${context.baseSha}..${context.headSha})
|
|
13255
13314
|
|
|
13315
|
+
Each added or context line is prefixed with a left gutter showing its line number in the new file. When citing a finding as \`file:line\`, use that gutter number \u2014 do **not** count lines in this document. Removed lines (\`-\`) and headers have a blank gutter and cannot be commented on.
|
|
13316
|
+
|
|
13256
13317
|
\`\`\`diff
|
|
13257
|
-
${context.diff.trimEnd()}
|
|
13318
|
+
${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
13258
13319
|
\`\`\`
|
|
13259
13320
|
`;
|
|
13260
13321
|
}
|
|
@@ -13642,19 +13703,102 @@ async function postAndMaybeSubmit(lineBound, markdown, options2) {
|
|
|
13642
13703
|
console.log("Leaving pending review unsubmitted.");
|
|
13643
13704
|
}
|
|
13644
13705
|
|
|
13645
|
-
// src/commands/review/
|
|
13706
|
+
// src/commands/review/buildDiffLineIndex.ts
|
|
13707
|
+
var FILE_HEADER3 = /^\+\+\+ (?:b\/)?(.+)$/;
|
|
13708
|
+
var HUNK_HEADER3 = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
13709
|
+
function buildDiffLineIndex(diff2) {
|
|
13710
|
+
const index2 = /* @__PURE__ */ new Map();
|
|
13711
|
+
let currentFile = null;
|
|
13712
|
+
let newLine = 0;
|
|
13713
|
+
for (const line of diff2.split("\n")) {
|
|
13714
|
+
const fileMatch = line.match(FILE_HEADER3);
|
|
13715
|
+
if (fileMatch) {
|
|
13716
|
+
currentFile = fileMatch[1] === "/dev/null" ? null : fileMatch[1];
|
|
13717
|
+
continue;
|
|
13718
|
+
}
|
|
13719
|
+
const hunkMatch = line.match(HUNK_HEADER3);
|
|
13720
|
+
if (hunkMatch) {
|
|
13721
|
+
newLine = Number(hunkMatch[1]);
|
|
13722
|
+
continue;
|
|
13723
|
+
}
|
|
13724
|
+
if (currentFile === null) continue;
|
|
13725
|
+
if (line.startsWith("-")) continue;
|
|
13726
|
+
if (line.startsWith("+") || line.startsWith(" ")) {
|
|
13727
|
+
let set = index2.get(currentFile);
|
|
13728
|
+
if (!set) {
|
|
13729
|
+
set = /* @__PURE__ */ new Set();
|
|
13730
|
+
index2.set(currentFile, set);
|
|
13731
|
+
}
|
|
13732
|
+
set.add(newLine);
|
|
13733
|
+
newLine++;
|
|
13734
|
+
}
|
|
13735
|
+
}
|
|
13736
|
+
return index2;
|
|
13737
|
+
}
|
|
13738
|
+
|
|
13739
|
+
// src/commands/review/partitionFindingsByDiff.ts
|
|
13740
|
+
function isWithinDiff(finding, index2) {
|
|
13741
|
+
const lines = index2.get(finding.file);
|
|
13742
|
+
if (!lines) return false;
|
|
13743
|
+
if (!lines.has(finding.line)) return false;
|
|
13744
|
+
if (finding.startLine !== void 0 && !lines.has(finding.startLine)) {
|
|
13745
|
+
return false;
|
|
13746
|
+
}
|
|
13747
|
+
return true;
|
|
13748
|
+
}
|
|
13749
|
+
function partitionFindingsByDiff(findings, index2) {
|
|
13750
|
+
const inDiff = [];
|
|
13751
|
+
const outOfDiff = [];
|
|
13752
|
+
for (const finding of findings) {
|
|
13753
|
+
if (isWithinDiff(finding, index2)) inDiff.push(finding);
|
|
13754
|
+
else outOfDiff.push(finding);
|
|
13755
|
+
}
|
|
13756
|
+
return { inDiff, outOfDiff };
|
|
13757
|
+
}
|
|
13758
|
+
|
|
13759
|
+
// src/commands/review/warnOutOfDiff.ts
|
|
13646
13760
|
import chalk142 from "chalk";
|
|
13761
|
+
function warnOutOfDiff(outOfDiff) {
|
|
13762
|
+
if (outOfDiff.length === 0) return;
|
|
13763
|
+
console.warn(
|
|
13764
|
+
chalk142.yellow(
|
|
13765
|
+
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
13766
|
+
)
|
|
13767
|
+
);
|
|
13768
|
+
for (const finding of outOfDiff) {
|
|
13769
|
+
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
13770
|
+
console.warn(
|
|
13771
|
+
` ${chalk142.yellow("\xB7")} ${finding.title} ${chalk142.dim(
|
|
13772
|
+
`(${finding.file}:${range})`
|
|
13773
|
+
)}`
|
|
13774
|
+
);
|
|
13775
|
+
}
|
|
13776
|
+
}
|
|
13777
|
+
|
|
13778
|
+
// src/commands/review/selectInDiffFindings.ts
|
|
13779
|
+
function selectInDiffFindings(lineBound, prDiff) {
|
|
13780
|
+
const diff2 = fetchPrDiff(prDiff.prNumber, prDiff.baseSha, prDiff.headSha);
|
|
13781
|
+
const { inDiff, outOfDiff } = partitionFindingsByDiff(
|
|
13782
|
+
lineBound,
|
|
13783
|
+
buildDiffLineIndex(diff2)
|
|
13784
|
+
);
|
|
13785
|
+
warnOutOfDiff(outOfDiff);
|
|
13786
|
+
return inDiff;
|
|
13787
|
+
}
|
|
13788
|
+
|
|
13789
|
+
// src/commands/review/warnUnlocated.ts
|
|
13790
|
+
import chalk143 from "chalk";
|
|
13647
13791
|
function warnUnlocated(unlocated) {
|
|
13648
13792
|
if (unlocated.length === 0) return;
|
|
13649
13793
|
console.warn(
|
|
13650
|
-
|
|
13794
|
+
chalk143.yellow(
|
|
13651
13795
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
13652
13796
|
)
|
|
13653
13797
|
);
|
|
13654
13798
|
for (const finding of unlocated) {
|
|
13655
|
-
const where = finding.location ||
|
|
13799
|
+
const where = finding.location || chalk143.dim("missing");
|
|
13656
13800
|
console.warn(
|
|
13657
|
-
` ${
|
|
13801
|
+
` ${chalk143.yellow("\xB7")} ${finding.title} ${chalk143.dim(`(${where})`)}`
|
|
13658
13802
|
);
|
|
13659
13803
|
}
|
|
13660
13804
|
}
|
|
@@ -13665,11 +13809,8 @@ async function confirmPost(prNumber, count6, options2) {
|
|
|
13665
13809
|
return promptConfirm(`Post ${count6} comment(s) to PR #${prNumber}?`, false);
|
|
13666
13810
|
}
|
|
13667
13811
|
async function postReviewToPr(synthesisPath, options2) {
|
|
13668
|
-
const
|
|
13669
|
-
|
|
13670
|
-
console.log("No PR found for current branch; nothing posted.");
|
|
13671
|
-
return;
|
|
13672
|
-
}
|
|
13812
|
+
const prInfo = fetchPrDiffInfo();
|
|
13813
|
+
const prNumber = prInfo.prNumber;
|
|
13673
13814
|
const markdown = readFileSync31(synthesisPath, "utf-8");
|
|
13674
13815
|
const findings = parseFindings(markdown);
|
|
13675
13816
|
if (findings.length === 0) {
|
|
@@ -13687,15 +13828,20 @@ async function postReviewToPr(synthesisPath, options2) {
|
|
|
13687
13828
|
console.log("No line-bound findings to post.");
|
|
13688
13829
|
return;
|
|
13689
13830
|
}
|
|
13831
|
+
const inDiff = selectInDiffFindings(lineBound, prInfo);
|
|
13832
|
+
if (inDiff.length === 0) {
|
|
13833
|
+
console.log("No findings fall within the PR diff; nothing to post.");
|
|
13834
|
+
return;
|
|
13835
|
+
}
|
|
13690
13836
|
console.log(
|
|
13691
|
-
`Found PR #${prNumber} with ${
|
|
13837
|
+
`Found PR #${prNumber} with ${inDiff.length} line-bound finding(s) in the diff.`
|
|
13692
13838
|
);
|
|
13693
|
-
const confirmed = await confirmPost(prNumber,
|
|
13839
|
+
const confirmed = await confirmPost(prNumber, inDiff.length, options2);
|
|
13694
13840
|
if (!confirmed) {
|
|
13695
13841
|
console.log("Skipped posting.");
|
|
13696
13842
|
return;
|
|
13697
13843
|
}
|
|
13698
|
-
await postAndMaybeSubmit(
|
|
13844
|
+
await postAndMaybeSubmit(inDiff, markdown, options2);
|
|
13699
13845
|
}
|
|
13700
13846
|
|
|
13701
13847
|
// src/commands/review/runRefineSession.ts
|
|
@@ -14076,7 +14222,7 @@ List every finding that the original author would want to know about and fix. Do
|
|
|
14076
14222
|
|
|
14077
14223
|
For each finding include:
|
|
14078
14224
|
- Severity (blocker, major, minor, nit) \u2014 see rubric below
|
|
14079
|
-
- File and line (e.g. \`src/foo.ts:42\`) when the finding is tied to a specific location
|
|
14225
|
+
- File and line (e.g. \`src/foo.ts:42\`) when the finding is tied to a specific location. Take the line number from the diff's left gutter (its line in the new file); never count lines in request.md.
|
|
14080
14226
|
- Impact: what could go wrong, including the conditions under which it manifests
|
|
14081
14227
|
- Recommendation: a concrete change
|
|
14082
14228
|
|
|
@@ -14826,7 +14972,7 @@ function registerReview(program2) {
|
|
|
14826
14972
|
}
|
|
14827
14973
|
|
|
14828
14974
|
// src/commands/seq/seqAuth.ts
|
|
14829
|
-
import
|
|
14975
|
+
import chalk145 from "chalk";
|
|
14830
14976
|
|
|
14831
14977
|
// src/commands/seq/loadConnections.ts
|
|
14832
14978
|
function loadConnections2() {
|
|
@@ -14855,10 +15001,10 @@ function setDefaultConnection(name) {
|
|
|
14855
15001
|
}
|
|
14856
15002
|
|
|
14857
15003
|
// src/shared/assertUniqueName.ts
|
|
14858
|
-
import
|
|
15004
|
+
import chalk144 from "chalk";
|
|
14859
15005
|
function assertUniqueName(existingNames, name) {
|
|
14860
15006
|
if (existingNames.includes(name)) {
|
|
14861
|
-
console.error(
|
|
15007
|
+
console.error(chalk144.red(`Connection "${name}" already exists.`));
|
|
14862
15008
|
process.exit(1);
|
|
14863
15009
|
}
|
|
14864
15010
|
}
|
|
@@ -14876,16 +15022,16 @@ async function promptConnection2(existingNames) {
|
|
|
14876
15022
|
var seqAuth = createConnectionAuth({
|
|
14877
15023
|
load: loadConnections2,
|
|
14878
15024
|
save: saveConnections2,
|
|
14879
|
-
format: (c) => `${
|
|
15025
|
+
format: (c) => `${chalk145.bold(c.name)} ${c.url}`,
|
|
14880
15026
|
promptNew: promptConnection2,
|
|
14881
15027
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
14882
15028
|
});
|
|
14883
15029
|
|
|
14884
15030
|
// src/commands/seq/seqQuery.ts
|
|
14885
|
-
import
|
|
15031
|
+
import chalk149 from "chalk";
|
|
14886
15032
|
|
|
14887
15033
|
// src/commands/seq/fetchSeq.ts
|
|
14888
|
-
import
|
|
15034
|
+
import chalk146 from "chalk";
|
|
14889
15035
|
async function fetchSeq(conn, path53, params) {
|
|
14890
15036
|
const url = `${conn.url}${path53}?${params}`;
|
|
14891
15037
|
const response = await fetch(url, {
|
|
@@ -14896,7 +15042,7 @@ async function fetchSeq(conn, path53, params) {
|
|
|
14896
15042
|
});
|
|
14897
15043
|
if (!response.ok) {
|
|
14898
15044
|
const body = await response.text();
|
|
14899
|
-
console.error(
|
|
15045
|
+
console.error(chalk146.red(`Seq returned ${response.status}: ${body}`));
|
|
14900
15046
|
process.exit(1);
|
|
14901
15047
|
}
|
|
14902
15048
|
return response;
|
|
@@ -14951,23 +15097,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
14951
15097
|
}
|
|
14952
15098
|
|
|
14953
15099
|
// src/commands/seq/formatEvent.ts
|
|
14954
|
-
import
|
|
15100
|
+
import chalk147 from "chalk";
|
|
14955
15101
|
function levelColor(level) {
|
|
14956
15102
|
switch (level) {
|
|
14957
15103
|
case "Fatal":
|
|
14958
|
-
return
|
|
15104
|
+
return chalk147.bgRed.white;
|
|
14959
15105
|
case "Error":
|
|
14960
|
-
return
|
|
15106
|
+
return chalk147.red;
|
|
14961
15107
|
case "Warning":
|
|
14962
|
-
return
|
|
15108
|
+
return chalk147.yellow;
|
|
14963
15109
|
case "Information":
|
|
14964
|
-
return
|
|
15110
|
+
return chalk147.cyan;
|
|
14965
15111
|
case "Debug":
|
|
14966
|
-
return
|
|
15112
|
+
return chalk147.gray;
|
|
14967
15113
|
case "Verbose":
|
|
14968
|
-
return
|
|
15114
|
+
return chalk147.dim;
|
|
14969
15115
|
default:
|
|
14970
|
-
return
|
|
15116
|
+
return chalk147.white;
|
|
14971
15117
|
}
|
|
14972
15118
|
}
|
|
14973
15119
|
function levelAbbrev(level) {
|
|
@@ -15008,12 +15154,12 @@ function formatTimestamp(iso) {
|
|
|
15008
15154
|
function formatEvent(event) {
|
|
15009
15155
|
const color = levelColor(event.Level);
|
|
15010
15156
|
const abbrev = levelAbbrev(event.Level);
|
|
15011
|
-
const ts8 =
|
|
15157
|
+
const ts8 = chalk147.dim(formatTimestamp(event.Timestamp));
|
|
15012
15158
|
const msg = renderMessage(event);
|
|
15013
15159
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
15014
15160
|
if (event.Exception) {
|
|
15015
15161
|
for (const line of event.Exception.split("\n")) {
|
|
15016
|
-
lines.push(
|
|
15162
|
+
lines.push(chalk147.red(` ${line}`));
|
|
15017
15163
|
}
|
|
15018
15164
|
}
|
|
15019
15165
|
return lines.join("\n");
|
|
@@ -15046,11 +15192,11 @@ function rejectTimestampFilter(filter) {
|
|
|
15046
15192
|
}
|
|
15047
15193
|
|
|
15048
15194
|
// src/shared/resolveNamedConnection.ts
|
|
15049
|
-
import
|
|
15195
|
+
import chalk148 from "chalk";
|
|
15050
15196
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
15051
15197
|
if (connections.length === 0) {
|
|
15052
15198
|
console.error(
|
|
15053
|
-
|
|
15199
|
+
chalk148.red(
|
|
15054
15200
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
15055
15201
|
)
|
|
15056
15202
|
);
|
|
@@ -15059,7 +15205,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
15059
15205
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
15060
15206
|
const connection = connections.find((c) => c.name === target);
|
|
15061
15207
|
if (!connection) {
|
|
15062
|
-
console.error(
|
|
15208
|
+
console.error(chalk148.red(`${kind} connection "${target}" not found.`));
|
|
15063
15209
|
process.exit(1);
|
|
15064
15210
|
}
|
|
15065
15211
|
return connection;
|
|
@@ -15088,7 +15234,7 @@ async function seqQuery(filter, options2) {
|
|
|
15088
15234
|
new URLSearchParams({ filter, count: String(count6) })
|
|
15089
15235
|
);
|
|
15090
15236
|
if (events.length === 0) {
|
|
15091
|
-
console.log(
|
|
15237
|
+
console.log(chalk149.yellow("No events found."));
|
|
15092
15238
|
return;
|
|
15093
15239
|
}
|
|
15094
15240
|
if (options2.json) {
|
|
@@ -15099,11 +15245,11 @@ async function seqQuery(filter, options2) {
|
|
|
15099
15245
|
for (const event of chronological) {
|
|
15100
15246
|
console.log(formatEvent(event));
|
|
15101
15247
|
}
|
|
15102
|
-
console.log(
|
|
15248
|
+
console.log(chalk149.dim(`
|
|
15103
15249
|
${events.length} events`));
|
|
15104
15250
|
if (events.length >= count6) {
|
|
15105
15251
|
console.log(
|
|
15106
|
-
|
|
15252
|
+
chalk149.yellow(
|
|
15107
15253
|
`Results limited to ${count6}. Use --count to retrieve more.`
|
|
15108
15254
|
)
|
|
15109
15255
|
);
|
|
@@ -15111,10 +15257,10 @@ ${events.length} events`));
|
|
|
15111
15257
|
}
|
|
15112
15258
|
|
|
15113
15259
|
// src/shared/setNamedDefaultConnection.ts
|
|
15114
|
-
import
|
|
15260
|
+
import chalk150 from "chalk";
|
|
15115
15261
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
15116
15262
|
if (!connections.find((c) => c.name === name)) {
|
|
15117
|
-
console.error(
|
|
15263
|
+
console.error(chalk150.red(`Connection "${name}" not found.`));
|
|
15118
15264
|
process.exit(1);
|
|
15119
15265
|
}
|
|
15120
15266
|
setDefault(name);
|
|
@@ -15162,7 +15308,7 @@ function registerSignal(program2) {
|
|
|
15162
15308
|
}
|
|
15163
15309
|
|
|
15164
15310
|
// src/commands/sql/sqlAuth.ts
|
|
15165
|
-
import
|
|
15311
|
+
import chalk152 from "chalk";
|
|
15166
15312
|
|
|
15167
15313
|
// src/commands/sql/loadConnections.ts
|
|
15168
15314
|
function loadConnections3() {
|
|
@@ -15191,7 +15337,7 @@ function setDefaultConnection2(name) {
|
|
|
15191
15337
|
}
|
|
15192
15338
|
|
|
15193
15339
|
// src/commands/sql/promptConnection.ts
|
|
15194
|
-
import
|
|
15340
|
+
import chalk151 from "chalk";
|
|
15195
15341
|
async function promptConnection3(existingNames) {
|
|
15196
15342
|
const name = await promptInput("name", "Connection name:", "default");
|
|
15197
15343
|
assertUniqueName(existingNames, name);
|
|
@@ -15199,7 +15345,7 @@ async function promptConnection3(existingNames) {
|
|
|
15199
15345
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
15200
15346
|
const port = Number.parseInt(portStr, 10);
|
|
15201
15347
|
if (!Number.isFinite(port)) {
|
|
15202
|
-
console.error(
|
|
15348
|
+
console.error(chalk151.red(`Invalid port "${portStr}".`));
|
|
15203
15349
|
process.exit(1);
|
|
15204
15350
|
}
|
|
15205
15351
|
const user = await promptInput("user", "User:");
|
|
@@ -15212,13 +15358,13 @@ async function promptConnection3(existingNames) {
|
|
|
15212
15358
|
var sqlAuth = createConnectionAuth({
|
|
15213
15359
|
load: loadConnections3,
|
|
15214
15360
|
save: saveConnections3,
|
|
15215
|
-
format: (c) => `${
|
|
15361
|
+
format: (c) => `${chalk152.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
15216
15362
|
promptNew: promptConnection3,
|
|
15217
15363
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
15218
15364
|
});
|
|
15219
15365
|
|
|
15220
15366
|
// src/commands/sql/printTable.ts
|
|
15221
|
-
import
|
|
15367
|
+
import chalk153 from "chalk";
|
|
15222
15368
|
function formatCell(value) {
|
|
15223
15369
|
if (value === null || value === void 0) return "";
|
|
15224
15370
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -15227,7 +15373,7 @@ function formatCell(value) {
|
|
|
15227
15373
|
}
|
|
15228
15374
|
function printTable(rows) {
|
|
15229
15375
|
if (rows.length === 0) {
|
|
15230
|
-
console.log(
|
|
15376
|
+
console.log(chalk153.yellow("(no rows)"));
|
|
15231
15377
|
return;
|
|
15232
15378
|
}
|
|
15233
15379
|
const columns = Object.keys(rows[0]);
|
|
@@ -15235,13 +15381,13 @@ function printTable(rows) {
|
|
|
15235
15381
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
15236
15382
|
);
|
|
15237
15383
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
15238
|
-
console.log(
|
|
15239
|
-
console.log(
|
|
15384
|
+
console.log(chalk153.dim(header));
|
|
15385
|
+
console.log(chalk153.dim("-".repeat(header.length)));
|
|
15240
15386
|
for (const row of rows) {
|
|
15241
15387
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
15242
15388
|
console.log(line);
|
|
15243
15389
|
}
|
|
15244
|
-
console.log(
|
|
15390
|
+
console.log(chalk153.dim(`
|
|
15245
15391
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
15246
15392
|
}
|
|
15247
15393
|
|
|
@@ -15301,7 +15447,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
15301
15447
|
}
|
|
15302
15448
|
|
|
15303
15449
|
// src/commands/sql/sqlMutate.ts
|
|
15304
|
-
import
|
|
15450
|
+
import chalk154 from "chalk";
|
|
15305
15451
|
|
|
15306
15452
|
// src/commands/sql/isMutation.ts
|
|
15307
15453
|
var MUTATION_KEYWORDS = [
|
|
@@ -15335,7 +15481,7 @@ function isMutation(sql4) {
|
|
|
15335
15481
|
async function sqlMutate(query, connectionName) {
|
|
15336
15482
|
if (!isMutation(query)) {
|
|
15337
15483
|
console.error(
|
|
15338
|
-
|
|
15484
|
+
chalk154.red(
|
|
15339
15485
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
15340
15486
|
)
|
|
15341
15487
|
);
|
|
@@ -15345,18 +15491,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
15345
15491
|
const pool = await sqlConnect(conn);
|
|
15346
15492
|
try {
|
|
15347
15493
|
const result = await pool.request().query(query);
|
|
15348
|
-
console.log(
|
|
15494
|
+
console.log(chalk154.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
15349
15495
|
} finally {
|
|
15350
15496
|
await pool.close();
|
|
15351
15497
|
}
|
|
15352
15498
|
}
|
|
15353
15499
|
|
|
15354
15500
|
// src/commands/sql/sqlQuery.ts
|
|
15355
|
-
import
|
|
15501
|
+
import chalk155 from "chalk";
|
|
15356
15502
|
async function sqlQuery(query, connectionName) {
|
|
15357
15503
|
if (isMutation(query)) {
|
|
15358
15504
|
console.error(
|
|
15359
|
-
|
|
15505
|
+
chalk155.red(
|
|
15360
15506
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
15361
15507
|
)
|
|
15362
15508
|
);
|
|
@@ -15371,7 +15517,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
15371
15517
|
printTable(rows);
|
|
15372
15518
|
} else {
|
|
15373
15519
|
console.log(
|
|
15374
|
-
|
|
15520
|
+
chalk155.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
15375
15521
|
);
|
|
15376
15522
|
}
|
|
15377
15523
|
} finally {
|
|
@@ -15951,14 +16097,14 @@ import {
|
|
|
15951
16097
|
import { dirname as dirname22, join as join42 } from "path";
|
|
15952
16098
|
|
|
15953
16099
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
15954
|
-
import
|
|
16100
|
+
import chalk156 from "chalk";
|
|
15955
16101
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
15956
16102
|
function validateStagedContent(filename, content) {
|
|
15957
16103
|
const firstLine = content.split("\n")[0];
|
|
15958
16104
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
15959
16105
|
if (!match) {
|
|
15960
16106
|
console.error(
|
|
15961
|
-
|
|
16107
|
+
chalk156.red(
|
|
15962
16108
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
15963
16109
|
)
|
|
15964
16110
|
);
|
|
@@ -15967,7 +16113,7 @@ function validateStagedContent(filename, content) {
|
|
|
15967
16113
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
15968
16114
|
if (!contentAfterLink) {
|
|
15969
16115
|
console.error(
|
|
15970
|
-
|
|
16116
|
+
chalk156.red(
|
|
15971
16117
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
15972
16118
|
)
|
|
15973
16119
|
);
|
|
@@ -16364,7 +16510,7 @@ function registerVoice(program2) {
|
|
|
16364
16510
|
|
|
16365
16511
|
// src/commands/roam/auth.ts
|
|
16366
16512
|
import { randomBytes } from "crypto";
|
|
16367
|
-
import
|
|
16513
|
+
import chalk157 from "chalk";
|
|
16368
16514
|
|
|
16369
16515
|
// src/lib/openBrowser.ts
|
|
16370
16516
|
import { execSync as execSync46 } from "child_process";
|
|
@@ -16539,13 +16685,13 @@ async function auth() {
|
|
|
16539
16685
|
saveGlobalConfig(config);
|
|
16540
16686
|
const state = randomBytes(16).toString("hex");
|
|
16541
16687
|
console.log(
|
|
16542
|
-
|
|
16688
|
+
chalk157.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
16543
16689
|
);
|
|
16544
|
-
console.log(
|
|
16545
|
-
console.log(
|
|
16546
|
-
console.log(
|
|
16690
|
+
console.log(chalk157.white("http://localhost:14523/callback\n"));
|
|
16691
|
+
console.log(chalk157.blue("Opening browser for authorization..."));
|
|
16692
|
+
console.log(chalk157.dim("Waiting for authorization callback..."));
|
|
16547
16693
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
16548
|
-
console.log(
|
|
16694
|
+
console.log(chalk157.dim("Exchanging code for tokens..."));
|
|
16549
16695
|
const tokens = await exchangeToken({
|
|
16550
16696
|
code,
|
|
16551
16697
|
clientId,
|
|
@@ -16561,7 +16707,7 @@ async function auth() {
|
|
|
16561
16707
|
};
|
|
16562
16708
|
saveGlobalConfig(config);
|
|
16563
16709
|
console.log(
|
|
16564
|
-
|
|
16710
|
+
chalk157.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
16565
16711
|
);
|
|
16566
16712
|
}
|
|
16567
16713
|
|
|
@@ -17013,7 +17159,7 @@ import { execSync as execSync48 } from "child_process";
|
|
|
17013
17159
|
import { existsSync as existsSync50, mkdirSync as mkdirSync20, unlinkSync as unlinkSync16, writeFileSync as writeFileSync32 } from "fs";
|
|
17014
17160
|
import { tmpdir as tmpdir7 } from "os";
|
|
17015
17161
|
import { join as join53, resolve as resolve13 } from "path";
|
|
17016
|
-
import
|
|
17162
|
+
import chalk158 from "chalk";
|
|
17017
17163
|
|
|
17018
17164
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
17019
17165
|
var captureWindowPs1 = `
|
|
@@ -17164,13 +17310,13 @@ function screenshot(processName) {
|
|
|
17164
17310
|
const config = loadConfig();
|
|
17165
17311
|
const outputDir = resolve13(config.screenshot.outputDir);
|
|
17166
17312
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
17167
|
-
console.log(
|
|
17313
|
+
console.log(chalk158.gray(`Capturing window for process "${processName}" ...`));
|
|
17168
17314
|
try {
|
|
17169
17315
|
runPowerShellScript(processName, outputPath);
|
|
17170
|
-
console.log(
|
|
17316
|
+
console.log(chalk158.green(`Screenshot saved: ${outputPath}`));
|
|
17171
17317
|
} catch (error) {
|
|
17172
17318
|
const msg = error instanceof Error ? error.message : String(error);
|
|
17173
|
-
console.error(
|
|
17319
|
+
console.error(chalk158.red(`Failed to capture screenshot: ${msg}`));
|
|
17174
17320
|
process.exit(1);
|
|
17175
17321
|
}
|
|
17176
17322
|
}
|
|
@@ -18316,7 +18462,7 @@ function registerDaemon(program2) {
|
|
|
18316
18462
|
|
|
18317
18463
|
// src/commands/sessions/summarise/index.ts
|
|
18318
18464
|
import * as fs30 from "fs";
|
|
18319
|
-
import
|
|
18465
|
+
import chalk159 from "chalk";
|
|
18320
18466
|
|
|
18321
18467
|
// src/commands/sessions/summarise/shared.ts
|
|
18322
18468
|
import * as fs28 from "fs";
|
|
@@ -18443,22 +18589,22 @@ ${firstMessage}`);
|
|
|
18443
18589
|
async function summarise4(options2) {
|
|
18444
18590
|
const files = await discoverSessionJsonlPaths();
|
|
18445
18591
|
if (files.length === 0) {
|
|
18446
|
-
console.log(
|
|
18592
|
+
console.log(chalk159.yellow("No sessions found."));
|
|
18447
18593
|
return;
|
|
18448
18594
|
}
|
|
18449
18595
|
const toProcess = selectCandidates(files, options2);
|
|
18450
18596
|
if (toProcess.length === 0) {
|
|
18451
|
-
console.log(
|
|
18597
|
+
console.log(chalk159.green("All sessions already summarised."));
|
|
18452
18598
|
return;
|
|
18453
18599
|
}
|
|
18454
18600
|
console.log(
|
|
18455
|
-
|
|
18601
|
+
chalk159.cyan(
|
|
18456
18602
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
18457
18603
|
)
|
|
18458
18604
|
);
|
|
18459
18605
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
18460
18606
|
console.log(
|
|
18461
|
-
|
|
18607
|
+
chalk159.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk159.yellow(`, ${failed2} skipped`) : "")
|
|
18462
18608
|
);
|
|
18463
18609
|
}
|
|
18464
18610
|
function selectCandidates(files, options2) {
|
|
@@ -18478,16 +18624,16 @@ function processSessions(files) {
|
|
|
18478
18624
|
let failed2 = 0;
|
|
18479
18625
|
for (let i = 0; i < files.length; i++) {
|
|
18480
18626
|
const file = files[i];
|
|
18481
|
-
process.stdout.write(
|
|
18627
|
+
process.stdout.write(chalk159.dim(` [${i + 1}/${files.length}] `));
|
|
18482
18628
|
const summary = summariseSession(file);
|
|
18483
18629
|
if (summary) {
|
|
18484
18630
|
writeSummary(file, summary);
|
|
18485
18631
|
succeeded++;
|
|
18486
|
-
process.stdout.write(`${
|
|
18632
|
+
process.stdout.write(`${chalk159.green("\u2713")} ${summary}
|
|
18487
18633
|
`);
|
|
18488
18634
|
} else {
|
|
18489
18635
|
failed2++;
|
|
18490
|
-
process.stdout.write(` ${
|
|
18636
|
+
process.stdout.write(` ${chalk159.yellow("skip")}
|
|
18491
18637
|
`);
|
|
18492
18638
|
}
|
|
18493
18639
|
}
|
|
@@ -18502,10 +18648,10 @@ function registerSessions(program2) {
|
|
|
18502
18648
|
}
|
|
18503
18649
|
|
|
18504
18650
|
// src/commands/statusLine.ts
|
|
18505
|
-
import
|
|
18651
|
+
import chalk161 from "chalk";
|
|
18506
18652
|
|
|
18507
18653
|
// src/commands/buildLimitsSegment.ts
|
|
18508
|
-
import
|
|
18654
|
+
import chalk160 from "chalk";
|
|
18509
18655
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
18510
18656
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
18511
18657
|
function formatTimeLeft(resetsAt) {
|
|
@@ -18528,10 +18674,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
18528
18674
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
18529
18675
|
const label2 = `${Math.round(pct)}%`;
|
|
18530
18676
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
18531
|
-
if (projected == null) return
|
|
18532
|
-
if (projected > 100) return
|
|
18533
|
-
if (projected > 75) return
|
|
18534
|
-
return
|
|
18677
|
+
if (projected == null) return chalk160.green(label2);
|
|
18678
|
+
if (projected > 100) return chalk160.red(label2);
|
|
18679
|
+
if (projected > 75) return chalk160.yellow(label2);
|
|
18680
|
+
return chalk160.green(label2);
|
|
18535
18681
|
}
|
|
18536
18682
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
18537
18683
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -18557,14 +18703,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
18557
18703
|
}
|
|
18558
18704
|
|
|
18559
18705
|
// src/commands/statusLine.ts
|
|
18560
|
-
|
|
18706
|
+
chalk161.level = 3;
|
|
18561
18707
|
function formatNumber(num) {
|
|
18562
18708
|
return num.toLocaleString("en-US");
|
|
18563
18709
|
}
|
|
18564
18710
|
function colorizePercent(pct) {
|
|
18565
18711
|
const label2 = `${Math.round(pct)}%`;
|
|
18566
|
-
if (pct > 80) return
|
|
18567
|
-
if (pct > 40) return
|
|
18712
|
+
if (pct > 80) return chalk161.red(label2);
|
|
18713
|
+
if (pct > 40) return chalk161.yellow(label2);
|
|
18568
18714
|
return label2;
|
|
18569
18715
|
}
|
|
18570
18716
|
async function statusLine() {
|
|
@@ -18587,7 +18733,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
18587
18733
|
// src/commands/sync/syncClaudeMd.ts
|
|
18588
18734
|
import * as fs31 from "fs";
|
|
18589
18735
|
import * as path49 from "path";
|
|
18590
|
-
import
|
|
18736
|
+
import chalk162 from "chalk";
|
|
18591
18737
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
18592
18738
|
const source = path49.join(claudeDir, "CLAUDE.md");
|
|
18593
18739
|
const target = path49.join(targetBase, "CLAUDE.md");
|
|
@@ -18596,12 +18742,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
18596
18742
|
const targetContent = fs31.readFileSync(target, "utf-8");
|
|
18597
18743
|
if (sourceContent !== targetContent) {
|
|
18598
18744
|
console.log(
|
|
18599
|
-
|
|
18745
|
+
chalk162.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
18600
18746
|
);
|
|
18601
18747
|
console.log();
|
|
18602
18748
|
printDiff(targetContent, sourceContent);
|
|
18603
18749
|
const confirm = options2?.yes || await promptConfirm(
|
|
18604
|
-
|
|
18750
|
+
chalk162.red("Overwrite existing CLAUDE.md?"),
|
|
18605
18751
|
false
|
|
18606
18752
|
);
|
|
18607
18753
|
if (!confirm) {
|
|
@@ -18617,7 +18763,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
18617
18763
|
// src/commands/sync/syncSettings.ts
|
|
18618
18764
|
import * as fs32 from "fs";
|
|
18619
18765
|
import * as path50 from "path";
|
|
18620
|
-
import
|
|
18766
|
+
import chalk163 from "chalk";
|
|
18621
18767
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
18622
18768
|
const source = path50.join(claudeDir, "settings.json");
|
|
18623
18769
|
const target = path50.join(targetBase, "settings.json");
|
|
@@ -18633,14 +18779,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
18633
18779
|
if (mergedContent !== normalizedTarget) {
|
|
18634
18780
|
if (!options2?.yes) {
|
|
18635
18781
|
console.log(
|
|
18636
|
-
|
|
18782
|
+
chalk163.yellow(
|
|
18637
18783
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
18638
18784
|
)
|
|
18639
18785
|
);
|
|
18640
18786
|
console.log();
|
|
18641
18787
|
printDiff(targetContent, mergedContent);
|
|
18642
18788
|
const confirm = await promptConfirm(
|
|
18643
|
-
|
|
18789
|
+
chalk163.red("Overwrite existing settings.json?"),
|
|
18644
18790
|
false
|
|
18645
18791
|
);
|
|
18646
18792
|
if (!confirm) {
|