@staff0rd/assist 0.577.0 → 0.578.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 +1 -1
- package/dist/index.js +806 -670
- 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.578.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -16820,6 +16820,12 @@ function findBuiltinDenyRaw(rawCommand) {
|
|
|
16820
16820
|
// src/shared/isApprovedRead.ts
|
|
16821
16821
|
import { resolve as resolve13, sep } from "path";
|
|
16822
16822
|
|
|
16823
|
+
// src/shared/appliesFixStructure.ts
|
|
16824
|
+
var APPLY_RE = /^assist\s+github\s+issue\s+fix-structure\b.*\s--apply\b/;
|
|
16825
|
+
function appliesFixStructure(command) {
|
|
16826
|
+
return APPLY_RE.test(command);
|
|
16827
|
+
}
|
|
16828
|
+
|
|
16823
16829
|
// src/shared/tokenize.ts
|
|
16824
16830
|
function tokenize(command) {
|
|
16825
16831
|
const tokens = [];
|
|
@@ -17046,6 +17052,7 @@ function isApprovedRead(command, toolName = "Bash") {
|
|
|
17046
17052
|
if (isCdToCwd(command)) return "cd to current directory";
|
|
17047
17053
|
const cdRead = isCdToReadAllowedDir(command);
|
|
17048
17054
|
if (cdRead) return cdRead;
|
|
17055
|
+
if (appliesFixStructure(command)) return void 0;
|
|
17049
17056
|
const matchedRead = findCliRead(command);
|
|
17050
17057
|
if (matchedRead) return `Read-only CLI command: ${matchedRead}`;
|
|
17051
17058
|
const matchedWrite = findCliWrite(command);
|
|
@@ -20695,309 +20702,178 @@ function parseTopCount(value) {
|
|
|
20695
20702
|
return Number.parseInt(value, 10);
|
|
20696
20703
|
}
|
|
20697
20704
|
|
|
20698
|
-
// src/commands/github/issue/
|
|
20699
|
-
import
|
|
20705
|
+
// src/commands/github/issue/fixStructure/applyAndVerifySubtree.ts
|
|
20706
|
+
import chalk163 from "chalk";
|
|
20700
20707
|
|
|
20701
|
-
// src/
|
|
20702
|
-
|
|
20703
|
-
const { subject, context } = labels;
|
|
20704
|
-
if (title.toLowerCase().includes("claude")) {
|
|
20705
|
-
console.error(`Error: ${subject} title must not reference Claude`);
|
|
20706
|
-
process.exit(1);
|
|
20707
|
-
}
|
|
20708
|
-
if (body.toLowerCase().includes("claude")) {
|
|
20709
|
-
console.error(`Error: ${subject} body must not reference Claude`);
|
|
20710
|
-
process.exit(1);
|
|
20711
|
-
}
|
|
20712
|
-
const titleBacklogIds = findBacklogRefs(title);
|
|
20713
|
-
if (titleBacklogIds.length > 0) {
|
|
20714
|
-
console.error(
|
|
20715
|
-
backlogRefError(`${subject} title`, context, titleBacklogIds)
|
|
20716
|
-
);
|
|
20717
|
-
process.exit(1);
|
|
20718
|
-
}
|
|
20719
|
-
const bodyBacklogIds = findBacklogRefs(body);
|
|
20720
|
-
if (bodyBacklogIds.length > 0) {
|
|
20721
|
-
console.error(backlogRefError(`${subject} body`, context, bodyBacklogIds));
|
|
20722
|
-
process.exit(1);
|
|
20723
|
-
}
|
|
20724
|
-
}
|
|
20708
|
+
// src/commands/github/issue/fixStructure/applyFixStructurePlan.ts
|
|
20709
|
+
import chalk162 from "chalk";
|
|
20725
20710
|
|
|
20726
|
-
// src/
|
|
20727
|
-
import {
|
|
20728
|
-
|
|
20729
|
-
const
|
|
20730
|
-
|
|
20731
|
-
|
|
20732
|
-
|
|
20733
|
-
|
|
20734
|
-
title,
|
|
20735
|
-
body,
|
|
20736
|
-
prNumber: null,
|
|
20737
|
-
kind: "github-issue-comment"
|
|
20711
|
+
// src/shared/runGhGraphqlJson.ts
|
|
20712
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
20713
|
+
function runGhGraphqlJson(query, vars = {}) {
|
|
20714
|
+
const result = spawnSync5("gh", ["api", "graphql", "--input", "-"], {
|
|
20715
|
+
encoding: "utf8",
|
|
20716
|
+
windowsHide: true,
|
|
20717
|
+
input: JSON.stringify({ query, variables: vars }),
|
|
20718
|
+
maxBuffer: 64 * 1024 * 1024
|
|
20738
20719
|
});
|
|
20720
|
+
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
20721
|
+
throwOnGraphqlErrors(result.stdout);
|
|
20722
|
+
return result.stdout;
|
|
20739
20723
|
}
|
|
20740
20724
|
|
|
20741
|
-
// src/commands/github/issue/
|
|
20742
|
-
var
|
|
20743
|
-
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
}
|
|
20749
|
-
const { body } = options2;
|
|
20750
|
-
const target = options2.repo ? `${options2.repo}#${number}` : `issue #${number}`;
|
|
20751
|
-
validateProposedContent(
|
|
20752
|
-
{ subject: "Comment", context: "GitHub issues" },
|
|
20753
|
-
"",
|
|
20754
|
-
body
|
|
20755
|
-
);
|
|
20756
|
-
await reviewProposedIssueComment(`Comment on ${target}`, body);
|
|
20757
|
-
const args = ["issue", "comment", String(number), "--body", body];
|
|
20758
|
-
if (options2.repo) args.push("--repo", options2.repo);
|
|
20759
|
-
try {
|
|
20760
|
-
execFileSync6("gh", args, { stdio: "inherit" });
|
|
20761
|
-
} catch {
|
|
20762
|
-
process.exit(1);
|
|
20763
|
-
}
|
|
20764
|
-
console.log(`Comment posted to ${target}`);
|
|
20725
|
+
// src/commands/github/issue/fixStructure/removeIssueLabels.ts
|
|
20726
|
+
var MUTATION = `mutation($labelableId: ID!, $labelIds: [ID!]!) {
|
|
20727
|
+
removeLabelsFromLabelable(input: { labelableId: $labelableId, labelIds: $labelIds }) {
|
|
20728
|
+
labelable { __typename }
|
|
20729
|
+
}
|
|
20730
|
+
}`;
|
|
20731
|
+
function removeIssueLabels(issueId, labelIds) {
|
|
20732
|
+
runGhGraphqlJson(MUTATION, { labelableId: issueId, labelIds });
|
|
20765
20733
|
}
|
|
20766
20734
|
|
|
20767
|
-
// src/commands/github/issue/
|
|
20768
|
-
|
|
20769
|
-
|
|
20770
|
-
|
|
20771
|
-
|
|
20772
|
-
|
|
20773
|
-
|
|
20774
|
-
|
|
20775
|
-
await awaitPreviewApproval("GitHub issue preview", {
|
|
20776
|
-
sessionId,
|
|
20777
|
-
requestId: randomUUID8(),
|
|
20778
|
-
title,
|
|
20779
|
-
body,
|
|
20780
|
-
prNumber: null,
|
|
20781
|
-
kind: "github-issue"
|
|
20782
|
-
});
|
|
20735
|
+
// src/commands/github/issue/fixStructure/updateIssueType.ts
|
|
20736
|
+
var MUTATION2 = `mutation($issueId: ID!, $issueTypeId: ID!) {
|
|
20737
|
+
updateIssueIssueType(input: { issueId: $issueId, issueTypeId: $issueTypeId }) {
|
|
20738
|
+
issue { id }
|
|
20739
|
+
}
|
|
20740
|
+
}`;
|
|
20741
|
+
function updateIssueType(issueId, issueTypeId) {
|
|
20742
|
+
runGhGraphqlJson(MUTATION2, { issueId, issueTypeId });
|
|
20783
20743
|
}
|
|
20784
20744
|
|
|
20785
|
-
// src/commands/github/issue/
|
|
20786
|
-
|
|
20787
|
-
|
|
20788
|
-
|
|
20789
|
-
|
|
20790
|
-
process.exit(1);
|
|
20791
|
-
}
|
|
20792
|
-
const { title, body } = options2;
|
|
20793
|
-
validateProposedContent(
|
|
20794
|
-
{ subject: "Issue", context: "GitHub issues" },
|
|
20795
|
-
title,
|
|
20796
|
-
body
|
|
20797
|
-
);
|
|
20798
|
-
await reviewProposedIssue(title, body);
|
|
20799
|
-
const args = ["issue", "create", "--title", title, "--body", body];
|
|
20800
|
-
if (options2.repo) args.push("--repo", options2.repo);
|
|
20745
|
+
// src/commands/github/issue/fixStructure/writeLineNow.ts
|
|
20746
|
+
import { writeSync as writeSync2 } from "fs";
|
|
20747
|
+
function writeLineNow(line) {
|
|
20748
|
+
const text18 = `${line}
|
|
20749
|
+
`;
|
|
20801
20750
|
try {
|
|
20802
|
-
|
|
20751
|
+
writeSync2(1, text18);
|
|
20803
20752
|
} catch {
|
|
20804
|
-
process.
|
|
20753
|
+
process.stdout.write(text18);
|
|
20805
20754
|
}
|
|
20806
20755
|
}
|
|
20807
20756
|
|
|
20808
|
-
// src/commands/
|
|
20809
|
-
function
|
|
20810
|
-
|
|
20811
|
-
}
|
|
20812
|
-
|
|
20813
|
-
|
|
20814
|
-
|
|
20815
|
-
|
|
20816
|
-
|
|
20817
|
-
|
|
20818
|
-
|
|
20819
|
-
|
|
20820
|
-
|
|
20821
|
-
|
|
20822
|
-
|
|
20823
|
-
|
|
20824
|
-
|
|
20825
|
-
|
|
20826
|
-
|
|
20827
|
-
|
|
20828
|
-
console.error(`Could not fetch issue #${number} with gh issue view`);
|
|
20829
|
-
process.exit(1);
|
|
20830
|
-
}
|
|
20831
|
-
try {
|
|
20832
|
-
return JSON.parse(raw);
|
|
20833
|
-
} catch {
|
|
20834
|
-
console.error(`Could not parse the gh issue view output for #${number}`);
|
|
20835
|
-
process.exit(1);
|
|
20757
|
+
// src/commands/github/issue/fixStructure/applyFixStructurePlan.ts
|
|
20758
|
+
function applyFixStructurePlan(plan2) {
|
|
20759
|
+
for (const entry of plan2.entries) {
|
|
20760
|
+
const where = chalk162.cyan(`${entry.issue.repo}#${entry.issue.number}`);
|
|
20761
|
+
const { typeChange, labelRemovals } = entry;
|
|
20762
|
+
if (typeChange) {
|
|
20763
|
+
writeLineNow(
|
|
20764
|
+
`${where} type ${typeChange.from ?? "no type"} -> ${typeChange.to}`
|
|
20765
|
+
);
|
|
20766
|
+
updateIssueType(entry.issue.id, typeChange.typeId);
|
|
20767
|
+
}
|
|
20768
|
+
if (labelRemovals.length > 0) {
|
|
20769
|
+
writeLineNow(
|
|
20770
|
+
`${where} removing ${labelRemovals.map((label2) => label2.name).join(", ")}`
|
|
20771
|
+
);
|
|
20772
|
+
removeIssueLabels(
|
|
20773
|
+
entry.issue.id,
|
|
20774
|
+
labelRemovals.map((label2) => label2.id)
|
|
20775
|
+
);
|
|
20776
|
+
}
|
|
20836
20777
|
}
|
|
20837
20778
|
}
|
|
20838
20779
|
|
|
20839
|
-
// src/commands/github/issue/
|
|
20840
|
-
|
|
20841
|
-
|
|
20842
|
-
|
|
20843
|
-
|
|
20844
|
-
function issueWorkingFile(slug, number) {
|
|
20845
|
-
const [owner = "unknown", repo = "unknown"] = slug.split("/");
|
|
20846
|
-
const dir = join50(getStoreDir(), "github-issues", owner, repo);
|
|
20847
|
-
return {
|
|
20848
|
-
dir,
|
|
20849
|
-
bodyPath: join50(dir, `${number}.md`),
|
|
20850
|
-
metaPath: join50(dir, `${number}.json`)
|
|
20851
|
-
};
|
|
20852
|
-
}
|
|
20853
|
-
|
|
20854
|
-
// src/commands/github/issue/resumeIssueBody.ts
|
|
20855
|
-
function resumeIssueBody(slug, number, updatedAt) {
|
|
20856
|
-
const { bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
20857
|
-
if (!existsSync48(bodyPath) || !existsSync48(metaPath)) return void 0;
|
|
20858
|
-
try {
|
|
20859
|
-
const meta = JSON.parse(readFileSync37(metaPath, "utf8"));
|
|
20860
|
-
if (meta.updatedAt !== updatedAt) return void 0;
|
|
20861
|
-
return readFileSync37(bodyPath, "utf8");
|
|
20862
|
-
} catch {
|
|
20863
|
-
return void 0;
|
|
20864
|
-
}
|
|
20780
|
+
// src/commands/github/issue/fixStructure/assertNothingTooDeep.ts
|
|
20781
|
+
function describe2(entry, leaf) {
|
|
20782
|
+
const parent = entry.parent;
|
|
20783
|
+
const under = parent ? ` under ${parent.repo}#${parent.number}` : "";
|
|
20784
|
+
return `${entry.issue.repo}#${entry.issue.number}${under} sits below ${leaf}, the leaf level`;
|
|
20865
20785
|
}
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20786
|
+
function assertNothingTooDeep(tooDeep, chain2) {
|
|
20787
|
+
if (tooDeep.length === 0) return;
|
|
20788
|
+
const leaf = chain2[chain2.length - 1] ?? "the leaf";
|
|
20789
|
+
throw new Error(
|
|
20790
|
+
[
|
|
20791
|
+
...tooDeep.map((entry) => describe2(entry, leaf)),
|
|
20792
|
+
"Re-parent those issues or aim the run at a deeper target"
|
|
20793
|
+
].join("\n")
|
|
20873
20794
|
);
|
|
20874
20795
|
}
|
|
20875
20796
|
|
|
20876
|
-
// src/commands/github/issue/
|
|
20877
|
-
|
|
20878
|
-
|
|
20879
|
-
const
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
|
|
20883
|
-
|
|
20884
|
-
|
|
20885
|
-
|
|
20797
|
+
// src/commands/github/issue/fixStructure/assertNoResidualDrift.ts
|
|
20798
|
+
function describe3(entry) {
|
|
20799
|
+
const where = `${entry.issue.repo}#${entry.issue.number}`;
|
|
20800
|
+
const notes = [];
|
|
20801
|
+
if (entry.typeChange) {
|
|
20802
|
+
notes.push(
|
|
20803
|
+
`${where} is still ${entry.typeChange.from ?? "untyped"}, not ${entry.typeChange.to}`
|
|
20804
|
+
);
|
|
20805
|
+
}
|
|
20806
|
+
for (const label2 of entry.labelRemovals) {
|
|
20807
|
+
notes.push(`${where} still carries ${label2.name}`);
|
|
20808
|
+
}
|
|
20809
|
+
return notes;
|
|
20810
|
+
}
|
|
20811
|
+
function assertNoResidualDrift(plan2, chain2) {
|
|
20812
|
+
assertNothingTooDeep(plan2.tooDeep, chain2);
|
|
20813
|
+
const residual = plan2.entries.flatMap(describe3);
|
|
20814
|
+
if (residual.length === 0) return;
|
|
20815
|
+
throw new Error(
|
|
20816
|
+
["The subtree still drifts after applying:", ...residual].join("\n")
|
|
20886
20817
|
);
|
|
20887
|
-
return bodyPath;
|
|
20888
20818
|
}
|
|
20889
20819
|
|
|
20890
|
-
// src/commands/github/issue/
|
|
20891
|
-
|
|
20892
|
-
|
|
20893
|
-
|
|
20894
|
-
|
|
20895
|
-
|
|
20896
|
-
|
|
20897
|
-
|
|
20898
|
-
|
|
20899
|
-
|
|
20900
|
-
const body = resumed ?? issue.body;
|
|
20901
|
-
validateIssueBody(issue.title, body);
|
|
20902
|
-
const save = (markdown) => writeIssueWorkingFile(slug, number, target, issue.updatedAt, markdown);
|
|
20903
|
-
const bodyPath = save(body);
|
|
20904
|
-
if (resumed !== void 0)
|
|
20905
|
-
console.log(`Previewing the in-progress markdown from ${bodyPath}`);
|
|
20906
|
-
return {
|
|
20907
|
-
title: issue.title,
|
|
20908
|
-
target,
|
|
20909
|
-
updatedAt: issue.updatedAt,
|
|
20910
|
-
body,
|
|
20911
|
-
bodyPath,
|
|
20912
|
-
save
|
|
20913
|
-
};
|
|
20914
|
-
}
|
|
20820
|
+
// src/commands/github/issue/fixStructure/issueFieldsFragment.ts
|
|
20821
|
+
var issueFieldsFragment = `fragment issueFields on Issue {
|
|
20822
|
+
id
|
|
20823
|
+
number
|
|
20824
|
+
title
|
|
20825
|
+
issueType { name }
|
|
20826
|
+
repository { nameWithOwner }
|
|
20827
|
+
labels(first: 100) { nodes { id name } pageInfo { hasNextPage } }
|
|
20828
|
+
subIssues(first: 100) { nodes { id } pageInfo { hasNextPage } }
|
|
20829
|
+
}`;
|
|
20915
20830
|
|
|
20916
|
-
// src/commands/github/issue/
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
const
|
|
20920
|
-
|
|
20921
|
-
|
|
20922
|
-
|
|
20923
|
-
|
|
20924
|
-
|
|
20831
|
+
// src/commands/github/issue/fixStructure/parseIssueNode.ts
|
|
20832
|
+
function parseIssueNode(node) {
|
|
20833
|
+
const raw = node;
|
|
20834
|
+
const repo = raw.repository?.nameWithOwner ?? "";
|
|
20835
|
+
const where = `${repo}#${raw.number}`;
|
|
20836
|
+
if (raw.labels?.pageInfo?.hasNextPage) {
|
|
20837
|
+
throw new Error(
|
|
20838
|
+
`${where} carries more than 100 labels, which is not supported`
|
|
20839
|
+
);
|
|
20925
20840
|
}
|
|
20926
|
-
|
|
20927
|
-
|
|
20928
|
-
|
|
20929
|
-
function pushUnchangedIssue(number, repo, target, fetchedAt, bodyPath) {
|
|
20930
|
-
if (fetchIssue2(number, repo).updatedAt !== fetchedAt) {
|
|
20931
|
-
console.error(
|
|
20932
|
-
`${target} was updated on GitHub after it was fetched. Nothing was pushed; the markdown is at ${bodyPath}`
|
|
20841
|
+
if (raw.subIssues?.pageInfo?.hasNextPage) {
|
|
20842
|
+
throw new Error(
|
|
20843
|
+
`${where} has more than 100 sub-issues, which is not supported`
|
|
20933
20844
|
);
|
|
20934
|
-
process.exit(1);
|
|
20935
20845
|
}
|
|
20936
|
-
|
|
20937
|
-
|
|
20938
|
-
|
|
20939
|
-
|
|
20940
|
-
|
|
20941
|
-
|
|
20942
|
-
|
|
20943
|
-
|
|
20944
|
-
|
|
20945
|
-
const decision = await awaitPreviewApproval(
|
|
20946
|
-
"GitHub issue edit preview",
|
|
20947
|
-
{
|
|
20948
|
-
sessionId,
|
|
20949
|
-
requestId: randomUUID9(),
|
|
20950
|
-
title,
|
|
20951
|
-
body,
|
|
20952
|
-
prNumber: null,
|
|
20953
|
-
kind: "github-issue-edit"
|
|
20954
|
-
},
|
|
20955
|
-
{
|
|
20956
|
-
saveEditedBody: working.save,
|
|
20957
|
-
rejectionAdvice: `Nothing was pushed. The pane's markdown, including any collapses already applied, is at ${working.path}. Revise that file in place \u2014 do not recompose the body from scratch \u2014 then re-run this command to preview the revision.`
|
|
20958
|
-
}
|
|
20959
|
-
);
|
|
20960
|
-
return decision.body ?? body;
|
|
20846
|
+
return {
|
|
20847
|
+
id: raw.id,
|
|
20848
|
+
number: raw.number,
|
|
20849
|
+
title: raw.title,
|
|
20850
|
+
repo,
|
|
20851
|
+
typeName: raw.issueType?.name ?? null,
|
|
20852
|
+
labels: (raw.labels?.nodes ?? []).filter((label2) => label2 !== null),
|
|
20853
|
+
childIds: (raw.subIssues?.nodes ?? []).filter((child) => child !== null).map((child) => child.id)
|
|
20854
|
+
};
|
|
20961
20855
|
}
|
|
20962
20856
|
|
|
20963
|
-
// src/commands/github/issue/
|
|
20964
|
-
|
|
20965
|
-
|
|
20966
|
-
|
|
20967
|
-
|
|
20968
|
-
try {
|
|
20969
|
-
execFileSync10("gh", args, { stdio: "inherit" });
|
|
20970
|
-
} catch {
|
|
20971
|
-
process.exit(1);
|
|
20972
|
-
}
|
|
20857
|
+
// src/commands/github/issue/fixStructure/fetchRootIssue.ts
|
|
20858
|
+
var QUERY = `query($owner: String!, $repo: String!, $number: Int!) {
|
|
20859
|
+
repository(owner: $owner, name: $repo) {
|
|
20860
|
+
issue(number: $number) { ...issueFields }
|
|
20861
|
+
}
|
|
20973
20862
|
}
|
|
20974
|
-
|
|
20975
|
-
|
|
20976
|
-
|
|
20977
|
-
|
|
20978
|
-
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
|
|
20985
|
-
|
|
20863
|
+
${issueFieldsFragment}`;
|
|
20864
|
+
function fetchRootIssue(target) {
|
|
20865
|
+
const raw = runGhGraphqlJson(QUERY, {
|
|
20866
|
+
owner: target.owner,
|
|
20867
|
+
repo: target.repo,
|
|
20868
|
+
number: target.number
|
|
20869
|
+
});
|
|
20870
|
+
const issue = JSON.parse(raw).data?.repository?.issue;
|
|
20871
|
+
if (!issue) {
|
|
20872
|
+
throw new Error(
|
|
20873
|
+
`No issue ${target.owner}/${target.repo}#${target.number} could be read`
|
|
20874
|
+
);
|
|
20986
20875
|
}
|
|
20987
|
-
|
|
20988
|
-
const edited = await reviewProposedIssueEdit(
|
|
20989
|
-
`Edit ${issue.target}: ${issue.title}`,
|
|
20990
|
-
issue.body,
|
|
20991
|
-
{ path: issue.bodyPath, save: issue.save }
|
|
20992
|
-
);
|
|
20993
|
-
validateIssueBody(issue.title, edited);
|
|
20994
|
-
pushUnchangedIssue(
|
|
20995
|
-
number,
|
|
20996
|
-
options2.repo,
|
|
20997
|
-
issue.target,
|
|
20998
|
-
issue.updatedAt,
|
|
20999
|
-
issue.bodyPath
|
|
21000
|
-
);
|
|
20876
|
+
return parseIssueNode(issue);
|
|
21001
20877
|
}
|
|
21002
20878
|
|
|
21003
20879
|
// src/commands/github/issue/fixStructure/matchedLabels.ts
|
|
@@ -21095,127 +20971,110 @@ function buildFixStructurePlan(issues, options2) {
|
|
|
21095
20971
|
};
|
|
21096
20972
|
}
|
|
21097
20973
|
|
|
21098
|
-
// src/
|
|
21099
|
-
|
|
21100
|
-
|
|
21101
|
-
const result = spawnSync5("gh", ["api", "graphql", "--input", "-"], {
|
|
21102
|
-
encoding: "utf8",
|
|
21103
|
-
windowsHide: true,
|
|
21104
|
-
input: JSON.stringify({ query, variables: vars }),
|
|
21105
|
-
maxBuffer: 64 * 1024 * 1024
|
|
21106
|
-
});
|
|
21107
|
-
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
21108
|
-
throwOnGraphqlErrors(result.stdout);
|
|
21109
|
-
return result.stdout;
|
|
20974
|
+
// src/commands/github/issue/fixStructure/fetchSubtreeIssues.ts
|
|
20975
|
+
var QUERY2 = `query($ids: [ID!]!) {
|
|
20976
|
+
nodes(ids: $ids) { ... on Issue { ...issueFields } }
|
|
21110
20977
|
}
|
|
21111
|
-
|
|
21112
|
-
|
|
21113
|
-
|
|
21114
|
-
|
|
21115
|
-
|
|
21116
|
-
|
|
21117
|
-
|
|
21118
|
-
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
|
|
21122
|
-
|
|
21123
|
-
// src/commands/github/issue/fixStructure/parseIssueNode.ts
|
|
21124
|
-
function parseIssueNode(node) {
|
|
21125
|
-
const raw = node;
|
|
21126
|
-
const repo = raw.repository?.nameWithOwner ?? "";
|
|
21127
|
-
const where = `${repo}#${raw.number}`;
|
|
21128
|
-
if (raw.labels?.pageInfo?.hasNextPage) {
|
|
21129
|
-
throw new Error(
|
|
21130
|
-
`${where} carries more than 100 labels, which is not supported`
|
|
21131
|
-
);
|
|
20978
|
+
${issueFieldsFragment}`;
|
|
20979
|
+
var BATCH = 50;
|
|
20980
|
+
function fetchSubtreeIssues(ids) {
|
|
20981
|
+
const issues = [];
|
|
20982
|
+
for (let start3 = 0; start3 < ids.length; start3 += BATCH) {
|
|
20983
|
+
const raw = runGhGraphqlJson(QUERY2, {
|
|
20984
|
+
ids: ids.slice(start3, start3 + BATCH)
|
|
20985
|
+
});
|
|
20986
|
+
const nodes = JSON.parse(raw).data?.nodes ?? [];
|
|
20987
|
+
for (const node of nodes) {
|
|
20988
|
+
if (node) issues.push(parseIssueNode(node));
|
|
20989
|
+
}
|
|
21132
20990
|
}
|
|
21133
|
-
|
|
21134
|
-
|
|
21135
|
-
|
|
21136
|
-
|
|
20991
|
+
return issues;
|
|
20992
|
+
}
|
|
20993
|
+
|
|
20994
|
+
// src/commands/github/issue/fixStructure/walkSubtree.ts
|
|
20995
|
+
function walkSubtree(root, maxDepth, fetchIssues = fetchSubtreeIssues) {
|
|
20996
|
+
const placed = [{ ...root, depth: 0, parentId: null }];
|
|
20997
|
+
const seen = /* @__PURE__ */ new Set([root.id]);
|
|
20998
|
+
let frontier = placed;
|
|
20999
|
+
for (let depth = 1; depth <= maxDepth && frontier.length > 0; depth += 1) {
|
|
21000
|
+
const parentOf2 = /* @__PURE__ */ new Map();
|
|
21001
|
+
for (const parent of frontier) {
|
|
21002
|
+
for (const childId of parent.childIds) {
|
|
21003
|
+
if (seen.has(childId)) continue;
|
|
21004
|
+
seen.add(childId);
|
|
21005
|
+
parentOf2.set(childId, parent.id);
|
|
21006
|
+
}
|
|
21007
|
+
}
|
|
21008
|
+
if (parentOf2.size === 0) break;
|
|
21009
|
+
const children = fetchIssues([...parentOf2.keys()]).map((issue) => ({
|
|
21010
|
+
...issue,
|
|
21011
|
+
depth,
|
|
21012
|
+
parentId: parentOf2.get(issue.id) ?? null
|
|
21013
|
+
}));
|
|
21014
|
+
placed.push(...children);
|
|
21015
|
+
frontier = children;
|
|
21137
21016
|
}
|
|
21138
|
-
return
|
|
21139
|
-
id: raw.id,
|
|
21140
|
-
number: raw.number,
|
|
21141
|
-
title: raw.title,
|
|
21142
|
-
repo,
|
|
21143
|
-
typeName: raw.issueType?.name ?? null,
|
|
21144
|
-
labels: (raw.labels?.nodes ?? []).filter((label2) => label2 !== null),
|
|
21145
|
-
childIds: (raw.subIssues?.nodes ?? []).filter((child) => child !== null).map((child) => child.id)
|
|
21146
|
-
};
|
|
21017
|
+
return placed;
|
|
21147
21018
|
}
|
|
21148
21019
|
|
|
21149
|
-
// src/commands/github/issue/fixStructure/
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
}
|
|
21020
|
+
// src/commands/github/issue/fixStructure/planSubtree.ts
|
|
21021
|
+
function planSubtree(root, context) {
|
|
21022
|
+
const depth = context.chain.length - context.rootLevelIndex;
|
|
21023
|
+
return buildFixStructurePlan(walkSubtree(root, depth), context);
|
|
21154
21024
|
}
|
|
21155
|
-
|
|
21156
|
-
|
|
21157
|
-
|
|
21158
|
-
|
|
21159
|
-
|
|
21160
|
-
|
|
21161
|
-
|
|
21162
|
-
|
|
21163
|
-
|
|
21164
|
-
|
|
21165
|
-
|
|
21166
|
-
);
|
|
21167
|
-
}
|
|
21168
|
-
return parseIssueNode(issue);
|
|
21025
|
+
|
|
21026
|
+
// src/commands/github/issue/fixStructure/applyAndVerifySubtree.ts
|
|
21027
|
+
function applyAndVerifySubtree(target, plan2, context) {
|
|
21028
|
+
if (plan2.typeChangeCount === 0 && plan2.labelRemovalCount === 0) return;
|
|
21029
|
+
applyFixStructurePlan(plan2);
|
|
21030
|
+
writeLineNow(chalk163.dim("Re-walking the subtree to confirm"));
|
|
21031
|
+
assertNoResidualDrift(
|
|
21032
|
+
planSubtree(fetchRootIssue(target), context),
|
|
21033
|
+
context.chain
|
|
21034
|
+
);
|
|
21035
|
+
writeLineNow(chalk163.green("Subtree normalised"));
|
|
21169
21036
|
}
|
|
21170
21037
|
|
|
21171
21038
|
// src/commands/github/issue/fixStructure/printFixStructurePlan.ts
|
|
21172
|
-
import
|
|
21039
|
+
import chalk164 from "chalk";
|
|
21173
21040
|
function annotate(entry) {
|
|
21174
21041
|
const notes = [];
|
|
21175
21042
|
if (entry.level === null) {
|
|
21176
|
-
notes.push(
|
|
21043
|
+
notes.push(chalk164.red("deeper than the leaf level"));
|
|
21177
21044
|
} else if (entry.typeChange) {
|
|
21178
21045
|
notes.push(
|
|
21179
|
-
|
|
21046
|
+
chalk164.yellow(
|
|
21180
21047
|
`${entry.typeChange.from ?? "no type"} -> ${entry.typeChange.to}`
|
|
21181
21048
|
)
|
|
21182
21049
|
);
|
|
21183
21050
|
} else {
|
|
21184
|
-
notes.push(
|
|
21051
|
+
notes.push(chalk164.dim(entry.issue.typeName ?? "no type"));
|
|
21185
21052
|
}
|
|
21186
21053
|
for (const label2 of entry.labelRemovals) {
|
|
21187
|
-
notes.push(
|
|
21054
|
+
notes.push(chalk164.yellow(`-${label2.name}`));
|
|
21188
21055
|
}
|
|
21189
21056
|
return notes;
|
|
21190
21057
|
}
|
|
21191
21058
|
function formatCount(count8, noun) {
|
|
21192
21059
|
return `${count8} ${noun}${count8 === 1 ? "" : "s"}`;
|
|
21193
21060
|
}
|
|
21194
|
-
function printFixStructurePlan(plan2, chain2) {
|
|
21195
|
-
|
|
21061
|
+
function printFixStructurePlan(plan2, chain2, apply) {
|
|
21062
|
+
writeLineNow(chalk164.dim(`chain: ${chain2.join(" > ")}`));
|
|
21196
21063
|
for (const entry of plan2.entries) {
|
|
21197
21064
|
const indent3 = " ".repeat(entry.issue.depth);
|
|
21198
|
-
const name =
|
|
21199
|
-
|
|
21065
|
+
const name = chalk164.cyan(`${entry.issue.repo}#${entry.issue.number}`);
|
|
21066
|
+
writeLineNow(
|
|
21200
21067
|
`${indent3}${name} ${entry.issue.title} [${annotate(entry).join(", ")}]`
|
|
21201
21068
|
);
|
|
21202
21069
|
}
|
|
21203
|
-
for (const { issue, parent } of plan2.tooDeep) {
|
|
21204
|
-
const where = parent ? ` under ${parent.repo}#${parent.number}` : "";
|
|
21205
|
-
console.error(
|
|
21206
|
-
chalk162.red(
|
|
21207
|
-
`${issue.repo}#${issue.number}${where} sits below ${chain2[chain2.length - 1]}, the leaf level`
|
|
21208
|
-
)
|
|
21209
|
-
);
|
|
21210
|
-
}
|
|
21211
21070
|
if (plan2.typeChangeCount === 0 && plan2.labelRemovalCount === 0) {
|
|
21212
|
-
|
|
21071
|
+
writeLineNow(chalk164.green("Nothing to change"));
|
|
21213
21072
|
return;
|
|
21214
21073
|
}
|
|
21215
|
-
|
|
21074
|
+
writeLineNow(
|
|
21216
21075
|
`${formatCount(plan2.typeChangeCount, "type change")}, ${formatCount(plan2.labelRemovalCount, "label removal")} planned`
|
|
21217
21076
|
);
|
|
21218
|
-
|
|
21077
|
+
if (!apply) writeLineNow(chalk164.dim("Dry run \u2014 nothing written"));
|
|
21219
21078
|
}
|
|
21220
21079
|
|
|
21221
21080
|
// src/commands/github/issue/fixStructure/resolveFixStructureTarget.ts
|
|
@@ -21251,7 +21110,7 @@ function resolveFixStructureTarget(target, repo) {
|
|
|
21251
21110
|
}
|
|
21252
21111
|
|
|
21253
21112
|
// src/commands/github/issue/fixStructure/resolveOrgIssueTypes.ts
|
|
21254
|
-
var
|
|
21113
|
+
var QUERY3 = `query($owner: String!) {
|
|
21255
21114
|
organization(login: $owner) {
|
|
21256
21115
|
issueTypes(first: 50) { nodes { id name } }
|
|
21257
21116
|
}
|
|
@@ -21264,7 +21123,7 @@ function missingOrg(owner) {
|
|
|
21264
21123
|
function resolveOrgIssueTypes(owner) {
|
|
21265
21124
|
let raw;
|
|
21266
21125
|
try {
|
|
21267
|
-
raw = runGhGraphqlJson(
|
|
21126
|
+
raw = runGhGraphqlJson(QUERY3, { owner });
|
|
21268
21127
|
} catch (error) {
|
|
21269
21128
|
const message3 = error instanceof Error ? error.message : String(error);
|
|
21270
21129
|
if (message3.includes("Could not resolve to an Organization")) {
|
|
@@ -21307,52 +21166,6 @@ function resolveRootLevelIndex(chain2, targetTypeName, level) {
|
|
|
21307
21166
|
// src/commands/github/issue/fixStructure/types.ts
|
|
21308
21167
|
var defaultTypeChain = ["Epic", "Story", "Subtask"];
|
|
21309
21168
|
|
|
21310
|
-
// src/commands/github/issue/fixStructure/fetchSubtreeIssues.ts
|
|
21311
|
-
var QUERY3 = `query($ids: [ID!]!) {
|
|
21312
|
-
nodes(ids: $ids) { ... on Issue { ...issueFields } }
|
|
21313
|
-
}
|
|
21314
|
-
${issueFieldsFragment}`;
|
|
21315
|
-
var BATCH = 50;
|
|
21316
|
-
function fetchSubtreeIssues(ids) {
|
|
21317
|
-
const issues = [];
|
|
21318
|
-
for (let start3 = 0; start3 < ids.length; start3 += BATCH) {
|
|
21319
|
-
const raw = runGhGraphqlJson(QUERY3, {
|
|
21320
|
-
ids: ids.slice(start3, start3 + BATCH)
|
|
21321
|
-
});
|
|
21322
|
-
const nodes = JSON.parse(raw).data?.nodes ?? [];
|
|
21323
|
-
for (const node of nodes) {
|
|
21324
|
-
if (node) issues.push(parseIssueNode(node));
|
|
21325
|
-
}
|
|
21326
|
-
}
|
|
21327
|
-
return issues;
|
|
21328
|
-
}
|
|
21329
|
-
|
|
21330
|
-
// src/commands/github/issue/fixStructure/walkSubtree.ts
|
|
21331
|
-
function walkSubtree(root, maxDepth, fetchIssues = fetchSubtreeIssues) {
|
|
21332
|
-
const placed = [{ ...root, depth: 0, parentId: null }];
|
|
21333
|
-
const seen = /* @__PURE__ */ new Set([root.id]);
|
|
21334
|
-
let frontier = placed;
|
|
21335
|
-
for (let depth = 1; depth <= maxDepth && frontier.length > 0; depth += 1) {
|
|
21336
|
-
const parentOf2 = /* @__PURE__ */ new Map();
|
|
21337
|
-
for (const parent of frontier) {
|
|
21338
|
-
for (const childId of parent.childIds) {
|
|
21339
|
-
if (seen.has(childId)) continue;
|
|
21340
|
-
seen.add(childId);
|
|
21341
|
-
parentOf2.set(childId, parent.id);
|
|
21342
|
-
}
|
|
21343
|
-
}
|
|
21344
|
-
if (parentOf2.size === 0) break;
|
|
21345
|
-
const children = fetchIssues([...parentOf2.keys()]).map((issue) => ({
|
|
21346
|
-
...issue,
|
|
21347
|
-
depth,
|
|
21348
|
-
parentId: parentOf2.get(issue.id) ?? null
|
|
21349
|
-
}));
|
|
21350
|
-
placed.push(...children);
|
|
21351
|
-
frontier = children;
|
|
21352
|
-
}
|
|
21353
|
-
return placed;
|
|
21354
|
-
}
|
|
21355
|
-
|
|
21356
21169
|
// src/commands/github/issue/fixStructure/fixStructure.ts
|
|
21357
21170
|
function fixStructure(target, options2) {
|
|
21358
21171
|
const chain2 = defaultTypeChain;
|
|
@@ -21364,15 +21177,17 @@ function fixStructure(target, options2) {
|
|
|
21364
21177
|
root.typeName,
|
|
21365
21178
|
options2.level
|
|
21366
21179
|
);
|
|
21367
|
-
const
|
|
21368
|
-
const issues = walkSubtree(root, chain2.length - index3);
|
|
21369
|
-
const plan2 = buildFixStructurePlan(issues, {
|
|
21180
|
+
const context = {
|
|
21370
21181
|
chain: chain2,
|
|
21371
21182
|
rootLevelIndex: index3,
|
|
21372
21183
|
rootAsserted: asserted,
|
|
21373
|
-
issueTypes
|
|
21374
|
-
|
|
21375
|
-
|
|
21184
|
+
issueTypes: resolveOrgIssueTypes(resolved.owner),
|
|
21185
|
+
stripLabels: []
|
|
21186
|
+
};
|
|
21187
|
+
const plan2 = planSubtree(root, context);
|
|
21188
|
+
printFixStructurePlan(plan2, chain2, options2.apply === true);
|
|
21189
|
+
assertNothingTooDeep(plan2.tooDeep, chain2);
|
|
21190
|
+
if (options2.apply) applyAndVerifySubtree(resolved, plan2, context);
|
|
21376
21191
|
} catch (error) {
|
|
21377
21192
|
console.error(error instanceof Error ? error.message : String(error));
|
|
21378
21193
|
process.exit(1);
|
|
@@ -21383,19 +21198,20 @@ function fixStructure(target, options2) {
|
|
|
21383
21198
|
var chain = defaultTypeChain.join(" > ");
|
|
21384
21199
|
var levels = defaultTypeChain.map((name) => name.toLowerCase()).join("|");
|
|
21385
21200
|
function registerFixStructure(issueCommand) {
|
|
21386
|
-
issueCommand.command("fix-structure <target>").description("
|
|
21201
|
+
issueCommand.command("fix-structure <target>").description("Normalise the issue types across one issue subtree").option(
|
|
21387
21202
|
"-R, --repo <owner/repo>",
|
|
21388
21203
|
"Repository a bare issue number belongs to"
|
|
21389
21204
|
).option(
|
|
21390
21205
|
"--level <level>",
|
|
21391
21206
|
`The target's own position in the ${chain} chain, when it cannot be inferred from its type`
|
|
21392
|
-
).addHelpText(
|
|
21207
|
+
).option("--apply", "Write the planned changes instead of reporting them").addHelpText(
|
|
21393
21208
|
"after",
|
|
21394
21209
|
`
|
|
21395
21210
|
Walks the subtree reachable from <target> via sub-issues and reports the type each issue should carry: every level below the target is typed to the next level down the ${chain} chain. Nothing outside the subtree is ever read or written.
|
|
21396
21211
|
The target's own level is inferred from its issue type, so aiming at a story types its children as subtasks. When the target's type is not in the chain the level cannot be inferred, and --level ${levels} asserts it instead \u2014 which also plans the target's own type.
|
|
21397
21212
|
The target is owner/repo#number, a github.com issue URL, or a bare number with --repo.
|
|
21398
|
-
|
|
21213
|
+
Without --apply nothing is written. With --apply each write is announced before it is issued, and the subtree is re-walked afterwards so any residual drift fails the run.
|
|
21214
|
+
Anything nested below the leaf level fails the run before a single write, naming the offender and its parent.`
|
|
21399
21215
|
).action(fixStructure);
|
|
21400
21216
|
}
|
|
21401
21217
|
|
|
@@ -21410,9 +21226,136 @@ async function readBodyArgument(value) {
|
|
|
21410
21226
|
return body;
|
|
21411
21227
|
}
|
|
21412
21228
|
|
|
21413
|
-
// src/commands/
|
|
21414
|
-
|
|
21415
|
-
|
|
21229
|
+
// src/commands/github/issue/commentIssue.ts
|
|
21230
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
21231
|
+
|
|
21232
|
+
// src/shared/validateProposedContent.ts
|
|
21233
|
+
function validateProposedContent(labels, title, body) {
|
|
21234
|
+
const { subject, context } = labels;
|
|
21235
|
+
if (title.toLowerCase().includes("claude")) {
|
|
21236
|
+
console.error(`Error: ${subject} title must not reference Claude`);
|
|
21237
|
+
process.exit(1);
|
|
21238
|
+
}
|
|
21239
|
+
if (body.toLowerCase().includes("claude")) {
|
|
21240
|
+
console.error(`Error: ${subject} body must not reference Claude`);
|
|
21241
|
+
process.exit(1);
|
|
21242
|
+
}
|
|
21243
|
+
const titleBacklogIds = findBacklogRefs(title);
|
|
21244
|
+
if (titleBacklogIds.length > 0) {
|
|
21245
|
+
console.error(
|
|
21246
|
+
backlogRefError(`${subject} title`, context, titleBacklogIds)
|
|
21247
|
+
);
|
|
21248
|
+
process.exit(1);
|
|
21249
|
+
}
|
|
21250
|
+
const bodyBacklogIds = findBacklogRefs(body);
|
|
21251
|
+
if (bodyBacklogIds.length > 0) {
|
|
21252
|
+
console.error(backlogRefError(`${subject} body`, context, bodyBacklogIds));
|
|
21253
|
+
process.exit(1);
|
|
21254
|
+
}
|
|
21255
|
+
}
|
|
21256
|
+
|
|
21257
|
+
// src/commands/github/issue/reviewProposedIssueComment.ts
|
|
21258
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
21259
|
+
async function reviewProposedIssueComment(title, body) {
|
|
21260
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
21261
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
|
|
21262
|
+
await awaitPreviewApproval("GitHub issue comment preview", {
|
|
21263
|
+
sessionId,
|
|
21264
|
+
requestId: randomUUID7(),
|
|
21265
|
+
title,
|
|
21266
|
+
body,
|
|
21267
|
+
prNumber: null,
|
|
21268
|
+
kind: "github-issue-comment"
|
|
21269
|
+
});
|
|
21270
|
+
}
|
|
21271
|
+
|
|
21272
|
+
// src/commands/github/issue/commentIssue.ts
|
|
21273
|
+
var USAGE = "Usage: assist github issue comment <number> --body <body> [-R <owner>/<repo>]";
|
|
21274
|
+
async function commentIssue(numberArg, options2) {
|
|
21275
|
+
const number = Number.parseInt(numberArg, 10);
|
|
21276
|
+
if (!Number.isInteger(number) || number <= 0 || !options2.body) {
|
|
21277
|
+
console.error(USAGE);
|
|
21278
|
+
process.exit(1);
|
|
21279
|
+
}
|
|
21280
|
+
const { body } = options2;
|
|
21281
|
+
const target = options2.repo ? `${options2.repo}#${number}` : `issue #${number}`;
|
|
21282
|
+
validateProposedContent(
|
|
21283
|
+
{ subject: "Comment", context: "GitHub issues" },
|
|
21284
|
+
"",
|
|
21285
|
+
body
|
|
21286
|
+
);
|
|
21287
|
+
await reviewProposedIssueComment(`Comment on ${target}`, body);
|
|
21288
|
+
const args = ["issue", "comment", String(number), "--body", body];
|
|
21289
|
+
if (options2.repo) args.push("--repo", options2.repo);
|
|
21290
|
+
try {
|
|
21291
|
+
execFileSync6("gh", args, { stdio: "inherit" });
|
|
21292
|
+
} catch {
|
|
21293
|
+
process.exit(1);
|
|
21294
|
+
}
|
|
21295
|
+
console.log(`Comment posted to ${target}`);
|
|
21296
|
+
}
|
|
21297
|
+
|
|
21298
|
+
// src/commands/github/issue/registerCommentIssue.ts
|
|
21299
|
+
function registerCommentIssue(issueCommand) {
|
|
21300
|
+
issueCommand.command("comment <number>").description("Comment on a GitHub issue (body of - reads it from stdin)").option("--body <body>", "Comment body (- reads it from stdin)").option(
|
|
21301
|
+
"-R, --repo <owner/repo>",
|
|
21302
|
+
"Target repository (defaults to the current repo)"
|
|
21303
|
+
).addHelpText(
|
|
21304
|
+
"after",
|
|
21305
|
+
"\nThe comment is outward-facing: write it for the repo's readers, not the team. It is rejected if it references Claude or an assist backlog item.\nIn an assist web session the body is previewed for approve/reject first (with inline comments); nothing is posted until it is approved."
|
|
21306
|
+
).action(
|
|
21307
|
+
async (number, options2) => {
|
|
21308
|
+
await commentIssue(number, {
|
|
21309
|
+
...options2,
|
|
21310
|
+
body: options2.body ? await readBodyArgument(options2.body) : void 0
|
|
21311
|
+
});
|
|
21312
|
+
}
|
|
21313
|
+
);
|
|
21314
|
+
}
|
|
21315
|
+
|
|
21316
|
+
// src/commands/github/issue/createIssue.ts
|
|
21317
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
21318
|
+
|
|
21319
|
+
// src/commands/github/issue/reviewProposedIssue.ts
|
|
21320
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
21321
|
+
async function reviewProposedIssue(title, body) {
|
|
21322
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
21323
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
|
|
21324
|
+
await awaitPreviewApproval("GitHub issue preview", {
|
|
21325
|
+
sessionId,
|
|
21326
|
+
requestId: randomUUID8(),
|
|
21327
|
+
title,
|
|
21328
|
+
body,
|
|
21329
|
+
prNumber: null,
|
|
21330
|
+
kind: "github-issue"
|
|
21331
|
+
});
|
|
21332
|
+
}
|
|
21333
|
+
|
|
21334
|
+
// src/commands/github/issue/createIssue.ts
|
|
21335
|
+
var USAGE2 = "Usage: assist github issue create --title <title> --body <body> [-R <owner>/<repo>]";
|
|
21336
|
+
async function createIssue(options2) {
|
|
21337
|
+
if (!options2.title || !options2.body) {
|
|
21338
|
+
console.error(USAGE2);
|
|
21339
|
+
process.exit(1);
|
|
21340
|
+
}
|
|
21341
|
+
const { title, body } = options2;
|
|
21342
|
+
validateProposedContent(
|
|
21343
|
+
{ subject: "Issue", context: "GitHub issues" },
|
|
21344
|
+
title,
|
|
21345
|
+
body
|
|
21346
|
+
);
|
|
21347
|
+
await reviewProposedIssue(title, body);
|
|
21348
|
+
const args = ["issue", "create", "--title", title, "--body", body];
|
|
21349
|
+
if (options2.repo) args.push("--repo", options2.repo);
|
|
21350
|
+
try {
|
|
21351
|
+
execFileSync7("gh", args, { stdio: "inherit" });
|
|
21352
|
+
} catch {
|
|
21353
|
+
process.exit(1);
|
|
21354
|
+
}
|
|
21355
|
+
}
|
|
21356
|
+
|
|
21357
|
+
// src/commands/github/issue/registerCreateIssue.ts
|
|
21358
|
+
function registerCreateIssue(issueCommand) {
|
|
21416
21359
|
issueCommand.command("create").description("Create a GitHub issue").option("--title <title>", "Issue title").option("--body <body>", "Issue body").option(
|
|
21417
21360
|
"-R, --repo <owner/repo>",
|
|
21418
21361
|
"Target repository (defaults to the current repo)"
|
|
@@ -21420,6 +21363,205 @@ function registerGithubIssue(githubCommand) {
|
|
|
21420
21363
|
"after",
|
|
21421
21364
|
"\nThere is no What/Why/How template: an issue reports a problem, and the target repo's own issue template is unknowable from here. Write the body as the repo's maintainers would expect.\nIn an assist web session the title and body are previewed for approve/reject first (with inline comments); nothing is created until it is approved."
|
|
21422
21365
|
).action(createIssue);
|
|
21366
|
+
}
|
|
21367
|
+
|
|
21368
|
+
// src/commands/sessions/shared/inWebSession.ts
|
|
21369
|
+
function inWebSession() {
|
|
21370
|
+
return process.env.ASSIST_SESSION === "1" && !!process.env.ASSIST_SESSION_ID;
|
|
21371
|
+
}
|
|
21372
|
+
|
|
21373
|
+
// src/commands/github/issue/fetchIssue.ts
|
|
21374
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
21375
|
+
function fetchIssue2(number, repo) {
|
|
21376
|
+
const args = [
|
|
21377
|
+
"issue",
|
|
21378
|
+
"view",
|
|
21379
|
+
String(number),
|
|
21380
|
+
"--json",
|
|
21381
|
+
"title,body,updatedAt,url"
|
|
21382
|
+
];
|
|
21383
|
+
if (repo) args.push("--repo", repo);
|
|
21384
|
+
let raw;
|
|
21385
|
+
try {
|
|
21386
|
+
raw = execFileSync8("gh", args, { encoding: "utf8" });
|
|
21387
|
+
} catch {
|
|
21388
|
+
console.error(`Could not fetch issue #${number} with gh issue view`);
|
|
21389
|
+
process.exit(1);
|
|
21390
|
+
}
|
|
21391
|
+
try {
|
|
21392
|
+
return JSON.parse(raw);
|
|
21393
|
+
} catch {
|
|
21394
|
+
console.error(`Could not parse the gh issue view output for #${number}`);
|
|
21395
|
+
process.exit(1);
|
|
21396
|
+
}
|
|
21397
|
+
}
|
|
21398
|
+
|
|
21399
|
+
// src/commands/github/issue/resumeIssueBody.ts
|
|
21400
|
+
import { existsSync as existsSync48, readFileSync as readFileSync37 } from "fs";
|
|
21401
|
+
|
|
21402
|
+
// src/commands/github/issue/issueWorkingFile.ts
|
|
21403
|
+
import { join as join50 } from "path";
|
|
21404
|
+
function issueWorkingFile(slug, number) {
|
|
21405
|
+
const [owner = "unknown", repo = "unknown"] = slug.split("/");
|
|
21406
|
+
const dir = join50(getStoreDir(), "github-issues", owner, repo);
|
|
21407
|
+
return {
|
|
21408
|
+
dir,
|
|
21409
|
+
bodyPath: join50(dir, `${number}.md`),
|
|
21410
|
+
metaPath: join50(dir, `${number}.json`)
|
|
21411
|
+
};
|
|
21412
|
+
}
|
|
21413
|
+
|
|
21414
|
+
// src/commands/github/issue/resumeIssueBody.ts
|
|
21415
|
+
function resumeIssueBody(slug, number, updatedAt) {
|
|
21416
|
+
const { bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
21417
|
+
if (!existsSync48(bodyPath) || !existsSync48(metaPath)) return void 0;
|
|
21418
|
+
try {
|
|
21419
|
+
const meta = JSON.parse(readFileSync37(metaPath, "utf8"));
|
|
21420
|
+
if (meta.updatedAt !== updatedAt) return void 0;
|
|
21421
|
+
return readFileSync37(bodyPath, "utf8");
|
|
21422
|
+
} catch {
|
|
21423
|
+
return void 0;
|
|
21424
|
+
}
|
|
21425
|
+
}
|
|
21426
|
+
|
|
21427
|
+
// src/commands/github/issue/validateIssueBody.ts
|
|
21428
|
+
function validateIssueBody(title, body) {
|
|
21429
|
+
validateProposedContent(
|
|
21430
|
+
{ subject: "Issue", context: "GitHub issues" },
|
|
21431
|
+
title,
|
|
21432
|
+
body
|
|
21433
|
+
);
|
|
21434
|
+
}
|
|
21435
|
+
|
|
21436
|
+
// src/commands/github/issue/writeIssueWorkingFile.ts
|
|
21437
|
+
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync31 } from "fs";
|
|
21438
|
+
function writeIssueWorkingFile(slug, number, target, updatedAt, body) {
|
|
21439
|
+
const { dir, bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
21440
|
+
mkdirSync16(dir, { recursive: true });
|
|
21441
|
+
writeFileSync31(bodyPath, body);
|
|
21442
|
+
writeFileSync31(
|
|
21443
|
+
metaPath,
|
|
21444
|
+
`${JSON.stringify({ target, updatedAt }, null, 2)}
|
|
21445
|
+
`
|
|
21446
|
+
);
|
|
21447
|
+
return bodyPath;
|
|
21448
|
+
}
|
|
21449
|
+
|
|
21450
|
+
// src/commands/github/issue/prepareIssueEdit.ts
|
|
21451
|
+
function slugFromUrl(url) {
|
|
21452
|
+
const match = /github\.com\/([^/]+\/[^/]+)\//.exec(url ?? "");
|
|
21453
|
+
return match ? match[1] : "unknown/unknown";
|
|
21454
|
+
}
|
|
21455
|
+
function prepareIssueEdit(number, repo, fresh) {
|
|
21456
|
+
const issue = fetchIssue2(number, repo);
|
|
21457
|
+
const slug = repo ?? slugFromUrl(issue.url);
|
|
21458
|
+
const target = `${slug}#${number}`;
|
|
21459
|
+
const resumed = fresh ? void 0 : resumeIssueBody(slug, number, issue.updatedAt);
|
|
21460
|
+
const body = resumed ?? issue.body;
|
|
21461
|
+
validateIssueBody(issue.title, body);
|
|
21462
|
+
const save = (markdown) => writeIssueWorkingFile(slug, number, target, issue.updatedAt, markdown);
|
|
21463
|
+
const bodyPath = save(body);
|
|
21464
|
+
if (resumed !== void 0)
|
|
21465
|
+
console.log(`Previewing the in-progress markdown from ${bodyPath}`);
|
|
21466
|
+
return {
|
|
21467
|
+
title: issue.title,
|
|
21468
|
+
target,
|
|
21469
|
+
updatedAt: issue.updatedAt,
|
|
21470
|
+
body,
|
|
21471
|
+
bodyPath,
|
|
21472
|
+
save
|
|
21473
|
+
};
|
|
21474
|
+
}
|
|
21475
|
+
|
|
21476
|
+
// src/commands/github/issue/pushIssueBody.ts
|
|
21477
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
21478
|
+
function pushIssueBody(number, repo, bodyPath) {
|
|
21479
|
+
const args = ["issue", "edit", String(number), "--body-file", bodyPath];
|
|
21480
|
+
if (repo) args.push("--repo", repo);
|
|
21481
|
+
try {
|
|
21482
|
+
execFileSync9("gh", args, { stdio: "inherit" });
|
|
21483
|
+
} catch {
|
|
21484
|
+
process.exit(1);
|
|
21485
|
+
}
|
|
21486
|
+
}
|
|
21487
|
+
|
|
21488
|
+
// src/commands/github/issue/pushUnchangedIssue.ts
|
|
21489
|
+
function pushUnchangedIssue(number, repo, target, fetchedAt, bodyPath) {
|
|
21490
|
+
if (fetchIssue2(number, repo).updatedAt !== fetchedAt) {
|
|
21491
|
+
console.error(
|
|
21492
|
+
`${target} was updated on GitHub after it was fetched. Nothing was pushed; the markdown is at ${bodyPath}`
|
|
21493
|
+
);
|
|
21494
|
+
process.exit(1);
|
|
21495
|
+
}
|
|
21496
|
+
pushIssueBody(number, repo, bodyPath);
|
|
21497
|
+
console.log(`Issue body updated on ${target}`);
|
|
21498
|
+
}
|
|
21499
|
+
|
|
21500
|
+
// src/commands/github/issue/reviewProposedIssueEdit.ts
|
|
21501
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
21502
|
+
async function reviewProposedIssueEdit(title, body, working) {
|
|
21503
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
21504
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return body;
|
|
21505
|
+
const decision = await awaitPreviewApproval(
|
|
21506
|
+
"GitHub issue edit preview",
|
|
21507
|
+
{
|
|
21508
|
+
sessionId,
|
|
21509
|
+
requestId: randomUUID9(),
|
|
21510
|
+
title,
|
|
21511
|
+
body,
|
|
21512
|
+
prNumber: null,
|
|
21513
|
+
kind: "github-issue-edit"
|
|
21514
|
+
},
|
|
21515
|
+
{
|
|
21516
|
+
saveEditedBody: working.save,
|
|
21517
|
+
rejectionAdvice: `Nothing was pushed. The pane's markdown, including any collapses already applied, is at ${working.path}. Revise that file in place \u2014 do not recompose the body from scratch \u2014 then re-run this command to preview the revision.`
|
|
21518
|
+
}
|
|
21519
|
+
);
|
|
21520
|
+
return decision.body ?? body;
|
|
21521
|
+
}
|
|
21522
|
+
|
|
21523
|
+
// src/commands/github/issue/viewIssue.ts
|
|
21524
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
21525
|
+
function viewIssue(number, repo) {
|
|
21526
|
+
const args = ["issue", "view", String(number)];
|
|
21527
|
+
if (repo) args.push("--repo", repo);
|
|
21528
|
+
try {
|
|
21529
|
+
execFileSync10("gh", args, { stdio: "inherit" });
|
|
21530
|
+
} catch {
|
|
21531
|
+
process.exit(1);
|
|
21532
|
+
}
|
|
21533
|
+
}
|
|
21534
|
+
|
|
21535
|
+
// src/commands/github/issue/editIssue.ts
|
|
21536
|
+
var USAGE3 = "Usage: assist github issue edit <number> [-R <owner>/<repo>]";
|
|
21537
|
+
async function editIssue(numberArg, options2) {
|
|
21538
|
+
const number = Number.parseInt(numberArg, 10);
|
|
21539
|
+
if (!Number.isInteger(number) || number <= 0) {
|
|
21540
|
+
console.error(USAGE3);
|
|
21541
|
+
process.exit(1);
|
|
21542
|
+
}
|
|
21543
|
+
if (!inWebSession()) {
|
|
21544
|
+
viewIssue(number, options2.repo);
|
|
21545
|
+
return;
|
|
21546
|
+
}
|
|
21547
|
+
const issue = prepareIssueEdit(number, options2.repo, options2.fresh);
|
|
21548
|
+
const edited = await reviewProposedIssueEdit(
|
|
21549
|
+
`Edit ${issue.target}: ${issue.title}`,
|
|
21550
|
+
issue.body,
|
|
21551
|
+
{ path: issue.bodyPath, save: issue.save }
|
|
21552
|
+
);
|
|
21553
|
+
validateIssueBody(issue.title, edited);
|
|
21554
|
+
pushUnchangedIssue(
|
|
21555
|
+
number,
|
|
21556
|
+
options2.repo,
|
|
21557
|
+
issue.target,
|
|
21558
|
+
issue.updatedAt,
|
|
21559
|
+
issue.bodyPath
|
|
21560
|
+
);
|
|
21561
|
+
}
|
|
21562
|
+
|
|
21563
|
+
// src/commands/github/issue/registerEditIssue.ts
|
|
21564
|
+
function registerEditIssue(issueCommand) {
|
|
21423
21565
|
issueCommand.command("edit <number>").description("Edit an existing GitHub issue's body in the preview pane").option(
|
|
21424
21566
|
"-R, --repo <owner/repo>",
|
|
21425
21567
|
"Target repository (defaults to the current repo)"
|
|
@@ -21430,20 +21572,14 @@ function registerGithubIssue(githubCommand) {
|
|
|
21430
21572
|
"after",
|
|
21431
21573
|
"\nFetches the issue's current body and opens it in the assist web preview pane, where it can be reworked before it is pushed back. Approving pushes the pane's markdown to the issue; nothing is pushed if the issue moved on GitHub after it was fetched, or outside a web session.\nRejecting writes the pane's markdown to a working file and names it: revise that file in place and re-run to preview the revision, which keeps any collapses already applied. A re-run resumes from the working file while the issue has not moved on GitHub; --fresh discards it and re-fetches.\nOnly the body is touched \u2014 the title, labels, assignees and state are left alone."
|
|
21432
21574
|
).action(editIssue);
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
|
|
21436
|
-
|
|
21437
|
-
|
|
21438
|
-
|
|
21439
|
-
)
|
|
21440
|
-
|
|
21441
|
-
await commentIssue(number, {
|
|
21442
|
-
...options2,
|
|
21443
|
-
body: options2.body ? await readBodyArgument(options2.body) : void 0
|
|
21444
|
-
});
|
|
21445
|
-
}
|
|
21446
|
-
);
|
|
21575
|
+
}
|
|
21576
|
+
|
|
21577
|
+
// src/commands/registerGithubIssue.ts
|
|
21578
|
+
function registerGithubIssue(githubCommand) {
|
|
21579
|
+
const issueCommand = githubCommand.command("issue").description("GitHub issue utilities");
|
|
21580
|
+
registerCreateIssue(issueCommand);
|
|
21581
|
+
registerEditIssue(issueCommand);
|
|
21582
|
+
registerCommentIssue(issueCommand);
|
|
21447
21583
|
registerFixStructure(issueCommand);
|
|
21448
21584
|
}
|
|
21449
21585
|
|
|
@@ -21684,7 +21820,7 @@ function registerHandover(program2) {
|
|
|
21684
21820
|
}
|
|
21685
21821
|
|
|
21686
21822
|
// src/commands/jira/acceptanceCriteria.ts
|
|
21687
|
-
import
|
|
21823
|
+
import chalk165 from "chalk";
|
|
21688
21824
|
|
|
21689
21825
|
// src/commands/jira/adfToText.ts
|
|
21690
21826
|
function renderInline(node) {
|
|
@@ -21751,7 +21887,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
21751
21887
|
const parsed = fetchIssue(issueKey, field);
|
|
21752
21888
|
const acValue = parsed?.fields?.[field];
|
|
21753
21889
|
if (!acValue) {
|
|
21754
|
-
console.log(
|
|
21890
|
+
console.log(chalk165.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
21755
21891
|
return;
|
|
21756
21892
|
}
|
|
21757
21893
|
if (typeof acValue === "string") {
|
|
@@ -21817,14 +21953,14 @@ async function jiraAuth() {
|
|
|
21817
21953
|
}
|
|
21818
21954
|
|
|
21819
21955
|
// src/commands/jira/viewIssue.ts
|
|
21820
|
-
import
|
|
21956
|
+
import chalk166 from "chalk";
|
|
21821
21957
|
function viewIssue2(issueKey) {
|
|
21822
21958
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
21823
21959
|
const fields = parsed?.fields;
|
|
21824
21960
|
const summary = fields?.summary;
|
|
21825
21961
|
const description = fields?.description;
|
|
21826
21962
|
if (summary) {
|
|
21827
|
-
console.log(
|
|
21963
|
+
console.log(chalk166.bold(summary));
|
|
21828
21964
|
}
|
|
21829
21965
|
if (description) {
|
|
21830
21966
|
if (summary) console.log();
|
|
@@ -21838,7 +21974,7 @@ function viewIssue2(issueKey) {
|
|
|
21838
21974
|
}
|
|
21839
21975
|
if (!summary && !description) {
|
|
21840
21976
|
console.log(
|
|
21841
|
-
|
|
21977
|
+
chalk166.yellow(`No summary or description found on ${issueKey}.`)
|
|
21842
21978
|
);
|
|
21843
21979
|
}
|
|
21844
21980
|
}
|
|
@@ -21873,7 +22009,7 @@ import { randomUUID as randomUUID10 } from "crypto";
|
|
|
21873
22009
|
|
|
21874
22010
|
// src/commands/review/checkoutPr.ts
|
|
21875
22011
|
import { execFileSync as execFileSync12 } from "child_process";
|
|
21876
|
-
import
|
|
22012
|
+
import chalk167 from "chalk";
|
|
21877
22013
|
|
|
21878
22014
|
// src/commands/sessions/daemon/daemonLog.ts
|
|
21879
22015
|
var RING_CAPACITY = 1e3;
|
|
@@ -22485,7 +22621,7 @@ async function checkoutPr(number) {
|
|
|
22485
22621
|
try {
|
|
22486
22622
|
execFileSync12("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
22487
22623
|
} catch {
|
|
22488
|
-
console.error(
|
|
22624
|
+
console.error(chalk167.red(`gh pr checkout ${number} failed; aborting.`));
|
|
22489
22625
|
process.exit(1);
|
|
22490
22626
|
}
|
|
22491
22627
|
}
|
|
@@ -22622,15 +22758,15 @@ function registerList(program2) {
|
|
|
22622
22758
|
// src/commands/mermaid/index.ts
|
|
22623
22759
|
import { mkdirSync as mkdirSync18, readdirSync as readdirSync11 } from "fs";
|
|
22624
22760
|
import { resolve as resolve16 } from "path";
|
|
22625
|
-
import
|
|
22761
|
+
import chalk170 from "chalk";
|
|
22626
22762
|
|
|
22627
22763
|
// src/commands/mermaid/exportFile.ts
|
|
22628
22764
|
import { readFileSync as readFileSync39, writeFileSync as writeFileSync32 } from "fs";
|
|
22629
22765
|
import { basename as basename17, extname as extname2, resolve as resolve15 } from "path";
|
|
22630
|
-
import
|
|
22766
|
+
import chalk169 from "chalk";
|
|
22631
22767
|
|
|
22632
22768
|
// src/commands/mermaid/renderBlock.ts
|
|
22633
|
-
import
|
|
22769
|
+
import chalk168 from "chalk";
|
|
22634
22770
|
async function renderBlock(krokiUrl, source) {
|
|
22635
22771
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
22636
22772
|
method: "POST",
|
|
@@ -22639,7 +22775,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
22639
22775
|
});
|
|
22640
22776
|
if (!response.ok) {
|
|
22641
22777
|
console.error(
|
|
22642
|
-
|
|
22778
|
+
chalk168.red(
|
|
22643
22779
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
22644
22780
|
)
|
|
22645
22781
|
);
|
|
@@ -22657,19 +22793,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
22657
22793
|
if (onlyIndex !== void 0) {
|
|
22658
22794
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
22659
22795
|
console.error(
|
|
22660
|
-
|
|
22796
|
+
chalk169.red(
|
|
22661
22797
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
22662
22798
|
)
|
|
22663
22799
|
);
|
|
22664
22800
|
process.exit(1);
|
|
22665
22801
|
}
|
|
22666
22802
|
console.log(
|
|
22667
|
-
|
|
22803
|
+
chalk169.gray(
|
|
22668
22804
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
22669
22805
|
)
|
|
22670
22806
|
);
|
|
22671
22807
|
} else {
|
|
22672
|
-
console.log(
|
|
22808
|
+
console.log(chalk169.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
22673
22809
|
}
|
|
22674
22810
|
for (const [i, source] of blocks.entries()) {
|
|
22675
22811
|
const idx = i + 1;
|
|
@@ -22677,7 +22813,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
22677
22813
|
const outPath = resolve15(outDir, `${stem}-${idx}.svg`);
|
|
22678
22814
|
const svg = await renderBlock(krokiUrl, source);
|
|
22679
22815
|
writeFileSync32(outPath, svg, "utf8");
|
|
22680
|
-
console.log(
|
|
22816
|
+
console.log(chalk169.green(` \u2192 ${outPath}`));
|
|
22681
22817
|
}
|
|
22682
22818
|
}
|
|
22683
22819
|
function extractMermaidBlocks(markdown) {
|
|
@@ -22693,18 +22829,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
22693
22829
|
if (options2.index !== void 0) {
|
|
22694
22830
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
22695
22831
|
console.error(
|
|
22696
|
-
|
|
22832
|
+
chalk170.red(`--index must be a positive integer (got ${options2.index})`)
|
|
22697
22833
|
);
|
|
22698
22834
|
process.exit(1);
|
|
22699
22835
|
}
|
|
22700
22836
|
if (!file) {
|
|
22701
|
-
console.error(
|
|
22837
|
+
console.error(chalk170.red("--index requires a file argument"));
|
|
22702
22838
|
process.exit(1);
|
|
22703
22839
|
}
|
|
22704
22840
|
}
|
|
22705
22841
|
const files = file ? [file] : readdirSync11(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
22706
22842
|
if (files.length === 0) {
|
|
22707
|
-
console.log(
|
|
22843
|
+
console.log(chalk170.gray("No markdown files found in current directory."));
|
|
22708
22844
|
return;
|
|
22709
22845
|
}
|
|
22710
22846
|
for (const f of files) {
|
|
@@ -22760,13 +22896,13 @@ function stripHtml2(content) {
|
|
|
22760
22896
|
|
|
22761
22897
|
// src/commands/miro/normaliseItems.ts
|
|
22762
22898
|
var frameCoordinates = "parent_top_left";
|
|
22763
|
-
function
|
|
22899
|
+
function describe4(item) {
|
|
22764
22900
|
return ` ${item.id ?? "(no id)"} (${item.type ?? "unknown type"}): relativeTo=${item.position?.relativeTo ?? "missing"}`;
|
|
22765
22901
|
}
|
|
22766
22902
|
function coordinateSpaceError(rejected) {
|
|
22767
22903
|
return new MiroExtractError(
|
|
22768
22904
|
`${rejected.length} item(s) are not in frame coordinates (position.relativeTo must be "${frameCoordinates}"):
|
|
22769
|
-
${rejected.slice(0, 5).map(
|
|
22905
|
+
${rejected.slice(0, 5).map(describe4).join(
|
|
22770
22906
|
"\n"
|
|
22771
22907
|
)}
|
|
22772
22908
|
|
|
@@ -22911,7 +23047,7 @@ function registerMiro(program2) {
|
|
|
22911
23047
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
22912
23048
|
import { createServer as createServer2 } from "http";
|
|
22913
23049
|
import { dirname as dirname28 } from "path";
|
|
22914
|
-
import
|
|
23050
|
+
import chalk172 from "chalk";
|
|
22915
23051
|
|
|
22916
23052
|
// src/commands/netcap/corsHeaders.ts
|
|
22917
23053
|
var corsHeaders = {
|
|
@@ -22990,7 +23126,7 @@ function createNetcapHandler(options2) {
|
|
|
22990
23126
|
import { cp, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
22991
23127
|
import { networkInterfaces } from "os";
|
|
22992
23128
|
import { join as join58 } from "path";
|
|
22993
|
-
import
|
|
23129
|
+
import chalk171 from "chalk";
|
|
22994
23130
|
|
|
22995
23131
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
22996
23132
|
import { dirname as dirname27, join as join57 } from "path";
|
|
@@ -23034,7 +23170,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
23034
23170
|
const host = lanIPv4();
|
|
23035
23171
|
if (!host) {
|
|
23036
23172
|
console.log(
|
|
23037
|
-
|
|
23173
|
+
chalk171.yellow("could not determine the WSL IP for the extension")
|
|
23038
23174
|
);
|
|
23039
23175
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
23040
23176
|
return source;
|
|
@@ -23045,7 +23181,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
23045
23181
|
return WSL_WINDOWS_PATH;
|
|
23046
23182
|
} catch {
|
|
23047
23183
|
console.log(
|
|
23048
|
-
|
|
23184
|
+
chalk171.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
23049
23185
|
);
|
|
23050
23186
|
return source;
|
|
23051
23187
|
}
|
|
@@ -23078,30 +23214,30 @@ async function netcap(options2) {
|
|
|
23078
23214
|
let count8 = 0;
|
|
23079
23215
|
const handler = createNetcapHandler({
|
|
23080
23216
|
outPath,
|
|
23081
|
-
onPing: () => console.log(
|
|
23217
|
+
onPing: () => console.log(chalk172.dim("ping from extension")),
|
|
23082
23218
|
onCapture: (entry) => {
|
|
23083
23219
|
count8 += 1;
|
|
23084
23220
|
console.log(
|
|
23085
|
-
|
|
23086
|
-
|
|
23221
|
+
chalk172.green(`captured #${count8}`),
|
|
23222
|
+
chalk172.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
23087
23223
|
);
|
|
23088
23224
|
}
|
|
23089
23225
|
});
|
|
23090
23226
|
const server = createServer2(handler);
|
|
23091
23227
|
server.listen(port, () => {
|
|
23092
23228
|
console.log(
|
|
23093
|
-
|
|
23229
|
+
chalk172.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
23094
23230
|
);
|
|
23095
|
-
console.log(
|
|
23231
|
+
console.log(chalk172.dim(`appending captures to ${outPath}`));
|
|
23096
23232
|
if (filter)
|
|
23097
|
-
console.log(
|
|
23098
|
-
console.log(
|
|
23099
|
-
console.log(
|
|
23233
|
+
console.log(chalk172.dim(`forwarding only URLs matching "${filter}"`));
|
|
23234
|
+
console.log(chalk172.dim(`load the unpacked extension from ${extensionPath}`));
|
|
23235
|
+
console.log(chalk172.dim("press Ctrl-C to stop"));
|
|
23100
23236
|
});
|
|
23101
23237
|
process.on("SIGINT", () => {
|
|
23102
23238
|
server.close();
|
|
23103
23239
|
console.log(
|
|
23104
|
-
|
|
23240
|
+
chalk172.bold(
|
|
23105
23241
|
`
|
|
23106
23242
|
netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
23107
23243
|
)
|
|
@@ -23113,7 +23249,7 @@ netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} t
|
|
|
23113
23249
|
// src/commands/netcap/netcapExtract.ts
|
|
23114
23250
|
import { writeFileSync as writeFileSync33 } from "fs";
|
|
23115
23251
|
import { join as join61 } from "path";
|
|
23116
|
-
import
|
|
23252
|
+
import chalk173 from "chalk";
|
|
23117
23253
|
|
|
23118
23254
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
23119
23255
|
import { readFileSync as readFileSync41 } from "fs";
|
|
@@ -23561,8 +23697,8 @@ function netcapExtract(file) {
|
|
|
23561
23697
|
writeFileSync33(outFile, `${JSON.stringify(posts, null, 2)}
|
|
23562
23698
|
`);
|
|
23563
23699
|
console.log(
|
|
23564
|
-
|
|
23565
|
-
|
|
23700
|
+
chalk173.green(`extracted ${posts.length} posts`),
|
|
23701
|
+
chalk173.dim(`-> ${outFile}`)
|
|
23566
23702
|
);
|
|
23567
23703
|
}
|
|
23568
23704
|
|
|
@@ -23583,7 +23719,7 @@ function registerNetcap(program2) {
|
|
|
23583
23719
|
}
|
|
23584
23720
|
|
|
23585
23721
|
// src/commands/news/add/index.ts
|
|
23586
|
-
import
|
|
23722
|
+
import chalk174 from "chalk";
|
|
23587
23723
|
import enquirer8 from "enquirer";
|
|
23588
23724
|
async function add2(url) {
|
|
23589
23725
|
if (!url) {
|
|
@@ -23605,10 +23741,10 @@ async function add2(url) {
|
|
|
23605
23741
|
const { orm } = await getReady();
|
|
23606
23742
|
const added = await addFeed(orm, url);
|
|
23607
23743
|
if (!added) {
|
|
23608
|
-
console.log(
|
|
23744
|
+
console.log(chalk174.yellow("Feed already exists"));
|
|
23609
23745
|
return;
|
|
23610
23746
|
}
|
|
23611
|
-
console.log(
|
|
23747
|
+
console.log(chalk174.green(`Added feed: ${url}`));
|
|
23612
23748
|
}
|
|
23613
23749
|
|
|
23614
23750
|
// src/commands/registerNews.ts
|
|
@@ -23655,7 +23791,7 @@ function registerPiHook(program2) {
|
|
|
23655
23791
|
}
|
|
23656
23792
|
|
|
23657
23793
|
// src/commands/prompts/printPromptsTable.ts
|
|
23658
|
-
import
|
|
23794
|
+
import chalk175 from "chalk";
|
|
23659
23795
|
function truncate(str, max) {
|
|
23660
23796
|
if (str.length <= max) return str;
|
|
23661
23797
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -23673,14 +23809,14 @@ function printPromptsTable(rows) {
|
|
|
23673
23809
|
"Command".padEnd(commandWidth),
|
|
23674
23810
|
"Repos"
|
|
23675
23811
|
].join(" ");
|
|
23676
|
-
console.log(
|
|
23677
|
-
console.log(
|
|
23812
|
+
console.log(chalk175.dim(header));
|
|
23813
|
+
console.log(chalk175.dim("-".repeat(header.length)));
|
|
23678
23814
|
for (const row of rows) {
|
|
23679
23815
|
const count8 = String(row.count).padStart(countWidth);
|
|
23680
23816
|
const tool = row.tool.padEnd(toolWidth);
|
|
23681
23817
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
23682
23818
|
console.log(
|
|
23683
|
-
`${
|
|
23819
|
+
`${chalk175.yellow(count8)} ${tool} ${command} ${chalk175.dim(row.repos)}`
|
|
23684
23820
|
);
|
|
23685
23821
|
}
|
|
23686
23822
|
}
|
|
@@ -24347,13 +24483,13 @@ function agentFooter(unresolvedCount) {
|
|
|
24347
24483
|
}
|
|
24348
24484
|
|
|
24349
24485
|
// src/commands/prs/listComments/commentStyle.ts
|
|
24350
|
-
import
|
|
24486
|
+
import chalk176 from "chalk";
|
|
24351
24487
|
var plain = (text18) => text18;
|
|
24352
24488
|
function colouredState(state) {
|
|
24353
24489
|
const label2 = `[${state}]`;
|
|
24354
|
-
if (state === "APPROVED") return
|
|
24355
|
-
if (state === "CHANGES_REQUESTED") return
|
|
24356
|
-
return
|
|
24490
|
+
if (state === "APPROVED") return chalk176.green(label2);
|
|
24491
|
+
if (state === "CHANGES_REQUESTED") return chalk176.red(label2);
|
|
24492
|
+
return chalk176.yellow(label2);
|
|
24357
24493
|
}
|
|
24358
24494
|
function commentStyle() {
|
|
24359
24495
|
if (isClaudeCode()) {
|
|
@@ -24367,9 +24503,9 @@ function commentStyle() {
|
|
|
24367
24503
|
};
|
|
24368
24504
|
}
|
|
24369
24505
|
return {
|
|
24370
|
-
cyan:
|
|
24371
|
-
bold:
|
|
24372
|
-
dim:
|
|
24506
|
+
cyan: chalk176.cyan,
|
|
24507
|
+
bold: chalk176.bold,
|
|
24508
|
+
dim: chalk176.dim,
|
|
24373
24509
|
state: colouredState,
|
|
24374
24510
|
diffHunk: true,
|
|
24375
24511
|
agent: false
|
|
@@ -24539,13 +24675,13 @@ import { execSync as execSync48 } from "child_process";
|
|
|
24539
24675
|
import enquirer9 from "enquirer";
|
|
24540
24676
|
|
|
24541
24677
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
24542
|
-
import
|
|
24678
|
+
import chalk177 from "chalk";
|
|
24543
24679
|
var STATUS_MAP = {
|
|
24544
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
24545
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
24680
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk177.magenta("merged"), date: pr.mergedAt } : null,
|
|
24681
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk177.red("closed"), date: pr.closedAt } : null
|
|
24546
24682
|
};
|
|
24547
24683
|
function defaultStatus(pr) {
|
|
24548
|
-
return { label:
|
|
24684
|
+
return { label: chalk177.green("opened"), date: pr.createdAt };
|
|
24549
24685
|
}
|
|
24550
24686
|
function getStatus2(pr) {
|
|
24551
24687
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -24554,11 +24690,11 @@ function formatDate(dateStr) {
|
|
|
24554
24690
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
24555
24691
|
}
|
|
24556
24692
|
function formatPrHeader(pr, status3) {
|
|
24557
|
-
return `${
|
|
24693
|
+
return `${chalk177.cyan(`#${pr.number}`)} ${pr.title} ${chalk177.dim(`(${pr.author.login},`)} ${status3.label} ${chalk177.dim(`${formatDate(status3.date)})`)}`;
|
|
24558
24694
|
}
|
|
24559
24695
|
function logPrDetails(pr) {
|
|
24560
24696
|
console.log(
|
|
24561
|
-
|
|
24697
|
+
chalk177.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
24562
24698
|
);
|
|
24563
24699
|
console.log();
|
|
24564
24700
|
}
|
|
@@ -25273,10 +25409,10 @@ function registerPrs(program2) {
|
|
|
25273
25409
|
}
|
|
25274
25410
|
|
|
25275
25411
|
// src/commands/ravendb/ravendbAuth.ts
|
|
25276
|
-
import
|
|
25412
|
+
import chalk183 from "chalk";
|
|
25277
25413
|
|
|
25278
25414
|
// src/shared/createConnectionAuth.ts
|
|
25279
|
-
import
|
|
25415
|
+
import chalk178 from "chalk";
|
|
25280
25416
|
function listConnections(connections, format) {
|
|
25281
25417
|
if (connections.length === 0) {
|
|
25282
25418
|
console.log("No connections configured.");
|
|
@@ -25289,7 +25425,7 @@ function listConnections(connections, format) {
|
|
|
25289
25425
|
function removeConnection(connections, name, save) {
|
|
25290
25426
|
const filtered = connections.filter((c) => c.name !== name);
|
|
25291
25427
|
if (filtered.length === connections.length) {
|
|
25292
|
-
console.error(
|
|
25428
|
+
console.error(chalk178.red(`Connection "${name}" not found.`));
|
|
25293
25429
|
process.exit(1);
|
|
25294
25430
|
}
|
|
25295
25431
|
save(filtered);
|
|
@@ -25335,15 +25471,15 @@ function saveConnections(connections) {
|
|
|
25335
25471
|
}
|
|
25336
25472
|
|
|
25337
25473
|
// src/commands/ravendb/promptConnection.ts
|
|
25338
|
-
import
|
|
25474
|
+
import chalk181 from "chalk";
|
|
25339
25475
|
|
|
25340
25476
|
// src/commands/ravendb/selectOpSecret.ts
|
|
25341
|
-
import
|
|
25477
|
+
import chalk180 from "chalk";
|
|
25342
25478
|
import Enquirer2 from "enquirer";
|
|
25343
25479
|
|
|
25344
25480
|
// src/commands/ravendb/searchItems.ts
|
|
25345
25481
|
import { execSync as execSync51 } from "child_process";
|
|
25346
|
-
import
|
|
25482
|
+
import chalk179 from "chalk";
|
|
25347
25483
|
function opExec(args) {
|
|
25348
25484
|
return execSync51(`op ${args}`, {
|
|
25349
25485
|
encoding: "utf8",
|
|
@@ -25356,7 +25492,7 @@ function searchItems(search2) {
|
|
|
25356
25492
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
25357
25493
|
} catch {
|
|
25358
25494
|
console.error(
|
|
25359
|
-
|
|
25495
|
+
chalk179.red(
|
|
25360
25496
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
25361
25497
|
)
|
|
25362
25498
|
);
|
|
@@ -25370,7 +25506,7 @@ function getItemFields(itemId2) {
|
|
|
25370
25506
|
const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
|
|
25371
25507
|
return item.fields.filter((f) => f.reference && f.label);
|
|
25372
25508
|
} catch {
|
|
25373
|
-
console.error(
|
|
25509
|
+
console.error(chalk179.red("Failed to get item details from 1Password."));
|
|
25374
25510
|
process.exit(1);
|
|
25375
25511
|
}
|
|
25376
25512
|
}
|
|
@@ -25389,7 +25525,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
25389
25525
|
}).run();
|
|
25390
25526
|
const items2 = searchItems(search2);
|
|
25391
25527
|
if (items2.length === 0) {
|
|
25392
|
-
console.error(
|
|
25528
|
+
console.error(chalk180.red(`No items found matching "${search2}".`));
|
|
25393
25529
|
process.exit(1);
|
|
25394
25530
|
}
|
|
25395
25531
|
const itemId2 = await selectOne(
|
|
@@ -25398,7 +25534,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
25398
25534
|
);
|
|
25399
25535
|
const fields = getItemFields(itemId2);
|
|
25400
25536
|
if (fields.length === 0) {
|
|
25401
|
-
console.error(
|
|
25537
|
+
console.error(chalk180.red("No fields with references found on this item."));
|
|
25402
25538
|
process.exit(1);
|
|
25403
25539
|
}
|
|
25404
25540
|
const ref = await selectOne(
|
|
@@ -25412,7 +25548,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
25412
25548
|
async function promptConnection(existingNames) {
|
|
25413
25549
|
const name = await promptInput("name", "Connection name:");
|
|
25414
25550
|
if (existingNames.includes(name)) {
|
|
25415
|
-
console.error(
|
|
25551
|
+
console.error(chalk181.red(`Connection "${name}" already exists.`));
|
|
25416
25552
|
process.exit(1);
|
|
25417
25553
|
}
|
|
25418
25554
|
const url = await promptInput(
|
|
@@ -25421,22 +25557,22 @@ async function promptConnection(existingNames) {
|
|
|
25421
25557
|
);
|
|
25422
25558
|
const database = await promptInput("database", "Database name:");
|
|
25423
25559
|
if (!name || !url || !database) {
|
|
25424
|
-
console.error(
|
|
25560
|
+
console.error(chalk181.red("All fields are required."));
|
|
25425
25561
|
process.exit(1);
|
|
25426
25562
|
}
|
|
25427
25563
|
const apiKeyRef = await selectOpSecret();
|
|
25428
|
-
console.log(
|
|
25564
|
+
console.log(chalk181.dim(`Using: ${apiKeyRef}`));
|
|
25429
25565
|
return { name, url, database, apiKeyRef };
|
|
25430
25566
|
}
|
|
25431
25567
|
|
|
25432
25568
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
25433
|
-
import
|
|
25569
|
+
import chalk182 from "chalk";
|
|
25434
25570
|
function ravendbSetConnection(name) {
|
|
25435
25571
|
const raw = loadGlobalConfigRaw();
|
|
25436
25572
|
const ravendb = raw.ravendb ?? {};
|
|
25437
25573
|
const connections = ravendb.connections ?? [];
|
|
25438
25574
|
if (!connections.some((c) => c.name === name)) {
|
|
25439
|
-
console.error(
|
|
25575
|
+
console.error(chalk182.red(`Connection "${name}" not found.`));
|
|
25440
25576
|
console.error(
|
|
25441
25577
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
25442
25578
|
);
|
|
@@ -25452,16 +25588,16 @@ function ravendbSetConnection(name) {
|
|
|
25452
25588
|
var ravendbAuth = createConnectionAuth({
|
|
25453
25589
|
load: loadConnections,
|
|
25454
25590
|
save: saveConnections,
|
|
25455
|
-
format: (c) => `${
|
|
25591
|
+
format: (c) => `${chalk183.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
25456
25592
|
promptNew: promptConnection,
|
|
25457
25593
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
25458
25594
|
});
|
|
25459
25595
|
|
|
25460
25596
|
// src/commands/ravendb/ravendbCollections.ts
|
|
25461
|
-
import
|
|
25597
|
+
import chalk187 from "chalk";
|
|
25462
25598
|
|
|
25463
25599
|
// src/commands/ravendb/ravenFetch.ts
|
|
25464
|
-
import
|
|
25600
|
+
import chalk185 from "chalk";
|
|
25465
25601
|
|
|
25466
25602
|
// src/commands/ravendb/getAccessToken.ts
|
|
25467
25603
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -25498,10 +25634,10 @@ ${errorText}`
|
|
|
25498
25634
|
|
|
25499
25635
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
25500
25636
|
import { execSync as execSync52 } from "child_process";
|
|
25501
|
-
import
|
|
25637
|
+
import chalk184 from "chalk";
|
|
25502
25638
|
function resolveOpSecret(reference) {
|
|
25503
25639
|
if (!reference.startsWith("op://")) {
|
|
25504
|
-
console.error(
|
|
25640
|
+
console.error(chalk184.red(`Invalid secret reference: must start with op://`));
|
|
25505
25641
|
process.exit(1);
|
|
25506
25642
|
}
|
|
25507
25643
|
try {
|
|
@@ -25511,7 +25647,7 @@ function resolveOpSecret(reference) {
|
|
|
25511
25647
|
}).trim();
|
|
25512
25648
|
} catch {
|
|
25513
25649
|
console.error(
|
|
25514
|
-
|
|
25650
|
+
chalk184.red(
|
|
25515
25651
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
25516
25652
|
)
|
|
25517
25653
|
);
|
|
@@ -25538,7 +25674,7 @@ async function ravenFetch(connection, path80) {
|
|
|
25538
25674
|
if (!response.ok) {
|
|
25539
25675
|
const body = await response.text();
|
|
25540
25676
|
console.error(
|
|
25541
|
-
|
|
25677
|
+
chalk185.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
25542
25678
|
);
|
|
25543
25679
|
console.error(body.substring(0, 500));
|
|
25544
25680
|
process.exit(1);
|
|
@@ -25547,7 +25683,7 @@ async function ravenFetch(connection, path80) {
|
|
|
25547
25683
|
}
|
|
25548
25684
|
|
|
25549
25685
|
// src/commands/ravendb/resolveConnection.ts
|
|
25550
|
-
import
|
|
25686
|
+
import chalk186 from "chalk";
|
|
25551
25687
|
function loadRavendb() {
|
|
25552
25688
|
const raw = loadGlobalConfigRaw();
|
|
25553
25689
|
const ravendb = raw.ravendb;
|
|
@@ -25561,7 +25697,7 @@ function resolveConnection(name) {
|
|
|
25561
25697
|
const connectionName = name ?? defaultConnection;
|
|
25562
25698
|
if (!connectionName) {
|
|
25563
25699
|
console.error(
|
|
25564
|
-
|
|
25700
|
+
chalk186.red(
|
|
25565
25701
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
25566
25702
|
)
|
|
25567
25703
|
);
|
|
@@ -25569,7 +25705,7 @@ function resolveConnection(name) {
|
|
|
25569
25705
|
}
|
|
25570
25706
|
const connection = connections.find((c) => c.name === connectionName);
|
|
25571
25707
|
if (!connection) {
|
|
25572
|
-
console.error(
|
|
25708
|
+
console.error(chalk186.red(`Connection "${connectionName}" not found.`));
|
|
25573
25709
|
console.error(
|
|
25574
25710
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
25575
25711
|
);
|
|
@@ -25600,15 +25736,15 @@ async function ravendbCollections(connectionName) {
|
|
|
25600
25736
|
return;
|
|
25601
25737
|
}
|
|
25602
25738
|
for (const c of collections) {
|
|
25603
|
-
console.log(`${
|
|
25739
|
+
console.log(`${chalk187.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
25604
25740
|
}
|
|
25605
25741
|
}
|
|
25606
25742
|
|
|
25607
25743
|
// src/commands/ravendb/ravendbQuery.ts
|
|
25608
|
-
import
|
|
25744
|
+
import chalk189 from "chalk";
|
|
25609
25745
|
|
|
25610
25746
|
// src/commands/ravendb/fetchAllPages.ts
|
|
25611
|
-
import
|
|
25747
|
+
import chalk188 from "chalk";
|
|
25612
25748
|
|
|
25613
25749
|
// src/commands/ravendb/buildQueryPath.ts
|
|
25614
25750
|
function buildQueryPath(opts) {
|
|
@@ -25646,7 +25782,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25646
25782
|
allResults.push(...results);
|
|
25647
25783
|
start3 += results.length;
|
|
25648
25784
|
process.stderr.write(
|
|
25649
|
-
`\r${
|
|
25785
|
+
`\r${chalk188.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
25650
25786
|
);
|
|
25651
25787
|
if (start3 >= totalResults) break;
|
|
25652
25788
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -25661,7 +25797,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25661
25797
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
25662
25798
|
const resolved = resolveArgs(connectionName, collection);
|
|
25663
25799
|
if (!resolved.collection && !options2.query) {
|
|
25664
|
-
console.error(
|
|
25800
|
+
console.error(chalk189.red("Provide a collection name or --query filter."));
|
|
25665
25801
|
process.exit(1);
|
|
25666
25802
|
}
|
|
25667
25803
|
const { collection: col } = resolved;
|
|
@@ -25700,7 +25836,7 @@ import { spawn as spawn6 } from "child_process";
|
|
|
25700
25836
|
import * as path42 from "path";
|
|
25701
25837
|
|
|
25702
25838
|
// src/commands/refactor/logViolations.ts
|
|
25703
|
-
import
|
|
25839
|
+
import chalk190 from "chalk";
|
|
25704
25840
|
var DEFAULT_MAX_LINES2 = 100;
|
|
25705
25841
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
25706
25842
|
if (violations.length === 0) {
|
|
@@ -25709,43 +25845,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
|
25709
25845
|
}
|
|
25710
25846
|
return;
|
|
25711
25847
|
}
|
|
25712
|
-
console.error(
|
|
25848
|
+
console.error(chalk190.red(`
|
|
25713
25849
|
Refactor check failed:
|
|
25714
25850
|
`));
|
|
25715
|
-
console.error(
|
|
25851
|
+
console.error(chalk190.red(` The following files exceed ${maxLines} lines:
|
|
25716
25852
|
`));
|
|
25717
25853
|
for (const violation of violations) {
|
|
25718
|
-
console.error(
|
|
25854
|
+
console.error(chalk190.red(` ${violation.file} (${violation.lines} lines)`));
|
|
25719
25855
|
}
|
|
25720
25856
|
console.error(
|
|
25721
|
-
|
|
25857
|
+
chalk190.yellow(
|
|
25722
25858
|
`
|
|
25723
25859
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
25724
25860
|
way to refactor it, ignore it with:
|
|
25725
25861
|
`
|
|
25726
25862
|
)
|
|
25727
25863
|
);
|
|
25728
|
-
console.error(
|
|
25864
|
+
console.error(chalk190.gray(` assist refactor ignore <file>
|
|
25729
25865
|
`));
|
|
25730
25866
|
if (process.env.CLAUDECODE) {
|
|
25731
|
-
console.error(
|
|
25867
|
+
console.error(chalk190.cyan(`
|
|
25732
25868
|
## Extracting Code to New Files
|
|
25733
25869
|
`));
|
|
25734
25870
|
console.error(
|
|
25735
|
-
|
|
25871
|
+
chalk190.cyan(
|
|
25736
25872
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
25737
25873
|
`
|
|
25738
25874
|
)
|
|
25739
25875
|
);
|
|
25740
25876
|
console.error(
|
|
25741
|
-
|
|
25877
|
+
chalk190.cyan(
|
|
25742
25878
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
25743
25879
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
25744
25880
|
`
|
|
25745
25881
|
)
|
|
25746
25882
|
);
|
|
25747
25883
|
console.error(
|
|
25748
|
-
|
|
25884
|
+
chalk190.cyan(
|
|
25749
25885
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
25750
25886
|
domains, move it to a common/shared folder.
|
|
25751
25887
|
`
|
|
@@ -25901,7 +26037,7 @@ async function check(pattern2, options2) {
|
|
|
25901
26037
|
|
|
25902
26038
|
// src/commands/refactor/extract/index.ts
|
|
25903
26039
|
import path50 from "path";
|
|
25904
|
-
import
|
|
26040
|
+
import chalk193 from "chalk";
|
|
25905
26041
|
|
|
25906
26042
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
25907
26043
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -26500,23 +26636,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
26500
26636
|
|
|
26501
26637
|
// src/commands/refactor/extract/displayPlan.ts
|
|
26502
26638
|
import path46 from "path";
|
|
26503
|
-
import
|
|
26639
|
+
import chalk191 from "chalk";
|
|
26504
26640
|
function section2(title) {
|
|
26505
26641
|
return `
|
|
26506
|
-
${
|
|
26642
|
+
${chalk191.cyan(title)}`;
|
|
26507
26643
|
}
|
|
26508
26644
|
function displayImporters(plan2, cwd) {
|
|
26509
26645
|
if (plan2.importersToUpdate.length === 0) return;
|
|
26510
26646
|
console.log(section2("Update importers:"));
|
|
26511
26647
|
for (const imp of plan2.importersToUpdate) {
|
|
26512
26648
|
const rel = path46.relative(cwd, imp.file.getFilePath());
|
|
26513
|
-
console.log(` ${
|
|
26649
|
+
console.log(` ${chalk191.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
26514
26650
|
}
|
|
26515
26651
|
}
|
|
26516
26652
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
26517
|
-
console.log(
|
|
26653
|
+
console.log(chalk191.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
26518
26654
|
`));
|
|
26519
|
-
console.log(` ${
|
|
26655
|
+
console.log(` ${chalk191.cyan("Functions to move:")}`);
|
|
26520
26656
|
for (const name of plan2.extractedNames) {
|
|
26521
26657
|
console.log(` ${name}`);
|
|
26522
26658
|
}
|
|
@@ -26550,7 +26686,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
26550
26686
|
|
|
26551
26687
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
26552
26688
|
import path49 from "path";
|
|
26553
|
-
import
|
|
26689
|
+
import chalk192 from "chalk";
|
|
26554
26690
|
import { Project as Project4 } from "ts-morph";
|
|
26555
26691
|
|
|
26556
26692
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -26642,7 +26778,7 @@ function loadProjectFile(file) {
|
|
|
26642
26778
|
});
|
|
26643
26779
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
26644
26780
|
if (!sourceFile) {
|
|
26645
|
-
console.log(
|
|
26781
|
+
console.log(chalk192.red(`File not found in project: ${file}`));
|
|
26646
26782
|
process.exit(1);
|
|
26647
26783
|
}
|
|
26648
26784
|
return { project, sourceFile };
|
|
@@ -26665,19 +26801,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
26665
26801
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
26666
26802
|
if (options2.apply) {
|
|
26667
26803
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
26668
|
-
console.log(
|
|
26804
|
+
console.log(chalk193.green("\nExtraction complete"));
|
|
26669
26805
|
} else {
|
|
26670
|
-
console.log(
|
|
26806
|
+
console.log(chalk193.dim("\nDry run. Use --apply to execute."));
|
|
26671
26807
|
}
|
|
26672
26808
|
}
|
|
26673
26809
|
|
|
26674
26810
|
// src/commands/refactor/ignore.ts
|
|
26675
26811
|
import fs33 from "fs";
|
|
26676
|
-
import
|
|
26812
|
+
import chalk194 from "chalk";
|
|
26677
26813
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
26678
26814
|
function ignore2(file) {
|
|
26679
26815
|
if (!fs33.existsSync(file)) {
|
|
26680
|
-
console.error(
|
|
26816
|
+
console.error(chalk194.red(`Error: File does not exist: ${file}`));
|
|
26681
26817
|
process.exit(1);
|
|
26682
26818
|
}
|
|
26683
26819
|
const content = fs33.readFileSync(file, "utf8");
|
|
@@ -26693,7 +26829,7 @@ function ignore2(file) {
|
|
|
26693
26829
|
fs33.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
26694
26830
|
}
|
|
26695
26831
|
console.log(
|
|
26696
|
-
|
|
26832
|
+
chalk194.green(
|
|
26697
26833
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
26698
26834
|
)
|
|
26699
26835
|
);
|
|
@@ -26702,12 +26838,12 @@ function ignore2(file) {
|
|
|
26702
26838
|
// src/commands/refactor/rename/index.ts
|
|
26703
26839
|
import fs36 from "fs";
|
|
26704
26840
|
import path55 from "path";
|
|
26705
|
-
import
|
|
26841
|
+
import chalk197 from "chalk";
|
|
26706
26842
|
|
|
26707
26843
|
// src/commands/refactor/rename/applyRename.ts
|
|
26708
26844
|
import fs35 from "fs";
|
|
26709
26845
|
import path52 from "path";
|
|
26710
|
-
import
|
|
26846
|
+
import chalk195 from "chalk";
|
|
26711
26847
|
|
|
26712
26848
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
26713
26849
|
import path51 from "path";
|
|
@@ -26812,13 +26948,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
26812
26948
|
const updatedContents = applyRewrites(rewrites);
|
|
26813
26949
|
for (const [file, content] of updatedContents) {
|
|
26814
26950
|
fs35.writeFileSync(file, content, "utf8");
|
|
26815
|
-
console.log(
|
|
26951
|
+
console.log(chalk195.cyan(` Updated imports in ${path52.relative(cwd, file)}`));
|
|
26816
26952
|
}
|
|
26817
26953
|
const destDir = path52.dirname(destPath);
|
|
26818
26954
|
if (!fs35.existsSync(destDir)) fs35.mkdirSync(destDir, { recursive: true });
|
|
26819
26955
|
fs35.renameSync(sourcePath, destPath);
|
|
26820
26956
|
console.log(
|
|
26821
|
-
|
|
26957
|
+
chalk195.white(
|
|
26822
26958
|
` Moved ${path52.relative(cwd, sourcePath)} \u2192 ${path52.relative(cwd, destPath)}`
|
|
26823
26959
|
)
|
|
26824
26960
|
);
|
|
@@ -26905,16 +27041,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
26905
27041
|
|
|
26906
27042
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
26907
27043
|
import path54 from "path";
|
|
26908
|
-
import
|
|
27044
|
+
import chalk196 from "chalk";
|
|
26909
27045
|
function printRenamePreview(rewrites, cwd) {
|
|
26910
27046
|
for (const rewrite of rewrites) {
|
|
26911
27047
|
console.log(
|
|
26912
|
-
|
|
27048
|
+
chalk196.dim(
|
|
26913
27049
|
` ${path54.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
26914
27050
|
)
|
|
26915
27051
|
);
|
|
26916
27052
|
}
|
|
26917
|
-
console.log(
|
|
27053
|
+
console.log(chalk196.dim("Dry run. Use --apply to execute."));
|
|
26918
27054
|
}
|
|
26919
27055
|
|
|
26920
27056
|
// src/commands/refactor/rename/index.ts
|
|
@@ -26925,20 +27061,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26925
27061
|
const relSource = path55.relative(cwd, sourcePath);
|
|
26926
27062
|
const relDest = path55.relative(cwd, destPath);
|
|
26927
27063
|
if (!fs36.existsSync(sourcePath)) {
|
|
26928
|
-
console.log(
|
|
27064
|
+
console.log(chalk197.red(`File not found: ${source}`));
|
|
26929
27065
|
process.exit(1);
|
|
26930
27066
|
}
|
|
26931
27067
|
if (destPath !== sourcePath && fs36.existsSync(destPath)) {
|
|
26932
|
-
console.log(
|
|
27068
|
+
console.log(chalk197.red(`Destination already exists: ${destination}`));
|
|
26933
27069
|
process.exit(1);
|
|
26934
27070
|
}
|
|
26935
|
-
console.log(
|
|
26936
|
-
console.log(
|
|
26937
|
-
console.log(
|
|
27071
|
+
console.log(chalk197.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
27072
|
+
console.log(chalk197.dim("Loading project..."));
|
|
27073
|
+
console.log(chalk197.dim("Scanning imports across the project..."));
|
|
26938
27074
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
26939
27075
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
26940
27076
|
console.log(
|
|
26941
|
-
|
|
27077
|
+
chalk197.dim(
|
|
26942
27078
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
26943
27079
|
)
|
|
26944
27080
|
);
|
|
@@ -26947,11 +27083,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26947
27083
|
return;
|
|
26948
27084
|
}
|
|
26949
27085
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
26950
|
-
console.log(
|
|
27086
|
+
console.log(chalk197.green("Done"));
|
|
26951
27087
|
}
|
|
26952
27088
|
|
|
26953
27089
|
// src/commands/refactor/renameSymbol/index.ts
|
|
26954
|
-
import
|
|
27090
|
+
import chalk198 from "chalk";
|
|
26955
27091
|
|
|
26956
27092
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
26957
27093
|
import { SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
@@ -26997,33 +27133,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
26997
27133
|
const { project, sourceFile } = loadProjectFile(file);
|
|
26998
27134
|
const symbol = findSymbol(sourceFile, oldName);
|
|
26999
27135
|
if (!symbol) {
|
|
27000
|
-
console.log(
|
|
27136
|
+
console.log(chalk198.red(`Symbol "${oldName}" not found in ${file}`));
|
|
27001
27137
|
process.exit(1);
|
|
27002
27138
|
}
|
|
27003
27139
|
const grouped = groupReferences(symbol, cwd);
|
|
27004
27140
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
27005
27141
|
console.log(
|
|
27006
|
-
|
|
27142
|
+
chalk198.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
27007
27143
|
`)
|
|
27008
27144
|
);
|
|
27009
27145
|
for (const [refFile, lines2] of grouped) {
|
|
27010
27146
|
console.log(
|
|
27011
|
-
` ${
|
|
27147
|
+
` ${chalk198.dim(refFile)}: lines ${chalk198.cyan(lines2.join(", "))}`
|
|
27012
27148
|
);
|
|
27013
27149
|
}
|
|
27014
27150
|
if (options2.apply) {
|
|
27015
27151
|
symbol.rename(newName);
|
|
27016
27152
|
await project.save();
|
|
27017
|
-
console.log(
|
|
27153
|
+
console.log(chalk198.green(`
|
|
27018
27154
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
27019
27155
|
} else {
|
|
27020
|
-
console.log(
|
|
27156
|
+
console.log(chalk198.dim("\nDry run. Use --apply to execute."));
|
|
27021
27157
|
}
|
|
27022
27158
|
}
|
|
27023
27159
|
|
|
27024
27160
|
// src/commands/refactor/restructure/index.ts
|
|
27025
27161
|
import path63 from "path";
|
|
27026
|
-
import
|
|
27162
|
+
import chalk201 from "chalk";
|
|
27027
27163
|
|
|
27028
27164
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
27029
27165
|
import path57 from "path";
|
|
@@ -27102,50 +27238,50 @@ function clusterFiles(graph) {
|
|
|
27102
27238
|
|
|
27103
27239
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
27104
27240
|
import path59 from "path";
|
|
27105
|
-
import
|
|
27241
|
+
import chalk199 from "chalk";
|
|
27106
27242
|
function relPath(filePath) {
|
|
27107
27243
|
return path59.relative(process.cwd(), filePath);
|
|
27108
27244
|
}
|
|
27109
27245
|
function displayMoves(plan2) {
|
|
27110
27246
|
if (plan2.moves.length === 0) return;
|
|
27111
|
-
console.log(
|
|
27247
|
+
console.log(chalk199.bold("\nFile moves:"));
|
|
27112
27248
|
for (const move2 of plan2.moves) {
|
|
27113
27249
|
console.log(
|
|
27114
|
-
` ${
|
|
27250
|
+
` ${chalk199.red(relPath(move2.from))} \u2192 ${chalk199.green(relPath(move2.to))}`
|
|
27115
27251
|
);
|
|
27116
|
-
console.log(
|
|
27252
|
+
console.log(chalk199.dim(` ${move2.reason}`));
|
|
27117
27253
|
}
|
|
27118
27254
|
}
|
|
27119
27255
|
function displayRewrites(rewrites) {
|
|
27120
27256
|
if (rewrites.length === 0) return;
|
|
27121
27257
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
27122
|
-
console.log(
|
|
27258
|
+
console.log(chalk199.bold(`
|
|
27123
27259
|
Import rewrites (${affectedFiles.size} files):`));
|
|
27124
27260
|
for (const file of affectedFiles) {
|
|
27125
|
-
console.log(` ${
|
|
27261
|
+
console.log(` ${chalk199.cyan(relPath(file))}:`);
|
|
27126
27262
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
27127
27263
|
(r) => r.file === file
|
|
27128
27264
|
)) {
|
|
27129
27265
|
console.log(
|
|
27130
|
-
` ${
|
|
27266
|
+
` ${chalk199.red(`"${oldSpecifier}"`)} \u2192 ${chalk199.green(`"${newSpecifier}"`)}`
|
|
27131
27267
|
);
|
|
27132
27268
|
}
|
|
27133
27269
|
}
|
|
27134
27270
|
}
|
|
27135
27271
|
function displayPlan2(plan2) {
|
|
27136
27272
|
if (plan2.warnings.length > 0) {
|
|
27137
|
-
console.log(
|
|
27138
|
-
for (const w of plan2.warnings) console.log(
|
|
27273
|
+
console.log(chalk199.yellow("\nWarnings:"));
|
|
27274
|
+
for (const w of plan2.warnings) console.log(chalk199.yellow(` ${w}`));
|
|
27139
27275
|
}
|
|
27140
27276
|
if (plan2.newDirectories.length > 0) {
|
|
27141
|
-
console.log(
|
|
27277
|
+
console.log(chalk199.bold("\nNew directories:"));
|
|
27142
27278
|
for (const dir of plan2.newDirectories)
|
|
27143
|
-
console.log(
|
|
27279
|
+
console.log(chalk199.green(` ${dir}/`));
|
|
27144
27280
|
}
|
|
27145
27281
|
displayMoves(plan2);
|
|
27146
27282
|
displayRewrites(plan2.rewrites);
|
|
27147
27283
|
console.log(
|
|
27148
|
-
|
|
27284
|
+
chalk199.dim(
|
|
27149
27285
|
`
|
|
27150
27286
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
27151
27287
|
)
|
|
@@ -27155,18 +27291,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
27155
27291
|
// src/commands/refactor/restructure/executePlan.ts
|
|
27156
27292
|
import fs37 from "fs";
|
|
27157
27293
|
import path60 from "path";
|
|
27158
|
-
import
|
|
27294
|
+
import chalk200 from "chalk";
|
|
27159
27295
|
function executePlan(plan2) {
|
|
27160
27296
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
27161
27297
|
for (const [file, content] of updatedContents) {
|
|
27162
27298
|
fs37.writeFileSync(file, content, "utf8");
|
|
27163
27299
|
console.log(
|
|
27164
|
-
|
|
27300
|
+
chalk200.cyan(` Rewrote imports in ${path60.relative(process.cwd(), file)}`)
|
|
27165
27301
|
);
|
|
27166
27302
|
}
|
|
27167
27303
|
for (const dir of plan2.newDirectories) {
|
|
27168
27304
|
fs37.mkdirSync(dir, { recursive: true });
|
|
27169
|
-
console.log(
|
|
27305
|
+
console.log(chalk200.green(` Created ${path60.relative(process.cwd(), dir)}/`));
|
|
27170
27306
|
}
|
|
27171
27307
|
for (const move2 of plan2.moves) {
|
|
27172
27308
|
const targetDir = path60.dirname(move2.to);
|
|
@@ -27175,7 +27311,7 @@ function executePlan(plan2) {
|
|
|
27175
27311
|
}
|
|
27176
27312
|
fs37.renameSync(move2.from, move2.to);
|
|
27177
27313
|
console.log(
|
|
27178
|
-
|
|
27314
|
+
chalk200.white(
|
|
27179
27315
|
` Moved ${path60.relative(process.cwd(), move2.from)} \u2192 ${path60.relative(process.cwd(), move2.to)}`
|
|
27180
27316
|
)
|
|
27181
27317
|
);
|
|
@@ -27190,7 +27326,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
27190
27326
|
if (entries.length === 0) {
|
|
27191
27327
|
fs37.rmdirSync(dir);
|
|
27192
27328
|
console.log(
|
|
27193
|
-
|
|
27329
|
+
chalk200.dim(
|
|
27194
27330
|
` Removed empty directory ${path60.relative(process.cwd(), dir)}`
|
|
27195
27331
|
)
|
|
27196
27332
|
);
|
|
@@ -27323,22 +27459,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
27323
27459
|
const targetPattern = pattern2 ?? "src";
|
|
27324
27460
|
const files = findSourceFiles2(targetPattern);
|
|
27325
27461
|
if (files.length === 0) {
|
|
27326
|
-
console.log(
|
|
27462
|
+
console.log(chalk201.yellow("No files found matching pattern"));
|
|
27327
27463
|
return;
|
|
27328
27464
|
}
|
|
27329
27465
|
const tsConfigPath = findTsConfig(path63.resolve(files[0]));
|
|
27330
27466
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
27331
27467
|
if (plan2.moves.length === 0) {
|
|
27332
|
-
console.log(
|
|
27468
|
+
console.log(chalk201.green("No restructuring needed"));
|
|
27333
27469
|
return;
|
|
27334
27470
|
}
|
|
27335
27471
|
displayPlan2(plan2);
|
|
27336
27472
|
if (options2.apply) {
|
|
27337
|
-
console.log(
|
|
27473
|
+
console.log(chalk201.bold("\nApplying changes..."));
|
|
27338
27474
|
executePlan(plan2);
|
|
27339
|
-
console.log(
|
|
27475
|
+
console.log(chalk201.green("\nRestructuring complete"));
|
|
27340
27476
|
} else {
|
|
27341
|
-
console.log(
|
|
27477
|
+
console.log(chalk201.dim("\nDry run. Use --apply to execute."));
|
|
27342
27478
|
}
|
|
27343
27479
|
}
|
|
27344
27480
|
|
|
@@ -27865,15 +28001,15 @@ function runReviewSubmission(mutation, body) {
|
|
|
27865
28001
|
}
|
|
27866
28002
|
|
|
27867
28003
|
// src/commands/review/submitBodyOnlyReview.ts
|
|
27868
|
-
var
|
|
28004
|
+
var MUTATION3 = `mutation($prId: ID!, $body: String) { addPullRequestReview(input: { pullRequestId: $prId, event: COMMENT, body: $body }) { pullRequestReview { id } } }`;
|
|
27869
28005
|
function submitBodyOnlyReview(body) {
|
|
27870
|
-
runReviewSubmission(
|
|
28006
|
+
runReviewSubmission(MUTATION3, body);
|
|
27871
28007
|
}
|
|
27872
28008
|
|
|
27873
28009
|
// src/commands/review/submitPendingReview.ts
|
|
27874
|
-
var
|
|
28010
|
+
var MUTATION4 = `mutation($prId: ID!, $body: String) { submitPullRequestReview(input: { pullRequestId: $prId, event: COMMENT, body: $body }) { pullRequestReview { id } } }`;
|
|
27875
28011
|
function submitPendingReview(body) {
|
|
27876
|
-
runReviewSubmission(
|
|
28012
|
+
runReviewSubmission(MUTATION4, body);
|
|
27877
28013
|
}
|
|
27878
28014
|
|
|
27879
28015
|
// src/commands/review/postAndMaybeSubmit.ts
|
|
@@ -27996,18 +28132,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
27996
28132
|
}
|
|
27997
28133
|
|
|
27998
28134
|
// src/commands/review/warnOutOfDiff.ts
|
|
27999
|
-
import
|
|
28135
|
+
import chalk202 from "chalk";
|
|
28000
28136
|
function warnOutOfDiff(outOfDiff) {
|
|
28001
28137
|
if (outOfDiff.length === 0) return;
|
|
28002
28138
|
console.warn(
|
|
28003
|
-
|
|
28139
|
+
chalk202.yellow(
|
|
28004
28140
|
`Moved ${outOfDiff.length} finding(s) whose lines fall outside the PR diff into the review body (GitHub cannot anchor a comment on these):`
|
|
28005
28141
|
)
|
|
28006
28142
|
);
|
|
28007
28143
|
for (const finding of outOfDiff) {
|
|
28008
28144
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
28009
28145
|
console.warn(
|
|
28010
|
-
` ${
|
|
28146
|
+
` ${chalk202.yellow("\xB7")} ${finding.title} ${chalk202.dim(
|
|
28011
28147
|
`(${finding.file}:${range})`
|
|
28012
28148
|
)}`
|
|
28013
28149
|
);
|
|
@@ -28031,18 +28167,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
28031
28167
|
}
|
|
28032
28168
|
|
|
28033
28169
|
// src/commands/review/warnUnlocated.ts
|
|
28034
|
-
import
|
|
28170
|
+
import chalk203 from "chalk";
|
|
28035
28171
|
function warnUnlocated(unlocated) {
|
|
28036
28172
|
if (unlocated.length === 0) return;
|
|
28037
28173
|
console.warn(
|
|
28038
|
-
|
|
28174
|
+
chalk203.yellow(
|
|
28039
28175
|
`Moved ${unlocated.length} finding(s) without a parseable file:line into the review body:`
|
|
28040
28176
|
)
|
|
28041
28177
|
);
|
|
28042
28178
|
for (const finding of unlocated) {
|
|
28043
|
-
const where = finding.location ||
|
|
28179
|
+
const where = finding.location || chalk203.dim("missing");
|
|
28044
28180
|
console.warn(
|
|
28045
|
-
` ${
|
|
28181
|
+
` ${chalk203.yellow("\xB7")} ${finding.title} ${chalk203.dim(`(${where})`)}`
|
|
28046
28182
|
);
|
|
28047
28183
|
}
|
|
28048
28184
|
}
|
|
@@ -29297,7 +29433,7 @@ function registerReview(program2) {
|
|
|
29297
29433
|
}
|
|
29298
29434
|
|
|
29299
29435
|
// src/commands/seq/seqAuth.ts
|
|
29300
|
-
import
|
|
29436
|
+
import chalk205 from "chalk";
|
|
29301
29437
|
|
|
29302
29438
|
// src/commands/seq/loadConnections.ts
|
|
29303
29439
|
function loadConnections2() {
|
|
@@ -29326,10 +29462,10 @@ function setDefaultConnection(name) {
|
|
|
29326
29462
|
}
|
|
29327
29463
|
|
|
29328
29464
|
// src/shared/assertUniqueName.ts
|
|
29329
|
-
import
|
|
29465
|
+
import chalk204 from "chalk";
|
|
29330
29466
|
function assertUniqueName(existingNames, name) {
|
|
29331
29467
|
if (existingNames.includes(name)) {
|
|
29332
|
-
console.error(
|
|
29468
|
+
console.error(chalk204.red(`Connection "${name}" already exists.`));
|
|
29333
29469
|
process.exit(1);
|
|
29334
29470
|
}
|
|
29335
29471
|
}
|
|
@@ -29347,16 +29483,16 @@ async function promptConnection2(existingNames) {
|
|
|
29347
29483
|
var seqAuth = createConnectionAuth({
|
|
29348
29484
|
load: loadConnections2,
|
|
29349
29485
|
save: saveConnections2,
|
|
29350
|
-
format: (c) => `${
|
|
29486
|
+
format: (c) => `${chalk205.bold(c.name)} ${c.url}`,
|
|
29351
29487
|
promptNew: promptConnection2,
|
|
29352
29488
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
29353
29489
|
});
|
|
29354
29490
|
|
|
29355
29491
|
// src/commands/seq/seqQuery.ts
|
|
29356
|
-
import
|
|
29492
|
+
import chalk209 from "chalk";
|
|
29357
29493
|
|
|
29358
29494
|
// src/commands/seq/fetchSeq.ts
|
|
29359
|
-
import
|
|
29495
|
+
import chalk206 from "chalk";
|
|
29360
29496
|
async function fetchSeq(conn, path80, params) {
|
|
29361
29497
|
const url = `${conn.url}${path80}?${params}`;
|
|
29362
29498
|
const response = await fetch(url, {
|
|
@@ -29367,7 +29503,7 @@ async function fetchSeq(conn, path80, params) {
|
|
|
29367
29503
|
});
|
|
29368
29504
|
if (!response.ok) {
|
|
29369
29505
|
const body = await response.text();
|
|
29370
|
-
console.error(
|
|
29506
|
+
console.error(chalk206.red(`Seq returned ${response.status}: ${body}`));
|
|
29371
29507
|
process.exit(1);
|
|
29372
29508
|
}
|
|
29373
29509
|
return response;
|
|
@@ -29426,23 +29562,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
29426
29562
|
}
|
|
29427
29563
|
|
|
29428
29564
|
// src/commands/seq/formatEvent.ts
|
|
29429
|
-
import
|
|
29565
|
+
import chalk207 from "chalk";
|
|
29430
29566
|
function levelColor(level) {
|
|
29431
29567
|
switch (level) {
|
|
29432
29568
|
case "Fatal":
|
|
29433
|
-
return
|
|
29569
|
+
return chalk207.bgRed.white;
|
|
29434
29570
|
case "Error":
|
|
29435
|
-
return
|
|
29571
|
+
return chalk207.red;
|
|
29436
29572
|
case "Warning":
|
|
29437
|
-
return
|
|
29573
|
+
return chalk207.yellow;
|
|
29438
29574
|
case "Information":
|
|
29439
|
-
return
|
|
29575
|
+
return chalk207.cyan;
|
|
29440
29576
|
case "Debug":
|
|
29441
|
-
return
|
|
29577
|
+
return chalk207.gray;
|
|
29442
29578
|
case "Verbose":
|
|
29443
|
-
return
|
|
29579
|
+
return chalk207.dim;
|
|
29444
29580
|
default:
|
|
29445
|
-
return
|
|
29581
|
+
return chalk207.white;
|
|
29446
29582
|
}
|
|
29447
29583
|
}
|
|
29448
29584
|
function levelAbbrev(level) {
|
|
@@ -29483,12 +29619,12 @@ function formatTimestamp(iso) {
|
|
|
29483
29619
|
function formatEvent(event) {
|
|
29484
29620
|
const color = levelColor(event.Level);
|
|
29485
29621
|
const abbrev = levelAbbrev(event.Level);
|
|
29486
|
-
const ts8 =
|
|
29622
|
+
const ts8 = chalk207.dim(formatTimestamp(event.Timestamp));
|
|
29487
29623
|
const msg = renderMessage(event);
|
|
29488
29624
|
const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
29489
29625
|
if (event.Exception) {
|
|
29490
29626
|
for (const line of event.Exception.split("\n")) {
|
|
29491
|
-
lines2.push(
|
|
29627
|
+
lines2.push(chalk207.red(` ${line}`));
|
|
29492
29628
|
}
|
|
29493
29629
|
}
|
|
29494
29630
|
return lines2.join("\n");
|
|
@@ -29521,11 +29657,11 @@ function rejectTimestampFilter(filter) {
|
|
|
29521
29657
|
}
|
|
29522
29658
|
|
|
29523
29659
|
// src/shared/resolveNamedConnection.ts
|
|
29524
|
-
import
|
|
29660
|
+
import chalk208 from "chalk";
|
|
29525
29661
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
29526
29662
|
if (connections.length === 0) {
|
|
29527
29663
|
console.error(
|
|
29528
|
-
|
|
29664
|
+
chalk208.red(
|
|
29529
29665
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
29530
29666
|
)
|
|
29531
29667
|
);
|
|
@@ -29534,7 +29670,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
29534
29670
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
29535
29671
|
const connection = connections.find((c) => c.name === target);
|
|
29536
29672
|
if (!connection) {
|
|
29537
|
-
console.error(
|
|
29673
|
+
console.error(chalk208.red(`${kind} connection "${target}" not found.`));
|
|
29538
29674
|
process.exit(1);
|
|
29539
29675
|
}
|
|
29540
29676
|
return connection;
|
|
@@ -29563,7 +29699,7 @@ async function seqQuery(filter, options2) {
|
|
|
29563
29699
|
new URLSearchParams({ filter, count: String(count8) })
|
|
29564
29700
|
);
|
|
29565
29701
|
if (events.length === 0) {
|
|
29566
|
-
console.log(
|
|
29702
|
+
console.log(chalk209.yellow("No events found."));
|
|
29567
29703
|
return;
|
|
29568
29704
|
}
|
|
29569
29705
|
if (options2.json) {
|
|
@@ -29574,11 +29710,11 @@ async function seqQuery(filter, options2) {
|
|
|
29574
29710
|
for (const event of chronological) {
|
|
29575
29711
|
console.log(formatEvent(event));
|
|
29576
29712
|
}
|
|
29577
|
-
console.log(
|
|
29713
|
+
console.log(chalk209.dim(`
|
|
29578
29714
|
${events.length} events`));
|
|
29579
29715
|
if (events.length >= count8) {
|
|
29580
29716
|
console.log(
|
|
29581
|
-
|
|
29717
|
+
chalk209.yellow(
|
|
29582
29718
|
`Results limited to ${count8}. Use --count to retrieve more.`
|
|
29583
29719
|
)
|
|
29584
29720
|
);
|
|
@@ -29586,10 +29722,10 @@ ${events.length} events`));
|
|
|
29586
29722
|
}
|
|
29587
29723
|
|
|
29588
29724
|
// src/shared/setNamedDefaultConnection.ts
|
|
29589
|
-
import
|
|
29725
|
+
import chalk210 from "chalk";
|
|
29590
29726
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
29591
29727
|
if (!connections.find((c) => c.name === name)) {
|
|
29592
|
-
console.error(
|
|
29728
|
+
console.error(chalk210.red(`Connection "${name}" not found.`));
|
|
29593
29729
|
process.exit(1);
|
|
29594
29730
|
}
|
|
29595
29731
|
setDefault(name);
|
|
@@ -29638,7 +29774,7 @@ function registerSignal(program2) {
|
|
|
29638
29774
|
}
|
|
29639
29775
|
|
|
29640
29776
|
// src/commands/sql/sqlAuth.ts
|
|
29641
|
-
import
|
|
29777
|
+
import chalk212 from "chalk";
|
|
29642
29778
|
|
|
29643
29779
|
// src/commands/sql/loadConnections.ts
|
|
29644
29780
|
function loadConnections3() {
|
|
@@ -29667,7 +29803,7 @@ function setDefaultConnection2(name) {
|
|
|
29667
29803
|
}
|
|
29668
29804
|
|
|
29669
29805
|
// src/commands/sql/promptConnection.ts
|
|
29670
|
-
import
|
|
29806
|
+
import chalk211 from "chalk";
|
|
29671
29807
|
async function promptConnection3(existingNames) {
|
|
29672
29808
|
const name = await promptInput("name", "Connection name:", "default");
|
|
29673
29809
|
assertUniqueName(existingNames, name);
|
|
@@ -29675,7 +29811,7 @@ async function promptConnection3(existingNames) {
|
|
|
29675
29811
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
29676
29812
|
const port = Number.parseInt(portStr, 10);
|
|
29677
29813
|
if (!Number.isFinite(port)) {
|
|
29678
|
-
console.error(
|
|
29814
|
+
console.error(chalk211.red(`Invalid port "${portStr}".`));
|
|
29679
29815
|
process.exit(1);
|
|
29680
29816
|
}
|
|
29681
29817
|
const user = await promptInput("user", "User:");
|
|
@@ -29688,13 +29824,13 @@ async function promptConnection3(existingNames) {
|
|
|
29688
29824
|
var sqlAuth = createConnectionAuth({
|
|
29689
29825
|
load: loadConnections3,
|
|
29690
29826
|
save: saveConnections3,
|
|
29691
|
-
format: (c) => `${
|
|
29827
|
+
format: (c) => `${chalk212.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
29692
29828
|
promptNew: promptConnection3,
|
|
29693
29829
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
29694
29830
|
});
|
|
29695
29831
|
|
|
29696
29832
|
// src/commands/sql/printTable.ts
|
|
29697
|
-
import
|
|
29833
|
+
import chalk213 from "chalk";
|
|
29698
29834
|
function formatCell(value) {
|
|
29699
29835
|
if (value === null || value === void 0) return "";
|
|
29700
29836
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -29703,7 +29839,7 @@ function formatCell(value) {
|
|
|
29703
29839
|
}
|
|
29704
29840
|
function printTable(rows) {
|
|
29705
29841
|
if (rows.length === 0) {
|
|
29706
|
-
console.log(
|
|
29842
|
+
console.log(chalk213.yellow("(no rows)"));
|
|
29707
29843
|
return;
|
|
29708
29844
|
}
|
|
29709
29845
|
const columns = Object.keys(rows[0]);
|
|
@@ -29711,13 +29847,13 @@ function printTable(rows) {
|
|
|
29711
29847
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
29712
29848
|
);
|
|
29713
29849
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
29714
|
-
console.log(
|
|
29715
|
-
console.log(
|
|
29850
|
+
console.log(chalk213.dim(header));
|
|
29851
|
+
console.log(chalk213.dim("-".repeat(header.length)));
|
|
29716
29852
|
for (const row of rows) {
|
|
29717
29853
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
29718
29854
|
console.log(line);
|
|
29719
29855
|
}
|
|
29720
|
-
console.log(
|
|
29856
|
+
console.log(chalk213.dim(`
|
|
29721
29857
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
29722
29858
|
}
|
|
29723
29859
|
|
|
@@ -29777,7 +29913,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
29777
29913
|
}
|
|
29778
29914
|
|
|
29779
29915
|
// src/commands/sql/sqlMutate.ts
|
|
29780
|
-
import
|
|
29916
|
+
import chalk214 from "chalk";
|
|
29781
29917
|
|
|
29782
29918
|
// src/commands/sql/isMutation.ts
|
|
29783
29919
|
var MUTATION_KEYWORDS = [
|
|
@@ -29811,7 +29947,7 @@ function isMutation(sql25) {
|
|
|
29811
29947
|
async function sqlMutate(query, connectionName) {
|
|
29812
29948
|
if (!isMutation(query)) {
|
|
29813
29949
|
console.error(
|
|
29814
|
-
|
|
29950
|
+
chalk214.red(
|
|
29815
29951
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
29816
29952
|
)
|
|
29817
29953
|
);
|
|
@@ -29821,18 +29957,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
29821
29957
|
const pool = await sqlConnect(conn);
|
|
29822
29958
|
try {
|
|
29823
29959
|
const result = await pool.request().query(query);
|
|
29824
|
-
console.log(
|
|
29960
|
+
console.log(chalk214.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
29825
29961
|
} finally {
|
|
29826
29962
|
await pool.close();
|
|
29827
29963
|
}
|
|
29828
29964
|
}
|
|
29829
29965
|
|
|
29830
29966
|
// src/commands/sql/sqlQuery.ts
|
|
29831
|
-
import
|
|
29967
|
+
import chalk215 from "chalk";
|
|
29832
29968
|
async function sqlQuery(query, connectionName) {
|
|
29833
29969
|
if (isMutation(query)) {
|
|
29834
29970
|
console.error(
|
|
29835
|
-
|
|
29971
|
+
chalk215.red(
|
|
29836
29972
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
29837
29973
|
)
|
|
29838
29974
|
);
|
|
@@ -29847,7 +29983,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
29847
29983
|
printTable(rows);
|
|
29848
29984
|
} else {
|
|
29849
29985
|
console.log(
|
|
29850
|
-
|
|
29986
|
+
chalk215.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
29851
29987
|
);
|
|
29852
29988
|
}
|
|
29853
29989
|
} finally {
|
|
@@ -29992,7 +30128,7 @@ function reportPrune(label2, result, force) {
|
|
|
29992
30128
|
// src/commands/sync/syncClaudeMd.ts
|
|
29993
30129
|
import * as fs41 from "fs";
|
|
29994
30130
|
import * as path66 from "path";
|
|
29995
|
-
import
|
|
30131
|
+
import chalk216 from "chalk";
|
|
29996
30132
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
29997
30133
|
const source = path66.join(claudeDir, "CLAUDE.md");
|
|
29998
30134
|
const target = path66.join(targetBase, "CLAUDE.md");
|
|
@@ -30001,14 +30137,14 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
30001
30137
|
const targetContent = fs41.readFileSync(target, "utf8");
|
|
30002
30138
|
if (sourceContent !== targetContent) {
|
|
30003
30139
|
console.log(
|
|
30004
|
-
|
|
30140
|
+
chalk216.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
30005
30141
|
);
|
|
30006
30142
|
console.log();
|
|
30007
30143
|
printDiff(targetContent, sourceContent);
|
|
30008
30144
|
if (!options2?.yes) {
|
|
30009
30145
|
printAutoConfirmHint();
|
|
30010
30146
|
const confirm = await promptConfirm(
|
|
30011
|
-
|
|
30147
|
+
chalk216.red("Overwrite existing CLAUDE.md?"),
|
|
30012
30148
|
false
|
|
30013
30149
|
);
|
|
30014
30150
|
if (!confirm) {
|
|
@@ -30241,7 +30377,7 @@ function syncPi(claudeDir, options2) {
|
|
|
30241
30377
|
// src/commands/sync/syncSettings.ts
|
|
30242
30378
|
import * as fs47 from "fs";
|
|
30243
30379
|
import * as path73 from "path";
|
|
30244
|
-
import
|
|
30380
|
+
import chalk217 from "chalk";
|
|
30245
30381
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
30246
30382
|
const source = path73.join(claudeDir, "settings.json");
|
|
30247
30383
|
const target = path73.join(targetBase, "settings.json");
|
|
@@ -30260,7 +30396,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
30260
30396
|
if (mergedContent !== normalizedTarget) {
|
|
30261
30397
|
if (!options2?.yes) {
|
|
30262
30398
|
console.log(
|
|
30263
|
-
|
|
30399
|
+
chalk217.yellow(
|
|
30264
30400
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
30265
30401
|
)
|
|
30266
30402
|
);
|
|
@@ -30268,7 +30404,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
30268
30404
|
printDiff(targetContent, mergedContent);
|
|
30269
30405
|
printAutoConfirmHint();
|
|
30270
30406
|
const confirm = await promptConfirm(
|
|
30271
|
-
|
|
30407
|
+
chalk217.red("Overwrite existing settings.json?"),
|
|
30272
30408
|
false
|
|
30273
30409
|
);
|
|
30274
30410
|
if (!confirm) {
|
|
@@ -31695,7 +31831,7 @@ function registerWatch(program2) {
|
|
|
31695
31831
|
|
|
31696
31832
|
// src/commands/roam/auth.ts
|
|
31697
31833
|
import { randomBytes } from "crypto";
|
|
31698
|
-
import
|
|
31834
|
+
import chalk218 from "chalk";
|
|
31699
31835
|
|
|
31700
31836
|
// src/commands/roam/waitForCallback.ts
|
|
31701
31837
|
import { createServer as createServer3 } from "http";
|
|
@@ -31826,13 +31962,13 @@ async function auth() {
|
|
|
31826
31962
|
saveGlobalConfig(config);
|
|
31827
31963
|
const state = randomBytes(16).toString("hex");
|
|
31828
31964
|
console.log(
|
|
31829
|
-
|
|
31965
|
+
chalk218.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
31830
31966
|
);
|
|
31831
|
-
console.log(
|
|
31832
|
-
console.log(
|
|
31833
|
-
console.log(
|
|
31967
|
+
console.log(chalk218.white("http://localhost:14523/callback\n"));
|
|
31968
|
+
console.log(chalk218.blue("Opening browser for authorization..."));
|
|
31969
|
+
console.log(chalk218.dim("Waiting for authorization callback..."));
|
|
31834
31970
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
31835
|
-
console.log(
|
|
31971
|
+
console.log(chalk218.dim("Exchanging code for tokens..."));
|
|
31836
31972
|
const tokens = await exchangeToken({
|
|
31837
31973
|
code,
|
|
31838
31974
|
clientId,
|
|
@@ -31848,7 +31984,7 @@ async function auth() {
|
|
|
31848
31984
|
};
|
|
31849
31985
|
saveGlobalConfig(config);
|
|
31850
31986
|
console.log(
|
|
31851
|
-
|
|
31987
|
+
chalk218.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
31852
31988
|
);
|
|
31853
31989
|
}
|
|
31854
31990
|
|
|
@@ -32199,7 +32335,7 @@ import { execSync as execSync60 } from "child_process";
|
|
|
32199
32335
|
import { existsSync as existsSync72, mkdirSync as mkdirSync31, unlinkSync as unlinkSync22, writeFileSync as writeFileSync46 } from "fs";
|
|
32200
32336
|
import { tmpdir as tmpdir8 } from "os";
|
|
32201
32337
|
import { join as join89, resolve as resolve20 } from "path";
|
|
32202
|
-
import
|
|
32338
|
+
import chalk219 from "chalk";
|
|
32203
32339
|
|
|
32204
32340
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
32205
32341
|
var captureWindowPs1 = `
|
|
@@ -32350,13 +32486,13 @@ function screenshot(processName) {
|
|
|
32350
32486
|
const config = loadConfig();
|
|
32351
32487
|
const outputDir = resolve20(config.screenshot.outputDir);
|
|
32352
32488
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
32353
|
-
console.log(
|
|
32489
|
+
console.log(chalk219.gray(`Capturing window for process "${processName}" ...`));
|
|
32354
32490
|
try {
|
|
32355
32491
|
runPowerShellScript(processName, outputPath);
|
|
32356
|
-
console.log(
|
|
32492
|
+
console.log(chalk219.green(`Screenshot saved: ${outputPath}`));
|
|
32357
32493
|
} catch (error) {
|
|
32358
32494
|
const msg = error instanceof Error ? error.message : String(error);
|
|
32359
|
-
console.error(
|
|
32495
|
+
console.error(chalk219.red(`Failed to capture screenshot: ${msg}`));
|
|
32360
32496
|
process.exit(1);
|
|
32361
32497
|
}
|
|
32362
32498
|
}
|
|
@@ -38133,7 +38269,7 @@ function registerSetStatusCommand(cmd) {
|
|
|
38133
38269
|
|
|
38134
38270
|
// src/commands/sessions/summarise/index.ts
|
|
38135
38271
|
import * as fs56 from "fs";
|
|
38136
|
-
import
|
|
38272
|
+
import chalk220 from "chalk";
|
|
38137
38273
|
|
|
38138
38274
|
// src/commands/sessions/summarise/shared.ts
|
|
38139
38275
|
import * as fs55 from "fs";
|
|
@@ -38192,22 +38328,22 @@ ${firstMessage}`);
|
|
|
38192
38328
|
async function summarise2(options2) {
|
|
38193
38329
|
const files = await discoverSessionFiles();
|
|
38194
38330
|
if (files.length === 0) {
|
|
38195
|
-
console.log(
|
|
38331
|
+
console.log(chalk220.yellow("No sessions found."));
|
|
38196
38332
|
return;
|
|
38197
38333
|
}
|
|
38198
38334
|
const toProcess = selectCandidates(files, options2);
|
|
38199
38335
|
if (toProcess.length === 0) {
|
|
38200
|
-
console.log(
|
|
38336
|
+
console.log(chalk220.green("All sessions already summarised."));
|
|
38201
38337
|
return;
|
|
38202
38338
|
}
|
|
38203
38339
|
console.log(
|
|
38204
|
-
|
|
38340
|
+
chalk220.cyan(
|
|
38205
38341
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
38206
38342
|
)
|
|
38207
38343
|
);
|
|
38208
38344
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
38209
38345
|
console.log(
|
|
38210
|
-
|
|
38346
|
+
chalk220.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk220.yellow(`, ${failed2} skipped`) : "")
|
|
38211
38347
|
);
|
|
38212
38348
|
}
|
|
38213
38349
|
function selectCandidates(files, options2) {
|
|
@@ -38227,16 +38363,16 @@ function processSessions(files) {
|
|
|
38227
38363
|
let failed2 = 0;
|
|
38228
38364
|
for (let i = 0; i < files.length; i++) {
|
|
38229
38365
|
const file = files[i];
|
|
38230
|
-
process.stdout.write(
|
|
38366
|
+
process.stdout.write(chalk220.dim(` [${i + 1}/${files.length}] `));
|
|
38231
38367
|
const summary = summariseSession(file);
|
|
38232
38368
|
if (summary) {
|
|
38233
38369
|
writeSummary(file, summary);
|
|
38234
38370
|
succeeded++;
|
|
38235
|
-
process.stdout.write(`${
|
|
38371
|
+
process.stdout.write(`${chalk220.green("\u2713")} ${summary}
|
|
38236
38372
|
`);
|
|
38237
38373
|
} else {
|
|
38238
38374
|
failed2++;
|
|
38239
|
-
process.stdout.write(` ${
|
|
38375
|
+
process.stdout.write(` ${chalk220.yellow("skip")}
|
|
38240
38376
|
`);
|
|
38241
38377
|
}
|
|
38242
38378
|
}
|
|
@@ -38257,7 +38393,7 @@ function registerSessions(program2) {
|
|
|
38257
38393
|
}
|
|
38258
38394
|
|
|
38259
38395
|
// src/commands/statusLine.ts
|
|
38260
|
-
import
|
|
38396
|
+
import chalk222 from "chalk";
|
|
38261
38397
|
|
|
38262
38398
|
// src/shared/contextLevel.ts
|
|
38263
38399
|
function contextLevel(pct) {
|
|
@@ -38267,7 +38403,7 @@ function contextLevel(pct) {
|
|
|
38267
38403
|
}
|
|
38268
38404
|
|
|
38269
38405
|
// src/commands/buildLimitsSegment.ts
|
|
38270
|
-
import
|
|
38406
|
+
import chalk221 from "chalk";
|
|
38271
38407
|
|
|
38272
38408
|
// src/shared/rateLimitLevel.ts
|
|
38273
38409
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -38305,9 +38441,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
38305
38441
|
|
|
38306
38442
|
// src/commands/buildLimitsSegment.ts
|
|
38307
38443
|
var LEVEL_COLOR = {
|
|
38308
|
-
ok:
|
|
38309
|
-
warn:
|
|
38310
|
-
over:
|
|
38444
|
+
ok: chalk221.green,
|
|
38445
|
+
warn: chalk221.yellow,
|
|
38446
|
+
over: chalk221.red
|
|
38311
38447
|
};
|
|
38312
38448
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
38313
38449
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -38403,7 +38539,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
|
|
|
38403
38539
|
}
|
|
38404
38540
|
|
|
38405
38541
|
// src/commands/statusLine.ts
|
|
38406
|
-
|
|
38542
|
+
chalk222.level = 3;
|
|
38407
38543
|
function formatNumber(num) {
|
|
38408
38544
|
return num.toLocaleString("en-US");
|
|
38409
38545
|
}
|
|
@@ -38411,9 +38547,9 @@ function colorizePercent(pct) {
|
|
|
38411
38547
|
const label2 = `${Math.round(pct)}%`;
|
|
38412
38548
|
switch (contextLevel(pct)) {
|
|
38413
38549
|
case "red":
|
|
38414
|
-
return
|
|
38550
|
+
return chalk222.red(label2);
|
|
38415
38551
|
case "yellow":
|
|
38416
|
-
return
|
|
38552
|
+
return chalk222.yellow(label2);
|
|
38417
38553
|
default:
|
|
38418
38554
|
return label2;
|
|
38419
38555
|
}
|
|
@@ -38426,7 +38562,7 @@ async function statusLine() {
|
|
|
38426
38562
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
38427
38563
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
38428
38564
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
38429
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
38565
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk222.cyan(branch2)} | ` : "";
|
|
38430
38566
|
console.log(
|
|
38431
38567
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
38432
38568
|
);
|
|
@@ -38496,10 +38632,10 @@ async function update2() {
|
|
|
38496
38632
|
}
|
|
38497
38633
|
|
|
38498
38634
|
// src/reportCliError.ts
|
|
38499
|
-
import
|
|
38635
|
+
import chalk223 from "chalk";
|
|
38500
38636
|
function reportCliError(error) {
|
|
38501
38637
|
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError || error instanceof MiroExtractError) {
|
|
38502
|
-
console.error(
|
|
38638
|
+
console.error(chalk223.red(error.message));
|
|
38503
38639
|
} else {
|
|
38504
38640
|
console.error(error);
|
|
38505
38641
|
}
|