@staff0rd/assist 0.574.1 → 0.576.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 +4 -3
- package/allowed.cli-reads +1 -0
- package/claude/commands/github.md +1 -1
- package/dist/allowed.cli-reads +1 -0
- package/dist/commands/sessions/web/bundle.js +294 -292
- package/dist/index.js +987 -451
- 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.576.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -4946,14 +4946,14 @@ function findRuleViolations(data, rule) {
|
|
|
4946
4946
|
}
|
|
4947
4947
|
return violations;
|
|
4948
4948
|
}
|
|
4949
|
-
function findForbiddenStrings(
|
|
4950
|
-
return
|
|
4949
|
+
function findForbiddenStrings(rules3, readJson) {
|
|
4950
|
+
return rules3.flatMap((rule) => findRuleViolations(readJson(rule.file), rule));
|
|
4951
4951
|
}
|
|
4952
4952
|
|
|
4953
4953
|
// src/commands/verify/forbiddenStrings/index.ts
|
|
4954
4954
|
function forbiddenStrings() {
|
|
4955
|
-
const
|
|
4956
|
-
if (
|
|
4955
|
+
const rules3 = loadConfig().forbiddenStrings ?? [];
|
|
4956
|
+
if (rules3.length === 0) {
|
|
4957
4957
|
console.log("No forbidden-strings rules configured.");
|
|
4958
4958
|
process.exit(0);
|
|
4959
4959
|
}
|
|
@@ -4974,7 +4974,7 @@ function forbiddenStrings() {
|
|
|
4974
4974
|
cache5.set(file, parsed);
|
|
4975
4975
|
return parsed;
|
|
4976
4976
|
};
|
|
4977
|
-
const violations = findForbiddenStrings(
|
|
4977
|
+
const violations = findForbiddenStrings(rules3, readJson);
|
|
4978
4978
|
if (violations.length === 0) {
|
|
4979
4979
|
console.log("No forbidden strings found.");
|
|
4980
4980
|
process.exit(0);
|
|
@@ -13949,7 +13949,7 @@ import chalk71 from "chalk";
|
|
|
13949
13949
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
13950
13950
|
|
|
13951
13951
|
// src/commands/sessions/shared/reportPreviewRejection.ts
|
|
13952
|
-
function reportPreviewRejection(subject, decision) {
|
|
13952
|
+
function reportPreviewRejection(subject, decision, advice) {
|
|
13953
13953
|
console.error(
|
|
13954
13954
|
`${subject} rejected${decision.reason ? `: ${decision.reason}` : "."}`
|
|
13955
13955
|
);
|
|
@@ -13968,6 +13968,7 @@ ${quoted}
|
|
|
13968
13968
|
`);
|
|
13969
13969
|
}
|
|
13970
13970
|
}
|
|
13971
|
+
if (advice) console.error(advice);
|
|
13971
13972
|
process.exit(1);
|
|
13972
13973
|
}
|
|
13973
13974
|
|
|
@@ -13979,6 +13980,7 @@ function toPreviewDecision(msg) {
|
|
|
13979
13980
|
reason: msg.reason,
|
|
13980
13981
|
comments: Array.isArray(msg.comments) ? msg.comments : void 0,
|
|
13981
13982
|
screenshots: Array.isArray(msg.screenshots) ? msg.screenshots : void 0,
|
|
13983
|
+
body: typeof msg.body === "string" ? msg.body : void 0,
|
|
13982
13984
|
reviewAfter: msg.reviewAfter === true,
|
|
13983
13985
|
announceAfter: msg.announceAfter === true,
|
|
13984
13986
|
draft: typeof msg.draft === "boolean" ? msg.draft : void 0
|
|
@@ -14029,7 +14031,7 @@ function requestPreviewDecision(request) {
|
|
|
14029
14031
|
}
|
|
14030
14032
|
|
|
14031
14033
|
// src/commands/sessions/shared/awaitPreviewApproval.ts
|
|
14032
|
-
async function awaitPreviewApproval(subject, request) {
|
|
14034
|
+
async function awaitPreviewApproval(subject, request, options2 = {}) {
|
|
14033
14035
|
console.log("Awaiting your approval in the assist web UI preview pane\u2026");
|
|
14034
14036
|
let decision;
|
|
14035
14037
|
try {
|
|
@@ -14040,7 +14042,9 @@ async function awaitPreviewApproval(subject, request) {
|
|
|
14040
14042
|
);
|
|
14041
14043
|
process.exit(1);
|
|
14042
14044
|
}
|
|
14043
|
-
if (decision.
|
|
14045
|
+
if (decision.body !== void 0) options2.saveEditedBody?.(decision.body);
|
|
14046
|
+
if (decision.decision === "reject")
|
|
14047
|
+
reportPreviewRejection(subject, decision, options2.rejectionAdvice);
|
|
14044
14048
|
return decision;
|
|
14045
14049
|
}
|
|
14046
14050
|
|
|
@@ -20498,14 +20502,8 @@ import { spawnSync as spawnSync4 } from "child_process";
|
|
|
20498
20502
|
import { unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
|
|
20499
20503
|
import { tmpdir as tmpdir5 } from "os";
|
|
20500
20504
|
import { join as join49 } from "path";
|
|
20501
|
-
|
|
20502
|
-
|
|
20503
|
-
for (const [key, value] of Object.entries(vars)) {
|
|
20504
|
-
const flag = typeof value === "number" ? "-F" : "-f";
|
|
20505
|
-
args.push(flag, `${key}=${value}`);
|
|
20506
|
-
}
|
|
20507
|
-
return args;
|
|
20508
|
-
}
|
|
20505
|
+
|
|
20506
|
+
// src/shared/throwOnGraphqlErrors.ts
|
|
20509
20507
|
function throwOnGraphqlErrors(stdout) {
|
|
20510
20508
|
let parsed;
|
|
20511
20509
|
try {
|
|
@@ -20521,6 +20519,16 @@ function throwOnGraphqlErrors(stdout) {
|
|
|
20521
20519
|
).join("; ");
|
|
20522
20520
|
throw new Error(messages || "GraphQL request returned errors");
|
|
20523
20521
|
}
|
|
20522
|
+
|
|
20523
|
+
// src/shared/runGhGraphql.ts
|
|
20524
|
+
function buildArgs2(queryFile, vars) {
|
|
20525
|
+
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
20526
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
20527
|
+
const flag = typeof value === "number" ? "-F" : "-f";
|
|
20528
|
+
args.push(flag, `${key}=${value}`);
|
|
20529
|
+
}
|
|
20530
|
+
return args;
|
|
20531
|
+
}
|
|
20524
20532
|
function runGhGraphql(mutation, vars) {
|
|
20525
20533
|
const queryFile = join49(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
20526
20534
|
writeFileSync30(queryFile, mutation);
|
|
@@ -20828,6 +20836,83 @@ function fetchIssue2(number, repo) {
|
|
|
20828
20836
|
}
|
|
20829
20837
|
}
|
|
20830
20838
|
|
|
20839
|
+
// src/commands/github/issue/resumeIssueBody.ts
|
|
20840
|
+
import { existsSync as existsSync48, readFileSync as readFileSync37 } from "fs";
|
|
20841
|
+
|
|
20842
|
+
// src/commands/github/issue/issueWorkingFile.ts
|
|
20843
|
+
import { join as join50 } from "path";
|
|
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
|
+
}
|
|
20865
|
+
}
|
|
20866
|
+
|
|
20867
|
+
// src/commands/github/issue/validateIssueBody.ts
|
|
20868
|
+
function validateIssueBody(title, body) {
|
|
20869
|
+
validateProposedContent(
|
|
20870
|
+
{ subject: "Issue", context: "GitHub issues" },
|
|
20871
|
+
title,
|
|
20872
|
+
body
|
|
20873
|
+
);
|
|
20874
|
+
}
|
|
20875
|
+
|
|
20876
|
+
// src/commands/github/issue/writeIssueWorkingFile.ts
|
|
20877
|
+
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync31 } from "fs";
|
|
20878
|
+
function writeIssueWorkingFile(slug, number, target, updatedAt, body) {
|
|
20879
|
+
const { dir, bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
20880
|
+
mkdirSync16(dir, { recursive: true });
|
|
20881
|
+
writeFileSync31(bodyPath, body);
|
|
20882
|
+
writeFileSync31(
|
|
20883
|
+
metaPath,
|
|
20884
|
+
`${JSON.stringify({ target, updatedAt }, null, 2)}
|
|
20885
|
+
`
|
|
20886
|
+
);
|
|
20887
|
+
return bodyPath;
|
|
20888
|
+
}
|
|
20889
|
+
|
|
20890
|
+
// src/commands/github/issue/prepareIssueEdit.ts
|
|
20891
|
+
function slugFromUrl(url) {
|
|
20892
|
+
const match = /github\.com\/([^/]+\/[^/]+)\//.exec(url ?? "");
|
|
20893
|
+
return match ? match[1] : "unknown/unknown";
|
|
20894
|
+
}
|
|
20895
|
+
function prepareIssueEdit(number, repo, fresh) {
|
|
20896
|
+
const issue = fetchIssue2(number, repo);
|
|
20897
|
+
const slug = repo ?? slugFromUrl(issue.url);
|
|
20898
|
+
const target = `${slug}#${number}`;
|
|
20899
|
+
const resumed = fresh ? void 0 : resumeIssueBody(slug, number, issue.updatedAt);
|
|
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
|
+
}
|
|
20915
|
+
|
|
20831
20916
|
// src/commands/github/issue/pushIssueBody.ts
|
|
20832
20917
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
20833
20918
|
function pushIssueBody(number, repo, bodyPath) {
|
|
@@ -20840,19 +20925,39 @@ function pushIssueBody(number, repo, bodyPath) {
|
|
|
20840
20925
|
}
|
|
20841
20926
|
}
|
|
20842
20927
|
|
|
20928
|
+
// src/commands/github/issue/pushUnchangedIssue.ts
|
|
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}`
|
|
20933
|
+
);
|
|
20934
|
+
process.exit(1);
|
|
20935
|
+
}
|
|
20936
|
+
pushIssueBody(number, repo, bodyPath);
|
|
20937
|
+
console.log(`Issue body updated on ${target}`);
|
|
20938
|
+
}
|
|
20939
|
+
|
|
20843
20940
|
// src/commands/github/issue/reviewProposedIssueEdit.ts
|
|
20844
20941
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
20845
|
-
async function reviewProposedIssueEdit(title, body) {
|
|
20942
|
+
async function reviewProposedIssueEdit(title, body, working) {
|
|
20846
20943
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
20847
|
-
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return;
|
|
20848
|
-
await awaitPreviewApproval(
|
|
20849
|
-
|
|
20850
|
-
|
|
20851
|
-
|
|
20852
|
-
|
|
20853
|
-
|
|
20854
|
-
|
|
20855
|
-
|
|
20944
|
+
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return body;
|
|
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;
|
|
20856
20961
|
}
|
|
20857
20962
|
|
|
20858
20963
|
// src/commands/github/issue/viewIssue.ts
|
|
@@ -20867,40 +20972,8 @@ function viewIssue(number, repo) {
|
|
|
20867
20972
|
}
|
|
20868
20973
|
}
|
|
20869
20974
|
|
|
20870
|
-
// src/commands/github/issue/writeIssueWorkingFile.ts
|
|
20871
|
-
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync31 } from "fs";
|
|
20872
|
-
|
|
20873
|
-
// src/commands/github/issue/issueWorkingFile.ts
|
|
20874
|
-
import { join as join50 } from "path";
|
|
20875
|
-
function issueWorkingFile(slug, number) {
|
|
20876
|
-
const [owner = "unknown", repo = "unknown"] = slug.split("/");
|
|
20877
|
-
const dir = join50(getStoreDir(), "github-issues", owner, repo);
|
|
20878
|
-
return {
|
|
20879
|
-
dir,
|
|
20880
|
-
bodyPath: join50(dir, `${number}.md`),
|
|
20881
|
-
metaPath: join50(dir, `${number}.json`)
|
|
20882
|
-
};
|
|
20883
|
-
}
|
|
20884
|
-
|
|
20885
|
-
// src/commands/github/issue/writeIssueWorkingFile.ts
|
|
20886
|
-
function writeIssueWorkingFile(slug, number, target, updatedAt, body) {
|
|
20887
|
-
const { dir, bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
20888
|
-
mkdirSync16(dir, { recursive: true });
|
|
20889
|
-
writeFileSync31(bodyPath, body);
|
|
20890
|
-
writeFileSync31(
|
|
20891
|
-
metaPath,
|
|
20892
|
-
`${JSON.stringify({ target, updatedAt }, null, 2)}
|
|
20893
|
-
`
|
|
20894
|
-
);
|
|
20895
|
-
return bodyPath;
|
|
20896
|
-
}
|
|
20897
|
-
|
|
20898
20975
|
// src/commands/github/issue/editIssue.ts
|
|
20899
20976
|
var USAGE3 = "Usage: assist github issue edit <number> [-R <owner>/<repo>]";
|
|
20900
|
-
function slugFromUrl(url) {
|
|
20901
|
-
const match = /github\.com\/([^/]+\/[^/]+)\//.exec(url ?? "");
|
|
20902
|
-
return match ? match[1] : "unknown/unknown";
|
|
20903
|
-
}
|
|
20904
20977
|
async function editIssue(numberArg, options2) {
|
|
20905
20978
|
const number = Number.parseInt(numberArg, 10);
|
|
20906
20979
|
if (!Number.isInteger(number) || number <= 0) {
|
|
@@ -20911,30 +20984,419 @@ async function editIssue(numberArg, options2) {
|
|
|
20911
20984
|
viewIssue(number, options2.repo);
|
|
20912
20985
|
return;
|
|
20913
20986
|
}
|
|
20914
|
-
const issue =
|
|
20915
|
-
const
|
|
20916
|
-
|
|
20917
|
-
|
|
20918
|
-
{
|
|
20919
|
-
issue.title,
|
|
20920
|
-
issue.body
|
|
20987
|
+
const issue = prepareIssueEdit(number, options2.repo, options2.fresh);
|
|
20988
|
+
const edited = await reviewProposedIssueEdit(
|
|
20989
|
+
`Edit ${issue.target}: ${issue.title}`,
|
|
20990
|
+
issue.body,
|
|
20991
|
+
{ path: issue.bodyPath, save: issue.save }
|
|
20921
20992
|
);
|
|
20922
|
-
|
|
20923
|
-
|
|
20993
|
+
validateIssueBody(issue.title, edited);
|
|
20994
|
+
pushUnchangedIssue(
|
|
20924
20995
|
number,
|
|
20925
|
-
|
|
20996
|
+
options2.repo,
|
|
20997
|
+
issue.target,
|
|
20926
20998
|
issue.updatedAt,
|
|
20927
|
-
issue.
|
|
20999
|
+
issue.bodyPath
|
|
21000
|
+
);
|
|
21001
|
+
}
|
|
21002
|
+
|
|
21003
|
+
// src/commands/github/issue/fixStructure/matchedLabels.ts
|
|
21004
|
+
function matchedLabels(labels, stripLabels) {
|
|
21005
|
+
if (stripLabels.length === 0) return [];
|
|
21006
|
+
const wanted = new Set(stripLabels.map((name) => name.trim().toLowerCase()));
|
|
21007
|
+
return labels.filter((label2) => wanted.has(label2.name.trim().toLowerCase()));
|
|
21008
|
+
}
|
|
21009
|
+
|
|
21010
|
+
// src/commands/github/issue/fixStructure/normaliseTypeName.ts
|
|
21011
|
+
function normaliseTypeName(name) {
|
|
21012
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
21013
|
+
}
|
|
21014
|
+
|
|
21015
|
+
// src/commands/github/issue/fixStructure/resolveIssueType.ts
|
|
21016
|
+
function resolveIssueType(issueTypes, levelName) {
|
|
21017
|
+
const wanted = normaliseTypeName(levelName);
|
|
21018
|
+
const match = issueTypes.find(
|
|
21019
|
+
(type) => normaliseTypeName(type.name) === wanted
|
|
20928
21020
|
);
|
|
20929
|
-
|
|
20930
|
-
|
|
21021
|
+
if (!match) {
|
|
21022
|
+
throw new Error(
|
|
21023
|
+
`The organisation has no ${levelName} issue type. It has ${issueTypes.map((type) => type.name).join(", ")}`
|
|
21024
|
+
);
|
|
21025
|
+
}
|
|
21026
|
+
return match;
|
|
21027
|
+
}
|
|
21028
|
+
|
|
21029
|
+
// src/commands/github/issue/fixStructure/resolveLevelIndex.ts
|
|
21030
|
+
function resolveLevelIndex(chain2, name) {
|
|
21031
|
+
if (!name) return -1;
|
|
21032
|
+
const wanted = normaliseTypeName(name);
|
|
21033
|
+
return chain2.findIndex((level) => normaliseTypeName(level) === wanted);
|
|
21034
|
+
}
|
|
21035
|
+
|
|
21036
|
+
// src/commands/github/issue/fixStructure/buildPlanEntry.ts
|
|
21037
|
+
function buildPlanEntry(issue, context) {
|
|
21038
|
+
const labelRemovals = matchedLabels(issue.labels, context.stripLabels);
|
|
21039
|
+
const level = context.chain[context.rootLevelIndex + issue.depth];
|
|
21040
|
+
if (level === void 0) {
|
|
21041
|
+
return { issue, level: null, typeChange: null, labelRemovals };
|
|
21042
|
+
}
|
|
21043
|
+
const settled = resolveLevelIndex([level], issue.typeName) === 0 || issue.depth === 0 && !context.rootAsserted;
|
|
21044
|
+
if (settled) return { issue, level, typeChange: null, labelRemovals };
|
|
21045
|
+
const target = resolveIssueType(context.issueTypes, level);
|
|
21046
|
+
return {
|
|
21047
|
+
issue,
|
|
21048
|
+
level,
|
|
21049
|
+
typeChange: { from: issue.typeName, to: target.name, typeId: target.id },
|
|
21050
|
+
labelRemovals
|
|
21051
|
+
};
|
|
21052
|
+
}
|
|
21053
|
+
|
|
21054
|
+
// src/commands/github/issue/fixStructure/orderDepthFirst.ts
|
|
21055
|
+
function orderDepthFirst(issues) {
|
|
21056
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
21057
|
+
for (const issue of issues) {
|
|
21058
|
+
const siblings = byParent.get(issue.parentId) ?? [];
|
|
21059
|
+
siblings.push(issue);
|
|
21060
|
+
byParent.set(issue.parentId, siblings);
|
|
21061
|
+
}
|
|
21062
|
+
const ordered = [];
|
|
21063
|
+
const visit = (issue) => {
|
|
21064
|
+
ordered.push(issue);
|
|
21065
|
+
for (const child of byParent.get(issue.id) ?? []) visit(child);
|
|
21066
|
+
};
|
|
21067
|
+
for (const root of byParent.get(null) ?? []) visit(root);
|
|
21068
|
+
return ordered;
|
|
21069
|
+
}
|
|
21070
|
+
|
|
21071
|
+
// src/commands/github/issue/fixStructure/buildFixStructurePlan.ts
|
|
21072
|
+
function buildFixStructurePlan(issues, options2) {
|
|
21073
|
+
const context = { ...options2, stripLabels: options2.stripLabels ?? [] };
|
|
21074
|
+
const byId = new Map(issues.map((issue) => [issue.id, issue]));
|
|
21075
|
+
const entries = [];
|
|
21076
|
+
const tooDeep = [];
|
|
21077
|
+
for (const issue of orderDepthFirst(issues)) {
|
|
21078
|
+
const entry = buildPlanEntry(issue, context);
|
|
21079
|
+
entries.push(entry);
|
|
21080
|
+
if (entry.level === null) {
|
|
21081
|
+
tooDeep.push({
|
|
21082
|
+
issue,
|
|
21083
|
+
parent: issue.parentId ? byId.get(issue.parentId) ?? null : null
|
|
21084
|
+
});
|
|
21085
|
+
}
|
|
21086
|
+
}
|
|
21087
|
+
return {
|
|
21088
|
+
entries,
|
|
21089
|
+
tooDeep,
|
|
21090
|
+
typeChangeCount: entries.filter((entry) => entry.typeChange).length,
|
|
21091
|
+
labelRemovalCount: entries.reduce(
|
|
21092
|
+
(total, entry) => total + entry.labelRemovals.length,
|
|
21093
|
+
0
|
|
21094
|
+
)
|
|
21095
|
+
};
|
|
21096
|
+
}
|
|
21097
|
+
|
|
21098
|
+
// src/shared/runGhGraphqlJson.ts
|
|
21099
|
+
import { spawnSync as spawnSync5 } from "child_process";
|
|
21100
|
+
function runGhGraphqlJson(query, vars = {}) {
|
|
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;
|
|
21110
|
+
}
|
|
21111
|
+
|
|
21112
|
+
// src/commands/github/issue/fixStructure/issueFieldsFragment.ts
|
|
21113
|
+
var issueFieldsFragment = `fragment issueFields on Issue {
|
|
21114
|
+
id
|
|
21115
|
+
number
|
|
21116
|
+
title
|
|
21117
|
+
issueType { name }
|
|
21118
|
+
repository { nameWithOwner }
|
|
21119
|
+
labels(first: 100) { nodes { id name } pageInfo { hasNextPage } }
|
|
21120
|
+
subIssues(first: 100) { nodes { id } pageInfo { hasNextPage } }
|
|
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
|
+
);
|
|
21132
|
+
}
|
|
21133
|
+
if (raw.subIssues?.pageInfo?.hasNextPage) {
|
|
21134
|
+
throw new Error(
|
|
21135
|
+
`${where} has more than 100 sub-issues, which is not supported`
|
|
21136
|
+
);
|
|
21137
|
+
}
|
|
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
|
+
};
|
|
21147
|
+
}
|
|
21148
|
+
|
|
21149
|
+
// src/commands/github/issue/fixStructure/fetchRootIssue.ts
|
|
21150
|
+
var QUERY = `query($owner: String!, $repo: String!, $number: Int!) {
|
|
21151
|
+
repository(owner: $owner, name: $repo) {
|
|
21152
|
+
issue(number: $number) { ...issueFields }
|
|
21153
|
+
}
|
|
21154
|
+
}
|
|
21155
|
+
${issueFieldsFragment}`;
|
|
21156
|
+
function fetchRootIssue(target) {
|
|
21157
|
+
const raw = runGhGraphqlJson(QUERY, {
|
|
21158
|
+
owner: target.owner,
|
|
21159
|
+
repo: target.repo,
|
|
21160
|
+
number: target.number
|
|
21161
|
+
});
|
|
21162
|
+
const issue = JSON.parse(raw).data?.repository?.issue;
|
|
21163
|
+
if (!issue) {
|
|
21164
|
+
throw new Error(
|
|
21165
|
+
`No issue ${target.owner}/${target.repo}#${target.number} could be read`
|
|
21166
|
+
);
|
|
21167
|
+
}
|
|
21168
|
+
return parseIssueNode(issue);
|
|
21169
|
+
}
|
|
21170
|
+
|
|
21171
|
+
// src/commands/github/issue/fixStructure/printFixStructurePlan.ts
|
|
21172
|
+
import chalk162 from "chalk";
|
|
21173
|
+
function annotate(entry) {
|
|
21174
|
+
const notes = [];
|
|
21175
|
+
if (entry.level === null) {
|
|
21176
|
+
notes.push(chalk162.red("deeper than the leaf level"));
|
|
21177
|
+
} else if (entry.typeChange) {
|
|
21178
|
+
notes.push(
|
|
21179
|
+
chalk162.yellow(
|
|
21180
|
+
`${entry.typeChange.from ?? "no type"} -> ${entry.typeChange.to}`
|
|
21181
|
+
)
|
|
21182
|
+
);
|
|
21183
|
+
} else {
|
|
21184
|
+
notes.push(chalk162.dim(entry.issue.typeName ?? "no type"));
|
|
21185
|
+
}
|
|
21186
|
+
for (const label2 of entry.labelRemovals) {
|
|
21187
|
+
notes.push(chalk162.yellow(`-${label2.name}`));
|
|
21188
|
+
}
|
|
21189
|
+
return notes;
|
|
21190
|
+
}
|
|
21191
|
+
function formatCount(count8, noun) {
|
|
21192
|
+
return `${count8} ${noun}${count8 === 1 ? "" : "s"}`;
|
|
21193
|
+
}
|
|
21194
|
+
function printFixStructurePlan(plan2, chain2) {
|
|
21195
|
+
console.log(chalk162.dim(`chain: ${chain2.join(" > ")}`));
|
|
21196
|
+
for (const entry of plan2.entries) {
|
|
21197
|
+
const indent3 = " ".repeat(entry.issue.depth);
|
|
21198
|
+
const name = chalk162.cyan(`${entry.issue.repo}#${entry.issue.number}`);
|
|
21199
|
+
console.log(
|
|
21200
|
+
`${indent3}${name} ${entry.issue.title} [${annotate(entry).join(", ")}]`
|
|
21201
|
+
);
|
|
21202
|
+
}
|
|
21203
|
+
for (const { issue, parent } of plan2.tooDeep) {
|
|
21204
|
+
const where = parent ? ` under ${parent.repo}#${parent.number}` : "";
|
|
20931
21205
|
console.error(
|
|
20932
|
-
|
|
21206
|
+
chalk162.red(
|
|
21207
|
+
`${issue.repo}#${issue.number}${where} sits below ${chain2[chain2.length - 1]}, the leaf level`
|
|
21208
|
+
)
|
|
21209
|
+
);
|
|
21210
|
+
}
|
|
21211
|
+
if (plan2.typeChangeCount === 0 && plan2.labelRemovalCount === 0) {
|
|
21212
|
+
console.log(chalk162.green("Nothing to change"));
|
|
21213
|
+
return;
|
|
21214
|
+
}
|
|
21215
|
+
console.log(
|
|
21216
|
+
`${formatCount(plan2.typeChangeCount, "type change")}, ${formatCount(plan2.labelRemovalCount, "label removal")} planned`
|
|
21217
|
+
);
|
|
21218
|
+
console.log(chalk162.dim("Dry run \u2014 nothing written"));
|
|
21219
|
+
}
|
|
21220
|
+
|
|
21221
|
+
// src/commands/github/issue/fixStructure/resolveFixStructureTarget.ts
|
|
21222
|
+
var BARE_NUMBER = /^#?(\d+)$/;
|
|
21223
|
+
var REPO_SLUG = /^([^/\s]+)\/([^/\s]+)$/;
|
|
21224
|
+
function resolveFixStructureTarget(target, repo) {
|
|
21225
|
+
const shorthand = normalizeGithubIssue(target);
|
|
21226
|
+
if (shorthand) {
|
|
21227
|
+
const [slug2, number] = shorthand.split("#");
|
|
21228
|
+
const [owner, name] = (slug2 ?? "").split("/");
|
|
21229
|
+
return { owner: owner ?? "", repo: name ?? "", number: Number(number) };
|
|
21230
|
+
}
|
|
21231
|
+
const bare = BARE_NUMBER.exec(target.trim());
|
|
21232
|
+
if (!bare) {
|
|
21233
|
+
throw new Error(
|
|
21234
|
+
`Could not read "${target}" as a GitHub issue. Pass owner/repo#number, a github.com issue URL, or a bare number with --repo owner/repo`
|
|
21235
|
+
);
|
|
21236
|
+
}
|
|
21237
|
+
if (!repo) {
|
|
21238
|
+
throw new Error(
|
|
21239
|
+
`A bare issue number needs a repository. Re-run with --repo owner/repo, or pass the issue as owner/repo#${bare[1]}`
|
|
21240
|
+
);
|
|
21241
|
+
}
|
|
21242
|
+
const slug = REPO_SLUG.exec(repo.trim());
|
|
21243
|
+
if (!slug) {
|
|
21244
|
+
throw new Error(`--repo must be owner/repo, not "${repo}"`);
|
|
21245
|
+
}
|
|
21246
|
+
return {
|
|
21247
|
+
owner: slug[1] ?? "",
|
|
21248
|
+
repo: slug[2] ?? "",
|
|
21249
|
+
number: Number(bare[1])
|
|
21250
|
+
};
|
|
21251
|
+
}
|
|
21252
|
+
|
|
21253
|
+
// src/commands/github/issue/fixStructure/resolveOrgIssueTypes.ts
|
|
21254
|
+
var QUERY2 = `query($owner: String!) {
|
|
21255
|
+
organization(login: $owner) {
|
|
21256
|
+
issueTypes(first: 50) { nodes { id name } }
|
|
21257
|
+
}
|
|
21258
|
+
}`;
|
|
21259
|
+
function missingOrg(owner) {
|
|
21260
|
+
return new Error(
|
|
21261
|
+
`Issue types live on the organisation, and ${owner} is not one this token can read`
|
|
21262
|
+
);
|
|
21263
|
+
}
|
|
21264
|
+
function resolveOrgIssueTypes(owner) {
|
|
21265
|
+
let raw;
|
|
21266
|
+
try {
|
|
21267
|
+
raw = runGhGraphqlJson(QUERY2, { owner });
|
|
21268
|
+
} catch (error) {
|
|
21269
|
+
const message3 = error instanceof Error ? error.message : String(error);
|
|
21270
|
+
if (message3.includes("Could not resolve to an Organization")) {
|
|
21271
|
+
throw missingOrg(owner);
|
|
21272
|
+
}
|
|
21273
|
+
throw error;
|
|
21274
|
+
}
|
|
21275
|
+
const organization = JSON.parse(raw).data?.organization;
|
|
21276
|
+
if (!organization) throw missingOrg(owner);
|
|
21277
|
+
const types = (organization.issueTypes?.nodes ?? []).filter(
|
|
21278
|
+
(type) => type !== null
|
|
21279
|
+
);
|
|
21280
|
+
if (types.length === 0) {
|
|
21281
|
+
throw new Error(`The ${owner} organisation has no issue types defined`);
|
|
21282
|
+
}
|
|
21283
|
+
return types;
|
|
21284
|
+
}
|
|
21285
|
+
|
|
21286
|
+
// src/commands/github/issue/fixStructure/resolveRootLevelIndex.ts
|
|
21287
|
+
function resolveRootLevelIndex(chain2, targetTypeName, level) {
|
|
21288
|
+
if (level) {
|
|
21289
|
+
const index4 = resolveLevelIndex(chain2, level);
|
|
21290
|
+
if (index4 === -1) {
|
|
21291
|
+
throw new Error(
|
|
21292
|
+
`--level must name one of ${chain2.join(", ")}, not "${level}"`
|
|
21293
|
+
);
|
|
21294
|
+
}
|
|
21295
|
+
return { index: index4, asserted: true };
|
|
21296
|
+
}
|
|
21297
|
+
const index3 = resolveLevelIndex(chain2, targetTypeName);
|
|
21298
|
+
if (index3 === -1) {
|
|
21299
|
+
const has = targetTypeName ? `has the type ${targetTypeName}, which is not in the ${chain2.join(" > ")} chain` : "has no issue type";
|
|
21300
|
+
throw new Error(
|
|
21301
|
+
`The target ${has}, so its level cannot be inferred. Re-run with --level ${chain2.map((name) => name.toLowerCase()).join("|")} to assert where it sits.`
|
|
20933
21302
|
);
|
|
21303
|
+
}
|
|
21304
|
+
return { index: index3, asserted: false };
|
|
21305
|
+
}
|
|
21306
|
+
|
|
21307
|
+
// src/commands/github/issue/fixStructure/types.ts
|
|
21308
|
+
var defaultTypeChain = ["Epic", "Story", "Subtask"];
|
|
21309
|
+
|
|
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
|
+
// src/commands/github/issue/fixStructure/fixStructure.ts
|
|
21357
|
+
function fixStructure(target, options2) {
|
|
21358
|
+
const chain2 = defaultTypeChain;
|
|
21359
|
+
try {
|
|
21360
|
+
const resolved = resolveFixStructureTarget(target, options2.repo);
|
|
21361
|
+
const root = fetchRootIssue(resolved);
|
|
21362
|
+
const { index: index3, asserted } = resolveRootLevelIndex(
|
|
21363
|
+
chain2,
|
|
21364
|
+
root.typeName,
|
|
21365
|
+
options2.level
|
|
21366
|
+
);
|
|
21367
|
+
const issueTypes = resolveOrgIssueTypes(resolved.owner);
|
|
21368
|
+
const issues = walkSubtree(root, chain2.length - index3);
|
|
21369
|
+
const plan2 = buildFixStructurePlan(issues, {
|
|
21370
|
+
chain: chain2,
|
|
21371
|
+
rootLevelIndex: index3,
|
|
21372
|
+
rootAsserted: asserted,
|
|
21373
|
+
issueTypes
|
|
21374
|
+
});
|
|
21375
|
+
printFixStructurePlan(plan2, chain2);
|
|
21376
|
+
} catch (error) {
|
|
21377
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
20934
21378
|
process.exit(1);
|
|
20935
21379
|
}
|
|
20936
|
-
|
|
20937
|
-
|
|
21380
|
+
}
|
|
21381
|
+
|
|
21382
|
+
// src/commands/github/issue/fixStructure/registerFixStructure.ts
|
|
21383
|
+
var chain = defaultTypeChain.join(" > ");
|
|
21384
|
+
var levels = defaultTypeChain.map((name) => name.toLowerCase()).join("|");
|
|
21385
|
+
function registerFixStructure(issueCommand) {
|
|
21386
|
+
issueCommand.command("fix-structure <target>").description("Report the issue type drift across one issue subtree").option(
|
|
21387
|
+
"-R, --repo <owner/repo>",
|
|
21388
|
+
"Repository a bare issue number belongs to"
|
|
21389
|
+
).option(
|
|
21390
|
+
"--level <level>",
|
|
21391
|
+
`The target's own position in the ${chain} chain, when it cannot be inferred from its type`
|
|
21392
|
+
).addHelpText(
|
|
21393
|
+
"after",
|
|
21394
|
+
`
|
|
21395
|
+
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
|
+
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
|
+
The target is owner/repo#number, a github.com issue URL, or a bare number with --repo.
|
|
21398
|
+
This reports only; nothing is written.`
|
|
21399
|
+
).action(fixStructure);
|
|
20938
21400
|
}
|
|
20939
21401
|
|
|
20940
21402
|
// src/commands/prs/readBodyArgument.ts
|
|
@@ -20961,9 +21423,12 @@ function registerGithubIssue(githubCommand) {
|
|
|
20961
21423
|
issueCommand.command("edit <number>").description("Edit an existing GitHub issue's body in the preview pane").option(
|
|
20962
21424
|
"-R, --repo <owner/repo>",
|
|
20963
21425
|
"Target repository (defaults to the current repo)"
|
|
21426
|
+
).option(
|
|
21427
|
+
"--fresh",
|
|
21428
|
+
"Discard any working file for the issue and re-fetch its body from GitHub"
|
|
20964
21429
|
).addHelpText(
|
|
20965
21430
|
"after",
|
|
20966
|
-
"\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.\nOnly the body is touched \u2014 the title, labels, assignees and state are left alone."
|
|
21431
|
+
"\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."
|
|
20967
21432
|
).action(editIssue);
|
|
20968
21433
|
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(
|
|
20969
21434
|
"-R, --repo <owner/repo>",
|
|
@@ -20979,6 +21444,7 @@ function registerGithubIssue(githubCommand) {
|
|
|
20979
21444
|
});
|
|
20980
21445
|
}
|
|
20981
21446
|
);
|
|
21447
|
+
registerFixStructure(issueCommand);
|
|
20982
21448
|
}
|
|
20983
21449
|
|
|
20984
21450
|
// src/commands/registerGithub.ts
|
|
@@ -21005,9 +21471,9 @@ async function countPendingHandovers(orm, origin) {
|
|
|
21005
21471
|
|
|
21006
21472
|
// src/commands/handover/migrateDiskHandovers.ts
|
|
21007
21473
|
import {
|
|
21008
|
-
existsSync as
|
|
21474
|
+
existsSync as existsSync49,
|
|
21009
21475
|
readdirSync as readdirSync10,
|
|
21010
|
-
readFileSync as
|
|
21476
|
+
readFileSync as readFileSync38,
|
|
21011
21477
|
rmSync as rmSync3,
|
|
21012
21478
|
statSync as statSync8
|
|
21013
21479
|
} from "fs";
|
|
@@ -21060,7 +21526,7 @@ function summariseHandoverContent(content) {
|
|
|
21060
21526
|
|
|
21061
21527
|
// src/commands/handover/migrateDiskHandovers.ts
|
|
21062
21528
|
function collectMarkdown(dir) {
|
|
21063
|
-
if (!
|
|
21529
|
+
if (!existsSync49(dir)) return [];
|
|
21064
21530
|
const out = [];
|
|
21065
21531
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
21066
21532
|
const full = join53(dir, entry.name);
|
|
@@ -21070,7 +21536,7 @@ function collectMarkdown(dir) {
|
|
|
21070
21536
|
return out;
|
|
21071
21537
|
}
|
|
21072
21538
|
async function migrateFile(orm, origin, file, createdAt) {
|
|
21073
|
-
const content =
|
|
21539
|
+
const content = readFileSync38(file, "utf8");
|
|
21074
21540
|
await saveHandover(orm, {
|
|
21075
21541
|
origin,
|
|
21076
21542
|
summary: summariseHandoverContent(content),
|
|
@@ -21087,7 +21553,7 @@ async function migrateDiskHandovers(orm, origin, cwd = process.cwd()) {
|
|
|
21087
21553
|
migrated++;
|
|
21088
21554
|
}
|
|
21089
21555
|
const handoverPath = getHandoverPath(cwd);
|
|
21090
|
-
if (
|
|
21556
|
+
if (existsSync49(handoverPath)) {
|
|
21091
21557
|
await migrateFile(orm, origin, handoverPath, statSync8(handoverPath).mtime);
|
|
21092
21558
|
migrated++;
|
|
21093
21559
|
}
|
|
@@ -21218,7 +21684,7 @@ function registerHandover(program2) {
|
|
|
21218
21684
|
}
|
|
21219
21685
|
|
|
21220
21686
|
// src/commands/jira/acceptanceCriteria.ts
|
|
21221
|
-
import
|
|
21687
|
+
import chalk163 from "chalk";
|
|
21222
21688
|
|
|
21223
21689
|
// src/commands/jira/adfToText.ts
|
|
21224
21690
|
function renderInline(node) {
|
|
@@ -21285,7 +21751,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
21285
21751
|
const parsed = fetchIssue(issueKey, field);
|
|
21286
21752
|
const acValue = parsed?.fields?.[field];
|
|
21287
21753
|
if (!acValue) {
|
|
21288
|
-
console.log(
|
|
21754
|
+
console.log(chalk163.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
21289
21755
|
return;
|
|
21290
21756
|
}
|
|
21291
21757
|
if (typeof acValue === "string") {
|
|
@@ -21351,14 +21817,14 @@ async function jiraAuth() {
|
|
|
21351
21817
|
}
|
|
21352
21818
|
|
|
21353
21819
|
// src/commands/jira/viewIssue.ts
|
|
21354
|
-
import
|
|
21820
|
+
import chalk164 from "chalk";
|
|
21355
21821
|
function viewIssue2(issueKey) {
|
|
21356
21822
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
21357
21823
|
const fields = parsed?.fields;
|
|
21358
21824
|
const summary = fields?.summary;
|
|
21359
21825
|
const description = fields?.description;
|
|
21360
21826
|
if (summary) {
|
|
21361
|
-
console.log(
|
|
21827
|
+
console.log(chalk164.bold(summary));
|
|
21362
21828
|
}
|
|
21363
21829
|
if (description) {
|
|
21364
21830
|
if (summary) console.log();
|
|
@@ -21372,7 +21838,7 @@ function viewIssue2(issueKey) {
|
|
|
21372
21838
|
}
|
|
21373
21839
|
if (!summary && !description) {
|
|
21374
21840
|
console.log(
|
|
21375
|
-
|
|
21841
|
+
chalk164.yellow(`No summary or description found on ${issueKey}.`)
|
|
21376
21842
|
);
|
|
21377
21843
|
}
|
|
21378
21844
|
}
|
|
@@ -21407,7 +21873,7 @@ import { randomUUID as randomUUID10 } from "crypto";
|
|
|
21407
21873
|
|
|
21408
21874
|
// src/commands/review/checkoutPr.ts
|
|
21409
21875
|
import { execFileSync as execFileSync12 } from "child_process";
|
|
21410
|
-
import
|
|
21876
|
+
import chalk165 from "chalk";
|
|
21411
21877
|
|
|
21412
21878
|
// src/commands/sessions/daemon/daemonLog.ts
|
|
21413
21879
|
var RING_CAPACITY = 1e3;
|
|
@@ -21444,7 +21910,7 @@ function canonicalTreePath(path80) {
|
|
|
21444
21910
|
}
|
|
21445
21911
|
|
|
21446
21912
|
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
21447
|
-
import { existsSync as
|
|
21913
|
+
import { existsSync as existsSync50 } from "fs";
|
|
21448
21914
|
import { basename as basename16, dirname as dirname25 } from "path";
|
|
21449
21915
|
|
|
21450
21916
|
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
@@ -21491,7 +21957,7 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
|
21491
21957
|
const base = strategy.root ? expandTilde2(strategy.root) : dirname25(clone);
|
|
21492
21958
|
const registered = new Set(listWorktreePaths(clone));
|
|
21493
21959
|
const branches = new Set(listLocalBranches(clone));
|
|
21494
|
-
const isTaken = (candidate) => registered.has(candidate) ||
|
|
21960
|
+
const isTaken = (candidate) => registered.has(candidate) || existsSync50(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename16(candidate));
|
|
21495
21961
|
const path80 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
|
|
21496
21962
|
const start3 = worktreeStartPoint(clone, strategy.trunk);
|
|
21497
21963
|
gitSync(clone, [
|
|
@@ -21517,7 +21983,7 @@ function keptInTree(cwd, reason4) {
|
|
|
21517
21983
|
}
|
|
21518
21984
|
|
|
21519
21985
|
// src/commands/sessions/daemon/worktree/treeDurability.ts
|
|
21520
|
-
import { existsSync as
|
|
21986
|
+
import { existsSync as existsSync51 } from "fs";
|
|
21521
21987
|
var treeIsGone = { durable: true, gone: true };
|
|
21522
21988
|
function treeDurability(state) {
|
|
21523
21989
|
if (state.dirty) return { durable: false, reason: "uncommitted changes" };
|
|
@@ -21548,14 +22014,14 @@ function* durabilityProbes() {
|
|
|
21548
22014
|
});
|
|
21549
22015
|
}
|
|
21550
22016
|
async function checkDurability(cwd) {
|
|
21551
|
-
if (!
|
|
22017
|
+
if (!existsSync51(cwd)) return treeIsGone;
|
|
21552
22018
|
const probes = durabilityProbes();
|
|
21553
22019
|
let step2 = probes.next();
|
|
21554
22020
|
while (!step2.done) step2 = probes.next(await gitResult(cwd, step2.value));
|
|
21555
22021
|
return step2.value;
|
|
21556
22022
|
}
|
|
21557
22023
|
function checkDurabilitySync(cwd) {
|
|
21558
|
-
if (!
|
|
22024
|
+
if (!existsSync51(cwd)) return treeIsGone;
|
|
21559
22025
|
const probes = durabilityProbes();
|
|
21560
22026
|
let step2 = probes.next();
|
|
21561
22027
|
while (!step2.done) step2 = probes.next(gitSyncResult(cwd, step2.value));
|
|
@@ -21798,20 +22264,20 @@ function persistedTreeRoots() {
|
|
|
21798
22264
|
}
|
|
21799
22265
|
|
|
21800
22266
|
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
21801
|
-
import { copyFileSync, existsSync as
|
|
22267
|
+
import { copyFileSync, existsSync as existsSync53, mkdirSync as mkdirSync17 } from "fs";
|
|
21802
22268
|
import { dirname as dirname26, join as join56 } from "path";
|
|
21803
22269
|
|
|
21804
22270
|
// src/commands/sessions/daemon/worktree/runInstall.ts
|
|
21805
22271
|
import { spawn as spawn5 } from "child_process";
|
|
21806
22272
|
|
|
21807
22273
|
// src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
|
|
21808
|
-
import { existsSync as
|
|
22274
|
+
import { existsSync as existsSync52 } from "fs";
|
|
21809
22275
|
import { join as join55 } from "path";
|
|
21810
22276
|
function detectInstallCommand(repoRoot2) {
|
|
21811
|
-
if (!
|
|
21812
|
-
if (
|
|
21813
|
-
if (
|
|
21814
|
-
if (
|
|
22277
|
+
if (!existsSync52(join55(repoRoot2, "package.json"))) return null;
|
|
22278
|
+
if (existsSync52(join55(repoRoot2, "pnpm-lock.yaml"))) return "pnpm install";
|
|
22279
|
+
if (existsSync52(join55(repoRoot2, "yarn.lock"))) return "yarn install";
|
|
22280
|
+
if (existsSync52(join55(repoRoot2, "bun.lockb"))) return "bun install";
|
|
21815
22281
|
return "npm install";
|
|
21816
22282
|
}
|
|
21817
22283
|
function resolveInstallCommand(repoRoot2, install) {
|
|
@@ -21924,7 +22390,7 @@ function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
|
21924
22390
|
function copyConfigFiles(worktreePath, clone, copy) {
|
|
21925
22391
|
for (const rel of copy) {
|
|
21926
22392
|
const src = join56(clone, rel);
|
|
21927
|
-
if (!
|
|
22393
|
+
if (!existsSync53(src)) continue;
|
|
21928
22394
|
const dest = join56(worktreePath, rel);
|
|
21929
22395
|
try {
|
|
21930
22396
|
mkdirSync17(dirname26(dest), { recursive: true });
|
|
@@ -22019,7 +22485,7 @@ async function checkoutPr(number) {
|
|
|
22019
22485
|
try {
|
|
22020
22486
|
execFileSync12("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
22021
22487
|
} catch {
|
|
22022
|
-
console.error(
|
|
22488
|
+
console.error(chalk165.red(`gh pr checkout ${number} failed; aborting.`));
|
|
22023
22489
|
process.exit(1);
|
|
22024
22490
|
}
|
|
22025
22491
|
}
|
|
@@ -22156,15 +22622,15 @@ function registerList(program2) {
|
|
|
22156
22622
|
// src/commands/mermaid/index.ts
|
|
22157
22623
|
import { mkdirSync as mkdirSync18, readdirSync as readdirSync11 } from "fs";
|
|
22158
22624
|
import { resolve as resolve16 } from "path";
|
|
22159
|
-
import
|
|
22625
|
+
import chalk168 from "chalk";
|
|
22160
22626
|
|
|
22161
22627
|
// src/commands/mermaid/exportFile.ts
|
|
22162
|
-
import { readFileSync as
|
|
22628
|
+
import { readFileSync as readFileSync39, writeFileSync as writeFileSync32 } from "fs";
|
|
22163
22629
|
import { basename as basename17, extname as extname2, resolve as resolve15 } from "path";
|
|
22164
|
-
import
|
|
22630
|
+
import chalk167 from "chalk";
|
|
22165
22631
|
|
|
22166
22632
|
// src/commands/mermaid/renderBlock.ts
|
|
22167
|
-
import
|
|
22633
|
+
import chalk166 from "chalk";
|
|
22168
22634
|
async function renderBlock(krokiUrl, source) {
|
|
22169
22635
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
22170
22636
|
method: "POST",
|
|
@@ -22173,7 +22639,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
22173
22639
|
});
|
|
22174
22640
|
if (!response.ok) {
|
|
22175
22641
|
console.error(
|
|
22176
|
-
|
|
22642
|
+
chalk166.red(
|
|
22177
22643
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
22178
22644
|
)
|
|
22179
22645
|
);
|
|
@@ -22185,25 +22651,25 @@ async function renderBlock(krokiUrl, source) {
|
|
|
22185
22651
|
|
|
22186
22652
|
// src/commands/mermaid/exportFile.ts
|
|
22187
22653
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
22188
|
-
const content =
|
|
22654
|
+
const content = readFileSync39(file, "utf8");
|
|
22189
22655
|
const blocks = extractMermaidBlocks(content);
|
|
22190
22656
|
const stem = basename17(file, extname2(file));
|
|
22191
22657
|
if (onlyIndex !== void 0) {
|
|
22192
22658
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
22193
22659
|
console.error(
|
|
22194
|
-
|
|
22660
|
+
chalk167.red(
|
|
22195
22661
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
22196
22662
|
)
|
|
22197
22663
|
);
|
|
22198
22664
|
process.exit(1);
|
|
22199
22665
|
}
|
|
22200
22666
|
console.log(
|
|
22201
|
-
|
|
22667
|
+
chalk167.gray(
|
|
22202
22668
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
22203
22669
|
)
|
|
22204
22670
|
);
|
|
22205
22671
|
} else {
|
|
22206
|
-
console.log(
|
|
22672
|
+
console.log(chalk167.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
22207
22673
|
}
|
|
22208
22674
|
for (const [i, source] of blocks.entries()) {
|
|
22209
22675
|
const idx = i + 1;
|
|
@@ -22211,7 +22677,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
22211
22677
|
const outPath = resolve15(outDir, `${stem}-${idx}.svg`);
|
|
22212
22678
|
const svg = await renderBlock(krokiUrl, source);
|
|
22213
22679
|
writeFileSync32(outPath, svg, "utf8");
|
|
22214
|
-
console.log(
|
|
22680
|
+
console.log(chalk167.green(` \u2192 ${outPath}`));
|
|
22215
22681
|
}
|
|
22216
22682
|
}
|
|
22217
22683
|
function extractMermaidBlocks(markdown) {
|
|
@@ -22227,18 +22693,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
22227
22693
|
if (options2.index !== void 0) {
|
|
22228
22694
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
22229
22695
|
console.error(
|
|
22230
|
-
|
|
22696
|
+
chalk168.red(`--index must be a positive integer (got ${options2.index})`)
|
|
22231
22697
|
);
|
|
22232
22698
|
process.exit(1);
|
|
22233
22699
|
}
|
|
22234
22700
|
if (!file) {
|
|
22235
|
-
console.error(
|
|
22701
|
+
console.error(chalk168.red("--index requires a file argument"));
|
|
22236
22702
|
process.exit(1);
|
|
22237
22703
|
}
|
|
22238
22704
|
}
|
|
22239
22705
|
const files = file ? [file] : readdirSync11(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
22240
22706
|
if (files.length === 0) {
|
|
22241
|
-
console.log(
|
|
22707
|
+
console.log(chalk168.gray("No markdown files found in current directory."));
|
|
22242
22708
|
return;
|
|
22243
22709
|
}
|
|
22244
22710
|
for (const f of files) {
|
|
@@ -22265,7 +22731,7 @@ function registerMermaid(program2) {
|
|
|
22265
22731
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
22266
22732
|
import { createServer as createServer2 } from "http";
|
|
22267
22733
|
import { dirname as dirname28 } from "path";
|
|
22268
|
-
import
|
|
22734
|
+
import chalk170 from "chalk";
|
|
22269
22735
|
|
|
22270
22736
|
// src/commands/netcap/corsHeaders.ts
|
|
22271
22737
|
var corsHeaders = {
|
|
@@ -22344,7 +22810,7 @@ function createNetcapHandler(options2) {
|
|
|
22344
22810
|
import { cp, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
22345
22811
|
import { networkInterfaces } from "os";
|
|
22346
22812
|
import { join as join58 } from "path";
|
|
22347
|
-
import
|
|
22813
|
+
import chalk169 from "chalk";
|
|
22348
22814
|
|
|
22349
22815
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
22350
22816
|
import { dirname as dirname27, join as join57 } from "path";
|
|
@@ -22388,7 +22854,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
22388
22854
|
const host = lanIPv4();
|
|
22389
22855
|
if (!host) {
|
|
22390
22856
|
console.log(
|
|
22391
|
-
|
|
22857
|
+
chalk169.yellow("could not determine the WSL IP for the extension")
|
|
22392
22858
|
);
|
|
22393
22859
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
22394
22860
|
return source;
|
|
@@ -22399,7 +22865,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
22399
22865
|
return WSL_WINDOWS_PATH;
|
|
22400
22866
|
} catch {
|
|
22401
22867
|
console.log(
|
|
22402
|
-
|
|
22868
|
+
chalk169.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
22403
22869
|
);
|
|
22404
22870
|
return source;
|
|
22405
22871
|
}
|
|
@@ -22432,30 +22898,30 @@ async function netcap(options2) {
|
|
|
22432
22898
|
let count8 = 0;
|
|
22433
22899
|
const handler = createNetcapHandler({
|
|
22434
22900
|
outPath,
|
|
22435
|
-
onPing: () => console.log(
|
|
22901
|
+
onPing: () => console.log(chalk170.dim("ping from extension")),
|
|
22436
22902
|
onCapture: (entry) => {
|
|
22437
22903
|
count8 += 1;
|
|
22438
22904
|
console.log(
|
|
22439
|
-
|
|
22440
|
-
|
|
22905
|
+
chalk170.green(`captured #${count8}`),
|
|
22906
|
+
chalk170.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
22441
22907
|
);
|
|
22442
22908
|
}
|
|
22443
22909
|
});
|
|
22444
22910
|
const server = createServer2(handler);
|
|
22445
22911
|
server.listen(port, () => {
|
|
22446
22912
|
console.log(
|
|
22447
|
-
|
|
22913
|
+
chalk170.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
22448
22914
|
);
|
|
22449
|
-
console.log(
|
|
22915
|
+
console.log(chalk170.dim(`appending captures to ${outPath}`));
|
|
22450
22916
|
if (filter)
|
|
22451
|
-
console.log(
|
|
22452
|
-
console.log(
|
|
22453
|
-
console.log(
|
|
22917
|
+
console.log(chalk170.dim(`forwarding only URLs matching "${filter}"`));
|
|
22918
|
+
console.log(chalk170.dim(`load the unpacked extension from ${extensionPath}`));
|
|
22919
|
+
console.log(chalk170.dim("press Ctrl-C to stop"));
|
|
22454
22920
|
});
|
|
22455
22921
|
process.on("SIGINT", () => {
|
|
22456
22922
|
server.close();
|
|
22457
22923
|
console.log(
|
|
22458
|
-
|
|
22924
|
+
chalk170.bold(
|
|
22459
22925
|
`
|
|
22460
22926
|
netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
22461
22927
|
)
|
|
@@ -22467,10 +22933,10 @@ netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} t
|
|
|
22467
22933
|
// src/commands/netcap/netcapExtract.ts
|
|
22468
22934
|
import { writeFileSync as writeFileSync33 } from "fs";
|
|
22469
22935
|
import { join as join61 } from "path";
|
|
22470
|
-
import
|
|
22936
|
+
import chalk171 from "chalk";
|
|
22471
22937
|
|
|
22472
22938
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
22473
|
-
import { readFileSync as
|
|
22939
|
+
import { readFileSync as readFileSync40 } from "fs";
|
|
22474
22940
|
|
|
22475
22941
|
// src/commands/netcap/parseRscRows.ts
|
|
22476
22942
|
var isRscRef = (v) => typeof v === "string" && /^\$[0-9a-fL@]/.test(v);
|
|
@@ -22866,7 +23332,7 @@ function extractVoyagerPosts(body) {
|
|
|
22866
23332
|
|
|
22867
23333
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
22868
23334
|
function captureEntries(captureFile) {
|
|
22869
|
-
const lines2 =
|
|
23335
|
+
const lines2 = readFileSync40(captureFile, "utf8").split("\n").filter(Boolean);
|
|
22870
23336
|
const entries = [];
|
|
22871
23337
|
for (const line of lines2) {
|
|
22872
23338
|
let entry;
|
|
@@ -22915,8 +23381,8 @@ function netcapExtract(file) {
|
|
|
22915
23381
|
writeFileSync33(outFile, `${JSON.stringify(posts, null, 2)}
|
|
22916
23382
|
`);
|
|
22917
23383
|
console.log(
|
|
22918
|
-
|
|
22919
|
-
|
|
23384
|
+
chalk171.green(`extracted ${posts.length} posts`),
|
|
23385
|
+
chalk171.dim(`-> ${outFile}`)
|
|
22920
23386
|
);
|
|
22921
23387
|
}
|
|
22922
23388
|
|
|
@@ -22937,7 +23403,7 @@ function registerNetcap(program2) {
|
|
|
22937
23403
|
}
|
|
22938
23404
|
|
|
22939
23405
|
// src/commands/news/add/index.ts
|
|
22940
|
-
import
|
|
23406
|
+
import chalk172 from "chalk";
|
|
22941
23407
|
import enquirer8 from "enquirer";
|
|
22942
23408
|
async function add2(url) {
|
|
22943
23409
|
if (!url) {
|
|
@@ -22959,10 +23425,10 @@ async function add2(url) {
|
|
|
22959
23425
|
const { orm } = await getReady();
|
|
22960
23426
|
const added = await addFeed(orm, url);
|
|
22961
23427
|
if (!added) {
|
|
22962
|
-
console.log(
|
|
23428
|
+
console.log(chalk172.yellow("Feed already exists"));
|
|
22963
23429
|
return;
|
|
22964
23430
|
}
|
|
22965
|
-
console.log(
|
|
23431
|
+
console.log(chalk172.green(`Added feed: ${url}`));
|
|
22966
23432
|
}
|
|
22967
23433
|
|
|
22968
23434
|
// src/commands/registerNews.ts
|
|
@@ -23009,7 +23475,7 @@ function registerPiHook(program2) {
|
|
|
23009
23475
|
}
|
|
23010
23476
|
|
|
23011
23477
|
// src/commands/prompts/printPromptsTable.ts
|
|
23012
|
-
import
|
|
23478
|
+
import chalk173 from "chalk";
|
|
23013
23479
|
function truncate(str, max) {
|
|
23014
23480
|
if (str.length <= max) return str;
|
|
23015
23481
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -23027,14 +23493,14 @@ function printPromptsTable(rows) {
|
|
|
23027
23493
|
"Command".padEnd(commandWidth),
|
|
23028
23494
|
"Repos"
|
|
23029
23495
|
].join(" ");
|
|
23030
|
-
console.log(
|
|
23031
|
-
console.log(
|
|
23496
|
+
console.log(chalk173.dim(header));
|
|
23497
|
+
console.log(chalk173.dim("-".repeat(header.length)));
|
|
23032
23498
|
for (const row of rows) {
|
|
23033
23499
|
const count8 = String(row.count).padStart(countWidth);
|
|
23034
23500
|
const tool = row.tool.padEnd(toolWidth);
|
|
23035
23501
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
23036
23502
|
console.log(
|
|
23037
|
-
`${
|
|
23503
|
+
`${chalk173.yellow(count8)} ${tool} ${command} ${chalk173.dim(row.repos)}`
|
|
23038
23504
|
);
|
|
23039
23505
|
}
|
|
23040
23506
|
}
|
|
@@ -23440,7 +23906,7 @@ import { tmpdir as tmpdir6 } from "os";
|
|
|
23440
23906
|
import { join as join63 } from "path";
|
|
23441
23907
|
|
|
23442
23908
|
// src/commands/prs/loadCommentsCache.ts
|
|
23443
|
-
import { existsSync as
|
|
23909
|
+
import { existsSync as existsSync54, readFileSync as readFileSync41, unlinkSync as unlinkSync13 } from "fs";
|
|
23444
23910
|
import { parse as parse2 } from "yaml";
|
|
23445
23911
|
|
|
23446
23912
|
// src/commands/prs/commentsCachePath.ts
|
|
@@ -23460,24 +23926,24 @@ function commentsCachePath(org, repo, prNumber) {
|
|
|
23460
23926
|
// src/commands/prs/loadCommentsCache.ts
|
|
23461
23927
|
function loadCommentsCache(org, repo, prNumber) {
|
|
23462
23928
|
const cachePath = commentsCachePath(org, repo, prNumber);
|
|
23463
|
-
if (!
|
|
23929
|
+
if (!existsSync54(cachePath)) {
|
|
23464
23930
|
return null;
|
|
23465
23931
|
}
|
|
23466
|
-
const content =
|
|
23932
|
+
const content = readFileSync41(cachePath, "utf8");
|
|
23467
23933
|
return parse2(content);
|
|
23468
23934
|
}
|
|
23469
23935
|
function deleteCommentsCache(org, repo, prNumber) {
|
|
23470
23936
|
const cachePath = commentsCachePath(org, repo, prNumber);
|
|
23471
|
-
if (
|
|
23937
|
+
if (existsSync54(cachePath)) {
|
|
23472
23938
|
unlinkSync13(cachePath);
|
|
23473
23939
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
23474
23940
|
}
|
|
23475
23941
|
}
|
|
23476
23942
|
|
|
23477
23943
|
// src/commands/prs/replyToComment.ts
|
|
23478
|
-
import { spawnSync as
|
|
23944
|
+
import { spawnSync as spawnSync6 } from "child_process";
|
|
23479
23945
|
function replyToComment(org, repo, prNumber, commentId, message3) {
|
|
23480
|
-
const result =
|
|
23946
|
+
const result = spawnSync6(
|
|
23481
23947
|
"gh",
|
|
23482
23948
|
[
|
|
23483
23949
|
"api",
|
|
@@ -23701,13 +24167,13 @@ function agentFooter(unresolvedCount) {
|
|
|
23701
24167
|
}
|
|
23702
24168
|
|
|
23703
24169
|
// src/commands/prs/listComments/commentStyle.ts
|
|
23704
|
-
import
|
|
24170
|
+
import chalk174 from "chalk";
|
|
23705
24171
|
var plain = (text18) => text18;
|
|
23706
24172
|
function colouredState(state) {
|
|
23707
24173
|
const label2 = `[${state}]`;
|
|
23708
|
-
if (state === "APPROVED") return
|
|
23709
|
-
if (state === "CHANGES_REQUESTED") return
|
|
23710
|
-
return
|
|
24174
|
+
if (state === "APPROVED") return chalk174.green(label2);
|
|
24175
|
+
if (state === "CHANGES_REQUESTED") return chalk174.red(label2);
|
|
24176
|
+
return chalk174.yellow(label2);
|
|
23711
24177
|
}
|
|
23712
24178
|
function commentStyle() {
|
|
23713
24179
|
if (isClaudeCode()) {
|
|
@@ -23721,9 +24187,9 @@ function commentStyle() {
|
|
|
23721
24187
|
};
|
|
23722
24188
|
}
|
|
23723
24189
|
return {
|
|
23724
|
-
cyan:
|
|
23725
|
-
bold:
|
|
23726
|
-
dim:
|
|
24190
|
+
cyan: chalk174.cyan,
|
|
24191
|
+
bold: chalk174.bold,
|
|
24192
|
+
dim: chalk174.dim,
|
|
23727
24193
|
state: colouredState,
|
|
23728
24194
|
diffHunk: true,
|
|
23729
24195
|
agent: false
|
|
@@ -23893,13 +24359,13 @@ import { execSync as execSync48 } from "child_process";
|
|
|
23893
24359
|
import enquirer9 from "enquirer";
|
|
23894
24360
|
|
|
23895
24361
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
23896
|
-
import
|
|
24362
|
+
import chalk175 from "chalk";
|
|
23897
24363
|
var STATUS_MAP = {
|
|
23898
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
23899
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
24364
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk175.magenta("merged"), date: pr.mergedAt } : null,
|
|
24365
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk175.red("closed"), date: pr.closedAt } : null
|
|
23900
24366
|
};
|
|
23901
24367
|
function defaultStatus(pr) {
|
|
23902
|
-
return { label:
|
|
24368
|
+
return { label: chalk175.green("opened"), date: pr.createdAt };
|
|
23903
24369
|
}
|
|
23904
24370
|
function getStatus2(pr) {
|
|
23905
24371
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -23908,11 +24374,11 @@ function formatDate(dateStr) {
|
|
|
23908
24374
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
23909
24375
|
}
|
|
23910
24376
|
function formatPrHeader(pr, status3) {
|
|
23911
|
-
return `${
|
|
24377
|
+
return `${chalk175.cyan(`#${pr.number}`)} ${pr.title} ${chalk175.dim(`(${pr.author.login},`)} ${status3.label} ${chalk175.dim(`${formatDate(status3.date)})`)}`;
|
|
23912
24378
|
}
|
|
23913
24379
|
function logPrDetails(pr) {
|
|
23914
24380
|
console.log(
|
|
23915
|
-
|
|
24381
|
+
chalk175.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
23916
24382
|
);
|
|
23917
24383
|
console.log();
|
|
23918
24384
|
}
|
|
@@ -24627,10 +25093,10 @@ function registerPrs(program2) {
|
|
|
24627
25093
|
}
|
|
24628
25094
|
|
|
24629
25095
|
// src/commands/ravendb/ravendbAuth.ts
|
|
24630
|
-
import
|
|
25096
|
+
import chalk181 from "chalk";
|
|
24631
25097
|
|
|
24632
25098
|
// src/shared/createConnectionAuth.ts
|
|
24633
|
-
import
|
|
25099
|
+
import chalk176 from "chalk";
|
|
24634
25100
|
function listConnections(connections, format) {
|
|
24635
25101
|
if (connections.length === 0) {
|
|
24636
25102
|
console.log("No connections configured.");
|
|
@@ -24643,7 +25109,7 @@ function listConnections(connections, format) {
|
|
|
24643
25109
|
function removeConnection(connections, name, save) {
|
|
24644
25110
|
const filtered = connections.filter((c) => c.name !== name);
|
|
24645
25111
|
if (filtered.length === connections.length) {
|
|
24646
|
-
console.error(
|
|
25112
|
+
console.error(chalk176.red(`Connection "${name}" not found.`));
|
|
24647
25113
|
process.exit(1);
|
|
24648
25114
|
}
|
|
24649
25115
|
save(filtered);
|
|
@@ -24689,15 +25155,15 @@ function saveConnections(connections) {
|
|
|
24689
25155
|
}
|
|
24690
25156
|
|
|
24691
25157
|
// src/commands/ravendb/promptConnection.ts
|
|
24692
|
-
import
|
|
25158
|
+
import chalk179 from "chalk";
|
|
24693
25159
|
|
|
24694
25160
|
// src/commands/ravendb/selectOpSecret.ts
|
|
24695
|
-
import
|
|
25161
|
+
import chalk178 from "chalk";
|
|
24696
25162
|
import Enquirer2 from "enquirer";
|
|
24697
25163
|
|
|
24698
25164
|
// src/commands/ravendb/searchItems.ts
|
|
24699
25165
|
import { execSync as execSync51 } from "child_process";
|
|
24700
|
-
import
|
|
25166
|
+
import chalk177 from "chalk";
|
|
24701
25167
|
function opExec(args) {
|
|
24702
25168
|
return execSync51(`op ${args}`, {
|
|
24703
25169
|
encoding: "utf8",
|
|
@@ -24710,7 +25176,7 @@ function searchItems(search2) {
|
|
|
24710
25176
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
24711
25177
|
} catch {
|
|
24712
25178
|
console.error(
|
|
24713
|
-
|
|
25179
|
+
chalk177.red(
|
|
24714
25180
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
24715
25181
|
)
|
|
24716
25182
|
);
|
|
@@ -24724,7 +25190,7 @@ function getItemFields(itemId2) {
|
|
|
24724
25190
|
const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
|
|
24725
25191
|
return item.fields.filter((f) => f.reference && f.label);
|
|
24726
25192
|
} catch {
|
|
24727
|
-
console.error(
|
|
25193
|
+
console.error(chalk177.red("Failed to get item details from 1Password."));
|
|
24728
25194
|
process.exit(1);
|
|
24729
25195
|
}
|
|
24730
25196
|
}
|
|
@@ -24743,7 +25209,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
24743
25209
|
}).run();
|
|
24744
25210
|
const items2 = searchItems(search2);
|
|
24745
25211
|
if (items2.length === 0) {
|
|
24746
|
-
console.error(
|
|
25212
|
+
console.error(chalk178.red(`No items found matching "${search2}".`));
|
|
24747
25213
|
process.exit(1);
|
|
24748
25214
|
}
|
|
24749
25215
|
const itemId2 = await selectOne(
|
|
@@ -24752,7 +25218,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
24752
25218
|
);
|
|
24753
25219
|
const fields = getItemFields(itemId2);
|
|
24754
25220
|
if (fields.length === 0) {
|
|
24755
|
-
console.error(
|
|
25221
|
+
console.error(chalk178.red("No fields with references found on this item."));
|
|
24756
25222
|
process.exit(1);
|
|
24757
25223
|
}
|
|
24758
25224
|
const ref = await selectOne(
|
|
@@ -24766,7 +25232,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
24766
25232
|
async function promptConnection(existingNames) {
|
|
24767
25233
|
const name = await promptInput("name", "Connection name:");
|
|
24768
25234
|
if (existingNames.includes(name)) {
|
|
24769
|
-
console.error(
|
|
25235
|
+
console.error(chalk179.red(`Connection "${name}" already exists.`));
|
|
24770
25236
|
process.exit(1);
|
|
24771
25237
|
}
|
|
24772
25238
|
const url = await promptInput(
|
|
@@ -24775,22 +25241,22 @@ async function promptConnection(existingNames) {
|
|
|
24775
25241
|
);
|
|
24776
25242
|
const database = await promptInput("database", "Database name:");
|
|
24777
25243
|
if (!name || !url || !database) {
|
|
24778
|
-
console.error(
|
|
25244
|
+
console.error(chalk179.red("All fields are required."));
|
|
24779
25245
|
process.exit(1);
|
|
24780
25246
|
}
|
|
24781
25247
|
const apiKeyRef = await selectOpSecret();
|
|
24782
|
-
console.log(
|
|
25248
|
+
console.log(chalk179.dim(`Using: ${apiKeyRef}`));
|
|
24783
25249
|
return { name, url, database, apiKeyRef };
|
|
24784
25250
|
}
|
|
24785
25251
|
|
|
24786
25252
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
24787
|
-
import
|
|
25253
|
+
import chalk180 from "chalk";
|
|
24788
25254
|
function ravendbSetConnection(name) {
|
|
24789
25255
|
const raw = loadGlobalConfigRaw();
|
|
24790
25256
|
const ravendb = raw.ravendb ?? {};
|
|
24791
25257
|
const connections = ravendb.connections ?? [];
|
|
24792
25258
|
if (!connections.some((c) => c.name === name)) {
|
|
24793
|
-
console.error(
|
|
25259
|
+
console.error(chalk180.red(`Connection "${name}" not found.`));
|
|
24794
25260
|
console.error(
|
|
24795
25261
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
24796
25262
|
);
|
|
@@ -24806,16 +25272,16 @@ function ravendbSetConnection(name) {
|
|
|
24806
25272
|
var ravendbAuth = createConnectionAuth({
|
|
24807
25273
|
load: loadConnections,
|
|
24808
25274
|
save: saveConnections,
|
|
24809
|
-
format: (c) => `${
|
|
25275
|
+
format: (c) => `${chalk181.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
24810
25276
|
promptNew: promptConnection,
|
|
24811
25277
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
24812
25278
|
});
|
|
24813
25279
|
|
|
24814
25280
|
// src/commands/ravendb/ravendbCollections.ts
|
|
24815
|
-
import
|
|
25281
|
+
import chalk185 from "chalk";
|
|
24816
25282
|
|
|
24817
25283
|
// src/commands/ravendb/ravenFetch.ts
|
|
24818
|
-
import
|
|
25284
|
+
import chalk183 from "chalk";
|
|
24819
25285
|
|
|
24820
25286
|
// src/commands/ravendb/getAccessToken.ts
|
|
24821
25287
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -24852,10 +25318,10 @@ ${errorText}`
|
|
|
24852
25318
|
|
|
24853
25319
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
24854
25320
|
import { execSync as execSync52 } from "child_process";
|
|
24855
|
-
import
|
|
25321
|
+
import chalk182 from "chalk";
|
|
24856
25322
|
function resolveOpSecret(reference) {
|
|
24857
25323
|
if (!reference.startsWith("op://")) {
|
|
24858
|
-
console.error(
|
|
25324
|
+
console.error(chalk182.red(`Invalid secret reference: must start with op://`));
|
|
24859
25325
|
process.exit(1);
|
|
24860
25326
|
}
|
|
24861
25327
|
try {
|
|
@@ -24865,7 +25331,7 @@ function resolveOpSecret(reference) {
|
|
|
24865
25331
|
}).trim();
|
|
24866
25332
|
} catch {
|
|
24867
25333
|
console.error(
|
|
24868
|
-
|
|
25334
|
+
chalk182.red(
|
|
24869
25335
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
24870
25336
|
)
|
|
24871
25337
|
);
|
|
@@ -24892,7 +25358,7 @@ async function ravenFetch(connection, path80) {
|
|
|
24892
25358
|
if (!response.ok) {
|
|
24893
25359
|
const body = await response.text();
|
|
24894
25360
|
console.error(
|
|
24895
|
-
|
|
25361
|
+
chalk183.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
24896
25362
|
);
|
|
24897
25363
|
console.error(body.substring(0, 500));
|
|
24898
25364
|
process.exit(1);
|
|
@@ -24901,7 +25367,7 @@ async function ravenFetch(connection, path80) {
|
|
|
24901
25367
|
}
|
|
24902
25368
|
|
|
24903
25369
|
// src/commands/ravendb/resolveConnection.ts
|
|
24904
|
-
import
|
|
25370
|
+
import chalk184 from "chalk";
|
|
24905
25371
|
function loadRavendb() {
|
|
24906
25372
|
const raw = loadGlobalConfigRaw();
|
|
24907
25373
|
const ravendb = raw.ravendb;
|
|
@@ -24915,7 +25381,7 @@ function resolveConnection(name) {
|
|
|
24915
25381
|
const connectionName = name ?? defaultConnection;
|
|
24916
25382
|
if (!connectionName) {
|
|
24917
25383
|
console.error(
|
|
24918
|
-
|
|
25384
|
+
chalk184.red(
|
|
24919
25385
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
24920
25386
|
)
|
|
24921
25387
|
);
|
|
@@ -24923,7 +25389,7 @@ function resolveConnection(name) {
|
|
|
24923
25389
|
}
|
|
24924
25390
|
const connection = connections.find((c) => c.name === connectionName);
|
|
24925
25391
|
if (!connection) {
|
|
24926
|
-
console.error(
|
|
25392
|
+
console.error(chalk184.red(`Connection "${connectionName}" not found.`));
|
|
24927
25393
|
console.error(
|
|
24928
25394
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
24929
25395
|
);
|
|
@@ -24954,15 +25420,15 @@ async function ravendbCollections(connectionName) {
|
|
|
24954
25420
|
return;
|
|
24955
25421
|
}
|
|
24956
25422
|
for (const c of collections) {
|
|
24957
|
-
console.log(`${
|
|
25423
|
+
console.log(`${chalk185.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
24958
25424
|
}
|
|
24959
25425
|
}
|
|
24960
25426
|
|
|
24961
25427
|
// src/commands/ravendb/ravendbQuery.ts
|
|
24962
|
-
import
|
|
25428
|
+
import chalk187 from "chalk";
|
|
24963
25429
|
|
|
24964
25430
|
// src/commands/ravendb/fetchAllPages.ts
|
|
24965
|
-
import
|
|
25431
|
+
import chalk186 from "chalk";
|
|
24966
25432
|
|
|
24967
25433
|
// src/commands/ravendb/buildQueryPath.ts
|
|
24968
25434
|
function buildQueryPath(opts) {
|
|
@@ -25000,7 +25466,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25000
25466
|
allResults.push(...results);
|
|
25001
25467
|
start3 += results.length;
|
|
25002
25468
|
process.stderr.write(
|
|
25003
|
-
`\r${
|
|
25469
|
+
`\r${chalk186.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
25004
25470
|
);
|
|
25005
25471
|
if (start3 >= totalResults) break;
|
|
25006
25472
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -25015,7 +25481,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25015
25481
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
25016
25482
|
const resolved = resolveArgs(connectionName, collection);
|
|
25017
25483
|
if (!resolved.collection && !options2.query) {
|
|
25018
|
-
console.error(
|
|
25484
|
+
console.error(chalk187.red("Provide a collection name or --query filter."));
|
|
25019
25485
|
process.exit(1);
|
|
25020
25486
|
}
|
|
25021
25487
|
const { collection: col } = resolved;
|
|
@@ -25054,7 +25520,7 @@ import { spawn as spawn6 } from "child_process";
|
|
|
25054
25520
|
import * as path42 from "path";
|
|
25055
25521
|
|
|
25056
25522
|
// src/commands/refactor/logViolations.ts
|
|
25057
|
-
import
|
|
25523
|
+
import chalk188 from "chalk";
|
|
25058
25524
|
var DEFAULT_MAX_LINES2 = 100;
|
|
25059
25525
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
25060
25526
|
if (violations.length === 0) {
|
|
@@ -25063,43 +25529,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
|
25063
25529
|
}
|
|
25064
25530
|
return;
|
|
25065
25531
|
}
|
|
25066
|
-
console.error(
|
|
25532
|
+
console.error(chalk188.red(`
|
|
25067
25533
|
Refactor check failed:
|
|
25068
25534
|
`));
|
|
25069
|
-
console.error(
|
|
25535
|
+
console.error(chalk188.red(` The following files exceed ${maxLines} lines:
|
|
25070
25536
|
`));
|
|
25071
25537
|
for (const violation of violations) {
|
|
25072
|
-
console.error(
|
|
25538
|
+
console.error(chalk188.red(` ${violation.file} (${violation.lines} lines)`));
|
|
25073
25539
|
}
|
|
25074
25540
|
console.error(
|
|
25075
|
-
|
|
25541
|
+
chalk188.yellow(
|
|
25076
25542
|
`
|
|
25077
25543
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
25078
25544
|
way to refactor it, ignore it with:
|
|
25079
25545
|
`
|
|
25080
25546
|
)
|
|
25081
25547
|
);
|
|
25082
|
-
console.error(
|
|
25548
|
+
console.error(chalk188.gray(` assist refactor ignore <file>
|
|
25083
25549
|
`));
|
|
25084
25550
|
if (process.env.CLAUDECODE) {
|
|
25085
|
-
console.error(
|
|
25551
|
+
console.error(chalk188.cyan(`
|
|
25086
25552
|
## Extracting Code to New Files
|
|
25087
25553
|
`));
|
|
25088
25554
|
console.error(
|
|
25089
|
-
|
|
25555
|
+
chalk188.cyan(
|
|
25090
25556
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
25091
25557
|
`
|
|
25092
25558
|
)
|
|
25093
25559
|
);
|
|
25094
25560
|
console.error(
|
|
25095
|
-
|
|
25561
|
+
chalk188.cyan(
|
|
25096
25562
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
25097
25563
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
25098
25564
|
`
|
|
25099
25565
|
)
|
|
25100
25566
|
);
|
|
25101
25567
|
console.error(
|
|
25102
|
-
|
|
25568
|
+
chalk188.cyan(
|
|
25103
25569
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
25104
25570
|
domains, move it to a common/shared folder.
|
|
25105
25571
|
`
|
|
@@ -25255,7 +25721,7 @@ async function check(pattern2, options2) {
|
|
|
25255
25721
|
|
|
25256
25722
|
// src/commands/refactor/extract/index.ts
|
|
25257
25723
|
import path50 from "path";
|
|
25258
|
-
import
|
|
25724
|
+
import chalk191 from "chalk";
|
|
25259
25725
|
|
|
25260
25726
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
25261
25727
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -25854,23 +26320,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
25854
26320
|
|
|
25855
26321
|
// src/commands/refactor/extract/displayPlan.ts
|
|
25856
26322
|
import path46 from "path";
|
|
25857
|
-
import
|
|
26323
|
+
import chalk189 from "chalk";
|
|
25858
26324
|
function section2(title) {
|
|
25859
26325
|
return `
|
|
25860
|
-
${
|
|
26326
|
+
${chalk189.cyan(title)}`;
|
|
25861
26327
|
}
|
|
25862
26328
|
function displayImporters(plan2, cwd) {
|
|
25863
26329
|
if (plan2.importersToUpdate.length === 0) return;
|
|
25864
26330
|
console.log(section2("Update importers:"));
|
|
25865
26331
|
for (const imp of plan2.importersToUpdate) {
|
|
25866
26332
|
const rel = path46.relative(cwd, imp.file.getFilePath());
|
|
25867
|
-
console.log(` ${
|
|
26333
|
+
console.log(` ${chalk189.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
25868
26334
|
}
|
|
25869
26335
|
}
|
|
25870
26336
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
25871
|
-
console.log(
|
|
26337
|
+
console.log(chalk189.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
25872
26338
|
`));
|
|
25873
|
-
console.log(` ${
|
|
26339
|
+
console.log(` ${chalk189.cyan("Functions to move:")}`);
|
|
25874
26340
|
for (const name of plan2.extractedNames) {
|
|
25875
26341
|
console.log(` ${name}`);
|
|
25876
26342
|
}
|
|
@@ -25904,7 +26370,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
25904
26370
|
|
|
25905
26371
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
25906
26372
|
import path49 from "path";
|
|
25907
|
-
import
|
|
26373
|
+
import chalk190 from "chalk";
|
|
25908
26374
|
import { Project as Project4 } from "ts-morph";
|
|
25909
26375
|
|
|
25910
26376
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -25996,7 +26462,7 @@ function loadProjectFile(file) {
|
|
|
25996
26462
|
});
|
|
25997
26463
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
25998
26464
|
if (!sourceFile) {
|
|
25999
|
-
console.log(
|
|
26465
|
+
console.log(chalk190.red(`File not found in project: ${file}`));
|
|
26000
26466
|
process.exit(1);
|
|
26001
26467
|
}
|
|
26002
26468
|
return { project, sourceFile };
|
|
@@ -26019,19 +26485,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
26019
26485
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
26020
26486
|
if (options2.apply) {
|
|
26021
26487
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
26022
|
-
console.log(
|
|
26488
|
+
console.log(chalk191.green("\nExtraction complete"));
|
|
26023
26489
|
} else {
|
|
26024
|
-
console.log(
|
|
26490
|
+
console.log(chalk191.dim("\nDry run. Use --apply to execute."));
|
|
26025
26491
|
}
|
|
26026
26492
|
}
|
|
26027
26493
|
|
|
26028
26494
|
// src/commands/refactor/ignore.ts
|
|
26029
26495
|
import fs33 from "fs";
|
|
26030
|
-
import
|
|
26496
|
+
import chalk192 from "chalk";
|
|
26031
26497
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
26032
26498
|
function ignore2(file) {
|
|
26033
26499
|
if (!fs33.existsSync(file)) {
|
|
26034
|
-
console.error(
|
|
26500
|
+
console.error(chalk192.red(`Error: File does not exist: ${file}`));
|
|
26035
26501
|
process.exit(1);
|
|
26036
26502
|
}
|
|
26037
26503
|
const content = fs33.readFileSync(file, "utf8");
|
|
@@ -26047,7 +26513,7 @@ function ignore2(file) {
|
|
|
26047
26513
|
fs33.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
26048
26514
|
}
|
|
26049
26515
|
console.log(
|
|
26050
|
-
|
|
26516
|
+
chalk192.green(
|
|
26051
26517
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
26052
26518
|
)
|
|
26053
26519
|
);
|
|
@@ -26056,12 +26522,12 @@ function ignore2(file) {
|
|
|
26056
26522
|
// src/commands/refactor/rename/index.ts
|
|
26057
26523
|
import fs36 from "fs";
|
|
26058
26524
|
import path55 from "path";
|
|
26059
|
-
import
|
|
26525
|
+
import chalk195 from "chalk";
|
|
26060
26526
|
|
|
26061
26527
|
// src/commands/refactor/rename/applyRename.ts
|
|
26062
26528
|
import fs35 from "fs";
|
|
26063
26529
|
import path52 from "path";
|
|
26064
|
-
import
|
|
26530
|
+
import chalk193 from "chalk";
|
|
26065
26531
|
|
|
26066
26532
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
26067
26533
|
import path51 from "path";
|
|
@@ -26166,13 +26632,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
26166
26632
|
const updatedContents = applyRewrites(rewrites);
|
|
26167
26633
|
for (const [file, content] of updatedContents) {
|
|
26168
26634
|
fs35.writeFileSync(file, content, "utf8");
|
|
26169
|
-
console.log(
|
|
26635
|
+
console.log(chalk193.cyan(` Updated imports in ${path52.relative(cwd, file)}`));
|
|
26170
26636
|
}
|
|
26171
26637
|
const destDir = path52.dirname(destPath);
|
|
26172
26638
|
if (!fs35.existsSync(destDir)) fs35.mkdirSync(destDir, { recursive: true });
|
|
26173
26639
|
fs35.renameSync(sourcePath, destPath);
|
|
26174
26640
|
console.log(
|
|
26175
|
-
|
|
26641
|
+
chalk193.white(
|
|
26176
26642
|
` Moved ${path52.relative(cwd, sourcePath)} \u2192 ${path52.relative(cwd, destPath)}`
|
|
26177
26643
|
)
|
|
26178
26644
|
);
|
|
@@ -26259,16 +26725,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
26259
26725
|
|
|
26260
26726
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
26261
26727
|
import path54 from "path";
|
|
26262
|
-
import
|
|
26728
|
+
import chalk194 from "chalk";
|
|
26263
26729
|
function printRenamePreview(rewrites, cwd) {
|
|
26264
26730
|
for (const rewrite of rewrites) {
|
|
26265
26731
|
console.log(
|
|
26266
|
-
|
|
26732
|
+
chalk194.dim(
|
|
26267
26733
|
` ${path54.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
26268
26734
|
)
|
|
26269
26735
|
);
|
|
26270
26736
|
}
|
|
26271
|
-
console.log(
|
|
26737
|
+
console.log(chalk194.dim("Dry run. Use --apply to execute."));
|
|
26272
26738
|
}
|
|
26273
26739
|
|
|
26274
26740
|
// src/commands/refactor/rename/index.ts
|
|
@@ -26279,20 +26745,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26279
26745
|
const relSource = path55.relative(cwd, sourcePath);
|
|
26280
26746
|
const relDest = path55.relative(cwd, destPath);
|
|
26281
26747
|
if (!fs36.existsSync(sourcePath)) {
|
|
26282
|
-
console.log(
|
|
26748
|
+
console.log(chalk195.red(`File not found: ${source}`));
|
|
26283
26749
|
process.exit(1);
|
|
26284
26750
|
}
|
|
26285
26751
|
if (destPath !== sourcePath && fs36.existsSync(destPath)) {
|
|
26286
|
-
console.log(
|
|
26752
|
+
console.log(chalk195.red(`Destination already exists: ${destination}`));
|
|
26287
26753
|
process.exit(1);
|
|
26288
26754
|
}
|
|
26289
|
-
console.log(
|
|
26290
|
-
console.log(
|
|
26291
|
-
console.log(
|
|
26755
|
+
console.log(chalk195.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
26756
|
+
console.log(chalk195.dim("Loading project..."));
|
|
26757
|
+
console.log(chalk195.dim("Scanning imports across the project..."));
|
|
26292
26758
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
26293
26759
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
26294
26760
|
console.log(
|
|
26295
|
-
|
|
26761
|
+
chalk195.dim(
|
|
26296
26762
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
26297
26763
|
)
|
|
26298
26764
|
);
|
|
@@ -26301,11 +26767,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26301
26767
|
return;
|
|
26302
26768
|
}
|
|
26303
26769
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
26304
|
-
console.log(
|
|
26770
|
+
console.log(chalk195.green("Done"));
|
|
26305
26771
|
}
|
|
26306
26772
|
|
|
26307
26773
|
// src/commands/refactor/renameSymbol/index.ts
|
|
26308
|
-
import
|
|
26774
|
+
import chalk196 from "chalk";
|
|
26309
26775
|
|
|
26310
26776
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
26311
26777
|
import { SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
@@ -26351,33 +26817,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
26351
26817
|
const { project, sourceFile } = loadProjectFile(file);
|
|
26352
26818
|
const symbol = findSymbol(sourceFile, oldName);
|
|
26353
26819
|
if (!symbol) {
|
|
26354
|
-
console.log(
|
|
26820
|
+
console.log(chalk196.red(`Symbol "${oldName}" not found in ${file}`));
|
|
26355
26821
|
process.exit(1);
|
|
26356
26822
|
}
|
|
26357
26823
|
const grouped = groupReferences(symbol, cwd);
|
|
26358
26824
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
26359
26825
|
console.log(
|
|
26360
|
-
|
|
26826
|
+
chalk196.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
26361
26827
|
`)
|
|
26362
26828
|
);
|
|
26363
26829
|
for (const [refFile, lines2] of grouped) {
|
|
26364
26830
|
console.log(
|
|
26365
|
-
` ${
|
|
26831
|
+
` ${chalk196.dim(refFile)}: lines ${chalk196.cyan(lines2.join(", "))}`
|
|
26366
26832
|
);
|
|
26367
26833
|
}
|
|
26368
26834
|
if (options2.apply) {
|
|
26369
26835
|
symbol.rename(newName);
|
|
26370
26836
|
await project.save();
|
|
26371
|
-
console.log(
|
|
26837
|
+
console.log(chalk196.green(`
|
|
26372
26838
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
26373
26839
|
} else {
|
|
26374
|
-
console.log(
|
|
26840
|
+
console.log(chalk196.dim("\nDry run. Use --apply to execute."));
|
|
26375
26841
|
}
|
|
26376
26842
|
}
|
|
26377
26843
|
|
|
26378
26844
|
// src/commands/refactor/restructure/index.ts
|
|
26379
26845
|
import path63 from "path";
|
|
26380
|
-
import
|
|
26846
|
+
import chalk199 from "chalk";
|
|
26381
26847
|
|
|
26382
26848
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
26383
26849
|
import path57 from "path";
|
|
@@ -26456,50 +26922,50 @@ function clusterFiles(graph) {
|
|
|
26456
26922
|
|
|
26457
26923
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
26458
26924
|
import path59 from "path";
|
|
26459
|
-
import
|
|
26925
|
+
import chalk197 from "chalk";
|
|
26460
26926
|
function relPath(filePath) {
|
|
26461
26927
|
return path59.relative(process.cwd(), filePath);
|
|
26462
26928
|
}
|
|
26463
26929
|
function displayMoves(plan2) {
|
|
26464
26930
|
if (plan2.moves.length === 0) return;
|
|
26465
|
-
console.log(
|
|
26931
|
+
console.log(chalk197.bold("\nFile moves:"));
|
|
26466
26932
|
for (const move2 of plan2.moves) {
|
|
26467
26933
|
console.log(
|
|
26468
|
-
` ${
|
|
26934
|
+
` ${chalk197.red(relPath(move2.from))} \u2192 ${chalk197.green(relPath(move2.to))}`
|
|
26469
26935
|
);
|
|
26470
|
-
console.log(
|
|
26936
|
+
console.log(chalk197.dim(` ${move2.reason}`));
|
|
26471
26937
|
}
|
|
26472
26938
|
}
|
|
26473
26939
|
function displayRewrites(rewrites) {
|
|
26474
26940
|
if (rewrites.length === 0) return;
|
|
26475
26941
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
26476
|
-
console.log(
|
|
26942
|
+
console.log(chalk197.bold(`
|
|
26477
26943
|
Import rewrites (${affectedFiles.size} files):`));
|
|
26478
26944
|
for (const file of affectedFiles) {
|
|
26479
|
-
console.log(` ${
|
|
26945
|
+
console.log(` ${chalk197.cyan(relPath(file))}:`);
|
|
26480
26946
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
26481
26947
|
(r) => r.file === file
|
|
26482
26948
|
)) {
|
|
26483
26949
|
console.log(
|
|
26484
|
-
` ${
|
|
26950
|
+
` ${chalk197.red(`"${oldSpecifier}"`)} \u2192 ${chalk197.green(`"${newSpecifier}"`)}`
|
|
26485
26951
|
);
|
|
26486
26952
|
}
|
|
26487
26953
|
}
|
|
26488
26954
|
}
|
|
26489
26955
|
function displayPlan2(plan2) {
|
|
26490
26956
|
if (plan2.warnings.length > 0) {
|
|
26491
|
-
console.log(
|
|
26492
|
-
for (const w of plan2.warnings) console.log(
|
|
26957
|
+
console.log(chalk197.yellow("\nWarnings:"));
|
|
26958
|
+
for (const w of plan2.warnings) console.log(chalk197.yellow(` ${w}`));
|
|
26493
26959
|
}
|
|
26494
26960
|
if (plan2.newDirectories.length > 0) {
|
|
26495
|
-
console.log(
|
|
26961
|
+
console.log(chalk197.bold("\nNew directories:"));
|
|
26496
26962
|
for (const dir of plan2.newDirectories)
|
|
26497
|
-
console.log(
|
|
26963
|
+
console.log(chalk197.green(` ${dir}/`));
|
|
26498
26964
|
}
|
|
26499
26965
|
displayMoves(plan2);
|
|
26500
26966
|
displayRewrites(plan2.rewrites);
|
|
26501
26967
|
console.log(
|
|
26502
|
-
|
|
26968
|
+
chalk197.dim(
|
|
26503
26969
|
`
|
|
26504
26970
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
26505
26971
|
)
|
|
@@ -26509,18 +26975,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
26509
26975
|
// src/commands/refactor/restructure/executePlan.ts
|
|
26510
26976
|
import fs37 from "fs";
|
|
26511
26977
|
import path60 from "path";
|
|
26512
|
-
import
|
|
26978
|
+
import chalk198 from "chalk";
|
|
26513
26979
|
function executePlan(plan2) {
|
|
26514
26980
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
26515
26981
|
for (const [file, content] of updatedContents) {
|
|
26516
26982
|
fs37.writeFileSync(file, content, "utf8");
|
|
26517
26983
|
console.log(
|
|
26518
|
-
|
|
26984
|
+
chalk198.cyan(` Rewrote imports in ${path60.relative(process.cwd(), file)}`)
|
|
26519
26985
|
);
|
|
26520
26986
|
}
|
|
26521
26987
|
for (const dir of plan2.newDirectories) {
|
|
26522
26988
|
fs37.mkdirSync(dir, { recursive: true });
|
|
26523
|
-
console.log(
|
|
26989
|
+
console.log(chalk198.green(` Created ${path60.relative(process.cwd(), dir)}/`));
|
|
26524
26990
|
}
|
|
26525
26991
|
for (const move2 of plan2.moves) {
|
|
26526
26992
|
const targetDir = path60.dirname(move2.to);
|
|
@@ -26529,7 +26995,7 @@ function executePlan(plan2) {
|
|
|
26529
26995
|
}
|
|
26530
26996
|
fs37.renameSync(move2.from, move2.to);
|
|
26531
26997
|
console.log(
|
|
26532
|
-
|
|
26998
|
+
chalk198.white(
|
|
26533
26999
|
` Moved ${path60.relative(process.cwd(), move2.from)} \u2192 ${path60.relative(process.cwd(), move2.to)}`
|
|
26534
27000
|
)
|
|
26535
27001
|
);
|
|
@@ -26544,7 +27010,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
26544
27010
|
if (entries.length === 0) {
|
|
26545
27011
|
fs37.rmdirSync(dir);
|
|
26546
27012
|
console.log(
|
|
26547
|
-
|
|
27013
|
+
chalk198.dim(
|
|
26548
27014
|
` Removed empty directory ${path60.relative(process.cwd(), dir)}`
|
|
26549
27015
|
)
|
|
26550
27016
|
);
|
|
@@ -26677,22 +27143,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
26677
27143
|
const targetPattern = pattern2 ?? "src";
|
|
26678
27144
|
const files = findSourceFiles2(targetPattern);
|
|
26679
27145
|
if (files.length === 0) {
|
|
26680
|
-
console.log(
|
|
27146
|
+
console.log(chalk199.yellow("No files found matching pattern"));
|
|
26681
27147
|
return;
|
|
26682
27148
|
}
|
|
26683
27149
|
const tsConfigPath = findTsConfig(path63.resolve(files[0]));
|
|
26684
27150
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
26685
27151
|
if (plan2.moves.length === 0) {
|
|
26686
|
-
console.log(
|
|
27152
|
+
console.log(chalk199.green("No restructuring needed"));
|
|
26687
27153
|
return;
|
|
26688
27154
|
}
|
|
26689
27155
|
displayPlan2(plan2);
|
|
26690
27156
|
if (options2.apply) {
|
|
26691
|
-
console.log(
|
|
27157
|
+
console.log(chalk199.bold("\nApplying changes..."));
|
|
26692
27158
|
executePlan(plan2);
|
|
26693
|
-
console.log(
|
|
27159
|
+
console.log(chalk199.green("\nRestructuring complete"));
|
|
26694
27160
|
} else {
|
|
26695
|
-
console.log(
|
|
27161
|
+
console.log(chalk199.dim("\nDry run. Use --apply to execute."));
|
|
26696
27162
|
}
|
|
26697
27163
|
}
|
|
26698
27164
|
|
|
@@ -27015,7 +27481,7 @@ function gatherContext() {
|
|
|
27015
27481
|
}
|
|
27016
27482
|
|
|
27017
27483
|
// src/commands/review/postReviewToPr.ts
|
|
27018
|
-
import { readFileSync as
|
|
27484
|
+
import { readFileSync as readFileSync42 } from "fs";
|
|
27019
27485
|
|
|
27020
27486
|
// src/commands/review/carriedUnanchoredFindings.ts
|
|
27021
27487
|
function carriedUnanchoredFindings(unanchored) {
|
|
@@ -27350,18 +27816,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
27350
27816
|
}
|
|
27351
27817
|
|
|
27352
27818
|
// src/commands/review/warnOutOfDiff.ts
|
|
27353
|
-
import
|
|
27819
|
+
import chalk200 from "chalk";
|
|
27354
27820
|
function warnOutOfDiff(outOfDiff) {
|
|
27355
27821
|
if (outOfDiff.length === 0) return;
|
|
27356
27822
|
console.warn(
|
|
27357
|
-
|
|
27823
|
+
chalk200.yellow(
|
|
27358
27824
|
`Moved ${outOfDiff.length} finding(s) whose lines fall outside the PR diff into the review body (GitHub cannot anchor a comment on these):`
|
|
27359
27825
|
)
|
|
27360
27826
|
);
|
|
27361
27827
|
for (const finding of outOfDiff) {
|
|
27362
27828
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
27363
27829
|
console.warn(
|
|
27364
|
-
` ${
|
|
27830
|
+
` ${chalk200.yellow("\xB7")} ${finding.title} ${chalk200.dim(
|
|
27365
27831
|
`(${finding.file}:${range})`
|
|
27366
27832
|
)}`
|
|
27367
27833
|
);
|
|
@@ -27385,18 +27851,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
27385
27851
|
}
|
|
27386
27852
|
|
|
27387
27853
|
// src/commands/review/warnUnlocated.ts
|
|
27388
|
-
import
|
|
27854
|
+
import chalk201 from "chalk";
|
|
27389
27855
|
function warnUnlocated(unlocated) {
|
|
27390
27856
|
if (unlocated.length === 0) return;
|
|
27391
27857
|
console.warn(
|
|
27392
|
-
|
|
27858
|
+
chalk201.yellow(
|
|
27393
27859
|
`Moved ${unlocated.length} finding(s) without a parseable file:line into the review body:`
|
|
27394
27860
|
)
|
|
27395
27861
|
);
|
|
27396
27862
|
for (const finding of unlocated) {
|
|
27397
|
-
const where = finding.location ||
|
|
27863
|
+
const where = finding.location || chalk201.dim("missing");
|
|
27398
27864
|
console.warn(
|
|
27399
|
-
` ${
|
|
27865
|
+
` ${chalk201.yellow("\xB7")} ${finding.title} ${chalk201.dim(`(${where})`)}`
|
|
27400
27866
|
);
|
|
27401
27867
|
}
|
|
27402
27868
|
}
|
|
@@ -27463,7 +27929,7 @@ async function confirmPost(prNumber, work, options2) {
|
|
|
27463
27929
|
return promptConfirm(`Post ${work} to PR #${prNumber}?`, false);
|
|
27464
27930
|
}
|
|
27465
27931
|
async function postFindingsToPr(prInfo, synthesisPath, options2) {
|
|
27466
|
-
const markdown =
|
|
27932
|
+
const markdown = readFileSync42(synthesisPath, "utf8");
|
|
27467
27933
|
const { inDiff, unanchored } = selectPostableFindings(markdown, prInfo);
|
|
27468
27934
|
const carried = carriedUnanchoredFindings(unanchored);
|
|
27469
27935
|
if (inDiff.length === 0 && carried.length === 0) return NOTHING_POSTED;
|
|
@@ -27599,10 +28065,10 @@ async function handlePostSynthesis(synthesisPath, prInfo, options2) {
|
|
|
27599
28065
|
}
|
|
27600
28066
|
|
|
27601
28067
|
// src/commands/review/prepareReviewDir.ts
|
|
27602
|
-
import { existsSync as
|
|
28068
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync20, unlinkSync as unlinkSync17, writeFileSync as writeFileSync37 } from "fs";
|
|
27603
28069
|
function clearReviewFiles(paths) {
|
|
27604
28070
|
for (const path80 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
27605
|
-
if (
|
|
28071
|
+
if (existsSync55(path80)) unlinkSync17(path80);
|
|
27606
28072
|
}
|
|
27607
28073
|
}
|
|
27608
28074
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -27728,9 +28194,9 @@ var MultiSpinner = class {
|
|
|
27728
28194
|
};
|
|
27729
28195
|
|
|
27730
28196
|
// src/commands/review/ensureCodexAvailable.ts
|
|
27731
|
-
import { spawnSync as
|
|
28197
|
+
import { spawnSync as spawnSync7 } from "child_process";
|
|
27732
28198
|
function runNpmInstall() {
|
|
27733
|
-
const result =
|
|
28199
|
+
const result = spawnSync7("npm", ["install", "-g", "@openai/codex"], {
|
|
27734
28200
|
stdio: "inherit",
|
|
27735
28201
|
shell: true
|
|
27736
28202
|
});
|
|
@@ -27829,7 +28295,7 @@ function printReviewerFailures(results) {
|
|
|
27829
28295
|
}
|
|
27830
28296
|
|
|
27831
28297
|
// src/commands/review/runAndSynthesise.ts
|
|
27832
|
-
import { existsSync as
|
|
28298
|
+
import { existsSync as existsSync57, unlinkSync as unlinkSync19 } from "fs";
|
|
27833
28299
|
|
|
27834
28300
|
// src/commands/review/buildReviewerStdin.ts
|
|
27835
28301
|
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in the request file whose absolute path is given below.
|
|
@@ -28258,7 +28724,7 @@ function resolveClaude(args) {
|
|
|
28258
28724
|
}
|
|
28259
28725
|
|
|
28260
28726
|
// src/commands/review/runCodexReviewer.ts
|
|
28261
|
-
import { existsSync as
|
|
28727
|
+
import { existsSync as existsSync56, unlinkSync as unlinkSync18 } from "fs";
|
|
28262
28728
|
|
|
28263
28729
|
// src/commands/review/parseCodexEvent.ts
|
|
28264
28730
|
function isItemStarted(value) {
|
|
@@ -28310,7 +28776,7 @@ async function runCodexReviewer(spec) {
|
|
|
28310
28776
|
reportReviewerToolUse(spec.name, event, spinner);
|
|
28311
28777
|
}
|
|
28312
28778
|
});
|
|
28313
|
-
if (result.exitCode !== 0 &&
|
|
28779
|
+
if (result.exitCode !== 0 && existsSync56(spec.outputPath)) {
|
|
28314
28780
|
unlinkSync18(spec.outputPath);
|
|
28315
28781
|
}
|
|
28316
28782
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
@@ -28352,7 +28818,7 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
|
|
|
28352
28818
|
}
|
|
28353
28819
|
|
|
28354
28820
|
// src/commands/review/synthesise.ts
|
|
28355
|
-
import { readFileSync as
|
|
28821
|
+
import { readFileSync as readFileSync43 } from "fs";
|
|
28356
28822
|
|
|
28357
28823
|
// src/commands/review/buildSynthesisStdin.ts
|
|
28358
28824
|
var SYNTHESIS_PROMPT = `You are consolidating two independent code reviews of the same change. The original review request is in request.md. The two reviews are in claude.md and codex.md in the current working directory.
|
|
@@ -28417,7 +28883,7 @@ Files:
|
|
|
28417
28883
|
|
|
28418
28884
|
// src/commands/review/synthesise.ts
|
|
28419
28885
|
function printSummary2(synthesisPath) {
|
|
28420
|
-
const markdown =
|
|
28886
|
+
const markdown = readFileSync43(synthesisPath, "utf8");
|
|
28421
28887
|
console.log("");
|
|
28422
28888
|
console.log(buildReviewSummary(markdown));
|
|
28423
28889
|
console.log("");
|
|
@@ -28465,7 +28931,7 @@ async function runAndSynthesise(args) {
|
|
|
28465
28931
|
console.error("Both reviewers failed; skipping synthesis.");
|
|
28466
28932
|
return { ok: false, failures };
|
|
28467
28933
|
}
|
|
28468
|
-
if (anyFresh &&
|
|
28934
|
+
if (anyFresh && existsSync57(paths.synthesisPath)) {
|
|
28469
28935
|
unlinkSync19(paths.synthesisPath);
|
|
28470
28936
|
}
|
|
28471
28937
|
const synthesisResult = await synthesise(paths, { multi });
|
|
@@ -28651,7 +29117,7 @@ function registerReview(program2) {
|
|
|
28651
29117
|
}
|
|
28652
29118
|
|
|
28653
29119
|
// src/commands/seq/seqAuth.ts
|
|
28654
|
-
import
|
|
29120
|
+
import chalk203 from "chalk";
|
|
28655
29121
|
|
|
28656
29122
|
// src/commands/seq/loadConnections.ts
|
|
28657
29123
|
function loadConnections2() {
|
|
@@ -28680,10 +29146,10 @@ function setDefaultConnection(name) {
|
|
|
28680
29146
|
}
|
|
28681
29147
|
|
|
28682
29148
|
// src/shared/assertUniqueName.ts
|
|
28683
|
-
import
|
|
29149
|
+
import chalk202 from "chalk";
|
|
28684
29150
|
function assertUniqueName(existingNames, name) {
|
|
28685
29151
|
if (existingNames.includes(name)) {
|
|
28686
|
-
console.error(
|
|
29152
|
+
console.error(chalk202.red(`Connection "${name}" already exists.`));
|
|
28687
29153
|
process.exit(1);
|
|
28688
29154
|
}
|
|
28689
29155
|
}
|
|
@@ -28701,16 +29167,16 @@ async function promptConnection2(existingNames) {
|
|
|
28701
29167
|
var seqAuth = createConnectionAuth({
|
|
28702
29168
|
load: loadConnections2,
|
|
28703
29169
|
save: saveConnections2,
|
|
28704
|
-
format: (c) => `${
|
|
29170
|
+
format: (c) => `${chalk203.bold(c.name)} ${c.url}`,
|
|
28705
29171
|
promptNew: promptConnection2,
|
|
28706
29172
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
28707
29173
|
});
|
|
28708
29174
|
|
|
28709
29175
|
// src/commands/seq/seqQuery.ts
|
|
28710
|
-
import
|
|
29176
|
+
import chalk207 from "chalk";
|
|
28711
29177
|
|
|
28712
29178
|
// src/commands/seq/fetchSeq.ts
|
|
28713
|
-
import
|
|
29179
|
+
import chalk204 from "chalk";
|
|
28714
29180
|
async function fetchSeq(conn, path80, params) {
|
|
28715
29181
|
const url = `${conn.url}${path80}?${params}`;
|
|
28716
29182
|
const response = await fetch(url, {
|
|
@@ -28721,7 +29187,7 @@ async function fetchSeq(conn, path80, params) {
|
|
|
28721
29187
|
});
|
|
28722
29188
|
if (!response.ok) {
|
|
28723
29189
|
const body = await response.text();
|
|
28724
|
-
console.error(
|
|
29190
|
+
console.error(chalk204.red(`Seq returned ${response.status}: ${body}`));
|
|
28725
29191
|
process.exit(1);
|
|
28726
29192
|
}
|
|
28727
29193
|
return response;
|
|
@@ -28780,23 +29246,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
28780
29246
|
}
|
|
28781
29247
|
|
|
28782
29248
|
// src/commands/seq/formatEvent.ts
|
|
28783
|
-
import
|
|
29249
|
+
import chalk205 from "chalk";
|
|
28784
29250
|
function levelColor(level) {
|
|
28785
29251
|
switch (level) {
|
|
28786
29252
|
case "Fatal":
|
|
28787
|
-
return
|
|
29253
|
+
return chalk205.bgRed.white;
|
|
28788
29254
|
case "Error":
|
|
28789
|
-
return
|
|
29255
|
+
return chalk205.red;
|
|
28790
29256
|
case "Warning":
|
|
28791
|
-
return
|
|
29257
|
+
return chalk205.yellow;
|
|
28792
29258
|
case "Information":
|
|
28793
|
-
return
|
|
29259
|
+
return chalk205.cyan;
|
|
28794
29260
|
case "Debug":
|
|
28795
|
-
return
|
|
29261
|
+
return chalk205.gray;
|
|
28796
29262
|
case "Verbose":
|
|
28797
|
-
return
|
|
29263
|
+
return chalk205.dim;
|
|
28798
29264
|
default:
|
|
28799
|
-
return
|
|
29265
|
+
return chalk205.white;
|
|
28800
29266
|
}
|
|
28801
29267
|
}
|
|
28802
29268
|
function levelAbbrev(level) {
|
|
@@ -28837,12 +29303,12 @@ function formatTimestamp(iso) {
|
|
|
28837
29303
|
function formatEvent(event) {
|
|
28838
29304
|
const color = levelColor(event.Level);
|
|
28839
29305
|
const abbrev = levelAbbrev(event.Level);
|
|
28840
|
-
const ts8 =
|
|
29306
|
+
const ts8 = chalk205.dim(formatTimestamp(event.Timestamp));
|
|
28841
29307
|
const msg = renderMessage(event);
|
|
28842
29308
|
const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
28843
29309
|
if (event.Exception) {
|
|
28844
29310
|
for (const line of event.Exception.split("\n")) {
|
|
28845
|
-
lines2.push(
|
|
29311
|
+
lines2.push(chalk205.red(` ${line}`));
|
|
28846
29312
|
}
|
|
28847
29313
|
}
|
|
28848
29314
|
return lines2.join("\n");
|
|
@@ -28875,11 +29341,11 @@ function rejectTimestampFilter(filter) {
|
|
|
28875
29341
|
}
|
|
28876
29342
|
|
|
28877
29343
|
// src/shared/resolveNamedConnection.ts
|
|
28878
|
-
import
|
|
29344
|
+
import chalk206 from "chalk";
|
|
28879
29345
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
28880
29346
|
if (connections.length === 0) {
|
|
28881
29347
|
console.error(
|
|
28882
|
-
|
|
29348
|
+
chalk206.red(
|
|
28883
29349
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
28884
29350
|
)
|
|
28885
29351
|
);
|
|
@@ -28888,7 +29354,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
28888
29354
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
28889
29355
|
const connection = connections.find((c) => c.name === target);
|
|
28890
29356
|
if (!connection) {
|
|
28891
|
-
console.error(
|
|
29357
|
+
console.error(chalk206.red(`${kind} connection "${target}" not found.`));
|
|
28892
29358
|
process.exit(1);
|
|
28893
29359
|
}
|
|
28894
29360
|
return connection;
|
|
@@ -28917,7 +29383,7 @@ async function seqQuery(filter, options2) {
|
|
|
28917
29383
|
new URLSearchParams({ filter, count: String(count8) })
|
|
28918
29384
|
);
|
|
28919
29385
|
if (events.length === 0) {
|
|
28920
|
-
console.log(
|
|
29386
|
+
console.log(chalk207.yellow("No events found."));
|
|
28921
29387
|
return;
|
|
28922
29388
|
}
|
|
28923
29389
|
if (options2.json) {
|
|
@@ -28928,11 +29394,11 @@ async function seqQuery(filter, options2) {
|
|
|
28928
29394
|
for (const event of chronological) {
|
|
28929
29395
|
console.log(formatEvent(event));
|
|
28930
29396
|
}
|
|
28931
|
-
console.log(
|
|
29397
|
+
console.log(chalk207.dim(`
|
|
28932
29398
|
${events.length} events`));
|
|
28933
29399
|
if (events.length >= count8) {
|
|
28934
29400
|
console.log(
|
|
28935
|
-
|
|
29401
|
+
chalk207.yellow(
|
|
28936
29402
|
`Results limited to ${count8}. Use --count to retrieve more.`
|
|
28937
29403
|
)
|
|
28938
29404
|
);
|
|
@@ -28940,10 +29406,10 @@ ${events.length} events`));
|
|
|
28940
29406
|
}
|
|
28941
29407
|
|
|
28942
29408
|
// src/shared/setNamedDefaultConnection.ts
|
|
28943
|
-
import
|
|
29409
|
+
import chalk208 from "chalk";
|
|
28944
29410
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
28945
29411
|
if (!connections.find((c) => c.name === name)) {
|
|
28946
|
-
console.error(
|
|
29412
|
+
console.error(chalk208.red(`Connection "${name}" not found.`));
|
|
28947
29413
|
process.exit(1);
|
|
28948
29414
|
}
|
|
28949
29415
|
setDefault(name);
|
|
@@ -28992,7 +29458,7 @@ function registerSignal(program2) {
|
|
|
28992
29458
|
}
|
|
28993
29459
|
|
|
28994
29460
|
// src/commands/sql/sqlAuth.ts
|
|
28995
|
-
import
|
|
29461
|
+
import chalk210 from "chalk";
|
|
28996
29462
|
|
|
28997
29463
|
// src/commands/sql/loadConnections.ts
|
|
28998
29464
|
function loadConnections3() {
|
|
@@ -29021,7 +29487,7 @@ function setDefaultConnection2(name) {
|
|
|
29021
29487
|
}
|
|
29022
29488
|
|
|
29023
29489
|
// src/commands/sql/promptConnection.ts
|
|
29024
|
-
import
|
|
29490
|
+
import chalk209 from "chalk";
|
|
29025
29491
|
async function promptConnection3(existingNames) {
|
|
29026
29492
|
const name = await promptInput("name", "Connection name:", "default");
|
|
29027
29493
|
assertUniqueName(existingNames, name);
|
|
@@ -29029,7 +29495,7 @@ async function promptConnection3(existingNames) {
|
|
|
29029
29495
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
29030
29496
|
const port = Number.parseInt(portStr, 10);
|
|
29031
29497
|
if (!Number.isFinite(port)) {
|
|
29032
|
-
console.error(
|
|
29498
|
+
console.error(chalk209.red(`Invalid port "${portStr}".`));
|
|
29033
29499
|
process.exit(1);
|
|
29034
29500
|
}
|
|
29035
29501
|
const user = await promptInput("user", "User:");
|
|
@@ -29042,13 +29508,13 @@ async function promptConnection3(existingNames) {
|
|
|
29042
29508
|
var sqlAuth = createConnectionAuth({
|
|
29043
29509
|
load: loadConnections3,
|
|
29044
29510
|
save: saveConnections3,
|
|
29045
|
-
format: (c) => `${
|
|
29511
|
+
format: (c) => `${chalk210.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
29046
29512
|
promptNew: promptConnection3,
|
|
29047
29513
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
29048
29514
|
});
|
|
29049
29515
|
|
|
29050
29516
|
// src/commands/sql/printTable.ts
|
|
29051
|
-
import
|
|
29517
|
+
import chalk211 from "chalk";
|
|
29052
29518
|
function formatCell(value) {
|
|
29053
29519
|
if (value === null || value === void 0) return "";
|
|
29054
29520
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -29057,7 +29523,7 @@ function formatCell(value) {
|
|
|
29057
29523
|
}
|
|
29058
29524
|
function printTable(rows) {
|
|
29059
29525
|
if (rows.length === 0) {
|
|
29060
|
-
console.log(
|
|
29526
|
+
console.log(chalk211.yellow("(no rows)"));
|
|
29061
29527
|
return;
|
|
29062
29528
|
}
|
|
29063
29529
|
const columns = Object.keys(rows[0]);
|
|
@@ -29065,13 +29531,13 @@ function printTable(rows) {
|
|
|
29065
29531
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
29066
29532
|
);
|
|
29067
29533
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
29068
|
-
console.log(
|
|
29069
|
-
console.log(
|
|
29534
|
+
console.log(chalk211.dim(header));
|
|
29535
|
+
console.log(chalk211.dim("-".repeat(header.length)));
|
|
29070
29536
|
for (const row of rows) {
|
|
29071
29537
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
29072
29538
|
console.log(line);
|
|
29073
29539
|
}
|
|
29074
|
-
console.log(
|
|
29540
|
+
console.log(chalk211.dim(`
|
|
29075
29541
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
29076
29542
|
}
|
|
29077
29543
|
|
|
@@ -29131,7 +29597,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
29131
29597
|
}
|
|
29132
29598
|
|
|
29133
29599
|
// src/commands/sql/sqlMutate.ts
|
|
29134
|
-
import
|
|
29600
|
+
import chalk212 from "chalk";
|
|
29135
29601
|
|
|
29136
29602
|
// src/commands/sql/isMutation.ts
|
|
29137
29603
|
var MUTATION_KEYWORDS = [
|
|
@@ -29165,7 +29631,7 @@ function isMutation(sql25) {
|
|
|
29165
29631
|
async function sqlMutate(query, connectionName) {
|
|
29166
29632
|
if (!isMutation(query)) {
|
|
29167
29633
|
console.error(
|
|
29168
|
-
|
|
29634
|
+
chalk212.red(
|
|
29169
29635
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
29170
29636
|
)
|
|
29171
29637
|
);
|
|
@@ -29175,18 +29641,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
29175
29641
|
const pool = await sqlConnect(conn);
|
|
29176
29642
|
try {
|
|
29177
29643
|
const result = await pool.request().query(query);
|
|
29178
|
-
console.log(
|
|
29644
|
+
console.log(chalk212.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
29179
29645
|
} finally {
|
|
29180
29646
|
await pool.close();
|
|
29181
29647
|
}
|
|
29182
29648
|
}
|
|
29183
29649
|
|
|
29184
29650
|
// src/commands/sql/sqlQuery.ts
|
|
29185
|
-
import
|
|
29651
|
+
import chalk213 from "chalk";
|
|
29186
29652
|
async function sqlQuery(query, connectionName) {
|
|
29187
29653
|
if (isMutation(query)) {
|
|
29188
29654
|
console.error(
|
|
29189
|
-
|
|
29655
|
+
chalk213.red(
|
|
29190
29656
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
29191
29657
|
)
|
|
29192
29658
|
);
|
|
@@ -29201,7 +29667,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
29201
29667
|
printTable(rows);
|
|
29202
29668
|
} else {
|
|
29203
29669
|
console.log(
|
|
29204
|
-
|
|
29670
|
+
chalk213.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
29205
29671
|
);
|
|
29206
29672
|
}
|
|
29207
29673
|
} finally {
|
|
@@ -29346,7 +29812,7 @@ function reportPrune(label2, result, force) {
|
|
|
29346
29812
|
// src/commands/sync/syncClaudeMd.ts
|
|
29347
29813
|
import * as fs41 from "fs";
|
|
29348
29814
|
import * as path66 from "path";
|
|
29349
|
-
import
|
|
29815
|
+
import chalk214 from "chalk";
|
|
29350
29816
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
29351
29817
|
const source = path66.join(claudeDir, "CLAUDE.md");
|
|
29352
29818
|
const target = path66.join(targetBase, "CLAUDE.md");
|
|
@@ -29355,14 +29821,14 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
29355
29821
|
const targetContent = fs41.readFileSync(target, "utf8");
|
|
29356
29822
|
if (sourceContent !== targetContent) {
|
|
29357
29823
|
console.log(
|
|
29358
|
-
|
|
29824
|
+
chalk214.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
29359
29825
|
);
|
|
29360
29826
|
console.log();
|
|
29361
29827
|
printDiff(targetContent, sourceContent);
|
|
29362
29828
|
if (!options2?.yes) {
|
|
29363
29829
|
printAutoConfirmHint();
|
|
29364
29830
|
const confirm = await promptConfirm(
|
|
29365
|
-
|
|
29831
|
+
chalk214.red("Overwrite existing CLAUDE.md?"),
|
|
29366
29832
|
false
|
|
29367
29833
|
);
|
|
29368
29834
|
if (!confirm) {
|
|
@@ -29595,7 +30061,7 @@ function syncPi(claudeDir, options2) {
|
|
|
29595
30061
|
// src/commands/sync/syncSettings.ts
|
|
29596
30062
|
import * as fs47 from "fs";
|
|
29597
30063
|
import * as path73 from "path";
|
|
29598
|
-
import
|
|
30064
|
+
import chalk215 from "chalk";
|
|
29599
30065
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
29600
30066
|
const source = path73.join(claudeDir, "settings.json");
|
|
29601
30067
|
const target = path73.join(targetBase, "settings.json");
|
|
@@ -29614,7 +30080,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
29614
30080
|
if (mergedContent !== normalizedTarget) {
|
|
29615
30081
|
if (!options2?.yes) {
|
|
29616
30082
|
console.log(
|
|
29617
|
-
|
|
30083
|
+
chalk215.yellow(
|
|
29618
30084
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
29619
30085
|
)
|
|
29620
30086
|
);
|
|
@@ -29622,7 +30088,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
29622
30088
|
printDiff(targetContent, mergedContent);
|
|
29623
30089
|
printAutoConfirmHint();
|
|
29624
30090
|
const confirm = await promptConfirm(
|
|
29625
|
-
|
|
30091
|
+
chalk215.red("Overwrite existing settings.json?"),
|
|
29626
30092
|
false
|
|
29627
30093
|
);
|
|
29628
30094
|
if (!confirm) {
|
|
@@ -29764,11 +30230,11 @@ async function configure() {
|
|
|
29764
30230
|
}
|
|
29765
30231
|
|
|
29766
30232
|
// src/commands/transcript/list.ts
|
|
29767
|
-
import { existsSync as
|
|
30233
|
+
import { existsSync as existsSync62, readdirSync as readdirSync19, statSync as statSync10 } from "fs";
|
|
29768
30234
|
import { join as join77 } from "path";
|
|
29769
30235
|
function list4() {
|
|
29770
30236
|
const { vttDir } = getTranscriptConfig();
|
|
29771
|
-
if (!
|
|
30237
|
+
if (!existsSync62(vttDir)) return;
|
|
29772
30238
|
for (const entry of readdirSync19(vttDir)) {
|
|
29773
30239
|
if (!entry.endsWith(".vtt")) continue;
|
|
29774
30240
|
if (statSync10(join77(vttDir, entry)).isDirectory()) continue;
|
|
@@ -29778,9 +30244,9 @@ function list4() {
|
|
|
29778
30244
|
|
|
29779
30245
|
// src/commands/transcript/move.ts
|
|
29780
30246
|
import {
|
|
29781
|
-
existsSync as
|
|
30247
|
+
existsSync as existsSync63,
|
|
29782
30248
|
mkdirSync as mkdirSync26,
|
|
29783
|
-
readFileSync as
|
|
30249
|
+
readFileSync as readFileSync48,
|
|
29784
30250
|
renameSync as renameSync2,
|
|
29785
30251
|
writeFileSync as writeFileSync42
|
|
29786
30252
|
} from "fs";
|
|
@@ -29992,7 +30458,7 @@ function formatChatLog(messages) {
|
|
|
29992
30458
|
// src/commands/transcript/move.ts
|
|
29993
30459
|
var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
29994
30460
|
function convertVttToMarkdown(inputPath) {
|
|
29995
|
-
const cues = parseVtt(
|
|
30461
|
+
const cues = parseVtt(readFileSync48(inputPath, "utf8"));
|
|
29996
30462
|
const messages = cuesToChatMessages(deduplicateCues(cues));
|
|
29997
30463
|
return formatChatLog(messages);
|
|
29998
30464
|
}
|
|
@@ -30010,7 +30476,7 @@ function move(file, options2) {
|
|
|
30010
30476
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
30011
30477
|
const filename = basename21(file);
|
|
30012
30478
|
const sourcePath = join78(vttDir, filename);
|
|
30013
|
-
if (!
|
|
30479
|
+
if (!existsSync63(sourcePath)) {
|
|
30014
30480
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
30015
30481
|
process.exit(1);
|
|
30016
30482
|
}
|
|
@@ -30102,7 +30568,7 @@ function registerVerify(program2) {
|
|
|
30102
30568
|
}
|
|
30103
30569
|
|
|
30104
30570
|
// src/commands/voice/devices.ts
|
|
30105
|
-
import { spawnSync as
|
|
30571
|
+
import { spawnSync as spawnSync8 } from "child_process";
|
|
30106
30572
|
import { join as join80 } from "path";
|
|
30107
30573
|
|
|
30108
30574
|
// src/commands/voice/shared.ts
|
|
@@ -30135,18 +30601,18 @@ function getLockFile() {
|
|
|
30135
30601
|
// src/commands/voice/devices.ts
|
|
30136
30602
|
function devices() {
|
|
30137
30603
|
const script = join80(getPythonDir(), "list_devices.py");
|
|
30138
|
-
|
|
30604
|
+
spawnSync8(getVenvPython(), [script], { stdio: "inherit" });
|
|
30139
30605
|
}
|
|
30140
30606
|
|
|
30141
30607
|
// src/commands/voice/logs.ts
|
|
30142
|
-
import { existsSync as
|
|
30608
|
+
import { existsSync as existsSync64, readFileSync as readFileSync49 } from "fs";
|
|
30143
30609
|
function logs(options2) {
|
|
30144
|
-
if (!
|
|
30610
|
+
if (!existsSync64(voicePaths.log)) {
|
|
30145
30611
|
console.log("No voice log file found");
|
|
30146
30612
|
return;
|
|
30147
30613
|
}
|
|
30148
30614
|
const count8 = Number.parseInt(options2.lines ?? "150", 10);
|
|
30149
|
-
const content =
|
|
30615
|
+
const content = readFileSync49(voicePaths.log, "utf8").trim();
|
|
30150
30616
|
if (!content) {
|
|
30151
30617
|
console.log("Voice log is empty");
|
|
30152
30618
|
return;
|
|
@@ -30167,13 +30633,13 @@ function logs(options2) {
|
|
|
30167
30633
|
}
|
|
30168
30634
|
|
|
30169
30635
|
// src/commands/voice/setup.ts
|
|
30170
|
-
import { spawnSync as
|
|
30636
|
+
import { spawnSync as spawnSync9 } from "child_process";
|
|
30171
30637
|
import { mkdirSync as mkdirSync28 } from "fs";
|
|
30172
30638
|
import { join as join82 } from "path";
|
|
30173
30639
|
|
|
30174
30640
|
// src/commands/voice/checkLockFile.ts
|
|
30175
30641
|
import { execSync as execSync58 } from "child_process";
|
|
30176
|
-
import { existsSync as
|
|
30642
|
+
import { existsSync as existsSync65, mkdirSync as mkdirSync27, readFileSync as readFileSync50, writeFileSync as writeFileSync43 } from "fs";
|
|
30177
30643
|
import { join as join81 } from "path";
|
|
30178
30644
|
function isProcessAlive2(pid) {
|
|
30179
30645
|
try {
|
|
@@ -30185,9 +30651,9 @@ function isProcessAlive2(pid) {
|
|
|
30185
30651
|
}
|
|
30186
30652
|
function checkLockFile() {
|
|
30187
30653
|
const lockFile = getLockFile();
|
|
30188
|
-
if (!
|
|
30654
|
+
if (!existsSync65(lockFile)) return;
|
|
30189
30655
|
try {
|
|
30190
|
-
const lock2 = JSON.parse(
|
|
30656
|
+
const lock2 = JSON.parse(readFileSync50(lockFile, "utf8"));
|
|
30191
30657
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
30192
30658
|
console.error(
|
|
30193
30659
|
`Voice daemon already running (PID ${lock2.pid}, env: ${lock2.env}). Stop it first with: assist voice stop`
|
|
@@ -30198,7 +30664,7 @@ function checkLockFile() {
|
|
|
30198
30664
|
}
|
|
30199
30665
|
}
|
|
30200
30666
|
function bootstrapVenv() {
|
|
30201
|
-
if (
|
|
30667
|
+
if (existsSync65(getVenvPython())) return;
|
|
30202
30668
|
console.log("Setting up Python environment...");
|
|
30203
30669
|
const pythonDir = getPythonDir();
|
|
30204
30670
|
execSync58(
|
|
@@ -30228,7 +30694,7 @@ function setup() {
|
|
|
30228
30694
|
bootstrapVenv();
|
|
30229
30695
|
console.log("\nDownloading models...\n");
|
|
30230
30696
|
const script = join82(getPythonDir(), "setup_models.py");
|
|
30231
|
-
const result =
|
|
30697
|
+
const result = spawnSync9(getVenvPython(), [script], {
|
|
30232
30698
|
stdio: "inherit",
|
|
30233
30699
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
30234
30700
|
});
|
|
@@ -30289,7 +30755,7 @@ function start2(options2) {
|
|
|
30289
30755
|
}
|
|
30290
30756
|
|
|
30291
30757
|
// src/commands/voice/status.ts
|
|
30292
|
-
import { existsSync as
|
|
30758
|
+
import { existsSync as existsSync66, readFileSync as readFileSync51 } from "fs";
|
|
30293
30759
|
function isProcessAlive3(pid) {
|
|
30294
30760
|
try {
|
|
30295
30761
|
process.kill(pid, 0);
|
|
@@ -30299,16 +30765,16 @@ function isProcessAlive3(pid) {
|
|
|
30299
30765
|
}
|
|
30300
30766
|
}
|
|
30301
30767
|
function readRecentLogs(count8) {
|
|
30302
|
-
if (!
|
|
30303
|
-
const lines2 =
|
|
30768
|
+
if (!existsSync66(voicePaths.log)) return [];
|
|
30769
|
+
const lines2 = readFileSync51(voicePaths.log, "utf8").trim().split("\n");
|
|
30304
30770
|
return lines2.slice(-count8);
|
|
30305
30771
|
}
|
|
30306
30772
|
function status2() {
|
|
30307
|
-
if (!
|
|
30773
|
+
if (!existsSync66(voicePaths.pid)) {
|
|
30308
30774
|
console.log("Voice daemon: not running (no PID file)");
|
|
30309
30775
|
return;
|
|
30310
30776
|
}
|
|
30311
|
-
const pid = Number.parseInt(
|
|
30777
|
+
const pid = Number.parseInt(readFileSync51(voicePaths.pid, "utf8").trim(), 10);
|
|
30312
30778
|
const alive = isProcessAlive3(pid);
|
|
30313
30779
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
30314
30780
|
const recent = readRecentLogs(5);
|
|
@@ -30327,13 +30793,13 @@ function status2() {
|
|
|
30327
30793
|
}
|
|
30328
30794
|
|
|
30329
30795
|
// src/commands/voice/stop.ts
|
|
30330
|
-
import { existsSync as
|
|
30796
|
+
import { existsSync as existsSync67, readFileSync as readFileSync52, unlinkSync as unlinkSync20 } from "fs";
|
|
30331
30797
|
function stop2() {
|
|
30332
|
-
if (!
|
|
30798
|
+
if (!existsSync67(voicePaths.pid)) {
|
|
30333
30799
|
console.log("Voice daemon is not running (no PID file)");
|
|
30334
30800
|
return;
|
|
30335
30801
|
}
|
|
30336
|
-
const pid = Number.parseInt(
|
|
30802
|
+
const pid = Number.parseInt(readFileSync52(voicePaths.pid, "utf8").trim(), 10);
|
|
30337
30803
|
try {
|
|
30338
30804
|
process.kill(pid, "SIGTERM");
|
|
30339
30805
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -30346,7 +30812,7 @@ function stop2() {
|
|
|
30346
30812
|
}
|
|
30347
30813
|
try {
|
|
30348
30814
|
const lockFile = getLockFile();
|
|
30349
|
-
if (
|
|
30815
|
+
if (existsSync67(lockFile)) unlinkSync20(lockFile);
|
|
30350
30816
|
} catch {
|
|
30351
30817
|
}
|
|
30352
30818
|
console.log("Voice daemon stopped");
|
|
@@ -30364,9 +30830,6 @@ function registerVoice(program2) {
|
|
|
30364
30830
|
configHelp(voiceCommand, voiceConfigHelp);
|
|
30365
30831
|
}
|
|
30366
30832
|
|
|
30367
|
-
// src/commands/watch/readBuiltVersion.ts
|
|
30368
|
-
import { join as join84 } from "path";
|
|
30369
|
-
|
|
30370
30833
|
// src/commands/watch/resolveUpstream.ts
|
|
30371
30834
|
import { execFileSync as execFileSync15 } from "child_process";
|
|
30372
30835
|
function runGit3(args, cwd) {
|
|
@@ -30407,7 +30870,13 @@ function resolveUpstream(cwd) {
|
|
|
30407
30870
|
}
|
|
30408
30871
|
}
|
|
30409
30872
|
|
|
30873
|
+
// src/commands/watch/changedPaths.ts
|
|
30874
|
+
function changedPaths(from, cwd) {
|
|
30875
|
+
return runGit3(["diff", "--name-only", `${from}..HEAD`], cwd).split("\n").filter((line) => line.length > 0);
|
|
30876
|
+
}
|
|
30877
|
+
|
|
30410
30878
|
// src/commands/watch/readBuiltVersion.ts
|
|
30879
|
+
import { join as join84 } from "path";
|
|
30411
30880
|
function readBuiltVersion(cwd) {
|
|
30412
30881
|
try {
|
|
30413
30882
|
const root = runGit3(["rev-parse", "--show-toplevel"], cwd);
|
|
@@ -30436,7 +30905,8 @@ function renderWatchReport({
|
|
|
30436
30905
|
version: version2,
|
|
30437
30906
|
commits: commits2,
|
|
30438
30907
|
newShas,
|
|
30439
|
-
restarts
|
|
30908
|
+
restarts,
|
|
30909
|
+
syncs
|
|
30440
30910
|
}) {
|
|
30441
30911
|
const isNew = new Set(newShas);
|
|
30442
30912
|
const lines2 = [`**Version** ${version2}`, ""];
|
|
@@ -30455,6 +30925,10 @@ function renderWatchReport({
|
|
|
30455
30925
|
lines2.push(
|
|
30456
30926
|
...restarts.length === 0 ? ["- none needed"] : restarts.map((restart) => `- ${restart}`)
|
|
30457
30927
|
);
|
|
30928
|
+
lines2.push("", "**Sync**", "");
|
|
30929
|
+
lines2.push(
|
|
30930
|
+
...syncs.length === 0 ? ["- not needed"] : syncs.map((sync2) => `- ${sync2}`)
|
|
30931
|
+
);
|
|
30458
30932
|
return lines2.join("\n");
|
|
30459
30933
|
}
|
|
30460
30934
|
|
|
@@ -30475,17 +30949,51 @@ function restartAdvice(paths) {
|
|
|
30475
30949
|
return rules.filter((rule) => paths.some(rule.matches)).map((rule) => rule.advice);
|
|
30476
30950
|
}
|
|
30477
30951
|
|
|
30952
|
+
// src/commands/watch/syncAdvice.ts
|
|
30953
|
+
var rules2 = [
|
|
30954
|
+
{
|
|
30955
|
+
matches: (path80) => path80.startsWith("claude/commands/"),
|
|
30956
|
+
reason: "claude/commands changed"
|
|
30957
|
+
},
|
|
30958
|
+
{
|
|
30959
|
+
matches: (path80) => path80.startsWith("claude/skills/"),
|
|
30960
|
+
reason: "claude/skills changed"
|
|
30961
|
+
},
|
|
30962
|
+
{
|
|
30963
|
+
matches: (path80) => path80 === "claude/settings.json",
|
|
30964
|
+
reason: "claude/settings.json changed"
|
|
30965
|
+
},
|
|
30966
|
+
{
|
|
30967
|
+
matches: (path80) => path80 === "claude/CLAUDE.md",
|
|
30968
|
+
reason: "claude/CLAUDE.md changed"
|
|
30969
|
+
},
|
|
30970
|
+
{
|
|
30971
|
+
matches: (path80) => path80 === "claude/design-system-prompt.md",
|
|
30972
|
+
reason: "claude/design-system-prompt.md changed"
|
|
30973
|
+
},
|
|
30974
|
+
{
|
|
30975
|
+
matches: (path80) => path80.startsWith("codex/"),
|
|
30976
|
+
reason: "codex sources changed"
|
|
30977
|
+
},
|
|
30978
|
+
{
|
|
30979
|
+
matches: (path80) => path80.startsWith("pi/"),
|
|
30980
|
+
reason: "pi sources changed"
|
|
30981
|
+
}
|
|
30982
|
+
];
|
|
30983
|
+
function syncAdvice(paths) {
|
|
30984
|
+
return rules2.filter((rule) => paths.some(rule.matches)).map((rule) => rule.reason);
|
|
30985
|
+
}
|
|
30986
|
+
|
|
30478
30987
|
// src/commands/watch/buildWatchReport.ts
|
|
30479
30988
|
var lines = (output) => output.split("\n").filter((line) => line.length > 0);
|
|
30480
30989
|
function buildWatchReport(from, cwd) {
|
|
30481
|
-
const
|
|
30990
|
+
const changed = from ? changedPaths(from, cwd) : [];
|
|
30482
30991
|
return renderWatchReport({
|
|
30483
30992
|
version: readBuiltVersion(cwd),
|
|
30484
30993
|
commits: readRecentCommits(10, cwd),
|
|
30485
|
-
newShas:
|
|
30486
|
-
restarts: restartAdvice(
|
|
30487
|
-
|
|
30488
|
-
)
|
|
30994
|
+
newShas: from ? lines(runGit3(["rev-list", `${from}..HEAD`], cwd)) : [],
|
|
30995
|
+
restarts: restartAdvice(changed),
|
|
30996
|
+
syncs: syncAdvice(changed)
|
|
30489
30997
|
});
|
|
30490
30998
|
}
|
|
30491
30999
|
|
|
@@ -30709,7 +31217,7 @@ function resolveParams(params, cliArgs) {
|
|
|
30709
31217
|
}
|
|
30710
31218
|
|
|
30711
31219
|
// src/commands/run/resolveRunCwd.ts
|
|
30712
|
-
import { existsSync as
|
|
31220
|
+
import { existsSync as existsSync68 } from "fs";
|
|
30713
31221
|
import { resolve as resolve18 } from "path";
|
|
30714
31222
|
var MissingRunCwdError = class extends Error {
|
|
30715
31223
|
constructor(runName, cwd) {
|
|
@@ -30722,17 +31230,17 @@ var MissingRunCwdError = class extends Error {
|
|
|
30722
31230
|
function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
|
|
30723
31231
|
if (!config.cwd) return void 0;
|
|
30724
31232
|
const cwd = resolve18(baseDir, config.cwd);
|
|
30725
|
-
if (!
|
|
31233
|
+
if (!existsSync68(cwd)) throw new MissingRunCwdError(config.name, cwd);
|
|
30726
31234
|
return cwd;
|
|
30727
31235
|
}
|
|
30728
31236
|
|
|
30729
31237
|
// src/commands/run/runCommandToCompletion.ts
|
|
30730
31238
|
import { spawn as spawn9 } from "child_process";
|
|
30731
|
-
import { existsSync as
|
|
31239
|
+
import { existsSync as existsSync70 } from "fs";
|
|
30732
31240
|
|
|
30733
31241
|
// src/commands/run/resolveCommand.ts
|
|
30734
31242
|
import { execFileSync as execFileSync16 } from "child_process";
|
|
30735
|
-
import { existsSync as
|
|
31243
|
+
import { existsSync as existsSync69 } from "fs";
|
|
30736
31244
|
import { dirname as dirname35, join as join85, resolve as resolve19 } from "path";
|
|
30737
31245
|
function resolveCommand2(command) {
|
|
30738
31246
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
@@ -30740,7 +31248,7 @@ function resolveCommand2(command) {
|
|
|
30740
31248
|
const gitPath = execFileSync16("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
30741
31249
|
const gitRoot = resolve19(dirname35(gitPath), "..");
|
|
30742
31250
|
const gitBash = join85(gitRoot, "bin", "bash.exe");
|
|
30743
|
-
if (
|
|
31251
|
+
if (existsSync69(gitBash)) return gitBash;
|
|
30744
31252
|
} catch {
|
|
30745
31253
|
return command;
|
|
30746
31254
|
}
|
|
@@ -30750,7 +31258,7 @@ function resolveCommand2(command) {
|
|
|
30750
31258
|
// src/commands/run/runCommandToCompletion.ts
|
|
30751
31259
|
function runCommandToCompletion(command, args, env, cwd, quiet) {
|
|
30752
31260
|
return new Promise((resolveResult) => {
|
|
30753
|
-
if (cwd && !
|
|
31261
|
+
if (cwd && !existsSync70(cwd)) {
|
|
30754
31262
|
resolveResult({
|
|
30755
31263
|
kind: "failed",
|
|
30756
31264
|
message: `Failed to execute command: cwd ${cwd} does not exist`
|
|
@@ -30796,6 +31304,15 @@ function runPreCommands(pre, cwd) {
|
|
|
30796
31304
|
}
|
|
30797
31305
|
}
|
|
30798
31306
|
|
|
31307
|
+
// src/commands/watch/toBuildOutcome.ts
|
|
31308
|
+
function toBuildOutcome(result) {
|
|
31309
|
+
if (result.kind === "failed")
|
|
31310
|
+
return { kind: "failed", exitCode: 1, output: result.message };
|
|
31311
|
+
if (result.exitCode !== 0)
|
|
31312
|
+
return { kind: "failed", exitCode: result.exitCode, output: result.output };
|
|
31313
|
+
return { kind: "built" };
|
|
31314
|
+
}
|
|
31315
|
+
|
|
30799
31316
|
// src/commands/watch/runWatchBuild.ts
|
|
30800
31317
|
async function runWatchBuild(entry) {
|
|
30801
31318
|
const config = findRunConfig(entry);
|
|
@@ -30807,18 +31324,15 @@ async function runWatchBuild(entry) {
|
|
|
30807
31324
|
return { kind: "failed", exitCode: 1, output: error.message };
|
|
30808
31325
|
}
|
|
30809
31326
|
if (config.pre) runPreCommands(config.pre, cwd);
|
|
30810
|
-
|
|
30811
|
-
|
|
30812
|
-
|
|
30813
|
-
|
|
30814
|
-
|
|
30815
|
-
|
|
31327
|
+
return toBuildOutcome(
|
|
31328
|
+
await runCommandToCompletion(
|
|
31329
|
+
config.command,
|
|
31330
|
+
[...config.args ?? [], ...resolveParams(config.params, [])],
|
|
31331
|
+
config.env,
|
|
31332
|
+
cwd,
|
|
31333
|
+
config.quiet
|
|
31334
|
+
)
|
|
30816
31335
|
);
|
|
30817
|
-
if (result.kind === "failed")
|
|
30818
|
-
return { kind: "failed", exitCode: 1, output: result.message };
|
|
30819
|
-
if (result.exitCode !== 0)
|
|
30820
|
-
return { kind: "failed", exitCode: result.exitCode, output: result.output };
|
|
30821
|
-
return { kind: "built" };
|
|
30822
31336
|
}
|
|
30823
31337
|
|
|
30824
31338
|
// src/commands/watch/reportBuildOrExit.ts
|
|
@@ -30833,6 +31347,25 @@ async function reportBuildOrExit(entry) {
|
|
|
30833
31347
|
process.exit(4);
|
|
30834
31348
|
}
|
|
30835
31349
|
|
|
31350
|
+
// src/commands/watch/runPostBuildSync.ts
|
|
31351
|
+
async function runPostBuildSync() {
|
|
31352
|
+
return toBuildOutcome(
|
|
31353
|
+
await runCommandToCompletion("assist", ["sync", "--yes"])
|
|
31354
|
+
);
|
|
31355
|
+
}
|
|
31356
|
+
|
|
31357
|
+
// src/commands/watch/reportSyncOrExit.ts
|
|
31358
|
+
async function reportSyncOrExit() {
|
|
31359
|
+
const outcome = await runPostBuildSync();
|
|
31360
|
+
if (outcome.kind === "built") {
|
|
31361
|
+
console.log("synced ~/.claude");
|
|
31362
|
+
return;
|
|
31363
|
+
}
|
|
31364
|
+
if (outcome.output.length > 0) process.stdout.write(outcome.output);
|
|
31365
|
+
console.error(`sync failed with exit code ${outcome.exitCode}`);
|
|
31366
|
+
process.exit(4);
|
|
31367
|
+
}
|
|
31368
|
+
|
|
30836
31369
|
// src/commands/watch/fetchQuietly.ts
|
|
30837
31370
|
import { execFileSync as execFileSync17 } from "child_process";
|
|
30838
31371
|
var MIN_FETCH_TIMEOUT_MS = 6e4;
|
|
@@ -30944,6 +31477,8 @@ ${buildWatchReport(outcome.from)}`);
|
|
|
30944
31477
|
await reportBuildOrExit(
|
|
30945
31478
|
typeof options2.build === "string" ? options2.build : DEFAULT_BUILD_ENTRY
|
|
30946
31479
|
);
|
|
31480
|
+
if (syncAdvice(changedPaths(outcome.from)).length > 0)
|
|
31481
|
+
await reportSyncOrExit();
|
|
30947
31482
|
}
|
|
30948
31483
|
process.exit(0);
|
|
30949
31484
|
}
|
|
@@ -30952,7 +31487,7 @@ ${buildWatchReport(outcome.from)}`);
|
|
|
30952
31487
|
function registerWatch(program2) {
|
|
30953
31488
|
const watchCommand = program2.command("watch").description("Wait on upstream movement for the current branch");
|
|
30954
31489
|
watchCommand.command("wait").description(
|
|
30955
|
-
"Block until the current branch's upstream gains commits, then exit 0 (2 on timeout, 3 when --pull hits genuine divergence, 4 when --build fails, 1 when waiting is impossible, 130 on interrupt)"
|
|
31490
|
+
"Block until the current branch's upstream gains commits, then exit 0 (2 on timeout, 3 when --pull hits genuine divergence, 4 when --build or the post-build sync fails, 1 when waiting is impossible, 130 on interrupt)"
|
|
30956
31491
|
).option(
|
|
30957
31492
|
"--interval <duration>",
|
|
30958
31493
|
"How often to fetch after the fetch at startup (e.g. 30s, 2m)",
|
|
@@ -30966,21 +31501,21 @@ function registerWatch(program2) {
|
|
|
30966
31501
|
"On movement, fast-forward with git pull --ff-only, recovering a dirty tree or a merely-behind branch; exit 3 with git's reason on genuine divergence"
|
|
30967
31502
|
).option(
|
|
30968
31503
|
"--build [entry]",
|
|
30969
|
-
"After a successful pull, run this run entry (default auto-build); exit 4 with
|
|
31504
|
+
"After a successful pull, run this run entry (default auto-build), then run assist sync --yes when the pulled commits touched the files sync installs; exit 4 with the output of whichever fails"
|
|
30970
31505
|
).action(
|
|
30971
31506
|
(options2) => watchWait(options2)
|
|
30972
31507
|
);
|
|
30973
31508
|
watchCommand.command("report").description(
|
|
30974
|
-
"Print the built version, the last 10 commits as a markdown table,
|
|
31509
|
+
"Print the built version, the last 10 commits as a markdown table, the restarts the new commits make necessary, and whether ~/.claude needs a sync"
|
|
30975
31510
|
).option(
|
|
30976
31511
|
"--from <sha>",
|
|
30977
|
-
"Mark commits reachable from HEAD but not <sha> as new, and derive restart advice from the files they changed"
|
|
31512
|
+
"Mark commits reachable from HEAD but not <sha> as new, and derive the restart and sync advice from the files they changed"
|
|
30978
31513
|
).action((options2) => watchReport(options2));
|
|
30979
31514
|
}
|
|
30980
31515
|
|
|
30981
31516
|
// src/commands/roam/auth.ts
|
|
30982
31517
|
import { randomBytes } from "crypto";
|
|
30983
|
-
import
|
|
31518
|
+
import chalk216 from "chalk";
|
|
30984
31519
|
|
|
30985
31520
|
// src/commands/roam/waitForCallback.ts
|
|
30986
31521
|
import { createServer as createServer3 } from "http";
|
|
@@ -31111,13 +31646,13 @@ async function auth() {
|
|
|
31111
31646
|
saveGlobalConfig(config);
|
|
31112
31647
|
const state = randomBytes(16).toString("hex");
|
|
31113
31648
|
console.log(
|
|
31114
|
-
|
|
31649
|
+
chalk216.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
31115
31650
|
);
|
|
31116
|
-
console.log(
|
|
31117
|
-
console.log(
|
|
31118
|
-
console.log(
|
|
31651
|
+
console.log(chalk216.white("http://localhost:14523/callback\n"));
|
|
31652
|
+
console.log(chalk216.blue("Opening browser for authorization..."));
|
|
31653
|
+
console.log(chalk216.dim("Waiting for authorization callback..."));
|
|
31119
31654
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
31120
|
-
console.log(
|
|
31655
|
+
console.log(chalk216.dim("Exchanging code for tokens..."));
|
|
31121
31656
|
const tokens = await exchangeToken({
|
|
31122
31657
|
code,
|
|
31123
31658
|
clientId,
|
|
@@ -31133,13 +31668,13 @@ async function auth() {
|
|
|
31133
31668
|
};
|
|
31134
31669
|
saveGlobalConfig(config);
|
|
31135
31670
|
console.log(
|
|
31136
|
-
|
|
31671
|
+
chalk216.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
31137
31672
|
);
|
|
31138
31673
|
}
|
|
31139
31674
|
|
|
31140
31675
|
// src/commands/roam/postRoamActivity.ts
|
|
31141
31676
|
import { execFileSync as execFileSync18 } from "child_process";
|
|
31142
|
-
import { readdirSync as readdirSync20, readFileSync as
|
|
31677
|
+
import { readdirSync as readdirSync20, readFileSync as readFileSync53, statSync as statSync11 } from "fs";
|
|
31143
31678
|
import { join as join86 } from "path";
|
|
31144
31679
|
function findPortFile(roamDir) {
|
|
31145
31680
|
let entries;
|
|
@@ -31165,7 +31700,7 @@ function postRoamActivity(app, event) {
|
|
|
31165
31700
|
if (!portFile) return;
|
|
31166
31701
|
let port;
|
|
31167
31702
|
try {
|
|
31168
|
-
port =
|
|
31703
|
+
port = readFileSync53(portFile, "utf8").trim();
|
|
31169
31704
|
} catch {
|
|
31170
31705
|
return;
|
|
31171
31706
|
}
|
|
@@ -31419,7 +31954,7 @@ function link2() {
|
|
|
31419
31954
|
}
|
|
31420
31955
|
|
|
31421
31956
|
// src/commands/run/remove.ts
|
|
31422
|
-
import { existsSync as
|
|
31957
|
+
import { existsSync as existsSync71, unlinkSync as unlinkSync21 } from "fs";
|
|
31423
31958
|
import { join as join88 } from "path";
|
|
31424
31959
|
function findRemoveIndex() {
|
|
31425
31960
|
const idx = process.argv.indexOf("remove");
|
|
@@ -31436,7 +31971,7 @@ function parseRemoveName() {
|
|
|
31436
31971
|
}
|
|
31437
31972
|
function deleteCommandFile(name) {
|
|
31438
31973
|
const filePath = join88(".claude", "commands", `${name}.md`);
|
|
31439
|
-
if (
|
|
31974
|
+
if (existsSync71(filePath)) {
|
|
31440
31975
|
unlinkSync21(filePath);
|
|
31441
31976
|
console.log(`Deleted command file: ${filePath}`);
|
|
31442
31977
|
}
|
|
@@ -31481,10 +32016,10 @@ function registerRun(program2) {
|
|
|
31481
32016
|
|
|
31482
32017
|
// src/commands/screenshot/index.ts
|
|
31483
32018
|
import { execSync as execSync60 } from "child_process";
|
|
31484
|
-
import { existsSync as
|
|
32019
|
+
import { existsSync as existsSync72, mkdirSync as mkdirSync31, unlinkSync as unlinkSync22, writeFileSync as writeFileSync46 } from "fs";
|
|
31485
32020
|
import { tmpdir as tmpdir8 } from "os";
|
|
31486
32021
|
import { join as join89, resolve as resolve20 } from "path";
|
|
31487
|
-
import
|
|
32022
|
+
import chalk217 from "chalk";
|
|
31488
32023
|
|
|
31489
32024
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
31490
32025
|
var captureWindowPs1 = `
|
|
@@ -31613,7 +32148,7 @@ Write-Output $OutputPath
|
|
|
31613
32148
|
|
|
31614
32149
|
// src/commands/screenshot/index.ts
|
|
31615
32150
|
function buildOutputPath(outputDir, processName) {
|
|
31616
|
-
if (!
|
|
32151
|
+
if (!existsSync72(outputDir)) {
|
|
31617
32152
|
mkdirSync31(outputDir, { recursive: true });
|
|
31618
32153
|
}
|
|
31619
32154
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -31635,13 +32170,13 @@ function screenshot(processName) {
|
|
|
31635
32170
|
const config = loadConfig();
|
|
31636
32171
|
const outputDir = resolve20(config.screenshot.outputDir);
|
|
31637
32172
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
31638
|
-
console.log(
|
|
32173
|
+
console.log(chalk217.gray(`Capturing window for process "${processName}" ...`));
|
|
31639
32174
|
try {
|
|
31640
32175
|
runPowerShellScript(processName, outputPath);
|
|
31641
|
-
console.log(
|
|
32176
|
+
console.log(chalk217.green(`Screenshot saved: ${outputPath}`));
|
|
31642
32177
|
} catch (error) {
|
|
31643
32178
|
const msg = error instanceof Error ? error.message : String(error);
|
|
31644
|
-
console.error(
|
|
32179
|
+
console.error(chalk217.red(`Failed to capture screenshot: ${msg}`));
|
|
31645
32180
|
process.exit(1);
|
|
31646
32181
|
}
|
|
31647
32182
|
}
|
|
@@ -31697,11 +32232,11 @@ function applyLine(result, pending, line) {
|
|
|
31697
32232
|
}
|
|
31698
32233
|
|
|
31699
32234
|
// src/commands/sessions/daemon/readDaemonPidFile.ts
|
|
31700
|
-
import { readFileSync as
|
|
32235
|
+
import { readFileSync as readFileSync54 } from "fs";
|
|
31701
32236
|
function readDaemonPidFile() {
|
|
31702
32237
|
try {
|
|
31703
32238
|
const pid = Number.parseInt(
|
|
31704
|
-
|
|
32239
|
+
readFileSync54(daemonPaths.pid, "utf8").trim(),
|
|
31705
32240
|
10
|
|
31706
32241
|
);
|
|
31707
32242
|
return Number.isInteger(pid) ? pid : void 0;
|
|
@@ -31958,12 +32493,12 @@ function toSessionRunInfo({
|
|
|
31958
32493
|
}
|
|
31959
32494
|
|
|
31960
32495
|
// src/commands/sessions/daemon/worktree/joinRefusal.ts
|
|
31961
|
-
import { existsSync as
|
|
32496
|
+
import { existsSync as existsSync73 } from "fs";
|
|
31962
32497
|
function joinRefusal(session) {
|
|
31963
32498
|
if (session.commandType === "run") return "a server run has no agent stream";
|
|
31964
32499
|
if (session.closing === true) return "the session is closing";
|
|
31965
32500
|
if (!session.cwd) return "the session has no working directory";
|
|
31966
|
-
if (!
|
|
32501
|
+
if (!existsSync73(session.cwd))
|
|
31967
32502
|
return "the session's workspace no longer exists";
|
|
31968
32503
|
return void 0;
|
|
31969
32504
|
}
|
|
@@ -32127,11 +32662,11 @@ function sessionBase(id, status3) {
|
|
|
32127
32662
|
}
|
|
32128
32663
|
|
|
32129
32664
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
32130
|
-
import { existsSync as
|
|
32665
|
+
import { existsSync as existsSync75 } from "fs";
|
|
32131
32666
|
import * as pty from "node-pty";
|
|
32132
32667
|
|
|
32133
32668
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
32134
|
-
import { chmodSync, existsSync as
|
|
32669
|
+
import { chmodSync, existsSync as existsSync74, statSync as statSync12 } from "fs";
|
|
32135
32670
|
import { createRequire as createRequire3 } from "module";
|
|
32136
32671
|
import path75 from "path";
|
|
32137
32672
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -32146,7 +32681,7 @@ function ensureSpawnHelperExecutable() {
|
|
|
32146
32681
|
`${process.platform}-${process.arch}`,
|
|
32147
32682
|
"spawn-helper"
|
|
32148
32683
|
);
|
|
32149
|
-
if (!
|
|
32684
|
+
if (!existsSync74(helper)) return;
|
|
32150
32685
|
const mode = statSync12(helper).mode;
|
|
32151
32686
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
32152
32687
|
}
|
|
@@ -32182,7 +32717,7 @@ function spawnPty(args, cwd, sessionId, extraEnv) {
|
|
|
32182
32717
|
});
|
|
32183
32718
|
}
|
|
32184
32719
|
function refuseMissingCwd(cwd, sessionId) {
|
|
32185
|
-
if (!cwd ||
|
|
32720
|
+
if (!cwd || existsSync75(cwd)) return;
|
|
32186
32721
|
daemonLog(
|
|
32187
32722
|
`${sessionId ? `session ${sessionId}` : "pty"} not spawned: working directory ${cwd} no longer exists`
|
|
32188
32723
|
);
|
|
@@ -32364,11 +32899,11 @@ function setStatus2(session, newStatus) {
|
|
|
32364
32899
|
}
|
|
32365
32900
|
|
|
32366
32901
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
32367
|
-
import { existsSync as
|
|
32902
|
+
import { existsSync as existsSync77 } from "fs";
|
|
32368
32903
|
import { basename as basename22 } from "path";
|
|
32369
32904
|
|
|
32370
32905
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
32371
|
-
import { existsSync as
|
|
32906
|
+
import { existsSync as existsSync76 } from "fs";
|
|
32372
32907
|
import { join as join92 } from "path";
|
|
32373
32908
|
|
|
32374
32909
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
@@ -32438,7 +32973,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
32438
32973
|
);
|
|
32439
32974
|
}
|
|
32440
32975
|
function strandedReason(worktreePath, cause) {
|
|
32441
|
-
if (!
|
|
32976
|
+
if (!existsSync76(join92(worktreePath, ".git")))
|
|
32442
32977
|
return "its .git link is already gone";
|
|
32443
32978
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
32444
32979
|
return "git no longer recognises it as a working tree";
|
|
@@ -32490,7 +33025,7 @@ function reason3(error) {
|
|
|
32490
33025
|
|
|
32491
33026
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
32492
33027
|
async function reapWorktree(worktreePath, force = false) {
|
|
32493
|
-
if (!
|
|
33028
|
+
if (!existsSync77(worktreePath)) {
|
|
32494
33029
|
forgetWorktree(worktreePath);
|
|
32495
33030
|
daemonLog(
|
|
32496
33031
|
`worktree ${worktreePath} already gone; its record was forgotten`
|
|
@@ -32515,7 +33050,7 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
32515
33050
|
}
|
|
32516
33051
|
function owningClone(worktreePath) {
|
|
32517
33052
|
const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
|
|
32518
|
-
if (recorded &&
|
|
33053
|
+
if (recorded && existsSync77(recorded)) return recorded;
|
|
32519
33054
|
const detected = mainWorktree(worktreePath);
|
|
32520
33055
|
if (detected) return detected;
|
|
32521
33056
|
daemonLog(
|
|
@@ -32646,12 +33181,12 @@ function closeGateApplies(sessions, session) {
|
|
|
32646
33181
|
}
|
|
32647
33182
|
|
|
32648
33183
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
32649
|
-
import { existsSync as
|
|
33184
|
+
import { existsSync as existsSync78, watch } from "fs";
|
|
32650
33185
|
var DEBOUNCE_MS = 500;
|
|
32651
33186
|
var POLL_MS = 3e4;
|
|
32652
33187
|
function watchGitState(cwd, onChange) {
|
|
32653
33188
|
const common = gitCommonDir(cwd);
|
|
32654
|
-
if (!common || !
|
|
33189
|
+
if (!common || !existsSync78(common)) return void 0;
|
|
32655
33190
|
const watchers = [
|
|
32656
33191
|
watchGitDir(common, onChange),
|
|
32657
33192
|
pollGitState(cwd, onChange)
|
|
@@ -32826,9 +33361,9 @@ function flushPhaseActiveMs(session) {
|
|
|
32826
33361
|
if (await persistPhaseActiveMs(phase.itemId, phase.phaseIdx, delta))
|
|
32827
33362
|
session.activeMsFlushedForStretch = { since, ms: flushed + delta };
|
|
32828
33363
|
};
|
|
32829
|
-
const
|
|
32830
|
-
session.activeMsFlushChain =
|
|
32831
|
-
return
|
|
33364
|
+
const chain2 = (session.activeMsFlushChain ?? Promise.resolve()).then(run4);
|
|
33365
|
+
session.activeMsFlushChain = chain2;
|
|
33366
|
+
return chain2;
|
|
32832
33367
|
}
|
|
32833
33368
|
|
|
32834
33369
|
// src/commands/sessions/daemon/stripReplayQueries.ts
|
|
@@ -32885,6 +33420,7 @@ function decidePrPreview(sessions, waiters, notify2, d) {
|
|
|
32885
33420
|
reason: d.reason,
|
|
32886
33421
|
comments: d.comments,
|
|
32887
33422
|
screenshots: d.screenshots,
|
|
33423
|
+
body: d.body,
|
|
32888
33424
|
reviewAfter: d.reviewAfter,
|
|
32889
33425
|
announceAfter: d.announceAfter,
|
|
32890
33426
|
draft: d.draft
|
|
@@ -33125,10 +33661,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
33125
33661
|
}
|
|
33126
33662
|
|
|
33127
33663
|
// src/commands/sessions/daemon/exitReason.ts
|
|
33128
|
-
import { existsSync as
|
|
33664
|
+
import { existsSync as existsSync79 } from "fs";
|
|
33129
33665
|
import { resolve as resolve21 } from "path";
|
|
33130
33666
|
function exitDetail(session) {
|
|
33131
|
-
if (session.cwd && !
|
|
33667
|
+
if (session.cwd && !existsSync79(session.cwd))
|
|
33132
33668
|
return `working directory ${session.cwd} no longer exists`;
|
|
33133
33669
|
return missingRunConfigCwd(session);
|
|
33134
33670
|
}
|
|
@@ -33142,7 +33678,7 @@ function missingRunConfigCwd(session) {
|
|
|
33142
33678
|
const config = resolveRunConfig(session.runName, dir);
|
|
33143
33679
|
if (!config?.cwd) return void 0;
|
|
33144
33680
|
const configured = resolve21(runConfigBaseDirFrom(dir), config.cwd);
|
|
33145
|
-
if (
|
|
33681
|
+
if (existsSync79(configured)) return void 0;
|
|
33146
33682
|
return `run config "${config.name}": cwd ${configured} does not exist`;
|
|
33147
33683
|
}
|
|
33148
33684
|
|
|
@@ -33183,7 +33719,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
33183
33719
|
}
|
|
33184
33720
|
|
|
33185
33721
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
33186
|
-
import { existsSync as
|
|
33722
|
+
import { existsSync as existsSync80, mkdirSync as mkdirSync32, watch as watch2 } from "fs";
|
|
33187
33723
|
import { dirname as dirname37 } from "path";
|
|
33188
33724
|
|
|
33189
33725
|
// src/commands/sessions/daemon/applyActivityToSession.ts
|
|
@@ -33269,7 +33805,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
33269
33805
|
if (timer) clearTimeout(timer);
|
|
33270
33806
|
timer = setTimeout(read2, DEBOUNCE_MS2);
|
|
33271
33807
|
});
|
|
33272
|
-
if (
|
|
33808
|
+
if (existsSync80(path80)) read2();
|
|
33273
33809
|
}
|
|
33274
33810
|
function refreshActivity(session) {
|
|
33275
33811
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -34891,7 +35427,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
34891
35427
|
}
|
|
34892
35428
|
|
|
34893
35429
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
34894
|
-
import { existsSync as
|
|
35430
|
+
import { existsSync as existsSync83 } from "fs";
|
|
34895
35431
|
import { basename as basename24 } from "path";
|
|
34896
35432
|
|
|
34897
35433
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
@@ -34946,9 +35482,9 @@ function bindResumedWorktree(session, cwd, notify2) {
|
|
|
34946
35482
|
}
|
|
34947
35483
|
|
|
34948
35484
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
34949
|
-
import { existsSync as
|
|
35485
|
+
import { existsSync as existsSync82 } from "fs";
|
|
34950
35486
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
34951
|
-
if (!
|
|
35487
|
+
if (!existsSync82(clone)) {
|
|
34952
35488
|
for (const { path: path80 } of paths) forgetWorktree(path80);
|
|
34953
35489
|
daemonLog(
|
|
34954
35490
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
@@ -35114,7 +35650,7 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
|
35114
35650
|
);
|
|
35115
35651
|
continue;
|
|
35116
35652
|
}
|
|
35117
|
-
if (!
|
|
35653
|
+
if (!existsSync83(path80)) {
|
|
35118
35654
|
logVanishedTree(sessions, path80);
|
|
35119
35655
|
vanished.set(clone, [
|
|
35120
35656
|
...vanished.get(clone) ?? [],
|
|
@@ -35731,14 +36267,14 @@ async function defaultConnect() {
|
|
|
35731
36267
|
}
|
|
35732
36268
|
|
|
35733
36269
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
35734
|
-
import { existsSync as
|
|
36270
|
+
import { existsSync as existsSync84, readFileSync as readFileSync56 } from "fs";
|
|
35735
36271
|
import { posix as posix3 } from "path";
|
|
35736
36272
|
function hasPersistedWindowsSessions() {
|
|
35737
36273
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
35738
36274
|
if (!sessionsFile) return false;
|
|
35739
36275
|
try {
|
|
35740
|
-
if (!
|
|
35741
|
-
const data = JSON.parse(
|
|
36276
|
+
if (!existsSync84(sessionsFile)) return false;
|
|
36277
|
+
const data = JSON.parse(readFileSync56(sessionsFile, "utf8"));
|
|
35742
36278
|
return Array.isArray(data) && data.length > 0;
|
|
35743
36279
|
} catch (error) {
|
|
35744
36280
|
const message3 = error instanceof Error ? error.message : String(error);
|
|
@@ -36472,7 +37008,7 @@ function setAutoAdvance(sessions, id, enabled) {
|
|
|
36472
37008
|
}
|
|
36473
37009
|
|
|
36474
37010
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
36475
|
-
import { existsSync as
|
|
37011
|
+
import { existsSync as existsSync87 } from "fs";
|
|
36476
37012
|
|
|
36477
37013
|
// src/commands/sessions/daemon/resumeSession.ts
|
|
36478
37014
|
function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
@@ -36503,10 +37039,10 @@ function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
|
36503
37039
|
}
|
|
36504
37040
|
|
|
36505
37041
|
// src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
|
|
36506
|
-
import { existsSync as
|
|
37042
|
+
import { existsSync as existsSync86 } from "fs";
|
|
36507
37043
|
|
|
36508
37044
|
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
36509
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
37045
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync85, mkdirSync as mkdirSync34 } from "fs";
|
|
36510
37046
|
import { join as join94 } from "path";
|
|
36511
37047
|
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
36512
37048
|
const dir = projectDirForCwd(toCwd);
|
|
@@ -36517,7 +37053,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
36517
37053
|
return;
|
|
36518
37054
|
}
|
|
36519
37055
|
const dest = join94(dir, `${claudeSessionId}.jsonl`);
|
|
36520
|
-
if (
|
|
37056
|
+
if (existsSync85(dest)) {
|
|
36521
37057
|
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
36522
37058
|
return;
|
|
36523
37059
|
}
|
|
@@ -36568,7 +37104,7 @@ function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name, harness
|
|
|
36568
37104
|
}
|
|
36569
37105
|
function cloneForReapedTree(missingCwd) {
|
|
36570
37106
|
const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
|
|
36571
|
-
if (!clone || !
|
|
37107
|
+
if (!clone || !existsSync86(clone))
|
|
36572
37108
|
throw new Error(
|
|
36573
37109
|
`working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
|
|
36574
37110
|
);
|
|
@@ -36577,7 +37113,7 @@ function cloneForReapedTree(missingCwd) {
|
|
|
36577
37113
|
|
|
36578
37114
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
36579
37115
|
function resumeInTree(ctx, sessionId, cwd, name, harness) {
|
|
36580
|
-
if (!
|
|
37116
|
+
if (!existsSync87(cwd))
|
|
36581
37117
|
return resumeInReplacementTree(ctx, sessionId, cwd, name, harness);
|
|
36582
37118
|
const id = ctx.spawnWith(
|
|
36583
37119
|
(sid) => resumeSession(sid, sessionId, cwd, name, void 0, harness)
|
|
@@ -37156,7 +37692,7 @@ function handleConnection(socket, manager) {
|
|
|
37156
37692
|
import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync47 } from "fs";
|
|
37157
37693
|
|
|
37158
37694
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
37159
|
-
import { readFileSync as
|
|
37695
|
+
import { readFileSync as readFileSync57 } from "fs";
|
|
37160
37696
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
37161
37697
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
37162
37698
|
const timer = setInterval(() => {
|
|
@@ -37167,7 +37703,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
37167
37703
|
}
|
|
37168
37704
|
function ownsPidFile() {
|
|
37169
37705
|
try {
|
|
37170
|
-
return
|
|
37706
|
+
return readFileSync57(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
37171
37707
|
} catch {
|
|
37172
37708
|
return false;
|
|
37173
37709
|
}
|
|
@@ -37417,7 +37953,7 @@ function registerSetStatusCommand(cmd) {
|
|
|
37417
37953
|
|
|
37418
37954
|
// src/commands/sessions/summarise/index.ts
|
|
37419
37955
|
import * as fs56 from "fs";
|
|
37420
|
-
import
|
|
37956
|
+
import chalk218 from "chalk";
|
|
37421
37957
|
|
|
37422
37958
|
// src/commands/sessions/summarise/shared.ts
|
|
37423
37959
|
import * as fs55 from "fs";
|
|
@@ -37476,22 +38012,22 @@ ${firstMessage}`);
|
|
|
37476
38012
|
async function summarise2(options2) {
|
|
37477
38013
|
const files = await discoverSessionFiles();
|
|
37478
38014
|
if (files.length === 0) {
|
|
37479
|
-
console.log(
|
|
38015
|
+
console.log(chalk218.yellow("No sessions found."));
|
|
37480
38016
|
return;
|
|
37481
38017
|
}
|
|
37482
38018
|
const toProcess = selectCandidates(files, options2);
|
|
37483
38019
|
if (toProcess.length === 0) {
|
|
37484
|
-
console.log(
|
|
38020
|
+
console.log(chalk218.green("All sessions already summarised."));
|
|
37485
38021
|
return;
|
|
37486
38022
|
}
|
|
37487
38023
|
console.log(
|
|
37488
|
-
|
|
38024
|
+
chalk218.cyan(
|
|
37489
38025
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
37490
38026
|
)
|
|
37491
38027
|
);
|
|
37492
38028
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
37493
38029
|
console.log(
|
|
37494
|
-
|
|
38030
|
+
chalk218.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk218.yellow(`, ${failed2} skipped`) : "")
|
|
37495
38031
|
);
|
|
37496
38032
|
}
|
|
37497
38033
|
function selectCandidates(files, options2) {
|
|
@@ -37511,16 +38047,16 @@ function processSessions(files) {
|
|
|
37511
38047
|
let failed2 = 0;
|
|
37512
38048
|
for (let i = 0; i < files.length; i++) {
|
|
37513
38049
|
const file = files[i];
|
|
37514
|
-
process.stdout.write(
|
|
38050
|
+
process.stdout.write(chalk218.dim(` [${i + 1}/${files.length}] `));
|
|
37515
38051
|
const summary = summariseSession(file);
|
|
37516
38052
|
if (summary) {
|
|
37517
38053
|
writeSummary(file, summary);
|
|
37518
38054
|
succeeded++;
|
|
37519
|
-
process.stdout.write(`${
|
|
38055
|
+
process.stdout.write(`${chalk218.green("\u2713")} ${summary}
|
|
37520
38056
|
`);
|
|
37521
38057
|
} else {
|
|
37522
38058
|
failed2++;
|
|
37523
|
-
process.stdout.write(` ${
|
|
38059
|
+
process.stdout.write(` ${chalk218.yellow("skip")}
|
|
37524
38060
|
`);
|
|
37525
38061
|
}
|
|
37526
38062
|
}
|
|
@@ -37541,7 +38077,7 @@ function registerSessions(program2) {
|
|
|
37541
38077
|
}
|
|
37542
38078
|
|
|
37543
38079
|
// src/commands/statusLine.ts
|
|
37544
|
-
import
|
|
38080
|
+
import chalk220 from "chalk";
|
|
37545
38081
|
|
|
37546
38082
|
// src/shared/contextLevel.ts
|
|
37547
38083
|
function contextLevel(pct) {
|
|
@@ -37551,7 +38087,7 @@ function contextLevel(pct) {
|
|
|
37551
38087
|
}
|
|
37552
38088
|
|
|
37553
38089
|
// src/commands/buildLimitsSegment.ts
|
|
37554
|
-
import
|
|
38090
|
+
import chalk219 from "chalk";
|
|
37555
38091
|
|
|
37556
38092
|
// src/shared/rateLimitLevel.ts
|
|
37557
38093
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -37589,9 +38125,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
37589
38125
|
|
|
37590
38126
|
// src/commands/buildLimitsSegment.ts
|
|
37591
38127
|
var LEVEL_COLOR = {
|
|
37592
|
-
ok:
|
|
37593
|
-
warn:
|
|
37594
|
-
over:
|
|
38128
|
+
ok: chalk219.green,
|
|
38129
|
+
warn: chalk219.yellow,
|
|
38130
|
+
over: chalk219.red
|
|
37595
38131
|
};
|
|
37596
38132
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
37597
38133
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -37622,7 +38158,7 @@ function buildLimitsSegment(rateLimits) {
|
|
|
37622
38158
|
}
|
|
37623
38159
|
|
|
37624
38160
|
// src/commands/readGitBranch.ts
|
|
37625
|
-
import { readFileSync as
|
|
38161
|
+
import { readFileSync as readFileSync59, statSync as statSync15 } from "fs";
|
|
37626
38162
|
import { isAbsolute as isAbsolute4, join as join95, resolve as resolve22 } from "path";
|
|
37627
38163
|
function resolveGitDir(cwd) {
|
|
37628
38164
|
const dotGit = join95(cwd, ".git");
|
|
@@ -37637,7 +38173,7 @@ function resolveGitDir(cwd) {
|
|
|
37637
38173
|
}
|
|
37638
38174
|
let contents;
|
|
37639
38175
|
try {
|
|
37640
|
-
contents =
|
|
38176
|
+
contents = readFileSync59(dotGit, "utf8");
|
|
37641
38177
|
} catch {
|
|
37642
38178
|
return null;
|
|
37643
38179
|
}
|
|
@@ -37655,7 +38191,7 @@ function readGitBranch(cwd) {
|
|
|
37655
38191
|
}
|
|
37656
38192
|
let head;
|
|
37657
38193
|
try {
|
|
37658
|
-
head =
|
|
38194
|
+
head = readFileSync59(join95(gitDir, "HEAD"), "utf8");
|
|
37659
38195
|
} catch {
|
|
37660
38196
|
return null;
|
|
37661
38197
|
}
|
|
@@ -37687,7 +38223,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
|
|
|
37687
38223
|
}
|
|
37688
38224
|
|
|
37689
38225
|
// src/commands/statusLine.ts
|
|
37690
|
-
|
|
38226
|
+
chalk220.level = 3;
|
|
37691
38227
|
function formatNumber(num) {
|
|
37692
38228
|
return num.toLocaleString("en-US");
|
|
37693
38229
|
}
|
|
@@ -37695,9 +38231,9 @@ function colorizePercent(pct) {
|
|
|
37695
38231
|
const label2 = `${Math.round(pct)}%`;
|
|
37696
38232
|
switch (contextLevel(pct)) {
|
|
37697
38233
|
case "red":
|
|
37698
|
-
return
|
|
38234
|
+
return chalk220.red(label2);
|
|
37699
38235
|
case "yellow":
|
|
37700
|
-
return
|
|
38236
|
+
return chalk220.yellow(label2);
|
|
37701
38237
|
default:
|
|
37702
38238
|
return label2;
|
|
37703
38239
|
}
|
|
@@ -37710,7 +38246,7 @@ async function statusLine() {
|
|
|
37710
38246
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
37711
38247
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
37712
38248
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
37713
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
38249
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk220.cyan(branch2)} | ` : "";
|
|
37714
38250
|
console.log(
|
|
37715
38251
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
37716
38252
|
);
|
|
@@ -37780,10 +38316,10 @@ async function update2() {
|
|
|
37780
38316
|
}
|
|
37781
38317
|
|
|
37782
38318
|
// src/reportCliError.ts
|
|
37783
|
-
import
|
|
38319
|
+
import chalk221 from "chalk";
|
|
37784
38320
|
function reportCliError(error) {
|
|
37785
38321
|
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError) {
|
|
37786
|
-
console.error(
|
|
38322
|
+
console.error(chalk221.red(error.message));
|
|
37787
38323
|
} else {
|
|
37788
38324
|
console.error(error);
|
|
37789
38325
|
}
|