@staff0rd/assist 0.774.1 → 0.775.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/dist/commands/sessions/web/bundle.js +448 -445
- package/dist/index.js +844 -696
- 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.775.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -10943,209 +10943,11 @@ function delay(ms) {
|
|
|
10943
10943
|
return new Promise((resolve28) => setTimeout(resolve28, ms));
|
|
10944
10944
|
}
|
|
10945
10945
|
|
|
10946
|
-
// src/commands/sessions/daemon/originForCwd.ts
|
|
10947
|
-
var cache = /* @__PURE__ */ new Map();
|
|
10948
|
-
function originResolutionForCwd(cwd) {
|
|
10949
|
-
if (!cwd) return void 0;
|
|
10950
|
-
const cached = cache.get(cwd);
|
|
10951
|
-
if (cached !== void 0) return { origin: cached, stable: true };
|
|
10952
|
-
const resolved = resolveCurrentOrigin(cwd);
|
|
10953
|
-
if (resolved.stable) cache.set(cwd, resolved.origin);
|
|
10954
|
-
return resolved;
|
|
10955
|
-
}
|
|
10956
|
-
function originForCwd(cwd) {
|
|
10957
|
-
return originResolutionForCwd(cwd)?.origin;
|
|
10958
|
-
}
|
|
10959
|
-
|
|
10960
|
-
// src/commands/sessions/daemon/repoDirExists.ts
|
|
10961
|
-
import { existsSync as existsSync31 } from "fs";
|
|
10962
|
-
function repoDirExists(cwd) {
|
|
10963
|
-
return existsSync31(cwd);
|
|
10964
|
-
}
|
|
10965
|
-
|
|
10966
|
-
// src/commands/sessions/daemon/worktree/git.ts
|
|
10967
|
-
import { execFile as execFile2, execFileSync as execFileSync2 } from "child_process";
|
|
10968
|
-
function isWindowsPath(cwd) {
|
|
10969
|
-
return /^[A-Za-z]:[\\/]/.test(cwd);
|
|
10970
|
-
}
|
|
10971
|
-
function gitInvocation(cwd, args) {
|
|
10972
|
-
const windows = isWindowsPath(cwd);
|
|
10973
|
-
return {
|
|
10974
|
-
file: windows ? "git.exe" : "git",
|
|
10975
|
-
argv: windows ? ["-C", cwd, ...args] : args,
|
|
10976
|
-
options: {
|
|
10977
|
-
encoding: "utf8",
|
|
10978
|
-
windowsHide: true,
|
|
10979
|
-
...windows ? {} : { cwd }
|
|
10980
|
-
}
|
|
10981
|
-
};
|
|
10982
|
-
}
|
|
10983
|
-
function git(cwd, args) {
|
|
10984
|
-
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
10985
|
-
return new Promise((resolve28, reject) => {
|
|
10986
|
-
execFile2(file, argv, options2, (error, stdout) => {
|
|
10987
|
-
if (error) reject(error);
|
|
10988
|
-
else resolve28(stdout.toString());
|
|
10989
|
-
});
|
|
10990
|
-
});
|
|
10991
|
-
}
|
|
10992
|
-
async function gitOrNull(cwd, args) {
|
|
10993
|
-
try {
|
|
10994
|
-
return (await git(cwd, args)).trim() || null;
|
|
10995
|
-
} catch {
|
|
10996
|
-
return null;
|
|
10997
|
-
}
|
|
10998
|
-
}
|
|
10999
|
-
async function gitResult(cwd, args) {
|
|
11000
|
-
try {
|
|
11001
|
-
return { ok: true, out: (await git(cwd, args)).trim() };
|
|
11002
|
-
} catch (error) {
|
|
11003
|
-
return {
|
|
11004
|
-
ok: false,
|
|
11005
|
-
error: error instanceof Error ? error.message : String(error)
|
|
11006
|
-
};
|
|
11007
|
-
}
|
|
11008
|
-
}
|
|
11009
|
-
function gitSyncResult(cwd, args) {
|
|
11010
|
-
try {
|
|
11011
|
-
return { ok: true, out: gitSync(cwd, args).trim() };
|
|
11012
|
-
} catch (error) {
|
|
11013
|
-
return {
|
|
11014
|
-
ok: false,
|
|
11015
|
-
error: error instanceof Error ? error.message : String(error)
|
|
11016
|
-
};
|
|
11017
|
-
}
|
|
11018
|
-
}
|
|
11019
|
-
function gitSync(cwd, args) {
|
|
11020
|
-
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
11021
|
-
return execFileSync2(file, argv, {
|
|
11022
|
-
...options2,
|
|
11023
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
11024
|
-
}).toString();
|
|
11025
|
-
}
|
|
11026
|
-
function gitSyncOrNull(cwd, args) {
|
|
11027
|
-
try {
|
|
11028
|
-
return gitSync(cwd, args).trim() || null;
|
|
11029
|
-
} catch {
|
|
11030
|
-
return null;
|
|
11031
|
-
}
|
|
11032
|
-
}
|
|
11033
|
-
|
|
11034
|
-
// src/commands/sessions/daemon/worktree/listWorktreePaths.ts
|
|
11035
|
-
function listWorktreePaths(cwd) {
|
|
11036
|
-
const out = gitSyncOrNull(cwd, ["worktree", "list", "--porcelain"]);
|
|
11037
|
-
if (!out) return [];
|
|
11038
|
-
return out.split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice("worktree ".length).trim());
|
|
11039
|
-
}
|
|
11040
|
-
function mainWorktree(cwd) {
|
|
11041
|
-
return listWorktreePaths(cwd)[0] ?? null;
|
|
11042
|
-
}
|
|
11043
|
-
function listLocalBranches(cwd) {
|
|
11044
|
-
const out = gitSyncOrNull(cwd, [
|
|
11045
|
-
"for-each-ref",
|
|
11046
|
-
"--format=%(refname:short)",
|
|
11047
|
-
"refs/heads"
|
|
11048
|
-
]);
|
|
11049
|
-
return out ? out.split("\n").map((line) => line.trim()) : [];
|
|
11050
|
-
}
|
|
11051
|
-
function gitCommonDir(cwd) {
|
|
11052
|
-
return gitSyncOrNull(cwd, [
|
|
11053
|
-
"rev-parse",
|
|
11054
|
-
"--path-format=absolute",
|
|
11055
|
-
"--git-common-dir"
|
|
11056
|
-
]);
|
|
11057
|
-
}
|
|
11058
|
-
|
|
11059
|
-
// src/shared/loadJson.ts
|
|
11060
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync21 } from "fs";
|
|
11061
|
-
import { homedir as homedir14 } from "os";
|
|
11062
|
-
import { join as join36 } from "path";
|
|
11063
|
-
function getStoreDir() {
|
|
11064
|
-
return process.env.ASSIST_STORE_DIR || join36(homedir14(), ".assist");
|
|
11065
|
-
}
|
|
11066
|
-
function getStorePath(filename) {
|
|
11067
|
-
return join36(getStoreDir(), filename);
|
|
11068
|
-
}
|
|
11069
|
-
function loadJson(filename) {
|
|
11070
|
-
const path106 = getStorePath(filename);
|
|
11071
|
-
if (existsSync32(path106)) {
|
|
11072
|
-
try {
|
|
11073
|
-
return JSON.parse(readFileSync20(path106, "utf8"));
|
|
11074
|
-
} catch {
|
|
11075
|
-
return {};
|
|
11076
|
-
}
|
|
11077
|
-
}
|
|
11078
|
-
return {};
|
|
11079
|
-
}
|
|
11080
|
-
function saveJson(filename, data) {
|
|
11081
|
-
const dir = getStoreDir();
|
|
11082
|
-
if (!existsSync32(dir)) {
|
|
11083
|
-
mkdirSync11(dir, { recursive: true });
|
|
11084
|
-
}
|
|
11085
|
-
writeFileSync21(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
11086
|
-
}
|
|
11087
|
-
|
|
11088
|
-
// src/commands/sessions/daemon/worktree/readWorktreeRegistry.ts
|
|
11089
|
-
var REGISTRY_FILE = "worktrees.json";
|
|
11090
|
-
function readWorktreeRegistry() {
|
|
11091
|
-
const data = loadJson(REGISTRY_FILE);
|
|
11092
|
-
return Object.entries(data).filter(([, record]) => !record.reaped).map(([path106, record]) => ({ path: path106, ...record }));
|
|
11093
|
-
}
|
|
11094
|
-
function worktreeAttributionIncludingReaped(path106) {
|
|
11095
|
-
const record = loadJson(REGISTRY_FILE)[path106];
|
|
11096
|
-
return record ? { clone: record.clone, origin: record.origin } : void 0;
|
|
11097
|
-
}
|
|
11098
|
-
function recordWorktree(path106, clone, origin) {
|
|
11099
|
-
const data = loadJson(REGISTRY_FILE);
|
|
11100
|
-
data[path106] = { clone, origin };
|
|
11101
|
-
saveJson(REGISTRY_FILE, data);
|
|
11102
|
-
}
|
|
11103
|
-
function forgetWorktree(path106) {
|
|
11104
|
-
const data = loadJson(REGISTRY_FILE);
|
|
11105
|
-
const record = data[path106];
|
|
11106
|
-
if (!record || record.reaped) return;
|
|
11107
|
-
data[path106] = { ...record, reaped: true };
|
|
11108
|
-
saveJson(REGISTRY_FILE, data);
|
|
11109
|
-
}
|
|
11110
|
-
|
|
11111
|
-
// src/commands/sessions/daemon/repoGroupForCwd.ts
|
|
11112
|
-
var cache2 = /* @__PURE__ */ new Map();
|
|
11113
|
-
function repoGroupForCwd(cwd) {
|
|
11114
|
-
if (!cwd) return void 0;
|
|
11115
|
-
if (cache2.has(cwd)) return cache2.get(cwd);
|
|
11116
|
-
const { group, stable } = resolveRepoGroup(cwd);
|
|
11117
|
-
if (stable) cache2.set(cwd, group);
|
|
11118
|
-
return group;
|
|
11119
|
-
}
|
|
11120
|
-
function resolveRepoGroup(cwd) {
|
|
11121
|
-
const clone = mainWorktree(cwd);
|
|
11122
|
-
const origin = clone ? originResolutionForCwd(clone) : void 0;
|
|
11123
|
-
if (clone && origin)
|
|
11124
|
-
return {
|
|
11125
|
-
group: hostedGroup(origin.origin, clone),
|
|
11126
|
-
stable: origin.stable
|
|
11127
|
-
};
|
|
11128
|
-
const reaped = worktreeAttributionIncludingReaped(cwd);
|
|
11129
|
-
if (!reaped) return { group: void 0, stable: repoDirExists(cwd) };
|
|
11130
|
-
const current = currentOriginOfClone(reaped.clone);
|
|
11131
|
-
return {
|
|
11132
|
-
group: hostedGroup(current?.origin ?? reaped.origin, reaped.clone),
|
|
11133
|
-
stable: current?.stable === true
|
|
11134
|
-
};
|
|
11135
|
-
}
|
|
11136
|
-
function currentOriginOfClone(clone) {
|
|
11137
|
-
const main = mainWorktree(clone);
|
|
11138
|
-
return main ? originResolutionForCwd(main) : void 0;
|
|
11139
|
-
}
|
|
11140
|
-
function hostedGroup(origin, clone) {
|
|
11141
|
-
return { origin, clone };
|
|
11142
|
-
}
|
|
11143
|
-
|
|
11144
10946
|
// src/commands/sessions/nodes/tailscaleStatus.ts
|
|
11145
|
-
import { execFile as
|
|
11146
|
-
import { existsSync as
|
|
10947
|
+
import { execFile as execFile2 } from "child_process";
|
|
10948
|
+
import { existsSync as existsSync31 } from "fs";
|
|
11147
10949
|
import { promisify as promisify2 } from "util";
|
|
11148
|
-
var execFileAsync2 = promisify2(
|
|
10950
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
11149
10951
|
var STATUS_TIMEOUT_MS = 1e4;
|
|
11150
10952
|
var INSTALLED_CLI = {
|
|
11151
10953
|
wsl: "/mnt/c/Program Files/Tailscale/tailscale.exe",
|
|
@@ -11155,7 +10957,7 @@ var INSTALLED_CLI = {
|
|
|
11155
10957
|
function tailscaleCli() {
|
|
11156
10958
|
const platform = detectPlatform();
|
|
11157
10959
|
const installed = INSTALLED_CLI[platform];
|
|
11158
|
-
if (installed &&
|
|
10960
|
+
if (installed && existsSync31(installed)) return installed;
|
|
11159
10961
|
return platform === "wsl" ? "tailscale.exe" : "tailscale";
|
|
11160
10962
|
}
|
|
11161
10963
|
async function tailscaleStatus() {
|
|
@@ -11214,9 +11016,9 @@ async function runningStatus(status2) {
|
|
|
11214
11016
|
}
|
|
11215
11017
|
|
|
11216
11018
|
// src/commands/sessions/nodes/runTailscale.ts
|
|
11217
|
-
import { execFile as
|
|
11019
|
+
import { execFile as execFile3 } from "child_process";
|
|
11218
11020
|
import { promisify as promisify3 } from "util";
|
|
11219
|
-
var execFileAsync3 = promisify3(
|
|
11021
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
11220
11022
|
async function runTailscale(args) {
|
|
11221
11023
|
const { stdout } = await execFileAsync3(tailscaleCli(), args, {
|
|
11222
11024
|
encoding: "utf8",
|
|
@@ -11433,16 +11235,16 @@ function attachSessionSocket(server, ctx) {
|
|
|
11433
11235
|
|
|
11434
11236
|
// src/shared/createBundleHandler.ts
|
|
11435
11237
|
import { createHash } from "crypto";
|
|
11436
|
-
import { readFileSync as
|
|
11437
|
-
import { dirname as dirname21, join as
|
|
11238
|
+
import { readFileSync as readFileSync20, statSync as statSync5 } from "fs";
|
|
11239
|
+
import { dirname as dirname21, join as join36 } from "path";
|
|
11438
11240
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
11439
11241
|
function createBundleHandler(importMetaUrl, bundlePath, contentType = "application/javascript") {
|
|
11440
|
-
const file =
|
|
11242
|
+
const file = join36(dirname21(fileURLToPath4(importMetaUrl)), bundlePath);
|
|
11441
11243
|
let cache6;
|
|
11442
11244
|
return (req, res) => {
|
|
11443
11245
|
const mtimeMs = statSync5(file).mtimeMs;
|
|
11444
11246
|
if (cache6?.mtimeMs !== mtimeMs) {
|
|
11445
|
-
const body =
|
|
11247
|
+
const body = readFileSync20(file, "utf8");
|
|
11446
11248
|
const etag = `"${createHash("sha256").update(body).digest("hex").slice(0, 16)}"`;
|
|
11447
11249
|
cache6 = { body, etag, mtimeMs };
|
|
11448
11250
|
}
|
|
@@ -11482,12 +11284,12 @@ function createFallbackHandler(routes3, htmlHandler2, extra) {
|
|
|
11482
11284
|
}
|
|
11483
11285
|
|
|
11484
11286
|
// src/commands/backlog/resolveRepoLocation.ts
|
|
11485
|
-
import { existsSync as
|
|
11287
|
+
import { existsSync as existsSync32 } from "fs";
|
|
11486
11288
|
function resolveRepoLocation(origin, knownCwd, baseDir) {
|
|
11487
11289
|
if (knownCwd) return { cwd: knownCwd };
|
|
11488
11290
|
const target = cloneTargetDir(origin, baseDir);
|
|
11489
11291
|
if (!target) return {};
|
|
11490
|
-
if (
|
|
11292
|
+
if (existsSync32(target) && getCurrentOrigin(target) === origin)
|
|
11491
11293
|
return { cwd: target };
|
|
11492
11294
|
return { cloneTarget: target };
|
|
11493
11295
|
}
|
|
@@ -11896,9 +11698,9 @@ function getSessionParam(req) {
|
|
|
11896
11698
|
}
|
|
11897
11699
|
|
|
11898
11700
|
// src/commands/sessions/web/execGit.ts
|
|
11899
|
-
import { execFile as
|
|
11701
|
+
import { execFile as execFile4 } from "child_process";
|
|
11900
11702
|
import { promisify as promisify4 } from "util";
|
|
11901
|
-
var execFileAsync4 = promisify4(
|
|
11703
|
+
var execFileAsync4 = promisify4(execFile4);
|
|
11902
11704
|
async function execGit(cwd, args, opts = {}) {
|
|
11903
11705
|
const { maxBuffer, allowFailure } = opts;
|
|
11904
11706
|
const { file, argv } = /^[A-Za-z]:[\\/]/.test(cwd) ? { file: "git.exe", argv: ["-C", cwd, ...args] } : { file: "git", argv: args };
|
|
@@ -12087,17 +11889,17 @@ async function commitPaths(cwd, sha) {
|
|
|
12087
11889
|
}
|
|
12088
11890
|
|
|
12089
11891
|
// src/commands/sessions/web/committedPaths.ts
|
|
12090
|
-
var
|
|
11892
|
+
var cache = /* @__PURE__ */ new Map();
|
|
12091
11893
|
var inFlight = /* @__PURE__ */ new Map();
|
|
12092
11894
|
var CACHE_TTL_MS = 1e4;
|
|
12093
11895
|
async function committedPaths(cwd, sessionId) {
|
|
12094
11896
|
const key = `${cwd} ${sessionId}`;
|
|
12095
|
-
const cached =
|
|
11897
|
+
const cached = cache.get(key);
|
|
12096
11898
|
if (cached && cached.expiresAt > Date.now()) return cached.value;
|
|
12097
11899
|
const pending = inFlight.get(key);
|
|
12098
11900
|
if (pending) return pending;
|
|
12099
11901
|
const lookup = loadCommittedPaths(cwd, sessionId).then((value) => {
|
|
12100
|
-
|
|
11902
|
+
cache.set(key, { value, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
12101
11903
|
return value;
|
|
12102
11904
|
}).finally(() => inFlight.delete(key));
|
|
12103
11905
|
inFlight.set(key, lookup);
|
|
@@ -13549,26 +13351,26 @@ function handleServerRuns(req, res) {
|
|
|
13549
13351
|
}
|
|
13550
13352
|
|
|
13551
13353
|
// src/commands/sessions/web/getReviewSynthesis.ts
|
|
13552
|
-
import { execFile as
|
|
13553
|
-
import { readFileSync as
|
|
13554
|
-
import { homedir as
|
|
13555
|
-
import { basename as basename11, join as
|
|
13354
|
+
import { execFile as execFile5 } from "child_process";
|
|
13355
|
+
import { readFileSync as readFileSync21 } from "fs";
|
|
13356
|
+
import { homedir as homedir14 } from "os";
|
|
13357
|
+
import { basename as basename11, join as join38 } from "path";
|
|
13556
13358
|
import { promisify as promisify5 } from "util";
|
|
13557
13359
|
|
|
13558
13360
|
// src/commands/sessions/web/findSynthesisForBranch.ts
|
|
13559
|
-
import { existsSync as
|
|
13560
|
-
import { basename as basename10, dirname as dirname22, join as
|
|
13361
|
+
import { existsSync as existsSync33, readdirSync as readdirSync5, statSync as statSync6 } from "fs";
|
|
13362
|
+
import { basename as basename10, dirname as dirname22, join as join37 } from "path";
|
|
13561
13363
|
function findSynthesisForBranch(repoReviewsDir, branch2) {
|
|
13562
|
-
const branchKeyPath =
|
|
13364
|
+
const branchKeyPath = join37(repoReviewsDir, `${branch2}-`);
|
|
13563
13365
|
const parent = dirname22(branchKeyPath);
|
|
13564
13366
|
const branchPrefix = basename10(branchKeyPath);
|
|
13565
|
-
if (!
|
|
13566
|
-
const synthesisFiles = readdirSync5(parent).filter((name) => name.startsWith(branchPrefix)).map((name) =>
|
|
13367
|
+
if (!existsSync33(parent)) return null;
|
|
13368
|
+
const synthesisFiles = readdirSync5(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join37(parent, name, "synthesis.md")).filter((path106) => existsSync33(path106)).map((path106) => ({ path: path106, mtime: statSync6(path106).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
13567
13369
|
return synthesisFiles[0]?.path ?? null;
|
|
13568
13370
|
}
|
|
13569
13371
|
|
|
13570
13372
|
// src/commands/sessions/web/getReviewSynthesis.ts
|
|
13571
|
-
var execFileAsync5 = promisify5(
|
|
13373
|
+
var execFileAsync5 = promisify5(execFile5);
|
|
13572
13374
|
function runGit2(cwd, args) {
|
|
13573
13375
|
return execFileAsync5("git", args, {
|
|
13574
13376
|
encoding: "utf8",
|
|
@@ -13581,8 +13383,8 @@ async function resolveSynthesisPath(cwd) {
|
|
|
13581
13383
|
runGit2(cwd, ["rev-parse", "--show-toplevel"]),
|
|
13582
13384
|
runGit2(cwd, ["rev-parse", "--abbrev-ref", "HEAD"])
|
|
13583
13385
|
]);
|
|
13584
|
-
const repoReviewsDir =
|
|
13585
|
-
|
|
13386
|
+
const repoReviewsDir = join38(
|
|
13387
|
+
homedir14(),
|
|
13586
13388
|
".assist",
|
|
13587
13389
|
"reviews",
|
|
13588
13390
|
basename11(repoRoot2)
|
|
@@ -13598,7 +13400,7 @@ async function getReviewSynthesis(req, res) {
|
|
|
13598
13400
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
13599
13401
|
return;
|
|
13600
13402
|
}
|
|
13601
|
-
respondJson(res, 200, { synthesis:
|
|
13403
|
+
respondJson(res, 200, { synthesis: readFileSync21(path106, "utf8") });
|
|
13602
13404
|
} catch {
|
|
13603
13405
|
respondJson(res, 404, { error: "No synthesis found" });
|
|
13604
13406
|
}
|
|
@@ -13621,7 +13423,7 @@ var EMPTY = {
|
|
|
13621
13423
|
defaultBranch: null,
|
|
13622
13424
|
onDefaultBranch: false
|
|
13623
13425
|
};
|
|
13624
|
-
var
|
|
13426
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
13625
13427
|
async function currentBranch2(cwd) {
|
|
13626
13428
|
try {
|
|
13627
13429
|
const branch2 = (await execGit(cwd, ["rev-parse", "--abbrev-ref", "HEAD"])).trim();
|
|
@@ -13644,7 +13446,7 @@ async function resolve11(cwd) {
|
|
|
13644
13446
|
}
|
|
13645
13447
|
async function gitBranchInfo(cwd) {
|
|
13646
13448
|
const now = Date.now();
|
|
13647
|
-
const cached =
|
|
13449
|
+
const cached = cache2.get(cwd);
|
|
13648
13450
|
if (cached && cached.expires > now) return cached.value;
|
|
13649
13451
|
let value = EMPTY;
|
|
13650
13452
|
try {
|
|
@@ -13652,7 +13454,7 @@ async function gitBranchInfo(cwd) {
|
|
|
13652
13454
|
} catch {
|
|
13653
13455
|
value = EMPTY;
|
|
13654
13456
|
}
|
|
13655
|
-
|
|
13457
|
+
cache2.set(cwd, { value, expires: now + CACHE_TTL_MS2 });
|
|
13656
13458
|
return value;
|
|
13657
13459
|
}
|
|
13658
13460
|
|
|
@@ -13808,10 +13610,10 @@ function protocolMismatched(msg) {
|
|
|
13808
13610
|
return typeof msg.protocol === "number" && msg.protocol !== PROTOCOL_VERSION;
|
|
13809
13611
|
}
|
|
13810
13612
|
|
|
13811
|
-
// src/commands/sessions/
|
|
13613
|
+
// src/commands/sessions/daemon/requestDaemonReply.ts
|
|
13812
13614
|
import { createInterface as createInterface5 } from "readline";
|
|
13813
13615
|
var QUERY_TIMEOUT_MS = 3e3;
|
|
13814
|
-
async function
|
|
13616
|
+
async function requestDaemonReply(request, replyType) {
|
|
13815
13617
|
let socket;
|
|
13816
13618
|
try {
|
|
13817
13619
|
socket = await connectToDaemon();
|
|
@@ -13831,16 +13633,21 @@ async function queryNodes() {
|
|
|
13831
13633
|
lines2.on("line", (line) => {
|
|
13832
13634
|
try {
|
|
13833
13635
|
const data = JSON.parse(line);
|
|
13834
|
-
if (data.type ===
|
|
13636
|
+
if (data.type === replyType) finish2(data);
|
|
13835
13637
|
} catch {
|
|
13836
13638
|
}
|
|
13837
13639
|
});
|
|
13838
13640
|
socket.on("error", () => finish2(void 0));
|
|
13839
|
-
socket.write(`${JSON.stringify(
|
|
13641
|
+
socket.write(`${JSON.stringify(request)}
|
|
13840
13642
|
`);
|
|
13841
13643
|
});
|
|
13842
13644
|
}
|
|
13843
13645
|
|
|
13646
|
+
// src/commands/sessions/nodes/queryNodes.ts
|
|
13647
|
+
function queryNodes() {
|
|
13648
|
+
return requestDaemonReply({ type: "nodes" }, "nodes");
|
|
13649
|
+
}
|
|
13650
|
+
|
|
13844
13651
|
// src/commands/sessions/web/health.ts
|
|
13845
13652
|
async function health(_req, res) {
|
|
13846
13653
|
const [reachable, nodes] = await Promise.all([
|
|
@@ -13871,6 +13678,35 @@ function hotkeyBindings(_req, res) {
|
|
|
13871
13678
|
respondJson(res, 200, resolveHotkeys(loadConfig().sessions?.hotkeys));
|
|
13872
13679
|
}
|
|
13873
13680
|
|
|
13681
|
+
// src/shared/loadJson.ts
|
|
13682
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync11, readFileSync as readFileSync22, writeFileSync as writeFileSync21 } from "fs";
|
|
13683
|
+
import { homedir as homedir15 } from "os";
|
|
13684
|
+
import { join as join39 } from "path";
|
|
13685
|
+
function getStoreDir() {
|
|
13686
|
+
return process.env.ASSIST_STORE_DIR || join39(homedir15(), ".assist");
|
|
13687
|
+
}
|
|
13688
|
+
function getStorePath(filename) {
|
|
13689
|
+
return join39(getStoreDir(), filename);
|
|
13690
|
+
}
|
|
13691
|
+
function loadJson(filename) {
|
|
13692
|
+
const path106 = getStorePath(filename);
|
|
13693
|
+
if (existsSync34(path106)) {
|
|
13694
|
+
try {
|
|
13695
|
+
return JSON.parse(readFileSync22(path106, "utf8"));
|
|
13696
|
+
} catch {
|
|
13697
|
+
return {};
|
|
13698
|
+
}
|
|
13699
|
+
}
|
|
13700
|
+
return {};
|
|
13701
|
+
}
|
|
13702
|
+
function saveJson(filename, data) {
|
|
13703
|
+
const dir = getStoreDir();
|
|
13704
|
+
if (!existsSync34(dir)) {
|
|
13705
|
+
mkdirSync11(dir, { recursive: true });
|
|
13706
|
+
}
|
|
13707
|
+
writeFileSync21(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
13708
|
+
}
|
|
13709
|
+
|
|
13874
13710
|
// src/commands/sessions/web/jiraSite.ts
|
|
13875
13711
|
function jiraSite(_req, res) {
|
|
13876
13712
|
const config = loadJson("jira.json");
|
|
@@ -14086,11 +13922,11 @@ function newsNavConfig(_req, res) {
|
|
|
14086
13922
|
}
|
|
14087
13923
|
|
|
14088
13924
|
// src/commands/sessions/web/releases/ghJson.ts
|
|
14089
|
-
import { execFile as
|
|
13925
|
+
import { execFile as execFile6 } from "child_process";
|
|
14090
13926
|
import { promisify as promisify6 } from "util";
|
|
14091
|
-
var execFileAsync6 = promisify6(
|
|
13927
|
+
var execFileAsync6 = promisify6(execFile6);
|
|
14092
13928
|
var CACHE_TTL_MS4 = 3e4;
|
|
14093
|
-
var
|
|
13929
|
+
var cache3 = /* @__PURE__ */ new Map();
|
|
14094
13930
|
function partialGraphqlData(error) {
|
|
14095
13931
|
const stdout = error.stdout;
|
|
14096
13932
|
if (typeof stdout !== "string") return null;
|
|
@@ -14118,12 +13954,12 @@ async function runGh(cwd, args) {
|
|
|
14118
13954
|
}
|
|
14119
13955
|
function ghJson(cwd, args) {
|
|
14120
13956
|
const key = [cwd, ...args].join("\0");
|
|
14121
|
-
const hit =
|
|
13957
|
+
const hit = cache3.get(key);
|
|
14122
13958
|
if (hit && Date.now() - hit.at < CACHE_TTL_MS4)
|
|
14123
13959
|
return hit.result;
|
|
14124
13960
|
const result = runGh(cwd, args);
|
|
14125
|
-
|
|
14126
|
-
result.catch(() =>
|
|
13961
|
+
cache3.set(key, { at: Date.now(), result });
|
|
13962
|
+
result.catch(() => cache3.delete(key));
|
|
14127
13963
|
return result;
|
|
14128
13964
|
}
|
|
14129
13965
|
|
|
@@ -14649,7 +14485,7 @@ function assertProjectScope() {
|
|
|
14649
14485
|
}
|
|
14650
14486
|
|
|
14651
14487
|
// src/commands/github/issue/assignIssueToSelf.ts
|
|
14652
|
-
import { execFileSync as
|
|
14488
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
14653
14489
|
function assignIssueToSelf(number, repo) {
|
|
14654
14490
|
const args = [
|
|
14655
14491
|
"issue",
|
|
@@ -14661,7 +14497,7 @@ function assignIssueToSelf(number, repo) {
|
|
|
14661
14497
|
"@me"
|
|
14662
14498
|
];
|
|
14663
14499
|
try {
|
|
14664
|
-
|
|
14500
|
+
execFileSync2("gh", args, {
|
|
14665
14501
|
stdio: ["ignore", "ignore", "pipe"],
|
|
14666
14502
|
encoding: "utf8"
|
|
14667
14503
|
});
|
|
@@ -14831,7 +14667,7 @@ async function nextPickup(req, res) {
|
|
|
14831
14667
|
import path27 from "path";
|
|
14832
14668
|
|
|
14833
14669
|
// src/commands/rules/readScopedRules.ts
|
|
14834
|
-
import { existsSync as
|
|
14670
|
+
import { existsSync as existsSync36, readFileSync as readFileSync23 } from "fs";
|
|
14835
14671
|
import path26 from "path";
|
|
14836
14672
|
|
|
14837
14673
|
// src/commands/rules/rulesSectionRange.ts
|
|
@@ -14867,24 +14703,24 @@ function parseRulesSection(content) {
|
|
|
14867
14703
|
const lines2 = content.split(/\r?\n/);
|
|
14868
14704
|
const range = rulesSectionRange(lines2);
|
|
14869
14705
|
if (!range) return [];
|
|
14870
|
-
const
|
|
14706
|
+
const rules2 = [];
|
|
14871
14707
|
for (const line of lines2.slice(range.start + 1, range.end)) {
|
|
14872
14708
|
const match = RULE_BULLET.exec(line);
|
|
14873
14709
|
if (!match) continue;
|
|
14874
14710
|
const code = match[1].trim();
|
|
14875
14711
|
const rest = match[2].trim();
|
|
14876
14712
|
if (code === "" || rest === "") continue;
|
|
14877
|
-
|
|
14713
|
+
rules2.push({ code, ...splitTitle(rest) });
|
|
14878
14714
|
}
|
|
14879
|
-
return
|
|
14715
|
+
return rules2;
|
|
14880
14716
|
}
|
|
14881
14717
|
|
|
14882
14718
|
// src/commands/rules/scopeDirectory.ts
|
|
14883
|
-
import { existsSync as
|
|
14719
|
+
import { existsSync as existsSync35, statSync as statSync7 } from "fs";
|
|
14884
14720
|
import path25 from "path";
|
|
14885
14721
|
function scopeDirectory(target) {
|
|
14886
14722
|
const resolved = path25.resolve(target);
|
|
14887
|
-
return
|
|
14723
|
+
return existsSync35(resolved) && statSync7(resolved).isDirectory() ? resolved : path25.dirname(resolved);
|
|
14888
14724
|
}
|
|
14889
14725
|
|
|
14890
14726
|
// src/commands/rules/readScopedRules.ts
|
|
@@ -14895,7 +14731,7 @@ function scopedClaudeFiles(target) {
|
|
|
14895
14731
|
let current = startDir;
|
|
14896
14732
|
while (true) {
|
|
14897
14733
|
const candidate = path26.join(current, "CLAUDE.md");
|
|
14898
|
-
if (
|
|
14734
|
+
if (existsSync36(candidate)) files.push(candidate);
|
|
14899
14735
|
if (current === root2 || current === path26.dirname(current)) break;
|
|
14900
14736
|
current = path26.dirname(current);
|
|
14901
14737
|
}
|
|
@@ -15206,9 +15042,9 @@ async function openInCode(req, res) {
|
|
|
15206
15042
|
}
|
|
15207
15043
|
|
|
15208
15044
|
// src/commands/sessions/web/createCachedGhJson.ts
|
|
15209
|
-
import { execFile as
|
|
15045
|
+
import { execFile as execFile7 } from "child_process";
|
|
15210
15046
|
import { promisify as promisify8 } from "util";
|
|
15211
|
-
var execFileAsync7 = promisify8(
|
|
15047
|
+
var execFileAsync7 = promisify8(execFile7);
|
|
15212
15048
|
var CACHE_TTL_MS5 = 3e4;
|
|
15213
15049
|
function createCachedGhJson(args, parse5, fallback, options2 = {}) {
|
|
15214
15050
|
const { cacheFallback = true } = options2;
|
|
@@ -15306,7 +15142,7 @@ function peerTimeoutFor(pathname) {
|
|
|
15306
15142
|
}
|
|
15307
15143
|
|
|
15308
15144
|
// src/commands/sessions/web/isQuietPoll.ts
|
|
15309
|
-
var POLLED_PATHS = /* @__PURE__ */ new Set(["/api/git-status"]);
|
|
15145
|
+
var POLLED_PATHS = /* @__PURE__ */ new Set(["/api/git-status", "/api/updates"]);
|
|
15310
15146
|
function isQuietPoll(pathname, status2) {
|
|
15311
15147
|
return POLLED_PATHS.has(pathname) && status2 >= 200 && status2 < 300;
|
|
15312
15148
|
}
|
|
@@ -15459,9 +15295,9 @@ async function previewImage(req, res) {
|
|
|
15459
15295
|
}
|
|
15460
15296
|
|
|
15461
15297
|
// src/commands/sessions/web/prStatus.ts
|
|
15462
|
-
import { execFile as
|
|
15298
|
+
import { execFile as execFile8 } from "child_process";
|
|
15463
15299
|
import { promisify as promisify9 } from "util";
|
|
15464
|
-
var execFileAsync8 = promisify9(
|
|
15300
|
+
var execFileAsync8 = promisify9(execFile8);
|
|
15465
15301
|
function toPrSummary(parsed) {
|
|
15466
15302
|
if (typeof parsed.number !== "number") return null;
|
|
15467
15303
|
return {
|
|
@@ -16070,19 +15906,19 @@ async function revertDiffFile(req, res) {
|
|
|
16070
15906
|
|
|
16071
15907
|
// src/commands/run/runCommandToCompletion.ts
|
|
16072
15908
|
import { spawn as spawn4 } from "child_process";
|
|
16073
|
-
import { existsSync as
|
|
15909
|
+
import { existsSync as existsSync38 } from "fs";
|
|
16074
15910
|
|
|
16075
15911
|
// src/commands/run/resolveCommand.ts
|
|
16076
|
-
import { execFileSync as
|
|
16077
|
-
import { existsSync as
|
|
15912
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
15913
|
+
import { existsSync as existsSync37 } from "fs";
|
|
16078
15914
|
import { dirname as dirname23, join as join40, resolve as resolve13 } from "path";
|
|
16079
15915
|
function resolveCommand(command) {
|
|
16080
15916
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
16081
15917
|
try {
|
|
16082
|
-
const gitPath =
|
|
15918
|
+
const gitPath = execFileSync3("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
16083
15919
|
const gitRoot = resolve13(dirname23(gitPath), "..");
|
|
16084
15920
|
const gitBash = join40(gitRoot, "bin", "bash.exe");
|
|
16085
|
-
if (
|
|
15921
|
+
if (existsSync37(gitBash)) return gitBash;
|
|
16086
15922
|
} catch {
|
|
16087
15923
|
return command;
|
|
16088
15924
|
}
|
|
@@ -16092,7 +15928,7 @@ function resolveCommand(command) {
|
|
|
16092
15928
|
// src/commands/run/runCommandToCompletion.ts
|
|
16093
15929
|
function runCommandToCompletion(command, args, env, cwd, quiet) {
|
|
16094
15930
|
return new Promise((resolveResult) => {
|
|
16095
|
-
if (cwd && !
|
|
15931
|
+
if (cwd && !existsSync38(cwd)) {
|
|
16096
15932
|
resolveResult({
|
|
16097
15933
|
kind: "failed",
|
|
16098
15934
|
message: `Failed to execute command: cwd ${cwd} does not exist`
|
|
@@ -16406,6 +16242,23 @@ function findTailscalePeer(status2, hostname2) {
|
|
|
16406
16242
|
);
|
|
16407
16243
|
}
|
|
16408
16244
|
|
|
16245
|
+
// src/commands/sessions/nodes/tailscaleCliFailure.ts
|
|
16246
|
+
function tailscaleCliFailure(error, cli) {
|
|
16247
|
+
const detail = describePeerError(error);
|
|
16248
|
+
const owner = /Tailscale already in use by (\S+?),/.exec(detail)?.[1];
|
|
16249
|
+
if (owner)
|
|
16250
|
+
return failed(
|
|
16251
|
+
"tailscale",
|
|
16252
|
+
`Tailscale on this node is signed in by Windows user ${owner}, so it is disconnected while another user is active`,
|
|
16253
|
+
`sign in to Windows as ${owner} and run \`${cli} up --unattended\` (or tick "Run unattended" in Tailscale's menu) so it stays connected for every user; otherwise sign ${owner} out and run \`${cli} up\` as this user`
|
|
16254
|
+
);
|
|
16255
|
+
return failed(
|
|
16256
|
+
"tailscale",
|
|
16257
|
+
detail,
|
|
16258
|
+
`\`${cli} status --json\` failed \u2014 install Tailscale on this node and sign in with \`${cli} up\``
|
|
16259
|
+
);
|
|
16260
|
+
}
|
|
16261
|
+
|
|
16409
16262
|
// src/commands/sessions/nodes/tailscaleHop.ts
|
|
16410
16263
|
async function tailscaleHop(spec, probes) {
|
|
16411
16264
|
const cli = tailscaleCli();
|
|
@@ -16413,11 +16266,7 @@ async function tailscaleHop(spec, probes) {
|
|
|
16413
16266
|
try {
|
|
16414
16267
|
status2 = await probes.tailscale();
|
|
16415
16268
|
} catch (error) {
|
|
16416
|
-
return
|
|
16417
|
-
"tailscale",
|
|
16418
|
-
describePeerError(error),
|
|
16419
|
-
`\`${cli} status --json\` failed \u2014 install Tailscale on this node and sign in with \`${cli} up\``
|
|
16420
|
-
);
|
|
16269
|
+
return tailscaleCliFailure(error, cli);
|
|
16421
16270
|
}
|
|
16422
16271
|
if (status2.BackendState !== "Running")
|
|
16423
16272
|
return failed(
|
|
@@ -16437,7 +16286,7 @@ async function tailscaleHop(spec, probes) {
|
|
|
16437
16286
|
return failed(
|
|
16438
16287
|
"tailscale",
|
|
16439
16288
|
`${hostname2} is offline in the tailnet`,
|
|
16440
|
-
`is ${spec.name}'s machine awake with Tailscale running and signed in
|
|
16289
|
+
`is ${spec.name}'s machine awake with Tailscale running and signed in? On Windows, Tailscale disconnects while a user other than the one who signed it in is active unless it runs unattended \u2014 run \`assist sessions nodes doctor\` on ${spec.name}`
|
|
16441
16290
|
);
|
|
16442
16291
|
return passed(
|
|
16443
16292
|
"tailscale",
|
|
@@ -17164,6 +17013,194 @@ function unsetConfig(req, res) {
|
|
|
17164
17013
|
});
|
|
17165
17014
|
}
|
|
17166
17015
|
|
|
17016
|
+
// src/commands/watch/resolveUpstream.ts
|
|
17017
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
17018
|
+
function runGit3(args, cwd) {
|
|
17019
|
+
return execFileSync4("git", args, {
|
|
17020
|
+
encoding: "utf8",
|
|
17021
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
17022
|
+
cwd
|
|
17023
|
+
}).trim();
|
|
17024
|
+
}
|
|
17025
|
+
function resolveUpstream(cwd) {
|
|
17026
|
+
try {
|
|
17027
|
+
runGit3(["rev-parse", "--is-inside-work-tree"], cwd);
|
|
17028
|
+
} catch {
|
|
17029
|
+
throw new Error(
|
|
17030
|
+
"not a git repository \u2014 run assist watch wait from inside a repo"
|
|
17031
|
+
);
|
|
17032
|
+
}
|
|
17033
|
+
let branch2;
|
|
17034
|
+
try {
|
|
17035
|
+
branch2 = runGit3(["symbolic-ref", "--quiet", "--short", "HEAD"], cwd);
|
|
17036
|
+
} catch {
|
|
17037
|
+
throw new Error(
|
|
17038
|
+
"HEAD is detached \u2014 check out a branch before waiting on its upstream"
|
|
17039
|
+
);
|
|
17040
|
+
}
|
|
17041
|
+
try {
|
|
17042
|
+
return {
|
|
17043
|
+
branch: branch2,
|
|
17044
|
+
upstream: runGit3(
|
|
17045
|
+
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
17046
|
+
cwd
|
|
17047
|
+
)
|
|
17048
|
+
};
|
|
17049
|
+
} catch {
|
|
17050
|
+
throw new Error(
|
|
17051
|
+
`branch "${branch2}" has no upstream \u2014 set one with: git push -u origin ${branch2}`
|
|
17052
|
+
);
|
|
17053
|
+
}
|
|
17054
|
+
}
|
|
17055
|
+
|
|
17056
|
+
// src/commands/watch/changedPaths.ts
|
|
17057
|
+
function changedPaths(from, cwd) {
|
|
17058
|
+
return runGit3(["diff", "--name-only", `${from}..HEAD`], cwd).split("\n").filter((line) => line.length > 0);
|
|
17059
|
+
}
|
|
17060
|
+
|
|
17061
|
+
// src/commands/watch/readBuiltVersion.ts
|
|
17062
|
+
import { join as join41 } from "path";
|
|
17063
|
+
function readBuiltVersion(cwd) {
|
|
17064
|
+
try {
|
|
17065
|
+
const root2 = runGit3(["rev-parse", "--show-toplevel"], cwd);
|
|
17066
|
+
return readPackageJson(join41(root2, "package.json")).version ?? "unknown";
|
|
17067
|
+
} catch {
|
|
17068
|
+
return "unknown";
|
|
17069
|
+
}
|
|
17070
|
+
}
|
|
17071
|
+
|
|
17072
|
+
// src/commands/watch/restartRules.ts
|
|
17073
|
+
var webUiPrefix = "src/commands/sessions/web/ui/";
|
|
17074
|
+
var sessionsPrefix = "src/commands/sessions/";
|
|
17075
|
+
var restartRules = [
|
|
17076
|
+
{
|
|
17077
|
+
target: "webserver",
|
|
17078
|
+
matches: (path106) => path106.startsWith(webUiPrefix),
|
|
17079
|
+
advice: "restart the web server, then hard-reload the browser tab"
|
|
17080
|
+
},
|
|
17081
|
+
{
|
|
17082
|
+
target: "daemon",
|
|
17083
|
+
matches: (path106) => path106.startsWith(sessionsPrefix) && !path106.startsWith(webUiPrefix),
|
|
17084
|
+
advice: "restart the daemon"
|
|
17085
|
+
}
|
|
17086
|
+
];
|
|
17087
|
+
|
|
17088
|
+
// src/commands/watch/restartTargets.ts
|
|
17089
|
+
function restartTargets(paths) {
|
|
17090
|
+
return restartRules.filter((rule) => paths.some(rule.matches)).map((rule) => rule.target);
|
|
17091
|
+
}
|
|
17092
|
+
|
|
17093
|
+
// src/commands/sessions/web/updates/pendingRestarts.ts
|
|
17094
|
+
function targetsSince(commit2, target, changedSince2) {
|
|
17095
|
+
return commit2 !== void 0 && restartTargets(changedSince2(commit2)).includes(target);
|
|
17096
|
+
}
|
|
17097
|
+
function pendingRestarts(input) {
|
|
17098
|
+
const { daemonVersion, built, changedSince: changedSince2 } = input;
|
|
17099
|
+
const daemon = daemonVersion !== void 0 && (built !== "unknown" && daemonVersion !== built || targetsSince(input.daemonStartCommit, "daemon", changedSince2));
|
|
17100
|
+
const web3 = targetsSince(input.webStartCommit, "webserver", changedSince2);
|
|
17101
|
+
return [
|
|
17102
|
+
...daemon ? ["daemon"] : [],
|
|
17103
|
+
...web3 ? ["webserver"] : []
|
|
17104
|
+
];
|
|
17105
|
+
}
|
|
17106
|
+
|
|
17107
|
+
// src/shared/stripAnsi.ts
|
|
17108
|
+
var ANSI = new RegExp(
|
|
17109
|
+
`${String.fromCharCode(27)}\\[[0-9;?]*[ -/]*[@-~]`,
|
|
17110
|
+
"g"
|
|
17111
|
+
);
|
|
17112
|
+
function stripAnsi(text17) {
|
|
17113
|
+
return text17.replace(ANSI, "");
|
|
17114
|
+
}
|
|
17115
|
+
|
|
17116
|
+
// src/commands/sessions/daemon/worktree/watcherLogPath.ts
|
|
17117
|
+
import { createHash as createHash2 } from "crypto";
|
|
17118
|
+
import { homedir as homedir16 } from "os";
|
|
17119
|
+
import { basename as basename12, join as join42 } from "path";
|
|
17120
|
+
|
|
17121
|
+
// src/commands/sessions/daemon/worktree/canonicalTreePath.ts
|
|
17122
|
+
import { realpathSync as realpathSync2 } from "fs";
|
|
17123
|
+
import { resolve as resolve14 } from "path";
|
|
17124
|
+
function canonicalTreePath(path106) {
|
|
17125
|
+
try {
|
|
17126
|
+
return realpathSync2(path106);
|
|
17127
|
+
} catch {
|
|
17128
|
+
return resolve14(path106);
|
|
17129
|
+
}
|
|
17130
|
+
}
|
|
17131
|
+
|
|
17132
|
+
// src/commands/sessions/daemon/worktree/watcherLogPath.ts
|
|
17133
|
+
function watcherLogPath(cwd) {
|
|
17134
|
+
const clone = canonicalTreePath(cwd);
|
|
17135
|
+
const key = createHash2("sha1").update(clone).digest("hex").slice(0, 8);
|
|
17136
|
+
const dir = process.env.ASSIST_WATCHER_LOG_DIR ?? join42(homedir16(), ".assist", "watchers");
|
|
17137
|
+
return join42(dir, `${basename12(clone) || "root"}-${key}.log`);
|
|
17138
|
+
}
|
|
17139
|
+
|
|
17140
|
+
// src/commands/sessions/web/updates/readUpdateHistory.ts
|
|
17141
|
+
var HISTORY_LINES = 200;
|
|
17142
|
+
function readUpdateHistory(installDir) {
|
|
17143
|
+
return readLogTail(watcherLogPath(installDir), HISTORY_LINES * 2).flatMap((line) => line.split("\r")).map((line) => stripAnsi(line).trimEnd()).filter((line) => line.trim().length > 0).slice(-HISTORY_LINES);
|
|
17144
|
+
}
|
|
17145
|
+
|
|
17146
|
+
// src/commands/watch/headCommit.ts
|
|
17147
|
+
function headCommit3(cwd) {
|
|
17148
|
+
try {
|
|
17149
|
+
return runGit3(["rev-parse", "HEAD"], cwd);
|
|
17150
|
+
} catch {
|
|
17151
|
+
return void 0;
|
|
17152
|
+
}
|
|
17153
|
+
}
|
|
17154
|
+
|
|
17155
|
+
// src/commands/sessions/web/updates/webStartCommit.ts
|
|
17156
|
+
var captured;
|
|
17157
|
+
var webStartCommit = {
|
|
17158
|
+
capture: () => {
|
|
17159
|
+
captured = headCommit3(getInstallDir());
|
|
17160
|
+
},
|
|
17161
|
+
value: () => captured
|
|
17162
|
+
};
|
|
17163
|
+
|
|
17164
|
+
// src/commands/sessions/web/updates/updates.ts
|
|
17165
|
+
function changedSince(installDir) {
|
|
17166
|
+
return (commit2) => {
|
|
17167
|
+
try {
|
|
17168
|
+
return changedPaths(commit2, installDir);
|
|
17169
|
+
} catch {
|
|
17170
|
+
return [];
|
|
17171
|
+
}
|
|
17172
|
+
};
|
|
17173
|
+
}
|
|
17174
|
+
async function updates(_req, res) {
|
|
17175
|
+
const installDir = getInstallDir();
|
|
17176
|
+
const reply2 = await requestDaemonReply(
|
|
17177
|
+
{ type: "auto-update" },
|
|
17178
|
+
"auto-update"
|
|
17179
|
+
);
|
|
17180
|
+
const built = readBuiltVersion(installDir);
|
|
17181
|
+
const status2 = {
|
|
17182
|
+
nodeName: resolveNodeName(),
|
|
17183
|
+
installDir,
|
|
17184
|
+
running: reply2?.version ?? ASSIST_VERSION,
|
|
17185
|
+
built,
|
|
17186
|
+
restart: pendingRestarts({
|
|
17187
|
+
daemonVersion: reply2?.version,
|
|
17188
|
+
daemonStartCommit: reply2?.startCommit,
|
|
17189
|
+
webStartCommit: webStartCommit.value(),
|
|
17190
|
+
built,
|
|
17191
|
+
changedSince: changedSince(installDir)
|
|
17192
|
+
}),
|
|
17193
|
+
daemonReachable: reply2 !== void 0,
|
|
17194
|
+
loop: reply2?.loop ?? {
|
|
17195
|
+
phase: "off",
|
|
17196
|
+
since: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17197
|
+
reason: "daemon not reachable"
|
|
17198
|
+
},
|
|
17199
|
+
history: readUpdateHistory(installDir)
|
|
17200
|
+
};
|
|
17201
|
+
respondJson(res, 200, status2);
|
|
17202
|
+
}
|
|
17203
|
+
|
|
17167
17204
|
// src/commands/sessions/web/readRequestBuffer.ts
|
|
17168
17205
|
async function readRequestBuffer(req, limit) {
|
|
17169
17206
|
const chunks = [];
|
|
@@ -17185,7 +17222,7 @@ async function readRequestBuffer(req, limit) {
|
|
|
17185
17222
|
|
|
17186
17223
|
// src/commands/sessions/web/stageAttachment.ts
|
|
17187
17224
|
import { mkdir as mkdir4, mkdtemp, writeFile as writeFile2 } from "fs/promises";
|
|
17188
|
-
import { extname as extname2, join as
|
|
17225
|
+
import { extname as extname2, join as join43 } from "path";
|
|
17189
17226
|
function extensionFromMime(contentType) {
|
|
17190
17227
|
const mime = contentType.split(";")[0].trim().toLowerCase();
|
|
17191
17228
|
const known = attachmentMimeTypes[mime];
|
|
@@ -17213,9 +17250,9 @@ function safeBaseName(name) {
|
|
|
17213
17250
|
async function stageAttachment(name, contentType, body) {
|
|
17214
17251
|
const ext = pickExtension(name, contentType);
|
|
17215
17252
|
await mkdir4(stagedAttachmentsDir, { recursive: true });
|
|
17216
|
-
const dir = await mkdtemp(
|
|
17253
|
+
const dir = await mkdtemp(join43(stagedAttachmentsDir, "upload-"));
|
|
17217
17254
|
const alt = safeBaseName(name);
|
|
17218
|
-
const filePath =
|
|
17255
|
+
const filePath = join43(dir, `${alt}.${ext}`);
|
|
17219
17256
|
await writeFile2(filePath, body);
|
|
17220
17257
|
return { dir, filePath, alt };
|
|
17221
17258
|
}
|
|
@@ -17263,17 +17300,17 @@ async function uploadPrImage(req, res) {
|
|
|
17263
17300
|
import { readFile as readFile3, stat as stat4, writeFile as writeFile3 } from "fs/promises";
|
|
17264
17301
|
|
|
17265
17302
|
// src/commands/sessions/web/formatWithOxfmt.ts
|
|
17266
|
-
import { execFile as
|
|
17267
|
-
import { existsSync as
|
|
17268
|
-
import { dirname as dirname24, join as
|
|
17303
|
+
import { execFile as execFile9 } from "child_process";
|
|
17304
|
+
import { existsSync as existsSync39 } from "fs";
|
|
17305
|
+
import { dirname as dirname24, join as join44 } from "path";
|
|
17269
17306
|
import { promisify as promisify10 } from "util";
|
|
17270
|
-
var execFileAsync9 = promisify10(
|
|
17307
|
+
var execFileAsync9 = promisify10(execFile9);
|
|
17271
17308
|
var TIMEOUT_MS = 15e3;
|
|
17272
17309
|
function findOxfmtScript(root2) {
|
|
17273
17310
|
let dir = root2;
|
|
17274
17311
|
for (; ; ) {
|
|
17275
|
-
const candidate =
|
|
17276
|
-
if (
|
|
17312
|
+
const candidate = join44(dir, "node_modules", "oxfmt", "bin", "oxfmt");
|
|
17313
|
+
if (existsSync39(candidate)) return candidate;
|
|
17277
17314
|
const parent = dirname24(dir);
|
|
17278
17315
|
if (parent === dir) return void 0;
|
|
17279
17316
|
dir = parent;
|
|
@@ -17343,7 +17380,7 @@ async function writeFileContent(req, res) {
|
|
|
17343
17380
|
}
|
|
17344
17381
|
|
|
17345
17382
|
// src/commands/sessions/web/createCssHandler.ts
|
|
17346
|
-
import { createHash as
|
|
17383
|
+
import { createHash as createHash3 } from "crypto";
|
|
17347
17384
|
import { readFileSync as readFileSync24 } from "fs";
|
|
17348
17385
|
import { createRequire } from "module";
|
|
17349
17386
|
var require2 = createRequire(import.meta.url);
|
|
@@ -17353,7 +17390,7 @@ function createCssHandler(packageEntry) {
|
|
|
17353
17390
|
if (!cache6) {
|
|
17354
17391
|
const resolved = require2.resolve(packageEntry);
|
|
17355
17392
|
const body = readFileSync24(resolved, "utf8");
|
|
17356
|
-
const etag = `"${
|
|
17393
|
+
const etag = `"${createHash3("sha256").update(body).digest("hex").slice(0, 16)}"`;
|
|
17357
17394
|
cache6 = { body, etag };
|
|
17358
17395
|
}
|
|
17359
17396
|
const headers = { ETag: cache6.etag, "Cache-Control": "no-cache" };
|
|
@@ -17436,7 +17473,8 @@ var routes2 = {
|
|
|
17436
17473
|
"GET /api/config": getConfig,
|
|
17437
17474
|
"POST /api/config/set": setConfig,
|
|
17438
17475
|
"POST /api/config/unset": unsetConfig,
|
|
17439
|
-
"GET /api/review/synthesis": getReviewSynthesis
|
|
17476
|
+
"GET /api/review/synthesis": getReviewSynthesis,
|
|
17477
|
+
"GET /api/updates": updates
|
|
17440
17478
|
};
|
|
17441
17479
|
var handleRequest = createFallbackHandler(
|
|
17442
17480
|
routes2,
|
|
@@ -17705,11 +17743,183 @@ function scheduleReconnect() {
|
|
|
17705
17743
|
setTimeout(() => void connect2(), RECONNECT_MS).unref();
|
|
17706
17744
|
}
|
|
17707
17745
|
|
|
17708
|
-
// src/commands/sessions/
|
|
17746
|
+
// src/commands/sessions/daemon/originForCwd.ts
|
|
17747
|
+
var cache4 = /* @__PURE__ */ new Map();
|
|
17748
|
+
function originResolutionForCwd(cwd) {
|
|
17749
|
+
if (!cwd) return void 0;
|
|
17750
|
+
const cached = cache4.get(cwd);
|
|
17751
|
+
if (cached !== void 0) return { origin: cached, stable: true };
|
|
17752
|
+
const resolved = resolveCurrentOrigin(cwd);
|
|
17753
|
+
if (resolved.stable) cache4.set(cwd, resolved.origin);
|
|
17754
|
+
return resolved;
|
|
17755
|
+
}
|
|
17756
|
+
function originForCwd(cwd) {
|
|
17757
|
+
return originResolutionForCwd(cwd)?.origin;
|
|
17758
|
+
}
|
|
17759
|
+
|
|
17760
|
+
// src/commands/sessions/daemon/repoDirExists.ts
|
|
17761
|
+
import { existsSync as existsSync40 } from "fs";
|
|
17762
|
+
function repoDirExists(cwd) {
|
|
17763
|
+
return existsSync40(cwd);
|
|
17764
|
+
}
|
|
17765
|
+
|
|
17766
|
+
// src/commands/sessions/daemon/worktree/git.ts
|
|
17767
|
+
import { execFile as execFile10, execFileSync as execFileSync5 } from "child_process";
|
|
17768
|
+
function isWindowsPath(cwd) {
|
|
17769
|
+
return /^[A-Za-z]:[\\/]/.test(cwd);
|
|
17770
|
+
}
|
|
17771
|
+
function gitInvocation(cwd, args) {
|
|
17772
|
+
const windows = isWindowsPath(cwd);
|
|
17773
|
+
return {
|
|
17774
|
+
file: windows ? "git.exe" : "git",
|
|
17775
|
+
argv: windows ? ["-C", cwd, ...args] : args,
|
|
17776
|
+
options: {
|
|
17777
|
+
encoding: "utf8",
|
|
17778
|
+
windowsHide: true,
|
|
17779
|
+
...windows ? {} : { cwd }
|
|
17780
|
+
}
|
|
17781
|
+
};
|
|
17782
|
+
}
|
|
17783
|
+
function git(cwd, args) {
|
|
17784
|
+
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
17785
|
+
return new Promise((resolve28, reject) => {
|
|
17786
|
+
execFile10(file, argv, options2, (error, stdout) => {
|
|
17787
|
+
if (error) reject(error);
|
|
17788
|
+
else resolve28(stdout.toString());
|
|
17789
|
+
});
|
|
17790
|
+
});
|
|
17791
|
+
}
|
|
17792
|
+
async function gitOrNull(cwd, args) {
|
|
17793
|
+
try {
|
|
17794
|
+
return (await git(cwd, args)).trim() || null;
|
|
17795
|
+
} catch {
|
|
17796
|
+
return null;
|
|
17797
|
+
}
|
|
17798
|
+
}
|
|
17799
|
+
async function gitResult(cwd, args) {
|
|
17800
|
+
try {
|
|
17801
|
+
return { ok: true, out: (await git(cwd, args)).trim() };
|
|
17802
|
+
} catch (error) {
|
|
17803
|
+
return {
|
|
17804
|
+
ok: false,
|
|
17805
|
+
error: error instanceof Error ? error.message : String(error)
|
|
17806
|
+
};
|
|
17807
|
+
}
|
|
17808
|
+
}
|
|
17809
|
+
function gitSyncResult(cwd, args) {
|
|
17810
|
+
try {
|
|
17811
|
+
return { ok: true, out: gitSync(cwd, args).trim() };
|
|
17812
|
+
} catch (error) {
|
|
17813
|
+
return {
|
|
17814
|
+
ok: false,
|
|
17815
|
+
error: error instanceof Error ? error.message : String(error)
|
|
17816
|
+
};
|
|
17817
|
+
}
|
|
17818
|
+
}
|
|
17819
|
+
function gitSync(cwd, args) {
|
|
17820
|
+
const { file, argv, options: options2 } = gitInvocation(cwd, args);
|
|
17821
|
+
return execFileSync5(file, argv, {
|
|
17822
|
+
...options2,
|
|
17823
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
17824
|
+
}).toString();
|
|
17825
|
+
}
|
|
17826
|
+
function gitSyncOrNull(cwd, args) {
|
|
17827
|
+
try {
|
|
17828
|
+
return gitSync(cwd, args).trim() || null;
|
|
17829
|
+
} catch {
|
|
17830
|
+
return null;
|
|
17831
|
+
}
|
|
17832
|
+
}
|
|
17833
|
+
|
|
17834
|
+
// src/commands/sessions/daemon/worktree/listWorktreePaths.ts
|
|
17835
|
+
function listWorktreePaths(cwd) {
|
|
17836
|
+
const out = gitSyncOrNull(cwd, ["worktree", "list", "--porcelain"]);
|
|
17837
|
+
if (!out) return [];
|
|
17838
|
+
return out.split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice("worktree ".length).trim());
|
|
17839
|
+
}
|
|
17840
|
+
function mainWorktree(cwd) {
|
|
17841
|
+
return listWorktreePaths(cwd)[0] ?? null;
|
|
17842
|
+
}
|
|
17843
|
+
function listLocalBranches(cwd) {
|
|
17844
|
+
const out = gitSyncOrNull(cwd, [
|
|
17845
|
+
"for-each-ref",
|
|
17846
|
+
"--format=%(refname:short)",
|
|
17847
|
+
"refs/heads"
|
|
17848
|
+
]);
|
|
17849
|
+
return out ? out.split("\n").map((line) => line.trim()) : [];
|
|
17850
|
+
}
|
|
17851
|
+
function gitCommonDir(cwd) {
|
|
17852
|
+
return gitSyncOrNull(cwd, [
|
|
17853
|
+
"rev-parse",
|
|
17854
|
+
"--path-format=absolute",
|
|
17855
|
+
"--git-common-dir"
|
|
17856
|
+
]);
|
|
17857
|
+
}
|
|
17858
|
+
|
|
17859
|
+
// src/commands/sessions/daemon/worktree/readWorktreeRegistry.ts
|
|
17860
|
+
var REGISTRY_FILE = "worktrees.json";
|
|
17861
|
+
function readWorktreeRegistry() {
|
|
17862
|
+
const data = loadJson(REGISTRY_FILE);
|
|
17863
|
+
return Object.entries(data).filter(([, record]) => !record.reaped).map(([path106, record]) => ({ path: path106, ...record }));
|
|
17864
|
+
}
|
|
17865
|
+
function worktreeAttributionIncludingReaped(path106) {
|
|
17866
|
+
const record = loadJson(REGISTRY_FILE)[path106];
|
|
17867
|
+
return record ? { clone: record.clone, origin: record.origin } : void 0;
|
|
17868
|
+
}
|
|
17869
|
+
function recordWorktree(path106, clone, origin) {
|
|
17870
|
+
const data = loadJson(REGISTRY_FILE);
|
|
17871
|
+
data[path106] = { clone, origin };
|
|
17872
|
+
saveJson(REGISTRY_FILE, data);
|
|
17873
|
+
}
|
|
17874
|
+
function forgetWorktree(path106) {
|
|
17875
|
+
const data = loadJson(REGISTRY_FILE);
|
|
17876
|
+
const record = data[path106];
|
|
17877
|
+
if (!record || record.reaped) return;
|
|
17878
|
+
data[path106] = { ...record, reaped: true };
|
|
17879
|
+
saveJson(REGISTRY_FILE, data);
|
|
17880
|
+
}
|
|
17881
|
+
|
|
17882
|
+
// src/commands/sessions/daemon/repoGroupForCwd.ts
|
|
17883
|
+
var cache5 = /* @__PURE__ */ new Map();
|
|
17884
|
+
function repoGroupForCwd(cwd) {
|
|
17885
|
+
if (!cwd) return void 0;
|
|
17886
|
+
if (cache5.has(cwd)) return cache5.get(cwd);
|
|
17887
|
+
const { group, stable } = resolveRepoGroup(cwd);
|
|
17888
|
+
if (stable) cache5.set(cwd, group);
|
|
17889
|
+
return group;
|
|
17890
|
+
}
|
|
17891
|
+
function resolveRepoGroup(cwd) {
|
|
17892
|
+
const clone = mainWorktree(cwd);
|
|
17893
|
+
const origin = clone ? originResolutionForCwd(clone) : void 0;
|
|
17894
|
+
if (clone && origin)
|
|
17895
|
+
return {
|
|
17896
|
+
group: hostedGroup(origin.origin, clone),
|
|
17897
|
+
stable: origin.stable
|
|
17898
|
+
};
|
|
17899
|
+
const reaped = worktreeAttributionIncludingReaped(cwd);
|
|
17900
|
+
if (!reaped) return { group: void 0, stable: repoDirExists(cwd) };
|
|
17901
|
+
const current = currentOriginOfClone(reaped.clone);
|
|
17902
|
+
return {
|
|
17903
|
+
group: hostedGroup(current?.origin ?? reaped.origin, reaped.clone),
|
|
17904
|
+
stable: current?.stable === true
|
|
17905
|
+
};
|
|
17906
|
+
}
|
|
17907
|
+
function currentOriginOfClone(clone) {
|
|
17908
|
+
const main = mainWorktree(clone);
|
|
17909
|
+
return main ? originResolutionForCwd(main) : void 0;
|
|
17910
|
+
}
|
|
17911
|
+
function hostedGroup(origin, clone) {
|
|
17912
|
+
return { origin, clone };
|
|
17913
|
+
}
|
|
17914
|
+
|
|
17915
|
+
// src/commands/sessions/repoEntryCwd.ts
|
|
17709
17916
|
function repoEntryCwd(serverCwd) {
|
|
17710
17917
|
return repoGroupForCwd(serverCwd)?.clone ?? serverCwd;
|
|
17711
17918
|
}
|
|
17919
|
+
|
|
17920
|
+
// src/commands/sessions/web.ts
|
|
17712
17921
|
async function web(options2) {
|
|
17922
|
+
webStartCommit.capture();
|
|
17713
17923
|
const port = Number.parseInt(options2.port, 10);
|
|
17714
17924
|
const server = startWebServer(
|
|
17715
17925
|
"Assist",
|
|
@@ -18115,7 +18325,7 @@ function registerBranch(program2) {
|
|
|
18115
18325
|
}
|
|
18116
18326
|
|
|
18117
18327
|
// src/commands/cliHook.ts
|
|
18118
|
-
import { basename as
|
|
18328
|
+
import { basename as basename13 } from "path";
|
|
18119
18329
|
|
|
18120
18330
|
// src/shared/splitCompound.ts
|
|
18121
18331
|
import { parse } from "shell-quote";
|
|
@@ -18691,7 +18901,7 @@ function findTruncatedReadDenyRaw(rawCommand) {
|
|
|
18691
18901
|
}
|
|
18692
18902
|
|
|
18693
18903
|
// src/shared/isApprovedRead.ts
|
|
18694
|
-
import { resolve as
|
|
18904
|
+
import { resolve as resolve16, sep as sep2 } from "path";
|
|
18695
18905
|
|
|
18696
18906
|
// src/shared/appliesFixStructure.ts
|
|
18697
18907
|
var APPLY_RE = /^assist\s+github\s+issue\s+fix-structure\b.*\s--apply\b/;
|
|
@@ -18745,7 +18955,7 @@ function extractGraphqlQuery(args) {
|
|
|
18745
18955
|
|
|
18746
18956
|
// src/shared/loadCliReads.ts
|
|
18747
18957
|
import { existsSync as existsSync41, readFileSync as readFileSync26, writeFileSync as writeFileSync22 } from "fs";
|
|
18748
|
-
import { dirname as dirname25, resolve as
|
|
18958
|
+
import { dirname as dirname25, resolve as resolve15 } from "path";
|
|
18749
18959
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
18750
18960
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
18751
18961
|
var __dirname4 = dirname25(__filename3);
|
|
@@ -18760,13 +18970,13 @@ var cachedReads;
|
|
|
18760
18970
|
var cachedWrites;
|
|
18761
18971
|
function getCliReadsLines() {
|
|
18762
18972
|
if (!cachedReads) {
|
|
18763
|
-
cachedReads = readLines(
|
|
18973
|
+
cachedReads = readLines(resolve15(packageRoot(), "allowed.cli-reads"));
|
|
18764
18974
|
}
|
|
18765
18975
|
return cachedReads;
|
|
18766
18976
|
}
|
|
18767
18977
|
function getCliWritesLines() {
|
|
18768
18978
|
if (!cachedWrites) {
|
|
18769
|
-
cachedWrites = readLines(
|
|
18979
|
+
cachedWrites = readLines(resolve15(packageRoot(), "allowed.cli-writes"));
|
|
18770
18980
|
}
|
|
18771
18981
|
return cachedWrites;
|
|
18772
18982
|
}
|
|
@@ -18775,7 +18985,7 @@ function loadCliReads() {
|
|
|
18775
18985
|
}
|
|
18776
18986
|
function saveCliReads(commands) {
|
|
18777
18987
|
writeFileSync22(
|
|
18778
|
-
|
|
18988
|
+
resolve15(packageRoot(), "allowed.cli-reads"),
|
|
18779
18989
|
`${commands.join("\n")}
|
|
18780
18990
|
`
|
|
18781
18991
|
);
|
|
@@ -18801,13 +19011,13 @@ function findCliWrite(command) {
|
|
|
18801
19011
|
|
|
18802
19012
|
// src/shared/readSettingsPerms.ts
|
|
18803
19013
|
import { existsSync as existsSync42, readFileSync as readFileSync27 } from "fs";
|
|
18804
|
-
import { homedir as
|
|
18805
|
-
import { join as
|
|
19014
|
+
import { homedir as homedir17 } from "os";
|
|
19015
|
+
import { join as join45 } from "path";
|
|
18806
19016
|
function readSettingsPerms(key) {
|
|
18807
19017
|
const paths = [
|
|
18808
|
-
|
|
18809
|
-
|
|
18810
|
-
|
|
19018
|
+
join45(homedir17(), ".claude", "settings.json"),
|
|
19019
|
+
join45(process.cwd(), ".claude", "settings.json"),
|
|
19020
|
+
join45(process.cwd(), ".claude", "settings.local.json")
|
|
18811
19021
|
];
|
|
18812
19022
|
const entries = [];
|
|
18813
19023
|
for (const p of paths) {
|
|
@@ -18913,19 +19123,19 @@ function isCdToCwd(command) {
|
|
|
18913
19123
|
const parts = command.split(/\s+/);
|
|
18914
19124
|
if (parts[0] !== "cd" || parts.length > 2) return false;
|
|
18915
19125
|
if (parts.length === 1) return false;
|
|
18916
|
-
const resolved =
|
|
18917
|
-
return resolved ===
|
|
19126
|
+
const resolved = resolve16(normalizeMsysPath(parts[1]));
|
|
19127
|
+
return resolved === resolve16(process.cwd());
|
|
18918
19128
|
}
|
|
18919
19129
|
function isCdToReadAllowedDir(command) {
|
|
18920
19130
|
const parts = command.split(/\s+/);
|
|
18921
19131
|
if (parts[0] !== "cd" || parts.length !== 2) return void 0;
|
|
18922
|
-
const target =
|
|
19132
|
+
const target = resolve16(normalizeMsysPath(parts[1]));
|
|
18923
19133
|
for (const entry of readSettingsPerms("allow")) {
|
|
18924
19134
|
const m = entry.match(READ_RE);
|
|
18925
19135
|
if (!m) continue;
|
|
18926
19136
|
const base = globBaseDir(m[1]);
|
|
18927
19137
|
if (!base) continue;
|
|
18928
|
-
const resolved =
|
|
19138
|
+
const resolved = resolve16(normalizeMsysPath(base));
|
|
18929
19139
|
if (target === resolved || target.startsWith(resolved + sep2)) {
|
|
18930
19140
|
return `cd to Read-allowed directory: ${entry}`;
|
|
18931
19141
|
}
|
|
@@ -19030,12 +19240,12 @@ function decideCommand(toolName, rawCommand) {
|
|
|
19030
19240
|
|
|
19031
19241
|
// src/commands/cliHook/logDeniedToolCall.ts
|
|
19032
19242
|
import { mkdirSync as mkdirSync12 } from "fs";
|
|
19033
|
-
import { homedir as
|
|
19034
|
-
import { join as
|
|
19243
|
+
import { homedir as homedir18 } from "os";
|
|
19244
|
+
import { join as join46 } from "path";
|
|
19035
19245
|
import Database from "better-sqlite3";
|
|
19036
19246
|
var _db;
|
|
19037
19247
|
function getDbDir() {
|
|
19038
|
-
return
|
|
19248
|
+
return join46(homedir18(), ".assist");
|
|
19039
19249
|
}
|
|
19040
19250
|
function initSchema(db) {
|
|
19041
19251
|
db.exec(`
|
|
@@ -19054,7 +19264,7 @@ function openPromptsDb(dir) {
|
|
|
19054
19264
|
if (_db) return _db;
|
|
19055
19265
|
const dbDir = dir ?? getDbDir();
|
|
19056
19266
|
mkdirSync12(dbDir, { recursive: true });
|
|
19057
|
-
const db = new Database(
|
|
19267
|
+
const db = new Database(join46(dbDir, "assist.db"));
|
|
19058
19268
|
db.pragma("journal_mode = WAL");
|
|
19059
19269
|
initSchema(db);
|
|
19060
19270
|
_db = db;
|
|
@@ -19125,7 +19335,7 @@ async function cliHook() {
|
|
|
19125
19335
|
logDeniedToolCall({
|
|
19126
19336
|
tool: input.toolName,
|
|
19127
19337
|
command: input.command,
|
|
19128
|
-
repo:
|
|
19338
|
+
repo: basename13(process.cwd()),
|
|
19129
19339
|
sessionId: process.env.CLAUDE_SESSION_ID,
|
|
19130
19340
|
denyReason: decision.permissionDecisionReason
|
|
19131
19341
|
});
|
|
@@ -19174,8 +19384,8 @@ ${reasons.join("\n")}`);
|
|
|
19174
19384
|
|
|
19175
19385
|
// src/commands/permitCliReads.ts
|
|
19176
19386
|
import { existsSync as existsSync43, mkdirSync as mkdirSync13, readFileSync as readFileSync28, writeFileSync as writeFileSync23 } from "fs";
|
|
19177
|
-
import { homedir as
|
|
19178
|
-
import { join as
|
|
19387
|
+
import { homedir as homedir19 } from "os";
|
|
19388
|
+
import { join as join47 } from "path";
|
|
19179
19389
|
|
|
19180
19390
|
// src/commands/permitCliReads/assertCliExists.ts
|
|
19181
19391
|
function assertCliExists(cli) {
|
|
@@ -19438,7 +19648,7 @@ function updateSettings(cli, commands) {
|
|
|
19438
19648
|
// src/commands/permitCliReads.ts
|
|
19439
19649
|
function logPath(cli) {
|
|
19440
19650
|
const safeName = cli.replace(/\s+/g, "-");
|
|
19441
|
-
return
|
|
19651
|
+
return join47(homedir19(), ".assist", `cli-discover-${safeName}.log`);
|
|
19442
19652
|
}
|
|
19443
19653
|
function readCache(cli) {
|
|
19444
19654
|
const path106 = logPath(cli);
|
|
@@ -19446,7 +19656,7 @@ function readCache(cli) {
|
|
|
19446
19656
|
return readFileSync28(path106, "utf8");
|
|
19447
19657
|
}
|
|
19448
19658
|
function writeCache(cli, output) {
|
|
19449
|
-
const dir =
|
|
19659
|
+
const dir = join47(homedir19(), ".assist");
|
|
19450
19660
|
mkdirSync13(dir, { recursive: true });
|
|
19451
19661
|
writeFileSync23(logPath(cli), output);
|
|
19452
19662
|
}
|
|
@@ -19610,18 +19820,18 @@ function isHashCommentFile(filePath) {
|
|
|
19610
19820
|
}
|
|
19611
19821
|
|
|
19612
19822
|
// src/commands/codeComment/getRestrictedDir.ts
|
|
19613
|
-
import { homedir as
|
|
19614
|
-
import { join as
|
|
19823
|
+
import { homedir as homedir20 } from "os";
|
|
19824
|
+
import { join as join48 } from "path";
|
|
19615
19825
|
function getRestrictedDir() {
|
|
19616
|
-
return
|
|
19826
|
+
return join48(homedir20(), ".assist", "restricted");
|
|
19617
19827
|
}
|
|
19618
19828
|
function getPinStatePath(pin2) {
|
|
19619
|
-
return
|
|
19829
|
+
return join48(getRestrictedDir(), `code-comment-${pin2}.json`);
|
|
19620
19830
|
}
|
|
19621
19831
|
|
|
19622
19832
|
// src/commands/codeComment/sweepRestrictedDir.ts
|
|
19623
19833
|
import { readdirSync as readdirSync6, statSync as statSync8, unlinkSync as unlinkSync7 } from "fs";
|
|
19624
|
-
import { join as
|
|
19834
|
+
import { join as join49 } from "path";
|
|
19625
19835
|
var STALE_AFTER_MS = 30 * 60 * 1e3;
|
|
19626
19836
|
function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
19627
19837
|
let entries;
|
|
@@ -19632,7 +19842,7 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
|
|
|
19632
19842
|
}
|
|
19633
19843
|
const cutoff = Date.now() - STALE_AFTER_MS;
|
|
19634
19844
|
for (const entry of entries) {
|
|
19635
|
-
const path106 =
|
|
19845
|
+
const path106 = join49(dir, entry);
|
|
19636
19846
|
try {
|
|
19637
19847
|
if (statSync8(path106).mtimeMs < cutoff) unlinkSync7(path106);
|
|
19638
19848
|
} catch {
|
|
@@ -21286,18 +21496,18 @@ import chalk137 from "chalk";
|
|
|
21286
21496
|
|
|
21287
21497
|
// src/commands/criteriaExtension/criteriaExtensionDir.ts
|
|
21288
21498
|
import { existsSync as existsSync46 } from "fs";
|
|
21289
|
-
import { dirname as dirname26, join as
|
|
21499
|
+
import { dirname as dirname26, join as join50 } from "path";
|
|
21290
21500
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
21291
21501
|
var moduleDir = dirname26(fileURLToPath6(import.meta.url));
|
|
21292
21502
|
function criteriaExtensionDir() {
|
|
21293
|
-
const bundled =
|
|
21503
|
+
const bundled = join50(
|
|
21294
21504
|
moduleDir,
|
|
21295
21505
|
"commands",
|
|
21296
21506
|
"criteriaExtension",
|
|
21297
21507
|
"criteria-extension"
|
|
21298
21508
|
);
|
|
21299
21509
|
if (existsSync46(bundled)) return bundled;
|
|
21300
|
-
return
|
|
21510
|
+
return join50(moduleDir, "..", "..", "..", "criteria-extension");
|
|
21301
21511
|
}
|
|
21302
21512
|
|
|
21303
21513
|
// src/commands/criteriaExtension/criteriaExtension.ts
|
|
@@ -21325,24 +21535,24 @@ async function criteriaExtension() {
|
|
|
21325
21535
|
|
|
21326
21536
|
// src/commands/criteriaExtension/printCriteriaExtensionUrl.ts
|
|
21327
21537
|
import { readFile as readFile4 } from "fs/promises";
|
|
21328
|
-
import { join as
|
|
21538
|
+
import { join as join51 } from "path";
|
|
21329
21539
|
import chalk138 from "chalk";
|
|
21330
21540
|
|
|
21331
21541
|
// src/commands/criteriaExtension/latestUpdate.ts
|
|
21332
|
-
function latestUpdate(manifest,
|
|
21542
|
+
function latestUpdate(manifest, updates2) {
|
|
21333
21543
|
const { id } = JSON.parse(manifest).browser_specific_settings.gecko;
|
|
21334
|
-
return JSON.parse(
|
|
21544
|
+
return JSON.parse(updates2).addons[id]?.updates.at(-1);
|
|
21335
21545
|
}
|
|
21336
21546
|
|
|
21337
21547
|
// src/commands/criteriaExtension/latestUpdateLink.ts
|
|
21338
|
-
function latestUpdateLink(manifest,
|
|
21339
|
-
return latestUpdate(manifest,
|
|
21548
|
+
function latestUpdateLink(manifest, updates2) {
|
|
21549
|
+
return latestUpdate(manifest, updates2)?.update_link;
|
|
21340
21550
|
}
|
|
21341
21551
|
|
|
21342
21552
|
// src/commands/criteriaExtension/printCriteriaExtensionUrl.ts
|
|
21343
21553
|
async function printCriteriaExtensionUrl() {
|
|
21344
21554
|
const manifest = await readFile4(
|
|
21345
|
-
|
|
21555
|
+
join51(criteriaExtensionDir(), "manifest.json"),
|
|
21346
21556
|
"utf8"
|
|
21347
21557
|
);
|
|
21348
21558
|
const { update_url } = JSON.parse(manifest).browser_specific_settings.gecko;
|
|
@@ -21358,16 +21568,16 @@ async function printCriteriaExtensionUrl() {
|
|
|
21358
21568
|
|
|
21359
21569
|
// src/commands/criteriaExtension/signCriteriaExtension.ts
|
|
21360
21570
|
import { rm as rm2 } from "fs/promises";
|
|
21361
|
-
import { homedir as
|
|
21362
|
-
import { join as
|
|
21571
|
+
import { homedir as homedir21, tmpdir as tmpdir3 } from "os";
|
|
21572
|
+
import { join as join57 } from "path";
|
|
21363
21573
|
import chalk140 from "chalk";
|
|
21364
21574
|
|
|
21365
21575
|
// src/commands/criteriaExtension/copySignedXpi.ts
|
|
21366
21576
|
import { copyFile } from "fs/promises";
|
|
21367
|
-
import { join as
|
|
21577
|
+
import { join as join52 } from "path";
|
|
21368
21578
|
var SIGNED_XPI_NAME = "criteria-extension.xpi";
|
|
21369
21579
|
async function copySignedXpi(xpi, dir) {
|
|
21370
|
-
const fixed2 =
|
|
21580
|
+
const fixed2 = join52(dir, SIGNED_XPI_NAME);
|
|
21371
21581
|
if (fixed2 === xpi) return fixed2;
|
|
21372
21582
|
await copyFile(xpi, fixed2);
|
|
21373
21583
|
return fixed2;
|
|
@@ -21376,11 +21586,11 @@ async function copySignedXpi(xpi, dir) {
|
|
|
21376
21586
|
// src/commands/criteriaExtension/findSignedXpi.ts
|
|
21377
21587
|
import { existsSync as existsSync47 } from "fs";
|
|
21378
21588
|
import { readdir } from "fs/promises";
|
|
21379
|
-
import { join as
|
|
21589
|
+
import { join as join53 } from "path";
|
|
21380
21590
|
async function findSignedXpi(dir) {
|
|
21381
21591
|
if (!existsSync47(dir)) return null;
|
|
21382
21592
|
const name = (await readdir(dir)).find((entry) => entry.endsWith(".xpi"));
|
|
21383
|
-
return name ?
|
|
21593
|
+
return name ? join53(dir, name) : null;
|
|
21384
21594
|
}
|
|
21385
21595
|
|
|
21386
21596
|
// src/commands/criteriaExtension/signedAddonInstallPath.ts
|
|
@@ -21403,10 +21613,10 @@ async function signedAddonInstallPath(xpi) {
|
|
|
21403
21613
|
|
|
21404
21614
|
// src/commands/criteriaExtension/signPreflightProblem.ts
|
|
21405
21615
|
import { existsSync as existsSync48 } from "fs";
|
|
21406
|
-
import { join as
|
|
21616
|
+
import { join as join54 } from "path";
|
|
21407
21617
|
var KEY_URL = "https://addons.mozilla.org/en-US/developers/addon/api/key/";
|
|
21408
21618
|
function signPreflightProblem(source) {
|
|
21409
|
-
if (!existsSync48(
|
|
21619
|
+
if (!existsSync48(join54(source, "content.js")))
|
|
21410
21620
|
return {
|
|
21411
21621
|
message: `no content.js in ${source}`,
|
|
21412
21622
|
hint: "run npm run build to bundle the content script"
|
|
@@ -21421,7 +21631,7 @@ function signPreflightProblem(source) {
|
|
|
21421
21631
|
|
|
21422
21632
|
// src/commands/criteriaExtension/stageCriteriaExtension.ts
|
|
21423
21633
|
import { cp as cp3, mkdir as mkdir5, readFile as readFile5, rm, writeFile as writeFile4 } from "fs/promises";
|
|
21424
|
-
import { basename as
|
|
21634
|
+
import { basename as basename14, join as join55 } from "path";
|
|
21425
21635
|
|
|
21426
21636
|
// src/commands/criteriaExtension/stampManifestVersion.ts
|
|
21427
21637
|
function stampManifestVersion(manifest, version2) {
|
|
@@ -21436,9 +21646,9 @@ async function stageCriteriaExtension(source, staging, version2) {
|
|
|
21436
21646
|
await mkdir5(staging, { recursive: true });
|
|
21437
21647
|
await cp3(source, staging, {
|
|
21438
21648
|
recursive: true,
|
|
21439
|
-
filter: (path106) =>
|
|
21649
|
+
filter: (path106) => basename14(path106) !== "updates.json"
|
|
21440
21650
|
});
|
|
21441
|
-
const manifest =
|
|
21651
|
+
const manifest = join55(staging, "manifest.json");
|
|
21442
21652
|
const stamped = stampManifestVersion(
|
|
21443
21653
|
await readFile5(manifest, "utf8"),
|
|
21444
21654
|
version2
|
|
@@ -21448,13 +21658,13 @@ async function stageCriteriaExtension(source, staging, version2) {
|
|
|
21448
21658
|
|
|
21449
21659
|
// src/commands/criteriaExtension/writeUpdateManifest.ts
|
|
21450
21660
|
import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
21451
|
-
import { join as
|
|
21661
|
+
import { join as join56 } from "path";
|
|
21452
21662
|
|
|
21453
21663
|
// src/commands/criteriaExtension/buildUpdateManifest.ts
|
|
21454
21664
|
var RELEASE_DOWNLOAD_URL = "https://github.com/staff0rd/assist/releases/download";
|
|
21455
21665
|
function buildUpdateManifest(manifest, version2) {
|
|
21456
21666
|
const { id } = JSON.parse(manifest).browser_specific_settings.gecko;
|
|
21457
|
-
const
|
|
21667
|
+
const updates2 = {
|
|
21458
21668
|
addons: {
|
|
21459
21669
|
[id]: {
|
|
21460
21670
|
updates: [
|
|
@@ -21466,24 +21676,24 @@ function buildUpdateManifest(manifest, version2) {
|
|
|
21466
21676
|
}
|
|
21467
21677
|
}
|
|
21468
21678
|
};
|
|
21469
|
-
return `${JSON.stringify(
|
|
21679
|
+
return `${JSON.stringify(updates2, null, " ")}
|
|
21470
21680
|
`;
|
|
21471
21681
|
}
|
|
21472
21682
|
|
|
21473
21683
|
// src/commands/criteriaExtension/writeUpdateManifest.ts
|
|
21474
21684
|
async function writeUpdateManifest(source, dir, version2) {
|
|
21475
21685
|
await writeFile5(
|
|
21476
|
-
|
|
21686
|
+
join56(dir, "updates.json"),
|
|
21477
21687
|
buildUpdateManifest(
|
|
21478
|
-
await readFile6(
|
|
21688
|
+
await readFile6(join56(source, "manifest.json"), "utf8"),
|
|
21479
21689
|
version2
|
|
21480
21690
|
)
|
|
21481
21691
|
);
|
|
21482
21692
|
}
|
|
21483
21693
|
|
|
21484
21694
|
// src/commands/criteriaExtension/signCriteriaExtension.ts
|
|
21485
|
-
var ARTIFACTS_DIR =
|
|
21486
|
-
var STAGING_DIR =
|
|
21695
|
+
var ARTIFACTS_DIR = join57(homedir21(), ".assist", "criteria-extension");
|
|
21696
|
+
var STAGING_DIR = join57(tmpdir3(), "assist-criteria-extension");
|
|
21487
21697
|
async function signCriteriaExtension() {
|
|
21488
21698
|
const source = criteriaExtensionDir();
|
|
21489
21699
|
const problem = signPreflightProblem(source);
|
|
@@ -21671,12 +21881,12 @@ import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync26 } from "fs"
|
|
|
21671
21881
|
import chalk143 from "chalk";
|
|
21672
21882
|
|
|
21673
21883
|
// src/commands/dbMigration/getMigrationPinPath.ts
|
|
21674
|
-
import { join as
|
|
21884
|
+
import { join as join58 } from "path";
|
|
21675
21885
|
function getMigrationPinPath(pin2) {
|
|
21676
|
-
return
|
|
21886
|
+
return join58(getRestrictedDir(), `db-migration-pin-${pin2}.json`);
|
|
21677
21887
|
}
|
|
21678
21888
|
function getMigrationApprovalPath(migrationId) {
|
|
21679
|
-
return
|
|
21889
|
+
return join58(getRestrictedDir(), `db-migration-approval-${migrationId}.json`);
|
|
21680
21890
|
}
|
|
21681
21891
|
|
|
21682
21892
|
// src/commands/dbMigration/readMigrationPinState.ts
|
|
@@ -21809,15 +22019,15 @@ function registerDeploy(program2) {
|
|
|
21809
22019
|
}
|
|
21810
22020
|
|
|
21811
22021
|
// src/commands/devlog/list.ts
|
|
21812
|
-
import { execFileSync as
|
|
21813
|
-
import { basename as
|
|
22022
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
22023
|
+
import { basename as basename16 } from "path";
|
|
21814
22024
|
|
|
21815
22025
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
21816
|
-
import { homedir as
|
|
21817
|
-
import { join as
|
|
21818
|
-
var BLOG_REPO_ROOT =
|
|
22026
|
+
import { homedir as homedir22 } from "os";
|
|
22027
|
+
import { join as join59 } from "path";
|
|
22028
|
+
var BLOG_REPO_ROOT = join59(homedir22(), "git/blog");
|
|
21819
22029
|
function loadBlogSkipDays(repoName) {
|
|
21820
|
-
const config = loadRawYaml(
|
|
22030
|
+
const config = loadRawYaml(join59(BLOG_REPO_ROOT, "assist.yml"));
|
|
21821
22031
|
const devlog = config.devlog;
|
|
21822
22032
|
const skip2 = devlog?.skip;
|
|
21823
22033
|
return new Set(skip2?.[repoName]);
|
|
@@ -21829,13 +22039,13 @@ import chalk146 from "chalk";
|
|
|
21829
22039
|
|
|
21830
22040
|
// src/shared/getRepoName.ts
|
|
21831
22041
|
import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
|
|
21832
|
-
import { basename as
|
|
22042
|
+
import { basename as basename15, join as join60 } from "path";
|
|
21833
22043
|
function getRepoName() {
|
|
21834
22044
|
const config = loadConfig();
|
|
21835
22045
|
if (config.devlog?.name) {
|
|
21836
22046
|
return config.devlog.name;
|
|
21837
22047
|
}
|
|
21838
|
-
const packageJsonPath =
|
|
22048
|
+
const packageJsonPath = join60(process.cwd(), "package.json");
|
|
21839
22049
|
if (existsSync51(packageJsonPath)) {
|
|
21840
22050
|
try {
|
|
21841
22051
|
const content = readFileSync33(packageJsonPath, "utf8");
|
|
@@ -21846,13 +22056,13 @@ function getRepoName() {
|
|
|
21846
22056
|
} catch {
|
|
21847
22057
|
}
|
|
21848
22058
|
}
|
|
21849
|
-
return
|
|
22059
|
+
return basename15(process.cwd());
|
|
21850
22060
|
}
|
|
21851
22061
|
|
|
21852
22062
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
21853
22063
|
import { readdirSync as readdirSync7, readFileSync as readFileSync34 } from "fs";
|
|
21854
|
-
import { join as
|
|
21855
|
-
var DEVLOG_DIR =
|
|
22064
|
+
import { join as join61 } from "path";
|
|
22065
|
+
var DEVLOG_DIR = join61(BLOG_REPO_ROOT, "src/content/devlog");
|
|
21856
22066
|
function extractFrontmatter(content) {
|
|
21857
22067
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
21858
22068
|
return fm?.[1] ?? null;
|
|
@@ -21880,7 +22090,7 @@ function readDevlogFiles(callback) {
|
|
|
21880
22090
|
try {
|
|
21881
22091
|
const files = readdirSync7(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
21882
22092
|
for (const file of files) {
|
|
21883
|
-
const content = readFileSync34(
|
|
22093
|
+
const content = readFileSync34(join61(DEVLOG_DIR, file), "utf8");
|
|
21884
22094
|
const parsed = parseFrontmatter(content, file);
|
|
21885
22095
|
if (parsed) callback(parsed);
|
|
21886
22096
|
}
|
|
@@ -21982,14 +22192,14 @@ function list2(options2) {
|
|
|
21982
22192
|
const config = loadConfig();
|
|
21983
22193
|
const days = options2.days ?? 30;
|
|
21984
22194
|
const ignore3 = options2.ignore ?? config.devlog?.ignore ?? [];
|
|
21985
|
-
const repoName =
|
|
22195
|
+
const repoName = basename16(process.cwd());
|
|
21986
22196
|
const skipDays = loadBlogSkipDays(repoName);
|
|
21987
22197
|
const devlogEntries = loadDevlogEntries(repoName);
|
|
21988
22198
|
const args = ["log"];
|
|
21989
22199
|
if (options2.reverse) args.push("--reverse");
|
|
21990
22200
|
else args.push("-n", "500");
|
|
21991
22201
|
args.push("--pretty=format:%ad|%h|%s", "--date=short");
|
|
21992
|
-
const output =
|
|
22202
|
+
const output = execFileSync6("git", args, { encoding: "utf8" });
|
|
21993
22203
|
const commitsByDate = parseGitLogCommits(output, ignore3);
|
|
21994
22204
|
let dateCount = 0;
|
|
21995
22205
|
let isFirst = true;
|
|
@@ -22012,7 +22222,7 @@ function list2(options2) {
|
|
|
22012
22222
|
}
|
|
22013
22223
|
|
|
22014
22224
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
22015
|
-
import { execFileSync as
|
|
22225
|
+
import { execFileSync as execFileSync7, execSync as execSync32 } from "child_process";
|
|
22016
22226
|
import semver from "semver";
|
|
22017
22227
|
function getVersionAtCommit(hash) {
|
|
22018
22228
|
try {
|
|
@@ -22031,7 +22241,7 @@ function stripToMinor(version2) {
|
|
|
22031
22241
|
}
|
|
22032
22242
|
function getLastVersionInfoFromGit() {
|
|
22033
22243
|
try {
|
|
22034
|
-
const output =
|
|
22244
|
+
const output = execFileSync7(
|
|
22035
22245
|
"git",
|
|
22036
22246
|
["log", "-1", "--pretty=format:%ad|%h", "--date=short"],
|
|
22037
22247
|
{
|
|
@@ -22076,7 +22286,7 @@ function bumpVersion(version2, type) {
|
|
|
22076
22286
|
}
|
|
22077
22287
|
|
|
22078
22288
|
// src/commands/devlog/next/displayNextEntry.ts
|
|
22079
|
-
import { execFileSync as
|
|
22289
|
+
import { execFileSync as execFileSync8 } from "child_process";
|
|
22080
22290
|
import chalk149 from "chalk";
|
|
22081
22291
|
|
|
22082
22292
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
@@ -22110,7 +22320,7 @@ function findTargetDate(commitsByDate, skipDays) {
|
|
|
22110
22320
|
return Array.from(commitsByDate.keys()).filter((d) => !skipDays.has(d)).sort()[0];
|
|
22111
22321
|
}
|
|
22112
22322
|
function fetchCommitsByDate(ignore3, lastDate) {
|
|
22113
|
-
const output =
|
|
22323
|
+
const output = execFileSync8(
|
|
22114
22324
|
"git",
|
|
22115
22325
|
["log", "--pretty=format:%ad|%h|%s", "--date=short", "-n", "500"],
|
|
22116
22326
|
{ encoding: "utf8" }
|
|
@@ -22268,11 +22478,11 @@ function repos(options2) {
|
|
|
22268
22478
|
|
|
22269
22479
|
// src/commands/devlog/skip.ts
|
|
22270
22480
|
import { writeFileSync as writeFileSync29 } from "fs";
|
|
22271
|
-
import { join as
|
|
22481
|
+
import { join as join62 } from "path";
|
|
22272
22482
|
import chalk151 from "chalk";
|
|
22273
22483
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
22274
22484
|
function getBlogConfigPath() {
|
|
22275
|
-
return
|
|
22485
|
+
return join62(BLOG_REPO_ROOT, "assist.yml");
|
|
22276
22486
|
}
|
|
22277
22487
|
function skip(date) {
|
|
22278
22488
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
@@ -22334,7 +22544,7 @@ function registerDevlog(program2) {
|
|
|
22334
22544
|
|
|
22335
22545
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
22336
22546
|
import { closeSync as closeSync4, openSync as openSync5, readdirSync as readdirSync8 } from "fs";
|
|
22337
|
-
import { join as
|
|
22547
|
+
import { join as join63 } from "path";
|
|
22338
22548
|
import chalk153 from "chalk";
|
|
22339
22549
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "packages"]);
|
|
22340
22550
|
function isLockedDll(debugDir) {
|
|
@@ -22346,7 +22556,7 @@ function isLockedDll(debugDir) {
|
|
|
22346
22556
|
}
|
|
22347
22557
|
for (const file of files) {
|
|
22348
22558
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
22349
|
-
const dllPath =
|
|
22559
|
+
const dllPath = join63(debugDir, file);
|
|
22350
22560
|
try {
|
|
22351
22561
|
const fd = openSync5(dllPath, "r+");
|
|
22352
22562
|
closeSync4(fd);
|
|
@@ -22364,13 +22574,13 @@ function findFirstLockedDll(dir) {
|
|
|
22364
22574
|
return null;
|
|
22365
22575
|
}
|
|
22366
22576
|
if (entries.includes("bin")) {
|
|
22367
|
-
const locked = isLockedDll(
|
|
22577
|
+
const locked = isLockedDll(join63(dir, "bin", "Debug"));
|
|
22368
22578
|
if (locked) return locked;
|
|
22369
22579
|
}
|
|
22370
22580
|
for (const entry of entries) {
|
|
22371
22581
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
22372
22582
|
continue;
|
|
22373
|
-
const found = findFirstLockedDll(
|
|
22583
|
+
const found = findFirstLockedDll(join63(dir, entry));
|
|
22374
22584
|
if (found) return found;
|
|
22375
22585
|
}
|
|
22376
22586
|
return null;
|
|
@@ -22717,11 +22927,11 @@ import chalk159 from "chalk";
|
|
|
22717
22927
|
|
|
22718
22928
|
// src/commands/dotnet/findSolution.ts
|
|
22719
22929
|
import { readdirSync as readdirSync10 } from "fs";
|
|
22720
|
-
import { dirname as dirname27, join as
|
|
22930
|
+
import { dirname as dirname27, join as join64 } from "path";
|
|
22721
22931
|
import chalk158 from "chalk";
|
|
22722
22932
|
function findSlnInDir(dir) {
|
|
22723
22933
|
try {
|
|
22724
|
-
return readdirSync10(dir).filter((f) => f.endsWith(".sln")).map((f) =>
|
|
22934
|
+
return readdirSync10(dir).filter((f) => f.endsWith(".sln")).map((f) => join64(dir, f));
|
|
22725
22935
|
} catch {
|
|
22726
22936
|
return [];
|
|
22727
22937
|
}
|
|
@@ -23716,7 +23926,7 @@ function aggregateCommitters(authorLists) {
|
|
|
23716
23926
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
23717
23927
|
import { unlinkSync as unlinkSync12, writeFileSync as writeFileSync30 } from "fs";
|
|
23718
23928
|
import { tmpdir as tmpdir5 } from "os";
|
|
23719
|
-
import { join as
|
|
23929
|
+
import { join as join65 } from "path";
|
|
23720
23930
|
function buildArgs2(queryFile, vars) {
|
|
23721
23931
|
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
23722
23932
|
for (const [key, value] of Object.entries(vars)) {
|
|
@@ -23726,7 +23936,7 @@ function buildArgs2(queryFile, vars) {
|
|
|
23726
23936
|
return args;
|
|
23727
23937
|
}
|
|
23728
23938
|
function runGhGraphql(mutation, vars) {
|
|
23729
|
-
const queryFile =
|
|
23939
|
+
const queryFile = join65(tmpdir5(), `gh-query-${Date.now()}.graphql`);
|
|
23730
23940
|
writeFileSync30(queryFile, mutation);
|
|
23731
23941
|
try {
|
|
23732
23942
|
const result = spawnSync6("gh", buildArgs2(queryFile, vars), {
|
|
@@ -24439,7 +24649,7 @@ Anything nested below the leaf level fails the run before a single write, naming
|
|
|
24439
24649
|
}
|
|
24440
24650
|
|
|
24441
24651
|
// src/commands/github/issue/commentIssue.ts
|
|
24442
|
-
import { execFileSync as
|
|
24652
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
24443
24653
|
|
|
24444
24654
|
// src/shared/validateProposedContent.ts
|
|
24445
24655
|
function validateProposedContent(labels, title, body) {
|
|
@@ -24500,7 +24710,7 @@ async function commentIssue(numberArg, options2) {
|
|
|
24500
24710
|
const args = ["issue", "comment", String(number), "--body", body];
|
|
24501
24711
|
if (options2.repo) args.push("--repo", options2.repo);
|
|
24502
24712
|
try {
|
|
24503
|
-
|
|
24713
|
+
execFileSync9("gh", args, { stdio: "inherit" });
|
|
24504
24714
|
} catch {
|
|
24505
24715
|
process.exit(1);
|
|
24506
24716
|
}
|
|
@@ -24903,8 +25113,8 @@ function attachArgs(attachments) {
|
|
|
24903
25113
|
}
|
|
24904
25114
|
|
|
24905
25115
|
// src/commands/prs/runGhWithAttachments.ts
|
|
24906
|
-
import { execFileSync as
|
|
24907
|
-
import { basename as
|
|
25116
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
25117
|
+
import { basename as basename17 } from "path";
|
|
24908
25118
|
|
|
24909
25119
|
// src/shared/removeStagedAttachments.ts
|
|
24910
25120
|
import { rmSync as rmSync4 } from "fs";
|
|
@@ -24921,7 +25131,7 @@ function removeStagedAttachments(attachments) {
|
|
|
24921
25131
|
var PLACED_URL = /https:\/\/\S+\/(pull|issues)\/\d+/;
|
|
24922
25132
|
function reportPartialFailure(attachments, stderr) {
|
|
24923
25133
|
const failed3 = attachments.filter(
|
|
24924
|
-
({ path: path106 }) => stderr.includes(path106) || stderr.includes(
|
|
25134
|
+
({ path: path106 }) => stderr.includes(path106) || stderr.includes(basename17(path106))
|
|
24925
25135
|
);
|
|
24926
25136
|
const named = failed3.length > 0 ? failed3 : attachments;
|
|
24927
25137
|
console.error(
|
|
@@ -24931,7 +25141,7 @@ function reportPartialFailure(attachments, stderr) {
|
|
|
24931
25141
|
function runGhWithAttachments(args, attachments) {
|
|
24932
25142
|
const attaching = attachments.length > 0;
|
|
24933
25143
|
try {
|
|
24934
|
-
const stdout =
|
|
25144
|
+
const stdout = execFileSync10("gh", args, {
|
|
24935
25145
|
encoding: "utf8",
|
|
24936
25146
|
stdio: ["inherit", "pipe", attaching ? "pipe" : "inherit"]
|
|
24937
25147
|
});
|
|
@@ -25042,7 +25252,7 @@ function inWebSession() {
|
|
|
25042
25252
|
}
|
|
25043
25253
|
|
|
25044
25254
|
// src/commands/github/issue/fetchIssue.ts
|
|
25045
|
-
import { execFileSync as
|
|
25255
|
+
import { execFileSync as execFileSync11 } from "child_process";
|
|
25046
25256
|
function fetchIssue2(number, repo) {
|
|
25047
25257
|
const args = [
|
|
25048
25258
|
"issue",
|
|
@@ -25054,7 +25264,7 @@ function fetchIssue2(number, repo) {
|
|
|
25054
25264
|
if (repo) args.push("--repo", repo);
|
|
25055
25265
|
let raw;
|
|
25056
25266
|
try {
|
|
25057
|
-
raw =
|
|
25267
|
+
raw = execFileSync11("gh", args, { encoding: "utf8" });
|
|
25058
25268
|
} catch {
|
|
25059
25269
|
console.error(`Could not fetch issue #${number} with gh issue view`);
|
|
25060
25270
|
process.exit(1);
|
|
@@ -25071,14 +25281,14 @@ function fetchIssue2(number, repo) {
|
|
|
25071
25281
|
import { existsSync as existsSync56, readFileSync as readFileSync38 } from "fs";
|
|
25072
25282
|
|
|
25073
25283
|
// src/commands/github/issue/issueWorkingFile.ts
|
|
25074
|
-
import { join as
|
|
25284
|
+
import { join as join66 } from "path";
|
|
25075
25285
|
function issueWorkingFile(slug2, number) {
|
|
25076
25286
|
const [owner = "unknown", repo = "unknown"] = slug2.split("/");
|
|
25077
|
-
const dir =
|
|
25287
|
+
const dir = join66(getStoreDir(), "github-issues", owner, repo);
|
|
25078
25288
|
return {
|
|
25079
25289
|
dir,
|
|
25080
|
-
bodyPath:
|
|
25081
|
-
metaPath:
|
|
25290
|
+
bodyPath: join66(dir, `${number}.md`),
|
|
25291
|
+
metaPath: join66(dir, `${number}.json`)
|
|
25082
25292
|
};
|
|
25083
25293
|
}
|
|
25084
25294
|
|
|
@@ -25145,12 +25355,12 @@ function prepareIssueEdit(number, repo, fresh) {
|
|
|
25145
25355
|
}
|
|
25146
25356
|
|
|
25147
25357
|
// src/commands/github/issue/pushIssueBody.ts
|
|
25148
|
-
import { execFileSync as
|
|
25358
|
+
import { execFileSync as execFileSync12 } from "child_process";
|
|
25149
25359
|
function pushIssueBody(number, repo, bodyPath) {
|
|
25150
25360
|
const args = ["issue", "edit", String(number), "--body-file", bodyPath];
|
|
25151
25361
|
if (repo) args.push("--repo", repo);
|
|
25152
25362
|
try {
|
|
25153
|
-
|
|
25363
|
+
execFileSync12("gh", args, { stdio: "inherit" });
|
|
25154
25364
|
} catch {
|
|
25155
25365
|
process.exit(1);
|
|
25156
25366
|
}
|
|
@@ -25210,12 +25420,12 @@ function setIssueParent(number, repo, parentArg) {
|
|
|
25210
25420
|
}
|
|
25211
25421
|
|
|
25212
25422
|
// src/commands/github/issue/viewIssue.ts
|
|
25213
|
-
import { execFileSync as
|
|
25423
|
+
import { execFileSync as execFileSync13 } from "child_process";
|
|
25214
25424
|
function viewIssue(number, repo) {
|
|
25215
25425
|
const args = ["issue", "view", String(number)];
|
|
25216
25426
|
if (repo) args.push("--repo", repo);
|
|
25217
25427
|
try {
|
|
25218
|
-
|
|
25428
|
+
execFileSync13("gh", args, { stdio: "inherit" });
|
|
25219
25429
|
} catch {
|
|
25220
25430
|
process.exit(1);
|
|
25221
25431
|
}
|
|
@@ -25271,7 +25481,7 @@ function registerEditIssue(issueCommand) {
|
|
|
25271
25481
|
}
|
|
25272
25482
|
|
|
25273
25483
|
// src/commands/github/issue/editIssueComment.ts
|
|
25274
|
-
import { execFileSync as
|
|
25484
|
+
import { execFileSync as execFileSync14 } from "child_process";
|
|
25275
25485
|
var USAGE4 = "Usage: assist github issue edit-comment <comment-id> --body <body> [-R <owner>/<repo>]";
|
|
25276
25486
|
async function editIssueComment(commentIdArg, options2) {
|
|
25277
25487
|
const commentId = Number.parseInt(commentIdArg, 10);
|
|
@@ -25298,7 +25508,7 @@ async function editIssueComment(commentIdArg, options2) {
|
|
|
25298
25508
|
];
|
|
25299
25509
|
let raw;
|
|
25300
25510
|
try {
|
|
25301
|
-
raw =
|
|
25511
|
+
raw = execFileSync14("gh", args, {
|
|
25302
25512
|
input: JSON.stringify({ body }),
|
|
25303
25513
|
encoding: "utf8"
|
|
25304
25514
|
});
|
|
@@ -25679,7 +25889,7 @@ function registerRefineLaunch(program2, resumeFlag) {
|
|
|
25679
25889
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
25680
25890
|
|
|
25681
25891
|
// src/commands/review/checkoutPr.ts
|
|
25682
|
-
import { execFileSync as
|
|
25892
|
+
import { execFileSync as execFileSync16 } from "child_process";
|
|
25683
25893
|
import chalk170 from "chalk";
|
|
25684
25894
|
|
|
25685
25895
|
// src/commands/sessions/daemon/daemonLog.ts
|
|
@@ -25705,30 +25915,19 @@ function recentDaemonLogLines(includeRelayed = true) {
|
|
|
25705
25915
|
return ring.filter((entry) => includeRelayed || !entry.relayed).map((entry) => entry.line);
|
|
25706
25916
|
}
|
|
25707
25917
|
|
|
25708
|
-
// src/commands/sessions/daemon/worktree/canonicalTreePath.ts
|
|
25709
|
-
import { realpathSync as realpathSync2 } from "fs";
|
|
25710
|
-
import { resolve as resolve16 } from "path";
|
|
25711
|
-
function canonicalTreePath(path106) {
|
|
25712
|
-
try {
|
|
25713
|
-
return realpathSync2(path106);
|
|
25714
|
-
} catch {
|
|
25715
|
-
return resolve16(path106);
|
|
25716
|
-
}
|
|
25717
|
-
}
|
|
25718
|
-
|
|
25719
25918
|
// src/commands/sessions/daemon/worktree/createWorktree.ts
|
|
25720
25919
|
import { existsSync as existsSync57 } from "fs";
|
|
25721
|
-
import { basename as
|
|
25920
|
+
import { basename as basename19, dirname as dirname29 } from "path";
|
|
25722
25921
|
|
|
25723
25922
|
// src/commands/sessions/daemon/worktree/planAllocation.ts
|
|
25724
|
-
import { basename as
|
|
25923
|
+
import { basename as basename18, join as join67 } from "path";
|
|
25725
25924
|
function planAllocation(clone, boundTreeRoots2) {
|
|
25726
25925
|
return boundTreeRoots2.has(clone) ? "spill" : "primary";
|
|
25727
25926
|
}
|
|
25728
25927
|
function nextWorktreePath(clone, base, isTaken) {
|
|
25729
|
-
const name =
|
|
25928
|
+
const name = basename18(clone);
|
|
25730
25929
|
for (let n = 2; n < 1e3; n++) {
|
|
25731
|
-
const candidate =
|
|
25930
|
+
const candidate = join67(base, `${name}-${n}`);
|
|
25732
25931
|
if (!isTaken(candidate)) return candidate;
|
|
25733
25932
|
}
|
|
25734
25933
|
throw new Error(`no free worktree suffix for ${clone}`);
|
|
@@ -25764,7 +25963,7 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
|
25764
25963
|
const base = strategy.root ? expandTilde2(strategy.root) : dirname29(clone);
|
|
25765
25964
|
const registered = new Set(listWorktreePaths(clone));
|
|
25766
25965
|
const branches = new Set(listLocalBranches(clone));
|
|
25767
|
-
const isTaken = (candidate) => registered.has(candidate) || existsSync57(candidate) || boundTreeRoots2.has(candidate) || branches.has(
|
|
25966
|
+
const isTaken = (candidate) => registered.has(candidate) || existsSync57(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename19(candidate));
|
|
25768
25967
|
const path106 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
|
|
25769
25968
|
const start2 = worktreeStartPoint(clone, strategy.trunk);
|
|
25770
25969
|
gitSync(clone, [
|
|
@@ -25772,13 +25971,13 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
|
|
|
25772
25971
|
"add",
|
|
25773
25972
|
start2.track ? "--track" : "--no-track",
|
|
25774
25973
|
"-b",
|
|
25775
|
-
|
|
25974
|
+
basename19(path106),
|
|
25776
25975
|
path106,
|
|
25777
25976
|
start2.ref
|
|
25778
25977
|
]);
|
|
25779
25978
|
recordWorktree(path106, clone, getCurrentOrigin(clone));
|
|
25780
25979
|
daemonLog(
|
|
25781
|
-
start2.track ? `worktree allocated ${path106} (branch ${
|
|
25980
|
+
start2.track ? `worktree allocated ${path106} (branch ${basename19(path106)} tracking ${start2.ref}) for clone ${clone}` : `worktree allocated ${path106} (branch ${basename19(path106)} off ${start2.ref}, no mainline tracking) for clone ${clone}`
|
|
25782
25981
|
);
|
|
25783
25982
|
return path106;
|
|
25784
25983
|
}
|
|
@@ -26080,19 +26279,19 @@ function persistedTreeRoots() {
|
|
|
26080
26279
|
|
|
26081
26280
|
// src/commands/sessions/daemon/worktree/seedWorktree.ts
|
|
26082
26281
|
import { copyFileSync, existsSync as existsSync60, mkdirSync as mkdirSync17 } from "fs";
|
|
26083
|
-
import { dirname as dirname30, join as
|
|
26282
|
+
import { dirname as dirname30, join as join69 } from "path";
|
|
26084
26283
|
|
|
26085
26284
|
// src/commands/sessions/daemon/worktree/runInstall.ts
|
|
26086
26285
|
import { resolve as resolve17 } from "path";
|
|
26087
26286
|
|
|
26088
26287
|
// src/commands/sessions/daemon/worktree/detectInstallCommand.ts
|
|
26089
26288
|
import { existsSync as existsSync59 } from "fs";
|
|
26090
|
-
import { join as
|
|
26289
|
+
import { join as join68 } from "path";
|
|
26091
26290
|
function detectInstallCommand(dir) {
|
|
26092
|
-
if (!existsSync59(
|
|
26093
|
-
if (existsSync59(
|
|
26094
|
-
if (existsSync59(
|
|
26095
|
-
if (existsSync59(
|
|
26291
|
+
if (!existsSync59(join68(dir, "package.json"))) return null;
|
|
26292
|
+
if (existsSync59(join68(dir, "pnpm-lock.yaml"))) return "pnpm install";
|
|
26293
|
+
if (existsSync59(join68(dir, "yarn.lock"))) return "yarn install";
|
|
26294
|
+
if (existsSync59(join68(dir, "bun.lockb"))) return "bun install";
|
|
26096
26295
|
return "npm install";
|
|
26097
26296
|
}
|
|
26098
26297
|
|
|
@@ -26254,9 +26453,9 @@ function seedWorktree(worktreePath, clone, onSeeded = () => {
|
|
|
26254
26453
|
}
|
|
26255
26454
|
function copyConfigFiles(worktreePath, clone, copy) {
|
|
26256
26455
|
for (const rel of copy) {
|
|
26257
|
-
const src =
|
|
26456
|
+
const src = join69(clone, rel);
|
|
26258
26457
|
if (!existsSync60(src)) continue;
|
|
26259
|
-
const dest =
|
|
26458
|
+
const dest = join69(worktreePath, rel);
|
|
26260
26459
|
try {
|
|
26261
26460
|
mkdirSync17(dirname30(dest), { recursive: true });
|
|
26262
26461
|
copyFileSync(src, dest);
|
|
@@ -26297,10 +26496,10 @@ async function moveToPrCheckoutTree() {
|
|
|
26297
26496
|
}
|
|
26298
26497
|
|
|
26299
26498
|
// src/commands/review/prHeadBranch.ts
|
|
26300
|
-
import { execFileSync as
|
|
26499
|
+
import { execFileSync as execFileSync15 } from "child_process";
|
|
26301
26500
|
function prHeadBranch(number) {
|
|
26302
26501
|
try {
|
|
26303
|
-
const out =
|
|
26502
|
+
const out = execFileSync15(
|
|
26304
26503
|
"gh",
|
|
26305
26504
|
["pr", "view", number, "--json", "headRefName", "-q", ".headRefName"],
|
|
26306
26505
|
{ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
|
|
@@ -26362,7 +26561,7 @@ async function checkoutPr(number) {
|
|
|
26362
26561
|
if (headRef && await moveToExistingCheckout(number, headRef)) return;
|
|
26363
26562
|
await moveToPrCheckoutTree();
|
|
26364
26563
|
try {
|
|
26365
|
-
|
|
26564
|
+
execFileSync16("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
26366
26565
|
} catch {
|
|
26367
26566
|
console.error(chalk170.red(`gh pr checkout ${number} failed; aborting.`));
|
|
26368
26567
|
process.exit(1);
|
|
@@ -26566,7 +26765,7 @@ import chalk175 from "chalk";
|
|
|
26566
26765
|
|
|
26567
26766
|
// src/commands/mermaid/exportFile.ts
|
|
26568
26767
|
import { readFileSync as readFileSync39, writeFileSync as writeFileSync32 } from "fs";
|
|
26569
|
-
import { basename as
|
|
26768
|
+
import { basename as basename20, extname as extname3, resolve as resolve18 } from "path";
|
|
26570
26769
|
import chalk174 from "chalk";
|
|
26571
26770
|
|
|
26572
26771
|
// src/commands/mermaid/renderBlock.ts
|
|
@@ -26593,7 +26792,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
26593
26792
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
26594
26793
|
const content = readFileSync39(file, "utf8");
|
|
26595
26794
|
const blocks = extractMermaidBlocks(content);
|
|
26596
|
-
const stem =
|
|
26795
|
+
const stem = basename20(file, extname3(file));
|
|
26597
26796
|
if (onlyIndex !== void 0) {
|
|
26598
26797
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
26599
26798
|
console.error(
|
|
@@ -27290,15 +27489,15 @@ function createNetcapHandler(options2) {
|
|
|
27290
27489
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
27291
27490
|
import { cp as cp4, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
|
|
27292
27491
|
import { networkInterfaces } from "os";
|
|
27293
|
-
import { join as
|
|
27492
|
+
import { join as join71 } from "path";
|
|
27294
27493
|
import chalk178 from "chalk";
|
|
27295
27494
|
|
|
27296
27495
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
27297
|
-
import { dirname as dirname32, join as
|
|
27496
|
+
import { dirname as dirname32, join as join70 } from "path";
|
|
27298
27497
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
27299
27498
|
var moduleDir2 = dirname32(fileURLToPath7(import.meta.url));
|
|
27300
27499
|
function netcapExtensionDir() {
|
|
27301
|
-
return
|
|
27500
|
+
return join70(moduleDir2, "commands", "netcap", "netcap-extension");
|
|
27302
27501
|
}
|
|
27303
27502
|
|
|
27304
27503
|
// src/commands/netcap/prepareExtensionForLoad.ts
|
|
@@ -27313,7 +27512,7 @@ function lanIPv4() {
|
|
|
27313
27512
|
return void 0;
|
|
27314
27513
|
}
|
|
27315
27514
|
async function configureBackground(dir, host, port, filter) {
|
|
27316
|
-
const file =
|
|
27515
|
+
const file = join71(dir, "background.js");
|
|
27317
27516
|
const source = await readFile7(file, "utf8");
|
|
27318
27517
|
await writeFile6(
|
|
27319
27518
|
file,
|
|
@@ -27353,20 +27552,20 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
27353
27552
|
}
|
|
27354
27553
|
|
|
27355
27554
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
27356
|
-
import { isAbsolute as isAbsolute5, join as
|
|
27555
|
+
import { isAbsolute as isAbsolute5, join as join73, resolve as resolve21 } from "path";
|
|
27357
27556
|
|
|
27358
27557
|
// src/commands/netcap/defaultCapturePath.ts
|
|
27359
|
-
import { homedir as
|
|
27360
|
-
import { join as
|
|
27558
|
+
import { homedir as homedir23 } from "os";
|
|
27559
|
+
import { join as join72 } from "path";
|
|
27361
27560
|
function defaultCapturePath() {
|
|
27362
|
-
return
|
|
27561
|
+
return join72(homedir23(), ".assist", "netcap", "capture.jsonl");
|
|
27363
27562
|
}
|
|
27364
27563
|
|
|
27365
27564
|
// src/commands/netcap/resolveNetcapOutPath.ts
|
|
27366
27565
|
function resolveNetcapOutPath(out) {
|
|
27367
27566
|
if (!out) return defaultCapturePath();
|
|
27368
27567
|
const dir = isAbsolute5(out) ? out : resolve21(process.cwd(), out);
|
|
27369
|
-
return
|
|
27568
|
+
return join73(dir, "capture.jsonl");
|
|
27370
27569
|
}
|
|
27371
27570
|
|
|
27372
27571
|
// src/commands/netcap/netcap.ts
|
|
@@ -27413,7 +27612,7 @@ netcap stopped \u2014 captured ${count8} ${count8 === 1 ? "entry" : "entries"} t
|
|
|
27413
27612
|
|
|
27414
27613
|
// src/commands/netcap/netcapExtract.ts
|
|
27415
27614
|
import { writeFileSync as writeFileSync34 } from "fs";
|
|
27416
|
-
import { join as
|
|
27615
|
+
import { join as join74 } from "path";
|
|
27417
27616
|
import chalk180 from "chalk";
|
|
27418
27617
|
|
|
27419
27618
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
@@ -27858,7 +28057,7 @@ function extractPostsFromCapture(captureFile) {
|
|
|
27858
28057
|
function netcapExtract(file) {
|
|
27859
28058
|
const captureFile = file ?? defaultCapturePath();
|
|
27860
28059
|
const posts = extractPostsFromCapture(captureFile);
|
|
27861
|
-
const outFile =
|
|
28060
|
+
const outFile = join74(captureFile, "..", "posts.json");
|
|
27862
28061
|
writeFileSync34(outFile, `${JSON.stringify(posts, null, 2)}
|
|
27863
28062
|
`);
|
|
27864
28063
|
console.log(
|
|
@@ -28221,18 +28420,18 @@ import { execSync as execSync41 } from "child_process";
|
|
|
28221
28420
|
import { execSync as execSync40 } from "child_process";
|
|
28222
28421
|
import { unlinkSync as unlinkSync14, writeFileSync as writeFileSync35 } from "fs";
|
|
28223
28422
|
import { tmpdir as tmpdir6 } from "os";
|
|
28224
|
-
import { join as
|
|
28423
|
+
import { join as join76 } from "path";
|
|
28225
28424
|
|
|
28226
28425
|
// src/commands/prs/loadCommentsCache.ts
|
|
28227
28426
|
import { existsSync as existsSync62, readFileSync as readFileSync43, unlinkSync as unlinkSync13 } from "fs";
|
|
28228
28427
|
import { parse as parse3 } from "yaml";
|
|
28229
28428
|
|
|
28230
28429
|
// src/commands/prs/commentsCachePath.ts
|
|
28231
|
-
import { homedir as
|
|
28232
|
-
import { join as
|
|
28430
|
+
import { homedir as homedir24 } from "os";
|
|
28431
|
+
import { join as join75 } from "path";
|
|
28233
28432
|
function commentsCachePath(org, repo, prNumber) {
|
|
28234
|
-
return
|
|
28235
|
-
|
|
28433
|
+
return join75(
|
|
28434
|
+
homedir24(),
|
|
28236
28435
|
".assist",
|
|
28237
28436
|
"pr-comments",
|
|
28238
28437
|
org,
|
|
@@ -28280,7 +28479,7 @@ function replyToComment(org, repo, prNumber, commentId, message3) {
|
|
|
28280
28479
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
28281
28480
|
function resolveThread(threadId) {
|
|
28282
28481
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
28283
|
-
const queryFile =
|
|
28482
|
+
const queryFile = join76(tmpdir6(), `gh-mutation-${Date.now()}.graphql`);
|
|
28284
28483
|
writeFileSync35(queryFile, mutation);
|
|
28285
28484
|
try {
|
|
28286
28485
|
execSync40(
|
|
@@ -28365,10 +28564,10 @@ function fixed(commentId, sha) {
|
|
|
28365
28564
|
import { execSync as execSync42 } from "child_process";
|
|
28366
28565
|
import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync36 } from "fs";
|
|
28367
28566
|
import { tmpdir as tmpdir7 } from "os";
|
|
28368
|
-
import { join as
|
|
28567
|
+
import { join as join77 } from "path";
|
|
28369
28568
|
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 } } } } } } }`;
|
|
28370
28569
|
function fetchThreadIds(org, repo, prNumber) {
|
|
28371
|
-
const queryFile =
|
|
28570
|
+
const queryFile = join77(tmpdir7(), `gh-query-${Date.now()}.graphql`);
|
|
28372
28571
|
writeFileSync36(queryFile, THREAD_QUERY);
|
|
28373
28572
|
try {
|
|
28374
28573
|
const result = execSync42(
|
|
@@ -28443,10 +28642,10 @@ import { stringify as stringify3 } from "yaml";
|
|
|
28443
28642
|
|
|
28444
28643
|
// src/commands/prs/removeStaleCommentsCaches.ts
|
|
28445
28644
|
import { readdirSync as readdirSync12, unlinkSync as unlinkSync16 } from "fs";
|
|
28446
|
-
import { join as
|
|
28645
|
+
import { join as join78 } from "path";
|
|
28447
28646
|
var STALE_PATTERN = /^pr-\d+-comments\.yaml$/;
|
|
28448
28647
|
function removeStaleCommentsCaches(cwd = process.cwd()) {
|
|
28449
|
-
const dir =
|
|
28648
|
+
const dir = join78(cwd, ".assist");
|
|
28450
28649
|
let entries;
|
|
28451
28650
|
try {
|
|
28452
28651
|
entries = readdirSync12(dir);
|
|
@@ -28454,7 +28653,7 @@ function removeStaleCommentsCaches(cwd = process.cwd()) {
|
|
|
28454
28653
|
return;
|
|
28455
28654
|
}
|
|
28456
28655
|
for (const entry of entries.filter((e) => STALE_PATTERN.test(e))) {
|
|
28457
|
-
unlinkSync16(
|
|
28656
|
+
unlinkSync16(join78(dir, entry));
|
|
28458
28657
|
}
|
|
28459
28658
|
}
|
|
28460
28659
|
|
|
@@ -29088,7 +29287,7 @@ function buildValidatedBody(options2, usage) {
|
|
|
29088
29287
|
}
|
|
29089
29288
|
|
|
29090
29289
|
// src/commands/prs/placePr.ts
|
|
29091
|
-
import { execFileSync as
|
|
29290
|
+
import { execFileSync as execFileSync17 } from "child_process";
|
|
29092
29291
|
|
|
29093
29292
|
// src/commands/prs/buildCreateArgs.ts
|
|
29094
29293
|
function buildCreateArgs(title, body, options2, attachments = []) {
|
|
@@ -29174,7 +29373,7 @@ function buildEditArgs(number, title, body, attachments = []) {
|
|
|
29174
29373
|
// src/commands/prs/placePr.ts
|
|
29175
29374
|
function hasUpstream2() {
|
|
29176
29375
|
try {
|
|
29177
|
-
|
|
29376
|
+
execFileSync17(
|
|
29178
29377
|
"git",
|
|
29179
29378
|
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
29180
29379
|
{ stdio: "pipe" }
|
|
@@ -29186,7 +29385,7 @@ function hasUpstream2() {
|
|
|
29186
29385
|
}
|
|
29187
29386
|
function ensureBranchPushed() {
|
|
29188
29387
|
const args = hasUpstream2() ? ["push"] : ["push", "--set-upstream", "origin", "HEAD"];
|
|
29189
|
-
|
|
29388
|
+
execFileSync17("git", args, { stdio: "inherit" });
|
|
29190
29389
|
}
|
|
29191
29390
|
async function placePr(prNumber, title, body, options2, attachments = []) {
|
|
29192
29391
|
const args = prNumber !== null ? buildEditArgs(prNumber, title, body, attachments) : buildCreateArgs(title, body, options2, attachments);
|
|
@@ -29332,10 +29531,10 @@ function warn(reason4) {
|
|
|
29332
29531
|
}
|
|
29333
29532
|
|
|
29334
29533
|
// src/commands/prs/enableAutoMerge.ts
|
|
29335
|
-
import { execFileSync as
|
|
29534
|
+
import { execFileSync as execFileSync18 } from "child_process";
|
|
29336
29535
|
function enableAutoMerge() {
|
|
29337
29536
|
try {
|
|
29338
|
-
|
|
29537
|
+
execFileSync18(
|
|
29339
29538
|
"gh",
|
|
29340
29539
|
["pr", "merge", getCurrentBranch2(), "--auto", "--squash"],
|
|
29341
29540
|
{ stdio: "inherit" }
|
|
@@ -31093,7 +31292,7 @@ async function notify() {
|
|
|
31093
31292
|
import { execSync as execSync52 } from "child_process";
|
|
31094
31293
|
import { existsSync as existsSync63, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync38 } from "fs";
|
|
31095
31294
|
import { tmpdir as tmpdir8 } from "os";
|
|
31096
|
-
import { join as
|
|
31295
|
+
import { join as join79, resolve as resolve22 } from "path";
|
|
31097
31296
|
import chalk205 from "chalk";
|
|
31098
31297
|
|
|
31099
31298
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -31230,7 +31429,7 @@ function buildOutputPath(outputDir, processName) {
|
|
|
31230
31429
|
return resolve22(outputDir, `${processName}-${timestamp5}.png`);
|
|
31231
31430
|
}
|
|
31232
31431
|
function runPowerShellScript(processName, outputPath) {
|
|
31233
|
-
const scriptPath =
|
|
31432
|
+
const scriptPath = join79(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
|
|
31234
31433
|
writeFileSync38(scriptPath, captureWindowPs1, "utf8");
|
|
31235
31434
|
try {
|
|
31236
31435
|
execSync52(
|
|
@@ -31345,9 +31544,9 @@ function buildLimitsSegment(rateLimits) {
|
|
|
31345
31544
|
|
|
31346
31545
|
// src/commands/readGitBranch.ts
|
|
31347
31546
|
import { readFileSync as readFileSync46, statSync as statSync10 } from "fs";
|
|
31348
|
-
import { isAbsolute as isAbsolute6, join as
|
|
31547
|
+
import { isAbsolute as isAbsolute6, join as join80, resolve as resolve23 } from "path";
|
|
31349
31548
|
function resolveGitDir(cwd) {
|
|
31350
|
-
const dotGit =
|
|
31549
|
+
const dotGit = join80(cwd, ".git");
|
|
31351
31550
|
let stat5;
|
|
31352
31551
|
try {
|
|
31353
31552
|
stat5 = statSync10(dotGit);
|
|
@@ -31377,7 +31576,7 @@ function readGitBranch(cwd) {
|
|
|
31377
31576
|
}
|
|
31378
31577
|
let head;
|
|
31379
31578
|
try {
|
|
31380
|
-
head = readFileSync46(
|
|
31579
|
+
head = readFileSync46(join80(gitDir, "HEAD"), "utf8");
|
|
31381
31580
|
} catch {
|
|
31382
31581
|
return null;
|
|
31383
31582
|
}
|
|
@@ -33798,7 +33997,7 @@ function exitWith(message3) {
|
|
|
33798
33997
|
}
|
|
33799
33998
|
|
|
33800
33999
|
// src/commands/review/highLevel/proposeHighLevelGlobs.ts
|
|
33801
|
-
import { execFileSync as
|
|
34000
|
+
import { execFileSync as execFileSync20 } from "child_process";
|
|
33802
34001
|
import chalk228 from "chalk";
|
|
33803
34002
|
|
|
33804
34003
|
// src/commands/review/highLevel/buildGlobProposalPrompt.ts
|
|
@@ -33846,7 +34045,7 @@ function readGlobs(value) {
|
|
|
33846
34045
|
}
|
|
33847
34046
|
|
|
33848
34047
|
// src/commands/review/highLevel/summariseRepoTree.ts
|
|
33849
|
-
import { execFileSync as
|
|
34048
|
+
import { execFileSync as execFileSync19 } from "child_process";
|
|
33850
34049
|
import { dirname as dirname36, extname as extname4 } from "path";
|
|
33851
34050
|
var MAX_DIRECTORIES = 200;
|
|
33852
34051
|
var MAX_EXTENSIONS_PER_DIRECTORY = 6;
|
|
@@ -33862,7 +34061,7 @@ function summariseRepoTree(cwd = process.cwd()) {
|
|
|
33862
34061
|
}
|
|
33863
34062
|
function listTrackedFiles(cwd) {
|
|
33864
34063
|
try {
|
|
33865
|
-
return
|
|
34064
|
+
return execFileSync19("git", ["ls-files"], {
|
|
33866
34065
|
cwd,
|
|
33867
34066
|
encoding: "utf8",
|
|
33868
34067
|
maxBuffer: 64 * 1024 * 1024
|
|
@@ -33907,7 +34106,7 @@ function proposeHighLevelGlobs(cwd = process.cwd()) {
|
|
|
33907
34106
|
}
|
|
33908
34107
|
function askClaude(prompt, cwd) {
|
|
33909
34108
|
try {
|
|
33910
|
-
return
|
|
34109
|
+
return execFileSync20("claude", ["-p", "--model", "sonnet", prompt], {
|
|
33911
34110
|
cwd,
|
|
33912
34111
|
encoding: "utf8",
|
|
33913
34112
|
timeout: 12e4,
|
|
@@ -34000,7 +34199,7 @@ function groupFilesByDirectory(files) {
|
|
|
34000
34199
|
}
|
|
34001
34200
|
|
|
34002
34201
|
// src/commands/review/highLevel/buildHighLevelTree.ts
|
|
34003
|
-
function
|
|
34202
|
+
function basename21(path106) {
|
|
34004
34203
|
return path106.slice(path106.lastIndexOf("/") + 1);
|
|
34005
34204
|
}
|
|
34006
34205
|
function sum(nodes, key) {
|
|
@@ -34016,7 +34215,7 @@ function nodesOf(at2, prefix2) {
|
|
|
34016
34215
|
const files = at2.files.map(
|
|
34017
34216
|
(file) => ({
|
|
34018
34217
|
kind: "file",
|
|
34019
|
-
name:
|
|
34218
|
+
name: basename21(file.path),
|
|
34020
34219
|
...file
|
|
34021
34220
|
})
|
|
34022
34221
|
);
|
|
@@ -34287,7 +34486,7 @@ function evaluateHighLevelChecks(subject) {
|
|
|
34287
34486
|
|
|
34288
34487
|
// src/commands/review/highLevel/fetchHighLevelFiles.ts
|
|
34289
34488
|
import { execSync as execSync55 } from "child_process";
|
|
34290
|
-
import { createHash as
|
|
34489
|
+
import { createHash as createHash4 } from "crypto";
|
|
34291
34490
|
var JQ = ".[] | {filename,status,additions,deletions,patch} | @json";
|
|
34292
34491
|
function toStatus(status2) {
|
|
34293
34492
|
if (status2 === "added") return "added";
|
|
@@ -34295,7 +34494,7 @@ function toStatus(status2) {
|
|
|
34295
34494
|
return "modified";
|
|
34296
34495
|
}
|
|
34297
34496
|
function diffUrl(repo, prNumber, path106) {
|
|
34298
|
-
const anchor =
|
|
34497
|
+
const anchor = createHash4("sha256").update(path106).digest("hex");
|
|
34299
34498
|
return `https://github.com/${repo}/pull/${prNumber}/files#diff-${anchor}`;
|
|
34300
34499
|
}
|
|
34301
34500
|
function fetchHighLevelFiles(prNumber, repo) {
|
|
@@ -34336,12 +34535,12 @@ function fetchHighLevelPr(prNumber, repo) {
|
|
|
34336
34535
|
import { existsSync as existsSync64, readFileSync as readFileSync47 } from "fs";
|
|
34337
34536
|
|
|
34338
34537
|
// src/commands/review/highLevel/highLevelReviewPath.ts
|
|
34339
|
-
import { join as
|
|
34538
|
+
import { join as join81 } from "path";
|
|
34340
34539
|
function slug(value) {
|
|
34341
34540
|
return value.replace(/[^\w.-]+/g, "-");
|
|
34342
34541
|
}
|
|
34343
34542
|
function highLevelReviewPath(repo, headRef, headSha) {
|
|
34344
|
-
return
|
|
34543
|
+
return join81(
|
|
34345
34544
|
getStoreDir(),
|
|
34346
34545
|
"high-level-reviews",
|
|
34347
34546
|
slug(repo),
|
|
@@ -35417,18 +35616,7 @@ import { format } from "util";
|
|
|
35417
35616
|
|
|
35418
35617
|
// src/commands/review/createReviewLogSink.ts
|
|
35419
35618
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync23 } from "fs";
|
|
35420
|
-
import { join as
|
|
35421
|
-
|
|
35422
|
-
// src/shared/stripAnsi.ts
|
|
35423
|
-
var ANSI = new RegExp(
|
|
35424
|
-
`${String.fromCharCode(27)}\\[[0-9;?]*[ -/]*[@-~]`,
|
|
35425
|
-
"g"
|
|
35426
|
-
);
|
|
35427
|
-
function stripAnsi(text17) {
|
|
35428
|
-
return text17.replace(ANSI, "");
|
|
35429
|
-
}
|
|
35430
|
-
|
|
35431
|
-
// src/commands/review/createReviewLogSink.ts
|
|
35619
|
+
import { join as join82 } from "path";
|
|
35432
35620
|
var LOG_FILE = "review.log";
|
|
35433
35621
|
function createReviewLogSink() {
|
|
35434
35622
|
let logPath2;
|
|
@@ -35445,7 +35633,7 @@ function createReviewLogSink() {
|
|
|
35445
35633
|
},
|
|
35446
35634
|
attach(reviewDir) {
|
|
35447
35635
|
mkdirSync23(reviewDir, { recursive: true });
|
|
35448
|
-
logPath2 =
|
|
35636
|
+
logPath2 = join82(reviewDir, LOG_FILE);
|
|
35449
35637
|
const lines2 = [
|
|
35450
35638
|
"",
|
|
35451
35639
|
`=== ${(/* @__PURE__ */ new Date()).toISOString()} ===`,
|
|
@@ -36526,22 +36714,22 @@ ${annotateDiffWithLineNumbers(context.diff.trimEnd())}
|
|
|
36526
36714
|
}
|
|
36527
36715
|
|
|
36528
36716
|
// src/commands/review/buildReviewPaths.ts
|
|
36529
|
-
import { homedir as
|
|
36530
|
-
import { basename as
|
|
36717
|
+
import { homedir as homedir25 } from "os";
|
|
36718
|
+
import { basename as basename22, join as join83 } from "path";
|
|
36531
36719
|
function buildReviewPaths(repoRoot2, key) {
|
|
36532
|
-
const reviewDir =
|
|
36533
|
-
|
|
36720
|
+
const reviewDir = join83(
|
|
36721
|
+
homedir25(),
|
|
36534
36722
|
".assist",
|
|
36535
36723
|
"reviews",
|
|
36536
|
-
|
|
36724
|
+
basename22(repoRoot2),
|
|
36537
36725
|
key
|
|
36538
36726
|
);
|
|
36539
36727
|
return {
|
|
36540
36728
|
reviewDir,
|
|
36541
|
-
requestPath:
|
|
36542
|
-
claudePath:
|
|
36543
|
-
codexPath:
|
|
36544
|
-
synthesisPath:
|
|
36729
|
+
requestPath: join83(reviewDir, "request.md"),
|
|
36730
|
+
claudePath: join83(reviewDir, "claude.md"),
|
|
36731
|
+
codexPath: join83(reviewDir, "codex.md"),
|
|
36732
|
+
synthesisPath: join83(reviewDir, "synthesis.md")
|
|
36545
36733
|
};
|
|
36546
36734
|
}
|
|
36547
36735
|
|
|
@@ -36995,16 +37183,16 @@ import path87 from "path";
|
|
|
36995
37183
|
import chalk239 from "chalk";
|
|
36996
37184
|
function listRules(target, options2 = {}) {
|
|
36997
37185
|
const resolved = path87.resolve(target ?? process.cwd());
|
|
36998
|
-
const
|
|
36999
|
-
if (
|
|
37186
|
+
const rules2 = readScopedRules(resolved);
|
|
37187
|
+
if (rules2.length === 0) {
|
|
37000
37188
|
const label2 = path87.relative(process.cwd(), resolved) || ".";
|
|
37001
37189
|
console.log(chalk239.gray(`No rules in scope for ${label2}`));
|
|
37002
37190
|
return;
|
|
37003
37191
|
}
|
|
37004
37192
|
const base = findRepoRoot(scopeDirectory(resolved));
|
|
37005
|
-
const width = Math.max(...
|
|
37193
|
+
const width = Math.max(...rules2.map((rule) => rule.code.length));
|
|
37006
37194
|
let shown;
|
|
37007
|
-
for (const rule of
|
|
37195
|
+
for (const rule of rules2) {
|
|
37008
37196
|
if (rule.source !== shown) {
|
|
37009
37197
|
shown = rule.source;
|
|
37010
37198
|
console.log(
|
|
@@ -37522,12 +37710,12 @@ async function reviewProposedSlackMessage(target, body, workingPath) {
|
|
|
37522
37710
|
}
|
|
37523
37711
|
|
|
37524
37712
|
// src/commands/slack/slackWorkingFile.ts
|
|
37525
|
-
import { join as
|
|
37713
|
+
import { join as join84 } from "path";
|
|
37526
37714
|
function slackWorkingFile(channel, partIndex) {
|
|
37527
37715
|
const slug2 = channel.replace(/^[#@]/, "").toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "channel";
|
|
37528
|
-
const dir =
|
|
37716
|
+
const dir = join84(getStoreDir(), "slack");
|
|
37529
37717
|
const name = partIndex === void 0 ? slug2 : `${slug2}-${partIndex}`;
|
|
37530
|
-
return { dir, bodyPath:
|
|
37718
|
+
return { dir, bodyPath: join84(dir, `${name}.md`) };
|
|
37531
37719
|
}
|
|
37532
37720
|
|
|
37533
37721
|
// src/commands/slack/previewSlackThreadParts.ts
|
|
@@ -38707,20 +38895,20 @@ async function configure() {
|
|
|
38707
38895
|
|
|
38708
38896
|
// src/commands/transcript/list.ts
|
|
38709
38897
|
import { existsSync as existsSync76, readdirSync as readdirSync20, statSync as statSync12 } from "fs";
|
|
38710
|
-
import { join as
|
|
38898
|
+
import { join as join96 } from "path";
|
|
38711
38899
|
function list3() {
|
|
38712
38900
|
const { vttDir } = getTranscriptConfig();
|
|
38713
38901
|
if (!existsSync76(vttDir)) return;
|
|
38714
38902
|
for (const entry of readdirSync20(vttDir)) {
|
|
38715
38903
|
if (!entry.endsWith(".vtt")) continue;
|
|
38716
|
-
if (statSync12(
|
|
38904
|
+
if (statSync12(join96(vttDir, entry)).isDirectory()) continue;
|
|
38717
38905
|
console.log(entry);
|
|
38718
38906
|
}
|
|
38719
38907
|
}
|
|
38720
38908
|
|
|
38721
38909
|
// src/commands/transcript/move.ts
|
|
38722
38910
|
import { existsSync as existsSync77, mkdirSync as mkdirSync32, renameSync as renameSync2, writeFileSync as writeFileSync50 } from "fs";
|
|
38723
|
-
import { basename as
|
|
38911
|
+
import { basename as basename26, join as join97 } from "path";
|
|
38724
38912
|
|
|
38725
38913
|
// src/commands/transcript/convertVttToMarkdown.ts
|
|
38726
38914
|
function convertVttToMarkdown(inputPath) {
|
|
@@ -38730,9 +38918,9 @@ function convertVttToMarkdown(inputPath) {
|
|
|
38730
38918
|
// src/commands/transcript/move.ts
|
|
38731
38919
|
var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
38732
38920
|
function archiveRawVtt(vttDir, sourcePath, filename) {
|
|
38733
|
-
const processedDir =
|
|
38921
|
+
const processedDir = join97(vttDir, "processed");
|
|
38734
38922
|
mkdirSync32(processedDir, { recursive: true });
|
|
38735
|
-
renameSync2(sourcePath,
|
|
38923
|
+
renameSync2(sourcePath, join97(processedDir, filename));
|
|
38736
38924
|
}
|
|
38737
38925
|
function move(file, options2) {
|
|
38738
38926
|
const { date, client } = options2;
|
|
@@ -38741,27 +38929,27 @@ function move(file, options2) {
|
|
|
38741
38929
|
process.exit(1);
|
|
38742
38930
|
}
|
|
38743
38931
|
const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
38744
|
-
const filename =
|
|
38745
|
-
const sourcePath =
|
|
38932
|
+
const filename = basename26(file);
|
|
38933
|
+
const sourcePath = join97(vttDir, filename);
|
|
38746
38934
|
if (!existsSync77(sourcePath)) {
|
|
38747
38935
|
console.error(`Error: VTT file not found: ${sourcePath}`);
|
|
38748
38936
|
process.exit(1);
|
|
38749
38937
|
}
|
|
38750
|
-
const base =
|
|
38938
|
+
const base = basename26(filename, ".vtt").replace(/ Transcription$/, "");
|
|
38751
38939
|
const outputName = `${date} ${base}.md`;
|
|
38752
|
-
const formattedDir =
|
|
38940
|
+
const formattedDir = join97(transcriptsDir, client);
|
|
38753
38941
|
mkdirSync32(formattedDir, { recursive: true });
|
|
38754
|
-
const formattedPath =
|
|
38942
|
+
const formattedPath = join97(formattedDir, outputName);
|
|
38755
38943
|
writeFileSync50(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
|
|
38756
38944
|
archiveRawVtt(vttDir, sourcePath, filename);
|
|
38757
|
-
const summaryPath =
|
|
38945
|
+
const summaryPath = join97(summaryDir, client, outputName);
|
|
38758
38946
|
console.log(`Formatted transcript: ${formattedPath}`);
|
|
38759
38947
|
console.log(`Summary target: ${summaryPath}`);
|
|
38760
38948
|
}
|
|
38761
38949
|
|
|
38762
38950
|
// src/commands/transcript/merge.ts
|
|
38763
38951
|
import { existsSync as existsSync78, writeFileSync as writeFileSync51 } from "fs";
|
|
38764
|
-
import { basename as
|
|
38952
|
+
import { basename as basename27 } from "path";
|
|
38765
38953
|
|
|
38766
38954
|
// src/commands/transcript/failTranscript.ts
|
|
38767
38955
|
function failTranscript(message3) {
|
|
@@ -38907,7 +39095,7 @@ function readSource3(file) {
|
|
|
38907
39095
|
if (!existsSync78(file)) failTranscript(`VTT file not found: ${file}`);
|
|
38908
39096
|
const cues = readCleanedCues(file);
|
|
38909
39097
|
if (cues.length === 0) failTranscript(`no cues found in: ${file}`);
|
|
38910
|
-
return { path: file, name:
|
|
39098
|
+
return { path: file, name: basename27(file), cues };
|
|
38911
39099
|
}
|
|
38912
39100
|
function wholePassages(sources) {
|
|
38913
39101
|
return sources.map((source) => ({
|
|
@@ -39398,14 +39586,14 @@ function findRuleViolations(data, rule) {
|
|
|
39398
39586
|
}
|
|
39399
39587
|
return violations;
|
|
39400
39588
|
}
|
|
39401
|
-
function findForbiddenStrings(
|
|
39402
|
-
return
|
|
39589
|
+
function findForbiddenStrings(rules2, readJson) {
|
|
39590
|
+
return rules2.flatMap((rule) => findRuleViolations(readJson(rule.file), rule));
|
|
39403
39591
|
}
|
|
39404
39592
|
|
|
39405
39593
|
// src/commands/verify/forbiddenStrings.ts
|
|
39406
39594
|
function forbiddenStrings() {
|
|
39407
|
-
const
|
|
39408
|
-
if (
|
|
39595
|
+
const rules2 = loadConfig().forbiddenStrings ?? [];
|
|
39596
|
+
if (rules2.length === 0) {
|
|
39409
39597
|
console.log("No forbidden-strings rules configured.");
|
|
39410
39598
|
process.exit(0);
|
|
39411
39599
|
}
|
|
@@ -39426,7 +39614,7 @@ function forbiddenStrings() {
|
|
|
39426
39614
|
cache6.set(file, parsed);
|
|
39427
39615
|
return parsed;
|
|
39428
39616
|
};
|
|
39429
|
-
const violations = findForbiddenStrings(
|
|
39617
|
+
const violations = findForbiddenStrings(rules2, readJson);
|
|
39430
39618
|
if (violations.length === 0) {
|
|
39431
39619
|
console.log("No forbidden strings found.");
|
|
39432
39620
|
process.exit(0);
|
|
@@ -39568,7 +39756,7 @@ function listMigrationFiles(dir) {
|
|
|
39568
39756
|
|
|
39569
39757
|
// src/commands/verify/migrations/readBaselineMigrations.ts
|
|
39570
39758
|
import { execSync as execSync63 } from "child_process";
|
|
39571
|
-
import { basename as
|
|
39759
|
+
import { basename as basename28 } from "path";
|
|
39572
39760
|
var MIGRATION_FILE3 = /^migration\d+[A-Za-z0-9]*\.ts$/;
|
|
39573
39761
|
function readBaselineMigrations(repoRelativeDir, ref) {
|
|
39574
39762
|
const baseline = /* @__PURE__ */ new Map();
|
|
@@ -39581,7 +39769,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
39581
39769
|
} catch {
|
|
39582
39770
|
return baseline;
|
|
39583
39771
|
}
|
|
39584
|
-
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path106) => MIGRATION_FILE3.test(
|
|
39772
|
+
const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path106) => MIGRATION_FILE3.test(basename28(path106)));
|
|
39585
39773
|
for (const path106 of paths) {
|
|
39586
39774
|
try {
|
|
39587
39775
|
const content = execSync63(`git show "${ref}:${path106}"`, {
|
|
@@ -39589,7 +39777,7 @@ function readBaselineMigrations(repoRelativeDir, ref) {
|
|
|
39589
39777
|
maxBuffer: 16 * 1024 * 1024,
|
|
39590
39778
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39591
39779
|
});
|
|
39592
|
-
baseline.set(
|
|
39780
|
+
baseline.set(basename28(path106), content);
|
|
39593
39781
|
} catch {
|
|
39594
39782
|
}
|
|
39595
39783
|
}
|
|
@@ -39802,46 +39990,6 @@ function gitFailureReason(error) {
|
|
|
39802
39990
|
return message3.trim() || "git failed without reporting a reason";
|
|
39803
39991
|
}
|
|
39804
39992
|
|
|
39805
|
-
// src/commands/watch/resolveUpstream.ts
|
|
39806
|
-
import { execFileSync as execFileSync20 } from "child_process";
|
|
39807
|
-
function runGit3(args, cwd) {
|
|
39808
|
-
return execFileSync20("git", args, {
|
|
39809
|
-
encoding: "utf8",
|
|
39810
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
39811
|
-
cwd
|
|
39812
|
-
}).trim();
|
|
39813
|
-
}
|
|
39814
|
-
function resolveUpstream(cwd) {
|
|
39815
|
-
try {
|
|
39816
|
-
runGit3(["rev-parse", "--is-inside-work-tree"], cwd);
|
|
39817
|
-
} catch {
|
|
39818
|
-
throw new Error(
|
|
39819
|
-
"not a git repository \u2014 run assist watch wait from inside a repo"
|
|
39820
|
-
);
|
|
39821
|
-
}
|
|
39822
|
-
let branch2;
|
|
39823
|
-
try {
|
|
39824
|
-
branch2 = runGit3(["symbolic-ref", "--quiet", "--short", "HEAD"], cwd);
|
|
39825
|
-
} catch {
|
|
39826
|
-
throw new Error(
|
|
39827
|
-
"HEAD is detached \u2014 check out a branch before waiting on its upstream"
|
|
39828
|
-
);
|
|
39829
|
-
}
|
|
39830
|
-
try {
|
|
39831
|
-
return {
|
|
39832
|
-
branch: branch2,
|
|
39833
|
-
upstream: runGit3(
|
|
39834
|
-
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
39835
|
-
cwd
|
|
39836
|
-
)
|
|
39837
|
-
};
|
|
39838
|
-
} catch {
|
|
39839
|
-
throw new Error(
|
|
39840
|
-
`branch "${branch2}" has no upstream \u2014 set one with: git push -u origin ${branch2}`
|
|
39841
|
-
);
|
|
39842
|
-
}
|
|
39843
|
-
}
|
|
39844
|
-
|
|
39845
39993
|
// src/commands/watch/simulatedDivergencePath.ts
|
|
39846
39994
|
import { resolve as resolve25 } from "path";
|
|
39847
39995
|
function simulatedDivergencePath(cwd) {
|
|
@@ -39909,22 +40057,6 @@ async function watchLoop() {
|
|
|
39909
40057
|
}
|
|
39910
40058
|
}
|
|
39911
40059
|
|
|
39912
|
-
// src/commands/watch/changedPaths.ts
|
|
39913
|
-
function changedPaths(from, cwd) {
|
|
39914
|
-
return runGit3(["diff", "--name-only", `${from}..HEAD`], cwd).split("\n").filter((line) => line.length > 0);
|
|
39915
|
-
}
|
|
39916
|
-
|
|
39917
|
-
// src/commands/watch/readBuiltVersion.ts
|
|
39918
|
-
import { join as join96 } from "path";
|
|
39919
|
-
function readBuiltVersion(cwd) {
|
|
39920
|
-
try {
|
|
39921
|
-
const root2 = runGit3(["rev-parse", "--show-toplevel"], cwd);
|
|
39922
|
-
return readPackageJson(join96(root2, "package.json")).version ?? "unknown";
|
|
39923
|
-
} catch {
|
|
39924
|
-
return "unknown";
|
|
39925
|
-
}
|
|
39926
|
-
}
|
|
39927
|
-
|
|
39928
40060
|
// src/commands/watch/readRecentCommits.ts
|
|
39929
40061
|
function readRecentCommits(count8 = 10, cwd) {
|
|
39930
40062
|
const output = runGit3(
|
|
@@ -39972,24 +40104,12 @@ function renderWatchReport({
|
|
|
39972
40104
|
}
|
|
39973
40105
|
|
|
39974
40106
|
// src/commands/watch/restartAdvice.ts
|
|
39975
|
-
var webUiPrefix = "src/commands/sessions/web/ui/";
|
|
39976
|
-
var sessionsPrefix = "src/commands/sessions/";
|
|
39977
|
-
var rules = [
|
|
39978
|
-
{
|
|
39979
|
-
matches: (path106) => path106.startsWith(webUiPrefix),
|
|
39980
|
-
advice: "restart the web server, then hard-reload the browser tab"
|
|
39981
|
-
},
|
|
39982
|
-
{
|
|
39983
|
-
matches: (path106) => path106.startsWith(sessionsPrefix) && !path106.startsWith(webUiPrefix),
|
|
39984
|
-
advice: "restart the daemon"
|
|
39985
|
-
}
|
|
39986
|
-
];
|
|
39987
40107
|
function restartAdvice(paths) {
|
|
39988
|
-
return
|
|
40108
|
+
return restartRules.filter((rule) => paths.some(rule.matches)).map((rule) => rule.advice);
|
|
39989
40109
|
}
|
|
39990
40110
|
|
|
39991
40111
|
// src/commands/watch/syncAdvice.ts
|
|
39992
|
-
var
|
|
40112
|
+
var rules = [
|
|
39993
40113
|
{
|
|
39994
40114
|
matches: (path106) => path106.startsWith("claude/commands/"),
|
|
39995
40115
|
reason: "claude/commands changed"
|
|
@@ -40016,7 +40136,7 @@ var rules2 = [
|
|
|
40016
40136
|
}
|
|
40017
40137
|
];
|
|
40018
40138
|
function syncAdvice(paths) {
|
|
40019
|
-
return
|
|
40139
|
+
return rules.filter((rule) => paths.some(rule.matches)).map((rule) => rule.reason);
|
|
40020
40140
|
}
|
|
40021
40141
|
|
|
40022
40142
|
// src/commands/watch/buildWatchReport.ts
|
|
@@ -40702,7 +40822,7 @@ async function auth() {
|
|
|
40702
40822
|
// src/commands/roam/postRoamActivity.ts
|
|
40703
40823
|
import { execFileSync as execFileSync22 } from "child_process";
|
|
40704
40824
|
import { readdirSync as readdirSync22, readFileSync as readFileSync62, statSync as statSync13 } from "fs";
|
|
40705
|
-
import { join as
|
|
40825
|
+
import { join as join98 } from "path";
|
|
40706
40826
|
function findPortFile(roamDir) {
|
|
40707
40827
|
let entries;
|
|
40708
40828
|
try {
|
|
@@ -40711,7 +40831,7 @@ function findPortFile(roamDir) {
|
|
|
40711
40831
|
return void 0;
|
|
40712
40832
|
}
|
|
40713
40833
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
40714
|
-
const path106 =
|
|
40834
|
+
const path106 = join98(roamDir, name);
|
|
40715
40835
|
try {
|
|
40716
40836
|
return { path: path106, mtimeMs: statSync13(path106).mtimeMs };
|
|
40717
40837
|
} catch {
|
|
@@ -40728,7 +40848,7 @@ var PID_BY_APP = {
|
|
|
40728
40848
|
function postRoamActivity(app, event) {
|
|
40729
40849
|
const appData = process.env.APPDATA;
|
|
40730
40850
|
if (!appData) return;
|
|
40731
|
-
const portFile = findPortFile(
|
|
40851
|
+
const portFile = findPortFile(join98(appData, "Roam"));
|
|
40732
40852
|
if (!portFile) return;
|
|
40733
40853
|
let port;
|
|
40734
40854
|
try {
|
|
@@ -40864,7 +40984,7 @@ async function run3(name, args) {
|
|
|
40864
40984
|
|
|
40865
40985
|
// src/commands/run/add.ts
|
|
40866
40986
|
import { mkdirSync as mkdirSync33, writeFileSync as writeFileSync53 } from "fs";
|
|
40867
|
-
import { join as
|
|
40987
|
+
import { join as join99 } from "path";
|
|
40868
40988
|
|
|
40869
40989
|
// src/commands/run/extractOption.ts
|
|
40870
40990
|
function extractOption(args, flag) {
|
|
@@ -40925,7 +41045,7 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
40925
41045
|
saveConfig(config);
|
|
40926
41046
|
}
|
|
40927
41047
|
function createCommandFile(name) {
|
|
40928
|
-
const dir =
|
|
41048
|
+
const dir = join99(".claude", "commands");
|
|
40929
41049
|
mkdirSync33(dir, { recursive: true });
|
|
40930
41050
|
const content = `---
|
|
40931
41051
|
description: Run ${name}
|
|
@@ -40933,7 +41053,7 @@ description: Run ${name}
|
|
|
40933
41053
|
|
|
40934
41054
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
40935
41055
|
`;
|
|
40936
|
-
const filePath =
|
|
41056
|
+
const filePath = join99(dir, `${name}.md`);
|
|
40937
41057
|
writeFileSync53(filePath, content);
|
|
40938
41058
|
console.log(`Created command file: ${filePath}`);
|
|
40939
41059
|
}
|
|
@@ -40990,7 +41110,7 @@ function link2() {
|
|
|
40990
41110
|
|
|
40991
41111
|
// src/commands/run/remove.ts
|
|
40992
41112
|
import { existsSync as existsSync82, unlinkSync as unlinkSync21 } from "fs";
|
|
40993
|
-
import { join as
|
|
41113
|
+
import { join as join100 } from "path";
|
|
40994
41114
|
function findRemoveIndex() {
|
|
40995
41115
|
const idx = process.argv.indexOf("remove");
|
|
40996
41116
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -41005,7 +41125,7 @@ function parseRemoveName() {
|
|
|
41005
41125
|
return process.argv[idx + 1];
|
|
41006
41126
|
}
|
|
41007
41127
|
function deleteCommandFile(name) {
|
|
41008
|
-
const filePath =
|
|
41128
|
+
const filePath = join100(".claude", "commands", `${name}.md`);
|
|
41009
41129
|
if (existsSync82(filePath)) {
|
|
41010
41130
|
unlinkSync21(filePath);
|
|
41011
41131
|
console.log(`Deleted command file: ${filePath}`);
|
|
@@ -41996,7 +42116,116 @@ function createRunSession(id, { runName, runArgs, cwd, meta }) {
|
|
|
41996
42116
|
};
|
|
41997
42117
|
}
|
|
41998
42118
|
|
|
41999
|
-
// src/commands/sessions/daemon/autoUpdate/
|
|
42119
|
+
// src/commands/sessions/daemon/autoUpdate/autoUpdateEnabled.ts
|
|
42120
|
+
function autoUpdateEnabled(installDir) {
|
|
42121
|
+
try {
|
|
42122
|
+
return loadConfigFrom(installDir).autoUpdate?.enabled ?? true;
|
|
42123
|
+
} catch (error) {
|
|
42124
|
+
daemonLog(
|
|
42125
|
+
`auto-update: config failed to load, keeping the default (on): ${error instanceof Error ? error.message : String(error)}`
|
|
42126
|
+
);
|
|
42127
|
+
return true;
|
|
42128
|
+
}
|
|
42129
|
+
}
|
|
42130
|
+
|
|
42131
|
+
// src/commands/sessions/daemon/autoUpdate/autoUpdateState.ts
|
|
42132
|
+
var loop = {
|
|
42133
|
+
phase: "off",
|
|
42134
|
+
since: (/* @__PURE__ */ new Date()).toISOString(),
|
|
42135
|
+
reason: "not started"
|
|
42136
|
+
};
|
|
42137
|
+
var startCommit;
|
|
42138
|
+
var autoUpdateState = {
|
|
42139
|
+
loop: () => loop,
|
|
42140
|
+
startCommit: () => startCommit,
|
|
42141
|
+
setStartCommit: (commit2) => {
|
|
42142
|
+
startCommit = commit2;
|
|
42143
|
+
},
|
|
42144
|
+
enter: (phase, extra = {}) => {
|
|
42145
|
+
loop = { phase, since: (/* @__PURE__ */ new Date()).toISOString(), ...extra };
|
|
42146
|
+
}
|
|
42147
|
+
};
|
|
42148
|
+
|
|
42149
|
+
// src/commands/sessions/daemon/autoUpdate/holdForEscalation.ts
|
|
42150
|
+
var ESCALATION_POLL_MS = 5e3;
|
|
42151
|
+
async function holdForEscalation(sessionId, deps2) {
|
|
42152
|
+
deps2.enter("diverged", { escalationId: sessionId });
|
|
42153
|
+
deps2.note(`paused while session ${sessionId} reconciles the divergence`);
|
|
42154
|
+
while (deps2.isLive(sessionId)) await deps2.sleep(ESCALATION_POLL_MS);
|
|
42155
|
+
deps2.note(`session ${sessionId} ended; resuming`);
|
|
42156
|
+
}
|
|
42157
|
+
|
|
42158
|
+
// src/commands/sessions/daemon/autoUpdate/runLapCapturingTail.ts
|
|
42159
|
+
var OUTPUT_TAIL = 16 * 1024;
|
|
42160
|
+
async function runLapCapturingTail(deps2) {
|
|
42161
|
+
let tail = "";
|
|
42162
|
+
const end = await deps2.runLap((text17) => {
|
|
42163
|
+
tail = (tail + text17).slice(-OUTPUT_TAIL);
|
|
42164
|
+
deps2.record(text17);
|
|
42165
|
+
});
|
|
42166
|
+
return { end, tail };
|
|
42167
|
+
}
|
|
42168
|
+
|
|
42169
|
+
// src/commands/sessions/daemon/autoUpdate/runAutoUpdateLoop.ts
|
|
42170
|
+
var DIVERGED_EXIT_CODE = 3;
|
|
42171
|
+
var RETRY_AFTER_FAILURE_MS = 5 * 60 * 1e3;
|
|
42172
|
+
async function runAutoUpdateLoop(deps2, maxLaps = Number.POSITIVE_INFINITY) {
|
|
42173
|
+
let held = deps2.liveEscalation();
|
|
42174
|
+
for (let lap = 1; lap <= maxLaps; lap++) {
|
|
42175
|
+
if (held) await holdForEscalation(held, deps2);
|
|
42176
|
+
held = void 0;
|
|
42177
|
+
deps2.enter("waiting");
|
|
42178
|
+
deps2.note(
|
|
42179
|
+
`lap ${lap} at ${(/* @__PURE__ */ new Date()).toLocaleString()}: assist ${WATCH_LAP_ARGS.join(" ")}`
|
|
42180
|
+
);
|
|
42181
|
+
let result;
|
|
42182
|
+
try {
|
|
42183
|
+
result = await runLapCapturingTail(deps2);
|
|
42184
|
+
} catch (error) {
|
|
42185
|
+
await backOff(
|
|
42186
|
+
`lap ${lap} could not start (${error instanceof Error ? error.message : String(error)})`,
|
|
42187
|
+
deps2
|
|
42188
|
+
);
|
|
42189
|
+
continue;
|
|
42190
|
+
}
|
|
42191
|
+
const { end, tail } = result;
|
|
42192
|
+
const how = end.signal ? `killed by ${end.signal}` : `exited ${end.code}`;
|
|
42193
|
+
if (end.code === DIVERGED_EXIT_CODE) {
|
|
42194
|
+
held = deps2.escalate(tail);
|
|
42195
|
+
deps2.note(`lap ${lap} ${how} (divergence); escalated to session ${held}`);
|
|
42196
|
+
continue;
|
|
42197
|
+
}
|
|
42198
|
+
if (decideLap(end, false).kind === "relaunch") {
|
|
42199
|
+
deps2.note(`lap ${lap} ${how}; relaunching`);
|
|
42200
|
+
continue;
|
|
42201
|
+
}
|
|
42202
|
+
await backOff(`lap ${lap} ${how}`, deps2);
|
|
42203
|
+
}
|
|
42204
|
+
}
|
|
42205
|
+
async function backOff(reason4, deps2) {
|
|
42206
|
+
deps2.enter("retrying", { reason: reason4 });
|
|
42207
|
+
deps2.note(`${reason4}; retrying in ${RETRY_AFTER_FAILURE_MS / 6e4}m`);
|
|
42208
|
+
await deps2.sleep(RETRY_AFTER_FAILURE_MS);
|
|
42209
|
+
}
|
|
42210
|
+
|
|
42211
|
+
// src/commands/sessions/daemon/autoUpdate/trimWatcherLog.ts
|
|
42212
|
+
import { readFileSync as readFileSync65, writeFileSync as writeFileSync54 } from "fs";
|
|
42213
|
+
var KEEP_TAIL = 256 * 1024;
|
|
42214
|
+
var MAX_LOG_SIZE = 4 * 1024 * 1024;
|
|
42215
|
+
function trimWatcherLog(cwd) {
|
|
42216
|
+
const path106 = watcherLogPath(cwd);
|
|
42217
|
+
let log2;
|
|
42218
|
+
try {
|
|
42219
|
+
log2 = readFileSync65(path106, "utf8");
|
|
42220
|
+
} catch {
|
|
42221
|
+
return;
|
|
42222
|
+
}
|
|
42223
|
+
if (log2.length <= MAX_LOG_SIZE) return;
|
|
42224
|
+
writeFileSync54(path106, log2.slice(-KEEP_TAIL));
|
|
42225
|
+
daemonLog(`auto-update: log ${path106} trimmed to its last ${KEEP_TAIL} chars`);
|
|
42226
|
+
}
|
|
42227
|
+
|
|
42228
|
+
// src/commands/sessions/daemon/autoUpdate/loopDeps.ts
|
|
42000
42229
|
import { setTimeout as sleep2 } from "timers/promises";
|
|
42001
42230
|
|
|
42002
42231
|
// src/commands/sessions/daemon/watcherNote.ts
|
|
@@ -42009,19 +42238,6 @@ function watcherNote(text17) {
|
|
|
42009
42238
|
// src/commands/sessions/daemon/worktree/appendWatcherLog.ts
|
|
42010
42239
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync34 } from "fs";
|
|
42011
42240
|
import { dirname as dirname42 } from "path";
|
|
42012
|
-
|
|
42013
|
-
// src/commands/sessions/daemon/worktree/watcherLogPath.ts
|
|
42014
|
-
import { createHash as createHash4 } from "crypto";
|
|
42015
|
-
import { homedir as homedir26 } from "os";
|
|
42016
|
-
import { basename as basename28, join as join101 } from "path";
|
|
42017
|
-
function watcherLogPath(cwd) {
|
|
42018
|
-
const clone = canonicalTreePath(cwd);
|
|
42019
|
-
const key = createHash4("sha1").update(clone).digest("hex").slice(0, 8);
|
|
42020
|
-
const dir = process.env.ASSIST_WATCHER_LOG_DIR ?? join101(homedir26(), ".assist", "watchers");
|
|
42021
|
-
return join101(dir, `${basename28(clone) || "root"}-${key}.log`);
|
|
42022
|
-
}
|
|
42023
|
-
|
|
42024
|
-
// src/commands/sessions/daemon/worktree/appendWatcherLog.ts
|
|
42025
42241
|
function appendWatcherLog(cwd, data) {
|
|
42026
42242
|
try {
|
|
42027
42243
|
const path106 = watcherLogPath(cwd);
|
|
@@ -42175,18 +42391,6 @@ function escalateDivergence(ctx, cwd, output) {
|
|
|
42175
42391
|
return id;
|
|
42176
42392
|
}
|
|
42177
42393
|
|
|
42178
|
-
// src/commands/sessions/daemon/autoUpdate/autoUpdateEnabled.ts
|
|
42179
|
-
function autoUpdateEnabled(installDir) {
|
|
42180
|
-
try {
|
|
42181
|
-
return loadConfigFrom(installDir).autoUpdate?.enabled ?? true;
|
|
42182
|
-
} catch (error) {
|
|
42183
|
-
daemonLog(
|
|
42184
|
-
`auto-update: config failed to load, keeping the default (on): ${error instanceof Error ? error.message : String(error)}`
|
|
42185
|
-
);
|
|
42186
|
-
return true;
|
|
42187
|
-
}
|
|
42188
|
-
}
|
|
42189
|
-
|
|
42190
42394
|
// src/commands/sessions/daemon/autoUpdate/lineRecorder.ts
|
|
42191
42395
|
function lineRecorder(onLine) {
|
|
42192
42396
|
let pending = "";
|
|
@@ -42200,64 +42404,6 @@ function lineRecorder(onLine) {
|
|
|
42200
42404
|
};
|
|
42201
42405
|
}
|
|
42202
42406
|
|
|
42203
|
-
// src/commands/sessions/daemon/autoUpdate/holdForEscalation.ts
|
|
42204
|
-
var ESCALATION_POLL_MS = 5e3;
|
|
42205
|
-
async function holdForEscalation(sessionId, deps2) {
|
|
42206
|
-
deps2.note(`paused while session ${sessionId} reconciles the divergence`);
|
|
42207
|
-
while (deps2.isLive(sessionId)) await deps2.sleep(ESCALATION_POLL_MS);
|
|
42208
|
-
deps2.note(`session ${sessionId} ended; resuming`);
|
|
42209
|
-
}
|
|
42210
|
-
|
|
42211
|
-
// src/commands/sessions/daemon/autoUpdate/runLapCapturingTail.ts
|
|
42212
|
-
var OUTPUT_TAIL = 16 * 1024;
|
|
42213
|
-
async function runLapCapturingTail(deps2) {
|
|
42214
|
-
let tail = "";
|
|
42215
|
-
const end = await deps2.runLap((text17) => {
|
|
42216
|
-
tail = (tail + text17).slice(-OUTPUT_TAIL);
|
|
42217
|
-
deps2.record(text17);
|
|
42218
|
-
});
|
|
42219
|
-
return { end, tail };
|
|
42220
|
-
}
|
|
42221
|
-
|
|
42222
|
-
// src/commands/sessions/daemon/autoUpdate/runAutoUpdateLoop.ts
|
|
42223
|
-
var DIVERGED_EXIT_CODE = 3;
|
|
42224
|
-
var RETRY_AFTER_FAILURE_MS = 5 * 60 * 1e3;
|
|
42225
|
-
async function runAutoUpdateLoop(deps2, maxLaps = Number.POSITIVE_INFINITY) {
|
|
42226
|
-
let held = deps2.liveEscalation();
|
|
42227
|
-
for (let lap = 1; lap <= maxLaps; lap++) {
|
|
42228
|
-
if (held) await holdForEscalation(held, deps2);
|
|
42229
|
-
held = void 0;
|
|
42230
|
-
deps2.note(
|
|
42231
|
-
`lap ${lap} at ${(/* @__PURE__ */ new Date()).toLocaleString()}: assist ${WATCH_LAP_ARGS.join(" ")}`
|
|
42232
|
-
);
|
|
42233
|
-
let result;
|
|
42234
|
-
try {
|
|
42235
|
-
result = await runLapCapturingTail(deps2);
|
|
42236
|
-
} catch (error) {
|
|
42237
|
-
deps2.note(
|
|
42238
|
-
`lap ${lap} could not start (${error instanceof Error ? error.message : String(error)}); retrying in ${RETRY_AFTER_FAILURE_MS / 6e4}m`
|
|
42239
|
-
);
|
|
42240
|
-
await deps2.sleep(RETRY_AFTER_FAILURE_MS);
|
|
42241
|
-
continue;
|
|
42242
|
-
}
|
|
42243
|
-
const { end, tail } = result;
|
|
42244
|
-
const how = end.signal ? `killed by ${end.signal}` : `exited ${end.code}`;
|
|
42245
|
-
if (end.code === DIVERGED_EXIT_CODE) {
|
|
42246
|
-
held = deps2.escalate(tail);
|
|
42247
|
-
deps2.note(`lap ${lap} ${how} (divergence); escalated to session ${held}`);
|
|
42248
|
-
continue;
|
|
42249
|
-
}
|
|
42250
|
-
if (decideLap(end, false).kind === "relaunch") {
|
|
42251
|
-
deps2.note(`lap ${lap} ${how}; relaunching`);
|
|
42252
|
-
continue;
|
|
42253
|
-
}
|
|
42254
|
-
deps2.note(
|
|
42255
|
-
`lap ${lap} ${how}; retrying in ${RETRY_AFTER_FAILURE_MS / 6e4}m`
|
|
42256
|
-
);
|
|
42257
|
-
await deps2.sleep(RETRY_AFTER_FAILURE_MS);
|
|
42258
|
-
}
|
|
42259
|
-
}
|
|
42260
|
-
|
|
42261
42407
|
// src/commands/sessions/daemon/autoUpdate/runUpdateLap.ts
|
|
42262
42408
|
import { spawn as spawn11 } from "child_process";
|
|
42263
42409
|
function runUpdateLap(cwd, onOutput) {
|
|
@@ -42290,24 +42436,7 @@ function runUpdateLap(cwd, onOutput) {
|
|
|
42290
42436
|
});
|
|
42291
42437
|
}
|
|
42292
42438
|
|
|
42293
|
-
// src/commands/sessions/daemon/autoUpdate/
|
|
42294
|
-
import { readFileSync as readFileSync65, writeFileSync as writeFileSync54 } from "fs";
|
|
42295
|
-
var KEEP_TAIL = 256 * 1024;
|
|
42296
|
-
var MAX_LOG_SIZE = 4 * 1024 * 1024;
|
|
42297
|
-
function trimWatcherLog(cwd) {
|
|
42298
|
-
const path106 = watcherLogPath(cwd);
|
|
42299
|
-
let log2;
|
|
42300
|
-
try {
|
|
42301
|
-
log2 = readFileSync65(path106, "utf8");
|
|
42302
|
-
} catch {
|
|
42303
|
-
return;
|
|
42304
|
-
}
|
|
42305
|
-
if (log2.length <= MAX_LOG_SIZE) return;
|
|
42306
|
-
writeFileSync54(path106, log2.slice(-KEEP_TAIL));
|
|
42307
|
-
daemonLog(`auto-update: log ${path106} trimmed to its last ${KEEP_TAIL} chars`);
|
|
42308
|
-
}
|
|
42309
|
-
|
|
42310
|
-
// src/commands/sessions/daemon/autoUpdate/startAutoUpdate.ts
|
|
42439
|
+
// src/commands/sessions/daemon/autoUpdate/loopDeps.ts
|
|
42311
42440
|
function loopDeps(installDir, ctx) {
|
|
42312
42441
|
const clone = canonicalTreePath(installDir);
|
|
42313
42442
|
const logLine = lineRecorder((line) => daemonLog(`auto-update: ${line}`));
|
|
@@ -42321,6 +42450,7 @@ function loopDeps(installDir, ctx) {
|
|
|
42321
42450
|
appendWatcherLog(installDir, watcherNote(text17));
|
|
42322
42451
|
daemonLog(`auto-update: ${text17}`);
|
|
42323
42452
|
},
|
|
42453
|
+
enter: autoUpdateState.enter,
|
|
42324
42454
|
liveEscalation: () => liveEscalationIn(ctx().sessions, clone)?.id,
|
|
42325
42455
|
escalate: (output) => escalateDivergence(ctx(), installDir, output),
|
|
42326
42456
|
isLive: (sessionId) => {
|
|
@@ -42330,14 +42460,21 @@ function loopDeps(installDir, ctx) {
|
|
|
42330
42460
|
sleep: (ms) => sleep2(ms)
|
|
42331
42461
|
};
|
|
42332
42462
|
}
|
|
42463
|
+
|
|
42464
|
+
// src/commands/sessions/daemon/autoUpdate/startAutoUpdate.ts
|
|
42465
|
+
function stayOff(reason4) {
|
|
42466
|
+
autoUpdateState.enter("off", { reason: reason4 });
|
|
42467
|
+
daemonLog(`auto-update: off (${reason4})`);
|
|
42468
|
+
}
|
|
42333
42469
|
function startAutoUpdate(ctx) {
|
|
42334
42470
|
const installDir = getInstallDir();
|
|
42335
|
-
if (!
|
|
42336
|
-
|
|
42471
|
+
if (!isGitRepo(installDir)) {
|
|
42472
|
+
stayOff(`${installDir} is not a git clone`);
|
|
42337
42473
|
return;
|
|
42338
42474
|
}
|
|
42339
|
-
|
|
42340
|
-
|
|
42475
|
+
autoUpdateState.setStartCommit(headCommit3(installDir));
|
|
42476
|
+
if (!autoUpdateEnabled(installDir)) {
|
|
42477
|
+
stayOff("autoUpdate.enabled is false");
|
|
42341
42478
|
return;
|
|
42342
42479
|
}
|
|
42343
42480
|
trimWatcherLog(installDir);
|
|
@@ -47014,6 +47151,16 @@ function exitAfterFlush(code) {
|
|
|
47014
47151
|
// src/commands/sessions/daemon/handleConnection.ts
|
|
47015
47152
|
import { createInterface as createInterface10 } from "readline";
|
|
47016
47153
|
|
|
47154
|
+
// src/commands/sessions/daemon/autoUpdate/autoUpdateReply.ts
|
|
47155
|
+
function autoUpdateReply() {
|
|
47156
|
+
return {
|
|
47157
|
+
type: "auto-update",
|
|
47158
|
+
version: ASSIST_VERSION,
|
|
47159
|
+
startCommit: autoUpdateState.startCommit(),
|
|
47160
|
+
loop: autoUpdateState.loop()
|
|
47161
|
+
};
|
|
47162
|
+
}
|
|
47163
|
+
|
|
47017
47164
|
// src/commands/sessions/daemon/handleHelloRequest.ts
|
|
47018
47165
|
var handleHelloRequest = (client, m, d) => {
|
|
47019
47166
|
sendTo(client, buildHello());
|
|
@@ -47539,6 +47686,7 @@ var messageHandlers = {
|
|
|
47539
47686
|
hello: handleHelloRequest,
|
|
47540
47687
|
output: handleOutputRequest,
|
|
47541
47688
|
nodes: (client, m) => m.links.sendNodes(client),
|
|
47689
|
+
"auto-update": (client) => sendTo(client, autoUpdateReply()),
|
|
47542
47690
|
"reload-links": (client, m) => {
|
|
47543
47691
|
daemonLog("reload-links received");
|
|
47544
47692
|
m.links.reload();
|