@staff0rd/assist 0.158.1 → 0.159.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claude/settings.json +7 -1
- package/dist/index.js +403 -319
- 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.159.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -256,6 +256,45 @@ async function exitOnCancel(promise) {
|
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
// src/commands/backlog/acquireLock.ts
|
|
260
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
261
|
+
import { join as join2 } from "path";
|
|
262
|
+
function getLockPath(itemId) {
|
|
263
|
+
return join2(process.cwd(), `.assist-lock-${itemId}.json`);
|
|
264
|
+
}
|
|
265
|
+
function isProcessAlive(pid) {
|
|
266
|
+
try {
|
|
267
|
+
process.kill(pid, 0);
|
|
268
|
+
return true;
|
|
269
|
+
} catch {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function isLockedByOther(itemId) {
|
|
274
|
+
const lockPath = getLockPath(itemId);
|
|
275
|
+
if (!existsSync2(lockPath)) return false;
|
|
276
|
+
try {
|
|
277
|
+
const lock = JSON.parse(readFileSync2(lockPath, "utf-8"));
|
|
278
|
+
if (lock.pid === process.pid) return false;
|
|
279
|
+
return isProcessAlive(lock.pid);
|
|
280
|
+
} catch {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function acquireLock(itemId) {
|
|
285
|
+
writeFileSync2(
|
|
286
|
+
getLockPath(itemId),
|
|
287
|
+
JSON.stringify({ pid: process.pid, timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
function releaseLock(itemId) {
|
|
291
|
+
const lockPath = getLockPath(itemId);
|
|
292
|
+
try {
|
|
293
|
+
unlinkSync(lockPath);
|
|
294
|
+
} catch {
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
259
298
|
// src/commands/backlog/list/shared.ts
|
|
260
299
|
import chalk4 from "chalk";
|
|
261
300
|
function statusIcon(status2) {
|
|
@@ -406,7 +445,7 @@ function buildReviewPhase() {
|
|
|
406
445
|
import chalk6 from "chalk";
|
|
407
446
|
|
|
408
447
|
// src/commands/backlog/resolvePhaseResult.ts
|
|
409
|
-
import { existsSync as
|
|
448
|
+
import { existsSync as existsSync3, unlinkSync as unlinkSync2 } from "fs";
|
|
410
449
|
import chalk5 from "chalk";
|
|
411
450
|
|
|
412
451
|
// src/commands/backlog/handleIncompletePhase.ts
|
|
@@ -426,27 +465,27 @@ async function handleIncompletePhase() {
|
|
|
426
465
|
}
|
|
427
466
|
|
|
428
467
|
// src/commands/backlog/writeSignal.ts
|
|
429
|
-
import { writeFileSync as
|
|
430
|
-
import { join as
|
|
468
|
+
import { writeFileSync as writeFileSync3 } from "fs";
|
|
469
|
+
import { join as join3 } from "path";
|
|
431
470
|
var SIGNAL_FILE = ".assist-signal.json";
|
|
432
471
|
function getSignalPath() {
|
|
433
|
-
return
|
|
472
|
+
return join3(process.cwd(), SIGNAL_FILE);
|
|
434
473
|
}
|
|
435
474
|
function writeSignal(event, data) {
|
|
436
475
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
437
476
|
const signal = { event, ...sessionId && { sessionId }, ...data };
|
|
438
|
-
|
|
477
|
+
writeFileSync3(getSignalPath(), JSON.stringify(signal));
|
|
439
478
|
}
|
|
440
479
|
|
|
441
480
|
// src/commands/backlog/resolvePhaseResult.ts
|
|
442
481
|
function cleanupSignal() {
|
|
443
482
|
const statusPath = getSignalPath();
|
|
444
|
-
if (
|
|
445
|
-
|
|
483
|
+
if (existsSync3(statusPath)) {
|
|
484
|
+
unlinkSync2(statusPath);
|
|
446
485
|
}
|
|
447
486
|
}
|
|
448
487
|
async function resolvePhaseResult(phaseIndex) {
|
|
449
|
-
if (!
|
|
488
|
+
if (!existsSync3(getSignalPath())) {
|
|
450
489
|
const action = await handleIncompletePhase();
|
|
451
490
|
if (action === "abort") return -1;
|
|
452
491
|
return action === "skip" ? 1 : 0;
|
|
@@ -475,15 +514,15 @@ function spawnClaude(prompt, options2 = {}) {
|
|
|
475
514
|
}
|
|
476
515
|
|
|
477
516
|
// src/commands/backlog/watchForMarker.ts
|
|
478
|
-
import { existsSync as
|
|
517
|
+
import { existsSync as existsSync5, unwatchFile, watchFile } from "fs";
|
|
479
518
|
|
|
480
519
|
// src/commands/backlog/readSignal.ts
|
|
481
|
-
import { existsSync as
|
|
520
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
482
521
|
function readSignal() {
|
|
483
522
|
const path50 = getSignalPath();
|
|
484
|
-
if (!
|
|
523
|
+
if (!existsSync4(path50)) return void 0;
|
|
485
524
|
try {
|
|
486
|
-
return JSON.parse(
|
|
525
|
+
return JSON.parse(readFileSync3(path50, "utf-8"));
|
|
487
526
|
} catch {
|
|
488
527
|
return void 0;
|
|
489
528
|
}
|
|
@@ -494,7 +533,7 @@ function watchForMarker(child) {
|
|
|
494
533
|
const statusPath = getSignalPath();
|
|
495
534
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
496
535
|
watchFile(statusPath, { interval: 1e3 }, () => {
|
|
497
|
-
if (!
|
|
536
|
+
if (!existsSync5(statusPath)) return;
|
|
498
537
|
const signal = readSignal();
|
|
499
538
|
if (signal && (!signal.sessionId || signal.sessionId === sessionId)) {
|
|
500
539
|
unwatchFile(statusPath);
|
|
@@ -571,13 +610,16 @@ async function run(id, spawnOptions) {
|
|
|
571
610
|
if (!prepared) return false;
|
|
572
611
|
const { item, plan: plan2, startPhase } = prepared;
|
|
573
612
|
setStatus(id, "in-progress");
|
|
613
|
+
acquireLock(item.id);
|
|
574
614
|
logProgress(id, item.name, startPhase, plan2.length);
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
615
|
+
try {
|
|
616
|
+
if (!await runPhases(item, startPhase, plan2, spawnOptions)) return false;
|
|
617
|
+
if (!await runReview(item, plan2, spawnOptions)) return false;
|
|
618
|
+
ensureDone(id);
|
|
619
|
+
return true;
|
|
620
|
+
} finally {
|
|
621
|
+
releaseLock(item.id);
|
|
622
|
+
}
|
|
581
623
|
}
|
|
582
624
|
function logProgress(id, name, startPhase, total) {
|
|
583
625
|
console.log(chalk8.bold(`Running plan for #${id}: ${name}`));
|
|
@@ -616,6 +658,11 @@ async function runReview(item, plan2, spawnOptions) {
|
|
|
616
658
|
}
|
|
617
659
|
|
|
618
660
|
// src/commands/backlog/next.ts
|
|
661
|
+
function findResumable(items) {
|
|
662
|
+
return items.find(
|
|
663
|
+
(i) => i.status === "in-progress" && i.plan && !isLockedByOther(i.id)
|
|
664
|
+
);
|
|
665
|
+
}
|
|
619
666
|
async function selectItem(todo) {
|
|
620
667
|
const choices = todo.map((i) => `${typeLabel(i.type)} #${i.id}: ${i.name}`);
|
|
621
668
|
const { selected } = await exitOnCancel(
|
|
@@ -631,7 +678,7 @@ async function selectItem(todo) {
|
|
|
631
678
|
async function next(options2) {
|
|
632
679
|
while (true) {
|
|
633
680
|
const items = loadBacklog();
|
|
634
|
-
const inProgress = items
|
|
681
|
+
const inProgress = findResumable(items);
|
|
635
682
|
if (inProgress) {
|
|
636
683
|
console.log(
|
|
637
684
|
chalk9.bold(
|
|
@@ -802,11 +849,11 @@ async function start(id) {
|
|
|
802
849
|
|
|
803
850
|
// src/shared/web.ts
|
|
804
851
|
import { exec } from "child_process";
|
|
805
|
-
import { readFileSync as
|
|
852
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
806
853
|
import {
|
|
807
854
|
createServer
|
|
808
855
|
} from "http";
|
|
809
|
-
import { dirname, join as
|
|
856
|
+
import { dirname, join as join4 } from "path";
|
|
810
857
|
import { fileURLToPath } from "url";
|
|
811
858
|
import chalk15 from "chalk";
|
|
812
859
|
function respondJson(res, status2, data) {
|
|
@@ -818,7 +865,7 @@ function createBundleHandler(importMetaUrl, bundlePath) {
|
|
|
818
865
|
let cache;
|
|
819
866
|
return (_req, res) => {
|
|
820
867
|
if (!cache) {
|
|
821
|
-
cache =
|
|
868
|
+
cache = readFileSync4(join4(dir, bundlePath), "utf-8");
|
|
822
869
|
}
|
|
823
870
|
res.writeHead(200, { "Content-Type": "application/javascript" });
|
|
824
871
|
res.end(cache);
|
|
@@ -1020,19 +1067,19 @@ async function launchMode(slashCommand) {
|
|
|
1020
1067
|
import { execSync } from "child_process";
|
|
1021
1068
|
|
|
1022
1069
|
// src/shared/loadConfig.ts
|
|
1023
|
-
import { existsSync as
|
|
1070
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
1024
1071
|
import { homedir } from "os";
|
|
1025
|
-
import { basename, dirname as dirname2, join as
|
|
1072
|
+
import { basename, dirname as dirname2, join as join5 } from "path";
|
|
1026
1073
|
import chalk17 from "chalk";
|
|
1027
1074
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
1028
1075
|
|
|
1029
1076
|
// src/shared/loadRawYaml.ts
|
|
1030
|
-
import { existsSync as
|
|
1077
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
1031
1078
|
import { parse as parseYaml2 } from "yaml";
|
|
1032
1079
|
function loadRawYaml(path50) {
|
|
1033
|
-
if (!
|
|
1080
|
+
if (!existsSync6(path50)) return {};
|
|
1034
1081
|
try {
|
|
1035
|
-
const content =
|
|
1082
|
+
const content = readFileSync5(path50, "utf-8");
|
|
1036
1083
|
return parseYaml2(content) || {};
|
|
1037
1084
|
} catch {
|
|
1038
1085
|
return {};
|
|
@@ -1153,10 +1200,10 @@ var assistConfigSchema = z2.strictObject({
|
|
|
1153
1200
|
function findConfigUp(startDir) {
|
|
1154
1201
|
let current = startDir;
|
|
1155
1202
|
while (current !== dirname2(current)) {
|
|
1156
|
-
const claudePath =
|
|
1157
|
-
if (
|
|
1158
|
-
const rootPath =
|
|
1159
|
-
if (
|
|
1203
|
+
const claudePath = join5(current, ".claude", "assist.yml");
|
|
1204
|
+
if (existsSync7(claudePath)) return claudePath;
|
|
1205
|
+
const rootPath = join5(current, "assist.yml");
|
|
1206
|
+
if (existsSync7(rootPath)) return rootPath;
|
|
1160
1207
|
current = dirname2(current);
|
|
1161
1208
|
}
|
|
1162
1209
|
return null;
|
|
@@ -1164,10 +1211,10 @@ function findConfigUp(startDir) {
|
|
|
1164
1211
|
function getConfigPath() {
|
|
1165
1212
|
const found = findConfigUp(process.cwd());
|
|
1166
1213
|
if (found) return found;
|
|
1167
|
-
return
|
|
1214
|
+
return join5(process.cwd(), "assist.yml");
|
|
1168
1215
|
}
|
|
1169
1216
|
function getGlobalConfigPath() {
|
|
1170
|
-
return
|
|
1217
|
+
return join5(homedir(), ".assist.yml");
|
|
1171
1218
|
}
|
|
1172
1219
|
function loadConfig() {
|
|
1173
1220
|
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
@@ -1182,21 +1229,21 @@ function loadGlobalConfigRaw() {
|
|
|
1182
1229
|
return loadRawYaml(getGlobalConfigPath());
|
|
1183
1230
|
}
|
|
1184
1231
|
function saveGlobalConfig(config) {
|
|
1185
|
-
|
|
1232
|
+
writeFileSync4(getGlobalConfigPath(), stringifyYaml2(config, { lineWidth: 0 }));
|
|
1186
1233
|
}
|
|
1187
1234
|
function saveConfig(config) {
|
|
1188
1235
|
const configPath = getConfigPath();
|
|
1189
|
-
|
|
1236
|
+
writeFileSync4(configPath, stringifyYaml2(config, { lineWidth: 0 }));
|
|
1190
1237
|
}
|
|
1191
1238
|
function getRepoName() {
|
|
1192
1239
|
const config = loadConfig();
|
|
1193
1240
|
if (config.devlog?.name) {
|
|
1194
1241
|
return config.devlog.name;
|
|
1195
1242
|
}
|
|
1196
|
-
const packageJsonPath =
|
|
1197
|
-
if (
|
|
1243
|
+
const packageJsonPath = join5(process.cwd(), "package.json");
|
|
1244
|
+
if (existsSync7(packageJsonPath)) {
|
|
1198
1245
|
try {
|
|
1199
|
-
const content =
|
|
1246
|
+
const content = readFileSync6(packageJsonPath, "utf-8");
|
|
1200
1247
|
const pkg = JSON.parse(content);
|
|
1201
1248
|
if (pkg.name) {
|
|
1202
1249
|
return pkg.name;
|
|
@@ -1511,10 +1558,10 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
1511
1558
|
|
|
1512
1559
|
// src/commands/verify/installPackage.ts
|
|
1513
1560
|
import { execSync as execSync3 } from "child_process";
|
|
1514
|
-
import { writeFileSync as
|
|
1561
|
+
import { writeFileSync as writeFileSync5 } from "fs";
|
|
1515
1562
|
import chalk21 from "chalk";
|
|
1516
1563
|
function writePackageJson(filePath, pkg) {
|
|
1517
|
-
|
|
1564
|
+
writeFileSync5(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
1518
1565
|
`);
|
|
1519
1566
|
}
|
|
1520
1567
|
function addScript(pkg, name, command) {
|
|
@@ -1619,23 +1666,23 @@ import * as path3 from "path";
|
|
|
1619
1666
|
import chalk25 from "chalk";
|
|
1620
1667
|
|
|
1621
1668
|
// src/commands/verify/addToKnipIgnoreBinaries.ts
|
|
1622
|
-
import { existsSync as
|
|
1623
|
-
import { join as
|
|
1669
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
1670
|
+
import { join as join7 } from "path";
|
|
1624
1671
|
import chalk24 from "chalk";
|
|
1625
1672
|
function loadKnipConfig(knipJsonPath) {
|
|
1626
|
-
if (
|
|
1627
|
-
return JSON.parse(
|
|
1673
|
+
if (existsSync9(knipJsonPath)) {
|
|
1674
|
+
return JSON.parse(readFileSync8(knipJsonPath, "utf-8"));
|
|
1628
1675
|
}
|
|
1629
1676
|
return { $schema: "https://unpkg.com/knip@5/schema.json" };
|
|
1630
1677
|
}
|
|
1631
1678
|
function addToKnipIgnoreBinaries(cwd, binary) {
|
|
1632
|
-
const knipJsonPath =
|
|
1679
|
+
const knipJsonPath = join7(cwd, "knip.json");
|
|
1633
1680
|
try {
|
|
1634
1681
|
const knipConfig = loadKnipConfig(knipJsonPath);
|
|
1635
1682
|
const ignoreBinaries = knipConfig.ignoreBinaries ?? [];
|
|
1636
1683
|
if (!ignoreBinaries.includes(binary)) {
|
|
1637
1684
|
knipConfig.ignoreBinaries = [...ignoreBinaries, binary];
|
|
1638
|
-
|
|
1685
|
+
writeFileSync6(
|
|
1639
1686
|
knipJsonPath,
|
|
1640
1687
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
1641
1688
|
`
|
|
@@ -1677,8 +1724,8 @@ import chalk29 from "chalk";
|
|
|
1677
1724
|
|
|
1678
1725
|
// src/commands/lint/init.ts
|
|
1679
1726
|
import { execSync as execSync5 } from "child_process";
|
|
1680
|
-
import { existsSync as
|
|
1681
|
-
import { dirname as dirname7, join as
|
|
1727
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
|
|
1728
|
+
import { dirname as dirname7, join as join8 } from "path";
|
|
1682
1729
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1683
1730
|
import chalk28 from "chalk";
|
|
1684
1731
|
|
|
@@ -1703,10 +1750,10 @@ async function promptConfirm(message, initial = true) {
|
|
|
1703
1750
|
|
|
1704
1751
|
// src/shared/removeEslint/index.ts
|
|
1705
1752
|
import { execSync as execSync4 } from "child_process";
|
|
1706
|
-
import { existsSync as
|
|
1753
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
1707
1754
|
|
|
1708
1755
|
// src/shared/removeEslint/removeEslintConfigFiles.ts
|
|
1709
|
-
import { existsSync as
|
|
1756
|
+
import { existsSync as existsSync10, unlinkSync as unlinkSync3 } from "fs";
|
|
1710
1757
|
var ESLINT_CONFIG_FILES = [
|
|
1711
1758
|
"eslint.config.js",
|
|
1712
1759
|
"eslint.config.mjs",
|
|
@@ -1722,8 +1769,8 @@ var ESLINT_CONFIG_FILES = [
|
|
|
1722
1769
|
function removeEslintConfigFiles() {
|
|
1723
1770
|
let removed = false;
|
|
1724
1771
|
for (const configFile of ESLINT_CONFIG_FILES) {
|
|
1725
|
-
if (
|
|
1726
|
-
|
|
1772
|
+
if (existsSync10(configFile)) {
|
|
1773
|
+
unlinkSync3(configFile);
|
|
1727
1774
|
console.log(`Removed ${configFile}`);
|
|
1728
1775
|
removed = true;
|
|
1729
1776
|
}
|
|
@@ -1744,16 +1791,16 @@ function removeEslint(options2 = {}) {
|
|
|
1744
1791
|
}
|
|
1745
1792
|
function removeEslintFromPackageJson(options2) {
|
|
1746
1793
|
const packageJsonPath = "package.json";
|
|
1747
|
-
if (!
|
|
1794
|
+
if (!existsSync11(packageJsonPath)) {
|
|
1748
1795
|
return false;
|
|
1749
1796
|
}
|
|
1750
|
-
const packageJson = JSON.parse(
|
|
1797
|
+
const packageJson = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
|
|
1751
1798
|
let modified = false;
|
|
1752
1799
|
modified = removeEslintDeps(packageJson.dependencies) || modified;
|
|
1753
1800
|
modified = removeEslintDeps(packageJson.devDependencies) || modified;
|
|
1754
1801
|
modified = removeEslintScripts(packageJson.scripts, options2) || modified;
|
|
1755
1802
|
if (modified) {
|
|
1756
|
-
|
|
1803
|
+
writeFileSync7(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
1757
1804
|
`);
|
|
1758
1805
|
console.log("Removed eslint references from package.json");
|
|
1759
1806
|
}
|
|
@@ -1817,17 +1864,17 @@ var __dirname2 = dirname7(fileURLToPath2(import.meta.url));
|
|
|
1817
1864
|
async function init() {
|
|
1818
1865
|
removeEslint();
|
|
1819
1866
|
const biomeConfigPath = "biome.json";
|
|
1820
|
-
if (!
|
|
1867
|
+
if (!existsSync12(biomeConfigPath)) {
|
|
1821
1868
|
console.log("Initializing Biome...");
|
|
1822
1869
|
execSync5("npx @biomejs/biome init", { stdio: "inherit" });
|
|
1823
1870
|
}
|
|
1824
|
-
if (!
|
|
1871
|
+
if (!existsSync12(biomeConfigPath)) {
|
|
1825
1872
|
console.log("No biome.json found, skipping linter config");
|
|
1826
1873
|
return;
|
|
1827
1874
|
}
|
|
1828
|
-
const linterConfigPath =
|
|
1829
|
-
const linterConfig = JSON.parse(
|
|
1830
|
-
const biomeConfig = JSON.parse(
|
|
1875
|
+
const linterConfigPath = join8(__dirname2, "commands/lint/biome.linter.json");
|
|
1876
|
+
const linterConfig = JSON.parse(readFileSync10(linterConfigPath, "utf-8"));
|
|
1877
|
+
const biomeConfig = JSON.parse(readFileSync10(biomeConfigPath, "utf-8"));
|
|
1831
1878
|
const oldContent = `${JSON.stringify(biomeConfig, null, 2)}
|
|
1832
1879
|
`;
|
|
1833
1880
|
biomeConfig.linter = linterConfig.linter;
|
|
@@ -1848,7 +1895,7 @@ async function init() {
|
|
|
1848
1895
|
console.log("Skipped biome.json update");
|
|
1849
1896
|
return;
|
|
1850
1897
|
}
|
|
1851
|
-
|
|
1898
|
+
writeFileSync8(biomeConfigPath, newContent);
|
|
1852
1899
|
console.log("Updated biome.json with linter config");
|
|
1853
1900
|
}
|
|
1854
1901
|
|
|
@@ -2862,11 +2909,11 @@ async function run2(options2 = {}) {
|
|
|
2862
2909
|
|
|
2863
2910
|
// src/commands/new/registerNew/initGit.ts
|
|
2864
2911
|
import { execSync as execSync9 } from "child_process";
|
|
2865
|
-
import { writeFileSync as
|
|
2912
|
+
import { writeFileSync as writeFileSync10 } from "fs";
|
|
2866
2913
|
function initGit() {
|
|
2867
2914
|
console.log("Initializing git repository...");
|
|
2868
2915
|
execSync9("git init", { stdio: "inherit" });
|
|
2869
|
-
|
|
2916
|
+
writeFileSync10(".gitignore", "dist\nnode_modules\n");
|
|
2870
2917
|
}
|
|
2871
2918
|
|
|
2872
2919
|
// src/commands/new/registerNew/newCli/initPackageJson.ts
|
|
@@ -2885,10 +2932,10 @@ function initPackageJson(name) {
|
|
|
2885
2932
|
}
|
|
2886
2933
|
|
|
2887
2934
|
// src/commands/new/registerNew/newCli/writeCliTemplate.ts
|
|
2888
|
-
import { mkdirSync as mkdirSync2, writeFileSync as
|
|
2935
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync11 } from "fs";
|
|
2889
2936
|
function writeCliTemplate(name) {
|
|
2890
2937
|
console.log("Writing tsconfig.json...");
|
|
2891
|
-
|
|
2938
|
+
writeFileSync11(
|
|
2892
2939
|
"tsconfig.json",
|
|
2893
2940
|
JSON.stringify(
|
|
2894
2941
|
{
|
|
@@ -2912,7 +2959,7 @@ function writeCliTemplate(name) {
|
|
|
2912
2959
|
)
|
|
2913
2960
|
);
|
|
2914
2961
|
console.log("Writing tsup.config.ts...");
|
|
2915
|
-
|
|
2962
|
+
writeFileSync11(
|
|
2916
2963
|
"tsup.config.ts",
|
|
2917
2964
|
`import { defineConfig } from "tsup";
|
|
2918
2965
|
export default defineConfig({
|
|
@@ -2927,7 +2974,7 @@ export default defineConfig({
|
|
|
2927
2974
|
);
|
|
2928
2975
|
console.log("Writing src/index.ts...");
|
|
2929
2976
|
mkdirSync2("src", { recursive: true });
|
|
2930
|
-
|
|
2977
|
+
writeFileSync11(
|
|
2931
2978
|
"src/index.ts",
|
|
2932
2979
|
`#!/usr/bin/env node
|
|
2933
2980
|
import { Command } from "commander";
|
|
@@ -2955,7 +3002,7 @@ async function newCli() {
|
|
|
2955
3002
|
|
|
2956
3003
|
// src/commands/new/registerNew/newProject.ts
|
|
2957
3004
|
import { execSync as execSync13 } from "child_process";
|
|
2958
|
-
import { existsSync as
|
|
3005
|
+
import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
|
|
2959
3006
|
|
|
2960
3007
|
// src/commands/deploy/init/index.ts
|
|
2961
3008
|
import { execSync as execSync12 } from "child_process";
|
|
@@ -2963,33 +3010,33 @@ import chalk40 from "chalk";
|
|
|
2963
3010
|
import enquirer5 from "enquirer";
|
|
2964
3011
|
|
|
2965
3012
|
// src/commands/deploy/init/updateWorkflow.ts
|
|
2966
|
-
import { existsSync as
|
|
2967
|
-
import { dirname as dirname13, join as
|
|
3013
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync3, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
3014
|
+
import { dirname as dirname13, join as join11 } from "path";
|
|
2968
3015
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2969
3016
|
import chalk39 from "chalk";
|
|
2970
3017
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
2971
3018
|
var __dirname3 = dirname13(fileURLToPath3(import.meta.url));
|
|
2972
3019
|
function getExistingSiteId() {
|
|
2973
|
-
if (!
|
|
3020
|
+
if (!existsSync15(WORKFLOW_PATH)) {
|
|
2974
3021
|
return null;
|
|
2975
3022
|
}
|
|
2976
|
-
const content =
|
|
3023
|
+
const content = readFileSync12(WORKFLOW_PATH, "utf-8");
|
|
2977
3024
|
const match = content.match(/-s\s+([a-f0-9-]{36})/);
|
|
2978
3025
|
return match ? match[1] : null;
|
|
2979
3026
|
}
|
|
2980
3027
|
function getTemplateContent(siteId) {
|
|
2981
|
-
const templatePath =
|
|
2982
|
-
const template =
|
|
3028
|
+
const templatePath = join11(__dirname3, "commands/deploy/build.yml");
|
|
3029
|
+
const template = readFileSync12(templatePath, "utf-8");
|
|
2983
3030
|
return template.replace("{{NETLIFY_SITE_ID}}", siteId);
|
|
2984
3031
|
}
|
|
2985
3032
|
async function updateWorkflow(siteId) {
|
|
2986
3033
|
const newContent = getTemplateContent(siteId);
|
|
2987
3034
|
const workflowDir = ".github/workflows";
|
|
2988
|
-
if (!
|
|
3035
|
+
if (!existsSync15(workflowDir)) {
|
|
2989
3036
|
mkdirSync3(workflowDir, { recursive: true });
|
|
2990
3037
|
}
|
|
2991
|
-
if (
|
|
2992
|
-
const oldContent =
|
|
3038
|
+
if (existsSync15(WORKFLOW_PATH)) {
|
|
3039
|
+
const oldContent = readFileSync12(WORKFLOW_PATH, "utf-8");
|
|
2993
3040
|
if (oldContent === newContent) {
|
|
2994
3041
|
console.log(chalk39.green("build.yml is already up to date"));
|
|
2995
3042
|
return;
|
|
@@ -3003,7 +3050,7 @@ async function updateWorkflow(siteId) {
|
|
|
3003
3050
|
return;
|
|
3004
3051
|
}
|
|
3005
3052
|
}
|
|
3006
|
-
|
|
3053
|
+
writeFileSync12(WORKFLOW_PATH, newContent);
|
|
3007
3054
|
console.log(chalk39.green(`
|
|
3008
3055
|
Created ${WORKFLOW_PATH}`));
|
|
3009
3056
|
}
|
|
@@ -3083,11 +3130,11 @@ async function newProject() {
|
|
|
3083
3130
|
}
|
|
3084
3131
|
function addViteBaseConfig() {
|
|
3085
3132
|
const viteConfigPath = "vite.config.ts";
|
|
3086
|
-
if (!
|
|
3133
|
+
if (!existsSync16(viteConfigPath)) {
|
|
3087
3134
|
console.log("No vite.config.ts found, skipping base config");
|
|
3088
3135
|
return;
|
|
3089
3136
|
}
|
|
3090
|
-
const content =
|
|
3137
|
+
const content = readFileSync13(viteConfigPath, "utf-8");
|
|
3091
3138
|
if (content.includes("base:")) {
|
|
3092
3139
|
console.log("vite.config.ts already has base config");
|
|
3093
3140
|
return;
|
|
@@ -3097,7 +3144,7 @@ function addViteBaseConfig() {
|
|
|
3097
3144
|
'defineConfig({\n base: "./",'
|
|
3098
3145
|
);
|
|
3099
3146
|
if (updated !== content) {
|
|
3100
|
-
|
|
3147
|
+
writeFileSync13(viteConfigPath, updated);
|
|
3101
3148
|
console.log('Added base: "./" to vite.config.ts');
|
|
3102
3149
|
}
|
|
3103
3150
|
}
|
|
@@ -3265,7 +3312,7 @@ function registerCommentCommands(cmd) {
|
|
|
3265
3312
|
}
|
|
3266
3313
|
|
|
3267
3314
|
// src/commands/backlog/add/index.ts
|
|
3268
|
-
import { existsSync as
|
|
3315
|
+
import { existsSync as existsSync17 } from "fs";
|
|
3269
3316
|
import chalk44 from "chalk";
|
|
3270
3317
|
|
|
3271
3318
|
// src/commands/backlog/commitBacklog.ts
|
|
@@ -3284,9 +3331,9 @@ function commitBacklog(id, name) {
|
|
|
3284
3331
|
|
|
3285
3332
|
// src/commands/backlog/add/shared.ts
|
|
3286
3333
|
import { spawnSync } from "child_process";
|
|
3287
|
-
import { mkdtempSync, readFileSync as
|
|
3334
|
+
import { mkdtempSync, readFileSync as readFileSync14, unlinkSync as unlinkSync4, writeFileSync as writeFileSync14 } from "fs";
|
|
3288
3335
|
import { tmpdir } from "os";
|
|
3289
|
-
import { join as
|
|
3336
|
+
import { join as join12 } from "path";
|
|
3290
3337
|
import enquirer6 from "enquirer";
|
|
3291
3338
|
async function promptType() {
|
|
3292
3339
|
const { type } = await enquirer6.prompt({
|
|
@@ -3326,16 +3373,16 @@ async function promptDescription() {
|
|
|
3326
3373
|
}
|
|
3327
3374
|
function openEditor() {
|
|
3328
3375
|
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
3329
|
-
const dir = mkdtempSync(
|
|
3330
|
-
const filePath =
|
|
3331
|
-
|
|
3376
|
+
const dir = mkdtempSync(join12(tmpdir(), "assist-"));
|
|
3377
|
+
const filePath = join12(dir, "description.md");
|
|
3378
|
+
writeFileSync14(filePath, "");
|
|
3332
3379
|
const result = spawnSync(editor, [filePath], { stdio: "inherit" });
|
|
3333
3380
|
if (result.status !== 0) {
|
|
3334
|
-
|
|
3381
|
+
unlinkSync4(filePath);
|
|
3335
3382
|
return void 0;
|
|
3336
3383
|
}
|
|
3337
|
-
const content =
|
|
3338
|
-
|
|
3384
|
+
const content = readFileSync14(filePath, "utf-8").trim();
|
|
3385
|
+
unlinkSync4(filePath);
|
|
3339
3386
|
return content || void 0;
|
|
3340
3387
|
}
|
|
3341
3388
|
async function promptAcceptanceCriteria() {
|
|
@@ -3392,7 +3439,7 @@ async function addInteractive() {
|
|
|
3392
3439
|
console.log(chalk44.green(`Added item #${id}: ${name}`));
|
|
3393
3440
|
}
|
|
3394
3441
|
async function add(options2) {
|
|
3395
|
-
if (!
|
|
3442
|
+
if (!existsSync17(getBacklogPath())) {
|
|
3396
3443
|
console.log(
|
|
3397
3444
|
chalk44.yellow(
|
|
3398
3445
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
@@ -3408,11 +3455,11 @@ async function add(options2) {
|
|
|
3408
3455
|
}
|
|
3409
3456
|
|
|
3410
3457
|
// src/commands/backlog/init/index.ts
|
|
3411
|
-
import { existsSync as
|
|
3458
|
+
import { existsSync as existsSync18 } from "fs";
|
|
3412
3459
|
import chalk45 from "chalk";
|
|
3413
3460
|
async function init6() {
|
|
3414
3461
|
const backlogPath = getBacklogPath();
|
|
3415
|
-
if (
|
|
3462
|
+
if (existsSync18(backlogPath)) {
|
|
3416
3463
|
console.log(chalk45.yellow("assist.backlog.yml already exists."));
|
|
3417
3464
|
return;
|
|
3418
3465
|
}
|
|
@@ -3421,7 +3468,7 @@ async function init6() {
|
|
|
3421
3468
|
}
|
|
3422
3469
|
|
|
3423
3470
|
// src/commands/backlog/list/index.ts
|
|
3424
|
-
import { existsSync as
|
|
3471
|
+
import { existsSync as existsSync19 } from "fs";
|
|
3425
3472
|
import chalk46 from "chalk";
|
|
3426
3473
|
function filterItems(items, options2) {
|
|
3427
3474
|
if (options2.status) return items.filter((i) => i.status === options2.status);
|
|
@@ -3429,7 +3476,7 @@ function filterItems(items, options2) {
|
|
|
3429
3476
|
return items;
|
|
3430
3477
|
}
|
|
3431
3478
|
async function list2(options2) {
|
|
3432
|
-
if (!
|
|
3479
|
+
if (!existsSync19(getBacklogPath())) {
|
|
3433
3480
|
console.log(
|
|
3434
3481
|
chalk46.yellow(
|
|
3435
3482
|
"No backlog found. Run 'assist backlog init' to create one."
|
|
@@ -3579,7 +3626,7 @@ function extractGraphqlQuery(args) {
|
|
|
3579
3626
|
}
|
|
3580
3627
|
|
|
3581
3628
|
// src/shared/loadCliReads.ts
|
|
3582
|
-
import { existsSync as
|
|
3629
|
+
import { existsSync as existsSync20, readFileSync as readFileSync15, writeFileSync as writeFileSync15 } from "fs";
|
|
3583
3630
|
import { dirname as dirname14, resolve as resolve2 } from "path";
|
|
3584
3631
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
3585
3632
|
var __filename2 = fileURLToPath4(import.meta.url);
|
|
@@ -3591,18 +3638,18 @@ var cachedLines;
|
|
|
3591
3638
|
function getCliReadsLines() {
|
|
3592
3639
|
if (cachedLines) return cachedLines;
|
|
3593
3640
|
const path50 = getCliReadsPath();
|
|
3594
|
-
if (!
|
|
3641
|
+
if (!existsSync20(path50)) {
|
|
3595
3642
|
cachedLines = [];
|
|
3596
3643
|
return cachedLines;
|
|
3597
3644
|
}
|
|
3598
|
-
cachedLines =
|
|
3645
|
+
cachedLines = readFileSync15(path50, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
3599
3646
|
return cachedLines;
|
|
3600
3647
|
}
|
|
3601
3648
|
function loadCliReads() {
|
|
3602
3649
|
return getCliReadsLines();
|
|
3603
3650
|
}
|
|
3604
3651
|
function saveCliReads(commands) {
|
|
3605
|
-
|
|
3652
|
+
writeFileSync15(getCliReadsPath(), `${commands.join("\n")}
|
|
3606
3653
|
`);
|
|
3607
3654
|
cachedLines = void 0;
|
|
3608
3655
|
}
|
|
@@ -3619,61 +3666,82 @@ function findCliRead(command) {
|
|
|
3619
3666
|
return candidates.sort((a, b) => b.length - a.length).find((rc) => command === rc || command.startsWith(`${rc} `));
|
|
3620
3667
|
}
|
|
3621
3668
|
|
|
3622
|
-
// src/shared/
|
|
3623
|
-
import { existsSync as
|
|
3669
|
+
// src/shared/matchesAllow.ts
|
|
3670
|
+
import { existsSync as existsSync21, readFileSync as readFileSync16 } from "fs";
|
|
3624
3671
|
import { homedir as homedir3 } from "os";
|
|
3625
|
-
import { join as
|
|
3626
|
-
var
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3672
|
+
import { join as join13 } from "path";
|
|
3673
|
+
var allowCache;
|
|
3674
|
+
var denyCache;
|
|
3675
|
+
var TOOL_RE = /^(Bash|PowerShell)\((.+?)(?::.*)\)$/;
|
|
3676
|
+
function loadPrefixes(key) {
|
|
3677
|
+
const entries = collectEntries(key);
|
|
3678
|
+
return parsePrefixes(entries);
|
|
3679
|
+
}
|
|
3680
|
+
var SHELL_TOOLS = ["Bash", "PowerShell"];
|
|
3681
|
+
function shellPrefixes(map, toolName) {
|
|
3682
|
+
if (SHELL_TOOLS.includes(toolName)) {
|
|
3683
|
+
return SHELL_TOOLS.flatMap((t) => map.get(t) ?? []);
|
|
3684
|
+
}
|
|
3685
|
+
return map.get(toolName) ?? [];
|
|
3686
|
+
}
|
|
3687
|
+
function matchesAllow(toolName, command) {
|
|
3688
|
+
if (!allowCache) allowCache = loadPrefixes("allow");
|
|
3689
|
+
const prefixes = shellPrefixes(allowCache, toolName);
|
|
3690
|
+
return prefixes.find(
|
|
3691
|
+
(pfx) => command === pfx || command.startsWith(`${pfx} `)
|
|
3692
|
+
);
|
|
3693
|
+
}
|
|
3694
|
+
function matchesDeny(toolName, command) {
|
|
3695
|
+
if (!denyCache) denyCache = loadPrefixes("deny");
|
|
3696
|
+
const prefixes = shellPrefixes(denyCache, toolName);
|
|
3634
3697
|
return prefixes.find(
|
|
3635
3698
|
(pfx) => command === pfx || command.startsWith(`${pfx} `)
|
|
3636
3699
|
);
|
|
3637
3700
|
}
|
|
3638
|
-
function
|
|
3701
|
+
function collectEntries(key) {
|
|
3639
3702
|
const paths = [
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3703
|
+
join13(homedir3(), ".claude", "settings.json"),
|
|
3704
|
+
join13(process.cwd(), ".claude", "settings.json"),
|
|
3705
|
+
join13(process.cwd(), ".claude", "settings.local.json")
|
|
3643
3706
|
];
|
|
3644
3707
|
const entries = [];
|
|
3645
3708
|
for (const p of paths) {
|
|
3646
|
-
entries.push(...
|
|
3709
|
+
entries.push(...readPermissionArray(p, key));
|
|
3647
3710
|
}
|
|
3648
3711
|
return entries;
|
|
3649
3712
|
}
|
|
3650
|
-
function
|
|
3651
|
-
if (!
|
|
3713
|
+
function readPermissionArray(filePath, key) {
|
|
3714
|
+
if (!existsSync21(filePath)) return [];
|
|
3652
3715
|
try {
|
|
3653
|
-
const data = JSON.parse(
|
|
3654
|
-
const
|
|
3655
|
-
return Array.isArray(
|
|
3716
|
+
const data = JSON.parse(readFileSync16(filePath, "utf-8"));
|
|
3717
|
+
const arr = data?.permissions?.[key];
|
|
3718
|
+
return Array.isArray(arr) ? arr.filter((e) => typeof e === "string") : [];
|
|
3656
3719
|
} catch {
|
|
3657
3720
|
return [];
|
|
3658
3721
|
}
|
|
3659
3722
|
}
|
|
3660
3723
|
function parsePrefixes(entries) {
|
|
3661
|
-
const
|
|
3662
|
-
const prefixes = [];
|
|
3724
|
+
const map = /* @__PURE__ */ new Map();
|
|
3663
3725
|
for (const entry of entries) {
|
|
3664
|
-
const m = entry.match(
|
|
3665
|
-
if (m)
|
|
3726
|
+
const m = entry.match(TOOL_RE);
|
|
3727
|
+
if (m) {
|
|
3728
|
+
const tool = m[1];
|
|
3729
|
+
const prefix2 = m[2];
|
|
3730
|
+
const list4 = map.get(tool) ?? [];
|
|
3731
|
+
list4.push(prefix2);
|
|
3732
|
+
map.set(tool, list4);
|
|
3733
|
+
}
|
|
3666
3734
|
}
|
|
3667
|
-
return
|
|
3735
|
+
return map;
|
|
3668
3736
|
}
|
|
3669
3737
|
|
|
3670
3738
|
// src/shared/isApprovedRead.ts
|
|
3671
|
-
function isApprovedRead(command) {
|
|
3739
|
+
function isApprovedRead(command, toolName = "Bash") {
|
|
3672
3740
|
if (isCdToCwd(command)) return "cd to current directory";
|
|
3673
3741
|
const matched = findCliRead(command);
|
|
3674
3742
|
if (matched) return `Read-only CLI command: ${matched}`;
|
|
3675
3743
|
if (isGhApiRead(command)) return "Read-only gh api command";
|
|
3676
|
-
const allowMatch =
|
|
3744
|
+
const allowMatch = matchesAllow(toolName, command);
|
|
3677
3745
|
if (allowMatch) return `Allowed by settings: ${allowMatch}`;
|
|
3678
3746
|
return void 0;
|
|
3679
3747
|
}
|
|
@@ -3745,6 +3813,28 @@ function stripEnvPrefix(parts) {
|
|
|
3745
3813
|
}
|
|
3746
3814
|
|
|
3747
3815
|
// src/commands/cliHook/index.ts
|
|
3816
|
+
var SUPPORTED_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
|
|
3817
|
+
function resolvePermission(toolName, parts) {
|
|
3818
|
+
for (const part of parts) {
|
|
3819
|
+
const denied = matchesDeny(toolName, part);
|
|
3820
|
+
if (denied) {
|
|
3821
|
+
return {
|
|
3822
|
+
permissionDecision: "deny",
|
|
3823
|
+
permissionDecisionReason: `Denied by settings: ${denied}`
|
|
3824
|
+
};
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
const reasons = [];
|
|
3828
|
+
for (const part of parts) {
|
|
3829
|
+
const reason = isApprovedRead(part, toolName);
|
|
3830
|
+
if (!reason) return void 0;
|
|
3831
|
+
reasons.push(reason);
|
|
3832
|
+
}
|
|
3833
|
+
return {
|
|
3834
|
+
permissionDecision: "allow",
|
|
3835
|
+
permissionDecisionReason: reasons.join("; ")
|
|
3836
|
+
};
|
|
3837
|
+
}
|
|
3748
3838
|
async function cliHook() {
|
|
3749
3839
|
const inputData = await readStdin2();
|
|
3750
3840
|
let data;
|
|
@@ -3753,24 +3843,18 @@ async function cliHook() {
|
|
|
3753
3843
|
} catch {
|
|
3754
3844
|
return;
|
|
3755
3845
|
}
|
|
3756
|
-
if (data.tool_name
|
|
3846
|
+
if (!SUPPORTED_TOOLS.has(data.tool_name) || !data.tool_input?.command) {
|
|
3757
3847
|
return;
|
|
3758
3848
|
}
|
|
3759
|
-
const
|
|
3760
|
-
const parts = splitCompound(command);
|
|
3849
|
+
const parts = splitCompound(data.tool_input.command.trim());
|
|
3761
3850
|
if (!parts) return;
|
|
3762
|
-
const
|
|
3763
|
-
|
|
3764
|
-
const reason = isApprovedRead(part);
|
|
3765
|
-
if (!reason) return;
|
|
3766
|
-
reasons.push(reason);
|
|
3767
|
-
}
|
|
3851
|
+
const decision = resolvePermission(data.tool_name, parts);
|
|
3852
|
+
if (!decision) return;
|
|
3768
3853
|
console.log(
|
|
3769
3854
|
JSON.stringify({
|
|
3770
3855
|
hookSpecificOutput: {
|
|
3771
3856
|
hookEventName: "PreToolUse",
|
|
3772
|
-
|
|
3773
|
-
permissionDecisionReason: reasons.join("; ")
|
|
3857
|
+
...decision
|
|
3774
3858
|
}
|
|
3775
3859
|
})
|
|
3776
3860
|
);
|
|
@@ -3800,9 +3884,9 @@ ${reasons.join("\n")}`);
|
|
|
3800
3884
|
}
|
|
3801
3885
|
|
|
3802
3886
|
// src/commands/permitCliReads/index.ts
|
|
3803
|
-
import { existsSync as
|
|
3887
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync4, readFileSync as readFileSync17, writeFileSync as writeFileSync16 } from "fs";
|
|
3804
3888
|
import { homedir as homedir4 } from "os";
|
|
3805
|
-
import { join as
|
|
3889
|
+
import { join as join14 } from "path";
|
|
3806
3890
|
|
|
3807
3891
|
// src/shared/getInstallDir.ts
|
|
3808
3892
|
import { execSync as execSync15 } from "child_process";
|
|
@@ -4076,10 +4160,10 @@ function formatHuman(cli, commands) {
|
|
|
4076
4160
|
}
|
|
4077
4161
|
|
|
4078
4162
|
// src/commands/permitCliReads/parseCached.ts
|
|
4079
|
-
function parseCached(cli,
|
|
4163
|
+
function parseCached(cli, cached) {
|
|
4080
4164
|
const prefix2 = `${cli} `;
|
|
4081
4165
|
const commands = [];
|
|
4082
|
-
for (const line of
|
|
4166
|
+
for (const line of cached.split("\n")) {
|
|
4083
4167
|
const trimmed = line.replace(/^ [RW?] {2}/, "").trim();
|
|
4084
4168
|
if (!trimmed.startsWith(prefix2)) continue;
|
|
4085
4169
|
const rest = trimmed.slice(prefix2.length);
|
|
@@ -4104,17 +4188,17 @@ function updateSettings(cli, commands) {
|
|
|
4104
4188
|
// src/commands/permitCliReads/index.ts
|
|
4105
4189
|
function logPath(cli) {
|
|
4106
4190
|
const safeName = cli.replace(/\s+/g, "-");
|
|
4107
|
-
return
|
|
4191
|
+
return join14(homedir4(), ".assist", `cli-discover-${safeName}.log`);
|
|
4108
4192
|
}
|
|
4109
4193
|
function readCache(cli) {
|
|
4110
4194
|
const path50 = logPath(cli);
|
|
4111
|
-
if (!
|
|
4112
|
-
return
|
|
4195
|
+
if (!existsSync22(path50)) return void 0;
|
|
4196
|
+
return readFileSync17(path50, "utf-8");
|
|
4113
4197
|
}
|
|
4114
4198
|
function writeCache(cli, output) {
|
|
4115
|
-
const dir =
|
|
4199
|
+
const dir = join14(homedir4(), ".assist");
|
|
4116
4200
|
mkdirSync4(dir, { recursive: true });
|
|
4117
|
-
|
|
4201
|
+
writeFileSync16(logPath(cli), output);
|
|
4118
4202
|
}
|
|
4119
4203
|
async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
4120
4204
|
if (!cli) {
|
|
@@ -4132,10 +4216,10 @@ async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
|
4132
4216
|
const binary = parts[0];
|
|
4133
4217
|
const prefixPath = parts.slice(1);
|
|
4134
4218
|
if (!options2.noCache) {
|
|
4135
|
-
const
|
|
4136
|
-
if (
|
|
4137
|
-
console.log(colorize(
|
|
4138
|
-
updateSettings(binary, parseCached(binary,
|
|
4219
|
+
const cached = readCache(cli);
|
|
4220
|
+
if (cached) {
|
|
4221
|
+
console.log(colorize(cached));
|
|
4222
|
+
updateSettings(binary, parseCached(binary, cached));
|
|
4139
4223
|
return;
|
|
4140
4224
|
}
|
|
4141
4225
|
}
|
|
@@ -4657,7 +4741,7 @@ function registerComplexity(program2) {
|
|
|
4657
4741
|
}
|
|
4658
4742
|
|
|
4659
4743
|
// src/commands/deploy/redirect.ts
|
|
4660
|
-
import { existsSync as
|
|
4744
|
+
import { existsSync as existsSync23, readFileSync as readFileSync18, writeFileSync as writeFileSync17 } from "fs";
|
|
4661
4745
|
import chalk54 from "chalk";
|
|
4662
4746
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
4663
4747
|
if (!window.location.pathname.endsWith('/')) {
|
|
@@ -4666,11 +4750,11 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
4666
4750
|
</script>`;
|
|
4667
4751
|
function redirect() {
|
|
4668
4752
|
const indexPath = "index.html";
|
|
4669
|
-
if (!
|
|
4753
|
+
if (!existsSync23(indexPath)) {
|
|
4670
4754
|
console.log(chalk54.yellow("No index.html found"));
|
|
4671
4755
|
return;
|
|
4672
4756
|
}
|
|
4673
|
-
const content =
|
|
4757
|
+
const content = readFileSync18(indexPath, "utf-8");
|
|
4674
4758
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
4675
4759
|
console.log(chalk54.dim("Trailing slash script already present"));
|
|
4676
4760
|
return;
|
|
@@ -4681,7 +4765,7 @@ function redirect() {
|
|
|
4681
4765
|
return;
|
|
4682
4766
|
}
|
|
4683
4767
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
4684
|
-
|
|
4768
|
+
writeFileSync17(indexPath, newContent);
|
|
4685
4769
|
console.log(chalk54.green("Added trailing slash redirect to index.html"));
|
|
4686
4770
|
}
|
|
4687
4771
|
|
|
@@ -4698,10 +4782,10 @@ import { basename as basename3 } from "path";
|
|
|
4698
4782
|
|
|
4699
4783
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
4700
4784
|
import { homedir as homedir5 } from "os";
|
|
4701
|
-
import { join as
|
|
4702
|
-
var BLOG_REPO_ROOT =
|
|
4785
|
+
import { join as join15 } from "path";
|
|
4786
|
+
var BLOG_REPO_ROOT = join15(homedir5(), "git/blog");
|
|
4703
4787
|
function loadBlogSkipDays(repoName) {
|
|
4704
|
-
const config = loadRawYaml(
|
|
4788
|
+
const config = loadRawYaml(join15(BLOG_REPO_ROOT, "assist.yml"));
|
|
4705
4789
|
const devlog = config.devlog;
|
|
4706
4790
|
const skip2 = devlog?.skip;
|
|
4707
4791
|
return new Set(skip2?.[repoName] ?? []);
|
|
@@ -4712,9 +4796,9 @@ import { execSync as execSync17 } from "child_process";
|
|
|
4712
4796
|
import chalk55 from "chalk";
|
|
4713
4797
|
|
|
4714
4798
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
4715
|
-
import { readdirSync, readFileSync as
|
|
4716
|
-
import { join as
|
|
4717
|
-
var DEVLOG_DIR =
|
|
4799
|
+
import { readdirSync, readFileSync as readFileSync19 } from "fs";
|
|
4800
|
+
import { join as join16 } from "path";
|
|
4801
|
+
var DEVLOG_DIR = join16(BLOG_REPO_ROOT, "src/content/devlog");
|
|
4718
4802
|
function extractFrontmatter(content) {
|
|
4719
4803
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
4720
4804
|
return fm?.[1] ?? null;
|
|
@@ -4742,7 +4826,7 @@ function readDevlogFiles(callback) {
|
|
|
4742
4826
|
try {
|
|
4743
4827
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
4744
4828
|
for (const file of files) {
|
|
4745
|
-
const content =
|
|
4829
|
+
const content = readFileSync19(join16(DEVLOG_DIR, file), "utf-8");
|
|
4746
4830
|
const parsed = parseFrontmatter(content, file);
|
|
4747
4831
|
if (parsed) callback(parsed);
|
|
4748
4832
|
}
|
|
@@ -5127,12 +5211,12 @@ function repos(options2) {
|
|
|
5127
5211
|
}
|
|
5128
5212
|
|
|
5129
5213
|
// src/commands/devlog/skip.ts
|
|
5130
|
-
import { writeFileSync as
|
|
5131
|
-
import { join as
|
|
5214
|
+
import { writeFileSync as writeFileSync18 } from "fs";
|
|
5215
|
+
import { join as join17 } from "path";
|
|
5132
5216
|
import chalk60 from "chalk";
|
|
5133
5217
|
import { stringify as stringifyYaml4 } from "yaml";
|
|
5134
5218
|
function getBlogConfigPath() {
|
|
5135
|
-
return
|
|
5219
|
+
return join17(BLOG_REPO_ROOT, "assist.yml");
|
|
5136
5220
|
}
|
|
5137
5221
|
function skip(date) {
|
|
5138
5222
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
@@ -5156,7 +5240,7 @@ function skip(date) {
|
|
|
5156
5240
|
skip2[repoName] = skipDays;
|
|
5157
5241
|
devlog.skip = skip2;
|
|
5158
5242
|
config.devlog = devlog;
|
|
5159
|
-
|
|
5243
|
+
writeFileSync18(configPath, stringifyYaml4(config, { lineWidth: 0 }));
|
|
5160
5244
|
console.log(chalk60.green(`Added ${date} to skip list for ${repoName}`));
|
|
5161
5245
|
}
|
|
5162
5246
|
|
|
@@ -5193,16 +5277,16 @@ function registerDevlog(program2) {
|
|
|
5193
5277
|
|
|
5194
5278
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
5195
5279
|
import { closeSync, openSync, readdirSync as readdirSync2 } from "fs";
|
|
5196
|
-
import { join as
|
|
5280
|
+
import { join as join18 } from "path";
|
|
5197
5281
|
import chalk62 from "chalk";
|
|
5198
5282
|
|
|
5199
5283
|
// src/shared/findRepoRoot.ts
|
|
5200
|
-
import { existsSync as
|
|
5284
|
+
import { existsSync as existsSync24 } from "fs";
|
|
5201
5285
|
import path21 from "path";
|
|
5202
5286
|
function findRepoRoot(dir) {
|
|
5203
5287
|
let current = dir;
|
|
5204
5288
|
while (current !== path21.dirname(current)) {
|
|
5205
|
-
if (
|
|
5289
|
+
if (existsSync24(path21.join(current, ".git"))) {
|
|
5206
5290
|
return current;
|
|
5207
5291
|
}
|
|
5208
5292
|
current = path21.dirname(current);
|
|
@@ -5221,7 +5305,7 @@ function isLockedDll(debugDir) {
|
|
|
5221
5305
|
}
|
|
5222
5306
|
for (const file of files) {
|
|
5223
5307
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
5224
|
-
const dllPath =
|
|
5308
|
+
const dllPath = join18(debugDir, file);
|
|
5225
5309
|
try {
|
|
5226
5310
|
const fd = openSync(dllPath, "r+");
|
|
5227
5311
|
closeSync(fd);
|
|
@@ -5239,13 +5323,13 @@ function findFirstLockedDll(dir) {
|
|
|
5239
5323
|
return null;
|
|
5240
5324
|
}
|
|
5241
5325
|
if (entries.includes("bin")) {
|
|
5242
|
-
const locked = isLockedDll(
|
|
5326
|
+
const locked = isLockedDll(join18(dir, "bin", "Debug"));
|
|
5243
5327
|
if (locked) return locked;
|
|
5244
5328
|
}
|
|
5245
5329
|
for (const entry of entries) {
|
|
5246
5330
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
5247
5331
|
continue;
|
|
5248
|
-
const found = findFirstLockedDll(
|
|
5332
|
+
const found = findFirstLockedDll(join18(dir, entry));
|
|
5249
5333
|
if (found) return found;
|
|
5250
5334
|
}
|
|
5251
5335
|
return null;
|
|
@@ -5268,11 +5352,11 @@ async function checkBuildLocksCommand() {
|
|
|
5268
5352
|
}
|
|
5269
5353
|
|
|
5270
5354
|
// src/commands/dotnet/buildTree.ts
|
|
5271
|
-
import { readFileSync as
|
|
5355
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
5272
5356
|
import path22 from "path";
|
|
5273
5357
|
var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
|
|
5274
5358
|
function getProjectRefs(csprojPath) {
|
|
5275
|
-
const content =
|
|
5359
|
+
const content = readFileSync20(csprojPath, "utf-8");
|
|
5276
5360
|
const refs = [];
|
|
5277
5361
|
for (const match of content.matchAll(PROJECT_REF_RE)) {
|
|
5278
5362
|
refs.push(match[1].replace(/\\/g, "/"));
|
|
@@ -5289,7 +5373,7 @@ function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
|
|
|
5289
5373
|
for (const ref of getProjectRefs(abs)) {
|
|
5290
5374
|
const childAbs = path22.resolve(dir, ref);
|
|
5291
5375
|
try {
|
|
5292
|
-
|
|
5376
|
+
readFileSync20(childAbs);
|
|
5293
5377
|
node.children.push(buildTree(childAbs, repoRoot, visited));
|
|
5294
5378
|
} catch {
|
|
5295
5379
|
node.children.push({
|
|
@@ -5314,7 +5398,7 @@ function collectAllDeps(node) {
|
|
|
5314
5398
|
}
|
|
5315
5399
|
|
|
5316
5400
|
// src/commands/dotnet/findContainingSolutions.ts
|
|
5317
|
-
import { readdirSync as readdirSync3, readFileSync as
|
|
5401
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync21, statSync } from "fs";
|
|
5318
5402
|
import path23 from "path";
|
|
5319
5403
|
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
5320
5404
|
if (depth > maxDepth) return [];
|
|
@@ -5349,7 +5433,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
|
|
|
5349
5433
|
const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
|
|
5350
5434
|
for (const sln of slnFiles) {
|
|
5351
5435
|
try {
|
|
5352
|
-
const content =
|
|
5436
|
+
const content = readFileSync21(sln, "utf-8");
|
|
5353
5437
|
if (pattern2.test(content)) {
|
|
5354
5438
|
matches.push(path23.relative(repoRoot, sln));
|
|
5355
5439
|
}
|
|
@@ -5413,12 +5497,12 @@ function printJson(tree, totalCount, solutions) {
|
|
|
5413
5497
|
}
|
|
5414
5498
|
|
|
5415
5499
|
// src/commands/dotnet/resolveCsproj.ts
|
|
5416
|
-
import { existsSync as
|
|
5500
|
+
import { existsSync as existsSync25 } from "fs";
|
|
5417
5501
|
import path24 from "path";
|
|
5418
5502
|
import chalk64 from "chalk";
|
|
5419
5503
|
function resolveCsproj(csprojPath) {
|
|
5420
5504
|
const resolved = path24.resolve(csprojPath);
|
|
5421
|
-
if (!
|
|
5505
|
+
if (!existsSync25(resolved)) {
|
|
5422
5506
|
console.error(chalk64.red(`File not found: ${resolved}`));
|
|
5423
5507
|
process.exit(1);
|
|
5424
5508
|
}
|
|
@@ -5586,17 +5670,17 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
5586
5670
|
}
|
|
5587
5671
|
|
|
5588
5672
|
// src/commands/dotnet/resolveSolution.ts
|
|
5589
|
-
import { existsSync as
|
|
5673
|
+
import { existsSync as existsSync26 } from "fs";
|
|
5590
5674
|
import path25 from "path";
|
|
5591
5675
|
import chalk68 from "chalk";
|
|
5592
5676
|
|
|
5593
5677
|
// src/commands/dotnet/findSolution.ts
|
|
5594
5678
|
import { readdirSync as readdirSync4 } from "fs";
|
|
5595
|
-
import { dirname as dirname16, join as
|
|
5679
|
+
import { dirname as dirname16, join as join19 } from "path";
|
|
5596
5680
|
import chalk67 from "chalk";
|
|
5597
5681
|
function findSlnInDir(dir) {
|
|
5598
5682
|
try {
|
|
5599
|
-
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) =>
|
|
5683
|
+
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join19(dir, f));
|
|
5600
5684
|
} catch {
|
|
5601
5685
|
return [];
|
|
5602
5686
|
}
|
|
@@ -5627,7 +5711,7 @@ function findSolution() {
|
|
|
5627
5711
|
function resolveSolution(sln) {
|
|
5628
5712
|
if (sln) {
|
|
5629
5713
|
const resolved = path25.resolve(sln);
|
|
5630
|
-
if (!
|
|
5714
|
+
if (!existsSync26(resolved)) {
|
|
5631
5715
|
console.error(chalk68.red(`Solution file not found: ${resolved}`));
|
|
5632
5716
|
process.exit(1);
|
|
5633
5717
|
}
|
|
@@ -5667,7 +5751,7 @@ function parseInspectReport(json) {
|
|
|
5667
5751
|
|
|
5668
5752
|
// src/commands/dotnet/runInspectCode.ts
|
|
5669
5753
|
import { execSync as execSync23 } from "child_process";
|
|
5670
|
-
import { existsSync as
|
|
5754
|
+
import { existsSync as existsSync27, readFileSync as readFileSync22, unlinkSync as unlinkSync5 } from "fs";
|
|
5671
5755
|
import { tmpdir as tmpdir2 } from "os";
|
|
5672
5756
|
import path26 from "path";
|
|
5673
5757
|
import chalk69 from "chalk";
|
|
@@ -5698,12 +5782,12 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
5698
5782
|
console.error(chalk69.red("jb inspectcode failed"));
|
|
5699
5783
|
process.exit(1);
|
|
5700
5784
|
}
|
|
5701
|
-
if (!
|
|
5785
|
+
if (!existsSync27(reportPath)) {
|
|
5702
5786
|
console.error(chalk69.red("Report file not generated"));
|
|
5703
5787
|
process.exit(1);
|
|
5704
5788
|
}
|
|
5705
|
-
const xml =
|
|
5706
|
-
|
|
5789
|
+
const xml = readFileSync22(reportPath, "utf-8");
|
|
5790
|
+
unlinkSync5(reportPath);
|
|
5707
5791
|
return xml;
|
|
5708
5792
|
}
|
|
5709
5793
|
|
|
@@ -5930,20 +6014,20 @@ function acceptanceCriteria(issueKey) {
|
|
|
5930
6014
|
import { execSync as execSync26 } from "child_process";
|
|
5931
6015
|
|
|
5932
6016
|
// src/shared/loadJson.ts
|
|
5933
|
-
import { existsSync as
|
|
6017
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync5, readFileSync as readFileSync23, writeFileSync as writeFileSync19 } from "fs";
|
|
5934
6018
|
import { homedir as homedir6 } from "os";
|
|
5935
|
-
import { join as
|
|
6019
|
+
import { join as join20 } from "path";
|
|
5936
6020
|
function getStoreDir() {
|
|
5937
|
-
return
|
|
6021
|
+
return join20(homedir6(), ".assist");
|
|
5938
6022
|
}
|
|
5939
6023
|
function getStorePath(filename) {
|
|
5940
|
-
return
|
|
6024
|
+
return join20(getStoreDir(), filename);
|
|
5941
6025
|
}
|
|
5942
6026
|
function loadJson(filename) {
|
|
5943
6027
|
const path50 = getStorePath(filename);
|
|
5944
|
-
if (
|
|
6028
|
+
if (existsSync28(path50)) {
|
|
5945
6029
|
try {
|
|
5946
|
-
return JSON.parse(
|
|
6030
|
+
return JSON.parse(readFileSync23(path50, "utf-8"));
|
|
5947
6031
|
} catch {
|
|
5948
6032
|
return {};
|
|
5949
6033
|
}
|
|
@@ -5952,10 +6036,10 @@ function loadJson(filename) {
|
|
|
5952
6036
|
}
|
|
5953
6037
|
function saveJson(filename, data) {
|
|
5954
6038
|
const dir = getStoreDir();
|
|
5955
|
-
if (!
|
|
6039
|
+
if (!existsSync28(dir)) {
|
|
5956
6040
|
mkdirSync5(dir, { recursive: true });
|
|
5957
6041
|
}
|
|
5958
|
-
|
|
6042
|
+
writeFileSync19(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
5959
6043
|
}
|
|
5960
6044
|
|
|
5961
6045
|
// src/shared/promptInput.ts
|
|
@@ -6267,9 +6351,9 @@ function registerNews(program2) {
|
|
|
6267
6351
|
|
|
6268
6352
|
// src/commands/prs/comment.ts
|
|
6269
6353
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
6270
|
-
import { unlinkSync as
|
|
6354
|
+
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync20 } from "fs";
|
|
6271
6355
|
import { tmpdir as tmpdir3 } from "os";
|
|
6272
|
-
import { join as
|
|
6356
|
+
import { join as join21 } from "path";
|
|
6273
6357
|
|
|
6274
6358
|
// src/commands/prs/shared.ts
|
|
6275
6359
|
import { execSync as execSync27 } from "child_process";
|
|
@@ -6341,8 +6425,8 @@ function comment2(path50, line, body) {
|
|
|
6341
6425
|
validateLine(line);
|
|
6342
6426
|
try {
|
|
6343
6427
|
const prId = getCurrentPrNodeId();
|
|
6344
|
-
const queryFile =
|
|
6345
|
-
|
|
6428
|
+
const queryFile = join21(tmpdir3(), `gh-query-${Date.now()}.graphql`);
|
|
6429
|
+
writeFileSync20(queryFile, MUTATION);
|
|
6346
6430
|
try {
|
|
6347
6431
|
const result = spawnSync2(
|
|
6348
6432
|
"gh",
|
|
@@ -6367,7 +6451,7 @@ function comment2(path50, line, body) {
|
|
|
6367
6451
|
}
|
|
6368
6452
|
console.log(`Added review comment on ${path50}:${line}`);
|
|
6369
6453
|
} finally {
|
|
6370
|
-
|
|
6454
|
+
unlinkSync6(queryFile);
|
|
6371
6455
|
}
|
|
6372
6456
|
} catch (error) {
|
|
6373
6457
|
if (isGhNotInstalled(error)) {
|
|
@@ -6384,29 +6468,29 @@ import { execSync as execSync29 } from "child_process";
|
|
|
6384
6468
|
|
|
6385
6469
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
6386
6470
|
import { execSync as execSync28 } from "child_process";
|
|
6387
|
-
import { unlinkSync as
|
|
6471
|
+
import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync21 } from "fs";
|
|
6388
6472
|
import { tmpdir as tmpdir4 } from "os";
|
|
6389
|
-
import { join as
|
|
6473
|
+
import { join as join23 } from "path";
|
|
6390
6474
|
|
|
6391
6475
|
// src/commands/prs/loadCommentsCache.ts
|
|
6392
|
-
import { existsSync as
|
|
6393
|
-
import { join as
|
|
6476
|
+
import { existsSync as existsSync29, readFileSync as readFileSync24, unlinkSync as unlinkSync7 } from "fs";
|
|
6477
|
+
import { join as join22 } from "path";
|
|
6394
6478
|
import { parse as parse2 } from "yaml";
|
|
6395
6479
|
function getCachePath(prNumber) {
|
|
6396
|
-
return
|
|
6480
|
+
return join22(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
6397
6481
|
}
|
|
6398
6482
|
function loadCommentsCache(prNumber) {
|
|
6399
6483
|
const cachePath = getCachePath(prNumber);
|
|
6400
|
-
if (!
|
|
6484
|
+
if (!existsSync29(cachePath)) {
|
|
6401
6485
|
return null;
|
|
6402
6486
|
}
|
|
6403
|
-
const content =
|
|
6487
|
+
const content = readFileSync24(cachePath, "utf-8");
|
|
6404
6488
|
return parse2(content);
|
|
6405
6489
|
}
|
|
6406
6490
|
function deleteCommentsCache(prNumber) {
|
|
6407
6491
|
const cachePath = getCachePath(prNumber);
|
|
6408
|
-
if (
|
|
6409
|
-
|
|
6492
|
+
if (existsSync29(cachePath)) {
|
|
6493
|
+
unlinkSync7(cachePath);
|
|
6410
6494
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
6411
6495
|
}
|
|
6412
6496
|
}
|
|
@@ -6420,15 +6504,15 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
6420
6504
|
}
|
|
6421
6505
|
function resolveThread(threadId) {
|
|
6422
6506
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
6423
|
-
const queryFile =
|
|
6424
|
-
|
|
6507
|
+
const queryFile = join23(tmpdir4(), `gh-mutation-${Date.now()}.graphql`);
|
|
6508
|
+
writeFileSync21(queryFile, mutation);
|
|
6425
6509
|
try {
|
|
6426
6510
|
execSync28(
|
|
6427
6511
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
6428
6512
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
6429
6513
|
);
|
|
6430
6514
|
} finally {
|
|
6431
|
-
|
|
6515
|
+
unlinkSync8(queryFile);
|
|
6432
6516
|
}
|
|
6433
6517
|
}
|
|
6434
6518
|
function requireCache(prNumber) {
|
|
@@ -6502,19 +6586,19 @@ function fixed(commentId, sha) {
|
|
|
6502
6586
|
}
|
|
6503
6587
|
|
|
6504
6588
|
// src/commands/prs/listComments/index.ts
|
|
6505
|
-
import { existsSync as
|
|
6506
|
-
import { join as
|
|
6589
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync6, writeFileSync as writeFileSync23 } from "fs";
|
|
6590
|
+
import { join as join25 } from "path";
|
|
6507
6591
|
import { stringify } from "yaml";
|
|
6508
6592
|
|
|
6509
6593
|
// src/commands/prs/fetchThreadIds.ts
|
|
6510
6594
|
import { execSync as execSync30 } from "child_process";
|
|
6511
|
-
import { unlinkSync as
|
|
6595
|
+
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
|
|
6512
6596
|
import { tmpdir as tmpdir5 } from "os";
|
|
6513
|
-
import { join as
|
|
6597
|
+
import { join as join24 } from "path";
|
|
6514
6598
|
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 } } } } } } }`;
|
|
6515
6599
|
function fetchThreadIds(org, repo, prNumber) {
|
|
6516
|
-
const queryFile =
|
|
6517
|
-
|
|
6600
|
+
const queryFile = join24(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
6601
|
+
writeFileSync22(queryFile, THREAD_QUERY);
|
|
6518
6602
|
try {
|
|
6519
6603
|
const result = execSync30(
|
|
6520
6604
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -6533,7 +6617,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
6533
6617
|
}
|
|
6534
6618
|
return { threadMap, resolvedThreadIds };
|
|
6535
6619
|
} finally {
|
|
6536
|
-
|
|
6620
|
+
unlinkSync9(queryFile);
|
|
6537
6621
|
}
|
|
6538
6622
|
}
|
|
6539
6623
|
|
|
@@ -6627,8 +6711,8 @@ function printComments2(result) {
|
|
|
6627
6711
|
|
|
6628
6712
|
// src/commands/prs/listComments/index.ts
|
|
6629
6713
|
function writeCommentsCache(prNumber, comments2) {
|
|
6630
|
-
const assistDir =
|
|
6631
|
-
if (!
|
|
6714
|
+
const assistDir = join25(process.cwd(), ".assist");
|
|
6715
|
+
if (!existsSync30(assistDir)) {
|
|
6632
6716
|
mkdirSync6(assistDir, { recursive: true });
|
|
6633
6717
|
}
|
|
6634
6718
|
const cacheData = {
|
|
@@ -6636,8 +6720,8 @@ function writeCommentsCache(prNumber, comments2) {
|
|
|
6636
6720
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6637
6721
|
comments: comments2
|
|
6638
6722
|
};
|
|
6639
|
-
const cachePath =
|
|
6640
|
-
|
|
6723
|
+
const cachePath = join25(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
6724
|
+
writeFileSync23(cachePath, stringify(cacheData));
|
|
6641
6725
|
}
|
|
6642
6726
|
function handleKnownErrors(error) {
|
|
6643
6727
|
if (isGhNotInstalled(error)) {
|
|
@@ -6669,7 +6753,7 @@ async function listComments() {
|
|
|
6669
6753
|
];
|
|
6670
6754
|
updateCache(prNumber, allComments);
|
|
6671
6755
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
6672
|
-
const cachePath = hasLineComments ?
|
|
6756
|
+
const cachePath = hasLineComments ? join25(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
6673
6757
|
return { comments: allComments, cachePath };
|
|
6674
6758
|
} catch (error) {
|
|
6675
6759
|
const handled = handleKnownErrors(error);
|
|
@@ -7069,9 +7153,9 @@ function clearCachedToken(apiKey) {
|
|
|
7069
7153
|
}
|
|
7070
7154
|
async function getAccessToken(apiKey) {
|
|
7071
7155
|
const now = Date.now();
|
|
7072
|
-
const
|
|
7073
|
-
if (
|
|
7074
|
-
return
|
|
7156
|
+
const cached = tokenCache.get(apiKey);
|
|
7157
|
+
if (cached && now < cached.expiry) {
|
|
7158
|
+
return cached.token;
|
|
7075
7159
|
}
|
|
7076
7160
|
const response = await fetch(OAUTH_URL, {
|
|
7077
7161
|
method: "GET",
|
|
@@ -8988,8 +9072,8 @@ function registerSeq(program2) {
|
|
|
8988
9072
|
}
|
|
8989
9073
|
|
|
8990
9074
|
// src/commands/transcript/shared.ts
|
|
8991
|
-
import { existsSync as
|
|
8992
|
-
import { basename as basename4, join as
|
|
9075
|
+
import { existsSync as existsSync31, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
|
|
9076
|
+
import { basename as basename4, join as join26, relative } from "path";
|
|
8993
9077
|
import * as readline2 from "readline";
|
|
8994
9078
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
8995
9079
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -9004,10 +9088,10 @@ function isValidDatePrefix(filename) {
|
|
|
9004
9088
|
return DATE_PREFIX_REGEX.test(filename);
|
|
9005
9089
|
}
|
|
9006
9090
|
function collectFiles(dir, extension) {
|
|
9007
|
-
if (!
|
|
9091
|
+
if (!existsSync31(dir)) return [];
|
|
9008
9092
|
const results = [];
|
|
9009
9093
|
for (const entry of readdirSync5(dir)) {
|
|
9010
|
-
const fullPath =
|
|
9094
|
+
const fullPath = join26(dir, entry);
|
|
9011
9095
|
if (statSync2(fullPath).isDirectory()) {
|
|
9012
9096
|
results.push(...collectFiles(fullPath, extension));
|
|
9013
9097
|
} else if (entry.endsWith(extension)) {
|
|
@@ -9101,14 +9185,14 @@ async function configure() {
|
|
|
9101
9185
|
}
|
|
9102
9186
|
|
|
9103
9187
|
// src/commands/transcript/format/index.ts
|
|
9104
|
-
import { existsSync as
|
|
9188
|
+
import { existsSync as existsSync33 } from "fs";
|
|
9105
9189
|
|
|
9106
9190
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
9107
|
-
import { dirname as dirname18, join as
|
|
9191
|
+
import { dirname as dirname18, join as join28 } from "path";
|
|
9108
9192
|
|
|
9109
9193
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
9110
9194
|
import { renameSync } from "fs";
|
|
9111
|
-
import { join as
|
|
9195
|
+
import { join as join27 } from "path";
|
|
9112
9196
|
async function resolveDate(rl, choice) {
|
|
9113
9197
|
if (choice === "1") return getDatePrefix(0);
|
|
9114
9198
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -9123,7 +9207,7 @@ async function resolveDate(rl, choice) {
|
|
|
9123
9207
|
}
|
|
9124
9208
|
function renameWithPrefix(vttDir, vttFile, prefix2) {
|
|
9125
9209
|
const newFilename = `${prefix2}.${vttFile}`;
|
|
9126
|
-
renameSync(
|
|
9210
|
+
renameSync(join27(vttDir, vttFile), join27(vttDir, newFilename));
|
|
9127
9211
|
console.log(`Renamed to: ${newFilename}`);
|
|
9128
9212
|
return newFilename;
|
|
9129
9213
|
}
|
|
@@ -9157,12 +9241,12 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
9157
9241
|
const vttFileDir = dirname18(vttFile.absolutePath);
|
|
9158
9242
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
9159
9243
|
if (newFilename) {
|
|
9160
|
-
const newRelativePath =
|
|
9244
|
+
const newRelativePath = join28(
|
|
9161
9245
|
dirname18(vttFile.relativePath),
|
|
9162
9246
|
newFilename
|
|
9163
9247
|
);
|
|
9164
9248
|
vttFiles[i] = {
|
|
9165
|
-
absolutePath:
|
|
9249
|
+
absolutePath: join28(vttFileDir, newFilename),
|
|
9166
9250
|
relativePath: newRelativePath,
|
|
9167
9251
|
filename: newFilename
|
|
9168
9252
|
};
|
|
@@ -9175,8 +9259,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
9175
9259
|
}
|
|
9176
9260
|
|
|
9177
9261
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
9178
|
-
import { existsSync as
|
|
9179
|
-
import { basename as basename5, dirname as dirname19, join as
|
|
9262
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync7, readFileSync as readFileSync25, writeFileSync as writeFileSync24 } from "fs";
|
|
9263
|
+
import { basename as basename5, dirname as dirname19, join as join29 } from "path";
|
|
9180
9264
|
|
|
9181
9265
|
// src/commands/transcript/cleanText.ts
|
|
9182
9266
|
function cleanText(text) {
|
|
@@ -9386,21 +9470,21 @@ function toMdFilename(vttFilename) {
|
|
|
9386
9470
|
return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
9387
9471
|
}
|
|
9388
9472
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
9389
|
-
return relativeDir === "." ? transcriptsDir :
|
|
9473
|
+
return relativeDir === "." ? transcriptsDir : join29(transcriptsDir, relativeDir);
|
|
9390
9474
|
}
|
|
9391
9475
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
9392
9476
|
const mdFile = toMdFilename(vttFile.filename);
|
|
9393
9477
|
const relativeDir = dirname19(vttFile.relativePath);
|
|
9394
9478
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
9395
|
-
const outputPath =
|
|
9479
|
+
const outputPath = join29(outputDir, mdFile);
|
|
9396
9480
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
9397
9481
|
}
|
|
9398
9482
|
function logSkipped(relativeDir, mdFile) {
|
|
9399
|
-
console.log(`Skipping (already exists): ${
|
|
9483
|
+
console.log(`Skipping (already exists): ${join29(relativeDir, mdFile)}`);
|
|
9400
9484
|
return "skipped";
|
|
9401
9485
|
}
|
|
9402
9486
|
function ensureDirectory(dir, label2) {
|
|
9403
|
-
if (!
|
|
9487
|
+
if (!existsSync32(dir)) {
|
|
9404
9488
|
mkdirSync7(dir, { recursive: true });
|
|
9405
9489
|
console.log(`Created ${label2}: ${dir}`);
|
|
9406
9490
|
}
|
|
@@ -9423,10 +9507,10 @@ function logReduction(cueCount, messageCount) {
|
|
|
9423
9507
|
}
|
|
9424
9508
|
function readAndParseCues(inputPath) {
|
|
9425
9509
|
console.log(`Reading: ${inputPath}`);
|
|
9426
|
-
return processCues(
|
|
9510
|
+
return processCues(readFileSync25(inputPath, "utf-8"));
|
|
9427
9511
|
}
|
|
9428
9512
|
function writeFormatted(outputPath, content) {
|
|
9429
|
-
|
|
9513
|
+
writeFileSync24(outputPath, content, "utf-8");
|
|
9430
9514
|
console.log(`Written: ${outputPath}`);
|
|
9431
9515
|
}
|
|
9432
9516
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -9436,7 +9520,7 @@ function convertVttToMarkdown(inputPath, outputPath) {
|
|
|
9436
9520
|
logReduction(cues.length, chatMessages.length);
|
|
9437
9521
|
}
|
|
9438
9522
|
function tryProcessVtt(vttFile, paths) {
|
|
9439
|
-
if (
|
|
9523
|
+
if (existsSync32(paths.outputPath))
|
|
9440
9524
|
return logSkipped(paths.relativeDir, paths.mdFile);
|
|
9441
9525
|
convertVttToMarkdown(vttFile.absolutePath, paths.outputPath);
|
|
9442
9526
|
return "processed";
|
|
@@ -9462,7 +9546,7 @@ function processAllFiles(vttFiles, transcriptsDir) {
|
|
|
9462
9546
|
logSummary(counts);
|
|
9463
9547
|
}
|
|
9464
9548
|
function requireVttDir(vttDir) {
|
|
9465
|
-
if (!
|
|
9549
|
+
if (!existsSync33(vttDir)) {
|
|
9466
9550
|
console.error(`VTT directory not found: ${vttDir}`);
|
|
9467
9551
|
process.exit(1);
|
|
9468
9552
|
}
|
|
@@ -9494,18 +9578,18 @@ async function format() {
|
|
|
9494
9578
|
}
|
|
9495
9579
|
|
|
9496
9580
|
// src/commands/transcript/summarise/index.ts
|
|
9497
|
-
import { existsSync as
|
|
9498
|
-
import { basename as basename6, dirname as dirname21, join as
|
|
9581
|
+
import { existsSync as existsSync35 } from "fs";
|
|
9582
|
+
import { basename as basename6, dirname as dirname21, join as join31, relative as relative2 } from "path";
|
|
9499
9583
|
|
|
9500
9584
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
9501
9585
|
import {
|
|
9502
|
-
existsSync as
|
|
9586
|
+
existsSync as existsSync34,
|
|
9503
9587
|
mkdirSync as mkdirSync8,
|
|
9504
|
-
readFileSync as
|
|
9588
|
+
readFileSync as readFileSync26,
|
|
9505
9589
|
renameSync as renameSync2,
|
|
9506
9590
|
rmSync
|
|
9507
9591
|
} from "fs";
|
|
9508
|
-
import { dirname as dirname20, join as
|
|
9592
|
+
import { dirname as dirname20, join as join30 } from "path";
|
|
9509
9593
|
|
|
9510
9594
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
9511
9595
|
import chalk107 from "chalk";
|
|
@@ -9534,9 +9618,9 @@ function validateStagedContent(filename, content) {
|
|
|
9534
9618
|
}
|
|
9535
9619
|
|
|
9536
9620
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
9537
|
-
var STAGING_DIR =
|
|
9621
|
+
var STAGING_DIR = join30(process.cwd(), ".assist", "transcript");
|
|
9538
9622
|
function processStagedFile() {
|
|
9539
|
-
if (!
|
|
9623
|
+
if (!existsSync34(STAGING_DIR)) {
|
|
9540
9624
|
return false;
|
|
9541
9625
|
}
|
|
9542
9626
|
const stagedFiles = findMdFilesRecursive(STAGING_DIR);
|
|
@@ -9545,7 +9629,7 @@ function processStagedFile() {
|
|
|
9545
9629
|
}
|
|
9546
9630
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
9547
9631
|
const stagedFile = stagedFiles[0];
|
|
9548
|
-
const content =
|
|
9632
|
+
const content = readFileSync26(stagedFile.absolutePath, "utf-8");
|
|
9549
9633
|
validateStagedContent(stagedFile.filename, content);
|
|
9550
9634
|
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
9551
9635
|
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
@@ -9558,9 +9642,9 @@ function processStagedFile() {
|
|
|
9558
9642
|
);
|
|
9559
9643
|
process.exit(1);
|
|
9560
9644
|
}
|
|
9561
|
-
const destPath =
|
|
9645
|
+
const destPath = join30(summaryDir, matchingTranscript.relativePath);
|
|
9562
9646
|
const destDir = dirname20(destPath);
|
|
9563
|
-
if (!
|
|
9647
|
+
if (!existsSync34(destDir)) {
|
|
9564
9648
|
mkdirSync8(destDir, { recursive: true });
|
|
9565
9649
|
}
|
|
9566
9650
|
renameSync2(stagedFile.absolutePath, destPath);
|
|
@@ -9574,7 +9658,7 @@ function processStagedFile() {
|
|
|
9574
9658
|
// src/commands/transcript/summarise/index.ts
|
|
9575
9659
|
function buildRelativeKey(relativePath, baseName) {
|
|
9576
9660
|
const relDir = dirname21(relativePath);
|
|
9577
|
-
return relDir === "." ? baseName :
|
|
9661
|
+
return relDir === "." ? baseName : join31(relDir, baseName);
|
|
9578
9662
|
}
|
|
9579
9663
|
function buildSummaryIndex(summaryDir) {
|
|
9580
9664
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -9587,7 +9671,7 @@ function buildSummaryIndex(summaryDir) {
|
|
|
9587
9671
|
function summarise2() {
|
|
9588
9672
|
processStagedFile();
|
|
9589
9673
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
9590
|
-
if (!
|
|
9674
|
+
if (!existsSync35(transcriptsDir)) {
|
|
9591
9675
|
console.log("No transcripts directory found.");
|
|
9592
9676
|
return;
|
|
9593
9677
|
}
|
|
@@ -9608,8 +9692,8 @@ function summarise2() {
|
|
|
9608
9692
|
}
|
|
9609
9693
|
const next3 = missing[0];
|
|
9610
9694
|
const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
|
|
9611
|
-
const outputPath =
|
|
9612
|
-
const summaryFileDir =
|
|
9695
|
+
const outputPath = join31(STAGING_DIR, outputFilename);
|
|
9696
|
+
const summaryFileDir = join31(summaryDir, dirname21(next3.relativePath));
|
|
9613
9697
|
const relativeTranscriptPath = encodeURI(
|
|
9614
9698
|
relative2(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
|
|
9615
9699
|
);
|
|
@@ -9655,50 +9739,50 @@ function registerVerify(program2) {
|
|
|
9655
9739
|
|
|
9656
9740
|
// src/commands/voice/devices.ts
|
|
9657
9741
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
9658
|
-
import { join as
|
|
9742
|
+
import { join as join33 } from "path";
|
|
9659
9743
|
|
|
9660
9744
|
// src/commands/voice/shared.ts
|
|
9661
9745
|
import { homedir as homedir7 } from "os";
|
|
9662
|
-
import { dirname as dirname22, join as
|
|
9746
|
+
import { dirname as dirname22, join as join32 } from "path";
|
|
9663
9747
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
9664
9748
|
var __dirname6 = dirname22(fileURLToPath6(import.meta.url));
|
|
9665
|
-
var VOICE_DIR =
|
|
9749
|
+
var VOICE_DIR = join32(homedir7(), ".assist", "voice");
|
|
9666
9750
|
var voicePaths = {
|
|
9667
9751
|
dir: VOICE_DIR,
|
|
9668
|
-
pid:
|
|
9669
|
-
log:
|
|
9670
|
-
venv:
|
|
9671
|
-
lock:
|
|
9752
|
+
pid: join32(VOICE_DIR, "voice.pid"),
|
|
9753
|
+
log: join32(VOICE_DIR, "voice.log"),
|
|
9754
|
+
venv: join32(VOICE_DIR, ".venv"),
|
|
9755
|
+
lock: join32(VOICE_DIR, "voice.lock")
|
|
9672
9756
|
};
|
|
9673
9757
|
function getPythonDir() {
|
|
9674
|
-
return
|
|
9758
|
+
return join32(__dirname6, "commands", "voice", "python");
|
|
9675
9759
|
}
|
|
9676
9760
|
function getVenvPython() {
|
|
9677
|
-
return process.platform === "win32" ?
|
|
9761
|
+
return process.platform === "win32" ? join32(voicePaths.venv, "Scripts", "python.exe") : join32(voicePaths.venv, "bin", "python");
|
|
9678
9762
|
}
|
|
9679
9763
|
function getLockDir() {
|
|
9680
9764
|
const config = loadConfig();
|
|
9681
9765
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
9682
9766
|
}
|
|
9683
9767
|
function getLockFile() {
|
|
9684
|
-
return
|
|
9768
|
+
return join32(getLockDir(), "voice.lock");
|
|
9685
9769
|
}
|
|
9686
9770
|
|
|
9687
9771
|
// src/commands/voice/devices.ts
|
|
9688
9772
|
function devices() {
|
|
9689
|
-
const script =
|
|
9773
|
+
const script = join33(getPythonDir(), "list_devices.py");
|
|
9690
9774
|
spawnSync3(getVenvPython(), [script], { stdio: "inherit" });
|
|
9691
9775
|
}
|
|
9692
9776
|
|
|
9693
9777
|
// src/commands/voice/logs.ts
|
|
9694
|
-
import { existsSync as
|
|
9778
|
+
import { existsSync as existsSync36, readFileSync as readFileSync27 } from "fs";
|
|
9695
9779
|
function logs(options2) {
|
|
9696
|
-
if (!
|
|
9780
|
+
if (!existsSync36(voicePaths.log)) {
|
|
9697
9781
|
console.log("No voice log file found");
|
|
9698
9782
|
return;
|
|
9699
9783
|
}
|
|
9700
9784
|
const count = Number.parseInt(options2.lines ?? "150", 10);
|
|
9701
|
-
const content =
|
|
9785
|
+
const content = readFileSync27(voicePaths.log, "utf-8").trim();
|
|
9702
9786
|
if (!content) {
|
|
9703
9787
|
console.log("Voice log is empty");
|
|
9704
9788
|
return;
|
|
@@ -9721,13 +9805,13 @@ function logs(options2) {
|
|
|
9721
9805
|
// src/commands/voice/setup.ts
|
|
9722
9806
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
9723
9807
|
import { mkdirSync as mkdirSync10 } from "fs";
|
|
9724
|
-
import { join as
|
|
9808
|
+
import { join as join35 } from "path";
|
|
9725
9809
|
|
|
9726
9810
|
// src/commands/voice/checkLockFile.ts
|
|
9727
9811
|
import { execSync as execSync37 } from "child_process";
|
|
9728
|
-
import { existsSync as
|
|
9729
|
-
import { join as
|
|
9730
|
-
function
|
|
9812
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync9, readFileSync as readFileSync28, writeFileSync as writeFileSync25 } from "fs";
|
|
9813
|
+
import { join as join34 } from "path";
|
|
9814
|
+
function isProcessAlive2(pid) {
|
|
9731
9815
|
try {
|
|
9732
9816
|
process.kill(pid, 0);
|
|
9733
9817
|
return true;
|
|
@@ -9737,10 +9821,10 @@ function isProcessAlive(pid) {
|
|
|
9737
9821
|
}
|
|
9738
9822
|
function checkLockFile() {
|
|
9739
9823
|
const lockFile = getLockFile();
|
|
9740
|
-
if (!
|
|
9824
|
+
if (!existsSync37(lockFile)) return;
|
|
9741
9825
|
try {
|
|
9742
|
-
const lock = JSON.parse(
|
|
9743
|
-
if (lock.pid &&
|
|
9826
|
+
const lock = JSON.parse(readFileSync28(lockFile, "utf-8"));
|
|
9827
|
+
if (lock.pid && isProcessAlive2(lock.pid)) {
|
|
9744
9828
|
console.error(
|
|
9745
9829
|
`Voice daemon already running (PID ${lock.pid}, env: ${lock.env}). Stop it first with: assist voice stop`
|
|
9746
9830
|
);
|
|
@@ -9750,7 +9834,7 @@ function checkLockFile() {
|
|
|
9750
9834
|
}
|
|
9751
9835
|
}
|
|
9752
9836
|
function bootstrapVenv() {
|
|
9753
|
-
if (
|
|
9837
|
+
if (existsSync37(getVenvPython())) return;
|
|
9754
9838
|
console.log("Setting up Python environment...");
|
|
9755
9839
|
const pythonDir = getPythonDir();
|
|
9756
9840
|
execSync37(
|
|
@@ -9763,8 +9847,8 @@ function bootstrapVenv() {
|
|
|
9763
9847
|
}
|
|
9764
9848
|
function writeLockFile(pid) {
|
|
9765
9849
|
const lockFile = getLockFile();
|
|
9766
|
-
mkdirSync9(
|
|
9767
|
-
|
|
9850
|
+
mkdirSync9(join34(lockFile, ".."), { recursive: true });
|
|
9851
|
+
writeFileSync25(
|
|
9768
9852
|
lockFile,
|
|
9769
9853
|
JSON.stringify({
|
|
9770
9854
|
pid,
|
|
@@ -9779,7 +9863,7 @@ function setup() {
|
|
|
9779
9863
|
mkdirSync10(voicePaths.dir, { recursive: true });
|
|
9780
9864
|
bootstrapVenv();
|
|
9781
9865
|
console.log("\nDownloading models...\n");
|
|
9782
|
-
const script =
|
|
9866
|
+
const script = join35(getPythonDir(), "setup_models.py");
|
|
9783
9867
|
const result = spawnSync4(getVenvPython(), [script], {
|
|
9784
9868
|
stdio: "inherit",
|
|
9785
9869
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -9792,8 +9876,8 @@ function setup() {
|
|
|
9792
9876
|
|
|
9793
9877
|
// src/commands/voice/start.ts
|
|
9794
9878
|
import { spawn as spawn5 } from "child_process";
|
|
9795
|
-
import { mkdirSync as mkdirSync11, writeFileSync as
|
|
9796
|
-
import { join as
|
|
9879
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync26 } from "fs";
|
|
9880
|
+
import { join as join36 } from "path";
|
|
9797
9881
|
|
|
9798
9882
|
// src/commands/voice/buildDaemonEnv.ts
|
|
9799
9883
|
function buildDaemonEnv(options2) {
|
|
@@ -9821,7 +9905,7 @@ function spawnBackground(python, script, env) {
|
|
|
9821
9905
|
console.error("Failed to start voice daemon");
|
|
9822
9906
|
process.exit(1);
|
|
9823
9907
|
}
|
|
9824
|
-
|
|
9908
|
+
writeFileSync26(voicePaths.pid, String(pid));
|
|
9825
9909
|
writeLockFile(pid);
|
|
9826
9910
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
9827
9911
|
}
|
|
@@ -9831,7 +9915,7 @@ function start2(options2) {
|
|
|
9831
9915
|
bootstrapVenv();
|
|
9832
9916
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
9833
9917
|
const env = buildDaemonEnv({ debug });
|
|
9834
|
-
const script =
|
|
9918
|
+
const script = join36(getPythonDir(), "voice_daemon.py");
|
|
9835
9919
|
const python = getVenvPython();
|
|
9836
9920
|
if (options2.foreground) {
|
|
9837
9921
|
spawnForeground(python, script, env);
|
|
@@ -9841,8 +9925,8 @@ function start2(options2) {
|
|
|
9841
9925
|
}
|
|
9842
9926
|
|
|
9843
9927
|
// src/commands/voice/status.ts
|
|
9844
|
-
import { existsSync as
|
|
9845
|
-
function
|
|
9928
|
+
import { existsSync as existsSync38, readFileSync as readFileSync29 } from "fs";
|
|
9929
|
+
function isProcessAlive3(pid) {
|
|
9846
9930
|
try {
|
|
9847
9931
|
process.kill(pid, 0);
|
|
9848
9932
|
return true;
|
|
@@ -9851,17 +9935,17 @@ function isProcessAlive2(pid) {
|
|
|
9851
9935
|
}
|
|
9852
9936
|
}
|
|
9853
9937
|
function readRecentLogs(count) {
|
|
9854
|
-
if (!
|
|
9855
|
-
const lines =
|
|
9938
|
+
if (!existsSync38(voicePaths.log)) return [];
|
|
9939
|
+
const lines = readFileSync29(voicePaths.log, "utf-8").trim().split("\n");
|
|
9856
9940
|
return lines.slice(-count);
|
|
9857
9941
|
}
|
|
9858
9942
|
function status() {
|
|
9859
|
-
if (!
|
|
9943
|
+
if (!existsSync38(voicePaths.pid)) {
|
|
9860
9944
|
console.log("Voice daemon: not running (no PID file)");
|
|
9861
9945
|
return;
|
|
9862
9946
|
}
|
|
9863
|
-
const pid = Number.parseInt(
|
|
9864
|
-
const alive =
|
|
9947
|
+
const pid = Number.parseInt(readFileSync29(voicePaths.pid, "utf-8").trim(), 10);
|
|
9948
|
+
const alive = isProcessAlive3(pid);
|
|
9865
9949
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
9866
9950
|
const recent = readRecentLogs(5);
|
|
9867
9951
|
if (recent.length > 0) {
|
|
@@ -9879,13 +9963,13 @@ function status() {
|
|
|
9879
9963
|
}
|
|
9880
9964
|
|
|
9881
9965
|
// src/commands/voice/stop.ts
|
|
9882
|
-
import { existsSync as
|
|
9966
|
+
import { existsSync as existsSync39, readFileSync as readFileSync30, unlinkSync as unlinkSync10 } from "fs";
|
|
9883
9967
|
function stop() {
|
|
9884
|
-
if (!
|
|
9968
|
+
if (!existsSync39(voicePaths.pid)) {
|
|
9885
9969
|
console.log("Voice daemon is not running (no PID file)");
|
|
9886
9970
|
return;
|
|
9887
9971
|
}
|
|
9888
|
-
const pid = Number.parseInt(
|
|
9972
|
+
const pid = Number.parseInt(readFileSync30(voicePaths.pid, "utf-8").trim(), 10);
|
|
9889
9973
|
try {
|
|
9890
9974
|
process.kill(pid, "SIGTERM");
|
|
9891
9975
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -9893,12 +9977,12 @@ function stop() {
|
|
|
9893
9977
|
console.log(`Voice daemon (PID ${pid}) is not running`);
|
|
9894
9978
|
}
|
|
9895
9979
|
try {
|
|
9896
|
-
|
|
9980
|
+
unlinkSync10(voicePaths.pid);
|
|
9897
9981
|
} catch {
|
|
9898
9982
|
}
|
|
9899
9983
|
try {
|
|
9900
9984
|
const lockFile = getLockFile();
|
|
9901
|
-
if (
|
|
9985
|
+
if (existsSync39(lockFile)) unlinkSync10(lockFile);
|
|
9902
9986
|
} catch {
|
|
9903
9987
|
}
|
|
9904
9988
|
console.log("Voice daemon stopped");
|
|
@@ -10119,15 +10203,15 @@ async function auth() {
|
|
|
10119
10203
|
}
|
|
10120
10204
|
|
|
10121
10205
|
// src/commands/roam/showClaudeCodeIcon.ts
|
|
10122
|
-
import { readFileSync as
|
|
10123
|
-
import { join as
|
|
10206
|
+
import { readFileSync as readFileSync31 } from "fs";
|
|
10207
|
+
import { join as join37 } from "path";
|
|
10124
10208
|
async function showClaudeCodeIcon() {
|
|
10125
10209
|
const appData = process.env.APPDATA;
|
|
10126
10210
|
if (!appData) return;
|
|
10127
|
-
const portFile =
|
|
10211
|
+
const portFile = join37(appData, "Roam", "roam-local-api.port");
|
|
10128
10212
|
let port;
|
|
10129
10213
|
try {
|
|
10130
|
-
port =
|
|
10214
|
+
port = readFileSync31(portFile, "utf-8").trim();
|
|
10131
10215
|
} catch {
|
|
10132
10216
|
return;
|
|
10133
10217
|
}
|
|
@@ -10198,8 +10282,8 @@ Done in ${elapsed}`);
|
|
|
10198
10282
|
}
|
|
10199
10283
|
|
|
10200
10284
|
// src/commands/run/add.ts
|
|
10201
|
-
import { mkdirSync as mkdirSync12, writeFileSync as
|
|
10202
|
-
import { join as
|
|
10285
|
+
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync27 } from "fs";
|
|
10286
|
+
import { join as join38 } from "path";
|
|
10203
10287
|
function findAddIndex() {
|
|
10204
10288
|
const addIndex = process.argv.indexOf("add");
|
|
10205
10289
|
if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
|
|
@@ -10245,7 +10329,7 @@ function saveNewRunConfig(name, command, args) {
|
|
|
10245
10329
|
saveConfig(config);
|
|
10246
10330
|
}
|
|
10247
10331
|
function createCommandFile(name) {
|
|
10248
|
-
const dir =
|
|
10332
|
+
const dir = join38(".claude", "commands");
|
|
10249
10333
|
mkdirSync12(dir, { recursive: true });
|
|
10250
10334
|
const content = `---
|
|
10251
10335
|
description: Run ${name}
|
|
@@ -10253,8 +10337,8 @@ description: Run ${name}
|
|
|
10253
10337
|
|
|
10254
10338
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
10255
10339
|
`;
|
|
10256
|
-
const filePath =
|
|
10257
|
-
|
|
10340
|
+
const filePath = join38(dir, `${name}.md`);
|
|
10341
|
+
writeFileSync27(filePath, content);
|
|
10258
10342
|
console.log(`Created command file: ${filePath}`);
|
|
10259
10343
|
}
|
|
10260
10344
|
function add3() {
|
|
@@ -10324,9 +10408,9 @@ function run3(name, args) {
|
|
|
10324
10408
|
|
|
10325
10409
|
// src/commands/screenshot/index.ts
|
|
10326
10410
|
import { execSync as execSync40 } from "child_process";
|
|
10327
|
-
import { existsSync as
|
|
10411
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync13, unlinkSync as unlinkSync11, writeFileSync as writeFileSync28 } from "fs";
|
|
10328
10412
|
import { tmpdir as tmpdir6 } from "os";
|
|
10329
|
-
import { join as
|
|
10413
|
+
import { join as join39, resolve as resolve5 } from "path";
|
|
10330
10414
|
import chalk109 from "chalk";
|
|
10331
10415
|
|
|
10332
10416
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -10456,22 +10540,22 @@ Write-Output $OutputPath
|
|
|
10456
10540
|
|
|
10457
10541
|
// src/commands/screenshot/index.ts
|
|
10458
10542
|
function buildOutputPath(outputDir, processName) {
|
|
10459
|
-
if (!
|
|
10543
|
+
if (!existsSync40(outputDir)) {
|
|
10460
10544
|
mkdirSync13(outputDir, { recursive: true });
|
|
10461
10545
|
}
|
|
10462
10546
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
10463
10547
|
return resolve5(outputDir, `${processName}-${timestamp}.png`);
|
|
10464
10548
|
}
|
|
10465
10549
|
function runPowerShellScript(processName, outputPath) {
|
|
10466
|
-
const scriptPath =
|
|
10467
|
-
|
|
10550
|
+
const scriptPath = join39(tmpdir6(), `assist-screenshot-${Date.now()}.ps1`);
|
|
10551
|
+
writeFileSync28(scriptPath, captureWindowPs1, "utf-8");
|
|
10468
10552
|
try {
|
|
10469
10553
|
execSync40(
|
|
10470
10554
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
10471
10555
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
10472
10556
|
);
|
|
10473
10557
|
} finally {
|
|
10474
|
-
|
|
10558
|
+
unlinkSync11(scriptPath);
|
|
10475
10559
|
}
|
|
10476
10560
|
}
|
|
10477
10561
|
function screenshot(processName) {
|