@staff0rd/assist 0.226.1 → 0.227.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/allowed.cli-reads +1 -0
- package/dist/allowed.cli-reads +1 -0
- package/dist/index.js +717 -408
- package/package.json +3 -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.227.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -53,6 +53,7 @@ var package_default = {
|
|
|
53
53
|
"node-notifier": "^10.0.1",
|
|
54
54
|
"node-pty": "^1.1.0",
|
|
55
55
|
pg: "^8.21.0",
|
|
56
|
+
"pg-copy-streams": "^7.0.0",
|
|
56
57
|
semver: "^7.7.3",
|
|
57
58
|
"shell-quote": "^1.8.3",
|
|
58
59
|
"ts-morph": "^27.0.2",
|
|
@@ -77,6 +78,7 @@ var package_default = {
|
|
|
77
78
|
"@types/node": "^24.10.1",
|
|
78
79
|
"@types/node-notifier": "^8.0.5",
|
|
79
80
|
"@types/pg": "^8.20.0",
|
|
81
|
+
"@types/pg-copy-streams": "^1.2.5",
|
|
80
82
|
"@types/react": "^19.2.14",
|
|
81
83
|
"@types/react-dom": "^19.2.3",
|
|
82
84
|
"@types/semver": "^7.7.1",
|
|
@@ -630,7 +632,8 @@ async function rowToItem(db, row) {
|
|
|
630
632
|
type: row.type,
|
|
631
633
|
name: row.name,
|
|
632
634
|
acceptanceCriteria: JSON.parse(row.acceptance_criteria),
|
|
633
|
-
status: row.status
|
|
635
|
+
status: row.status,
|
|
636
|
+
origin: row.origin
|
|
634
637
|
};
|
|
635
638
|
if (row.description != null) item.description = row.description;
|
|
636
639
|
if (row.current_phase != null) item.currentPhase = row.current_phase;
|
|
@@ -641,7 +644,7 @@ async function rowToItem(db, row) {
|
|
|
641
644
|
}
|
|
642
645
|
async function loadAllItems(db, origin) {
|
|
643
646
|
const rows = await db.all(
|
|
644
|
-
`SELECT id, type, name, description, acceptance_criteria, status, current_phase
|
|
647
|
+
`SELECT id, type, name, description, acceptance_criteria, status, current_phase, origin
|
|
645
648
|
FROM items
|
|
646
649
|
WHERE (?::text IS NULL OR origin = ?)
|
|
647
650
|
ORDER BY id`,
|
|
@@ -688,7 +691,8 @@ var backlogItemSchema = z3.strictObject({
|
|
|
688
691
|
currentPhase: z3.number().optional(),
|
|
689
692
|
status: backlogStatusSchema,
|
|
690
693
|
comments: z3.array(backlogCommentSchema).optional(),
|
|
691
|
-
links: z3.array(backlogLinkSchema).optional()
|
|
694
|
+
links: z3.array(backlogLinkSchema).optional(),
|
|
695
|
+
origin: z3.string().optional()
|
|
692
696
|
});
|
|
693
697
|
var backlogFileSchema = z3.array(backlogItemSchema);
|
|
694
698
|
|
|
@@ -926,6 +930,19 @@ function getBacklogDb() {
|
|
|
926
930
|
})();
|
|
927
931
|
return _connecting;
|
|
928
932
|
}
|
|
933
|
+
async function withBacklogClient(fn) {
|
|
934
|
+
await getBacklogDb();
|
|
935
|
+
const pool = _pool;
|
|
936
|
+
if (!pool) {
|
|
937
|
+
throw new Error("COPY streaming requires a pooled Postgres connection.");
|
|
938
|
+
}
|
|
939
|
+
const client = await pool.connect();
|
|
940
|
+
try {
|
|
941
|
+
return await fn(client);
|
|
942
|
+
} finally {
|
|
943
|
+
client.release();
|
|
944
|
+
}
|
|
945
|
+
}
|
|
929
946
|
async function closeBacklogDb() {
|
|
930
947
|
const pool = _pool;
|
|
931
948
|
if (!pool) return;
|
|
@@ -1314,7 +1331,7 @@ import { spawn } from "child_process";
|
|
|
1314
1331
|
function spawnClaude(prompt, options2 = {}) {
|
|
1315
1332
|
const args = [prompt];
|
|
1316
1333
|
if (options2.allowEdits) {
|
|
1317
|
-
args.push("--permission-mode", "
|
|
1334
|
+
args.push("--permission-mode", "auto");
|
|
1318
1335
|
}
|
|
1319
1336
|
const child = spawn("claude", args, {
|
|
1320
1337
|
stdio: "inherit"
|
|
@@ -4987,9 +5004,280 @@ function registerCommentCommands(cmd) {
|
|
|
4987
5004
|
cmd.command("delete-comment <id> <comment-id>").description("Delete a comment from a backlog item").action(deleteCommentCmd);
|
|
4988
5005
|
}
|
|
4989
5006
|
|
|
4990
|
-
// src/commands/backlog/
|
|
5007
|
+
// src/commands/backlog/export/index.ts
|
|
5008
|
+
import { writeFile } from "fs/promises";
|
|
4991
5009
|
import chalk49 from "chalk";
|
|
4992
5010
|
|
|
5011
|
+
// src/commands/backlog/dump/DumpTable.ts
|
|
5012
|
+
var DUMP_FORMAT = "assist-backlog-dump";
|
|
5013
|
+
var DUMP_VERSION = 1;
|
|
5014
|
+
var DUMP_TABLES = [
|
|
5015
|
+
{
|
|
5016
|
+
name: "items",
|
|
5017
|
+
columns: [
|
|
5018
|
+
"id",
|
|
5019
|
+
"origin",
|
|
5020
|
+
"type",
|
|
5021
|
+
"name",
|
|
5022
|
+
"description",
|
|
5023
|
+
"acceptance_criteria",
|
|
5024
|
+
"status",
|
|
5025
|
+
"current_phase"
|
|
5026
|
+
]
|
|
5027
|
+
},
|
|
5028
|
+
{
|
|
5029
|
+
name: "comments",
|
|
5030
|
+
columns: ["id", "item_id", "idx", "text", "phase", "timestamp", "type"]
|
|
5031
|
+
},
|
|
5032
|
+
{ name: "links", columns: ["item_id", "type", "target_id"] },
|
|
5033
|
+
{ name: "plan_phases", columns: ["item_id", "idx", "name", "manual_checks"] },
|
|
5034
|
+
{ name: "plan_tasks", columns: ["item_id", "phase_idx", "idx", "task"] },
|
|
5035
|
+
{ name: "metadata", columns: ["key", "value"] }
|
|
5036
|
+
];
|
|
5037
|
+
|
|
5038
|
+
// src/commands/backlog/dump/buildDump.ts
|
|
5039
|
+
async function buildDump(copyOut) {
|
|
5040
|
+
const header = JSON.stringify({
|
|
5041
|
+
format: DUMP_FORMAT,
|
|
5042
|
+
version: DUMP_VERSION,
|
|
5043
|
+
tables: DUMP_TABLES.map(({ name, columns }) => ({ name, columns }))
|
|
5044
|
+
});
|
|
5045
|
+
const parts = [Buffer.from(`${header}
|
|
5046
|
+
`, "utf8")];
|
|
5047
|
+
for (const table of DUMP_TABLES) {
|
|
5048
|
+
const data = await copyOut(table);
|
|
5049
|
+
parts.push(Buffer.from(`@table ${table.name} ${data.length}
|
|
5050
|
+
`, "utf8"));
|
|
5051
|
+
parts.push(data);
|
|
5052
|
+
}
|
|
5053
|
+
return Buffer.concat(parts);
|
|
5054
|
+
}
|
|
5055
|
+
|
|
5056
|
+
// src/commands/backlog/dump/copyTableOut.ts
|
|
5057
|
+
import { to as copyTo } from "pg-copy-streams";
|
|
5058
|
+
async function copyTableOut(client, table) {
|
|
5059
|
+
const sql2 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
|
|
5060
|
+
const stream = client.query(copyTo(sql2));
|
|
5061
|
+
const chunks = [];
|
|
5062
|
+
for await (const chunk of stream) {
|
|
5063
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
5064
|
+
}
|
|
5065
|
+
return Buffer.concat(chunks);
|
|
5066
|
+
}
|
|
5067
|
+
|
|
5068
|
+
// src/commands/backlog/export/index.ts
|
|
5069
|
+
async function exportBacklog(file) {
|
|
5070
|
+
const dump = await withBacklogClient(
|
|
5071
|
+
(client) => buildDump((table) => copyTableOut(client, table))
|
|
5072
|
+
);
|
|
5073
|
+
if (file) {
|
|
5074
|
+
await writeFile(file, dump);
|
|
5075
|
+
console.error(
|
|
5076
|
+
chalk49.green(`Exported backlog to ${file} (${dump.length} bytes).`)
|
|
5077
|
+
);
|
|
5078
|
+
return;
|
|
5079
|
+
}
|
|
5080
|
+
process.stdout.write(dump);
|
|
5081
|
+
}
|
|
5082
|
+
|
|
5083
|
+
// src/commands/backlog/registerExportCommand.ts
|
|
5084
|
+
function registerExportCommand(cmd) {
|
|
5085
|
+
cmd.command("export [file]").description(
|
|
5086
|
+
"Export the entire backlog database to a file, or stdout if omitted"
|
|
5087
|
+
).action(exportBacklog);
|
|
5088
|
+
}
|
|
5089
|
+
|
|
5090
|
+
// src/commands/backlog/import/index.ts
|
|
5091
|
+
import { readFile } from "fs/promises";
|
|
5092
|
+
import chalk51 from "chalk";
|
|
5093
|
+
|
|
5094
|
+
// src/commands/backlog/dump/countCopyRows.ts
|
|
5095
|
+
function countCopyRows(data) {
|
|
5096
|
+
let rows = 0;
|
|
5097
|
+
let index = data.indexOf(10);
|
|
5098
|
+
while (index !== -1) {
|
|
5099
|
+
rows++;
|
|
5100
|
+
index = data.indexOf(10, index + 1);
|
|
5101
|
+
}
|
|
5102
|
+
return rows;
|
|
5103
|
+
}
|
|
5104
|
+
|
|
5105
|
+
// src/commands/backlog/dump/parseDump.ts
|
|
5106
|
+
var NEWLINE = 10;
|
|
5107
|
+
function invalid(reason) {
|
|
5108
|
+
throw new Error(`Invalid dump: ${reason}`);
|
|
5109
|
+
}
|
|
5110
|
+
function readLine(dump, start3) {
|
|
5111
|
+
const eol = dump.indexOf(NEWLINE, start3);
|
|
5112
|
+
if (eol === -1) invalid("truncated line (missing newline).");
|
|
5113
|
+
return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
|
|
5114
|
+
}
|
|
5115
|
+
function parseHeader(dump) {
|
|
5116
|
+
const { text, next: next3 } = readLine(dump, 0);
|
|
5117
|
+
try {
|
|
5118
|
+
return { header: JSON.parse(text), bodyStart: next3 };
|
|
5119
|
+
} catch {
|
|
5120
|
+
return invalid("header is not valid JSON.");
|
|
5121
|
+
}
|
|
5122
|
+
}
|
|
5123
|
+
function parseSections(dump, bodyStart) {
|
|
5124
|
+
const sections = /* @__PURE__ */ new Map();
|
|
5125
|
+
let cursor = bodyStart;
|
|
5126
|
+
while (cursor < dump.length) {
|
|
5127
|
+
const { text, next: next3 } = readLine(dump, cursor);
|
|
5128
|
+
const match = text.match(/^@table (\S+) (\d+)$/);
|
|
5129
|
+
if (!match) invalid(`malformed table marker "${text}".`);
|
|
5130
|
+
const [, name, bytes] = match;
|
|
5131
|
+
const end = next3 + Number(bytes);
|
|
5132
|
+
if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
|
|
5133
|
+
sections.set(name, dump.subarray(next3, end));
|
|
5134
|
+
cursor = end;
|
|
5135
|
+
}
|
|
5136
|
+
return sections;
|
|
5137
|
+
}
|
|
5138
|
+
function parseDump(dump) {
|
|
5139
|
+
const { header, bodyStart } = parseHeader(dump);
|
|
5140
|
+
return { header, sections: parseSections(dump, bodyStart) };
|
|
5141
|
+
}
|
|
5142
|
+
|
|
5143
|
+
// src/commands/backlog/dump/validateDump.ts
|
|
5144
|
+
function tableShape(tables) {
|
|
5145
|
+
return JSON.stringify(tables.map(({ name, columns }) => ({ name, columns })));
|
|
5146
|
+
}
|
|
5147
|
+
function validateDump({ header, sections }) {
|
|
5148
|
+
const missing = DUMP_TABLES.find(({ name }) => !sections.has(name))?.name;
|
|
5149
|
+
const checks = [
|
|
5150
|
+
[
|
|
5151
|
+
header.format === DUMP_FORMAT,
|
|
5152
|
+
`Unrecognised dump format "${header.format}" (expected "${DUMP_FORMAT}").`
|
|
5153
|
+
],
|
|
5154
|
+
[
|
|
5155
|
+
header.version === DUMP_VERSION,
|
|
5156
|
+
`Unsupported dump version ${header.version} (this build restores version ${DUMP_VERSION}).`
|
|
5157
|
+
],
|
|
5158
|
+
[
|
|
5159
|
+
tableShape(header.tables ?? []) === tableShape(DUMP_TABLES),
|
|
5160
|
+
"Dump table set does not match this build's backlog schema; cannot restore."
|
|
5161
|
+
],
|
|
5162
|
+
[!missing, `Invalid dump: missing data section for "${missing}".`]
|
|
5163
|
+
];
|
|
5164
|
+
const failure = checks.find(([ok]) => !ok);
|
|
5165
|
+
if (failure) throw new Error(failure[1]);
|
|
5166
|
+
}
|
|
5167
|
+
|
|
5168
|
+
// src/commands/backlog/import/confirmReplace.ts
|
|
5169
|
+
import chalk50 from "chalk";
|
|
5170
|
+
async function countRows(client, table) {
|
|
5171
|
+
const { rows } = await client.query(
|
|
5172
|
+
`SELECT count(*)::int AS n FROM ${table}`
|
|
5173
|
+
);
|
|
5174
|
+
return rows[0].n;
|
|
5175
|
+
}
|
|
5176
|
+
function printSummary(current, incoming) {
|
|
5177
|
+
const lines = DUMP_TABLES.map(
|
|
5178
|
+
(t, i) => ` ${t.name}: ${current[i]} \u2192 ${incoming[i]} rows`
|
|
5179
|
+
);
|
|
5180
|
+
console.error(chalk50.bold("\nThis will REPLACE all backlog data:"));
|
|
5181
|
+
console.error(`${lines.join("\n")}
|
|
5182
|
+
`);
|
|
5183
|
+
}
|
|
5184
|
+
async function confirmReplace(client, incoming, fromStdin) {
|
|
5185
|
+
if (fromStdin) {
|
|
5186
|
+
throw new Error(
|
|
5187
|
+
"Reading a dump from stdin requires --yes (stdin is consumed by the dump)."
|
|
5188
|
+
);
|
|
5189
|
+
}
|
|
5190
|
+
const current = await Promise.all(
|
|
5191
|
+
DUMP_TABLES.map((t) => countRows(client, t.name))
|
|
5192
|
+
);
|
|
5193
|
+
printSummary(current, incoming);
|
|
5194
|
+
return promptConfirm("Replace all backlog data with this dump?", false);
|
|
5195
|
+
}
|
|
5196
|
+
|
|
5197
|
+
// src/commands/backlog/import/readStdinBuffer.ts
|
|
5198
|
+
async function readStdinBuffer() {
|
|
5199
|
+
const chunks = [];
|
|
5200
|
+
for await (const chunk of process.stdin) {
|
|
5201
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
5202
|
+
}
|
|
5203
|
+
return Buffer.concat(chunks);
|
|
5204
|
+
}
|
|
5205
|
+
|
|
5206
|
+
// src/commands/backlog/dump/copyTableIn.ts
|
|
5207
|
+
import { finished } from "stream/promises";
|
|
5208
|
+
import { from as copyFrom } from "pg-copy-streams";
|
|
5209
|
+
async function copyTableIn(client, table, data) {
|
|
5210
|
+
const sql2 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
|
|
5211
|
+
const stream = client.query(copyFrom(sql2));
|
|
5212
|
+
stream.end(data);
|
|
5213
|
+
await finished(stream);
|
|
5214
|
+
}
|
|
5215
|
+
|
|
5216
|
+
// src/commands/backlog/import/restore.ts
|
|
5217
|
+
var IDENTITY_TABLES = ["items", "comments"];
|
|
5218
|
+
function resyncIdentitySql(table) {
|
|
5219
|
+
return `SELECT setval(pg_get_serial_sequence('${table}', 'id'),
|
|
5220
|
+
GREATEST(COALESCE((SELECT max(id) FROM ${table}), 0), 1),
|
|
5221
|
+
(SELECT count(*) FROM ${table}) > 0)`;
|
|
5222
|
+
}
|
|
5223
|
+
async function replaceData(client, parsed) {
|
|
5224
|
+
const tables = DUMP_TABLES.map((t) => t.name).join(", ");
|
|
5225
|
+
await client.query(SCHEMA);
|
|
5226
|
+
await client.query(`TRUNCATE ${tables} RESTART IDENTITY CASCADE`);
|
|
5227
|
+
for (const table of DUMP_TABLES) {
|
|
5228
|
+
const data = parsed.sections.get(table.name) ?? Buffer.alloc(0);
|
|
5229
|
+
await copyTableIn(client, table, data);
|
|
5230
|
+
}
|
|
5231
|
+
for (const table of IDENTITY_TABLES) {
|
|
5232
|
+
await client.query(resyncIdentitySql(table));
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
async function restore(client, parsed) {
|
|
5236
|
+
await client.query("BEGIN");
|
|
5237
|
+
try {
|
|
5238
|
+
await replaceData(client, parsed);
|
|
5239
|
+
await client.query("COMMIT");
|
|
5240
|
+
} catch (error) {
|
|
5241
|
+
await client.query("ROLLBACK");
|
|
5242
|
+
throw error;
|
|
5243
|
+
}
|
|
5244
|
+
}
|
|
5245
|
+
|
|
5246
|
+
// src/commands/backlog/import/index.ts
|
|
5247
|
+
async function importBacklog(file, options2 = {}) {
|
|
5248
|
+
const raw = file ? await readFile(file) : await readStdinBuffer();
|
|
5249
|
+
const parsed = parseDump(raw);
|
|
5250
|
+
validateDump(parsed);
|
|
5251
|
+
const incoming = DUMP_TABLES.map(
|
|
5252
|
+
(t) => countCopyRows(parsed.sections.get(t.name) ?? Buffer.alloc(0))
|
|
5253
|
+
);
|
|
5254
|
+
await withBacklogClient(async (client) => {
|
|
5255
|
+
if (!options2.yes && !await confirmReplace(client, incoming, !file)) {
|
|
5256
|
+
console.error(chalk51.yellow("Import cancelled; no changes made."));
|
|
5257
|
+
return;
|
|
5258
|
+
}
|
|
5259
|
+
await restore(client, parsed);
|
|
5260
|
+
const total = incoming.reduce((sum, n) => sum + n, 0);
|
|
5261
|
+
console.error(
|
|
5262
|
+
chalk51.green(
|
|
5263
|
+
`Imported backlog: ${total} rows restored across ${DUMP_TABLES.length} tables.`
|
|
5264
|
+
)
|
|
5265
|
+
);
|
|
5266
|
+
});
|
|
5267
|
+
}
|
|
5268
|
+
|
|
5269
|
+
// src/commands/backlog/registerImportCommand.ts
|
|
5270
|
+
function registerImportCommand(cmd) {
|
|
5271
|
+
cmd.command("import [file]").description(
|
|
5272
|
+
"Restore the entire backlog database from a dump file, or stdin if omitted (destructive)"
|
|
5273
|
+
).option("-y, --yes", "Skip the confirmation prompt").action(
|
|
5274
|
+
(file, options2) => importBacklog(file, options2)
|
|
5275
|
+
);
|
|
5276
|
+
}
|
|
5277
|
+
|
|
5278
|
+
// src/commands/backlog/add/index.ts
|
|
5279
|
+
import chalk52 from "chalk";
|
|
5280
|
+
|
|
4993
5281
|
// src/commands/backlog/add/shared.ts
|
|
4994
5282
|
import { spawnSync } from "child_process";
|
|
4995
5283
|
import { mkdtempSync, readFileSync as readFileSync14, unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
@@ -5078,11 +5366,11 @@ async function add(options2) {
|
|
|
5078
5366
|
},
|
|
5079
5367
|
getOrigin()
|
|
5080
5368
|
);
|
|
5081
|
-
console.log(
|
|
5369
|
+
console.log(chalk52.green(`Added item #${id}: ${name}`));
|
|
5082
5370
|
}
|
|
5083
5371
|
|
|
5084
5372
|
// src/commands/backlog/addPhase.ts
|
|
5085
|
-
import
|
|
5373
|
+
import chalk54 from "chalk";
|
|
5086
5374
|
|
|
5087
5375
|
// src/commands/backlog/insertPhaseAt.ts
|
|
5088
5376
|
async function insertPhaseAt(db, itemId, phaseIdx, name, tasks, manualChecks, currentPhase) {
|
|
@@ -5121,7 +5409,7 @@ async function insertPhaseAt(db, itemId, phaseIdx, name, tasks, manualChecks, cu
|
|
|
5121
5409
|
}
|
|
5122
5410
|
|
|
5123
5411
|
// src/commands/backlog/resolveInsertPosition.ts
|
|
5124
|
-
import
|
|
5412
|
+
import chalk53 from "chalk";
|
|
5125
5413
|
async function resolveInsertPosition(db, itemId, position) {
|
|
5126
5414
|
const row = await db.get(
|
|
5127
5415
|
"SELECT COUNT(*)::int as cnt FROM plan_phases WHERE item_id = ?",
|
|
@@ -5132,7 +5420,7 @@ async function resolveInsertPosition(db, itemId, position) {
|
|
|
5132
5420
|
const pos = Number.parseInt(position, 10);
|
|
5133
5421
|
if (pos < 1 || pos > phaseCount + 1) {
|
|
5134
5422
|
console.log(
|
|
5135
|
-
|
|
5423
|
+
chalk53.red(
|
|
5136
5424
|
`Position ${pos} is out of range. Must be between 1 and ${phaseCount + 1}.`
|
|
5137
5425
|
)
|
|
5138
5426
|
);
|
|
@@ -5153,7 +5441,7 @@ async function addPhase(id, name, options2) {
|
|
|
5153
5441
|
if (!result) return;
|
|
5154
5442
|
const tasks = options2.task ?? [];
|
|
5155
5443
|
if (tasks.length === 0) {
|
|
5156
|
-
console.log(
|
|
5444
|
+
console.log(chalk54.red("At least one --task is required."));
|
|
5157
5445
|
process.exitCode = 1;
|
|
5158
5446
|
return;
|
|
5159
5447
|
}
|
|
@@ -5172,25 +5460,39 @@ async function addPhase(id, name, options2) {
|
|
|
5172
5460
|
);
|
|
5173
5461
|
const verb = options2.position !== void 0 ? "Inserted" : "Added";
|
|
5174
5462
|
console.log(
|
|
5175
|
-
|
|
5463
|
+
chalk54.green(
|
|
5176
5464
|
`${verb} phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
5177
5465
|
)
|
|
5178
5466
|
);
|
|
5179
5467
|
}
|
|
5180
5468
|
|
|
5181
5469
|
// src/commands/backlog/init/index.ts
|
|
5182
|
-
import
|
|
5470
|
+
import chalk55 from "chalk";
|
|
5183
5471
|
async function init6() {
|
|
5184
5472
|
await getBacklogDb();
|
|
5185
5473
|
console.log(
|
|
5186
|
-
|
|
5474
|
+
chalk55.green(
|
|
5187
5475
|
`Backlog database ready. This repository maps to origin: ${getOrigin()}`
|
|
5188
5476
|
)
|
|
5189
5477
|
);
|
|
5190
5478
|
}
|
|
5191
5479
|
|
|
5192
5480
|
// src/commands/backlog/list/index.ts
|
|
5193
|
-
import
|
|
5481
|
+
import chalk56 from "chalk";
|
|
5482
|
+
|
|
5483
|
+
// src/commands/backlog/originDisplayName.ts
|
|
5484
|
+
function originDisplayName(origin) {
|
|
5485
|
+
if (origin.startsWith("local:")) {
|
|
5486
|
+
const path52 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
5487
|
+
const segments = path52.split("/").filter(Boolean);
|
|
5488
|
+
return segments[segments.length - 1] ?? origin;
|
|
5489
|
+
}
|
|
5490
|
+
const firstSlash = origin.indexOf("/");
|
|
5491
|
+
if (firstSlash === -1) return origin;
|
|
5492
|
+
return origin.slice(firstSlash + 1);
|
|
5493
|
+
}
|
|
5494
|
+
|
|
5495
|
+
// src/commands/backlog/list/index.ts
|
|
5194
5496
|
function filterItems(items, options2) {
|
|
5195
5497
|
if (options2.status) return items.filter((i) => i.status === options2.status);
|
|
5196
5498
|
if (!options2.all)
|
|
@@ -5201,12 +5503,15 @@ async function list2(options2) {
|
|
|
5201
5503
|
const allItems = await loadBacklog(options2.allRepos);
|
|
5202
5504
|
const items = filterItems(allItems, options2);
|
|
5203
5505
|
if (items.length === 0) {
|
|
5204
|
-
console.log(
|
|
5506
|
+
console.log(chalk56.dim("Backlog is empty."));
|
|
5205
5507
|
return;
|
|
5206
5508
|
}
|
|
5509
|
+
const repoNameOf = (item) => item.origin ? originDisplayName(item.origin) : "";
|
|
5510
|
+
const prefixWidth = options2.allRepos ? Math.max(0, ...items.map((i) => repoNameOf(i).length)) : 0;
|
|
5207
5511
|
for (const item of items) {
|
|
5512
|
+
const repoPrefix2 = options2.allRepos ? `${chalk56.dim(repoNameOf(item).padEnd(prefixWidth))} ` : "";
|
|
5208
5513
|
console.log(
|
|
5209
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
5514
|
+
`${repoPrefix2}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk56.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
5210
5515
|
);
|
|
5211
5516
|
if (options2.verbose) {
|
|
5212
5517
|
printVerboseDetails(item);
|
|
@@ -5232,7 +5537,7 @@ function registerItemCommands(cmd) {
|
|
|
5232
5537
|
}
|
|
5233
5538
|
|
|
5234
5539
|
// src/commands/backlog/link.ts
|
|
5235
|
-
import
|
|
5540
|
+
import chalk58 from "chalk";
|
|
5236
5541
|
|
|
5237
5542
|
// src/commands/backlog/hasCycle.ts
|
|
5238
5543
|
function hasCycle(items, fromId, toId) {
|
|
@@ -5255,11 +5560,11 @@ function hasCycle(items, fromId, toId) {
|
|
|
5255
5560
|
}
|
|
5256
5561
|
|
|
5257
5562
|
// src/commands/backlog/validateLinkTarget.ts
|
|
5258
|
-
import
|
|
5563
|
+
import chalk57 from "chalk";
|
|
5259
5564
|
function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
5260
5565
|
const toItem = items.find((i) => i.id === toNum);
|
|
5261
5566
|
if (!toItem) {
|
|
5262
|
-
console.log(
|
|
5567
|
+
console.log(chalk57.red(`Item #${toId} not found.`));
|
|
5263
5568
|
return void 0;
|
|
5264
5569
|
}
|
|
5265
5570
|
if (!fromItem.links) fromItem.links = [];
|
|
@@ -5268,7 +5573,7 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
5268
5573
|
);
|
|
5269
5574
|
if (duplicate) {
|
|
5270
5575
|
console.log(
|
|
5271
|
-
|
|
5576
|
+
chalk57.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
|
|
5272
5577
|
);
|
|
5273
5578
|
return void 0;
|
|
5274
5579
|
}
|
|
@@ -5279,13 +5584,13 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
5279
5584
|
async function link(fromId, toId, opts) {
|
|
5280
5585
|
const linkType = opts.type ?? "relates-to";
|
|
5281
5586
|
if (linkType !== "relates-to" && linkType !== "depends-on") {
|
|
5282
|
-
console.log(
|
|
5587
|
+
console.log(chalk58.red(`Invalid link type: ${linkType}`));
|
|
5283
5588
|
return;
|
|
5284
5589
|
}
|
|
5285
5590
|
const fromNum = Number.parseInt(fromId, 10);
|
|
5286
5591
|
const toNum = Number.parseInt(toId, 10);
|
|
5287
5592
|
if (fromNum === toNum) {
|
|
5288
|
-
console.log(
|
|
5593
|
+
console.log(chalk58.red("Cannot link an item to itself."));
|
|
5289
5594
|
return;
|
|
5290
5595
|
}
|
|
5291
5596
|
const result = await loadAndFindItem(fromId);
|
|
@@ -5302,7 +5607,7 @@ async function link(fromId, toId, opts) {
|
|
|
5302
5607
|
if (!toItem) return;
|
|
5303
5608
|
if (linkType === "depends-on" && hasCycle(items, fromNum, toNum)) {
|
|
5304
5609
|
console.log(
|
|
5305
|
-
|
|
5610
|
+
chalk58.red(
|
|
5306
5611
|
`Cannot add dependency: #${fromId} \u2192 #${toId} would create a circular dependency.`
|
|
5307
5612
|
)
|
|
5308
5613
|
);
|
|
@@ -5312,32 +5617,32 @@ async function link(fromId, toId, opts) {
|
|
|
5312
5617
|
fromItem.links.push({ type: linkType, targetId: toNum });
|
|
5313
5618
|
await saveBacklog(items);
|
|
5314
5619
|
console.log(
|
|
5315
|
-
|
|
5620
|
+
chalk58.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
|
|
5316
5621
|
);
|
|
5317
5622
|
}
|
|
5318
5623
|
|
|
5319
5624
|
// src/commands/backlog/unlink.ts
|
|
5320
|
-
import
|
|
5625
|
+
import chalk59 from "chalk";
|
|
5321
5626
|
async function unlink(fromId, toId) {
|
|
5322
5627
|
const toNum = Number.parseInt(toId, 10);
|
|
5323
5628
|
const result = await loadAndFindItem(fromId);
|
|
5324
5629
|
if (!result) return;
|
|
5325
5630
|
const { items, item: fromItem } = result;
|
|
5326
5631
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
5327
|
-
console.log(
|
|
5632
|
+
console.log(chalk59.yellow(`No links found on item #${fromId}.`));
|
|
5328
5633
|
return;
|
|
5329
5634
|
}
|
|
5330
5635
|
const before = fromItem.links.length;
|
|
5331
5636
|
fromItem.links = fromItem.links.filter((l) => l.targetId !== toNum);
|
|
5332
5637
|
if (fromItem.links.length === before) {
|
|
5333
|
-
console.log(
|
|
5638
|
+
console.log(chalk59.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
5334
5639
|
return;
|
|
5335
5640
|
}
|
|
5336
5641
|
if (fromItem.links.length === 0) {
|
|
5337
5642
|
fromItem.links = void 0;
|
|
5338
5643
|
}
|
|
5339
5644
|
await saveBacklog(items);
|
|
5340
|
-
console.log(
|
|
5645
|
+
console.log(chalk59.green(`Removed link from #${fromId} to #${toId}.`));
|
|
5341
5646
|
}
|
|
5342
5647
|
|
|
5343
5648
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -5350,8 +5655,14 @@ function registerLinkCommands(cmd) {
|
|
|
5350
5655
|
cmd.command("unlink <from> <to>").description("Remove a link between two backlog items").action(unlink);
|
|
5351
5656
|
}
|
|
5352
5657
|
|
|
5658
|
+
// src/commands/backlog/registerPlanCommands.ts
|
|
5659
|
+
function registerPlanCommands(cmd) {
|
|
5660
|
+
cmd.command("plan <id>").description("Display the plan for a backlog item").action(plan);
|
|
5661
|
+
cmd.command("phase-done <id> <phase> <summary>").description("Signal that a plan phase is complete").action(phaseDone);
|
|
5662
|
+
}
|
|
5663
|
+
|
|
5353
5664
|
// src/commands/backlog/rewindPhase.ts
|
|
5354
|
-
import
|
|
5665
|
+
import chalk60 from "chalk";
|
|
5355
5666
|
function validateRewind2(item, phaseNumber) {
|
|
5356
5667
|
if (!item.plan || item.plan.length === 0) {
|
|
5357
5668
|
return `Item #${item.id} has no plan phases.`;
|
|
@@ -5373,7 +5684,7 @@ async function rewindPhase(id, phase, opts) {
|
|
|
5373
5684
|
const { item } = result;
|
|
5374
5685
|
const error = validateRewind2(item, phaseNumber);
|
|
5375
5686
|
if (error) {
|
|
5376
|
-
console.log(
|
|
5687
|
+
console.log(chalk60.red(error));
|
|
5377
5688
|
process.exitCode = 1;
|
|
5378
5689
|
return;
|
|
5379
5690
|
}
|
|
@@ -5391,7 +5702,7 @@ async function rewindPhase(id, phase, opts) {
|
|
|
5391
5702
|
targetPhase: phaseIndex
|
|
5392
5703
|
});
|
|
5393
5704
|
console.log(
|
|
5394
|
-
|
|
5705
|
+
chalk60.green(`Rewound item #${id} to phase ${phaseNumber} (${phaseName}).`)
|
|
5395
5706
|
);
|
|
5396
5707
|
}
|
|
5397
5708
|
|
|
@@ -5402,28 +5713,28 @@ function registerRewindCommand(cmd) {
|
|
|
5402
5713
|
|
|
5403
5714
|
// src/commands/backlog/registerRunCommand.ts
|
|
5404
5715
|
function registerRunCommand(cmd) {
|
|
5405
|
-
cmd.command("run <id>").description("Run a backlog item's plan phase-by-phase with Claude").option("-w, --write", "Run Claude with
|
|
5716
|
+
cmd.command("run <id>").description("Run a backlog item's plan phase-by-phase with Claude").option("-w, --write", "Run Claude with auto permission mode").action(async (id, opts) => {
|
|
5406
5717
|
await run(id, { allowEdits: opts.write });
|
|
5407
5718
|
});
|
|
5408
5719
|
}
|
|
5409
5720
|
|
|
5410
5721
|
// src/commands/backlog/search/index.ts
|
|
5411
|
-
import
|
|
5722
|
+
import chalk61 from "chalk";
|
|
5412
5723
|
async function search(query) {
|
|
5413
5724
|
const items = await searchBacklog(query);
|
|
5414
5725
|
if (items.length === 0) {
|
|
5415
|
-
console.log(
|
|
5726
|
+
console.log(chalk61.dim(`No items matching "${query}".`));
|
|
5416
5727
|
return;
|
|
5417
5728
|
}
|
|
5418
5729
|
console.log(
|
|
5419
|
-
|
|
5730
|
+
chalk61.dim(
|
|
5420
5731
|
`${items.length} item${items.length === 1 ? "" : "s"} matching "${query}":
|
|
5421
5732
|
`
|
|
5422
5733
|
)
|
|
5423
5734
|
);
|
|
5424
5735
|
for (const item of items) {
|
|
5425
5736
|
console.log(
|
|
5426
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
5737
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk61.dim(`#${item.id}`)} ${item.name}`
|
|
5427
5738
|
);
|
|
5428
5739
|
}
|
|
5429
5740
|
}
|
|
@@ -5434,16 +5745,16 @@ function registerSearchCommand(cmd) {
|
|
|
5434
5745
|
}
|
|
5435
5746
|
|
|
5436
5747
|
// src/commands/backlog/delete/index.ts
|
|
5437
|
-
import
|
|
5748
|
+
import chalk62 from "chalk";
|
|
5438
5749
|
async function del(id) {
|
|
5439
5750
|
const name = await removeItem(id);
|
|
5440
5751
|
if (name) {
|
|
5441
|
-
console.log(
|
|
5752
|
+
console.log(chalk62.green(`Deleted item #${id}: ${name}`));
|
|
5442
5753
|
}
|
|
5443
5754
|
}
|
|
5444
5755
|
|
|
5445
5756
|
// src/commands/backlog/done/index.ts
|
|
5446
|
-
import
|
|
5757
|
+
import chalk63 from "chalk";
|
|
5447
5758
|
async function done(id, summary) {
|
|
5448
5759
|
const result = await loadAndFindItem(id);
|
|
5449
5760
|
if (!result) return;
|
|
@@ -5453,12 +5764,12 @@ async function done(id, summary) {
|
|
|
5453
5764
|
const pending = item.plan.slice(completedCount);
|
|
5454
5765
|
if (pending.length > 0) {
|
|
5455
5766
|
console.log(
|
|
5456
|
-
|
|
5767
|
+
chalk63.red(
|
|
5457
5768
|
`Cannot complete item #${id}: ${pending.length} pending phase(s):`
|
|
5458
5769
|
)
|
|
5459
5770
|
);
|
|
5460
5771
|
for (const phase of pending) {
|
|
5461
|
-
console.log(
|
|
5772
|
+
console.log(chalk63.yellow(` - ${phase.name}`));
|
|
5462
5773
|
}
|
|
5463
5774
|
process.exitCode = 1;
|
|
5464
5775
|
return;
|
|
@@ -5470,25 +5781,25 @@ async function done(id, summary) {
|
|
|
5470
5781
|
addPhaseSummary(item, summary, phase);
|
|
5471
5782
|
}
|
|
5472
5783
|
await saveBacklog(result.items);
|
|
5473
|
-
console.log(
|
|
5784
|
+
console.log(chalk63.green(`Completed item #${id}: ${item.name}`));
|
|
5474
5785
|
}
|
|
5475
5786
|
|
|
5476
5787
|
// src/commands/backlog/start/index.ts
|
|
5477
|
-
import
|
|
5788
|
+
import chalk64 from "chalk";
|
|
5478
5789
|
async function start(id) {
|
|
5479
5790
|
const name = await setStatus(id, "in-progress");
|
|
5480
5791
|
if (name) {
|
|
5481
|
-
console.log(
|
|
5792
|
+
console.log(chalk64.green(`Started item #${id}: ${name}`));
|
|
5482
5793
|
}
|
|
5483
5794
|
}
|
|
5484
5795
|
|
|
5485
5796
|
// src/commands/backlog/stop/index.ts
|
|
5486
|
-
import
|
|
5797
|
+
import chalk65 from "chalk";
|
|
5487
5798
|
async function stop() {
|
|
5488
5799
|
const items = await loadBacklog();
|
|
5489
5800
|
const inProgress = items.filter((item) => item.status === "in-progress");
|
|
5490
5801
|
if (inProgress.length === 0) {
|
|
5491
|
-
console.log(
|
|
5802
|
+
console.log(chalk65.yellow("No in-progress items to stop."));
|
|
5492
5803
|
return;
|
|
5493
5804
|
}
|
|
5494
5805
|
for (const item of inProgress) {
|
|
@@ -5497,12 +5808,12 @@ async function stop() {
|
|
|
5497
5808
|
}
|
|
5498
5809
|
await saveBacklog(items);
|
|
5499
5810
|
for (const item of inProgress) {
|
|
5500
|
-
console.log(
|
|
5811
|
+
console.log(chalk65.yellow(`Stopped item #${item.id}: ${item.name}`));
|
|
5501
5812
|
}
|
|
5502
5813
|
}
|
|
5503
5814
|
|
|
5504
5815
|
// src/commands/backlog/wontdo/index.ts
|
|
5505
|
-
import
|
|
5816
|
+
import chalk66 from "chalk";
|
|
5506
5817
|
async function wontdo(id, reason) {
|
|
5507
5818
|
const result = await loadAndFindItem(id);
|
|
5508
5819
|
if (!result) return;
|
|
@@ -5512,7 +5823,7 @@ async function wontdo(id, reason) {
|
|
|
5512
5823
|
addPhaseSummary(result.item, reason, phase);
|
|
5513
5824
|
}
|
|
5514
5825
|
await saveBacklog(result.items);
|
|
5515
|
-
console.log(
|
|
5826
|
+
console.log(chalk66.red(`Won't do item #${id}: ${result.item.name}`));
|
|
5516
5827
|
}
|
|
5517
5828
|
|
|
5518
5829
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -5525,10 +5836,10 @@ function registerStatusCommands(cmd) {
|
|
|
5525
5836
|
}
|
|
5526
5837
|
|
|
5527
5838
|
// src/commands/backlog/removePhase.ts
|
|
5528
|
-
import
|
|
5839
|
+
import chalk68 from "chalk";
|
|
5529
5840
|
|
|
5530
5841
|
// src/commands/backlog/findPhase.ts
|
|
5531
|
-
import
|
|
5842
|
+
import chalk67 from "chalk";
|
|
5532
5843
|
async function findPhase(id, phase) {
|
|
5533
5844
|
const result = await loadAndFindItem(id);
|
|
5534
5845
|
if (!result) return void 0;
|
|
@@ -5541,7 +5852,7 @@ async function findPhase(id, phase) {
|
|
|
5541
5852
|
);
|
|
5542
5853
|
if (!row || row.cnt === 0) {
|
|
5543
5854
|
console.log(
|
|
5544
|
-
|
|
5855
|
+
chalk67.red(`Phase ${phaseIdx + 1} not found on item #${itemId}.`)
|
|
5545
5856
|
);
|
|
5546
5857
|
process.exitCode = 1;
|
|
5547
5858
|
return void 0;
|
|
@@ -5609,12 +5920,12 @@ async function removePhase(id, phase) {
|
|
|
5609
5920
|
await adjustCurrentPhase(tx, result.item, phaseIdx);
|
|
5610
5921
|
});
|
|
5611
5922
|
console.log(
|
|
5612
|
-
|
|
5923
|
+
chalk68.green(`Removed phase ${phaseIdx + 1} from item #${itemId}.`)
|
|
5613
5924
|
);
|
|
5614
5925
|
}
|
|
5615
5926
|
|
|
5616
5927
|
// src/commands/backlog/update/index.ts
|
|
5617
|
-
import
|
|
5928
|
+
import chalk70 from "chalk";
|
|
5618
5929
|
|
|
5619
5930
|
// src/commands/backlog/update/parseListIndex.ts
|
|
5620
5931
|
function parseListIndex(raw, length, label2) {
|
|
@@ -5689,16 +6000,16 @@ function applyAcMutations(current, options2) {
|
|
|
5689
6000
|
}
|
|
5690
6001
|
|
|
5691
6002
|
// src/commands/backlog/update/buildUpdateSql.ts
|
|
5692
|
-
import
|
|
6003
|
+
import chalk69 from "chalk";
|
|
5693
6004
|
function buildUpdateSql(options2) {
|
|
5694
6005
|
const { name, desc, type, ac } = options2;
|
|
5695
6006
|
if (!name && !desc && !type && !ac) {
|
|
5696
|
-
console.log(
|
|
6007
|
+
console.log(chalk69.red("Nothing to update. Provide at least one flag."));
|
|
5697
6008
|
process.exitCode = 1;
|
|
5698
6009
|
return void 0;
|
|
5699
6010
|
}
|
|
5700
6011
|
if (type && type !== "story" && type !== "bug") {
|
|
5701
|
-
console.log(
|
|
6012
|
+
console.log(chalk69.red('Invalid type. Must be "story" or "bug".'));
|
|
5702
6013
|
process.exitCode = 1;
|
|
5703
6014
|
return void 0;
|
|
5704
6015
|
}
|
|
@@ -5736,14 +6047,14 @@ async function update(id, options2) {
|
|
|
5736
6047
|
if (hasAcMutations(options2)) {
|
|
5737
6048
|
if (options2.ac) {
|
|
5738
6049
|
console.log(
|
|
5739
|
-
|
|
6050
|
+
chalk70.red("Cannot combine --ac with --add-ac/--edit-ac/--remove-ac.")
|
|
5740
6051
|
);
|
|
5741
6052
|
process.exitCode = 1;
|
|
5742
6053
|
return;
|
|
5743
6054
|
}
|
|
5744
6055
|
const mutation = applyAcMutations(result.item.acceptanceCriteria, options2);
|
|
5745
6056
|
if (!mutation.ok) {
|
|
5746
|
-
console.log(
|
|
6057
|
+
console.log(chalk70.red(mutation.error));
|
|
5747
6058
|
process.exitCode = 1;
|
|
5748
6059
|
return;
|
|
5749
6060
|
}
|
|
@@ -5757,11 +6068,11 @@ async function update(id, options2) {
|
|
|
5757
6068
|
...built.params,
|
|
5758
6069
|
itemId
|
|
5759
6070
|
]);
|
|
5760
|
-
console.log(
|
|
6071
|
+
console.log(chalk70.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
5761
6072
|
}
|
|
5762
6073
|
|
|
5763
6074
|
// src/commands/backlog/updatePhase.ts
|
|
5764
|
-
import
|
|
6075
|
+
import chalk71 from "chalk";
|
|
5765
6076
|
|
|
5766
6077
|
// src/commands/backlog/applyPhaseUpdate.ts
|
|
5767
6078
|
async function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
@@ -5863,7 +6174,7 @@ async function updatePhase(id, phase, options2) {
|
|
|
5863
6174
|
const { result, db, itemId, phaseIdx } = found;
|
|
5864
6175
|
const resolved = resolvePhaseFields(options2, result.item.plan?.[phaseIdx]);
|
|
5865
6176
|
if (!resolved.ok) {
|
|
5866
|
-
console.log(
|
|
6177
|
+
console.log(chalk71.red(resolved.error));
|
|
5867
6178
|
process.exitCode = 1;
|
|
5868
6179
|
return;
|
|
5869
6180
|
}
|
|
@@ -5875,7 +6186,7 @@ async function updatePhase(id, phase, options2) {
|
|
|
5875
6186
|
manualCheck && "manual checks"
|
|
5876
6187
|
].filter(Boolean).join(", ");
|
|
5877
6188
|
console.log(
|
|
5878
|
-
|
|
6189
|
+
chalk71.green(
|
|
5879
6190
|
`Updated ${fields} on phase ${phaseIdx + 1} of item #${itemId}.`
|
|
5880
6191
|
)
|
|
5881
6192
|
);
|
|
@@ -5914,12 +6225,8 @@ function registerShowCommands(cmd) {
|
|
|
5914
6225
|
function registerWebCommand(cmd) {
|
|
5915
6226
|
cmd.command("web").description("Open the backlog tab in the web dashboard").option("-p, --port <number>", "Port to listen on", "3100").action(web2);
|
|
5916
6227
|
}
|
|
5917
|
-
function registerPlanCommands(cmd) {
|
|
5918
|
-
cmd.command("plan <id>").description("Display the plan for a backlog item").action(plan);
|
|
5919
|
-
cmd.command("phase-done <id> <phase> <summary>").description("Signal that a plan phase is complete").action(phaseDone);
|
|
5920
|
-
}
|
|
5921
6228
|
function registerNextCommand(cmd) {
|
|
5922
|
-
cmd.command("next").description("Pick and run the next backlog item, or open /draft if none").option("-w, --write", "Run Claude with
|
|
6229
|
+
cmd.command("next").description("Pick and run the next backlog item, or open /draft if none").option("-w, --write", "Run Claude with auto permission mode").action(
|
|
5923
6230
|
(opts) => next({ allowEdits: opts.write })
|
|
5924
6231
|
);
|
|
5925
6232
|
}
|
|
@@ -5939,6 +6246,8 @@ function registerBacklog(program2) {
|
|
|
5939
6246
|
registerRunCommand(cmd);
|
|
5940
6247
|
registerSearchCommand(cmd);
|
|
5941
6248
|
registerUpdateCommands(cmd);
|
|
6249
|
+
registerExportCommand(cmd);
|
|
6250
|
+
registerImportCommand(cmd);
|
|
5942
6251
|
}
|
|
5943
6252
|
|
|
5944
6253
|
// src/commands/cliHook/index.ts
|
|
@@ -6557,11 +6866,11 @@ function assertCliExists(cli) {
|
|
|
6557
6866
|
}
|
|
6558
6867
|
|
|
6559
6868
|
// src/commands/permitCliReads/colorize.ts
|
|
6560
|
-
import
|
|
6869
|
+
import chalk72 from "chalk";
|
|
6561
6870
|
function colorize(plainOutput) {
|
|
6562
6871
|
return plainOutput.split("\n").map((line) => {
|
|
6563
|
-
if (line.startsWith(" R ")) return
|
|
6564
|
-
if (line.startsWith(" W ")) return
|
|
6872
|
+
if (line.startsWith(" R ")) return chalk72.green(line);
|
|
6873
|
+
if (line.startsWith(" W ")) return chalk72.red(line);
|
|
6565
6874
|
return line;
|
|
6566
6875
|
}).join("\n");
|
|
6567
6876
|
}
|
|
@@ -6859,7 +7168,7 @@ async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
|
6859
7168
|
}
|
|
6860
7169
|
|
|
6861
7170
|
// src/commands/deny/denyAdd.ts
|
|
6862
|
-
import
|
|
7171
|
+
import chalk73 from "chalk";
|
|
6863
7172
|
|
|
6864
7173
|
// src/commands/deny/loadDenyConfig.ts
|
|
6865
7174
|
function loadDenyConfig(global) {
|
|
@@ -6879,16 +7188,16 @@ function loadDenyConfig(global) {
|
|
|
6879
7188
|
function denyAdd(pattern2, message, options2) {
|
|
6880
7189
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
6881
7190
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
6882
|
-
console.log(
|
|
7191
|
+
console.log(chalk73.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
6883
7192
|
return;
|
|
6884
7193
|
}
|
|
6885
7194
|
deny.push({ pattern: pattern2, message });
|
|
6886
7195
|
saveDeny(deny);
|
|
6887
|
-
console.log(
|
|
7196
|
+
console.log(chalk73.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
6888
7197
|
}
|
|
6889
7198
|
|
|
6890
7199
|
// src/commands/deny/denyList.ts
|
|
6891
|
-
import
|
|
7200
|
+
import chalk74 from "chalk";
|
|
6892
7201
|
function denyList() {
|
|
6893
7202
|
const globalRaw = loadGlobalConfigRaw();
|
|
6894
7203
|
const projectRaw = loadProjectConfig();
|
|
@@ -6899,7 +7208,7 @@ function denyList() {
|
|
|
6899
7208
|
projectDeny.length > 0 ? projectDeny : void 0
|
|
6900
7209
|
);
|
|
6901
7210
|
if (!merged || merged.length === 0) {
|
|
6902
|
-
console.log(
|
|
7211
|
+
console.log(chalk74.dim("No deny rules configured."));
|
|
6903
7212
|
return;
|
|
6904
7213
|
}
|
|
6905
7214
|
const projectPatterns = new Set(projectDeny.map((r) => r.pattern));
|
|
@@ -6907,23 +7216,23 @@ function denyList() {
|
|
|
6907
7216
|
for (const rule of merged) {
|
|
6908
7217
|
const inProject = projectPatterns.has(rule.pattern);
|
|
6909
7218
|
const inGlobal = globalPatterns.has(rule.pattern);
|
|
6910
|
-
const label2 = inProject && inGlobal ?
|
|
6911
|
-
console.log(`${
|
|
7219
|
+
const label2 = inProject && inGlobal ? chalk74.dim(" (project, overrides global)") : inGlobal ? chalk74.dim(" (global)") : "";
|
|
7220
|
+
console.log(`${chalk74.red(rule.pattern)} \u2192 ${rule.message}${label2}`);
|
|
6912
7221
|
}
|
|
6913
7222
|
}
|
|
6914
7223
|
|
|
6915
7224
|
// src/commands/deny/denyRemove.ts
|
|
6916
|
-
import
|
|
7225
|
+
import chalk75 from "chalk";
|
|
6917
7226
|
function denyRemove(pattern2, options2) {
|
|
6918
7227
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
6919
7228
|
const index = deny.findIndex((r) => r.pattern === pattern2);
|
|
6920
7229
|
if (index === -1) {
|
|
6921
|
-
console.log(
|
|
7230
|
+
console.log(chalk75.yellow(`No deny rule found for: ${pattern2}`));
|
|
6922
7231
|
return;
|
|
6923
7232
|
}
|
|
6924
7233
|
deny.splice(index, 1);
|
|
6925
7234
|
saveDeny(deny.length > 0 ? deny : void 0);
|
|
6926
|
-
console.log(
|
|
7235
|
+
console.log(chalk75.green(`Removed deny rule: ${pattern2}`));
|
|
6927
7236
|
}
|
|
6928
7237
|
|
|
6929
7238
|
// src/commands/registerDeny.ts
|
|
@@ -6952,15 +7261,15 @@ function registerCliHook(program2) {
|
|
|
6952
7261
|
}
|
|
6953
7262
|
|
|
6954
7263
|
// src/commands/complexity/analyze.ts
|
|
6955
|
-
import
|
|
7264
|
+
import chalk81 from "chalk";
|
|
6956
7265
|
|
|
6957
7266
|
// src/commands/complexity/cyclomatic.ts
|
|
6958
|
-
import
|
|
7267
|
+
import chalk77 from "chalk";
|
|
6959
7268
|
|
|
6960
7269
|
// src/commands/complexity/shared/index.ts
|
|
6961
7270
|
import fs14 from "fs";
|
|
6962
7271
|
import path22 from "path";
|
|
6963
|
-
import
|
|
7272
|
+
import chalk76 from "chalk";
|
|
6964
7273
|
import ts5 from "typescript";
|
|
6965
7274
|
|
|
6966
7275
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -7206,7 +7515,7 @@ function createSourceFromFile(filePath) {
|
|
|
7206
7515
|
function withSourceFiles(pattern2, callback) {
|
|
7207
7516
|
const files = findSourceFiles2(pattern2);
|
|
7208
7517
|
if (files.length === 0) {
|
|
7209
|
-
console.log(
|
|
7518
|
+
console.log(chalk76.yellow("No files found matching pattern"));
|
|
7210
7519
|
return void 0;
|
|
7211
7520
|
}
|
|
7212
7521
|
return callback(files);
|
|
@@ -7239,11 +7548,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7239
7548
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
7240
7549
|
for (const { file, name, complexity } of results) {
|
|
7241
7550
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
7242
|
-
const color = exceedsThreshold ?
|
|
7243
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
7551
|
+
const color = exceedsThreshold ? chalk77.red : chalk77.white;
|
|
7552
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk77.cyan(complexity)}`);
|
|
7244
7553
|
}
|
|
7245
7554
|
console.log(
|
|
7246
|
-
|
|
7555
|
+
chalk77.dim(
|
|
7247
7556
|
`
|
|
7248
7557
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
7249
7558
|
)
|
|
@@ -7255,7 +7564,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
7255
7564
|
}
|
|
7256
7565
|
|
|
7257
7566
|
// src/commands/complexity/halstead.ts
|
|
7258
|
-
import
|
|
7567
|
+
import chalk78 from "chalk";
|
|
7259
7568
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
7260
7569
|
withSourceFiles(pattern2, (files) => {
|
|
7261
7570
|
const results = [];
|
|
@@ -7270,13 +7579,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7270
7579
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
7271
7580
|
for (const { file, name, metrics } of results) {
|
|
7272
7581
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
7273
|
-
const color = exceedsThreshold ?
|
|
7582
|
+
const color = exceedsThreshold ? chalk78.red : chalk78.white;
|
|
7274
7583
|
console.log(
|
|
7275
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
7584
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk78.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk78.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk78.magenta(metrics.effort.toFixed(1))}`
|
|
7276
7585
|
);
|
|
7277
7586
|
}
|
|
7278
7587
|
console.log(
|
|
7279
|
-
|
|
7588
|
+
chalk78.dim(
|
|
7280
7589
|
`
|
|
7281
7590
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
7282
7591
|
)
|
|
@@ -7291,28 +7600,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
7291
7600
|
import fs15 from "fs";
|
|
7292
7601
|
|
|
7293
7602
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
7294
|
-
import
|
|
7603
|
+
import chalk79 from "chalk";
|
|
7295
7604
|
function displayMaintainabilityResults(results, threshold) {
|
|
7296
7605
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
7297
7606
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
7298
|
-
console.log(
|
|
7607
|
+
console.log(chalk79.green("All files pass maintainability threshold"));
|
|
7299
7608
|
} else {
|
|
7300
7609
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
7301
|
-
const color = threshold !== void 0 ?
|
|
7610
|
+
const color = threshold !== void 0 ? chalk79.red : chalk79.white;
|
|
7302
7611
|
console.log(
|
|
7303
|
-
`${color(file)} \u2192 avg: ${
|
|
7612
|
+
`${color(file)} \u2192 avg: ${chalk79.cyan(avgMaintainability.toFixed(1))}, min: ${chalk79.yellow(minMaintainability.toFixed(1))}`
|
|
7304
7613
|
);
|
|
7305
7614
|
}
|
|
7306
7615
|
}
|
|
7307
|
-
console.log(
|
|
7616
|
+
console.log(chalk79.dim(`
|
|
7308
7617
|
Analyzed ${results.length} files`));
|
|
7309
7618
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
7310
7619
|
console.error(
|
|
7311
|
-
|
|
7620
|
+
chalk79.red(
|
|
7312
7621
|
`
|
|
7313
7622
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
7314
7623
|
|
|
7315
|
-
\u26A0\uFE0F ${
|
|
7624
|
+
\u26A0\uFE0F ${chalk79.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.`
|
|
7316
7625
|
)
|
|
7317
7626
|
);
|
|
7318
7627
|
process.exit(1);
|
|
@@ -7369,7 +7678,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7369
7678
|
|
|
7370
7679
|
// src/commands/complexity/sloc.ts
|
|
7371
7680
|
import fs16 from "fs";
|
|
7372
|
-
import
|
|
7681
|
+
import chalk80 from "chalk";
|
|
7373
7682
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
7374
7683
|
withSourceFiles(pattern2, (files) => {
|
|
7375
7684
|
const results = [];
|
|
@@ -7385,12 +7694,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
7385
7694
|
results.sort((a, b) => b.lines - a.lines);
|
|
7386
7695
|
for (const { file, lines } of results) {
|
|
7387
7696
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
7388
|
-
const color = exceedsThreshold ?
|
|
7389
|
-
console.log(`${color(file)} \u2192 ${
|
|
7697
|
+
const color = exceedsThreshold ? chalk80.red : chalk80.white;
|
|
7698
|
+
console.log(`${color(file)} \u2192 ${chalk80.cyan(lines)} lines`);
|
|
7390
7699
|
}
|
|
7391
7700
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
7392
7701
|
console.log(
|
|
7393
|
-
|
|
7702
|
+
chalk80.dim(`
|
|
7394
7703
|
Total: ${total} lines across ${files.length} files`)
|
|
7395
7704
|
);
|
|
7396
7705
|
if (hasViolation) {
|
|
@@ -7404,21 +7713,21 @@ async function analyze(pattern2) {
|
|
|
7404
7713
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
7405
7714
|
const files = findSourceFiles2(searchPattern);
|
|
7406
7715
|
if (files.length === 0) {
|
|
7407
|
-
console.log(
|
|
7716
|
+
console.log(chalk81.yellow("No files found matching pattern"));
|
|
7408
7717
|
return;
|
|
7409
7718
|
}
|
|
7410
7719
|
if (files.length === 1) {
|
|
7411
7720
|
const file = files[0];
|
|
7412
|
-
console.log(
|
|
7721
|
+
console.log(chalk81.bold.underline("SLOC"));
|
|
7413
7722
|
await sloc(file);
|
|
7414
7723
|
console.log();
|
|
7415
|
-
console.log(
|
|
7724
|
+
console.log(chalk81.bold.underline("Cyclomatic Complexity"));
|
|
7416
7725
|
await cyclomatic(file);
|
|
7417
7726
|
console.log();
|
|
7418
|
-
console.log(
|
|
7727
|
+
console.log(chalk81.bold.underline("Halstead Metrics"));
|
|
7419
7728
|
await halstead(file);
|
|
7420
7729
|
console.log();
|
|
7421
|
-
console.log(
|
|
7730
|
+
console.log(chalk81.bold.underline("Maintainability Index"));
|
|
7422
7731
|
await maintainability(file);
|
|
7423
7732
|
return;
|
|
7424
7733
|
}
|
|
@@ -7445,7 +7754,7 @@ function registerComplexity(program2) {
|
|
|
7445
7754
|
}
|
|
7446
7755
|
|
|
7447
7756
|
// src/commands/config/index.ts
|
|
7448
|
-
import
|
|
7757
|
+
import chalk82 from "chalk";
|
|
7449
7758
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
7450
7759
|
|
|
7451
7760
|
// src/commands/config/setNestedValue.ts
|
|
@@ -7508,7 +7817,7 @@ function formatIssuePath(issue, key) {
|
|
|
7508
7817
|
function printValidationErrors(issues, key) {
|
|
7509
7818
|
for (const issue of issues) {
|
|
7510
7819
|
console.error(
|
|
7511
|
-
|
|
7820
|
+
chalk82.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
7512
7821
|
);
|
|
7513
7822
|
}
|
|
7514
7823
|
}
|
|
@@ -7525,7 +7834,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
7525
7834
|
function assertNotGlobalOnly(key, global) {
|
|
7526
7835
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
7527
7836
|
console.error(
|
|
7528
|
-
|
|
7837
|
+
chalk82.red(
|
|
7529
7838
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
7530
7839
|
)
|
|
7531
7840
|
);
|
|
@@ -7548,7 +7857,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
7548
7857
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
7549
7858
|
const target = options2.global ? "global" : "project";
|
|
7550
7859
|
console.log(
|
|
7551
|
-
|
|
7860
|
+
chalk82.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
7552
7861
|
);
|
|
7553
7862
|
}
|
|
7554
7863
|
function configList() {
|
|
@@ -7557,7 +7866,7 @@ function configList() {
|
|
|
7557
7866
|
}
|
|
7558
7867
|
|
|
7559
7868
|
// src/commands/config/configGet.ts
|
|
7560
|
-
import
|
|
7869
|
+
import chalk83 from "chalk";
|
|
7561
7870
|
|
|
7562
7871
|
// src/commands/config/getNestedValue.ts
|
|
7563
7872
|
function isTraversable(value) {
|
|
@@ -7589,7 +7898,7 @@ function requireNestedValue(config, key) {
|
|
|
7589
7898
|
return value;
|
|
7590
7899
|
}
|
|
7591
7900
|
function exitKeyNotSet(key) {
|
|
7592
|
-
console.error(
|
|
7901
|
+
console.error(chalk83.red(`Key "${key}" is not set`));
|
|
7593
7902
|
process.exit(1);
|
|
7594
7903
|
}
|
|
7595
7904
|
|
|
@@ -7603,7 +7912,7 @@ function registerConfig(program2) {
|
|
|
7603
7912
|
|
|
7604
7913
|
// src/commands/deploy/redirect.ts
|
|
7605
7914
|
import { existsSync as existsSync24, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
7606
|
-
import
|
|
7915
|
+
import chalk84 from "chalk";
|
|
7607
7916
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
7608
7917
|
if (!window.location.pathname.endsWith('/')) {
|
|
7609
7918
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -7612,22 +7921,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
7612
7921
|
function redirect() {
|
|
7613
7922
|
const indexPath = "index.html";
|
|
7614
7923
|
if (!existsSync24(indexPath)) {
|
|
7615
|
-
console.log(
|
|
7924
|
+
console.log(chalk84.yellow("No index.html found"));
|
|
7616
7925
|
return;
|
|
7617
7926
|
}
|
|
7618
7927
|
const content = readFileSync18(indexPath, "utf-8");
|
|
7619
7928
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
7620
|
-
console.log(
|
|
7929
|
+
console.log(chalk84.dim("Trailing slash script already present"));
|
|
7621
7930
|
return;
|
|
7622
7931
|
}
|
|
7623
7932
|
const headCloseIndex = content.indexOf("</head>");
|
|
7624
7933
|
if (headCloseIndex === -1) {
|
|
7625
|
-
console.log(
|
|
7934
|
+
console.log(chalk84.red("Could not find </head> tag in index.html"));
|
|
7626
7935
|
return;
|
|
7627
7936
|
}
|
|
7628
7937
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
7629
7938
|
writeFileSync16(indexPath, newContent);
|
|
7630
|
-
console.log(
|
|
7939
|
+
console.log(chalk84.green("Added trailing slash redirect to index.html"));
|
|
7631
7940
|
}
|
|
7632
7941
|
|
|
7633
7942
|
// src/commands/registerDeploy.ts
|
|
@@ -7654,7 +7963,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
7654
7963
|
|
|
7655
7964
|
// src/commands/devlog/shared.ts
|
|
7656
7965
|
import { execSync as execSync19 } from "child_process";
|
|
7657
|
-
import
|
|
7966
|
+
import chalk85 from "chalk";
|
|
7658
7967
|
|
|
7659
7968
|
// src/shared/getRepoName.ts
|
|
7660
7969
|
import { existsSync as existsSync25, readFileSync as readFileSync19 } from "fs";
|
|
@@ -7763,13 +8072,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
7763
8072
|
}
|
|
7764
8073
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
7765
8074
|
for (const commit2 of commits) {
|
|
7766
|
-
console.log(` ${
|
|
8075
|
+
console.log(` ${chalk85.yellow(commit2.hash)} ${commit2.message}`);
|
|
7767
8076
|
if (verbose) {
|
|
7768
8077
|
const visibleFiles = commit2.files.filter(
|
|
7769
8078
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
7770
8079
|
);
|
|
7771
8080
|
for (const file of visibleFiles) {
|
|
7772
|
-
console.log(` ${
|
|
8081
|
+
console.log(` ${chalk85.dim(file)}`);
|
|
7773
8082
|
}
|
|
7774
8083
|
}
|
|
7775
8084
|
}
|
|
@@ -7794,15 +8103,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
7794
8103
|
}
|
|
7795
8104
|
|
|
7796
8105
|
// src/commands/devlog/list/printDateHeader.ts
|
|
7797
|
-
import
|
|
8106
|
+
import chalk86 from "chalk";
|
|
7798
8107
|
function printDateHeader(date, isSkipped, entries) {
|
|
7799
8108
|
if (isSkipped) {
|
|
7800
|
-
console.log(`${
|
|
8109
|
+
console.log(`${chalk86.bold.blue(date)} ${chalk86.dim("skipped")}`);
|
|
7801
8110
|
} else if (entries && entries.length > 0) {
|
|
7802
|
-
const entryInfo = entries.map((e) => `${
|
|
7803
|
-
console.log(`${
|
|
8111
|
+
const entryInfo = entries.map((e) => `${chalk86.green(e.version)} ${e.title}`).join(" | ");
|
|
8112
|
+
console.log(`${chalk86.bold.blue(date)} ${entryInfo}`);
|
|
7804
8113
|
} else {
|
|
7805
|
-
console.log(`${
|
|
8114
|
+
console.log(`${chalk86.bold.blue(date)} ${chalk86.red("\u26A0 devlog missing")}`);
|
|
7806
8115
|
}
|
|
7807
8116
|
}
|
|
7808
8117
|
|
|
@@ -7906,24 +8215,24 @@ function bumpVersion(version2, type) {
|
|
|
7906
8215
|
|
|
7907
8216
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
7908
8217
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
7909
|
-
import
|
|
8218
|
+
import chalk88 from "chalk";
|
|
7910
8219
|
|
|
7911
8220
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
7912
|
-
import
|
|
8221
|
+
import chalk87 from "chalk";
|
|
7913
8222
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
7914
8223
|
if (conventional && firstHash) {
|
|
7915
8224
|
const version2 = getVersionAtCommit(firstHash);
|
|
7916
8225
|
if (version2) {
|
|
7917
|
-
console.log(`${
|
|
8226
|
+
console.log(`${chalk87.bold("version:")} ${stripToMinor(version2)}`);
|
|
7918
8227
|
} else {
|
|
7919
|
-
console.log(`${
|
|
8228
|
+
console.log(`${chalk87.bold("version:")} ${chalk87.red("unknown")}`);
|
|
7920
8229
|
}
|
|
7921
8230
|
} else if (patchVersion && minorVersion) {
|
|
7922
8231
|
console.log(
|
|
7923
|
-
`${
|
|
8232
|
+
`${chalk87.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
7924
8233
|
);
|
|
7925
8234
|
} else {
|
|
7926
|
-
console.log(`${
|
|
8235
|
+
console.log(`${chalk87.bold("version:")} v0.1 (initial)`);
|
|
7927
8236
|
}
|
|
7928
8237
|
}
|
|
7929
8238
|
|
|
@@ -7971,16 +8280,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
7971
8280
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
7972
8281
|
}
|
|
7973
8282
|
function logName(repoName) {
|
|
7974
|
-
console.log(`${
|
|
8283
|
+
console.log(`${chalk88.bold("name:")} ${repoName}`);
|
|
7975
8284
|
}
|
|
7976
8285
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
7977
8286
|
logName(ctx.repoName);
|
|
7978
8287
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
7979
|
-
console.log(
|
|
8288
|
+
console.log(chalk88.bold.blue(targetDate));
|
|
7980
8289
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
7981
8290
|
}
|
|
7982
8291
|
function logNoCommits(lastInfo) {
|
|
7983
|
-
console.log(
|
|
8292
|
+
console.log(chalk88.dim(noCommitsMessage(!!lastInfo)));
|
|
7984
8293
|
}
|
|
7985
8294
|
|
|
7986
8295
|
// src/commands/devlog/next/index.ts
|
|
@@ -8021,11 +8330,11 @@ function next2(options2) {
|
|
|
8021
8330
|
import { execSync as execSync21 } from "child_process";
|
|
8022
8331
|
|
|
8023
8332
|
// src/commands/devlog/repos/printReposTable.ts
|
|
8024
|
-
import
|
|
8333
|
+
import chalk89 from "chalk";
|
|
8025
8334
|
function colorStatus(status2) {
|
|
8026
|
-
if (status2 === "missing") return
|
|
8027
|
-
if (status2 === "outdated") return
|
|
8028
|
-
return
|
|
8335
|
+
if (status2 === "missing") return chalk89.red(status2);
|
|
8336
|
+
if (status2 === "outdated") return chalk89.yellow(status2);
|
|
8337
|
+
return chalk89.green(status2);
|
|
8029
8338
|
}
|
|
8030
8339
|
function formatRow(row, nameWidth) {
|
|
8031
8340
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -8039,8 +8348,8 @@ function printReposTable(rows) {
|
|
|
8039
8348
|
"Last Devlog".padEnd(11),
|
|
8040
8349
|
"Status"
|
|
8041
8350
|
].join(" ");
|
|
8042
|
-
console.log(
|
|
8043
|
-
console.log(
|
|
8351
|
+
console.log(chalk89.dim(header));
|
|
8352
|
+
console.log(chalk89.dim("-".repeat(header.length)));
|
|
8044
8353
|
for (const row of rows) {
|
|
8045
8354
|
console.log(formatRow(row, nameWidth));
|
|
8046
8355
|
}
|
|
@@ -8098,14 +8407,14 @@ function repos(options2) {
|
|
|
8098
8407
|
// src/commands/devlog/skip.ts
|
|
8099
8408
|
import { writeFileSync as writeFileSync17 } from "fs";
|
|
8100
8409
|
import { join as join24 } from "path";
|
|
8101
|
-
import
|
|
8410
|
+
import chalk90 from "chalk";
|
|
8102
8411
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
8103
8412
|
function getBlogConfigPath() {
|
|
8104
8413
|
return join24(BLOG_REPO_ROOT, "assist.yml");
|
|
8105
8414
|
}
|
|
8106
8415
|
function skip(date) {
|
|
8107
8416
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
8108
|
-
console.log(
|
|
8417
|
+
console.log(chalk90.red("Invalid date format. Use YYYY-MM-DD"));
|
|
8109
8418
|
process.exit(1);
|
|
8110
8419
|
}
|
|
8111
8420
|
const repoName = getRepoName();
|
|
@@ -8116,7 +8425,7 @@ function skip(date) {
|
|
|
8116
8425
|
const skipDays = skip2[repoName] ?? [];
|
|
8117
8426
|
if (skipDays.includes(date)) {
|
|
8118
8427
|
console.log(
|
|
8119
|
-
|
|
8428
|
+
chalk90.yellow(`${date} is already in skip list for ${repoName}`)
|
|
8120
8429
|
);
|
|
8121
8430
|
return;
|
|
8122
8431
|
}
|
|
@@ -8126,20 +8435,20 @@ function skip(date) {
|
|
|
8126
8435
|
devlog.skip = skip2;
|
|
8127
8436
|
config.devlog = devlog;
|
|
8128
8437
|
writeFileSync17(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
8129
|
-
console.log(
|
|
8438
|
+
console.log(chalk90.green(`Added ${date} to skip list for ${repoName}`));
|
|
8130
8439
|
}
|
|
8131
8440
|
|
|
8132
8441
|
// src/commands/devlog/version.ts
|
|
8133
|
-
import
|
|
8442
|
+
import chalk91 from "chalk";
|
|
8134
8443
|
function version() {
|
|
8135
8444
|
const config = loadConfig();
|
|
8136
8445
|
const name = getRepoName();
|
|
8137
8446
|
const lastInfo = getLastVersionInfo(name, config);
|
|
8138
8447
|
const lastVersion = lastInfo?.version ?? null;
|
|
8139
8448
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
8140
|
-
console.log(`${
|
|
8141
|
-
console.log(`${
|
|
8142
|
-
console.log(`${
|
|
8449
|
+
console.log(`${chalk91.bold("name:")} ${name}`);
|
|
8450
|
+
console.log(`${chalk91.bold("last:")} ${lastVersion ?? chalk91.dim("none")}`);
|
|
8451
|
+
console.log(`${chalk91.bold("next:")} ${nextVersion ?? chalk91.dim("none")}`);
|
|
8143
8452
|
}
|
|
8144
8453
|
|
|
8145
8454
|
// src/commands/registerDevlog.ts
|
|
@@ -8163,7 +8472,7 @@ function registerDevlog(program2) {
|
|
|
8163
8472
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
8164
8473
|
import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
|
|
8165
8474
|
import { join as join25 } from "path";
|
|
8166
|
-
import
|
|
8475
|
+
import chalk92 from "chalk";
|
|
8167
8476
|
|
|
8168
8477
|
// src/shared/findRepoRoot.ts
|
|
8169
8478
|
import { existsSync as existsSync26 } from "fs";
|
|
@@ -8226,14 +8535,14 @@ function checkBuildLocks(startDir) {
|
|
|
8226
8535
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
8227
8536
|
if (locked) {
|
|
8228
8537
|
console.error(
|
|
8229
|
-
|
|
8538
|
+
chalk92.red("Build output locked (is VS debugging?): ") + locked
|
|
8230
8539
|
);
|
|
8231
8540
|
process.exit(1);
|
|
8232
8541
|
}
|
|
8233
8542
|
}
|
|
8234
8543
|
async function checkBuildLocksCommand() {
|
|
8235
8544
|
checkBuildLocks();
|
|
8236
|
-
console.log(
|
|
8545
|
+
console.log(chalk92.green("No build locks detected"));
|
|
8237
8546
|
}
|
|
8238
8547
|
|
|
8239
8548
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -8332,30 +8641,30 @@ function escapeRegex(s) {
|
|
|
8332
8641
|
}
|
|
8333
8642
|
|
|
8334
8643
|
// src/commands/dotnet/printTree.ts
|
|
8335
|
-
import
|
|
8644
|
+
import chalk93 from "chalk";
|
|
8336
8645
|
function printNodes(nodes, prefix2) {
|
|
8337
8646
|
for (let i = 0; i < nodes.length; i++) {
|
|
8338
8647
|
const isLast = i === nodes.length - 1;
|
|
8339
8648
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
8340
8649
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
8341
8650
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
8342
|
-
const label2 = isMissing ?
|
|
8651
|
+
const label2 = isMissing ? chalk93.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
8343
8652
|
console.log(`${prefix2}${connector}${label2}`);
|
|
8344
8653
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
8345
8654
|
}
|
|
8346
8655
|
}
|
|
8347
8656
|
function printTree(tree, totalCount, solutions) {
|
|
8348
|
-
console.log(
|
|
8349
|
-
console.log(
|
|
8657
|
+
console.log(chalk93.bold("\nProject Dependency Tree"));
|
|
8658
|
+
console.log(chalk93.cyan(tree.relativePath));
|
|
8350
8659
|
printNodes(tree.children, "");
|
|
8351
|
-
console.log(
|
|
8660
|
+
console.log(chalk93.dim(`
|
|
8352
8661
|
${totalCount} projects total (including root)`));
|
|
8353
|
-
console.log(
|
|
8662
|
+
console.log(chalk93.bold("\nSolution Membership"));
|
|
8354
8663
|
if (solutions.length === 0) {
|
|
8355
|
-
console.log(
|
|
8664
|
+
console.log(chalk93.yellow(" Not found in any .sln"));
|
|
8356
8665
|
} else {
|
|
8357
8666
|
for (const sln of solutions) {
|
|
8358
|
-
console.log(` ${
|
|
8667
|
+
console.log(` ${chalk93.green(sln)}`);
|
|
8359
8668
|
}
|
|
8360
8669
|
}
|
|
8361
8670
|
console.log();
|
|
@@ -8384,16 +8693,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
8384
8693
|
// src/commands/dotnet/resolveCsproj.ts
|
|
8385
8694
|
import { existsSync as existsSync27 } from "fs";
|
|
8386
8695
|
import path26 from "path";
|
|
8387
|
-
import
|
|
8696
|
+
import chalk94 from "chalk";
|
|
8388
8697
|
function resolveCsproj(csprojPath) {
|
|
8389
8698
|
const resolved = path26.resolve(csprojPath);
|
|
8390
8699
|
if (!existsSync27(resolved)) {
|
|
8391
|
-
console.error(
|
|
8700
|
+
console.error(chalk94.red(`File not found: ${resolved}`));
|
|
8392
8701
|
process.exit(1);
|
|
8393
8702
|
}
|
|
8394
8703
|
const repoRoot = findRepoRoot(path26.dirname(resolved));
|
|
8395
8704
|
if (!repoRoot) {
|
|
8396
|
-
console.error(
|
|
8705
|
+
console.error(chalk94.red("Could not find git repository root"));
|
|
8397
8706
|
process.exit(1);
|
|
8398
8707
|
}
|
|
8399
8708
|
return { resolved, repoRoot };
|
|
@@ -8443,12 +8752,12 @@ function getChangedCsFiles(scope) {
|
|
|
8443
8752
|
}
|
|
8444
8753
|
|
|
8445
8754
|
// src/commands/dotnet/inSln.ts
|
|
8446
|
-
import
|
|
8755
|
+
import chalk95 from "chalk";
|
|
8447
8756
|
async function inSln(csprojPath) {
|
|
8448
8757
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
8449
8758
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
8450
8759
|
if (solutions.length === 0) {
|
|
8451
|
-
console.log(
|
|
8760
|
+
console.log(chalk95.yellow("Not found in any .sln file"));
|
|
8452
8761
|
process.exit(1);
|
|
8453
8762
|
}
|
|
8454
8763
|
for (const sln of solutions) {
|
|
@@ -8457,7 +8766,7 @@ async function inSln(csprojPath) {
|
|
|
8457
8766
|
}
|
|
8458
8767
|
|
|
8459
8768
|
// src/commands/dotnet/inspect.ts
|
|
8460
|
-
import
|
|
8769
|
+
import chalk101 from "chalk";
|
|
8461
8770
|
|
|
8462
8771
|
// src/shared/formatElapsed.ts
|
|
8463
8772
|
function formatElapsed(ms) {
|
|
@@ -8469,12 +8778,12 @@ function formatElapsed(ms) {
|
|
|
8469
8778
|
}
|
|
8470
8779
|
|
|
8471
8780
|
// src/commands/dotnet/displayIssues.ts
|
|
8472
|
-
import
|
|
8781
|
+
import chalk96 from "chalk";
|
|
8473
8782
|
var SEVERITY_COLOR = {
|
|
8474
|
-
ERROR:
|
|
8475
|
-
WARNING:
|
|
8476
|
-
SUGGESTION:
|
|
8477
|
-
HINT:
|
|
8783
|
+
ERROR: chalk96.red,
|
|
8784
|
+
WARNING: chalk96.yellow,
|
|
8785
|
+
SUGGESTION: chalk96.cyan,
|
|
8786
|
+
HINT: chalk96.dim
|
|
8478
8787
|
};
|
|
8479
8788
|
function groupByFile(issues) {
|
|
8480
8789
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -8490,15 +8799,15 @@ function groupByFile(issues) {
|
|
|
8490
8799
|
}
|
|
8491
8800
|
function displayIssues(issues) {
|
|
8492
8801
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
8493
|
-
console.log(
|
|
8802
|
+
console.log(chalk96.bold(file));
|
|
8494
8803
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
8495
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
8804
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk96.white;
|
|
8496
8805
|
console.log(
|
|
8497
|
-
` ${
|
|
8806
|
+
` ${chalk96.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
8498
8807
|
);
|
|
8499
8808
|
}
|
|
8500
8809
|
}
|
|
8501
|
-
console.log(
|
|
8810
|
+
console.log(chalk96.dim(`
|
|
8502
8811
|
${issues.length} issue(s) found`));
|
|
8503
8812
|
}
|
|
8504
8813
|
|
|
@@ -8557,12 +8866,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
8557
8866
|
// src/commands/dotnet/resolveSolution.ts
|
|
8558
8867
|
import { existsSync as existsSync28 } from "fs";
|
|
8559
8868
|
import path27 from "path";
|
|
8560
|
-
import
|
|
8869
|
+
import chalk98 from "chalk";
|
|
8561
8870
|
|
|
8562
8871
|
// src/commands/dotnet/findSolution.ts
|
|
8563
8872
|
import { readdirSync as readdirSync4 } from "fs";
|
|
8564
8873
|
import { dirname as dirname18, join as join26 } from "path";
|
|
8565
|
-
import
|
|
8874
|
+
import chalk97 from "chalk";
|
|
8566
8875
|
function findSlnInDir(dir) {
|
|
8567
8876
|
try {
|
|
8568
8877
|
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join26(dir, f));
|
|
@@ -8578,17 +8887,17 @@ function findSolution() {
|
|
|
8578
8887
|
const slnFiles = findSlnInDir(current);
|
|
8579
8888
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
8580
8889
|
if (slnFiles.length > 1) {
|
|
8581
|
-
console.error(
|
|
8890
|
+
console.error(chalk97.red(`Multiple .sln files found in ${current}:`));
|
|
8582
8891
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
8583
8892
|
console.error(
|
|
8584
|
-
|
|
8893
|
+
chalk97.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
8585
8894
|
);
|
|
8586
8895
|
process.exit(1);
|
|
8587
8896
|
}
|
|
8588
8897
|
if (current === ceiling) break;
|
|
8589
8898
|
current = dirname18(current);
|
|
8590
8899
|
}
|
|
8591
|
-
console.error(
|
|
8900
|
+
console.error(chalk97.red("No .sln file found between cwd and repo root"));
|
|
8592
8901
|
process.exit(1);
|
|
8593
8902
|
}
|
|
8594
8903
|
|
|
@@ -8597,7 +8906,7 @@ function resolveSolution(sln) {
|
|
|
8597
8906
|
if (sln) {
|
|
8598
8907
|
const resolved = path27.resolve(sln);
|
|
8599
8908
|
if (!existsSync28(resolved)) {
|
|
8600
|
-
console.error(
|
|
8909
|
+
console.error(chalk98.red(`Solution file not found: ${resolved}`));
|
|
8601
8910
|
process.exit(1);
|
|
8602
8911
|
}
|
|
8603
8912
|
return resolved;
|
|
@@ -8639,14 +8948,14 @@ import { execSync as execSync23 } from "child_process";
|
|
|
8639
8948
|
import { existsSync as existsSync29, readFileSync as readFileSync23, unlinkSync as unlinkSync5 } from "fs";
|
|
8640
8949
|
import { tmpdir as tmpdir3 } from "os";
|
|
8641
8950
|
import path28 from "path";
|
|
8642
|
-
import
|
|
8951
|
+
import chalk99 from "chalk";
|
|
8643
8952
|
function assertJbInstalled() {
|
|
8644
8953
|
try {
|
|
8645
8954
|
execSync23("jb inspectcode --version", { stdio: "pipe" });
|
|
8646
8955
|
} catch {
|
|
8647
|
-
console.error(
|
|
8956
|
+
console.error(chalk99.red("jb is not installed. Install with:"));
|
|
8648
8957
|
console.error(
|
|
8649
|
-
|
|
8958
|
+
chalk99.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
8650
8959
|
);
|
|
8651
8960
|
process.exit(1);
|
|
8652
8961
|
}
|
|
@@ -8664,11 +8973,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8664
8973
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
8665
8974
|
process.stderr.write(err.stderr);
|
|
8666
8975
|
}
|
|
8667
|
-
console.error(
|
|
8976
|
+
console.error(chalk99.red("jb inspectcode failed"));
|
|
8668
8977
|
process.exit(1);
|
|
8669
8978
|
}
|
|
8670
8979
|
if (!existsSync29(reportPath)) {
|
|
8671
|
-
console.error(
|
|
8980
|
+
console.error(chalk99.red("Report file not generated"));
|
|
8672
8981
|
process.exit(1);
|
|
8673
8982
|
}
|
|
8674
8983
|
const xml = readFileSync23(reportPath, "utf-8");
|
|
@@ -8678,7 +8987,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8678
8987
|
|
|
8679
8988
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
8680
8989
|
import { execSync as execSync24 } from "child_process";
|
|
8681
|
-
import
|
|
8990
|
+
import chalk100 from "chalk";
|
|
8682
8991
|
function resolveMsbuildPath() {
|
|
8683
8992
|
const { run: run4 } = loadConfig();
|
|
8684
8993
|
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
@@ -8690,9 +8999,9 @@ function assertMsbuildInstalled() {
|
|
|
8690
8999
|
try {
|
|
8691
9000
|
execSync24(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
8692
9001
|
} catch {
|
|
8693
|
-
console.error(
|
|
9002
|
+
console.error(chalk100.red(`msbuild not found at: ${msbuild}`));
|
|
8694
9003
|
console.error(
|
|
8695
|
-
|
|
9004
|
+
chalk100.yellow(
|
|
8696
9005
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
8697
9006
|
)
|
|
8698
9007
|
);
|
|
@@ -8739,17 +9048,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
8739
9048
|
// src/commands/dotnet/inspect.ts
|
|
8740
9049
|
function logScope(changedFiles) {
|
|
8741
9050
|
if (changedFiles === null) {
|
|
8742
|
-
console.log(
|
|
9051
|
+
console.log(chalk101.dim("Inspecting full solution..."));
|
|
8743
9052
|
} else {
|
|
8744
9053
|
console.log(
|
|
8745
|
-
|
|
9054
|
+
chalk101.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
8746
9055
|
);
|
|
8747
9056
|
}
|
|
8748
9057
|
}
|
|
8749
9058
|
function reportResults(issues, elapsed) {
|
|
8750
9059
|
if (issues.length > 0) displayIssues(issues);
|
|
8751
|
-
else console.log(
|
|
8752
|
-
console.log(
|
|
9060
|
+
else console.log(chalk101.green("No issues found"));
|
|
9061
|
+
console.log(chalk101.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
8753
9062
|
if (issues.length > 0) process.exit(1);
|
|
8754
9063
|
}
|
|
8755
9064
|
async function inspect(sln, options2) {
|
|
@@ -8760,7 +9069,7 @@ async function inspect(sln, options2) {
|
|
|
8760
9069
|
const scope = parseScope(options2.scope);
|
|
8761
9070
|
const changedFiles = getChangedCsFiles(scope);
|
|
8762
9071
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
8763
|
-
console.log(
|
|
9072
|
+
console.log(chalk101.green("No changed .cs files found"));
|
|
8764
9073
|
return;
|
|
8765
9074
|
}
|
|
8766
9075
|
logScope(changedFiles);
|
|
@@ -9014,7 +9323,7 @@ function registerHandover(program2) {
|
|
|
9014
9323
|
}
|
|
9015
9324
|
|
|
9016
9325
|
// src/commands/jira/acceptanceCriteria.ts
|
|
9017
|
-
import
|
|
9326
|
+
import chalk103 from "chalk";
|
|
9018
9327
|
|
|
9019
9328
|
// src/commands/jira/adfToText.ts
|
|
9020
9329
|
function renderInline(node) {
|
|
@@ -9075,7 +9384,7 @@ function adfToText(doc) {
|
|
|
9075
9384
|
|
|
9076
9385
|
// src/commands/jira/fetchIssue.ts
|
|
9077
9386
|
import { execSync as execSync25 } from "child_process";
|
|
9078
|
-
import
|
|
9387
|
+
import chalk102 from "chalk";
|
|
9079
9388
|
function fetchIssue(issueKey, fields) {
|
|
9080
9389
|
let result;
|
|
9081
9390
|
try {
|
|
@@ -9088,15 +9397,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
9088
9397
|
const stderr = error.stderr;
|
|
9089
9398
|
if (stderr.includes("unauthorized")) {
|
|
9090
9399
|
console.error(
|
|
9091
|
-
|
|
9400
|
+
chalk102.red("Jira authentication expired."),
|
|
9092
9401
|
"Run",
|
|
9093
|
-
|
|
9402
|
+
chalk102.cyan("assist jira auth"),
|
|
9094
9403
|
"to re-authenticate."
|
|
9095
9404
|
);
|
|
9096
9405
|
process.exit(1);
|
|
9097
9406
|
}
|
|
9098
9407
|
}
|
|
9099
|
-
console.error(
|
|
9408
|
+
console.error(chalk102.red(`Failed to fetch ${issueKey}.`));
|
|
9100
9409
|
process.exit(1);
|
|
9101
9410
|
}
|
|
9102
9411
|
return JSON.parse(result);
|
|
@@ -9110,7 +9419,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
9110
9419
|
const parsed = fetchIssue(issueKey, field);
|
|
9111
9420
|
const acValue = parsed?.fields?.[field];
|
|
9112
9421
|
if (!acValue) {
|
|
9113
|
-
console.log(
|
|
9422
|
+
console.log(chalk103.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
9114
9423
|
return;
|
|
9115
9424
|
}
|
|
9116
9425
|
if (typeof acValue === "string") {
|
|
@@ -9205,14 +9514,14 @@ async function jiraAuth() {
|
|
|
9205
9514
|
}
|
|
9206
9515
|
|
|
9207
9516
|
// src/commands/jira/viewIssue.ts
|
|
9208
|
-
import
|
|
9517
|
+
import chalk104 from "chalk";
|
|
9209
9518
|
function viewIssue(issueKey) {
|
|
9210
9519
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
9211
9520
|
const fields = parsed?.fields;
|
|
9212
9521
|
const summary = fields?.summary;
|
|
9213
9522
|
const description = fields?.description;
|
|
9214
9523
|
if (summary) {
|
|
9215
|
-
console.log(
|
|
9524
|
+
console.log(chalk104.bold(summary));
|
|
9216
9525
|
}
|
|
9217
9526
|
if (description) {
|
|
9218
9527
|
if (summary) console.log();
|
|
@@ -9226,7 +9535,7 @@ function viewIssue(issueKey) {
|
|
|
9226
9535
|
}
|
|
9227
9536
|
if (!summary && !description) {
|
|
9228
9537
|
console.log(
|
|
9229
|
-
|
|
9538
|
+
chalk104.yellow(`No summary or description found on ${issueKey}.`)
|
|
9230
9539
|
);
|
|
9231
9540
|
}
|
|
9232
9541
|
}
|
|
@@ -9242,15 +9551,15 @@ function registerJira(program2) {
|
|
|
9242
9551
|
// src/commands/mermaid/index.ts
|
|
9243
9552
|
import { mkdirSync as mkdirSync8, readdirSync as readdirSync5 } from "fs";
|
|
9244
9553
|
import { resolve as resolve10 } from "path";
|
|
9245
|
-
import
|
|
9554
|
+
import chalk107 from "chalk";
|
|
9246
9555
|
|
|
9247
9556
|
// src/commands/mermaid/exportFile.ts
|
|
9248
9557
|
import { readFileSync as readFileSync27, writeFileSync as writeFileSync19 } from "fs";
|
|
9249
9558
|
import { basename as basename7, extname, resolve as resolve9 } from "path";
|
|
9250
|
-
import
|
|
9559
|
+
import chalk106 from "chalk";
|
|
9251
9560
|
|
|
9252
9561
|
// src/commands/mermaid/renderBlock.ts
|
|
9253
|
-
import
|
|
9562
|
+
import chalk105 from "chalk";
|
|
9254
9563
|
async function renderBlock(krokiUrl, source) {
|
|
9255
9564
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
9256
9565
|
method: "POST",
|
|
@@ -9259,7 +9568,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
9259
9568
|
});
|
|
9260
9569
|
if (!response.ok) {
|
|
9261
9570
|
console.error(
|
|
9262
|
-
|
|
9571
|
+
chalk105.red(
|
|
9263
9572
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
9264
9573
|
)
|
|
9265
9574
|
);
|
|
@@ -9277,19 +9586,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
9277
9586
|
if (onlyIndex !== void 0) {
|
|
9278
9587
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
9279
9588
|
console.error(
|
|
9280
|
-
|
|
9589
|
+
chalk106.red(
|
|
9281
9590
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
9282
9591
|
)
|
|
9283
9592
|
);
|
|
9284
9593
|
process.exit(1);
|
|
9285
9594
|
}
|
|
9286
9595
|
console.log(
|
|
9287
|
-
|
|
9596
|
+
chalk106.gray(
|
|
9288
9597
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
9289
9598
|
)
|
|
9290
9599
|
);
|
|
9291
9600
|
} else {
|
|
9292
|
-
console.log(
|
|
9601
|
+
console.log(chalk106.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
9293
9602
|
}
|
|
9294
9603
|
for (const [i, source] of blocks.entries()) {
|
|
9295
9604
|
const idx = i + 1;
|
|
@@ -9297,7 +9606,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
9297
9606
|
const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
|
|
9298
9607
|
const svg = await renderBlock(krokiUrl, source);
|
|
9299
9608
|
writeFileSync19(outPath, svg, "utf8");
|
|
9300
|
-
console.log(
|
|
9609
|
+
console.log(chalk106.green(` \u2192 ${outPath}`));
|
|
9301
9610
|
}
|
|
9302
9611
|
}
|
|
9303
9612
|
function extractMermaidBlocks(markdown) {
|
|
@@ -9313,18 +9622,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
9313
9622
|
if (options2.index !== void 0) {
|
|
9314
9623
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
9315
9624
|
console.error(
|
|
9316
|
-
|
|
9625
|
+
chalk107.red(`--index must be a positive integer (got ${options2.index})`)
|
|
9317
9626
|
);
|
|
9318
9627
|
process.exit(1);
|
|
9319
9628
|
}
|
|
9320
9629
|
if (!file) {
|
|
9321
|
-
console.error(
|
|
9630
|
+
console.error(chalk107.red("--index requires a file argument"));
|
|
9322
9631
|
process.exit(1);
|
|
9323
9632
|
}
|
|
9324
9633
|
}
|
|
9325
9634
|
const files = file ? [file] : readdirSync5(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
9326
9635
|
if (files.length === 0) {
|
|
9327
|
-
console.log(
|
|
9636
|
+
console.log(chalk107.gray("No markdown files found in current directory."));
|
|
9328
9637
|
return;
|
|
9329
9638
|
}
|
|
9330
9639
|
for (const f of files) {
|
|
@@ -9347,7 +9656,7 @@ function registerMermaid(program2) {
|
|
|
9347
9656
|
}
|
|
9348
9657
|
|
|
9349
9658
|
// src/commands/news/add/index.ts
|
|
9350
|
-
import
|
|
9659
|
+
import chalk108 from "chalk";
|
|
9351
9660
|
import enquirer8 from "enquirer";
|
|
9352
9661
|
async function add2(url) {
|
|
9353
9662
|
if (!url) {
|
|
@@ -9370,17 +9679,17 @@ async function add2(url) {
|
|
|
9370
9679
|
const news = config.news ?? {};
|
|
9371
9680
|
const feeds = news.feeds ?? [];
|
|
9372
9681
|
if (feeds.includes(url)) {
|
|
9373
|
-
console.log(
|
|
9682
|
+
console.log(chalk108.yellow("Feed already exists in config"));
|
|
9374
9683
|
return;
|
|
9375
9684
|
}
|
|
9376
9685
|
feeds.push(url);
|
|
9377
9686
|
config.news = { ...news, feeds };
|
|
9378
9687
|
saveGlobalConfig(config);
|
|
9379
|
-
console.log(
|
|
9688
|
+
console.log(chalk108.green(`Added feed: ${url}`));
|
|
9380
9689
|
}
|
|
9381
9690
|
|
|
9382
9691
|
// src/commands/news/web/handleRequest.ts
|
|
9383
|
-
import
|
|
9692
|
+
import chalk109 from "chalk";
|
|
9384
9693
|
|
|
9385
9694
|
// src/commands/news/web/shared.ts
|
|
9386
9695
|
import { decodeHTML } from "entities";
|
|
@@ -9516,17 +9825,17 @@ function prefetch() {
|
|
|
9516
9825
|
const config = loadConfig();
|
|
9517
9826
|
const total = config.news.feeds.length;
|
|
9518
9827
|
if (total === 0) return;
|
|
9519
|
-
process.stdout.write(
|
|
9828
|
+
process.stdout.write(chalk109.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
9520
9829
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
9521
9830
|
const width = 20;
|
|
9522
9831
|
const filled = Math.round(done2 / t * width);
|
|
9523
9832
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
9524
9833
|
process.stdout.write(
|
|
9525
|
-
`\r${
|
|
9834
|
+
`\r${chalk109.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
9526
9835
|
);
|
|
9527
9836
|
}).then((items) => {
|
|
9528
9837
|
process.stdout.write(
|
|
9529
|
-
`\r${
|
|
9838
|
+
`\r${chalk109.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
9530
9839
|
`
|
|
9531
9840
|
);
|
|
9532
9841
|
cachedItems = items;
|
|
@@ -9571,7 +9880,7 @@ function registerNews(program2) {
|
|
|
9571
9880
|
}
|
|
9572
9881
|
|
|
9573
9882
|
// src/commands/prompts/printPromptsTable.ts
|
|
9574
|
-
import
|
|
9883
|
+
import chalk110 from "chalk";
|
|
9575
9884
|
function truncate(str, max) {
|
|
9576
9885
|
if (str.length <= max) return str;
|
|
9577
9886
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -9589,14 +9898,14 @@ function printPromptsTable(rows) {
|
|
|
9589
9898
|
"Command".padEnd(commandWidth),
|
|
9590
9899
|
"Repos"
|
|
9591
9900
|
].join(" ");
|
|
9592
|
-
console.log(
|
|
9593
|
-
console.log(
|
|
9901
|
+
console.log(chalk110.dim(header));
|
|
9902
|
+
console.log(chalk110.dim("-".repeat(header.length)));
|
|
9594
9903
|
for (const row of rows) {
|
|
9595
9904
|
const count = String(row.count).padStart(countWidth);
|
|
9596
9905
|
const tool = row.tool.padEnd(toolWidth);
|
|
9597
9906
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
9598
9907
|
console.log(
|
|
9599
|
-
`${
|
|
9908
|
+
`${chalk110.yellow(count)} ${tool} ${command} ${chalk110.dim(row.repos)}`
|
|
9600
9909
|
);
|
|
9601
9910
|
}
|
|
9602
9911
|
}
|
|
@@ -10028,20 +10337,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
10028
10337
|
}
|
|
10029
10338
|
|
|
10030
10339
|
// src/commands/prs/listComments/printComments.ts
|
|
10031
|
-
import
|
|
10340
|
+
import chalk111 from "chalk";
|
|
10032
10341
|
function formatForHuman(comment3) {
|
|
10033
10342
|
if (comment3.type === "review") {
|
|
10034
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
10343
|
+
const stateColor = comment3.state === "APPROVED" ? chalk111.green : comment3.state === "CHANGES_REQUESTED" ? chalk111.red : chalk111.yellow;
|
|
10035
10344
|
return [
|
|
10036
|
-
`${
|
|
10345
|
+
`${chalk111.cyan("Review")} by ${chalk111.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
10037
10346
|
comment3.body,
|
|
10038
10347
|
""
|
|
10039
10348
|
].join("\n");
|
|
10040
10349
|
}
|
|
10041
10350
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
10042
10351
|
return [
|
|
10043
|
-
`${
|
|
10044
|
-
|
|
10352
|
+
`${chalk111.cyan("Line comment")} by ${chalk111.bold(comment3.user)} on ${chalk111.dim(`${comment3.path}${location}`)}`,
|
|
10353
|
+
chalk111.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
10045
10354
|
comment3.body,
|
|
10046
10355
|
""
|
|
10047
10356
|
].join("\n");
|
|
@@ -10131,13 +10440,13 @@ import { execSync as execSync33 } from "child_process";
|
|
|
10131
10440
|
import enquirer9 from "enquirer";
|
|
10132
10441
|
|
|
10133
10442
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
10134
|
-
import
|
|
10443
|
+
import chalk112 from "chalk";
|
|
10135
10444
|
var STATUS_MAP = {
|
|
10136
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
10137
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
10445
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk112.magenta("merged"), date: pr.mergedAt } : null,
|
|
10446
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk112.red("closed"), date: pr.closedAt } : null
|
|
10138
10447
|
};
|
|
10139
10448
|
function defaultStatus(pr) {
|
|
10140
|
-
return { label:
|
|
10449
|
+
return { label: chalk112.green("opened"), date: pr.createdAt };
|
|
10141
10450
|
}
|
|
10142
10451
|
function getStatus2(pr) {
|
|
10143
10452
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -10146,11 +10455,11 @@ function formatDate(dateStr) {
|
|
|
10146
10455
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
10147
10456
|
}
|
|
10148
10457
|
function formatPrHeader(pr, status2) {
|
|
10149
|
-
return `${
|
|
10458
|
+
return `${chalk112.cyan(`#${pr.number}`)} ${pr.title} ${chalk112.dim(`(${pr.author.login},`)} ${status2.label} ${chalk112.dim(`${formatDate(status2.date)})`)}`;
|
|
10150
10459
|
}
|
|
10151
10460
|
function logPrDetails(pr) {
|
|
10152
10461
|
console.log(
|
|
10153
|
-
|
|
10462
|
+
chalk112.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
10154
10463
|
);
|
|
10155
10464
|
console.log();
|
|
10156
10465
|
}
|
|
@@ -10317,10 +10626,10 @@ function registerPrs(program2) {
|
|
|
10317
10626
|
}
|
|
10318
10627
|
|
|
10319
10628
|
// src/commands/ravendb/ravendbAuth.ts
|
|
10320
|
-
import
|
|
10629
|
+
import chalk118 from "chalk";
|
|
10321
10630
|
|
|
10322
10631
|
// src/shared/createConnectionAuth.ts
|
|
10323
|
-
import
|
|
10632
|
+
import chalk113 from "chalk";
|
|
10324
10633
|
function listConnections(connections, format2) {
|
|
10325
10634
|
if (connections.length === 0) {
|
|
10326
10635
|
console.log("No connections configured.");
|
|
@@ -10333,7 +10642,7 @@ function listConnections(connections, format2) {
|
|
|
10333
10642
|
function removeConnection(connections, name, save) {
|
|
10334
10643
|
const filtered = connections.filter((c) => c.name !== name);
|
|
10335
10644
|
if (filtered.length === connections.length) {
|
|
10336
|
-
console.error(
|
|
10645
|
+
console.error(chalk113.red(`Connection "${name}" not found.`));
|
|
10337
10646
|
process.exit(1);
|
|
10338
10647
|
}
|
|
10339
10648
|
save(filtered);
|
|
@@ -10379,15 +10688,15 @@ function saveConnections(connections) {
|
|
|
10379
10688
|
}
|
|
10380
10689
|
|
|
10381
10690
|
// src/commands/ravendb/promptConnection.ts
|
|
10382
|
-
import
|
|
10691
|
+
import chalk116 from "chalk";
|
|
10383
10692
|
|
|
10384
10693
|
// src/commands/ravendb/selectOpSecret.ts
|
|
10385
|
-
import
|
|
10694
|
+
import chalk115 from "chalk";
|
|
10386
10695
|
import Enquirer2 from "enquirer";
|
|
10387
10696
|
|
|
10388
10697
|
// src/commands/ravendb/searchItems.ts
|
|
10389
10698
|
import { execSync as execSync35 } from "child_process";
|
|
10390
|
-
import
|
|
10699
|
+
import chalk114 from "chalk";
|
|
10391
10700
|
function opExec(args) {
|
|
10392
10701
|
return execSync35(`op ${args}`, {
|
|
10393
10702
|
encoding: "utf-8",
|
|
@@ -10400,7 +10709,7 @@ function searchItems(search2) {
|
|
|
10400
10709
|
items = JSON.parse(opExec("item list --format=json"));
|
|
10401
10710
|
} catch {
|
|
10402
10711
|
console.error(
|
|
10403
|
-
|
|
10712
|
+
chalk114.red(
|
|
10404
10713
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
10405
10714
|
)
|
|
10406
10715
|
);
|
|
@@ -10414,7 +10723,7 @@ function getItemFields(itemId) {
|
|
|
10414
10723
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
10415
10724
|
return item.fields.filter((f) => f.reference && f.label);
|
|
10416
10725
|
} catch {
|
|
10417
|
-
console.error(
|
|
10726
|
+
console.error(chalk114.red("Failed to get item details from 1Password."));
|
|
10418
10727
|
process.exit(1);
|
|
10419
10728
|
}
|
|
10420
10729
|
}
|
|
@@ -10433,7 +10742,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
10433
10742
|
}).run();
|
|
10434
10743
|
const items = searchItems(search2);
|
|
10435
10744
|
if (items.length === 0) {
|
|
10436
|
-
console.error(
|
|
10745
|
+
console.error(chalk115.red(`No items found matching "${search2}".`));
|
|
10437
10746
|
process.exit(1);
|
|
10438
10747
|
}
|
|
10439
10748
|
const itemId = await selectOne(
|
|
@@ -10442,7 +10751,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
10442
10751
|
);
|
|
10443
10752
|
const fields = getItemFields(itemId);
|
|
10444
10753
|
if (fields.length === 0) {
|
|
10445
|
-
console.error(
|
|
10754
|
+
console.error(chalk115.red("No fields with references found on this item."));
|
|
10446
10755
|
process.exit(1);
|
|
10447
10756
|
}
|
|
10448
10757
|
const ref = await selectOne(
|
|
@@ -10456,7 +10765,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
10456
10765
|
async function promptConnection(existingNames) {
|
|
10457
10766
|
const name = await promptInput("name", "Connection name:");
|
|
10458
10767
|
if (existingNames.includes(name)) {
|
|
10459
|
-
console.error(
|
|
10768
|
+
console.error(chalk116.red(`Connection "${name}" already exists.`));
|
|
10460
10769
|
process.exit(1);
|
|
10461
10770
|
}
|
|
10462
10771
|
const url = await promptInput(
|
|
@@ -10465,22 +10774,22 @@ async function promptConnection(existingNames) {
|
|
|
10465
10774
|
);
|
|
10466
10775
|
const database = await promptInput("database", "Database name:");
|
|
10467
10776
|
if (!name || !url || !database) {
|
|
10468
|
-
console.error(
|
|
10777
|
+
console.error(chalk116.red("All fields are required."));
|
|
10469
10778
|
process.exit(1);
|
|
10470
10779
|
}
|
|
10471
10780
|
const apiKeyRef = await selectOpSecret();
|
|
10472
|
-
console.log(
|
|
10781
|
+
console.log(chalk116.dim(`Using: ${apiKeyRef}`));
|
|
10473
10782
|
return { name, url, database, apiKeyRef };
|
|
10474
10783
|
}
|
|
10475
10784
|
|
|
10476
10785
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
10477
|
-
import
|
|
10786
|
+
import chalk117 from "chalk";
|
|
10478
10787
|
function ravendbSetConnection(name) {
|
|
10479
10788
|
const raw = loadGlobalConfigRaw();
|
|
10480
10789
|
const ravendb = raw.ravendb ?? {};
|
|
10481
10790
|
const connections = ravendb.connections ?? [];
|
|
10482
10791
|
if (!connections.some((c) => c.name === name)) {
|
|
10483
|
-
console.error(
|
|
10792
|
+
console.error(chalk117.red(`Connection "${name}" not found.`));
|
|
10484
10793
|
console.error(
|
|
10485
10794
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
10486
10795
|
);
|
|
@@ -10496,16 +10805,16 @@ function ravendbSetConnection(name) {
|
|
|
10496
10805
|
var ravendbAuth = createConnectionAuth({
|
|
10497
10806
|
load: loadConnections,
|
|
10498
10807
|
save: saveConnections,
|
|
10499
|
-
format: (c) => `${
|
|
10808
|
+
format: (c) => `${chalk118.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
10500
10809
|
promptNew: promptConnection,
|
|
10501
10810
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
10502
10811
|
});
|
|
10503
10812
|
|
|
10504
10813
|
// src/commands/ravendb/ravendbCollections.ts
|
|
10505
|
-
import
|
|
10814
|
+
import chalk122 from "chalk";
|
|
10506
10815
|
|
|
10507
10816
|
// src/commands/ravendb/ravenFetch.ts
|
|
10508
|
-
import
|
|
10817
|
+
import chalk120 from "chalk";
|
|
10509
10818
|
|
|
10510
10819
|
// src/commands/ravendb/getAccessToken.ts
|
|
10511
10820
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -10542,10 +10851,10 @@ ${errorText}`
|
|
|
10542
10851
|
|
|
10543
10852
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
10544
10853
|
import { execSync as execSync36 } from "child_process";
|
|
10545
|
-
import
|
|
10854
|
+
import chalk119 from "chalk";
|
|
10546
10855
|
function resolveOpSecret(reference) {
|
|
10547
10856
|
if (!reference.startsWith("op://")) {
|
|
10548
|
-
console.error(
|
|
10857
|
+
console.error(chalk119.red(`Invalid secret reference: must start with op://`));
|
|
10549
10858
|
process.exit(1);
|
|
10550
10859
|
}
|
|
10551
10860
|
try {
|
|
@@ -10555,7 +10864,7 @@ function resolveOpSecret(reference) {
|
|
|
10555
10864
|
}).trim();
|
|
10556
10865
|
} catch {
|
|
10557
10866
|
console.error(
|
|
10558
|
-
|
|
10867
|
+
chalk119.red(
|
|
10559
10868
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
10560
10869
|
)
|
|
10561
10870
|
);
|
|
@@ -10582,7 +10891,7 @@ async function ravenFetch(connection, path52) {
|
|
|
10582
10891
|
if (!response.ok) {
|
|
10583
10892
|
const body = await response.text();
|
|
10584
10893
|
console.error(
|
|
10585
|
-
|
|
10894
|
+
chalk120.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
10586
10895
|
);
|
|
10587
10896
|
console.error(body.substring(0, 500));
|
|
10588
10897
|
process.exit(1);
|
|
@@ -10591,7 +10900,7 @@ async function ravenFetch(connection, path52) {
|
|
|
10591
10900
|
}
|
|
10592
10901
|
|
|
10593
10902
|
// src/commands/ravendb/resolveConnection.ts
|
|
10594
|
-
import
|
|
10903
|
+
import chalk121 from "chalk";
|
|
10595
10904
|
function loadRavendb() {
|
|
10596
10905
|
const raw = loadGlobalConfigRaw();
|
|
10597
10906
|
const ravendb = raw.ravendb;
|
|
@@ -10605,7 +10914,7 @@ function resolveConnection(name) {
|
|
|
10605
10914
|
const connectionName = name ?? defaultConnection;
|
|
10606
10915
|
if (!connectionName) {
|
|
10607
10916
|
console.error(
|
|
10608
|
-
|
|
10917
|
+
chalk121.red(
|
|
10609
10918
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
10610
10919
|
)
|
|
10611
10920
|
);
|
|
@@ -10613,7 +10922,7 @@ function resolveConnection(name) {
|
|
|
10613
10922
|
}
|
|
10614
10923
|
const connection = connections.find((c) => c.name === connectionName);
|
|
10615
10924
|
if (!connection) {
|
|
10616
|
-
console.error(
|
|
10925
|
+
console.error(chalk121.red(`Connection "${connectionName}" not found.`));
|
|
10617
10926
|
console.error(
|
|
10618
10927
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
10619
10928
|
);
|
|
@@ -10644,15 +10953,15 @@ async function ravendbCollections(connectionName) {
|
|
|
10644
10953
|
return;
|
|
10645
10954
|
}
|
|
10646
10955
|
for (const c of collections) {
|
|
10647
|
-
console.log(`${
|
|
10956
|
+
console.log(`${chalk122.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
10648
10957
|
}
|
|
10649
10958
|
}
|
|
10650
10959
|
|
|
10651
10960
|
// src/commands/ravendb/ravendbQuery.ts
|
|
10652
|
-
import
|
|
10961
|
+
import chalk124 from "chalk";
|
|
10653
10962
|
|
|
10654
10963
|
// src/commands/ravendb/fetchAllPages.ts
|
|
10655
|
-
import
|
|
10964
|
+
import chalk123 from "chalk";
|
|
10656
10965
|
|
|
10657
10966
|
// src/commands/ravendb/buildQueryPath.ts
|
|
10658
10967
|
function buildQueryPath(opts) {
|
|
@@ -10690,7 +10999,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
10690
10999
|
allResults.push(...results);
|
|
10691
11000
|
start3 += results.length;
|
|
10692
11001
|
process.stderr.write(
|
|
10693
|
-
`\r${
|
|
11002
|
+
`\r${chalk123.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
10694
11003
|
);
|
|
10695
11004
|
if (start3 >= totalResults) break;
|
|
10696
11005
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -10705,7 +11014,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
10705
11014
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
10706
11015
|
const resolved = resolveArgs(connectionName, collection);
|
|
10707
11016
|
if (!resolved.collection && !options2.query) {
|
|
10708
|
-
console.error(
|
|
11017
|
+
console.error(chalk124.red("Provide a collection name or --query filter."));
|
|
10709
11018
|
process.exit(1);
|
|
10710
11019
|
}
|
|
10711
11020
|
const { collection: col } = resolved;
|
|
@@ -10743,7 +11052,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
10743
11052
|
import * as path29 from "path";
|
|
10744
11053
|
|
|
10745
11054
|
// src/commands/refactor/logViolations.ts
|
|
10746
|
-
import
|
|
11055
|
+
import chalk125 from "chalk";
|
|
10747
11056
|
var DEFAULT_MAX_LINES = 100;
|
|
10748
11057
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
10749
11058
|
if (violations.length === 0) {
|
|
@@ -10752,43 +11061,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
10752
11061
|
}
|
|
10753
11062
|
return;
|
|
10754
11063
|
}
|
|
10755
|
-
console.error(
|
|
11064
|
+
console.error(chalk125.red(`
|
|
10756
11065
|
Refactor check failed:
|
|
10757
11066
|
`));
|
|
10758
|
-
console.error(
|
|
11067
|
+
console.error(chalk125.red(` The following files exceed ${maxLines} lines:
|
|
10759
11068
|
`));
|
|
10760
11069
|
for (const violation of violations) {
|
|
10761
|
-
console.error(
|
|
11070
|
+
console.error(chalk125.red(` ${violation.file} (${violation.lines} lines)`));
|
|
10762
11071
|
}
|
|
10763
11072
|
console.error(
|
|
10764
|
-
|
|
11073
|
+
chalk125.yellow(
|
|
10765
11074
|
`
|
|
10766
11075
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
10767
11076
|
way to refactor it, ignore it with:
|
|
10768
11077
|
`
|
|
10769
11078
|
)
|
|
10770
11079
|
);
|
|
10771
|
-
console.error(
|
|
11080
|
+
console.error(chalk125.gray(` assist refactor ignore <file>
|
|
10772
11081
|
`));
|
|
10773
11082
|
if (process.env.CLAUDECODE) {
|
|
10774
|
-
console.error(
|
|
11083
|
+
console.error(chalk125.cyan(`
|
|
10775
11084
|
## Extracting Code to New Files
|
|
10776
11085
|
`));
|
|
10777
11086
|
console.error(
|
|
10778
|
-
|
|
11087
|
+
chalk125.cyan(
|
|
10779
11088
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
10780
11089
|
`
|
|
10781
11090
|
)
|
|
10782
11091
|
);
|
|
10783
11092
|
console.error(
|
|
10784
|
-
|
|
11093
|
+
chalk125.cyan(
|
|
10785
11094
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
10786
11095
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
10787
11096
|
`
|
|
10788
11097
|
)
|
|
10789
11098
|
);
|
|
10790
11099
|
console.error(
|
|
10791
|
-
|
|
11100
|
+
chalk125.cyan(
|
|
10792
11101
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
10793
11102
|
domains, move it to a common/shared folder.
|
|
10794
11103
|
`
|
|
@@ -10944,7 +11253,7 @@ async function check(pattern2, options2) {
|
|
|
10944
11253
|
|
|
10945
11254
|
// src/commands/refactor/extract/index.ts
|
|
10946
11255
|
import path36 from "path";
|
|
10947
|
-
import
|
|
11256
|
+
import chalk128 from "chalk";
|
|
10948
11257
|
|
|
10949
11258
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
10950
11259
|
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
@@ -11491,23 +11800,23 @@ function buildPlan(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
11491
11800
|
|
|
11492
11801
|
// src/commands/refactor/extract/displayPlan.ts
|
|
11493
11802
|
import path33 from "path";
|
|
11494
|
-
import
|
|
11803
|
+
import chalk126 from "chalk";
|
|
11495
11804
|
function section(title) {
|
|
11496
11805
|
return `
|
|
11497
|
-
${
|
|
11806
|
+
${chalk126.cyan(title)}`;
|
|
11498
11807
|
}
|
|
11499
11808
|
function displayImporters(plan2, cwd) {
|
|
11500
11809
|
if (plan2.importersToUpdate.length === 0) return;
|
|
11501
11810
|
console.log(section("Update importers:"));
|
|
11502
11811
|
for (const imp of plan2.importersToUpdate) {
|
|
11503
11812
|
const rel = path33.relative(cwd, imp.file.getFilePath());
|
|
11504
|
-
console.log(` ${
|
|
11813
|
+
console.log(` ${chalk126.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
11505
11814
|
}
|
|
11506
11815
|
}
|
|
11507
11816
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
11508
|
-
console.log(
|
|
11817
|
+
console.log(chalk126.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
11509
11818
|
`));
|
|
11510
|
-
console.log(` ${
|
|
11819
|
+
console.log(` ${chalk126.cyan("Functions to move:")}`);
|
|
11511
11820
|
for (const name of plan2.extractedNames) {
|
|
11512
11821
|
console.log(` ${name}`);
|
|
11513
11822
|
}
|
|
@@ -11541,7 +11850,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
11541
11850
|
|
|
11542
11851
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
11543
11852
|
import path35 from "path";
|
|
11544
|
-
import
|
|
11853
|
+
import chalk127 from "chalk";
|
|
11545
11854
|
import { Project as Project3 } from "ts-morph";
|
|
11546
11855
|
|
|
11547
11856
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -11601,7 +11910,7 @@ function loadProjectFile(file) {
|
|
|
11601
11910
|
});
|
|
11602
11911
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
11603
11912
|
if (!sourceFile) {
|
|
11604
|
-
console.log(
|
|
11913
|
+
console.log(chalk127.red(`File not found in project: ${file}`));
|
|
11605
11914
|
process.exit(1);
|
|
11606
11915
|
}
|
|
11607
11916
|
return { project, sourceFile };
|
|
@@ -11624,19 +11933,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
11624
11933
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
11625
11934
|
if (options2.apply) {
|
|
11626
11935
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
11627
|
-
console.log(
|
|
11936
|
+
console.log(chalk128.green("\nExtraction complete"));
|
|
11628
11937
|
} else {
|
|
11629
|
-
console.log(
|
|
11938
|
+
console.log(chalk128.dim("\nDry run. Use --apply to execute."));
|
|
11630
11939
|
}
|
|
11631
11940
|
}
|
|
11632
11941
|
|
|
11633
11942
|
// src/commands/refactor/ignore.ts
|
|
11634
11943
|
import fs21 from "fs";
|
|
11635
|
-
import
|
|
11944
|
+
import chalk129 from "chalk";
|
|
11636
11945
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
11637
11946
|
function ignore(file) {
|
|
11638
11947
|
if (!fs21.existsSync(file)) {
|
|
11639
|
-
console.error(
|
|
11948
|
+
console.error(chalk129.red(`Error: File does not exist: ${file}`));
|
|
11640
11949
|
process.exit(1);
|
|
11641
11950
|
}
|
|
11642
11951
|
const content = fs21.readFileSync(file, "utf-8");
|
|
@@ -11652,7 +11961,7 @@ function ignore(file) {
|
|
|
11652
11961
|
fs21.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
11653
11962
|
}
|
|
11654
11963
|
console.log(
|
|
11655
|
-
|
|
11964
|
+
chalk129.green(
|
|
11656
11965
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
11657
11966
|
)
|
|
11658
11967
|
);
|
|
@@ -11660,25 +11969,25 @@ function ignore(file) {
|
|
|
11660
11969
|
|
|
11661
11970
|
// src/commands/refactor/rename/index.ts
|
|
11662
11971
|
import path37 from "path";
|
|
11663
|
-
import
|
|
11972
|
+
import chalk130 from "chalk";
|
|
11664
11973
|
async function rename(source, destination, options2 = {}) {
|
|
11665
11974
|
const destPath = path37.resolve(destination);
|
|
11666
11975
|
const cwd = process.cwd();
|
|
11667
11976
|
const relSource = path37.relative(cwd, path37.resolve(source));
|
|
11668
11977
|
const relDest = path37.relative(cwd, destPath);
|
|
11669
11978
|
const { project, sourceFile } = loadProjectFile(source);
|
|
11670
|
-
console.log(
|
|
11979
|
+
console.log(chalk130.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
11671
11980
|
if (options2.apply) {
|
|
11672
11981
|
sourceFile.move(destPath);
|
|
11673
11982
|
await project.save();
|
|
11674
|
-
console.log(
|
|
11983
|
+
console.log(chalk130.green("Done"));
|
|
11675
11984
|
} else {
|
|
11676
|
-
console.log(
|
|
11985
|
+
console.log(chalk130.dim("Dry run. Use --apply to execute."));
|
|
11677
11986
|
}
|
|
11678
11987
|
}
|
|
11679
11988
|
|
|
11680
11989
|
// src/commands/refactor/renameSymbol/index.ts
|
|
11681
|
-
import
|
|
11990
|
+
import chalk131 from "chalk";
|
|
11682
11991
|
|
|
11683
11992
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
11684
11993
|
import { SyntaxKind as SyntaxKind13 } from "ts-morph";
|
|
@@ -11724,33 +12033,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
11724
12033
|
const { project, sourceFile } = loadProjectFile(file);
|
|
11725
12034
|
const symbol = findSymbol(sourceFile, oldName);
|
|
11726
12035
|
if (!symbol) {
|
|
11727
|
-
console.log(
|
|
12036
|
+
console.log(chalk131.red(`Symbol "${oldName}" not found in ${file}`));
|
|
11728
12037
|
process.exit(1);
|
|
11729
12038
|
}
|
|
11730
12039
|
const grouped = groupReferences(symbol, cwd);
|
|
11731
12040
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
11732
12041
|
console.log(
|
|
11733
|
-
|
|
12042
|
+
chalk131.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
11734
12043
|
`)
|
|
11735
12044
|
);
|
|
11736
12045
|
for (const [refFile, lines] of grouped) {
|
|
11737
12046
|
console.log(
|
|
11738
|
-
` ${
|
|
12047
|
+
` ${chalk131.dim(refFile)}: lines ${chalk131.cyan(lines.join(", "))}`
|
|
11739
12048
|
);
|
|
11740
12049
|
}
|
|
11741
12050
|
if (options2.apply) {
|
|
11742
12051
|
symbol.rename(newName);
|
|
11743
12052
|
await project.save();
|
|
11744
|
-
console.log(
|
|
12053
|
+
console.log(chalk131.green(`
|
|
11745
12054
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
11746
12055
|
} else {
|
|
11747
|
-
console.log(
|
|
12056
|
+
console.log(chalk131.dim("\nDry run. Use --apply to execute."));
|
|
11748
12057
|
}
|
|
11749
12058
|
}
|
|
11750
12059
|
|
|
11751
12060
|
// src/commands/refactor/restructure/index.ts
|
|
11752
12061
|
import path47 from "path";
|
|
11753
|
-
import
|
|
12062
|
+
import chalk134 from "chalk";
|
|
11754
12063
|
|
|
11755
12064
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
11756
12065
|
import path39 from "path";
|
|
@@ -11993,50 +12302,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
11993
12302
|
|
|
11994
12303
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
11995
12304
|
import path43 from "path";
|
|
11996
|
-
import
|
|
12305
|
+
import chalk132 from "chalk";
|
|
11997
12306
|
function relPath(filePath) {
|
|
11998
12307
|
return path43.relative(process.cwd(), filePath);
|
|
11999
12308
|
}
|
|
12000
12309
|
function displayMoves(plan2) {
|
|
12001
12310
|
if (plan2.moves.length === 0) return;
|
|
12002
|
-
console.log(
|
|
12311
|
+
console.log(chalk132.bold("\nFile moves:"));
|
|
12003
12312
|
for (const move of plan2.moves) {
|
|
12004
12313
|
console.log(
|
|
12005
|
-
` ${
|
|
12314
|
+
` ${chalk132.red(relPath(move.from))} \u2192 ${chalk132.green(relPath(move.to))}`
|
|
12006
12315
|
);
|
|
12007
|
-
console.log(
|
|
12316
|
+
console.log(chalk132.dim(` ${move.reason}`));
|
|
12008
12317
|
}
|
|
12009
12318
|
}
|
|
12010
12319
|
function displayRewrites(rewrites) {
|
|
12011
12320
|
if (rewrites.length === 0) return;
|
|
12012
12321
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
12013
|
-
console.log(
|
|
12322
|
+
console.log(chalk132.bold(`
|
|
12014
12323
|
Import rewrites (${affectedFiles.size} files):`));
|
|
12015
12324
|
for (const file of affectedFiles) {
|
|
12016
|
-
console.log(` ${
|
|
12325
|
+
console.log(` ${chalk132.cyan(relPath(file))}:`);
|
|
12017
12326
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
12018
12327
|
(r) => r.file === file
|
|
12019
12328
|
)) {
|
|
12020
12329
|
console.log(
|
|
12021
|
-
` ${
|
|
12330
|
+
` ${chalk132.red(`"${oldSpecifier}"`)} \u2192 ${chalk132.green(`"${newSpecifier}"`)}`
|
|
12022
12331
|
);
|
|
12023
12332
|
}
|
|
12024
12333
|
}
|
|
12025
12334
|
}
|
|
12026
12335
|
function displayPlan2(plan2) {
|
|
12027
12336
|
if (plan2.warnings.length > 0) {
|
|
12028
|
-
console.log(
|
|
12029
|
-
for (const w of plan2.warnings) console.log(
|
|
12337
|
+
console.log(chalk132.yellow("\nWarnings:"));
|
|
12338
|
+
for (const w of plan2.warnings) console.log(chalk132.yellow(` ${w}`));
|
|
12030
12339
|
}
|
|
12031
12340
|
if (plan2.newDirectories.length > 0) {
|
|
12032
|
-
console.log(
|
|
12341
|
+
console.log(chalk132.bold("\nNew directories:"));
|
|
12033
12342
|
for (const dir of plan2.newDirectories)
|
|
12034
|
-
console.log(
|
|
12343
|
+
console.log(chalk132.green(` ${dir}/`));
|
|
12035
12344
|
}
|
|
12036
12345
|
displayMoves(plan2);
|
|
12037
12346
|
displayRewrites(plan2.rewrites);
|
|
12038
12347
|
console.log(
|
|
12039
|
-
|
|
12348
|
+
chalk132.dim(
|
|
12040
12349
|
`
|
|
12041
12350
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
12042
12351
|
)
|
|
@@ -12046,18 +12355,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
12046
12355
|
// src/commands/refactor/restructure/executePlan.ts
|
|
12047
12356
|
import fs23 from "fs";
|
|
12048
12357
|
import path44 from "path";
|
|
12049
|
-
import
|
|
12358
|
+
import chalk133 from "chalk";
|
|
12050
12359
|
function executePlan(plan2) {
|
|
12051
12360
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
12052
12361
|
for (const [file, content] of updatedContents) {
|
|
12053
12362
|
fs23.writeFileSync(file, content, "utf-8");
|
|
12054
12363
|
console.log(
|
|
12055
|
-
|
|
12364
|
+
chalk133.cyan(` Rewrote imports in ${path44.relative(process.cwd(), file)}`)
|
|
12056
12365
|
);
|
|
12057
12366
|
}
|
|
12058
12367
|
for (const dir of plan2.newDirectories) {
|
|
12059
12368
|
fs23.mkdirSync(dir, { recursive: true });
|
|
12060
|
-
console.log(
|
|
12369
|
+
console.log(chalk133.green(` Created ${path44.relative(process.cwd(), dir)}/`));
|
|
12061
12370
|
}
|
|
12062
12371
|
for (const move of plan2.moves) {
|
|
12063
12372
|
const targetDir = path44.dirname(move.to);
|
|
@@ -12066,7 +12375,7 @@ function executePlan(plan2) {
|
|
|
12066
12375
|
}
|
|
12067
12376
|
fs23.renameSync(move.from, move.to);
|
|
12068
12377
|
console.log(
|
|
12069
|
-
|
|
12378
|
+
chalk133.white(
|
|
12070
12379
|
` Moved ${path44.relative(process.cwd(), move.from)} \u2192 ${path44.relative(process.cwd(), move.to)}`
|
|
12071
12380
|
)
|
|
12072
12381
|
);
|
|
@@ -12081,7 +12390,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
12081
12390
|
if (entries.length === 0) {
|
|
12082
12391
|
fs23.rmdirSync(dir);
|
|
12083
12392
|
console.log(
|
|
12084
|
-
|
|
12393
|
+
chalk133.dim(
|
|
12085
12394
|
` Removed empty directory ${path44.relative(process.cwd(), dir)}`
|
|
12086
12395
|
)
|
|
12087
12396
|
);
|
|
@@ -12214,22 +12523,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
12214
12523
|
const targetPattern = pattern2 ?? "src";
|
|
12215
12524
|
const files = findSourceFiles2(targetPattern);
|
|
12216
12525
|
if (files.length === 0) {
|
|
12217
|
-
console.log(
|
|
12526
|
+
console.log(chalk134.yellow("No files found matching pattern"));
|
|
12218
12527
|
return;
|
|
12219
12528
|
}
|
|
12220
12529
|
const tsConfigPath = path47.resolve("tsconfig.json");
|
|
12221
12530
|
const plan2 = buildPlan2(files, tsConfigPath);
|
|
12222
12531
|
if (plan2.moves.length === 0) {
|
|
12223
|
-
console.log(
|
|
12532
|
+
console.log(chalk134.green("No restructuring needed"));
|
|
12224
12533
|
return;
|
|
12225
12534
|
}
|
|
12226
12535
|
displayPlan2(plan2);
|
|
12227
12536
|
if (options2.apply) {
|
|
12228
|
-
console.log(
|
|
12537
|
+
console.log(chalk134.bold("\nApplying changes..."));
|
|
12229
12538
|
executePlan(plan2);
|
|
12230
|
-
console.log(
|
|
12539
|
+
console.log(chalk134.green("\nRestructuring complete"));
|
|
12231
12540
|
} else {
|
|
12232
|
-
console.log(
|
|
12541
|
+
console.log(chalk134.dim("\nDry run. Use --apply to execute."));
|
|
12233
12542
|
}
|
|
12234
12543
|
}
|
|
12235
12544
|
|
|
@@ -12694,18 +13003,18 @@ async function postAndMaybeSubmit(lineBound, markdown, options2) {
|
|
|
12694
13003
|
}
|
|
12695
13004
|
|
|
12696
13005
|
// src/commands/review/warnUnlocated.ts
|
|
12697
|
-
import
|
|
13006
|
+
import chalk135 from "chalk";
|
|
12698
13007
|
function warnUnlocated(unlocated) {
|
|
12699
13008
|
if (unlocated.length === 0) return;
|
|
12700
13009
|
console.warn(
|
|
12701
|
-
|
|
13010
|
+
chalk135.yellow(
|
|
12702
13011
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
12703
13012
|
)
|
|
12704
13013
|
);
|
|
12705
13014
|
for (const finding of unlocated) {
|
|
12706
|
-
const where = finding.location ||
|
|
13015
|
+
const where = finding.location || chalk135.dim("missing");
|
|
12707
13016
|
console.warn(
|
|
12708
|
-
` ${
|
|
13017
|
+
` ${chalk135.yellow("\xB7")} ${finding.title} ${chalk135.dim(`(${where})`)}`
|
|
12709
13018
|
);
|
|
12710
13019
|
}
|
|
12711
13020
|
}
|
|
@@ -13634,7 +13943,7 @@ Files:
|
|
|
13634
13943
|
}
|
|
13635
13944
|
|
|
13636
13945
|
// src/commands/review/synthesise.ts
|
|
13637
|
-
function
|
|
13946
|
+
function printSummary2(synthesisPath) {
|
|
13638
13947
|
const markdown = readFileSync30(synthesisPath, "utf-8");
|
|
13639
13948
|
console.log("");
|
|
13640
13949
|
console.log(buildReviewSummary(markdown));
|
|
@@ -13643,7 +13952,7 @@ function printSummary(synthesisPath) {
|
|
|
13643
13952
|
async function synthesise(paths, options2) {
|
|
13644
13953
|
const cached = cachedReviewerResult("synthesis", paths.synthesisPath);
|
|
13645
13954
|
if (cached) {
|
|
13646
|
-
|
|
13955
|
+
printSummary2(paths.synthesisPath);
|
|
13647
13956
|
return cached;
|
|
13648
13957
|
}
|
|
13649
13958
|
const { multi } = options2;
|
|
@@ -13661,7 +13970,7 @@ async function synthesise(paths, options2) {
|
|
|
13661
13970
|
outputPath: paths.synthesisPath,
|
|
13662
13971
|
spinner
|
|
13663
13972
|
});
|
|
13664
|
-
if (result.exitCode === 0)
|
|
13973
|
+
if (result.exitCode === 0) printSummary2(paths.synthesisPath);
|
|
13665
13974
|
return result;
|
|
13666
13975
|
}
|
|
13667
13976
|
|
|
@@ -13899,7 +14208,7 @@ function registerReview(program2) {
|
|
|
13899
14208
|
}
|
|
13900
14209
|
|
|
13901
14210
|
// src/commands/seq/seqAuth.ts
|
|
13902
|
-
import
|
|
14211
|
+
import chalk137 from "chalk";
|
|
13903
14212
|
|
|
13904
14213
|
// src/commands/seq/loadConnections.ts
|
|
13905
14214
|
function loadConnections2() {
|
|
@@ -13928,10 +14237,10 @@ function setDefaultConnection(name) {
|
|
|
13928
14237
|
}
|
|
13929
14238
|
|
|
13930
14239
|
// src/shared/assertUniqueName.ts
|
|
13931
|
-
import
|
|
14240
|
+
import chalk136 from "chalk";
|
|
13932
14241
|
function assertUniqueName(existingNames, name) {
|
|
13933
14242
|
if (existingNames.includes(name)) {
|
|
13934
|
-
console.error(
|
|
14243
|
+
console.error(chalk136.red(`Connection "${name}" already exists.`));
|
|
13935
14244
|
process.exit(1);
|
|
13936
14245
|
}
|
|
13937
14246
|
}
|
|
@@ -13949,16 +14258,16 @@ async function promptConnection2(existingNames) {
|
|
|
13949
14258
|
var seqAuth = createConnectionAuth({
|
|
13950
14259
|
load: loadConnections2,
|
|
13951
14260
|
save: saveConnections2,
|
|
13952
|
-
format: (c) => `${
|
|
14261
|
+
format: (c) => `${chalk137.bold(c.name)} ${c.url}`,
|
|
13953
14262
|
promptNew: promptConnection2,
|
|
13954
14263
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
13955
14264
|
});
|
|
13956
14265
|
|
|
13957
14266
|
// src/commands/seq/seqQuery.ts
|
|
13958
|
-
import
|
|
14267
|
+
import chalk141 from "chalk";
|
|
13959
14268
|
|
|
13960
14269
|
// src/commands/seq/fetchSeq.ts
|
|
13961
|
-
import
|
|
14270
|
+
import chalk138 from "chalk";
|
|
13962
14271
|
async function fetchSeq(conn, path52, params) {
|
|
13963
14272
|
const url = `${conn.url}${path52}?${params}`;
|
|
13964
14273
|
const response = await fetch(url, {
|
|
@@ -13969,7 +14278,7 @@ async function fetchSeq(conn, path52, params) {
|
|
|
13969
14278
|
});
|
|
13970
14279
|
if (!response.ok) {
|
|
13971
14280
|
const body = await response.text();
|
|
13972
|
-
console.error(
|
|
14281
|
+
console.error(chalk138.red(`Seq returned ${response.status}: ${body}`));
|
|
13973
14282
|
process.exit(1);
|
|
13974
14283
|
}
|
|
13975
14284
|
return response;
|
|
@@ -14024,23 +14333,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
14024
14333
|
}
|
|
14025
14334
|
|
|
14026
14335
|
// src/commands/seq/formatEvent.ts
|
|
14027
|
-
import
|
|
14336
|
+
import chalk139 from "chalk";
|
|
14028
14337
|
function levelColor(level) {
|
|
14029
14338
|
switch (level) {
|
|
14030
14339
|
case "Fatal":
|
|
14031
|
-
return
|
|
14340
|
+
return chalk139.bgRed.white;
|
|
14032
14341
|
case "Error":
|
|
14033
|
-
return
|
|
14342
|
+
return chalk139.red;
|
|
14034
14343
|
case "Warning":
|
|
14035
|
-
return
|
|
14344
|
+
return chalk139.yellow;
|
|
14036
14345
|
case "Information":
|
|
14037
|
-
return
|
|
14346
|
+
return chalk139.cyan;
|
|
14038
14347
|
case "Debug":
|
|
14039
|
-
return
|
|
14348
|
+
return chalk139.gray;
|
|
14040
14349
|
case "Verbose":
|
|
14041
|
-
return
|
|
14350
|
+
return chalk139.dim;
|
|
14042
14351
|
default:
|
|
14043
|
-
return
|
|
14352
|
+
return chalk139.white;
|
|
14044
14353
|
}
|
|
14045
14354
|
}
|
|
14046
14355
|
function levelAbbrev(level) {
|
|
@@ -14081,12 +14390,12 @@ function formatTimestamp(iso) {
|
|
|
14081
14390
|
function formatEvent(event) {
|
|
14082
14391
|
const color = levelColor(event.Level);
|
|
14083
14392
|
const abbrev = levelAbbrev(event.Level);
|
|
14084
|
-
const ts8 =
|
|
14393
|
+
const ts8 = chalk139.dim(formatTimestamp(event.Timestamp));
|
|
14085
14394
|
const msg = renderMessage(event);
|
|
14086
14395
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
14087
14396
|
if (event.Exception) {
|
|
14088
14397
|
for (const line of event.Exception.split("\n")) {
|
|
14089
|
-
lines.push(
|
|
14398
|
+
lines.push(chalk139.red(` ${line}`));
|
|
14090
14399
|
}
|
|
14091
14400
|
}
|
|
14092
14401
|
return lines.join("\n");
|
|
@@ -14119,11 +14428,11 @@ function rejectTimestampFilter(filter) {
|
|
|
14119
14428
|
}
|
|
14120
14429
|
|
|
14121
14430
|
// src/shared/resolveNamedConnection.ts
|
|
14122
|
-
import
|
|
14431
|
+
import chalk140 from "chalk";
|
|
14123
14432
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
14124
14433
|
if (connections.length === 0) {
|
|
14125
14434
|
console.error(
|
|
14126
|
-
|
|
14435
|
+
chalk140.red(
|
|
14127
14436
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
14128
14437
|
)
|
|
14129
14438
|
);
|
|
@@ -14132,7 +14441,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
14132
14441
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
14133
14442
|
const connection = connections.find((c) => c.name === target);
|
|
14134
14443
|
if (!connection) {
|
|
14135
|
-
console.error(
|
|
14444
|
+
console.error(chalk140.red(`${kind} connection "${target}" not found.`));
|
|
14136
14445
|
process.exit(1);
|
|
14137
14446
|
}
|
|
14138
14447
|
return connection;
|
|
@@ -14161,7 +14470,7 @@ async function seqQuery(filter, options2) {
|
|
|
14161
14470
|
new URLSearchParams({ filter, count: String(count) })
|
|
14162
14471
|
);
|
|
14163
14472
|
if (events.length === 0) {
|
|
14164
|
-
console.log(
|
|
14473
|
+
console.log(chalk141.yellow("No events found."));
|
|
14165
14474
|
return;
|
|
14166
14475
|
}
|
|
14167
14476
|
if (options2.json) {
|
|
@@ -14172,11 +14481,11 @@ async function seqQuery(filter, options2) {
|
|
|
14172
14481
|
for (const event of chronological) {
|
|
14173
14482
|
console.log(formatEvent(event));
|
|
14174
14483
|
}
|
|
14175
|
-
console.log(
|
|
14484
|
+
console.log(chalk141.dim(`
|
|
14176
14485
|
${events.length} events`));
|
|
14177
14486
|
if (events.length >= count) {
|
|
14178
14487
|
console.log(
|
|
14179
|
-
|
|
14488
|
+
chalk141.yellow(
|
|
14180
14489
|
`Results limited to ${count}. Use --count to retrieve more.`
|
|
14181
14490
|
)
|
|
14182
14491
|
);
|
|
@@ -14184,10 +14493,10 @@ ${events.length} events`));
|
|
|
14184
14493
|
}
|
|
14185
14494
|
|
|
14186
14495
|
// src/shared/setNamedDefaultConnection.ts
|
|
14187
|
-
import
|
|
14496
|
+
import chalk142 from "chalk";
|
|
14188
14497
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
14189
14498
|
if (!connections.find((c) => c.name === name)) {
|
|
14190
|
-
console.error(
|
|
14499
|
+
console.error(chalk142.red(`Connection "${name}" not found.`));
|
|
14191
14500
|
process.exit(1);
|
|
14192
14501
|
}
|
|
14193
14502
|
setDefault(name);
|
|
@@ -14231,7 +14540,7 @@ function registerSignal(program2) {
|
|
|
14231
14540
|
}
|
|
14232
14541
|
|
|
14233
14542
|
// src/commands/sql/sqlAuth.ts
|
|
14234
|
-
import
|
|
14543
|
+
import chalk144 from "chalk";
|
|
14235
14544
|
|
|
14236
14545
|
// src/commands/sql/loadConnections.ts
|
|
14237
14546
|
function loadConnections3() {
|
|
@@ -14260,7 +14569,7 @@ function setDefaultConnection2(name) {
|
|
|
14260
14569
|
}
|
|
14261
14570
|
|
|
14262
14571
|
// src/commands/sql/promptConnection.ts
|
|
14263
|
-
import
|
|
14572
|
+
import chalk143 from "chalk";
|
|
14264
14573
|
async function promptConnection3(existingNames) {
|
|
14265
14574
|
const name = await promptInput("name", "Connection name:", "default");
|
|
14266
14575
|
assertUniqueName(existingNames, name);
|
|
@@ -14268,7 +14577,7 @@ async function promptConnection3(existingNames) {
|
|
|
14268
14577
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
14269
14578
|
const port = Number.parseInt(portStr, 10);
|
|
14270
14579
|
if (!Number.isFinite(port)) {
|
|
14271
|
-
console.error(
|
|
14580
|
+
console.error(chalk143.red(`Invalid port "${portStr}".`));
|
|
14272
14581
|
process.exit(1);
|
|
14273
14582
|
}
|
|
14274
14583
|
const user = await promptInput("user", "User:");
|
|
@@ -14281,13 +14590,13 @@ async function promptConnection3(existingNames) {
|
|
|
14281
14590
|
var sqlAuth = createConnectionAuth({
|
|
14282
14591
|
load: loadConnections3,
|
|
14283
14592
|
save: saveConnections3,
|
|
14284
|
-
format: (c) => `${
|
|
14593
|
+
format: (c) => `${chalk144.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
14285
14594
|
promptNew: promptConnection3,
|
|
14286
14595
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
14287
14596
|
});
|
|
14288
14597
|
|
|
14289
14598
|
// src/commands/sql/printTable.ts
|
|
14290
|
-
import
|
|
14599
|
+
import chalk145 from "chalk";
|
|
14291
14600
|
function formatCell(value) {
|
|
14292
14601
|
if (value === null || value === void 0) return "";
|
|
14293
14602
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -14296,7 +14605,7 @@ function formatCell(value) {
|
|
|
14296
14605
|
}
|
|
14297
14606
|
function printTable(rows) {
|
|
14298
14607
|
if (rows.length === 0) {
|
|
14299
|
-
console.log(
|
|
14608
|
+
console.log(chalk145.yellow("(no rows)"));
|
|
14300
14609
|
return;
|
|
14301
14610
|
}
|
|
14302
14611
|
const columns = Object.keys(rows[0]);
|
|
@@ -14304,13 +14613,13 @@ function printTable(rows) {
|
|
|
14304
14613
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
14305
14614
|
);
|
|
14306
14615
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
14307
|
-
console.log(
|
|
14308
|
-
console.log(
|
|
14616
|
+
console.log(chalk145.dim(header));
|
|
14617
|
+
console.log(chalk145.dim("-".repeat(header.length)));
|
|
14309
14618
|
for (const row of rows) {
|
|
14310
14619
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
14311
14620
|
console.log(line);
|
|
14312
14621
|
}
|
|
14313
|
-
console.log(
|
|
14622
|
+
console.log(chalk145.dim(`
|
|
14314
14623
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
14315
14624
|
}
|
|
14316
14625
|
|
|
@@ -14370,7 +14679,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
14370
14679
|
}
|
|
14371
14680
|
|
|
14372
14681
|
// src/commands/sql/sqlMutate.ts
|
|
14373
|
-
import
|
|
14682
|
+
import chalk146 from "chalk";
|
|
14374
14683
|
|
|
14375
14684
|
// src/commands/sql/isMutation.ts
|
|
14376
14685
|
var MUTATION_KEYWORDS = [
|
|
@@ -14404,7 +14713,7 @@ function isMutation(sql2) {
|
|
|
14404
14713
|
async function sqlMutate(query, connectionName) {
|
|
14405
14714
|
if (!isMutation(query)) {
|
|
14406
14715
|
console.error(
|
|
14407
|
-
|
|
14716
|
+
chalk146.red(
|
|
14408
14717
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
14409
14718
|
)
|
|
14410
14719
|
);
|
|
@@ -14414,18 +14723,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
14414
14723
|
const pool = await sqlConnect(conn);
|
|
14415
14724
|
try {
|
|
14416
14725
|
const result = await pool.request().query(query);
|
|
14417
|
-
console.log(
|
|
14726
|
+
console.log(chalk146.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
14418
14727
|
} finally {
|
|
14419
14728
|
await pool.close();
|
|
14420
14729
|
}
|
|
14421
14730
|
}
|
|
14422
14731
|
|
|
14423
14732
|
// src/commands/sql/sqlQuery.ts
|
|
14424
|
-
import
|
|
14733
|
+
import chalk147 from "chalk";
|
|
14425
14734
|
async function sqlQuery(query, connectionName) {
|
|
14426
14735
|
if (isMutation(query)) {
|
|
14427
14736
|
console.error(
|
|
14428
|
-
|
|
14737
|
+
chalk147.red(
|
|
14429
14738
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
14430
14739
|
)
|
|
14431
14740
|
);
|
|
@@ -14440,7 +14749,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
14440
14749
|
printTable(rows);
|
|
14441
14750
|
} else {
|
|
14442
14751
|
console.log(
|
|
14443
|
-
|
|
14752
|
+
chalk147.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
14444
14753
|
);
|
|
14445
14754
|
}
|
|
14446
14755
|
} finally {
|
|
@@ -15020,14 +15329,14 @@ import {
|
|
|
15020
15329
|
import { dirname as dirname22, join as join40 } from "path";
|
|
15021
15330
|
|
|
15022
15331
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
15023
|
-
import
|
|
15332
|
+
import chalk148 from "chalk";
|
|
15024
15333
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
15025
15334
|
function validateStagedContent(filename, content) {
|
|
15026
15335
|
const firstLine = content.split("\n")[0];
|
|
15027
15336
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
15028
15337
|
if (!match) {
|
|
15029
15338
|
console.error(
|
|
15030
|
-
|
|
15339
|
+
chalk148.red(
|
|
15031
15340
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
15032
15341
|
)
|
|
15033
15342
|
);
|
|
@@ -15036,7 +15345,7 @@ function validateStagedContent(filename, content) {
|
|
|
15036
15345
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
15037
15346
|
if (!contentAfterLink) {
|
|
15038
15347
|
console.error(
|
|
15039
|
-
|
|
15348
|
+
chalk148.red(
|
|
15040
15349
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
15041
15350
|
)
|
|
15042
15351
|
);
|
|
@@ -15432,7 +15741,7 @@ function registerVoice(program2) {
|
|
|
15432
15741
|
|
|
15433
15742
|
// src/commands/roam/auth.ts
|
|
15434
15743
|
import { randomBytes } from "crypto";
|
|
15435
|
-
import
|
|
15744
|
+
import chalk149 from "chalk";
|
|
15436
15745
|
|
|
15437
15746
|
// src/lib/openBrowser.ts
|
|
15438
15747
|
import { execSync as execSync43 } from "child_process";
|
|
@@ -15607,13 +15916,13 @@ async function auth() {
|
|
|
15607
15916
|
saveGlobalConfig(config);
|
|
15608
15917
|
const state = randomBytes(16).toString("hex");
|
|
15609
15918
|
console.log(
|
|
15610
|
-
|
|
15919
|
+
chalk149.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
15611
15920
|
);
|
|
15612
|
-
console.log(
|
|
15613
|
-
console.log(
|
|
15614
|
-
console.log(
|
|
15921
|
+
console.log(chalk149.white("http://localhost:14523/callback\n"));
|
|
15922
|
+
console.log(chalk149.blue("Opening browser for authorization..."));
|
|
15923
|
+
console.log(chalk149.dim("Waiting for authorization callback..."));
|
|
15615
15924
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
15616
|
-
console.log(
|
|
15925
|
+
console.log(chalk149.dim("Exchanging code for tokens..."));
|
|
15617
15926
|
const tokens = await exchangeToken({
|
|
15618
15927
|
code,
|
|
15619
15928
|
clientId,
|
|
@@ -15629,7 +15938,7 @@ async function auth() {
|
|
|
15629
15938
|
};
|
|
15630
15939
|
saveGlobalConfig(config);
|
|
15631
15940
|
console.log(
|
|
15632
|
-
|
|
15941
|
+
chalk149.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
15633
15942
|
);
|
|
15634
15943
|
}
|
|
15635
15944
|
|
|
@@ -16052,7 +16361,7 @@ import { execSync as execSync45 } from "child_process";
|
|
|
16052
16361
|
import { existsSync as existsSync49, mkdirSync as mkdirSync17, unlinkSync as unlinkSync15, writeFileSync as writeFileSync30 } from "fs";
|
|
16053
16362
|
import { tmpdir as tmpdir7 } from "os";
|
|
16054
16363
|
import { join as join51, resolve as resolve13 } from "path";
|
|
16055
|
-
import
|
|
16364
|
+
import chalk150 from "chalk";
|
|
16056
16365
|
|
|
16057
16366
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
16058
16367
|
var captureWindowPs1 = `
|
|
@@ -16203,20 +16512,20 @@ function screenshot(processName) {
|
|
|
16203
16512
|
const config = loadConfig();
|
|
16204
16513
|
const outputDir = resolve13(config.screenshot.outputDir);
|
|
16205
16514
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
16206
|
-
console.log(
|
|
16515
|
+
console.log(chalk150.gray(`Capturing window for process "${processName}" ...`));
|
|
16207
16516
|
try {
|
|
16208
16517
|
runPowerShellScript(processName, outputPath);
|
|
16209
|
-
console.log(
|
|
16518
|
+
console.log(chalk150.green(`Screenshot saved: ${outputPath}`));
|
|
16210
16519
|
} catch (error) {
|
|
16211
16520
|
const msg = error instanceof Error ? error.message : String(error);
|
|
16212
|
-
console.error(
|
|
16521
|
+
console.error(chalk150.red(`Failed to capture screenshot: ${msg}`));
|
|
16213
16522
|
process.exit(1);
|
|
16214
16523
|
}
|
|
16215
16524
|
}
|
|
16216
16525
|
|
|
16217
16526
|
// src/commands/sessions/summarise/index.ts
|
|
16218
16527
|
import * as fs28 from "fs";
|
|
16219
|
-
import
|
|
16528
|
+
import chalk151 from "chalk";
|
|
16220
16529
|
|
|
16221
16530
|
// src/commands/sessions/summarise/shared.ts
|
|
16222
16531
|
import * as fs26 from "fs";
|
|
@@ -16343,22 +16652,22 @@ ${firstMessage}`);
|
|
|
16343
16652
|
async function summarise4(options2) {
|
|
16344
16653
|
const files = await discoverSessionJsonlPaths();
|
|
16345
16654
|
if (files.length === 0) {
|
|
16346
|
-
console.log(
|
|
16655
|
+
console.log(chalk151.yellow("No sessions found."));
|
|
16347
16656
|
return;
|
|
16348
16657
|
}
|
|
16349
16658
|
const toProcess = selectCandidates(files, options2);
|
|
16350
16659
|
if (toProcess.length === 0) {
|
|
16351
|
-
console.log(
|
|
16660
|
+
console.log(chalk151.green("All sessions already summarised."));
|
|
16352
16661
|
return;
|
|
16353
16662
|
}
|
|
16354
16663
|
console.log(
|
|
16355
|
-
|
|
16664
|
+
chalk151.cyan(
|
|
16356
16665
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
16357
16666
|
)
|
|
16358
16667
|
);
|
|
16359
16668
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
16360
16669
|
console.log(
|
|
16361
|
-
|
|
16670
|
+
chalk151.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk151.yellow(`, ${failed2} skipped`) : "")
|
|
16362
16671
|
);
|
|
16363
16672
|
}
|
|
16364
16673
|
function selectCandidates(files, options2) {
|
|
@@ -16378,16 +16687,16 @@ function processSessions(files) {
|
|
|
16378
16687
|
let failed2 = 0;
|
|
16379
16688
|
for (let i = 0; i < files.length; i++) {
|
|
16380
16689
|
const file = files[i];
|
|
16381
|
-
process.stdout.write(
|
|
16690
|
+
process.stdout.write(chalk151.dim(` [${i + 1}/${files.length}] `));
|
|
16382
16691
|
const summary = summariseSession(file);
|
|
16383
16692
|
if (summary) {
|
|
16384
16693
|
writeSummary(file, summary);
|
|
16385
16694
|
succeeded++;
|
|
16386
|
-
process.stdout.write(`${
|
|
16695
|
+
process.stdout.write(`${chalk151.green("\u2713")} ${summary}
|
|
16387
16696
|
`);
|
|
16388
16697
|
} else {
|
|
16389
16698
|
failed2++;
|
|
16390
|
-
process.stdout.write(` ${
|
|
16699
|
+
process.stdout.write(` ${chalk151.yellow("skip")}
|
|
16391
16700
|
`);
|
|
16392
16701
|
}
|
|
16393
16702
|
}
|
|
@@ -16402,10 +16711,10 @@ function registerSessions(program2) {
|
|
|
16402
16711
|
}
|
|
16403
16712
|
|
|
16404
16713
|
// src/commands/statusLine.ts
|
|
16405
|
-
import
|
|
16714
|
+
import chalk153 from "chalk";
|
|
16406
16715
|
|
|
16407
16716
|
// src/commands/buildLimitsSegment.ts
|
|
16408
|
-
import
|
|
16717
|
+
import chalk152 from "chalk";
|
|
16409
16718
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
16410
16719
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
16411
16720
|
function formatTimeLeft(resetsAt) {
|
|
@@ -16428,10 +16737,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
16428
16737
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
16429
16738
|
const label2 = `${Math.round(pct)}%`;
|
|
16430
16739
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
16431
|
-
if (projected == null) return
|
|
16432
|
-
if (projected > 100) return
|
|
16433
|
-
if (projected > 75) return
|
|
16434
|
-
return
|
|
16740
|
+
if (projected == null) return chalk152.green(label2);
|
|
16741
|
+
if (projected > 100) return chalk152.red(label2);
|
|
16742
|
+
if (projected > 75) return chalk152.yellow(label2);
|
|
16743
|
+
return chalk152.green(label2);
|
|
16435
16744
|
}
|
|
16436
16745
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
16437
16746
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -16457,14 +16766,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
16457
16766
|
}
|
|
16458
16767
|
|
|
16459
16768
|
// src/commands/statusLine.ts
|
|
16460
|
-
|
|
16769
|
+
chalk153.level = 3;
|
|
16461
16770
|
function formatNumber(num) {
|
|
16462
16771
|
return num.toLocaleString("en-US");
|
|
16463
16772
|
}
|
|
16464
16773
|
function colorizePercent(pct) {
|
|
16465
16774
|
const label2 = `${Math.round(pct)}%`;
|
|
16466
|
-
if (pct > 80) return
|
|
16467
|
-
if (pct > 40) return
|
|
16775
|
+
if (pct > 80) return chalk153.red(label2);
|
|
16776
|
+
if (pct > 40) return chalk153.yellow(label2);
|
|
16468
16777
|
return label2;
|
|
16469
16778
|
}
|
|
16470
16779
|
async function statusLine() {
|
|
@@ -16487,7 +16796,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
16487
16796
|
// src/commands/sync/syncClaudeMd.ts
|
|
16488
16797
|
import * as fs29 from "fs";
|
|
16489
16798
|
import * as path48 from "path";
|
|
16490
|
-
import
|
|
16799
|
+
import chalk154 from "chalk";
|
|
16491
16800
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
16492
16801
|
const source = path48.join(claudeDir, "CLAUDE.md");
|
|
16493
16802
|
const target = path48.join(targetBase, "CLAUDE.md");
|
|
@@ -16496,12 +16805,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
16496
16805
|
const targetContent = fs29.readFileSync(target, "utf-8");
|
|
16497
16806
|
if (sourceContent !== targetContent) {
|
|
16498
16807
|
console.log(
|
|
16499
|
-
|
|
16808
|
+
chalk154.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
16500
16809
|
);
|
|
16501
16810
|
console.log();
|
|
16502
16811
|
printDiff(targetContent, sourceContent);
|
|
16503
16812
|
const confirm = options2?.yes || await promptConfirm(
|
|
16504
|
-
|
|
16813
|
+
chalk154.red("Overwrite existing CLAUDE.md?"),
|
|
16505
16814
|
false
|
|
16506
16815
|
);
|
|
16507
16816
|
if (!confirm) {
|
|
@@ -16517,7 +16826,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
16517
16826
|
// src/commands/sync/syncSettings.ts
|
|
16518
16827
|
import * as fs30 from "fs";
|
|
16519
16828
|
import * as path49 from "path";
|
|
16520
|
-
import
|
|
16829
|
+
import chalk155 from "chalk";
|
|
16521
16830
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
16522
16831
|
const source = path49.join(claudeDir, "settings.json");
|
|
16523
16832
|
const target = path49.join(targetBase, "settings.json");
|
|
@@ -16533,14 +16842,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
16533
16842
|
if (mergedContent !== normalizedTarget) {
|
|
16534
16843
|
if (!options2?.yes) {
|
|
16535
16844
|
console.log(
|
|
16536
|
-
|
|
16845
|
+
chalk155.yellow(
|
|
16537
16846
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
16538
16847
|
)
|
|
16539
16848
|
);
|
|
16540
16849
|
console.log();
|
|
16541
16850
|
printDiff(targetContent, mergedContent);
|
|
16542
16851
|
const confirm = await promptConfirm(
|
|
16543
|
-
|
|
16852
|
+
chalk155.red("Overwrite existing settings.json?"),
|
|
16544
16853
|
false
|
|
16545
16854
|
);
|
|
16546
16855
|
if (!confirm) {
|