@staff0rd/assist 0.52.0 → 0.54.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 +6 -0
- package/dist/index.js +406 -189
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,12 @@ After installation, the `assist` command will be available globally.
|
|
|
50
50
|
- `assist prs list-comments` - List all comments on the current branch's pull request
|
|
51
51
|
- `assist prs fixed <comment-id> <sha>` - Reply with commit link and resolve thread
|
|
52
52
|
- `assist prs wontfix <comment-id> <reason>` - Reply with reason and resolve thread
|
|
53
|
+
- `assist backlog` - List all backlog items (same as `backlog list`)
|
|
54
|
+
- `assist backlog init` - Create an empty assist.backlog.yml
|
|
55
|
+
- `assist backlog list [--status <type>] [-v]` - List all backlog items with status icons
|
|
56
|
+
- `assist backlog add` - Add a new backlog item interactively
|
|
57
|
+
- `assist backlog start <id>` - Set a backlog item to in-progress
|
|
58
|
+
- `assist backlog done <id>` - Set a backlog item to done
|
|
53
59
|
- `assist run <name>` - Run a configured command from assist.yml
|
|
54
60
|
- `assist run add` - Add a new run configuration to assist.yml
|
|
55
61
|
- `assist config set <key> <value>` - Set a config value (e.g. commit.push true)
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { Command } from "commander";
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@staff0rd/assist",
|
|
10
|
-
version: "0.
|
|
10
|
+
version: "0.54.0",
|
|
11
11
|
type: "module",
|
|
12
12
|
main: "dist/index.js",
|
|
13
13
|
bin: {
|
|
@@ -1802,16 +1802,232 @@ async function notify() {
|
|
|
1802
1802
|
console.log(`Notification sent: ${notification_type} for ${projectName}`);
|
|
1803
1803
|
}
|
|
1804
1804
|
|
|
1805
|
-
// src/commands/
|
|
1805
|
+
// src/commands/backlog/add/index.ts
|
|
1806
|
+
import { existsSync as existsSync12 } from "fs";
|
|
1807
|
+
import chalk23 from "chalk";
|
|
1808
|
+
|
|
1809
|
+
// src/commands/backlog/shared.ts
|
|
1810
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
1811
|
+
import { join as join8 } from "path";
|
|
1812
|
+
import chalk22 from "chalk";
|
|
1813
|
+
import { parse as parseYaml2, stringify as stringifyYaml3 } from "yaml";
|
|
1814
|
+
|
|
1815
|
+
// src/commands/backlog/types.ts
|
|
1816
|
+
import { z as z2 } from "zod";
|
|
1817
|
+
var backlogStatusSchema = z2.enum(["todo", "in-progress", "done"]);
|
|
1818
|
+
var backlogItemSchema = z2.strictObject({
|
|
1819
|
+
id: z2.number(),
|
|
1820
|
+
name: z2.string(),
|
|
1821
|
+
description: z2.string().optional(),
|
|
1822
|
+
acceptanceCriteria: z2.array(z2.string()),
|
|
1823
|
+
status: backlogStatusSchema
|
|
1824
|
+
});
|
|
1825
|
+
var backlogFileSchema = z2.array(backlogItemSchema);
|
|
1826
|
+
|
|
1827
|
+
// src/commands/backlog/shared.ts
|
|
1828
|
+
function getBacklogPath() {
|
|
1829
|
+
return join8(process.cwd(), "assist.backlog.yml");
|
|
1830
|
+
}
|
|
1831
|
+
function loadBacklog() {
|
|
1832
|
+
const backlogPath = getBacklogPath();
|
|
1833
|
+
if (!existsSync11(backlogPath)) {
|
|
1834
|
+
return [];
|
|
1835
|
+
}
|
|
1836
|
+
try {
|
|
1837
|
+
const content = readFileSync9(backlogPath, "utf-8");
|
|
1838
|
+
const raw = parseYaml2(content) || [];
|
|
1839
|
+
return backlogFileSchema.parse(raw);
|
|
1840
|
+
} catch {
|
|
1841
|
+
return [];
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
function saveBacklog(items) {
|
|
1845
|
+
const backlogPath = getBacklogPath();
|
|
1846
|
+
writeFileSync10(backlogPath, stringifyYaml3(items, { lineWidth: 0 }));
|
|
1847
|
+
}
|
|
1848
|
+
function findItem(items, id) {
|
|
1849
|
+
return items.find((item) => item.id === id);
|
|
1850
|
+
}
|
|
1851
|
+
function setStatus(id, status) {
|
|
1852
|
+
const backlogPath = getBacklogPath();
|
|
1853
|
+
if (!existsSync11(backlogPath)) {
|
|
1854
|
+
console.log(
|
|
1855
|
+
chalk22.yellow(
|
|
1856
|
+
"No backlog found. Run 'assist backlog init' to create one."
|
|
1857
|
+
)
|
|
1858
|
+
);
|
|
1859
|
+
return void 0;
|
|
1860
|
+
}
|
|
1861
|
+
const items = loadBacklog();
|
|
1862
|
+
const item = findItem(items, Number.parseInt(id, 10));
|
|
1863
|
+
if (!item) {
|
|
1864
|
+
console.log(chalk22.red(`Item #${id} not found.`));
|
|
1865
|
+
return void 0;
|
|
1866
|
+
}
|
|
1867
|
+
item.status = status;
|
|
1868
|
+
saveBacklog(items);
|
|
1869
|
+
return item.name;
|
|
1870
|
+
}
|
|
1871
|
+
function getNextId(items) {
|
|
1872
|
+
if (items.length === 0) return 1;
|
|
1873
|
+
return Math.max(...items.map((item) => item.id)) + 1;
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
// src/commands/backlog/add/shared.ts
|
|
1877
|
+
import enquirer4 from "enquirer";
|
|
1878
|
+
async function promptName() {
|
|
1879
|
+
const { name } = await enquirer4.prompt({
|
|
1880
|
+
type: "input",
|
|
1881
|
+
name: "name",
|
|
1882
|
+
message: "Name:",
|
|
1883
|
+
validate: (value) => value.trim().length > 0 || "Name is required"
|
|
1884
|
+
});
|
|
1885
|
+
return name.trim();
|
|
1886
|
+
}
|
|
1887
|
+
async function promptDescription() {
|
|
1888
|
+
const { description } = await enquirer4.prompt({
|
|
1889
|
+
type: "input",
|
|
1890
|
+
name: "description",
|
|
1891
|
+
message: "Description (optional):"
|
|
1892
|
+
});
|
|
1893
|
+
return description.trim() || void 0;
|
|
1894
|
+
}
|
|
1895
|
+
async function promptAcceptanceCriteria() {
|
|
1896
|
+
const criteria = [];
|
|
1897
|
+
for (; ; ) {
|
|
1898
|
+
const { criterion } = await enquirer4.prompt({
|
|
1899
|
+
type: "input",
|
|
1900
|
+
name: "criterion",
|
|
1901
|
+
message: "Acceptance criterion (empty to finish):"
|
|
1902
|
+
});
|
|
1903
|
+
if (criterion.trim() === "") break;
|
|
1904
|
+
criteria.push(criterion.trim());
|
|
1905
|
+
}
|
|
1906
|
+
return criteria;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
// src/commands/backlog/add/index.ts
|
|
1910
|
+
async function add() {
|
|
1911
|
+
const backlogPath = getBacklogPath();
|
|
1912
|
+
if (!existsSync12(backlogPath)) {
|
|
1913
|
+
console.log(
|
|
1914
|
+
chalk23.yellow(
|
|
1915
|
+
"No backlog found. Run 'assist backlog init' to create one."
|
|
1916
|
+
)
|
|
1917
|
+
);
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
const name = await promptName();
|
|
1921
|
+
const description = await promptDescription();
|
|
1922
|
+
const acceptanceCriteria = await promptAcceptanceCriteria();
|
|
1923
|
+
const items = loadBacklog();
|
|
1924
|
+
const id = getNextId(items);
|
|
1925
|
+
items.push({ id, name, description, acceptanceCriteria, status: "todo" });
|
|
1926
|
+
saveBacklog(items);
|
|
1927
|
+
console.log(chalk23.green(`Added item #${id}: ${name}`));
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
// src/commands/backlog/done/index.ts
|
|
1931
|
+
import chalk24 from "chalk";
|
|
1932
|
+
async function done(id) {
|
|
1933
|
+
const name = setStatus(id, "done");
|
|
1934
|
+
if (name) {
|
|
1935
|
+
console.log(chalk24.green(`Completed item #${id}: ${name}`));
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
// src/commands/backlog/init/index.ts
|
|
1940
|
+
import { existsSync as existsSync13 } from "fs";
|
|
1941
|
+
import chalk25 from "chalk";
|
|
1942
|
+
async function init6() {
|
|
1943
|
+
const backlogPath = getBacklogPath();
|
|
1944
|
+
if (existsSync13(backlogPath)) {
|
|
1945
|
+
console.log(chalk25.yellow("assist.backlog.yml already exists."));
|
|
1946
|
+
return;
|
|
1947
|
+
}
|
|
1948
|
+
saveBacklog([]);
|
|
1949
|
+
console.log(chalk25.green("Created assist.backlog.yml"));
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
// src/commands/backlog/list/index.ts
|
|
1953
|
+
import { existsSync as existsSync14 } from "fs";
|
|
1954
|
+
import chalk26 from "chalk";
|
|
1955
|
+
function statusIcon(status) {
|
|
1956
|
+
switch (status) {
|
|
1957
|
+
case "todo":
|
|
1958
|
+
return chalk26.dim("[ ]");
|
|
1959
|
+
case "in-progress":
|
|
1960
|
+
return chalk26.yellow("[~]");
|
|
1961
|
+
case "done":
|
|
1962
|
+
return chalk26.green("[x]");
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
async function list(options2) {
|
|
1966
|
+
const backlogPath = getBacklogPath();
|
|
1967
|
+
if (!existsSync14(backlogPath)) {
|
|
1968
|
+
console.log(
|
|
1969
|
+
chalk26.yellow(
|
|
1970
|
+
"No backlog found. Run 'assist backlog init' to create one."
|
|
1971
|
+
)
|
|
1972
|
+
);
|
|
1973
|
+
return;
|
|
1974
|
+
}
|
|
1975
|
+
let items = loadBacklog();
|
|
1976
|
+
if (options2.status) {
|
|
1977
|
+
items = items.filter((item) => item.status === options2.status);
|
|
1978
|
+
}
|
|
1979
|
+
if (items.length === 0) {
|
|
1980
|
+
console.log(chalk26.dim("Backlog is empty."));
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
for (const item of items) {
|
|
1984
|
+
console.log(
|
|
1985
|
+
`${statusIcon(item.status)} ${chalk26.dim(`#${item.id}`)} ${item.name}`
|
|
1986
|
+
);
|
|
1987
|
+
if (options2.verbose) {
|
|
1988
|
+
if (item.description) {
|
|
1989
|
+
console.log(` ${chalk26.dim("Description:")} ${item.description}`);
|
|
1990
|
+
}
|
|
1991
|
+
if (item.acceptanceCriteria.length > 0) {
|
|
1992
|
+
console.log(` ${chalk26.dim("Acceptance criteria:")}`);
|
|
1993
|
+
for (const criterion of item.acceptanceCriteria) {
|
|
1994
|
+
console.log(` - ${criterion}`);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
console.log();
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
// src/commands/backlog/start/index.ts
|
|
1806
2003
|
import chalk27 from "chalk";
|
|
2004
|
+
async function start(id) {
|
|
2005
|
+
const name = setStatus(id, "in-progress");
|
|
2006
|
+
if (name) {
|
|
2007
|
+
console.log(chalk27.green(`Started item #${id}: ${name}`));
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
// src/commands/registerBacklog.ts
|
|
2012
|
+
function registerBacklog(program2) {
|
|
2013
|
+
const backlogCommand = program2.command("backlog").description("Manage a backlog of work items").action(list);
|
|
2014
|
+
backlogCommand.command("init").description("Create an empty assist.backlog.yml").action(init6);
|
|
2015
|
+
backlogCommand.command("list").description("List all backlog items").option("--status <type>", "Filter by status (todo, in-progress, done)").option("-v, --verbose", "Show all item details").action(list);
|
|
2016
|
+
backlogCommand.command("add").description("Add a new backlog item").action(add);
|
|
2017
|
+
backlogCommand.command("start <id>").description("Set a backlog item to in-progress").action(start);
|
|
2018
|
+
backlogCommand.command("done <id>").description("Set a backlog item to done").action(done);
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
// src/commands/complexity/analyze.ts
|
|
2022
|
+
import chalk33 from "chalk";
|
|
1807
2023
|
|
|
1808
2024
|
// src/commands/complexity/cyclomatic.ts
|
|
1809
|
-
import
|
|
2025
|
+
import chalk29 from "chalk";
|
|
1810
2026
|
|
|
1811
2027
|
// src/commands/complexity/shared/index.ts
|
|
1812
2028
|
import fs11 from "fs";
|
|
1813
2029
|
import path16 from "path";
|
|
1814
|
-
import
|
|
2030
|
+
import chalk28 from "chalk";
|
|
1815
2031
|
import ts5 from "typescript";
|
|
1816
2032
|
|
|
1817
2033
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -2057,7 +2273,7 @@ function createSourceFromFile(filePath) {
|
|
|
2057
2273
|
function withSourceFiles(pattern2, callback) {
|
|
2058
2274
|
const files = findSourceFiles2(pattern2);
|
|
2059
2275
|
if (files.length === 0) {
|
|
2060
|
-
console.log(
|
|
2276
|
+
console.log(chalk28.yellow("No files found matching pattern"));
|
|
2061
2277
|
return void 0;
|
|
2062
2278
|
}
|
|
2063
2279
|
return callback(files);
|
|
@@ -2090,11 +2306,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2090
2306
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
2091
2307
|
for (const { file, name, complexity } of results) {
|
|
2092
2308
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
2093
|
-
const color = exceedsThreshold ?
|
|
2094
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
2309
|
+
const color = exceedsThreshold ? chalk29.red : chalk29.white;
|
|
2310
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk29.cyan(complexity)}`);
|
|
2095
2311
|
}
|
|
2096
2312
|
console.log(
|
|
2097
|
-
|
|
2313
|
+
chalk29.dim(
|
|
2098
2314
|
`
|
|
2099
2315
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2100
2316
|
)
|
|
@@ -2106,7 +2322,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2106
2322
|
}
|
|
2107
2323
|
|
|
2108
2324
|
// src/commands/complexity/halstead.ts
|
|
2109
|
-
import
|
|
2325
|
+
import chalk30 from "chalk";
|
|
2110
2326
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
2111
2327
|
withSourceFiles(pattern2, (files) => {
|
|
2112
2328
|
const results = [];
|
|
@@ -2121,13 +2337,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2121
2337
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
2122
2338
|
for (const { file, name, metrics } of results) {
|
|
2123
2339
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
2124
|
-
const color = exceedsThreshold ?
|
|
2340
|
+
const color = exceedsThreshold ? chalk30.red : chalk30.white;
|
|
2125
2341
|
console.log(
|
|
2126
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
2342
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk30.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk30.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk30.magenta(metrics.effort.toFixed(1))}`
|
|
2127
2343
|
);
|
|
2128
2344
|
}
|
|
2129
2345
|
console.log(
|
|
2130
|
-
|
|
2346
|
+
chalk30.dim(
|
|
2131
2347
|
`
|
|
2132
2348
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2133
2349
|
)
|
|
@@ -2142,24 +2358,24 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2142
2358
|
import fs12 from "fs";
|
|
2143
2359
|
|
|
2144
2360
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
2145
|
-
import
|
|
2361
|
+
import chalk31 from "chalk";
|
|
2146
2362
|
function displayMaintainabilityResults(results, threshold) {
|
|
2147
2363
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
2148
2364
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
2149
|
-
console.log(
|
|
2365
|
+
console.log(chalk31.green("All files pass maintainability threshold"));
|
|
2150
2366
|
} else {
|
|
2151
2367
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
2152
|
-
const color = threshold !== void 0 ?
|
|
2368
|
+
const color = threshold !== void 0 ? chalk31.red : chalk31.white;
|
|
2153
2369
|
console.log(
|
|
2154
|
-
`${color(file)} \u2192 avg: ${
|
|
2370
|
+
`${color(file)} \u2192 avg: ${chalk31.cyan(avgMaintainability.toFixed(1))}, min: ${chalk31.yellow(minMaintainability.toFixed(1))}`
|
|
2155
2371
|
);
|
|
2156
2372
|
}
|
|
2157
2373
|
}
|
|
2158
|
-
console.log(
|
|
2374
|
+
console.log(chalk31.dim(`
|
|
2159
2375
|
Analyzed ${results.length} files`));
|
|
2160
2376
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
2161
2377
|
console.error(
|
|
2162
|
-
|
|
2378
|
+
chalk31.red(
|
|
2163
2379
|
`
|
|
2164
2380
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code. Focus on one file at a time \u2014 run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
|
|
2165
2381
|
)
|
|
@@ -2218,7 +2434,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2218
2434
|
|
|
2219
2435
|
// src/commands/complexity/sloc.ts
|
|
2220
2436
|
import fs13 from "fs";
|
|
2221
|
-
import
|
|
2437
|
+
import chalk32 from "chalk";
|
|
2222
2438
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
2223
2439
|
withSourceFiles(pattern2, (files) => {
|
|
2224
2440
|
const results = [];
|
|
@@ -2234,12 +2450,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2234
2450
|
results.sort((a, b) => b.lines - a.lines);
|
|
2235
2451
|
for (const { file, lines } of results) {
|
|
2236
2452
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
2237
|
-
const color = exceedsThreshold ?
|
|
2238
|
-
console.log(`${color(file)} \u2192 ${
|
|
2453
|
+
const color = exceedsThreshold ? chalk32.red : chalk32.white;
|
|
2454
|
+
console.log(`${color(file)} \u2192 ${chalk32.cyan(lines)} lines`);
|
|
2239
2455
|
}
|
|
2240
2456
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
2241
2457
|
console.log(
|
|
2242
|
-
|
|
2458
|
+
chalk32.dim(`
|
|
2243
2459
|
Total: ${total} lines across ${files.length} files`)
|
|
2244
2460
|
);
|
|
2245
2461
|
if (hasViolation) {
|
|
@@ -2253,21 +2469,21 @@ async function analyze(pattern2) {
|
|
|
2253
2469
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
2254
2470
|
const files = findSourceFiles2(searchPattern);
|
|
2255
2471
|
if (files.length === 0) {
|
|
2256
|
-
console.log(
|
|
2472
|
+
console.log(chalk33.yellow("No files found matching pattern"));
|
|
2257
2473
|
return;
|
|
2258
2474
|
}
|
|
2259
2475
|
if (files.length === 1) {
|
|
2260
2476
|
const file = files[0];
|
|
2261
|
-
console.log(
|
|
2477
|
+
console.log(chalk33.bold.underline("SLOC"));
|
|
2262
2478
|
await sloc(file);
|
|
2263
2479
|
console.log();
|
|
2264
|
-
console.log(
|
|
2480
|
+
console.log(chalk33.bold.underline("Cyclomatic Complexity"));
|
|
2265
2481
|
await cyclomatic(file);
|
|
2266
2482
|
console.log();
|
|
2267
|
-
console.log(
|
|
2483
|
+
console.log(chalk33.bold.underline("Halstead Metrics"));
|
|
2268
2484
|
await halstead(file);
|
|
2269
2485
|
console.log();
|
|
2270
|
-
console.log(
|
|
2486
|
+
console.log(chalk33.bold.underline("Maintainability Index"));
|
|
2271
2487
|
await maintainability(file);
|
|
2272
2488
|
return;
|
|
2273
2489
|
}
|
|
@@ -2294,8 +2510,8 @@ function registerComplexity(program2) {
|
|
|
2294
2510
|
}
|
|
2295
2511
|
|
|
2296
2512
|
// src/commands/deploy/redirect.ts
|
|
2297
|
-
import { existsSync as
|
|
2298
|
-
import
|
|
2513
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
2514
|
+
import chalk34 from "chalk";
|
|
2299
2515
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
2300
2516
|
if (!window.location.pathname.endsWith('/')) {
|
|
2301
2517
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -2303,23 +2519,23 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
2303
2519
|
</script>`;
|
|
2304
2520
|
function redirect() {
|
|
2305
2521
|
const indexPath = "index.html";
|
|
2306
|
-
if (!
|
|
2307
|
-
console.log(
|
|
2522
|
+
if (!existsSync15(indexPath)) {
|
|
2523
|
+
console.log(chalk34.yellow("No index.html found"));
|
|
2308
2524
|
return;
|
|
2309
2525
|
}
|
|
2310
|
-
const content =
|
|
2526
|
+
const content = readFileSync10(indexPath, "utf-8");
|
|
2311
2527
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
2312
|
-
console.log(
|
|
2528
|
+
console.log(chalk34.dim("Trailing slash script already present"));
|
|
2313
2529
|
return;
|
|
2314
2530
|
}
|
|
2315
2531
|
const headCloseIndex = content.indexOf("</head>");
|
|
2316
2532
|
if (headCloseIndex === -1) {
|
|
2317
|
-
console.log(
|
|
2533
|
+
console.log(chalk34.red("Could not find </head> tag in index.html"));
|
|
2318
2534
|
return;
|
|
2319
2535
|
}
|
|
2320
2536
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
2321
|
-
|
|
2322
|
-
console.log(
|
|
2537
|
+
writeFileSync11(indexPath, newContent);
|
|
2538
|
+
console.log(chalk34.green("Added trailing slash redirect to index.html"));
|
|
2323
2539
|
}
|
|
2324
2540
|
|
|
2325
2541
|
// src/commands/registerDeploy.ts
|
|
@@ -2335,19 +2551,19 @@ import { basename as basename3 } from "path";
|
|
|
2335
2551
|
|
|
2336
2552
|
// src/commands/devlog/shared.ts
|
|
2337
2553
|
import { execSync as execSync11 } from "child_process";
|
|
2338
|
-
import
|
|
2554
|
+
import chalk35 from "chalk";
|
|
2339
2555
|
|
|
2340
2556
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
2341
|
-
import { readdirSync, readFileSync as
|
|
2557
|
+
import { readdirSync, readFileSync as readFileSync11 } from "fs";
|
|
2342
2558
|
import { homedir } from "os";
|
|
2343
|
-
import { join as
|
|
2344
|
-
var DEVLOG_DIR =
|
|
2559
|
+
import { join as join9 } from "path";
|
|
2560
|
+
var DEVLOG_DIR = join9(homedir(), "git/blog/src/content/devlog");
|
|
2345
2561
|
function loadDevlogEntries(repoName) {
|
|
2346
2562
|
const entries = /* @__PURE__ */ new Map();
|
|
2347
2563
|
try {
|
|
2348
2564
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
2349
2565
|
for (const file of files) {
|
|
2350
|
-
const content =
|
|
2566
|
+
const content = readFileSync11(join9(DEVLOG_DIR, file), "utf-8");
|
|
2351
2567
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
2352
2568
|
if (frontmatterMatch) {
|
|
2353
2569
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -2396,13 +2612,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
2396
2612
|
}
|
|
2397
2613
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
2398
2614
|
for (const commit2 of commits) {
|
|
2399
|
-
console.log(` ${
|
|
2615
|
+
console.log(` ${chalk35.yellow(commit2.hash)} ${commit2.message}`);
|
|
2400
2616
|
if (verbose) {
|
|
2401
2617
|
const visibleFiles = commit2.files.filter(
|
|
2402
2618
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
2403
2619
|
);
|
|
2404
2620
|
for (const file of visibleFiles) {
|
|
2405
|
-
console.log(` ${
|
|
2621
|
+
console.log(` ${chalk35.dim(file)}`);
|
|
2406
2622
|
}
|
|
2407
2623
|
}
|
|
2408
2624
|
}
|
|
@@ -2427,20 +2643,20 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
2427
2643
|
}
|
|
2428
2644
|
|
|
2429
2645
|
// src/commands/devlog/list/printDateHeader.ts
|
|
2430
|
-
import
|
|
2646
|
+
import chalk36 from "chalk";
|
|
2431
2647
|
function printDateHeader(date, isSkipped, entries) {
|
|
2432
2648
|
if (isSkipped) {
|
|
2433
|
-
console.log(`${
|
|
2649
|
+
console.log(`${chalk36.bold.blue(date)} ${chalk36.dim("skipped")}`);
|
|
2434
2650
|
} else if (entries && entries.length > 0) {
|
|
2435
|
-
const entryInfo = entries.map((e) => `${
|
|
2436
|
-
console.log(`${
|
|
2651
|
+
const entryInfo = entries.map((e) => `${chalk36.green(e.version)} ${e.title}`).join(" | ");
|
|
2652
|
+
console.log(`${chalk36.bold.blue(date)} ${entryInfo}`);
|
|
2437
2653
|
} else {
|
|
2438
|
-
console.log(`${
|
|
2654
|
+
console.log(`${chalk36.bold.blue(date)} ${chalk36.red("\u26A0 devlog missing")}`);
|
|
2439
2655
|
}
|
|
2440
2656
|
}
|
|
2441
2657
|
|
|
2442
2658
|
// src/commands/devlog/list/index.ts
|
|
2443
|
-
function
|
|
2659
|
+
function list2(options2) {
|
|
2444
2660
|
const config = loadConfig();
|
|
2445
2661
|
const days = options2.days ?? 30;
|
|
2446
2662
|
const ignore2 = options2.ignore ?? config.devlog?.ignore ?? [];
|
|
@@ -2538,24 +2754,24 @@ function bumpVersion(version2, type) {
|
|
|
2538
2754
|
|
|
2539
2755
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
2540
2756
|
import { execSync as execSync14 } from "child_process";
|
|
2541
|
-
import
|
|
2757
|
+
import chalk38 from "chalk";
|
|
2542
2758
|
|
|
2543
2759
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
2544
|
-
import
|
|
2760
|
+
import chalk37 from "chalk";
|
|
2545
2761
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
2546
2762
|
if (conventional && firstHash) {
|
|
2547
2763
|
const version2 = getVersionAtCommit(firstHash);
|
|
2548
2764
|
if (version2) {
|
|
2549
|
-
console.log(`${
|
|
2765
|
+
console.log(`${chalk37.bold("version:")} ${stripToMinor(version2)}`);
|
|
2550
2766
|
} else {
|
|
2551
|
-
console.log(`${
|
|
2767
|
+
console.log(`${chalk37.bold("version:")} ${chalk37.red("unknown")}`);
|
|
2552
2768
|
}
|
|
2553
2769
|
} else if (patchVersion && minorVersion) {
|
|
2554
2770
|
console.log(
|
|
2555
|
-
`${
|
|
2771
|
+
`${chalk37.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
2556
2772
|
);
|
|
2557
2773
|
} else {
|
|
2558
|
-
console.log(`${
|
|
2774
|
+
console.log(`${chalk37.bold("version:")} v0.1 (initial)`);
|
|
2559
2775
|
}
|
|
2560
2776
|
}
|
|
2561
2777
|
|
|
@@ -2602,16 +2818,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
2602
2818
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
2603
2819
|
}
|
|
2604
2820
|
function logName(repoName) {
|
|
2605
|
-
console.log(`${
|
|
2821
|
+
console.log(`${chalk38.bold("name:")} ${repoName}`);
|
|
2606
2822
|
}
|
|
2607
2823
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
2608
2824
|
logName(ctx.repoName);
|
|
2609
2825
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
2610
|
-
console.log(
|
|
2826
|
+
console.log(chalk38.bold.blue(targetDate));
|
|
2611
2827
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
2612
2828
|
}
|
|
2613
2829
|
function logNoCommits(lastInfo) {
|
|
2614
|
-
console.log(
|
|
2830
|
+
console.log(chalk38.dim(noCommitsMessage(!!lastInfo)));
|
|
2615
2831
|
}
|
|
2616
2832
|
|
|
2617
2833
|
// src/commands/devlog/next/index.ts
|
|
@@ -2646,16 +2862,16 @@ function next(options2) {
|
|
|
2646
2862
|
}
|
|
2647
2863
|
|
|
2648
2864
|
// src/commands/devlog/skip.ts
|
|
2649
|
-
import
|
|
2865
|
+
import chalk39 from "chalk";
|
|
2650
2866
|
function skip(date) {
|
|
2651
2867
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
2652
|
-
console.log(
|
|
2868
|
+
console.log(chalk39.red("Invalid date format. Use YYYY-MM-DD"));
|
|
2653
2869
|
process.exit(1);
|
|
2654
2870
|
}
|
|
2655
2871
|
const config = loadConfig();
|
|
2656
2872
|
const skipDays = config.devlog?.skip?.days ?? [];
|
|
2657
2873
|
if (skipDays.includes(date)) {
|
|
2658
|
-
console.log(
|
|
2874
|
+
console.log(chalk39.yellow(`${date} is already in skip list`));
|
|
2659
2875
|
return;
|
|
2660
2876
|
}
|
|
2661
2877
|
skipDays.push(date);
|
|
@@ -2668,20 +2884,20 @@ function skip(date) {
|
|
|
2668
2884
|
}
|
|
2669
2885
|
};
|
|
2670
2886
|
saveConfig(config);
|
|
2671
|
-
console.log(
|
|
2887
|
+
console.log(chalk39.green(`Added ${date} to skip list`));
|
|
2672
2888
|
}
|
|
2673
2889
|
|
|
2674
2890
|
// src/commands/devlog/version.ts
|
|
2675
|
-
import
|
|
2891
|
+
import chalk40 from "chalk";
|
|
2676
2892
|
function version() {
|
|
2677
2893
|
const config = loadConfig();
|
|
2678
2894
|
const name = getRepoName();
|
|
2679
2895
|
const lastInfo = getLastVersionInfo(name, config);
|
|
2680
2896
|
const lastVersion = lastInfo?.version ?? null;
|
|
2681
2897
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
2682
|
-
console.log(`${
|
|
2683
|
-
console.log(`${
|
|
2684
|
-
console.log(`${
|
|
2898
|
+
console.log(`${chalk40.bold("name:")} ${name}`);
|
|
2899
|
+
console.log(`${chalk40.bold("last:")} ${lastVersion ?? chalk40.dim("none")}`);
|
|
2900
|
+
console.log(`${chalk40.bold("next:")} ${nextVersion ?? chalk40.dim("none")}`);
|
|
2685
2901
|
}
|
|
2686
2902
|
|
|
2687
2903
|
// src/commands/registerDevlog.ts
|
|
@@ -2691,7 +2907,7 @@ function registerDevlog(program2) {
|
|
|
2691
2907
|
"--days <number>",
|
|
2692
2908
|
"Number of days to show (default: 30)",
|
|
2693
2909
|
Number.parseInt
|
|
2694
|
-
).option("--since <date>", "Only show commits since this date (YYYY-MM-DD)").option("-r, --reverse", "Show earliest commits first").option("-v, --verbose", "Show file names for each commit").action(
|
|
2910
|
+
).option("--since <date>", "Only show commits since this date (YYYY-MM-DD)").option("-r, --reverse", "Show earliest commits first").option("-v, --verbose", "Show file names for each commit").action(list2);
|
|
2695
2911
|
devlogCommand.command("version").description("Show current repo name and version info").action(version);
|
|
2696
2912
|
devlogCommand.command("next").description("Show commits for the day after the last versioned entry").option("-v, --verbose", "Show file names for each commit").action(next);
|
|
2697
2913
|
devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
|
|
@@ -2702,28 +2918,28 @@ import { execSync as execSync17 } from "child_process";
|
|
|
2702
2918
|
|
|
2703
2919
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
2704
2920
|
import { execSync as execSync16 } from "child_process";
|
|
2705
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
2921
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "fs";
|
|
2706
2922
|
import { tmpdir } from "os";
|
|
2707
|
-
import { join as
|
|
2923
|
+
import { join as join11 } from "path";
|
|
2708
2924
|
|
|
2709
2925
|
// src/commands/prs/loadCommentsCache.ts
|
|
2710
|
-
import { existsSync as
|
|
2711
|
-
import { join as
|
|
2926
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "fs";
|
|
2927
|
+
import { join as join10 } from "path";
|
|
2712
2928
|
import { parse } from "yaml";
|
|
2713
2929
|
function getCachePath(prNumber) {
|
|
2714
|
-
return
|
|
2930
|
+
return join10(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
2715
2931
|
}
|
|
2716
2932
|
function loadCommentsCache(prNumber) {
|
|
2717
2933
|
const cachePath = getCachePath(prNumber);
|
|
2718
|
-
if (!
|
|
2934
|
+
if (!existsSync16(cachePath)) {
|
|
2719
2935
|
return null;
|
|
2720
2936
|
}
|
|
2721
|
-
const content =
|
|
2937
|
+
const content = readFileSync12(cachePath, "utf-8");
|
|
2722
2938
|
return parse(content);
|
|
2723
2939
|
}
|
|
2724
2940
|
function deleteCommentsCache(prNumber) {
|
|
2725
2941
|
const cachePath = getCachePath(prNumber);
|
|
2726
|
-
if (
|
|
2942
|
+
if (existsSync16(cachePath)) {
|
|
2727
2943
|
unlinkSync2(cachePath);
|
|
2728
2944
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
2729
2945
|
}
|
|
@@ -2774,8 +2990,8 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
2774
2990
|
}
|
|
2775
2991
|
function resolveThread(threadId) {
|
|
2776
2992
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
2777
|
-
const queryFile =
|
|
2778
|
-
|
|
2993
|
+
const queryFile = join11(tmpdir(), `gh-mutation-${Date.now()}.graphql`);
|
|
2994
|
+
writeFileSync12(queryFile, mutation);
|
|
2779
2995
|
try {
|
|
2780
2996
|
execSync16(
|
|
2781
2997
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
@@ -2855,8 +3071,8 @@ function fixed(commentId, sha) {
|
|
|
2855
3071
|
}
|
|
2856
3072
|
|
|
2857
3073
|
// src/commands/prs/listComments/index.ts
|
|
2858
|
-
import { existsSync as
|
|
2859
|
-
import { join as
|
|
3074
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync14 } from "fs";
|
|
3075
|
+
import { join as join13 } from "path";
|
|
2860
3076
|
import { stringify } from "yaml";
|
|
2861
3077
|
|
|
2862
3078
|
// src/lib/isClaudeCode.ts
|
|
@@ -2866,13 +3082,13 @@ function isClaudeCode() {
|
|
|
2866
3082
|
|
|
2867
3083
|
// src/commands/prs/fetchThreadIds.ts
|
|
2868
3084
|
import { execSync as execSync18 } from "child_process";
|
|
2869
|
-
import { unlinkSync as unlinkSync4, writeFileSync as
|
|
3085
|
+
import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
2870
3086
|
import { tmpdir as tmpdir2 } from "os";
|
|
2871
|
-
import { join as
|
|
3087
|
+
import { join as join12 } from "path";
|
|
2872
3088
|
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 } } } } } } }`;
|
|
2873
3089
|
function fetchThreadIds(org, repo, prNumber) {
|
|
2874
|
-
const queryFile =
|
|
2875
|
-
|
|
3090
|
+
const queryFile = join12(tmpdir2(), `gh-query-${Date.now()}.graphql`);
|
|
3091
|
+
writeFileSync13(queryFile, THREAD_QUERY);
|
|
2876
3092
|
try {
|
|
2877
3093
|
const result = execSync18(
|
|
2878
3094
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -2938,20 +3154,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
2938
3154
|
}
|
|
2939
3155
|
|
|
2940
3156
|
// src/commands/prs/listComments/formatForHuman.ts
|
|
2941
|
-
import
|
|
3157
|
+
import chalk41 from "chalk";
|
|
2942
3158
|
function formatForHuman(comment) {
|
|
2943
3159
|
if (comment.type === "review") {
|
|
2944
|
-
const stateColor = comment.state === "APPROVED" ?
|
|
3160
|
+
const stateColor = comment.state === "APPROVED" ? chalk41.green : comment.state === "CHANGES_REQUESTED" ? chalk41.red : chalk41.yellow;
|
|
2945
3161
|
return [
|
|
2946
|
-
`${
|
|
3162
|
+
`${chalk41.cyan("Review")} by ${chalk41.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
|
|
2947
3163
|
comment.body,
|
|
2948
3164
|
""
|
|
2949
3165
|
].join("\n");
|
|
2950
3166
|
}
|
|
2951
3167
|
const location = comment.line ? `:${comment.line}` : "";
|
|
2952
3168
|
return [
|
|
2953
|
-
`${
|
|
2954
|
-
|
|
3169
|
+
`${chalk41.cyan("Line comment")} by ${chalk41.bold(comment.user)} on ${chalk41.dim(`${comment.path}${location}`)}`,
|
|
3170
|
+
chalk41.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
2955
3171
|
comment.body,
|
|
2956
3172
|
""
|
|
2957
3173
|
].join("\n");
|
|
@@ -2974,8 +3190,8 @@ function printComments(comments) {
|
|
|
2974
3190
|
}
|
|
2975
3191
|
}
|
|
2976
3192
|
function writeCommentsCache(prNumber, comments) {
|
|
2977
|
-
const assistDir =
|
|
2978
|
-
if (!
|
|
3193
|
+
const assistDir = join13(process.cwd(), ".assist");
|
|
3194
|
+
if (!existsSync17(assistDir)) {
|
|
2979
3195
|
mkdirSync4(assistDir, { recursive: true });
|
|
2980
3196
|
}
|
|
2981
3197
|
const cacheData = {
|
|
@@ -2983,8 +3199,8 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
2983
3199
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2984
3200
|
comments
|
|
2985
3201
|
};
|
|
2986
|
-
const cachePath =
|
|
2987
|
-
|
|
3202
|
+
const cachePath = join13(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
3203
|
+
writeFileSync14(cachePath, stringify(cacheData));
|
|
2988
3204
|
}
|
|
2989
3205
|
function handleKnownErrors(error) {
|
|
2990
3206
|
if (isGhNotInstalled(error)) {
|
|
@@ -3027,16 +3243,16 @@ async function listComments() {
|
|
|
3027
3243
|
import { execSync as execSync20 } from "child_process";
|
|
3028
3244
|
|
|
3029
3245
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
3030
|
-
import
|
|
3246
|
+
import enquirer5 from "enquirer";
|
|
3031
3247
|
|
|
3032
3248
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
3033
|
-
import
|
|
3249
|
+
import chalk42 from "chalk";
|
|
3034
3250
|
var STATUS_MAP = {
|
|
3035
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
3036
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
3251
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk42.magenta("merged"), date: pr.mergedAt } : null,
|
|
3252
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk42.red("closed"), date: pr.closedAt } : null
|
|
3037
3253
|
};
|
|
3038
3254
|
function defaultStatus(pr) {
|
|
3039
|
-
return { label:
|
|
3255
|
+
return { label: chalk42.green("opened"), date: pr.createdAt };
|
|
3040
3256
|
}
|
|
3041
3257
|
function getStatus(pr) {
|
|
3042
3258
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -3045,11 +3261,11 @@ function formatDate(dateStr) {
|
|
|
3045
3261
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
3046
3262
|
}
|
|
3047
3263
|
function formatPrHeader(pr, status) {
|
|
3048
|
-
return `${
|
|
3264
|
+
return `${chalk42.cyan(`#${pr.number}`)} ${pr.title} ${chalk42.dim(`(${pr.author.login},`)} ${status.label} ${chalk42.dim(`${formatDate(status.date)})`)}`;
|
|
3049
3265
|
}
|
|
3050
3266
|
function logPrDetails(pr) {
|
|
3051
3267
|
console.log(
|
|
3052
|
-
|
|
3268
|
+
chalk42.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
3053
3269
|
);
|
|
3054
3270
|
console.log();
|
|
3055
3271
|
}
|
|
@@ -3061,8 +3277,8 @@ function printPr(pr) {
|
|
|
3061
3277
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
3062
3278
|
var PAGE_SIZE = 10;
|
|
3063
3279
|
function getPageSlice(pullRequests, page) {
|
|
3064
|
-
const
|
|
3065
|
-
return pullRequests.slice(
|
|
3280
|
+
const start2 = page * PAGE_SIZE;
|
|
3281
|
+
return pullRequests.slice(start2, start2 + PAGE_SIZE);
|
|
3066
3282
|
}
|
|
3067
3283
|
function pageHeader(page, totalPages, total) {
|
|
3068
3284
|
return `
|
|
@@ -3097,7 +3313,7 @@ function parseAction(action) {
|
|
|
3097
3313
|
}
|
|
3098
3314
|
async function promptNavigation(currentPage, totalPages) {
|
|
3099
3315
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
3100
|
-
const { action } = await
|
|
3316
|
+
const { action } = await enquirer5.prompt({
|
|
3101
3317
|
type: "select",
|
|
3102
3318
|
name: "action",
|
|
3103
3319
|
message: "Navigate",
|
|
@@ -3216,7 +3432,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
3216
3432
|
import * as path17 from "path";
|
|
3217
3433
|
|
|
3218
3434
|
// src/commands/refactor/logViolations.ts
|
|
3219
|
-
import
|
|
3435
|
+
import chalk43 from "chalk";
|
|
3220
3436
|
var DEFAULT_MAX_LINES = 100;
|
|
3221
3437
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
3222
3438
|
if (violations.length === 0) {
|
|
@@ -3225,43 +3441,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
3225
3441
|
}
|
|
3226
3442
|
return;
|
|
3227
3443
|
}
|
|
3228
|
-
console.error(
|
|
3444
|
+
console.error(chalk43.red(`
|
|
3229
3445
|
Refactor check failed:
|
|
3230
3446
|
`));
|
|
3231
|
-
console.error(
|
|
3447
|
+
console.error(chalk43.red(` The following files exceed ${maxLines} lines:
|
|
3232
3448
|
`));
|
|
3233
3449
|
for (const violation of violations) {
|
|
3234
|
-
console.error(
|
|
3450
|
+
console.error(chalk43.red(` ${violation.file} (${violation.lines} lines)`));
|
|
3235
3451
|
}
|
|
3236
3452
|
console.error(
|
|
3237
|
-
|
|
3453
|
+
chalk43.yellow(
|
|
3238
3454
|
`
|
|
3239
3455
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
3240
3456
|
way to refactor it, ignore it with:
|
|
3241
3457
|
`
|
|
3242
3458
|
)
|
|
3243
3459
|
);
|
|
3244
|
-
console.error(
|
|
3460
|
+
console.error(chalk43.gray(` assist refactor ignore <file>
|
|
3245
3461
|
`));
|
|
3246
3462
|
if (process.env.CLAUDECODE) {
|
|
3247
|
-
console.error(
|
|
3463
|
+
console.error(chalk43.cyan(`
|
|
3248
3464
|
## Extracting Code to New Files
|
|
3249
3465
|
`));
|
|
3250
3466
|
console.error(
|
|
3251
|
-
|
|
3467
|
+
chalk43.cyan(
|
|
3252
3468
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
3253
3469
|
`
|
|
3254
3470
|
)
|
|
3255
3471
|
);
|
|
3256
3472
|
console.error(
|
|
3257
|
-
|
|
3473
|
+
chalk43.cyan(
|
|
3258
3474
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
3259
3475
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
3260
3476
|
`
|
|
3261
3477
|
)
|
|
3262
3478
|
);
|
|
3263
3479
|
console.error(
|
|
3264
|
-
|
|
3480
|
+
chalk43.cyan(
|
|
3265
3481
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
3266
3482
|
domains, move it to a common/shared folder.
|
|
3267
3483
|
`
|
|
@@ -3417,11 +3633,11 @@ async function check(pattern2, options2) {
|
|
|
3417
3633
|
|
|
3418
3634
|
// src/commands/refactor/ignore.ts
|
|
3419
3635
|
import fs16 from "fs";
|
|
3420
|
-
import
|
|
3636
|
+
import chalk44 from "chalk";
|
|
3421
3637
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
3422
3638
|
function ignore(file) {
|
|
3423
3639
|
if (!fs16.existsSync(file)) {
|
|
3424
|
-
console.error(
|
|
3640
|
+
console.error(chalk44.red(`Error: File does not exist: ${file}`));
|
|
3425
3641
|
process.exit(1);
|
|
3426
3642
|
}
|
|
3427
3643
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -3437,7 +3653,7 @@ function ignore(file) {
|
|
|
3437
3653
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
3438
3654
|
}
|
|
3439
3655
|
console.log(
|
|
3440
|
-
|
|
3656
|
+
chalk44.green(
|
|
3441
3657
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
3442
3658
|
)
|
|
3443
3659
|
);
|
|
@@ -3445,7 +3661,7 @@ function ignore(file) {
|
|
|
3445
3661
|
|
|
3446
3662
|
// src/commands/refactor/restructure/index.ts
|
|
3447
3663
|
import path26 from "path";
|
|
3448
|
-
import
|
|
3664
|
+
import chalk47 from "chalk";
|
|
3449
3665
|
|
|
3450
3666
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
3451
3667
|
import path18 from "path";
|
|
@@ -3594,9 +3810,9 @@ import path21 from "path";
|
|
|
3594
3810
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
3595
3811
|
import fs17 from "fs";
|
|
3596
3812
|
function getOrCreateList(map, key) {
|
|
3597
|
-
const
|
|
3598
|
-
if (!map.has(key)) map.set(key,
|
|
3599
|
-
return
|
|
3813
|
+
const list3 = map.get(key) ?? [];
|
|
3814
|
+
if (!map.has(key)) map.set(key, list3);
|
|
3815
|
+
return list3;
|
|
3600
3816
|
}
|
|
3601
3817
|
function groupByFile(rewrites) {
|
|
3602
3818
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -3688,50 +3904,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
3688
3904
|
|
|
3689
3905
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
3690
3906
|
import path22 from "path";
|
|
3691
|
-
import
|
|
3907
|
+
import chalk45 from "chalk";
|
|
3692
3908
|
function relPath(filePath) {
|
|
3693
3909
|
return path22.relative(process.cwd(), filePath);
|
|
3694
3910
|
}
|
|
3695
3911
|
function displayMoves(plan) {
|
|
3696
3912
|
if (plan.moves.length === 0) return;
|
|
3697
|
-
console.log(
|
|
3913
|
+
console.log(chalk45.bold("\nFile moves:"));
|
|
3698
3914
|
for (const move of plan.moves) {
|
|
3699
3915
|
console.log(
|
|
3700
|
-
` ${
|
|
3916
|
+
` ${chalk45.red(relPath(move.from))} \u2192 ${chalk45.green(relPath(move.to))}`
|
|
3701
3917
|
);
|
|
3702
|
-
console.log(
|
|
3918
|
+
console.log(chalk45.dim(` ${move.reason}`));
|
|
3703
3919
|
}
|
|
3704
3920
|
}
|
|
3705
3921
|
function displayRewrites(rewrites) {
|
|
3706
3922
|
if (rewrites.length === 0) return;
|
|
3707
3923
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
3708
|
-
console.log(
|
|
3924
|
+
console.log(chalk45.bold(`
|
|
3709
3925
|
Import rewrites (${affectedFiles.size} files):`));
|
|
3710
3926
|
for (const file of affectedFiles) {
|
|
3711
|
-
console.log(` ${
|
|
3927
|
+
console.log(` ${chalk45.cyan(relPath(file))}:`);
|
|
3712
3928
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
3713
3929
|
(r) => r.file === file
|
|
3714
3930
|
)) {
|
|
3715
3931
|
console.log(
|
|
3716
|
-
` ${
|
|
3932
|
+
` ${chalk45.red(`"${oldSpecifier}"`)} \u2192 ${chalk45.green(`"${newSpecifier}"`)}`
|
|
3717
3933
|
);
|
|
3718
3934
|
}
|
|
3719
3935
|
}
|
|
3720
3936
|
}
|
|
3721
3937
|
function displayPlan(plan) {
|
|
3722
3938
|
if (plan.warnings.length > 0) {
|
|
3723
|
-
console.log(
|
|
3724
|
-
for (const w of plan.warnings) console.log(
|
|
3939
|
+
console.log(chalk45.yellow("\nWarnings:"));
|
|
3940
|
+
for (const w of plan.warnings) console.log(chalk45.yellow(` ${w}`));
|
|
3725
3941
|
}
|
|
3726
3942
|
if (plan.newDirectories.length > 0) {
|
|
3727
|
-
console.log(
|
|
3943
|
+
console.log(chalk45.bold("\nNew directories:"));
|
|
3728
3944
|
for (const dir of plan.newDirectories)
|
|
3729
|
-
console.log(
|
|
3945
|
+
console.log(chalk45.green(` ${dir}/`));
|
|
3730
3946
|
}
|
|
3731
3947
|
displayMoves(plan);
|
|
3732
3948
|
displayRewrites(plan.rewrites);
|
|
3733
3949
|
console.log(
|
|
3734
|
-
|
|
3950
|
+
chalk45.dim(
|
|
3735
3951
|
`
|
|
3736
3952
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
3737
3953
|
)
|
|
@@ -3741,18 +3957,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
3741
3957
|
// src/commands/refactor/restructure/executePlan.ts
|
|
3742
3958
|
import fs18 from "fs";
|
|
3743
3959
|
import path23 from "path";
|
|
3744
|
-
import
|
|
3960
|
+
import chalk46 from "chalk";
|
|
3745
3961
|
function executePlan(plan) {
|
|
3746
3962
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
3747
3963
|
for (const [file, content] of updatedContents) {
|
|
3748
3964
|
fs18.writeFileSync(file, content, "utf-8");
|
|
3749
3965
|
console.log(
|
|
3750
|
-
|
|
3966
|
+
chalk46.cyan(` Rewrote imports in ${path23.relative(process.cwd(), file)}`)
|
|
3751
3967
|
);
|
|
3752
3968
|
}
|
|
3753
3969
|
for (const dir of plan.newDirectories) {
|
|
3754
3970
|
fs18.mkdirSync(dir, { recursive: true });
|
|
3755
|
-
console.log(
|
|
3971
|
+
console.log(chalk46.green(` Created ${path23.relative(process.cwd(), dir)}/`));
|
|
3756
3972
|
}
|
|
3757
3973
|
for (const move of plan.moves) {
|
|
3758
3974
|
const targetDir = path23.dirname(move.to);
|
|
@@ -3761,7 +3977,7 @@ function executePlan(plan) {
|
|
|
3761
3977
|
}
|
|
3762
3978
|
fs18.renameSync(move.from, move.to);
|
|
3763
3979
|
console.log(
|
|
3764
|
-
|
|
3980
|
+
chalk46.white(
|
|
3765
3981
|
` Moved ${path23.relative(process.cwd(), move.from)} \u2192 ${path23.relative(process.cwd(), move.to)}`
|
|
3766
3982
|
)
|
|
3767
3983
|
);
|
|
@@ -3776,7 +3992,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
3776
3992
|
if (entries.length === 0) {
|
|
3777
3993
|
fs18.rmdirSync(dir);
|
|
3778
3994
|
console.log(
|
|
3779
|
-
|
|
3995
|
+
chalk46.dim(
|
|
3780
3996
|
` Removed empty directory ${path23.relative(process.cwd(), dir)}`
|
|
3781
3997
|
)
|
|
3782
3998
|
);
|
|
@@ -3907,22 +4123,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
3907
4123
|
const targetPattern = pattern2 ?? "src";
|
|
3908
4124
|
const files = findSourceFiles2(targetPattern);
|
|
3909
4125
|
if (files.length === 0) {
|
|
3910
|
-
console.log(
|
|
4126
|
+
console.log(chalk47.yellow("No files found matching pattern"));
|
|
3911
4127
|
return;
|
|
3912
4128
|
}
|
|
3913
4129
|
const tsConfigPath = path26.resolve("tsconfig.json");
|
|
3914
4130
|
const plan = buildPlan(files, tsConfigPath);
|
|
3915
4131
|
if (plan.moves.length === 0) {
|
|
3916
|
-
console.log(
|
|
4132
|
+
console.log(chalk47.green("No restructuring needed"));
|
|
3917
4133
|
return;
|
|
3918
4134
|
}
|
|
3919
4135
|
displayPlan(plan);
|
|
3920
4136
|
if (options2.apply) {
|
|
3921
|
-
console.log(
|
|
4137
|
+
console.log(chalk47.bold("\nApplying changes..."));
|
|
3922
4138
|
executePlan(plan);
|
|
3923
|
-
console.log(
|
|
4139
|
+
console.log(chalk47.green("\nRestructuring complete"));
|
|
3924
4140
|
} else {
|
|
3925
|
-
console.log(
|
|
4141
|
+
console.log(chalk47.dim("\nDry run. Use --apply to execute."));
|
|
3926
4142
|
}
|
|
3927
4143
|
}
|
|
3928
4144
|
|
|
@@ -3945,8 +4161,8 @@ function registerRefactor(program2) {
|
|
|
3945
4161
|
}
|
|
3946
4162
|
|
|
3947
4163
|
// src/commands/transcript/shared.ts
|
|
3948
|
-
import { existsSync as
|
|
3949
|
-
import { basename as basename4, join as
|
|
4164
|
+
import { existsSync as existsSync18, readdirSync as readdirSync2, statSync } from "fs";
|
|
4165
|
+
import { basename as basename4, join as join14, relative } from "path";
|
|
3950
4166
|
import * as readline2 from "readline";
|
|
3951
4167
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
3952
4168
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -3961,10 +4177,10 @@ function isValidDatePrefix(filename) {
|
|
|
3961
4177
|
return DATE_PREFIX_REGEX.test(filename);
|
|
3962
4178
|
}
|
|
3963
4179
|
function collectFiles(dir, extension) {
|
|
3964
|
-
if (!
|
|
4180
|
+
if (!existsSync18(dir)) return [];
|
|
3965
4181
|
const results = [];
|
|
3966
4182
|
for (const entry of readdirSync2(dir)) {
|
|
3967
|
-
const fullPath =
|
|
4183
|
+
const fullPath = join14(dir, entry);
|
|
3968
4184
|
if (statSync(fullPath).isDirectory()) {
|
|
3969
4185
|
results.push(...collectFiles(fullPath, extension));
|
|
3970
4186
|
} else if (entry.endsWith(extension)) {
|
|
@@ -4058,14 +4274,14 @@ async function configure() {
|
|
|
4058
4274
|
}
|
|
4059
4275
|
|
|
4060
4276
|
// src/commands/transcript/format/index.ts
|
|
4061
|
-
import { existsSync as
|
|
4277
|
+
import { existsSync as existsSync20 } from "fs";
|
|
4062
4278
|
|
|
4063
4279
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
4064
|
-
import { dirname as dirname12, join as
|
|
4280
|
+
import { dirname as dirname12, join as join16 } from "path";
|
|
4065
4281
|
|
|
4066
4282
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
4067
4283
|
import { renameSync } from "fs";
|
|
4068
|
-
import { join as
|
|
4284
|
+
import { join as join15 } from "path";
|
|
4069
4285
|
async function resolveDate(rl, choice) {
|
|
4070
4286
|
if (choice === "1") return getDatePrefix(0);
|
|
4071
4287
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -4080,7 +4296,7 @@ async function resolveDate(rl, choice) {
|
|
|
4080
4296
|
}
|
|
4081
4297
|
function renameWithPrefix(vttDir, vttFile, prefix) {
|
|
4082
4298
|
const newFilename = `${prefix}.${vttFile}`;
|
|
4083
|
-
renameSync(
|
|
4299
|
+
renameSync(join15(vttDir, vttFile), join15(vttDir, newFilename));
|
|
4084
4300
|
console.log(`Renamed to: ${newFilename}`);
|
|
4085
4301
|
return newFilename;
|
|
4086
4302
|
}
|
|
@@ -4114,12 +4330,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4114
4330
|
const vttFileDir = dirname12(vttFile.absolutePath);
|
|
4115
4331
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
4116
4332
|
if (newFilename) {
|
|
4117
|
-
const newRelativePath =
|
|
4333
|
+
const newRelativePath = join16(
|
|
4118
4334
|
dirname12(vttFile.relativePath),
|
|
4119
4335
|
newFilename
|
|
4120
4336
|
);
|
|
4121
4337
|
vttFiles[i] = {
|
|
4122
|
-
absolutePath:
|
|
4338
|
+
absolutePath: join16(vttFileDir, newFilename),
|
|
4123
4339
|
relativePath: newRelativePath,
|
|
4124
4340
|
filename: newFilename
|
|
4125
4341
|
};
|
|
@@ -4132,8 +4348,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4132
4348
|
}
|
|
4133
4349
|
|
|
4134
4350
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
4135
|
-
import { existsSync as
|
|
4136
|
-
import { basename as basename5, dirname as dirname13, join as
|
|
4351
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync15 } from "fs";
|
|
4352
|
+
import { basename as basename5, dirname as dirname13, join as join17 } from "path";
|
|
4137
4353
|
|
|
4138
4354
|
// src/commands/transcript/cleanText.ts
|
|
4139
4355
|
function cleanText(text) {
|
|
@@ -4273,10 +4489,10 @@ function extractSpeaker(fullText) {
|
|
|
4273
4489
|
function isTextLine(line) {
|
|
4274
4490
|
return !!line.trim() && !line.includes("-->");
|
|
4275
4491
|
}
|
|
4276
|
-
function scanTextLines(lines,
|
|
4277
|
-
let i =
|
|
4492
|
+
function scanTextLines(lines, start2) {
|
|
4493
|
+
let i = start2;
|
|
4278
4494
|
while (i < lines.length && isTextLine(lines[i])) i++;
|
|
4279
|
-
return { texts: lines.slice(
|
|
4495
|
+
return { texts: lines.slice(start2, i).map((l) => l.trim()), end: i };
|
|
4280
4496
|
}
|
|
4281
4497
|
function collectTextLines(lines, startIndex) {
|
|
4282
4498
|
const { texts, end } = scanTextLines(lines, startIndex);
|
|
@@ -4343,21 +4559,21 @@ function toMdFilename(vttFilename) {
|
|
|
4343
4559
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
4344
4560
|
}
|
|
4345
4561
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
4346
|
-
return relativeDir === "." ? transcriptsDir :
|
|
4562
|
+
return relativeDir === "." ? transcriptsDir : join17(transcriptsDir, relativeDir);
|
|
4347
4563
|
}
|
|
4348
4564
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
4349
4565
|
const mdFile = toMdFilename(vttFile.filename);
|
|
4350
4566
|
const relativeDir = dirname13(vttFile.relativePath);
|
|
4351
4567
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
4352
|
-
const outputPath =
|
|
4568
|
+
const outputPath = join17(outputDir, mdFile);
|
|
4353
4569
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
4354
4570
|
}
|
|
4355
4571
|
function logSkipped(relativeDir, mdFile) {
|
|
4356
|
-
console.log(`Skipping (already exists): ${
|
|
4572
|
+
console.log(`Skipping (already exists): ${join17(relativeDir, mdFile)}`);
|
|
4357
4573
|
return "skipped";
|
|
4358
4574
|
}
|
|
4359
4575
|
function ensureDirectory(dir, label) {
|
|
4360
|
-
if (!
|
|
4576
|
+
if (!existsSync19(dir)) {
|
|
4361
4577
|
mkdirSync5(dir, { recursive: true });
|
|
4362
4578
|
console.log(`Created ${label}: ${dir}`);
|
|
4363
4579
|
}
|
|
@@ -4380,10 +4596,10 @@ function logReduction(cueCount, messageCount) {
|
|
|
4380
4596
|
}
|
|
4381
4597
|
function readAndParseCues(inputPath) {
|
|
4382
4598
|
console.log(`Reading: ${inputPath}`);
|
|
4383
|
-
return processCues(
|
|
4599
|
+
return processCues(readFileSync13(inputPath, "utf-8"));
|
|
4384
4600
|
}
|
|
4385
4601
|
function writeFormatted(outputPath, content) {
|
|
4386
|
-
|
|
4602
|
+
writeFileSync15(outputPath, content, "utf-8");
|
|
4387
4603
|
console.log(`Written: ${outputPath}`);
|
|
4388
4604
|
}
|
|
4389
4605
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -4393,7 +4609,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
4393
4609
|
logReduction(cues.length, chatMessages.length);
|
|
4394
4610
|
}
|
|
4395
4611
|
function tryProcessVtt(vttFile, paths) {
|
|
4396
|
-
if (
|
|
4612
|
+
if (existsSync19(paths.outputPath))
|
|
4397
4613
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
4398
4614
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
4399
4615
|
return "processed";
|
|
@@ -4419,7 +4635,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
4419
4635
|
logSummary(counts);
|
|
4420
4636
|
}
|
|
4421
4637
|
function requireVttDir(vttDir) {
|
|
4422
|
-
if (!
|
|
4638
|
+
if (!existsSync20(vttDir)) {
|
|
4423
4639
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
4424
4640
|
process.exit(1);
|
|
4425
4641
|
}
|
|
@@ -4451,28 +4667,28 @@ async function format() {
|
|
|
4451
4667
|
}
|
|
4452
4668
|
|
|
4453
4669
|
// src/commands/transcript/summarise/index.ts
|
|
4454
|
-
import { existsSync as
|
|
4455
|
-
import { basename as basename6, dirname as dirname15, join as
|
|
4670
|
+
import { existsSync as existsSync22 } from "fs";
|
|
4671
|
+
import { basename as basename6, dirname as dirname15, join as join19, relative as relative2 } from "path";
|
|
4456
4672
|
|
|
4457
4673
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4458
4674
|
import {
|
|
4459
|
-
existsSync as
|
|
4675
|
+
existsSync as existsSync21,
|
|
4460
4676
|
mkdirSync as mkdirSync6,
|
|
4461
|
-
readFileSync as
|
|
4677
|
+
readFileSync as readFileSync14,
|
|
4462
4678
|
renameSync as renameSync2,
|
|
4463
4679
|
rmSync
|
|
4464
4680
|
} from "fs";
|
|
4465
|
-
import { dirname as dirname14, join as
|
|
4681
|
+
import { dirname as dirname14, join as join18 } from "path";
|
|
4466
4682
|
|
|
4467
4683
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
4468
|
-
import
|
|
4684
|
+
import chalk48 from "chalk";
|
|
4469
4685
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
4470
4686
|
function validateStagedContent(filename, content) {
|
|
4471
4687
|
const firstLine = content.split("\n")[0];
|
|
4472
4688
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
4473
4689
|
if (!match) {
|
|
4474
4690
|
console.error(
|
|
4475
|
-
|
|
4691
|
+
chalk48.red(
|
|
4476
4692
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
4477
4693
|
)
|
|
4478
4694
|
);
|
|
@@ -4481,7 +4697,7 @@ function validateStagedContent(filename, content) {
|
|
|
4481
4697
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
4482
4698
|
if (!contentAfterLink) {
|
|
4483
4699
|
console.error(
|
|
4484
|
-
|
|
4700
|
+
chalk48.red(
|
|
4485
4701
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
4486
4702
|
)
|
|
4487
4703
|
);
|
|
@@ -4491,9 +4707,9 @@ function validateStagedContent(filename, content) {
|
|
|
4491
4707
|
}
|
|
4492
4708
|
|
|
4493
4709
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4494
|
-
var STAGING_DIR =
|
|
4710
|
+
var STAGING_DIR = join18(process.cwd(), ".assist", "transcript");
|
|
4495
4711
|
function processStagedFile() {
|
|
4496
|
-
if (!
|
|
4712
|
+
if (!existsSync21(STAGING_DIR)) {
|
|
4497
4713
|
return false;
|
|
4498
4714
|
}
|
|
4499
4715
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -4502,7 +4718,7 @@ function processStagedFile() {
|
|
|
4502
4718
|
}
|
|
4503
4719
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
4504
4720
|
const stagedFile = stagedFiles[0];
|
|
4505
|
-
const content =
|
|
4721
|
+
const content = readFileSync14(stagedFile.absolutePath, "utf-8");
|
|
4506
4722
|
validateStagedContent(stagedFile.filename, content);
|
|
4507
4723
|
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
4508
4724
|
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
@@ -4515,9 +4731,9 @@ function processStagedFile() {
|
|
|
4515
4731
|
);
|
|
4516
4732
|
process.exit(1);
|
|
4517
4733
|
}
|
|
4518
|
-
const destPath =
|
|
4734
|
+
const destPath = join18(summaryDir, matchingTranscript.relativePath);
|
|
4519
4735
|
const destDir = dirname14(destPath);
|
|
4520
|
-
if (!
|
|
4736
|
+
if (!existsSync21(destDir)) {
|
|
4521
4737
|
mkdirSync6(destDir, { recursive: true });
|
|
4522
4738
|
}
|
|
4523
4739
|
renameSync2(stagedFile.absolutePath, destPath);
|
|
@@ -4531,7 +4747,7 @@ function processStagedFile() {
|
|
|
4531
4747
|
// src/commands/transcript/summarise/index.ts
|
|
4532
4748
|
function buildRelativeKey(relativePath, baseName) {
|
|
4533
4749
|
const relDir = dirname15(relativePath);
|
|
4534
|
-
return relDir === "." ? baseName :
|
|
4750
|
+
return relDir === "." ? baseName : join19(relDir, baseName);
|
|
4535
4751
|
}
|
|
4536
4752
|
function buildSummaryIndex(summaryDir) {
|
|
4537
4753
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -4544,7 +4760,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
4544
4760
|
function summarise() {
|
|
4545
4761
|
processStagedFile();
|
|
4546
4762
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
4547
|
-
if (!
|
|
4763
|
+
if (!existsSync22(transcriptsDir)) {
|
|
4548
4764
|
console.log("No transcripts directory found.");
|
|
4549
4765
|
return;
|
|
4550
4766
|
}
|
|
@@ -4565,8 +4781,8 @@ function summarise() {
|
|
|
4565
4781
|
}
|
|
4566
4782
|
const next2 = missing[0];
|
|
4567
4783
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
4568
|
-
const outputPath =
|
|
4569
|
-
const summaryFileDir =
|
|
4784
|
+
const outputPath = join19(STAGING_DIR, outputFilename);
|
|
4785
|
+
const summaryFileDir = join19(summaryDir, dirname15(next2.relativePath));
|
|
4570
4786
|
const relativeTranscriptPath = encodeURI(
|
|
4571
4787
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
4572
4788
|
);
|
|
@@ -4653,7 +4869,7 @@ function saveNewRunConfig(name, command, args) {
|
|
|
4653
4869
|
runList.push(buildRunEntry(name, command, args));
|
|
4654
4870
|
saveConfig(config);
|
|
4655
4871
|
}
|
|
4656
|
-
function
|
|
4872
|
+
function add2() {
|
|
4657
4873
|
const { name, command, args } = requireParsedArgs();
|
|
4658
4874
|
saveNewRunConfig(name, command, args);
|
|
4659
4875
|
console.log(
|
|
@@ -4734,7 +4950,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
4734
4950
|
// src/commands/sync/syncClaudeMd.ts
|
|
4735
4951
|
import * as fs21 from "fs";
|
|
4736
4952
|
import * as path27 from "path";
|
|
4737
|
-
import
|
|
4953
|
+
import chalk49 from "chalk";
|
|
4738
4954
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
4739
4955
|
const source = path27.join(claudeDir, "CLAUDE.md");
|
|
4740
4956
|
const target = path27.join(targetBase, "CLAUDE.md");
|
|
@@ -4743,12 +4959,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
4743
4959
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
4744
4960
|
if (sourceContent !== targetContent) {
|
|
4745
4961
|
console.log(
|
|
4746
|
-
|
|
4962
|
+
chalk49.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
4747
4963
|
);
|
|
4748
4964
|
console.log();
|
|
4749
4965
|
printDiff(targetContent, sourceContent);
|
|
4750
4966
|
const confirm = await promptConfirm(
|
|
4751
|
-
|
|
4967
|
+
chalk49.red("Overwrite existing CLAUDE.md?"),
|
|
4752
4968
|
false
|
|
4753
4969
|
);
|
|
4754
4970
|
if (!confirm) {
|
|
@@ -4764,7 +4980,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
4764
4980
|
// src/commands/sync/syncSettings.ts
|
|
4765
4981
|
import * as fs22 from "fs";
|
|
4766
4982
|
import * as path28 from "path";
|
|
4767
|
-
import
|
|
4983
|
+
import chalk50 from "chalk";
|
|
4768
4984
|
async function syncSettings(claudeDir, targetBase) {
|
|
4769
4985
|
const source = path28.join(claudeDir, "settings.json");
|
|
4770
4986
|
const target = path28.join(targetBase, "settings.json");
|
|
@@ -4775,12 +4991,12 @@ async function syncSettings(claudeDir, targetBase) {
|
|
|
4775
4991
|
const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
|
|
4776
4992
|
if (normalizedSource !== normalizedTarget) {
|
|
4777
4993
|
console.log(
|
|
4778
|
-
|
|
4994
|
+
chalk50.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
|
|
4779
4995
|
);
|
|
4780
4996
|
console.log();
|
|
4781
4997
|
printDiff(targetContent, sourceContent);
|
|
4782
4998
|
const confirm = await promptConfirm(
|
|
4783
|
-
|
|
4999
|
+
chalk50.red("Overwrite existing settings.json?"),
|
|
4784
5000
|
false
|
|
4785
5001
|
);
|
|
4786
5002
|
if (!confirm) {
|
|
@@ -4832,7 +5048,7 @@ configCommand.command("list").description("List all config values").action(confi
|
|
|
4832
5048
|
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().action((name, args) => {
|
|
4833
5049
|
run2(name, args);
|
|
4834
5050
|
});
|
|
4835
|
-
runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() =>
|
|
5051
|
+
runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() => add2());
|
|
4836
5052
|
registerNew(program);
|
|
4837
5053
|
var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
|
|
4838
5054
|
lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
|
|
@@ -4843,6 +5059,7 @@ program.command("notify").description(
|
|
|
4843
5059
|
"Show notification from Claude Code hook (reads JSON from stdin)"
|
|
4844
5060
|
).action(notify);
|
|
4845
5061
|
registerPrs(program);
|
|
5062
|
+
registerBacklog(program);
|
|
4846
5063
|
registerVerify(program);
|
|
4847
5064
|
registerRefactor(program);
|
|
4848
5065
|
registerDevlog(program);
|