@staff0rd/assist 0.104.0 → 0.106.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 +1 -0
- package/dist/index.js +357 -226
- 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.106.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -129,9 +129,7 @@ var assistConfigSchema = z.strictObject({
|
|
|
129
129
|
devlog: z.strictObject({
|
|
130
130
|
name: z.string().optional(),
|
|
131
131
|
ignore: z.array(z.string()).optional(),
|
|
132
|
-
skip: z.
|
|
133
|
-
days: z.array(z.string()).optional()
|
|
134
|
-
}).optional()
|
|
132
|
+
skip: z.record(z.string(), z.array(z.string())).optional()
|
|
135
133
|
}).optional(),
|
|
136
134
|
notify: z.strictObject({
|
|
137
135
|
enabled: z.boolean().default(true)
|
|
@@ -3717,47 +3715,84 @@ function registerDeploy(program2) {
|
|
|
3717
3715
|
import { execSync as execSync16 } from "child_process";
|
|
3718
3716
|
import { basename as basename3 } from "path";
|
|
3719
3717
|
|
|
3718
|
+
// src/commands/devlog/loadBlogSkipDays.ts
|
|
3719
|
+
import { homedir as homedir5 } from "os";
|
|
3720
|
+
import { join as join13 } from "path";
|
|
3721
|
+
var BLOG_REPO_ROOT = join13(homedir5(), "git/blog");
|
|
3722
|
+
function loadBlogSkipDays(repoName) {
|
|
3723
|
+
const config = loadRawYaml(join13(BLOG_REPO_ROOT, "assist.yml"));
|
|
3724
|
+
const devlog = config.devlog;
|
|
3725
|
+
const skip2 = devlog?.skip;
|
|
3726
|
+
return new Set(skip2?.[repoName] ?? []);
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3720
3729
|
// src/commands/devlog/shared.ts
|
|
3721
3730
|
import { execSync as execSync15 } from "child_process";
|
|
3722
3731
|
import chalk38 from "chalk";
|
|
3723
3732
|
|
|
3724
3733
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
3725
3734
|
import { readdirSync, readFileSync as readFileSync17 } from "fs";
|
|
3726
|
-
import {
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3735
|
+
import { join as join14 } from "path";
|
|
3736
|
+
var DEVLOG_DIR = join14(BLOG_REPO_ROOT, "src/content/devlog");
|
|
3737
|
+
function extractFrontmatter(content) {
|
|
3738
|
+
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
3739
|
+
return fm?.[1] ?? null;
|
|
3740
|
+
}
|
|
3741
|
+
function matchField(frontmatter, pattern2) {
|
|
3742
|
+
return frontmatter.match(pattern2)?.[1]?.trim() ?? null;
|
|
3743
|
+
}
|
|
3744
|
+
function parseFrontmatter(content, filename) {
|
|
3745
|
+
const frontmatter = extractFrontmatter(content);
|
|
3746
|
+
if (!frontmatter) return null;
|
|
3747
|
+
const date = matchField(frontmatter, /date:\s*"?(\d{4}-\d{2}-\d{2})"?/);
|
|
3748
|
+
const tagsRaw = matchField(frontmatter, /tags:\s*\[([^\]]*)\]/);
|
|
3749
|
+
if (!date || !tagsRaw) return null;
|
|
3750
|
+
const repoTag = tagsRaw.split(",")[0]?.trim();
|
|
3751
|
+
if (!repoTag) return null;
|
|
3752
|
+
return {
|
|
3753
|
+
date,
|
|
3754
|
+
repoTag,
|
|
3755
|
+
version: matchField(frontmatter, /version:\s*(.+)/),
|
|
3756
|
+
title: matchField(frontmatter, /title:\s*(.+)/),
|
|
3757
|
+
filename
|
|
3758
|
+
};
|
|
3759
|
+
}
|
|
3760
|
+
function readDevlogFiles(callback) {
|
|
3731
3761
|
try {
|
|
3732
3762
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
3733
3763
|
for (const file of files) {
|
|
3734
|
-
const content = readFileSync17(
|
|
3735
|
-
const
|
|
3736
|
-
if (
|
|
3737
|
-
const frontmatter = frontmatterMatch[1];
|
|
3738
|
-
const dateMatch = frontmatter.match(/date:\s*"?(\d{4}-\d{2}-\d{2})"?/);
|
|
3739
|
-
const versionMatch = frontmatter.match(/version:\s*(.+)/);
|
|
3740
|
-
const titleMatch = frontmatter.match(/title:\s*(.+)/);
|
|
3741
|
-
const tagsMatch = frontmatter.match(/tags:\s*\[([^\]]*)\]/);
|
|
3742
|
-
if (dateMatch && versionMatch && titleMatch && tagsMatch) {
|
|
3743
|
-
const tags = tagsMatch[1].split(",").map((t) => t.trim());
|
|
3744
|
-
const firstTag = tags[0];
|
|
3745
|
-
if (firstTag !== repoName) {
|
|
3746
|
-
continue;
|
|
3747
|
-
}
|
|
3748
|
-
const date = dateMatch[1];
|
|
3749
|
-
const version2 = versionMatch[1].trim();
|
|
3750
|
-
const title = titleMatch[1].trim();
|
|
3751
|
-
const existing = entries.get(date) || [];
|
|
3752
|
-
existing.push({ version: version2, title, filename: file });
|
|
3753
|
-
entries.set(date, existing);
|
|
3754
|
-
}
|
|
3755
|
-
}
|
|
3764
|
+
const content = readFileSync17(join14(DEVLOG_DIR, file), "utf-8");
|
|
3765
|
+
const parsed = parseFrontmatter(content, file);
|
|
3766
|
+
if (parsed) callback(parsed);
|
|
3756
3767
|
}
|
|
3757
3768
|
} catch {
|
|
3758
3769
|
}
|
|
3770
|
+
}
|
|
3771
|
+
function loadDevlogEntries(repoName) {
|
|
3772
|
+
const entries = /* @__PURE__ */ new Map();
|
|
3773
|
+
readDevlogFiles((parsed) => {
|
|
3774
|
+
if (parsed.repoTag !== repoName) return;
|
|
3775
|
+
if (!parsed.version || !parsed.title) return;
|
|
3776
|
+
const existing = entries.get(parsed.date) || [];
|
|
3777
|
+
existing.push({
|
|
3778
|
+
version: parsed.version,
|
|
3779
|
+
title: parsed.title,
|
|
3780
|
+
filename: parsed.filename
|
|
3781
|
+
});
|
|
3782
|
+
entries.set(parsed.date, existing);
|
|
3783
|
+
});
|
|
3759
3784
|
return entries;
|
|
3760
3785
|
}
|
|
3786
|
+
function loadAllDevlogLatestDates() {
|
|
3787
|
+
const latest = /* @__PURE__ */ new Map();
|
|
3788
|
+
readDevlogFiles((parsed) => {
|
|
3789
|
+
const existing = latest.get(parsed.repoTag);
|
|
3790
|
+
if (!existing || parsed.date > existing) {
|
|
3791
|
+
latest.set(parsed.repoTag, parsed.date);
|
|
3792
|
+
}
|
|
3793
|
+
});
|
|
3794
|
+
return latest;
|
|
3795
|
+
}
|
|
3761
3796
|
|
|
3762
3797
|
// src/commands/devlog/shared.ts
|
|
3763
3798
|
function getCommitFiles(hash) {
|
|
@@ -3828,8 +3863,8 @@ function list3(options2) {
|
|
|
3828
3863
|
const config = loadConfig();
|
|
3829
3864
|
const days = options2.days ?? 30;
|
|
3830
3865
|
const ignore2 = options2.ignore ?? config.devlog?.ignore ?? [];
|
|
3831
|
-
const skipDays = new Set(config.devlog?.skip?.days ?? []);
|
|
3832
3866
|
const repoName = basename3(process.cwd());
|
|
3867
|
+
const skipDays = loadBlogSkipDays(repoName);
|
|
3833
3868
|
const devlogEntries = loadDevlogEntries(repoName);
|
|
3834
3869
|
const reverseFlag = options2.reverse ? "--reverse " : "";
|
|
3835
3870
|
const limitFlag = options2.reverse ? "" : "-n 500 ";
|
|
@@ -3973,8 +4008,8 @@ function printVersionInfo(config, lastInfo, firstHash) {
|
|
|
3973
4008
|
function resolveIgnoreList(options2, config) {
|
|
3974
4009
|
return options2.ignore ?? config.devlog?.ignore ?? [];
|
|
3975
4010
|
}
|
|
3976
|
-
function resolveSkipDays(
|
|
3977
|
-
return
|
|
4011
|
+
function resolveSkipDays(repoName) {
|
|
4012
|
+
return loadBlogSkipDays(repoName);
|
|
3978
4013
|
}
|
|
3979
4014
|
function getLastDate(lastInfo) {
|
|
3980
4015
|
return lastInfo?.date ?? null;
|
|
@@ -4014,7 +4049,10 @@ function fetchNextCommits(ctx) {
|
|
|
4014
4049
|
ctx.ignore,
|
|
4015
4050
|
getLastDate(ctx.lastInfo)
|
|
4016
4051
|
);
|
|
4017
|
-
const targetDate = findTargetDate(
|
|
4052
|
+
const targetDate = findTargetDate(
|
|
4053
|
+
commitsByDate,
|
|
4054
|
+
resolveSkipDays(ctx.repoName)
|
|
4055
|
+
);
|
|
4018
4056
|
return targetDate ? { targetDate, commits: getCommitsForDate(commitsByDate, targetDate) } : null;
|
|
4019
4057
|
}
|
|
4020
4058
|
function showResult(ctx, found) {
|
|
@@ -4029,41 +4067,129 @@ function next(options2) {
|
|
|
4029
4067
|
showResult(ctx, fetchNextCommits(ctx));
|
|
4030
4068
|
}
|
|
4031
4069
|
|
|
4032
|
-
// src/commands/devlog/
|
|
4070
|
+
// src/commands/devlog/repos/index.ts
|
|
4071
|
+
import { execSync as execSync19 } from "child_process";
|
|
4072
|
+
|
|
4073
|
+
// src/commands/devlog/repos/printReposTable.ts
|
|
4033
4074
|
import chalk42 from "chalk";
|
|
4075
|
+
function colorStatus(status2) {
|
|
4076
|
+
if (status2 === "missing") return chalk42.red(status2);
|
|
4077
|
+
if (status2 === "outdated") return chalk42.yellow(status2);
|
|
4078
|
+
return chalk42.green(status2);
|
|
4079
|
+
}
|
|
4080
|
+
function formatRow(row, nameWidth) {
|
|
4081
|
+
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
4082
|
+
return `${row.name.padEnd(nameWidth)} ${row.lastPush} ${devlog} ${colorStatus(row.status)}`;
|
|
4083
|
+
}
|
|
4084
|
+
function printReposTable(rows) {
|
|
4085
|
+
const nameWidth = Math.max(4, ...rows.map((r) => r.name.length));
|
|
4086
|
+
const header = [
|
|
4087
|
+
"Repo".padEnd(nameWidth),
|
|
4088
|
+
"Last Push".padEnd(10),
|
|
4089
|
+
"Last Devlog".padEnd(11),
|
|
4090
|
+
"Status"
|
|
4091
|
+
].join(" ");
|
|
4092
|
+
console.log(chalk42.dim(header));
|
|
4093
|
+
console.log(chalk42.dim("-".repeat(header.length)));
|
|
4094
|
+
for (const row of rows) {
|
|
4095
|
+
console.log(formatRow(row, nameWidth));
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
// src/commands/devlog/repos/index.ts
|
|
4100
|
+
var statusOrder = { missing: 0, outdated: 1, ok: 2 };
|
|
4101
|
+
function getStatus(lastPush, lastDevlog) {
|
|
4102
|
+
if (!lastDevlog) return "missing";
|
|
4103
|
+
return lastDevlog < lastPush ? "outdated" : "ok";
|
|
4104
|
+
}
|
|
4105
|
+
function fetchRepos(days, all) {
|
|
4106
|
+
const json = execSync19(
|
|
4107
|
+
"gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
|
|
4108
|
+
{ encoding: "utf-8" }
|
|
4109
|
+
);
|
|
4110
|
+
const allRepos = JSON.parse(json);
|
|
4111
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
4112
|
+
cutoff.setDate(cutoff.getDate() - days);
|
|
4113
|
+
const cutoffStr = cutoff.toISOString().slice(0, 10);
|
|
4114
|
+
return allRepos.filter((r) => {
|
|
4115
|
+
if (r.isArchived) return false;
|
|
4116
|
+
if (all) return true;
|
|
4117
|
+
return r.pushedAt.slice(0, 10) >= cutoffStr;
|
|
4118
|
+
});
|
|
4119
|
+
}
|
|
4120
|
+
function toRow(repo, devlogDates) {
|
|
4121
|
+
const lastPush = repo.pushedAt.slice(0, 10);
|
|
4122
|
+
const lastDevlog = devlogDates.get(repo.name) ?? null;
|
|
4123
|
+
return {
|
|
4124
|
+
name: repo.name,
|
|
4125
|
+
lastPush,
|
|
4126
|
+
lastDevlog,
|
|
4127
|
+
status: getStatus(lastPush, lastDevlog)
|
|
4128
|
+
};
|
|
4129
|
+
}
|
|
4130
|
+
function sortRows(rows) {
|
|
4131
|
+
return rows.sort((a, b) => {
|
|
4132
|
+
const s = statusOrder[a.status] - statusOrder[b.status];
|
|
4133
|
+
if (s !== 0) return s;
|
|
4134
|
+
return b.lastPush.localeCompare(a.lastPush);
|
|
4135
|
+
});
|
|
4136
|
+
}
|
|
4137
|
+
function repos(options2) {
|
|
4138
|
+
const ghRepos = fetchRepos(options2.days ?? 30, options2.all ?? false);
|
|
4139
|
+
if (ghRepos.length === 0) {
|
|
4140
|
+
console.log("No repos with recent activity found.");
|
|
4141
|
+
return;
|
|
4142
|
+
}
|
|
4143
|
+
const devlogDates = loadAllDevlogLatestDates();
|
|
4144
|
+
const rows = ghRepos.map((repo) => toRow(repo, devlogDates));
|
|
4145
|
+
printReposTable(sortRows(rows));
|
|
4146
|
+
}
|
|
4147
|
+
|
|
4148
|
+
// src/commands/devlog/skip.ts
|
|
4149
|
+
import { writeFileSync as writeFileSync15 } from "fs";
|
|
4150
|
+
import { join as join15 } from "path";
|
|
4151
|
+
import chalk43 from "chalk";
|
|
4152
|
+
import { stringify as stringifyYaml4 } from "yaml";
|
|
4153
|
+
function getBlogConfigPath() {
|
|
4154
|
+
return join15(BLOG_REPO_ROOT, "assist.yml");
|
|
4155
|
+
}
|
|
4034
4156
|
function skip(date) {
|
|
4035
4157
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
4036
|
-
console.log(
|
|
4158
|
+
console.log(chalk43.red("Invalid date format. Use YYYY-MM-DD"));
|
|
4037
4159
|
process.exit(1);
|
|
4038
4160
|
}
|
|
4039
|
-
const
|
|
4161
|
+
const repoName = getRepoName();
|
|
4162
|
+
const configPath = getBlogConfigPath();
|
|
4163
|
+
const config = loadRawYaml(configPath);
|
|
4040
4164
|
const devlog = config.devlog ?? {};
|
|
4041
4165
|
const skip2 = devlog.skip ?? {};
|
|
4042
|
-
const skipDays = skip2
|
|
4166
|
+
const skipDays = skip2[repoName] ?? [];
|
|
4043
4167
|
if (skipDays.includes(date)) {
|
|
4044
|
-
console.log(
|
|
4168
|
+
console.log(
|
|
4169
|
+
chalk43.yellow(`${date} is already in skip list for ${repoName}`)
|
|
4170
|
+
);
|
|
4045
4171
|
return;
|
|
4046
4172
|
}
|
|
4047
4173
|
skipDays.push(date);
|
|
4048
4174
|
skipDays.sort();
|
|
4049
|
-
skip2
|
|
4175
|
+
skip2[repoName] = skipDays;
|
|
4050
4176
|
devlog.skip = skip2;
|
|
4051
4177
|
config.devlog = devlog;
|
|
4052
|
-
|
|
4053
|
-
console.log(
|
|
4178
|
+
writeFileSync15(configPath, stringifyYaml4(config, { lineWidth: 0 }));
|
|
4179
|
+
console.log(chalk43.green(`Added ${date} to skip list for ${repoName}`));
|
|
4054
4180
|
}
|
|
4055
4181
|
|
|
4056
4182
|
// src/commands/devlog/version.ts
|
|
4057
|
-
import
|
|
4183
|
+
import chalk44 from "chalk";
|
|
4058
4184
|
function version() {
|
|
4059
4185
|
const config = loadConfig();
|
|
4060
4186
|
const name = getRepoName();
|
|
4061
4187
|
const lastInfo = getLastVersionInfo(name, config);
|
|
4062
4188
|
const lastVersion = lastInfo?.version ?? null;
|
|
4063
4189
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
4064
|
-
console.log(`${
|
|
4065
|
-
console.log(`${
|
|
4066
|
-
console.log(`${
|
|
4190
|
+
console.log(`${chalk44.bold("name:")} ${name}`);
|
|
4191
|
+
console.log(`${chalk44.bold("last:")} ${lastVersion ?? chalk44.dim("none")}`);
|
|
4192
|
+
console.log(`${chalk44.bold("next:")} ${nextVersion ?? chalk44.dim("none")}`);
|
|
4067
4193
|
}
|
|
4068
4194
|
|
|
4069
4195
|
// src/commands/registerDevlog.ts
|
|
@@ -4077,6 +4203,11 @@ function registerDevlog(program2) {
|
|
|
4077
4203
|
devlogCommand.command("version").description("Show current repo name and version info").action(version);
|
|
4078
4204
|
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);
|
|
4079
4205
|
devlogCommand.command("skip <date>").description("Add a date (YYYY-MM-DD) to the skip list").action(skip);
|
|
4206
|
+
devlogCommand.command("repos").description("Show repos missing devlog entries").option(
|
|
4207
|
+
"--days <number>",
|
|
4208
|
+
"Only show repos pushed within N days (default: 30)",
|
|
4209
|
+
Number.parseInt
|
|
4210
|
+
).option("--all", "Show all non-archived repos regardless of push date").action(repos);
|
|
4080
4211
|
}
|
|
4081
4212
|
|
|
4082
4213
|
// src/commands/netframework/buildTree.ts
|
|
@@ -4175,30 +4306,30 @@ function escapeRegex(s) {
|
|
|
4175
4306
|
}
|
|
4176
4307
|
|
|
4177
4308
|
// src/commands/netframework/printTree.ts
|
|
4178
|
-
import
|
|
4309
|
+
import chalk45 from "chalk";
|
|
4179
4310
|
function printNodes(nodes, prefix2) {
|
|
4180
4311
|
for (let i = 0; i < nodes.length; i++) {
|
|
4181
4312
|
const isLast = i === nodes.length - 1;
|
|
4182
4313
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
4183
4314
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
4184
4315
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
4185
|
-
const label2 = isMissing ?
|
|
4316
|
+
const label2 = isMissing ? chalk45.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
4186
4317
|
console.log(`${prefix2}${connector}${label2}`);
|
|
4187
4318
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
4188
4319
|
}
|
|
4189
4320
|
}
|
|
4190
4321
|
function printTree(tree, totalCount, solutions) {
|
|
4191
|
-
console.log(
|
|
4192
|
-
console.log(
|
|
4322
|
+
console.log(chalk45.bold("\nProject Dependency Tree"));
|
|
4323
|
+
console.log(chalk45.cyan(tree.relativePath));
|
|
4193
4324
|
printNodes(tree.children, "");
|
|
4194
|
-
console.log(
|
|
4325
|
+
console.log(chalk45.dim(`
|
|
4195
4326
|
${totalCount} projects total (including root)`));
|
|
4196
|
-
console.log(
|
|
4327
|
+
console.log(chalk45.bold("\nSolution Membership"));
|
|
4197
4328
|
if (solutions.length === 0) {
|
|
4198
|
-
console.log(
|
|
4329
|
+
console.log(chalk45.yellow(" Not found in any .sln"));
|
|
4199
4330
|
} else {
|
|
4200
4331
|
for (const sln of solutions) {
|
|
4201
|
-
console.log(` ${
|
|
4332
|
+
console.log(` ${chalk45.green(sln)}`);
|
|
4202
4333
|
}
|
|
4203
4334
|
}
|
|
4204
4335
|
console.log();
|
|
@@ -4227,7 +4358,7 @@ function printJson(tree, totalCount, solutions) {
|
|
|
4227
4358
|
// src/commands/netframework/resolveCsproj.ts
|
|
4228
4359
|
import { existsSync as existsSync21 } from "fs";
|
|
4229
4360
|
import path20 from "path";
|
|
4230
|
-
import
|
|
4361
|
+
import chalk46 from "chalk";
|
|
4231
4362
|
|
|
4232
4363
|
// src/commands/netframework/findRepoRoot.ts
|
|
4233
4364
|
import { existsSync as existsSync20 } from "fs";
|
|
@@ -4247,12 +4378,12 @@ function findRepoRoot(dir) {
|
|
|
4247
4378
|
function resolveCsproj(csprojPath) {
|
|
4248
4379
|
const resolved = path20.resolve(csprojPath);
|
|
4249
4380
|
if (!existsSync21(resolved)) {
|
|
4250
|
-
console.error(
|
|
4381
|
+
console.error(chalk46.red(`File not found: ${resolved}`));
|
|
4251
4382
|
process.exit(1);
|
|
4252
4383
|
}
|
|
4253
4384
|
const repoRoot = findRepoRoot(path20.dirname(resolved));
|
|
4254
4385
|
if (!repoRoot) {
|
|
4255
|
-
console.error(
|
|
4386
|
+
console.error(chalk46.red("Could not find git repository root"));
|
|
4256
4387
|
process.exit(1);
|
|
4257
4388
|
}
|
|
4258
4389
|
return { resolved, repoRoot };
|
|
@@ -4272,12 +4403,12 @@ async function deps(csprojPath, options2) {
|
|
|
4272
4403
|
}
|
|
4273
4404
|
|
|
4274
4405
|
// src/commands/netframework/inSln.ts
|
|
4275
|
-
import
|
|
4406
|
+
import chalk47 from "chalk";
|
|
4276
4407
|
async function inSln(csprojPath) {
|
|
4277
4408
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
4278
4409
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
4279
4410
|
if (solutions.length === 0) {
|
|
4280
|
-
console.log(
|
|
4411
|
+
console.log(chalk47.yellow("Not found in any .sln file"));
|
|
4281
4412
|
process.exit(1);
|
|
4282
4413
|
}
|
|
4283
4414
|
for (const sln of solutions) {
|
|
@@ -4294,12 +4425,12 @@ function registerNetframework(program2) {
|
|
|
4294
4425
|
|
|
4295
4426
|
// src/commands/prs/comment.ts
|
|
4296
4427
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
4297
|
-
import { unlinkSync as unlinkSync3, writeFileSync as
|
|
4428
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync16 } from "fs";
|
|
4298
4429
|
import { tmpdir as tmpdir2 } from "os";
|
|
4299
|
-
import { join as
|
|
4430
|
+
import { join as join16 } from "path";
|
|
4300
4431
|
|
|
4301
4432
|
// src/commands/prs/shared.ts
|
|
4302
|
-
import { execSync as
|
|
4433
|
+
import { execSync as execSync20 } from "child_process";
|
|
4303
4434
|
function isGhNotInstalled(error) {
|
|
4304
4435
|
if (error instanceof Error) {
|
|
4305
4436
|
const msg = error.message.toLowerCase();
|
|
@@ -4315,14 +4446,14 @@ function isNotFound(error) {
|
|
|
4315
4446
|
}
|
|
4316
4447
|
function getRepoInfo() {
|
|
4317
4448
|
const repoInfo = JSON.parse(
|
|
4318
|
-
|
|
4449
|
+
execSync20("gh repo view --json owner,name", { encoding: "utf-8" })
|
|
4319
4450
|
);
|
|
4320
4451
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
4321
4452
|
}
|
|
4322
4453
|
function getCurrentPrNumber() {
|
|
4323
4454
|
try {
|
|
4324
4455
|
const prInfo = JSON.parse(
|
|
4325
|
-
|
|
4456
|
+
execSync20("gh pr view --json number", { encoding: "utf-8" })
|
|
4326
4457
|
);
|
|
4327
4458
|
return prInfo.number;
|
|
4328
4459
|
} catch (error) {
|
|
@@ -4336,7 +4467,7 @@ function getCurrentPrNumber() {
|
|
|
4336
4467
|
function getCurrentPrNodeId() {
|
|
4337
4468
|
try {
|
|
4338
4469
|
const prInfo = JSON.parse(
|
|
4339
|
-
|
|
4470
|
+
execSync20("gh pr view --json id", { encoding: "utf-8" })
|
|
4340
4471
|
);
|
|
4341
4472
|
return prInfo.id;
|
|
4342
4473
|
} catch (error) {
|
|
@@ -4368,8 +4499,8 @@ function comment(path35, line, body) {
|
|
|
4368
4499
|
validateLine(line);
|
|
4369
4500
|
try {
|
|
4370
4501
|
const prId = getCurrentPrNodeId();
|
|
4371
|
-
const queryFile =
|
|
4372
|
-
|
|
4502
|
+
const queryFile = join16(tmpdir2(), `gh-query-${Date.now()}.graphql`);
|
|
4503
|
+
writeFileSync16(queryFile, MUTATION);
|
|
4373
4504
|
try {
|
|
4374
4505
|
const result = spawnSync2(
|
|
4375
4506
|
"gh",
|
|
@@ -4407,20 +4538,20 @@ function comment(path35, line, body) {
|
|
|
4407
4538
|
}
|
|
4408
4539
|
|
|
4409
4540
|
// src/commands/prs/fixed.ts
|
|
4410
|
-
import { execSync as
|
|
4541
|
+
import { execSync as execSync22 } from "child_process";
|
|
4411
4542
|
|
|
4412
4543
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
4413
|
-
import { execSync as
|
|
4414
|
-
import { unlinkSync as unlinkSync5, writeFileSync as
|
|
4544
|
+
import { execSync as execSync21 } from "child_process";
|
|
4545
|
+
import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync17 } from "fs";
|
|
4415
4546
|
import { tmpdir as tmpdir3 } from "os";
|
|
4416
|
-
import { join as
|
|
4547
|
+
import { join as join18 } from "path";
|
|
4417
4548
|
|
|
4418
4549
|
// src/commands/prs/loadCommentsCache.ts
|
|
4419
4550
|
import { existsSync as existsSync22, readFileSync as readFileSync20, unlinkSync as unlinkSync4 } from "fs";
|
|
4420
|
-
import { join as
|
|
4551
|
+
import { join as join17 } from "path";
|
|
4421
4552
|
import { parse as parse2 } from "yaml";
|
|
4422
4553
|
function getCachePath(prNumber) {
|
|
4423
|
-
return
|
|
4554
|
+
return join17(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
4424
4555
|
}
|
|
4425
4556
|
function loadCommentsCache(prNumber) {
|
|
4426
4557
|
const cachePath = getCachePath(prNumber);
|
|
@@ -4440,17 +4571,17 @@ function deleteCommentsCache(prNumber) {
|
|
|
4440
4571
|
|
|
4441
4572
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
4442
4573
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
4443
|
-
|
|
4574
|
+
execSync21(
|
|
4444
4575
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
|
|
4445
4576
|
{ stdio: "inherit" }
|
|
4446
4577
|
);
|
|
4447
4578
|
}
|
|
4448
4579
|
function resolveThread(threadId) {
|
|
4449
4580
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
4450
|
-
const queryFile =
|
|
4451
|
-
|
|
4581
|
+
const queryFile = join18(tmpdir3(), `gh-mutation-${Date.now()}.graphql`);
|
|
4582
|
+
writeFileSync17(queryFile, mutation);
|
|
4452
4583
|
try {
|
|
4453
|
-
|
|
4584
|
+
execSync21(
|
|
4454
4585
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
4455
4586
|
{ stdio: "inherit" }
|
|
4456
4587
|
);
|
|
@@ -4502,7 +4633,7 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
4502
4633
|
// src/commands/prs/fixed.ts
|
|
4503
4634
|
function verifySha(sha) {
|
|
4504
4635
|
try {
|
|
4505
|
-
return
|
|
4636
|
+
return execSync22(`git rev-parse --verify ${sha}`, {
|
|
4506
4637
|
encoding: "utf-8"
|
|
4507
4638
|
}).trim();
|
|
4508
4639
|
} catch {
|
|
@@ -4528,21 +4659,21 @@ function fixed(commentId, sha) {
|
|
|
4528
4659
|
}
|
|
4529
4660
|
|
|
4530
4661
|
// src/commands/prs/listComments/index.ts
|
|
4531
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync5, writeFileSync as
|
|
4532
|
-
import { join as
|
|
4662
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync5, writeFileSync as writeFileSync19 } from "fs";
|
|
4663
|
+
import { join as join20 } from "path";
|
|
4533
4664
|
import { stringify } from "yaml";
|
|
4534
4665
|
|
|
4535
4666
|
// src/commands/prs/fetchThreadIds.ts
|
|
4536
|
-
import { execSync as
|
|
4537
|
-
import { unlinkSync as unlinkSync6, writeFileSync as
|
|
4667
|
+
import { execSync as execSync23 } from "child_process";
|
|
4668
|
+
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync18 } from "fs";
|
|
4538
4669
|
import { tmpdir as tmpdir4 } from "os";
|
|
4539
|
-
import { join as
|
|
4670
|
+
import { join as join19 } from "path";
|
|
4540
4671
|
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 } } } } } } }`;
|
|
4541
4672
|
function fetchThreadIds(org, repo, prNumber) {
|
|
4542
|
-
const queryFile =
|
|
4543
|
-
|
|
4673
|
+
const queryFile = join19(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
4674
|
+
writeFileSync18(queryFile, THREAD_QUERY);
|
|
4544
4675
|
try {
|
|
4545
|
-
const result =
|
|
4676
|
+
const result = execSync23(
|
|
4546
4677
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
4547
4678
|
{ encoding: "utf-8" }
|
|
4548
4679
|
);
|
|
@@ -4564,9 +4695,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
4564
4695
|
}
|
|
4565
4696
|
|
|
4566
4697
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
4567
|
-
import { execSync as
|
|
4698
|
+
import { execSync as execSync24 } from "child_process";
|
|
4568
4699
|
function fetchJson(endpoint) {
|
|
4569
|
-
const result =
|
|
4700
|
+
const result = execSync24(`gh api --paginate ${endpoint}`, {
|
|
4570
4701
|
encoding: "utf-8"
|
|
4571
4702
|
});
|
|
4572
4703
|
if (!result.trim()) return [];
|
|
@@ -4608,20 +4739,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
4608
4739
|
}
|
|
4609
4740
|
|
|
4610
4741
|
// src/commands/prs/listComments/printComments.ts
|
|
4611
|
-
import
|
|
4742
|
+
import chalk48 from "chalk";
|
|
4612
4743
|
function formatForHuman(comment2) {
|
|
4613
4744
|
if (comment2.type === "review") {
|
|
4614
|
-
const stateColor = comment2.state === "APPROVED" ?
|
|
4745
|
+
const stateColor = comment2.state === "APPROVED" ? chalk48.green : comment2.state === "CHANGES_REQUESTED" ? chalk48.red : chalk48.yellow;
|
|
4615
4746
|
return [
|
|
4616
|
-
`${
|
|
4747
|
+
`${chalk48.cyan("Review")} by ${chalk48.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
4617
4748
|
comment2.body,
|
|
4618
4749
|
""
|
|
4619
4750
|
].join("\n");
|
|
4620
4751
|
}
|
|
4621
4752
|
const location = comment2.line ? `:${comment2.line}` : "";
|
|
4622
4753
|
return [
|
|
4623
|
-
`${
|
|
4624
|
-
|
|
4754
|
+
`${chalk48.cyan("Line comment")} by ${chalk48.bold(comment2.user)} on ${chalk48.dim(`${comment2.path}${location}`)}`,
|
|
4755
|
+
chalk48.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
4625
4756
|
comment2.body,
|
|
4626
4757
|
""
|
|
4627
4758
|
].join("\n");
|
|
@@ -4653,7 +4784,7 @@ function printComments(result) {
|
|
|
4653
4784
|
|
|
4654
4785
|
// src/commands/prs/listComments/index.ts
|
|
4655
4786
|
function writeCommentsCache(prNumber, comments) {
|
|
4656
|
-
const assistDir =
|
|
4787
|
+
const assistDir = join20(process.cwd(), ".assist");
|
|
4657
4788
|
if (!existsSync23(assistDir)) {
|
|
4658
4789
|
mkdirSync5(assistDir, { recursive: true });
|
|
4659
4790
|
}
|
|
@@ -4662,8 +4793,8 @@ function writeCommentsCache(prNumber, comments) {
|
|
|
4662
4793
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4663
4794
|
comments
|
|
4664
4795
|
};
|
|
4665
|
-
const cachePath =
|
|
4666
|
-
|
|
4796
|
+
const cachePath = join20(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
4797
|
+
writeFileSync19(cachePath, stringify(cacheData));
|
|
4667
4798
|
}
|
|
4668
4799
|
function handleKnownErrors(error) {
|
|
4669
4800
|
if (isGhNotInstalled(error)) {
|
|
@@ -4695,7 +4826,7 @@ async function listComments() {
|
|
|
4695
4826
|
];
|
|
4696
4827
|
updateCache(prNumber, allComments);
|
|
4697
4828
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
4698
|
-
const cachePath = hasLineComments ?
|
|
4829
|
+
const cachePath = hasLineComments ? join20(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
4699
4830
|
return { comments: allComments, cachePath };
|
|
4700
4831
|
} catch (error) {
|
|
4701
4832
|
const handled = handleKnownErrors(error);
|
|
@@ -4705,37 +4836,37 @@ async function listComments() {
|
|
|
4705
4836
|
}
|
|
4706
4837
|
|
|
4707
4838
|
// src/commands/prs/prs/index.ts
|
|
4708
|
-
import { execSync as
|
|
4839
|
+
import { execSync as execSync25 } from "child_process";
|
|
4709
4840
|
|
|
4710
4841
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
4711
4842
|
import enquirer5 from "enquirer";
|
|
4712
4843
|
|
|
4713
4844
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
4714
|
-
import
|
|
4845
|
+
import chalk49 from "chalk";
|
|
4715
4846
|
var STATUS_MAP = {
|
|
4716
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
4717
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
4847
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk49.magenta("merged"), date: pr.mergedAt } : null,
|
|
4848
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk49.red("closed"), date: pr.closedAt } : null
|
|
4718
4849
|
};
|
|
4719
4850
|
function defaultStatus(pr) {
|
|
4720
|
-
return { label:
|
|
4851
|
+
return { label: chalk49.green("opened"), date: pr.createdAt };
|
|
4721
4852
|
}
|
|
4722
|
-
function
|
|
4853
|
+
function getStatus2(pr) {
|
|
4723
4854
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
4724
4855
|
}
|
|
4725
4856
|
function formatDate(dateStr) {
|
|
4726
4857
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
4727
4858
|
}
|
|
4728
4859
|
function formatPrHeader(pr, status2) {
|
|
4729
|
-
return `${
|
|
4860
|
+
return `${chalk49.cyan(`#${pr.number}`)} ${pr.title} ${chalk49.dim(`(${pr.author.login},`)} ${status2.label} ${chalk49.dim(`${formatDate(status2.date)})`)}`;
|
|
4730
4861
|
}
|
|
4731
4862
|
function logPrDetails(pr) {
|
|
4732
4863
|
console.log(
|
|
4733
|
-
|
|
4864
|
+
chalk49.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
4734
4865
|
);
|
|
4735
4866
|
console.log();
|
|
4736
4867
|
}
|
|
4737
4868
|
function printPr(pr) {
|
|
4738
|
-
console.log(formatPrHeader(pr,
|
|
4869
|
+
console.log(formatPrHeader(pr, getStatus2(pr)));
|
|
4739
4870
|
logPrDetails(pr);
|
|
4740
4871
|
}
|
|
4741
4872
|
|
|
@@ -4811,7 +4942,7 @@ async function displayPaginated(pullRequests) {
|
|
|
4811
4942
|
async function prs(options2) {
|
|
4812
4943
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
4813
4944
|
try {
|
|
4814
|
-
const result =
|
|
4945
|
+
const result = execSync25(
|
|
4815
4946
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
|
|
4816
4947
|
{ encoding: "utf-8" }
|
|
4817
4948
|
);
|
|
@@ -4834,7 +4965,7 @@ async function prs(options2) {
|
|
|
4834
4965
|
}
|
|
4835
4966
|
|
|
4836
4967
|
// src/commands/prs/wontfix.ts
|
|
4837
|
-
import { execSync as
|
|
4968
|
+
import { execSync as execSync26 } from "child_process";
|
|
4838
4969
|
function validateReason(reason) {
|
|
4839
4970
|
const lowerReason = reason.toLowerCase();
|
|
4840
4971
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -4851,7 +4982,7 @@ function validateShaReferences(reason) {
|
|
|
4851
4982
|
const invalidShas = [];
|
|
4852
4983
|
for (const sha of shas) {
|
|
4853
4984
|
try {
|
|
4854
|
-
|
|
4985
|
+
execSync26(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
4855
4986
|
} catch {
|
|
4856
4987
|
invalidShas.push(sha);
|
|
4857
4988
|
}
|
|
@@ -4900,7 +5031,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
4900
5031
|
import * as path21 from "path";
|
|
4901
5032
|
|
|
4902
5033
|
// src/commands/refactor/logViolations.ts
|
|
4903
|
-
import
|
|
5034
|
+
import chalk50 from "chalk";
|
|
4904
5035
|
var DEFAULT_MAX_LINES = 100;
|
|
4905
5036
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
4906
5037
|
if (violations.length === 0) {
|
|
@@ -4909,43 +5040,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
4909
5040
|
}
|
|
4910
5041
|
return;
|
|
4911
5042
|
}
|
|
4912
|
-
console.error(
|
|
5043
|
+
console.error(chalk50.red(`
|
|
4913
5044
|
Refactor check failed:
|
|
4914
5045
|
`));
|
|
4915
|
-
console.error(
|
|
5046
|
+
console.error(chalk50.red(` The following files exceed ${maxLines} lines:
|
|
4916
5047
|
`));
|
|
4917
5048
|
for (const violation of violations) {
|
|
4918
|
-
console.error(
|
|
5049
|
+
console.error(chalk50.red(` ${violation.file} (${violation.lines} lines)`));
|
|
4919
5050
|
}
|
|
4920
5051
|
console.error(
|
|
4921
|
-
|
|
5052
|
+
chalk50.yellow(
|
|
4922
5053
|
`
|
|
4923
5054
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
4924
5055
|
way to refactor it, ignore it with:
|
|
4925
5056
|
`
|
|
4926
5057
|
)
|
|
4927
5058
|
);
|
|
4928
|
-
console.error(
|
|
5059
|
+
console.error(chalk50.gray(` assist refactor ignore <file>
|
|
4929
5060
|
`));
|
|
4930
5061
|
if (process.env.CLAUDECODE) {
|
|
4931
|
-
console.error(
|
|
5062
|
+
console.error(chalk50.cyan(`
|
|
4932
5063
|
## Extracting Code to New Files
|
|
4933
5064
|
`));
|
|
4934
5065
|
console.error(
|
|
4935
|
-
|
|
5066
|
+
chalk50.cyan(
|
|
4936
5067
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
4937
5068
|
`
|
|
4938
5069
|
)
|
|
4939
5070
|
);
|
|
4940
5071
|
console.error(
|
|
4941
|
-
|
|
5072
|
+
chalk50.cyan(
|
|
4942
5073
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
4943
5074
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
4944
5075
|
`
|
|
4945
5076
|
)
|
|
4946
5077
|
);
|
|
4947
5078
|
console.error(
|
|
4948
|
-
|
|
5079
|
+
chalk50.cyan(
|
|
4949
5080
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
4950
5081
|
domains, move it to a common/shared folder.
|
|
4951
5082
|
`
|
|
@@ -4955,7 +5086,7 @@ Refactor check failed:
|
|
|
4955
5086
|
}
|
|
4956
5087
|
|
|
4957
5088
|
// src/commands/refactor/check/getViolations/index.ts
|
|
4958
|
-
import { execSync as
|
|
5089
|
+
import { execSync as execSync27 } from "child_process";
|
|
4959
5090
|
import fs15 from "fs";
|
|
4960
5091
|
import { minimatch as minimatch4 } from "minimatch";
|
|
4961
5092
|
|
|
@@ -5005,7 +5136,7 @@ function getGitFiles(options2) {
|
|
|
5005
5136
|
}
|
|
5006
5137
|
const files = /* @__PURE__ */ new Set();
|
|
5007
5138
|
if (options2.staged || options2.modified) {
|
|
5008
|
-
const staged =
|
|
5139
|
+
const staged = execSync27("git diff --cached --name-only", {
|
|
5009
5140
|
encoding: "utf-8"
|
|
5010
5141
|
});
|
|
5011
5142
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -5013,7 +5144,7 @@ function getGitFiles(options2) {
|
|
|
5013
5144
|
}
|
|
5014
5145
|
}
|
|
5015
5146
|
if (options2.unstaged || options2.modified) {
|
|
5016
|
-
const unstaged =
|
|
5147
|
+
const unstaged = execSync27("git diff --name-only", { encoding: "utf-8" });
|
|
5017
5148
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
5018
5149
|
files.add(file);
|
|
5019
5150
|
}
|
|
@@ -5101,11 +5232,11 @@ async function check(pattern2, options2) {
|
|
|
5101
5232
|
|
|
5102
5233
|
// src/commands/refactor/ignore.ts
|
|
5103
5234
|
import fs16 from "fs";
|
|
5104
|
-
import
|
|
5235
|
+
import chalk51 from "chalk";
|
|
5105
5236
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
5106
5237
|
function ignore(file) {
|
|
5107
5238
|
if (!fs16.existsSync(file)) {
|
|
5108
|
-
console.error(
|
|
5239
|
+
console.error(chalk51.red(`Error: File does not exist: ${file}`));
|
|
5109
5240
|
process.exit(1);
|
|
5110
5241
|
}
|
|
5111
5242
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -5121,7 +5252,7 @@ function ignore(file) {
|
|
|
5121
5252
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
5122
5253
|
}
|
|
5123
5254
|
console.log(
|
|
5124
|
-
|
|
5255
|
+
chalk51.green(
|
|
5125
5256
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
5126
5257
|
)
|
|
5127
5258
|
);
|
|
@@ -5129,7 +5260,7 @@ function ignore(file) {
|
|
|
5129
5260
|
|
|
5130
5261
|
// src/commands/refactor/restructure/index.ts
|
|
5131
5262
|
import path30 from "path";
|
|
5132
|
-
import
|
|
5263
|
+
import chalk54 from "chalk";
|
|
5133
5264
|
|
|
5134
5265
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
5135
5266
|
import path22 from "path";
|
|
@@ -5372,50 +5503,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
5372
5503
|
|
|
5373
5504
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
5374
5505
|
import path26 from "path";
|
|
5375
|
-
import
|
|
5506
|
+
import chalk52 from "chalk";
|
|
5376
5507
|
function relPath(filePath) {
|
|
5377
5508
|
return path26.relative(process.cwd(), filePath);
|
|
5378
5509
|
}
|
|
5379
5510
|
function displayMoves(plan) {
|
|
5380
5511
|
if (plan.moves.length === 0) return;
|
|
5381
|
-
console.log(
|
|
5512
|
+
console.log(chalk52.bold("\nFile moves:"));
|
|
5382
5513
|
for (const move of plan.moves) {
|
|
5383
5514
|
console.log(
|
|
5384
|
-
` ${
|
|
5515
|
+
` ${chalk52.red(relPath(move.from))} \u2192 ${chalk52.green(relPath(move.to))}`
|
|
5385
5516
|
);
|
|
5386
|
-
console.log(
|
|
5517
|
+
console.log(chalk52.dim(` ${move.reason}`));
|
|
5387
5518
|
}
|
|
5388
5519
|
}
|
|
5389
5520
|
function displayRewrites(rewrites) {
|
|
5390
5521
|
if (rewrites.length === 0) return;
|
|
5391
5522
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
5392
|
-
console.log(
|
|
5523
|
+
console.log(chalk52.bold(`
|
|
5393
5524
|
Import rewrites (${affectedFiles.size} files):`));
|
|
5394
5525
|
for (const file of affectedFiles) {
|
|
5395
|
-
console.log(` ${
|
|
5526
|
+
console.log(` ${chalk52.cyan(relPath(file))}:`);
|
|
5396
5527
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
5397
5528
|
(r) => r.file === file
|
|
5398
5529
|
)) {
|
|
5399
5530
|
console.log(
|
|
5400
|
-
` ${
|
|
5531
|
+
` ${chalk52.red(`"${oldSpecifier}"`)} \u2192 ${chalk52.green(`"${newSpecifier}"`)}`
|
|
5401
5532
|
);
|
|
5402
5533
|
}
|
|
5403
5534
|
}
|
|
5404
5535
|
}
|
|
5405
5536
|
function displayPlan(plan) {
|
|
5406
5537
|
if (plan.warnings.length > 0) {
|
|
5407
|
-
console.log(
|
|
5408
|
-
for (const w of plan.warnings) console.log(
|
|
5538
|
+
console.log(chalk52.yellow("\nWarnings:"));
|
|
5539
|
+
for (const w of plan.warnings) console.log(chalk52.yellow(` ${w}`));
|
|
5409
5540
|
}
|
|
5410
5541
|
if (plan.newDirectories.length > 0) {
|
|
5411
|
-
console.log(
|
|
5542
|
+
console.log(chalk52.bold("\nNew directories:"));
|
|
5412
5543
|
for (const dir of plan.newDirectories)
|
|
5413
|
-
console.log(
|
|
5544
|
+
console.log(chalk52.green(` ${dir}/`));
|
|
5414
5545
|
}
|
|
5415
5546
|
displayMoves(plan);
|
|
5416
5547
|
displayRewrites(plan.rewrites);
|
|
5417
5548
|
console.log(
|
|
5418
|
-
|
|
5549
|
+
chalk52.dim(
|
|
5419
5550
|
`
|
|
5420
5551
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
5421
5552
|
)
|
|
@@ -5425,18 +5556,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
5425
5556
|
// src/commands/refactor/restructure/executePlan.ts
|
|
5426
5557
|
import fs18 from "fs";
|
|
5427
5558
|
import path27 from "path";
|
|
5428
|
-
import
|
|
5559
|
+
import chalk53 from "chalk";
|
|
5429
5560
|
function executePlan(plan) {
|
|
5430
5561
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
5431
5562
|
for (const [file, content] of updatedContents) {
|
|
5432
5563
|
fs18.writeFileSync(file, content, "utf-8");
|
|
5433
5564
|
console.log(
|
|
5434
|
-
|
|
5565
|
+
chalk53.cyan(` Rewrote imports in ${path27.relative(process.cwd(), file)}`)
|
|
5435
5566
|
);
|
|
5436
5567
|
}
|
|
5437
5568
|
for (const dir of plan.newDirectories) {
|
|
5438
5569
|
fs18.mkdirSync(dir, { recursive: true });
|
|
5439
|
-
console.log(
|
|
5570
|
+
console.log(chalk53.green(` Created ${path27.relative(process.cwd(), dir)}/`));
|
|
5440
5571
|
}
|
|
5441
5572
|
for (const move of plan.moves) {
|
|
5442
5573
|
const targetDir = path27.dirname(move.to);
|
|
@@ -5445,7 +5576,7 @@ function executePlan(plan) {
|
|
|
5445
5576
|
}
|
|
5446
5577
|
fs18.renameSync(move.from, move.to);
|
|
5447
5578
|
console.log(
|
|
5448
|
-
|
|
5579
|
+
chalk53.white(
|
|
5449
5580
|
` Moved ${path27.relative(process.cwd(), move.from)} \u2192 ${path27.relative(process.cwd(), move.to)}`
|
|
5450
5581
|
)
|
|
5451
5582
|
);
|
|
@@ -5460,7 +5591,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
5460
5591
|
if (entries.length === 0) {
|
|
5461
5592
|
fs18.rmdirSync(dir);
|
|
5462
5593
|
console.log(
|
|
5463
|
-
|
|
5594
|
+
chalk53.dim(
|
|
5464
5595
|
` Removed empty directory ${path27.relative(process.cwd(), dir)}`
|
|
5465
5596
|
)
|
|
5466
5597
|
);
|
|
@@ -5591,22 +5722,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
5591
5722
|
const targetPattern = pattern2 ?? "src";
|
|
5592
5723
|
const files = findSourceFiles2(targetPattern);
|
|
5593
5724
|
if (files.length === 0) {
|
|
5594
|
-
console.log(
|
|
5725
|
+
console.log(chalk54.yellow("No files found matching pattern"));
|
|
5595
5726
|
return;
|
|
5596
5727
|
}
|
|
5597
5728
|
const tsConfigPath = path30.resolve("tsconfig.json");
|
|
5598
5729
|
const plan = buildPlan(files, tsConfigPath);
|
|
5599
5730
|
if (plan.moves.length === 0) {
|
|
5600
|
-
console.log(
|
|
5731
|
+
console.log(chalk54.green("No restructuring needed"));
|
|
5601
5732
|
return;
|
|
5602
5733
|
}
|
|
5603
5734
|
displayPlan(plan);
|
|
5604
5735
|
if (options2.apply) {
|
|
5605
|
-
console.log(
|
|
5736
|
+
console.log(chalk54.bold("\nApplying changes..."));
|
|
5606
5737
|
executePlan(plan);
|
|
5607
|
-
console.log(
|
|
5738
|
+
console.log(chalk54.green("\nRestructuring complete"));
|
|
5608
5739
|
} else {
|
|
5609
|
-
console.log(
|
|
5740
|
+
console.log(chalk54.dim("\nDry run. Use --apply to execute."));
|
|
5610
5741
|
}
|
|
5611
5742
|
}
|
|
5612
5743
|
|
|
@@ -5630,7 +5761,7 @@ function registerRefactor(program2) {
|
|
|
5630
5761
|
|
|
5631
5762
|
// src/commands/transcript/shared.ts
|
|
5632
5763
|
import { existsSync as existsSync24, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
|
|
5633
|
-
import { basename as basename4, join as
|
|
5764
|
+
import { basename as basename4, join as join21, relative } from "path";
|
|
5634
5765
|
import * as readline2 from "readline";
|
|
5635
5766
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
5636
5767
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -5648,7 +5779,7 @@ function collectFiles(dir, extension) {
|
|
|
5648
5779
|
if (!existsSync24(dir)) return [];
|
|
5649
5780
|
const results = [];
|
|
5650
5781
|
for (const entry of readdirSync3(dir)) {
|
|
5651
|
-
const fullPath =
|
|
5782
|
+
const fullPath = join21(dir, entry);
|
|
5652
5783
|
if (statSync2(fullPath).isDirectory()) {
|
|
5653
5784
|
results.push(...collectFiles(fullPath, extension));
|
|
5654
5785
|
} else if (entry.endsWith(extension)) {
|
|
@@ -5745,11 +5876,11 @@ async function configure() {
|
|
|
5745
5876
|
import { existsSync as existsSync26 } from "fs";
|
|
5746
5877
|
|
|
5747
5878
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
5748
|
-
import { dirname as dirname15, join as
|
|
5879
|
+
import { dirname as dirname15, join as join23 } from "path";
|
|
5749
5880
|
|
|
5750
5881
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
5751
5882
|
import { renameSync } from "fs";
|
|
5752
|
-
import { join as
|
|
5883
|
+
import { join as join22 } from "path";
|
|
5753
5884
|
async function resolveDate(rl, choice) {
|
|
5754
5885
|
if (choice === "1") return getDatePrefix(0);
|
|
5755
5886
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -5764,7 +5895,7 @@ async function resolveDate(rl, choice) {
|
|
|
5764
5895
|
}
|
|
5765
5896
|
function renameWithPrefix(vttDir, vttFile, prefix2) {
|
|
5766
5897
|
const newFilename = `${prefix2}.${vttFile}`;
|
|
5767
|
-
renameSync(
|
|
5898
|
+
renameSync(join22(vttDir, vttFile), join22(vttDir, newFilename));
|
|
5768
5899
|
console.log(`Renamed to: ${newFilename}`);
|
|
5769
5900
|
return newFilename;
|
|
5770
5901
|
}
|
|
@@ -5798,12 +5929,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
5798
5929
|
const vttFileDir = dirname15(vttFile.absolutePath);
|
|
5799
5930
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
5800
5931
|
if (newFilename) {
|
|
5801
|
-
const newRelativePath =
|
|
5932
|
+
const newRelativePath = join23(
|
|
5802
5933
|
dirname15(vttFile.relativePath),
|
|
5803
5934
|
newFilename
|
|
5804
5935
|
);
|
|
5805
5936
|
vttFiles[i] = {
|
|
5806
|
-
absolutePath:
|
|
5937
|
+
absolutePath: join23(vttFileDir, newFilename),
|
|
5807
5938
|
relativePath: newRelativePath,
|
|
5808
5939
|
filename: newFilename
|
|
5809
5940
|
};
|
|
@@ -5816,8 +5947,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
5816
5947
|
}
|
|
5817
5948
|
|
|
5818
5949
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
5819
|
-
import { existsSync as existsSync25, mkdirSync as mkdirSync6, readFileSync as readFileSync21, writeFileSync as
|
|
5820
|
-
import { basename as basename5, dirname as dirname16, join as
|
|
5950
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync6, readFileSync as readFileSync21, writeFileSync as writeFileSync20 } from "fs";
|
|
5951
|
+
import { basename as basename5, dirname as dirname16, join as join24 } from "path";
|
|
5821
5952
|
|
|
5822
5953
|
// src/commands/transcript/cleanText.ts
|
|
5823
5954
|
function cleanText(text) {
|
|
@@ -6027,17 +6158,17 @@ function toMdFilename(vttFilename) {
|
|
|
6027
6158
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
6028
6159
|
}
|
|
6029
6160
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
6030
|
-
return relativeDir === "." ? transcriptsDir :
|
|
6161
|
+
return relativeDir === "." ? transcriptsDir : join24(transcriptsDir, relativeDir);
|
|
6031
6162
|
}
|
|
6032
6163
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
6033
6164
|
const mdFile = toMdFilename(vttFile.filename);
|
|
6034
6165
|
const relativeDir = dirname16(vttFile.relativePath);
|
|
6035
6166
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
6036
|
-
const outputPath =
|
|
6167
|
+
const outputPath = join24(outputDir, mdFile);
|
|
6037
6168
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
6038
6169
|
}
|
|
6039
6170
|
function logSkipped(relativeDir, mdFile) {
|
|
6040
|
-
console.log(`Skipping (already exists): ${
|
|
6171
|
+
console.log(`Skipping (already exists): ${join24(relativeDir, mdFile)}`);
|
|
6041
6172
|
return "skipped";
|
|
6042
6173
|
}
|
|
6043
6174
|
function ensureDirectory(dir, label2) {
|
|
@@ -6067,7 +6198,7 @@ function readAndParseCues(inputPath) {
|
|
|
6067
6198
|
return processCues(readFileSync21(inputPath, "utf-8"));
|
|
6068
6199
|
}
|
|
6069
6200
|
function writeFormatted(outputPath, content) {
|
|
6070
|
-
|
|
6201
|
+
writeFileSync20(outputPath, content, "utf-8");
|
|
6071
6202
|
console.log(`Written: ${outputPath}`);
|
|
6072
6203
|
}
|
|
6073
6204
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -6136,7 +6267,7 @@ async function format() {
|
|
|
6136
6267
|
|
|
6137
6268
|
// src/commands/transcript/summarise/index.ts
|
|
6138
6269
|
import { existsSync as existsSync28 } from "fs";
|
|
6139
|
-
import { basename as basename6, dirname as dirname18, join as
|
|
6270
|
+
import { basename as basename6, dirname as dirname18, join as join26, relative as relative2 } from "path";
|
|
6140
6271
|
|
|
6141
6272
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
6142
6273
|
import {
|
|
@@ -6146,17 +6277,17 @@ import {
|
|
|
6146
6277
|
renameSync as renameSync2,
|
|
6147
6278
|
rmSync
|
|
6148
6279
|
} from "fs";
|
|
6149
|
-
import { dirname as dirname17, join as
|
|
6280
|
+
import { dirname as dirname17, join as join25 } from "path";
|
|
6150
6281
|
|
|
6151
6282
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
6152
|
-
import
|
|
6283
|
+
import chalk55 from "chalk";
|
|
6153
6284
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
6154
6285
|
function validateStagedContent(filename, content) {
|
|
6155
6286
|
const firstLine = content.split("\n")[0];
|
|
6156
6287
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
6157
6288
|
if (!match) {
|
|
6158
6289
|
console.error(
|
|
6159
|
-
|
|
6290
|
+
chalk55.red(
|
|
6160
6291
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
6161
6292
|
)
|
|
6162
6293
|
);
|
|
@@ -6165,7 +6296,7 @@ function validateStagedContent(filename, content) {
|
|
|
6165
6296
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
6166
6297
|
if (!contentAfterLink) {
|
|
6167
6298
|
console.error(
|
|
6168
|
-
|
|
6299
|
+
chalk55.red(
|
|
6169
6300
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
6170
6301
|
)
|
|
6171
6302
|
);
|
|
@@ -6175,7 +6306,7 @@ function validateStagedContent(filename, content) {
|
|
|
6175
6306
|
}
|
|
6176
6307
|
|
|
6177
6308
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
6178
|
-
var STAGING_DIR =
|
|
6309
|
+
var STAGING_DIR = join25(process.cwd(), ".assist", "transcript");
|
|
6179
6310
|
function processStagedFile() {
|
|
6180
6311
|
if (!existsSync27(STAGING_DIR)) {
|
|
6181
6312
|
return false;
|
|
@@ -6199,7 +6330,7 @@ function processStagedFile() {
|
|
|
6199
6330
|
);
|
|
6200
6331
|
process.exit(1);
|
|
6201
6332
|
}
|
|
6202
|
-
const destPath =
|
|
6333
|
+
const destPath = join25(summaryDir, matchingTranscript.relativePath);
|
|
6203
6334
|
const destDir = dirname17(destPath);
|
|
6204
6335
|
if (!existsSync27(destDir)) {
|
|
6205
6336
|
mkdirSync7(destDir, { recursive: true });
|
|
@@ -6215,7 +6346,7 @@ function processStagedFile() {
|
|
|
6215
6346
|
// src/commands/transcript/summarise/index.ts
|
|
6216
6347
|
function buildRelativeKey(relativePath, baseName) {
|
|
6217
6348
|
const relDir = dirname18(relativePath);
|
|
6218
|
-
return relDir === "." ? baseName :
|
|
6349
|
+
return relDir === "." ? baseName : join26(relDir, baseName);
|
|
6219
6350
|
}
|
|
6220
6351
|
function buildSummaryIndex(summaryDir) {
|
|
6221
6352
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -6249,8 +6380,8 @@ function summarise2() {
|
|
|
6249
6380
|
}
|
|
6250
6381
|
const next2 = missing[0];
|
|
6251
6382
|
const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
|
|
6252
|
-
const outputPath =
|
|
6253
|
-
const summaryFileDir =
|
|
6383
|
+
const outputPath = join26(STAGING_DIR, outputFilename);
|
|
6384
|
+
const summaryFileDir = join26(summaryDir, dirname18(next2.relativePath));
|
|
6254
6385
|
const relativeTranscriptPath = encodeURI(
|
|
6255
6386
|
relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
|
|
6256
6387
|
);
|
|
@@ -6296,38 +6427,38 @@ function registerVerify(program2) {
|
|
|
6296
6427
|
|
|
6297
6428
|
// src/commands/voice/devices.ts
|
|
6298
6429
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
6299
|
-
import { join as
|
|
6430
|
+
import { join as join28 } from "path";
|
|
6300
6431
|
|
|
6301
6432
|
// src/commands/voice/shared.ts
|
|
6302
6433
|
import { homedir as homedir6 } from "os";
|
|
6303
|
-
import { dirname as dirname19, join as
|
|
6434
|
+
import { dirname as dirname19, join as join27 } from "path";
|
|
6304
6435
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
6305
6436
|
var __dirname7 = dirname19(fileURLToPath6(import.meta.url));
|
|
6306
|
-
var VOICE_DIR =
|
|
6437
|
+
var VOICE_DIR = join27(homedir6(), ".assist", "voice");
|
|
6307
6438
|
var voicePaths = {
|
|
6308
6439
|
dir: VOICE_DIR,
|
|
6309
|
-
pid:
|
|
6310
|
-
log:
|
|
6311
|
-
venv:
|
|
6312
|
-
lock:
|
|
6440
|
+
pid: join27(VOICE_DIR, "voice.pid"),
|
|
6441
|
+
log: join27(VOICE_DIR, "voice.log"),
|
|
6442
|
+
venv: join27(VOICE_DIR, ".venv"),
|
|
6443
|
+
lock: join27(VOICE_DIR, "voice.lock")
|
|
6313
6444
|
};
|
|
6314
6445
|
function getPythonDir() {
|
|
6315
|
-
return
|
|
6446
|
+
return join27(__dirname7, "commands", "voice", "python");
|
|
6316
6447
|
}
|
|
6317
6448
|
function getVenvPython() {
|
|
6318
|
-
return process.platform === "win32" ?
|
|
6449
|
+
return process.platform === "win32" ? join27(voicePaths.venv, "Scripts", "python.exe") : join27(voicePaths.venv, "bin", "python");
|
|
6319
6450
|
}
|
|
6320
6451
|
function getLockDir() {
|
|
6321
6452
|
const config = loadConfig();
|
|
6322
6453
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
6323
6454
|
}
|
|
6324
6455
|
function getLockFile() {
|
|
6325
|
-
return
|
|
6456
|
+
return join27(getLockDir(), "voice.lock");
|
|
6326
6457
|
}
|
|
6327
6458
|
|
|
6328
6459
|
// src/commands/voice/devices.ts
|
|
6329
6460
|
function devices() {
|
|
6330
|
-
const script =
|
|
6461
|
+
const script = join28(getPythonDir(), "list_devices.py");
|
|
6331
6462
|
spawnSync3(getVenvPython(), [script], { stdio: "inherit" });
|
|
6332
6463
|
}
|
|
6333
6464
|
|
|
@@ -6362,12 +6493,12 @@ function logs(options2) {
|
|
|
6362
6493
|
// src/commands/voice/setup.ts
|
|
6363
6494
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
6364
6495
|
import { mkdirSync as mkdirSync9 } from "fs";
|
|
6365
|
-
import { join as
|
|
6496
|
+
import { join as join30 } from "path";
|
|
6366
6497
|
|
|
6367
6498
|
// src/commands/voice/checkLockFile.ts
|
|
6368
|
-
import { execSync as
|
|
6369
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync8, readFileSync as readFileSync24, writeFileSync as
|
|
6370
|
-
import { join as
|
|
6499
|
+
import { execSync as execSync28 } from "child_process";
|
|
6500
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync8, readFileSync as readFileSync24, writeFileSync as writeFileSync21 } from "fs";
|
|
6501
|
+
import { join as join29 } from "path";
|
|
6371
6502
|
function isProcessAlive(pid) {
|
|
6372
6503
|
try {
|
|
6373
6504
|
process.kill(pid, 0);
|
|
@@ -6394,7 +6525,7 @@ function bootstrapVenv() {
|
|
|
6394
6525
|
if (existsSync30(getVenvPython())) return;
|
|
6395
6526
|
console.log("Setting up Python environment...");
|
|
6396
6527
|
const pythonDir = getPythonDir();
|
|
6397
|
-
|
|
6528
|
+
execSync28(
|
|
6398
6529
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
6399
6530
|
{
|
|
6400
6531
|
stdio: "inherit",
|
|
@@ -6404,8 +6535,8 @@ function bootstrapVenv() {
|
|
|
6404
6535
|
}
|
|
6405
6536
|
function writeLockFile(pid) {
|
|
6406
6537
|
const lockFile = getLockFile();
|
|
6407
|
-
mkdirSync8(
|
|
6408
|
-
|
|
6538
|
+
mkdirSync8(join29(lockFile, ".."), { recursive: true });
|
|
6539
|
+
writeFileSync21(
|
|
6409
6540
|
lockFile,
|
|
6410
6541
|
JSON.stringify({
|
|
6411
6542
|
pid,
|
|
@@ -6420,7 +6551,7 @@ function setup() {
|
|
|
6420
6551
|
mkdirSync9(voicePaths.dir, { recursive: true });
|
|
6421
6552
|
bootstrapVenv();
|
|
6422
6553
|
console.log("\nDownloading models...\n");
|
|
6423
|
-
const script =
|
|
6554
|
+
const script = join30(getPythonDir(), "setup_models.py");
|
|
6424
6555
|
const result = spawnSync4(getVenvPython(), [script], {
|
|
6425
6556
|
stdio: "inherit",
|
|
6426
6557
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -6433,8 +6564,8 @@ function setup() {
|
|
|
6433
6564
|
|
|
6434
6565
|
// src/commands/voice/start.ts
|
|
6435
6566
|
import { spawn as spawn4 } from "child_process";
|
|
6436
|
-
import { mkdirSync as mkdirSync10, writeFileSync as
|
|
6437
|
-
import { join as
|
|
6567
|
+
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync22 } from "fs";
|
|
6568
|
+
import { join as join31 } from "path";
|
|
6438
6569
|
|
|
6439
6570
|
// src/commands/voice/buildDaemonEnv.ts
|
|
6440
6571
|
function buildDaemonEnv(options2) {
|
|
@@ -6462,7 +6593,7 @@ function spawnBackground(python, script, env) {
|
|
|
6462
6593
|
console.error("Failed to start voice daemon");
|
|
6463
6594
|
process.exit(1);
|
|
6464
6595
|
}
|
|
6465
|
-
|
|
6596
|
+
writeFileSync22(voicePaths.pid, String(pid));
|
|
6466
6597
|
writeLockFile(pid);
|
|
6467
6598
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
6468
6599
|
}
|
|
@@ -6472,7 +6603,7 @@ function start2(options2) {
|
|
|
6472
6603
|
bootstrapVenv();
|
|
6473
6604
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
6474
6605
|
const env = buildDaemonEnv({ debug });
|
|
6475
|
-
const script =
|
|
6606
|
+
const script = join31(getPythonDir(), "voice_daemon.py");
|
|
6476
6607
|
const python = getVenvPython();
|
|
6477
6608
|
if (options2.foreground) {
|
|
6478
6609
|
spawnForeground(python, script, env);
|
|
@@ -6558,14 +6689,14 @@ function registerVoice(program2) {
|
|
|
6558
6689
|
|
|
6559
6690
|
// src/commands/roam/auth.ts
|
|
6560
6691
|
import { randomBytes } from "crypto";
|
|
6561
|
-
import
|
|
6692
|
+
import chalk56 from "chalk";
|
|
6562
6693
|
|
|
6563
6694
|
// src/lib/openBrowser.ts
|
|
6564
|
-
import { execSync as
|
|
6695
|
+
import { execSync as execSync29 } from "child_process";
|
|
6565
6696
|
function tryExec(commands) {
|
|
6566
6697
|
for (const cmd of commands) {
|
|
6567
6698
|
try {
|
|
6568
|
-
|
|
6699
|
+
execSync29(cmd);
|
|
6569
6700
|
return true;
|
|
6570
6701
|
} catch {
|
|
6571
6702
|
}
|
|
@@ -6733,13 +6864,13 @@ async function auth() {
|
|
|
6733
6864
|
saveGlobalConfig(config);
|
|
6734
6865
|
const state = randomBytes(16).toString("hex");
|
|
6735
6866
|
console.log(
|
|
6736
|
-
|
|
6867
|
+
chalk56.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
6737
6868
|
);
|
|
6738
|
-
console.log(
|
|
6739
|
-
console.log(
|
|
6740
|
-
console.log(
|
|
6869
|
+
console.log(chalk56.white("http://localhost:14523/callback\n"));
|
|
6870
|
+
console.log(chalk56.blue("Opening browser for authorization..."));
|
|
6871
|
+
console.log(chalk56.dim("Waiting for authorization callback..."));
|
|
6741
6872
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
6742
|
-
console.log(
|
|
6873
|
+
console.log(chalk56.dim("Exchanging code for tokens..."));
|
|
6743
6874
|
const tokens = await exchangeToken({
|
|
6744
6875
|
code,
|
|
6745
6876
|
clientId,
|
|
@@ -6755,7 +6886,7 @@ async function auth() {
|
|
|
6755
6886
|
};
|
|
6756
6887
|
saveGlobalConfig(config);
|
|
6757
6888
|
console.log(
|
|
6758
|
-
|
|
6889
|
+
chalk56.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
6759
6890
|
);
|
|
6760
6891
|
}
|
|
6761
6892
|
|
|
@@ -6802,8 +6933,8 @@ function resolveParams(params, cliArgs) {
|
|
|
6802
6933
|
}
|
|
6803
6934
|
|
|
6804
6935
|
// src/commands/run/add.ts
|
|
6805
|
-
import { mkdirSync as mkdirSync11, writeFileSync as
|
|
6806
|
-
import { join as
|
|
6936
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync23 } from "fs";
|
|
6937
|
+
import { join as join32 } from "path";
|
|
6807
6938
|
function findAddIndex() {
|
|
6808
6939
|
const addIndex = process.argv.indexOf("add");
|
|
6809
6940
|
if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
|
|
@@ -6857,7 +6988,7 @@ function saveNewRunConfig(name, command, args) {
|
|
|
6857
6988
|
saveConfig(config);
|
|
6858
6989
|
}
|
|
6859
6990
|
function createCommandFile(name) {
|
|
6860
|
-
const dir =
|
|
6991
|
+
const dir = join32(".claude", "commands");
|
|
6861
6992
|
mkdirSync11(dir, { recursive: true });
|
|
6862
6993
|
const content = `---
|
|
6863
6994
|
description: Run ${name}
|
|
@@ -6865,8 +6996,8 @@ description: Run ${name}
|
|
|
6865
6996
|
|
|
6866
6997
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
6867
6998
|
`;
|
|
6868
|
-
const filePath =
|
|
6869
|
-
|
|
6999
|
+
const filePath = join32(dir, `${name}.md`);
|
|
7000
|
+
writeFileSync23(filePath, content);
|
|
6870
7001
|
console.log(`Created command file: ${filePath}`);
|
|
6871
7002
|
}
|
|
6872
7003
|
function add2() {
|
|
@@ -6943,14 +7074,14 @@ function run2(name, args) {
|
|
|
6943
7074
|
}
|
|
6944
7075
|
|
|
6945
7076
|
// src/commands/statusLine.ts
|
|
6946
|
-
import
|
|
7077
|
+
import chalk57 from "chalk";
|
|
6947
7078
|
function formatNumber(num) {
|
|
6948
7079
|
return num.toLocaleString("en-US");
|
|
6949
7080
|
}
|
|
6950
7081
|
function colorizePercent(pct) {
|
|
6951
7082
|
const label2 = `${pct}%`;
|
|
6952
|
-
if (pct > 80) return
|
|
6953
|
-
if (pct > 40) return
|
|
7083
|
+
if (pct > 80) return chalk57.red(label2);
|
|
7084
|
+
if (pct > 40) return chalk57.yellow(label2);
|
|
6954
7085
|
return label2;
|
|
6955
7086
|
}
|
|
6956
7087
|
async function statusLine() {
|
|
@@ -6976,7 +7107,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
6976
7107
|
// src/commands/sync/syncClaudeMd.ts
|
|
6977
7108
|
import * as fs21 from "fs";
|
|
6978
7109
|
import * as path31 from "path";
|
|
6979
|
-
import
|
|
7110
|
+
import chalk58 from "chalk";
|
|
6980
7111
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
6981
7112
|
const source = path31.join(claudeDir, "CLAUDE.md");
|
|
6982
7113
|
const target = path31.join(targetBase, "CLAUDE.md");
|
|
@@ -6985,12 +7116,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
6985
7116
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
6986
7117
|
if (sourceContent !== targetContent) {
|
|
6987
7118
|
console.log(
|
|
6988
|
-
|
|
7119
|
+
chalk58.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
6989
7120
|
);
|
|
6990
7121
|
console.log();
|
|
6991
7122
|
printDiff(targetContent, sourceContent);
|
|
6992
7123
|
const confirm = await promptConfirm(
|
|
6993
|
-
|
|
7124
|
+
chalk58.red("Overwrite existing CLAUDE.md?"),
|
|
6994
7125
|
false
|
|
6995
7126
|
);
|
|
6996
7127
|
if (!confirm) {
|
|
@@ -7006,7 +7137,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7006
7137
|
// src/commands/sync/syncSettings.ts
|
|
7007
7138
|
import * as fs22 from "fs";
|
|
7008
7139
|
import * as path32 from "path";
|
|
7009
|
-
import
|
|
7140
|
+
import chalk59 from "chalk";
|
|
7010
7141
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
7011
7142
|
const source = path32.join(claudeDir, "settings.json");
|
|
7012
7143
|
const target = path32.join(targetBase, "settings.json");
|
|
@@ -7022,14 +7153,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7022
7153
|
if (mergedContent !== normalizedTarget) {
|
|
7023
7154
|
if (!options2?.yes) {
|
|
7024
7155
|
console.log(
|
|
7025
|
-
|
|
7156
|
+
chalk59.yellow(
|
|
7026
7157
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
7027
7158
|
)
|
|
7028
7159
|
);
|
|
7029
7160
|
console.log();
|
|
7030
7161
|
printDiff(targetContent, mergedContent);
|
|
7031
7162
|
const confirm = await promptConfirm(
|
|
7032
|
-
|
|
7163
|
+
chalk59.red("Overwrite existing settings.json?"),
|
|
7033
7164
|
false
|
|
7034
7165
|
);
|
|
7035
7166
|
if (!confirm) {
|
|
@@ -7066,7 +7197,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
7066
7197
|
}
|
|
7067
7198
|
|
|
7068
7199
|
// src/commands/update.ts
|
|
7069
|
-
import { execSync as
|
|
7200
|
+
import { execSync as execSync30 } from "child_process";
|
|
7070
7201
|
import * as path34 from "path";
|
|
7071
7202
|
function isGlobalNpmInstall(dir) {
|
|
7072
7203
|
try {
|
|
@@ -7074,7 +7205,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
7074
7205
|
if (resolved.split(path34.sep).includes("node_modules")) {
|
|
7075
7206
|
return true;
|
|
7076
7207
|
}
|
|
7077
|
-
const globalPrefix =
|
|
7208
|
+
const globalPrefix = execSync30("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
7078
7209
|
return resolved.toLowerCase().startsWith(path34.resolve(globalPrefix).toLowerCase());
|
|
7079
7210
|
} catch {
|
|
7080
7211
|
return false;
|
|
@@ -7085,18 +7216,18 @@ async function update() {
|
|
|
7085
7216
|
console.log(`Assist is installed at: ${installDir}`);
|
|
7086
7217
|
if (isGitRepo(installDir)) {
|
|
7087
7218
|
console.log("Detected git repo installation, pulling latest...");
|
|
7088
|
-
|
|
7219
|
+
execSync30("git pull", { cwd: installDir, stdio: "inherit" });
|
|
7089
7220
|
console.log("Installing dependencies...");
|
|
7090
|
-
|
|
7221
|
+
execSync30("npm i", { cwd: installDir, stdio: "inherit" });
|
|
7091
7222
|
console.log("Building...");
|
|
7092
|
-
|
|
7223
|
+
execSync30("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
7093
7224
|
console.log("Syncing commands...");
|
|
7094
|
-
|
|
7225
|
+
execSync30("assist sync", { stdio: "inherit" });
|
|
7095
7226
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
7096
7227
|
console.log("Detected global npm installation, updating...");
|
|
7097
|
-
|
|
7228
|
+
execSync30("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
7098
7229
|
console.log("Syncing commands...");
|
|
7099
|
-
|
|
7230
|
+
execSync30("assist sync", { stdio: "inherit" });
|
|
7100
7231
|
} else {
|
|
7101
7232
|
console.error(
|
|
7102
7233
|
"Could not determine installation method. Expected a git repo or global npm install."
|