@staff0rd/assist 0.338.0 → 0.340.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 +3 -4
- package/allowed.cli-reads +1 -0
- package/allowed.cli-writes +0 -2
- package/claude/commands/transcripts.md +49 -0
- package/claude/settings.json +2 -4
- package/dist/allowed.cli-reads +1 -0
- package/dist/allowed.cli-writes +0 -2
- package/dist/commands/sessions/web/bundle.js +1 -1
- package/dist/index.js +187 -490
- package/package.json +1 -1
- package/claude/commands/transcript-format.md +0 -7
- package/claude/commands/transcript-summarise.md +0 -3
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.340.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -8861,9 +8861,9 @@ function parsePerms(entries) {
|
|
|
8861
8861
|
const tool = m[1];
|
|
8862
8862
|
const command = normCmd(m[2]);
|
|
8863
8863
|
const wildcard = m[3] !== void 0;
|
|
8864
|
-
const
|
|
8865
|
-
|
|
8866
|
-
map.set(tool,
|
|
8864
|
+
const list5 = map.get(tool) ?? [];
|
|
8865
|
+
list5.push({ command, wildcard });
|
|
8866
|
+
map.set(tool, list5);
|
|
8867
8867
|
}
|
|
8868
8868
|
}
|
|
8869
8869
|
return map;
|
|
@@ -14306,12 +14306,12 @@ import chalk145 from "chalk";
|
|
|
14306
14306
|
|
|
14307
14307
|
// src/shared/createConnectionAuth.ts
|
|
14308
14308
|
import chalk140 from "chalk";
|
|
14309
|
-
function listConnections(connections,
|
|
14309
|
+
function listConnections(connections, format) {
|
|
14310
14310
|
if (connections.length === 0) {
|
|
14311
14311
|
console.log("No connections configured.");
|
|
14312
14312
|
} else {
|
|
14313
14313
|
for (const c of connections) {
|
|
14314
|
-
console.log(
|
|
14314
|
+
console.log(format(c));
|
|
14315
14315
|
}
|
|
14316
14316
|
}
|
|
14317
14317
|
}
|
|
@@ -15687,9 +15687,9 @@ import path36 from "path";
|
|
|
15687
15687
|
// src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
|
|
15688
15688
|
import fs24 from "fs";
|
|
15689
15689
|
function getOrCreateList(map, key) {
|
|
15690
|
-
const
|
|
15691
|
-
if (!map.has(key)) map.set(key,
|
|
15692
|
-
return
|
|
15690
|
+
const list5 = map.get(key) ?? [];
|
|
15691
|
+
if (!map.has(key)) map.set(key, list5);
|
|
15692
|
+
return list5;
|
|
15693
15693
|
}
|
|
15694
15694
|
function groupByFile2(rewrites) {
|
|
15695
15695
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -15721,7 +15721,7 @@ function applyRewrites(rewrites) {
|
|
|
15721
15721
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
15722
15722
|
function buildMoveMap(moves) {
|
|
15723
15723
|
const map = /* @__PURE__ */ new Map();
|
|
15724
|
-
for (const
|
|
15724
|
+
for (const move2 of moves) map.set(move2.from, move2.to);
|
|
15725
15725
|
return map;
|
|
15726
15726
|
}
|
|
15727
15727
|
function stripTrailingIndex(specifier) {
|
|
@@ -15871,8 +15871,8 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
15871
15871
|
...graph.imports.keys(),
|
|
15872
15872
|
sourcePath
|
|
15873
15873
|
]);
|
|
15874
|
-
const
|
|
15875
|
-
return computeRewrites([
|
|
15874
|
+
const move2 = { from: sourcePath, to: destPath, reason: "rename" };
|
|
15875
|
+
return computeRewrites([move2], graph.edges, allProjectFiles);
|
|
15876
15876
|
}
|
|
15877
15877
|
|
|
15878
15878
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
@@ -16052,8 +16052,8 @@ function findRootParent(file, importedBy, visited) {
|
|
|
16052
16052
|
function clusterFiles(graph) {
|
|
16053
16053
|
const clusters = /* @__PURE__ */ new Map();
|
|
16054
16054
|
for (const file of graph.files) {
|
|
16055
|
-
const
|
|
16056
|
-
if (
|
|
16055
|
+
const basename11 = path43.basename(file, path43.extname(file));
|
|
16056
|
+
if (basename11 === "index") continue;
|
|
16057
16057
|
const importers = graph.importedBy.get(file);
|
|
16058
16058
|
if (!importers || importers.size !== 1) continue;
|
|
16059
16059
|
const parent = [...importers][0];
|
|
@@ -16081,11 +16081,11 @@ function relPath(filePath) {
|
|
|
16081
16081
|
function displayMoves(plan2) {
|
|
16082
16082
|
if (plan2.moves.length === 0) return;
|
|
16083
16083
|
console.log(chalk161.bold("\nFile moves:"));
|
|
16084
|
-
for (const
|
|
16084
|
+
for (const move2 of plan2.moves) {
|
|
16085
16085
|
console.log(
|
|
16086
|
-
` ${chalk161.red(relPath(
|
|
16086
|
+
` ${chalk161.red(relPath(move2.from))} \u2192 ${chalk161.green(relPath(move2.to))}`
|
|
16087
16087
|
);
|
|
16088
|
-
console.log(chalk161.dim(` ${
|
|
16088
|
+
console.log(chalk161.dim(` ${move2.reason}`));
|
|
16089
16089
|
}
|
|
16090
16090
|
}
|
|
16091
16091
|
function displayRewrites(rewrites) {
|
|
@@ -16140,15 +16140,15 @@ function executePlan(plan2) {
|
|
|
16140
16140
|
fs27.mkdirSync(dir, { recursive: true });
|
|
16141
16141
|
console.log(chalk162.green(` Created ${path45.relative(process.cwd(), dir)}/`));
|
|
16142
16142
|
}
|
|
16143
|
-
for (const
|
|
16144
|
-
const targetDir = path45.dirname(
|
|
16143
|
+
for (const move2 of plan2.moves) {
|
|
16144
|
+
const targetDir = path45.dirname(move2.to);
|
|
16145
16145
|
if (!fs27.existsSync(targetDir)) {
|
|
16146
16146
|
fs27.mkdirSync(targetDir, { recursive: true });
|
|
16147
16147
|
}
|
|
16148
|
-
fs27.renameSync(
|
|
16148
|
+
fs27.renameSync(move2.from, move2.to);
|
|
16149
16149
|
console.log(
|
|
16150
16150
|
chalk162.white(
|
|
16151
|
-
` Moved ${path45.relative(process.cwd(),
|
|
16151
|
+
` Moved ${path45.relative(process.cwd(), move2.from)} \u2192 ${path45.relative(process.cwd(), move2.to)}`
|
|
16152
16152
|
)
|
|
16153
16153
|
);
|
|
16154
16154
|
}
|
|
@@ -18700,50 +18700,7 @@ function registerSql(program2) {
|
|
|
18700
18700
|
}
|
|
18701
18701
|
|
|
18702
18702
|
// src/commands/transcript/shared.ts
|
|
18703
|
-
import { existsSync as existsSync41, readdirSync as readdirSync8, statSync as statSync6 } from "fs";
|
|
18704
|
-
import { basename as basename8, join as join48, relative as relative2 } from "path";
|
|
18705
18703
|
import * as readline2 from "readline";
|
|
18706
|
-
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
18707
|
-
function getDatePrefix(daysOffset = 0) {
|
|
18708
|
-
const date = /* @__PURE__ */ new Date();
|
|
18709
|
-
date.setDate(date.getDate() + daysOffset);
|
|
18710
|
-
const year = date.getFullYear();
|
|
18711
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
18712
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
18713
|
-
return `${year}-${month}-${day}`;
|
|
18714
|
-
}
|
|
18715
|
-
function isValidDatePrefix(filename) {
|
|
18716
|
-
return DATE_PREFIX_REGEX.test(filename);
|
|
18717
|
-
}
|
|
18718
|
-
function collectFiles(dir, extension) {
|
|
18719
|
-
if (!existsSync41(dir)) return [];
|
|
18720
|
-
const results = [];
|
|
18721
|
-
for (const entry of readdirSync8(dir)) {
|
|
18722
|
-
const fullPath = join48(dir, entry);
|
|
18723
|
-
if (statSync6(fullPath).isDirectory()) {
|
|
18724
|
-
results.push(...collectFiles(fullPath, extension));
|
|
18725
|
-
} else if (entry.endsWith(extension)) {
|
|
18726
|
-
results.push(fullPath);
|
|
18727
|
-
}
|
|
18728
|
-
}
|
|
18729
|
-
return results;
|
|
18730
|
-
}
|
|
18731
|
-
function toFileInfo(baseDir, fullPath) {
|
|
18732
|
-
return {
|
|
18733
|
-
absolutePath: fullPath,
|
|
18734
|
-
relativePath: relative2(baseDir, fullPath),
|
|
18735
|
-
filename: basename8(fullPath)
|
|
18736
|
-
};
|
|
18737
|
-
}
|
|
18738
|
-
function findVttFilesRecursive(dir, baseDir = dir) {
|
|
18739
|
-
return collectFiles(dir, ".vtt").map((f) => toFileInfo(baseDir, f));
|
|
18740
|
-
}
|
|
18741
|
-
function findMdFilesRecursive(dir, baseDir = dir) {
|
|
18742
|
-
return collectFiles(dir, ".md").map((f) => toFileInfo(baseDir, f));
|
|
18743
|
-
}
|
|
18744
|
-
function getTranscriptBaseName(transcriptFile) {
|
|
18745
|
-
return basename8(transcriptFile, ".md").replace(/ Transcription$/, "");
|
|
18746
|
-
}
|
|
18747
18704
|
function createReadlineInterface() {
|
|
18748
18705
|
return readline2.createInterface({
|
|
18749
18706
|
input: process.stdin,
|
|
@@ -18812,83 +18769,28 @@ async function configure() {
|
|
|
18812
18769
|
}
|
|
18813
18770
|
}
|
|
18814
18771
|
|
|
18815
|
-
// src/commands/transcript/
|
|
18816
|
-
import { existsSync as
|
|
18817
|
-
|
|
18818
|
-
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
|
|
18824
|
-
|
|
18825
|
-
if (choice === "1") return getDatePrefix(0);
|
|
18826
|
-
if (choice === "2") return getDatePrefix(-1);
|
|
18827
|
-
if (choice === "3") {
|
|
18828
|
-
const customDate = await askQuestion(rl, "Enter date (YYYY-MM-DD): ");
|
|
18829
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(customDate)) return customDate;
|
|
18830
|
-
console.log("Invalid date format. Cancelling.");
|
|
18831
|
-
return null;
|
|
18832
|
-
}
|
|
18833
|
-
console.log("Cancelled.");
|
|
18834
|
-
return null;
|
|
18835
|
-
}
|
|
18836
|
-
function renameWithPrefix(vttDir, vttFile, prefix2) {
|
|
18837
|
-
const newFilename = `${prefix2}.${vttFile}`;
|
|
18838
|
-
renameSync2(join49(vttDir, vttFile), join49(vttDir, newFilename));
|
|
18839
|
-
console.log(`Renamed to: ${newFilename}`);
|
|
18840
|
-
return newFilename;
|
|
18841
|
-
}
|
|
18842
|
-
async function promptForDateFix(vttFile, vttDir) {
|
|
18843
|
-
const rl = createReadlineInterface();
|
|
18844
|
-
console.log(
|
|
18845
|
-
`
|
|
18846
|
-
Error: File "${vttFile}" does not start with YYYY-MM-DD format.`
|
|
18847
|
-
);
|
|
18848
|
-
console.log("\nOptions:");
|
|
18849
|
-
console.log(" 1. Use today's date");
|
|
18850
|
-
console.log(" 2. Use yesterday's date");
|
|
18851
|
-
console.log(" 3. Enter your own date");
|
|
18852
|
-
console.log(" 4. Cancel");
|
|
18853
|
-
try {
|
|
18854
|
-
const choice = await askQuestion(rl, "\nSelect an option (1/2/3/4): ");
|
|
18855
|
-
const prefix2 = await resolveDate(rl, choice);
|
|
18856
|
-
rl.close();
|
|
18857
|
-
return prefix2 ? renameWithPrefix(vttDir, vttFile, prefix2) : null;
|
|
18858
|
-
} catch (error) {
|
|
18859
|
-
rl.close();
|
|
18860
|
-
throw error;
|
|
18861
|
-
}
|
|
18862
|
-
}
|
|
18863
|
-
|
|
18864
|
-
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
18865
|
-
async function fixInvalidDatePrefixes(vttFiles) {
|
|
18866
|
-
for (let i = 0; i < vttFiles.length; i++) {
|
|
18867
|
-
const vttFile = vttFiles[i];
|
|
18868
|
-
if (!isValidDatePrefix(vttFile.filename)) {
|
|
18869
|
-
const vttFileDir = dirname23(vttFile.absolutePath);
|
|
18870
|
-
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
18871
|
-
if (newFilename) {
|
|
18872
|
-
const newRelativePath = join50(
|
|
18873
|
-
dirname23(vttFile.relativePath),
|
|
18874
|
-
newFilename
|
|
18875
|
-
);
|
|
18876
|
-
vttFiles[i] = {
|
|
18877
|
-
absolutePath: join50(vttFileDir, newFilename),
|
|
18878
|
-
relativePath: newRelativePath,
|
|
18879
|
-
filename: newFilename
|
|
18880
|
-
};
|
|
18881
|
-
} else {
|
|
18882
|
-
vttFiles[i] = { absolutePath: "", relativePath: "", filename: "" };
|
|
18883
|
-
}
|
|
18884
|
-
}
|
|
18772
|
+
// src/commands/transcript/list.ts
|
|
18773
|
+
import { existsSync as existsSync41, readdirSync as readdirSync8, statSync as statSync6 } from "fs";
|
|
18774
|
+
import { join as join48 } from "path";
|
|
18775
|
+
function list4() {
|
|
18776
|
+
const { vttDir } = getTranscriptConfig();
|
|
18777
|
+
if (!existsSync41(vttDir)) return;
|
|
18778
|
+
for (const entry of readdirSync8(vttDir)) {
|
|
18779
|
+
if (!entry.endsWith(".vtt")) continue;
|
|
18780
|
+
if (statSync6(join48(vttDir, entry)).isDirectory()) continue;
|
|
18781
|
+
console.log(entry);
|
|
18885
18782
|
}
|
|
18886
|
-
return vttFiles.filter((f) => f.absolutePath !== "");
|
|
18887
18783
|
}
|
|
18888
18784
|
|
|
18889
|
-
// src/commands/transcript/
|
|
18890
|
-
import {
|
|
18891
|
-
|
|
18785
|
+
// src/commands/transcript/move.ts
|
|
18786
|
+
import {
|
|
18787
|
+
existsSync as existsSync42,
|
|
18788
|
+
mkdirSync as mkdirSync17,
|
|
18789
|
+
readFileSync as readFileSync36,
|
|
18790
|
+
renameSync as renameSync2,
|
|
18791
|
+
writeFileSync as writeFileSync35
|
|
18792
|
+
} from "fs";
|
|
18793
|
+
import { basename as basename8, join as join49 } from "path";
|
|
18892
18794
|
|
|
18893
18795
|
// src/commands/transcript/cleanText.ts
|
|
18894
18796
|
function cleanText(text6) {
|
|
@@ -18911,7 +18813,7 @@ function cleanText(text6) {
|
|
|
18911
18813
|
return cleaned.join(" ").replace(/\s+/g, " ").trim();
|
|
18912
18814
|
}
|
|
18913
18815
|
|
|
18914
|
-
// src/commands/transcript/
|
|
18816
|
+
// src/commands/transcript/convert/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
|
|
18915
18817
|
function normalizeText(text6) {
|
|
18916
18818
|
return text6.toLowerCase().trim();
|
|
18917
18819
|
}
|
|
@@ -18954,7 +18856,7 @@ function removeSubstringDuplicates(cues) {
|
|
|
18954
18856
|
return cues.filter((_, i) => !toRemove.has(i));
|
|
18955
18857
|
}
|
|
18956
18858
|
|
|
18957
|
-
// src/commands/transcript/
|
|
18859
|
+
// src/commands/transcript/convert/parseVtt/deduplicateCues/index.ts
|
|
18958
18860
|
function findWordOverlap(currentWords, nextWords) {
|
|
18959
18861
|
for (let j = Math.min(5, currentWords.length); j >= 1; j--) {
|
|
18960
18862
|
const suffix = currentWords.slice(-j).join(" ");
|
|
@@ -19002,7 +18904,7 @@ function deduplicateCues(cues) {
|
|
|
19002
18904
|
}));
|
|
19003
18905
|
}
|
|
19004
18906
|
|
|
19005
|
-
// src/commands/transcript/
|
|
18907
|
+
// src/commands/transcript/convert/parseVtt/index.ts
|
|
19006
18908
|
function parseHMS(h, m, s) {
|
|
19007
18909
|
return Number.parseInt(h, 10) * 3600 + Number.parseInt(m, 10) * 60 + Number.parseFloat(s);
|
|
19008
18910
|
}
|
|
@@ -19072,7 +18974,7 @@ function parseVtt(content) {
|
|
|
19072
18974
|
return cues;
|
|
19073
18975
|
}
|
|
19074
18976
|
|
|
19075
|
-
// src/commands/transcript/
|
|
18977
|
+
// src/commands/transcript/convert/formatChatLog.ts
|
|
19076
18978
|
function cuesToChatMessages(cues) {
|
|
19077
18979
|
const messages = [];
|
|
19078
18980
|
for (const cue of cues) {
|
|
@@ -19093,256 +18995,51 @@ function formatChatLog(messages) {
|
|
|
19093
18995
|
return messages.map((msg) => `${msg.speaker}: ${msg.text}`).join("\n\n");
|
|
19094
18996
|
}
|
|
19095
18997
|
|
|
19096
|
-
// src/commands/transcript/
|
|
19097
|
-
|
|
19098
|
-
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
return
|
|
19102
|
-
}
|
|
19103
|
-
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
19104
|
-
const mdFile = toMdFilename(vttFile.filename);
|
|
19105
|
-
const relativeDir = dirname24(vttFile.relativePath);
|
|
19106
|
-
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
19107
|
-
const outputPath = join51(outputDir, mdFile);
|
|
19108
|
-
return { outputDir, outputPath, mdFile, relativeDir };
|
|
19109
|
-
}
|
|
19110
|
-
function logSkipped(relativeDir, mdFile) {
|
|
19111
|
-
console.log(`Skipping (already exists): ${join51(relativeDir, mdFile)}`);
|
|
19112
|
-
return "skipped";
|
|
19113
|
-
}
|
|
19114
|
-
function ensureDirectory(dir, label2) {
|
|
19115
|
-
if (!existsSync42(dir)) {
|
|
19116
|
-
mkdirSync17(dir, { recursive: true });
|
|
19117
|
-
console.log(`Created ${label2}: ${dir}`);
|
|
19118
|
-
}
|
|
18998
|
+
// src/commands/transcript/move.ts
|
|
18999
|
+
var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
19000
|
+
function convertVttToMarkdown(inputPath) {
|
|
19001
|
+
const cues = parseVtt(readFileSync36(inputPath, "utf8"));
|
|
19002
|
+
const messages = cuesToChatMessages(deduplicateCues(cues));
|
|
19003
|
+
return formatChatLog(messages);
|
|
19119
19004
|
}
|
|
19120
|
-
function
|
|
19121
|
-
const
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
console.log(`After deduplication: ${dedupedCues.length} cues`);
|
|
19125
|
-
return { cues, dedupedCues };
|
|
19005
|
+
function archiveRawVtt(vttDir, sourcePath, filename) {
|
|
19006
|
+
const processedDir = join49(vttDir, "processed");
|
|
19007
|
+
mkdirSync17(processedDir, { recursive: true });
|
|
19008
|
+
renameSync2(sourcePath, join49(processedDir, filename));
|
|
19126
19009
|
}
|
|
19127
|
-
function
|
|
19128
|
-
const
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
}
|
|
19132
|
-
function logReduction(cueCount, messageCount) {
|
|
19133
|
-
console.log(`Reduction: ${cueCount} cues -> ${messageCount} messages
|
|
19134
|
-
`);
|
|
19135
|
-
}
|
|
19136
|
-
function readAndParseCues(inputPath) {
|
|
19137
|
-
console.log(`Reading: ${inputPath}`);
|
|
19138
|
-
return processCues(readFileSync36(inputPath, "utf8"));
|
|
19139
|
-
}
|
|
19140
|
-
function writeFormatted(outputPath, content) {
|
|
19141
|
-
writeFileSync35(outputPath, content, "utf8");
|
|
19142
|
-
console.log(`Written: ${outputPath}`);
|
|
19143
|
-
}
|
|
19144
|
-
function convertVttToMarkdown(inputPath, outputPath) {
|
|
19145
|
-
const { cues, dedupedCues } = readAndParseCues(inputPath);
|
|
19146
|
-
const chatMessages = convertToMessages(dedupedCues);
|
|
19147
|
-
writeFormatted(outputPath, formatChatLog(chatMessages));
|
|
19148
|
-
logReduction(cues.length, chatMessages.length);
|
|
19149
|
-
}
|
|
19150
|
-
function tryProcessVtt(vttFile, paths) {
|
|
19151
|
-
if (existsSync42(paths.outputPath))
|
|
19152
|
-
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
19153
|
-
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
19154
|
-
return "processed";
|
|
19155
|
-
}
|
|
19156
|
-
function processVttFile(vttFile, transcriptsDir) {
|
|
19157
|
-
const paths = buildOutputPaths(vttFile, transcriptsDir);
|
|
19158
|
-
ensureDirectory(paths.outputDir, "output directory");
|
|
19159
|
-
return tryProcessVtt(vttFile, paths);
|
|
19160
|
-
}
|
|
19161
|
-
|
|
19162
|
-
// src/commands/transcript/format/index.ts
|
|
19163
|
-
function logSummary(counts) {
|
|
19164
|
-
console.log(
|
|
19165
|
-
`
|
|
19166
|
-
Summary: ${counts.processed} processed, ${counts.skipped} skipped`
|
|
19167
|
-
);
|
|
19168
|
-
}
|
|
19169
|
-
function processAllFiles(vttFiles, transcriptsDir) {
|
|
19170
|
-
const counts = { processed: 0, skipped: 0 };
|
|
19171
|
-
for (const vttFile of vttFiles) {
|
|
19172
|
-
counts[processVttFile(vttFile, transcriptsDir)]++;
|
|
19173
|
-
}
|
|
19174
|
-
logSummary(counts);
|
|
19175
|
-
}
|
|
19176
|
-
function requireVttDir(vttDir) {
|
|
19177
|
-
if (!existsSync43(vttDir)) {
|
|
19178
|
-
console.error(`VTT directory not found: ${vttDir}`);
|
|
19179
|
-
process.exit(1);
|
|
19180
|
-
}
|
|
19181
|
-
}
|
|
19182
|
-
function logFoundFiles(files, vttDir) {
|
|
19183
|
-
console.log(`Found ${files.length} VTT file(s) in ${vttDir}
|
|
19184
|
-
`);
|
|
19185
|
-
}
|
|
19186
|
-
function logNoVttFiles() {
|
|
19187
|
-
console.log("No VTT files found in vtt directory.");
|
|
19188
|
-
return null;
|
|
19189
|
-
}
|
|
19190
|
-
function loadVttFiles(vttDir) {
|
|
19191
|
-
const files = findVttFilesRecursive(vttDir);
|
|
19192
|
-
if (files.length === 0) return logNoVttFiles();
|
|
19193
|
-
logFoundFiles(files, vttDir);
|
|
19194
|
-
return files;
|
|
19195
|
-
}
|
|
19196
|
-
async function formatLoadedFiles(vttFiles, transcriptsDir) {
|
|
19197
|
-
const fixed2 = await fixInvalidDatePrefixes(vttFiles);
|
|
19198
|
-
processAllFiles(fixed2, transcriptsDir);
|
|
19199
|
-
}
|
|
19200
|
-
async function format() {
|
|
19201
|
-
const { vttDir, transcriptsDir } = getTranscriptConfig();
|
|
19202
|
-
requireVttDir(vttDir);
|
|
19203
|
-
ensureDirectory(transcriptsDir, "output directory");
|
|
19204
|
-
const vttFiles = loadVttFiles(vttDir);
|
|
19205
|
-
if (vttFiles) await formatLoadedFiles(vttFiles, transcriptsDir);
|
|
19206
|
-
}
|
|
19207
|
-
|
|
19208
|
-
// src/commands/transcript/summarise/index.ts
|
|
19209
|
-
import { existsSync as existsSync45 } from "fs";
|
|
19210
|
-
import { basename as basename10, dirname as dirname26, join as join53, relative as relative3 } from "path";
|
|
19211
|
-
|
|
19212
|
-
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
19213
|
-
import {
|
|
19214
|
-
existsSync as existsSync44,
|
|
19215
|
-
mkdirSync as mkdirSync18,
|
|
19216
|
-
readFileSync as readFileSync37,
|
|
19217
|
-
renameSync as renameSync3,
|
|
19218
|
-
rmSync as rmSync3
|
|
19219
|
-
} from "fs";
|
|
19220
|
-
import { dirname as dirname25, join as join52 } from "path";
|
|
19221
|
-
|
|
19222
|
-
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
19223
|
-
import chalk178 from "chalk";
|
|
19224
|
-
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
19225
|
-
function validateStagedContent(filename, content) {
|
|
19226
|
-
const firstLine = content.split("\n")[0];
|
|
19227
|
-
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
19228
|
-
if (!match) {
|
|
19229
|
-
console.error(
|
|
19230
|
-
chalk178.red(
|
|
19231
|
-
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
19232
|
-
)
|
|
19233
|
-
);
|
|
19010
|
+
function move(file, options2) {
|
|
19011
|
+
const { date, client } = options2;
|
|
19012
|
+
if (!DATE_REGEX.test(date)) {
|
|
19013
|
+
console.error("Error: --date must be in YYYY-MM-DD format.");
|
|
19234
19014
|
process.exit(1);
|
|
19235
19015
|
}
|
|
19236
|
-
const
|
|
19237
|
-
|
|
19238
|
-
|
|
19239
|
-
|
|
19240
|
-
|
|
19241
|
-
)
|
|
19242
|
-
);
|
|
19016
|
+
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
19017
|
+
const filename = basename8(file);
|
|
19018
|
+
const sourcePath = join49(vttDir, filename);
|
|
19019
|
+
if (!existsSync42(sourcePath)) {
|
|
19020
|
+
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
19243
19021
|
process.exit(1);
|
|
19244
19022
|
}
|
|
19245
|
-
|
|
19246
|
-
}
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
|
|
19253
|
-
}
|
|
19254
|
-
|
|
19255
|
-
if (stagedFiles.length === 0) {
|
|
19256
|
-
return false;
|
|
19257
|
-
}
|
|
19258
|
-
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
19259
|
-
const stagedFile = stagedFiles[0];
|
|
19260
|
-
const content = readFileSync37(stagedFile.absolutePath, "utf8");
|
|
19261
|
-
validateStagedContent(stagedFile.filename, content);
|
|
19262
|
-
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
19263
|
-
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
19264
|
-
const matchingTranscript = transcriptFiles.find(
|
|
19265
|
-
(t) => getTranscriptBaseName(t.filename) === stagedBaseName
|
|
19266
|
-
);
|
|
19267
|
-
if (!matchingTranscript) {
|
|
19268
|
-
console.error(
|
|
19269
|
-
`No transcript found matching staged file: ${stagedFile.filename}`
|
|
19270
|
-
);
|
|
19271
|
-
process.exit(1);
|
|
19272
|
-
}
|
|
19273
|
-
const destPath = join52(summaryDir, matchingTranscript.relativePath);
|
|
19274
|
-
const destDir = dirname25(destPath);
|
|
19275
|
-
if (!existsSync44(destDir)) {
|
|
19276
|
-
mkdirSync18(destDir, { recursive: true });
|
|
19277
|
-
}
|
|
19278
|
-
renameSync3(stagedFile.absolutePath, destPath);
|
|
19279
|
-
const remaining = findMdFilesRecursive(STAGING_DIR);
|
|
19280
|
-
if (remaining.length === 0) {
|
|
19281
|
-
rmSync3(STAGING_DIR, { recursive: true });
|
|
19282
|
-
}
|
|
19283
|
-
return true;
|
|
19284
|
-
}
|
|
19285
|
-
|
|
19286
|
-
// src/commands/transcript/summarise/index.ts
|
|
19287
|
-
function buildRelativeKey(relativePath, baseName) {
|
|
19288
|
-
const relDir = dirname26(relativePath);
|
|
19289
|
-
return relDir === "." ? baseName : join53(relDir, baseName);
|
|
19290
|
-
}
|
|
19291
|
-
function buildSummaryIndex(summaryDir) {
|
|
19292
|
-
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
19293
|
-
return new Set(
|
|
19294
|
-
summaryFiles.map(
|
|
19295
|
-
(f) => buildRelativeKey(f.relativePath, basename10(f.filename, ".md"))
|
|
19296
|
-
)
|
|
19297
|
-
);
|
|
19298
|
-
}
|
|
19299
|
-
function summarise2() {
|
|
19300
|
-
processStagedFile();
|
|
19301
|
-
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
19302
|
-
if (!existsSync45(transcriptsDir)) {
|
|
19303
|
-
console.log("No transcripts directory found.");
|
|
19304
|
-
return;
|
|
19305
|
-
}
|
|
19306
|
-
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
19307
|
-
if (transcriptFiles.length === 0) {
|
|
19308
|
-
console.log("No transcript files found.");
|
|
19309
|
-
return;
|
|
19310
|
-
}
|
|
19311
|
-
const summaryIndex = buildSummaryIndex(summaryDir);
|
|
19312
|
-
const missing = transcriptFiles.filter(
|
|
19313
|
-
(t) => !summaryIndex.has(
|
|
19314
|
-
buildRelativeKey(t.relativePath, getTranscriptBaseName(t.filename))
|
|
19315
|
-
)
|
|
19316
|
-
);
|
|
19317
|
-
if (missing.length === 0) {
|
|
19318
|
-
console.log("All transcripts have summaries.");
|
|
19319
|
-
return;
|
|
19320
|
-
}
|
|
19321
|
-
const next3 = missing[0];
|
|
19322
|
-
const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
|
|
19323
|
-
const outputPath = join53(STAGING_DIR, outputFilename);
|
|
19324
|
-
const summaryFileDir = join53(summaryDir, dirname26(next3.relativePath));
|
|
19325
|
-
const relativeTranscriptPath = encodeURI(
|
|
19326
|
-
relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
|
|
19327
|
-
);
|
|
19328
|
-
console.log(`Missing summaries: ${missing.length}
|
|
19329
|
-
`);
|
|
19330
|
-
console.log("Read and summarise this transcript:");
|
|
19331
|
-
console.log(` ${next3.absolutePath}
|
|
19332
|
-
`);
|
|
19333
|
-
console.log("Write the summary to:");
|
|
19334
|
-
console.log(` ${outputPath}
|
|
19335
|
-
`);
|
|
19336
|
-
console.log("The summary must start with:");
|
|
19337
|
-
console.log(` [Full Transcript](${relativeTranscriptPath})`);
|
|
19023
|
+
const base = basename8(filename, ".vtt").replace(/ Transcription$/, "");
|
|
19024
|
+
const outputName = `${date} ${base}.md`;
|
|
19025
|
+
const formattedDir = join49(transcriptsDir, client);
|
|
19026
|
+
mkdirSync17(formattedDir, { recursive: true });
|
|
19027
|
+
const formattedPath = join49(formattedDir, outputName);
|
|
19028
|
+
writeFileSync35(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
19029
|
+
archiveRawVtt(vttDir, sourcePath, filename);
|
|
19030
|
+
const summaryPath = join49(summaryDir, client, outputName);
|
|
19031
|
+
console.log(`Formatted transcript: ${formattedPath}`);
|
|
19032
|
+
console.log(`Summary target: ${summaryPath}`);
|
|
19338
19033
|
}
|
|
19339
19034
|
|
|
19340
19035
|
// src/commands/registerTranscript.ts
|
|
19341
19036
|
function registerTranscript(program2) {
|
|
19342
19037
|
const transcriptCommand = program2.command("transcript").description("Meeting transcript utilities");
|
|
19343
19038
|
transcriptCommand.command("configure").description("Configure transcript directories").action(configure);
|
|
19344
|
-
transcriptCommand.command("
|
|
19345
|
-
transcriptCommand.command("
|
|
19039
|
+
transcriptCommand.command("list").description("List raw .vtt filenames waiting in the pick-up directory").action(list4);
|
|
19040
|
+
transcriptCommand.command("move <file>").description(
|
|
19041
|
+
"Convert a raw .vtt to a dated markdown transcript and archive the original"
|
|
19042
|
+
).requiredOption("--date <YYYY-MM-DD>", "meeting date").requiredOption("--client <name>", "client name").action(move);
|
|
19346
19043
|
}
|
|
19347
19044
|
|
|
19348
19045
|
// src/commands/registerVerify.ts
|
|
@@ -19378,50 +19075,50 @@ function registerVerify(program2) {
|
|
|
19378
19075
|
|
|
19379
19076
|
// src/commands/voice/devices.ts
|
|
19380
19077
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
19381
|
-
import { join as
|
|
19078
|
+
import { join as join51 } from "path";
|
|
19382
19079
|
|
|
19383
19080
|
// src/commands/voice/shared.ts
|
|
19384
19081
|
import { homedir as homedir17 } from "os";
|
|
19385
|
-
import { dirname as
|
|
19082
|
+
import { dirname as dirname23, join as join50 } from "path";
|
|
19386
19083
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
19387
|
-
var __dirname5 =
|
|
19388
|
-
var VOICE_DIR =
|
|
19084
|
+
var __dirname5 = dirname23(fileURLToPath6(import.meta.url));
|
|
19085
|
+
var VOICE_DIR = join50(homedir17(), ".assist", "voice");
|
|
19389
19086
|
var voicePaths = {
|
|
19390
19087
|
dir: VOICE_DIR,
|
|
19391
|
-
pid:
|
|
19392
|
-
log:
|
|
19393
|
-
venv:
|
|
19394
|
-
lock:
|
|
19088
|
+
pid: join50(VOICE_DIR, "voice.pid"),
|
|
19089
|
+
log: join50(VOICE_DIR, "voice.log"),
|
|
19090
|
+
venv: join50(VOICE_DIR, ".venv"),
|
|
19091
|
+
lock: join50(VOICE_DIR, "voice.lock")
|
|
19395
19092
|
};
|
|
19396
19093
|
function getPythonDir() {
|
|
19397
|
-
return
|
|
19094
|
+
return join50(__dirname5, "commands", "voice", "python");
|
|
19398
19095
|
}
|
|
19399
19096
|
function getVenvPython() {
|
|
19400
|
-
return process.platform === "win32" ?
|
|
19097
|
+
return process.platform === "win32" ? join50(voicePaths.venv, "Scripts", "python.exe") : join50(voicePaths.venv, "bin", "python");
|
|
19401
19098
|
}
|
|
19402
19099
|
function getLockDir() {
|
|
19403
19100
|
const config = loadConfig();
|
|
19404
19101
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
19405
19102
|
}
|
|
19406
19103
|
function getLockFile() {
|
|
19407
|
-
return
|
|
19104
|
+
return join50(getLockDir(), "voice.lock");
|
|
19408
19105
|
}
|
|
19409
19106
|
|
|
19410
19107
|
// src/commands/voice/devices.ts
|
|
19411
19108
|
function devices() {
|
|
19412
|
-
const script =
|
|
19109
|
+
const script = join51(getPythonDir(), "list_devices.py");
|
|
19413
19110
|
spawnSync5(getVenvPython(), [script], { stdio: "inherit" });
|
|
19414
19111
|
}
|
|
19415
19112
|
|
|
19416
19113
|
// src/commands/voice/logs.ts
|
|
19417
|
-
import { existsSync as
|
|
19114
|
+
import { existsSync as existsSync43, readFileSync as readFileSync37 } from "fs";
|
|
19418
19115
|
function logs(options2) {
|
|
19419
|
-
if (!
|
|
19116
|
+
if (!existsSync43(voicePaths.log)) {
|
|
19420
19117
|
console.log("No voice log file found");
|
|
19421
19118
|
return;
|
|
19422
19119
|
}
|
|
19423
19120
|
const count7 = Number.parseInt(options2.lines ?? "150", 10);
|
|
19424
|
-
const content =
|
|
19121
|
+
const content = readFileSync37(voicePaths.log, "utf8").trim();
|
|
19425
19122
|
if (!content) {
|
|
19426
19123
|
console.log("Voice log is empty");
|
|
19427
19124
|
return;
|
|
@@ -19443,13 +19140,13 @@ function logs(options2) {
|
|
|
19443
19140
|
|
|
19444
19141
|
// src/commands/voice/setup.ts
|
|
19445
19142
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
19446
|
-
import { mkdirSync as
|
|
19447
|
-
import { join as
|
|
19143
|
+
import { mkdirSync as mkdirSync19 } from "fs";
|
|
19144
|
+
import { join as join53 } from "path";
|
|
19448
19145
|
|
|
19449
19146
|
// src/commands/voice/checkLockFile.ts
|
|
19450
19147
|
import { execSync as execSync48 } from "child_process";
|
|
19451
|
-
import { existsSync as
|
|
19452
|
-
import { join as
|
|
19148
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync18, readFileSync as readFileSync38, writeFileSync as writeFileSync36 } from "fs";
|
|
19149
|
+
import { join as join52 } from "path";
|
|
19453
19150
|
function isProcessAlive2(pid) {
|
|
19454
19151
|
try {
|
|
19455
19152
|
process.kill(pid, 0);
|
|
@@ -19460,9 +19157,9 @@ function isProcessAlive2(pid) {
|
|
|
19460
19157
|
}
|
|
19461
19158
|
function checkLockFile() {
|
|
19462
19159
|
const lockFile = getLockFile();
|
|
19463
|
-
if (!
|
|
19160
|
+
if (!existsSync44(lockFile)) return;
|
|
19464
19161
|
try {
|
|
19465
|
-
const lock2 = JSON.parse(
|
|
19162
|
+
const lock2 = JSON.parse(readFileSync38(lockFile, "utf8"));
|
|
19466
19163
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
19467
19164
|
console.error(
|
|
19468
19165
|
`Voice daemon already running (PID ${lock2.pid}, env: ${lock2.env}). Stop it first with: assist voice stop`
|
|
@@ -19473,7 +19170,7 @@ function checkLockFile() {
|
|
|
19473
19170
|
}
|
|
19474
19171
|
}
|
|
19475
19172
|
function bootstrapVenv() {
|
|
19476
|
-
if (
|
|
19173
|
+
if (existsSync44(getVenvPython())) return;
|
|
19477
19174
|
console.log("Setting up Python environment...");
|
|
19478
19175
|
const pythonDir = getPythonDir();
|
|
19479
19176
|
execSync48(
|
|
@@ -19486,7 +19183,7 @@ function bootstrapVenv() {
|
|
|
19486
19183
|
}
|
|
19487
19184
|
function writeLockFile(pid) {
|
|
19488
19185
|
const lockFile = getLockFile();
|
|
19489
|
-
|
|
19186
|
+
mkdirSync18(join52(lockFile, ".."), { recursive: true });
|
|
19490
19187
|
writeFileSync36(
|
|
19491
19188
|
lockFile,
|
|
19492
19189
|
JSON.stringify({
|
|
@@ -19499,10 +19196,10 @@ function writeLockFile(pid) {
|
|
|
19499
19196
|
|
|
19500
19197
|
// src/commands/voice/setup.ts
|
|
19501
19198
|
function setup() {
|
|
19502
|
-
|
|
19199
|
+
mkdirSync19(voicePaths.dir, { recursive: true });
|
|
19503
19200
|
bootstrapVenv();
|
|
19504
19201
|
console.log("\nDownloading models...\n");
|
|
19505
|
-
const script =
|
|
19202
|
+
const script = join53(getPythonDir(), "setup_models.py");
|
|
19506
19203
|
const result = spawnSync6(getVenvPython(), [script], {
|
|
19507
19204
|
stdio: "inherit",
|
|
19508
19205
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -19515,8 +19212,8 @@ function setup() {
|
|
|
19515
19212
|
|
|
19516
19213
|
// src/commands/voice/start.ts
|
|
19517
19214
|
import { spawn as spawn7 } from "child_process";
|
|
19518
|
-
import { mkdirSync as
|
|
19519
|
-
import { join as
|
|
19215
|
+
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync37 } from "fs";
|
|
19216
|
+
import { join as join54 } from "path";
|
|
19520
19217
|
|
|
19521
19218
|
// src/commands/voice/buildDaemonEnv.ts
|
|
19522
19219
|
function buildDaemonEnv(options2) {
|
|
@@ -19549,12 +19246,12 @@ function spawnBackground(python, script, env) {
|
|
|
19549
19246
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
19550
19247
|
}
|
|
19551
19248
|
function start2(options2) {
|
|
19552
|
-
|
|
19249
|
+
mkdirSync20(voicePaths.dir, { recursive: true });
|
|
19553
19250
|
checkLockFile();
|
|
19554
19251
|
bootstrapVenv();
|
|
19555
19252
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
19556
19253
|
const env = buildDaemonEnv({ debug });
|
|
19557
|
-
const script =
|
|
19254
|
+
const script = join54(getPythonDir(), "voice_daemon.py");
|
|
19558
19255
|
const python = getVenvPython();
|
|
19559
19256
|
if (options2.foreground) {
|
|
19560
19257
|
spawnForeground(python, script, env);
|
|
@@ -19564,7 +19261,7 @@ function start2(options2) {
|
|
|
19564
19261
|
}
|
|
19565
19262
|
|
|
19566
19263
|
// src/commands/voice/status.ts
|
|
19567
|
-
import { existsSync as
|
|
19264
|
+
import { existsSync as existsSync45, readFileSync as readFileSync39 } from "fs";
|
|
19568
19265
|
function isProcessAlive3(pid) {
|
|
19569
19266
|
try {
|
|
19570
19267
|
process.kill(pid, 0);
|
|
@@ -19574,16 +19271,16 @@ function isProcessAlive3(pid) {
|
|
|
19574
19271
|
}
|
|
19575
19272
|
}
|
|
19576
19273
|
function readRecentLogs(count7) {
|
|
19577
|
-
if (!
|
|
19578
|
-
const lines =
|
|
19274
|
+
if (!existsSync45(voicePaths.log)) return [];
|
|
19275
|
+
const lines = readFileSync39(voicePaths.log, "utf8").trim().split("\n");
|
|
19579
19276
|
return lines.slice(-count7);
|
|
19580
19277
|
}
|
|
19581
19278
|
function status() {
|
|
19582
|
-
if (!
|
|
19279
|
+
if (!existsSync45(voicePaths.pid)) {
|
|
19583
19280
|
console.log("Voice daemon: not running (no PID file)");
|
|
19584
19281
|
return;
|
|
19585
19282
|
}
|
|
19586
|
-
const pid = Number.parseInt(
|
|
19283
|
+
const pid = Number.parseInt(readFileSync39(voicePaths.pid, "utf8").trim(), 10);
|
|
19587
19284
|
const alive = isProcessAlive3(pid);
|
|
19588
19285
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
19589
19286
|
const recent = readRecentLogs(5);
|
|
@@ -19602,13 +19299,13 @@ function status() {
|
|
|
19602
19299
|
}
|
|
19603
19300
|
|
|
19604
19301
|
// src/commands/voice/stop.ts
|
|
19605
|
-
import { existsSync as
|
|
19302
|
+
import { existsSync as existsSync46, readFileSync as readFileSync40, unlinkSync as unlinkSync17 } from "fs";
|
|
19606
19303
|
function stop2() {
|
|
19607
|
-
if (!
|
|
19304
|
+
if (!existsSync46(voicePaths.pid)) {
|
|
19608
19305
|
console.log("Voice daemon is not running (no PID file)");
|
|
19609
19306
|
return;
|
|
19610
19307
|
}
|
|
19611
|
-
const pid = Number.parseInt(
|
|
19308
|
+
const pid = Number.parseInt(readFileSync40(voicePaths.pid, "utf8").trim(), 10);
|
|
19612
19309
|
try {
|
|
19613
19310
|
process.kill(pid, "SIGTERM");
|
|
19614
19311
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -19621,7 +19318,7 @@ function stop2() {
|
|
|
19621
19318
|
}
|
|
19622
19319
|
try {
|
|
19623
19320
|
const lockFile = getLockFile();
|
|
19624
|
-
if (
|
|
19321
|
+
if (existsSync46(lockFile)) unlinkSync17(lockFile);
|
|
19625
19322
|
} catch {
|
|
19626
19323
|
}
|
|
19627
19324
|
console.log("Voice daemon stopped");
|
|
@@ -19640,7 +19337,7 @@ function registerVoice(program2) {
|
|
|
19640
19337
|
|
|
19641
19338
|
// src/commands/roam/auth.ts
|
|
19642
19339
|
import { randomBytes } from "crypto";
|
|
19643
|
-
import
|
|
19340
|
+
import chalk178 from "chalk";
|
|
19644
19341
|
|
|
19645
19342
|
// src/commands/roam/waitForCallback.ts
|
|
19646
19343
|
import { createServer as createServer3 } from "http";
|
|
@@ -19771,13 +19468,13 @@ async function auth() {
|
|
|
19771
19468
|
saveGlobalConfig(config);
|
|
19772
19469
|
const state = randomBytes(16).toString("hex");
|
|
19773
19470
|
console.log(
|
|
19774
|
-
|
|
19471
|
+
chalk178.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
19775
19472
|
);
|
|
19776
|
-
console.log(
|
|
19777
|
-
console.log(
|
|
19778
|
-
console.log(
|
|
19473
|
+
console.log(chalk178.white("http://localhost:14523/callback\n"));
|
|
19474
|
+
console.log(chalk178.blue("Opening browser for authorization..."));
|
|
19475
|
+
console.log(chalk178.dim("Waiting for authorization callback..."));
|
|
19779
19476
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
19780
|
-
console.log(
|
|
19477
|
+
console.log(chalk178.dim("Exchanging code for tokens..."));
|
|
19781
19478
|
const tokens = await exchangeToken({
|
|
19782
19479
|
code,
|
|
19783
19480
|
clientId,
|
|
@@ -19793,14 +19490,14 @@ async function auth() {
|
|
|
19793
19490
|
};
|
|
19794
19491
|
saveGlobalConfig(config);
|
|
19795
19492
|
console.log(
|
|
19796
|
-
|
|
19493
|
+
chalk178.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
19797
19494
|
);
|
|
19798
19495
|
}
|
|
19799
19496
|
|
|
19800
19497
|
// src/commands/roam/postRoamActivity.ts
|
|
19801
19498
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
19802
|
-
import { readdirSync as readdirSync9, readFileSync as
|
|
19803
|
-
import { join as
|
|
19499
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync41, statSync as statSync7 } from "fs";
|
|
19500
|
+
import { join as join55 } from "path";
|
|
19804
19501
|
function findPortFile(roamDir) {
|
|
19805
19502
|
let entries;
|
|
19806
19503
|
try {
|
|
@@ -19809,7 +19506,7 @@ function findPortFile(roamDir) {
|
|
|
19809
19506
|
return void 0;
|
|
19810
19507
|
}
|
|
19811
19508
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
19812
|
-
const path57 =
|
|
19509
|
+
const path57 = join55(roamDir, name);
|
|
19813
19510
|
try {
|
|
19814
19511
|
return { path: path57, mtimeMs: statSync7(path57).mtimeMs };
|
|
19815
19512
|
} catch {
|
|
@@ -19821,11 +19518,11 @@ function findPortFile(roamDir) {
|
|
|
19821
19518
|
function postRoamActivity(app, event) {
|
|
19822
19519
|
const appData = process.env.APPDATA;
|
|
19823
19520
|
if (!appData) return;
|
|
19824
|
-
const portFile = findPortFile(
|
|
19521
|
+
const portFile = findPortFile(join55(appData, "Roam"));
|
|
19825
19522
|
if (!portFile) return;
|
|
19826
19523
|
let port;
|
|
19827
19524
|
try {
|
|
19828
|
-
port =
|
|
19525
|
+
port = readFileSync41(portFile, "utf8").trim();
|
|
19829
19526
|
} catch {
|
|
19830
19527
|
return;
|
|
19831
19528
|
}
|
|
@@ -19967,15 +19664,15 @@ function runPreCommands(pre, cwd) {
|
|
|
19967
19664
|
|
|
19968
19665
|
// src/commands/run/spawnRunCommand.ts
|
|
19969
19666
|
import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
|
|
19970
|
-
import { existsSync as
|
|
19971
|
-
import { dirname as
|
|
19667
|
+
import { existsSync as existsSync47 } from "fs";
|
|
19668
|
+
import { dirname as dirname24, join as join56, resolve as resolve13 } from "path";
|
|
19972
19669
|
function resolveCommand2(command) {
|
|
19973
19670
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
19974
19671
|
try {
|
|
19975
19672
|
const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
19976
|
-
const gitRoot = resolve13(
|
|
19977
|
-
const gitBash =
|
|
19978
|
-
if (
|
|
19673
|
+
const gitRoot = resolve13(dirname24(gitPath), "..");
|
|
19674
|
+
const gitBash = join56(gitRoot, "bin", "bash.exe");
|
|
19675
|
+
if (existsSync47(gitBash)) return gitBash;
|
|
19979
19676
|
} catch {
|
|
19980
19677
|
}
|
|
19981
19678
|
return command;
|
|
@@ -20060,8 +19757,8 @@ async function run3(name, args) {
|
|
|
20060
19757
|
}
|
|
20061
19758
|
|
|
20062
19759
|
// src/commands/run/add.ts
|
|
20063
|
-
import { mkdirSync as
|
|
20064
|
-
import { join as
|
|
19760
|
+
import { mkdirSync as mkdirSync21, writeFileSync as writeFileSync38 } from "fs";
|
|
19761
|
+
import { join as join57 } from "path";
|
|
20065
19762
|
|
|
20066
19763
|
// src/commands/run/extractOption.ts
|
|
20067
19764
|
function extractOption(args, flag) {
|
|
@@ -20122,15 +19819,15 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
20122
19819
|
saveConfig(config);
|
|
20123
19820
|
}
|
|
20124
19821
|
function createCommandFile(name) {
|
|
20125
|
-
const dir =
|
|
20126
|
-
|
|
19822
|
+
const dir = join57(".claude", "commands");
|
|
19823
|
+
mkdirSync21(dir, { recursive: true });
|
|
20127
19824
|
const content = `---
|
|
20128
19825
|
description: Run ${name}
|
|
20129
19826
|
---
|
|
20130
19827
|
|
|
20131
19828
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
20132
19829
|
`;
|
|
20133
|
-
const filePath =
|
|
19830
|
+
const filePath = join57(dir, `${name}.md`);
|
|
20134
19831
|
writeFileSync38(filePath, content);
|
|
20135
19832
|
console.log(`Created command file: ${filePath}`);
|
|
20136
19833
|
}
|
|
@@ -20186,8 +19883,8 @@ function link2() {
|
|
|
20186
19883
|
}
|
|
20187
19884
|
|
|
20188
19885
|
// src/commands/run/remove.ts
|
|
20189
|
-
import { existsSync as
|
|
20190
|
-
import { join as
|
|
19886
|
+
import { existsSync as existsSync48, unlinkSync as unlinkSync18 } from "fs";
|
|
19887
|
+
import { join as join58 } from "path";
|
|
20191
19888
|
function findRemoveIndex() {
|
|
20192
19889
|
const idx = process.argv.indexOf("remove");
|
|
20193
19890
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -20202,8 +19899,8 @@ function parseRemoveName() {
|
|
|
20202
19899
|
return process.argv[idx + 1];
|
|
20203
19900
|
}
|
|
20204
19901
|
function deleteCommandFile(name) {
|
|
20205
|
-
const filePath =
|
|
20206
|
-
if (
|
|
19902
|
+
const filePath = join58(".claude", "commands", `${name}.md`);
|
|
19903
|
+
if (existsSync48(filePath)) {
|
|
20207
19904
|
unlinkSync18(filePath);
|
|
20208
19905
|
console.log(`Deleted command file: ${filePath}`);
|
|
20209
19906
|
}
|
|
@@ -20242,10 +19939,10 @@ function registerRun(program2) {
|
|
|
20242
19939
|
|
|
20243
19940
|
// src/commands/screenshot/index.ts
|
|
20244
19941
|
import { execSync as execSync50 } from "child_process";
|
|
20245
|
-
import { existsSync as
|
|
19942
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync22, unlinkSync as unlinkSync19, writeFileSync as writeFileSync39 } from "fs";
|
|
20246
19943
|
import { tmpdir as tmpdir7 } from "os";
|
|
20247
|
-
import { join as
|
|
20248
|
-
import
|
|
19944
|
+
import { join as join59, resolve as resolve15 } from "path";
|
|
19945
|
+
import chalk179 from "chalk";
|
|
20249
19946
|
|
|
20250
19947
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
20251
19948
|
var captureWindowPs1 = `
|
|
@@ -20374,14 +20071,14 @@ Write-Output $OutputPath
|
|
|
20374
20071
|
|
|
20375
20072
|
// src/commands/screenshot/index.ts
|
|
20376
20073
|
function buildOutputPath(outputDir, processName) {
|
|
20377
|
-
if (!
|
|
20378
|
-
|
|
20074
|
+
if (!existsSync49(outputDir)) {
|
|
20075
|
+
mkdirSync22(outputDir, { recursive: true });
|
|
20379
20076
|
}
|
|
20380
20077
|
const timestamp4 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
20381
20078
|
return resolve15(outputDir, `${processName}-${timestamp4}.png`);
|
|
20382
20079
|
}
|
|
20383
20080
|
function runPowerShellScript(processName, outputPath) {
|
|
20384
|
-
const scriptPath =
|
|
20081
|
+
const scriptPath = join59(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
20385
20082
|
writeFileSync39(scriptPath, captureWindowPs1, "utf8");
|
|
20386
20083
|
try {
|
|
20387
20084
|
execSync50(
|
|
@@ -20396,13 +20093,13 @@ function screenshot(processName) {
|
|
|
20396
20093
|
const config = loadConfig();
|
|
20397
20094
|
const outputDir = resolve15(config.screenshot.outputDir);
|
|
20398
20095
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
20399
|
-
console.log(
|
|
20096
|
+
console.log(chalk179.gray(`Capturing window for process "${processName}" ...`));
|
|
20400
20097
|
try {
|
|
20401
20098
|
runPowerShellScript(processName, outputPath);
|
|
20402
|
-
console.log(
|
|
20099
|
+
console.log(chalk179.green(`Screenshot saved: ${outputPath}`));
|
|
20403
20100
|
} catch (error) {
|
|
20404
20101
|
const msg = error instanceof Error ? error.message : String(error);
|
|
20405
|
-
console.error(
|
|
20102
|
+
console.error(chalk179.red(`Failed to capture screenshot: ${msg}`));
|
|
20406
20103
|
process.exit(1);
|
|
20407
20104
|
}
|
|
20408
20105
|
}
|
|
@@ -20458,7 +20155,7 @@ function applyLine(result, pending, line) {
|
|
|
20458
20155
|
}
|
|
20459
20156
|
|
|
20460
20157
|
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
20461
|
-
import { readFileSync as
|
|
20158
|
+
import { readFileSync as readFileSync42 } from "fs";
|
|
20462
20159
|
function reportStolenSocket(socketPid) {
|
|
20463
20160
|
if (!socketPid) return;
|
|
20464
20161
|
const filePid = readPidFile();
|
|
@@ -20470,7 +20167,7 @@ function reportStolenSocket(socketPid) {
|
|
|
20470
20167
|
function readPidFile() {
|
|
20471
20168
|
try {
|
|
20472
20169
|
const pid = Number.parseInt(
|
|
20473
|
-
|
|
20170
|
+
readFileSync42(daemonPaths.pid, "utf8").trim(),
|
|
20474
20171
|
10
|
|
20475
20172
|
);
|
|
20476
20173
|
return Number.isInteger(pid) ? pid : void 0;
|
|
@@ -20635,7 +20332,7 @@ function requestDrain(socket) {
|
|
|
20635
20332
|
}
|
|
20636
20333
|
|
|
20637
20334
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
20638
|
-
import { mkdirSync as
|
|
20335
|
+
import { mkdirSync as mkdirSync24 } from "fs";
|
|
20639
20336
|
|
|
20640
20337
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
20641
20338
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -20818,7 +20515,7 @@ var ClientHub = class extends Set {
|
|
|
20818
20515
|
import * as pty from "node-pty";
|
|
20819
20516
|
|
|
20820
20517
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
20821
|
-
import { chmodSync, existsSync as
|
|
20518
|
+
import { chmodSync, existsSync as existsSync50, statSync as statSync8 } from "fs";
|
|
20822
20519
|
import { createRequire as createRequire3 } from "module";
|
|
20823
20520
|
import path49 from "path";
|
|
20824
20521
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -20833,7 +20530,7 @@ function ensureSpawnHelperExecutable() {
|
|
|
20833
20530
|
`${process.platform}-${process.arch}`,
|
|
20834
20531
|
"spawn-helper"
|
|
20835
20532
|
);
|
|
20836
|
-
if (!
|
|
20533
|
+
if (!existsSync50(helper)) return;
|
|
20837
20534
|
const mode = statSync8(helper).mode;
|
|
20838
20535
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
20839
20536
|
}
|
|
@@ -21276,8 +20973,8 @@ function resumeSession(id2, sessionId, cwd, name) {
|
|
|
21276
20973
|
}
|
|
21277
20974
|
|
|
21278
20975
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
21279
|
-
import { existsSync as
|
|
21280
|
-
import { dirname as
|
|
20976
|
+
import { existsSync as existsSync51, mkdirSync as mkdirSync23, watch } from "fs";
|
|
20977
|
+
import { dirname as dirname25 } from "path";
|
|
21281
20978
|
|
|
21282
20979
|
// src/commands/sessions/daemon/applyReviewPause.ts
|
|
21283
20980
|
function applyReviewPause(session, activity2) {
|
|
@@ -21295,9 +20992,9 @@ var DEBOUNCE_MS = 50;
|
|
|
21295
20992
|
function watchActivity(session, notify2) {
|
|
21296
20993
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
21297
20994
|
const path57 = activityPath(session.id);
|
|
21298
|
-
const dir =
|
|
20995
|
+
const dir = dirname25(path57);
|
|
21299
20996
|
try {
|
|
21300
|
-
|
|
20997
|
+
mkdirSync23(dir, { recursive: true });
|
|
21301
20998
|
} catch {
|
|
21302
20999
|
return;
|
|
21303
21000
|
}
|
|
@@ -21318,7 +21015,7 @@ function watchActivity(session, notify2) {
|
|
|
21318
21015
|
if (timer) clearTimeout(timer);
|
|
21319
21016
|
timer = setTimeout(read, DEBOUNCE_MS);
|
|
21320
21017
|
});
|
|
21321
|
-
if (
|
|
21018
|
+
if (existsSync51(path57)) read();
|
|
21322
21019
|
}
|
|
21323
21020
|
function refreshActivity(session) {
|
|
21324
21021
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -22588,7 +22285,7 @@ function handleConnection(socket, manager) {
|
|
|
22588
22285
|
import { unlinkSync as unlinkSync20, writeFileSync as writeFileSync40 } from "fs";
|
|
22589
22286
|
|
|
22590
22287
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
22591
|
-
import { readFileSync as
|
|
22288
|
+
import { readFileSync as readFileSync43 } from "fs";
|
|
22592
22289
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
22593
22290
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
22594
22291
|
const timer = setInterval(() => {
|
|
@@ -22599,7 +22296,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
22599
22296
|
}
|
|
22600
22297
|
function ownsPidFile() {
|
|
22601
22298
|
try {
|
|
22602
|
-
return
|
|
22299
|
+
return readFileSync43(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
22603
22300
|
} catch {
|
|
22604
22301
|
return false;
|
|
22605
22302
|
}
|
|
@@ -22687,7 +22384,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
22687
22384
|
|
|
22688
22385
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
22689
22386
|
async function runDaemon() {
|
|
22690
|
-
|
|
22387
|
+
mkdirSync24(daemonPaths.dir, { recursive: true });
|
|
22691
22388
|
daemonLog(
|
|
22692
22389
|
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
22693
22390
|
);
|
|
@@ -22727,7 +22424,7 @@ function registerDaemon(program2) {
|
|
|
22727
22424
|
|
|
22728
22425
|
// src/commands/sessions/summarise/index.ts
|
|
22729
22426
|
import * as fs35 from "fs";
|
|
22730
|
-
import
|
|
22427
|
+
import chalk180 from "chalk";
|
|
22731
22428
|
|
|
22732
22429
|
// src/commands/sessions/summarise/shared.ts
|
|
22733
22430
|
import * as fs33 from "fs";
|
|
@@ -22878,25 +22575,25 @@ ${firstMessage}`);
|
|
|
22878
22575
|
}
|
|
22879
22576
|
|
|
22880
22577
|
// src/commands/sessions/summarise/index.ts
|
|
22881
|
-
async function
|
|
22578
|
+
async function summarise2(options2) {
|
|
22882
22579
|
const files = await discoverSessionFiles();
|
|
22883
22580
|
if (files.length === 0) {
|
|
22884
|
-
console.log(
|
|
22581
|
+
console.log(chalk180.yellow("No sessions found."));
|
|
22885
22582
|
return;
|
|
22886
22583
|
}
|
|
22887
22584
|
const toProcess = selectCandidates(files, options2);
|
|
22888
22585
|
if (toProcess.length === 0) {
|
|
22889
|
-
console.log(
|
|
22586
|
+
console.log(chalk180.green("All sessions already summarised."));
|
|
22890
22587
|
return;
|
|
22891
22588
|
}
|
|
22892
22589
|
console.log(
|
|
22893
|
-
|
|
22590
|
+
chalk180.cyan(
|
|
22894
22591
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
22895
22592
|
)
|
|
22896
22593
|
);
|
|
22897
22594
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
22898
22595
|
console.log(
|
|
22899
|
-
|
|
22596
|
+
chalk180.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk180.yellow(`, ${failed2} skipped`) : "")
|
|
22900
22597
|
);
|
|
22901
22598
|
}
|
|
22902
22599
|
function selectCandidates(files, options2) {
|
|
@@ -22916,16 +22613,16 @@ function processSessions(files) {
|
|
|
22916
22613
|
let failed2 = 0;
|
|
22917
22614
|
for (let i = 0; i < files.length; i++) {
|
|
22918
22615
|
const file = files[i];
|
|
22919
|
-
process.stdout.write(
|
|
22616
|
+
process.stdout.write(chalk180.dim(` [${i + 1}/${files.length}] `));
|
|
22920
22617
|
const summary = summariseSession(file);
|
|
22921
22618
|
if (summary) {
|
|
22922
22619
|
writeSummary(file, summary);
|
|
22923
22620
|
succeeded++;
|
|
22924
|
-
process.stdout.write(`${
|
|
22621
|
+
process.stdout.write(`${chalk180.green("\u2713")} ${summary}
|
|
22925
22622
|
`);
|
|
22926
22623
|
} else {
|
|
22927
22624
|
failed2++;
|
|
22928
|
-
process.stdout.write(` ${
|
|
22625
|
+
process.stdout.write(` ${chalk180.yellow("skip")}
|
|
22929
22626
|
`);
|
|
22930
22627
|
}
|
|
22931
22628
|
}
|
|
@@ -22936,17 +22633,17 @@ function processSessions(files) {
|
|
|
22936
22633
|
function registerSessions(program2) {
|
|
22937
22634
|
const cmd = program2.command("sessions").description("Web dashboard for Claude Code sessions").option("--no-open", "Do not open a browser on startup").action((options2) => web({ port: "3100", open: options2.open }));
|
|
22938
22635
|
cmd.command("web").description("Start the sessions web dashboard").option("-p, --port <number>", "Port to listen on", "3100").option("--no-open", "Do not open a browser on startup").action(web);
|
|
22939
|
-
cmd.command("summarise").description("Generate one-line summaries for Claude sessions").option("-f, --force", "Re-generate all summaries, even existing ones").option("-n, --limit <count>", "Maximum number of sessions to summarise").action(
|
|
22636
|
+
cmd.command("summarise").description("Generate one-line summaries for Claude sessions").option("-f, --force", "Re-generate all summaries, even existing ones").option("-n, --limit <count>", "Maximum number of sessions to summarise").action(summarise2);
|
|
22940
22637
|
cmd.command("set-status <status>").description(
|
|
22941
22638
|
"Report the current session's status to the sessions daemon (used by Claude Code hooks)"
|
|
22942
22639
|
).action(setSessionStatus);
|
|
22943
22640
|
}
|
|
22944
22641
|
|
|
22945
22642
|
// src/commands/statusLine.ts
|
|
22946
|
-
import
|
|
22643
|
+
import chalk182 from "chalk";
|
|
22947
22644
|
|
|
22948
22645
|
// src/commands/buildLimitsSegment.ts
|
|
22949
|
-
import
|
|
22646
|
+
import chalk181 from "chalk";
|
|
22950
22647
|
|
|
22951
22648
|
// src/shared/rateLimitLevel.ts
|
|
22952
22649
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -22977,9 +22674,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
22977
22674
|
|
|
22978
22675
|
// src/commands/buildLimitsSegment.ts
|
|
22979
22676
|
var LEVEL_COLOR = {
|
|
22980
|
-
ok:
|
|
22981
|
-
warn:
|
|
22982
|
-
over:
|
|
22677
|
+
ok: chalk181.green,
|
|
22678
|
+
warn: chalk181.yellow,
|
|
22679
|
+
over: chalk181.red
|
|
22983
22680
|
};
|
|
22984
22681
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
22985
22682
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -23019,14 +22716,14 @@ async function relayRateLimits(rateLimits) {
|
|
|
23019
22716
|
}
|
|
23020
22717
|
|
|
23021
22718
|
// src/commands/statusLine.ts
|
|
23022
|
-
|
|
22719
|
+
chalk182.level = 3;
|
|
23023
22720
|
function formatNumber(num) {
|
|
23024
22721
|
return num.toLocaleString("en-US");
|
|
23025
22722
|
}
|
|
23026
22723
|
function colorizePercent(pct) {
|
|
23027
22724
|
const label2 = `${Math.round(pct)}%`;
|
|
23028
|
-
if (pct > 80) return
|
|
23029
|
-
if (pct > 40) return
|
|
22725
|
+
if (pct > 80) return chalk182.red(label2);
|
|
22726
|
+
if (pct > 40) return chalk182.yellow(label2);
|
|
23030
22727
|
return label2;
|
|
23031
22728
|
}
|
|
23032
22729
|
async function statusLine() {
|
|
@@ -23050,7 +22747,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
23050
22747
|
// src/commands/sync/syncClaudeMd.ts
|
|
23051
22748
|
import * as fs36 from "fs";
|
|
23052
22749
|
import * as path53 from "path";
|
|
23053
|
-
import
|
|
22750
|
+
import chalk183 from "chalk";
|
|
23054
22751
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
23055
22752
|
const source = path53.join(claudeDir, "CLAUDE.md");
|
|
23056
22753
|
const target = path53.join(targetBase, "CLAUDE.md");
|
|
@@ -23059,12 +22756,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
23059
22756
|
const targetContent = fs36.readFileSync(target, "utf8");
|
|
23060
22757
|
if (sourceContent !== targetContent) {
|
|
23061
22758
|
console.log(
|
|
23062
|
-
|
|
22759
|
+
chalk183.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
23063
22760
|
);
|
|
23064
22761
|
console.log();
|
|
23065
22762
|
printDiff(targetContent, sourceContent);
|
|
23066
22763
|
const confirm = options2?.yes || await promptConfirm(
|
|
23067
|
-
|
|
22764
|
+
chalk183.red("Overwrite existing CLAUDE.md?"),
|
|
23068
22765
|
false
|
|
23069
22766
|
);
|
|
23070
22767
|
if (!confirm) {
|
|
@@ -23080,7 +22777,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
23080
22777
|
// src/commands/sync/syncSettings.ts
|
|
23081
22778
|
import * as fs37 from "fs";
|
|
23082
22779
|
import * as path54 from "path";
|
|
23083
|
-
import
|
|
22780
|
+
import chalk184 from "chalk";
|
|
23084
22781
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
23085
22782
|
const source = path54.join(claudeDir, "settings.json");
|
|
23086
22783
|
const target = path54.join(targetBase, "settings.json");
|
|
@@ -23096,14 +22793,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
23096
22793
|
if (mergedContent !== normalizedTarget) {
|
|
23097
22794
|
if (!options2?.yes) {
|
|
23098
22795
|
console.log(
|
|
23099
|
-
|
|
22796
|
+
chalk184.yellow(
|
|
23100
22797
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
23101
22798
|
)
|
|
23102
22799
|
);
|
|
23103
22800
|
console.log();
|
|
23104
22801
|
printDiff(targetContent, mergedContent);
|
|
23105
22802
|
const confirm = await promptConfirm(
|
|
23106
|
-
|
|
22803
|
+
chalk184.red("Overwrite existing settings.json?"),
|
|
23107
22804
|
false
|
|
23108
22805
|
);
|
|
23109
22806
|
if (!confirm) {
|