@staff0rd/assist 0.97.1 → 0.99.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/claude/settings.json +1 -0
- package/dist/index.js +412 -218
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.99.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -87,10 +87,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
87
87
|
// src/shared/loadRawYaml.ts
|
|
88
88
|
import { existsSync, readFileSync } from "fs";
|
|
89
89
|
import { parse as parseYaml } from "yaml";
|
|
90
|
-
function loadRawYaml(
|
|
91
|
-
if (!existsSync(
|
|
90
|
+
function loadRawYaml(path35) {
|
|
91
|
+
if (!existsSync(path35)) return {};
|
|
92
92
|
try {
|
|
93
|
-
const content = readFileSync(
|
|
93
|
+
const content = readFileSync(path35, "utf-8");
|
|
94
94
|
return parseYaml(content) || {};
|
|
95
95
|
} catch {
|
|
96
96
|
return {};
|
|
@@ -317,9 +317,9 @@ function isTraversable(value) {
|
|
|
317
317
|
function stepInto(current, key) {
|
|
318
318
|
return isTraversable(current) ? current[key] : void 0;
|
|
319
319
|
}
|
|
320
|
-
function getNestedValue(obj,
|
|
320
|
+
function getNestedValue(obj, path35) {
|
|
321
321
|
let current = obj;
|
|
322
|
-
for (const key of
|
|
322
|
+
for (const key of path35.split(".")) current = stepInto(current, key);
|
|
323
323
|
return current;
|
|
324
324
|
}
|
|
325
325
|
|
|
@@ -360,8 +360,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
360
360
|
}
|
|
361
361
|
return ensureObject(container, resolved);
|
|
362
362
|
}
|
|
363
|
-
function setNestedValue(obj,
|
|
364
|
-
const keys =
|
|
363
|
+
function setNestedValue(obj, path35, value) {
|
|
364
|
+
const keys = path35.split(".");
|
|
365
365
|
const result = { ...obj };
|
|
366
366
|
let current = result;
|
|
367
367
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -736,12 +736,12 @@ function removeEslintFromPackageJson(options2) {
|
|
|
736
736
|
}
|
|
737
737
|
return modified;
|
|
738
738
|
}
|
|
739
|
-
function removeEslintDeps(
|
|
740
|
-
if (!
|
|
739
|
+
function removeEslintDeps(deps2) {
|
|
740
|
+
if (!deps2) return false;
|
|
741
741
|
let modified = false;
|
|
742
|
-
for (const key of Object.keys(
|
|
742
|
+
for (const key of Object.keys(deps2)) {
|
|
743
743
|
if (key.includes("eslint")) {
|
|
744
|
-
delete
|
|
744
|
+
delete deps2[key];
|
|
745
745
|
modified = true;
|
|
746
746
|
}
|
|
747
747
|
}
|
|
@@ -2612,12 +2612,12 @@ function getCliReadsPath() {
|
|
|
2612
2612
|
var cachedLines;
|
|
2613
2613
|
function getCliReadsLines() {
|
|
2614
2614
|
if (cachedLines) return cachedLines;
|
|
2615
|
-
const
|
|
2616
|
-
if (!existsSync16(
|
|
2615
|
+
const path35 = getCliReadsPath();
|
|
2616
|
+
if (!existsSync16(path35)) {
|
|
2617
2617
|
cachedLines = [];
|
|
2618
2618
|
return cachedLines;
|
|
2619
2619
|
}
|
|
2620
|
-
cachedLines = readFileSync13(
|
|
2620
|
+
cachedLines = readFileSync13(path35, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
2621
2621
|
return cachedLines;
|
|
2622
2622
|
}
|
|
2623
2623
|
function loadCliReads() {
|
|
@@ -2968,14 +2968,14 @@ function showProgress(p, label2) {
|
|
|
2968
2968
|
const pct = Math.round(p.done / p.total * 100);
|
|
2969
2969
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
2970
2970
|
}
|
|
2971
|
-
async function resolveCommand(cli,
|
|
2972
|
-
showProgress(p,
|
|
2973
|
-
const subHelp = await runHelp([cli, ...
|
|
2971
|
+
async function resolveCommand(cli, path35, description, depth, p) {
|
|
2972
|
+
showProgress(p, path35.join(" "));
|
|
2973
|
+
const subHelp = await runHelp([cli, ...path35]);
|
|
2974
2974
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
2975
|
-
return [{ path:
|
|
2975
|
+
return [{ path: path35, description }];
|
|
2976
2976
|
}
|
|
2977
|
-
const children = await discoverAt(cli,
|
|
2978
|
-
return children.length > 0 ? children : [{ path:
|
|
2977
|
+
const children = await discoverAt(cli, path35, depth + 1, p);
|
|
2978
|
+
return children.length > 0 ? children : [{ path: path35, description }];
|
|
2979
2979
|
}
|
|
2980
2980
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
2981
2981
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -3123,9 +3123,9 @@ function logPath(cli) {
|
|
|
3123
3123
|
return join12(homedir4(), ".assist", `cli-discover-${safeName}.log`);
|
|
3124
3124
|
}
|
|
3125
3125
|
function readCache(cli) {
|
|
3126
|
-
const
|
|
3127
|
-
if (!existsSync18(
|
|
3128
|
-
return readFileSync15(
|
|
3126
|
+
const path35 = logPath(cli);
|
|
3127
|
+
if (!existsSync18(path35)) return void 0;
|
|
3128
|
+
return readFileSync15(path35, "utf-8");
|
|
3129
3129
|
}
|
|
3130
3130
|
function writeCache(cli, output) {
|
|
3131
3131
|
const dir = join12(homedir4(), ".assist");
|
|
@@ -3705,25 +3705,216 @@ function registerDeploy(program2) {
|
|
|
3705
3705
|
deployCommand.command("redirect").description("Add trailing slash redirect script to index.html").action(redirect);
|
|
3706
3706
|
}
|
|
3707
3707
|
|
|
3708
|
+
// src/commands/deps/deps.ts
|
|
3709
|
+
import { existsSync as existsSync21 } from "fs";
|
|
3710
|
+
import path20 from "path";
|
|
3711
|
+
import chalk39 from "chalk";
|
|
3712
|
+
|
|
3713
|
+
// src/commands/deps/buildTree.ts
|
|
3714
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
3715
|
+
import path17 from "path";
|
|
3716
|
+
var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
|
|
3717
|
+
function getProjectRefs(csprojPath) {
|
|
3718
|
+
const content = readFileSync17(csprojPath, "utf-8");
|
|
3719
|
+
const refs = [];
|
|
3720
|
+
for (const match of content.matchAll(PROJECT_REF_RE)) {
|
|
3721
|
+
refs.push(match[1].replace(/\\/g, "/"));
|
|
3722
|
+
}
|
|
3723
|
+
return refs;
|
|
3724
|
+
}
|
|
3725
|
+
function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
|
|
3726
|
+
const abs = path17.resolve(csprojPath);
|
|
3727
|
+
const rel = path17.relative(repoRoot, abs);
|
|
3728
|
+
const node = { path: abs, relativePath: rel, children: [] };
|
|
3729
|
+
if (visited.has(abs)) return node;
|
|
3730
|
+
visited.add(abs);
|
|
3731
|
+
const dir = path17.dirname(abs);
|
|
3732
|
+
for (const ref of getProjectRefs(abs)) {
|
|
3733
|
+
const childAbs = path17.resolve(dir, ref);
|
|
3734
|
+
try {
|
|
3735
|
+
readFileSync17(childAbs);
|
|
3736
|
+
node.children.push(buildTree(childAbs, repoRoot, visited));
|
|
3737
|
+
} catch {
|
|
3738
|
+
node.children.push({
|
|
3739
|
+
path: childAbs,
|
|
3740
|
+
relativePath: `[MISSING] ${ref}`,
|
|
3741
|
+
children: []
|
|
3742
|
+
});
|
|
3743
|
+
}
|
|
3744
|
+
}
|
|
3745
|
+
return node;
|
|
3746
|
+
}
|
|
3747
|
+
function collectAllDeps(node) {
|
|
3748
|
+
const result = /* @__PURE__ */ new Set();
|
|
3749
|
+
function walk2(n) {
|
|
3750
|
+
for (const child of n.children) {
|
|
3751
|
+
result.add(child.path);
|
|
3752
|
+
walk2(child);
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
walk2(node);
|
|
3756
|
+
return result;
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
// src/commands/deps/findContainingSolutions.ts
|
|
3760
|
+
import { readdirSync, readFileSync as readFileSync18, statSync } from "fs";
|
|
3761
|
+
import path18 from "path";
|
|
3762
|
+
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
3763
|
+
if (depth > maxDepth) return [];
|
|
3764
|
+
const results = [];
|
|
3765
|
+
let entries;
|
|
3766
|
+
try {
|
|
3767
|
+
entries = readdirSync(dir);
|
|
3768
|
+
} catch {
|
|
3769
|
+
return results;
|
|
3770
|
+
}
|
|
3771
|
+
for (const entry of entries) {
|
|
3772
|
+
if (entry.startsWith(".") || entry === "node_modules" || entry === "packages")
|
|
3773
|
+
continue;
|
|
3774
|
+
const full = path18.join(dir, entry);
|
|
3775
|
+
try {
|
|
3776
|
+
const stat = statSync(full);
|
|
3777
|
+
if (stat.isFile() && entry.endsWith(".sln")) {
|
|
3778
|
+
results.push(full);
|
|
3779
|
+
} else if (stat.isDirectory()) {
|
|
3780
|
+
results.push(...findSlnFiles(full, maxDepth, depth + 1));
|
|
3781
|
+
}
|
|
3782
|
+
} catch {
|
|
3783
|
+
}
|
|
3784
|
+
}
|
|
3785
|
+
return results;
|
|
3786
|
+
}
|
|
3787
|
+
function findContainingSolutions(csprojPath, repoRoot) {
|
|
3788
|
+
const csprojAbs = path18.resolve(csprojPath);
|
|
3789
|
+
const csprojBasename = path18.basename(csprojAbs);
|
|
3790
|
+
const slnFiles = findSlnFiles(repoRoot, 3);
|
|
3791
|
+
const matches = [];
|
|
3792
|
+
const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
|
|
3793
|
+
for (const sln of slnFiles) {
|
|
3794
|
+
try {
|
|
3795
|
+
const content = readFileSync18(sln, "utf-8");
|
|
3796
|
+
if (pattern2.test(content)) {
|
|
3797
|
+
matches.push(path18.relative(repoRoot, sln));
|
|
3798
|
+
}
|
|
3799
|
+
} catch {
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
return matches;
|
|
3803
|
+
}
|
|
3804
|
+
function escapeRegex(s) {
|
|
3805
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3806
|
+
}
|
|
3807
|
+
|
|
3808
|
+
// src/commands/deps/findRepoRoot.ts
|
|
3809
|
+
import { existsSync as existsSync20 } from "fs";
|
|
3810
|
+
import path19 from "path";
|
|
3811
|
+
function findRepoRoot(dir) {
|
|
3812
|
+
let current = dir;
|
|
3813
|
+
while (current !== path19.dirname(current)) {
|
|
3814
|
+
if (existsSync20(path19.join(current, ".git"))) {
|
|
3815
|
+
return current;
|
|
3816
|
+
}
|
|
3817
|
+
current = path19.dirname(current);
|
|
3818
|
+
}
|
|
3819
|
+
return null;
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
// src/commands/deps/printTree.ts
|
|
3823
|
+
import chalk38 from "chalk";
|
|
3824
|
+
function printNodes(nodes, prefix2) {
|
|
3825
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
3826
|
+
const isLast = i === nodes.length - 1;
|
|
3827
|
+
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
3828
|
+
const childPrefix = isLast ? " " : "\u2502 ";
|
|
3829
|
+
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
3830
|
+
const label2 = isMissing ? chalk38.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
3831
|
+
console.log(`${prefix2}${connector}${label2}`);
|
|
3832
|
+
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
function printTree(tree, totalCount, solutions) {
|
|
3836
|
+
console.log(chalk38.bold("\nProject Dependency Tree"));
|
|
3837
|
+
console.log(chalk38.cyan(tree.relativePath));
|
|
3838
|
+
printNodes(tree.children, "");
|
|
3839
|
+
console.log(chalk38.dim(`
|
|
3840
|
+
${totalCount} projects total (including root)`));
|
|
3841
|
+
console.log(chalk38.bold("\nSolution Membership"));
|
|
3842
|
+
if (solutions.length === 0) {
|
|
3843
|
+
console.log(chalk38.yellow(" Not found in any .sln"));
|
|
3844
|
+
} else {
|
|
3845
|
+
for (const sln of solutions) {
|
|
3846
|
+
console.log(` ${chalk38.green(sln)}`);
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
console.log();
|
|
3850
|
+
}
|
|
3851
|
+
function nodesToJson(node) {
|
|
3852
|
+
return node.children.map((child) => ({
|
|
3853
|
+
project: child.relativePath,
|
|
3854
|
+
dependencies: nodesToJson(child)
|
|
3855
|
+
}));
|
|
3856
|
+
}
|
|
3857
|
+
function printJson(tree, totalCount, solutions) {
|
|
3858
|
+
console.log(
|
|
3859
|
+
JSON.stringify(
|
|
3860
|
+
{
|
|
3861
|
+
project: tree.relativePath,
|
|
3862
|
+
totalProjects: totalCount,
|
|
3863
|
+
dependencies: nodesToJson(tree),
|
|
3864
|
+
solutions
|
|
3865
|
+
},
|
|
3866
|
+
null,
|
|
3867
|
+
2
|
|
3868
|
+
)
|
|
3869
|
+
);
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3872
|
+
// src/commands/deps/deps.ts
|
|
3873
|
+
async function deps(csprojPath, options2) {
|
|
3874
|
+
const resolved = path20.resolve(csprojPath);
|
|
3875
|
+
if (!existsSync21(resolved)) {
|
|
3876
|
+
console.error(chalk39.red(`File not found: ${resolved}`));
|
|
3877
|
+
process.exit(1);
|
|
3878
|
+
}
|
|
3879
|
+
const repoRoot = findRepoRoot(path20.dirname(resolved));
|
|
3880
|
+
if (!repoRoot) {
|
|
3881
|
+
console.error(chalk39.red("Could not find git repository root"));
|
|
3882
|
+
process.exit(1);
|
|
3883
|
+
}
|
|
3884
|
+
const tree = buildTree(resolved, repoRoot);
|
|
3885
|
+
const totalCount = collectAllDeps(tree).size + 1;
|
|
3886
|
+
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
3887
|
+
if (options2.json) {
|
|
3888
|
+
printJson(tree, totalCount, solutions);
|
|
3889
|
+
} else {
|
|
3890
|
+
printTree(tree, totalCount, solutions);
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
// src/commands/registerDeps.ts
|
|
3895
|
+
function registerDeps(program2) {
|
|
3896
|
+
program2.command("deps").description("Show .csproj project dependency tree and solution membership").argument("<csproj>", "Path to a .csproj file").option("--json", "Output as JSON").action(deps);
|
|
3897
|
+
}
|
|
3898
|
+
|
|
3708
3899
|
// src/commands/devlog/list/index.ts
|
|
3709
3900
|
import { execSync as execSync16 } from "child_process";
|
|
3710
3901
|
import { basename as basename3 } from "path";
|
|
3711
3902
|
|
|
3712
3903
|
// src/commands/devlog/shared.ts
|
|
3713
3904
|
import { execSync as execSync15 } from "child_process";
|
|
3714
|
-
import
|
|
3905
|
+
import chalk40 from "chalk";
|
|
3715
3906
|
|
|
3716
3907
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
3717
|
-
import { readdirSync, readFileSync as
|
|
3908
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync19 } from "fs";
|
|
3718
3909
|
import { homedir as homedir5 } from "os";
|
|
3719
3910
|
import { join as join13 } from "path";
|
|
3720
3911
|
var DEVLOG_DIR = join13(homedir5(), "git/blog/src/content/devlog");
|
|
3721
3912
|
function loadDevlogEntries(repoName) {
|
|
3722
3913
|
const entries = /* @__PURE__ */ new Map();
|
|
3723
3914
|
try {
|
|
3724
|
-
const files =
|
|
3915
|
+
const files = readdirSync2(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
3725
3916
|
for (const file of files) {
|
|
3726
|
-
const content =
|
|
3917
|
+
const content = readFileSync19(join13(DEVLOG_DIR, file), "utf-8");
|
|
3727
3918
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
3728
3919
|
if (frontmatterMatch) {
|
|
3729
3920
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -3772,13 +3963,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
3772
3963
|
}
|
|
3773
3964
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
3774
3965
|
for (const commit2 of commits) {
|
|
3775
|
-
console.log(` ${
|
|
3966
|
+
console.log(` ${chalk40.yellow(commit2.hash)} ${commit2.message}`);
|
|
3776
3967
|
if (verbose) {
|
|
3777
3968
|
const visibleFiles = commit2.files.filter(
|
|
3778
3969
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
3779
3970
|
);
|
|
3780
3971
|
for (const file of visibleFiles) {
|
|
3781
|
-
console.log(` ${
|
|
3972
|
+
console.log(` ${chalk40.dim(file)}`);
|
|
3782
3973
|
}
|
|
3783
3974
|
}
|
|
3784
3975
|
}
|
|
@@ -3803,15 +3994,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
3803
3994
|
}
|
|
3804
3995
|
|
|
3805
3996
|
// src/commands/devlog/list/printDateHeader.ts
|
|
3806
|
-
import
|
|
3997
|
+
import chalk41 from "chalk";
|
|
3807
3998
|
function printDateHeader(date, isSkipped, entries) {
|
|
3808
3999
|
if (isSkipped) {
|
|
3809
|
-
console.log(`${
|
|
4000
|
+
console.log(`${chalk41.bold.blue(date)} ${chalk41.dim("skipped")}`);
|
|
3810
4001
|
} else if (entries && entries.length > 0) {
|
|
3811
|
-
const entryInfo = entries.map((e) => `${
|
|
3812
|
-
console.log(`${
|
|
4002
|
+
const entryInfo = entries.map((e) => `${chalk41.green(e.version)} ${e.title}`).join(" | ");
|
|
4003
|
+
console.log(`${chalk41.bold.blue(date)} ${entryInfo}`);
|
|
3813
4004
|
} else {
|
|
3814
|
-
console.log(`${
|
|
4005
|
+
console.log(`${chalk41.bold.blue(date)} ${chalk41.red("\u26A0 devlog missing")}`);
|
|
3815
4006
|
}
|
|
3816
4007
|
}
|
|
3817
4008
|
|
|
@@ -3914,24 +4105,24 @@ function bumpVersion(version2, type) {
|
|
|
3914
4105
|
|
|
3915
4106
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
3916
4107
|
import { execSync as execSync18 } from "child_process";
|
|
3917
|
-
import
|
|
4108
|
+
import chalk43 from "chalk";
|
|
3918
4109
|
|
|
3919
4110
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
3920
|
-
import
|
|
4111
|
+
import chalk42 from "chalk";
|
|
3921
4112
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
3922
4113
|
if (conventional && firstHash) {
|
|
3923
4114
|
const version2 = getVersionAtCommit(firstHash);
|
|
3924
4115
|
if (version2) {
|
|
3925
|
-
console.log(`${
|
|
4116
|
+
console.log(`${chalk42.bold("version:")} ${stripToMinor(version2)}`);
|
|
3926
4117
|
} else {
|
|
3927
|
-
console.log(`${
|
|
4118
|
+
console.log(`${chalk42.bold("version:")} ${chalk42.red("unknown")}`);
|
|
3928
4119
|
}
|
|
3929
4120
|
} else if (patchVersion && minorVersion) {
|
|
3930
4121
|
console.log(
|
|
3931
|
-
`${
|
|
4122
|
+
`${chalk42.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
3932
4123
|
);
|
|
3933
4124
|
} else {
|
|
3934
|
-
console.log(`${
|
|
4125
|
+
console.log(`${chalk42.bold("version:")} v0.1 (initial)`);
|
|
3935
4126
|
}
|
|
3936
4127
|
}
|
|
3937
4128
|
|
|
@@ -3978,16 +4169,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
3978
4169
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
3979
4170
|
}
|
|
3980
4171
|
function logName(repoName) {
|
|
3981
|
-
console.log(`${
|
|
4172
|
+
console.log(`${chalk43.bold("name:")} ${repoName}`);
|
|
3982
4173
|
}
|
|
3983
4174
|
function displayNextEntry(ctx, targetDate, commits) {
|
|
3984
4175
|
logName(ctx.repoName);
|
|
3985
4176
|
printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
|
|
3986
|
-
console.log(
|
|
4177
|
+
console.log(chalk43.bold.blue(targetDate));
|
|
3987
4178
|
printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
|
|
3988
4179
|
}
|
|
3989
4180
|
function logNoCommits(lastInfo) {
|
|
3990
|
-
console.log(
|
|
4181
|
+
console.log(chalk43.dim(noCommitsMessage(!!lastInfo)));
|
|
3991
4182
|
}
|
|
3992
4183
|
|
|
3993
4184
|
// src/commands/devlog/next/index.ts
|
|
@@ -4022,10 +4213,10 @@ function next(options2) {
|
|
|
4022
4213
|
}
|
|
4023
4214
|
|
|
4024
4215
|
// src/commands/devlog/skip.ts
|
|
4025
|
-
import
|
|
4216
|
+
import chalk44 from "chalk";
|
|
4026
4217
|
function skip(date) {
|
|
4027
4218
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
4028
|
-
console.log(
|
|
4219
|
+
console.log(chalk44.red("Invalid date format. Use YYYY-MM-DD"));
|
|
4029
4220
|
process.exit(1);
|
|
4030
4221
|
}
|
|
4031
4222
|
const config = loadProjectConfig();
|
|
@@ -4033,7 +4224,7 @@ function skip(date) {
|
|
|
4033
4224
|
const skip2 = devlog.skip ?? {};
|
|
4034
4225
|
const skipDays = skip2.days ?? [];
|
|
4035
4226
|
if (skipDays.includes(date)) {
|
|
4036
|
-
console.log(
|
|
4227
|
+
console.log(chalk44.yellow(`${date} is already in skip list`));
|
|
4037
4228
|
return;
|
|
4038
4229
|
}
|
|
4039
4230
|
skipDays.push(date);
|
|
@@ -4042,20 +4233,20 @@ function skip(date) {
|
|
|
4042
4233
|
devlog.skip = skip2;
|
|
4043
4234
|
config.devlog = devlog;
|
|
4044
4235
|
saveConfig(config);
|
|
4045
|
-
console.log(
|
|
4236
|
+
console.log(chalk44.green(`Added ${date} to skip list`));
|
|
4046
4237
|
}
|
|
4047
4238
|
|
|
4048
4239
|
// src/commands/devlog/version.ts
|
|
4049
|
-
import
|
|
4240
|
+
import chalk45 from "chalk";
|
|
4050
4241
|
function version() {
|
|
4051
4242
|
const config = loadConfig();
|
|
4052
4243
|
const name = getRepoName();
|
|
4053
4244
|
const lastInfo = getLastVersionInfo(name, config);
|
|
4054
4245
|
const lastVersion = lastInfo?.version ?? null;
|
|
4055
4246
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
4056
|
-
console.log(`${
|
|
4057
|
-
console.log(`${
|
|
4058
|
-
console.log(`${
|
|
4247
|
+
console.log(`${chalk45.bold("name:")} ${name}`);
|
|
4248
|
+
console.log(`${chalk45.bold("last:")} ${lastVersion ?? chalk45.dim("none")}`);
|
|
4249
|
+
console.log(`${chalk45.bold("next:")} ${nextVersion ?? chalk45.dim("none")}`);
|
|
4059
4250
|
}
|
|
4060
4251
|
|
|
4061
4252
|
// src/commands/registerDevlog.ts
|
|
@@ -4142,7 +4333,7 @@ function validateLine(line) {
|
|
|
4142
4333
|
process.exit(1);
|
|
4143
4334
|
}
|
|
4144
4335
|
}
|
|
4145
|
-
function comment(
|
|
4336
|
+
function comment(path35, line, body) {
|
|
4146
4337
|
validateBody(body);
|
|
4147
4338
|
validateLine(line);
|
|
4148
4339
|
try {
|
|
@@ -4162,7 +4353,7 @@ function comment(path31, line, body) {
|
|
|
4162
4353
|
"-f",
|
|
4163
4354
|
`body=${body}`,
|
|
4164
4355
|
"-f",
|
|
4165
|
-
`path=${
|
|
4356
|
+
`path=${path35}`,
|
|
4166
4357
|
"-F",
|
|
4167
4358
|
`line=${line}`
|
|
4168
4359
|
],
|
|
@@ -4171,7 +4362,7 @@ function comment(path31, line, body) {
|
|
|
4171
4362
|
if (result.status !== 0) {
|
|
4172
4363
|
throw new Error(result.stderr || result.stdout);
|
|
4173
4364
|
}
|
|
4174
|
-
console.log(`Added review comment on ${
|
|
4365
|
+
console.log(`Added review comment on ${path35}:${line}`);
|
|
4175
4366
|
} finally {
|
|
4176
4367
|
unlinkSync3(queryFile);
|
|
4177
4368
|
}
|
|
@@ -4195,7 +4386,7 @@ import { tmpdir as tmpdir3 } from "os";
|
|
|
4195
4386
|
import { join as join16 } from "path";
|
|
4196
4387
|
|
|
4197
4388
|
// src/commands/prs/loadCommentsCache.ts
|
|
4198
|
-
import { existsSync as
|
|
4389
|
+
import { existsSync as existsSync22, readFileSync as readFileSync20, unlinkSync as unlinkSync4 } from "fs";
|
|
4199
4390
|
import { join as join15 } from "path";
|
|
4200
4391
|
import { parse as parse2 } from "yaml";
|
|
4201
4392
|
function getCachePath(prNumber) {
|
|
@@ -4203,15 +4394,15 @@ function getCachePath(prNumber) {
|
|
|
4203
4394
|
}
|
|
4204
4395
|
function loadCommentsCache(prNumber) {
|
|
4205
4396
|
const cachePath = getCachePath(prNumber);
|
|
4206
|
-
if (!
|
|
4397
|
+
if (!existsSync22(cachePath)) {
|
|
4207
4398
|
return null;
|
|
4208
4399
|
}
|
|
4209
|
-
const content =
|
|
4400
|
+
const content = readFileSync20(cachePath, "utf-8");
|
|
4210
4401
|
return parse2(content);
|
|
4211
4402
|
}
|
|
4212
4403
|
function deleteCommentsCache(prNumber) {
|
|
4213
4404
|
const cachePath = getCachePath(prNumber);
|
|
4214
|
-
if (
|
|
4405
|
+
if (existsSync22(cachePath)) {
|
|
4215
4406
|
unlinkSync4(cachePath);
|
|
4216
4407
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
4217
4408
|
}
|
|
@@ -4307,7 +4498,7 @@ function fixed(commentId, sha) {
|
|
|
4307
4498
|
}
|
|
4308
4499
|
|
|
4309
4500
|
// src/commands/prs/listComments/index.ts
|
|
4310
|
-
import { existsSync as
|
|
4501
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync5, writeFileSync as writeFileSync18 } from "fs";
|
|
4311
4502
|
import { join as join18 } from "path";
|
|
4312
4503
|
import { stringify } from "yaml";
|
|
4313
4504
|
|
|
@@ -4387,20 +4578,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
4387
4578
|
}
|
|
4388
4579
|
|
|
4389
4580
|
// src/commands/prs/listComments/formatForHuman.ts
|
|
4390
|
-
import
|
|
4581
|
+
import chalk46 from "chalk";
|
|
4391
4582
|
function formatForHuman(comment2) {
|
|
4392
4583
|
if (comment2.type === "review") {
|
|
4393
|
-
const stateColor = comment2.state === "APPROVED" ?
|
|
4584
|
+
const stateColor = comment2.state === "APPROVED" ? chalk46.green : comment2.state === "CHANGES_REQUESTED" ? chalk46.red : chalk46.yellow;
|
|
4394
4585
|
return [
|
|
4395
|
-
`${
|
|
4586
|
+
`${chalk46.cyan("Review")} by ${chalk46.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
4396
4587
|
comment2.body,
|
|
4397
4588
|
""
|
|
4398
4589
|
].join("\n");
|
|
4399
4590
|
}
|
|
4400
4591
|
const location = comment2.line ? `:${comment2.line}` : "";
|
|
4401
4592
|
return [
|
|
4402
|
-
`${
|
|
4403
|
-
|
|
4593
|
+
`${chalk46.cyan("Line comment")} by ${chalk46.bold(comment2.user)} on ${chalk46.dim(`${comment2.path}${location}`)}`,
|
|
4594
|
+
chalk46.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
4404
4595
|
comment2.body,
|
|
4405
4596
|
""
|
|
4406
4597
|
].join("\n");
|
|
@@ -4424,7 +4615,7 @@ function printComments(comments) {
|
|
|
4424
4615
|
}
|
|
4425
4616
|
function writeCommentsCache(prNumber, comments) {
|
|
4426
4617
|
const assistDir = join18(process.cwd(), ".assist");
|
|
4427
|
-
if (!
|
|
4618
|
+
if (!existsSync23(assistDir)) {
|
|
4428
4619
|
mkdirSync5(assistDir, { recursive: true });
|
|
4429
4620
|
}
|
|
4430
4621
|
const cacheData = {
|
|
@@ -4479,13 +4670,13 @@ import { execSync as execSync24 } from "child_process";
|
|
|
4479
4670
|
import enquirer5 from "enquirer";
|
|
4480
4671
|
|
|
4481
4672
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
4482
|
-
import
|
|
4673
|
+
import chalk47 from "chalk";
|
|
4483
4674
|
var STATUS_MAP = {
|
|
4484
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
4485
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
4675
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk47.magenta("merged"), date: pr.mergedAt } : null,
|
|
4676
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk47.red("closed"), date: pr.closedAt } : null
|
|
4486
4677
|
};
|
|
4487
4678
|
function defaultStatus(pr) {
|
|
4488
|
-
return { label:
|
|
4679
|
+
return { label: chalk47.green("opened"), date: pr.createdAt };
|
|
4489
4680
|
}
|
|
4490
4681
|
function getStatus(pr) {
|
|
4491
4682
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -4494,11 +4685,11 @@ function formatDate(dateStr) {
|
|
|
4494
4685
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
4495
4686
|
}
|
|
4496
4687
|
function formatPrHeader(pr, status2) {
|
|
4497
|
-
return `${
|
|
4688
|
+
return `${chalk47.cyan(`#${pr.number}`)} ${pr.title} ${chalk47.dim(`(${pr.author.login},`)} ${status2.label} ${chalk47.dim(`${formatDate(status2.date)})`)}`;
|
|
4498
4689
|
}
|
|
4499
4690
|
function logPrDetails(pr) {
|
|
4500
4691
|
console.log(
|
|
4501
|
-
|
|
4692
|
+
chalk47.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
4502
4693
|
);
|
|
4503
4694
|
console.log();
|
|
4504
4695
|
}
|
|
@@ -4658,17 +4849,17 @@ function registerPrs(program2) {
|
|
|
4658
4849
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
4659
4850
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
4660
4851
|
});
|
|
4661
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
4662
|
-
comment(
|
|
4852
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path35, line, body) => {
|
|
4853
|
+
comment(path35, Number.parseInt(line, 10), body);
|
|
4663
4854
|
});
|
|
4664
4855
|
}
|
|
4665
4856
|
|
|
4666
4857
|
// src/commands/refactor/check/index.ts
|
|
4667
4858
|
import { spawn as spawn3 } from "child_process";
|
|
4668
|
-
import * as
|
|
4859
|
+
import * as path21 from "path";
|
|
4669
4860
|
|
|
4670
4861
|
// src/commands/refactor/logViolations.ts
|
|
4671
|
-
import
|
|
4862
|
+
import chalk48 from "chalk";
|
|
4672
4863
|
var DEFAULT_MAX_LINES = 100;
|
|
4673
4864
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
4674
4865
|
if (violations.length === 0) {
|
|
@@ -4677,43 +4868,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
4677
4868
|
}
|
|
4678
4869
|
return;
|
|
4679
4870
|
}
|
|
4680
|
-
console.error(
|
|
4871
|
+
console.error(chalk48.red(`
|
|
4681
4872
|
Refactor check failed:
|
|
4682
4873
|
`));
|
|
4683
|
-
console.error(
|
|
4874
|
+
console.error(chalk48.red(` The following files exceed ${maxLines} lines:
|
|
4684
4875
|
`));
|
|
4685
4876
|
for (const violation of violations) {
|
|
4686
|
-
console.error(
|
|
4877
|
+
console.error(chalk48.red(` ${violation.file} (${violation.lines} lines)`));
|
|
4687
4878
|
}
|
|
4688
4879
|
console.error(
|
|
4689
|
-
|
|
4880
|
+
chalk48.yellow(
|
|
4690
4881
|
`
|
|
4691
4882
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
4692
4883
|
way to refactor it, ignore it with:
|
|
4693
4884
|
`
|
|
4694
4885
|
)
|
|
4695
4886
|
);
|
|
4696
|
-
console.error(
|
|
4887
|
+
console.error(chalk48.gray(` assist refactor ignore <file>
|
|
4697
4888
|
`));
|
|
4698
4889
|
if (process.env.CLAUDECODE) {
|
|
4699
|
-
console.error(
|
|
4890
|
+
console.error(chalk48.cyan(`
|
|
4700
4891
|
## Extracting Code to New Files
|
|
4701
4892
|
`));
|
|
4702
4893
|
console.error(
|
|
4703
|
-
|
|
4894
|
+
chalk48.cyan(
|
|
4704
4895
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
4705
4896
|
`
|
|
4706
4897
|
)
|
|
4707
4898
|
);
|
|
4708
4899
|
console.error(
|
|
4709
|
-
|
|
4900
|
+
chalk48.cyan(
|
|
4710
4901
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
4711
4902
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
4712
4903
|
`
|
|
4713
4904
|
)
|
|
4714
4905
|
);
|
|
4715
4906
|
console.error(
|
|
4716
|
-
|
|
4907
|
+
chalk48.cyan(
|
|
4717
4908
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
4718
4909
|
domains, move it to a common/shared folder.
|
|
4719
4910
|
`
|
|
@@ -4842,7 +5033,7 @@ ${failed.length} verify script(s) failed:`);
|
|
|
4842
5033
|
async function runVerifyQuietly() {
|
|
4843
5034
|
const result = findPackageJsonWithVerifyScripts(process.cwd());
|
|
4844
5035
|
if (!result) return true;
|
|
4845
|
-
const packageDir =
|
|
5036
|
+
const packageDir = path21.dirname(result.packageJsonPath);
|
|
4846
5037
|
const results = await Promise.all(
|
|
4847
5038
|
result.verifyScripts.map((script) => runScript(script, packageDir))
|
|
4848
5039
|
);
|
|
@@ -4869,11 +5060,11 @@ async function check(pattern2, options2) {
|
|
|
4869
5060
|
|
|
4870
5061
|
// src/commands/refactor/ignore.ts
|
|
4871
5062
|
import fs16 from "fs";
|
|
4872
|
-
import
|
|
5063
|
+
import chalk49 from "chalk";
|
|
4873
5064
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
4874
5065
|
function ignore(file) {
|
|
4875
5066
|
if (!fs16.existsSync(file)) {
|
|
4876
|
-
console.error(
|
|
5067
|
+
console.error(chalk49.red(`Error: File does not exist: ${file}`));
|
|
4877
5068
|
process.exit(1);
|
|
4878
5069
|
}
|
|
4879
5070
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -4889,18 +5080,18 @@ function ignore(file) {
|
|
|
4889
5080
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
4890
5081
|
}
|
|
4891
5082
|
console.log(
|
|
4892
|
-
|
|
5083
|
+
chalk49.green(
|
|
4893
5084
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
4894
5085
|
)
|
|
4895
5086
|
);
|
|
4896
5087
|
}
|
|
4897
5088
|
|
|
4898
5089
|
// src/commands/refactor/restructure/index.ts
|
|
4899
|
-
import
|
|
4900
|
-
import
|
|
5090
|
+
import path30 from "path";
|
|
5091
|
+
import chalk52 from "chalk";
|
|
4901
5092
|
|
|
4902
5093
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
4903
|
-
import
|
|
5094
|
+
import path22 from "path";
|
|
4904
5095
|
import ts7 from "typescript";
|
|
4905
5096
|
|
|
4906
5097
|
// src/commands/refactor/restructure/buildImportGraph/getImportSpecifiers.ts
|
|
@@ -4927,7 +5118,7 @@ function loadParsedConfig(tsConfigPath) {
|
|
|
4927
5118
|
return ts7.parseJsonConfigFileContent(
|
|
4928
5119
|
configFile.config,
|
|
4929
5120
|
ts7.sys,
|
|
4930
|
-
|
|
5121
|
+
path22.dirname(tsConfigPath)
|
|
4931
5122
|
);
|
|
4932
5123
|
}
|
|
4933
5124
|
function addToSetMap(map, key, value) {
|
|
@@ -4943,7 +5134,7 @@ function resolveImport(specifier, filePath, options2) {
|
|
|
4943
5134
|
const resolved = ts7.resolveModuleName(specifier, filePath, options2, ts7.sys);
|
|
4944
5135
|
const resolvedPath = resolved.resolvedModule?.resolvedFileName;
|
|
4945
5136
|
if (!resolvedPath || resolvedPath.includes("node_modules")) return null;
|
|
4946
|
-
return
|
|
5137
|
+
return path22.resolve(resolvedPath);
|
|
4947
5138
|
}
|
|
4948
5139
|
function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
4949
5140
|
const parsed = loadParsedConfig(tsConfigPath);
|
|
@@ -4952,7 +5143,7 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
4952
5143
|
const importedBy = /* @__PURE__ */ new Map();
|
|
4953
5144
|
const imports = /* @__PURE__ */ new Map();
|
|
4954
5145
|
for (const sourceFile of program2.getSourceFiles()) {
|
|
4955
|
-
const filePath =
|
|
5146
|
+
const filePath = path22.resolve(sourceFile.fileName);
|
|
4956
5147
|
if (filePath.includes("node_modules")) continue;
|
|
4957
5148
|
for (const specifier of getImportSpecifiers(sourceFile)) {
|
|
4958
5149
|
const absTarget = resolveImport(specifier, filePath, parsed.options);
|
|
@@ -4966,12 +5157,12 @@ function buildImportGraph(candidateFiles, tsConfigPath) {
|
|
|
4966
5157
|
}
|
|
4967
5158
|
|
|
4968
5159
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
4969
|
-
import
|
|
5160
|
+
import path23 from "path";
|
|
4970
5161
|
function clusterDirectories(graph) {
|
|
4971
5162
|
const dirImportedBy = /* @__PURE__ */ new Map();
|
|
4972
5163
|
for (const edge of graph.edges) {
|
|
4973
|
-
const sourceDir =
|
|
4974
|
-
const targetDir =
|
|
5164
|
+
const sourceDir = path23.dirname(edge.source);
|
|
5165
|
+
const targetDir = path23.dirname(edge.target);
|
|
4975
5166
|
if (sourceDir === targetDir) continue;
|
|
4976
5167
|
if (!graph.files.has(edge.target)) continue;
|
|
4977
5168
|
const existing = dirImportedBy.get(targetDir) ?? /* @__PURE__ */ new Set();
|
|
@@ -4999,20 +5190,20 @@ function clusterDirectories(graph) {
|
|
|
4999
5190
|
return clusters;
|
|
5000
5191
|
}
|
|
5001
5192
|
function isAncestor(ancestor, descendant) {
|
|
5002
|
-
const rel =
|
|
5193
|
+
const rel = path23.relative(ancestor, descendant);
|
|
5003
5194
|
return !rel.startsWith("..") && rel !== "";
|
|
5004
5195
|
}
|
|
5005
5196
|
|
|
5006
5197
|
// src/commands/refactor/restructure/clusterFiles.ts
|
|
5007
|
-
import
|
|
5198
|
+
import path24 from "path";
|
|
5008
5199
|
function findRootParent(file, importedBy, visited) {
|
|
5009
5200
|
const importers = importedBy.get(file);
|
|
5010
5201
|
if (!importers || importers.size !== 1) return file;
|
|
5011
5202
|
const parent = [...importers][0];
|
|
5012
|
-
const parentDir =
|
|
5013
|
-
const fileDir =
|
|
5203
|
+
const parentDir = path24.dirname(parent);
|
|
5204
|
+
const fileDir = path24.dirname(file);
|
|
5014
5205
|
if (parentDir !== fileDir) return file;
|
|
5015
|
-
if (
|
|
5206
|
+
if (path24.basename(parent, path24.extname(parent)) === "index") return file;
|
|
5016
5207
|
if (visited.has(parent)) return file;
|
|
5017
5208
|
visited.add(parent);
|
|
5018
5209
|
return findRootParent(parent, importedBy, visited);
|
|
@@ -5020,16 +5211,16 @@ function findRootParent(file, importedBy, visited) {
|
|
|
5020
5211
|
function clusterFiles(graph) {
|
|
5021
5212
|
const clusters = /* @__PURE__ */ new Map();
|
|
5022
5213
|
for (const file of graph.files) {
|
|
5023
|
-
const basename7 =
|
|
5214
|
+
const basename7 = path24.basename(file, path24.extname(file));
|
|
5024
5215
|
if (basename7 === "index") continue;
|
|
5025
5216
|
const importers = graph.importedBy.get(file);
|
|
5026
5217
|
if (!importers || importers.size !== 1) continue;
|
|
5027
5218
|
const parent = [...importers][0];
|
|
5028
5219
|
if (!graph.files.has(parent)) continue;
|
|
5029
|
-
const parentDir =
|
|
5030
|
-
const fileDir =
|
|
5220
|
+
const parentDir = path24.dirname(parent);
|
|
5221
|
+
const fileDir = path24.dirname(file);
|
|
5031
5222
|
if (parentDir !== fileDir) continue;
|
|
5032
|
-
const parentBasename =
|
|
5223
|
+
const parentBasename = path24.basename(parent, path24.extname(parent));
|
|
5033
5224
|
if (parentBasename === "index") continue;
|
|
5034
5225
|
const root = findRootParent(parent, graph.importedBy, /* @__PURE__ */ new Set([file]));
|
|
5035
5226
|
if (!root || root === file) continue;
|
|
@@ -5041,7 +5232,7 @@ function clusterFiles(graph) {
|
|
|
5041
5232
|
}
|
|
5042
5233
|
|
|
5043
5234
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
5044
|
-
import
|
|
5235
|
+
import path25 from "path";
|
|
5045
5236
|
|
|
5046
5237
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
5047
5238
|
import fs17 from "fs";
|
|
@@ -5095,7 +5286,7 @@ function normalizeSpecifier(rel) {
|
|
|
5095
5286
|
);
|
|
5096
5287
|
}
|
|
5097
5288
|
function computeSpecifier(fromFile, toFile) {
|
|
5098
|
-
return normalizeSpecifier(
|
|
5289
|
+
return normalizeSpecifier(path25.relative(path25.dirname(fromFile), toFile));
|
|
5099
5290
|
}
|
|
5100
5291
|
function isAffected(edge, moveMap) {
|
|
5101
5292
|
return moveMap.has(edge.target) || moveMap.has(edge.source);
|
|
@@ -5139,51 +5330,51 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
5139
5330
|
}
|
|
5140
5331
|
|
|
5141
5332
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
5142
|
-
import
|
|
5143
|
-
import
|
|
5333
|
+
import path26 from "path";
|
|
5334
|
+
import chalk50 from "chalk";
|
|
5144
5335
|
function relPath(filePath) {
|
|
5145
|
-
return
|
|
5336
|
+
return path26.relative(process.cwd(), filePath);
|
|
5146
5337
|
}
|
|
5147
5338
|
function displayMoves(plan) {
|
|
5148
5339
|
if (plan.moves.length === 0) return;
|
|
5149
|
-
console.log(
|
|
5340
|
+
console.log(chalk50.bold("\nFile moves:"));
|
|
5150
5341
|
for (const move of plan.moves) {
|
|
5151
5342
|
console.log(
|
|
5152
|
-
` ${
|
|
5343
|
+
` ${chalk50.red(relPath(move.from))} \u2192 ${chalk50.green(relPath(move.to))}`
|
|
5153
5344
|
);
|
|
5154
|
-
console.log(
|
|
5345
|
+
console.log(chalk50.dim(` ${move.reason}`));
|
|
5155
5346
|
}
|
|
5156
5347
|
}
|
|
5157
5348
|
function displayRewrites(rewrites) {
|
|
5158
5349
|
if (rewrites.length === 0) return;
|
|
5159
5350
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
5160
|
-
console.log(
|
|
5351
|
+
console.log(chalk50.bold(`
|
|
5161
5352
|
Import rewrites (${affectedFiles.size} files):`));
|
|
5162
5353
|
for (const file of affectedFiles) {
|
|
5163
|
-
console.log(` ${
|
|
5354
|
+
console.log(` ${chalk50.cyan(relPath(file))}:`);
|
|
5164
5355
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
5165
5356
|
(r) => r.file === file
|
|
5166
5357
|
)) {
|
|
5167
5358
|
console.log(
|
|
5168
|
-
` ${
|
|
5359
|
+
` ${chalk50.red(`"${oldSpecifier}"`)} \u2192 ${chalk50.green(`"${newSpecifier}"`)}`
|
|
5169
5360
|
);
|
|
5170
5361
|
}
|
|
5171
5362
|
}
|
|
5172
5363
|
}
|
|
5173
5364
|
function displayPlan(plan) {
|
|
5174
5365
|
if (plan.warnings.length > 0) {
|
|
5175
|
-
console.log(
|
|
5176
|
-
for (const w of plan.warnings) console.log(
|
|
5366
|
+
console.log(chalk50.yellow("\nWarnings:"));
|
|
5367
|
+
for (const w of plan.warnings) console.log(chalk50.yellow(` ${w}`));
|
|
5177
5368
|
}
|
|
5178
5369
|
if (plan.newDirectories.length > 0) {
|
|
5179
|
-
console.log(
|
|
5370
|
+
console.log(chalk50.bold("\nNew directories:"));
|
|
5180
5371
|
for (const dir of plan.newDirectories)
|
|
5181
|
-
console.log(
|
|
5372
|
+
console.log(chalk50.green(` ${dir}/`));
|
|
5182
5373
|
}
|
|
5183
5374
|
displayMoves(plan);
|
|
5184
5375
|
displayRewrites(plan.rewrites);
|
|
5185
5376
|
console.log(
|
|
5186
|
-
|
|
5377
|
+
chalk50.dim(
|
|
5187
5378
|
`
|
|
5188
5379
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
5189
5380
|
)
|
|
@@ -5192,33 +5383,33 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
5192
5383
|
|
|
5193
5384
|
// src/commands/refactor/restructure/executePlan.ts
|
|
5194
5385
|
import fs18 from "fs";
|
|
5195
|
-
import
|
|
5196
|
-
import
|
|
5386
|
+
import path27 from "path";
|
|
5387
|
+
import chalk51 from "chalk";
|
|
5197
5388
|
function executePlan(plan) {
|
|
5198
5389
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
5199
5390
|
for (const [file, content] of updatedContents) {
|
|
5200
5391
|
fs18.writeFileSync(file, content, "utf-8");
|
|
5201
5392
|
console.log(
|
|
5202
|
-
|
|
5393
|
+
chalk51.cyan(` Rewrote imports in ${path27.relative(process.cwd(), file)}`)
|
|
5203
5394
|
);
|
|
5204
5395
|
}
|
|
5205
5396
|
for (const dir of plan.newDirectories) {
|
|
5206
5397
|
fs18.mkdirSync(dir, { recursive: true });
|
|
5207
|
-
console.log(
|
|
5398
|
+
console.log(chalk51.green(` Created ${path27.relative(process.cwd(), dir)}/`));
|
|
5208
5399
|
}
|
|
5209
5400
|
for (const move of plan.moves) {
|
|
5210
|
-
const targetDir =
|
|
5401
|
+
const targetDir = path27.dirname(move.to);
|
|
5211
5402
|
if (!fs18.existsSync(targetDir)) {
|
|
5212
5403
|
fs18.mkdirSync(targetDir, { recursive: true });
|
|
5213
5404
|
}
|
|
5214
5405
|
fs18.renameSync(move.from, move.to);
|
|
5215
5406
|
console.log(
|
|
5216
|
-
|
|
5217
|
-
` Moved ${
|
|
5407
|
+
chalk51.white(
|
|
5408
|
+
` Moved ${path27.relative(process.cwd(), move.from)} \u2192 ${path27.relative(process.cwd(), move.to)}`
|
|
5218
5409
|
)
|
|
5219
5410
|
);
|
|
5220
5411
|
}
|
|
5221
|
-
removeEmptyDirectories(plan.moves.map((m) =>
|
|
5412
|
+
removeEmptyDirectories(plan.moves.map((m) => path27.dirname(m.from)));
|
|
5222
5413
|
}
|
|
5223
5414
|
function removeEmptyDirectories(dirs) {
|
|
5224
5415
|
const unique = [...new Set(dirs)];
|
|
@@ -5228,8 +5419,8 @@ function removeEmptyDirectories(dirs) {
|
|
|
5228
5419
|
if (entries.length === 0) {
|
|
5229
5420
|
fs18.rmdirSync(dir);
|
|
5230
5421
|
console.log(
|
|
5231
|
-
|
|
5232
|
-
` Removed empty directory ${
|
|
5422
|
+
chalk51.dim(
|
|
5423
|
+
` Removed empty directory ${path27.relative(process.cwd(), dir)}`
|
|
5233
5424
|
)
|
|
5234
5425
|
);
|
|
5235
5426
|
}
|
|
@@ -5238,13 +5429,13 @@ function removeEmptyDirectories(dirs) {
|
|
|
5238
5429
|
|
|
5239
5430
|
// src/commands/refactor/restructure/planFileMoves/index.ts
|
|
5240
5431
|
import fs20 from "fs";
|
|
5241
|
-
import
|
|
5432
|
+
import path29 from "path";
|
|
5242
5433
|
|
|
5243
5434
|
// src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
|
|
5244
5435
|
import fs19 from "fs";
|
|
5245
|
-
import
|
|
5436
|
+
import path28 from "path";
|
|
5246
5437
|
function collectEntry(results, dir, entry) {
|
|
5247
|
-
const full =
|
|
5438
|
+
const full = path28.join(dir, entry.name);
|
|
5248
5439
|
const items = entry.isDirectory() ? listFilesRecursive(full) : [full];
|
|
5249
5440
|
results.push(...items);
|
|
5250
5441
|
}
|
|
@@ -5258,15 +5449,15 @@ function listFilesRecursive(dir) {
|
|
|
5258
5449
|
}
|
|
5259
5450
|
function addDirectoryFileMoves(moves, childDir, newLocation, reason) {
|
|
5260
5451
|
for (const file of listFilesRecursive(childDir)) {
|
|
5261
|
-
const rel =
|
|
5262
|
-
moves.push({ from: file, to:
|
|
5452
|
+
const rel = path28.relative(childDir, file);
|
|
5453
|
+
moves.push({ from: file, to: path28.join(newLocation, rel), reason });
|
|
5263
5454
|
}
|
|
5264
5455
|
}
|
|
5265
5456
|
function resolveChildDest(parentDir, childDir) {
|
|
5266
|
-
return
|
|
5457
|
+
return path28.join(parentDir, path28.basename(childDir));
|
|
5267
5458
|
}
|
|
5268
5459
|
function childMoveReason(parentDir) {
|
|
5269
|
-
return `Directory only imported from ${
|
|
5460
|
+
return `Directory only imported from ${path28.basename(parentDir)}/`;
|
|
5270
5461
|
}
|
|
5271
5462
|
function registerDirectoryMove(result, childDir, dest, parentDir) {
|
|
5272
5463
|
result.directories.push(dest);
|
|
@@ -5294,7 +5485,7 @@ function emptyResult() {
|
|
|
5294
5485
|
return { moves: [], directories: [], warnings: [] };
|
|
5295
5486
|
}
|
|
5296
5487
|
function childMoveData(child, newDir, parentBase) {
|
|
5297
|
-
const to =
|
|
5488
|
+
const to = path29.join(newDir, path29.basename(child));
|
|
5298
5489
|
return { from: child, to, reason: `Only imported by ${parentBase}` };
|
|
5299
5490
|
}
|
|
5300
5491
|
function addChildMoves(moves, children, newDir, parentBase) {
|
|
@@ -5307,15 +5498,15 @@ function checkDirConflict(result, label2, dir) {
|
|
|
5307
5498
|
return true;
|
|
5308
5499
|
}
|
|
5309
5500
|
function getBaseName(filePath) {
|
|
5310
|
-
return
|
|
5501
|
+
return path29.basename(filePath, path29.extname(filePath));
|
|
5311
5502
|
}
|
|
5312
5503
|
function resolveClusterDir(parent) {
|
|
5313
|
-
return
|
|
5504
|
+
return path29.join(path29.dirname(parent), getBaseName(parent));
|
|
5314
5505
|
}
|
|
5315
5506
|
function createParentMove(parent, newDir) {
|
|
5316
5507
|
return {
|
|
5317
5508
|
from: parent,
|
|
5318
|
-
to:
|
|
5509
|
+
to: path29.join(newDir, `index${path29.extname(parent)}`),
|
|
5319
5510
|
reason: `Main module of new ${getBaseName(parent)}/ directory`
|
|
5320
5511
|
};
|
|
5321
5512
|
}
|
|
@@ -5339,7 +5530,7 @@ function planFileMoves(clusters) {
|
|
|
5339
5530
|
|
|
5340
5531
|
// src/commands/refactor/restructure/index.ts
|
|
5341
5532
|
function buildPlan(candidateFiles, tsConfigPath) {
|
|
5342
|
-
const candidates = new Set(candidateFiles.map((f) =>
|
|
5533
|
+
const candidates = new Set(candidateFiles.map((f) => path30.resolve(f)));
|
|
5343
5534
|
const graph = buildImportGraph(candidates, tsConfigPath);
|
|
5344
5535
|
const allProjectFiles = /* @__PURE__ */ new Set([
|
|
5345
5536
|
...graph.importedBy.keys(),
|
|
@@ -5359,22 +5550,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
5359
5550
|
const targetPattern = pattern2 ?? "src";
|
|
5360
5551
|
const files = findSourceFiles2(targetPattern);
|
|
5361
5552
|
if (files.length === 0) {
|
|
5362
|
-
console.log(
|
|
5553
|
+
console.log(chalk52.yellow("No files found matching pattern"));
|
|
5363
5554
|
return;
|
|
5364
5555
|
}
|
|
5365
|
-
const tsConfigPath =
|
|
5556
|
+
const tsConfigPath = path30.resolve("tsconfig.json");
|
|
5366
5557
|
const plan = buildPlan(files, tsConfigPath);
|
|
5367
5558
|
if (plan.moves.length === 0) {
|
|
5368
|
-
console.log(
|
|
5559
|
+
console.log(chalk52.green("No restructuring needed"));
|
|
5369
5560
|
return;
|
|
5370
5561
|
}
|
|
5371
5562
|
displayPlan(plan);
|
|
5372
5563
|
if (options2.apply) {
|
|
5373
|
-
console.log(
|
|
5564
|
+
console.log(chalk52.bold("\nApplying changes..."));
|
|
5374
5565
|
executePlan(plan);
|
|
5375
|
-
console.log(
|
|
5566
|
+
console.log(chalk52.green("\nRestructuring complete"));
|
|
5376
5567
|
} else {
|
|
5377
|
-
console.log(
|
|
5568
|
+
console.log(chalk52.dim("\nDry run. Use --apply to execute."));
|
|
5378
5569
|
}
|
|
5379
5570
|
}
|
|
5380
5571
|
|
|
@@ -5397,7 +5588,7 @@ function registerRefactor(program2) {
|
|
|
5397
5588
|
}
|
|
5398
5589
|
|
|
5399
5590
|
// src/commands/transcript/shared.ts
|
|
5400
|
-
import { existsSync as
|
|
5591
|
+
import { existsSync as existsSync24, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
|
|
5401
5592
|
import { basename as basename4, join as join19, relative } from "path";
|
|
5402
5593
|
import * as readline2 from "readline";
|
|
5403
5594
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
@@ -5413,11 +5604,11 @@ function isValidDatePrefix(filename) {
|
|
|
5413
5604
|
return DATE_PREFIX_REGEX.test(filename);
|
|
5414
5605
|
}
|
|
5415
5606
|
function collectFiles(dir, extension) {
|
|
5416
|
-
if (!
|
|
5607
|
+
if (!existsSync24(dir)) return [];
|
|
5417
5608
|
const results = [];
|
|
5418
|
-
for (const entry of
|
|
5609
|
+
for (const entry of readdirSync3(dir)) {
|
|
5419
5610
|
const fullPath = join19(dir, entry);
|
|
5420
|
-
if (
|
|
5611
|
+
if (statSync2(fullPath).isDirectory()) {
|
|
5421
5612
|
results.push(...collectFiles(fullPath, extension));
|
|
5422
5613
|
} else if (entry.endsWith(extension)) {
|
|
5423
5614
|
results.push(fullPath);
|
|
@@ -5510,7 +5701,7 @@ async function configure() {
|
|
|
5510
5701
|
}
|
|
5511
5702
|
|
|
5512
5703
|
// src/commands/transcript/format/index.ts
|
|
5513
|
-
import { existsSync as
|
|
5704
|
+
import { existsSync as existsSync26 } from "fs";
|
|
5514
5705
|
|
|
5515
5706
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
5516
5707
|
import { dirname as dirname15, join as join21 } from "path";
|
|
@@ -5584,7 +5775,7 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
5584
5775
|
}
|
|
5585
5776
|
|
|
5586
5777
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
5587
|
-
import { existsSync as
|
|
5778
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync6, readFileSync as readFileSync21, writeFileSync as writeFileSync19 } from "fs";
|
|
5588
5779
|
import { basename as basename5, dirname as dirname16, join as join22 } from "path";
|
|
5589
5780
|
|
|
5590
5781
|
// src/commands/transcript/cleanText.ts
|
|
@@ -5809,7 +6000,7 @@ function logSkipped(relativeDir, mdFile) {
|
|
|
5809
6000
|
return "skipped";
|
|
5810
6001
|
}
|
|
5811
6002
|
function ensureDirectory(dir, label2) {
|
|
5812
|
-
if (!
|
|
6003
|
+
if (!existsSync25(dir)) {
|
|
5813
6004
|
mkdirSync6(dir, { recursive: true });
|
|
5814
6005
|
console.log(`Created ${label2}: ${dir}`);
|
|
5815
6006
|
}
|
|
@@ -5832,7 +6023,7 @@ function logReduction(cueCount, messageCount) {
|
|
|
5832
6023
|
}
|
|
5833
6024
|
function readAndParseCues(inputPath) {
|
|
5834
6025
|
console.log(`Reading: ${inputPath}`);
|
|
5835
|
-
return processCues(
|
|
6026
|
+
return processCues(readFileSync21(inputPath, "utf-8"));
|
|
5836
6027
|
}
|
|
5837
6028
|
function writeFormatted(outputPath, content) {
|
|
5838
6029
|
writeFileSync19(outputPath, content, "utf-8");
|
|
@@ -5845,7 +6036,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
5845
6036
|
logReduction(cues.length, chatMessages.length);
|
|
5846
6037
|
}
|
|
5847
6038
|
function tryProcessVtt(vttFile, paths) {
|
|
5848
|
-
if (
|
|
6039
|
+
if (existsSync25(paths.outputPath))
|
|
5849
6040
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
5850
6041
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
5851
6042
|
return "processed";
|
|
@@ -5871,7 +6062,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
5871
6062
|
logSummary(counts);
|
|
5872
6063
|
}
|
|
5873
6064
|
function requireVttDir(vttDir) {
|
|
5874
|
-
if (!
|
|
6065
|
+
if (!existsSync26(vttDir)) {
|
|
5875
6066
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
5876
6067
|
process.exit(1);
|
|
5877
6068
|
}
|
|
@@ -5903,28 +6094,28 @@ async function format() {
|
|
|
5903
6094
|
}
|
|
5904
6095
|
|
|
5905
6096
|
// src/commands/transcript/summarise/index.ts
|
|
5906
|
-
import { existsSync as
|
|
6097
|
+
import { existsSync as existsSync28 } from "fs";
|
|
5907
6098
|
import { basename as basename6, dirname as dirname18, join as join24, relative as relative2 } from "path";
|
|
5908
6099
|
|
|
5909
6100
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
5910
6101
|
import {
|
|
5911
|
-
existsSync as
|
|
6102
|
+
existsSync as existsSync27,
|
|
5912
6103
|
mkdirSync as mkdirSync7,
|
|
5913
|
-
readFileSync as
|
|
6104
|
+
readFileSync as readFileSync22,
|
|
5914
6105
|
renameSync as renameSync2,
|
|
5915
6106
|
rmSync
|
|
5916
6107
|
} from "fs";
|
|
5917
6108
|
import { dirname as dirname17, join as join23 } from "path";
|
|
5918
6109
|
|
|
5919
6110
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
5920
|
-
import
|
|
6111
|
+
import chalk53 from "chalk";
|
|
5921
6112
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
5922
6113
|
function validateStagedContent(filename, content) {
|
|
5923
6114
|
const firstLine = content.split("\n")[0];
|
|
5924
6115
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
5925
6116
|
if (!match) {
|
|
5926
6117
|
console.error(
|
|
5927
|
-
|
|
6118
|
+
chalk53.red(
|
|
5928
6119
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
5929
6120
|
)
|
|
5930
6121
|
);
|
|
@@ -5933,7 +6124,7 @@ function validateStagedContent(filename, content) {
|
|
|
5933
6124
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
5934
6125
|
if (!contentAfterLink) {
|
|
5935
6126
|
console.error(
|
|
5936
|
-
|
|
6127
|
+
chalk53.red(
|
|
5937
6128
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
5938
6129
|
)
|
|
5939
6130
|
);
|
|
@@ -5945,7 +6136,7 @@ function validateStagedContent(filename, content) {
|
|
|
5945
6136
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
5946
6137
|
var STAGING_DIR = join23(process.cwd(), ".assist", "transcript");
|
|
5947
6138
|
function processStagedFile() {
|
|
5948
|
-
if (!
|
|
6139
|
+
if (!existsSync27(STAGING_DIR)) {
|
|
5949
6140
|
return false;
|
|
5950
6141
|
}
|
|
5951
6142
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -5954,7 +6145,7 @@ function processStagedFile() {
|
|
|
5954
6145
|
}
|
|
5955
6146
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
5956
6147
|
const stagedFile = stagedFiles[0];
|
|
5957
|
-
const content =
|
|
6148
|
+
const content = readFileSync22(stagedFile.absolutePath, "utf-8");
|
|
5958
6149
|
validateStagedContent(stagedFile.filename, content);
|
|
5959
6150
|
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
5960
6151
|
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
@@ -5969,7 +6160,7 @@ function processStagedFile() {
|
|
|
5969
6160
|
}
|
|
5970
6161
|
const destPath = join23(summaryDir, matchingTranscript.relativePath);
|
|
5971
6162
|
const destDir = dirname17(destPath);
|
|
5972
|
-
if (!
|
|
6163
|
+
if (!existsSync27(destDir)) {
|
|
5973
6164
|
mkdirSync7(destDir, { recursive: true });
|
|
5974
6165
|
}
|
|
5975
6166
|
renameSync2(stagedFile.absolutePath, destPath);
|
|
@@ -5996,7 +6187,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
5996
6187
|
function summarise() {
|
|
5997
6188
|
processStagedFile();
|
|
5998
6189
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
5999
|
-
if (!
|
|
6190
|
+
if (!existsSync28(transcriptsDir)) {
|
|
6000
6191
|
console.log("No transcripts directory found.");
|
|
6001
6192
|
return;
|
|
6002
6193
|
}
|
|
@@ -6100,14 +6291,14 @@ function devices() {
|
|
|
6100
6291
|
}
|
|
6101
6292
|
|
|
6102
6293
|
// src/commands/voice/logs.ts
|
|
6103
|
-
import { existsSync as
|
|
6294
|
+
import { existsSync as existsSync29, readFileSync as readFileSync23 } from "fs";
|
|
6104
6295
|
function logs(options2) {
|
|
6105
|
-
if (!
|
|
6296
|
+
if (!existsSync29(voicePaths.log)) {
|
|
6106
6297
|
console.log("No voice log file found");
|
|
6107
6298
|
return;
|
|
6108
6299
|
}
|
|
6109
6300
|
const count = Number.parseInt(options2.lines ?? "150", 10);
|
|
6110
|
-
const content =
|
|
6301
|
+
const content = readFileSync23(voicePaths.log, "utf-8").trim();
|
|
6111
6302
|
if (!content) {
|
|
6112
6303
|
console.log("Voice log is empty");
|
|
6113
6304
|
return;
|
|
@@ -6134,7 +6325,7 @@ import { join as join28 } from "path";
|
|
|
6134
6325
|
|
|
6135
6326
|
// src/commands/voice/checkLockFile.ts
|
|
6136
6327
|
import { execSync as execSync27 } from "child_process";
|
|
6137
|
-
import { existsSync as
|
|
6328
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync8, readFileSync as readFileSync24, writeFileSync as writeFileSync20 } from "fs";
|
|
6138
6329
|
import { join as join27 } from "path";
|
|
6139
6330
|
function isProcessAlive(pid) {
|
|
6140
6331
|
try {
|
|
@@ -6146,9 +6337,9 @@ function isProcessAlive(pid) {
|
|
|
6146
6337
|
}
|
|
6147
6338
|
function checkLockFile() {
|
|
6148
6339
|
const lockFile = getLockFile();
|
|
6149
|
-
if (!
|
|
6340
|
+
if (!existsSync30(lockFile)) return;
|
|
6150
6341
|
try {
|
|
6151
|
-
const lock = JSON.parse(
|
|
6342
|
+
const lock = JSON.parse(readFileSync24(lockFile, "utf-8"));
|
|
6152
6343
|
if (lock.pid && isProcessAlive(lock.pid)) {
|
|
6153
6344
|
console.error(
|
|
6154
6345
|
`Voice daemon already running (PID ${lock.pid}, env: ${lock.env}). Stop it first with: assist voice stop`
|
|
@@ -6159,7 +6350,7 @@ function checkLockFile() {
|
|
|
6159
6350
|
}
|
|
6160
6351
|
}
|
|
6161
6352
|
function bootstrapVenv() {
|
|
6162
|
-
if (
|
|
6353
|
+
if (existsSync30(getVenvPython())) return;
|
|
6163
6354
|
console.log("Setting up Python environment...");
|
|
6164
6355
|
const pythonDir = getPythonDir();
|
|
6165
6356
|
execSync27(
|
|
@@ -6250,7 +6441,7 @@ function start2(options2) {
|
|
|
6250
6441
|
}
|
|
6251
6442
|
|
|
6252
6443
|
// src/commands/voice/status.ts
|
|
6253
|
-
import { existsSync as
|
|
6444
|
+
import { existsSync as existsSync31, readFileSync as readFileSync25 } from "fs";
|
|
6254
6445
|
function isProcessAlive2(pid) {
|
|
6255
6446
|
try {
|
|
6256
6447
|
process.kill(pid, 0);
|
|
@@ -6260,16 +6451,16 @@ function isProcessAlive2(pid) {
|
|
|
6260
6451
|
}
|
|
6261
6452
|
}
|
|
6262
6453
|
function readRecentLogs(count) {
|
|
6263
|
-
if (!
|
|
6264
|
-
const lines =
|
|
6454
|
+
if (!existsSync31(voicePaths.log)) return [];
|
|
6455
|
+
const lines = readFileSync25(voicePaths.log, "utf-8").trim().split("\n");
|
|
6265
6456
|
return lines.slice(-count);
|
|
6266
6457
|
}
|
|
6267
6458
|
function status() {
|
|
6268
|
-
if (!
|
|
6459
|
+
if (!existsSync31(voicePaths.pid)) {
|
|
6269
6460
|
console.log("Voice daemon: not running (no PID file)");
|
|
6270
6461
|
return;
|
|
6271
6462
|
}
|
|
6272
|
-
const pid = Number.parseInt(
|
|
6463
|
+
const pid = Number.parseInt(readFileSync25(voicePaths.pid, "utf-8").trim(), 10);
|
|
6273
6464
|
const alive = isProcessAlive2(pid);
|
|
6274
6465
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
6275
6466
|
const recent = readRecentLogs(5);
|
|
@@ -6288,13 +6479,13 @@ function status() {
|
|
|
6288
6479
|
}
|
|
6289
6480
|
|
|
6290
6481
|
// src/commands/voice/stop.ts
|
|
6291
|
-
import { existsSync as
|
|
6482
|
+
import { existsSync as existsSync32, readFileSync as readFileSync26, unlinkSync as unlinkSync7 } from "fs";
|
|
6292
6483
|
function stop() {
|
|
6293
|
-
if (!
|
|
6484
|
+
if (!existsSync32(voicePaths.pid)) {
|
|
6294
6485
|
console.log("Voice daemon is not running (no PID file)");
|
|
6295
6486
|
return;
|
|
6296
6487
|
}
|
|
6297
|
-
const pid = Number.parseInt(
|
|
6488
|
+
const pid = Number.parseInt(readFileSync26(voicePaths.pid, "utf-8").trim(), 10);
|
|
6298
6489
|
try {
|
|
6299
6490
|
process.kill(pid, "SIGTERM");
|
|
6300
6491
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -6307,7 +6498,7 @@ function stop() {
|
|
|
6307
6498
|
}
|
|
6308
6499
|
try {
|
|
6309
6500
|
const lockFile = getLockFile();
|
|
6310
|
-
if (
|
|
6501
|
+
if (existsSync32(lockFile)) unlinkSync7(lockFile);
|
|
6311
6502
|
} catch {
|
|
6312
6503
|
}
|
|
6313
6504
|
console.log("Voice daemon stopped");
|
|
@@ -6326,7 +6517,7 @@ function registerVoice(program2) {
|
|
|
6326
6517
|
|
|
6327
6518
|
// src/commands/roam/auth.ts
|
|
6328
6519
|
import { randomBytes } from "crypto";
|
|
6329
|
-
import
|
|
6520
|
+
import chalk54 from "chalk";
|
|
6330
6521
|
|
|
6331
6522
|
// src/lib/openBrowser.ts
|
|
6332
6523
|
import { execSync as execSync28 } from "child_process";
|
|
@@ -6501,13 +6692,13 @@ async function auth() {
|
|
|
6501
6692
|
saveGlobalConfig(config);
|
|
6502
6693
|
const state = randomBytes(16).toString("hex");
|
|
6503
6694
|
console.log(
|
|
6504
|
-
|
|
6695
|
+
chalk54.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
6505
6696
|
);
|
|
6506
|
-
console.log(
|
|
6507
|
-
console.log(
|
|
6508
|
-
console.log(
|
|
6697
|
+
console.log(chalk54.white("http://localhost:14523/callback\n"));
|
|
6698
|
+
console.log(chalk54.blue("Opening browser for authorization..."));
|
|
6699
|
+
console.log(chalk54.dim("Waiting for authorization callback..."));
|
|
6509
6700
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
6510
|
-
console.log(
|
|
6701
|
+
console.log(chalk54.dim("Exchanging code for tokens..."));
|
|
6511
6702
|
const tokens = await exchangeToken({
|
|
6512
6703
|
code,
|
|
6513
6704
|
clientId,
|
|
@@ -6523,7 +6714,7 @@ async function auth() {
|
|
|
6523
6714
|
};
|
|
6524
6715
|
saveGlobalConfig(config);
|
|
6525
6716
|
console.log(
|
|
6526
|
-
|
|
6717
|
+
chalk54.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
6527
6718
|
);
|
|
6528
6719
|
}
|
|
6529
6720
|
|
|
@@ -6671,14 +6862,14 @@ function run2(name, args) {
|
|
|
6671
6862
|
}
|
|
6672
6863
|
|
|
6673
6864
|
// src/commands/statusLine.ts
|
|
6674
|
-
import
|
|
6865
|
+
import chalk55 from "chalk";
|
|
6675
6866
|
function formatNumber(num) {
|
|
6676
6867
|
return num.toLocaleString("en-US");
|
|
6677
6868
|
}
|
|
6678
6869
|
function colorizePercent(pct) {
|
|
6679
6870
|
const label2 = `${pct}%`;
|
|
6680
|
-
if (pct > 80) return
|
|
6681
|
-
if (pct > 40) return
|
|
6871
|
+
if (pct > 80) return chalk55.red(label2);
|
|
6872
|
+
if (pct > 40) return chalk55.yellow(label2);
|
|
6682
6873
|
return label2;
|
|
6683
6874
|
}
|
|
6684
6875
|
async function statusLine() {
|
|
@@ -6698,27 +6889,27 @@ async function statusLine() {
|
|
|
6698
6889
|
// src/commands/sync.ts
|
|
6699
6890
|
import * as fs23 from "fs";
|
|
6700
6891
|
import * as os from "os";
|
|
6701
|
-
import * as
|
|
6892
|
+
import * as path33 from "path";
|
|
6702
6893
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
6703
6894
|
|
|
6704
6895
|
// src/commands/sync/syncClaudeMd.ts
|
|
6705
6896
|
import * as fs21 from "fs";
|
|
6706
|
-
import * as
|
|
6707
|
-
import
|
|
6897
|
+
import * as path31 from "path";
|
|
6898
|
+
import chalk56 from "chalk";
|
|
6708
6899
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
6709
|
-
const source =
|
|
6710
|
-
const target =
|
|
6900
|
+
const source = path31.join(claudeDir, "CLAUDE.md");
|
|
6901
|
+
const target = path31.join(targetBase, "CLAUDE.md");
|
|
6711
6902
|
const sourceContent = fs21.readFileSync(source, "utf-8");
|
|
6712
6903
|
if (fs21.existsSync(target)) {
|
|
6713
6904
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
6714
6905
|
if (sourceContent !== targetContent) {
|
|
6715
6906
|
console.log(
|
|
6716
|
-
|
|
6907
|
+
chalk56.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
6717
6908
|
);
|
|
6718
6909
|
console.log();
|
|
6719
6910
|
printDiff(targetContent, sourceContent);
|
|
6720
6911
|
const confirm = await promptConfirm(
|
|
6721
|
-
|
|
6912
|
+
chalk56.red("Overwrite existing CLAUDE.md?"),
|
|
6722
6913
|
false
|
|
6723
6914
|
);
|
|
6724
6915
|
if (!confirm) {
|
|
@@ -6733,11 +6924,11 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
6733
6924
|
|
|
6734
6925
|
// src/commands/sync/syncSettings.ts
|
|
6735
6926
|
import * as fs22 from "fs";
|
|
6736
|
-
import * as
|
|
6737
|
-
import
|
|
6927
|
+
import * as path32 from "path";
|
|
6928
|
+
import chalk57 from "chalk";
|
|
6738
6929
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
6739
|
-
const source =
|
|
6740
|
-
const target =
|
|
6930
|
+
const source = path32.join(claudeDir, "settings.json");
|
|
6931
|
+
const target = path32.join(targetBase, "settings.json");
|
|
6741
6932
|
const sourceContent = fs22.readFileSync(source, "utf-8");
|
|
6742
6933
|
const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
|
|
6743
6934
|
if (fs22.existsSync(target)) {
|
|
@@ -6750,14 +6941,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
6750
6941
|
if (mergedContent !== normalizedTarget) {
|
|
6751
6942
|
if (!options2?.yes) {
|
|
6752
6943
|
console.log(
|
|
6753
|
-
|
|
6944
|
+
chalk57.yellow(
|
|
6754
6945
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
6755
6946
|
)
|
|
6756
6947
|
);
|
|
6757
6948
|
console.log();
|
|
6758
6949
|
printDiff(targetContent, mergedContent);
|
|
6759
6950
|
const confirm = await promptConfirm(
|
|
6760
|
-
|
|
6951
|
+
chalk57.red("Overwrite existing settings.json?"),
|
|
6761
6952
|
false
|
|
6762
6953
|
);
|
|
6763
6954
|
if (!confirm) {
|
|
@@ -6773,21 +6964,21 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
6773
6964
|
|
|
6774
6965
|
// src/commands/sync.ts
|
|
6775
6966
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
6776
|
-
var __dirname8 =
|
|
6967
|
+
var __dirname8 = path33.dirname(__filename4);
|
|
6777
6968
|
async function sync(options2) {
|
|
6778
|
-
const claudeDir =
|
|
6779
|
-
const targetBase =
|
|
6969
|
+
const claudeDir = path33.join(__dirname8, "..", "claude");
|
|
6970
|
+
const targetBase = path33.join(os.homedir(), ".claude");
|
|
6780
6971
|
syncCommands(claudeDir, targetBase);
|
|
6781
6972
|
await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
|
|
6782
6973
|
await syncClaudeMd(claudeDir, targetBase);
|
|
6783
6974
|
}
|
|
6784
6975
|
function syncCommands(claudeDir, targetBase) {
|
|
6785
|
-
const sourceDir =
|
|
6786
|
-
const targetDir =
|
|
6976
|
+
const sourceDir = path33.join(claudeDir, "commands");
|
|
6977
|
+
const targetDir = path33.join(targetBase, "commands");
|
|
6787
6978
|
fs23.mkdirSync(targetDir, { recursive: true });
|
|
6788
6979
|
const files = fs23.readdirSync(sourceDir);
|
|
6789
6980
|
for (const file of files) {
|
|
6790
|
-
fs23.copyFileSync(
|
|
6981
|
+
fs23.copyFileSync(path33.join(sourceDir, file), path33.join(targetDir, file));
|
|
6791
6982
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
6792
6983
|
}
|
|
6793
6984
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -6795,11 +6986,11 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
6795
6986
|
|
|
6796
6987
|
// src/commands/update.ts
|
|
6797
6988
|
import { execSync as execSync29 } from "child_process";
|
|
6798
|
-
import * as
|
|
6989
|
+
import * as path34 from "path";
|
|
6799
6990
|
function isGlobalNpmInstall(dir) {
|
|
6800
6991
|
try {
|
|
6801
6992
|
const globalPrefix = execSync29("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
6802
|
-
return
|
|
6993
|
+
return path34.resolve(dir).toLowerCase().startsWith(path34.resolve(globalPrefix).toLowerCase());
|
|
6803
6994
|
} catch {
|
|
6804
6995
|
return false;
|
|
6805
6996
|
}
|
|
@@ -6810,6 +7001,8 @@ async function update() {
|
|
|
6810
7001
|
if (isGitRepo(installDir)) {
|
|
6811
7002
|
console.log("Detected git repo installation, pulling latest...");
|
|
6812
7003
|
execSync29("git pull", { cwd: installDir, stdio: "inherit" });
|
|
7004
|
+
console.log("Installing dependencies...");
|
|
7005
|
+
execSync29("npm i", { cwd: installDir, stdio: "inherit" });
|
|
6813
7006
|
console.log("Building...");
|
|
6814
7007
|
execSync29("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
6815
7008
|
console.log("Syncing commands...");
|
|
@@ -6861,6 +7054,7 @@ registerRefactor(program);
|
|
|
6861
7054
|
registerDevlog(program);
|
|
6862
7055
|
registerDeploy(program);
|
|
6863
7056
|
registerComplexity(program);
|
|
7057
|
+
registerDeps(program);
|
|
6864
7058
|
registerTranscript(program);
|
|
6865
7059
|
registerVoice(program);
|
|
6866
7060
|
program.parse();
|