@staff0rd/assist 0.488.5 → 0.489.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 +2 -1
- package/allowed.cli-reads +1 -0
- package/dist/allowed.cli-reads +1 -0
- package/dist/commands/sessions/web/bundle.js +1 -1
- package/dist/index.js +712 -480
- 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.489.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -2415,8 +2415,8 @@ function printDiff(oldContent, newContent) {
|
|
|
2415
2415
|
normalizeJson(newContent)
|
|
2416
2416
|
);
|
|
2417
2417
|
for (const change of changes) {
|
|
2418
|
-
const
|
|
2419
|
-
for (const line of
|
|
2418
|
+
const lines2 = change.value.replace(/\n$/, "").split("\n");
|
|
2419
|
+
for (const line of lines2) {
|
|
2420
2420
|
if (change.added) {
|
|
2421
2421
|
console.log(chalk12.green(`+ ${line}`));
|
|
2422
2422
|
} else if (change.removed) {
|
|
@@ -2863,11 +2863,11 @@ function removeVscodeFromGitignore() {
|
|
|
2863
2863
|
return;
|
|
2864
2864
|
}
|
|
2865
2865
|
const content = fs3.readFileSync(gitignorePath, "utf8");
|
|
2866
|
-
const
|
|
2867
|
-
const filteredLines =
|
|
2866
|
+
const lines2 = content.split("\n");
|
|
2867
|
+
const filteredLines = lines2.filter(
|
|
2868
2868
|
(line) => !line.trim().toLowerCase().includes(".vscode")
|
|
2869
2869
|
);
|
|
2870
|
-
if (filteredLines.length !==
|
|
2870
|
+
if (filteredLines.length !== lines2.length) {
|
|
2871
2871
|
fs3.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
2872
2872
|
console.log(chalk20.dim("Removed .vscode references from .gitignore"));
|
|
2873
2873
|
}
|
|
@@ -3269,11 +3269,11 @@ ${checkName} failed:
|
|
|
3269
3269
|
// src/commands/lint/lint/runImportExtensionCheck.ts
|
|
3270
3270
|
function checkForImportExtensions(filePath) {
|
|
3271
3271
|
const content = fs12.readFileSync(filePath, "utf8");
|
|
3272
|
-
const
|
|
3272
|
+
const lines2 = content.split("\n");
|
|
3273
3273
|
const violations = [];
|
|
3274
3274
|
const importExtensionPattern = /from\s+["']\..*\.(js|ts)["']/;
|
|
3275
|
-
for (let i = 0; i <
|
|
3276
|
-
const line =
|
|
3275
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
3276
|
+
const line = lines2[i];
|
|
3277
3277
|
if (importExtensionPattern.test(line)) {
|
|
3278
3278
|
violations.push({
|
|
3279
3279
|
filePath,
|
|
@@ -3305,12 +3305,12 @@ function runImportExtensionCheck() {
|
|
|
3305
3305
|
import fs13 from "fs";
|
|
3306
3306
|
function checkForDynamicImports(filePath) {
|
|
3307
3307
|
const content = fs13.readFileSync(filePath, "utf8");
|
|
3308
|
-
const
|
|
3308
|
+
const lines2 = content.split("\n");
|
|
3309
3309
|
const violations = [];
|
|
3310
3310
|
const requirePattern = /\brequire\s*\(/;
|
|
3311
3311
|
const dynamicImportPattern = /\bimport\s*\(/;
|
|
3312
|
-
for (let i = 0; i <
|
|
3313
|
-
const line =
|
|
3312
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
3313
|
+
const line = lines2[i];
|
|
3314
3314
|
if (requirePattern.test(line) || dynamicImportPattern.test(line)) {
|
|
3315
3315
|
violations.push({
|
|
3316
3316
|
filePath,
|
|
@@ -3412,9 +3412,9 @@ function collectBicepComments(content) {
|
|
|
3412
3412
|
comments3.push({ line, text: match });
|
|
3413
3413
|
return blankNonNewline(match);
|
|
3414
3414
|
});
|
|
3415
|
-
const
|
|
3416
|
-
for (let i = 0; i <
|
|
3417
|
-
const match =
|
|
3415
|
+
const lines2 = work.split("\n");
|
|
3416
|
+
for (let i = 0; i < lines2.length; i++) {
|
|
3417
|
+
const match = lines2[i].match(LINE_COMMENT);
|
|
3418
3418
|
if (match) comments3.push({ line: i + 1, text: match[0] });
|
|
3419
3419
|
}
|
|
3420
3420
|
return comments3;
|
|
@@ -3429,14 +3429,14 @@ function isHeaderLine(line) {
|
|
|
3429
3429
|
return trimmed === "" || trimmed.startsWith("#");
|
|
3430
3430
|
}
|
|
3431
3431
|
function collectHashComments(content, options2) {
|
|
3432
|
-
const
|
|
3432
|
+
const lines2 = content.split("\n");
|
|
3433
3433
|
let start3 = 0;
|
|
3434
3434
|
if (options2.skipHeader) {
|
|
3435
|
-
while (start3 <
|
|
3435
|
+
while (start3 < lines2.length && isHeaderLine(lines2[start3])) start3++;
|
|
3436
3436
|
}
|
|
3437
3437
|
const comments3 = [];
|
|
3438
|
-
for (let i = start3; i <
|
|
3439
|
-
const work =
|
|
3438
|
+
for (let i = start3; i < lines2.length; i++) {
|
|
3439
|
+
const work = lines2[i].replace(
|
|
3440
3440
|
/"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'/g,
|
|
3441
3441
|
blankNonNewline2
|
|
3442
3442
|
);
|
|
@@ -3470,8 +3470,8 @@ function collectComments(sourceFile) {
|
|
|
3470
3470
|
var MAINTAINABILITY_OVERRIDE_MARKER = "assist-maintainability-override";
|
|
3471
3471
|
var OVERRIDE_MARKER = /^\s*\/\/\s*assist-maintainability-override:?\s*(-?\d+)\s*$/;
|
|
3472
3472
|
function parseMaintainabilityOverride(content) {
|
|
3473
|
-
const
|
|
3474
|
-
for (const line of
|
|
3473
|
+
const lines2 = content.split("\n").slice(0, 10);
|
|
3474
|
+
for (const line of lines2) {
|
|
3475
3475
|
const match = line.match(OVERRIDE_MARKER);
|
|
3476
3476
|
if (!match) continue;
|
|
3477
3477
|
const value = Number(match[1]);
|
|
@@ -3508,12 +3508,12 @@ function isCommentExempt(text17) {
|
|
|
3508
3508
|
function toSingleLine(text17) {
|
|
3509
3509
|
return text17.replace(/\s+/g, " ").trim();
|
|
3510
3510
|
}
|
|
3511
|
-
function collectSourceFindings(file,
|
|
3511
|
+
function collectSourceFindings(file, lines2, project) {
|
|
3512
3512
|
const findings = [];
|
|
3513
3513
|
const sourceFile = project.addSourceFileAtPath(file);
|
|
3514
3514
|
for (const { pos, text: text17 } of collectComments(sourceFile)) {
|
|
3515
3515
|
const { line } = sourceFile.getLineAndColumnAtPos(pos);
|
|
3516
|
-
if (!
|
|
3516
|
+
if (!lines2.has(line)) continue;
|
|
3517
3517
|
if (isCommentExempt(text17)) continue;
|
|
3518
3518
|
findings.push({ file, line, text: toSingleLine(text17) });
|
|
3519
3519
|
}
|
|
@@ -3533,29 +3533,29 @@ function collectYamlComments(content) {
|
|
|
3533
3533
|
}
|
|
3534
3534
|
|
|
3535
3535
|
// src/commands/verify/blockCodeComments/collectFileComments.ts
|
|
3536
|
-
function toFindings(file,
|
|
3536
|
+
function toFindings(file, lines2, raw, exempt) {
|
|
3537
3537
|
const findings = [];
|
|
3538
3538
|
for (const { line, text: text17 } of raw) {
|
|
3539
|
-
if (!
|
|
3539
|
+
if (!lines2.has(line)) continue;
|
|
3540
3540
|
if (exempt && isCommentExempt(text17)) continue;
|
|
3541
3541
|
findings.push({ file, line, text: text17.replace(/\s+/g, " ").trim() });
|
|
3542
3542
|
}
|
|
3543
3543
|
return findings;
|
|
3544
3544
|
}
|
|
3545
|
-
function collectFileComments(file,
|
|
3545
|
+
function collectFileComments(file, lines2, project) {
|
|
3546
3546
|
const read = () => fs14.readFileSync(file, "utf8");
|
|
3547
3547
|
if (isYamlFile(file))
|
|
3548
|
-
return toFindings(file,
|
|
3548
|
+
return toFindings(file, lines2, collectYamlComments(read()), false);
|
|
3549
3549
|
if (isDockerfile(file) || isEnvFile(file) || isShellFile(file))
|
|
3550
3550
|
return toFindings(
|
|
3551
3551
|
file,
|
|
3552
|
-
|
|
3552
|
+
lines2,
|
|
3553
3553
|
collectHashComments(read(), { skipHeader: isShellFile(file) }),
|
|
3554
3554
|
true
|
|
3555
3555
|
);
|
|
3556
3556
|
if (isBicepFile(file))
|
|
3557
|
-
return toFindings(file,
|
|
3558
|
-
return collectSourceFindings(file,
|
|
3557
|
+
return toFindings(file, lines2, collectBicepComments(read()), true);
|
|
3558
|
+
return collectSourceFindings(file, lines2, project);
|
|
3559
3559
|
}
|
|
3560
3560
|
|
|
3561
3561
|
// src/commands/verify/blockCodeComments/parseDiffAddedLines.ts
|
|
@@ -3623,9 +3623,9 @@ function findComments(options2) {
|
|
|
3623
3623
|
compilerOptions: { allowJs: true }
|
|
3624
3624
|
});
|
|
3625
3625
|
const findings = [];
|
|
3626
|
-
for (const [file,
|
|
3626
|
+
for (const [file, lines2] of addedLines) {
|
|
3627
3627
|
if (!shouldScan(file, options2.ignoreGlobs)) continue;
|
|
3628
|
-
findings.push(...collectFileComments(file,
|
|
3628
|
+
findings.push(...collectFileComments(file, lines2, project));
|
|
3629
3629
|
}
|
|
3630
3630
|
findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
3631
3631
|
return findings;
|
|
@@ -3658,10 +3658,10 @@ function getDocumentedConfigKeys() {
|
|
|
3658
3658
|
}
|
|
3659
3659
|
function renderConfigHelp(entries, preamble) {
|
|
3660
3660
|
const width = Math.max(...entries.map((entry) => entry.setter.length));
|
|
3661
|
-
const
|
|
3661
|
+
const lines2 = entries.map(
|
|
3662
3662
|
(entry) => ` ${entry.setter.padEnd(width)} # ${entry.note}`
|
|
3663
3663
|
);
|
|
3664
|
-
const body = preamble ? ["", preamble, "", "Config:", ...
|
|
3664
|
+
const body = preamble ? ["", preamble, "", "Config:", ...lines2] : ["", "Config:", ...lines2];
|
|
3665
3665
|
return body.join("\n");
|
|
3666
3666
|
}
|
|
3667
3667
|
function configHelp(command, entries, preamble) {
|
|
@@ -3960,14 +3960,14 @@ function findRuleViolations(data, rule) {
|
|
|
3960
3960
|
}
|
|
3961
3961
|
return violations;
|
|
3962
3962
|
}
|
|
3963
|
-
function findForbiddenStrings(
|
|
3964
|
-
return
|
|
3963
|
+
function findForbiddenStrings(rules2, readJson) {
|
|
3964
|
+
return rules2.flatMap((rule) => findRuleViolations(readJson(rule.file), rule));
|
|
3965
3965
|
}
|
|
3966
3966
|
|
|
3967
3967
|
// src/commands/verify/forbiddenStrings/index.ts
|
|
3968
3968
|
function forbiddenStrings() {
|
|
3969
|
-
const
|
|
3970
|
-
if (
|
|
3969
|
+
const rules2 = loadConfig().forbiddenStrings ?? [];
|
|
3970
|
+
if (rules2.length === 0) {
|
|
3971
3971
|
console.log("No forbidden-strings rules configured.");
|
|
3972
3972
|
process.exit(0);
|
|
3973
3973
|
}
|
|
@@ -3988,7 +3988,7 @@ function forbiddenStrings() {
|
|
|
3988
3988
|
cache4.set(file, parsed);
|
|
3989
3989
|
return parsed;
|
|
3990
3990
|
};
|
|
3991
|
-
const violations = findForbiddenStrings(
|
|
3991
|
+
const violations = findForbiddenStrings(rules2, readJson);
|
|
3992
3992
|
if (violations.length === 0) {
|
|
3993
3993
|
console.log("No forbidden strings found.");
|
|
3994
3994
|
process.exit(0);
|
|
@@ -4015,18 +4015,18 @@ function hardcodedColors() {
|
|
|
4015
4015
|
const output = execSync13(`grep -rEnH '${pattern}' src/`, {
|
|
4016
4016
|
encoding: "utf8"
|
|
4017
4017
|
});
|
|
4018
|
-
const
|
|
4018
|
+
const lines2 = output.trim().split("\n").filter((line) => {
|
|
4019
4019
|
const match = line.match(/^(.+?):\d+:/);
|
|
4020
4020
|
if (!match) return true;
|
|
4021
4021
|
const file = match[1];
|
|
4022
4022
|
return !ignoreGlobs.some((glob) => minimatch3(file, glob));
|
|
4023
4023
|
});
|
|
4024
|
-
if (
|
|
4024
|
+
if (lines2.length === 0) {
|
|
4025
4025
|
console.log("No hardcoded colors found.");
|
|
4026
4026
|
process.exit(0);
|
|
4027
4027
|
}
|
|
4028
4028
|
console.log("Hardcoded colors found:\n");
|
|
4029
|
-
for (const line of
|
|
4029
|
+
for (const line of lines2) {
|
|
4030
4030
|
const match = line.match(/^(.+):(\d+):(.+)$/);
|
|
4031
4031
|
if (match) {
|
|
4032
4032
|
const [, file, lineNum, content] = match;
|
|
@@ -4036,7 +4036,7 @@ function hardcodedColors() {
|
|
|
4036
4036
|
}
|
|
4037
4037
|
}
|
|
4038
4038
|
console.log(`
|
|
4039
|
-
Total: ${
|
|
4039
|
+
Total: ${lines2.length} hardcoded color(s)`);
|
|
4040
4040
|
console.log("\nUse colors from the 'open-color' (oc) library instead.");
|
|
4041
4041
|
console.log("\nExample fix:");
|
|
4042
4042
|
console.log(" Before: color: '#228be6'");
|
|
@@ -4523,7 +4523,7 @@ ${failed2.length} script(s) failed:`);
|
|
|
4523
4523
|
}
|
|
4524
4524
|
}
|
|
4525
4525
|
function runEntry(entry) {
|
|
4526
|
-
return new Promise((
|
|
4526
|
+
return new Promise((resolve22) => {
|
|
4527
4527
|
const startTime = Date.now();
|
|
4528
4528
|
const child = spawnCommand(
|
|
4529
4529
|
entry.fullCommand,
|
|
@@ -4535,7 +4535,7 @@ function runEntry(entry) {
|
|
|
4535
4535
|
child.on("close", (code) => {
|
|
4536
4536
|
const exitCode = code ?? 1;
|
|
4537
4537
|
flushIfFailed(exitCode, chunks);
|
|
4538
|
-
|
|
4538
|
+
resolve22({
|
|
4539
4539
|
script: entry.name,
|
|
4540
4540
|
code: exitCode,
|
|
4541
4541
|
durationMs: Date.now() - startTime
|
|
@@ -5158,38 +5158,38 @@ var END_MARKER = "# <<< assist backup schedule <<<";
|
|
|
5158
5158
|
function buildBlock(every, cronLine) {
|
|
5159
5159
|
return [BEGIN_MARKER, `# every ${every}`, cronLine, END_MARKER];
|
|
5160
5160
|
}
|
|
5161
|
-
function findBlockRange(
|
|
5162
|
-
const start3 =
|
|
5161
|
+
function findBlockRange(lines2) {
|
|
5162
|
+
const start3 = lines2.indexOf(BEGIN_MARKER);
|
|
5163
5163
|
if (start3 === -1) return void 0;
|
|
5164
|
-
const end =
|
|
5164
|
+
const end = lines2.indexOf(END_MARKER, start3);
|
|
5165
5165
|
if (end === -1) return void 0;
|
|
5166
5166
|
return { start: start3, end };
|
|
5167
5167
|
}
|
|
5168
5168
|
function upsertScheduleBlock(crontab, every, cronLine) {
|
|
5169
|
-
const
|
|
5169
|
+
const lines2 = crontab.length === 0 ? [] : crontab.replace(/\n$/, "").split("\n");
|
|
5170
5170
|
const block = buildBlock(every, cronLine);
|
|
5171
|
-
const range = findBlockRange(
|
|
5172
|
-
const next3 = range === void 0 ? [...
|
|
5173
|
-
...
|
|
5171
|
+
const range = findBlockRange(lines2);
|
|
5172
|
+
const next3 = range === void 0 ? [...lines2, ...block] : [
|
|
5173
|
+
...lines2.slice(0, range.start),
|
|
5174
5174
|
...block,
|
|
5175
|
-
...
|
|
5175
|
+
...lines2.slice(range.end + 1)
|
|
5176
5176
|
];
|
|
5177
5177
|
return `${next3.join("\n")}
|
|
5178
5178
|
`;
|
|
5179
5179
|
}
|
|
5180
5180
|
function removeScheduleBlock(crontab) {
|
|
5181
|
-
const
|
|
5182
|
-
const range = findBlockRange(
|
|
5181
|
+
const lines2 = crontab.length === 0 ? [] : crontab.replace(/\n$/, "").split("\n");
|
|
5182
|
+
const range = findBlockRange(lines2);
|
|
5183
5183
|
if (range === void 0) return crontab;
|
|
5184
|
-
const next3 = [...
|
|
5184
|
+
const next3 = [...lines2.slice(0, range.start), ...lines2.slice(range.end + 1)];
|
|
5185
5185
|
return next3.length === 0 ? "" : `${next3.join("\n")}
|
|
5186
5186
|
`;
|
|
5187
5187
|
}
|
|
5188
5188
|
function readScheduleBlock(crontab) {
|
|
5189
|
-
const
|
|
5190
|
-
const range = findBlockRange(
|
|
5189
|
+
const lines2 = crontab.length === 0 ? [] : crontab.split("\n");
|
|
5190
|
+
const range = findBlockRange(lines2);
|
|
5191
5191
|
if (range === void 0) return void 0;
|
|
5192
|
-
const body =
|
|
5192
|
+
const body = lines2.slice(range.start + 1, range.end);
|
|
5193
5193
|
const everyLine = body.find((line) => line.startsWith("# every "));
|
|
5194
5194
|
const cronLine = body.find(
|
|
5195
5195
|
(line) => !line.startsWith("#") && line.trim() !== ""
|
|
@@ -5705,8 +5705,8 @@ function spawnInherit(command, args, options2 = {}) {
|
|
|
5705
5705
|
env,
|
|
5706
5706
|
cwd: options2.cwd
|
|
5707
5707
|
});
|
|
5708
|
-
const done2 = new Promise((
|
|
5709
|
-
child.on("close", (code) =>
|
|
5708
|
+
const done2 = new Promise((resolve22, reject) => {
|
|
5709
|
+
child.on("close", (code) => resolve22(code ?? 0));
|
|
5710
5710
|
child.on("error", reject);
|
|
5711
5711
|
});
|
|
5712
5712
|
return { child, done: done2 };
|
|
@@ -6851,9 +6851,9 @@ Failed to launch Claude for ${context}: ${message3}`)
|
|
|
6851
6851
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
6852
6852
|
import * as net from "net";
|
|
6853
6853
|
function connectToDaemon() {
|
|
6854
|
-
return new Promise((
|
|
6854
|
+
return new Promise((resolve22, reject) => {
|
|
6855
6855
|
const socket = net.connect(daemonPaths.socket);
|
|
6856
|
-
socket.once("connect", () =>
|
|
6856
|
+
socket.once("connect", () => resolve22(socket));
|
|
6857
6857
|
socket.once("error", reject);
|
|
6858
6858
|
});
|
|
6859
6859
|
}
|
|
@@ -6869,7 +6869,7 @@ async function isDaemonRunning() {
|
|
|
6869
6869
|
// src/commands/sessions/daemon/sendToDaemon.ts
|
|
6870
6870
|
var WRITE_TIMEOUT_MS = 500;
|
|
6871
6871
|
function sendToDaemon(message3) {
|
|
6872
|
-
return new Promise((
|
|
6872
|
+
return new Promise((resolve22, reject) => {
|
|
6873
6873
|
connectToDaemon().then((socket) => {
|
|
6874
6874
|
const timer = setTimeout(() => {
|
|
6875
6875
|
socket.destroy();
|
|
@@ -6883,7 +6883,7 @@ function sendToDaemon(message3) {
|
|
|
6883
6883
|
`, () => {
|
|
6884
6884
|
clearTimeout(timer);
|
|
6885
6885
|
socket.end();
|
|
6886
|
-
|
|
6886
|
+
resolve22();
|
|
6887
6887
|
});
|
|
6888
6888
|
}, reject);
|
|
6889
6889
|
});
|
|
@@ -6906,7 +6906,7 @@ function readSocketLines(socket, onLine) {
|
|
|
6906
6906
|
// src/commands/sessions/daemon/sendToDaemonAwaitAck.ts
|
|
6907
6907
|
var ACK_TIMEOUT_MS = 1e3;
|
|
6908
6908
|
function sendToDaemonAwaitAck(message3) {
|
|
6909
|
-
return new Promise((
|
|
6909
|
+
return new Promise((resolve22, reject) => {
|
|
6910
6910
|
connectToDaemon().then((socket) => {
|
|
6911
6911
|
let settled = false;
|
|
6912
6912
|
const finish = (error) => {
|
|
@@ -6915,7 +6915,7 @@ function sendToDaemonAwaitAck(message3) {
|
|
|
6915
6915
|
clearTimeout(timer);
|
|
6916
6916
|
socket.destroy();
|
|
6917
6917
|
if (error) reject(error);
|
|
6918
|
-
else
|
|
6918
|
+
else resolve22();
|
|
6919
6919
|
};
|
|
6920
6920
|
const timer = setTimeout(
|
|
6921
6921
|
() => finish(new Error("timed out awaiting daemon ack")),
|
|
@@ -6989,7 +6989,7 @@ async function deliverReliably(sessionId, status3, payload) {
|
|
|
6989
6989
|
}
|
|
6990
6990
|
}
|
|
6991
6991
|
function sleep(ms) {
|
|
6992
|
-
return new Promise((
|
|
6992
|
+
return new Promise((resolve22) => setTimeout(resolve22, ms));
|
|
6993
6993
|
}
|
|
6994
6994
|
function describeError(error) {
|
|
6995
6995
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -7631,14 +7631,14 @@ function backlogRunMarkers(text17) {
|
|
|
7631
7631
|
}
|
|
7632
7632
|
|
|
7633
7633
|
// src/commands/sessions/shared/extractSessionMeta.ts
|
|
7634
|
-
function extractSessionMeta(
|
|
7634
|
+
function extractSessionMeta(lines2) {
|
|
7635
7635
|
let sessionId = "";
|
|
7636
7636
|
let cwd = "";
|
|
7637
7637
|
let timestamp6 = "";
|
|
7638
7638
|
let name = "";
|
|
7639
7639
|
let commandName = "";
|
|
7640
7640
|
let commandArgs = "";
|
|
7641
|
-
for (const line of
|
|
7641
|
+
for (const line of lines2) {
|
|
7642
7642
|
const entry = safeParse(line);
|
|
7643
7643
|
if (!entry) continue;
|
|
7644
7644
|
sessionId ||= strField(entry, "sessionId");
|
|
@@ -8645,7 +8645,7 @@ function spawnDaemon(reason4) {
|
|
|
8645
8645
|
child.unref();
|
|
8646
8646
|
}
|
|
8647
8647
|
function delay(ms) {
|
|
8648
|
-
return new Promise((
|
|
8648
|
+
return new Promise((resolve22) => setTimeout(resolve22, ms));
|
|
8649
8649
|
}
|
|
8650
8650
|
|
|
8651
8651
|
// src/commands/sessions/daemon/isWindowsCwd.ts
|
|
@@ -8682,10 +8682,10 @@ function gitInvocation(cwd, args) {
|
|
|
8682
8682
|
}
|
|
8683
8683
|
function git2(cwd, args) {
|
|
8684
8684
|
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
8685
|
-
return new Promise((
|
|
8685
|
+
return new Promise((resolve22, reject) => {
|
|
8686
8686
|
execFile2(file, argv, options2, (error, stdout) => {
|
|
8687
8687
|
if (error) reject(error);
|
|
8688
|
-
else
|
|
8688
|
+
else resolve22(stdout.toString());
|
|
8689
8689
|
});
|
|
8690
8690
|
});
|
|
8691
8691
|
}
|
|
@@ -9097,12 +9097,12 @@ async function loadVisibleItems(req) {
|
|
|
9097
9097
|
|
|
9098
9098
|
// src/commands/backlog/web/parseStatusBody.ts
|
|
9099
9099
|
function readBody(req) {
|
|
9100
|
-
return new Promise((
|
|
9100
|
+
return new Promise((resolve22, reject) => {
|
|
9101
9101
|
let body = "";
|
|
9102
9102
|
req.on("data", (chunk) => {
|
|
9103
9103
|
body += chunk.toString();
|
|
9104
9104
|
});
|
|
9105
|
-
req.on("end", () =>
|
|
9105
|
+
req.on("end", () => resolve22(body));
|
|
9106
9106
|
req.on("error", reject);
|
|
9107
9107
|
});
|
|
9108
9108
|
}
|
|
@@ -10586,17 +10586,17 @@ async function stopDaemon() {
|
|
|
10586
10586
|
}
|
|
10587
10587
|
}
|
|
10588
10588
|
function closedBeforeTimeout(socket) {
|
|
10589
|
-
return new Promise((
|
|
10589
|
+
return new Promise((resolve22) => {
|
|
10590
10590
|
const timer = setTimeout(() => {
|
|
10591
10591
|
socket.destroy();
|
|
10592
|
-
|
|
10592
|
+
resolve22(false);
|
|
10593
10593
|
}, STOP_TIMEOUT_MS);
|
|
10594
10594
|
socket.resume();
|
|
10595
10595
|
socket.on("error", () => {
|
|
10596
10596
|
});
|
|
10597
10597
|
socket.once("close", () => {
|
|
10598
10598
|
clearTimeout(timer);
|
|
10599
|
-
|
|
10599
|
+
resolve22(true);
|
|
10600
10600
|
});
|
|
10601
10601
|
});
|
|
10602
10602
|
}
|
|
@@ -10647,8 +10647,8 @@ async function restartWeb(req, res, deps2 = {}) {
|
|
|
10647
10647
|
respondJson(res, 400, { error: "Invalid target" });
|
|
10648
10648
|
return;
|
|
10649
10649
|
}
|
|
10650
|
-
await new Promise((
|
|
10651
|
-
res.once("finish",
|
|
10650
|
+
await new Promise((resolve22) => {
|
|
10651
|
+
res.once("finish", resolve22);
|
|
10652
10652
|
respondJson(res, 200, { ok: true });
|
|
10653
10653
|
});
|
|
10654
10654
|
if (target === "daemon" || target === "both") {
|
|
@@ -11185,8 +11185,8 @@ async function runGhImage(filePath, cwd) {
|
|
|
11185
11185
|
`gh image failed: ${stderr.trim() || err.message || "unknown error"}`
|
|
11186
11186
|
);
|
|
11187
11187
|
}
|
|
11188
|
-
const
|
|
11189
|
-
const markdown =
|
|
11188
|
+
const lines2 = stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
11189
|
+
const markdown = lines2.find((line) => /^!\[.*]\(.+\)$/.test(line)) ?? lines2.find((line) => line.includes("http")) ?? lines2[0];
|
|
11190
11190
|
if (!markdown) throw new Error("gh image produced no output");
|
|
11191
11191
|
return markdown;
|
|
11192
11192
|
}
|
|
@@ -11377,10 +11377,10 @@ async function openDaemonConnection(ws, ctx) {
|
|
|
11377
11377
|
}
|
|
11378
11378
|
}
|
|
11379
11379
|
function relayDaemonLines(conn, ws, repoCwd) {
|
|
11380
|
-
const
|
|
11381
|
-
|
|
11380
|
+
const lines2 = createInterface2({ input: conn });
|
|
11381
|
+
lines2.on("error", () => {
|
|
11382
11382
|
});
|
|
11383
|
-
|
|
11383
|
+
lines2.on("line", (line) => {
|
|
11384
11384
|
if (ws.readyState === ws.OPEN) ws.send(withRepoCwd(line, repoCwd));
|
|
11385
11385
|
});
|
|
11386
11386
|
conn.on("error", () => {
|
|
@@ -11522,7 +11522,7 @@ function firstEnabledIndex(items2) {
|
|
|
11522
11522
|
// src/commands/sessions/web/restartMenu/renderRestartMenu.ts
|
|
11523
11523
|
import chalk59 from "chalk";
|
|
11524
11524
|
function renderRestartMenu(items2, selected) {
|
|
11525
|
-
const
|
|
11525
|
+
const lines2 = [chalk59.bold.cyan("assist \u2014 restart menu")];
|
|
11526
11526
|
items2.forEach((item, i) => {
|
|
11527
11527
|
const active = i === selected;
|
|
11528
11528
|
const pointer = active ? chalk59.cyan("\u276F ") : " ";
|
|
@@ -11531,10 +11531,10 @@ function renderRestartMenu(items2, selected) {
|
|
|
11531
11531
|
let label2 = item.label;
|
|
11532
11532
|
if (item.disabled) label2 = chalk59.dim(label2);
|
|
11533
11533
|
else if (active) label2 = chalk59.cyan.bold(label2);
|
|
11534
|
-
|
|
11534
|
+
lines2.push(`${pointer}${number}${label2}${note}`);
|
|
11535
11535
|
});
|
|
11536
|
-
|
|
11537
|
-
return
|
|
11536
|
+
lines2.push(chalk59.dim("\u2191/\u2193 move \xB7 1-3 jump \xB7 enter select \xB7 esc close"));
|
|
11537
|
+
return lines2.join("\n");
|
|
11538
11538
|
}
|
|
11539
11539
|
|
|
11540
11540
|
// src/commands/sessions/web/restartMenu/createMenuState.ts
|
|
@@ -11660,10 +11660,10 @@ async function connect2() {
|
|
|
11660
11660
|
}
|
|
11661
11661
|
}
|
|
11662
11662
|
function wire(socket) {
|
|
11663
|
-
const
|
|
11664
|
-
|
|
11663
|
+
const lines2 = createInterface3({ input: socket });
|
|
11664
|
+
lines2.on("error", () => {
|
|
11665
11665
|
});
|
|
11666
|
-
|
|
11666
|
+
lines2.on("line", emit);
|
|
11667
11667
|
socket.on("error", () => {
|
|
11668
11668
|
});
|
|
11669
11669
|
socket.on("close", scheduleReconnect);
|
|
@@ -12203,11 +12203,11 @@ async function countRows(client, table) {
|
|
|
12203
12203
|
return rows[0].n;
|
|
12204
12204
|
}
|
|
12205
12205
|
function printSummary(tables, current, incoming) {
|
|
12206
|
-
const
|
|
12206
|
+
const lines2 = tables.map(
|
|
12207
12207
|
(t, i) => ` ${t.name}: ${current[i]} \u2192 ${incoming[i]} rows`
|
|
12208
12208
|
);
|
|
12209
12209
|
console.error(chalk71.bold("\nThis will REPLACE all backlog data:"));
|
|
12210
|
-
console.error(`${
|
|
12210
|
+
console.error(`${lines2.join("\n")}
|
|
12211
12211
|
`);
|
|
12212
12212
|
}
|
|
12213
12213
|
async function confirmReplace(client, tables, incoming, fromStdin) {
|
|
@@ -12600,7 +12600,7 @@ function parsePreviewDecision(line, requestId) {
|
|
|
12600
12600
|
|
|
12601
12601
|
// src/commands/sessions/shared/requestPreviewDecision.ts
|
|
12602
12602
|
function requestPreviewDecision(request) {
|
|
12603
|
-
return new Promise((
|
|
12603
|
+
return new Promise((resolve22, reject) => {
|
|
12604
12604
|
connectToDaemon().then((socket) => {
|
|
12605
12605
|
let settled = false;
|
|
12606
12606
|
const finish = (error, decision) => {
|
|
@@ -12608,7 +12608,7 @@ function requestPreviewDecision(request) {
|
|
|
12608
12608
|
settled = true;
|
|
12609
12609
|
socket.destroy();
|
|
12610
12610
|
if (error) reject(error);
|
|
12611
|
-
else
|
|
12611
|
+
else resolve22(decision);
|
|
12612
12612
|
};
|
|
12613
12613
|
readSocketLines(socket, (line) => {
|
|
12614
12614
|
const incoming = parsePreviewDecision(line, request.requestId);
|
|
@@ -14859,13 +14859,13 @@ function saveCliReads(commands) {
|
|
|
14859
14859
|
);
|
|
14860
14860
|
cachedReads = void 0;
|
|
14861
14861
|
}
|
|
14862
|
-
function findMatch(command,
|
|
14862
|
+
function findMatch(command, lines2) {
|
|
14863
14863
|
const words = command.split(/\s+/);
|
|
14864
14864
|
if (words.length === 0) return void 0;
|
|
14865
|
-
if (
|
|
14865
|
+
if (lines2.includes(words[0])) return words[0];
|
|
14866
14866
|
if (words.length < 2) return void 0;
|
|
14867
14867
|
const prefix2 = `${words[0]} ${words[1]}`;
|
|
14868
|
-
const candidates =
|
|
14868
|
+
const candidates = lines2.filter(
|
|
14869
14869
|
(line) => line === prefix2 || line.startsWith(`${prefix2} `)
|
|
14870
14870
|
);
|
|
14871
14871
|
return candidates.sort((a, b) => b.length - a.length).find((rc) => command === rc || command.startsWith(`${rc} `));
|
|
@@ -15299,12 +15299,12 @@ function hasSubcommands(helpText) {
|
|
|
15299
15299
|
// src/commands/permitCliReads/runHelp.ts
|
|
15300
15300
|
import { exec as exec2 } from "child_process";
|
|
15301
15301
|
function runHelp(args) {
|
|
15302
|
-
return new Promise((
|
|
15302
|
+
return new Promise((resolve22) => {
|
|
15303
15303
|
exec2(
|
|
15304
15304
|
`${args.join(" ")} --help`,
|
|
15305
15305
|
{ encoding: "utf8", timeout: 3e4 },
|
|
15306
15306
|
(_err, stdout, stderr) => {
|
|
15307
|
-
|
|
15307
|
+
resolve22(stdout || stderr || "");
|
|
15308
15308
|
}
|
|
15309
15309
|
);
|
|
15310
15310
|
});
|
|
@@ -15432,14 +15432,14 @@ function formatHuman(cli, commands) {
|
|
|
15432
15432
|
const sorted = [...commands].sort(
|
|
15433
15433
|
(a, b) => a.path.join(" ").localeCompare(b.path.join(" "))
|
|
15434
15434
|
);
|
|
15435
|
-
const
|
|
15435
|
+
const lines2 = [`Discovered ${commands.length} commands for "${cli}":
|
|
15436
15436
|
`];
|
|
15437
15437
|
for (const cmd of sorted) {
|
|
15438
15438
|
const full = `${cli} ${cmd.path.join(" ")}`;
|
|
15439
15439
|
const text17 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
|
|
15440
|
-
|
|
15440
|
+
lines2.push(`${prefix(classifyVerb(cmd.path))}${text17}`);
|
|
15441
15441
|
}
|
|
15442
|
-
return
|
|
15442
|
+
return lines2.join("\n");
|
|
15443
15443
|
}
|
|
15444
15444
|
|
|
15445
15445
|
// src/commands/permitCliReads/parseCached.ts
|
|
@@ -15686,22 +15686,22 @@ function codeCommentConfirm(pin) {
|
|
|
15686
15686
|
return;
|
|
15687
15687
|
}
|
|
15688
15688
|
const original = readFileSync29(state.file, "utf8");
|
|
15689
|
-
const
|
|
15689
|
+
const lines2 = original.split("\n");
|
|
15690
15690
|
const index3 = state.line - 1;
|
|
15691
|
-
if (index3 >
|
|
15691
|
+
if (index3 > lines2.length) {
|
|
15692
15692
|
console.error(
|
|
15693
15693
|
chalk118.red(
|
|
15694
|
-
`Line ${state.line} is beyond the end of ${state.file} (${
|
|
15694
|
+
`Line ${state.line} is beyond the end of ${state.file} (${lines2.length} lines).`
|
|
15695
15695
|
)
|
|
15696
15696
|
);
|
|
15697
15697
|
process.exitCode = 1;
|
|
15698
15698
|
return;
|
|
15699
15699
|
}
|
|
15700
15700
|
const marker = isHashCommentFile(state.file) ? "#" : "//";
|
|
15701
|
-
const indentSource =
|
|
15701
|
+
const indentSource = lines2[index3] ?? "";
|
|
15702
15702
|
const indent2 = indentSource.match(/^\s*/)?.[0] ?? "";
|
|
15703
|
-
|
|
15704
|
-
writeFileSync24(state.file,
|
|
15703
|
+
lines2.splice(index3, 0, `${indent2}${marker} ${state.text}`);
|
|
15704
|
+
writeFileSync24(state.file, lines2.join("\n"));
|
|
15705
15705
|
unlinkSync8(getPinStatePath(pin));
|
|
15706
15706
|
console.log(
|
|
15707
15707
|
chalk118.green(
|
|
@@ -16413,17 +16413,17 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
16413
16413
|
let hasViolation = false;
|
|
16414
16414
|
for (const file of files) {
|
|
16415
16415
|
const content = fs22.readFileSync(file, "utf8");
|
|
16416
|
-
const
|
|
16417
|
-
results.push({ file, lines });
|
|
16418
|
-
if (options2.threshold !== void 0 &&
|
|
16416
|
+
const lines2 = countSloc(content);
|
|
16417
|
+
results.push({ file, lines: lines2 });
|
|
16418
|
+
if (options2.threshold !== void 0 && lines2 > options2.threshold) {
|
|
16419
16419
|
hasViolation = true;
|
|
16420
16420
|
}
|
|
16421
16421
|
}
|
|
16422
16422
|
results.sort((a, b) => b.lines - a.lines);
|
|
16423
|
-
for (const { file, lines } of results) {
|
|
16424
|
-
const exceedsThreshold = options2.threshold !== void 0 &&
|
|
16423
|
+
for (const { file, lines: lines2 } of results) {
|
|
16424
|
+
const exceedsThreshold = options2.threshold !== void 0 && lines2 > options2.threshold;
|
|
16425
16425
|
const color = exceedsThreshold ? chalk127.red : chalk127.white;
|
|
16426
|
-
console.log(`${color(file)} \u2192 ${chalk127.cyan(
|
|
16426
|
+
console.log(`${color(file)} \u2192 ${chalk127.cyan(lines2)} lines`);
|
|
16427
16427
|
}
|
|
16428
16428
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
16429
16429
|
console.log(
|
|
@@ -17010,9 +17010,9 @@ function printCommitsWithFiles(commits2, ignore3, verbose) {
|
|
|
17010
17010
|
}
|
|
17011
17011
|
}
|
|
17012
17012
|
function parseGitLogCommits(output, ignore3, afterDate) {
|
|
17013
|
-
const
|
|
17013
|
+
const lines2 = output.trim().split("\n");
|
|
17014
17014
|
const commitsByDate = /* @__PURE__ */ new Map();
|
|
17015
|
-
for (const line of
|
|
17015
|
+
for (const line of lines2) {
|
|
17016
17016
|
const [date, hash, ...messageParts] = line.split("|");
|
|
17017
17017
|
const message3 = messageParts.join("|");
|
|
17018
17018
|
if (afterDate && date <= afterDate) {
|
|
@@ -18108,12 +18108,12 @@ function isHeaderLine2(line) {
|
|
|
18108
18108
|
return trimmed === "" || trimmed.startsWith("#");
|
|
18109
18109
|
}
|
|
18110
18110
|
function extractShellComments(text17) {
|
|
18111
|
-
const
|
|
18111
|
+
const lines2 = text17.split("\n");
|
|
18112
18112
|
let firstCodeLine = 0;
|
|
18113
|
-
while (firstCodeLine <
|
|
18113
|
+
while (firstCodeLine < lines2.length && isHeaderLine2(lines2[firstCodeLine])) {
|
|
18114
18114
|
firstCodeLine++;
|
|
18115
18115
|
}
|
|
18116
|
-
return extractYamlComments(
|
|
18116
|
+
return extractYamlComments(lines2.slice(firstCodeLine).join("\n"));
|
|
18117
18117
|
}
|
|
18118
18118
|
|
|
18119
18119
|
// src/commands/editHook/introducedComments.ts
|
|
@@ -19424,7 +19424,7 @@ function placedByDaemon() {
|
|
|
19424
19424
|
function seed(worktreePath, clone) {
|
|
19425
19425
|
console.log(`Preparing ${worktreePath}\u2026`);
|
|
19426
19426
|
return new Promise(
|
|
19427
|
-
(
|
|
19427
|
+
(resolve22) => seedWorktree(worktreePath, clone, resolve22)
|
|
19428
19428
|
);
|
|
19429
19429
|
}
|
|
19430
19430
|
async function moveToPrCheckoutTree() {
|
|
@@ -19931,25 +19931,25 @@ function isVisibleText(t) {
|
|
|
19931
19931
|
return /[a-zA-Z]{3,}/.test(t);
|
|
19932
19932
|
}
|
|
19933
19933
|
var isHashtag = (t) => /^#[A-Za-z0-9_]+$/.test(t);
|
|
19934
|
-
function collectRscText(v,
|
|
19934
|
+
function collectRscText(v, resolve22, sink2, seen) {
|
|
19935
19935
|
if (v == null) return;
|
|
19936
19936
|
if (typeof v === "string") {
|
|
19937
19937
|
if (isRscRef(v)) {
|
|
19938
19938
|
if (!seen.has(v)) {
|
|
19939
19939
|
seen.add(v);
|
|
19940
|
-
collectRscText(
|
|
19940
|
+
collectRscText(resolve22(v), resolve22, sink2, seen);
|
|
19941
19941
|
}
|
|
19942
19942
|
} else if (isHashtag(v)) sink2.hashtags.push(v);
|
|
19943
19943
|
else if (isVisibleText(v)) sink2.text.push(v);
|
|
19944
19944
|
return;
|
|
19945
19945
|
}
|
|
19946
19946
|
if (Array.isArray(v)) {
|
|
19947
|
-
for (const x of v) collectRscText(x,
|
|
19947
|
+
for (const x of v) collectRscText(x, resolve22, sink2, seen);
|
|
19948
19948
|
return;
|
|
19949
19949
|
}
|
|
19950
19950
|
if (typeof v === "object") {
|
|
19951
19951
|
for (const val of Object.values(v)) {
|
|
19952
|
-
collectRscText(val,
|
|
19952
|
+
collectRscText(val, resolve22, sink2, seen);
|
|
19953
19953
|
}
|
|
19954
19954
|
}
|
|
19955
19955
|
}
|
|
@@ -19981,7 +19981,7 @@ function visitObjects(root, fn) {
|
|
|
19981
19981
|
}
|
|
19982
19982
|
}
|
|
19983
19983
|
}
|
|
19984
|
-
function buildMentionMap(rows,
|
|
19984
|
+
function buildMentionMap(rows, resolve22) {
|
|
19985
19985
|
const map = /* @__PURE__ */ new Map();
|
|
19986
19986
|
visitObjects(rows, (o) => {
|
|
19987
19987
|
const url = profileActionUrl(o);
|
|
@@ -19989,7 +19989,7 @@ function buildMentionMap(rows, resolve21) {
|
|
|
19989
19989
|
const slug = slugFromProfileUrl(url);
|
|
19990
19990
|
if (!slug || map.has(slug)) return;
|
|
19991
19991
|
const sink2 = { text: [], hashtags: [] };
|
|
19992
|
-
collectRscText(o.children,
|
|
19992
|
+
collectRscText(o.children, resolve22, sink2, /* @__PURE__ */ new Set());
|
|
19993
19993
|
const name = sink2.text.join(" ").replace(/\s+/g, " ").trim();
|
|
19994
19994
|
map.set(slug, name ? { slug, name, url } : { slug, url });
|
|
19995
19995
|
});
|
|
@@ -20075,10 +20075,10 @@ function buildPost(raw, mentionMap, author) {
|
|
|
20075
20075
|
|
|
20076
20076
|
// src/commands/netcap/walkPostRow.ts
|
|
20077
20077
|
var isCommentary = (o) => asObject(o.viewTrackingSpecs)?.viewName === "feed-commentary";
|
|
20078
|
-
function walkPostRow(v,
|
|
20078
|
+
function walkPostRow(v, resolve22, raw) {
|
|
20079
20079
|
if (v == null || typeof v !== "object") return;
|
|
20080
20080
|
if (Array.isArray(v)) {
|
|
20081
|
-
for (const x of v) walkPostRow(x,
|
|
20081
|
+
for (const x of v) walkPostRow(x, resolve22, raw);
|
|
20082
20082
|
return;
|
|
20083
20083
|
}
|
|
20084
20084
|
const o = v;
|
|
@@ -20092,9 +20092,9 @@ function walkPostRow(v, resolve21, raw) {
|
|
|
20092
20092
|
}
|
|
20093
20093
|
if (isCommentary(o)) {
|
|
20094
20094
|
const sink2 = { text: raw.text, hashtags: raw.hashtags };
|
|
20095
|
-
collectRscText(o.children,
|
|
20095
|
+
collectRscText(o.children, resolve22, sink2, /* @__PURE__ */ new Set());
|
|
20096
20096
|
}
|
|
20097
|
-
for (const val of Object.values(o)) walkPostRow(val,
|
|
20097
|
+
for (const val of Object.values(o)) walkPostRow(val, resolve22, raw);
|
|
20098
20098
|
}
|
|
20099
20099
|
|
|
20100
20100
|
// src/commands/netcap/extractLinkedInPosts.ts
|
|
@@ -20108,8 +20108,8 @@ function findCommentaryRows(rows) {
|
|
|
20108
20108
|
}
|
|
20109
20109
|
function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
|
|
20110
20110
|
const rows = parseRscRows(flight);
|
|
20111
|
-
const
|
|
20112
|
-
const mentionMap = buildMentionMap(rows,
|
|
20111
|
+
const resolve22 = makeRscResolver(rows);
|
|
20112
|
+
const mentionMap = buildMentionMap(rows, resolve22);
|
|
20113
20113
|
const posts = [];
|
|
20114
20114
|
for (const id of findCommentaryRows(rows)) {
|
|
20115
20115
|
const raw = {
|
|
@@ -20119,7 +20119,7 @@ function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
|
|
|
20119
20119
|
links: [],
|
|
20120
20120
|
related: []
|
|
20121
20121
|
};
|
|
20122
|
-
walkPostRow(rows[id],
|
|
20122
|
+
walkPostRow(rows[id], resolve22, raw);
|
|
20123
20123
|
const post = buildPost(raw, mentionMap, author);
|
|
20124
20124
|
if (post) posts.push(post);
|
|
20125
20125
|
}
|
|
@@ -20288,9 +20288,9 @@ function extractVoyagerPosts(body) {
|
|
|
20288
20288
|
|
|
20289
20289
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
20290
20290
|
function captureEntries(captureFile) {
|
|
20291
|
-
const
|
|
20291
|
+
const lines2 = readFileSync39(captureFile, "utf8").split("\n").filter(Boolean);
|
|
20292
20292
|
const entries = [];
|
|
20293
|
-
for (const line of
|
|
20293
|
+
for (const line of lines2) {
|
|
20294
20294
|
let entry;
|
|
20295
20295
|
try {
|
|
20296
20296
|
entry = JSON.parse(line);
|
|
@@ -20730,11 +20730,11 @@ function findWallOfText(body) {
|
|
|
20730
20730
|
function splitParagraphs(body) {
|
|
20731
20731
|
const paragraphs = [];
|
|
20732
20732
|
let section3 = "(intro)";
|
|
20733
|
-
let
|
|
20733
|
+
let lines2 = [];
|
|
20734
20734
|
const flush = () => {
|
|
20735
|
-
if (
|
|
20736
|
-
paragraphs.push({ section: section3, lines });
|
|
20737
|
-
|
|
20735
|
+
if (lines2.length > 0) {
|
|
20736
|
+
paragraphs.push({ section: section3, lines: lines2 });
|
|
20737
|
+
lines2 = [];
|
|
20738
20738
|
}
|
|
20739
20739
|
};
|
|
20740
20740
|
for (const line of body.split("\n")) {
|
|
@@ -20745,17 +20745,17 @@ function splitParagraphs(body) {
|
|
|
20745
20745
|
} else if (line.trim() === "") {
|
|
20746
20746
|
flush();
|
|
20747
20747
|
} else {
|
|
20748
|
-
|
|
20748
|
+
lines2.push(line);
|
|
20749
20749
|
}
|
|
20750
20750
|
}
|
|
20751
20751
|
flush();
|
|
20752
20752
|
return paragraphs;
|
|
20753
20753
|
}
|
|
20754
|
-
function isWallOfText(
|
|
20755
|
-
if (
|
|
20754
|
+
function isWallOfText(lines2) {
|
|
20755
|
+
if (lines2.some(isListLine)) {
|
|
20756
20756
|
return false;
|
|
20757
20757
|
}
|
|
20758
|
-
const text17 =
|
|
20758
|
+
const text17 = lines2.join(" ").trim();
|
|
20759
20759
|
return text17.length > MAX_PARAGRAPH_CHARS || countSentences(text17) > MAX_PARAGRAPH_SENTENCES;
|
|
20760
20760
|
}
|
|
20761
20761
|
function countSentences(paragraph) {
|
|
@@ -22198,9 +22198,9 @@ function parseRefactorYml() {
|
|
|
22198
22198
|
}
|
|
22199
22199
|
const content = fs24.readFileSync(REFACTOR_YML_PATH, "utf8");
|
|
22200
22200
|
const entries = [];
|
|
22201
|
-
const
|
|
22201
|
+
const lines2 = content.split("\n");
|
|
22202
22202
|
let currentEntry = {};
|
|
22203
|
-
for (const line of
|
|
22203
|
+
for (const line of lines2) {
|
|
22204
22204
|
const trimmed = line.trim();
|
|
22205
22205
|
if (trimmed.startsWith("- file:")) {
|
|
22206
22206
|
if (currentEntry.file) {
|
|
@@ -22273,7 +22273,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES) {
|
|
|
22273
22273
|
|
|
22274
22274
|
// src/commands/refactor/check/index.ts
|
|
22275
22275
|
function runScript(script, cwd) {
|
|
22276
|
-
return new Promise((
|
|
22276
|
+
return new Promise((resolve22) => {
|
|
22277
22277
|
const child = spawn6("npm", ["run", script], {
|
|
22278
22278
|
stdio: "pipe",
|
|
22279
22279
|
shell: true,
|
|
@@ -22287,7 +22287,7 @@ function runScript(script, cwd) {
|
|
|
22287
22287
|
output += data.toString();
|
|
22288
22288
|
});
|
|
22289
22289
|
child.on("close", (code) => {
|
|
22290
|
-
|
|
22290
|
+
resolve22({ script, code: code ?? 1, output });
|
|
22291
22291
|
});
|
|
22292
22292
|
});
|
|
22293
22293
|
}
|
|
@@ -22788,22 +22788,22 @@ function formatImportLine(imp) {
|
|
|
22788
22788
|
|
|
22789
22789
|
// src/commands/refactor/extract/buildDestinationContent.ts
|
|
22790
22790
|
function buildDestinationContent(functionTexts, imports, sourceRelativePath, sourceImportNames) {
|
|
22791
|
-
const
|
|
22791
|
+
const lines2 = [];
|
|
22792
22792
|
for (const imp of imports) {
|
|
22793
|
-
|
|
22793
|
+
lines2.push(formatImportLine(imp));
|
|
22794
22794
|
}
|
|
22795
22795
|
if (sourceImportNames.length > 0) {
|
|
22796
|
-
|
|
22796
|
+
lines2.push(
|
|
22797
22797
|
`import { ${sourceImportNames.join(", ")} } from "${sourceRelativePath}";`
|
|
22798
22798
|
);
|
|
22799
22799
|
}
|
|
22800
|
-
if (
|
|
22800
|
+
if (lines2.length > 0) lines2.push("");
|
|
22801
22801
|
for (let i = 0; i < functionTexts.length; i++) {
|
|
22802
|
-
if (i > 0)
|
|
22803
|
-
|
|
22802
|
+
if (i > 0) lines2.push("");
|
|
22803
|
+
lines2.push(functionTexts[i]);
|
|
22804
22804
|
}
|
|
22805
|
-
|
|
22806
|
-
return
|
|
22805
|
+
lines2.push("");
|
|
22806
|
+
return lines2.join("\n");
|
|
22807
22807
|
}
|
|
22808
22808
|
|
|
22809
22809
|
// src/commands/refactor/extract/getRelativeImportPath.ts
|
|
@@ -23414,9 +23414,9 @@ function groupReferences(symbol, cwd) {
|
|
|
23414
23414
|
const grouped = /* @__PURE__ */ new Map();
|
|
23415
23415
|
for (const ref of refs) {
|
|
23416
23416
|
const refFile = path50.relative(cwd, ref.getSourceFile().getFilePath());
|
|
23417
|
-
const
|
|
23418
|
-
if (!grouped.has(refFile)) grouped.set(refFile,
|
|
23419
|
-
|
|
23417
|
+
const lines2 = grouped.get(refFile) ?? [];
|
|
23418
|
+
if (!grouped.has(refFile)) grouped.set(refFile, lines2);
|
|
23419
|
+
lines2.push(ref.getStartLineNumber());
|
|
23420
23420
|
}
|
|
23421
23421
|
return grouped;
|
|
23422
23422
|
}
|
|
@@ -23436,9 +23436,9 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
23436
23436
|
chalk189.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
23437
23437
|
`)
|
|
23438
23438
|
);
|
|
23439
|
-
for (const [refFile,
|
|
23439
|
+
for (const [refFile, lines2] of grouped) {
|
|
23440
23440
|
console.log(
|
|
23441
|
-
` ${chalk189.dim(refFile)}: lines ${chalk189.cyan(
|
|
23441
|
+
` ${chalk189.dim(refFile)}: lines ${chalk189.cyan(lines2.join(", "))}`
|
|
23442
23442
|
);
|
|
23443
23443
|
}
|
|
23444
23444
|
if (options2.apply) {
|
|
@@ -23879,12 +23879,12 @@ function headerFor(c) {
|
|
|
23879
23879
|
return tags ? `### ${location} [${tags}]` : `### ${location}`;
|
|
23880
23880
|
}
|
|
23881
23881
|
function formatThread(thread) {
|
|
23882
|
-
const
|
|
23882
|
+
const lines2 = [
|
|
23883
23883
|
headerFor(thread.root),
|
|
23884
23884
|
`**${thread.root.author}**: ${thread.root.body.trim()}`,
|
|
23885
23885
|
...thread.replies.map((r) => `**${r.author}** (reply): ${r.body.trim()}`)
|
|
23886
23886
|
];
|
|
23887
|
-
return
|
|
23887
|
+
return lines2.join("\n\n");
|
|
23888
23888
|
}
|
|
23889
23889
|
var INTRO = `The PR already has the review comments below (including resolved and outdated threads). Avoid re-raising findings that a prior comment substantively covers.`;
|
|
23890
23890
|
function formatPriorComments(comments3) {
|
|
@@ -24191,13 +24191,13 @@ function summariseSynthesis(markdown) {
|
|
|
24191
24191
|
return { summary: extractSummary(markdown), totals, findingCount };
|
|
24192
24192
|
}
|
|
24193
24193
|
function formatSynthesisSummary(summary) {
|
|
24194
|
-
const
|
|
24194
|
+
const lines2 = [];
|
|
24195
24195
|
const { totals, findingCount } = summary;
|
|
24196
|
-
|
|
24196
|
+
lines2.push(
|
|
24197
24197
|
`Findings: ${findingCount} (blocker ${totals.blocker}, major ${totals.major}, minor ${totals.minor}, nit ${totals.nit})`
|
|
24198
24198
|
);
|
|
24199
|
-
if (summary.summary)
|
|
24200
|
-
return
|
|
24199
|
+
if (summary.summary) lines2.push("", summary.summary);
|
|
24200
|
+
return lines2.join("\n");
|
|
24201
24201
|
}
|
|
24202
24202
|
|
|
24203
24203
|
// src/commands/review/buildReviewSummary.ts
|
|
@@ -24208,12 +24208,12 @@ function formatFindingLine(finding) {
|
|
|
24208
24208
|
function buildReviewSummary(markdown) {
|
|
24209
24209
|
const summary = summariseSynthesis(markdown);
|
|
24210
24210
|
const findings = parseFindings(markdown);
|
|
24211
|
-
const
|
|
24211
|
+
const lines2 = ["## Code review summary", "", formatSynthesisSummary(summary)];
|
|
24212
24212
|
if (findings.length > 0) {
|
|
24213
|
-
|
|
24214
|
-
for (const finding of findings)
|
|
24213
|
+
lines2.push("", "### Findings", "");
|
|
24214
|
+
for (const finding of findings) lines2.push(formatFindingLine(finding));
|
|
24215
24215
|
}
|
|
24216
|
-
return
|
|
24216
|
+
return lines2.join("\n");
|
|
24217
24217
|
}
|
|
24218
24218
|
|
|
24219
24219
|
// src/commands/review/sanitiseReviewerNames.ts
|
|
@@ -24224,13 +24224,13 @@ function sanitiseReviewerNames(value) {
|
|
|
24224
24224
|
|
|
24225
24225
|
// src/commands/review/postFindings.ts
|
|
24226
24226
|
function buildCommentBody(finding) {
|
|
24227
|
-
const
|
|
24227
|
+
const lines2 = [];
|
|
24228
24228
|
const severityLabel = finding.severity ?? "finding";
|
|
24229
|
-
|
|
24230
|
-
if (finding.impact)
|
|
24229
|
+
lines2.push(`**${severityLabel}: ${finding.title}**`);
|
|
24230
|
+
if (finding.impact) lines2.push("", `Impact: ${finding.impact}`);
|
|
24231
24231
|
if (finding.recommendation)
|
|
24232
|
-
|
|
24233
|
-
return sanitiseReviewerNames(
|
|
24232
|
+
lines2.push("", `Recommendation: ${finding.recommendation}`);
|
|
24233
|
+
return sanitiseReviewerNames(lines2.join("\n"));
|
|
24234
24234
|
}
|
|
24235
24235
|
function postFindings(findings) {
|
|
24236
24236
|
let posted = 0;
|
|
@@ -24329,10 +24329,10 @@ function buildDiffLineIndex(diff3) {
|
|
|
24329
24329
|
|
|
24330
24330
|
// src/commands/review/partitionFindingsByDiff.ts
|
|
24331
24331
|
function isWithinDiff(finding, index3) {
|
|
24332
|
-
const
|
|
24333
|
-
if (!
|
|
24334
|
-
if (!
|
|
24335
|
-
if (finding.startLine !== void 0 && !
|
|
24332
|
+
const lines2 = index3.get(finding.file);
|
|
24333
|
+
if (!lines2) return false;
|
|
24334
|
+
if (!lines2.has(finding.line)) return false;
|
|
24335
|
+
if (finding.startLine !== void 0 && !lines2.has(finding.startLine)) {
|
|
24336
24336
|
return false;
|
|
24337
24337
|
}
|
|
24338
24338
|
return true;
|
|
@@ -24723,8 +24723,8 @@ function indent(text17) {
|
|
|
24723
24723
|
return text17.split(/\r?\n/).map((line) => ` ${line}`);
|
|
24724
24724
|
}
|
|
24725
24725
|
function tailLines(text17, maxLines) {
|
|
24726
|
-
const
|
|
24727
|
-
return
|
|
24726
|
+
const lines2 = text17.split(/\r?\n/);
|
|
24727
|
+
return lines2.length <= maxLines ? text17 : lines2.slice(-maxLines).join("\n");
|
|
24728
24728
|
}
|
|
24729
24729
|
function isFastFail(input) {
|
|
24730
24730
|
return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
|
|
@@ -25096,12 +25096,12 @@ function onCloseResult(ctx, code) {
|
|
|
25096
25096
|
return { ...closed, stderr: ctx.stderr.value, stdout: ctx.stdout.value };
|
|
25097
25097
|
}
|
|
25098
25098
|
function waitForChildExit(ctx) {
|
|
25099
|
-
return new Promise((
|
|
25099
|
+
return new Promise((resolve22) => {
|
|
25100
25100
|
let settled = false;
|
|
25101
25101
|
const settle = (result) => {
|
|
25102
25102
|
if (settled) return;
|
|
25103
25103
|
settled = true;
|
|
25104
|
-
|
|
25104
|
+
resolve22(result);
|
|
25105
25105
|
};
|
|
25106
25106
|
ctx.child.on("error", (err) => settle(onErrorResult(ctx, err)));
|
|
25107
25107
|
ctx.child.on("close", (code) => settle(onCloseResult(ctx, code)));
|
|
@@ -25756,13 +25756,13 @@ function formatEvent(event) {
|
|
|
25756
25756
|
const abbrev = levelAbbrev(event.Level);
|
|
25757
25757
|
const ts8 = chalk198.dim(formatTimestamp(event.Timestamp));
|
|
25758
25758
|
const msg = renderMessage(event);
|
|
25759
|
-
const
|
|
25759
|
+
const lines2 = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
25760
25760
|
if (event.Exception) {
|
|
25761
25761
|
for (const line of event.Exception.split("\n")) {
|
|
25762
|
-
|
|
25762
|
+
lines2.push(chalk198.red(` ${line}`));
|
|
25763
25763
|
}
|
|
25764
25764
|
}
|
|
25765
|
-
return
|
|
25765
|
+
return lines2.join("\n");
|
|
25766
25766
|
}
|
|
25767
25767
|
|
|
25768
25768
|
// src/commands/seq/parseRelativeTime.ts
|
|
@@ -26201,9 +26201,9 @@ function createReadlineInterface() {
|
|
|
26201
26201
|
});
|
|
26202
26202
|
}
|
|
26203
26203
|
function askQuestion(rl, question) {
|
|
26204
|
-
return new Promise((
|
|
26204
|
+
return new Promise((resolve22) => {
|
|
26205
26205
|
rl.question(question, (answer) => {
|
|
26206
|
-
|
|
26206
|
+
resolve22(answer.trim());
|
|
26207
26207
|
});
|
|
26208
26208
|
});
|
|
26209
26209
|
}
|
|
@@ -26423,13 +26423,13 @@ function extractSpeaker(fullText) {
|
|
|
26423
26423
|
function isTextLine(line) {
|
|
26424
26424
|
return !!line.trim() && !line.includes("-->");
|
|
26425
26425
|
}
|
|
26426
|
-
function scanTextLines(
|
|
26426
|
+
function scanTextLines(lines2, start3) {
|
|
26427
26427
|
let i = start3;
|
|
26428
|
-
while (i <
|
|
26429
|
-
return { texts:
|
|
26428
|
+
while (i < lines2.length && isTextLine(lines2[i])) i++;
|
|
26429
|
+
return { texts: lines2.slice(start3, i).map((l) => l.trim()), end: i };
|
|
26430
26430
|
}
|
|
26431
|
-
function collectTextLines(
|
|
26432
|
-
const { texts, end } = scanTextLines(
|
|
26431
|
+
function collectTextLines(lines2, startIndex) {
|
|
26432
|
+
const { texts, end } = scanTextLines(lines2, startIndex);
|
|
26433
26433
|
return { text: texts.join(" "), nextIndex: end };
|
|
26434
26434
|
}
|
|
26435
26435
|
function parseTimestampLine(line) {
|
|
@@ -26440,30 +26440,30 @@ function buildCue(startMs, endMs, fullText) {
|
|
|
26440
26440
|
const { speaker, text: text17 } = extractSpeaker(fullText);
|
|
26441
26441
|
return text17 ? { startMs, endMs, speaker, text: text17 } : null;
|
|
26442
26442
|
}
|
|
26443
|
-
function parseCueLine(
|
|
26444
|
-
const { startMs, endMs } = parseTimestampLine(
|
|
26445
|
-
const { text: text17, nextIndex: nextIndex2 } = collectTextLines(
|
|
26443
|
+
function parseCueLine(lines2, i) {
|
|
26444
|
+
const { startMs, endMs } = parseTimestampLine(lines2[i]);
|
|
26445
|
+
const { text: text17, nextIndex: nextIndex2 } = collectTextLines(lines2, i + 1);
|
|
26446
26446
|
return { cue: buildCue(startMs, endMs, text17), nextIndex: nextIndex2 };
|
|
26447
26447
|
}
|
|
26448
26448
|
function isCueSeparator(line) {
|
|
26449
26449
|
return line.trim().includes("-->");
|
|
26450
26450
|
}
|
|
26451
|
-
function skipHeader(
|
|
26451
|
+
function skipHeader(lines2) {
|
|
26452
26452
|
let i = 0;
|
|
26453
|
-
while (i <
|
|
26453
|
+
while (i < lines2.length && !isCueSeparator(lines2[i])) i++;
|
|
26454
26454
|
return i;
|
|
26455
26455
|
}
|
|
26456
|
-
function processLine(cues,
|
|
26457
|
-
if (!isCueSeparator(
|
|
26458
|
-
const { cue, nextIndex: nextIndex2 } = parseCueLine(
|
|
26456
|
+
function processLine(cues, lines2, i) {
|
|
26457
|
+
if (!isCueSeparator(lines2[i])) return i + 1;
|
|
26458
|
+
const { cue, nextIndex: nextIndex2 } = parseCueLine(lines2, i);
|
|
26459
26459
|
if (cue) cues.push(cue);
|
|
26460
26460
|
return nextIndex2;
|
|
26461
26461
|
}
|
|
26462
26462
|
function parseVtt(content) {
|
|
26463
26463
|
const cues = [];
|
|
26464
|
-
const
|
|
26465
|
-
let i = skipHeader(
|
|
26466
|
-
while (i <
|
|
26464
|
+
const lines2 = content.split(/\r?\n/);
|
|
26465
|
+
let i = skipHeader(lines2);
|
|
26466
|
+
while (i < lines2.length) i = processLine(cues, lines2, i);
|
|
26467
26467
|
return cues;
|
|
26468
26468
|
}
|
|
26469
26469
|
|
|
@@ -26688,8 +26688,8 @@ function logs(options2) {
|
|
|
26688
26688
|
console.log("Voice log is empty");
|
|
26689
26689
|
return;
|
|
26690
26690
|
}
|
|
26691
|
-
const
|
|
26692
|
-
for (const line of
|
|
26691
|
+
const lines2 = content.split("\n").slice(-count8);
|
|
26692
|
+
for (const line of lines2) {
|
|
26693
26693
|
try {
|
|
26694
26694
|
const event = JSON.parse(line);
|
|
26695
26695
|
const time = event.timestamp?.slice(11, 19) ?? "";
|
|
@@ -26837,8 +26837,8 @@ function isProcessAlive3(pid) {
|
|
|
26837
26837
|
}
|
|
26838
26838
|
function readRecentLogs(count8) {
|
|
26839
26839
|
if (!existsSync56(voicePaths.log)) return [];
|
|
26840
|
-
const
|
|
26841
|
-
return
|
|
26840
|
+
const lines2 = readFileSync46(voicePaths.log, "utf8").trim().split("\n");
|
|
26841
|
+
return lines2.slice(-count8);
|
|
26842
26842
|
}
|
|
26843
26843
|
function status2() {
|
|
26844
26844
|
if (!existsSync56(voicePaths.pid)) {
|
|
@@ -26945,6 +26945,152 @@ function registerVoice(program2) {
|
|
|
26945
26945
|
configHelp(voiceCommand, voiceConfigHelp);
|
|
26946
26946
|
}
|
|
26947
26947
|
|
|
26948
|
+
// src/commands/watch/readBuiltVersion.ts
|
|
26949
|
+
import { join as join67 } from "path";
|
|
26950
|
+
|
|
26951
|
+
// src/commands/watch/resolveUpstream.ts
|
|
26952
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
26953
|
+
function runGit2(args, cwd) {
|
|
26954
|
+
return execFileSync10("git", args, {
|
|
26955
|
+
encoding: "utf8",
|
|
26956
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
26957
|
+
cwd
|
|
26958
|
+
}).trim();
|
|
26959
|
+
}
|
|
26960
|
+
function resolveUpstream(cwd) {
|
|
26961
|
+
try {
|
|
26962
|
+
runGit2(["rev-parse", "--is-inside-work-tree"], cwd);
|
|
26963
|
+
} catch {
|
|
26964
|
+
throw new Error(
|
|
26965
|
+
"not a git repository \u2014 run assist watch wait from inside a repo"
|
|
26966
|
+
);
|
|
26967
|
+
}
|
|
26968
|
+
let branch2;
|
|
26969
|
+
try {
|
|
26970
|
+
branch2 = runGit2(["symbolic-ref", "--quiet", "--short", "HEAD"], cwd);
|
|
26971
|
+
} catch {
|
|
26972
|
+
throw new Error(
|
|
26973
|
+
"HEAD is detached \u2014 check out a branch before waiting on its upstream"
|
|
26974
|
+
);
|
|
26975
|
+
}
|
|
26976
|
+
try {
|
|
26977
|
+
return {
|
|
26978
|
+
branch: branch2,
|
|
26979
|
+
upstream: runGit2(
|
|
26980
|
+
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
26981
|
+
cwd
|
|
26982
|
+
)
|
|
26983
|
+
};
|
|
26984
|
+
} catch {
|
|
26985
|
+
throw new Error(
|
|
26986
|
+
`branch "${branch2}" has no upstream \u2014 set one with: git push -u origin ${branch2}`
|
|
26987
|
+
);
|
|
26988
|
+
}
|
|
26989
|
+
}
|
|
26990
|
+
|
|
26991
|
+
// src/commands/watch/readBuiltVersion.ts
|
|
26992
|
+
function readBuiltVersion(cwd) {
|
|
26993
|
+
try {
|
|
26994
|
+
const root = runGit2(["rev-parse", "--show-toplevel"], cwd);
|
|
26995
|
+
return readPackageJson(join67(root, "package.json")).version ?? "unknown";
|
|
26996
|
+
} catch {
|
|
26997
|
+
return "unknown";
|
|
26998
|
+
}
|
|
26999
|
+
}
|
|
27000
|
+
|
|
27001
|
+
// src/commands/watch/readRecentCommits.ts
|
|
27002
|
+
function readRecentCommits(count8 = 10, cwd) {
|
|
27003
|
+
const output = runGit2(
|
|
27004
|
+
["log", `-${count8}`, "--pretty=format:%H%x09%h%x09%ar%x09%s"],
|
|
27005
|
+
cwd
|
|
27006
|
+
);
|
|
27007
|
+
if (!output) return [];
|
|
27008
|
+
return output.split("\n").map((line) => {
|
|
27009
|
+
const [sha, short2, when, ...subject] = line.split(" ");
|
|
27010
|
+
return { sha, short: short2, when, subject: subject.join(" ") };
|
|
27011
|
+
});
|
|
27012
|
+
}
|
|
27013
|
+
|
|
27014
|
+
// src/commands/watch/renderWatchReport.ts
|
|
27015
|
+
var escapeCell = (text17) => text17.replaceAll("|", String.raw`\|`);
|
|
27016
|
+
function renderWatchReport({
|
|
27017
|
+
version: version2,
|
|
27018
|
+
commits: commits2,
|
|
27019
|
+
newShas,
|
|
27020
|
+
restarts
|
|
27021
|
+
}) {
|
|
27022
|
+
const isNew = new Set(newShas);
|
|
27023
|
+
const lines2 = [`**Version** ${version2}`, ""];
|
|
27024
|
+
if (commits2.length === 0) {
|
|
27025
|
+
lines2.push("_no commits_");
|
|
27026
|
+
} else {
|
|
27027
|
+
lines2.push("| SHA | When | Subject |", "| --- | --- | --- |");
|
|
27028
|
+
for (const commit2 of commits2) {
|
|
27029
|
+
const marker = isNew.has(commit2.sha) ? " \u2190 new" : "";
|
|
27030
|
+
lines2.push(
|
|
27031
|
+
`| \`${commit2.short}\` | ${commit2.when} | ${escapeCell(commit2.subject)}${marker} |`
|
|
27032
|
+
);
|
|
27033
|
+
}
|
|
27034
|
+
}
|
|
27035
|
+
lines2.push("", "**Restarts**", "");
|
|
27036
|
+
lines2.push(
|
|
27037
|
+
...restarts.length === 0 ? ["- none needed"] : restarts.map((restart) => `- ${restart}`)
|
|
27038
|
+
);
|
|
27039
|
+
return lines2.join("\n");
|
|
27040
|
+
}
|
|
27041
|
+
|
|
27042
|
+
// src/commands/watch/restartAdvice.ts
|
|
27043
|
+
var webUiPrefix = "src/commands/sessions/web/ui/";
|
|
27044
|
+
var sessionsPrefix = "src/commands/sessions/";
|
|
27045
|
+
var rules = [
|
|
27046
|
+
{
|
|
27047
|
+
matches: (path71) => path71.startsWith(webUiPrefix),
|
|
27048
|
+
advice: "restart the web server, then hard-reload the browser tab"
|
|
27049
|
+
},
|
|
27050
|
+
{
|
|
27051
|
+
matches: (path71) => path71.startsWith(sessionsPrefix) && !path71.startsWith(webUiPrefix),
|
|
27052
|
+
advice: "restart the daemon"
|
|
27053
|
+
}
|
|
27054
|
+
];
|
|
27055
|
+
function restartAdvice(paths) {
|
|
27056
|
+
return rules.filter((rule) => paths.some(rule.matches)).map((rule) => rule.advice);
|
|
27057
|
+
}
|
|
27058
|
+
|
|
27059
|
+
// src/commands/watch/buildWatchReport.ts
|
|
27060
|
+
var lines = (output) => output.split("\n").filter((line) => line.length > 0);
|
|
27061
|
+
function buildWatchReport(from, cwd) {
|
|
27062
|
+
const range = from ? `${from}..HEAD` : void 0;
|
|
27063
|
+
return renderWatchReport({
|
|
27064
|
+
version: readBuiltVersion(cwd),
|
|
27065
|
+
commits: readRecentCommits(10, cwd),
|
|
27066
|
+
newShas: range ? lines(runGit2(["rev-list", range], cwd)) : [],
|
|
27067
|
+
restarts: restartAdvice(
|
|
27068
|
+
range ? lines(runGit2(["diff", "--name-only", range], cwd)) : []
|
|
27069
|
+
)
|
|
27070
|
+
});
|
|
27071
|
+
}
|
|
27072
|
+
|
|
27073
|
+
// src/commands/watch/gitFailureReason.ts
|
|
27074
|
+
function gitFailureReason(error) {
|
|
27075
|
+
const streams = error;
|
|
27076
|
+
for (const stream of [streams?.stderr, streams?.stdout]) {
|
|
27077
|
+
const text17 = stream == null ? "" : String(stream).trim();
|
|
27078
|
+
if (text17) return text17;
|
|
27079
|
+
}
|
|
27080
|
+
const message3 = error instanceof Error ? error.message : String(error);
|
|
27081
|
+
return message3.trim() || "git failed without reporting a reason";
|
|
27082
|
+
}
|
|
27083
|
+
|
|
27084
|
+
// src/commands/watch/watchReport.ts
|
|
27085
|
+
function watchReport(options2) {
|
|
27086
|
+
try {
|
|
27087
|
+
console.log(buildWatchReport(options2.from));
|
|
27088
|
+
} catch (error) {
|
|
27089
|
+
console.error(`cannot build the report: ${gitFailureReason(error)}`);
|
|
27090
|
+
process.exit(1);
|
|
27091
|
+
}
|
|
27092
|
+
}
|
|
27093
|
+
|
|
26948
27094
|
// src/commands/watch/describeOutcome.ts
|
|
26949
27095
|
var short = (sha) => sha.slice(0, 7);
|
|
26950
27096
|
function describeOutcome(outcome) {
|
|
@@ -26997,72 +27143,248 @@ function parseDuration(value) {
|
|
|
26997
27143
|
return amount * UNIT_MS[match[2]];
|
|
26998
27144
|
}
|
|
26999
27145
|
|
|
27000
|
-
// src/commands/watch/
|
|
27001
|
-
function
|
|
27002
|
-
|
|
27003
|
-
|
|
27004
|
-
|
|
27005
|
-
|
|
27146
|
+
// src/commands/watch/parseWatchDurations.ts
|
|
27147
|
+
function parseOrExit(value) {
|
|
27148
|
+
try {
|
|
27149
|
+
return parseDuration(value);
|
|
27150
|
+
} catch (error) {
|
|
27151
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
27152
|
+
return process.exit(1);
|
|
27006
27153
|
}
|
|
27007
|
-
|
|
27008
|
-
|
|
27154
|
+
}
|
|
27155
|
+
function parseWatchDurations(interval, timeout) {
|
|
27156
|
+
return {
|
|
27157
|
+
intervalMs: parseOrExit(interval),
|
|
27158
|
+
timeoutMs: timeout.trim() === "none" ? void 0 : parseOrExit(timeout)
|
|
27159
|
+
};
|
|
27009
27160
|
}
|
|
27010
27161
|
|
|
27011
|
-
// src/commands/watch/
|
|
27012
|
-
|
|
27013
|
-
function
|
|
27014
|
-
|
|
27015
|
-
|
|
27016
|
-
|
|
27017
|
-
|
|
27018
|
-
|
|
27162
|
+
// src/commands/watch/pullFastForward.ts
|
|
27163
|
+
var STASH_MESSAGE = "assist watch";
|
|
27164
|
+
function attemptGit(args, cwd) {
|
|
27165
|
+
try {
|
|
27166
|
+
runGit2(args, cwd);
|
|
27167
|
+
return { ok: true };
|
|
27168
|
+
} catch (error) {
|
|
27169
|
+
return { ok: false, reason: gitFailureReason(error) };
|
|
27170
|
+
}
|
|
27019
27171
|
}
|
|
27020
|
-
function
|
|
27172
|
+
function fastForwarded(cwd) {
|
|
27173
|
+
return { kind: "fast-forwarded", sha: runGit2(["rev-parse", "@"], cwd) };
|
|
27174
|
+
}
|
|
27175
|
+
function operationInProgress(cwd) {
|
|
27176
|
+
return ["MERGE_HEAD", "REBASE_HEAD"].some(
|
|
27177
|
+
(ref) => attemptGit(["rev-parse", "--verify", "--quiet", ref], cwd).ok
|
|
27178
|
+
);
|
|
27179
|
+
}
|
|
27180
|
+
function headMatchesUpstream(cwd) {
|
|
27021
27181
|
try {
|
|
27022
|
-
runGit2(["rev-parse", "
|
|
27182
|
+
return runGit2(["rev-parse", "@"], cwd) === runGit2(["rev-parse", "@{u}"], cwd);
|
|
27023
27183
|
} catch {
|
|
27024
|
-
|
|
27025
|
-
"not a git repository \u2014 run assist watch wait from inside a repo"
|
|
27026
|
-
);
|
|
27184
|
+
return false;
|
|
27027
27185
|
}
|
|
27028
|
-
|
|
27186
|
+
}
|
|
27187
|
+
function behindUpstream(cwd) {
|
|
27188
|
+
return attemptGit(["merge-base", "--is-ancestor", "@", "@{u}"], cwd).ok;
|
|
27189
|
+
}
|
|
27190
|
+
function stashDirtyTree(cwd) {
|
|
27191
|
+
let dirty;
|
|
27029
27192
|
try {
|
|
27030
|
-
|
|
27031
|
-
} catch {
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27193
|
+
dirty = runGit2(["status", "--porcelain"], cwd) !== "";
|
|
27194
|
+
} catch (error) {
|
|
27195
|
+
return { ok: false, reason: gitFailureReason(error) };
|
|
27196
|
+
}
|
|
27197
|
+
if (!dirty) return { ok: true, stashed: false };
|
|
27198
|
+
const push = attemptGit(
|
|
27199
|
+
["stash", "push", "--include-untracked", "--message", STASH_MESSAGE],
|
|
27200
|
+
cwd
|
|
27201
|
+
);
|
|
27202
|
+
return push.ok ? { ok: true, stashed: true } : push;
|
|
27203
|
+
}
|
|
27204
|
+
function mergeBehindBranch(cwd) {
|
|
27205
|
+
const stash = stashDirtyTree(cwd);
|
|
27206
|
+
if (!stash.ok) return { kind: "blocked", reason: stash.reason };
|
|
27207
|
+
const merge = attemptGit(["merge", "--ff-only", "@{u}"], cwd);
|
|
27208
|
+
const restore2 = stash.stashed ? attemptGit(["stash", "pop"], cwd) : { ok: true };
|
|
27209
|
+
if (!merge.ok) return { kind: "blocked", reason: merge.reason };
|
|
27210
|
+
if (!restore2.ok) return { kind: "blocked", reason: restore2.reason };
|
|
27211
|
+
return fastForwarded(cwd);
|
|
27212
|
+
}
|
|
27213
|
+
function pullFastForward(cwd) {
|
|
27214
|
+
const pull = attemptGit(["pull", "--ff-only"], cwd);
|
|
27215
|
+
if (pull.ok) return fastForwarded(cwd);
|
|
27216
|
+
if (operationInProgress(cwd)) return { kind: "blocked", reason: pull.reason };
|
|
27217
|
+
if (headMatchesUpstream(cwd)) return fastForwarded(cwd);
|
|
27218
|
+
if (!behindUpstream(cwd)) return { kind: "blocked", reason: pull.reason };
|
|
27219
|
+
return mergeBehindBranch(cwd);
|
|
27220
|
+
}
|
|
27221
|
+
|
|
27222
|
+
// src/commands/watch/runWatchBuild.ts
|
|
27223
|
+
import { resolve as resolve17 } from "path";
|
|
27224
|
+
|
|
27225
|
+
// src/commands/run/findRunConfig.ts
|
|
27226
|
+
function exitNoRunConfigs() {
|
|
27227
|
+
console.error("No run configurations found in assist.yml");
|
|
27228
|
+
process.exit(1);
|
|
27229
|
+
}
|
|
27230
|
+
function exitWithConfigNotFound(name, configs) {
|
|
27231
|
+
console.error(`No run configuration found with name: ${name}`);
|
|
27232
|
+
console.error("Available configurations:");
|
|
27233
|
+
for (const r of configs) {
|
|
27234
|
+
console.error(` - ${r.name}`);
|
|
27035
27235
|
}
|
|
27236
|
+
process.exit(1);
|
|
27237
|
+
}
|
|
27238
|
+
function exitWithAmbiguousConfig(name, matches) {
|
|
27239
|
+
console.error(`Ambiguous run configuration: ${name}`);
|
|
27240
|
+
console.error("Did you mean:");
|
|
27241
|
+
for (const r of matches) {
|
|
27242
|
+
console.error(` - ${r.name}`);
|
|
27243
|
+
}
|
|
27244
|
+
process.exit(1);
|
|
27245
|
+
}
|
|
27246
|
+
function requireRunConfigs() {
|
|
27247
|
+
const { run: run4 } = loadConfig();
|
|
27248
|
+
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
27249
|
+
if (configs.length === 0) return exitNoRunConfigs();
|
|
27250
|
+
return configs;
|
|
27251
|
+
}
|
|
27252
|
+
function lookupRunConfig(name) {
|
|
27253
|
+
const configs = requireRunConfigs();
|
|
27254
|
+
const exact = configs.find((r) => r.name === name);
|
|
27255
|
+
if (exact) return { kind: "match", config: exact };
|
|
27256
|
+
const suffixMatches = configs.filter((r) => r.name.endsWith(`:${name}`));
|
|
27257
|
+
if (suffixMatches.length === 1)
|
|
27258
|
+
return { kind: "match", config: suffixMatches[0] };
|
|
27259
|
+
if (suffixMatches.length > 1)
|
|
27260
|
+
return { kind: "ambiguous", matches: suffixMatches };
|
|
27261
|
+
return { kind: "not-found" };
|
|
27262
|
+
}
|
|
27263
|
+
function findRunConfig(name) {
|
|
27264
|
+
const result = lookupRunConfig(name);
|
|
27265
|
+
if (result.kind === "match") return result.config;
|
|
27266
|
+
if (result.kind === "ambiguous")
|
|
27267
|
+
return exitWithAmbiguousConfig(name, result.matches);
|
|
27268
|
+
return exitWithConfigNotFound(name, requireRunConfigs());
|
|
27269
|
+
}
|
|
27270
|
+
|
|
27271
|
+
// src/commands/run/resolveParams.ts
|
|
27272
|
+
function resolveParams(params, cliArgs) {
|
|
27273
|
+
if (!params || params.length === 0) return cliArgs;
|
|
27274
|
+
const resolved = [];
|
|
27275
|
+
const missing = [];
|
|
27276
|
+
for (let i = 0; i < params.length; i++) {
|
|
27277
|
+
const param = params[i];
|
|
27278
|
+
const value = cliArgs[i] ?? param.default;
|
|
27279
|
+
if (value !== void 0) {
|
|
27280
|
+
resolved.push(value);
|
|
27281
|
+
} else if (param.required) {
|
|
27282
|
+
missing.push(param.name);
|
|
27283
|
+
}
|
|
27284
|
+
}
|
|
27285
|
+
if (missing.length > 0) {
|
|
27286
|
+
const s = missing.length > 1 ? "s" : "";
|
|
27287
|
+
const names = missing.map((n) => `"${n}"`).join(", ");
|
|
27288
|
+
console.error(`Missing required param${s}: ${names}`);
|
|
27289
|
+
process.exit(1);
|
|
27290
|
+
}
|
|
27291
|
+
resolved.push(...cliArgs.slice(params.length));
|
|
27292
|
+
return resolved;
|
|
27293
|
+
}
|
|
27294
|
+
|
|
27295
|
+
// src/commands/run/runCommandToCompletion.ts
|
|
27296
|
+
import { execFileSync as execFileSync11, spawn as spawn9 } from "child_process";
|
|
27297
|
+
import { existsSync as existsSync58 } from "fs";
|
|
27298
|
+
import { dirname as dirname31, join as join68, resolve as resolve16 } from "path";
|
|
27299
|
+
function resolveCommand2(command) {
|
|
27300
|
+
if (process.platform !== "win32" || command !== "bash") return command;
|
|
27036
27301
|
try {
|
|
27037
|
-
|
|
27038
|
-
|
|
27039
|
-
|
|
27040
|
-
|
|
27041
|
-
cwd
|
|
27042
|
-
)
|
|
27043
|
-
};
|
|
27302
|
+
const gitPath = execFileSync11("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
27303
|
+
const gitRoot = resolve16(dirname31(gitPath), "..");
|
|
27304
|
+
const gitBash = join68(gitRoot, "bin", "bash.exe");
|
|
27305
|
+
if (existsSync58(gitBash)) return gitBash;
|
|
27044
27306
|
} catch {
|
|
27045
|
-
|
|
27046
|
-
`branch "${branch2}" has no upstream \u2014 set one with: git push -u origin ${branch2}`
|
|
27047
|
-
);
|
|
27307
|
+
return command;
|
|
27048
27308
|
}
|
|
27309
|
+
return command;
|
|
27310
|
+
}
|
|
27311
|
+
function runCommandToCompletion(command, args, env, cwd, quiet) {
|
|
27312
|
+
return new Promise((resolveResult) => {
|
|
27313
|
+
const child = spawn9(resolveCommand2(command), args, {
|
|
27314
|
+
stdio: quiet ? "pipe" : "inherit",
|
|
27315
|
+
env: env ? { ...process.env, ...expandEnv(env) } : void 0,
|
|
27316
|
+
cwd
|
|
27317
|
+
});
|
|
27318
|
+
const chunks = [];
|
|
27319
|
+
if (quiet) {
|
|
27320
|
+
child.stdout?.on("data", (data) => chunks.push(data));
|
|
27321
|
+
child.stderr?.on("data", (data) => chunks.push(data));
|
|
27322
|
+
}
|
|
27323
|
+
child.on("close", (code) => {
|
|
27324
|
+
resolveResult({
|
|
27325
|
+
kind: "completed",
|
|
27326
|
+
exitCode: code ?? 0,
|
|
27327
|
+
output: Buffer.concat(chunks).toString()
|
|
27328
|
+
});
|
|
27329
|
+
});
|
|
27330
|
+
child.on("error", (err) => {
|
|
27331
|
+
resolveResult({
|
|
27332
|
+
kind: "failed",
|
|
27333
|
+
message: `Failed to execute command: ${err.message}`
|
|
27334
|
+
});
|
|
27335
|
+
});
|
|
27336
|
+
});
|
|
27049
27337
|
}
|
|
27050
27338
|
|
|
27051
|
-
// src/commands/
|
|
27052
|
-
|
|
27053
|
-
|
|
27054
|
-
|
|
27055
|
-
|
|
27056
|
-
|
|
27057
|
-
|
|
27339
|
+
// src/commands/run/runPreCommands.ts
|
|
27340
|
+
import { execSync as execSync60 } from "child_process";
|
|
27341
|
+
function runPreCommands(pre, cwd) {
|
|
27342
|
+
for (const cmd of pre) {
|
|
27343
|
+
try {
|
|
27344
|
+
execSync60(cmd, { stdio: "inherit", cwd });
|
|
27345
|
+
} catch (error) {
|
|
27346
|
+
const code = error && typeof error === "object" && "status" in error ? error.status : 1;
|
|
27347
|
+
process.exit(code);
|
|
27348
|
+
}
|
|
27058
27349
|
}
|
|
27059
27350
|
}
|
|
27060
27351
|
|
|
27352
|
+
// src/commands/watch/runWatchBuild.ts
|
|
27353
|
+
async function runWatchBuild(entry) {
|
|
27354
|
+
const config = findRunConfig(entry);
|
|
27355
|
+
const cwd = config.cwd ? resolve17(getConfigDir(), config.cwd) : void 0;
|
|
27356
|
+
if (config.pre) runPreCommands(config.pre, cwd);
|
|
27357
|
+
const result = await runCommandToCompletion(
|
|
27358
|
+
config.command,
|
|
27359
|
+
[...config.args ?? [], ...resolveParams(config.params, [])],
|
|
27360
|
+
config.env,
|
|
27361
|
+
cwd,
|
|
27362
|
+
config.quiet
|
|
27363
|
+
);
|
|
27364
|
+
if (result.kind === "failed")
|
|
27365
|
+
return { kind: "failed", exitCode: 1, output: result.message };
|
|
27366
|
+
if (result.exitCode !== 0)
|
|
27367
|
+
return { kind: "failed", exitCode: result.exitCode, output: result.output };
|
|
27368
|
+
return { kind: "built" };
|
|
27369
|
+
}
|
|
27370
|
+
|
|
27371
|
+
// src/commands/watch/reportBuildOrExit.ts
|
|
27372
|
+
async function reportBuildOrExit(entry) {
|
|
27373
|
+
const outcome = await runWatchBuild(entry);
|
|
27374
|
+
if (outcome.kind === "built") {
|
|
27375
|
+
console.log(`built with "${entry}"`);
|
|
27376
|
+
return;
|
|
27377
|
+
}
|
|
27378
|
+
if (outcome.output.length > 0) process.stdout.write(outcome.output);
|
|
27379
|
+
console.error(`build "${entry}" failed with exit code ${outcome.exitCode}`);
|
|
27380
|
+
process.exit(4);
|
|
27381
|
+
}
|
|
27382
|
+
|
|
27061
27383
|
// src/commands/watch/fetchQuietly.ts
|
|
27062
|
-
import { execFileSync as
|
|
27384
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
27063
27385
|
function fetchQuietly(cwd, timeoutMs) {
|
|
27064
27386
|
try {
|
|
27065
|
-
|
|
27387
|
+
execFileSync12("git", ["fetch", "--quiet"], {
|
|
27066
27388
|
stdio: ["pipe", "pipe", "pipe"],
|
|
27067
27389
|
cwd,
|
|
27068
27390
|
timeout: timeoutMs
|
|
@@ -27090,26 +27412,12 @@ function readMovement(cwd) {
|
|
|
27090
27412
|
}
|
|
27091
27413
|
}
|
|
27092
27414
|
|
|
27093
|
-
// src/commands/watch/
|
|
27415
|
+
// src/commands/watch/pollForMovement.ts
|
|
27094
27416
|
var MIN_FETCH_TIMEOUT_MS = 6e4;
|
|
27095
|
-
function
|
|
27096
|
-
const { intervalMs, timeoutMs, timeout, cwd
|
|
27097
|
-
let upstream;
|
|
27098
|
-
try {
|
|
27099
|
-
upstream = resolveUpstream(cwd).upstream;
|
|
27100
|
-
} catch (error) {
|
|
27101
|
-
return Promise.resolve({
|
|
27102
|
-
kind: "unavailable",
|
|
27103
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
27104
|
-
});
|
|
27105
|
-
}
|
|
27106
|
-
onStart?.(upstream);
|
|
27107
|
-
const moved = readMovement(cwd);
|
|
27108
|
-
if (moved) {
|
|
27109
|
-
return Promise.resolve({ kind: "moved", upstream, ...moved });
|
|
27110
|
-
}
|
|
27417
|
+
function pollForMovement(options2) {
|
|
27418
|
+
const { upstream, intervalMs, timeoutMs, timeout, cwd } = options2;
|
|
27111
27419
|
const fetchTimeoutMs = Math.max(intervalMs, MIN_FETCH_TIMEOUT_MS);
|
|
27112
|
-
return new Promise((
|
|
27420
|
+
return new Promise((resolve22) => {
|
|
27113
27421
|
let settled = false;
|
|
27114
27422
|
const finish = (outcome) => {
|
|
27115
27423
|
if (settled) return;
|
|
@@ -27117,7 +27425,7 @@ function waitForUpstream(options2) {
|
|
|
27117
27425
|
clearInterval(ticker);
|
|
27118
27426
|
clearTimeout(deadline);
|
|
27119
27427
|
process.off("SIGINT", onInterrupt);
|
|
27120
|
-
|
|
27428
|
+
resolve22(outcome);
|
|
27121
27429
|
};
|
|
27122
27430
|
const onInterrupt = () => finish({ kind: "interrupted" });
|
|
27123
27431
|
const ticker = setInterval(() => {
|
|
@@ -27125,7 +27433,7 @@ function waitForUpstream(options2) {
|
|
|
27125
27433
|
const found = readMovement(cwd);
|
|
27126
27434
|
if (found) finish({ kind: "moved", upstream, ...found });
|
|
27127
27435
|
}, intervalMs);
|
|
27128
|
-
const deadline = setTimeout(
|
|
27436
|
+
const deadline = timeoutMs === void 0 ? void 0 : setTimeout(
|
|
27129
27437
|
() => finish({ kind: "timeout", upstream, timeout }),
|
|
27130
27438
|
timeoutMs
|
|
27131
27439
|
);
|
|
@@ -27133,22 +27441,35 @@ function waitForUpstream(options2) {
|
|
|
27133
27441
|
});
|
|
27134
27442
|
}
|
|
27135
27443
|
|
|
27136
|
-
// src/commands/watch/
|
|
27137
|
-
function
|
|
27444
|
+
// src/commands/watch/waitForUpstream.ts
|
|
27445
|
+
function waitForUpstream(options2) {
|
|
27446
|
+
const { intervalMs, timeoutMs, timeout, cwd, onStart } = options2;
|
|
27447
|
+
let upstream;
|
|
27138
27448
|
try {
|
|
27139
|
-
|
|
27449
|
+
upstream = resolveUpstream(cwd).upstream;
|
|
27140
27450
|
} catch (error) {
|
|
27141
|
-
|
|
27142
|
-
|
|
27451
|
+
return Promise.resolve({
|
|
27452
|
+
kind: "unavailable",
|
|
27453
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
27454
|
+
});
|
|
27143
27455
|
}
|
|
27456
|
+
onStart?.(upstream);
|
|
27457
|
+
const moved = readMovement(cwd);
|
|
27458
|
+
if (moved) return Promise.resolve({ kind: "moved", upstream, ...moved });
|
|
27459
|
+
return pollForMovement({ upstream, intervalMs, timeoutMs, timeout, cwd });
|
|
27144
27460
|
}
|
|
27461
|
+
|
|
27462
|
+
// src/commands/watch/watchWait.ts
|
|
27463
|
+
var DEFAULT_BUILD_ENTRY = "auto-build";
|
|
27145
27464
|
function report({ exitCode, message: message3 }) {
|
|
27146
27465
|
if (exitCode === 0) console.log(message3);
|
|
27147
27466
|
else console.error(message3);
|
|
27148
27467
|
}
|
|
27149
27468
|
async function watchWait(options2) {
|
|
27150
|
-
const intervalMs =
|
|
27151
|
-
|
|
27469
|
+
const { intervalMs, timeoutMs } = parseWatchDurations(
|
|
27470
|
+
options2.interval,
|
|
27471
|
+
options2.timeout
|
|
27472
|
+
);
|
|
27152
27473
|
const outcome = await waitForUpstream({
|
|
27153
27474
|
intervalMs,
|
|
27154
27475
|
timeoutMs,
|
|
@@ -27157,29 +27478,47 @@ async function watchWait(options2) {
|
|
|
27157
27478
|
});
|
|
27158
27479
|
const waitReport = describeOutcome(outcome);
|
|
27159
27480
|
report(waitReport);
|
|
27160
|
-
if (outcome.kind
|
|
27161
|
-
|
|
27162
|
-
|
|
27163
|
-
|
|
27481
|
+
if (outcome.kind !== "moved" || !options2.pull)
|
|
27482
|
+
return process.exit(waitReport.exitCode);
|
|
27483
|
+
const pullResult = pullFastForward();
|
|
27484
|
+
const pullReport = describePull(pullResult);
|
|
27485
|
+
report(pullReport);
|
|
27486
|
+
if (pullResult.kind !== "fast-forwarded")
|
|
27487
|
+
return process.exit(pullReport.exitCode);
|
|
27488
|
+
console.log(`
|
|
27489
|
+
${buildWatchReport(outcome.from)}`);
|
|
27490
|
+
if (options2.build) {
|
|
27491
|
+
await reportBuildOrExit(
|
|
27492
|
+
typeof options2.build === "string" ? options2.build : DEFAULT_BUILD_ENTRY
|
|
27493
|
+
);
|
|
27164
27494
|
}
|
|
27165
|
-
process.exit(
|
|
27495
|
+
process.exit(0);
|
|
27166
27496
|
}
|
|
27167
27497
|
|
|
27168
27498
|
// src/commands/registerWatch.ts
|
|
27169
27499
|
function registerWatch(program2) {
|
|
27170
27500
|
const watchCommand = program2.command("watch").description("Wait on upstream movement for the current branch");
|
|
27171
27501
|
watchCommand.command("wait").description(
|
|
27172
|
-
"Block until the current branch's upstream gains commits, then exit 0 (2 on timeout, 3 when --pull
|
|
27502
|
+
"Block until the current branch's upstream gains commits, then exit 0 (2 on timeout, 3 when --pull hits genuine divergence, 4 when --build fails, 1 when waiting is impossible, 130 on interrupt)"
|
|
27173
27503
|
).option("--interval <duration>", "How often to fetch (e.g. 30s, 2m)", "30s").option(
|
|
27174
27504
|
"--timeout <duration>",
|
|
27175
|
-
"Give up and exit 2 after this long (e.g. 60m, 2h)",
|
|
27176
|
-
"
|
|
27505
|
+
"Give up and exit 2 after this long (e.g. 60m, 2h), or none to wait indefinitely",
|
|
27506
|
+
"none"
|
|
27177
27507
|
).option(
|
|
27178
27508
|
"--pull",
|
|
27179
|
-
"On movement, fast-forward with git pull --ff-only; exit 3 with git's reason
|
|
27509
|
+
"On movement, fast-forward with git pull --ff-only, recovering a dirty tree or a merely-behind branch; exit 3 with git's reason on genuine divergence"
|
|
27510
|
+
).option(
|
|
27511
|
+
"--build [entry]",
|
|
27512
|
+
"After a successful pull, run this run entry (default auto-build); exit 4 with its output when it fails"
|
|
27180
27513
|
).action(
|
|
27181
27514
|
(options2) => watchWait(options2)
|
|
27182
27515
|
);
|
|
27516
|
+
watchCommand.command("report").description(
|
|
27517
|
+
"Print the built version, the last 10 commits as a markdown table, and the restarts the new commits make necessary"
|
|
27518
|
+
).option(
|
|
27519
|
+
"--from <sha>",
|
|
27520
|
+
"Mark commits reachable from HEAD but not <sha> as new, and derive restart advice from the files they changed"
|
|
27521
|
+
).action((options2) => watchReport(options2));
|
|
27183
27522
|
}
|
|
27184
27523
|
|
|
27185
27524
|
// src/commands/roam/auth.ts
|
|
@@ -27205,7 +27544,7 @@ function extractCode(url, expectedState) {
|
|
|
27205
27544
|
return code;
|
|
27206
27545
|
}
|
|
27207
27546
|
function waitForCallback(port, expectedState) {
|
|
27208
|
-
return new Promise((
|
|
27547
|
+
return new Promise((resolve22, reject) => {
|
|
27209
27548
|
const timeout = setTimeout(() => {
|
|
27210
27549
|
server.close();
|
|
27211
27550
|
reject(new Error("Authorization timed out after 120 seconds"));
|
|
@@ -27222,7 +27561,7 @@ function waitForCallback(port, expectedState) {
|
|
|
27222
27561
|
const code = extractCode(url, expectedState);
|
|
27223
27562
|
respondHtml(res, 200, "Authorization successful!");
|
|
27224
27563
|
server.close();
|
|
27225
|
-
|
|
27564
|
+
resolve22(code);
|
|
27226
27565
|
} catch (error) {
|
|
27227
27566
|
respondHtml(res, 400, error.message);
|
|
27228
27567
|
server.close();
|
|
@@ -27342,9 +27681,9 @@ async function auth() {
|
|
|
27342
27681
|
}
|
|
27343
27682
|
|
|
27344
27683
|
// src/commands/roam/postRoamActivity.ts
|
|
27345
|
-
import { execFileSync as
|
|
27684
|
+
import { execFileSync as execFileSync13 } from "child_process";
|
|
27346
27685
|
import { readdirSync as readdirSync12, readFileSync as readFileSync48, statSync as statSync10 } from "fs";
|
|
27347
|
-
import { join as
|
|
27686
|
+
import { join as join69 } from "path";
|
|
27348
27687
|
function findPortFile(roamDir) {
|
|
27349
27688
|
let entries;
|
|
27350
27689
|
try {
|
|
@@ -27353,7 +27692,7 @@ function findPortFile(roamDir) {
|
|
|
27353
27692
|
return void 0;
|
|
27354
27693
|
}
|
|
27355
27694
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
27356
|
-
const path71 =
|
|
27695
|
+
const path71 = join69(roamDir, name);
|
|
27357
27696
|
try {
|
|
27358
27697
|
return { path: path71, mtimeMs: statSync10(path71).mtimeMs };
|
|
27359
27698
|
} catch {
|
|
@@ -27365,7 +27704,7 @@ function findPortFile(roamDir) {
|
|
|
27365
27704
|
function postRoamActivity(app, event) {
|
|
27366
27705
|
const appData = process.env.APPDATA;
|
|
27367
27706
|
if (!appData) return;
|
|
27368
|
-
const portFile = findPortFile(
|
|
27707
|
+
const portFile = findPortFile(join69(appData, "Roam"));
|
|
27369
27708
|
if (!portFile) return;
|
|
27370
27709
|
let port;
|
|
27371
27710
|
try {
|
|
@@ -27375,7 +27714,7 @@ function postRoamActivity(app, event) {
|
|
|
27375
27714
|
}
|
|
27376
27715
|
const url = `http://127.0.0.1:${port}/api/v1/activity/${app}/${event}?pid=${app === "codex" ? 99998 : 99999}`;
|
|
27377
27716
|
try {
|
|
27378
|
-
|
|
27717
|
+
execFileSync13("curl", ["-sf", "--max-time", "0.2", "-X", "POST", url], {
|
|
27379
27718
|
stdio: "ignore"
|
|
27380
27719
|
});
|
|
27381
27720
|
} catch {
|
|
@@ -27499,53 +27838,7 @@ var rootConfigHelp = {
|
|
|
27499
27838
|
};
|
|
27500
27839
|
|
|
27501
27840
|
// src/commands/run/index.ts
|
|
27502
|
-
import { resolve as
|
|
27503
|
-
|
|
27504
|
-
// src/commands/run/findRunConfig.ts
|
|
27505
|
-
function exitNoRunConfigs() {
|
|
27506
|
-
console.error("No run configurations found in assist.yml");
|
|
27507
|
-
process.exit(1);
|
|
27508
|
-
}
|
|
27509
|
-
function exitWithConfigNotFound(name, configs) {
|
|
27510
|
-
console.error(`No run configuration found with name: ${name}`);
|
|
27511
|
-
console.error("Available configurations:");
|
|
27512
|
-
for (const r of configs) {
|
|
27513
|
-
console.error(` - ${r.name}`);
|
|
27514
|
-
}
|
|
27515
|
-
process.exit(1);
|
|
27516
|
-
}
|
|
27517
|
-
function exitWithAmbiguousConfig(name, matches) {
|
|
27518
|
-
console.error(`Ambiguous run configuration: ${name}`);
|
|
27519
|
-
console.error("Did you mean:");
|
|
27520
|
-
for (const r of matches) {
|
|
27521
|
-
console.error(` - ${r.name}`);
|
|
27522
|
-
}
|
|
27523
|
-
process.exit(1);
|
|
27524
|
-
}
|
|
27525
|
-
function requireRunConfigs() {
|
|
27526
|
-
const { run: run4 } = loadConfig();
|
|
27527
|
-
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
27528
|
-
if (configs.length === 0) return exitNoRunConfigs();
|
|
27529
|
-
return configs;
|
|
27530
|
-
}
|
|
27531
|
-
function lookupRunConfig(name) {
|
|
27532
|
-
const configs = requireRunConfigs();
|
|
27533
|
-
const exact = configs.find((r) => r.name === name);
|
|
27534
|
-
if (exact) return { kind: "match", config: exact };
|
|
27535
|
-
const suffixMatches = configs.filter((r) => r.name.endsWith(`:${name}`));
|
|
27536
|
-
if (suffixMatches.length === 1)
|
|
27537
|
-
return { kind: "match", config: suffixMatches[0] };
|
|
27538
|
-
if (suffixMatches.length > 1)
|
|
27539
|
-
return { kind: "ambiguous", matches: suffixMatches };
|
|
27540
|
-
return { kind: "not-found" };
|
|
27541
|
-
}
|
|
27542
|
-
function findRunConfig(name) {
|
|
27543
|
-
const result = lookupRunConfig(name);
|
|
27544
|
-
if (result.kind === "match") return result.config;
|
|
27545
|
-
if (result.kind === "ambiguous")
|
|
27546
|
-
return exitWithAmbiguousConfig(name, result.matches);
|
|
27547
|
-
return exitWithConfigNotFound(name, requireRunConfigs());
|
|
27548
|
-
}
|
|
27841
|
+
import { resolve as resolve18 } from "path";
|
|
27549
27842
|
|
|
27550
27843
|
// src/commands/run/formatConfiguredCommands.ts
|
|
27551
27844
|
function formatConfiguredCommands() {
|
|
@@ -27558,84 +27851,23 @@ Configured commands:
|
|
|
27558
27851
|
${names}`;
|
|
27559
27852
|
}
|
|
27560
27853
|
|
|
27561
|
-
// src/commands/run/resolveParams.ts
|
|
27562
|
-
function resolveParams(params, cliArgs) {
|
|
27563
|
-
if (!params || params.length === 0) return cliArgs;
|
|
27564
|
-
const resolved = [];
|
|
27565
|
-
const missing = [];
|
|
27566
|
-
for (let i = 0; i < params.length; i++) {
|
|
27567
|
-
const param = params[i];
|
|
27568
|
-
const value = cliArgs[i] ?? param.default;
|
|
27569
|
-
if (value !== void 0) {
|
|
27570
|
-
resolved.push(value);
|
|
27571
|
-
} else if (param.required) {
|
|
27572
|
-
missing.push(param.name);
|
|
27573
|
-
}
|
|
27574
|
-
}
|
|
27575
|
-
if (missing.length > 0) {
|
|
27576
|
-
const s = missing.length > 1 ? "s" : "";
|
|
27577
|
-
const names = missing.map((n) => `"${n}"`).join(", ");
|
|
27578
|
-
console.error(`Missing required param${s}: ${names}`);
|
|
27579
|
-
process.exit(1);
|
|
27580
|
-
}
|
|
27581
|
-
resolved.push(...cliArgs.slice(params.length));
|
|
27582
|
-
return resolved;
|
|
27583
|
-
}
|
|
27584
|
-
|
|
27585
|
-
// src/commands/run/runPreCommands.ts
|
|
27586
|
-
import { execSync as execSync60 } from "child_process";
|
|
27587
|
-
function runPreCommands(pre, cwd) {
|
|
27588
|
-
for (const cmd of pre) {
|
|
27589
|
-
try {
|
|
27590
|
-
execSync60(cmd, { stdio: "inherit", cwd });
|
|
27591
|
-
} catch (error) {
|
|
27592
|
-
const code = error && typeof error === "object" && "status" in error ? error.status : 1;
|
|
27593
|
-
process.exit(code);
|
|
27594
|
-
}
|
|
27595
|
-
}
|
|
27596
|
-
}
|
|
27597
|
-
|
|
27598
27854
|
// src/commands/run/spawnRunCommand.ts
|
|
27599
|
-
import { execFileSync as execFileSync13, spawn as spawn9 } from "child_process";
|
|
27600
|
-
import { existsSync as existsSync58 } from "fs";
|
|
27601
|
-
import { dirname as dirname31, join as join68, resolve as resolve16 } from "path";
|
|
27602
|
-
function resolveCommand2(command) {
|
|
27603
|
-
if (process.platform !== "win32" || command !== "bash") return command;
|
|
27604
|
-
try {
|
|
27605
|
-
const gitPath = execFileSync13("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
27606
|
-
const gitRoot = resolve16(dirname31(gitPath), "..");
|
|
27607
|
-
const gitBash = join68(gitRoot, "bin", "bash.exe");
|
|
27608
|
-
if (existsSync58(gitBash)) return gitBash;
|
|
27609
|
-
} catch {
|
|
27610
|
-
}
|
|
27611
|
-
return command;
|
|
27612
|
-
}
|
|
27613
27855
|
function spawnRunCommand(command, args, env, cwd, quiet) {
|
|
27614
27856
|
const start3 = Date.now();
|
|
27615
|
-
|
|
27616
|
-
|
|
27617
|
-
|
|
27618
|
-
|
|
27619
|
-
|
|
27620
|
-
|
|
27621
|
-
|
|
27622
|
-
|
|
27623
|
-
child.stderr?.on("data", (data) => chunks.push(data));
|
|
27624
|
-
}
|
|
27625
|
-
child.on("close", (code) => {
|
|
27626
|
-
const exitCode = code ?? 0;
|
|
27627
|
-
if (quiet && exitCode !== 0 && chunks.length > 0) {
|
|
27628
|
-
process.stdout.write(Buffer.concat(chunks));
|
|
27857
|
+
void runCommandToCompletion(command, args, env, cwd, quiet).then((result) => {
|
|
27858
|
+
if (result.kind === "failed") {
|
|
27859
|
+
console.error(result.message);
|
|
27860
|
+
process.exit(1);
|
|
27861
|
+
}
|
|
27862
|
+
const { exitCode, output } = result;
|
|
27863
|
+
if (quiet && exitCode !== 0 && output.length > 0) {
|
|
27864
|
+
process.stdout.write(output);
|
|
27629
27865
|
}
|
|
27630
27866
|
const elapsed = formatElapsed(Date.now() - start3);
|
|
27631
27867
|
if (!quiet || exitCode !== 0) console.log(`
|
|
27632
27868
|
Done in ${elapsed}`);
|
|
27633
27869
|
process.exit(exitCode);
|
|
27634
27870
|
});
|
|
27635
|
-
child.on("error", (err) => {
|
|
27636
|
-
console.error(`Failed to execute command: ${err.message}`);
|
|
27637
|
-
process.exit(1);
|
|
27638
|
-
});
|
|
27639
27871
|
}
|
|
27640
27872
|
|
|
27641
27873
|
// src/commands/run/index.ts
|
|
@@ -27651,7 +27883,7 @@ function listRunConfigs(verbose) {
|
|
|
27651
27883
|
}
|
|
27652
27884
|
}
|
|
27653
27885
|
function execRunConfig(config, args) {
|
|
27654
|
-
const cwd = config.cwd ?
|
|
27886
|
+
const cwd = config.cwd ? resolve18(getConfigDir(), config.cwd) : void 0;
|
|
27655
27887
|
if (config.pre) runPreCommands(config.pre, cwd);
|
|
27656
27888
|
const resolved = resolveParams(config.params, args);
|
|
27657
27889
|
spawnRunCommand(
|
|
@@ -27693,7 +27925,7 @@ async function run3(name, args) {
|
|
|
27693
27925
|
|
|
27694
27926
|
// src/commands/run/add.ts
|
|
27695
27927
|
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync41 } from "fs";
|
|
27696
|
-
import { join as
|
|
27928
|
+
import { join as join70 } from "path";
|
|
27697
27929
|
|
|
27698
27930
|
// src/commands/run/extractOption.ts
|
|
27699
27931
|
function extractOption(args, flag) {
|
|
@@ -27754,7 +27986,7 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
27754
27986
|
saveConfig(config);
|
|
27755
27987
|
}
|
|
27756
27988
|
function createCommandFile(name) {
|
|
27757
|
-
const dir =
|
|
27989
|
+
const dir = join70(".claude", "commands");
|
|
27758
27990
|
mkdirSync24(dir, { recursive: true });
|
|
27759
27991
|
const content = `---
|
|
27760
27992
|
description: Run ${name}
|
|
@@ -27762,7 +27994,7 @@ description: Run ${name}
|
|
|
27762
27994
|
|
|
27763
27995
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
27764
27996
|
`;
|
|
27765
|
-
const filePath =
|
|
27997
|
+
const filePath = join70(dir, `${name}.md`);
|
|
27766
27998
|
writeFileSync41(filePath, content);
|
|
27767
27999
|
console.log(`Created command file: ${filePath}`);
|
|
27768
28000
|
}
|
|
@@ -27819,7 +28051,7 @@ function link2() {
|
|
|
27819
28051
|
|
|
27820
28052
|
// src/commands/run/remove.ts
|
|
27821
28053
|
import { existsSync as existsSync59, unlinkSync as unlinkSync21 } from "fs";
|
|
27822
|
-
import { join as
|
|
28054
|
+
import { join as join71 } from "path";
|
|
27823
28055
|
function findRemoveIndex() {
|
|
27824
28056
|
const idx = process.argv.indexOf("remove");
|
|
27825
28057
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -27834,7 +28066,7 @@ function parseRemoveName() {
|
|
|
27834
28066
|
return process.argv[idx + 1];
|
|
27835
28067
|
}
|
|
27836
28068
|
function deleteCommandFile(name) {
|
|
27837
|
-
const filePath =
|
|
28069
|
+
const filePath = join71(".claude", "commands", `${name}.md`);
|
|
27838
28070
|
if (existsSync59(filePath)) {
|
|
27839
28071
|
unlinkSync21(filePath);
|
|
27840
28072
|
console.log(`Deleted command file: ${filePath}`);
|
|
@@ -27891,7 +28123,7 @@ function registerRun(program2) {
|
|
|
27891
28123
|
import { execSync as execSync61 } from "child_process";
|
|
27892
28124
|
import { existsSync as existsSync60, mkdirSync as mkdirSync25, unlinkSync as unlinkSync22, writeFileSync as writeFileSync42 } from "fs";
|
|
27893
28125
|
import { tmpdir as tmpdir8 } from "os";
|
|
27894
|
-
import { join as
|
|
28126
|
+
import { join as join72, resolve as resolve19 } from "path";
|
|
27895
28127
|
import chalk209 from "chalk";
|
|
27896
28128
|
|
|
27897
28129
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -28025,10 +28257,10 @@ function buildOutputPath(outputDir, processName) {
|
|
|
28025
28257
|
mkdirSync25(outputDir, { recursive: true });
|
|
28026
28258
|
}
|
|
28027
28259
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
28028
|
-
return
|
|
28260
|
+
return resolve19(outputDir, `${processName}-${timestamp6}.png`);
|
|
28029
28261
|
}
|
|
28030
28262
|
function runPowerShellScript(processName, outputPath) {
|
|
28031
|
-
const scriptPath =
|
|
28263
|
+
const scriptPath = join72(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
|
|
28032
28264
|
writeFileSync42(scriptPath, captureWindowPs1, "utf8");
|
|
28033
28265
|
try {
|
|
28034
28266
|
execSync61(
|
|
@@ -28041,7 +28273,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
28041
28273
|
}
|
|
28042
28274
|
function screenshot(processName) {
|
|
28043
28275
|
const config = loadConfig();
|
|
28044
|
-
const outputDir =
|
|
28276
|
+
const outputDir = resolve19(config.screenshot.outputDir);
|
|
28045
28277
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
28046
28278
|
console.log(chalk209.gray(`Capturing window for process "${processName}" ...`));
|
|
28047
28279
|
try {
|
|
@@ -28074,18 +28306,18 @@ var STATUS_TIMEOUT_MS = 5e3;
|
|
|
28074
28306
|
function queryDaemon(socket) {
|
|
28075
28307
|
socket.write(`${JSON.stringify({ type: "ping" })}
|
|
28076
28308
|
`);
|
|
28077
|
-
return new Promise((
|
|
28309
|
+
return new Promise((resolve22) => {
|
|
28078
28310
|
const result = { sessions: [] };
|
|
28079
28311
|
const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
|
|
28080
|
-
const timer = setTimeout(() =>
|
|
28081
|
-
const
|
|
28082
|
-
|
|
28312
|
+
const timer = setTimeout(() => resolve22(result), STATUS_TIMEOUT_MS);
|
|
28313
|
+
const lines2 = createInterface5({ input: socket });
|
|
28314
|
+
lines2.on("error", () => {
|
|
28083
28315
|
});
|
|
28084
|
-
|
|
28316
|
+
lines2.on("line", (line) => {
|
|
28085
28317
|
applyLine(result, pending, line);
|
|
28086
28318
|
if (pending.size === 0) {
|
|
28087
28319
|
clearTimeout(timer);
|
|
28088
|
-
|
|
28320
|
+
resolve22(result);
|
|
28089
28321
|
}
|
|
28090
28322
|
});
|
|
28091
28323
|
});
|
|
@@ -28170,12 +28402,12 @@ function clearPersistedSessionsOnDrain() {
|
|
|
28170
28402
|
}
|
|
28171
28403
|
|
|
28172
28404
|
// src/commands/sessions/daemon/readDaemonMessage.ts
|
|
28173
|
-
function readDaemonMessage(
|
|
28174
|
-
return new Promise((
|
|
28405
|
+
function readDaemonMessage(lines2, timeoutMs, fallback, match) {
|
|
28406
|
+
return new Promise((resolve22) => {
|
|
28175
28407
|
const finish = (value) => {
|
|
28176
28408
|
clearTimeout(timer);
|
|
28177
|
-
|
|
28178
|
-
|
|
28409
|
+
lines2.off("line", onLine);
|
|
28410
|
+
resolve22(value);
|
|
28179
28411
|
};
|
|
28180
28412
|
const timer = setTimeout(() => finish(fallback), timeoutMs);
|
|
28181
28413
|
const onLine = (line) => {
|
|
@@ -28185,7 +28417,7 @@ function readDaemonMessage(lines, timeoutMs, fallback, match) {
|
|
|
28185
28417
|
} catch {
|
|
28186
28418
|
}
|
|
28187
28419
|
};
|
|
28188
|
-
|
|
28420
|
+
lines2.on("line", onLine);
|
|
28189
28421
|
});
|
|
28190
28422
|
}
|
|
28191
28423
|
|
|
@@ -28200,10 +28432,10 @@ async function drainDaemon(options2 = {}) {
|
|
|
28200
28432
|
clearPersistedSessionsOnDrain();
|
|
28201
28433
|
return;
|
|
28202
28434
|
}
|
|
28203
|
-
const
|
|
28204
|
-
|
|
28435
|
+
const lines2 = createInterface6({ input: socket });
|
|
28436
|
+
lines2.on("error", () => {
|
|
28205
28437
|
});
|
|
28206
|
-
const live = await liveSessions(
|
|
28438
|
+
const live = await liveSessions(lines2);
|
|
28207
28439
|
if (live.length > 0 && options2.yes !== true) {
|
|
28208
28440
|
reportLive(live);
|
|
28209
28441
|
if (!await confirmDrain()) {
|
|
@@ -28211,7 +28443,7 @@ async function drainDaemon(options2 = {}) {
|
|
|
28211
28443
|
return;
|
|
28212
28444
|
}
|
|
28213
28445
|
}
|
|
28214
|
-
const count8 = await requestDrain(socket,
|
|
28446
|
+
const count8 = await requestDrain(socket, lines2);
|
|
28215
28447
|
socket.destroy();
|
|
28216
28448
|
console.log(`Drained ${count8} session(s)`);
|
|
28217
28449
|
}
|
|
@@ -28230,9 +28462,9 @@ async function confirmDrain() {
|
|
|
28230
28462
|
console.log("Drain cancelled");
|
|
28231
28463
|
return false;
|
|
28232
28464
|
}
|
|
28233
|
-
function liveSessions(
|
|
28465
|
+
function liveSessions(lines2) {
|
|
28234
28466
|
return readDaemonMessage(
|
|
28235
|
-
|
|
28467
|
+
lines2,
|
|
28236
28468
|
LIST_TIMEOUT_MS,
|
|
28237
28469
|
[],
|
|
28238
28470
|
(data) => data.type === "sessions" ? (data.sessions ?? []).filter(
|
|
@@ -28240,11 +28472,11 @@ function liveSessions(lines) {
|
|
|
28240
28472
|
) : void 0
|
|
28241
28473
|
);
|
|
28242
28474
|
}
|
|
28243
|
-
function requestDrain(socket,
|
|
28475
|
+
function requestDrain(socket, lines2) {
|
|
28244
28476
|
socket.write(`${JSON.stringify({ type: "drain" })}
|
|
28245
28477
|
`);
|
|
28246
28478
|
return readDaemonMessage(
|
|
28247
|
-
|
|
28479
|
+
lines2,
|
|
28248
28480
|
DRAIN_TIMEOUT_MS,
|
|
28249
28481
|
0,
|
|
28250
28482
|
(data) => data.type === "drained" ? data.count ?? 0 : void 0
|
|
@@ -28709,12 +28941,12 @@ import { basename as basename18 } from "path";
|
|
|
28709
28941
|
|
|
28710
28942
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
28711
28943
|
import { existsSync as existsSync63 } from "fs";
|
|
28712
|
-
import { join as
|
|
28944
|
+
import { join as join75 } from "path";
|
|
28713
28945
|
|
|
28714
28946
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
28715
28947
|
import { statSync as statSync12 } from "fs";
|
|
28716
28948
|
import { rm as rm2 } from "fs/promises";
|
|
28717
|
-
import { join as
|
|
28949
|
+
import { join as join74 } from "path";
|
|
28718
28950
|
async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
28719
28951
|
if (holdsAGitDirectoryRatherThanALink(worktreePath)) {
|
|
28720
28952
|
daemonLog(
|
|
@@ -28741,7 +28973,7 @@ async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
|
28741
28973
|
return true;
|
|
28742
28974
|
}
|
|
28743
28975
|
function holdsAGitDirectoryRatherThanALink(worktreePath) {
|
|
28744
|
-
return statSync12(
|
|
28976
|
+
return statSync12(join74(worktreePath, ".git"), {
|
|
28745
28977
|
throwIfNoEntry: false
|
|
28746
28978
|
})?.isDirectory() === true;
|
|
28747
28979
|
}
|
|
@@ -28777,7 +29009,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
28777
29009
|
);
|
|
28778
29010
|
}
|
|
28779
29011
|
function strandedReason(worktreePath, cause) {
|
|
28780
|
-
if (!existsSync63(
|
|
29012
|
+
if (!existsSync63(join75(worktreePath, ".git")))
|
|
28781
29013
|
return "its .git link is already gone";
|
|
28782
29014
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
28783
29015
|
return "git no longer recognises it as a working tree";
|
|
@@ -30000,9 +30232,9 @@ async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
|
30000
30232
|
|
|
30001
30233
|
// src/commands/sessions/shared/transcriptUsage.ts
|
|
30002
30234
|
import * as fs38 from "fs";
|
|
30003
|
-
function transcriptUsage(
|
|
30235
|
+
function transcriptUsage(lines2) {
|
|
30004
30236
|
const byId = /* @__PURE__ */ new Map();
|
|
30005
|
-
for (const line of
|
|
30237
|
+
for (const line of lines2) {
|
|
30006
30238
|
if (!line.trim()) continue;
|
|
30007
30239
|
let entry;
|
|
30008
30240
|
try {
|
|
@@ -30701,29 +30933,29 @@ async function describeHeldWork(path71, reason4) {
|
|
|
30701
30933
|
}
|
|
30702
30934
|
async function changedFiles(path71) {
|
|
30703
30935
|
const status3 = await gitResult(path71, ["status", "--porcelain"]);
|
|
30704
|
-
const
|
|
30936
|
+
const lines2 = status3.ok ? nonEmptyLines(status3.out) : [];
|
|
30705
30937
|
return {
|
|
30706
|
-
summary: `${
|
|
30707
|
-
items: capped(
|
|
30938
|
+
summary: `${lines2.length} uncommitted ${lines2.length === 1 ? "file" : "files"}`,
|
|
30939
|
+
items: capped(lines2)
|
|
30708
30940
|
};
|
|
30709
30941
|
}
|
|
30710
30942
|
async function unpushedCommits(path71, reason4) {
|
|
30711
30943
|
const log2 = await gitResult(path71, ["log", "--oneline", "@{upstream}..HEAD"]);
|
|
30712
30944
|
if (!log2.ok) return { summary: reason4, items: [] };
|
|
30713
|
-
const
|
|
30945
|
+
const lines2 = nonEmptyLines(log2.out);
|
|
30714
30946
|
return {
|
|
30715
|
-
summary: `${
|
|
30716
|
-
items: capped(
|
|
30947
|
+
summary: `${lines2.length} unpushed ${lines2.length === 1 ? "commit" : "commits"}`,
|
|
30948
|
+
items: capped(lines2)
|
|
30717
30949
|
};
|
|
30718
30950
|
}
|
|
30719
30951
|
function nonEmptyLines(out) {
|
|
30720
30952
|
return out.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
30721
30953
|
}
|
|
30722
|
-
function capped(
|
|
30723
|
-
if (
|
|
30954
|
+
function capped(lines2) {
|
|
30955
|
+
if (lines2.length <= MAX_ITEMS) return lines2;
|
|
30724
30956
|
return [
|
|
30725
|
-
...
|
|
30726
|
-
`\u2026 and ${
|
|
30957
|
+
...lines2.slice(0, MAX_ITEMS),
|
|
30958
|
+
`\u2026 and ${lines2.length - MAX_ITEMS} more`
|
|
30727
30959
|
];
|
|
30728
30960
|
}
|
|
30729
30961
|
|
|
@@ -31204,7 +31436,7 @@ function windowsDaemonHost() {
|
|
|
31204
31436
|
var CONNECT_TIMEOUT_MS = 2e3;
|
|
31205
31437
|
var KEEPALIVE_PROBE_MS = 1e4;
|
|
31206
31438
|
function connectToWindowsDaemon() {
|
|
31207
|
-
return new Promise((
|
|
31439
|
+
return new Promise((resolve22, reject) => {
|
|
31208
31440
|
const socket = net2.connect(windowsDaemonPort(), windowsDaemonHost());
|
|
31209
31441
|
socket.setTimeout(CONNECT_TIMEOUT_MS);
|
|
31210
31442
|
socket.once("timeout", () => {
|
|
@@ -31214,7 +31446,7 @@ function connectToWindowsDaemon() {
|
|
|
31214
31446
|
socket.once("connect", () => {
|
|
31215
31447
|
socket.setTimeout(0);
|
|
31216
31448
|
socket.setKeepAlive(true, KEEPALIVE_PROBE_MS);
|
|
31217
|
-
|
|
31449
|
+
resolve22(socket);
|
|
31218
31450
|
});
|
|
31219
31451
|
socket.once("error", reject);
|
|
31220
31452
|
});
|
|
@@ -31235,9 +31467,9 @@ import { spawn as spawn11 } from "child_process";
|
|
|
31235
31467
|
import { createInterface as createInterface7 } from "readline";
|
|
31236
31468
|
function logChildStream(stream, label2) {
|
|
31237
31469
|
if (!stream) return;
|
|
31238
|
-
const
|
|
31239
|
-
|
|
31240
|
-
|
|
31470
|
+
const lines2 = createInterface7({ input: stream });
|
|
31471
|
+
lines2.on("line", (line) => daemonLog(`[${label2}] ${line}`));
|
|
31472
|
+
lines2.on("error", () => {
|
|
31241
31473
|
});
|
|
31242
31474
|
}
|
|
31243
31475
|
|
|
@@ -31292,7 +31524,7 @@ async function waitForWindowsDaemon() {
|
|
|
31292
31524
|
);
|
|
31293
31525
|
}
|
|
31294
31526
|
function delay2(ms) {
|
|
31295
|
-
return new Promise((
|
|
31527
|
+
return new Promise((resolve22) => setTimeout(resolve22, ms));
|
|
31296
31528
|
}
|
|
31297
31529
|
|
|
31298
31530
|
// src/commands/sessions/daemon/defaultConnect.ts
|
|
@@ -31576,7 +31808,7 @@ async function healWindowsDaemon() {
|
|
|
31576
31808
|
daemonLog("windows daemon: auto-heal: stale daemon stopped");
|
|
31577
31809
|
}
|
|
31578
31810
|
function runOnWindowsHost(command, timeoutMs) {
|
|
31579
|
-
return new Promise((
|
|
31811
|
+
return new Promise((resolve22, reject) => {
|
|
31580
31812
|
const child = spawn12("pwsh.exe", ["-Command", command], {
|
|
31581
31813
|
stdio: ["ignore", "pipe", "pipe"]
|
|
31582
31814
|
});
|
|
@@ -31596,7 +31828,7 @@ function runOnWindowsHost(command, timeoutMs) {
|
|
|
31596
31828
|
});
|
|
31597
31829
|
child.on("exit", (code) => {
|
|
31598
31830
|
clearTimeout(timer);
|
|
31599
|
-
if (code === 0)
|
|
31831
|
+
if (code === 0) resolve22();
|
|
31600
31832
|
else
|
|
31601
31833
|
reject(
|
|
31602
31834
|
new Error(
|
|
@@ -31707,10 +31939,10 @@ var WindowsConnection = class {
|
|
|
31707
31939
|
return socket;
|
|
31708
31940
|
}
|
|
31709
31941
|
wire(socket) {
|
|
31710
|
-
const
|
|
31711
|
-
|
|
31942
|
+
const lines2 = createInterface8({ input: socket });
|
|
31943
|
+
lines2.on("error", () => {
|
|
31712
31944
|
});
|
|
31713
|
-
|
|
31945
|
+
lines2.on("line", (line) => this.deps.onLine(line));
|
|
31714
31946
|
socket.on("error", () => {
|
|
31715
31947
|
});
|
|
31716
31948
|
socket.on("close", () => {
|
|
@@ -32309,9 +32541,9 @@ async function parseTranscript(sessionId) {
|
|
|
32309
32541
|
return [];
|
|
32310
32542
|
}
|
|
32311
32543
|
}
|
|
32312
|
-
function parseTranscriptLines(
|
|
32544
|
+
function parseTranscriptLines(lines2) {
|
|
32313
32545
|
const messages = [];
|
|
32314
|
-
for (const line of
|
|
32546
|
+
for (const line of lines2) {
|
|
32315
32547
|
const entry = line.trim() ? safeParse2(line) : null;
|
|
32316
32548
|
if (!entry || entry.isSidechain || entry.isMeta) continue;
|
|
32317
32549
|
messages.push(...entryMessages(entry));
|
|
@@ -32493,10 +32725,10 @@ function handleConnection(socket, manager) {
|
|
|
32493
32725
|
};
|
|
32494
32726
|
manager.addClient(client);
|
|
32495
32727
|
manager.clients.greet(client);
|
|
32496
|
-
const
|
|
32497
|
-
|
|
32728
|
+
const lines2 = createInterface9({ input: socket });
|
|
32729
|
+
lines2.on("error", () => {
|
|
32498
32730
|
});
|
|
32499
|
-
|
|
32731
|
+
lines2.on("line", (line) => {
|
|
32500
32732
|
let data;
|
|
32501
32733
|
try {
|
|
32502
32734
|
data = JSON.parse(line);
|
|
@@ -32957,9 +33189,9 @@ function buildLimitsSegment(rateLimits) {
|
|
|
32957
33189
|
|
|
32958
33190
|
// src/commands/readGitBranch.ts
|
|
32959
33191
|
import { readFileSync as readFileSync54, statSync as statSync14 } from "fs";
|
|
32960
|
-
import { isAbsolute as isAbsolute4, join as
|
|
33192
|
+
import { isAbsolute as isAbsolute4, join as join77, resolve as resolve20 } from "path";
|
|
32961
33193
|
function resolveGitDir(cwd) {
|
|
32962
|
-
const dotGit =
|
|
33194
|
+
const dotGit = join77(cwd, ".git");
|
|
32963
33195
|
let stat3;
|
|
32964
33196
|
try {
|
|
32965
33197
|
stat3 = statSync14(dotGit);
|
|
@@ -32980,7 +33212,7 @@ function resolveGitDir(cwd) {
|
|
|
32980
33212
|
return null;
|
|
32981
33213
|
}
|
|
32982
33214
|
const gitDir = match[1].trim();
|
|
32983
|
-
return isAbsolute4(gitDir) ? gitDir :
|
|
33215
|
+
return isAbsolute4(gitDir) ? gitDir : resolve20(cwd, gitDir);
|
|
32984
33216
|
}
|
|
32985
33217
|
function readGitBranch(cwd) {
|
|
32986
33218
|
const gitDir = resolveGitDir(cwd);
|
|
@@ -32989,7 +33221,7 @@ function readGitBranch(cwd) {
|
|
|
32989
33221
|
}
|
|
32990
33222
|
let head;
|
|
32991
33223
|
try {
|
|
32992
|
-
head = readFileSync54(
|
|
33224
|
+
head = readFileSync54(join77(gitDir, "HEAD"), "utf8");
|
|
32993
33225
|
} catch {
|
|
32994
33226
|
return null;
|
|
32995
33227
|
}
|