@staff0rd/assist 0.444.1 → 0.445.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 +8 -3
- package/dist/commands/sessions/web/bundle.js +2 -2
- package/dist/index.js +935 -844
- 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.445.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -121,7 +121,7 @@ var package_default = {
|
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
// src/commands/commit.ts
|
|
124
|
-
import { execSync as
|
|
124
|
+
import { execSync as execSync7 } from "child_process";
|
|
125
125
|
|
|
126
126
|
// src/shared/resolveSessionItemId.ts
|
|
127
127
|
var ITEM_ID_ENV = "ASSIST_BACKLOG_ITEM_ID";
|
|
@@ -435,6 +435,7 @@ var assistConfigSchema = z2.strictObject({
|
|
|
435
435
|
repos: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional(),
|
|
436
436
|
worktree: z2.strictObject({
|
|
437
437
|
enabled: z2.boolean().default(false),
|
|
438
|
+
trunk: z2.boolean().default(false),
|
|
438
439
|
root: z2.string().optional(),
|
|
439
440
|
install: z2.union([z2.boolean(), z2.string()]).default(true),
|
|
440
441
|
commitBeforeManualChecks: z2.boolean().default(false),
|
|
@@ -1782,17 +1783,49 @@ function git(args) {
|
|
|
1782
1783
|
}
|
|
1783
1784
|
}
|
|
1784
1785
|
|
|
1785
|
-
// src/commands/commit/
|
|
1786
|
+
// src/commands/commit/pushCommit.ts
|
|
1786
1787
|
import { execSync as execSync5 } from "child_process";
|
|
1788
|
+
var HEADS_PREFIX = "refs/heads/";
|
|
1789
|
+
function pushCommit() {
|
|
1790
|
+
const target = renamedUpstream();
|
|
1791
|
+
const command = target ? `git push ${shellQuote(target.remote)} HEAD:${shellQuote(target.branch)}` : "git push";
|
|
1792
|
+
execSync5(command, { stdio: "inherit" });
|
|
1793
|
+
}
|
|
1794
|
+
function renamedUpstream() {
|
|
1795
|
+
const branch2 = gitOrNull("git symbolic-ref --short HEAD");
|
|
1796
|
+
if (!branch2) return null;
|
|
1797
|
+
const remote = gitOrNull(
|
|
1798
|
+
`git config --get branch.${shellQuote(branch2)}.remote`
|
|
1799
|
+
);
|
|
1800
|
+
const merge = gitOrNull(
|
|
1801
|
+
`git config --get branch.${shellQuote(branch2)}.merge`
|
|
1802
|
+
);
|
|
1803
|
+
if (!remote || !merge) return null;
|
|
1804
|
+
const upstream = merge.startsWith(HEADS_PREFIX) ? merge.slice(HEADS_PREFIX.length) : merge;
|
|
1805
|
+
return upstream === branch2 ? null : { remote, branch: upstream };
|
|
1806
|
+
}
|
|
1807
|
+
function gitOrNull(command) {
|
|
1808
|
+
try {
|
|
1809
|
+
return execSync5(command, {
|
|
1810
|
+
encoding: "utf8",
|
|
1811
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1812
|
+
}).trim() || null;
|
|
1813
|
+
} catch {
|
|
1814
|
+
return null;
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
// src/commands/commit/stageAndCommit.ts
|
|
1819
|
+
import { execSync as execSync6 } from "child_process";
|
|
1787
1820
|
function commitStaged(message2) {
|
|
1788
|
-
|
|
1789
|
-
return
|
|
1821
|
+
execSync6(`git commit -m ${shellQuote(message2)}`, { stdio: "inherit" });
|
|
1822
|
+
return execSync6("git rev-parse --short=7 HEAD", {
|
|
1790
1823
|
encoding: "utf8"
|
|
1791
1824
|
}).trim();
|
|
1792
1825
|
}
|
|
1793
1826
|
function stageAndCommit(files, message2) {
|
|
1794
1827
|
const escaped = files.map(shellQuote).join(" ");
|
|
1795
|
-
|
|
1828
|
+
execSync6(`git add ${escaped}`, { stdio: "inherit" });
|
|
1796
1829
|
return commitStaged(message2);
|
|
1797
1830
|
}
|
|
1798
1831
|
|
|
@@ -1920,13 +1953,13 @@ async function execCommit(files, message2, config) {
|
|
|
1920
1953
|
warnIfUnexpectedBranch(config);
|
|
1921
1954
|
const pulled = Boolean(config.commit?.pull);
|
|
1922
1955
|
if (pulled) {
|
|
1923
|
-
|
|
1956
|
+
execSync7("git pull --autostash", { stdio: "inherit" });
|
|
1924
1957
|
}
|
|
1925
1958
|
abortOnConflicts(files, pulled);
|
|
1926
1959
|
const sha = files.length > 0 ? stageAndCommit(files, message2) : commitStaged(message2);
|
|
1927
1960
|
console.log(`Committed: ${sha}`);
|
|
1928
1961
|
if (config.commit?.push) {
|
|
1929
|
-
|
|
1962
|
+
pushCommit();
|
|
1930
1963
|
console.log("Pushed to remote");
|
|
1931
1964
|
}
|
|
1932
1965
|
await recordCommitActivity(message2);
|
|
@@ -1941,7 +1974,7 @@ async function recordCommitActivity(message2) {
|
|
|
1941
1974
|
}
|
|
1942
1975
|
async function commit(args) {
|
|
1943
1976
|
if (args[0] === "status") {
|
|
1944
|
-
|
|
1977
|
+
execSync7("git status && echo '---DIFF---' && git diff", {
|
|
1945
1978
|
stdio: "inherit"
|
|
1946
1979
|
});
|
|
1947
1980
|
return;
|
|
@@ -1958,9 +1991,9 @@ async function commit(args) {
|
|
|
1958
1991
|
}
|
|
1959
1992
|
|
|
1960
1993
|
// src/commands/coverage.ts
|
|
1961
|
-
import { execSync as
|
|
1994
|
+
import { execSync as execSync8 } from "child_process";
|
|
1962
1995
|
function coverage() {
|
|
1963
|
-
const output =
|
|
1996
|
+
const output = execSync8(
|
|
1964
1997
|
"npx vitest run --coverage --coverage.include='src/**/*.ts' --coverage.all --coverage.reporter=text 2>&1",
|
|
1965
1998
|
{ encoding: "utf8", timeout: 12e4 }
|
|
1966
1999
|
);
|
|
@@ -2060,7 +2093,7 @@ function findPackageJsonWithVerifyScripts(startDir) {
|
|
|
2060
2093
|
}
|
|
2061
2094
|
|
|
2062
2095
|
// src/commands/verify/installPackage.ts
|
|
2063
|
-
import { execSync as
|
|
2096
|
+
import { execSync as execSync9 } from "child_process";
|
|
2064
2097
|
import { writeFileSync as writeFileSync2 } from "fs";
|
|
2065
2098
|
import chalk6 from "chalk";
|
|
2066
2099
|
function writePackageJson(filePath, pkg) {
|
|
@@ -2079,7 +2112,7 @@ function addScript(pkg, name, command) {
|
|
|
2079
2112
|
function installPackage(name, cwd) {
|
|
2080
2113
|
console.log(chalk6.dim(`Installing ${name}...`));
|
|
2081
2114
|
try {
|
|
2082
|
-
|
|
2115
|
+
execSync9(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
2083
2116
|
return true;
|
|
2084
2117
|
} catch {
|
|
2085
2118
|
console.error(chalk6.red(`Failed to install ${name}`));
|
|
@@ -2323,7 +2356,7 @@ import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync
|
|
|
2323
2356
|
import chalk14 from "chalk";
|
|
2324
2357
|
|
|
2325
2358
|
// src/shared/removeEslint/index.ts
|
|
2326
|
-
import { execSync as
|
|
2359
|
+
import { execSync as execSync10 } from "child_process";
|
|
2327
2360
|
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
2328
2361
|
|
|
2329
2362
|
// src/shared/removeEslint/removeEslintConfigFiles.ts
|
|
@@ -2358,7 +2391,7 @@ function removeEslint(options2 = {}) {
|
|
|
2358
2391
|
const removedConfigFiles = removeEslintConfigFiles();
|
|
2359
2392
|
if (removedFromPackageJson || removedConfigFiles) {
|
|
2360
2393
|
console.log("Running npm install...");
|
|
2361
|
-
|
|
2394
|
+
execSync10("npm install", { stdio: "inherit" });
|
|
2362
2395
|
return true;
|
|
2363
2396
|
}
|
|
2364
2397
|
return false;
|
|
@@ -3206,11 +3239,11 @@ function lint(options2 = {}) {
|
|
|
3206
3239
|
}
|
|
3207
3240
|
|
|
3208
3241
|
// src/commands/new/registerNew/newCli/index.ts
|
|
3209
|
-
import { execSync as
|
|
3242
|
+
import { execSync as execSync19 } from "child_process";
|
|
3210
3243
|
import { basename as basename2, resolve as resolve5 } from "path";
|
|
3211
3244
|
|
|
3212
3245
|
// src/commands/verify/blockCodeComments/findComments.ts
|
|
3213
|
-
import { execSync as
|
|
3246
|
+
import { execSync as execSync11 } from "child_process";
|
|
3214
3247
|
import fs15 from "fs";
|
|
3215
3248
|
import { minimatch } from "minimatch";
|
|
3216
3249
|
import { Project as Project2 } from "ts-morph";
|
|
@@ -3470,7 +3503,7 @@ function shouldScan(file, ignoreGlobs) {
|
|
|
3470
3503
|
return fs15.existsSync(file);
|
|
3471
3504
|
}
|
|
3472
3505
|
function findComments(options2) {
|
|
3473
|
-
const diff3 =
|
|
3506
|
+
const diff3 = execSync11("git diff HEAD", {
|
|
3474
3507
|
encoding: "utf8",
|
|
3475
3508
|
maxBuffer: 64 * 1024 * 1024
|
|
3476
3509
|
});
|
|
@@ -3716,13 +3749,13 @@ Total: ${violations.length} forbidden string(s).`);
|
|
|
3716
3749
|
}
|
|
3717
3750
|
|
|
3718
3751
|
// src/commands/verify/hardcodedColors.ts
|
|
3719
|
-
import { execSync as
|
|
3752
|
+
import { execSync as execSync12 } from "child_process";
|
|
3720
3753
|
import { minimatch as minimatch3 } from "minimatch";
|
|
3721
3754
|
var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
|
|
3722
3755
|
function hardcodedColors() {
|
|
3723
3756
|
const ignoreGlobs = loadConfig().hardcodedColors?.ignore ?? [];
|
|
3724
3757
|
try {
|
|
3725
|
-
const output =
|
|
3758
|
+
const output = execSync12(`grep -rEnH '${pattern}' src/`, {
|
|
3726
3759
|
encoding: "utf8"
|
|
3727
3760
|
});
|
|
3728
3761
|
const lines = output.trim().split("\n").filter((line) => {
|
|
@@ -3983,14 +4016,14 @@ function listMigrationFiles(dir) {
|
|
|
3983
4016
|
}
|
|
3984
4017
|
|
|
3985
4018
|
// src/commands/verify/migrations/readBaselineMigrations.ts
|
|
3986
|
-
import { execSync as
|
|
4019
|
+
import { execSync as execSync13 } from "child_process";
|
|
3987
4020
|
import { basename } from "path";
|
|
3988
4021
|
var MIGRATION_FILE3 = /^migration\d+[A-Za-z0-9]*\.ts$/;
|
|
3989
4022
|
function readBaselineMigrations(repoRelativeDir, ref) {
|
|
3990
4023
|
const baseline = /* @__PURE__ */ new Map();
|
|
3991
4024
|
let listing;
|
|
3992
4025
|
try {
|
|
3993
|
-
listing =
|
|
4026
|
+
listing = execSync13(
|
|
3994
4027
|
`git ls-tree -r --name-only "${ref}" -- "${repoRelativeDir}"`,
|
|
3995
4028
|
{ encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
|
|
3996
4029
|
);
|
|
@@ -4000,7 +4033,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
4000
4033
|
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path71) => MIGRATION_FILE3.test(basename(path71)));
|
|
4001
4034
|
for (const path71 of paths) {
|
|
4002
4035
|
try {
|
|
4003
|
-
const content =
|
|
4036
|
+
const content = execSync13(`git show "${ref}:${path71}"`, {
|
|
4004
4037
|
encoding: "utf8",
|
|
4005
4038
|
maxBuffer: 16 * 1024 * 1024,
|
|
4006
4039
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4013,10 +4046,10 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
4013
4046
|
}
|
|
4014
4047
|
|
|
4015
4048
|
// src/commands/verify/migrations/resolveBaselineRef.ts
|
|
4016
|
-
import { execSync as
|
|
4049
|
+
import { execSync as execSync14 } from "child_process";
|
|
4017
4050
|
function refExists(ref) {
|
|
4018
4051
|
try {
|
|
4019
|
-
|
|
4052
|
+
execSync14(`git rev-parse --verify --quiet "${ref}"`, {
|
|
4020
4053
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4021
4054
|
});
|
|
4022
4055
|
return true;
|
|
@@ -4088,10 +4121,10 @@ Total: ${problems.length} violation(s).`);
|
|
|
4088
4121
|
}
|
|
4089
4122
|
|
|
4090
4123
|
// src/commands/verify/noVenv.ts
|
|
4091
|
-
import { execSync as
|
|
4124
|
+
import { execSync as execSync15 } from "child_process";
|
|
4092
4125
|
function noVenv() {
|
|
4093
4126
|
try {
|
|
4094
|
-
const output =
|
|
4127
|
+
const output = execSync15(
|
|
4095
4128
|
"find . -type d -name venv -not -path '*/node_modules/*'",
|
|
4096
4129
|
{
|
|
4097
4130
|
encoding: "utf8"
|
|
@@ -4123,9 +4156,9 @@ Total: ${folders.length} venv folder(s)`);
|
|
|
4123
4156
|
import { minimatch as minimatch4 } from "minimatch";
|
|
4124
4157
|
|
|
4125
4158
|
// src/commands/verify/run/getChangedFiles.ts
|
|
4126
|
-
import { execSync as
|
|
4159
|
+
import { execSync as execSync16 } from "child_process";
|
|
4127
4160
|
function getChangedFiles() {
|
|
4128
|
-
const output =
|
|
4161
|
+
const output = execSync16("git diff --name-only HEAD", {
|
|
4129
4162
|
encoding: "utf8"
|
|
4130
4163
|
}).trim();
|
|
4131
4164
|
if (output === "") return [];
|
|
@@ -4297,25 +4330,25 @@ async function run(options2 = {}) {
|
|
|
4297
4330
|
}
|
|
4298
4331
|
|
|
4299
4332
|
// src/commands/new/registerNew/initGit.ts
|
|
4300
|
-
import { execSync as
|
|
4333
|
+
import { execSync as execSync17 } from "child_process";
|
|
4301
4334
|
import { writeFileSync as writeFileSync10 } from "fs";
|
|
4302
4335
|
function initGit() {
|
|
4303
4336
|
console.log("Initializing git repository...");
|
|
4304
|
-
|
|
4337
|
+
execSync17("git init", { stdio: "inherit" });
|
|
4305
4338
|
writeFileSync10(".gitignore", "dist\nnode_modules\n");
|
|
4306
4339
|
}
|
|
4307
4340
|
|
|
4308
4341
|
// src/commands/new/registerNew/newCli/initPackageJson.ts
|
|
4309
|
-
import { execSync as
|
|
4342
|
+
import { execSync as execSync18 } from "child_process";
|
|
4310
4343
|
function initPackageJson(name) {
|
|
4311
4344
|
console.log("Initializing package.json...");
|
|
4312
|
-
|
|
4345
|
+
execSync18("npm init -y", { stdio: "inherit" });
|
|
4313
4346
|
console.log("Configuring package.json...");
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4347
|
+
execSync18("npm pkg delete main", { stdio: "inherit" });
|
|
4348
|
+
execSync18("npm pkg set type=module", { stdio: "inherit" });
|
|
4349
|
+
execSync18(`npm pkg set bin.${name}=./dist/index.js`, { stdio: "inherit" });
|
|
4350
|
+
execSync18("npm pkg set scripts.build=tsup", { stdio: "inherit" });
|
|
4351
|
+
execSync18('npm pkg set scripts.start="node dist/index.js"', {
|
|
4319
4352
|
stdio: "inherit"
|
|
4320
4353
|
});
|
|
4321
4354
|
}
|
|
@@ -4380,8 +4413,8 @@ async function newCli() {
|
|
|
4380
4413
|
initGit();
|
|
4381
4414
|
initPackageJson(name);
|
|
4382
4415
|
console.log("Installing dependencies...");
|
|
4383
|
-
|
|
4384
|
-
|
|
4416
|
+
execSync19("npm install commander", { stdio: "inherit" });
|
|
4417
|
+
execSync19("npm install -D tsup typescript @types/node", {
|
|
4385
4418
|
stdio: "inherit"
|
|
4386
4419
|
});
|
|
4387
4420
|
writeCliTemplate(name);
|
|
@@ -4390,11 +4423,11 @@ async function newCli() {
|
|
|
4390
4423
|
}
|
|
4391
4424
|
|
|
4392
4425
|
// src/commands/new/registerNew/newProject.ts
|
|
4393
|
-
import { execSync as
|
|
4426
|
+
import { execSync as execSync21 } from "child_process";
|
|
4394
4427
|
import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
4395
4428
|
|
|
4396
4429
|
// src/commands/deploy/init/index.ts
|
|
4397
|
-
import { execSync as
|
|
4430
|
+
import { execSync as execSync20 } from "child_process";
|
|
4398
4431
|
import chalk28 from "chalk";
|
|
4399
4432
|
import enquirer3 from "enquirer";
|
|
4400
4433
|
|
|
@@ -4447,7 +4480,7 @@ Created ${WORKFLOW_PATH}`));
|
|
|
4447
4480
|
// src/commands/deploy/init/index.ts
|
|
4448
4481
|
async function ensureNetlifyCli() {
|
|
4449
4482
|
try {
|
|
4450
|
-
|
|
4483
|
+
execSync20("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
4451
4484
|
} catch (error) {
|
|
4452
4485
|
if (!(error instanceof Error) || !error.message.includes("command not found"))
|
|
4453
4486
|
throw error;
|
|
@@ -4462,9 +4495,9 @@ async function ensureNetlifyCli() {
|
|
|
4462
4495
|
process.exit(1);
|
|
4463
4496
|
}
|
|
4464
4497
|
console.log(chalk28.dim("\nInstalling netlify-cli...\n"));
|
|
4465
|
-
|
|
4498
|
+
execSync20("npm install -g netlify-cli", { stdio: "inherit" });
|
|
4466
4499
|
console.log();
|
|
4467
|
-
|
|
4500
|
+
execSync20("netlify sites:create --disable-linking", { stdio: "inherit" });
|
|
4468
4501
|
}
|
|
4469
4502
|
}
|
|
4470
4503
|
function printSetupInstructions() {
|
|
@@ -4507,7 +4540,7 @@ async function init6() {
|
|
|
4507
4540
|
// src/commands/new/registerNew/newProject.ts
|
|
4508
4541
|
async function newProject() {
|
|
4509
4542
|
console.log("Initializing Vite with react-ts template...");
|
|
4510
|
-
|
|
4543
|
+
execSync21("npm create vite@latest . -- --template react-ts", {
|
|
4511
4544
|
stdio: "inherit"
|
|
4512
4545
|
});
|
|
4513
4546
|
initGit();
|
|
@@ -4698,11 +4731,11 @@ function activityChart(data, range) {
|
|
|
4698
4731
|
}
|
|
4699
4732
|
|
|
4700
4733
|
// src/commands/activity/fetchCommitsPerDay.ts
|
|
4701
|
-
import { execSync as
|
|
4734
|
+
import { execSync as execSync22 } from "child_process";
|
|
4702
4735
|
function fetchContributions(from, to) {
|
|
4703
4736
|
const query = `{ viewer { contributionsCollection(from: "${from}T00:00:00Z", to: "${to}T23:59:59Z") { contributionCalendar { weeks { contributionDays { date contributionCount } } } } } }`;
|
|
4704
4737
|
const jq = ".data.viewer.contributionsCollection.contributionCalendar.weeks[].contributionDays[]";
|
|
4705
|
-
const raw =
|
|
4738
|
+
const raw = execSync22(`gh api graphql -f query='${query}' --jq '${jq}'`, {
|
|
4706
4739
|
encoding: "utf8"
|
|
4707
4740
|
}).trim();
|
|
4708
4741
|
if (!raw) return [];
|
|
@@ -4789,10 +4822,10 @@ import { join as join10 } from "path";
|
|
|
4789
4822
|
import chalk29 from "chalk";
|
|
4790
4823
|
|
|
4791
4824
|
// src/commands/backup/readCrontab.ts
|
|
4792
|
-
import { execSync as
|
|
4825
|
+
import { execSync as execSync23 } from "child_process";
|
|
4793
4826
|
function readCrontab() {
|
|
4794
4827
|
try {
|
|
4795
|
-
return
|
|
4828
|
+
return execSync23("crontab -l", {
|
|
4796
4829
|
encoding: "utf8",
|
|
4797
4830
|
stdio: ["ignore", "pipe", "ignore"]
|
|
4798
4831
|
});
|
|
@@ -4802,7 +4835,7 @@ function readCrontab() {
|
|
|
4802
4835
|
}
|
|
4803
4836
|
function writeCrontab(content) {
|
|
4804
4837
|
try {
|
|
4805
|
-
|
|
4838
|
+
execSync23("crontab -", {
|
|
4806
4839
|
input: content,
|
|
4807
4840
|
stdio: ["pipe", "ignore", "pipe"]
|
|
4808
4841
|
});
|
|
@@ -5143,7 +5176,7 @@ import chalk46 from "chalk";
|
|
|
5143
5176
|
import enquirer5 from "enquirer";
|
|
5144
5177
|
|
|
5145
5178
|
// src/shared/pullIfConfigured.ts
|
|
5146
|
-
import { execSync as
|
|
5179
|
+
import { execSync as execSync24 } from "child_process";
|
|
5147
5180
|
import chalk32 from "chalk";
|
|
5148
5181
|
function pullIfConfigured() {
|
|
5149
5182
|
const config = loadConfig();
|
|
@@ -5157,7 +5190,7 @@ function pullIfConfigured() {
|
|
|
5157
5190
|
return;
|
|
5158
5191
|
}
|
|
5159
5192
|
try {
|
|
5160
|
-
|
|
5193
|
+
execSync24("git pull --ff-only", { stdio: "inherit" });
|
|
5161
5194
|
} catch {
|
|
5162
5195
|
console.error(chalk32.red("git pull --ff-only failed; aborting."));
|
|
5163
5196
|
process.exit(1);
|
|
@@ -5165,7 +5198,7 @@ function pullIfConfigured() {
|
|
|
5165
5198
|
}
|
|
5166
5199
|
function hasLocalChanges() {
|
|
5167
5200
|
try {
|
|
5168
|
-
const status3 =
|
|
5201
|
+
const status3 = execSync24("git status --porcelain", {
|
|
5169
5202
|
encoding: "utf8"
|
|
5170
5203
|
});
|
|
5171
5204
|
return status3.trim().length > 0;
|
|
@@ -5432,7 +5465,7 @@ function buildArgs(prompt, options2) {
|
|
|
5432
5465
|
}
|
|
5433
5466
|
|
|
5434
5467
|
// src/commands/branch/createBranch.ts
|
|
5435
|
-
import { execSync as
|
|
5468
|
+
import { execSync as execSync26 } from "child_process";
|
|
5436
5469
|
|
|
5437
5470
|
// src/commands/branch/buildBranchName.ts
|
|
5438
5471
|
function buildBranchName({
|
|
@@ -5448,12 +5481,12 @@ function buildBranchName({
|
|
|
5448
5481
|
}
|
|
5449
5482
|
|
|
5450
5483
|
// src/commands/branch/resolveDefaultBranch.ts
|
|
5451
|
-
import { execSync as
|
|
5484
|
+
import { execSync as execSync25 } from "child_process";
|
|
5452
5485
|
var REMOTE_HEAD_REGEX = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/m;
|
|
5453
5486
|
function resolveDefaultBranch(override, cwd) {
|
|
5454
5487
|
if (override) return override;
|
|
5455
5488
|
try {
|
|
5456
|
-
const output =
|
|
5489
|
+
const output = execSync25("git ls-remote --symref origin HEAD", {
|
|
5457
5490
|
encoding: "utf8",
|
|
5458
5491
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5459
5492
|
cwd
|
|
@@ -5477,11 +5510,11 @@ async function createBranch({
|
|
|
5477
5510
|
jira,
|
|
5478
5511
|
slug
|
|
5479
5512
|
});
|
|
5480
|
-
|
|
5513
|
+
execSync26("git fetch", { stdio: "inherit" });
|
|
5481
5514
|
let baseRef;
|
|
5482
5515
|
if (from) {
|
|
5483
5516
|
try {
|
|
5484
|
-
|
|
5517
|
+
execSync26(`git rev-parse --verify ${shellQuote(from)}`, {
|
|
5485
5518
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5486
5519
|
});
|
|
5487
5520
|
} catch {
|
|
@@ -5491,7 +5524,7 @@ async function createBranch({
|
|
|
5491
5524
|
} else {
|
|
5492
5525
|
baseRef = `origin/${resolveDefaultBranch(config.branch?.defaultBranch)}`;
|
|
5493
5526
|
}
|
|
5494
|
-
|
|
5527
|
+
execSync26(`git switch -c ${shellQuote(branchName)} ${shellQuote(baseRef)}`, {
|
|
5495
5528
|
stdio: "inherit"
|
|
5496
5529
|
});
|
|
5497
5530
|
await recordBranchActivity(branchName);
|
|
@@ -5631,11 +5664,11 @@ function backupLocalBacklogFiles(dir) {
|
|
|
5631
5664
|
}
|
|
5632
5665
|
|
|
5633
5666
|
// src/commands/backlog/gitPullBacklog.ts
|
|
5634
|
-
import { execSync as
|
|
5667
|
+
import { execSync as execSync27 } from "child_process";
|
|
5635
5668
|
import chalk35 from "chalk";
|
|
5636
5669
|
function gitPullBacklog(dir) {
|
|
5637
5670
|
try {
|
|
5638
|
-
|
|
5671
|
+
execSync27("git pull --ff-only", {
|
|
5639
5672
|
cwd: dir,
|
|
5640
5673
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5641
5674
|
});
|
|
@@ -7925,7 +7958,7 @@ import chalk61 from "chalk";
|
|
|
7925
7958
|
import { WebSocketServer } from "ws";
|
|
7926
7959
|
|
|
7927
7960
|
// src/shared/getInstallDir.ts
|
|
7928
|
-
import { execSync as
|
|
7961
|
+
import { execSync as execSync28 } from "child_process";
|
|
7929
7962
|
import { dirname as dirname18, resolve as resolve7 } from "path";
|
|
7930
7963
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7931
7964
|
var __filename2 = fileURLToPath3(import.meta.url);
|
|
@@ -7935,7 +7968,7 @@ function getInstallDir() {
|
|
|
7935
7968
|
}
|
|
7936
7969
|
function isGitRepo(dir) {
|
|
7937
7970
|
try {
|
|
7938
|
-
const result =
|
|
7971
|
+
const result = execSync28("git rev-parse --show-toplevel", {
|
|
7939
7972
|
cwd: dir,
|
|
7940
7973
|
stdio: "pipe"
|
|
7941
7974
|
}).toString().trim();
|
|
@@ -7952,11 +7985,11 @@ import {
|
|
|
7952
7985
|
import chalk57 from "chalk";
|
|
7953
7986
|
|
|
7954
7987
|
// src/lib/openBrowser.ts
|
|
7955
|
-
import { execSync as
|
|
7988
|
+
import { execSync as execSync29 } from "child_process";
|
|
7956
7989
|
function tryExec(commands) {
|
|
7957
7990
|
for (const cmd of commands) {
|
|
7958
7991
|
try {
|
|
7959
|
-
|
|
7992
|
+
execSync29(cmd, { stdio: "ignore" });
|
|
7960
7993
|
return true;
|
|
7961
7994
|
} catch {
|
|
7962
7995
|
}
|
|
@@ -8188,7 +8221,7 @@ function git2(cwd, args) {
|
|
|
8188
8221
|
});
|
|
8189
8222
|
});
|
|
8190
8223
|
}
|
|
8191
|
-
async function
|
|
8224
|
+
async function gitOrNull2(cwd, args) {
|
|
8192
8225
|
try {
|
|
8193
8226
|
return (await git2(cwd, args)).trim() || null;
|
|
8194
8227
|
} catch {
|
|
@@ -9146,7 +9179,7 @@ import * as os3 from "os";
|
|
|
9146
9179
|
import * as path25 from "path";
|
|
9147
9180
|
|
|
9148
9181
|
// src/shared/checkCliAvailable.ts
|
|
9149
|
-
import { execSync as
|
|
9182
|
+
import { execSync as execSync30 } from "child_process";
|
|
9150
9183
|
function checkCliAvailable(cli) {
|
|
9151
9184
|
const binary = cli.split(/\s+/)[0];
|
|
9152
9185
|
const opts = {
|
|
@@ -9154,11 +9187,11 @@ function checkCliAvailable(cli) {
|
|
|
9154
9187
|
stdio: ["ignore", "pipe", "pipe"]
|
|
9155
9188
|
};
|
|
9156
9189
|
try {
|
|
9157
|
-
|
|
9190
|
+
execSync30(`command -v ${binary}`, opts);
|
|
9158
9191
|
return true;
|
|
9159
9192
|
} catch {
|
|
9160
9193
|
try {
|
|
9161
|
-
|
|
9194
|
+
execSync30(`where ${binary}`, opts);
|
|
9162
9195
|
return true;
|
|
9163
9196
|
} catch {
|
|
9164
9197
|
return false;
|
|
@@ -9249,8 +9282,8 @@ function subsequenceScore(text17, query) {
|
|
|
9249
9282
|
function scoreFilePath(path71, query) {
|
|
9250
9283
|
const needle = query.trim().toLowerCase();
|
|
9251
9284
|
if (!needle) return 0;
|
|
9252
|
-
const
|
|
9253
|
-
const inBasename = subsequenceScore(
|
|
9285
|
+
const basename19 = path71.slice(path71.lastIndexOf("/") + 1);
|
|
9286
|
+
const inBasename = subsequenceScore(basename19, needle);
|
|
9254
9287
|
if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
|
|
9255
9288
|
return subsequenceScore(path71, needle);
|
|
9256
9289
|
}
|
|
@@ -10561,13 +10594,13 @@ async function beginAssociation(id, options2, clearPatch, label2) {
|
|
|
10561
10594
|
}
|
|
10562
10595
|
|
|
10563
10596
|
// src/commands/backlog/associate-github/fetchGithubIssueTitle.ts
|
|
10564
|
-
import { execSync as
|
|
10597
|
+
import { execSync as execSync31 } from "child_process";
|
|
10565
10598
|
function fetchGithubIssueTitle(issue) {
|
|
10566
10599
|
const match = /^([^/]+)\/([^#]+)#(\d+)$/.exec(issue);
|
|
10567
10600
|
if (!match) return void 0;
|
|
10568
10601
|
const [, owner, repo, number] = match;
|
|
10569
10602
|
try {
|
|
10570
|
-
const result =
|
|
10603
|
+
const result = execSync31(
|
|
10571
10604
|
`gh issue view ${number} -R ${owner}/${repo} --json title`,
|
|
10572
10605
|
{ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
|
|
10573
10606
|
);
|
|
@@ -10634,12 +10667,12 @@ import chalk66 from "chalk";
|
|
|
10634
10667
|
import { eq as eq19 } from "drizzle-orm";
|
|
10635
10668
|
|
|
10636
10669
|
// src/commands/jira/fetchIssue.ts
|
|
10637
|
-
import { execSync as
|
|
10670
|
+
import { execSync as execSync32 } from "child_process";
|
|
10638
10671
|
import chalk65 from "chalk";
|
|
10639
10672
|
function fetchIssue(issueKey, fields) {
|
|
10640
10673
|
let result;
|
|
10641
10674
|
try {
|
|
10642
|
-
result =
|
|
10675
|
+
result = execSync32(
|
|
10643
10676
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
10644
10677
|
{ encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
|
|
10645
10678
|
);
|
|
@@ -14721,10 +14754,10 @@ function formatResultLine(entry, failing) {
|
|
|
14721
14754
|
}
|
|
14722
14755
|
|
|
14723
14756
|
// src/commands/complexity/maintainability/getMaintainabilityGitState.ts
|
|
14724
|
-
import { execSync as
|
|
14757
|
+
import { execSync as execSync33 } from "child_process";
|
|
14725
14758
|
import path28 from "path";
|
|
14726
14759
|
function git3(command) {
|
|
14727
|
-
return
|
|
14760
|
+
return execSync33(command, { encoding: "utf8" });
|
|
14728
14761
|
}
|
|
14729
14762
|
function toAbsolute(root, repoRelative) {
|
|
14730
14763
|
return path28.resolve(root, repoRelative);
|
|
@@ -15298,7 +15331,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
15298
15331
|
}
|
|
15299
15332
|
|
|
15300
15333
|
// src/commands/devlog/shared.ts
|
|
15301
|
-
import { execSync as
|
|
15334
|
+
import { execSync as execSync34 } from "child_process";
|
|
15302
15335
|
import chalk134 from "chalk";
|
|
15303
15336
|
|
|
15304
15337
|
// src/shared/getRepoName.ts
|
|
@@ -15390,7 +15423,7 @@ function loadAllDevlogLatestDates() {
|
|
|
15390
15423
|
// src/commands/devlog/shared.ts
|
|
15391
15424
|
function getCommitFiles(hash) {
|
|
15392
15425
|
try {
|
|
15393
|
-
const output =
|
|
15426
|
+
const output = execSync34(`git show --name-only --format="" ${hash}`, {
|
|
15394
15427
|
encoding: "utf8"
|
|
15395
15428
|
});
|
|
15396
15429
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -15486,11 +15519,11 @@ function list3(options2) {
|
|
|
15486
15519
|
}
|
|
15487
15520
|
|
|
15488
15521
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
15489
|
-
import { execFileSync as execFileSync4, execSync as
|
|
15522
|
+
import { execFileSync as execFileSync4, execSync as execSync35 } from "child_process";
|
|
15490
15523
|
import semver from "semver";
|
|
15491
15524
|
function getVersionAtCommit(hash) {
|
|
15492
15525
|
try {
|
|
15493
|
-
const content =
|
|
15526
|
+
const content = execSync35(`git show ${hash}:package.json`, {
|
|
15494
15527
|
encoding: "utf8"
|
|
15495
15528
|
});
|
|
15496
15529
|
const pkg = JSON.parse(content);
|
|
@@ -15663,7 +15696,7 @@ function next2(options2) {
|
|
|
15663
15696
|
}
|
|
15664
15697
|
|
|
15665
15698
|
// src/commands/devlog/repos/index.ts
|
|
15666
|
-
import { execSync as
|
|
15699
|
+
import { execSync as execSync36 } from "child_process";
|
|
15667
15700
|
|
|
15668
15701
|
// src/commands/devlog/repos/printReposTable.ts
|
|
15669
15702
|
import chalk138 from "chalk";
|
|
@@ -15698,7 +15731,7 @@ function getStatus(lastPush, lastDevlog) {
|
|
|
15698
15731
|
return lastDevlog < lastPush ? "outdated" : "ok";
|
|
15699
15732
|
}
|
|
15700
15733
|
function fetchRepos(days, all) {
|
|
15701
|
-
const json =
|
|
15734
|
+
const json = execSync36(
|
|
15702
15735
|
"gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
|
|
15703
15736
|
{ encoding: "utf8" }
|
|
15704
15737
|
);
|
|
@@ -16078,7 +16111,7 @@ async function deps(csprojPath, options2) {
|
|
|
16078
16111
|
}
|
|
16079
16112
|
|
|
16080
16113
|
// src/commands/dotnet/getChangedCsFiles.ts
|
|
16081
|
-
import { execSync as
|
|
16114
|
+
import { execSync as execSync37 } from "child_process";
|
|
16082
16115
|
var SCOPE_ALL = "all";
|
|
16083
16116
|
var SCOPE_BASE = "base:";
|
|
16084
16117
|
var SCOPE_COMMIT = "commit:";
|
|
@@ -16102,7 +16135,7 @@ function getChangedCsFiles(scope) {
|
|
|
16102
16135
|
} else {
|
|
16103
16136
|
cmd = "git diff --name-only HEAD";
|
|
16104
16137
|
}
|
|
16105
|
-
const output =
|
|
16138
|
+
const output = execSync37(cmd, { encoding: "utf8" }).trim();
|
|
16106
16139
|
if (output === "") return [];
|
|
16107
16140
|
return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
|
|
16108
16141
|
}
|
|
@@ -16300,14 +16333,14 @@ function parseInspectReport(json) {
|
|
|
16300
16333
|
}
|
|
16301
16334
|
|
|
16302
16335
|
// src/commands/dotnet/runInspectCode.ts
|
|
16303
|
-
import { execSync as
|
|
16336
|
+
import { execSync as execSync38 } from "child_process";
|
|
16304
16337
|
import { existsSync as existsSync40, readFileSync as readFileSync35, unlinkSync as unlinkSync10 } from "fs";
|
|
16305
16338
|
import { tmpdir as tmpdir4 } from "os";
|
|
16306
16339
|
import path35 from "path";
|
|
16307
16340
|
import chalk148 from "chalk";
|
|
16308
16341
|
function assertJbInstalled() {
|
|
16309
16342
|
try {
|
|
16310
|
-
|
|
16343
|
+
execSync38("jb inspectcode --version", { stdio: "pipe" });
|
|
16311
16344
|
} catch {
|
|
16312
16345
|
console.error(chalk148.red("jb is not installed. Install with:"));
|
|
16313
16346
|
console.error(
|
|
@@ -16321,7 +16354,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
16321
16354
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
16322
16355
|
const sweaFlag = swea ? " --swea" : "";
|
|
16323
16356
|
try {
|
|
16324
|
-
|
|
16357
|
+
execSync38(
|
|
16325
16358
|
`jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
|
|
16326
16359
|
{ stdio: "pipe" }
|
|
16327
16360
|
);
|
|
@@ -16342,7 +16375,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
16342
16375
|
}
|
|
16343
16376
|
|
|
16344
16377
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
16345
|
-
import { execSync as
|
|
16378
|
+
import { execSync as execSync39 } from "child_process";
|
|
16346
16379
|
import chalk149 from "chalk";
|
|
16347
16380
|
function resolveMsbuildPath() {
|
|
16348
16381
|
const { run: run4 } = loadConfig();
|
|
@@ -16353,7 +16386,7 @@ function resolveMsbuildPath() {
|
|
|
16353
16386
|
function assertMsbuildInstalled() {
|
|
16354
16387
|
const msbuild = resolveMsbuildPath();
|
|
16355
16388
|
try {
|
|
16356
|
-
|
|
16389
|
+
execSync39(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
16357
16390
|
} catch {
|
|
16358
16391
|
console.error(chalk149.red(`msbuild not found at: ${msbuild}`));
|
|
16359
16392
|
console.error(
|
|
@@ -16379,7 +16412,7 @@ function runRoslynInspect(slnPath) {
|
|
|
16379
16412
|
const msbuild = resolveMsbuildPath();
|
|
16380
16413
|
let output;
|
|
16381
16414
|
try {
|
|
16382
|
-
output =
|
|
16415
|
+
output = execSync39(
|
|
16383
16416
|
`"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
|
|
16384
16417
|
{ encoding: "utf8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
|
|
16385
16418
|
);
|
|
@@ -17226,7 +17259,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
17226
17259
|
}
|
|
17227
17260
|
|
|
17228
17261
|
// src/commands/jira/jiraAuth.ts
|
|
17229
|
-
import { execSync as
|
|
17262
|
+
import { execSync as execSync40 } from "child_process";
|
|
17230
17263
|
|
|
17231
17264
|
// src/shared/promptInput.ts
|
|
17232
17265
|
import Enquirer from "enquirer";
|
|
@@ -17261,7 +17294,7 @@ async function jiraAuth() {
|
|
|
17261
17294
|
console.error("All fields are required.");
|
|
17262
17295
|
process.exit(1);
|
|
17263
17296
|
}
|
|
17264
|
-
|
|
17297
|
+
execSync40(`acli jira auth login --site ${site} --email "${email}" --token`, {
|
|
17265
17298
|
encoding: "utf8",
|
|
17266
17299
|
input: token,
|
|
17267
17300
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -17352,175 +17385,538 @@ function registerRefineLaunch(program2, resumeFlag) {
|
|
|
17352
17385
|
}
|
|
17353
17386
|
|
|
17354
17387
|
// src/commands/reviewPrComments.ts
|
|
17355
|
-
import { execFileSync as execFileSync6 } from "child_process";
|
|
17356
17388
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
17389
|
+
|
|
17390
|
+
// src/commands/review/checkoutPr.ts
|
|
17391
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
17357
17392
|
import chalk155 from "chalk";
|
|
17358
|
-
async function reviewPrComments(number) {
|
|
17359
|
-
if (number) {
|
|
17360
|
-
try {
|
|
17361
|
-
execFileSync6("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
17362
|
-
} catch {
|
|
17363
|
-
console.error(chalk155.red(`gh pr checkout ${number} failed; aborting.`));
|
|
17364
|
-
process.exit(1);
|
|
17365
|
-
}
|
|
17366
|
-
}
|
|
17367
|
-
const claudeSessionId = randomUUID4();
|
|
17368
|
-
emitActivity({
|
|
17369
|
-
kind: "command",
|
|
17370
|
-
name: "review-pr-comments",
|
|
17371
|
-
claudeSessionId
|
|
17372
|
-
});
|
|
17373
|
-
const { done: done2 } = spawnClaude("/review-pr-comments", {
|
|
17374
|
-
permissionMode: "acceptEdits",
|
|
17375
|
-
sessionId: claudeSessionId
|
|
17376
|
-
});
|
|
17377
|
-
await done2;
|
|
17378
|
-
}
|
|
17379
17393
|
|
|
17380
|
-
// src/commands/
|
|
17381
|
-
var
|
|
17382
|
-
|
|
17383
|
-
|
|
17384
|
-
|
|
17385
|
-
);
|
|
17394
|
+
// src/commands/sessions/daemon/daemonLog.ts
|
|
17395
|
+
var RING_CAPACITY = 1e3;
|
|
17396
|
+
var ring = [];
|
|
17397
|
+
var sink;
|
|
17398
|
+
function daemonLog(message2) {
|
|
17399
|
+
emit3(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message2}`);
|
|
17386
17400
|
}
|
|
17387
|
-
function
|
|
17388
|
-
|
|
17389
|
-
"[description]",
|
|
17390
|
-
`Text to forward to the /${slashCommand} slash command`
|
|
17391
|
-
).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
|
|
17392
|
-
(text17, opts) => launchMode(slashCommand, {
|
|
17393
|
-
once: opts.once,
|
|
17394
|
-
description: text17,
|
|
17395
|
-
resumeSessionId: opts.resumeSession
|
|
17396
|
-
})
|
|
17397
|
-
);
|
|
17398
|
-
if (alias) command.alias(alias);
|
|
17401
|
+
function relayDaemonLog(line) {
|
|
17402
|
+
emit3(`[windows] ${line}`);
|
|
17399
17403
|
}
|
|
17400
|
-
function
|
|
17401
|
-
|
|
17404
|
+
function emit3(line) {
|
|
17405
|
+
console.log(line);
|
|
17406
|
+
ring.push(line);
|
|
17407
|
+
if (ring.length > RING_CAPACITY) ring.shift();
|
|
17408
|
+
sink?.(line);
|
|
17402
17409
|
}
|
|
17403
|
-
function
|
|
17404
|
-
|
|
17405
|
-
registerDescriptionLaunch(
|
|
17406
|
-
program2,
|
|
17407
|
-
"draft",
|
|
17408
|
-
"draft",
|
|
17409
|
-
"Launch Claude in /draft mode, chain into next on /next signal",
|
|
17410
|
-
"feat"
|
|
17411
|
-
);
|
|
17412
|
-
registerDescriptionLaunch(
|
|
17413
|
-
program2,
|
|
17414
|
-
"bug",
|
|
17415
|
-
"bug",
|
|
17416
|
-
"Launch Claude in /bug mode, chain into next on /next signal"
|
|
17417
|
-
);
|
|
17418
|
-
registerReviewPrComments(program2);
|
|
17419
|
-
registerRefineLaunch(program2, RESUME_SESSION_FLAG);
|
|
17410
|
+
function setDaemonLogSink(next3) {
|
|
17411
|
+
sink = next3;
|
|
17420
17412
|
}
|
|
17421
|
-
|
|
17422
|
-
|
|
17423
|
-
function registerList(program2) {
|
|
17424
|
-
program2.command("list").alias("ls").description("Alias for backlog list").option(
|
|
17425
|
-
"--status <type>",
|
|
17426
|
-
"Filter by status (todo, in-progress, done, wontdo)"
|
|
17427
|
-
).option("-a, --all", "Include done/wontdo items").option("--all-repos", "List items across all repositories").option("-v, --verbose", "Show all item details").option("--dir <path>", "Override directory for backlog file discovery").action((options2) => {
|
|
17428
|
-
setBacklogDir(options2.dir);
|
|
17429
|
-
return list2(options2);
|
|
17430
|
-
});
|
|
17413
|
+
function recentDaemonLogLines() {
|
|
17414
|
+
return [...ring];
|
|
17431
17415
|
}
|
|
17432
17416
|
|
|
17433
|
-
// src/commands/
|
|
17434
|
-
import {
|
|
17435
|
-
import {
|
|
17436
|
-
import chalk158 from "chalk";
|
|
17437
|
-
|
|
17438
|
-
// src/commands/mermaid/exportFile.ts
|
|
17439
|
-
import { readFileSync as readFileSync37, writeFileSync as writeFileSync31 } from "fs";
|
|
17440
|
-
import { basename as basename11, extname as extname2, resolve as resolve12 } from "path";
|
|
17441
|
-
import chalk157 from "chalk";
|
|
17417
|
+
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
17418
|
+
import { existsSync as existsSync43 } from "fs";
|
|
17419
|
+
import { basename as basename12, dirname as dirname23 } from "path";
|
|
17442
17420
|
|
|
17443
|
-
// src/commands/
|
|
17444
|
-
import
|
|
17445
|
-
|
|
17446
|
-
|
|
17447
|
-
|
|
17448
|
-
|
|
17449
|
-
|
|
17450
|
-
|
|
17451
|
-
|
|
17452
|
-
|
|
17453
|
-
chalk156.red(
|
|
17454
|
-
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
17455
|
-
)
|
|
17456
|
-
);
|
|
17457
|
-
console.error(await response.text());
|
|
17458
|
-
process.exit(1);
|
|
17421
|
+
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
17422
|
+
import { basename as basename11, join as join46 } from "path";
|
|
17423
|
+
function planAllocation(clone, boundTreeRoots2) {
|
|
17424
|
+
return boundTreeRoots2.has(clone) ? "spill" : "primary";
|
|
17425
|
+
}
|
|
17426
|
+
function nextWorktreePath(clone, base, isTaken) {
|
|
17427
|
+
const name = basename11(clone);
|
|
17428
|
+
for (let n = 2; n < 1e3; n++) {
|
|
17429
|
+
const candidate = join46(base, `${name}-${n}`);
|
|
17430
|
+
if (!isTaken(candidate)) return candidate;
|
|
17459
17431
|
}
|
|
17460
|
-
|
|
17432
|
+
throw new Error(`no free worktree suffix for ${clone}`);
|
|
17461
17433
|
}
|
|
17462
17434
|
|
|
17463
|
-
// src/commands/
|
|
17464
|
-
|
|
17465
|
-
const
|
|
17466
|
-
const
|
|
17467
|
-
|
|
17468
|
-
|
|
17469
|
-
|
|
17470
|
-
console.error(
|
|
17471
|
-
chalk157.red(
|
|
17472
|
-
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
17473
|
-
)
|
|
17474
|
-
);
|
|
17475
|
-
process.exit(1);
|
|
17476
|
-
}
|
|
17477
|
-
console.log(
|
|
17478
|
-
chalk157.gray(
|
|
17479
|
-
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
17480
|
-
)
|
|
17481
|
-
);
|
|
17482
|
-
} else {
|
|
17483
|
-
console.log(chalk157.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
17484
|
-
}
|
|
17485
|
-
for (const [i, source] of blocks.entries()) {
|
|
17486
|
-
const idx = i + 1;
|
|
17487
|
-
if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
|
|
17488
|
-
const outPath = resolve12(outDir, `${stem}-${idx}.svg`);
|
|
17489
|
-
const svg = await renderBlock(krokiUrl, source);
|
|
17490
|
-
writeFileSync31(outPath, svg, "utf8");
|
|
17491
|
-
console.log(chalk157.green(` \u2192 ${outPath}`));
|
|
17492
|
-
}
|
|
17435
|
+
// src/commands/sessions/daemon/worktree/worktreeStartPoint.ts
|
|
17436
|
+
function worktreeStartPoint(clone, trunk) {
|
|
17437
|
+
const branch2 = trunk ? cloneTrunkBranch(clone) : remoteDefaultBranch(clone);
|
|
17438
|
+
const ref = `origin/${branch2}`;
|
|
17439
|
+
if (gitSyncOrNull(clone, ["rev-parse", "--verify", "--quiet", ref]))
|
|
17440
|
+
return { ref, track: trunk };
|
|
17441
|
+
return { ref: "HEAD", track: false };
|
|
17493
17442
|
}
|
|
17494
|
-
function
|
|
17495
|
-
|
|
17496
|
-
return matches.map(([, src]) => src);
|
|
17443
|
+
function cloneTrunkBranch(clone) {
|
|
17444
|
+
return cloneHead(clone) ?? remoteDefaultBranch(clone);
|
|
17497
17445
|
}
|
|
17498
|
-
|
|
17499
|
-
|
|
17500
|
-
|
|
17501
|
-
|
|
17502
|
-
|
|
17503
|
-
|
|
17504
|
-
if (
|
|
17505
|
-
|
|
17506
|
-
|
|
17507
|
-
|
|
17508
|
-
|
|
17509
|
-
|
|
17510
|
-
|
|
17511
|
-
|
|
17512
|
-
|
|
17513
|
-
|
|
17514
|
-
|
|
17515
|
-
|
|
17516
|
-
const
|
|
17517
|
-
|
|
17518
|
-
|
|
17519
|
-
|
|
17520
|
-
|
|
17521
|
-
|
|
17522
|
-
|
|
17523
|
-
|
|
17446
|
+
function remoteDefaultBranch(clone) {
|
|
17447
|
+
const head = gitSyncOrNull(clone, [
|
|
17448
|
+
"symbolic-ref",
|
|
17449
|
+
"--short",
|
|
17450
|
+
"refs/remotes/origin/HEAD"
|
|
17451
|
+
]);
|
|
17452
|
+
if (!head) return cloneHead(clone) ?? "main";
|
|
17453
|
+
const slash = head.indexOf("/");
|
|
17454
|
+
return slash === -1 ? head : head.slice(slash + 1);
|
|
17455
|
+
}
|
|
17456
|
+
function cloneHead(clone) {
|
|
17457
|
+
return gitSyncOrNull(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
17458
|
+
}
|
|
17459
|
+
|
|
17460
|
+
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
17461
|
+
function createWorktree(clone, strategy, boundTreeRoots2) {
|
|
17462
|
+
const base = strategy.root ? expandTilde2(strategy.root) : dirname23(clone);
|
|
17463
|
+
const registered = new Set(listWorktreePaths(clone));
|
|
17464
|
+
const branches = new Set(listLocalBranches(clone));
|
|
17465
|
+
const path71 = nextWorktreePath(
|
|
17466
|
+
clone,
|
|
17467
|
+
base,
|
|
17468
|
+
(candidate) => registered.has(candidate) || existsSync43(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename12(candidate))
|
|
17469
|
+
);
|
|
17470
|
+
const start3 = worktreeStartPoint(clone, strategy.trunk);
|
|
17471
|
+
gitSync(clone, [
|
|
17472
|
+
"worktree",
|
|
17473
|
+
"add",
|
|
17474
|
+
start3.track ? "--track" : "--no-track",
|
|
17475
|
+
"-b",
|
|
17476
|
+
basename12(path71),
|
|
17477
|
+
path71,
|
|
17478
|
+
start3.ref
|
|
17479
|
+
]);
|
|
17480
|
+
recordWorktree(path71, clone, getCurrentOrigin(clone));
|
|
17481
|
+
daemonLog(
|
|
17482
|
+
start3.track ? `worktree allocated ${path71} (branch ${basename12(path71)} tracking ${start3.ref}) for clone ${clone}` : `worktree allocated ${path71} (branch ${basename12(path71)} off ${start3.ref}, no mainline tracking) for clone ${clone}`
|
|
17483
|
+
);
|
|
17484
|
+
return path71;
|
|
17485
|
+
}
|
|
17486
|
+
|
|
17487
|
+
// src/commands/sessions/daemon/worktree/treeDurability.ts
|
|
17488
|
+
import { existsSync as existsSync44 } from "fs";
|
|
17489
|
+
function treeDurability(state) {
|
|
17490
|
+
if (state.dirty) return { durable: false, reason: "uncommitted changes" };
|
|
17491
|
+
if (state.localOnlyCommits)
|
|
17492
|
+
return { durable: false, reason: "unpushed commits" };
|
|
17493
|
+
return { durable: true };
|
|
17494
|
+
}
|
|
17495
|
+
function* durabilityProbes() {
|
|
17496
|
+
const status3 = yield ["status", "--porcelain"];
|
|
17497
|
+
if (!status3.ok)
|
|
17498
|
+
return { durable: false, reason: `tree state unreadable: ${status3.error}` };
|
|
17499
|
+
const upstream = yield [
|
|
17500
|
+
"rev-parse",
|
|
17501
|
+
"--abbrev-ref",
|
|
17502
|
+
"--symbolic-full-name",
|
|
17503
|
+
"@{upstream}"
|
|
17504
|
+
];
|
|
17505
|
+
let localOnlyCommits;
|
|
17506
|
+
if (upstream.ok && upstream.out) {
|
|
17507
|
+
const ahead = yield ["rev-list", "--count", "@{upstream}..HEAD"];
|
|
17508
|
+
localOnlyCommits = !ahead.ok || Number(ahead.out) > 0;
|
|
17509
|
+
} else {
|
|
17510
|
+
const remoteBranches = yield ["branch", "-r", "--contains", "HEAD"];
|
|
17511
|
+
localOnlyCommits = !remoteBranches.ok || remoteBranches.out === "";
|
|
17512
|
+
}
|
|
17513
|
+
return treeDurability({ dirty: status3.out !== "", localOnlyCommits });
|
|
17514
|
+
}
|
|
17515
|
+
async function checkDurability(cwd) {
|
|
17516
|
+
if (!existsSync44(cwd)) return { durable: true };
|
|
17517
|
+
const probes = durabilityProbes();
|
|
17518
|
+
let step = probes.next();
|
|
17519
|
+
while (!step.done) step = probes.next(await gitResult(cwd, step.value));
|
|
17520
|
+
return step.value;
|
|
17521
|
+
}
|
|
17522
|
+
function checkDurabilitySync(cwd) {
|
|
17523
|
+
if (!existsSync44(cwd)) return { durable: true };
|
|
17524
|
+
const probes = durabilityProbes();
|
|
17525
|
+
let step = probes.next();
|
|
17526
|
+
while (!step.done) step = probes.next(gitSyncResult(cwd, step.value));
|
|
17527
|
+
return step.value;
|
|
17528
|
+
}
|
|
17529
|
+
|
|
17530
|
+
// src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
|
|
17531
|
+
var DISABLED = {
|
|
17532
|
+
enabled: false,
|
|
17533
|
+
trunk: false,
|
|
17534
|
+
install: true,
|
|
17535
|
+
commitBeforeManualChecks: false,
|
|
17536
|
+
copy: [".env", "settings.local.json", ".claude/settings.local.json"]
|
|
17537
|
+
};
|
|
17538
|
+
function worktreeConfigFor(cwd) {
|
|
17539
|
+
try {
|
|
17540
|
+
return loadConfigFrom(cwd).worktree ?? DISABLED;
|
|
17541
|
+
} catch {
|
|
17542
|
+
return DISABLED;
|
|
17543
|
+
}
|
|
17544
|
+
}
|
|
17545
|
+
|
|
17546
|
+
// src/commands/sessions/daemon/worktree/allocateTree.ts
|
|
17547
|
+
function allocateTree(requestedCwd, boundTreeRoots2, options2 = {}) {
|
|
17548
|
+
if (!requestedCwd)
|
|
17549
|
+
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
17550
|
+
const repoRoot = findRepoRoot(requestedCwd) ?? requestedCwd;
|
|
17551
|
+
const cfg = worktreeConfigFor(repoRoot);
|
|
17552
|
+
if (!cfg.enabled)
|
|
17553
|
+
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
17554
|
+
const clone = mainWorktree(repoRoot) ?? repoRoot;
|
|
17555
|
+
if (planAllocation(clone, boundTreeRoots2) === "primary" && !wouldDisturbWorkInProgress(clone, options2.forCheckout === true))
|
|
17556
|
+
return { cwd: clone, kind: "primary", created: false, clone };
|
|
17557
|
+
const path71 = createWorktree(
|
|
17558
|
+
clone,
|
|
17559
|
+
{ root: cfg.root, trunk: cfg.trunk },
|
|
17560
|
+
boundTreeRoots2
|
|
17561
|
+
);
|
|
17562
|
+
return { cwd: path71, kind: "worktree", created: true, clone };
|
|
17563
|
+
}
|
|
17564
|
+
function wouldDisturbWorkInProgress(clone, forCheckout) {
|
|
17565
|
+
if (!forCheckout) return false;
|
|
17566
|
+
const durability = checkDurabilitySync(clone);
|
|
17567
|
+
if (durability.durable) return false;
|
|
17568
|
+
daemonLog(
|
|
17569
|
+
`tree ${clone} not used for a PR checkout: ${durability.reason} \u2014 spilling to a worktree`
|
|
17570
|
+
);
|
|
17571
|
+
return true;
|
|
17572
|
+
}
|
|
17573
|
+
|
|
17574
|
+
// src/commands/sessions/daemon/persistedSessionSchema.ts
|
|
17575
|
+
import { z as z6 } from "zod";
|
|
17576
|
+
var persistedSessionSchema = z6.object({
|
|
17577
|
+
name: z6.string(),
|
|
17578
|
+
title: z6.string().optional(),
|
|
17579
|
+
subtitle: z6.string().optional(),
|
|
17580
|
+
commandType: z6.enum(["claude", "run", "assist"]),
|
|
17581
|
+
harness: z6.enum(["claude", "codex", "pi"]).optional(),
|
|
17582
|
+
status: z6.enum(["running", "waiting", "done", "error", "stopped"]).optional(),
|
|
17583
|
+
cwd: z6.string(),
|
|
17584
|
+
startedAt: z6.number(),
|
|
17585
|
+
runningMs: z6.number().optional(),
|
|
17586
|
+
claudeSessionId: z6.string().optional(),
|
|
17587
|
+
initialPrompt: z6.string().optional(),
|
|
17588
|
+
runName: z6.string().optional(),
|
|
17589
|
+
runArgs: z6.array(z6.string()).optional(),
|
|
17590
|
+
assistArgs: z6.array(z6.string()).optional(),
|
|
17591
|
+
activity: activitySchema.optional(),
|
|
17592
|
+
starred: z6.boolean().optional(),
|
|
17593
|
+
undurable: z6.object({ reason: z6.string(), removesTree: z6.boolean().optional() }).optional()
|
|
17594
|
+
});
|
|
17595
|
+
|
|
17596
|
+
// src/commands/sessions/daemon/toPersistedSession.ts
|
|
17597
|
+
function toPersistedSession(session) {
|
|
17598
|
+
return {
|
|
17599
|
+
name: session.name,
|
|
17600
|
+
title: session.title,
|
|
17601
|
+
subtitle: session.subtitle,
|
|
17602
|
+
commandType: session.commandType,
|
|
17603
|
+
harness: session.harness,
|
|
17604
|
+
status: session.status,
|
|
17605
|
+
cwd: session.cwd ?? process.cwd(),
|
|
17606
|
+
startedAt: session.startedAt,
|
|
17607
|
+
runningMs: accumulatedRunningMs(session),
|
|
17608
|
+
claudeSessionId: session.claudeSessionId,
|
|
17609
|
+
initialPrompt: session.initialPrompt,
|
|
17610
|
+
runName: session.runName,
|
|
17611
|
+
runArgs: session.runArgs,
|
|
17612
|
+
assistArgs: session.assistArgs,
|
|
17613
|
+
activity: session.activity,
|
|
17614
|
+
starred: session.starred,
|
|
17615
|
+
undurable: session.undurable
|
|
17616
|
+
};
|
|
17617
|
+
}
|
|
17618
|
+
function accumulatedRunningMs(session) {
|
|
17619
|
+
return session.runningSince != null ? session.runningMs + Date.now() - session.runningSince : session.runningMs;
|
|
17620
|
+
}
|
|
17621
|
+
|
|
17622
|
+
// src/commands/sessions/daemon/loadPersistedSessions.ts
|
|
17623
|
+
var SESSIONS_FILE = "sessions.json";
|
|
17624
|
+
function loadPersistedSessions() {
|
|
17625
|
+
const data = loadJson(SESSIONS_FILE);
|
|
17626
|
+
if (!Array.isArray(data)) return [];
|
|
17627
|
+
return data.flatMap((entry) => {
|
|
17628
|
+
const parsed = persistedSessionSchema.safeParse(entry);
|
|
17629
|
+
return parsed.success ? [parsed.data] : [];
|
|
17630
|
+
});
|
|
17631
|
+
}
|
|
17632
|
+
function savePersistedSessions(sessions) {
|
|
17633
|
+
saveJson(SESSIONS_FILE, sessions);
|
|
17634
|
+
}
|
|
17635
|
+
function persistLiveSessions(sessions) {
|
|
17636
|
+
const live = [...sessions.values()].filter(
|
|
17637
|
+
(s) => (s.pty || s.status === "stopped") && s.status !== "done"
|
|
17638
|
+
);
|
|
17639
|
+
savePersistedSessions(live.map(toPersistedSession));
|
|
17640
|
+
logPersist(live);
|
|
17641
|
+
}
|
|
17642
|
+
var lastPersistSignature = "";
|
|
17643
|
+
function logPersist(live) {
|
|
17644
|
+
const signature = live.map((s) => `${s.id}:${s.status}`).join(",");
|
|
17645
|
+
if (signature === lastPersistSignature) return;
|
|
17646
|
+
lastPersistSignature = signature;
|
|
17647
|
+
daemonLog(
|
|
17648
|
+
live.length > 0 ? `persisted ${live.length} session(s): ${live.map((s) => s.name).join(", ")}` : "persisted 0 sessions (sessions.json cleared)"
|
|
17649
|
+
);
|
|
17650
|
+
}
|
|
17651
|
+
|
|
17652
|
+
// src/commands/sessions/daemon/worktree/persistedTreeRoots.ts
|
|
17653
|
+
function persistedTreeRoots() {
|
|
17654
|
+
const roots = /* @__PURE__ */ new Set();
|
|
17655
|
+
for (const { cwd } of loadPersistedSessions()) {
|
|
17656
|
+
if (cwd) roots.add(findRepoRoot(cwd) ?? cwd);
|
|
17657
|
+
}
|
|
17658
|
+
return roots;
|
|
17659
|
+
}
|
|
17660
|
+
|
|
17661
|
+
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
17662
|
+
import { execFile as execFile8 } from "child_process";
|
|
17663
|
+
import { copyFileSync, existsSync as existsSync46, mkdirSync as mkdirSync16 } from "fs";
|
|
17664
|
+
import { dirname as dirname24, join as join48 } from "path";
|
|
17665
|
+
|
|
17666
|
+
// src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
|
|
17667
|
+
import { existsSync as existsSync45 } from "fs";
|
|
17668
|
+
import { join as join47 } from "path";
|
|
17669
|
+
function detectInstallCommand(repoRoot) {
|
|
17670
|
+
if (!existsSync45(join47(repoRoot, "package.json"))) return null;
|
|
17671
|
+
if (existsSync45(join47(repoRoot, "pnpm-lock.yaml"))) return "pnpm install";
|
|
17672
|
+
if (existsSync45(join47(repoRoot, "yarn.lock"))) return "yarn install";
|
|
17673
|
+
if (existsSync45(join47(repoRoot, "bun.lockb"))) return "bun install";
|
|
17674
|
+
return "npm install";
|
|
17675
|
+
}
|
|
17676
|
+
function resolveInstallCommand(repoRoot, install) {
|
|
17677
|
+
if (install === false) return null;
|
|
17678
|
+
if (typeof install === "string") return install;
|
|
17679
|
+
return detectInstallCommand(repoRoot);
|
|
17680
|
+
}
|
|
17681
|
+
|
|
17682
|
+
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
17683
|
+
function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
17684
|
+
}) {
|
|
17685
|
+
const cfg = worktreeConfigFor(clone);
|
|
17686
|
+
copyConfigFiles(worktreePath, clone, cfg.copy);
|
|
17687
|
+
runInstall(worktreePath, clone, cfg.install, onSeeded);
|
|
17688
|
+
}
|
|
17689
|
+
function copyConfigFiles(worktreePath, clone, copy) {
|
|
17690
|
+
for (const rel of copy) {
|
|
17691
|
+
const src = join48(clone, rel);
|
|
17692
|
+
if (!existsSync46(src)) continue;
|
|
17693
|
+
const dest = join48(worktreePath, rel);
|
|
17694
|
+
try {
|
|
17695
|
+
mkdirSync16(dirname24(dest), { recursive: true });
|
|
17696
|
+
copyFileSync(src, dest);
|
|
17697
|
+
daemonLog(`worktree ${worktreePath} seeded ${rel}`);
|
|
17698
|
+
} catch (error) {
|
|
17699
|
+
daemonLog(
|
|
17700
|
+
`worktree ${worktreePath} failed to seed ${rel}: ${message(error)}`
|
|
17701
|
+
);
|
|
17702
|
+
}
|
|
17703
|
+
}
|
|
17704
|
+
}
|
|
17705
|
+
function runInstall(worktreePath, clone, install, onSeeded) {
|
|
17706
|
+
const command = resolveInstallCommand(clone, install);
|
|
17707
|
+
if (!command) {
|
|
17708
|
+
onSeeded();
|
|
17709
|
+
return;
|
|
17710
|
+
}
|
|
17711
|
+
const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
|
|
17712
|
+
const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
17713
|
+
const shellArgs = windows ? ["/c", command] : ["-l", "-c", command];
|
|
17714
|
+
daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
|
|
17715
|
+
execFile8(shell, shellArgs, { cwd: worktreePath }, (error) => {
|
|
17716
|
+
daemonLog(
|
|
17717
|
+
error ? `worktree ${worktreePath} install failed: ${error.message}` : `worktree ${worktreePath} install complete`
|
|
17718
|
+
);
|
|
17719
|
+
onSeeded();
|
|
17720
|
+
});
|
|
17721
|
+
}
|
|
17722
|
+
function message(error) {
|
|
17723
|
+
return error instanceof Error ? error.message : String(error);
|
|
17724
|
+
}
|
|
17725
|
+
|
|
17726
|
+
// src/commands/review/moveToPrCheckoutTree.ts
|
|
17727
|
+
function placedByDaemon() {
|
|
17728
|
+
return process.env.ASSIST_SESSION === "1";
|
|
17729
|
+
}
|
|
17730
|
+
function seed(worktreePath, clone) {
|
|
17731
|
+
console.log(`Preparing ${worktreePath}\u2026`);
|
|
17732
|
+
return new Promise(
|
|
17733
|
+
(resolve20) => seedWorktree(worktreePath, clone, resolve20)
|
|
17734
|
+
);
|
|
17735
|
+
}
|
|
17736
|
+
async function moveToPrCheckoutTree() {
|
|
17737
|
+
if (placedByDaemon()) return;
|
|
17738
|
+
const from = process.cwd();
|
|
17739
|
+
const alloc = allocateTree(from, persistedTreeRoots(), {
|
|
17740
|
+
forCheckout: true
|
|
17741
|
+
});
|
|
17742
|
+
if (!alloc.cwd || alloc.cwd === from) return;
|
|
17743
|
+
process.chdir(alloc.cwd);
|
|
17744
|
+
console.log(`Checking the PR out in ${alloc.cwd}`);
|
|
17745
|
+
appendDaemonLog(`pr checkout placed in ${alloc.cwd} (invoked from ${from})`);
|
|
17746
|
+
if (alloc.created && alloc.clone) await seed(alloc.cwd, alloc.clone);
|
|
17747
|
+
}
|
|
17748
|
+
|
|
17749
|
+
// src/commands/review/checkoutPr.ts
|
|
17750
|
+
async function checkoutPr(number) {
|
|
17751
|
+
await moveToPrCheckoutTree();
|
|
17752
|
+
try {
|
|
17753
|
+
execFileSync6("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
17754
|
+
} catch {
|
|
17755
|
+
console.error(chalk155.red(`gh pr checkout ${number} failed; aborting.`));
|
|
17756
|
+
process.exit(1);
|
|
17757
|
+
}
|
|
17758
|
+
}
|
|
17759
|
+
|
|
17760
|
+
// src/commands/reviewPrComments.ts
|
|
17761
|
+
async function reviewPrComments(number) {
|
|
17762
|
+
if (number) await checkoutPr(number);
|
|
17763
|
+
const claudeSessionId = randomUUID4();
|
|
17764
|
+
emitActivity({
|
|
17765
|
+
kind: "command",
|
|
17766
|
+
name: "review-pr-comments",
|
|
17767
|
+
claudeSessionId
|
|
17768
|
+
});
|
|
17769
|
+
const { done: done2 } = spawnClaude("/review-pr-comments", {
|
|
17770
|
+
permissionMode: "acceptEdits",
|
|
17771
|
+
sessionId: claudeSessionId
|
|
17772
|
+
});
|
|
17773
|
+
await done2;
|
|
17774
|
+
}
|
|
17775
|
+
|
|
17776
|
+
// src/commands/registerLaunch.ts
|
|
17777
|
+
var RESUME_SESSION_FLAG = "Resume an interrupted Claude session (used by the sessions daemon on restart)";
|
|
17778
|
+
function registerNext(program2) {
|
|
17779
|
+
program2.command("next").argument("[id]", "Backlog item ID to run first").description("Alias for backlog next").option("--once", "Exit after the first completed item run").action(
|
|
17780
|
+
(id, opts) => next({ allowEdits: true, once: opts.once }, id)
|
|
17781
|
+
);
|
|
17782
|
+
}
|
|
17783
|
+
function registerDescriptionLaunch(program2, name, slashCommand, description, alias) {
|
|
17784
|
+
const command = program2.command(name).argument(
|
|
17785
|
+
"[description]",
|
|
17786
|
+
`Text to forward to the /${slashCommand} slash command`
|
|
17787
|
+
).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
|
|
17788
|
+
(text17, opts) => launchMode(slashCommand, {
|
|
17789
|
+
once: opts.once,
|
|
17790
|
+
description: text17,
|
|
17791
|
+
resumeSessionId: opts.resumeSession
|
|
17792
|
+
})
|
|
17793
|
+
);
|
|
17794
|
+
if (alias) command.alias(alias);
|
|
17795
|
+
}
|
|
17796
|
+
function registerReviewPrComments(program2) {
|
|
17797
|
+
program2.command("review-pr-comments").argument("[number]", "PR number to check out first").description("Launch Claude in /review-pr-comments mode (single session)").action((number) => reviewPrComments(number));
|
|
17798
|
+
}
|
|
17799
|
+
function registerLaunch(program2) {
|
|
17800
|
+
registerNext(program2);
|
|
17801
|
+
registerDescriptionLaunch(
|
|
17802
|
+
program2,
|
|
17803
|
+
"draft",
|
|
17804
|
+
"draft",
|
|
17805
|
+
"Launch Claude in /draft mode, chain into next on /next signal",
|
|
17806
|
+
"feat"
|
|
17807
|
+
);
|
|
17808
|
+
registerDescriptionLaunch(
|
|
17809
|
+
program2,
|
|
17810
|
+
"bug",
|
|
17811
|
+
"bug",
|
|
17812
|
+
"Launch Claude in /bug mode, chain into next on /next signal"
|
|
17813
|
+
);
|
|
17814
|
+
registerReviewPrComments(program2);
|
|
17815
|
+
registerRefineLaunch(program2, RESUME_SESSION_FLAG);
|
|
17816
|
+
}
|
|
17817
|
+
|
|
17818
|
+
// src/commands/registerList.ts
|
|
17819
|
+
function registerList(program2) {
|
|
17820
|
+
program2.command("list").alias("ls").description("Alias for backlog list").option(
|
|
17821
|
+
"--status <type>",
|
|
17822
|
+
"Filter by status (todo, in-progress, done, wontdo)"
|
|
17823
|
+
).option("-a, --all", "Include done/wontdo items").option("--all-repos", "List items across all repositories").option("-v, --verbose", "Show all item details").option("--dir <path>", "Override directory for backlog file discovery").action((options2) => {
|
|
17824
|
+
setBacklogDir(options2.dir);
|
|
17825
|
+
return list2(options2);
|
|
17826
|
+
});
|
|
17827
|
+
}
|
|
17828
|
+
|
|
17829
|
+
// src/commands/mermaid/index.ts
|
|
17830
|
+
import { mkdirSync as mkdirSync17, readdirSync as readdirSync9 } from "fs";
|
|
17831
|
+
import { resolve as resolve13 } from "path";
|
|
17832
|
+
import chalk158 from "chalk";
|
|
17833
|
+
|
|
17834
|
+
// src/commands/mermaid/exportFile.ts
|
|
17835
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync31 } from "fs";
|
|
17836
|
+
import { basename as basename13, extname as extname2, resolve as resolve12 } from "path";
|
|
17837
|
+
import chalk157 from "chalk";
|
|
17838
|
+
|
|
17839
|
+
// src/commands/mermaid/renderBlock.ts
|
|
17840
|
+
import chalk156 from "chalk";
|
|
17841
|
+
async function renderBlock(krokiUrl, source) {
|
|
17842
|
+
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
17843
|
+
method: "POST",
|
|
17844
|
+
headers: { "Content-Type": "text/plain" },
|
|
17845
|
+
body: source
|
|
17846
|
+
});
|
|
17847
|
+
if (!response.ok) {
|
|
17848
|
+
console.error(
|
|
17849
|
+
chalk156.red(
|
|
17850
|
+
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
17851
|
+
)
|
|
17852
|
+
);
|
|
17853
|
+
console.error(await response.text());
|
|
17854
|
+
process.exit(1);
|
|
17855
|
+
}
|
|
17856
|
+
return await response.text();
|
|
17857
|
+
}
|
|
17858
|
+
|
|
17859
|
+
// src/commands/mermaid/exportFile.ts
|
|
17860
|
+
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
17861
|
+
const content = readFileSync37(file, "utf8");
|
|
17862
|
+
const blocks = extractMermaidBlocks(content);
|
|
17863
|
+
const stem = basename13(file, extname2(file));
|
|
17864
|
+
if (onlyIndex !== void 0) {
|
|
17865
|
+
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
17866
|
+
console.error(
|
|
17867
|
+
chalk157.red(
|
|
17868
|
+
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
17869
|
+
)
|
|
17870
|
+
);
|
|
17871
|
+
process.exit(1);
|
|
17872
|
+
}
|
|
17873
|
+
console.log(
|
|
17874
|
+
chalk157.gray(
|
|
17875
|
+
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
17876
|
+
)
|
|
17877
|
+
);
|
|
17878
|
+
} else {
|
|
17879
|
+
console.log(chalk157.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
17880
|
+
}
|
|
17881
|
+
for (const [i, source] of blocks.entries()) {
|
|
17882
|
+
const idx = i + 1;
|
|
17883
|
+
if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
|
|
17884
|
+
const outPath = resolve12(outDir, `${stem}-${idx}.svg`);
|
|
17885
|
+
const svg = await renderBlock(krokiUrl, source);
|
|
17886
|
+
writeFileSync31(outPath, svg, "utf8");
|
|
17887
|
+
console.log(chalk157.green(` \u2192 ${outPath}`));
|
|
17888
|
+
}
|
|
17889
|
+
}
|
|
17890
|
+
function extractMermaidBlocks(markdown) {
|
|
17891
|
+
const matches = [...markdown.matchAll(/```mermaid\n([\s\S]*?)\n```/g)];
|
|
17892
|
+
return matches.map(([, src]) => src);
|
|
17893
|
+
}
|
|
17894
|
+
|
|
17895
|
+
// src/commands/mermaid/index.ts
|
|
17896
|
+
async function mermaidExport(file, options2 = {}) {
|
|
17897
|
+
const { mermaid } = loadConfig();
|
|
17898
|
+
const outDir = resolve13(process.cwd(), options2.out ?? ".");
|
|
17899
|
+
mkdirSync17(outDir, { recursive: true });
|
|
17900
|
+
if (options2.index !== void 0) {
|
|
17901
|
+
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
17902
|
+
console.error(
|
|
17903
|
+
chalk158.red(`--index must be a positive integer (got ${options2.index})`)
|
|
17904
|
+
);
|
|
17905
|
+
process.exit(1);
|
|
17906
|
+
}
|
|
17907
|
+
if (!file) {
|
|
17908
|
+
console.error(chalk158.red("--index requires a file argument"));
|
|
17909
|
+
process.exit(1);
|
|
17910
|
+
}
|
|
17911
|
+
}
|
|
17912
|
+
const files = file ? [file] : readdirSync9(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
17913
|
+
if (files.length === 0) {
|
|
17914
|
+
console.log(chalk158.gray("No markdown files found in current directory."));
|
|
17915
|
+
return;
|
|
17916
|
+
}
|
|
17917
|
+
for (const f of files) {
|
|
17918
|
+
await exportFile(f, outDir, mermaid.krokiUrl, options2.index);
|
|
17919
|
+
}
|
|
17524
17920
|
}
|
|
17525
17921
|
|
|
17526
17922
|
// src/commands/registerMermaid.ts
|
|
@@ -17547,7 +17943,7 @@ function registerMermaid(program2) {
|
|
|
17547
17943
|
// src/commands/netcap/netcap.ts
|
|
17548
17944
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
17549
17945
|
import { createServer as createServer2 } from "http";
|
|
17550
|
-
import { dirname as
|
|
17946
|
+
import { dirname as dirname26 } from "path";
|
|
17551
17947
|
import chalk160 from "chalk";
|
|
17552
17948
|
|
|
17553
17949
|
// src/commands/netcap/corsHeaders.ts
|
|
@@ -17626,15 +18022,15 @@ function createNetcapHandler(options2) {
|
|
|
17626
18022
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
17627
18023
|
import { cp, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
17628
18024
|
import { networkInterfaces } from "os";
|
|
17629
|
-
import { join as
|
|
18025
|
+
import { join as join50 } from "path";
|
|
17630
18026
|
import chalk159 from "chalk";
|
|
17631
18027
|
|
|
17632
18028
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
17633
|
-
import { dirname as
|
|
18029
|
+
import { dirname as dirname25, join as join49 } from "path";
|
|
17634
18030
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
17635
|
-
var moduleDir =
|
|
18031
|
+
var moduleDir = dirname25(fileURLToPath6(import.meta.url));
|
|
17636
18032
|
function netcapExtensionDir() {
|
|
17637
|
-
return
|
|
18033
|
+
return join49(moduleDir, "commands", "netcap", "netcap-extension");
|
|
17638
18034
|
}
|
|
17639
18035
|
|
|
17640
18036
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
@@ -17649,7 +18045,7 @@ function lanIPv4() {
|
|
|
17649
18045
|
return void 0;
|
|
17650
18046
|
}
|
|
17651
18047
|
async function configureBackground(dir, host, port, filter) {
|
|
17652
|
-
const file =
|
|
18048
|
+
const file = join50(dir, "background.js");
|
|
17653
18049
|
const source = await readFile3(file, "utf8");
|
|
17654
18050
|
await writeFile3(
|
|
17655
18051
|
file,
|
|
@@ -17689,20 +18085,20 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
17689
18085
|
}
|
|
17690
18086
|
|
|
17691
18087
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
17692
|
-
import { isAbsolute as isAbsolute2, join as
|
|
18088
|
+
import { isAbsolute as isAbsolute2, join as join52, resolve as resolve14 } from "path";
|
|
17693
18089
|
|
|
17694
18090
|
// src/commands/netcap/defaultCapturePath.ts
|
|
17695
18091
|
import { homedir as homedir19 } from "os";
|
|
17696
|
-
import { join as
|
|
18092
|
+
import { join as join51 } from "path";
|
|
17697
18093
|
function defaultCapturePath() {
|
|
17698
|
-
return
|
|
18094
|
+
return join51(homedir19(), ".assist", "netcap", "capture.jsonl");
|
|
17699
18095
|
}
|
|
17700
18096
|
|
|
17701
18097
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
17702
18098
|
function resolveNetcapOutPath(out) {
|
|
17703
18099
|
if (!out) return defaultCapturePath();
|
|
17704
18100
|
const dir = isAbsolute2(out) ? out : resolve14(process.cwd(), out);
|
|
17705
|
-
return
|
|
18101
|
+
return join52(dir, "capture.jsonl");
|
|
17706
18102
|
}
|
|
17707
18103
|
|
|
17708
18104
|
// src/commands/netcap/netcap.ts
|
|
@@ -17710,7 +18106,7 @@ async function netcap(options2) {
|
|
|
17710
18106
|
const port = Number(options2.port);
|
|
17711
18107
|
const outPath = resolveNetcapOutPath(options2.out);
|
|
17712
18108
|
const filter = options2.filter ?? "";
|
|
17713
|
-
await mkdir4(
|
|
18109
|
+
await mkdir4(dirname26(outPath), { recursive: true });
|
|
17714
18110
|
const extensionPath = await prepareExtensionForLoad(port, filter);
|
|
17715
18111
|
let count7 = 0;
|
|
17716
18112
|
const handler = createNetcapHandler({
|
|
@@ -17749,7 +18145,7 @@ netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} t
|
|
|
17749
18145
|
|
|
17750
18146
|
// src/commands/netcap/netcapExtract.ts
|
|
17751
18147
|
import { writeFileSync as writeFileSync32 } from "fs";
|
|
17752
|
-
import { join as
|
|
18148
|
+
import { join as join53 } from "path";
|
|
17753
18149
|
import chalk161 from "chalk";
|
|
17754
18150
|
|
|
17755
18151
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
@@ -18194,7 +18590,7 @@ function extractPostsFromCapture(captureFile) {
|
|
|
18194
18590
|
function netcapExtract(file) {
|
|
18195
18591
|
const captureFile = file ?? defaultCapturePath();
|
|
18196
18592
|
const posts = extractPostsFromCapture(captureFile);
|
|
18197
|
-
const outFile =
|
|
18593
|
+
const outFile = join53(captureFile, "..", "posts.json");
|
|
18198
18594
|
writeFileSync32(outFile, `${JSON.stringify(posts, null, 2)}
|
|
18199
18595
|
`);
|
|
18200
18596
|
console.log(
|
|
@@ -18346,7 +18742,7 @@ function registerPrompts(program2) {
|
|
|
18346
18742
|
}
|
|
18347
18743
|
|
|
18348
18744
|
// src/commands/prs/shared.ts
|
|
18349
|
-
import { execSync as
|
|
18745
|
+
import { execSync as execSync41 } from "child_process";
|
|
18350
18746
|
function isGhNotInstalled(error) {
|
|
18351
18747
|
if (error instanceof Error) {
|
|
18352
18748
|
const msg = error.message.toLowerCase();
|
|
@@ -18364,12 +18760,12 @@ function getRepoInfo() {
|
|
|
18364
18760
|
const preferred = getPreferredRemoteRepo();
|
|
18365
18761
|
if (preferred) return preferred;
|
|
18366
18762
|
const repoInfo = JSON.parse(
|
|
18367
|
-
|
|
18763
|
+
execSync41("gh repo view --json owner,name", { encoding: "utf8" })
|
|
18368
18764
|
);
|
|
18369
18765
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
18370
18766
|
}
|
|
18371
18767
|
function getCurrentBranch2() {
|
|
18372
|
-
return
|
|
18768
|
+
return execSync41("git rev-parse --abbrev-ref HEAD", {
|
|
18373
18769
|
encoding: "utf8"
|
|
18374
18770
|
}).trim();
|
|
18375
18771
|
}
|
|
@@ -18377,7 +18773,7 @@ function viewCurrentPr(fields) {
|
|
|
18377
18773
|
const { org, repo } = getRepoInfo();
|
|
18378
18774
|
const branch2 = getCurrentBranch2();
|
|
18379
18775
|
return JSON.parse(
|
|
18380
|
-
|
|
18776
|
+
execSync41(`gh pr view ${branch2} --json ${fields} -R ${org}/${repo}`, {
|
|
18381
18777
|
encoding: "utf8"
|
|
18382
18778
|
})
|
|
18383
18779
|
);
|
|
@@ -18679,24 +19075,24 @@ function edit(options2) {
|
|
|
18679
19075
|
}
|
|
18680
19076
|
|
|
18681
19077
|
// src/commands/prs/fixed.ts
|
|
18682
|
-
import { execSync as
|
|
19078
|
+
import { execSync as execSync44 } from "child_process";
|
|
18683
19079
|
|
|
18684
19080
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
18685
|
-
import { execSync as
|
|
19081
|
+
import { execSync as execSync43 } from "child_process";
|
|
18686
19082
|
import { unlinkSync as unlinkSync14, writeFileSync as writeFileSync33 } from "fs";
|
|
18687
19083
|
import { tmpdir as tmpdir6 } from "os";
|
|
18688
|
-
import { join as
|
|
19084
|
+
import { join as join55 } from "path";
|
|
18689
19085
|
|
|
18690
19086
|
// src/commands/prs/loadCommentsCache.ts
|
|
18691
|
-
import { existsSync as
|
|
18692
|
-
import { join as
|
|
19087
|
+
import { existsSync as existsSync47, readFileSync as readFileSync39, unlinkSync as unlinkSync13 } from "fs";
|
|
19088
|
+
import { join as join54 } from "path";
|
|
18693
19089
|
import { parse as parse2 } from "yaml";
|
|
18694
19090
|
function getCachePath(prNumber) {
|
|
18695
|
-
return
|
|
19091
|
+
return join54(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
18696
19092
|
}
|
|
18697
19093
|
function loadCommentsCache(prNumber) {
|
|
18698
19094
|
const cachePath = getCachePath(prNumber);
|
|
18699
|
-
if (!
|
|
19095
|
+
if (!existsSync47(cachePath)) {
|
|
18700
19096
|
return null;
|
|
18701
19097
|
}
|
|
18702
19098
|
const content = readFileSync39(cachePath, "utf8");
|
|
@@ -18704,16 +19100,16 @@ function loadCommentsCache(prNumber) {
|
|
|
18704
19100
|
}
|
|
18705
19101
|
function deleteCommentsCache(prNumber) {
|
|
18706
19102
|
const cachePath = getCachePath(prNumber);
|
|
18707
|
-
if (
|
|
19103
|
+
if (existsSync47(cachePath)) {
|
|
18708
19104
|
unlinkSync13(cachePath);
|
|
18709
19105
|
console.log("No more unresolved line comments. Cache dropped.");
|
|
18710
19106
|
}
|
|
18711
19107
|
}
|
|
18712
19108
|
|
|
18713
19109
|
// src/commands/prs/replyToComment.ts
|
|
18714
|
-
import { execSync as
|
|
19110
|
+
import { execSync as execSync42 } from "child_process";
|
|
18715
19111
|
function replyToComment(org, repo, prNumber, commentId, message2) {
|
|
18716
|
-
|
|
19112
|
+
execSync42(
|
|
18717
19113
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message2.replace(/"/g, String.raw`\"`)}" -F in_reply_to=${commentId}`,
|
|
18718
19114
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
18719
19115
|
);
|
|
@@ -18722,10 +19118,10 @@ function replyToComment(org, repo, prNumber, commentId, message2) {
|
|
|
18722
19118
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
18723
19119
|
function resolveThread(threadId) {
|
|
18724
19120
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
18725
|
-
const queryFile =
|
|
19121
|
+
const queryFile = join55(tmpdir6(), `gh-mutation-${Date.now()}.graphql`);
|
|
18726
19122
|
writeFileSync33(queryFile, mutation);
|
|
18727
19123
|
try {
|
|
18728
|
-
|
|
19124
|
+
execSync43(
|
|
18729
19125
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
18730
19126
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
18731
19127
|
);
|
|
@@ -18777,7 +19173,7 @@ function resolveCommentWithReply(commentId, message2) {
|
|
|
18777
19173
|
// src/commands/prs/fixed.ts
|
|
18778
19174
|
function verifySha(sha) {
|
|
18779
19175
|
try {
|
|
18780
|
-
return
|
|
19176
|
+
return execSync44(`git rev-parse --verify ${sha}`, {
|
|
18781
19177
|
encoding: "utf8"
|
|
18782
19178
|
}).trim();
|
|
18783
19179
|
} catch {
|
|
@@ -18791,7 +19187,7 @@ function fixed(commentId, sha) {
|
|
|
18791
19187
|
const { org, repo } = getRepoInfo();
|
|
18792
19188
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
18793
19189
|
const message2 = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
18794
|
-
|
|
19190
|
+
pushCommit();
|
|
18795
19191
|
resolveCommentWithReply(commentId, message2);
|
|
18796
19192
|
} catch (error) {
|
|
18797
19193
|
if (isGhNotInstalled(error)) {
|
|
@@ -18804,21 +19200,21 @@ function fixed(commentId, sha) {
|
|
|
18804
19200
|
}
|
|
18805
19201
|
|
|
18806
19202
|
// src/commands/prs/listComments/index.ts
|
|
18807
|
-
import { existsSync as
|
|
18808
|
-
import { join as
|
|
19203
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync18, writeFileSync as writeFileSync35 } from "fs";
|
|
19204
|
+
import { join as join57 } from "path";
|
|
18809
19205
|
import { stringify } from "yaml";
|
|
18810
19206
|
|
|
18811
19207
|
// src/commands/prs/fetchThreadIds.ts
|
|
18812
|
-
import { execSync as
|
|
19208
|
+
import { execSync as execSync45 } from "child_process";
|
|
18813
19209
|
import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync34 } from "fs";
|
|
18814
19210
|
import { tmpdir as tmpdir7 } from "os";
|
|
18815
|
-
import { join as
|
|
19211
|
+
import { join as join56 } from "path";
|
|
18816
19212
|
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 } } } } } } }`;
|
|
18817
19213
|
function fetchThreadIds(org, repo, prNumber) {
|
|
18818
|
-
const queryFile =
|
|
19214
|
+
const queryFile = join56(tmpdir7(), `gh-query-${Date.now()}.graphql`);
|
|
18819
19215
|
writeFileSync34(queryFile, THREAD_QUERY);
|
|
18820
19216
|
try {
|
|
18821
|
-
const result =
|
|
19217
|
+
const result = execSync45(
|
|
18822
19218
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
18823
19219
|
{ encoding: "utf8" }
|
|
18824
19220
|
);
|
|
@@ -18840,9 +19236,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
18840
19236
|
}
|
|
18841
19237
|
|
|
18842
19238
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
18843
|
-
import { execSync as
|
|
19239
|
+
import { execSync as execSync46 } from "child_process";
|
|
18844
19240
|
function fetchJson(endpoint) {
|
|
18845
|
-
const result =
|
|
19241
|
+
const result = execSync46(`gh api --paginate ${endpoint}`, {
|
|
18846
19242
|
encoding: "utf8"
|
|
18847
19243
|
});
|
|
18848
19244
|
if (!result.trim()) return [];
|
|
@@ -18929,16 +19325,16 @@ function printComments2(result) {
|
|
|
18929
19325
|
|
|
18930
19326
|
// src/commands/prs/listComments/index.ts
|
|
18931
19327
|
function writeCommentsCache(prNumber, comments3) {
|
|
18932
|
-
const assistDir =
|
|
18933
|
-
if (!
|
|
18934
|
-
|
|
19328
|
+
const assistDir = join57(process.cwd(), ".assist");
|
|
19329
|
+
if (!existsSync48(assistDir)) {
|
|
19330
|
+
mkdirSync18(assistDir, { recursive: true });
|
|
18935
19331
|
}
|
|
18936
19332
|
const cacheData = {
|
|
18937
19333
|
prNumber,
|
|
18938
19334
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18939
19335
|
comments: comments3
|
|
18940
19336
|
};
|
|
18941
|
-
const cachePath =
|
|
19337
|
+
const cachePath = join57(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
18942
19338
|
writeFileSync35(cachePath, stringify(cacheData));
|
|
18943
19339
|
}
|
|
18944
19340
|
function handleKnownErrors(error) {
|
|
@@ -18971,7 +19367,7 @@ async function listComments() {
|
|
|
18971
19367
|
];
|
|
18972
19368
|
updateCache(prNumber, allComments);
|
|
18973
19369
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
18974
|
-
const cachePath = hasLineComments ?
|
|
19370
|
+
const cachePath = hasLineComments ? join57(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
18975
19371
|
return { comments: allComments, cachePath };
|
|
18976
19372
|
} catch (error) {
|
|
18977
19373
|
const handled = handleKnownErrors(error);
|
|
@@ -18981,7 +19377,7 @@ async function listComments() {
|
|
|
18981
19377
|
}
|
|
18982
19378
|
|
|
18983
19379
|
// src/commands/prs/prs/index.ts
|
|
18984
|
-
import { execSync as
|
|
19380
|
+
import { execSync as execSync47 } from "child_process";
|
|
18985
19381
|
|
|
18986
19382
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
18987
19383
|
import enquirer9 from "enquirer";
|
|
@@ -19088,7 +19484,7 @@ async function prs(options2) {
|
|
|
19088
19484
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
19089
19485
|
try {
|
|
19090
19486
|
const { org, repo } = getRepoInfo();
|
|
19091
|
-
const result =
|
|
19487
|
+
const result = execSync47(
|
|
19092
19488
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
|
|
19093
19489
|
{ encoding: "utf8" }
|
|
19094
19490
|
);
|
|
@@ -19159,16 +19555,16 @@ function buildCreateArgs(title, body, options2) {
|
|
|
19159
19555
|
}
|
|
19160
19556
|
|
|
19161
19557
|
// src/commands/prs/readSessionPrRef.ts
|
|
19162
|
-
import { execSync as
|
|
19558
|
+
import { execSync as execSync48 } from "child_process";
|
|
19163
19559
|
function readSessionPrRef() {
|
|
19164
19560
|
try {
|
|
19165
|
-
const branch2 =
|
|
19561
|
+
const branch2 = execSync48("git rev-parse --abbrev-ref HEAD", {
|
|
19166
19562
|
encoding: "utf8",
|
|
19167
19563
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19168
19564
|
}).trim();
|
|
19169
19565
|
if (!branch2 || branch2 === "HEAD") return null;
|
|
19170
19566
|
const pr = JSON.parse(
|
|
19171
|
-
|
|
19567
|
+
execSync48(`gh pr view ${branch2} --json number,title,url,state`, {
|
|
19172
19568
|
encoding: "utf8",
|
|
19173
19569
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19174
19570
|
})
|
|
@@ -19296,7 +19692,7 @@ function reply(commentId, body) {
|
|
|
19296
19692
|
}
|
|
19297
19693
|
|
|
19298
19694
|
// src/commands/prs/wontfix.ts
|
|
19299
|
-
import { execSync as
|
|
19695
|
+
import { execSync as execSync49 } from "child_process";
|
|
19300
19696
|
function validateReason(reason2) {
|
|
19301
19697
|
const lowerReason = reason2.toLowerCase();
|
|
19302
19698
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -19313,7 +19709,7 @@ function validateShaReferences(reason2) {
|
|
|
19313
19709
|
const invalidShas = [];
|
|
19314
19710
|
for (const sha of shas) {
|
|
19315
19711
|
try {
|
|
19316
|
-
|
|
19712
|
+
execSync49(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
19317
19713
|
} catch {
|
|
19318
19714
|
invalidShas.push(sha);
|
|
19319
19715
|
}
|
|
@@ -19590,10 +19986,10 @@ import chalk168 from "chalk";
|
|
|
19590
19986
|
import Enquirer2 from "enquirer";
|
|
19591
19987
|
|
|
19592
19988
|
// src/commands/ravendb/searchItems.ts
|
|
19593
|
-
import { execSync as
|
|
19989
|
+
import { execSync as execSync50 } from "child_process";
|
|
19594
19990
|
import chalk167 from "chalk";
|
|
19595
19991
|
function opExec(args) {
|
|
19596
|
-
return
|
|
19992
|
+
return execSync50(`op ${args}`, {
|
|
19597
19993
|
encoding: "utf8",
|
|
19598
19994
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19599
19995
|
}).trim();
|
|
@@ -19745,7 +20141,7 @@ ${errorText}`
|
|
|
19745
20141
|
}
|
|
19746
20142
|
|
|
19747
20143
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
19748
|
-
import { execSync as
|
|
20144
|
+
import { execSync as execSync51 } from "child_process";
|
|
19749
20145
|
import chalk172 from "chalk";
|
|
19750
20146
|
function resolveOpSecret(reference) {
|
|
19751
20147
|
if (!reference.startsWith("op://")) {
|
|
@@ -19753,7 +20149,7 @@ function resolveOpSecret(reference) {
|
|
|
19753
20149
|
process.exit(1);
|
|
19754
20150
|
}
|
|
19755
20151
|
try {
|
|
19756
|
-
return
|
|
20152
|
+
return execSync51(`op read "${reference}"`, {
|
|
19757
20153
|
encoding: "utf8",
|
|
19758
20154
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19759
20155
|
}).trim();
|
|
@@ -20017,7 +20413,7 @@ Refactor check failed:
|
|
|
20017
20413
|
}
|
|
20018
20414
|
|
|
20019
20415
|
// src/commands/refactor/check/getViolations/index.ts
|
|
20020
|
-
import { execSync as
|
|
20416
|
+
import { execSync as execSync52 } from "child_process";
|
|
20021
20417
|
import fs25 from "fs";
|
|
20022
20418
|
import { minimatch as minimatch6 } from "minimatch";
|
|
20023
20419
|
|
|
@@ -20067,7 +20463,7 @@ function getGitFiles(options2) {
|
|
|
20067
20463
|
}
|
|
20068
20464
|
const files = /* @__PURE__ */ new Set();
|
|
20069
20465
|
if (options2.staged || options2.modified) {
|
|
20070
|
-
const staged =
|
|
20466
|
+
const staged = execSync52("git diff --cached --name-only", {
|
|
20071
20467
|
encoding: "utf8"
|
|
20072
20468
|
});
|
|
20073
20469
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -20075,7 +20471,7 @@ function getGitFiles(options2) {
|
|
|
20075
20471
|
}
|
|
20076
20472
|
}
|
|
20077
20473
|
if (options2.unstaged || options2.modified) {
|
|
20078
|
-
const unstaged =
|
|
20474
|
+
const unstaged = execSync52("git diff --name-only", { encoding: "utf8" });
|
|
20079
20475
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
20080
20476
|
files.add(file);
|
|
20081
20477
|
}
|
|
@@ -21342,8 +21738,8 @@ function findRootParent(file, importedBy, visited) {
|
|
|
21342
21738
|
function clusterFiles(graph) {
|
|
21343
21739
|
const clusters = /* @__PURE__ */ new Map();
|
|
21344
21740
|
for (const file of graph.files) {
|
|
21345
|
-
const
|
|
21346
|
-
if (
|
|
21741
|
+
const basename19 = path52.basename(file, path52.extname(file));
|
|
21742
|
+
if (basename19 === "index") continue;
|
|
21347
21743
|
const importers = graph.importedBy.get(file);
|
|
21348
21744
|
if (!importers || importers.size !== 1) continue;
|
|
21349
21745
|
const parent = [...importers][0];
|
|
@@ -21649,9 +22045,6 @@ function registerRefactor(program2) {
|
|
|
21649
22045
|
registerRestructure(refactorCommand);
|
|
21650
22046
|
}
|
|
21651
22047
|
|
|
21652
|
-
// src/commands/review/review.ts
|
|
21653
|
-
import { execFileSync as execFileSync9 } from "child_process";
|
|
21654
|
-
|
|
21655
22048
|
// src/commands/review/annotateDiffWithLineNumbers.ts
|
|
21656
22049
|
var FILE_HEADER2 = /^\+\+\+ (?:b\/)?(.+)$/;
|
|
21657
22050
|
var HUNK_HEADER2 = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
|
|
@@ -21766,28 +22159,28 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
|
21766
22159
|
|
|
21767
22160
|
// src/commands/review/buildReviewPaths.ts
|
|
21768
22161
|
import { homedir as homedir20 } from "os";
|
|
21769
|
-
import { basename as
|
|
22162
|
+
import { basename as basename14, join as join58 } from "path";
|
|
21770
22163
|
function buildReviewPaths(repoRoot, key) {
|
|
21771
|
-
const reviewDir =
|
|
22164
|
+
const reviewDir = join58(
|
|
21772
22165
|
homedir20(),
|
|
21773
22166
|
".assist",
|
|
21774
22167
|
"reviews",
|
|
21775
|
-
|
|
22168
|
+
basename14(repoRoot),
|
|
21776
22169
|
key
|
|
21777
22170
|
);
|
|
21778
22171
|
return {
|
|
21779
22172
|
reviewDir,
|
|
21780
|
-
requestPath:
|
|
21781
|
-
claudePath:
|
|
21782
|
-
codexPath:
|
|
21783
|
-
synthesisPath:
|
|
22173
|
+
requestPath: join58(reviewDir, "request.md"),
|
|
22174
|
+
claudePath: join58(reviewDir, "claude.md"),
|
|
22175
|
+
codexPath: join58(reviewDir, "codex.md"),
|
|
22176
|
+
synthesisPath: join58(reviewDir, "synthesis.md")
|
|
21784
22177
|
};
|
|
21785
22178
|
}
|
|
21786
22179
|
|
|
21787
22180
|
// src/commands/review/fetchExistingComments.ts
|
|
21788
|
-
import { execSync as
|
|
22181
|
+
import { execSync as execSync53 } from "child_process";
|
|
21789
22182
|
function fetchRawComments(org, repo, prNumber) {
|
|
21790
|
-
const out =
|
|
22183
|
+
const out = execSync53(
|
|
21791
22184
|
`gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
|
|
21792
22185
|
{ encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
|
|
21793
22186
|
);
|
|
@@ -21818,14 +22211,14 @@ function fetchExistingComments() {
|
|
|
21818
22211
|
}
|
|
21819
22212
|
|
|
21820
22213
|
// src/commands/review/gatherContext.ts
|
|
21821
|
-
import { execSync as
|
|
22214
|
+
import { execSync as execSync56 } from "child_process";
|
|
21822
22215
|
|
|
21823
22216
|
// src/commands/review/fetchPrDiff.ts
|
|
21824
|
-
import { execSync as
|
|
22217
|
+
import { execSync as execSync54 } from "child_process";
|
|
21825
22218
|
function fetchPrDiff(prNumber, baseSha, headSha) {
|
|
21826
22219
|
const { org, repo } = getRepoInfo();
|
|
21827
22220
|
try {
|
|
21828
|
-
return
|
|
22221
|
+
return execSync54(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
|
|
21829
22222
|
encoding: "utf8",
|
|
21830
22223
|
maxBuffer: 256 * 1024 * 1024,
|
|
21831
22224
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -21840,19 +22233,19 @@ function isDiffTooLarge(error) {
|
|
|
21840
22233
|
}
|
|
21841
22234
|
function fetchDiffViaGit(baseSha, headSha) {
|
|
21842
22235
|
try {
|
|
21843
|
-
|
|
22236
|
+
execSync54(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
|
|
21844
22237
|
} catch {
|
|
21845
22238
|
}
|
|
21846
|
-
return
|
|
22239
|
+
return execSync54(`git diff ${baseSha}...${headSha}`, {
|
|
21847
22240
|
encoding: "utf8",
|
|
21848
22241
|
maxBuffer: 256 * 1024 * 1024
|
|
21849
22242
|
});
|
|
21850
22243
|
}
|
|
21851
22244
|
|
|
21852
22245
|
// src/commands/review/fetchPrDiffInfo.ts
|
|
21853
|
-
import { execSync as
|
|
22246
|
+
import { execSync as execSync55 } from "child_process";
|
|
21854
22247
|
function getCurrentBranch3() {
|
|
21855
|
-
return
|
|
22248
|
+
return execSync55("git rev-parse --abbrev-ref HEAD", {
|
|
21856
22249
|
encoding: "utf8"
|
|
21857
22250
|
}).trim();
|
|
21858
22251
|
}
|
|
@@ -21860,7 +22253,7 @@ function fetchPrDiffInfo() {
|
|
|
21860
22253
|
const { org, repo } = getRepoInfo();
|
|
21861
22254
|
const branch2 = getCurrentBranch3();
|
|
21862
22255
|
const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
|
|
21863
|
-
const raw =
|
|
22256
|
+
const raw = execSync55(
|
|
21864
22257
|
`gh pr list --state open --head ${branch2} --json ${fields} -R ${org}/${repo}`,
|
|
21865
22258
|
{
|
|
21866
22259
|
encoding: "utf8",
|
|
@@ -21885,7 +22278,7 @@ function fetchPrDiffInfo() {
|
|
|
21885
22278
|
}
|
|
21886
22279
|
function fetchPrChangedFiles(prNumber) {
|
|
21887
22280
|
const { org, repo } = getRepoInfo();
|
|
21888
|
-
const out =
|
|
22281
|
+
const out = execSync55(
|
|
21889
22282
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
|
|
21890
22283
|
{
|
|
21891
22284
|
encoding: "utf8",
|
|
@@ -21897,11 +22290,11 @@ function fetchPrChangedFiles(prNumber) {
|
|
|
21897
22290
|
|
|
21898
22291
|
// src/commands/review/gatherContext.ts
|
|
21899
22292
|
function gatherContext() {
|
|
21900
|
-
const branch2 =
|
|
22293
|
+
const branch2 = execSync56("git rev-parse --abbrev-ref HEAD", {
|
|
21901
22294
|
encoding: "utf8"
|
|
21902
22295
|
}).trim();
|
|
21903
|
-
const sha =
|
|
21904
|
-
const shortSha =
|
|
22296
|
+
const sha = execSync56("git rev-parse HEAD", { encoding: "utf8" }).trim();
|
|
22297
|
+
const shortSha = execSync56("git rev-parse --short=7 HEAD", {
|
|
21905
22298
|
encoding: "utf8"
|
|
21906
22299
|
}).trim();
|
|
21907
22300
|
const prInfo = fetchPrDiffInfo();
|
|
@@ -22319,14 +22712,14 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
22319
22712
|
}
|
|
22320
22713
|
|
|
22321
22714
|
// src/commands/review/prepareReviewDir.ts
|
|
22322
|
-
import { existsSync as
|
|
22715
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync19, unlinkSync as unlinkSync16, writeFileSync as writeFileSync36 } from "fs";
|
|
22323
22716
|
function clearReviewFiles(paths) {
|
|
22324
22717
|
for (const path71 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
22325
|
-
if (
|
|
22718
|
+
if (existsSync49(path71)) unlinkSync16(path71);
|
|
22326
22719
|
}
|
|
22327
22720
|
}
|
|
22328
22721
|
function prepareReviewDir(paths, requestBody, force) {
|
|
22329
|
-
|
|
22722
|
+
mkdirSync19(paths.reviewDir, { recursive: true });
|
|
22330
22723
|
if (force) clearReviewFiles(paths);
|
|
22331
22724
|
writeFileSync36(paths.requestPath, requestBody);
|
|
22332
22725
|
}
|
|
@@ -22607,7 +23000,7 @@ function printReviewerFailures(results) {
|
|
|
22607
23000
|
}
|
|
22608
23001
|
|
|
22609
23002
|
// src/commands/review/runAndSynthesise.ts
|
|
22610
|
-
import { existsSync as
|
|
23003
|
+
import { existsSync as existsSync51, unlinkSync as unlinkSync18 } from "fs";
|
|
22611
23004
|
|
|
22612
23005
|
// src/commands/review/buildReviewerStdin.ts
|
|
22613
23006
|
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in the request file whose absolute path is given below.
|
|
@@ -23027,7 +23420,7 @@ function resolveClaude(args) {
|
|
|
23027
23420
|
}
|
|
23028
23421
|
|
|
23029
23422
|
// src/commands/review/runCodexReviewer.ts
|
|
23030
|
-
import { existsSync as
|
|
23423
|
+
import { existsSync as existsSync50, unlinkSync as unlinkSync17 } from "fs";
|
|
23031
23424
|
|
|
23032
23425
|
// src/commands/review/parseCodexEvent.ts
|
|
23033
23426
|
function isItemStarted(value) {
|
|
@@ -23079,7 +23472,7 @@ async function runCodexReviewer(spec) {
|
|
|
23079
23472
|
reportReviewerToolUse(spec.name, event, spinner);
|
|
23080
23473
|
}
|
|
23081
23474
|
});
|
|
23082
|
-
if (result.exitCode !== 0 &&
|
|
23475
|
+
if (result.exitCode !== 0 && existsSync50(spec.outputPath)) {
|
|
23083
23476
|
unlinkSync17(spec.outputPath);
|
|
23084
23477
|
}
|
|
23085
23478
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
@@ -23225,7 +23618,7 @@ async function runAndSynthesise(args) {
|
|
|
23225
23618
|
console.error("Both reviewers failed; skipping synthesis.");
|
|
23226
23619
|
return { ok: false, failures };
|
|
23227
23620
|
}
|
|
23228
|
-
if (anyFresh &&
|
|
23621
|
+
if (anyFresh && existsSync51(paths.synthesisPath)) {
|
|
23229
23622
|
unlinkSync18(paths.synthesisPath);
|
|
23230
23623
|
}
|
|
23231
23624
|
const synthesisResult = await synthesise(paths, { multi });
|
|
@@ -23346,20 +23739,13 @@ function validateOptions(options2) {
|
|
|
23346
23739
|
process.exit(1);
|
|
23347
23740
|
}
|
|
23348
23741
|
}
|
|
23349
|
-
function checkoutPr(number) {
|
|
23350
|
-
try {
|
|
23351
|
-
execFileSync9("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
23352
|
-
} catch {
|
|
23353
|
-
console.error(`gh pr checkout ${number} failed; aborting.`);
|
|
23354
|
-
process.exit(1);
|
|
23355
|
-
}
|
|
23356
|
-
}
|
|
23357
23742
|
async function review(options2 = {}) {
|
|
23358
23743
|
validateOptions(options2);
|
|
23359
|
-
const
|
|
23744
|
+
const invokedIn = resolveRepoRoot();
|
|
23360
23745
|
emitActivity({ kind: "command", name: "review" });
|
|
23361
|
-
if (options2.number)
|
|
23362
|
-
await
|
|
23746
|
+
if (!options2.number) return reviewPr(invokedIn, options2);
|
|
23747
|
+
await checkoutPr(options2.number);
|
|
23748
|
+
return reviewPr(resolveRepoRoot(), options2);
|
|
23363
23749
|
}
|
|
23364
23750
|
|
|
23365
23751
|
// src/commands/registerReview.ts
|
|
@@ -24105,27 +24491,27 @@ async function configure() {
|
|
|
24105
24491
|
}
|
|
24106
24492
|
|
|
24107
24493
|
// src/commands/transcript/list.ts
|
|
24108
|
-
import { existsSync as
|
|
24109
|
-
import { join as
|
|
24494
|
+
import { existsSync as existsSync52, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
|
|
24495
|
+
import { join as join59 } from "path";
|
|
24110
24496
|
function list4() {
|
|
24111
24497
|
const { vttDir } = getTranscriptConfig();
|
|
24112
|
-
if (!
|
|
24498
|
+
if (!existsSync52(vttDir)) return;
|
|
24113
24499
|
for (const entry of readdirSync10(vttDir)) {
|
|
24114
24500
|
if (!entry.endsWith(".vtt")) continue;
|
|
24115
|
-
if (statSync8(
|
|
24501
|
+
if (statSync8(join59(vttDir, entry)).isDirectory()) continue;
|
|
24116
24502
|
console.log(entry);
|
|
24117
24503
|
}
|
|
24118
24504
|
}
|
|
24119
24505
|
|
|
24120
24506
|
// src/commands/transcript/move.ts
|
|
24121
24507
|
import {
|
|
24122
|
-
existsSync as
|
|
24123
|
-
mkdirSync as
|
|
24508
|
+
existsSync as existsSync53,
|
|
24509
|
+
mkdirSync as mkdirSync20,
|
|
24124
24510
|
readFileSync as readFileSync42,
|
|
24125
24511
|
renameSync as renameSync2,
|
|
24126
24512
|
writeFileSync as writeFileSync38
|
|
24127
24513
|
} from "fs";
|
|
24128
|
-
import { basename as
|
|
24514
|
+
import { basename as basename15, join as join60 } from "path";
|
|
24129
24515
|
|
|
24130
24516
|
// src/commands/transcript/cleanText.ts
|
|
24131
24517
|
function cleanText(text17) {
|
|
@@ -24338,9 +24724,9 @@ function convertVttToMarkdown(inputPath) {
|
|
|
24338
24724
|
return formatChatLog(messages);
|
|
24339
24725
|
}
|
|
24340
24726
|
function archiveRawVtt(vttDir, sourcePath, filename) {
|
|
24341
|
-
const processedDir =
|
|
24342
|
-
|
|
24343
|
-
renameSync2(sourcePath,
|
|
24727
|
+
const processedDir = join60(vttDir, "processed");
|
|
24728
|
+
mkdirSync20(processedDir, { recursive: true });
|
|
24729
|
+
renameSync2(sourcePath, join60(processedDir, filename));
|
|
24344
24730
|
}
|
|
24345
24731
|
function move(file, options2) {
|
|
24346
24732
|
const { date, client } = options2;
|
|
@@ -24349,20 +24735,20 @@ function move(file, options2) {
|
|
|
24349
24735
|
process.exit(1);
|
|
24350
24736
|
}
|
|
24351
24737
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
24352
|
-
const filename =
|
|
24353
|
-
const sourcePath =
|
|
24354
|
-
if (!
|
|
24738
|
+
const filename = basename15(file);
|
|
24739
|
+
const sourcePath = join60(vttDir, filename);
|
|
24740
|
+
if (!existsSync53(sourcePath)) {
|
|
24355
24741
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
24356
24742
|
process.exit(1);
|
|
24357
24743
|
}
|
|
24358
|
-
const base =
|
|
24744
|
+
const base = basename15(filename, ".vtt").replace(/ Transcription$/, "");
|
|
24359
24745
|
const outputName = `${date} ${base}.md`;
|
|
24360
|
-
const formattedDir =
|
|
24361
|
-
|
|
24362
|
-
const formattedPath =
|
|
24746
|
+
const formattedDir = join60(transcriptsDir, client);
|
|
24747
|
+
mkdirSync20(formattedDir, { recursive: true });
|
|
24748
|
+
const formattedPath = join60(formattedDir, outputName);
|
|
24363
24749
|
writeFileSync38(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
24364
24750
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
24365
|
-
const summaryPath =
|
|
24751
|
+
const summaryPath = join60(summaryDir, client, outputName);
|
|
24366
24752
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
24367
24753
|
console.log(`Summary target: ${summaryPath}`);
|
|
24368
24754
|
}
|
|
@@ -24482,45 +24868,45 @@ function registerVerify(program2) {
|
|
|
24482
24868
|
|
|
24483
24869
|
// src/commands/voice/devices.ts
|
|
24484
24870
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
24485
|
-
import { join as
|
|
24871
|
+
import { join as join62 } from "path";
|
|
24486
24872
|
|
|
24487
24873
|
// src/commands/voice/shared.ts
|
|
24488
24874
|
import { homedir as homedir21 } from "os";
|
|
24489
|
-
import { dirname as
|
|
24875
|
+
import { dirname as dirname28, join as join61 } from "path";
|
|
24490
24876
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
24491
|
-
var __dirname5 =
|
|
24492
|
-
var VOICE_DIR =
|
|
24877
|
+
var __dirname5 = dirname28(fileURLToPath7(import.meta.url));
|
|
24878
|
+
var VOICE_DIR = join61(homedir21(), ".assist", "voice");
|
|
24493
24879
|
var voicePaths = {
|
|
24494
24880
|
dir: VOICE_DIR,
|
|
24495
|
-
pid:
|
|
24496
|
-
log:
|
|
24497
|
-
venv:
|
|
24498
|
-
lock:
|
|
24881
|
+
pid: join61(VOICE_DIR, "voice.pid"),
|
|
24882
|
+
log: join61(VOICE_DIR, "voice.log"),
|
|
24883
|
+
venv: join61(VOICE_DIR, ".venv"),
|
|
24884
|
+
lock: join61(VOICE_DIR, "voice.lock")
|
|
24499
24885
|
};
|
|
24500
24886
|
function getPythonDir() {
|
|
24501
|
-
return
|
|
24887
|
+
return join61(__dirname5, "commands", "voice", "python");
|
|
24502
24888
|
}
|
|
24503
24889
|
function getVenvPython() {
|
|
24504
|
-
return process.platform === "win32" ?
|
|
24890
|
+
return process.platform === "win32" ? join61(voicePaths.venv, "Scripts", "python.exe") : join61(voicePaths.venv, "bin", "python");
|
|
24505
24891
|
}
|
|
24506
24892
|
function getLockDir() {
|
|
24507
24893
|
const config = loadConfig();
|
|
24508
24894
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
24509
24895
|
}
|
|
24510
24896
|
function getLockFile() {
|
|
24511
|
-
return
|
|
24897
|
+
return join61(getLockDir(), "voice.lock");
|
|
24512
24898
|
}
|
|
24513
24899
|
|
|
24514
24900
|
// src/commands/voice/devices.ts
|
|
24515
24901
|
function devices() {
|
|
24516
|
-
const script =
|
|
24902
|
+
const script = join62(getPythonDir(), "list_devices.py");
|
|
24517
24903
|
spawnSync6(getVenvPython(), [script], { stdio: "inherit" });
|
|
24518
24904
|
}
|
|
24519
24905
|
|
|
24520
24906
|
// src/commands/voice/logs.ts
|
|
24521
|
-
import { existsSync as
|
|
24907
|
+
import { existsSync as existsSync54, readFileSync as readFileSync43 } from "fs";
|
|
24522
24908
|
function logs(options2) {
|
|
24523
|
-
if (!
|
|
24909
|
+
if (!existsSync54(voicePaths.log)) {
|
|
24524
24910
|
console.log("No voice log file found");
|
|
24525
24911
|
return;
|
|
24526
24912
|
}
|
|
@@ -24547,13 +24933,13 @@ function logs(options2) {
|
|
|
24547
24933
|
|
|
24548
24934
|
// src/commands/voice/setup.ts
|
|
24549
24935
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
24550
|
-
import { mkdirSync as
|
|
24551
|
-
import { join as
|
|
24936
|
+
import { mkdirSync as mkdirSync22 } from "fs";
|
|
24937
|
+
import { join as join64 } from "path";
|
|
24552
24938
|
|
|
24553
24939
|
// src/commands/voice/checkLockFile.ts
|
|
24554
|
-
import { execSync as
|
|
24555
|
-
import { existsSync as
|
|
24556
|
-
import { join as
|
|
24940
|
+
import { execSync as execSync57 } from "child_process";
|
|
24941
|
+
import { existsSync as existsSync55, mkdirSync as mkdirSync21, readFileSync as readFileSync44, writeFileSync as writeFileSync39 } from "fs";
|
|
24942
|
+
import { join as join63 } from "path";
|
|
24557
24943
|
function isProcessAlive2(pid) {
|
|
24558
24944
|
try {
|
|
24559
24945
|
process.kill(pid, 0);
|
|
@@ -24564,7 +24950,7 @@ function isProcessAlive2(pid) {
|
|
|
24564
24950
|
}
|
|
24565
24951
|
function checkLockFile() {
|
|
24566
24952
|
const lockFile = getLockFile();
|
|
24567
|
-
if (!
|
|
24953
|
+
if (!existsSync55(lockFile)) return;
|
|
24568
24954
|
try {
|
|
24569
24955
|
const lock2 = JSON.parse(readFileSync44(lockFile, "utf8"));
|
|
24570
24956
|
if (lock2.pid && isProcessAlive2(lock2.pid)) {
|
|
@@ -24577,10 +24963,10 @@ function checkLockFile() {
|
|
|
24577
24963
|
}
|
|
24578
24964
|
}
|
|
24579
24965
|
function bootstrapVenv() {
|
|
24580
|
-
if (
|
|
24966
|
+
if (existsSync55(getVenvPython())) return;
|
|
24581
24967
|
console.log("Setting up Python environment...");
|
|
24582
24968
|
const pythonDir = getPythonDir();
|
|
24583
|
-
|
|
24969
|
+
execSync57(
|
|
24584
24970
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
24585
24971
|
{
|
|
24586
24972
|
stdio: "inherit",
|
|
@@ -24590,7 +24976,7 @@ function bootstrapVenv() {
|
|
|
24590
24976
|
}
|
|
24591
24977
|
function writeLockFile(pid) {
|
|
24592
24978
|
const lockFile = getLockFile();
|
|
24593
|
-
|
|
24979
|
+
mkdirSync21(join63(lockFile, ".."), { recursive: true });
|
|
24594
24980
|
writeFileSync39(
|
|
24595
24981
|
lockFile,
|
|
24596
24982
|
JSON.stringify({
|
|
@@ -24603,10 +24989,10 @@ function writeLockFile(pid) {
|
|
|
24603
24989
|
|
|
24604
24990
|
// src/commands/voice/setup.ts
|
|
24605
24991
|
function setup() {
|
|
24606
|
-
|
|
24992
|
+
mkdirSync22(voicePaths.dir, { recursive: true });
|
|
24607
24993
|
bootstrapVenv();
|
|
24608
24994
|
console.log("\nDownloading models...\n");
|
|
24609
|
-
const script =
|
|
24995
|
+
const script = join64(getPythonDir(), "setup_models.py");
|
|
24610
24996
|
const result = spawnSync7(getVenvPython(), [script], {
|
|
24611
24997
|
stdio: "inherit",
|
|
24612
24998
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -24619,8 +25005,8 @@ function setup() {
|
|
|
24619
25005
|
|
|
24620
25006
|
// src/commands/voice/start.ts
|
|
24621
25007
|
import { spawn as spawn7 } from "child_process";
|
|
24622
|
-
import { mkdirSync as
|
|
24623
|
-
import { join as
|
|
25008
|
+
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync40 } from "fs";
|
|
25009
|
+
import { join as join65 } from "path";
|
|
24624
25010
|
|
|
24625
25011
|
// src/commands/voice/buildDaemonEnv.ts
|
|
24626
25012
|
function buildDaemonEnv(options2) {
|
|
@@ -24653,12 +25039,12 @@ function spawnBackground(python, script, env) {
|
|
|
24653
25039
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
24654
25040
|
}
|
|
24655
25041
|
function start2(options2) {
|
|
24656
|
-
|
|
25042
|
+
mkdirSync23(voicePaths.dir, { recursive: true });
|
|
24657
25043
|
checkLockFile();
|
|
24658
25044
|
bootstrapVenv();
|
|
24659
25045
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
24660
25046
|
const env = buildDaemonEnv({ debug });
|
|
24661
|
-
const script =
|
|
25047
|
+
const script = join65(getPythonDir(), "voice_daemon.py");
|
|
24662
25048
|
const python = getVenvPython();
|
|
24663
25049
|
if (options2.foreground) {
|
|
24664
25050
|
spawnForeground(python, script, env);
|
|
@@ -24668,7 +25054,7 @@ function start2(options2) {
|
|
|
24668
25054
|
}
|
|
24669
25055
|
|
|
24670
25056
|
// src/commands/voice/status.ts
|
|
24671
|
-
import { existsSync as
|
|
25057
|
+
import { existsSync as existsSync56, readFileSync as readFileSync45 } from "fs";
|
|
24672
25058
|
function isProcessAlive3(pid) {
|
|
24673
25059
|
try {
|
|
24674
25060
|
process.kill(pid, 0);
|
|
@@ -24678,12 +25064,12 @@ function isProcessAlive3(pid) {
|
|
|
24678
25064
|
}
|
|
24679
25065
|
}
|
|
24680
25066
|
function readRecentLogs(count7) {
|
|
24681
|
-
if (!
|
|
25067
|
+
if (!existsSync56(voicePaths.log)) return [];
|
|
24682
25068
|
const lines = readFileSync45(voicePaths.log, "utf8").trim().split("\n");
|
|
24683
25069
|
return lines.slice(-count7);
|
|
24684
25070
|
}
|
|
24685
25071
|
function status2() {
|
|
24686
|
-
if (!
|
|
25072
|
+
if (!existsSync56(voicePaths.pid)) {
|
|
24687
25073
|
console.log("Voice daemon: not running (no PID file)");
|
|
24688
25074
|
return;
|
|
24689
25075
|
}
|
|
@@ -24706,9 +25092,9 @@ function status2() {
|
|
|
24706
25092
|
}
|
|
24707
25093
|
|
|
24708
25094
|
// src/commands/voice/stop.ts
|
|
24709
|
-
import { existsSync as
|
|
25095
|
+
import { existsSync as existsSync57, readFileSync as readFileSync46, unlinkSync as unlinkSync19 } from "fs";
|
|
24710
25096
|
function stop2() {
|
|
24711
|
-
if (!
|
|
25097
|
+
if (!existsSync57(voicePaths.pid)) {
|
|
24712
25098
|
console.log("Voice daemon is not running (no PID file)");
|
|
24713
25099
|
return;
|
|
24714
25100
|
}
|
|
@@ -24725,7 +25111,7 @@ function stop2() {
|
|
|
24725
25111
|
}
|
|
24726
25112
|
try {
|
|
24727
25113
|
const lockFile = getLockFile();
|
|
24728
|
-
if (
|
|
25114
|
+
if (existsSync57(lockFile)) unlinkSync19(lockFile);
|
|
24729
25115
|
} catch {
|
|
24730
25116
|
}
|
|
24731
25117
|
console.log("Voice daemon stopped");
|
|
@@ -24947,9 +25333,9 @@ async function auth() {
|
|
|
24947
25333
|
}
|
|
24948
25334
|
|
|
24949
25335
|
// src/commands/roam/postRoamActivity.ts
|
|
24950
|
-
import { execFileSync as
|
|
25336
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
24951
25337
|
import { readdirSync as readdirSync11, readFileSync as readFileSync47, statSync as statSync9 } from "fs";
|
|
24952
|
-
import { join as
|
|
25338
|
+
import { join as join66 } from "path";
|
|
24953
25339
|
function findPortFile(roamDir) {
|
|
24954
25340
|
let entries;
|
|
24955
25341
|
try {
|
|
@@ -24958,7 +25344,7 @@ function findPortFile(roamDir) {
|
|
|
24958
25344
|
return void 0;
|
|
24959
25345
|
}
|
|
24960
25346
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
24961
|
-
const path71 =
|
|
25347
|
+
const path71 = join66(roamDir, name);
|
|
24962
25348
|
try {
|
|
24963
25349
|
return { path: path71, mtimeMs: statSync9(path71).mtimeMs };
|
|
24964
25350
|
} catch {
|
|
@@ -24970,7 +25356,7 @@ function findPortFile(roamDir) {
|
|
|
24970
25356
|
function postRoamActivity(app, event) {
|
|
24971
25357
|
const appData = process.env.APPDATA;
|
|
24972
25358
|
if (!appData) return;
|
|
24973
|
-
const portFile = findPortFile(
|
|
25359
|
+
const portFile = findPortFile(join66(appData, "Roam"));
|
|
24974
25360
|
if (!portFile) return;
|
|
24975
25361
|
let port;
|
|
24976
25362
|
try {
|
|
@@ -24980,7 +25366,7 @@ function postRoamActivity(app, event) {
|
|
|
24980
25366
|
}
|
|
24981
25367
|
const url = `http://127.0.0.1:${port}/api/v1/activity/${app}/${event}?pid=${app === "codex" ? 99998 : 99999}`;
|
|
24982
25368
|
try {
|
|
24983
|
-
|
|
25369
|
+
execFileSync9("curl", ["-sf", "--max-time", "0.2", "-X", "POST", url], {
|
|
24984
25370
|
stdio: "ignore"
|
|
24985
25371
|
});
|
|
24986
25372
|
} catch {
|
|
@@ -25188,11 +25574,11 @@ function resolveParams(params, cliArgs) {
|
|
|
25188
25574
|
}
|
|
25189
25575
|
|
|
25190
25576
|
// src/commands/run/runPreCommands.ts
|
|
25191
|
-
import { execSync as
|
|
25577
|
+
import { execSync as execSync58 } from "child_process";
|
|
25192
25578
|
function runPreCommands(pre, cwd) {
|
|
25193
25579
|
for (const cmd of pre) {
|
|
25194
25580
|
try {
|
|
25195
|
-
|
|
25581
|
+
execSync58(cmd, { stdio: "inherit", cwd });
|
|
25196
25582
|
} catch (error) {
|
|
25197
25583
|
const code = error && typeof error === "object" && "status" in error ? error.status : 1;
|
|
25198
25584
|
process.exit(code);
|
|
@@ -25201,16 +25587,16 @@ function runPreCommands(pre, cwd) {
|
|
|
25201
25587
|
}
|
|
25202
25588
|
|
|
25203
25589
|
// src/commands/run/spawnRunCommand.ts
|
|
25204
|
-
import { execFileSync as
|
|
25205
|
-
import { existsSync as
|
|
25206
|
-
import { dirname as
|
|
25590
|
+
import { execFileSync as execFileSync10, spawn as spawn8 } from "child_process";
|
|
25591
|
+
import { existsSync as existsSync58 } from "fs";
|
|
25592
|
+
import { dirname as dirname29, join as join67, resolve as resolve15 } from "path";
|
|
25207
25593
|
function resolveCommand2(command) {
|
|
25208
25594
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
25209
25595
|
try {
|
|
25210
|
-
const gitPath =
|
|
25211
|
-
const gitRoot = resolve15(
|
|
25212
|
-
const gitBash =
|
|
25213
|
-
if (
|
|
25596
|
+
const gitPath = execFileSync10("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
25597
|
+
const gitRoot = resolve15(dirname29(gitPath), "..");
|
|
25598
|
+
const gitBash = join67(gitRoot, "bin", "bash.exe");
|
|
25599
|
+
if (existsSync58(gitBash)) return gitBash;
|
|
25214
25600
|
} catch {
|
|
25215
25601
|
}
|
|
25216
25602
|
return command;
|
|
@@ -25297,8 +25683,8 @@ async function run3(name, args) {
|
|
|
25297
25683
|
}
|
|
25298
25684
|
|
|
25299
25685
|
// src/commands/run/add.ts
|
|
25300
|
-
import { mkdirSync as
|
|
25301
|
-
import { join as
|
|
25686
|
+
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync41 } from "fs";
|
|
25687
|
+
import { join as join68 } from "path";
|
|
25302
25688
|
|
|
25303
25689
|
// src/commands/run/extractOption.ts
|
|
25304
25690
|
function extractOption(args, flag) {
|
|
@@ -25359,15 +25745,15 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
25359
25745
|
saveConfig(config);
|
|
25360
25746
|
}
|
|
25361
25747
|
function createCommandFile(name) {
|
|
25362
|
-
const dir =
|
|
25363
|
-
|
|
25748
|
+
const dir = join68(".claude", "commands");
|
|
25749
|
+
mkdirSync24(dir, { recursive: true });
|
|
25364
25750
|
const content = `---
|
|
25365
25751
|
description: Run ${name}
|
|
25366
25752
|
---
|
|
25367
25753
|
|
|
25368
25754
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
25369
25755
|
`;
|
|
25370
|
-
const filePath =
|
|
25756
|
+
const filePath = join68(dir, `${name}.md`);
|
|
25371
25757
|
writeFileSync41(filePath, content);
|
|
25372
25758
|
console.log(`Created command file: ${filePath}`);
|
|
25373
25759
|
}
|
|
@@ -25423,8 +25809,8 @@ function link2() {
|
|
|
25423
25809
|
}
|
|
25424
25810
|
|
|
25425
25811
|
// src/commands/run/remove.ts
|
|
25426
|
-
import { existsSync as
|
|
25427
|
-
import { join as
|
|
25812
|
+
import { existsSync as existsSync59, unlinkSync as unlinkSync20 } from "fs";
|
|
25813
|
+
import { join as join69 } from "path";
|
|
25428
25814
|
function findRemoveIndex() {
|
|
25429
25815
|
const idx = process.argv.indexOf("remove");
|
|
25430
25816
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -25439,8 +25825,8 @@ function parseRemoveName() {
|
|
|
25439
25825
|
return process.argv[idx + 1];
|
|
25440
25826
|
}
|
|
25441
25827
|
function deleteCommandFile(name) {
|
|
25442
|
-
const filePath =
|
|
25443
|
-
if (
|
|
25828
|
+
const filePath = join69(".claude", "commands", `${name}.md`);
|
|
25829
|
+
if (existsSync59(filePath)) {
|
|
25444
25830
|
unlinkSync20(filePath);
|
|
25445
25831
|
console.log(`Deleted command file: ${filePath}`);
|
|
25446
25832
|
}
|
|
@@ -25493,10 +25879,10 @@ function registerRun(program2) {
|
|
|
25493
25879
|
}
|
|
25494
25880
|
|
|
25495
25881
|
// src/commands/screenshot/index.ts
|
|
25496
|
-
import { execSync as
|
|
25497
|
-
import { existsSync as
|
|
25882
|
+
import { execSync as execSync59 } from "child_process";
|
|
25883
|
+
import { existsSync as existsSync60, mkdirSync as mkdirSync25, unlinkSync as unlinkSync21, writeFileSync as writeFileSync42 } from "fs";
|
|
25498
25884
|
import { tmpdir as tmpdir8 } from "os";
|
|
25499
|
-
import { join as
|
|
25885
|
+
import { join as join70, resolve as resolve17 } from "path";
|
|
25500
25886
|
import chalk206 from "chalk";
|
|
25501
25887
|
|
|
25502
25888
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -25626,17 +26012,17 @@ Write-Output $OutputPath
|
|
|
25626
26012
|
|
|
25627
26013
|
// src/commands/screenshot/index.ts
|
|
25628
26014
|
function buildOutputPath(outputDir, processName) {
|
|
25629
|
-
if (!
|
|
25630
|
-
|
|
26015
|
+
if (!existsSync60(outputDir)) {
|
|
26016
|
+
mkdirSync25(outputDir, { recursive: true });
|
|
25631
26017
|
}
|
|
25632
26018
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
25633
26019
|
return resolve17(outputDir, `${processName}-${timestamp6}.png`);
|
|
25634
26020
|
}
|
|
25635
26021
|
function runPowerShellScript(processName, outputPath) {
|
|
25636
|
-
const scriptPath =
|
|
26022
|
+
const scriptPath = join70(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
|
|
25637
26023
|
writeFileSync42(scriptPath, captureWindowPs1, "utf8");
|
|
25638
26024
|
try {
|
|
25639
|
-
|
|
26025
|
+
execSync59(
|
|
25640
26026
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
25641
26027
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
|
|
25642
26028
|
);
|
|
@@ -25660,11 +26046,11 @@ function screenshot(processName) {
|
|
|
25660
26046
|
}
|
|
25661
26047
|
|
|
25662
26048
|
// src/commands/sessions/daemon/listDaemonPids.ts
|
|
25663
|
-
import { execFileSync as
|
|
26049
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
25664
26050
|
function listDaemonPids() {
|
|
25665
26051
|
if (process.platform === "win32") return [];
|
|
25666
26052
|
try {
|
|
25667
|
-
const out =
|
|
26053
|
+
const out = execFileSync11("ps", ["-eo", "pid=,args="], {
|
|
25668
26054
|
encoding: "utf8"
|
|
25669
26055
|
});
|
|
25670
26056
|
return out.split("\n").filter((line) => line.includes("assist") && / daemon run\b/.test(line)).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid));
|
|
@@ -25705,167 +26091,66 @@ function applyLine(result, pending, line) {
|
|
|
25705
26091
|
result.pid = data.pid;
|
|
25706
26092
|
pending.delete("pong");
|
|
25707
26093
|
}
|
|
25708
|
-
} catch {
|
|
25709
|
-
}
|
|
25710
|
-
}
|
|
25711
|
-
|
|
25712
|
-
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
25713
|
-
import { readFileSync as readFileSync48 } from "fs";
|
|
25714
|
-
function reportStolenSocket(socketPid) {
|
|
25715
|
-
if (!socketPid) return;
|
|
25716
|
-
const filePid = readPidFile();
|
|
25717
|
-
if (filePid === void 0 || filePid === socketPid) return;
|
|
25718
|
-
console.error(
|
|
25719
|
-
`Warning: daemon.pid records PID ${filePid} but the socket is owned by PID ${socketPid} (stolen socket)`
|
|
25720
|
-
);
|
|
25721
|
-
}
|
|
25722
|
-
function readPidFile() {
|
|
25723
|
-
try {
|
|
25724
|
-
const pid = Number.parseInt(
|
|
25725
|
-
readFileSync48(daemonPaths.pid, "utf8").trim(),
|
|
25726
|
-
10
|
|
25727
|
-
);
|
|
25728
|
-
return Number.isInteger(pid) ? pid : void 0;
|
|
25729
|
-
} catch {
|
|
25730
|
-
return void 0;
|
|
25731
|
-
}
|
|
25732
|
-
}
|
|
25733
|
-
|
|
25734
|
-
// src/commands/sessions/daemon/daemonStatus.ts
|
|
25735
|
-
async function daemonStatus() {
|
|
25736
|
-
let socket;
|
|
25737
|
-
try {
|
|
25738
|
-
socket = await connectToDaemon();
|
|
25739
|
-
} catch {
|
|
25740
|
-
console.log("Sessions daemon is not running");
|
|
25741
|
-
reportStrays(listDaemonPids());
|
|
25742
|
-
return;
|
|
25743
|
-
}
|
|
25744
|
-
const { pid, sessions } = await queryDaemon(socket);
|
|
25745
|
-
socket.destroy();
|
|
25746
|
-
console.log(`Sessions daemon is running${pid ? ` (PID ${pid})` : ""}`);
|
|
25747
|
-
reportStolenSocket(pid);
|
|
25748
|
-
reportStrays(listDaemonPids().filter((p) => p !== pid));
|
|
25749
|
-
if (sessions.length === 0) {
|
|
25750
|
-
console.log("No sessions");
|
|
25751
|
-
return;
|
|
25752
|
-
}
|
|
25753
|
-
for (const session of sessions) {
|
|
25754
|
-
const restored = session.restored === false ? " (not restored)" : "";
|
|
25755
|
-
console.log(` [${session.status}] ${session.name}${restored}`);
|
|
25756
|
-
}
|
|
25757
|
-
}
|
|
25758
|
-
function reportStrays(pids) {
|
|
25759
|
-
if (pids.length === 0) return;
|
|
25760
|
-
console.error(
|
|
25761
|
-
`Warning: stray daemon process(es) detected: ${pids.join(", ")}`
|
|
25762
|
-
);
|
|
25763
|
-
}
|
|
25764
|
-
|
|
25765
|
-
// src/commands/sessions/daemon/drainDaemon.ts
|
|
25766
|
-
import { createInterface as createInterface6 } from "readline";
|
|
25767
|
-
|
|
25768
|
-
// src/commands/sessions/daemon/daemonLog.ts
|
|
25769
|
-
var RING_CAPACITY = 1e3;
|
|
25770
|
-
var ring = [];
|
|
25771
|
-
var sink;
|
|
25772
|
-
function daemonLog(message2) {
|
|
25773
|
-
emit3(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message2}`);
|
|
25774
|
-
}
|
|
25775
|
-
function relayDaemonLog(line) {
|
|
25776
|
-
emit3(`[windows] ${line}`);
|
|
25777
|
-
}
|
|
25778
|
-
function emit3(line) {
|
|
25779
|
-
console.log(line);
|
|
25780
|
-
ring.push(line);
|
|
25781
|
-
if (ring.length > RING_CAPACITY) ring.shift();
|
|
25782
|
-
sink?.(line);
|
|
25783
|
-
}
|
|
25784
|
-
function setDaemonLogSink(next3) {
|
|
25785
|
-
sink = next3;
|
|
25786
|
-
}
|
|
25787
|
-
function recentDaemonLogLines() {
|
|
25788
|
-
return [...ring];
|
|
25789
|
-
}
|
|
25790
|
-
|
|
25791
|
-
// src/commands/sessions/daemon/persistedSessionSchema.ts
|
|
25792
|
-
import { z as z6 } from "zod";
|
|
25793
|
-
var persistedSessionSchema = z6.object({
|
|
25794
|
-
name: z6.string(),
|
|
25795
|
-
title: z6.string().optional(),
|
|
25796
|
-
subtitle: z6.string().optional(),
|
|
25797
|
-
commandType: z6.enum(["claude", "run", "assist"]),
|
|
25798
|
-
harness: z6.enum(["claude", "codex", "pi"]).optional(),
|
|
25799
|
-
status: z6.enum(["running", "waiting", "done", "error", "stopped"]).optional(),
|
|
25800
|
-
cwd: z6.string(),
|
|
25801
|
-
startedAt: z6.number(),
|
|
25802
|
-
runningMs: z6.number().optional(),
|
|
25803
|
-
claudeSessionId: z6.string().optional(),
|
|
25804
|
-
initialPrompt: z6.string().optional(),
|
|
25805
|
-
runName: z6.string().optional(),
|
|
25806
|
-
runArgs: z6.array(z6.string()).optional(),
|
|
25807
|
-
assistArgs: z6.array(z6.string()).optional(),
|
|
25808
|
-
activity: activitySchema.optional(),
|
|
25809
|
-
starred: z6.boolean().optional(),
|
|
25810
|
-
undurable: z6.object({ reason: z6.string(), removesTree: z6.boolean().optional() }).optional()
|
|
25811
|
-
});
|
|
25812
|
-
|
|
25813
|
-
// src/commands/sessions/daemon/toPersistedSession.ts
|
|
25814
|
-
function toPersistedSession(session) {
|
|
25815
|
-
return {
|
|
25816
|
-
name: session.name,
|
|
25817
|
-
title: session.title,
|
|
25818
|
-
subtitle: session.subtitle,
|
|
25819
|
-
commandType: session.commandType,
|
|
25820
|
-
harness: session.harness,
|
|
25821
|
-
status: session.status,
|
|
25822
|
-
cwd: session.cwd ?? process.cwd(),
|
|
25823
|
-
startedAt: session.startedAt,
|
|
25824
|
-
runningMs: accumulatedRunningMs(session),
|
|
25825
|
-
claudeSessionId: session.claudeSessionId,
|
|
25826
|
-
initialPrompt: session.initialPrompt,
|
|
25827
|
-
runName: session.runName,
|
|
25828
|
-
runArgs: session.runArgs,
|
|
25829
|
-
assistArgs: session.assistArgs,
|
|
25830
|
-
activity: session.activity,
|
|
25831
|
-
starred: session.starred,
|
|
25832
|
-
undurable: session.undurable
|
|
25833
|
-
};
|
|
25834
|
-
}
|
|
25835
|
-
function accumulatedRunningMs(session) {
|
|
25836
|
-
return session.runningSince != null ? session.runningMs + Date.now() - session.runningSince : session.runningMs;
|
|
26094
|
+
} catch {
|
|
26095
|
+
}
|
|
25837
26096
|
}
|
|
25838
26097
|
|
|
25839
|
-
// src/commands/sessions/daemon/
|
|
25840
|
-
|
|
25841
|
-
function
|
|
25842
|
-
|
|
25843
|
-
|
|
25844
|
-
|
|
25845
|
-
|
|
25846
|
-
|
|
25847
|
-
|
|
26098
|
+
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
26099
|
+
import { readFileSync as readFileSync48 } from "fs";
|
|
26100
|
+
function reportStolenSocket(socketPid) {
|
|
26101
|
+
if (!socketPid) return;
|
|
26102
|
+
const filePid = readPidFile();
|
|
26103
|
+
if (filePid === void 0 || filePid === socketPid) return;
|
|
26104
|
+
console.error(
|
|
26105
|
+
`Warning: daemon.pid records PID ${filePid} but the socket is owned by PID ${socketPid} (stolen socket)`
|
|
26106
|
+
);
|
|
25848
26107
|
}
|
|
25849
|
-
function
|
|
25850
|
-
|
|
26108
|
+
function readPidFile() {
|
|
26109
|
+
try {
|
|
26110
|
+
const pid = Number.parseInt(
|
|
26111
|
+
readFileSync48(daemonPaths.pid, "utf8").trim(),
|
|
26112
|
+
10
|
|
26113
|
+
);
|
|
26114
|
+
return Number.isInteger(pid) ? pid : void 0;
|
|
26115
|
+
} catch {
|
|
26116
|
+
return void 0;
|
|
26117
|
+
}
|
|
25851
26118
|
}
|
|
25852
|
-
|
|
25853
|
-
|
|
25854
|
-
|
|
25855
|
-
|
|
25856
|
-
|
|
25857
|
-
|
|
26119
|
+
|
|
26120
|
+
// src/commands/sessions/daemon/daemonStatus.ts
|
|
26121
|
+
async function daemonStatus() {
|
|
26122
|
+
let socket;
|
|
26123
|
+
try {
|
|
26124
|
+
socket = await connectToDaemon();
|
|
26125
|
+
} catch {
|
|
26126
|
+
console.log("Sessions daemon is not running");
|
|
26127
|
+
reportStrays(listDaemonPids());
|
|
26128
|
+
return;
|
|
26129
|
+
}
|
|
26130
|
+
const { pid, sessions } = await queryDaemon(socket);
|
|
26131
|
+
socket.destroy();
|
|
26132
|
+
console.log(`Sessions daemon is running${pid ? ` (PID ${pid})` : ""}`);
|
|
26133
|
+
reportStolenSocket(pid);
|
|
26134
|
+
reportStrays(listDaemonPids().filter((p) => p !== pid));
|
|
26135
|
+
if (sessions.length === 0) {
|
|
26136
|
+
console.log("No sessions");
|
|
26137
|
+
return;
|
|
26138
|
+
}
|
|
26139
|
+
for (const session of sessions) {
|
|
26140
|
+
const restored = session.restored === false ? " (not restored)" : "";
|
|
26141
|
+
console.log(` [${session.status}] ${session.name}${restored}`);
|
|
26142
|
+
}
|
|
25858
26143
|
}
|
|
25859
|
-
|
|
25860
|
-
|
|
25861
|
-
|
|
25862
|
-
|
|
25863
|
-
lastPersistSignature = signature;
|
|
25864
|
-
daemonLog(
|
|
25865
|
-
live.length > 0 ? `persisted ${live.length} session(s): ${live.map((s) => s.name).join(", ")}` : "persisted 0 sessions (sessions.json cleared)"
|
|
26144
|
+
function reportStrays(pids) {
|
|
26145
|
+
if (pids.length === 0) return;
|
|
26146
|
+
console.error(
|
|
26147
|
+
`Warning: stray daemon process(es) detected: ${pids.join(", ")}`
|
|
25866
26148
|
);
|
|
25867
26149
|
}
|
|
25868
26150
|
|
|
26151
|
+
// src/commands/sessions/daemon/drainDaemon.ts
|
|
26152
|
+
import { createInterface as createInterface6 } from "readline";
|
|
26153
|
+
|
|
25869
26154
|
// src/commands/sessions/daemon/clearPersistedSessionsOnDrain.ts
|
|
25870
26155
|
function clearPersistedSessionsOnDrain() {
|
|
25871
26156
|
const held = loadPersistedSessions().filter((s) => s.status === "stopped");
|
|
@@ -26213,7 +26498,7 @@ function readDesignSystemPrompt() {
|
|
|
26213
26498
|
import * as pty from "node-pty";
|
|
26214
26499
|
|
|
26215
26500
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
26216
|
-
import { chmodSync, existsSync as
|
|
26501
|
+
import { chmodSync, existsSync as existsSync61, statSync as statSync10 } from "fs";
|
|
26217
26502
|
import { createRequire as createRequire3 } from "module";
|
|
26218
26503
|
import path59 from "path";
|
|
26219
26504
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -26228,7 +26513,7 @@ function ensureSpawnHelperExecutable() {
|
|
|
26228
26513
|
`${process.platform}-${process.arch}`,
|
|
26229
26514
|
"spawn-helper"
|
|
26230
26515
|
);
|
|
26231
|
-
if (!
|
|
26516
|
+
if (!existsSync61(helper)) return;
|
|
26232
26517
|
const mode = statSync10(helper).mode;
|
|
26233
26518
|
if ((mode & 73) === 0) chmodSync(helper, mode | 493);
|
|
26234
26519
|
}
|
|
@@ -26387,7 +26672,8 @@ function otherTreeHolders(sessions, session) {
|
|
|
26387
26672
|
}
|
|
26388
26673
|
|
|
26389
26674
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
26390
|
-
import { existsSync as
|
|
26675
|
+
import { existsSync as existsSync62 } from "fs";
|
|
26676
|
+
import { basename as basename16 } from "path";
|
|
26391
26677
|
|
|
26392
26678
|
// src/commands/sessions/daemon/worktree/removeTree.ts
|
|
26393
26679
|
async function removeTree(clone, worktreePath, force) {
|
|
@@ -26424,63 +26710,9 @@ function reason(error) {
|
|
|
26424
26710
|
return error instanceof Error ? error.message : String(error);
|
|
26425
26711
|
}
|
|
26426
26712
|
|
|
26427
|
-
// src/commands/sessions/daemon/worktree/treeDurability.ts
|
|
26428
|
-
import { existsSync as existsSync58 } from "fs";
|
|
26429
|
-
function treeDurability(state) {
|
|
26430
|
-
if (state.dirty) return { durable: false, reason: "uncommitted changes" };
|
|
26431
|
-
if (!state.push && state.localOnlyCommits)
|
|
26432
|
-
return { durable: false, reason: "unpushed commits" };
|
|
26433
|
-
return { durable: true };
|
|
26434
|
-
}
|
|
26435
|
-
function* durabilityProbes(cwd) {
|
|
26436
|
-
const status3 = yield ["status", "--porcelain"];
|
|
26437
|
-
if (!status3.ok)
|
|
26438
|
-
return { durable: false, reason: `tree state unreadable: ${status3.error}` };
|
|
26439
|
-
const upstream = yield [
|
|
26440
|
-
"rev-parse",
|
|
26441
|
-
"--abbrev-ref",
|
|
26442
|
-
"--symbolic-full-name",
|
|
26443
|
-
"@{upstream}"
|
|
26444
|
-
];
|
|
26445
|
-
let localOnlyCommits;
|
|
26446
|
-
if (upstream.ok && upstream.out) {
|
|
26447
|
-
const ahead = yield ["rev-list", "--count", "@{upstream}..HEAD"];
|
|
26448
|
-
localOnlyCommits = !ahead.ok || Number(ahead.out) > 0;
|
|
26449
|
-
} else {
|
|
26450
|
-
const remoteBranches = yield ["branch", "-r", "--contains", "HEAD"];
|
|
26451
|
-
localOnlyCommits = !remoteBranches.ok || remoteBranches.out === "";
|
|
26452
|
-
}
|
|
26453
|
-
return treeDurability({
|
|
26454
|
-
dirty: status3.out !== "",
|
|
26455
|
-
push: pushOnCommit(cwd),
|
|
26456
|
-
localOnlyCommits
|
|
26457
|
-
});
|
|
26458
|
-
}
|
|
26459
|
-
function pushOnCommit(cwd) {
|
|
26460
|
-
try {
|
|
26461
|
-
return loadConfigFrom(cwd).commit.push;
|
|
26462
|
-
} catch {
|
|
26463
|
-
return false;
|
|
26464
|
-
}
|
|
26465
|
-
}
|
|
26466
|
-
async function checkDurability(cwd) {
|
|
26467
|
-
if (!existsSync58(cwd)) return { durable: true };
|
|
26468
|
-
const probes = durabilityProbes(cwd);
|
|
26469
|
-
let step = probes.next();
|
|
26470
|
-
while (!step.done) step = probes.next(await gitResult(cwd, step.value));
|
|
26471
|
-
return step.value;
|
|
26472
|
-
}
|
|
26473
|
-
function checkDurabilitySync(cwd) {
|
|
26474
|
-
if (!existsSync58(cwd)) return { durable: true };
|
|
26475
|
-
const probes = durabilityProbes(cwd);
|
|
26476
|
-
let step = probes.next();
|
|
26477
|
-
while (!step.done) step = probes.next(gitSyncResult(cwd, step.value));
|
|
26478
|
-
return step.value;
|
|
26479
|
-
}
|
|
26480
|
-
|
|
26481
26713
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
26482
26714
|
async function reapWorktree(worktreePath, force = false) {
|
|
26483
|
-
if (!
|
|
26715
|
+
if (!existsSync62(worktreePath)) {
|
|
26484
26716
|
daemonLog(`worktree ${worktreePath} already gone; skipping reap`);
|
|
26485
26717
|
return false;
|
|
26486
26718
|
}
|
|
@@ -26492,23 +26724,23 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
26492
26724
|
}
|
|
26493
26725
|
}
|
|
26494
26726
|
const clone = mainWorktree(worktreePath) ?? worktreePath;
|
|
26495
|
-
const branch2 = await gitOrNull(worktreePath, [
|
|
26496
|
-
"symbolic-ref",
|
|
26497
|
-
"--short",
|
|
26498
|
-
"HEAD"
|
|
26499
|
-
]);
|
|
26500
26727
|
if (!await removeTree(clone, worktreePath, force)) return false;
|
|
26501
|
-
|
|
26728
|
+
await deleteWorktreeBranch(clone, basename16(worktreePath));
|
|
26502
26729
|
forgetWorktree(worktreePath);
|
|
26503
26730
|
daemonLog(`worktree ${worktreePath} reaped${force ? " (forced)" : ""}`);
|
|
26504
26731
|
return true;
|
|
26505
26732
|
}
|
|
26506
|
-
async function
|
|
26507
|
-
|
|
26733
|
+
async function deleteWorktreeBranch(clone, branch2) {
|
|
26734
|
+
if (!listLocalBranches(clone).includes(branch2)) return;
|
|
26735
|
+
const current = await gitOrNull2(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
26508
26736
|
if (branch2 === current) return;
|
|
26509
26737
|
try {
|
|
26510
26738
|
await git2(clone, ["branch", "-D", branch2]);
|
|
26511
|
-
|
|
26739
|
+
daemonLog(`worktree branch ${branch2} deleted from clone ${clone}`);
|
|
26740
|
+
} catch (error) {
|
|
26741
|
+
daemonLog(
|
|
26742
|
+
`worktree branch ${branch2} retained in clone ${clone}: ${error instanceof Error ? error.message : String(error)}`
|
|
26743
|
+
);
|
|
26512
26744
|
}
|
|
26513
26745
|
}
|
|
26514
26746
|
|
|
@@ -26534,21 +26766,6 @@ function dismissSession(sessions, id) {
|
|
|
26534
26766
|
return true;
|
|
26535
26767
|
}
|
|
26536
26768
|
|
|
26537
|
-
// src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
|
|
26538
|
-
var DISABLED = {
|
|
26539
|
-
enabled: false,
|
|
26540
|
-
install: true,
|
|
26541
|
-
commitBeforeManualChecks: false,
|
|
26542
|
-
copy: [".env", "settings.local.json", ".claude/settings.local.json"]
|
|
26543
|
-
};
|
|
26544
|
-
function worktreeConfigFor(cwd) {
|
|
26545
|
-
try {
|
|
26546
|
-
return loadConfigFrom(cwd).worktree ?? DISABLED;
|
|
26547
|
-
} catch {
|
|
26548
|
-
return DISABLED;
|
|
26549
|
-
}
|
|
26550
|
-
}
|
|
26551
|
-
|
|
26552
26769
|
// src/commands/sessions/daemon/worktree/closeGateApplies.ts
|
|
26553
26770
|
function closeGateApplies(sessions, session) {
|
|
26554
26771
|
if (otherTreeHolders(sessions, session).length > 0) return false;
|
|
@@ -26570,12 +26787,12 @@ function setStatus2(session, newStatus) {
|
|
|
26570
26787
|
}
|
|
26571
26788
|
|
|
26572
26789
|
// src/commands/sessions/daemon/worktree/watchGitState.ts
|
|
26573
|
-
import { existsSync as
|
|
26790
|
+
import { existsSync as existsSync63, watch } from "fs";
|
|
26574
26791
|
var DEBOUNCE_MS = 500;
|
|
26575
26792
|
var POLL_MS = 3e4;
|
|
26576
26793
|
function watchGitState(cwd, onChange) {
|
|
26577
26794
|
const common = gitCommonDir(cwd);
|
|
26578
|
-
if (!common || !
|
|
26795
|
+
if (!common || !existsSync63(common)) return void 0;
|
|
26579
26796
|
const watchers = [
|
|
26580
26797
|
watchGitDir(common, onChange),
|
|
26581
26798
|
pollGitState(cwd, onChange)
|
|
@@ -27167,10 +27384,10 @@ function emitSessionOutput(session, clients, data) {
|
|
|
27167
27384
|
}
|
|
27168
27385
|
|
|
27169
27386
|
// src/commands/sessions/daemon/exitReason.ts
|
|
27170
|
-
import { existsSync as
|
|
27387
|
+
import { existsSync as existsSync64 } from "fs";
|
|
27171
27388
|
function exitReason(session, exitCode) {
|
|
27172
27389
|
const base = `process exited with code ${exitCode}`;
|
|
27173
|
-
if (session.cwd && !
|
|
27390
|
+
if (session.cwd && !existsSync64(session.cwd))
|
|
27174
27391
|
return `${base}: working directory ${session.cwd} no longer exists`;
|
|
27175
27392
|
return base;
|
|
27176
27393
|
}
|
|
@@ -27188,8 +27405,8 @@ function handleFailedResume(session, exitCode, onStatusChange) {
|
|
|
27188
27405
|
}
|
|
27189
27406
|
|
|
27190
27407
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
27191
|
-
import { existsSync as
|
|
27192
|
-
import { dirname as
|
|
27408
|
+
import { existsSync as existsSync65, mkdirSync as mkdirSync26, watch as watch2 } from "fs";
|
|
27409
|
+
import { dirname as dirname31 } from "path";
|
|
27193
27410
|
|
|
27194
27411
|
// src/commands/sessions/daemon/applyReviewPause.ts
|
|
27195
27412
|
function applyReviewPause(session, activity2) {
|
|
@@ -27243,9 +27460,9 @@ var DEBOUNCE_MS2 = 50;
|
|
|
27243
27460
|
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
27244
27461
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
27245
27462
|
const path71 = activityPath(session.id);
|
|
27246
|
-
const dir =
|
|
27463
|
+
const dir = dirname31(path71);
|
|
27247
27464
|
try {
|
|
27248
|
-
|
|
27465
|
+
mkdirSync26(dir, { recursive: true });
|
|
27249
27466
|
} catch {
|
|
27250
27467
|
return;
|
|
27251
27468
|
}
|
|
@@ -27269,7 +27486,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
|
|
|
27269
27486
|
if (timer) clearTimeout(timer);
|
|
27270
27487
|
timer = setTimeout(read, DEBOUNCE_MS2);
|
|
27271
27488
|
});
|
|
27272
|
-
if (
|
|
27489
|
+
if (existsSync65(path71)) read();
|
|
27273
27490
|
}
|
|
27274
27491
|
function refreshActivity(session) {
|
|
27275
27492
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
@@ -27929,8 +28146,8 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
27929
28146
|
}
|
|
27930
28147
|
|
|
27931
28148
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
27932
|
-
import { existsSync as
|
|
27933
|
-
import { basename as
|
|
28149
|
+
import { existsSync as existsSync68 } from "fs";
|
|
28150
|
+
import { basename as basename18 } from "path";
|
|
27934
28151
|
|
|
27935
28152
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
27936
28153
|
function accountedTrees(sessions) {
|
|
@@ -27958,71 +28175,6 @@ function detectExistingWorktree(cwd) {
|
|
|
27958
28175
|
return void 0;
|
|
27959
28176
|
}
|
|
27960
28177
|
|
|
27961
|
-
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
27962
|
-
import { execFile as execFile8 } from "child_process";
|
|
27963
|
-
import { copyFileSync, existsSync as existsSync65, mkdirSync as mkdirSync26 } from "fs";
|
|
27964
|
-
import { dirname as dirname30, join as join71 } from "path";
|
|
27965
|
-
|
|
27966
|
-
// src/commands/sessions/daemon/worktree/resolveInstallCommand.ts
|
|
27967
|
-
import { existsSync as existsSync64 } from "fs";
|
|
27968
|
-
import { join as join70 } from "path";
|
|
27969
|
-
function detectInstallCommand(repoRoot) {
|
|
27970
|
-
if (!existsSync64(join70(repoRoot, "package.json"))) return null;
|
|
27971
|
-
if (existsSync64(join70(repoRoot, "pnpm-lock.yaml"))) return "pnpm install";
|
|
27972
|
-
if (existsSync64(join70(repoRoot, "yarn.lock"))) return "yarn install";
|
|
27973
|
-
if (existsSync64(join70(repoRoot, "bun.lockb"))) return "bun install";
|
|
27974
|
-
return "npm install";
|
|
27975
|
-
}
|
|
27976
|
-
function resolveInstallCommand(repoRoot, install) {
|
|
27977
|
-
if (install === false) return null;
|
|
27978
|
-
if (typeof install === "string") return install;
|
|
27979
|
-
return detectInstallCommand(repoRoot);
|
|
27980
|
-
}
|
|
27981
|
-
|
|
27982
|
-
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
27983
|
-
function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
27984
|
-
}) {
|
|
27985
|
-
const cfg = worktreeConfigFor(clone);
|
|
27986
|
-
copyConfigFiles(worktreePath, clone, cfg.copy);
|
|
27987
|
-
runInstall(worktreePath, clone, cfg.install, onSeeded);
|
|
27988
|
-
}
|
|
27989
|
-
function copyConfigFiles(worktreePath, clone, copy) {
|
|
27990
|
-
for (const rel of copy) {
|
|
27991
|
-
const src = join71(clone, rel);
|
|
27992
|
-
if (!existsSync65(src)) continue;
|
|
27993
|
-
const dest = join71(worktreePath, rel);
|
|
27994
|
-
try {
|
|
27995
|
-
mkdirSync26(dirname30(dest), { recursive: true });
|
|
27996
|
-
copyFileSync(src, dest);
|
|
27997
|
-
daemonLog(`worktree ${worktreePath} seeded ${rel}`);
|
|
27998
|
-
} catch (error) {
|
|
27999
|
-
daemonLog(
|
|
28000
|
-
`worktree ${worktreePath} failed to seed ${rel}: ${message(error)}`
|
|
28001
|
-
);
|
|
28002
|
-
}
|
|
28003
|
-
}
|
|
28004
|
-
}
|
|
28005
|
-
function runInstall(worktreePath, clone, install, onSeeded) {
|
|
28006
|
-
const command = resolveInstallCommand(clone, install);
|
|
28007
|
-
if (!command) {
|
|
28008
|
-
onSeeded();
|
|
28009
|
-
return;
|
|
28010
|
-
}
|
|
28011
|
-
const windows = /^[A-Za-z]:[\\/]/.test(worktreePath);
|
|
28012
|
-
const shell = windows ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
28013
|
-
const shellArgs = windows ? ["/c", command] : ["-l", "-c", command];
|
|
28014
|
-
daemonLog(`worktree ${worktreePath} installing deps: ${command}`);
|
|
28015
|
-
execFile8(shell, shellArgs, { cwd: worktreePath }, (error) => {
|
|
28016
|
-
daemonLog(
|
|
28017
|
-
error ? `worktree ${worktreePath} install failed: ${error.message}` : `worktree ${worktreePath} install complete`
|
|
28018
|
-
);
|
|
28019
|
-
onSeeded();
|
|
28020
|
-
});
|
|
28021
|
-
}
|
|
28022
|
-
function message(error) {
|
|
28023
|
-
return error instanceof Error ? error.message : String(error);
|
|
28024
|
-
}
|
|
28025
|
-
|
|
28026
28178
|
// src/commands/sessions/daemon/worktree/bindNewWorktree.ts
|
|
28027
28179
|
function bindNewWorktree(session, alloc, notify2, startHeld = () => {
|
|
28028
28180
|
}) {
|
|
@@ -28084,9 +28236,9 @@ function capped(lines) {
|
|
|
28084
28236
|
}
|
|
28085
28237
|
|
|
28086
28238
|
// src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
|
|
28087
|
-
import { existsSync as
|
|
28239
|
+
import { existsSync as existsSync67 } from "fs";
|
|
28088
28240
|
async function reclaimVanishedWorktrees(clone, paths) {
|
|
28089
|
-
if (!
|
|
28241
|
+
if (!existsSync67(clone)) {
|
|
28090
28242
|
for (const { path: path71 } of paths) forgetWorktree(path71);
|
|
28091
28243
|
daemonLog(
|
|
28092
28244
|
`clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
|
|
@@ -28122,7 +28274,7 @@ async function reclaimBranch(clone, branch2) {
|
|
|
28122
28274
|
}
|
|
28123
28275
|
|
|
28124
28276
|
// src/commands/sessions/daemon/worktree/resurfaceOrphanedWorktree.ts
|
|
28125
|
-
import { basename as
|
|
28277
|
+
import { basename as basename17 } from "path";
|
|
28126
28278
|
function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
|
|
28127
28279
|
const { orphan, reason: reason2, held } = recovered;
|
|
28128
28280
|
let id;
|
|
@@ -28145,7 +28297,7 @@ function orphanedSession(id, recovered) {
|
|
|
28145
28297
|
const { orphan, reason: reason2, held } = recovered;
|
|
28146
28298
|
return {
|
|
28147
28299
|
...sessionBase(id, "stopped"),
|
|
28148
|
-
name: `recovered ${
|
|
28300
|
+
name: `recovered ${basename17(orphan.path)}`,
|
|
28149
28301
|
subtitle: `${held.summary} in ${orphan.path}`,
|
|
28150
28302
|
commandType: "claude",
|
|
28151
28303
|
pty: null,
|
|
@@ -28179,10 +28331,10 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
|
28179
28331
|
const vanished = /* @__PURE__ */ new Map();
|
|
28180
28332
|
for (const { path: path71, clone } of readWorktreeRegistry()) {
|
|
28181
28333
|
if (accounted.has(path71)) continue;
|
|
28182
|
-
if (!
|
|
28334
|
+
if (!existsSync68(path71)) {
|
|
28183
28335
|
vanished.set(clone, [
|
|
28184
28336
|
...vanished.get(clone) ?? [],
|
|
28185
|
-
{ path: path71, branch:
|
|
28337
|
+
{ path: path71, branch: basename18(path71) }
|
|
28186
28338
|
]);
|
|
28187
28339
|
continue;
|
|
28188
28340
|
}
|
|
@@ -28358,7 +28510,7 @@ function treeSpawnContext(sessions, spawnWith, notify2, clients, onStatusChange)
|
|
|
28358
28510
|
}
|
|
28359
28511
|
|
|
28360
28512
|
// src/commands/sessions/daemon/watchTranscript.ts
|
|
28361
|
-
import { existsSync as
|
|
28513
|
+
import { existsSync as existsSync69, watch as watch3 } from "fs";
|
|
28362
28514
|
|
|
28363
28515
|
// src/commands/sessions/daemon/reconcileTranscriptStatus.ts
|
|
28364
28516
|
async function resolveTranscriptPath(session) {
|
|
@@ -28393,7 +28545,7 @@ function watchTranscript(session, onStatusChange) {
|
|
|
28393
28545
|
if (!session.cwd || !session.claudeSessionId) return;
|
|
28394
28546
|
if (session.watchedTranscriptId === session.claudeSessionId) return;
|
|
28395
28547
|
const dir = projectDirForCwd(session.cwd);
|
|
28396
|
-
if (!
|
|
28548
|
+
if (!existsSync69(dir)) return;
|
|
28397
28549
|
if (session.transcriptWatcher) {
|
|
28398
28550
|
session.transcriptWatcher.close();
|
|
28399
28551
|
session.transcriptWatcher = void 0;
|
|
@@ -28544,13 +28696,13 @@ async function defaultConnect() {
|
|
|
28544
28696
|
}
|
|
28545
28697
|
|
|
28546
28698
|
// src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
|
|
28547
|
-
import { existsSync as
|
|
28699
|
+
import { existsSync as existsSync70, readFileSync as readFileSync50 } from "fs";
|
|
28548
28700
|
import { posix } from "path";
|
|
28549
28701
|
function hasPersistedWindowsSessions() {
|
|
28550
28702
|
const sessionsFile = windowsSessionsFileFromWsl();
|
|
28551
28703
|
if (!sessionsFile) return false;
|
|
28552
28704
|
try {
|
|
28553
|
-
if (!
|
|
28705
|
+
if (!existsSync70(sessionsFile)) return false;
|
|
28554
28706
|
const data = JSON.parse(readFileSync50(sessionsFile, "utf8"));
|
|
28555
28707
|
return Array.isArray(data) && data.length > 0;
|
|
28556
28708
|
} catch (error) {
|
|
@@ -29129,81 +29281,6 @@ function resumeSession(id, sessionId, cwd, name) {
|
|
|
29129
29281
|
};
|
|
29130
29282
|
}
|
|
29131
29283
|
|
|
29132
|
-
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
29133
|
-
import { existsSync as existsSync70 } from "fs";
|
|
29134
|
-
import { basename as basename17, dirname as dirname31 } from "path";
|
|
29135
|
-
|
|
29136
|
-
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
29137
|
-
import { basename as basename16, join as join72 } from "path";
|
|
29138
|
-
function planAllocation(clone, boundTreeRoots2) {
|
|
29139
|
-
return boundTreeRoots2.has(clone) ? "spill" : "primary";
|
|
29140
|
-
}
|
|
29141
|
-
function nextWorktreePath(clone, base, isTaken) {
|
|
29142
|
-
const name = basename16(clone);
|
|
29143
|
-
for (let n = 2; n < 1e3; n++) {
|
|
29144
|
-
const candidate = join72(base, `${name}-${n}`);
|
|
29145
|
-
if (!isTaken(candidate)) return candidate;
|
|
29146
|
-
}
|
|
29147
|
-
throw new Error(`no free worktree suffix for ${clone}`);
|
|
29148
|
-
}
|
|
29149
|
-
|
|
29150
|
-
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
29151
|
-
function createWorktree(clone, root, boundTreeRoots2) {
|
|
29152
|
-
const base = root ? expandTilde2(root) : dirname31(clone);
|
|
29153
|
-
const registered = new Set(listWorktreePaths(clone));
|
|
29154
|
-
const branches = new Set(listLocalBranches(clone));
|
|
29155
|
-
const path71 = nextWorktreePath(
|
|
29156
|
-
clone,
|
|
29157
|
-
base,
|
|
29158
|
-
(candidate) => registered.has(candidate) || existsSync70(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename17(candidate))
|
|
29159
|
-
);
|
|
29160
|
-
const trunk = cloneTrunkBranch(clone);
|
|
29161
|
-
gitSync(clone, ["config", "push.default", "upstream"]);
|
|
29162
|
-
gitSync(clone, [
|
|
29163
|
-
"worktree",
|
|
29164
|
-
"add",
|
|
29165
|
-
"--track",
|
|
29166
|
-
"-b",
|
|
29167
|
-
basename17(path71),
|
|
29168
|
-
path71,
|
|
29169
|
-
`origin/${trunk}`
|
|
29170
|
-
]);
|
|
29171
|
-
recordWorktree(path71, clone, getCurrentOrigin(clone));
|
|
29172
|
-
daemonLog(
|
|
29173
|
-
`worktree allocated ${path71} (branch ${basename17(path71)} tracking origin/${trunk}) for clone ${clone}`
|
|
29174
|
-
);
|
|
29175
|
-
return path71;
|
|
29176
|
-
}
|
|
29177
|
-
function cloneTrunkBranch(clone) {
|
|
29178
|
-
const branch2 = gitSyncOrNull(clone, ["symbolic-ref", "--short", "HEAD"]);
|
|
29179
|
-
if (branch2) return branch2;
|
|
29180
|
-
const head = gitSyncOrNull(clone, [
|
|
29181
|
-
"symbolic-ref",
|
|
29182
|
-
"--short",
|
|
29183
|
-
"refs/remotes/origin/HEAD"
|
|
29184
|
-
]);
|
|
29185
|
-
if (head) {
|
|
29186
|
-
const slash = head.indexOf("/");
|
|
29187
|
-
return slash === -1 ? head : head.slice(slash + 1);
|
|
29188
|
-
}
|
|
29189
|
-
return "main";
|
|
29190
|
-
}
|
|
29191
|
-
|
|
29192
|
-
// src/commands/sessions/daemon/worktree/allocateTree.ts
|
|
29193
|
-
function allocateTree(requestedCwd, boundTreeRoots2) {
|
|
29194
|
-
if (!requestedCwd)
|
|
29195
|
-
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
29196
|
-
const repoRoot = findRepoRoot(requestedCwd) ?? requestedCwd;
|
|
29197
|
-
const cfg = worktreeConfigFor(repoRoot);
|
|
29198
|
-
if (!cfg.enabled)
|
|
29199
|
-
return { cwd: requestedCwd, kind: "primary", created: false };
|
|
29200
|
-
const clone = mainWorktree(repoRoot) ?? repoRoot;
|
|
29201
|
-
if (planAllocation(clone, boundTreeRoots2) === "primary")
|
|
29202
|
-
return { cwd: clone, kind: "primary", created: false, clone };
|
|
29203
|
-
const path71 = createWorktree(clone, cfg.root, boundTreeRoots2);
|
|
29204
|
-
return { cwd: path71, kind: "worktree", created: true, clone };
|
|
29205
|
-
}
|
|
29206
|
-
|
|
29207
29284
|
// src/commands/sessions/daemon/worktree/boundTreeRoots.ts
|
|
29208
29285
|
function boundTreeRoots(sessions) {
|
|
29209
29286
|
const roots = /* @__PURE__ */ new Set();
|
|
@@ -29228,9 +29305,17 @@ function holdsTree(session, root) {
|
|
|
29228
29305
|
return !durability.durable;
|
|
29229
29306
|
}
|
|
29230
29307
|
|
|
29308
|
+
// src/commands/sessions/daemon/worktree/isPrCheckoutArgs.ts
|
|
29309
|
+
var CHECKOUT_COMMANDS = /* @__PURE__ */ new Set(["review", "review-pr-comments"]);
|
|
29310
|
+
function isPrCheckoutArgs(args) {
|
|
29311
|
+
const [command, ...rest] = args;
|
|
29312
|
+
if (!command || !CHECKOUT_COMMANDS.has(command)) return false;
|
|
29313
|
+
return rest.some((arg) => /^[1-9]\d*$/.test(arg));
|
|
29314
|
+
}
|
|
29315
|
+
|
|
29231
29316
|
// src/commands/sessions/daemon/worktree/spawnInTree.ts
|
|
29232
|
-
function allocateAndBind(ctx, cwd, create) {
|
|
29233
|
-
const alloc = allocateTree(cwd, boundTreeRoots(ctx.sessions));
|
|
29317
|
+
function allocateAndBind(ctx, cwd, create, options2 = {}) {
|
|
29318
|
+
const alloc = allocateTree(cwd, boundTreeRoots(ctx.sessions), options2);
|
|
29234
29319
|
const needsSeeding = alloc.kind === "worktree" && alloc.created === true;
|
|
29235
29320
|
const id = ctx.spawnWith((sid) => create(sid, alloc.cwd, needsSeeding));
|
|
29236
29321
|
bindNewWorktree(ctx.sessions.get(id), alloc, ctx.notify, ctx.startHeld);
|
|
@@ -29247,7 +29332,8 @@ function spawnAssistInTree(ctx, assistArgs, cwd, meta) {
|
|
|
29247
29332
|
return allocateAndBind(
|
|
29248
29333
|
ctx,
|
|
29249
29334
|
cwd,
|
|
29250
|
-
(sid, resolvedCwd, holdUntilSeeded) => createAssistSession(sid, assistArgs, resolvedCwd, meta, holdUntilSeeded)
|
|
29335
|
+
(sid, resolvedCwd, holdUntilSeeded) => createAssistSession(sid, assistArgs, resolvedCwd, meta, holdUntilSeeded),
|
|
29336
|
+
{ forCheckout: isPrCheckoutArgs(assistArgs) }
|
|
29251
29337
|
);
|
|
29252
29338
|
}
|
|
29253
29339
|
function resumeInTree(ctx, sessionId, cwd, name) {
|
|
@@ -29960,6 +30046,11 @@ var sessionsConfigHelp = [
|
|
|
29960
30046
|
setter: "assist config set worktree.enabled true -g --repo",
|
|
29961
30047
|
note: "opt in per repo: spill concurrent sessions into adjacent <clone>-N worktrees (default off)"
|
|
29962
30048
|
},
|
|
30049
|
+
{
|
|
30050
|
+
key: "worktree.trunk",
|
|
30051
|
+
setter: "assist config set worktree.trunk true -g --repo",
|
|
30052
|
+
note: "trunk-based: a spilled worktree lands on the mainline (default off: it starts off the remote default with no mainline tracking, so the session raises its own branch and PR)"
|
|
30053
|
+
},
|
|
29963
30054
|
{
|
|
29964
30055
|
key: "worktree.root",
|
|
29965
30056
|
setter: "assist config set worktree.root ~/git -g --repo",
|
|
@@ -30000,7 +30091,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
30000
30091
|
}
|
|
30001
30092
|
|
|
30002
30093
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
30003
|
-
import { execFileSync as
|
|
30094
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
30004
30095
|
|
|
30005
30096
|
// src/commands/sessions/summarise/extractFirstUserMessage.ts
|
|
30006
30097
|
function extractFirstUserMessage(filePath) {
|
|
@@ -30024,7 +30115,7 @@ function summariseSession(jsonlPath2) {
|
|
|
30024
30115
|
}
|
|
30025
30116
|
const prompt = buildPrompt3(firstMessage, backlogIds);
|
|
30026
30117
|
try {
|
|
30027
|
-
const output =
|
|
30118
|
+
const output = execFileSync12("claude", ["-p", "--model", "haiku", prompt], {
|
|
30028
30119
|
encoding: "utf8",
|
|
30029
30120
|
timeout: 3e4,
|
|
30030
30121
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -30586,7 +30677,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
30586
30677
|
}
|
|
30587
30678
|
|
|
30588
30679
|
// src/commands/update.ts
|
|
30589
|
-
import { execSync as
|
|
30680
|
+
import { execSync as execSync60 } from "child_process";
|
|
30590
30681
|
import * as path70 from "path";
|
|
30591
30682
|
|
|
30592
30683
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
@@ -30610,7 +30701,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
30610
30701
|
if (resolved.split(path70.sep).includes("node_modules")) {
|
|
30611
30702
|
return true;
|
|
30612
30703
|
}
|
|
30613
|
-
const globalPrefix =
|
|
30704
|
+
const globalPrefix = execSync60("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
30614
30705
|
return resolved.toLowerCase().startsWith(path70.resolve(globalPrefix).toLowerCase());
|
|
30615
30706
|
} catch {
|
|
30616
30707
|
return false;
|
|
@@ -30621,18 +30712,18 @@ async function update2() {
|
|
|
30621
30712
|
console.log(`Assist is installed at: ${installDir}`);
|
|
30622
30713
|
if (isGitRepo(installDir)) {
|
|
30623
30714
|
console.log("Detected git repo installation, pulling latest...");
|
|
30624
|
-
|
|
30715
|
+
execSync60("git pull", { cwd: installDir, stdio: "inherit" });
|
|
30625
30716
|
console.log("Installing dependencies...");
|
|
30626
|
-
|
|
30717
|
+
execSync60("npm i", { cwd: installDir, stdio: "inherit" });
|
|
30627
30718
|
console.log("Building...");
|
|
30628
|
-
|
|
30719
|
+
execSync60("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
30629
30720
|
console.log("Syncing commands...");
|
|
30630
|
-
|
|
30721
|
+
execSync60("assist sync", { stdio: "inherit" });
|
|
30631
30722
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
30632
30723
|
console.log("Detected global npm installation, updating...");
|
|
30633
|
-
|
|
30724
|
+
execSync60("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
30634
30725
|
console.log("Syncing commands...");
|
|
30635
|
-
|
|
30726
|
+
execSync60("assist sync", { stdio: "inherit" });
|
|
30636
30727
|
} else {
|
|
30637
30728
|
console.error(
|
|
30638
30729
|
"Could not determine installation method. Expected a git repo or global npm install."
|