@staff0rd/assist 0.174.2 → 0.176.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 +5 -0
- package/allowed.cli-writes +3 -0
- package/claude/commands/devlog.md +19 -0
- package/claude/commands/refine.md +74 -0
- package/dist/allowed.cli-writes +3 -0
- package/dist/index.js +770 -514
- 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.176.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -84,7 +84,7 @@ var package_default = {
|
|
|
84
84
|
};
|
|
85
85
|
|
|
86
86
|
// src/commands/backlog/next.ts
|
|
87
|
-
import
|
|
87
|
+
import chalk8 from "chalk";
|
|
88
88
|
import enquirer2 from "enquirer";
|
|
89
89
|
|
|
90
90
|
// src/shared/exitOnCancel.ts
|
|
@@ -688,8 +688,33 @@ function printVerboseDetails(item) {
|
|
|
688
688
|
console.log();
|
|
689
689
|
}
|
|
690
690
|
|
|
691
|
+
// src/commands/backlog/findResumable.ts
|
|
692
|
+
function findResumable(items) {
|
|
693
|
+
return items.find(
|
|
694
|
+
(i) => i.status === "in-progress" && i.plan && !isLockedByOther(i.id) && !isBlocked(i, items)
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// src/commands/backlog/findUnblockedTodos.ts
|
|
699
|
+
import chalk3 from "chalk";
|
|
700
|
+
function findUnblockedTodos(items) {
|
|
701
|
+
const todo = items.filter((i) => i.status === "todo");
|
|
702
|
+
if (todo.length === 0) {
|
|
703
|
+
console.log(chalk3.green("All backlog items complete."));
|
|
704
|
+
return void 0;
|
|
705
|
+
}
|
|
706
|
+
const unblocked = todo.filter((i) => !isBlocked(i, items));
|
|
707
|
+
if (unblocked.length === 0) {
|
|
708
|
+
console.log(
|
|
709
|
+
chalk3.yellow("All remaining todo items are blocked by dependencies.")
|
|
710
|
+
);
|
|
711
|
+
return void 0;
|
|
712
|
+
}
|
|
713
|
+
return unblocked;
|
|
714
|
+
}
|
|
715
|
+
|
|
691
716
|
// src/commands/backlog/run.ts
|
|
692
|
-
import
|
|
717
|
+
import chalk7 from "chalk";
|
|
693
718
|
|
|
694
719
|
// src/commands/backlog/buildCommentLines.ts
|
|
695
720
|
function buildCommentLines(comments2) {
|
|
@@ -804,11 +829,11 @@ function buildReviewPhase() {
|
|
|
804
829
|
}
|
|
805
830
|
|
|
806
831
|
// src/commands/backlog/executePhase.ts
|
|
807
|
-
import
|
|
832
|
+
import chalk5 from "chalk";
|
|
808
833
|
|
|
809
834
|
// src/commands/backlog/resolvePhaseResult.ts
|
|
810
835
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2 } from "fs";
|
|
811
|
-
import
|
|
836
|
+
import chalk4 from "chalk";
|
|
812
837
|
|
|
813
838
|
// src/commands/backlog/handleIncompletePhase.ts
|
|
814
839
|
import enquirer from "enquirer";
|
|
@@ -859,7 +884,7 @@ async function resolvePhaseResult(phaseIndex, itemId) {
|
|
|
859
884
|
return action === "skip" ? 1 : 0;
|
|
860
885
|
}
|
|
861
886
|
cleanupSignal();
|
|
862
|
-
console.log(
|
|
887
|
+
console.log(chalk4.green(`
|
|
863
888
|
Phase ${phaseIndex + 1} completed.`));
|
|
864
889
|
return 1;
|
|
865
890
|
}
|
|
@@ -917,7 +942,7 @@ function stopWatching() {
|
|
|
917
942
|
async function executePhase(item, phaseIndex, phases, spawnOptions) {
|
|
918
943
|
const phase = phases[phaseIndex];
|
|
919
944
|
console.log(
|
|
920
|
-
|
|
945
|
+
chalk5.bold(
|
|
921
946
|
`
|
|
922
947
|
--- Phase ${phaseIndex + 1}/${phases.length}: ${phase.name} ---
|
|
923
948
|
`
|
|
@@ -936,7 +961,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions) {
|
|
|
936
961
|
}
|
|
937
962
|
|
|
938
963
|
// src/commands/backlog/prepareRun.ts
|
|
939
|
-
import
|
|
964
|
+
import chalk6 from "chalk";
|
|
940
965
|
|
|
941
966
|
// src/commands/backlog/resolvePlan.ts
|
|
942
967
|
function resolvePlan(item) {
|
|
@@ -959,13 +984,13 @@ function prepareRun(id) {
|
|
|
959
984
|
const plan2 = resolvePlan(item);
|
|
960
985
|
const startPhase = item.currentPhase ?? 0;
|
|
961
986
|
if (item.status === "done") {
|
|
962
|
-
console.log(
|
|
987
|
+
console.log(chalk6.green(`Already done: #${id}: ${item.name}`));
|
|
963
988
|
return void 0;
|
|
964
989
|
}
|
|
965
990
|
if (startPhase > plan2.length) {
|
|
966
991
|
setStatus(id, "done");
|
|
967
992
|
console.log(
|
|
968
|
-
|
|
993
|
+
chalk6.green(`All phases already complete for #${id}: ${item.name}`)
|
|
969
994
|
);
|
|
970
995
|
return void 0;
|
|
971
996
|
}
|
|
@@ -990,12 +1015,12 @@ async function run(id, spawnOptions) {
|
|
|
990
1015
|
}
|
|
991
1016
|
}
|
|
992
1017
|
function logProgress(id, name, startPhase, total) {
|
|
993
|
-
console.log(
|
|
1018
|
+
console.log(chalk7.bold(`Running plan for #${id}: ${name}`));
|
|
994
1019
|
if (startPhase > 0) {
|
|
995
|
-
console.log(
|
|
1020
|
+
console.log(chalk7.dim(`Resuming from phase ${startPhase + 1}/${total}
|
|
996
1021
|
`));
|
|
997
1022
|
} else {
|
|
998
|
-
console.log(
|
|
1023
|
+
console.log(chalk7.dim(`${total} phase(s)
|
|
999
1024
|
`));
|
|
1000
1025
|
}
|
|
1001
1026
|
}
|
|
@@ -1026,14 +1051,9 @@ async function runReview(item, plan2, spawnOptions) {
|
|
|
1026
1051
|
}
|
|
1027
1052
|
|
|
1028
1053
|
// src/commands/backlog/next.ts
|
|
1029
|
-
function findResumable(items) {
|
|
1030
|
-
return items.find(
|
|
1031
|
-
(i) => i.status === "in-progress" && i.plan && !isLockedByOther(i.id) && !isBlocked(i, items)
|
|
1032
|
-
);
|
|
1033
|
-
}
|
|
1034
1054
|
function toChoice(item, items) {
|
|
1035
1055
|
const name = `${typeLabel(item.type)} #${item.id}: ${item.name}`;
|
|
1036
|
-
return isBlocked(item, items) ? { name, disabled:
|
|
1056
|
+
return isBlocked(item, items) ? { name, disabled: chalk8.red("[blocked]") } : { name };
|
|
1037
1057
|
}
|
|
1038
1058
|
async function selectItem(todo, items) {
|
|
1039
1059
|
const { selected } = await exitOnCancel(
|
|
@@ -1046,32 +1066,31 @@ async function selectItem(todo, items) {
|
|
|
1046
1066
|
);
|
|
1047
1067
|
return selected.match(/#(\d+)/)?.[1] ?? "";
|
|
1048
1068
|
}
|
|
1049
|
-
async function pickItem(items) {
|
|
1069
|
+
async function pickItem(items, firstPick = false) {
|
|
1050
1070
|
const resumable = findResumable(items);
|
|
1051
1071
|
if (resumable) {
|
|
1052
1072
|
console.log(
|
|
1053
|
-
|
|
1073
|
+
chalk8.bold(
|
|
1054
1074
|
`Resuming in-progress item #${resumable.id}: ${resumable.name}`
|
|
1055
1075
|
)
|
|
1056
1076
|
);
|
|
1057
1077
|
return String(resumable.id);
|
|
1058
1078
|
}
|
|
1059
|
-
const
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
console.log(
|
|
1066
|
-
chalk7.yellow("All remaining todo items are blocked by dependencies.")
|
|
1067
|
-
);
|
|
1068
|
-
return void 0;
|
|
1079
|
+
const unblocked = findUnblockedTodos(items);
|
|
1080
|
+
if (!unblocked) return void 0;
|
|
1081
|
+
if (firstPick && unblocked.length === 1) {
|
|
1082
|
+
const item = unblocked[0];
|
|
1083
|
+
console.log(chalk8.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
1084
|
+
return String(item.id);
|
|
1069
1085
|
}
|
|
1086
|
+
const todo = items.filter((i) => i.status === "todo");
|
|
1070
1087
|
return selectItem(todo, items);
|
|
1071
1088
|
}
|
|
1072
1089
|
async function next(options2) {
|
|
1090
|
+
let firstPick = true;
|
|
1073
1091
|
while (true) {
|
|
1074
|
-
const id = await pickItem(loadBacklog());
|
|
1092
|
+
const id = await pickItem(loadBacklog(), firstPick);
|
|
1093
|
+
firstPick = false;
|
|
1075
1094
|
if (id === void 0) return;
|
|
1076
1095
|
const completed = await run(id, options2);
|
|
1077
1096
|
if (!completed) return;
|
|
@@ -1079,7 +1098,7 @@ async function next(options2) {
|
|
|
1079
1098
|
}
|
|
1080
1099
|
|
|
1081
1100
|
// src/commands/backlog/phaseDone.ts
|
|
1082
|
-
import
|
|
1101
|
+
import chalk9 from "chalk";
|
|
1083
1102
|
|
|
1084
1103
|
// src/commands/backlog/addComment.ts
|
|
1085
1104
|
function addComment(item, text, phase) {
|
|
@@ -1113,7 +1132,7 @@ function phaseDone(id, phase, summary) {
|
|
|
1113
1132
|
});
|
|
1114
1133
|
const result = loadAndFindItem(id);
|
|
1115
1134
|
if (result?.item.status === "done") {
|
|
1116
|
-
console.log(
|
|
1135
|
+
console.log(chalk9.dim(`Item #${id} already done, skipping phase advance.`));
|
|
1117
1136
|
return;
|
|
1118
1137
|
}
|
|
1119
1138
|
if (result) {
|
|
@@ -1121,23 +1140,23 @@ function phaseDone(id, phase, summary) {
|
|
|
1121
1140
|
saveBacklog(result.items);
|
|
1122
1141
|
}
|
|
1123
1142
|
setCurrentPhase(id, phaseIndex + 1);
|
|
1124
|
-
console.log(
|
|
1143
|
+
console.log(chalk9.green(`Phase ${phase} of item #${id} marked as complete.`));
|
|
1125
1144
|
}
|
|
1126
1145
|
|
|
1127
1146
|
// src/commands/backlog/plan.ts
|
|
1128
|
-
import
|
|
1147
|
+
import chalk10 from "chalk";
|
|
1129
1148
|
function plan(id) {
|
|
1130
1149
|
const result = loadAndFindItem(id);
|
|
1131
1150
|
if (!result) return;
|
|
1132
1151
|
const { item } = result;
|
|
1133
1152
|
if (!item.plan || item.plan.length === 0) {
|
|
1134
|
-
console.log(
|
|
1153
|
+
console.log(chalk10.dim("No plan defined for this item."));
|
|
1135
1154
|
return;
|
|
1136
1155
|
}
|
|
1137
|
-
console.log(
|
|
1156
|
+
console.log(chalk10.bold(item.name));
|
|
1138
1157
|
console.log();
|
|
1139
1158
|
for (const [i, phase] of item.plan.entries()) {
|
|
1140
|
-
console.log(`${
|
|
1159
|
+
console.log(`${chalk10.bold(`Phase ${i + 1}:`)} ${phase.name}`);
|
|
1141
1160
|
for (const task of phase.tasks) {
|
|
1142
1161
|
console.log(` - ${task.task}`);
|
|
1143
1162
|
}
|
|
@@ -1146,34 +1165,34 @@ function plan(id) {
|
|
|
1146
1165
|
}
|
|
1147
1166
|
|
|
1148
1167
|
// src/commands/backlog/show/index.ts
|
|
1149
|
-
import
|
|
1168
|
+
import chalk14 from "chalk";
|
|
1150
1169
|
|
|
1151
1170
|
// src/commands/backlog/formatComment.ts
|
|
1152
|
-
import
|
|
1171
|
+
import chalk11 from "chalk";
|
|
1153
1172
|
function formatComment(entry) {
|
|
1154
|
-
const tag = entry.type === "summary" ?
|
|
1155
|
-
const phase = entry.phase !== void 0 ?
|
|
1156
|
-
const time =
|
|
1173
|
+
const tag = entry.type === "summary" ? chalk11.magenta("[summary]") : chalk11.cyan("[comment]");
|
|
1174
|
+
const phase = entry.phase !== void 0 ? chalk11.dim(` (phase ${entry.phase + 1})`) : "";
|
|
1175
|
+
const time = chalk11.dim(entry.timestamp);
|
|
1157
1176
|
return `${tag}${phase} ${time}
|
|
1158
1177
|
${entry.text}`;
|
|
1159
1178
|
}
|
|
1160
1179
|
|
|
1161
1180
|
// src/commands/backlog/show/printLinks.ts
|
|
1162
|
-
import
|
|
1181
|
+
import chalk12 from "chalk";
|
|
1163
1182
|
function printLinks(item, items) {
|
|
1164
1183
|
const links = item.links ?? [];
|
|
1165
1184
|
if (links.length === 0) return;
|
|
1166
|
-
console.log(
|
|
1185
|
+
console.log(chalk12.bold("Links"));
|
|
1167
1186
|
for (const link2 of links) {
|
|
1168
1187
|
const target = items.find((i) => i.id === link2.targetId);
|
|
1169
|
-
const typeLabel2 = link2.type === "depends-on" ?
|
|
1188
|
+
const typeLabel2 = link2.type === "depends-on" ? chalk12.red("depends-on") : chalk12.blue("relates-to");
|
|
1170
1189
|
if (target) {
|
|
1171
1190
|
console.log(
|
|
1172
|
-
` ${typeLabel2} #${target.id} ${target.name} ${
|
|
1191
|
+
` ${typeLabel2} #${target.id} ${target.name} ${chalk12.dim(`(${target.status})`)}`
|
|
1173
1192
|
);
|
|
1174
1193
|
} else {
|
|
1175
1194
|
console.log(
|
|
1176
|
-
` ${typeLabel2} #${link2.targetId} ${
|
|
1195
|
+
` ${typeLabel2} #${link2.targetId} ${chalk12.dim("(not found)")}`
|
|
1177
1196
|
);
|
|
1178
1197
|
}
|
|
1179
1198
|
}
|
|
@@ -1181,15 +1200,15 @@ function printLinks(item, items) {
|
|
|
1181
1200
|
}
|
|
1182
1201
|
|
|
1183
1202
|
// src/commands/backlog/show/printPhaseTasks.ts
|
|
1184
|
-
import
|
|
1203
|
+
import chalk13 from "chalk";
|
|
1185
1204
|
function printPhaseTasks(phase) {
|
|
1186
1205
|
for (const task of phase.tasks) {
|
|
1187
1206
|
console.log(` - ${task.task}`);
|
|
1188
1207
|
}
|
|
1189
1208
|
if (phase.manualChecks && phase.manualChecks.length > 0) {
|
|
1190
|
-
console.log(` ${
|
|
1209
|
+
console.log(` ${chalk13.dim("Manual checks:")}`);
|
|
1191
1210
|
for (const check2 of phase.manualChecks) {
|
|
1192
|
-
console.log(` ${
|
|
1211
|
+
console.log(` ${chalk13.dim(`- ${check2}`)}`);
|
|
1193
1212
|
}
|
|
1194
1213
|
}
|
|
1195
1214
|
}
|
|
@@ -1197,7 +1216,7 @@ function printPhaseTasks(phase) {
|
|
|
1197
1216
|
// src/commands/backlog/show/index.ts
|
|
1198
1217
|
function printPlan(item) {
|
|
1199
1218
|
if (!item.plan || item.plan.length === 0) return;
|
|
1200
|
-
console.log(
|
|
1219
|
+
console.log(chalk14.bold("Plan"));
|
|
1201
1220
|
for (const [i, phase] of item.plan.entries()) {
|
|
1202
1221
|
const isCurrent = item.currentPhase === i;
|
|
1203
1222
|
printPhase(phase, i, isCurrent);
|
|
@@ -1205,8 +1224,8 @@ function printPlan(item) {
|
|
|
1205
1224
|
console.log();
|
|
1206
1225
|
}
|
|
1207
1226
|
function phaseHeader(index, name, isCurrent) {
|
|
1208
|
-
const marker = isCurrent ?
|
|
1209
|
-
const label2 = isCurrent ?
|
|
1227
|
+
const marker = isCurrent ? chalk14.green("\u25B6 ") : " ";
|
|
1228
|
+
const label2 = isCurrent ? chalk14.green.bold(`Phase ${index + 1}: ${name}`) : `${chalk14.bold(`Phase ${index + 1}:`)} ${name}`;
|
|
1210
1229
|
return `${marker}${label2}`;
|
|
1211
1230
|
}
|
|
1212
1231
|
function printPhase(phase, index, isCurrent) {
|
|
@@ -1214,15 +1233,15 @@ function printPhase(phase, index, isCurrent) {
|
|
|
1214
1233
|
printPhaseTasks(phase);
|
|
1215
1234
|
}
|
|
1216
1235
|
function printHeader(item) {
|
|
1217
|
-
console.log(
|
|
1236
|
+
console.log(chalk14.bold(`#${item.id} ${item.name}`));
|
|
1218
1237
|
console.log(
|
|
1219
|
-
`${
|
|
1238
|
+
`${chalk14.dim("Type:")} ${item.type} ${chalk14.dim("Status:")} ${item.status}`
|
|
1220
1239
|
);
|
|
1221
1240
|
console.log();
|
|
1222
1241
|
}
|
|
1223
1242
|
function printAcceptanceCriteria(criteria) {
|
|
1224
1243
|
if (criteria.length === 0) return;
|
|
1225
|
-
console.log(
|
|
1244
|
+
console.log(chalk14.bold("Acceptance Criteria"));
|
|
1226
1245
|
for (const [i, ac] of criteria.entries()) {
|
|
1227
1246
|
console.log(` ${i + 1}. ${ac}`);
|
|
1228
1247
|
}
|
|
@@ -1234,7 +1253,7 @@ function show(id) {
|
|
|
1234
1253
|
const { item, items } = result;
|
|
1235
1254
|
printHeader(item);
|
|
1236
1255
|
if (item.description) {
|
|
1237
|
-
console.log(
|
|
1256
|
+
console.log(chalk14.bold("Description"));
|
|
1238
1257
|
console.log(item.description);
|
|
1239
1258
|
console.log();
|
|
1240
1259
|
}
|
|
@@ -1246,7 +1265,7 @@ function show(id) {
|
|
|
1246
1265
|
function printComments(item) {
|
|
1247
1266
|
const entries = item.comments ?? [];
|
|
1248
1267
|
if (entries.length === 0) return;
|
|
1249
|
-
console.log(
|
|
1268
|
+
console.log(chalk14.bold("Comments"));
|
|
1250
1269
|
for (const entry of entries) {
|
|
1251
1270
|
console.log(` ${formatComment(entry)}`);
|
|
1252
1271
|
}
|
|
@@ -1261,7 +1280,7 @@ import {
|
|
|
1261
1280
|
} from "http";
|
|
1262
1281
|
import { dirname, join as join7 } from "path";
|
|
1263
1282
|
import { fileURLToPath } from "url";
|
|
1264
|
-
import
|
|
1283
|
+
import chalk15 from "chalk";
|
|
1265
1284
|
function respondJson(res, status2, data) {
|
|
1266
1285
|
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
1267
1286
|
res.end(JSON.stringify(data));
|
|
@@ -1305,8 +1324,8 @@ function startWebServer(label2, port, handler) {
|
|
|
1305
1324
|
handler(req, res, port);
|
|
1306
1325
|
});
|
|
1307
1326
|
server.listen(port, () => {
|
|
1308
|
-
console.log(
|
|
1309
|
-
console.log(
|
|
1327
|
+
console.log(chalk15.green(`${label2}: ${url}`));
|
|
1328
|
+
console.log(chalk15.dim("Press Ctrl+C to stop"));
|
|
1310
1329
|
exec(`open ${url}`);
|
|
1311
1330
|
});
|
|
1312
1331
|
}
|
|
@@ -1466,7 +1485,7 @@ async function web(options2) {
|
|
|
1466
1485
|
}
|
|
1467
1486
|
|
|
1468
1487
|
// src/commands/backlog/launchMode.ts
|
|
1469
|
-
import
|
|
1488
|
+
import chalk16 from "chalk";
|
|
1470
1489
|
async function launchMode(slashCommand) {
|
|
1471
1490
|
process.env.ASSIST_SESSION_ID = String(process.pid);
|
|
1472
1491
|
const { child, done: done2 } = spawnClaude(`/${slashCommand}`, { allowEdits: true });
|
|
@@ -1476,11 +1495,46 @@ async function launchMode(slashCommand) {
|
|
|
1476
1495
|
const signal = readSignal();
|
|
1477
1496
|
cleanupSignal();
|
|
1478
1497
|
if (signal?.event === "next") {
|
|
1479
|
-
console.log(
|
|
1498
|
+
console.log(chalk16.bold("\nChaining into assist next...\n"));
|
|
1480
1499
|
await next({ allowEdits: true });
|
|
1481
1500
|
}
|
|
1482
1501
|
}
|
|
1483
1502
|
|
|
1503
|
+
// src/commands/backlog/refine.ts
|
|
1504
|
+
import chalk17 from "chalk";
|
|
1505
|
+
import enquirer3 from "enquirer";
|
|
1506
|
+
async function pickItemForRefine() {
|
|
1507
|
+
const items = loadBacklog();
|
|
1508
|
+
const active = items.filter(
|
|
1509
|
+
(i) => i.status === "todo" || i.status === "in-progress"
|
|
1510
|
+
);
|
|
1511
|
+
if (active.length === 0) {
|
|
1512
|
+
console.log(chalk17.yellow("No active backlog items to refine."));
|
|
1513
|
+
return void 0;
|
|
1514
|
+
}
|
|
1515
|
+
if (active.length === 1) {
|
|
1516
|
+
const item = active[0];
|
|
1517
|
+
console.log(chalk17.bold(`Auto-selecting item #${item.id}: ${item.name}`));
|
|
1518
|
+
return String(item.id);
|
|
1519
|
+
}
|
|
1520
|
+
const { selected } = await exitOnCancel(
|
|
1521
|
+
enquirer3.prompt({
|
|
1522
|
+
type: "select",
|
|
1523
|
+
name: "selected",
|
|
1524
|
+
message: "Choose a backlog item to refine:",
|
|
1525
|
+
choices: active.map((item) => ({
|
|
1526
|
+
name: `${typeLabel(item.type)} #${item.id}: ${item.name}`
|
|
1527
|
+
}))
|
|
1528
|
+
})
|
|
1529
|
+
);
|
|
1530
|
+
return selected.match(/#(\d+)/)?.[1] ?? "";
|
|
1531
|
+
}
|
|
1532
|
+
async function refine(id) {
|
|
1533
|
+
const itemId = id ?? await pickItemForRefine();
|
|
1534
|
+
if (!itemId) return;
|
|
1535
|
+
await launchMode(`refine ${itemId}`);
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1484
1538
|
// src/commands/commit.ts
|
|
1485
1539
|
import { execSync } from "child_process";
|
|
1486
1540
|
|
|
@@ -1488,7 +1542,7 @@ import { execSync } from "child_process";
|
|
|
1488
1542
|
import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
|
|
1489
1543
|
import { homedir } from "os";
|
|
1490
1544
|
import { basename, dirname as dirname2, join as join8 } from "path";
|
|
1491
|
-
import
|
|
1545
|
+
import chalk18 from "chalk";
|
|
1492
1546
|
import { stringify as stringifyYaml } from "yaml";
|
|
1493
1547
|
|
|
1494
1548
|
// src/shared/loadRawYaml.ts
|
|
@@ -1684,7 +1738,7 @@ function getTranscriptConfig() {
|
|
|
1684
1738
|
const config = loadConfig();
|
|
1685
1739
|
if (!config.transcript) {
|
|
1686
1740
|
console.error(
|
|
1687
|
-
|
|
1741
|
+
chalk18.red(
|
|
1688
1742
|
"Transcript directories not configured. Run 'assist transcript configure' first."
|
|
1689
1743
|
)
|
|
1690
1744
|
);
|
|
@@ -1773,7 +1827,7 @@ function commit(args) {
|
|
|
1773
1827
|
}
|
|
1774
1828
|
|
|
1775
1829
|
// src/commands/config/index.ts
|
|
1776
|
-
import
|
|
1830
|
+
import chalk19 from "chalk";
|
|
1777
1831
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
1778
1832
|
|
|
1779
1833
|
// src/commands/config/setNestedValue.ts
|
|
@@ -1836,7 +1890,7 @@ function formatIssuePath(issue, key) {
|
|
|
1836
1890
|
function printValidationErrors(issues, key) {
|
|
1837
1891
|
for (const issue of issues) {
|
|
1838
1892
|
console.error(
|
|
1839
|
-
|
|
1893
|
+
chalk19.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
1840
1894
|
);
|
|
1841
1895
|
}
|
|
1842
1896
|
}
|
|
@@ -1853,7 +1907,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
1853
1907
|
function assertNotGlobalOnly(key, global) {
|
|
1854
1908
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
1855
1909
|
console.error(
|
|
1856
|
-
|
|
1910
|
+
chalk19.red(
|
|
1857
1911
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
1858
1912
|
)
|
|
1859
1913
|
);
|
|
@@ -1876,7 +1930,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
1876
1930
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
1877
1931
|
const target = options2.global ? "global" : "project";
|
|
1878
1932
|
console.log(
|
|
1879
|
-
|
|
1933
|
+
chalk19.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
1880
1934
|
);
|
|
1881
1935
|
}
|
|
1882
1936
|
function configList() {
|
|
@@ -1885,7 +1939,7 @@ function configList() {
|
|
|
1885
1939
|
}
|
|
1886
1940
|
|
|
1887
1941
|
// src/commands/config/configGet.ts
|
|
1888
|
-
import
|
|
1942
|
+
import chalk20 from "chalk";
|
|
1889
1943
|
|
|
1890
1944
|
// src/commands/config/getNestedValue.ts
|
|
1891
1945
|
function isTraversable(value) {
|
|
@@ -1917,7 +1971,7 @@ function requireNestedValue(config, key) {
|
|
|
1917
1971
|
return value;
|
|
1918
1972
|
}
|
|
1919
1973
|
function exitKeyNotSet(key) {
|
|
1920
|
-
console.error(
|
|
1974
|
+
console.error(chalk20.red(`Key "${key}" is not set`));
|
|
1921
1975
|
process.exit(1);
|
|
1922
1976
|
}
|
|
1923
1977
|
|
|
@@ -1937,20 +1991,20 @@ function coverage() {
|
|
|
1937
1991
|
}
|
|
1938
1992
|
|
|
1939
1993
|
// src/commands/verify/init/index.ts
|
|
1940
|
-
import
|
|
1994
|
+
import chalk35 from "chalk";
|
|
1941
1995
|
|
|
1942
1996
|
// src/shared/promptMultiselect.ts
|
|
1943
|
-
import
|
|
1944
|
-
import
|
|
1997
|
+
import chalk21 from "chalk";
|
|
1998
|
+
import enquirer4 from "enquirer";
|
|
1945
1999
|
async function promptMultiselect(message, options2) {
|
|
1946
2000
|
const { selected } = await exitOnCancel(
|
|
1947
|
-
|
|
2001
|
+
enquirer4.prompt({
|
|
1948
2002
|
type: "multiselect",
|
|
1949
2003
|
name: "selected",
|
|
1950
2004
|
message,
|
|
1951
2005
|
choices: options2.map((opt) => ({
|
|
1952
2006
|
name: opt.value,
|
|
1953
|
-
message: `${opt.name} - ${
|
|
2007
|
+
message: `${opt.name} - ${chalk21.dim(opt.description)}`
|
|
1954
2008
|
})),
|
|
1955
2009
|
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
1956
2010
|
symbols: {
|
|
@@ -1967,7 +2021,7 @@ async function promptMultiselect(message, options2) {
|
|
|
1967
2021
|
// src/shared/readPackageJson.ts
|
|
1968
2022
|
import * as fs from "fs";
|
|
1969
2023
|
import * as path from "path";
|
|
1970
|
-
import
|
|
2024
|
+
import chalk22 from "chalk";
|
|
1971
2025
|
function findPackageJson() {
|
|
1972
2026
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
1973
2027
|
if (fs.existsSync(packageJsonPath)) {
|
|
@@ -1981,7 +2035,7 @@ function readPackageJson(filePath) {
|
|
|
1981
2035
|
function requirePackageJson() {
|
|
1982
2036
|
const packageJsonPath = findPackageJson();
|
|
1983
2037
|
if (!packageJsonPath) {
|
|
1984
|
-
console.error(
|
|
2038
|
+
console.error(chalk22.red("No package.json found in current directory"));
|
|
1985
2039
|
process.exit(1);
|
|
1986
2040
|
}
|
|
1987
2041
|
const pkg = readPackageJson(packageJsonPath);
|
|
@@ -2012,7 +2066,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
2012
2066
|
// src/commands/verify/installPackage.ts
|
|
2013
2067
|
import { execSync as execSync3 } from "child_process";
|
|
2014
2068
|
import { writeFileSync as writeFileSync6 } from "fs";
|
|
2015
|
-
import
|
|
2069
|
+
import chalk23 from "chalk";
|
|
2016
2070
|
function writePackageJson(filePath, pkg) {
|
|
2017
2071
|
writeFileSync6(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
2018
2072
|
`);
|
|
@@ -2027,12 +2081,12 @@ function addScript(pkg, name, command) {
|
|
|
2027
2081
|
};
|
|
2028
2082
|
}
|
|
2029
2083
|
function installPackage(name, cwd) {
|
|
2030
|
-
console.log(
|
|
2084
|
+
console.log(chalk23.dim(`Installing ${name}...`));
|
|
2031
2085
|
try {
|
|
2032
2086
|
execSync3(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
2033
2087
|
return true;
|
|
2034
2088
|
} catch {
|
|
2035
|
-
console.error(
|
|
2089
|
+
console.error(chalk23.red(`Failed to install ${name}`));
|
|
2036
2090
|
return false;
|
|
2037
2091
|
}
|
|
2038
2092
|
}
|
|
@@ -2079,9 +2133,9 @@ var expectedScripts = {
|
|
|
2079
2133
|
};
|
|
2080
2134
|
|
|
2081
2135
|
// src/commands/verify/setup/setupBuild.ts
|
|
2082
|
-
import
|
|
2136
|
+
import chalk24 from "chalk";
|
|
2083
2137
|
async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
2084
|
-
console.log(
|
|
2138
|
+
console.log(chalk24.blue("\nSetting up build verification..."));
|
|
2085
2139
|
let command;
|
|
2086
2140
|
if (hasVite && hasTypescript) {
|
|
2087
2141
|
command = "tsc -b && vite build --logLevel error";
|
|
@@ -2090,21 +2144,21 @@ async function setupBuild(_packageJsonPath, writer, hasVite, hasTypescript) {
|
|
|
2090
2144
|
} else {
|
|
2091
2145
|
command = "npm run build";
|
|
2092
2146
|
}
|
|
2093
|
-
console.log(
|
|
2147
|
+
console.log(chalk24.dim(`Using: ${command}`));
|
|
2094
2148
|
writer("verify:build", command);
|
|
2095
2149
|
}
|
|
2096
2150
|
async function setupTypecheck(_packageJsonPath, writer) {
|
|
2097
|
-
console.log(
|
|
2151
|
+
console.log(chalk24.blue("\nSetting up typecheck verification..."));
|
|
2098
2152
|
const command = "tsc --noEmit";
|
|
2099
|
-
console.log(
|
|
2153
|
+
console.log(chalk24.dim(`Using: ${command}`));
|
|
2100
2154
|
writer("verify:typecheck", command);
|
|
2101
2155
|
}
|
|
2102
2156
|
|
|
2103
2157
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
2104
2158
|
import * as path2 from "path";
|
|
2105
|
-
import
|
|
2159
|
+
import chalk25 from "chalk";
|
|
2106
2160
|
async function setupDuplicateCode(packageJsonPath, writer) {
|
|
2107
|
-
console.log(
|
|
2161
|
+
console.log(chalk25.blue("\nSetting up jscpd..."));
|
|
2108
2162
|
const cwd = path2.dirname(packageJsonPath);
|
|
2109
2163
|
const pkg = readPackageJson(packageJsonPath);
|
|
2110
2164
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
@@ -2116,12 +2170,12 @@ async function setupDuplicateCode(packageJsonPath, writer) {
|
|
|
2116
2170
|
|
|
2117
2171
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2118
2172
|
import * as path3 from "path";
|
|
2119
|
-
import
|
|
2173
|
+
import chalk27 from "chalk";
|
|
2120
2174
|
|
|
2121
2175
|
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
2122
2176
|
import { existsSync as existsSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
2123
2177
|
import { join as join10 } from "path";
|
|
2124
|
-
import
|
|
2178
|
+
import chalk26 from "chalk";
|
|
2125
2179
|
function loadKnipConfig(knipJsonPath) {
|
|
2126
2180
|
if (existsSync11(knipJsonPath)) {
|
|
2127
2181
|
return JSON.parse(readFileSync10(knipJsonPath, "utf-8"));
|
|
@@ -2140,16 +2194,16 @@ function addToKnipIgnoreBinaries(cwd, binary) {
|
|
|
2140
2194
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
2141
2195
|
`
|
|
2142
2196
|
);
|
|
2143
|
-
console.log(
|
|
2197
|
+
console.log(chalk26.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
2144
2198
|
}
|
|
2145
2199
|
} catch {
|
|
2146
|
-
console.log(
|
|
2200
|
+
console.log(chalk26.yellow("Warning: Could not update knip.json"));
|
|
2147
2201
|
}
|
|
2148
2202
|
}
|
|
2149
2203
|
|
|
2150
2204
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
2151
2205
|
async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
2152
|
-
console.log(
|
|
2206
|
+
console.log(chalk27.blue("\nSetting up hardcoded colors check..."));
|
|
2153
2207
|
const cwd = path3.dirname(packageJsonPath);
|
|
2154
2208
|
if (!hasOpenColor) {
|
|
2155
2209
|
installPackage("open-color", cwd);
|
|
@@ -2160,9 +2214,9 @@ async function setupHardcodedColors(packageJsonPath, writer, hasOpenColor) {
|
|
|
2160
2214
|
|
|
2161
2215
|
// src/commands/verify/setup/setupKnip.ts
|
|
2162
2216
|
import * as path4 from "path";
|
|
2163
|
-
import
|
|
2217
|
+
import chalk28 from "chalk";
|
|
2164
2218
|
async function setupKnip(packageJsonPath, writer) {
|
|
2165
|
-
console.log(
|
|
2219
|
+
console.log(chalk28.blue("\nSetting up knip..."));
|
|
2166
2220
|
const cwd = path4.dirname(packageJsonPath);
|
|
2167
2221
|
const pkg = readPackageJson(packageJsonPath);
|
|
2168
2222
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
@@ -2173,20 +2227,20 @@ async function setupKnip(packageJsonPath, writer) {
|
|
|
2173
2227
|
|
|
2174
2228
|
// src/commands/verify/setup/setupLint.ts
|
|
2175
2229
|
import * as path5 from "path";
|
|
2176
|
-
import
|
|
2230
|
+
import chalk31 from "chalk";
|
|
2177
2231
|
|
|
2178
2232
|
// src/commands/lint/init.ts
|
|
2179
2233
|
import { execSync as execSync5 } from "child_process";
|
|
2180
2234
|
import { existsSync as existsSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
2181
2235
|
import { dirname as dirname7, join as join11 } from "path";
|
|
2182
2236
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2183
|
-
import
|
|
2237
|
+
import chalk30 from "chalk";
|
|
2184
2238
|
|
|
2185
2239
|
// src/shared/promptConfirm.ts
|
|
2186
|
-
import
|
|
2240
|
+
import enquirer5 from "enquirer";
|
|
2187
2241
|
async function promptConfirm(message, initial = true) {
|
|
2188
2242
|
const { confirmed } = await exitOnCancel(
|
|
2189
|
-
|
|
2243
|
+
enquirer5.prompt({
|
|
2190
2244
|
type: "confirm",
|
|
2191
2245
|
name: "confirmed",
|
|
2192
2246
|
message,
|
|
@@ -2284,7 +2338,7 @@ function removeEslintScripts(scripts, options2) {
|
|
|
2284
2338
|
}
|
|
2285
2339
|
|
|
2286
2340
|
// src/utils/printDiff.ts
|
|
2287
|
-
import
|
|
2341
|
+
import chalk29 from "chalk";
|
|
2288
2342
|
import * as diff from "diff";
|
|
2289
2343
|
function normalizeJson(content) {
|
|
2290
2344
|
try {
|
|
@@ -2302,11 +2356,11 @@ function printDiff(oldContent, newContent) {
|
|
|
2302
2356
|
const lines = change.value.replace(/\n$/, "").split("\n");
|
|
2303
2357
|
for (const line of lines) {
|
|
2304
2358
|
if (change.added) {
|
|
2305
|
-
console.log(
|
|
2359
|
+
console.log(chalk29.green(`+ ${line}`));
|
|
2306
2360
|
} else if (change.removed) {
|
|
2307
|
-
console.log(
|
|
2361
|
+
console.log(chalk29.red(`- ${line}`));
|
|
2308
2362
|
} else {
|
|
2309
|
-
console.log(
|
|
2363
|
+
console.log(chalk29.dim(` ${line}`));
|
|
2310
2364
|
}
|
|
2311
2365
|
}
|
|
2312
2366
|
}
|
|
@@ -2340,10 +2394,10 @@ async function init() {
|
|
|
2340
2394
|
console.log("biome.json already has the correct linter config");
|
|
2341
2395
|
return;
|
|
2342
2396
|
}
|
|
2343
|
-
console.log(
|
|
2397
|
+
console.log(chalk30.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
2344
2398
|
console.log();
|
|
2345
2399
|
printDiff(oldContent, newContent);
|
|
2346
|
-
const confirm = await promptConfirm(
|
|
2400
|
+
const confirm = await promptConfirm(chalk30.red("Update biome.json?"));
|
|
2347
2401
|
if (!confirm) {
|
|
2348
2402
|
console.log("Skipped biome.json update");
|
|
2349
2403
|
return;
|
|
@@ -2354,7 +2408,7 @@ async function init() {
|
|
|
2354
2408
|
|
|
2355
2409
|
// src/commands/verify/setup/setupLint.ts
|
|
2356
2410
|
async function setupLint(packageJsonPath, writer) {
|
|
2357
|
-
console.log(
|
|
2411
|
+
console.log(chalk31.blue("\nSetting up biome..."));
|
|
2358
2412
|
const cwd = path5.dirname(packageJsonPath);
|
|
2359
2413
|
const pkg = readPackageJson(packageJsonPath);
|
|
2360
2414
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
@@ -2368,9 +2422,9 @@ async function setupLint(packageJsonPath, writer) {
|
|
|
2368
2422
|
|
|
2369
2423
|
// src/commands/verify/setup/setupMadge.ts
|
|
2370
2424
|
import * as path6 from "path";
|
|
2371
|
-
import
|
|
2425
|
+
import chalk32 from "chalk";
|
|
2372
2426
|
async function setupMadge(packageJsonPath, writer) {
|
|
2373
|
-
console.log(
|
|
2427
|
+
console.log(chalk32.blue("\nSetting up madge..."));
|
|
2374
2428
|
const cwd = path6.dirname(packageJsonPath);
|
|
2375
2429
|
const pkg = readPackageJson(packageJsonPath);
|
|
2376
2430
|
const hasMadge = !!pkg.dependencies?.madge || !!pkg.devDependencies?.madge;
|
|
@@ -2382,18 +2436,18 @@ async function setupMadge(packageJsonPath, writer) {
|
|
|
2382
2436
|
|
|
2383
2437
|
// src/commands/verify/setup/setupMaintainability.ts
|
|
2384
2438
|
import * as path7 from "path";
|
|
2385
|
-
import
|
|
2439
|
+
import chalk33 from "chalk";
|
|
2386
2440
|
async function setupMaintainability(packageJsonPath, writer) {
|
|
2387
|
-
console.log(
|
|
2441
|
+
console.log(chalk33.blue("\nSetting up maintainability check..."));
|
|
2388
2442
|
addToKnipIgnoreBinaries(path7.dirname(packageJsonPath), "assist");
|
|
2389
2443
|
writer("verify:maintainability", expectedScripts["verify:maintainability"]);
|
|
2390
2444
|
}
|
|
2391
2445
|
|
|
2392
2446
|
// src/commands/verify/setup/setupTest.ts
|
|
2393
2447
|
import * as path8 from "path";
|
|
2394
|
-
import
|
|
2448
|
+
import chalk34 from "chalk";
|
|
2395
2449
|
async function setupTest(packageJsonPath, writer) {
|
|
2396
|
-
console.log(
|
|
2450
|
+
console.log(chalk34.blue("\nSetting up vitest..."));
|
|
2397
2451
|
const cwd = path8.dirname(packageJsonPath);
|
|
2398
2452
|
const pkg = readPackageJson(packageJsonPath);
|
|
2399
2453
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
@@ -2562,25 +2616,25 @@ async function runSelectedSetups(selected, packageJsonPath, writer, handlers) {
|
|
|
2562
2616
|
for (const choice of selected) {
|
|
2563
2617
|
await handlers[choice]?.(packageJsonPath, writer);
|
|
2564
2618
|
}
|
|
2565
|
-
console.log(
|
|
2619
|
+
console.log(chalk35.green(`
|
|
2566
2620
|
Added ${selected.length} verify script(s):`));
|
|
2567
2621
|
for (const choice of selected) {
|
|
2568
|
-
console.log(
|
|
2622
|
+
console.log(chalk35.green(` - verify:${choice}`));
|
|
2569
2623
|
}
|
|
2570
|
-
console.log(
|
|
2624
|
+
console.log(chalk35.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
2571
2625
|
}
|
|
2572
2626
|
async function promptForScripts(availableOptions) {
|
|
2573
2627
|
if (availableOptions.length === 0) {
|
|
2574
|
-
console.log(
|
|
2628
|
+
console.log(chalk35.green("All verify scripts are already configured!"));
|
|
2575
2629
|
return null;
|
|
2576
2630
|
}
|
|
2577
|
-
console.log(
|
|
2631
|
+
console.log(chalk35.bold("Available verify scripts to add:\n"));
|
|
2578
2632
|
const selected = await promptMultiselect(
|
|
2579
2633
|
"Select verify scripts to add:",
|
|
2580
2634
|
availableOptions
|
|
2581
2635
|
);
|
|
2582
2636
|
if (selected.length === 0) {
|
|
2583
|
-
console.log(
|
|
2637
|
+
console.log(chalk35.yellow("No scripts selected"));
|
|
2584
2638
|
return null;
|
|
2585
2639
|
}
|
|
2586
2640
|
return selected;
|
|
@@ -2600,17 +2654,17 @@ async function init2() {
|
|
|
2600
2654
|
}
|
|
2601
2655
|
|
|
2602
2656
|
// src/commands/vscode/init/index.ts
|
|
2603
|
-
import
|
|
2657
|
+
import chalk37 from "chalk";
|
|
2604
2658
|
|
|
2605
2659
|
// src/commands/vscode/init/createLaunchJson.ts
|
|
2606
2660
|
import * as fs2 from "fs";
|
|
2607
2661
|
import * as path9 from "path";
|
|
2608
|
-
import
|
|
2662
|
+
import chalk36 from "chalk";
|
|
2609
2663
|
function ensureVscodeFolder() {
|
|
2610
2664
|
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
2611
2665
|
if (!fs2.existsSync(vscodeDir)) {
|
|
2612
2666
|
fs2.mkdirSync(vscodeDir);
|
|
2613
|
-
console.log(
|
|
2667
|
+
console.log(chalk36.dim("Created .vscode folder"));
|
|
2614
2668
|
}
|
|
2615
2669
|
}
|
|
2616
2670
|
function removeVscodeFromGitignore() {
|
|
@@ -2625,7 +2679,7 @@ function removeVscodeFromGitignore() {
|
|
|
2625
2679
|
);
|
|
2626
2680
|
if (filteredLines.length !== lines.length) {
|
|
2627
2681
|
fs2.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
2628
|
-
console.log(
|
|
2682
|
+
console.log(chalk36.dim("Removed .vscode references from .gitignore"));
|
|
2629
2683
|
}
|
|
2630
2684
|
}
|
|
2631
2685
|
function createLaunchJson(type) {
|
|
@@ -2644,7 +2698,7 @@ function createLaunchJson(type) {
|
|
|
2644
2698
|
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
2645
2699
|
fs2.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
2646
2700
|
`);
|
|
2647
|
-
console.log(
|
|
2701
|
+
console.log(chalk36.green("Created .vscode/launch.json"));
|
|
2648
2702
|
}
|
|
2649
2703
|
function createSettingsJson() {
|
|
2650
2704
|
const settings = {
|
|
@@ -2657,7 +2711,7 @@ function createSettingsJson() {
|
|
|
2657
2711
|
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
2658
2712
|
fs2.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
2659
2713
|
`);
|
|
2660
|
-
console.log(
|
|
2714
|
+
console.log(chalk36.green("Created .vscode/settings.json"));
|
|
2661
2715
|
}
|
|
2662
2716
|
function createExtensionsJson() {
|
|
2663
2717
|
const extensions = {
|
|
@@ -2669,7 +2723,7 @@ function createExtensionsJson() {
|
|
|
2669
2723
|
`${JSON.stringify(extensions, null, " ")}
|
|
2670
2724
|
`
|
|
2671
2725
|
);
|
|
2672
|
-
console.log(
|
|
2726
|
+
console.log(chalk36.green("Created .vscode/extensions.json"));
|
|
2673
2727
|
}
|
|
2674
2728
|
|
|
2675
2729
|
// src/commands/vscode/init/detectVscodeSetup.ts
|
|
@@ -2726,7 +2780,7 @@ function applySelections(selected, setup2) {
|
|
|
2726
2780
|
for (const choice of selected) handlers[choice]?.();
|
|
2727
2781
|
}
|
|
2728
2782
|
async function promptForOptions(options2) {
|
|
2729
|
-
console.log(
|
|
2783
|
+
console.log(chalk37.bold("Available VS Code configurations to add:\n"));
|
|
2730
2784
|
return promptMultiselect("Select configurations to add:", options2);
|
|
2731
2785
|
}
|
|
2732
2786
|
async function init3({ all = false } = {}) {
|
|
@@ -2734,17 +2788,17 @@ async function init3({ all = false } = {}) {
|
|
|
2734
2788
|
const setup2 = detectVscodeSetup(pkg);
|
|
2735
2789
|
const options2 = getAvailableOptions2(setup2);
|
|
2736
2790
|
if (options2.length === 0) {
|
|
2737
|
-
console.log(
|
|
2791
|
+
console.log(chalk37.green("VS Code configuration already exists!"));
|
|
2738
2792
|
return;
|
|
2739
2793
|
}
|
|
2740
2794
|
const selected = all ? options2.map((o) => o.value) : await promptForOptions(options2);
|
|
2741
2795
|
if (selected.length === 0) {
|
|
2742
|
-
console.log(
|
|
2796
|
+
console.log(chalk37.yellow("No configurations selected"));
|
|
2743
2797
|
return;
|
|
2744
2798
|
}
|
|
2745
2799
|
applySelections(selected, setup2);
|
|
2746
2800
|
console.log(
|
|
2747
|
-
|
|
2801
|
+
chalk37.green(`
|
|
2748
2802
|
Added ${selected.length} VS Code configuration(s)`)
|
|
2749
2803
|
);
|
|
2750
2804
|
}
|
|
@@ -2757,7 +2811,7 @@ async function init4() {
|
|
|
2757
2811
|
|
|
2758
2812
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2759
2813
|
import path16 from "path";
|
|
2760
|
-
import
|
|
2814
|
+
import chalk39 from "chalk";
|
|
2761
2815
|
|
|
2762
2816
|
// src/commands/lint/lint/checkFileNames.ts
|
|
2763
2817
|
import fs5 from "fs";
|
|
@@ -2837,7 +2891,7 @@ function checkFileNames() {
|
|
|
2837
2891
|
}
|
|
2838
2892
|
|
|
2839
2893
|
// src/commands/lint/lint/fixFileNameViolations.ts
|
|
2840
|
-
import
|
|
2894
|
+
import chalk38 from "chalk";
|
|
2841
2895
|
|
|
2842
2896
|
// src/commands/lint/lint/applyMoves.ts
|
|
2843
2897
|
import fs6 from "fs";
|
|
@@ -2922,25 +2976,25 @@ function fixFileNameViolations(moves) {
|
|
|
2922
2976
|
const start3 = performance.now();
|
|
2923
2977
|
const project = createLintProject();
|
|
2924
2978
|
const cwd = process.cwd();
|
|
2925
|
-
applyMoves(project, moves, cwd, (line) => console.log(
|
|
2979
|
+
applyMoves(project, moves, cwd, (line) => console.log(chalk38.green(line)));
|
|
2926
2980
|
const ms = (performance.now() - start3).toFixed(0);
|
|
2927
|
-
console.log(
|
|
2981
|
+
console.log(chalk38.dim(` Done in ${ms}ms`));
|
|
2928
2982
|
}
|
|
2929
2983
|
|
|
2930
2984
|
// src/commands/lint/lint/runFileNameCheck.ts
|
|
2931
2985
|
function reportViolations(violations) {
|
|
2932
|
-
console.error(
|
|
2986
|
+
console.error(chalk39.red("\nFile name check failed:\n"));
|
|
2933
2987
|
console.error(
|
|
2934
|
-
|
|
2988
|
+
chalk39.red(
|
|
2935
2989
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
2936
2990
|
)
|
|
2937
2991
|
);
|
|
2938
2992
|
for (const violation of violations) {
|
|
2939
|
-
console.error(
|
|
2940
|
-
console.error(
|
|
2993
|
+
console.error(chalk39.red(` ${violation.filePath}`));
|
|
2994
|
+
console.error(chalk39.gray(` Rename to: ${violation.suggestedName}
|
|
2941
2995
|
`));
|
|
2942
2996
|
}
|
|
2943
|
-
console.error(
|
|
2997
|
+
console.error(chalk39.dim(" Run with -f to auto-fix.\n"));
|
|
2944
2998
|
}
|
|
2945
2999
|
function runFileNameCheck(fix = false) {
|
|
2946
3000
|
const violations = checkFileNames();
|
|
@@ -2969,17 +3023,17 @@ function runFileNameCheck(fix = false) {
|
|
|
2969
3023
|
import fs8 from "fs";
|
|
2970
3024
|
|
|
2971
3025
|
// src/commands/lint/shared.ts
|
|
2972
|
-
import
|
|
3026
|
+
import chalk40 from "chalk";
|
|
2973
3027
|
function reportViolations2(violations, checkName, errorMessage, successMessage) {
|
|
2974
3028
|
if (violations.length > 0) {
|
|
2975
|
-
console.error(
|
|
3029
|
+
console.error(chalk40.red(`
|
|
2976
3030
|
${checkName} failed:
|
|
2977
3031
|
`));
|
|
2978
|
-
console.error(
|
|
3032
|
+
console.error(chalk40.red(` ${errorMessage}
|
|
2979
3033
|
`));
|
|
2980
3034
|
for (const violation of violations) {
|
|
2981
|
-
console.error(
|
|
2982
|
-
console.error(
|
|
3035
|
+
console.error(chalk40.red(` ${violation.filePath}:${violation.line}`));
|
|
3036
|
+
console.error(chalk40.gray(` ${violation.content}
|
|
2983
3037
|
`));
|
|
2984
3038
|
}
|
|
2985
3039
|
return false;
|
|
@@ -3459,14 +3513,14 @@ import { existsSync as existsSync18, readFileSync as readFileSync15, writeFileSy
|
|
|
3459
3513
|
|
|
3460
3514
|
// src/commands/deploy/init/index.ts
|
|
3461
3515
|
import { execSync as execSync12 } from "child_process";
|
|
3462
|
-
import
|
|
3463
|
-
import
|
|
3516
|
+
import chalk42 from "chalk";
|
|
3517
|
+
import enquirer6 from "enquirer";
|
|
3464
3518
|
|
|
3465
3519
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
3466
3520
|
import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as readFileSync14, writeFileSync as writeFileSync13 } from "fs";
|
|
3467
3521
|
import { dirname as dirname13, join as join14 } from "path";
|
|
3468
3522
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3469
|
-
import
|
|
3523
|
+
import chalk41 from "chalk";
|
|
3470
3524
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
3471
3525
|
var __dirname3 = dirname13(fileURLToPath3(import.meta.url));
|
|
3472
3526
|
function getExistingSiteId() {
|
|
@@ -3491,20 +3545,20 @@ async function updateWorkflow(siteId) {
|
|
|
3491
3545
|
if (existsSync17(WORKFLOW_PATH)) {
|
|
3492
3546
|
const oldContent = readFileSync14(WORKFLOW_PATH, "utf-8");
|
|
3493
3547
|
if (oldContent === newContent) {
|
|
3494
|
-
console.log(
|
|
3548
|
+
console.log(chalk41.green("build.yml is already up to date"));
|
|
3495
3549
|
return;
|
|
3496
3550
|
}
|
|
3497
|
-
console.log(
|
|
3551
|
+
console.log(chalk41.yellow("\nbuild.yml will be updated:"));
|
|
3498
3552
|
console.log();
|
|
3499
3553
|
printDiff(oldContent, newContent);
|
|
3500
|
-
const confirm = await promptConfirm(
|
|
3554
|
+
const confirm = await promptConfirm(chalk41.red("Update build.yml?"));
|
|
3501
3555
|
if (!confirm) {
|
|
3502
3556
|
console.log("Skipped build.yml update");
|
|
3503
3557
|
return;
|
|
3504
3558
|
}
|
|
3505
3559
|
}
|
|
3506
3560
|
writeFileSync13(WORKFLOW_PATH, newContent);
|
|
3507
|
-
console.log(
|
|
3561
|
+
console.log(chalk41.green(`
|
|
3508
3562
|
Created ${WORKFLOW_PATH}`));
|
|
3509
3563
|
}
|
|
3510
3564
|
|
|
@@ -3515,50 +3569,50 @@ async function ensureNetlifyCli() {
|
|
|
3515
3569
|
} catch (error) {
|
|
3516
3570
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
3517
3571
|
throw error;
|
|
3518
|
-
console.error(
|
|
3572
|
+
console.error(chalk42.red("\nNetlify CLI is not installed.\n"));
|
|
3519
3573
|
const install = await promptConfirm("Would you like to install it now?");
|
|
3520
3574
|
if (!install) {
|
|
3521
3575
|
console.log(
|
|
3522
|
-
|
|
3576
|
+
chalk42.yellow(
|
|
3523
3577
|
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
3524
3578
|
)
|
|
3525
3579
|
);
|
|
3526
3580
|
process.exit(1);
|
|
3527
3581
|
}
|
|
3528
|
-
console.log(
|
|
3582
|
+
console.log(chalk42.dim("\nInstalling netlify-cli...\n"));
|
|
3529
3583
|
execSync12("npm install -g netlify-cli", { stdio: "inherit" });
|
|
3530
3584
|
console.log();
|
|
3531
3585
|
execSync12("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
3532
3586
|
}
|
|
3533
3587
|
}
|
|
3534
3588
|
function printSetupInstructions() {
|
|
3535
|
-
console.log(
|
|
3589
|
+
console.log(chalk42.bold("\nDeployment initialized successfully!"));
|
|
3536
3590
|
console.log(
|
|
3537
|
-
|
|
3591
|
+
chalk42.yellow("\nTo complete setup, create a personal access token at:")
|
|
3538
3592
|
);
|
|
3539
3593
|
console.log(
|
|
3540
|
-
|
|
3594
|
+
chalk42.cyan(
|
|
3541
3595
|
"https://app.netlify.com/user/applications#personal-access-tokens"
|
|
3542
3596
|
)
|
|
3543
3597
|
);
|
|
3544
3598
|
console.log(
|
|
3545
|
-
|
|
3599
|
+
chalk42.yellow(
|
|
3546
3600
|
"\nThen add it as NETLIFY_AUTH_TOKEN in your GitHub repository secrets."
|
|
3547
3601
|
)
|
|
3548
3602
|
);
|
|
3549
3603
|
}
|
|
3550
3604
|
async function init5() {
|
|
3551
|
-
console.log(
|
|
3605
|
+
console.log(chalk42.bold("Initializing Netlify deployment...\n"));
|
|
3552
3606
|
const existingSiteId = getExistingSiteId();
|
|
3553
3607
|
if (existingSiteId) {
|
|
3554
|
-
console.log(
|
|
3608
|
+
console.log(chalk42.dim(`Using existing site ID: ${existingSiteId}
|
|
3555
3609
|
`));
|
|
3556
3610
|
await updateWorkflow(existingSiteId);
|
|
3557
3611
|
return;
|
|
3558
3612
|
}
|
|
3559
3613
|
console.log("Creating Netlify site...\n");
|
|
3560
3614
|
await ensureNetlifyCli();
|
|
3561
|
-
const { siteId } = await
|
|
3615
|
+
const { siteId } = await enquirer6.prompt({
|
|
3562
3616
|
type: "input",
|
|
3563
3617
|
name: "siteId",
|
|
3564
3618
|
message: "Enter the Site ID from above:",
|
|
@@ -3730,27 +3784,27 @@ async function notify() {
|
|
|
3730
3784
|
}
|
|
3731
3785
|
|
|
3732
3786
|
// src/commands/backlog/comment/index.ts
|
|
3733
|
-
import
|
|
3787
|
+
import chalk43 from "chalk";
|
|
3734
3788
|
function comment(id, text) {
|
|
3735
3789
|
const result = loadAndFindItem(id);
|
|
3736
3790
|
if (!result) process.exit(1);
|
|
3737
3791
|
addComment(result.item, text);
|
|
3738
3792
|
saveBacklog(result.items);
|
|
3739
|
-
console.log(
|
|
3793
|
+
console.log(chalk43.green(`Comment added to item #${id}.`));
|
|
3740
3794
|
}
|
|
3741
3795
|
|
|
3742
3796
|
// src/commands/backlog/comments/index.ts
|
|
3743
|
-
import
|
|
3797
|
+
import chalk44 from "chalk";
|
|
3744
3798
|
function comments(id) {
|
|
3745
3799
|
const result = loadAndFindItem(id);
|
|
3746
3800
|
if (!result) process.exit(1);
|
|
3747
3801
|
const { item } = result;
|
|
3748
3802
|
const entries = item.comments ?? [];
|
|
3749
3803
|
if (entries.length === 0) {
|
|
3750
|
-
console.log(
|
|
3804
|
+
console.log(chalk44.dim(`No comments on item #${id}.`));
|
|
3751
3805
|
return;
|
|
3752
3806
|
}
|
|
3753
|
-
console.log(
|
|
3807
|
+
console.log(chalk44.bold(`Comments for #${id}: ${item.name}
|
|
3754
3808
|
`));
|
|
3755
3809
|
for (const entry of entries) {
|
|
3756
3810
|
console.log(`${formatComment(entry)}
|
|
@@ -3765,12 +3819,12 @@ function registerCommentCommands(cmd) {
|
|
|
3765
3819
|
}
|
|
3766
3820
|
|
|
3767
3821
|
// src/commands/backlog/add/index.ts
|
|
3768
|
-
import
|
|
3822
|
+
import chalk46 from "chalk";
|
|
3769
3823
|
|
|
3770
3824
|
// src/commands/backlog/commitBacklog.ts
|
|
3771
3825
|
import { execSync as execSync14 } from "child_process";
|
|
3772
3826
|
import { join as join15 } from "path";
|
|
3773
|
-
import
|
|
3827
|
+
import chalk45 from "chalk";
|
|
3774
3828
|
function commitBacklog(id, name) {
|
|
3775
3829
|
try {
|
|
3776
3830
|
const jsonlPath = join15(getBacklogDir(), ".assist", "backlog.jsonl");
|
|
@@ -3778,7 +3832,7 @@ function commitBacklog(id, name) {
|
|
|
3778
3832
|
execSync14(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
|
|
3779
3833
|
execSync14(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
|
|
3780
3834
|
} catch {
|
|
3781
|
-
console.log(
|
|
3835
|
+
console.log(chalk45.yellow("Warning: could not auto-commit backlog file."));
|
|
3782
3836
|
}
|
|
3783
3837
|
}
|
|
3784
3838
|
|
|
@@ -3787,9 +3841,9 @@ import { spawnSync } from "child_process";
|
|
|
3787
3841
|
import { mkdtempSync, readFileSync as readFileSync16, unlinkSync as unlinkSync4, writeFileSync as writeFileSync15 } from "fs";
|
|
3788
3842
|
import { tmpdir } from "os";
|
|
3789
3843
|
import { join as join16 } from "path";
|
|
3790
|
-
import
|
|
3844
|
+
import enquirer7 from "enquirer";
|
|
3791
3845
|
async function promptType() {
|
|
3792
|
-
const { type } = await
|
|
3846
|
+
const { type } = await enquirer7.prompt({
|
|
3793
3847
|
type: "select",
|
|
3794
3848
|
name: "type",
|
|
3795
3849
|
message: "Type:",
|
|
@@ -3799,7 +3853,7 @@ async function promptType() {
|
|
|
3799
3853
|
return type;
|
|
3800
3854
|
}
|
|
3801
3855
|
async function promptName() {
|
|
3802
|
-
const { name } = await
|
|
3856
|
+
const { name } = await enquirer7.prompt({
|
|
3803
3857
|
type: "input",
|
|
3804
3858
|
name: "name",
|
|
3805
3859
|
message: "Name:",
|
|
@@ -3808,14 +3862,14 @@ async function promptName() {
|
|
|
3808
3862
|
return name.trim();
|
|
3809
3863
|
}
|
|
3810
3864
|
async function promptDescription() {
|
|
3811
|
-
const { useEditor } = await
|
|
3865
|
+
const { useEditor } = await enquirer7.prompt({
|
|
3812
3866
|
type: "confirm",
|
|
3813
3867
|
name: "useEditor",
|
|
3814
3868
|
message: "Open editor for description?",
|
|
3815
3869
|
initial: false
|
|
3816
3870
|
});
|
|
3817
3871
|
if (!useEditor) {
|
|
3818
|
-
const { description } = await
|
|
3872
|
+
const { description } = await enquirer7.prompt({
|
|
3819
3873
|
type: "input",
|
|
3820
3874
|
name: "description",
|
|
3821
3875
|
message: "Description (optional):"
|
|
@@ -3841,7 +3895,7 @@ function openEditor() {
|
|
|
3841
3895
|
async function promptAcceptanceCriteria() {
|
|
3842
3896
|
const criteria = [];
|
|
3843
3897
|
for (; ; ) {
|
|
3844
|
-
const { criterion } = await
|
|
3898
|
+
const { criterion } = await enquirer7.prompt({
|
|
3845
3899
|
type: "input",
|
|
3846
3900
|
name: "criterion",
|
|
3847
3901
|
message: "Acceptance criterion (empty to finish):"
|
|
@@ -3870,12 +3924,12 @@ async function addFromOptions(options2) {
|
|
|
3870
3924
|
});
|
|
3871
3925
|
saveBacklog(items);
|
|
3872
3926
|
commitBacklog(id, name);
|
|
3873
|
-
console.log(
|
|
3927
|
+
console.log(chalk46.green(`Added item #${id}: ${name}`));
|
|
3874
3928
|
}
|
|
3875
3929
|
async function add(options2) {
|
|
3876
3930
|
if (!backlogExists()) {
|
|
3877
3931
|
console.log(
|
|
3878
|
-
|
|
3932
|
+
chalk46.yellow(
|
|
3879
3933
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3880
3934
|
)
|
|
3881
3935
|
);
|
|
@@ -3885,13 +3939,13 @@ async function add(options2) {
|
|
|
3885
3939
|
}
|
|
3886
3940
|
|
|
3887
3941
|
// src/commands/backlog/addPhase.ts
|
|
3888
|
-
import
|
|
3942
|
+
import chalk47 from "chalk";
|
|
3889
3943
|
function addPhase(id, name, options2) {
|
|
3890
3944
|
const result = loadAndFindItem(id);
|
|
3891
3945
|
if (!result) return;
|
|
3892
3946
|
const tasks = options2.task ?? [];
|
|
3893
3947
|
if (tasks.length === 0) {
|
|
3894
|
-
console.log(
|
|
3948
|
+
console.log(chalk47.red("At least one --task is required."));
|
|
3895
3949
|
process.exitCode = 1;
|
|
3896
3950
|
return;
|
|
3897
3951
|
}
|
|
@@ -3913,25 +3967,25 @@ function addPhase(id, name, options2) {
|
|
|
3913
3967
|
exportToJsonl(db, dir);
|
|
3914
3968
|
commitBacklog(itemId, result.item.name);
|
|
3915
3969
|
console.log(
|
|
3916
|
-
|
|
3970
|
+
chalk47.green(
|
|
3917
3971
|
`Added phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
3918
3972
|
)
|
|
3919
3973
|
);
|
|
3920
3974
|
}
|
|
3921
3975
|
|
|
3922
3976
|
// src/commands/backlog/init/index.ts
|
|
3923
|
-
import
|
|
3977
|
+
import chalk48 from "chalk";
|
|
3924
3978
|
async function init6() {
|
|
3925
3979
|
if (backlogExists()) {
|
|
3926
|
-
console.log(
|
|
3980
|
+
console.log(chalk48.yellow("Backlog already exists."));
|
|
3927
3981
|
return;
|
|
3928
3982
|
}
|
|
3929
3983
|
saveBacklog([]);
|
|
3930
|
-
console.log(
|
|
3984
|
+
console.log(chalk48.green("Created backlog."));
|
|
3931
3985
|
}
|
|
3932
3986
|
|
|
3933
3987
|
// src/commands/backlog/list/index.ts
|
|
3934
|
-
import
|
|
3988
|
+
import chalk49 from "chalk";
|
|
3935
3989
|
function filterItems(items, options2) {
|
|
3936
3990
|
if (options2.status) return items.filter((i) => i.status === options2.status);
|
|
3937
3991
|
if (!options2.all)
|
|
@@ -3941,7 +3995,7 @@ function filterItems(items, options2) {
|
|
|
3941
3995
|
async function list2(options2) {
|
|
3942
3996
|
if (!backlogExists()) {
|
|
3943
3997
|
console.log(
|
|
3944
|
-
|
|
3998
|
+
chalk49.yellow(
|
|
3945
3999
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3946
4000
|
)
|
|
3947
4001
|
);
|
|
@@ -3950,12 +4004,12 @@ async function list2(options2) {
|
|
|
3950
4004
|
const allItems = loadBacklog();
|
|
3951
4005
|
const items = filterItems(allItems, options2);
|
|
3952
4006
|
if (items.length === 0) {
|
|
3953
|
-
console.log(
|
|
4007
|
+
console.log(chalk49.dim("Backlog is empty."));
|
|
3954
4008
|
return;
|
|
3955
4009
|
}
|
|
3956
4010
|
for (const item of items) {
|
|
3957
4011
|
console.log(
|
|
3958
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4012
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk49.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
3959
4013
|
);
|
|
3960
4014
|
if (options2.verbose) {
|
|
3961
4015
|
printVerboseDetails(item);
|
|
@@ -3978,7 +4032,7 @@ function registerItemCommands(cmd) {
|
|
|
3978
4032
|
}
|
|
3979
4033
|
|
|
3980
4034
|
// src/commands/backlog/link.ts
|
|
3981
|
-
import
|
|
4035
|
+
import chalk51 from "chalk";
|
|
3982
4036
|
|
|
3983
4037
|
// src/commands/backlog/hasCycle.ts
|
|
3984
4038
|
function hasCycle(items, fromId, toId) {
|
|
@@ -4001,11 +4055,11 @@ function hasCycle(items, fromId, toId) {
|
|
|
4001
4055
|
}
|
|
4002
4056
|
|
|
4003
4057
|
// src/commands/backlog/validateLinkTarget.ts
|
|
4004
|
-
import
|
|
4058
|
+
import chalk50 from "chalk";
|
|
4005
4059
|
function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
4006
4060
|
const toItem = items.find((i) => i.id === toNum);
|
|
4007
4061
|
if (!toItem) {
|
|
4008
|
-
console.log(
|
|
4062
|
+
console.log(chalk50.red(`Item #${toId} not found.`));
|
|
4009
4063
|
return void 0;
|
|
4010
4064
|
}
|
|
4011
4065
|
if (!fromItem.links) fromItem.links = [];
|
|
@@ -4014,7 +4068,7 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4014
4068
|
);
|
|
4015
4069
|
if (duplicate) {
|
|
4016
4070
|
console.log(
|
|
4017
|
-
|
|
4071
|
+
chalk50.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
|
|
4018
4072
|
);
|
|
4019
4073
|
return void 0;
|
|
4020
4074
|
}
|
|
@@ -4025,13 +4079,13 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4025
4079
|
function link(fromId, toId, opts) {
|
|
4026
4080
|
const linkType = opts.type ?? "relates-to";
|
|
4027
4081
|
if (linkType !== "relates-to" && linkType !== "depends-on") {
|
|
4028
|
-
console.log(
|
|
4082
|
+
console.log(chalk51.red(`Invalid link type: ${linkType}`));
|
|
4029
4083
|
return;
|
|
4030
4084
|
}
|
|
4031
4085
|
const fromNum = Number.parseInt(fromId, 10);
|
|
4032
4086
|
const toNum = Number.parseInt(toId, 10);
|
|
4033
4087
|
if (fromNum === toNum) {
|
|
4034
|
-
console.log(
|
|
4088
|
+
console.log(chalk51.red("Cannot link an item to itself."));
|
|
4035
4089
|
return;
|
|
4036
4090
|
}
|
|
4037
4091
|
const result = loadAndFindItem(fromId);
|
|
@@ -4048,7 +4102,7 @@ function link(fromId, toId, opts) {
|
|
|
4048
4102
|
if (!toItem) return;
|
|
4049
4103
|
if (linkType === "depends-on" && hasCycle(items, fromNum, toNum)) {
|
|
4050
4104
|
console.log(
|
|
4051
|
-
|
|
4105
|
+
chalk51.red(
|
|
4052
4106
|
`Cannot add dependency: #${fromId} \u2192 #${toId} would create a circular dependency.`
|
|
4053
4107
|
)
|
|
4054
4108
|
);
|
|
@@ -4058,32 +4112,32 @@ function link(fromId, toId, opts) {
|
|
|
4058
4112
|
fromItem.links.push({ type: linkType, targetId: toNum });
|
|
4059
4113
|
saveBacklog(items);
|
|
4060
4114
|
console.log(
|
|
4061
|
-
|
|
4115
|
+
chalk51.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
|
|
4062
4116
|
);
|
|
4063
4117
|
}
|
|
4064
4118
|
|
|
4065
4119
|
// src/commands/backlog/unlink.ts
|
|
4066
|
-
import
|
|
4120
|
+
import chalk52 from "chalk";
|
|
4067
4121
|
function unlink(fromId, toId) {
|
|
4068
4122
|
const toNum = Number.parseInt(toId, 10);
|
|
4069
4123
|
const result = loadAndFindItem(fromId);
|
|
4070
4124
|
if (!result) return;
|
|
4071
4125
|
const { items, item: fromItem } = result;
|
|
4072
4126
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
4073
|
-
console.log(
|
|
4127
|
+
console.log(chalk52.yellow(`No links found on item #${fromId}.`));
|
|
4074
4128
|
return;
|
|
4075
4129
|
}
|
|
4076
4130
|
const before = fromItem.links.length;
|
|
4077
4131
|
fromItem.links = fromItem.links.filter((l) => l.targetId !== toNum);
|
|
4078
4132
|
if (fromItem.links.length === before) {
|
|
4079
|
-
console.log(
|
|
4133
|
+
console.log(chalk52.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
4080
4134
|
return;
|
|
4081
4135
|
}
|
|
4082
4136
|
if (fromItem.links.length === 0) {
|
|
4083
4137
|
fromItem.links = void 0;
|
|
4084
4138
|
}
|
|
4085
4139
|
saveBacklog(items);
|
|
4086
|
-
console.log(
|
|
4140
|
+
console.log(chalk52.green(`Removed link from #${fromId} to #${toId}.`));
|
|
4087
4141
|
}
|
|
4088
4142
|
|
|
4089
4143
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -4096,12 +4150,19 @@ function registerLinkCommands(cmd) {
|
|
|
4096
4150
|
cmd.command("unlink <from> <to>").description("Remove a link between two backlog items").action(unlink);
|
|
4097
4151
|
}
|
|
4098
4152
|
|
|
4153
|
+
// src/commands/backlog/registerRunCommand.ts
|
|
4154
|
+
function registerRunCommand(cmd) {
|
|
4155
|
+
cmd.command("run <id>").description("Run a backlog item's plan phase-by-phase with Claude").option("-w, --write", "Run Claude with acceptEdits permission mode").action(async (id, opts) => {
|
|
4156
|
+
await run(id, { allowEdits: opts.write });
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4159
|
+
|
|
4099
4160
|
// src/commands/backlog/search/index.ts
|
|
4100
|
-
import
|
|
4161
|
+
import chalk53 from "chalk";
|
|
4101
4162
|
async function search(query) {
|
|
4102
4163
|
if (!backlogExists()) {
|
|
4103
4164
|
console.log(
|
|
4104
|
-
|
|
4165
|
+
chalk53.yellow(
|
|
4105
4166
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
4106
4167
|
)
|
|
4107
4168
|
);
|
|
@@ -4109,18 +4170,18 @@ async function search(query) {
|
|
|
4109
4170
|
}
|
|
4110
4171
|
const items = searchBacklog(query);
|
|
4111
4172
|
if (items.length === 0) {
|
|
4112
|
-
console.log(
|
|
4173
|
+
console.log(chalk53.dim(`No items matching "${query}".`));
|
|
4113
4174
|
return;
|
|
4114
4175
|
}
|
|
4115
4176
|
console.log(
|
|
4116
|
-
|
|
4177
|
+
chalk53.dim(
|
|
4117
4178
|
`${items.length} item${items.length === 1 ? "" : "s"} matching "${query}":
|
|
4118
4179
|
`
|
|
4119
4180
|
)
|
|
4120
4181
|
);
|
|
4121
4182
|
for (const item of items) {
|
|
4122
4183
|
console.log(
|
|
4123
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4184
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk53.dim(`#${item.id}`)} ${item.name}`
|
|
4124
4185
|
);
|
|
4125
4186
|
}
|
|
4126
4187
|
}
|
|
@@ -4131,16 +4192,16 @@ function registerSearchCommand(cmd) {
|
|
|
4131
4192
|
}
|
|
4132
4193
|
|
|
4133
4194
|
// src/commands/backlog/delete/index.ts
|
|
4134
|
-
import
|
|
4195
|
+
import chalk54 from "chalk";
|
|
4135
4196
|
async function del(id) {
|
|
4136
4197
|
const name = removeItem(id);
|
|
4137
4198
|
if (name) {
|
|
4138
|
-
console.log(
|
|
4199
|
+
console.log(chalk54.green(`Deleted item #${id}: ${name}`));
|
|
4139
4200
|
}
|
|
4140
4201
|
}
|
|
4141
4202
|
|
|
4142
4203
|
// src/commands/backlog/done/index.ts
|
|
4143
|
-
import
|
|
4204
|
+
import chalk55 from "chalk";
|
|
4144
4205
|
async function done(id, summary) {
|
|
4145
4206
|
const result = loadAndFindItem(id);
|
|
4146
4207
|
if (!result) return;
|
|
@@ -4150,20 +4211,20 @@ async function done(id, summary) {
|
|
|
4150
4211
|
addPhaseSummary(result.item, summary, phase);
|
|
4151
4212
|
}
|
|
4152
4213
|
saveBacklog(result.items);
|
|
4153
|
-
console.log(
|
|
4214
|
+
console.log(chalk55.green(`Completed item #${id}: ${result.item.name}`));
|
|
4154
4215
|
}
|
|
4155
4216
|
|
|
4156
4217
|
// src/commands/backlog/start/index.ts
|
|
4157
|
-
import
|
|
4218
|
+
import chalk56 from "chalk";
|
|
4158
4219
|
async function start(id) {
|
|
4159
4220
|
const name = setStatus(id, "in-progress");
|
|
4160
4221
|
if (name) {
|
|
4161
|
-
console.log(
|
|
4222
|
+
console.log(chalk56.green(`Started item #${id}: ${name}`));
|
|
4162
4223
|
}
|
|
4163
4224
|
}
|
|
4164
4225
|
|
|
4165
4226
|
// src/commands/backlog/wontdo/index.ts
|
|
4166
|
-
import
|
|
4227
|
+
import chalk57 from "chalk";
|
|
4167
4228
|
async function wontdo(id, reason) {
|
|
4168
4229
|
const result = loadAndFindItem(id);
|
|
4169
4230
|
if (!result) return;
|
|
@@ -4173,7 +4234,7 @@ async function wontdo(id, reason) {
|
|
|
4173
4234
|
addPhaseSummary(result.item, reason, phase);
|
|
4174
4235
|
}
|
|
4175
4236
|
saveBacklog(result.items);
|
|
4176
|
-
console.log(
|
|
4237
|
+
console.log(chalk57.red(`Won't do item #${id}: ${result.item.name}`));
|
|
4177
4238
|
}
|
|
4178
4239
|
|
|
4179
4240
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -4184,6 +4245,204 @@ function registerStatusCommands(cmd) {
|
|
|
4184
4245
|
cmd.command("delete <id>").alias("remove").description("Delete a backlog item").action(del);
|
|
4185
4246
|
}
|
|
4186
4247
|
|
|
4248
|
+
// src/commands/backlog/removePhase.ts
|
|
4249
|
+
import chalk59 from "chalk";
|
|
4250
|
+
|
|
4251
|
+
// src/commands/backlog/findPhase.ts
|
|
4252
|
+
import chalk58 from "chalk";
|
|
4253
|
+
function findPhase(id, phase) {
|
|
4254
|
+
const result = loadAndFindItem(id);
|
|
4255
|
+
if (!result) return void 0;
|
|
4256
|
+
const dir = getBacklogDir();
|
|
4257
|
+
const db = openDb(dir);
|
|
4258
|
+
const itemId = result.item.id;
|
|
4259
|
+
const phaseIdx = Number.parseInt(phase, 10);
|
|
4260
|
+
const existing = db.prepare(
|
|
4261
|
+
"SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ? AND idx = ?"
|
|
4262
|
+
).get(itemId, phaseIdx);
|
|
4263
|
+
if (existing.cnt === 0) {
|
|
4264
|
+
console.log(chalk58.red(`Phase ${phaseIdx} not found on item #${itemId}.`));
|
|
4265
|
+
process.exitCode = 1;
|
|
4266
|
+
return void 0;
|
|
4267
|
+
}
|
|
4268
|
+
return { result, dir, db, itemId, phaseIdx };
|
|
4269
|
+
}
|
|
4270
|
+
function reindexPhases(db, itemId) {
|
|
4271
|
+
const remaining = db.prepare("SELECT idx FROM plan_phases WHERE item_id = ? ORDER BY idx").all(itemId);
|
|
4272
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
4273
|
+
const oldIdx = remaining[i].idx;
|
|
4274
|
+
if (oldIdx !== i) {
|
|
4275
|
+
db.prepare(
|
|
4276
|
+
"UPDATE plan_tasks SET phase_idx = ? WHERE item_id = ? AND phase_idx = ?"
|
|
4277
|
+
).run(i, itemId, oldIdx);
|
|
4278
|
+
db.prepare(
|
|
4279
|
+
"UPDATE plan_phases SET idx = ? WHERE item_id = ? AND idx = ?"
|
|
4280
|
+
).run(i, itemId, oldIdx);
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
function adjustCurrentPhase(db, item, removedIdx) {
|
|
4285
|
+
if (item.currentPhase === void 0) return;
|
|
4286
|
+
if (removedIdx < item.currentPhase) {
|
|
4287
|
+
db.prepare("UPDATE items SET current_phase = ? WHERE id = ?").run(
|
|
4288
|
+
item.currentPhase - 1,
|
|
4289
|
+
item.id
|
|
4290
|
+
);
|
|
4291
|
+
} else if (removedIdx === item.currentPhase) {
|
|
4292
|
+
const { cnt } = db.prepare("SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ?").get(item.id);
|
|
4293
|
+
const newPhase = cnt === 0 ? null : Math.min(item.currentPhase, cnt - 1);
|
|
4294
|
+
db.prepare("UPDATE items SET current_phase = ? WHERE id = ?").run(
|
|
4295
|
+
newPhase,
|
|
4296
|
+
item.id
|
|
4297
|
+
);
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
// src/commands/backlog/removePhase.ts
|
|
4302
|
+
function removePhase(id, phase) {
|
|
4303
|
+
const found = findPhase(id, phase);
|
|
4304
|
+
if (!found) return;
|
|
4305
|
+
const { result, dir, db, itemId, phaseIdx } = found;
|
|
4306
|
+
const run4 = db.transaction(() => {
|
|
4307
|
+
db.prepare(
|
|
4308
|
+
"DELETE FROM plan_tasks WHERE item_id = ? AND phase_idx = ?"
|
|
4309
|
+
).run(itemId, phaseIdx);
|
|
4310
|
+
db.prepare("DELETE FROM plan_phases WHERE item_id = ? AND idx = ?").run(
|
|
4311
|
+
itemId,
|
|
4312
|
+
phaseIdx
|
|
4313
|
+
);
|
|
4314
|
+
reindexPhases(db, itemId);
|
|
4315
|
+
adjustCurrentPhase(db, result.item, phaseIdx);
|
|
4316
|
+
});
|
|
4317
|
+
run4();
|
|
4318
|
+
exportToJsonl(db, dir);
|
|
4319
|
+
commitBacklog(itemId, result.item.name);
|
|
4320
|
+
console.log(chalk59.green(`Removed phase ${phaseIdx} from item #${itemId}.`));
|
|
4321
|
+
}
|
|
4322
|
+
|
|
4323
|
+
// src/commands/backlog/update/index.ts
|
|
4324
|
+
import chalk61 from "chalk";
|
|
4325
|
+
|
|
4326
|
+
// src/commands/backlog/update/buildUpdateSql.ts
|
|
4327
|
+
import chalk60 from "chalk";
|
|
4328
|
+
function buildUpdateSql(options2) {
|
|
4329
|
+
const { name, desc, type, ac } = options2;
|
|
4330
|
+
if (!name && !desc && !type && !ac) {
|
|
4331
|
+
console.log(chalk60.red("Nothing to update. Provide at least one flag."));
|
|
4332
|
+
process.exitCode = 1;
|
|
4333
|
+
return void 0;
|
|
4334
|
+
}
|
|
4335
|
+
if (type && type !== "story" && type !== "bug") {
|
|
4336
|
+
console.log(chalk60.red('Invalid type. Must be "story" or "bug".'));
|
|
4337
|
+
process.exitCode = 1;
|
|
4338
|
+
return void 0;
|
|
4339
|
+
}
|
|
4340
|
+
const sets = [];
|
|
4341
|
+
const params = [];
|
|
4342
|
+
const fieldNames = [];
|
|
4343
|
+
if (name) {
|
|
4344
|
+
sets.push("name = ?");
|
|
4345
|
+
params.push(name);
|
|
4346
|
+
fieldNames.push("name");
|
|
4347
|
+
}
|
|
4348
|
+
if (desc) {
|
|
4349
|
+
sets.push("description = ?");
|
|
4350
|
+
params.push(desc);
|
|
4351
|
+
fieldNames.push("description");
|
|
4352
|
+
}
|
|
4353
|
+
if (type) {
|
|
4354
|
+
sets.push("type = ?");
|
|
4355
|
+
params.push(type);
|
|
4356
|
+
fieldNames.push("type");
|
|
4357
|
+
}
|
|
4358
|
+
if (ac) {
|
|
4359
|
+
sets.push("acceptance_criteria = ?");
|
|
4360
|
+
params.push(JSON.stringify(ac));
|
|
4361
|
+
fieldNames.push("acceptance criteria");
|
|
4362
|
+
}
|
|
4363
|
+
return { sets, params, fields: fieldNames.join(", ") };
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
// src/commands/backlog/update/index.ts
|
|
4367
|
+
function update(id, options2) {
|
|
4368
|
+
const result = loadAndFindItem(id);
|
|
4369
|
+
if (!result) return;
|
|
4370
|
+
const built = buildUpdateSql(options2);
|
|
4371
|
+
if (!built) return;
|
|
4372
|
+
const dir = getBacklogDir();
|
|
4373
|
+
const db = openDb(dir);
|
|
4374
|
+
const itemId = result.item.id;
|
|
4375
|
+
db.prepare(`UPDATE items SET ${built.sets.join(", ")} WHERE id = ?`).run(
|
|
4376
|
+
...built.params,
|
|
4377
|
+
itemId
|
|
4378
|
+
);
|
|
4379
|
+
exportToJsonl(db, dir);
|
|
4380
|
+
commitBacklog(itemId, options2.name ?? result.item.name);
|
|
4381
|
+
console.log(chalk61.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
// src/commands/backlog/updatePhase.ts
|
|
4385
|
+
import chalk62 from "chalk";
|
|
4386
|
+
|
|
4387
|
+
// src/commands/backlog/applyPhaseUpdate.ts
|
|
4388
|
+
function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
4389
|
+
const run4 = db.transaction(() => {
|
|
4390
|
+
if (fields.name) {
|
|
4391
|
+
db.prepare(
|
|
4392
|
+
"UPDATE plan_phases SET name = ? WHERE item_id = ? AND idx = ?"
|
|
4393
|
+
).run(fields.name, itemId, phaseIdx);
|
|
4394
|
+
}
|
|
4395
|
+
if (fields.manualCheck) {
|
|
4396
|
+
db.prepare(
|
|
4397
|
+
"UPDATE plan_phases SET manual_checks = ? WHERE item_id = ? AND idx = ?"
|
|
4398
|
+
).run(JSON.stringify(fields.manualCheck), itemId, phaseIdx);
|
|
4399
|
+
}
|
|
4400
|
+
if (fields.task) {
|
|
4401
|
+
db.prepare(
|
|
4402
|
+
"DELETE FROM plan_tasks WHERE item_id = ? AND phase_idx = ?"
|
|
4403
|
+
).run(itemId, phaseIdx);
|
|
4404
|
+
const stmt = db.prepare(
|
|
4405
|
+
"INSERT INTO plan_tasks (item_id, phase_idx, idx, task) VALUES (?, ?, ?, ?)"
|
|
4406
|
+
);
|
|
4407
|
+
for (let i = 0; i < fields.task.length; i++) {
|
|
4408
|
+
stmt.run(itemId, phaseIdx, i, fields.task[i]);
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
});
|
|
4412
|
+
run4();
|
|
4413
|
+
}
|
|
4414
|
+
|
|
4415
|
+
// src/commands/backlog/updatePhase.ts
|
|
4416
|
+
function updatePhase(id, phase, options2) {
|
|
4417
|
+
const { name, task, manualCheck } = options2;
|
|
4418
|
+
if (!name && !task && !manualCheck) {
|
|
4419
|
+
console.log(chalk62.red("Nothing to update. Provide at least one flag."));
|
|
4420
|
+
process.exitCode = 1;
|
|
4421
|
+
return;
|
|
4422
|
+
}
|
|
4423
|
+
const found = findPhase(id, phase);
|
|
4424
|
+
if (!found) return;
|
|
4425
|
+
const { result, dir, db, itemId, phaseIdx } = found;
|
|
4426
|
+
applyPhaseUpdate(db, itemId, phaseIdx, { name, task, manualCheck });
|
|
4427
|
+
exportToJsonl(db, dir);
|
|
4428
|
+
commitBacklog(itemId, result.item.name);
|
|
4429
|
+
const fields = [
|
|
4430
|
+
name && "name",
|
|
4431
|
+
task && "tasks",
|
|
4432
|
+
manualCheck && "manual checks"
|
|
4433
|
+
].filter(Boolean).join(", ");
|
|
4434
|
+
console.log(
|
|
4435
|
+
chalk62.green(`Updated ${fields} on phase ${phaseIdx} of item #${itemId}.`)
|
|
4436
|
+
);
|
|
4437
|
+
}
|
|
4438
|
+
|
|
4439
|
+
// src/commands/backlog/registerUpdateCommands.ts
|
|
4440
|
+
function registerUpdateCommands(cmd) {
|
|
4441
|
+
cmd.command("update <id>").description("Update fields on a backlog item").option("--name <name>", "New item name").option("--desc <description>", "New description").option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").action(update);
|
|
4442
|
+
cmd.command("update-phase <id> <phase>").description("Modify a plan phase on a backlog item").option("--name <name>", "New phase name").option("--task <task...>", "Replace tasks (repeatable)").option("--manual-check <check...>", "Replace manual checks (repeatable)").action(updatePhase);
|
|
4443
|
+
cmd.command("remove-phase <id> <phase>").description("Remove a plan phase from a backlog item").action(removePhase);
|
|
4444
|
+
}
|
|
4445
|
+
|
|
4187
4446
|
// src/commands/registerBacklog.ts
|
|
4188
4447
|
function registerShowCommands(cmd) {
|
|
4189
4448
|
cmd.command("show <id>").alias("view").description("Show full detail for a backlog item").action(show);
|
|
@@ -4200,11 +4459,6 @@ function registerNextCommand(cmd) {
|
|
|
4200
4459
|
(opts) => next({ allowEdits: opts.write })
|
|
4201
4460
|
);
|
|
4202
4461
|
}
|
|
4203
|
-
function registerRunCommand(cmd) {
|
|
4204
|
-
cmd.command("run <id>").description("Run a backlog item's plan phase-by-phase with Claude").option("-w, --write", "Run Claude with acceptEdits permission mode").action(async (id, opts) => {
|
|
4205
|
-
await run(id, { allowEdits: opts.write });
|
|
4206
|
-
});
|
|
4207
|
-
}
|
|
4208
4462
|
function registerBacklog(program2) {
|
|
4209
4463
|
const cmd = program2.command("backlog").description("Manage a backlog of work items").option("--dir <path>", "Override directory for backlog file discovery").hook("preAction", (thisCommand) => {
|
|
4210
4464
|
setBacklogDir(thisCommand.opts().dir);
|
|
@@ -4219,6 +4473,7 @@ function registerBacklog(program2) {
|
|
|
4219
4473
|
registerNextCommand(cmd);
|
|
4220
4474
|
registerRunCommand(cmd);
|
|
4221
4475
|
registerSearchCommand(cmd);
|
|
4476
|
+
registerUpdateCommands(cmd);
|
|
4222
4477
|
}
|
|
4223
4478
|
|
|
4224
4479
|
// src/shared/isApprovedRead.ts
|
|
@@ -4628,48 +4883,48 @@ ${reasons.join("\n")}`);
|
|
|
4628
4883
|
}
|
|
4629
4884
|
|
|
4630
4885
|
// src/commands/deny/denyAdd.ts
|
|
4631
|
-
import
|
|
4886
|
+
import chalk63 from "chalk";
|
|
4632
4887
|
function denyAdd(pattern2, message) {
|
|
4633
4888
|
const config = loadProjectConfig();
|
|
4634
4889
|
const deny = config.deny ?? [];
|
|
4635
4890
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
4636
|
-
console.log(
|
|
4891
|
+
console.log(chalk63.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
4637
4892
|
return;
|
|
4638
4893
|
}
|
|
4639
4894
|
deny.push({ pattern: pattern2, message });
|
|
4640
4895
|
config.deny = deny;
|
|
4641
4896
|
saveConfig(config);
|
|
4642
|
-
console.log(
|
|
4897
|
+
console.log(chalk63.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
4643
4898
|
}
|
|
4644
4899
|
|
|
4645
4900
|
// src/commands/deny/denyList.ts
|
|
4646
|
-
import
|
|
4901
|
+
import chalk64 from "chalk";
|
|
4647
4902
|
function denyList() {
|
|
4648
4903
|
const config = loadConfig();
|
|
4649
4904
|
const deny = config.deny;
|
|
4650
4905
|
if (!deny || deny.length === 0) {
|
|
4651
|
-
console.log(
|
|
4906
|
+
console.log(chalk64.dim("No deny rules configured."));
|
|
4652
4907
|
return;
|
|
4653
4908
|
}
|
|
4654
4909
|
for (const rule of deny) {
|
|
4655
|
-
console.log(`${
|
|
4910
|
+
console.log(`${chalk64.red(rule.pattern)} \u2192 ${rule.message}`);
|
|
4656
4911
|
}
|
|
4657
4912
|
}
|
|
4658
4913
|
|
|
4659
4914
|
// src/commands/deny/denyRemove.ts
|
|
4660
|
-
import
|
|
4915
|
+
import chalk65 from "chalk";
|
|
4661
4916
|
function denyRemove(pattern2) {
|
|
4662
4917
|
const config = loadProjectConfig();
|
|
4663
4918
|
const deny = config.deny ?? [];
|
|
4664
4919
|
const index = deny.findIndex((r) => r.pattern === pattern2);
|
|
4665
4920
|
if (index === -1) {
|
|
4666
|
-
console.log(
|
|
4921
|
+
console.log(chalk65.yellow(`No deny rule found for: ${pattern2}`));
|
|
4667
4922
|
return;
|
|
4668
4923
|
}
|
|
4669
4924
|
deny.splice(index, 1);
|
|
4670
4925
|
config.deny = deny.length > 0 ? deny : void 0;
|
|
4671
4926
|
saveConfig(config);
|
|
4672
|
-
console.log(
|
|
4927
|
+
console.log(chalk65.green(`Removed deny rule: ${pattern2}`));
|
|
4673
4928
|
}
|
|
4674
4929
|
|
|
4675
4930
|
// src/commands/permitCliReads/index.ts
|
|
@@ -4719,11 +4974,11 @@ function assertCliExists(cli) {
|
|
|
4719
4974
|
}
|
|
4720
4975
|
|
|
4721
4976
|
// src/commands/permitCliReads/colorize.ts
|
|
4722
|
-
import
|
|
4977
|
+
import chalk66 from "chalk";
|
|
4723
4978
|
function colorize(plainOutput) {
|
|
4724
4979
|
return plainOutput.split("\n").map((line) => {
|
|
4725
|
-
if (line.startsWith(" R ")) return
|
|
4726
|
-
if (line.startsWith(" W ")) return
|
|
4980
|
+
if (line.startsWith(" R ")) return chalk66.green(line);
|
|
4981
|
+
if (line.startsWith(" W ")) return chalk66.red(line);
|
|
4727
4982
|
return line;
|
|
4728
4983
|
}).join("\n");
|
|
4729
4984
|
}
|
|
@@ -5041,15 +5296,15 @@ function registerCliHook(program2) {
|
|
|
5041
5296
|
}
|
|
5042
5297
|
|
|
5043
5298
|
// src/commands/complexity/analyze.ts
|
|
5044
|
-
import
|
|
5299
|
+
import chalk72 from "chalk";
|
|
5045
5300
|
|
|
5046
5301
|
// src/commands/complexity/cyclomatic.ts
|
|
5047
|
-
import
|
|
5302
|
+
import chalk68 from "chalk";
|
|
5048
5303
|
|
|
5049
5304
|
// src/commands/complexity/shared/index.ts
|
|
5050
5305
|
import fs12 from "fs";
|
|
5051
5306
|
import path20 from "path";
|
|
5052
|
-
import
|
|
5307
|
+
import chalk67 from "chalk";
|
|
5053
5308
|
import ts5 from "typescript";
|
|
5054
5309
|
|
|
5055
5310
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -5295,7 +5550,7 @@ function createSourceFromFile(filePath) {
|
|
|
5295
5550
|
function withSourceFiles(pattern2, callback) {
|
|
5296
5551
|
const files = findSourceFiles2(pattern2);
|
|
5297
5552
|
if (files.length === 0) {
|
|
5298
|
-
console.log(
|
|
5553
|
+
console.log(chalk67.yellow("No files found matching pattern"));
|
|
5299
5554
|
return void 0;
|
|
5300
5555
|
}
|
|
5301
5556
|
return callback(files);
|
|
@@ -5328,11 +5583,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5328
5583
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
5329
5584
|
for (const { file, name, complexity } of results) {
|
|
5330
5585
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
5331
|
-
const color = exceedsThreshold ?
|
|
5332
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
5586
|
+
const color = exceedsThreshold ? chalk68.red : chalk68.white;
|
|
5587
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk68.cyan(complexity)}`);
|
|
5333
5588
|
}
|
|
5334
5589
|
console.log(
|
|
5335
|
-
|
|
5590
|
+
chalk68.dim(
|
|
5336
5591
|
`
|
|
5337
5592
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5338
5593
|
)
|
|
@@ -5344,7 +5599,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5344
5599
|
}
|
|
5345
5600
|
|
|
5346
5601
|
// src/commands/complexity/halstead.ts
|
|
5347
|
-
import
|
|
5602
|
+
import chalk69 from "chalk";
|
|
5348
5603
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
5349
5604
|
withSourceFiles(pattern2, (files) => {
|
|
5350
5605
|
const results = [];
|
|
@@ -5359,13 +5614,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5359
5614
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
5360
5615
|
for (const { file, name, metrics } of results) {
|
|
5361
5616
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
5362
|
-
const color = exceedsThreshold ?
|
|
5617
|
+
const color = exceedsThreshold ? chalk69.red : chalk69.white;
|
|
5363
5618
|
console.log(
|
|
5364
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
5619
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk69.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk69.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk69.magenta(metrics.effort.toFixed(1))}`
|
|
5365
5620
|
);
|
|
5366
5621
|
}
|
|
5367
5622
|
console.log(
|
|
5368
|
-
|
|
5623
|
+
chalk69.dim(
|
|
5369
5624
|
`
|
|
5370
5625
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5371
5626
|
)
|
|
@@ -5380,28 +5635,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5380
5635
|
import fs13 from "fs";
|
|
5381
5636
|
|
|
5382
5637
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
5383
|
-
import
|
|
5638
|
+
import chalk70 from "chalk";
|
|
5384
5639
|
function displayMaintainabilityResults(results, threshold) {
|
|
5385
5640
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
5386
5641
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
5387
|
-
console.log(
|
|
5642
|
+
console.log(chalk70.green("All files pass maintainability threshold"));
|
|
5388
5643
|
} else {
|
|
5389
5644
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
5390
|
-
const color = threshold !== void 0 ?
|
|
5645
|
+
const color = threshold !== void 0 ? chalk70.red : chalk70.white;
|
|
5391
5646
|
console.log(
|
|
5392
|
-
`${color(file)} \u2192 avg: ${
|
|
5647
|
+
`${color(file)} \u2192 avg: ${chalk70.cyan(avgMaintainability.toFixed(1))}, min: ${chalk70.yellow(minMaintainability.toFixed(1))}`
|
|
5393
5648
|
);
|
|
5394
5649
|
}
|
|
5395
5650
|
}
|
|
5396
|
-
console.log(
|
|
5651
|
+
console.log(chalk70.dim(`
|
|
5397
5652
|
Analyzed ${results.length} files`));
|
|
5398
5653
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
5399
5654
|
console.error(
|
|
5400
|
-
|
|
5655
|
+
chalk70.red(
|
|
5401
5656
|
`
|
|
5402
5657
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
5403
5658
|
|
|
5404
|
-
\u26A0\uFE0F ${
|
|
5659
|
+
\u26A0\uFE0F ${chalk70.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
|
|
5405
5660
|
)
|
|
5406
5661
|
);
|
|
5407
5662
|
process.exit(1);
|
|
@@ -5458,7 +5713,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5458
5713
|
|
|
5459
5714
|
// src/commands/complexity/sloc.ts
|
|
5460
5715
|
import fs14 from "fs";
|
|
5461
|
-
import
|
|
5716
|
+
import chalk71 from "chalk";
|
|
5462
5717
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
5463
5718
|
withSourceFiles(pattern2, (files) => {
|
|
5464
5719
|
const results = [];
|
|
@@ -5474,12 +5729,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5474
5729
|
results.sort((a, b) => b.lines - a.lines);
|
|
5475
5730
|
for (const { file, lines } of results) {
|
|
5476
5731
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
5477
|
-
const color = exceedsThreshold ?
|
|
5478
|
-
console.log(`${color(file)} \u2192 ${
|
|
5732
|
+
const color = exceedsThreshold ? chalk71.red : chalk71.white;
|
|
5733
|
+
console.log(`${color(file)} \u2192 ${chalk71.cyan(lines)} lines`);
|
|
5479
5734
|
}
|
|
5480
5735
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
5481
5736
|
console.log(
|
|
5482
|
-
|
|
5737
|
+
chalk71.dim(`
|
|
5483
5738
|
Total: ${total} lines across ${files.length} files`)
|
|
5484
5739
|
);
|
|
5485
5740
|
if (hasViolation) {
|
|
@@ -5493,21 +5748,21 @@ async function analyze(pattern2) {
|
|
|
5493
5748
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
5494
5749
|
const files = findSourceFiles2(searchPattern);
|
|
5495
5750
|
if (files.length === 0) {
|
|
5496
|
-
console.log(
|
|
5751
|
+
console.log(chalk72.yellow("No files found matching pattern"));
|
|
5497
5752
|
return;
|
|
5498
5753
|
}
|
|
5499
5754
|
if (files.length === 1) {
|
|
5500
5755
|
const file = files[0];
|
|
5501
|
-
console.log(
|
|
5756
|
+
console.log(chalk72.bold.underline("SLOC"));
|
|
5502
5757
|
await sloc(file);
|
|
5503
5758
|
console.log();
|
|
5504
|
-
console.log(
|
|
5759
|
+
console.log(chalk72.bold.underline("Cyclomatic Complexity"));
|
|
5505
5760
|
await cyclomatic(file);
|
|
5506
5761
|
console.log();
|
|
5507
|
-
console.log(
|
|
5762
|
+
console.log(chalk72.bold.underline("Halstead Metrics"));
|
|
5508
5763
|
await halstead(file);
|
|
5509
5764
|
console.log();
|
|
5510
|
-
console.log(
|
|
5765
|
+
console.log(chalk72.bold.underline("Maintainability Index"));
|
|
5511
5766
|
await maintainability(file);
|
|
5512
5767
|
return;
|
|
5513
5768
|
}
|
|
@@ -5535,7 +5790,7 @@ function registerComplexity(program2) {
|
|
|
5535
5790
|
|
|
5536
5791
|
// src/commands/deploy/redirect.ts
|
|
5537
5792
|
import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync18 } from "fs";
|
|
5538
|
-
import
|
|
5793
|
+
import chalk73 from "chalk";
|
|
5539
5794
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
5540
5795
|
if (!window.location.pathname.endsWith('/')) {
|
|
5541
5796
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -5544,22 +5799,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
5544
5799
|
function redirect() {
|
|
5545
5800
|
const indexPath = "index.html";
|
|
5546
5801
|
if (!existsSync22(indexPath)) {
|
|
5547
|
-
console.log(
|
|
5802
|
+
console.log(chalk73.yellow("No index.html found"));
|
|
5548
5803
|
return;
|
|
5549
5804
|
}
|
|
5550
5805
|
const content = readFileSync20(indexPath, "utf-8");
|
|
5551
5806
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
5552
|
-
console.log(
|
|
5807
|
+
console.log(chalk73.dim("Trailing slash script already present"));
|
|
5553
5808
|
return;
|
|
5554
5809
|
}
|
|
5555
5810
|
const headCloseIndex = content.indexOf("</head>");
|
|
5556
5811
|
if (headCloseIndex === -1) {
|
|
5557
|
-
console.log(
|
|
5812
|
+
console.log(chalk73.red("Could not find </head> tag in index.html"));
|
|
5558
5813
|
return;
|
|
5559
5814
|
}
|
|
5560
5815
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
5561
5816
|
writeFileSync18(indexPath, newContent);
|
|
5562
|
-
console.log(
|
|
5817
|
+
console.log(chalk73.green("Added trailing slash redirect to index.html"));
|
|
5563
5818
|
}
|
|
5564
5819
|
|
|
5565
5820
|
// src/commands/registerDeploy.ts
|
|
@@ -5586,7 +5841,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
5586
5841
|
|
|
5587
5842
|
// src/commands/devlog/shared.ts
|
|
5588
5843
|
import { execSync as execSync17 } from "child_process";
|
|
5589
|
-
import
|
|
5844
|
+
import chalk74 from "chalk";
|
|
5590
5845
|
|
|
5591
5846
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
5592
5847
|
import { readdirSync, readFileSync as readFileSync21 } from "fs";
|
|
@@ -5673,13 +5928,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
5673
5928
|
}
|
|
5674
5929
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
5675
5930
|
for (const commit2 of commits) {
|
|
5676
|
-
console.log(` ${
|
|
5931
|
+
console.log(` ${chalk74.yellow(commit2.hash)} ${commit2.message}`);
|
|
5677
5932
|
if (verbose) {
|
|
5678
5933
|
const visibleFiles = commit2.files.filter(
|
|
5679
5934
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
5680
5935
|
);
|
|
5681
5936
|
for (const file of visibleFiles) {
|
|
5682
|
-
console.log(` ${
|
|
5937
|
+
console.log(` ${chalk74.dim(file)}`);
|
|
5683
5938
|
}
|
|
5684
5939
|
}
|
|
5685
5940
|
}
|
|
@@ -5704,15 +5959,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
5704
5959
|
}
|
|
5705
5960
|
|
|
5706
5961
|
// src/commands/devlog/list/printDateHeader.ts
|
|
5707
|
-
import
|
|
5962
|
+
import chalk75 from "chalk";
|
|
5708
5963
|
function printDateHeader(date, isSkipped, entries) {
|
|
5709
5964
|
if (isSkipped) {
|
|
5710
|
-
console.log(`${
|
|
5965
|
+
console.log(`${chalk75.bold.blue(date)} ${chalk75.dim("skipped")}`);
|
|
5711
5966
|
} else if (entries && entries.length > 0) {
|
|
5712
|
-
const entryInfo = entries.map((e) => `${
|
|
5713
|
-
console.log(`${
|
|
5967
|
+
const entryInfo = entries.map((e) => `${chalk75.green(e.version)} ${e.title}`).join(" | ");
|
|
5968
|
+
console.log(`${chalk75.bold.blue(date)} ${entryInfo}`);
|
|
5714
5969
|
} else {
|
|
5715
|
-
console.log(`${
|
|
5970
|
+
console.log(`${chalk75.bold.blue(date)} ${chalk75.red("\u26A0 devlog missing")}`);
|
|
5716
5971
|
}
|
|
5717
5972
|
}
|
|
5718
5973
|
|
|
@@ -5816,24 +6071,24 @@ function bumpVersion(version2, type) {
|
|
|
5816
6071
|
|
|
5817
6072
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
5818
6073
|
import { execSync as execSync20 } from "child_process";
|
|
5819
|
-
import
|
|
6074
|
+
import chalk77 from "chalk";
|
|
5820
6075
|
|
|
5821
6076
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
5822
|
-
import
|
|
6077
|
+
import chalk76 from "chalk";
|
|
5823
6078
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
5824
6079
|
if (conventional && firstHash) {
|
|
5825
6080
|
const version2 = getVersionAtCommit(firstHash);
|
|
5826
6081
|
if (version2) {
|
|
5827
|
-
console.log(`${
|
|
6082
|
+
console.log(`${chalk76.bold("version:")} ${stripToMinor(version2)}`);
|
|
5828
6083
|
} else {
|
|
5829
|
-
console.log(`${
|
|
6084
|
+
console.log(`${chalk76.bold("version:")} ${chalk76.red("unknown")}`);
|
|
5830
6085
|
}
|
|
5831
6086
|
} else if (patchVersion && minorVersion) {
|
|
5832
6087
|
console.log(
|
|
5833
|
-
`${
|
|
6088
|
+
`${chalk76.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
5834
6089
|
);
|
|
5835
6090
|
} else {
|
|
5836
|
-
console.log(`${
|
|
6091
|
+
console.log(`${chalk76.bold("version:")} v0.1 (initial)`);
|
|
5837
6092
|
}
|
|
5838
6093
|
}
|
|
5839
6094
|
|
|
@@ -5880,16 +6135,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
5880
6135
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
5881
6136
|
}
|
|
5882
6137
|
function logName(repoName) {
|
|
5883
|
-
console.log(`${
|
|
6138
|
+
console.log(`${chalk77.bold("name:")} ${repoName}`);
|
|
5884
6139
|
}
|
|
5885
6140
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
5886
6141
|
logName(ctx.repoName);
|
|
5887
6142
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
5888
|
-
console.log(
|
|
6143
|
+
console.log(chalk77.bold.blue(targetDate));
|
|
5889
6144
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
5890
6145
|
}
|
|
5891
6146
|
function logNoCommits(lastInfo) {
|
|
5892
|
-
console.log(
|
|
6147
|
+
console.log(chalk77.dim(noCommitsMessage(!!lastInfo)));
|
|
5893
6148
|
}
|
|
5894
6149
|
|
|
5895
6150
|
// src/commands/devlog/next/index.ts
|
|
@@ -5930,11 +6185,11 @@ function next2(options2) {
|
|
|
5930
6185
|
import { execSync as execSync21 } from "child_process";
|
|
5931
6186
|
|
|
5932
6187
|
// src/commands/devlog/repos/printReposTable.ts
|
|
5933
|
-
import
|
|
6188
|
+
import chalk78 from "chalk";
|
|
5934
6189
|
function colorStatus(status2) {
|
|
5935
|
-
if (status2 === "missing") return
|
|
5936
|
-
if (status2 === "outdated") return
|
|
5937
|
-
return
|
|
6190
|
+
if (status2 === "missing") return chalk78.red(status2);
|
|
6191
|
+
if (status2 === "outdated") return chalk78.yellow(status2);
|
|
6192
|
+
return chalk78.green(status2);
|
|
5938
6193
|
}
|
|
5939
6194
|
function formatRow(row, nameWidth) {
|
|
5940
6195
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -5948,8 +6203,8 @@ function printReposTable(rows) {
|
|
|
5948
6203
|
"Last Devlog".padEnd(11),
|
|
5949
6204
|
"Status"
|
|
5950
6205
|
].join(" ");
|
|
5951
|
-
console.log(
|
|
5952
|
-
console.log(
|
|
6206
|
+
console.log(chalk78.dim(header));
|
|
6207
|
+
console.log(chalk78.dim("-".repeat(header.length)));
|
|
5953
6208
|
for (const row of rows) {
|
|
5954
6209
|
console.log(formatRow(row, nameWidth));
|
|
5955
6210
|
}
|
|
@@ -6007,14 +6262,14 @@ function repos(options2) {
|
|
|
6007
6262
|
// src/commands/devlog/skip.ts
|
|
6008
6263
|
import { writeFileSync as writeFileSync19 } from "fs";
|
|
6009
6264
|
import { join as join21 } from "path";
|
|
6010
|
-
import
|
|
6265
|
+
import chalk79 from "chalk";
|
|
6011
6266
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
6012
6267
|
function getBlogConfigPath() {
|
|
6013
6268
|
return join21(BLOG_REPO_ROOT, "assist.yml");
|
|
6014
6269
|
}
|
|
6015
6270
|
function skip(date) {
|
|
6016
6271
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
6017
|
-
console.log(
|
|
6272
|
+
console.log(chalk79.red("Invalid date format. Use YYYY-MM-DD"));
|
|
6018
6273
|
process.exit(1);
|
|
6019
6274
|
}
|
|
6020
6275
|
const repoName = getRepoName();
|
|
@@ -6025,7 +6280,7 @@ function skip(date) {
|
|
|
6025
6280
|
const skipDays = skip2[repoName] ?? [];
|
|
6026
6281
|
if (skipDays.includes(date)) {
|
|
6027
6282
|
console.log(
|
|
6028
|
-
|
|
6283
|
+
chalk79.yellow(`${date} is already in skip list for ${repoName}`)
|
|
6029
6284
|
);
|
|
6030
6285
|
return;
|
|
6031
6286
|
}
|
|
@@ -6035,20 +6290,20 @@ function skip(date) {
|
|
|
6035
6290
|
devlog.skip = skip2;
|
|
6036
6291
|
config.devlog = devlog;
|
|
6037
6292
|
writeFileSync19(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
6038
|
-
console.log(
|
|
6293
|
+
console.log(chalk79.green(`Added ${date} to skip list for ${repoName}`));
|
|
6039
6294
|
}
|
|
6040
6295
|
|
|
6041
6296
|
// src/commands/devlog/version.ts
|
|
6042
|
-
import
|
|
6297
|
+
import chalk80 from "chalk";
|
|
6043
6298
|
function version() {
|
|
6044
6299
|
const config = loadConfig();
|
|
6045
6300
|
const name = getRepoName();
|
|
6046
6301
|
const lastInfo = getLastVersionInfo(name, config);
|
|
6047
6302
|
const lastVersion = lastInfo?.version ?? null;
|
|
6048
6303
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
6049
|
-
console.log(`${
|
|
6050
|
-
console.log(`${
|
|
6051
|
-
console.log(`${
|
|
6304
|
+
console.log(`${chalk80.bold("name:")} ${name}`);
|
|
6305
|
+
console.log(`${chalk80.bold("last:")} ${lastVersion ?? chalk80.dim("none")}`);
|
|
6306
|
+
console.log(`${chalk80.bold("next:")} ${nextVersion ?? chalk80.dim("none")}`);
|
|
6052
6307
|
}
|
|
6053
6308
|
|
|
6054
6309
|
// src/commands/registerDevlog.ts
|
|
@@ -6072,7 +6327,7 @@ function registerDevlog(program2) {
|
|
|
6072
6327
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
6073
6328
|
import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
|
|
6074
6329
|
import { join as join22 } from "path";
|
|
6075
|
-
import
|
|
6330
|
+
import chalk81 from "chalk";
|
|
6076
6331
|
|
|
6077
6332
|
// src/shared/findRepoRoot.ts
|
|
6078
6333
|
import { existsSync as existsSync23 } from "fs";
|
|
@@ -6135,14 +6390,14 @@ function checkBuildLocks(startDir) {
|
|
|
6135
6390
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
6136
6391
|
if (locked) {
|
|
6137
6392
|
console.error(
|
|
6138
|
-
|
|
6393
|
+
chalk81.red("Build output locked (is VS debugging?): ") + locked
|
|
6139
6394
|
);
|
|
6140
6395
|
process.exit(1);
|
|
6141
6396
|
}
|
|
6142
6397
|
}
|
|
6143
6398
|
async function checkBuildLocksCommand() {
|
|
6144
6399
|
checkBuildLocks();
|
|
6145
|
-
console.log(
|
|
6400
|
+
console.log(chalk81.green("No build locks detected"));
|
|
6146
6401
|
}
|
|
6147
6402
|
|
|
6148
6403
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -6241,30 +6496,30 @@ function escapeRegex(s) {
|
|
|
6241
6496
|
}
|
|
6242
6497
|
|
|
6243
6498
|
// src/commands/dotnet/printTree.ts
|
|
6244
|
-
import
|
|
6499
|
+
import chalk82 from "chalk";
|
|
6245
6500
|
function printNodes(nodes, prefix2) {
|
|
6246
6501
|
for (let i = 0; i < nodes.length; i++) {
|
|
6247
6502
|
const isLast = i === nodes.length - 1;
|
|
6248
6503
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
6249
6504
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
6250
6505
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
6251
|
-
const label2 = isMissing ?
|
|
6506
|
+
const label2 = isMissing ? chalk82.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
6252
6507
|
console.log(`${prefix2}${connector}${label2}`);
|
|
6253
6508
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
6254
6509
|
}
|
|
6255
6510
|
}
|
|
6256
6511
|
function printTree(tree, totalCount, solutions) {
|
|
6257
|
-
console.log(
|
|
6258
|
-
console.log(
|
|
6512
|
+
console.log(chalk82.bold("\nProject Dependency Tree"));
|
|
6513
|
+
console.log(chalk82.cyan(tree.relativePath));
|
|
6259
6514
|
printNodes(tree.children, "");
|
|
6260
|
-
console.log(
|
|
6515
|
+
console.log(chalk82.dim(`
|
|
6261
6516
|
${totalCount} projects total (including root)`));
|
|
6262
|
-
console.log(
|
|
6517
|
+
console.log(chalk82.bold("\nSolution Membership"));
|
|
6263
6518
|
if (solutions.length === 0) {
|
|
6264
|
-
console.log(
|
|
6519
|
+
console.log(chalk82.yellow(" Not found in any .sln"));
|
|
6265
6520
|
} else {
|
|
6266
6521
|
for (const sln of solutions) {
|
|
6267
|
-
console.log(` ${
|
|
6522
|
+
console.log(` ${chalk82.green(sln)}`);
|
|
6268
6523
|
}
|
|
6269
6524
|
}
|
|
6270
6525
|
console.log();
|
|
@@ -6293,16 +6548,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
6293
6548
|
// src/commands/dotnet/resolveCsproj.ts
|
|
6294
6549
|
import { existsSync as existsSync24 } from "fs";
|
|
6295
6550
|
import path24 from "path";
|
|
6296
|
-
import
|
|
6551
|
+
import chalk83 from "chalk";
|
|
6297
6552
|
function resolveCsproj(csprojPath) {
|
|
6298
6553
|
const resolved = path24.resolve(csprojPath);
|
|
6299
6554
|
if (!existsSync24(resolved)) {
|
|
6300
|
-
console.error(
|
|
6555
|
+
console.error(chalk83.red(`File not found: ${resolved}`));
|
|
6301
6556
|
process.exit(1);
|
|
6302
6557
|
}
|
|
6303
6558
|
const repoRoot = findRepoRoot(path24.dirname(resolved));
|
|
6304
6559
|
if (!repoRoot) {
|
|
6305
|
-
console.error(
|
|
6560
|
+
console.error(chalk83.red("Could not find git repository root"));
|
|
6306
6561
|
process.exit(1);
|
|
6307
6562
|
}
|
|
6308
6563
|
return { resolved, repoRoot };
|
|
@@ -6352,12 +6607,12 @@ function getChangedCsFiles(scope) {
|
|
|
6352
6607
|
}
|
|
6353
6608
|
|
|
6354
6609
|
// src/commands/dotnet/inSln.ts
|
|
6355
|
-
import
|
|
6610
|
+
import chalk84 from "chalk";
|
|
6356
6611
|
async function inSln(csprojPath) {
|
|
6357
6612
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
6358
6613
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
6359
6614
|
if (solutions.length === 0) {
|
|
6360
|
-
console.log(
|
|
6615
|
+
console.log(chalk84.yellow("Not found in any .sln file"));
|
|
6361
6616
|
process.exit(1);
|
|
6362
6617
|
}
|
|
6363
6618
|
for (const sln of solutions) {
|
|
@@ -6366,7 +6621,7 @@ async function inSln(csprojPath) {
|
|
|
6366
6621
|
}
|
|
6367
6622
|
|
|
6368
6623
|
// src/commands/dotnet/inspect.ts
|
|
6369
|
-
import
|
|
6624
|
+
import chalk90 from "chalk";
|
|
6370
6625
|
|
|
6371
6626
|
// src/shared/formatElapsed.ts
|
|
6372
6627
|
function formatElapsed(ms) {
|
|
@@ -6378,12 +6633,12 @@ function formatElapsed(ms) {
|
|
|
6378
6633
|
}
|
|
6379
6634
|
|
|
6380
6635
|
// src/commands/dotnet/displayIssues.ts
|
|
6381
|
-
import
|
|
6636
|
+
import chalk85 from "chalk";
|
|
6382
6637
|
var SEVERITY_COLOR = {
|
|
6383
|
-
ERROR:
|
|
6384
|
-
WARNING:
|
|
6385
|
-
SUGGESTION:
|
|
6386
|
-
HINT:
|
|
6638
|
+
ERROR: chalk85.red,
|
|
6639
|
+
WARNING: chalk85.yellow,
|
|
6640
|
+
SUGGESTION: chalk85.cyan,
|
|
6641
|
+
HINT: chalk85.dim
|
|
6387
6642
|
};
|
|
6388
6643
|
function groupByFile(issues) {
|
|
6389
6644
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -6399,15 +6654,15 @@ function groupByFile(issues) {
|
|
|
6399
6654
|
}
|
|
6400
6655
|
function displayIssues(issues) {
|
|
6401
6656
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
6402
|
-
console.log(
|
|
6657
|
+
console.log(chalk85.bold(file));
|
|
6403
6658
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
6404
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
6659
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk85.white;
|
|
6405
6660
|
console.log(
|
|
6406
|
-
` ${
|
|
6661
|
+
` ${chalk85.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
6407
6662
|
);
|
|
6408
6663
|
}
|
|
6409
6664
|
}
|
|
6410
|
-
console.log(
|
|
6665
|
+
console.log(chalk85.dim(`
|
|
6411
6666
|
${issues.length} issue(s) found`));
|
|
6412
6667
|
}
|
|
6413
6668
|
|
|
@@ -6466,12 +6721,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
6466
6721
|
// src/commands/dotnet/resolveSolution.ts
|
|
6467
6722
|
import { existsSync as existsSync25 } from "fs";
|
|
6468
6723
|
import path25 from "path";
|
|
6469
|
-
import
|
|
6724
|
+
import chalk87 from "chalk";
|
|
6470
6725
|
|
|
6471
6726
|
// src/commands/dotnet/findSolution.ts
|
|
6472
6727
|
import { readdirSync as readdirSync4 } from "fs";
|
|
6473
6728
|
import { dirname as dirname16, join as join23 } from "path";
|
|
6474
|
-
import
|
|
6729
|
+
import chalk86 from "chalk";
|
|
6475
6730
|
function findSlnInDir(dir) {
|
|
6476
6731
|
try {
|
|
6477
6732
|
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join23(dir, f));
|
|
@@ -6487,17 +6742,17 @@ function findSolution() {
|
|
|
6487
6742
|
const slnFiles = findSlnInDir(current);
|
|
6488
6743
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
6489
6744
|
if (slnFiles.length > 1) {
|
|
6490
|
-
console.error(
|
|
6745
|
+
console.error(chalk86.red(`Multiple .sln files found in ${current}:`));
|
|
6491
6746
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
6492
6747
|
console.error(
|
|
6493
|
-
|
|
6748
|
+
chalk86.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
6494
6749
|
);
|
|
6495
6750
|
process.exit(1);
|
|
6496
6751
|
}
|
|
6497
6752
|
if (current === ceiling) break;
|
|
6498
6753
|
current = dirname16(current);
|
|
6499
6754
|
}
|
|
6500
|
-
console.error(
|
|
6755
|
+
console.error(chalk86.red("No .sln file found between cwd and repo root"));
|
|
6501
6756
|
process.exit(1);
|
|
6502
6757
|
}
|
|
6503
6758
|
|
|
@@ -6506,7 +6761,7 @@ function resolveSolution(sln) {
|
|
|
6506
6761
|
if (sln) {
|
|
6507
6762
|
const resolved = path25.resolve(sln);
|
|
6508
6763
|
if (!existsSync25(resolved)) {
|
|
6509
|
-
console.error(
|
|
6764
|
+
console.error(chalk87.red(`Solution file not found: ${resolved}`));
|
|
6510
6765
|
process.exit(1);
|
|
6511
6766
|
}
|
|
6512
6767
|
return resolved;
|
|
@@ -6548,14 +6803,14 @@ import { execSync as execSync23 } from "child_process";
|
|
|
6548
6803
|
import { existsSync as existsSync26, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
|
|
6549
6804
|
import { tmpdir as tmpdir2 } from "os";
|
|
6550
6805
|
import path26 from "path";
|
|
6551
|
-
import
|
|
6806
|
+
import chalk88 from "chalk";
|
|
6552
6807
|
function assertJbInstalled() {
|
|
6553
6808
|
try {
|
|
6554
6809
|
execSync23("jb inspectcode --version", { stdio: "pipe" });
|
|
6555
6810
|
} catch {
|
|
6556
|
-
console.error(
|
|
6811
|
+
console.error(chalk88.red("jb is not installed. Install with:"));
|
|
6557
6812
|
console.error(
|
|
6558
|
-
|
|
6813
|
+
chalk88.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
6559
6814
|
);
|
|
6560
6815
|
process.exit(1);
|
|
6561
6816
|
}
|
|
@@ -6573,11 +6828,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6573
6828
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
6574
6829
|
process.stderr.write(err.stderr);
|
|
6575
6830
|
}
|
|
6576
|
-
console.error(
|
|
6831
|
+
console.error(chalk88.red("jb inspectcode failed"));
|
|
6577
6832
|
process.exit(1);
|
|
6578
6833
|
}
|
|
6579
6834
|
if (!existsSync26(reportPath)) {
|
|
6580
|
-
console.error(
|
|
6835
|
+
console.error(chalk88.red("Report file not generated"));
|
|
6581
6836
|
process.exit(1);
|
|
6582
6837
|
}
|
|
6583
6838
|
const xml = readFileSync24(reportPath, "utf-8");
|
|
@@ -6587,7 +6842,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6587
6842
|
|
|
6588
6843
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
6589
6844
|
import { execSync as execSync24 } from "child_process";
|
|
6590
|
-
import
|
|
6845
|
+
import chalk89 from "chalk";
|
|
6591
6846
|
function resolveMsbuildPath() {
|
|
6592
6847
|
const config = loadConfig();
|
|
6593
6848
|
const buildConfig = config.run?.find((r) => r.name === "build");
|
|
@@ -6598,9 +6853,9 @@ function assertMsbuildInstalled() {
|
|
|
6598
6853
|
try {
|
|
6599
6854
|
execSync24(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
6600
6855
|
} catch {
|
|
6601
|
-
console.error(
|
|
6856
|
+
console.error(chalk89.red(`msbuild not found at: ${msbuild}`));
|
|
6602
6857
|
console.error(
|
|
6603
|
-
|
|
6858
|
+
chalk89.yellow(
|
|
6604
6859
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
6605
6860
|
)
|
|
6606
6861
|
);
|
|
@@ -6647,17 +6902,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
6647
6902
|
// src/commands/dotnet/inspect.ts
|
|
6648
6903
|
function logScope(changedFiles) {
|
|
6649
6904
|
if (changedFiles === null) {
|
|
6650
|
-
console.log(
|
|
6905
|
+
console.log(chalk90.dim("Inspecting full solution..."));
|
|
6651
6906
|
} else {
|
|
6652
6907
|
console.log(
|
|
6653
|
-
|
|
6908
|
+
chalk90.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
6654
6909
|
);
|
|
6655
6910
|
}
|
|
6656
6911
|
}
|
|
6657
6912
|
function reportResults(issues, elapsed) {
|
|
6658
6913
|
if (issues.length > 0) displayIssues(issues);
|
|
6659
|
-
else console.log(
|
|
6660
|
-
console.log(
|
|
6914
|
+
else console.log(chalk90.green("No issues found"));
|
|
6915
|
+
console.log(chalk90.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
6661
6916
|
if (issues.length > 0) process.exit(1);
|
|
6662
6917
|
}
|
|
6663
6918
|
async function inspect(sln, options2) {
|
|
@@ -6668,7 +6923,7 @@ async function inspect(sln, options2) {
|
|
|
6668
6923
|
const scope = parseScope(options2.scope);
|
|
6669
6924
|
const changedFiles = getChangedCsFiles(scope);
|
|
6670
6925
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
6671
|
-
console.log(
|
|
6926
|
+
console.log(chalk90.green("No changed .cs files found"));
|
|
6672
6927
|
return;
|
|
6673
6928
|
}
|
|
6674
6929
|
logScope(changedFiles);
|
|
@@ -6694,7 +6949,7 @@ function registerDotnet(program2) {
|
|
|
6694
6949
|
}
|
|
6695
6950
|
|
|
6696
6951
|
// src/commands/jira/acceptanceCriteria.ts
|
|
6697
|
-
import
|
|
6952
|
+
import chalk92 from "chalk";
|
|
6698
6953
|
|
|
6699
6954
|
// src/commands/jira/adfToText.ts
|
|
6700
6955
|
function renderInline(node) {
|
|
@@ -6755,7 +7010,7 @@ function adfToText(doc) {
|
|
|
6755
7010
|
|
|
6756
7011
|
// src/commands/jira/fetchIssue.ts
|
|
6757
7012
|
import { execSync as execSync25 } from "child_process";
|
|
6758
|
-
import
|
|
7013
|
+
import chalk91 from "chalk";
|
|
6759
7014
|
function fetchIssue(issueKey, fields) {
|
|
6760
7015
|
let result;
|
|
6761
7016
|
try {
|
|
@@ -6768,15 +7023,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
6768
7023
|
const stderr = error.stderr;
|
|
6769
7024
|
if (stderr.includes("unauthorized")) {
|
|
6770
7025
|
console.error(
|
|
6771
|
-
|
|
7026
|
+
chalk91.red("Jira authentication expired."),
|
|
6772
7027
|
"Run",
|
|
6773
|
-
|
|
7028
|
+
chalk91.cyan("assist jira auth"),
|
|
6774
7029
|
"to re-authenticate."
|
|
6775
7030
|
);
|
|
6776
7031
|
process.exit(1);
|
|
6777
7032
|
}
|
|
6778
7033
|
}
|
|
6779
|
-
console.error(
|
|
7034
|
+
console.error(chalk91.red(`Failed to fetch ${issueKey}.`));
|
|
6780
7035
|
process.exit(1);
|
|
6781
7036
|
}
|
|
6782
7037
|
return JSON.parse(result);
|
|
@@ -6790,7 +7045,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
6790
7045
|
const parsed = fetchIssue(issueKey, field);
|
|
6791
7046
|
const acValue = parsed?.fields?.[field];
|
|
6792
7047
|
if (!acValue) {
|
|
6793
|
-
console.log(
|
|
7048
|
+
console.log(chalk92.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
6794
7049
|
return;
|
|
6795
7050
|
}
|
|
6796
7051
|
if (typeof acValue === "string") {
|
|
@@ -6885,14 +7140,14 @@ async function jiraAuth() {
|
|
|
6885
7140
|
}
|
|
6886
7141
|
|
|
6887
7142
|
// src/commands/jira/viewIssue.ts
|
|
6888
|
-
import
|
|
7143
|
+
import chalk93 from "chalk";
|
|
6889
7144
|
function viewIssue(issueKey) {
|
|
6890
7145
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
6891
7146
|
const fields = parsed?.fields;
|
|
6892
7147
|
const summary = fields?.summary;
|
|
6893
7148
|
const description = fields?.description;
|
|
6894
7149
|
if (summary) {
|
|
6895
|
-
console.log(
|
|
7150
|
+
console.log(chalk93.bold(summary));
|
|
6896
7151
|
}
|
|
6897
7152
|
if (description) {
|
|
6898
7153
|
if (summary) console.log();
|
|
@@ -6906,7 +7161,7 @@ function viewIssue(issueKey) {
|
|
|
6906
7161
|
}
|
|
6907
7162
|
if (!summary && !description) {
|
|
6908
7163
|
console.log(
|
|
6909
|
-
|
|
7164
|
+
chalk93.yellow(`No summary or description found on ${issueKey}.`)
|
|
6910
7165
|
);
|
|
6911
7166
|
}
|
|
6912
7167
|
}
|
|
@@ -6920,11 +7175,11 @@ function registerJira(program2) {
|
|
|
6920
7175
|
}
|
|
6921
7176
|
|
|
6922
7177
|
// src/commands/news/add/index.ts
|
|
6923
|
-
import
|
|
6924
|
-
import
|
|
7178
|
+
import chalk94 from "chalk";
|
|
7179
|
+
import enquirer8 from "enquirer";
|
|
6925
7180
|
async function add2(url) {
|
|
6926
7181
|
if (!url) {
|
|
6927
|
-
const response = await
|
|
7182
|
+
const response = await enquirer8.prompt({
|
|
6928
7183
|
type: "input",
|
|
6929
7184
|
name: "url",
|
|
6930
7185
|
message: "RSS feed URL:",
|
|
@@ -6943,17 +7198,17 @@ async function add2(url) {
|
|
|
6943
7198
|
const news = config.news ?? {};
|
|
6944
7199
|
const feeds = news.feeds ?? [];
|
|
6945
7200
|
if (feeds.includes(url)) {
|
|
6946
|
-
console.log(
|
|
7201
|
+
console.log(chalk94.yellow("Feed already exists in config"));
|
|
6947
7202
|
return;
|
|
6948
7203
|
}
|
|
6949
7204
|
feeds.push(url);
|
|
6950
7205
|
config.news = { ...news, feeds };
|
|
6951
7206
|
saveGlobalConfig(config);
|
|
6952
|
-
console.log(
|
|
7207
|
+
console.log(chalk94.green(`Added feed: ${url}`));
|
|
6953
7208
|
}
|
|
6954
7209
|
|
|
6955
7210
|
// src/commands/news/web/handleRequest.ts
|
|
6956
|
-
import
|
|
7211
|
+
import chalk95 from "chalk";
|
|
6957
7212
|
|
|
6958
7213
|
// src/commands/news/web/shared.ts
|
|
6959
7214
|
import { decodeHTML } from "entities";
|
|
@@ -7089,17 +7344,17 @@ function prefetch() {
|
|
|
7089
7344
|
const config = loadConfig();
|
|
7090
7345
|
const total = config.news.feeds.length;
|
|
7091
7346
|
if (total === 0) return;
|
|
7092
|
-
process.stdout.write(
|
|
7347
|
+
process.stdout.write(chalk95.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
7093
7348
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
7094
7349
|
const width = 20;
|
|
7095
7350
|
const filled = Math.round(done2 / t * width);
|
|
7096
7351
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
7097
7352
|
process.stdout.write(
|
|
7098
|
-
`\r${
|
|
7353
|
+
`\r${chalk95.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
7099
7354
|
);
|
|
7100
7355
|
}).then((items) => {
|
|
7101
7356
|
process.stdout.write(
|
|
7102
|
-
`\r${
|
|
7357
|
+
`\r${chalk95.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
7103
7358
|
`
|
|
7104
7359
|
);
|
|
7105
7360
|
cachedItems = items;
|
|
@@ -7460,20 +7715,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
7460
7715
|
}
|
|
7461
7716
|
|
|
7462
7717
|
// src/commands/prs/listComments/printComments.ts
|
|
7463
|
-
import
|
|
7718
|
+
import chalk96 from "chalk";
|
|
7464
7719
|
function formatForHuman(comment3) {
|
|
7465
7720
|
if (comment3.type === "review") {
|
|
7466
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
7721
|
+
const stateColor = comment3.state === "APPROVED" ? chalk96.green : comment3.state === "CHANGES_REQUESTED" ? chalk96.red : chalk96.yellow;
|
|
7467
7722
|
return [
|
|
7468
|
-
`${
|
|
7723
|
+
`${chalk96.cyan("Review")} by ${chalk96.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
7469
7724
|
comment3.body,
|
|
7470
7725
|
""
|
|
7471
7726
|
].join("\n");
|
|
7472
7727
|
}
|
|
7473
7728
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
7474
7729
|
return [
|
|
7475
|
-
`${
|
|
7476
|
-
|
|
7730
|
+
`${chalk96.cyan("Line comment")} by ${chalk96.bold(comment3.user)} on ${chalk96.dim(`${comment3.path}${location}`)}`,
|
|
7731
|
+
chalk96.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
7477
7732
|
comment3.body,
|
|
7478
7733
|
""
|
|
7479
7734
|
].join("\n");
|
|
@@ -7560,16 +7815,16 @@ async function listComments() {
|
|
|
7560
7815
|
import { execSync as execSync32 } from "child_process";
|
|
7561
7816
|
|
|
7562
7817
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
7563
|
-
import
|
|
7818
|
+
import enquirer9 from "enquirer";
|
|
7564
7819
|
|
|
7565
7820
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
7566
|
-
import
|
|
7821
|
+
import chalk97 from "chalk";
|
|
7567
7822
|
var STATUS_MAP = {
|
|
7568
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
7569
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
7823
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk97.magenta("merged"), date: pr.mergedAt } : null,
|
|
7824
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk97.red("closed"), date: pr.closedAt } : null
|
|
7570
7825
|
};
|
|
7571
7826
|
function defaultStatus(pr) {
|
|
7572
|
-
return { label:
|
|
7827
|
+
return { label: chalk97.green("opened"), date: pr.createdAt };
|
|
7573
7828
|
}
|
|
7574
7829
|
function getStatus2(pr) {
|
|
7575
7830
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -7578,11 +7833,11 @@ function formatDate(dateStr) {
|
|
|
7578
7833
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
7579
7834
|
}
|
|
7580
7835
|
function formatPrHeader(pr, status2) {
|
|
7581
|
-
return `${
|
|
7836
|
+
return `${chalk97.cyan(`#${pr.number}`)} ${pr.title} ${chalk97.dim(`(${pr.author.login},`)} ${status2.label} ${chalk97.dim(`${formatDate(status2.date)})`)}`;
|
|
7582
7837
|
}
|
|
7583
7838
|
function logPrDetails(pr) {
|
|
7584
7839
|
console.log(
|
|
7585
|
-
|
|
7840
|
+
chalk97.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
7586
7841
|
);
|
|
7587
7842
|
console.log();
|
|
7588
7843
|
}
|
|
@@ -7630,7 +7885,7 @@ function parseAction(action) {
|
|
|
7630
7885
|
}
|
|
7631
7886
|
async function promptNavigation(currentPage, totalPages) {
|
|
7632
7887
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
7633
|
-
const { action } = await
|
|
7888
|
+
const { action } = await enquirer9.prompt({
|
|
7634
7889
|
type: "select",
|
|
7635
7890
|
name: "action",
|
|
7636
7891
|
message: "Navigate",
|
|
@@ -7748,10 +8003,10 @@ function registerPrs(program2) {
|
|
|
7748
8003
|
}
|
|
7749
8004
|
|
|
7750
8005
|
// src/commands/ravendb/ravendbAuth.ts
|
|
7751
|
-
import
|
|
8006
|
+
import chalk103 from "chalk";
|
|
7752
8007
|
|
|
7753
8008
|
// src/shared/createConnectionAuth.ts
|
|
7754
|
-
import
|
|
8009
|
+
import chalk98 from "chalk";
|
|
7755
8010
|
function listConnections(connections, format2) {
|
|
7756
8011
|
if (connections.length === 0) {
|
|
7757
8012
|
console.log("No connections configured.");
|
|
@@ -7764,7 +8019,7 @@ function listConnections(connections, format2) {
|
|
|
7764
8019
|
function removeConnection(connections, name, save) {
|
|
7765
8020
|
const filtered = connections.filter((c) => c.name !== name);
|
|
7766
8021
|
if (filtered.length === connections.length) {
|
|
7767
|
-
console.error(
|
|
8022
|
+
console.error(chalk98.red(`Connection "${name}" not found.`));
|
|
7768
8023
|
process.exit(1);
|
|
7769
8024
|
}
|
|
7770
8025
|
save(filtered);
|
|
@@ -7810,15 +8065,15 @@ function saveConnections(connections) {
|
|
|
7810
8065
|
}
|
|
7811
8066
|
|
|
7812
8067
|
// src/commands/ravendb/promptConnection.ts
|
|
7813
|
-
import
|
|
8068
|
+
import chalk101 from "chalk";
|
|
7814
8069
|
|
|
7815
8070
|
// src/commands/ravendb/selectOpSecret.ts
|
|
7816
|
-
import
|
|
8071
|
+
import chalk100 from "chalk";
|
|
7817
8072
|
import Enquirer2 from "enquirer";
|
|
7818
8073
|
|
|
7819
8074
|
// src/commands/ravendb/searchItems.ts
|
|
7820
8075
|
import { execSync as execSync34 } from "child_process";
|
|
7821
|
-
import
|
|
8076
|
+
import chalk99 from "chalk";
|
|
7822
8077
|
function opExec(args) {
|
|
7823
8078
|
return execSync34(`op ${args}`, {
|
|
7824
8079
|
encoding: "utf-8",
|
|
@@ -7831,7 +8086,7 @@ function searchItems(search2) {
|
|
|
7831
8086
|
items = JSON.parse(opExec("item list --format=json"));
|
|
7832
8087
|
} catch {
|
|
7833
8088
|
console.error(
|
|
7834
|
-
|
|
8089
|
+
chalk99.red(
|
|
7835
8090
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
7836
8091
|
)
|
|
7837
8092
|
);
|
|
@@ -7845,7 +8100,7 @@ function getItemFields(itemId) {
|
|
|
7845
8100
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
7846
8101
|
return item.fields.filter((f) => f.reference && f.label);
|
|
7847
8102
|
} catch {
|
|
7848
|
-
console.error(
|
|
8103
|
+
console.error(chalk99.red("Failed to get item details from 1Password."));
|
|
7849
8104
|
process.exit(1);
|
|
7850
8105
|
}
|
|
7851
8106
|
}
|
|
@@ -7864,7 +8119,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7864
8119
|
}).run();
|
|
7865
8120
|
const items = searchItems(search2);
|
|
7866
8121
|
if (items.length === 0) {
|
|
7867
|
-
console.error(
|
|
8122
|
+
console.error(chalk100.red(`No items found matching "${search2}".`));
|
|
7868
8123
|
process.exit(1);
|
|
7869
8124
|
}
|
|
7870
8125
|
const itemId = await selectOne(
|
|
@@ -7873,7 +8128,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7873
8128
|
);
|
|
7874
8129
|
const fields = getItemFields(itemId);
|
|
7875
8130
|
if (fields.length === 0) {
|
|
7876
|
-
console.error(
|
|
8131
|
+
console.error(chalk100.red("No fields with references found on this item."));
|
|
7877
8132
|
process.exit(1);
|
|
7878
8133
|
}
|
|
7879
8134
|
const ref = await selectOne(
|
|
@@ -7887,7 +8142,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
7887
8142
|
async function promptConnection(existingNames) {
|
|
7888
8143
|
const name = await promptInput("name", "Connection name:");
|
|
7889
8144
|
if (existingNames.includes(name)) {
|
|
7890
|
-
console.error(
|
|
8145
|
+
console.error(chalk101.red(`Connection "${name}" already exists.`));
|
|
7891
8146
|
process.exit(1);
|
|
7892
8147
|
}
|
|
7893
8148
|
const url = await promptInput(
|
|
@@ -7896,22 +8151,22 @@ async function promptConnection(existingNames) {
|
|
|
7896
8151
|
);
|
|
7897
8152
|
const database = await promptInput("database", "Database name:");
|
|
7898
8153
|
if (!name || !url || !database) {
|
|
7899
|
-
console.error(
|
|
8154
|
+
console.error(chalk101.red("All fields are required."));
|
|
7900
8155
|
process.exit(1);
|
|
7901
8156
|
}
|
|
7902
8157
|
const apiKeyRef = await selectOpSecret();
|
|
7903
|
-
console.log(
|
|
8158
|
+
console.log(chalk101.dim(`Using: ${apiKeyRef}`));
|
|
7904
8159
|
return { name, url, database, apiKeyRef };
|
|
7905
8160
|
}
|
|
7906
8161
|
|
|
7907
8162
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
7908
|
-
import
|
|
8163
|
+
import chalk102 from "chalk";
|
|
7909
8164
|
function ravendbSetConnection(name) {
|
|
7910
8165
|
const raw = loadGlobalConfigRaw();
|
|
7911
8166
|
const ravendb = raw.ravendb ?? {};
|
|
7912
8167
|
const connections = ravendb.connections ?? [];
|
|
7913
8168
|
if (!connections.some((c) => c.name === name)) {
|
|
7914
|
-
console.error(
|
|
8169
|
+
console.error(chalk102.red(`Connection "${name}" not found.`));
|
|
7915
8170
|
console.error(
|
|
7916
8171
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
7917
8172
|
);
|
|
@@ -7927,16 +8182,16 @@ function ravendbSetConnection(name) {
|
|
|
7927
8182
|
var ravendbAuth = createConnectionAuth({
|
|
7928
8183
|
load: loadConnections,
|
|
7929
8184
|
save: saveConnections,
|
|
7930
|
-
format: (c) => `${
|
|
8185
|
+
format: (c) => `${chalk103.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
7931
8186
|
promptNew: promptConnection,
|
|
7932
8187
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
7933
8188
|
});
|
|
7934
8189
|
|
|
7935
8190
|
// src/commands/ravendb/ravendbCollections.ts
|
|
7936
|
-
import
|
|
8191
|
+
import chalk107 from "chalk";
|
|
7937
8192
|
|
|
7938
8193
|
// src/commands/ravendb/ravenFetch.ts
|
|
7939
|
-
import
|
|
8194
|
+
import chalk105 from "chalk";
|
|
7940
8195
|
|
|
7941
8196
|
// src/commands/ravendb/getAccessToken.ts
|
|
7942
8197
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -7973,10 +8228,10 @@ ${errorText}`
|
|
|
7973
8228
|
|
|
7974
8229
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
7975
8230
|
import { execSync as execSync35 } from "child_process";
|
|
7976
|
-
import
|
|
8231
|
+
import chalk104 from "chalk";
|
|
7977
8232
|
function resolveOpSecret(reference) {
|
|
7978
8233
|
if (!reference.startsWith("op://")) {
|
|
7979
|
-
console.error(
|
|
8234
|
+
console.error(chalk104.red(`Invalid secret reference: must start with op://`));
|
|
7980
8235
|
process.exit(1);
|
|
7981
8236
|
}
|
|
7982
8237
|
try {
|
|
@@ -7986,7 +8241,7 @@ function resolveOpSecret(reference) {
|
|
|
7986
8241
|
}).trim();
|
|
7987
8242
|
} catch {
|
|
7988
8243
|
console.error(
|
|
7989
|
-
|
|
8244
|
+
chalk104.red(
|
|
7990
8245
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
7991
8246
|
)
|
|
7992
8247
|
);
|
|
@@ -8013,7 +8268,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8013
8268
|
if (!response.ok) {
|
|
8014
8269
|
const body = await response.text();
|
|
8015
8270
|
console.error(
|
|
8016
|
-
|
|
8271
|
+
chalk105.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
8017
8272
|
);
|
|
8018
8273
|
console.error(body.substring(0, 500));
|
|
8019
8274
|
process.exit(1);
|
|
@@ -8022,7 +8277,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8022
8277
|
}
|
|
8023
8278
|
|
|
8024
8279
|
// src/commands/ravendb/resolveConnection.ts
|
|
8025
|
-
import
|
|
8280
|
+
import chalk106 from "chalk";
|
|
8026
8281
|
function loadRavendb() {
|
|
8027
8282
|
const raw = loadGlobalConfigRaw();
|
|
8028
8283
|
const ravendb = raw.ravendb;
|
|
@@ -8036,7 +8291,7 @@ function resolveConnection(name) {
|
|
|
8036
8291
|
const connectionName = name ?? defaultConnection;
|
|
8037
8292
|
if (!connectionName) {
|
|
8038
8293
|
console.error(
|
|
8039
|
-
|
|
8294
|
+
chalk106.red(
|
|
8040
8295
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
8041
8296
|
)
|
|
8042
8297
|
);
|
|
@@ -8044,7 +8299,7 @@ function resolveConnection(name) {
|
|
|
8044
8299
|
}
|
|
8045
8300
|
const connection = connections.find((c) => c.name === connectionName);
|
|
8046
8301
|
if (!connection) {
|
|
8047
|
-
console.error(
|
|
8302
|
+
console.error(chalk106.red(`Connection "${connectionName}" not found.`));
|
|
8048
8303
|
console.error(
|
|
8049
8304
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
8050
8305
|
);
|
|
@@ -8075,15 +8330,15 @@ async function ravendbCollections(connectionName) {
|
|
|
8075
8330
|
return;
|
|
8076
8331
|
}
|
|
8077
8332
|
for (const c of collections) {
|
|
8078
|
-
console.log(`${
|
|
8333
|
+
console.log(`${chalk107.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
8079
8334
|
}
|
|
8080
8335
|
}
|
|
8081
8336
|
|
|
8082
8337
|
// src/commands/ravendb/ravendbQuery.ts
|
|
8083
|
-
import
|
|
8338
|
+
import chalk109 from "chalk";
|
|
8084
8339
|
|
|
8085
8340
|
// src/commands/ravendb/fetchAllPages.ts
|
|
8086
|
-
import
|
|
8341
|
+
import chalk108 from "chalk";
|
|
8087
8342
|
|
|
8088
8343
|
// src/commands/ravendb/buildQueryPath.ts
|
|
8089
8344
|
function buildQueryPath(opts) {
|
|
@@ -8121,7 +8376,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8121
8376
|
allResults.push(...results);
|
|
8122
8377
|
start3 += results.length;
|
|
8123
8378
|
process.stderr.write(
|
|
8124
|
-
`\r${
|
|
8379
|
+
`\r${chalk108.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
8125
8380
|
);
|
|
8126
8381
|
if (start3 >= totalResults) break;
|
|
8127
8382
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -8136,7 +8391,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8136
8391
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
8137
8392
|
const resolved = resolveArgs(connectionName, collection);
|
|
8138
8393
|
if (!resolved.collection && !options2.query) {
|
|
8139
|
-
console.error(
|
|
8394
|
+
console.error(chalk109.red("Provide a collection name or --query filter."));
|
|
8140
8395
|
process.exit(1);
|
|
8141
8396
|
}
|
|
8142
8397
|
const { collection: col } = resolved;
|
|
@@ -8174,7 +8429,7 @@ import { spawn as spawn4 } from "child_process";
|
|
|
8174
8429
|
import * as path27 from "path";
|
|
8175
8430
|
|
|
8176
8431
|
// src/commands/refactor/logViolations.ts
|
|
8177
|
-
import
|
|
8432
|
+
import chalk110 from "chalk";
|
|
8178
8433
|
var DEFAULT_MAX_LINES = 100;
|
|
8179
8434
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
8180
8435
|
if (violations.length === 0) {
|
|
@@ -8183,43 +8438,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
8183
8438
|
}
|
|
8184
8439
|
return;
|
|
8185
8440
|
}
|
|
8186
|
-
console.error(
|
|
8441
|
+
console.error(chalk110.red(`
|
|
8187
8442
|
Refactor check failed:
|
|
8188
8443
|
`));
|
|
8189
|
-
console.error(
|
|
8444
|
+
console.error(chalk110.red(` The following files exceed ${maxLines} lines:
|
|
8190
8445
|
`));
|
|
8191
8446
|
for (const violation of violations) {
|
|
8192
|
-
console.error(
|
|
8447
|
+
console.error(chalk110.red(` ${violation.file} (${violation.lines} lines)`));
|
|
8193
8448
|
}
|
|
8194
8449
|
console.error(
|
|
8195
|
-
|
|
8450
|
+
chalk110.yellow(
|
|
8196
8451
|
`
|
|
8197
8452
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
8198
8453
|
way to refactor it, ignore it with:
|
|
8199
8454
|
`
|
|
8200
8455
|
)
|
|
8201
8456
|
);
|
|
8202
|
-
console.error(
|
|
8457
|
+
console.error(chalk110.gray(` assist refactor ignore <file>
|
|
8203
8458
|
`));
|
|
8204
8459
|
if (process.env.CLAUDECODE) {
|
|
8205
|
-
console.error(
|
|
8460
|
+
console.error(chalk110.cyan(`
|
|
8206
8461
|
## Extracting Code to New Files
|
|
8207
8462
|
`));
|
|
8208
8463
|
console.error(
|
|
8209
|
-
|
|
8464
|
+
chalk110.cyan(
|
|
8210
8465
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
8211
8466
|
`
|
|
8212
8467
|
)
|
|
8213
8468
|
);
|
|
8214
8469
|
console.error(
|
|
8215
|
-
|
|
8470
|
+
chalk110.cyan(
|
|
8216
8471
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
8217
8472
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
8218
8473
|
`
|
|
8219
8474
|
)
|
|
8220
8475
|
);
|
|
8221
8476
|
console.error(
|
|
8222
|
-
|
|
8477
|
+
chalk110.cyan(
|
|
8223
8478
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
8224
8479
|
domains, move it to a common/shared folder.
|
|
8225
8480
|
`
|
|
@@ -8375,7 +8630,7 @@ async function check(pattern2, options2) {
|
|
|
8375
8630
|
|
|
8376
8631
|
// src/commands/refactor/extract/index.ts
|
|
8377
8632
|
import path33 from "path";
|
|
8378
|
-
import
|
|
8633
|
+
import chalk113 from "chalk";
|
|
8379
8634
|
|
|
8380
8635
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
8381
8636
|
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
@@ -8922,23 +9177,23 @@ function buildPlan(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
8922
9177
|
|
|
8923
9178
|
// src/commands/refactor/extract/displayPlan.ts
|
|
8924
9179
|
import path31 from "path";
|
|
8925
|
-
import
|
|
9180
|
+
import chalk111 from "chalk";
|
|
8926
9181
|
function section(title) {
|
|
8927
9182
|
return `
|
|
8928
|
-
${
|
|
9183
|
+
${chalk111.cyan(title)}`;
|
|
8929
9184
|
}
|
|
8930
9185
|
function displayImporters(plan2, cwd) {
|
|
8931
9186
|
if (plan2.importersToUpdate.length === 0) return;
|
|
8932
9187
|
console.log(section("Update importers:"));
|
|
8933
9188
|
for (const imp of plan2.importersToUpdate) {
|
|
8934
9189
|
const rel = path31.relative(cwd, imp.file.getFilePath());
|
|
8935
|
-
console.log(` ${
|
|
9190
|
+
console.log(` ${chalk111.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
8936
9191
|
}
|
|
8937
9192
|
}
|
|
8938
9193
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
8939
|
-
console.log(
|
|
9194
|
+
console.log(chalk111.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
8940
9195
|
`));
|
|
8941
|
-
console.log(` ${
|
|
9196
|
+
console.log(` ${chalk111.cyan("Functions to move:")}`);
|
|
8942
9197
|
for (const name of plan2.extractedNames) {
|
|
8943
9198
|
console.log(` ${name}`);
|
|
8944
9199
|
}
|
|
@@ -8973,7 +9228,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
8973
9228
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
8974
9229
|
import fs17 from "fs";
|
|
8975
9230
|
import path32 from "path";
|
|
8976
|
-
import
|
|
9231
|
+
import chalk112 from "chalk";
|
|
8977
9232
|
import { Project as Project2 } from "ts-morph";
|
|
8978
9233
|
function findTsConfig(sourcePath) {
|
|
8979
9234
|
const rootConfig = path32.resolve("tsconfig.json");
|
|
@@ -9004,7 +9259,7 @@ function loadProjectFile(file) {
|
|
|
9004
9259
|
});
|
|
9005
9260
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
9006
9261
|
if (!sourceFile) {
|
|
9007
|
-
console.log(
|
|
9262
|
+
console.log(chalk112.red(`File not found in project: ${file}`));
|
|
9008
9263
|
process.exit(1);
|
|
9009
9264
|
}
|
|
9010
9265
|
return { project, sourceFile };
|
|
@@ -9027,19 +9282,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
9027
9282
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
9028
9283
|
if (options2.apply) {
|
|
9029
9284
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
9030
|
-
console.log(
|
|
9285
|
+
console.log(chalk113.green("\nExtraction complete"));
|
|
9031
9286
|
} else {
|
|
9032
|
-
console.log(
|
|
9287
|
+
console.log(chalk113.dim("\nDry run. Use --apply to execute."));
|
|
9033
9288
|
}
|
|
9034
9289
|
}
|
|
9035
9290
|
|
|
9036
9291
|
// src/commands/refactor/ignore.ts
|
|
9037
9292
|
import fs18 from "fs";
|
|
9038
|
-
import
|
|
9293
|
+
import chalk114 from "chalk";
|
|
9039
9294
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
9040
9295
|
function ignore(file) {
|
|
9041
9296
|
if (!fs18.existsSync(file)) {
|
|
9042
|
-
console.error(
|
|
9297
|
+
console.error(chalk114.red(`Error: File does not exist: ${file}`));
|
|
9043
9298
|
process.exit(1);
|
|
9044
9299
|
}
|
|
9045
9300
|
const content = fs18.readFileSync(file, "utf-8");
|
|
@@ -9055,7 +9310,7 @@ function ignore(file) {
|
|
|
9055
9310
|
fs18.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
9056
9311
|
}
|
|
9057
9312
|
console.log(
|
|
9058
|
-
|
|
9313
|
+
chalk114.green(
|
|
9059
9314
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
9060
9315
|
)
|
|
9061
9316
|
);
|
|
@@ -9063,26 +9318,26 @@ function ignore(file) {
|
|
|
9063
9318
|
|
|
9064
9319
|
// src/commands/refactor/rename/index.ts
|
|
9065
9320
|
import path34 from "path";
|
|
9066
|
-
import
|
|
9321
|
+
import chalk115 from "chalk";
|
|
9067
9322
|
async function rename(source, destination, options2 = {}) {
|
|
9068
9323
|
const destPath = path34.resolve(destination);
|
|
9069
9324
|
const cwd = process.cwd();
|
|
9070
9325
|
const relSource = path34.relative(cwd, path34.resolve(source));
|
|
9071
9326
|
const relDest = path34.relative(cwd, destPath);
|
|
9072
9327
|
const { project, sourceFile } = loadProjectFile(source);
|
|
9073
|
-
console.log(
|
|
9328
|
+
console.log(chalk115.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
9074
9329
|
if (options2.apply) {
|
|
9075
9330
|
sourceFile.move(destPath);
|
|
9076
9331
|
await project.save();
|
|
9077
|
-
console.log(
|
|
9332
|
+
console.log(chalk115.green("Done"));
|
|
9078
9333
|
} else {
|
|
9079
|
-
console.log(
|
|
9334
|
+
console.log(chalk115.dim("Dry run. Use --apply to execute."));
|
|
9080
9335
|
}
|
|
9081
9336
|
}
|
|
9082
9337
|
|
|
9083
9338
|
// src/commands/refactor/renameSymbol/index.ts
|
|
9084
9339
|
import path36 from "path";
|
|
9085
|
-
import
|
|
9340
|
+
import chalk116 from "chalk";
|
|
9086
9341
|
import { Project as Project3 } from "ts-morph";
|
|
9087
9342
|
|
|
9088
9343
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
@@ -9131,38 +9386,38 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
9131
9386
|
const project = new Project3({ tsConfigFilePath: tsConfigPath });
|
|
9132
9387
|
const sourceFile = project.getSourceFile(filePath);
|
|
9133
9388
|
if (!sourceFile) {
|
|
9134
|
-
console.log(
|
|
9389
|
+
console.log(chalk116.red(`File not found in project: ${file}`));
|
|
9135
9390
|
process.exit(1);
|
|
9136
9391
|
}
|
|
9137
9392
|
const symbol = findSymbol(sourceFile, oldName);
|
|
9138
9393
|
if (!symbol) {
|
|
9139
|
-
console.log(
|
|
9394
|
+
console.log(chalk116.red(`Symbol "${oldName}" not found in ${file}`));
|
|
9140
9395
|
process.exit(1);
|
|
9141
9396
|
}
|
|
9142
9397
|
const grouped = groupReferences(symbol, cwd);
|
|
9143
9398
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
9144
9399
|
console.log(
|
|
9145
|
-
|
|
9400
|
+
chalk116.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
9146
9401
|
`)
|
|
9147
9402
|
);
|
|
9148
9403
|
for (const [refFile, lines] of grouped) {
|
|
9149
9404
|
console.log(
|
|
9150
|
-
` ${
|
|
9405
|
+
` ${chalk116.dim(refFile)}: lines ${chalk116.cyan(lines.join(", "))}`
|
|
9151
9406
|
);
|
|
9152
9407
|
}
|
|
9153
9408
|
if (options2.apply) {
|
|
9154
9409
|
symbol.rename(newName);
|
|
9155
9410
|
await project.save();
|
|
9156
|
-
console.log(
|
|
9411
|
+
console.log(chalk116.green(`
|
|
9157
9412
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
9158
9413
|
} else {
|
|
9159
|
-
console.log(
|
|
9414
|
+
console.log(chalk116.dim("\nDry run. Use --apply to execute."));
|
|
9160
9415
|
}
|
|
9161
9416
|
}
|
|
9162
9417
|
|
|
9163
9418
|
// src/commands/refactor/restructure/index.ts
|
|
9164
9419
|
import path45 from "path";
|
|
9165
|
-
import
|
|
9420
|
+
import chalk119 from "chalk";
|
|
9166
9421
|
|
|
9167
9422
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
9168
9423
|
import path37 from "path";
|
|
@@ -9405,50 +9660,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
9405
9660
|
|
|
9406
9661
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
9407
9662
|
import path41 from "path";
|
|
9408
|
-
import
|
|
9663
|
+
import chalk117 from "chalk";
|
|
9409
9664
|
function relPath(filePath) {
|
|
9410
9665
|
return path41.relative(process.cwd(), filePath);
|
|
9411
9666
|
}
|
|
9412
9667
|
function displayMoves(plan2) {
|
|
9413
9668
|
if (plan2.moves.length === 0) return;
|
|
9414
|
-
console.log(
|
|
9669
|
+
console.log(chalk117.bold("\nFile moves:"));
|
|
9415
9670
|
for (const move of plan2.moves) {
|
|
9416
9671
|
console.log(
|
|
9417
|
-
` ${
|
|
9672
|
+
` ${chalk117.red(relPath(move.from))} \u2192 ${chalk117.green(relPath(move.to))}`
|
|
9418
9673
|
);
|
|
9419
|
-
console.log(
|
|
9674
|
+
console.log(chalk117.dim(` ${move.reason}`));
|
|
9420
9675
|
}
|
|
9421
9676
|
}
|
|
9422
9677
|
function displayRewrites(rewrites) {
|
|
9423
9678
|
if (rewrites.length === 0) return;
|
|
9424
9679
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
9425
|
-
console.log(
|
|
9680
|
+
console.log(chalk117.bold(`
|
|
9426
9681
|
Import rewrites (${affectedFiles.size} files):`));
|
|
9427
9682
|
for (const file of affectedFiles) {
|
|
9428
|
-
console.log(` ${
|
|
9683
|
+
console.log(` ${chalk117.cyan(relPath(file))}:`);
|
|
9429
9684
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
9430
9685
|
(r) => r.file === file
|
|
9431
9686
|
)) {
|
|
9432
9687
|
console.log(
|
|
9433
|
-
` ${
|
|
9688
|
+
` ${chalk117.red(`"${oldSpecifier}"`)} \u2192 ${chalk117.green(`"${newSpecifier}"`)}`
|
|
9434
9689
|
);
|
|
9435
9690
|
}
|
|
9436
9691
|
}
|
|
9437
9692
|
}
|
|
9438
9693
|
function displayPlan2(plan2) {
|
|
9439
9694
|
if (plan2.warnings.length > 0) {
|
|
9440
|
-
console.log(
|
|
9441
|
-
for (const w of plan2.warnings) console.log(
|
|
9695
|
+
console.log(chalk117.yellow("\nWarnings:"));
|
|
9696
|
+
for (const w of plan2.warnings) console.log(chalk117.yellow(` ${w}`));
|
|
9442
9697
|
}
|
|
9443
9698
|
if (plan2.newDirectories.length > 0) {
|
|
9444
|
-
console.log(
|
|
9699
|
+
console.log(chalk117.bold("\nNew directories:"));
|
|
9445
9700
|
for (const dir of plan2.newDirectories)
|
|
9446
|
-
console.log(
|
|
9701
|
+
console.log(chalk117.green(` ${dir}/`));
|
|
9447
9702
|
}
|
|
9448
9703
|
displayMoves(plan2);
|
|
9449
9704
|
displayRewrites(plan2.rewrites);
|
|
9450
9705
|
console.log(
|
|
9451
|
-
|
|
9706
|
+
chalk117.dim(
|
|
9452
9707
|
`
|
|
9453
9708
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
9454
9709
|
)
|
|
@@ -9458,18 +9713,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
9458
9713
|
// src/commands/refactor/restructure/executePlan.ts
|
|
9459
9714
|
import fs20 from "fs";
|
|
9460
9715
|
import path42 from "path";
|
|
9461
|
-
import
|
|
9716
|
+
import chalk118 from "chalk";
|
|
9462
9717
|
function executePlan(plan2) {
|
|
9463
9718
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
9464
9719
|
for (const [file, content] of updatedContents) {
|
|
9465
9720
|
fs20.writeFileSync(file, content, "utf-8");
|
|
9466
9721
|
console.log(
|
|
9467
|
-
|
|
9722
|
+
chalk118.cyan(` Rewrote imports in ${path42.relative(process.cwd(), file)}`)
|
|
9468
9723
|
);
|
|
9469
9724
|
}
|
|
9470
9725
|
for (const dir of plan2.newDirectories) {
|
|
9471
9726
|
fs20.mkdirSync(dir, { recursive: true });
|
|
9472
|
-
console.log(
|
|
9727
|
+
console.log(chalk118.green(` Created ${path42.relative(process.cwd(), dir)}/`));
|
|
9473
9728
|
}
|
|
9474
9729
|
for (const move of plan2.moves) {
|
|
9475
9730
|
const targetDir = path42.dirname(move.to);
|
|
@@ -9478,7 +9733,7 @@ function executePlan(plan2) {
|
|
|
9478
9733
|
}
|
|
9479
9734
|
fs20.renameSync(move.from, move.to);
|
|
9480
9735
|
console.log(
|
|
9481
|
-
|
|
9736
|
+
chalk118.white(
|
|
9482
9737
|
` Moved ${path42.relative(process.cwd(), move.from)} \u2192 ${path42.relative(process.cwd(), move.to)}`
|
|
9483
9738
|
)
|
|
9484
9739
|
);
|
|
@@ -9493,7 +9748,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
9493
9748
|
if (entries.length === 0) {
|
|
9494
9749
|
fs20.rmdirSync(dir);
|
|
9495
9750
|
console.log(
|
|
9496
|
-
|
|
9751
|
+
chalk118.dim(
|
|
9497
9752
|
` Removed empty directory ${path42.relative(process.cwd(), dir)}`
|
|
9498
9753
|
)
|
|
9499
9754
|
);
|
|
@@ -9626,22 +9881,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
9626
9881
|
const targetPattern = pattern2 ?? "src";
|
|
9627
9882
|
const files = findSourceFiles2(targetPattern);
|
|
9628
9883
|
if (files.length === 0) {
|
|
9629
|
-
console.log(
|
|
9884
|
+
console.log(chalk119.yellow("No files found matching pattern"));
|
|
9630
9885
|
return;
|
|
9631
9886
|
}
|
|
9632
9887
|
const tsConfigPath = path45.resolve("tsconfig.json");
|
|
9633
9888
|
const plan2 = buildPlan2(files, tsConfigPath);
|
|
9634
9889
|
if (plan2.moves.length === 0) {
|
|
9635
|
-
console.log(
|
|
9890
|
+
console.log(chalk119.green("No restructuring needed"));
|
|
9636
9891
|
return;
|
|
9637
9892
|
}
|
|
9638
9893
|
displayPlan2(plan2);
|
|
9639
9894
|
if (options2.apply) {
|
|
9640
|
-
console.log(
|
|
9895
|
+
console.log(chalk119.bold("\nApplying changes..."));
|
|
9641
9896
|
executePlan(plan2);
|
|
9642
|
-
console.log(
|
|
9897
|
+
console.log(chalk119.green("\nRestructuring complete"));
|
|
9643
9898
|
} else {
|
|
9644
|
-
console.log(
|
|
9899
|
+
console.log(chalk119.dim("\nDry run. Use --apply to execute."));
|
|
9645
9900
|
}
|
|
9646
9901
|
}
|
|
9647
9902
|
|
|
@@ -9681,7 +9936,7 @@ function registerRefactor(program2) {
|
|
|
9681
9936
|
}
|
|
9682
9937
|
|
|
9683
9938
|
// src/commands/seq/seqAuth.ts
|
|
9684
|
-
import
|
|
9939
|
+
import chalk121 from "chalk";
|
|
9685
9940
|
|
|
9686
9941
|
// src/commands/seq/loadConnections.ts
|
|
9687
9942
|
function loadConnections2() {
|
|
@@ -9710,11 +9965,11 @@ function setDefaultConnection(name) {
|
|
|
9710
9965
|
}
|
|
9711
9966
|
|
|
9712
9967
|
// src/commands/seq/promptConnection.ts
|
|
9713
|
-
import
|
|
9968
|
+
import chalk120 from "chalk";
|
|
9714
9969
|
async function promptConnection2(existingNames) {
|
|
9715
9970
|
const name = await promptInput("name", "Connection name:", "default");
|
|
9716
9971
|
if (existingNames.includes(name)) {
|
|
9717
|
-
console.error(
|
|
9972
|
+
console.error(chalk120.red(`Connection "${name}" already exists.`));
|
|
9718
9973
|
process.exit(1);
|
|
9719
9974
|
}
|
|
9720
9975
|
const url = await promptInput("url", "Seq URL:", "http://localhost:5341");
|
|
@@ -9726,16 +9981,16 @@ async function promptConnection2(existingNames) {
|
|
|
9726
9981
|
var seqAuth = createConnectionAuth({
|
|
9727
9982
|
load: loadConnections2,
|
|
9728
9983
|
save: saveConnections2,
|
|
9729
|
-
format: (c) => `${
|
|
9984
|
+
format: (c) => `${chalk121.bold(c.name)} ${c.url}`,
|
|
9730
9985
|
promptNew: promptConnection2,
|
|
9731
9986
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
9732
9987
|
});
|
|
9733
9988
|
|
|
9734
9989
|
// src/commands/seq/seqQuery.ts
|
|
9735
|
-
import
|
|
9990
|
+
import chalk125 from "chalk";
|
|
9736
9991
|
|
|
9737
9992
|
// src/commands/seq/fetchSeq.ts
|
|
9738
|
-
import
|
|
9993
|
+
import chalk122 from "chalk";
|
|
9739
9994
|
async function fetchSeq(conn, path50, params) {
|
|
9740
9995
|
const url = `${conn.url}${path50}?${params}`;
|
|
9741
9996
|
const response = await fetch(url, {
|
|
@@ -9746,7 +10001,7 @@ async function fetchSeq(conn, path50, params) {
|
|
|
9746
10001
|
});
|
|
9747
10002
|
if (!response.ok) {
|
|
9748
10003
|
const body = await response.text();
|
|
9749
|
-
console.error(
|
|
10004
|
+
console.error(chalk122.red(`Seq returned ${response.status}: ${body}`));
|
|
9750
10005
|
process.exit(1);
|
|
9751
10006
|
}
|
|
9752
10007
|
return response;
|
|
@@ -9799,23 +10054,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
9799
10054
|
}
|
|
9800
10055
|
|
|
9801
10056
|
// src/commands/seq/formatEvent.ts
|
|
9802
|
-
import
|
|
10057
|
+
import chalk123 from "chalk";
|
|
9803
10058
|
function levelColor(level) {
|
|
9804
10059
|
switch (level) {
|
|
9805
10060
|
case "Fatal":
|
|
9806
|
-
return
|
|
10061
|
+
return chalk123.bgRed.white;
|
|
9807
10062
|
case "Error":
|
|
9808
|
-
return
|
|
10063
|
+
return chalk123.red;
|
|
9809
10064
|
case "Warning":
|
|
9810
|
-
return
|
|
10065
|
+
return chalk123.yellow;
|
|
9811
10066
|
case "Information":
|
|
9812
|
-
return
|
|
10067
|
+
return chalk123.cyan;
|
|
9813
10068
|
case "Debug":
|
|
9814
|
-
return
|
|
10069
|
+
return chalk123.gray;
|
|
9815
10070
|
case "Verbose":
|
|
9816
|
-
return
|
|
10071
|
+
return chalk123.dim;
|
|
9817
10072
|
default:
|
|
9818
|
-
return
|
|
10073
|
+
return chalk123.white;
|
|
9819
10074
|
}
|
|
9820
10075
|
}
|
|
9821
10076
|
function levelAbbrev(level) {
|
|
@@ -9856,31 +10111,31 @@ function formatTimestamp(iso) {
|
|
|
9856
10111
|
function formatEvent(event) {
|
|
9857
10112
|
const color = levelColor(event.Level);
|
|
9858
10113
|
const abbrev = levelAbbrev(event.Level);
|
|
9859
|
-
const ts8 =
|
|
10114
|
+
const ts8 = chalk123.dim(formatTimestamp(event.Timestamp));
|
|
9860
10115
|
const msg = renderMessage(event);
|
|
9861
10116
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
9862
10117
|
if (event.Exception) {
|
|
9863
10118
|
for (const line of event.Exception.split("\n")) {
|
|
9864
|
-
lines.push(
|
|
10119
|
+
lines.push(chalk123.red(` ${line}`));
|
|
9865
10120
|
}
|
|
9866
10121
|
}
|
|
9867
10122
|
return lines.join("\n");
|
|
9868
10123
|
}
|
|
9869
10124
|
|
|
9870
10125
|
// src/commands/seq/resolveConnection.ts
|
|
9871
|
-
import
|
|
10126
|
+
import chalk124 from "chalk";
|
|
9872
10127
|
function resolveConnection2(name) {
|
|
9873
10128
|
const connections = loadConnections2();
|
|
9874
10129
|
if (connections.length === 0) {
|
|
9875
10130
|
console.error(
|
|
9876
|
-
|
|
10131
|
+
chalk124.red("No Seq connections configured. Run 'assist seq auth' first.")
|
|
9877
10132
|
);
|
|
9878
10133
|
process.exit(1);
|
|
9879
10134
|
}
|
|
9880
10135
|
const target = name ?? getDefaultConnection() ?? connections[0].name;
|
|
9881
10136
|
const connection = connections.find((c) => c.name === target);
|
|
9882
10137
|
if (!connection) {
|
|
9883
|
-
console.error(
|
|
10138
|
+
console.error(chalk124.red(`Seq connection "${target}" not found.`));
|
|
9884
10139
|
process.exit(1);
|
|
9885
10140
|
}
|
|
9886
10141
|
return connection;
|
|
@@ -9895,7 +10150,7 @@ async function seqQuery(filter, options2) {
|
|
|
9895
10150
|
new URLSearchParams({ filter, count: String(count) })
|
|
9896
10151
|
);
|
|
9897
10152
|
if (events.length === 0) {
|
|
9898
|
-
console.log(
|
|
10153
|
+
console.log(chalk125.yellow("No events found."));
|
|
9899
10154
|
return;
|
|
9900
10155
|
}
|
|
9901
10156
|
if (options2.json) {
|
|
@@ -9906,11 +10161,11 @@ async function seqQuery(filter, options2) {
|
|
|
9906
10161
|
for (const event of chronological) {
|
|
9907
10162
|
console.log(formatEvent(event));
|
|
9908
10163
|
}
|
|
9909
|
-
console.log(
|
|
10164
|
+
console.log(chalk125.dim(`
|
|
9910
10165
|
${events.length} events`));
|
|
9911
10166
|
if (events.length >= count) {
|
|
9912
10167
|
console.log(
|
|
9913
|
-
|
|
10168
|
+
chalk125.yellow(
|
|
9914
10169
|
`Results limited to ${count}. Use --count to retrieve more.`
|
|
9915
10170
|
)
|
|
9916
10171
|
);
|
|
@@ -9918,11 +10173,11 @@ ${events.length} events`));
|
|
|
9918
10173
|
}
|
|
9919
10174
|
|
|
9920
10175
|
// src/commands/seq/seqSetConnection.ts
|
|
9921
|
-
import
|
|
10176
|
+
import chalk126 from "chalk";
|
|
9922
10177
|
function seqSetConnection(name) {
|
|
9923
10178
|
const connections = loadConnections2();
|
|
9924
10179
|
if (!connections.find((c) => c.name === name)) {
|
|
9925
|
-
console.error(
|
|
10180
|
+
console.error(chalk126.red(`Connection "${name}" not found.`));
|
|
9926
10181
|
process.exit(1);
|
|
9927
10182
|
}
|
|
9928
10183
|
setDefaultConnection(name);
|
|
@@ -10461,14 +10716,14 @@ import {
|
|
|
10461
10716
|
import { dirname as dirname20, join as join34 } from "path";
|
|
10462
10717
|
|
|
10463
10718
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
10464
|
-
import
|
|
10719
|
+
import chalk127 from "chalk";
|
|
10465
10720
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
10466
10721
|
function validateStagedContent(filename, content) {
|
|
10467
10722
|
const firstLine = content.split("\n")[0];
|
|
10468
10723
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
10469
10724
|
if (!match) {
|
|
10470
10725
|
console.error(
|
|
10471
|
-
|
|
10726
|
+
chalk127.red(
|
|
10472
10727
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
10473
10728
|
)
|
|
10474
10729
|
);
|
|
@@ -10477,7 +10732,7 @@ function validateStagedContent(filename, content) {
|
|
|
10477
10732
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
10478
10733
|
if (!contentAfterLink) {
|
|
10479
10734
|
console.error(
|
|
10480
|
-
|
|
10735
|
+
chalk127.red(
|
|
10481
10736
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
10482
10737
|
)
|
|
10483
10738
|
);
|
|
@@ -10870,7 +11125,7 @@ function registerVoice(program2) {
|
|
|
10870
11125
|
|
|
10871
11126
|
// src/commands/roam/auth.ts
|
|
10872
11127
|
import { randomBytes } from "crypto";
|
|
10873
|
-
import
|
|
11128
|
+
import chalk128 from "chalk";
|
|
10874
11129
|
|
|
10875
11130
|
// src/lib/openBrowser.ts
|
|
10876
11131
|
import { execSync as execSync38 } from "child_process";
|
|
@@ -11005,7 +11260,7 @@ async function exchangeToken(params) {
|
|
|
11005
11260
|
}
|
|
11006
11261
|
|
|
11007
11262
|
// src/commands/roam/promptCredentials.ts
|
|
11008
|
-
import
|
|
11263
|
+
import enquirer10 from "enquirer";
|
|
11009
11264
|
function censor(value) {
|
|
11010
11265
|
const visible = value.slice(-4);
|
|
11011
11266
|
return `${"*".repeat(value.length - 4)}${visible}`;
|
|
@@ -11014,7 +11269,7 @@ function label(name, existing) {
|
|
|
11014
11269
|
return existing ? `${name} (${censor(existing)})` : name;
|
|
11015
11270
|
}
|
|
11016
11271
|
async function promptField(name, existing) {
|
|
11017
|
-
const { value } = await
|
|
11272
|
+
const { value } = await enquirer10.prompt({
|
|
11018
11273
|
type: "input",
|
|
11019
11274
|
name: "value",
|
|
11020
11275
|
message: `${label(name, existing)}:`,
|
|
@@ -11045,13 +11300,13 @@ async function auth() {
|
|
|
11045
11300
|
saveGlobalConfig(config);
|
|
11046
11301
|
const state = randomBytes(16).toString("hex");
|
|
11047
11302
|
console.log(
|
|
11048
|
-
|
|
11303
|
+
chalk128.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
11049
11304
|
);
|
|
11050
|
-
console.log(
|
|
11051
|
-
console.log(
|
|
11052
|
-
console.log(
|
|
11305
|
+
console.log(chalk128.white("http://localhost:14523/callback\n"));
|
|
11306
|
+
console.log(chalk128.blue("Opening browser for authorization..."));
|
|
11307
|
+
console.log(chalk128.dim("Waiting for authorization callback..."));
|
|
11053
11308
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
11054
|
-
console.log(
|
|
11309
|
+
console.log(chalk128.dim("Exchanging code for tokens..."));
|
|
11055
11310
|
const tokens = await exchangeToken({
|
|
11056
11311
|
code,
|
|
11057
11312
|
clientId,
|
|
@@ -11067,7 +11322,7 @@ async function auth() {
|
|
|
11067
11322
|
};
|
|
11068
11323
|
saveGlobalConfig(config);
|
|
11069
11324
|
console.log(
|
|
11070
|
-
|
|
11325
|
+
chalk128.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
11071
11326
|
);
|
|
11072
11327
|
}
|
|
11073
11328
|
|
|
@@ -11280,7 +11535,7 @@ import { execSync as execSync40 } from "child_process";
|
|
|
11280
11535
|
import { existsSync as existsSync39, mkdirSync as mkdirSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync29 } from "fs";
|
|
11281
11536
|
import { tmpdir as tmpdir6 } from "os";
|
|
11282
11537
|
import { join as join43, resolve as resolve5 } from "path";
|
|
11283
|
-
import
|
|
11538
|
+
import chalk129 from "chalk";
|
|
11284
11539
|
|
|
11285
11540
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
11286
11541
|
var captureWindowPs1 = `
|
|
@@ -11431,22 +11686,22 @@ function screenshot(processName) {
|
|
|
11431
11686
|
const config = loadConfig();
|
|
11432
11687
|
const outputDir = resolve5(config.screenshot.outputDir);
|
|
11433
11688
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
11434
|
-
console.log(
|
|
11689
|
+
console.log(chalk129.gray(`Capturing window for process "${processName}" ...`));
|
|
11435
11690
|
try {
|
|
11436
11691
|
runPowerShellScript(processName, outputPath);
|
|
11437
|
-
console.log(
|
|
11692
|
+
console.log(chalk129.green(`Screenshot saved: ${outputPath}`));
|
|
11438
11693
|
} catch (error) {
|
|
11439
11694
|
const msg = error instanceof Error ? error.message : String(error);
|
|
11440
|
-
console.error(
|
|
11695
|
+
console.error(chalk129.red(`Failed to capture screenshot: ${msg}`));
|
|
11441
11696
|
process.exit(1);
|
|
11442
11697
|
}
|
|
11443
11698
|
}
|
|
11444
11699
|
|
|
11445
11700
|
// src/commands/statusLine.ts
|
|
11446
|
-
import
|
|
11701
|
+
import chalk131 from "chalk";
|
|
11447
11702
|
|
|
11448
11703
|
// src/commands/buildLimitsSegment.ts
|
|
11449
|
-
import
|
|
11704
|
+
import chalk130 from "chalk";
|
|
11450
11705
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
11451
11706
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
11452
11707
|
function formatTimeLeft(resetsAt) {
|
|
@@ -11469,10 +11724,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
11469
11724
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
11470
11725
|
const label2 = `${Math.round(pct)}%`;
|
|
11471
11726
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
11472
|
-
if (projected == null) return
|
|
11473
|
-
if (projected > 100) return
|
|
11474
|
-
if (projected > 75) return
|
|
11475
|
-
return
|
|
11727
|
+
if (projected == null) return chalk130.green(label2);
|
|
11728
|
+
if (projected > 100) return chalk130.red(label2);
|
|
11729
|
+
if (projected > 75) return chalk130.yellow(label2);
|
|
11730
|
+
return chalk130.green(label2);
|
|
11476
11731
|
}
|
|
11477
11732
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
11478
11733
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -11498,14 +11753,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
11498
11753
|
}
|
|
11499
11754
|
|
|
11500
11755
|
// src/commands/statusLine.ts
|
|
11501
|
-
|
|
11756
|
+
chalk131.level = 3;
|
|
11502
11757
|
function formatNumber(num) {
|
|
11503
11758
|
return num.toLocaleString("en-US");
|
|
11504
11759
|
}
|
|
11505
11760
|
function colorizePercent(pct) {
|
|
11506
11761
|
const label2 = `${Math.round(pct)}%`;
|
|
11507
|
-
if (pct > 80) return
|
|
11508
|
-
if (pct > 40) return
|
|
11762
|
+
if (pct > 80) return chalk131.red(label2);
|
|
11763
|
+
if (pct > 40) return chalk131.yellow(label2);
|
|
11509
11764
|
return label2;
|
|
11510
11765
|
}
|
|
11511
11766
|
async function statusLine() {
|
|
@@ -11528,7 +11783,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
11528
11783
|
// src/commands/sync/syncClaudeMd.ts
|
|
11529
11784
|
import * as fs23 from "fs";
|
|
11530
11785
|
import * as path46 from "path";
|
|
11531
|
-
import
|
|
11786
|
+
import chalk132 from "chalk";
|
|
11532
11787
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
11533
11788
|
const source = path46.join(claudeDir, "CLAUDE.md");
|
|
11534
11789
|
const target = path46.join(targetBase, "CLAUDE.md");
|
|
@@ -11537,12 +11792,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11537
11792
|
const targetContent = fs23.readFileSync(target, "utf-8");
|
|
11538
11793
|
if (sourceContent !== targetContent) {
|
|
11539
11794
|
console.log(
|
|
11540
|
-
|
|
11795
|
+
chalk132.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
11541
11796
|
);
|
|
11542
11797
|
console.log();
|
|
11543
11798
|
printDiff(targetContent, sourceContent);
|
|
11544
11799
|
const confirm = options2?.yes || await promptConfirm(
|
|
11545
|
-
|
|
11800
|
+
chalk132.red("Overwrite existing CLAUDE.md?"),
|
|
11546
11801
|
false
|
|
11547
11802
|
);
|
|
11548
11803
|
if (!confirm) {
|
|
@@ -11558,7 +11813,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11558
11813
|
// src/commands/sync/syncSettings.ts
|
|
11559
11814
|
import * as fs24 from "fs";
|
|
11560
11815
|
import * as path47 from "path";
|
|
11561
|
-
import
|
|
11816
|
+
import chalk133 from "chalk";
|
|
11562
11817
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
11563
11818
|
const source = path47.join(claudeDir, "settings.json");
|
|
11564
11819
|
const target = path47.join(targetBase, "settings.json");
|
|
@@ -11574,14 +11829,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
11574
11829
|
if (mergedContent !== normalizedTarget) {
|
|
11575
11830
|
if (!options2?.yes) {
|
|
11576
11831
|
console.log(
|
|
11577
|
-
|
|
11832
|
+
chalk133.yellow(
|
|
11578
11833
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
11579
11834
|
)
|
|
11580
11835
|
);
|
|
11581
11836
|
console.log();
|
|
11582
11837
|
printDiff(targetContent, mergedContent);
|
|
11583
11838
|
const confirm = await promptConfirm(
|
|
11584
|
-
|
|
11839
|
+
chalk133.red("Overwrite existing settings.json?"),
|
|
11585
11840
|
false
|
|
11586
11841
|
);
|
|
11587
11842
|
if (!confirm) {
|
|
@@ -11634,7 +11889,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
11634
11889
|
return false;
|
|
11635
11890
|
}
|
|
11636
11891
|
}
|
|
11637
|
-
async function
|
|
11892
|
+
async function update2() {
|
|
11638
11893
|
const installDir = getInstallDir();
|
|
11639
11894
|
console.log(`Assist is installed at: ${installDir}`);
|
|
11640
11895
|
if (isGitRepo(installDir)) {
|
|
@@ -11686,7 +11941,7 @@ program.command("status-line").description("Format Claude Code status line from
|
|
|
11686
11941
|
program.command("notify").description(
|
|
11687
11942
|
"Show notification from Claude Code hook (reads JSON from stdin)"
|
|
11688
11943
|
).action(notify);
|
|
11689
|
-
program.command("update").description("Update assist to the latest version and sync commands").action(
|
|
11944
|
+
program.command("update").description("Update assist to the latest version and sync commands").action(update2);
|
|
11690
11945
|
program.command("coverage").description("Print global statement coverage percentage").action(coverage);
|
|
11691
11946
|
program.command("screenshot").description("Capture a screenshot of a running application window").argument("<process>", "Name of the running process (e.g. notepad, code)").action(screenshot);
|
|
11692
11947
|
registerCliHook(program);
|
|
@@ -11708,6 +11963,7 @@ registerVoice(program);
|
|
|
11708
11963
|
program.command("next").description("Alias for backlog next -w").action(() => next({ allowEdits: true }));
|
|
11709
11964
|
program.command("draft").alias("feat").description("Launch Claude in /draft mode, chain into next on /next signal").action(() => launchMode("draft"));
|
|
11710
11965
|
program.command("bug").description("Launch Claude in /bug mode, chain into next on /next signal").action(() => launchMode("bug"));
|
|
11966
|
+
program.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").action((id) => refine(id));
|
|
11711
11967
|
var signalCommand = program.command("signal").description("Write an assist signal file");
|
|
11712
11968
|
signalCommand.command("next").description("Write a next signal to chain into assist next").action(() => {
|
|
11713
11969
|
writeSignal("next");
|