@staff0rd/assist 0.294.0 → 0.295.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/commands/sessions/web/bundle.js +66 -66
- package/dist/index.js +794 -714
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.295.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -384,6 +384,7 @@ import {
|
|
|
384
384
|
|
|
385
385
|
// src/commands/backlog/backlogSchema.ts
|
|
386
386
|
import {
|
|
387
|
+
boolean,
|
|
387
388
|
foreignKey,
|
|
388
389
|
index,
|
|
389
390
|
integer,
|
|
@@ -401,7 +402,8 @@ var items = pgTable(
|
|
|
401
402
|
description: text(),
|
|
402
403
|
acceptanceCriteria: text("acceptance_criteria").notNull().default("[]"),
|
|
403
404
|
status: text().notNull().default("todo"),
|
|
404
|
-
currentPhase: integer("current_phase")
|
|
405
|
+
currentPhase: integer("current_phase"),
|
|
406
|
+
starred: boolean().notNull().default(false)
|
|
405
407
|
},
|
|
406
408
|
(t) => [index("items_origin_idx").on(t.origin)]
|
|
407
409
|
);
|
|
@@ -482,9 +484,13 @@ var SCHEMA = `
|
|
|
482
484
|
description TEXT,
|
|
483
485
|
acceptance_criteria TEXT NOT NULL DEFAULT '[]',
|
|
484
486
|
status TEXT NOT NULL DEFAULT 'todo',
|
|
485
|
-
current_phase INTEGER
|
|
487
|
+
current_phase INTEGER,
|
|
488
|
+
starred BOOLEAN NOT NULL DEFAULT false
|
|
486
489
|
);
|
|
487
490
|
|
|
491
|
+
-- Backfill the column on databases created before it was introduced.
|
|
492
|
+
ALTER TABLE items ADD COLUMN IF NOT EXISTS starred BOOLEAN NOT NULL DEFAULT false;
|
|
493
|
+
|
|
488
494
|
CREATE INDEX IF NOT EXISTS items_origin_idx ON items (origin);
|
|
489
495
|
|
|
490
496
|
CREATE TABLE IF NOT EXISTS comments (
|
|
@@ -2988,6 +2994,9 @@ function statusIcon(status2) {
|
|
|
2988
2994
|
return chalk27.dim("[-]");
|
|
2989
2995
|
}
|
|
2990
2996
|
}
|
|
2997
|
+
function starMarker(item) {
|
|
2998
|
+
return item.starred ? `${chalk27.yellow("\u2605")} ` : "";
|
|
2999
|
+
}
|
|
2991
3000
|
function typeLabel(type) {
|
|
2992
3001
|
switch (type) {
|
|
2993
3002
|
case "bug":
|
|
@@ -3093,8 +3102,8 @@ import chalk31 from "chalk";
|
|
|
3093
3102
|
|
|
3094
3103
|
// src/commands/backlog/deleteItem.ts
|
|
3095
3104
|
import { eq } from "drizzle-orm";
|
|
3096
|
-
async function deleteItem(orm,
|
|
3097
|
-
const [row] = await orm.delete(items).where(eq(items.id,
|
|
3105
|
+
async function deleteItem(orm, id2) {
|
|
3106
|
+
const [row] = await orm.delete(items).where(eq(items.id, id2)).returning({ name: items.name });
|
|
3098
3107
|
return row?.name;
|
|
3099
3108
|
}
|
|
3100
3109
|
|
|
@@ -3146,7 +3155,8 @@ function itemColumns(item, origin) {
|
|
|
3146
3155
|
description: item.description ?? null,
|
|
3147
3156
|
acceptanceCriteria: JSON.stringify(item.acceptanceCriteria),
|
|
3148
3157
|
status: item.status,
|
|
3149
|
-
currentPhase: item.currentPhase ?? null
|
|
3158
|
+
currentPhase: item.currentPhase ?? null,
|
|
3159
|
+
starred: item.starred
|
|
3150
3160
|
};
|
|
3151
3161
|
}
|
|
3152
3162
|
|
|
@@ -3321,22 +3331,23 @@ function baseItem(row) {
|
|
|
3321
3331
|
name: row.name,
|
|
3322
3332
|
acceptanceCriteria: JSON.parse(row.acceptanceCriteria),
|
|
3323
3333
|
status: row.status,
|
|
3334
|
+
starred: row.starred,
|
|
3324
3335
|
origin: row.origin
|
|
3325
3336
|
};
|
|
3326
3337
|
assignOptionalColumns(item, row);
|
|
3327
3338
|
return item;
|
|
3328
3339
|
}
|
|
3329
|
-
function attachComments(item, rel,
|
|
3330
|
-
const comments3 = (rel.comments.get(
|
|
3340
|
+
function attachComments(item, rel, id2) {
|
|
3341
|
+
const comments3 = (rel.comments.get(id2) ?? []).map(rowToComment);
|
|
3331
3342
|
if (comments3.length > 0) item.comments = comments3;
|
|
3332
3343
|
}
|
|
3333
|
-
function attachLinks(item, rel,
|
|
3334
|
-
const links2 = (rel.links.get(
|
|
3344
|
+
function attachLinks(item, rel, id2) {
|
|
3345
|
+
const links2 = (rel.links.get(id2) ?? []).map(rowToLink);
|
|
3335
3346
|
if (links2.length > 0) item.links = links2;
|
|
3336
3347
|
}
|
|
3337
|
-
function attachPlan(item, rel,
|
|
3338
|
-
const phases = rel.phases.get(
|
|
3339
|
-
if (phases.length > 0) item.plan = buildPlan(phases, rel.tasks.get(
|
|
3348
|
+
function attachPlan(item, rel, id2) {
|
|
3349
|
+
const phases = rel.phases.get(id2) ?? [];
|
|
3350
|
+
if (phases.length > 0) item.plan = buildPlan(phases, rel.tasks.get(id2) ?? []);
|
|
3340
3351
|
}
|
|
3341
3352
|
function rowToItem(row, rel) {
|
|
3342
3353
|
const item = baseItem(row);
|
|
@@ -3394,6 +3405,7 @@ var backlogItemSchema = z3.strictObject({
|
|
|
3394
3405
|
acceptanceCriteria: z3.array(z3.string()),
|
|
3395
3406
|
plan: z3.array(planPhaseSchema).optional(),
|
|
3396
3407
|
currentPhase: z3.number().optional(),
|
|
3408
|
+
starred: z3.boolean().default(false),
|
|
3397
3409
|
status: backlogStatusSchema,
|
|
3398
3410
|
comments: z3.array(backlogCommentSchema).optional(),
|
|
3399
3411
|
links: z3.array(backlogLinkSchema).optional(),
|
|
@@ -3530,10 +3542,10 @@ function getCurrentOrigin(cwd) {
|
|
|
3530
3542
|
|
|
3531
3543
|
// src/commands/backlog/loadItem.ts
|
|
3532
3544
|
import { eq as eq3 } from "drizzle-orm";
|
|
3533
|
-
async function loadItem(orm,
|
|
3534
|
-
const [row] = await orm.select().from(items).where(eq3(items.id,
|
|
3545
|
+
async function loadItem(orm, id2) {
|
|
3546
|
+
const [row] = await orm.select().from(items).where(eq3(items.id, id2));
|
|
3535
3547
|
if (!row) return void 0;
|
|
3536
|
-
const rel = await loadRelations(orm, [
|
|
3548
|
+
const rel = await loadRelations(orm, [id2]);
|
|
3537
3549
|
return rowToItem(row, rel);
|
|
3538
3550
|
}
|
|
3539
3551
|
|
|
@@ -3564,14 +3576,14 @@ async function searchItemIds(orm, query, origin) {
|
|
|
3564
3576
|
|
|
3565
3577
|
// src/commands/backlog/updateCurrentPhase.ts
|
|
3566
3578
|
import { eq as eq7 } from "drizzle-orm";
|
|
3567
|
-
async function updateCurrentPhase(orm,
|
|
3568
|
-
await orm.update(items).set({ currentPhase: phase }).where(eq7(items.id,
|
|
3579
|
+
async function updateCurrentPhase(orm, id2, phase) {
|
|
3580
|
+
await orm.update(items).set({ currentPhase: phase }).where(eq7(items.id, id2));
|
|
3569
3581
|
}
|
|
3570
3582
|
|
|
3571
3583
|
// src/commands/backlog/updateStatus.ts
|
|
3572
3584
|
import { eq as eq8 } from "drizzle-orm";
|
|
3573
|
-
async function updateStatus(orm,
|
|
3574
|
-
const [row] = await orm.update(items).set({ status: status2 }).where(eq8(items.id,
|
|
3585
|
+
async function updateStatus(orm, id2, status2) {
|
|
3586
|
+
const [row] = await orm.update(items).set({ status: status2 }).where(eq8(items.id, id2)).returning({ name: items.name });
|
|
3575
3587
|
return row?.name;
|
|
3576
3588
|
}
|
|
3577
3589
|
|
|
@@ -3603,35 +3615,35 @@ async function searchBacklog(query) {
|
|
|
3603
3615
|
const allItems = await loadAllItems(orm, origin);
|
|
3604
3616
|
return allItems.filter((item) => ids.includes(item.id));
|
|
3605
3617
|
}
|
|
3606
|
-
async function findOneItem(
|
|
3607
|
-
const numId = Number.parseInt(
|
|
3618
|
+
async function findOneItem(id2) {
|
|
3619
|
+
const numId = Number.parseInt(id2, 10);
|
|
3608
3620
|
const { orm } = await getReady();
|
|
3609
3621
|
const item = Number.isNaN(numId) ? void 0 : await loadItem(orm, numId);
|
|
3610
3622
|
if (!item) {
|
|
3611
|
-
console.log(chalk31.red(`Item #${
|
|
3623
|
+
console.log(chalk31.red(`Item #${id2} not found.`));
|
|
3612
3624
|
return void 0;
|
|
3613
3625
|
}
|
|
3614
3626
|
return { orm, item };
|
|
3615
3627
|
}
|
|
3616
|
-
async function setStatus(
|
|
3628
|
+
async function setStatus(id2, status2) {
|
|
3617
3629
|
const { orm } = await getReady();
|
|
3618
|
-
const name = await updateStatus(orm, Number.parseInt(
|
|
3619
|
-
if (name === void 0) console.log(chalk31.red(`Item #${
|
|
3630
|
+
const name = await updateStatus(orm, Number.parseInt(id2, 10), status2);
|
|
3631
|
+
if (name === void 0) console.log(chalk31.red(`Item #${id2} not found.`));
|
|
3620
3632
|
return name;
|
|
3621
3633
|
}
|
|
3622
|
-
async function setCurrentPhase(
|
|
3634
|
+
async function setCurrentPhase(id2, phase) {
|
|
3623
3635
|
const { orm } = await getReady();
|
|
3624
|
-
await updateCurrentPhase(orm, Number.parseInt(
|
|
3636
|
+
await updateCurrentPhase(orm, Number.parseInt(id2, 10), phase);
|
|
3625
3637
|
}
|
|
3626
|
-
async function removeItem(
|
|
3638
|
+
async function removeItem(id2) {
|
|
3627
3639
|
const { orm } = await getReady();
|
|
3628
|
-
const name = await deleteItem(orm, Number.parseInt(
|
|
3629
|
-
if (name === void 0) console.log(chalk31.red(`Item #${
|
|
3640
|
+
const name = await deleteItem(orm, Number.parseInt(id2, 10));
|
|
3641
|
+
if (name === void 0) console.log(chalk31.red(`Item #${id2} not found.`));
|
|
3630
3642
|
return name;
|
|
3631
3643
|
}
|
|
3632
3644
|
|
|
3633
3645
|
// src/commands/backlog/handleReviewResult.ts
|
|
3634
|
-
async function handleReviewResult(
|
|
3646
|
+
async function handleReviewResult(id2, review2) {
|
|
3635
3647
|
if (review2.kind === "fail" || review2.kind === "abort")
|
|
3636
3648
|
return { kind: "stop", success: false };
|
|
3637
3649
|
if (review2.kind === "paused") return { kind: "stop", success: true };
|
|
@@ -3641,12 +3653,12 @@ async function handleReviewResult(id, review2) {
|
|
|
3641
3653
|
startPhase: review2.targetPhase,
|
|
3642
3654
|
plan: review2.plan
|
|
3643
3655
|
};
|
|
3644
|
-
await ensureDone(
|
|
3656
|
+
await ensureDone(id2);
|
|
3645
3657
|
return { kind: "stop", success: true };
|
|
3646
3658
|
}
|
|
3647
|
-
async function ensureDone(
|
|
3659
|
+
async function ensureDone(id2) {
|
|
3648
3660
|
try {
|
|
3649
|
-
await setStatus(
|
|
3661
|
+
await setStatus(id2, "done");
|
|
3650
3662
|
} catch {
|
|
3651
3663
|
}
|
|
3652
3664
|
}
|
|
@@ -3668,20 +3680,20 @@ function resolvePlan(item) {
|
|
|
3668
3680
|
}
|
|
3669
3681
|
|
|
3670
3682
|
// src/commands/backlog/prepareRun.ts
|
|
3671
|
-
async function prepareRun(
|
|
3672
|
-
const found = await findOneItem(
|
|
3683
|
+
async function prepareRun(id2) {
|
|
3684
|
+
const found = await findOneItem(id2);
|
|
3673
3685
|
if (!found) return void 0;
|
|
3674
3686
|
const { item } = found;
|
|
3675
3687
|
const plan2 = resolvePlan(item);
|
|
3676
3688
|
const startPhase = (item.currentPhase ?? 1) - 1;
|
|
3677
3689
|
if (item.status === "done") {
|
|
3678
|
-
console.log(chalk32.green(`Already done: #${
|
|
3690
|
+
console.log(chalk32.green(`Already done: #${id2}: ${item.name}`));
|
|
3679
3691
|
return void 0;
|
|
3680
3692
|
}
|
|
3681
3693
|
if (startPhase > plan2.length) {
|
|
3682
|
-
await setStatus(
|
|
3694
|
+
await setStatus(id2, "done");
|
|
3683
3695
|
console.log(
|
|
3684
|
-
chalk32.green(`All phases already complete for #${
|
|
3696
|
+
chalk32.green(`All phases already complete for #${id2}: ${item.name}`)
|
|
3685
3697
|
);
|
|
3686
3698
|
return void 0;
|
|
3687
3699
|
}
|
|
@@ -3770,10 +3782,10 @@ function buildCommentLines(comments3) {
|
|
|
3770
3782
|
return ["", "Comments:", ...comments3.map(formatPromptComment)];
|
|
3771
3783
|
}
|
|
3772
3784
|
function formatPromptComment(entry) {
|
|
3773
|
-
const
|
|
3785
|
+
const id2 = entry.id !== void 0 ? `#${entry.id} ` : "";
|
|
3774
3786
|
const tag = entry.type === "summary" ? "[summary]" : "[comment]";
|
|
3775
3787
|
const phase = entry.phase !== void 0 ? ` (phase ${entry.phase})` : "";
|
|
3776
|
-
return `${
|
|
3788
|
+
return `${id2}${tag}${phase} ${entry.timestamp}
|
|
3777
3789
|
${entry.text}`;
|
|
3778
3790
|
}
|
|
3779
3791
|
|
|
@@ -4005,8 +4017,8 @@ async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases
|
|
|
4005
4017
|
}
|
|
4006
4018
|
|
|
4007
4019
|
// src/commands/backlog/reloadPlan.ts
|
|
4008
|
-
async function reloadPlan(
|
|
4009
|
-
const found = await findOneItem(String(
|
|
4020
|
+
async function reloadPlan(id2) {
|
|
4021
|
+
const found = await findOneItem(String(id2));
|
|
4010
4022
|
if (!found) return void 0;
|
|
4011
4023
|
return resolvePlan(found.item);
|
|
4012
4024
|
}
|
|
@@ -4073,15 +4085,15 @@ async function runOnce(item, startPhase, plan2, spawnOptions) {
|
|
|
4073
4085
|
}
|
|
4074
4086
|
|
|
4075
4087
|
// src/commands/backlog/run.ts
|
|
4076
|
-
async function run2(
|
|
4088
|
+
async function run2(id2, spawnOptions) {
|
|
4077
4089
|
if (blockedByHandover()) return false;
|
|
4078
|
-
const prepared = await prepareRun(
|
|
4090
|
+
const prepared = await prepareRun(id2);
|
|
4079
4091
|
if (!prepared) return false;
|
|
4080
|
-
await setStatus(
|
|
4081
|
-
logProgress(
|
|
4082
|
-
return runPrepared(
|
|
4092
|
+
await setStatus(id2, "in-progress");
|
|
4093
|
+
logProgress(id2, prepared);
|
|
4094
|
+
return runPrepared(id2, prepared, spawnOptions);
|
|
4083
4095
|
}
|
|
4084
|
-
async function runPrepared(
|
|
4096
|
+
async function runPrepared(id2, prepared, spawnOptions) {
|
|
4085
4097
|
const { item } = prepared;
|
|
4086
4098
|
let { plan: plan2, startPhase } = prepared;
|
|
4087
4099
|
acquireLock(item.id);
|
|
@@ -4089,7 +4101,7 @@ async function runPrepared(id, prepared, spawnOptions) {
|
|
|
4089
4101
|
while (true) {
|
|
4090
4102
|
const review2 = await runOnce(item, startPhase, plan2, spawnOptions);
|
|
4091
4103
|
spawnOptions = withoutResumeSession(spawnOptions);
|
|
4092
|
-
const outcome = await handleReviewResult(
|
|
4104
|
+
const outcome = await handleReviewResult(id2, review2);
|
|
4093
4105
|
if (outcome.kind === "stop") return outcome.success;
|
|
4094
4106
|
startPhase = outcome.startPhase;
|
|
4095
4107
|
plan2 = outcome.plan;
|
|
@@ -4098,8 +4110,8 @@ async function runPrepared(id, prepared, spawnOptions) {
|
|
|
4098
4110
|
releaseLock(item.id);
|
|
4099
4111
|
}
|
|
4100
4112
|
}
|
|
4101
|
-
function logProgress(
|
|
4102
|
-
console.log(chalk35.bold(`Running plan for #${
|
|
4113
|
+
function logProgress(id2, { plan: plan2, startPhase, item }) {
|
|
4114
|
+
console.log(chalk35.bold(`Running plan for #${id2}: ${item.name}`));
|
|
4103
4115
|
const totalPhases = plan2.length + 1;
|
|
4104
4116
|
if (startPhase > 0) {
|
|
4105
4117
|
const phaseNumber = startPhase + 1;
|
|
@@ -4157,11 +4169,11 @@ async function next(options2, startId) {
|
|
|
4157
4169
|
let pendingId = startId;
|
|
4158
4170
|
let firstPick = true;
|
|
4159
4171
|
while (true) {
|
|
4160
|
-
const
|
|
4172
|
+
const id2 = pendingId ?? await pickItem(await loadBacklog(), firstPick);
|
|
4161
4173
|
pendingId = void 0;
|
|
4162
4174
|
firstPick = false;
|
|
4163
|
-
if (
|
|
4164
|
-
const completed = await run2(
|
|
4175
|
+
if (id2 === void 0) return;
|
|
4176
|
+
const completed = await run2(id2, options2);
|
|
4165
4177
|
if (!completed || options2?.once) return;
|
|
4166
4178
|
}
|
|
4167
4179
|
}
|
|
@@ -4184,16 +4196,16 @@ async function appendComment(orm, itemId, text3, opts = {}) {
|
|
|
4184
4196
|
|
|
4185
4197
|
// src/commands/backlog/getItemStatus.ts
|
|
4186
4198
|
import { eq as eq9 } from "drizzle-orm";
|
|
4187
|
-
async function getItemStatus(orm,
|
|
4188
|
-
const [row] = await orm.select({ status: items.status }).from(items).where(eq9(items.id,
|
|
4199
|
+
async function getItemStatus(orm, id2) {
|
|
4200
|
+
const [row] = await orm.select({ status: items.status }).from(items).where(eq9(items.id, id2));
|
|
4189
4201
|
return row?.status;
|
|
4190
4202
|
}
|
|
4191
4203
|
|
|
4192
4204
|
// src/commands/backlog/phaseDone.ts
|
|
4193
|
-
async function phaseDone(
|
|
4205
|
+
async function phaseDone(id2, phase, summary) {
|
|
4194
4206
|
const phaseNumber = Number.parseInt(phase, 10);
|
|
4195
4207
|
const phaseIndex = phaseNumber - 1;
|
|
4196
|
-
const itemId = Number.parseInt(
|
|
4208
|
+
const itemId = Number.parseInt(id2, 10);
|
|
4197
4209
|
writeSignal("phase-done", {
|
|
4198
4210
|
itemId,
|
|
4199
4211
|
phaseIndex,
|
|
@@ -4202,27 +4214,27 @@ async function phaseDone(id, phase, summary) {
|
|
|
4202
4214
|
const { orm } = await getReady();
|
|
4203
4215
|
const status2 = await getItemStatus(orm, itemId);
|
|
4204
4216
|
if (status2 === void 0) {
|
|
4205
|
-
console.log(chalk37.red(`Item #${
|
|
4217
|
+
console.log(chalk37.red(`Item #${id2} not found.`));
|
|
4206
4218
|
return;
|
|
4207
4219
|
}
|
|
4208
4220
|
if (status2 === "done") {
|
|
4209
|
-
console.log(chalk37.dim(`Item #${
|
|
4221
|
+
console.log(chalk37.dim(`Item #${id2} already done, skipping phase advance.`));
|
|
4210
4222
|
return;
|
|
4211
4223
|
}
|
|
4212
4224
|
await appendComment(orm, itemId, summary, {
|
|
4213
4225
|
phase: phaseNumber,
|
|
4214
4226
|
type: "summary"
|
|
4215
4227
|
});
|
|
4216
|
-
await setCurrentPhase(
|
|
4228
|
+
await setCurrentPhase(id2, phaseNumber + 1);
|
|
4217
4229
|
console.log(
|
|
4218
|
-
chalk37.green(`Phase ${phaseNumber} of item #${
|
|
4230
|
+
chalk37.green(`Phase ${phaseNumber} of item #${id2} marked as complete.`)
|
|
4219
4231
|
);
|
|
4220
4232
|
}
|
|
4221
4233
|
|
|
4222
4234
|
// src/commands/backlog/plan.ts
|
|
4223
4235
|
import chalk38 from "chalk";
|
|
4224
|
-
async function plan(
|
|
4225
|
-
const found = await findOneItem(
|
|
4236
|
+
async function plan(id2) {
|
|
4237
|
+
const found = await findOneItem(id2);
|
|
4226
4238
|
if (!found) return;
|
|
4227
4239
|
const { item } = found;
|
|
4228
4240
|
if (!item.plan || item.plan.length === 0) {
|
|
@@ -4246,11 +4258,11 @@ import chalk42 from "chalk";
|
|
|
4246
4258
|
// src/commands/backlog/formatComment.ts
|
|
4247
4259
|
import chalk39 from "chalk";
|
|
4248
4260
|
function formatComment(entry) {
|
|
4249
|
-
const
|
|
4261
|
+
const id2 = entry.id !== void 0 ? chalk39.dim(`#${entry.id} `) : "";
|
|
4250
4262
|
const tag = entry.type === "summary" ? chalk39.magenta("[summary]") : chalk39.cyan("[comment]");
|
|
4251
4263
|
const phase = entry.phase !== void 0 ? chalk39.dim(` (phase ${entry.phase})`) : "";
|
|
4252
4264
|
const time = chalk39.dim(entry.timestamp);
|
|
4253
|
-
return `${
|
|
4265
|
+
return `${id2}${tag}${phase} ${time}
|
|
4254
4266
|
${entry.text}`;
|
|
4255
4267
|
}
|
|
4256
4268
|
|
|
@@ -4343,8 +4355,8 @@ function printAcceptanceCriteria(criteria) {
|
|
|
4343
4355
|
}
|
|
4344
4356
|
console.log();
|
|
4345
4357
|
}
|
|
4346
|
-
async function show(
|
|
4347
|
-
const found = await findOneItem(
|
|
4358
|
+
async function show(id2) {
|
|
4359
|
+
const found = await findOneItem(id2);
|
|
4348
4360
|
if (!found) process.exit(1);
|
|
4349
4361
|
const { orm, item } = found;
|
|
4350
4362
|
printHeader(item);
|
|
@@ -4457,10 +4469,10 @@ function parseRoute(req, port) {
|
|
|
4457
4469
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
4458
4470
|
return { method: req.method ?? "GET", pathname: url.pathname };
|
|
4459
4471
|
}
|
|
4460
|
-
function createRouteHandler(
|
|
4472
|
+
function createRouteHandler(routes3) {
|
|
4461
4473
|
return async (req, res, port) => {
|
|
4462
4474
|
const { method, pathname } = parseRoute(req, port);
|
|
4463
|
-
const handler =
|
|
4475
|
+
const handler = routes3[`${method} ${pathname}`];
|
|
4464
4476
|
if (handler) {
|
|
4465
4477
|
await handler(req, res);
|
|
4466
4478
|
return;
|
|
@@ -4622,12 +4634,12 @@ function createBundleHandler(importMetaUrl, bundlePath) {
|
|
|
4622
4634
|
}
|
|
4623
4635
|
|
|
4624
4636
|
// src/shared/createFallbackHandler.ts
|
|
4625
|
-
function createFallbackHandler(
|
|
4626
|
-
const baseHandler = createRouteHandler(
|
|
4637
|
+
function createFallbackHandler(routes3, htmlHandler2, extra) {
|
|
4638
|
+
const baseHandler = createRouteHandler(routes3);
|
|
4627
4639
|
return async (req, res, port) => {
|
|
4628
4640
|
const { method, pathname } = parseRoute(req, port);
|
|
4629
4641
|
if (extra && await extra(req, res, pathname)) return;
|
|
4630
|
-
if (
|
|
4642
|
+
if (routes3[`${method} ${pathname}`]) {
|
|
4631
4643
|
await baseHandler(req, res, port);
|
|
4632
4644
|
return;
|
|
4633
4645
|
}
|
|
@@ -4650,14 +4662,16 @@ async function loadItemSummaries(orm, origin) {
|
|
|
4650
4662
|
origin: items.origin,
|
|
4651
4663
|
type: items.type,
|
|
4652
4664
|
name: items.name,
|
|
4653
|
-
status: items.status
|
|
4665
|
+
status: items.status,
|
|
4666
|
+
starred: items.starred
|
|
4654
4667
|
}).from(items).where(origin === void 0 ? void 0 : eq10(items.origin, origin)).orderBy(asc5(items.id));
|
|
4655
4668
|
return rows.map((row) => ({
|
|
4656
4669
|
id: row.id,
|
|
4657
4670
|
origin: row.origin,
|
|
4658
4671
|
type: row.type,
|
|
4659
4672
|
name: row.name,
|
|
4660
|
-
status: row.status
|
|
4673
|
+
status: row.status,
|
|
4674
|
+
starred: row.starred
|
|
4661
4675
|
}));
|
|
4662
4676
|
}
|
|
4663
4677
|
|
|
@@ -4691,8 +4705,32 @@ async function getBacklogExists(req, res) {
|
|
|
4691
4705
|
respondJson(res, 200, { exists: await backlogHasItems() });
|
|
4692
4706
|
}
|
|
4693
4707
|
|
|
4694
|
-
// src/commands/backlog/
|
|
4708
|
+
// src/commands/backlog/deleteComment.ts
|
|
4709
|
+
import { and as and2, eq as eq12 } from "drizzle-orm";
|
|
4710
|
+
async function deleteComment(orm, itemId, commentId) {
|
|
4711
|
+
const [row] = await orm.select({ type: comments.type }).from(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
|
|
4712
|
+
if (!row) return "not-found";
|
|
4713
|
+
if (row.type === "summary") return "is-summary";
|
|
4714
|
+
await orm.delete(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
|
|
4715
|
+
return "deleted";
|
|
4716
|
+
}
|
|
4717
|
+
|
|
4718
|
+
// src/commands/backlog/updateStarred.ts
|
|
4695
4719
|
import { eq as eq13 } from "drizzle-orm";
|
|
4720
|
+
async function updateStarred(orm, id2, starred) {
|
|
4721
|
+
const [row] = await orm.update(items).set({ starred }).where(eq13(items.id, id2)).returning({ name: items.name });
|
|
4722
|
+
return row?.name;
|
|
4723
|
+
}
|
|
4724
|
+
|
|
4725
|
+
// src/commands/backlog/web/loadVisibleItems.ts
|
|
4726
|
+
var completedStatuses = /* @__PURE__ */ new Set(["done", "wontdo"]);
|
|
4727
|
+
async function loadVisibleItems(req) {
|
|
4728
|
+
const params = new URL(req.url ?? "/", "http://localhost").searchParams;
|
|
4729
|
+
const q = params.get("q");
|
|
4730
|
+
const loaded = q ? await searchBacklogSummaries(q) : await loadBacklogSummaries();
|
|
4731
|
+
if (params.get("showCompleted") === "true") return loaded;
|
|
4732
|
+
return loaded.filter((item) => !completedStatuses.has(item.status));
|
|
4733
|
+
}
|
|
4696
4734
|
|
|
4697
4735
|
// src/commands/backlog/web/parseItemBody.ts
|
|
4698
4736
|
function readBody(req) {
|
|
@@ -4714,25 +4752,8 @@ async function parseStatusBody(req) {
|
|
|
4714
4752
|
async function parseRewindBody(req) {
|
|
4715
4753
|
return JSON.parse(await readBody(req));
|
|
4716
4754
|
}
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
import { and as and2, eq as eq12 } from "drizzle-orm";
|
|
4720
|
-
async function deleteComment(orm, itemId, commentId) {
|
|
4721
|
-
const [row] = await orm.select({ type: comments.type }).from(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
|
|
4722
|
-
if (!row) return "not-found";
|
|
4723
|
-
if (row.type === "summary") return "is-summary";
|
|
4724
|
-
await orm.delete(comments).where(and2(eq12(comments.id, commentId), eq12(comments.itemId, itemId)));
|
|
4725
|
-
return "deleted";
|
|
4726
|
-
}
|
|
4727
|
-
|
|
4728
|
-
// src/commands/backlog/web/loadVisibleItems.ts
|
|
4729
|
-
var completedStatuses = /* @__PURE__ */ new Set(["done", "wontdo"]);
|
|
4730
|
-
async function loadVisibleItems(req) {
|
|
4731
|
-
const params = new URL(req.url ?? "/", "http://localhost").searchParams;
|
|
4732
|
-
const q = params.get("q");
|
|
4733
|
-
const loaded = q ? await searchBacklogSummaries(q) : await loadBacklogSummaries();
|
|
4734
|
-
if (params.get("showCompleted") === "true") return loaded;
|
|
4735
|
-
return loaded.filter((item) => !completedStatuses.has(item.status));
|
|
4755
|
+
async function parseStarBody(req) {
|
|
4756
|
+
return JSON.parse(await readBody(req));
|
|
4736
4757
|
}
|
|
4737
4758
|
|
|
4738
4759
|
// src/commands/backlog/web/shared.ts
|
|
@@ -4741,25 +4762,43 @@ async function listItems(req, res) {
|
|
|
4741
4762
|
const items2 = await loadVisibleItems(req);
|
|
4742
4763
|
respondJson(res, 200, items2.slice().reverse());
|
|
4743
4764
|
}
|
|
4744
|
-
async function findItemOr404(res,
|
|
4765
|
+
async function findItemOr404(res, id2) {
|
|
4745
4766
|
const { orm } = await getReady();
|
|
4746
|
-
const item = await loadItem(orm,
|
|
4767
|
+
const item = await loadItem(orm, id2);
|
|
4747
4768
|
if (!item) {
|
|
4748
4769
|
respondJson(res, 404, { error: "Not found" });
|
|
4749
4770
|
return void 0;
|
|
4750
4771
|
}
|
|
4751
4772
|
return { orm, item };
|
|
4752
4773
|
}
|
|
4753
|
-
async function getItemById(res,
|
|
4754
|
-
const result = await findItemOr404(res,
|
|
4774
|
+
async function getItemById(res, id2) {
|
|
4775
|
+
const result = await findItemOr404(res, id2);
|
|
4755
4776
|
if (result) respondJson(res, 200, result.item);
|
|
4756
4777
|
}
|
|
4757
|
-
async function deleteItem2(res,
|
|
4758
|
-
const result = await findItemOr404(res,
|
|
4778
|
+
async function deleteItem2(res, id2) {
|
|
4779
|
+
const result = await findItemOr404(res, id2);
|
|
4759
4780
|
if (!result) return;
|
|
4760
|
-
await deleteItem(result.orm,
|
|
4781
|
+
await deleteItem(result.orm, id2);
|
|
4761
4782
|
respondJson(res, 200, result.item);
|
|
4762
4783
|
}
|
|
4784
|
+
async function patchItemStatus(req, res, id2) {
|
|
4785
|
+
const { status: status2 } = await parseStatusBody(req);
|
|
4786
|
+
const result = await findItemOr404(res, id2);
|
|
4787
|
+
if (!result) return;
|
|
4788
|
+
await updateStatus(result.orm, id2, status2);
|
|
4789
|
+
const updated = { ...result.item, status: status2 };
|
|
4790
|
+
respondJson(res, 200, updated);
|
|
4791
|
+
}
|
|
4792
|
+
async function patchItemStar(req, res, id2) {
|
|
4793
|
+
const { starred } = await parseStarBody(req);
|
|
4794
|
+
const result = await findItemOr404(res, id2);
|
|
4795
|
+
if (!result) return;
|
|
4796
|
+
await updateStarred(result.orm, id2, starred);
|
|
4797
|
+
const updated = { ...result.item, starred };
|
|
4798
|
+
respondJson(res, 200, updated);
|
|
4799
|
+
}
|
|
4800
|
+
|
|
4801
|
+
// src/commands/backlog/web/deleteItemComment.ts
|
|
4763
4802
|
async function deleteItemComment(res, itemId, commentId) {
|
|
4764
4803
|
const result = await findItemOr404(res, itemId);
|
|
4765
4804
|
if (!result) return;
|
|
@@ -4778,19 +4817,12 @@ async function deleteItemComment(res, itemId, commentId) {
|
|
|
4778
4817
|
}
|
|
4779
4818
|
respondJson(res, 200, await loadItem(result.orm, itemId));
|
|
4780
4819
|
}
|
|
4781
|
-
async function patchItemStatus(req, res, id) {
|
|
4782
|
-
const { status: status2 } = await parseStatusBody(req);
|
|
4783
|
-
const result = await findItemOr404(res, id);
|
|
4784
|
-
if (!result) return;
|
|
4785
|
-
await updateStatus(result.orm, id, status2);
|
|
4786
|
-
const updated = { ...result.item, status: status2 };
|
|
4787
|
-
respondJson(res, 200, updated);
|
|
4788
|
-
}
|
|
4789
4820
|
|
|
4790
4821
|
// src/commands/backlog/web/rewindItemPhase.ts
|
|
4791
|
-
|
|
4822
|
+
import { eq as eq14 } from "drizzle-orm";
|
|
4823
|
+
async function rewindItemPhase(req, res, id2) {
|
|
4792
4824
|
const { phase, reason } = await parseRewindBody(req);
|
|
4793
|
-
const result = await findItemOr404(res,
|
|
4825
|
+
const result = await findItemOr404(res, id2);
|
|
4794
4826
|
if (!result) return;
|
|
4795
4827
|
const { orm, item } = result;
|
|
4796
4828
|
const error = validateRewind(item, phase);
|
|
@@ -4801,12 +4833,12 @@ async function rewindItemPhase(req, res, id) {
|
|
|
4801
4833
|
const phaseName = item.plan?.[phase - 1].name;
|
|
4802
4834
|
await appendComment(
|
|
4803
4835
|
orm,
|
|
4804
|
-
|
|
4836
|
+
id2,
|
|
4805
4837
|
`Rewound to phase ${phase} (${phaseName}): ${reason}`,
|
|
4806
4838
|
{ phase }
|
|
4807
4839
|
);
|
|
4808
|
-
await orm.update(items).set({ currentPhase: phase, status: "in-progress" }).where(
|
|
4809
|
-
respondJson(res, 200, await loadItem(orm,
|
|
4840
|
+
await orm.update(items).set({ currentPhase: phase, status: "in-progress" }).where(eq14(items.id, id2));
|
|
4841
|
+
respondJson(res, 200, await loadItem(orm, id2));
|
|
4810
4842
|
}
|
|
4811
4843
|
function validateRewind(item, phase) {
|
|
4812
4844
|
if (!item.plan || item.plan.length === 0) {
|
|
@@ -4823,10 +4855,10 @@ function validateRewind(item, phase) {
|
|
|
4823
4855
|
}
|
|
4824
4856
|
|
|
4825
4857
|
// src/commands/backlog/web/updateItem.ts
|
|
4826
|
-
import { eq as
|
|
4827
|
-
async function updateItem(req, res,
|
|
4858
|
+
import { eq as eq15 } from "drizzle-orm";
|
|
4859
|
+
async function updateItem(req, res, id2) {
|
|
4828
4860
|
const body = await parseItemBody(req);
|
|
4829
|
-
const result = await findItemOr404(res,
|
|
4861
|
+
const result = await findItemOr404(res, id2);
|
|
4830
4862
|
if (!result) return;
|
|
4831
4863
|
const { orm } = result;
|
|
4832
4864
|
await orm.update(items).set({
|
|
@@ -4834,41 +4866,59 @@ async function updateItem(req, res, id) {
|
|
|
4834
4866
|
name: body.name,
|
|
4835
4867
|
description: body.description ?? null,
|
|
4836
4868
|
acceptanceCriteria: JSON.stringify(body.acceptanceCriteria ?? [])
|
|
4837
|
-
}).where(
|
|
4838
|
-
respondJson(res, 200, await loadItem(orm,
|
|
4869
|
+
}).where(eq15(items.id, id2));
|
|
4870
|
+
respondJson(res, 200, await loadItem(orm, id2));
|
|
4839
4871
|
}
|
|
4840
4872
|
|
|
4841
4873
|
// src/commands/backlog/web/handleItemRoute.ts
|
|
4842
|
-
var
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4874
|
+
var id = (match, group = 1) => Number.parseInt(match[group], 10);
|
|
4875
|
+
var routes = [
|
|
4876
|
+
{
|
|
4877
|
+
pattern: /^\/api\/items\/(\d+)\/rewind$/,
|
|
4878
|
+
method: "POST",
|
|
4879
|
+
run: (req, res, m) => rewindItemPhase(req, res, id(m))
|
|
4880
|
+
},
|
|
4881
|
+
{
|
|
4882
|
+
pattern: /^\/api\/items\/(\d+)\/star$/,
|
|
4883
|
+
method: "POST",
|
|
4884
|
+
run: (req, res, m) => patchItemStar(req, res, id(m))
|
|
4885
|
+
},
|
|
4886
|
+
{
|
|
4887
|
+
pattern: /^\/api\/items\/(\d+)\/comments\/(\d+)$/,
|
|
4888
|
+
method: "DELETE",
|
|
4889
|
+
run: (_req, res, m) => deleteItemComment(res, id(m), id(m, 2))
|
|
4890
|
+
},
|
|
4891
|
+
{
|
|
4892
|
+
pattern: /^\/api\/items\/(\d+)$/,
|
|
4893
|
+
method: "GET",
|
|
4894
|
+
run: (_req, res, m) => getItemById(res, id(m))
|
|
4895
|
+
},
|
|
4896
|
+
{
|
|
4897
|
+
pattern: /^\/api\/items\/(\d+)$/,
|
|
4898
|
+
method: "PUT",
|
|
4899
|
+
run: (req, res, m) => updateItem(req, res, id(m))
|
|
4900
|
+
},
|
|
4901
|
+
{
|
|
4902
|
+
pattern: /^\/api\/items\/(\d+)$/,
|
|
4903
|
+
method: "PATCH",
|
|
4904
|
+
run: (req, res, m) => patchItemStatus(req, res, id(m))
|
|
4905
|
+
},
|
|
4906
|
+
{
|
|
4907
|
+
pattern: /^\/api\/items\/(\d+)$/,
|
|
4908
|
+
method: "DELETE",
|
|
4909
|
+
run: (_req, res, m) => deleteItem2(res, id(m))
|
|
4854
4910
|
}
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4911
|
+
];
|
|
4912
|
+
async function handleItemRoute(req, res, pathname) {
|
|
4913
|
+
for (const route of routes) {
|
|
4914
|
+
const match = pathname.match(route.pattern);
|
|
4915
|
+
if (match && req.method === route.method) {
|
|
4916
|
+
applyCwdFromReq(req);
|
|
4917
|
+
await route.run(req, res, match);
|
|
4918
|
+
return true;
|
|
4919
|
+
}
|
|
4864
4920
|
}
|
|
4865
|
-
|
|
4866
|
-
if (!match) return false;
|
|
4867
|
-
const handler = itemRoutes[req.method ?? "GET"];
|
|
4868
|
-
if (!handler) return false;
|
|
4869
|
-
applyCwdFromReq(req);
|
|
4870
|
-
await handler(req, res, Number.parseInt(match[1], 10));
|
|
4871
|
-
return true;
|
|
4921
|
+
return false;
|
|
4872
4922
|
}
|
|
4873
4923
|
|
|
4874
4924
|
// src/commands/backlog/init/index.ts
|
|
@@ -5308,7 +5358,7 @@ function createCssHandler(packageEntry) {
|
|
|
5308
5358
|
};
|
|
5309
5359
|
}
|
|
5310
5360
|
var htmlHandler = createHtmlHandler(getHtml);
|
|
5311
|
-
var
|
|
5361
|
+
var routes2 = {
|
|
5312
5362
|
"GET /": htmlHandler,
|
|
5313
5363
|
"GET /bundle.js": createBundleHandler(
|
|
5314
5364
|
import.meta.url,
|
|
@@ -5325,7 +5375,7 @@ var routes = {
|
|
|
5325
5375
|
"GET /api/news/items": listNewsItems
|
|
5326
5376
|
};
|
|
5327
5377
|
var handleRequest = createFallbackHandler(
|
|
5328
|
-
|
|
5378
|
+
routes2,
|
|
5329
5379
|
htmlHandler,
|
|
5330
5380
|
handleItemRoute
|
|
5331
5381
|
);
|
|
@@ -5335,14 +5385,14 @@ import { createInterface as createInterface2 } from "readline";
|
|
|
5335
5385
|
|
|
5336
5386
|
// src/commands/sessions/daemon/toWindowsSessionId.ts
|
|
5337
5387
|
var PREFIX = "w-";
|
|
5338
|
-
function toWindowsSessionId(
|
|
5339
|
-
return `${PREFIX}${
|
|
5388
|
+
function toWindowsSessionId(id2) {
|
|
5389
|
+
return `${PREFIX}${id2}`;
|
|
5340
5390
|
}
|
|
5341
|
-
function isWindowsSessionId(
|
|
5342
|
-
return
|
|
5391
|
+
function isWindowsSessionId(id2) {
|
|
5392
|
+
return id2.startsWith(PREFIX);
|
|
5343
5393
|
}
|
|
5344
|
-
function stripWindowsSessionId(
|
|
5345
|
-
return
|
|
5394
|
+
function stripWindowsSessionId(id2) {
|
|
5395
|
+
return id2.startsWith(PREFIX) ? id2.slice(PREFIX.length) : id2;
|
|
5346
5396
|
}
|
|
5347
5397
|
|
|
5348
5398
|
// src/commands/sessions/web/ui/repoLabel.ts
|
|
@@ -5378,9 +5428,9 @@ function applySnapshot(known, sessions) {
|
|
|
5378
5428
|
if (previous === void 0) logEvent("started", session);
|
|
5379
5429
|
else if (isDone(session) && !isDone(previous)) logEvent("ended", session);
|
|
5380
5430
|
}
|
|
5381
|
-
for (const [
|
|
5382
|
-
if (present.has(
|
|
5383
|
-
known.delete(
|
|
5431
|
+
for (const [id2, session] of [...known]) {
|
|
5432
|
+
if (present.has(id2)) continue;
|
|
5433
|
+
known.delete(id2);
|
|
5384
5434
|
if (!isDone(session)) logEvent("ended", session);
|
|
5385
5435
|
}
|
|
5386
5436
|
}
|
|
@@ -5736,25 +5786,25 @@ async function web2(options2) {
|
|
|
5736
5786
|
|
|
5737
5787
|
// src/commands/backlog/comment/index.ts
|
|
5738
5788
|
import chalk48 from "chalk";
|
|
5739
|
-
async function comment(
|
|
5740
|
-
const found = await findOneItem(
|
|
5789
|
+
async function comment(id2, text3) {
|
|
5790
|
+
const found = await findOneItem(id2);
|
|
5741
5791
|
if (!found) process.exit(1);
|
|
5742
5792
|
await appendComment(found.orm, found.item.id, text3);
|
|
5743
|
-
console.log(chalk48.green(`Comment added to item #${
|
|
5793
|
+
console.log(chalk48.green(`Comment added to item #${id2}.`));
|
|
5744
5794
|
}
|
|
5745
5795
|
|
|
5746
5796
|
// src/commands/backlog/comments/index.ts
|
|
5747
5797
|
import chalk49 from "chalk";
|
|
5748
|
-
async function comments2(
|
|
5749
|
-
const found = await findOneItem(
|
|
5798
|
+
async function comments2(id2) {
|
|
5799
|
+
const found = await findOneItem(id2);
|
|
5750
5800
|
if (!found) process.exit(1);
|
|
5751
5801
|
const { item } = found;
|
|
5752
5802
|
const entries = item.comments ?? [];
|
|
5753
5803
|
if (entries.length === 0) {
|
|
5754
|
-
console.log(chalk49.dim(`No comments on item #${
|
|
5804
|
+
console.log(chalk49.dim(`No comments on item #${id2}.`));
|
|
5755
5805
|
return;
|
|
5756
5806
|
}
|
|
5757
|
-
console.log(chalk49.bold(`Comments for #${
|
|
5807
|
+
console.log(chalk49.bold(`Comments for #${id2}: ${item.name}
|
|
5758
5808
|
`));
|
|
5759
5809
|
for (const entry of entries) {
|
|
5760
5810
|
console.log(`${formatComment(entry)}
|
|
@@ -5764,8 +5814,8 @@ async function comments2(id) {
|
|
|
5764
5814
|
|
|
5765
5815
|
// src/commands/backlog/delete-comment/index.ts
|
|
5766
5816
|
import chalk50 from "chalk";
|
|
5767
|
-
async function deleteCommentCmd(
|
|
5768
|
-
const found = await findOneItem(
|
|
5817
|
+
async function deleteCommentCmd(id2, commentId) {
|
|
5818
|
+
const found = await findOneItem(id2);
|
|
5769
5819
|
if (!found) process.exit(1);
|
|
5770
5820
|
const outcome = await deleteComment(
|
|
5771
5821
|
found.orm,
|
|
@@ -5775,11 +5825,11 @@ async function deleteCommentCmd(id, commentId) {
|
|
|
5775
5825
|
switch (outcome) {
|
|
5776
5826
|
case "deleted":
|
|
5777
5827
|
console.log(
|
|
5778
|
-
chalk50.green(`Comment #${commentId} deleted from item #${
|
|
5828
|
+
chalk50.green(`Comment #${commentId} deleted from item #${id2}.`)
|
|
5779
5829
|
);
|
|
5780
5830
|
break;
|
|
5781
5831
|
case "not-found":
|
|
5782
|
-
console.log(chalk50.red(`Comment #${commentId} not found on item #${
|
|
5832
|
+
console.log(chalk50.red(`Comment #${commentId} not found on item #${id2}.`));
|
|
5783
5833
|
process.exit(1);
|
|
5784
5834
|
break;
|
|
5785
5835
|
case "is-summary":
|
|
@@ -6151,40 +6201,41 @@ async function add(options2) {
|
|
|
6151
6201
|
const description = options2.desc?.replaceAll("\\n", "\n") ?? await promptDescription();
|
|
6152
6202
|
const acceptanceCriteria2 = options2.ac ?? await promptAcceptanceCriteria();
|
|
6153
6203
|
const orm = await getBacklogOrm();
|
|
6154
|
-
const
|
|
6204
|
+
const id2 = await insertItem(
|
|
6155
6205
|
orm,
|
|
6156
6206
|
{
|
|
6157
6207
|
type,
|
|
6158
6208
|
name,
|
|
6159
6209
|
description: description || void 0,
|
|
6160
6210
|
acceptanceCriteria: acceptanceCriteria2,
|
|
6161
|
-
status: "todo"
|
|
6211
|
+
status: "todo",
|
|
6212
|
+
starred: false
|
|
6162
6213
|
},
|
|
6163
6214
|
getOrigin()
|
|
6164
6215
|
);
|
|
6165
|
-
console.log(chalk54.green(`Added item #${
|
|
6216
|
+
console.log(chalk54.green(`Added item #${id2}: ${name}`));
|
|
6166
6217
|
}
|
|
6167
6218
|
|
|
6168
6219
|
// src/commands/backlog/addPhase.ts
|
|
6169
6220
|
import chalk56 from "chalk";
|
|
6170
6221
|
|
|
6171
6222
|
// src/commands/backlog/insertPhaseAt.ts
|
|
6172
|
-
import { count, eq as
|
|
6223
|
+
import { count, eq as eq17 } from "drizzle-orm";
|
|
6173
6224
|
|
|
6174
6225
|
// src/commands/backlog/shiftPhasesUp.ts
|
|
6175
|
-
import { and as and3, desc, eq as
|
|
6226
|
+
import { and as and3, desc, eq as eq16, gte } from "drizzle-orm";
|
|
6176
6227
|
async function shiftPhasesUp(db, itemId, fromIdx) {
|
|
6177
|
-
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(
|
|
6228
|
+
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and3(eq16(planPhases.itemId, itemId), gte(planPhases.idx, fromIdx))).orderBy(desc(planPhases.idx));
|
|
6178
6229
|
for (const p of toShift) {
|
|
6179
|
-
await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and3(
|
|
6180
|
-
await db.update(planPhases).set({ idx: p.idx + 1 }).where(and3(
|
|
6230
|
+
await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and3(eq16(planTasks.itemId, itemId), eq16(planTasks.phaseIdx, p.idx)));
|
|
6231
|
+
await db.update(planPhases).set({ idx: p.idx + 1 }).where(and3(eq16(planPhases.itemId, itemId), eq16(planPhases.idx, p.idx)));
|
|
6181
6232
|
}
|
|
6182
6233
|
}
|
|
6183
6234
|
|
|
6184
6235
|
// src/commands/backlog/insertPhaseAt.ts
|
|
6185
6236
|
async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, currentPhase) {
|
|
6186
6237
|
await orm.transaction(async (tx) => {
|
|
6187
|
-
const [row] = await tx.select({ cnt: count() }).from(planPhases).where(
|
|
6238
|
+
const [row] = await tx.select({ cnt: count() }).from(planPhases).where(eq17(planPhases.itemId, itemId));
|
|
6188
6239
|
const phaseCount = row?.cnt ?? 0;
|
|
6189
6240
|
await shiftPhasesUp(tx, itemId, phaseIdx);
|
|
6190
6241
|
await tx.insert(planPhases).values({ itemId, idx: phaseIdx, name, manualChecks });
|
|
@@ -6193,16 +6244,16 @@ async function insertPhaseAt(orm, itemId, phaseIdx, name, tasks, manualChecks, c
|
|
|
6193
6244
|
}
|
|
6194
6245
|
if (currentPhase !== void 0 && currentPhase - 1 >= phaseIdx) {
|
|
6195
6246
|
const atReviewSlot = currentPhase - 1 >= phaseCount;
|
|
6196
|
-
await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(
|
|
6247
|
+
await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(eq17(items.id, itemId));
|
|
6197
6248
|
}
|
|
6198
6249
|
});
|
|
6199
6250
|
}
|
|
6200
6251
|
|
|
6201
6252
|
// src/commands/backlog/resolveInsertPosition.ts
|
|
6202
6253
|
import chalk55 from "chalk";
|
|
6203
|
-
import { count as count2, eq as
|
|
6254
|
+
import { count as count2, eq as eq18 } from "drizzle-orm";
|
|
6204
6255
|
async function resolveInsertPosition(orm, itemId, position) {
|
|
6205
|
-
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(
|
|
6256
|
+
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(eq18(planPhases.itemId, itemId));
|
|
6206
6257
|
const phaseCount = row?.cnt ?? 0;
|
|
6207
6258
|
if (position === void 0) return phaseCount;
|
|
6208
6259
|
const pos = Number.parseInt(position, 10);
|
|
@@ -6224,8 +6275,8 @@ function serializeManualChecks(manualCheck) {
|
|
|
6224
6275
|
}
|
|
6225
6276
|
|
|
6226
6277
|
// src/commands/backlog/addPhase.ts
|
|
6227
|
-
async function addPhase(
|
|
6228
|
-
const found = await findOneItem(
|
|
6278
|
+
async function addPhase(id2, name, options2) {
|
|
6279
|
+
const found = await findOneItem(id2);
|
|
6229
6280
|
if (!found) return;
|
|
6230
6281
|
const tasks = options2.task ?? [];
|
|
6231
6282
|
if (tasks.length === 0) {
|
|
@@ -6318,7 +6369,7 @@ async function list2(options2) {
|
|
|
6318
6369
|
for (const item of items2) {
|
|
6319
6370
|
const repoPrefix = options2.allRepos ? `${chalk57.dim(repoNameOf(item).padEnd(prefixWidth))} ` : "";
|
|
6320
6371
|
console.log(
|
|
6321
|
-
`${repoPrefix}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk57.dim(`#${item.id}`)} ${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
6372
|
+
`${repoPrefix}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk57.dim(`#${item.id}`)} ${starMarker(item)}${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
6322
6373
|
);
|
|
6323
6374
|
if (options2.verbose) {
|
|
6324
6375
|
printVerboseDetails(item);
|
|
@@ -6363,9 +6414,9 @@ function hasCycle(adjacency, fromId, toId) {
|
|
|
6363
6414
|
}
|
|
6364
6415
|
|
|
6365
6416
|
// src/commands/backlog/loadDependencyGraph.ts
|
|
6366
|
-
import { eq as
|
|
6417
|
+
import { eq as eq19 } from "drizzle-orm";
|
|
6367
6418
|
async function loadDependencyGraph(orm) {
|
|
6368
|
-
const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(
|
|
6419
|
+
const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq19(links.type, "depends-on"));
|
|
6369
6420
|
const graph = /* @__PURE__ */ new Map();
|
|
6370
6421
|
for (const { itemId, targetId } of rows) {
|
|
6371
6422
|
const bucket = graph.get(itemId);
|
|
@@ -6428,7 +6479,7 @@ async function link(fromId, toId, opts) {
|
|
|
6428
6479
|
|
|
6429
6480
|
// src/commands/backlog/unlink.ts
|
|
6430
6481
|
import chalk60 from "chalk";
|
|
6431
|
-
import { and as and4, eq as
|
|
6482
|
+
import { and as and4, eq as eq20 } from "drizzle-orm";
|
|
6432
6483
|
async function unlink(fromId, toId) {
|
|
6433
6484
|
const fromNum = Number.parseInt(fromId, 10);
|
|
6434
6485
|
const toNum = Number.parseInt(toId, 10);
|
|
@@ -6446,7 +6497,7 @@ async function unlink(fromId, toId) {
|
|
|
6446
6497
|
console.log(chalk60.yellow(`No link from #${fromId} to #${toId} found.`));
|
|
6447
6498
|
return;
|
|
6448
6499
|
}
|
|
6449
|
-
await orm.delete(links).where(and4(
|
|
6500
|
+
await orm.delete(links).where(and4(eq20(links.itemId, fromNum), eq20(links.targetId, toNum)));
|
|
6450
6501
|
console.log(chalk60.green(`Removed link from #${fromId} to #${toId}.`));
|
|
6451
6502
|
}
|
|
6452
6503
|
|
|
@@ -6462,7 +6513,7 @@ function registerLinkCommands(cmd) {
|
|
|
6462
6513
|
|
|
6463
6514
|
// src/commands/backlog/move-repo/index.ts
|
|
6464
6515
|
import chalk62 from "chalk";
|
|
6465
|
-
import { eq as
|
|
6516
|
+
import { eq as eq22 } from "drizzle-orm";
|
|
6466
6517
|
|
|
6467
6518
|
// src/commands/backlog/move-repo/confirmMove.ts
|
|
6468
6519
|
import chalk61 from "chalk";
|
|
@@ -6477,9 +6528,9 @@ async function confirmMove(cnt, oldOrigin, newOrigin) {
|
|
|
6477
6528
|
}
|
|
6478
6529
|
|
|
6479
6530
|
// src/commands/backlog/move-repo/countByOrigin.ts
|
|
6480
|
-
import { count as count3, eq as
|
|
6531
|
+
import { count as count3, eq as eq21 } from "drizzle-orm";
|
|
6481
6532
|
async function countByOrigin(orm, origin) {
|
|
6482
|
-
const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(
|
|
6533
|
+
const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(eq21(items.origin, origin));
|
|
6483
6534
|
return cnt;
|
|
6484
6535
|
}
|
|
6485
6536
|
|
|
@@ -6522,7 +6573,7 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
|
|
|
6522
6573
|
console.log(chalk62.yellow("Move cancelled; no changes made."));
|
|
6523
6574
|
return;
|
|
6524
6575
|
}
|
|
6525
|
-
await orm.update(items).set({ origin: newOrigin }).where(
|
|
6576
|
+
await orm.update(items).set({ origin: newOrigin }).where(eq22(items.origin, oldOrigin));
|
|
6526
6577
|
console.log(
|
|
6527
6578
|
chalk62.green(
|
|
6528
6579
|
`Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
|
|
@@ -6542,7 +6593,7 @@ function registerMoveRepoCommand(cmd) {
|
|
|
6542
6593
|
// src/commands/backlog/registerNextCommand.ts
|
|
6543
6594
|
function registerNextCommand(cmd) {
|
|
6544
6595
|
cmd.command("next").argument("[id]", "Backlog item ID to run first").description("Pick and run the next backlog item, or open /draft if none").option("-w, --write", "Run Claude with auto permission mode (default)").option("--no-write", "Run Claude without auto permission mode").option("--once", "Exit after the first completed item run").action(
|
|
6545
|
-
(
|
|
6596
|
+
(id2, opts) => next({ allowEdits: opts.write !== false, once: opts.once }, id2)
|
|
6546
6597
|
);
|
|
6547
6598
|
}
|
|
6548
6599
|
|
|
@@ -6560,8 +6611,8 @@ import enquirer7 from "enquirer";
|
|
|
6560
6611
|
import chalk64 from "chalk";
|
|
6561
6612
|
|
|
6562
6613
|
// src/commands/backlog/surfaceCreatedItem.ts
|
|
6563
|
-
async function surfaceCreatedItem(slashCommand,
|
|
6564
|
-
const numericId = Number.parseInt(
|
|
6614
|
+
async function surfaceCreatedItem(slashCommand, id2) {
|
|
6615
|
+
const numericId = Number.parseInt(id2, 10);
|
|
6565
6616
|
if (Number.isNaN(numericId)) return;
|
|
6566
6617
|
const { orm } = await getReady();
|
|
6567
6618
|
const item = await loadItem(orm, numericId);
|
|
@@ -6576,33 +6627,33 @@ async function surfaceCreatedItem(slashCommand, id) {
|
|
|
6576
6627
|
|
|
6577
6628
|
// src/commands/backlog/tryRunById.ts
|
|
6578
6629
|
import chalk63 from "chalk";
|
|
6579
|
-
async function tryRunById(
|
|
6580
|
-
const numericId = Number.parseInt(
|
|
6630
|
+
async function tryRunById(id2, options2) {
|
|
6631
|
+
const numericId = Number.parseInt(id2, 10);
|
|
6581
6632
|
const { orm } = await getReady();
|
|
6582
6633
|
const item = Number.isNaN(numericId) ? void 0 : await loadItem(orm, numericId);
|
|
6583
6634
|
if (!item) {
|
|
6584
|
-
console.log(chalk63.red(`Item #${
|
|
6635
|
+
console.log(chalk63.red(`Item #${id2} not found.`));
|
|
6585
6636
|
return false;
|
|
6586
6637
|
}
|
|
6587
6638
|
if (item.status === "done") {
|
|
6588
|
-
console.log(chalk63.red(`Item #${
|
|
6639
|
+
console.log(chalk63.red(`Item #${id2} is already done.`));
|
|
6589
6640
|
return false;
|
|
6590
6641
|
}
|
|
6591
6642
|
if (item.status === "wontdo") {
|
|
6592
|
-
console.log(chalk63.red(`Item #${
|
|
6643
|
+
console.log(chalk63.red(`Item #${id2} is marked won't do.`));
|
|
6593
6644
|
return false;
|
|
6594
6645
|
}
|
|
6595
6646
|
const hasDeps = (item.links ?? []).some((l) => l.type === "depends-on");
|
|
6596
6647
|
if (hasDeps && isBlocked(item, await loadItemSummaries(orm, getOrigin()))) {
|
|
6597
6648
|
console.log(
|
|
6598
|
-
chalk63.red(`Item #${
|
|
6649
|
+
chalk63.red(`Item #${id2} is blocked by unresolved dependencies.`)
|
|
6599
6650
|
);
|
|
6600
6651
|
return false;
|
|
6601
6652
|
}
|
|
6602
6653
|
console.log(chalk63.bold(`
|
|
6603
|
-
Running backlog item #${
|
|
6654
|
+
Running backlog item #${id2}...
|
|
6604
6655
|
`));
|
|
6605
|
-
await run2(
|
|
6656
|
+
await run2(id2, options2);
|
|
6606
6657
|
return true;
|
|
6607
6658
|
}
|
|
6608
6659
|
|
|
@@ -6668,8 +6719,8 @@ async function pickItemForRefine() {
|
|
|
6668
6719
|
);
|
|
6669
6720
|
return selected.match(/#(\d+)/)?.[1] ?? "";
|
|
6670
6721
|
}
|
|
6671
|
-
async function refine(
|
|
6672
|
-
const itemId =
|
|
6722
|
+
async function refine(id2, options2) {
|
|
6723
|
+
const itemId = id2 ?? await pickItemForRefine();
|
|
6673
6724
|
if (!itemId) return;
|
|
6674
6725
|
const numericId = Number.parseInt(itemId, 10);
|
|
6675
6726
|
const item = Number.isNaN(numericId) ? void 0 : await loadItem((await getReady()).orm, numericId);
|
|
@@ -6683,7 +6734,7 @@ async function refine(id, options2) {
|
|
|
6683
6734
|
// src/commands/backlog/registerRefineCommand.ts
|
|
6684
6735
|
function registerRefineCommand(cmd) {
|
|
6685
6736
|
cmd.command("refine").argument("[id]", "Backlog item ID").description("Alias for refine").option("--once", "Exit when the initial task completes").action(
|
|
6686
|
-
(
|
|
6737
|
+
(id2, opts) => refine(id2, { once: opts.once })
|
|
6687
6738
|
);
|
|
6688
6739
|
}
|
|
6689
6740
|
|
|
@@ -6702,13 +6753,13 @@ function validateRewind2(item, phaseNumber) {
|
|
|
6702
6753
|
}
|
|
6703
6754
|
return void 0;
|
|
6704
6755
|
}
|
|
6705
|
-
async function rewindPhase(
|
|
6756
|
+
async function rewindPhase(id2, phase, opts) {
|
|
6706
6757
|
const phaseNumber = Number.parseInt(phase, 10);
|
|
6707
6758
|
const phaseIndex = phaseNumber - 1;
|
|
6708
6759
|
const { orm } = await getReady();
|
|
6709
|
-
const item = await loadItem(orm, Number.parseInt(
|
|
6760
|
+
const item = await loadItem(orm, Number.parseInt(id2, 10));
|
|
6710
6761
|
if (!item) {
|
|
6711
|
-
console.log(chalk66.red(`Item #${
|
|
6762
|
+
console.log(chalk66.red(`Item #${id2} not found.`));
|
|
6712
6763
|
return;
|
|
6713
6764
|
}
|
|
6714
6765
|
const error = validateRewind2(item, phaseNumber);
|
|
@@ -6724,14 +6775,14 @@ async function rewindPhase(id, phase, opts) {
|
|
|
6724
6775
|
`Rewound to phase ${phaseNumber} (${phaseName}): ${opts.reason}`,
|
|
6725
6776
|
{ phase: phaseNumber }
|
|
6726
6777
|
);
|
|
6727
|
-
await setCurrentPhase(
|
|
6728
|
-
await setStatus(
|
|
6778
|
+
await setCurrentPhase(id2, phaseNumber);
|
|
6779
|
+
await setStatus(id2, "in-progress");
|
|
6729
6780
|
writeSignal("rewind", {
|
|
6730
|
-
itemId: Number.parseInt(
|
|
6781
|
+
itemId: Number.parseInt(id2, 10),
|
|
6731
6782
|
targetPhase: phaseIndex
|
|
6732
6783
|
});
|
|
6733
6784
|
console.log(
|
|
6734
|
-
chalk66.green(`Rewound item #${
|
|
6785
|
+
chalk66.green(`Rewound item #${id2} to phase ${phaseNumber} (${phaseName}).`)
|
|
6735
6786
|
);
|
|
6736
6787
|
}
|
|
6737
6788
|
|
|
@@ -6746,9 +6797,9 @@ function registerRunCommand(cmd) {
|
|
|
6746
6797
|
"--resume-session <id>",
|
|
6747
6798
|
"Resume an interrupted Claude session for the current phase (used by the sessions daemon on restart)"
|
|
6748
6799
|
).action(
|
|
6749
|
-
async (
|
|
6800
|
+
async (id2, opts) => {
|
|
6750
6801
|
if (!opts.resumeSession) pullIfConfigured();
|
|
6751
|
-
await run2(
|
|
6802
|
+
await run2(id2, {
|
|
6752
6803
|
allowEdits: opts.write !== false,
|
|
6753
6804
|
resumeSessionId: opts.resumeSession
|
|
6754
6805
|
});
|
|
@@ -6784,17 +6835,17 @@ function registerSearchCommand(cmd) {
|
|
|
6784
6835
|
|
|
6785
6836
|
// src/commands/backlog/delete/index.ts
|
|
6786
6837
|
import chalk68 from "chalk";
|
|
6787
|
-
async function del(
|
|
6788
|
-
const name = await removeItem(
|
|
6838
|
+
async function del(id2) {
|
|
6839
|
+
const name = await removeItem(id2);
|
|
6789
6840
|
if (name) {
|
|
6790
|
-
console.log(chalk68.green(`Deleted item #${
|
|
6841
|
+
console.log(chalk68.green(`Deleted item #${id2}: ${name}`));
|
|
6791
6842
|
}
|
|
6792
6843
|
}
|
|
6793
6844
|
|
|
6794
6845
|
// src/commands/backlog/done/index.ts
|
|
6795
6846
|
import chalk69 from "chalk";
|
|
6796
|
-
async function done(
|
|
6797
|
-
const found = await findOneItem(
|
|
6847
|
+
async function done(id2, summary) {
|
|
6848
|
+
const found = await findOneItem(id2);
|
|
6798
6849
|
if (!found) return;
|
|
6799
6850
|
const { orm, item } = found;
|
|
6800
6851
|
if (item.plan && item.plan.length > 0) {
|
|
@@ -6803,7 +6854,7 @@ async function done(id, summary) {
|
|
|
6803
6854
|
if (pending.length > 0) {
|
|
6804
6855
|
console.log(
|
|
6805
6856
|
chalk69.red(
|
|
6806
|
-
`Cannot complete item #${
|
|
6857
|
+
`Cannot complete item #${id2}: ${pending.length} pending phase(s):`
|
|
6807
6858
|
)
|
|
6808
6859
|
);
|
|
6809
6860
|
for (const phase of pending) {
|
|
@@ -6818,37 +6869,66 @@ async function done(id, summary) {
|
|
|
6818
6869
|
const phase = item.currentPhase ?? 1;
|
|
6819
6870
|
await appendComment(orm, item.id, summary, { phase, type: "summary" });
|
|
6820
6871
|
}
|
|
6821
|
-
console.log(chalk69.green(`Completed item #${
|
|
6872
|
+
console.log(chalk69.green(`Completed item #${id2}: ${item.name}`));
|
|
6822
6873
|
}
|
|
6823
6874
|
|
|
6824
|
-
// src/commands/backlog/
|
|
6875
|
+
// src/commands/backlog/star/index.ts
|
|
6876
|
+
import chalk71 from "chalk";
|
|
6877
|
+
|
|
6878
|
+
// src/commands/backlog/setStarred.ts
|
|
6825
6879
|
import chalk70 from "chalk";
|
|
6826
|
-
async function
|
|
6827
|
-
const
|
|
6880
|
+
async function setStarred(id2, starred) {
|
|
6881
|
+
const { orm } = await getReady();
|
|
6882
|
+
const name = await updateStarred(orm, Number.parseInt(id2, 10), starred);
|
|
6883
|
+
if (name === void 0) console.log(chalk70.red(`Item #${id2} not found.`));
|
|
6884
|
+
return name;
|
|
6885
|
+
}
|
|
6886
|
+
|
|
6887
|
+
// src/commands/backlog/star/index.ts
|
|
6888
|
+
async function star(id2) {
|
|
6889
|
+
const name = await setStarred(id2, true);
|
|
6828
6890
|
if (name) {
|
|
6829
|
-
console.log(
|
|
6891
|
+
console.log(chalk71.green(`Starred item #${id2}: ${name}`));
|
|
6892
|
+
}
|
|
6893
|
+
}
|
|
6894
|
+
|
|
6895
|
+
// src/commands/backlog/start/index.ts
|
|
6896
|
+
import chalk72 from "chalk";
|
|
6897
|
+
async function start(id2) {
|
|
6898
|
+
const name = await setStatus(id2, "in-progress");
|
|
6899
|
+
if (name) {
|
|
6900
|
+
console.log(chalk72.green(`Started item #${id2}: ${name}`));
|
|
6830
6901
|
}
|
|
6831
6902
|
}
|
|
6832
6903
|
|
|
6833
6904
|
// src/commands/backlog/stop/index.ts
|
|
6834
|
-
import
|
|
6835
|
-
import { and as and5, eq as
|
|
6905
|
+
import chalk73 from "chalk";
|
|
6906
|
+
import { and as and5, eq as eq23 } from "drizzle-orm";
|
|
6836
6907
|
async function stop() {
|
|
6837
6908
|
const { orm } = await getReady();
|
|
6838
|
-
const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and5(
|
|
6909
|
+
const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and5(eq23(items.status, "in-progress"), eq23(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
|
|
6839
6910
|
if (stopped.length === 0) {
|
|
6840
|
-
console.log(
|
|
6911
|
+
console.log(chalk73.yellow("No in-progress items to stop."));
|
|
6841
6912
|
return;
|
|
6842
6913
|
}
|
|
6843
6914
|
for (const item of stopped) {
|
|
6844
|
-
console.log(
|
|
6915
|
+
console.log(chalk73.yellow(`Stopped item #${item.id}: ${item.name}`));
|
|
6916
|
+
}
|
|
6917
|
+
}
|
|
6918
|
+
|
|
6919
|
+
// src/commands/backlog/unstar/index.ts
|
|
6920
|
+
import chalk74 from "chalk";
|
|
6921
|
+
async function unstar(id2) {
|
|
6922
|
+
const name = await setStarred(id2, false);
|
|
6923
|
+
if (name) {
|
|
6924
|
+
console.log(chalk74.green(`Unstarred item #${id2}: ${name}`));
|
|
6845
6925
|
}
|
|
6846
6926
|
}
|
|
6847
6927
|
|
|
6848
6928
|
// src/commands/backlog/wontdo/index.ts
|
|
6849
|
-
import
|
|
6850
|
-
async function wontdo(
|
|
6851
|
-
const found = await findOneItem(
|
|
6929
|
+
import chalk75 from "chalk";
|
|
6930
|
+
async function wontdo(id2, reason) {
|
|
6931
|
+
const found = await findOneItem(id2);
|
|
6852
6932
|
if (!found) return;
|
|
6853
6933
|
const { orm, item } = found;
|
|
6854
6934
|
await updateStatus(orm, item.id, "wontdo");
|
|
@@ -6856,7 +6936,7 @@ async function wontdo(id, reason) {
|
|
|
6856
6936
|
const phase = item.currentPhase ?? 1;
|
|
6857
6937
|
await appendComment(orm, item.id, reason, { phase, type: "summary" });
|
|
6858
6938
|
}
|
|
6859
|
-
console.log(
|
|
6939
|
+
console.log(chalk75.red(`Won't do item #${id2}: ${item.name}`));
|
|
6860
6940
|
}
|
|
6861
6941
|
|
|
6862
6942
|
// src/commands/backlog/registerStatusCommands.ts
|
|
@@ -6865,26 +6945,28 @@ function registerStatusCommands(cmd) {
|
|
|
6865
6945
|
cmd.command("stop").description("Revert all in-progress backlog items to todo").action(stop);
|
|
6866
6946
|
cmd.command("done <id> [summary]").description("Set a backlog item to done").action(done);
|
|
6867
6947
|
cmd.command("wontdo <id> [reason]").description("Set a backlog item to won't do").action(wontdo);
|
|
6948
|
+
cmd.command("star <id>").description("Star a backlog item to pin it in the web view").action(star);
|
|
6949
|
+
cmd.command("unstar <id>").description("Remove the star from a backlog item").action(unstar);
|
|
6868
6950
|
cmd.command("delete <id>").alias("remove").description("Delete a backlog item").action(del);
|
|
6869
6951
|
}
|
|
6870
6952
|
|
|
6871
6953
|
// src/commands/backlog/removePhase.ts
|
|
6872
|
-
import
|
|
6873
|
-
import { and as and8, eq as
|
|
6954
|
+
import chalk77 from "chalk";
|
|
6955
|
+
import { and as and8, eq as eq26 } from "drizzle-orm";
|
|
6874
6956
|
|
|
6875
6957
|
// src/commands/backlog/findPhase.ts
|
|
6876
|
-
import
|
|
6877
|
-
import { and as and6, count as count4, eq as
|
|
6878
|
-
async function findPhase(
|
|
6879
|
-
const found = await findOneItem(
|
|
6958
|
+
import chalk76 from "chalk";
|
|
6959
|
+
import { and as and6, count as count4, eq as eq24 } from "drizzle-orm";
|
|
6960
|
+
async function findPhase(id2, phase) {
|
|
6961
|
+
const found = await findOneItem(id2);
|
|
6880
6962
|
if (!found) return void 0;
|
|
6881
6963
|
const { orm, item } = found;
|
|
6882
6964
|
const itemId = item.id;
|
|
6883
6965
|
const phaseIdx = Number.parseInt(phase, 10) - 1;
|
|
6884
|
-
const [row] = await orm.select({ cnt: count4() }).from(planPhases).where(and6(
|
|
6966
|
+
const [row] = await orm.select({ cnt: count4() }).from(planPhases).where(and6(eq24(planPhases.itemId, itemId), eq24(planPhases.idx, phaseIdx)));
|
|
6885
6967
|
if (!row || row.cnt === 0) {
|
|
6886
6968
|
console.log(
|
|
6887
|
-
|
|
6969
|
+
chalk76.red(`Phase ${phaseIdx + 1} not found on item #${itemId}.`)
|
|
6888
6970
|
);
|
|
6889
6971
|
process.exitCode = 1;
|
|
6890
6972
|
return void 0;
|
|
@@ -6893,14 +6975,14 @@ async function findPhase(id, phase) {
|
|
|
6893
6975
|
}
|
|
6894
6976
|
|
|
6895
6977
|
// src/commands/backlog/reindexPhases.ts
|
|
6896
|
-
import { and as and7, asc as asc6, count as count5, eq as
|
|
6978
|
+
import { and as and7, asc as asc6, count as count5, eq as eq25 } from "drizzle-orm";
|
|
6897
6979
|
async function reindexPhases(db, itemId) {
|
|
6898
|
-
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(
|
|
6980
|
+
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq25(planPhases.itemId, itemId)).orderBy(asc6(planPhases.idx));
|
|
6899
6981
|
for (let i = 0; i < remaining.length; i++) {
|
|
6900
6982
|
const oldIdx = remaining[i].idx;
|
|
6901
6983
|
if (oldIdx === i) continue;
|
|
6902
|
-
await db.update(planTasks).set({ phaseIdx: i }).where(and7(
|
|
6903
|
-
await db.update(planPhases).set({ idx: i }).where(and7(
|
|
6984
|
+
await db.update(planTasks).set({ phaseIdx: i }).where(and7(eq25(planTasks.itemId, itemId), eq25(planTasks.phaseIdx, oldIdx)));
|
|
6985
|
+
await db.update(planPhases).set({ idx: i }).where(and7(eq25(planPhases.itemId, itemId), eq25(planPhases.idx, oldIdx)));
|
|
6904
6986
|
}
|
|
6905
6987
|
}
|
|
6906
6988
|
async function adjustCurrentPhase(db, item, removedIdx) {
|
|
@@ -6908,36 +6990,36 @@ async function adjustCurrentPhase(db, item, removedIdx) {
|
|
|
6908
6990
|
if (currentPhase === void 0) return;
|
|
6909
6991
|
const currentIdx = currentPhase - 1;
|
|
6910
6992
|
if (removedIdx < currentIdx) {
|
|
6911
|
-
await db.update(items).set({ currentPhase: currentPhase - 1 }).where(
|
|
6993
|
+
await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq25(items.id, item.id));
|
|
6912
6994
|
return;
|
|
6913
6995
|
}
|
|
6914
6996
|
if (removedIdx !== currentIdx) return;
|
|
6915
|
-
const [row] = await db.select({ cnt: count5() }).from(planPhases).where(
|
|
6997
|
+
const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq25(planPhases.itemId, item.id));
|
|
6916
6998
|
const cnt = row?.cnt ?? 0;
|
|
6917
|
-
await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(
|
|
6999
|
+
await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq25(items.id, item.id));
|
|
6918
7000
|
}
|
|
6919
7001
|
|
|
6920
7002
|
// src/commands/backlog/removePhase.ts
|
|
6921
|
-
async function removePhase(
|
|
6922
|
-
const found = await findPhase(
|
|
7003
|
+
async function removePhase(id2, phase) {
|
|
7004
|
+
const found = await findPhase(id2, phase);
|
|
6923
7005
|
if (!found) return;
|
|
6924
7006
|
const { item, orm, itemId, phaseIdx } = found;
|
|
6925
7007
|
await orm.transaction(async (tx) => {
|
|
6926
7008
|
await tx.delete(planTasks).where(
|
|
6927
|
-
and8(
|
|
7009
|
+
and8(eq26(planTasks.itemId, itemId), eq26(planTasks.phaseIdx, phaseIdx))
|
|
6928
7010
|
);
|
|
6929
|
-
await tx.delete(planPhases).where(and8(
|
|
7011
|
+
await tx.delete(planPhases).where(and8(eq26(planPhases.itemId, itemId), eq26(planPhases.idx, phaseIdx)));
|
|
6930
7012
|
await reindexPhases(tx, itemId);
|
|
6931
7013
|
await adjustCurrentPhase(tx, item, phaseIdx);
|
|
6932
7014
|
});
|
|
6933
7015
|
console.log(
|
|
6934
|
-
|
|
7016
|
+
chalk77.green(`Removed phase ${phaseIdx + 1} from item #${itemId}.`)
|
|
6935
7017
|
);
|
|
6936
7018
|
}
|
|
6937
7019
|
|
|
6938
7020
|
// src/commands/backlog/update/index.ts
|
|
6939
|
-
import
|
|
6940
|
-
import { eq as
|
|
7021
|
+
import chalk79 from "chalk";
|
|
7022
|
+
import { eq as eq27 } from "drizzle-orm";
|
|
6941
7023
|
|
|
6942
7024
|
// src/commands/backlog/update/parseListIndex.ts
|
|
6943
7025
|
function parseListIndex(raw, length, label2) {
|
|
@@ -7012,16 +7094,16 @@ function applyAcMutations(current, options2) {
|
|
|
7012
7094
|
}
|
|
7013
7095
|
|
|
7014
7096
|
// src/commands/backlog/update/buildUpdateValues.ts
|
|
7015
|
-
import
|
|
7097
|
+
import chalk78 from "chalk";
|
|
7016
7098
|
function buildUpdateValues(options2) {
|
|
7017
7099
|
const { name, desc: desc2, type, ac } = options2;
|
|
7018
7100
|
if (!name && !desc2 && !type && !ac) {
|
|
7019
|
-
console.log(
|
|
7101
|
+
console.log(chalk78.red("Nothing to update. Provide at least one flag."));
|
|
7020
7102
|
process.exitCode = 1;
|
|
7021
7103
|
return void 0;
|
|
7022
7104
|
}
|
|
7023
7105
|
if (type && type !== "story" && type !== "bug") {
|
|
7024
|
-
console.log(
|
|
7106
|
+
console.log(chalk78.red('Invalid type. Must be "story" or "bug".'));
|
|
7025
7107
|
process.exitCode = 1;
|
|
7026
7108
|
return void 0;
|
|
7027
7109
|
}
|
|
@@ -7047,21 +7129,21 @@ function buildUpdateValues(options2) {
|
|
|
7047
7129
|
}
|
|
7048
7130
|
|
|
7049
7131
|
// src/commands/backlog/update/index.ts
|
|
7050
|
-
async function update(
|
|
7051
|
-
const found = await findOneItem(
|
|
7132
|
+
async function update(id2, options2) {
|
|
7133
|
+
const found = await findOneItem(id2);
|
|
7052
7134
|
if (!found) return;
|
|
7053
7135
|
let ac = options2.ac;
|
|
7054
7136
|
if (hasAcMutations(options2)) {
|
|
7055
7137
|
if (options2.ac) {
|
|
7056
7138
|
console.log(
|
|
7057
|
-
|
|
7139
|
+
chalk79.red("Cannot combine --ac with --add-ac/--edit-ac/--remove-ac.")
|
|
7058
7140
|
);
|
|
7059
7141
|
process.exitCode = 1;
|
|
7060
7142
|
return;
|
|
7061
7143
|
}
|
|
7062
7144
|
const mutation = applyAcMutations(found.item.acceptanceCriteria, options2);
|
|
7063
7145
|
if (!mutation.ok) {
|
|
7064
|
-
console.log(
|
|
7146
|
+
console.log(chalk79.red(mutation.error));
|
|
7065
7147
|
process.exitCode = 1;
|
|
7066
7148
|
return;
|
|
7067
7149
|
}
|
|
@@ -7071,30 +7153,30 @@ async function update(id, options2) {
|
|
|
7071
7153
|
if (!built) return;
|
|
7072
7154
|
const { orm } = found;
|
|
7073
7155
|
const itemId = found.item.id;
|
|
7074
|
-
await orm.update(items).set(built.set).where(
|
|
7075
|
-
console.log(
|
|
7156
|
+
await orm.update(items).set(built.set).where(eq27(items.id, itemId));
|
|
7157
|
+
console.log(chalk79.green(`Updated ${built.fields} on item #${itemId}.`));
|
|
7076
7158
|
}
|
|
7077
7159
|
|
|
7078
7160
|
// src/commands/backlog/updatePhase.ts
|
|
7079
|
-
import
|
|
7161
|
+
import chalk80 from "chalk";
|
|
7080
7162
|
|
|
7081
7163
|
// src/commands/backlog/applyPhaseUpdate.ts
|
|
7082
|
-
import { and as and9, eq as
|
|
7164
|
+
import { and as and9, eq as eq28 } from "drizzle-orm";
|
|
7083
7165
|
async function applyPhaseUpdate(orm, itemId, phaseIdx, fields) {
|
|
7084
7166
|
await orm.transaction(async (tx) => {
|
|
7085
7167
|
if (fields.name) {
|
|
7086
7168
|
await tx.update(planPhases).set({ name: fields.name }).where(
|
|
7087
|
-
and9(
|
|
7169
|
+
and9(eq28(planPhases.itemId, itemId), eq28(planPhases.idx, phaseIdx))
|
|
7088
7170
|
);
|
|
7089
7171
|
}
|
|
7090
7172
|
if (fields.manualCheck) {
|
|
7091
7173
|
await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
|
|
7092
|
-
and9(
|
|
7174
|
+
and9(eq28(planPhases.itemId, itemId), eq28(planPhases.idx, phaseIdx))
|
|
7093
7175
|
);
|
|
7094
7176
|
}
|
|
7095
7177
|
if (fields.task) {
|
|
7096
7178
|
await tx.delete(planTasks).where(
|
|
7097
|
-
and9(
|
|
7179
|
+
and9(eq28(planTasks.itemId, itemId), eq28(planTasks.phaseIdx, phaseIdx))
|
|
7098
7180
|
);
|
|
7099
7181
|
if (fields.task.length) {
|
|
7100
7182
|
await tx.insert(planTasks).values(
|
|
@@ -7174,13 +7256,13 @@ function resolvePhaseFields(options2, current) {
|
|
|
7174
7256
|
}
|
|
7175
7257
|
|
|
7176
7258
|
// src/commands/backlog/updatePhase.ts
|
|
7177
|
-
async function updatePhase(
|
|
7178
|
-
const found = await findPhase(
|
|
7259
|
+
async function updatePhase(id2, phase, options2) {
|
|
7260
|
+
const found = await findPhase(id2, phase);
|
|
7179
7261
|
if (!found) return;
|
|
7180
7262
|
const { item, orm, itemId, phaseIdx } = found;
|
|
7181
7263
|
const resolved = resolvePhaseFields(options2, item.plan?.[phaseIdx]);
|
|
7182
7264
|
if (!resolved.ok) {
|
|
7183
|
-
console.log(
|
|
7265
|
+
console.log(chalk80.red(resolved.error));
|
|
7184
7266
|
process.exitCode = 1;
|
|
7185
7267
|
return;
|
|
7186
7268
|
}
|
|
@@ -7192,7 +7274,7 @@ async function updatePhase(id, phase, options2) {
|
|
|
7192
7274
|
manualCheck && "manual checks"
|
|
7193
7275
|
].filter(Boolean).join(", ");
|
|
7194
7276
|
console.log(
|
|
7195
|
-
|
|
7277
|
+
chalk80.green(
|
|
7196
7278
|
`Updated ${fields} on phase ${phaseIdx + 1} of item #${itemId}.`
|
|
7197
7279
|
)
|
|
7198
7280
|
);
|
|
@@ -7925,11 +8007,11 @@ function assertCliExists(cli) {
|
|
|
7925
8007
|
}
|
|
7926
8008
|
|
|
7927
8009
|
// src/commands/permitCliReads/colorize.ts
|
|
7928
|
-
import
|
|
8010
|
+
import chalk81 from "chalk";
|
|
7929
8011
|
function colorize(plainOutput) {
|
|
7930
8012
|
return plainOutput.split("\n").map((line) => {
|
|
7931
|
-
if (line.startsWith(" R ")) return
|
|
7932
|
-
if (line.startsWith(" W ")) return
|
|
8013
|
+
if (line.startsWith(" R ")) return chalk81.green(line);
|
|
8014
|
+
if (line.startsWith(" W ")) return chalk81.red(line);
|
|
7933
8015
|
return line;
|
|
7934
8016
|
}).join("\n");
|
|
7935
8017
|
}
|
|
@@ -8227,7 +8309,7 @@ async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
|
8227
8309
|
}
|
|
8228
8310
|
|
|
8229
8311
|
// src/commands/deny/denyAdd.ts
|
|
8230
|
-
import
|
|
8312
|
+
import chalk82 from "chalk";
|
|
8231
8313
|
|
|
8232
8314
|
// src/commands/deny/loadDenyConfig.ts
|
|
8233
8315
|
function loadDenyConfig(global) {
|
|
@@ -8247,16 +8329,16 @@ function loadDenyConfig(global) {
|
|
|
8247
8329
|
function denyAdd(pattern2, message, options2) {
|
|
8248
8330
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
8249
8331
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
8250
|
-
console.log(
|
|
8332
|
+
console.log(chalk82.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
8251
8333
|
return;
|
|
8252
8334
|
}
|
|
8253
8335
|
deny.push({ pattern: pattern2, message });
|
|
8254
8336
|
saveDeny(deny);
|
|
8255
|
-
console.log(
|
|
8337
|
+
console.log(chalk82.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
8256
8338
|
}
|
|
8257
8339
|
|
|
8258
8340
|
// src/commands/deny/denyList.ts
|
|
8259
|
-
import
|
|
8341
|
+
import chalk83 from "chalk";
|
|
8260
8342
|
function denyList() {
|
|
8261
8343
|
const globalRaw = loadGlobalConfigRaw();
|
|
8262
8344
|
const projectRaw = loadProjectConfig();
|
|
@@ -8267,7 +8349,7 @@ function denyList() {
|
|
|
8267
8349
|
projectDeny.length > 0 ? projectDeny : void 0
|
|
8268
8350
|
);
|
|
8269
8351
|
if (!merged || merged.length === 0) {
|
|
8270
|
-
console.log(
|
|
8352
|
+
console.log(chalk83.dim("No deny rules configured."));
|
|
8271
8353
|
return;
|
|
8272
8354
|
}
|
|
8273
8355
|
const projectPatterns = new Set(projectDeny.map((r) => r.pattern));
|
|
@@ -8275,23 +8357,23 @@ function denyList() {
|
|
|
8275
8357
|
for (const rule of merged) {
|
|
8276
8358
|
const inProject = projectPatterns.has(rule.pattern);
|
|
8277
8359
|
const inGlobal = globalPatterns.has(rule.pattern);
|
|
8278
|
-
const label2 = inProject && inGlobal ?
|
|
8279
|
-
console.log(`${
|
|
8360
|
+
const label2 = inProject && inGlobal ? chalk83.dim(" (project, overrides global)") : inGlobal ? chalk83.dim(" (global)") : "";
|
|
8361
|
+
console.log(`${chalk83.red(rule.pattern)} \u2192 ${rule.message}${label2}`);
|
|
8280
8362
|
}
|
|
8281
8363
|
}
|
|
8282
8364
|
|
|
8283
8365
|
// src/commands/deny/denyRemove.ts
|
|
8284
|
-
import
|
|
8366
|
+
import chalk84 from "chalk";
|
|
8285
8367
|
function denyRemove(pattern2, options2) {
|
|
8286
8368
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
8287
8369
|
const index2 = deny.findIndex((r) => r.pattern === pattern2);
|
|
8288
8370
|
if (index2 === -1) {
|
|
8289
|
-
console.log(
|
|
8371
|
+
console.log(chalk84.yellow(`No deny rule found for: ${pattern2}`));
|
|
8290
8372
|
return;
|
|
8291
8373
|
}
|
|
8292
8374
|
deny.splice(index2, 1);
|
|
8293
8375
|
saveDeny(deny.length > 0 ? deny : void 0);
|
|
8294
|
-
console.log(
|
|
8376
|
+
console.log(chalk84.green(`Removed deny rule: ${pattern2}`));
|
|
8295
8377
|
}
|
|
8296
8378
|
|
|
8297
8379
|
// src/commands/registerDeny.ts
|
|
@@ -8320,15 +8402,15 @@ function registerCliHook(program2) {
|
|
|
8320
8402
|
}
|
|
8321
8403
|
|
|
8322
8404
|
// src/commands/complexity/analyze.ts
|
|
8323
|
-
import
|
|
8405
|
+
import chalk91 from "chalk";
|
|
8324
8406
|
|
|
8325
8407
|
// src/commands/complexity/cyclomatic.ts
|
|
8326
|
-
import
|
|
8408
|
+
import chalk86 from "chalk";
|
|
8327
8409
|
|
|
8328
8410
|
// src/commands/complexity/shared/index.ts
|
|
8329
8411
|
import fs13 from "fs";
|
|
8330
8412
|
import path19 from "path";
|
|
8331
|
-
import
|
|
8413
|
+
import chalk85 from "chalk";
|
|
8332
8414
|
import ts5 from "typescript";
|
|
8333
8415
|
|
|
8334
8416
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -8579,7 +8661,7 @@ function createSourceFromFile(filePath) {
|
|
|
8579
8661
|
function withSourceFiles(pattern2, callback, extraIgnore = []) {
|
|
8580
8662
|
const files = findSourceFiles2(pattern2, ".", extraIgnore);
|
|
8581
8663
|
if (files.length === 0) {
|
|
8582
|
-
console.log(
|
|
8664
|
+
console.log(chalk85.yellow("No files found matching pattern"));
|
|
8583
8665
|
return void 0;
|
|
8584
8666
|
}
|
|
8585
8667
|
return callback(files);
|
|
@@ -8612,11 +8694,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
8612
8694
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
8613
8695
|
for (const { file, name, complexity } of results) {
|
|
8614
8696
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
8615
|
-
const color = exceedsThreshold ?
|
|
8616
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
8697
|
+
const color = exceedsThreshold ? chalk86.red : chalk86.white;
|
|
8698
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk86.cyan(complexity)}`);
|
|
8617
8699
|
}
|
|
8618
8700
|
console.log(
|
|
8619
|
-
|
|
8701
|
+
chalk86.dim(
|
|
8620
8702
|
`
|
|
8621
8703
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
8622
8704
|
)
|
|
@@ -8628,7 +8710,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
8628
8710
|
}
|
|
8629
8711
|
|
|
8630
8712
|
// src/commands/complexity/halstead.ts
|
|
8631
|
-
import
|
|
8713
|
+
import chalk87 from "chalk";
|
|
8632
8714
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
8633
8715
|
withSourceFiles(pattern2, (files) => {
|
|
8634
8716
|
const results = [];
|
|
@@ -8643,13 +8725,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
8643
8725
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
8644
8726
|
for (const { file, name, metrics } of results) {
|
|
8645
8727
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
8646
|
-
const color = exceedsThreshold ?
|
|
8728
|
+
const color = exceedsThreshold ? chalk87.red : chalk87.white;
|
|
8647
8729
|
console.log(
|
|
8648
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
8730
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk87.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk87.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk87.magenta(metrics.effort.toFixed(1))}`
|
|
8649
8731
|
);
|
|
8650
8732
|
}
|
|
8651
8733
|
console.log(
|
|
8652
|
-
|
|
8734
|
+
chalk87.dim(
|
|
8653
8735
|
`
|
|
8654
8736
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
8655
8737
|
)
|
|
@@ -8673,28 +8755,28 @@ function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, slo
|
|
|
8673
8755
|
}
|
|
8674
8756
|
|
|
8675
8757
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
8676
|
-
import
|
|
8758
|
+
import chalk88 from "chalk";
|
|
8677
8759
|
function displayMaintainabilityResults(results, threshold) {
|
|
8678
8760
|
const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
|
|
8679
8761
|
if (threshold !== void 0 && filtered.length === 0) {
|
|
8680
|
-
console.log(
|
|
8762
|
+
console.log(chalk88.green("All files pass maintainability threshold"));
|
|
8681
8763
|
} else {
|
|
8682
8764
|
for (const { file, avgMaintainability, minMaintainability } of filtered) {
|
|
8683
|
-
const color = threshold !== void 0 ?
|
|
8765
|
+
const color = threshold !== void 0 ? chalk88.red : chalk88.white;
|
|
8684
8766
|
console.log(
|
|
8685
|
-
`${color(file)} \u2192 avg: ${
|
|
8767
|
+
`${color(file)} \u2192 avg: ${chalk88.cyan(avgMaintainability.toFixed(1))}, min: ${chalk88.yellow(minMaintainability.toFixed(1))}`
|
|
8686
8768
|
);
|
|
8687
8769
|
}
|
|
8688
8770
|
}
|
|
8689
|
-
console.log(
|
|
8771
|
+
console.log(chalk88.dim(`
|
|
8690
8772
|
Analyzed ${results.length} files`));
|
|
8691
8773
|
if (filtered.length > 0 && threshold !== void 0) {
|
|
8692
8774
|
console.error(
|
|
8693
|
-
|
|
8775
|
+
chalk88.red(
|
|
8694
8776
|
`
|
|
8695
8777
|
Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
8696
8778
|
|
|
8697
|
-
\u26A0\uFE0F ${
|
|
8779
|
+
\u26A0\uFE0F ${chalk88.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
|
|
8698
8780
|
)
|
|
8699
8781
|
);
|
|
8700
8782
|
process.exit(1);
|
|
@@ -8702,10 +8784,10 @@ Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability i
|
|
|
8702
8784
|
}
|
|
8703
8785
|
|
|
8704
8786
|
// src/commands/complexity/maintainability/printMaintainabilityFormula.ts
|
|
8705
|
-
import
|
|
8787
|
+
import chalk89 from "chalk";
|
|
8706
8788
|
var MI_FORMULA = "171 - 5.2*ln(HalsteadVolume) - 0.23*CyclomaticComplexity - 16.2*ln(SLOC), clamped 0-100";
|
|
8707
8789
|
function printMaintainabilityFormula() {
|
|
8708
|
-
console.log(
|
|
8790
|
+
console.log(chalk89.dim(MI_FORMULA));
|
|
8709
8791
|
}
|
|
8710
8792
|
|
|
8711
8793
|
// src/commands/complexity/maintainability/index.ts
|
|
@@ -8756,7 +8838,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
8756
8838
|
|
|
8757
8839
|
// src/commands/complexity/sloc.ts
|
|
8758
8840
|
import fs15 from "fs";
|
|
8759
|
-
import
|
|
8841
|
+
import chalk90 from "chalk";
|
|
8760
8842
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
8761
8843
|
withSourceFiles(pattern2, (files) => {
|
|
8762
8844
|
const results = [];
|
|
@@ -8772,12 +8854,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
8772
8854
|
results.sort((a, b) => b.lines - a.lines);
|
|
8773
8855
|
for (const { file, lines } of results) {
|
|
8774
8856
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
8775
|
-
const color = exceedsThreshold ?
|
|
8776
|
-
console.log(`${color(file)} \u2192 ${
|
|
8857
|
+
const color = exceedsThreshold ? chalk90.red : chalk90.white;
|
|
8858
|
+
console.log(`${color(file)} \u2192 ${chalk90.cyan(lines)} lines`);
|
|
8777
8859
|
}
|
|
8778
8860
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
8779
8861
|
console.log(
|
|
8780
|
-
|
|
8862
|
+
chalk90.dim(`
|
|
8781
8863
|
Total: ${total} lines across ${files.length} files`)
|
|
8782
8864
|
);
|
|
8783
8865
|
if (hasViolation) {
|
|
@@ -8791,21 +8873,21 @@ async function analyze(pattern2) {
|
|
|
8791
8873
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
8792
8874
|
const files = findSourceFiles2(searchPattern);
|
|
8793
8875
|
if (files.length === 0) {
|
|
8794
|
-
console.log(
|
|
8876
|
+
console.log(chalk91.yellow("No files found matching pattern"));
|
|
8795
8877
|
return;
|
|
8796
8878
|
}
|
|
8797
8879
|
if (files.length === 1) {
|
|
8798
8880
|
const file = files[0];
|
|
8799
|
-
console.log(
|
|
8881
|
+
console.log(chalk91.bold.underline("SLOC"));
|
|
8800
8882
|
await sloc(file);
|
|
8801
8883
|
console.log();
|
|
8802
|
-
console.log(
|
|
8884
|
+
console.log(chalk91.bold.underline("Cyclomatic Complexity"));
|
|
8803
8885
|
await cyclomatic(file);
|
|
8804
8886
|
console.log();
|
|
8805
|
-
console.log(
|
|
8887
|
+
console.log(chalk91.bold.underline("Halstead Metrics"));
|
|
8806
8888
|
await halstead(file);
|
|
8807
8889
|
console.log();
|
|
8808
|
-
console.log(
|
|
8890
|
+
console.log(chalk91.bold.underline("Maintainability Index"));
|
|
8809
8891
|
await maintainability(file);
|
|
8810
8892
|
return;
|
|
8811
8893
|
}
|
|
@@ -8837,7 +8919,7 @@ function registerComplexity(program2) {
|
|
|
8837
8919
|
}
|
|
8838
8920
|
|
|
8839
8921
|
// src/commands/config/index.ts
|
|
8840
|
-
import
|
|
8922
|
+
import chalk92 from "chalk";
|
|
8841
8923
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
8842
8924
|
|
|
8843
8925
|
// src/commands/config/setNestedValue.ts
|
|
@@ -8900,7 +8982,7 @@ function formatIssuePath(issue, key) {
|
|
|
8900
8982
|
function printValidationErrors(issues, key) {
|
|
8901
8983
|
for (const issue of issues) {
|
|
8902
8984
|
console.error(
|
|
8903
|
-
|
|
8985
|
+
chalk92.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
8904
8986
|
);
|
|
8905
8987
|
}
|
|
8906
8988
|
}
|
|
@@ -8917,7 +8999,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
8917
8999
|
function assertNotGlobalOnly(key, global) {
|
|
8918
9000
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
8919
9001
|
console.error(
|
|
8920
|
-
|
|
9002
|
+
chalk92.red(
|
|
8921
9003
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
8922
9004
|
)
|
|
8923
9005
|
);
|
|
@@ -8940,7 +9022,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
8940
9022
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
8941
9023
|
const target = options2.global ? "global" : "project";
|
|
8942
9024
|
console.log(
|
|
8943
|
-
|
|
9025
|
+
chalk92.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
8944
9026
|
);
|
|
8945
9027
|
}
|
|
8946
9028
|
function configList() {
|
|
@@ -8949,7 +9031,7 @@ function configList() {
|
|
|
8949
9031
|
}
|
|
8950
9032
|
|
|
8951
9033
|
// src/commands/config/configGet.ts
|
|
8952
|
-
import
|
|
9034
|
+
import chalk93 from "chalk";
|
|
8953
9035
|
|
|
8954
9036
|
// src/commands/config/getNestedValue.ts
|
|
8955
9037
|
function isTraversable(value) {
|
|
@@ -8981,7 +9063,7 @@ function requireNestedValue(config, key) {
|
|
|
8981
9063
|
return value;
|
|
8982
9064
|
}
|
|
8983
9065
|
function exitKeyNotSet(key) {
|
|
8984
|
-
console.error(
|
|
9066
|
+
console.error(chalk93.red(`Key "${key}" is not set`));
|
|
8985
9067
|
process.exit(1);
|
|
8986
9068
|
}
|
|
8987
9069
|
|
|
@@ -8995,7 +9077,7 @@ function registerConfig(program2) {
|
|
|
8995
9077
|
|
|
8996
9078
|
// src/commands/deploy/redirect.ts
|
|
8997
9079
|
import { existsSync as existsSync25, readFileSync as readFileSync19, writeFileSync as writeFileSync18 } from "fs";
|
|
8998
|
-
import
|
|
9080
|
+
import chalk94 from "chalk";
|
|
8999
9081
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
9000
9082
|
if (!window.location.pathname.endsWith('/')) {
|
|
9001
9083
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -9004,22 +9086,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
9004
9086
|
function redirect() {
|
|
9005
9087
|
const indexPath = "index.html";
|
|
9006
9088
|
if (!existsSync25(indexPath)) {
|
|
9007
|
-
console.log(
|
|
9089
|
+
console.log(chalk94.yellow("No index.html found"));
|
|
9008
9090
|
return;
|
|
9009
9091
|
}
|
|
9010
9092
|
const content = readFileSync19(indexPath, "utf-8");
|
|
9011
9093
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
9012
|
-
console.log(
|
|
9094
|
+
console.log(chalk94.dim("Trailing slash script already present"));
|
|
9013
9095
|
return;
|
|
9014
9096
|
}
|
|
9015
9097
|
const headCloseIndex = content.indexOf("</head>");
|
|
9016
9098
|
if (headCloseIndex === -1) {
|
|
9017
|
-
console.log(
|
|
9099
|
+
console.log(chalk94.red("Could not find </head> tag in index.html"));
|
|
9018
9100
|
return;
|
|
9019
9101
|
}
|
|
9020
9102
|
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
9021
9103
|
writeFileSync18(indexPath, newContent);
|
|
9022
|
-
console.log(
|
|
9104
|
+
console.log(chalk94.green("Added trailing slash redirect to index.html"));
|
|
9023
9105
|
}
|
|
9024
9106
|
|
|
9025
9107
|
// src/commands/registerDeploy.ts
|
|
@@ -9046,7 +9128,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
9046
9128
|
|
|
9047
9129
|
// src/commands/devlog/shared.ts
|
|
9048
9130
|
import { execSync as execSync22 } from "child_process";
|
|
9049
|
-
import
|
|
9131
|
+
import chalk95 from "chalk";
|
|
9050
9132
|
|
|
9051
9133
|
// src/shared/getRepoName.ts
|
|
9052
9134
|
import { existsSync as existsSync26, readFileSync as readFileSync20 } from "fs";
|
|
@@ -9155,13 +9237,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
9155
9237
|
}
|
|
9156
9238
|
function printCommitsWithFiles(commits2, ignore2, verbose) {
|
|
9157
9239
|
for (const commit2 of commits2) {
|
|
9158
|
-
console.log(` ${
|
|
9240
|
+
console.log(` ${chalk95.yellow(commit2.hash)} ${commit2.message}`);
|
|
9159
9241
|
if (verbose) {
|
|
9160
9242
|
const visibleFiles = commit2.files.filter(
|
|
9161
9243
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
9162
9244
|
);
|
|
9163
9245
|
for (const file of visibleFiles) {
|
|
9164
|
-
console.log(` ${
|
|
9246
|
+
console.log(` ${chalk95.dim(file)}`);
|
|
9165
9247
|
}
|
|
9166
9248
|
}
|
|
9167
9249
|
}
|
|
@@ -9186,15 +9268,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
|
|
|
9186
9268
|
}
|
|
9187
9269
|
|
|
9188
9270
|
// src/commands/devlog/list/printDateHeader.ts
|
|
9189
|
-
import
|
|
9271
|
+
import chalk96 from "chalk";
|
|
9190
9272
|
function printDateHeader(date, isSkipped, entries) {
|
|
9191
9273
|
if (isSkipped) {
|
|
9192
|
-
console.log(`${
|
|
9274
|
+
console.log(`${chalk96.bold.blue(date)} ${chalk96.dim("skipped")}`);
|
|
9193
9275
|
} else if (entries && entries.length > 0) {
|
|
9194
|
-
const entryInfo = entries.map((e) => `${
|
|
9195
|
-
console.log(`${
|
|
9276
|
+
const entryInfo = entries.map((e) => `${chalk96.green(e.version)} ${e.title}`).join(" | ");
|
|
9277
|
+
console.log(`${chalk96.bold.blue(date)} ${entryInfo}`);
|
|
9196
9278
|
} else {
|
|
9197
|
-
console.log(`${
|
|
9279
|
+
console.log(`${chalk96.bold.blue(date)} ${chalk96.red("\u26A0 devlog missing")}`);
|
|
9198
9280
|
}
|
|
9199
9281
|
}
|
|
9200
9282
|
|
|
@@ -9298,24 +9380,24 @@ function bumpVersion(version2, type) {
|
|
|
9298
9380
|
|
|
9299
9381
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
9300
9382
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
9301
|
-
import
|
|
9383
|
+
import chalk98 from "chalk";
|
|
9302
9384
|
|
|
9303
9385
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
9304
|
-
import
|
|
9386
|
+
import chalk97 from "chalk";
|
|
9305
9387
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
9306
9388
|
if (conventional && firstHash) {
|
|
9307
9389
|
const version2 = getVersionAtCommit(firstHash);
|
|
9308
9390
|
if (version2) {
|
|
9309
|
-
console.log(`${
|
|
9391
|
+
console.log(`${chalk97.bold("version:")} ${stripToMinor(version2)}`);
|
|
9310
9392
|
} else {
|
|
9311
|
-
console.log(`${
|
|
9393
|
+
console.log(`${chalk97.bold("version:")} ${chalk97.red("unknown")}`);
|
|
9312
9394
|
}
|
|
9313
9395
|
} else if (patchVersion && minorVersion) {
|
|
9314
9396
|
console.log(
|
|
9315
|
-
`${
|
|
9397
|
+
`${chalk97.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
9316
9398
|
);
|
|
9317
9399
|
} else {
|
|
9318
|
-
console.log(`${
|
|
9400
|
+
console.log(`${chalk97.bold("version:")} v0.1 (initial)`);
|
|
9319
9401
|
}
|
|
9320
9402
|
}
|
|
9321
9403
|
|
|
@@ -9363,16 +9445,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
9363
9445
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
9364
9446
|
}
|
|
9365
9447
|
function logName(repoName) {
|
|
9366
|
-
console.log(`${
|
|
9448
|
+
console.log(`${chalk98.bold("name:")} ${repoName}`);
|
|
9367
9449
|
}
|
|
9368
9450
|
function displayNextEntry(ctx, targetDate, commits2) {
|
|
9369
9451
|
logName(ctx.repoName);
|
|
9370
9452
|
printVersionInfo(ctx.config, ctx.lastInfo, commits2[0]?.hash);
|
|
9371
|
-
console.log(
|
|
9453
|
+
console.log(chalk98.bold.blue(targetDate));
|
|
9372
9454
|
printCommitsWithFiles(commits2, ctx.ignore, ctx.verbose);
|
|
9373
9455
|
}
|
|
9374
9456
|
function logNoCommits(lastInfo) {
|
|
9375
|
-
console.log(
|
|
9457
|
+
console.log(chalk98.dim(noCommitsMessage(!!lastInfo)));
|
|
9376
9458
|
}
|
|
9377
9459
|
|
|
9378
9460
|
// src/commands/devlog/next/index.ts
|
|
@@ -9413,11 +9495,11 @@ function next2(options2) {
|
|
|
9413
9495
|
import { execSync as execSync24 } from "child_process";
|
|
9414
9496
|
|
|
9415
9497
|
// src/commands/devlog/repos/printReposTable.ts
|
|
9416
|
-
import
|
|
9498
|
+
import chalk99 from "chalk";
|
|
9417
9499
|
function colorStatus(status2) {
|
|
9418
|
-
if (status2 === "missing") return
|
|
9419
|
-
if (status2 === "outdated") return
|
|
9420
|
-
return
|
|
9500
|
+
if (status2 === "missing") return chalk99.red(status2);
|
|
9501
|
+
if (status2 === "outdated") return chalk99.yellow(status2);
|
|
9502
|
+
return chalk99.green(status2);
|
|
9421
9503
|
}
|
|
9422
9504
|
function formatRow(row, nameWidth) {
|
|
9423
9505
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -9431,8 +9513,8 @@ function printReposTable(rows) {
|
|
|
9431
9513
|
"Last Devlog".padEnd(11),
|
|
9432
9514
|
"Status"
|
|
9433
9515
|
].join(" ");
|
|
9434
|
-
console.log(
|
|
9435
|
-
console.log(
|
|
9516
|
+
console.log(chalk99.dim(header));
|
|
9517
|
+
console.log(chalk99.dim("-".repeat(header.length)));
|
|
9436
9518
|
for (const row of rows) {
|
|
9437
9519
|
console.log(formatRow(row, nameWidth));
|
|
9438
9520
|
}
|
|
@@ -9490,14 +9572,14 @@ function repos(options2) {
|
|
|
9490
9572
|
// src/commands/devlog/skip.ts
|
|
9491
9573
|
import { writeFileSync as writeFileSync19 } from "fs";
|
|
9492
9574
|
import { join as join26 } from "path";
|
|
9493
|
-
import
|
|
9575
|
+
import chalk100 from "chalk";
|
|
9494
9576
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
9495
9577
|
function getBlogConfigPath() {
|
|
9496
9578
|
return join26(BLOG_REPO_ROOT, "assist.yml");
|
|
9497
9579
|
}
|
|
9498
9580
|
function skip(date) {
|
|
9499
9581
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
9500
|
-
console.log(
|
|
9582
|
+
console.log(chalk100.red("Invalid date format. Use YYYY-MM-DD"));
|
|
9501
9583
|
process.exit(1);
|
|
9502
9584
|
}
|
|
9503
9585
|
const repoName = getRepoName();
|
|
@@ -9508,7 +9590,7 @@ function skip(date) {
|
|
|
9508
9590
|
const skipDays = skip2[repoName] ?? [];
|
|
9509
9591
|
if (skipDays.includes(date)) {
|
|
9510
9592
|
console.log(
|
|
9511
|
-
|
|
9593
|
+
chalk100.yellow(`${date} is already in skip list for ${repoName}`)
|
|
9512
9594
|
);
|
|
9513
9595
|
return;
|
|
9514
9596
|
}
|
|
@@ -9518,20 +9600,20 @@ function skip(date) {
|
|
|
9518
9600
|
devlog.skip = skip2;
|
|
9519
9601
|
config.devlog = devlog;
|
|
9520
9602
|
writeFileSync19(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
9521
|
-
console.log(
|
|
9603
|
+
console.log(chalk100.green(`Added ${date} to skip list for ${repoName}`));
|
|
9522
9604
|
}
|
|
9523
9605
|
|
|
9524
9606
|
// src/commands/devlog/version.ts
|
|
9525
|
-
import
|
|
9607
|
+
import chalk101 from "chalk";
|
|
9526
9608
|
function version() {
|
|
9527
9609
|
const config = loadConfig();
|
|
9528
9610
|
const name = getRepoName();
|
|
9529
9611
|
const lastInfo = getLastVersionInfo(name, config);
|
|
9530
9612
|
const lastVersion = lastInfo?.version ?? null;
|
|
9531
9613
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
9532
|
-
console.log(`${
|
|
9533
|
-
console.log(`${
|
|
9534
|
-
console.log(`${
|
|
9614
|
+
console.log(`${chalk101.bold("name:")} ${name}`);
|
|
9615
|
+
console.log(`${chalk101.bold("last:")} ${lastVersion ?? chalk101.dim("none")}`);
|
|
9616
|
+
console.log(`${chalk101.bold("next:")} ${nextVersion ?? chalk101.dim("none")}`);
|
|
9535
9617
|
}
|
|
9536
9618
|
|
|
9537
9619
|
// src/commands/registerDevlog.ts
|
|
@@ -9555,7 +9637,7 @@ function registerDevlog(program2) {
|
|
|
9555
9637
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
9556
9638
|
import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync2 } from "fs";
|
|
9557
9639
|
import { join as join27 } from "path";
|
|
9558
|
-
import
|
|
9640
|
+
import chalk102 from "chalk";
|
|
9559
9641
|
|
|
9560
9642
|
// src/shared/findRepoRoot.ts
|
|
9561
9643
|
import { existsSync as existsSync27 } from "fs";
|
|
@@ -9618,14 +9700,14 @@ function checkBuildLocks(startDir) {
|
|
|
9618
9700
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
9619
9701
|
if (locked) {
|
|
9620
9702
|
console.error(
|
|
9621
|
-
|
|
9703
|
+
chalk102.red("Build output locked (is VS debugging?): ") + locked
|
|
9622
9704
|
);
|
|
9623
9705
|
process.exit(1);
|
|
9624
9706
|
}
|
|
9625
9707
|
}
|
|
9626
9708
|
async function checkBuildLocksCommand() {
|
|
9627
9709
|
checkBuildLocks();
|
|
9628
|
-
console.log(
|
|
9710
|
+
console.log(chalk102.green("No build locks detected"));
|
|
9629
9711
|
}
|
|
9630
9712
|
|
|
9631
9713
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -9724,30 +9806,30 @@ function escapeRegex(s) {
|
|
|
9724
9806
|
}
|
|
9725
9807
|
|
|
9726
9808
|
// src/commands/dotnet/printTree.ts
|
|
9727
|
-
import
|
|
9809
|
+
import chalk103 from "chalk";
|
|
9728
9810
|
function printNodes(nodes, prefix2) {
|
|
9729
9811
|
for (let i = 0; i < nodes.length; i++) {
|
|
9730
9812
|
const isLast = i === nodes.length - 1;
|
|
9731
9813
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
9732
9814
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
9733
9815
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
9734
|
-
const label2 = isMissing ?
|
|
9816
|
+
const label2 = isMissing ? chalk103.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
9735
9817
|
console.log(`${prefix2}${connector}${label2}`);
|
|
9736
9818
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
9737
9819
|
}
|
|
9738
9820
|
}
|
|
9739
9821
|
function printTree(tree, totalCount, solutions) {
|
|
9740
|
-
console.log(
|
|
9741
|
-
console.log(
|
|
9822
|
+
console.log(chalk103.bold("\nProject Dependency Tree"));
|
|
9823
|
+
console.log(chalk103.cyan(tree.relativePath));
|
|
9742
9824
|
printNodes(tree.children, "");
|
|
9743
|
-
console.log(
|
|
9825
|
+
console.log(chalk103.dim(`
|
|
9744
9826
|
${totalCount} projects total (including root)`));
|
|
9745
|
-
console.log(
|
|
9827
|
+
console.log(chalk103.bold("\nSolution Membership"));
|
|
9746
9828
|
if (solutions.length === 0) {
|
|
9747
|
-
console.log(
|
|
9829
|
+
console.log(chalk103.yellow(" Not found in any .sln"));
|
|
9748
9830
|
} else {
|
|
9749
9831
|
for (const sln of solutions) {
|
|
9750
|
-
console.log(` ${
|
|
9832
|
+
console.log(` ${chalk103.green(sln)}`);
|
|
9751
9833
|
}
|
|
9752
9834
|
}
|
|
9753
9835
|
console.log();
|
|
@@ -9776,16 +9858,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
9776
9858
|
// src/commands/dotnet/resolveCsproj.ts
|
|
9777
9859
|
import { existsSync as existsSync28 } from "fs";
|
|
9778
9860
|
import path23 from "path";
|
|
9779
|
-
import
|
|
9861
|
+
import chalk104 from "chalk";
|
|
9780
9862
|
function resolveCsproj(csprojPath) {
|
|
9781
9863
|
const resolved = path23.resolve(csprojPath);
|
|
9782
9864
|
if (!existsSync28(resolved)) {
|
|
9783
|
-
console.error(
|
|
9865
|
+
console.error(chalk104.red(`File not found: ${resolved}`));
|
|
9784
9866
|
process.exit(1);
|
|
9785
9867
|
}
|
|
9786
9868
|
const repoRoot = findRepoRoot(path23.dirname(resolved));
|
|
9787
9869
|
if (!repoRoot) {
|
|
9788
|
-
console.error(
|
|
9870
|
+
console.error(chalk104.red("Could not find git repository root"));
|
|
9789
9871
|
process.exit(1);
|
|
9790
9872
|
}
|
|
9791
9873
|
return { resolved, repoRoot };
|
|
@@ -9835,12 +9917,12 @@ function getChangedCsFiles(scope) {
|
|
|
9835
9917
|
}
|
|
9836
9918
|
|
|
9837
9919
|
// src/commands/dotnet/inSln.ts
|
|
9838
|
-
import
|
|
9920
|
+
import chalk105 from "chalk";
|
|
9839
9921
|
async function inSln(csprojPath) {
|
|
9840
9922
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
9841
9923
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
9842
9924
|
if (solutions.length === 0) {
|
|
9843
|
-
console.log(
|
|
9925
|
+
console.log(chalk105.yellow("Not found in any .sln file"));
|
|
9844
9926
|
process.exit(1);
|
|
9845
9927
|
}
|
|
9846
9928
|
for (const sln of solutions) {
|
|
@@ -9849,7 +9931,7 @@ async function inSln(csprojPath) {
|
|
|
9849
9931
|
}
|
|
9850
9932
|
|
|
9851
9933
|
// src/commands/dotnet/inspect.ts
|
|
9852
|
-
import
|
|
9934
|
+
import chalk111 from "chalk";
|
|
9853
9935
|
|
|
9854
9936
|
// src/shared/formatElapsed.ts
|
|
9855
9937
|
function formatElapsed(ms) {
|
|
@@ -9861,12 +9943,12 @@ function formatElapsed(ms) {
|
|
|
9861
9943
|
}
|
|
9862
9944
|
|
|
9863
9945
|
// src/commands/dotnet/displayIssues.ts
|
|
9864
|
-
import
|
|
9946
|
+
import chalk106 from "chalk";
|
|
9865
9947
|
var SEVERITY_COLOR = {
|
|
9866
|
-
ERROR:
|
|
9867
|
-
WARNING:
|
|
9868
|
-
SUGGESTION:
|
|
9869
|
-
HINT:
|
|
9948
|
+
ERROR: chalk106.red,
|
|
9949
|
+
WARNING: chalk106.yellow,
|
|
9950
|
+
SUGGESTION: chalk106.cyan,
|
|
9951
|
+
HINT: chalk106.dim
|
|
9870
9952
|
};
|
|
9871
9953
|
function groupByFile(issues) {
|
|
9872
9954
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -9882,15 +9964,15 @@ function groupByFile(issues) {
|
|
|
9882
9964
|
}
|
|
9883
9965
|
function displayIssues(issues) {
|
|
9884
9966
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
9885
|
-
console.log(
|
|
9967
|
+
console.log(chalk106.bold(file));
|
|
9886
9968
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
9887
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
9969
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk106.white;
|
|
9888
9970
|
console.log(
|
|
9889
|
-
` ${
|
|
9971
|
+
` ${chalk106.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
9890
9972
|
);
|
|
9891
9973
|
}
|
|
9892
9974
|
}
|
|
9893
|
-
console.log(
|
|
9975
|
+
console.log(chalk106.dim(`
|
|
9894
9976
|
${issues.length} issue(s) found`));
|
|
9895
9977
|
}
|
|
9896
9978
|
|
|
@@ -9949,12 +10031,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
9949
10031
|
// src/commands/dotnet/resolveSolution.ts
|
|
9950
10032
|
import { existsSync as existsSync29 } from "fs";
|
|
9951
10033
|
import path24 from "path";
|
|
9952
|
-
import
|
|
10034
|
+
import chalk108 from "chalk";
|
|
9953
10035
|
|
|
9954
10036
|
// src/commands/dotnet/findSolution.ts
|
|
9955
10037
|
import { readdirSync as readdirSync4 } from "fs";
|
|
9956
10038
|
import { dirname as dirname18, join as join28 } from "path";
|
|
9957
|
-
import
|
|
10039
|
+
import chalk107 from "chalk";
|
|
9958
10040
|
function findSlnInDir(dir) {
|
|
9959
10041
|
try {
|
|
9960
10042
|
return readdirSync4(dir).filter((f) => f.endsWith(".sln")).map((f) => join28(dir, f));
|
|
@@ -9970,17 +10052,17 @@ function findSolution() {
|
|
|
9970
10052
|
const slnFiles = findSlnInDir(current);
|
|
9971
10053
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
9972
10054
|
if (slnFiles.length > 1) {
|
|
9973
|
-
console.error(
|
|
10055
|
+
console.error(chalk107.red(`Multiple .sln files found in ${current}:`));
|
|
9974
10056
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
9975
10057
|
console.error(
|
|
9976
|
-
|
|
10058
|
+
chalk107.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
9977
10059
|
);
|
|
9978
10060
|
process.exit(1);
|
|
9979
10061
|
}
|
|
9980
10062
|
if (current === ceiling) break;
|
|
9981
10063
|
current = dirname18(current);
|
|
9982
10064
|
}
|
|
9983
|
-
console.error(
|
|
10065
|
+
console.error(chalk107.red("No .sln file found between cwd and repo root"));
|
|
9984
10066
|
process.exit(1);
|
|
9985
10067
|
}
|
|
9986
10068
|
|
|
@@ -9989,7 +10071,7 @@ function resolveSolution(sln) {
|
|
|
9989
10071
|
if (sln) {
|
|
9990
10072
|
const resolved = path24.resolve(sln);
|
|
9991
10073
|
if (!existsSync29(resolved)) {
|
|
9992
|
-
console.error(
|
|
10074
|
+
console.error(chalk108.red(`Solution file not found: ${resolved}`));
|
|
9993
10075
|
process.exit(1);
|
|
9994
10076
|
}
|
|
9995
10077
|
return resolved;
|
|
@@ -10031,14 +10113,14 @@ import { execSync as execSync26 } from "child_process";
|
|
|
10031
10113
|
import { existsSync as existsSync30, readFileSync as readFileSync24, unlinkSync as unlinkSync7 } from "fs";
|
|
10032
10114
|
import { tmpdir as tmpdir3 } from "os";
|
|
10033
10115
|
import path25 from "path";
|
|
10034
|
-
import
|
|
10116
|
+
import chalk109 from "chalk";
|
|
10035
10117
|
function assertJbInstalled() {
|
|
10036
10118
|
try {
|
|
10037
10119
|
execSync26("jb inspectcode --version", { stdio: "pipe" });
|
|
10038
10120
|
} catch {
|
|
10039
|
-
console.error(
|
|
10121
|
+
console.error(chalk109.red("jb is not installed. Install with:"));
|
|
10040
10122
|
console.error(
|
|
10041
|
-
|
|
10123
|
+
chalk109.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
10042
10124
|
);
|
|
10043
10125
|
process.exit(1);
|
|
10044
10126
|
}
|
|
@@ -10056,11 +10138,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
10056
10138
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
10057
10139
|
process.stderr.write(err.stderr);
|
|
10058
10140
|
}
|
|
10059
|
-
console.error(
|
|
10141
|
+
console.error(chalk109.red("jb inspectcode failed"));
|
|
10060
10142
|
process.exit(1);
|
|
10061
10143
|
}
|
|
10062
10144
|
if (!existsSync30(reportPath)) {
|
|
10063
|
-
console.error(
|
|
10145
|
+
console.error(chalk109.red("Report file not generated"));
|
|
10064
10146
|
process.exit(1);
|
|
10065
10147
|
}
|
|
10066
10148
|
const xml = readFileSync24(reportPath, "utf-8");
|
|
@@ -10070,7 +10152,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
10070
10152
|
|
|
10071
10153
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
10072
10154
|
import { execSync as execSync27 } from "child_process";
|
|
10073
|
-
import
|
|
10155
|
+
import chalk110 from "chalk";
|
|
10074
10156
|
function resolveMsbuildPath() {
|
|
10075
10157
|
const { run: run4 } = loadConfig();
|
|
10076
10158
|
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
@@ -10082,9 +10164,9 @@ function assertMsbuildInstalled() {
|
|
|
10082
10164
|
try {
|
|
10083
10165
|
execSync27(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
10084
10166
|
} catch {
|
|
10085
|
-
console.error(
|
|
10167
|
+
console.error(chalk110.red(`msbuild not found at: ${msbuild}`));
|
|
10086
10168
|
console.error(
|
|
10087
|
-
|
|
10169
|
+
chalk110.yellow(
|
|
10088
10170
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
10089
10171
|
)
|
|
10090
10172
|
);
|
|
@@ -10131,17 +10213,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
10131
10213
|
// src/commands/dotnet/inspect.ts
|
|
10132
10214
|
function logScope(changedFiles) {
|
|
10133
10215
|
if (changedFiles === null) {
|
|
10134
|
-
console.log(
|
|
10216
|
+
console.log(chalk111.dim("Inspecting full solution..."));
|
|
10135
10217
|
} else {
|
|
10136
10218
|
console.log(
|
|
10137
|
-
|
|
10219
|
+
chalk111.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
10138
10220
|
);
|
|
10139
10221
|
}
|
|
10140
10222
|
}
|
|
10141
10223
|
function reportResults(issues, elapsed) {
|
|
10142
10224
|
if (issues.length > 0) displayIssues(issues);
|
|
10143
|
-
else console.log(
|
|
10144
|
-
console.log(
|
|
10225
|
+
else console.log(chalk111.green("No issues found"));
|
|
10226
|
+
console.log(chalk111.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
10145
10227
|
if (issues.length > 0) process.exit(1);
|
|
10146
10228
|
}
|
|
10147
10229
|
async function inspect(sln, options2) {
|
|
@@ -10152,7 +10234,7 @@ async function inspect(sln, options2) {
|
|
|
10152
10234
|
const scope = parseScope(options2.scope);
|
|
10153
10235
|
const changedFiles = getChangedCsFiles(scope);
|
|
10154
10236
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
10155
|
-
console.log(
|
|
10237
|
+
console.log(chalk111.green("No changed .cs files found"));
|
|
10156
10238
|
return;
|
|
10157
10239
|
}
|
|
10158
10240
|
logScope(changedFiles);
|
|
@@ -10281,25 +10363,25 @@ function fetchRepoCommitAuthors(org, repo, since) {
|
|
|
10281
10363
|
}
|
|
10282
10364
|
|
|
10283
10365
|
// src/commands/github/printCountTable.ts
|
|
10284
|
-
import
|
|
10366
|
+
import chalk112 from "chalk";
|
|
10285
10367
|
function printCountTable(labelHeader, rows) {
|
|
10286
10368
|
const labelWidth = Math.max(
|
|
10287
10369
|
labelHeader.length,
|
|
10288
10370
|
...rows.map((row) => row.label.length)
|
|
10289
10371
|
);
|
|
10290
10372
|
const header = `${labelHeader.padEnd(labelWidth)} Commits`;
|
|
10291
|
-
console.log(
|
|
10292
|
-
console.log(
|
|
10373
|
+
console.log(chalk112.dim(header));
|
|
10374
|
+
console.log(chalk112.dim("-".repeat(header.length)));
|
|
10293
10375
|
for (const row of rows) {
|
|
10294
10376
|
console.log(`${row.label.padEnd(labelWidth)} ${row.count}`);
|
|
10295
10377
|
}
|
|
10296
10378
|
}
|
|
10297
10379
|
|
|
10298
10380
|
// src/commands/github/printRepoAuthorBreakdown.ts
|
|
10299
|
-
import
|
|
10381
|
+
import chalk113 from "chalk";
|
|
10300
10382
|
function printRepoAuthorBreakdown(repos2) {
|
|
10301
10383
|
for (const repo of repos2) {
|
|
10302
|
-
console.log(
|
|
10384
|
+
console.log(chalk113.bold(repo.name));
|
|
10303
10385
|
const authorWidth = Math.max(
|
|
10304
10386
|
0,
|
|
10305
10387
|
...repo.authors.map((a) => a.author.length)
|
|
@@ -10624,7 +10706,7 @@ function registerHandover(program2) {
|
|
|
10624
10706
|
}
|
|
10625
10707
|
|
|
10626
10708
|
// src/commands/jira/acceptanceCriteria.ts
|
|
10627
|
-
import
|
|
10709
|
+
import chalk115 from "chalk";
|
|
10628
10710
|
|
|
10629
10711
|
// src/commands/jira/adfToText.ts
|
|
10630
10712
|
function renderInline(node) {
|
|
@@ -10685,7 +10767,7 @@ function adfToText(doc) {
|
|
|
10685
10767
|
|
|
10686
10768
|
// src/commands/jira/fetchIssue.ts
|
|
10687
10769
|
import { execSync as execSync28 } from "child_process";
|
|
10688
|
-
import
|
|
10770
|
+
import chalk114 from "chalk";
|
|
10689
10771
|
function fetchIssue(issueKey, fields) {
|
|
10690
10772
|
let result;
|
|
10691
10773
|
try {
|
|
@@ -10698,15 +10780,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
10698
10780
|
const stderr = error.stderr;
|
|
10699
10781
|
if (stderr.includes("unauthorized")) {
|
|
10700
10782
|
console.error(
|
|
10701
|
-
|
|
10783
|
+
chalk114.red("Jira authentication expired."),
|
|
10702
10784
|
"Run",
|
|
10703
|
-
|
|
10785
|
+
chalk114.cyan("assist jira auth"),
|
|
10704
10786
|
"to re-authenticate."
|
|
10705
10787
|
);
|
|
10706
10788
|
process.exit(1);
|
|
10707
10789
|
}
|
|
10708
10790
|
}
|
|
10709
|
-
console.error(
|
|
10791
|
+
console.error(chalk114.red(`Failed to fetch ${issueKey}.`));
|
|
10710
10792
|
process.exit(1);
|
|
10711
10793
|
}
|
|
10712
10794
|
return JSON.parse(result);
|
|
@@ -10720,7 +10802,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
10720
10802
|
const parsed = fetchIssue(issueKey, field);
|
|
10721
10803
|
const acValue = parsed?.fields?.[field];
|
|
10722
10804
|
if (!acValue) {
|
|
10723
|
-
console.log(
|
|
10805
|
+
console.log(chalk115.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
10724
10806
|
return;
|
|
10725
10807
|
}
|
|
10726
10808
|
if (typeof acValue === "string") {
|
|
@@ -10815,14 +10897,14 @@ async function jiraAuth() {
|
|
|
10815
10897
|
}
|
|
10816
10898
|
|
|
10817
10899
|
// src/commands/jira/viewIssue.ts
|
|
10818
|
-
import
|
|
10900
|
+
import chalk116 from "chalk";
|
|
10819
10901
|
function viewIssue(issueKey) {
|
|
10820
10902
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
10821
10903
|
const fields = parsed?.fields;
|
|
10822
10904
|
const summary = fields?.summary;
|
|
10823
10905
|
const description = fields?.description;
|
|
10824
10906
|
if (summary) {
|
|
10825
|
-
console.log(
|
|
10907
|
+
console.log(chalk116.bold(summary));
|
|
10826
10908
|
}
|
|
10827
10909
|
if (description) {
|
|
10828
10910
|
if (summary) console.log();
|
|
@@ -10836,7 +10918,7 @@ function viewIssue(issueKey) {
|
|
|
10836
10918
|
}
|
|
10837
10919
|
if (!summary && !description) {
|
|
10838
10920
|
console.log(
|
|
10839
|
-
|
|
10921
|
+
chalk116.yellow(`No summary or description found on ${issueKey}.`)
|
|
10840
10922
|
);
|
|
10841
10923
|
}
|
|
10842
10924
|
}
|
|
@@ -10851,13 +10933,13 @@ function registerJira(program2) {
|
|
|
10851
10933
|
|
|
10852
10934
|
// src/commands/reviewComments.ts
|
|
10853
10935
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
10854
|
-
import
|
|
10936
|
+
import chalk117 from "chalk";
|
|
10855
10937
|
async function reviewComments(number) {
|
|
10856
10938
|
if (number) {
|
|
10857
10939
|
try {
|
|
10858
10940
|
execFileSync6("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
10859
10941
|
} catch {
|
|
10860
|
-
console.error(
|
|
10942
|
+
console.error(chalk117.red(`gh pr checkout ${number} failed; aborting.`));
|
|
10861
10943
|
process.exit(1);
|
|
10862
10944
|
}
|
|
10863
10945
|
}
|
|
@@ -10870,7 +10952,7 @@ async function reviewComments(number) {
|
|
|
10870
10952
|
// src/commands/registerLaunch.ts
|
|
10871
10953
|
function registerLaunch(program2) {
|
|
10872
10954
|
program2.command("next").argument("[id]", "Backlog item ID to run first").description("Alias for backlog next").option("--once", "Exit after the first completed item run").action(
|
|
10873
|
-
(
|
|
10955
|
+
(id2, opts) => next({ allowEdits: true, once: opts.once }, id2)
|
|
10874
10956
|
);
|
|
10875
10957
|
program2.command("draft").alias("feat").argument("[description]", "Text to forward to the /draft slash command").description(
|
|
10876
10958
|
"Launch Claude in /draft mode, chain into next on /next signal"
|
|
@@ -10882,7 +10964,7 @@ function registerLaunch(program2) {
|
|
|
10882
10964
|
);
|
|
10883
10965
|
program2.command("review-comments").argument("[number]", "PR number to check out first").description("Launch Claude in /review-comments mode (single session)").action((number) => reviewComments(number));
|
|
10884
10966
|
program2.command("refine").argument("[id]", "Backlog item ID").description("Launch Claude in /refine mode to refine a backlog item").option("--once", "Exit when the initial task completes").action(
|
|
10885
|
-
(
|
|
10967
|
+
(id2, opts) => refine(id2, { once: opts.once })
|
|
10886
10968
|
);
|
|
10887
10969
|
}
|
|
10888
10970
|
|
|
@@ -10900,15 +10982,15 @@ function registerList(program2) {
|
|
|
10900
10982
|
// src/commands/mermaid/index.ts
|
|
10901
10983
|
import { mkdirSync as mkdirSync12, readdirSync as readdirSync5 } from "fs";
|
|
10902
10984
|
import { resolve as resolve10 } from "path";
|
|
10903
|
-
import
|
|
10985
|
+
import chalk120 from "chalk";
|
|
10904
10986
|
|
|
10905
10987
|
// src/commands/mermaid/exportFile.ts
|
|
10906
10988
|
import { readFileSync as readFileSync28, writeFileSync as writeFileSync22 } from "fs";
|
|
10907
10989
|
import { basename as basename5, extname, resolve as resolve9 } from "path";
|
|
10908
|
-
import
|
|
10990
|
+
import chalk119 from "chalk";
|
|
10909
10991
|
|
|
10910
10992
|
// src/commands/mermaid/renderBlock.ts
|
|
10911
|
-
import
|
|
10993
|
+
import chalk118 from "chalk";
|
|
10912
10994
|
async function renderBlock(krokiUrl, source) {
|
|
10913
10995
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
10914
10996
|
method: "POST",
|
|
@@ -10917,7 +10999,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
10917
10999
|
});
|
|
10918
11000
|
if (!response.ok) {
|
|
10919
11001
|
console.error(
|
|
10920
|
-
|
|
11002
|
+
chalk118.red(
|
|
10921
11003
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
10922
11004
|
)
|
|
10923
11005
|
);
|
|
@@ -10935,19 +11017,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
10935
11017
|
if (onlyIndex !== void 0) {
|
|
10936
11018
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
10937
11019
|
console.error(
|
|
10938
|
-
|
|
11020
|
+
chalk119.red(
|
|
10939
11021
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
10940
11022
|
)
|
|
10941
11023
|
);
|
|
10942
11024
|
process.exit(1);
|
|
10943
11025
|
}
|
|
10944
11026
|
console.log(
|
|
10945
|
-
|
|
11027
|
+
chalk119.gray(
|
|
10946
11028
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
10947
11029
|
)
|
|
10948
11030
|
);
|
|
10949
11031
|
} else {
|
|
10950
|
-
console.log(
|
|
11032
|
+
console.log(chalk119.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
10951
11033
|
}
|
|
10952
11034
|
for (const [i, source] of blocks.entries()) {
|
|
10953
11035
|
const idx = i + 1;
|
|
@@ -10955,7 +11037,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
10955
11037
|
const outPath = resolve9(outDir, `${stem}-${idx}.svg`);
|
|
10956
11038
|
const svg = await renderBlock(krokiUrl, source);
|
|
10957
11039
|
writeFileSync22(outPath, svg, "utf8");
|
|
10958
|
-
console.log(
|
|
11040
|
+
console.log(chalk119.green(` \u2192 ${outPath}`));
|
|
10959
11041
|
}
|
|
10960
11042
|
}
|
|
10961
11043
|
function extractMermaidBlocks(markdown) {
|
|
@@ -10971,18 +11053,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
10971
11053
|
if (options2.index !== void 0) {
|
|
10972
11054
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
10973
11055
|
console.error(
|
|
10974
|
-
|
|
11056
|
+
chalk120.red(`--index must be a positive integer (got ${options2.index})`)
|
|
10975
11057
|
);
|
|
10976
11058
|
process.exit(1);
|
|
10977
11059
|
}
|
|
10978
11060
|
if (!file) {
|
|
10979
|
-
console.error(
|
|
11061
|
+
console.error(chalk120.red("--index requires a file argument"));
|
|
10980
11062
|
process.exit(1);
|
|
10981
11063
|
}
|
|
10982
11064
|
}
|
|
10983
11065
|
const files = file ? [file] : readdirSync5(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
10984
11066
|
if (files.length === 0) {
|
|
10985
|
-
console.log(
|
|
11067
|
+
console.log(chalk120.gray("No markdown files found in current directory."));
|
|
10986
11068
|
return;
|
|
10987
11069
|
}
|
|
10988
11070
|
for (const f of files) {
|
|
@@ -11005,7 +11087,7 @@ function registerMermaid(program2) {
|
|
|
11005
11087
|
}
|
|
11006
11088
|
|
|
11007
11089
|
// src/commands/news/add/index.ts
|
|
11008
|
-
import
|
|
11090
|
+
import chalk121 from "chalk";
|
|
11009
11091
|
import enquirer8 from "enquirer";
|
|
11010
11092
|
async function add2(url) {
|
|
11011
11093
|
if (!url) {
|
|
@@ -11027,10 +11109,10 @@ async function add2(url) {
|
|
|
11027
11109
|
const { orm } = await getReady();
|
|
11028
11110
|
const added = await addFeed(orm, url);
|
|
11029
11111
|
if (!added) {
|
|
11030
|
-
console.log(
|
|
11112
|
+
console.log(chalk121.yellow("Feed already exists"));
|
|
11031
11113
|
return;
|
|
11032
11114
|
}
|
|
11033
|
-
console.log(
|
|
11115
|
+
console.log(chalk121.green(`Added feed: ${url}`));
|
|
11034
11116
|
}
|
|
11035
11117
|
|
|
11036
11118
|
// src/commands/registerNews.ts
|
|
@@ -11040,7 +11122,7 @@ function registerNews(program2) {
|
|
|
11040
11122
|
}
|
|
11041
11123
|
|
|
11042
11124
|
// src/commands/prompts/printPromptsTable.ts
|
|
11043
|
-
import
|
|
11125
|
+
import chalk122 from "chalk";
|
|
11044
11126
|
function truncate(str, max) {
|
|
11045
11127
|
if (str.length <= max) return str;
|
|
11046
11128
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -11058,14 +11140,14 @@ function printPromptsTable(rows) {
|
|
|
11058
11140
|
"Command".padEnd(commandWidth),
|
|
11059
11141
|
"Repos"
|
|
11060
11142
|
].join(" ");
|
|
11061
|
-
console.log(
|
|
11062
|
-
console.log(
|
|
11143
|
+
console.log(chalk122.dim(header));
|
|
11144
|
+
console.log(chalk122.dim("-".repeat(header.length)));
|
|
11063
11145
|
for (const row of rows) {
|
|
11064
11146
|
const count6 = String(row.count).padStart(countWidth);
|
|
11065
11147
|
const tool = row.tool.padEnd(toolWidth);
|
|
11066
11148
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
11067
11149
|
console.log(
|
|
11068
|
-
`${
|
|
11150
|
+
`${chalk122.yellow(count6)} ${tool} ${command} ${chalk122.dim(row.repos)}`
|
|
11069
11151
|
);
|
|
11070
11152
|
}
|
|
11071
11153
|
}
|
|
@@ -11197,8 +11279,8 @@ function assertThreadCreated(stdout) {
|
|
|
11197
11279
|
} catch {
|
|
11198
11280
|
throw new Error(`GitHub returned an unparseable response: ${stdout}`);
|
|
11199
11281
|
}
|
|
11200
|
-
const
|
|
11201
|
-
if (typeof
|
|
11282
|
+
const id2 = parsed.data?.addPullRequestReviewThread?.thread?.id;
|
|
11283
|
+
if (typeof id2 !== "string" || id2.length === 0) {
|
|
11202
11284
|
throw new Error(
|
|
11203
11285
|
"GitHub did not create a review thread (no thread id returned); the line is likely outside the PR diff."
|
|
11204
11286
|
);
|
|
@@ -11611,20 +11693,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
11611
11693
|
}
|
|
11612
11694
|
|
|
11613
11695
|
// src/commands/prs/listComments/printComments.ts
|
|
11614
|
-
import
|
|
11696
|
+
import chalk123 from "chalk";
|
|
11615
11697
|
function formatForHuman(comment3) {
|
|
11616
11698
|
if (comment3.type === "review") {
|
|
11617
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
11699
|
+
const stateColor = comment3.state === "APPROVED" ? chalk123.green : comment3.state === "CHANGES_REQUESTED" ? chalk123.red : chalk123.yellow;
|
|
11618
11700
|
return [
|
|
11619
|
-
`${
|
|
11701
|
+
`${chalk123.cyan("Review")} by ${chalk123.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
11620
11702
|
comment3.body,
|
|
11621
11703
|
""
|
|
11622
11704
|
].join("\n");
|
|
11623
11705
|
}
|
|
11624
11706
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
11625
11707
|
return [
|
|
11626
|
-
`${
|
|
11627
|
-
|
|
11708
|
+
`${chalk123.cyan("Line comment")} by ${chalk123.bold(comment3.user)} on ${chalk123.dim(`${comment3.path}${location}`)}`,
|
|
11709
|
+
chalk123.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
11628
11710
|
comment3.body,
|
|
11629
11711
|
""
|
|
11630
11712
|
].join("\n");
|
|
@@ -11714,13 +11796,13 @@ import { execSync as execSync36 } from "child_process";
|
|
|
11714
11796
|
import enquirer9 from "enquirer";
|
|
11715
11797
|
|
|
11716
11798
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
11717
|
-
import
|
|
11799
|
+
import chalk124 from "chalk";
|
|
11718
11800
|
var STATUS_MAP = {
|
|
11719
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
11720
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
11801
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk124.magenta("merged"), date: pr.mergedAt } : null,
|
|
11802
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk124.red("closed"), date: pr.closedAt } : null
|
|
11721
11803
|
};
|
|
11722
11804
|
function defaultStatus(pr) {
|
|
11723
|
-
return { label:
|
|
11805
|
+
return { label: chalk124.green("opened"), date: pr.createdAt };
|
|
11724
11806
|
}
|
|
11725
11807
|
function getStatus2(pr) {
|
|
11726
11808
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -11729,11 +11811,11 @@ function formatDate(dateStr) {
|
|
|
11729
11811
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
11730
11812
|
}
|
|
11731
11813
|
function formatPrHeader(pr, status2) {
|
|
11732
|
-
return `${
|
|
11814
|
+
return `${chalk124.cyan(`#${pr.number}`)} ${pr.title} ${chalk124.dim(`(${pr.author.login},`)} ${status2.label} ${chalk124.dim(`${formatDate(status2.date)})`)}`;
|
|
11733
11815
|
}
|
|
11734
11816
|
function logPrDetails(pr) {
|
|
11735
11817
|
console.log(
|
|
11736
|
-
|
|
11818
|
+
chalk124.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
11737
11819
|
);
|
|
11738
11820
|
console.log();
|
|
11739
11821
|
}
|
|
@@ -12012,10 +12094,10 @@ function registerPrs(program2) {
|
|
|
12012
12094
|
}
|
|
12013
12095
|
|
|
12014
12096
|
// src/commands/ravendb/ravendbAuth.ts
|
|
12015
|
-
import
|
|
12097
|
+
import chalk130 from "chalk";
|
|
12016
12098
|
|
|
12017
12099
|
// src/shared/createConnectionAuth.ts
|
|
12018
|
-
import
|
|
12100
|
+
import chalk125 from "chalk";
|
|
12019
12101
|
function listConnections(connections, format2) {
|
|
12020
12102
|
if (connections.length === 0) {
|
|
12021
12103
|
console.log("No connections configured.");
|
|
@@ -12028,7 +12110,7 @@ function listConnections(connections, format2) {
|
|
|
12028
12110
|
function removeConnection(connections, name, save) {
|
|
12029
12111
|
const filtered = connections.filter((c) => c.name !== name);
|
|
12030
12112
|
if (filtered.length === connections.length) {
|
|
12031
|
-
console.error(
|
|
12113
|
+
console.error(chalk125.red(`Connection "${name}" not found.`));
|
|
12032
12114
|
process.exit(1);
|
|
12033
12115
|
}
|
|
12034
12116
|
save(filtered);
|
|
@@ -12074,15 +12156,15 @@ function saveConnections(connections) {
|
|
|
12074
12156
|
}
|
|
12075
12157
|
|
|
12076
12158
|
// src/commands/ravendb/promptConnection.ts
|
|
12077
|
-
import
|
|
12159
|
+
import chalk128 from "chalk";
|
|
12078
12160
|
|
|
12079
12161
|
// src/commands/ravendb/selectOpSecret.ts
|
|
12080
|
-
import
|
|
12162
|
+
import chalk127 from "chalk";
|
|
12081
12163
|
import Enquirer2 from "enquirer";
|
|
12082
12164
|
|
|
12083
12165
|
// src/commands/ravendb/searchItems.ts
|
|
12084
12166
|
import { execSync as execSync39 } from "child_process";
|
|
12085
|
-
import
|
|
12167
|
+
import chalk126 from "chalk";
|
|
12086
12168
|
function opExec(args) {
|
|
12087
12169
|
return execSync39(`op ${args}`, {
|
|
12088
12170
|
encoding: "utf-8",
|
|
@@ -12095,7 +12177,7 @@ function searchItems(search2) {
|
|
|
12095
12177
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
12096
12178
|
} catch {
|
|
12097
12179
|
console.error(
|
|
12098
|
-
|
|
12180
|
+
chalk126.red(
|
|
12099
12181
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
12100
12182
|
)
|
|
12101
12183
|
);
|
|
@@ -12109,7 +12191,7 @@ function getItemFields(itemId) {
|
|
|
12109
12191
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
12110
12192
|
return item.fields.filter((f) => f.reference && f.label);
|
|
12111
12193
|
} catch {
|
|
12112
|
-
console.error(
|
|
12194
|
+
console.error(chalk126.red("Failed to get item details from 1Password."));
|
|
12113
12195
|
process.exit(1);
|
|
12114
12196
|
}
|
|
12115
12197
|
}
|
|
@@ -12128,7 +12210,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
12128
12210
|
}).run();
|
|
12129
12211
|
const items2 = searchItems(search2);
|
|
12130
12212
|
if (items2.length === 0) {
|
|
12131
|
-
console.error(
|
|
12213
|
+
console.error(chalk127.red(`No items found matching "${search2}".`));
|
|
12132
12214
|
process.exit(1);
|
|
12133
12215
|
}
|
|
12134
12216
|
const itemId = await selectOne(
|
|
@@ -12137,7 +12219,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
12137
12219
|
);
|
|
12138
12220
|
const fields = getItemFields(itemId);
|
|
12139
12221
|
if (fields.length === 0) {
|
|
12140
|
-
console.error(
|
|
12222
|
+
console.error(chalk127.red("No fields with references found on this item."));
|
|
12141
12223
|
process.exit(1);
|
|
12142
12224
|
}
|
|
12143
12225
|
const ref = await selectOne(
|
|
@@ -12151,7 +12233,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
12151
12233
|
async function promptConnection(existingNames) {
|
|
12152
12234
|
const name = await promptInput("name", "Connection name:");
|
|
12153
12235
|
if (existingNames.includes(name)) {
|
|
12154
|
-
console.error(
|
|
12236
|
+
console.error(chalk128.red(`Connection "${name}" already exists.`));
|
|
12155
12237
|
process.exit(1);
|
|
12156
12238
|
}
|
|
12157
12239
|
const url = await promptInput(
|
|
@@ -12160,22 +12242,22 @@ async function promptConnection(existingNames) {
|
|
|
12160
12242
|
);
|
|
12161
12243
|
const database = await promptInput("database", "Database name:");
|
|
12162
12244
|
if (!name || !url || !database) {
|
|
12163
|
-
console.error(
|
|
12245
|
+
console.error(chalk128.red("All fields are required."));
|
|
12164
12246
|
process.exit(1);
|
|
12165
12247
|
}
|
|
12166
12248
|
const apiKeyRef = await selectOpSecret();
|
|
12167
|
-
console.log(
|
|
12249
|
+
console.log(chalk128.dim(`Using: ${apiKeyRef}`));
|
|
12168
12250
|
return { name, url, database, apiKeyRef };
|
|
12169
12251
|
}
|
|
12170
12252
|
|
|
12171
12253
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
12172
|
-
import
|
|
12254
|
+
import chalk129 from "chalk";
|
|
12173
12255
|
function ravendbSetConnection(name) {
|
|
12174
12256
|
const raw = loadGlobalConfigRaw();
|
|
12175
12257
|
const ravendb = raw.ravendb ?? {};
|
|
12176
12258
|
const connections = ravendb.connections ?? [];
|
|
12177
12259
|
if (!connections.some((c) => c.name === name)) {
|
|
12178
|
-
console.error(
|
|
12260
|
+
console.error(chalk129.red(`Connection "${name}" not found.`));
|
|
12179
12261
|
console.error(
|
|
12180
12262
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
12181
12263
|
);
|
|
@@ -12191,16 +12273,16 @@ function ravendbSetConnection(name) {
|
|
|
12191
12273
|
var ravendbAuth = createConnectionAuth({
|
|
12192
12274
|
load: loadConnections,
|
|
12193
12275
|
save: saveConnections,
|
|
12194
|
-
format: (c) => `${
|
|
12276
|
+
format: (c) => `${chalk130.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
12195
12277
|
promptNew: promptConnection,
|
|
12196
12278
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
12197
12279
|
});
|
|
12198
12280
|
|
|
12199
12281
|
// src/commands/ravendb/ravendbCollections.ts
|
|
12200
|
-
import
|
|
12282
|
+
import chalk134 from "chalk";
|
|
12201
12283
|
|
|
12202
12284
|
// src/commands/ravendb/ravenFetch.ts
|
|
12203
|
-
import
|
|
12285
|
+
import chalk132 from "chalk";
|
|
12204
12286
|
|
|
12205
12287
|
// src/commands/ravendb/getAccessToken.ts
|
|
12206
12288
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -12237,10 +12319,10 @@ ${errorText}`
|
|
|
12237
12319
|
|
|
12238
12320
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
12239
12321
|
import { execSync as execSync40 } from "child_process";
|
|
12240
|
-
import
|
|
12322
|
+
import chalk131 from "chalk";
|
|
12241
12323
|
function resolveOpSecret(reference) {
|
|
12242
12324
|
if (!reference.startsWith("op://")) {
|
|
12243
|
-
console.error(
|
|
12325
|
+
console.error(chalk131.red(`Invalid secret reference: must start with op://`));
|
|
12244
12326
|
process.exit(1);
|
|
12245
12327
|
}
|
|
12246
12328
|
try {
|
|
@@ -12250,7 +12332,7 @@ function resolveOpSecret(reference) {
|
|
|
12250
12332
|
}).trim();
|
|
12251
12333
|
} catch {
|
|
12252
12334
|
console.error(
|
|
12253
|
-
|
|
12335
|
+
chalk131.red(
|
|
12254
12336
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
12255
12337
|
)
|
|
12256
12338
|
);
|
|
@@ -12277,7 +12359,7 @@ async function ravenFetch(connection, path56) {
|
|
|
12277
12359
|
if (!response.ok) {
|
|
12278
12360
|
const body = await response.text();
|
|
12279
12361
|
console.error(
|
|
12280
|
-
|
|
12362
|
+
chalk132.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
12281
12363
|
);
|
|
12282
12364
|
console.error(body.substring(0, 500));
|
|
12283
12365
|
process.exit(1);
|
|
@@ -12286,7 +12368,7 @@ async function ravenFetch(connection, path56) {
|
|
|
12286
12368
|
}
|
|
12287
12369
|
|
|
12288
12370
|
// src/commands/ravendb/resolveConnection.ts
|
|
12289
|
-
import
|
|
12371
|
+
import chalk133 from "chalk";
|
|
12290
12372
|
function loadRavendb() {
|
|
12291
12373
|
const raw = loadGlobalConfigRaw();
|
|
12292
12374
|
const ravendb = raw.ravendb;
|
|
@@ -12300,7 +12382,7 @@ function resolveConnection(name) {
|
|
|
12300
12382
|
const connectionName = name ?? defaultConnection;
|
|
12301
12383
|
if (!connectionName) {
|
|
12302
12384
|
console.error(
|
|
12303
|
-
|
|
12385
|
+
chalk133.red(
|
|
12304
12386
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
12305
12387
|
)
|
|
12306
12388
|
);
|
|
@@ -12308,7 +12390,7 @@ function resolveConnection(name) {
|
|
|
12308
12390
|
}
|
|
12309
12391
|
const connection = connections.find((c) => c.name === connectionName);
|
|
12310
12392
|
if (!connection) {
|
|
12311
|
-
console.error(
|
|
12393
|
+
console.error(chalk133.red(`Connection "${connectionName}" not found.`));
|
|
12312
12394
|
console.error(
|
|
12313
12395
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
12314
12396
|
);
|
|
@@ -12339,15 +12421,15 @@ async function ravendbCollections(connectionName) {
|
|
|
12339
12421
|
return;
|
|
12340
12422
|
}
|
|
12341
12423
|
for (const c of collections) {
|
|
12342
|
-
console.log(`${
|
|
12424
|
+
console.log(`${chalk134.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
12343
12425
|
}
|
|
12344
12426
|
}
|
|
12345
12427
|
|
|
12346
12428
|
// src/commands/ravendb/ravendbQuery.ts
|
|
12347
|
-
import
|
|
12429
|
+
import chalk136 from "chalk";
|
|
12348
12430
|
|
|
12349
12431
|
// src/commands/ravendb/fetchAllPages.ts
|
|
12350
|
-
import
|
|
12432
|
+
import chalk135 from "chalk";
|
|
12351
12433
|
|
|
12352
12434
|
// src/commands/ravendb/buildQueryPath.ts
|
|
12353
12435
|
function buildQueryPath(opts) {
|
|
@@ -12385,7 +12467,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
12385
12467
|
allResults.push(...results);
|
|
12386
12468
|
start3 += results.length;
|
|
12387
12469
|
process.stderr.write(
|
|
12388
|
-
`\r${
|
|
12470
|
+
`\r${chalk135.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
12389
12471
|
);
|
|
12390
12472
|
if (start3 >= totalResults) break;
|
|
12391
12473
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -12400,7 +12482,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
12400
12482
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
12401
12483
|
const resolved = resolveArgs(connectionName, collection);
|
|
12402
12484
|
if (!resolved.collection && !options2.query) {
|
|
12403
|
-
console.error(
|
|
12485
|
+
console.error(chalk136.red("Provide a collection name or --query filter."));
|
|
12404
12486
|
process.exit(1);
|
|
12405
12487
|
}
|
|
12406
12488
|
const { collection: col } = resolved;
|
|
@@ -12438,7 +12520,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
12438
12520
|
import * as path26 from "path";
|
|
12439
12521
|
|
|
12440
12522
|
// src/commands/refactor/logViolations.ts
|
|
12441
|
-
import
|
|
12523
|
+
import chalk137 from "chalk";
|
|
12442
12524
|
var DEFAULT_MAX_LINES = 100;
|
|
12443
12525
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
12444
12526
|
if (violations.length === 0) {
|
|
@@ -12447,43 +12529,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
12447
12529
|
}
|
|
12448
12530
|
return;
|
|
12449
12531
|
}
|
|
12450
|
-
console.error(
|
|
12532
|
+
console.error(chalk137.red(`
|
|
12451
12533
|
Refactor check failed:
|
|
12452
12534
|
`));
|
|
12453
|
-
console.error(
|
|
12535
|
+
console.error(chalk137.red(` The following files exceed ${maxLines} lines:
|
|
12454
12536
|
`));
|
|
12455
12537
|
for (const violation of violations) {
|
|
12456
|
-
console.error(
|
|
12538
|
+
console.error(chalk137.red(` ${violation.file} (${violation.lines} lines)`));
|
|
12457
12539
|
}
|
|
12458
12540
|
console.error(
|
|
12459
|
-
|
|
12541
|
+
chalk137.yellow(
|
|
12460
12542
|
`
|
|
12461
12543
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
12462
12544
|
way to refactor it, ignore it with:
|
|
12463
12545
|
`
|
|
12464
12546
|
)
|
|
12465
12547
|
);
|
|
12466
|
-
console.error(
|
|
12548
|
+
console.error(chalk137.gray(` assist refactor ignore <file>
|
|
12467
12549
|
`));
|
|
12468
12550
|
if (process.env.CLAUDECODE) {
|
|
12469
|
-
console.error(
|
|
12551
|
+
console.error(chalk137.cyan(`
|
|
12470
12552
|
## Extracting Code to New Files
|
|
12471
12553
|
`));
|
|
12472
12554
|
console.error(
|
|
12473
|
-
|
|
12555
|
+
chalk137.cyan(
|
|
12474
12556
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
12475
12557
|
`
|
|
12476
12558
|
)
|
|
12477
12559
|
);
|
|
12478
12560
|
console.error(
|
|
12479
|
-
|
|
12561
|
+
chalk137.cyan(
|
|
12480
12562
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
12481
12563
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
12482
12564
|
`
|
|
12483
12565
|
)
|
|
12484
12566
|
);
|
|
12485
12567
|
console.error(
|
|
12486
|
-
|
|
12568
|
+
chalk137.cyan(
|
|
12487
12569
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
12488
12570
|
domains, move it to a common/shared folder.
|
|
12489
12571
|
`
|
|
@@ -12639,7 +12721,7 @@ async function check(pattern2, options2) {
|
|
|
12639
12721
|
|
|
12640
12722
|
// src/commands/refactor/extract/index.ts
|
|
12641
12723
|
import path33 from "path";
|
|
12642
|
-
import
|
|
12724
|
+
import chalk140 from "chalk";
|
|
12643
12725
|
|
|
12644
12726
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
12645
12727
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -12676,9 +12758,9 @@ function addImportPreservingSuppressions(sourceFile, structure) {
|
|
|
12676
12758
|
import { SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
12677
12759
|
function collectReferencedNames(sourceFile) {
|
|
12678
12760
|
const names = /* @__PURE__ */ new Set();
|
|
12679
|
-
for (const
|
|
12680
|
-
if (
|
|
12681
|
-
names.add(
|
|
12761
|
+
for (const id2 of sourceFile.getDescendantsOfKind(SyntaxKind3.Identifier)) {
|
|
12762
|
+
if (id2.getFirstAncestorByKind(SyntaxKind3.ImportDeclaration)) continue;
|
|
12763
|
+
names.add(id2.getText());
|
|
12682
12764
|
}
|
|
12683
12765
|
return names;
|
|
12684
12766
|
}
|
|
@@ -12729,7 +12811,7 @@ function updateImporters(functionName, sourceFile, importers) {
|
|
|
12729
12811
|
|
|
12730
12812
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
12731
12813
|
function isNameReferencedInSource(sourceFile, name) {
|
|
12732
|
-
return sourceFile.getDescendantsOfKind(SyntaxKind4.Identifier).some((
|
|
12814
|
+
return sourceFile.getDescendantsOfKind(SyntaxKind4.Identifier).some((id2) => id2.getText() === name);
|
|
12733
12815
|
}
|
|
12734
12816
|
async function applyExtraction(functionName, sourceFile, destPath, plan2, project) {
|
|
12735
12817
|
project.createSourceFile(destPath, plan2.destContent, { overwrite: false });
|
|
@@ -12813,8 +12895,8 @@ function collectPrivateFunctions(target, fnMap) {
|
|
|
12813
12895
|
import { SyntaxKind as SyntaxKind6 } from "ts-morph";
|
|
12814
12896
|
function getReferencedIdentifiers(fn) {
|
|
12815
12897
|
const names = /* @__PURE__ */ new Set();
|
|
12816
|
-
for (const
|
|
12817
|
-
names.add(
|
|
12898
|
+
for (const id2 of fn.getDescendantsOfKind(SyntaxKind6.Identifier)) {
|
|
12899
|
+
names.add(id2.getText());
|
|
12818
12900
|
}
|
|
12819
12901
|
return names;
|
|
12820
12902
|
}
|
|
@@ -12982,8 +13064,8 @@ function matchImport(importDecl, neededNames) {
|
|
|
12982
13064
|
function getReferencedNames(nodes) {
|
|
12983
13065
|
const names = /* @__PURE__ */ new Set();
|
|
12984
13066
|
for (const node of nodes) {
|
|
12985
|
-
for (const
|
|
12986
|
-
names.add(
|
|
13067
|
+
for (const id2 of node.getDescendantsOfKind(SyntaxKind12.Identifier)) {
|
|
13068
|
+
names.add(id2.getText());
|
|
12987
13069
|
}
|
|
12988
13070
|
}
|
|
12989
13071
|
return names;
|
|
@@ -13173,9 +13255,9 @@ function isInsideExtractedFunction(node, extracted) {
|
|
|
13173
13255
|
}
|
|
13174
13256
|
function sourceReferencesName(sourceFile, functionName, extractedNames) {
|
|
13175
13257
|
const extracted = new Set(extractedNames);
|
|
13176
|
-
for (const
|
|
13177
|
-
if (
|
|
13178
|
-
const parent =
|
|
13258
|
+
for (const id2 of sourceFile.getDescendantsOfKind(SyntaxKind13.Identifier)) {
|
|
13259
|
+
if (id2.getText() !== functionName) continue;
|
|
13260
|
+
const parent = id2.getParent();
|
|
13179
13261
|
if (!parent || DECLARATION_KINDS.has(parent.getKind())) continue;
|
|
13180
13262
|
if (!isInsideExtractedFunction(parent, extracted)) return true;
|
|
13181
13263
|
}
|
|
@@ -13214,23 +13296,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
13214
13296
|
|
|
13215
13297
|
// src/commands/refactor/extract/displayPlan.ts
|
|
13216
13298
|
import path30 from "path";
|
|
13217
|
-
import
|
|
13299
|
+
import chalk138 from "chalk";
|
|
13218
13300
|
function section(title) {
|
|
13219
13301
|
return `
|
|
13220
|
-
${
|
|
13302
|
+
${chalk138.cyan(title)}`;
|
|
13221
13303
|
}
|
|
13222
13304
|
function displayImporters(plan2, cwd) {
|
|
13223
13305
|
if (plan2.importersToUpdate.length === 0) return;
|
|
13224
13306
|
console.log(section("Update importers:"));
|
|
13225
13307
|
for (const imp of plan2.importersToUpdate) {
|
|
13226
13308
|
const rel = path30.relative(cwd, imp.file.getFilePath());
|
|
13227
|
-
console.log(` ${
|
|
13309
|
+
console.log(` ${chalk138.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
13228
13310
|
}
|
|
13229
13311
|
}
|
|
13230
13312
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
13231
|
-
console.log(
|
|
13313
|
+
console.log(chalk138.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
13232
13314
|
`));
|
|
13233
|
-
console.log(` ${
|
|
13315
|
+
console.log(` ${chalk138.cyan("Functions to move:")}`);
|
|
13234
13316
|
for (const name of plan2.extractedNames) {
|
|
13235
13317
|
console.log(` ${name}`);
|
|
13236
13318
|
}
|
|
@@ -13264,7 +13346,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
13264
13346
|
|
|
13265
13347
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
13266
13348
|
import path32 from "path";
|
|
13267
|
-
import
|
|
13349
|
+
import chalk139 from "chalk";
|
|
13268
13350
|
import { Project as Project4 } from "ts-morph";
|
|
13269
13351
|
|
|
13270
13352
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -13324,7 +13406,7 @@ function loadProjectFile(file) {
|
|
|
13324
13406
|
});
|
|
13325
13407
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
13326
13408
|
if (!sourceFile) {
|
|
13327
|
-
console.log(
|
|
13409
|
+
console.log(chalk139.red(`File not found in project: ${file}`));
|
|
13328
13410
|
process.exit(1);
|
|
13329
13411
|
}
|
|
13330
13412
|
return { project, sourceFile };
|
|
@@ -13347,19 +13429,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
13347
13429
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
13348
13430
|
if (options2.apply) {
|
|
13349
13431
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
13350
|
-
console.log(
|
|
13432
|
+
console.log(chalk140.green("\nExtraction complete"));
|
|
13351
13433
|
} else {
|
|
13352
|
-
console.log(
|
|
13434
|
+
console.log(chalk140.dim("\nDry run. Use --apply to execute."));
|
|
13353
13435
|
}
|
|
13354
13436
|
}
|
|
13355
13437
|
|
|
13356
13438
|
// src/commands/refactor/ignore.ts
|
|
13357
13439
|
import fs20 from "fs";
|
|
13358
|
-
import
|
|
13440
|
+
import chalk141 from "chalk";
|
|
13359
13441
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
13360
13442
|
function ignore(file) {
|
|
13361
13443
|
if (!fs20.existsSync(file)) {
|
|
13362
|
-
console.error(
|
|
13444
|
+
console.error(chalk141.red(`Error: File does not exist: ${file}`));
|
|
13363
13445
|
process.exit(1);
|
|
13364
13446
|
}
|
|
13365
13447
|
const content = fs20.readFileSync(file, "utf-8");
|
|
@@ -13375,7 +13457,7 @@ function ignore(file) {
|
|
|
13375
13457
|
fs20.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
13376
13458
|
}
|
|
13377
13459
|
console.log(
|
|
13378
|
-
|
|
13460
|
+
chalk141.green(
|
|
13379
13461
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
13380
13462
|
)
|
|
13381
13463
|
);
|
|
@@ -13384,12 +13466,12 @@ function ignore(file) {
|
|
|
13384
13466
|
// src/commands/refactor/rename/index.ts
|
|
13385
13467
|
import fs23 from "fs";
|
|
13386
13468
|
import path38 from "path";
|
|
13387
|
-
import
|
|
13469
|
+
import chalk144 from "chalk";
|
|
13388
13470
|
|
|
13389
13471
|
// src/commands/refactor/rename/applyRename.ts
|
|
13390
13472
|
import fs22 from "fs";
|
|
13391
13473
|
import path35 from "path";
|
|
13392
|
-
import
|
|
13474
|
+
import chalk142 from "chalk";
|
|
13393
13475
|
|
|
13394
13476
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
13395
13477
|
import path34 from "path";
|
|
@@ -13494,13 +13576,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
13494
13576
|
const updatedContents = applyRewrites(rewrites);
|
|
13495
13577
|
for (const [file, content] of updatedContents) {
|
|
13496
13578
|
fs22.writeFileSync(file, content, "utf-8");
|
|
13497
|
-
console.log(
|
|
13579
|
+
console.log(chalk142.cyan(` Updated imports in ${path35.relative(cwd, file)}`));
|
|
13498
13580
|
}
|
|
13499
13581
|
const destDir = path35.dirname(destPath);
|
|
13500
13582
|
if (!fs22.existsSync(destDir)) fs22.mkdirSync(destDir, { recursive: true });
|
|
13501
13583
|
fs22.renameSync(sourcePath, destPath);
|
|
13502
13584
|
console.log(
|
|
13503
|
-
|
|
13585
|
+
chalk142.white(
|
|
13504
13586
|
` Moved ${path35.relative(cwd, sourcePath)} \u2192 ${path35.relative(cwd, destPath)}`
|
|
13505
13587
|
)
|
|
13506
13588
|
);
|
|
@@ -13587,16 +13669,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
13587
13669
|
|
|
13588
13670
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
13589
13671
|
import path37 from "path";
|
|
13590
|
-
import
|
|
13672
|
+
import chalk143 from "chalk";
|
|
13591
13673
|
function printRenamePreview(rewrites, cwd) {
|
|
13592
13674
|
for (const rewrite of rewrites) {
|
|
13593
13675
|
console.log(
|
|
13594
|
-
|
|
13676
|
+
chalk143.dim(
|
|
13595
13677
|
` ${path37.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
13596
13678
|
)
|
|
13597
13679
|
);
|
|
13598
13680
|
}
|
|
13599
|
-
console.log(
|
|
13681
|
+
console.log(chalk143.dim("Dry run. Use --apply to execute."));
|
|
13600
13682
|
}
|
|
13601
13683
|
|
|
13602
13684
|
// src/commands/refactor/rename/index.ts
|
|
@@ -13607,20 +13689,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
13607
13689
|
const relSource = path38.relative(cwd, sourcePath);
|
|
13608
13690
|
const relDest = path38.relative(cwd, destPath);
|
|
13609
13691
|
if (!fs23.existsSync(sourcePath)) {
|
|
13610
|
-
console.log(
|
|
13692
|
+
console.log(chalk144.red(`File not found: ${source}`));
|
|
13611
13693
|
process.exit(1);
|
|
13612
13694
|
}
|
|
13613
13695
|
if (destPath !== sourcePath && fs23.existsSync(destPath)) {
|
|
13614
|
-
console.log(
|
|
13696
|
+
console.log(chalk144.red(`Destination already exists: ${destination}`));
|
|
13615
13697
|
process.exit(1);
|
|
13616
13698
|
}
|
|
13617
|
-
console.log(
|
|
13618
|
-
console.log(
|
|
13619
|
-
console.log(
|
|
13699
|
+
console.log(chalk144.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
13700
|
+
console.log(chalk144.dim("Loading project..."));
|
|
13701
|
+
console.log(chalk144.dim("Scanning imports across the project..."));
|
|
13620
13702
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
13621
13703
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
13622
13704
|
console.log(
|
|
13623
|
-
|
|
13705
|
+
chalk144.dim(
|
|
13624
13706
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
13625
13707
|
)
|
|
13626
13708
|
);
|
|
@@ -13629,11 +13711,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
13629
13711
|
return;
|
|
13630
13712
|
}
|
|
13631
13713
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
13632
|
-
console.log(
|
|
13714
|
+
console.log(chalk144.green("Done"));
|
|
13633
13715
|
}
|
|
13634
13716
|
|
|
13635
13717
|
// src/commands/refactor/renameSymbol/index.ts
|
|
13636
|
-
import
|
|
13718
|
+
import chalk145 from "chalk";
|
|
13637
13719
|
|
|
13638
13720
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
13639
13721
|
import { SyntaxKind as SyntaxKind14 } from "ts-morph";
|
|
@@ -13653,8 +13735,8 @@ function isDeclaration(identifier) {
|
|
|
13653
13735
|
return parent !== void 0 && declarationKinds.includes(parent.getKind());
|
|
13654
13736
|
}
|
|
13655
13737
|
function findSymbol(sourceFile, symbolName) {
|
|
13656
|
-
for (const
|
|
13657
|
-
if (
|
|
13738
|
+
for (const id2 of sourceFile.getDescendantsOfKind(SyntaxKind14.Identifier)) {
|
|
13739
|
+
if (id2.getText() === symbolName && isDeclaration(id2)) return id2;
|
|
13658
13740
|
}
|
|
13659
13741
|
return void 0;
|
|
13660
13742
|
}
|
|
@@ -13679,33 +13761,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
13679
13761
|
const { project, sourceFile } = loadProjectFile(file);
|
|
13680
13762
|
const symbol = findSymbol(sourceFile, oldName);
|
|
13681
13763
|
if (!symbol) {
|
|
13682
|
-
console.log(
|
|
13764
|
+
console.log(chalk145.red(`Symbol "${oldName}" not found in ${file}`));
|
|
13683
13765
|
process.exit(1);
|
|
13684
13766
|
}
|
|
13685
13767
|
const grouped = groupReferences(symbol, cwd);
|
|
13686
13768
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
13687
13769
|
console.log(
|
|
13688
|
-
|
|
13770
|
+
chalk145.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
13689
13771
|
`)
|
|
13690
13772
|
);
|
|
13691
13773
|
for (const [refFile, lines] of grouped) {
|
|
13692
13774
|
console.log(
|
|
13693
|
-
` ${
|
|
13775
|
+
` ${chalk145.dim(refFile)}: lines ${chalk145.cyan(lines.join(", "))}`
|
|
13694
13776
|
);
|
|
13695
13777
|
}
|
|
13696
13778
|
if (options2.apply) {
|
|
13697
13779
|
symbol.rename(newName);
|
|
13698
13780
|
await project.save();
|
|
13699
|
-
console.log(
|
|
13781
|
+
console.log(chalk145.green(`
|
|
13700
13782
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
13701
13783
|
} else {
|
|
13702
|
-
console.log(
|
|
13784
|
+
console.log(chalk145.dim("\nDry run. Use --apply to execute."));
|
|
13703
13785
|
}
|
|
13704
13786
|
}
|
|
13705
13787
|
|
|
13706
13788
|
// src/commands/refactor/restructure/index.ts
|
|
13707
13789
|
import path46 from "path";
|
|
13708
|
-
import
|
|
13790
|
+
import chalk148 from "chalk";
|
|
13709
13791
|
|
|
13710
13792
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
13711
13793
|
import path40 from "path";
|
|
@@ -13784,50 +13866,50 @@ function clusterFiles(graph) {
|
|
|
13784
13866
|
|
|
13785
13867
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
13786
13868
|
import path42 from "path";
|
|
13787
|
-
import
|
|
13869
|
+
import chalk146 from "chalk";
|
|
13788
13870
|
function relPath(filePath) {
|
|
13789
13871
|
return path42.relative(process.cwd(), filePath);
|
|
13790
13872
|
}
|
|
13791
13873
|
function displayMoves(plan2) {
|
|
13792
13874
|
if (plan2.moves.length === 0) return;
|
|
13793
|
-
console.log(
|
|
13875
|
+
console.log(chalk146.bold("\nFile moves:"));
|
|
13794
13876
|
for (const move of plan2.moves) {
|
|
13795
13877
|
console.log(
|
|
13796
|
-
` ${
|
|
13878
|
+
` ${chalk146.red(relPath(move.from))} \u2192 ${chalk146.green(relPath(move.to))}`
|
|
13797
13879
|
);
|
|
13798
|
-
console.log(
|
|
13880
|
+
console.log(chalk146.dim(` ${move.reason}`));
|
|
13799
13881
|
}
|
|
13800
13882
|
}
|
|
13801
13883
|
function displayRewrites(rewrites) {
|
|
13802
13884
|
if (rewrites.length === 0) return;
|
|
13803
13885
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
13804
|
-
console.log(
|
|
13886
|
+
console.log(chalk146.bold(`
|
|
13805
13887
|
Import rewrites (${affectedFiles.size} files):`));
|
|
13806
13888
|
for (const file of affectedFiles) {
|
|
13807
|
-
console.log(` ${
|
|
13889
|
+
console.log(` ${chalk146.cyan(relPath(file))}:`);
|
|
13808
13890
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
13809
13891
|
(r) => r.file === file
|
|
13810
13892
|
)) {
|
|
13811
13893
|
console.log(
|
|
13812
|
-
` ${
|
|
13894
|
+
` ${chalk146.red(`"${oldSpecifier}"`)} \u2192 ${chalk146.green(`"${newSpecifier}"`)}`
|
|
13813
13895
|
);
|
|
13814
13896
|
}
|
|
13815
13897
|
}
|
|
13816
13898
|
}
|
|
13817
13899
|
function displayPlan2(plan2) {
|
|
13818
13900
|
if (plan2.warnings.length > 0) {
|
|
13819
|
-
console.log(
|
|
13820
|
-
for (const w of plan2.warnings) console.log(
|
|
13901
|
+
console.log(chalk146.yellow("\nWarnings:"));
|
|
13902
|
+
for (const w of plan2.warnings) console.log(chalk146.yellow(` ${w}`));
|
|
13821
13903
|
}
|
|
13822
13904
|
if (plan2.newDirectories.length > 0) {
|
|
13823
|
-
console.log(
|
|
13905
|
+
console.log(chalk146.bold("\nNew directories:"));
|
|
13824
13906
|
for (const dir of plan2.newDirectories)
|
|
13825
|
-
console.log(
|
|
13907
|
+
console.log(chalk146.green(` ${dir}/`));
|
|
13826
13908
|
}
|
|
13827
13909
|
displayMoves(plan2);
|
|
13828
13910
|
displayRewrites(plan2.rewrites);
|
|
13829
13911
|
console.log(
|
|
13830
|
-
|
|
13912
|
+
chalk146.dim(
|
|
13831
13913
|
`
|
|
13832
13914
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
13833
13915
|
)
|
|
@@ -13837,18 +13919,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
13837
13919
|
// src/commands/refactor/restructure/executePlan.ts
|
|
13838
13920
|
import fs24 from "fs";
|
|
13839
13921
|
import path43 from "path";
|
|
13840
|
-
import
|
|
13922
|
+
import chalk147 from "chalk";
|
|
13841
13923
|
function executePlan(plan2) {
|
|
13842
13924
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
13843
13925
|
for (const [file, content] of updatedContents) {
|
|
13844
13926
|
fs24.writeFileSync(file, content, "utf-8");
|
|
13845
13927
|
console.log(
|
|
13846
|
-
|
|
13928
|
+
chalk147.cyan(` Rewrote imports in ${path43.relative(process.cwd(), file)}`)
|
|
13847
13929
|
);
|
|
13848
13930
|
}
|
|
13849
13931
|
for (const dir of plan2.newDirectories) {
|
|
13850
13932
|
fs24.mkdirSync(dir, { recursive: true });
|
|
13851
|
-
console.log(
|
|
13933
|
+
console.log(chalk147.green(` Created ${path43.relative(process.cwd(), dir)}/`));
|
|
13852
13934
|
}
|
|
13853
13935
|
for (const move of plan2.moves) {
|
|
13854
13936
|
const targetDir = path43.dirname(move.to);
|
|
@@ -13857,7 +13939,7 @@ function executePlan(plan2) {
|
|
|
13857
13939
|
}
|
|
13858
13940
|
fs24.renameSync(move.from, move.to);
|
|
13859
13941
|
console.log(
|
|
13860
|
-
|
|
13942
|
+
chalk147.white(
|
|
13861
13943
|
` Moved ${path43.relative(process.cwd(), move.from)} \u2192 ${path43.relative(process.cwd(), move.to)}`
|
|
13862
13944
|
)
|
|
13863
13945
|
);
|
|
@@ -13872,7 +13954,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
13872
13954
|
if (entries.length === 0) {
|
|
13873
13955
|
fs24.rmdirSync(dir);
|
|
13874
13956
|
console.log(
|
|
13875
|
-
|
|
13957
|
+
chalk147.dim(
|
|
13876
13958
|
` Removed empty directory ${path43.relative(process.cwd(), dir)}`
|
|
13877
13959
|
)
|
|
13878
13960
|
);
|
|
@@ -14005,22 +14087,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
14005
14087
|
const targetPattern = pattern2 ?? "src";
|
|
14006
14088
|
const files = findSourceFiles2(targetPattern);
|
|
14007
14089
|
if (files.length === 0) {
|
|
14008
|
-
console.log(
|
|
14090
|
+
console.log(chalk148.yellow("No files found matching pattern"));
|
|
14009
14091
|
return;
|
|
14010
14092
|
}
|
|
14011
14093
|
const tsConfigPath = path46.resolve("tsconfig.json");
|
|
14012
14094
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
14013
14095
|
if (plan2.moves.length === 0) {
|
|
14014
|
-
console.log(
|
|
14096
|
+
console.log(chalk148.green("No restructuring needed"));
|
|
14015
14097
|
return;
|
|
14016
14098
|
}
|
|
14017
14099
|
displayPlan2(plan2);
|
|
14018
14100
|
if (options2.apply) {
|
|
14019
|
-
console.log(
|
|
14101
|
+
console.log(chalk148.bold("\nApplying changes..."));
|
|
14020
14102
|
executePlan(plan2);
|
|
14021
|
-
console.log(
|
|
14103
|
+
console.log(chalk148.green("\nRestructuring complete"));
|
|
14022
14104
|
} else {
|
|
14023
|
-
console.log(
|
|
14105
|
+
console.log(chalk148.dim("\nDry run. Use --apply to execute."));
|
|
14024
14106
|
}
|
|
14025
14107
|
}
|
|
14026
14108
|
|
|
@@ -14589,18 +14671,18 @@ function partitionFindingsByDiff(findings, index2) {
|
|
|
14589
14671
|
}
|
|
14590
14672
|
|
|
14591
14673
|
// src/commands/review/warnOutOfDiff.ts
|
|
14592
|
-
import
|
|
14674
|
+
import chalk149 from "chalk";
|
|
14593
14675
|
function warnOutOfDiff(outOfDiff) {
|
|
14594
14676
|
if (outOfDiff.length === 0) return;
|
|
14595
14677
|
console.warn(
|
|
14596
|
-
|
|
14678
|
+
chalk149.yellow(
|
|
14597
14679
|
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
14598
14680
|
)
|
|
14599
14681
|
);
|
|
14600
14682
|
for (const finding of outOfDiff) {
|
|
14601
14683
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
14602
14684
|
console.warn(
|
|
14603
|
-
` ${
|
|
14685
|
+
` ${chalk149.yellow("\xB7")} ${finding.title} ${chalk149.dim(
|
|
14604
14686
|
`(${finding.file}:${range})`
|
|
14605
14687
|
)}`
|
|
14606
14688
|
);
|
|
@@ -14619,18 +14701,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
14619
14701
|
}
|
|
14620
14702
|
|
|
14621
14703
|
// src/commands/review/warnUnlocated.ts
|
|
14622
|
-
import
|
|
14704
|
+
import chalk150 from "chalk";
|
|
14623
14705
|
function warnUnlocated(unlocated) {
|
|
14624
14706
|
if (unlocated.length === 0) return;
|
|
14625
14707
|
console.warn(
|
|
14626
|
-
|
|
14708
|
+
chalk150.yellow(
|
|
14627
14709
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
14628
14710
|
)
|
|
14629
14711
|
);
|
|
14630
14712
|
for (const finding of unlocated) {
|
|
14631
|
-
const where = finding.location ||
|
|
14713
|
+
const where = finding.location || chalk150.dim("missing");
|
|
14632
14714
|
console.warn(
|
|
14633
|
-
` ${
|
|
14715
|
+
` ${chalk150.yellow("\xB7")} ${finding.title} ${chalk150.dim(`(${where})`)}`
|
|
14634
14716
|
);
|
|
14635
14717
|
}
|
|
14636
14718
|
}
|
|
@@ -15016,9 +15098,11 @@ function printReviewerFailures(results) {
|
|
|
15016
15098
|
import { existsSync as existsSync38, unlinkSync as unlinkSync14 } from "fs";
|
|
15017
15099
|
|
|
15018
15100
|
// src/commands/review/buildReviewerStdin.ts
|
|
15019
|
-
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in request
|
|
15101
|
+
var REVIEW_PROMPT = `You are acting as a reviewer for a proposed code change made by another engineer. The full review request \u2014 branch, base, changed files, and unified diff \u2014 is in the request file whose absolute path is given below.
|
|
15102
|
+
|
|
15103
|
+
Your working directory is the repository under review, so you can read any file in it for context beyond the diff.
|
|
15020
15104
|
|
|
15021
|
-
Read request
|
|
15105
|
+
Read the request file, then produce a thorough code review in Markdown.
|
|
15022
15106
|
|
|
15023
15107
|
## When to flag a finding
|
|
15024
15108
|
|
|
@@ -15054,7 +15138,7 @@ List every finding that the original author would want to know about and fix. Do
|
|
|
15054
15138
|
|
|
15055
15139
|
For each finding include:
|
|
15056
15140
|
- Severity (blocker, major, minor, nit) \u2014 see rubric below
|
|
15057
|
-
- File and line (e.g. \`src/foo.ts:42\`) when the finding is tied to a specific location. Take the line number from the diff's left gutter (its line in the new file); never count lines in request.
|
|
15141
|
+
- File and line (e.g. \`src/foo.ts:42\`) when the finding is tied to a specific location. Take the line number from the diff's left gutter (its line in the new file); never count lines in the request file.
|
|
15058
15142
|
- Impact: what could go wrong, including the conditions under which it manifests
|
|
15059
15143
|
- Recommendation: a concrete change
|
|
15060
15144
|
|
|
@@ -15458,11 +15542,9 @@ function parseCodexEvent(line) {
|
|
|
15458
15542
|
}
|
|
15459
15543
|
|
|
15460
15544
|
// src/commands/review/runCodexReviewer.ts
|
|
15461
|
-
function codexArgs(
|
|
15545
|
+
function codexArgs(outputPath) {
|
|
15462
15546
|
return [
|
|
15463
15547
|
"exec",
|
|
15464
|
-
"--cd",
|
|
15465
|
-
reviewDir,
|
|
15466
15548
|
"--sandbox",
|
|
15467
15549
|
"read-only",
|
|
15468
15550
|
"--json",
|
|
@@ -15476,7 +15558,7 @@ async function runCodexReviewer(spec) {
|
|
|
15476
15558
|
const result = await runStreamingChild({
|
|
15477
15559
|
name: spec.name,
|
|
15478
15560
|
command,
|
|
15479
|
-
args: codexArgs(spec.
|
|
15561
|
+
args: codexArgs(spec.outputPath),
|
|
15480
15562
|
stdin: spec.stdin,
|
|
15481
15563
|
quiet: Boolean(spinner),
|
|
15482
15564
|
onLine: (line) => {
|
|
@@ -15500,7 +15582,6 @@ function resolveCodex(args) {
|
|
|
15500
15582
|
const spinner = args.multi?.create("codex \u2014 starting");
|
|
15501
15583
|
return runCodexReviewer({
|
|
15502
15584
|
name: "codex",
|
|
15503
|
-
reviewDir: args.reviewDir,
|
|
15504
15585
|
stdin: args.stdin,
|
|
15505
15586
|
outputPath: args.codexPath,
|
|
15506
15587
|
spinner
|
|
@@ -15517,7 +15598,6 @@ async function runReviewers(reviewDir, claudePath, codexPath, stdinPrompt, optio
|
|
|
15517
15598
|
multi: options2.multi
|
|
15518
15599
|
});
|
|
15519
15600
|
const codexPromise = resolveCodex({
|
|
15520
|
-
reviewDir,
|
|
15521
15601
|
codexPath,
|
|
15522
15602
|
stdin: stdinPrompt,
|
|
15523
15603
|
plan: options2.codexPlan,
|
|
@@ -15803,7 +15883,7 @@ function registerReview(program2) {
|
|
|
15803
15883
|
}
|
|
15804
15884
|
|
|
15805
15885
|
// src/commands/seq/seqAuth.ts
|
|
15806
|
-
import
|
|
15886
|
+
import chalk152 from "chalk";
|
|
15807
15887
|
|
|
15808
15888
|
// src/commands/seq/loadConnections.ts
|
|
15809
15889
|
function loadConnections2() {
|
|
@@ -15832,10 +15912,10 @@ function setDefaultConnection(name) {
|
|
|
15832
15912
|
}
|
|
15833
15913
|
|
|
15834
15914
|
// src/shared/assertUniqueName.ts
|
|
15835
|
-
import
|
|
15915
|
+
import chalk151 from "chalk";
|
|
15836
15916
|
function assertUniqueName(existingNames, name) {
|
|
15837
15917
|
if (existingNames.includes(name)) {
|
|
15838
|
-
console.error(
|
|
15918
|
+
console.error(chalk151.red(`Connection "${name}" already exists.`));
|
|
15839
15919
|
process.exit(1);
|
|
15840
15920
|
}
|
|
15841
15921
|
}
|
|
@@ -15853,16 +15933,16 @@ async function promptConnection2(existingNames) {
|
|
|
15853
15933
|
var seqAuth = createConnectionAuth({
|
|
15854
15934
|
load: loadConnections2,
|
|
15855
15935
|
save: saveConnections2,
|
|
15856
|
-
format: (c) => `${
|
|
15936
|
+
format: (c) => `${chalk152.bold(c.name)} ${c.url}`,
|
|
15857
15937
|
promptNew: promptConnection2,
|
|
15858
15938
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
15859
15939
|
});
|
|
15860
15940
|
|
|
15861
15941
|
// src/commands/seq/seqQuery.ts
|
|
15862
|
-
import
|
|
15942
|
+
import chalk156 from "chalk";
|
|
15863
15943
|
|
|
15864
15944
|
// src/commands/seq/fetchSeq.ts
|
|
15865
|
-
import
|
|
15945
|
+
import chalk153 from "chalk";
|
|
15866
15946
|
async function fetchSeq(conn, path56, params) {
|
|
15867
15947
|
const url = `${conn.url}${path56}?${params}`;
|
|
15868
15948
|
const response = await fetch(url, {
|
|
@@ -15873,7 +15953,7 @@ async function fetchSeq(conn, path56, params) {
|
|
|
15873
15953
|
});
|
|
15874
15954
|
if (!response.ok) {
|
|
15875
15955
|
const body = await response.text();
|
|
15876
|
-
console.error(
|
|
15956
|
+
console.error(chalk153.red(`Seq returned ${response.status}: ${body}`));
|
|
15877
15957
|
process.exit(1);
|
|
15878
15958
|
}
|
|
15879
15959
|
return response;
|
|
@@ -15932,23 +16012,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
15932
16012
|
}
|
|
15933
16013
|
|
|
15934
16014
|
// src/commands/seq/formatEvent.ts
|
|
15935
|
-
import
|
|
16015
|
+
import chalk154 from "chalk";
|
|
15936
16016
|
function levelColor(level) {
|
|
15937
16017
|
switch (level) {
|
|
15938
16018
|
case "Fatal":
|
|
15939
|
-
return
|
|
16019
|
+
return chalk154.bgRed.white;
|
|
15940
16020
|
case "Error":
|
|
15941
|
-
return
|
|
16021
|
+
return chalk154.red;
|
|
15942
16022
|
case "Warning":
|
|
15943
|
-
return
|
|
16023
|
+
return chalk154.yellow;
|
|
15944
16024
|
case "Information":
|
|
15945
|
-
return
|
|
16025
|
+
return chalk154.cyan;
|
|
15946
16026
|
case "Debug":
|
|
15947
|
-
return
|
|
16027
|
+
return chalk154.gray;
|
|
15948
16028
|
case "Verbose":
|
|
15949
|
-
return
|
|
16029
|
+
return chalk154.dim;
|
|
15950
16030
|
default:
|
|
15951
|
-
return
|
|
16031
|
+
return chalk154.white;
|
|
15952
16032
|
}
|
|
15953
16033
|
}
|
|
15954
16034
|
function levelAbbrev(level) {
|
|
@@ -15989,12 +16069,12 @@ function formatTimestamp(iso) {
|
|
|
15989
16069
|
function formatEvent(event) {
|
|
15990
16070
|
const color = levelColor(event.Level);
|
|
15991
16071
|
const abbrev = levelAbbrev(event.Level);
|
|
15992
|
-
const ts8 =
|
|
16072
|
+
const ts8 = chalk154.dim(formatTimestamp(event.Timestamp));
|
|
15993
16073
|
const msg = renderMessage(event);
|
|
15994
16074
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
15995
16075
|
if (event.Exception) {
|
|
15996
16076
|
for (const line of event.Exception.split("\n")) {
|
|
15997
|
-
lines.push(
|
|
16077
|
+
lines.push(chalk154.red(` ${line}`));
|
|
15998
16078
|
}
|
|
15999
16079
|
}
|
|
16000
16080
|
return lines.join("\n");
|
|
@@ -16027,11 +16107,11 @@ function rejectTimestampFilter(filter) {
|
|
|
16027
16107
|
}
|
|
16028
16108
|
|
|
16029
16109
|
// src/shared/resolveNamedConnection.ts
|
|
16030
|
-
import
|
|
16110
|
+
import chalk155 from "chalk";
|
|
16031
16111
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
16032
16112
|
if (connections.length === 0) {
|
|
16033
16113
|
console.error(
|
|
16034
|
-
|
|
16114
|
+
chalk155.red(
|
|
16035
16115
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
16036
16116
|
)
|
|
16037
16117
|
);
|
|
@@ -16040,7 +16120,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
16040
16120
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
16041
16121
|
const connection = connections.find((c) => c.name === target);
|
|
16042
16122
|
if (!connection) {
|
|
16043
|
-
console.error(
|
|
16123
|
+
console.error(chalk155.red(`${kind} connection "${target}" not found.`));
|
|
16044
16124
|
process.exit(1);
|
|
16045
16125
|
}
|
|
16046
16126
|
return connection;
|
|
@@ -16069,7 +16149,7 @@ async function seqQuery(filter, options2) {
|
|
|
16069
16149
|
new URLSearchParams({ filter, count: String(count6) })
|
|
16070
16150
|
);
|
|
16071
16151
|
if (events.length === 0) {
|
|
16072
|
-
console.log(
|
|
16152
|
+
console.log(chalk156.yellow("No events found."));
|
|
16073
16153
|
return;
|
|
16074
16154
|
}
|
|
16075
16155
|
if (options2.json) {
|
|
@@ -16080,11 +16160,11 @@ async function seqQuery(filter, options2) {
|
|
|
16080
16160
|
for (const event of chronological) {
|
|
16081
16161
|
console.log(formatEvent(event));
|
|
16082
16162
|
}
|
|
16083
|
-
console.log(
|
|
16163
|
+
console.log(chalk156.dim(`
|
|
16084
16164
|
${events.length} events`));
|
|
16085
16165
|
if (events.length >= count6) {
|
|
16086
16166
|
console.log(
|
|
16087
|
-
|
|
16167
|
+
chalk156.yellow(
|
|
16088
16168
|
`Results limited to ${count6}. Use --count to retrieve more.`
|
|
16089
16169
|
)
|
|
16090
16170
|
);
|
|
@@ -16092,10 +16172,10 @@ ${events.length} events`));
|
|
|
16092
16172
|
}
|
|
16093
16173
|
|
|
16094
16174
|
// src/shared/setNamedDefaultConnection.ts
|
|
16095
|
-
import
|
|
16175
|
+
import chalk157 from "chalk";
|
|
16096
16176
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
16097
16177
|
if (!connections.find((c) => c.name === name)) {
|
|
16098
|
-
console.error(
|
|
16178
|
+
console.error(chalk157.red(`Connection "${name}" not found.`));
|
|
16099
16179
|
process.exit(1);
|
|
16100
16180
|
}
|
|
16101
16181
|
setDefault(name);
|
|
@@ -16132,18 +16212,18 @@ function registerSeq(program2) {
|
|
|
16132
16212
|
// src/commands/registerSignal.ts
|
|
16133
16213
|
function registerSignal(program2) {
|
|
16134
16214
|
const signalCommand = program2.command("signal").description("Write an assist signal file");
|
|
16135
|
-
signalCommand.command("next").argument("[id]", "Backlog item ID to run directly").description("Write a next signal to chain into assist next").action((
|
|
16136
|
-
writeSignal("next",
|
|
16215
|
+
signalCommand.command("next").argument("[id]", "Backlog item ID to run directly").description("Write a next signal to chain into assist next").action((id2) => {
|
|
16216
|
+
writeSignal("next", id2 ? { id: id2 } : void 0);
|
|
16137
16217
|
console.log("Signal written.");
|
|
16138
16218
|
});
|
|
16139
|
-
signalCommand.command("done").argument("[id]", "Backlog item ID created by the session").description("Write a done signal to end a --once launch session").action((
|
|
16140
|
-
writeSignal("done",
|
|
16219
|
+
signalCommand.command("done").argument("[id]", "Backlog item ID created by the session").description("Write a done signal to end a --once launch session").action((id2) => {
|
|
16220
|
+
writeSignal("done", id2 ? { id: id2 } : void 0);
|
|
16141
16221
|
console.log("Signal written.");
|
|
16142
16222
|
});
|
|
16143
16223
|
}
|
|
16144
16224
|
|
|
16145
16225
|
// src/commands/sql/sqlAuth.ts
|
|
16146
|
-
import
|
|
16226
|
+
import chalk159 from "chalk";
|
|
16147
16227
|
|
|
16148
16228
|
// src/commands/sql/loadConnections.ts
|
|
16149
16229
|
function loadConnections3() {
|
|
@@ -16172,7 +16252,7 @@ function setDefaultConnection2(name) {
|
|
|
16172
16252
|
}
|
|
16173
16253
|
|
|
16174
16254
|
// src/commands/sql/promptConnection.ts
|
|
16175
|
-
import
|
|
16255
|
+
import chalk158 from "chalk";
|
|
16176
16256
|
async function promptConnection3(existingNames) {
|
|
16177
16257
|
const name = await promptInput("name", "Connection name:", "default");
|
|
16178
16258
|
assertUniqueName(existingNames, name);
|
|
@@ -16180,7 +16260,7 @@ async function promptConnection3(existingNames) {
|
|
|
16180
16260
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
16181
16261
|
const port = Number.parseInt(portStr, 10);
|
|
16182
16262
|
if (!Number.isFinite(port)) {
|
|
16183
|
-
console.error(
|
|
16263
|
+
console.error(chalk158.red(`Invalid port "${portStr}".`));
|
|
16184
16264
|
process.exit(1);
|
|
16185
16265
|
}
|
|
16186
16266
|
const user = await promptInput("user", "User:");
|
|
@@ -16193,13 +16273,13 @@ async function promptConnection3(existingNames) {
|
|
|
16193
16273
|
var sqlAuth = createConnectionAuth({
|
|
16194
16274
|
load: loadConnections3,
|
|
16195
16275
|
save: saveConnections3,
|
|
16196
|
-
format: (c) => `${
|
|
16276
|
+
format: (c) => `${chalk159.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
16197
16277
|
promptNew: promptConnection3,
|
|
16198
16278
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
16199
16279
|
});
|
|
16200
16280
|
|
|
16201
16281
|
// src/commands/sql/printTable.ts
|
|
16202
|
-
import
|
|
16282
|
+
import chalk160 from "chalk";
|
|
16203
16283
|
function formatCell(value) {
|
|
16204
16284
|
if (value === null || value === void 0) return "";
|
|
16205
16285
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -16208,7 +16288,7 @@ function formatCell(value) {
|
|
|
16208
16288
|
}
|
|
16209
16289
|
function printTable(rows) {
|
|
16210
16290
|
if (rows.length === 0) {
|
|
16211
|
-
console.log(
|
|
16291
|
+
console.log(chalk160.yellow("(no rows)"));
|
|
16212
16292
|
return;
|
|
16213
16293
|
}
|
|
16214
16294
|
const columns = Object.keys(rows[0]);
|
|
@@ -16216,13 +16296,13 @@ function printTable(rows) {
|
|
|
16216
16296
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
16217
16297
|
);
|
|
16218
16298
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
16219
|
-
console.log(
|
|
16220
|
-
console.log(
|
|
16299
|
+
console.log(chalk160.dim(header));
|
|
16300
|
+
console.log(chalk160.dim("-".repeat(header.length)));
|
|
16221
16301
|
for (const row of rows) {
|
|
16222
16302
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
16223
16303
|
console.log(line);
|
|
16224
16304
|
}
|
|
16225
|
-
console.log(
|
|
16305
|
+
console.log(chalk160.dim(`
|
|
16226
16306
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
16227
16307
|
}
|
|
16228
16308
|
|
|
@@ -16282,7 +16362,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
16282
16362
|
}
|
|
16283
16363
|
|
|
16284
16364
|
// src/commands/sql/sqlMutate.ts
|
|
16285
|
-
import
|
|
16365
|
+
import chalk161 from "chalk";
|
|
16286
16366
|
|
|
16287
16367
|
// src/commands/sql/isMutation.ts
|
|
16288
16368
|
var MUTATION_KEYWORDS = [
|
|
@@ -16316,7 +16396,7 @@ function isMutation(sql4) {
|
|
|
16316
16396
|
async function sqlMutate(query, connectionName) {
|
|
16317
16397
|
if (!isMutation(query)) {
|
|
16318
16398
|
console.error(
|
|
16319
|
-
|
|
16399
|
+
chalk161.red(
|
|
16320
16400
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
16321
16401
|
)
|
|
16322
16402
|
);
|
|
@@ -16326,18 +16406,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
16326
16406
|
const pool = await sqlConnect(conn);
|
|
16327
16407
|
try {
|
|
16328
16408
|
const result = await pool.request().query(query);
|
|
16329
|
-
console.log(
|
|
16409
|
+
console.log(chalk161.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
16330
16410
|
} finally {
|
|
16331
16411
|
await pool.close();
|
|
16332
16412
|
}
|
|
16333
16413
|
}
|
|
16334
16414
|
|
|
16335
16415
|
// src/commands/sql/sqlQuery.ts
|
|
16336
|
-
import
|
|
16416
|
+
import chalk162 from "chalk";
|
|
16337
16417
|
async function sqlQuery(query, connectionName) {
|
|
16338
16418
|
if (isMutation(query)) {
|
|
16339
16419
|
console.error(
|
|
16340
|
-
|
|
16420
|
+
chalk162.red(
|
|
16341
16421
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
16342
16422
|
)
|
|
16343
16423
|
);
|
|
@@ -16352,7 +16432,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
16352
16432
|
printTable(rows);
|
|
16353
16433
|
} else {
|
|
16354
16434
|
console.log(
|
|
16355
|
-
|
|
16435
|
+
chalk162.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
16356
16436
|
);
|
|
16357
16437
|
}
|
|
16358
16438
|
} finally {
|
|
@@ -16932,14 +17012,14 @@ import {
|
|
|
16932
17012
|
import { dirname as dirname22, join as join42 } from "path";
|
|
16933
17013
|
|
|
16934
17014
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
16935
|
-
import
|
|
17015
|
+
import chalk163 from "chalk";
|
|
16936
17016
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
16937
17017
|
function validateStagedContent(filename, content) {
|
|
16938
17018
|
const firstLine = content.split("\n")[0];
|
|
16939
17019
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
16940
17020
|
if (!match) {
|
|
16941
17021
|
console.error(
|
|
16942
|
-
|
|
17022
|
+
chalk163.red(
|
|
16943
17023
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
16944
17024
|
)
|
|
16945
17025
|
);
|
|
@@ -16948,7 +17028,7 @@ function validateStagedContent(filename, content) {
|
|
|
16948
17028
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
16949
17029
|
if (!contentAfterLink) {
|
|
16950
17030
|
console.error(
|
|
16951
|
-
|
|
17031
|
+
chalk163.red(
|
|
16952
17032
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
16953
17033
|
)
|
|
16954
17034
|
);
|
|
@@ -17345,7 +17425,7 @@ function registerVoice(program2) {
|
|
|
17345
17425
|
|
|
17346
17426
|
// src/commands/roam/auth.ts
|
|
17347
17427
|
import { randomBytes } from "crypto";
|
|
17348
|
-
import
|
|
17428
|
+
import chalk164 from "chalk";
|
|
17349
17429
|
|
|
17350
17430
|
// src/commands/roam/waitForCallback.ts
|
|
17351
17431
|
import { createServer as createServer2 } from "http";
|
|
@@ -17476,13 +17556,13 @@ async function auth() {
|
|
|
17476
17556
|
saveGlobalConfig(config);
|
|
17477
17557
|
const state = randomBytes(16).toString("hex");
|
|
17478
17558
|
console.log(
|
|
17479
|
-
|
|
17559
|
+
chalk164.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
17480
17560
|
);
|
|
17481
|
-
console.log(
|
|
17482
|
-
console.log(
|
|
17483
|
-
console.log(
|
|
17561
|
+
console.log(chalk164.white("http://localhost:14523/callback\n"));
|
|
17562
|
+
console.log(chalk164.blue("Opening browser for authorization..."));
|
|
17563
|
+
console.log(chalk164.dim("Waiting for authorization callback..."));
|
|
17484
17564
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
17485
|
-
console.log(
|
|
17565
|
+
console.log(chalk164.dim("Exchanging code for tokens..."));
|
|
17486
17566
|
const tokens = await exchangeToken({
|
|
17487
17567
|
code,
|
|
17488
17568
|
clientId,
|
|
@@ -17498,7 +17578,7 @@ async function auth() {
|
|
|
17498
17578
|
};
|
|
17499
17579
|
saveGlobalConfig(config);
|
|
17500
17580
|
console.log(
|
|
17501
|
-
|
|
17581
|
+
chalk164.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
17502
17582
|
);
|
|
17503
17583
|
}
|
|
17504
17584
|
|
|
@@ -17737,13 +17817,13 @@ function execRunConfig(config, args) {
|
|
|
17737
17817
|
config.quiet
|
|
17738
17818
|
);
|
|
17739
17819
|
}
|
|
17740
|
-
function parseBacklogRunOptions(
|
|
17820
|
+
function parseBacklogRunOptions(id2, args) {
|
|
17741
17821
|
let allowEdits = true;
|
|
17742
17822
|
for (const arg of args) {
|
|
17743
17823
|
if (arg === "--write" || arg === "-w") allowEdits = true;
|
|
17744
17824
|
else if (arg === "--no-write") allowEdits = false;
|
|
17745
17825
|
else {
|
|
17746
|
-
console.error(`error: unexpected argument '${arg}' for 'run ${
|
|
17826
|
+
console.error(`error: unexpected argument '${arg}' for 'run ${id2}'`);
|
|
17747
17827
|
process.exit(1);
|
|
17748
17828
|
}
|
|
17749
17829
|
}
|
|
@@ -17950,7 +18030,7 @@ import { execSync as execSync48 } from "child_process";
|
|
|
17950
18030
|
import { existsSync as existsSync50, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
|
|
17951
18031
|
import { tmpdir as tmpdir7 } from "os";
|
|
17952
18032
|
import { join as join53, resolve as resolve13 } from "path";
|
|
17953
|
-
import
|
|
18033
|
+
import chalk165 from "chalk";
|
|
17954
18034
|
|
|
17955
18035
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
17956
18036
|
var captureWindowPs1 = `
|
|
@@ -18101,13 +18181,13 @@ function screenshot(processName) {
|
|
|
18101
18181
|
const config = loadConfig();
|
|
18102
18182
|
const outputDir = resolve13(config.screenshot.outputDir);
|
|
18103
18183
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
18104
|
-
console.log(
|
|
18184
|
+
console.log(chalk165.gray(`Capturing window for process "${processName}" ...`));
|
|
18105
18185
|
try {
|
|
18106
18186
|
runPowerShellScript(processName, outputPath);
|
|
18107
|
-
console.log(
|
|
18187
|
+
console.log(chalk165.green(`Screenshot saved: ${outputPath}`));
|
|
18108
18188
|
} catch (error) {
|
|
18109
18189
|
const msg = error instanceof Error ? error.message : String(error);
|
|
18110
|
-
console.error(
|
|
18190
|
+
console.error(chalk165.red(`Failed to capture screenshot: ${msg}`));
|
|
18111
18191
|
process.exit(1);
|
|
18112
18192
|
}
|
|
18113
18193
|
}
|
|
@@ -18294,7 +18374,7 @@ function toPersistedSession(session) {
|
|
|
18294
18374
|
|
|
18295
18375
|
// src/commands/sessions/daemon/toSessionInfo.ts
|
|
18296
18376
|
function toSessionInfo({
|
|
18297
|
-
id,
|
|
18377
|
+
id: id2,
|
|
18298
18378
|
name,
|
|
18299
18379
|
commandType,
|
|
18300
18380
|
status: status2,
|
|
@@ -18309,7 +18389,7 @@ function toSessionInfo({
|
|
|
18309
18389
|
autoAdvance
|
|
18310
18390
|
}) {
|
|
18311
18391
|
return {
|
|
18312
|
-
id,
|
|
18392
|
+
id: id2,
|
|
18313
18393
|
name,
|
|
18314
18394
|
commandType,
|
|
18315
18395
|
status: status2,
|
|
@@ -18396,14 +18476,14 @@ function shellEscape(s) {
|
|
|
18396
18476
|
}
|
|
18397
18477
|
|
|
18398
18478
|
// src/commands/sessions/daemon/createAssistSession.ts
|
|
18399
|
-
function createAssistSession(
|
|
18479
|
+
function createAssistSession(id2, assistArgs, cwd) {
|
|
18400
18480
|
return {
|
|
18401
|
-
id,
|
|
18481
|
+
id: id2,
|
|
18402
18482
|
name: `assist ${assistArgs.join(" ")}`,
|
|
18403
18483
|
commandType: "assist",
|
|
18404
18484
|
status: "running",
|
|
18405
18485
|
startedAt: Date.now(),
|
|
18406
|
-
pty: spawnPty(["assist", ...assistArgs], cwd,
|
|
18486
|
+
pty: spawnPty(["assist", ...assistArgs], cwd, id2),
|
|
18407
18487
|
scrollback: "",
|
|
18408
18488
|
idleTimer: null,
|
|
18409
18489
|
lastResizeAt: 0,
|
|
@@ -18428,10 +18508,10 @@ function spawnRun(opts) {
|
|
|
18428
18508
|
}
|
|
18429
18509
|
|
|
18430
18510
|
// src/commands/sessions/daemon/createSession.ts
|
|
18431
|
-
function createSession(
|
|
18511
|
+
function createSession(id2, prompt, cwd) {
|
|
18432
18512
|
return {
|
|
18433
|
-
id,
|
|
18434
|
-
name: prompt?.slice(0, 40) || `Session ${
|
|
18513
|
+
id: id2,
|
|
18514
|
+
name: prompt?.slice(0, 40) || `Session ${id2}`,
|
|
18435
18515
|
commandType: "claude",
|
|
18436
18516
|
status: "running",
|
|
18437
18517
|
startedAt: Date.now(),
|
|
@@ -18442,9 +18522,9 @@ function createSession(id, prompt, cwd) {
|
|
|
18442
18522
|
cwd
|
|
18443
18523
|
};
|
|
18444
18524
|
}
|
|
18445
|
-
function createRunSession(
|
|
18525
|
+
function createRunSession(id2, runName, runArgs, cwd) {
|
|
18446
18526
|
return {
|
|
18447
|
-
id,
|
|
18527
|
+
id: id2,
|
|
18448
18528
|
name: `run: ${runName}`,
|
|
18449
18529
|
commandType: "run",
|
|
18450
18530
|
status: "running",
|
|
@@ -18515,9 +18595,9 @@ function backlogRunArgs(persisted) {
|
|
|
18515
18595
|
}
|
|
18516
18596
|
|
|
18517
18597
|
// src/commands/sessions/daemon/restoreBase.ts
|
|
18518
|
-
function restoreBase(
|
|
18598
|
+
function restoreBase(id2, persisted) {
|
|
18519
18599
|
return {
|
|
18520
|
-
id,
|
|
18600
|
+
id: id2,
|
|
18521
18601
|
name: persisted.name,
|
|
18522
18602
|
commandType: persisted.commandType,
|
|
18523
18603
|
scrollback: "",
|
|
@@ -18542,10 +18622,10 @@ function runningSession(base, persisted, pty2) {
|
|
|
18542
18622
|
}
|
|
18543
18623
|
|
|
18544
18624
|
// src/commands/sessions/daemon/restoreSession.ts
|
|
18545
|
-
function restoreSession(
|
|
18546
|
-
const base = restoreBase(
|
|
18625
|
+
function restoreSession(id2, persisted) {
|
|
18626
|
+
const base = restoreBase(id2, persisted);
|
|
18547
18627
|
if (isBacklogRun(persisted)) {
|
|
18548
|
-
const pty2 = spawnPty(backlogRunArgs(persisted), persisted.cwd,
|
|
18628
|
+
const pty2 = spawnPty(backlogRunArgs(persisted), persisted.cwd, id2);
|
|
18549
18629
|
return runningSession(base, persisted, pty2);
|
|
18550
18630
|
}
|
|
18551
18631
|
if (persisted.commandType !== "run" && persisted.claudeSessionId) {
|
|
@@ -18570,9 +18650,9 @@ function isBacklogRun(persisted) {
|
|
|
18570
18650
|
}
|
|
18571
18651
|
|
|
18572
18652
|
// src/commands/sessions/daemon/resumeSession.ts
|
|
18573
|
-
function resumeSession(
|
|
18653
|
+
function resumeSession(id2, sessionId, cwd, name) {
|
|
18574
18654
|
return {
|
|
18575
|
-
id,
|
|
18655
|
+
id: id2,
|
|
18576
18656
|
name: name ? `${name.slice(0, 36)} (R)` : `Resume ${sessionId.slice(0, 8)}`,
|
|
18577
18657
|
commandType: "claude",
|
|
18578
18658
|
status: "running",
|
|
@@ -18941,8 +19021,8 @@ function handleSessions(state, msg) {
|
|
|
18941
19021
|
id: toWindowsSessionId(s.id)
|
|
18942
19022
|
}));
|
|
18943
19023
|
const live = new Set(state.windowsSessions.map((s) => s.id));
|
|
18944
|
-
for (const
|
|
18945
|
-
if (!live.has(
|
|
19024
|
+
for (const id2 of state.scrollback.keys())
|
|
19025
|
+
if (!live.has(id2)) state.scrollback.delete(id2);
|
|
18946
19026
|
state.onSessionsChanged();
|
|
18947
19027
|
}
|
|
18948
19028
|
function handleOutput(state, msg) {
|
|
@@ -19404,25 +19484,25 @@ function isBacklogRun2(session) {
|
|
|
19404
19484
|
}
|
|
19405
19485
|
|
|
19406
19486
|
// src/commands/sessions/daemon/writeToSession.ts
|
|
19407
|
-
function writeToSession(sessions,
|
|
19408
|
-
const s = sessions.get(
|
|
19487
|
+
function writeToSession(sessions, id2, data) {
|
|
19488
|
+
const s = sessions.get(id2);
|
|
19409
19489
|
if (s && s.status !== "done") s.pty?.write(data);
|
|
19410
19490
|
}
|
|
19411
|
-
function resizeSession(sessions,
|
|
19412
|
-
const s = sessions.get(
|
|
19491
|
+
function resizeSession(sessions, id2, cols, rows) {
|
|
19492
|
+
const s = sessions.get(id2);
|
|
19413
19493
|
if (s && s.status !== "done") {
|
|
19414
19494
|
s.lastResizeAt = Date.now();
|
|
19415
19495
|
s.pty?.resize(cols, rows);
|
|
19416
19496
|
}
|
|
19417
19497
|
}
|
|
19418
|
-
function setAutoRun(sessions,
|
|
19419
|
-
const s = sessions.get(
|
|
19498
|
+
function setAutoRun(sessions, id2, enabled) {
|
|
19499
|
+
const s = sessions.get(id2);
|
|
19420
19500
|
if (!s) return false;
|
|
19421
19501
|
s.autoRun = enabled;
|
|
19422
19502
|
return true;
|
|
19423
19503
|
}
|
|
19424
|
-
function setAutoAdvance(sessions,
|
|
19425
|
-
const s = sessions.get(
|
|
19504
|
+
function setAutoAdvance(sessions, id2, enabled) {
|
|
19505
|
+
const s = sessions.get(id2);
|
|
19426
19506
|
if (!s) return false;
|
|
19427
19507
|
s.autoAdvance = enabled;
|
|
19428
19508
|
const itemId = s.activity?.itemId;
|
|
@@ -19432,15 +19512,15 @@ function setAutoAdvance(sessions, id, enabled) {
|
|
|
19432
19512
|
}
|
|
19433
19513
|
return true;
|
|
19434
19514
|
}
|
|
19435
|
-
function dismissSession(sessions,
|
|
19436
|
-
const s = sessions.get(
|
|
19515
|
+
function dismissSession(sessions, id2) {
|
|
19516
|
+
const s = sessions.get(id2);
|
|
19437
19517
|
if (!s) return false;
|
|
19438
19518
|
if (s.status !== "done") s.pty?.kill();
|
|
19439
19519
|
clearIdle(s);
|
|
19440
19520
|
s.activityWatcher?.close();
|
|
19441
19521
|
removeActivity(s.id);
|
|
19442
19522
|
if (s.activity?.itemId != null) releaseLock(s.activity.itemId);
|
|
19443
|
-
sessions.delete(
|
|
19523
|
+
sessions.delete(id2);
|
|
19444
19524
|
return true;
|
|
19445
19525
|
}
|
|
19446
19526
|
|
|
@@ -19473,7 +19553,7 @@ var SessionManager = class {
|
|
|
19473
19553
|
}
|
|
19474
19554
|
restore() {
|
|
19475
19555
|
return loadPersistedSessions().map((persisted) => {
|
|
19476
|
-
this.spawnWith((
|
|
19556
|
+
this.spawnWith((id2) => restoreSession(id2, persisted));
|
|
19477
19557
|
return persisted.name;
|
|
19478
19558
|
});
|
|
19479
19559
|
}
|
|
@@ -19487,19 +19567,19 @@ var SessionManager = class {
|
|
|
19487
19567
|
return this.add(create(String(this.nextId++)));
|
|
19488
19568
|
}
|
|
19489
19569
|
spawn(prompt, cwd) {
|
|
19490
|
-
return this.spawnWith((
|
|
19570
|
+
return this.spawnWith((id2) => createSession(id2, prompt, cwd));
|
|
19491
19571
|
}
|
|
19492
19572
|
spawnRun(runName, runArgs, cwd) {
|
|
19493
|
-
return this.spawnWith((
|
|
19573
|
+
return this.spawnWith((id2) => createRunSession(id2, runName, runArgs, cwd));
|
|
19494
19574
|
}
|
|
19495
19575
|
spawnAssist(assistArgs, cwd) {
|
|
19496
|
-
return this.spawnWith((
|
|
19576
|
+
return this.spawnWith((id2) => createAssistSession(id2, assistArgs, cwd));
|
|
19497
19577
|
}
|
|
19498
19578
|
resume(sessionId, cwd, name) {
|
|
19499
|
-
return this.spawnWith((
|
|
19579
|
+
return this.spawnWith((id2) => resumeSession(id2, sessionId, cwd, name));
|
|
19500
19580
|
}
|
|
19501
19581
|
onStatusChange = makeStatusChangeHandler(
|
|
19502
|
-
(
|
|
19582
|
+
(id2) => this.dismissSession(id2),
|
|
19503
19583
|
() => this.notify(),
|
|
19504
19584
|
(session, itemId) => reuseSessionForRun(session, itemId, this.clients, this.onStatusChange)
|
|
19505
19585
|
);
|
|
@@ -19508,24 +19588,24 @@ var SessionManager = class {
|
|
|
19508
19588
|
wirePtyEvents(session, this.clients, this.onStatusChange);
|
|
19509
19589
|
this.notify();
|
|
19510
19590
|
}
|
|
19511
|
-
writeToSession(
|
|
19512
|
-
writeToSession(this.sessions,
|
|
19591
|
+
writeToSession(id2, data) {
|
|
19592
|
+
writeToSession(this.sessions, id2, data);
|
|
19513
19593
|
}
|
|
19514
|
-
resizeSession(
|
|
19515
|
-
resizeSession(this.sessions,
|
|
19594
|
+
resizeSession(id2, cols, rows) {
|
|
19595
|
+
resizeSession(this.sessions, id2, cols, rows);
|
|
19516
19596
|
}
|
|
19517
|
-
retrySession(
|
|
19518
|
-
const s = this.sessions.get(
|
|
19597
|
+
retrySession(id2) {
|
|
19598
|
+
const s = this.sessions.get(id2);
|
|
19519
19599
|
if (s && retrySession(s, this.clients, this.onStatusChange)) this.notify();
|
|
19520
19600
|
}
|
|
19521
|
-
dismissSession = (
|
|
19522
|
-
if (dismissSession(this.sessions,
|
|
19601
|
+
dismissSession = (id2) => {
|
|
19602
|
+
if (dismissSession(this.sessions, id2)) this.notify();
|
|
19523
19603
|
};
|
|
19524
|
-
setAutoRun(
|
|
19525
|
-
if (setAutoRun(this.sessions,
|
|
19604
|
+
setAutoRun(id2, enabled) {
|
|
19605
|
+
if (setAutoRun(this.sessions, id2, enabled)) this.notify();
|
|
19526
19606
|
}
|
|
19527
|
-
setAutoAdvance(
|
|
19528
|
-
if (setAutoAdvance(this.sessions,
|
|
19607
|
+
setAutoAdvance(id2, enabled) {
|
|
19608
|
+
if (setAutoAdvance(this.sessions, id2, enabled)) this.notify();
|
|
19529
19609
|
}
|
|
19530
19610
|
listSessions = () => {
|
|
19531
19611
|
const local = [...this.sessions.values()].map(toSessionInfo);
|
|
@@ -19883,7 +19963,7 @@ function registerDaemon(program2) {
|
|
|
19883
19963
|
|
|
19884
19964
|
// src/commands/sessions/summarise/index.ts
|
|
19885
19965
|
import * as fs33 from "fs";
|
|
19886
|
-
import
|
|
19966
|
+
import chalk166 from "chalk";
|
|
19887
19967
|
|
|
19888
19968
|
// src/commands/sessions/summarise/shared.ts
|
|
19889
19969
|
import * as fs31 from "fs";
|
|
@@ -19941,8 +20021,8 @@ function truncate3(text3, maxChars = 500) {
|
|
|
19941
20021
|
function scanSessionBacklogRefs(filePath) {
|
|
19942
20022
|
const ids = /* @__PURE__ */ new Set();
|
|
19943
20023
|
for (const text3 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
|
|
19944
|
-
for (const
|
|
19945
|
-
ids.add(
|
|
20024
|
+
for (const id2 of extractBacklogIds(text3)) {
|
|
20025
|
+
ids.add(id2);
|
|
19946
20026
|
}
|
|
19947
20027
|
}
|
|
19948
20028
|
return [...ids].sort((a, b) => a - b);
|
|
@@ -19994,7 +20074,7 @@ function buildPrompt2(firstMessage, backlogIds) {
|
|
|
19994
20074
|
"Return ONLY the summary, no quotes or explanation."
|
|
19995
20075
|
];
|
|
19996
20076
|
if (backlogIds.length > 0) {
|
|
19997
|
-
const refs = backlogIds.map((
|
|
20077
|
+
const refs = backlogIds.map((id2) => `#${id2}`).join(", ");
|
|
19998
20078
|
parts.push(
|
|
19999
20079
|
`The session references backlog item(s) ${refs}. Start the summary with "Backlog ${refs} \u2014" if relevant.`
|
|
20000
20080
|
);
|
|
@@ -20010,22 +20090,22 @@ ${firstMessage}`);
|
|
|
20010
20090
|
async function summarise4(options2) {
|
|
20011
20091
|
const files = await discoverSessionFiles();
|
|
20012
20092
|
if (files.length === 0) {
|
|
20013
|
-
console.log(
|
|
20093
|
+
console.log(chalk166.yellow("No sessions found."));
|
|
20014
20094
|
return;
|
|
20015
20095
|
}
|
|
20016
20096
|
const toProcess = selectCandidates(files, options2);
|
|
20017
20097
|
if (toProcess.length === 0) {
|
|
20018
|
-
console.log(
|
|
20098
|
+
console.log(chalk166.green("All sessions already summarised."));
|
|
20019
20099
|
return;
|
|
20020
20100
|
}
|
|
20021
20101
|
console.log(
|
|
20022
|
-
|
|
20102
|
+
chalk166.cyan(
|
|
20023
20103
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
20024
20104
|
)
|
|
20025
20105
|
);
|
|
20026
20106
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
20027
20107
|
console.log(
|
|
20028
|
-
|
|
20108
|
+
chalk166.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk166.yellow(`, ${failed2} skipped`) : "")
|
|
20029
20109
|
);
|
|
20030
20110
|
}
|
|
20031
20111
|
function selectCandidates(files, options2) {
|
|
@@ -20045,16 +20125,16 @@ function processSessions(files) {
|
|
|
20045
20125
|
let failed2 = 0;
|
|
20046
20126
|
for (let i = 0; i < files.length; i++) {
|
|
20047
20127
|
const file = files[i];
|
|
20048
|
-
process.stdout.write(
|
|
20128
|
+
process.stdout.write(chalk166.dim(` [${i + 1}/${files.length}] `));
|
|
20049
20129
|
const summary = summariseSession(file);
|
|
20050
20130
|
if (summary) {
|
|
20051
20131
|
writeSummary(file, summary);
|
|
20052
20132
|
succeeded++;
|
|
20053
|
-
process.stdout.write(`${
|
|
20133
|
+
process.stdout.write(`${chalk166.green("\u2713")} ${summary}
|
|
20054
20134
|
`);
|
|
20055
20135
|
} else {
|
|
20056
20136
|
failed2++;
|
|
20057
|
-
process.stdout.write(` ${
|
|
20137
|
+
process.stdout.write(` ${chalk166.yellow("skip")}
|
|
20058
20138
|
`);
|
|
20059
20139
|
}
|
|
20060
20140
|
}
|
|
@@ -20069,10 +20149,10 @@ function registerSessions(program2) {
|
|
|
20069
20149
|
}
|
|
20070
20150
|
|
|
20071
20151
|
// src/commands/statusLine.ts
|
|
20072
|
-
import
|
|
20152
|
+
import chalk168 from "chalk";
|
|
20073
20153
|
|
|
20074
20154
|
// src/commands/buildLimitsSegment.ts
|
|
20075
|
-
import
|
|
20155
|
+
import chalk167 from "chalk";
|
|
20076
20156
|
|
|
20077
20157
|
// src/shared/rateLimitLevel.ts
|
|
20078
20158
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -20103,9 +20183,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
20103
20183
|
|
|
20104
20184
|
// src/commands/buildLimitsSegment.ts
|
|
20105
20185
|
var LEVEL_COLOR = {
|
|
20106
|
-
ok:
|
|
20107
|
-
warn:
|
|
20108
|
-
over:
|
|
20186
|
+
ok: chalk167.green,
|
|
20187
|
+
warn: chalk167.yellow,
|
|
20188
|
+
over: chalk167.red
|
|
20109
20189
|
};
|
|
20110
20190
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
20111
20191
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -20153,14 +20233,14 @@ async function relayRateLimits(rateLimits) {
|
|
|
20153
20233
|
}
|
|
20154
20234
|
|
|
20155
20235
|
// src/commands/statusLine.ts
|
|
20156
|
-
|
|
20236
|
+
chalk168.level = 3;
|
|
20157
20237
|
function formatNumber(num) {
|
|
20158
20238
|
return num.toLocaleString("en-US");
|
|
20159
20239
|
}
|
|
20160
20240
|
function colorizePercent(pct) {
|
|
20161
20241
|
const label2 = `${Math.round(pct)}%`;
|
|
20162
|
-
if (pct > 80) return
|
|
20163
|
-
if (pct > 40) return
|
|
20242
|
+
if (pct > 80) return chalk168.red(label2);
|
|
20243
|
+
if (pct > 40) return chalk168.yellow(label2);
|
|
20164
20244
|
return label2;
|
|
20165
20245
|
}
|
|
20166
20246
|
async function statusLine() {
|
|
@@ -20184,7 +20264,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
20184
20264
|
// src/commands/sync/syncClaudeMd.ts
|
|
20185
20265
|
import * as fs34 from "fs";
|
|
20186
20266
|
import * as path52 from "path";
|
|
20187
|
-
import
|
|
20267
|
+
import chalk169 from "chalk";
|
|
20188
20268
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
20189
20269
|
const source = path52.join(claudeDir, "CLAUDE.md");
|
|
20190
20270
|
const target = path52.join(targetBase, "CLAUDE.md");
|
|
@@ -20193,12 +20273,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
20193
20273
|
const targetContent = fs34.readFileSync(target, "utf-8");
|
|
20194
20274
|
if (sourceContent !== targetContent) {
|
|
20195
20275
|
console.log(
|
|
20196
|
-
|
|
20276
|
+
chalk169.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
20197
20277
|
);
|
|
20198
20278
|
console.log();
|
|
20199
20279
|
printDiff(targetContent, sourceContent);
|
|
20200
20280
|
const confirm = options2?.yes || await promptConfirm(
|
|
20201
|
-
|
|
20281
|
+
chalk169.red("Overwrite existing CLAUDE.md?"),
|
|
20202
20282
|
false
|
|
20203
20283
|
);
|
|
20204
20284
|
if (!confirm) {
|
|
@@ -20214,7 +20294,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
20214
20294
|
// src/commands/sync/syncSettings.ts
|
|
20215
20295
|
import * as fs35 from "fs";
|
|
20216
20296
|
import * as path53 from "path";
|
|
20217
|
-
import
|
|
20297
|
+
import chalk170 from "chalk";
|
|
20218
20298
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
20219
20299
|
const source = path53.join(claudeDir, "settings.json");
|
|
20220
20300
|
const target = path53.join(targetBase, "settings.json");
|
|
@@ -20230,14 +20310,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
20230
20310
|
if (mergedContent !== normalizedTarget) {
|
|
20231
20311
|
if (!options2?.yes) {
|
|
20232
20312
|
console.log(
|
|
20233
|
-
|
|
20313
|
+
chalk170.yellow(
|
|
20234
20314
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
20235
20315
|
)
|
|
20236
20316
|
);
|
|
20237
20317
|
console.log();
|
|
20238
20318
|
printDiff(targetContent, mergedContent);
|
|
20239
20319
|
const confirm = await promptConfirm(
|
|
20240
|
-
|
|
20320
|
+
chalk170.red("Overwrite existing settings.json?"),
|
|
20241
20321
|
false
|
|
20242
20322
|
);
|
|
20243
20323
|
if (!confirm) {
|