@staff0rd/assist 0.577.0 → 0.579.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/commands/sessions/web/bundle.js +395 -395
- package/dist/index.js +885 -697
- 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.579.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -13973,6 +13973,12 @@ ${quoted}
|
|
|
13973
13973
|
}
|
|
13974
13974
|
|
|
13975
13975
|
// src/commands/sessions/shared/toPreviewDecision.ts
|
|
13976
|
+
function toSelection(value) {
|
|
13977
|
+
const selection = value;
|
|
13978
|
+
if (typeof selection?.topLeft !== "string" || typeof selection.bottomRight !== "string")
|
|
13979
|
+
return void 0;
|
|
13980
|
+
return { topLeft: selection.topLeft, bottomRight: selection.bottomRight };
|
|
13981
|
+
}
|
|
13976
13982
|
function toPreviewDecision(msg) {
|
|
13977
13983
|
if (msg.decision !== "approve" && msg.decision !== "reject") return null;
|
|
13978
13984
|
return {
|
|
@@ -13983,7 +13989,8 @@ function toPreviewDecision(msg) {
|
|
|
13983
13989
|
body: typeof msg.body === "string" ? msg.body : void 0,
|
|
13984
13990
|
reviewAfter: msg.reviewAfter === true,
|
|
13985
13991
|
announceAfter: msg.announceAfter === true,
|
|
13986
|
-
draft: typeof msg.draft === "boolean" ? msg.draft : void 0
|
|
13992
|
+
draft: typeof msg.draft === "boolean" ? msg.draft : void 0,
|
|
13993
|
+
selection: toSelection(msg.selection)
|
|
13987
13994
|
};
|
|
13988
13995
|
}
|
|
13989
13996
|
|
|
@@ -16820,6 +16827,12 @@ function findBuiltinDenyRaw(rawCommand) {
|
|
|
16820
16827
|
// src/shared/isApprovedRead.ts
|
|
16821
16828
|
import { resolve as resolve13, sep } from "path";
|
|
16822
16829
|
|
|
16830
|
+
// src/shared/appliesFixStructure.ts
|
|
16831
|
+
var APPLY_RE = /^assist\s+github\s+issue\s+fix-structure\b.*\s--apply\b/;
|
|
16832
|
+
function appliesFixStructure(command) {
|
|
16833
|
+
return APPLY_RE.test(command);
|
|
16834
|
+
}
|
|
16835
|
+
|
|
16823
16836
|
// src/shared/tokenize.ts
|
|
16824
16837
|
function tokenize(command) {
|
|
16825
16838
|
const tokens = [];
|
|
@@ -17046,6 +17059,7 @@ function isApprovedRead(command, toolName = "Bash") {
|
|
|
17046
17059
|
if (isCdToCwd(command)) return "cd to current directory";
|
|
17047
17060
|
const cdRead = isCdToReadAllowedDir(command);
|
|
17048
17061
|
if (cdRead) return cdRead;
|
|
17062
|
+
if (appliesFixStructure(command)) return void 0;
|
|
17049
17063
|
const matchedRead = findCliRead(command);
|
|
17050
17064
|
if (matchedRead) return `Read-only CLI command: ${matchedRead}`;
|
|
17051
17065
|
const matchedWrite = findCliWrite(command);
|
|
@@ -20695,309 +20709,178 @@ function parseTopCount(value) {
|
|
|
20695
20709
|
return Number.parseInt(value, 10);
|
|
20696
20710
|
}
|
|
20697
20711
|
|
|
20698
|
-
// src/commands/github/issue/
|
|
20699
|
-
import
|
|
20712
|
+
// src/commands/github/issue/fixStructure/applyAndVerifySubtree.ts
|
|
20713
|
+
import chalk163 from "chalk";
|
|
20700
20714
|
|
|
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
|
-
}
|
|
20715
|
+
// src/commands/github/issue/fixStructure/applyFixStructurePlan.ts
|
|
20716
|
+
import chalk162 from "chalk";
|
|
20725
20717
|
|
|
20726
|
-
// src/
|
|
20727
|
-
import {
|
|
20728
|
-
|
|
20729
|
-
const
|
|
20730
|
-
|
|
20731
|
-
|
|
20732
|
-
|
|
20733
|
-
|
|
20734
|
-
title,
|
|
20735
|
-
body,
|
|
20736
|
-
prNumber: null,
|
|
20737
|
-
kind: "github-issue-comment"
|
|
20718
|
+
// src/shared/runGhGraphqlJson.ts
|
|
20719
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
20720
|
+
function runGhGraphqlJson(query, vars = {}) {
|
|
20721
|
+
const result = spawnSync5("gh", ["api", "graphql", "--input", "-"], {
|
|
20722
|
+
encoding: "utf8",
|
|
20723
|
+
windowsHide: true,
|
|
20724
|
+
input: JSON.stringify({ query, variables: vars }),
|
|
20725
|
+
maxBuffer: 64 * 1024 * 1024
|
|
20738
20726
|
});
|
|
20727
|
+
if (result.status !== 0) throw new Error(result.stderr || result.stdout);
|
|
20728
|
+
throwOnGraphqlErrors(result.stdout);
|
|
20729
|
+
return result.stdout;
|
|
20739
20730
|
}
|
|
20740
20731
|
|
|
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}`);
|
|
20732
|
+
// src/commands/github/issue/fixStructure/removeIssueLabels.ts
|
|
20733
|
+
var MUTATION = `mutation($labelableId: ID!, $labelIds: [ID!]!) {
|
|
20734
|
+
removeLabelsFromLabelable(input: { labelableId: $labelableId, labelIds: $labelIds }) {
|
|
20735
|
+
labelable { __typename }
|
|
20736
|
+
}
|
|
20737
|
+
}`;
|
|
20738
|
+
function removeIssueLabels(issueId, labelIds) {
|
|
20739
|
+
runGhGraphqlJson(MUTATION, { labelableId: issueId, labelIds });
|
|
20765
20740
|
}
|
|
20766
20741
|
|
|
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
|
-
});
|
|
20742
|
+
// src/commands/github/issue/fixStructure/updateIssueType.ts
|
|
20743
|
+
var MUTATION2 = `mutation($issueId: ID!, $issueTypeId: ID!) {
|
|
20744
|
+
updateIssueIssueType(input: { issueId: $issueId, issueTypeId: $issueTypeId }) {
|
|
20745
|
+
issue { id }
|
|
20746
|
+
}
|
|
20747
|
+
}`;
|
|
20748
|
+
function updateIssueType(issueId, issueTypeId) {
|
|
20749
|
+
runGhGraphqlJson(MUTATION2, { issueId, issueTypeId });
|
|
20783
20750
|
}
|
|
20784
20751
|
|
|
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);
|
|
20752
|
+
// src/commands/github/issue/fixStructure/writeLineNow.ts
|
|
20753
|
+
import { writeSync as writeSync2 } from "fs";
|
|
20754
|
+
function writeLineNow(line) {
|
|
20755
|
+
const text18 = `${line}
|
|
20756
|
+
`;
|
|
20801
20757
|
try {
|
|
20802
|
-
|
|
20758
|
+
writeSync2(1, text18);
|
|
20803
20759
|
} catch {
|
|
20804
|
-
process.
|
|
20760
|
+
process.stdout.write(text18);
|
|
20805
20761
|
}
|
|
20806
20762
|
}
|
|
20807
20763
|
|
|
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);
|
|
20764
|
+
// src/commands/github/issue/fixStructure/applyFixStructurePlan.ts
|
|
20765
|
+
function applyFixStructurePlan(plan2) {
|
|
20766
|
+
for (const entry of plan2.entries) {
|
|
20767
|
+
const where = chalk162.cyan(`${entry.issue.repo}#${entry.issue.number}`);
|
|
20768
|
+
const { typeChange, labelRemovals } = entry;
|
|
20769
|
+
if (typeChange) {
|
|
20770
|
+
writeLineNow(
|
|
20771
|
+
`${where} type ${typeChange.from ?? "no type"} -> ${typeChange.to}`
|
|
20772
|
+
);
|
|
20773
|
+
updateIssueType(entry.issue.id, typeChange.typeId);
|
|
20774
|
+
}
|
|
20775
|
+
if (labelRemovals.length > 0) {
|
|
20776
|
+
writeLineNow(
|
|
20777
|
+
`${where} removing ${labelRemovals.map((label2) => label2.name).join(", ")}`
|
|
20778
|
+
);
|
|
20779
|
+
removeIssueLabels(
|
|
20780
|
+
entry.issue.id,
|
|
20781
|
+
labelRemovals.map((label2) => label2.id)
|
|
20782
|
+
);
|
|
20783
|
+
}
|
|
20836
20784
|
}
|
|
20837
20785
|
}
|
|
20838
20786
|
|
|
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
|
-
}
|
|
20787
|
+
// src/commands/github/issue/fixStructure/assertNothingTooDeep.ts
|
|
20788
|
+
function describe2(entry, leaf) {
|
|
20789
|
+
const parent = entry.parent;
|
|
20790
|
+
const under = parent ? ` under ${parent.repo}#${parent.number}` : "";
|
|
20791
|
+
return `${entry.issue.repo}#${entry.issue.number}${under} sits below ${leaf}, the leaf level`;
|
|
20865
20792
|
}
|
|
20866
|
-
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20793
|
+
function assertNothingTooDeep(tooDeep, chain2) {
|
|
20794
|
+
if (tooDeep.length === 0) return;
|
|
20795
|
+
const leaf = chain2[chain2.length - 1] ?? "the leaf";
|
|
20796
|
+
throw new Error(
|
|
20797
|
+
[
|
|
20798
|
+
...tooDeep.map((entry) => describe2(entry, leaf)),
|
|
20799
|
+
"Re-parent those issues or aim the run at a deeper target"
|
|
20800
|
+
].join("\n")
|
|
20873
20801
|
);
|
|
20874
20802
|
}
|
|
20875
20803
|
|
|
20876
|
-
// src/commands/github/issue/
|
|
20877
|
-
|
|
20878
|
-
|
|
20879
|
-
const
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
|
|
20883
|
-
|
|
20884
|
-
|
|
20885
|
-
|
|
20804
|
+
// src/commands/github/issue/fixStructure/assertNoResidualDrift.ts
|
|
20805
|
+
function describe3(entry) {
|
|
20806
|
+
const where = `${entry.issue.repo}#${entry.issue.number}`;
|
|
20807
|
+
const notes = [];
|
|
20808
|
+
if (entry.typeChange) {
|
|
20809
|
+
notes.push(
|
|
20810
|
+
`${where} is still ${entry.typeChange.from ?? "untyped"}, not ${entry.typeChange.to}`
|
|
20811
|
+
);
|
|
20812
|
+
}
|
|
20813
|
+
for (const label2 of entry.labelRemovals) {
|
|
20814
|
+
notes.push(`${where} still carries ${label2.name}`);
|
|
20815
|
+
}
|
|
20816
|
+
return notes;
|
|
20817
|
+
}
|
|
20818
|
+
function assertNoResidualDrift(plan2, chain2) {
|
|
20819
|
+
assertNothingTooDeep(plan2.tooDeep, chain2);
|
|
20820
|
+
const residual = plan2.entries.flatMap(describe3);
|
|
20821
|
+
if (residual.length === 0) return;
|
|
20822
|
+
throw new Error(
|
|
20823
|
+
["The subtree still drifts after applying:", ...residual].join("\n")
|
|
20886
20824
|
);
|
|
20887
|
-
return bodyPath;
|
|
20888
20825
|
}
|
|
20889
20826
|
|
|
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
|
-
}
|
|
20827
|
+
// src/commands/github/issue/fixStructure/issueFieldsFragment.ts
|
|
20828
|
+
var issueFieldsFragment = `fragment issueFields on Issue {
|
|
20829
|
+
id
|
|
20830
|
+
number
|
|
20831
|
+
title
|
|
20832
|
+
issueType { name }
|
|
20833
|
+
repository { nameWithOwner }
|
|
20834
|
+
labels(first: 100) { nodes { id name } pageInfo { hasNextPage } }
|
|
20835
|
+
subIssues(first: 100) { nodes { id } pageInfo { hasNextPage } }
|
|
20836
|
+
}`;
|
|
20915
20837
|
|
|
20916
|
-
// src/commands/github/issue/
|
|
20917
|
-
|
|
20918
|
-
|
|
20919
|
-
const
|
|
20920
|
-
|
|
20921
|
-
|
|
20922
|
-
|
|
20923
|
-
|
|
20924
|
-
|
|
20838
|
+
// src/commands/github/issue/fixStructure/parseIssueNode.ts
|
|
20839
|
+
function parseIssueNode(node) {
|
|
20840
|
+
const raw = node;
|
|
20841
|
+
const repo = raw.repository?.nameWithOwner ?? "";
|
|
20842
|
+
const where = `${repo}#${raw.number}`;
|
|
20843
|
+
if (raw.labels?.pageInfo?.hasNextPage) {
|
|
20844
|
+
throw new Error(
|
|
20845
|
+
`${where} carries more than 100 labels, which is not supported`
|
|
20846
|
+
);
|
|
20925
20847
|
}
|
|
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}`
|
|
20848
|
+
if (raw.subIssues?.pageInfo?.hasNextPage) {
|
|
20849
|
+
throw new Error(
|
|
20850
|
+
`${where} has more than 100 sub-issues, which is not supported`
|
|
20933
20851
|
);
|
|
20934
|
-
process.exit(1);
|
|
20935
20852
|
}
|
|
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;
|
|
20853
|
+
return {
|
|
20854
|
+
id: raw.id,
|
|
20855
|
+
number: raw.number,
|
|
20856
|
+
title: raw.title,
|
|
20857
|
+
repo,
|
|
20858
|
+
typeName: raw.issueType?.name ?? null,
|
|
20859
|
+
labels: (raw.labels?.nodes ?? []).filter((label2) => label2 !== null),
|
|
20860
|
+
childIds: (raw.subIssues?.nodes ?? []).filter((child) => child !== null).map((child) => child.id)
|
|
20861
|
+
};
|
|
20961
20862
|
}
|
|
20962
20863
|
|
|
20963
|
-
// src/commands/github/issue/
|
|
20964
|
-
|
|
20965
|
-
|
|
20966
|
-
|
|
20967
|
-
|
|
20968
|
-
try {
|
|
20969
|
-
execFileSync10("gh", args, { stdio: "inherit" });
|
|
20970
|
-
} catch {
|
|
20971
|
-
process.exit(1);
|
|
20972
|
-
}
|
|
20864
|
+
// src/commands/github/issue/fixStructure/fetchRootIssue.ts
|
|
20865
|
+
var QUERY = `query($owner: String!, $repo: String!, $number: Int!) {
|
|
20866
|
+
repository(owner: $owner, name: $repo) {
|
|
20867
|
+
issue(number: $number) { ...issueFields }
|
|
20868
|
+
}
|
|
20973
20869
|
}
|
|
20974
|
-
|
|
20975
|
-
|
|
20976
|
-
|
|
20977
|
-
|
|
20978
|
-
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
|
|
20985
|
-
|
|
20870
|
+
${issueFieldsFragment}`;
|
|
20871
|
+
function fetchRootIssue(target) {
|
|
20872
|
+
const raw = runGhGraphqlJson(QUERY, {
|
|
20873
|
+
owner: target.owner,
|
|
20874
|
+
repo: target.repo,
|
|
20875
|
+
number: target.number
|
|
20876
|
+
});
|
|
20877
|
+
const issue = JSON.parse(raw).data?.repository?.issue;
|
|
20878
|
+
if (!issue) {
|
|
20879
|
+
throw new Error(
|
|
20880
|
+
`No issue ${target.owner}/${target.repo}#${target.number} could be read`
|
|
20881
|
+
);
|
|
20986
20882
|
}
|
|
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
|
-
);
|
|
20883
|
+
return parseIssueNode(issue);
|
|
21001
20884
|
}
|
|
21002
20885
|
|
|
21003
20886
|
// src/commands/github/issue/fixStructure/matchedLabels.ts
|
|
@@ -21095,127 +20978,110 @@ function buildFixStructurePlan(issues, options2) {
|
|
|
21095
20978
|
};
|
|
21096
20979
|
}
|
|
21097
20980
|
|
|
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;
|
|
20981
|
+
// src/commands/github/issue/fixStructure/fetchSubtreeIssues.ts
|
|
20982
|
+
var QUERY2 = `query($ids: [ID!]!) {
|
|
20983
|
+
nodes(ids: $ids) { ... on Issue { ...issueFields } }
|
|
21110
20984
|
}
|
|
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
|
-
);
|
|
20985
|
+
${issueFieldsFragment}`;
|
|
20986
|
+
var BATCH = 50;
|
|
20987
|
+
function fetchSubtreeIssues(ids) {
|
|
20988
|
+
const issues = [];
|
|
20989
|
+
for (let start3 = 0; start3 < ids.length; start3 += BATCH) {
|
|
20990
|
+
const raw = runGhGraphqlJson(QUERY2, {
|
|
20991
|
+
ids: ids.slice(start3, start3 + BATCH)
|
|
20992
|
+
});
|
|
20993
|
+
const nodes = JSON.parse(raw).data?.nodes ?? [];
|
|
20994
|
+
for (const node of nodes) {
|
|
20995
|
+
if (node) issues.push(parseIssueNode(node));
|
|
20996
|
+
}
|
|
21132
20997
|
}
|
|
21133
|
-
|
|
21134
|
-
|
|
21135
|
-
|
|
21136
|
-
|
|
20998
|
+
return issues;
|
|
20999
|
+
}
|
|
21000
|
+
|
|
21001
|
+
// src/commands/github/issue/fixStructure/walkSubtree.ts
|
|
21002
|
+
function walkSubtree(root, maxDepth, fetchIssues = fetchSubtreeIssues) {
|
|
21003
|
+
const placed = [{ ...root, depth: 0, parentId: null }];
|
|
21004
|
+
const seen = /* @__PURE__ */ new Set([root.id]);
|
|
21005
|
+
let frontier = placed;
|
|
21006
|
+
for (let depth = 1; depth <= maxDepth && frontier.length > 0; depth += 1) {
|
|
21007
|
+
const parentOf2 = /* @__PURE__ */ new Map();
|
|
21008
|
+
for (const parent of frontier) {
|
|
21009
|
+
for (const childId of parent.childIds) {
|
|
21010
|
+
if (seen.has(childId)) continue;
|
|
21011
|
+
seen.add(childId);
|
|
21012
|
+
parentOf2.set(childId, parent.id);
|
|
21013
|
+
}
|
|
21014
|
+
}
|
|
21015
|
+
if (parentOf2.size === 0) break;
|
|
21016
|
+
const children = fetchIssues([...parentOf2.keys()]).map((issue) => ({
|
|
21017
|
+
...issue,
|
|
21018
|
+
depth,
|
|
21019
|
+
parentId: parentOf2.get(issue.id) ?? null
|
|
21020
|
+
}));
|
|
21021
|
+
placed.push(...children);
|
|
21022
|
+
frontier = children;
|
|
21137
21023
|
}
|
|
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
|
-
};
|
|
21024
|
+
return placed;
|
|
21147
21025
|
}
|
|
21148
21026
|
|
|
21149
|
-
// src/commands/github/issue/fixStructure/
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
}
|
|
21027
|
+
// src/commands/github/issue/fixStructure/planSubtree.ts
|
|
21028
|
+
function planSubtree(root, context) {
|
|
21029
|
+
const depth = context.chain.length - context.rootLevelIndex;
|
|
21030
|
+
return buildFixStructurePlan(walkSubtree(root, depth), context);
|
|
21154
21031
|
}
|
|
21155
|
-
|
|
21156
|
-
|
|
21157
|
-
|
|
21158
|
-
|
|
21159
|
-
|
|
21160
|
-
|
|
21161
|
-
|
|
21162
|
-
|
|
21163
|
-
|
|
21164
|
-
|
|
21165
|
-
|
|
21166
|
-
);
|
|
21167
|
-
}
|
|
21168
|
-
return parseIssueNode(issue);
|
|
21032
|
+
|
|
21033
|
+
// src/commands/github/issue/fixStructure/applyAndVerifySubtree.ts
|
|
21034
|
+
function applyAndVerifySubtree(target, plan2, context) {
|
|
21035
|
+
if (plan2.typeChangeCount === 0 && plan2.labelRemovalCount === 0) return;
|
|
21036
|
+
applyFixStructurePlan(plan2);
|
|
21037
|
+
writeLineNow(chalk163.dim("Re-walking the subtree to confirm"));
|
|
21038
|
+
assertNoResidualDrift(
|
|
21039
|
+
planSubtree(fetchRootIssue(target), context),
|
|
21040
|
+
context.chain
|
|
21041
|
+
);
|
|
21042
|
+
writeLineNow(chalk163.green("Subtree normalised"));
|
|
21169
21043
|
}
|
|
21170
21044
|
|
|
21171
21045
|
// src/commands/github/issue/fixStructure/printFixStructurePlan.ts
|
|
21172
|
-
import
|
|
21046
|
+
import chalk164 from "chalk";
|
|
21173
21047
|
function annotate(entry) {
|
|
21174
21048
|
const notes = [];
|
|
21175
21049
|
if (entry.level === null) {
|
|
21176
|
-
notes.push(
|
|
21050
|
+
notes.push(chalk164.red("deeper than the leaf level"));
|
|
21177
21051
|
} else if (entry.typeChange) {
|
|
21178
21052
|
notes.push(
|
|
21179
|
-
|
|
21053
|
+
chalk164.yellow(
|
|
21180
21054
|
`${entry.typeChange.from ?? "no type"} -> ${entry.typeChange.to}`
|
|
21181
21055
|
)
|
|
21182
21056
|
);
|
|
21183
21057
|
} else {
|
|
21184
|
-
notes.push(
|
|
21058
|
+
notes.push(chalk164.dim(entry.issue.typeName ?? "no type"));
|
|
21185
21059
|
}
|
|
21186
21060
|
for (const label2 of entry.labelRemovals) {
|
|
21187
|
-
notes.push(
|
|
21061
|
+
notes.push(chalk164.yellow(`-${label2.name}`));
|
|
21188
21062
|
}
|
|
21189
21063
|
return notes;
|
|
21190
21064
|
}
|
|
21191
21065
|
function formatCount(count8, noun) {
|
|
21192
21066
|
return `${count8} ${noun}${count8 === 1 ? "" : "s"}`;
|
|
21193
21067
|
}
|
|
21194
|
-
function printFixStructurePlan(plan2, chain2) {
|
|
21195
|
-
|
|
21068
|
+
function printFixStructurePlan(plan2, chain2, apply) {
|
|
21069
|
+
writeLineNow(chalk164.dim(`chain: ${chain2.join(" > ")}`));
|
|
21196
21070
|
for (const entry of plan2.entries) {
|
|
21197
21071
|
const indent3 = " ".repeat(entry.issue.depth);
|
|
21198
|
-
const name =
|
|
21199
|
-
|
|
21072
|
+
const name = chalk164.cyan(`${entry.issue.repo}#${entry.issue.number}`);
|
|
21073
|
+
writeLineNow(
|
|
21200
21074
|
`${indent3}${name} ${entry.issue.title} [${annotate(entry).join(", ")}]`
|
|
21201
21075
|
);
|
|
21202
21076
|
}
|
|
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
21077
|
if (plan2.typeChangeCount === 0 && plan2.labelRemovalCount === 0) {
|
|
21212
|
-
|
|
21078
|
+
writeLineNow(chalk164.green("Nothing to change"));
|
|
21213
21079
|
return;
|
|
21214
21080
|
}
|
|
21215
|
-
|
|
21081
|
+
writeLineNow(
|
|
21216
21082
|
`${formatCount(plan2.typeChangeCount, "type change")}, ${formatCount(plan2.labelRemovalCount, "label removal")} planned`
|
|
21217
21083
|
);
|
|
21218
|
-
|
|
21084
|
+
if (!apply) writeLineNow(chalk164.dim("Dry run \u2014 nothing written"));
|
|
21219
21085
|
}
|
|
21220
21086
|
|
|
21221
21087
|
// src/commands/github/issue/fixStructure/resolveFixStructureTarget.ts
|
|
@@ -21251,7 +21117,7 @@ function resolveFixStructureTarget(target, repo) {
|
|
|
21251
21117
|
}
|
|
21252
21118
|
|
|
21253
21119
|
// src/commands/github/issue/fixStructure/resolveOrgIssueTypes.ts
|
|
21254
|
-
var
|
|
21120
|
+
var QUERY3 = `query($owner: String!) {
|
|
21255
21121
|
organization(login: $owner) {
|
|
21256
21122
|
issueTypes(first: 50) { nodes { id name } }
|
|
21257
21123
|
}
|
|
@@ -21264,7 +21130,7 @@ function missingOrg(owner) {
|
|
|
21264
21130
|
function resolveOrgIssueTypes(owner) {
|
|
21265
21131
|
let raw;
|
|
21266
21132
|
try {
|
|
21267
|
-
raw = runGhGraphqlJson(
|
|
21133
|
+
raw = runGhGraphqlJson(QUERY3, { owner });
|
|
21268
21134
|
} catch (error) {
|
|
21269
21135
|
const message3 = error instanceof Error ? error.message : String(error);
|
|
21270
21136
|
if (message3.includes("Could not resolve to an Organization")) {
|
|
@@ -21307,52 +21173,6 @@ function resolveRootLevelIndex(chain2, targetTypeName, level) {
|
|
|
21307
21173
|
// src/commands/github/issue/fixStructure/types.ts
|
|
21308
21174
|
var defaultTypeChain = ["Epic", "Story", "Subtask"];
|
|
21309
21175
|
|
|
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
21176
|
// src/commands/github/issue/fixStructure/fixStructure.ts
|
|
21357
21177
|
function fixStructure(target, options2) {
|
|
21358
21178
|
const chain2 = defaultTypeChain;
|
|
@@ -21364,15 +21184,17 @@ function fixStructure(target, options2) {
|
|
|
21364
21184
|
root.typeName,
|
|
21365
21185
|
options2.level
|
|
21366
21186
|
);
|
|
21367
|
-
const
|
|
21368
|
-
const issues = walkSubtree(root, chain2.length - index3);
|
|
21369
|
-
const plan2 = buildFixStructurePlan(issues, {
|
|
21187
|
+
const context = {
|
|
21370
21188
|
chain: chain2,
|
|
21371
21189
|
rootLevelIndex: index3,
|
|
21372
21190
|
rootAsserted: asserted,
|
|
21373
|
-
issueTypes
|
|
21374
|
-
|
|
21375
|
-
|
|
21191
|
+
issueTypes: resolveOrgIssueTypes(resolved.owner),
|
|
21192
|
+
stripLabels: []
|
|
21193
|
+
};
|
|
21194
|
+
const plan2 = planSubtree(root, context);
|
|
21195
|
+
printFixStructurePlan(plan2, chain2, options2.apply === true);
|
|
21196
|
+
assertNothingTooDeep(plan2.tooDeep, chain2);
|
|
21197
|
+
if (options2.apply) applyAndVerifySubtree(resolved, plan2, context);
|
|
21376
21198
|
} catch (error) {
|
|
21377
21199
|
console.error(error instanceof Error ? error.message : String(error));
|
|
21378
21200
|
process.exit(1);
|
|
@@ -21383,19 +21205,20 @@ function fixStructure(target, options2) {
|
|
|
21383
21205
|
var chain = defaultTypeChain.join(" > ");
|
|
21384
21206
|
var levels = defaultTypeChain.map((name) => name.toLowerCase()).join("|");
|
|
21385
21207
|
function registerFixStructure(issueCommand) {
|
|
21386
|
-
issueCommand.command("fix-structure <target>").description("
|
|
21208
|
+
issueCommand.command("fix-structure <target>").description("Normalise the issue types across one issue subtree").option(
|
|
21387
21209
|
"-R, --repo <owner/repo>",
|
|
21388
21210
|
"Repository a bare issue number belongs to"
|
|
21389
21211
|
).option(
|
|
21390
21212
|
"--level <level>",
|
|
21391
21213
|
`The target's own position in the ${chain} chain, when it cannot be inferred from its type`
|
|
21392
|
-
).addHelpText(
|
|
21214
|
+
).option("--apply", "Write the planned changes instead of reporting them").addHelpText(
|
|
21393
21215
|
"after",
|
|
21394
21216
|
`
|
|
21395
21217
|
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
21218
|
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
21219
|
The target is owner/repo#number, a github.com issue URL, or a bare number with --repo.
|
|
21398
|
-
|
|
21220
|
+
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.
|
|
21221
|
+
Anything nested below the leaf level fails the run before a single write, naming the offender and its parent.`
|
|
21399
21222
|
).action(fixStructure);
|
|
21400
21223
|
}
|
|
21401
21224
|
|
|
@@ -21410,9 +21233,136 @@ async function readBodyArgument(value) {
|
|
|
21410
21233
|
return body;
|
|
21411
21234
|
}
|
|
21412
21235
|
|
|
21413
|
-
// src/commands/
|
|
21414
|
-
|
|
21415
|
-
|
|
21236
|
+
// src/commands/github/issue/commentIssue.ts
|
|
21237
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
21238
|
+
|
|
21239
|
+
// src/shared/validateProposedContent.ts
|
|
21240
|
+
function validateProposedContent(labels, title, body) {
|
|
21241
|
+
const { subject, context } = labels;
|
|
21242
|
+
if (title.toLowerCase().includes("claude")) {
|
|
21243
|
+
console.error(`Error: ${subject} title must not reference Claude`);
|
|
21244
|
+
process.exit(1);
|
|
21245
|
+
}
|
|
21246
|
+
if (body.toLowerCase().includes("claude")) {
|
|
21247
|
+
console.error(`Error: ${subject} body must not reference Claude`);
|
|
21248
|
+
process.exit(1);
|
|
21249
|
+
}
|
|
21250
|
+
const titleBacklogIds = findBacklogRefs(title);
|
|
21251
|
+
if (titleBacklogIds.length > 0) {
|
|
21252
|
+
console.error(
|
|
21253
|
+
backlogRefError(`${subject} title`, context, titleBacklogIds)
|
|
21254
|
+
);
|
|
21255
|
+
process.exit(1);
|
|
21256
|
+
}
|
|
21257
|
+
const bodyBacklogIds = findBacklogRefs(body);
|
|
21258
|
+
if (bodyBacklogIds.length > 0) {
|
|
21259
|
+
console.error(backlogRefError(`${subject} body`, context, bodyBacklogIds));
|
|
21260
|
+
process.exit(1);
|
|
21261
|
+
}
|
|
21262
|
+
}
|
|
21263
|
+
|
|
21264
|
+
// src/commands/github/issue/reviewProposedIssueComment.ts
|
|
21265
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
21266
|
+
async function reviewProposedIssueComment(title, body) {
|
|
21267
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
21268
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
|
|
21269
|
+
await awaitPreviewApproval("GitHub issue comment preview", {
|
|
21270
|
+
sessionId,
|
|
21271
|
+
requestId: randomUUID7(),
|
|
21272
|
+
title,
|
|
21273
|
+
body,
|
|
21274
|
+
prNumber: null,
|
|
21275
|
+
kind: "github-issue-comment"
|
|
21276
|
+
});
|
|
21277
|
+
}
|
|
21278
|
+
|
|
21279
|
+
// src/commands/github/issue/commentIssue.ts
|
|
21280
|
+
var USAGE = "Usage: assist github issue comment <number> --body <body> [-R <owner>/<repo>]";
|
|
21281
|
+
async function commentIssue(numberArg, options2) {
|
|
21282
|
+
const number = Number.parseInt(numberArg, 10);
|
|
21283
|
+
if (!Number.isInteger(number) || number <= 0 || !options2.body) {
|
|
21284
|
+
console.error(USAGE);
|
|
21285
|
+
process.exit(1);
|
|
21286
|
+
}
|
|
21287
|
+
const { body } = options2;
|
|
21288
|
+
const target = options2.repo ? `${options2.repo}#${number}` : `issue #${number}`;
|
|
21289
|
+
validateProposedContent(
|
|
21290
|
+
{ subject: "Comment", context: "GitHub issues" },
|
|
21291
|
+
"",
|
|
21292
|
+
body
|
|
21293
|
+
);
|
|
21294
|
+
await reviewProposedIssueComment(`Comment on ${target}`, body);
|
|
21295
|
+
const args = ["issue", "comment", String(number), "--body", body];
|
|
21296
|
+
if (options2.repo) args.push("--repo", options2.repo);
|
|
21297
|
+
try {
|
|
21298
|
+
execFileSync6("gh", args, { stdio: "inherit" });
|
|
21299
|
+
} catch {
|
|
21300
|
+
process.exit(1);
|
|
21301
|
+
}
|
|
21302
|
+
console.log(`Comment posted to ${target}`);
|
|
21303
|
+
}
|
|
21304
|
+
|
|
21305
|
+
// src/commands/github/issue/registerCommentIssue.ts
|
|
21306
|
+
function registerCommentIssue(issueCommand) {
|
|
21307
|
+
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(
|
|
21308
|
+
"-R, --repo <owner/repo>",
|
|
21309
|
+
"Target repository (defaults to the current repo)"
|
|
21310
|
+
).addHelpText(
|
|
21311
|
+
"after",
|
|
21312
|
+
"\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."
|
|
21313
|
+
).action(
|
|
21314
|
+
async (number, options2) => {
|
|
21315
|
+
await commentIssue(number, {
|
|
21316
|
+
...options2,
|
|
21317
|
+
body: options2.body ? await readBodyArgument(options2.body) : void 0
|
|
21318
|
+
});
|
|
21319
|
+
}
|
|
21320
|
+
);
|
|
21321
|
+
}
|
|
21322
|
+
|
|
21323
|
+
// src/commands/github/issue/createIssue.ts
|
|
21324
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
21325
|
+
|
|
21326
|
+
// src/commands/github/issue/reviewProposedIssue.ts
|
|
21327
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
21328
|
+
async function reviewProposedIssue(title, body) {
|
|
21329
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
21330
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
|
|
21331
|
+
await awaitPreviewApproval("GitHub issue preview", {
|
|
21332
|
+
sessionId,
|
|
21333
|
+
requestId: randomUUID8(),
|
|
21334
|
+
title,
|
|
21335
|
+
body,
|
|
21336
|
+
prNumber: null,
|
|
21337
|
+
kind: "github-issue"
|
|
21338
|
+
});
|
|
21339
|
+
}
|
|
21340
|
+
|
|
21341
|
+
// src/commands/github/issue/createIssue.ts
|
|
21342
|
+
var USAGE2 = "Usage: assist github issue create --title <title> --body <body> [-R <owner>/<repo>]";
|
|
21343
|
+
async function createIssue(options2) {
|
|
21344
|
+
if (!options2.title || !options2.body) {
|
|
21345
|
+
console.error(USAGE2);
|
|
21346
|
+
process.exit(1);
|
|
21347
|
+
}
|
|
21348
|
+
const { title, body } = options2;
|
|
21349
|
+
validateProposedContent(
|
|
21350
|
+
{ subject: "Issue", context: "GitHub issues" },
|
|
21351
|
+
title,
|
|
21352
|
+
body
|
|
21353
|
+
);
|
|
21354
|
+
await reviewProposedIssue(title, body);
|
|
21355
|
+
const args = ["issue", "create", "--title", title, "--body", body];
|
|
21356
|
+
if (options2.repo) args.push("--repo", options2.repo);
|
|
21357
|
+
try {
|
|
21358
|
+
execFileSync7("gh", args, { stdio: "inherit" });
|
|
21359
|
+
} catch {
|
|
21360
|
+
process.exit(1);
|
|
21361
|
+
}
|
|
21362
|
+
}
|
|
21363
|
+
|
|
21364
|
+
// src/commands/github/issue/registerCreateIssue.ts
|
|
21365
|
+
function registerCreateIssue(issueCommand) {
|
|
21416
21366
|
issueCommand.command("create").description("Create a GitHub issue").option("--title <title>", "Issue title").option("--body <body>", "Issue body").option(
|
|
21417
21367
|
"-R, --repo <owner/repo>",
|
|
21418
21368
|
"Target repository (defaults to the current repo)"
|
|
@@ -21420,6 +21370,205 @@ function registerGithubIssue(githubCommand) {
|
|
|
21420
21370
|
"after",
|
|
21421
21371
|
"\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
21372
|
).action(createIssue);
|
|
21373
|
+
}
|
|
21374
|
+
|
|
21375
|
+
// src/commands/sessions/shared/inWebSession.ts
|
|
21376
|
+
function inWebSession() {
|
|
21377
|
+
return process.env.ASSIST_SESSION === "1" && !!process.env.ASSIST_SESSION_ID;
|
|
21378
|
+
}
|
|
21379
|
+
|
|
21380
|
+
// src/commands/github/issue/fetchIssue.ts
|
|
21381
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
21382
|
+
function fetchIssue2(number, repo) {
|
|
21383
|
+
const args = [
|
|
21384
|
+
"issue",
|
|
21385
|
+
"view",
|
|
21386
|
+
String(number),
|
|
21387
|
+
"--json",
|
|
21388
|
+
"title,body,updatedAt,url"
|
|
21389
|
+
];
|
|
21390
|
+
if (repo) args.push("--repo", repo);
|
|
21391
|
+
let raw;
|
|
21392
|
+
try {
|
|
21393
|
+
raw = execFileSync8("gh", args, { encoding: "utf8" });
|
|
21394
|
+
} catch {
|
|
21395
|
+
console.error(`Could not fetch issue #${number} with gh issue view`);
|
|
21396
|
+
process.exit(1);
|
|
21397
|
+
}
|
|
21398
|
+
try {
|
|
21399
|
+
return JSON.parse(raw);
|
|
21400
|
+
} catch {
|
|
21401
|
+
console.error(`Could not parse the gh issue view output for #${number}`);
|
|
21402
|
+
process.exit(1);
|
|
21403
|
+
}
|
|
21404
|
+
}
|
|
21405
|
+
|
|
21406
|
+
// src/commands/github/issue/resumeIssueBody.ts
|
|
21407
|
+
import { existsSync as existsSync48, readFileSync as readFileSync37 } from "fs";
|
|
21408
|
+
|
|
21409
|
+
// src/commands/github/issue/issueWorkingFile.ts
|
|
21410
|
+
import { join as join50 } from "path";
|
|
21411
|
+
function issueWorkingFile(slug, number) {
|
|
21412
|
+
const [owner = "unknown", repo = "unknown"] = slug.split("/");
|
|
21413
|
+
const dir = join50(getStoreDir(), "github-issues", owner, repo);
|
|
21414
|
+
return {
|
|
21415
|
+
dir,
|
|
21416
|
+
bodyPath: join50(dir, `${number}.md`),
|
|
21417
|
+
metaPath: join50(dir, `${number}.json`)
|
|
21418
|
+
};
|
|
21419
|
+
}
|
|
21420
|
+
|
|
21421
|
+
// src/commands/github/issue/resumeIssueBody.ts
|
|
21422
|
+
function resumeIssueBody(slug, number, updatedAt) {
|
|
21423
|
+
const { bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
21424
|
+
if (!existsSync48(bodyPath) || !existsSync48(metaPath)) return void 0;
|
|
21425
|
+
try {
|
|
21426
|
+
const meta = JSON.parse(readFileSync37(metaPath, "utf8"));
|
|
21427
|
+
if (meta.updatedAt !== updatedAt) return void 0;
|
|
21428
|
+
return readFileSync37(bodyPath, "utf8");
|
|
21429
|
+
} catch {
|
|
21430
|
+
return void 0;
|
|
21431
|
+
}
|
|
21432
|
+
}
|
|
21433
|
+
|
|
21434
|
+
// src/commands/github/issue/validateIssueBody.ts
|
|
21435
|
+
function validateIssueBody(title, body) {
|
|
21436
|
+
validateProposedContent(
|
|
21437
|
+
{ subject: "Issue", context: "GitHub issues" },
|
|
21438
|
+
title,
|
|
21439
|
+
body
|
|
21440
|
+
);
|
|
21441
|
+
}
|
|
21442
|
+
|
|
21443
|
+
// src/commands/github/issue/writeIssueWorkingFile.ts
|
|
21444
|
+
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync31 } from "fs";
|
|
21445
|
+
function writeIssueWorkingFile(slug, number, target, updatedAt, body) {
|
|
21446
|
+
const { dir, bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
21447
|
+
mkdirSync16(dir, { recursive: true });
|
|
21448
|
+
writeFileSync31(bodyPath, body);
|
|
21449
|
+
writeFileSync31(
|
|
21450
|
+
metaPath,
|
|
21451
|
+
`${JSON.stringify({ target, updatedAt }, null, 2)}
|
|
21452
|
+
`
|
|
21453
|
+
);
|
|
21454
|
+
return bodyPath;
|
|
21455
|
+
}
|
|
21456
|
+
|
|
21457
|
+
// src/commands/github/issue/prepareIssueEdit.ts
|
|
21458
|
+
function slugFromUrl(url) {
|
|
21459
|
+
const match = /github\.com\/([^/]+\/[^/]+)\//.exec(url ?? "");
|
|
21460
|
+
return match ? match[1] : "unknown/unknown";
|
|
21461
|
+
}
|
|
21462
|
+
function prepareIssueEdit(number, repo, fresh) {
|
|
21463
|
+
const issue = fetchIssue2(number, repo);
|
|
21464
|
+
const slug = repo ?? slugFromUrl(issue.url);
|
|
21465
|
+
const target = `${slug}#${number}`;
|
|
21466
|
+
const resumed = fresh ? void 0 : resumeIssueBody(slug, number, issue.updatedAt);
|
|
21467
|
+
const body = resumed ?? issue.body;
|
|
21468
|
+
validateIssueBody(issue.title, body);
|
|
21469
|
+
const save = (markdown) => writeIssueWorkingFile(slug, number, target, issue.updatedAt, markdown);
|
|
21470
|
+
const bodyPath = save(body);
|
|
21471
|
+
if (resumed !== void 0)
|
|
21472
|
+
console.log(`Previewing the in-progress markdown from ${bodyPath}`);
|
|
21473
|
+
return {
|
|
21474
|
+
title: issue.title,
|
|
21475
|
+
target,
|
|
21476
|
+
updatedAt: issue.updatedAt,
|
|
21477
|
+
body,
|
|
21478
|
+
bodyPath,
|
|
21479
|
+
save
|
|
21480
|
+
};
|
|
21481
|
+
}
|
|
21482
|
+
|
|
21483
|
+
// src/commands/github/issue/pushIssueBody.ts
|
|
21484
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
21485
|
+
function pushIssueBody(number, repo, bodyPath) {
|
|
21486
|
+
const args = ["issue", "edit", String(number), "--body-file", bodyPath];
|
|
21487
|
+
if (repo) args.push("--repo", repo);
|
|
21488
|
+
try {
|
|
21489
|
+
execFileSync9("gh", args, { stdio: "inherit" });
|
|
21490
|
+
} catch {
|
|
21491
|
+
process.exit(1);
|
|
21492
|
+
}
|
|
21493
|
+
}
|
|
21494
|
+
|
|
21495
|
+
// src/commands/github/issue/pushUnchangedIssue.ts
|
|
21496
|
+
function pushUnchangedIssue(number, repo, target, fetchedAt, bodyPath) {
|
|
21497
|
+
if (fetchIssue2(number, repo).updatedAt !== fetchedAt) {
|
|
21498
|
+
console.error(
|
|
21499
|
+
`${target} was updated on GitHub after it was fetched. Nothing was pushed; the markdown is at ${bodyPath}`
|
|
21500
|
+
);
|
|
21501
|
+
process.exit(1);
|
|
21502
|
+
}
|
|
21503
|
+
pushIssueBody(number, repo, bodyPath);
|
|
21504
|
+
console.log(`Issue body updated on ${target}`);
|
|
21505
|
+
}
|
|
21506
|
+
|
|
21507
|
+
// src/commands/github/issue/reviewProposedIssueEdit.ts
|
|
21508
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
21509
|
+
async function reviewProposedIssueEdit(title, body, working) {
|
|
21510
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
21511
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return body;
|
|
21512
|
+
const decision = await awaitPreviewApproval(
|
|
21513
|
+
"GitHub issue edit preview",
|
|
21514
|
+
{
|
|
21515
|
+
sessionId,
|
|
21516
|
+
requestId: randomUUID9(),
|
|
21517
|
+
title,
|
|
21518
|
+
body,
|
|
21519
|
+
prNumber: null,
|
|
21520
|
+
kind: "github-issue-edit"
|
|
21521
|
+
},
|
|
21522
|
+
{
|
|
21523
|
+
saveEditedBody: working.save,
|
|
21524
|
+
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.`
|
|
21525
|
+
}
|
|
21526
|
+
);
|
|
21527
|
+
return decision.body ?? body;
|
|
21528
|
+
}
|
|
21529
|
+
|
|
21530
|
+
// src/commands/github/issue/viewIssue.ts
|
|
21531
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
21532
|
+
function viewIssue(number, repo) {
|
|
21533
|
+
const args = ["issue", "view", String(number)];
|
|
21534
|
+
if (repo) args.push("--repo", repo);
|
|
21535
|
+
try {
|
|
21536
|
+
execFileSync10("gh", args, { stdio: "inherit" });
|
|
21537
|
+
} catch {
|
|
21538
|
+
process.exit(1);
|
|
21539
|
+
}
|
|
21540
|
+
}
|
|
21541
|
+
|
|
21542
|
+
// src/commands/github/issue/editIssue.ts
|
|
21543
|
+
var USAGE3 = "Usage: assist github issue edit <number> [-R <owner>/<repo>]";
|
|
21544
|
+
async function editIssue(numberArg, options2) {
|
|
21545
|
+
const number = Number.parseInt(numberArg, 10);
|
|
21546
|
+
if (!Number.isInteger(number) || number <= 0) {
|
|
21547
|
+
console.error(USAGE3);
|
|
21548
|
+
process.exit(1);
|
|
21549
|
+
}
|
|
21550
|
+
if (!inWebSession()) {
|
|
21551
|
+
viewIssue(number, options2.repo);
|
|
21552
|
+
return;
|
|
21553
|
+
}
|
|
21554
|
+
const issue = prepareIssueEdit(number, options2.repo, options2.fresh);
|
|
21555
|
+
const edited = await reviewProposedIssueEdit(
|
|
21556
|
+
`Edit ${issue.target}: ${issue.title}`,
|
|
21557
|
+
issue.body,
|
|
21558
|
+
{ path: issue.bodyPath, save: issue.save }
|
|
21559
|
+
);
|
|
21560
|
+
validateIssueBody(issue.title, edited);
|
|
21561
|
+
pushUnchangedIssue(
|
|
21562
|
+
number,
|
|
21563
|
+
options2.repo,
|
|
21564
|
+
issue.target,
|
|
21565
|
+
issue.updatedAt,
|
|
21566
|
+
issue.bodyPath
|
|
21567
|
+
);
|
|
21568
|
+
}
|
|
21569
|
+
|
|
21570
|
+
// src/commands/github/issue/registerEditIssue.ts
|
|
21571
|
+
function registerEditIssue(issueCommand) {
|
|
21423
21572
|
issueCommand.command("edit <number>").description("Edit an existing GitHub issue's body in the preview pane").option(
|
|
21424
21573
|
"-R, --repo <owner/repo>",
|
|
21425
21574
|
"Target repository (defaults to the current repo)"
|
|
@@ -21430,20 +21579,14 @@ function registerGithubIssue(githubCommand) {
|
|
|
21430
21579
|
"after",
|
|
21431
21580
|
"\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
21581
|
).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
|
-
);
|
|
21582
|
+
}
|
|
21583
|
+
|
|
21584
|
+
// src/commands/registerGithubIssue.ts
|
|
21585
|
+
function registerGithubIssue(githubCommand) {
|
|
21586
|
+
const issueCommand = githubCommand.command("issue").description("GitHub issue utilities");
|
|
21587
|
+
registerCreateIssue(issueCommand);
|
|
21588
|
+
registerEditIssue(issueCommand);
|
|
21589
|
+
registerCommentIssue(issueCommand);
|
|
21447
21590
|
registerFixStructure(issueCommand);
|
|
21448
21591
|
}
|
|
21449
21592
|
|
|
@@ -21684,7 +21827,7 @@ function registerHandover(program2) {
|
|
|
21684
21827
|
}
|
|
21685
21828
|
|
|
21686
21829
|
// src/commands/jira/acceptanceCriteria.ts
|
|
21687
|
-
import
|
|
21830
|
+
import chalk165 from "chalk";
|
|
21688
21831
|
|
|
21689
21832
|
// src/commands/jira/adfToText.ts
|
|
21690
21833
|
function renderInline(node) {
|
|
@@ -21751,7 +21894,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
21751
21894
|
const parsed = fetchIssue(issueKey, field);
|
|
21752
21895
|
const acValue = parsed?.fields?.[field];
|
|
21753
21896
|
if (!acValue) {
|
|
21754
|
-
console.log(
|
|
21897
|
+
console.log(chalk165.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
21755
21898
|
return;
|
|
21756
21899
|
}
|
|
21757
21900
|
if (typeof acValue === "string") {
|
|
@@ -21817,14 +21960,14 @@ async function jiraAuth() {
|
|
|
21817
21960
|
}
|
|
21818
21961
|
|
|
21819
21962
|
// src/commands/jira/viewIssue.ts
|
|
21820
|
-
import
|
|
21963
|
+
import chalk166 from "chalk";
|
|
21821
21964
|
function viewIssue2(issueKey) {
|
|
21822
21965
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
21823
21966
|
const fields = parsed?.fields;
|
|
21824
21967
|
const summary = fields?.summary;
|
|
21825
21968
|
const description = fields?.description;
|
|
21826
21969
|
if (summary) {
|
|
21827
|
-
console.log(
|
|
21970
|
+
console.log(chalk166.bold(summary));
|
|
21828
21971
|
}
|
|
21829
21972
|
if (description) {
|
|
21830
21973
|
if (summary) console.log();
|
|
@@ -21838,7 +21981,7 @@ function viewIssue2(issueKey) {
|
|
|
21838
21981
|
}
|
|
21839
21982
|
if (!summary && !description) {
|
|
21840
21983
|
console.log(
|
|
21841
|
-
|
|
21984
|
+
chalk166.yellow(`No summary or description found on ${issueKey}.`)
|
|
21842
21985
|
);
|
|
21843
21986
|
}
|
|
21844
21987
|
}
|
|
@@ -21873,7 +22016,7 @@ import { randomUUID as randomUUID10 } from "crypto";
|
|
|
21873
22016
|
|
|
21874
22017
|
// src/commands/review/checkoutPr.ts
|
|
21875
22018
|
import { execFileSync as execFileSync12 } from "child_process";
|
|
21876
|
-
import
|
|
22019
|
+
import chalk167 from "chalk";
|
|
21877
22020
|
|
|
21878
22021
|
// src/commands/sessions/daemon/daemonLog.ts
|
|
21879
22022
|
var RING_CAPACITY = 1e3;
|
|
@@ -22485,7 +22628,7 @@ async function checkoutPr(number) {
|
|
|
22485
22628
|
try {
|
|
22486
22629
|
execFileSync12("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
22487
22630
|
} catch {
|
|
22488
|
-
console.error(
|
|
22631
|
+
console.error(chalk167.red(`gh pr checkout ${number} failed; aborting.`));
|
|
22489
22632
|
process.exit(1);
|
|
22490
22633
|
}
|
|
22491
22634
|
}
|
|
@@ -22622,15 +22765,15 @@ function registerList(program2) {
|
|
|
22622
22765
|
// src/commands/mermaid/index.ts
|
|
22623
22766
|
import { mkdirSync as mkdirSync18, readdirSync as readdirSync11 } from "fs";
|
|
22624
22767
|
import { resolve as resolve16 } from "path";
|
|
22625
|
-
import
|
|
22768
|
+
import chalk170 from "chalk";
|
|
22626
22769
|
|
|
22627
22770
|
// src/commands/mermaid/exportFile.ts
|
|
22628
22771
|
import { readFileSync as readFileSync39, writeFileSync as writeFileSync32 } from "fs";
|
|
22629
22772
|
import { basename as basename17, extname as extname2, resolve as resolve15 } from "path";
|
|
22630
|
-
import
|
|
22773
|
+
import chalk169 from "chalk";
|
|
22631
22774
|
|
|
22632
22775
|
// src/commands/mermaid/renderBlock.ts
|
|
22633
|
-
import
|
|
22776
|
+
import chalk168 from "chalk";
|
|
22634
22777
|
async function renderBlock(krokiUrl, source) {
|
|
22635
22778
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
22636
22779
|
method: "POST",
|
|
@@ -22639,7 +22782,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
22639
22782
|
});
|
|
22640
22783
|
if (!response.ok) {
|
|
22641
22784
|
console.error(
|
|
22642
|
-
|
|
22785
|
+
chalk168.red(
|
|
22643
22786
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
22644
22787
|
)
|
|
22645
22788
|
);
|
|
@@ -22657,19 +22800,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
22657
22800
|
if (onlyIndex !== void 0) {
|
|
22658
22801
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
22659
22802
|
console.error(
|
|
22660
|
-
|
|
22803
|
+
chalk169.red(
|
|
22661
22804
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
22662
22805
|
)
|
|
22663
22806
|
);
|
|
22664
22807
|
process.exit(1);
|
|
22665
22808
|
}
|
|
22666
22809
|
console.log(
|
|
22667
|
-
|
|
22810
|
+
chalk169.gray(
|
|
22668
22811
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
22669
22812
|
)
|
|
22670
22813
|
);
|
|
22671
22814
|
} else {
|
|
22672
|
-
console.log(
|
|
22815
|
+
console.log(chalk169.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
22673
22816
|
}
|
|
22674
22817
|
for (const [i, source] of blocks.entries()) {
|
|
22675
22818
|
const idx = i + 1;
|
|
@@ -22677,7 +22820,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
22677
22820
|
const outPath = resolve15(outDir, `${stem}-${idx}.svg`);
|
|
22678
22821
|
const svg = await renderBlock(krokiUrl, source);
|
|
22679
22822
|
writeFileSync32(outPath, svg, "utf8");
|
|
22680
|
-
console.log(
|
|
22823
|
+
console.log(chalk169.green(` \u2192 ${outPath}`));
|
|
22681
22824
|
}
|
|
22682
22825
|
}
|
|
22683
22826
|
function extractMermaidBlocks(markdown) {
|
|
@@ -22693,18 +22836,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
22693
22836
|
if (options2.index !== void 0) {
|
|
22694
22837
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
22695
22838
|
console.error(
|
|
22696
|
-
|
|
22839
|
+
chalk170.red(`--index must be a positive integer (got ${options2.index})`)
|
|
22697
22840
|
);
|
|
22698
22841
|
process.exit(1);
|
|
22699
22842
|
}
|
|
22700
22843
|
if (!file) {
|
|
22701
|
-
console.error(
|
|
22844
|
+
console.error(chalk170.red("--index requires a file argument"));
|
|
22702
22845
|
process.exit(1);
|
|
22703
22846
|
}
|
|
22704
22847
|
}
|
|
22705
22848
|
const files = file ? [file] : readdirSync11(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
22706
22849
|
if (files.length === 0) {
|
|
22707
|
-
console.log(
|
|
22850
|
+
console.log(chalk170.gray("No markdown files found in current directory."));
|
|
22708
22851
|
return;
|
|
22709
22852
|
}
|
|
22710
22853
|
for (const f of files) {
|
|
@@ -22760,13 +22903,13 @@ function stripHtml2(content) {
|
|
|
22760
22903
|
|
|
22761
22904
|
// src/commands/miro/normaliseItems.ts
|
|
22762
22905
|
var frameCoordinates = "parent_top_left";
|
|
22763
|
-
function
|
|
22906
|
+
function describe4(item) {
|
|
22764
22907
|
return ` ${item.id ?? "(no id)"} (${item.type ?? "unknown type"}): relativeTo=${item.position?.relativeTo ?? "missing"}`;
|
|
22765
22908
|
}
|
|
22766
22909
|
function coordinateSpaceError(rejected) {
|
|
22767
22910
|
return new MiroExtractError(
|
|
22768
22911
|
`${rejected.length} item(s) are not in frame coordinates (position.relativeTo must be "${frameCoordinates}"):
|
|
22769
|
-
${rejected.slice(0, 5).map(
|
|
22912
|
+
${rejected.slice(0, 5).map(describe4).join(
|
|
22770
22913
|
"\n"
|
|
22771
22914
|
)}
|
|
22772
22915
|
|
|
@@ -22803,6 +22946,45 @@ function parseAnchorId(value) {
|
|
|
22803
22946
|
return link3 ? decodeURIComponent(link3[1]).trim() : trimmed;
|
|
22804
22947
|
}
|
|
22805
22948
|
|
|
22949
|
+
// src/commands/miro/pickAnchors.ts
|
|
22950
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
22951
|
+
|
|
22952
|
+
// src/commands/miro/isBox.ts
|
|
22953
|
+
var boxTypes = /* @__PURE__ */ new Set(["shape", "sticky_note"]);
|
|
22954
|
+
function isBox(item) {
|
|
22955
|
+
return boxTypes.has(item.type) && item.text.length > 0;
|
|
22956
|
+
}
|
|
22957
|
+
|
|
22958
|
+
// src/commands/miro/encodeMiroBoardPreview.ts
|
|
22959
|
+
function encodeMiroBoardPreview(items2) {
|
|
22960
|
+
const preview = { boxes: items2.filter(isBox) };
|
|
22961
|
+
return JSON.stringify(preview);
|
|
22962
|
+
}
|
|
22963
|
+
|
|
22964
|
+
// src/commands/miro/pickAnchors.ts
|
|
22965
|
+
var skipAdvice = "Re-run with --top-left <id|link> --bottom-right <id|link> to skip the picker.";
|
|
22966
|
+
async function pickAnchors(sessionId, items2) {
|
|
22967
|
+
const decision = await awaitPreviewApproval(
|
|
22968
|
+
"Miro anchor selection",
|
|
22969
|
+
{
|
|
22970
|
+
sessionId,
|
|
22971
|
+
requestId: randomUUID12(),
|
|
22972
|
+
title: "Pick the top-left then the bottom-right box",
|
|
22973
|
+
body: encodeMiroBoardPreview(items2),
|
|
22974
|
+
prNumber: null,
|
|
22975
|
+
kind: "miro-board"
|
|
22976
|
+
},
|
|
22977
|
+
{ rejectionAdvice: `Nothing was extracted. ${skipAdvice}` }
|
|
22978
|
+
);
|
|
22979
|
+
const selection = decision.selection;
|
|
22980
|
+
if (!selection)
|
|
22981
|
+
throw new MiroExtractError(`The picker returned no boxes. ${skipAdvice}`);
|
|
22982
|
+
console.log(
|
|
22983
|
+
`Anchors: --top-left ${selection.topLeft} --bottom-right ${selection.bottomRight}`
|
|
22984
|
+
);
|
|
22985
|
+
return [selection.topLeft, selection.bottomRight];
|
|
22986
|
+
}
|
|
22987
|
+
|
|
22806
22988
|
// src/commands/miro/readMiroItems.ts
|
|
22807
22989
|
import { readFileSync as readFileSync40 } from "fs";
|
|
22808
22990
|
function tryParse(text18) {
|
|
@@ -22844,7 +23026,6 @@ function readMiroItems(file) {
|
|
|
22844
23026
|
}
|
|
22845
23027
|
|
|
22846
23028
|
// src/commands/miro/selectBoxes.ts
|
|
22847
|
-
var boxTypes = /* @__PURE__ */ new Set(["shape", "sticky_note"]);
|
|
22848
23029
|
function findAnchor(items2, id) {
|
|
22849
23030
|
const anchor = items2.find((item) => item.id === id);
|
|
22850
23031
|
if (!anchor)
|
|
@@ -22853,9 +23034,6 @@ function findAnchor(items2, id) {
|
|
|
22853
23034
|
);
|
|
22854
23035
|
return anchor;
|
|
22855
23036
|
}
|
|
22856
|
-
function isBox(item) {
|
|
22857
|
-
return boxTypes.has(item.type) && item.text.length > 0;
|
|
22858
|
-
}
|
|
22859
23037
|
function centreInside(rect, item) {
|
|
22860
23038
|
const x = (item.left + item.right) / 2;
|
|
22861
23039
|
const y = (item.top + item.bottom) / 2;
|
|
@@ -22881,16 +23059,24 @@ function requireItems(file) {
|
|
|
22881
23059
|
);
|
|
22882
23060
|
return file;
|
|
22883
23061
|
}
|
|
22884
|
-
function
|
|
22885
|
-
if (
|
|
23062
|
+
function anchorSource(options2) {
|
|
23063
|
+
if (options2.topLeft && options2.bottomRight)
|
|
23064
|
+
return {
|
|
23065
|
+
pick: false,
|
|
23066
|
+
topLeft: parseAnchorId(options2.topLeft),
|
|
23067
|
+
bottomRight: parseAnchorId(options2.bottomRight)
|
|
23068
|
+
};
|
|
23069
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
23070
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId)
|
|
22886
23071
|
throw new MiroExtractError(
|
|
22887
|
-
"Both --top-left <id|link> and --bottom-right <id|link> are required."
|
|
23072
|
+
"Both --top-left <id|link> and --bottom-right <id|link> are required: there is no assist session to host the picker pane."
|
|
22888
23073
|
);
|
|
22889
|
-
return
|
|
23074
|
+
return { pick: true, sessionId };
|
|
22890
23075
|
}
|
|
22891
|
-
function runExtract(options2) {
|
|
22892
|
-
const
|
|
23076
|
+
async function runExtract(options2) {
|
|
23077
|
+
const source = anchorSource(options2);
|
|
22893
23078
|
const items2 = normaliseItems(readMiroItems(requireItems(options2.items)));
|
|
23079
|
+
const [topLeft, bottomRight] = source.pick ? await pickAnchors(source.sessionId, items2) : [source.topLeft, source.bottomRight];
|
|
22894
23080
|
const boxes = selectBoxes(items2, topLeft, bottomRight);
|
|
22895
23081
|
process.stdout.write(stringify(boxes.map((box) => box.text)));
|
|
22896
23082
|
}
|
|
@@ -22900,7 +23086,7 @@ function registerMiro(program2) {
|
|
|
22900
23086
|
const miroCommand = program2.command("miro").description("Miro board utilities");
|
|
22901
23087
|
miroCommand.command("extract").description("Print the text of every box inside a rectangle on a board").option("--items <file>", "File of raw board_list_items response pages").option(
|
|
22902
23088
|
"--top-left <id>",
|
|
22903
|
-
"Widget id or ?moveToWidget=<id> link of the top-left box"
|
|
23089
|
+
"Widget id or ?moveToWidget=<id> link of the top-left box (omit both anchors to pick them in the assist web UI)"
|
|
22904
23090
|
).option(
|
|
22905
23091
|
"--bottom-right <id>",
|
|
22906
23092
|
"Widget id or ?moveToWidget=<id> link of the bottom-right box"
|
|
@@ -22911,7 +23097,7 @@ function registerMiro(program2) {
|
|
|
22911
23097
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
22912
23098
|
import { createServer as createServer2 } from "http";
|
|
22913
23099
|
import { dirname as dirname28 } from "path";
|
|
22914
|
-
import
|
|
23100
|
+
import chalk172 from "chalk";
|
|
22915
23101
|
|
|
22916
23102
|
// src/commands/netcap/corsHeaders.ts
|
|
22917
23103
|
var corsHeaders = {
|
|
@@ -22990,7 +23176,7 @@ function createNetcapHandler(options2) {
|
|
|
22990
23176
|
import { cp, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
22991
23177
|
import { networkInterfaces } from "os";
|
|
22992
23178
|
import { join as join58 } from "path";
|
|
22993
|
-
import
|
|
23179
|
+
import chalk171 from "chalk";
|
|
22994
23180
|
|
|
22995
23181
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
22996
23182
|
import { dirname as dirname27, join as join57 } from "path";
|
|
@@ -23034,7 +23220,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
23034
23220
|
const host = lanIPv4();
|
|
23035
23221
|
if (!host) {
|
|
23036
23222
|
console.log(
|
|
23037
|
-
|
|
23223
|
+
chalk171.yellow("could not determine the WSL IP for the extension")
|
|
23038
23224
|
);
|
|
23039
23225
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
23040
23226
|
return source;
|
|
@@ -23045,7 +23231,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
23045
23231
|
return WSL_WINDOWS_PATH;
|
|
23046
23232
|
} catch {
|
|
23047
23233
|
console.log(
|
|
23048
|
-
|
|
23234
|
+
chalk171.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
23049
23235
|
);
|
|
23050
23236
|
return source;
|
|
23051
23237
|
}
|
|
@@ -23078,30 +23264,30 @@ async function netcap(options2) {
|
|
|
23078
23264
|
let count8 = 0;
|
|
23079
23265
|
const handler = createNetcapHandler({
|
|
23080
23266
|
outPath,
|
|
23081
|
-
onPing: () => console.log(
|
|
23267
|
+
onPing: () => console.log(chalk172.dim("ping from extension")),
|
|
23082
23268
|
onCapture: (entry) => {
|
|
23083
23269
|
count8 += 1;
|
|
23084
23270
|
console.log(
|
|
23085
|
-
|
|
23086
|
-
|
|
23271
|
+
chalk172.green(`captured #${count8}`),
|
|
23272
|
+
chalk172.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
23087
23273
|
);
|
|
23088
23274
|
}
|
|
23089
23275
|
});
|
|
23090
23276
|
const server = createServer2(handler);
|
|
23091
23277
|
server.listen(port, () => {
|
|
23092
23278
|
console.log(
|
|
23093
|
-
|
|
23279
|
+
chalk172.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
23094
23280
|
);
|
|
23095
|
-
console.log(
|
|
23281
|
+
console.log(chalk172.dim(`appending captures to ${outPath}`));
|
|
23096
23282
|
if (filter)
|
|
23097
|
-
console.log(
|
|
23098
|
-
console.log(
|
|
23099
|
-
console.log(
|
|
23283
|
+
console.log(chalk172.dim(`forwarding only URLs matching "${filter}"`));
|
|
23284
|
+
console.log(chalk172.dim(`load the unpacked extension from ${extensionPath}`));
|
|
23285
|
+
console.log(chalk172.dim("press Ctrl-C to stop"));
|
|
23100
23286
|
});
|
|
23101
23287
|
process.on("SIGINT", () => {
|
|
23102
23288
|
server.close();
|
|
23103
23289
|
console.log(
|
|
23104
|
-
|
|
23290
|
+
chalk172.bold(
|
|
23105
23291
|
`
|
|
23106
23292
|
netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
23107
23293
|
)
|
|
@@ -23113,7 +23299,7 @@ netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} t
|
|
|
23113
23299
|
// src/commands/netcap/netcapExtract.ts
|
|
23114
23300
|
import { writeFileSync as writeFileSync33 } from "fs";
|
|
23115
23301
|
import { join as join61 } from "path";
|
|
23116
|
-
import
|
|
23302
|
+
import chalk173 from "chalk";
|
|
23117
23303
|
|
|
23118
23304
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
23119
23305
|
import { readFileSync as readFileSync41 } from "fs";
|
|
@@ -23561,8 +23747,8 @@ function netcapExtract(file) {
|
|
|
23561
23747
|
writeFileSync33(outFile, `${JSON.stringify(posts, null, 2)}
|
|
23562
23748
|
`);
|
|
23563
23749
|
console.log(
|
|
23564
|
-
|
|
23565
|
-
|
|
23750
|
+
chalk173.green(`extracted ${posts.length} posts`),
|
|
23751
|
+
chalk173.dim(`-> ${outFile}`)
|
|
23566
23752
|
);
|
|
23567
23753
|
}
|
|
23568
23754
|
|
|
@@ -23583,7 +23769,7 @@ function registerNetcap(program2) {
|
|
|
23583
23769
|
}
|
|
23584
23770
|
|
|
23585
23771
|
// src/commands/news/add/index.ts
|
|
23586
|
-
import
|
|
23772
|
+
import chalk174 from "chalk";
|
|
23587
23773
|
import enquirer8 from "enquirer";
|
|
23588
23774
|
async function add2(url) {
|
|
23589
23775
|
if (!url) {
|
|
@@ -23605,10 +23791,10 @@ async function add2(url) {
|
|
|
23605
23791
|
const { orm } = await getReady();
|
|
23606
23792
|
const added = await addFeed(orm, url);
|
|
23607
23793
|
if (!added) {
|
|
23608
|
-
console.log(
|
|
23794
|
+
console.log(chalk174.yellow("Feed already exists"));
|
|
23609
23795
|
return;
|
|
23610
23796
|
}
|
|
23611
|
-
console.log(
|
|
23797
|
+
console.log(chalk174.green(`Added feed: ${url}`));
|
|
23612
23798
|
}
|
|
23613
23799
|
|
|
23614
23800
|
// src/commands/registerNews.ts
|
|
@@ -23655,7 +23841,7 @@ function registerPiHook(program2) {
|
|
|
23655
23841
|
}
|
|
23656
23842
|
|
|
23657
23843
|
// src/commands/prompts/printPromptsTable.ts
|
|
23658
|
-
import
|
|
23844
|
+
import chalk175 from "chalk";
|
|
23659
23845
|
function truncate(str, max) {
|
|
23660
23846
|
if (str.length <= max) return str;
|
|
23661
23847
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -23673,14 +23859,14 @@ function printPromptsTable(rows) {
|
|
|
23673
23859
|
"Command".padEnd(commandWidth),
|
|
23674
23860
|
"Repos"
|
|
23675
23861
|
].join(" ");
|
|
23676
|
-
console.log(
|
|
23677
|
-
console.log(
|
|
23862
|
+
console.log(chalk175.dim(header));
|
|
23863
|
+
console.log(chalk175.dim("-".repeat(header.length)));
|
|
23678
23864
|
for (const row of rows) {
|
|
23679
23865
|
const count8 = String(row.count).padStart(countWidth);
|
|
23680
23866
|
const tool = row.tool.padEnd(toolWidth);
|
|
23681
23867
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
23682
23868
|
console.log(
|
|
23683
|
-
`${
|
|
23869
|
+
`${chalk175.yellow(count8)} ${tool} ${command} ${chalk175.dim(row.repos)}`
|
|
23684
23870
|
);
|
|
23685
23871
|
}
|
|
23686
23872
|
}
|
|
@@ -23732,13 +23918,13 @@ function postReviewComment(vars) {
|
|
|
23732
23918
|
}
|
|
23733
23919
|
|
|
23734
23920
|
// src/commands/prs/reviewProposedPrComment.ts
|
|
23735
|
-
import { randomUUID as
|
|
23921
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
23736
23922
|
async function reviewProposedPrComment(title, body, prNumber) {
|
|
23737
23923
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
23738
23924
|
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
|
|
23739
23925
|
await awaitPreviewApproval("PR comment preview", {
|
|
23740
23926
|
sessionId,
|
|
23741
|
-
requestId:
|
|
23927
|
+
requestId: randomUUID13(),
|
|
23742
23928
|
title,
|
|
23743
23929
|
body,
|
|
23744
23930
|
prNumber,
|
|
@@ -23864,7 +24050,7 @@ async function comment2(path80, line, body, startLine) {
|
|
|
23864
24050
|
}
|
|
23865
24051
|
|
|
23866
24052
|
// src/commands/prs/edit.ts
|
|
23867
|
-
import { randomUUID as
|
|
24053
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
23868
24054
|
|
|
23869
24055
|
// src/commands/prs/appendScreenshots.ts
|
|
23870
24056
|
function appendScreenshots(body, screenshots) {
|
|
@@ -24061,7 +24247,7 @@ async function edit(options2) {
|
|
|
24061
24247
|
if (process.env.ASSIST_SESSION === "1" && sessionId) {
|
|
24062
24248
|
const decision = await awaitPreviewApproval("PR preview", {
|
|
24063
24249
|
sessionId,
|
|
24064
|
-
requestId:
|
|
24250
|
+
requestId: randomUUID14(),
|
|
24065
24251
|
title: options2.title ?? title,
|
|
24066
24252
|
body: newBody,
|
|
24067
24253
|
prNumber: number
|
|
@@ -24347,13 +24533,13 @@ function agentFooter(unresolvedCount) {
|
|
|
24347
24533
|
}
|
|
24348
24534
|
|
|
24349
24535
|
// src/commands/prs/listComments/commentStyle.ts
|
|
24350
|
-
import
|
|
24536
|
+
import chalk176 from "chalk";
|
|
24351
24537
|
var plain = (text18) => text18;
|
|
24352
24538
|
function colouredState(state) {
|
|
24353
24539
|
const label2 = `[${state}]`;
|
|
24354
|
-
if (state === "APPROVED") return
|
|
24355
|
-
if (state === "CHANGES_REQUESTED") return
|
|
24356
|
-
return
|
|
24540
|
+
if (state === "APPROVED") return chalk176.green(label2);
|
|
24541
|
+
if (state === "CHANGES_REQUESTED") return chalk176.red(label2);
|
|
24542
|
+
return chalk176.yellow(label2);
|
|
24357
24543
|
}
|
|
24358
24544
|
function commentStyle() {
|
|
24359
24545
|
if (isClaudeCode()) {
|
|
@@ -24367,9 +24553,9 @@ function commentStyle() {
|
|
|
24367
24553
|
};
|
|
24368
24554
|
}
|
|
24369
24555
|
return {
|
|
24370
|
-
cyan:
|
|
24371
|
-
bold:
|
|
24372
|
-
dim:
|
|
24556
|
+
cyan: chalk176.cyan,
|
|
24557
|
+
bold: chalk176.bold,
|
|
24558
|
+
dim: chalk176.dim,
|
|
24373
24559
|
state: colouredState,
|
|
24374
24560
|
diffHunk: true,
|
|
24375
24561
|
agent: false
|
|
@@ -24539,13 +24725,13 @@ import { execSync as execSync48 } from "child_process";
|
|
|
24539
24725
|
import enquirer9 from "enquirer";
|
|
24540
24726
|
|
|
24541
24727
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
24542
|
-
import
|
|
24728
|
+
import chalk177 from "chalk";
|
|
24543
24729
|
var STATUS_MAP = {
|
|
24544
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
24545
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
24730
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk177.magenta("merged"), date: pr.mergedAt } : null,
|
|
24731
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk177.red("closed"), date: pr.closedAt } : null
|
|
24546
24732
|
};
|
|
24547
24733
|
function defaultStatus(pr) {
|
|
24548
|
-
return { label:
|
|
24734
|
+
return { label: chalk177.green("opened"), date: pr.createdAt };
|
|
24549
24735
|
}
|
|
24550
24736
|
function getStatus2(pr) {
|
|
24551
24737
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -24554,11 +24740,11 @@ function formatDate(dateStr) {
|
|
|
24554
24740
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
24555
24741
|
}
|
|
24556
24742
|
function formatPrHeader(pr, status3) {
|
|
24557
|
-
return `${
|
|
24743
|
+
return `${chalk177.cyan(`#${pr.number}`)} ${pr.title} ${chalk177.dim(`(${pr.author.login},`)} ${status3.label} ${chalk177.dim(`${formatDate(status3.date)})`)}`;
|
|
24558
24744
|
}
|
|
24559
24745
|
function logPrDetails(pr) {
|
|
24560
24746
|
console.log(
|
|
24561
|
-
|
|
24747
|
+
chalk177.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
24562
24748
|
);
|
|
24563
24749
|
console.log();
|
|
24564
24750
|
}
|
|
@@ -24772,7 +24958,7 @@ async function placePr(prNumber, title, body, options2) {
|
|
|
24772
24958
|
}
|
|
24773
24959
|
|
|
24774
24960
|
// src/commands/prs/previewAndPlace.ts
|
|
24775
|
-
import { randomUUID as
|
|
24961
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
24776
24962
|
|
|
24777
24963
|
// src/commands/sessions/shared/requestSession.ts
|
|
24778
24964
|
function parseIncoming(line, type) {
|
|
@@ -24907,7 +25093,7 @@ function warn(reason4) {
|
|
|
24907
25093
|
async function previewAndPlace(args) {
|
|
24908
25094
|
const decision = await awaitPreviewApproval("PR preview", {
|
|
24909
25095
|
sessionId: args.sessionId,
|
|
24910
|
-
requestId:
|
|
25096
|
+
requestId: randomUUID15(),
|
|
24911
25097
|
title: args.title,
|
|
24912
25098
|
body: args.body,
|
|
24913
25099
|
prNumber: args.prNumber,
|
|
@@ -25273,10 +25459,10 @@ function registerPrs(program2) {
|
|
|
25273
25459
|
}
|
|
25274
25460
|
|
|
25275
25461
|
// src/commands/ravendb/ravendbAuth.ts
|
|
25276
|
-
import
|
|
25462
|
+
import chalk183 from "chalk";
|
|
25277
25463
|
|
|
25278
25464
|
// src/shared/createConnectionAuth.ts
|
|
25279
|
-
import
|
|
25465
|
+
import chalk178 from "chalk";
|
|
25280
25466
|
function listConnections(connections, format) {
|
|
25281
25467
|
if (connections.length === 0) {
|
|
25282
25468
|
console.log("No connections configured.");
|
|
@@ -25289,7 +25475,7 @@ function listConnections(connections, format) {
|
|
|
25289
25475
|
function removeConnection(connections, name, save) {
|
|
25290
25476
|
const filtered = connections.filter((c) => c.name !== name);
|
|
25291
25477
|
if (filtered.length === connections.length) {
|
|
25292
|
-
console.error(
|
|
25478
|
+
console.error(chalk178.red(`Connection "${name}" not found.`));
|
|
25293
25479
|
process.exit(1);
|
|
25294
25480
|
}
|
|
25295
25481
|
save(filtered);
|
|
@@ -25335,15 +25521,15 @@ function saveConnections(connections) {
|
|
|
25335
25521
|
}
|
|
25336
25522
|
|
|
25337
25523
|
// src/commands/ravendb/promptConnection.ts
|
|
25338
|
-
import
|
|
25524
|
+
import chalk181 from "chalk";
|
|
25339
25525
|
|
|
25340
25526
|
// src/commands/ravendb/selectOpSecret.ts
|
|
25341
|
-
import
|
|
25527
|
+
import chalk180 from "chalk";
|
|
25342
25528
|
import Enquirer2 from "enquirer";
|
|
25343
25529
|
|
|
25344
25530
|
// src/commands/ravendb/searchItems.ts
|
|
25345
25531
|
import { execSync as execSync51 } from "child_process";
|
|
25346
|
-
import
|
|
25532
|
+
import chalk179 from "chalk";
|
|
25347
25533
|
function opExec(args) {
|
|
25348
25534
|
return execSync51(`op ${args}`, {
|
|
25349
25535
|
encoding: "utf8",
|
|
@@ -25356,7 +25542,7 @@ function searchItems(search2) {
|
|
|
25356
25542
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
25357
25543
|
} catch {
|
|
25358
25544
|
console.error(
|
|
25359
|
-
|
|
25545
|
+
chalk179.red(
|
|
25360
25546
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
25361
25547
|
)
|
|
25362
25548
|
);
|
|
@@ -25370,7 +25556,7 @@ function getItemFields(itemId2) {
|
|
|
25370
25556
|
const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
|
|
25371
25557
|
return item.fields.filter((f) => f.reference && f.label);
|
|
25372
25558
|
} catch {
|
|
25373
|
-
console.error(
|
|
25559
|
+
console.error(chalk179.red("Failed to get item details from 1Password."));
|
|
25374
25560
|
process.exit(1);
|
|
25375
25561
|
}
|
|
25376
25562
|
}
|
|
@@ -25389,7 +25575,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
25389
25575
|
}).run();
|
|
25390
25576
|
const items2 = searchItems(search2);
|
|
25391
25577
|
if (items2.length === 0) {
|
|
25392
|
-
console.error(
|
|
25578
|
+
console.error(chalk180.red(`No items found matching "${search2}".`));
|
|
25393
25579
|
process.exit(1);
|
|
25394
25580
|
}
|
|
25395
25581
|
const itemId2 = await selectOne(
|
|
@@ -25398,7 +25584,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
25398
25584
|
);
|
|
25399
25585
|
const fields = getItemFields(itemId2);
|
|
25400
25586
|
if (fields.length === 0) {
|
|
25401
|
-
console.error(
|
|
25587
|
+
console.error(chalk180.red("No fields with references found on this item."));
|
|
25402
25588
|
process.exit(1);
|
|
25403
25589
|
}
|
|
25404
25590
|
const ref = await selectOne(
|
|
@@ -25412,7 +25598,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
25412
25598
|
async function promptConnection(existingNames) {
|
|
25413
25599
|
const name = await promptInput("name", "Connection name:");
|
|
25414
25600
|
if (existingNames.includes(name)) {
|
|
25415
|
-
console.error(
|
|
25601
|
+
console.error(chalk181.red(`Connection "${name}" already exists.`));
|
|
25416
25602
|
process.exit(1);
|
|
25417
25603
|
}
|
|
25418
25604
|
const url = await promptInput(
|
|
@@ -25421,22 +25607,22 @@ async function promptConnection(existingNames) {
|
|
|
25421
25607
|
);
|
|
25422
25608
|
const database = await promptInput("database", "Database name:");
|
|
25423
25609
|
if (!name || !url || !database) {
|
|
25424
|
-
console.error(
|
|
25610
|
+
console.error(chalk181.red("All fields are required."));
|
|
25425
25611
|
process.exit(1);
|
|
25426
25612
|
}
|
|
25427
25613
|
const apiKeyRef = await selectOpSecret();
|
|
25428
|
-
console.log(
|
|
25614
|
+
console.log(chalk181.dim(`Using: ${apiKeyRef}`));
|
|
25429
25615
|
return { name, url, database, apiKeyRef };
|
|
25430
25616
|
}
|
|
25431
25617
|
|
|
25432
25618
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
25433
|
-
import
|
|
25619
|
+
import chalk182 from "chalk";
|
|
25434
25620
|
function ravendbSetConnection(name) {
|
|
25435
25621
|
const raw = loadGlobalConfigRaw();
|
|
25436
25622
|
const ravendb = raw.ravendb ?? {};
|
|
25437
25623
|
const connections = ravendb.connections ?? [];
|
|
25438
25624
|
if (!connections.some((c) => c.name === name)) {
|
|
25439
|
-
console.error(
|
|
25625
|
+
console.error(chalk182.red(`Connection "${name}" not found.`));
|
|
25440
25626
|
console.error(
|
|
25441
25627
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
25442
25628
|
);
|
|
@@ -25452,16 +25638,16 @@ function ravendbSetConnection(name) {
|
|
|
25452
25638
|
var ravendbAuth = createConnectionAuth({
|
|
25453
25639
|
load: loadConnections,
|
|
25454
25640
|
save: saveConnections,
|
|
25455
|
-
format: (c) => `${
|
|
25641
|
+
format: (c) => `${chalk183.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
25456
25642
|
promptNew: promptConnection,
|
|
25457
25643
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
25458
25644
|
});
|
|
25459
25645
|
|
|
25460
25646
|
// src/commands/ravendb/ravendbCollections.ts
|
|
25461
|
-
import
|
|
25647
|
+
import chalk187 from "chalk";
|
|
25462
25648
|
|
|
25463
25649
|
// src/commands/ravendb/ravenFetch.ts
|
|
25464
|
-
import
|
|
25650
|
+
import chalk185 from "chalk";
|
|
25465
25651
|
|
|
25466
25652
|
// src/commands/ravendb/getAccessToken.ts
|
|
25467
25653
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -25498,10 +25684,10 @@ ${errorText}`
|
|
|
25498
25684
|
|
|
25499
25685
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
25500
25686
|
import { execSync as execSync52 } from "child_process";
|
|
25501
|
-
import
|
|
25687
|
+
import chalk184 from "chalk";
|
|
25502
25688
|
function resolveOpSecret(reference) {
|
|
25503
25689
|
if (!reference.startsWith("op://")) {
|
|
25504
|
-
console.error(
|
|
25690
|
+
console.error(chalk184.red(`Invalid secret reference: must start with op://`));
|
|
25505
25691
|
process.exit(1);
|
|
25506
25692
|
}
|
|
25507
25693
|
try {
|
|
@@ -25511,7 +25697,7 @@ function resolveOpSecret(reference) {
|
|
|
25511
25697
|
}).trim();
|
|
25512
25698
|
} catch {
|
|
25513
25699
|
console.error(
|
|
25514
|
-
|
|
25700
|
+
chalk184.red(
|
|
25515
25701
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
25516
25702
|
)
|
|
25517
25703
|
);
|
|
@@ -25538,7 +25724,7 @@ async function ravenFetch(connection, path80) {
|
|
|
25538
25724
|
if (!response.ok) {
|
|
25539
25725
|
const body = await response.text();
|
|
25540
25726
|
console.error(
|
|
25541
|
-
|
|
25727
|
+
chalk185.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
25542
25728
|
);
|
|
25543
25729
|
console.error(body.substring(0, 500));
|
|
25544
25730
|
process.exit(1);
|
|
@@ -25547,7 +25733,7 @@ async function ravenFetch(connection, path80) {
|
|
|
25547
25733
|
}
|
|
25548
25734
|
|
|
25549
25735
|
// src/commands/ravendb/resolveConnection.ts
|
|
25550
|
-
import
|
|
25736
|
+
import chalk186 from "chalk";
|
|
25551
25737
|
function loadRavendb() {
|
|
25552
25738
|
const raw = loadGlobalConfigRaw();
|
|
25553
25739
|
const ravendb = raw.ravendb;
|
|
@@ -25561,7 +25747,7 @@ function resolveConnection(name) {
|
|
|
25561
25747
|
const connectionName = name ?? defaultConnection;
|
|
25562
25748
|
if (!connectionName) {
|
|
25563
25749
|
console.error(
|
|
25564
|
-
|
|
25750
|
+
chalk186.red(
|
|
25565
25751
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
25566
25752
|
)
|
|
25567
25753
|
);
|
|
@@ -25569,7 +25755,7 @@ function resolveConnection(name) {
|
|
|
25569
25755
|
}
|
|
25570
25756
|
const connection = connections.find((c) => c.name === connectionName);
|
|
25571
25757
|
if (!connection) {
|
|
25572
|
-
console.error(
|
|
25758
|
+
console.error(chalk186.red(`Connection "${connectionName}" not found.`));
|
|
25573
25759
|
console.error(
|
|
25574
25760
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
25575
25761
|
);
|
|
@@ -25600,15 +25786,15 @@ async function ravendbCollections(connectionName) {
|
|
|
25600
25786
|
return;
|
|
25601
25787
|
}
|
|
25602
25788
|
for (const c of collections) {
|
|
25603
|
-
console.log(`${
|
|
25789
|
+
console.log(`${chalk187.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
25604
25790
|
}
|
|
25605
25791
|
}
|
|
25606
25792
|
|
|
25607
25793
|
// src/commands/ravendb/ravendbQuery.ts
|
|
25608
|
-
import
|
|
25794
|
+
import chalk189 from "chalk";
|
|
25609
25795
|
|
|
25610
25796
|
// src/commands/ravendb/fetchAllPages.ts
|
|
25611
|
-
import
|
|
25797
|
+
import chalk188 from "chalk";
|
|
25612
25798
|
|
|
25613
25799
|
// src/commands/ravendb/buildQueryPath.ts
|
|
25614
25800
|
function buildQueryPath(opts) {
|
|
@@ -25646,7 +25832,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25646
25832
|
allResults.push(...results);
|
|
25647
25833
|
start3 += results.length;
|
|
25648
25834
|
process.stderr.write(
|
|
25649
|
-
`\r${
|
|
25835
|
+
`\r${chalk188.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
25650
25836
|
);
|
|
25651
25837
|
if (start3 >= totalResults) break;
|
|
25652
25838
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -25661,7 +25847,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25661
25847
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
25662
25848
|
const resolved = resolveArgs(connectionName, collection);
|
|
25663
25849
|
if (!resolved.collection && !options2.query) {
|
|
25664
|
-
console.error(
|
|
25850
|
+
console.error(chalk189.red("Provide a collection name or --query filter."));
|
|
25665
25851
|
process.exit(1);
|
|
25666
25852
|
}
|
|
25667
25853
|
const { collection: col } = resolved;
|
|
@@ -25700,7 +25886,7 @@ import { spawn as spawn6 } from "child_process";
|
|
|
25700
25886
|
import * as path42 from "path";
|
|
25701
25887
|
|
|
25702
25888
|
// src/commands/refactor/logViolations.ts
|
|
25703
|
-
import
|
|
25889
|
+
import chalk190 from "chalk";
|
|
25704
25890
|
var DEFAULT_MAX_LINES2 = 100;
|
|
25705
25891
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
25706
25892
|
if (violations.length === 0) {
|
|
@@ -25709,43 +25895,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
|
25709
25895
|
}
|
|
25710
25896
|
return;
|
|
25711
25897
|
}
|
|
25712
|
-
console.error(
|
|
25898
|
+
console.error(chalk190.red(`
|
|
25713
25899
|
Refactor check failed:
|
|
25714
25900
|
`));
|
|
25715
|
-
console.error(
|
|
25901
|
+
console.error(chalk190.red(` The following files exceed ${maxLines} lines:
|
|
25716
25902
|
`));
|
|
25717
25903
|
for (const violation of violations) {
|
|
25718
|
-
console.error(
|
|
25904
|
+
console.error(chalk190.red(` ${violation.file} (${violation.lines} lines)`));
|
|
25719
25905
|
}
|
|
25720
25906
|
console.error(
|
|
25721
|
-
|
|
25907
|
+
chalk190.yellow(
|
|
25722
25908
|
`
|
|
25723
25909
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
25724
25910
|
way to refactor it, ignore it with:
|
|
25725
25911
|
`
|
|
25726
25912
|
)
|
|
25727
25913
|
);
|
|
25728
|
-
console.error(
|
|
25914
|
+
console.error(chalk190.gray(` assist refactor ignore <file>
|
|
25729
25915
|
`));
|
|
25730
25916
|
if (process.env.CLAUDECODE) {
|
|
25731
|
-
console.error(
|
|
25917
|
+
console.error(chalk190.cyan(`
|
|
25732
25918
|
## Extracting Code to New Files
|
|
25733
25919
|
`));
|
|
25734
25920
|
console.error(
|
|
25735
|
-
|
|
25921
|
+
chalk190.cyan(
|
|
25736
25922
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
25737
25923
|
`
|
|
25738
25924
|
)
|
|
25739
25925
|
);
|
|
25740
25926
|
console.error(
|
|
25741
|
-
|
|
25927
|
+
chalk190.cyan(
|
|
25742
25928
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
25743
25929
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
25744
25930
|
`
|
|
25745
25931
|
)
|
|
25746
25932
|
);
|
|
25747
25933
|
console.error(
|
|
25748
|
-
|
|
25934
|
+
chalk190.cyan(
|
|
25749
25935
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
25750
25936
|
domains, move it to a common/shared folder.
|
|
25751
25937
|
`
|
|
@@ -25901,7 +26087,7 @@ async function check(pattern2, options2) {
|
|
|
25901
26087
|
|
|
25902
26088
|
// src/commands/refactor/extract/index.ts
|
|
25903
26089
|
import path50 from "path";
|
|
25904
|
-
import
|
|
26090
|
+
import chalk193 from "chalk";
|
|
25905
26091
|
|
|
25906
26092
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
25907
26093
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -26500,23 +26686,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
26500
26686
|
|
|
26501
26687
|
// src/commands/refactor/extract/displayPlan.ts
|
|
26502
26688
|
import path46 from "path";
|
|
26503
|
-
import
|
|
26689
|
+
import chalk191 from "chalk";
|
|
26504
26690
|
function section2(title) {
|
|
26505
26691
|
return `
|
|
26506
|
-
${
|
|
26692
|
+
${chalk191.cyan(title)}`;
|
|
26507
26693
|
}
|
|
26508
26694
|
function displayImporters(plan2, cwd) {
|
|
26509
26695
|
if (plan2.importersToUpdate.length === 0) return;
|
|
26510
26696
|
console.log(section2("Update importers:"));
|
|
26511
26697
|
for (const imp of plan2.importersToUpdate) {
|
|
26512
26698
|
const rel = path46.relative(cwd, imp.file.getFilePath());
|
|
26513
|
-
console.log(` ${
|
|
26699
|
+
console.log(` ${chalk191.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
26514
26700
|
}
|
|
26515
26701
|
}
|
|
26516
26702
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
26517
|
-
console.log(
|
|
26703
|
+
console.log(chalk191.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
26518
26704
|
`));
|
|
26519
|
-
console.log(` ${
|
|
26705
|
+
console.log(` ${chalk191.cyan("Functions to move:")}`);
|
|
26520
26706
|
for (const name of plan2.extractedNames) {
|
|
26521
26707
|
console.log(` ${name}`);
|
|
26522
26708
|
}
|
|
@@ -26550,7 +26736,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
26550
26736
|
|
|
26551
26737
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
26552
26738
|
import path49 from "path";
|
|
26553
|
-
import
|
|
26739
|
+
import chalk192 from "chalk";
|
|
26554
26740
|
import { Project as Project4 } from "ts-morph";
|
|
26555
26741
|
|
|
26556
26742
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -26642,7 +26828,7 @@ function loadProjectFile(file) {
|
|
|
26642
26828
|
});
|
|
26643
26829
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
26644
26830
|
if (!sourceFile) {
|
|
26645
|
-
console.log(
|
|
26831
|
+
console.log(chalk192.red(`File not found in project: ${file}`));
|
|
26646
26832
|
process.exit(1);
|
|
26647
26833
|
}
|
|
26648
26834
|
return { project, sourceFile };
|
|
@@ -26665,19 +26851,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
26665
26851
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
26666
26852
|
if (options2.apply) {
|
|
26667
26853
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
26668
|
-
console.log(
|
|
26854
|
+
console.log(chalk193.green("\nExtraction complete"));
|
|
26669
26855
|
} else {
|
|
26670
|
-
console.log(
|
|
26856
|
+
console.log(chalk193.dim("\nDry run. Use --apply to execute."));
|
|
26671
26857
|
}
|
|
26672
26858
|
}
|
|
26673
26859
|
|
|
26674
26860
|
// src/commands/refactor/ignore.ts
|
|
26675
26861
|
import fs33 from "fs";
|
|
26676
|
-
import
|
|
26862
|
+
import chalk194 from "chalk";
|
|
26677
26863
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
26678
26864
|
function ignore2(file) {
|
|
26679
26865
|
if (!fs33.existsSync(file)) {
|
|
26680
|
-
console.error(
|
|
26866
|
+
console.error(chalk194.red(`Error: File does not exist: ${file}`));
|
|
26681
26867
|
process.exit(1);
|
|
26682
26868
|
}
|
|
26683
26869
|
const content = fs33.readFileSync(file, "utf8");
|
|
@@ -26693,7 +26879,7 @@ function ignore2(file) {
|
|
|
26693
26879
|
fs33.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
26694
26880
|
}
|
|
26695
26881
|
console.log(
|
|
26696
|
-
|
|
26882
|
+
chalk194.green(
|
|
26697
26883
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
26698
26884
|
)
|
|
26699
26885
|
);
|
|
@@ -26702,12 +26888,12 @@ function ignore2(file) {
|
|
|
26702
26888
|
// src/commands/refactor/rename/index.ts
|
|
26703
26889
|
import fs36 from "fs";
|
|
26704
26890
|
import path55 from "path";
|
|
26705
|
-
import
|
|
26891
|
+
import chalk197 from "chalk";
|
|
26706
26892
|
|
|
26707
26893
|
// src/commands/refactor/rename/applyRename.ts
|
|
26708
26894
|
import fs35 from "fs";
|
|
26709
26895
|
import path52 from "path";
|
|
26710
|
-
import
|
|
26896
|
+
import chalk195 from "chalk";
|
|
26711
26897
|
|
|
26712
26898
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
26713
26899
|
import path51 from "path";
|
|
@@ -26812,13 +26998,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
26812
26998
|
const updatedContents = applyRewrites(rewrites);
|
|
26813
26999
|
for (const [file, content] of updatedContents) {
|
|
26814
27000
|
fs35.writeFileSync(file, content, "utf8");
|
|
26815
|
-
console.log(
|
|
27001
|
+
console.log(chalk195.cyan(` Updated imports in ${path52.relative(cwd, file)}`));
|
|
26816
27002
|
}
|
|
26817
27003
|
const destDir = path52.dirname(destPath);
|
|
26818
27004
|
if (!fs35.existsSync(destDir)) fs35.mkdirSync(destDir, { recursive: true });
|
|
26819
27005
|
fs35.renameSync(sourcePath, destPath);
|
|
26820
27006
|
console.log(
|
|
26821
|
-
|
|
27007
|
+
chalk195.white(
|
|
26822
27008
|
` Moved ${path52.relative(cwd, sourcePath)} \u2192 ${path52.relative(cwd, destPath)}`
|
|
26823
27009
|
)
|
|
26824
27010
|
);
|
|
@@ -26905,16 +27091,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
26905
27091
|
|
|
26906
27092
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
26907
27093
|
import path54 from "path";
|
|
26908
|
-
import
|
|
27094
|
+
import chalk196 from "chalk";
|
|
26909
27095
|
function printRenamePreview(rewrites, cwd) {
|
|
26910
27096
|
for (const rewrite of rewrites) {
|
|
26911
27097
|
console.log(
|
|
26912
|
-
|
|
27098
|
+
chalk196.dim(
|
|
26913
27099
|
` ${path54.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
26914
27100
|
)
|
|
26915
27101
|
);
|
|
26916
27102
|
}
|
|
26917
|
-
console.log(
|
|
27103
|
+
console.log(chalk196.dim("Dry run. Use --apply to execute."));
|
|
26918
27104
|
}
|
|
26919
27105
|
|
|
26920
27106
|
// src/commands/refactor/rename/index.ts
|
|
@@ -26925,20 +27111,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26925
27111
|
const relSource = path55.relative(cwd, sourcePath);
|
|
26926
27112
|
const relDest = path55.relative(cwd, destPath);
|
|
26927
27113
|
if (!fs36.existsSync(sourcePath)) {
|
|
26928
|
-
console.log(
|
|
27114
|
+
console.log(chalk197.red(`File not found: ${source}`));
|
|
26929
27115
|
process.exit(1);
|
|
26930
27116
|
}
|
|
26931
27117
|
if (destPath !== sourcePath && fs36.existsSync(destPath)) {
|
|
26932
|
-
console.log(
|
|
27118
|
+
console.log(chalk197.red(`Destination already exists: ${destination}`));
|
|
26933
27119
|
process.exit(1);
|
|
26934
27120
|
}
|
|
26935
|
-
console.log(
|
|
26936
|
-
console.log(
|
|
26937
|
-
console.log(
|
|
27121
|
+
console.log(chalk197.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
27122
|
+
console.log(chalk197.dim("Loading project..."));
|
|
27123
|
+
console.log(chalk197.dim("Scanning imports across the project..."));
|
|
26938
27124
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
26939
27125
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
26940
27126
|
console.log(
|
|
26941
|
-
|
|
27127
|
+
chalk197.dim(
|
|
26942
27128
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
26943
27129
|
)
|
|
26944
27130
|
);
|
|
@@ -26947,11 +27133,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26947
27133
|
return;
|
|
26948
27134
|
}
|
|
26949
27135
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
26950
|
-
console.log(
|
|
27136
|
+
console.log(chalk197.green("Done"));
|
|
26951
27137
|
}
|
|
26952
27138
|
|
|
26953
27139
|
// src/commands/refactor/renameSymbol/index.ts
|
|
26954
|
-
import
|
|
27140
|
+
import chalk198 from "chalk";
|
|
26955
27141
|
|
|
26956
27142
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
26957
27143
|
import { SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
@@ -26997,33 +27183,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
26997
27183
|
const { project, sourceFile } = loadProjectFile(file);
|
|
26998
27184
|
const symbol = findSymbol(sourceFile, oldName);
|
|
26999
27185
|
if (!symbol) {
|
|
27000
|
-
console.log(
|
|
27186
|
+
console.log(chalk198.red(`Symbol "${oldName}" not found in ${file}`));
|
|
27001
27187
|
process.exit(1);
|
|
27002
27188
|
}
|
|
27003
27189
|
const grouped = groupReferences(symbol, cwd);
|
|
27004
27190
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
27005
27191
|
console.log(
|
|
27006
|
-
|
|
27192
|
+
chalk198.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
27007
27193
|
`)
|
|
27008
27194
|
);
|
|
27009
27195
|
for (const [refFile, lines2] of grouped) {
|
|
27010
27196
|
console.log(
|
|
27011
|
-
` ${
|
|
27197
|
+
` ${chalk198.dim(refFile)}: lines ${chalk198.cyan(lines2.join(", "))}`
|
|
27012
27198
|
);
|
|
27013
27199
|
}
|
|
27014
27200
|
if (options2.apply) {
|
|
27015
27201
|
symbol.rename(newName);
|
|
27016
27202
|
await project.save();
|
|
27017
|
-
console.log(
|
|
27203
|
+
console.log(chalk198.green(`
|
|
27018
27204
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
27019
27205
|
} else {
|
|
27020
|
-
console.log(
|
|
27206
|
+
console.log(chalk198.dim("\nDry run. Use --apply to execute."));
|
|
27021
27207
|
}
|
|
27022
27208
|
}
|
|
27023
27209
|
|
|
27024
27210
|
// src/commands/refactor/restructure/index.ts
|
|
27025
27211
|
import path63 from "path";
|
|
27026
|
-
import
|
|
27212
|
+
import chalk201 from "chalk";
|
|
27027
27213
|
|
|
27028
27214
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
27029
27215
|
import path57 from "path";
|
|
@@ -27102,50 +27288,50 @@ function clusterFiles(graph) {
|
|
|
27102
27288
|
|
|
27103
27289
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
27104
27290
|
import path59 from "path";
|
|
27105
|
-
import
|
|
27291
|
+
import chalk199 from "chalk";
|
|
27106
27292
|
function relPath(filePath) {
|
|
27107
27293
|
return path59.relative(process.cwd(), filePath);
|
|
27108
27294
|
}
|
|
27109
27295
|
function displayMoves(plan2) {
|
|
27110
27296
|
if (plan2.moves.length === 0) return;
|
|
27111
|
-
console.log(
|
|
27297
|
+
console.log(chalk199.bold("\nFile moves:"));
|
|
27112
27298
|
for (const move2 of plan2.moves) {
|
|
27113
27299
|
console.log(
|
|
27114
|
-
` ${
|
|
27300
|
+
` ${chalk199.red(relPath(move2.from))} \u2192 ${chalk199.green(relPath(move2.to))}`
|
|
27115
27301
|
);
|
|
27116
|
-
console.log(
|
|
27302
|
+
console.log(chalk199.dim(` ${move2.reason}`));
|
|
27117
27303
|
}
|
|
27118
27304
|
}
|
|
27119
27305
|
function displayRewrites(rewrites) {
|
|
27120
27306
|
if (rewrites.length === 0) return;
|
|
27121
27307
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
27122
|
-
console.log(
|
|
27308
|
+
console.log(chalk199.bold(`
|
|
27123
27309
|
Import rewrites (${affectedFiles.size} files):`));
|
|
27124
27310
|
for (const file of affectedFiles) {
|
|
27125
|
-
console.log(` ${
|
|
27311
|
+
console.log(` ${chalk199.cyan(relPath(file))}:`);
|
|
27126
27312
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
27127
27313
|
(r) => r.file === file
|
|
27128
27314
|
)) {
|
|
27129
27315
|
console.log(
|
|
27130
|
-
` ${
|
|
27316
|
+
` ${chalk199.red(`"${oldSpecifier}"`)} \u2192 ${chalk199.green(`"${newSpecifier}"`)}`
|
|
27131
27317
|
);
|
|
27132
27318
|
}
|
|
27133
27319
|
}
|
|
27134
27320
|
}
|
|
27135
27321
|
function displayPlan2(plan2) {
|
|
27136
27322
|
if (plan2.warnings.length > 0) {
|
|
27137
|
-
console.log(
|
|
27138
|
-
for (const w of plan2.warnings) console.log(
|
|
27323
|
+
console.log(chalk199.yellow("\nWarnings:"));
|
|
27324
|
+
for (const w of plan2.warnings) console.log(chalk199.yellow(` ${w}`));
|
|
27139
27325
|
}
|
|
27140
27326
|
if (plan2.newDirectories.length > 0) {
|
|
27141
|
-
console.log(
|
|
27327
|
+
console.log(chalk199.bold("\nNew directories:"));
|
|
27142
27328
|
for (const dir of plan2.newDirectories)
|
|
27143
|
-
console.log(
|
|
27329
|
+
console.log(chalk199.green(` ${dir}/`));
|
|
27144
27330
|
}
|
|
27145
27331
|
displayMoves(plan2);
|
|
27146
27332
|
displayRewrites(plan2.rewrites);
|
|
27147
27333
|
console.log(
|
|
27148
|
-
|
|
27334
|
+
chalk199.dim(
|
|
27149
27335
|
`
|
|
27150
27336
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
27151
27337
|
)
|
|
@@ -27155,18 +27341,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
27155
27341
|
// src/commands/refactor/restructure/executePlan.ts
|
|
27156
27342
|
import fs37 from "fs";
|
|
27157
27343
|
import path60 from "path";
|
|
27158
|
-
import
|
|
27344
|
+
import chalk200 from "chalk";
|
|
27159
27345
|
function executePlan(plan2) {
|
|
27160
27346
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
27161
27347
|
for (const [file, content] of updatedContents) {
|
|
27162
27348
|
fs37.writeFileSync(file, content, "utf8");
|
|
27163
27349
|
console.log(
|
|
27164
|
-
|
|
27350
|
+
chalk200.cyan(` Rewrote imports in ${path60.relative(process.cwd(), file)}`)
|
|
27165
27351
|
);
|
|
27166
27352
|
}
|
|
27167
27353
|
for (const dir of plan2.newDirectories) {
|
|
27168
27354
|
fs37.mkdirSync(dir, { recursive: true });
|
|
27169
|
-
console.log(
|
|
27355
|
+
console.log(chalk200.green(` Created ${path60.relative(process.cwd(), dir)}/`));
|
|
27170
27356
|
}
|
|
27171
27357
|
for (const move2 of plan2.moves) {
|
|
27172
27358
|
const targetDir = path60.dirname(move2.to);
|
|
@@ -27175,7 +27361,7 @@ function executePlan(plan2) {
|
|
|
27175
27361
|
}
|
|
27176
27362
|
fs37.renameSync(move2.from, move2.to);
|
|
27177
27363
|
console.log(
|
|
27178
|
-
|
|
27364
|
+
chalk200.white(
|
|
27179
27365
|
` Moved ${path60.relative(process.cwd(), move2.from)} \u2192 ${path60.relative(process.cwd(), move2.to)}`
|
|
27180
27366
|
)
|
|
27181
27367
|
);
|
|
@@ -27190,7 +27376,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
27190
27376
|
if (entries.length === 0) {
|
|
27191
27377
|
fs37.rmdirSync(dir);
|
|
27192
27378
|
console.log(
|
|
27193
|
-
|
|
27379
|
+
chalk200.dim(
|
|
27194
27380
|
` Removed empty directory ${path60.relative(process.cwd(), dir)}`
|
|
27195
27381
|
)
|
|
27196
27382
|
);
|
|
@@ -27323,22 +27509,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
27323
27509
|
const targetPattern = pattern2 ?? "src";
|
|
27324
27510
|
const files = findSourceFiles2(targetPattern);
|
|
27325
27511
|
if (files.length === 0) {
|
|
27326
|
-
console.log(
|
|
27512
|
+
console.log(chalk201.yellow("No files found matching pattern"));
|
|
27327
27513
|
return;
|
|
27328
27514
|
}
|
|
27329
27515
|
const tsConfigPath = findTsConfig(path63.resolve(files[0]));
|
|
27330
27516
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
27331
27517
|
if (plan2.moves.length === 0) {
|
|
27332
|
-
console.log(
|
|
27518
|
+
console.log(chalk201.green("No restructuring needed"));
|
|
27333
27519
|
return;
|
|
27334
27520
|
}
|
|
27335
27521
|
displayPlan2(plan2);
|
|
27336
27522
|
if (options2.apply) {
|
|
27337
|
-
console.log(
|
|
27523
|
+
console.log(chalk201.bold("\nApplying changes..."));
|
|
27338
27524
|
executePlan(plan2);
|
|
27339
|
-
console.log(
|
|
27525
|
+
console.log(chalk201.green("\nRestructuring complete"));
|
|
27340
27526
|
} else {
|
|
27341
|
-
console.log(
|
|
27527
|
+
console.log(chalk201.dim("\nDry run. Use --apply to execute."));
|
|
27342
27528
|
}
|
|
27343
27529
|
}
|
|
27344
27530
|
|
|
@@ -27379,10 +27565,10 @@ function registerRefactor(program2) {
|
|
|
27379
27565
|
}
|
|
27380
27566
|
|
|
27381
27567
|
// src/commands/review/checkoutOnlySession.ts
|
|
27382
|
-
import { randomUUID as
|
|
27568
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
27383
27569
|
async function checkoutOnlySession(number) {
|
|
27384
27570
|
await checkoutPr(number);
|
|
27385
|
-
const claudeSessionId =
|
|
27571
|
+
const claudeSessionId = randomUUID16();
|
|
27386
27572
|
emitActivity({ kind: "command", name: "review", claudeSessionId });
|
|
27387
27573
|
const { done: done2 } = spawnClaude("", {
|
|
27388
27574
|
permissionMode: "acceptEdits",
|
|
@@ -27865,15 +28051,15 @@ function runReviewSubmission(mutation, body) {
|
|
|
27865
28051
|
}
|
|
27866
28052
|
|
|
27867
28053
|
// src/commands/review/submitBodyOnlyReview.ts
|
|
27868
|
-
var
|
|
28054
|
+
var MUTATION3 = `mutation($prId: ID!, $body: String) { addPullRequestReview(input: { pullRequestId: $prId, event: COMMENT, body: $body }) { pullRequestReview { id } } }`;
|
|
27869
28055
|
function submitBodyOnlyReview(body) {
|
|
27870
|
-
runReviewSubmission(
|
|
28056
|
+
runReviewSubmission(MUTATION3, body);
|
|
27871
28057
|
}
|
|
27872
28058
|
|
|
27873
28059
|
// src/commands/review/submitPendingReview.ts
|
|
27874
|
-
var
|
|
28060
|
+
var MUTATION4 = `mutation($prId: ID!, $body: String) { submitPullRequestReview(input: { pullRequestId: $prId, event: COMMENT, body: $body }) { pullRequestReview { id } } }`;
|
|
27875
28061
|
function submitPendingReview(body) {
|
|
27876
|
-
runReviewSubmission(
|
|
28062
|
+
runReviewSubmission(MUTATION4, body);
|
|
27877
28063
|
}
|
|
27878
28064
|
|
|
27879
28065
|
// src/commands/review/postAndMaybeSubmit.ts
|
|
@@ -27996,18 +28182,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
27996
28182
|
}
|
|
27997
28183
|
|
|
27998
28184
|
// src/commands/review/warnOutOfDiff.ts
|
|
27999
|
-
import
|
|
28185
|
+
import chalk202 from "chalk";
|
|
28000
28186
|
function warnOutOfDiff(outOfDiff) {
|
|
28001
28187
|
if (outOfDiff.length === 0) return;
|
|
28002
28188
|
console.warn(
|
|
28003
|
-
|
|
28189
|
+
chalk202.yellow(
|
|
28004
28190
|
`Moved ${outOfDiff.length} finding(s) whose lines fall outside the PR diff into the review body (GitHub cannot anchor a comment on these):`
|
|
28005
28191
|
)
|
|
28006
28192
|
);
|
|
28007
28193
|
for (const finding of outOfDiff) {
|
|
28008
28194
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
28009
28195
|
console.warn(
|
|
28010
|
-
` ${
|
|
28196
|
+
` ${chalk202.yellow("\xB7")} ${finding.title} ${chalk202.dim(
|
|
28011
28197
|
`(${finding.file}:${range})`
|
|
28012
28198
|
)}`
|
|
28013
28199
|
);
|
|
@@ -28031,18 +28217,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
28031
28217
|
}
|
|
28032
28218
|
|
|
28033
28219
|
// src/commands/review/warnUnlocated.ts
|
|
28034
|
-
import
|
|
28220
|
+
import chalk203 from "chalk";
|
|
28035
28221
|
function warnUnlocated(unlocated) {
|
|
28036
28222
|
if (unlocated.length === 0) return;
|
|
28037
28223
|
console.warn(
|
|
28038
|
-
|
|
28224
|
+
chalk203.yellow(
|
|
28039
28225
|
`Moved ${unlocated.length} finding(s) without a parseable file:line into the review body:`
|
|
28040
28226
|
)
|
|
28041
28227
|
);
|
|
28042
28228
|
for (const finding of unlocated) {
|
|
28043
|
-
const where = finding.location ||
|
|
28229
|
+
const where = finding.location || chalk203.dim("missing");
|
|
28044
28230
|
console.warn(
|
|
28045
|
-
` ${
|
|
28231
|
+
` ${chalk203.yellow("\xB7")} ${finding.title} ${chalk203.dim(`(${where})`)}`
|
|
28046
28232
|
);
|
|
28047
28233
|
}
|
|
28048
28234
|
}
|
|
@@ -29297,7 +29483,7 @@ function registerReview(program2) {
|
|
|
29297
29483
|
}
|
|
29298
29484
|
|
|
29299
29485
|
// src/commands/seq/seqAuth.ts
|
|
29300
|
-
import
|
|
29486
|
+
import chalk205 from "chalk";
|
|
29301
29487
|
|
|
29302
29488
|
// src/commands/seq/loadConnections.ts
|
|
29303
29489
|
function loadConnections2() {
|
|
@@ -29326,10 +29512,10 @@ function setDefaultConnection(name) {
|
|
|
29326
29512
|
}
|
|
29327
29513
|
|
|
29328
29514
|
// src/shared/assertUniqueName.ts
|
|
29329
|
-
import
|
|
29515
|
+
import chalk204 from "chalk";
|
|
29330
29516
|
function assertUniqueName(existingNames, name) {
|
|
29331
29517
|
if (existingNames.includes(name)) {
|
|
29332
|
-
console.error(
|
|
29518
|
+
console.error(chalk204.red(`Connection "${name}" already exists.`));
|
|
29333
29519
|
process.exit(1);
|
|
29334
29520
|
}
|
|
29335
29521
|
}
|
|
@@ -29347,16 +29533,16 @@ async function promptConnection2(existingNames) {
|
|
|
29347
29533
|
var seqAuth = createConnectionAuth({
|
|
29348
29534
|
load: loadConnections2,
|
|
29349
29535
|
save: saveConnections2,
|
|
29350
|
-
format: (c) => `${
|
|
29536
|
+
format: (c) => `${chalk205.bold(c.name)} ${c.url}`,
|
|
29351
29537
|
promptNew: promptConnection2,
|
|
29352
29538
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
29353
29539
|
});
|
|
29354
29540
|
|
|
29355
29541
|
// src/commands/seq/seqQuery.ts
|
|
29356
|
-
import
|
|
29542
|
+
import chalk209 from "chalk";
|
|
29357
29543
|
|
|
29358
29544
|
// src/commands/seq/fetchSeq.ts
|
|
29359
|
-
import
|
|
29545
|
+
import chalk206 from "chalk";
|
|
29360
29546
|
async function fetchSeq(conn, path80, params) {
|
|
29361
29547
|
const url = `${conn.url}${path80}?${params}`;
|
|
29362
29548
|
const response = await fetch(url, {
|
|
@@ -29367,7 +29553,7 @@ async function fetchSeq(conn, path80, params) {
|
|
|
29367
29553
|
});
|
|
29368
29554
|
if (!response.ok) {
|
|
29369
29555
|
const body = await response.text();
|
|
29370
|
-
console.error(
|
|
29556
|
+
console.error(chalk206.red(`Seq returned ${response.status}: ${body}`));
|
|
29371
29557
|
process.exit(1);
|
|
29372
29558
|
}
|
|
29373
29559
|
return response;
|
|
@@ -29426,23 +29612,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
29426
29612
|
}
|
|
29427
29613
|
|
|
29428
29614
|
// src/commands/seq/formatEvent.ts
|
|
29429
|
-
import
|
|
29615
|
+
import chalk207 from "chalk";
|
|
29430
29616
|
function levelColor(level) {
|
|
29431
29617
|
switch (level) {
|
|
29432
29618
|
case "Fatal":
|
|
29433
|
-
return
|
|
29619
|
+
return chalk207.bgRed.white;
|
|
29434
29620
|
case "Error":
|
|
29435
|
-
return
|
|
29621
|
+
return chalk207.red;
|
|
29436
29622
|
case "Warning":
|
|
29437
|
-
return
|
|
29623
|
+
return chalk207.yellow;
|
|
29438
29624
|
case "Information":
|
|
29439
|
-
return
|
|
29625
|
+
return chalk207.cyan;
|
|
29440
29626
|
case "Debug":
|
|
29441
|
-
return
|
|
29627
|
+
return chalk207.gray;
|
|
29442
29628
|
case "Verbose":
|
|
29443
|
-
return
|
|
29629
|
+
return chalk207.dim;
|
|
29444
29630
|
default:
|
|
29445
|
-
return
|
|
29631
|
+
return chalk207.white;
|
|
29446
29632
|
}
|
|
29447
29633
|
}
|
|
29448
29634
|
function levelAbbrev(level) {
|
|
@@ -29483,12 +29669,12 @@ function formatTimestamp(iso) {
|
|
|
29483
29669
|
function formatEvent(event) {
|
|
29484
29670
|
const color = levelColor(event.Level);
|
|
29485
29671
|
const abbrev = levelAbbrev(event.Level);
|
|
29486
|
-
const ts8 =
|
|
29672
|
+
const ts8 = chalk207.dim(formatTimestamp(event.Timestamp));
|
|
29487
29673
|
const msg = renderMessage(event);
|
|
29488
29674
|
const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
29489
29675
|
if (event.Exception) {
|
|
29490
29676
|
for (const line of event.Exception.split("\n")) {
|
|
29491
|
-
lines2.push(
|
|
29677
|
+
lines2.push(chalk207.red(` ${line}`));
|
|
29492
29678
|
}
|
|
29493
29679
|
}
|
|
29494
29680
|
return lines2.join("\n");
|
|
@@ -29521,11 +29707,11 @@ function rejectTimestampFilter(filter) {
|
|
|
29521
29707
|
}
|
|
29522
29708
|
|
|
29523
29709
|
// src/shared/resolveNamedConnection.ts
|
|
29524
|
-
import
|
|
29710
|
+
import chalk208 from "chalk";
|
|
29525
29711
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
29526
29712
|
if (connections.length === 0) {
|
|
29527
29713
|
console.error(
|
|
29528
|
-
|
|
29714
|
+
chalk208.red(
|
|
29529
29715
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
29530
29716
|
)
|
|
29531
29717
|
);
|
|
@@ -29534,7 +29720,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
29534
29720
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
29535
29721
|
const connection = connections.find((c) => c.name === target);
|
|
29536
29722
|
if (!connection) {
|
|
29537
|
-
console.error(
|
|
29723
|
+
console.error(chalk208.red(`${kind} connection "${target}" not found.`));
|
|
29538
29724
|
process.exit(1);
|
|
29539
29725
|
}
|
|
29540
29726
|
return connection;
|
|
@@ -29563,7 +29749,7 @@ async function seqQuery(filter, options2) {
|
|
|
29563
29749
|
new URLSearchParams({ filter, count: String(count8) })
|
|
29564
29750
|
);
|
|
29565
29751
|
if (events.length === 0) {
|
|
29566
|
-
console.log(
|
|
29752
|
+
console.log(chalk209.yellow("No events found."));
|
|
29567
29753
|
return;
|
|
29568
29754
|
}
|
|
29569
29755
|
if (options2.json) {
|
|
@@ -29574,11 +29760,11 @@ async function seqQuery(filter, options2) {
|
|
|
29574
29760
|
for (const event of chronological) {
|
|
29575
29761
|
console.log(formatEvent(event));
|
|
29576
29762
|
}
|
|
29577
|
-
console.log(
|
|
29763
|
+
console.log(chalk209.dim(`
|
|
29578
29764
|
${events.length} events`));
|
|
29579
29765
|
if (events.length >= count8) {
|
|
29580
29766
|
console.log(
|
|
29581
|
-
|
|
29767
|
+
chalk209.yellow(
|
|
29582
29768
|
`Results limited to ${count8}. Use --count to retrieve more.`
|
|
29583
29769
|
)
|
|
29584
29770
|
);
|
|
@@ -29586,10 +29772,10 @@ ${events.length} events`));
|
|
|
29586
29772
|
}
|
|
29587
29773
|
|
|
29588
29774
|
// src/shared/setNamedDefaultConnection.ts
|
|
29589
|
-
import
|
|
29775
|
+
import chalk210 from "chalk";
|
|
29590
29776
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
29591
29777
|
if (!connections.find((c) => c.name === name)) {
|
|
29592
|
-
console.error(
|
|
29778
|
+
console.error(chalk210.red(`Connection "${name}" not found.`));
|
|
29593
29779
|
process.exit(1);
|
|
29594
29780
|
}
|
|
29595
29781
|
setDefault(name);
|
|
@@ -29638,7 +29824,7 @@ function registerSignal(program2) {
|
|
|
29638
29824
|
}
|
|
29639
29825
|
|
|
29640
29826
|
// src/commands/sql/sqlAuth.ts
|
|
29641
|
-
import
|
|
29827
|
+
import chalk212 from "chalk";
|
|
29642
29828
|
|
|
29643
29829
|
// src/commands/sql/loadConnections.ts
|
|
29644
29830
|
function loadConnections3() {
|
|
@@ -29667,7 +29853,7 @@ function setDefaultConnection2(name) {
|
|
|
29667
29853
|
}
|
|
29668
29854
|
|
|
29669
29855
|
// src/commands/sql/promptConnection.ts
|
|
29670
|
-
import
|
|
29856
|
+
import chalk211 from "chalk";
|
|
29671
29857
|
async function promptConnection3(existingNames) {
|
|
29672
29858
|
const name = await promptInput("name", "Connection name:", "default");
|
|
29673
29859
|
assertUniqueName(existingNames, name);
|
|
@@ -29675,7 +29861,7 @@ async function promptConnection3(existingNames) {
|
|
|
29675
29861
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
29676
29862
|
const port = Number.parseInt(portStr, 10);
|
|
29677
29863
|
if (!Number.isFinite(port)) {
|
|
29678
|
-
console.error(
|
|
29864
|
+
console.error(chalk211.red(`Invalid port "${portStr}".`));
|
|
29679
29865
|
process.exit(1);
|
|
29680
29866
|
}
|
|
29681
29867
|
const user = await promptInput("user", "User:");
|
|
@@ -29688,13 +29874,13 @@ async function promptConnection3(existingNames) {
|
|
|
29688
29874
|
var sqlAuth = createConnectionAuth({
|
|
29689
29875
|
load: loadConnections3,
|
|
29690
29876
|
save: saveConnections3,
|
|
29691
|
-
format: (c) => `${
|
|
29877
|
+
format: (c) => `${chalk212.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
29692
29878
|
promptNew: promptConnection3,
|
|
29693
29879
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
29694
29880
|
});
|
|
29695
29881
|
|
|
29696
29882
|
// src/commands/sql/printTable.ts
|
|
29697
|
-
import
|
|
29883
|
+
import chalk213 from "chalk";
|
|
29698
29884
|
function formatCell(value) {
|
|
29699
29885
|
if (value === null || value === void 0) return "";
|
|
29700
29886
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -29703,7 +29889,7 @@ function formatCell(value) {
|
|
|
29703
29889
|
}
|
|
29704
29890
|
function printTable(rows) {
|
|
29705
29891
|
if (rows.length === 0) {
|
|
29706
|
-
console.log(
|
|
29892
|
+
console.log(chalk213.yellow("(no rows)"));
|
|
29707
29893
|
return;
|
|
29708
29894
|
}
|
|
29709
29895
|
const columns = Object.keys(rows[0]);
|
|
@@ -29711,13 +29897,13 @@ function printTable(rows) {
|
|
|
29711
29897
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
29712
29898
|
);
|
|
29713
29899
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
29714
|
-
console.log(
|
|
29715
|
-
console.log(
|
|
29900
|
+
console.log(chalk213.dim(header));
|
|
29901
|
+
console.log(chalk213.dim("-".repeat(header.length)));
|
|
29716
29902
|
for (const row of rows) {
|
|
29717
29903
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
29718
29904
|
console.log(line);
|
|
29719
29905
|
}
|
|
29720
|
-
console.log(
|
|
29906
|
+
console.log(chalk213.dim(`
|
|
29721
29907
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
29722
29908
|
}
|
|
29723
29909
|
|
|
@@ -29777,7 +29963,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
29777
29963
|
}
|
|
29778
29964
|
|
|
29779
29965
|
// src/commands/sql/sqlMutate.ts
|
|
29780
|
-
import
|
|
29966
|
+
import chalk214 from "chalk";
|
|
29781
29967
|
|
|
29782
29968
|
// src/commands/sql/isMutation.ts
|
|
29783
29969
|
var MUTATION_KEYWORDS = [
|
|
@@ -29811,7 +29997,7 @@ function isMutation(sql25) {
|
|
|
29811
29997
|
async function sqlMutate(query, connectionName) {
|
|
29812
29998
|
if (!isMutation(query)) {
|
|
29813
29999
|
console.error(
|
|
29814
|
-
|
|
30000
|
+
chalk214.red(
|
|
29815
30001
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
29816
30002
|
)
|
|
29817
30003
|
);
|
|
@@ -29821,18 +30007,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
29821
30007
|
const pool = await sqlConnect(conn);
|
|
29822
30008
|
try {
|
|
29823
30009
|
const result = await pool.request().query(query);
|
|
29824
|
-
console.log(
|
|
30010
|
+
console.log(chalk214.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
29825
30011
|
} finally {
|
|
29826
30012
|
await pool.close();
|
|
29827
30013
|
}
|
|
29828
30014
|
}
|
|
29829
30015
|
|
|
29830
30016
|
// src/commands/sql/sqlQuery.ts
|
|
29831
|
-
import
|
|
30017
|
+
import chalk215 from "chalk";
|
|
29832
30018
|
async function sqlQuery(query, connectionName) {
|
|
29833
30019
|
if (isMutation(query)) {
|
|
29834
30020
|
console.error(
|
|
29835
|
-
|
|
30021
|
+
chalk215.red(
|
|
29836
30022
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
29837
30023
|
)
|
|
29838
30024
|
);
|
|
@@ -29847,7 +30033,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
29847
30033
|
printTable(rows);
|
|
29848
30034
|
} else {
|
|
29849
30035
|
console.log(
|
|
29850
|
-
|
|
30036
|
+
chalk215.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
29851
30037
|
);
|
|
29852
30038
|
}
|
|
29853
30039
|
} finally {
|
|
@@ -29992,7 +30178,7 @@ function reportPrune(label2, result, force) {
|
|
|
29992
30178
|
// src/commands/sync/syncClaudeMd.ts
|
|
29993
30179
|
import * as fs41 from "fs";
|
|
29994
30180
|
import * as path66 from "path";
|
|
29995
|
-
import
|
|
30181
|
+
import chalk216 from "chalk";
|
|
29996
30182
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
29997
30183
|
const source = path66.join(claudeDir, "CLAUDE.md");
|
|
29998
30184
|
const target = path66.join(targetBase, "CLAUDE.md");
|
|
@@ -30001,14 +30187,14 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
30001
30187
|
const targetContent = fs41.readFileSync(target, "utf8");
|
|
30002
30188
|
if (sourceContent !== targetContent) {
|
|
30003
30189
|
console.log(
|
|
30004
|
-
|
|
30190
|
+
chalk216.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
30005
30191
|
);
|
|
30006
30192
|
console.log();
|
|
30007
30193
|
printDiff(targetContent, sourceContent);
|
|
30008
30194
|
if (!options2?.yes) {
|
|
30009
30195
|
printAutoConfirmHint();
|
|
30010
30196
|
const confirm = await promptConfirm(
|
|
30011
|
-
|
|
30197
|
+
chalk216.red("Overwrite existing CLAUDE.md?"),
|
|
30012
30198
|
false
|
|
30013
30199
|
);
|
|
30014
30200
|
if (!confirm) {
|
|
@@ -30241,7 +30427,7 @@ function syncPi(claudeDir, options2) {
|
|
|
30241
30427
|
// src/commands/sync/syncSettings.ts
|
|
30242
30428
|
import * as fs47 from "fs";
|
|
30243
30429
|
import * as path73 from "path";
|
|
30244
|
-
import
|
|
30430
|
+
import chalk217 from "chalk";
|
|
30245
30431
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
30246
30432
|
const source = path73.join(claudeDir, "settings.json");
|
|
30247
30433
|
const target = path73.join(targetBase, "settings.json");
|
|
@@ -30260,7 +30446,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
30260
30446
|
if (mergedContent !== normalizedTarget) {
|
|
30261
30447
|
if (!options2?.yes) {
|
|
30262
30448
|
console.log(
|
|
30263
|
-
|
|
30449
|
+
chalk217.yellow(
|
|
30264
30450
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
30265
30451
|
)
|
|
30266
30452
|
);
|
|
@@ -30268,7 +30454,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
30268
30454
|
printDiff(targetContent, mergedContent);
|
|
30269
30455
|
printAutoConfirmHint();
|
|
30270
30456
|
const confirm = await promptConfirm(
|
|
30271
|
-
|
|
30457
|
+
chalk217.red("Overwrite existing settings.json?"),
|
|
30272
30458
|
false
|
|
30273
30459
|
);
|
|
30274
30460
|
if (!confirm) {
|
|
@@ -31695,7 +31881,7 @@ function registerWatch(program2) {
|
|
|
31695
31881
|
|
|
31696
31882
|
// src/commands/roam/auth.ts
|
|
31697
31883
|
import { randomBytes } from "crypto";
|
|
31698
|
-
import
|
|
31884
|
+
import chalk218 from "chalk";
|
|
31699
31885
|
|
|
31700
31886
|
// src/commands/roam/waitForCallback.ts
|
|
31701
31887
|
import { createServer as createServer3 } from "http";
|
|
@@ -31826,13 +32012,13 @@ async function auth() {
|
|
|
31826
32012
|
saveGlobalConfig(config);
|
|
31827
32013
|
const state = randomBytes(16).toString("hex");
|
|
31828
32014
|
console.log(
|
|
31829
|
-
|
|
32015
|
+
chalk218.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
31830
32016
|
);
|
|
31831
|
-
console.log(
|
|
31832
|
-
console.log(
|
|
31833
|
-
console.log(
|
|
32017
|
+
console.log(chalk218.white("http://localhost:14523/callback\n"));
|
|
32018
|
+
console.log(chalk218.blue("Opening browser for authorization..."));
|
|
32019
|
+
console.log(chalk218.dim("Waiting for authorization callback..."));
|
|
31834
32020
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
31835
|
-
console.log(
|
|
32021
|
+
console.log(chalk218.dim("Exchanging code for tokens..."));
|
|
31836
32022
|
const tokens = await exchangeToken({
|
|
31837
32023
|
code,
|
|
31838
32024
|
clientId,
|
|
@@ -31848,7 +32034,7 @@ async function auth() {
|
|
|
31848
32034
|
};
|
|
31849
32035
|
saveGlobalConfig(config);
|
|
31850
32036
|
console.log(
|
|
31851
|
-
|
|
32037
|
+
chalk218.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
31852
32038
|
);
|
|
31853
32039
|
}
|
|
31854
32040
|
|
|
@@ -32199,7 +32385,7 @@ import { execSync as execSync60 } from "child_process";
|
|
|
32199
32385
|
import { existsSync as existsSync72, mkdirSync as mkdirSync31, unlinkSync as unlinkSync22, writeFileSync as writeFileSync46 } from "fs";
|
|
32200
32386
|
import { tmpdir as tmpdir8 } from "os";
|
|
32201
32387
|
import { join as join89, resolve as resolve20 } from "path";
|
|
32202
|
-
import
|
|
32388
|
+
import chalk219 from "chalk";
|
|
32203
32389
|
|
|
32204
32390
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
32205
32391
|
var captureWindowPs1 = `
|
|
@@ -32350,13 +32536,13 @@ function screenshot(processName) {
|
|
|
32350
32536
|
const config = loadConfig();
|
|
32351
32537
|
const outputDir = resolve20(config.screenshot.outputDir);
|
|
32352
32538
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
32353
|
-
console.log(
|
|
32539
|
+
console.log(chalk219.gray(`Capturing window for process "${processName}" ...`));
|
|
32354
32540
|
try {
|
|
32355
32541
|
runPowerShellScript(processName, outputPath);
|
|
32356
|
-
console.log(
|
|
32542
|
+
console.log(chalk219.green(`Screenshot saved: ${outputPath}`));
|
|
32357
32543
|
} catch (error) {
|
|
32358
32544
|
const msg = error instanceof Error ? error.message : String(error);
|
|
32359
|
-
console.error(
|
|
32545
|
+
console.error(chalk219.red(`Failed to capture screenshot: ${msg}`));
|
|
32360
32546
|
process.exit(1);
|
|
32361
32547
|
}
|
|
32362
32548
|
}
|
|
@@ -32823,7 +33009,7 @@ var ClientHub = class extends Set {
|
|
|
32823
33009
|
};
|
|
32824
33010
|
|
|
32825
33011
|
// src/commands/sessions/daemon/createSession.ts
|
|
32826
|
-
import { randomUUID as
|
|
33012
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
32827
33013
|
|
|
32828
33014
|
// src/commands/sessions/daemon/sessionBase.ts
|
|
32829
33015
|
function sessionBase(id, status3) {
|
|
@@ -33019,7 +33205,7 @@ function spawnRun(opts) {
|
|
|
33019
33205
|
function createSession(id, { prompt, cwd, design, auto, harness, holdPty } = {}) {
|
|
33020
33206
|
if (harness && harness !== "claude")
|
|
33021
33207
|
return createHarnessSession(id, harness, prompt, cwd, holdPty);
|
|
33022
|
-
const claudeSessionId =
|
|
33208
|
+
const claudeSessionId = randomUUID17();
|
|
33023
33209
|
return {
|
|
33024
33210
|
...sessionBase(id, prompt ? "running" : "waiting"),
|
|
33025
33211
|
name: `Session ${id}`,
|
|
@@ -33618,7 +33804,8 @@ var PREVIEW_KINDS = [
|
|
|
33618
33804
|
"pr-comment",
|
|
33619
33805
|
"github-issue",
|
|
33620
33806
|
"github-issue-comment",
|
|
33621
|
-
"github-issue-edit"
|
|
33807
|
+
"github-issue-edit",
|
|
33808
|
+
"miro-board"
|
|
33622
33809
|
];
|
|
33623
33810
|
function isPreviewKind(value) {
|
|
33624
33811
|
return PREVIEW_KINDS.includes(value);
|
|
@@ -33631,6 +33818,7 @@ function previewTargetLabel(kind, itemType, prNumber, draft) {
|
|
|
33631
33818
|
if (kind === "github-issue-comment") return "github issue comment";
|
|
33632
33819
|
if (kind === "github-issue-edit") return "github issue edit";
|
|
33633
33820
|
if (kind === "github-issue") return "github issue";
|
|
33821
|
+
if (kind === "miro-board") return "miro anchors";
|
|
33634
33822
|
if (kind === "backlog-item") return `backlog ${itemType}`;
|
|
33635
33823
|
if (prNumber !== null) return `edit #${prNumber}`;
|
|
33636
33824
|
return draft ? "create draft" : "create";
|
|
@@ -35090,7 +35278,7 @@ function codexRespawnPlan(session) {
|
|
|
35090
35278
|
}
|
|
35091
35279
|
|
|
35092
35280
|
// src/commands/sessions/daemon/interactiveRespawnPlan.ts
|
|
35093
|
-
import { randomUUID as
|
|
35281
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
35094
35282
|
function interactiveRespawnPlan(session, resumes) {
|
|
35095
35283
|
const { claudeSessionId, cwd, initialPrompt, design, auto } = session;
|
|
35096
35284
|
if (!resumes) return null;
|
|
@@ -35110,7 +35298,7 @@ function interactiveRespawnPlan(session, resumes) {
|
|
|
35110
35298
|
return null;
|
|
35111
35299
|
}
|
|
35112
35300
|
function freshClaudePlan(session, prompt, cwd) {
|
|
35113
|
-
const claudeSessionId =
|
|
35301
|
+
const claudeSessionId = randomUUID18();
|
|
35114
35302
|
return {
|
|
35115
35303
|
spawn: () => {
|
|
35116
35304
|
session.claudeSessionId = claudeSessionId;
|
|
@@ -35995,10 +36183,10 @@ function startReusedRunPty(session, assistArgs, itemId2, hold, clients, onStatus
|
|
|
35995
36183
|
}
|
|
35996
36184
|
|
|
35997
36185
|
// src/commands/sessions/daemon/createWatcherSession.ts
|
|
35998
|
-
import { randomUUID as
|
|
36186
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
35999
36187
|
var WATCH_PROMPT = "/watch";
|
|
36000
36188
|
function createWatcherSession(id, cwd) {
|
|
36001
|
-
const claudeSessionId =
|
|
36189
|
+
const claudeSessionId = randomUUID19();
|
|
36002
36190
|
return {
|
|
36003
36191
|
...sessionBase(id, "running"),
|
|
36004
36192
|
name: `Session ${id}`,
|
|
@@ -38133,7 +38321,7 @@ function registerSetStatusCommand(cmd) {
|
|
|
38133
38321
|
|
|
38134
38322
|
// src/commands/sessions/summarise/index.ts
|
|
38135
38323
|
import * as fs56 from "fs";
|
|
38136
|
-
import
|
|
38324
|
+
import chalk220 from "chalk";
|
|
38137
38325
|
|
|
38138
38326
|
// src/commands/sessions/summarise/shared.ts
|
|
38139
38327
|
import * as fs55 from "fs";
|
|
@@ -38192,22 +38380,22 @@ ${firstMessage}`);
|
|
|
38192
38380
|
async function summarise2(options2) {
|
|
38193
38381
|
const files = await discoverSessionFiles();
|
|
38194
38382
|
if (files.length === 0) {
|
|
38195
|
-
console.log(
|
|
38383
|
+
console.log(chalk220.yellow("No sessions found."));
|
|
38196
38384
|
return;
|
|
38197
38385
|
}
|
|
38198
38386
|
const toProcess = selectCandidates(files, options2);
|
|
38199
38387
|
if (toProcess.length === 0) {
|
|
38200
|
-
console.log(
|
|
38388
|
+
console.log(chalk220.green("All sessions already summarised."));
|
|
38201
38389
|
return;
|
|
38202
38390
|
}
|
|
38203
38391
|
console.log(
|
|
38204
|
-
|
|
38392
|
+
chalk220.cyan(
|
|
38205
38393
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
38206
38394
|
)
|
|
38207
38395
|
);
|
|
38208
38396
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
38209
38397
|
console.log(
|
|
38210
|
-
|
|
38398
|
+
chalk220.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk220.yellow(`, ${failed2} skipped`) : "")
|
|
38211
38399
|
);
|
|
38212
38400
|
}
|
|
38213
38401
|
function selectCandidates(files, options2) {
|
|
@@ -38227,16 +38415,16 @@ function processSessions(files) {
|
|
|
38227
38415
|
let failed2 = 0;
|
|
38228
38416
|
for (let i = 0; i < files.length; i++) {
|
|
38229
38417
|
const file = files[i];
|
|
38230
|
-
process.stdout.write(
|
|
38418
|
+
process.stdout.write(chalk220.dim(` [${i + 1}/${files.length}] `));
|
|
38231
38419
|
const summary = summariseSession(file);
|
|
38232
38420
|
if (summary) {
|
|
38233
38421
|
writeSummary(file, summary);
|
|
38234
38422
|
succeeded++;
|
|
38235
|
-
process.stdout.write(`${
|
|
38423
|
+
process.stdout.write(`${chalk220.green("\u2713")} ${summary}
|
|
38236
38424
|
`);
|
|
38237
38425
|
} else {
|
|
38238
38426
|
failed2++;
|
|
38239
|
-
process.stdout.write(` ${
|
|
38427
|
+
process.stdout.write(` ${chalk220.yellow("skip")}
|
|
38240
38428
|
`);
|
|
38241
38429
|
}
|
|
38242
38430
|
}
|
|
@@ -38257,7 +38445,7 @@ function registerSessions(program2) {
|
|
|
38257
38445
|
}
|
|
38258
38446
|
|
|
38259
38447
|
// src/commands/statusLine.ts
|
|
38260
|
-
import
|
|
38448
|
+
import chalk222 from "chalk";
|
|
38261
38449
|
|
|
38262
38450
|
// src/shared/contextLevel.ts
|
|
38263
38451
|
function contextLevel(pct) {
|
|
@@ -38267,7 +38455,7 @@ function contextLevel(pct) {
|
|
|
38267
38455
|
}
|
|
38268
38456
|
|
|
38269
38457
|
// src/commands/buildLimitsSegment.ts
|
|
38270
|
-
import
|
|
38458
|
+
import chalk221 from "chalk";
|
|
38271
38459
|
|
|
38272
38460
|
// src/shared/rateLimitLevel.ts
|
|
38273
38461
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -38305,9 +38493,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
38305
38493
|
|
|
38306
38494
|
// src/commands/buildLimitsSegment.ts
|
|
38307
38495
|
var LEVEL_COLOR = {
|
|
38308
|
-
ok:
|
|
38309
|
-
warn:
|
|
38310
|
-
over:
|
|
38496
|
+
ok: chalk221.green,
|
|
38497
|
+
warn: chalk221.yellow,
|
|
38498
|
+
over: chalk221.red
|
|
38311
38499
|
};
|
|
38312
38500
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
38313
38501
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -38403,7 +38591,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
|
|
|
38403
38591
|
}
|
|
38404
38592
|
|
|
38405
38593
|
// src/commands/statusLine.ts
|
|
38406
|
-
|
|
38594
|
+
chalk222.level = 3;
|
|
38407
38595
|
function formatNumber(num) {
|
|
38408
38596
|
return num.toLocaleString("en-US");
|
|
38409
38597
|
}
|
|
@@ -38411,9 +38599,9 @@ function colorizePercent(pct) {
|
|
|
38411
38599
|
const label2 = `${Math.round(pct)}%`;
|
|
38412
38600
|
switch (contextLevel(pct)) {
|
|
38413
38601
|
case "red":
|
|
38414
|
-
return
|
|
38602
|
+
return chalk222.red(label2);
|
|
38415
38603
|
case "yellow":
|
|
38416
|
-
return
|
|
38604
|
+
return chalk222.yellow(label2);
|
|
38417
38605
|
default:
|
|
38418
38606
|
return label2;
|
|
38419
38607
|
}
|
|
@@ -38426,7 +38614,7 @@ async function statusLine() {
|
|
|
38426
38614
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
38427
38615
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
38428
38616
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
38429
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
38617
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk222.cyan(branch2)} | ` : "";
|
|
38430
38618
|
console.log(
|
|
38431
38619
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
38432
38620
|
);
|
|
@@ -38496,10 +38684,10 @@ async function update2() {
|
|
|
38496
38684
|
}
|
|
38497
38685
|
|
|
38498
38686
|
// src/reportCliError.ts
|
|
38499
|
-
import
|
|
38687
|
+
import chalk223 from "chalk";
|
|
38500
38688
|
function reportCliError(error) {
|
|
38501
38689
|
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError || error instanceof MiroExtractError) {
|
|
38502
|
-
console.error(
|
|
38690
|
+
console.error(chalk223.red(error.message));
|
|
38503
38691
|
} else {
|
|
38504
38692
|
console.error(error);
|
|
38505
38693
|
}
|