@staff0rd/assist 0.428.1 → 0.429.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/commands/sessions/web/bundle.js +388 -388
- package/dist/index.js +299 -152
- 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.429.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -9291,6 +9291,132 @@ async function restartWeb(req, res, deps2 = {}) {
|
|
|
9291
9291
|
}
|
|
9292
9292
|
}
|
|
9293
9293
|
|
|
9294
|
+
// src/commands/sessions/web/uploadPrImage.ts
|
|
9295
|
+
import { rm } from "fs/promises";
|
|
9296
|
+
|
|
9297
|
+
// src/commands/sessions/web/runGhImage.ts
|
|
9298
|
+
import { execFile as execFile6 } from "child_process";
|
|
9299
|
+
import { promisify as promisify7 } from "util";
|
|
9300
|
+
var execFileAsync6 = promisify7(execFile6);
|
|
9301
|
+
var GhImageUnavailableError = class extends Error {
|
|
9302
|
+
name = "GhImageUnavailableError";
|
|
9303
|
+
};
|
|
9304
|
+
var GH_IMAGE_INSTALL_COMMAND = "gh extension install drogers0/gh-image";
|
|
9305
|
+
var INSTALL_HINT = `Install the gh-image extension: ${GH_IMAGE_INSTALL_COMMAND}`;
|
|
9306
|
+
async function runGhImage(filePath, cwd) {
|
|
9307
|
+
let stdout;
|
|
9308
|
+
try {
|
|
9309
|
+
({ stdout } = await execFileAsync6("gh", ["image", filePath], {
|
|
9310
|
+
cwd,
|
|
9311
|
+
maxBuffer: 10 * 1024 * 1024
|
|
9312
|
+
}));
|
|
9313
|
+
} catch (error) {
|
|
9314
|
+
const err = error;
|
|
9315
|
+
if (err.code === "ENOENT")
|
|
9316
|
+
throw new GhImageUnavailableError(
|
|
9317
|
+
`The GitHub CLI (\`gh\`) is not installed. ${INSTALL_HINT}`
|
|
9318
|
+
);
|
|
9319
|
+
const stderr = err.stderr ?? "";
|
|
9320
|
+
if (/unknown command "image"/i.test(stderr) || /extension.*not found/i.test(stderr))
|
|
9321
|
+
throw new GhImageUnavailableError(
|
|
9322
|
+
`The \`gh-image\` extension is not installed. ${INSTALL_HINT}`
|
|
9323
|
+
);
|
|
9324
|
+
throw new Error(
|
|
9325
|
+
`gh image failed: ${stderr.trim() || err.message || "unknown error"}`
|
|
9326
|
+
);
|
|
9327
|
+
}
|
|
9328
|
+
const lines = stdout.split("\n").map((line) => line.trim()).filter(Boolean);
|
|
9329
|
+
const markdown = lines.find((line) => /^!\[.*]\(.+\)$/.test(line)) ?? lines.find((line) => line.includes("http")) ?? lines[0];
|
|
9330
|
+
if (!markdown) throw new Error("gh image produced no output");
|
|
9331
|
+
return markdown;
|
|
9332
|
+
}
|
|
9333
|
+
|
|
9334
|
+
// src/commands/sessions/web/readRequestBuffer.ts
|
|
9335
|
+
async function readRequestBuffer(req, limit) {
|
|
9336
|
+
const chunks = [];
|
|
9337
|
+
let size = 0;
|
|
9338
|
+
for await (const chunk of req) {
|
|
9339
|
+
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
9340
|
+
size += buf.length;
|
|
9341
|
+
if (size > limit) {
|
|
9342
|
+
req.destroy();
|
|
9343
|
+
return null;
|
|
9344
|
+
}
|
|
9345
|
+
chunks.push(buf);
|
|
9346
|
+
}
|
|
9347
|
+
return Buffer.concat(chunks);
|
|
9348
|
+
}
|
|
9349
|
+
|
|
9350
|
+
// src/commands/sessions/web/writeTempImage.ts
|
|
9351
|
+
import { mkdtemp, writeFile as writeFile2 } from "fs/promises";
|
|
9352
|
+
import { tmpdir } from "os";
|
|
9353
|
+
import { extname, join as join28 } from "path";
|
|
9354
|
+
var EXT_BY_MIME = {
|
|
9355
|
+
"image/png": "png",
|
|
9356
|
+
"image/jpeg": "jpg",
|
|
9357
|
+
"image/gif": "gif",
|
|
9358
|
+
"image/webp": "webp",
|
|
9359
|
+
"image/svg+xml": "svg",
|
|
9360
|
+
"image/bmp": "bmp",
|
|
9361
|
+
"image/avif": "avif"
|
|
9362
|
+
};
|
|
9363
|
+
function pickExtension(name, contentType) {
|
|
9364
|
+
const fromName = extname(name).replace(/^\./, "").toLowerCase();
|
|
9365
|
+
if (fromName) return fromName;
|
|
9366
|
+
return EXT_BY_MIME[contentType.split(";")[0].trim().toLowerCase()] ?? "png";
|
|
9367
|
+
}
|
|
9368
|
+
function safeBaseName(name) {
|
|
9369
|
+
const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]+/g, "-");
|
|
9370
|
+
return base.replace(/^-+|-+$/g, "").slice(0, 60) || "screenshot";
|
|
9371
|
+
}
|
|
9372
|
+
async function writeTempImage(name, contentType, body) {
|
|
9373
|
+
const dir = await mkdtemp(join28(tmpdir(), "assist-pr-img-"));
|
|
9374
|
+
const filePath = join28(
|
|
9375
|
+
dir,
|
|
9376
|
+
`${safeBaseName(name)}.${pickExtension(name, contentType)}`
|
|
9377
|
+
);
|
|
9378
|
+
await writeFile2(filePath, body);
|
|
9379
|
+
return { dir, filePath };
|
|
9380
|
+
}
|
|
9381
|
+
|
|
9382
|
+
// src/commands/sessions/web/uploadPrImage.ts
|
|
9383
|
+
var MAX_BYTES = 25 * 1024 * 1024;
|
|
9384
|
+
async function uploadPrImage(req, res) {
|
|
9385
|
+
const cwd = getCwdParam(req, res);
|
|
9386
|
+
if (!cwd) return;
|
|
9387
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
9388
|
+
const name = url.searchParams.get("name") ?? "";
|
|
9389
|
+
const contentType = req.headers["content-type"] ?? "";
|
|
9390
|
+
const body = await readRequestBuffer(req, MAX_BYTES);
|
|
9391
|
+
if (!body) {
|
|
9392
|
+
respondJson(res, 413, { error: "Image too large (max 25MB)." });
|
|
9393
|
+
return;
|
|
9394
|
+
}
|
|
9395
|
+
if (body.length === 0) {
|
|
9396
|
+
respondJson(res, 400, { error: "Empty upload." });
|
|
9397
|
+
return;
|
|
9398
|
+
}
|
|
9399
|
+
const { dir, filePath } = await writeTempImage(name, contentType, body);
|
|
9400
|
+
try {
|
|
9401
|
+
const markdown = await runGhImage(filePath, cwd);
|
|
9402
|
+
respondJson(res, 200, { markdown });
|
|
9403
|
+
} catch (error) {
|
|
9404
|
+
if (error instanceof GhImageUnavailableError) {
|
|
9405
|
+
respondJson(res, 501, {
|
|
9406
|
+
error: error.message,
|
|
9407
|
+
command: GH_IMAGE_INSTALL_COMMAND
|
|
9408
|
+
});
|
|
9409
|
+
} else {
|
|
9410
|
+
respondJson(res, 500, {
|
|
9411
|
+
error: error instanceof Error ? error.message : "Upload failed"
|
|
9412
|
+
});
|
|
9413
|
+
}
|
|
9414
|
+
} finally {
|
|
9415
|
+
await rm(dir, { recursive: true, force: true }).catch(() => {
|
|
9416
|
+
});
|
|
9417
|
+
}
|
|
9418
|
+
}
|
|
9419
|
+
|
|
9294
9420
|
// src/commands/sessions/web/createCssHandler.ts
|
|
9295
9421
|
import { createHash as createHash2 } from "crypto";
|
|
9296
9422
|
import { readFileSync as readFileSync21 } from "fs";
|
|
@@ -9333,6 +9459,7 @@ var routes2 = {
|
|
|
9333
9459
|
"GET /api/items": listItems,
|
|
9334
9460
|
"GET /api/backlog/summary": getBacklogSummary,
|
|
9335
9461
|
"POST /api/open-in-code": openInCode,
|
|
9462
|
+
"POST /api/pr-preview/upload-image": uploadPrImage,
|
|
9336
9463
|
"POST /api/restart": restartWeb,
|
|
9337
9464
|
"GET /api/github-url": githubUrl,
|
|
9338
9465
|
"GET /api/git-status": gitStatus,
|
|
@@ -10390,8 +10517,8 @@ function ensureRemoteOrigin() {
|
|
|
10390
10517
|
// src/commands/backlog/add/shared.ts
|
|
10391
10518
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
10392
10519
|
import { mkdtempSync, readFileSync as readFileSync22, unlinkSync as unlinkSync6, writeFileSync as writeFileSync21 } from "fs";
|
|
10393
|
-
import { tmpdir } from "os";
|
|
10394
|
-
import { join as
|
|
10520
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
10521
|
+
import { join as join29 } from "path";
|
|
10395
10522
|
import enquirer6 from "enquirer";
|
|
10396
10523
|
async function promptType() {
|
|
10397
10524
|
const { type } = await enquirer6.prompt({
|
|
@@ -10431,8 +10558,8 @@ async function promptDescription() {
|
|
|
10431
10558
|
}
|
|
10432
10559
|
function openEditor() {
|
|
10433
10560
|
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
10434
|
-
const dir = mkdtempSync(
|
|
10435
|
-
const filePath =
|
|
10561
|
+
const dir = mkdtempSync(join29(tmpdir2(), "assist-"));
|
|
10562
|
+
const filePath = join29(dir, "description.md");
|
|
10436
10563
|
writeFileSync21(filePath, "");
|
|
10437
10564
|
const result = spawnSync3(editor, [filePath], { stdio: "inherit" });
|
|
10438
10565
|
if (result.status !== 0) {
|
|
@@ -12065,7 +12192,7 @@ import { basename as basename7 } from "path";
|
|
|
12065
12192
|
import { parse } from "shell-quote";
|
|
12066
12193
|
|
|
12067
12194
|
// src/shared/consumeRedirect.ts
|
|
12068
|
-
import { tmpdir as
|
|
12195
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
12069
12196
|
|
|
12070
12197
|
// src/shared/isRedirectTargetAllowed.ts
|
|
12071
12198
|
function isRedirectTargetAllowed(target, tmp) {
|
|
@@ -12093,7 +12220,7 @@ function consumeRedirect(tokens, opIndex, current) {
|
|
|
12093
12220
|
if (typeof target !== "string") {
|
|
12094
12221
|
return { ok: false, error: "unable to parse" };
|
|
12095
12222
|
}
|
|
12096
|
-
if (!isRedirectTargetAllowed(target,
|
|
12223
|
+
if (!isRedirectTargetAllowed(target, tmpdir3())) {
|
|
12097
12224
|
return {
|
|
12098
12225
|
ok: false,
|
|
12099
12226
|
error: `redirect target '${target}' is outside the OS temp directory`
|
|
@@ -12384,12 +12511,12 @@ function findCliWrite(command) {
|
|
|
12384
12511
|
// src/shared/readSettingsPerms.ts
|
|
12385
12512
|
import { existsSync as existsSync30, readFileSync as readFileSync24 } from "fs";
|
|
12386
12513
|
import { homedir as homedir14 } from "os";
|
|
12387
|
-
import { join as
|
|
12514
|
+
import { join as join30 } from "path";
|
|
12388
12515
|
function readSettingsPerms(key) {
|
|
12389
12516
|
const paths = [
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
|
|
12517
|
+
join30(homedir14(), ".claude", "settings.json"),
|
|
12518
|
+
join30(process.cwd(), ".claude", "settings.json"),
|
|
12519
|
+
join30(process.cwd(), ".claude", "settings.local.json")
|
|
12393
12520
|
];
|
|
12394
12521
|
const entries = [];
|
|
12395
12522
|
for (const p of paths) {
|
|
@@ -12591,11 +12718,11 @@ function decideCommand(toolName, rawCommand) {
|
|
|
12591
12718
|
// src/commands/cliHook/logDeniedToolCall.ts
|
|
12592
12719
|
import { mkdirSync as mkdirSync12 } from "fs";
|
|
12593
12720
|
import { homedir as homedir15 } from "os";
|
|
12594
|
-
import { join as
|
|
12721
|
+
import { join as join31 } from "path";
|
|
12595
12722
|
import Database from "better-sqlite3";
|
|
12596
12723
|
var _db;
|
|
12597
12724
|
function getDbDir() {
|
|
12598
|
-
return
|
|
12725
|
+
return join31(homedir15(), ".assist");
|
|
12599
12726
|
}
|
|
12600
12727
|
function initSchema(db) {
|
|
12601
12728
|
db.exec(`
|
|
@@ -12614,7 +12741,7 @@ function openPromptsDb(dir) {
|
|
|
12614
12741
|
if (_db) return _db;
|
|
12615
12742
|
const dbDir = dir ?? getDbDir();
|
|
12616
12743
|
mkdirSync12(dbDir, { recursive: true });
|
|
12617
|
-
const db = new Database(
|
|
12744
|
+
const db = new Database(join31(dbDir, "assist.db"));
|
|
12618
12745
|
db.pragma("journal_mode = WAL");
|
|
12619
12746
|
initSchema(db);
|
|
12620
12747
|
_db = db;
|
|
@@ -12712,7 +12839,7 @@ ${reasons.join("\n")}`);
|
|
|
12712
12839
|
// src/commands/permitCliReads/index.ts
|
|
12713
12840
|
import { existsSync as existsSync31, mkdirSync as mkdirSync13, readFileSync as readFileSync25, writeFileSync as writeFileSync23 } from "fs";
|
|
12714
12841
|
import { homedir as homedir16 } from "os";
|
|
12715
|
-
import { join as
|
|
12842
|
+
import { join as join32 } from "path";
|
|
12716
12843
|
|
|
12717
12844
|
// src/commands/permitCliReads/assertCliExists.ts
|
|
12718
12845
|
function assertCliExists(cli) {
|
|
@@ -12980,7 +13107,7 @@ function updateSettings(cli, commands) {
|
|
|
12980
13107
|
// src/commands/permitCliReads/index.ts
|
|
12981
13108
|
function logPath(cli) {
|
|
12982
13109
|
const safeName = cli.replace(/\s+/g, "-");
|
|
12983
|
-
return
|
|
13110
|
+
return join32(homedir16(), ".assist", `cli-discover-${safeName}.log`);
|
|
12984
13111
|
}
|
|
12985
13112
|
function readCache(cli) {
|
|
12986
13113
|
const path71 = logPath(cli);
|
|
@@ -12988,7 +13115,7 @@ function readCache(cli) {
|
|
|
12988
13115
|
return readFileSync25(path71, "utf8");
|
|
12989
13116
|
}
|
|
12990
13117
|
function writeCache(cli, output) {
|
|
12991
|
-
const dir =
|
|
13118
|
+
const dir = join32(homedir16(), ".assist");
|
|
12992
13119
|
mkdirSync13(dir, { recursive: true });
|
|
12993
13120
|
writeFileSync23(logPath(cli), output);
|
|
12994
13121
|
}
|
|
@@ -13136,17 +13263,17 @@ import chalk113 from "chalk";
|
|
|
13136
13263
|
|
|
13137
13264
|
// src/commands/codeComment/getRestrictedDir.ts
|
|
13138
13265
|
import { homedir as homedir17 } from "os";
|
|
13139
|
-
import { join as
|
|
13266
|
+
import { join as join33 } from "path";
|
|
13140
13267
|
function getRestrictedDir() {
|
|
13141
|
-
return
|
|
13268
|
+
return join33(homedir17(), ".assist", "restricted");
|
|
13142
13269
|
}
|
|
13143
13270
|
function getPinStatePath(pin) {
|
|
13144
|
-
return
|
|
13271
|
+
return join33(getRestrictedDir(), `code-comment-${pin}.json`);
|
|
13145
13272
|
}
|
|
13146
13273
|
|
|
13147
13274
|
// src/commands/codeComment/sweepRestrictedDir.ts
|
|
13148
13275
|
import { readdirSync as readdirSync3, statSync as statSync3, unlinkSync as unlinkSync7 } from "fs";
|
|
13149
|
-
import { join as
|
|
13276
|
+
import { join as join34 } from "path";
|
|
13150
13277
|
var STALE_AFTER_MS = 30 * 60 * 1e3;
|
|
13151
13278
|
function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
13152
13279
|
let entries;
|
|
@@ -13157,7 +13284,7 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
13157
13284
|
}
|
|
13158
13285
|
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
13159
13286
|
for (const entry of entries) {
|
|
13160
|
-
const path71 =
|
|
13287
|
+
const path71 = join34(dir, entry);
|
|
13161
13288
|
try {
|
|
13162
13289
|
if (statSync3(path71).mtimeMs < cutoff) unlinkSync7(path71);
|
|
13163
13290
|
} catch {
|
|
@@ -14327,12 +14454,12 @@ import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync26 } from "fs"
|
|
|
14327
14454
|
import chalk129 from "chalk";
|
|
14328
14455
|
|
|
14329
14456
|
// src/commands/dbMigration/getMigrationPinPath.ts
|
|
14330
|
-
import { join as
|
|
14457
|
+
import { join as join35 } from "path";
|
|
14331
14458
|
function getMigrationPinPath(pin) {
|
|
14332
|
-
return
|
|
14459
|
+
return join35(getRestrictedDir(), `db-migration-pin-${pin}.json`);
|
|
14333
14460
|
}
|
|
14334
14461
|
function getMigrationApprovalPath(migrationId) {
|
|
14335
|
-
return
|
|
14462
|
+
return join35(getRestrictedDir(), `db-migration-approval-${migrationId}.json`);
|
|
14336
14463
|
}
|
|
14337
14464
|
|
|
14338
14465
|
// src/commands/dbMigration/readMigrationPinState.ts
|
|
@@ -14470,10 +14597,10 @@ import { basename as basename9 } from "path";
|
|
|
14470
14597
|
|
|
14471
14598
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
14472
14599
|
import { homedir as homedir18 } from "os";
|
|
14473
|
-
import { join as
|
|
14474
|
-
var BLOG_REPO_ROOT =
|
|
14600
|
+
import { join as join36 } from "path";
|
|
14601
|
+
var BLOG_REPO_ROOT = join36(homedir18(), "git/blog");
|
|
14475
14602
|
function loadBlogSkipDays(repoName) {
|
|
14476
|
-
const config = loadRawYaml(
|
|
14603
|
+
const config = loadRawYaml(join36(BLOG_REPO_ROOT, "assist.yml"));
|
|
14477
14604
|
const devlog = config.devlog;
|
|
14478
14605
|
const skip2 = devlog?.skip;
|
|
14479
14606
|
return new Set(skip2?.[repoName]);
|
|
@@ -14485,13 +14612,13 @@ import chalk132 from "chalk";
|
|
|
14485
14612
|
|
|
14486
14613
|
// src/shared/getRepoName.ts
|
|
14487
14614
|
import { existsSync as existsSync36, readFileSync as readFileSync30 } from "fs";
|
|
14488
|
-
import { basename as basename8, join as
|
|
14615
|
+
import { basename as basename8, join as join37 } from "path";
|
|
14489
14616
|
function getRepoName() {
|
|
14490
14617
|
const config = loadConfig();
|
|
14491
14618
|
if (config.devlog?.name) {
|
|
14492
14619
|
return config.devlog.name;
|
|
14493
14620
|
}
|
|
14494
|
-
const packageJsonPath =
|
|
14621
|
+
const packageJsonPath = join37(process.cwd(), "package.json");
|
|
14495
14622
|
if (existsSync36(packageJsonPath)) {
|
|
14496
14623
|
try {
|
|
14497
14624
|
const content = readFileSync30(packageJsonPath, "utf8");
|
|
@@ -14507,8 +14634,8 @@ function getRepoName() {
|
|
|
14507
14634
|
|
|
14508
14635
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
14509
14636
|
import { readdirSync as readdirSync4, readFileSync as readFileSync31 } from "fs";
|
|
14510
|
-
import { join as
|
|
14511
|
-
var DEVLOG_DIR =
|
|
14637
|
+
import { join as join38 } from "path";
|
|
14638
|
+
var DEVLOG_DIR = join38(BLOG_REPO_ROOT, "src/content/devlog");
|
|
14512
14639
|
function extractFrontmatter(content) {
|
|
14513
14640
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
14514
14641
|
return fm?.[1] ?? null;
|
|
@@ -14536,7 +14663,7 @@ function readDevlogFiles(callback) {
|
|
|
14536
14663
|
try {
|
|
14537
14664
|
const files = readdirSync4(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
14538
14665
|
for (const file of files) {
|
|
14539
|
-
const content = readFileSync31(
|
|
14666
|
+
const content = readFileSync31(join38(DEVLOG_DIR, file), "utf8");
|
|
14540
14667
|
const parsed = parseFrontmatter(content, file);
|
|
14541
14668
|
if (parsed) callback(parsed);
|
|
14542
14669
|
}
|
|
@@ -14924,11 +15051,11 @@ function repos(options2) {
|
|
|
14924
15051
|
|
|
14925
15052
|
// src/commands/devlog/skip.ts
|
|
14926
15053
|
import { writeFileSync as writeFileSync29 } from "fs";
|
|
14927
|
-
import { join as
|
|
15054
|
+
import { join as join39 } from "path";
|
|
14928
15055
|
import chalk137 from "chalk";
|
|
14929
15056
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
14930
15057
|
function getBlogConfigPath() {
|
|
14931
|
-
return
|
|
15058
|
+
return join39(BLOG_REPO_ROOT, "assist.yml");
|
|
14932
15059
|
}
|
|
14933
15060
|
function skip(date) {
|
|
14934
15061
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
@@ -15009,7 +15136,7 @@ function registerDevlog(program2) {
|
|
|
15009
15136
|
|
|
15010
15137
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
15011
15138
|
import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync5 } from "fs";
|
|
15012
|
-
import { join as
|
|
15139
|
+
import { join as join40 } from "path";
|
|
15013
15140
|
import chalk139 from "chalk";
|
|
15014
15141
|
|
|
15015
15142
|
// src/shared/findRepoRoot.ts
|
|
@@ -15037,7 +15164,7 @@ function isLockedDll(debugDir) {
|
|
|
15037
15164
|
}
|
|
15038
15165
|
for (const file of files) {
|
|
15039
15166
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
15040
|
-
const dllPath =
|
|
15167
|
+
const dllPath = join40(debugDir, file);
|
|
15041
15168
|
try {
|
|
15042
15169
|
const fd = openSync3(dllPath, "r+");
|
|
15043
15170
|
closeSync3(fd);
|
|
@@ -15055,13 +15182,13 @@ function findFirstLockedDll(dir) {
|
|
|
15055
15182
|
return null;
|
|
15056
15183
|
}
|
|
15057
15184
|
if (entries.includes("bin")) {
|
|
15058
|
-
const locked = isLockedDll(
|
|
15185
|
+
const locked = isLockedDll(join40(dir, "bin", "Debug"));
|
|
15059
15186
|
if (locked) return locked;
|
|
15060
15187
|
}
|
|
15061
15188
|
for (const entry of entries) {
|
|
15062
15189
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
15063
15190
|
continue;
|
|
15064
|
-
const found = findFirstLockedDll(
|
|
15191
|
+
const found = findFirstLockedDll(join40(dir, entry));
|
|
15065
15192
|
if (found) return found;
|
|
15066
15193
|
}
|
|
15067
15194
|
return null;
|
|
@@ -15408,11 +15535,11 @@ import chalk145 from "chalk";
|
|
|
15408
15535
|
|
|
15409
15536
|
// src/commands/dotnet/findSolution.ts
|
|
15410
15537
|
import { readdirSync as readdirSync7 } from "fs";
|
|
15411
|
-
import { dirname as dirname22, join as
|
|
15538
|
+
import { dirname as dirname22, join as join41 } from "path";
|
|
15412
15539
|
import chalk144 from "chalk";
|
|
15413
15540
|
function findSlnInDir(dir) {
|
|
15414
15541
|
try {
|
|
15415
|
-
return readdirSync7(dir).filter((f) => f.endsWith(".sln")).map((f) =>
|
|
15542
|
+
return readdirSync7(dir).filter((f) => f.endsWith(".sln")).map((f) => join41(dir, f));
|
|
15416
15543
|
} catch {
|
|
15417
15544
|
return [];
|
|
15418
15545
|
}
|
|
@@ -15484,7 +15611,7 @@ function parseInspectReport(json) {
|
|
|
15484
15611
|
// src/commands/dotnet/runInspectCode.ts
|
|
15485
15612
|
import { execSync as execSync37 } from "child_process";
|
|
15486
15613
|
import { existsSync as existsSync40, readFileSync as readFileSync34, unlinkSync as unlinkSync10 } from "fs";
|
|
15487
|
-
import { tmpdir as
|
|
15614
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
15488
15615
|
import path35 from "path";
|
|
15489
15616
|
import chalk146 from "chalk";
|
|
15490
15617
|
function assertJbInstalled() {
|
|
@@ -15499,7 +15626,7 @@ function assertJbInstalled() {
|
|
|
15499
15626
|
}
|
|
15500
15627
|
}
|
|
15501
15628
|
function runInspectCode(slnPath, include, swea) {
|
|
15502
|
-
const reportPath = path35.join(
|
|
15629
|
+
const reportPath = path35.join(tmpdir4(), `inspect-${Date.now()}.xml`);
|
|
15503
15630
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
15504
15631
|
const sweaFlag = swea ? " --swea" : "";
|
|
15505
15632
|
try {
|
|
@@ -15900,8 +16027,8 @@ function aggregateCommitters(authorLists) {
|
|
|
15900
16027
|
// src/shared/runGhGraphql.ts
|
|
15901
16028
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
15902
16029
|
import { unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
|
|
15903
|
-
import { tmpdir as
|
|
15904
|
-
import { join as
|
|
16030
|
+
import { tmpdir as tmpdir5 } from "os";
|
|
16031
|
+
import { join as join42 } from "path";
|
|
15905
16032
|
function buildArgs2(queryFile, vars) {
|
|
15906
16033
|
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
15907
16034
|
for (const [key, value] of Object.entries(vars)) {
|
|
@@ -15926,7 +16053,7 @@ function throwOnGraphqlErrors(stdout) {
|
|
|
15926
16053
|
throw new Error(messages || "GraphQL request returned errors");
|
|
15927
16054
|
}
|
|
15928
16055
|
function runGhGraphql(mutation, vars) {
|
|
15929
|
-
const queryFile =
|
|
16056
|
+
const queryFile = join42(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
15930
16057
|
writeFileSync30(queryFile, mutation);
|
|
15931
16058
|
try {
|
|
15932
16059
|
const result = spawnSync4("gh", buildArgs2(queryFile, vars), {
|
|
@@ -16119,18 +16246,18 @@ import {
|
|
|
16119
16246
|
rmSync as rmSync3,
|
|
16120
16247
|
statSync as statSync5
|
|
16121
16248
|
} from "fs";
|
|
16122
|
-
import { basename as basename10, join as
|
|
16249
|
+
import { basename as basename10, join as join45 } from "path";
|
|
16123
16250
|
|
|
16124
16251
|
// src/commands/handover/getHandoverPath.ts
|
|
16125
|
-
import { join as
|
|
16252
|
+
import { join as join43 } from "path";
|
|
16126
16253
|
function getHandoverPath(cwd = process.cwd()) {
|
|
16127
|
-
return
|
|
16254
|
+
return join43(cwd, ".assist", "HANDOVER.md");
|
|
16128
16255
|
}
|
|
16129
16256
|
|
|
16130
16257
|
// src/commands/handover/getHandoversDir.ts
|
|
16131
|
-
import { join as
|
|
16258
|
+
import { join as join44 } from "path";
|
|
16132
16259
|
function getHandoversDir(cwd = process.cwd()) {
|
|
16133
|
-
return
|
|
16260
|
+
return join44(cwd, ".assist", "handovers");
|
|
16134
16261
|
}
|
|
16135
16262
|
|
|
16136
16263
|
// src/commands/handover/parseArchiveTimestamp.ts
|
|
@@ -16171,7 +16298,7 @@ function collectMarkdown(dir) {
|
|
|
16171
16298
|
if (!existsSync42(dir)) return [];
|
|
16172
16299
|
const out = [];
|
|
16173
16300
|
for (const entry of readdirSync8(dir, { withFileTypes: true })) {
|
|
16174
|
-
const full =
|
|
16301
|
+
const full = join45(dir, entry.name);
|
|
16175
16302
|
if (entry.isDirectory()) out.push(...collectMarkdown(full));
|
|
16176
16303
|
else if (entry.isFile() && entry.name.endsWith(".md")) out.push(full);
|
|
16177
16304
|
}
|
|
@@ -16619,7 +16746,7 @@ import chalk156 from "chalk";
|
|
|
16619
16746
|
|
|
16620
16747
|
// src/commands/mermaid/exportFile.ts
|
|
16621
16748
|
import { readFileSync as readFileSync36, writeFileSync as writeFileSync31 } from "fs";
|
|
16622
|
-
import { basename as basename11, extname, resolve as resolve11 } from "path";
|
|
16749
|
+
import { basename as basename11, extname as extname2, resolve as resolve11 } from "path";
|
|
16623
16750
|
import chalk155 from "chalk";
|
|
16624
16751
|
|
|
16625
16752
|
// src/commands/mermaid/renderBlock.ts
|
|
@@ -16646,7 +16773,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
16646
16773
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
16647
16774
|
const content = readFileSync36(file, "utf8");
|
|
16648
16775
|
const blocks = extractMermaidBlocks(content);
|
|
16649
|
-
const stem = basename11(file,
|
|
16776
|
+
const stem = basename11(file, extname2(file));
|
|
16650
16777
|
if (onlyIndex !== void 0) {
|
|
16651
16778
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
16652
16779
|
console.error(
|
|
@@ -16806,17 +16933,17 @@ function createNetcapHandler(options2) {
|
|
|
16806
16933
|
}
|
|
16807
16934
|
|
|
16808
16935
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
16809
|
-
import { cp, readFile as readFile2, writeFile as
|
|
16936
|
+
import { cp, readFile as readFile2, writeFile as writeFile3 } from "fs/promises";
|
|
16810
16937
|
import { networkInterfaces } from "os";
|
|
16811
|
-
import { join as
|
|
16938
|
+
import { join as join47 } from "path";
|
|
16812
16939
|
import chalk157 from "chalk";
|
|
16813
16940
|
|
|
16814
16941
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
16815
|
-
import { dirname as dirname23, join as
|
|
16942
|
+
import { dirname as dirname23, join as join46 } from "path";
|
|
16816
16943
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
16817
16944
|
var moduleDir = dirname23(fileURLToPath6(import.meta.url));
|
|
16818
16945
|
function netcapExtensionDir() {
|
|
16819
|
-
return
|
|
16946
|
+
return join46(moduleDir, "commands", "netcap", "netcap-extension");
|
|
16820
16947
|
}
|
|
16821
16948
|
|
|
16822
16949
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
@@ -16831,9 +16958,9 @@ function lanIPv4() {
|
|
|
16831
16958
|
return void 0;
|
|
16832
16959
|
}
|
|
16833
16960
|
async function configureBackground(dir, host, port, filter) {
|
|
16834
|
-
const file =
|
|
16961
|
+
const file = join47(dir, "background.js");
|
|
16835
16962
|
const source = await readFile2(file, "utf8");
|
|
16836
|
-
await
|
|
16963
|
+
await writeFile3(
|
|
16837
16964
|
file,
|
|
16838
16965
|
source.replace(
|
|
16839
16966
|
/const RECEIVER = "[^"]*";/,
|
|
@@ -16871,20 +16998,20 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
16871
16998
|
}
|
|
16872
16999
|
|
|
16873
17000
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
16874
|
-
import { isAbsolute, join as
|
|
17001
|
+
import { isAbsolute, join as join49, resolve as resolve13 } from "path";
|
|
16875
17002
|
|
|
16876
17003
|
// src/commands/netcap/defaultCapturePath.ts
|
|
16877
17004
|
import { homedir as homedir19 } from "os";
|
|
16878
|
-
import { join as
|
|
17005
|
+
import { join as join48 } from "path";
|
|
16879
17006
|
function defaultCapturePath() {
|
|
16880
|
-
return
|
|
17007
|
+
return join48(homedir19(), ".assist", "netcap", "capture.jsonl");
|
|
16881
17008
|
}
|
|
16882
17009
|
|
|
16883
17010
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
16884
17011
|
function resolveNetcapOutPath(out) {
|
|
16885
17012
|
if (!out) return defaultCapturePath();
|
|
16886
17013
|
const dir = isAbsolute(out) ? out : resolve13(process.cwd(), out);
|
|
16887
|
-
return
|
|
17014
|
+
return join49(dir, "capture.jsonl");
|
|
16888
17015
|
}
|
|
16889
17016
|
|
|
16890
17017
|
// src/commands/netcap/netcap.ts
|
|
@@ -16931,7 +17058,7 @@ netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} t
|
|
|
16931
17058
|
|
|
16932
17059
|
// src/commands/netcap/netcapExtract.ts
|
|
16933
17060
|
import { writeFileSync as writeFileSync32 } from "fs";
|
|
16934
|
-
import { join as
|
|
17061
|
+
import { join as join50 } from "path";
|
|
16935
17062
|
import chalk159 from "chalk";
|
|
16936
17063
|
|
|
16937
17064
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
@@ -17376,7 +17503,7 @@ function extractPostsFromCapture(captureFile) {
|
|
|
17376
17503
|
function netcapExtract(file) {
|
|
17377
17504
|
const captureFile = file ?? defaultCapturePath();
|
|
17378
17505
|
const posts = extractPostsFromCapture(captureFile);
|
|
17379
|
-
const outFile =
|
|
17506
|
+
const outFile = join50(captureFile, "..", "posts.json");
|
|
17380
17507
|
writeFileSync32(outFile, `${JSON.stringify(posts, null, 2)}
|
|
17381
17508
|
`);
|
|
17382
17509
|
console.log(
|
|
@@ -17866,15 +17993,15 @@ import { execSync as execSync43 } from "child_process";
|
|
|
17866
17993
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
17867
17994
|
import { execSync as execSync42 } from "child_process";
|
|
17868
17995
|
import { unlinkSync as unlinkSync14, writeFileSync as writeFileSync33 } from "fs";
|
|
17869
|
-
import { tmpdir as
|
|
17870
|
-
import { join as
|
|
17996
|
+
import { tmpdir as tmpdir6 } from "os";
|
|
17997
|
+
import { join as join52 } from "path";
|
|
17871
17998
|
|
|
17872
17999
|
// src/commands/prs/loadCommentsCache.ts
|
|
17873
18000
|
import { existsSync as existsSync43, readFileSync as readFileSync38, unlinkSync as unlinkSync13 } from "fs";
|
|
17874
|
-
import { join as
|
|
18001
|
+
import { join as join51 } from "path";
|
|
17875
18002
|
import { parse as parse2 } from "yaml";
|
|
17876
18003
|
function getCachePath(prNumber) {
|
|
17877
|
-
return
|
|
18004
|
+
return join51(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
17878
18005
|
}
|
|
17879
18006
|
function loadCommentsCache(prNumber) {
|
|
17880
18007
|
const cachePath = getCachePath(prNumber);
|
|
@@ -17904,7 +18031,7 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
17904
18031
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
17905
18032
|
function resolveThread(threadId) {
|
|
17906
18033
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
17907
|
-
const queryFile =
|
|
18034
|
+
const queryFile = join52(tmpdir6(), `gh-mutation-${Date.now()}.graphql`);
|
|
17908
18035
|
writeFileSync33(queryFile, mutation);
|
|
17909
18036
|
try {
|
|
17910
18037
|
execSync42(
|
|
@@ -17987,17 +18114,17 @@ function fixed(commentId, sha) {
|
|
|
17987
18114
|
|
|
17988
18115
|
// src/commands/prs/listComments/index.ts
|
|
17989
18116
|
import { existsSync as existsSync44, mkdirSync as mkdirSync17, writeFileSync as writeFileSync35 } from "fs";
|
|
17990
|
-
import { join as
|
|
18117
|
+
import { join as join54 } from "path";
|
|
17991
18118
|
import { stringify } from "yaml";
|
|
17992
18119
|
|
|
17993
18120
|
// src/commands/prs/fetchThreadIds.ts
|
|
17994
18121
|
import { execSync as execSync44 } from "child_process";
|
|
17995
18122
|
import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync34 } from "fs";
|
|
17996
|
-
import { tmpdir as
|
|
17997
|
-
import { join as
|
|
18123
|
+
import { tmpdir as tmpdir7 } from "os";
|
|
18124
|
+
import { join as join53 } from "path";
|
|
17998
18125
|
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 } } } } } } }`;
|
|
17999
18126
|
function fetchThreadIds(org, repo, prNumber) {
|
|
18000
|
-
const queryFile =
|
|
18127
|
+
const queryFile = join53(tmpdir7(), `gh-query-${Date.now()}.graphql`);
|
|
18001
18128
|
writeFileSync34(queryFile, THREAD_QUERY);
|
|
18002
18129
|
try {
|
|
18003
18130
|
const result = execSync44(
|
|
@@ -18111,7 +18238,7 @@ function printComments2(result) {
|
|
|
18111
18238
|
|
|
18112
18239
|
// src/commands/prs/listComments/index.ts
|
|
18113
18240
|
function writeCommentsCache(prNumber, comments3) {
|
|
18114
|
-
const assistDir =
|
|
18241
|
+
const assistDir = join54(process.cwd(), ".assist");
|
|
18115
18242
|
if (!existsSync44(assistDir)) {
|
|
18116
18243
|
mkdirSync17(assistDir, { recursive: true });
|
|
18117
18244
|
}
|
|
@@ -18120,7 +18247,7 @@ function writeCommentsCache(prNumber, comments3) {
|
|
|
18120
18247
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18121
18248
|
comments: comments3
|
|
18122
18249
|
};
|
|
18123
|
-
const cachePath =
|
|
18250
|
+
const cachePath = join54(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
18124
18251
|
writeFileSync35(cachePath, stringify(cacheData));
|
|
18125
18252
|
}
|
|
18126
18253
|
function handleKnownErrors(error) {
|
|
@@ -18153,7 +18280,7 @@ async function listComments() {
|
|
|
18153
18280
|
];
|
|
18154
18281
|
updateCache(prNumber, allComments);
|
|
18155
18282
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
18156
|
-
const cachePath = hasLineComments ?
|
|
18283
|
+
const cachePath = hasLineComments ? join54(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
18157
18284
|
return { comments: allComments, cachePath };
|
|
18158
18285
|
} catch (error) {
|
|
18159
18286
|
const handled = handleKnownErrors(error);
|
|
@@ -18404,6 +18531,39 @@ async function placePr(prNumber, title, body, options2) {
|
|
|
18404
18531
|
// src/commands/prs/previewAndPlace.ts
|
|
18405
18532
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
18406
18533
|
|
|
18534
|
+
// src/commands/prs/appendScreenshots.ts
|
|
18535
|
+
function appendScreenshots(body, screenshots) {
|
|
18536
|
+
if (screenshots.length === 0) return body;
|
|
18537
|
+
return `${body}
|
|
18538
|
+
|
|
18539
|
+
## Screenshots
|
|
18540
|
+
|
|
18541
|
+
${screenshots.join("\n\n")}`;
|
|
18542
|
+
}
|
|
18543
|
+
|
|
18544
|
+
// src/commands/prs/reportPrRejection.ts
|
|
18545
|
+
function reportPrRejection(decision) {
|
|
18546
|
+
console.error(
|
|
18547
|
+
`PR preview rejected${decision.reason ? `: ${decision.reason}` : "."}`
|
|
18548
|
+
);
|
|
18549
|
+
const comments3 = decision.comments ?? [];
|
|
18550
|
+
if (comments3.length > 0) {
|
|
18551
|
+
console.error(
|
|
18552
|
+
`
|
|
18553
|
+
The reviewer left ${comments3.length} comment${comments3.length === 1 ? "" : "s"} on the preview. Address each one, then re-run this command:
|
|
18554
|
+
`
|
|
18555
|
+
);
|
|
18556
|
+
for (const [i, c] of comments3.entries()) {
|
|
18557
|
+
const quoted = c.quote.split("\n").map((line) => ` > ${line}`).join("\n");
|
|
18558
|
+
console.error(`${i + 1}. On:
|
|
18559
|
+
${quoted}
|
|
18560
|
+
Comment: ${c.note}
|
|
18561
|
+
`);
|
|
18562
|
+
}
|
|
18563
|
+
}
|
|
18564
|
+
process.exit(1);
|
|
18565
|
+
}
|
|
18566
|
+
|
|
18407
18567
|
// src/commands/prs/parseIncoming.ts
|
|
18408
18568
|
function parseIncoming(line, requestId) {
|
|
18409
18569
|
try {
|
|
@@ -18417,7 +18577,8 @@ function parseIncoming(line, requestId) {
|
|
|
18417
18577
|
decision: {
|
|
18418
18578
|
decision: msg.decision,
|
|
18419
18579
|
reason: msg.reason,
|
|
18420
|
-
comments: Array.isArray(msg.comments) ? msg.comments : void 0
|
|
18580
|
+
comments: Array.isArray(msg.comments) ? msg.comments : void 0,
|
|
18581
|
+
screenshots: Array.isArray(msg.screenshots) ? msg.screenshots : void 0
|
|
18421
18582
|
}
|
|
18422
18583
|
};
|
|
18423
18584
|
} catch {
|
|
@@ -18472,28 +18633,9 @@ async function previewAndPlace(args) {
|
|
|
18472
18633
|
);
|
|
18473
18634
|
process.exit(1);
|
|
18474
18635
|
}
|
|
18475
|
-
if (decision.decision === "reject")
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
);
|
|
18479
|
-
const comments3 = decision.comments ?? [];
|
|
18480
|
-
if (comments3.length > 0) {
|
|
18481
|
-
console.error(
|
|
18482
|
-
`
|
|
18483
|
-
The reviewer left ${comments3.length} comment${comments3.length === 1 ? "" : "s"} on the preview. Address each one, then re-run this command:
|
|
18484
|
-
`
|
|
18485
|
-
);
|
|
18486
|
-
for (const [i, c] of comments3.entries()) {
|
|
18487
|
-
const quoted = c.quote.split("\n").map((line) => ` > ${line}`).join("\n");
|
|
18488
|
-
console.error(`${i + 1}. On:
|
|
18489
|
-
${quoted}
|
|
18490
|
-
Comment: ${c.note}
|
|
18491
|
-
`);
|
|
18492
|
-
}
|
|
18493
|
-
}
|
|
18494
|
-
process.exit(1);
|
|
18495
|
-
}
|
|
18496
|
-
await placePr(args.prNumber, args.title, args.body, args.options);
|
|
18636
|
+
if (decision.decision === "reject") reportPrRejection(decision);
|
|
18637
|
+
const body = appendScreenshots(args.body, decision.screenshots ?? []);
|
|
18638
|
+
await placePr(args.prNumber, args.title, body, args.options);
|
|
18497
18639
|
}
|
|
18498
18640
|
|
|
18499
18641
|
// src/commands/prs/raise.ts
|
|
@@ -18706,7 +18848,10 @@ on rejection it exits non-zero with the reason. The reviewer may also attach
|
|
|
18706
18848
|
inline comments to specific spans of the preview; on rejection these are printed
|
|
18707
18849
|
as numbered quoted-span + note pairs on stderr. Address every comment (and the
|
|
18708
18850
|
reason), then run the command again to re-preview the revised PR. Repeat until it
|
|
18709
|
-
is approved.
|
|
18851
|
+
is approved. The reviewer may also drop or paste screenshots into the pane; on
|
|
18852
|
+
approval these are appended to the PR body under a ## Screenshots section
|
|
18853
|
+
automatically (they are discarded on rejection), so you never author that section
|
|
18854
|
+
yourself. Just compose the sections and run the command.`;
|
|
18710
18855
|
function raiseHelpText(promptJira) {
|
|
18711
18856
|
const prompt = promptJira ?? loadConfig().prs?.promptJira ?? false;
|
|
18712
18857
|
const confirm = process.env.ASSIST_SESSION === "1" ? WEB_CONFIRM : TERMINAL_CONFIRM;
|
|
@@ -21014,9 +21159,9 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
|
21014
21159
|
|
|
21015
21160
|
// src/commands/review/buildReviewPaths.ts
|
|
21016
21161
|
import { homedir as homedir20 } from "os";
|
|
21017
|
-
import { basename as basename12, join as
|
|
21162
|
+
import { basename as basename12, join as join55 } from "path";
|
|
21018
21163
|
function buildReviewPaths(repoRoot, key) {
|
|
21019
|
-
const reviewDir =
|
|
21164
|
+
const reviewDir = join55(
|
|
21020
21165
|
homedir20(),
|
|
21021
21166
|
".assist",
|
|
21022
21167
|
"reviews",
|
|
@@ -21025,10 +21170,10 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
21025
21170
|
);
|
|
21026
21171
|
return {
|
|
21027
21172
|
reviewDir,
|
|
21028
|
-
requestPath:
|
|
21029
|
-
claudePath:
|
|
21030
|
-
codexPath:
|
|
21031
|
-
synthesisPath:
|
|
21173
|
+
requestPath: join55(reviewDir, "request.md"),
|
|
21174
|
+
claudePath: join55(reviewDir, "claude.md"),
|
|
21175
|
+
codexPath: join55(reviewDir, "codex.md"),
|
|
21176
|
+
synthesisPath: join55(reviewDir, "synthesis.md")
|
|
21032
21177
|
};
|
|
21033
21178
|
}
|
|
21034
21179
|
|
|
@@ -23354,13 +23499,13 @@ async function configure() {
|
|
|
23354
23499
|
|
|
23355
23500
|
// src/commands/transcript/list.ts
|
|
23356
23501
|
import { existsSync as existsSync48, readdirSync as readdirSync10, statSync as statSync7 } from "fs";
|
|
23357
|
-
import { join as
|
|
23502
|
+
import { join as join56 } from "path";
|
|
23358
23503
|
function list4() {
|
|
23359
23504
|
const { vttDir } = getTranscriptConfig();
|
|
23360
23505
|
if (!existsSync48(vttDir)) return;
|
|
23361
23506
|
for (const entry of readdirSync10(vttDir)) {
|
|
23362
23507
|
if (!entry.endsWith(".vtt")) continue;
|
|
23363
|
-
if (statSync7(
|
|
23508
|
+
if (statSync7(join56(vttDir, entry)).isDirectory()) continue;
|
|
23364
23509
|
console.log(entry);
|
|
23365
23510
|
}
|
|
23366
23511
|
}
|
|
@@ -23373,7 +23518,7 @@ import {
|
|
|
23373
23518
|
renameSync as renameSync2,
|
|
23374
23519
|
writeFileSync as writeFileSync38
|
|
23375
23520
|
} from "fs";
|
|
23376
|
-
import { basename as basename13, join as
|
|
23521
|
+
import { basename as basename13, join as join57 } from "path";
|
|
23377
23522
|
|
|
23378
23523
|
// src/commands/transcript/cleanText.ts
|
|
23379
23524
|
function cleanText(text17) {
|
|
@@ -23586,9 +23731,9 @@ function convertVttToMarkdown(inputPath) {
|
|
|
23586
23731
|
return formatChatLog(messages);
|
|
23587
23732
|
}
|
|
23588
23733
|
function archiveRawVtt(vttDir, sourcePath, filename) {
|
|
23589
|
-
const processedDir =
|
|
23734
|
+
const processedDir = join57(vttDir, "processed");
|
|
23590
23735
|
mkdirSync19(processedDir, { recursive: true });
|
|
23591
|
-
renameSync2(sourcePath,
|
|
23736
|
+
renameSync2(sourcePath, join57(processedDir, filename));
|
|
23592
23737
|
}
|
|
23593
23738
|
function move(file, options2) {
|
|
23594
23739
|
const { date, client } = options2;
|
|
@@ -23598,19 +23743,19 @@ function move(file, options2) {
|
|
|
23598
23743
|
}
|
|
23599
23744
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
23600
23745
|
const filename = basename13(file);
|
|
23601
|
-
const sourcePath =
|
|
23746
|
+
const sourcePath = join57(vttDir, filename);
|
|
23602
23747
|
if (!existsSync49(sourcePath)) {
|
|
23603
23748
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
23604
23749
|
process.exit(1);
|
|
23605
23750
|
}
|
|
23606
23751
|
const base = basename13(filename, ".vtt").replace(/ Transcription$/, "");
|
|
23607
23752
|
const outputName = `${date} ${base}.md`;
|
|
23608
|
-
const formattedDir =
|
|
23753
|
+
const formattedDir = join57(transcriptsDir, client);
|
|
23609
23754
|
mkdirSync19(formattedDir, { recursive: true });
|
|
23610
|
-
const formattedPath =
|
|
23755
|
+
const formattedPath = join57(formattedDir, outputName);
|
|
23611
23756
|
writeFileSync38(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
23612
23757
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
23613
|
-
const summaryPath =
|
|
23758
|
+
const summaryPath = join57(summaryDir, client, outputName);
|
|
23614
23759
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
23615
23760
|
console.log(`Summary target: ${summaryPath}`);
|
|
23616
23761
|
}
|
|
@@ -23730,38 +23875,38 @@ function registerVerify(program2) {
|
|
|
23730
23875
|
|
|
23731
23876
|
// src/commands/voice/devices.ts
|
|
23732
23877
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
23733
|
-
import { join as
|
|
23878
|
+
import { join as join59 } from "path";
|
|
23734
23879
|
|
|
23735
23880
|
// src/commands/voice/shared.ts
|
|
23736
23881
|
import { homedir as homedir21 } from "os";
|
|
23737
|
-
import { dirname as dirname26, join as
|
|
23882
|
+
import { dirname as dirname26, join as join58 } from "path";
|
|
23738
23883
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
23739
23884
|
var __dirname5 = dirname26(fileURLToPath7(import.meta.url));
|
|
23740
|
-
var VOICE_DIR =
|
|
23885
|
+
var VOICE_DIR = join58(homedir21(), ".assist", "voice");
|
|
23741
23886
|
var voicePaths = {
|
|
23742
23887
|
dir: VOICE_DIR,
|
|
23743
|
-
pid:
|
|
23744
|
-
log:
|
|
23745
|
-
venv:
|
|
23746
|
-
lock:
|
|
23888
|
+
pid: join58(VOICE_DIR, "voice.pid"),
|
|
23889
|
+
log: join58(VOICE_DIR, "voice.log"),
|
|
23890
|
+
venv: join58(VOICE_DIR, ".venv"),
|
|
23891
|
+
lock: join58(VOICE_DIR, "voice.lock")
|
|
23747
23892
|
};
|
|
23748
23893
|
function getPythonDir() {
|
|
23749
|
-
return
|
|
23894
|
+
return join58(__dirname5, "commands", "voice", "python");
|
|
23750
23895
|
}
|
|
23751
23896
|
function getVenvPython() {
|
|
23752
|
-
return process.platform === "win32" ?
|
|
23897
|
+
return process.platform === "win32" ? join58(voicePaths.venv, "Scripts", "python.exe") : join58(voicePaths.venv, "bin", "python");
|
|
23753
23898
|
}
|
|
23754
23899
|
function getLockDir() {
|
|
23755
23900
|
const config = loadConfig();
|
|
23756
23901
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
23757
23902
|
}
|
|
23758
23903
|
function getLockFile() {
|
|
23759
|
-
return
|
|
23904
|
+
return join58(getLockDir(), "voice.lock");
|
|
23760
23905
|
}
|
|
23761
23906
|
|
|
23762
23907
|
// src/commands/voice/devices.ts
|
|
23763
23908
|
function devices() {
|
|
23764
|
-
const script =
|
|
23909
|
+
const script = join59(getPythonDir(), "list_devices.py");
|
|
23765
23910
|
spawnSync6(getVenvPython(), [script], { stdio: "inherit" });
|
|
23766
23911
|
}
|
|
23767
23912
|
|
|
@@ -23796,12 +23941,12 @@ function logs(options2) {
|
|
|
23796
23941
|
// src/commands/voice/setup.ts
|
|
23797
23942
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
23798
23943
|
import { mkdirSync as mkdirSync21 } from "fs";
|
|
23799
|
-
import { join as
|
|
23944
|
+
import { join as join61 } from "path";
|
|
23800
23945
|
|
|
23801
23946
|
// src/commands/voice/checkLockFile.ts
|
|
23802
23947
|
import { execSync as execSync56 } from "child_process";
|
|
23803
23948
|
import { existsSync as existsSync51, mkdirSync as mkdirSync20, readFileSync as readFileSync43, writeFileSync as writeFileSync39 } from "fs";
|
|
23804
|
-
import { join as
|
|
23949
|
+
import { join as join60 } from "path";
|
|
23805
23950
|
function isProcessAlive2(pid) {
|
|
23806
23951
|
try {
|
|
23807
23952
|
process.kill(pid, 0);
|
|
@@ -23838,7 +23983,7 @@ function bootstrapVenv() {
|
|
|
23838
23983
|
}
|
|
23839
23984
|
function writeLockFile(pid) {
|
|
23840
23985
|
const lockFile = getLockFile();
|
|
23841
|
-
mkdirSync20(
|
|
23986
|
+
mkdirSync20(join60(lockFile, ".."), { recursive: true });
|
|
23842
23987
|
writeFileSync39(
|
|
23843
23988
|
lockFile,
|
|
23844
23989
|
JSON.stringify({
|
|
@@ -23854,7 +23999,7 @@ function setup() {
|
|
|
23854
23999
|
mkdirSync21(voicePaths.dir, { recursive: true });
|
|
23855
24000
|
bootstrapVenv();
|
|
23856
24001
|
console.log("\nDownloading models...\n");
|
|
23857
|
-
const script =
|
|
24002
|
+
const script = join61(getPythonDir(), "setup_models.py");
|
|
23858
24003
|
const result = spawnSync7(getVenvPython(), [script], {
|
|
23859
24004
|
stdio: "inherit",
|
|
23860
24005
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -23868,7 +24013,7 @@ function setup() {
|
|
|
23868
24013
|
// src/commands/voice/start.ts
|
|
23869
24014
|
import { spawn as spawn7 } from "child_process";
|
|
23870
24015
|
import { mkdirSync as mkdirSync22, writeFileSync as writeFileSync40 } from "fs";
|
|
23871
|
-
import { join as
|
|
24016
|
+
import { join as join62 } from "path";
|
|
23872
24017
|
|
|
23873
24018
|
// src/commands/voice/buildDaemonEnv.ts
|
|
23874
24019
|
function buildDaemonEnv(options2) {
|
|
@@ -23906,7 +24051,7 @@ function start2(options2) {
|
|
|
23906
24051
|
bootstrapVenv();
|
|
23907
24052
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
23908
24053
|
const env = buildDaemonEnv({ debug });
|
|
23909
|
-
const script =
|
|
24054
|
+
const script = join62(getPythonDir(), "voice_daemon.py");
|
|
23910
24055
|
const python = getVenvPython();
|
|
23911
24056
|
if (options2.foreground) {
|
|
23912
24057
|
spawnForeground(python, script, env);
|
|
@@ -24197,7 +24342,7 @@ async function auth() {
|
|
|
24197
24342
|
// src/commands/roam/postRoamActivity.ts
|
|
24198
24343
|
import { execFileSync as execFileSync9 } from "child_process";
|
|
24199
24344
|
import { readdirSync as readdirSync11, readFileSync as readFileSync46, statSync as statSync8 } from "fs";
|
|
24200
|
-
import { join as
|
|
24345
|
+
import { join as join63 } from "path";
|
|
24201
24346
|
function findPortFile(roamDir) {
|
|
24202
24347
|
let entries;
|
|
24203
24348
|
try {
|
|
@@ -24206,7 +24351,7 @@ function findPortFile(roamDir) {
|
|
|
24206
24351
|
return void 0;
|
|
24207
24352
|
}
|
|
24208
24353
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
24209
|
-
const path71 =
|
|
24354
|
+
const path71 = join63(roamDir, name);
|
|
24210
24355
|
try {
|
|
24211
24356
|
return { path: path71, mtimeMs: statSync8(path71).mtimeMs };
|
|
24212
24357
|
} catch {
|
|
@@ -24218,7 +24363,7 @@ function findPortFile(roamDir) {
|
|
|
24218
24363
|
function postRoamActivity(app, event) {
|
|
24219
24364
|
const appData = process.env.APPDATA;
|
|
24220
24365
|
if (!appData) return;
|
|
24221
|
-
const portFile = findPortFile(
|
|
24366
|
+
const portFile = findPortFile(join63(appData, "Roam"));
|
|
24222
24367
|
if (!portFile) return;
|
|
24223
24368
|
let port;
|
|
24224
24369
|
try {
|
|
@@ -24439,13 +24584,13 @@ function runPreCommands(pre, cwd) {
|
|
|
24439
24584
|
// src/commands/run/spawnRunCommand.ts
|
|
24440
24585
|
import { execFileSync as execFileSync10, spawn as spawn8 } from "child_process";
|
|
24441
24586
|
import { existsSync as existsSync54 } from "fs";
|
|
24442
|
-
import { dirname as dirname27, join as
|
|
24587
|
+
import { dirname as dirname27, join as join64, resolve as resolve14 } from "path";
|
|
24443
24588
|
function resolveCommand2(command) {
|
|
24444
24589
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
24445
24590
|
try {
|
|
24446
24591
|
const gitPath = execFileSync10("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
24447
24592
|
const gitRoot = resolve14(dirname27(gitPath), "..");
|
|
24448
|
-
const gitBash =
|
|
24593
|
+
const gitBash = join64(gitRoot, "bin", "bash.exe");
|
|
24449
24594
|
if (existsSync54(gitBash)) return gitBash;
|
|
24450
24595
|
} catch {
|
|
24451
24596
|
}
|
|
@@ -24534,7 +24679,7 @@ async function run3(name, args) {
|
|
|
24534
24679
|
|
|
24535
24680
|
// src/commands/run/add.ts
|
|
24536
24681
|
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync41 } from "fs";
|
|
24537
|
-
import { join as
|
|
24682
|
+
import { join as join65 } from "path";
|
|
24538
24683
|
|
|
24539
24684
|
// src/commands/run/extractOption.ts
|
|
24540
24685
|
function extractOption(args, flag) {
|
|
@@ -24595,7 +24740,7 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
24595
24740
|
saveConfig(config);
|
|
24596
24741
|
}
|
|
24597
24742
|
function createCommandFile(name) {
|
|
24598
|
-
const dir =
|
|
24743
|
+
const dir = join65(".claude", "commands");
|
|
24599
24744
|
mkdirSync23(dir, { recursive: true });
|
|
24600
24745
|
const content = `---
|
|
24601
24746
|
description: Run ${name}
|
|
@@ -24603,7 +24748,7 @@ description: Run ${name}
|
|
|
24603
24748
|
|
|
24604
24749
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
24605
24750
|
`;
|
|
24606
|
-
const filePath =
|
|
24751
|
+
const filePath = join65(dir, `${name}.md`);
|
|
24607
24752
|
writeFileSync41(filePath, content);
|
|
24608
24753
|
console.log(`Created command file: ${filePath}`);
|
|
24609
24754
|
}
|
|
@@ -24660,7 +24805,7 @@ function link2() {
|
|
|
24660
24805
|
|
|
24661
24806
|
// src/commands/run/remove.ts
|
|
24662
24807
|
import { existsSync as existsSync55, unlinkSync as unlinkSync20 } from "fs";
|
|
24663
|
-
import { join as
|
|
24808
|
+
import { join as join66 } from "path";
|
|
24664
24809
|
function findRemoveIndex() {
|
|
24665
24810
|
const idx = process.argv.indexOf("remove");
|
|
24666
24811
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -24675,7 +24820,7 @@ function parseRemoveName() {
|
|
|
24675
24820
|
return process.argv[idx + 1];
|
|
24676
24821
|
}
|
|
24677
24822
|
function deleteCommandFile(name) {
|
|
24678
|
-
const filePath =
|
|
24823
|
+
const filePath = join66(".claude", "commands", `${name}.md`);
|
|
24679
24824
|
if (existsSync55(filePath)) {
|
|
24680
24825
|
unlinkSync20(filePath);
|
|
24681
24826
|
console.log(`Deleted command file: ${filePath}`);
|
|
@@ -24731,8 +24876,8 @@ function registerRun(program2) {
|
|
|
24731
24876
|
// src/commands/screenshot/index.ts
|
|
24732
24877
|
import { execSync as execSync58 } from "child_process";
|
|
24733
24878
|
import { existsSync as existsSync56, mkdirSync as mkdirSync24, unlinkSync as unlinkSync21, writeFileSync as writeFileSync42 } from "fs";
|
|
24734
|
-
import { tmpdir as
|
|
24735
|
-
import { join as
|
|
24879
|
+
import { tmpdir as tmpdir8 } from "os";
|
|
24880
|
+
import { join as join67, resolve as resolve16 } from "path";
|
|
24736
24881
|
import chalk203 from "chalk";
|
|
24737
24882
|
|
|
24738
24883
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -24869,7 +25014,7 @@ function buildOutputPath(outputDir, processName) {
|
|
|
24869
25014
|
return resolve16(outputDir, `${processName}-${timestamp6}.png`);
|
|
24870
25015
|
}
|
|
24871
25016
|
function runPowerShellScript(processName, outputPath) {
|
|
24872
|
-
const scriptPath =
|
|
25017
|
+
const scriptPath = join67(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
|
|
24873
25018
|
writeFileSync42(scriptPath, captureWindowPs1, "utf8");
|
|
24874
25019
|
try {
|
|
24875
25020
|
execSync58(
|
|
@@ -25673,8 +25818,9 @@ function decidePrPreview(sessions, waiters, notify2, d) {
|
|
|
25673
25818
|
return;
|
|
25674
25819
|
}
|
|
25675
25820
|
const commentCount = Array.isArray(d.comments) ? d.comments.length : 0;
|
|
25821
|
+
const screenshotCount = Array.isArray(d.screenshots) ? d.screenshots.length : 0;
|
|
25676
25822
|
daemonLog(
|
|
25677
|
-
`pr-decision received: id=${id} requestId=${requestId} decision=${d.decision} comments=${commentCount}`
|
|
25823
|
+
`pr-decision received: id=${id} requestId=${requestId} decision=${d.decision} comments=${commentCount} screenshots=${screenshotCount}`
|
|
25678
25824
|
);
|
|
25679
25825
|
const waiter = waiters.get(id);
|
|
25680
25826
|
if (waiter)
|
|
@@ -25683,7 +25829,8 @@ function decidePrPreview(sessions, waiters, notify2, d) {
|
|
|
25683
25829
|
requestId,
|
|
25684
25830
|
decision: d.decision,
|
|
25685
25831
|
reason: d.reason,
|
|
25686
|
-
comments: d.comments
|
|
25832
|
+
comments: d.comments,
|
|
25833
|
+
screenshots: d.screenshots
|
|
25687
25834
|
});
|
|
25688
25835
|
waiters.delete(id);
|
|
25689
25836
|
session.pendingPrPreview = void 0;
|
|
@@ -28469,9 +28616,9 @@ function buildLimitsSegment(rateLimits) {
|
|
|
28469
28616
|
|
|
28470
28617
|
// src/commands/readGitBranch.ts
|
|
28471
28618
|
import { readFileSync as readFileSync52, statSync as statSync11 } from "fs";
|
|
28472
|
-
import { isAbsolute as isAbsolute2, join as
|
|
28619
|
+
import { isAbsolute as isAbsolute2, join as join70, resolve as resolve17 } from "path";
|
|
28473
28620
|
function resolveGitDir(cwd) {
|
|
28474
|
-
const dotGit =
|
|
28621
|
+
const dotGit = join70(cwd, ".git");
|
|
28475
28622
|
let stat2;
|
|
28476
28623
|
try {
|
|
28477
28624
|
stat2 = statSync11(dotGit);
|
|
@@ -28501,7 +28648,7 @@ function readGitBranch(cwd) {
|
|
|
28501
28648
|
}
|
|
28502
28649
|
let head;
|
|
28503
28650
|
try {
|
|
28504
|
-
head = readFileSync52(
|
|
28651
|
+
head = readFileSync52(join70(gitDir, "HEAD"), "utf8");
|
|
28505
28652
|
} catch {
|
|
28506
28653
|
return null;
|
|
28507
28654
|
}
|