@staff0rd/assist 0.575.0 → 0.577.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 -2
- 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 +1 -1
- package/dist/index.js +1101 -441
- 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.577.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -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
|
|
|
@@ -14030,7 +14031,7 @@ function requestPreviewDecision(request) {
|
|
|
14030
14031
|
}
|
|
14031
14032
|
|
|
14032
14033
|
// src/commands/sessions/shared/awaitPreviewApproval.ts
|
|
14033
|
-
async function awaitPreviewApproval(subject, request,
|
|
14034
|
+
async function awaitPreviewApproval(subject, request, options2 = {}) {
|
|
14034
14035
|
console.log("Awaiting your approval in the assist web UI preview pane\u2026");
|
|
14035
14036
|
let decision;
|
|
14036
14037
|
try {
|
|
@@ -14041,8 +14042,9 @@ async function awaitPreviewApproval(subject, request, saveEditedBody) {
|
|
|
14041
14042
|
);
|
|
14042
14043
|
process.exit(1);
|
|
14043
14044
|
}
|
|
14044
|
-
if (decision.body !== void 0) saveEditedBody?.(decision.body);
|
|
14045
|
-
if (decision.decision === "reject")
|
|
14045
|
+
if (decision.body !== void 0) options2.saveEditedBody?.(decision.body);
|
|
14046
|
+
if (decision.decision === "reject")
|
|
14047
|
+
reportPreviewRejection(subject, decision, options2.rejectionAdvice);
|
|
14046
14048
|
return decision;
|
|
14047
14049
|
}
|
|
14048
14050
|
|
|
@@ -14912,12 +14914,12 @@ async function link(fromId, toId, opts) {
|
|
|
14912
14914
|
const { orm } = await getReady();
|
|
14913
14915
|
const fromItem = await loadItem(orm, fromNum);
|
|
14914
14916
|
if (!fromItem) return void fail4(`Item ${from} not found.`);
|
|
14915
|
-
const
|
|
14916
|
-
if (!
|
|
14917
|
+
const toItem2 = await loadItem(orm, toNum);
|
|
14918
|
+
if (!toItem2) return void fail4(`Item ${to} not found.`);
|
|
14917
14919
|
if (!validateLinkTarget(fromItem, fromNum, toNum, linkType)) return;
|
|
14918
14920
|
if (await createsCycle(orm, linkType, fromNum, toNum)) return;
|
|
14919
14921
|
await orm.insert(links).values({ itemId: fromNum, type: linkType, targetId: toNum });
|
|
14920
|
-
console.log(chalk85.green(`Linked ${from} ${linkType} ${to} (${
|
|
14922
|
+
console.log(chalk85.green(`Linked ${from} ${linkType} ${to} (${toItem2.name})`));
|
|
14921
14923
|
}
|
|
14922
14924
|
|
|
14923
14925
|
// src/commands/backlog/unlink.ts
|
|
@@ -20500,14 +20502,8 @@ import { spawnSync as spawnSync4 } from "child_process";
|
|
|
20500
20502
|
import { unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
|
|
20501
20503
|
import { tmpdir as tmpdir5 } from "os";
|
|
20502
20504
|
import { join as join49 } from "path";
|
|
20503
|
-
|
|
20504
|
-
|
|
20505
|
-
for (const [key, value] of Object.entries(vars)) {
|
|
20506
|
-
const flag = typeof value === "number" ? "-F" : "-f";
|
|
20507
|
-
args.push(flag, `${key}=${value}`);
|
|
20508
|
-
}
|
|
20509
|
-
return args;
|
|
20510
|
-
}
|
|
20505
|
+
|
|
20506
|
+
// src/shared/throwOnGraphqlErrors.ts
|
|
20511
20507
|
function throwOnGraphqlErrors(stdout) {
|
|
20512
20508
|
let parsed;
|
|
20513
20509
|
try {
|
|
@@ -20523,6 +20519,16 @@ function throwOnGraphqlErrors(stdout) {
|
|
|
20523
20519
|
).join("; ");
|
|
20524
20520
|
throw new Error(messages || "GraphQL request returned errors");
|
|
20525
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
|
+
}
|
|
20526
20532
|
function runGhGraphql(mutation, vars) {
|
|
20527
20533
|
const queryFile = join49(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
20528
20534
|
writeFileSync30(queryFile, mutation);
|
|
@@ -20830,6 +20836,83 @@ function fetchIssue2(number, repo) {
|
|
|
20830
20836
|
}
|
|
20831
20837
|
}
|
|
20832
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
|
+
|
|
20833
20916
|
// src/commands/github/issue/pushIssueBody.ts
|
|
20834
20917
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
20835
20918
|
function pushIssueBody(number, repo, bodyPath) {
|
|
@@ -20856,7 +20939,7 @@ function pushUnchangedIssue(number, repo, target, fetchedAt, bodyPath) {
|
|
|
20856
20939
|
|
|
20857
20940
|
// src/commands/github/issue/reviewProposedIssueEdit.ts
|
|
20858
20941
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
20859
|
-
async function reviewProposedIssueEdit(title, body,
|
|
20942
|
+
async function reviewProposedIssueEdit(title, body, working) {
|
|
20860
20943
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
20861
20944
|
if (process.env.ASSIST_SESSION !== "1" || !sessionId) return body;
|
|
20862
20945
|
const decision = await awaitPreviewApproval(
|
|
@@ -20869,7 +20952,10 @@ async function reviewProposedIssueEdit(title, body, saveEditedBody) {
|
|
|
20869
20952
|
prNumber: null,
|
|
20870
20953
|
kind: "github-issue-edit"
|
|
20871
20954
|
},
|
|
20872
|
-
|
|
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
|
+
}
|
|
20873
20959
|
);
|
|
20874
20960
|
return decision.body ?? body;
|
|
20875
20961
|
}
|
|
@@ -20886,40 +20972,8 @@ function viewIssue(number, repo) {
|
|
|
20886
20972
|
}
|
|
20887
20973
|
}
|
|
20888
20974
|
|
|
20889
|
-
// src/commands/github/issue/writeIssueWorkingFile.ts
|
|
20890
|
-
import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync31 } from "fs";
|
|
20891
|
-
|
|
20892
|
-
// src/commands/github/issue/issueWorkingFile.ts
|
|
20893
|
-
import { join as join50 } from "path";
|
|
20894
|
-
function issueWorkingFile(slug, number) {
|
|
20895
|
-
const [owner = "unknown", repo = "unknown"] = slug.split("/");
|
|
20896
|
-
const dir = join50(getStoreDir(), "github-issues", owner, repo);
|
|
20897
|
-
return {
|
|
20898
|
-
dir,
|
|
20899
|
-
bodyPath: join50(dir, `${number}.md`),
|
|
20900
|
-
metaPath: join50(dir, `${number}.json`)
|
|
20901
|
-
};
|
|
20902
|
-
}
|
|
20903
|
-
|
|
20904
|
-
// src/commands/github/issue/writeIssueWorkingFile.ts
|
|
20905
|
-
function writeIssueWorkingFile(slug, number, target, updatedAt, body) {
|
|
20906
|
-
const { dir, bodyPath, metaPath } = issueWorkingFile(slug, number);
|
|
20907
|
-
mkdirSync16(dir, { recursive: true });
|
|
20908
|
-
writeFileSync31(bodyPath, body);
|
|
20909
|
-
writeFileSync31(
|
|
20910
|
-
metaPath,
|
|
20911
|
-
`${JSON.stringify({ target, updatedAt }, null, 2)}
|
|
20912
|
-
`
|
|
20913
|
-
);
|
|
20914
|
-
return bodyPath;
|
|
20915
|
-
}
|
|
20916
|
-
|
|
20917
20975
|
// src/commands/github/issue/editIssue.ts
|
|
20918
20976
|
var USAGE3 = "Usage: assist github issue edit <number> [-R <owner>/<repo>]";
|
|
20919
|
-
function slugFromUrl(url) {
|
|
20920
|
-
const match = /github\.com\/([^/]+\/[^/]+)\//.exec(url ?? "");
|
|
20921
|
-
return match ? match[1] : "unknown/unknown";
|
|
20922
|
-
}
|
|
20923
20977
|
async function editIssue(numberArg, options2) {
|
|
20924
20978
|
const number = Number.parseInt(numberArg, 10);
|
|
20925
20979
|
if (!Number.isInteger(number) || number <= 0) {
|
|
@@ -20930,27 +20984,419 @@ async function editIssue(numberArg, options2) {
|
|
|
20930
20984
|
viewIssue(number, options2.repo);
|
|
20931
20985
|
return;
|
|
20932
20986
|
}
|
|
20933
|
-
const issue =
|
|
20934
|
-
const slug = options2.repo ?? slugFromUrl(issue.url);
|
|
20935
|
-
const target = `${slug}#${number}`;
|
|
20936
|
-
validateProposedContent(
|
|
20937
|
-
{ subject: "Issue", context: "GitHub issues" },
|
|
20938
|
-
issue.title,
|
|
20939
|
-
issue.body
|
|
20940
|
-
);
|
|
20941
|
-
const save = (markdown) => writeIssueWorkingFile(slug, number, target, issue.updatedAt, markdown);
|
|
20942
|
-
const bodyPath = save(issue.body);
|
|
20987
|
+
const issue = prepareIssueEdit(number, options2.repo, options2.fresh);
|
|
20943
20988
|
const edited = await reviewProposedIssueEdit(
|
|
20944
|
-
`Edit ${target}: ${issue.title}`,
|
|
20989
|
+
`Edit ${issue.target}: ${issue.title}`,
|
|
20945
20990
|
issue.body,
|
|
20946
|
-
save
|
|
20991
|
+
{ path: issue.bodyPath, save: issue.save }
|
|
20947
20992
|
);
|
|
20948
|
-
|
|
20949
|
-
|
|
20950
|
-
|
|
20951
|
-
|
|
20993
|
+
validateIssueBody(issue.title, edited);
|
|
20994
|
+
pushUnchangedIssue(
|
|
20995
|
+
number,
|
|
20996
|
+
options2.repo,
|
|
20997
|
+
issue.target,
|
|
20998
|
+
issue.updatedAt,
|
|
20999
|
+
issue.bodyPath
|
|
20952
21000
|
);
|
|
20953
|
-
|
|
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
|
|
21020
|
+
);
|
|
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}` : "";
|
|
21205
|
+
console.error(
|
|
21206
|
+
chalk162.red(
|
|
21207
|
+
`${issue.repo}#${issue.number}${where} sits below ${chain2[chain2.length - 1]}, the leaf level`
|
|
21208
|
+
)
|
|
21209
|
+
);
|
|
21210
|
+
}
|
|
21211
|
+
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.`
|
|
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));
|
|
21378
|
+
process.exit(1);
|
|
21379
|
+
}
|
|
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);
|
|
20954
21400
|
}
|
|
20955
21401
|
|
|
20956
21402
|
// src/commands/prs/readBodyArgument.ts
|
|
@@ -20977,9 +21423,12 @@ function registerGithubIssue(githubCommand) {
|
|
|
20977
21423
|
issueCommand.command("edit <number>").description("Edit an existing GitHub issue's body in the preview pane").option(
|
|
20978
21424
|
"-R, --repo <owner/repo>",
|
|
20979
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"
|
|
20980
21429
|
).addHelpText(
|
|
20981
21430
|
"after",
|
|
20982
|
-
"\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."
|
|
20983
21432
|
).action(editIssue);
|
|
20984
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(
|
|
20985
21434
|
"-R, --repo <owner/repo>",
|
|
@@ -20995,6 +21444,7 @@ function registerGithubIssue(githubCommand) {
|
|
|
20995
21444
|
});
|
|
20996
21445
|
}
|
|
20997
21446
|
);
|
|
21447
|
+
registerFixStructure(issueCommand);
|
|
20998
21448
|
}
|
|
20999
21449
|
|
|
21000
21450
|
// src/commands/registerGithub.ts
|
|
@@ -21021,9 +21471,9 @@ async function countPendingHandovers(orm, origin) {
|
|
|
21021
21471
|
|
|
21022
21472
|
// src/commands/handover/migrateDiskHandovers.ts
|
|
21023
21473
|
import {
|
|
21024
|
-
existsSync as
|
|
21474
|
+
existsSync as existsSync49,
|
|
21025
21475
|
readdirSync as readdirSync10,
|
|
21026
|
-
readFileSync as
|
|
21476
|
+
readFileSync as readFileSync38,
|
|
21027
21477
|
rmSync as rmSync3,
|
|
21028
21478
|
statSync as statSync8
|
|
21029
21479
|
} from "fs";
|
|
@@ -21076,7 +21526,7 @@ function summariseHandoverContent(content) {
|
|
|
21076
21526
|
|
|
21077
21527
|
// src/commands/handover/migrateDiskHandovers.ts
|
|
21078
21528
|
function collectMarkdown(dir) {
|
|
21079
|
-
if (!
|
|
21529
|
+
if (!existsSync49(dir)) return [];
|
|
21080
21530
|
const out = [];
|
|
21081
21531
|
for (const entry of readdirSync10(dir, { withFileTypes: true })) {
|
|
21082
21532
|
const full = join53(dir, entry.name);
|
|
@@ -21086,7 +21536,7 @@ function collectMarkdown(dir) {
|
|
|
21086
21536
|
return out;
|
|
21087
21537
|
}
|
|
21088
21538
|
async function migrateFile(orm, origin, file, createdAt) {
|
|
21089
|
-
const content =
|
|
21539
|
+
const content = readFileSync38(file, "utf8");
|
|
21090
21540
|
await saveHandover(orm, {
|
|
21091
21541
|
origin,
|
|
21092
21542
|
summary: summariseHandoverContent(content),
|
|
@@ -21103,7 +21553,7 @@ async function migrateDiskHandovers(orm, origin, cwd = process.cwd()) {
|
|
|
21103
21553
|
migrated++;
|
|
21104
21554
|
}
|
|
21105
21555
|
const handoverPath = getHandoverPath(cwd);
|
|
21106
|
-
if (
|
|
21556
|
+
if (existsSync49(handoverPath)) {
|
|
21107
21557
|
await migrateFile(orm, origin, handoverPath, statSync8(handoverPath).mtime);
|
|
21108
21558
|
migrated++;
|
|
21109
21559
|
}
|
|
@@ -21234,7 +21684,7 @@ function registerHandover(program2) {
|
|
|
21234
21684
|
}
|
|
21235
21685
|
|
|
21236
21686
|
// src/commands/jira/acceptanceCriteria.ts
|
|
21237
|
-
import
|
|
21687
|
+
import chalk163 from "chalk";
|
|
21238
21688
|
|
|
21239
21689
|
// src/commands/jira/adfToText.ts
|
|
21240
21690
|
function renderInline(node) {
|
|
@@ -21301,7 +21751,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
21301
21751
|
const parsed = fetchIssue(issueKey, field);
|
|
21302
21752
|
const acValue = parsed?.fields?.[field];
|
|
21303
21753
|
if (!acValue) {
|
|
21304
|
-
console.log(
|
|
21754
|
+
console.log(chalk163.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
21305
21755
|
return;
|
|
21306
21756
|
}
|
|
21307
21757
|
if (typeof acValue === "string") {
|
|
@@ -21367,14 +21817,14 @@ async function jiraAuth() {
|
|
|
21367
21817
|
}
|
|
21368
21818
|
|
|
21369
21819
|
// src/commands/jira/viewIssue.ts
|
|
21370
|
-
import
|
|
21820
|
+
import chalk164 from "chalk";
|
|
21371
21821
|
function viewIssue2(issueKey) {
|
|
21372
21822
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
21373
21823
|
const fields = parsed?.fields;
|
|
21374
21824
|
const summary = fields?.summary;
|
|
21375
21825
|
const description = fields?.description;
|
|
21376
21826
|
if (summary) {
|
|
21377
|
-
console.log(
|
|
21827
|
+
console.log(chalk164.bold(summary));
|
|
21378
21828
|
}
|
|
21379
21829
|
if (description) {
|
|
21380
21830
|
if (summary) console.log();
|
|
@@ -21388,7 +21838,7 @@ function viewIssue2(issueKey) {
|
|
|
21388
21838
|
}
|
|
21389
21839
|
if (!summary && !description) {
|
|
21390
21840
|
console.log(
|
|
21391
|
-
|
|
21841
|
+
chalk164.yellow(`No summary or description found on ${issueKey}.`)
|
|
21392
21842
|
);
|
|
21393
21843
|
}
|
|
21394
21844
|
}
|
|
@@ -21423,7 +21873,7 @@ import { randomUUID as randomUUID10 } from "crypto";
|
|
|
21423
21873
|
|
|
21424
21874
|
// src/commands/review/checkoutPr.ts
|
|
21425
21875
|
import { execFileSync as execFileSync12 } from "child_process";
|
|
21426
|
-
import
|
|
21876
|
+
import chalk165 from "chalk";
|
|
21427
21877
|
|
|
21428
21878
|
// src/commands/sessions/daemon/daemonLog.ts
|
|
21429
21879
|
var RING_CAPACITY = 1e3;
|
|
@@ -21460,7 +21910,7 @@ function canonicalTreePath(path80) {
|
|
|
21460
21910
|
}
|
|
21461
21911
|
|
|
21462
21912
|
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
21463
|
-
import { existsSync as
|
|
21913
|
+
import { existsSync as existsSync50 } from "fs";
|
|
21464
21914
|
import { basename as basename16, dirname as dirname25 } from "path";
|
|
21465
21915
|
|
|
21466
21916
|
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
@@ -21507,7 +21957,7 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
|
21507
21957
|
const base = strategy.root ? expandTilde2(strategy.root) : dirname25(clone);
|
|
21508
21958
|
const registered = new Set(listWorktreePaths(clone));
|
|
21509
21959
|
const branches = new Set(listLocalBranches(clone));
|
|
21510
|
-
const isTaken = (candidate) => registered.has(candidate) ||
|
|
21960
|
+
const isTaken = (candidate) => registered.has(candidate) || existsSync50(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename16(candidate));
|
|
21511
21961
|
const path80 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
|
|
21512
21962
|
const start3 = worktreeStartPoint(clone, strategy.trunk);
|
|
21513
21963
|
gitSync(clone, [
|
|
@@ -21533,7 +21983,7 @@ function keptInTree(cwd, reason4) {
|
|
|
21533
21983
|
}
|
|
21534
21984
|
|
|
21535
21985
|
// src/commands/sessions/daemon/worktree/treeDurability.ts
|
|
21536
|
-
import { existsSync as
|
|
21986
|
+
import { existsSync as existsSync51 } from "fs";
|
|
21537
21987
|
var treeIsGone = { durable: true, gone: true };
|
|
21538
21988
|
function treeDurability(state) {
|
|
21539
21989
|
if (state.dirty) return { durable: false, reason: "uncommitted changes" };
|
|
@@ -21564,14 +22014,14 @@ function* durabilityProbes() {
|
|
|
21564
22014
|
});
|
|
21565
22015
|
}
|
|
21566
22016
|
async function checkDurability(cwd) {
|
|
21567
|
-
if (!
|
|
22017
|
+
if (!existsSync51(cwd)) return treeIsGone;
|
|
21568
22018
|
const probes = durabilityProbes();
|
|
21569
22019
|
let step2 = probes.next();
|
|
21570
22020
|
while (!step2.done) step2 = probes.next(await gitResult(cwd, step2.value));
|
|
21571
22021
|
return step2.value;
|
|
21572
22022
|
}
|
|
21573
22023
|
function checkDurabilitySync(cwd) {
|
|
21574
|
-
if (!
|
|
22024
|
+
if (!existsSync51(cwd)) return treeIsGone;
|
|
21575
22025
|
const probes = durabilityProbes();
|
|
21576
22026
|
let step2 = probes.next();
|
|
21577
22027
|
while (!step2.done) step2 = probes.next(gitSyncResult(cwd, step2.value));
|
|
@@ -21814,20 +22264,20 @@ function persistedTreeRoots() {
|
|
|
21814
22264
|
}
|
|
21815
22265
|
|
|
21816
22266
|
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
21817
|
-
import { copyFileSync, existsSync as
|
|
22267
|
+
import { copyFileSync, existsSync as existsSync53, mkdirSync as mkdirSync17 } from "fs";
|
|
21818
22268
|
import { dirname as dirname26, join as join56 } from "path";
|
|
21819
22269
|
|
|
21820
22270
|
// src/commands/sessions/daemon/worktree/runInstall.ts
|
|
21821
22271
|
import { spawn as spawn5 } from "child_process";
|
|
21822
22272
|
|
|
21823
22273
|
// src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
|
|
21824
|
-
import { existsSync as
|
|
22274
|
+
import { existsSync as existsSync52 } from "fs";
|
|
21825
22275
|
import { join as join55 } from "path";
|
|
21826
22276
|
function detectInstallCommand(repoRoot2) {
|
|
21827
|
-
if (!
|
|
21828
|
-
if (
|
|
21829
|
-
if (
|
|
21830
|
-
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";
|
|
21831
22281
|
return "npm install";
|
|
21832
22282
|
}
|
|
21833
22283
|
function resolveInstallCommand(repoRoot2, install) {
|
|
@@ -21940,7 +22390,7 @@ function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
|
21940
22390
|
function copyConfigFiles(worktreePath, clone, copy) {
|
|
21941
22391
|
for (const rel of copy) {
|
|
21942
22392
|
const src = join56(clone, rel);
|
|
21943
|
-
if (!
|
|
22393
|
+
if (!existsSync53(src)) continue;
|
|
21944
22394
|
const dest = join56(worktreePath, rel);
|
|
21945
22395
|
try {
|
|
21946
22396
|
mkdirSync17(dirname26(dest), { recursive: true });
|
|
@@ -22035,7 +22485,7 @@ async function checkoutPr(number) {
|
|
|
22035
22485
|
try {
|
|
22036
22486
|
execFileSync12("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
22037
22487
|
} catch {
|
|
22038
|
-
console.error(
|
|
22488
|
+
console.error(chalk165.red(`gh pr checkout ${number} failed; aborting.`));
|
|
22039
22489
|
process.exit(1);
|
|
22040
22490
|
}
|
|
22041
22491
|
}
|
|
@@ -22172,15 +22622,15 @@ function registerList(program2) {
|
|
|
22172
22622
|
// src/commands/mermaid/index.ts
|
|
22173
22623
|
import { mkdirSync as mkdirSync18, readdirSync as readdirSync11 } from "fs";
|
|
22174
22624
|
import { resolve as resolve16 } from "path";
|
|
22175
|
-
import
|
|
22625
|
+
import chalk168 from "chalk";
|
|
22176
22626
|
|
|
22177
22627
|
// src/commands/mermaid/exportFile.ts
|
|
22178
|
-
import { readFileSync as
|
|
22628
|
+
import { readFileSync as readFileSync39, writeFileSync as writeFileSync32 } from "fs";
|
|
22179
22629
|
import { basename as basename17, extname as extname2, resolve as resolve15 } from "path";
|
|
22180
|
-
import
|
|
22630
|
+
import chalk167 from "chalk";
|
|
22181
22631
|
|
|
22182
22632
|
// src/commands/mermaid/renderBlock.ts
|
|
22183
|
-
import
|
|
22633
|
+
import chalk166 from "chalk";
|
|
22184
22634
|
async function renderBlock(krokiUrl, source) {
|
|
22185
22635
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
22186
22636
|
method: "POST",
|
|
@@ -22189,7 +22639,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
22189
22639
|
});
|
|
22190
22640
|
if (!response.ok) {
|
|
22191
22641
|
console.error(
|
|
22192
|
-
|
|
22642
|
+
chalk166.red(
|
|
22193
22643
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
22194
22644
|
)
|
|
22195
22645
|
);
|
|
@@ -22201,25 +22651,25 @@ async function renderBlock(krokiUrl, source) {
|
|
|
22201
22651
|
|
|
22202
22652
|
// src/commands/mermaid/exportFile.ts
|
|
22203
22653
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
22204
|
-
const content =
|
|
22654
|
+
const content = readFileSync39(file, "utf8");
|
|
22205
22655
|
const blocks = extractMermaidBlocks(content);
|
|
22206
22656
|
const stem = basename17(file, extname2(file));
|
|
22207
22657
|
if (onlyIndex !== void 0) {
|
|
22208
22658
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
22209
22659
|
console.error(
|
|
22210
|
-
|
|
22660
|
+
chalk167.red(
|
|
22211
22661
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
22212
22662
|
)
|
|
22213
22663
|
);
|
|
22214
22664
|
process.exit(1);
|
|
22215
22665
|
}
|
|
22216
22666
|
console.log(
|
|
22217
|
-
|
|
22667
|
+
chalk167.gray(
|
|
22218
22668
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
22219
22669
|
)
|
|
22220
22670
|
);
|
|
22221
22671
|
} else {
|
|
22222
|
-
console.log(
|
|
22672
|
+
console.log(chalk167.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
22223
22673
|
}
|
|
22224
22674
|
for (const [i, source] of blocks.entries()) {
|
|
22225
22675
|
const idx = i + 1;
|
|
@@ -22227,7 +22677,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
22227
22677
|
const outPath = resolve15(outDir, `${stem}-${idx}.svg`);
|
|
22228
22678
|
const svg = await renderBlock(krokiUrl, source);
|
|
22229
22679
|
writeFileSync32(outPath, svg, "utf8");
|
|
22230
|
-
console.log(
|
|
22680
|
+
console.log(chalk167.green(` \u2192 ${outPath}`));
|
|
22231
22681
|
}
|
|
22232
22682
|
}
|
|
22233
22683
|
function extractMermaidBlocks(markdown) {
|
|
@@ -22243,18 +22693,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
22243
22693
|
if (options2.index !== void 0) {
|
|
22244
22694
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
22245
22695
|
console.error(
|
|
22246
|
-
|
|
22696
|
+
chalk168.red(`--index must be a positive integer (got ${options2.index})`)
|
|
22247
22697
|
);
|
|
22248
22698
|
process.exit(1);
|
|
22249
22699
|
}
|
|
22250
22700
|
if (!file) {
|
|
22251
|
-
console.error(
|
|
22701
|
+
console.error(chalk168.red("--index requires a file argument"));
|
|
22252
22702
|
process.exit(1);
|
|
22253
22703
|
}
|
|
22254
22704
|
}
|
|
22255
22705
|
const files = file ? [file] : readdirSync11(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
22256
22706
|
if (files.length === 0) {
|
|
22257
|
-
console.log(
|
|
22707
|
+
console.log(chalk168.gray("No markdown files found in current directory."));
|
|
22258
22708
|
return;
|
|
22259
22709
|
}
|
|
22260
22710
|
for (const f of files) {
|
|
@@ -22277,11 +22727,191 @@ function registerMermaid(program2) {
|
|
|
22277
22727
|
configHelp(cmd, mermaidConfigHelp);
|
|
22278
22728
|
}
|
|
22279
22729
|
|
|
22730
|
+
// src/commands/miro/runExtract.ts
|
|
22731
|
+
import { stringify } from "yaml";
|
|
22732
|
+
|
|
22733
|
+
// src/commands/miro/MiroExtractError.ts
|
|
22734
|
+
var MiroExtractError = class extends Error {
|
|
22735
|
+
constructor(message3) {
|
|
22736
|
+
super(message3);
|
|
22737
|
+
this.name = "MiroExtractError";
|
|
22738
|
+
}
|
|
22739
|
+
};
|
|
22740
|
+
|
|
22741
|
+
// src/commands/miro/stripHtml.ts
|
|
22742
|
+
var namedEntities = {
|
|
22743
|
+
amp: "&",
|
|
22744
|
+
apos: "'",
|
|
22745
|
+
gt: ">",
|
|
22746
|
+
lt: "<",
|
|
22747
|
+
nbsp: " ",
|
|
22748
|
+
quot: '"'
|
|
22749
|
+
};
|
|
22750
|
+
function decodeEntity(_match, entity) {
|
|
22751
|
+
if (entity.startsWith("#")) {
|
|
22752
|
+
const code = entity.startsWith("#x") || entity.startsWith("#X") ? Number.parseInt(entity.slice(2), 16) : Number.parseInt(entity.slice(1), 10);
|
|
22753
|
+
return Number.isNaN(code) ? _match : String.fromCodePoint(code);
|
|
22754
|
+
}
|
|
22755
|
+
return namedEntities[entity.toLowerCase()] ?? _match;
|
|
22756
|
+
}
|
|
22757
|
+
function stripHtml2(content) {
|
|
22758
|
+
return content.replace(/<br\s*\/?>/gi, " ").replace(/<\/(?:p|div|li|h[1-6])>/gi, " ").replace(/<[^>]*>/g, "").replace(/&(#[0-9a-f]+|[a-z]+);/gi, decodeEntity).replace(/\s+/g, " ").trim();
|
|
22759
|
+
}
|
|
22760
|
+
|
|
22761
|
+
// src/commands/miro/normaliseItems.ts
|
|
22762
|
+
var frameCoordinates = "parent_top_left";
|
|
22763
|
+
function describe2(item) {
|
|
22764
|
+
return ` ${item.id ?? "(no id)"} (${item.type ?? "unknown type"}): relativeTo=${item.position?.relativeTo ?? "missing"}`;
|
|
22765
|
+
}
|
|
22766
|
+
function coordinateSpaceError(rejected) {
|
|
22767
|
+
return new MiroExtractError(
|
|
22768
|
+
`${rejected.length} item(s) are not in frame coordinates (position.relativeTo must be "${frameCoordinates}"):
|
|
22769
|
+
${rejected.slice(0, 5).map(describe2).join(
|
|
22770
|
+
"\n"
|
|
22771
|
+
)}
|
|
22772
|
+
|
|
22773
|
+
Dump the frame with board_list_items using ?moveToWidget=<frame id> so every item shares one coordinate space.`
|
|
22774
|
+
);
|
|
22775
|
+
}
|
|
22776
|
+
function toItem(item) {
|
|
22777
|
+
const halfWidth = (item.geometry?.width ?? 0) / 2;
|
|
22778
|
+
const halfHeight = (item.geometry?.height ?? 0) / 2;
|
|
22779
|
+
const x = item.position?.x ?? 0;
|
|
22780
|
+
const y = item.position?.y ?? 0;
|
|
22781
|
+
return {
|
|
22782
|
+
id: item.id ?? "",
|
|
22783
|
+
type: item.type ?? "",
|
|
22784
|
+
text: stripHtml2(item.data?.content ?? ""),
|
|
22785
|
+
left: x - halfWidth,
|
|
22786
|
+
top: y - halfHeight,
|
|
22787
|
+
right: x + halfWidth,
|
|
22788
|
+
bottom: y + halfHeight
|
|
22789
|
+
};
|
|
22790
|
+
}
|
|
22791
|
+
function normaliseItems(items2) {
|
|
22792
|
+
const rejected = items2.filter(
|
|
22793
|
+
(item) => item.position?.relativeTo !== frameCoordinates
|
|
22794
|
+
);
|
|
22795
|
+
if (rejected.length > 0) throw coordinateSpaceError(rejected);
|
|
22796
|
+
return items2.map(toItem);
|
|
22797
|
+
}
|
|
22798
|
+
|
|
22799
|
+
// src/commands/miro/parseAnchorId.ts
|
|
22800
|
+
function parseAnchorId(value) {
|
|
22801
|
+
const trimmed = value.trim();
|
|
22802
|
+
const link3 = /[?&]moveToWidget=([^&#]+)/.exec(trimmed);
|
|
22803
|
+
return link3 ? decodeURIComponent(link3[1]).trim() : trimmed;
|
|
22804
|
+
}
|
|
22805
|
+
|
|
22806
|
+
// src/commands/miro/readMiroItems.ts
|
|
22807
|
+
import { readFileSync as readFileSync40 } from "fs";
|
|
22808
|
+
function tryParse(text18) {
|
|
22809
|
+
try {
|
|
22810
|
+
return JSON.parse(text18);
|
|
22811
|
+
} catch {
|
|
22812
|
+
return void 0;
|
|
22813
|
+
}
|
|
22814
|
+
}
|
|
22815
|
+
function toPage(value) {
|
|
22816
|
+
const record = value ?? {};
|
|
22817
|
+
if (Array.isArray(record.data)) return { data: record.data };
|
|
22818
|
+
return record.id ? { data: [record] } : {};
|
|
22819
|
+
}
|
|
22820
|
+
function parseJsonLines(raw, file) {
|
|
22821
|
+
return raw.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
22822
|
+
const parsed = tryParse(line);
|
|
22823
|
+
if (parsed === void 0)
|
|
22824
|
+
throw new MiroExtractError(
|
|
22825
|
+
`${file} is not valid JSON or JSON lines. Save the raw board_list_items response pages without editing them.`
|
|
22826
|
+
);
|
|
22827
|
+
return toPage(parsed);
|
|
22828
|
+
});
|
|
22829
|
+
}
|
|
22830
|
+
function parsePages(raw, file) {
|
|
22831
|
+
const parsed = tryParse(raw);
|
|
22832
|
+
if (parsed === void 0) return parseJsonLines(raw, file);
|
|
22833
|
+
return Array.isArray(parsed) ? parsed.map(toPage) : [toPage(parsed)];
|
|
22834
|
+
}
|
|
22835
|
+
function readMiroItems(file) {
|
|
22836
|
+
const items2 = parsePages(readFileSync40(file, "utf8"), file).flatMap(
|
|
22837
|
+
(page) => page.data ?? []
|
|
22838
|
+
);
|
|
22839
|
+
if (items2.length === 0)
|
|
22840
|
+
throw new MiroExtractError(
|
|
22841
|
+
`No board items found in ${file}. Dump the frame with board_list_items, paging until has_more is false.`
|
|
22842
|
+
);
|
|
22843
|
+
return items2;
|
|
22844
|
+
}
|
|
22845
|
+
|
|
22846
|
+
// src/commands/miro/selectBoxes.ts
|
|
22847
|
+
var boxTypes = /* @__PURE__ */ new Set(["shape", "sticky_note"]);
|
|
22848
|
+
function findAnchor(items2, id) {
|
|
22849
|
+
const anchor = items2.find((item) => item.id === id);
|
|
22850
|
+
if (!anchor)
|
|
22851
|
+
throw new MiroExtractError(
|
|
22852
|
+
`No item with id ${id} in the supplied items. Re-dump the frame so the anchor is included, then try again.`
|
|
22853
|
+
);
|
|
22854
|
+
return anchor;
|
|
22855
|
+
}
|
|
22856
|
+
function isBox(item) {
|
|
22857
|
+
return boxTypes.has(item.type) && item.text.length > 0;
|
|
22858
|
+
}
|
|
22859
|
+
function centreInside(rect, item) {
|
|
22860
|
+
const x = (item.left + item.right) / 2;
|
|
22861
|
+
const y = (item.top + item.bottom) / 2;
|
|
22862
|
+
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
|
|
22863
|
+
}
|
|
22864
|
+
function selectBoxes(items2, topLeftId, bottomRightId) {
|
|
22865
|
+
const topLeft = findAnchor(items2, topLeftId);
|
|
22866
|
+
const bottomRight = findAnchor(items2, bottomRightId);
|
|
22867
|
+
const rect = {
|
|
22868
|
+
left: topLeft.left,
|
|
22869
|
+
top: topLeft.top,
|
|
22870
|
+
right: bottomRight.right,
|
|
22871
|
+
bottom: bottomRight.bottom
|
|
22872
|
+
};
|
|
22873
|
+
return items2.filter((item) => isBox(item) && centreInside(rect, item)).sort((a, b) => a.left - b.left || a.top - b.top);
|
|
22874
|
+
}
|
|
22875
|
+
|
|
22876
|
+
// src/commands/miro/runExtract.ts
|
|
22877
|
+
function requireItems(file) {
|
|
22878
|
+
if (!file)
|
|
22879
|
+
throw new MiroExtractError(
|
|
22880
|
+
"--items <file> is required: a file of raw board_list_items response pages."
|
|
22881
|
+
);
|
|
22882
|
+
return file;
|
|
22883
|
+
}
|
|
22884
|
+
function requireAnchors(options2) {
|
|
22885
|
+
if (!options2.topLeft || !options2.bottomRight)
|
|
22886
|
+
throw new MiroExtractError(
|
|
22887
|
+
"Both --top-left <id|link> and --bottom-right <id|link> are required."
|
|
22888
|
+
);
|
|
22889
|
+
return [parseAnchorId(options2.topLeft), parseAnchorId(options2.bottomRight)];
|
|
22890
|
+
}
|
|
22891
|
+
function runExtract(options2) {
|
|
22892
|
+
const [topLeft, bottomRight] = requireAnchors(options2);
|
|
22893
|
+
const items2 = normaliseItems(readMiroItems(requireItems(options2.items)));
|
|
22894
|
+
const boxes = selectBoxes(items2, topLeft, bottomRight);
|
|
22895
|
+
process.stdout.write(stringify(boxes.map((box) => box.text)));
|
|
22896
|
+
}
|
|
22897
|
+
|
|
22898
|
+
// src/commands/miro/registerMiro.ts
|
|
22899
|
+
function registerMiro(program2) {
|
|
22900
|
+
const miroCommand = program2.command("miro").description("Miro board utilities");
|
|
22901
|
+
miroCommand.command("extract").description("Print the text of every box inside a rectangle on a board").option("--items <file>", "File of raw board_list_items response pages").option(
|
|
22902
|
+
"--top-left <id>",
|
|
22903
|
+
"Widget id or ?moveToWidget=<id> link of the top-left box"
|
|
22904
|
+
).option(
|
|
22905
|
+
"--bottom-right <id>",
|
|
22906
|
+
"Widget id or ?moveToWidget=<id> link of the bottom-right box"
|
|
22907
|
+
).action(runExtract);
|
|
22908
|
+
}
|
|
22909
|
+
|
|
22280
22910
|
// src/commands/netcap/netcap.ts
|
|
22281
22911
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
22282
22912
|
import { createServer as createServer2 } from "http";
|
|
22283
22913
|
import { dirname as dirname28 } from "path";
|
|
22284
|
-
import
|
|
22914
|
+
import chalk170 from "chalk";
|
|
22285
22915
|
|
|
22286
22916
|
// src/commands/netcap/corsHeaders.ts
|
|
22287
22917
|
var corsHeaders = {
|
|
@@ -22360,7 +22990,7 @@ function createNetcapHandler(options2) {
|
|
|
22360
22990
|
import { cp, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
22361
22991
|
import { networkInterfaces } from "os";
|
|
22362
22992
|
import { join as join58 } from "path";
|
|
22363
|
-
import
|
|
22993
|
+
import chalk169 from "chalk";
|
|
22364
22994
|
|
|
22365
22995
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
22366
22996
|
import { dirname as dirname27, join as join57 } from "path";
|
|
@@ -22404,7 +23034,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
22404
23034
|
const host = lanIPv4();
|
|
22405
23035
|
if (!host) {
|
|
22406
23036
|
console.log(
|
|
22407
|
-
|
|
23037
|
+
chalk169.yellow("could not determine the WSL IP for the extension")
|
|
22408
23038
|
);
|
|
22409
23039
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
22410
23040
|
return source;
|
|
@@ -22415,7 +23045,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
22415
23045
|
return WSL_WINDOWS_PATH;
|
|
22416
23046
|
} catch {
|
|
22417
23047
|
console.log(
|
|
22418
|
-
|
|
23048
|
+
chalk169.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
22419
23049
|
);
|
|
22420
23050
|
return source;
|
|
22421
23051
|
}
|
|
@@ -22448,30 +23078,30 @@ async function netcap(options2) {
|
|
|
22448
23078
|
let count8 = 0;
|
|
22449
23079
|
const handler = createNetcapHandler({
|
|
22450
23080
|
outPath,
|
|
22451
|
-
onPing: () => console.log(
|
|
23081
|
+
onPing: () => console.log(chalk170.dim("ping from extension")),
|
|
22452
23082
|
onCapture: (entry) => {
|
|
22453
23083
|
count8 += 1;
|
|
22454
23084
|
console.log(
|
|
22455
|
-
|
|
22456
|
-
|
|
23085
|
+
chalk170.green(`captured #${count8}`),
|
|
23086
|
+
chalk170.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
22457
23087
|
);
|
|
22458
23088
|
}
|
|
22459
23089
|
});
|
|
22460
23090
|
const server = createServer2(handler);
|
|
22461
23091
|
server.listen(port, () => {
|
|
22462
23092
|
console.log(
|
|
22463
|
-
|
|
23093
|
+
chalk170.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
22464
23094
|
);
|
|
22465
|
-
console.log(
|
|
23095
|
+
console.log(chalk170.dim(`appending captures to ${outPath}`));
|
|
22466
23096
|
if (filter)
|
|
22467
|
-
console.log(
|
|
22468
|
-
console.log(
|
|
22469
|
-
console.log(
|
|
23097
|
+
console.log(chalk170.dim(`forwarding only URLs matching "${filter}"`));
|
|
23098
|
+
console.log(chalk170.dim(`load the unpacked extension from ${extensionPath}`));
|
|
23099
|
+
console.log(chalk170.dim("press Ctrl-C to stop"));
|
|
22470
23100
|
});
|
|
22471
23101
|
process.on("SIGINT", () => {
|
|
22472
23102
|
server.close();
|
|
22473
23103
|
console.log(
|
|
22474
|
-
|
|
23104
|
+
chalk170.bold(
|
|
22475
23105
|
`
|
|
22476
23106
|
netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
22477
23107
|
)
|
|
@@ -22483,10 +23113,10 @@ netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} t
|
|
|
22483
23113
|
// src/commands/netcap/netcapExtract.ts
|
|
22484
23114
|
import { writeFileSync as writeFileSync33 } from "fs";
|
|
22485
23115
|
import { join as join61 } from "path";
|
|
22486
|
-
import
|
|
23116
|
+
import chalk171 from "chalk";
|
|
22487
23117
|
|
|
22488
23118
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
22489
|
-
import { readFileSync as
|
|
23119
|
+
import { readFileSync as readFileSync41 } from "fs";
|
|
22490
23120
|
|
|
22491
23121
|
// src/commands/netcap/parseRscRows.ts
|
|
22492
23122
|
var isRscRef = (v) => typeof v === "string" && /^\$[0-9a-fL@]/.test(v);
|
|
@@ -22882,7 +23512,7 @@ function extractVoyagerPosts(body) {
|
|
|
22882
23512
|
|
|
22883
23513
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
22884
23514
|
function captureEntries(captureFile) {
|
|
22885
|
-
const lines2 =
|
|
23515
|
+
const lines2 = readFileSync41(captureFile, "utf8").split("\n").filter(Boolean);
|
|
22886
23516
|
const entries = [];
|
|
22887
23517
|
for (const line of lines2) {
|
|
22888
23518
|
let entry;
|
|
@@ -22931,8 +23561,8 @@ function netcapExtract(file) {
|
|
|
22931
23561
|
writeFileSync33(outFile, `${JSON.stringify(posts, null, 2)}
|
|
22932
23562
|
`);
|
|
22933
23563
|
console.log(
|
|
22934
|
-
|
|
22935
|
-
|
|
23564
|
+
chalk171.green(`extracted ${posts.length} posts`),
|
|
23565
|
+
chalk171.dim(`-> ${outFile}`)
|
|
22936
23566
|
);
|
|
22937
23567
|
}
|
|
22938
23568
|
|
|
@@ -22953,7 +23583,7 @@ function registerNetcap(program2) {
|
|
|
22953
23583
|
}
|
|
22954
23584
|
|
|
22955
23585
|
// src/commands/news/add/index.ts
|
|
22956
|
-
import
|
|
23586
|
+
import chalk172 from "chalk";
|
|
22957
23587
|
import enquirer8 from "enquirer";
|
|
22958
23588
|
async function add2(url) {
|
|
22959
23589
|
if (!url) {
|
|
@@ -22975,10 +23605,10 @@ async function add2(url) {
|
|
|
22975
23605
|
const { orm } = await getReady();
|
|
22976
23606
|
const added = await addFeed(orm, url);
|
|
22977
23607
|
if (!added) {
|
|
22978
|
-
console.log(
|
|
23608
|
+
console.log(chalk172.yellow("Feed already exists"));
|
|
22979
23609
|
return;
|
|
22980
23610
|
}
|
|
22981
|
-
console.log(
|
|
23611
|
+
console.log(chalk172.green(`Added feed: ${url}`));
|
|
22982
23612
|
}
|
|
22983
23613
|
|
|
22984
23614
|
// src/commands/registerNews.ts
|
|
@@ -23025,7 +23655,7 @@ function registerPiHook(program2) {
|
|
|
23025
23655
|
}
|
|
23026
23656
|
|
|
23027
23657
|
// src/commands/prompts/printPromptsTable.ts
|
|
23028
|
-
import
|
|
23658
|
+
import chalk173 from "chalk";
|
|
23029
23659
|
function truncate(str, max) {
|
|
23030
23660
|
if (str.length <= max) return str;
|
|
23031
23661
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -23043,14 +23673,14 @@ function printPromptsTable(rows) {
|
|
|
23043
23673
|
"Command".padEnd(commandWidth),
|
|
23044
23674
|
"Repos"
|
|
23045
23675
|
].join(" ");
|
|
23046
|
-
console.log(
|
|
23047
|
-
console.log(
|
|
23676
|
+
console.log(chalk173.dim(header));
|
|
23677
|
+
console.log(chalk173.dim("-".repeat(header.length)));
|
|
23048
23678
|
for (const row of rows) {
|
|
23049
23679
|
const count8 = String(row.count).padStart(countWidth);
|
|
23050
23680
|
const tool = row.tool.padEnd(toolWidth);
|
|
23051
23681
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
23052
23682
|
console.log(
|
|
23053
|
-
`${
|
|
23683
|
+
`${chalk173.yellow(count8)} ${tool} ${command} ${chalk173.dim(row.repos)}`
|
|
23054
23684
|
);
|
|
23055
23685
|
}
|
|
23056
23686
|
}
|
|
@@ -23456,7 +24086,7 @@ import { tmpdir as tmpdir6 } from "os";
|
|
|
23456
24086
|
import { join as join63 } from "path";
|
|
23457
24087
|
|
|
23458
24088
|
// src/commands/prs/loadCommentsCache.ts
|
|
23459
|
-
import { existsSync as
|
|
24089
|
+
import { existsSync as existsSync54, readFileSync as readFileSync42, unlinkSync as unlinkSync13 } from "fs";
|
|
23460
24090
|
import { parse as parse2 } from "yaml";
|
|
23461
24091
|
|
|
23462
24092
|
// src/commands/prs/commentsCachePath.ts
|
|
@@ -23476,24 +24106,24 @@ function commentsCachePath(org, repo, prNumber) {
|
|
|
23476
24106
|
// src/commands/prs/loadCommentsCache.ts
|
|
23477
24107
|
function loadCommentsCache(org, repo, prNumber) {
|
|
23478
24108
|
const cachePath = commentsCachePath(org, repo, prNumber);
|
|
23479
|
-
if (!
|
|
24109
|
+
if (!existsSync54(cachePath)) {
|
|
23480
24110
|
return null;
|
|
23481
24111
|
}
|
|
23482
|
-
const content =
|
|
24112
|
+
const content = readFileSync42(cachePath, "utf8");
|
|
23483
24113
|
return parse2(content);
|
|
23484
24114
|
}
|
|
23485
24115
|
function deleteCommentsCache(org, repo, prNumber) {
|
|
23486
24116
|
const cachePath = commentsCachePath(org, repo, prNumber);
|
|
23487
|
-
if (
|
|
24117
|
+
if (existsSync54(cachePath)) {
|
|
23488
24118
|
unlinkSync13(cachePath);
|
|
23489
24119
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
23490
24120
|
}
|
|
23491
24121
|
}
|
|
23492
24122
|
|
|
23493
24123
|
// src/commands/prs/replyToComment.ts
|
|
23494
|
-
import { spawnSync as
|
|
24124
|
+
import { spawnSync as spawnSync6 } from "child_process";
|
|
23495
24125
|
function replyToComment(org, repo, prNumber, commentId, message3) {
|
|
23496
|
-
const result =
|
|
24126
|
+
const result = spawnSync6(
|
|
23497
24127
|
"gh",
|
|
23498
24128
|
[
|
|
23499
24129
|
"api",
|
|
@@ -23671,7 +24301,7 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
23671
24301
|
// src/commands/prs/listComments/updateCommentsCache.ts
|
|
23672
24302
|
import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync36 } from "fs";
|
|
23673
24303
|
import { dirname as dirname29 } from "path";
|
|
23674
|
-
import { stringify } from "yaml";
|
|
24304
|
+
import { stringify as stringify2 } from "yaml";
|
|
23675
24305
|
|
|
23676
24306
|
// src/commands/prs/removeStaleCommentsCaches.ts
|
|
23677
24307
|
import { readdirSync as readdirSync12, unlinkSync as unlinkSync16 } from "fs";
|
|
@@ -23699,7 +24329,7 @@ function writeCommentsCache(org, repo, prNumber, comments3) {
|
|
|
23699
24329
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23700
24330
|
comments: comments3
|
|
23701
24331
|
};
|
|
23702
|
-
writeFileSync36(cachePath,
|
|
24332
|
+
writeFileSync36(cachePath, stringify2(cacheData));
|
|
23703
24333
|
}
|
|
23704
24334
|
function updateCommentsCache(org, repo, prNumber, comments3) {
|
|
23705
24335
|
removeStaleCommentsCaches();
|
|
@@ -23717,13 +24347,13 @@ function agentFooter(unresolvedCount) {
|
|
|
23717
24347
|
}
|
|
23718
24348
|
|
|
23719
24349
|
// src/commands/prs/listComments/commentStyle.ts
|
|
23720
|
-
import
|
|
24350
|
+
import chalk174 from "chalk";
|
|
23721
24351
|
var plain = (text18) => text18;
|
|
23722
24352
|
function colouredState(state) {
|
|
23723
24353
|
const label2 = `[${state}]`;
|
|
23724
|
-
if (state === "APPROVED") return
|
|
23725
|
-
if (state === "CHANGES_REQUESTED") return
|
|
23726
|
-
return
|
|
24354
|
+
if (state === "APPROVED") return chalk174.green(label2);
|
|
24355
|
+
if (state === "CHANGES_REQUESTED") return chalk174.red(label2);
|
|
24356
|
+
return chalk174.yellow(label2);
|
|
23727
24357
|
}
|
|
23728
24358
|
function commentStyle() {
|
|
23729
24359
|
if (isClaudeCode()) {
|
|
@@ -23737,9 +24367,9 @@ function commentStyle() {
|
|
|
23737
24367
|
};
|
|
23738
24368
|
}
|
|
23739
24369
|
return {
|
|
23740
|
-
cyan:
|
|
23741
|
-
bold:
|
|
23742
|
-
dim:
|
|
24370
|
+
cyan: chalk174.cyan,
|
|
24371
|
+
bold: chalk174.bold,
|
|
24372
|
+
dim: chalk174.dim,
|
|
23743
24373
|
state: colouredState,
|
|
23744
24374
|
diffHunk: true,
|
|
23745
24375
|
agent: false
|
|
@@ -23909,13 +24539,13 @@ import { execSync as execSync48 } from "child_process";
|
|
|
23909
24539
|
import enquirer9 from "enquirer";
|
|
23910
24540
|
|
|
23911
24541
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
23912
|
-
import
|
|
24542
|
+
import chalk175 from "chalk";
|
|
23913
24543
|
var STATUS_MAP = {
|
|
23914
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
23915
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
24544
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk175.magenta("merged"), date: pr.mergedAt } : null,
|
|
24545
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk175.red("closed"), date: pr.closedAt } : null
|
|
23916
24546
|
};
|
|
23917
24547
|
function defaultStatus(pr) {
|
|
23918
|
-
return { label:
|
|
24548
|
+
return { label: chalk175.green("opened"), date: pr.createdAt };
|
|
23919
24549
|
}
|
|
23920
24550
|
function getStatus2(pr) {
|
|
23921
24551
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -23924,11 +24554,11 @@ function formatDate(dateStr) {
|
|
|
23924
24554
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
23925
24555
|
}
|
|
23926
24556
|
function formatPrHeader(pr, status3) {
|
|
23927
|
-
return `${
|
|
24557
|
+
return `${chalk175.cyan(`#${pr.number}`)} ${pr.title} ${chalk175.dim(`(${pr.author.login},`)} ${status3.label} ${chalk175.dim(`${formatDate(status3.date)})`)}`;
|
|
23928
24558
|
}
|
|
23929
24559
|
function logPrDetails(pr) {
|
|
23930
24560
|
console.log(
|
|
23931
|
-
|
|
24561
|
+
chalk175.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
23932
24562
|
);
|
|
23933
24563
|
console.log();
|
|
23934
24564
|
}
|
|
@@ -24643,10 +25273,10 @@ function registerPrs(program2) {
|
|
|
24643
25273
|
}
|
|
24644
25274
|
|
|
24645
25275
|
// src/commands/ravendb/ravendbAuth.ts
|
|
24646
|
-
import
|
|
25276
|
+
import chalk181 from "chalk";
|
|
24647
25277
|
|
|
24648
25278
|
// src/shared/createConnectionAuth.ts
|
|
24649
|
-
import
|
|
25279
|
+
import chalk176 from "chalk";
|
|
24650
25280
|
function listConnections(connections, format) {
|
|
24651
25281
|
if (connections.length === 0) {
|
|
24652
25282
|
console.log("No connections configured.");
|
|
@@ -24659,7 +25289,7 @@ function listConnections(connections, format) {
|
|
|
24659
25289
|
function removeConnection(connections, name, save) {
|
|
24660
25290
|
const filtered = connections.filter((c) => c.name !== name);
|
|
24661
25291
|
if (filtered.length === connections.length) {
|
|
24662
|
-
console.error(
|
|
25292
|
+
console.error(chalk176.red(`Connection "${name}" not found.`));
|
|
24663
25293
|
process.exit(1);
|
|
24664
25294
|
}
|
|
24665
25295
|
save(filtered);
|
|
@@ -24705,15 +25335,15 @@ function saveConnections(connections) {
|
|
|
24705
25335
|
}
|
|
24706
25336
|
|
|
24707
25337
|
// src/commands/ravendb/promptConnection.ts
|
|
24708
|
-
import
|
|
25338
|
+
import chalk179 from "chalk";
|
|
24709
25339
|
|
|
24710
25340
|
// src/commands/ravendb/selectOpSecret.ts
|
|
24711
|
-
import
|
|
25341
|
+
import chalk178 from "chalk";
|
|
24712
25342
|
import Enquirer2 from "enquirer";
|
|
24713
25343
|
|
|
24714
25344
|
// src/commands/ravendb/searchItems.ts
|
|
24715
25345
|
import { execSync as execSync51 } from "child_process";
|
|
24716
|
-
import
|
|
25346
|
+
import chalk177 from "chalk";
|
|
24717
25347
|
function opExec(args) {
|
|
24718
25348
|
return execSync51(`op ${args}`, {
|
|
24719
25349
|
encoding: "utf8",
|
|
@@ -24726,7 +25356,7 @@ function searchItems(search2) {
|
|
|
24726
25356
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
24727
25357
|
} catch {
|
|
24728
25358
|
console.error(
|
|
24729
|
-
|
|
25359
|
+
chalk177.red(
|
|
24730
25360
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
24731
25361
|
)
|
|
24732
25362
|
);
|
|
@@ -24740,7 +25370,7 @@ function getItemFields(itemId2) {
|
|
|
24740
25370
|
const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
|
|
24741
25371
|
return item.fields.filter((f) => f.reference && f.label);
|
|
24742
25372
|
} catch {
|
|
24743
|
-
console.error(
|
|
25373
|
+
console.error(chalk177.red("Failed to get item details from 1Password."));
|
|
24744
25374
|
process.exit(1);
|
|
24745
25375
|
}
|
|
24746
25376
|
}
|
|
@@ -24759,7 +25389,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
24759
25389
|
}).run();
|
|
24760
25390
|
const items2 = searchItems(search2);
|
|
24761
25391
|
if (items2.length === 0) {
|
|
24762
|
-
console.error(
|
|
25392
|
+
console.error(chalk178.red(`No items found matching "${search2}".`));
|
|
24763
25393
|
process.exit(1);
|
|
24764
25394
|
}
|
|
24765
25395
|
const itemId2 = await selectOne(
|
|
@@ -24768,7 +25398,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
24768
25398
|
);
|
|
24769
25399
|
const fields = getItemFields(itemId2);
|
|
24770
25400
|
if (fields.length === 0) {
|
|
24771
|
-
console.error(
|
|
25401
|
+
console.error(chalk178.red("No fields with references found on this item."));
|
|
24772
25402
|
process.exit(1);
|
|
24773
25403
|
}
|
|
24774
25404
|
const ref = await selectOne(
|
|
@@ -24782,7 +25412,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
24782
25412
|
async function promptConnection(existingNames) {
|
|
24783
25413
|
const name = await promptInput("name", "Connection name:");
|
|
24784
25414
|
if (existingNames.includes(name)) {
|
|
24785
|
-
console.error(
|
|
25415
|
+
console.error(chalk179.red(`Connection "${name}" already exists.`));
|
|
24786
25416
|
process.exit(1);
|
|
24787
25417
|
}
|
|
24788
25418
|
const url = await promptInput(
|
|
@@ -24791,22 +25421,22 @@ async function promptConnection(existingNames) {
|
|
|
24791
25421
|
);
|
|
24792
25422
|
const database = await promptInput("database", "Database name:");
|
|
24793
25423
|
if (!name || !url || !database) {
|
|
24794
|
-
console.error(
|
|
25424
|
+
console.error(chalk179.red("All fields are required."));
|
|
24795
25425
|
process.exit(1);
|
|
24796
25426
|
}
|
|
24797
25427
|
const apiKeyRef = await selectOpSecret();
|
|
24798
|
-
console.log(
|
|
25428
|
+
console.log(chalk179.dim(`Using: ${apiKeyRef}`));
|
|
24799
25429
|
return { name, url, database, apiKeyRef };
|
|
24800
25430
|
}
|
|
24801
25431
|
|
|
24802
25432
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
24803
|
-
import
|
|
25433
|
+
import chalk180 from "chalk";
|
|
24804
25434
|
function ravendbSetConnection(name) {
|
|
24805
25435
|
const raw = loadGlobalConfigRaw();
|
|
24806
25436
|
const ravendb = raw.ravendb ?? {};
|
|
24807
25437
|
const connections = ravendb.connections ?? [];
|
|
24808
25438
|
if (!connections.some((c) => c.name === name)) {
|
|
24809
|
-
console.error(
|
|
25439
|
+
console.error(chalk180.red(`Connection "${name}" not found.`));
|
|
24810
25440
|
console.error(
|
|
24811
25441
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
24812
25442
|
);
|
|
@@ -24822,16 +25452,16 @@ function ravendbSetConnection(name) {
|
|
|
24822
25452
|
var ravendbAuth = createConnectionAuth({
|
|
24823
25453
|
load: loadConnections,
|
|
24824
25454
|
save: saveConnections,
|
|
24825
|
-
format: (c) => `${
|
|
25455
|
+
format: (c) => `${chalk181.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
24826
25456
|
promptNew: promptConnection,
|
|
24827
25457
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
24828
25458
|
});
|
|
24829
25459
|
|
|
24830
25460
|
// src/commands/ravendb/ravendbCollections.ts
|
|
24831
|
-
import
|
|
25461
|
+
import chalk185 from "chalk";
|
|
24832
25462
|
|
|
24833
25463
|
// src/commands/ravendb/ravenFetch.ts
|
|
24834
|
-
import
|
|
25464
|
+
import chalk183 from "chalk";
|
|
24835
25465
|
|
|
24836
25466
|
// src/commands/ravendb/getAccessToken.ts
|
|
24837
25467
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -24868,10 +25498,10 @@ ${errorText}`
|
|
|
24868
25498
|
|
|
24869
25499
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
24870
25500
|
import { execSync as execSync52 } from "child_process";
|
|
24871
|
-
import
|
|
25501
|
+
import chalk182 from "chalk";
|
|
24872
25502
|
function resolveOpSecret(reference) {
|
|
24873
25503
|
if (!reference.startsWith("op://")) {
|
|
24874
|
-
console.error(
|
|
25504
|
+
console.error(chalk182.red(`Invalid secret reference: must start with op://`));
|
|
24875
25505
|
process.exit(1);
|
|
24876
25506
|
}
|
|
24877
25507
|
try {
|
|
@@ -24881,7 +25511,7 @@ function resolveOpSecret(reference) {
|
|
|
24881
25511
|
}).trim();
|
|
24882
25512
|
} catch {
|
|
24883
25513
|
console.error(
|
|
24884
|
-
|
|
25514
|
+
chalk182.red(
|
|
24885
25515
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
24886
25516
|
)
|
|
24887
25517
|
);
|
|
@@ -24908,7 +25538,7 @@ async function ravenFetch(connection, path80) {
|
|
|
24908
25538
|
if (!response.ok) {
|
|
24909
25539
|
const body = await response.text();
|
|
24910
25540
|
console.error(
|
|
24911
|
-
|
|
25541
|
+
chalk183.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
24912
25542
|
);
|
|
24913
25543
|
console.error(body.substring(0, 500));
|
|
24914
25544
|
process.exit(1);
|
|
@@ -24917,7 +25547,7 @@ async function ravenFetch(connection, path80) {
|
|
|
24917
25547
|
}
|
|
24918
25548
|
|
|
24919
25549
|
// src/commands/ravendb/resolveConnection.ts
|
|
24920
|
-
import
|
|
25550
|
+
import chalk184 from "chalk";
|
|
24921
25551
|
function loadRavendb() {
|
|
24922
25552
|
const raw = loadGlobalConfigRaw();
|
|
24923
25553
|
const ravendb = raw.ravendb;
|
|
@@ -24931,7 +25561,7 @@ function resolveConnection(name) {
|
|
|
24931
25561
|
const connectionName = name ?? defaultConnection;
|
|
24932
25562
|
if (!connectionName) {
|
|
24933
25563
|
console.error(
|
|
24934
|
-
|
|
25564
|
+
chalk184.red(
|
|
24935
25565
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
24936
25566
|
)
|
|
24937
25567
|
);
|
|
@@ -24939,7 +25569,7 @@ function resolveConnection(name) {
|
|
|
24939
25569
|
}
|
|
24940
25570
|
const connection = connections.find((c) => c.name === connectionName);
|
|
24941
25571
|
if (!connection) {
|
|
24942
|
-
console.error(
|
|
25572
|
+
console.error(chalk184.red(`Connection "${connectionName}" not found.`));
|
|
24943
25573
|
console.error(
|
|
24944
25574
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
24945
25575
|
);
|
|
@@ -24970,15 +25600,15 @@ async function ravendbCollections(connectionName) {
|
|
|
24970
25600
|
return;
|
|
24971
25601
|
}
|
|
24972
25602
|
for (const c of collections) {
|
|
24973
|
-
console.log(`${
|
|
25603
|
+
console.log(`${chalk185.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
24974
25604
|
}
|
|
24975
25605
|
}
|
|
24976
25606
|
|
|
24977
25607
|
// src/commands/ravendb/ravendbQuery.ts
|
|
24978
|
-
import
|
|
25608
|
+
import chalk187 from "chalk";
|
|
24979
25609
|
|
|
24980
25610
|
// src/commands/ravendb/fetchAllPages.ts
|
|
24981
|
-
import
|
|
25611
|
+
import chalk186 from "chalk";
|
|
24982
25612
|
|
|
24983
25613
|
// src/commands/ravendb/buildQueryPath.ts
|
|
24984
25614
|
function buildQueryPath(opts) {
|
|
@@ -25016,7 +25646,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25016
25646
|
allResults.push(...results);
|
|
25017
25647
|
start3 += results.length;
|
|
25018
25648
|
process.stderr.write(
|
|
25019
|
-
`\r${
|
|
25649
|
+
`\r${chalk186.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
25020
25650
|
);
|
|
25021
25651
|
if (start3 >= totalResults) break;
|
|
25022
25652
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -25031,7 +25661,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
25031
25661
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
25032
25662
|
const resolved = resolveArgs(connectionName, collection);
|
|
25033
25663
|
if (!resolved.collection && !options2.query) {
|
|
25034
|
-
console.error(
|
|
25664
|
+
console.error(chalk187.red("Provide a collection name or --query filter."));
|
|
25035
25665
|
process.exit(1);
|
|
25036
25666
|
}
|
|
25037
25667
|
const { collection: col } = resolved;
|
|
@@ -25070,7 +25700,7 @@ import { spawn as spawn6 } from "child_process";
|
|
|
25070
25700
|
import * as path42 from "path";
|
|
25071
25701
|
|
|
25072
25702
|
// src/commands/refactor/logViolations.ts
|
|
25073
|
-
import
|
|
25703
|
+
import chalk188 from "chalk";
|
|
25074
25704
|
var DEFAULT_MAX_LINES2 = 100;
|
|
25075
25705
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
25076
25706
|
if (violations.length === 0) {
|
|
@@ -25079,43 +25709,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES2) {
|
|
|
25079
25709
|
}
|
|
25080
25710
|
return;
|
|
25081
25711
|
}
|
|
25082
|
-
console.error(
|
|
25712
|
+
console.error(chalk188.red(`
|
|
25083
25713
|
Refactor check failed:
|
|
25084
25714
|
`));
|
|
25085
|
-
console.error(
|
|
25715
|
+
console.error(chalk188.red(` The following files exceed ${maxLines} lines:
|
|
25086
25716
|
`));
|
|
25087
25717
|
for (const violation of violations) {
|
|
25088
|
-
console.error(
|
|
25718
|
+
console.error(chalk188.red(` ${violation.file} (${violation.lines} lines)`));
|
|
25089
25719
|
}
|
|
25090
25720
|
console.error(
|
|
25091
|
-
|
|
25721
|
+
chalk188.yellow(
|
|
25092
25722
|
`
|
|
25093
25723
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
25094
25724
|
way to refactor it, ignore it with:
|
|
25095
25725
|
`
|
|
25096
25726
|
)
|
|
25097
25727
|
);
|
|
25098
|
-
console.error(
|
|
25728
|
+
console.error(chalk188.gray(` assist refactor ignore <file>
|
|
25099
25729
|
`));
|
|
25100
25730
|
if (process.env.CLAUDECODE) {
|
|
25101
|
-
console.error(
|
|
25731
|
+
console.error(chalk188.cyan(`
|
|
25102
25732
|
## Extracting Code to New Files
|
|
25103
25733
|
`));
|
|
25104
25734
|
console.error(
|
|
25105
|
-
|
|
25735
|
+
chalk188.cyan(
|
|
25106
25736
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
25107
25737
|
`
|
|
25108
25738
|
)
|
|
25109
25739
|
);
|
|
25110
25740
|
console.error(
|
|
25111
|
-
|
|
25741
|
+
chalk188.cyan(
|
|
25112
25742
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
25113
25743
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
25114
25744
|
`
|
|
25115
25745
|
)
|
|
25116
25746
|
);
|
|
25117
25747
|
console.error(
|
|
25118
|
-
|
|
25748
|
+
chalk188.cyan(
|
|
25119
25749
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
25120
25750
|
domains, move it to a common/shared folder.
|
|
25121
25751
|
`
|
|
@@ -25271,7 +25901,7 @@ async function check(pattern2, options2) {
|
|
|
25271
25901
|
|
|
25272
25902
|
// src/commands/refactor/extract/index.ts
|
|
25273
25903
|
import path50 from "path";
|
|
25274
|
-
import
|
|
25904
|
+
import chalk191 from "chalk";
|
|
25275
25905
|
|
|
25276
25906
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
25277
25907
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -25870,23 +26500,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
25870
26500
|
|
|
25871
26501
|
// src/commands/refactor/extract/displayPlan.ts
|
|
25872
26502
|
import path46 from "path";
|
|
25873
|
-
import
|
|
26503
|
+
import chalk189 from "chalk";
|
|
25874
26504
|
function section2(title) {
|
|
25875
26505
|
return `
|
|
25876
|
-
${
|
|
26506
|
+
${chalk189.cyan(title)}`;
|
|
25877
26507
|
}
|
|
25878
26508
|
function displayImporters(plan2, cwd) {
|
|
25879
26509
|
if (plan2.importersToUpdate.length === 0) return;
|
|
25880
26510
|
console.log(section2("Update importers:"));
|
|
25881
26511
|
for (const imp of plan2.importersToUpdate) {
|
|
25882
26512
|
const rel = path46.relative(cwd, imp.file.getFilePath());
|
|
25883
|
-
console.log(` ${
|
|
26513
|
+
console.log(` ${chalk189.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
25884
26514
|
}
|
|
25885
26515
|
}
|
|
25886
26516
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
25887
|
-
console.log(
|
|
26517
|
+
console.log(chalk189.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
25888
26518
|
`));
|
|
25889
|
-
console.log(` ${
|
|
26519
|
+
console.log(` ${chalk189.cyan("Functions to move:")}`);
|
|
25890
26520
|
for (const name of plan2.extractedNames) {
|
|
25891
26521
|
console.log(` ${name}`);
|
|
25892
26522
|
}
|
|
@@ -25920,7 +26550,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
25920
26550
|
|
|
25921
26551
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
25922
26552
|
import path49 from "path";
|
|
25923
|
-
import
|
|
26553
|
+
import chalk190 from "chalk";
|
|
25924
26554
|
import { Project as Project4 } from "ts-morph";
|
|
25925
26555
|
|
|
25926
26556
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -26012,7 +26642,7 @@ function loadProjectFile(file) {
|
|
|
26012
26642
|
});
|
|
26013
26643
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
26014
26644
|
if (!sourceFile) {
|
|
26015
|
-
console.log(
|
|
26645
|
+
console.log(chalk190.red(`File not found in project: ${file}`));
|
|
26016
26646
|
process.exit(1);
|
|
26017
26647
|
}
|
|
26018
26648
|
return { project, sourceFile };
|
|
@@ -26035,19 +26665,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
26035
26665
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
26036
26666
|
if (options2.apply) {
|
|
26037
26667
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
26038
|
-
console.log(
|
|
26668
|
+
console.log(chalk191.green("\nExtraction complete"));
|
|
26039
26669
|
} else {
|
|
26040
|
-
console.log(
|
|
26670
|
+
console.log(chalk191.dim("\nDry run. Use --apply to execute."));
|
|
26041
26671
|
}
|
|
26042
26672
|
}
|
|
26043
26673
|
|
|
26044
26674
|
// src/commands/refactor/ignore.ts
|
|
26045
26675
|
import fs33 from "fs";
|
|
26046
|
-
import
|
|
26676
|
+
import chalk192 from "chalk";
|
|
26047
26677
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
26048
26678
|
function ignore2(file) {
|
|
26049
26679
|
if (!fs33.existsSync(file)) {
|
|
26050
|
-
console.error(
|
|
26680
|
+
console.error(chalk192.red(`Error: File does not exist: ${file}`));
|
|
26051
26681
|
process.exit(1);
|
|
26052
26682
|
}
|
|
26053
26683
|
const content = fs33.readFileSync(file, "utf8");
|
|
@@ -26063,7 +26693,7 @@ function ignore2(file) {
|
|
|
26063
26693
|
fs33.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
26064
26694
|
}
|
|
26065
26695
|
console.log(
|
|
26066
|
-
|
|
26696
|
+
chalk192.green(
|
|
26067
26697
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
26068
26698
|
)
|
|
26069
26699
|
);
|
|
@@ -26072,12 +26702,12 @@ function ignore2(file) {
|
|
|
26072
26702
|
// src/commands/refactor/rename/index.ts
|
|
26073
26703
|
import fs36 from "fs";
|
|
26074
26704
|
import path55 from "path";
|
|
26075
|
-
import
|
|
26705
|
+
import chalk195 from "chalk";
|
|
26076
26706
|
|
|
26077
26707
|
// src/commands/refactor/rename/applyRename.ts
|
|
26078
26708
|
import fs35 from "fs";
|
|
26079
26709
|
import path52 from "path";
|
|
26080
|
-
import
|
|
26710
|
+
import chalk193 from "chalk";
|
|
26081
26711
|
|
|
26082
26712
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
26083
26713
|
import path51 from "path";
|
|
@@ -26182,13 +26812,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
26182
26812
|
const updatedContents = applyRewrites(rewrites);
|
|
26183
26813
|
for (const [file, content] of updatedContents) {
|
|
26184
26814
|
fs35.writeFileSync(file, content, "utf8");
|
|
26185
|
-
console.log(
|
|
26815
|
+
console.log(chalk193.cyan(` Updated imports in ${path52.relative(cwd, file)}`));
|
|
26186
26816
|
}
|
|
26187
26817
|
const destDir = path52.dirname(destPath);
|
|
26188
26818
|
if (!fs35.existsSync(destDir)) fs35.mkdirSync(destDir, { recursive: true });
|
|
26189
26819
|
fs35.renameSync(sourcePath, destPath);
|
|
26190
26820
|
console.log(
|
|
26191
|
-
|
|
26821
|
+
chalk193.white(
|
|
26192
26822
|
` Moved ${path52.relative(cwd, sourcePath)} \u2192 ${path52.relative(cwd, destPath)}`
|
|
26193
26823
|
)
|
|
26194
26824
|
);
|
|
@@ -26275,16 +26905,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
26275
26905
|
|
|
26276
26906
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
26277
26907
|
import path54 from "path";
|
|
26278
|
-
import
|
|
26908
|
+
import chalk194 from "chalk";
|
|
26279
26909
|
function printRenamePreview(rewrites, cwd) {
|
|
26280
26910
|
for (const rewrite of rewrites) {
|
|
26281
26911
|
console.log(
|
|
26282
|
-
|
|
26912
|
+
chalk194.dim(
|
|
26283
26913
|
` ${path54.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
26284
26914
|
)
|
|
26285
26915
|
);
|
|
26286
26916
|
}
|
|
26287
|
-
console.log(
|
|
26917
|
+
console.log(chalk194.dim("Dry run. Use --apply to execute."));
|
|
26288
26918
|
}
|
|
26289
26919
|
|
|
26290
26920
|
// src/commands/refactor/rename/index.ts
|
|
@@ -26295,20 +26925,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26295
26925
|
const relSource = path55.relative(cwd, sourcePath);
|
|
26296
26926
|
const relDest = path55.relative(cwd, destPath);
|
|
26297
26927
|
if (!fs36.existsSync(sourcePath)) {
|
|
26298
|
-
console.log(
|
|
26928
|
+
console.log(chalk195.red(`File not found: ${source}`));
|
|
26299
26929
|
process.exit(1);
|
|
26300
26930
|
}
|
|
26301
26931
|
if (destPath !== sourcePath && fs36.existsSync(destPath)) {
|
|
26302
|
-
console.log(
|
|
26932
|
+
console.log(chalk195.red(`Destination already exists: ${destination}`));
|
|
26303
26933
|
process.exit(1);
|
|
26304
26934
|
}
|
|
26305
|
-
console.log(
|
|
26306
|
-
console.log(
|
|
26307
|
-
console.log(
|
|
26935
|
+
console.log(chalk195.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
26936
|
+
console.log(chalk195.dim("Loading project..."));
|
|
26937
|
+
console.log(chalk195.dim("Scanning imports across the project..."));
|
|
26308
26938
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
26309
26939
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
26310
26940
|
console.log(
|
|
26311
|
-
|
|
26941
|
+
chalk195.dim(
|
|
26312
26942
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
26313
26943
|
)
|
|
26314
26944
|
);
|
|
@@ -26317,11 +26947,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
26317
26947
|
return;
|
|
26318
26948
|
}
|
|
26319
26949
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
26320
|
-
console.log(
|
|
26950
|
+
console.log(chalk195.green("Done"));
|
|
26321
26951
|
}
|
|
26322
26952
|
|
|
26323
26953
|
// src/commands/refactor/renameSymbol/index.ts
|
|
26324
|
-
import
|
|
26954
|
+
import chalk196 from "chalk";
|
|
26325
26955
|
|
|
26326
26956
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
26327
26957
|
import { SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
@@ -26367,33 +26997,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
26367
26997
|
const { project, sourceFile } = loadProjectFile(file);
|
|
26368
26998
|
const symbol = findSymbol(sourceFile, oldName);
|
|
26369
26999
|
if (!symbol) {
|
|
26370
|
-
console.log(
|
|
27000
|
+
console.log(chalk196.red(`Symbol "${oldName}" not found in ${file}`));
|
|
26371
27001
|
process.exit(1);
|
|
26372
27002
|
}
|
|
26373
27003
|
const grouped = groupReferences(symbol, cwd);
|
|
26374
27004
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
26375
27005
|
console.log(
|
|
26376
|
-
|
|
27006
|
+
chalk196.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
26377
27007
|
`)
|
|
26378
27008
|
);
|
|
26379
27009
|
for (const [refFile, lines2] of grouped) {
|
|
26380
27010
|
console.log(
|
|
26381
|
-
` ${
|
|
27011
|
+
` ${chalk196.dim(refFile)}: lines ${chalk196.cyan(lines2.join(", "))}`
|
|
26382
27012
|
);
|
|
26383
27013
|
}
|
|
26384
27014
|
if (options2.apply) {
|
|
26385
27015
|
symbol.rename(newName);
|
|
26386
27016
|
await project.save();
|
|
26387
|
-
console.log(
|
|
27017
|
+
console.log(chalk196.green(`
|
|
26388
27018
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
26389
27019
|
} else {
|
|
26390
|
-
console.log(
|
|
27020
|
+
console.log(chalk196.dim("\nDry run. Use --apply to execute."));
|
|
26391
27021
|
}
|
|
26392
27022
|
}
|
|
26393
27023
|
|
|
26394
27024
|
// src/commands/refactor/restructure/index.ts
|
|
26395
27025
|
import path63 from "path";
|
|
26396
|
-
import
|
|
27026
|
+
import chalk199 from "chalk";
|
|
26397
27027
|
|
|
26398
27028
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
26399
27029
|
import path57 from "path";
|
|
@@ -26472,50 +27102,50 @@ function clusterFiles(graph) {
|
|
|
26472
27102
|
|
|
26473
27103
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
26474
27104
|
import path59 from "path";
|
|
26475
|
-
import
|
|
27105
|
+
import chalk197 from "chalk";
|
|
26476
27106
|
function relPath(filePath) {
|
|
26477
27107
|
return path59.relative(process.cwd(), filePath);
|
|
26478
27108
|
}
|
|
26479
27109
|
function displayMoves(plan2) {
|
|
26480
27110
|
if (plan2.moves.length === 0) return;
|
|
26481
|
-
console.log(
|
|
27111
|
+
console.log(chalk197.bold("\nFile moves:"));
|
|
26482
27112
|
for (const move2 of plan2.moves) {
|
|
26483
27113
|
console.log(
|
|
26484
|
-
` ${
|
|
27114
|
+
` ${chalk197.red(relPath(move2.from))} \u2192 ${chalk197.green(relPath(move2.to))}`
|
|
26485
27115
|
);
|
|
26486
|
-
console.log(
|
|
27116
|
+
console.log(chalk197.dim(` ${move2.reason}`));
|
|
26487
27117
|
}
|
|
26488
27118
|
}
|
|
26489
27119
|
function displayRewrites(rewrites) {
|
|
26490
27120
|
if (rewrites.length === 0) return;
|
|
26491
27121
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
26492
|
-
console.log(
|
|
27122
|
+
console.log(chalk197.bold(`
|
|
26493
27123
|
Import rewrites (${affectedFiles.size} files):`));
|
|
26494
27124
|
for (const file of affectedFiles) {
|
|
26495
|
-
console.log(` ${
|
|
27125
|
+
console.log(` ${chalk197.cyan(relPath(file))}:`);
|
|
26496
27126
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
26497
27127
|
(r) => r.file === file
|
|
26498
27128
|
)) {
|
|
26499
27129
|
console.log(
|
|
26500
|
-
` ${
|
|
27130
|
+
` ${chalk197.red(`"${oldSpecifier}"`)} \u2192 ${chalk197.green(`"${newSpecifier}"`)}`
|
|
26501
27131
|
);
|
|
26502
27132
|
}
|
|
26503
27133
|
}
|
|
26504
27134
|
}
|
|
26505
27135
|
function displayPlan2(plan2) {
|
|
26506
27136
|
if (plan2.warnings.length > 0) {
|
|
26507
|
-
console.log(
|
|
26508
|
-
for (const w of plan2.warnings) console.log(
|
|
27137
|
+
console.log(chalk197.yellow("\nWarnings:"));
|
|
27138
|
+
for (const w of plan2.warnings) console.log(chalk197.yellow(` ${w}`));
|
|
26509
27139
|
}
|
|
26510
27140
|
if (plan2.newDirectories.length > 0) {
|
|
26511
|
-
console.log(
|
|
27141
|
+
console.log(chalk197.bold("\nNew directories:"));
|
|
26512
27142
|
for (const dir of plan2.newDirectories)
|
|
26513
|
-
console.log(
|
|
27143
|
+
console.log(chalk197.green(` ${dir}/`));
|
|
26514
27144
|
}
|
|
26515
27145
|
displayMoves(plan2);
|
|
26516
27146
|
displayRewrites(plan2.rewrites);
|
|
26517
27147
|
console.log(
|
|
26518
|
-
|
|
27148
|
+
chalk197.dim(
|
|
26519
27149
|
`
|
|
26520
27150
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
26521
27151
|
)
|
|
@@ -26525,18 +27155,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
26525
27155
|
// src/commands/refactor/restructure/executePlan.ts
|
|
26526
27156
|
import fs37 from "fs";
|
|
26527
27157
|
import path60 from "path";
|
|
26528
|
-
import
|
|
27158
|
+
import chalk198 from "chalk";
|
|
26529
27159
|
function executePlan(plan2) {
|
|
26530
27160
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
26531
27161
|
for (const [file, content] of updatedContents) {
|
|
26532
27162
|
fs37.writeFileSync(file, content, "utf8");
|
|
26533
27163
|
console.log(
|
|
26534
|
-
|
|
27164
|
+
chalk198.cyan(` Rewrote imports in ${path60.relative(process.cwd(), file)}`)
|
|
26535
27165
|
);
|
|
26536
27166
|
}
|
|
26537
27167
|
for (const dir of plan2.newDirectories) {
|
|
26538
27168
|
fs37.mkdirSync(dir, { recursive: true });
|
|
26539
|
-
console.log(
|
|
27169
|
+
console.log(chalk198.green(` Created ${path60.relative(process.cwd(), dir)}/`));
|
|
26540
27170
|
}
|
|
26541
27171
|
for (const move2 of plan2.moves) {
|
|
26542
27172
|
const targetDir = path60.dirname(move2.to);
|
|
@@ -26545,7 +27175,7 @@ function executePlan(plan2) {
|
|
|
26545
27175
|
}
|
|
26546
27176
|
fs37.renameSync(move2.from, move2.to);
|
|
26547
27177
|
console.log(
|
|
26548
|
-
|
|
27178
|
+
chalk198.white(
|
|
26549
27179
|
` Moved ${path60.relative(process.cwd(), move2.from)} \u2192 ${path60.relative(process.cwd(), move2.to)}`
|
|
26550
27180
|
)
|
|
26551
27181
|
);
|
|
@@ -26560,7 +27190,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
26560
27190
|
if (entries.length === 0) {
|
|
26561
27191
|
fs37.rmdirSync(dir);
|
|
26562
27192
|
console.log(
|
|
26563
|
-
|
|
27193
|
+
chalk198.dim(
|
|
26564
27194
|
` Removed empty directory ${path60.relative(process.cwd(), dir)}`
|
|
26565
27195
|
)
|
|
26566
27196
|
);
|
|
@@ -26693,22 +27323,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
26693
27323
|
const targetPattern = pattern2 ?? "src";
|
|
26694
27324
|
const files = findSourceFiles2(targetPattern);
|
|
26695
27325
|
if (files.length === 0) {
|
|
26696
|
-
console.log(
|
|
27326
|
+
console.log(chalk199.yellow("No files found matching pattern"));
|
|
26697
27327
|
return;
|
|
26698
27328
|
}
|
|
26699
27329
|
const tsConfigPath = findTsConfig(path63.resolve(files[0]));
|
|
26700
27330
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
26701
27331
|
if (plan2.moves.length === 0) {
|
|
26702
|
-
console.log(
|
|
27332
|
+
console.log(chalk199.green("No restructuring needed"));
|
|
26703
27333
|
return;
|
|
26704
27334
|
}
|
|
26705
27335
|
displayPlan2(plan2);
|
|
26706
27336
|
if (options2.apply) {
|
|
26707
|
-
console.log(
|
|
27337
|
+
console.log(chalk199.bold("\nApplying changes..."));
|
|
26708
27338
|
executePlan(plan2);
|
|
26709
|
-
console.log(
|
|
27339
|
+
console.log(chalk199.green("\nRestructuring complete"));
|
|
26710
27340
|
} else {
|
|
26711
|
-
console.log(
|
|
27341
|
+
console.log(chalk199.dim("\nDry run. Use --apply to execute."));
|
|
26712
27342
|
}
|
|
26713
27343
|
}
|
|
26714
27344
|
|
|
@@ -27031,7 +27661,7 @@ function gatherContext() {
|
|
|
27031
27661
|
}
|
|
27032
27662
|
|
|
27033
27663
|
// src/commands/review/postReviewToPr.ts
|
|
27034
|
-
import { readFileSync as
|
|
27664
|
+
import { readFileSync as readFileSync43 } from "fs";
|
|
27035
27665
|
|
|
27036
27666
|
// src/commands/review/carriedUnanchoredFindings.ts
|
|
27037
27667
|
function carriedUnanchoredFindings(unanchored) {
|
|
@@ -27366,18 +27996,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
27366
27996
|
}
|
|
27367
27997
|
|
|
27368
27998
|
// src/commands/review/warnOutOfDiff.ts
|
|
27369
|
-
import
|
|
27999
|
+
import chalk200 from "chalk";
|
|
27370
28000
|
function warnOutOfDiff(outOfDiff) {
|
|
27371
28001
|
if (outOfDiff.length === 0) return;
|
|
27372
28002
|
console.warn(
|
|
27373
|
-
|
|
28003
|
+
chalk200.yellow(
|
|
27374
28004
|
`Moved ${outOfDiff.length} finding(s) whose lines fall outside the PR diff into the review body (GitHub cannot anchor a comment on these):`
|
|
27375
28005
|
)
|
|
27376
28006
|
);
|
|
27377
28007
|
for (const finding of outOfDiff) {
|
|
27378
28008
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
27379
28009
|
console.warn(
|
|
27380
|
-
` ${
|
|
28010
|
+
` ${chalk200.yellow("\xB7")} ${finding.title} ${chalk200.dim(
|
|
27381
28011
|
`(${finding.file}:${range})`
|
|
27382
28012
|
)}`
|
|
27383
28013
|
);
|
|
@@ -27401,18 +28031,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
27401
28031
|
}
|
|
27402
28032
|
|
|
27403
28033
|
// src/commands/review/warnUnlocated.ts
|
|
27404
|
-
import
|
|
28034
|
+
import chalk201 from "chalk";
|
|
27405
28035
|
function warnUnlocated(unlocated) {
|
|
27406
28036
|
if (unlocated.length === 0) return;
|
|
27407
28037
|
console.warn(
|
|
27408
|
-
|
|
28038
|
+
chalk201.yellow(
|
|
27409
28039
|
`Moved ${unlocated.length} finding(s) without a parseable file:line into the review body:`
|
|
27410
28040
|
)
|
|
27411
28041
|
);
|
|
27412
28042
|
for (const finding of unlocated) {
|
|
27413
|
-
const where = finding.location ||
|
|
28043
|
+
const where = finding.location || chalk201.dim("missing");
|
|
27414
28044
|
console.warn(
|
|
27415
|
-
` ${
|
|
28045
|
+
` ${chalk201.yellow("\xB7")} ${finding.title} ${chalk201.dim(`(${where})`)}`
|
|
27416
28046
|
);
|
|
27417
28047
|
}
|
|
27418
28048
|
}
|
|
@@ -27479,7 +28109,7 @@ async function confirmPost(prNumber, work, options2) {
|
|
|
27479
28109
|
return promptConfirm(`Post ${work} to PR #${prNumber}?`, false);
|
|
27480
28110
|
}
|
|
27481
28111
|
async function postFindingsToPr(prInfo, synthesisPath, options2) {
|
|
27482
|
-
const markdown =
|
|
28112
|
+
const markdown = readFileSync43(synthesisPath, "utf8");
|
|
27483
28113
|
const { inDiff, unanchored } = selectPostableFindings(markdown, prInfo);
|
|
27484
28114
|
const carried = carriedUnanchoredFindings(unanchored);
|
|
27485
28115
|
if (inDiff.length === 0 && carried.length === 0) return NOTHING_POSTED;
|
|
@@ -27615,10 +28245,10 @@ async function handlePostSynthesis(synthesisPath, prInfo, options2) {
|
|
|
27615
28245
|
}
|
|
27616
28246
|
|
|
27617
28247
|
// src/commands/review/prepareReviewDir.ts
|
|
27618
|
-
import { existsSync as
|
|
28248
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync20, unlinkSync as unlinkSync17, writeFileSync as writeFileSync37 } from "fs";
|
|
27619
28249
|
function clearReviewFiles(paths) {
|
|
27620
28250
|
for (const path80 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
27621
|
-
if (
|
|
28251
|
+
if (existsSync55(path80)) unlinkSync17(path80);
|
|
27622
28252
|
}
|
|
27623
28253
|
}
|
|
27624
28254
|
function prepareReviewDir(paths, requestBody, force) {
|
|
@@ -27744,9 +28374,9 @@ var MultiSpinner = class {
|
|
|
27744
28374
|
};
|
|
27745
28375
|
|
|
27746
28376
|
// src/commands/review/ensureCodexAvailable.ts
|
|
27747
|
-
import { spawnSync as
|
|
28377
|
+
import { spawnSync as spawnSync7 } from "child_process";
|
|
27748
28378
|
function runNpmInstall() {
|
|
27749
|
-
const result =
|
|
28379
|
+
const result = spawnSync7("npm", ["install", "-g", "@openai/codex"], {
|
|
27750
28380
|
stdio: "inherit",
|
|
27751
28381
|
shell: true
|
|
27752
28382
|
});
|
|
@@ -27845,7 +28475,7 @@ function printReviewerFailures(results) {
|
|
|
27845
28475
|
}
|
|
27846
28476
|
|
|
27847
28477
|
// src/commands/review/runAndSynthesise.ts
|
|
27848
|
-
import { existsSync as
|
|
28478
|
+
import { existsSync as existsSync57, unlinkSync as unlinkSync19 } from "fs";
|
|
27849
28479
|
|
|
27850
28480
|
// src/commands/review/buildReviewerStdin.ts
|
|
27851
28481
|
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.
|
|
@@ -28274,7 +28904,7 @@ function resolveClaude(args) {
|
|
|
28274
28904
|
}
|
|
28275
28905
|
|
|
28276
28906
|
// src/commands/review/runCodexReviewer.ts
|
|
28277
|
-
import { existsSync as
|
|
28907
|
+
import { existsSync as existsSync56, unlinkSync as unlinkSync18 } from "fs";
|
|
28278
28908
|
|
|
28279
28909
|
// src/commands/review/parseCodexEvent.ts
|
|
28280
28910
|
function isItemStarted(value) {
|
|
@@ -28326,7 +28956,7 @@ async function runCodexReviewer(spec) {
|
|
|
28326
28956
|
reportReviewerToolUse(spec.name, event, spinner);
|
|
28327
28957
|
}
|
|
28328
28958
|
});
|
|
28329
|
-
if (result.exitCode !== 0 &&
|
|
28959
|
+
if (result.exitCode !== 0 && existsSync56(spec.outputPath)) {
|
|
28330
28960
|
unlinkSync18(spec.outputPath);
|
|
28331
28961
|
}
|
|
28332
28962
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
@@ -28368,7 +28998,7 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
|
|
|
28368
28998
|
}
|
|
28369
28999
|
|
|
28370
29000
|
// src/commands/review/synthesise.ts
|
|
28371
|
-
import { readFileSync as
|
|
29001
|
+
import { readFileSync as readFileSync44 } from "fs";
|
|
28372
29002
|
|
|
28373
29003
|
// src/commands/review/buildSynthesisStdin.ts
|
|
28374
29004
|
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.
|
|
@@ -28433,7 +29063,7 @@ Files:
|
|
|
28433
29063
|
|
|
28434
29064
|
// src/commands/review/synthesise.ts
|
|
28435
29065
|
function printSummary2(synthesisPath) {
|
|
28436
|
-
const markdown =
|
|
29066
|
+
const markdown = readFileSync44(synthesisPath, "utf8");
|
|
28437
29067
|
console.log("");
|
|
28438
29068
|
console.log(buildReviewSummary(markdown));
|
|
28439
29069
|
console.log("");
|
|
@@ -28481,7 +29111,7 @@ async function runAndSynthesise(args) {
|
|
|
28481
29111
|
console.error("Both reviewers failed; skipping synthesis.");
|
|
28482
29112
|
return { ok: false, failures };
|
|
28483
29113
|
}
|
|
28484
|
-
if (anyFresh &&
|
|
29114
|
+
if (anyFresh && existsSync57(paths.synthesisPath)) {
|
|
28485
29115
|
unlinkSync19(paths.synthesisPath);
|
|
28486
29116
|
}
|
|
28487
29117
|
const synthesisResult = await synthesise(paths, { multi });
|
|
@@ -28667,7 +29297,7 @@ function registerReview(program2) {
|
|
|
28667
29297
|
}
|
|
28668
29298
|
|
|
28669
29299
|
// src/commands/seq/seqAuth.ts
|
|
28670
|
-
import
|
|
29300
|
+
import chalk203 from "chalk";
|
|
28671
29301
|
|
|
28672
29302
|
// src/commands/seq/loadConnections.ts
|
|
28673
29303
|
function loadConnections2() {
|
|
@@ -28696,10 +29326,10 @@ function setDefaultConnection(name) {
|
|
|
28696
29326
|
}
|
|
28697
29327
|
|
|
28698
29328
|
// src/shared/assertUniqueName.ts
|
|
28699
|
-
import
|
|
29329
|
+
import chalk202 from "chalk";
|
|
28700
29330
|
function assertUniqueName(existingNames, name) {
|
|
28701
29331
|
if (existingNames.includes(name)) {
|
|
28702
|
-
console.error(
|
|
29332
|
+
console.error(chalk202.red(`Connection "${name}" already exists.`));
|
|
28703
29333
|
process.exit(1);
|
|
28704
29334
|
}
|
|
28705
29335
|
}
|
|
@@ -28717,16 +29347,16 @@ async function promptConnection2(existingNames) {
|
|
|
28717
29347
|
var seqAuth = createConnectionAuth({
|
|
28718
29348
|
load: loadConnections2,
|
|
28719
29349
|
save: saveConnections2,
|
|
28720
|
-
format: (c) => `${
|
|
29350
|
+
format: (c) => `${chalk203.bold(c.name)} ${c.url}`,
|
|
28721
29351
|
promptNew: promptConnection2,
|
|
28722
29352
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
28723
29353
|
});
|
|
28724
29354
|
|
|
28725
29355
|
// src/commands/seq/seqQuery.ts
|
|
28726
|
-
import
|
|
29356
|
+
import chalk207 from "chalk";
|
|
28727
29357
|
|
|
28728
29358
|
// src/commands/seq/fetchSeq.ts
|
|
28729
|
-
import
|
|
29359
|
+
import chalk204 from "chalk";
|
|
28730
29360
|
async function fetchSeq(conn, path80, params) {
|
|
28731
29361
|
const url = `${conn.url}${path80}?${params}`;
|
|
28732
29362
|
const response = await fetch(url, {
|
|
@@ -28737,7 +29367,7 @@ async function fetchSeq(conn, path80, params) {
|
|
|
28737
29367
|
});
|
|
28738
29368
|
if (!response.ok) {
|
|
28739
29369
|
const body = await response.text();
|
|
28740
|
-
console.error(
|
|
29370
|
+
console.error(chalk204.red(`Seq returned ${response.status}: ${body}`));
|
|
28741
29371
|
process.exit(1);
|
|
28742
29372
|
}
|
|
28743
29373
|
return response;
|
|
@@ -28796,23 +29426,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
28796
29426
|
}
|
|
28797
29427
|
|
|
28798
29428
|
// src/commands/seq/formatEvent.ts
|
|
28799
|
-
import
|
|
29429
|
+
import chalk205 from "chalk";
|
|
28800
29430
|
function levelColor(level) {
|
|
28801
29431
|
switch (level) {
|
|
28802
29432
|
case "Fatal":
|
|
28803
|
-
return
|
|
29433
|
+
return chalk205.bgRed.white;
|
|
28804
29434
|
case "Error":
|
|
28805
|
-
return
|
|
29435
|
+
return chalk205.red;
|
|
28806
29436
|
case "Warning":
|
|
28807
|
-
return
|
|
29437
|
+
return chalk205.yellow;
|
|
28808
29438
|
case "Information":
|
|
28809
|
-
return
|
|
29439
|
+
return chalk205.cyan;
|
|
28810
29440
|
case "Debug":
|
|
28811
|
-
return
|
|
29441
|
+
return chalk205.gray;
|
|
28812
29442
|
case "Verbose":
|
|
28813
|
-
return
|
|
29443
|
+
return chalk205.dim;
|
|
28814
29444
|
default:
|
|
28815
|
-
return
|
|
29445
|
+
return chalk205.white;
|
|
28816
29446
|
}
|
|
28817
29447
|
}
|
|
28818
29448
|
function levelAbbrev(level) {
|
|
@@ -28853,12 +29483,12 @@ function formatTimestamp(iso) {
|
|
|
28853
29483
|
function formatEvent(event) {
|
|
28854
29484
|
const color = levelColor(event.Level);
|
|
28855
29485
|
const abbrev = levelAbbrev(event.Level);
|
|
28856
|
-
const ts8 =
|
|
29486
|
+
const ts8 = chalk205.dim(formatTimestamp(event.Timestamp));
|
|
28857
29487
|
const msg = renderMessage(event);
|
|
28858
29488
|
const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
28859
29489
|
if (event.Exception) {
|
|
28860
29490
|
for (const line of event.Exception.split("\n")) {
|
|
28861
|
-
lines2.push(
|
|
29491
|
+
lines2.push(chalk205.red(` ${line}`));
|
|
28862
29492
|
}
|
|
28863
29493
|
}
|
|
28864
29494
|
return lines2.join("\n");
|
|
@@ -28891,11 +29521,11 @@ function rejectTimestampFilter(filter) {
|
|
|
28891
29521
|
}
|
|
28892
29522
|
|
|
28893
29523
|
// src/shared/resolveNamedConnection.ts
|
|
28894
|
-
import
|
|
29524
|
+
import chalk206 from "chalk";
|
|
28895
29525
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
28896
29526
|
if (connections.length === 0) {
|
|
28897
29527
|
console.error(
|
|
28898
|
-
|
|
29528
|
+
chalk206.red(
|
|
28899
29529
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
28900
29530
|
)
|
|
28901
29531
|
);
|
|
@@ -28904,7 +29534,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
28904
29534
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
28905
29535
|
const connection = connections.find((c) => c.name === target);
|
|
28906
29536
|
if (!connection) {
|
|
28907
|
-
console.error(
|
|
29537
|
+
console.error(chalk206.red(`${kind} connection "${target}" not found.`));
|
|
28908
29538
|
process.exit(1);
|
|
28909
29539
|
}
|
|
28910
29540
|
return connection;
|
|
@@ -28933,7 +29563,7 @@ async function seqQuery(filter, options2) {
|
|
|
28933
29563
|
new URLSearchParams({ filter, count: String(count8) })
|
|
28934
29564
|
);
|
|
28935
29565
|
if (events.length === 0) {
|
|
28936
|
-
console.log(
|
|
29566
|
+
console.log(chalk207.yellow("No events found."));
|
|
28937
29567
|
return;
|
|
28938
29568
|
}
|
|
28939
29569
|
if (options2.json) {
|
|
@@ -28944,11 +29574,11 @@ async function seqQuery(filter, options2) {
|
|
|
28944
29574
|
for (const event of chronological) {
|
|
28945
29575
|
console.log(formatEvent(event));
|
|
28946
29576
|
}
|
|
28947
|
-
console.log(
|
|
29577
|
+
console.log(chalk207.dim(`
|
|
28948
29578
|
${events.length} events`));
|
|
28949
29579
|
if (events.length >= count8) {
|
|
28950
29580
|
console.log(
|
|
28951
|
-
|
|
29581
|
+
chalk207.yellow(
|
|
28952
29582
|
`Results limited to ${count8}. Use --count to retrieve more.`
|
|
28953
29583
|
)
|
|
28954
29584
|
);
|
|
@@ -28956,10 +29586,10 @@ ${events.length} events`));
|
|
|
28956
29586
|
}
|
|
28957
29587
|
|
|
28958
29588
|
// src/shared/setNamedDefaultConnection.ts
|
|
28959
|
-
import
|
|
29589
|
+
import chalk208 from "chalk";
|
|
28960
29590
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
28961
29591
|
if (!connections.find((c) => c.name === name)) {
|
|
28962
|
-
console.error(
|
|
29592
|
+
console.error(chalk208.red(`Connection "${name}" not found.`));
|
|
28963
29593
|
process.exit(1);
|
|
28964
29594
|
}
|
|
28965
29595
|
setDefault(name);
|
|
@@ -29008,7 +29638,7 @@ function registerSignal(program2) {
|
|
|
29008
29638
|
}
|
|
29009
29639
|
|
|
29010
29640
|
// src/commands/sql/sqlAuth.ts
|
|
29011
|
-
import
|
|
29641
|
+
import chalk210 from "chalk";
|
|
29012
29642
|
|
|
29013
29643
|
// src/commands/sql/loadConnections.ts
|
|
29014
29644
|
function loadConnections3() {
|
|
@@ -29037,7 +29667,7 @@ function setDefaultConnection2(name) {
|
|
|
29037
29667
|
}
|
|
29038
29668
|
|
|
29039
29669
|
// src/commands/sql/promptConnection.ts
|
|
29040
|
-
import
|
|
29670
|
+
import chalk209 from "chalk";
|
|
29041
29671
|
async function promptConnection3(existingNames) {
|
|
29042
29672
|
const name = await promptInput("name", "Connection name:", "default");
|
|
29043
29673
|
assertUniqueName(existingNames, name);
|
|
@@ -29045,7 +29675,7 @@ async function promptConnection3(existingNames) {
|
|
|
29045
29675
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
29046
29676
|
const port = Number.parseInt(portStr, 10);
|
|
29047
29677
|
if (!Number.isFinite(port)) {
|
|
29048
|
-
console.error(
|
|
29678
|
+
console.error(chalk209.red(`Invalid port "${portStr}".`));
|
|
29049
29679
|
process.exit(1);
|
|
29050
29680
|
}
|
|
29051
29681
|
const user = await promptInput("user", "User:");
|
|
@@ -29058,13 +29688,13 @@ async function promptConnection3(existingNames) {
|
|
|
29058
29688
|
var sqlAuth = createConnectionAuth({
|
|
29059
29689
|
load: loadConnections3,
|
|
29060
29690
|
save: saveConnections3,
|
|
29061
|
-
format: (c) => `${
|
|
29691
|
+
format: (c) => `${chalk210.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
29062
29692
|
promptNew: promptConnection3,
|
|
29063
29693
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
29064
29694
|
});
|
|
29065
29695
|
|
|
29066
29696
|
// src/commands/sql/printTable.ts
|
|
29067
|
-
import
|
|
29697
|
+
import chalk211 from "chalk";
|
|
29068
29698
|
function formatCell(value) {
|
|
29069
29699
|
if (value === null || value === void 0) return "";
|
|
29070
29700
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -29073,7 +29703,7 @@ function formatCell(value) {
|
|
|
29073
29703
|
}
|
|
29074
29704
|
function printTable(rows) {
|
|
29075
29705
|
if (rows.length === 0) {
|
|
29076
|
-
console.log(
|
|
29706
|
+
console.log(chalk211.yellow("(no rows)"));
|
|
29077
29707
|
return;
|
|
29078
29708
|
}
|
|
29079
29709
|
const columns = Object.keys(rows[0]);
|
|
@@ -29081,13 +29711,13 @@ function printTable(rows) {
|
|
|
29081
29711
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
29082
29712
|
);
|
|
29083
29713
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
29084
|
-
console.log(
|
|
29085
|
-
console.log(
|
|
29714
|
+
console.log(chalk211.dim(header));
|
|
29715
|
+
console.log(chalk211.dim("-".repeat(header.length)));
|
|
29086
29716
|
for (const row of rows) {
|
|
29087
29717
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
29088
29718
|
console.log(line);
|
|
29089
29719
|
}
|
|
29090
|
-
console.log(
|
|
29720
|
+
console.log(chalk211.dim(`
|
|
29091
29721
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
29092
29722
|
}
|
|
29093
29723
|
|
|
@@ -29147,7 +29777,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
29147
29777
|
}
|
|
29148
29778
|
|
|
29149
29779
|
// src/commands/sql/sqlMutate.ts
|
|
29150
|
-
import
|
|
29780
|
+
import chalk212 from "chalk";
|
|
29151
29781
|
|
|
29152
29782
|
// src/commands/sql/isMutation.ts
|
|
29153
29783
|
var MUTATION_KEYWORDS = [
|
|
@@ -29181,7 +29811,7 @@ function isMutation(sql25) {
|
|
|
29181
29811
|
async function sqlMutate(query, connectionName) {
|
|
29182
29812
|
if (!isMutation(query)) {
|
|
29183
29813
|
console.error(
|
|
29184
|
-
|
|
29814
|
+
chalk212.red(
|
|
29185
29815
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
29186
29816
|
)
|
|
29187
29817
|
);
|
|
@@ -29191,18 +29821,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
29191
29821
|
const pool = await sqlConnect(conn);
|
|
29192
29822
|
try {
|
|
29193
29823
|
const result = await pool.request().query(query);
|
|
29194
|
-
console.log(
|
|
29824
|
+
console.log(chalk212.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
29195
29825
|
} finally {
|
|
29196
29826
|
await pool.close();
|
|
29197
29827
|
}
|
|
29198
29828
|
}
|
|
29199
29829
|
|
|
29200
29830
|
// src/commands/sql/sqlQuery.ts
|
|
29201
|
-
import
|
|
29831
|
+
import chalk213 from "chalk";
|
|
29202
29832
|
async function sqlQuery(query, connectionName) {
|
|
29203
29833
|
if (isMutation(query)) {
|
|
29204
29834
|
console.error(
|
|
29205
|
-
|
|
29835
|
+
chalk213.red(
|
|
29206
29836
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
29207
29837
|
)
|
|
29208
29838
|
);
|
|
@@ -29217,7 +29847,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
29217
29847
|
printTable(rows);
|
|
29218
29848
|
} else {
|
|
29219
29849
|
console.log(
|
|
29220
|
-
|
|
29850
|
+
chalk213.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
29221
29851
|
);
|
|
29222
29852
|
}
|
|
29223
29853
|
} finally {
|
|
@@ -29362,7 +29992,7 @@ function reportPrune(label2, result, force) {
|
|
|
29362
29992
|
// src/commands/sync/syncClaudeMd.ts
|
|
29363
29993
|
import * as fs41 from "fs";
|
|
29364
29994
|
import * as path66 from "path";
|
|
29365
|
-
import
|
|
29995
|
+
import chalk214 from "chalk";
|
|
29366
29996
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
29367
29997
|
const source = path66.join(claudeDir, "CLAUDE.md");
|
|
29368
29998
|
const target = path66.join(targetBase, "CLAUDE.md");
|
|
@@ -29371,14 +30001,14 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
29371
30001
|
const targetContent = fs41.readFileSync(target, "utf8");
|
|
29372
30002
|
if (sourceContent !== targetContent) {
|
|
29373
30003
|
console.log(
|
|
29374
|
-
|
|
30004
|
+
chalk214.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
29375
30005
|
);
|
|
29376
30006
|
console.log();
|
|
29377
30007
|
printDiff(targetContent, sourceContent);
|
|
29378
30008
|
if (!options2?.yes) {
|
|
29379
30009
|
printAutoConfirmHint();
|
|
29380
30010
|
const confirm = await promptConfirm(
|
|
29381
|
-
|
|
30011
|
+
chalk214.red("Overwrite existing CLAUDE.md?"),
|
|
29382
30012
|
false
|
|
29383
30013
|
);
|
|
29384
30014
|
if (!confirm) {
|
|
@@ -29611,7 +30241,7 @@ function syncPi(claudeDir, options2) {
|
|
|
29611
30241
|
// src/commands/sync/syncSettings.ts
|
|
29612
30242
|
import * as fs47 from "fs";
|
|
29613
30243
|
import * as path73 from "path";
|
|
29614
|
-
import
|
|
30244
|
+
import chalk215 from "chalk";
|
|
29615
30245
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
29616
30246
|
const source = path73.join(claudeDir, "settings.json");
|
|
29617
30247
|
const target = path73.join(targetBase, "settings.json");
|
|
@@ -29630,7 +30260,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
29630
30260
|
if (mergedContent !== normalizedTarget) {
|
|
29631
30261
|
if (!options2?.yes) {
|
|
29632
30262
|
console.log(
|
|
29633
|
-
|
|
30263
|
+
chalk215.yellow(
|
|
29634
30264
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
29635
30265
|
)
|
|
29636
30266
|
);
|
|
@@ -29638,7 +30268,7 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
29638
30268
|
printDiff(targetContent, mergedContent);
|
|
29639
30269
|
printAutoConfirmHint();
|
|
29640
30270
|
const confirm = await promptConfirm(
|
|
29641
|
-
|
|
30271
|
+
chalk215.red("Overwrite existing settings.json?"),
|
|
29642
30272
|
false
|
|
29643
30273
|
);
|
|
29644
30274
|
if (!confirm) {
|
|
@@ -29780,11 +30410,11 @@ async function configure() {
|
|
|
29780
30410
|
}
|
|
29781
30411
|
|
|
29782
30412
|
// src/commands/transcript/list.ts
|
|
29783
|
-
import { existsSync as
|
|
30413
|
+
import { existsSync as existsSync62, readdirSync as readdirSync19, statSync as statSync10 } from "fs";
|
|
29784
30414
|
import { join as join77 } from "path";
|
|
29785
30415
|
function list4() {
|
|
29786
30416
|
const { vttDir } = getTranscriptConfig();
|
|
29787
|
-
if (!
|
|
30417
|
+
if (!existsSync62(vttDir)) return;
|
|
29788
30418
|
for (const entry of readdirSync19(vttDir)) {
|
|
29789
30419
|
if (!entry.endsWith(".vtt")) continue;
|
|
29790
30420
|
if (statSync10(join77(vttDir, entry)).isDirectory()) continue;
|
|
@@ -29794,9 +30424,9 @@ function list4() {
|
|
|
29794
30424
|
|
|
29795
30425
|
// src/commands/transcript/move.ts
|
|
29796
30426
|
import {
|
|
29797
|
-
existsSync as
|
|
30427
|
+
existsSync as existsSync63,
|
|
29798
30428
|
mkdirSync as mkdirSync26,
|
|
29799
|
-
readFileSync as
|
|
30429
|
+
readFileSync as readFileSync49,
|
|
29800
30430
|
renameSync as renameSync2,
|
|
29801
30431
|
writeFileSync as writeFileSync42
|
|
29802
30432
|
} from "fs";
|
|
@@ -30008,7 +30638,7 @@ function formatChatLog(messages) {
|
|
|
30008
30638
|
// src/commands/transcript/move.ts
|
|
30009
30639
|
var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
30010
30640
|
function convertVttToMarkdown(inputPath) {
|
|
30011
|
-
const cues = parseVtt(
|
|
30641
|
+
const cues = parseVtt(readFileSync49(inputPath, "utf8"));
|
|
30012
30642
|
const messages = cuesToChatMessages(deduplicateCues(cues));
|
|
30013
30643
|
return formatChatLog(messages);
|
|
30014
30644
|
}
|
|
@@ -30026,7 +30656,7 @@ function move(file, options2) {
|
|
|
30026
30656
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
30027
30657
|
const filename = basename21(file);
|
|
30028
30658
|
const sourcePath = join78(vttDir, filename);
|
|
30029
|
-
if (!
|
|
30659
|
+
if (!existsSync63(sourcePath)) {
|
|
30030
30660
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
30031
30661
|
process.exit(1);
|
|
30032
30662
|
}
|
|
@@ -30118,7 +30748,7 @@ function registerVerify(program2) {
|
|
|
30118
30748
|
}
|
|
30119
30749
|
|
|
30120
30750
|
// src/commands/voice/devices.ts
|
|
30121
|
-
import { spawnSync as
|
|
30751
|
+
import { spawnSync as spawnSync8 } from "child_process";
|
|
30122
30752
|
import { join as join80 } from "path";
|
|
30123
30753
|
|
|
30124
30754
|
// src/commands/voice/shared.ts
|
|
@@ -30151,18 +30781,18 @@ function getLockFile() {
|
|
|
30151
30781
|
// src/commands/voice/devices.ts
|
|
30152
30782
|
function devices() {
|
|
30153
30783
|
const script = join80(getPythonDir(), "list_devices.py");
|
|
30154
|
-
|
|
30784
|
+
spawnSync8(getVenvPython(), [script], { stdio: "inherit" });
|
|
30155
30785
|
}
|
|
30156
30786
|
|
|
30157
30787
|
// src/commands/voice/logs.ts
|
|
30158
|
-
import { existsSync as
|
|
30788
|
+
import { existsSync as existsSync64, readFileSync as readFileSync50 } from "fs";
|
|
30159
30789
|
function logs(options2) {
|
|
30160
|
-
if (!
|
|
30790
|
+
if (!existsSync64(voicePaths.log)) {
|
|
30161
30791
|
console.log("No voice log file found");
|
|
30162
30792
|
return;
|
|
30163
30793
|
}
|
|
30164
30794
|
const count8 = Number.parseInt(options2.lines ?? "150", 10);
|
|
30165
|
-
const content =
|
|
30795
|
+
const content = readFileSync50(voicePaths.log, "utf8").trim();
|
|
30166
30796
|
if (!content) {
|
|
30167
30797
|
console.log("Voice log is empty");
|
|
30168
30798
|
return;
|
|
@@ -30183,13 +30813,13 @@ function logs(options2) {
|
|
|
30183
30813
|
}
|
|
30184
30814
|
|
|
30185
30815
|
// src/commands/voice/setup.ts
|
|
30186
|
-
import { spawnSync as
|
|
30816
|
+
import { spawnSync as spawnSync9 } from "child_process";
|
|
30187
30817
|
import { mkdirSync as mkdirSync28 } from "fs";
|
|
30188
30818
|
import { join as join82 } from "path";
|
|
30189
30819
|
|
|
30190
30820
|
// src/commands/voice/checkLockFile.ts
|
|
30191
30821
|
import { execSync as execSync58 } from "child_process";
|
|
30192
|
-
import { existsSync as
|
|
30822
|
+
import { existsSync as existsSync65, mkdirSync as mkdirSync27, readFileSync as readFileSync51, writeFileSync as writeFileSync43 } from "fs";
|
|
30193
30823
|
import { join as join81 } from "path";
|
|
30194
30824
|
function isProcessAlive2(pid) {
|
|
30195
30825
|
try {
|
|
@@ -30201,9 +30831,9 @@ function isProcessAlive2(pid) {
|
|
|
30201
30831
|
}
|
|
30202
30832
|
function checkLockFile() {
|
|
30203
30833
|
const lockFile = getLockFile();
|
|
30204
|
-
if (!
|
|
30834
|
+
if (!existsSync65(lockFile)) return;
|
|
30205
30835
|
try {
|
|
30206
|
-
const lock2 = JSON.parse(
|
|
30836
|
+
const lock2 = JSON.parse(readFileSync51(lockFile, "utf8"));
|
|
30207
30837
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
30208
30838
|
console.error(
|
|
30209
30839
|
`Voice daemon already running (PID ${lock2.pid}, env: ${lock2.env}). Stop it first with: assist voice stop`
|
|
@@ -30214,7 +30844,7 @@ function checkLockFile() {
|
|
|
30214
30844
|
}
|
|
30215
30845
|
}
|
|
30216
30846
|
function bootstrapVenv() {
|
|
30217
|
-
if (
|
|
30847
|
+
if (existsSync65(getVenvPython())) return;
|
|
30218
30848
|
console.log("Setting up Python environment...");
|
|
30219
30849
|
const pythonDir = getPythonDir();
|
|
30220
30850
|
execSync58(
|
|
@@ -30244,7 +30874,7 @@ function setup() {
|
|
|
30244
30874
|
bootstrapVenv();
|
|
30245
30875
|
console.log("\nDownloading models...\n");
|
|
30246
30876
|
const script = join82(getPythonDir(), "setup_models.py");
|
|
30247
|
-
const result =
|
|
30877
|
+
const result = spawnSync9(getVenvPython(), [script], {
|
|
30248
30878
|
stdio: "inherit",
|
|
30249
30879
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
30250
30880
|
});
|
|
@@ -30305,7 +30935,7 @@ function start2(options2) {
|
|
|
30305
30935
|
}
|
|
30306
30936
|
|
|
30307
30937
|
// src/commands/voice/status.ts
|
|
30308
|
-
import { existsSync as
|
|
30938
|
+
import { existsSync as existsSync66, readFileSync as readFileSync52 } from "fs";
|
|
30309
30939
|
function isProcessAlive3(pid) {
|
|
30310
30940
|
try {
|
|
30311
30941
|
process.kill(pid, 0);
|
|
@@ -30315,16 +30945,16 @@ function isProcessAlive3(pid) {
|
|
|
30315
30945
|
}
|
|
30316
30946
|
}
|
|
30317
30947
|
function readRecentLogs(count8) {
|
|
30318
|
-
if (!
|
|
30319
|
-
const lines2 =
|
|
30948
|
+
if (!existsSync66(voicePaths.log)) return [];
|
|
30949
|
+
const lines2 = readFileSync52(voicePaths.log, "utf8").trim().split("\n");
|
|
30320
30950
|
return lines2.slice(-count8);
|
|
30321
30951
|
}
|
|
30322
30952
|
function status2() {
|
|
30323
|
-
if (!
|
|
30953
|
+
if (!existsSync66(voicePaths.pid)) {
|
|
30324
30954
|
console.log("Voice daemon: not running (no PID file)");
|
|
30325
30955
|
return;
|
|
30326
30956
|
}
|
|
30327
|
-
const pid = Number.parseInt(
|
|
30957
|
+
const pid = Number.parseInt(readFileSync52(voicePaths.pid, "utf8").trim(), 10);
|
|
30328
30958
|
const alive = isProcessAlive3(pid);
|
|
30329
30959
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
30330
30960
|
const recent = readRecentLogs(5);
|
|
@@ -30343,13 +30973,13 @@ function status2() {
|
|
|
30343
30973
|
}
|
|
30344
30974
|
|
|
30345
30975
|
// src/commands/voice/stop.ts
|
|
30346
|
-
import { existsSync as
|
|
30976
|
+
import { existsSync as existsSync67, readFileSync as readFileSync53, unlinkSync as unlinkSync20 } from "fs";
|
|
30347
30977
|
function stop2() {
|
|
30348
|
-
if (!
|
|
30978
|
+
if (!existsSync67(voicePaths.pid)) {
|
|
30349
30979
|
console.log("Voice daemon is not running (no PID file)");
|
|
30350
30980
|
return;
|
|
30351
30981
|
}
|
|
30352
|
-
const pid = Number.parseInt(
|
|
30982
|
+
const pid = Number.parseInt(readFileSync53(voicePaths.pid, "utf8").trim(), 10);
|
|
30353
30983
|
try {
|
|
30354
30984
|
process.kill(pid, "SIGTERM");
|
|
30355
30985
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -30362,7 +30992,7 @@ function stop2() {
|
|
|
30362
30992
|
}
|
|
30363
30993
|
try {
|
|
30364
30994
|
const lockFile = getLockFile();
|
|
30365
|
-
if (
|
|
30995
|
+
if (existsSync67(lockFile)) unlinkSync20(lockFile);
|
|
30366
30996
|
} catch {
|
|
30367
30997
|
}
|
|
30368
30998
|
console.log("Voice daemon stopped");
|
|
@@ -30380,9 +31010,6 @@ function registerVoice(program2) {
|
|
|
30380
31010
|
configHelp(voiceCommand, voiceConfigHelp);
|
|
30381
31011
|
}
|
|
30382
31012
|
|
|
30383
|
-
// src/commands/watch/readBuiltVersion.ts
|
|
30384
|
-
import { join as join84 } from "path";
|
|
30385
|
-
|
|
30386
31013
|
// src/commands/watch/resolveUpstream.ts
|
|
30387
31014
|
import { execFileSync as execFileSync15 } from "child_process";
|
|
30388
31015
|
function runGit3(args, cwd) {
|
|
@@ -30423,7 +31050,13 @@ function resolveUpstream(cwd) {
|
|
|
30423
31050
|
}
|
|
30424
31051
|
}
|
|
30425
31052
|
|
|
31053
|
+
// src/commands/watch/changedPaths.ts
|
|
31054
|
+
function changedPaths(from, cwd) {
|
|
31055
|
+
return runGit3(["diff", "--name-only", `${from}..HEAD`], cwd).split("\n").filter((line) => line.length > 0);
|
|
31056
|
+
}
|
|
31057
|
+
|
|
30426
31058
|
// src/commands/watch/readBuiltVersion.ts
|
|
31059
|
+
import { join as join84 } from "path";
|
|
30427
31060
|
function readBuiltVersion(cwd) {
|
|
30428
31061
|
try {
|
|
30429
31062
|
const root = runGit3(["rev-parse", "--show-toplevel"], cwd);
|
|
@@ -30534,12 +31167,11 @@ function syncAdvice(paths) {
|
|
|
30534
31167
|
// src/commands/watch/buildWatchReport.ts
|
|
30535
31168
|
var lines = (output) => output.split("\n").filter((line) => line.length > 0);
|
|
30536
31169
|
function buildWatchReport(from, cwd) {
|
|
30537
|
-
const
|
|
30538
|
-
const changed = range ? lines(runGit3(["diff", "--name-only", range], cwd)) : [];
|
|
31170
|
+
const changed = from ? changedPaths(from, cwd) : [];
|
|
30539
31171
|
return renderWatchReport({
|
|
30540
31172
|
version: readBuiltVersion(cwd),
|
|
30541
31173
|
commits: readRecentCommits(10, cwd),
|
|
30542
|
-
newShas:
|
|
31174
|
+
newShas: from ? lines(runGit3(["rev-list", `${from}..HEAD`], cwd)) : [],
|
|
30543
31175
|
restarts: restartAdvice(changed),
|
|
30544
31176
|
syncs: syncAdvice(changed)
|
|
30545
31177
|
});
|
|
@@ -30765,7 +31397,7 @@ function resolveParams(params, cliArgs) {
|
|
|
30765
31397
|
}
|
|
30766
31398
|
|
|
30767
31399
|
// src/commands/run/resolveRunCwd.ts
|
|
30768
|
-
import { existsSync as
|
|
31400
|
+
import { existsSync as existsSync68 } from "fs";
|
|
30769
31401
|
import { resolve as resolve18 } from "path";
|
|
30770
31402
|
var MissingRunCwdError = class extends Error {
|
|
30771
31403
|
constructor(runName, cwd) {
|
|
@@ -30778,17 +31410,17 @@ var MissingRunCwdError = class extends Error {
|
|
|
30778
31410
|
function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
|
|
30779
31411
|
if (!config.cwd) return void 0;
|
|
30780
31412
|
const cwd = resolve18(baseDir, config.cwd);
|
|
30781
|
-
if (!
|
|
31413
|
+
if (!existsSync68(cwd)) throw new MissingRunCwdError(config.name, cwd);
|
|
30782
31414
|
return cwd;
|
|
30783
31415
|
}
|
|
30784
31416
|
|
|
30785
31417
|
// src/commands/run/runCommandToCompletion.ts
|
|
30786
31418
|
import { spawn as spawn9 } from "child_process";
|
|
30787
|
-
import { existsSync as
|
|
31419
|
+
import { existsSync as existsSync70 } from "fs";
|
|
30788
31420
|
|
|
30789
31421
|
// src/commands/run/resolveCommand.ts
|
|
30790
31422
|
import { execFileSync as execFileSync16 } from "child_process";
|
|
30791
|
-
import { existsSync as
|
|
31423
|
+
import { existsSync as existsSync69 } from "fs";
|
|
30792
31424
|
import { dirname as dirname35, join as join85, resolve as resolve19 } from "path";
|
|
30793
31425
|
function resolveCommand2(command) {
|
|
30794
31426
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
@@ -30796,7 +31428,7 @@ function resolveCommand2(command) {
|
|
|
30796
31428
|
const gitPath = execFileSync16("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
30797
31429
|
const gitRoot = resolve19(dirname35(gitPath), "..");
|
|
30798
31430
|
const gitBash = join85(gitRoot, "bin", "bash.exe");
|
|
30799
|
-
if (
|
|
31431
|
+
if (existsSync69(gitBash)) return gitBash;
|
|
30800
31432
|
} catch {
|
|
30801
31433
|
return command;
|
|
30802
31434
|
}
|
|
@@ -30806,7 +31438,7 @@ function resolveCommand2(command) {
|
|
|
30806
31438
|
// src/commands/run/runCommandToCompletion.ts
|
|
30807
31439
|
function runCommandToCompletion(command, args, env, cwd, quiet) {
|
|
30808
31440
|
return new Promise((resolveResult) => {
|
|
30809
|
-
if (cwd && !
|
|
31441
|
+
if (cwd && !existsSync70(cwd)) {
|
|
30810
31442
|
resolveResult({
|
|
30811
31443
|
kind: "failed",
|
|
30812
31444
|
message: `Failed to execute command: cwd ${cwd} does not exist`
|
|
@@ -30852,6 +31484,15 @@ function runPreCommands(pre, cwd) {
|
|
|
30852
31484
|
}
|
|
30853
31485
|
}
|
|
30854
31486
|
|
|
31487
|
+
// src/commands/watch/toBuildOutcome.ts
|
|
31488
|
+
function toBuildOutcome(result) {
|
|
31489
|
+
if (result.kind === "failed")
|
|
31490
|
+
return { kind: "failed", exitCode: 1, output: result.message };
|
|
31491
|
+
if (result.exitCode !== 0)
|
|
31492
|
+
return { kind: "failed", exitCode: result.exitCode, output: result.output };
|
|
31493
|
+
return { kind: "built" };
|
|
31494
|
+
}
|
|
31495
|
+
|
|
30855
31496
|
// src/commands/watch/runWatchBuild.ts
|
|
30856
31497
|
async function runWatchBuild(entry) {
|
|
30857
31498
|
const config = findRunConfig(entry);
|
|
@@ -30863,18 +31504,15 @@ async function runWatchBuild(entry) {
|
|
|
30863
31504
|
return { kind: "failed", exitCode: 1, output: error.message };
|
|
30864
31505
|
}
|
|
30865
31506
|
if (config.pre) runPreCommands(config.pre, cwd);
|
|
30866
|
-
|
|
30867
|
-
|
|
30868
|
-
|
|
30869
|
-
|
|
30870
|
-
|
|
30871
|
-
|
|
31507
|
+
return toBuildOutcome(
|
|
31508
|
+
await runCommandToCompletion(
|
|
31509
|
+
config.command,
|
|
31510
|
+
[...config.args ?? [], ...resolveParams(config.params, [])],
|
|
31511
|
+
config.env,
|
|
31512
|
+
cwd,
|
|
31513
|
+
config.quiet
|
|
31514
|
+
)
|
|
30872
31515
|
);
|
|
30873
|
-
if (result.kind === "failed")
|
|
30874
|
-
return { kind: "failed", exitCode: 1, output: result.message };
|
|
30875
|
-
if (result.exitCode !== 0)
|
|
30876
|
-
return { kind: "failed", exitCode: result.exitCode, output: result.output };
|
|
30877
|
-
return { kind: "built" };
|
|
30878
31516
|
}
|
|
30879
31517
|
|
|
30880
31518
|
// src/commands/watch/reportBuildOrExit.ts
|
|
@@ -30889,6 +31527,25 @@ async function reportBuildOrExit(entry) {
|
|
|
30889
31527
|
process.exit(4);
|
|
30890
31528
|
}
|
|
30891
31529
|
|
|
31530
|
+
// src/commands/watch/runPostBuildSync.ts
|
|
31531
|
+
async function runPostBuildSync() {
|
|
31532
|
+
return toBuildOutcome(
|
|
31533
|
+
await runCommandToCompletion("assist", ["sync", "--yes"])
|
|
31534
|
+
);
|
|
31535
|
+
}
|
|
31536
|
+
|
|
31537
|
+
// src/commands/watch/reportSyncOrExit.ts
|
|
31538
|
+
async function reportSyncOrExit() {
|
|
31539
|
+
const outcome = await runPostBuildSync();
|
|
31540
|
+
if (outcome.kind === "built") {
|
|
31541
|
+
console.log("synced ~/.claude");
|
|
31542
|
+
return;
|
|
31543
|
+
}
|
|
31544
|
+
if (outcome.output.length > 0) process.stdout.write(outcome.output);
|
|
31545
|
+
console.error(`sync failed with exit code ${outcome.exitCode}`);
|
|
31546
|
+
process.exit(4);
|
|
31547
|
+
}
|
|
31548
|
+
|
|
30892
31549
|
// src/commands/watch/fetchQuietly.ts
|
|
30893
31550
|
import { execFileSync as execFileSync17 } from "child_process";
|
|
30894
31551
|
var MIN_FETCH_TIMEOUT_MS = 6e4;
|
|
@@ -31000,6 +31657,8 @@ ${buildWatchReport(outcome.from)}`);
|
|
|
31000
31657
|
await reportBuildOrExit(
|
|
31001
31658
|
typeof options2.build === "string" ? options2.build : DEFAULT_BUILD_ENTRY
|
|
31002
31659
|
);
|
|
31660
|
+
if (syncAdvice(changedPaths(outcome.from)).length > 0)
|
|
31661
|
+
await reportSyncOrExit();
|
|
31003
31662
|
}
|
|
31004
31663
|
process.exit(0);
|
|
31005
31664
|
}
|
|
@@ -31008,7 +31667,7 @@ ${buildWatchReport(outcome.from)}`);
|
|
|
31008
31667
|
function registerWatch(program2) {
|
|
31009
31668
|
const watchCommand = program2.command("watch").description("Wait on upstream movement for the current branch");
|
|
31010
31669
|
watchCommand.command("wait").description(
|
|
31011
|
-
"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)"
|
|
31670
|
+
"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)"
|
|
31012
31671
|
).option(
|
|
31013
31672
|
"--interval <duration>",
|
|
31014
31673
|
"How often to fetch after the fetch at startup (e.g. 30s, 2m)",
|
|
@@ -31022,7 +31681,7 @@ function registerWatch(program2) {
|
|
|
31022
31681
|
"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"
|
|
31023
31682
|
).option(
|
|
31024
31683
|
"--build [entry]",
|
|
31025
|
-
"After a successful pull, run this run entry (default auto-build); exit 4 with
|
|
31684
|
+
"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"
|
|
31026
31685
|
).action(
|
|
31027
31686
|
(options2) => watchWait(options2)
|
|
31028
31687
|
);
|
|
@@ -31036,7 +31695,7 @@ function registerWatch(program2) {
|
|
|
31036
31695
|
|
|
31037
31696
|
// src/commands/roam/auth.ts
|
|
31038
31697
|
import { randomBytes } from "crypto";
|
|
31039
|
-
import
|
|
31698
|
+
import chalk216 from "chalk";
|
|
31040
31699
|
|
|
31041
31700
|
// src/commands/roam/waitForCallback.ts
|
|
31042
31701
|
import { createServer as createServer3 } from "http";
|
|
@@ -31167,13 +31826,13 @@ async function auth() {
|
|
|
31167
31826
|
saveGlobalConfig(config);
|
|
31168
31827
|
const state = randomBytes(16).toString("hex");
|
|
31169
31828
|
console.log(
|
|
31170
|
-
|
|
31829
|
+
chalk216.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
31171
31830
|
);
|
|
31172
|
-
console.log(
|
|
31173
|
-
console.log(
|
|
31174
|
-
console.log(
|
|
31831
|
+
console.log(chalk216.white("http://localhost:14523/callback\n"));
|
|
31832
|
+
console.log(chalk216.blue("Opening browser for authorization..."));
|
|
31833
|
+
console.log(chalk216.dim("Waiting for authorization callback..."));
|
|
31175
31834
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
31176
|
-
console.log(
|
|
31835
|
+
console.log(chalk216.dim("Exchanging code for tokens..."));
|
|
31177
31836
|
const tokens = await exchangeToken({
|
|
31178
31837
|
code,
|
|
31179
31838
|
clientId,
|
|
@@ -31189,13 +31848,13 @@ async function auth() {
|
|
|
31189
31848
|
};
|
|
31190
31849
|
saveGlobalConfig(config);
|
|
31191
31850
|
console.log(
|
|
31192
|
-
|
|
31851
|
+
chalk216.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
31193
31852
|
);
|
|
31194
31853
|
}
|
|
31195
31854
|
|
|
31196
31855
|
// src/commands/roam/postRoamActivity.ts
|
|
31197
31856
|
import { execFileSync as execFileSync18 } from "child_process";
|
|
31198
|
-
import { readdirSync as readdirSync20, readFileSync as
|
|
31857
|
+
import { readdirSync as readdirSync20, readFileSync as readFileSync54, statSync as statSync11 } from "fs";
|
|
31199
31858
|
import { join as join86 } from "path";
|
|
31200
31859
|
function findPortFile(roamDir) {
|
|
31201
31860
|
let entries;
|
|
@@ -31221,7 +31880,7 @@ function postRoamActivity(app, event) {
|
|
|
31221
31880
|
if (!portFile) return;
|
|
31222
31881
|
let port;
|
|
31223
31882
|
try {
|
|
31224
|
-
port =
|
|
31883
|
+
port = readFileSync54(portFile, "utf8").trim();
|
|
31225
31884
|
} catch {
|
|
31226
31885
|
return;
|
|
31227
31886
|
}
|
|
@@ -31475,7 +32134,7 @@ function link2() {
|
|
|
31475
32134
|
}
|
|
31476
32135
|
|
|
31477
32136
|
// src/commands/run/remove.ts
|
|
31478
|
-
import { existsSync as
|
|
32137
|
+
import { existsSync as existsSync71, unlinkSync as unlinkSync21 } from "fs";
|
|
31479
32138
|
import { join as join88 } from "path";
|
|
31480
32139
|
function findRemoveIndex() {
|
|
31481
32140
|
const idx = process.argv.indexOf("remove");
|
|
@@ -31492,7 +32151,7 @@ function parseRemoveName() {
|
|
|
31492
32151
|
}
|
|
31493
32152
|
function deleteCommandFile(name) {
|
|
31494
32153
|
const filePath = join88(".claude", "commands", `${name}.md`);
|
|
31495
|
-
if (
|
|
32154
|
+
if (existsSync71(filePath)) {
|
|
31496
32155
|
unlinkSync21(filePath);
|
|
31497
32156
|
console.log(`Deleted command file: ${filePath}`);
|
|
31498
32157
|
}
|
|
@@ -31537,10 +32196,10 @@ function registerRun(program2) {
|
|
|
31537
32196
|
|
|
31538
32197
|
// src/commands/screenshot/index.ts
|
|
31539
32198
|
import { execSync as execSync60 } from "child_process";
|
|
31540
|
-
import { existsSync as
|
|
32199
|
+
import { existsSync as existsSync72, mkdirSync as mkdirSync31, unlinkSync as unlinkSync22, writeFileSync as writeFileSync46 } from "fs";
|
|
31541
32200
|
import { tmpdir as tmpdir8 } from "os";
|
|
31542
32201
|
import { join as join89, resolve as resolve20 } from "path";
|
|
31543
|
-
import
|
|
32202
|
+
import chalk217 from "chalk";
|
|
31544
32203
|
|
|
31545
32204
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
31546
32205
|
var captureWindowPs1 = `
|
|
@@ -31669,7 +32328,7 @@ Write-Output $OutputPath
|
|
|
31669
32328
|
|
|
31670
32329
|
// src/commands/screenshot/index.ts
|
|
31671
32330
|
function buildOutputPath(outputDir, processName) {
|
|
31672
|
-
if (!
|
|
32331
|
+
if (!existsSync72(outputDir)) {
|
|
31673
32332
|
mkdirSync31(outputDir, { recursive: true });
|
|
31674
32333
|
}
|
|
31675
32334
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -31691,13 +32350,13 @@ function screenshot(processName) {
|
|
|
31691
32350
|
const config = loadConfig();
|
|
31692
32351
|
const outputDir = resolve20(config.screenshot.outputDir);
|
|
31693
32352
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
31694
|
-
console.log(
|
|
32353
|
+
console.log(chalk217.gray(`Capturing window for process "${processName}" ...`));
|
|
31695
32354
|
try {
|
|
31696
32355
|
runPowerShellScript(processName, outputPath);
|
|
31697
|
-
console.log(
|
|
32356
|
+
console.log(chalk217.green(`Screenshot saved: ${outputPath}`));
|
|
31698
32357
|
} catch (error) {
|
|
31699
32358
|
const msg = error instanceof Error ? error.message : String(error);
|
|
31700
|
-
console.error(
|
|
32359
|
+
console.error(chalk217.red(`Failed to capture screenshot: ${msg}`));
|
|
31701
32360
|
process.exit(1);
|
|
31702
32361
|
}
|
|
31703
32362
|
}
|
|
@@ -31753,11 +32412,11 @@ function applyLine(result, pending, line) {
|
|
|
31753
32412
|
}
|
|
31754
32413
|
|
|
31755
32414
|
// src/commands/sessions/daemon/readDaemonPidFile.ts
|
|
31756
|
-
import { readFileSync as
|
|
32415
|
+
import { readFileSync as readFileSync55 } from "fs";
|
|
31757
32416
|
function readDaemonPidFile() {
|
|
31758
32417
|
try {
|
|
31759
32418
|
const pid = Number.parseInt(
|
|
31760
|
-
|
|
32419
|
+
readFileSync55(daemonPaths.pid, "utf8").trim(),
|
|
31761
32420
|
10
|
|
31762
32421
|
);
|
|
31763
32422
|
return Number.isInteger(pid) ? pid : void 0;
|
|
@@ -32014,12 +32673,12 @@ function toSessionRunInfo({
|
|
|
32014
32673
|
}
|
|
32015
32674
|
|
|
32016
32675
|
// src/commands/sessions/daemon/worktree/joinRefusal.ts
|
|
32017
|
-
import { existsSync as
|
|
32676
|
+
import { existsSync as existsSync73 } from "fs";
|
|
32018
32677
|
function joinRefusal(session) {
|
|
32019
32678
|
if (session.commandType === "run") return "a server run has no agent stream";
|
|
32020
32679
|
if (session.closing === true) return "the session is closing";
|
|
32021
32680
|
if (!session.cwd) return "the session has no working directory";
|
|
32022
|
-
if (!
|
|
32681
|
+
if (!existsSync73(session.cwd))
|
|
32023
32682
|
return "the session's workspace no longer exists";
|
|
32024
32683
|
return void 0;
|
|
32025
32684
|
}
|
|
@@ -32183,11 +32842,11 @@ function sessionBase(id, status3) {
|
|
|
32183
32842
|
}
|
|
32184
32843
|
|
|
32185
32844
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
32186
|
-
import { existsSync as
|
|
32845
|
+
import { existsSync as existsSync75 } from "fs";
|
|
32187
32846
|
import * as pty from "node-pty";
|
|
32188
32847
|
|
|
32189
32848
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
32190
|
-
import { chmodSync, existsSync as
|
|
32849
|
+
import { chmodSync, existsSync as existsSync74, statSync as statSync12 } from "fs";
|
|
32191
32850
|
import { createRequire as createRequire3 } from "module";
|
|
32192
32851
|
import path75 from "path";
|
|
32193
32852
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -32202,7 +32861,7 @@ function ensureSpawnHelperExecutable() {
|
|
|
32202
32861
|
`${process.platform}-${process.arch}`,
|
|
32203
32862
|
"spawn-helper"
|
|
32204
32863
|
);
|
|
32205
|
-
if (!
|
|
32864
|
+
if (!existsSync74(helper)) return;
|
|
32206
32865
|
const mode = statSync12(helper).mode;
|
|
32207
32866
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
32208
32867
|
}
|
|
@@ -32238,7 +32897,7 @@ function spawnPty(args, cwd, sessionId, extraEnv) {
|
|
|
32238
32897
|
});
|
|
32239
32898
|
}
|
|
32240
32899
|
function refuseMissingCwd(cwd, sessionId) {
|
|
32241
|
-
if (!cwd ||
|
|
32900
|
+
if (!cwd || existsSync75(cwd)) return;
|
|
32242
32901
|
daemonLog(
|
|
32243
32902
|
`${sessionId ? `session ${sessionId}` : "pty"} not spawned: working directory ${cwd} no longer exists`
|
|
32244
32903
|
);
|
|
@@ -32420,11 +33079,11 @@ function setStatus2(session, newStatus) {
|
|
|
32420
33079
|
}
|
|
32421
33080
|
|
|
32422
33081
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
32423
|
-
import { existsSync as
|
|
33082
|
+
import { existsSync as existsSync77 } from "fs";
|
|
32424
33083
|
import { basename as basename22 } from "path";
|
|
32425
33084
|
|
|
32426
33085
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
32427
|
-
import { existsSync as
|
|
33086
|
+
import { existsSync as existsSync76 } from "fs";
|
|
32428
33087
|
import { join as join92 } from "path";
|
|
32429
33088
|
|
|
32430
33089
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
@@ -32494,7 +33153,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
32494
33153
|
);
|
|
32495
33154
|
}
|
|
32496
33155
|
function strandedReason(worktreePath, cause) {
|
|
32497
|
-
if (!
|
|
33156
|
+
if (!existsSync76(join92(worktreePath, ".git")))
|
|
32498
33157
|
return "its .git link is already gone";
|
|
32499
33158
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
32500
33159
|
return "git no longer recognises it as a working tree";
|
|
@@ -32546,7 +33205,7 @@ function reason3(error) {
|
|
|
32546
33205
|
|
|
32547
33206
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
32548
33207
|
async function reapWorktree(worktreePath, force = false) {
|
|
32549
|
-
if (!
|
|
33208
|
+
if (!existsSync77(worktreePath)) {
|
|
32550
33209
|
forgetWorktree(worktreePath);
|
|
32551
33210
|
daemonLog(
|
|
32552
33211
|
`worktree ${worktreePath} already gone; its record was forgotten`
|
|
@@ -32571,7 +33230,7 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
32571
33230
|
}
|
|
32572
33231
|
function owningClone(worktreePath) {
|
|
32573
33232
|
const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
|
|
32574
|
-
if (recorded &&
|
|
33233
|
+
if (recorded && existsSync77(recorded)) return recorded;
|
|
32575
33234
|
const detected = mainWorktree(worktreePath);
|
|
32576
33235
|
if (detected) return detected;
|
|
32577
33236
|
daemonLog(
|
|
@@ -32702,12 +33361,12 @@ function closeGateApplies(sessions, session) {
|
|
|
32702
33361
|
}
|
|
32703
33362
|
|
|
32704
33363
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
32705
|
-
import { existsSync as
|
|
33364
|
+
import { existsSync as existsSync78, watch } from "fs";
|
|
32706
33365
|
var DEBOUNCE_MS = 500;
|
|
32707
33366
|
var POLL_MS = 3e4;
|
|
32708
33367
|
function watchGitState(cwd, onChange) {
|
|
32709
33368
|
const common = gitCommonDir(cwd);
|
|
32710
|
-
if (!common || !
|
|
33369
|
+
if (!common || !existsSync78(common)) return void 0;
|
|
32711
33370
|
const watchers = [
|
|
32712
33371
|
watchGitDir(common, onChange),
|
|
32713
33372
|
pollGitState(cwd, onChange)
|
|
@@ -32882,9 +33541,9 @@ function flushPhaseActiveMs(session) {
|
|
|
32882
33541
|
if (await persistPhaseActiveMs(phase.itemId, phase.phaseIdx, delta))
|
|
32883
33542
|
session.activeMsFlushedForStretch = { since, ms: flushed + delta };
|
|
32884
33543
|
};
|
|
32885
|
-
const
|
|
32886
|
-
session.activeMsFlushChain =
|
|
32887
|
-
return
|
|
33544
|
+
const chain2 = (session.activeMsFlushChain ?? Promise.resolve()).then(run4);
|
|
33545
|
+
session.activeMsFlushChain = chain2;
|
|
33546
|
+
return chain2;
|
|
32888
33547
|
}
|
|
32889
33548
|
|
|
32890
33549
|
// src/commands/sessions/daemon/stripReplayQueries.ts
|
|
@@ -33182,10 +33841,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
33182
33841
|
}
|
|
33183
33842
|
|
|
33184
33843
|
// src/commands/sessions/daemon/exitReason.ts
|
|
33185
|
-
import { existsSync as
|
|
33844
|
+
import { existsSync as existsSync79 } from "fs";
|
|
33186
33845
|
import { resolve as resolve21 } from "path";
|
|
33187
33846
|
function exitDetail(session) {
|
|
33188
|
-
if (session.cwd && !
|
|
33847
|
+
if (session.cwd && !existsSync79(session.cwd))
|
|
33189
33848
|
return `working directory ${session.cwd} no longer exists`;
|
|
33190
33849
|
return missingRunConfigCwd(session);
|
|
33191
33850
|
}
|
|
@@ -33199,7 +33858,7 @@ function missingRunConfigCwd(session) {
|
|
|
33199
33858
|
const config = resolveRunConfig(session.runName, dir);
|
|
33200
33859
|
if (!config?.cwd) return void 0;
|
|
33201
33860
|
const configured = resolve21(runConfigBaseDirFrom(dir), config.cwd);
|
|
33202
|
-
if (
|
|
33861
|
+
if (existsSync79(configured)) return void 0;
|
|
33203
33862
|
return `run config "${config.name}": cwd ${configured} does not exist`;
|
|
33204
33863
|
}
|
|
33205
33864
|
|
|
@@ -33240,7 +33899,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
33240
33899
|
}
|
|
33241
33900
|
|
|
33242
33901
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
33243
|
-
import { existsSync as
|
|
33902
|
+
import { existsSync as existsSync80, mkdirSync as mkdirSync32, watch as watch2 } from "fs";
|
|
33244
33903
|
import { dirname as dirname37 } from "path";
|
|
33245
33904
|
|
|
33246
33905
|
// src/commands/sessions/daemon/applyActivityToSession.ts
|
|
@@ -33326,7 +33985,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
33326
33985
|
if (timer) clearTimeout(timer);
|
|
33327
33986
|
timer = setTimeout(read2, DEBOUNCE_MS2);
|
|
33328
33987
|
});
|
|
33329
|
-
if (
|
|
33988
|
+
if (existsSync80(path80)) read2();
|
|
33330
33989
|
}
|
|
33331
33990
|
function refreshActivity(session) {
|
|
33332
33991
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -34948,7 +35607,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
34948
35607
|
}
|
|
34949
35608
|
|
|
34950
35609
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
34951
|
-
import { existsSync as
|
|
35610
|
+
import { existsSync as existsSync83 } from "fs";
|
|
34952
35611
|
import { basename as basename24 } from "path";
|
|
34953
35612
|
|
|
34954
35613
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
@@ -35003,9 +35662,9 @@ function bindResumedWorktree(session, cwd, notify2) {
|
|
|
35003
35662
|
}
|
|
35004
35663
|
|
|
35005
35664
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
35006
|
-
import { existsSync as
|
|
35665
|
+
import { existsSync as existsSync82 } from "fs";
|
|
35007
35666
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
35008
|
-
if (!
|
|
35667
|
+
if (!existsSync82(clone)) {
|
|
35009
35668
|
for (const { path: path80 } of paths) forgetWorktree(path80);
|
|
35010
35669
|
daemonLog(
|
|
35011
35670
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
@@ -35171,7 +35830,7 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
|
35171
35830
|
);
|
|
35172
35831
|
continue;
|
|
35173
35832
|
}
|
|
35174
|
-
if (!
|
|
35833
|
+
if (!existsSync83(path80)) {
|
|
35175
35834
|
logVanishedTree(sessions, path80);
|
|
35176
35835
|
vanished.set(clone, [
|
|
35177
35836
|
...vanished.get(clone) ?? [],
|
|
@@ -35788,14 +36447,14 @@ async function defaultConnect() {
|
|
|
35788
36447
|
}
|
|
35789
36448
|
|
|
35790
36449
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
35791
|
-
import { existsSync as
|
|
36450
|
+
import { existsSync as existsSync84, readFileSync as readFileSync57 } from "fs";
|
|
35792
36451
|
import { posix as posix3 } from "path";
|
|
35793
36452
|
function hasPersistedWindowsSessions() {
|
|
35794
36453
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
35795
36454
|
if (!sessionsFile) return false;
|
|
35796
36455
|
try {
|
|
35797
|
-
if (!
|
|
35798
|
-
const data = JSON.parse(
|
|
36456
|
+
if (!existsSync84(sessionsFile)) return false;
|
|
36457
|
+
const data = JSON.parse(readFileSync57(sessionsFile, "utf8"));
|
|
35799
36458
|
return Array.isArray(data) && data.length > 0;
|
|
35800
36459
|
} catch (error) {
|
|
35801
36460
|
const message3 = error instanceof Error ? error.message : String(error);
|
|
@@ -36529,7 +37188,7 @@ function setAutoAdvance(sessions, id, enabled) {
|
|
|
36529
37188
|
}
|
|
36530
37189
|
|
|
36531
37190
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
36532
|
-
import { existsSync as
|
|
37191
|
+
import { existsSync as existsSync87 } from "fs";
|
|
36533
37192
|
|
|
36534
37193
|
// src/commands/sessions/daemon/resumeSession.ts
|
|
36535
37194
|
function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
@@ -36560,10 +37219,10 @@ function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
|
36560
37219
|
}
|
|
36561
37220
|
|
|
36562
37221
|
// src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
|
|
36563
|
-
import { existsSync as
|
|
37222
|
+
import { existsSync as existsSync86 } from "fs";
|
|
36564
37223
|
|
|
36565
37224
|
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
36566
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
37225
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync85, mkdirSync as mkdirSync34 } from "fs";
|
|
36567
37226
|
import { join as join94 } from "path";
|
|
36568
37227
|
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
36569
37228
|
const dir = projectDirForCwd(toCwd);
|
|
@@ -36574,7 +37233,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
36574
37233
|
return;
|
|
36575
37234
|
}
|
|
36576
37235
|
const dest = join94(dir, `${claudeSessionId}.jsonl`);
|
|
36577
|
-
if (
|
|
37236
|
+
if (existsSync85(dest)) {
|
|
36578
37237
|
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
36579
37238
|
return;
|
|
36580
37239
|
}
|
|
@@ -36625,7 +37284,7 @@ function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name, harness
|
|
|
36625
37284
|
}
|
|
36626
37285
|
function cloneForReapedTree(missingCwd) {
|
|
36627
37286
|
const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
|
|
36628
|
-
if (!clone || !
|
|
37287
|
+
if (!clone || !existsSync86(clone))
|
|
36629
37288
|
throw new Error(
|
|
36630
37289
|
`working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
|
|
36631
37290
|
);
|
|
@@ -36634,7 +37293,7 @@ function cloneForReapedTree(missingCwd) {
|
|
|
36634
37293
|
|
|
36635
37294
|
// src/commands/sessions/daemon/worktree/resumeInTree.ts
|
|
36636
37295
|
function resumeInTree(ctx, sessionId, cwd, name, harness) {
|
|
36637
|
-
if (!
|
|
37296
|
+
if (!existsSync87(cwd))
|
|
36638
37297
|
return resumeInReplacementTree(ctx, sessionId, cwd, name, harness);
|
|
36639
37298
|
const id = ctx.spawnWith(
|
|
36640
37299
|
(sid) => resumeSession(sid, sessionId, cwd, name, void 0, harness)
|
|
@@ -37213,7 +37872,7 @@ function handleConnection(socket, manager) {
|
|
|
37213
37872
|
import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync47 } from "fs";
|
|
37214
37873
|
|
|
37215
37874
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
37216
|
-
import { readFileSync as
|
|
37875
|
+
import { readFileSync as readFileSync58 } from "fs";
|
|
37217
37876
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
37218
37877
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
37219
37878
|
const timer = setInterval(() => {
|
|
@@ -37224,7 +37883,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
37224
37883
|
}
|
|
37225
37884
|
function ownsPidFile() {
|
|
37226
37885
|
try {
|
|
37227
|
-
return
|
|
37886
|
+
return readFileSync58(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
37228
37887
|
} catch {
|
|
37229
37888
|
return false;
|
|
37230
37889
|
}
|
|
@@ -37474,7 +38133,7 @@ function registerSetStatusCommand(cmd) {
|
|
|
37474
38133
|
|
|
37475
38134
|
// src/commands/sessions/summarise/index.ts
|
|
37476
38135
|
import * as fs56 from "fs";
|
|
37477
|
-
import
|
|
38136
|
+
import chalk218 from "chalk";
|
|
37478
38137
|
|
|
37479
38138
|
// src/commands/sessions/summarise/shared.ts
|
|
37480
38139
|
import * as fs55 from "fs";
|
|
@@ -37533,22 +38192,22 @@ ${firstMessage}`);
|
|
|
37533
38192
|
async function summarise2(options2) {
|
|
37534
38193
|
const files = await discoverSessionFiles();
|
|
37535
38194
|
if (files.length === 0) {
|
|
37536
|
-
console.log(
|
|
38195
|
+
console.log(chalk218.yellow("No sessions found."));
|
|
37537
38196
|
return;
|
|
37538
38197
|
}
|
|
37539
38198
|
const toProcess = selectCandidates(files, options2);
|
|
37540
38199
|
if (toProcess.length === 0) {
|
|
37541
|
-
console.log(
|
|
38200
|
+
console.log(chalk218.green("All sessions already summarised."));
|
|
37542
38201
|
return;
|
|
37543
38202
|
}
|
|
37544
38203
|
console.log(
|
|
37545
|
-
|
|
38204
|
+
chalk218.cyan(
|
|
37546
38205
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
37547
38206
|
)
|
|
37548
38207
|
);
|
|
37549
38208
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
37550
38209
|
console.log(
|
|
37551
|
-
|
|
38210
|
+
chalk218.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk218.yellow(`, ${failed2} skipped`) : "")
|
|
37552
38211
|
);
|
|
37553
38212
|
}
|
|
37554
38213
|
function selectCandidates(files, options2) {
|
|
@@ -37568,16 +38227,16 @@ function processSessions(files) {
|
|
|
37568
38227
|
let failed2 = 0;
|
|
37569
38228
|
for (let i = 0; i < files.length; i++) {
|
|
37570
38229
|
const file = files[i];
|
|
37571
|
-
process.stdout.write(
|
|
38230
|
+
process.stdout.write(chalk218.dim(` [${i + 1}/${files.length}] `));
|
|
37572
38231
|
const summary = summariseSession(file);
|
|
37573
38232
|
if (summary) {
|
|
37574
38233
|
writeSummary(file, summary);
|
|
37575
38234
|
succeeded++;
|
|
37576
|
-
process.stdout.write(`${
|
|
38235
|
+
process.stdout.write(`${chalk218.green("\u2713")} ${summary}
|
|
37577
38236
|
`);
|
|
37578
38237
|
} else {
|
|
37579
38238
|
failed2++;
|
|
37580
|
-
process.stdout.write(` ${
|
|
38239
|
+
process.stdout.write(` ${chalk218.yellow("skip")}
|
|
37581
38240
|
`);
|
|
37582
38241
|
}
|
|
37583
38242
|
}
|
|
@@ -37598,7 +38257,7 @@ function registerSessions(program2) {
|
|
|
37598
38257
|
}
|
|
37599
38258
|
|
|
37600
38259
|
// src/commands/statusLine.ts
|
|
37601
|
-
import
|
|
38260
|
+
import chalk220 from "chalk";
|
|
37602
38261
|
|
|
37603
38262
|
// src/shared/contextLevel.ts
|
|
37604
38263
|
function contextLevel(pct) {
|
|
@@ -37608,7 +38267,7 @@ function contextLevel(pct) {
|
|
|
37608
38267
|
}
|
|
37609
38268
|
|
|
37610
38269
|
// src/commands/buildLimitsSegment.ts
|
|
37611
|
-
import
|
|
38270
|
+
import chalk219 from "chalk";
|
|
37612
38271
|
|
|
37613
38272
|
// src/shared/rateLimitLevel.ts
|
|
37614
38273
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -37646,9 +38305,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
37646
38305
|
|
|
37647
38306
|
// src/commands/buildLimitsSegment.ts
|
|
37648
38307
|
var LEVEL_COLOR = {
|
|
37649
|
-
ok:
|
|
37650
|
-
warn:
|
|
37651
|
-
over:
|
|
38308
|
+
ok: chalk219.green,
|
|
38309
|
+
warn: chalk219.yellow,
|
|
38310
|
+
over: chalk219.red
|
|
37652
38311
|
};
|
|
37653
38312
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
37654
38313
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -37679,7 +38338,7 @@ function buildLimitsSegment(rateLimits) {
|
|
|
37679
38338
|
}
|
|
37680
38339
|
|
|
37681
38340
|
// src/commands/readGitBranch.ts
|
|
37682
|
-
import { readFileSync as
|
|
38341
|
+
import { readFileSync as readFileSync60, statSync as statSync15 } from "fs";
|
|
37683
38342
|
import { isAbsolute as isAbsolute4, join as join95, resolve as resolve22 } from "path";
|
|
37684
38343
|
function resolveGitDir(cwd) {
|
|
37685
38344
|
const dotGit = join95(cwd, ".git");
|
|
@@ -37694,7 +38353,7 @@ function resolveGitDir(cwd) {
|
|
|
37694
38353
|
}
|
|
37695
38354
|
let contents;
|
|
37696
38355
|
try {
|
|
37697
|
-
contents =
|
|
38356
|
+
contents = readFileSync60(dotGit, "utf8");
|
|
37698
38357
|
} catch {
|
|
37699
38358
|
return null;
|
|
37700
38359
|
}
|
|
@@ -37712,7 +38371,7 @@ function readGitBranch(cwd) {
|
|
|
37712
38371
|
}
|
|
37713
38372
|
let head;
|
|
37714
38373
|
try {
|
|
37715
|
-
head =
|
|
38374
|
+
head = readFileSync60(join95(gitDir, "HEAD"), "utf8");
|
|
37716
38375
|
} catch {
|
|
37717
38376
|
return null;
|
|
37718
38377
|
}
|
|
@@ -37744,7 +38403,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
|
|
|
37744
38403
|
}
|
|
37745
38404
|
|
|
37746
38405
|
// src/commands/statusLine.ts
|
|
37747
|
-
|
|
38406
|
+
chalk220.level = 3;
|
|
37748
38407
|
function formatNumber(num) {
|
|
37749
38408
|
return num.toLocaleString("en-US");
|
|
37750
38409
|
}
|
|
@@ -37752,9 +38411,9 @@ function colorizePercent(pct) {
|
|
|
37752
38411
|
const label2 = `${Math.round(pct)}%`;
|
|
37753
38412
|
switch (contextLevel(pct)) {
|
|
37754
38413
|
case "red":
|
|
37755
|
-
return
|
|
38414
|
+
return chalk220.red(label2);
|
|
37756
38415
|
case "yellow":
|
|
37757
|
-
return
|
|
38416
|
+
return chalk220.yellow(label2);
|
|
37758
38417
|
default:
|
|
37759
38418
|
return label2;
|
|
37760
38419
|
}
|
|
@@ -37767,7 +38426,7 @@ async function statusLine() {
|
|
|
37767
38426
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
37768
38427
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
37769
38428
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
37770
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
38429
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk220.cyan(branch2)} | ` : "";
|
|
37771
38430
|
console.log(
|
|
37772
38431
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
37773
38432
|
);
|
|
@@ -37837,10 +38496,10 @@ async function update2() {
|
|
|
37837
38496
|
}
|
|
37838
38497
|
|
|
37839
38498
|
// src/reportCliError.ts
|
|
37840
|
-
import
|
|
38499
|
+
import chalk221 from "chalk";
|
|
37841
38500
|
function reportCliError(error) {
|
|
37842
|
-
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError) {
|
|
37843
|
-
console.error(
|
|
38501
|
+
if (error instanceof InvalidItemIdError || error instanceof AmbiguousRepoConfigError || error instanceof UnknownRepoConfigError || error instanceof MissingRunCwdError || error instanceof MiroExtractError) {
|
|
38502
|
+
console.error(chalk221.red(error.message));
|
|
37844
38503
|
} else {
|
|
37845
38504
|
console.error(error);
|
|
37846
38505
|
}
|
|
@@ -37883,6 +38542,7 @@ registerGithub(program);
|
|
|
37883
38542
|
registerHandover(program);
|
|
37884
38543
|
registerJira(program);
|
|
37885
38544
|
registerMermaid(program);
|
|
38545
|
+
registerMiro(program);
|
|
37886
38546
|
registerPrs(program);
|
|
37887
38547
|
registerRoam(program);
|
|
37888
38548
|
registerBacklog(program);
|