@staff0rd/assist 0.52.0 → 0.53.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 +394 -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>]` - 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.53.0",
|
|
11
11
|
type: "module",
|
|
12
12
|
main: "dist/index.js",
|
|
13
13
|
bin: {
|
|
@@ -1802,16 +1802,220 @@ 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)} ${item.name} ${chalk26.dim(`#${item.id}`)}`
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
// src/commands/backlog/start/index.ts
|
|
1806
1991
|
import chalk27 from "chalk";
|
|
1992
|
+
async function start(id) {
|
|
1993
|
+
const name = setStatus(id, "in-progress");
|
|
1994
|
+
if (name) {
|
|
1995
|
+
console.log(chalk27.green(`Started item #${id}: ${name}`));
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// src/commands/registerBacklog.ts
|
|
2000
|
+
function registerBacklog(program2) {
|
|
2001
|
+
const backlogCommand = program2.command("backlog").description("Manage a backlog of work items").action(list);
|
|
2002
|
+
backlogCommand.command("init").description("Create an empty assist.backlog.yml").action(init6);
|
|
2003
|
+
backlogCommand.command("list").description("List all backlog items").option("--status <type>", "Filter by status (todo, in-progress, done)").action(list);
|
|
2004
|
+
backlogCommand.command("add").description("Add a new backlog item").action(add);
|
|
2005
|
+
backlogCommand.command("start <id>").description("Set a backlog item to in-progress").action(start);
|
|
2006
|
+
backlogCommand.command("done <id>").description("Set a backlog item to done").action(done);
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
// src/commands/complexity/analyze.ts
|
|
2010
|
+
import chalk33 from "chalk";
|
|
1807
2011
|
|
|
1808
2012
|
// src/commands/complexity/cyclomatic.ts
|
|
1809
|
-
import
|
|
2013
|
+
import chalk29 from "chalk";
|
|
1810
2014
|
|
|
1811
2015
|
// src/commands/complexity/shared/index.ts
|
|
1812
2016
|
import fs11 from "fs";
|
|
1813
2017
|
import path16 from "path";
|
|
1814
|
-
import
|
|
2018
|
+
import chalk28 from "chalk";
|
|
1815
2019
|
import ts5 from "typescript";
|
|
1816
2020
|
|
|
1817
2021
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -2057,7 +2261,7 @@ function createSourceFromFile(filePath) {
|
|
|
2057
2261
|
function withSourceFiles(pattern2, callback) {
|
|
2058
2262
|
const files = findSourceFiles2(pattern2);
|
|
2059
2263
|
if (files.length === 0) {
|
|
2060
|
-
console.log(
|
|
2264
|
+
console.log(chalk28.yellow("No files found matching pattern"));
|
|
2061
2265
|
return void 0;
|
|
2062
2266
|
}
|
|
2063
2267
|
return callback(files);
|
|
@@ -2090,11 +2294,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2090
2294
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
2091
2295
|
for (const { file, name, complexity } of results) {
|
|
2092
2296
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
2093
|
-
const color = exceedsThreshold ?
|
|
2094
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
2297
|
+
const color = exceedsThreshold ? chalk29.red : chalk29.white;
|
|
2298
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk29.cyan(complexity)}`);
|
|
2095
2299
|
}
|
|
2096
2300
|
console.log(
|
|
2097
|
-
|
|
2301
|
+
chalk29.dim(
|
|
2098
2302
|
`
|
|
2099
2303
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2100
2304
|
)
|
|
@@ -2106,7 +2310,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2106
2310
|
}
|
|
2107
2311
|
|
|
2108
2312
|
// src/commands/complexity/halstead.ts
|
|
2109
|
-
import
|
|
2313
|
+
import chalk30 from "chalk";
|
|
2110
2314
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
2111
2315
|
withSourceFiles(pattern2, (files) => {
|
|
2112
2316
|
const results = [];
|
|
@@ -2121,13 +2325,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2121
2325
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
2122
2326
|
for (const { file, name, metrics } of results) {
|
|
2123
2327
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
2124
|
-
const color = exceedsThreshold ?
|
|
2328
|
+
const color = exceedsThreshold ? chalk30.red : chalk30.white;
|
|
2125
2329
|
console.log(
|
|
2126
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
2330
|
+
`${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
2331
|
);
|
|
2128
2332
|
}
|
|
2129
2333
|
console.log(
|
|
2130
|
-
|
|
2334
|
+
chalk30.dim(
|
|
2131
2335
|
`
|
|
2132
2336
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
2133
2337
|
)
|
|
@@ -2142,24 +2346,24 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
2142
2346
|
import fs12 from "fs";
|
|
2143
2347
|
|
|
2144
2348
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
2145
|
-
import
|
|
2349
|
+
import chalk31 from "chalk";
|
|
2146
2350
|
function displayMaintainabilityResults(results, threshold) {
|
|
2147
2351
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
2148
2352
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
2149
|
-
console.log(
|
|
2353
|
+
console.log(chalk31.green("All files pass maintainability threshold"));
|
|
2150
2354
|
} else {
|
|
2151
2355
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
2152
|
-
const color = threshold !== void 0 ?
|
|
2356
|
+
const color = threshold !== void 0 ? chalk31.red : chalk31.white;
|
|
2153
2357
|
console.log(
|
|
2154
|
-
`${color(file)} \u2192 avg: ${
|
|
2358
|
+
`${color(file)} \u2192 avg: ${chalk31.cyan(avgMaintainability.toFixed(1))}, min: ${chalk31.yellow(minMaintainability.toFixed(1))}`
|
|
2155
2359
|
);
|
|
2156
2360
|
}
|
|
2157
2361
|
}
|
|
2158
|
-
console.log(
|
|
2362
|
+
console.log(chalk31.dim(`
|
|
2159
2363
|
Analyzed ${results.length} files`));
|
|
2160
2364
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
2161
2365
|
console.error(
|
|
2162
|
-
|
|
2366
|
+
chalk31.red(
|
|
2163
2367
|
`
|
|
2164
2368
|
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
2369
|
)
|
|
@@ -2218,7 +2422,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2218
2422
|
|
|
2219
2423
|
// src/commands/complexity/sloc.ts
|
|
2220
2424
|
import fs13 from "fs";
|
|
2221
|
-
import
|
|
2425
|
+
import chalk32 from "chalk";
|
|
2222
2426
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
2223
2427
|
withSourceFiles(pattern2, (files) => {
|
|
2224
2428
|
const results = [];
|
|
@@ -2234,12 +2438,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
2234
2438
|
results.sort((a, b) => b.lines - a.lines);
|
|
2235
2439
|
for (const { file, lines } of results) {
|
|
2236
2440
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
2237
|
-
const color = exceedsThreshold ?
|
|
2238
|
-
console.log(`${color(file)} \u2192 ${
|
|
2441
|
+
const color = exceedsThreshold ? chalk32.red : chalk32.white;
|
|
2442
|
+
console.log(`${color(file)} \u2192 ${chalk32.cyan(lines)} lines`);
|
|
2239
2443
|
}
|
|
2240
2444
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
2241
2445
|
console.log(
|
|
2242
|
-
|
|
2446
|
+
chalk32.dim(`
|
|
2243
2447
|
Total: ${total} lines across ${files.length} files`)
|
|
2244
2448
|
);
|
|
2245
2449
|
if (hasViolation) {
|
|
@@ -2253,21 +2457,21 @@ async function analyze(pattern2) {
|
|
|
2253
2457
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
2254
2458
|
const files = findSourceFiles2(searchPattern);
|
|
2255
2459
|
if (files.length === 0) {
|
|
2256
|
-
console.log(
|
|
2460
|
+
console.log(chalk33.yellow("No files found matching pattern"));
|
|
2257
2461
|
return;
|
|
2258
2462
|
}
|
|
2259
2463
|
if (files.length === 1) {
|
|
2260
2464
|
const file = files[0];
|
|
2261
|
-
console.log(
|
|
2465
|
+
console.log(chalk33.bold.underline("SLOC"));
|
|
2262
2466
|
await sloc(file);
|
|
2263
2467
|
console.log();
|
|
2264
|
-
console.log(
|
|
2468
|
+
console.log(chalk33.bold.underline("Cyclomatic Complexity"));
|
|
2265
2469
|
await cyclomatic(file);
|
|
2266
2470
|
console.log();
|
|
2267
|
-
console.log(
|
|
2471
|
+
console.log(chalk33.bold.underline("Halstead Metrics"));
|
|
2268
2472
|
await halstead(file);
|
|
2269
2473
|
console.log();
|
|
2270
|
-
console.log(
|
|
2474
|
+
console.log(chalk33.bold.underline("Maintainability Index"));
|
|
2271
2475
|
await maintainability(file);
|
|
2272
2476
|
return;
|
|
2273
2477
|
}
|
|
@@ -2294,8 +2498,8 @@ function registerComplexity(program2) {
|
|
|
2294
2498
|
}
|
|
2295
2499
|
|
|
2296
2500
|
// src/commands/deploy/redirect.ts
|
|
2297
|
-
import { existsSync as
|
|
2298
|
-
import
|
|
2501
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
2502
|
+
import chalk34 from "chalk";
|
|
2299
2503
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
2300
2504
|
if (!window.location.pathname.endsWith('/')) {
|
|
2301
2505
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -2303,23 +2507,23 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
2303
2507
|
</script>`;
|
|
2304
2508
|
function redirect() {
|
|
2305
2509
|
const indexPath = "index.html";
|
|
2306
|
-
if (!
|
|
2307
|
-
console.log(
|
|
2510
|
+
if (!existsSync15(indexPath)) {
|
|
2511
|
+
console.log(chalk34.yellow("No index.html found"));
|
|
2308
2512
|
return;
|
|
2309
2513
|
}
|
|
2310
|
-
const content =
|
|
2514
|
+
const content = readFileSync10(indexPath, "utf-8");
|
|
2311
2515
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
2312
|
-
console.log(
|
|
2516
|
+
console.log(chalk34.dim("Trailing slash script already present"));
|
|
2313
2517
|
return;
|
|
2314
2518
|
}
|
|
2315
2519
|
const headCloseIndex = content.indexOf("</head>");
|
|
2316
2520
|
if (headCloseIndex === -1) {
|
|
2317
|
-
console.log(
|
|
2521
|
+
console.log(chalk34.red("Could not find </head> tag in index.html"));
|
|
2318
2522
|
return;
|
|
2319
2523
|
}
|
|
2320
2524
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
2321
|
-
|
|
2322
|
-
console.log(
|
|
2525
|
+
writeFileSync11(indexPath, newContent);
|
|
2526
|
+
console.log(chalk34.green("Added trailing slash redirect to index.html"));
|
|
2323
2527
|
}
|
|
2324
2528
|
|
|
2325
2529
|
// src/commands/registerDeploy.ts
|
|
@@ -2335,19 +2539,19 @@ import { basename as basename3 } from "path";
|
|
|
2335
2539
|
|
|
2336
2540
|
// src/commands/devlog/shared.ts
|
|
2337
2541
|
import { execSync as execSync11 } from "child_process";
|
|
2338
|
-
import
|
|
2542
|
+
import chalk35 from "chalk";
|
|
2339
2543
|
|
|
2340
2544
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
2341
|
-
import { readdirSync, readFileSync as
|
|
2545
|
+
import { readdirSync, readFileSync as readFileSync11 } from "fs";
|
|
2342
2546
|
import { homedir } from "os";
|
|
2343
|
-
import { join as
|
|
2344
|
-
var DEVLOG_DIR =
|
|
2547
|
+
import { join as join9 } from "path";
|
|
2548
|
+
var DEVLOG_DIR = join9(homedir(), "git/blog/src/content/devlog");
|
|
2345
2549
|
function loadDevlogEntries(repoName) {
|
|
2346
2550
|
const entries = /* @__PURE__ */ new Map();
|
|
2347
2551
|
try {
|
|
2348
2552
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
2349
2553
|
for (const file of files) {
|
|
2350
|
-
const content =
|
|
2554
|
+
const content = readFileSync11(join9(DEVLOG_DIR, file), "utf-8");
|
|
2351
2555
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
2352
2556
|
if (frontmatterMatch) {
|
|
2353
2557
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -2396,13 +2600,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
2396
2600
|
}
|
|
2397
2601
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
2398
2602
|
for (const commit2 of commits) {
|
|
2399
|
-
console.log(` ${
|
|
2603
|
+
console.log(` ${chalk35.yellow(commit2.hash)} ${commit2.message}`);
|
|
2400
2604
|
if (verbose) {
|
|
2401
2605
|
const visibleFiles = commit2.files.filter(
|
|
2402
2606
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
2403
2607
|
);
|
|
2404
2608
|
for (const file of visibleFiles) {
|
|
2405
|
-
console.log(` ${
|
|
2609
|
+
console.log(` ${chalk35.dim(file)}`);
|
|
2406
2610
|
}
|
|
2407
2611
|
}
|
|
2408
2612
|
}
|
|
@@ -2427,20 +2631,20 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
2427
2631
|
}
|
|
2428
2632
|
|
|
2429
2633
|
// src/commands/devlog/list/printDateHeader.ts
|
|
2430
|
-
import
|
|
2634
|
+
import chalk36 from "chalk";
|
|
2431
2635
|
function printDateHeader(date, isSkipped, entries) {
|
|
2432
2636
|
if (isSkipped) {
|
|
2433
|
-
console.log(`${
|
|
2637
|
+
console.log(`${chalk36.bold.blue(date)} ${chalk36.dim("skipped")}`);
|
|
2434
2638
|
} else if (entries && entries.length > 0) {
|
|
2435
|
-
const entryInfo = entries.map((e) => `${
|
|
2436
|
-
console.log(`${
|
|
2639
|
+
const entryInfo = entries.map((e) => `${chalk36.green(e.version)} ${e.title}`).join(" | ");
|
|
2640
|
+
console.log(`${chalk36.bold.blue(date)} ${entryInfo}`);
|
|
2437
2641
|
} else {
|
|
2438
|
-
console.log(`${
|
|
2642
|
+
console.log(`${chalk36.bold.blue(date)} ${chalk36.red("\u26A0 devlog missing")}`);
|
|
2439
2643
|
}
|
|
2440
2644
|
}
|
|
2441
2645
|
|
|
2442
2646
|
// src/commands/devlog/list/index.ts
|
|
2443
|
-
function
|
|
2647
|
+
function list2(options2) {
|
|
2444
2648
|
const config = loadConfig();
|
|
2445
2649
|
const days = options2.days ?? 30;
|
|
2446
2650
|
const ignore2 = options2.ignore ?? config.devlog?.ignore ?? [];
|
|
@@ -2538,24 +2742,24 @@ function bumpVersion(version2, type) {
|
|
|
2538
2742
|
|
|
2539
2743
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
2540
2744
|
import { execSync as execSync14 } from "child_process";
|
|
2541
|
-
import
|
|
2745
|
+
import chalk38 from "chalk";
|
|
2542
2746
|
|
|
2543
2747
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
2544
|
-
import
|
|
2748
|
+
import chalk37 from "chalk";
|
|
2545
2749
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
2546
2750
|
if (conventional && firstHash) {
|
|
2547
2751
|
const version2 = getVersionAtCommit(firstHash);
|
|
2548
2752
|
if (version2) {
|
|
2549
|
-
console.log(`${
|
|
2753
|
+
console.log(`${chalk37.bold("version:")} ${stripToMinor(version2)}`);
|
|
2550
2754
|
} else {
|
|
2551
|
-
console.log(`${
|
|
2755
|
+
console.log(`${chalk37.bold("version:")} ${chalk37.red("unknown")}`);
|
|
2552
2756
|
}
|
|
2553
2757
|
} else if (patchVersion && minorVersion) {
|
|
2554
2758
|
console.log(
|
|
2555
|
-
`${
|
|
2759
|
+
`${chalk37.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
2556
2760
|
);
|
|
2557
2761
|
} else {
|
|
2558
|
-
console.log(`${
|
|
2762
|
+
console.log(`${chalk37.bold("version:")} v0.1 (initial)`);
|
|
2559
2763
|
}
|
|
2560
2764
|
}
|
|
2561
2765
|
|
|
@@ -2602,16 +2806,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
2602
2806
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
2603
2807
|
}
|
|
2604
2808
|
function logName(repoName) {
|
|
2605
|
-
console.log(`${
|
|
2809
|
+
console.log(`${chalk38.bold("name:")} ${repoName}`);
|
|
2606
2810
|
}
|
|
2607
2811
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
2608
2812
|
logName(ctx.repoName);
|
|
2609
2813
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
2610
|
-
console.log(
|
|
2814
|
+
console.log(chalk38.bold.blue(targetDate));
|
|
2611
2815
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
2612
2816
|
}
|
|
2613
2817
|
function logNoCommits(lastInfo) {
|
|
2614
|
-
console.log(
|
|
2818
|
+
console.log(chalk38.dim(noCommitsMessage(!!lastInfo)));
|
|
2615
2819
|
}
|
|
2616
2820
|
|
|
2617
2821
|
// src/commands/devlog/next/index.ts
|
|
@@ -2646,16 +2850,16 @@ function next(options2) {
|
|
|
2646
2850
|
}
|
|
2647
2851
|
|
|
2648
2852
|
// src/commands/devlog/skip.ts
|
|
2649
|
-
import
|
|
2853
|
+
import chalk39 from "chalk";
|
|
2650
2854
|
function skip(date) {
|
|
2651
2855
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
2652
|
-
console.log(
|
|
2856
|
+
console.log(chalk39.red("Invalid date format. Use YYYY-MM-DD"));
|
|
2653
2857
|
process.exit(1);
|
|
2654
2858
|
}
|
|
2655
2859
|
const config = loadConfig();
|
|
2656
2860
|
const skipDays = config.devlog?.skip?.days ?? [];
|
|
2657
2861
|
if (skipDays.includes(date)) {
|
|
2658
|
-
console.log(
|
|
2862
|
+
console.log(chalk39.yellow(`${date} is already in skip list`));
|
|
2659
2863
|
return;
|
|
2660
2864
|
}
|
|
2661
2865
|
skipDays.push(date);
|
|
@@ -2668,20 +2872,20 @@ function skip(date) {
|
|
|
2668
2872
|
}
|
|
2669
2873
|
};
|
|
2670
2874
|
saveConfig(config);
|
|
2671
|
-
console.log(
|
|
2875
|
+
console.log(chalk39.green(`Added ${date} to skip list`));
|
|
2672
2876
|
}
|
|
2673
2877
|
|
|
2674
2878
|
// src/commands/devlog/version.ts
|
|
2675
|
-
import
|
|
2879
|
+
import chalk40 from "chalk";
|
|
2676
2880
|
function version() {
|
|
2677
2881
|
const config = loadConfig();
|
|
2678
2882
|
const name = getRepoName();
|
|
2679
2883
|
const lastInfo = getLastVersionInfo(name, config);
|
|
2680
2884
|
const lastVersion = lastInfo?.version ?? null;
|
|
2681
2885
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
2682
|
-
console.log(`${
|
|
2683
|
-
console.log(`${
|
|
2684
|
-
console.log(`${
|
|
2886
|
+
console.log(`${chalk40.bold("name:")} ${name}`);
|
|
2887
|
+
console.log(`${chalk40.bold("last:")} ${lastVersion ?? chalk40.dim("none")}`);
|
|
2888
|
+
console.log(`${chalk40.bold("next:")} ${nextVersion ?? chalk40.dim("none")}`);
|
|
2685
2889
|
}
|
|
2686
2890
|
|
|
2687
2891
|
// src/commands/registerDevlog.ts
|
|
@@ -2691,7 +2895,7 @@ function registerDevlog(program2) {
|
|
|
2691
2895
|
"--days <number>",
|
|
2692
2896
|
"Number of days to show (default: 30)",
|
|
2693
2897
|
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(
|
|
2898
|
+
).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
2899
|
devlogCommand.command("version").description("Show current repo name and version info").action(version);
|
|
2696
2900
|
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
2901
|
devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
|
|
@@ -2702,28 +2906,28 @@ import { execSync as execSync17 } from "child_process";
|
|
|
2702
2906
|
|
|
2703
2907
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
2704
2908
|
import { execSync as execSync16 } from "child_process";
|
|
2705
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
2909
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync12 } from "fs";
|
|
2706
2910
|
import { tmpdir } from "os";
|
|
2707
|
-
import { join as
|
|
2911
|
+
import { join as join11 } from "path";
|
|
2708
2912
|
|
|
2709
2913
|
// src/commands/prs/loadCommentsCache.ts
|
|
2710
|
-
import { existsSync as
|
|
2711
|
-
import { join as
|
|
2914
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12, unlinkSync as unlinkSync2 } from "fs";
|
|
2915
|
+
import { join as join10 } from "path";
|
|
2712
2916
|
import { parse } from "yaml";
|
|
2713
2917
|
function getCachePath(prNumber) {
|
|
2714
|
-
return
|
|
2918
|
+
return join10(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
2715
2919
|
}
|
|
2716
2920
|
function loadCommentsCache(prNumber) {
|
|
2717
2921
|
const cachePath = getCachePath(prNumber);
|
|
2718
|
-
if (!
|
|
2922
|
+
if (!existsSync16(cachePath)) {
|
|
2719
2923
|
return null;
|
|
2720
2924
|
}
|
|
2721
|
-
const content =
|
|
2925
|
+
const content = readFileSync12(cachePath, "utf-8");
|
|
2722
2926
|
return parse(content);
|
|
2723
2927
|
}
|
|
2724
2928
|
function deleteCommentsCache(prNumber) {
|
|
2725
2929
|
const cachePath = getCachePath(prNumber);
|
|
2726
|
-
if (
|
|
2930
|
+
if (existsSync16(cachePath)) {
|
|
2727
2931
|
unlinkSync2(cachePath);
|
|
2728
2932
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
2729
2933
|
}
|
|
@@ -2774,8 +2978,8 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
2774
2978
|
}
|
|
2775
2979
|
function resolveThread(threadId) {
|
|
2776
2980
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
2777
|
-
const queryFile =
|
|
2778
|
-
|
|
2981
|
+
const queryFile = join11(tmpdir(), `gh-mutation-${Date.now()}.graphql`);
|
|
2982
|
+
writeFileSync12(queryFile, mutation);
|
|
2779
2983
|
try {
|
|
2780
2984
|
execSync16(
|
|
2781
2985
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
@@ -2855,8 +3059,8 @@ function fixed(commentId, sha) {
|
|
|
2855
3059
|
}
|
|
2856
3060
|
|
|
2857
3061
|
// src/commands/prs/listComments/index.ts
|
|
2858
|
-
import { existsSync as
|
|
2859
|
-
import { join as
|
|
3062
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync14 } from "fs";
|
|
3063
|
+
import { join as join13 } from "path";
|
|
2860
3064
|
import { stringify } from "yaml";
|
|
2861
3065
|
|
|
2862
3066
|
// src/lib/isClaudeCode.ts
|
|
@@ -2866,13 +3070,13 @@ function isClaudeCode() {
|
|
|
2866
3070
|
|
|
2867
3071
|
// src/commands/prs/fetchThreadIds.ts
|
|
2868
3072
|
import { execSync as execSync18 } from "child_process";
|
|
2869
|
-
import { unlinkSync as unlinkSync4, writeFileSync as
|
|
3073
|
+
import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
|
|
2870
3074
|
import { tmpdir as tmpdir2 } from "os";
|
|
2871
|
-
import { join as
|
|
3075
|
+
import { join as join12 } from "path";
|
|
2872
3076
|
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
3077
|
function fetchThreadIds(org, repo, prNumber) {
|
|
2874
|
-
const queryFile =
|
|
2875
|
-
|
|
3078
|
+
const queryFile = join12(tmpdir2(), `gh-query-${Date.now()}.graphql`);
|
|
3079
|
+
writeFileSync13(queryFile, THREAD_QUERY);
|
|
2876
3080
|
try {
|
|
2877
3081
|
const result = execSync18(
|
|
2878
3082
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -2938,20 +3142,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
2938
3142
|
}
|
|
2939
3143
|
|
|
2940
3144
|
// src/commands/prs/listComments/formatForHuman.ts
|
|
2941
|
-
import
|
|
3145
|
+
import chalk41 from "chalk";
|
|
2942
3146
|
function formatForHuman(comment) {
|
|
2943
3147
|
if (comment.type === "review") {
|
|
2944
|
-
const stateColor = comment.state === "APPROVED" ?
|
|
3148
|
+
const stateColor = comment.state === "APPROVED" ? chalk41.green : comment.state === "CHANGES_REQUESTED" ? chalk41.red : chalk41.yellow;
|
|
2945
3149
|
return [
|
|
2946
|
-
`${
|
|
3150
|
+
`${chalk41.cyan("Review")} by ${chalk41.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
|
|
2947
3151
|
comment.body,
|
|
2948
3152
|
""
|
|
2949
3153
|
].join("\n");
|
|
2950
3154
|
}
|
|
2951
3155
|
const location = comment.line ? `:${comment.line}` : "";
|
|
2952
3156
|
return [
|
|
2953
|
-
`${
|
|
2954
|
-
|
|
3157
|
+
`${chalk41.cyan("Line comment")} by ${chalk41.bold(comment.user)} on ${chalk41.dim(`${comment.path}${location}`)}`,
|
|
3158
|
+
chalk41.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
2955
3159
|
comment.body,
|
|
2956
3160
|
""
|
|
2957
3161
|
].join("\n");
|
|
@@ -2974,8 +3178,8 @@ function printComments(comments) {
|
|
|
2974
3178
|
}
|
|
2975
3179
|
}
|
|
2976
3180
|
function writeCommentsCache(prNumber, comments) {
|
|
2977
|
-
const assistDir =
|
|
2978
|
-
if (!
|
|
3181
|
+
const assistDir = join13(process.cwd(), ".assist");
|
|
3182
|
+
if (!existsSync17(assistDir)) {
|
|
2979
3183
|
mkdirSync4(assistDir, { recursive: true });
|
|
2980
3184
|
}
|
|
2981
3185
|
const cacheData = {
|
|
@@ -2983,8 +3187,8 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
2983
3187
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2984
3188
|
comments
|
|
2985
3189
|
};
|
|
2986
|
-
const cachePath =
|
|
2987
|
-
|
|
3190
|
+
const cachePath = join13(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
3191
|
+
writeFileSync14(cachePath, stringify(cacheData));
|
|
2988
3192
|
}
|
|
2989
3193
|
function handleKnownErrors(error) {
|
|
2990
3194
|
if (isGhNotInstalled(error)) {
|
|
@@ -3027,16 +3231,16 @@ async function listComments() {
|
|
|
3027
3231
|
import { execSync as execSync20 } from "child_process";
|
|
3028
3232
|
|
|
3029
3233
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
3030
|
-
import
|
|
3234
|
+
import enquirer5 from "enquirer";
|
|
3031
3235
|
|
|
3032
3236
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
3033
|
-
import
|
|
3237
|
+
import chalk42 from "chalk";
|
|
3034
3238
|
var STATUS_MAP = {
|
|
3035
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
3036
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
3239
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk42.magenta("merged"), date: pr.mergedAt } : null,
|
|
3240
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk42.red("closed"), date: pr.closedAt } : null
|
|
3037
3241
|
};
|
|
3038
3242
|
function defaultStatus(pr) {
|
|
3039
|
-
return { label:
|
|
3243
|
+
return { label: chalk42.green("opened"), date: pr.createdAt };
|
|
3040
3244
|
}
|
|
3041
3245
|
function getStatus(pr) {
|
|
3042
3246
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -3045,11 +3249,11 @@ function formatDate(dateStr) {
|
|
|
3045
3249
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
3046
3250
|
}
|
|
3047
3251
|
function formatPrHeader(pr, status) {
|
|
3048
|
-
return `${
|
|
3252
|
+
return `${chalk42.cyan(`#${pr.number}`)} ${pr.title} ${chalk42.dim(`(${pr.author.login},`)} ${status.label} ${chalk42.dim(`${formatDate(status.date)})`)}`;
|
|
3049
3253
|
}
|
|
3050
3254
|
function logPrDetails(pr) {
|
|
3051
3255
|
console.log(
|
|
3052
|
-
|
|
3256
|
+
chalk42.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
3053
3257
|
);
|
|
3054
3258
|
console.log();
|
|
3055
3259
|
}
|
|
@@ -3061,8 +3265,8 @@ function printPr(pr) {
|
|
|
3061
3265
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
3062
3266
|
var PAGE_SIZE = 10;
|
|
3063
3267
|
function getPageSlice(pullRequests, page) {
|
|
3064
|
-
const
|
|
3065
|
-
return pullRequests.slice(
|
|
3268
|
+
const start2 = page * PAGE_SIZE;
|
|
3269
|
+
return pullRequests.slice(start2, start2 + PAGE_SIZE);
|
|
3066
3270
|
}
|
|
3067
3271
|
function pageHeader(page, totalPages, total) {
|
|
3068
3272
|
return `
|
|
@@ -3097,7 +3301,7 @@ function parseAction(action) {
|
|
|
3097
3301
|
}
|
|
3098
3302
|
async function promptNavigation(currentPage, totalPages) {
|
|
3099
3303
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
3100
|
-
const { action } = await
|
|
3304
|
+
const { action } = await enquirer5.prompt({
|
|
3101
3305
|
type: "select",
|
|
3102
3306
|
name: "action",
|
|
3103
3307
|
message: "Navigate",
|
|
@@ -3216,7 +3420,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
3216
3420
|
import * as path17 from "path";
|
|
3217
3421
|
|
|
3218
3422
|
// src/commands/refactor/logViolations.ts
|
|
3219
|
-
import
|
|
3423
|
+
import chalk43 from "chalk";
|
|
3220
3424
|
var DEFAULT_MAX_LINES = 100;
|
|
3221
3425
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
3222
3426
|
if (violations.length === 0) {
|
|
@@ -3225,43 +3429,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
3225
3429
|
}
|
|
3226
3430
|
return;
|
|
3227
3431
|
}
|
|
3228
|
-
console.error(
|
|
3432
|
+
console.error(chalk43.red(`
|
|
3229
3433
|
Refactor check failed:
|
|
3230
3434
|
`));
|
|
3231
|
-
console.error(
|
|
3435
|
+
console.error(chalk43.red(` The following files exceed ${maxLines} lines:
|
|
3232
3436
|
`));
|
|
3233
3437
|
for (const violation of violations) {
|
|
3234
|
-
console.error(
|
|
3438
|
+
console.error(chalk43.red(` ${violation.file} (${violation.lines} lines)`));
|
|
3235
3439
|
}
|
|
3236
3440
|
console.error(
|
|
3237
|
-
|
|
3441
|
+
chalk43.yellow(
|
|
3238
3442
|
`
|
|
3239
3443
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
3240
3444
|
way to refactor it, ignore it with:
|
|
3241
3445
|
`
|
|
3242
3446
|
)
|
|
3243
3447
|
);
|
|
3244
|
-
console.error(
|
|
3448
|
+
console.error(chalk43.gray(` assist refactor ignore <file>
|
|
3245
3449
|
`));
|
|
3246
3450
|
if (process.env.CLAUDECODE) {
|
|
3247
|
-
console.error(
|
|
3451
|
+
console.error(chalk43.cyan(`
|
|
3248
3452
|
## Extracting Code to New Files
|
|
3249
3453
|
`));
|
|
3250
3454
|
console.error(
|
|
3251
|
-
|
|
3455
|
+
chalk43.cyan(
|
|
3252
3456
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
3253
3457
|
`
|
|
3254
3458
|
)
|
|
3255
3459
|
);
|
|
3256
3460
|
console.error(
|
|
3257
|
-
|
|
3461
|
+
chalk43.cyan(
|
|
3258
3462
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
3259
3463
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
3260
3464
|
`
|
|
3261
3465
|
)
|
|
3262
3466
|
);
|
|
3263
3467
|
console.error(
|
|
3264
|
-
|
|
3468
|
+
chalk43.cyan(
|
|
3265
3469
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
3266
3470
|
domains, move it to a common/shared folder.
|
|
3267
3471
|
`
|
|
@@ -3417,11 +3621,11 @@ async function check(pattern2, options2) {
|
|
|
3417
3621
|
|
|
3418
3622
|
// src/commands/refactor/ignore.ts
|
|
3419
3623
|
import fs16 from "fs";
|
|
3420
|
-
import
|
|
3624
|
+
import chalk44 from "chalk";
|
|
3421
3625
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
3422
3626
|
function ignore(file) {
|
|
3423
3627
|
if (!fs16.existsSync(file)) {
|
|
3424
|
-
console.error(
|
|
3628
|
+
console.error(chalk44.red(`Error: File does not exist: ${file}`));
|
|
3425
3629
|
process.exit(1);
|
|
3426
3630
|
}
|
|
3427
3631
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -3437,7 +3641,7 @@ function ignore(file) {
|
|
|
3437
3641
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
3438
3642
|
}
|
|
3439
3643
|
console.log(
|
|
3440
|
-
|
|
3644
|
+
chalk44.green(
|
|
3441
3645
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
3442
3646
|
)
|
|
3443
3647
|
);
|
|
@@ -3445,7 +3649,7 @@ function ignore(file) {
|
|
|
3445
3649
|
|
|
3446
3650
|
// src/commands/refactor/restructure/index.ts
|
|
3447
3651
|
import path26 from "path";
|
|
3448
|
-
import
|
|
3652
|
+
import chalk47 from "chalk";
|
|
3449
3653
|
|
|
3450
3654
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
3451
3655
|
import path18 from "path";
|
|
@@ -3594,9 +3798,9 @@ import path21 from "path";
|
|
|
3594
3798
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
3595
3799
|
import fs17 from "fs";
|
|
3596
3800
|
function getOrCreateList(map, key) {
|
|
3597
|
-
const
|
|
3598
|
-
if (!map.has(key)) map.set(key,
|
|
3599
|
-
return
|
|
3801
|
+
const list3 = map.get(key) ?? [];
|
|
3802
|
+
if (!map.has(key)) map.set(key, list3);
|
|
3803
|
+
return list3;
|
|
3600
3804
|
}
|
|
3601
3805
|
function groupByFile(rewrites) {
|
|
3602
3806
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -3688,50 +3892,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
3688
3892
|
|
|
3689
3893
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
3690
3894
|
import path22 from "path";
|
|
3691
|
-
import
|
|
3895
|
+
import chalk45 from "chalk";
|
|
3692
3896
|
function relPath(filePath) {
|
|
3693
3897
|
return path22.relative(process.cwd(), filePath);
|
|
3694
3898
|
}
|
|
3695
3899
|
function displayMoves(plan) {
|
|
3696
3900
|
if (plan.moves.length === 0) return;
|
|
3697
|
-
console.log(
|
|
3901
|
+
console.log(chalk45.bold("\nFile moves:"));
|
|
3698
3902
|
for (const move of plan.moves) {
|
|
3699
3903
|
console.log(
|
|
3700
|
-
` ${
|
|
3904
|
+
` ${chalk45.red(relPath(move.from))} \u2192 ${chalk45.green(relPath(move.to))}`
|
|
3701
3905
|
);
|
|
3702
|
-
console.log(
|
|
3906
|
+
console.log(chalk45.dim(` ${move.reason}`));
|
|
3703
3907
|
}
|
|
3704
3908
|
}
|
|
3705
3909
|
function displayRewrites(rewrites) {
|
|
3706
3910
|
if (rewrites.length === 0) return;
|
|
3707
3911
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
3708
|
-
console.log(
|
|
3912
|
+
console.log(chalk45.bold(`
|
|
3709
3913
|
Import rewrites (${affectedFiles.size} files):`));
|
|
3710
3914
|
for (const file of affectedFiles) {
|
|
3711
|
-
console.log(` ${
|
|
3915
|
+
console.log(` ${chalk45.cyan(relPath(file))}:`);
|
|
3712
3916
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
3713
3917
|
(r) => r.file === file
|
|
3714
3918
|
)) {
|
|
3715
3919
|
console.log(
|
|
3716
|
-
` ${
|
|
3920
|
+
` ${chalk45.red(`"${oldSpecifier}"`)} \u2192 ${chalk45.green(`"${newSpecifier}"`)}`
|
|
3717
3921
|
);
|
|
3718
3922
|
}
|
|
3719
3923
|
}
|
|
3720
3924
|
}
|
|
3721
3925
|
function displayPlan(plan) {
|
|
3722
3926
|
if (plan.warnings.length > 0) {
|
|
3723
|
-
console.log(
|
|
3724
|
-
for (const w of plan.warnings) console.log(
|
|
3927
|
+
console.log(chalk45.yellow("\nWarnings:"));
|
|
3928
|
+
for (const w of plan.warnings) console.log(chalk45.yellow(` ${w}`));
|
|
3725
3929
|
}
|
|
3726
3930
|
if (plan.newDirectories.length > 0) {
|
|
3727
|
-
console.log(
|
|
3931
|
+
console.log(chalk45.bold("\nNew directories:"));
|
|
3728
3932
|
for (const dir of plan.newDirectories)
|
|
3729
|
-
console.log(
|
|
3933
|
+
console.log(chalk45.green(` ${dir}/`));
|
|
3730
3934
|
}
|
|
3731
3935
|
displayMoves(plan);
|
|
3732
3936
|
displayRewrites(plan.rewrites);
|
|
3733
3937
|
console.log(
|
|
3734
|
-
|
|
3938
|
+
chalk45.dim(
|
|
3735
3939
|
`
|
|
3736
3940
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
3737
3941
|
)
|
|
@@ -3741,18 +3945,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
3741
3945
|
// src/commands/refactor/restructure/executePlan.ts
|
|
3742
3946
|
import fs18 from "fs";
|
|
3743
3947
|
import path23 from "path";
|
|
3744
|
-
import
|
|
3948
|
+
import chalk46 from "chalk";
|
|
3745
3949
|
function executePlan(plan) {
|
|
3746
3950
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
3747
3951
|
for (const [file, content] of updatedContents) {
|
|
3748
3952
|
fs18.writeFileSync(file, content, "utf-8");
|
|
3749
3953
|
console.log(
|
|
3750
|
-
|
|
3954
|
+
chalk46.cyan(` Rewrote imports in ${path23.relative(process.cwd(), file)}`)
|
|
3751
3955
|
);
|
|
3752
3956
|
}
|
|
3753
3957
|
for (const dir of plan.newDirectories) {
|
|
3754
3958
|
fs18.mkdirSync(dir, { recursive: true });
|
|
3755
|
-
console.log(
|
|
3959
|
+
console.log(chalk46.green(` Created ${path23.relative(process.cwd(), dir)}/`));
|
|
3756
3960
|
}
|
|
3757
3961
|
for (const move of plan.moves) {
|
|
3758
3962
|
const targetDir = path23.dirname(move.to);
|
|
@@ -3761,7 +3965,7 @@ function executePlan(plan) {
|
|
|
3761
3965
|
}
|
|
3762
3966
|
fs18.renameSync(move.from, move.to);
|
|
3763
3967
|
console.log(
|
|
3764
|
-
|
|
3968
|
+
chalk46.white(
|
|
3765
3969
|
` Moved ${path23.relative(process.cwd(), move.from)} \u2192 ${path23.relative(process.cwd(), move.to)}`
|
|
3766
3970
|
)
|
|
3767
3971
|
);
|
|
@@ -3776,7 +3980,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
3776
3980
|
if (entries.length === 0) {
|
|
3777
3981
|
fs18.rmdirSync(dir);
|
|
3778
3982
|
console.log(
|
|
3779
|
-
|
|
3983
|
+
chalk46.dim(
|
|
3780
3984
|
` Removed empty directory ${path23.relative(process.cwd(), dir)}`
|
|
3781
3985
|
)
|
|
3782
3986
|
);
|
|
@@ -3907,22 +4111,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
3907
4111
|
const targetPattern = pattern2 ?? "src";
|
|
3908
4112
|
const files = findSourceFiles2(targetPattern);
|
|
3909
4113
|
if (files.length === 0) {
|
|
3910
|
-
console.log(
|
|
4114
|
+
console.log(chalk47.yellow("No files found matching pattern"));
|
|
3911
4115
|
return;
|
|
3912
4116
|
}
|
|
3913
4117
|
const tsConfigPath = path26.resolve("tsconfig.json");
|
|
3914
4118
|
const plan = buildPlan(files, tsConfigPath);
|
|
3915
4119
|
if (plan.moves.length === 0) {
|
|
3916
|
-
console.log(
|
|
4120
|
+
console.log(chalk47.green("No restructuring needed"));
|
|
3917
4121
|
return;
|
|
3918
4122
|
}
|
|
3919
4123
|
displayPlan(plan);
|
|
3920
4124
|
if (options2.apply) {
|
|
3921
|
-
console.log(
|
|
4125
|
+
console.log(chalk47.bold("\nApplying changes..."));
|
|
3922
4126
|
executePlan(plan);
|
|
3923
|
-
console.log(
|
|
4127
|
+
console.log(chalk47.green("\nRestructuring complete"));
|
|
3924
4128
|
} else {
|
|
3925
|
-
console.log(
|
|
4129
|
+
console.log(chalk47.dim("\nDry run. Use --apply to execute."));
|
|
3926
4130
|
}
|
|
3927
4131
|
}
|
|
3928
4132
|
|
|
@@ -3945,8 +4149,8 @@ function registerRefactor(program2) {
|
|
|
3945
4149
|
}
|
|
3946
4150
|
|
|
3947
4151
|
// src/commands/transcript/shared.ts
|
|
3948
|
-
import { existsSync as
|
|
3949
|
-
import { basename as basename4, join as
|
|
4152
|
+
import { existsSync as existsSync18, readdirSync as readdirSync2, statSync } from "fs";
|
|
4153
|
+
import { basename as basename4, join as join14, relative } from "path";
|
|
3950
4154
|
import * as readline2 from "readline";
|
|
3951
4155
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
3952
4156
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -3961,10 +4165,10 @@ function isValidDatePrefix(filename) {
|
|
|
3961
4165
|
return DATE_PREFIX_REGEX.test(filename);
|
|
3962
4166
|
}
|
|
3963
4167
|
function collectFiles(dir, extension) {
|
|
3964
|
-
if (!
|
|
4168
|
+
if (!existsSync18(dir)) return [];
|
|
3965
4169
|
const results = [];
|
|
3966
4170
|
for (const entry of readdirSync2(dir)) {
|
|
3967
|
-
const fullPath =
|
|
4171
|
+
const fullPath = join14(dir, entry);
|
|
3968
4172
|
if (statSync(fullPath).isDirectory()) {
|
|
3969
4173
|
results.push(...collectFiles(fullPath, extension));
|
|
3970
4174
|
} else if (entry.endsWith(extension)) {
|
|
@@ -4058,14 +4262,14 @@ async function configure() {
|
|
|
4058
4262
|
}
|
|
4059
4263
|
|
|
4060
4264
|
// src/commands/transcript/format/index.ts
|
|
4061
|
-
import { existsSync as
|
|
4265
|
+
import { existsSync as existsSync20 } from "fs";
|
|
4062
4266
|
|
|
4063
4267
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
4064
|
-
import { dirname as dirname12, join as
|
|
4268
|
+
import { dirname as dirname12, join as join16 } from "path";
|
|
4065
4269
|
|
|
4066
4270
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
4067
4271
|
import { renameSync } from "fs";
|
|
4068
|
-
import { join as
|
|
4272
|
+
import { join as join15 } from "path";
|
|
4069
4273
|
async function resolveDate(rl, choice) {
|
|
4070
4274
|
if (choice === "1") return getDatePrefix(0);
|
|
4071
4275
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -4080,7 +4284,7 @@ async function resolveDate(rl, choice) {
|
|
|
4080
4284
|
}
|
|
4081
4285
|
function renameWithPrefix(vttDir, vttFile, prefix) {
|
|
4082
4286
|
const newFilename = `${prefix}.${vttFile}`;
|
|
4083
|
-
renameSync(
|
|
4287
|
+
renameSync(join15(vttDir, vttFile), join15(vttDir, newFilename));
|
|
4084
4288
|
console.log(`Renamed to: ${newFilename}`);
|
|
4085
4289
|
return newFilename;
|
|
4086
4290
|
}
|
|
@@ -4114,12 +4318,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4114
4318
|
const vttFileDir = dirname12(vttFile.absolutePath);
|
|
4115
4319
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
4116
4320
|
if (newFilename) {
|
|
4117
|
-
const newRelativePath =
|
|
4321
|
+
const newRelativePath = join16(
|
|
4118
4322
|
dirname12(vttFile.relativePath),
|
|
4119
4323
|
newFilename
|
|
4120
4324
|
);
|
|
4121
4325
|
vttFiles[i] = {
|
|
4122
|
-
absolutePath:
|
|
4326
|
+
absolutePath: join16(vttFileDir, newFilename),
|
|
4123
4327
|
relativePath: newRelativePath,
|
|
4124
4328
|
filename: newFilename
|
|
4125
4329
|
};
|
|
@@ -4132,8 +4336,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
4132
4336
|
}
|
|
4133
4337
|
|
|
4134
4338
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
4135
|
-
import { existsSync as
|
|
4136
|
-
import { basename as basename5, dirname as dirname13, join as
|
|
4339
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync15 } from "fs";
|
|
4340
|
+
import { basename as basename5, dirname as dirname13, join as join17 } from "path";
|
|
4137
4341
|
|
|
4138
4342
|
// src/commands/transcript/cleanText.ts
|
|
4139
4343
|
function cleanText(text) {
|
|
@@ -4273,10 +4477,10 @@ function extractSpeaker(fullText) {
|
|
|
4273
4477
|
function isTextLine(line) {
|
|
4274
4478
|
return !!line.trim() && !line.includes("-->");
|
|
4275
4479
|
}
|
|
4276
|
-
function scanTextLines(lines,
|
|
4277
|
-
let i =
|
|
4480
|
+
function scanTextLines(lines, start2) {
|
|
4481
|
+
let i = start2;
|
|
4278
4482
|
while (i < lines.length && isTextLine(lines[i])) i++;
|
|
4279
|
-
return { texts: lines.slice(
|
|
4483
|
+
return { texts: lines.slice(start2, i).map((l) => l.trim()), end: i };
|
|
4280
4484
|
}
|
|
4281
4485
|
function collectTextLines(lines, startIndex) {
|
|
4282
4486
|
const { texts, end } = scanTextLines(lines, startIndex);
|
|
@@ -4343,21 +4547,21 @@ function toMdFilename(vttFilename) {
|
|
|
4343
4547
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
4344
4548
|
}
|
|
4345
4549
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
4346
|
-
return relativeDir === "." ? transcriptsDir :
|
|
4550
|
+
return relativeDir === "." ? transcriptsDir : join17(transcriptsDir, relativeDir);
|
|
4347
4551
|
}
|
|
4348
4552
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
4349
4553
|
const mdFile = toMdFilename(vttFile.filename);
|
|
4350
4554
|
const relativeDir = dirname13(vttFile.relativePath);
|
|
4351
4555
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
4352
|
-
const outputPath =
|
|
4556
|
+
const outputPath = join17(outputDir, mdFile);
|
|
4353
4557
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
4354
4558
|
}
|
|
4355
4559
|
function logSkipped(relativeDir, mdFile) {
|
|
4356
|
-
console.log(`Skipping (already exists): ${
|
|
4560
|
+
console.log(`Skipping (already exists): ${join17(relativeDir, mdFile)}`);
|
|
4357
4561
|
return "skipped";
|
|
4358
4562
|
}
|
|
4359
4563
|
function ensureDirectory(dir, label) {
|
|
4360
|
-
if (!
|
|
4564
|
+
if (!existsSync19(dir)) {
|
|
4361
4565
|
mkdirSync5(dir, { recursive: true });
|
|
4362
4566
|
console.log(`Created ${label}: ${dir}`);
|
|
4363
4567
|
}
|
|
@@ -4380,10 +4584,10 @@ function logReduction(cueCount, messageCount) {
|
|
|
4380
4584
|
}
|
|
4381
4585
|
function readAndParseCues(inputPath) {
|
|
4382
4586
|
console.log(`Reading: ${inputPath}`);
|
|
4383
|
-
return processCues(
|
|
4587
|
+
return processCues(readFileSync13(inputPath, "utf-8"));
|
|
4384
4588
|
}
|
|
4385
4589
|
function writeFormatted(outputPath, content) {
|
|
4386
|
-
|
|
4590
|
+
writeFileSync15(outputPath, content, "utf-8");
|
|
4387
4591
|
console.log(`Written: ${outputPath}`);
|
|
4388
4592
|
}
|
|
4389
4593
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -4393,7 +4597,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
4393
4597
|
logReduction(cues.length, chatMessages.length);
|
|
4394
4598
|
}
|
|
4395
4599
|
function tryProcessVtt(vttFile, paths) {
|
|
4396
|
-
if (
|
|
4600
|
+
if (existsSync19(paths.outputPath))
|
|
4397
4601
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
4398
4602
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
4399
4603
|
return "processed";
|
|
@@ -4419,7 +4623,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
4419
4623
|
logSummary(counts);
|
|
4420
4624
|
}
|
|
4421
4625
|
function requireVttDir(vttDir) {
|
|
4422
|
-
if (!
|
|
4626
|
+
if (!existsSync20(vttDir)) {
|
|
4423
4627
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
4424
4628
|
process.exit(1);
|
|
4425
4629
|
}
|
|
@@ -4451,28 +4655,28 @@ async function format() {
|
|
|
4451
4655
|
}
|
|
4452
4656
|
|
|
4453
4657
|
// src/commands/transcript/summarise/index.ts
|
|
4454
|
-
import { existsSync as
|
|
4455
|
-
import { basename as basename6, dirname as dirname15, join as
|
|
4658
|
+
import { existsSync as existsSync22 } from "fs";
|
|
4659
|
+
import { basename as basename6, dirname as dirname15, join as join19, relative as relative2 } from "path";
|
|
4456
4660
|
|
|
4457
4661
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4458
4662
|
import {
|
|
4459
|
-
existsSync as
|
|
4663
|
+
existsSync as existsSync21,
|
|
4460
4664
|
mkdirSync as mkdirSync6,
|
|
4461
|
-
readFileSync as
|
|
4665
|
+
readFileSync as readFileSync14,
|
|
4462
4666
|
renameSync as renameSync2,
|
|
4463
4667
|
rmSync
|
|
4464
4668
|
} from "fs";
|
|
4465
|
-
import { dirname as dirname14, join as
|
|
4669
|
+
import { dirname as dirname14, join as join18 } from "path";
|
|
4466
4670
|
|
|
4467
4671
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
4468
|
-
import
|
|
4672
|
+
import chalk48 from "chalk";
|
|
4469
4673
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
4470
4674
|
function validateStagedContent(filename, content) {
|
|
4471
4675
|
const firstLine = content.split("\n")[0];
|
|
4472
4676
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
4473
4677
|
if (!match) {
|
|
4474
4678
|
console.error(
|
|
4475
|
-
|
|
4679
|
+
chalk48.red(
|
|
4476
4680
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
4477
4681
|
)
|
|
4478
4682
|
);
|
|
@@ -4481,7 +4685,7 @@ function validateStagedContent(filename, content) {
|
|
|
4481
4685
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
4482
4686
|
if (!contentAfterLink) {
|
|
4483
4687
|
console.error(
|
|
4484
|
-
|
|
4688
|
+
chalk48.red(
|
|
4485
4689
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
4486
4690
|
)
|
|
4487
4691
|
);
|
|
@@ -4491,9 +4695,9 @@ function validateStagedContent(filename, content) {
|
|
|
4491
4695
|
}
|
|
4492
4696
|
|
|
4493
4697
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
4494
|
-
var STAGING_DIR =
|
|
4698
|
+
var STAGING_DIR = join18(process.cwd(), ".assist", "transcript");
|
|
4495
4699
|
function processStagedFile() {
|
|
4496
|
-
if (!
|
|
4700
|
+
if (!existsSync21(STAGING_DIR)) {
|
|
4497
4701
|
return false;
|
|
4498
4702
|
}
|
|
4499
4703
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -4502,7 +4706,7 @@ function processStagedFile() {
|
|
|
4502
4706
|
}
|
|
4503
4707
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
4504
4708
|
const stagedFile = stagedFiles[0];
|
|
4505
|
-
const content =
|
|
4709
|
+
const content = readFileSync14(stagedFile.absolutePath, "utf-8");
|
|
4506
4710
|
validateStagedContent(stagedFile.filename, content);
|
|
4507
4711
|
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
4508
4712
|
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
@@ -4515,9 +4719,9 @@ function processStagedFile() {
|
|
|
4515
4719
|
);
|
|
4516
4720
|
process.exit(1);
|
|
4517
4721
|
}
|
|
4518
|
-
const destPath =
|
|
4722
|
+
const destPath = join18(summaryDir, matchingTranscript.relativePath);
|
|
4519
4723
|
const destDir = dirname14(destPath);
|
|
4520
|
-
if (!
|
|
4724
|
+
if (!existsSync21(destDir)) {
|
|
4521
4725
|
mkdirSync6(destDir, { recursive: true });
|
|
4522
4726
|
}
|
|
4523
4727
|
renameSync2(stagedFile.absolutePath, destPath);
|
|
@@ -4531,7 +4735,7 @@ function processStagedFile() {
|
|
|
4531
4735
|
// src/commands/transcript/summarise/index.ts
|
|
4532
4736
|
function buildRelativeKey(relativePath, baseName) {
|
|
4533
4737
|
const relDir = dirname15(relativePath);
|
|
4534
|
-
return relDir === "." ? baseName :
|
|
4738
|
+
return relDir === "." ? baseName : join19(relDir, baseName);
|
|
4535
4739
|
}
|
|
4536
4740
|
function buildSummaryIndex(summaryDir) {
|
|
4537
4741
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -4544,7 +4748,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
4544
4748
|
function summarise() {
|
|
4545
4749
|
processStagedFile();
|
|
4546
4750
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
4547
|
-
if (!
|
|
4751
|
+
if (!existsSync22(transcriptsDir)) {
|
|
4548
4752
|
console.log("No transcripts directory found.");
|
|
4549
4753
|
return;
|
|
4550
4754
|
}
|
|
@@ -4565,8 +4769,8 @@ function summarise() {
|
|
|
4565
4769
|
}
|
|
4566
4770
|
const next2 = missing[0];
|
|
4567
4771
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
4568
|
-
const outputPath =
|
|
4569
|
-
const summaryFileDir =
|
|
4772
|
+
const outputPath = join19(STAGING_DIR, outputFilename);
|
|
4773
|
+
const summaryFileDir = join19(summaryDir, dirname15(next2.relativePath));
|
|
4570
4774
|
const relativeTranscriptPath = encodeURI(
|
|
4571
4775
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
4572
4776
|
);
|
|
@@ -4653,7 +4857,7 @@ function saveNewRunConfig(name, command, args) {
|
|
|
4653
4857
|
runList.push(buildRunEntry(name, command, args));
|
|
4654
4858
|
saveConfig(config);
|
|
4655
4859
|
}
|
|
4656
|
-
function
|
|
4860
|
+
function add2() {
|
|
4657
4861
|
const { name, command, args } = requireParsedArgs();
|
|
4658
4862
|
saveNewRunConfig(name, command, args);
|
|
4659
4863
|
console.log(
|
|
@@ -4734,7 +4938,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
4734
4938
|
// src/commands/sync/syncClaudeMd.ts
|
|
4735
4939
|
import * as fs21 from "fs";
|
|
4736
4940
|
import * as path27 from "path";
|
|
4737
|
-
import
|
|
4941
|
+
import chalk49 from "chalk";
|
|
4738
4942
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
4739
4943
|
const source = path27.join(claudeDir, "CLAUDE.md");
|
|
4740
4944
|
const target = path27.join(targetBase, "CLAUDE.md");
|
|
@@ -4743,12 +4947,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
4743
4947
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
4744
4948
|
if (sourceContent !== targetContent) {
|
|
4745
4949
|
console.log(
|
|
4746
|
-
|
|
4950
|
+
chalk49.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
4747
4951
|
);
|
|
4748
4952
|
console.log();
|
|
4749
4953
|
printDiff(targetContent, sourceContent);
|
|
4750
4954
|
const confirm = await promptConfirm(
|
|
4751
|
-
|
|
4955
|
+
chalk49.red("Overwrite existing CLAUDE.md?"),
|
|
4752
4956
|
false
|
|
4753
4957
|
);
|
|
4754
4958
|
if (!confirm) {
|
|
@@ -4764,7 +4968,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
4764
4968
|
// src/commands/sync/syncSettings.ts
|
|
4765
4969
|
import * as fs22 from "fs";
|
|
4766
4970
|
import * as path28 from "path";
|
|
4767
|
-
import
|
|
4971
|
+
import chalk50 from "chalk";
|
|
4768
4972
|
async function syncSettings(claudeDir, targetBase) {
|
|
4769
4973
|
const source = path28.join(claudeDir, "settings.json");
|
|
4770
4974
|
const target = path28.join(targetBase, "settings.json");
|
|
@@ -4775,12 +4979,12 @@ async function syncSettings(claudeDir, targetBase) {
|
|
|
4775
4979
|
const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
|
|
4776
4980
|
if (normalizedSource !== normalizedTarget) {
|
|
4777
4981
|
console.log(
|
|
4778
|
-
|
|
4982
|
+
chalk50.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
|
|
4779
4983
|
);
|
|
4780
4984
|
console.log();
|
|
4781
4985
|
printDiff(targetContent, sourceContent);
|
|
4782
4986
|
const confirm = await promptConfirm(
|
|
4783
|
-
|
|
4987
|
+
chalk50.red("Overwrite existing settings.json?"),
|
|
4784
4988
|
false
|
|
4785
4989
|
);
|
|
4786
4990
|
if (!confirm) {
|
|
@@ -4832,7 +5036,7 @@ configCommand.command("list").description("List all config values").action(confi
|
|
|
4832
5036
|
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
5037
|
run2(name, args);
|
|
4834
5038
|
});
|
|
4835
|
-
runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() =>
|
|
5039
|
+
runCommand.command("add").description("Add a new run configuration to assist.yml").allowUnknownOption().allowExcessArguments().action(() => add2());
|
|
4836
5040
|
registerNew(program);
|
|
4837
5041
|
var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
|
|
4838
5042
|
lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
|
|
@@ -4843,6 +5047,7 @@ program.command("notify").description(
|
|
|
4843
5047
|
"Show notification from Claude Code hook (reads JSON from stdin)"
|
|
4844
5048
|
).action(notify);
|
|
4845
5049
|
registerPrs(program);
|
|
5050
|
+
registerBacklog(program);
|
|
4846
5051
|
registerVerify(program);
|
|
4847
5052
|
registerRefactor(program);
|
|
4848
5053
|
registerDevlog(program);
|