@staff0rd/assist 0.253.0 → 0.254.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/allowed.cli-reads +1 -0
- package/claude/settings.json +1 -2
- package/dist/allowed.cli-reads +1 -0
- package/dist/commands/sessions/web/bundle.js +63 -63
- package/dist/index.js +534 -402
- package/package.json +4 -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.254.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -73,6 +73,8 @@ var package_default = {
|
|
|
73
73
|
"@semantic-release/changelog": "^6.0.3",
|
|
74
74
|
"@semantic-release/exec": "^7.1.0",
|
|
75
75
|
"@semantic-release/git": "^10.0.1",
|
|
76
|
+
"@testing-library/dom": "^10.4.1",
|
|
77
|
+
"@testing-library/react": "^16.3.2",
|
|
76
78
|
"@types/better-sqlite3": "^7.6.13",
|
|
77
79
|
"@types/blessed": "^0.1.27",
|
|
78
80
|
"@types/mssql": "^12.3.0",
|
|
@@ -90,6 +92,7 @@ var package_default = {
|
|
|
90
92
|
"@xterm/xterm": "^6.0.0",
|
|
91
93
|
esbuild: "^0.27.3",
|
|
92
94
|
jscpd: "^4.0.5",
|
|
95
|
+
jsdom: "^29.1.1",
|
|
93
96
|
knip: "^5.71.0",
|
|
94
97
|
marked: "^15.0.12",
|
|
95
98
|
react: "^19.2.4",
|
|
@@ -115,10 +118,10 @@ import { stringify as stringifyYaml } from "yaml";
|
|
|
115
118
|
// src/shared/loadRawYaml.ts
|
|
116
119
|
import { existsSync, readFileSync } from "fs";
|
|
117
120
|
import { parse as parseYaml } from "yaml";
|
|
118
|
-
function loadRawYaml(
|
|
119
|
-
if (!existsSync(
|
|
121
|
+
function loadRawYaml(path53) {
|
|
122
|
+
if (!existsSync(path53)) return {};
|
|
120
123
|
try {
|
|
121
|
-
const content = readFileSync(
|
|
124
|
+
const content = readFileSync(path53, "utf-8");
|
|
122
125
|
return parseYaml(content) || {};
|
|
123
126
|
} catch {
|
|
124
127
|
return {};
|
|
@@ -2743,9 +2746,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
|
|
|
2743
2746
|
function backupLocalBacklogFiles(dir) {
|
|
2744
2747
|
const moved = [];
|
|
2745
2748
|
for (const name of LOCAL_FILES) {
|
|
2746
|
-
const
|
|
2747
|
-
if (existsSync14(
|
|
2748
|
-
renameSync(
|
|
2749
|
+
const path53 = join10(dir, ".assist", name);
|
|
2750
|
+
if (existsSync14(path53)) {
|
|
2751
|
+
renameSync(path53, `${path53}.bak`);
|
|
2749
2752
|
moved.push(`${name} \u2192 ${name}.bak`);
|
|
2750
2753
|
}
|
|
2751
2754
|
}
|
|
@@ -2893,12 +2896,12 @@ var selectTasks = (orm, ids) => orm.select().from(planTasks).where(inArray(planT
|
|
|
2893
2896
|
asc(planTasks.phaseIdx),
|
|
2894
2897
|
asc(planTasks.idx)
|
|
2895
2898
|
);
|
|
2896
|
-
async function loadRelations(orm, ids) {
|
|
2899
|
+
async function loadRelations(orm, ids, { includeComments = true, includeTasks = true } = {}) {
|
|
2897
2900
|
const [commentRows, linkRows, phaseRows, taskRows] = await Promise.all([
|
|
2898
|
-
selectComments(orm, ids),
|
|
2901
|
+
includeComments ? selectComments(orm, ids) : [],
|
|
2899
2902
|
selectLinks(orm, ids),
|
|
2900
2903
|
selectPhases(orm, ids),
|
|
2901
|
-
selectTasks(orm, ids)
|
|
2904
|
+
includeTasks ? selectTasks(orm, ids) : []
|
|
2902
2905
|
]);
|
|
2903
2906
|
return {
|
|
2904
2907
|
comments: groupByItem(commentRows),
|
|
@@ -2985,7 +2988,8 @@ async function loadAllItems(orm, origin) {
|
|
|
2985
2988
|
if (rows.length === 0) return [];
|
|
2986
2989
|
const rel = await loadRelations(
|
|
2987
2990
|
orm,
|
|
2988
|
-
rows.map((r) => r.id)
|
|
2991
|
+
rows.map((r) => r.id),
|
|
2992
|
+
{ includeComments: false, includeTasks: false }
|
|
2989
2993
|
);
|
|
2990
2994
|
return rows.map((row) => rowToItem(row, rel));
|
|
2991
2995
|
}
|
|
@@ -3034,8 +3038,8 @@ var backlogItemSchema = z3.strictObject({
|
|
|
3034
3038
|
var backlogFileSchema = z3.array(backlogItemSchema);
|
|
3035
3039
|
|
|
3036
3040
|
// src/commands/backlog/parseBacklogJsonl.ts
|
|
3037
|
-
function parseBacklogJsonl(
|
|
3038
|
-
const content = readFileSync9(
|
|
3041
|
+
function parseBacklogJsonl(path53) {
|
|
3042
|
+
const content = readFileSync9(path53, "utf-8").trim();
|
|
3039
3043
|
if (content.length === 0) return [];
|
|
3040
3044
|
return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
|
|
3041
3045
|
}
|
|
@@ -3110,8 +3114,8 @@ function findBacklogUp(startDir) {
|
|
|
3110
3114
|
|
|
3111
3115
|
// src/commands/backlog/getCurrentOrigin.ts
|
|
3112
3116
|
import { execSync as execSync17 } from "child_process";
|
|
3113
|
-
function stripLeadingSlashes(
|
|
3114
|
-
return
|
|
3117
|
+
function stripLeadingSlashes(path53) {
|
|
3118
|
+
return path53.replace(/^\/+/, "");
|
|
3115
3119
|
}
|
|
3116
3120
|
function normalizeOrigin(raw) {
|
|
3117
3121
|
const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
@@ -3423,6 +3427,33 @@ async function reloadPlan(id) {
|
|
|
3423
3427
|
// src/commands/backlog/executePhase.ts
|
|
3424
3428
|
import chalk34 from "chalk";
|
|
3425
3429
|
|
|
3430
|
+
// src/shared/emitActivity.ts
|
|
3431
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync12 } from "fs";
|
|
3432
|
+
import { dirname as dirname14, join as join14 } from "path";
|
|
3433
|
+
function activityPath(cwd, sessionId) {
|
|
3434
|
+
return join14(cwd, ".assist", `activity-${sessionId}.json`);
|
|
3435
|
+
}
|
|
3436
|
+
function emitActivity(activity2) {
|
|
3437
|
+
const sessionId = process.env.ASSIST_ACTIVITY_ID;
|
|
3438
|
+
if (!sessionId) return;
|
|
3439
|
+
const path53 = activityPath(process.cwd(), sessionId);
|
|
3440
|
+
mkdirSync4(dirname14(path53), { recursive: true });
|
|
3441
|
+
writeFileSync12(path53, JSON.stringify({ ...activity2, startedAt: Date.now() }));
|
|
3442
|
+
}
|
|
3443
|
+
function readActivity(path53) {
|
|
3444
|
+
try {
|
|
3445
|
+
return JSON.parse(readFileSync11(path53, "utf-8"));
|
|
3446
|
+
} catch {
|
|
3447
|
+
return void 0;
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3450
|
+
function removeActivity(cwd, sessionId) {
|
|
3451
|
+
try {
|
|
3452
|
+
rmSync(activityPath(cwd, sessionId));
|
|
3453
|
+
} catch {
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3426
3457
|
// src/shared/spawnClaude.ts
|
|
3427
3458
|
import { spawn as spawn3 } from "child_process";
|
|
3428
3459
|
function spawnClaude(prompt, options2 = {}) {
|
|
@@ -3430,8 +3461,10 @@ function spawnClaude(prompt, options2 = {}) {
|
|
|
3430
3461
|
if (options2.allowEdits) {
|
|
3431
3462
|
args.push("--permission-mode", "auto");
|
|
3432
3463
|
}
|
|
3464
|
+
const { ASSIST_ACTIVITY_ID: _activityId, ...env } = process.env;
|
|
3433
3465
|
const child = spawn3("claude", args, {
|
|
3434
|
-
stdio: "inherit"
|
|
3466
|
+
stdio: "inherit",
|
|
3467
|
+
env
|
|
3435
3468
|
});
|
|
3436
3469
|
const done2 = new Promise((resolve16, reject) => {
|
|
3437
3470
|
child.on("close", (code) => resolve16(code ?? 0));
|
|
@@ -3565,28 +3598,28 @@ async function handleIncompletePhase() {
|
|
|
3565
3598
|
}
|
|
3566
3599
|
|
|
3567
3600
|
// src/commands/backlog/readSignal.ts
|
|
3568
|
-
import { existsSync as existsSync18, readFileSync as
|
|
3601
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
|
|
3569
3602
|
|
|
3570
3603
|
// src/commands/backlog/writeSignal.ts
|
|
3571
|
-
import { writeFileSync as
|
|
3572
|
-
import { join as
|
|
3604
|
+
import { writeFileSync as writeFileSync13 } from "fs";
|
|
3605
|
+
import { join as join15 } from "path";
|
|
3573
3606
|
function getSignalPath() {
|
|
3574
3607
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
3575
3608
|
const filename = sessionId ? `.assist-signal-${sessionId}.json` : ".assist-signal.json";
|
|
3576
|
-
return
|
|
3609
|
+
return join15(getBacklogDir(), filename);
|
|
3577
3610
|
}
|
|
3578
3611
|
function writeSignal(event, data) {
|
|
3579
3612
|
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
3580
3613
|
const signal = { event, ...sessionId && { sessionId }, ...data };
|
|
3581
|
-
|
|
3614
|
+
writeFileSync13(getSignalPath(), JSON.stringify(signal));
|
|
3582
3615
|
}
|
|
3583
3616
|
|
|
3584
3617
|
// src/commands/backlog/readSignal.ts
|
|
3585
3618
|
function readSignal() {
|
|
3586
|
-
const
|
|
3587
|
-
if (!existsSync18(
|
|
3619
|
+
const path53 = getSignalPath();
|
|
3620
|
+
if (!existsSync18(path53)) return void 0;
|
|
3588
3621
|
try {
|
|
3589
|
-
return JSON.parse(
|
|
3622
|
+
return JSON.parse(readFileSync12(path53, "utf-8"));
|
|
3590
3623
|
} catch {
|
|
3591
3624
|
return void 0;
|
|
3592
3625
|
}
|
|
@@ -3600,8 +3633,8 @@ function cleanupSignal() {
|
|
|
3600
3633
|
}
|
|
3601
3634
|
}
|
|
3602
3635
|
async function isTerminalStatus(itemId) {
|
|
3603
|
-
const
|
|
3604
|
-
const item =
|
|
3636
|
+
const { orm } = await getReady();
|
|
3637
|
+
const item = await loadItem(orm, itemId);
|
|
3605
3638
|
return item?.status === "done" || item?.status === "wontdo";
|
|
3606
3639
|
}
|
|
3607
3640
|
async function resolvePhaseResult(phaseIndex, itemId) {
|
|
@@ -3644,17 +3677,24 @@ function stopWatching() {
|
|
|
3644
3677
|
}
|
|
3645
3678
|
|
|
3646
3679
|
// src/commands/backlog/executePhase.ts
|
|
3647
|
-
async function executePhase(item, phaseIndex, phases, spawnOptions) {
|
|
3680
|
+
async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases = phases.length) {
|
|
3648
3681
|
const phase = phases[phaseIndex];
|
|
3649
3682
|
const phaseNumber = phaseIndex + 1;
|
|
3650
3683
|
console.log(
|
|
3651
3684
|
chalk34.bold(
|
|
3652
3685
|
`
|
|
3653
|
-
--- Phase ${phaseNumber}/${
|
|
3686
|
+
--- Phase ${phaseNumber}/${totalPhases}: ${phase.name} ---
|
|
3654
3687
|
`
|
|
3655
3688
|
)
|
|
3656
3689
|
);
|
|
3657
|
-
process.env.ASSIST_SESSION_ID
|
|
3690
|
+
process.env.ASSIST_SESSION_ID ??= String(process.pid);
|
|
3691
|
+
emitActivity({
|
|
3692
|
+
kind: "backlog",
|
|
3693
|
+
itemId: item.id,
|
|
3694
|
+
itemName: item.name,
|
|
3695
|
+
phase: phaseNumber,
|
|
3696
|
+
totalPhases
|
|
3697
|
+
});
|
|
3658
3698
|
const { child, done: done2 } = spawnClaude(
|
|
3659
3699
|
buildPhasePrompt(item, phaseNumber, phase),
|
|
3660
3700
|
spawnOptions
|
|
@@ -3674,7 +3714,9 @@ async function runPhases(item, startPhase, plan2, spawnOptions) {
|
|
|
3674
3714
|
item,
|
|
3675
3715
|
phaseIndex,
|
|
3676
3716
|
currentPlan,
|
|
3677
|
-
spawnOptions
|
|
3717
|
+
spawnOptions,
|
|
3718
|
+
// +1 for the review phase appended after the authored phases complete
|
|
3719
|
+
currentPlan.length + 1
|
|
3678
3720
|
);
|
|
3679
3721
|
if (phaseIndex < 0) return false;
|
|
3680
3722
|
currentPlan = await reloadPlan(item.id) ?? currentPlan;
|
|
@@ -4023,10 +4065,10 @@ import { WebSocketServer } from "ws";
|
|
|
4023
4065
|
|
|
4024
4066
|
// src/shared/getInstallDir.ts
|
|
4025
4067
|
import { execSync as execSync18 } from "child_process";
|
|
4026
|
-
import { dirname as
|
|
4068
|
+
import { dirname as dirname15, resolve as resolve6 } from "path";
|
|
4027
4069
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4028
4070
|
var __filename2 = fileURLToPath3(import.meta.url);
|
|
4029
|
-
var __dirname4 =
|
|
4071
|
+
var __dirname4 = dirname15(__filename2);
|
|
4030
4072
|
function getInstallDir() {
|
|
4031
4073
|
return resolve6(__dirname4, "..");
|
|
4032
4074
|
}
|
|
@@ -4103,7 +4145,7 @@ function startWebServer(label2, port, handler, initialPath) {
|
|
|
4103
4145
|
import { spawn as spawn4 } from "child_process";
|
|
4104
4146
|
import {
|
|
4105
4147
|
closeSync,
|
|
4106
|
-
mkdirSync as
|
|
4148
|
+
mkdirSync as mkdirSync5,
|
|
4107
4149
|
openSync,
|
|
4108
4150
|
statSync,
|
|
4109
4151
|
unlinkSync as unlinkSync4,
|
|
@@ -4115,14 +4157,14 @@ import * as net from "net";
|
|
|
4115
4157
|
|
|
4116
4158
|
// src/commands/sessions/daemon/daemonPaths.ts
|
|
4117
4159
|
import { homedir as homedir3 } from "os";
|
|
4118
|
-
import { join as
|
|
4119
|
-
var DAEMON_DIR =
|
|
4160
|
+
import { join as join16 } from "path";
|
|
4161
|
+
var DAEMON_DIR = join16(homedir3(), ".assist", "daemon");
|
|
4120
4162
|
var daemonPaths = {
|
|
4121
4163
|
dir: DAEMON_DIR,
|
|
4122
|
-
socket: process.platform === "win32" ? "\\\\.\\pipe\\assist-sessions-daemon" :
|
|
4123
|
-
log:
|
|
4124
|
-
pid:
|
|
4125
|
-
spawnLock:
|
|
4164
|
+
socket: process.platform === "win32" ? "\\\\.\\pipe\\assist-sessions-daemon" : join16(DAEMON_DIR, "daemon.sock"),
|
|
4165
|
+
log: join16(DAEMON_DIR, "daemon.log"),
|
|
4166
|
+
pid: join16(DAEMON_DIR, "daemon.pid"),
|
|
4167
|
+
spawnLock: join16(DAEMON_DIR, "spawn.lock")
|
|
4126
4168
|
};
|
|
4127
4169
|
|
|
4128
4170
|
// src/commands/sessions/daemon/connectToDaemon.ts
|
|
@@ -4148,7 +4190,7 @@ var RETRY_DELAY_MS = 200;
|
|
|
4148
4190
|
var STALE_LOCK_MS = SPAWN_TIMEOUT_MS + 5e3;
|
|
4149
4191
|
async function ensureDaemonRunning(reason = "unspecified") {
|
|
4150
4192
|
if (await isDaemonRunning()) return;
|
|
4151
|
-
|
|
4193
|
+
mkdirSync5(daemonPaths.dir, { recursive: true });
|
|
4152
4194
|
const holdsLock = acquireSpawnLock();
|
|
4153
4195
|
if (holdsLock) spawnDaemon(reason);
|
|
4154
4196
|
try {
|
|
@@ -4213,19 +4255,19 @@ function delay(ms) {
|
|
|
4213
4255
|
}
|
|
4214
4256
|
|
|
4215
4257
|
// src/commands/sessions/web/handleRequest.ts
|
|
4216
|
-
import { readFileSync as
|
|
4258
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
4217
4259
|
import { createRequire as createRequire2 } from "module";
|
|
4218
4260
|
|
|
4219
4261
|
// src/shared/createBundleHandler.ts
|
|
4220
|
-
import { readFileSync as
|
|
4221
|
-
import { dirname as
|
|
4262
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
4263
|
+
import { dirname as dirname16, join as join17 } from "path";
|
|
4222
4264
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
4223
4265
|
function createBundleHandler(importMetaUrl, bundlePath) {
|
|
4224
|
-
const dir =
|
|
4266
|
+
const dir = dirname16(fileURLToPath4(importMetaUrl));
|
|
4225
4267
|
let cache;
|
|
4226
4268
|
return (_req, res) => {
|
|
4227
4269
|
if (!cache) {
|
|
4228
|
-
cache =
|
|
4270
|
+
cache = readFileSync13(join17(dir, bundlePath), "utf-8");
|
|
4229
4271
|
}
|
|
4230
4272
|
res.writeHead(200, { "Content-Type": "application/javascript" });
|
|
4231
4273
|
res.end(cache);
|
|
@@ -4293,31 +4335,79 @@ async function createItem(req, res) {
|
|
|
4293
4335
|
respondJson(res, 201, { id, ...newItem });
|
|
4294
4336
|
}
|
|
4295
4337
|
|
|
4338
|
+
// src/commands/backlog/loadBacklogSummaries.ts
|
|
4339
|
+
import { eq as eq11 } from "drizzle-orm";
|
|
4340
|
+
|
|
4341
|
+
// src/commands/backlog/loadItemSummaries.ts
|
|
4342
|
+
import { asc as asc4, eq as eq10 } from "drizzle-orm";
|
|
4343
|
+
async function loadItemSummaries(orm, origin) {
|
|
4344
|
+
const rows = await orm.select({
|
|
4345
|
+
id: items.id,
|
|
4346
|
+
origin: items.origin,
|
|
4347
|
+
type: items.type,
|
|
4348
|
+
name: items.name,
|
|
4349
|
+
status: items.status
|
|
4350
|
+
}).from(items).where(origin === void 0 ? void 0 : eq10(items.origin, origin)).orderBy(asc4(items.id));
|
|
4351
|
+
return rows.map((row) => ({
|
|
4352
|
+
id: row.id,
|
|
4353
|
+
origin: row.origin,
|
|
4354
|
+
type: row.type,
|
|
4355
|
+
name: row.name,
|
|
4356
|
+
status: row.status
|
|
4357
|
+
}));
|
|
4358
|
+
}
|
|
4359
|
+
|
|
4360
|
+
// src/commands/backlog/loadBacklogSummaries.ts
|
|
4361
|
+
async function loadBacklogSummaries(allRepos = false) {
|
|
4362
|
+
const { orm } = await getReady();
|
|
4363
|
+
return loadItemSummaries(orm, allRepos ? void 0 : getOrigin());
|
|
4364
|
+
}
|
|
4365
|
+
async function searchBacklogSummaries(query) {
|
|
4366
|
+
const { orm } = await getReady();
|
|
4367
|
+
const origin = getOrigin();
|
|
4368
|
+
const ids = await searchItemIds(orm, query, origin);
|
|
4369
|
+
const summaries = await loadItemSummaries(orm, origin);
|
|
4370
|
+
return summaries.filter((item) => ids.includes(item.id));
|
|
4371
|
+
}
|
|
4372
|
+
async function backlogHasItems() {
|
|
4373
|
+
const { orm } = await getReady();
|
|
4374
|
+
const [row] = await orm.select({ id: items.id }).from(items).where(eq11(items.origin, getOrigin())).limit(1);
|
|
4375
|
+
return row !== void 0;
|
|
4376
|
+
}
|
|
4377
|
+
|
|
4296
4378
|
// src/commands/backlog/web/getBacklogExists.ts
|
|
4297
4379
|
async function getBacklogExists(req, res) {
|
|
4298
4380
|
applyCwdFromReq(req);
|
|
4299
|
-
|
|
4300
|
-
respondJson(res, 200, { exists: items2.length > 0 });
|
|
4381
|
+
respondJson(res, 200, { exists: await backlogHasItems() });
|
|
4301
4382
|
}
|
|
4302
4383
|
|
|
4303
4384
|
// src/commands/backlog/web/rewindItemPhase.ts
|
|
4304
|
-
import { eq as
|
|
4385
|
+
import { eq as eq13 } from "drizzle-orm";
|
|
4305
4386
|
|
|
4306
4387
|
// src/commands/backlog/deleteComment.ts
|
|
4307
|
-
import { and as and2, eq as
|
|
4388
|
+
import { and as and2, eq as eq12 } from "drizzle-orm";
|
|
4308
4389
|
async function deleteComment(orm, itemId, commentId) {
|
|
4309
|
-
const [row] = await orm.select({ type: comments.type }).from(comments).where(and2(
|
|
4390
|
+
const [row] = await orm.select({ type: comments.type }).from(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
|
|
4310
4391
|
if (!row) return "not-found";
|
|
4311
4392
|
if (row.type === "summary") return "is-summary";
|
|
4312
|
-
await orm.delete(comments).where(and2(
|
|
4393
|
+
await orm.delete(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
|
|
4313
4394
|
return "deleted";
|
|
4314
4395
|
}
|
|
4315
4396
|
|
|
4397
|
+
// src/commands/backlog/web/loadVisibleItems.ts
|
|
4398
|
+
var completedStatuses = /* @__PURE__ */ new Set(["done", "wontdo"]);
|
|
4399
|
+
async function loadVisibleItems(req) {
|
|
4400
|
+
const params = new URL(req.url ?? "/", "http://localhost").searchParams;
|
|
4401
|
+
const q = params.get("q");
|
|
4402
|
+
const loaded = q ? await searchBacklogSummaries(q) : await loadBacklogSummaries();
|
|
4403
|
+
if (params.get("showCompleted") === "true") return loaded;
|
|
4404
|
+
return loaded.filter((item) => !completedStatuses.has(item.status));
|
|
4405
|
+
}
|
|
4406
|
+
|
|
4316
4407
|
// src/commands/backlog/web/shared.ts
|
|
4317
4408
|
async function listItems(req, res) {
|
|
4318
4409
|
applyCwdFromReq(req);
|
|
4319
|
-
const
|
|
4320
|
-
const items2 = q ? await searchBacklog(q) : await loadBacklog();
|
|
4410
|
+
const items2 = await loadVisibleItems(req);
|
|
4321
4411
|
respondJson(res, 200, items2.slice().reverse());
|
|
4322
4412
|
}
|
|
4323
4413
|
async function findItemOr404(res, id) {
|
|
@@ -4384,7 +4474,7 @@ async function rewindItemPhase(req, res, id) {
|
|
|
4384
4474
|
`Rewound to phase ${phase} (${phaseName}): ${reason}`,
|
|
4385
4475
|
{ phase }
|
|
4386
4476
|
);
|
|
4387
|
-
await orm.update(items).set({ currentPhase: phase, status: "in-progress" }).where(
|
|
4477
|
+
await orm.update(items).set({ currentPhase: phase, status: "in-progress" }).where(eq13(items.id, id));
|
|
4388
4478
|
respondJson(res, 200, await loadItem(orm, id));
|
|
4389
4479
|
}
|
|
4390
4480
|
function validateRewind(item, phase) {
|
|
@@ -4402,7 +4492,7 @@ function validateRewind(item, phase) {
|
|
|
4402
4492
|
}
|
|
4403
4493
|
|
|
4404
4494
|
// src/commands/backlog/web/updateItem.ts
|
|
4405
|
-
import { eq as
|
|
4495
|
+
import { eq as eq14 } from "drizzle-orm";
|
|
4406
4496
|
async function updateItem(req, res, id) {
|
|
4407
4497
|
const body = await parseItemBody(req);
|
|
4408
4498
|
const result = await findItemOr404(res, id);
|
|
@@ -4413,7 +4503,7 @@ async function updateItem(req, res, id) {
|
|
|
4413
4503
|
name: body.name,
|
|
4414
4504
|
description: body.description ?? null,
|
|
4415
4505
|
acceptanceCriteria: JSON.stringify(body.acceptanceCriteria ?? [])
|
|
4416
|
-
}).where(
|
|
4506
|
+
}).where(eq14(items.id, id));
|
|
4417
4507
|
respondJson(res, 200, await loadItem(orm, id));
|
|
4418
4508
|
}
|
|
4419
4509
|
|
|
@@ -4525,7 +4615,7 @@ function createCssHandler(packageEntry) {
|
|
|
4525
4615
|
return (_req, res) => {
|
|
4526
4616
|
if (!cache) {
|
|
4527
4617
|
const resolved = require3.resolve(packageEntry);
|
|
4528
|
-
cache =
|
|
4618
|
+
cache = readFileSync14(resolved, "utf-8");
|
|
4529
4619
|
}
|
|
4530
4620
|
res.writeHead(200, { "Content-Type": "text/css" });
|
|
4531
4621
|
res.end(cache);
|
|
@@ -4996,9 +5086,9 @@ import chalk51 from "chalk";
|
|
|
4996
5086
|
|
|
4997
5087
|
// src/commands/backlog/add/shared.ts
|
|
4998
5088
|
import { spawnSync } from "child_process";
|
|
4999
|
-
import { mkdtempSync, readFileSync as
|
|
5089
|
+
import { mkdtempSync, readFileSync as readFileSync15, unlinkSync as unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
|
|
5000
5090
|
import { tmpdir } from "os";
|
|
5001
|
-
import { join as
|
|
5091
|
+
import { join as join18 } from "path";
|
|
5002
5092
|
import enquirer6 from "enquirer";
|
|
5003
5093
|
async function promptType() {
|
|
5004
5094
|
const { type } = await enquirer6.prompt({
|
|
@@ -5038,15 +5128,15 @@ async function promptDescription() {
|
|
|
5038
5128
|
}
|
|
5039
5129
|
function openEditor() {
|
|
5040
5130
|
const editor = process.env.EDITOR || process.env.VISUAL || "vi";
|
|
5041
|
-
const dir = mkdtempSync(
|
|
5042
|
-
const filePath =
|
|
5043
|
-
|
|
5131
|
+
const dir = mkdtempSync(join18(tmpdir(), "assist-"));
|
|
5132
|
+
const filePath = join18(dir, "description.md");
|
|
5133
|
+
writeFileSync14(filePath, "");
|
|
5044
5134
|
const result = spawnSync(editor, [filePath], { stdio: "inherit" });
|
|
5045
5135
|
if (result.status !== 0) {
|
|
5046
5136
|
unlinkSync5(filePath);
|
|
5047
5137
|
return void 0;
|
|
5048
5138
|
}
|
|
5049
|
-
const content =
|
|
5139
|
+
const content = readFileSync15(filePath, "utf-8").trim();
|
|
5050
5140
|
unlinkSync5(filePath);
|
|
5051
5141
|
return content || void 0;
|
|
5052
5142
|
}
|
|
@@ -5089,22 +5179,22 @@ async function add(options2) {
|
|
|
5089
5179
|
import chalk53 from "chalk";
|
|
5090
5180
|
|
|
5091
5181
|
// src/commands/backlog/insertPhaseAt.ts
|
|
5092
|
-
import { count, eq as
|
|
5182
|
+
import { count, eq as eq16 } from "drizzle-orm";
|
|
5093
5183
|
|
|
5094
5184
|
// src/commands/backlog/shiftPhasesUp.ts
|
|
5095
|
-
import { and as and3, desc, eq as
|
|
5185
|
+
import { and as and3, desc, eq as eq15, gte } from "drizzle-orm";
|
|
5096
5186
|
async function shiftPhasesUp(db, itemId, fromIdx) {
|
|
5097
|
-
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(
|
|
5187
|
+
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(eq15(planPhases.itemId, itemId), gte(planPhases.idx, fromIdx))).orderBy(desc(planPhases.idx));
|
|
5098
5188
|
for (const p of toShift) {
|
|
5099
|
-
await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and3(
|
|
5100
|
-
await db.update(planPhases).set({ idx: p.idx + 1 }).where(and3(
|
|
5189
|
+
await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and3(eq15(planTasks.itemId, itemId), eq15(planTasks.phaseIdx, p.idx)));
|
|
5190
|
+
await db.update(planPhases).set({ idx: p.idx + 1 }).where(and3(eq15(planPhases.itemId, itemId), eq15(planPhases.idx, p.idx)));
|
|
5101
5191
|
}
|
|
5102
5192
|
}
|
|
5103
5193
|
|
|
5104
5194
|
// src/commands/backlog/insertPhaseAt.ts
|
|
5105
5195
|
async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, currentPhase) {
|
|
5106
5196
|
await orm.transaction(async (tx) => {
|
|
5107
|
-
const [row] = await tx.select({ cnt: count() }).from(planPhases).where(
|
|
5197
|
+
const [row] = await tx.select({ cnt: count() }).from(planPhases).where(eq16(planPhases.itemId, itemId));
|
|
5108
5198
|
const phaseCount = row?.cnt ?? 0;
|
|
5109
5199
|
await shiftPhasesUp(tx, itemId, phaseIdx);
|
|
5110
5200
|
await tx.insert(planPhases).values({ itemId, idx: phaseIdx, name, manualChecks });
|
|
@@ -5113,16 +5203,16 @@ async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, c
|
|
|
5113
5203
|
}
|
|
5114
5204
|
if (currentPhase !== void 0 && currentPhase - 1 >= phaseIdx) {
|
|
5115
5205
|
const atReviewSlot = currentPhase - 1 >= phaseCount;
|
|
5116
|
-
await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(
|
|
5206
|
+
await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(eq16(items.id, itemId));
|
|
5117
5207
|
}
|
|
5118
5208
|
});
|
|
5119
5209
|
}
|
|
5120
5210
|
|
|
5121
5211
|
// src/commands/backlog/resolveInsertPosition.ts
|
|
5122
5212
|
import chalk52 from "chalk";
|
|
5123
|
-
import { count as count2, eq as
|
|
5213
|
+
import { count as count2, eq as eq17 } from "drizzle-orm";
|
|
5124
5214
|
async function resolveInsertPosition(orm, itemId, position) {
|
|
5125
|
-
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(
|
|
5215
|
+
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(eq17(planPhases.itemId, itemId));
|
|
5126
5216
|
const phaseCount = row?.cnt ?? 0;
|
|
5127
5217
|
if (position === void 0) return phaseCount;
|
|
5128
5218
|
const pos = Number.parseInt(position, 10);
|
|
@@ -5180,8 +5270,8 @@ import chalk54 from "chalk";
|
|
|
5180
5270
|
// src/commands/backlog/originDisplayName.ts
|
|
5181
5271
|
function originDisplayName(origin) {
|
|
5182
5272
|
if (origin.startsWith("local:")) {
|
|
5183
|
-
const
|
|
5184
|
-
const segments =
|
|
5273
|
+
const path53 = origin.slice("local:".length).replace(/\/+$/, "");
|
|
5274
|
+
const segments = path53.split("/").filter(Boolean);
|
|
5185
5275
|
return segments[segments.length - 1] ?? origin;
|
|
5186
5276
|
}
|
|
5187
5277
|
const firstSlash = origin.indexOf("/");
|
|
@@ -5236,9 +5326,9 @@ async function list2(options2) {
|
|
|
5236
5326
|
const repoNameOf = (item) => item.origin ? labels.get(item.origin) ?? "" : "";
|
|
5237
5327
|
const prefixWidth = options2.allRepos ? Math.max(0, ...items2.map((i) => repoNameOf(i).length)) : 0;
|
|
5238
5328
|
for (const item of items2) {
|
|
5239
|
-
const
|
|
5329
|
+
const repoPrefix = options2.allRepos ? `${chalk54.dim(repoNameOf(item).padEnd(prefixWidth))} ` : "";
|
|
5240
5330
|
console.log(
|
|
5241
|
-
`${
|
|
5331
|
+
`${repoPrefix}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk54.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
5242
5332
|
);
|
|
5243
5333
|
if (options2.verbose) {
|
|
5244
5334
|
printVerboseDetails(item);
|
|
@@ -5283,9 +5373,9 @@ function hasCycle(adjacency, fromId, toId) {
|
|
|
5283
5373
|
}
|
|
5284
5374
|
|
|
5285
5375
|
// src/commands/backlog/loadDependencyGraph.ts
|
|
5286
|
-
import { eq as
|
|
5376
|
+
import { eq as eq18 } from "drizzle-orm";
|
|
5287
5377
|
async function loadDependencyGraph(orm) {
|
|
5288
|
-
const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(
|
|
5378
|
+
const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq18(links.type, "depends-on"));
|
|
5289
5379
|
const graph = /* @__PURE__ */ new Map();
|
|
5290
5380
|
for (const { itemId, targetId } of rows) {
|
|
5291
5381
|
const bucket = graph.get(itemId);
|
|
@@ -5348,7 +5438,7 @@ async function link(fromId, toId, opts) {
|
|
|
5348
5438
|
|
|
5349
5439
|
// src/commands/backlog/unlink.ts
|
|
5350
5440
|
import chalk57 from "chalk";
|
|
5351
|
-
import { and as and4, eq as
|
|
5441
|
+
import { and as and4, eq as eq19 } from "drizzle-orm";
|
|
5352
5442
|
async function unlink(fromId, toId) {
|
|
5353
5443
|
const fromNum = Number.parseInt(fromId, 10);
|
|
5354
5444
|
const toNum = Number.parseInt(toId, 10);
|
|
@@ -5366,7 +5456,7 @@ async function unlink(fromId, toId) {
|
|
|
5366
5456
|
console.log(chalk57.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
5367
5457
|
return;
|
|
5368
5458
|
}
|
|
5369
|
-
await orm.delete(links).where(and4(
|
|
5459
|
+
await orm.delete(links).where(and4(eq19(links.itemId, fromNum), eq19(links.targetId, toNum)));
|
|
5370
5460
|
console.log(chalk57.green(`Removed link from #${fromId} to #${toId}.`));
|
|
5371
5461
|
}
|
|
5372
5462
|
|
|
@@ -5382,7 +5472,7 @@ function registerLinkCommands(cmd) {
|
|
|
5382
5472
|
|
|
5383
5473
|
// src/commands/backlog/move-repo/index.ts
|
|
5384
5474
|
import chalk59 from "chalk";
|
|
5385
|
-
import { eq as
|
|
5475
|
+
import { eq as eq21 } from "drizzle-orm";
|
|
5386
5476
|
|
|
5387
5477
|
// src/commands/backlog/move-repo/confirmMove.ts
|
|
5388
5478
|
import chalk58 from "chalk";
|
|
@@ -5397,9 +5487,9 @@ async function confirmMove(cnt, oldOrigin, newOrigin) {
|
|
|
5397
5487
|
}
|
|
5398
5488
|
|
|
5399
5489
|
// src/commands/backlog/move-repo/countByOrigin.ts
|
|
5400
|
-
import { count as count3, eq as
|
|
5490
|
+
import { count as count3, eq as eq20 } from "drizzle-orm";
|
|
5401
5491
|
async function countByOrigin(orm, origin) {
|
|
5402
|
-
const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(
|
|
5492
|
+
const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(eq20(items.origin, origin));
|
|
5403
5493
|
return cnt;
|
|
5404
5494
|
}
|
|
5405
5495
|
|
|
@@ -5442,7 +5532,7 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
|
|
|
5442
5532
|
console.log(chalk59.yellow("Move cancelled; no changes made."));
|
|
5443
5533
|
return;
|
|
5444
5534
|
}
|
|
5445
|
-
await orm.update(items).set({ origin: newOrigin }).where(
|
|
5535
|
+
await orm.update(items).set({ origin: newOrigin }).where(eq21(items.origin, oldOrigin));
|
|
5446
5536
|
console.log(
|
|
5447
5537
|
chalk59.green(
|
|
5448
5538
|
`Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
|
|
@@ -5482,9 +5572,9 @@ import chalk61 from "chalk";
|
|
|
5482
5572
|
// src/commands/backlog/tryRunById.ts
|
|
5483
5573
|
import chalk60 from "chalk";
|
|
5484
5574
|
async function tryRunById(id, options2) {
|
|
5485
|
-
const items2 = await loadBacklog();
|
|
5486
5575
|
const numericId = Number.parseInt(id, 10);
|
|
5487
|
-
const
|
|
5576
|
+
const { orm } = await getReady();
|
|
5577
|
+
const item = Number.isNaN(numericId) ? void 0 : await loadItem(orm, numericId);
|
|
5488
5578
|
if (!item) {
|
|
5489
5579
|
console.log(chalk60.red(`Item #${id} not found.`));
|
|
5490
5580
|
return false;
|
|
@@ -5497,7 +5587,8 @@ async function tryRunById(id, options2) {
|
|
|
5497
5587
|
console.log(chalk60.red(`Item #${id} is marked won't do.`));
|
|
5498
5588
|
return false;
|
|
5499
5589
|
}
|
|
5500
|
-
|
|
5590
|
+
const hasDeps = (item.links ?? []).some((l) => l.type === "depends-on");
|
|
5591
|
+
if (hasDeps && isBlocked(item, await loadItemSummaries(orm, getOrigin()))) {
|
|
5501
5592
|
console.log(
|
|
5502
5593
|
chalk60.red(`Item #${id} is blocked by unresolved dependencies.`)
|
|
5503
5594
|
);
|
|
@@ -5517,7 +5608,8 @@ function buildSlashCommand(slashCommand, description) {
|
|
|
5517
5608
|
}
|
|
5518
5609
|
async function launchMode(slashCommand, options2) {
|
|
5519
5610
|
pullIfConfigured();
|
|
5520
|
-
process.env.ASSIST_SESSION_ID
|
|
5611
|
+
process.env.ASSIST_SESSION_ID ??= String(process.pid);
|
|
5612
|
+
emitActivity({ kind: "command", name: slashCommand });
|
|
5521
5613
|
const { child, done: done2 } = spawnClaude(
|
|
5522
5614
|
buildSlashCommand(slashCommand, options2?.description),
|
|
5523
5615
|
{ allowEdits: true }
|
|
@@ -5538,7 +5630,7 @@ async function launchMode(slashCommand, options2) {
|
|
|
5538
5630
|
|
|
5539
5631
|
// src/commands/backlog/refine.ts
|
|
5540
5632
|
async function pickItemForRefine() {
|
|
5541
|
-
const items2 = await
|
|
5633
|
+
const items2 = await loadBacklogSummaries();
|
|
5542
5634
|
const active = items2.filter(
|
|
5543
5635
|
(i) => i.status === "todo" || i.status === "in-progress"
|
|
5544
5636
|
);
|
|
@@ -5713,10 +5805,10 @@ async function start(id) {
|
|
|
5713
5805
|
|
|
5714
5806
|
// src/commands/backlog/stop/index.ts
|
|
5715
5807
|
import chalk68 from "chalk";
|
|
5716
|
-
import { and as and5, eq as
|
|
5808
|
+
import { and as and5, eq as eq22 } from "drizzle-orm";
|
|
5717
5809
|
async function stop() {
|
|
5718
5810
|
const { orm } = await getReady();
|
|
5719
|
-
const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and5(
|
|
5811
|
+
const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and5(eq22(items.status, "in-progress"), eq22(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
|
|
5720
5812
|
if (stopped.length === 0) {
|
|
5721
5813
|
console.log(chalk68.yellow("No in-progress items to stop."));
|
|
5722
5814
|
return;
|
|
@@ -5751,18 +5843,18 @@ function registerStatusCommands(cmd) {
|
|
|
5751
5843
|
|
|
5752
5844
|
// src/commands/backlog/removePhase.ts
|
|
5753
5845
|
import chalk71 from "chalk";
|
|
5754
|
-
import { and as and8, eq as
|
|
5846
|
+
import { and as and8, eq as eq25 } from "drizzle-orm";
|
|
5755
5847
|
|
|
5756
5848
|
// src/commands/backlog/findPhase.ts
|
|
5757
5849
|
import chalk70 from "chalk";
|
|
5758
|
-
import { and as and6, count as count4, eq as
|
|
5850
|
+
import { and as and6, count as count4, eq as eq23 } from "drizzle-orm";
|
|
5759
5851
|
async function findPhase(id, phase) {
|
|
5760
5852
|
const found = await findOneItem(id);
|
|
5761
5853
|
if (!found) return void 0;
|
|
5762
5854
|
const { orm, item } = found;
|
|
5763
5855
|
const itemId = item.id;
|
|
5764
5856
|
const phaseIdx = Number.parseInt(phase, 10) - 1;
|
|
5765
|
-
const [row] = await orm.select({ cnt: count4() }).from(planPhases).where(and6(
|
|
5857
|
+
const [row] = await orm.select({ cnt: count4() }).from(planPhases).where(and6(eq23(planPhases.itemId, itemId), eq23(planPhases.idx, phaseIdx)));
|
|
5766
5858
|
if (!row || row.cnt === 0) {
|
|
5767
5859
|
console.log(
|
|
5768
5860
|
chalk70.red(`Phase ${phaseIdx + 1} not found on item #${itemId}.`)
|
|
@@ -5774,14 +5866,14 @@ async function findPhase(id, phase) {
|
|
|
5774
5866
|
}
|
|
5775
5867
|
|
|
5776
5868
|
// src/commands/backlog/reindexPhases.ts
|
|
5777
|
-
import { and as and7, asc as
|
|
5869
|
+
import { and as and7, asc as asc5, count as count5, eq as eq24 } from "drizzle-orm";
|
|
5778
5870
|
async function reindexPhases(db, itemId) {
|
|
5779
|
-
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(
|
|
5871
|
+
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq24(planPhases.itemId, itemId)).orderBy(asc5(planPhases.idx));
|
|
5780
5872
|
for (let i = 0; i < remaining.length; i++) {
|
|
5781
5873
|
const oldIdx = remaining[i].idx;
|
|
5782
5874
|
if (oldIdx === i) continue;
|
|
5783
|
-
await db.update(planTasks).set({ phaseIdx: i }).where(and7(
|
|
5784
|
-
await db.update(planPhases).set({ idx: i }).where(and7(
|
|
5875
|
+
await db.update(planTasks).set({ phaseIdx: i }).where(and7(eq24(planTasks.itemId, itemId), eq24(planTasks.phaseIdx, oldIdx)));
|
|
5876
|
+
await db.update(planPhases).set({ idx: i }).where(and7(eq24(planPhases.itemId, itemId), eq24(planPhases.idx, oldIdx)));
|
|
5785
5877
|
}
|
|
5786
5878
|
}
|
|
5787
5879
|
async function adjustCurrentPhase(db, item, removedIdx) {
|
|
@@ -5789,13 +5881,13 @@ async function adjustCurrentPhase(db, item, removedIdx) {
|
|
|
5789
5881
|
if (currentPhase === void 0) return;
|
|
5790
5882
|
const currentIdx = currentPhase - 1;
|
|
5791
5883
|
if (removedIdx < currentIdx) {
|
|
5792
|
-
await db.update(items).set({ currentPhase: currentPhase - 1 }).where(
|
|
5884
|
+
await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq24(items.id, item.id));
|
|
5793
5885
|
return;
|
|
5794
5886
|
}
|
|
5795
5887
|
if (removedIdx !== currentIdx) return;
|
|
5796
|
-
const [row] = await db.select({ cnt: count5() }).from(planPhases).where(
|
|
5888
|
+
const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq24(planPhases.itemId, item.id));
|
|
5797
5889
|
const cnt = row?.cnt ?? 0;
|
|
5798
|
-
await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(
|
|
5890
|
+
await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq24(items.id, item.id));
|
|
5799
5891
|
}
|
|
5800
5892
|
|
|
5801
5893
|
// src/commands/backlog/removePhase.ts
|
|
@@ -5805,9 +5897,9 @@ async function removePhase(id, phase) {
|
|
|
5805
5897
|
const { item, orm, itemId, phaseIdx } = found;
|
|
5806
5898
|
await orm.transaction(async (tx) => {
|
|
5807
5899
|
await tx.delete(planTasks).where(
|
|
5808
|
-
and8(
|
|
5900
|
+
and8(eq25(planTasks.itemId, itemId), eq25(planTasks.phaseIdx, phaseIdx))
|
|
5809
5901
|
);
|
|
5810
|
-
await tx.delete(planPhases).where(and8(
|
|
5902
|
+
await tx.delete(planPhases).where(and8(eq25(planPhases.itemId, itemId), eq25(planPhases.idx, phaseIdx)));
|
|
5811
5903
|
await reindexPhases(tx, itemId);
|
|
5812
5904
|
await adjustCurrentPhase(tx, item, phaseIdx);
|
|
5813
5905
|
});
|
|
@@ -5818,7 +5910,7 @@ async function removePhase(id, phase) {
|
|
|
5818
5910
|
|
|
5819
5911
|
// src/commands/backlog/update/index.ts
|
|
5820
5912
|
import chalk73 from "chalk";
|
|
5821
|
-
import { eq as
|
|
5913
|
+
import { eq as eq26 } from "drizzle-orm";
|
|
5822
5914
|
|
|
5823
5915
|
// src/commands/backlog/update/parseListIndex.ts
|
|
5824
5916
|
function parseListIndex(raw, length, label2) {
|
|
@@ -5952,7 +6044,7 @@ async function update(id, options2) {
|
|
|
5952
6044
|
if (!built) return;
|
|
5953
6045
|
const { orm } = found;
|
|
5954
6046
|
const itemId = found.item.id;
|
|
5955
|
-
await orm.update(items).set(built.set).where(
|
|
6047
|
+
await orm.update(items).set(built.set).where(eq26(items.id, itemId));
|
|
5956
6048
|
console.log(chalk73.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
5957
6049
|
}
|
|
5958
6050
|
|
|
@@ -5960,22 +6052,22 @@ async function update(id, options2) {
|
|
|
5960
6052
|
import chalk74 from "chalk";
|
|
5961
6053
|
|
|
5962
6054
|
// src/commands/backlog/applyPhaseUpdate.ts
|
|
5963
|
-
import { and as and9, eq as
|
|
6055
|
+
import { and as and9, eq as eq27 } from "drizzle-orm";
|
|
5964
6056
|
async function applyPhaseUpdate(orm, itemId, phaseIdx, fields) {
|
|
5965
6057
|
await orm.transaction(async (tx) => {
|
|
5966
6058
|
if (fields.name) {
|
|
5967
6059
|
await tx.update(planPhases).set({ name: fields.name }).where(
|
|
5968
|
-
and9(
|
|
6060
|
+
and9(eq27(planPhases.itemId, itemId), eq27(planPhases.idx, phaseIdx))
|
|
5969
6061
|
);
|
|
5970
6062
|
}
|
|
5971
6063
|
if (fields.manualCheck) {
|
|
5972
6064
|
await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
|
|
5973
|
-
and9(
|
|
6065
|
+
and9(eq27(planPhases.itemId, itemId), eq27(planPhases.idx, phaseIdx))
|
|
5974
6066
|
);
|
|
5975
6067
|
}
|
|
5976
6068
|
if (fields.task) {
|
|
5977
6069
|
await tx.delete(planTasks).where(
|
|
5978
|
-
and9(
|
|
6070
|
+
and9(eq27(planTasks.itemId, itemId), eq27(planTasks.phaseIdx, phaseIdx))
|
|
5979
6071
|
);
|
|
5980
6072
|
if (fields.task.length) {
|
|
5981
6073
|
await tx.insert(planTasks).values(
|
|
@@ -6265,13 +6357,13 @@ function stripEnvPrefix(parts) {
|
|
|
6265
6357
|
}
|
|
6266
6358
|
|
|
6267
6359
|
// src/commands/cliHook/logDeniedToolCall.ts
|
|
6268
|
-
import { mkdirSync as
|
|
6360
|
+
import { mkdirSync as mkdirSync6 } from "fs";
|
|
6269
6361
|
import { homedir as homedir4 } from "os";
|
|
6270
|
-
import { join as
|
|
6362
|
+
import { join as join19 } from "path";
|
|
6271
6363
|
import Database from "better-sqlite3";
|
|
6272
6364
|
var _db;
|
|
6273
6365
|
function getDbDir() {
|
|
6274
|
-
return
|
|
6366
|
+
return join19(homedir4(), ".assist");
|
|
6275
6367
|
}
|
|
6276
6368
|
function initSchema(db) {
|
|
6277
6369
|
db.exec(`
|
|
@@ -6289,8 +6381,8 @@ function initSchema(db) {
|
|
|
6289
6381
|
function openPromptsDb(dir) {
|
|
6290
6382
|
if (_db) return _db;
|
|
6291
6383
|
const dbDir = dir ?? getDbDir();
|
|
6292
|
-
|
|
6293
|
-
const db = new Database(
|
|
6384
|
+
mkdirSync6(dbDir, { recursive: true });
|
|
6385
|
+
const db = new Database(join19(dbDir, "assist.db"));
|
|
6294
6386
|
db.pragma("journal_mode = WAL");
|
|
6295
6387
|
initSchema(db);
|
|
6296
6388
|
_db = db;
|
|
@@ -6392,17 +6484,17 @@ function extractGraphqlQuery(args) {
|
|
|
6392
6484
|
}
|
|
6393
6485
|
|
|
6394
6486
|
// src/shared/loadCliReads.ts
|
|
6395
|
-
import { existsSync as existsSync21, readFileSync as
|
|
6396
|
-
import { dirname as
|
|
6487
|
+
import { existsSync as existsSync21, readFileSync as readFileSync16, writeFileSync as writeFileSync15 } from "fs";
|
|
6488
|
+
import { dirname as dirname17, resolve as resolve7 } from "path";
|
|
6397
6489
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
6398
6490
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
6399
|
-
var __dirname5 =
|
|
6491
|
+
var __dirname5 = dirname17(__filename3);
|
|
6400
6492
|
function packageRoot() {
|
|
6401
6493
|
return __dirname5;
|
|
6402
6494
|
}
|
|
6403
|
-
function readLines(
|
|
6404
|
-
if (!existsSync21(
|
|
6405
|
-
return
|
|
6495
|
+
function readLines(path53) {
|
|
6496
|
+
if (!existsSync21(path53)) return [];
|
|
6497
|
+
return readFileSync16(path53, "utf-8").split("\n").filter((line) => line.trim() !== "");
|
|
6406
6498
|
}
|
|
6407
6499
|
var cachedReads;
|
|
6408
6500
|
var cachedWrites;
|
|
@@ -6422,7 +6514,7 @@ function loadCliReads() {
|
|
|
6422
6514
|
return getCliReadsLines();
|
|
6423
6515
|
}
|
|
6424
6516
|
function saveCliReads(commands) {
|
|
6425
|
-
|
|
6517
|
+
writeFileSync15(
|
|
6426
6518
|
resolve7(packageRoot(), "allowed.cli-reads"),
|
|
6427
6519
|
`${commands.join("\n")}
|
|
6428
6520
|
`
|
|
@@ -6448,14 +6540,14 @@ function findCliWrite(command) {
|
|
|
6448
6540
|
}
|
|
6449
6541
|
|
|
6450
6542
|
// src/shared/readSettingsPerms.ts
|
|
6451
|
-
import { existsSync as existsSync22, readFileSync as
|
|
6543
|
+
import { existsSync as existsSync22, readFileSync as readFileSync17 } from "fs";
|
|
6452
6544
|
import { homedir as homedir5 } from "os";
|
|
6453
|
-
import { join as
|
|
6545
|
+
import { join as join20 } from "path";
|
|
6454
6546
|
function readSettingsPerms(key) {
|
|
6455
6547
|
const paths = [
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6548
|
+
join20(homedir5(), ".claude", "settings.json"),
|
|
6549
|
+
join20(process.cwd(), ".claude", "settings.json"),
|
|
6550
|
+
join20(process.cwd(), ".claude", "settings.local.json")
|
|
6459
6551
|
];
|
|
6460
6552
|
const entries = [];
|
|
6461
6553
|
for (const p of paths) {
|
|
@@ -6466,7 +6558,7 @@ function readSettingsPerms(key) {
|
|
|
6466
6558
|
function readPermissionArray(filePath, key) {
|
|
6467
6559
|
if (!existsSync22(filePath)) return [];
|
|
6468
6560
|
try {
|
|
6469
|
-
const data = JSON.parse(
|
|
6561
|
+
const data = JSON.parse(readFileSync17(filePath, "utf-8"));
|
|
6470
6562
|
const arr = data?.permissions?.[key];
|
|
6471
6563
|
return Array.isArray(arr) ? arr.filter((e) => typeof e === "string") : [];
|
|
6472
6564
|
} catch {
|
|
@@ -6746,9 +6838,9 @@ ${reasons.join("\n")}`);
|
|
|
6746
6838
|
}
|
|
6747
6839
|
|
|
6748
6840
|
// src/commands/permitCliReads/index.ts
|
|
6749
|
-
import { existsSync as existsSync23, mkdirSync as
|
|
6841
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync7, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
6750
6842
|
import { homedir as homedir6 } from "os";
|
|
6751
|
-
import { join as
|
|
6843
|
+
import { join as join21 } from "path";
|
|
6752
6844
|
|
|
6753
6845
|
// src/shared/checkCliAvailable.ts
|
|
6754
6846
|
import { execSync as execSync19 } from "child_process";
|
|
@@ -6885,14 +6977,14 @@ function showProgress(p, label2) {
|
|
|
6885
6977
|
const pct = Math.round(p.done / p.total * 100);
|
|
6886
6978
|
process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
|
|
6887
6979
|
}
|
|
6888
|
-
async function resolveCommand(cli,
|
|
6889
|
-
showProgress(p,
|
|
6890
|
-
const subHelp = await runHelp([cli, ...
|
|
6980
|
+
async function resolveCommand(cli, path53, description, depth, p) {
|
|
6981
|
+
showProgress(p, path53.join(" "));
|
|
6982
|
+
const subHelp = await runHelp([cli, ...path53]);
|
|
6891
6983
|
if (!subHelp || !hasSubcommands(subHelp)) {
|
|
6892
|
-
return [{ path:
|
|
6984
|
+
return [{ path: path53, description }];
|
|
6893
6985
|
}
|
|
6894
|
-
const children = await discoverAt(cli,
|
|
6895
|
-
return children.length > 0 ? children : [{ path:
|
|
6986
|
+
const children = await discoverAt(cli, path53, depth + 1, p);
|
|
6987
|
+
return children.length > 0 ? children : [{ path: path53, description }];
|
|
6896
6988
|
}
|
|
6897
6989
|
async function discoverAt(cli, parentPath, depth, p) {
|
|
6898
6990
|
if (depth > SAFETY_DEPTH) return [];
|
|
@@ -7037,17 +7129,17 @@ function updateSettings(cli, commands) {
|
|
|
7037
7129
|
// src/commands/permitCliReads/index.ts
|
|
7038
7130
|
function logPath(cli) {
|
|
7039
7131
|
const safeName = cli.replace(/\s+/g, "-");
|
|
7040
|
-
return
|
|
7132
|
+
return join21(homedir6(), ".assist", `cli-discover-${safeName}.log`);
|
|
7041
7133
|
}
|
|
7042
7134
|
function readCache(cli) {
|
|
7043
|
-
const
|
|
7044
|
-
if (!existsSync23(
|
|
7045
|
-
return
|
|
7135
|
+
const path53 = logPath(cli);
|
|
7136
|
+
if (!existsSync23(path53)) return void 0;
|
|
7137
|
+
return readFileSync18(path53, "utf-8");
|
|
7046
7138
|
}
|
|
7047
7139
|
function writeCache(cli, output) {
|
|
7048
|
-
const dir =
|
|
7049
|
-
|
|
7050
|
-
|
|
7140
|
+
const dir = join21(homedir6(), ".assist");
|
|
7141
|
+
mkdirSync7(dir, { recursive: true });
|
|
7142
|
+
writeFileSync16(logPath(cli), output);
|
|
7051
7143
|
}
|
|
7052
7144
|
async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
7053
7145
|
if (!cli) {
|
|
@@ -7641,6 +7733,11 @@ async function analyze(pattern2) {
|
|
|
7641
7733
|
await halstead(file);
|
|
7642
7734
|
console.log();
|
|
7643
7735
|
console.log(chalk84.bold.underline("Maintainability Index"));
|
|
7736
|
+
console.log(
|
|
7737
|
+
chalk84.dim(
|
|
7738
|
+
"171 - 5.2*ln(HalsteadVolume) - 0.23*CyclomaticComplexity - 16.2*ln(SLOC), clamped 0-100"
|
|
7739
|
+
)
|
|
7740
|
+
);
|
|
7644
7741
|
await maintainability(file);
|
|
7645
7742
|
return;
|
|
7646
7743
|
}
|
|
@@ -7707,8 +7804,8 @@ function stepIntoNested(container, key, nextKey) {
|
|
|
7707
7804
|
}
|
|
7708
7805
|
return ensureObject(container, resolved);
|
|
7709
7806
|
}
|
|
7710
|
-
function setNestedValue(obj,
|
|
7711
|
-
const keys =
|
|
7807
|
+
function setNestedValue(obj, path53, value) {
|
|
7808
|
+
const keys = path53.split(".");
|
|
7712
7809
|
const result = { ...obj };
|
|
7713
7810
|
let current = result;
|
|
7714
7811
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -7788,9 +7885,9 @@ function isTraversable(value) {
|
|
|
7788
7885
|
function stepInto(current, key) {
|
|
7789
7886
|
return isTraversable(current) ? current[key] : void 0;
|
|
7790
7887
|
}
|
|
7791
|
-
function getNestedValue(obj,
|
|
7888
|
+
function getNestedValue(obj, path53) {
|
|
7792
7889
|
let current = obj;
|
|
7793
|
-
for (const key of
|
|
7890
|
+
for (const key of path53.split(".")) current = stepInto(current, key);
|
|
7794
7891
|
return current;
|
|
7795
7892
|
}
|
|
7796
7893
|
|
|
@@ -7824,7 +7921,7 @@ function registerConfig(program2) {
|
|
|
7824
7921
|
}
|
|
7825
7922
|
|
|
7826
7923
|
// src/commands/deploy/redirect.ts
|
|
7827
|
-
import { existsSync as existsSync24, readFileSync as
|
|
7924
|
+
import { existsSync as existsSync24, readFileSync as readFileSync19, writeFileSync as writeFileSync17 } from "fs";
|
|
7828
7925
|
import chalk87 from "chalk";
|
|
7829
7926
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
7830
7927
|
if (!window.location.pathname.endsWith('/')) {
|
|
@@ -7837,7 +7934,7 @@ function redirect() {
|
|
|
7837
7934
|
console.log(chalk87.yellow("No index.html found"));
|
|
7838
7935
|
return;
|
|
7839
7936
|
}
|
|
7840
|
-
const content =
|
|
7937
|
+
const content = readFileSync19(indexPath, "utf-8");
|
|
7841
7938
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
7842
7939
|
console.log(chalk87.dim("Trailing slash script already present"));
|
|
7843
7940
|
return;
|
|
@@ -7848,7 +7945,7 @@ function redirect() {
|
|
|
7848
7945
|
return;
|
|
7849
7946
|
}
|
|
7850
7947
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
7851
|
-
|
|
7948
|
+
writeFileSync17(indexPath, newContent);
|
|
7852
7949
|
console.log(chalk87.green("Added trailing slash redirect to index.html"));
|
|
7853
7950
|
}
|
|
7854
7951
|
|
|
@@ -7865,10 +7962,10 @@ import { basename as basename4 } from "path";
|
|
|
7865
7962
|
|
|
7866
7963
|
// src/commands/devlog/loadBlogSkipDays.ts
|
|
7867
7964
|
import { homedir as homedir7 } from "os";
|
|
7868
|
-
import { join as
|
|
7869
|
-
var BLOG_REPO_ROOT =
|
|
7965
|
+
import { join as join22 } from "path";
|
|
7966
|
+
var BLOG_REPO_ROOT = join22(homedir7(), "git/blog");
|
|
7870
7967
|
function loadBlogSkipDays(repoName) {
|
|
7871
|
-
const config = loadRawYaml(
|
|
7968
|
+
const config = loadRawYaml(join22(BLOG_REPO_ROOT, "assist.yml"));
|
|
7872
7969
|
const devlog = config.devlog;
|
|
7873
7970
|
const skip2 = devlog?.skip;
|
|
7874
7971
|
return new Set(skip2?.[repoName] ?? []);
|
|
@@ -7879,17 +7976,17 @@ import { execSync as execSync20 } from "child_process";
|
|
|
7879
7976
|
import chalk88 from "chalk";
|
|
7880
7977
|
|
|
7881
7978
|
// src/shared/getRepoName.ts
|
|
7882
|
-
import { existsSync as existsSync25, readFileSync as
|
|
7883
|
-
import { basename as basename3, join as
|
|
7979
|
+
import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
|
|
7980
|
+
import { basename as basename3, join as join23 } from "path";
|
|
7884
7981
|
function getRepoName() {
|
|
7885
7982
|
const config = loadConfig();
|
|
7886
7983
|
if (config.devlog?.name) {
|
|
7887
7984
|
return config.devlog.name;
|
|
7888
7985
|
}
|
|
7889
|
-
const packageJsonPath =
|
|
7986
|
+
const packageJsonPath = join23(process.cwd(), "package.json");
|
|
7890
7987
|
if (existsSync25(packageJsonPath)) {
|
|
7891
7988
|
try {
|
|
7892
|
-
const content =
|
|
7989
|
+
const content = readFileSync20(packageJsonPath, "utf-8");
|
|
7893
7990
|
const pkg = JSON.parse(content);
|
|
7894
7991
|
if (pkg.name) {
|
|
7895
7992
|
return pkg.name;
|
|
@@ -7901,9 +7998,9 @@ function getRepoName() {
|
|
|
7901
7998
|
}
|
|
7902
7999
|
|
|
7903
8000
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
7904
|
-
import { readdirSync, readFileSync as
|
|
7905
|
-
import { join as
|
|
7906
|
-
var DEVLOG_DIR =
|
|
8001
|
+
import { readdirSync, readFileSync as readFileSync21 } from "fs";
|
|
8002
|
+
import { join as join24 } from "path";
|
|
8003
|
+
var DEVLOG_DIR = join24(BLOG_REPO_ROOT, "src/content/devlog");
|
|
7907
8004
|
function extractFrontmatter(content) {
|
|
7908
8005
|
const fm = content.match(/^---\n([\s\S]*?)\n---/);
|
|
7909
8006
|
return fm?.[1] ?? null;
|
|
@@ -7931,7 +8028,7 @@ function readDevlogFiles(callback) {
|
|
|
7931
8028
|
try {
|
|
7932
8029
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
7933
8030
|
for (const file of files) {
|
|
7934
|
-
const content =
|
|
8031
|
+
const content = readFileSync21(join24(DEVLOG_DIR, file), "utf-8");
|
|
7935
8032
|
const parsed = parseFrontmatter(content, file);
|
|
7936
8033
|
if (parsed) callback(parsed);
|
|
7937
8034
|
}
|
|
@@ -8318,12 +8415,12 @@ function repos(options2) {
|
|
|
8318
8415
|
}
|
|
8319
8416
|
|
|
8320
8417
|
// src/commands/devlog/skip.ts
|
|
8321
|
-
import { writeFileSync as
|
|
8322
|
-
import { join as
|
|
8418
|
+
import { writeFileSync as writeFileSync18 } from "fs";
|
|
8419
|
+
import { join as join25 } from "path";
|
|
8323
8420
|
import chalk93 from "chalk";
|
|
8324
8421
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
8325
8422
|
function getBlogConfigPath() {
|
|
8326
|
-
return
|
|
8423
|
+
return join25(BLOG_REPO_ROOT, "assist.yml");
|
|
8327
8424
|
}
|
|
8328
8425
|
function skip(date) {
|
|
8329
8426
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
@@ -8347,7 +8444,7 @@ function skip(date) {
|
|
|
8347
8444
|
skip2[repoName] = skipDays;
|
|
8348
8445
|
devlog.skip = skip2;
|
|
8349
8446
|
config.devlog = devlog;
|
|
8350
|
-
|
|
8447
|
+
writeFileSync18(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
8351
8448
|
console.log(chalk93.green(`Added ${date} to skip list for ${repoName}`));
|
|
8352
8449
|
}
|
|
8353
8450
|
|
|
@@ -8384,7 +8481,7 @@ function registerDevlog(program2) {
|
|
|
8384
8481
|
|
|
8385
8482
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
8386
8483
|
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
|
|
8387
|
-
import { join as
|
|
8484
|
+
import { join as join26 } from "path";
|
|
8388
8485
|
import chalk95 from "chalk";
|
|
8389
8486
|
|
|
8390
8487
|
// src/shared/findRepoRoot.ts
|
|
@@ -8412,7 +8509,7 @@ function isLockedDll(debugDir) {
|
|
|
8412
8509
|
}
|
|
8413
8510
|
for (const file of files) {
|
|
8414
8511
|
if (!file.toLowerCase().endsWith(".dll")) continue;
|
|
8415
|
-
const dllPath =
|
|
8512
|
+
const dllPath = join26(debugDir, file);
|
|
8416
8513
|
try {
|
|
8417
8514
|
const fd = openSync2(dllPath, "r+");
|
|
8418
8515
|
closeSync2(fd);
|
|
@@ -8430,13 +8527,13 @@ function findFirstLockedDll(dir) {
|
|
|
8430
8527
|
return null;
|
|
8431
8528
|
}
|
|
8432
8529
|
if (entries.includes("bin")) {
|
|
8433
|
-
const locked = isLockedDll(
|
|
8530
|
+
const locked = isLockedDll(join26(dir, "bin", "Debug"));
|
|
8434
8531
|
if (locked) return locked;
|
|
8435
8532
|
}
|
|
8436
8533
|
for (const entry of entries) {
|
|
8437
8534
|
if (SKIP_DIRS.has(entry) || entry === "bin" || entry.startsWith("."))
|
|
8438
8535
|
continue;
|
|
8439
|
-
const found = findFirstLockedDll(
|
|
8536
|
+
const found = findFirstLockedDll(join26(dir, entry));
|
|
8440
8537
|
if (found) return found;
|
|
8441
8538
|
}
|
|
8442
8539
|
return null;
|
|
@@ -8459,11 +8556,11 @@ async function checkBuildLocksCommand() {
|
|
|
8459
8556
|
}
|
|
8460
8557
|
|
|
8461
8558
|
// src/commands/dotnet/buildTree.ts
|
|
8462
|
-
import { readFileSync as
|
|
8559
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
8463
8560
|
import path21 from "path";
|
|
8464
8561
|
var PROJECT_REF_RE = /<ProjectReference\s+Include="([^"]+)"/g;
|
|
8465
8562
|
function getProjectRefs(csprojPath) {
|
|
8466
|
-
const content =
|
|
8563
|
+
const content = readFileSync22(csprojPath, "utf-8");
|
|
8467
8564
|
const refs = [];
|
|
8468
8565
|
for (const match of content.matchAll(PROJECT_REF_RE)) {
|
|
8469
8566
|
refs.push(match[1].replace(/\\/g, "/"));
|
|
@@ -8480,7 +8577,7 @@ function buildTree(csprojPath, repoRoot, visited = /* @__PURE__ */ new Set()) {
|
|
|
8480
8577
|
for (const ref of getProjectRefs(abs)) {
|
|
8481
8578
|
const childAbs = path21.resolve(dir, ref);
|
|
8482
8579
|
try {
|
|
8483
|
-
|
|
8580
|
+
readFileSync22(childAbs);
|
|
8484
8581
|
node.children.push(buildTree(childAbs, repoRoot, visited));
|
|
8485
8582
|
} catch {
|
|
8486
8583
|
node.children.push({
|
|
@@ -8505,7 +8602,7 @@ function collectAllDeps(node) {
|
|
|
8505
8602
|
}
|
|
8506
8603
|
|
|
8507
8604
|
// src/commands/dotnet/findContainingSolutions.ts
|
|
8508
|
-
import { readdirSync as readdirSync3, readFileSync as
|
|
8605
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync23, statSync as statSync2 } from "fs";
|
|
8509
8606
|
import path22 from "path";
|
|
8510
8607
|
function findSlnFiles(dir, maxDepth, depth = 0) {
|
|
8511
8608
|
if (depth > maxDepth) return [];
|
|
@@ -8540,7 +8637,7 @@ function findContainingSolutions(csprojPath, repoRoot) {
|
|
|
8540
8637
|
const pattern2 = new RegExp(`[\\\\"/]${escapeRegex(csprojBasename)}"`);
|
|
8541
8638
|
for (const sln of slnFiles) {
|
|
8542
8639
|
try {
|
|
8543
|
-
const content =
|
|
8640
|
+
const content = readFileSync23(sln, "utf-8");
|
|
8544
8641
|
if (pattern2.test(content)) {
|
|
8545
8642
|
matches.push(path22.relative(repoRoot, sln));
|
|
8546
8643
|
}
|
|
@@ -8783,11 +8880,11 @@ import chalk101 from "chalk";
|
|
|
8783
8880
|
|
|
8784
8881
|
// src/commands/dotnet/findSolution.ts
|
|
8785
8882
|
import { readdirSync as readdirSync4 } from "fs";
|
|
8786
|
-
import { dirname as
|
|
8883
|
+
import { dirname as dirname18, join as join27 } from "path";
|
|
8787
8884
|
import chalk100 from "chalk";
|
|
8788
8885
|
function findSlnInDir(dir) {
|
|
8789
8886
|
try {
|
|
8790
|
-
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) =>
|
|
8887
|
+
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join27(dir, f));
|
|
8791
8888
|
} catch {
|
|
8792
8889
|
return [];
|
|
8793
8890
|
}
|
|
@@ -8808,7 +8905,7 @@ function findSolution() {
|
|
|
8808
8905
|
process.exit(1);
|
|
8809
8906
|
}
|
|
8810
8907
|
if (current === ceiling) break;
|
|
8811
|
-
current =
|
|
8908
|
+
current = dirname18(current);
|
|
8812
8909
|
}
|
|
8813
8910
|
console.error(chalk100.red("No .sln file found between cwd and repo root"));
|
|
8814
8911
|
process.exit(1);
|
|
@@ -8858,7 +8955,7 @@ function parseInspectReport(json) {
|
|
|
8858
8955
|
|
|
8859
8956
|
// src/commands/dotnet/runInspectCode.ts
|
|
8860
8957
|
import { execSync as execSync24 } from "child_process";
|
|
8861
|
-
import { existsSync as existsSync29, readFileSync as
|
|
8958
|
+
import { existsSync as existsSync29, readFileSync as readFileSync24, unlinkSync as unlinkSync6 } from "fs";
|
|
8862
8959
|
import { tmpdir as tmpdir3 } from "os";
|
|
8863
8960
|
import path25 from "path";
|
|
8864
8961
|
import chalk102 from "chalk";
|
|
@@ -8893,7 +8990,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
8893
8990
|
console.error(chalk102.red("Report file not generated"));
|
|
8894
8991
|
process.exit(1);
|
|
8895
8992
|
}
|
|
8896
|
-
const xml =
|
|
8993
|
+
const xml = readFileSync24(reportPath, "utf-8");
|
|
8897
8994
|
unlinkSync6(reportPath);
|
|
8898
8995
|
return xml;
|
|
8899
8996
|
}
|
|
@@ -9020,9 +9117,9 @@ function aggregateCommitters(authorLists) {
|
|
|
9020
9117
|
|
|
9021
9118
|
// src/shared/runGhGraphql.ts
|
|
9022
9119
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
9023
|
-
import { unlinkSync as unlinkSync7, writeFileSync as
|
|
9120
|
+
import { unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
|
|
9024
9121
|
import { tmpdir as tmpdir4 } from "os";
|
|
9025
|
-
import { join as
|
|
9122
|
+
import { join as join28 } from "path";
|
|
9026
9123
|
function buildArgs(queryFile, vars) {
|
|
9027
9124
|
const args = ["api", "graphql", "-F", `query=@${queryFile}`];
|
|
9028
9125
|
for (const [key, value] of Object.entries(vars)) {
|
|
@@ -9032,8 +9129,8 @@ function buildArgs(queryFile, vars) {
|
|
|
9032
9129
|
return args;
|
|
9033
9130
|
}
|
|
9034
9131
|
function runGhGraphql(mutation, vars) {
|
|
9035
|
-
const queryFile =
|
|
9036
|
-
|
|
9132
|
+
const queryFile = join28(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
9133
|
+
writeFileSync19(queryFile, mutation);
|
|
9037
9134
|
try {
|
|
9038
9135
|
const result = spawnSync2("gh", buildArgs(queryFile, vars), {
|
|
9039
9136
|
encoding: "utf-8"
|
|
@@ -9210,8 +9307,8 @@ function registerGithub(program2) {
|
|
|
9210
9307
|
}
|
|
9211
9308
|
|
|
9212
9309
|
// src/commands/handover/archive.ts
|
|
9213
|
-
import { existsSync as existsSync30, mkdirSync as
|
|
9214
|
-
import { join as
|
|
9310
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync8, renameSync as renameSync2 } from "fs";
|
|
9311
|
+
import { join as join30 } from "path";
|
|
9215
9312
|
|
|
9216
9313
|
// src/commands/handover/formatArchiveTimestamp.ts
|
|
9217
9314
|
function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
@@ -9226,9 +9323,9 @@ function formatArchiveTimestamp(date = /* @__PURE__ */ new Date()) {
|
|
|
9226
9323
|
}
|
|
9227
9324
|
|
|
9228
9325
|
// src/commands/handover/getHandoverArchiveDir.ts
|
|
9229
|
-
import { join as
|
|
9326
|
+
import { join as join29 } from "path";
|
|
9230
9327
|
function getHandoverArchiveDir(cwd = process.cwd()) {
|
|
9231
|
-
return
|
|
9328
|
+
return join29(cwd, ".assist", "handovers", "archive");
|
|
9232
9329
|
}
|
|
9233
9330
|
|
|
9234
9331
|
// src/commands/handover/archive.ts
|
|
@@ -9238,11 +9335,11 @@ function buildArchiveFilename(timestamp, suffix) {
|
|
|
9238
9335
|
return `${base}.md`;
|
|
9239
9336
|
}
|
|
9240
9337
|
function resolveCollisionPath(archiveDir, timestamp, suffix) {
|
|
9241
|
-
const initial =
|
|
9338
|
+
const initial = join30(archiveDir, buildArchiveFilename(timestamp, suffix));
|
|
9242
9339
|
if (!existsSync30(initial)) return initial;
|
|
9243
9340
|
for (let i = 1; i <= MAX_COLLISION_SUFFIX; i++) {
|
|
9244
9341
|
const collisionSuffix = suffix ? `${suffix}-${i}` : `${i}`;
|
|
9245
|
-
const candidate =
|
|
9342
|
+
const candidate = join30(
|
|
9246
9343
|
archiveDir,
|
|
9247
9344
|
buildArchiveFilename(timestamp, collisionSuffix)
|
|
9248
9345
|
);
|
|
@@ -9257,7 +9354,7 @@ function archive(options2 = {}) {
|
|
|
9257
9354
|
const handoverPath = getHandoverPath(cwd);
|
|
9258
9355
|
if (!existsSync30(handoverPath)) return void 0;
|
|
9259
9356
|
const archiveDir = getHandoverArchiveDir(cwd);
|
|
9260
|
-
|
|
9357
|
+
mkdirSync8(archiveDir, { recursive: true });
|
|
9261
9358
|
const timestamp = formatArchiveTimestamp(options2.now);
|
|
9262
9359
|
const destination = resolveCollisionPath(
|
|
9263
9360
|
archiveDir,
|
|
@@ -9269,7 +9366,7 @@ function archive(options2 = {}) {
|
|
|
9269
9366
|
}
|
|
9270
9367
|
|
|
9271
9368
|
// src/commands/handover/load.ts
|
|
9272
|
-
import { existsSync as existsSync31, readFileSync as
|
|
9369
|
+
import { existsSync as existsSync31, readFileSync as readFileSync26 } from "fs";
|
|
9273
9370
|
|
|
9274
9371
|
// src/commands/handover/parseLoadInput.ts
|
|
9275
9372
|
async function parseLoadInput(stdin) {
|
|
@@ -9385,7 +9482,7 @@ function normaliseOutput(raw) {
|
|
|
9385
9482
|
function loadFromHandover(cwd) {
|
|
9386
9483
|
const handoverPath = getHandoverPath(cwd);
|
|
9387
9484
|
if (!existsSync31(handoverPath)) return void 0;
|
|
9388
|
-
const content =
|
|
9485
|
+
const content = readFileSync26(handoverPath, "utf-8");
|
|
9389
9486
|
archive({ cwd });
|
|
9390
9487
|
return {
|
|
9391
9488
|
additionalContext: content,
|
|
@@ -9552,20 +9649,20 @@ function acceptanceCriteria(issueKey) {
|
|
|
9552
9649
|
import { execSync as execSync27 } from "child_process";
|
|
9553
9650
|
|
|
9554
9651
|
// src/shared/loadJson.ts
|
|
9555
|
-
import { existsSync as existsSync32, mkdirSync as
|
|
9652
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync9, readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "fs";
|
|
9556
9653
|
import { homedir as homedir8 } from "os";
|
|
9557
|
-
import { join as
|
|
9654
|
+
import { join as join31 } from "path";
|
|
9558
9655
|
function getStoreDir() {
|
|
9559
|
-
return
|
|
9656
|
+
return join31(homedir8(), ".assist");
|
|
9560
9657
|
}
|
|
9561
9658
|
function getStorePath(filename) {
|
|
9562
|
-
return
|
|
9659
|
+
return join31(getStoreDir(), filename);
|
|
9563
9660
|
}
|
|
9564
9661
|
function loadJson(filename) {
|
|
9565
|
-
const
|
|
9566
|
-
if (existsSync32(
|
|
9662
|
+
const path53 = getStorePath(filename);
|
|
9663
|
+
if (existsSync32(path53)) {
|
|
9567
9664
|
try {
|
|
9568
|
-
return JSON.parse(
|
|
9665
|
+
return JSON.parse(readFileSync27(path53, "utf-8"));
|
|
9569
9666
|
} catch {
|
|
9570
9667
|
return {};
|
|
9571
9668
|
}
|
|
@@ -9575,9 +9672,9 @@ function loadJson(filename) {
|
|
|
9575
9672
|
function saveJson(filename, data) {
|
|
9576
9673
|
const dir = getStoreDir();
|
|
9577
9674
|
if (!existsSync32(dir)) {
|
|
9578
|
-
|
|
9675
|
+
mkdirSync9(dir, { recursive: true });
|
|
9579
9676
|
}
|
|
9580
|
-
|
|
9677
|
+
writeFileSync20(getStorePath(filename), JSON.stringify(data, null, 2));
|
|
9581
9678
|
}
|
|
9582
9679
|
|
|
9583
9680
|
// src/shared/promptInput.ts
|
|
@@ -9710,12 +9807,12 @@ function registerList(program2) {
|
|
|
9710
9807
|
}
|
|
9711
9808
|
|
|
9712
9809
|
// src/commands/mermaid/index.ts
|
|
9713
|
-
import { mkdirSync as
|
|
9810
|
+
import { mkdirSync as mkdirSync10, readdirSync as readdirSync5 } from "fs";
|
|
9714
9811
|
import { resolve as resolve10 } from "path";
|
|
9715
9812
|
import chalk113 from "chalk";
|
|
9716
9813
|
|
|
9717
9814
|
// src/commands/mermaid/exportFile.ts
|
|
9718
|
-
import { readFileSync as
|
|
9815
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "fs";
|
|
9719
9816
|
import { basename as basename5, extname, resolve as resolve9 } from "path";
|
|
9720
9817
|
import chalk112 from "chalk";
|
|
9721
9818
|
|
|
@@ -9741,7 +9838,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
9741
9838
|
|
|
9742
9839
|
// src/commands/mermaid/exportFile.ts
|
|
9743
9840
|
async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
9744
|
-
const content =
|
|
9841
|
+
const content = readFileSync28(file, "utf8");
|
|
9745
9842
|
const blocks = extractMermaidBlocks(content);
|
|
9746
9843
|
const stem = basename5(file, extname(file));
|
|
9747
9844
|
if (onlyIndex !== void 0) {
|
|
@@ -9766,7 +9863,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
9766
9863
|
if (onlyIndex !== void 0 && idx !== onlyIndex) continue;
|
|
9767
9864
|
const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
|
|
9768
9865
|
const svg = await renderBlock(krokiUrl, source);
|
|
9769
|
-
|
|
9866
|
+
writeFileSync21(outPath, svg, "utf8");
|
|
9770
9867
|
console.log(chalk112.green(` \u2192 ${outPath}`));
|
|
9771
9868
|
}
|
|
9772
9869
|
}
|
|
@@ -9779,7 +9876,7 @@ function extractMermaidBlocks(markdown) {
|
|
|
9779
9876
|
async function mermaidExport(file, options2 = {}) {
|
|
9780
9877
|
const { mermaid } = loadConfig();
|
|
9781
9878
|
const outDir = resolve10(process.cwd(), options2.out ?? ".");
|
|
9782
|
-
|
|
9879
|
+
mkdirSync10(outDir, { recursive: true });
|
|
9783
9880
|
if (options2.index !== void 0) {
|
|
9784
9881
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
9785
9882
|
console.error(
|
|
@@ -10249,15 +10346,15 @@ function postComment(vars) {
|
|
|
10249
10346
|
}
|
|
10250
10347
|
runGhGraphql(MUTATION_MULTI, { ...base, startLine });
|
|
10251
10348
|
}
|
|
10252
|
-
function comment2(
|
|
10349
|
+
function comment2(path53, line, body, startLine) {
|
|
10253
10350
|
validateBody(body);
|
|
10254
10351
|
validateLine(line);
|
|
10255
10352
|
if (startLine !== void 0) validateLine(startLine);
|
|
10256
10353
|
try {
|
|
10257
10354
|
const prId = getCurrentPrNodeId();
|
|
10258
|
-
postComment({ prId, body, path:
|
|
10355
|
+
postComment({ prId, body, path: path53, line, startLine });
|
|
10259
10356
|
const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
|
|
10260
|
-
console.log(`Added review comment on ${
|
|
10357
|
+
console.log(`Added review comment on ${path53}:${range}`);
|
|
10261
10358
|
} catch (error) {
|
|
10262
10359
|
if (isGhNotInstalled(error)) {
|
|
10263
10360
|
console.error("Error: GitHub CLI (gh) is not installed.");
|
|
@@ -10335,23 +10432,23 @@ import { execSync as execSync32 } from "child_process";
|
|
|
10335
10432
|
|
|
10336
10433
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
10337
10434
|
import { execSync as execSync31 } from "child_process";
|
|
10338
|
-
import { unlinkSync as unlinkSync9, writeFileSync as
|
|
10435
|
+
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync22 } from "fs";
|
|
10339
10436
|
import { tmpdir as tmpdir5 } from "os";
|
|
10340
|
-
import { join as
|
|
10437
|
+
import { join as join33 } from "path";
|
|
10341
10438
|
|
|
10342
10439
|
// src/commands/prs/loadCommentsCache.ts
|
|
10343
|
-
import { existsSync as existsSync33, readFileSync as
|
|
10344
|
-
import { join as
|
|
10440
|
+
import { existsSync as existsSync33, readFileSync as readFileSync29, unlinkSync as unlinkSync8 } from "fs";
|
|
10441
|
+
import { join as join32 } from "path";
|
|
10345
10442
|
import { parse as parse2 } from "yaml";
|
|
10346
10443
|
function getCachePath(prNumber) {
|
|
10347
|
-
return
|
|
10444
|
+
return join32(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
|
|
10348
10445
|
}
|
|
10349
10446
|
function loadCommentsCache(prNumber) {
|
|
10350
10447
|
const cachePath = getCachePath(prNumber);
|
|
10351
10448
|
if (!existsSync33(cachePath)) {
|
|
10352
10449
|
return null;
|
|
10353
10450
|
}
|
|
10354
|
-
const content =
|
|
10451
|
+
const content = readFileSync29(cachePath, "utf-8");
|
|
10355
10452
|
return parse2(content);
|
|
10356
10453
|
}
|
|
10357
10454
|
function deleteCommentsCache(prNumber) {
|
|
@@ -10371,8 +10468,8 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
10371
10468
|
}
|
|
10372
10469
|
function resolveThread(threadId) {
|
|
10373
10470
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
10374
|
-
const queryFile =
|
|
10375
|
-
|
|
10471
|
+
const queryFile = join33(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
|
|
10472
|
+
writeFileSync22(queryFile, mutation);
|
|
10376
10473
|
try {
|
|
10377
10474
|
execSync31(
|
|
10378
10475
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
@@ -10453,19 +10550,19 @@ function fixed(commentId, sha) {
|
|
|
10453
10550
|
}
|
|
10454
10551
|
|
|
10455
10552
|
// src/commands/prs/listComments/index.ts
|
|
10456
|
-
import { existsSync as existsSync34, mkdirSync as
|
|
10457
|
-
import { join as
|
|
10553
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync11, writeFileSync as writeFileSync24 } from "fs";
|
|
10554
|
+
import { join as join35 } from "path";
|
|
10458
10555
|
import { stringify } from "yaml";
|
|
10459
10556
|
|
|
10460
10557
|
// src/commands/prs/fetchThreadIds.ts
|
|
10461
10558
|
import { execSync as execSync33 } from "child_process";
|
|
10462
|
-
import { unlinkSync as unlinkSync10, writeFileSync as
|
|
10559
|
+
import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync23 } from "fs";
|
|
10463
10560
|
import { tmpdir as tmpdir6 } from "os";
|
|
10464
|
-
import { join as
|
|
10561
|
+
import { join as join34 } from "path";
|
|
10465
10562
|
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 } } } } } } }`;
|
|
10466
10563
|
function fetchThreadIds(org, repo, prNumber) {
|
|
10467
|
-
const queryFile =
|
|
10468
|
-
|
|
10564
|
+
const queryFile = join34(tmpdir6(), `gh-query-${Date.now()}.graphql`);
|
|
10565
|
+
writeFileSync23(queryFile, THREAD_QUERY);
|
|
10469
10566
|
try {
|
|
10470
10567
|
const result = execSync33(
|
|
10471
10568
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
@@ -10578,17 +10675,17 @@ function printComments2(result) {
|
|
|
10578
10675
|
|
|
10579
10676
|
// src/commands/prs/listComments/index.ts
|
|
10580
10677
|
function writeCommentsCache(prNumber, comments3) {
|
|
10581
|
-
const assistDir =
|
|
10678
|
+
const assistDir = join35(process.cwd(), ".assist");
|
|
10582
10679
|
if (!existsSync34(assistDir)) {
|
|
10583
|
-
|
|
10680
|
+
mkdirSync11(assistDir, { recursive: true });
|
|
10584
10681
|
}
|
|
10585
10682
|
const cacheData = {
|
|
10586
10683
|
prNumber,
|
|
10587
10684
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10588
10685
|
comments: comments3
|
|
10589
10686
|
};
|
|
10590
|
-
const cachePath =
|
|
10591
|
-
|
|
10687
|
+
const cachePath = join35(assistDir, `pr-${prNumber}-comments.yaml`);
|
|
10688
|
+
writeFileSync24(cachePath, stringify(cacheData));
|
|
10592
10689
|
}
|
|
10593
10690
|
function handleKnownErrors(error) {
|
|
10594
10691
|
if (isGhNotInstalled(error)) {
|
|
@@ -10620,7 +10717,7 @@ async function listComments() {
|
|
|
10620
10717
|
];
|
|
10621
10718
|
updateCache(prNumber, allComments);
|
|
10622
10719
|
const hasLineComments = allComments.some((c) => c.type === "line");
|
|
10623
|
-
const cachePath = hasLineComments ?
|
|
10720
|
+
const cachePath = hasLineComments ? join35(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`) : null;
|
|
10624
10721
|
return { comments: allComments, cachePath };
|
|
10625
10722
|
} catch (error) {
|
|
10626
10723
|
const handled = handleKnownErrors(error);
|
|
@@ -10837,8 +10934,8 @@ function registerPrs(program2) {
|
|
|
10837
10934
|
prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason) => {
|
|
10838
10935
|
wontfix(Number.parseInt(commentId, 10), reason);
|
|
10839
10936
|
});
|
|
10840
|
-
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((
|
|
10841
|
-
comment2(
|
|
10937
|
+
prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path53, line, body) => {
|
|
10938
|
+
comment2(path53, Number.parseInt(line, 10), body);
|
|
10842
10939
|
});
|
|
10843
10940
|
}
|
|
10844
10941
|
|
|
@@ -11090,10 +11187,10 @@ function resolveOpSecret(reference) {
|
|
|
11090
11187
|
}
|
|
11091
11188
|
|
|
11092
11189
|
// src/commands/ravendb/ravenFetch.ts
|
|
11093
|
-
async function ravenFetch(connection,
|
|
11190
|
+
async function ravenFetch(connection, path53) {
|
|
11094
11191
|
const apiKey = resolveOpSecret(connection.apiKeyRef);
|
|
11095
11192
|
let accessToken = await getAccessToken(apiKey);
|
|
11096
|
-
const url = `${connection.url}${
|
|
11193
|
+
const url = `${connection.url}${path53}`;
|
|
11097
11194
|
const headers = {
|
|
11098
11195
|
Authorization: `Bearer ${accessToken}`,
|
|
11099
11196
|
"Content-Type": "application/json"
|
|
@@ -11183,16 +11280,16 @@ import chalk129 from "chalk";
|
|
|
11183
11280
|
// src/commands/ravendb/buildQueryPath.ts
|
|
11184
11281
|
function buildQueryPath(opts) {
|
|
11185
11282
|
const db = encodeURIComponent(opts.db);
|
|
11186
|
-
let
|
|
11283
|
+
let path53;
|
|
11187
11284
|
if (opts.collection) {
|
|
11188
|
-
|
|
11285
|
+
path53 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
|
|
11189
11286
|
} else {
|
|
11190
|
-
|
|
11287
|
+
path53 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
|
|
11191
11288
|
}
|
|
11192
11289
|
if (opts.query) {
|
|
11193
|
-
|
|
11290
|
+
path53 += `&query=${encodeURIComponent(opts.query)}`;
|
|
11194
11291
|
}
|
|
11195
|
-
return
|
|
11292
|
+
return path53;
|
|
11196
11293
|
}
|
|
11197
11294
|
|
|
11198
11295
|
// src/commands/ravendb/fetchAllPages.ts
|
|
@@ -11201,7 +11298,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11201
11298
|
let start3 = 0;
|
|
11202
11299
|
while (true) {
|
|
11203
11300
|
const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
|
|
11204
|
-
const
|
|
11301
|
+
const path53 = buildQueryPath({
|
|
11205
11302
|
db: connection.database,
|
|
11206
11303
|
collection: opts.collection,
|
|
11207
11304
|
start: start3,
|
|
@@ -11209,7 +11306,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
11209
11306
|
sort: opts.sort,
|
|
11210
11307
|
query: opts.query
|
|
11211
11308
|
});
|
|
11212
|
-
const data = await ravenFetch(connection,
|
|
11309
|
+
const data = await ravenFetch(connection, path53);
|
|
11213
11310
|
const results = data.Results ?? [];
|
|
11214
11311
|
const totalResults = data.TotalResults ?? 0;
|
|
11215
11312
|
if (results.length === 0) break;
|
|
@@ -12427,8 +12524,8 @@ function findRootParent(file, importedBy, visited) {
|
|
|
12427
12524
|
function clusterFiles(graph) {
|
|
12428
12525
|
const clusters = /* @__PURE__ */ new Map();
|
|
12429
12526
|
for (const file of graph.files) {
|
|
12430
|
-
const
|
|
12431
|
-
if (
|
|
12527
|
+
const basename10 = path38.basename(file, path38.extname(file));
|
|
12528
|
+
if (basename10 === "index") continue;
|
|
12432
12529
|
const importers = graph.importedBy.get(file);
|
|
12433
12530
|
if (!importers || importers.size !== 1) continue;
|
|
12434
12531
|
const parent = [...importers][0];
|
|
@@ -12905,15 +13002,15 @@ ${context.diff.trimEnd()}
|
|
|
12905
13002
|
}
|
|
12906
13003
|
|
|
12907
13004
|
// src/commands/review/buildReviewPaths.ts
|
|
12908
|
-
import { join as
|
|
13005
|
+
import { join as join36 } from "path";
|
|
12909
13006
|
function buildReviewPaths(repoRoot, key) {
|
|
12910
|
-
const reviewDir =
|
|
13007
|
+
const reviewDir = join36(repoRoot, ".assist", "reviews", key);
|
|
12911
13008
|
return {
|
|
12912
13009
|
reviewDir,
|
|
12913
|
-
requestPath:
|
|
12914
|
-
claudePath:
|
|
12915
|
-
codexPath:
|
|
12916
|
-
synthesisPath:
|
|
13010
|
+
requestPath: join36(reviewDir, "request.md"),
|
|
13011
|
+
claudePath: join36(reviewDir, "claude.md"),
|
|
13012
|
+
codexPath: join36(reviewDir, "codex.md"),
|
|
13013
|
+
synthesisPath: join36(reviewDir, "synthesis.md")
|
|
12917
13014
|
};
|
|
12918
13015
|
}
|
|
12919
13016
|
|
|
@@ -12921,24 +13018,24 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
12921
13018
|
import {
|
|
12922
13019
|
appendFileSync,
|
|
12923
13020
|
existsSync as existsSync35,
|
|
12924
|
-
readFileSync as
|
|
12925
|
-
writeFileSync as
|
|
13021
|
+
readFileSync as readFileSync30,
|
|
13022
|
+
writeFileSync as writeFileSync25
|
|
12926
13023
|
} from "fs";
|
|
12927
|
-
import { join as
|
|
13024
|
+
import { join as join37 } from "path";
|
|
12928
13025
|
var REVIEWS_ENTRY = ".assist/reviews";
|
|
12929
13026
|
function coversReviews(line) {
|
|
12930
13027
|
const pattern2 = line.trim().replace(/^\//, "").replace(/\/$/, "");
|
|
12931
13028
|
return pattern2 === ".assist" || pattern2 === REVIEWS_ENTRY;
|
|
12932
13029
|
}
|
|
12933
13030
|
function ensureReviewsIgnored(repoRoot) {
|
|
12934
|
-
const gitignorePath =
|
|
13031
|
+
const gitignorePath = join37(repoRoot, ".gitignore");
|
|
12935
13032
|
if (!existsSync35(gitignorePath)) {
|
|
12936
|
-
|
|
13033
|
+
writeFileSync25(gitignorePath, `${REVIEWS_ENTRY}
|
|
12937
13034
|
`);
|
|
12938
13035
|
console.log(`Created .gitignore with ${REVIEWS_ENTRY} entry.`);
|
|
12939
13036
|
return;
|
|
12940
13037
|
}
|
|
12941
|
-
const content =
|
|
13038
|
+
const content = readFileSync30(gitignorePath, "utf-8");
|
|
12942
13039
|
if (content.split("\n").some(coversReviews)) return;
|
|
12943
13040
|
const separator = content === "" || content.endsWith("\n") ? "" : "\n";
|
|
12944
13041
|
appendFileSync(gitignorePath, `${separator}${REVIEWS_ENTRY}
|
|
@@ -13085,7 +13182,7 @@ function gatherContext() {
|
|
|
13085
13182
|
}
|
|
13086
13183
|
|
|
13087
13184
|
// src/commands/review/postReviewToPr.ts
|
|
13088
|
-
import { readFileSync as
|
|
13185
|
+
import { readFileSync as readFileSync31 } from "fs";
|
|
13089
13186
|
|
|
13090
13187
|
// src/commands/review/parseFindings.ts
|
|
13091
13188
|
var SEVERITIES = ["blocker", "major", "minor", "nit"];
|
|
@@ -13315,7 +13412,7 @@ async function postReviewToPr(synthesisPath, options2) {
|
|
|
13315
13412
|
console.log("No PR found for current branch; nothing posted.");
|
|
13316
13413
|
return;
|
|
13317
13414
|
}
|
|
13318
|
-
const markdown =
|
|
13415
|
+
const markdown = readFileSync31(synthesisPath, "utf-8");
|
|
13319
13416
|
const findings = parseFindings(markdown);
|
|
13320
13417
|
if (findings.length === 0) {
|
|
13321
13418
|
console.log("Synthesis contains no findings; nothing to post.");
|
|
@@ -13392,16 +13489,16 @@ async function handlePostSynthesis(synthesisPath, options2) {
|
|
|
13392
13489
|
}
|
|
13393
13490
|
|
|
13394
13491
|
// src/commands/review/prepareReviewDir.ts
|
|
13395
|
-
import { existsSync as existsSync36, mkdirSync as
|
|
13492
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync12, unlinkSync as unlinkSync11, writeFileSync as writeFileSync26 } from "fs";
|
|
13396
13493
|
function clearReviewFiles(paths) {
|
|
13397
|
-
for (const
|
|
13398
|
-
if (existsSync36(
|
|
13494
|
+
for (const path53 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
|
|
13495
|
+
if (existsSync36(path53)) unlinkSync11(path53);
|
|
13399
13496
|
}
|
|
13400
13497
|
}
|
|
13401
13498
|
function prepareReviewDir(paths, requestBody, force) {
|
|
13402
|
-
|
|
13499
|
+
mkdirSync12(paths.reviewDir, { recursive: true });
|
|
13403
13500
|
if (force) clearReviewFiles(paths);
|
|
13404
|
-
|
|
13501
|
+
writeFileSync26(paths.requestPath, requestBody);
|
|
13405
13502
|
}
|
|
13406
13503
|
|
|
13407
13504
|
// src/commands/review/runApplySession.ts
|
|
@@ -13744,7 +13841,7 @@ The review request is at: ${requestPath}
|
|
|
13744
13841
|
}
|
|
13745
13842
|
|
|
13746
13843
|
// src/commands/review/runClaudeReviewer.ts
|
|
13747
|
-
import { writeFileSync as
|
|
13844
|
+
import { writeFileSync as writeFileSync27 } from "fs";
|
|
13748
13845
|
|
|
13749
13846
|
// src/commands/review/finaliseReviewerSpinner.ts
|
|
13750
13847
|
var SUMMARY_MAX_LEN = 80;
|
|
@@ -14080,7 +14177,7 @@ async function runClaudeReviewer(spec) {
|
|
|
14080
14177
|
}
|
|
14081
14178
|
});
|
|
14082
14179
|
if (result.exitCode === 0 && finalText)
|
|
14083
|
-
|
|
14180
|
+
writeFileSync27(spec.outputPath, finalText);
|
|
14084
14181
|
return finaliseReviewerRun({ ...spec, command }, spinner, result);
|
|
14085
14182
|
}
|
|
14086
14183
|
|
|
@@ -14196,7 +14293,7 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
|
|
|
14196
14293
|
}
|
|
14197
14294
|
|
|
14198
14295
|
// src/commands/review/synthesise.ts
|
|
14199
|
-
import { readFileSync as
|
|
14296
|
+
import { readFileSync as readFileSync32 } from "fs";
|
|
14200
14297
|
|
|
14201
14298
|
// src/commands/review/buildSynthesisStdin.ts
|
|
14202
14299
|
var SYNTHESIS_PROMPT = `You are consolidating two independent code reviews of the same change. The original review request is in request.md. The two reviews are in claude.md and codex.md in the current working directory.
|
|
@@ -14252,7 +14349,7 @@ Files:
|
|
|
14252
14349
|
|
|
14253
14350
|
// src/commands/review/synthesise.ts
|
|
14254
14351
|
function printSummary2(synthesisPath) {
|
|
14255
|
-
const markdown =
|
|
14352
|
+
const markdown = readFileSync32(synthesisPath, "utf-8");
|
|
14256
14353
|
console.log("");
|
|
14257
14354
|
console.log(buildReviewSummary(markdown));
|
|
14258
14355
|
console.log("");
|
|
@@ -14531,8 +14628,8 @@ import chalk147 from "chalk";
|
|
|
14531
14628
|
|
|
14532
14629
|
// src/commands/seq/fetchSeq.ts
|
|
14533
14630
|
import chalk144 from "chalk";
|
|
14534
|
-
async function fetchSeq(conn,
|
|
14535
|
-
const url = `${conn.url}${
|
|
14631
|
+
async function fetchSeq(conn, path53, params) {
|
|
14632
|
+
const url = `${conn.url}${path53}?${params}`;
|
|
14536
14633
|
const response = await fetch(url, {
|
|
14537
14634
|
headers: {
|
|
14538
14635
|
Accept: "application/json",
|
|
@@ -15077,7 +15174,7 @@ function registerSql(program2) {
|
|
|
15077
15174
|
|
|
15078
15175
|
// src/commands/transcript/shared.ts
|
|
15079
15176
|
import { existsSync as existsSync39, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
15080
|
-
import { basename as basename6, join as
|
|
15177
|
+
import { basename as basename6, join as join38, relative as relative2 } from "path";
|
|
15081
15178
|
import * as readline2 from "readline";
|
|
15082
15179
|
var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
|
|
15083
15180
|
function getDatePrefix(daysOffset = 0) {
|
|
@@ -15095,7 +15192,7 @@ function collectFiles(dir, extension) {
|
|
|
15095
15192
|
if (!existsSync39(dir)) return [];
|
|
15096
15193
|
const results = [];
|
|
15097
15194
|
for (const entry of readdirSync6(dir)) {
|
|
15098
|
-
const fullPath =
|
|
15195
|
+
const fullPath = join38(dir, entry);
|
|
15099
15196
|
if (statSync4(fullPath).isDirectory()) {
|
|
15100
15197
|
results.push(...collectFiles(fullPath, extension));
|
|
15101
15198
|
} else if (entry.endsWith(extension)) {
|
|
@@ -15192,11 +15289,11 @@ async function configure() {
|
|
|
15192
15289
|
import { existsSync as existsSync41 } from "fs";
|
|
15193
15290
|
|
|
15194
15291
|
// src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
|
|
15195
|
-
import { dirname as
|
|
15292
|
+
import { dirname as dirname20, join as join40 } from "path";
|
|
15196
15293
|
|
|
15197
15294
|
// src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
|
|
15198
15295
|
import { renameSync as renameSync3 } from "fs";
|
|
15199
|
-
import { join as
|
|
15296
|
+
import { join as join39 } from "path";
|
|
15200
15297
|
async function resolveDate(rl, choice) {
|
|
15201
15298
|
if (choice === "1") return getDatePrefix(0);
|
|
15202
15299
|
if (choice === "2") return getDatePrefix(-1);
|
|
@@ -15211,7 +15308,7 @@ async function resolveDate(rl, choice) {
|
|
|
15211
15308
|
}
|
|
15212
15309
|
function renameWithPrefix(vttDir, vttFile, prefix2) {
|
|
15213
15310
|
const newFilename = `${prefix2}.${vttFile}`;
|
|
15214
|
-
renameSync3(
|
|
15311
|
+
renameSync3(join39(vttDir, vttFile), join39(vttDir, newFilename));
|
|
15215
15312
|
console.log(`Renamed to: ${newFilename}`);
|
|
15216
15313
|
return newFilename;
|
|
15217
15314
|
}
|
|
@@ -15242,15 +15339,15 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
15242
15339
|
for (let i = 0; i < vttFiles.length; i++) {
|
|
15243
15340
|
const vttFile = vttFiles[i];
|
|
15244
15341
|
if (!isValidDatePrefix(vttFile.filename)) {
|
|
15245
|
-
const vttFileDir =
|
|
15342
|
+
const vttFileDir = dirname20(vttFile.absolutePath);
|
|
15246
15343
|
const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
|
|
15247
15344
|
if (newFilename) {
|
|
15248
|
-
const newRelativePath =
|
|
15249
|
-
|
|
15345
|
+
const newRelativePath = join40(
|
|
15346
|
+
dirname20(vttFile.relativePath),
|
|
15250
15347
|
newFilename
|
|
15251
15348
|
);
|
|
15252
15349
|
vttFiles[i] = {
|
|
15253
|
-
absolutePath:
|
|
15350
|
+
absolutePath: join40(vttFileDir, newFilename),
|
|
15254
15351
|
relativePath: newRelativePath,
|
|
15255
15352
|
filename: newFilename
|
|
15256
15353
|
};
|
|
@@ -15263,8 +15360,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
|
|
|
15263
15360
|
}
|
|
15264
15361
|
|
|
15265
15362
|
// src/commands/transcript/format/processVttFile/index.ts
|
|
15266
|
-
import { existsSync as existsSync40, mkdirSync as
|
|
15267
|
-
import { basename as basename7, dirname as
|
|
15363
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync13, readFileSync as readFileSync33, writeFileSync as writeFileSync28 } from "fs";
|
|
15364
|
+
import { basename as basename7, dirname as dirname21, join as join41 } from "path";
|
|
15268
15365
|
|
|
15269
15366
|
// src/commands/transcript/cleanText.ts
|
|
15270
15367
|
function cleanText(text2) {
|
|
@@ -15474,22 +15571,22 @@ function toMdFilename(vttFilename) {
|
|
|
15474
15571
|
return `${basename7(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
|
|
15475
15572
|
}
|
|
15476
15573
|
function resolveOutputDir(relativeDir, transcriptsDir) {
|
|
15477
|
-
return relativeDir === "." ? transcriptsDir :
|
|
15574
|
+
return relativeDir === "." ? transcriptsDir : join41(transcriptsDir, relativeDir);
|
|
15478
15575
|
}
|
|
15479
15576
|
function buildOutputPaths(vttFile, transcriptsDir) {
|
|
15480
15577
|
const mdFile = toMdFilename(vttFile.filename);
|
|
15481
|
-
const relativeDir =
|
|
15578
|
+
const relativeDir = dirname21(vttFile.relativePath);
|
|
15482
15579
|
const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
|
|
15483
|
-
const outputPath =
|
|
15580
|
+
const outputPath = join41(outputDir, mdFile);
|
|
15484
15581
|
return { outputDir, outputPath, mdFile, relativeDir };
|
|
15485
15582
|
}
|
|
15486
15583
|
function logSkipped(relativeDir, mdFile) {
|
|
15487
|
-
console.log(`Skipping (already exists): ${
|
|
15584
|
+
console.log(`Skipping (already exists): ${join41(relativeDir, mdFile)}`);
|
|
15488
15585
|
return "skipped";
|
|
15489
15586
|
}
|
|
15490
15587
|
function ensureDirectory(dir, label2) {
|
|
15491
15588
|
if (!existsSync40(dir)) {
|
|
15492
|
-
|
|
15589
|
+
mkdirSync13(dir, { recursive: true });
|
|
15493
15590
|
console.log(`Created ${label2}: ${dir}`);
|
|
15494
15591
|
}
|
|
15495
15592
|
}
|
|
@@ -15511,10 +15608,10 @@ function logReduction(cueCount, messageCount) {
|
|
|
15511
15608
|
}
|
|
15512
15609
|
function readAndParseCues(inputPath) {
|
|
15513
15610
|
console.log(`Reading: ${inputPath}`);
|
|
15514
|
-
return processCues(
|
|
15611
|
+
return processCues(readFileSync33(inputPath, "utf-8"));
|
|
15515
15612
|
}
|
|
15516
15613
|
function writeFormatted(outputPath, content) {
|
|
15517
|
-
|
|
15614
|
+
writeFileSync28(outputPath, content, "utf-8");
|
|
15518
15615
|
console.log(`Written: ${outputPath}`);
|
|
15519
15616
|
}
|
|
15520
15617
|
function convertVttToMarkdown(inputPath, outputPath) {
|
|
@@ -15583,17 +15680,17 @@ async function format() {
|
|
|
15583
15680
|
|
|
15584
15681
|
// src/commands/transcript/summarise/index.ts
|
|
15585
15682
|
import { existsSync as existsSync43 } from "fs";
|
|
15586
|
-
import { basename as basename8, dirname as
|
|
15683
|
+
import { basename as basename8, dirname as dirname23, join as join43, relative as relative3 } from "path";
|
|
15587
15684
|
|
|
15588
15685
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
15589
15686
|
import {
|
|
15590
15687
|
existsSync as existsSync42,
|
|
15591
|
-
mkdirSync as
|
|
15592
|
-
readFileSync as
|
|
15688
|
+
mkdirSync as mkdirSync14,
|
|
15689
|
+
readFileSync as readFileSync34,
|
|
15593
15690
|
renameSync as renameSync4,
|
|
15594
|
-
rmSync
|
|
15691
|
+
rmSync as rmSync2
|
|
15595
15692
|
} from "fs";
|
|
15596
|
-
import { dirname as
|
|
15693
|
+
import { dirname as dirname22, join as join42 } from "path";
|
|
15597
15694
|
|
|
15598
15695
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
15599
15696
|
import chalk154 from "chalk";
|
|
@@ -15622,7 +15719,7 @@ function validateStagedContent(filename, content) {
|
|
|
15622
15719
|
}
|
|
15623
15720
|
|
|
15624
15721
|
// src/commands/transcript/summarise/processStagedFile/index.ts
|
|
15625
|
-
var STAGING_DIR =
|
|
15722
|
+
var STAGING_DIR = join42(process.cwd(), ".assist", "transcript");
|
|
15626
15723
|
function processStagedFile() {
|
|
15627
15724
|
if (!existsSync42(STAGING_DIR)) {
|
|
15628
15725
|
return false;
|
|
@@ -15633,7 +15730,7 @@ function processStagedFile() {
|
|
|
15633
15730
|
}
|
|
15634
15731
|
const { transcriptsDir, summaryDir } = getTranscriptConfig();
|
|
15635
15732
|
const stagedFile = stagedFiles[0];
|
|
15636
|
-
const content =
|
|
15733
|
+
const content = readFileSync34(stagedFile.absolutePath, "utf-8");
|
|
15637
15734
|
validateStagedContent(stagedFile.filename, content);
|
|
15638
15735
|
const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
|
|
15639
15736
|
const transcriptFiles = findMdFilesRecursive(transcriptsDir);
|
|
@@ -15646,23 +15743,23 @@ function processStagedFile() {
|
|
|
15646
15743
|
);
|
|
15647
15744
|
process.exit(1);
|
|
15648
15745
|
}
|
|
15649
|
-
const destPath =
|
|
15650
|
-
const destDir =
|
|
15746
|
+
const destPath = join42(summaryDir, matchingTranscript.relativePath);
|
|
15747
|
+
const destDir = dirname22(destPath);
|
|
15651
15748
|
if (!existsSync42(destDir)) {
|
|
15652
|
-
|
|
15749
|
+
mkdirSync14(destDir, { recursive: true });
|
|
15653
15750
|
}
|
|
15654
15751
|
renameSync4(stagedFile.absolutePath, destPath);
|
|
15655
15752
|
const remaining = findMdFilesRecursive(STAGING_DIR);
|
|
15656
15753
|
if (remaining.length === 0) {
|
|
15657
|
-
|
|
15754
|
+
rmSync2(STAGING_DIR, { recursive: true });
|
|
15658
15755
|
}
|
|
15659
15756
|
return true;
|
|
15660
15757
|
}
|
|
15661
15758
|
|
|
15662
15759
|
// src/commands/transcript/summarise/index.ts
|
|
15663
15760
|
function buildRelativeKey(relativePath, baseName) {
|
|
15664
|
-
const relDir =
|
|
15665
|
-
return relDir === "." ? baseName :
|
|
15761
|
+
const relDir = dirname23(relativePath);
|
|
15762
|
+
return relDir === "." ? baseName : join43(relDir, baseName);
|
|
15666
15763
|
}
|
|
15667
15764
|
function buildSummaryIndex(summaryDir) {
|
|
15668
15765
|
const summaryFiles = findMdFilesRecursive(summaryDir);
|
|
@@ -15696,8 +15793,8 @@ function summarise3() {
|
|
|
15696
15793
|
}
|
|
15697
15794
|
const next3 = missing[0];
|
|
15698
15795
|
const outputFilename = `${getTranscriptBaseName(next3.filename)}.md`;
|
|
15699
|
-
const outputPath =
|
|
15700
|
-
const summaryFileDir =
|
|
15796
|
+
const outputPath = join43(STAGING_DIR, outputFilename);
|
|
15797
|
+
const summaryFileDir = join43(summaryDir, dirname23(next3.relativePath));
|
|
15701
15798
|
const relativeTranscriptPath = encodeURI(
|
|
15702
15799
|
relative3(summaryFileDir, next3.absolutePath).replace(/\\/g, "/")
|
|
15703
15800
|
);
|
|
@@ -15746,50 +15843,50 @@ function registerVerify(program2) {
|
|
|
15746
15843
|
|
|
15747
15844
|
// src/commands/voice/devices.ts
|
|
15748
15845
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
15749
|
-
import { join as
|
|
15846
|
+
import { join as join45 } from "path";
|
|
15750
15847
|
|
|
15751
15848
|
// src/commands/voice/shared.ts
|
|
15752
15849
|
import { homedir as homedir9 } from "os";
|
|
15753
|
-
import { dirname as
|
|
15850
|
+
import { dirname as dirname24, join as join44 } from "path";
|
|
15754
15851
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
15755
|
-
var __dirname6 =
|
|
15756
|
-
var VOICE_DIR =
|
|
15852
|
+
var __dirname6 = dirname24(fileURLToPath6(import.meta.url));
|
|
15853
|
+
var VOICE_DIR = join44(homedir9(), ".assist", "voice");
|
|
15757
15854
|
var voicePaths = {
|
|
15758
15855
|
dir: VOICE_DIR,
|
|
15759
|
-
pid:
|
|
15760
|
-
log:
|
|
15761
|
-
venv:
|
|
15762
|
-
lock:
|
|
15856
|
+
pid: join44(VOICE_DIR, "voice.pid"),
|
|
15857
|
+
log: join44(VOICE_DIR, "voice.log"),
|
|
15858
|
+
venv: join44(VOICE_DIR, ".venv"),
|
|
15859
|
+
lock: join44(VOICE_DIR, "voice.lock")
|
|
15763
15860
|
};
|
|
15764
15861
|
function getPythonDir() {
|
|
15765
|
-
return
|
|
15862
|
+
return join44(__dirname6, "commands", "voice", "python");
|
|
15766
15863
|
}
|
|
15767
15864
|
function getVenvPython() {
|
|
15768
|
-
return process.platform === "win32" ?
|
|
15865
|
+
return process.platform === "win32" ? join44(voicePaths.venv, "Scripts", "python.exe") : join44(voicePaths.venv, "bin", "python");
|
|
15769
15866
|
}
|
|
15770
15867
|
function getLockDir() {
|
|
15771
15868
|
const config = loadConfig();
|
|
15772
15869
|
return config.voice?.lockDir ?? VOICE_DIR;
|
|
15773
15870
|
}
|
|
15774
15871
|
function getLockFile() {
|
|
15775
|
-
return
|
|
15872
|
+
return join44(getLockDir(), "voice.lock");
|
|
15776
15873
|
}
|
|
15777
15874
|
|
|
15778
15875
|
// src/commands/voice/devices.ts
|
|
15779
15876
|
function devices() {
|
|
15780
|
-
const script =
|
|
15877
|
+
const script = join45(getPythonDir(), "list_devices.py");
|
|
15781
15878
|
spawnSync4(getVenvPython(), [script], { stdio: "inherit" });
|
|
15782
15879
|
}
|
|
15783
15880
|
|
|
15784
15881
|
// src/commands/voice/logs.ts
|
|
15785
|
-
import { existsSync as existsSync44, readFileSync as
|
|
15882
|
+
import { existsSync as existsSync44, readFileSync as readFileSync35 } from "fs";
|
|
15786
15883
|
function logs(options2) {
|
|
15787
15884
|
if (!existsSync44(voicePaths.log)) {
|
|
15788
15885
|
console.log("No voice log file found");
|
|
15789
15886
|
return;
|
|
15790
15887
|
}
|
|
15791
15888
|
const count6 = Number.parseInt(options2.lines ?? "150", 10);
|
|
15792
|
-
const content =
|
|
15889
|
+
const content = readFileSync35(voicePaths.log, "utf-8").trim();
|
|
15793
15890
|
if (!content) {
|
|
15794
15891
|
console.log("Voice log is empty");
|
|
15795
15892
|
return;
|
|
@@ -15811,13 +15908,13 @@ function logs(options2) {
|
|
|
15811
15908
|
|
|
15812
15909
|
// src/commands/voice/setup.ts
|
|
15813
15910
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
15814
|
-
import { mkdirSync as
|
|
15815
|
-
import { join as
|
|
15911
|
+
import { mkdirSync as mkdirSync16 } from "fs";
|
|
15912
|
+
import { join as join47 } from "path";
|
|
15816
15913
|
|
|
15817
15914
|
// src/commands/voice/checkLockFile.ts
|
|
15818
15915
|
import { execSync as execSync44 } from "child_process";
|
|
15819
|
-
import { existsSync as existsSync45, mkdirSync as
|
|
15820
|
-
import { join as
|
|
15916
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync15, readFileSync as readFileSync36, writeFileSync as writeFileSync29 } from "fs";
|
|
15917
|
+
import { join as join46 } from "path";
|
|
15821
15918
|
function isProcessAlive2(pid) {
|
|
15822
15919
|
try {
|
|
15823
15920
|
process.kill(pid, 0);
|
|
@@ -15830,7 +15927,7 @@ function checkLockFile() {
|
|
|
15830
15927
|
const lockFile = getLockFile();
|
|
15831
15928
|
if (!existsSync45(lockFile)) return;
|
|
15832
15929
|
try {
|
|
15833
|
-
const lock = JSON.parse(
|
|
15930
|
+
const lock = JSON.parse(readFileSync36(lockFile, "utf-8"));
|
|
15834
15931
|
if (lock.pid && isProcessAlive2(lock.pid)) {
|
|
15835
15932
|
console.error(
|
|
15836
15933
|
`Voice daemon already running (PID ${lock.pid}, env: ${lock.env}). Stop it first with: assist voice stop`
|
|
@@ -15854,8 +15951,8 @@ function bootstrapVenv() {
|
|
|
15854
15951
|
}
|
|
15855
15952
|
function writeLockFile(pid) {
|
|
15856
15953
|
const lockFile = getLockFile();
|
|
15857
|
-
|
|
15858
|
-
|
|
15954
|
+
mkdirSync15(join46(lockFile, ".."), { recursive: true });
|
|
15955
|
+
writeFileSync29(
|
|
15859
15956
|
lockFile,
|
|
15860
15957
|
JSON.stringify({
|
|
15861
15958
|
pid,
|
|
@@ -15867,10 +15964,10 @@ function writeLockFile(pid) {
|
|
|
15867
15964
|
|
|
15868
15965
|
// src/commands/voice/setup.ts
|
|
15869
15966
|
function setup() {
|
|
15870
|
-
|
|
15967
|
+
mkdirSync16(voicePaths.dir, { recursive: true });
|
|
15871
15968
|
bootstrapVenv();
|
|
15872
15969
|
console.log("\nDownloading models...\n");
|
|
15873
|
-
const script =
|
|
15970
|
+
const script = join47(getPythonDir(), "setup_models.py");
|
|
15874
15971
|
const result = spawnSync5(getVenvPython(), [script], {
|
|
15875
15972
|
stdio: "inherit",
|
|
15876
15973
|
env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
|
|
@@ -15883,8 +15980,8 @@ function setup() {
|
|
|
15883
15980
|
|
|
15884
15981
|
// src/commands/voice/start.ts
|
|
15885
15982
|
import { spawn as spawn7 } from "child_process";
|
|
15886
|
-
import { mkdirSync as
|
|
15887
|
-
import { join as
|
|
15983
|
+
import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync30 } from "fs";
|
|
15984
|
+
import { join as join48 } from "path";
|
|
15888
15985
|
|
|
15889
15986
|
// src/commands/voice/buildDaemonEnv.ts
|
|
15890
15987
|
function buildDaemonEnv(options2) {
|
|
@@ -15912,17 +16009,17 @@ function spawnBackground(python, script, env) {
|
|
|
15912
16009
|
console.error("Failed to start voice daemon");
|
|
15913
16010
|
process.exit(1);
|
|
15914
16011
|
}
|
|
15915
|
-
|
|
16012
|
+
writeFileSync30(voicePaths.pid, String(pid));
|
|
15916
16013
|
writeLockFile(pid);
|
|
15917
16014
|
console.log(`Voice daemon started (PID ${pid})`);
|
|
15918
16015
|
}
|
|
15919
16016
|
function start2(options2) {
|
|
15920
|
-
|
|
16017
|
+
mkdirSync17(voicePaths.dir, { recursive: true });
|
|
15921
16018
|
checkLockFile();
|
|
15922
16019
|
bootstrapVenv();
|
|
15923
16020
|
const debug = options2.debug || options2.foreground || process.platform === "win32";
|
|
15924
16021
|
const env = buildDaemonEnv({ debug });
|
|
15925
|
-
const script =
|
|
16022
|
+
const script = join48(getPythonDir(), "voice_daemon.py");
|
|
15926
16023
|
const python = getVenvPython();
|
|
15927
16024
|
if (options2.foreground) {
|
|
15928
16025
|
spawnForeground(python, script, env);
|
|
@@ -15932,7 +16029,7 @@ function start2(options2) {
|
|
|
15932
16029
|
}
|
|
15933
16030
|
|
|
15934
16031
|
// src/commands/voice/status.ts
|
|
15935
|
-
import { existsSync as existsSync46, readFileSync as
|
|
16032
|
+
import { existsSync as existsSync46, readFileSync as readFileSync37 } from "fs";
|
|
15936
16033
|
function isProcessAlive3(pid) {
|
|
15937
16034
|
try {
|
|
15938
16035
|
process.kill(pid, 0);
|
|
@@ -15943,7 +16040,7 @@ function isProcessAlive3(pid) {
|
|
|
15943
16040
|
}
|
|
15944
16041
|
function readRecentLogs(count6) {
|
|
15945
16042
|
if (!existsSync46(voicePaths.log)) return [];
|
|
15946
|
-
const lines =
|
|
16043
|
+
const lines = readFileSync37(voicePaths.log, "utf-8").trim().split("\n");
|
|
15947
16044
|
return lines.slice(-count6);
|
|
15948
16045
|
}
|
|
15949
16046
|
function status() {
|
|
@@ -15951,7 +16048,7 @@ function status() {
|
|
|
15951
16048
|
console.log("Voice daemon: not running (no PID file)");
|
|
15952
16049
|
return;
|
|
15953
16050
|
}
|
|
15954
|
-
const pid = Number.parseInt(
|
|
16051
|
+
const pid = Number.parseInt(readFileSync37(voicePaths.pid, "utf-8").trim(), 10);
|
|
15955
16052
|
const alive = isProcessAlive3(pid);
|
|
15956
16053
|
console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
|
|
15957
16054
|
const recent = readRecentLogs(5);
|
|
@@ -15970,13 +16067,13 @@ function status() {
|
|
|
15970
16067
|
}
|
|
15971
16068
|
|
|
15972
16069
|
// src/commands/voice/stop.ts
|
|
15973
|
-
import { existsSync as existsSync47, readFileSync as
|
|
16070
|
+
import { existsSync as existsSync47, readFileSync as readFileSync38, unlinkSync as unlinkSync14 } from "fs";
|
|
15974
16071
|
function stop2() {
|
|
15975
16072
|
if (!existsSync47(voicePaths.pid)) {
|
|
15976
16073
|
console.log("Voice daemon is not running (no PID file)");
|
|
15977
16074
|
return;
|
|
15978
16075
|
}
|
|
15979
|
-
const pid = Number.parseInt(
|
|
16076
|
+
const pid = Number.parseInt(readFileSync38(voicePaths.pid, "utf-8").trim(), 10);
|
|
15980
16077
|
try {
|
|
15981
16078
|
process.kill(pid, "SIGTERM");
|
|
15982
16079
|
console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
|
|
@@ -16211,8 +16308,8 @@ async function auth() {
|
|
|
16211
16308
|
|
|
16212
16309
|
// src/commands/roam/postRoamActivity.ts
|
|
16213
16310
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
16214
|
-
import { readdirSync as readdirSync7, readFileSync as
|
|
16215
|
-
import { join as
|
|
16311
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync39, statSync as statSync5 } from "fs";
|
|
16312
|
+
import { join as join49 } from "path";
|
|
16216
16313
|
function findPortFile(roamDir) {
|
|
16217
16314
|
let entries;
|
|
16218
16315
|
try {
|
|
@@ -16221,9 +16318,9 @@ function findPortFile(roamDir) {
|
|
|
16221
16318
|
return void 0;
|
|
16222
16319
|
}
|
|
16223
16320
|
const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
|
|
16224
|
-
const
|
|
16321
|
+
const path53 = join49(roamDir, name);
|
|
16225
16322
|
try {
|
|
16226
|
-
return { path:
|
|
16323
|
+
return { path: path53, mtimeMs: statSync5(path53).mtimeMs };
|
|
16227
16324
|
} catch {
|
|
16228
16325
|
return void 0;
|
|
16229
16326
|
}
|
|
@@ -16233,11 +16330,11 @@ function findPortFile(roamDir) {
|
|
|
16233
16330
|
function postRoamActivity(app, event) {
|
|
16234
16331
|
const appData = process.env.APPDATA;
|
|
16235
16332
|
if (!appData) return;
|
|
16236
|
-
const portFile = findPortFile(
|
|
16333
|
+
const portFile = findPortFile(join49(appData, "Roam"));
|
|
16237
16334
|
if (!portFile) return;
|
|
16238
16335
|
let port;
|
|
16239
16336
|
try {
|
|
16240
|
-
port =
|
|
16337
|
+
port = readFileSync39(portFile, "utf-8").trim();
|
|
16241
16338
|
} catch {
|
|
16242
16339
|
return;
|
|
16243
16340
|
}
|
|
@@ -16380,13 +16477,13 @@ function runPreCommands(pre, cwd) {
|
|
|
16380
16477
|
// src/commands/run/spawnRunCommand.ts
|
|
16381
16478
|
import { execFileSync as execFileSync8, spawn as spawn8 } from "child_process";
|
|
16382
16479
|
import { existsSync as existsSync48 } from "fs";
|
|
16383
|
-
import { dirname as
|
|
16480
|
+
import { dirname as dirname25, join as join50, resolve as resolve11 } from "path";
|
|
16384
16481
|
function resolveCommand2(command) {
|
|
16385
16482
|
if (process.platform !== "win32" || command !== "bash") return command;
|
|
16386
16483
|
try {
|
|
16387
16484
|
const gitPath = execFileSync8("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
|
|
16388
|
-
const gitRoot = resolve11(
|
|
16389
|
-
const gitBash =
|
|
16485
|
+
const gitRoot = resolve11(dirname25(gitPath), "..");
|
|
16486
|
+
const gitBash = join50(gitRoot, "bin", "bash.exe");
|
|
16390
16487
|
if (existsSync48(gitBash)) return gitBash;
|
|
16391
16488
|
} catch {
|
|
16392
16489
|
}
|
|
@@ -16472,8 +16569,8 @@ async function run3(name, args) {
|
|
|
16472
16569
|
}
|
|
16473
16570
|
|
|
16474
16571
|
// src/commands/run/add.ts
|
|
16475
|
-
import { mkdirSync as
|
|
16476
|
-
import { join as
|
|
16572
|
+
import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync31 } from "fs";
|
|
16573
|
+
import { join as join51 } from "path";
|
|
16477
16574
|
|
|
16478
16575
|
// src/commands/run/extractOption.ts
|
|
16479
16576
|
function extractOption(args, flag) {
|
|
@@ -16534,16 +16631,16 @@ function saveNewRunConfig(name, command, args, cwd) {
|
|
|
16534
16631
|
saveConfig(config);
|
|
16535
16632
|
}
|
|
16536
16633
|
function createCommandFile(name) {
|
|
16537
|
-
const dir =
|
|
16538
|
-
|
|
16634
|
+
const dir = join51(".claude", "commands");
|
|
16635
|
+
mkdirSync18(dir, { recursive: true });
|
|
16539
16636
|
const content = `---
|
|
16540
16637
|
description: Run ${name}
|
|
16541
16638
|
---
|
|
16542
16639
|
|
|
16543
16640
|
Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
16544
16641
|
`;
|
|
16545
|
-
const filePath =
|
|
16546
|
-
|
|
16642
|
+
const filePath = join51(dir, `${name}.md`);
|
|
16643
|
+
writeFileSync31(filePath, content);
|
|
16547
16644
|
console.log(`Created command file: ${filePath}`);
|
|
16548
16645
|
}
|
|
16549
16646
|
function add3() {
|
|
@@ -16566,11 +16663,11 @@ function findLinkIndex() {
|
|
|
16566
16663
|
function parseLinkArgs() {
|
|
16567
16664
|
const idx = findLinkIndex();
|
|
16568
16665
|
if (idx === -1) return null;
|
|
16569
|
-
const
|
|
16666
|
+
const path53 = process.argv[idx + 1];
|
|
16570
16667
|
const rest = process.argv.slice(idx + 2);
|
|
16571
16668
|
const { value: prefix2 } = extractOption(rest, "--prefix");
|
|
16572
16669
|
if (!prefix2) return null;
|
|
16573
|
-
return { path:
|
|
16670
|
+
return { path: path53, prefix: prefix2 };
|
|
16574
16671
|
}
|
|
16575
16672
|
function hasDuplicateLink(runList, linkPath) {
|
|
16576
16673
|
return runList.some(
|
|
@@ -16599,7 +16696,7 @@ function link2() {
|
|
|
16599
16696
|
|
|
16600
16697
|
// src/commands/run/remove.ts
|
|
16601
16698
|
import { existsSync as existsSync49, unlinkSync as unlinkSync15 } from "fs";
|
|
16602
|
-
import { join as
|
|
16699
|
+
import { join as join52 } from "path";
|
|
16603
16700
|
function findRemoveIndex() {
|
|
16604
16701
|
const idx = process.argv.indexOf("remove");
|
|
16605
16702
|
if (idx === -1 || idx + 1 >= process.argv.length) return -1;
|
|
@@ -16614,7 +16711,7 @@ function parseRemoveName() {
|
|
|
16614
16711
|
return process.argv[idx + 1];
|
|
16615
16712
|
}
|
|
16616
16713
|
function deleteCommandFile(name) {
|
|
16617
|
-
const filePath =
|
|
16714
|
+
const filePath = join52(".claude", "commands", `${name}.md`);
|
|
16618
16715
|
if (existsSync49(filePath)) {
|
|
16619
16716
|
unlinkSync15(filePath);
|
|
16620
16717
|
console.log(`Deleted command file: ${filePath}`);
|
|
@@ -16654,9 +16751,9 @@ function registerRun(program2) {
|
|
|
16654
16751
|
|
|
16655
16752
|
// src/commands/screenshot/index.ts
|
|
16656
16753
|
import { execSync as execSync47 } from "child_process";
|
|
16657
|
-
import { existsSync as existsSync50, mkdirSync as
|
|
16754
|
+
import { existsSync as existsSync50, mkdirSync as mkdirSync19, unlinkSync as unlinkSync16, writeFileSync as writeFileSync32 } from "fs";
|
|
16658
16755
|
import { tmpdir as tmpdir7 } from "os";
|
|
16659
|
-
import { join as
|
|
16756
|
+
import { join as join53, resolve as resolve13 } from "path";
|
|
16660
16757
|
import chalk156 from "chalk";
|
|
16661
16758
|
|
|
16662
16759
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
@@ -16787,14 +16884,14 @@ Write-Output $OutputPath
|
|
|
16787
16884
|
// src/commands/screenshot/index.ts
|
|
16788
16885
|
function buildOutputPath(outputDir, processName) {
|
|
16789
16886
|
if (!existsSync50(outputDir)) {
|
|
16790
|
-
|
|
16887
|
+
mkdirSync19(outputDir, { recursive: true });
|
|
16791
16888
|
}
|
|
16792
16889
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
16793
16890
|
return resolve13(outputDir, `${processName}-${timestamp}.png`);
|
|
16794
16891
|
}
|
|
16795
16892
|
function runPowerShellScript(processName, outputPath) {
|
|
16796
|
-
const scriptPath =
|
|
16797
|
-
|
|
16893
|
+
const scriptPath = join53(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
16894
|
+
writeFileSync32(scriptPath, captureWindowPs1, "utf-8");
|
|
16798
16895
|
try {
|
|
16799
16896
|
execSync47(
|
|
16800
16897
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
@@ -16870,7 +16967,7 @@ function applyLine(result, pending, line) {
|
|
|
16870
16967
|
}
|
|
16871
16968
|
|
|
16872
16969
|
// src/commands/sessions/daemon/reportStolenSocket.ts
|
|
16873
|
-
import { readFileSync as
|
|
16970
|
+
import { readFileSync as readFileSync40 } from "fs";
|
|
16874
16971
|
function reportStolenSocket(socketPid) {
|
|
16875
16972
|
if (!socketPid) return;
|
|
16876
16973
|
const filePid = readPidFile();
|
|
@@ -16882,7 +16979,7 @@ function reportStolenSocket(socketPid) {
|
|
|
16882
16979
|
function readPidFile() {
|
|
16883
16980
|
try {
|
|
16884
16981
|
const pid = Number.parseInt(
|
|
16885
|
-
|
|
16982
|
+
readFileSync40(daemonPaths.pid, "utf-8").trim(),
|
|
16886
16983
|
10
|
|
16887
16984
|
);
|
|
16888
16985
|
return Number.isInteger(pid) ? pid : void 0;
|
|
@@ -16969,7 +17066,7 @@ async function restartDaemon() {
|
|
|
16969
17066
|
}
|
|
16970
17067
|
|
|
16971
17068
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
16972
|
-
import { mkdirSync as
|
|
17069
|
+
import { mkdirSync as mkdirSync21 } from "fs";
|
|
16973
17070
|
|
|
16974
17071
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
16975
17072
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -17129,27 +17226,20 @@ function broadcast(clients, msg) {
|
|
|
17129
17226
|
}
|
|
17130
17227
|
}
|
|
17131
17228
|
|
|
17132
|
-
// src/commands/sessions/daemon/repoPrefix.ts
|
|
17133
|
-
import * as path47 from "path";
|
|
17134
|
-
function repoPrefix(cwd) {
|
|
17135
|
-
if (!cwd) return "";
|
|
17136
|
-
return `${path47.basename(cwd)}/`;
|
|
17137
|
-
}
|
|
17138
|
-
|
|
17139
17229
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
17140
17230
|
import * as pty from "node-pty";
|
|
17141
17231
|
|
|
17142
17232
|
// src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
|
|
17143
17233
|
import { chmodSync, existsSync as existsSync51, statSync as statSync6 } from "fs";
|
|
17144
17234
|
import { createRequire as createRequire3 } from "module";
|
|
17145
|
-
import
|
|
17235
|
+
import path47 from "path";
|
|
17146
17236
|
var require4 = createRequire3(import.meta.url);
|
|
17147
17237
|
var ensured = false;
|
|
17148
17238
|
function ensureSpawnHelperExecutable() {
|
|
17149
17239
|
if (ensured || process.platform !== "darwin") return;
|
|
17150
17240
|
ensured = true;
|
|
17151
|
-
const ptyRoot =
|
|
17152
|
-
const helper =
|
|
17241
|
+
const ptyRoot = path47.join(path47.dirname(require4.resolve("node-pty")), "..");
|
|
17242
|
+
const helper = path47.join(
|
|
17153
17243
|
ptyRoot,
|
|
17154
17244
|
"prebuilds",
|
|
17155
17245
|
`${process.platform}-${process.arch}`,
|
|
@@ -17161,7 +17251,7 @@ function ensureSpawnHelperExecutable() {
|
|
|
17161
17251
|
}
|
|
17162
17252
|
|
|
17163
17253
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
17164
|
-
function spawnPty(args, cwd) {
|
|
17254
|
+
function spawnPty(args, cwd, sessionId) {
|
|
17165
17255
|
ensureSpawnHelperExecutable();
|
|
17166
17256
|
const shell = process.platform === "win32" ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
17167
17257
|
const shellArgs = process.platform === "win32" ? ["/c", ...args] : ["-c", `exec ${args.map(shellEscape).join(" ")}`];
|
|
@@ -17170,7 +17260,13 @@ function spawnPty(args, cwd) {
|
|
|
17170
17260
|
cols: 120,
|
|
17171
17261
|
rows: 30,
|
|
17172
17262
|
cwd: cwd ?? process.cwd(),
|
|
17173
|
-
env: {
|
|
17263
|
+
env: {
|
|
17264
|
+
...process.env,
|
|
17265
|
+
...sessionId && {
|
|
17266
|
+
ASSIST_SESSION_ID: sessionId,
|
|
17267
|
+
ASSIST_ACTIVITY_ID: sessionId
|
|
17268
|
+
}
|
|
17269
|
+
}
|
|
17174
17270
|
});
|
|
17175
17271
|
}
|
|
17176
17272
|
function shellEscape(s) {
|
|
@@ -17181,11 +17277,11 @@ function shellEscape(s) {
|
|
|
17181
17277
|
function createAssistSession(id, assistArgs, cwd) {
|
|
17182
17278
|
return {
|
|
17183
17279
|
id,
|
|
17184
|
-
name:
|
|
17280
|
+
name: `assist ${assistArgs.join(" ")}`,
|
|
17185
17281
|
commandType: "assist",
|
|
17186
17282
|
status: "running",
|
|
17187
17283
|
startedAt: Date.now(),
|
|
17188
|
-
pty: spawnPty(["assist", ...assistArgs], cwd),
|
|
17284
|
+
pty: spawnPty(["assist", ...assistArgs], cwd, id),
|
|
17189
17285
|
scrollback: "",
|
|
17190
17286
|
idleTimer: null,
|
|
17191
17287
|
lastResizeAt: 0,
|
|
@@ -17213,7 +17309,7 @@ function spawnRun(opts) {
|
|
|
17213
17309
|
function createSession(id, prompt, cwd) {
|
|
17214
17310
|
return {
|
|
17215
17311
|
id,
|
|
17216
|
-
name:
|
|
17312
|
+
name: prompt?.slice(0, 40) || `Session ${id}`,
|
|
17217
17313
|
commandType: "claude",
|
|
17218
17314
|
status: "running",
|
|
17219
17315
|
startedAt: Date.now(),
|
|
@@ -17227,7 +17323,7 @@ function createSession(id, prompt, cwd) {
|
|
|
17227
17323
|
function createRunSession(id, runName, runArgs, cwd) {
|
|
17228
17324
|
return {
|
|
17229
17325
|
id,
|
|
17230
|
-
name:
|
|
17326
|
+
name: `run: ${runName}`,
|
|
17231
17327
|
commandType: "run",
|
|
17232
17328
|
status: "running",
|
|
17233
17329
|
startedAt: Date.now(),
|
|
@@ -17341,7 +17437,7 @@ function restoreSession(id, persisted) {
|
|
|
17341
17437
|
function resumeSession(id, sessionId, cwd, name) {
|
|
17342
17438
|
return {
|
|
17343
17439
|
id,
|
|
17344
|
-
name:
|
|
17440
|
+
name: name ? `${name.slice(0, 36)} (R)` : `Resume ${sessionId.slice(0, 8)}`,
|
|
17345
17441
|
commandType: "claude",
|
|
17346
17442
|
status: "running",
|
|
17347
17443
|
startedAt: Date.now(),
|
|
@@ -17413,7 +17509,7 @@ function respawnThunk(session) {
|
|
|
17413
17509
|
if (session.commandType === "run" && runName)
|
|
17414
17510
|
return () => spawnRun({ name: runName, args: runArgs, cwd });
|
|
17415
17511
|
if (session.commandType === "assist" && assistArgs)
|
|
17416
|
-
return () => spawnPty(["assist", ...assistArgs], cwd);
|
|
17512
|
+
return () => spawnPty(["assist", ...assistArgs], cwd, session.id);
|
|
17417
17513
|
return null;
|
|
17418
17514
|
}
|
|
17419
17515
|
|
|
@@ -17434,8 +17530,10 @@ function toSessionInfo({
|
|
|
17434
17530
|
startedAt,
|
|
17435
17531
|
runName,
|
|
17436
17532
|
runArgs,
|
|
17533
|
+
assistArgs,
|
|
17437
17534
|
cwd,
|
|
17438
|
-
restored
|
|
17535
|
+
restored,
|
|
17536
|
+
activity: activity2
|
|
17439
17537
|
}) {
|
|
17440
17538
|
return {
|
|
17441
17539
|
id,
|
|
@@ -17445,14 +17543,45 @@ function toSessionInfo({
|
|
|
17445
17543
|
startedAt,
|
|
17446
17544
|
runName,
|
|
17447
17545
|
runArgs,
|
|
17546
|
+
assistArgs,
|
|
17448
17547
|
cwd,
|
|
17449
|
-
restored
|
|
17548
|
+
restored,
|
|
17549
|
+
activity: activity2
|
|
17550
|
+
};
|
|
17551
|
+
}
|
|
17552
|
+
|
|
17553
|
+
// src/commands/sessions/daemon/watchActivity.ts
|
|
17554
|
+
import { existsSync as existsSync52, mkdirSync as mkdirSync20, watch } from "fs";
|
|
17555
|
+
import { dirname as dirname27 } from "path";
|
|
17556
|
+
var DEBOUNCE_MS = 50;
|
|
17557
|
+
function watchActivity(session, notify2) {
|
|
17558
|
+
if (session.commandType !== "assist" || !session.cwd) return;
|
|
17559
|
+
const path53 = activityPath(session.cwd, session.id);
|
|
17560
|
+
const dir = dirname27(path53);
|
|
17561
|
+
try {
|
|
17562
|
+
mkdirSync20(dir, { recursive: true });
|
|
17563
|
+
} catch {
|
|
17564
|
+
return;
|
|
17565
|
+
}
|
|
17566
|
+
let timer = null;
|
|
17567
|
+
const read = () => {
|
|
17568
|
+
timer = null;
|
|
17569
|
+
const activity2 = readActivity(path53);
|
|
17570
|
+
if (!activity2) return;
|
|
17571
|
+
session.activity = activity2;
|
|
17572
|
+
notify2();
|
|
17450
17573
|
};
|
|
17574
|
+
session.activityWatcher = watch(dir, (_event, filename) => {
|
|
17575
|
+
if (filename && !path53.endsWith(filename)) return;
|
|
17576
|
+
if (timer) clearTimeout(timer);
|
|
17577
|
+
timer = setTimeout(read, DEBOUNCE_MS);
|
|
17578
|
+
});
|
|
17579
|
+
if (existsSync52(path53)) read();
|
|
17451
17580
|
}
|
|
17452
17581
|
|
|
17453
17582
|
// src/commands/sessions/daemon/discoverClaudeSessionId.ts
|
|
17454
17583
|
import * as fs26 from "fs";
|
|
17455
|
-
import * as
|
|
17584
|
+
import * as path48 from "path";
|
|
17456
17585
|
var POLL_MS = 3e3;
|
|
17457
17586
|
async function discoverClaudeSessionId(options2) {
|
|
17458
17587
|
while (options2.isActive()) {
|
|
@@ -17468,7 +17597,7 @@ async function findNewSessionId(options2) {
|
|
|
17468
17597
|
if (!await isCreatedSince(filePath, options2.sinceMs)) continue;
|
|
17469
17598
|
const meta = await parseSessionFile(filePath);
|
|
17470
17599
|
if (!meta?.cwd || options2.isClaimed(meta.sessionId)) continue;
|
|
17471
|
-
if (
|
|
17600
|
+
if (path48.resolve(meta.cwd) === path48.resolve(options2.cwd))
|
|
17472
17601
|
return meta.sessionId;
|
|
17473
17602
|
}
|
|
17474
17603
|
return null;
|
|
@@ -17520,6 +17649,8 @@ function dismissSession(sessions, id) {
|
|
|
17520
17649
|
if (!s) return false;
|
|
17521
17650
|
if (s.status !== "done") s.pty?.kill();
|
|
17522
17651
|
clearIdle(s);
|
|
17652
|
+
s.activityWatcher?.close();
|
|
17653
|
+
if (s.cwd) removeActivity(s.cwd, s.id);
|
|
17523
17654
|
sessions.delete(id);
|
|
17524
17655
|
return true;
|
|
17525
17656
|
}
|
|
@@ -17558,6 +17689,7 @@ var SessionManager = class {
|
|
|
17558
17689
|
add(session) {
|
|
17559
17690
|
this.wire(session);
|
|
17560
17691
|
watchForClaudeSessionId(session, this.sessions, this.notify);
|
|
17692
|
+
watchActivity(session, this.notify);
|
|
17561
17693
|
return session.id;
|
|
17562
17694
|
}
|
|
17563
17695
|
spawn(prompt, cwd) {
|
|
@@ -17722,10 +17854,10 @@ function handleConnection(socket, manager) {
|
|
|
17722
17854
|
}
|
|
17723
17855
|
|
|
17724
17856
|
// src/commands/sessions/daemon/onListening.ts
|
|
17725
|
-
import { unlinkSync as unlinkSync17, writeFileSync as
|
|
17857
|
+
import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync33 } from "fs";
|
|
17726
17858
|
|
|
17727
17859
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
17728
|
-
import { readFileSync as
|
|
17860
|
+
import { readFileSync as readFileSync41 } from "fs";
|
|
17729
17861
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
17730
17862
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
17731
17863
|
const timer = setInterval(() => {
|
|
@@ -17736,7 +17868,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
17736
17868
|
}
|
|
17737
17869
|
function ownsPidFile() {
|
|
17738
17870
|
try {
|
|
17739
|
-
return
|
|
17871
|
+
return readFileSync41(daemonPaths.pid, "utf-8").trim() === String(process.pid);
|
|
17740
17872
|
} catch {
|
|
17741
17873
|
return false;
|
|
17742
17874
|
}
|
|
@@ -17744,7 +17876,7 @@ function ownsPidFile() {
|
|
|
17744
17876
|
|
|
17745
17877
|
// src/commands/sessions/daemon/onListening.ts
|
|
17746
17878
|
function onListening(manager, checkAutoExit) {
|
|
17747
|
-
|
|
17879
|
+
writeFileSync33(daemonPaths.pid, String(process.pid));
|
|
17748
17880
|
startPidFileWatchdog(() => {
|
|
17749
17881
|
daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
|
|
17750
17882
|
manager.shutdown();
|
|
@@ -17805,7 +17937,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
17805
17937
|
|
|
17806
17938
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
17807
17939
|
async function runDaemon() {
|
|
17808
|
-
|
|
17940
|
+
mkdirSync21(daemonPaths.dir, { recursive: true });
|
|
17809
17941
|
daemonLog(
|
|
17810
17942
|
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
17811
17943
|
);
|
|
@@ -18105,16 +18237,16 @@ async function statusLine() {
|
|
|
18105
18237
|
// src/commands/sync.ts
|
|
18106
18238
|
import * as fs32 from "fs";
|
|
18107
18239
|
import * as os2 from "os";
|
|
18108
|
-
import * as
|
|
18240
|
+
import * as path51 from "path";
|
|
18109
18241
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
18110
18242
|
|
|
18111
18243
|
// src/commands/sync/syncClaudeMd.ts
|
|
18112
18244
|
import * as fs30 from "fs";
|
|
18113
|
-
import * as
|
|
18245
|
+
import * as path49 from "path";
|
|
18114
18246
|
import chalk160 from "chalk";
|
|
18115
18247
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
18116
|
-
const source =
|
|
18117
|
-
const target =
|
|
18248
|
+
const source = path49.join(claudeDir, "CLAUDE.md");
|
|
18249
|
+
const target = path49.join(targetBase, "CLAUDE.md");
|
|
18118
18250
|
const sourceContent = fs30.readFileSync(source, "utf-8");
|
|
18119
18251
|
if (fs30.existsSync(target)) {
|
|
18120
18252
|
const targetContent = fs30.readFileSync(target, "utf-8");
|
|
@@ -18140,11 +18272,11 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
18140
18272
|
|
|
18141
18273
|
// src/commands/sync/syncSettings.ts
|
|
18142
18274
|
import * as fs31 from "fs";
|
|
18143
|
-
import * as
|
|
18275
|
+
import * as path50 from "path";
|
|
18144
18276
|
import chalk161 from "chalk";
|
|
18145
18277
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
18146
|
-
const source =
|
|
18147
|
-
const target =
|
|
18278
|
+
const source = path50.join(claudeDir, "settings.json");
|
|
18279
|
+
const target = path50.join(targetBase, "settings.json");
|
|
18148
18280
|
const sourceContent = fs31.readFileSync(source, "utf-8");
|
|
18149
18281
|
const mergedContent = JSON.stringify(JSON.parse(sourceContent), null, " ");
|
|
18150
18282
|
if (fs31.existsSync(target)) {
|
|
@@ -18180,23 +18312,23 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
18180
18312
|
|
|
18181
18313
|
// src/commands/sync.ts
|
|
18182
18314
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
18183
|
-
var __dirname7 =
|
|
18315
|
+
var __dirname7 = path51.dirname(__filename4);
|
|
18184
18316
|
async function sync(options2) {
|
|
18185
18317
|
const config = loadConfig();
|
|
18186
18318
|
const yes = options2?.yes ?? config.sync.autoConfirm;
|
|
18187
|
-
const claudeDir =
|
|
18188
|
-
const targetBase =
|
|
18319
|
+
const claudeDir = path51.join(__dirname7, "..", "claude");
|
|
18320
|
+
const targetBase = path51.join(os2.homedir(), ".claude");
|
|
18189
18321
|
syncCommands(claudeDir, targetBase);
|
|
18190
18322
|
await syncSettings(claudeDir, targetBase, { yes });
|
|
18191
18323
|
await syncClaudeMd(claudeDir, targetBase, { yes });
|
|
18192
18324
|
}
|
|
18193
18325
|
function syncCommands(claudeDir, targetBase) {
|
|
18194
|
-
const sourceDir =
|
|
18195
|
-
const targetDir =
|
|
18326
|
+
const sourceDir = path51.join(claudeDir, "commands");
|
|
18327
|
+
const targetDir = path51.join(targetBase, "commands");
|
|
18196
18328
|
fs32.mkdirSync(targetDir, { recursive: true });
|
|
18197
18329
|
const files = fs32.readdirSync(sourceDir);
|
|
18198
18330
|
for (const file of files) {
|
|
18199
|
-
fs32.copyFileSync(
|
|
18331
|
+
fs32.copyFileSync(path51.join(sourceDir, file), path51.join(targetDir, file));
|
|
18200
18332
|
console.log(`Copied ${file} to ${targetDir}`);
|
|
18201
18333
|
}
|
|
18202
18334
|
console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
|
|
@@ -18204,15 +18336,15 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
18204
18336
|
|
|
18205
18337
|
// src/commands/update.ts
|
|
18206
18338
|
import { execSync as execSync48 } from "child_process";
|
|
18207
|
-
import * as
|
|
18339
|
+
import * as path52 from "path";
|
|
18208
18340
|
function isGlobalNpmInstall(dir) {
|
|
18209
18341
|
try {
|
|
18210
|
-
const resolved =
|
|
18211
|
-
if (resolved.split(
|
|
18342
|
+
const resolved = path52.resolve(dir);
|
|
18343
|
+
if (resolved.split(path52.sep).includes("node_modules")) {
|
|
18212
18344
|
return true;
|
|
18213
18345
|
}
|
|
18214
18346
|
const globalPrefix = execSync48("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
18215
|
-
return resolved.toLowerCase().startsWith(
|
|
18347
|
+
return resolved.toLowerCase().startsWith(path52.resolve(globalPrefix).toLowerCase());
|
|
18216
18348
|
} catch {
|
|
18217
18349
|
return false;
|
|
18218
18350
|
}
|