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