@staff0rd/assist 0.181.0 → 0.183.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-writes +1 -0
- package/dist/allowed.cli-writes +1 -0
- package/dist/commands/backlog/web/bundle.js +6 -6
- package/dist/index.js +716 -591
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.183.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -136,10 +136,11 @@ import { join } from "path";
|
|
|
136
136
|
// src/commands/backlog/loadComments.ts
|
|
137
137
|
function loadComments(db, itemId) {
|
|
138
138
|
const rows = db.prepare(
|
|
139
|
-
"SELECT text, phase, timestamp, type FROM comments WHERE item_id = ? ORDER BY idx"
|
|
139
|
+
"SELECT id, text, phase, timestamp, type FROM comments WHERE item_id = ? ORDER BY idx"
|
|
140
140
|
).all(itemId);
|
|
141
141
|
return rows.map((r) => {
|
|
142
142
|
const c = {
|
|
143
|
+
id: r.id,
|
|
143
144
|
text: r.text,
|
|
144
145
|
timestamp: r.timestamp,
|
|
145
146
|
type: r.type
|
|
@@ -220,12 +221,27 @@ import { readFileSync, statSync as statSync2 } from "fs";
|
|
|
220
221
|
// src/commands/backlog/insertItemRelations.ts
|
|
221
222
|
function insertComments(db, item) {
|
|
222
223
|
if (!item.comments) return;
|
|
223
|
-
const
|
|
224
|
+
const stmtWithId = db.prepare(
|
|
225
|
+
"INSERT INTO comments (id, item_id, idx, text, phase, timestamp, type) VALUES (?, ?, ?, ?, ?, ?, ?)"
|
|
226
|
+
);
|
|
227
|
+
const stmtNoId = db.prepare(
|
|
224
228
|
"INSERT INTO comments (item_id, idx, text, phase, timestamp, type) VALUES (?, ?, ?, ?, ?, ?)"
|
|
225
229
|
);
|
|
226
230
|
for (let i = 0; i < item.comments.length; i++) {
|
|
227
231
|
const c = item.comments[i];
|
|
228
|
-
|
|
232
|
+
if (c.id !== void 0) {
|
|
233
|
+
stmtWithId.run(
|
|
234
|
+
c.id,
|
|
235
|
+
item.id,
|
|
236
|
+
i,
|
|
237
|
+
c.text,
|
|
238
|
+
c.phase ?? null,
|
|
239
|
+
c.timestamp,
|
|
240
|
+
c.type
|
|
241
|
+
);
|
|
242
|
+
} else {
|
|
243
|
+
stmtNoId.run(item.id, i, c.text, c.phase ?? null, c.timestamp, c.type);
|
|
244
|
+
}
|
|
229
245
|
}
|
|
230
246
|
}
|
|
231
247
|
function insertLinks(db, item) {
|
|
@@ -320,6 +336,7 @@ var planPhaseSchema = z.strictObject({
|
|
|
320
336
|
});
|
|
321
337
|
var backlogCommentTypeSchema = z.enum(["comment", "summary"]);
|
|
322
338
|
var backlogCommentSchema = z.strictObject({
|
|
339
|
+
id: z.number().optional(),
|
|
323
340
|
text: z.string(),
|
|
324
341
|
phase: z.number().optional(),
|
|
325
342
|
timestamp: z.string(),
|
|
@@ -407,7 +424,9 @@ import { join as join2 } from "path";
|
|
|
407
424
|
var gitignoreEntries = [
|
|
408
425
|
".assist/backlog.db",
|
|
409
426
|
".assist/backlog.db-shm",
|
|
410
|
-
".assist/backlog.db-wal"
|
|
427
|
+
".assist/backlog.db-wal",
|
|
428
|
+
".assist-signal*.json",
|
|
429
|
+
".assist-lock-*.json"
|
|
411
430
|
];
|
|
412
431
|
function ensureGitignore(dir) {
|
|
413
432
|
const gitignorePath = join2(dir, ".gitignore");
|
|
@@ -425,6 +444,25 @@ var _db;
|
|
|
425
444
|
function getDbPath(dir) {
|
|
426
445
|
return join3(dir, ".assist", "backlog.db");
|
|
427
446
|
}
|
|
447
|
+
function migrateCommentsAddId(db) {
|
|
448
|
+
const cols = db.pragma("table_info(comments)");
|
|
449
|
+
if (cols.length === 0 || cols.some((c) => c.name === "id")) return;
|
|
450
|
+
db.exec(`
|
|
451
|
+
CREATE TABLE comments_new (
|
|
452
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
453
|
+
item_id INTEGER NOT NULL REFERENCES items(id) ON DELETE CASCADE,
|
|
454
|
+
idx INTEGER NOT NULL,
|
|
455
|
+
text TEXT NOT NULL,
|
|
456
|
+
phase INTEGER,
|
|
457
|
+
timestamp TEXT NOT NULL,
|
|
458
|
+
type TEXT NOT NULL DEFAULT 'comment'
|
|
459
|
+
);
|
|
460
|
+
INSERT INTO comments_new (item_id, idx, text, phase, timestamp, type)
|
|
461
|
+
SELECT item_id, idx, text, phase, timestamp, type FROM comments;
|
|
462
|
+
DROP TABLE comments;
|
|
463
|
+
ALTER TABLE comments_new RENAME TO comments;
|
|
464
|
+
`);
|
|
465
|
+
}
|
|
428
466
|
function initSchema(db) {
|
|
429
467
|
db.exec(`
|
|
430
468
|
CREATE TABLE IF NOT EXISTS items (
|
|
@@ -438,13 +476,13 @@ function initSchema(db) {
|
|
|
438
476
|
);
|
|
439
477
|
|
|
440
478
|
CREATE TABLE IF NOT EXISTS comments (
|
|
479
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
441
480
|
item_id INTEGER NOT NULL REFERENCES items(id) ON DELETE CASCADE,
|
|
442
481
|
idx INTEGER NOT NULL,
|
|
443
482
|
text TEXT NOT NULL,
|
|
444
483
|
phase INTEGER,
|
|
445
484
|
timestamp TEXT NOT NULL,
|
|
446
|
-
type TEXT NOT NULL DEFAULT 'comment'
|
|
447
|
-
PRIMARY KEY (item_id, idx)
|
|
485
|
+
type TEXT NOT NULL DEFAULT 'comment'
|
|
448
486
|
);
|
|
449
487
|
|
|
450
488
|
CREATE TABLE IF NOT EXISTS links (
|
|
@@ -485,6 +523,7 @@ function openDb(dir) {
|
|
|
485
523
|
db.pragma("journal_mode = WAL");
|
|
486
524
|
db.pragma("foreign_keys = ON");
|
|
487
525
|
initSchema(db);
|
|
526
|
+
migrateCommentsAddId(db);
|
|
488
527
|
ensureGitignore(dir);
|
|
489
528
|
_db = db;
|
|
490
529
|
return db;
|
|
@@ -725,9 +764,10 @@ function buildCommentLines(comments2) {
|
|
|
725
764
|
return ["", "Comments:", ...comments2.map(formatPromptComment)];
|
|
726
765
|
}
|
|
727
766
|
function formatPromptComment(entry) {
|
|
767
|
+
const id = entry.id !== void 0 ? `#${entry.id} ` : "";
|
|
728
768
|
const tag = entry.type === "summary" ? "[summary]" : "[comment]";
|
|
729
769
|
const phase = entry.phase !== void 0 ? ` (phase ${entry.phase + 1})` : "";
|
|
730
|
-
return `${tag}${phase} ${entry.timestamp}
|
|
770
|
+
return `${id}${tag}${phase} ${entry.timestamp}
|
|
731
771
|
${entry.text}`;
|
|
732
772
|
}
|
|
733
773
|
|
|
@@ -903,8 +943,8 @@ function spawnClaude(prompt, options2 = {}) {
|
|
|
903
943
|
const child = spawn("claude", args, {
|
|
904
944
|
stdio: "inherit"
|
|
905
945
|
});
|
|
906
|
-
const done2 = new Promise((
|
|
907
|
-
child.on("close", (code) =>
|
|
946
|
+
const done2 = new Promise((resolve8, reject) => {
|
|
947
|
+
child.on("close", (code) => resolve8(code ?? 0));
|
|
908
948
|
child.on("error", reject);
|
|
909
949
|
});
|
|
910
950
|
return { child, done: done2 };
|
|
@@ -1173,10 +1213,11 @@ import chalk14 from "chalk";
|
|
|
1173
1213
|
// src/commands/backlog/formatComment.ts
|
|
1174
1214
|
import chalk11 from "chalk";
|
|
1175
1215
|
function formatComment(entry) {
|
|
1216
|
+
const id = entry.id !== void 0 ? chalk11.dim(`#${entry.id} `) : "";
|
|
1176
1217
|
const tag = entry.type === "summary" ? chalk11.magenta("[summary]") : chalk11.cyan("[comment]");
|
|
1177
1218
|
const phase = entry.phase !== void 0 ? chalk11.dim(` (phase ${entry.phase + 1})`) : "";
|
|
1178
1219
|
const time = chalk11.dim(entry.timestamp);
|
|
1179
|
-
return `${tag}${phase} ${time}
|
|
1220
|
+
return `${id}${tag}${phase} ${time}
|
|
1180
1221
|
${entry.text}`;
|
|
1181
1222
|
}
|
|
1182
1223
|
|
|
@@ -1358,12 +1399,12 @@ function getHtml() {
|
|
|
1358
1399
|
|
|
1359
1400
|
// src/commands/backlog/web/parseItemBody.ts
|
|
1360
1401
|
function readBody(req) {
|
|
1361
|
-
return new Promise((
|
|
1402
|
+
return new Promise((resolve8, reject) => {
|
|
1362
1403
|
let body = "";
|
|
1363
1404
|
req.on("data", (chunk) => {
|
|
1364
1405
|
body += chunk.toString();
|
|
1365
1406
|
});
|
|
1366
|
-
req.on("end", () =>
|
|
1407
|
+
req.on("end", () => resolve8(body));
|
|
1367
1408
|
req.on("error", reject);
|
|
1368
1409
|
});
|
|
1369
1410
|
}
|
|
@@ -1542,9 +1583,9 @@ async function refine(id) {
|
|
|
1542
1583
|
import { execSync } from "child_process";
|
|
1543
1584
|
|
|
1544
1585
|
// src/shared/loadConfig.ts
|
|
1545
|
-
import { existsSync as existsSync9,
|
|
1586
|
+
import { existsSync as existsSync9, writeFileSync as writeFileSync5 } from "fs";
|
|
1546
1587
|
import { homedir } from "os";
|
|
1547
|
-
import {
|
|
1588
|
+
import { dirname as dirname2, join as join8 } from "path";
|
|
1548
1589
|
import chalk18 from "chalk";
|
|
1549
1590
|
import { stringify as stringifyYaml } from "yaml";
|
|
1550
1591
|
|
|
@@ -1576,7 +1617,8 @@ var runConfigSchema = z2.strictObject({
|
|
|
1576
1617
|
params: z2.array(runParamSchema).optional(),
|
|
1577
1618
|
env: z2.record(z2.string(), z2.string()).optional(),
|
|
1578
1619
|
filter: z2.string().optional(),
|
|
1579
|
-
pre: z2.array(z2.string()).optional()
|
|
1620
|
+
pre: z2.array(z2.string()).optional(),
|
|
1621
|
+
cwd: z2.string().optional()
|
|
1580
1622
|
});
|
|
1581
1623
|
var transcriptConfigSchema = z2.strictObject({
|
|
1582
1624
|
vttDir: z2.string(),
|
|
@@ -1703,6 +1745,9 @@ function getConfigPath() {
|
|
|
1703
1745
|
function getGlobalConfigPath() {
|
|
1704
1746
|
return join8(homedir(), ".assist.yml");
|
|
1705
1747
|
}
|
|
1748
|
+
function getConfigDir() {
|
|
1749
|
+
return dirname2(getConfigPath());
|
|
1750
|
+
}
|
|
1706
1751
|
function loadConfig() {
|
|
1707
1752
|
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
1708
1753
|
const projectRaw = loadRawYaml(getConfigPath());
|
|
@@ -1722,24 +1767,6 @@ function saveConfig(config) {
|
|
|
1722
1767
|
const configPath = getConfigPath();
|
|
1723
1768
|
writeFileSync5(configPath, stringifyYaml(config, { lineWidth: 0 }));
|
|
1724
1769
|
}
|
|
1725
|
-
function getRepoName() {
|
|
1726
|
-
const config = loadConfig();
|
|
1727
|
-
if (config.devlog?.name) {
|
|
1728
|
-
return config.devlog.name;
|
|
1729
|
-
}
|
|
1730
|
-
const packageJsonPath = join8(process.cwd(), "package.json");
|
|
1731
|
-
if (existsSync9(packageJsonPath)) {
|
|
1732
|
-
try {
|
|
1733
|
-
const content = readFileSync8(packageJsonPath, "utf-8");
|
|
1734
|
-
const pkg = JSON.parse(content);
|
|
1735
|
-
if (pkg.name) {
|
|
1736
|
-
return pkg.name;
|
|
1737
|
-
}
|
|
1738
|
-
} catch {
|
|
1739
|
-
}
|
|
1740
|
-
}
|
|
1741
|
-
return basename(process.cwd());
|
|
1742
|
-
}
|
|
1743
1770
|
function getTranscriptConfig() {
|
|
1744
1771
|
const config = loadConfig();
|
|
1745
1772
|
if (!config.transcript) {
|
|
@@ -1955,11 +1982,12 @@ function setupVerifyScript(packageJsonPath, scriptName, command) {
|
|
|
1955
1982
|
}
|
|
1956
1983
|
|
|
1957
1984
|
// src/commands/run/buildRunEntry.ts
|
|
1958
|
-
function buildRunEntry(name, command, args) {
|
|
1985
|
+
function buildRunEntry(name, command, args, options2) {
|
|
1959
1986
|
const effectiveArgs = args.length === 0 && command.includes(" ") ? command.split(/\s+/).slice(1) : args;
|
|
1960
1987
|
const effectiveCommand = args.length === 0 && command.includes(" ") ? command.split(/\s+/)[0] : command;
|
|
1961
1988
|
const entry = { name, command: effectiveCommand };
|
|
1962
1989
|
if (effectiveArgs.length > 0) entry.args = effectiveArgs;
|
|
1990
|
+
if (options2?.cwd) entry.cwd = options2.cwd;
|
|
1963
1991
|
return entry;
|
|
1964
1992
|
}
|
|
1965
1993
|
|
|
@@ -2030,12 +2058,12 @@ import * as path3 from "path";
|
|
|
2030
2058
|
import chalk25 from "chalk";
|
|
2031
2059
|
|
|
2032
2060
|
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
2033
|
-
import { existsSync as existsSync11, readFileSync as
|
|
2061
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
2034
2062
|
import { join as join10 } from "path";
|
|
2035
2063
|
import chalk24 from "chalk";
|
|
2036
2064
|
function loadKnipConfig(knipJsonPath) {
|
|
2037
2065
|
if (existsSync11(knipJsonPath)) {
|
|
2038
|
-
return JSON.parse(
|
|
2066
|
+
return JSON.parse(readFileSync9(knipJsonPath, "utf-8"));
|
|
2039
2067
|
}
|
|
2040
2068
|
return { $schema: "https://unpkg.com/knip@5/schema.json" };
|
|
2041
2069
|
}
|
|
@@ -2088,7 +2116,7 @@ import chalk29 from "chalk";
|
|
|
2088
2116
|
|
|
2089
2117
|
// src/commands/lint/init.ts
|
|
2090
2118
|
import { execSync as execSync5 } from "child_process";
|
|
2091
|
-
import { existsSync as existsSync14, readFileSync as
|
|
2119
|
+
import { existsSync as existsSync14, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
2092
2120
|
import { dirname as dirname7, join as join11 } from "path";
|
|
2093
2121
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2094
2122
|
import chalk28 from "chalk";
|
|
@@ -2114,7 +2142,7 @@ async function promptConfirm(message, initial = true) {
|
|
|
2114
2142
|
|
|
2115
2143
|
// src/shared/removeEslint/index.ts
|
|
2116
2144
|
import { execSync as execSync4 } from "child_process";
|
|
2117
|
-
import { existsSync as existsSync13, readFileSync as
|
|
2145
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
2118
2146
|
|
|
2119
2147
|
// src/shared/removeEslint/removeEslintConfigFiles.ts
|
|
2120
2148
|
import { existsSync as existsSync12, unlinkSync as unlinkSync3 } from "fs";
|
|
@@ -2158,7 +2186,7 @@ function removeEslintFromPackageJson(options2) {
|
|
|
2158
2186
|
if (!existsSync13(packageJsonPath)) {
|
|
2159
2187
|
return false;
|
|
2160
2188
|
}
|
|
2161
|
-
const packageJson = JSON.parse(
|
|
2189
|
+
const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
2162
2190
|
let modified = false;
|
|
2163
2191
|
modified = removeEslintDeps(packageJson.dependencies) || modified;
|
|
2164
2192
|
modified = removeEslintDeps(packageJson.devDependencies) || modified;
|
|
@@ -2237,8 +2265,8 @@ async function init() {
|
|
|
2237
2265
|
return;
|
|
2238
2266
|
}
|
|
2239
2267
|
const linterConfigPath = join11(__dirname2, "commands/lint/biome.linter.json");
|
|
2240
|
-
const linterConfig = JSON.parse(
|
|
2241
|
-
const biomeConfig = JSON.parse(
|
|
2268
|
+
const linterConfig = JSON.parse(readFileSync11(linterConfigPath, "utf-8"));
|
|
2269
|
+
const biomeConfig = JSON.parse(readFileSync11(biomeConfigPath, "utf-8"));
|
|
2242
2270
|
const oldContent = `${JSON.stringify(biomeConfig, null, 2)}
|
|
2243
2271
|
`;
|
|
2244
2272
|
biomeConfig.linter = linterConfig.linter;
|
|
@@ -2985,7 +3013,7 @@ function lint(options2 = {}) {
|
|
|
2985
3013
|
|
|
2986
3014
|
// src/commands/new/registerNew/newCli/index.ts
|
|
2987
3015
|
import { execSync as execSync11 } from "child_process";
|
|
2988
|
-
import { basename
|
|
3016
|
+
import { basename, resolve } from "path";
|
|
2989
3017
|
|
|
2990
3018
|
// src/commands/verify/hardcodedColors.ts
|
|
2991
3019
|
import { execSync as execSync6 } from "child_process";
|
|
@@ -3214,14 +3242,14 @@ function flushIfFailed(exitCode, chunks) {
|
|
|
3214
3242
|
|
|
3215
3243
|
// src/commands/verify/run/runAllEntries.ts
|
|
3216
3244
|
function runEntry(entry, onComplete) {
|
|
3217
|
-
return new Promise((
|
|
3245
|
+
return new Promise((resolve8) => {
|
|
3218
3246
|
const child = spawnCommand(entry.fullCommand, entry.cwd, entry.env);
|
|
3219
3247
|
const chunks = collectOutput(child);
|
|
3220
3248
|
child.on("close", (code) => {
|
|
3221
3249
|
const exitCode = code ?? 1;
|
|
3222
3250
|
flushIfFailed(exitCode, chunks);
|
|
3223
3251
|
onComplete?.(exitCode);
|
|
3224
|
-
|
|
3252
|
+
resolve8({ script: entry.name, code: exitCode });
|
|
3225
3253
|
});
|
|
3226
3254
|
});
|
|
3227
3255
|
}
|
|
@@ -3351,7 +3379,7 @@ program.parse();
|
|
|
3351
3379
|
|
|
3352
3380
|
// src/commands/new/registerNew/newCli/index.ts
|
|
3353
3381
|
async function newCli() {
|
|
3354
|
-
const name =
|
|
3382
|
+
const name = basename(resolve("."));
|
|
3355
3383
|
initGit();
|
|
3356
3384
|
initPackageJson(name);
|
|
3357
3385
|
console.log("Installing dependencies...");
|
|
@@ -3366,7 +3394,7 @@ async function newCli() {
|
|
|
3366
3394
|
|
|
3367
3395
|
// src/commands/new/registerNew/newProject.ts
|
|
3368
3396
|
import { execSync as execSync13 } from "child_process";
|
|
3369
|
-
import { existsSync as existsSync18, readFileSync as
|
|
3397
|
+
import { existsSync as existsSync18, readFileSync as readFileSync14, writeFileSync as writeFileSync14 } from "fs";
|
|
3370
3398
|
|
|
3371
3399
|
// src/commands/deploy/init/index.ts
|
|
3372
3400
|
import { execSync as execSync12 } from "child_process";
|
|
@@ -3374,7 +3402,7 @@ import chalk40 from "chalk";
|
|
|
3374
3402
|
import enquirer6 from "enquirer";
|
|
3375
3403
|
|
|
3376
3404
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
3377
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as
|
|
3405
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync4, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
|
|
3378
3406
|
import { dirname as dirname13, join as join14 } from "path";
|
|
3379
3407
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3380
3408
|
import chalk39 from "chalk";
|
|
@@ -3384,13 +3412,13 @@ function getExistingSiteId() {
|
|
|
3384
3412
|
if (!existsSync17(WORKFLOW_PATH)) {
|
|
3385
3413
|
return null;
|
|
3386
3414
|
}
|
|
3387
|
-
const content =
|
|
3415
|
+
const content = readFileSync13(WORKFLOW_PATH, "utf-8");
|
|
3388
3416
|
const match = content.match(/-s\s+([a-f0-9-]{36})/);
|
|
3389
3417
|
return match ? match[1] : null;
|
|
3390
3418
|
}
|
|
3391
3419
|
function getTemplateContent(siteId) {
|
|
3392
3420
|
const templatePath = join14(__dirname3, "commands/deploy/build.yml");
|
|
3393
|
-
const template =
|
|
3421
|
+
const template = readFileSync13(templatePath, "utf-8");
|
|
3394
3422
|
return template.replace("{{NETLIFY_SITE_ID}}", siteId);
|
|
3395
3423
|
}
|
|
3396
3424
|
async function updateWorkflow(siteId) {
|
|
@@ -3400,7 +3428,7 @@ async function updateWorkflow(siteId) {
|
|
|
3400
3428
|
mkdirSync4(workflowDir, { recursive: true });
|
|
3401
3429
|
}
|
|
3402
3430
|
if (existsSync17(WORKFLOW_PATH)) {
|
|
3403
|
-
const oldContent =
|
|
3431
|
+
const oldContent = readFileSync13(WORKFLOW_PATH, "utf-8");
|
|
3404
3432
|
if (oldContent === newContent) {
|
|
3405
3433
|
console.log(chalk39.green("build.yml is already up to date"));
|
|
3406
3434
|
return;
|
|
@@ -3498,7 +3526,7 @@ function addViteBaseConfig() {
|
|
|
3498
3526
|
console.log("No vite.config.ts found, skipping base config");
|
|
3499
3527
|
return;
|
|
3500
3528
|
}
|
|
3501
|
-
const content =
|
|
3529
|
+
const content = readFileSync14(viteConfigPath, "utf-8");
|
|
3502
3530
|
if (content.includes("base:")) {
|
|
3503
3531
|
console.log("vite.config.ts already has base config");
|
|
3504
3532
|
return;
|
|
@@ -3768,24 +3796,73 @@ function comments(id) {
|
|
|
3768
3796
|
}
|
|
3769
3797
|
}
|
|
3770
3798
|
|
|
3799
|
+
// src/commands/backlog/delete-comment/index.ts
|
|
3800
|
+
import chalk43 from "chalk";
|
|
3801
|
+
|
|
3802
|
+
// src/commands/backlog/deleteComment.ts
|
|
3803
|
+
function deleteComment(db, itemId, commentId) {
|
|
3804
|
+
const row = db.prepare("SELECT type FROM comments WHERE id = ? AND item_id = ?").get(commentId, itemId);
|
|
3805
|
+
if (!row) return "not-found";
|
|
3806
|
+
if (row.type === "summary") return "is-summary";
|
|
3807
|
+
db.prepare("DELETE FROM comments WHERE id = ? AND item_id = ?").run(
|
|
3808
|
+
commentId,
|
|
3809
|
+
itemId
|
|
3810
|
+
);
|
|
3811
|
+
return "deleted";
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
// src/commands/backlog/delete-comment/index.ts
|
|
3815
|
+
function deleteCommentCmd(id, commentId) {
|
|
3816
|
+
const result = loadAndFindItem(id);
|
|
3817
|
+
if (!result) process.exit(1);
|
|
3818
|
+
const dir = getBacklogDir();
|
|
3819
|
+
const db = openDb(dir);
|
|
3820
|
+
const outcome = deleteComment(
|
|
3821
|
+
db,
|
|
3822
|
+
result.item.id,
|
|
3823
|
+
Number.parseInt(commentId, 10)
|
|
3824
|
+
);
|
|
3825
|
+
switch (outcome) {
|
|
3826
|
+
case "deleted":
|
|
3827
|
+
exportToJsonl(db, dir);
|
|
3828
|
+
console.log(
|
|
3829
|
+
chalk43.green(`Comment #${commentId} deleted from item #${id}.`)
|
|
3830
|
+
);
|
|
3831
|
+
break;
|
|
3832
|
+
case "not-found":
|
|
3833
|
+
console.log(chalk43.red(`Comment #${commentId} not found on item #${id}.`));
|
|
3834
|
+
process.exit(1);
|
|
3835
|
+
break;
|
|
3836
|
+
case "is-summary":
|
|
3837
|
+
console.log(
|
|
3838
|
+
chalk43.red(
|
|
3839
|
+
`Comment #${commentId} is a phase summary and cannot be deleted.`
|
|
3840
|
+
)
|
|
3841
|
+
);
|
|
3842
|
+
process.exit(1);
|
|
3843
|
+
break;
|
|
3844
|
+
}
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3771
3847
|
// src/commands/backlog/registerCommentCommands.ts
|
|
3772
3848
|
function registerCommentCommands(cmd) {
|
|
3773
3849
|
cmd.command("comment <id> <text>").description("Add a comment to a backlog item").action(comment);
|
|
3774
3850
|
cmd.command("comments <id>").description("List comments and summaries for a backlog item").action(comments);
|
|
3851
|
+
cmd.command("delete-comment <id> <comment-id>").description("Delete a comment from a backlog item").action(deleteCommentCmd);
|
|
3775
3852
|
}
|
|
3776
3853
|
|
|
3777
3854
|
// src/commands/backlog/add/index.ts
|
|
3778
|
-
import
|
|
3855
|
+
import chalk45 from "chalk";
|
|
3779
3856
|
|
|
3780
3857
|
// src/commands/backlog/commitBacklog.ts
|
|
3781
3858
|
import { execSync as execSync15 } from "child_process";
|
|
3782
3859
|
import { join as join15 } from "path";
|
|
3783
|
-
import
|
|
3860
|
+
import chalk44 from "chalk";
|
|
3784
3861
|
function commitBacklog(id, name) {
|
|
3785
3862
|
const config = loadConfig();
|
|
3786
3863
|
if (!config.backlog.autoCommit) {
|
|
3787
3864
|
console.log(
|
|
3788
|
-
|
|
3865
|
+
chalk44.yellow(
|
|
3789
3866
|
"Warning: auto-commit is disabled. Stage and commit the backlog file manually."
|
|
3790
3867
|
)
|
|
3791
3868
|
);
|
|
@@ -3797,13 +3874,13 @@ function commitBacklog(id, name) {
|
|
|
3797
3874
|
execSync15(`git add ${shellQuote(jsonlPath)}`, { stdio: "ignore" });
|
|
3798
3875
|
execSync15(`git commit -m ${shellQuote(message)}`, { stdio: "ignore" });
|
|
3799
3876
|
} catch {
|
|
3800
|
-
console.log(
|
|
3877
|
+
console.log(chalk44.yellow("Warning: could not auto-commit backlog file."));
|
|
3801
3878
|
}
|
|
3802
3879
|
}
|
|
3803
3880
|
|
|
3804
3881
|
// src/commands/backlog/add/shared.ts
|
|
3805
3882
|
import { spawnSync } from "child_process";
|
|
3806
|
-
import { mkdtempSync, readFileSync as
|
|
3883
|
+
import { mkdtempSync, readFileSync as readFileSync15, unlinkSync as unlinkSync4, writeFileSync as writeFileSync15 } from "fs";
|
|
3807
3884
|
import { tmpdir } from "os";
|
|
3808
3885
|
import { join as join16 } from "path";
|
|
3809
3886
|
import enquirer7 from "enquirer";
|
|
@@ -3853,7 +3930,7 @@ function openEditor() {
|
|
|
3853
3930
|
unlinkSync4(filePath);
|
|
3854
3931
|
return void 0;
|
|
3855
3932
|
}
|
|
3856
|
-
const content =
|
|
3933
|
+
const content = readFileSync15(filePath, "utf-8").trim();
|
|
3857
3934
|
unlinkSync4(filePath);
|
|
3858
3935
|
return content || void 0;
|
|
3859
3936
|
}
|
|
@@ -3889,12 +3966,12 @@ async function addFromOptions(options2) {
|
|
|
3889
3966
|
});
|
|
3890
3967
|
saveBacklog(items);
|
|
3891
3968
|
commitBacklog(id, name);
|
|
3892
|
-
console.log(
|
|
3969
|
+
console.log(chalk45.green(`Added item #${id}: ${name}`));
|
|
3893
3970
|
}
|
|
3894
3971
|
async function add(options2) {
|
|
3895
3972
|
if (!backlogExists()) {
|
|
3896
3973
|
console.log(
|
|
3897
|
-
|
|
3974
|
+
chalk45.yellow(
|
|
3898
3975
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3899
3976
|
)
|
|
3900
3977
|
);
|
|
@@ -3904,13 +3981,13 @@ async function add(options2) {
|
|
|
3904
3981
|
}
|
|
3905
3982
|
|
|
3906
3983
|
// src/commands/backlog/addPhase.ts
|
|
3907
|
-
import
|
|
3984
|
+
import chalk46 from "chalk";
|
|
3908
3985
|
function addPhase(id, name, options2) {
|
|
3909
3986
|
const result = loadAndFindItem(id);
|
|
3910
3987
|
if (!result) return;
|
|
3911
3988
|
const tasks = options2.task ?? [];
|
|
3912
3989
|
if (tasks.length === 0) {
|
|
3913
|
-
console.log(
|
|
3990
|
+
console.log(chalk46.red("At least one --task is required."));
|
|
3914
3991
|
process.exitCode = 1;
|
|
3915
3992
|
return;
|
|
3916
3993
|
}
|
|
@@ -3932,25 +4009,25 @@ function addPhase(id, name, options2) {
|
|
|
3932
4009
|
exportToJsonl(db, dir);
|
|
3933
4010
|
commitBacklog(itemId, result.item.name);
|
|
3934
4011
|
console.log(
|
|
3935
|
-
|
|
4012
|
+
chalk46.green(
|
|
3936
4013
|
`Added phase ${phaseIdx + 1} "${name}" to item #${itemId} with ${tasks.length} task(s).`
|
|
3937
4014
|
)
|
|
3938
4015
|
);
|
|
3939
4016
|
}
|
|
3940
4017
|
|
|
3941
4018
|
// src/commands/backlog/init/index.ts
|
|
3942
|
-
import
|
|
4019
|
+
import chalk47 from "chalk";
|
|
3943
4020
|
async function init6() {
|
|
3944
4021
|
if (backlogExists()) {
|
|
3945
|
-
console.log(
|
|
4022
|
+
console.log(chalk47.yellow("Backlog already exists."));
|
|
3946
4023
|
return;
|
|
3947
4024
|
}
|
|
3948
4025
|
saveBacklog([]);
|
|
3949
|
-
console.log(
|
|
4026
|
+
console.log(chalk47.green("Created backlog."));
|
|
3950
4027
|
}
|
|
3951
4028
|
|
|
3952
4029
|
// src/commands/backlog/list/index.ts
|
|
3953
|
-
import
|
|
4030
|
+
import chalk48 from "chalk";
|
|
3954
4031
|
function filterItems(items, options2) {
|
|
3955
4032
|
if (options2.status) return items.filter((i) => i.status === options2.status);
|
|
3956
4033
|
if (!options2.all)
|
|
@@ -3960,7 +4037,7 @@ function filterItems(items, options2) {
|
|
|
3960
4037
|
async function list2(options2) {
|
|
3961
4038
|
if (!backlogExists()) {
|
|
3962
4039
|
console.log(
|
|
3963
|
-
|
|
4040
|
+
chalk48.yellow(
|
|
3964
4041
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
3965
4042
|
)
|
|
3966
4043
|
);
|
|
@@ -3969,12 +4046,12 @@ async function list2(options2) {
|
|
|
3969
4046
|
const allItems = loadBacklog();
|
|
3970
4047
|
const items = filterItems(allItems, options2);
|
|
3971
4048
|
if (items.length === 0) {
|
|
3972
|
-
console.log(
|
|
4049
|
+
console.log(chalk48.dim("Backlog is empty."));
|
|
3973
4050
|
return;
|
|
3974
4051
|
}
|
|
3975
4052
|
for (const item of items) {
|
|
3976
4053
|
console.log(
|
|
3977
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4054
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk48.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
3978
4055
|
);
|
|
3979
4056
|
if (options2.verbose) {
|
|
3980
4057
|
printVerboseDetails(item);
|
|
@@ -3997,7 +4074,7 @@ function registerItemCommands(cmd) {
|
|
|
3997
4074
|
}
|
|
3998
4075
|
|
|
3999
4076
|
// src/commands/backlog/link.ts
|
|
4000
|
-
import
|
|
4077
|
+
import chalk50 from "chalk";
|
|
4001
4078
|
|
|
4002
4079
|
// src/commands/backlog/hasCycle.ts
|
|
4003
4080
|
function hasCycle(items, fromId, toId) {
|
|
@@ -4020,11 +4097,11 @@ function hasCycle(items, fromId, toId) {
|
|
|
4020
4097
|
}
|
|
4021
4098
|
|
|
4022
4099
|
// src/commands/backlog/validateLinkTarget.ts
|
|
4023
|
-
import
|
|
4100
|
+
import chalk49 from "chalk";
|
|
4024
4101
|
function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
4025
4102
|
const toItem = items.find((i) => i.id === toNum);
|
|
4026
4103
|
if (!toItem) {
|
|
4027
|
-
console.log(
|
|
4104
|
+
console.log(chalk49.red(`Item #${toId} not found.`));
|
|
4028
4105
|
return void 0;
|
|
4029
4106
|
}
|
|
4030
4107
|
if (!fromItem.links) fromItem.links = [];
|
|
@@ -4033,7 +4110,7 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4033
4110
|
);
|
|
4034
4111
|
if (duplicate) {
|
|
4035
4112
|
console.log(
|
|
4036
|
-
|
|
4113
|
+
chalk49.yellow(`Link already exists: #${fromId} ${linkType} #${toId}`)
|
|
4037
4114
|
);
|
|
4038
4115
|
return void 0;
|
|
4039
4116
|
}
|
|
@@ -4044,13 +4121,13 @@ function validateLinkTarget(items, fromItem, fromId, toId, toNum, linkType) {
|
|
|
4044
4121
|
function link(fromId, toId, opts) {
|
|
4045
4122
|
const linkType = opts.type ?? "relates-to";
|
|
4046
4123
|
if (linkType !== "relates-to" && linkType !== "depends-on") {
|
|
4047
|
-
console.log(
|
|
4124
|
+
console.log(chalk50.red(`Invalid link type: ${linkType}`));
|
|
4048
4125
|
return;
|
|
4049
4126
|
}
|
|
4050
4127
|
const fromNum = Number.parseInt(fromId, 10);
|
|
4051
4128
|
const toNum = Number.parseInt(toId, 10);
|
|
4052
4129
|
if (fromNum === toNum) {
|
|
4053
|
-
console.log(
|
|
4130
|
+
console.log(chalk50.red("Cannot link an item to itself."));
|
|
4054
4131
|
return;
|
|
4055
4132
|
}
|
|
4056
4133
|
const result = loadAndFindItem(fromId);
|
|
@@ -4067,7 +4144,7 @@ function link(fromId, toId, opts) {
|
|
|
4067
4144
|
if (!toItem) return;
|
|
4068
4145
|
if (linkType === "depends-on" && hasCycle(items, fromNum, toNum)) {
|
|
4069
4146
|
console.log(
|
|
4070
|
-
|
|
4147
|
+
chalk50.red(
|
|
4071
4148
|
`Cannot add dependency: #${fromId} \u2192 #${toId} would create a circular dependency.`
|
|
4072
4149
|
)
|
|
4073
4150
|
);
|
|
@@ -4077,32 +4154,32 @@ function link(fromId, toId, opts) {
|
|
|
4077
4154
|
fromItem.links.push({ type: linkType, targetId: toNum });
|
|
4078
4155
|
saveBacklog(items);
|
|
4079
4156
|
console.log(
|
|
4080
|
-
|
|
4157
|
+
chalk50.green(`Linked #${fromId} ${linkType} #${toId} (${toItem.name})`)
|
|
4081
4158
|
);
|
|
4082
4159
|
}
|
|
4083
4160
|
|
|
4084
4161
|
// src/commands/backlog/unlink.ts
|
|
4085
|
-
import
|
|
4162
|
+
import chalk51 from "chalk";
|
|
4086
4163
|
function unlink(fromId, toId) {
|
|
4087
4164
|
const toNum = Number.parseInt(toId, 10);
|
|
4088
4165
|
const result = loadAndFindItem(fromId);
|
|
4089
4166
|
if (!result) return;
|
|
4090
4167
|
const { items, item: fromItem } = result;
|
|
4091
4168
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
4092
|
-
console.log(
|
|
4169
|
+
console.log(chalk51.yellow(`No links found on item #${fromId}.`));
|
|
4093
4170
|
return;
|
|
4094
4171
|
}
|
|
4095
4172
|
const before = fromItem.links.length;
|
|
4096
4173
|
fromItem.links = fromItem.links.filter((l) => l.targetId !== toNum);
|
|
4097
4174
|
if (fromItem.links.length === before) {
|
|
4098
|
-
console.log(
|
|
4175
|
+
console.log(chalk51.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
4099
4176
|
return;
|
|
4100
4177
|
}
|
|
4101
4178
|
if (fromItem.links.length === 0) {
|
|
4102
4179
|
fromItem.links = void 0;
|
|
4103
4180
|
}
|
|
4104
4181
|
saveBacklog(items);
|
|
4105
|
-
console.log(
|
|
4182
|
+
console.log(chalk51.green(`Removed link from #${fromId} to #${toId}.`));
|
|
4106
4183
|
}
|
|
4107
4184
|
|
|
4108
4185
|
// src/commands/backlog/registerLinkCommands.ts
|
|
@@ -4123,11 +4200,11 @@ function registerRunCommand(cmd) {
|
|
|
4123
4200
|
}
|
|
4124
4201
|
|
|
4125
4202
|
// src/commands/backlog/search/index.ts
|
|
4126
|
-
import
|
|
4203
|
+
import chalk52 from "chalk";
|
|
4127
4204
|
async function search(query) {
|
|
4128
4205
|
if (!backlogExists()) {
|
|
4129
4206
|
console.log(
|
|
4130
|
-
|
|
4207
|
+
chalk52.yellow(
|
|
4131
4208
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
4132
4209
|
)
|
|
4133
4210
|
);
|
|
@@ -4135,18 +4212,18 @@ async function search(query) {
|
|
|
4135
4212
|
}
|
|
4136
4213
|
const items = searchBacklog(query);
|
|
4137
4214
|
if (items.length === 0) {
|
|
4138
|
-
console.log(
|
|
4215
|
+
console.log(chalk52.dim(`No items matching "${query}".`));
|
|
4139
4216
|
return;
|
|
4140
4217
|
}
|
|
4141
4218
|
console.log(
|
|
4142
|
-
|
|
4219
|
+
chalk52.dim(
|
|
4143
4220
|
`${items.length} item${items.length === 1 ? "" : "s"} matching "${query}":
|
|
4144
4221
|
`
|
|
4145
4222
|
)
|
|
4146
4223
|
);
|
|
4147
4224
|
for (const item of items) {
|
|
4148
4225
|
console.log(
|
|
4149
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
4226
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk52.dim(`#${item.id}`)} ${item.name}`
|
|
4150
4227
|
);
|
|
4151
4228
|
}
|
|
4152
4229
|
}
|
|
@@ -4157,16 +4234,16 @@ function registerSearchCommand(cmd) {
|
|
|
4157
4234
|
}
|
|
4158
4235
|
|
|
4159
4236
|
// src/commands/backlog/delete/index.ts
|
|
4160
|
-
import
|
|
4237
|
+
import chalk53 from "chalk";
|
|
4161
4238
|
async function del(id) {
|
|
4162
4239
|
const name = removeItem(id);
|
|
4163
4240
|
if (name) {
|
|
4164
|
-
console.log(
|
|
4241
|
+
console.log(chalk53.green(`Deleted item #${id}: ${name}`));
|
|
4165
4242
|
}
|
|
4166
4243
|
}
|
|
4167
4244
|
|
|
4168
4245
|
// src/commands/backlog/done/index.ts
|
|
4169
|
-
import
|
|
4246
|
+
import chalk54 from "chalk";
|
|
4170
4247
|
async function done(id, summary) {
|
|
4171
4248
|
const result = loadAndFindItem(id);
|
|
4172
4249
|
if (!result) return;
|
|
@@ -4176,12 +4253,12 @@ async function done(id, summary) {
|
|
|
4176
4253
|
const pending = item.plan.slice(completed);
|
|
4177
4254
|
if (pending.length > 0) {
|
|
4178
4255
|
console.log(
|
|
4179
|
-
|
|
4256
|
+
chalk54.red(
|
|
4180
4257
|
`Cannot complete item #${id}: ${pending.length} pending phase(s):`
|
|
4181
4258
|
)
|
|
4182
4259
|
);
|
|
4183
4260
|
for (const phase of pending) {
|
|
4184
|
-
console.log(
|
|
4261
|
+
console.log(chalk54.yellow(` - ${phase.name}`));
|
|
4185
4262
|
}
|
|
4186
4263
|
process.exitCode = 1;
|
|
4187
4264
|
return;
|
|
@@ -4193,20 +4270,20 @@ async function done(id, summary) {
|
|
|
4193
4270
|
addPhaseSummary(item, summary, phase);
|
|
4194
4271
|
}
|
|
4195
4272
|
saveBacklog(result.items);
|
|
4196
|
-
console.log(
|
|
4273
|
+
console.log(chalk54.green(`Completed item #${id}: ${item.name}`));
|
|
4197
4274
|
}
|
|
4198
4275
|
|
|
4199
4276
|
// src/commands/backlog/start/index.ts
|
|
4200
|
-
import
|
|
4277
|
+
import chalk55 from "chalk";
|
|
4201
4278
|
async function start(id) {
|
|
4202
4279
|
const name = setStatus(id, "in-progress");
|
|
4203
4280
|
if (name) {
|
|
4204
|
-
console.log(
|
|
4281
|
+
console.log(chalk55.green(`Started item #${id}: ${name}`));
|
|
4205
4282
|
}
|
|
4206
4283
|
}
|
|
4207
4284
|
|
|
4208
4285
|
// src/commands/backlog/wontdo/index.ts
|
|
4209
|
-
import
|
|
4286
|
+
import chalk56 from "chalk";
|
|
4210
4287
|
async function wontdo(id, reason) {
|
|
4211
4288
|
const result = loadAndFindItem(id);
|
|
4212
4289
|
if (!result) return;
|
|
@@ -4216,7 +4293,7 @@ async function wontdo(id, reason) {
|
|
|
4216
4293
|
addPhaseSummary(result.item, reason, phase);
|
|
4217
4294
|
}
|
|
4218
4295
|
saveBacklog(result.items);
|
|
4219
|
-
console.log(
|
|
4296
|
+
console.log(chalk56.red(`Won't do item #${id}: ${result.item.name}`));
|
|
4220
4297
|
}
|
|
4221
4298
|
|
|
4222
4299
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -4228,10 +4305,10 @@ function registerStatusCommands(cmd) {
|
|
|
4228
4305
|
}
|
|
4229
4306
|
|
|
4230
4307
|
// src/commands/backlog/removePhase.ts
|
|
4231
|
-
import
|
|
4308
|
+
import chalk58 from "chalk";
|
|
4232
4309
|
|
|
4233
4310
|
// src/commands/backlog/findPhase.ts
|
|
4234
|
-
import
|
|
4311
|
+
import chalk57 from "chalk";
|
|
4235
4312
|
function findPhase(id, phase) {
|
|
4236
4313
|
const result = loadAndFindItem(id);
|
|
4237
4314
|
if (!result) return void 0;
|
|
@@ -4243,7 +4320,7 @@ function findPhase(id, phase) {
|
|
|
4243
4320
|
"SELECT COUNT(*) as cnt FROM plan_phases WHERE item_id = ? AND idx = ?"
|
|
4244
4321
|
).get(itemId, phaseIdx);
|
|
4245
4322
|
if (existing.cnt === 0) {
|
|
4246
|
-
console.log(
|
|
4323
|
+
console.log(chalk57.red(`Phase ${phaseIdx} not found on item #${itemId}.`));
|
|
4247
4324
|
process.exitCode = 1;
|
|
4248
4325
|
return void 0;
|
|
4249
4326
|
}
|
|
@@ -4299,23 +4376,23 @@ function removePhase(id, phase) {
|
|
|
4299
4376
|
run4();
|
|
4300
4377
|
exportToJsonl(db, dir);
|
|
4301
4378
|
commitBacklog(itemId, result.item.name);
|
|
4302
|
-
console.log(
|
|
4379
|
+
console.log(chalk58.green(`Removed phase ${phaseIdx} from item #${itemId}.`));
|
|
4303
4380
|
}
|
|
4304
4381
|
|
|
4305
4382
|
// src/commands/backlog/update/index.ts
|
|
4306
|
-
import
|
|
4383
|
+
import chalk60 from "chalk";
|
|
4307
4384
|
|
|
4308
4385
|
// src/commands/backlog/update/buildUpdateSql.ts
|
|
4309
|
-
import
|
|
4386
|
+
import chalk59 from "chalk";
|
|
4310
4387
|
function buildUpdateSql(options2) {
|
|
4311
4388
|
const { name, desc, type, ac } = options2;
|
|
4312
4389
|
if (!name && !desc && !type && !ac) {
|
|
4313
|
-
console.log(
|
|
4390
|
+
console.log(chalk59.red("Nothing to update. Provide at least one flag."));
|
|
4314
4391
|
process.exitCode = 1;
|
|
4315
4392
|
return void 0;
|
|
4316
4393
|
}
|
|
4317
4394
|
if (type && type !== "story" && type !== "bug") {
|
|
4318
|
-
console.log(
|
|
4395
|
+
console.log(chalk59.red('Invalid type. Must be "story" or "bug".'));
|
|
4319
4396
|
process.exitCode = 1;
|
|
4320
4397
|
return void 0;
|
|
4321
4398
|
}
|
|
@@ -4360,11 +4437,11 @@ function update(id, options2) {
|
|
|
4360
4437
|
);
|
|
4361
4438
|
exportToJsonl(db, dir);
|
|
4362
4439
|
commitBacklog(itemId, options2.name ?? result.item.name);
|
|
4363
|
-
console.log(
|
|
4440
|
+
console.log(chalk60.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
4364
4441
|
}
|
|
4365
4442
|
|
|
4366
4443
|
// src/commands/backlog/updatePhase.ts
|
|
4367
|
-
import
|
|
4444
|
+
import chalk61 from "chalk";
|
|
4368
4445
|
|
|
4369
4446
|
// src/commands/backlog/applyPhaseUpdate.ts
|
|
4370
4447
|
function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
@@ -4398,7 +4475,7 @@ function applyPhaseUpdate(db, itemId, phaseIdx, fields) {
|
|
|
4398
4475
|
function updatePhase(id, phase, options2) {
|
|
4399
4476
|
const { name, task, manualCheck } = options2;
|
|
4400
4477
|
if (!name && !task && !manualCheck) {
|
|
4401
|
-
console.log(
|
|
4478
|
+
console.log(chalk61.red("Nothing to update. Provide at least one flag."));
|
|
4402
4479
|
process.exitCode = 1;
|
|
4403
4480
|
return;
|
|
4404
4481
|
}
|
|
@@ -4414,7 +4491,7 @@ function updatePhase(id, phase, options2) {
|
|
|
4414
4491
|
manualCheck && "manual checks"
|
|
4415
4492
|
].filter(Boolean).join(", ");
|
|
4416
4493
|
console.log(
|
|
4417
|
-
|
|
4494
|
+
chalk61.green(`Updated ${fields} on phase ${phaseIdx} of item #${itemId}.`)
|
|
4418
4495
|
);
|
|
4419
4496
|
}
|
|
4420
4497
|
|
|
@@ -4540,7 +4617,7 @@ function extractGraphqlQuery(args) {
|
|
|
4540
4617
|
}
|
|
4541
4618
|
|
|
4542
4619
|
// src/shared/loadCliReads.ts
|
|
4543
|
-
import { existsSync as existsSync19, readFileSync as
|
|
4620
|
+
import { existsSync as existsSync19, readFileSync as readFileSync16, writeFileSync as writeFileSync16 } from "fs";
|
|
4544
4621
|
import { dirname as dirname14, resolve as resolve2 } from "path";
|
|
4545
4622
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
4546
4623
|
var __filename2 = fileURLToPath4(import.meta.url);
|
|
@@ -4550,7 +4627,7 @@ function packageRoot() {
|
|
|
4550
4627
|
}
|
|
4551
4628
|
function readLines(path50) {
|
|
4552
4629
|
if (!existsSync19(path50)) return [];
|
|
4553
|
-
return
|
|
4630
|
+
return readFileSync16(path50, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
4554
4631
|
}
|
|
4555
4632
|
var cachedReads;
|
|
4556
4633
|
var cachedWrites;
|
|
@@ -4596,7 +4673,7 @@ function findCliWrite(command) {
|
|
|
4596
4673
|
}
|
|
4597
4674
|
|
|
4598
4675
|
// src/shared/readSettingsPerms.ts
|
|
4599
|
-
import { existsSync as existsSync20, readFileSync as
|
|
4676
|
+
import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
|
|
4600
4677
|
import { homedir as homedir3 } from "os";
|
|
4601
4678
|
import { join as join17 } from "path";
|
|
4602
4679
|
function readSettingsPerms(key) {
|
|
@@ -4614,7 +4691,7 @@ function readSettingsPerms(key) {
|
|
|
4614
4691
|
function readPermissionArray(filePath, key) {
|
|
4615
4692
|
if (!existsSync20(filePath)) return [];
|
|
4616
4693
|
try {
|
|
4617
|
-
const data = JSON.parse(
|
|
4694
|
+
const data = JSON.parse(readFileSync17(filePath, "utf-8"));
|
|
4618
4695
|
const arr = data?.permissions?.[key];
|
|
4619
4696
|
return Array.isArray(arr) ? arr.filter((e) => typeof e === "string") : [];
|
|
4620
4697
|
} catch {
|
|
@@ -4864,53 +4941,8 @@ function cliHookCheck(command, toolName = "Bash") {
|
|
|
4864
4941
|
${reasons.join("\n")}`);
|
|
4865
4942
|
}
|
|
4866
4943
|
|
|
4867
|
-
// src/commands/deny/denyAdd.ts
|
|
4868
|
-
import chalk61 from "chalk";
|
|
4869
|
-
function denyAdd(pattern2, message) {
|
|
4870
|
-
const config = loadProjectConfig();
|
|
4871
|
-
const deny = config.deny ?? [];
|
|
4872
|
-
if (deny.some((r) => r.pattern === pattern2)) {
|
|
4873
|
-
console.log(chalk61.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
4874
|
-
return;
|
|
4875
|
-
}
|
|
4876
|
-
deny.push({ pattern: pattern2, message });
|
|
4877
|
-
config.deny = deny;
|
|
4878
|
-
saveConfig(config);
|
|
4879
|
-
console.log(chalk61.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
4880
|
-
}
|
|
4881
|
-
|
|
4882
|
-
// src/commands/deny/denyList.ts
|
|
4883
|
-
import chalk62 from "chalk";
|
|
4884
|
-
function denyList() {
|
|
4885
|
-
const config = loadConfig();
|
|
4886
|
-
const deny = config.deny;
|
|
4887
|
-
if (!deny || deny.length === 0) {
|
|
4888
|
-
console.log(chalk62.dim("No deny rules configured."));
|
|
4889
|
-
return;
|
|
4890
|
-
}
|
|
4891
|
-
for (const rule of deny) {
|
|
4892
|
-
console.log(`${chalk62.red(rule.pattern)} \u2192 ${rule.message}`);
|
|
4893
|
-
}
|
|
4894
|
-
}
|
|
4895
|
-
|
|
4896
|
-
// src/commands/deny/denyRemove.ts
|
|
4897
|
-
import chalk63 from "chalk";
|
|
4898
|
-
function denyRemove(pattern2) {
|
|
4899
|
-
const config = loadProjectConfig();
|
|
4900
|
-
const deny = config.deny ?? [];
|
|
4901
|
-
const index = deny.findIndex((r) => r.pattern === pattern2);
|
|
4902
|
-
if (index === -1) {
|
|
4903
|
-
console.log(chalk63.yellow(`No deny rule found for: ${pattern2}`));
|
|
4904
|
-
return;
|
|
4905
|
-
}
|
|
4906
|
-
deny.splice(index, 1);
|
|
4907
|
-
config.deny = deny.length > 0 ? deny : void 0;
|
|
4908
|
-
saveConfig(config);
|
|
4909
|
-
console.log(chalk63.green(`Removed deny rule: ${pattern2}`));
|
|
4910
|
-
}
|
|
4911
|
-
|
|
4912
4944
|
// src/commands/permitCliReads/index.ts
|
|
4913
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync5, readFileSync as
|
|
4945
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync5, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
|
|
4914
4946
|
import { homedir as homedir4 } from "os";
|
|
4915
4947
|
import { join as join18 } from "path";
|
|
4916
4948
|
|
|
@@ -4956,11 +4988,11 @@ function assertCliExists(cli) {
|
|
|
4956
4988
|
}
|
|
4957
4989
|
|
|
4958
4990
|
// src/commands/permitCliReads/colorize.ts
|
|
4959
|
-
import
|
|
4991
|
+
import chalk62 from "chalk";
|
|
4960
4992
|
function colorize(plainOutput) {
|
|
4961
4993
|
return plainOutput.split("\n").map((line) => {
|
|
4962
|
-
if (line.startsWith(" R ")) return
|
|
4963
|
-
if (line.startsWith(" W ")) return
|
|
4994
|
+
if (line.startsWith(" R ")) return chalk62.green(line);
|
|
4995
|
+
if (line.startsWith(" W ")) return chalk62.red(line);
|
|
4964
4996
|
return line;
|
|
4965
4997
|
}).join("\n");
|
|
4966
4998
|
}
|
|
@@ -5042,12 +5074,12 @@ function hasSubcommands(helpText) {
|
|
|
5042
5074
|
// src/commands/permitCliReads/runHelp.ts
|
|
5043
5075
|
import { exec as exec2 } from "child_process";
|
|
5044
5076
|
function runHelp(args) {
|
|
5045
|
-
return new Promise((
|
|
5077
|
+
return new Promise((resolve8) => {
|
|
5046
5078
|
exec2(
|
|
5047
5079
|
`${args.join(" ")} --help`,
|
|
5048
5080
|
{ encoding: "utf-8", timeout: 3e4 },
|
|
5049
5081
|
(_err, stdout, stderr) => {
|
|
5050
|
-
|
|
5082
|
+
resolve8(stdout || stderr || "");
|
|
5051
5083
|
}
|
|
5052
5084
|
);
|
|
5053
5085
|
});
|
|
@@ -5219,7 +5251,7 @@ function logPath(cli) {
|
|
|
5219
5251
|
function readCache(cli) {
|
|
5220
5252
|
const path50 = logPath(cli);
|
|
5221
5253
|
if (!existsSync21(path50)) return void 0;
|
|
5222
|
-
return
|
|
5254
|
+
return readFileSync18(path50, "utf-8");
|
|
5223
5255
|
}
|
|
5224
5256
|
function writeCache(cli, output) {
|
|
5225
5257
|
const dir = join18(homedir4(), ".assist");
|
|
@@ -5257,6 +5289,59 @@ async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
|
5257
5289
|
updateSettings(binary, commands);
|
|
5258
5290
|
}
|
|
5259
5291
|
|
|
5292
|
+
// src/commands/deny/denyAdd.ts
|
|
5293
|
+
import chalk63 from "chalk";
|
|
5294
|
+
function denyAdd(pattern2, message) {
|
|
5295
|
+
const config = loadProjectConfig();
|
|
5296
|
+
const deny = config.deny ?? [];
|
|
5297
|
+
if (deny.some((r) => r.pattern === pattern2)) {
|
|
5298
|
+
console.log(chalk63.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
5299
|
+
return;
|
|
5300
|
+
}
|
|
5301
|
+
deny.push({ pattern: pattern2, message });
|
|
5302
|
+
config.deny = deny;
|
|
5303
|
+
saveConfig(config);
|
|
5304
|
+
console.log(chalk63.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
5305
|
+
}
|
|
5306
|
+
|
|
5307
|
+
// src/commands/deny/denyList.ts
|
|
5308
|
+
import chalk64 from "chalk";
|
|
5309
|
+
function denyList() {
|
|
5310
|
+
const config = loadConfig();
|
|
5311
|
+
const deny = config.deny;
|
|
5312
|
+
if (!deny || deny.length === 0) {
|
|
5313
|
+
console.log(chalk64.dim("No deny rules configured."));
|
|
5314
|
+
return;
|
|
5315
|
+
}
|
|
5316
|
+
for (const rule of deny) {
|
|
5317
|
+
console.log(`${chalk64.red(rule.pattern)} \u2192 ${rule.message}`);
|
|
5318
|
+
}
|
|
5319
|
+
}
|
|
5320
|
+
|
|
5321
|
+
// src/commands/deny/denyRemove.ts
|
|
5322
|
+
import chalk65 from "chalk";
|
|
5323
|
+
function denyRemove(pattern2) {
|
|
5324
|
+
const config = loadProjectConfig();
|
|
5325
|
+
const deny = config.deny ?? [];
|
|
5326
|
+
const index = deny.findIndex((r) => r.pattern === pattern2);
|
|
5327
|
+
if (index === -1) {
|
|
5328
|
+
console.log(chalk65.yellow(`No deny rule found for: ${pattern2}`));
|
|
5329
|
+
return;
|
|
5330
|
+
}
|
|
5331
|
+
deny.splice(index, 1);
|
|
5332
|
+
config.deny = deny.length > 0 ? deny : void 0;
|
|
5333
|
+
saveConfig(config);
|
|
5334
|
+
console.log(chalk65.green(`Removed deny rule: ${pattern2}`));
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
// src/commands/registerDeny.ts
|
|
5338
|
+
function registerDeny(parent) {
|
|
5339
|
+
const denyCommand = parent.command("deny").description("Manage command deny rules").action(denyList);
|
|
5340
|
+
denyCommand.command("add").description("Add a deny rule for a command pattern").argument("<pattern>", "Command prefix to deny").argument("<message>", "Correction message shown to the agent").action(denyAdd);
|
|
5341
|
+
denyCommand.command("remove").description("Remove a deny rule by pattern").argument("<pattern>", "Command prefix to remove").action(denyRemove);
|
|
5342
|
+
denyCommand.command("list").description("List all deny rules").action(denyList);
|
|
5343
|
+
}
|
|
5344
|
+
|
|
5260
5345
|
// src/commands/registerCliHook.ts
|
|
5261
5346
|
function registerCliHook(program2) {
|
|
5262
5347
|
const cmd = program2.command("cli-hook").description("PreToolUse hook for auto-approving read-only CLI commands").action(() => {
|
|
@@ -5271,22 +5356,19 @@ function registerCliHook(program2) {
|
|
|
5271
5356
|
).option("--no-cache", "Force fresh discovery, ignoring cached results").action((cli, options2) => {
|
|
5272
5357
|
permitCliReads(cli.join(" "), { noCache: !options2.cache });
|
|
5273
5358
|
});
|
|
5274
|
-
|
|
5275
|
-
denyCommand.command("add").description("Add a deny rule for a command pattern").argument("<pattern>", "Command prefix to deny").argument("<message>", "Correction message shown to the agent").action(denyAdd);
|
|
5276
|
-
denyCommand.command("remove").description("Remove a deny rule by pattern").argument("<pattern>", "Command prefix to remove").action(denyRemove);
|
|
5277
|
-
denyCommand.command("list").description("List all deny rules").action(denyList);
|
|
5359
|
+
registerDeny(cmd);
|
|
5278
5360
|
}
|
|
5279
5361
|
|
|
5280
5362
|
// src/commands/complexity/analyze.ts
|
|
5281
|
-
import
|
|
5363
|
+
import chalk71 from "chalk";
|
|
5282
5364
|
|
|
5283
5365
|
// src/commands/complexity/cyclomatic.ts
|
|
5284
|
-
import
|
|
5366
|
+
import chalk67 from "chalk";
|
|
5285
5367
|
|
|
5286
5368
|
// src/commands/complexity/shared/index.ts
|
|
5287
5369
|
import fs12 from "fs";
|
|
5288
5370
|
import path20 from "path";
|
|
5289
|
-
import
|
|
5371
|
+
import chalk66 from "chalk";
|
|
5290
5372
|
import ts5 from "typescript";
|
|
5291
5373
|
|
|
5292
5374
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -5532,7 +5614,7 @@ function createSourceFromFile(filePath) {
|
|
|
5532
5614
|
function withSourceFiles(pattern2, callback) {
|
|
5533
5615
|
const files = findSourceFiles2(pattern2);
|
|
5534
5616
|
if (files.length === 0) {
|
|
5535
|
-
console.log(
|
|
5617
|
+
console.log(chalk66.yellow("No files found matching pattern"));
|
|
5536
5618
|
return void 0;
|
|
5537
5619
|
}
|
|
5538
5620
|
return callback(files);
|
|
@@ -5565,11 +5647,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5565
5647
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
5566
5648
|
for (const { file, name, complexity } of results) {
|
|
5567
5649
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
5568
|
-
const color = exceedsThreshold ?
|
|
5569
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
5650
|
+
const color = exceedsThreshold ? chalk67.red : chalk67.white;
|
|
5651
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk67.cyan(complexity)}`);
|
|
5570
5652
|
}
|
|
5571
5653
|
console.log(
|
|
5572
|
-
|
|
5654
|
+
chalk67.dim(
|
|
5573
5655
|
`
|
|
5574
5656
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5575
5657
|
)
|
|
@@ -5581,7 +5663,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5581
5663
|
}
|
|
5582
5664
|
|
|
5583
5665
|
// src/commands/complexity/halstead.ts
|
|
5584
|
-
import
|
|
5666
|
+
import chalk68 from "chalk";
|
|
5585
5667
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
5586
5668
|
withSourceFiles(pattern2, (files) => {
|
|
5587
5669
|
const results = [];
|
|
@@ -5596,13 +5678,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5596
5678
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
5597
5679
|
for (const { file, name, metrics } of results) {
|
|
5598
5680
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
5599
|
-
const color = exceedsThreshold ?
|
|
5681
|
+
const color = exceedsThreshold ? chalk68.red : chalk68.white;
|
|
5600
5682
|
console.log(
|
|
5601
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
5683
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk68.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk68.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk68.magenta(metrics.effort.toFixed(1))}`
|
|
5602
5684
|
);
|
|
5603
5685
|
}
|
|
5604
5686
|
console.log(
|
|
5605
|
-
|
|
5687
|
+
chalk68.dim(
|
|
5606
5688
|
`
|
|
5607
5689
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
5608
5690
|
)
|
|
@@ -5617,28 +5699,28 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
5617
5699
|
import fs13 from "fs";
|
|
5618
5700
|
|
|
5619
5701
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
5620
|
-
import
|
|
5702
|
+
import chalk69 from "chalk";
|
|
5621
5703
|
function displayMaintainabilityResults(results, threshold) {
|
|
5622
5704
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
5623
5705
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
5624
|
-
console.log(
|
|
5706
|
+
console.log(chalk69.green("All files pass maintainability threshold"));
|
|
5625
5707
|
} else {
|
|
5626
5708
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
5627
|
-
const color = threshold !== void 0 ?
|
|
5709
|
+
const color = threshold !== void 0 ? chalk69.red : chalk69.white;
|
|
5628
5710
|
console.log(
|
|
5629
|
-
`${color(file)} \u2192 avg: ${
|
|
5711
|
+
`${color(file)} \u2192 avg: ${chalk69.cyan(avgMaintainability.toFixed(1))}, min: ${chalk69.yellow(minMaintainability.toFixed(1))}`
|
|
5630
5712
|
);
|
|
5631
5713
|
}
|
|
5632
5714
|
}
|
|
5633
|
-
console.log(
|
|
5715
|
+
console.log(chalk69.dim(`
|
|
5634
5716
|
Analyzed ${results.length} files`));
|
|
5635
5717
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
5636
5718
|
console.error(
|
|
5637
|
-
|
|
5719
|
+
chalk69.red(
|
|
5638
5720
|
`
|
|
5639
5721
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
5640
5722
|
|
|
5641
|
-
\u26A0\uFE0F ${
|
|
5723
|
+
\u26A0\uFE0F ${chalk69.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.`
|
|
5642
5724
|
)
|
|
5643
5725
|
);
|
|
5644
5726
|
process.exit(1);
|
|
@@ -5695,7 +5777,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5695
5777
|
|
|
5696
5778
|
// src/commands/complexity/sloc.ts
|
|
5697
5779
|
import fs14 from "fs";
|
|
5698
|
-
import
|
|
5780
|
+
import chalk70 from "chalk";
|
|
5699
5781
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
5700
5782
|
withSourceFiles(pattern2, (files) => {
|
|
5701
5783
|
const results = [];
|
|
@@ -5711,12 +5793,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
5711
5793
|
results.sort((a, b) => b.lines - a.lines);
|
|
5712
5794
|
for (const { file, lines } of results) {
|
|
5713
5795
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
5714
|
-
const color = exceedsThreshold ?
|
|
5715
|
-
console.log(`${color(file)} \u2192 ${
|
|
5796
|
+
const color = exceedsThreshold ? chalk70.red : chalk70.white;
|
|
5797
|
+
console.log(`${color(file)} \u2192 ${chalk70.cyan(lines)} lines`);
|
|
5716
5798
|
}
|
|
5717
5799
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
5718
5800
|
console.log(
|
|
5719
|
-
|
|
5801
|
+
chalk70.dim(`
|
|
5720
5802
|
Total: ${total} lines across ${files.length} files`)
|
|
5721
5803
|
);
|
|
5722
5804
|
if (hasViolation) {
|
|
@@ -5730,21 +5812,21 @@ async function analyze(pattern2) {
|
|
|
5730
5812
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
5731
5813
|
const files = findSourceFiles2(searchPattern);
|
|
5732
5814
|
if (files.length === 0) {
|
|
5733
|
-
console.log(
|
|
5815
|
+
console.log(chalk71.yellow("No files found matching pattern"));
|
|
5734
5816
|
return;
|
|
5735
5817
|
}
|
|
5736
5818
|
if (files.length === 1) {
|
|
5737
5819
|
const file = files[0];
|
|
5738
|
-
console.log(
|
|
5820
|
+
console.log(chalk71.bold.underline("SLOC"));
|
|
5739
5821
|
await sloc(file);
|
|
5740
5822
|
console.log();
|
|
5741
|
-
console.log(
|
|
5823
|
+
console.log(chalk71.bold.underline("Cyclomatic Complexity"));
|
|
5742
5824
|
await cyclomatic(file);
|
|
5743
5825
|
console.log();
|
|
5744
|
-
console.log(
|
|
5826
|
+
console.log(chalk71.bold.underline("Halstead Metrics"));
|
|
5745
5827
|
await halstead(file);
|
|
5746
5828
|
console.log();
|
|
5747
|
-
console.log(
|
|
5829
|
+
console.log(chalk71.bold.underline("Maintainability Index"));
|
|
5748
5830
|
await maintainability(file);
|
|
5749
5831
|
return;
|
|
5750
5832
|
}
|
|
@@ -5771,7 +5853,7 @@ function registerComplexity(program2) {
|
|
|
5771
5853
|
}
|
|
5772
5854
|
|
|
5773
5855
|
// src/commands/config/index.ts
|
|
5774
|
-
import
|
|
5856
|
+
import chalk72 from "chalk";
|
|
5775
5857
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
5776
5858
|
|
|
5777
5859
|
// src/commands/config/setNestedValue.ts
|
|
@@ -5834,7 +5916,7 @@ function formatIssuePath(issue, key) {
|
|
|
5834
5916
|
function printValidationErrors(issues, key) {
|
|
5835
5917
|
for (const issue of issues) {
|
|
5836
5918
|
console.error(
|
|
5837
|
-
|
|
5919
|
+
chalk72.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
5838
5920
|
);
|
|
5839
5921
|
}
|
|
5840
5922
|
}
|
|
@@ -5851,7 +5933,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
5851
5933
|
function assertNotGlobalOnly(key, global) {
|
|
5852
5934
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
5853
5935
|
console.error(
|
|
5854
|
-
|
|
5936
|
+
chalk72.red(
|
|
5855
5937
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
5856
5938
|
)
|
|
5857
5939
|
);
|
|
@@ -5874,7 +5956,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
5874
5956
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
5875
5957
|
const target = options2.global ? "global" : "project";
|
|
5876
5958
|
console.log(
|
|
5877
|
-
|
|
5959
|
+
chalk72.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
5878
5960
|
);
|
|
5879
5961
|
}
|
|
5880
5962
|
function configList() {
|
|
@@ -5883,7 +5965,7 @@ function configList() {
|
|
|
5883
5965
|
}
|
|
5884
5966
|
|
|
5885
5967
|
// src/commands/config/configGet.ts
|
|
5886
|
-
import
|
|
5968
|
+
import chalk73 from "chalk";
|
|
5887
5969
|
|
|
5888
5970
|
// src/commands/config/getNestedValue.ts
|
|
5889
5971
|
function isTraversable(value) {
|
|
@@ -5915,7 +5997,7 @@ function requireNestedValue(config, key) {
|
|
|
5915
5997
|
return value;
|
|
5916
5998
|
}
|
|
5917
5999
|
function exitKeyNotSet(key) {
|
|
5918
|
-
console.error(
|
|
6000
|
+
console.error(chalk73.red(`Key "${key}" is not set`));
|
|
5919
6001
|
process.exit(1);
|
|
5920
6002
|
}
|
|
5921
6003
|
|
|
@@ -5928,8 +6010,8 @@ function registerConfig(program2) {
|
|
|
5928
6010
|
}
|
|
5929
6011
|
|
|
5930
6012
|
// src/commands/deploy/redirect.ts
|
|
5931
|
-
import { existsSync as existsSync22, readFileSync as
|
|
5932
|
-
import
|
|
6013
|
+
import { existsSync as existsSync22, readFileSync as readFileSync19, writeFileSync as writeFileSync18 } from "fs";
|
|
6014
|
+
import chalk74 from "chalk";
|
|
5933
6015
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
5934
6016
|
if (!window.location.pathname.endsWith('/')) {
|
|
5935
6017
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -5938,22 +6020,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
5938
6020
|
function redirect() {
|
|
5939
6021
|
const indexPath = "index.html";
|
|
5940
6022
|
if (!existsSync22(indexPath)) {
|
|
5941
|
-
console.log(
|
|
6023
|
+
console.log(chalk74.yellow("No index.html found"));
|
|
5942
6024
|
return;
|
|
5943
6025
|
}
|
|
5944
|
-
const content =
|
|
6026
|
+
const content = readFileSync19(indexPath, "utf-8");
|
|
5945
6027
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
5946
|
-
console.log(
|
|
6028
|
+
console.log(chalk74.dim("Trailing slash script already present"));
|
|
5947
6029
|
return;
|
|
5948
6030
|
}
|
|
5949
6031
|
const headCloseIndex = content.indexOf("</head>");
|
|
5950
6032
|
if (headCloseIndex === -1) {
|
|
5951
|
-
console.log(
|
|
6033
|
+
console.log(chalk74.red("Could not find </head> tag in index.html"));
|
|
5952
6034
|
return;
|
|
5953
6035
|
}
|
|
5954
6036
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
5955
6037
|
writeFileSync18(indexPath, newContent);
|
|
5956
|
-
console.log(
|
|
6038
|
+
console.log(chalk74.green("Added trailing slash redirect to index.html"));
|
|
5957
6039
|
}
|
|
5958
6040
|
|
|
5959
6041
|
// src/commands/registerDeploy.ts
|
|
@@ -5980,12 +6062,34 @@ function loadBlogSkipDays(repoName) {
|
|
|
5980
6062
|
|
|
5981
6063
|
// src/commands/devlog/shared.ts
|
|
5982
6064
|
import { execSync as execSync18 } from "child_process";
|
|
5983
|
-
import
|
|
6065
|
+
import chalk75 from "chalk";
|
|
6066
|
+
|
|
6067
|
+
// src/shared/getRepoName.ts
|
|
6068
|
+
import { existsSync as existsSync23, readFileSync as readFileSync20 } from "fs";
|
|
6069
|
+
import { basename as basename2, join as join20 } from "path";
|
|
6070
|
+
function getRepoName() {
|
|
6071
|
+
const config = loadConfig();
|
|
6072
|
+
if (config.devlog?.name) {
|
|
6073
|
+
return config.devlog.name;
|
|
6074
|
+
}
|
|
6075
|
+
const packageJsonPath = join20(process.cwd(), "package.json");
|
|
6076
|
+
if (existsSync23(packageJsonPath)) {
|
|
6077
|
+
try {
|
|
6078
|
+
const content = readFileSync20(packageJsonPath, "utf-8");
|
|
6079
|
+
const pkg = JSON.parse(content);
|
|
6080
|
+
if (pkg.name) {
|
|
6081
|
+
return pkg.name;
|
|
6082
|
+
}
|
|
6083
|
+
} catch {
|
|
6084
|
+
}
|
|
6085
|
+
}
|
|
6086
|
+
return basename2(process.cwd());
|
|
6087
|
+
}
|
|
5984
6088
|
|
|
5985
6089
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
5986
6090
|
import { readdirSync, readFileSync as readFileSync21 } from "fs";
|
|
5987
|
-
import { join as
|
|
5988
|
-
var DEVLOG_DIR =
|
|
6091
|
+
import { join as join21 } from "path";
|
|
6092
|
+
var DEVLOG_DIR = join21(BLOG_REPO_ROOT, "src/content/devlog");
|
|
5989
6093
|
function extractFrontmatter(content) {
|
|
5990
6094
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
5991
6095
|
return fm?.[1] ?? null;
|
|
@@ -6013,7 +6117,7 @@ function readDevlogFiles(callback) {
|
|
|
6013
6117
|
try {
|
|
6014
6118
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
6015
6119
|
for (const file of files) {
|
|
6016
|
-
const content = readFileSync21(
|
|
6120
|
+
const content = readFileSync21(join21(DEVLOG_DIR, file), "utf-8");
|
|
6017
6121
|
const parsed = parseFrontmatter(content, file);
|
|
6018
6122
|
if (parsed) callback(parsed);
|
|
6019
6123
|
}
|
|
@@ -6067,13 +6171,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
6067
6171
|
}
|
|
6068
6172
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
6069
6173
|
for (const commit2 of commits) {
|
|
6070
|
-
console.log(` ${
|
|
6174
|
+
console.log(` ${chalk75.yellow(commit2.hash)} ${commit2.message}`);
|
|
6071
6175
|
if (verbose) {
|
|
6072
6176
|
const visibleFiles = commit2.files.filter(
|
|
6073
6177
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
6074
6178
|
);
|
|
6075
6179
|
for (const file of visibleFiles) {
|
|
6076
|
-
console.log(` ${
|
|
6180
|
+
console.log(` ${chalk75.dim(file)}`);
|
|
6077
6181
|
}
|
|
6078
6182
|
}
|
|
6079
6183
|
}
|
|
@@ -6098,15 +6202,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
6098
6202
|
}
|
|
6099
6203
|
|
|
6100
6204
|
// src/commands/devlog/list/printDateHeader.ts
|
|
6101
|
-
import
|
|
6205
|
+
import chalk76 from "chalk";
|
|
6102
6206
|
function printDateHeader(date, isSkipped, entries) {
|
|
6103
6207
|
if (isSkipped) {
|
|
6104
|
-
console.log(`${
|
|
6208
|
+
console.log(`${chalk76.bold.blue(date)} ${chalk76.dim("skipped")}`);
|
|
6105
6209
|
} else if (entries && entries.length > 0) {
|
|
6106
|
-
const entryInfo = entries.map((e) => `${
|
|
6107
|
-
console.log(`${
|
|
6210
|
+
const entryInfo = entries.map((e) => `${chalk76.green(e.version)} ${e.title}`).join(" | ");
|
|
6211
|
+
console.log(`${chalk76.bold.blue(date)} ${entryInfo}`);
|
|
6108
6212
|
} else {
|
|
6109
|
-
console.log(`${
|
|
6213
|
+
console.log(`${chalk76.bold.blue(date)} ${chalk76.red("\u26A0 devlog missing")}`);
|
|
6110
6214
|
}
|
|
6111
6215
|
}
|
|
6112
6216
|
|
|
@@ -6210,24 +6314,24 @@ function bumpVersion(version2, type) {
|
|
|
6210
6314
|
|
|
6211
6315
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
6212
6316
|
import { execSync as execSync21 } from "child_process";
|
|
6213
|
-
import
|
|
6317
|
+
import chalk78 from "chalk";
|
|
6214
6318
|
|
|
6215
6319
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
6216
|
-
import
|
|
6320
|
+
import chalk77 from "chalk";
|
|
6217
6321
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
6218
6322
|
if (conventional && firstHash) {
|
|
6219
6323
|
const version2 = getVersionAtCommit(firstHash);
|
|
6220
6324
|
if (version2) {
|
|
6221
|
-
console.log(`${
|
|
6325
|
+
console.log(`${chalk77.bold("version:")} ${stripToMinor(version2)}`);
|
|
6222
6326
|
} else {
|
|
6223
|
-
console.log(`${
|
|
6327
|
+
console.log(`${chalk77.bold("version:")} ${chalk77.red("unknown")}`);
|
|
6224
6328
|
}
|
|
6225
6329
|
} else if (patchVersion && minorVersion) {
|
|
6226
6330
|
console.log(
|
|
6227
|
-
`${
|
|
6331
|
+
`${chalk77.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
6228
6332
|
);
|
|
6229
6333
|
} else {
|
|
6230
|
-
console.log(`${
|
|
6334
|
+
console.log(`${chalk77.bold("version:")} v0.1 (initial)`);
|
|
6231
6335
|
}
|
|
6232
6336
|
}
|
|
6233
6337
|
|
|
@@ -6274,16 +6378,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
6274
6378
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
6275
6379
|
}
|
|
6276
6380
|
function logName(repoName) {
|
|
6277
|
-
console.log(`${
|
|
6381
|
+
console.log(`${chalk78.bold("name:")} ${repoName}`);
|
|
6278
6382
|
}
|
|
6279
6383
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
6280
6384
|
logName(ctx.repoName);
|
|
6281
6385
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
6282
|
-
console.log(
|
|
6386
|
+
console.log(chalk78.bold.blue(targetDate));
|
|
6283
6387
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
6284
6388
|
}
|
|
6285
6389
|
function logNoCommits(lastInfo) {
|
|
6286
|
-
console.log(
|
|
6390
|
+
console.log(chalk78.dim(noCommitsMessage(!!lastInfo)));
|
|
6287
6391
|
}
|
|
6288
6392
|
|
|
6289
6393
|
// src/commands/devlog/next/index.ts
|
|
@@ -6324,11 +6428,11 @@ function next2(options2) {
|
|
|
6324
6428
|
import { execSync as execSync22 } from "child_process";
|
|
6325
6429
|
|
|
6326
6430
|
// src/commands/devlog/repos/printReposTable.ts
|
|
6327
|
-
import
|
|
6431
|
+
import chalk79 from "chalk";
|
|
6328
6432
|
function colorStatus(status2) {
|
|
6329
|
-
if (status2 === "missing") return
|
|
6330
|
-
if (status2 === "outdated") return
|
|
6331
|
-
return
|
|
6433
|
+
if (status2 === "missing") return chalk79.red(status2);
|
|
6434
|
+
if (status2 === "outdated") return chalk79.yellow(status2);
|
|
6435
|
+
return chalk79.green(status2);
|
|
6332
6436
|
}
|
|
6333
6437
|
function formatRow(row, nameWidth) {
|
|
6334
6438
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -6342,8 +6446,8 @@ function printReposTable(rows) {
|
|
|
6342
6446
|
"Last Devlog".padEnd(11),
|
|
6343
6447
|
"Status"
|
|
6344
6448
|
].join(" ");
|
|
6345
|
-
console.log(
|
|
6346
|
-
console.log(
|
|
6449
|
+
console.log(chalk79.dim(header));
|
|
6450
|
+
console.log(chalk79.dim("-".repeat(header.length)));
|
|
6347
6451
|
for (const row of rows) {
|
|
6348
6452
|
console.log(formatRow(row, nameWidth));
|
|
6349
6453
|
}
|
|
@@ -6400,15 +6504,15 @@ function repos(options2) {
|
|
|
6400
6504
|
|
|
6401
6505
|
// src/commands/devlog/skip.ts
|
|
6402
6506
|
import { writeFileSync as writeFileSync19 } from "fs";
|
|
6403
|
-
import { join as
|
|
6404
|
-
import
|
|
6507
|
+
import { join as join22 } from "path";
|
|
6508
|
+
import chalk80 from "chalk";
|
|
6405
6509
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
6406
6510
|
function getBlogConfigPath() {
|
|
6407
|
-
return
|
|
6511
|
+
return join22(BLOG_REPO_ROOT, "assist.yml");
|
|
6408
6512
|
}
|
|
6409
6513
|
function skip(date) {
|
|
6410
6514
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
6411
|
-
console.log(
|
|
6515
|
+
console.log(chalk80.red("Invalid date format. Use YYYY-MM-DD"));
|
|
6412
6516
|
process.exit(1);
|
|
6413
6517
|
}
|
|
6414
6518
|
const repoName = getRepoName();
|
|
@@ -6419,7 +6523,7 @@ function skip(date) {
|
|
|
6419
6523
|
const skipDays = skip2[repoName] ?? [];
|
|
6420
6524
|
if (skipDays.includes(date)) {
|
|
6421
6525
|
console.log(
|
|
6422
|
-
|
|
6526
|
+
chalk80.yellow(`${date} is already in skip list for ${repoName}`)
|
|
6423
6527
|
);
|
|
6424
6528
|
return;
|
|
6425
6529
|
}
|
|
@@ -6429,20 +6533,20 @@ function skip(date) {
|
|
|
6429
6533
|
devlog.skip = skip2;
|
|
6430
6534
|
config.devlog = devlog;
|
|
6431
6535
|
writeFileSync19(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
6432
|
-
console.log(
|
|
6536
|
+
console.log(chalk80.green(`Added ${date} to skip list for ${repoName}`));
|
|
6433
6537
|
}
|
|
6434
6538
|
|
|
6435
6539
|
// src/commands/devlog/version.ts
|
|
6436
|
-
import
|
|
6540
|
+
import chalk81 from "chalk";
|
|
6437
6541
|
function version() {
|
|
6438
6542
|
const config = loadConfig();
|
|
6439
6543
|
const name = getRepoName();
|
|
6440
6544
|
const lastInfo = getLastVersionInfo(name, config);
|
|
6441
6545
|
const lastVersion = lastInfo?.version ?? null;
|
|
6442
6546
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
6443
|
-
console.log(`${
|
|
6444
|
-
console.log(`${
|
|
6445
|
-
console.log(`${
|
|
6547
|
+
console.log(`${chalk81.bold("name:")} ${name}`);
|
|
6548
|
+
console.log(`${chalk81.bold("last:")} ${lastVersion ?? chalk81.dim("none")}`);
|
|
6549
|
+
console.log(`${chalk81.bold("next:")} ${nextVersion ?? chalk81.dim("none")}`);
|
|
6446
6550
|
}
|
|
6447
6551
|
|
|
6448
6552
|
// src/commands/registerDevlog.ts
|
|
@@ -6465,16 +6569,16 @@ function registerDevlog(program2) {
|
|
|
6465
6569
|
|
|
6466
6570
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
6467
6571
|
import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
|
|
6468
|
-
import { join as
|
|
6469
|
-
import
|
|
6572
|
+
import { join as join23 } from "path";
|
|
6573
|
+
import chalk82 from "chalk";
|
|
6470
6574
|
|
|
6471
6575
|
// src/shared/findRepoRoot.ts
|
|
6472
|
-
import { existsSync as
|
|
6576
|
+
import { existsSync as existsSync24 } from "fs";
|
|
6473
6577
|
import path21 from "path";
|
|
6474
6578
|
function findRepoRoot(dir) {
|
|
6475
6579
|
let current = dir;
|
|
6476
6580
|
while (current !== path21.dirname(current)) {
|
|
6477
|
-
if (
|
|
6581
|
+
if (existsSync24(path21.join(current, ".git"))) {
|
|
6478
6582
|
return current;
|
|
6479
6583
|
}
|
|
6480
6584
|
current = path21.dirname(current);
|
|
@@ -6493,7 +6597,7 @@ function isLockedDll(debugDir) {
|
|
|
6493
6597
|
}
|
|
6494
6598
|
for (const file of files) {
|
|
6495
6599
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
6496
|
-
const dllPath =
|
|
6600
|
+
const dllPath = join23(debugDir, file);
|
|
6497
6601
|
try {
|
|
6498
6602
|
const fd = openSync(dllPath, "r+");
|
|
6499
6603
|
closeSync(fd);
|
|
@@ -6511,13 +6615,13 @@ function findFirstLockedDll(dir) {
|
|
|
6511
6615
|
return null;
|
|
6512
6616
|
}
|
|
6513
6617
|
if (entries.includes("bin")) {
|
|
6514
|
-
const locked = isLockedDll(
|
|
6618
|
+
const locked = isLockedDll(join23(dir, "bin", "Debug"));
|
|
6515
6619
|
if (locked) return locked;
|
|
6516
6620
|
}
|
|
6517
6621
|
for (const entry of entries) {
|
|
6518
6622
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
6519
6623
|
continue;
|
|
6520
|
-
const found = findFirstLockedDll(
|
|
6624
|
+
const found = findFirstLockedDll(join23(dir, entry));
|
|
6521
6625
|
if (found) return found;
|
|
6522
6626
|
}
|
|
6523
6627
|
return null;
|
|
@@ -6529,14 +6633,14 @@ function checkBuildLocks(startDir) {
|
|
|
6529
6633
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
6530
6634
|
if (locked) {
|
|
6531
6635
|
console.error(
|
|
6532
|
-
|
|
6636
|
+
chalk82.red("Build output locked (is VS debugging?): ") + locked
|
|
6533
6637
|
);
|
|
6534
6638
|
process.exit(1);
|
|
6535
6639
|
}
|
|
6536
6640
|
}
|
|
6537
6641
|
async function checkBuildLocksCommand() {
|
|
6538
6642
|
checkBuildLocks();
|
|
6539
|
-
console.log(
|
|
6643
|
+
console.log(chalk82.green("No build locks detected"));
|
|
6540
6644
|
}
|
|
6541
6645
|
|
|
6542
6646
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -6635,30 +6739,30 @@ function escapeRegex(s) {
|
|
|
6635
6739
|
}
|
|
6636
6740
|
|
|
6637
6741
|
// src/commands/dotnet/printTree.ts
|
|
6638
|
-
import
|
|
6742
|
+
import chalk83 from "chalk";
|
|
6639
6743
|
function printNodes(nodes, prefix2) {
|
|
6640
6744
|
for (let i = 0; i < nodes.length; i++) {
|
|
6641
6745
|
const isLast = i === nodes.length - 1;
|
|
6642
6746
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
6643
6747
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
6644
6748
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
6645
|
-
const label2 = isMissing ?
|
|
6749
|
+
const label2 = isMissing ? chalk83.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
6646
6750
|
console.log(`${prefix2}${connector}${label2}`);
|
|
6647
6751
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
6648
6752
|
}
|
|
6649
6753
|
}
|
|
6650
6754
|
function printTree(tree, totalCount, solutions) {
|
|
6651
|
-
console.log(
|
|
6652
|
-
console.log(
|
|
6755
|
+
console.log(chalk83.bold("\nProject Dependency Tree"));
|
|
6756
|
+
console.log(chalk83.cyan(tree.relativePath));
|
|
6653
6757
|
printNodes(tree.children, "");
|
|
6654
|
-
console.log(
|
|
6758
|
+
console.log(chalk83.dim(`
|
|
6655
6759
|
${totalCount} projects total (including root)`));
|
|
6656
|
-
console.log(
|
|
6760
|
+
console.log(chalk83.bold("\nSolution Membership"));
|
|
6657
6761
|
if (solutions.length === 0) {
|
|
6658
|
-
console.log(
|
|
6762
|
+
console.log(chalk83.yellow(" Not found in any .sln"));
|
|
6659
6763
|
} else {
|
|
6660
6764
|
for (const sln of solutions) {
|
|
6661
|
-
console.log(` ${
|
|
6765
|
+
console.log(` ${chalk83.green(sln)}`);
|
|
6662
6766
|
}
|
|
6663
6767
|
}
|
|
6664
6768
|
console.log();
|
|
@@ -6685,18 +6789,18 @@ function printJson(tree, totalCount, solutions) {
|
|
|
6685
6789
|
}
|
|
6686
6790
|
|
|
6687
6791
|
// src/commands/dotnet/resolveCsproj.ts
|
|
6688
|
-
import { existsSync as
|
|
6792
|
+
import { existsSync as existsSync25 } from "fs";
|
|
6689
6793
|
import path24 from "path";
|
|
6690
|
-
import
|
|
6794
|
+
import chalk84 from "chalk";
|
|
6691
6795
|
function resolveCsproj(csprojPath) {
|
|
6692
6796
|
const resolved = path24.resolve(csprojPath);
|
|
6693
|
-
if (!
|
|
6694
|
-
console.error(
|
|
6797
|
+
if (!existsSync25(resolved)) {
|
|
6798
|
+
console.error(chalk84.red(`File not found: ${resolved}`));
|
|
6695
6799
|
process.exit(1);
|
|
6696
6800
|
}
|
|
6697
6801
|
const repoRoot = findRepoRoot(path24.dirname(resolved));
|
|
6698
6802
|
if (!repoRoot) {
|
|
6699
|
-
console.error(
|
|
6803
|
+
console.error(chalk84.red("Could not find git repository root"));
|
|
6700
6804
|
process.exit(1);
|
|
6701
6805
|
}
|
|
6702
6806
|
return { resolved, repoRoot };
|
|
@@ -6746,12 +6850,12 @@ function getChangedCsFiles(scope) {
|
|
|
6746
6850
|
}
|
|
6747
6851
|
|
|
6748
6852
|
// src/commands/dotnet/inSln.ts
|
|
6749
|
-
import
|
|
6853
|
+
import chalk85 from "chalk";
|
|
6750
6854
|
async function inSln(csprojPath) {
|
|
6751
6855
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
6752
6856
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
6753
6857
|
if (solutions.length === 0) {
|
|
6754
|
-
console.log(
|
|
6858
|
+
console.log(chalk85.yellow("Not found in any .sln file"));
|
|
6755
6859
|
process.exit(1);
|
|
6756
6860
|
}
|
|
6757
6861
|
for (const sln of solutions) {
|
|
@@ -6760,7 +6864,7 @@ async function inSln(csprojPath) {
|
|
|
6760
6864
|
}
|
|
6761
6865
|
|
|
6762
6866
|
// src/commands/dotnet/inspect.ts
|
|
6763
|
-
import
|
|
6867
|
+
import chalk91 from "chalk";
|
|
6764
6868
|
|
|
6765
6869
|
// src/shared/formatElapsed.ts
|
|
6766
6870
|
function formatElapsed(ms) {
|
|
@@ -6772,12 +6876,12 @@ function formatElapsed(ms) {
|
|
|
6772
6876
|
}
|
|
6773
6877
|
|
|
6774
6878
|
// src/commands/dotnet/displayIssues.ts
|
|
6775
|
-
import
|
|
6879
|
+
import chalk86 from "chalk";
|
|
6776
6880
|
var SEVERITY_COLOR = {
|
|
6777
|
-
ERROR:
|
|
6778
|
-
WARNING:
|
|
6779
|
-
SUGGESTION:
|
|
6780
|
-
HINT:
|
|
6881
|
+
ERROR: chalk86.red,
|
|
6882
|
+
WARNING: chalk86.yellow,
|
|
6883
|
+
SUGGESTION: chalk86.cyan,
|
|
6884
|
+
HINT: chalk86.dim
|
|
6781
6885
|
};
|
|
6782
6886
|
function groupByFile(issues) {
|
|
6783
6887
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -6793,15 +6897,15 @@ function groupByFile(issues) {
|
|
|
6793
6897
|
}
|
|
6794
6898
|
function displayIssues(issues) {
|
|
6795
6899
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
6796
|
-
console.log(
|
|
6900
|
+
console.log(chalk86.bold(file));
|
|
6797
6901
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
6798
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
6902
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk86.white;
|
|
6799
6903
|
console.log(
|
|
6800
|
-
` ${
|
|
6904
|
+
` ${chalk86.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
6801
6905
|
);
|
|
6802
6906
|
}
|
|
6803
6907
|
}
|
|
6804
|
-
console.log(
|
|
6908
|
+
console.log(chalk86.dim(`
|
|
6805
6909
|
${issues.length} issue(s) found`));
|
|
6806
6910
|
}
|
|
6807
6911
|
|
|
@@ -6858,17 +6962,17 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
6858
6962
|
}
|
|
6859
6963
|
|
|
6860
6964
|
// src/commands/dotnet/resolveSolution.ts
|
|
6861
|
-
import { existsSync as
|
|
6965
|
+
import { existsSync as existsSync26 } from "fs";
|
|
6862
6966
|
import path25 from "path";
|
|
6863
|
-
import
|
|
6967
|
+
import chalk88 from "chalk";
|
|
6864
6968
|
|
|
6865
6969
|
// src/commands/dotnet/findSolution.ts
|
|
6866
6970
|
import { readdirSync as readdirSync4 } from "fs";
|
|
6867
|
-
import { dirname as dirname16, join as
|
|
6868
|
-
import
|
|
6971
|
+
import { dirname as dirname16, join as join24 } from "path";
|
|
6972
|
+
import chalk87 from "chalk";
|
|
6869
6973
|
function findSlnInDir(dir) {
|
|
6870
6974
|
try {
|
|
6871
|
-
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) =>
|
|
6975
|
+
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join24(dir, f));
|
|
6872
6976
|
} catch {
|
|
6873
6977
|
return [];
|
|
6874
6978
|
}
|
|
@@ -6881,17 +6985,17 @@ function findSolution() {
|
|
|
6881
6985
|
const slnFiles = findSlnInDir(current);
|
|
6882
6986
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
6883
6987
|
if (slnFiles.length > 1) {
|
|
6884
|
-
console.error(
|
|
6988
|
+
console.error(chalk87.red(`Multiple .sln files found in ${current}:`));
|
|
6885
6989
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
6886
6990
|
console.error(
|
|
6887
|
-
|
|
6991
|
+
chalk87.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
6888
6992
|
);
|
|
6889
6993
|
process.exit(1);
|
|
6890
6994
|
}
|
|
6891
6995
|
if (current === ceiling) break;
|
|
6892
6996
|
current = dirname16(current);
|
|
6893
6997
|
}
|
|
6894
|
-
console.error(
|
|
6998
|
+
console.error(chalk87.red("No .sln file found between cwd and repo root"));
|
|
6895
6999
|
process.exit(1);
|
|
6896
7000
|
}
|
|
6897
7001
|
|
|
@@ -6899,8 +7003,8 @@ function findSolution() {
|
|
|
6899
7003
|
function resolveSolution(sln) {
|
|
6900
7004
|
if (sln) {
|
|
6901
7005
|
const resolved = path25.resolve(sln);
|
|
6902
|
-
if (!
|
|
6903
|
-
console.error(
|
|
7006
|
+
if (!existsSync26(resolved)) {
|
|
7007
|
+
console.error(chalk88.red(`Solution file not found: ${resolved}`));
|
|
6904
7008
|
process.exit(1);
|
|
6905
7009
|
}
|
|
6906
7010
|
return resolved;
|
|
@@ -6939,17 +7043,17 @@ function parseInspectReport(json) {
|
|
|
6939
7043
|
|
|
6940
7044
|
// src/commands/dotnet/runInspectCode.ts
|
|
6941
7045
|
import { execSync as execSync24 } from "child_process";
|
|
6942
|
-
import { existsSync as
|
|
7046
|
+
import { existsSync as existsSync27, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "fs";
|
|
6943
7047
|
import { tmpdir as tmpdir2 } from "os";
|
|
6944
7048
|
import path26 from "path";
|
|
6945
|
-
import
|
|
7049
|
+
import chalk89 from "chalk";
|
|
6946
7050
|
function assertJbInstalled() {
|
|
6947
7051
|
try {
|
|
6948
7052
|
execSync24("jb inspectcode --version", { stdio: "pipe" });
|
|
6949
7053
|
} catch {
|
|
6950
|
-
console.error(
|
|
7054
|
+
console.error(chalk89.red("jb is not installed. Install with:"));
|
|
6951
7055
|
console.error(
|
|
6952
|
-
|
|
7056
|
+
chalk89.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
6953
7057
|
);
|
|
6954
7058
|
process.exit(1);
|
|
6955
7059
|
}
|
|
@@ -6967,11 +7071,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6967
7071
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
6968
7072
|
process.stderr.write(err.stderr);
|
|
6969
7073
|
}
|
|
6970
|
-
console.error(
|
|
7074
|
+
console.error(chalk89.red("jb inspectcode failed"));
|
|
6971
7075
|
process.exit(1);
|
|
6972
7076
|
}
|
|
6973
|
-
if (!
|
|
6974
|
-
console.error(
|
|
7077
|
+
if (!existsSync27(reportPath)) {
|
|
7078
|
+
console.error(chalk89.red("Report file not generated"));
|
|
6975
7079
|
process.exit(1);
|
|
6976
7080
|
}
|
|
6977
7081
|
const xml = readFileSync24(reportPath, "utf-8");
|
|
@@ -6981,7 +7085,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
6981
7085
|
|
|
6982
7086
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
6983
7087
|
import { execSync as execSync25 } from "child_process";
|
|
6984
|
-
import
|
|
7088
|
+
import chalk90 from "chalk";
|
|
6985
7089
|
function resolveMsbuildPath() {
|
|
6986
7090
|
const config = loadConfig();
|
|
6987
7091
|
const buildConfig = config.run?.find((r) => r.name === "build");
|
|
@@ -6992,9 +7096,9 @@ function assertMsbuildInstalled() {
|
|
|
6992
7096
|
try {
|
|
6993
7097
|
execSync25(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
6994
7098
|
} catch {
|
|
6995
|
-
console.error(
|
|
7099
|
+
console.error(chalk90.red(`msbuild not found at: ${msbuild}`));
|
|
6996
7100
|
console.error(
|
|
6997
|
-
|
|
7101
|
+
chalk90.yellow(
|
|
6998
7102
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
6999
7103
|
)
|
|
7000
7104
|
);
|
|
@@ -7041,17 +7145,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
7041
7145
|
// src/commands/dotnet/inspect.ts
|
|
7042
7146
|
function logScope(changedFiles) {
|
|
7043
7147
|
if (changedFiles === null) {
|
|
7044
|
-
console.log(
|
|
7148
|
+
console.log(chalk91.dim("Inspecting full solution..."));
|
|
7045
7149
|
} else {
|
|
7046
7150
|
console.log(
|
|
7047
|
-
|
|
7151
|
+
chalk91.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
7048
7152
|
);
|
|
7049
7153
|
}
|
|
7050
7154
|
}
|
|
7051
7155
|
function reportResults(issues, elapsed) {
|
|
7052
7156
|
if (issues.length > 0) displayIssues(issues);
|
|
7053
|
-
else console.log(
|
|
7054
|
-
console.log(
|
|
7157
|
+
else console.log(chalk91.green("No issues found"));
|
|
7158
|
+
console.log(chalk91.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
7055
7159
|
if (issues.length > 0) process.exit(1);
|
|
7056
7160
|
}
|
|
7057
7161
|
async function inspect(sln, options2) {
|
|
@@ -7062,7 +7166,7 @@ async function inspect(sln, options2) {
|
|
|
7062
7166
|
const scope = parseScope(options2.scope);
|
|
7063
7167
|
const changedFiles = getChangedCsFiles(scope);
|
|
7064
7168
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
7065
|
-
console.log(
|
|
7169
|
+
console.log(chalk91.green("No changed .cs files found"));
|
|
7066
7170
|
return;
|
|
7067
7171
|
}
|
|
7068
7172
|
logScope(changedFiles);
|
|
@@ -7088,7 +7192,7 @@ function registerDotnet(program2) {
|
|
|
7088
7192
|
}
|
|
7089
7193
|
|
|
7090
7194
|
// src/commands/jira/acceptanceCriteria.ts
|
|
7091
|
-
import
|
|
7195
|
+
import chalk93 from "chalk";
|
|
7092
7196
|
|
|
7093
7197
|
// src/commands/jira/adfToText.ts
|
|
7094
7198
|
function renderInline(node) {
|
|
@@ -7149,7 +7253,7 @@ function adfToText(doc) {
|
|
|
7149
7253
|
|
|
7150
7254
|
// src/commands/jira/fetchIssue.ts
|
|
7151
7255
|
import { execSync as execSync26 } from "child_process";
|
|
7152
|
-
import
|
|
7256
|
+
import chalk92 from "chalk";
|
|
7153
7257
|
function fetchIssue(issueKey, fields) {
|
|
7154
7258
|
let result;
|
|
7155
7259
|
try {
|
|
@@ -7162,15 +7266,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
7162
7266
|
const stderr = error.stderr;
|
|
7163
7267
|
if (stderr.includes("unauthorized")) {
|
|
7164
7268
|
console.error(
|
|
7165
|
-
|
|
7269
|
+
chalk92.red("Jira authentication expired."),
|
|
7166
7270
|
"Run",
|
|
7167
|
-
|
|
7271
|
+
chalk92.cyan("assist jira auth"),
|
|
7168
7272
|
"to re-authenticate."
|
|
7169
7273
|
);
|
|
7170
7274
|
process.exit(1);
|
|
7171
7275
|
}
|
|
7172
7276
|
}
|
|
7173
|
-
console.error(
|
|
7277
|
+
console.error(chalk92.red(`Failed to fetch ${issueKey}.`));
|
|
7174
7278
|
process.exit(1);
|
|
7175
7279
|
}
|
|
7176
7280
|
return JSON.parse(result);
|
|
@@ -7184,7 +7288,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
7184
7288
|
const parsed = fetchIssue(issueKey, field);
|
|
7185
7289
|
const acValue = parsed?.fields?.[field];
|
|
7186
7290
|
if (!acValue) {
|
|
7187
|
-
console.log(
|
|
7291
|
+
console.log(chalk93.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
7188
7292
|
return;
|
|
7189
7293
|
}
|
|
7190
7294
|
if (typeof acValue === "string") {
|
|
@@ -7202,18 +7306,18 @@ function acceptanceCriteria(issueKey) {
|
|
|
7202
7306
|
import { execSync as execSync27 } from "child_process";
|
|
7203
7307
|
|
|
7204
7308
|
// src/shared/loadJson.ts
|
|
7205
|
-
import { existsSync as
|
|
7309
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "fs";
|
|
7206
7310
|
import { homedir as homedir6 } from "os";
|
|
7207
|
-
import { join as
|
|
7311
|
+
import { join as join25 } from "path";
|
|
7208
7312
|
function getStoreDir() {
|
|
7209
|
-
return
|
|
7313
|
+
return join25(homedir6(), ".assist");
|
|
7210
7314
|
}
|
|
7211
7315
|
function getStorePath(filename) {
|
|
7212
|
-
return
|
|
7316
|
+
return join25(getStoreDir(), filename);
|
|
7213
7317
|
}
|
|
7214
7318
|
function loadJson(filename) {
|
|
7215
7319
|
const path50 = getStorePath(filename);
|
|
7216
|
-
if (
|
|
7320
|
+
if (existsSync28(path50)) {
|
|
7217
7321
|
try {
|
|
7218
7322
|
return JSON.parse(readFileSync25(path50, "utf-8"));
|
|
7219
7323
|
} catch {
|
|
@@ -7224,7 +7328,7 @@ function loadJson(filename) {
|
|
|
7224
7328
|
}
|
|
7225
7329
|
function saveJson(filename, data) {
|
|
7226
7330
|
const dir = getStoreDir();
|
|
7227
|
-
if (!
|
|
7331
|
+
if (!existsSync28(dir)) {
|
|
7228
7332
|
mkdirSync6(dir, { recursive: true });
|
|
7229
7333
|
}
|
|
7230
7334
|
writeFileSync20(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
@@ -7279,14 +7383,14 @@ async function jiraAuth() {
|
|
|
7279
7383
|
}
|
|
7280
7384
|
|
|
7281
7385
|
// src/commands/jira/viewIssue.ts
|
|
7282
|
-
import
|
|
7386
|
+
import chalk94 from "chalk";
|
|
7283
7387
|
function viewIssue(issueKey) {
|
|
7284
7388
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
7285
7389
|
const fields = parsed?.fields;
|
|
7286
7390
|
const summary = fields?.summary;
|
|
7287
7391
|
const description = fields?.description;
|
|
7288
7392
|
if (summary) {
|
|
7289
|
-
console.log(
|
|
7393
|
+
console.log(chalk94.bold(summary));
|
|
7290
7394
|
}
|
|
7291
7395
|
if (description) {
|
|
7292
7396
|
if (summary) console.log();
|
|
@@ -7300,7 +7404,7 @@ function viewIssue(issueKey) {
|
|
|
7300
7404
|
}
|
|
7301
7405
|
if (!summary && !description) {
|
|
7302
7406
|
console.log(
|
|
7303
|
-
|
|
7407
|
+
chalk94.yellow(`No summary or description found on ${issueKey}.`)
|
|
7304
7408
|
);
|
|
7305
7409
|
}
|
|
7306
7410
|
}
|
|
@@ -7314,7 +7418,7 @@ function registerJira(program2) {
|
|
|
7314
7418
|
}
|
|
7315
7419
|
|
|
7316
7420
|
// src/commands/news/add/index.ts
|
|
7317
|
-
import
|
|
7421
|
+
import chalk95 from "chalk";
|
|
7318
7422
|
import enquirer8 from "enquirer";
|
|
7319
7423
|
async function add2(url) {
|
|
7320
7424
|
if (!url) {
|
|
@@ -7337,17 +7441,17 @@ async function add2(url) {
|
|
|
7337
7441
|
const news = config.news ?? {};
|
|
7338
7442
|
const feeds = news.feeds ?? [];
|
|
7339
7443
|
if (feeds.includes(url)) {
|
|
7340
|
-
console.log(
|
|
7444
|
+
console.log(chalk95.yellow("Feed already exists in config"));
|
|
7341
7445
|
return;
|
|
7342
7446
|
}
|
|
7343
7447
|
feeds.push(url);
|
|
7344
7448
|
config.news = { ...news, feeds };
|
|
7345
7449
|
saveGlobalConfig(config);
|
|
7346
|
-
console.log(
|
|
7450
|
+
console.log(chalk95.green(`Added feed: ${url}`));
|
|
7347
7451
|
}
|
|
7348
7452
|
|
|
7349
7453
|
// src/commands/news/web/handleRequest.ts
|
|
7350
|
-
import
|
|
7454
|
+
import chalk96 from "chalk";
|
|
7351
7455
|
|
|
7352
7456
|
// src/commands/news/web/shared.ts
|
|
7353
7457
|
import { decodeHTML } from "entities";
|
|
@@ -7483,17 +7587,17 @@ function prefetch() {
|
|
|
7483
7587
|
const config = loadConfig();
|
|
7484
7588
|
const total = config.news.feeds.length;
|
|
7485
7589
|
if (total === 0) return;
|
|
7486
|
-
process.stdout.write(
|
|
7590
|
+
process.stdout.write(chalk96.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
7487
7591
|
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
7488
7592
|
const width = 20;
|
|
7489
7593
|
const filled = Math.round(done2 / t * width);
|
|
7490
7594
|
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
7491
7595
|
process.stdout.write(
|
|
7492
|
-
`\r${
|
|
7596
|
+
`\r${chalk96.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
7493
7597
|
);
|
|
7494
7598
|
}).then((items) => {
|
|
7495
7599
|
process.stdout.write(
|
|
7496
|
-
`\r${
|
|
7600
|
+
`\r${chalk96.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
7497
7601
|
`
|
|
7498
7602
|
);
|
|
7499
7603
|
cachedItems = items;
|
|
@@ -7541,7 +7645,7 @@ function registerNews(program2) {
|
|
|
7541
7645
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
7542
7646
|
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync21 } from "fs";
|
|
7543
7647
|
import { tmpdir as tmpdir3 } from "os";
|
|
7544
|
-
import { join as
|
|
7648
|
+
import { join as join26 } from "path";
|
|
7545
7649
|
|
|
7546
7650
|
// src/commands/prs/shared.ts
|
|
7547
7651
|
import { execSync as execSync28 } from "child_process";
|
|
@@ -7613,7 +7717,7 @@ function comment2(path50, line, body) {
|
|
|
7613
7717
|
validateLine(line);
|
|
7614
7718
|
try {
|
|
7615
7719
|
const prId = getCurrentPrNodeId();
|
|
7616
|
-
const queryFile =
|
|
7720
|
+
const queryFile = join26(tmpdir3(), `gh-query-${Date.now()}.graphql`);
|
|
7617
7721
|
writeFileSync21(queryFile, MUTATION);
|
|
7618
7722
|
try {
|
|
7619
7723
|
const result = spawnSync2(
|
|
@@ -7658,18 +7762,18 @@ import { execSync as execSync30 } from "child_process";
|
|
|
7658
7762
|
import { execSync as execSync29 } from "child_process";
|
|
7659
7763
|
import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync22 } from "fs";
|
|
7660
7764
|
import { tmpdir as tmpdir4 } from "os";
|
|
7661
|
-
import { join as
|
|
7765
|
+
import { join as join28 } from "path";
|
|
7662
7766
|
|
|
7663
7767
|
// src/commands/prs/loadCommentsCache.ts
|
|
7664
|
-
import { existsSync as
|
|
7665
|
-
import { join as
|
|
7768
|
+
import { existsSync as existsSync29, readFileSync as readFileSync26, unlinkSync as unlinkSync7 } from "fs";
|
|
7769
|
+
import { join as join27 } from "path";
|
|
7666
7770
|
import { parse as parse2 } from "yaml";
|
|
7667
7771
|
function getCachePath(prNumber) {
|
|
7668
|
-
return
|
|
7772
|
+
return join27(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
7669
7773
|
}
|
|
7670
7774
|
function loadCommentsCache(prNumber) {
|
|
7671
7775
|
const cachePath = getCachePath(prNumber);
|
|
7672
|
-
if (!
|
|
7776
|
+
if (!existsSync29(cachePath)) {
|
|
7673
7777
|
return null;
|
|
7674
7778
|
}
|
|
7675
7779
|
const content = readFileSync26(cachePath, "utf-8");
|
|
@@ -7677,7 +7781,7 @@ function loadCommentsCache(prNumber) {
|
|
|
7677
7781
|
}
|
|
7678
7782
|
function deleteCommentsCache(prNumber) {
|
|
7679
7783
|
const cachePath = getCachePath(prNumber);
|
|
7680
|
-
if (
|
|
7784
|
+
if (existsSync29(cachePath)) {
|
|
7681
7785
|
unlinkSync7(cachePath);
|
|
7682
7786
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
7683
7787
|
}
|
|
@@ -7692,7 +7796,7 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
7692
7796
|
}
|
|
7693
7797
|
function resolveThread(threadId) {
|
|
7694
7798
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
7695
|
-
const queryFile =
|
|
7799
|
+
const queryFile = join28(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
|
|
7696
7800
|
writeFileSync22(queryFile, mutation);
|
|
7697
7801
|
try {
|
|
7698
7802
|
execSync29(
|
|
@@ -7774,18 +7878,18 @@ function fixed(commentId, sha) {
|
|
|
7774
7878
|
}
|
|
7775
7879
|
|
|
7776
7880
|
// src/commands/prs/listComments/index.ts
|
|
7777
|
-
import { existsSync as
|
|
7778
|
-
import { join as
|
|
7881
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync7, writeFileSync as writeFileSync24 } from "fs";
|
|
7882
|
+
import { join as join30 } from "path";
|
|
7779
7883
|
import { stringify } from "yaml";
|
|
7780
7884
|
|
|
7781
7885
|
// src/commands/prs/fetchThreadIds.ts
|
|
7782
7886
|
import { execSync as execSync31 } from "child_process";
|
|
7783
7887
|
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync23 } from "fs";
|
|
7784
7888
|
import { tmpdir as tmpdir5 } from "os";
|
|
7785
|
-
import { join as
|
|
7889
|
+
import { join as join29 } from "path";
|
|
7786
7890
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
7787
7891
|
function fetchThreadIds(org, repo, prNumber) {
|
|
7788
|
-
const queryFile =
|
|
7892
|
+
const queryFile = join29(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
7789
7893
|
writeFileSync23(queryFile, THREAD_QUERY);
|
|
7790
7894
|
try {
|
|
7791
7895
|
const result = execSync31(
|
|
@@ -7854,20 +7958,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
7854
7958
|
}
|
|
7855
7959
|
|
|
7856
7960
|
// src/commands/prs/listComments/printComments.ts
|
|
7857
|
-
import
|
|
7961
|
+
import chalk97 from "chalk";
|
|
7858
7962
|
function formatForHuman(comment3) {
|
|
7859
7963
|
if (comment3.type === "review") {
|
|
7860
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
7964
|
+
const stateColor = comment3.state === "APPROVED" ? chalk97.green : comment3.state === "CHANGES_REQUESTED" ? chalk97.red : chalk97.yellow;
|
|
7861
7965
|
return [
|
|
7862
|
-
`${
|
|
7966
|
+
`${chalk97.cyan("Review")} by ${chalk97.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
7863
7967
|
comment3.body,
|
|
7864
7968
|
""
|
|
7865
7969
|
].join("\n");
|
|
7866
7970
|
}
|
|
7867
7971
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
7868
7972
|
return [
|
|
7869
|
-
`${
|
|
7870
|
-
|
|
7973
|
+
`${chalk97.cyan("Line comment")} by ${chalk97.bold(comment3.user)} on ${chalk97.dim(`${comment3.path}${location}`)}`,
|
|
7974
|
+
chalk97.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
7871
7975
|
comment3.body,
|
|
7872
7976
|
""
|
|
7873
7977
|
].join("\n");
|
|
@@ -7899,8 +8003,8 @@ function printComments2(result) {
|
|
|
7899
8003
|
|
|
7900
8004
|
// src/commands/prs/listComments/index.ts
|
|
7901
8005
|
function writeCommentsCache(prNumber, comments2) {
|
|
7902
|
-
const assistDir =
|
|
7903
|
-
if (!
|
|
8006
|
+
const assistDir = join30(process.cwd(), ".assist");
|
|
8007
|
+
if (!existsSync30(assistDir)) {
|
|
7904
8008
|
mkdirSync7(assistDir, { recursive: true });
|
|
7905
8009
|
}
|
|
7906
8010
|
const cacheData = {
|
|
@@ -7908,7 +8012,7 @@ function writeCommentsCache(prNumber, comments2) {
|
|
|
7908
8012
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7909
8013
|
comments: comments2
|
|
7910
8014
|
};
|
|
7911
|
-
const cachePath =
|
|
8015
|
+
const cachePath = join30(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
7912
8016
|
writeFileSync24(cachePath, stringify(cacheData));
|
|
7913
8017
|
}
|
|
7914
8018
|
function handleKnownErrors(error) {
|
|
@@ -7941,7 +8045,7 @@ async function listComments() {
|
|
|
7941
8045
|
];
|
|
7942
8046
|
updateCache(prNumber, allComments);
|
|
7943
8047
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
7944
|
-
const cachePath = hasLineComments ?
|
|
8048
|
+
const cachePath = hasLineComments ? join30(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
7945
8049
|
return { comments: allComments, cachePath };
|
|
7946
8050
|
} catch (error) {
|
|
7947
8051
|
const handled = handleKnownErrors(error);
|
|
@@ -7957,13 +8061,13 @@ import { execSync as execSync33 } from "child_process";
|
|
|
7957
8061
|
import enquirer9 from "enquirer";
|
|
7958
8062
|
|
|
7959
8063
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
7960
|
-
import
|
|
8064
|
+
import chalk98 from "chalk";
|
|
7961
8065
|
var STATUS_MAP = {
|
|
7962
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
7963
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
8066
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk98.magenta("merged"), date: pr.mergedAt } : null,
|
|
8067
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk98.red("closed"), date: pr.closedAt } : null
|
|
7964
8068
|
};
|
|
7965
8069
|
function defaultStatus(pr) {
|
|
7966
|
-
return { label:
|
|
8070
|
+
return { label: chalk98.green("opened"), date: pr.createdAt };
|
|
7967
8071
|
}
|
|
7968
8072
|
function getStatus2(pr) {
|
|
7969
8073
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -7972,11 +8076,11 @@ function formatDate(dateStr) {
|
|
|
7972
8076
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
7973
8077
|
}
|
|
7974
8078
|
function formatPrHeader(pr, status2) {
|
|
7975
|
-
return `${
|
|
8079
|
+
return `${chalk98.cyan(`#${pr.number}`)} ${pr.title} ${chalk98.dim(`(${pr.author.login},`)} ${status2.label} ${chalk98.dim(`${formatDate(status2.date)})`)}`;
|
|
7976
8080
|
}
|
|
7977
8081
|
function logPrDetails(pr) {
|
|
7978
8082
|
console.log(
|
|
7979
|
-
|
|
8083
|
+
chalk98.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
7980
8084
|
);
|
|
7981
8085
|
console.log();
|
|
7982
8086
|
}
|
|
@@ -8142,10 +8246,10 @@ function registerPrs(program2) {
|
|
|
8142
8246
|
}
|
|
8143
8247
|
|
|
8144
8248
|
// src/commands/ravendb/ravendbAuth.ts
|
|
8145
|
-
import
|
|
8249
|
+
import chalk104 from "chalk";
|
|
8146
8250
|
|
|
8147
8251
|
// src/shared/createConnectionAuth.ts
|
|
8148
|
-
import
|
|
8252
|
+
import chalk99 from "chalk";
|
|
8149
8253
|
function listConnections(connections, format2) {
|
|
8150
8254
|
if (connections.length === 0) {
|
|
8151
8255
|
console.log("No connections configured.");
|
|
@@ -8158,7 +8262,7 @@ function listConnections(connections, format2) {
|
|
|
8158
8262
|
function removeConnection(connections, name, save) {
|
|
8159
8263
|
const filtered = connections.filter((c) => c.name !== name);
|
|
8160
8264
|
if (filtered.length === connections.length) {
|
|
8161
|
-
console.error(
|
|
8265
|
+
console.error(chalk99.red(`Connection "${name}" not found.`));
|
|
8162
8266
|
process.exit(1);
|
|
8163
8267
|
}
|
|
8164
8268
|
save(filtered);
|
|
@@ -8204,15 +8308,15 @@ function saveConnections(connections) {
|
|
|
8204
8308
|
}
|
|
8205
8309
|
|
|
8206
8310
|
// src/commands/ravendb/promptConnection.ts
|
|
8207
|
-
import
|
|
8311
|
+
import chalk102 from "chalk";
|
|
8208
8312
|
|
|
8209
8313
|
// src/commands/ravendb/selectOpSecret.ts
|
|
8210
|
-
import
|
|
8314
|
+
import chalk101 from "chalk";
|
|
8211
8315
|
import Enquirer2 from "enquirer";
|
|
8212
8316
|
|
|
8213
8317
|
// src/commands/ravendb/searchItems.ts
|
|
8214
8318
|
import { execSync as execSync35 } from "child_process";
|
|
8215
|
-
import
|
|
8319
|
+
import chalk100 from "chalk";
|
|
8216
8320
|
function opExec(args) {
|
|
8217
8321
|
return execSync35(`op ${args}`, {
|
|
8218
8322
|
encoding: "utf-8",
|
|
@@ -8225,7 +8329,7 @@ function searchItems(search2) {
|
|
|
8225
8329
|
items = JSON.parse(opExec("item list --format=json"));
|
|
8226
8330
|
} catch {
|
|
8227
8331
|
console.error(
|
|
8228
|
-
|
|
8332
|
+
chalk100.red(
|
|
8229
8333
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
8230
8334
|
)
|
|
8231
8335
|
);
|
|
@@ -8239,7 +8343,7 @@ function getItemFields(itemId) {
|
|
|
8239
8343
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
8240
8344
|
return item.fields.filter((f) => f.reference && f.label);
|
|
8241
8345
|
} catch {
|
|
8242
|
-
console.error(
|
|
8346
|
+
console.error(chalk100.red("Failed to get item details from 1Password."));
|
|
8243
8347
|
process.exit(1);
|
|
8244
8348
|
}
|
|
8245
8349
|
}
|
|
@@ -8258,7 +8362,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
8258
8362
|
}).run();
|
|
8259
8363
|
const items = searchItems(search2);
|
|
8260
8364
|
if (items.length === 0) {
|
|
8261
|
-
console.error(
|
|
8365
|
+
console.error(chalk101.red(`No items found matching "${search2}".`));
|
|
8262
8366
|
process.exit(1);
|
|
8263
8367
|
}
|
|
8264
8368
|
const itemId = await selectOne(
|
|
@@ -8267,7 +8371,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
8267
8371
|
);
|
|
8268
8372
|
const fields = getItemFields(itemId);
|
|
8269
8373
|
if (fields.length === 0) {
|
|
8270
|
-
console.error(
|
|
8374
|
+
console.error(chalk101.red("No fields with references found on this item."));
|
|
8271
8375
|
process.exit(1);
|
|
8272
8376
|
}
|
|
8273
8377
|
const ref = await selectOne(
|
|
@@ -8281,7 +8385,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
8281
8385
|
async function promptConnection(existingNames) {
|
|
8282
8386
|
const name = await promptInput("name", "Connection name:");
|
|
8283
8387
|
if (existingNames.includes(name)) {
|
|
8284
|
-
console.error(
|
|
8388
|
+
console.error(chalk102.red(`Connection "${name}" already exists.`));
|
|
8285
8389
|
process.exit(1);
|
|
8286
8390
|
}
|
|
8287
8391
|
const url = await promptInput(
|
|
@@ -8290,22 +8394,22 @@ async function promptConnection(existingNames) {
|
|
|
8290
8394
|
);
|
|
8291
8395
|
const database = await promptInput("database", "Database name:");
|
|
8292
8396
|
if (!name || !url || !database) {
|
|
8293
|
-
console.error(
|
|
8397
|
+
console.error(chalk102.red("All fields are required."));
|
|
8294
8398
|
process.exit(1);
|
|
8295
8399
|
}
|
|
8296
8400
|
const apiKeyRef = await selectOpSecret();
|
|
8297
|
-
console.log(
|
|
8401
|
+
console.log(chalk102.dim(`Using: ${apiKeyRef}`));
|
|
8298
8402
|
return { name, url, database, apiKeyRef };
|
|
8299
8403
|
}
|
|
8300
8404
|
|
|
8301
8405
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
8302
|
-
import
|
|
8406
|
+
import chalk103 from "chalk";
|
|
8303
8407
|
function ravendbSetConnection(name) {
|
|
8304
8408
|
const raw = loadGlobalConfigRaw();
|
|
8305
8409
|
const ravendb = raw.ravendb ?? {};
|
|
8306
8410
|
const connections = ravendb.connections ?? [];
|
|
8307
8411
|
if (!connections.some((c) => c.name === name)) {
|
|
8308
|
-
console.error(
|
|
8412
|
+
console.error(chalk103.red(`Connection "${name}" not found.`));
|
|
8309
8413
|
console.error(
|
|
8310
8414
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
8311
8415
|
);
|
|
@@ -8321,16 +8425,16 @@ function ravendbSetConnection(name) {
|
|
|
8321
8425
|
var ravendbAuth = createConnectionAuth({
|
|
8322
8426
|
load: loadConnections,
|
|
8323
8427
|
save: saveConnections,
|
|
8324
|
-
format: (c) => `${
|
|
8428
|
+
format: (c) => `${chalk104.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
8325
8429
|
promptNew: promptConnection,
|
|
8326
8430
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
8327
8431
|
});
|
|
8328
8432
|
|
|
8329
8433
|
// src/commands/ravendb/ravendbCollections.ts
|
|
8330
|
-
import
|
|
8434
|
+
import chalk108 from "chalk";
|
|
8331
8435
|
|
|
8332
8436
|
// src/commands/ravendb/ravenFetch.ts
|
|
8333
|
-
import
|
|
8437
|
+
import chalk106 from "chalk";
|
|
8334
8438
|
|
|
8335
8439
|
// src/commands/ravendb/getAccessToken.ts
|
|
8336
8440
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -8367,10 +8471,10 @@ ${errorText}`
|
|
|
8367
8471
|
|
|
8368
8472
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
8369
8473
|
import { execSync as execSync36 } from "child_process";
|
|
8370
|
-
import
|
|
8474
|
+
import chalk105 from "chalk";
|
|
8371
8475
|
function resolveOpSecret(reference) {
|
|
8372
8476
|
if (!reference.startsWith("op://")) {
|
|
8373
|
-
console.error(
|
|
8477
|
+
console.error(chalk105.red(`Invalid secret reference: must start with op://`));
|
|
8374
8478
|
process.exit(1);
|
|
8375
8479
|
}
|
|
8376
8480
|
try {
|
|
@@ -8380,7 +8484,7 @@ function resolveOpSecret(reference) {
|
|
|
8380
8484
|
}).trim();
|
|
8381
8485
|
} catch {
|
|
8382
8486
|
console.error(
|
|
8383
|
-
|
|
8487
|
+
chalk105.red(
|
|
8384
8488
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
8385
8489
|
)
|
|
8386
8490
|
);
|
|
@@ -8407,7 +8511,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8407
8511
|
if (!response.ok) {
|
|
8408
8512
|
const body = await response.text();
|
|
8409
8513
|
console.error(
|
|
8410
|
-
|
|
8514
|
+
chalk106.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
8411
8515
|
);
|
|
8412
8516
|
console.error(body.substring(0, 500));
|
|
8413
8517
|
process.exit(1);
|
|
@@ -8416,7 +8520,7 @@ async function ravenFetch(connection, path50) {
|
|
|
8416
8520
|
}
|
|
8417
8521
|
|
|
8418
8522
|
// src/commands/ravendb/resolveConnection.ts
|
|
8419
|
-
import
|
|
8523
|
+
import chalk107 from "chalk";
|
|
8420
8524
|
function loadRavendb() {
|
|
8421
8525
|
const raw = loadGlobalConfigRaw();
|
|
8422
8526
|
const ravendb = raw.ravendb;
|
|
@@ -8430,7 +8534,7 @@ function resolveConnection(name) {
|
|
|
8430
8534
|
const connectionName = name ?? defaultConnection;
|
|
8431
8535
|
if (!connectionName) {
|
|
8432
8536
|
console.error(
|
|
8433
|
-
|
|
8537
|
+
chalk107.red(
|
|
8434
8538
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
8435
8539
|
)
|
|
8436
8540
|
);
|
|
@@ -8438,7 +8542,7 @@ function resolveConnection(name) {
|
|
|
8438
8542
|
}
|
|
8439
8543
|
const connection = connections.find((c) => c.name === connectionName);
|
|
8440
8544
|
if (!connection) {
|
|
8441
|
-
console.error(
|
|
8545
|
+
console.error(chalk107.red(`Connection "${connectionName}" not found.`));
|
|
8442
8546
|
console.error(
|
|
8443
8547
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
8444
8548
|
);
|
|
@@ -8469,15 +8573,15 @@ async function ravendbCollections(connectionName) {
|
|
|
8469
8573
|
return;
|
|
8470
8574
|
}
|
|
8471
8575
|
for (const c of collections) {
|
|
8472
|
-
console.log(`${
|
|
8576
|
+
console.log(`${chalk108.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
8473
8577
|
}
|
|
8474
8578
|
}
|
|
8475
8579
|
|
|
8476
8580
|
// src/commands/ravendb/ravendbQuery.ts
|
|
8477
|
-
import
|
|
8581
|
+
import chalk110 from "chalk";
|
|
8478
8582
|
|
|
8479
8583
|
// src/commands/ravendb/fetchAllPages.ts
|
|
8480
|
-
import
|
|
8584
|
+
import chalk109 from "chalk";
|
|
8481
8585
|
|
|
8482
8586
|
// src/commands/ravendb/buildQueryPath.ts
|
|
8483
8587
|
function buildQueryPath(opts) {
|
|
@@ -8515,7 +8619,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8515
8619
|
allResults.push(...results);
|
|
8516
8620
|
start3 += results.length;
|
|
8517
8621
|
process.stderr.write(
|
|
8518
|
-
`\r${
|
|
8622
|
+
`\r${chalk109.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
8519
8623
|
);
|
|
8520
8624
|
if (start3 >= totalResults) break;
|
|
8521
8625
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -8530,7 +8634,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
8530
8634
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
8531
8635
|
const resolved = resolveArgs(connectionName, collection);
|
|
8532
8636
|
if (!resolved.collection && !options2.query) {
|
|
8533
|
-
console.error(
|
|
8637
|
+
console.error(chalk110.red("Provide a collection name or --query filter."));
|
|
8534
8638
|
process.exit(1);
|
|
8535
8639
|
}
|
|
8536
8640
|
const { collection: col } = resolved;
|
|
@@ -8568,7 +8672,7 @@ import { spawn as spawn4 } from "child_process";
|
|
|
8568
8672
|
import * as path27 from "path";
|
|
8569
8673
|
|
|
8570
8674
|
// src/commands/refactor/logViolations.ts
|
|
8571
|
-
import
|
|
8675
|
+
import chalk111 from "chalk";
|
|
8572
8676
|
var DEFAULT_MAX_LINES = 100;
|
|
8573
8677
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
8574
8678
|
if (violations.length === 0) {
|
|
@@ -8577,43 +8681,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
8577
8681
|
}
|
|
8578
8682
|
return;
|
|
8579
8683
|
}
|
|
8580
|
-
console.error(
|
|
8684
|
+
console.error(chalk111.red(`
|
|
8581
8685
|
Refactor check failed:
|
|
8582
8686
|
`));
|
|
8583
|
-
console.error(
|
|
8687
|
+
console.error(chalk111.red(` The following files exceed ${maxLines} lines:
|
|
8584
8688
|
`));
|
|
8585
8689
|
for (const violation of violations) {
|
|
8586
|
-
console.error(
|
|
8690
|
+
console.error(chalk111.red(` ${violation.file} (${violation.lines} lines)`));
|
|
8587
8691
|
}
|
|
8588
8692
|
console.error(
|
|
8589
|
-
|
|
8693
|
+
chalk111.yellow(
|
|
8590
8694
|
`
|
|
8591
8695
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
8592
8696
|
way to refactor it, ignore it with:
|
|
8593
8697
|
`
|
|
8594
8698
|
)
|
|
8595
8699
|
);
|
|
8596
|
-
console.error(
|
|
8700
|
+
console.error(chalk111.gray(` assist refactor ignore <file>
|
|
8597
8701
|
`));
|
|
8598
8702
|
if (process.env.CLAUDECODE) {
|
|
8599
|
-
console.error(
|
|
8703
|
+
console.error(chalk111.cyan(`
|
|
8600
8704
|
## Extracting Code to New Files
|
|
8601
8705
|
`));
|
|
8602
8706
|
console.error(
|
|
8603
|
-
|
|
8707
|
+
chalk111.cyan(
|
|
8604
8708
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
8605
8709
|
`
|
|
8606
8710
|
)
|
|
8607
8711
|
);
|
|
8608
8712
|
console.error(
|
|
8609
|
-
|
|
8713
|
+
chalk111.cyan(
|
|
8610
8714
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
8611
8715
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
8612
8716
|
`
|
|
8613
8717
|
)
|
|
8614
8718
|
);
|
|
8615
8719
|
console.error(
|
|
8616
|
-
|
|
8720
|
+
chalk111.cyan(
|
|
8617
8721
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
8618
8722
|
domains, move it to a common/shared folder.
|
|
8619
8723
|
`
|
|
@@ -8711,7 +8815,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
|
|
|
8711
8815
|
|
|
8712
8816
|
// src/commands/refactor/check/index.ts
|
|
8713
8817
|
function runScript(script, cwd) {
|
|
8714
|
-
return new Promise((
|
|
8818
|
+
return new Promise((resolve8) => {
|
|
8715
8819
|
const child = spawn4("npm", ["run", script], {
|
|
8716
8820
|
stdio: "pipe",
|
|
8717
8821
|
shell: true,
|
|
@@ -8725,7 +8829,7 @@ function runScript(script, cwd) {
|
|
|
8725
8829
|
output += data.toString();
|
|
8726
8830
|
});
|
|
8727
8831
|
child.on("close", (code) => {
|
|
8728
|
-
|
|
8832
|
+
resolve8({ script, code: code ?? 1, output });
|
|
8729
8833
|
});
|
|
8730
8834
|
});
|
|
8731
8835
|
}
|
|
@@ -8769,7 +8873,7 @@ async function check(pattern2, options2) {
|
|
|
8769
8873
|
|
|
8770
8874
|
// src/commands/refactor/extract/index.ts
|
|
8771
8875
|
import path33 from "path";
|
|
8772
|
-
import
|
|
8876
|
+
import chalk114 from "chalk";
|
|
8773
8877
|
|
|
8774
8878
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
8775
8879
|
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
@@ -9316,23 +9420,23 @@ function buildPlan(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
9316
9420
|
|
|
9317
9421
|
// src/commands/refactor/extract/displayPlan.ts
|
|
9318
9422
|
import path31 from "path";
|
|
9319
|
-
import
|
|
9423
|
+
import chalk112 from "chalk";
|
|
9320
9424
|
function section(title) {
|
|
9321
9425
|
return `
|
|
9322
|
-
${
|
|
9426
|
+
${chalk112.cyan(title)}`;
|
|
9323
9427
|
}
|
|
9324
9428
|
function displayImporters(plan2, cwd) {
|
|
9325
9429
|
if (plan2.importersToUpdate.length === 0) return;
|
|
9326
9430
|
console.log(section("Update importers:"));
|
|
9327
9431
|
for (const imp of plan2.importersToUpdate) {
|
|
9328
9432
|
const rel = path31.relative(cwd, imp.file.getFilePath());
|
|
9329
|
-
console.log(` ${
|
|
9433
|
+
console.log(` ${chalk112.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
9330
9434
|
}
|
|
9331
9435
|
}
|
|
9332
9436
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
9333
|
-
console.log(
|
|
9437
|
+
console.log(chalk112.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
9334
9438
|
`));
|
|
9335
|
-
console.log(` ${
|
|
9439
|
+
console.log(` ${chalk112.cyan("Functions to move:")}`);
|
|
9336
9440
|
for (const name of plan2.extractedNames) {
|
|
9337
9441
|
console.log(` ${name}`);
|
|
9338
9442
|
}
|
|
@@ -9367,7 +9471,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
9367
9471
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
9368
9472
|
import fs17 from "fs";
|
|
9369
9473
|
import path32 from "path";
|
|
9370
|
-
import
|
|
9474
|
+
import chalk113 from "chalk";
|
|
9371
9475
|
import { Project as Project2 } from "ts-morph";
|
|
9372
9476
|
function findTsConfig(sourcePath) {
|
|
9373
9477
|
const rootConfig = path32.resolve("tsconfig.json");
|
|
@@ -9398,7 +9502,7 @@ function loadProjectFile(file) {
|
|
|
9398
9502
|
});
|
|
9399
9503
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
9400
9504
|
if (!sourceFile) {
|
|
9401
|
-
console.log(
|
|
9505
|
+
console.log(chalk113.red(`File not found in project: ${file}`));
|
|
9402
9506
|
process.exit(1);
|
|
9403
9507
|
}
|
|
9404
9508
|
return { project, sourceFile };
|
|
@@ -9421,19 +9525,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
9421
9525
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
9422
9526
|
if (options2.apply) {
|
|
9423
9527
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
9424
|
-
console.log(
|
|
9528
|
+
console.log(chalk114.green("\nExtraction complete"));
|
|
9425
9529
|
} else {
|
|
9426
|
-
console.log(
|
|
9530
|
+
console.log(chalk114.dim("\nDry run. Use --apply to execute."));
|
|
9427
9531
|
}
|
|
9428
9532
|
}
|
|
9429
9533
|
|
|
9430
9534
|
// src/commands/refactor/ignore.ts
|
|
9431
9535
|
import fs18 from "fs";
|
|
9432
|
-
import
|
|
9536
|
+
import chalk115 from "chalk";
|
|
9433
9537
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
9434
9538
|
function ignore(file) {
|
|
9435
9539
|
if (!fs18.existsSync(file)) {
|
|
9436
|
-
console.error(
|
|
9540
|
+
console.error(chalk115.red(`Error: File does not exist: ${file}`));
|
|
9437
9541
|
process.exit(1);
|
|
9438
9542
|
}
|
|
9439
9543
|
const content = fs18.readFileSync(file, "utf-8");
|
|
@@ -9449,7 +9553,7 @@ function ignore(file) {
|
|
|
9449
9553
|
fs18.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
9450
9554
|
}
|
|
9451
9555
|
console.log(
|
|
9452
|
-
|
|
9556
|
+
chalk115.green(
|
|
9453
9557
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
9454
9558
|
)
|
|
9455
9559
|
);
|
|
@@ -9457,26 +9561,26 @@ function ignore(file) {
|
|
|
9457
9561
|
|
|
9458
9562
|
// src/commands/refactor/rename/index.ts
|
|
9459
9563
|
import path34 from "path";
|
|
9460
|
-
import
|
|
9564
|
+
import chalk116 from "chalk";
|
|
9461
9565
|
async function rename(source, destination, options2 = {}) {
|
|
9462
9566
|
const destPath = path34.resolve(destination);
|
|
9463
9567
|
const cwd = process.cwd();
|
|
9464
9568
|
const relSource = path34.relative(cwd, path34.resolve(source));
|
|
9465
9569
|
const relDest = path34.relative(cwd, destPath);
|
|
9466
9570
|
const { project, sourceFile } = loadProjectFile(source);
|
|
9467
|
-
console.log(
|
|
9571
|
+
console.log(chalk116.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
9468
9572
|
if (options2.apply) {
|
|
9469
9573
|
sourceFile.move(destPath);
|
|
9470
9574
|
await project.save();
|
|
9471
|
-
console.log(
|
|
9575
|
+
console.log(chalk116.green("Done"));
|
|
9472
9576
|
} else {
|
|
9473
|
-
console.log(
|
|
9577
|
+
console.log(chalk116.dim("Dry run. Use --apply to execute."));
|
|
9474
9578
|
}
|
|
9475
9579
|
}
|
|
9476
9580
|
|
|
9477
9581
|
// src/commands/refactor/renameSymbol/index.ts
|
|
9478
9582
|
import path36 from "path";
|
|
9479
|
-
import
|
|
9583
|
+
import chalk117 from "chalk";
|
|
9480
9584
|
import { Project as Project3 } from "ts-morph";
|
|
9481
9585
|
|
|
9482
9586
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
@@ -9525,38 +9629,38 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
9525
9629
|
const project = new Project3({ tsConfigFilePath: tsConfigPath });
|
|
9526
9630
|
const sourceFile = project.getSourceFile(filePath);
|
|
9527
9631
|
if (!sourceFile) {
|
|
9528
|
-
console.log(
|
|
9632
|
+
console.log(chalk117.red(`File not found in project: ${file}`));
|
|
9529
9633
|
process.exit(1);
|
|
9530
9634
|
}
|
|
9531
9635
|
const symbol = findSymbol(sourceFile, oldName);
|
|
9532
9636
|
if (!symbol) {
|
|
9533
|
-
console.log(
|
|
9637
|
+
console.log(chalk117.red(`Symbol "${oldName}" not found in ${file}`));
|
|
9534
9638
|
process.exit(1);
|
|
9535
9639
|
}
|
|
9536
9640
|
const grouped = groupReferences(symbol, cwd);
|
|
9537
9641
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
9538
9642
|
console.log(
|
|
9539
|
-
|
|
9643
|
+
chalk117.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
9540
9644
|
`)
|
|
9541
9645
|
);
|
|
9542
9646
|
for (const [refFile, lines] of grouped) {
|
|
9543
9647
|
console.log(
|
|
9544
|
-
` ${
|
|
9648
|
+
` ${chalk117.dim(refFile)}: lines ${chalk117.cyan(lines.join(", "))}`
|
|
9545
9649
|
);
|
|
9546
9650
|
}
|
|
9547
9651
|
if (options2.apply) {
|
|
9548
9652
|
symbol.rename(newName);
|
|
9549
9653
|
await project.save();
|
|
9550
|
-
console.log(
|
|
9654
|
+
console.log(chalk117.green(`
|
|
9551
9655
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
9552
9656
|
} else {
|
|
9553
|
-
console.log(
|
|
9657
|
+
console.log(chalk117.dim("\nDry run. Use --apply to execute."));
|
|
9554
9658
|
}
|
|
9555
9659
|
}
|
|
9556
9660
|
|
|
9557
9661
|
// src/commands/refactor/restructure/index.ts
|
|
9558
9662
|
import path45 from "path";
|
|
9559
|
-
import
|
|
9663
|
+
import chalk120 from "chalk";
|
|
9560
9664
|
|
|
9561
9665
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
9562
9666
|
import path37 from "path";
|
|
@@ -9799,50 +9903,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
9799
9903
|
|
|
9800
9904
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
9801
9905
|
import path41 from "path";
|
|
9802
|
-
import
|
|
9906
|
+
import chalk118 from "chalk";
|
|
9803
9907
|
function relPath(filePath) {
|
|
9804
9908
|
return path41.relative(process.cwd(), filePath);
|
|
9805
9909
|
}
|
|
9806
9910
|
function displayMoves(plan2) {
|
|
9807
9911
|
if (plan2.moves.length === 0) return;
|
|
9808
|
-
console.log(
|
|
9912
|
+
console.log(chalk118.bold("\nFile moves:"));
|
|
9809
9913
|
for (const move of plan2.moves) {
|
|
9810
9914
|
console.log(
|
|
9811
|
-
` ${
|
|
9915
|
+
` ${chalk118.red(relPath(move.from))} \u2192 ${chalk118.green(relPath(move.to))}`
|
|
9812
9916
|
);
|
|
9813
|
-
console.log(
|
|
9917
|
+
console.log(chalk118.dim(` ${move.reason}`));
|
|
9814
9918
|
}
|
|
9815
9919
|
}
|
|
9816
9920
|
function displayRewrites(rewrites) {
|
|
9817
9921
|
if (rewrites.length === 0) return;
|
|
9818
9922
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
9819
|
-
console.log(
|
|
9923
|
+
console.log(chalk118.bold(`
|
|
9820
9924
|
Import rewrites (${affectedFiles.size} files):`));
|
|
9821
9925
|
for (const file of affectedFiles) {
|
|
9822
|
-
console.log(` ${
|
|
9926
|
+
console.log(` ${chalk118.cyan(relPath(file))}:`);
|
|
9823
9927
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
9824
9928
|
(r) => r.file === file
|
|
9825
9929
|
)) {
|
|
9826
9930
|
console.log(
|
|
9827
|
-
` ${
|
|
9931
|
+
` ${chalk118.red(`"${oldSpecifier}"`)} \u2192 ${chalk118.green(`"${newSpecifier}"`)}`
|
|
9828
9932
|
);
|
|
9829
9933
|
}
|
|
9830
9934
|
}
|
|
9831
9935
|
}
|
|
9832
9936
|
function displayPlan2(plan2) {
|
|
9833
9937
|
if (plan2.warnings.length > 0) {
|
|
9834
|
-
console.log(
|
|
9835
|
-
for (const w of plan2.warnings) console.log(
|
|
9938
|
+
console.log(chalk118.yellow("\nWarnings:"));
|
|
9939
|
+
for (const w of plan2.warnings) console.log(chalk118.yellow(` ${w}`));
|
|
9836
9940
|
}
|
|
9837
9941
|
if (plan2.newDirectories.length > 0) {
|
|
9838
|
-
console.log(
|
|
9942
|
+
console.log(chalk118.bold("\nNew directories:"));
|
|
9839
9943
|
for (const dir of plan2.newDirectories)
|
|
9840
|
-
console.log(
|
|
9944
|
+
console.log(chalk118.green(` ${dir}/`));
|
|
9841
9945
|
}
|
|
9842
9946
|
displayMoves(plan2);
|
|
9843
9947
|
displayRewrites(plan2.rewrites);
|
|
9844
9948
|
console.log(
|
|
9845
|
-
|
|
9949
|
+
chalk118.dim(
|
|
9846
9950
|
`
|
|
9847
9951
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
9848
9952
|
)
|
|
@@ -9852,18 +9956,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
9852
9956
|
// src/commands/refactor/restructure/executePlan.ts
|
|
9853
9957
|
import fs20 from "fs";
|
|
9854
9958
|
import path42 from "path";
|
|
9855
|
-
import
|
|
9959
|
+
import chalk119 from "chalk";
|
|
9856
9960
|
function executePlan(plan2) {
|
|
9857
9961
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
9858
9962
|
for (const [file, content] of updatedContents) {
|
|
9859
9963
|
fs20.writeFileSync(file, content, "utf-8");
|
|
9860
9964
|
console.log(
|
|
9861
|
-
|
|
9965
|
+
chalk119.cyan(` Rewrote imports in ${path42.relative(process.cwd(), file)}`)
|
|
9862
9966
|
);
|
|
9863
9967
|
}
|
|
9864
9968
|
for (const dir of plan2.newDirectories) {
|
|
9865
9969
|
fs20.mkdirSync(dir, { recursive: true });
|
|
9866
|
-
console.log(
|
|
9970
|
+
console.log(chalk119.green(` Created ${path42.relative(process.cwd(), dir)}/`));
|
|
9867
9971
|
}
|
|
9868
9972
|
for (const move of plan2.moves) {
|
|
9869
9973
|
const targetDir = path42.dirname(move.to);
|
|
@@ -9872,7 +9976,7 @@ function executePlan(plan2) {
|
|
|
9872
9976
|
}
|
|
9873
9977
|
fs20.renameSync(move.from, move.to);
|
|
9874
9978
|
console.log(
|
|
9875
|
-
|
|
9979
|
+
chalk119.white(
|
|
9876
9980
|
` Moved ${path42.relative(process.cwd(), move.from)} \u2192 ${path42.relative(process.cwd(), move.to)}`
|
|
9877
9981
|
)
|
|
9878
9982
|
);
|
|
@@ -9887,7 +9991,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
9887
9991
|
if (entries.length === 0) {
|
|
9888
9992
|
fs20.rmdirSync(dir);
|
|
9889
9993
|
console.log(
|
|
9890
|
-
|
|
9994
|
+
chalk119.dim(
|
|
9891
9995
|
` Removed empty directory ${path42.relative(process.cwd(), dir)}`
|
|
9892
9996
|
)
|
|
9893
9997
|
);
|
|
@@ -10020,22 +10124,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
10020
10124
|
const targetPattern = pattern2 ?? "src";
|
|
10021
10125
|
const files = findSourceFiles2(targetPattern);
|
|
10022
10126
|
if (files.length === 0) {
|
|
10023
|
-
console.log(
|
|
10127
|
+
console.log(chalk120.yellow("No files found matching pattern"));
|
|
10024
10128
|
return;
|
|
10025
10129
|
}
|
|
10026
10130
|
const tsConfigPath = path45.resolve("tsconfig.json");
|
|
10027
10131
|
const plan2 = buildPlan2(files, tsConfigPath);
|
|
10028
10132
|
if (plan2.moves.length === 0) {
|
|
10029
|
-
console.log(
|
|
10133
|
+
console.log(chalk120.green("No restructuring needed"));
|
|
10030
10134
|
return;
|
|
10031
10135
|
}
|
|
10032
10136
|
displayPlan2(plan2);
|
|
10033
10137
|
if (options2.apply) {
|
|
10034
|
-
console.log(
|
|
10138
|
+
console.log(chalk120.bold("\nApplying changes..."));
|
|
10035
10139
|
executePlan(plan2);
|
|
10036
|
-
console.log(
|
|
10140
|
+
console.log(chalk120.green("\nRestructuring complete"));
|
|
10037
10141
|
} else {
|
|
10038
|
-
console.log(
|
|
10142
|
+
console.log(chalk120.dim("\nDry run. Use --apply to execute."));
|
|
10039
10143
|
}
|
|
10040
10144
|
}
|
|
10041
10145
|
|
|
@@ -10075,7 +10179,7 @@ function registerRefactor(program2) {
|
|
|
10075
10179
|
}
|
|
10076
10180
|
|
|
10077
10181
|
// src/commands/seq/seqAuth.ts
|
|
10078
|
-
import
|
|
10182
|
+
import chalk122 from "chalk";
|
|
10079
10183
|
|
|
10080
10184
|
// src/commands/seq/loadConnections.ts
|
|
10081
10185
|
function loadConnections2() {
|
|
@@ -10104,11 +10208,11 @@ function setDefaultConnection(name) {
|
|
|
10104
10208
|
}
|
|
10105
10209
|
|
|
10106
10210
|
// src/commands/seq/promptConnection.ts
|
|
10107
|
-
import
|
|
10211
|
+
import chalk121 from "chalk";
|
|
10108
10212
|
async function promptConnection2(existingNames) {
|
|
10109
10213
|
const name = await promptInput("name", "Connection name:", "default");
|
|
10110
10214
|
if (existingNames.includes(name)) {
|
|
10111
|
-
console.error(
|
|
10215
|
+
console.error(chalk121.red(`Connection "${name}" already exists.`));
|
|
10112
10216
|
process.exit(1);
|
|
10113
10217
|
}
|
|
10114
10218
|
const url = await promptInput("url", "Seq URL:", "http://localhost:5341");
|
|
@@ -10120,16 +10224,16 @@ async function promptConnection2(existingNames) {
|
|
|
10120
10224
|
var seqAuth = createConnectionAuth({
|
|
10121
10225
|
load: loadConnections2,
|
|
10122
10226
|
save: saveConnections2,
|
|
10123
|
-
format: (c) => `${
|
|
10227
|
+
format: (c) => `${chalk122.bold(c.name)} ${c.url}`,
|
|
10124
10228
|
promptNew: promptConnection2,
|
|
10125
10229
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
10126
10230
|
});
|
|
10127
10231
|
|
|
10128
10232
|
// src/commands/seq/seqQuery.ts
|
|
10129
|
-
import
|
|
10233
|
+
import chalk126 from "chalk";
|
|
10130
10234
|
|
|
10131
10235
|
// src/commands/seq/fetchSeq.ts
|
|
10132
|
-
import
|
|
10236
|
+
import chalk123 from "chalk";
|
|
10133
10237
|
async function fetchSeq(conn, path50, params) {
|
|
10134
10238
|
const url = `${conn.url}${path50}?${params}`;
|
|
10135
10239
|
const response = await fetch(url, {
|
|
@@ -10140,7 +10244,7 @@ async function fetchSeq(conn, path50, params) {
|
|
|
10140
10244
|
});
|
|
10141
10245
|
if (!response.ok) {
|
|
10142
10246
|
const body = await response.text();
|
|
10143
|
-
console.error(
|
|
10247
|
+
console.error(chalk123.red(`Seq returned ${response.status}: ${body}`));
|
|
10144
10248
|
process.exit(1);
|
|
10145
10249
|
}
|
|
10146
10250
|
return response;
|
|
@@ -10193,23 +10297,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
10193
10297
|
}
|
|
10194
10298
|
|
|
10195
10299
|
// src/commands/seq/formatEvent.ts
|
|
10196
|
-
import
|
|
10300
|
+
import chalk124 from "chalk";
|
|
10197
10301
|
function levelColor(level) {
|
|
10198
10302
|
switch (level) {
|
|
10199
10303
|
case "Fatal":
|
|
10200
|
-
return
|
|
10304
|
+
return chalk124.bgRed.white;
|
|
10201
10305
|
case "Error":
|
|
10202
|
-
return
|
|
10306
|
+
return chalk124.red;
|
|
10203
10307
|
case "Warning":
|
|
10204
|
-
return
|
|
10308
|
+
return chalk124.yellow;
|
|
10205
10309
|
case "Information":
|
|
10206
|
-
return
|
|
10310
|
+
return chalk124.cyan;
|
|
10207
10311
|
case "Debug":
|
|
10208
|
-
return
|
|
10312
|
+
return chalk124.gray;
|
|
10209
10313
|
case "Verbose":
|
|
10210
|
-
return
|
|
10314
|
+
return chalk124.dim;
|
|
10211
10315
|
default:
|
|
10212
|
-
return
|
|
10316
|
+
return chalk124.white;
|
|
10213
10317
|
}
|
|
10214
10318
|
}
|
|
10215
10319
|
function levelAbbrev(level) {
|
|
@@ -10250,31 +10354,31 @@ function formatTimestamp(iso) {
|
|
|
10250
10354
|
function formatEvent(event) {
|
|
10251
10355
|
const color = levelColor(event.Level);
|
|
10252
10356
|
const abbrev = levelAbbrev(event.Level);
|
|
10253
|
-
const ts8 =
|
|
10357
|
+
const ts8 = chalk124.dim(formatTimestamp(event.Timestamp));
|
|
10254
10358
|
const msg = renderMessage(event);
|
|
10255
10359
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
10256
10360
|
if (event.Exception) {
|
|
10257
10361
|
for (const line of event.Exception.split("\n")) {
|
|
10258
|
-
lines.push(
|
|
10362
|
+
lines.push(chalk124.red(` ${line}`));
|
|
10259
10363
|
}
|
|
10260
10364
|
}
|
|
10261
10365
|
return lines.join("\n");
|
|
10262
10366
|
}
|
|
10263
10367
|
|
|
10264
10368
|
// src/commands/seq/resolveConnection.ts
|
|
10265
|
-
import
|
|
10369
|
+
import chalk125 from "chalk";
|
|
10266
10370
|
function resolveConnection2(name) {
|
|
10267
10371
|
const connections = loadConnections2();
|
|
10268
10372
|
if (connections.length === 0) {
|
|
10269
10373
|
console.error(
|
|
10270
|
-
|
|
10374
|
+
chalk125.red("No Seq connections configured. Run 'assist seq auth' first.")
|
|
10271
10375
|
);
|
|
10272
10376
|
process.exit(1);
|
|
10273
10377
|
}
|
|
10274
10378
|
const target = name ?? getDefaultConnection() ?? connections[0].name;
|
|
10275
10379
|
const connection = connections.find((c) => c.name === target);
|
|
10276
10380
|
if (!connection) {
|
|
10277
|
-
console.error(
|
|
10381
|
+
console.error(chalk125.red(`Seq connection "${target}" not found.`));
|
|
10278
10382
|
process.exit(1);
|
|
10279
10383
|
}
|
|
10280
10384
|
return connection;
|
|
@@ -10289,7 +10393,7 @@ async function seqQuery(filter, options2) {
|
|
|
10289
10393
|
new URLSearchParams({ filter, count: String(count) })
|
|
10290
10394
|
);
|
|
10291
10395
|
if (events.length === 0) {
|
|
10292
|
-
console.log(
|
|
10396
|
+
console.log(chalk126.yellow("No events found."));
|
|
10293
10397
|
return;
|
|
10294
10398
|
}
|
|
10295
10399
|
if (options2.json) {
|
|
@@ -10300,11 +10404,11 @@ async function seqQuery(filter, options2) {
|
|
|
10300
10404
|
for (const event of chronological) {
|
|
10301
10405
|
console.log(formatEvent(event));
|
|
10302
10406
|
}
|
|
10303
|
-
console.log(
|
|
10407
|
+
console.log(chalk126.dim(`
|
|
10304
10408
|
${events.length} events`));
|
|
10305
10409
|
if (events.length >= count) {
|
|
10306
10410
|
console.log(
|
|
10307
|
-
|
|
10411
|
+
chalk126.yellow(
|
|
10308
10412
|
`Results limited to ${count}. Use --count to retrieve more.`
|
|
10309
10413
|
)
|
|
10310
10414
|
);
|
|
@@ -10312,11 +10416,11 @@ ${events.length} events`));
|
|
|
10312
10416
|
}
|
|
10313
10417
|
|
|
10314
10418
|
// src/commands/seq/seqSetConnection.ts
|
|
10315
|
-
import
|
|
10419
|
+
import chalk127 from "chalk";
|
|
10316
10420
|
function seqSetConnection(name) {
|
|
10317
10421
|
const connections = loadConnections2();
|
|
10318
10422
|
if (!connections.find((c) => c.name === name)) {
|
|
10319
|
-
console.error(
|
|
10423
|
+
console.error(chalk127.red(`Connection "${name}" not found.`));
|
|
10320
10424
|
process.exit(1);
|
|
10321
10425
|
}
|
|
10322
10426
|
setDefaultConnection(name);
|
|
@@ -10335,8 +10439,8 @@ function registerSeq(program2) {
|
|
|
10335
10439
|
}
|
|
10336
10440
|
|
|
10337
10441
|
// src/commands/transcript/shared.ts
|
|
10338
|
-
import { existsSync as
|
|
10339
|
-
import { basename as basename4, join as
|
|
10442
|
+
import { existsSync as existsSync31, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
10443
|
+
import { basename as basename4, join as join31, relative } from "path";
|
|
10340
10444
|
import * as readline2 from "readline";
|
|
10341
10445
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
10342
10446
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -10351,10 +10455,10 @@ function isValidDatePrefix(filename) {
|
|
|
10351
10455
|
return DATE_PREFIX_REGEX.test(filename);
|
|
10352
10456
|
}
|
|
10353
10457
|
function collectFiles(dir, extension) {
|
|
10354
|
-
if (!
|
|
10458
|
+
if (!existsSync31(dir)) return [];
|
|
10355
10459
|
const results = [];
|
|
10356
10460
|
for (const entry of readdirSync5(dir)) {
|
|
10357
|
-
const fullPath =
|
|
10461
|
+
const fullPath = join31(dir, entry);
|
|
10358
10462
|
if (statSync4(fullPath).isDirectory()) {
|
|
10359
10463
|
results.push(...collectFiles(fullPath, extension));
|
|
10360
10464
|
} else if (entry.endsWith(extension)) {
|
|
@@ -10386,9 +10490,9 @@ function createReadlineInterface() {
|
|
|
10386
10490
|
});
|
|
10387
10491
|
}
|
|
10388
10492
|
function askQuestion(rl, question) {
|
|
10389
|
-
return new Promise((
|
|
10493
|
+
return new Promise((resolve8) => {
|
|
10390
10494
|
rl.question(question, (answer) => {
|
|
10391
|
-
|
|
10495
|
+
resolve8(answer.trim());
|
|
10392
10496
|
});
|
|
10393
10497
|
});
|
|
10394
10498
|
}
|
|
@@ -10448,14 +10552,14 @@ async function configure() {
|
|
|
10448
10552
|
}
|
|
10449
10553
|
|
|
10450
10554
|
// src/commands/transcript/format/index.ts
|
|
10451
|
-
import { existsSync as
|
|
10555
|
+
import { existsSync as existsSync33 } from "fs";
|
|
10452
10556
|
|
|
10453
10557
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
10454
|
-
import { dirname as dirname18, join as
|
|
10558
|
+
import { dirname as dirname18, join as join33 } from "path";
|
|
10455
10559
|
|
|
10456
10560
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
10457
10561
|
import { renameSync as renameSync2 } from "fs";
|
|
10458
|
-
import { join as
|
|
10562
|
+
import { join as join32 } from "path";
|
|
10459
10563
|
async function resolveDate(rl, choice) {
|
|
10460
10564
|
if (choice === "1") return getDatePrefix(0);
|
|
10461
10565
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -10470,7 +10574,7 @@ async function resolveDate(rl, choice) {
|
|
|
10470
10574
|
}
|
|
10471
10575
|
function renameWithPrefix(vttDir, vttFile, prefix2) {
|
|
10472
10576
|
const newFilename = `${prefix2}.${vttFile}`;
|
|
10473
|
-
renameSync2(
|
|
10577
|
+
renameSync2(join32(vttDir, vttFile), join32(vttDir, newFilename));
|
|
10474
10578
|
console.log(`Renamed to: ${newFilename}`);
|
|
10475
10579
|
return newFilename;
|
|
10476
10580
|
}
|
|
@@ -10504,12 +10608,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
10504
10608
|
const vttFileDir = dirname18(vttFile.absolutePath);
|
|
10505
10609
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
10506
10610
|
if (newFilename) {
|
|
10507
|
-
const newRelativePath =
|
|
10611
|
+
const newRelativePath = join33(
|
|
10508
10612
|
dirname18(vttFile.relativePath),
|
|
10509
10613
|
newFilename
|
|
10510
10614
|
);
|
|
10511
10615
|
vttFiles[i] = {
|
|
10512
|
-
absolutePath:
|
|
10616
|
+
absolutePath: join33(vttFileDir, newFilename),
|
|
10513
10617
|
relativePath: newRelativePath,
|
|
10514
10618
|
filename: newFilename
|
|
10515
10619
|
};
|
|
@@ -10522,8 +10626,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
10522
10626
|
}
|
|
10523
10627
|
|
|
10524
10628
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
10525
|
-
import { existsSync as
|
|
10526
|
-
import { basename as basename5, dirname as dirname19, join as
|
|
10629
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync8, readFileSync as readFileSync27, writeFileSync as writeFileSync25 } from "fs";
|
|
10630
|
+
import { basename as basename5, dirname as dirname19, join as join34 } from "path";
|
|
10527
10631
|
|
|
10528
10632
|
// src/commands/transcript/cleanText.ts
|
|
10529
10633
|
function cleanText(text) {
|
|
@@ -10733,21 +10837,21 @@ function toMdFilename(vttFilename) {
|
|
|
10733
10837
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
10734
10838
|
}
|
|
10735
10839
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
10736
|
-
return relativeDir === "." ? transcriptsDir :
|
|
10840
|
+
return relativeDir === "." ? transcriptsDir : join34(transcriptsDir, relativeDir);
|
|
10737
10841
|
}
|
|
10738
10842
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
10739
10843
|
const mdFile = toMdFilename(vttFile.filename);
|
|
10740
10844
|
const relativeDir = dirname19(vttFile.relativePath);
|
|
10741
10845
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
10742
|
-
const outputPath =
|
|
10846
|
+
const outputPath = join34(outputDir, mdFile);
|
|
10743
10847
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
10744
10848
|
}
|
|
10745
10849
|
function logSkipped(relativeDir, mdFile) {
|
|
10746
|
-
console.log(`Skipping (already exists): ${
|
|
10850
|
+
console.log(`Skipping (already exists): ${join34(relativeDir, mdFile)}`);
|
|
10747
10851
|
return "skipped";
|
|
10748
10852
|
}
|
|
10749
10853
|
function ensureDirectory(dir, label2) {
|
|
10750
|
-
if (!
|
|
10854
|
+
if (!existsSync32(dir)) {
|
|
10751
10855
|
mkdirSync8(dir, { recursive: true });
|
|
10752
10856
|
console.log(`Created ${label2}: ${dir}`);
|
|
10753
10857
|
}
|
|
@@ -10783,7 +10887,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
10783
10887
|
logReduction(cues.length, chatMessages.length);
|
|
10784
10888
|
}
|
|
10785
10889
|
function tryProcessVtt(vttFile, paths) {
|
|
10786
|
-
if (
|
|
10890
|
+
if (existsSync32(paths.outputPath))
|
|
10787
10891
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
10788
10892
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
10789
10893
|
return "processed";
|
|
@@ -10809,7 +10913,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
10809
10913
|
logSummary(counts);
|
|
10810
10914
|
}
|
|
10811
10915
|
function requireVttDir(vttDir) {
|
|
10812
|
-
if (!
|
|
10916
|
+
if (!existsSync33(vttDir)) {
|
|
10813
10917
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
10814
10918
|
process.exit(1);
|
|
10815
10919
|
}
|
|
@@ -10841,28 +10945,28 @@ async function format() {
|
|
|
10841
10945
|
}
|
|
10842
10946
|
|
|
10843
10947
|
// src/commands/transcript/summarise/index.ts
|
|
10844
|
-
import { existsSync as
|
|
10845
|
-
import { basename as basename6, dirname as dirname21, join as
|
|
10948
|
+
import { existsSync as existsSync35 } from "fs";
|
|
10949
|
+
import { basename as basename6, dirname as dirname21, join as join36, relative as relative2 } from "path";
|
|
10846
10950
|
|
|
10847
10951
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
10848
10952
|
import {
|
|
10849
|
-
existsSync as
|
|
10953
|
+
existsSync as existsSync34,
|
|
10850
10954
|
mkdirSync as mkdirSync9,
|
|
10851
10955
|
readFileSync as readFileSync28,
|
|
10852
10956
|
renameSync as renameSync3,
|
|
10853
10957
|
rmSync
|
|
10854
10958
|
} from "fs";
|
|
10855
|
-
import { dirname as dirname20, join as
|
|
10959
|
+
import { dirname as dirname20, join as join35 } from "path";
|
|
10856
10960
|
|
|
10857
10961
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
10858
|
-
import
|
|
10962
|
+
import chalk128 from "chalk";
|
|
10859
10963
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
10860
10964
|
function validateStagedContent(filename, content) {
|
|
10861
10965
|
const firstLine = content.split("\n")[0];
|
|
10862
10966
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
10863
10967
|
if (!match) {
|
|
10864
10968
|
console.error(
|
|
10865
|
-
|
|
10969
|
+
chalk128.red(
|
|
10866
10970
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
10867
10971
|
)
|
|
10868
10972
|
);
|
|
@@ -10871,7 +10975,7 @@ function validateStagedContent(filename, content) {
|
|
|
10871
10975
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
10872
10976
|
if (!contentAfterLink) {
|
|
10873
10977
|
console.error(
|
|
10874
|
-
|
|
10978
|
+
chalk128.red(
|
|
10875
10979
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
10876
10980
|
)
|
|
10877
10981
|
);
|
|
@@ -10881,9 +10985,9 @@ function validateStagedContent(filename, content) {
|
|
|
10881
10985
|
}
|
|
10882
10986
|
|
|
10883
10987
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
10884
|
-
var STAGING_DIR =
|
|
10988
|
+
var STAGING_DIR = join35(process.cwd(), ".assist", "transcript");
|
|
10885
10989
|
function processStagedFile() {
|
|
10886
|
-
if (!
|
|
10990
|
+
if (!existsSync34(STAGING_DIR)) {
|
|
10887
10991
|
return false;
|
|
10888
10992
|
}
|
|
10889
10993
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -10905,9 +11009,9 @@ function processStagedFile() {
|
|
|
10905
11009
|
);
|
|
10906
11010
|
process.exit(1);
|
|
10907
11011
|
}
|
|
10908
|
-
const destPath =
|
|
11012
|
+
const destPath = join35(summaryDir, matchingTranscript.relativePath);
|
|
10909
11013
|
const destDir = dirname20(destPath);
|
|
10910
|
-
if (!
|
|
11014
|
+
if (!existsSync34(destDir)) {
|
|
10911
11015
|
mkdirSync9(destDir, { recursive: true });
|
|
10912
11016
|
}
|
|
10913
11017
|
renameSync3(stagedFile.absolutePath, destPath);
|
|
@@ -10921,7 +11025,7 @@ function processStagedFile() {
|
|
|
10921
11025
|
// src/commands/transcript/summarise/index.ts
|
|
10922
11026
|
function buildRelativeKey(relativePath, baseName) {
|
|
10923
11027
|
const relDir = dirname21(relativePath);
|
|
10924
|
-
return relDir === "." ? baseName :
|
|
11028
|
+
return relDir === "." ? baseName : join36(relDir, baseName);
|
|
10925
11029
|
}
|
|
10926
11030
|
function buildSummaryIndex(summaryDir) {
|
|
10927
11031
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -10934,7 +11038,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
10934
11038
|
function summarise2() {
|
|
10935
11039
|
processStagedFile();
|
|
10936
11040
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
10937
|
-
if (!
|
|
11041
|
+
if (!existsSync35(transcriptsDir)) {
|
|
10938
11042
|
console.log("No transcripts directory found.");
|
|
10939
11043
|
return;
|
|
10940
11044
|
}
|
|
@@ -10955,8 +11059,8 @@ function summarise2() {
|
|
|
10955
11059
|
}
|
|
10956
11060
|
const next3 = missing[0];
|
|
10957
11061
|
const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
|
|
10958
|
-
const outputPath =
|
|
10959
|
-
const summaryFileDir =
|
|
11062
|
+
const outputPath = join36(STAGING_DIR, outputFilename);
|
|
11063
|
+
const summaryFileDir = join36(summaryDir, dirname21(next3.relativePath));
|
|
10960
11064
|
const relativeTranscriptPath = encodeURI(
|
|
10961
11065
|
relative2(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
|
|
10962
11066
|
);
|
|
@@ -11002,45 +11106,45 @@ function registerVerify(program2) {
|
|
|
11002
11106
|
|
|
11003
11107
|
// src/commands/voice/devices.ts
|
|
11004
11108
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
11005
|
-
import { join as
|
|
11109
|
+
import { join as join38 } from "path";
|
|
11006
11110
|
|
|
11007
11111
|
// src/commands/voice/shared.ts
|
|
11008
11112
|
import { homedir as homedir7 } from "os";
|
|
11009
|
-
import { dirname as dirname22, join as
|
|
11113
|
+
import { dirname as dirname22, join as join37 } from "path";
|
|
11010
11114
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
11011
11115
|
var __dirname6 = dirname22(fileURLToPath6(import.meta.url));
|
|
11012
|
-
var VOICE_DIR =
|
|
11116
|
+
var VOICE_DIR = join37(homedir7(), ".assist", "voice");
|
|
11013
11117
|
var voicePaths = {
|
|
11014
11118
|
dir: VOICE_DIR,
|
|
11015
|
-
pid:
|
|
11016
|
-
log:
|
|
11017
|
-
venv:
|
|
11018
|
-
lock:
|
|
11119
|
+
pid: join37(VOICE_DIR, "voice.pid"),
|
|
11120
|
+
log: join37(VOICE_DIR, "voice.log"),
|
|
11121
|
+
venv: join37(VOICE_DIR, ".venv"),
|
|
11122
|
+
lock: join37(VOICE_DIR, "voice.lock")
|
|
11019
11123
|
};
|
|
11020
11124
|
function getPythonDir() {
|
|
11021
|
-
return
|
|
11125
|
+
return join37(__dirname6, "commands", "voice", "python");
|
|
11022
11126
|
}
|
|
11023
11127
|
function getVenvPython() {
|
|
11024
|
-
return process.platform === "win32" ?
|
|
11128
|
+
return process.platform === "win32" ? join37(voicePaths.venv, "Scripts", "python.exe") : join37(voicePaths.venv, "bin", "python");
|
|
11025
11129
|
}
|
|
11026
11130
|
function getLockDir() {
|
|
11027
11131
|
const config = loadConfig();
|
|
11028
11132
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
11029
11133
|
}
|
|
11030
11134
|
function getLockFile() {
|
|
11031
|
-
return
|
|
11135
|
+
return join37(getLockDir(), "voice.lock");
|
|
11032
11136
|
}
|
|
11033
11137
|
|
|
11034
11138
|
// src/commands/voice/devices.ts
|
|
11035
11139
|
function devices() {
|
|
11036
|
-
const script =
|
|
11140
|
+
const script = join38(getPythonDir(), "list_devices.py");
|
|
11037
11141
|
spawnSync3(getVenvPython(), [script], { stdio: "inherit" });
|
|
11038
11142
|
}
|
|
11039
11143
|
|
|
11040
11144
|
// src/commands/voice/logs.ts
|
|
11041
|
-
import { existsSync as
|
|
11145
|
+
import { existsSync as existsSync36, readFileSync as readFileSync29 } from "fs";
|
|
11042
11146
|
function logs(options2) {
|
|
11043
|
-
if (!
|
|
11147
|
+
if (!existsSync36(voicePaths.log)) {
|
|
11044
11148
|
console.log("No voice log file found");
|
|
11045
11149
|
return;
|
|
11046
11150
|
}
|
|
@@ -11068,12 +11172,12 @@ function logs(options2) {
|
|
|
11068
11172
|
// src/commands/voice/setup.ts
|
|
11069
11173
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
11070
11174
|
import { mkdirSync as mkdirSync11 } from "fs";
|
|
11071
|
-
import { join as
|
|
11175
|
+
import { join as join40 } from "path";
|
|
11072
11176
|
|
|
11073
11177
|
// src/commands/voice/checkLockFile.ts
|
|
11074
11178
|
import { execSync as execSync38 } from "child_process";
|
|
11075
|
-
import { existsSync as
|
|
11076
|
-
import { join as
|
|
11179
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync10, readFileSync as readFileSync30, writeFileSync as writeFileSync26 } from "fs";
|
|
11180
|
+
import { join as join39 } from "path";
|
|
11077
11181
|
function isProcessAlive2(pid) {
|
|
11078
11182
|
try {
|
|
11079
11183
|
process.kill(pid, 0);
|
|
@@ -11084,7 +11188,7 @@ function isProcessAlive2(pid) {
|
|
|
11084
11188
|
}
|
|
11085
11189
|
function checkLockFile() {
|
|
11086
11190
|
const lockFile = getLockFile();
|
|
11087
|
-
if (!
|
|
11191
|
+
if (!existsSync37(lockFile)) return;
|
|
11088
11192
|
try {
|
|
11089
11193
|
const lock = JSON.parse(readFileSync30(lockFile, "utf-8"));
|
|
11090
11194
|
if (lock.pid && isProcessAlive2(lock.pid)) {
|
|
@@ -11097,7 +11201,7 @@ function checkLockFile() {
|
|
|
11097
11201
|
}
|
|
11098
11202
|
}
|
|
11099
11203
|
function bootstrapVenv() {
|
|
11100
|
-
if (
|
|
11204
|
+
if (existsSync37(getVenvPython())) return;
|
|
11101
11205
|
console.log("Setting up Python environment...");
|
|
11102
11206
|
const pythonDir = getPythonDir();
|
|
11103
11207
|
execSync38(
|
|
@@ -11110,7 +11214,7 @@ function bootstrapVenv() {
|
|
|
11110
11214
|
}
|
|
11111
11215
|
function writeLockFile(pid) {
|
|
11112
11216
|
const lockFile = getLockFile();
|
|
11113
|
-
mkdirSync10(
|
|
11217
|
+
mkdirSync10(join39(lockFile, ".."), { recursive: true });
|
|
11114
11218
|
writeFileSync26(
|
|
11115
11219
|
lockFile,
|
|
11116
11220
|
JSON.stringify({
|
|
@@ -11126,7 +11230,7 @@ function setup() {
|
|
|
11126
11230
|
mkdirSync11(voicePaths.dir, { recursive: true });
|
|
11127
11231
|
bootstrapVenv();
|
|
11128
11232
|
console.log("\nDownloading models...\n");
|
|
11129
|
-
const script =
|
|
11233
|
+
const script = join40(getPythonDir(), "setup_models.py");
|
|
11130
11234
|
const result = spawnSync4(getVenvPython(), [script], {
|
|
11131
11235
|
stdio: "inherit",
|
|
11132
11236
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -11140,7 +11244,7 @@ function setup() {
|
|
|
11140
11244
|
// src/commands/voice/start.ts
|
|
11141
11245
|
import { spawn as spawn5 } from "child_process";
|
|
11142
11246
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync27 } from "fs";
|
|
11143
|
-
import { join as
|
|
11247
|
+
import { join as join41 } from "path";
|
|
11144
11248
|
|
|
11145
11249
|
// src/commands/voice/buildDaemonEnv.ts
|
|
11146
11250
|
function buildDaemonEnv(options2) {
|
|
@@ -11178,7 +11282,7 @@ function start2(options2) {
|
|
|
11178
11282
|
bootstrapVenv();
|
|
11179
11283
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
11180
11284
|
const env = buildDaemonEnv({ debug });
|
|
11181
|
-
const script =
|
|
11285
|
+
const script = join41(getPythonDir(), "voice_daemon.py");
|
|
11182
11286
|
const python = getVenvPython();
|
|
11183
11287
|
if (options2.foreground) {
|
|
11184
11288
|
spawnForeground(python, script, env);
|
|
@@ -11188,7 +11292,7 @@ function start2(options2) {
|
|
|
11188
11292
|
}
|
|
11189
11293
|
|
|
11190
11294
|
// src/commands/voice/status.ts
|
|
11191
|
-
import { existsSync as
|
|
11295
|
+
import { existsSync as existsSync38, readFileSync as readFileSync31 } from "fs";
|
|
11192
11296
|
function isProcessAlive3(pid) {
|
|
11193
11297
|
try {
|
|
11194
11298
|
process.kill(pid, 0);
|
|
@@ -11198,12 +11302,12 @@ function isProcessAlive3(pid) {
|
|
|
11198
11302
|
}
|
|
11199
11303
|
}
|
|
11200
11304
|
function readRecentLogs(count) {
|
|
11201
|
-
if (!
|
|
11305
|
+
if (!existsSync38(voicePaths.log)) return [];
|
|
11202
11306
|
const lines = readFileSync31(voicePaths.log, "utf-8").trim().split("\n");
|
|
11203
11307
|
return lines.slice(-count);
|
|
11204
11308
|
}
|
|
11205
11309
|
function status() {
|
|
11206
|
-
if (!
|
|
11310
|
+
if (!existsSync38(voicePaths.pid)) {
|
|
11207
11311
|
console.log("Voice daemon: not running (no PID file)");
|
|
11208
11312
|
return;
|
|
11209
11313
|
}
|
|
@@ -11226,9 +11330,9 @@ function status() {
|
|
|
11226
11330
|
}
|
|
11227
11331
|
|
|
11228
11332
|
// src/commands/voice/stop.ts
|
|
11229
|
-
import { existsSync as
|
|
11333
|
+
import { existsSync as existsSync39, readFileSync as readFileSync32, unlinkSync as unlinkSync10 } from "fs";
|
|
11230
11334
|
function stop() {
|
|
11231
|
-
if (!
|
|
11335
|
+
if (!existsSync39(voicePaths.pid)) {
|
|
11232
11336
|
console.log("Voice daemon is not running (no PID file)");
|
|
11233
11337
|
return;
|
|
11234
11338
|
}
|
|
@@ -11245,7 +11349,7 @@ function stop() {
|
|
|
11245
11349
|
}
|
|
11246
11350
|
try {
|
|
11247
11351
|
const lockFile = getLockFile();
|
|
11248
|
-
if (
|
|
11352
|
+
if (existsSync39(lockFile)) unlinkSync10(lockFile);
|
|
11249
11353
|
} catch {
|
|
11250
11354
|
}
|
|
11251
11355
|
console.log("Voice daemon stopped");
|
|
@@ -11264,7 +11368,7 @@ function registerVoice(program2) {
|
|
|
11264
11368
|
|
|
11265
11369
|
// src/commands/roam/auth.ts
|
|
11266
11370
|
import { randomBytes } from "crypto";
|
|
11267
|
-
import
|
|
11371
|
+
import chalk129 from "chalk";
|
|
11268
11372
|
|
|
11269
11373
|
// src/lib/openBrowser.ts
|
|
11270
11374
|
import { execSync as execSync39 } from "child_process";
|
|
@@ -11329,7 +11433,7 @@ function extractCode(url, expectedState) {
|
|
|
11329
11433
|
return code;
|
|
11330
11434
|
}
|
|
11331
11435
|
function waitForCallback(port, expectedState) {
|
|
11332
|
-
return new Promise((
|
|
11436
|
+
return new Promise((resolve8, reject) => {
|
|
11333
11437
|
const timeout = setTimeout(() => {
|
|
11334
11438
|
server.close();
|
|
11335
11439
|
reject(new Error("Authorization timed out after 120 seconds"));
|
|
@@ -11346,7 +11450,7 @@ function waitForCallback(port, expectedState) {
|
|
|
11346
11450
|
const code = extractCode(url, expectedState);
|
|
11347
11451
|
respondHtml(res, 200, "Authorization successful!");
|
|
11348
11452
|
server.close();
|
|
11349
|
-
|
|
11453
|
+
resolve8(code);
|
|
11350
11454
|
} catch (err) {
|
|
11351
11455
|
respondHtml(res, 400, err.message);
|
|
11352
11456
|
server.close();
|
|
@@ -11439,13 +11543,13 @@ async function auth() {
|
|
|
11439
11543
|
saveGlobalConfig(config);
|
|
11440
11544
|
const state = randomBytes(16).toString("hex");
|
|
11441
11545
|
console.log(
|
|
11442
|
-
|
|
11546
|
+
chalk129.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
11443
11547
|
);
|
|
11444
|
-
console.log(
|
|
11445
|
-
console.log(
|
|
11446
|
-
console.log(
|
|
11548
|
+
console.log(chalk129.white("http://localhost:14523/callback\n"));
|
|
11549
|
+
console.log(chalk129.blue("Opening browser for authorization..."));
|
|
11550
|
+
console.log(chalk129.dim("Waiting for authorization callback..."));
|
|
11447
11551
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
11448
|
-
console.log(
|
|
11552
|
+
console.log(chalk129.dim("Exchanging code for tokens..."));
|
|
11449
11553
|
const tokens = await exchangeToken({
|
|
11450
11554
|
code,
|
|
11451
11555
|
clientId,
|
|
@@ -11461,17 +11565,17 @@ async function auth() {
|
|
|
11461
11565
|
};
|
|
11462
11566
|
saveGlobalConfig(config);
|
|
11463
11567
|
console.log(
|
|
11464
|
-
|
|
11568
|
+
chalk129.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
11465
11569
|
);
|
|
11466
11570
|
}
|
|
11467
11571
|
|
|
11468
11572
|
// src/commands/roam/showClaudeCodeIcon.ts
|
|
11469
11573
|
import { readFileSync as readFileSync33 } from "fs";
|
|
11470
|
-
import { join as
|
|
11574
|
+
import { join as join42 } from "path";
|
|
11471
11575
|
async function showClaudeCodeIcon() {
|
|
11472
11576
|
const appData = process.env.APPDATA;
|
|
11473
11577
|
if (!appData) return;
|
|
11474
|
-
const portFile =
|
|
11578
|
+
const portFile = join42(appData, "Roam", "roam-local-api.port");
|
|
11475
11579
|
let port;
|
|
11476
11580
|
try {
|
|
11477
11581
|
port = readFileSync33(portFile, "utf-8").trim();
|
|
@@ -11497,7 +11601,7 @@ function registerRoam(program2) {
|
|
|
11497
11601
|
}
|
|
11498
11602
|
|
|
11499
11603
|
// src/commands/run/index.ts
|
|
11500
|
-
import {
|
|
11604
|
+
import { resolve as resolve5 } from "path";
|
|
11501
11605
|
|
|
11502
11606
|
// src/commands/run/formatConfiguredCommands.ts
|
|
11503
11607
|
function formatConfiguredCommands() {
|
|
@@ -11533,14 +11637,28 @@ function resolveParams(params, cliArgs) {
|
|
|
11533
11637
|
return resolved;
|
|
11534
11638
|
}
|
|
11535
11639
|
|
|
11640
|
+
// src/commands/run/runPreCommands.ts
|
|
11641
|
+
import { execSync as execSync40 } from "child_process";
|
|
11642
|
+
function runPreCommands(pre, cwd) {
|
|
11643
|
+
for (const cmd of pre) {
|
|
11644
|
+
try {
|
|
11645
|
+
execSync40(cmd, { stdio: "inherit", cwd });
|
|
11646
|
+
} catch (err) {
|
|
11647
|
+
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
11648
|
+
process.exit(code);
|
|
11649
|
+
}
|
|
11650
|
+
}
|
|
11651
|
+
}
|
|
11652
|
+
|
|
11536
11653
|
// src/commands/run/spawnRunCommand.ts
|
|
11537
11654
|
import { spawn as spawn6 } from "child_process";
|
|
11538
|
-
function spawnRunCommand(fullCommand, env) {
|
|
11655
|
+
function spawnRunCommand(fullCommand, env, cwd) {
|
|
11539
11656
|
const start3 = Date.now();
|
|
11540
11657
|
const child = spawn6(fullCommand, [], {
|
|
11541
11658
|
stdio: "inherit",
|
|
11542
11659
|
shell: true,
|
|
11543
|
-
env: env ? { ...process.env, ...expandEnv(env) } : void 0
|
|
11660
|
+
env: env ? { ...process.env, ...expandEnv(env) } : void 0,
|
|
11661
|
+
cwd
|
|
11544
11662
|
});
|
|
11545
11663
|
child.on("close", (code) => {
|
|
11546
11664
|
const elapsed = formatElapsed(Date.now() - start3);
|
|
@@ -11556,17 +11674,28 @@ Done in ${elapsed}`);
|
|
|
11556
11674
|
|
|
11557
11675
|
// src/commands/run/add.ts
|
|
11558
11676
|
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync28 } from "fs";
|
|
11559
|
-
import { join as
|
|
11677
|
+
import { join as join43 } from "path";
|
|
11560
11678
|
function findAddIndex() {
|
|
11561
11679
|
const addIndex = process.argv.indexOf("add");
|
|
11562
11680
|
if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
|
|
11563
11681
|
return addIndex;
|
|
11564
11682
|
}
|
|
11683
|
+
function extractOption(args, flag) {
|
|
11684
|
+
const index = args.indexOf(flag);
|
|
11685
|
+
if (index === -1) return { value: void 0, remaining: args };
|
|
11686
|
+
return {
|
|
11687
|
+
value: args[index + 1],
|
|
11688
|
+
remaining: [...args.slice(0, index), ...args.slice(index + 2)]
|
|
11689
|
+
};
|
|
11690
|
+
}
|
|
11565
11691
|
function extractAddArgs(addIndex) {
|
|
11692
|
+
const rawArgs = process.argv.slice(addIndex + 3);
|
|
11693
|
+
const { value: cwd, remaining: args } = extractOption(rawArgs, "--cwd");
|
|
11566
11694
|
return {
|
|
11567
11695
|
name: process.argv[addIndex + 1],
|
|
11568
11696
|
command: process.argv[addIndex + 2],
|
|
11569
|
-
args
|
|
11697
|
+
args,
|
|
11698
|
+
cwd
|
|
11570
11699
|
};
|
|
11571
11700
|
}
|
|
11572
11701
|
function parseAddArguments() {
|
|
@@ -11595,14 +11724,14 @@ function getOrInitRunList() {
|
|
|
11595
11724
|
if (!config.run) config.run = [];
|
|
11596
11725
|
return { config, runList: config.run };
|
|
11597
11726
|
}
|
|
11598
|
-
function saveNewRunConfig(name, command, args) {
|
|
11727
|
+
function saveNewRunConfig(name, command, args, cwd) {
|
|
11599
11728
|
const { config, runList } = getOrInitRunList();
|
|
11600
11729
|
ensureNoDuplicate(runList, name);
|
|
11601
|
-
runList.push(buildRunEntry(name, command, args));
|
|
11730
|
+
runList.push(buildRunEntry(name, command, args, { cwd }));
|
|
11602
11731
|
saveConfig(config);
|
|
11603
11732
|
}
|
|
11604
11733
|
function createCommandFile(name) {
|
|
11605
|
-
const dir =
|
|
11734
|
+
const dir = join43(".claude", "commands");
|
|
11606
11735
|
mkdirSync13(dir, { recursive: true });
|
|
11607
11736
|
const content = `---
|
|
11608
11737
|
description: Run ${name}
|
|
@@ -11610,13 +11739,13 @@ description: Run ${name}
|
|
|
11610
11739
|
|
|
11611
11740
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
11612
11741
|
`;
|
|
11613
|
-
const filePath =
|
|
11742
|
+
const filePath = join43(dir, `${name}.md`);
|
|
11614
11743
|
writeFileSync28(filePath, content);
|
|
11615
11744
|
console.log(`Created command file: ${filePath}`);
|
|
11616
11745
|
}
|
|
11617
11746
|
function add3() {
|
|
11618
|
-
const { name, command, args } = requireParsedArgs();
|
|
11619
|
-
saveNewRunConfig(name, command, args);
|
|
11747
|
+
const { name, command, args, cwd } = requireParsedArgs();
|
|
11748
|
+
saveNewRunConfig(name, command, args, cwd);
|
|
11620
11749
|
createCommandFile(name);
|
|
11621
11750
|
console.log(
|
|
11622
11751
|
`Added run configuration: ${name} -> ${formatDisplay(command, args)}`
|
|
@@ -11659,16 +11788,6 @@ function listRunConfigs() {
|
|
|
11659
11788
|
console.log(`${config.name}: ${config.command}${args}`);
|
|
11660
11789
|
}
|
|
11661
11790
|
}
|
|
11662
|
-
function runPreCommands(pre) {
|
|
11663
|
-
for (const cmd of pre) {
|
|
11664
|
-
try {
|
|
11665
|
-
execSync40(cmd, { stdio: "inherit" });
|
|
11666
|
-
} catch (err) {
|
|
11667
|
-
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
11668
|
-
process.exit(code);
|
|
11669
|
-
}
|
|
11670
|
-
}
|
|
11671
|
-
}
|
|
11672
11791
|
function run3(name, args) {
|
|
11673
11792
|
if (!name) {
|
|
11674
11793
|
console.error("error: missing required argument 'name'");
|
|
@@ -11676,20 +11795,22 @@ function run3(name, args) {
|
|
|
11676
11795
|
process.exit(1);
|
|
11677
11796
|
}
|
|
11678
11797
|
const runConfig = findRunConfig(name);
|
|
11679
|
-
|
|
11798
|
+
const resolvedCwd = runConfig.cwd ? resolve5(getConfigDir(), runConfig.cwd) : void 0;
|
|
11799
|
+
if (runConfig.pre) runPreCommands(runConfig.pre, resolvedCwd);
|
|
11680
11800
|
const resolved = resolveParams(runConfig.params, args);
|
|
11681
11801
|
spawnRunCommand(
|
|
11682
11802
|
buildCommand(runConfig.command, runConfig.args ?? [], resolved),
|
|
11683
|
-
runConfig.env
|
|
11803
|
+
runConfig.env,
|
|
11804
|
+
resolvedCwd
|
|
11684
11805
|
);
|
|
11685
11806
|
}
|
|
11686
11807
|
|
|
11687
11808
|
// src/commands/screenshot/index.ts
|
|
11688
11809
|
import { execSync as execSync41 } from "child_process";
|
|
11689
|
-
import { existsSync as
|
|
11810
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync14, unlinkSync as unlinkSync11, writeFileSync as writeFileSync29 } from "fs";
|
|
11690
11811
|
import { tmpdir as tmpdir6 } from "os";
|
|
11691
|
-
import { join as
|
|
11692
|
-
import
|
|
11812
|
+
import { join as join44, resolve as resolve6 } from "path";
|
|
11813
|
+
import chalk130 from "chalk";
|
|
11693
11814
|
|
|
11694
11815
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
11695
11816
|
var captureWindowPs1 = `
|
|
@@ -11818,14 +11939,14 @@ Write-Output $OutputPath
|
|
|
11818
11939
|
|
|
11819
11940
|
// src/commands/screenshot/index.ts
|
|
11820
11941
|
function buildOutputPath(outputDir, processName) {
|
|
11821
|
-
if (!
|
|
11942
|
+
if (!existsSync40(outputDir)) {
|
|
11822
11943
|
mkdirSync14(outputDir, { recursive: true });
|
|
11823
11944
|
}
|
|
11824
11945
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
11825
|
-
return
|
|
11946
|
+
return resolve6(outputDir, `${processName}-${timestamp}.png`);
|
|
11826
11947
|
}
|
|
11827
11948
|
function runPowerShellScript(processName, outputPath) {
|
|
11828
|
-
const scriptPath =
|
|
11949
|
+
const scriptPath = join44(tmpdir6(), `assist-screenshot-${Date.now()}.ps1`);
|
|
11829
11950
|
writeFileSync29(scriptPath, captureWindowPs1, "utf-8");
|
|
11830
11951
|
try {
|
|
11831
11952
|
execSync41(
|
|
@@ -11838,24 +11959,24 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
11838
11959
|
}
|
|
11839
11960
|
function screenshot(processName) {
|
|
11840
11961
|
const config = loadConfig();
|
|
11841
|
-
const outputDir =
|
|
11962
|
+
const outputDir = resolve6(config.screenshot.outputDir);
|
|
11842
11963
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
11843
|
-
console.log(
|
|
11964
|
+
console.log(chalk130.gray(`Capturing window for process "${processName}" ...`));
|
|
11844
11965
|
try {
|
|
11845
11966
|
runPowerShellScript(processName, outputPath);
|
|
11846
|
-
console.log(
|
|
11967
|
+
console.log(chalk130.green(`Screenshot saved: ${outputPath}`));
|
|
11847
11968
|
} catch (error) {
|
|
11848
11969
|
const msg = error instanceof Error ? error.message : String(error);
|
|
11849
|
-
console.error(
|
|
11970
|
+
console.error(chalk130.red(`Failed to capture screenshot: ${msg}`));
|
|
11850
11971
|
process.exit(1);
|
|
11851
11972
|
}
|
|
11852
11973
|
}
|
|
11853
11974
|
|
|
11854
11975
|
// src/commands/statusLine.ts
|
|
11855
|
-
import
|
|
11976
|
+
import chalk132 from "chalk";
|
|
11856
11977
|
|
|
11857
11978
|
// src/commands/buildLimitsSegment.ts
|
|
11858
|
-
import
|
|
11979
|
+
import chalk131 from "chalk";
|
|
11859
11980
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
11860
11981
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
11861
11982
|
function formatTimeLeft(resetsAt) {
|
|
@@ -11878,10 +11999,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
11878
11999
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
11879
12000
|
const label2 = `${Math.round(pct)}%`;
|
|
11880
12001
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
11881
|
-
if (projected == null) return
|
|
11882
|
-
if (projected > 100) return
|
|
11883
|
-
if (projected > 75) return
|
|
11884
|
-
return
|
|
12002
|
+
if (projected == null) return chalk131.green(label2);
|
|
12003
|
+
if (projected > 100) return chalk131.red(label2);
|
|
12004
|
+
if (projected > 75) return chalk131.yellow(label2);
|
|
12005
|
+
return chalk131.green(label2);
|
|
11885
12006
|
}
|
|
11886
12007
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
11887
12008
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -11907,14 +12028,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
11907
12028
|
}
|
|
11908
12029
|
|
|
11909
12030
|
// src/commands/statusLine.ts
|
|
11910
|
-
|
|
12031
|
+
chalk132.level = 3;
|
|
11911
12032
|
function formatNumber(num) {
|
|
11912
12033
|
return num.toLocaleString("en-US");
|
|
11913
12034
|
}
|
|
11914
12035
|
function colorizePercent(pct) {
|
|
11915
12036
|
const label2 = `${Math.round(pct)}%`;
|
|
11916
|
-
if (pct > 80) return
|
|
11917
|
-
if (pct > 40) return
|
|
12037
|
+
if (pct > 80) return chalk132.red(label2);
|
|
12038
|
+
if (pct > 40) return chalk132.yellow(label2);
|
|
11918
12039
|
return label2;
|
|
11919
12040
|
}
|
|
11920
12041
|
async function statusLine() {
|
|
@@ -11937,7 +12058,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
11937
12058
|
// src/commands/sync/syncClaudeMd.ts
|
|
11938
12059
|
import * as fs23 from "fs";
|
|
11939
12060
|
import * as path46 from "path";
|
|
11940
|
-
import
|
|
12061
|
+
import chalk133 from "chalk";
|
|
11941
12062
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
11942
12063
|
const source = path46.join(claudeDir, "CLAUDE.md");
|
|
11943
12064
|
const target = path46.join(targetBase, "CLAUDE.md");
|
|
@@ -11946,12 +12067,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11946
12067
|
const targetContent = fs23.readFileSync(target, "utf-8");
|
|
11947
12068
|
if (sourceContent !== targetContent) {
|
|
11948
12069
|
console.log(
|
|
11949
|
-
|
|
12070
|
+
chalk133.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
11950
12071
|
);
|
|
11951
12072
|
console.log();
|
|
11952
12073
|
printDiff(targetContent, sourceContent);
|
|
11953
12074
|
const confirm = options2?.yes || await promptConfirm(
|
|
11954
|
-
|
|
12075
|
+
chalk133.red("Overwrite existing CLAUDE.md?"),
|
|
11955
12076
|
false
|
|
11956
12077
|
);
|
|
11957
12078
|
if (!confirm) {
|
|
@@ -11967,7 +12088,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
11967
12088
|
// src/commands/sync/syncSettings.ts
|
|
11968
12089
|
import * as fs24 from "fs";
|
|
11969
12090
|
import * as path47 from "path";
|
|
11970
|
-
import
|
|
12091
|
+
import chalk134 from "chalk";
|
|
11971
12092
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
11972
12093
|
const source = path47.join(claudeDir, "settings.json");
|
|
11973
12094
|
const target = path47.join(targetBase, "settings.json");
|
|
@@ -11983,14 +12104,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
11983
12104
|
if (mergedContent !== normalizedTarget) {
|
|
11984
12105
|
if (!options2?.yes) {
|
|
11985
12106
|
console.log(
|
|
11986
|
-
|
|
12107
|
+
chalk134.yellow(
|
|
11987
12108
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
11988
12109
|
)
|
|
11989
12110
|
);
|
|
11990
12111
|
console.log();
|
|
11991
12112
|
printDiff(targetContent, mergedContent);
|
|
11992
12113
|
const confirm = await promptConfirm(
|
|
11993
|
-
|
|
12114
|
+
chalk134.red("Overwrite existing settings.json?"),
|
|
11994
12115
|
false
|
|
11995
12116
|
);
|
|
11996
12117
|
if (!confirm) {
|
|
@@ -12077,7 +12198,10 @@ program.command("commit").description("Create a git commit with validation").arg
|
|
|
12077
12198
|
registerConfig(program);
|
|
12078
12199
|
var runCommand = program.command("run").description("Run a configured command from assist.yml").argument("[name]", "Name of the configured command").argument("[args...]", "Arguments to pass to the command").allowUnknownOption().addHelpText("after", () => formatConfiguredCommands()).action((name, args) => run3(name, args));
|
|
12079
12200
|
runCommand.command("list").description("List configured run commands").action(listRunConfigs);
|
|
12080
|
-
runCommand.command("add").description("Add a new run configuration to assist.yml").argument("<name>", "Name for the run configuration").argument("<command>", "Command to execute").argument("[args...]", "Static args to pass to the command").
|
|
12201
|
+
runCommand.command("add").description("Add a new run configuration to assist.yml").argument("<name>", "Name for the run configuration").argument("<command>", "Command to execute").argument("[args...]", "Static args to pass to the command").option(
|
|
12202
|
+
"--cwd <dir>",
|
|
12203
|
+
"Working directory (resolved relative to the config file)"
|
|
12204
|
+
).addHelpText(
|
|
12081
12205
|
"after",
|
|
12082
12206
|
'\nPositional params can be added to the config manually:\n params:\n - name: env # assist run deploy prod \u2192 appends "prod"\n required: true\n - name: tag\n default: latest'
|
|
12083
12207
|
).allowUnknownOption().allowExcessArguments().action(() => add3());
|
|
@@ -12110,6 +12234,7 @@ registerRavendb(program);
|
|
|
12110
12234
|
registerSeq(program);
|
|
12111
12235
|
registerTranscript(program);
|
|
12112
12236
|
registerVoice(program);
|
|
12237
|
+
registerDeny(program);
|
|
12113
12238
|
program.command("next").description("Alias for backlog next -w").action(() => next({ allowEdits: true }));
|
|
12114
12239
|
program.command("draft").alias("feat").description("Launch Claude in /draft mode, chain into next on /next signal").action(() => launchMode("draft"));
|
|
12115
12240
|
program.command("bug").description("Launch Claude in /bug mode, chain into next on /next signal").action(() => launchMode("bug"));
|