@staff0rd/assist 0.488.5 → 0.489.1
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/claude/settings.json +3 -0
- package/dist/allowed.cli-reads +1 -0
- package/dist/commands/sessions/web/bundle.js +1 -1
- package/dist/index.js +722 -486
- 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.1",
|
|
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,75 +27143,252 @@ 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}`);
|
|
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}`);
|
|
27035
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
|
+
}
|
|
27349
|
+
}
|
|
27350
|
+
}
|
|
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;
|
|
27058
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);
|
|
27059
27381
|
}
|
|
27060
27382
|
|
|
27061
27383
|
// src/commands/watch/fetchQuietly.ts
|
|
27062
|
-
import { execFileSync as
|
|
27063
|
-
|
|
27384
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
27385
|
+
var MIN_FETCH_TIMEOUT_MS = 6e4;
|
|
27386
|
+
function fetchQuietly(cwd, intervalMs) {
|
|
27064
27387
|
try {
|
|
27065
|
-
|
|
27388
|
+
execFileSync12("git", ["fetch", "--quiet"], {
|
|
27066
27389
|
stdio: ["pipe", "pipe", "pipe"],
|
|
27067
27390
|
cwd,
|
|
27068
|
-
timeout:
|
|
27391
|
+
timeout: Math.max(intervalMs, MIN_FETCH_TIMEOUT_MS)
|
|
27069
27392
|
});
|
|
27070
27393
|
} catch {
|
|
27071
27394
|
}
|
|
@@ -27090,26 +27413,10 @@ function readMovement(cwd) {
|
|
|
27090
27413
|
}
|
|
27091
27414
|
}
|
|
27092
27415
|
|
|
27093
|
-
// src/commands/watch/
|
|
27094
|
-
|
|
27095
|
-
|
|
27096
|
-
|
|
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
|
-
}
|
|
27111
|
-
const fetchTimeoutMs = Math.max(intervalMs, MIN_FETCH_TIMEOUT_MS);
|
|
27112
|
-
return new Promise((resolve21) => {
|
|
27416
|
+
// src/commands/watch/pollForMovement.ts
|
|
27417
|
+
function pollForMovement(options2) {
|
|
27418
|
+
const { upstream, intervalMs, timeoutMs, timeout, cwd } = options2;
|
|
27419
|
+
return new Promise((resolve22) => {
|
|
27113
27420
|
let settled = false;
|
|
27114
27421
|
const finish = (outcome) => {
|
|
27115
27422
|
if (settled) return;
|
|
@@ -27117,15 +27424,15 @@ function waitForUpstream(options2) {
|
|
|
27117
27424
|
clearInterval(ticker);
|
|
27118
27425
|
clearTimeout(deadline);
|
|
27119
27426
|
process.off("SIGINT", onInterrupt);
|
|
27120
|
-
|
|
27427
|
+
resolve22(outcome);
|
|
27121
27428
|
};
|
|
27122
27429
|
const onInterrupt = () => finish({ kind: "interrupted" });
|
|
27123
27430
|
const ticker = setInterval(() => {
|
|
27124
|
-
fetchQuietly(cwd,
|
|
27431
|
+
fetchQuietly(cwd, intervalMs);
|
|
27125
27432
|
const found = readMovement(cwd);
|
|
27126
27433
|
if (found) finish({ kind: "moved", upstream, ...found });
|
|
27127
27434
|
}, intervalMs);
|
|
27128
|
-
const deadline = setTimeout(
|
|
27435
|
+
const deadline = timeoutMs === void 0 ? void 0 : setTimeout(
|
|
27129
27436
|
() => finish({ kind: "timeout", upstream, timeout }),
|
|
27130
27437
|
timeoutMs
|
|
27131
27438
|
);
|
|
@@ -27133,22 +27440,36 @@ function waitForUpstream(options2) {
|
|
|
27133
27440
|
});
|
|
27134
27441
|
}
|
|
27135
27442
|
|
|
27136
|
-
// src/commands/watch/
|
|
27137
|
-
function
|
|
27443
|
+
// src/commands/watch/waitForUpstream.ts
|
|
27444
|
+
function waitForUpstream(options2) {
|
|
27445
|
+
const { intervalMs, timeoutMs, timeout, cwd, onStart } = options2;
|
|
27446
|
+
let upstream;
|
|
27138
27447
|
try {
|
|
27139
|
-
|
|
27448
|
+
upstream = resolveUpstream(cwd).upstream;
|
|
27140
27449
|
} catch (error) {
|
|
27141
|
-
|
|
27142
|
-
|
|
27450
|
+
return Promise.resolve({
|
|
27451
|
+
kind: "unavailable",
|
|
27452
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
27453
|
+
});
|
|
27143
27454
|
}
|
|
27455
|
+
onStart?.(upstream);
|
|
27456
|
+
fetchQuietly(cwd, intervalMs);
|
|
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,51 @@ 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
|
|
27173
|
-
).option(
|
|
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)"
|
|
27503
|
+
).option(
|
|
27504
|
+
"--interval <duration>",
|
|
27505
|
+
"How often to fetch after the fetch at startup (e.g. 30s, 2m)",
|
|
27506
|
+
"30s"
|
|
27507
|
+
).option(
|
|
27174
27508
|
"--timeout <duration>",
|
|
27175
|
-
"Give up and exit 2 after this long (e.g. 60m, 2h)",
|
|
27176
|
-
"
|
|
27509
|
+
"Give up and exit 2 after this long (e.g. 60m, 2h), or none to wait indefinitely",
|
|
27510
|
+
"none"
|
|
27177
27511
|
).option(
|
|
27178
27512
|
"--pull",
|
|
27179
|
-
"On movement, fast-forward with git pull --ff-only; exit 3 with git's reason
|
|
27513
|
+
"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"
|
|
27514
|
+
).option(
|
|
27515
|
+
"--build [entry]",
|
|
27516
|
+
"After a successful pull, run this run entry (default auto-build); exit 4 with its output when it fails"
|
|
27180
27517
|
).action(
|
|
27181
27518
|
(options2) => watchWait(options2)
|
|
27182
27519
|
);
|
|
27520
|
+
watchCommand.command("report").description(
|
|
27521
|
+
"Print the built version, the last 10 commits as a markdown table, and the restarts the new commits make necessary"
|
|
27522
|
+
).option(
|
|
27523
|
+
"--from <sha>",
|
|
27524
|
+
"Mark commits reachable from HEAD but not <sha> as new, and derive restart advice from the files they changed"
|
|
27525
|
+
).action((options2) => watchReport(options2));
|
|
27183
27526
|
}
|
|
27184
27527
|
|
|
27185
27528
|
// src/commands/roam/auth.ts
|
|
@@ -27205,7 +27548,7 @@ function extractCode(url, expectedState) {
|
|
|
27205
27548
|
return code;
|
|
27206
27549
|
}
|
|
27207
27550
|
function waitForCallback(port, expectedState) {
|
|
27208
|
-
return new Promise((
|
|
27551
|
+
return new Promise((resolve22, reject) => {
|
|
27209
27552
|
const timeout = setTimeout(() => {
|
|
27210
27553
|
server.close();
|
|
27211
27554
|
reject(new Error("Authorization timed out after 120 seconds"));
|
|
@@ -27222,7 +27565,7 @@ function waitForCallback(port, expectedState) {
|
|
|
27222
27565
|
const code = extractCode(url, expectedState);
|
|
27223
27566
|
respondHtml(res, 200, "Authorization successful!");
|
|
27224
27567
|
server.close();
|
|
27225
|
-
|
|
27568
|
+
resolve22(code);
|
|
27226
27569
|
} catch (error) {
|
|
27227
27570
|
respondHtml(res, 400, error.message);
|
|
27228
27571
|
server.close();
|
|
@@ -27342,9 +27685,9 @@ async function auth() {
|
|
|
27342
27685
|
}
|
|
27343
27686
|
|
|
27344
27687
|
// src/commands/roam/postRoamActivity.ts
|
|
27345
|
-
import { execFileSync as
|
|
27688
|
+
import { execFileSync as execFileSync13 } from "child_process";
|
|
27346
27689
|
import { readdirSync as readdirSync12, readFileSync as readFileSync48, statSync as statSync10 } from "fs";
|
|
27347
|
-
import { join as
|
|
27690
|
+
import { join as join69 } from "path";
|
|
27348
27691
|
function findPortFile(roamDir) {
|
|
27349
27692
|
let entries;
|
|
27350
27693
|
try {
|
|
@@ -27353,7 +27696,7 @@ function findPortFile(roamDir) {
|
|
|
27353
27696
|
return void 0;
|
|
27354
27697
|
}
|
|
27355
27698
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
27356
|
-
const path71 =
|
|
27699
|
+
const path71 = join69(roamDir, name);
|
|
27357
27700
|
try {
|
|
27358
27701
|
return { path: path71, mtimeMs: statSync10(path71).mtimeMs };
|
|
27359
27702
|
} catch {
|
|
@@ -27365,7 +27708,7 @@ function findPortFile(roamDir) {
|
|
|
27365
27708
|
function postRoamActivity(app, event) {
|
|
27366
27709
|
const appData = process.env.APPDATA;
|
|
27367
27710
|
if (!appData) return;
|
|
27368
|
-
const portFile = findPortFile(
|
|
27711
|
+
const portFile = findPortFile(join69(appData, "Roam"));
|
|
27369
27712
|
if (!portFile) return;
|
|
27370
27713
|
let port;
|
|
27371
27714
|
try {
|
|
@@ -27375,7 +27718,7 @@ function postRoamActivity(app, event) {
|
|
|
27375
27718
|
}
|
|
27376
27719
|
const url = `http://127.0.0.1:${port}/api/v1/activity/${app}/${event}?pid=${app === "codex" ? 99998 : 99999}`;
|
|
27377
27720
|
try {
|
|
27378
|
-
|
|
27721
|
+
execFileSync13("curl", ["-sf", "--max-time", "0.2", "-X", "POST", url], {
|
|
27379
27722
|
stdio: "ignore"
|
|
27380
27723
|
});
|
|
27381
27724
|
} catch {
|
|
@@ -27499,53 +27842,7 @@ var rootConfigHelp = {
|
|
|
27499
27842
|
};
|
|
27500
27843
|
|
|
27501
27844
|
// 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
|
-
}
|
|
27845
|
+
import { resolve as resolve18 } from "path";
|
|
27549
27846
|
|
|
27550
27847
|
// src/commands/run/formatConfiguredCommands.ts
|
|
27551
27848
|
function formatConfiguredCommands() {
|
|
@@ -27558,84 +27855,23 @@ Configured commands:
|
|
|
27558
27855
|
${names}`;
|
|
27559
27856
|
}
|
|
27560
27857
|
|
|
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
27858
|
// 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
27859
|
function spawnRunCommand(command, args, env, cwd, quiet) {
|
|
27614
27860
|
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));
|
|
27861
|
+
void runCommandToCompletion(command, args, env, cwd, quiet).then((result) => {
|
|
27862
|
+
if (result.kind === "failed") {
|
|
27863
|
+
console.error(result.message);
|
|
27864
|
+
process.exit(1);
|
|
27865
|
+
}
|
|
27866
|
+
const { exitCode, output } = result;
|
|
27867
|
+
if (quiet && exitCode !== 0 && output.length > 0) {
|
|
27868
|
+
process.stdout.write(output);
|
|
27629
27869
|
}
|
|
27630
27870
|
const elapsed = formatElapsed(Date.now() - start3);
|
|
27631
27871
|
if (!quiet || exitCode !== 0) console.log(`
|
|
27632
27872
|
Done in ${elapsed}`);
|
|
27633
27873
|
process.exit(exitCode);
|
|
27634
27874
|
});
|
|
27635
|
-
child.on("error", (err) => {
|
|
27636
|
-
console.error(`Failed to execute command: ${err.message}`);
|
|
27637
|
-
process.exit(1);
|
|
27638
|
-
});
|
|
27639
27875
|
}
|
|
27640
27876
|
|
|
27641
27877
|
// src/commands/run/index.ts
|
|
@@ -27651,7 +27887,7 @@ function listRunConfigs(verbose) {
|
|
|
27651
27887
|
}
|
|
27652
27888
|
}
|
|
27653
27889
|
function execRunConfig(config, args) {
|
|
27654
|
-
const cwd = config.cwd ?
|
|
27890
|
+
const cwd = config.cwd ? resolve18(getConfigDir(), config.cwd) : void 0;
|
|
27655
27891
|
if (config.pre) runPreCommands(config.pre, cwd);
|
|
27656
27892
|
const resolved = resolveParams(config.params, args);
|
|
27657
27893
|
spawnRunCommand(
|
|
@@ -27693,7 +27929,7 @@ async function run3(name, args) {
|
|
|
27693
27929
|
|
|
27694
27930
|
// src/commands/run/add.ts
|
|
27695
27931
|
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync41 } from "fs";
|
|
27696
|
-
import { join as
|
|
27932
|
+
import { join as join70 } from "path";
|
|
27697
27933
|
|
|
27698
27934
|
// src/commands/run/extractOption.ts
|
|
27699
27935
|
function extractOption(args, flag) {
|
|
@@ -27754,7 +27990,7 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
27754
27990
|
saveConfig(config);
|
|
27755
27991
|
}
|
|
27756
27992
|
function createCommandFile(name) {
|
|
27757
|
-
const dir =
|
|
27993
|
+
const dir = join70(".claude", "commands");
|
|
27758
27994
|
mkdirSync24(dir, { recursive: true });
|
|
27759
27995
|
const content = `---
|
|
27760
27996
|
description: Run ${name}
|
|
@@ -27762,7 +27998,7 @@ description: Run ${name}
|
|
|
27762
27998
|
|
|
27763
27999
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
27764
28000
|
`;
|
|
27765
|
-
const filePath =
|
|
28001
|
+
const filePath = join70(dir, `${name}.md`);
|
|
27766
28002
|
writeFileSync41(filePath, content);
|
|
27767
28003
|
console.log(`Created command file: ${filePath}`);
|
|
27768
28004
|
}
|
|
@@ -27819,7 +28055,7 @@ function link2() {
|
|
|
27819
28055
|
|
|
27820
28056
|
// src/commands/run/remove.ts
|
|
27821
28057
|
import { existsSync as existsSync59, unlinkSync as unlinkSync21 } from "fs";
|
|
27822
|
-
import { join as
|
|
28058
|
+
import { join as join71 } from "path";
|
|
27823
28059
|
function findRemoveIndex() {
|
|
27824
28060
|
const idx = process.argv.indexOf("remove");
|
|
27825
28061
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -27834,7 +28070,7 @@ function parseRemoveName() {
|
|
|
27834
28070
|
return process.argv[idx + 1];
|
|
27835
28071
|
}
|
|
27836
28072
|
function deleteCommandFile(name) {
|
|
27837
|
-
const filePath =
|
|
28073
|
+
const filePath = join71(".claude", "commands", `${name}.md`);
|
|
27838
28074
|
if (existsSync59(filePath)) {
|
|
27839
28075
|
unlinkSync21(filePath);
|
|
27840
28076
|
console.log(`Deleted command file: ${filePath}`);
|
|
@@ -27891,7 +28127,7 @@ function registerRun(program2) {
|
|
|
27891
28127
|
import { execSync as execSync61 } from "child_process";
|
|
27892
28128
|
import { existsSync as existsSync60, mkdirSync as mkdirSync25, unlinkSync as unlinkSync22, writeFileSync as writeFileSync42 } from "fs";
|
|
27893
28129
|
import { tmpdir as tmpdir8 } from "os";
|
|
27894
|
-
import { join as
|
|
28130
|
+
import { join as join72, resolve as resolve19 } from "path";
|
|
27895
28131
|
import chalk209 from "chalk";
|
|
27896
28132
|
|
|
27897
28133
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -28025,10 +28261,10 @@ function buildOutputPath(outputDir, processName) {
|
|
|
28025
28261
|
mkdirSync25(outputDir, { recursive: true });
|
|
28026
28262
|
}
|
|
28027
28263
|
const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
28028
|
-
return
|
|
28264
|
+
return resolve19(outputDir, `${processName}-${timestamp6}.png`);
|
|
28029
28265
|
}
|
|
28030
28266
|
function runPowerShellScript(processName, outputPath) {
|
|
28031
|
-
const scriptPath =
|
|
28267
|
+
const scriptPath = join72(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
|
|
28032
28268
|
writeFileSync42(scriptPath, captureWindowPs1, "utf8");
|
|
28033
28269
|
try {
|
|
28034
28270
|
execSync61(
|
|
@@ -28041,7 +28277,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
28041
28277
|
}
|
|
28042
28278
|
function screenshot(processName) {
|
|
28043
28279
|
const config = loadConfig();
|
|
28044
|
-
const outputDir =
|
|
28280
|
+
const outputDir = resolve19(config.screenshot.outputDir);
|
|
28045
28281
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
28046
28282
|
console.log(chalk209.gray(`Capturing window for process "${processName}" ...`));
|
|
28047
28283
|
try {
|
|
@@ -28074,18 +28310,18 @@ var STATUS_TIMEOUT_MS = 5e3;
|
|
|
28074
28310
|
function queryDaemon(socket) {
|
|
28075
28311
|
socket.write(`${JSON.stringify({ type: "ping" })}
|
|
28076
28312
|
`);
|
|
28077
|
-
return new Promise((
|
|
28313
|
+
return new Promise((resolve22) => {
|
|
28078
28314
|
const result = { sessions: [] };
|
|
28079
28315
|
const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
|
|
28080
|
-
const timer = setTimeout(() =>
|
|
28081
|
-
const
|
|
28082
|
-
|
|
28316
|
+
const timer = setTimeout(() => resolve22(result), STATUS_TIMEOUT_MS);
|
|
28317
|
+
const lines2 = createInterface5({ input: socket });
|
|
28318
|
+
lines2.on("error", () => {
|
|
28083
28319
|
});
|
|
28084
|
-
|
|
28320
|
+
lines2.on("line", (line) => {
|
|
28085
28321
|
applyLine(result, pending, line);
|
|
28086
28322
|
if (pending.size === 0) {
|
|
28087
28323
|
clearTimeout(timer);
|
|
28088
|
-
|
|
28324
|
+
resolve22(result);
|
|
28089
28325
|
}
|
|
28090
28326
|
});
|
|
28091
28327
|
});
|
|
@@ -28170,12 +28406,12 @@ function clearPersistedSessionsOnDrain() {
|
|
|
28170
28406
|
}
|
|
28171
28407
|
|
|
28172
28408
|
// src/commands/sessions/daemon/readDaemonMessage.ts
|
|
28173
|
-
function readDaemonMessage(
|
|
28174
|
-
return new Promise((
|
|
28409
|
+
function readDaemonMessage(lines2, timeoutMs, fallback, match) {
|
|
28410
|
+
return new Promise((resolve22) => {
|
|
28175
28411
|
const finish = (value) => {
|
|
28176
28412
|
clearTimeout(timer);
|
|
28177
|
-
|
|
28178
|
-
|
|
28413
|
+
lines2.off("line", onLine);
|
|
28414
|
+
resolve22(value);
|
|
28179
28415
|
};
|
|
28180
28416
|
const timer = setTimeout(() => finish(fallback), timeoutMs);
|
|
28181
28417
|
const onLine = (line) => {
|
|
@@ -28185,7 +28421,7 @@ function readDaemonMessage(lines, timeoutMs, fallback, match) {
|
|
|
28185
28421
|
} catch {
|
|
28186
28422
|
}
|
|
28187
28423
|
};
|
|
28188
|
-
|
|
28424
|
+
lines2.on("line", onLine);
|
|
28189
28425
|
});
|
|
28190
28426
|
}
|
|
28191
28427
|
|
|
@@ -28200,10 +28436,10 @@ async function drainDaemon(options2 = {}) {
|
|
|
28200
28436
|
clearPersistedSessionsOnDrain();
|
|
28201
28437
|
return;
|
|
28202
28438
|
}
|
|
28203
|
-
const
|
|
28204
|
-
|
|
28439
|
+
const lines2 = createInterface6({ input: socket });
|
|
28440
|
+
lines2.on("error", () => {
|
|
28205
28441
|
});
|
|
28206
|
-
const live = await liveSessions(
|
|
28442
|
+
const live = await liveSessions(lines2);
|
|
28207
28443
|
if (live.length > 0 && options2.yes !== true) {
|
|
28208
28444
|
reportLive(live);
|
|
28209
28445
|
if (!await confirmDrain()) {
|
|
@@ -28211,7 +28447,7 @@ async function drainDaemon(options2 = {}) {
|
|
|
28211
28447
|
return;
|
|
28212
28448
|
}
|
|
28213
28449
|
}
|
|
28214
|
-
const count8 = await requestDrain(socket,
|
|
28450
|
+
const count8 = await requestDrain(socket, lines2);
|
|
28215
28451
|
socket.destroy();
|
|
28216
28452
|
console.log(`Drained ${count8} session(s)`);
|
|
28217
28453
|
}
|
|
@@ -28230,9 +28466,9 @@ async function confirmDrain() {
|
|
|
28230
28466
|
console.log("Drain cancelled");
|
|
28231
28467
|
return false;
|
|
28232
28468
|
}
|
|
28233
|
-
function liveSessions(
|
|
28469
|
+
function liveSessions(lines2) {
|
|
28234
28470
|
return readDaemonMessage(
|
|
28235
|
-
|
|
28471
|
+
lines2,
|
|
28236
28472
|
LIST_TIMEOUT_MS,
|
|
28237
28473
|
[],
|
|
28238
28474
|
(data) => data.type === "sessions" ? (data.sessions ?? []).filter(
|
|
@@ -28240,11 +28476,11 @@ function liveSessions(lines) {
|
|
|
28240
28476
|
) : void 0
|
|
28241
28477
|
);
|
|
28242
28478
|
}
|
|
28243
|
-
function requestDrain(socket,
|
|
28479
|
+
function requestDrain(socket, lines2) {
|
|
28244
28480
|
socket.write(`${JSON.stringify({ type: "drain" })}
|
|
28245
28481
|
`);
|
|
28246
28482
|
return readDaemonMessage(
|
|
28247
|
-
|
|
28483
|
+
lines2,
|
|
28248
28484
|
DRAIN_TIMEOUT_MS,
|
|
28249
28485
|
0,
|
|
28250
28486
|
(data) => data.type === "drained" ? data.count ?? 0 : void 0
|
|
@@ -28709,12 +28945,12 @@ import { basename as basename18 } from "path";
|
|
|
28709
28945
|
|
|
28710
28946
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
28711
28947
|
import { existsSync as existsSync63 } from "fs";
|
|
28712
|
-
import { join as
|
|
28948
|
+
import { join as join75 } from "path";
|
|
28713
28949
|
|
|
28714
28950
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
28715
28951
|
import { statSync as statSync12 } from "fs";
|
|
28716
28952
|
import { rm as rm2 } from "fs/promises";
|
|
28717
|
-
import { join as
|
|
28953
|
+
import { join as join74 } from "path";
|
|
28718
28954
|
async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
28719
28955
|
if (holdsAGitDirectoryRatherThanALink(worktreePath)) {
|
|
28720
28956
|
daemonLog(
|
|
@@ -28741,7 +28977,7 @@ async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
|
28741
28977
|
return true;
|
|
28742
28978
|
}
|
|
28743
28979
|
function holdsAGitDirectoryRatherThanALink(worktreePath) {
|
|
28744
|
-
return statSync12(
|
|
28980
|
+
return statSync12(join74(worktreePath, ".git"), {
|
|
28745
28981
|
throwIfNoEntry: false
|
|
28746
28982
|
})?.isDirectory() === true;
|
|
28747
28983
|
}
|
|
@@ -28777,7 +29013,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
28777
29013
|
);
|
|
28778
29014
|
}
|
|
28779
29015
|
function strandedReason(worktreePath, cause) {
|
|
28780
|
-
if (!existsSync63(
|
|
29016
|
+
if (!existsSync63(join75(worktreePath, ".git")))
|
|
28781
29017
|
return "its .git link is already gone";
|
|
28782
29018
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
28783
29019
|
return "git no longer recognises it as a working tree";
|
|
@@ -30000,9 +30236,9 @@ async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
|
30000
30236
|
|
|
30001
30237
|
// src/commands/sessions/shared/transcriptUsage.ts
|
|
30002
30238
|
import * as fs38 from "fs";
|
|
30003
|
-
function transcriptUsage(
|
|
30239
|
+
function transcriptUsage(lines2) {
|
|
30004
30240
|
const byId = /* @__PURE__ */ new Map();
|
|
30005
|
-
for (const line of
|
|
30241
|
+
for (const line of lines2) {
|
|
30006
30242
|
if (!line.trim()) continue;
|
|
30007
30243
|
let entry;
|
|
30008
30244
|
try {
|
|
@@ -30701,29 +30937,29 @@ async function describeHeldWork(path71, reason4) {
|
|
|
30701
30937
|
}
|
|
30702
30938
|
async function changedFiles(path71) {
|
|
30703
30939
|
const status3 = await gitResult(path71, ["status", "--porcelain"]);
|
|
30704
|
-
const
|
|
30940
|
+
const lines2 = status3.ok ? nonEmptyLines(status3.out) : [];
|
|
30705
30941
|
return {
|
|
30706
|
-
summary: `${
|
|
30707
|
-
items: capped(
|
|
30942
|
+
summary: `${lines2.length} uncommitted ${lines2.length === 1 ? "file" : "files"}`,
|
|
30943
|
+
items: capped(lines2)
|
|
30708
30944
|
};
|
|
30709
30945
|
}
|
|
30710
30946
|
async function unpushedCommits(path71, reason4) {
|
|
30711
30947
|
const log2 = await gitResult(path71, ["log", "--oneline", "@{upstream}..HEAD"]);
|
|
30712
30948
|
if (!log2.ok) return { summary: reason4, items: [] };
|
|
30713
|
-
const
|
|
30949
|
+
const lines2 = nonEmptyLines(log2.out);
|
|
30714
30950
|
return {
|
|
30715
|
-
summary: `${
|
|
30716
|
-
items: capped(
|
|
30951
|
+
summary: `${lines2.length} unpushed ${lines2.length === 1 ? "commit" : "commits"}`,
|
|
30952
|
+
items: capped(lines2)
|
|
30717
30953
|
};
|
|
30718
30954
|
}
|
|
30719
30955
|
function nonEmptyLines(out) {
|
|
30720
30956
|
return out.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
30721
30957
|
}
|
|
30722
|
-
function capped(
|
|
30723
|
-
if (
|
|
30958
|
+
function capped(lines2) {
|
|
30959
|
+
if (lines2.length <= MAX_ITEMS) return lines2;
|
|
30724
30960
|
return [
|
|
30725
|
-
...
|
|
30726
|
-
`\u2026 and ${
|
|
30961
|
+
...lines2.slice(0, MAX_ITEMS),
|
|
30962
|
+
`\u2026 and ${lines2.length - MAX_ITEMS} more`
|
|
30727
30963
|
];
|
|
30728
30964
|
}
|
|
30729
30965
|
|
|
@@ -31204,7 +31440,7 @@ function windowsDaemonHost() {
|
|
|
31204
31440
|
var CONNECT_TIMEOUT_MS = 2e3;
|
|
31205
31441
|
var KEEPALIVE_PROBE_MS = 1e4;
|
|
31206
31442
|
function connectToWindowsDaemon() {
|
|
31207
|
-
return new Promise((
|
|
31443
|
+
return new Promise((resolve22, reject) => {
|
|
31208
31444
|
const socket = net2.connect(windowsDaemonPort(), windowsDaemonHost());
|
|
31209
31445
|
socket.setTimeout(CONNECT_TIMEOUT_MS);
|
|
31210
31446
|
socket.once("timeout", () => {
|
|
@@ -31214,7 +31450,7 @@ function connectToWindowsDaemon() {
|
|
|
31214
31450
|
socket.once("connect", () => {
|
|
31215
31451
|
socket.setTimeout(0);
|
|
31216
31452
|
socket.setKeepAlive(true, KEEPALIVE_PROBE_MS);
|
|
31217
|
-
|
|
31453
|
+
resolve22(socket);
|
|
31218
31454
|
});
|
|
31219
31455
|
socket.once("error", reject);
|
|
31220
31456
|
});
|
|
@@ -31235,9 +31471,9 @@ import { spawn as spawn11 } from "child_process";
|
|
|
31235
31471
|
import { createInterface as createInterface7 } from "readline";
|
|
31236
31472
|
function logChildStream(stream, label2) {
|
|
31237
31473
|
if (!stream) return;
|
|
31238
|
-
const
|
|
31239
|
-
|
|
31240
|
-
|
|
31474
|
+
const lines2 = createInterface7({ input: stream });
|
|
31475
|
+
lines2.on("line", (line) => daemonLog(`[${label2}] ${line}`));
|
|
31476
|
+
lines2.on("error", () => {
|
|
31241
31477
|
});
|
|
31242
31478
|
}
|
|
31243
31479
|
|
|
@@ -31292,7 +31528,7 @@ async function waitForWindowsDaemon() {
|
|
|
31292
31528
|
);
|
|
31293
31529
|
}
|
|
31294
31530
|
function delay2(ms) {
|
|
31295
|
-
return new Promise((
|
|
31531
|
+
return new Promise((resolve22) => setTimeout(resolve22, ms));
|
|
31296
31532
|
}
|
|
31297
31533
|
|
|
31298
31534
|
// src/commands/sessions/daemon/defaultConnect.ts
|
|
@@ -31576,7 +31812,7 @@ async function healWindowsDaemon() {
|
|
|
31576
31812
|
daemonLog("windows daemon: auto-heal: stale daemon stopped");
|
|
31577
31813
|
}
|
|
31578
31814
|
function runOnWindowsHost(command, timeoutMs) {
|
|
31579
|
-
return new Promise((
|
|
31815
|
+
return new Promise((resolve22, reject) => {
|
|
31580
31816
|
const child = spawn12("pwsh.exe", ["-Command", command], {
|
|
31581
31817
|
stdio: ["ignore", "pipe", "pipe"]
|
|
31582
31818
|
});
|
|
@@ -31596,7 +31832,7 @@ function runOnWindowsHost(command, timeoutMs) {
|
|
|
31596
31832
|
});
|
|
31597
31833
|
child.on("exit", (code) => {
|
|
31598
31834
|
clearTimeout(timer);
|
|
31599
|
-
if (code === 0)
|
|
31835
|
+
if (code === 0) resolve22();
|
|
31600
31836
|
else
|
|
31601
31837
|
reject(
|
|
31602
31838
|
new Error(
|
|
@@ -31707,10 +31943,10 @@ var WindowsConnection = class {
|
|
|
31707
31943
|
return socket;
|
|
31708
31944
|
}
|
|
31709
31945
|
wire(socket) {
|
|
31710
|
-
const
|
|
31711
|
-
|
|
31946
|
+
const lines2 = createInterface8({ input: socket });
|
|
31947
|
+
lines2.on("error", () => {
|
|
31712
31948
|
});
|
|
31713
|
-
|
|
31949
|
+
lines2.on("line", (line) => this.deps.onLine(line));
|
|
31714
31950
|
socket.on("error", () => {
|
|
31715
31951
|
});
|
|
31716
31952
|
socket.on("close", () => {
|
|
@@ -32309,9 +32545,9 @@ async function parseTranscript(sessionId) {
|
|
|
32309
32545
|
return [];
|
|
32310
32546
|
}
|
|
32311
32547
|
}
|
|
32312
|
-
function parseTranscriptLines(
|
|
32548
|
+
function parseTranscriptLines(lines2) {
|
|
32313
32549
|
const messages = [];
|
|
32314
|
-
for (const line of
|
|
32550
|
+
for (const line of lines2) {
|
|
32315
32551
|
const entry = line.trim() ? safeParse2(line) : null;
|
|
32316
32552
|
if (!entry || entry.isSidechain || entry.isMeta) continue;
|
|
32317
32553
|
messages.push(...entryMessages(entry));
|
|
@@ -32493,10 +32729,10 @@ function handleConnection(socket, manager) {
|
|
|
32493
32729
|
};
|
|
32494
32730
|
manager.addClient(client);
|
|
32495
32731
|
manager.clients.greet(client);
|
|
32496
|
-
const
|
|
32497
|
-
|
|
32732
|
+
const lines2 = createInterface9({ input: socket });
|
|
32733
|
+
lines2.on("error", () => {
|
|
32498
32734
|
});
|
|
32499
|
-
|
|
32735
|
+
lines2.on("line", (line) => {
|
|
32500
32736
|
let data;
|
|
32501
32737
|
try {
|
|
32502
32738
|
data = JSON.parse(line);
|
|
@@ -32957,9 +33193,9 @@ function buildLimitsSegment(rateLimits) {
|
|
|
32957
33193
|
|
|
32958
33194
|
// src/commands/readGitBranch.ts
|
|
32959
33195
|
import { readFileSync as readFileSync54, statSync as statSync14 } from "fs";
|
|
32960
|
-
import { isAbsolute as isAbsolute4, join as
|
|
33196
|
+
import { isAbsolute as isAbsolute4, join as join77, resolve as resolve20 } from "path";
|
|
32961
33197
|
function resolveGitDir(cwd) {
|
|
32962
|
-
const dotGit =
|
|
33198
|
+
const dotGit = join77(cwd, ".git");
|
|
32963
33199
|
let stat3;
|
|
32964
33200
|
try {
|
|
32965
33201
|
stat3 = statSync14(dotGit);
|
|
@@ -32980,7 +33216,7 @@ function resolveGitDir(cwd) {
|
|
|
32980
33216
|
return null;
|
|
32981
33217
|
}
|
|
32982
33218
|
const gitDir = match[1].trim();
|
|
32983
|
-
return isAbsolute4(gitDir) ? gitDir :
|
|
33219
|
+
return isAbsolute4(gitDir) ? gitDir : resolve20(cwd, gitDir);
|
|
32984
33220
|
}
|
|
32985
33221
|
function readGitBranch(cwd) {
|
|
32986
33222
|
const gitDir = resolveGitDir(cwd);
|
|
@@ -32989,7 +33225,7 @@ function readGitBranch(cwd) {
|
|
|
32989
33225
|
}
|
|
32990
33226
|
let head;
|
|
32991
33227
|
try {
|
|
32992
|
-
head = readFileSync54(
|
|
33228
|
+
head = readFileSync54(join77(gitDir, "HEAD"), "utf8");
|
|
32993
33229
|
} catch {
|
|
32994
33230
|
return null;
|
|
32995
33231
|
}
|