@staff0rd/assist 0.765.0 → 0.766.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/claude/skills/review-ci/scripts/review.mjs +94 -94
- package/dist/commands/sessions/web/bundle.js +399 -399
- package/dist/index.js +593 -553
- 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.766.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -1792,9 +1792,9 @@ var daemonPaths = {
|
|
|
1792
1792
|
|
|
1793
1793
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
1794
1794
|
function connectToDaemon() {
|
|
1795
|
-
return new Promise((
|
|
1795
|
+
return new Promise((resolve28, reject) => {
|
|
1796
1796
|
const socket = net.connect(daemonPaths.socket);
|
|
1797
|
-
socket.once("connect", () =>
|
|
1797
|
+
socket.once("connect", () => resolve28(socket));
|
|
1798
1798
|
socket.once("error", reject);
|
|
1799
1799
|
});
|
|
1800
1800
|
}
|
|
@@ -2112,7 +2112,7 @@ ${failed3.length} script(s) failed:`);
|
|
|
2112
2112
|
}
|
|
2113
2113
|
}
|
|
2114
2114
|
function runEntry(entry) {
|
|
2115
|
-
return new Promise((
|
|
2115
|
+
return new Promise((resolve28) => {
|
|
2116
2116
|
const startTime = Date.now();
|
|
2117
2117
|
const child = spawnCommand(
|
|
2118
2118
|
entry.fullCommand,
|
|
@@ -2124,7 +2124,7 @@ function runEntry(entry) {
|
|
|
2124
2124
|
child.on("close", (code) => {
|
|
2125
2125
|
const exitCode = code ?? 1;
|
|
2126
2126
|
flushIfFailed(exitCode, chunks);
|
|
2127
|
-
|
|
2127
|
+
resolve28({
|
|
2128
2128
|
script: entry.name,
|
|
2129
2129
|
code: exitCode,
|
|
2130
2130
|
durationMs: Date.now() - startTime
|
|
@@ -2941,13 +2941,21 @@ function toChecklist(value) {
|
|
|
2941
2941
|
];
|
|
2942
2942
|
});
|
|
2943
2943
|
}
|
|
2944
|
+
function toAttachments(value) {
|
|
2945
|
+
if (!Array.isArray(value)) return void 0;
|
|
2946
|
+
return value.flatMap((entry) => {
|
|
2947
|
+
const { path: path106, alt } = entry ?? {};
|
|
2948
|
+
if (typeof path106 !== "string" || path106 === "") return [];
|
|
2949
|
+
return [{ path: path106, alt: typeof alt === "string" ? alt : "" }];
|
|
2950
|
+
});
|
|
2951
|
+
}
|
|
2944
2952
|
function toPreviewDecision(msg) {
|
|
2945
2953
|
if (msg.decision !== "approve" && msg.decision !== "reject") return null;
|
|
2946
2954
|
return {
|
|
2947
2955
|
decision: msg.decision,
|
|
2948
2956
|
reason: msg.reason,
|
|
2949
2957
|
comments: Array.isArray(msg.comments) ? msg.comments : void 0,
|
|
2950
|
-
screenshots:
|
|
2958
|
+
screenshots: toAttachments(msg.screenshots),
|
|
2951
2959
|
body: typeof msg.body === "string" ? msg.body : void 0,
|
|
2952
2960
|
reviewAfter: msg.reviewAfter === true,
|
|
2953
2961
|
announceAfter: msg.announceAfter === true,
|
|
@@ -2974,7 +2982,7 @@ function parsePreviewDecision(line, requestId) {
|
|
|
2974
2982
|
|
|
2975
2983
|
// src/commands/sessions/shared/requestPreviewDecision.ts
|
|
2976
2984
|
function requestPreviewDecision(request) {
|
|
2977
|
-
return new Promise((
|
|
2985
|
+
return new Promise((resolve28, reject) => {
|
|
2978
2986
|
connectToDaemon().then((socket) => {
|
|
2979
2987
|
let settled = false;
|
|
2980
2988
|
const finish2 = (error, decision) => {
|
|
@@ -2982,7 +2990,7 @@ function requestPreviewDecision(request) {
|
|
|
2982
2990
|
settled = true;
|
|
2983
2991
|
socket.destroy();
|
|
2984
2992
|
if (error) reject(error);
|
|
2985
|
-
else
|
|
2993
|
+
else resolve28(decision);
|
|
2986
2994
|
};
|
|
2987
2995
|
readSocketLines(socket, (line) => {
|
|
2988
2996
|
const incoming = parsePreviewDecision(line, request.requestId);
|
|
@@ -7225,8 +7233,8 @@ function spawnInherit(command, args, options2 = {}) {
|
|
|
7225
7233
|
env: { ...env, ...options2.env },
|
|
7226
7234
|
cwd: options2.cwd
|
|
7227
7235
|
});
|
|
7228
|
-
const done2 = new Promise((
|
|
7229
|
-
child.on("close", (code) =>
|
|
7236
|
+
const done2 = new Promise((resolve28, reject) => {
|
|
7237
|
+
child.on("close", (code) => resolve28(code ?? 0));
|
|
7230
7238
|
child.on("error", reject);
|
|
7231
7239
|
});
|
|
7232
7240
|
return { child, done: done2 };
|
|
@@ -7658,7 +7666,7 @@ Failed to launch Claude for ${context}: ${message3}`)
|
|
|
7658
7666
|
// src/commands/sessions/daemon/sendToDaemon.ts
|
|
7659
7667
|
var WRITE_TIMEOUT_MS = 500;
|
|
7660
7668
|
function sendToDaemon(message3) {
|
|
7661
|
-
return new Promise((
|
|
7669
|
+
return new Promise((resolve28, reject) => {
|
|
7662
7670
|
connectToDaemon().then((socket) => {
|
|
7663
7671
|
const timer = setTimeout(() => {
|
|
7664
7672
|
socket.destroy();
|
|
@@ -7672,7 +7680,7 @@ function sendToDaemon(message3) {
|
|
|
7672
7680
|
`, () => {
|
|
7673
7681
|
clearTimeout(timer);
|
|
7674
7682
|
socket.end();
|
|
7675
|
-
|
|
7683
|
+
resolve28();
|
|
7676
7684
|
});
|
|
7677
7685
|
}, reject);
|
|
7678
7686
|
});
|
|
@@ -7681,7 +7689,7 @@ function sendToDaemon(message3) {
|
|
|
7681
7689
|
// src/commands/sessions/daemon/sendToDaemonAwaitAck.ts
|
|
7682
7690
|
var ACK_TIMEOUT_MS = 1e3;
|
|
7683
7691
|
function sendToDaemonAwaitAck(message3) {
|
|
7684
|
-
return new Promise((
|
|
7692
|
+
return new Promise((resolve28, reject) => {
|
|
7685
7693
|
connectToDaemon().then((socket) => {
|
|
7686
7694
|
let settled = false;
|
|
7687
7695
|
const finish2 = (error) => {
|
|
@@ -7690,7 +7698,7 @@ function sendToDaemonAwaitAck(message3) {
|
|
|
7690
7698
|
clearTimeout(timer);
|
|
7691
7699
|
socket.destroy();
|
|
7692
7700
|
if (error) reject(error);
|
|
7693
|
-
else
|
|
7701
|
+
else resolve28();
|
|
7694
7702
|
};
|
|
7695
7703
|
const timer = setTimeout(
|
|
7696
7704
|
() => finish2(new Error("timed out awaiting daemon ack")),
|
|
@@ -7781,7 +7789,7 @@ async function deliverReliably(sessionId, status2, payload) {
|
|
|
7781
7789
|
}
|
|
7782
7790
|
}
|
|
7783
7791
|
function sleep(ms) {
|
|
7784
|
-
return new Promise((
|
|
7792
|
+
return new Promise((resolve28) => setTimeout(resolve28, ms));
|
|
7785
7793
|
}
|
|
7786
7794
|
function describeError(error) {
|
|
7787
7795
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -10757,7 +10765,7 @@ function spawnDaemon(reason4) {
|
|
|
10757
10765
|
child.unref();
|
|
10758
10766
|
}
|
|
10759
10767
|
function delay(ms) {
|
|
10760
|
-
return new Promise((
|
|
10768
|
+
return new Promise((resolve28) => setTimeout(resolve28, ms));
|
|
10761
10769
|
}
|
|
10762
10770
|
|
|
10763
10771
|
// src/commands/sessions/daemon/originForCwd.ts
|
|
@@ -10799,10 +10807,10 @@ function gitInvocation(cwd, args) {
|
|
|
10799
10807
|
}
|
|
10800
10808
|
function git(cwd, args) {
|
|
10801
10809
|
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
10802
|
-
return new Promise((
|
|
10810
|
+
return new Promise((resolve28, reject) => {
|
|
10803
10811
|
execFile2(file, argv, options2, (error, stdout) => {
|
|
10804
10812
|
if (error) reject(error);
|
|
10805
|
-
else
|
|
10813
|
+
else resolve28(stdout.toString());
|
|
10806
10814
|
});
|
|
10807
10815
|
});
|
|
10808
10816
|
}
|
|
@@ -11061,7 +11069,7 @@ var defaultDeps = {
|
|
|
11061
11069
|
serve: async (args) => {
|
|
11062
11070
|
await runTailscale(args);
|
|
11063
11071
|
},
|
|
11064
|
-
sleep: (ms) => new Promise((
|
|
11072
|
+
sleep: (ms) => new Promise((resolve28) => setTimeout(resolve28, ms)),
|
|
11065
11073
|
httpsPort: tailnetHttpsPort
|
|
11066
11074
|
};
|
|
11067
11075
|
async function ensureTailscaleServe(port, deps2 = {}) {
|
|
@@ -11468,12 +11476,12 @@ async function loadVisibleItems(req) {
|
|
|
11468
11476
|
|
|
11469
11477
|
// src/commands/backlog/web/parseStatusBody.ts
|
|
11470
11478
|
function readBody(req) {
|
|
11471
|
-
return new Promise((
|
|
11479
|
+
return new Promise((resolve28, reject) => {
|
|
11472
11480
|
let body = "";
|
|
11473
11481
|
req.on("data", (chunk) => {
|
|
11474
11482
|
body += chunk.toString();
|
|
11475
11483
|
});
|
|
11476
|
-
req.on("end", () =>
|
|
11484
|
+
req.on("end", () => resolve28(body));
|
|
11477
11485
|
req.on("error", reject);
|
|
11478
11486
|
});
|
|
11479
11487
|
}
|
|
@@ -13582,11 +13590,11 @@ async function queryNodes() {
|
|
|
13582
13590
|
} catch {
|
|
13583
13591
|
return void 0;
|
|
13584
13592
|
}
|
|
13585
|
-
return new Promise((
|
|
13593
|
+
return new Promise((resolve28) => {
|
|
13586
13594
|
const finish2 = (result) => {
|
|
13587
13595
|
clearTimeout(timer);
|
|
13588
13596
|
socket.destroy();
|
|
13589
|
-
|
|
13597
|
+
resolve28(result);
|
|
13590
13598
|
};
|
|
13591
13599
|
const timer = setTimeout(() => finish2(void 0), QUERY_TIMEOUT_MS);
|
|
13592
13600
|
const lines2 = createInterface5({ input: socket });
|
|
@@ -13659,8 +13667,8 @@ function subsequenceScore(text17, query) {
|
|
|
13659
13667
|
function scoreFilePath(path106, query) {
|
|
13660
13668
|
const needle = query.trim().toLowerCase();
|
|
13661
13669
|
if (!needle) return 0;
|
|
13662
|
-
const
|
|
13663
|
-
const inBasename = subsequenceScore(
|
|
13670
|
+
const basename32 = path106.slice(path106.lastIndexOf("/") + 1);
|
|
13671
|
+
const inBasename = subsequenceScore(basename32, needle);
|
|
13664
13672
|
if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
|
|
13665
13673
|
return subsequenceScore(path106, needle);
|
|
13666
13674
|
}
|
|
@@ -15078,7 +15086,7 @@ function forwardToPeer(req, res, node, url) {
|
|
|
15078
15086
|
const label2 = `link ${node} http: ${req.method} ${url.pathname} trace=${traceId}`;
|
|
15079
15087
|
const log2 = (outcome) => console.log(`${label2} -> ${outcome} (${Date.now() - started}ms)`);
|
|
15080
15088
|
const send = url.protocol === "https:" ? httpsRequest : httpRequest;
|
|
15081
|
-
return new Promise((
|
|
15089
|
+
return new Promise((resolve28) => {
|
|
15082
15090
|
const upstream = send(
|
|
15083
15091
|
url,
|
|
15084
15092
|
{
|
|
@@ -15090,7 +15098,7 @@ function forwardToPeer(req, res, node, url) {
|
|
|
15090
15098
|
[TRACE_HEADER]: traceId
|
|
15091
15099
|
}
|
|
15092
15100
|
},
|
|
15093
|
-
(peer) => relayPeerResponse(peer, res, url.pathname, log2,
|
|
15101
|
+
(peer) => relayPeerResponse(peer, res, url.pathname, log2, resolve28)
|
|
15094
15102
|
);
|
|
15095
15103
|
boundUpstream(upstream, res, peerTimeoutFor(url.pathname));
|
|
15096
15104
|
upstream.on("error", (error) => {
|
|
@@ -15100,7 +15108,7 @@ function forwardToPeer(req, res, node, url) {
|
|
|
15100
15108
|
respondJson(res, 502, {
|
|
15101
15109
|
error: `${node} unreachable: ${error.message}`
|
|
15102
15110
|
});
|
|
15103
|
-
|
|
15111
|
+
resolve28();
|
|
15104
15112
|
});
|
|
15105
15113
|
req.pipe(upstream);
|
|
15106
15114
|
});
|
|
@@ -15153,64 +15161,74 @@ async function proxyToNode(req, res) {
|
|
|
15153
15161
|
return true;
|
|
15154
15162
|
}
|
|
15155
15163
|
|
|
15156
|
-
// src/commands/sessions/web/
|
|
15157
|
-
import {
|
|
15158
|
-
import {
|
|
15159
|
-
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
|
|
15167
|
-
|
|
15164
|
+
// src/commands/sessions/web/previewImage.ts
|
|
15165
|
+
import { createReadStream as createReadStream2 } from "fs";
|
|
15166
|
+
import { stat as stat3 } from "fs/promises";
|
|
15167
|
+
|
|
15168
|
+
// src/shared/isStagedAttachmentPath.ts
|
|
15169
|
+
import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve12, sep } from "path";
|
|
15170
|
+
|
|
15171
|
+
// src/shared/stagedAttachmentsDir.ts
|
|
15172
|
+
import { homedir as homedir15 } from "os";
|
|
15173
|
+
import { join as join38 } from "path";
|
|
15174
|
+
var stagedAttachmentsDir = join38(homedir15(), ".assist", "attachments");
|
|
15175
|
+
|
|
15176
|
+
// src/shared/isStagedAttachmentPath.ts
|
|
15177
|
+
function isStagedAttachmentPath(path106) {
|
|
15178
|
+
const rel = relative3(stagedAttachmentsDir, resolve12(path106));
|
|
15179
|
+
return rel !== "" && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute3(rel);
|
|
15168
15180
|
}
|
|
15169
15181
|
|
|
15170
|
-
// src/commands/sessions/web/
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15182
|
+
// src/commands/sessions/web/attachmentContentType.ts
|
|
15183
|
+
import { extname } from "path";
|
|
15184
|
+
|
|
15185
|
+
// src/commands/sessions/web/attachmentMimeTypes.ts
|
|
15186
|
+
var attachmentMimeTypes = {
|
|
15187
|
+
"image/png": "png",
|
|
15188
|
+
"image/jpeg": "jpg",
|
|
15189
|
+
"image/gif": "gif",
|
|
15190
|
+
"image/webp": "webp",
|
|
15191
|
+
"image/svg+xml": "svg",
|
|
15192
|
+
"image/bmp": "bmp",
|
|
15193
|
+
"image/avif": "avif",
|
|
15194
|
+
"video/mp4": "mp4",
|
|
15195
|
+
"video/webm": "webm",
|
|
15196
|
+
"video/quicktime": "mov",
|
|
15197
|
+
"video/ogg": "ogv"
|
|
15198
|
+
};
|
|
15199
|
+
|
|
15200
|
+
// src/commands/sessions/web/attachmentContentType.ts
|
|
15201
|
+
function attachmentContentType(path106) {
|
|
15202
|
+
const ext = extname(path106).replace(/^\./, "").toLowerCase();
|
|
15203
|
+
const match = Object.entries(attachmentMimeTypes).find(([, e]) => e === ext);
|
|
15204
|
+
return match?.[0] ?? "application/octet-stream";
|
|
15174
15205
|
}
|
|
15175
15206
|
|
|
15176
15207
|
// src/commands/sessions/web/previewImage.ts
|
|
15177
15208
|
async function previewImage(req, res) {
|
|
15178
15209
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
15179
|
-
const
|
|
15180
|
-
if (!
|
|
15181
|
-
respondJson(res, 400, { error: "Not a
|
|
15182
|
-
return;
|
|
15183
|
-
}
|
|
15184
|
-
let token;
|
|
15185
|
-
try {
|
|
15186
|
-
token = await ghAuthToken(url.searchParams.get("cwd") ?? void 0);
|
|
15187
|
-
} catch {
|
|
15188
|
-
respondJson(res, 502, { error: "Could not read a GitHub token." });
|
|
15189
|
-
return;
|
|
15190
|
-
}
|
|
15191
|
-
let location;
|
|
15192
|
-
try {
|
|
15193
|
-
const upstream = await fetch(target, {
|
|
15194
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
15195
|
-
redirect: "manual"
|
|
15196
|
-
});
|
|
15197
|
-
location = upstream.headers.get("location");
|
|
15198
|
-
} catch {
|
|
15199
|
-
respondJson(res, 502, { error: "Could not reach GitHub." });
|
|
15210
|
+
const path106 = url.searchParams.get("path") ?? "";
|
|
15211
|
+
if (!isStagedAttachmentPath(path106)) {
|
|
15212
|
+
respondJson(res, 400, { error: "Not a staged attachment." });
|
|
15200
15213
|
return;
|
|
15201
15214
|
}
|
|
15202
|
-
|
|
15203
|
-
|
|
15215
|
+
const info = await stat3(path106).catch(() => null);
|
|
15216
|
+
if (!info?.isFile()) {
|
|
15217
|
+
respondJson(res, 404, { error: "Attachment is no longer staged." });
|
|
15204
15218
|
return;
|
|
15205
15219
|
}
|
|
15206
|
-
res.writeHead(
|
|
15207
|
-
|
|
15220
|
+
res.writeHead(200, {
|
|
15221
|
+
"Content-Type": attachmentContentType(path106),
|
|
15222
|
+
"Content-Length": info.size,
|
|
15223
|
+
"Cache-Control": "no-store"
|
|
15224
|
+
});
|
|
15225
|
+
createReadStream2(path106).pipe(res);
|
|
15208
15226
|
}
|
|
15209
15227
|
|
|
15210
15228
|
// src/commands/sessions/web/prStatus.ts
|
|
15211
|
-
import { execFile as
|
|
15212
|
-
import { promisify as
|
|
15213
|
-
var
|
|
15229
|
+
import { execFile as execFile9 } from "child_process";
|
|
15230
|
+
import { promisify as promisify9 } from "util";
|
|
15231
|
+
var execFileAsync8 = promisify9(execFile9);
|
|
15214
15232
|
function toPrSummary(parsed) {
|
|
15215
15233
|
if (typeof parsed.number !== "number") return null;
|
|
15216
15234
|
return {
|
|
@@ -15240,7 +15258,7 @@ var getOpenPrForBranch = createCachedGhJson(
|
|
|
15240
15258
|
);
|
|
15241
15259
|
async function getCurrentBranch(cwd) {
|
|
15242
15260
|
try {
|
|
15243
|
-
const { stdout } = await
|
|
15261
|
+
const { stdout } = await execFileAsync8(
|
|
15244
15262
|
"git",
|
|
15245
15263
|
["rev-parse", "--abbrev-ref", "HEAD"],
|
|
15246
15264
|
{ encoding: "utf8", windowsHide: true, cwd }
|
|
@@ -15680,17 +15698,17 @@ async function stopDaemon() {
|
|
|
15680
15698
|
}
|
|
15681
15699
|
}
|
|
15682
15700
|
function closedBeforeTimeout(socket) {
|
|
15683
|
-
return new Promise((
|
|
15701
|
+
return new Promise((resolve28) => {
|
|
15684
15702
|
const timer = setTimeout(() => {
|
|
15685
15703
|
socket.destroy();
|
|
15686
|
-
|
|
15704
|
+
resolve28(false);
|
|
15687
15705
|
}, STOP_TIMEOUT_MS);
|
|
15688
15706
|
socket.resume();
|
|
15689
15707
|
socket.on("error", () => {
|
|
15690
15708
|
});
|
|
15691
15709
|
socket.once("close", () => {
|
|
15692
15710
|
clearTimeout(timer);
|
|
15693
|
-
|
|
15711
|
+
resolve28(true);
|
|
15694
15712
|
});
|
|
15695
15713
|
});
|
|
15696
15714
|
}
|
|
@@ -15748,8 +15766,8 @@ async function restartWeb(req, res, deps2 = {}) {
|
|
|
15748
15766
|
return;
|
|
15749
15767
|
}
|
|
15750
15768
|
console.log(`restart ${target} ${linkedRequester(req)}`);
|
|
15751
|
-
await new Promise((
|
|
15752
|
-
res.once("finish",
|
|
15769
|
+
await new Promise((resolve28) => {
|
|
15770
|
+
res.once("finish", resolve28);
|
|
15753
15771
|
respondJson(res, 200, { ok: true });
|
|
15754
15772
|
});
|
|
15755
15773
|
await performRestart(target, deps2);
|
|
@@ -15765,7 +15783,7 @@ async function performRestart(target, deps2 = {}) {
|
|
|
15765
15783
|
}
|
|
15766
15784
|
|
|
15767
15785
|
// src/commands/sessions/web/revertDiffFile.ts
|
|
15768
|
-
import { relative as
|
|
15786
|
+
import { relative as relative4 } from "path";
|
|
15769
15787
|
|
|
15770
15788
|
// src/commands/sessions/web/revertPathChanges.ts
|
|
15771
15789
|
async function isTracked(cwd, path106) {
|
|
@@ -15796,7 +15814,7 @@ async function revertPathChanges(cwd, path106) {
|
|
|
15796
15814
|
async function revertDiffFile(req, res) {
|
|
15797
15815
|
const resolved = getFileTarget(req, res);
|
|
15798
15816
|
if (!resolved) return;
|
|
15799
|
-
const path106 =
|
|
15817
|
+
const path106 = relative4(repoRoot(resolved.cwd), resolved.target);
|
|
15800
15818
|
try {
|
|
15801
15819
|
await revertPathChanges(resolved.cwd, path106);
|
|
15802
15820
|
respondJson(res, 200, { reverted: path106 });
|
|
@@ -15814,13 +15832,13 @@ import { existsSync as existsSync39 } from "fs";
|
|
|
15814
15832
|
// src/commands/run/resolveCommand.ts
|
|
15815
15833
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
15816
15834
|
import { existsSync as existsSync38 } from "fs";
|
|
15817
|
-
import { dirname as dirname23, join as
|
|
15835
|
+
import { dirname as dirname23, join as join39, resolve as resolve13 } from "path";
|
|
15818
15836
|
function resolveCommand(command) {
|
|
15819
15837
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
15820
15838
|
try {
|
|
15821
15839
|
const gitPath = execFileSync4("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
15822
|
-
const gitRoot =
|
|
15823
|
-
const gitBash =
|
|
15840
|
+
const gitRoot = resolve13(dirname23(gitPath), "..");
|
|
15841
|
+
const gitBash = join39(gitRoot, "bin", "bash.exe");
|
|
15824
15842
|
if (existsSync38(gitBash)) return gitBash;
|
|
15825
15843
|
} catch {
|
|
15826
15844
|
return command;
|
|
@@ -15885,15 +15903,15 @@ async function selfUpdate(req, res, deps2 = {}) {
|
|
|
15885
15903
|
return;
|
|
15886
15904
|
}
|
|
15887
15905
|
console.log("self-update: updated; restarting daemon and web server");
|
|
15888
|
-
await new Promise((
|
|
15889
|
-
res.once("finish",
|
|
15906
|
+
await new Promise((resolve28) => {
|
|
15907
|
+
res.once("finish", resolve28);
|
|
15890
15908
|
respondJson(res, 200, { ok: true });
|
|
15891
15909
|
});
|
|
15892
15910
|
await performRestart("both", restartDeps);
|
|
15893
15911
|
}
|
|
15894
15912
|
|
|
15895
15913
|
// src/commands/sessions/web/revertDiffPaths.ts
|
|
15896
|
-
import { relative as
|
|
15914
|
+
import { relative as relative5 } from "path";
|
|
15897
15915
|
function requestedPaths(body) {
|
|
15898
15916
|
const paths = body.paths;
|
|
15899
15917
|
if (!Array.isArray(paths)) return null;
|
|
@@ -15923,7 +15941,7 @@ async function revertDiffPaths(req, res) {
|
|
|
15923
15941
|
failed3.push({ path: path106, error: "Path outside cwd" });
|
|
15924
15942
|
continue;
|
|
15925
15943
|
}
|
|
15926
|
-
const relativePath =
|
|
15944
|
+
const relativePath = relative5(root2, target);
|
|
15927
15945
|
try {
|
|
15928
15946
|
await revertPathChanges(cwd, relativePath);
|
|
15929
15947
|
reverted.push(relativePath);
|
|
@@ -15987,14 +16005,14 @@ function linkWebSocketUrl(url) {
|
|
|
15987
16005
|
return target.toString();
|
|
15988
16006
|
}
|
|
15989
16007
|
function connectLinkWebSocket(url, handlers) {
|
|
15990
|
-
return new Promise((
|
|
16008
|
+
return new Promise((resolve28, reject) => {
|
|
15991
16009
|
const ws = new WebSocket(linkWebSocketUrl(url), {
|
|
15992
16010
|
handshakeTimeout: HANDSHAKE_TIMEOUT_MS
|
|
15993
16011
|
});
|
|
15994
16012
|
let open = false;
|
|
15995
16013
|
ws.on("open", () => {
|
|
15996
16014
|
open = true;
|
|
15997
|
-
|
|
16015
|
+
resolve28({
|
|
15998
16016
|
send: (line) => {
|
|
15999
16017
|
if (ws.readyState !== WebSocket.OPEN) return false;
|
|
16000
16018
|
ws.send(line);
|
|
@@ -16020,8 +16038,8 @@ var HELLO_TIMEOUT_MS = 5e3;
|
|
|
16020
16038
|
async function probePeerHello(url) {
|
|
16021
16039
|
let settle = () => {
|
|
16022
16040
|
};
|
|
16023
|
-
const reply2 = new Promise((
|
|
16024
|
-
settle =
|
|
16041
|
+
const reply2 = new Promise((resolve28) => {
|
|
16042
|
+
settle = resolve28;
|
|
16025
16043
|
});
|
|
16026
16044
|
const socket = await connectLinkWebSocket(url, {
|
|
16027
16045
|
onLine: (line) => {
|
|
@@ -16900,47 +16918,6 @@ function unsetConfig(req, res) {
|
|
|
16900
16918
|
});
|
|
16901
16919
|
}
|
|
16902
16920
|
|
|
16903
|
-
// src/commands/sessions/web/uploadPrImage.ts
|
|
16904
|
-
import { rm } from "fs/promises";
|
|
16905
|
-
|
|
16906
|
-
// src/commands/sessions/web/runGhImage.ts
|
|
16907
|
-
import { execFile as execFile11 } from "child_process";
|
|
16908
|
-
import { promisify as promisify11 } from "util";
|
|
16909
|
-
var execFileAsync10 = promisify11(execFile11);
|
|
16910
|
-
var GhImageUnavailableError = class extends Error {
|
|
16911
|
-
name = "GhImageUnavailableError";
|
|
16912
|
-
};
|
|
16913
|
-
var GH_IMAGE_INSTALL_COMMAND = "gh extension install drogers0/gh-image";
|
|
16914
|
-
var INSTALL_HINT = `Install the gh-image extension: ${GH_IMAGE_INSTALL_COMMAND}`;
|
|
16915
|
-
async function runGhImage(filePath, cwd) {
|
|
16916
|
-
let stdout;
|
|
16917
|
-
try {
|
|
16918
|
-
({ stdout } = await execFileAsync10("gh", ["image", filePath], {
|
|
16919
|
-
cwd,
|
|
16920
|
-
windowsHide: true,
|
|
16921
|
-
maxBuffer: 10 * 1024 * 1024
|
|
16922
|
-
}));
|
|
16923
|
-
} catch (error) {
|
|
16924
|
-
const err = error;
|
|
16925
|
-
if (err.code === "ENOENT")
|
|
16926
|
-
throw new GhImageUnavailableError(
|
|
16927
|
-
`The GitHub CLI (\`gh\`) is not installed. ${INSTALL_HINT}`
|
|
16928
|
-
);
|
|
16929
|
-
const stderr = err.stderr ?? "";
|
|
16930
|
-
if (/unknown command "image"/i.test(stderr) || /extension.*not found/i.test(stderr))
|
|
16931
|
-
throw new GhImageUnavailableError(
|
|
16932
|
-
`The \`gh-image\` extension is not installed. ${INSTALL_HINT}`
|
|
16933
|
-
);
|
|
16934
|
-
throw new Error(
|
|
16935
|
-
`gh image failed: ${stderr.trim() || err.message || "unknown error"}`
|
|
16936
|
-
);
|
|
16937
|
-
}
|
|
16938
|
-
const lines2 = stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
16939
|
-
const markdown = lines2.find((line) => /^!\[.*]\(.+\)$/.test(line)) ?? lines2.find((line) => /^https?:\/\/\S+$/.test(line)) ?? lines2.find((line) => line.includes("http")) ?? lines2[0];
|
|
16940
|
-
if (!markdown) throw new Error("gh image produced no output");
|
|
16941
|
-
return markdown;
|
|
16942
|
-
}
|
|
16943
|
-
|
|
16944
16921
|
// src/commands/sessions/web/readRequestBuffer.ts
|
|
16945
16922
|
async function readRequestBuffer(req, limit) {
|
|
16946
16923
|
const chunks = [];
|
|
@@ -16960,67 +16937,50 @@ async function readRequestBuffer(req, limit) {
|
|
|
16960
16937
|
return overLimit ? null : Buffer.concat(chunks);
|
|
16961
16938
|
}
|
|
16962
16939
|
|
|
16963
|
-
// src/commands/sessions/web/
|
|
16964
|
-
|
|
16965
|
-
|
|
16966
|
-
function uploadSizeLimit(contentType) {
|
|
16967
|
-
const mime = contentType.split(";")[0].trim().toLowerCase();
|
|
16968
|
-
return mime.startsWith("video/") ? {
|
|
16969
|
-
maxBytes: MAX_VIDEO_BYTES,
|
|
16970
|
-
tooLargeMessage: "Video too large (max 100MB)."
|
|
16971
|
-
} : {
|
|
16972
|
-
maxBytes: MAX_IMAGE_BYTES,
|
|
16973
|
-
tooLargeMessage: "Image too large (max 25MB)."
|
|
16974
|
-
};
|
|
16975
|
-
}
|
|
16976
|
-
|
|
16977
|
-
// src/commands/sessions/web/writeTempImage.ts
|
|
16978
|
-
import { mkdtemp, writeFile as writeFile2 } from "fs/promises";
|
|
16979
|
-
import { tmpdir as tmpdir2 } from "os";
|
|
16980
|
-
import { extname, join as join39 } from "path";
|
|
16981
|
-
var EXT_BY_MIME = {
|
|
16982
|
-
"image/png": "png",
|
|
16983
|
-
"image/jpeg": "jpg",
|
|
16984
|
-
"image/gif": "gif",
|
|
16985
|
-
"image/webp": "webp",
|
|
16986
|
-
"image/svg+xml": "svg",
|
|
16987
|
-
"image/bmp": "bmp",
|
|
16988
|
-
"image/avif": "avif",
|
|
16989
|
-
"video/mp4": "mp4",
|
|
16990
|
-
"video/webm": "webm",
|
|
16991
|
-
"video/quicktime": "mov",
|
|
16992
|
-
"video/ogg": "ogv"
|
|
16993
|
-
};
|
|
16940
|
+
// src/commands/sessions/web/stageAttachment.ts
|
|
16941
|
+
import { mkdir as mkdir4, mkdtemp, writeFile as writeFile2 } from "fs/promises";
|
|
16942
|
+
import { extname as extname2, join as join40 } from "path";
|
|
16994
16943
|
function extensionFromMime(contentType) {
|
|
16995
16944
|
const mime = contentType.split(";")[0].trim().toLowerCase();
|
|
16996
|
-
const known =
|
|
16945
|
+
const known = attachmentMimeTypes[mime];
|
|
16997
16946
|
if (known) return known;
|
|
16998
16947
|
const subtype = mime.split("/")[1]?.replace(/^x-/, "").replace(/\+.*$/, "");
|
|
16999
16948
|
return subtype && /^[a-z0-9]+$/.test(subtype) ? subtype : void 0;
|
|
17000
16949
|
}
|
|
17001
16950
|
function pickExtension(name, contentType) {
|
|
17002
|
-
const fromName =
|
|
17003
|
-
if (fromName) return fromName;
|
|
16951
|
+
const fromName = extname2(name).replace(/^\./, "").toLowerCase();
|
|
16952
|
+
if (/^[a-z0-9]+$/.test(fromName)) return fromName;
|
|
17004
16953
|
return extensionFromMime(contentType) ?? "png";
|
|
17005
16954
|
}
|
|
17006
16955
|
function safeBaseName(name) {
|
|
17007
16956
|
const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]+/g, "-");
|
|
17008
16957
|
return base.replace(/^-+|-+$/g, "").slice(0, 60) || "screenshot";
|
|
17009
16958
|
}
|
|
17010
|
-
async function
|
|
17011
|
-
|
|
17012
|
-
const
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
);
|
|
16959
|
+
async function stageAttachment(name, contentType, body) {
|
|
16960
|
+
await mkdir4(stagedAttachmentsDir, { recursive: true });
|
|
16961
|
+
const dir = await mkdtemp(join40(stagedAttachmentsDir, "upload-"));
|
|
16962
|
+
const alt = safeBaseName(name);
|
|
16963
|
+
const filePath = join40(dir, `${alt}.${pickExtension(name, contentType)}`);
|
|
17016
16964
|
await writeFile2(filePath, body);
|
|
17017
|
-
return { dir, filePath };
|
|
16965
|
+
return { dir, filePath, alt };
|
|
16966
|
+
}
|
|
16967
|
+
|
|
16968
|
+
// src/commands/sessions/web/uploadSizeLimit.ts
|
|
16969
|
+
var MAX_IMAGE_BYTES = 25 * 1024 * 1024;
|
|
16970
|
+
var MAX_VIDEO_BYTES = 100 * 1024 * 1024;
|
|
16971
|
+
function uploadSizeLimit(contentType) {
|
|
16972
|
+
const mime = contentType.split(";")[0].trim().toLowerCase();
|
|
16973
|
+
return mime.startsWith("video/") ? {
|
|
16974
|
+
maxBytes: MAX_VIDEO_BYTES,
|
|
16975
|
+
tooLargeMessage: "Video too large (max 100MB)."
|
|
16976
|
+
} : {
|
|
16977
|
+
maxBytes: MAX_IMAGE_BYTES,
|
|
16978
|
+
tooLargeMessage: "Image too large (max 25MB)."
|
|
16979
|
+
};
|
|
17018
16980
|
}
|
|
17019
16981
|
|
|
17020
16982
|
// src/commands/sessions/web/uploadPrImage.ts
|
|
17021
16983
|
async function uploadPrImage(req, res) {
|
|
17022
|
-
const cwd = getCwdParam(req, res);
|
|
17023
|
-
if (!cwd) return;
|
|
17024
16984
|
const url = new URL(req.url ?? "/", "http://localhost");
|
|
17025
16985
|
const name = url.searchParams.get("name") ?? "";
|
|
17026
16986
|
const contentType = req.headers["content-type"] ?? "";
|
|
@@ -17034,41 +16994,30 @@ async function uploadPrImage(req, res) {
|
|
|
17034
16994
|
respondJson(res, 400, { error: "Empty upload." });
|
|
17035
16995
|
return;
|
|
17036
16996
|
}
|
|
17037
|
-
const { dir, filePath } = await writeTempImage(name, contentType, body);
|
|
17038
16997
|
try {
|
|
17039
|
-
const
|
|
17040
|
-
respondJson(res, 200, {
|
|
16998
|
+
const { filePath, alt } = await stageAttachment(name, contentType, body);
|
|
16999
|
+
respondJson(res, 200, { path: filePath, alt });
|
|
17041
17000
|
} catch (error) {
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
error: error.message,
|
|
17045
|
-
command: GH_IMAGE_INSTALL_COMMAND
|
|
17046
|
-
});
|
|
17047
|
-
} else {
|
|
17048
|
-
respondJson(res, 500, {
|
|
17049
|
-
error: error instanceof Error ? error.message : "Upload failed"
|
|
17050
|
-
});
|
|
17051
|
-
}
|
|
17052
|
-
} finally {
|
|
17053
|
-
await rm(dir, { recursive: true, force: true }).catch(() => {
|
|
17001
|
+
respondJson(res, 500, {
|
|
17002
|
+
error: error instanceof Error ? error.message : "Staging failed"
|
|
17054
17003
|
});
|
|
17055
17004
|
}
|
|
17056
17005
|
}
|
|
17057
17006
|
|
|
17058
17007
|
// src/commands/sessions/web/writeFileContent.ts
|
|
17059
|
-
import { readFile as readFile3, stat as
|
|
17008
|
+
import { readFile as readFile3, stat as stat4, writeFile as writeFile3 } from "fs/promises";
|
|
17060
17009
|
|
|
17061
17010
|
// src/commands/sessions/web/formatWithOxfmt.ts
|
|
17062
|
-
import { execFile as
|
|
17011
|
+
import { execFile as execFile10 } from "child_process";
|
|
17063
17012
|
import { existsSync as existsSync40 } from "fs";
|
|
17064
|
-
import { dirname as dirname24, join as
|
|
17065
|
-
import { promisify as
|
|
17066
|
-
var
|
|
17013
|
+
import { dirname as dirname24, join as join41 } from "path";
|
|
17014
|
+
import { promisify as promisify10 } from "util";
|
|
17015
|
+
var execFileAsync9 = promisify10(execFile10);
|
|
17067
17016
|
var TIMEOUT_MS = 15e3;
|
|
17068
17017
|
function findOxfmtScript(root2) {
|
|
17069
17018
|
let dir = root2;
|
|
17070
17019
|
for (; ; ) {
|
|
17071
|
-
const candidate =
|
|
17020
|
+
const candidate = join41(dir, "node_modules", "oxfmt", "bin", "oxfmt");
|
|
17072
17021
|
if (existsSync40(candidate)) return candidate;
|
|
17073
17022
|
const parent = dirname24(dir);
|
|
17074
17023
|
if (parent === dir) return void 0;
|
|
@@ -17078,7 +17027,7 @@ function findOxfmtScript(root2) {
|
|
|
17078
17027
|
async function formatWithOxfmt(target, root2) {
|
|
17079
17028
|
const script = findOxfmtScript(root2);
|
|
17080
17029
|
if (!script) return;
|
|
17081
|
-
await
|
|
17030
|
+
await execFileAsync9(process.execPath, [script, target], {
|
|
17082
17031
|
cwd: root2,
|
|
17083
17032
|
windowsHide: true,
|
|
17084
17033
|
timeout: TIMEOUT_MS
|
|
@@ -17110,7 +17059,7 @@ async function getFileWriteBody(req, res) {
|
|
|
17110
17059
|
var STALE_MESSAGE = "The file changed on disk since it was opened";
|
|
17111
17060
|
async function currentMtimeMs(target) {
|
|
17112
17061
|
try {
|
|
17113
|
-
return (await
|
|
17062
|
+
return (await stat4(target)).mtimeMs;
|
|
17114
17063
|
} catch {
|
|
17115
17064
|
return null;
|
|
17116
17065
|
}
|
|
@@ -17915,7 +17864,7 @@ import { basename as basename12 } from "path";
|
|
|
17915
17864
|
import { parse } from "shell-quote";
|
|
17916
17865
|
|
|
17917
17866
|
// src/shared/consumeRedirect.ts
|
|
17918
|
-
import { tmpdir as
|
|
17867
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
17919
17868
|
|
|
17920
17869
|
// src/shared/isRedirectTargetAllowed.ts
|
|
17921
17870
|
function isRedirectTargetAllowed(target, tmp) {
|
|
@@ -17943,7 +17892,7 @@ function consumeRedirect(tokens, opIndex, current) {
|
|
|
17943
17892
|
if (typeof target !== "string") {
|
|
17944
17893
|
return { ok: false, error: "unable to parse" };
|
|
17945
17894
|
}
|
|
17946
|
-
if (!isRedirectTargetAllowed(target,
|
|
17895
|
+
if (!isRedirectTargetAllowed(target, tmpdir2())) {
|
|
17947
17896
|
return {
|
|
17948
17897
|
ok: false,
|
|
17949
17898
|
error: `redirect target '${target}' is outside the OS temp directory`
|
|
@@ -18485,7 +18434,7 @@ function findTruncatedReadDenyRaw(rawCommand) {
|
|
|
18485
18434
|
}
|
|
18486
18435
|
|
|
18487
18436
|
// src/shared/isApprovedRead.ts
|
|
18488
|
-
import { resolve as
|
|
18437
|
+
import { resolve as resolve15, sep as sep2 } from "path";
|
|
18489
18438
|
|
|
18490
18439
|
// src/shared/appliesFixStructure.ts
|
|
18491
18440
|
var APPLY_RE = /^assist\s+github\s+issue\s+fix-structure\b.*\s--apply\b/;
|
|
@@ -18539,7 +18488,7 @@ function extractGraphqlQuery(args) {
|
|
|
18539
18488
|
|
|
18540
18489
|
// src/shared/loadCliReads.ts
|
|
18541
18490
|
import { existsSync as existsSync41, readFileSync as readFileSync26, writeFileSync as writeFileSync22 } from "fs";
|
|
18542
|
-
import { dirname as dirname25, resolve as
|
|
18491
|
+
import { dirname as dirname25, resolve as resolve14 } from "path";
|
|
18543
18492
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
18544
18493
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
18545
18494
|
var __dirname4 = dirname25(__filename3);
|
|
@@ -18554,13 +18503,13 @@ var cachedReads;
|
|
|
18554
18503
|
var cachedWrites;
|
|
18555
18504
|
function getCliReadsLines() {
|
|
18556
18505
|
if (!cachedReads) {
|
|
18557
|
-
cachedReads = readLines(
|
|
18506
|
+
cachedReads = readLines(resolve14(packageRoot(), "allowed.cli-reads"));
|
|
18558
18507
|
}
|
|
18559
18508
|
return cachedReads;
|
|
18560
18509
|
}
|
|
18561
18510
|
function getCliWritesLines() {
|
|
18562
18511
|
if (!cachedWrites) {
|
|
18563
|
-
cachedWrites = readLines(
|
|
18512
|
+
cachedWrites = readLines(resolve14(packageRoot(), "allowed.cli-writes"));
|
|
18564
18513
|
}
|
|
18565
18514
|
return cachedWrites;
|
|
18566
18515
|
}
|
|
@@ -18569,7 +18518,7 @@ function loadCliReads() {
|
|
|
18569
18518
|
}
|
|
18570
18519
|
function saveCliReads(commands) {
|
|
18571
18520
|
writeFileSync22(
|
|
18572
|
-
|
|
18521
|
+
resolve14(packageRoot(), "allowed.cli-reads"),
|
|
18573
18522
|
`${commands.join("\n")}
|
|
18574
18523
|
`
|
|
18575
18524
|
);
|
|
@@ -18595,13 +18544,13 @@ function findCliWrite(command) {
|
|
|
18595
18544
|
|
|
18596
18545
|
// src/shared/readSettingsPerms.ts
|
|
18597
18546
|
import { existsSync as existsSync42, readFileSync as readFileSync27 } from "fs";
|
|
18598
|
-
import { homedir as
|
|
18599
|
-
import { join as
|
|
18547
|
+
import { homedir as homedir16 } from "os";
|
|
18548
|
+
import { join as join42 } from "path";
|
|
18600
18549
|
function readSettingsPerms(key) {
|
|
18601
18550
|
const paths = [
|
|
18602
|
-
|
|
18603
|
-
|
|
18604
|
-
|
|
18551
|
+
join42(homedir16(), ".claude", "settings.json"),
|
|
18552
|
+
join42(process.cwd(), ".claude", "settings.json"),
|
|
18553
|
+
join42(process.cwd(), ".claude", "settings.local.json")
|
|
18605
18554
|
];
|
|
18606
18555
|
const entries = [];
|
|
18607
18556
|
for (const p of paths) {
|
|
@@ -18707,20 +18656,20 @@ function isCdToCwd(command) {
|
|
|
18707
18656
|
const parts = command.split(/\s+/);
|
|
18708
18657
|
if (parts[0] !== "cd" || parts.length > 2) return false;
|
|
18709
18658
|
if (parts.length === 1) return false;
|
|
18710
|
-
const resolved =
|
|
18711
|
-
return resolved ===
|
|
18659
|
+
const resolved = resolve15(normalizeMsysPath(parts[1]));
|
|
18660
|
+
return resolved === resolve15(process.cwd());
|
|
18712
18661
|
}
|
|
18713
18662
|
function isCdToReadAllowedDir(command) {
|
|
18714
18663
|
const parts = command.split(/\s+/);
|
|
18715
18664
|
if (parts[0] !== "cd" || parts.length !== 2) return void 0;
|
|
18716
|
-
const target =
|
|
18665
|
+
const target = resolve15(normalizeMsysPath(parts[1]));
|
|
18717
18666
|
for (const entry of readSettingsPerms("allow")) {
|
|
18718
18667
|
const m = entry.match(READ_RE);
|
|
18719
18668
|
if (!m) continue;
|
|
18720
18669
|
const base = globBaseDir(m[1]);
|
|
18721
18670
|
if (!base) continue;
|
|
18722
|
-
const resolved =
|
|
18723
|
-
if (target === resolved || target.startsWith(resolved +
|
|
18671
|
+
const resolved = resolve15(normalizeMsysPath(base));
|
|
18672
|
+
if (target === resolved || target.startsWith(resolved + sep2)) {
|
|
18724
18673
|
return `cd to Read-allowed directory: ${entry}`;
|
|
18725
18674
|
}
|
|
18726
18675
|
}
|
|
@@ -18824,12 +18773,12 @@ function decideCommand(toolName, rawCommand) {
|
|
|
18824
18773
|
|
|
18825
18774
|
// src/commands/cliHook/logDeniedToolCall.ts
|
|
18826
18775
|
import { mkdirSync as mkdirSync12 } from "fs";
|
|
18827
|
-
import { homedir as
|
|
18828
|
-
import { join as
|
|
18776
|
+
import { homedir as homedir17 } from "os";
|
|
18777
|
+
import { join as join43 } from "path";
|
|
18829
18778
|
import Database from "better-sqlite3";
|
|
18830
18779
|
var _db;
|
|
18831
18780
|
function getDbDir() {
|
|
18832
|
-
return
|
|
18781
|
+
return join43(homedir17(), ".assist");
|
|
18833
18782
|
}
|
|
18834
18783
|
function initSchema(db) {
|
|
18835
18784
|
db.exec(`
|
|
@@ -18848,7 +18797,7 @@ function openPromptsDb(dir) {
|
|
|
18848
18797
|
if (_db) return _db;
|
|
18849
18798
|
const dbDir = dir ?? getDbDir();
|
|
18850
18799
|
mkdirSync12(dbDir, { recursive: true });
|
|
18851
|
-
const db = new Database(
|
|
18800
|
+
const db = new Database(join43(dbDir, "assist.db"));
|
|
18852
18801
|
db.pragma("journal_mode = WAL");
|
|
18853
18802
|
initSchema(db);
|
|
18854
18803
|
_db = db;
|
|
@@ -18968,8 +18917,8 @@ ${reasons.join("\n")}`);
|
|
|
18968
18917
|
|
|
18969
18918
|
// src/commands/permitCliReads.ts
|
|
18970
18919
|
import { existsSync as existsSync43, mkdirSync as mkdirSync13, readFileSync as readFileSync28, writeFileSync as writeFileSync23 } from "fs";
|
|
18971
|
-
import { homedir as
|
|
18972
|
-
import { join as
|
|
18920
|
+
import { homedir as homedir18 } from "os";
|
|
18921
|
+
import { join as join44 } from "path";
|
|
18973
18922
|
|
|
18974
18923
|
// src/commands/permitCliReads/assertCliExists.ts
|
|
18975
18924
|
function assertCliExists(cli) {
|
|
@@ -19060,12 +19009,12 @@ function hasSubcommands(helpText) {
|
|
|
19060
19009
|
// src/commands/permitCliReads/runHelp.ts
|
|
19061
19010
|
import { exec as exec2 } from "child_process";
|
|
19062
19011
|
function runHelp(args) {
|
|
19063
|
-
return new Promise((
|
|
19012
|
+
return new Promise((resolve28) => {
|
|
19064
19013
|
exec2(
|
|
19065
19014
|
`${args.join(" ")} --help`,
|
|
19066
19015
|
{ encoding: "utf8", timeout: 3e4 },
|
|
19067
19016
|
(_err, stdout, stderr) => {
|
|
19068
|
-
|
|
19017
|
+
resolve28(stdout || stderr || "");
|
|
19069
19018
|
}
|
|
19070
19019
|
);
|
|
19071
19020
|
});
|
|
@@ -19232,7 +19181,7 @@ function updateSettings(cli, commands) {
|
|
|
19232
19181
|
// src/commands/permitCliReads.ts
|
|
19233
19182
|
function logPath(cli) {
|
|
19234
19183
|
const safeName = cli.replace(/\s+/g, "-");
|
|
19235
|
-
return
|
|
19184
|
+
return join44(homedir18(), ".assist", `cli-discover-${safeName}.log`);
|
|
19236
19185
|
}
|
|
19237
19186
|
function readCache(cli) {
|
|
19238
19187
|
const path106 = logPath(cli);
|
|
@@ -19240,7 +19189,7 @@ function readCache(cli) {
|
|
|
19240
19189
|
return readFileSync28(path106, "utf8");
|
|
19241
19190
|
}
|
|
19242
19191
|
function writeCache(cli, output) {
|
|
19243
|
-
const dir =
|
|
19192
|
+
const dir = join44(homedir18(), ".assist");
|
|
19244
19193
|
mkdirSync13(dir, { recursive: true });
|
|
19245
19194
|
writeFileSync23(logPath(cli), output);
|
|
19246
19195
|
}
|
|
@@ -19404,18 +19353,18 @@ function isHashCommentFile(filePath) {
|
|
|
19404
19353
|
}
|
|
19405
19354
|
|
|
19406
19355
|
// src/commands/codeComment/getRestrictedDir.ts
|
|
19407
|
-
import { homedir as
|
|
19408
|
-
import { join as
|
|
19356
|
+
import { homedir as homedir19 } from "os";
|
|
19357
|
+
import { join as join45 } from "path";
|
|
19409
19358
|
function getRestrictedDir() {
|
|
19410
|
-
return
|
|
19359
|
+
return join45(homedir19(), ".assist", "restricted");
|
|
19411
19360
|
}
|
|
19412
19361
|
function getPinStatePath(pin2) {
|
|
19413
|
-
return
|
|
19362
|
+
return join45(getRestrictedDir(), `code-comment-${pin2}.json`);
|
|
19414
19363
|
}
|
|
19415
19364
|
|
|
19416
19365
|
// src/commands/codeComment/sweepRestrictedDir.ts
|
|
19417
19366
|
import { readdirSync as readdirSync5, statSync as statSync7, unlinkSync as unlinkSync7 } from "fs";
|
|
19418
|
-
import { join as
|
|
19367
|
+
import { join as join46 } from "path";
|
|
19419
19368
|
var STALE_AFTER_MS = 30 * 60 * 1e3;
|
|
19420
19369
|
function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
19421
19370
|
let entries;
|
|
@@ -19426,7 +19375,7 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
19426
19375
|
}
|
|
19427
19376
|
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
19428
19377
|
for (const entry of entries) {
|
|
19429
|
-
const path106 =
|
|
19378
|
+
const path106 = join46(dir, entry);
|
|
19430
19379
|
try {
|
|
19431
19380
|
if (statSync7(path106).mtimeMs < cutoff) unlinkSync7(path106);
|
|
19432
19381
|
} catch {
|
|
@@ -21080,18 +21029,18 @@ import chalk137 from "chalk";
|
|
|
21080
21029
|
|
|
21081
21030
|
// src/commands/criteriaExtension/criteriaExtensionDir.ts
|
|
21082
21031
|
import { existsSync as existsSync46 } from "fs";
|
|
21083
|
-
import { dirname as dirname26, join as
|
|
21032
|
+
import { dirname as dirname26, join as join47 } from "path";
|
|
21084
21033
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
21085
21034
|
var moduleDir = dirname26(fileURLToPath6(import.meta.url));
|
|
21086
21035
|
function criteriaExtensionDir() {
|
|
21087
|
-
const bundled =
|
|
21036
|
+
const bundled = join47(
|
|
21088
21037
|
moduleDir,
|
|
21089
21038
|
"commands",
|
|
21090
21039
|
"criteriaExtension",
|
|
21091
21040
|
"criteria-extension"
|
|
21092
21041
|
);
|
|
21093
21042
|
if (existsSync46(bundled)) return bundled;
|
|
21094
|
-
return
|
|
21043
|
+
return join47(moduleDir, "..", "..", "..", "criteria-extension");
|
|
21095
21044
|
}
|
|
21096
21045
|
|
|
21097
21046
|
// src/commands/criteriaExtension/criteriaExtension.ts
|
|
@@ -21118,17 +21067,17 @@ async function criteriaExtension() {
|
|
|
21118
21067
|
}
|
|
21119
21068
|
|
|
21120
21069
|
// src/commands/criteriaExtension/signCriteriaExtension.ts
|
|
21121
|
-
import { rm as
|
|
21122
|
-
import { homedir as
|
|
21123
|
-
import { join as
|
|
21070
|
+
import { rm as rm2 } from "fs/promises";
|
|
21071
|
+
import { homedir as homedir20, tmpdir as tmpdir3 } from "os";
|
|
21072
|
+
import { join as join53 } from "path";
|
|
21124
21073
|
import chalk139 from "chalk";
|
|
21125
21074
|
|
|
21126
21075
|
// src/commands/criteriaExtension/copySignedXpi.ts
|
|
21127
21076
|
import { copyFile } from "fs/promises";
|
|
21128
|
-
import { join as
|
|
21077
|
+
import { join as join48 } from "path";
|
|
21129
21078
|
var SIGNED_XPI_NAME = "criteria-extension.xpi";
|
|
21130
21079
|
async function copySignedXpi(xpi, dir) {
|
|
21131
|
-
const fixed2 =
|
|
21080
|
+
const fixed2 = join48(dir, SIGNED_XPI_NAME);
|
|
21132
21081
|
if (fixed2 === xpi) return fixed2;
|
|
21133
21082
|
await copyFile(xpi, fixed2);
|
|
21134
21083
|
return fixed2;
|
|
@@ -21137,11 +21086,11 @@ async function copySignedXpi(xpi, dir) {
|
|
|
21137
21086
|
// src/commands/criteriaExtension/findSignedXpi.ts
|
|
21138
21087
|
import { existsSync as existsSync47 } from "fs";
|
|
21139
21088
|
import { readdir } from "fs/promises";
|
|
21140
|
-
import { join as
|
|
21089
|
+
import { join as join49 } from "path";
|
|
21141
21090
|
async function findSignedXpi(dir) {
|
|
21142
21091
|
if (!existsSync47(dir)) return null;
|
|
21143
21092
|
const name = (await readdir(dir)).find((entry) => entry.endsWith(".xpi"));
|
|
21144
|
-
return name ?
|
|
21093
|
+
return name ? join49(dir, name) : null;
|
|
21145
21094
|
}
|
|
21146
21095
|
|
|
21147
21096
|
// src/commands/criteriaExtension/signedAddonInstallPath.ts
|
|
@@ -21164,10 +21113,10 @@ async function signedAddonInstallPath(xpi) {
|
|
|
21164
21113
|
|
|
21165
21114
|
// src/commands/criteriaExtension/signPreflightProblem.ts
|
|
21166
21115
|
import { existsSync as existsSync48 } from "fs";
|
|
21167
|
-
import { join as
|
|
21116
|
+
import { join as join50 } from "path";
|
|
21168
21117
|
var KEY_URL = "https://addons.mozilla.org/en-US/developers/addon/api/key/";
|
|
21169
21118
|
function signPreflightProblem(source) {
|
|
21170
|
-
if (!existsSync48(
|
|
21119
|
+
if (!existsSync48(join50(source, "content.js")))
|
|
21171
21120
|
return {
|
|
21172
21121
|
message: `no content.js in ${source}`,
|
|
21173
21122
|
hint: "run npm run build to bundle the content script"
|
|
@@ -21181,8 +21130,8 @@ function signPreflightProblem(source) {
|
|
|
21181
21130
|
}
|
|
21182
21131
|
|
|
21183
21132
|
// src/commands/criteriaExtension/stageCriteriaExtension.ts
|
|
21184
|
-
import { cp as cp3, mkdir as
|
|
21185
|
-
import { basename as basename13, join as
|
|
21133
|
+
import { cp as cp3, mkdir as mkdir5, readFile as readFile4, rm, writeFile as writeFile4 } from "fs/promises";
|
|
21134
|
+
import { basename as basename13, join as join51 } from "path";
|
|
21186
21135
|
|
|
21187
21136
|
// src/commands/criteriaExtension/stampManifestVersion.ts
|
|
21188
21137
|
function stampManifestVersion(manifest, version2) {
|
|
@@ -21193,13 +21142,13 @@ function stampManifestVersion(manifest, version2) {
|
|
|
21193
21142
|
|
|
21194
21143
|
// src/commands/criteriaExtension/stageCriteriaExtension.ts
|
|
21195
21144
|
async function stageCriteriaExtension(source, staging, version2) {
|
|
21196
|
-
await
|
|
21197
|
-
await
|
|
21145
|
+
await rm(staging, { recursive: true, force: true });
|
|
21146
|
+
await mkdir5(staging, { recursive: true });
|
|
21198
21147
|
await cp3(source, staging, {
|
|
21199
21148
|
recursive: true,
|
|
21200
21149
|
filter: (path106) => basename13(path106) !== "updates.json"
|
|
21201
21150
|
});
|
|
21202
|
-
const manifest =
|
|
21151
|
+
const manifest = join51(staging, "manifest.json");
|
|
21203
21152
|
const stamped = stampManifestVersion(
|
|
21204
21153
|
await readFile4(manifest, "utf8"),
|
|
21205
21154
|
version2
|
|
@@ -21209,7 +21158,7 @@ async function stageCriteriaExtension(source, staging, version2) {
|
|
|
21209
21158
|
|
|
21210
21159
|
// src/commands/criteriaExtension/writeUpdateManifest.ts
|
|
21211
21160
|
import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
21212
|
-
import { join as
|
|
21161
|
+
import { join as join52 } from "path";
|
|
21213
21162
|
|
|
21214
21163
|
// src/commands/criteriaExtension/buildUpdateManifest.ts
|
|
21215
21164
|
var RELEASE_DOWNLOAD_URL = "https://github.com/staff0rd/assist/releases/download";
|
|
@@ -21234,17 +21183,17 @@ function buildUpdateManifest(manifest, version2) {
|
|
|
21234
21183
|
// src/commands/criteriaExtension/writeUpdateManifest.ts
|
|
21235
21184
|
async function writeUpdateManifest(source, dir, version2) {
|
|
21236
21185
|
await writeFile5(
|
|
21237
|
-
|
|
21186
|
+
join52(dir, "updates.json"),
|
|
21238
21187
|
buildUpdateManifest(
|
|
21239
|
-
await readFile5(
|
|
21188
|
+
await readFile5(join52(source, "manifest.json"), "utf8"),
|
|
21240
21189
|
version2
|
|
21241
21190
|
)
|
|
21242
21191
|
);
|
|
21243
21192
|
}
|
|
21244
21193
|
|
|
21245
21194
|
// src/commands/criteriaExtension/signCriteriaExtension.ts
|
|
21246
|
-
var ARTIFACTS_DIR =
|
|
21247
|
-
var STAGING_DIR =
|
|
21195
|
+
var ARTIFACTS_DIR = join53(homedir20(), ".assist", "criteria-extension");
|
|
21196
|
+
var STAGING_DIR = join53(tmpdir3(), "assist-criteria-extension");
|
|
21248
21197
|
async function signCriteriaExtension() {
|
|
21249
21198
|
const source = criteriaExtensionDir();
|
|
21250
21199
|
const problem = signPreflightProblem(source);
|
|
@@ -21256,7 +21205,7 @@ async function signCriteriaExtension() {
|
|
|
21256
21205
|
}
|
|
21257
21206
|
const { version: version2 } = package_default;
|
|
21258
21207
|
await stageCriteriaExtension(source, STAGING_DIR, version2);
|
|
21259
|
-
await
|
|
21208
|
+
await rm2(ARTIFACTS_DIR, { recursive: true, force: true });
|
|
21260
21209
|
console.log(chalk139.bold(`signing version ${version2} for self-distribution`));
|
|
21261
21210
|
const { done: done2 } = spawnInherit("npx", [
|
|
21262
21211
|
"--yes",
|
|
@@ -21428,12 +21377,12 @@ import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync26 } from "fs"
|
|
|
21428
21377
|
import chalk142 from "chalk";
|
|
21429
21378
|
|
|
21430
21379
|
// src/commands/dbMigration/getMigrationPinPath.ts
|
|
21431
|
-
import { join as
|
|
21380
|
+
import { join as join54 } from "path";
|
|
21432
21381
|
function getMigrationPinPath(pin2) {
|
|
21433
|
-
return
|
|
21382
|
+
return join54(getRestrictedDir(), `db-migration-pin-${pin2}.json`);
|
|
21434
21383
|
}
|
|
21435
21384
|
function getMigrationApprovalPath(migrationId) {
|
|
21436
|
-
return
|
|
21385
|
+
return join54(getRestrictedDir(), `db-migration-approval-${migrationId}.json`);
|
|
21437
21386
|
}
|
|
21438
21387
|
|
|
21439
21388
|
// src/commands/dbMigration/readMigrationPinState.ts
|
|
@@ -21570,11 +21519,11 @@ import { execFileSync as execFileSync5 } from "child_process";
|
|
|
21570
21519
|
import { basename as basename15 } from "path";
|
|
21571
21520
|
|
|
21572
21521
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
21573
|
-
import { homedir as
|
|
21574
|
-
import { join as
|
|
21575
|
-
var BLOG_REPO_ROOT =
|
|
21522
|
+
import { homedir as homedir21 } from "os";
|
|
21523
|
+
import { join as join55 } from "path";
|
|
21524
|
+
var BLOG_REPO_ROOT = join55(homedir21(), "git/blog");
|
|
21576
21525
|
function loadBlogSkipDays(repoName) {
|
|
21577
|
-
const config = loadRawYaml(
|
|
21526
|
+
const config = loadRawYaml(join55(BLOG_REPO_ROOT, "assist.yml"));
|
|
21578
21527
|
const devlog = config.devlog;
|
|
21579
21528
|
const skip2 = devlog?.skip;
|
|
21580
21529
|
return new Set(skip2?.[repoName]);
|
|
@@ -21586,13 +21535,13 @@ import chalk145 from "chalk";
|
|
|
21586
21535
|
|
|
21587
21536
|
// src/shared/getRepoName.ts
|
|
21588
21537
|
import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
|
|
21589
|
-
import { basename as basename14, join as
|
|
21538
|
+
import { basename as basename14, join as join56 } from "path";
|
|
21590
21539
|
function getRepoName() {
|
|
21591
21540
|
const config = loadConfig();
|
|
21592
21541
|
if (config.devlog?.name) {
|
|
21593
21542
|
return config.devlog.name;
|
|
21594
21543
|
}
|
|
21595
|
-
const packageJsonPath =
|
|
21544
|
+
const packageJsonPath = join56(process.cwd(), "package.json");
|
|
21596
21545
|
if (existsSync51(packageJsonPath)) {
|
|
21597
21546
|
try {
|
|
21598
21547
|
const content = readFileSync33(packageJsonPath, "utf8");
|
|
@@ -21608,8 +21557,8 @@ function getRepoName() {
|
|
|
21608
21557
|
|
|
21609
21558
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
21610
21559
|
import { readdirSync as readdirSync6, readFileSync as readFileSync34 } from "fs";
|
|
21611
|
-
import { join as
|
|
21612
|
-
var DEVLOG_DIR =
|
|
21560
|
+
import { join as join57 } from "path";
|
|
21561
|
+
var DEVLOG_DIR = join57(BLOG_REPO_ROOT, "src/content/devlog");
|
|
21613
21562
|
function extractFrontmatter(content) {
|
|
21614
21563
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
21615
21564
|
return fm?.[1] ?? null;
|
|
@@ -21637,7 +21586,7 @@ function readDevlogFiles(callback) {
|
|
|
21637
21586
|
try {
|
|
21638
21587
|
const files = readdirSync6(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
21639
21588
|
for (const file of files) {
|
|
21640
|
-
const content = readFileSync34(
|
|
21589
|
+
const content = readFileSync34(join57(DEVLOG_DIR, file), "utf8");
|
|
21641
21590
|
const parsed = parseFrontmatter(content, file);
|
|
21642
21591
|
if (parsed) callback(parsed);
|
|
21643
21592
|
}
|
|
@@ -22025,11 +21974,11 @@ function repos(options2) {
|
|
|
22025
21974
|
|
|
22026
21975
|
// src/commands/devlog/skip.ts
|
|
22027
21976
|
import { writeFileSync as writeFileSync29 } from "fs";
|
|
22028
|
-
import { join as
|
|
21977
|
+
import { join as join58 } from "path";
|
|
22029
21978
|
import chalk150 from "chalk";
|
|
22030
21979
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
22031
21980
|
function getBlogConfigPath() {
|
|
22032
|
-
return
|
|
21981
|
+
return join58(BLOG_REPO_ROOT, "assist.yml");
|
|
22033
21982
|
}
|
|
22034
21983
|
function skip(date) {
|
|
22035
21984
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
@@ -22091,7 +22040,7 @@ function registerDevlog(program2) {
|
|
|
22091
22040
|
|
|
22092
22041
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
22093
22042
|
import { closeSync as closeSync4, openSync as openSync5, readdirSync as readdirSync7 } from "fs";
|
|
22094
|
-
import { join as
|
|
22043
|
+
import { join as join59 } from "path";
|
|
22095
22044
|
import chalk152 from "chalk";
|
|
22096
22045
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "packages"]);
|
|
22097
22046
|
function isLockedDll(debugDir) {
|
|
@@ -22103,7 +22052,7 @@ function isLockedDll(debugDir) {
|
|
|
22103
22052
|
}
|
|
22104
22053
|
for (const file of files) {
|
|
22105
22054
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
22106
|
-
const dllPath =
|
|
22055
|
+
const dllPath = join59(debugDir, file);
|
|
22107
22056
|
try {
|
|
22108
22057
|
const fd = openSync5(dllPath, "r+");
|
|
22109
22058
|
closeSync4(fd);
|
|
@@ -22121,13 +22070,13 @@ function findFirstLockedDll(dir) {
|
|
|
22121
22070
|
return null;
|
|
22122
22071
|
}
|
|
22123
22072
|
if (entries.includes("bin")) {
|
|
22124
|
-
const locked = isLockedDll(
|
|
22073
|
+
const locked = isLockedDll(join59(dir, "bin", "Debug"));
|
|
22125
22074
|
if (locked) return locked;
|
|
22126
22075
|
}
|
|
22127
22076
|
for (const entry of entries) {
|
|
22128
22077
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
22129
22078
|
continue;
|
|
22130
|
-
const found = findFirstLockedDll(
|
|
22079
|
+
const found = findFirstLockedDll(join59(dir, entry));
|
|
22131
22080
|
if (found) return found;
|
|
22132
22081
|
}
|
|
22133
22082
|
return null;
|
|
@@ -22212,10 +22161,10 @@ function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
|
22212
22161
|
continue;
|
|
22213
22162
|
const full = path35.join(dir, entry);
|
|
22214
22163
|
try {
|
|
22215
|
-
const
|
|
22216
|
-
if (
|
|
22164
|
+
const stat5 = statSync8(full);
|
|
22165
|
+
if (stat5.isFile() && entry.endsWith(".sln")) {
|
|
22217
22166
|
results.push(full);
|
|
22218
|
-
} else if (
|
|
22167
|
+
} else if (stat5.isDirectory()) {
|
|
22219
22168
|
results.push(...findSlnFiles(full, maxDepth, depth + 1));
|
|
22220
22169
|
}
|
|
22221
22170
|
} catch {
|
|
@@ -22474,11 +22423,11 @@ import chalk158 from "chalk";
|
|
|
22474
22423
|
|
|
22475
22424
|
// src/commands/dotnet/findSolution.ts
|
|
22476
22425
|
import { readdirSync as readdirSync9 } from "fs";
|
|
22477
|
-
import { dirname as dirname27, join as
|
|
22426
|
+
import { dirname as dirname27, join as join60 } from "path";
|
|
22478
22427
|
import chalk157 from "chalk";
|
|
22479
22428
|
function findSlnInDir(dir) {
|
|
22480
22429
|
try {
|
|
22481
|
-
return readdirSync9(dir).filter((f) => f.endsWith(".sln")).map((f) =>
|
|
22430
|
+
return readdirSync9(dir).filter((f) => f.endsWith(".sln")).map((f) => join60(dir, f));
|
|
22482
22431
|
} catch {
|
|
22483
22432
|
return [];
|
|
22484
22433
|
}
|
|
@@ -22550,7 +22499,7 @@ function parseInspectReport(json) {
|
|
|
22550
22499
|
// src/commands/dotnet/runInspectCode.ts
|
|
22551
22500
|
import { execSync as execSync35 } from "child_process";
|
|
22552
22501
|
import { existsSync as existsSync54, readFileSync as readFileSync37, unlinkSync as unlinkSync10 } from "fs";
|
|
22553
|
-
import { tmpdir as
|
|
22502
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
22554
22503
|
import path38 from "path";
|
|
22555
22504
|
import chalk159 from "chalk";
|
|
22556
22505
|
function assertJbInstalled() {
|
|
@@ -22565,7 +22514,7 @@ function assertJbInstalled() {
|
|
|
22565
22514
|
}
|
|
22566
22515
|
}
|
|
22567
22516
|
function runInspectCode(slnPath, include, swea) {
|
|
22568
|
-
const reportPath = path38.join(
|
|
22517
|
+
const reportPath = path38.join(tmpdir4(), `inspect-${Date.now()}.xml`);
|
|
22569
22518
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
22570
22519
|
const sweaFlag = swea ? " --swea" : "";
|
|
22571
22520
|
try {
|
|
@@ -23472,8 +23421,8 @@ function aggregateCommitters(authorLists) {
|
|
|
23472
23421
|
// src/shared/runGhGraphql.ts
|
|
23473
23422
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
23474
23423
|
import { unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
|
|
23475
|
-
import { tmpdir as
|
|
23476
|
-
import { join as
|
|
23424
|
+
import { tmpdir as tmpdir5 } from "os";
|
|
23425
|
+
import { join as join61 } from "path";
|
|
23477
23426
|
function buildArgs2(queryFile, vars) {
|
|
23478
23427
|
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
23479
23428
|
for (const [key, value] of Object.entries(vars)) {
|
|
@@ -23483,7 +23432,7 @@ function buildArgs2(queryFile, vars) {
|
|
|
23483
23432
|
return args;
|
|
23484
23433
|
}
|
|
23485
23434
|
function runGhGraphql(mutation, vars) {
|
|
23486
|
-
const queryFile =
|
|
23435
|
+
const queryFile = join61(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
23487
23436
|
writeFileSync30(queryFile, mutation);
|
|
23488
23437
|
try {
|
|
23489
23438
|
const result = spawnSync6("gh", buildArgs2(queryFile, vars), {
|
|
@@ -24282,6 +24231,9 @@ function registerCommentIssue(issueCommand) {
|
|
|
24282
24231
|
);
|
|
24283
24232
|
}
|
|
24284
24233
|
|
|
24234
|
+
// src/commands/prs/minGhAttachVersion.ts
|
|
24235
|
+
var minGhAttachVersion = "2.99.0";
|
|
24236
|
+
|
|
24285
24237
|
// src/commands/github/issue/collectLabels.ts
|
|
24286
24238
|
function collectLabels(value, previous) {
|
|
24287
24239
|
const added = value.split(",").map((label2) => label2.trim()).filter((label2) => label2.length > 0);
|
|
@@ -24289,13 +24241,17 @@ function collectLabels(value, previous) {
|
|
|
24289
24241
|
}
|
|
24290
24242
|
|
|
24291
24243
|
// src/commands/prs/appendScreenshots.ts
|
|
24292
|
-
function
|
|
24293
|
-
|
|
24244
|
+
function reference({ path: path106, alt }) {
|
|
24245
|
+
const target = /\s/.test(path106) ? `<${path106}>` : path106;
|
|
24246
|
+
return ``;
|
|
24247
|
+
}
|
|
24248
|
+
function appendScreenshots(body, attachments) {
|
|
24249
|
+
if (attachments.length === 0) return body;
|
|
24294
24250
|
return `${body}
|
|
24295
24251
|
|
|
24296
24252
|
## Screenshots
|
|
24297
24253
|
|
|
24298
|
-
${
|
|
24254
|
+
${attachments.map(reference).join("\n\n")}`;
|
|
24299
24255
|
}
|
|
24300
24256
|
|
|
24301
24257
|
// src/commands/github/issue/addIssueToProject.ts
|
|
@@ -24571,11 +24527,11 @@ function resolveIssueRepoTarget(repo) {
|
|
|
24571
24527
|
|
|
24572
24528
|
// src/commands/github/issue/resolveCreateIssueParent.ts
|
|
24573
24529
|
function resolveCreateIssueParent(target, parent) {
|
|
24574
|
-
const
|
|
24530
|
+
const reference2 = resolveFixStructureTarget(
|
|
24575
24531
|
parent,
|
|
24576
24532
|
`${target.owner}/${target.repo}`
|
|
24577
24533
|
);
|
|
24578
|
-
return { ...
|
|
24534
|
+
return { ...reference2, id: fetchIssueNodeId(reference2) };
|
|
24579
24535
|
}
|
|
24580
24536
|
|
|
24581
24537
|
// src/commands/github/issue/resolveCreateIssueProject.ts
|
|
@@ -24647,22 +24603,75 @@ async function reviewProposedIssue(title, body, metadata2 = []) {
|
|
|
24647
24603
|
});
|
|
24648
24604
|
}
|
|
24649
24605
|
|
|
24650
|
-
// src/commands/
|
|
24606
|
+
// src/commands/prs/attachArgs.ts
|
|
24607
|
+
function attachArgs(attachments) {
|
|
24608
|
+
return attachments.flatMap(({ path: path106, alt }) => [
|
|
24609
|
+
"--attach",
|
|
24610
|
+
alt ? `${path106}#${alt}` : path106
|
|
24611
|
+
]);
|
|
24612
|
+
}
|
|
24613
|
+
|
|
24614
|
+
// src/commands/prs/runGhWithAttachments.ts
|
|
24651
24615
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
24652
|
-
|
|
24653
|
-
|
|
24654
|
-
|
|
24655
|
-
|
|
24616
|
+
import { basename as basename16 } from "path";
|
|
24617
|
+
|
|
24618
|
+
// src/shared/removeStagedAttachments.ts
|
|
24619
|
+
import { rmSync as rmSync3 } from "fs";
|
|
24620
|
+
import { dirname as dirname28 } from "path";
|
|
24621
|
+
function removeStagedAttachments(attachments) {
|
|
24622
|
+
for (const { path: path106 } of attachments) {
|
|
24623
|
+
const dir = dirname28(path106);
|
|
24624
|
+
if (!isStagedAttachmentPath(dir)) continue;
|
|
24625
|
+
rmSync3(dir, { recursive: true, force: true });
|
|
24626
|
+
}
|
|
24627
|
+
}
|
|
24628
|
+
|
|
24629
|
+
// src/commands/prs/runGhWithAttachments.ts
|
|
24630
|
+
var PLACED_URL = /https:\/\/\S+\/(pull|issues)\/\d+/;
|
|
24631
|
+
function reportPartialFailure(attachments, stderr) {
|
|
24632
|
+
const failed3 = attachments.filter(
|
|
24633
|
+
({ path: path106 }) => stderr.includes(path106) || stderr.includes(basename16(path106))
|
|
24634
|
+
);
|
|
24635
|
+
const named = failed3.length > 0 ? failed3 : attachments;
|
|
24636
|
+
console.error(
|
|
24637
|
+
`Some attachments failed to upload: ${named.map((a) => a.path).join(", ")}. The body still references their local paths, so re-attach them with gh's --attach flag; the staged files were kept.`
|
|
24638
|
+
);
|
|
24639
|
+
}
|
|
24640
|
+
function runGhWithAttachments(args, attachments) {
|
|
24641
|
+
const attaching = attachments.length > 0;
|
|
24656
24642
|
try {
|
|
24657
|
-
|
|
24643
|
+
const stdout = execFileSync9("gh", args, {
|
|
24658
24644
|
encoding: "utf8",
|
|
24659
|
-
stdio: ["
|
|
24645
|
+
stdio: ["inherit", "pipe", attaching ? "pipe" : "inherit"]
|
|
24660
24646
|
});
|
|
24661
|
-
|
|
24647
|
+
removeStagedAttachments(attachments);
|
|
24648
|
+
return stdout;
|
|
24649
|
+
} catch (error) {
|
|
24650
|
+
const { stdout = "", stderr = "" } = error;
|
|
24651
|
+
if (stderr) process.stderr.write(stderr);
|
|
24652
|
+
if (/unknown flag:? --attach/.test(stderr)) {
|
|
24653
|
+
console.error(
|
|
24654
|
+
`Your gh does not support --attach. Upgrade the GitHub CLI to ${minGhAttachVersion} or later.`
|
|
24655
|
+
);
|
|
24656
|
+
process.exit(1);
|
|
24657
|
+
}
|
|
24658
|
+
if (attaching && PLACED_URL.test(stdout)) {
|
|
24659
|
+
reportPartialFailure(attachments, stderr);
|
|
24660
|
+
return stdout;
|
|
24661
|
+
}
|
|
24662
24662
|
process.exit(1);
|
|
24663
24663
|
}
|
|
24664
24664
|
}
|
|
24665
24665
|
|
|
24666
|
+
// src/commands/github/issue/runGhIssueCreate.ts
|
|
24667
|
+
function runGhIssueCreate(title, body, repo, labels, attachments = []) {
|
|
24668
|
+
const args = ["issue", "create", "--title", title, "--body", body];
|
|
24669
|
+
if (repo) args.push("--repo", repo);
|
|
24670
|
+
for (const label2 of labels ?? []) args.push("--label", label2);
|
|
24671
|
+
args.push(...attachArgs(attachments));
|
|
24672
|
+
return runGhWithAttachments(args, attachments);
|
|
24673
|
+
}
|
|
24674
|
+
|
|
24666
24675
|
// src/commands/github/issue/createIssue.ts
|
|
24667
24676
|
var USAGE2 = "Usage: assist github issue create --title <title> --body <body> [-R <owner>/<repo>] [--type <name>] [--parent <issue>] [--project <number>] [--status <name>] [--label <name>]";
|
|
24668
24677
|
function preflight(options2) {
|
|
@@ -24690,11 +24699,13 @@ async function createIssue(options2) {
|
|
|
24690
24699
|
body,
|
|
24691
24700
|
issuePreviewMetadata(resolved)
|
|
24692
24701
|
);
|
|
24702
|
+
const attachments = decision?.screenshots ?? [];
|
|
24693
24703
|
const output = runGhIssueCreate(
|
|
24694
24704
|
title,
|
|
24695
|
-
appendScreenshots(body,
|
|
24705
|
+
appendScreenshots(body, attachments),
|
|
24696
24706
|
options2.repo,
|
|
24697
|
-
resolved?.labels
|
|
24707
|
+
resolved?.labels,
|
|
24708
|
+
attachments
|
|
24698
24709
|
);
|
|
24699
24710
|
console.log(output.trim());
|
|
24700
24711
|
if (resolved) applyCreatedIssueMetadata(output, resolved);
|
|
@@ -24724,7 +24735,13 @@ function registerCreateIssue(issueCommand) {
|
|
|
24724
24735
|
[]
|
|
24725
24736
|
).addHelpText(
|
|
24726
24737
|
"after",
|
|
24727
|
-
|
|
24738
|
+
`
|
|
24739
|
+
There is no What/Why/How template: an issue reports a problem, and the target repo's own issue template is unknowable from here. Write the body as the repo's maintainers would expect.
|
|
24740
|
+
In an assist web session the title and body are previewed for approve/reject first (with inline comments); nothing is created until it is approved.
|
|
24741
|
+
The reviewer may also drop or paste screenshots or video into the pane; on approval gh attaches them (gh ${minGhAttachVersion}+) under a ## Screenshots section of the issue body automatically, and on rejection they stay attached and reappear in the preview you re-propose \u2014 so never author that section yourself.
|
|
24742
|
+
--type, --parent, --project, --status and --label are all resolved before the preview, so an unknown name, an unreadable parent, a missing project scope or --status without --project creates nothing.
|
|
24743
|
+
A bare --parent number is read against --repo, or the current repo; a parent in another repository is allowed.
|
|
24744
|
+
The project scope is needed for --project: gh auth refresh -h github.com -s project`
|
|
24728
24745
|
).action(createIssue);
|
|
24729
24746
|
}
|
|
24730
24747
|
|
|
@@ -24763,14 +24780,14 @@ function fetchIssue2(number, repo) {
|
|
|
24763
24780
|
import { existsSync as existsSync56, readFileSync as readFileSync38 } from "fs";
|
|
24764
24781
|
|
|
24765
24782
|
// src/commands/github/issue/issueWorkingFile.ts
|
|
24766
|
-
import { join as
|
|
24783
|
+
import { join as join62 } from "path";
|
|
24767
24784
|
function issueWorkingFile(slug2, number) {
|
|
24768
24785
|
const [owner = "unknown", repo = "unknown"] = slug2.split("/");
|
|
24769
|
-
const dir =
|
|
24786
|
+
const dir = join62(getStoreDir(), "github-issues", owner, repo);
|
|
24770
24787
|
return {
|
|
24771
24788
|
dir,
|
|
24772
|
-
bodyPath:
|
|
24773
|
-
metaPath:
|
|
24789
|
+
bodyPath: join62(dir, `${number}.md`),
|
|
24790
|
+
metaPath: join62(dir, `${number}.json`)
|
|
24774
24791
|
};
|
|
24775
24792
|
}
|
|
24776
24793
|
|
|
@@ -25399,28 +25416,28 @@ function recentDaemonLogLines(includeRelayed = true) {
|
|
|
25399
25416
|
|
|
25400
25417
|
// src/commands/sessions/daemon/worktree/canonicalTreePath.ts
|
|
25401
25418
|
import { realpathSync as realpathSync2 } from "fs";
|
|
25402
|
-
import { resolve as
|
|
25419
|
+
import { resolve as resolve16 } from "path";
|
|
25403
25420
|
function canonicalTreePath(path106) {
|
|
25404
25421
|
try {
|
|
25405
25422
|
return realpathSync2(path106);
|
|
25406
25423
|
} catch {
|
|
25407
|
-
return
|
|
25424
|
+
return resolve16(path106);
|
|
25408
25425
|
}
|
|
25409
25426
|
}
|
|
25410
25427
|
|
|
25411
25428
|
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
25412
25429
|
import { existsSync as existsSync57 } from "fs";
|
|
25413
|
-
import { basename as
|
|
25430
|
+
import { basename as basename18, dirname as dirname29 } from "path";
|
|
25414
25431
|
|
|
25415
25432
|
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
25416
|
-
import { basename as
|
|
25433
|
+
import { basename as basename17, join as join63 } from "path";
|
|
25417
25434
|
function planAllocation(clone, boundTreeRoots2) {
|
|
25418
25435
|
return boundTreeRoots2.has(clone) ? "spill" : "primary";
|
|
25419
25436
|
}
|
|
25420
25437
|
function nextWorktreePath(clone, base, isTaken) {
|
|
25421
|
-
const name =
|
|
25438
|
+
const name = basename17(clone);
|
|
25422
25439
|
for (let n = 2; n < 1e3; n++) {
|
|
25423
|
-
const candidate =
|
|
25440
|
+
const candidate = join63(base, `${name}-${n}`);
|
|
25424
25441
|
if (!isTaken(candidate)) return candidate;
|
|
25425
25442
|
}
|
|
25426
25443
|
throw new Error(`no free worktree suffix for ${clone}`);
|
|
@@ -25453,10 +25470,10 @@ function cloneHead(clone) {
|
|
|
25453
25470
|
|
|
25454
25471
|
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
25455
25472
|
function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
25456
|
-
const base = strategy.root ? expandTilde2(strategy.root) :
|
|
25473
|
+
const base = strategy.root ? expandTilde2(strategy.root) : dirname29(clone);
|
|
25457
25474
|
const registered = new Set(listWorktreePaths(clone));
|
|
25458
25475
|
const branches = new Set(listLocalBranches(clone));
|
|
25459
|
-
const isTaken = (candidate) => registered.has(candidate) || existsSync57(candidate) || boundTreeRoots2.has(candidate) || branches.has(
|
|
25476
|
+
const isTaken = (candidate) => registered.has(candidate) || existsSync57(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename18(candidate));
|
|
25460
25477
|
const path106 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
|
|
25461
25478
|
const start2 = worktreeStartPoint(clone, strategy.trunk);
|
|
25462
25479
|
gitSync(clone, [
|
|
@@ -25464,13 +25481,13 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
|
25464
25481
|
"add",
|
|
25465
25482
|
start2.track ? "--track" : "--no-track",
|
|
25466
25483
|
"-b",
|
|
25467
|
-
|
|
25484
|
+
basename18(path106),
|
|
25468
25485
|
path106,
|
|
25469
25486
|
start2.ref
|
|
25470
25487
|
]);
|
|
25471
25488
|
recordWorktree(path106, clone, getCurrentOrigin(clone));
|
|
25472
25489
|
daemonLog(
|
|
25473
|
-
start2.track ? `worktree allocated ${path106} (branch ${
|
|
25490
|
+
start2.track ? `worktree allocated ${path106} (branch ${basename18(path106)} tracking ${start2.ref}) for clone ${clone}` : `worktree allocated ${path106} (branch ${basename18(path106)} off ${start2.ref}, no mainline tracking) for clone ${clone}`
|
|
25474
25491
|
);
|
|
25475
25492
|
return path106;
|
|
25476
25493
|
}
|
|
@@ -25774,19 +25791,19 @@ function persistedTreeRoots() {
|
|
|
25774
25791
|
|
|
25775
25792
|
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
25776
25793
|
import { copyFileSync, existsSync as existsSync60, mkdirSync as mkdirSync17 } from "fs";
|
|
25777
|
-
import { dirname as
|
|
25794
|
+
import { dirname as dirname30, join as join65 } from "path";
|
|
25778
25795
|
|
|
25779
25796
|
// src/commands/sessions/daemon/worktree/runInstall.ts
|
|
25780
|
-
import { resolve as
|
|
25797
|
+
import { resolve as resolve17 } from "path";
|
|
25781
25798
|
|
|
25782
25799
|
// src/commands/sessions/daemon/worktree/detectInstallCommand.ts
|
|
25783
25800
|
import { existsSync as existsSync59 } from "fs";
|
|
25784
|
-
import { join as
|
|
25801
|
+
import { join as join64 } from "path";
|
|
25785
25802
|
function detectInstallCommand(dir) {
|
|
25786
|
-
if (!existsSync59(
|
|
25787
|
-
if (existsSync59(
|
|
25788
|
-
if (existsSync59(
|
|
25789
|
-
if (existsSync59(
|
|
25803
|
+
if (!existsSync59(join64(dir, "package.json"))) return null;
|
|
25804
|
+
if (existsSync59(join64(dir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
25805
|
+
if (existsSync59(join64(dir, "yarn.lock"))) return "yarn install";
|
|
25806
|
+
if (existsSync59(join64(dir, "bun.lockb"))) return "bun install";
|
|
25790
25807
|
return "npm install";
|
|
25791
25808
|
}
|
|
25792
25809
|
|
|
@@ -25824,7 +25841,7 @@ function quoteForPosixShell(value) {
|
|
|
25824
25841
|
}
|
|
25825
25842
|
|
|
25826
25843
|
// src/commands/sessions/daemon/worktree/stopInstall.ts
|
|
25827
|
-
import { execFile as
|
|
25844
|
+
import { execFile as execFile11 } from "child_process";
|
|
25828
25845
|
var running2 = /* @__PURE__ */ new Map();
|
|
25829
25846
|
function trackInstall(worktreePath, child) {
|
|
25830
25847
|
running2.set(worktreePath, child);
|
|
@@ -25845,7 +25862,7 @@ function stopInstall(worktreePath) {
|
|
|
25845
25862
|
}
|
|
25846
25863
|
function killTree(pid) {
|
|
25847
25864
|
if (process.platform === "win32") {
|
|
25848
|
-
|
|
25865
|
+
execFile11(
|
|
25849
25866
|
"taskkill",
|
|
25850
25867
|
["/T", "/F", "/PID", String(pid)],
|
|
25851
25868
|
{ windowsHide: true },
|
|
@@ -25915,7 +25932,7 @@ function installPaths(worktreePath, paths, onSeeded) {
|
|
|
25915
25932
|
onSeeded();
|
|
25916
25933
|
return;
|
|
25917
25934
|
}
|
|
25918
|
-
const dir =
|
|
25935
|
+
const dir = resolve17(worktreePath, rel);
|
|
25919
25936
|
const command = detectInstallCommand(dir);
|
|
25920
25937
|
if (!command) {
|
|
25921
25938
|
daemonLog(
|
|
@@ -25948,11 +25965,11 @@ function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
|
25948
25965
|
}
|
|
25949
25966
|
function copyConfigFiles(worktreePath, clone, copy) {
|
|
25950
25967
|
for (const rel of copy) {
|
|
25951
|
-
const src =
|
|
25968
|
+
const src = join65(clone, rel);
|
|
25952
25969
|
if (!existsSync60(src)) continue;
|
|
25953
|
-
const dest =
|
|
25970
|
+
const dest = join65(worktreePath, rel);
|
|
25954
25971
|
try {
|
|
25955
|
-
mkdirSync17(
|
|
25972
|
+
mkdirSync17(dirname30(dest), { recursive: true });
|
|
25956
25973
|
copyFileSync(src, dest);
|
|
25957
25974
|
daemonLog(`worktree ${worktreePath} seeded ${rel}`);
|
|
25958
25975
|
} catch (error) {
|
|
@@ -25973,7 +25990,7 @@ function placedByDaemon() {
|
|
|
25973
25990
|
function seed(worktreePath, clone) {
|
|
25974
25991
|
console.log(`Preparing ${worktreePath}\u2026`);
|
|
25975
25992
|
return new Promise(
|
|
25976
|
-
(
|
|
25993
|
+
(resolve28) => seedWorktree(worktreePath, clone, resolve28)
|
|
25977
25994
|
);
|
|
25978
25995
|
}
|
|
25979
25996
|
async function moveToPrCheckoutTree() {
|
|
@@ -26255,12 +26272,12 @@ function registerLitellm(program2) {
|
|
|
26255
26272
|
|
|
26256
26273
|
// src/commands/mermaidExport.ts
|
|
26257
26274
|
import { mkdirSync as mkdirSync18, readdirSync as readdirSync10 } from "fs";
|
|
26258
|
-
import { resolve as
|
|
26275
|
+
import { resolve as resolve19 } from "path";
|
|
26259
26276
|
import chalk174 from "chalk";
|
|
26260
26277
|
|
|
26261
26278
|
// src/commands/mermaid/exportFile.ts
|
|
26262
26279
|
import { readFileSync as readFileSync39, writeFileSync as writeFileSync32 } from "fs";
|
|
26263
|
-
import { basename as
|
|
26280
|
+
import { basename as basename19, extname as extname3, resolve as resolve18 } from "path";
|
|
26264
26281
|
import chalk173 from "chalk";
|
|
26265
26282
|
|
|
26266
26283
|
// src/commands/mermaid/renderBlock.ts
|
|
@@ -26287,7 +26304,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
26287
26304
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
26288
26305
|
const content = readFileSync39(file, "utf8");
|
|
26289
26306
|
const blocks = extractMermaidBlocks(content);
|
|
26290
|
-
const stem =
|
|
26307
|
+
const stem = basename19(file, extname3(file));
|
|
26291
26308
|
if (onlyIndex !== void 0) {
|
|
26292
26309
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
26293
26310
|
console.error(
|
|
@@ -26308,7 +26325,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
26308
26325
|
for (const [i, source] of blocks.entries()) {
|
|
26309
26326
|
const idx = i + 1;
|
|
26310
26327
|
if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
|
|
26311
|
-
const outPath =
|
|
26328
|
+
const outPath = resolve18(outDir, `${stem}-${idx}.svg`);
|
|
26312
26329
|
const svg = await renderBlock(krokiUrl, source);
|
|
26313
26330
|
writeFileSync32(outPath, svg, "utf8");
|
|
26314
26331
|
console.log(chalk173.green(` \u2192 ${outPath}`));
|
|
@@ -26322,7 +26339,7 @@ function extractMermaidBlocks(markdown) {
|
|
|
26322
26339
|
// src/commands/mermaidExport.ts
|
|
26323
26340
|
async function mermaidExport(file, options2 = {}) {
|
|
26324
26341
|
const { mermaid } = loadConfig();
|
|
26325
|
-
const outDir =
|
|
26342
|
+
const outDir = resolve19(process.cwd(), options2.out ?? ".");
|
|
26326
26343
|
mkdirSync18(outDir, { recursive: true });
|
|
26327
26344
|
if (options2.index !== void 0) {
|
|
26328
26345
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
@@ -26419,7 +26436,7 @@ import { stringify as stringify2 } from "yaml";
|
|
|
26419
26436
|
|
|
26420
26437
|
// src/commands/miro/writeExtract.ts
|
|
26421
26438
|
import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync33 } from "fs";
|
|
26422
|
-
import { dirname as
|
|
26439
|
+
import { dirname as dirname31 } from "path";
|
|
26423
26440
|
import { stringify } from "yaml";
|
|
26424
26441
|
function headerLines(header) {
|
|
26425
26442
|
const { rect } = header;
|
|
@@ -26432,7 +26449,7 @@ function headerLines(header) {
|
|
|
26432
26449
|
];
|
|
26433
26450
|
}
|
|
26434
26451
|
function writeExtract(file, header, texts) {
|
|
26435
|
-
mkdirSync19(
|
|
26452
|
+
mkdirSync19(dirname31(file), { recursive: true });
|
|
26436
26453
|
writeFileSync33(file, `${headerLines(header).join("\n")}
|
|
26437
26454
|
${stringify(texts)}`);
|
|
26438
26455
|
}
|
|
@@ -26450,18 +26467,18 @@ function emitExtract(out, header, texts) {
|
|
|
26450
26467
|
}
|
|
26451
26468
|
|
|
26452
26469
|
// src/commands/miro/resolveExtractPath.ts
|
|
26453
|
-
import { isAbsolute as
|
|
26470
|
+
import { isAbsolute as isAbsolute4, relative as relative6, resolve as resolve20 } from "path";
|
|
26454
26471
|
function extractRoot(cwd) {
|
|
26455
26472
|
return findConfigUp(cwd)?.rootDir ?? cwd;
|
|
26456
26473
|
}
|
|
26457
26474
|
function resolveExtractPath(value, cwd) {
|
|
26458
26475
|
if (value === void 0) return void 0;
|
|
26459
|
-
return
|
|
26476
|
+
return isAbsolute4(value) ? value : resolve20(extractRoot(cwd), value);
|
|
26460
26477
|
}
|
|
26461
26478
|
function storedExtractPath(value, cwd) {
|
|
26462
26479
|
if (value === void 0) return void 0;
|
|
26463
|
-
const absolute2 =
|
|
26464
|
-
const within =
|
|
26480
|
+
const absolute2 = resolve20(cwd, value);
|
|
26481
|
+
const within = relative6(extractRoot(cwd), absolute2);
|
|
26465
26482
|
return within.startsWith("..") ? absolute2 : within;
|
|
26466
26483
|
}
|
|
26467
26484
|
|
|
@@ -26903,9 +26920,9 @@ function registerMiro(program2) {
|
|
|
26903
26920
|
}
|
|
26904
26921
|
|
|
26905
26922
|
// src/commands/netcap/netcap.ts
|
|
26906
|
-
import { mkdir as
|
|
26923
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
26907
26924
|
import { createServer as createServer2 } from "http";
|
|
26908
|
-
import { dirname as
|
|
26925
|
+
import { dirname as dirname33 } from "path";
|
|
26909
26926
|
import chalk178 from "chalk";
|
|
26910
26927
|
|
|
26911
26928
|
// src/commands/netcap/corsHeaders.ts
|
|
@@ -26984,15 +27001,15 @@ function createNetcapHandler(options2) {
|
|
|
26984
27001
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
26985
27002
|
import { cp as cp4, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
26986
27003
|
import { networkInterfaces } from "os";
|
|
26987
|
-
import { join as
|
|
27004
|
+
import { join as join67 } from "path";
|
|
26988
27005
|
import chalk177 from "chalk";
|
|
26989
27006
|
|
|
26990
27007
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
26991
|
-
import { dirname as
|
|
27008
|
+
import { dirname as dirname32, join as join66 } from "path";
|
|
26992
27009
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
26993
|
-
var moduleDir2 =
|
|
27010
|
+
var moduleDir2 = dirname32(fileURLToPath7(import.meta.url));
|
|
26994
27011
|
function netcapExtensionDir() {
|
|
26995
|
-
return
|
|
27012
|
+
return join66(moduleDir2, "commands", "netcap", "netcap-extension");
|
|
26996
27013
|
}
|
|
26997
27014
|
|
|
26998
27015
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
@@ -27007,7 +27024,7 @@ function lanIPv4() {
|
|
|
27007
27024
|
return void 0;
|
|
27008
27025
|
}
|
|
27009
27026
|
async function configureBackground(dir, host, port, filter) {
|
|
27010
|
-
const file =
|
|
27027
|
+
const file = join67(dir, "background.js");
|
|
27011
27028
|
const source = await readFile6(file, "utf8");
|
|
27012
27029
|
await writeFile6(
|
|
27013
27030
|
file,
|
|
@@ -27047,20 +27064,20 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
27047
27064
|
}
|
|
27048
27065
|
|
|
27049
27066
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
27050
|
-
import { isAbsolute as
|
|
27067
|
+
import { isAbsolute as isAbsolute5, join as join69, resolve as resolve21 } from "path";
|
|
27051
27068
|
|
|
27052
27069
|
// src/commands/netcap/defaultCapturePath.ts
|
|
27053
|
-
import { homedir as
|
|
27054
|
-
import { join as
|
|
27070
|
+
import { homedir as homedir22 } from "os";
|
|
27071
|
+
import { join as join68 } from "path";
|
|
27055
27072
|
function defaultCapturePath() {
|
|
27056
|
-
return
|
|
27073
|
+
return join68(homedir22(), ".assist", "netcap", "capture.jsonl");
|
|
27057
27074
|
}
|
|
27058
27075
|
|
|
27059
27076
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
27060
27077
|
function resolveNetcapOutPath(out) {
|
|
27061
27078
|
if (!out) return defaultCapturePath();
|
|
27062
|
-
const dir =
|
|
27063
|
-
return
|
|
27079
|
+
const dir = isAbsolute5(out) ? out : resolve21(process.cwd(), out);
|
|
27080
|
+
return join69(dir, "capture.jsonl");
|
|
27064
27081
|
}
|
|
27065
27082
|
|
|
27066
27083
|
// src/commands/netcap/netcap.ts
|
|
@@ -27068,7 +27085,7 @@ async function netcap(options2) {
|
|
|
27068
27085
|
const port = Number(options2.port);
|
|
27069
27086
|
const outPath = resolveNetcapOutPath(options2.out);
|
|
27070
27087
|
const filter = options2.filter ?? "";
|
|
27071
|
-
await
|
|
27088
|
+
await mkdir6(dirname33(outPath), { recursive: true });
|
|
27072
27089
|
const extensionPath = await prepareExtensionForLoad(port, filter);
|
|
27073
27090
|
let count8 = 0;
|
|
27074
27091
|
const handler = createNetcapHandler({
|
|
@@ -27107,7 +27124,7 @@ netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} t
|
|
|
27107
27124
|
|
|
27108
27125
|
// src/commands/netcap/netcapExtract.ts
|
|
27109
27126
|
import { writeFileSync as writeFileSync34 } from "fs";
|
|
27110
|
-
import { join as
|
|
27127
|
+
import { join as join70 } from "path";
|
|
27111
27128
|
import chalk179 from "chalk";
|
|
27112
27129
|
|
|
27113
27130
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
@@ -27150,25 +27167,25 @@ function isVisibleText(t) {
|
|
|
27150
27167
|
return /[a-zA-Z]{3,}/.test(t);
|
|
27151
27168
|
}
|
|
27152
27169
|
var isHashtag = (t) => /^#[A-Za-z0-9_]+$/.test(t);
|
|
27153
|
-
function collectRscText(v,
|
|
27170
|
+
function collectRscText(v, resolve28, sink3, seen) {
|
|
27154
27171
|
if (v == null) return;
|
|
27155
27172
|
if (typeof v === "string") {
|
|
27156
27173
|
if (isRscRef(v)) {
|
|
27157
27174
|
if (!seen.has(v)) {
|
|
27158
27175
|
seen.add(v);
|
|
27159
|
-
collectRscText(
|
|
27176
|
+
collectRscText(resolve28(v), resolve28, sink3, seen);
|
|
27160
27177
|
}
|
|
27161
27178
|
} else if (isHashtag(v)) sink3.hashtags.push(v);
|
|
27162
27179
|
else if (isVisibleText(v)) sink3.text.push(v);
|
|
27163
27180
|
return;
|
|
27164
27181
|
}
|
|
27165
27182
|
if (Array.isArray(v)) {
|
|
27166
|
-
for (const x of v) collectRscText(x,
|
|
27183
|
+
for (const x of v) collectRscText(x, resolve28, sink3, seen);
|
|
27167
27184
|
return;
|
|
27168
27185
|
}
|
|
27169
27186
|
if (typeof v === "object") {
|
|
27170
27187
|
for (const val of Object.values(v)) {
|
|
27171
|
-
collectRscText(val,
|
|
27188
|
+
collectRscText(val, resolve28, sink3, seen);
|
|
27172
27189
|
}
|
|
27173
27190
|
}
|
|
27174
27191
|
}
|
|
@@ -27200,7 +27217,7 @@ function visitObjects(root2, fn) {
|
|
|
27200
27217
|
}
|
|
27201
27218
|
}
|
|
27202
27219
|
}
|
|
27203
|
-
function buildMentionMap(rows,
|
|
27220
|
+
function buildMentionMap(rows, resolve28) {
|
|
27204
27221
|
const map = /* @__PURE__ */ new Map();
|
|
27205
27222
|
visitObjects(rows, (o) => {
|
|
27206
27223
|
const url = profileActionUrl(o);
|
|
@@ -27208,7 +27225,7 @@ function buildMentionMap(rows, resolve27) {
|
|
|
27208
27225
|
const slug2 = slugFromProfileUrl(url);
|
|
27209
27226
|
if (!slug2 || map.has(slug2)) return;
|
|
27210
27227
|
const sink3 = { text: [], hashtags: [] };
|
|
27211
|
-
collectRscText(o.children,
|
|
27228
|
+
collectRscText(o.children, resolve28, sink3, /* @__PURE__ */ new Set());
|
|
27212
27229
|
const name = sink3.text.join(" ").replace(/\s+/g, " ").trim();
|
|
27213
27230
|
map.set(slug2, name ? { slug: slug2, name, url } : { slug: slug2, url });
|
|
27214
27231
|
});
|
|
@@ -27294,10 +27311,10 @@ function buildPost(raw, mentionMap, author) {
|
|
|
27294
27311
|
|
|
27295
27312
|
// src/commands/netcap/walkPostRow.ts
|
|
27296
27313
|
var isCommentary = (o) => asObject(o.viewTrackingSpecs)?.viewName === "feed-commentary";
|
|
27297
|
-
function walkPostRow(v,
|
|
27314
|
+
function walkPostRow(v, resolve28, raw) {
|
|
27298
27315
|
if (v == null || typeof v !== "object") return;
|
|
27299
27316
|
if (Array.isArray(v)) {
|
|
27300
|
-
for (const x of v) walkPostRow(x,
|
|
27317
|
+
for (const x of v) walkPostRow(x, resolve28, raw);
|
|
27301
27318
|
return;
|
|
27302
27319
|
}
|
|
27303
27320
|
const o = v;
|
|
@@ -27311,9 +27328,9 @@ function walkPostRow(v, resolve27, raw) {
|
|
|
27311
27328
|
}
|
|
27312
27329
|
if (isCommentary(o)) {
|
|
27313
27330
|
const sink3 = { text: raw.text, hashtags: raw.hashtags };
|
|
27314
|
-
collectRscText(o.children,
|
|
27331
|
+
collectRscText(o.children, resolve28, sink3, /* @__PURE__ */ new Set());
|
|
27315
27332
|
}
|
|
27316
|
-
for (const val of Object.values(o)) walkPostRow(val,
|
|
27333
|
+
for (const val of Object.values(o)) walkPostRow(val, resolve28, raw);
|
|
27317
27334
|
}
|
|
27318
27335
|
|
|
27319
27336
|
// src/commands/netcap/extractLinkedInPosts.ts
|
|
@@ -27327,8 +27344,8 @@ function findCommentaryRows(rows) {
|
|
|
27327
27344
|
}
|
|
27328
27345
|
function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
|
|
27329
27346
|
const rows = parseRscRows(flight);
|
|
27330
|
-
const
|
|
27331
|
-
const mentionMap = buildMentionMap(rows,
|
|
27347
|
+
const resolve28 = makeRscResolver(rows);
|
|
27348
|
+
const mentionMap = buildMentionMap(rows, resolve28);
|
|
27332
27349
|
const posts = [];
|
|
27333
27350
|
for (const id of findCommentaryRows(rows)) {
|
|
27334
27351
|
const raw = {
|
|
@@ -27338,7 +27355,7 @@ function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
|
|
|
27338
27355
|
links: [],
|
|
27339
27356
|
related: []
|
|
27340
27357
|
};
|
|
27341
|
-
walkPostRow(rows[id],
|
|
27358
|
+
walkPostRow(rows[id], resolve28, raw);
|
|
27342
27359
|
const post = buildPost(raw, mentionMap, author);
|
|
27343
27360
|
if (post) posts.push(post);
|
|
27344
27361
|
}
|
|
@@ -27552,7 +27569,7 @@ function extractPostsFromCapture(captureFile) {
|
|
|
27552
27569
|
function netcapExtract(file) {
|
|
27553
27570
|
const captureFile = file ?? defaultCapturePath();
|
|
27554
27571
|
const posts = extractPostsFromCapture(captureFile);
|
|
27555
|
-
const outFile =
|
|
27572
|
+
const outFile = join70(captureFile, "..", "posts.json");
|
|
27556
27573
|
writeFileSync34(outFile, `${JSON.stringify(posts, null, 2)}
|
|
27557
27574
|
`);
|
|
27558
27575
|
console.log(
|
|
@@ -27914,19 +27931,19 @@ import { execSync as execSync41 } from "child_process";
|
|
|
27914
27931
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
27915
27932
|
import { execSync as execSync40 } from "child_process";
|
|
27916
27933
|
import { unlinkSync as unlinkSync14, writeFileSync as writeFileSync35 } from "fs";
|
|
27917
|
-
import { tmpdir as
|
|
27918
|
-
import { join as
|
|
27934
|
+
import { tmpdir as tmpdir6 } from "os";
|
|
27935
|
+
import { join as join72 } from "path";
|
|
27919
27936
|
|
|
27920
27937
|
// src/commands/prs/loadCommentsCache.ts
|
|
27921
27938
|
import { existsSync as existsSync62, readFileSync as readFileSync43, unlinkSync as unlinkSync13 } from "fs";
|
|
27922
27939
|
import { parse as parse3 } from "yaml";
|
|
27923
27940
|
|
|
27924
27941
|
// src/commands/prs/commentsCachePath.ts
|
|
27925
|
-
import { homedir as
|
|
27926
|
-
import { join as
|
|
27942
|
+
import { homedir as homedir23 } from "os";
|
|
27943
|
+
import { join as join71 } from "path";
|
|
27927
27944
|
function commentsCachePath(org, repo, prNumber) {
|
|
27928
|
-
return
|
|
27929
|
-
|
|
27945
|
+
return join71(
|
|
27946
|
+
homedir23(),
|
|
27930
27947
|
".assist",
|
|
27931
27948
|
"pr-comments",
|
|
27932
27949
|
org,
|
|
@@ -27974,7 +27991,7 @@ function replyToComment(org, repo, prNumber, commentId, message3) {
|
|
|
27974
27991
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
27975
27992
|
function resolveThread(threadId) {
|
|
27976
27993
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
27977
|
-
const queryFile =
|
|
27994
|
+
const queryFile = join72(tmpdir6(), `gh-mutation-${Date.now()}.graphql`);
|
|
27978
27995
|
writeFileSync35(queryFile, mutation);
|
|
27979
27996
|
try {
|
|
27980
27997
|
execSync40(
|
|
@@ -28058,11 +28075,11 @@ function fixed(commentId, sha) {
|
|
|
28058
28075
|
// src/commands/prs/fetchThreadIds.ts
|
|
28059
28076
|
import { execSync as execSync42 } from "child_process";
|
|
28060
28077
|
import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync36 } from "fs";
|
|
28061
|
-
import { tmpdir as
|
|
28062
|
-
import { join as
|
|
28078
|
+
import { tmpdir as tmpdir7 } from "os";
|
|
28079
|
+
import { join as join73 } from "path";
|
|
28063
28080
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
28064
28081
|
function fetchThreadIds(org, repo, prNumber) {
|
|
28065
|
-
const queryFile =
|
|
28082
|
+
const queryFile = join73(tmpdir7(), `gh-query-${Date.now()}.graphql`);
|
|
28066
28083
|
writeFileSync36(queryFile, THREAD_QUERY);
|
|
28067
28084
|
try {
|
|
28068
28085
|
const result = execSync42(
|
|
@@ -28132,15 +28149,15 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
28132
28149
|
|
|
28133
28150
|
// src/commands/prs/listComments/updateCommentsCache.ts
|
|
28134
28151
|
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync37 } from "fs";
|
|
28135
|
-
import { dirname as
|
|
28152
|
+
import { dirname as dirname34 } from "path";
|
|
28136
28153
|
import { stringify as stringify3 } from "yaml";
|
|
28137
28154
|
|
|
28138
28155
|
// src/commands/prs/removeStaleCommentsCaches.ts
|
|
28139
28156
|
import { readdirSync as readdirSync11, unlinkSync as unlinkSync16 } from "fs";
|
|
28140
|
-
import { join as
|
|
28157
|
+
import { join as join74 } from "path";
|
|
28141
28158
|
var STALE_PATTERN = /^pr-\d+-comments\.yaml$/;
|
|
28142
28159
|
function removeStaleCommentsCaches(cwd = process.cwd()) {
|
|
28143
|
-
const dir =
|
|
28160
|
+
const dir = join74(cwd, ".assist");
|
|
28144
28161
|
let entries;
|
|
28145
28162
|
try {
|
|
28146
28163
|
entries = readdirSync11(dir);
|
|
@@ -28148,14 +28165,14 @@ function removeStaleCommentsCaches(cwd = process.cwd()) {
|
|
|
28148
28165
|
return;
|
|
28149
28166
|
}
|
|
28150
28167
|
for (const entry of entries.filter((e) => STALE_PATTERN.test(e))) {
|
|
28151
|
-
unlinkSync16(
|
|
28168
|
+
unlinkSync16(join74(dir, entry));
|
|
28152
28169
|
}
|
|
28153
28170
|
}
|
|
28154
28171
|
|
|
28155
28172
|
// src/commands/prs/listComments/updateCommentsCache.ts
|
|
28156
28173
|
function writeCommentsCache(org, repo, prNumber, comments3) {
|
|
28157
28174
|
const cachePath = commentsCachePath(org, repo, prNumber);
|
|
28158
|
-
mkdirSync20(
|
|
28175
|
+
mkdirSync20(dirname34(cachePath), { recursive: true });
|
|
28159
28176
|
const cacheData = {
|
|
28160
28177
|
prNumber,
|
|
28161
28178
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -28487,16 +28504,11 @@ function registerPrsComments(prsCommand) {
|
|
|
28487
28504
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
28488
28505
|
|
|
28489
28506
|
// src/commands/prs/applyEdit.ts
|
|
28490
|
-
|
|
28491
|
-
function applyEdit(number, title, body) {
|
|
28507
|
+
function applyEdit(number, title, body, attachments = []) {
|
|
28492
28508
|
const args = ["pr", "edit", String(number)];
|
|
28493
28509
|
if (title) args.push("--title", title);
|
|
28494
|
-
args.push("--body", body);
|
|
28495
|
-
|
|
28496
|
-
execFileSync16("gh", args, { stdio: "inherit" });
|
|
28497
|
-
} catch {
|
|
28498
|
-
process.exit(1);
|
|
28499
|
-
}
|
|
28510
|
+
args.push("--body", body, ...attachArgs(attachments));
|
|
28511
|
+
process.stdout.write(runGhWithAttachments(args, attachments));
|
|
28500
28512
|
}
|
|
28501
28513
|
|
|
28502
28514
|
// src/commands/prs/formatResolvesReference.ts
|
|
@@ -28684,10 +28696,12 @@ async function edit(options2) {
|
|
|
28684
28696
|
body: newBody,
|
|
28685
28697
|
prNumber: number
|
|
28686
28698
|
});
|
|
28699
|
+
const attachments = decision.screenshots ?? [];
|
|
28687
28700
|
applyEdit(
|
|
28688
28701
|
number,
|
|
28689
28702
|
options2.title,
|
|
28690
|
-
appendScreenshots(newBody,
|
|
28703
|
+
appendScreenshots(newBody, attachments),
|
|
28704
|
+
attachments
|
|
28691
28705
|
);
|
|
28692
28706
|
return;
|
|
28693
28707
|
}
|
|
@@ -28785,14 +28799,19 @@ function buildValidatedBody(options2, usage) {
|
|
|
28785
28799
|
}
|
|
28786
28800
|
|
|
28787
28801
|
// src/commands/prs/placePr.ts
|
|
28788
|
-
import { execFileSync as
|
|
28802
|
+
import { execFileSync as execFileSync16 } from "child_process";
|
|
28789
28803
|
|
|
28790
28804
|
// src/commands/prs/buildCreateArgs.ts
|
|
28791
|
-
function
|
|
28792
|
-
|
|
28793
|
-
|
|
28794
|
-
|
|
28795
|
-
|
|
28805
|
+
function buildCreateArgs(title, body, options2, attachments = []) {
|
|
28806
|
+
const args = [
|
|
28807
|
+
"pr",
|
|
28808
|
+
"create",
|
|
28809
|
+
"--title",
|
|
28810
|
+
title,
|
|
28811
|
+
"--body",
|
|
28812
|
+
body,
|
|
28813
|
+
...attachArgs(attachments)
|
|
28814
|
+
];
|
|
28796
28815
|
const valueFlags = [
|
|
28797
28816
|
["--base", options2.base],
|
|
28798
28817
|
["--head", options2.head],
|
|
@@ -28849,10 +28868,24 @@ async function recordPrActivity() {
|
|
|
28849
28868
|
if (pr) await recordSessionRefs([pr]);
|
|
28850
28869
|
}
|
|
28851
28870
|
|
|
28871
|
+
// src/commands/prs/buildEditArgs.ts
|
|
28872
|
+
function buildEditArgs(number, title, body, attachments = []) {
|
|
28873
|
+
return [
|
|
28874
|
+
"pr",
|
|
28875
|
+
"edit",
|
|
28876
|
+
String(number),
|
|
28877
|
+
"--title",
|
|
28878
|
+
title,
|
|
28879
|
+
"--body",
|
|
28880
|
+
body,
|
|
28881
|
+
...attachArgs(attachments)
|
|
28882
|
+
];
|
|
28883
|
+
}
|
|
28884
|
+
|
|
28852
28885
|
// src/commands/prs/placePr.ts
|
|
28853
28886
|
function hasUpstream2() {
|
|
28854
28887
|
try {
|
|
28855
|
-
|
|
28888
|
+
execFileSync16(
|
|
28856
28889
|
"git",
|
|
28857
28890
|
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
28858
28891
|
{ stdio: "pipe" }
|
|
@@ -28864,16 +28897,16 @@ function hasUpstream2() {
|
|
|
28864
28897
|
}
|
|
28865
28898
|
function ensureBranchPushed() {
|
|
28866
28899
|
const args = hasUpstream2() ? ["push"] : ["push", "--set-upstream", "origin", "HEAD"];
|
|
28867
|
-
|
|
28900
|
+
execFileSync16("git", args, { stdio: "inherit" });
|
|
28868
28901
|
}
|
|
28869
|
-
async function placePr(prNumber, title, body, options2) {
|
|
28870
|
-
const args = prNumber !== null ? buildEditArgs(prNumber, title, body) : buildCreateArgs(title, body, options2);
|
|
28902
|
+
async function placePr(prNumber, title, body, options2, attachments = []) {
|
|
28903
|
+
const args = prNumber !== null ? buildEditArgs(prNumber, title, body, attachments) : buildCreateArgs(title, body, options2, attachments);
|
|
28871
28904
|
try {
|
|
28872
28905
|
if (prNumber === null && !options2.head) ensureBranchPushed();
|
|
28873
|
-
execFileSync17("gh", args, { stdio: "inherit" });
|
|
28874
28906
|
} catch {
|
|
28875
28907
|
process.exit(1);
|
|
28876
28908
|
}
|
|
28909
|
+
process.stdout.write(runGhWithAttachments(args, attachments));
|
|
28877
28910
|
await recordPrActivity();
|
|
28878
28911
|
}
|
|
28879
28912
|
|
|
@@ -28893,7 +28926,7 @@ function parseIncoming(line, type) {
|
|
|
28893
28926
|
}
|
|
28894
28927
|
}
|
|
28895
28928
|
function requestSession(message3) {
|
|
28896
|
-
return new Promise((
|
|
28929
|
+
return new Promise((resolve28, reject) => {
|
|
28897
28930
|
connectToDaemon().then((socket) => {
|
|
28898
28931
|
let settled = false;
|
|
28899
28932
|
const finish2 = (error, sessionId) => {
|
|
@@ -28901,7 +28934,7 @@ function requestSession(message3) {
|
|
|
28901
28934
|
settled = true;
|
|
28902
28935
|
socket.destroy();
|
|
28903
28936
|
if (error) reject(error);
|
|
28904
|
-
else
|
|
28937
|
+
else resolve28(sessionId);
|
|
28905
28938
|
};
|
|
28906
28939
|
readSocketLines(socket, (line) => {
|
|
28907
28940
|
const incoming = parseIncoming(line, message3.type);
|
|
@@ -29010,10 +29043,10 @@ function warn(reason4) {
|
|
|
29010
29043
|
}
|
|
29011
29044
|
|
|
29012
29045
|
// src/commands/prs/enableAutoMerge.ts
|
|
29013
|
-
import { execFileSync as
|
|
29046
|
+
import { execFileSync as execFileSync17 } from "child_process";
|
|
29014
29047
|
function enableAutoMerge() {
|
|
29015
29048
|
try {
|
|
29016
|
-
|
|
29049
|
+
execFileSync17(
|
|
29017
29050
|
"gh",
|
|
29018
29051
|
["pr", "merge", getCurrentBranch2(), "--auto", "--squash"],
|
|
29019
29052
|
{ stdio: "inherit" }
|
|
@@ -29035,9 +29068,10 @@ async function previewAndPlace(args) {
|
|
|
29035
29068
|
prNumber: args.prNumber,
|
|
29036
29069
|
draft: args.options.draft === true
|
|
29037
29070
|
});
|
|
29038
|
-
const
|
|
29071
|
+
const attachments = decision.screenshots ?? [];
|
|
29072
|
+
const body = appendScreenshots(args.body, attachments);
|
|
29039
29073
|
const options2 = decision.draft === void 0 ? args.options : { ...args.options, draft: decision.draft };
|
|
29040
|
-
await placePr(args.prNumber, args.title, body, options2);
|
|
29074
|
+
await placePr(args.prNumber, args.title, body, options2, attachments);
|
|
29041
29075
|
if (decision.autoMerge === true) enableAutoMerge();
|
|
29042
29076
|
await chainAfterRaise(args.prNumber, decision);
|
|
29043
29077
|
}
|
|
@@ -29178,7 +29212,7 @@ inline comments to specific spans of the preview; on rejection these are printed
|
|
|
29178
29212
|
as numbered quoted-span + note pairs on stderr. Address every comment (and the
|
|
29179
29213
|
reason), then run the command again to re-preview the revised PR. Repeat until it
|
|
29180
29214
|
is approved. The reviewer may also drop or paste screenshots or video into the
|
|
29181
|
-
pane; on approval
|
|
29215
|
+
pane; on approval gh attaches them (gh ${minGhAttachVersion}+) under a ## Screenshots section
|
|
29182
29216
|
automatically; on rejection they stay attached and reappear in the preview you
|
|
29183
29217
|
re-propose, so you never author that section yourself. Just compose the sections
|
|
29184
29218
|
and run the command.`;
|
|
@@ -29954,13 +29988,13 @@ ${errorText}`
|
|
|
29954
29988
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
29955
29989
|
import { execSync as execSync50 } from "child_process";
|
|
29956
29990
|
import chalk192 from "chalk";
|
|
29957
|
-
function resolveOpSecret(
|
|
29958
|
-
if (!
|
|
29991
|
+
function resolveOpSecret(reference2) {
|
|
29992
|
+
if (!reference2.startsWith("op://")) {
|
|
29959
29993
|
console.error(chalk192.red(`Invalid secret reference: must start with op://`));
|
|
29960
29994
|
process.exit(1);
|
|
29961
29995
|
}
|
|
29962
29996
|
try {
|
|
29963
|
-
return execSync50(`op read "${
|
|
29997
|
+
return execSync50(`op read "${reference2}"`, {
|
|
29964
29998
|
encoding: "utf8",
|
|
29965
29999
|
stdio: ["pipe", "pipe", "pipe"]
|
|
29966
30000
|
}).trim();
|
|
@@ -30769,8 +30803,8 @@ async function notify() {
|
|
|
30769
30803
|
// src/commands/screenshot.ts
|
|
30770
30804
|
import { execSync as execSync52 } from "child_process";
|
|
30771
30805
|
import { existsSync as existsSync63, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync38 } from "fs";
|
|
30772
|
-
import { tmpdir as
|
|
30773
|
-
import { join as
|
|
30806
|
+
import { tmpdir as tmpdir8 } from "os";
|
|
30807
|
+
import { join as join75, resolve as resolve22 } from "path";
|
|
30774
30808
|
import chalk204 from "chalk";
|
|
30775
30809
|
|
|
30776
30810
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -30904,10 +30938,10 @@ function buildOutputPath(outputDir, processName) {
|
|
|
30904
30938
|
mkdirSync21(outputDir, { recursive: true });
|
|
30905
30939
|
}
|
|
30906
30940
|
const timestamp5 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
30907
|
-
return
|
|
30941
|
+
return resolve22(outputDir, `${processName}-${timestamp5}.png`);
|
|
30908
30942
|
}
|
|
30909
30943
|
function runPowerShellScript(processName, outputPath) {
|
|
30910
|
-
const scriptPath =
|
|
30944
|
+
const scriptPath = join75(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
|
|
30911
30945
|
writeFileSync38(scriptPath, captureWindowPs1, "utf8");
|
|
30912
30946
|
try {
|
|
30913
30947
|
execSync52(
|
|
@@ -30920,7 +30954,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
30920
30954
|
}
|
|
30921
30955
|
function screenshot(processName) {
|
|
30922
30956
|
const config = loadConfig();
|
|
30923
|
-
const outputDir =
|
|
30957
|
+
const outputDir = resolve22(config.screenshot.outputDir);
|
|
30924
30958
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
30925
30959
|
console.log(chalk204.gray(`Capturing window for process "${processName}" ...`));
|
|
30926
30960
|
try {
|
|
@@ -31022,16 +31056,16 @@ function buildLimitsSegment(rateLimits) {
|
|
|
31022
31056
|
|
|
31023
31057
|
// src/commands/readGitBranch.ts
|
|
31024
31058
|
import { readFileSync as readFileSync46, statSync as statSync9 } from "fs";
|
|
31025
|
-
import { isAbsolute as
|
|
31059
|
+
import { isAbsolute as isAbsolute6, join as join76, resolve as resolve23 } from "path";
|
|
31026
31060
|
function resolveGitDir(cwd) {
|
|
31027
|
-
const dotGit =
|
|
31028
|
-
let
|
|
31061
|
+
const dotGit = join76(cwd, ".git");
|
|
31062
|
+
let stat5;
|
|
31029
31063
|
try {
|
|
31030
|
-
|
|
31064
|
+
stat5 = statSync9(dotGit);
|
|
31031
31065
|
} catch {
|
|
31032
31066
|
return null;
|
|
31033
31067
|
}
|
|
31034
|
-
if (
|
|
31068
|
+
if (stat5.isDirectory()) {
|
|
31035
31069
|
return dotGit;
|
|
31036
31070
|
}
|
|
31037
31071
|
let contents;
|
|
@@ -31045,7 +31079,7 @@ function resolveGitDir(cwd) {
|
|
|
31045
31079
|
return null;
|
|
31046
31080
|
}
|
|
31047
31081
|
const gitDir = match[1].trim();
|
|
31048
|
-
return
|
|
31082
|
+
return isAbsolute6(gitDir) ? gitDir : resolve23(cwd, gitDir);
|
|
31049
31083
|
}
|
|
31050
31084
|
function readGitBranch(cwd) {
|
|
31051
31085
|
const gitDir = resolveGitDir(cwd);
|
|
@@ -31054,7 +31088,7 @@ function readGitBranch(cwd) {
|
|
|
31054
31088
|
}
|
|
31055
31089
|
let head;
|
|
31056
31090
|
try {
|
|
31057
|
-
head = readFileSync46(
|
|
31091
|
+
head = readFileSync46(join76(gitDir, "HEAD"), "utf8");
|
|
31058
31092
|
} catch {
|
|
31059
31093
|
return null;
|
|
31060
31094
|
}
|
|
@@ -31355,7 +31389,7 @@ function getViolations(pattern2, options2 = {}, maxLines = DEFAULT_MAX_LINES2) {
|
|
|
31355
31389
|
|
|
31356
31390
|
// src/commands/refactor/check.ts
|
|
31357
31391
|
function runScript(script, cwd) {
|
|
31358
|
-
return new Promise((
|
|
31392
|
+
return new Promise((resolve28) => {
|
|
31359
31393
|
const child = spawn7("npm", ["run", script], {
|
|
31360
31394
|
stdio: "pipe",
|
|
31361
31395
|
shell: true,
|
|
@@ -31369,7 +31403,7 @@ function runScript(script, cwd) {
|
|
|
31369
31403
|
output += data.toString();
|
|
31370
31404
|
});
|
|
31371
31405
|
child.on("close", (code) => {
|
|
31372
|
-
|
|
31406
|
+
resolve28({ script, code: code ?? 1, output });
|
|
31373
31407
|
});
|
|
31374
31408
|
});
|
|
31375
31409
|
}
|
|
@@ -33475,7 +33509,7 @@ function exitWith(message3) {
|
|
|
33475
33509
|
}
|
|
33476
33510
|
|
|
33477
33511
|
// src/commands/review/highLevel/proposeHighLevelGlobs.ts
|
|
33478
|
-
import { execFileSync as
|
|
33512
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
33479
33513
|
import chalk227 from "chalk";
|
|
33480
33514
|
|
|
33481
33515
|
// src/commands/review/highLevel/buildGlobProposalPrompt.ts
|
|
@@ -33523,8 +33557,8 @@ function readGlobs(value) {
|
|
|
33523
33557
|
}
|
|
33524
33558
|
|
|
33525
33559
|
// src/commands/review/highLevel/summariseRepoTree.ts
|
|
33526
|
-
import { execFileSync as
|
|
33527
|
-
import { dirname as
|
|
33560
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
33561
|
+
import { dirname as dirname36, extname as extname4 } from "path";
|
|
33528
33562
|
var MAX_DIRECTORIES = 200;
|
|
33529
33563
|
var MAX_EXTENSIONS_PER_DIRECTORY = 6;
|
|
33530
33564
|
function summariseRepoTree(cwd = process.cwd()) {
|
|
@@ -33539,7 +33573,7 @@ function summariseRepoTree(cwd = process.cwd()) {
|
|
|
33539
33573
|
}
|
|
33540
33574
|
function listTrackedFiles(cwd) {
|
|
33541
33575
|
try {
|
|
33542
|
-
return
|
|
33576
|
+
return execFileSync18("git", ["ls-files"], {
|
|
33543
33577
|
cwd,
|
|
33544
33578
|
encoding: "utf8",
|
|
33545
33579
|
maxBuffer: 64 * 1024 * 1024
|
|
@@ -33551,9 +33585,9 @@ function listTrackedFiles(cwd) {
|
|
|
33551
33585
|
function countByDirectory(files) {
|
|
33552
33586
|
const directories = /* @__PURE__ */ new Map();
|
|
33553
33587
|
for (const file of files) {
|
|
33554
|
-
const directory =
|
|
33588
|
+
const directory = dirname36(file) === "." ? "(repo root)" : dirname36(file);
|
|
33555
33589
|
const extensions = directories.get(directory) ?? /* @__PURE__ */ new Map();
|
|
33556
|
-
const extension =
|
|
33590
|
+
const extension = extname4(file) === "" ? "(no extension)" : extname4(file);
|
|
33557
33591
|
extensions.set(extension, (extensions.get(extension) ?? 0) + 1);
|
|
33558
33592
|
directories.set(directory, extensions);
|
|
33559
33593
|
}
|
|
@@ -33584,7 +33618,7 @@ function proposeHighLevelGlobs(cwd = process.cwd()) {
|
|
|
33584
33618
|
}
|
|
33585
33619
|
function askClaude(prompt, cwd) {
|
|
33586
33620
|
try {
|
|
33587
|
-
return
|
|
33621
|
+
return execFileSync19("claude", ["-p", "--model", "sonnet", prompt], {
|
|
33588
33622
|
cwd,
|
|
33589
33623
|
encoding: "utf8",
|
|
33590
33624
|
timeout: 12e4,
|
|
@@ -33677,7 +33711,7 @@ function groupFilesByDirectory(files) {
|
|
|
33677
33711
|
}
|
|
33678
33712
|
|
|
33679
33713
|
// src/commands/review/highLevel/buildHighLevelTree.ts
|
|
33680
|
-
function
|
|
33714
|
+
function basename20(path106) {
|
|
33681
33715
|
return path106.slice(path106.lastIndexOf("/") + 1);
|
|
33682
33716
|
}
|
|
33683
33717
|
function sum(nodes, key) {
|
|
@@ -33693,7 +33727,7 @@ function nodesOf(at2, prefix2) {
|
|
|
33693
33727
|
const files = at2.files.map(
|
|
33694
33728
|
(file) => ({
|
|
33695
33729
|
kind: "file",
|
|
33696
|
-
name:
|
|
33730
|
+
name: basename20(file.path),
|
|
33697
33731
|
...file
|
|
33698
33732
|
})
|
|
33699
33733
|
);
|
|
@@ -33809,13 +33843,13 @@ function firstMatch(body, pattern2) {
|
|
|
33809
33843
|
return body.match(pattern2)?.[0] ?? null;
|
|
33810
33844
|
}
|
|
33811
33845
|
function checkDescriptionLinksIssue(body) {
|
|
33812
|
-
const
|
|
33813
|
-
if (!
|
|
33846
|
+
const reference2 = firstMatch(body, ISSUE_URL_PATTERN) ?? firstMatch(body, CROSS_REPO_PATTERN) ?? firstMatch(body, SAME_REPO_PATTERN2);
|
|
33847
|
+
if (!reference2)
|
|
33814
33848
|
return {
|
|
33815
33849
|
status: "fail",
|
|
33816
33850
|
reason: "no GitHub issue reference (`#123`, `owner/repo#123`, or an issue URL) in the description"
|
|
33817
33851
|
};
|
|
33818
|
-
return { status: "pass", reason: `links ${
|
|
33852
|
+
return { status: "pass", reason: `links ${reference2}` };
|
|
33819
33853
|
}
|
|
33820
33854
|
|
|
33821
33855
|
// src/commands/review/highLevel/checkDescriptionSections.ts
|
|
@@ -34013,12 +34047,12 @@ function fetchHighLevelPr(prNumber, repo) {
|
|
|
34013
34047
|
import { existsSync as existsSync64, readFileSync as readFileSync47 } from "fs";
|
|
34014
34048
|
|
|
34015
34049
|
// src/commands/review/highLevel/highLevelReviewPath.ts
|
|
34016
|
-
import { join as
|
|
34050
|
+
import { join as join77 } from "path";
|
|
34017
34051
|
function slug(value) {
|
|
34018
34052
|
return value.replace(/[^\w.-]+/g, "-");
|
|
34019
34053
|
}
|
|
34020
34054
|
function highLevelReviewPath(repo, headRef, headSha) {
|
|
34021
|
-
return
|
|
34055
|
+
return join77(
|
|
34022
34056
|
getStoreDir(),
|
|
34023
34057
|
"high-level-reviews",
|
|
34024
34058
|
slug(repo),
|
|
@@ -34156,10 +34190,10 @@ function highLevelPreviewPayload(subject) {
|
|
|
34156
34190
|
|
|
34157
34191
|
// src/commands/review/highLevel/saveHighLevelReview.ts
|
|
34158
34192
|
import { mkdirSync as mkdirSync22, writeFileSync as writeFileSync39 } from "fs";
|
|
34159
|
-
import { dirname as
|
|
34193
|
+
import { dirname as dirname37 } from "path";
|
|
34160
34194
|
function saveHighLevelReview(record) {
|
|
34161
34195
|
const path106 = highLevelReviewPath(record.repo, record.headRef, record.headSha);
|
|
34162
|
-
mkdirSync22(
|
|
34196
|
+
mkdirSync22(dirname37(path106), { recursive: true });
|
|
34163
34197
|
writeFileSync39(path106, `${JSON.stringify(record, null, 2)}
|
|
34164
34198
|
`);
|
|
34165
34199
|
return path106;
|
|
@@ -35094,7 +35128,7 @@ import { format } from "util";
|
|
|
35094
35128
|
|
|
35095
35129
|
// src/commands/review/createReviewLogSink.ts
|
|
35096
35130
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync23 } from "fs";
|
|
35097
|
-
import { join as
|
|
35131
|
+
import { join as join78 } from "path";
|
|
35098
35132
|
|
|
35099
35133
|
// src/shared/stripAnsi.ts
|
|
35100
35134
|
var ANSI = new RegExp(
|
|
@@ -35122,7 +35156,7 @@ function createReviewLogSink() {
|
|
|
35122
35156
|
},
|
|
35123
35157
|
attach(reviewDir) {
|
|
35124
35158
|
mkdirSync23(reviewDir, { recursive: true });
|
|
35125
|
-
logPath2 =
|
|
35159
|
+
logPath2 = join78(reviewDir, LOG_FILE);
|
|
35126
35160
|
const lines2 = [
|
|
35127
35161
|
"",
|
|
35128
35162
|
`=== ${(/* @__PURE__ */ new Date()).toISOString()} ===`,
|
|
@@ -35677,12 +35711,12 @@ function onCloseResult(ctx, code) {
|
|
|
35677
35711
|
return { ...closed, stderr: ctx.stderr.value, stdout: ctx.stdout.value };
|
|
35678
35712
|
}
|
|
35679
35713
|
function waitForChildExit(ctx) {
|
|
35680
|
-
return new Promise((
|
|
35714
|
+
return new Promise((resolve28) => {
|
|
35681
35715
|
let settled = false;
|
|
35682
35716
|
const settle = (result) => {
|
|
35683
35717
|
if (settled) return;
|
|
35684
35718
|
settled = true;
|
|
35685
|
-
|
|
35719
|
+
resolve28(result);
|
|
35686
35720
|
};
|
|
35687
35721
|
ctx.child.on("error", (err) => settle(onErrorResult(ctx, err)));
|
|
35688
35722
|
ctx.child.on("close", (code) => settle(onCloseResult(ctx, code)));
|
|
@@ -36203,22 +36237,22 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
|
36203
36237
|
}
|
|
36204
36238
|
|
|
36205
36239
|
// src/commands/review/buildReviewPaths.ts
|
|
36206
|
-
import { homedir as
|
|
36207
|
-
import { basename as
|
|
36240
|
+
import { homedir as homedir24 } from "os";
|
|
36241
|
+
import { basename as basename21, join as join79 } from "path";
|
|
36208
36242
|
function buildReviewPaths(repoRoot2, key) {
|
|
36209
|
-
const reviewDir =
|
|
36210
|
-
|
|
36243
|
+
const reviewDir = join79(
|
|
36244
|
+
homedir24(),
|
|
36211
36245
|
".assist",
|
|
36212
36246
|
"reviews",
|
|
36213
|
-
|
|
36247
|
+
basename21(repoRoot2),
|
|
36214
36248
|
key
|
|
36215
36249
|
);
|
|
36216
36250
|
return {
|
|
36217
36251
|
reviewDir,
|
|
36218
|
-
requestPath:
|
|
36219
|
-
claudePath:
|
|
36220
|
-
codexPath:
|
|
36221
|
-
synthesisPath:
|
|
36252
|
+
requestPath: join79(reviewDir, "request.md"),
|
|
36253
|
+
claudePath: join79(reviewDir, "claude.md"),
|
|
36254
|
+
codexPath: join79(reviewDir, "codex.md"),
|
|
36255
|
+
synthesisPath: join79(reviewDir, "synthesis.md")
|
|
36222
36256
|
};
|
|
36223
36257
|
}
|
|
36224
36258
|
|
|
@@ -37054,11 +37088,11 @@ import { randomUUID as randomUUID20 } from "crypto";
|
|
|
37054
37088
|
// src/commands/sessions/shared/sendShowPreview.ts
|
|
37055
37089
|
async function sendShowPreview(request) {
|
|
37056
37090
|
const socket = await connectToDaemon();
|
|
37057
|
-
await new Promise((
|
|
37091
|
+
await new Promise((resolve28, reject) => {
|
|
37058
37092
|
const finish2 = (error) => {
|
|
37059
37093
|
socket.destroy();
|
|
37060
37094
|
if (error) reject(error);
|
|
37061
|
-
else
|
|
37095
|
+
else resolve28();
|
|
37062
37096
|
};
|
|
37063
37097
|
readSocketLines(socket, (line) => {
|
|
37064
37098
|
const reply2 = parseReply(line);
|
|
@@ -37199,12 +37233,12 @@ async function reviewProposedSlackMessage(target, body, workingPath) {
|
|
|
37199
37233
|
}
|
|
37200
37234
|
|
|
37201
37235
|
// src/commands/slack/slackWorkingFile.ts
|
|
37202
|
-
import { join as
|
|
37236
|
+
import { join as join80 } from "path";
|
|
37203
37237
|
function slackWorkingFile(channel, partIndex) {
|
|
37204
37238
|
const slug2 = channel.replace(/^[#@]/, "").toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "channel";
|
|
37205
|
-
const dir =
|
|
37239
|
+
const dir = join80(getStoreDir(), "slack");
|
|
37206
37240
|
const name = partIndex === void 0 ? slug2 : `${slug2}-${partIndex}`;
|
|
37207
|
-
return { dir, bodyPath:
|
|
37241
|
+
return { dir, bodyPath: join80(dir, `${name}.md`) };
|
|
37208
37242
|
}
|
|
37209
37243
|
|
|
37210
37244
|
// src/commands/slack/previewSlackThreadParts.ts
|
|
@@ -38321,9 +38355,9 @@ function createReadlineInterface() {
|
|
|
38321
38355
|
});
|
|
38322
38356
|
}
|
|
38323
38357
|
function askQuestion(rl, question) {
|
|
38324
|
-
return new Promise((
|
|
38358
|
+
return new Promise((resolve28) => {
|
|
38325
38359
|
rl.question(question, (answer) => {
|
|
38326
|
-
|
|
38360
|
+
resolve28(answer.trim());
|
|
38327
38361
|
});
|
|
38328
38362
|
});
|
|
38329
38363
|
}
|
|
@@ -38384,20 +38418,20 @@ async function configure() {
|
|
|
38384
38418
|
|
|
38385
38419
|
// src/commands/transcript/list.ts
|
|
38386
38420
|
import { existsSync as existsSync76, readdirSync as readdirSync19, statSync as statSync11 } from "fs";
|
|
38387
|
-
import { join as
|
|
38421
|
+
import { join as join92 } from "path";
|
|
38388
38422
|
function list3() {
|
|
38389
38423
|
const { vttDir } = getTranscriptConfig();
|
|
38390
38424
|
if (!existsSync76(vttDir)) return;
|
|
38391
38425
|
for (const entry of readdirSync19(vttDir)) {
|
|
38392
38426
|
if (!entry.endsWith(".vtt")) continue;
|
|
38393
|
-
if (statSync11(
|
|
38427
|
+
if (statSync11(join92(vttDir, entry)).isDirectory()) continue;
|
|
38394
38428
|
console.log(entry);
|
|
38395
38429
|
}
|
|
38396
38430
|
}
|
|
38397
38431
|
|
|
38398
38432
|
// src/commands/transcript/move.ts
|
|
38399
38433
|
import { existsSync as existsSync77, mkdirSync as mkdirSync32, renameSync as renameSync2, writeFileSync as writeFileSync50 } from "fs";
|
|
38400
|
-
import { basename as
|
|
38434
|
+
import { basename as basename25, join as join93 } from "path";
|
|
38401
38435
|
|
|
38402
38436
|
// src/commands/transcript/convertVttToMarkdown.ts
|
|
38403
38437
|
function convertVttToMarkdown(inputPath) {
|
|
@@ -38407,9 +38441,9 @@ function convertVttToMarkdown(inputPath) {
|
|
|
38407
38441
|
// src/commands/transcript/move.ts
|
|
38408
38442
|
var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
38409
38443
|
function archiveRawVtt(vttDir, sourcePath, filename) {
|
|
38410
|
-
const processedDir =
|
|
38444
|
+
const processedDir = join93(vttDir, "processed");
|
|
38411
38445
|
mkdirSync32(processedDir, { recursive: true });
|
|
38412
|
-
renameSync2(sourcePath,
|
|
38446
|
+
renameSync2(sourcePath, join93(processedDir, filename));
|
|
38413
38447
|
}
|
|
38414
38448
|
function move(file, options2) {
|
|
38415
38449
|
const { date, client } = options2;
|
|
@@ -38418,27 +38452,27 @@ function move(file, options2) {
|
|
|
38418
38452
|
process.exit(1);
|
|
38419
38453
|
}
|
|
38420
38454
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
38421
|
-
const filename =
|
|
38422
|
-
const sourcePath =
|
|
38455
|
+
const filename = basename25(file);
|
|
38456
|
+
const sourcePath = join93(vttDir, filename);
|
|
38423
38457
|
if (!existsSync77(sourcePath)) {
|
|
38424
38458
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
38425
38459
|
process.exit(1);
|
|
38426
38460
|
}
|
|
38427
|
-
const base =
|
|
38461
|
+
const base = basename25(filename, ".vtt").replace(/ Transcription$/, "");
|
|
38428
38462
|
const outputName = `${date} ${base}.md`;
|
|
38429
|
-
const formattedDir =
|
|
38463
|
+
const formattedDir = join93(transcriptsDir, client);
|
|
38430
38464
|
mkdirSync32(formattedDir, { recursive: true });
|
|
38431
|
-
const formattedPath =
|
|
38465
|
+
const formattedPath = join93(formattedDir, outputName);
|
|
38432
38466
|
writeFileSync50(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
38433
38467
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
38434
|
-
const summaryPath =
|
|
38468
|
+
const summaryPath = join93(summaryDir, client, outputName);
|
|
38435
38469
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
38436
38470
|
console.log(`Summary target: ${summaryPath}`);
|
|
38437
38471
|
}
|
|
38438
38472
|
|
|
38439
38473
|
// src/commands/transcript/merge.ts
|
|
38440
38474
|
import { existsSync as existsSync78, writeFileSync as writeFileSync51 } from "fs";
|
|
38441
|
-
import { basename as
|
|
38475
|
+
import { basename as basename26 } from "path";
|
|
38442
38476
|
|
|
38443
38477
|
// src/commands/transcript/failTranscript.ts
|
|
38444
38478
|
function failTranscript(message3) {
|
|
@@ -38584,7 +38618,7 @@ function readSource3(file) {
|
|
|
38584
38618
|
if (!existsSync78(file)) failTranscript(`VTT file not found: ${file}`);
|
|
38585
38619
|
const cues = readCleanedCues(file);
|
|
38586
38620
|
if (cues.length === 0) failTranscript(`no cues found in: ${file}`);
|
|
38587
|
-
return { path: file, name:
|
|
38621
|
+
return { path: file, name: basename26(file), cues };
|
|
38588
38622
|
}
|
|
38589
38623
|
function wholePassages(sources) {
|
|
38590
38624
|
return sources.map((source) => ({
|
|
@@ -39245,7 +39279,7 @@ function listMigrationFiles(dir) {
|
|
|
39245
39279
|
|
|
39246
39280
|
// src/commands/verify/migrations/readBaselineMigrations.ts
|
|
39247
39281
|
import { execSync as execSync63 } from "child_process";
|
|
39248
|
-
import { basename as
|
|
39282
|
+
import { basename as basename27 } from "path";
|
|
39249
39283
|
var MIGRATION_FILE3 = /^migration\d+[A-Za-z0-9]*\.ts$/;
|
|
39250
39284
|
function readBaselineMigrations(repoRelativeDir, ref) {
|
|
39251
39285
|
const baseline = /* @__PURE__ */ new Map();
|
|
@@ -39258,7 +39292,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
39258
39292
|
} catch {
|
|
39259
39293
|
return baseline;
|
|
39260
39294
|
}
|
|
39261
|
-
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path106) => MIGRATION_FILE3.test(
|
|
39295
|
+
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path106) => MIGRATION_FILE3.test(basename27(path106)));
|
|
39262
39296
|
for (const path106 of paths) {
|
|
39263
39297
|
try {
|
|
39264
39298
|
const content = execSync63(`git show "${ref}:${path106}"`, {
|
|
@@ -39266,7 +39300,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
39266
39300
|
maxBuffer: 16 * 1024 * 1024,
|
|
39267
39301
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39268
39302
|
});
|
|
39269
|
-
baseline.set(
|
|
39303
|
+
baseline.set(basename27(path106), content);
|
|
39270
39304
|
} catch {
|
|
39271
39305
|
}
|
|
39272
39306
|
}
|
|
@@ -39480,9 +39514,9 @@ function gitFailureReason(error) {
|
|
|
39480
39514
|
}
|
|
39481
39515
|
|
|
39482
39516
|
// src/commands/watch/resolveUpstream.ts
|
|
39483
|
-
import { execFileSync as
|
|
39517
|
+
import { execFileSync as execFileSync20 } from "child_process";
|
|
39484
39518
|
function runGit3(args, cwd) {
|
|
39485
|
-
return
|
|
39519
|
+
return execFileSync20("git", args, {
|
|
39486
39520
|
encoding: "utf8",
|
|
39487
39521
|
stdio: ["pipe", "pipe", "pipe"],
|
|
39488
39522
|
cwd
|
|
@@ -39520,9 +39554,9 @@ function resolveUpstream(cwd) {
|
|
|
39520
39554
|
}
|
|
39521
39555
|
|
|
39522
39556
|
// src/commands/watch/simulatedDivergencePath.ts
|
|
39523
|
-
import { resolve as
|
|
39557
|
+
import { resolve as resolve25 } from "path";
|
|
39524
39558
|
function simulatedDivergencePath(cwd) {
|
|
39525
|
-
return
|
|
39559
|
+
return resolve25(
|
|
39526
39560
|
cwd ?? process.cwd(),
|
|
39527
39561
|
runGit3(["rev-parse", "--git-path", "assist-simulate-divergence"], cwd)
|
|
39528
39562
|
);
|
|
@@ -39554,12 +39588,12 @@ function decideLap(end, interrupted) {
|
|
|
39554
39588
|
import { spawn as spawn9 } from "child_process";
|
|
39555
39589
|
var WATCH_LAP_ARGS = ["watch", "wait", "--pull", "--build"];
|
|
39556
39590
|
function runWatchLap() {
|
|
39557
|
-
return new Promise((
|
|
39591
|
+
return new Promise((resolve28, reject) => {
|
|
39558
39592
|
const assistFromPath = spawn9("assist", WATCH_LAP_ARGS, {
|
|
39559
39593
|
stdio: "inherit",
|
|
39560
39594
|
shell: process.platform === "win32"
|
|
39561
39595
|
});
|
|
39562
|
-
assistFromPath.on("close", (code, signal) =>
|
|
39596
|
+
assistFromPath.on("close", (code, signal) => resolve28({ code, signal }));
|
|
39563
39597
|
assistFromPath.on("error", reject);
|
|
39564
39598
|
});
|
|
39565
39599
|
}
|
|
@@ -39590,11 +39624,11 @@ function changedPaths(from, cwd) {
|
|
|
39590
39624
|
}
|
|
39591
39625
|
|
|
39592
39626
|
// src/commands/watch/readBuiltVersion.ts
|
|
39593
|
-
import { join as
|
|
39627
|
+
import { join as join94 } from "path";
|
|
39594
39628
|
function readBuiltVersion(cwd) {
|
|
39595
39629
|
try {
|
|
39596
39630
|
const root2 = runGit3(["rev-parse", "--show-toplevel"], cwd);
|
|
39597
|
-
return readPackageJson(
|
|
39631
|
+
return readPackageJson(join94(root2, "package.json")).version ?? "unknown";
|
|
39598
39632
|
} catch {
|
|
39599
39633
|
return "unknown";
|
|
39600
39634
|
}
|
|
@@ -39930,7 +39964,7 @@ function resolveParams(params, cliArgs) {
|
|
|
39930
39964
|
|
|
39931
39965
|
// src/commands/run/resolveRunCwd.ts
|
|
39932
39966
|
import { existsSync as existsSync80 } from "fs";
|
|
39933
|
-
import { resolve as
|
|
39967
|
+
import { resolve as resolve26 } from "path";
|
|
39934
39968
|
var MissingRunCwdError = class extends Error {
|
|
39935
39969
|
constructor(runName, cwd) {
|
|
39936
39970
|
super(`run config "${runName}": cwd ${cwd} does not exist`);
|
|
@@ -39941,7 +39975,7 @@ var MissingRunCwdError = class extends Error {
|
|
|
39941
39975
|
};
|
|
39942
39976
|
function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
|
|
39943
39977
|
if (!config.cwd) return void 0;
|
|
39944
|
-
const cwd =
|
|
39978
|
+
const cwd = resolve26(baseDir, config.cwd);
|
|
39945
39979
|
if (!existsSync80(cwd)) throw new MissingRunCwdError(config.name, cwd);
|
|
39946
39980
|
return cwd;
|
|
39947
39981
|
}
|
|
@@ -40062,12 +40096,12 @@ ${buildWatchReport(from)}`);
|
|
|
40062
40096
|
}
|
|
40063
40097
|
|
|
40064
40098
|
// src/commands/watch/consumeSimulatedDivergence.ts
|
|
40065
|
-
import { existsSync as existsSync81, rmSync as
|
|
40099
|
+
import { existsSync as existsSync81, rmSync as rmSync7 } from "fs";
|
|
40066
40100
|
function consumeSimulatedDivergence(cwd) {
|
|
40067
40101
|
try {
|
|
40068
40102
|
const path106 = simulatedDivergencePath(cwd);
|
|
40069
40103
|
if (!existsSync81(path106)) return false;
|
|
40070
|
-
|
|
40104
|
+
rmSync7(path106);
|
|
40071
40105
|
return true;
|
|
40072
40106
|
} catch {
|
|
40073
40107
|
return false;
|
|
@@ -40075,11 +40109,11 @@ function consumeSimulatedDivergence(cwd) {
|
|
|
40075
40109
|
}
|
|
40076
40110
|
|
|
40077
40111
|
// src/commands/watch/fetchQuietly.ts
|
|
40078
|
-
import { execFileSync as
|
|
40112
|
+
import { execFileSync as execFileSync21 } from "child_process";
|
|
40079
40113
|
var MIN_FETCH_TIMEOUT_MS = 6e4;
|
|
40080
40114
|
function fetchQuietly(cwd, intervalMs) {
|
|
40081
40115
|
try {
|
|
40082
|
-
|
|
40116
|
+
execFileSync21("git", ["fetch", "--quiet"], {
|
|
40083
40117
|
stdio: ["pipe", "pipe", "pipe"],
|
|
40084
40118
|
cwd,
|
|
40085
40119
|
timeout: Math.max(intervalMs, MIN_FETCH_TIMEOUT_MS)
|
|
@@ -40110,7 +40144,7 @@ function readMovement(cwd) {
|
|
|
40110
40144
|
// src/commands/watch/pollForMovement.ts
|
|
40111
40145
|
function pollForMovement(options2) {
|
|
40112
40146
|
const { upstream, intervalMs, timeoutMs, timeout, cwd } = options2;
|
|
40113
|
-
return new Promise((
|
|
40147
|
+
return new Promise((resolve28) => {
|
|
40114
40148
|
let settled = false;
|
|
40115
40149
|
const finish2 = (outcome) => {
|
|
40116
40150
|
if (settled) return;
|
|
@@ -40118,7 +40152,7 @@ function pollForMovement(options2) {
|
|
|
40118
40152
|
clearInterval(ticker);
|
|
40119
40153
|
clearTimeout(deadline);
|
|
40120
40154
|
process.off("SIGINT", onInterrupt);
|
|
40121
|
-
|
|
40155
|
+
resolve28(outcome);
|
|
40122
40156
|
};
|
|
40123
40157
|
const onInterrupt = () => finish2({ kind: "interrupted" });
|
|
40124
40158
|
const ticker = setInterval(() => {
|
|
@@ -40238,7 +40272,7 @@ function extractCode(url, expectedState) {
|
|
|
40238
40272
|
return code;
|
|
40239
40273
|
}
|
|
40240
40274
|
function waitForCallback(port, expectedState) {
|
|
40241
|
-
return new Promise((
|
|
40275
|
+
return new Promise((resolve28, reject) => {
|
|
40242
40276
|
const timeout = setTimeout(() => {
|
|
40243
40277
|
server.close();
|
|
40244
40278
|
reject(new Error("Authorization timed out after 120 seconds"));
|
|
@@ -40255,7 +40289,7 @@ function waitForCallback(port, expectedState) {
|
|
|
40255
40289
|
const code = extractCode(url, expectedState);
|
|
40256
40290
|
respondHtml(res, 200, "Authorization successful!");
|
|
40257
40291
|
server.close();
|
|
40258
|
-
|
|
40292
|
+
resolve28(code);
|
|
40259
40293
|
} catch (error) {
|
|
40260
40294
|
respondHtml(res, 400, error.message);
|
|
40261
40295
|
server.close();
|
|
@@ -40375,9 +40409,9 @@ async function auth() {
|
|
|
40375
40409
|
}
|
|
40376
40410
|
|
|
40377
40411
|
// src/commands/roam/postRoamActivity.ts
|
|
40378
|
-
import { execFileSync as
|
|
40412
|
+
import { execFileSync as execFileSync22 } from "child_process";
|
|
40379
40413
|
import { readdirSync as readdirSync21, readFileSync as readFileSync62, statSync as statSync12 } from "fs";
|
|
40380
|
-
import { join as
|
|
40414
|
+
import { join as join95 } from "path";
|
|
40381
40415
|
function findPortFile(roamDir) {
|
|
40382
40416
|
let entries;
|
|
40383
40417
|
try {
|
|
@@ -40386,7 +40420,7 @@ function findPortFile(roamDir) {
|
|
|
40386
40420
|
return void 0;
|
|
40387
40421
|
}
|
|
40388
40422
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
40389
|
-
const path106 =
|
|
40423
|
+
const path106 = join95(roamDir, name);
|
|
40390
40424
|
try {
|
|
40391
40425
|
return { path: path106, mtimeMs: statSync12(path106).mtimeMs };
|
|
40392
40426
|
} catch {
|
|
@@ -40403,7 +40437,7 @@ var PID_BY_APP = {
|
|
|
40403
40437
|
function postRoamActivity(app, event) {
|
|
40404
40438
|
const appData = process.env.APPDATA;
|
|
40405
40439
|
if (!appData) return;
|
|
40406
|
-
const portFile = findPortFile(
|
|
40440
|
+
const portFile = findPortFile(join95(appData, "Roam"));
|
|
40407
40441
|
if (!portFile) return;
|
|
40408
40442
|
let port;
|
|
40409
40443
|
try {
|
|
@@ -40414,7 +40448,7 @@ function postRoamActivity(app, event) {
|
|
|
40414
40448
|
const pid = PID_BY_APP[app] ?? 99999;
|
|
40415
40449
|
const url = `http://127.0.0.1:${port}/api/v1/activity/${app}/${event}?pid=${pid}`;
|
|
40416
40450
|
try {
|
|
40417
|
-
|
|
40451
|
+
execFileSync22("curl", ["-sf", "--max-time", "0.2", "-X", "POST", url], {
|
|
40418
40452
|
stdio: "ignore"
|
|
40419
40453
|
});
|
|
40420
40454
|
} catch {
|
|
@@ -40539,7 +40573,7 @@ async function run3(name, args) {
|
|
|
40539
40573
|
|
|
40540
40574
|
// src/commands/run/add.ts
|
|
40541
40575
|
import { mkdirSync as mkdirSync33, writeFileSync as writeFileSync53 } from "fs";
|
|
40542
|
-
import { join as
|
|
40576
|
+
import { join as join96 } from "path";
|
|
40543
40577
|
|
|
40544
40578
|
// src/commands/run/extractOption.ts
|
|
40545
40579
|
function extractOption(args, flag) {
|
|
@@ -40600,7 +40634,7 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
40600
40634
|
saveConfig(config);
|
|
40601
40635
|
}
|
|
40602
40636
|
function createCommandFile(name) {
|
|
40603
|
-
const dir =
|
|
40637
|
+
const dir = join96(".claude", "commands");
|
|
40604
40638
|
mkdirSync33(dir, { recursive: true });
|
|
40605
40639
|
const content = `---
|
|
40606
40640
|
description: Run ${name}
|
|
@@ -40608,7 +40642,7 @@ description: Run ${name}
|
|
|
40608
40642
|
|
|
40609
40643
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
40610
40644
|
`;
|
|
40611
|
-
const filePath =
|
|
40645
|
+
const filePath = join96(dir, `${name}.md`);
|
|
40612
40646
|
writeFileSync53(filePath, content);
|
|
40613
40647
|
console.log(`Created command file: ${filePath}`);
|
|
40614
40648
|
}
|
|
@@ -40665,7 +40699,7 @@ function link2() {
|
|
|
40665
40699
|
|
|
40666
40700
|
// src/commands/run/remove.ts
|
|
40667
40701
|
import { existsSync as existsSync82, unlinkSync as unlinkSync21 } from "fs";
|
|
40668
|
-
import { join as
|
|
40702
|
+
import { join as join97 } from "path";
|
|
40669
40703
|
function findRemoveIndex() {
|
|
40670
40704
|
const idx = process.argv.indexOf("remove");
|
|
40671
40705
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -40680,7 +40714,7 @@ function parseRemoveName() {
|
|
|
40680
40714
|
return process.argv[idx + 1];
|
|
40681
40715
|
}
|
|
40682
40716
|
function deleteCommandFile(name) {
|
|
40683
|
-
const filePath =
|
|
40717
|
+
const filePath = join97(".claude", "commands", `${name}.md`);
|
|
40684
40718
|
if (existsSync82(filePath)) {
|
|
40685
40719
|
unlinkSync21(filePath);
|
|
40686
40720
|
console.log(`Deleted command file: ${filePath}`);
|
|
@@ -40741,11 +40775,11 @@ function formatLink(link3) {
|
|
|
40741
40775
|
}
|
|
40742
40776
|
|
|
40743
40777
|
// src/commands/sessions/daemon/listDaemonPids.ts
|
|
40744
|
-
import { execFileSync as
|
|
40778
|
+
import { execFileSync as execFileSync23 } from "child_process";
|
|
40745
40779
|
function listDaemonPids() {
|
|
40746
40780
|
if (process.platform === "win32") return [];
|
|
40747
40781
|
try {
|
|
40748
|
-
const out =
|
|
40782
|
+
const out = execFileSync23("ps", ["-eo", "pid=,args="], {
|
|
40749
40783
|
encoding: "utf8"
|
|
40750
40784
|
});
|
|
40751
40785
|
return out.split("\n").filter((line) => line.includes("assist") && / daemon run\b/.test(line)).map((line) => Number.parseInt(line.trim(), 10)).filter((pid) => Number.isInteger(pid));
|
|
@@ -40760,10 +40794,10 @@ var STATUS_TIMEOUT_MS2 = 5e3;
|
|
|
40760
40794
|
function queryDaemon(socket) {
|
|
40761
40795
|
socket.write(`${JSON.stringify({ type: "ping" })}
|
|
40762
40796
|
`);
|
|
40763
|
-
return new Promise((
|
|
40797
|
+
return new Promise((resolve28) => {
|
|
40764
40798
|
const result = { sessions: [] };
|
|
40765
40799
|
const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
|
|
40766
|
-
const timer = setTimeout(() =>
|
|
40800
|
+
const timer = setTimeout(() => resolve28(result), STATUS_TIMEOUT_MS2);
|
|
40767
40801
|
const lines2 = createInterface8({ input: socket });
|
|
40768
40802
|
lines2.on("error", () => {
|
|
40769
40803
|
});
|
|
@@ -40771,7 +40805,7 @@ function queryDaemon(socket) {
|
|
|
40771
40805
|
applyLine(result, pending, line);
|
|
40772
40806
|
if (pending.size === 0) {
|
|
40773
40807
|
clearTimeout(timer);
|
|
40774
|
-
|
|
40808
|
+
resolve28(result);
|
|
40775
40809
|
}
|
|
40776
40810
|
});
|
|
40777
40811
|
});
|
|
@@ -40871,11 +40905,11 @@ function clearPersistedSessionsOnDrain() {
|
|
|
40871
40905
|
|
|
40872
40906
|
// src/commands/sessions/daemon/readDaemonMessage.ts
|
|
40873
40907
|
function readDaemonMessage(lines2, timeoutMs, fallback, match) {
|
|
40874
|
-
return new Promise((
|
|
40908
|
+
return new Promise((resolve28) => {
|
|
40875
40909
|
const finish2 = (value) => {
|
|
40876
40910
|
clearTimeout(timer);
|
|
40877
40911
|
lines2.off("line", onLine);
|
|
40878
|
-
|
|
40912
|
+
resolve28(value);
|
|
40879
40913
|
};
|
|
40880
40914
|
const timer = setTimeout(() => finish2(fallback), timeoutMs);
|
|
40881
40915
|
const onLine = (line) => {
|
|
@@ -41691,16 +41725,16 @@ function setStatus2(session, newStatus) {
|
|
|
41691
41725
|
|
|
41692
41726
|
// src/commands/sessions/daemon/worktree/reapWorktree.ts
|
|
41693
41727
|
import { existsSync as existsSync87 } from "fs";
|
|
41694
|
-
import { basename as
|
|
41728
|
+
import { basename as basename28 } from "path";
|
|
41695
41729
|
|
|
41696
41730
|
// src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
|
|
41697
41731
|
import { existsSync as existsSync86 } from "fs";
|
|
41698
|
-
import { join as
|
|
41732
|
+
import { join as join100 } from "path";
|
|
41699
41733
|
|
|
41700
41734
|
// src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
|
|
41701
41735
|
import { statSync as statSync14 } from "fs";
|
|
41702
|
-
import { rm as
|
|
41703
|
-
import { join as
|
|
41736
|
+
import { rm as rm3 } from "fs/promises";
|
|
41737
|
+
import { join as join99 } from "path";
|
|
41704
41738
|
async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
41705
41739
|
if (holdsAGitDirectoryRatherThanALink(worktreePath)) {
|
|
41706
41740
|
const refusal = "it is a clone of its own, not a linked worktree";
|
|
@@ -41711,7 +41745,7 @@ async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
|
41711
41745
|
}
|
|
41712
41746
|
daemonLog(`worktree ${worktreePath} deleting its directory directly: ${why}`);
|
|
41713
41747
|
try {
|
|
41714
|
-
await
|
|
41748
|
+
await rm3(worktreePath, {
|
|
41715
41749
|
recursive: true,
|
|
41716
41750
|
force: true,
|
|
41717
41751
|
maxRetries: 3,
|
|
@@ -41728,7 +41762,7 @@ async function deleteTreeDirectly(clone, worktreePath, why) {
|
|
|
41728
41762
|
return { removed: true };
|
|
41729
41763
|
}
|
|
41730
41764
|
function holdsAGitDirectoryRatherThanALink(worktreePath) {
|
|
41731
|
-
return statSync14(
|
|
41765
|
+
return statSync14(join99(worktreePath, ".git"), {
|
|
41732
41766
|
throwIfNoEntry: false
|
|
41733
41767
|
})?.isDirectory() === true;
|
|
41734
41768
|
}
|
|
@@ -41764,7 +41798,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
|
|
|
41764
41798
|
);
|
|
41765
41799
|
}
|
|
41766
41800
|
function strandedReason(worktreePath, cause) {
|
|
41767
|
-
if (!existsSync86(
|
|
41801
|
+
if (!existsSync86(join100(worktreePath, ".git")))
|
|
41768
41802
|
return "its .git link is already gone";
|
|
41769
41803
|
if (/not a working tree|not a git repository/i.test(reason2(cause)))
|
|
41770
41804
|
return "git no longer recognises it as a working tree";
|
|
@@ -41834,7 +41868,7 @@ async function reapWorktree(worktreePath, force = false) {
|
|
|
41834
41868
|
const clone = owningClone(worktreePath);
|
|
41835
41869
|
const removal = await removeTree(clone, worktreePath, force);
|
|
41836
41870
|
if (!removal.removed) return removal;
|
|
41837
|
-
await deleteWorktreeBranch(clone,
|
|
41871
|
+
await deleteWorktreeBranch(clone, basename28(worktreePath));
|
|
41838
41872
|
forgetWorktree(worktreePath);
|
|
41839
41873
|
daemonLog(`worktree ${worktreePath} reaped${force ? " (forced)" : ""}`);
|
|
41840
41874
|
return removal;
|
|
@@ -42008,7 +42042,7 @@ function closeGateApplies(sessions, session) {
|
|
|
42008
42042
|
|
|
42009
42043
|
// src/commands/sessions/daemon/worktree/liveProcessesInTree.ts
|
|
42010
42044
|
import { readdirSync as readdirSync22, readlinkSync } from "fs";
|
|
42011
|
-
import { sep as
|
|
42045
|
+
import { sep as sep4 } from "path";
|
|
42012
42046
|
function liveProcessesInTree(treePath, procRoot = "/proc") {
|
|
42013
42047
|
let entries;
|
|
42014
42048
|
try {
|
|
@@ -42021,7 +42055,7 @@ function liveProcessesInTree(treePath, procRoot = "/proc") {
|
|
|
42021
42055
|
const pid = Number(entry);
|
|
42022
42056
|
if (!Number.isInteger(pid) || pid === process.pid) continue;
|
|
42023
42057
|
const cwd = processCwd(`${procRoot}/${entry}/cwd`);
|
|
42024
|
-
if (cwd && (cwd === treePath || cwd.startsWith(treePath +
|
|
42058
|
+
if (cwd && (cwd === treePath || cwd.startsWith(treePath + sep4)))
|
|
42025
42059
|
pids.push(pid);
|
|
42026
42060
|
}
|
|
42027
42061
|
return pids;
|
|
@@ -42038,12 +42072,12 @@ function processCwd(link3) {
|
|
|
42038
42072
|
var POLL_MS = 500;
|
|
42039
42073
|
var GRACE_MS = 5e3;
|
|
42040
42074
|
function awaitTreeVacated(session, treePath) {
|
|
42041
|
-
return new Promise((
|
|
42075
|
+
return new Promise((resolve28) => {
|
|
42042
42076
|
let ticks = GRACE_MS / POLL_MS;
|
|
42043
42077
|
const settle = (outcome) => {
|
|
42044
42078
|
clearTimeout(timer);
|
|
42045
42079
|
session.closeGrace = void 0;
|
|
42046
|
-
|
|
42080
|
+
resolve28(outcome);
|
|
42047
42081
|
};
|
|
42048
42082
|
const tick = () => {
|
|
42049
42083
|
if (liveProcessesInTree(treePath).length === 0) settle("vacated");
|
|
@@ -42209,26 +42243,29 @@ function dismissSessionGated(sessions, id, notify2, discard = false) {
|
|
|
42209
42243
|
|
|
42210
42244
|
// src/commands/sessions/daemon/worktree/resumeWatcherAfterEscalation.ts
|
|
42211
42245
|
var ENDED = ["done", "error"];
|
|
42246
|
+
var endedViaDismissOrExit = /* @__PURE__ */ new WeakSet();
|
|
42212
42247
|
function resumeWatcherAfterEscalation(sessions, escalation, restart) {
|
|
42213
42248
|
if (escalation.divergenceEscalation !== true || !escalation.cwd) return;
|
|
42249
|
+
if (endedViaDismissOrExit.has(escalation)) return;
|
|
42250
|
+
endedViaDismissOrExit.add(escalation);
|
|
42214
42251
|
const clone = canonicalTreePath(escalation.cwd);
|
|
42215
42252
|
const watcher = [...sessions.values()].find(
|
|
42216
42253
|
(s) => s.watcher === true && s.cwd !== void 0 && canonicalTreePath(s.cwd) === clone
|
|
42217
42254
|
);
|
|
42218
42255
|
if (!watcher) {
|
|
42219
42256
|
daemonLog(
|
|
42220
|
-
`escalation session ${escalation.id} ended
|
|
42257
|
+
`escalation session ${escalation.id} ended: no watcher left in the clone ${clone} to restart`
|
|
42221
42258
|
);
|
|
42222
42259
|
return;
|
|
42223
42260
|
}
|
|
42224
42261
|
if (!ENDED.includes(watcher.status)) {
|
|
42225
42262
|
daemonLog(
|
|
42226
|
-
`escalation session ${escalation.id} ended
|
|
42263
|
+
`escalation session ${escalation.id} ended: watcher session ${watcher.id} in the clone ${clone} is already ${watcher.status}`
|
|
42227
42264
|
);
|
|
42228
42265
|
return;
|
|
42229
42266
|
}
|
|
42230
42267
|
daemonLog(
|
|
42231
|
-
`escalation session ${escalation.id} ended
|
|
42268
|
+
`escalation session ${escalation.id} ended: restarting watcher session ${watcher.id} in the clone ${clone}`
|
|
42232
42269
|
);
|
|
42233
42270
|
restart(watcher.id);
|
|
42234
42271
|
}
|
|
@@ -42579,13 +42616,13 @@ function isBacklogItemId(text17) {
|
|
|
42579
42616
|
}
|
|
42580
42617
|
|
|
42581
42618
|
// src/commands/sessions/daemon/generateSessionTitle.ts
|
|
42582
|
-
import { execFile as
|
|
42583
|
-
import { promisify as
|
|
42584
|
-
var
|
|
42619
|
+
import { execFile as execFile12 } from "child_process";
|
|
42620
|
+
import { promisify as promisify11 } from "util";
|
|
42621
|
+
var execFileAsync10 = promisify11(execFile12);
|
|
42585
42622
|
var SESSION_TITLE_MAX_LENGTH = 48;
|
|
42586
42623
|
async function generateSessionTitle(prompt) {
|
|
42587
42624
|
try {
|
|
42588
|
-
const { stdout } = await
|
|
42625
|
+
const { stdout } = await execFileAsync10(
|
|
42589
42626
|
"claude",
|
|
42590
42627
|
["-p", "--model", "haiku", buildPrompt5(prompt)],
|
|
42591
42628
|
{ encoding: "utf8", windowsHide: true, timeout: 3e4 }
|
|
@@ -42665,7 +42702,7 @@ function emitSessionOutput(session, clients, data) {
|
|
|
42665
42702
|
|
|
42666
42703
|
// src/commands/sessions/daemon/exitReason.ts
|
|
42667
42704
|
import { existsSync as existsSync89 } from "fs";
|
|
42668
|
-
import { resolve as
|
|
42705
|
+
import { resolve as resolve27 } from "path";
|
|
42669
42706
|
function exitDetail(session) {
|
|
42670
42707
|
if (session.cwd && !existsSync89(session.cwd))
|
|
42671
42708
|
return `working directory ${session.cwd} no longer exists`;
|
|
@@ -42680,7 +42717,7 @@ function missingRunConfigCwd(session) {
|
|
|
42680
42717
|
const dir = session.cwd ?? process.cwd();
|
|
42681
42718
|
const config = resolveRunConfig(session.runName, dir);
|
|
42682
42719
|
if (!config?.cwd) return void 0;
|
|
42683
|
-
const configured =
|
|
42720
|
+
const configured = resolve27(runConfigBaseDirFrom(dir), config.cwd);
|
|
42684
42721
|
if (existsSync89(configured)) return void 0;
|
|
42685
42722
|
return `run config "${config.name}": cwd ${configured} does not exist`;
|
|
42686
42723
|
}
|
|
@@ -42730,7 +42767,7 @@ function handleRefusedRun(session, exitCode, onStatusChange) {
|
|
|
42730
42767
|
|
|
42731
42768
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
42732
42769
|
import { existsSync as existsSync90, mkdirSync as mkdirSync34, watch as watch2 } from "fs";
|
|
42733
|
-
import { dirname as
|
|
42770
|
+
import { dirname as dirname42 } from "path";
|
|
42734
42771
|
|
|
42735
42772
|
// src/commands/sessions/daemon/applyActivityToSession.ts
|
|
42736
42773
|
function applyActivityToSession(session, activity2) {
|
|
@@ -42792,7 +42829,7 @@ var DEBOUNCE_MS2 = 50;
|
|
|
42792
42829
|
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
42793
42830
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
42794
42831
|
const path106 = activityPath(session.id);
|
|
42795
|
-
const dir =
|
|
42832
|
+
const dir = dirname42(path106);
|
|
42796
42833
|
try {
|
|
42797
42834
|
mkdirSync34(dir, { recursive: true });
|
|
42798
42835
|
} catch {
|
|
@@ -44143,6 +44180,7 @@ function reuseSessionForRun(session, itemId2, clients, onStatusChange, tree) {
|
|
|
44143
44180
|
}
|
|
44144
44181
|
|
|
44145
44182
|
// src/commands/sessions/daemon/respawnSession.ts
|
|
44183
|
+
var WATCHER_RESTART_MARK = "\r\n\x1B[2m\u2500\u2500 watcher restarted \u2500\u2500\x1B[0m\r\n";
|
|
44146
44184
|
function respawnSession(session, respawn, status2, clients, onStatusChange) {
|
|
44147
44185
|
session.gitWatcher?.close();
|
|
44148
44186
|
session.gitWatcher = void 0;
|
|
@@ -44150,7 +44188,8 @@ function respawnSession(session, respawn, status2, clients, onStatusChange) {
|
|
|
44150
44188
|
session.pendingDismiss = void 0;
|
|
44151
44189
|
session.closeGrace?.cancel();
|
|
44152
44190
|
session.closing = void 0;
|
|
44153
|
-
session.
|
|
44191
|
+
const keepHistory = session.watcher === true;
|
|
44192
|
+
if (!keepHistory) session.scrollback = "";
|
|
44154
44193
|
session.startedAt = Date.now();
|
|
44155
44194
|
session.runningMs = 0;
|
|
44156
44195
|
session.runningSince = null;
|
|
@@ -44167,7 +44206,8 @@ function respawnSession(session, respawn, status2, clients, onStatusChange) {
|
|
|
44167
44206
|
session.pty?.resize(session.cols, session.rows);
|
|
44168
44207
|
} catch {
|
|
44169
44208
|
}
|
|
44170
|
-
|
|
44209
|
+
if (keepHistory) emitSessionOutput(session, clients, WATCHER_RESTART_MARK);
|
|
44210
|
+
else broadcast(clients, { type: "clear", sessionId: session.id });
|
|
44171
44211
|
wirePtyEvents(session, clients, onStatusChange);
|
|
44172
44212
|
}
|
|
44173
44213
|
|
|
@@ -44550,10 +44590,10 @@ function deferralNotice(persisted, cap2) {
|
|
|
44550
44590
|
|
|
44551
44591
|
// src/commands/sessions/daemon/worktree/underTempRoot.ts
|
|
44552
44592
|
import { realpathSync as realpathSync3 } from "fs";
|
|
44553
|
-
import { tmpdir as
|
|
44554
|
-
import { sep as
|
|
44593
|
+
import { tmpdir as tmpdir9 } from "os";
|
|
44594
|
+
import { sep as sep5 } from "path";
|
|
44555
44595
|
function tempRoots() {
|
|
44556
|
-
const raw =
|
|
44596
|
+
const raw = tmpdir9();
|
|
44557
44597
|
const roots = /* @__PURE__ */ new Set([raw]);
|
|
44558
44598
|
try {
|
|
44559
44599
|
roots.add(realpathSync3(raw));
|
|
@@ -44564,7 +44604,7 @@ function tempRoots() {
|
|
|
44564
44604
|
}
|
|
44565
44605
|
function underTempRoot(path106) {
|
|
44566
44606
|
return tempRoots().some(
|
|
44567
|
-
(root2) => path106.startsWith(root2.endsWith(
|
|
44607
|
+
(root2) => path106.startsWith(root2.endsWith(sep5) ? root2 : root2 + sep5)
|
|
44568
44608
|
);
|
|
44569
44609
|
}
|
|
44570
44610
|
|
|
@@ -45045,7 +45085,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
45045
45085
|
|
|
45046
45086
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
45047
45087
|
import { existsSync as existsSync93 } from "fs";
|
|
45048
|
-
import { basename as
|
|
45088
|
+
import { basename as basename30 } from "path";
|
|
45049
45089
|
|
|
45050
45090
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
45051
45091
|
function accountedTrees(sessions) {
|
|
@@ -45153,7 +45193,7 @@ function capped2(lines2) {
|
|
|
45153
45193
|
}
|
|
45154
45194
|
|
|
45155
45195
|
// src/commands/sessions/daemon/worktree/resurfaceOrphanedWorktree.ts
|
|
45156
|
-
import { basename as
|
|
45196
|
+
import { basename as basename29 } from "path";
|
|
45157
45197
|
function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
|
|
45158
45198
|
const { orphan, reason: reason4, held } = recovered;
|
|
45159
45199
|
let id;
|
|
@@ -45176,7 +45216,7 @@ function orphanedSession(id, recovered) {
|
|
|
45176
45216
|
const { orphan, reason: reason4, held } = recovered;
|
|
45177
45217
|
return {
|
|
45178
45218
|
...sessionBase(id, "stopped"),
|
|
45179
|
-
name: `recovered ${
|
|
45219
|
+
name: `recovered ${basename29(orphan.path)}`,
|
|
45180
45220
|
subtitle: `${held.summary} in ${orphan.path}`,
|
|
45181
45221
|
commandType: "claude",
|
|
45182
45222
|
pty: null,
|
|
@@ -45237,7 +45277,7 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
|
45237
45277
|
logVanishedTree(sessions, path106);
|
|
45238
45278
|
vanished.set(clone, [
|
|
45239
45279
|
...vanished.get(clone) ?? [],
|
|
45240
|
-
{ path: path106, branch:
|
|
45280
|
+
{ path: path106, branch: basename30(path106) }
|
|
45241
45281
|
]);
|
|
45242
45282
|
continue;
|
|
45243
45283
|
}
|
|
@@ -45649,7 +45689,7 @@ function failPendingCreators(state, message3) {
|
|
|
45649
45689
|
}
|
|
45650
45690
|
function resetRelayState(state, reason4) {
|
|
45651
45691
|
failPendingCreators(state, reason4);
|
|
45652
|
-
for (const
|
|
45692
|
+
for (const resolve28 of state.historyWaiters) resolve28([]);
|
|
45653
45693
|
state.historyWaiters = [];
|
|
45654
45694
|
state.sessions = [];
|
|
45655
45695
|
state.lastSnapshot = void 0;
|
|
@@ -46090,16 +46130,16 @@ var HISTORY_TIMEOUT_MS = 5e3;
|
|
|
46090
46130
|
function requestLinkHistory(ctx) {
|
|
46091
46131
|
if (!ctx.greeted) return Promise.resolve([]);
|
|
46092
46132
|
const waiters = ctx.relay.historyWaiters;
|
|
46093
|
-
return new Promise((
|
|
46133
|
+
return new Promise((resolve28) => {
|
|
46094
46134
|
const settle = (sessions) => {
|
|
46095
46135
|
clearTimeout(timer);
|
|
46096
|
-
|
|
46136
|
+
resolve28(sessions);
|
|
46097
46137
|
};
|
|
46098
46138
|
const timer = setTimeout(() => {
|
|
46099
46139
|
const index2 = waiters.indexOf(settle);
|
|
46100
46140
|
if (index2 !== -1) waiters.splice(index2, 1);
|
|
46101
46141
|
daemonLog(`link ${ctx.spec.name} ws: history timed out`);
|
|
46102
|
-
|
|
46142
|
+
resolve28(ctx.relay.lastHistory ?? []);
|
|
46103
46143
|
}, HISTORY_TIMEOUT_MS);
|
|
46104
46144
|
timer.unref?.();
|
|
46105
46145
|
waiters.push(settle);
|
|
@@ -46358,7 +46398,7 @@ import { existsSync as existsSync95 } from "fs";
|
|
|
46358
46398
|
|
|
46359
46399
|
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
46360
46400
|
import { copyFileSync as copyFileSync5, existsSync as existsSync94, mkdirSync as mkdirSync36 } from "fs";
|
|
46361
|
-
import { join as
|
|
46401
|
+
import { join as join102 } from "path";
|
|
46362
46402
|
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
46363
46403
|
const dir = projectDirForCwd(toCwd);
|
|
46364
46404
|
if (dir === projectDirForCwd(fromCwd)) {
|
|
@@ -46367,7 +46407,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
46367
46407
|
);
|
|
46368
46408
|
return;
|
|
46369
46409
|
}
|
|
46370
|
-
const dest =
|
|
46410
|
+
const dest = join102(dir, `${claudeSessionId}.jsonl`);
|
|
46371
46411
|
if (existsSync94(dest)) {
|
|
46372
46412
|
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
46373
46413
|
return;
|
|
@@ -47811,7 +47851,7 @@ function summaryPathFor(jsonlPath2) {
|
|
|
47811
47851
|
}
|
|
47812
47852
|
|
|
47813
47853
|
// src/commands/sessions/summarise/summariseSession.ts
|
|
47814
|
-
import { execFileSync as
|
|
47854
|
+
import { execFileSync as execFileSync24 } from "child_process";
|
|
47815
47855
|
function summariseSession(jsonlPath2) {
|
|
47816
47856
|
const firstMessage = extractFirstUserMessage(jsonlPath2);
|
|
47817
47857
|
const backlogIds = scanSessionBacklogRefs(jsonlPath2);
|
|
@@ -47820,7 +47860,7 @@ function summariseSession(jsonlPath2) {
|
|
|
47820
47860
|
}
|
|
47821
47861
|
const prompt = buildPrompt6(firstMessage, backlogIds);
|
|
47822
47862
|
try {
|
|
47823
|
-
const output =
|
|
47863
|
+
const output = execFileSync24("claude", ["-p", "--model", "haiku", prompt], {
|
|
47824
47864
|
encoding: "utf8",
|
|
47825
47865
|
timeout: 3e4,
|
|
47826
47866
|
stdio: ["ignore", "pipe", "ignore"]
|