@staff0rd/assist 0.404.2 → 0.405.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 +3 -1
- package/claude/commands/github.md +130 -0
- package/claude/settings.json +2 -0
- package/dist/commands/sessions/web/bundle.js +80 -80
- package/dist/index.js +844 -724
- 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.405.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -458,7 +458,8 @@ var items = pgTable2(
|
|
|
458
458
|
status: text2().notNull().default("todo"),
|
|
459
459
|
currentPhase: integer2("current_phase"),
|
|
460
460
|
starred: boolean().notNull().default(false),
|
|
461
|
-
jiraKey: text2("jira_key")
|
|
461
|
+
jiraKey: text2("jira_key"),
|
|
462
|
+
githubIssue: text2("github_issue")
|
|
462
463
|
},
|
|
463
464
|
(t) => [index("items_origin_idx").on(t.origin)]
|
|
464
465
|
);
|
|
@@ -1114,6 +1115,16 @@ var migration0006BackfillPhaseSessions = {
|
|
|
1114
1115
|
sql: sql7
|
|
1115
1116
|
};
|
|
1116
1117
|
|
|
1118
|
+
// src/shared/db/migrations/migration0007GithubIssue.ts
|
|
1119
|
+
var sql8 = `
|
|
1120
|
+
ALTER TABLE items ADD COLUMN IF NOT EXISTS github_issue TEXT;
|
|
1121
|
+
`;
|
|
1122
|
+
var migration0007GithubIssue = {
|
|
1123
|
+
id: 7,
|
|
1124
|
+
name: "github-issue",
|
|
1125
|
+
sql: sql8
|
|
1126
|
+
};
|
|
1127
|
+
|
|
1117
1128
|
// src/shared/db/migrations/index.ts
|
|
1118
1129
|
var migrations = [
|
|
1119
1130
|
migration0001Baseline,
|
|
@@ -1121,7 +1132,8 @@ var migrations = [
|
|
|
1121
1132
|
migration0003PhaseCycleContext,
|
|
1122
1133
|
migration0004DropUsagePeaksContext,
|
|
1123
1134
|
migration0005PhaseSessions,
|
|
1124
|
-
migration0006BackfillPhaseSessions
|
|
1135
|
+
migration0006BackfillPhaseSessions,
|
|
1136
|
+
migration0007GithubIssue
|
|
1125
1137
|
];
|
|
1126
1138
|
var latestMigrationId = migrations.reduce(
|
|
1127
1139
|
(max, m) => Math.max(max, m.id),
|
|
@@ -1204,8 +1216,8 @@ async function assertMigrationsInSync(exec3) {
|
|
|
1204
1216
|
// src/shared/db/migrations/MigrationExecutor.ts
|
|
1205
1217
|
function pgExecutor(queryable) {
|
|
1206
1218
|
return {
|
|
1207
|
-
exec: (
|
|
1208
|
-
query: async (
|
|
1219
|
+
exec: (sql24) => queryable.query(sql24),
|
|
1220
|
+
query: async (sql24, params) => (await queryable.query(sql24, params)).rows
|
|
1209
1221
|
};
|
|
1210
1222
|
}
|
|
1211
1223
|
|
|
@@ -4737,8 +4749,8 @@ async function buildDump(tables, copyOut) {
|
|
|
4737
4749
|
// src/commands/backlog/dump/copyTableOut.ts
|
|
4738
4750
|
import { to as copyTo } from "pg-copy-streams";
|
|
4739
4751
|
async function copyTableOut(client, table) {
|
|
4740
|
-
const
|
|
4741
|
-
const stream = client.query(copyTo(
|
|
4752
|
+
const sql24 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
|
|
4753
|
+
const stream = client.query(copyTo(sql24));
|
|
4742
4754
|
const chunks = [];
|
|
4743
4755
|
for await (const chunk of stream) {
|
|
4744
4756
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
@@ -5421,7 +5433,8 @@ function itemColumns(item, origin) {
|
|
|
5421
5433
|
status: item.status,
|
|
5422
5434
|
currentPhase: item.currentPhase ?? null,
|
|
5423
5435
|
starred: item.starred,
|
|
5424
|
-
jiraKey: item.jiraKey ?? null
|
|
5436
|
+
jiraKey: item.jiraKey ?? null,
|
|
5437
|
+
githubIssue: item.githubIssue ?? null
|
|
5425
5438
|
};
|
|
5426
5439
|
}
|
|
5427
5440
|
|
|
@@ -5719,6 +5732,7 @@ function assignOptionalColumns(item, row) {
|
|
|
5719
5732
|
if (row.description != null) item.description = row.description;
|
|
5720
5733
|
if (row.currentPhase != null) item.currentPhase = row.currentPhase;
|
|
5721
5734
|
if (row.jiraKey != null) item.jiraKey = row.jiraKey;
|
|
5735
|
+
if (row.githubIssue != null) item.githubIssue = row.githubIssue;
|
|
5722
5736
|
}
|
|
5723
5737
|
function baseItem(row) {
|
|
5724
5738
|
const item = {
|
|
@@ -5849,7 +5863,8 @@ var backlogItemSchema = z3.strictObject({
|
|
|
5849
5863
|
usageTotal: phaseUsageTotalSchema.optional(),
|
|
5850
5864
|
gitRefs: z3.array(gitRefSchema).optional(),
|
|
5851
5865
|
origin: z3.string().optional(),
|
|
5852
|
-
jiraKey: z3.string().optional()
|
|
5866
|
+
jiraKey: z3.string().optional(),
|
|
5867
|
+
githubIssue: z3.string().optional()
|
|
5853
5868
|
});
|
|
5854
5869
|
var backlogFileSchema = z3.array(backlogItemSchema);
|
|
5855
5870
|
|
|
@@ -6003,13 +6018,13 @@ async function loadItem(orm, id) {
|
|
|
6003
6018
|
}
|
|
6004
6019
|
|
|
6005
6020
|
// src/commands/backlog/saveAllItems.ts
|
|
6006
|
-
import { eq as eq7, sql as
|
|
6021
|
+
import { eq as eq7, sql as sql9 } from "drizzle-orm";
|
|
6007
6022
|
|
|
6008
6023
|
// src/commands/backlog/deleteItemRelations.ts
|
|
6009
6024
|
import { eq as eq6 } from "drizzle-orm";
|
|
6010
6025
|
|
|
6011
6026
|
// src/commands/backlog/searchItemIds.ts
|
|
6012
|
-
import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as
|
|
6027
|
+
import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as sql10 } from "drizzle-orm";
|
|
6013
6028
|
async function searchItemIds(orm, query, origin) {
|
|
6014
6029
|
const pattern2 = `%${query}%`;
|
|
6015
6030
|
const numberPattern = `%${query.replace(/^#/, "")}%`;
|
|
@@ -6023,7 +6038,7 @@ async function searchItemIds(orm, query, origin) {
|
|
|
6023
6038
|
ilike(items.jiraKey, pattern2),
|
|
6024
6039
|
ilike(comments.text, pattern2),
|
|
6025
6040
|
ilike(planPhases.name, pattern2),
|
|
6026
|
-
ilike(
|
|
6041
|
+
ilike(sql10`${items.id}::text`, numberPattern)
|
|
6027
6042
|
)
|
|
6028
6043
|
)
|
|
6029
6044
|
).orderBy(asc4(items.id));
|
|
@@ -6147,11 +6162,11 @@ async function findPhaseBySessionId(db, itemId2, claudeSessionId) {
|
|
|
6147
6162
|
}
|
|
6148
6163
|
|
|
6149
6164
|
// src/commands/backlog/appendComment.ts
|
|
6150
|
-
import { sql as
|
|
6165
|
+
import { sql as sql11 } from "drizzle-orm";
|
|
6151
6166
|
async function appendComment(orm, itemId2, text17, opts = {}) {
|
|
6152
6167
|
await orm.insert(comments).values({
|
|
6153
6168
|
itemId: itemId2,
|
|
6154
|
-
idx:
|
|
6169
|
+
idx: sql11`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
|
|
6155
6170
|
text: text17,
|
|
6156
6171
|
phase: opts.phase ?? null,
|
|
6157
6172
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6604,7 +6619,7 @@ function launchPhaseSession(item, phaseNumber, phase, phaseLabel2, claudeSession
|
|
|
6604
6619
|
import os from "os";
|
|
6605
6620
|
|
|
6606
6621
|
// src/shared/db/recordPhaseSession.ts
|
|
6607
|
-
import { sql as
|
|
6622
|
+
import { sql as sql12 } from "drizzle-orm";
|
|
6608
6623
|
async function recordPhaseSession(db, itemId2, phaseIdx, claudeSessionId, hostname, osUser) {
|
|
6609
6624
|
await db.insert(phaseSessions).values({ itemId: itemId2, phaseIdx, claudeSessionId, hostname, osUser }).onConflictDoUpdate({
|
|
6610
6625
|
target: [
|
|
@@ -6613,7 +6628,7 @@ async function recordPhaseSession(db, itemId2, phaseIdx, claudeSessionId, hostna
|
|
|
6613
6628
|
phaseSessions.claudeSessionId
|
|
6614
6629
|
],
|
|
6615
6630
|
set: { hostname, osUser },
|
|
6616
|
-
setWhere:
|
|
6631
|
+
setWhere: sql12`${phaseSessions.hostname} = 'unknown'`
|
|
6617
6632
|
});
|
|
6618
6633
|
}
|
|
6619
6634
|
|
|
@@ -7354,6 +7369,18 @@ function renderMarkdownTerminal(text17) {
|
|
|
7354
7369
|
return marked.parse(text17).trimEnd();
|
|
7355
7370
|
}
|
|
7356
7371
|
|
|
7372
|
+
// src/commands/backlog/shortenGithubIssue.ts
|
|
7373
|
+
var SHORTHAND = /^([^/\s]+)\/([^/\s]+)#(\d+)$/;
|
|
7374
|
+
function shortenGithubIssue(githubIssue, origin) {
|
|
7375
|
+
const match = SHORTHAND.exec(githubIssue);
|
|
7376
|
+
if (!match || !origin) return githubIssue;
|
|
7377
|
+
const [, owner, repo, number] = match;
|
|
7378
|
+
if (`github.com/${owner}/${repo}`.toLowerCase() === origin.toLowerCase()) {
|
|
7379
|
+
return `#${number}`;
|
|
7380
|
+
}
|
|
7381
|
+
return githubIssue;
|
|
7382
|
+
}
|
|
7383
|
+
|
|
7357
7384
|
// src/commands/backlog/show/printActivity.ts
|
|
7358
7385
|
import chalk50 from "chalk";
|
|
7359
7386
|
|
|
@@ -7526,6 +7553,11 @@ function printHeader(item) {
|
|
|
7526
7553
|
if (item.jiraKey) {
|
|
7527
7554
|
console.log(`${chalk55.dim("Jira:")} ${item.jiraKey}`);
|
|
7528
7555
|
}
|
|
7556
|
+
if (item.githubIssue) {
|
|
7557
|
+
console.log(
|
|
7558
|
+
`${chalk55.dim("GitHub:")} ${shortenGithubIssue(item.githubIssue, item.origin)}`
|
|
7559
|
+
);
|
|
7560
|
+
}
|
|
7529
7561
|
console.log();
|
|
7530
7562
|
}
|
|
7531
7563
|
function printAcceptanceCriteria(criteria) {
|
|
@@ -7843,29 +7875,29 @@ function createFallbackHandler(routes3, htmlHandler2, extra) {
|
|
|
7843
7875
|
import { asc as asc5, eq as eq12 } from "drizzle-orm";
|
|
7844
7876
|
|
|
7845
7877
|
// src/commands/backlog/incompleteSubtaskCounts.ts
|
|
7846
|
-
import { ne, sql as
|
|
7878
|
+
import { ne, sql as sql13 } from "drizzle-orm";
|
|
7847
7879
|
function incompleteSubtaskCounts(orm) {
|
|
7848
7880
|
return orm.select({
|
|
7849
7881
|
itemId: itemSubtasks.itemId,
|
|
7850
|
-
count:
|
|
7882
|
+
count: sql13`count(*)::int`.as("incomplete_subtasks")
|
|
7851
7883
|
}).from(itemSubtasks).where(ne(itemSubtasks.status, "done")).groupBy(itemSubtasks.itemId).as("incomplete_counts");
|
|
7852
7884
|
}
|
|
7853
7885
|
|
|
7854
7886
|
// src/commands/backlog/phaseUsageTotals.ts
|
|
7855
|
-
import { sql as
|
|
7887
|
+
import { sql as sql14 } from "drizzle-orm";
|
|
7856
7888
|
function phaseUsageTotals(orm) {
|
|
7857
7889
|
return orm.select({
|
|
7858
7890
|
itemId: phaseUsage.itemId,
|
|
7859
|
-
tokensUp:
|
|
7891
|
+
tokensUp: sql14`sum(${phaseUsage.tokensUp})::bigint`.as(
|
|
7860
7892
|
"total_tokens_up"
|
|
7861
7893
|
),
|
|
7862
|
-
tokensDown:
|
|
7894
|
+
tokensDown: sql14`sum(${phaseUsage.tokensDown})::bigint`.as(
|
|
7863
7895
|
"total_tokens_down"
|
|
7864
7896
|
),
|
|
7865
|
-
activeMs:
|
|
7897
|
+
activeMs: sql14`sum(${phaseUsage.activeMs})::bigint`.as(
|
|
7866
7898
|
"total_active_ms"
|
|
7867
7899
|
),
|
|
7868
|
-
peakContextPct:
|
|
7900
|
+
peakContextPct: sql14`max(${phaseUsage.peakContextPct})`.as(
|
|
7869
7901
|
"max_peak_context_pct"
|
|
7870
7902
|
)
|
|
7871
7903
|
}).from(phaseUsage).groupBy(phaseUsage.itemId).as("usage_totals");
|
|
@@ -7881,6 +7913,7 @@ function rowToItemSummary(row) {
|
|
|
7881
7913
|
status: row.status,
|
|
7882
7914
|
starred: row.starred,
|
|
7883
7915
|
jiraKey: row.jiraKey ?? void 0,
|
|
7916
|
+
githubIssue: row.githubIssue ?? void 0,
|
|
7884
7917
|
incompleteSubtasks: row.incompleteSubtasks ?? 0,
|
|
7885
7918
|
usageTotal: row.tokensUp == null ? void 0 : {
|
|
7886
7919
|
tokensUp: Number(row.tokensUp),
|
|
@@ -7903,6 +7936,7 @@ async function loadItemSummaries(orm, origin) {
|
|
|
7903
7936
|
status: items.status,
|
|
7904
7937
|
starred: items.starred,
|
|
7905
7938
|
jiraKey: items.jiraKey,
|
|
7939
|
+
githubIssue: items.githubIssue,
|
|
7906
7940
|
incompleteSubtasks: incompleteCounts.count,
|
|
7907
7941
|
tokensUp: usageTotals.tokensUp,
|
|
7908
7942
|
tokensDown: usageTotals.tokensDown,
|
|
@@ -8674,12 +8708,12 @@ async function listNewsItems(_req, res) {
|
|
|
8674
8708
|
}
|
|
8675
8709
|
|
|
8676
8710
|
// src/shared/db/listUsagePeaks.ts
|
|
8677
|
-
import { and as and7, count, desc as desc2, eq as eq16, getTableColumns, sql as
|
|
8711
|
+
import { and as and7, count, desc as desc2, eq as eq16, getTableColumns, sql as sql15 } from "drizzle-orm";
|
|
8678
8712
|
async function listUsagePeaks(db, paging) {
|
|
8679
8713
|
const avgContext = db.select({
|
|
8680
8714
|
window: phaseCycleContext.window,
|
|
8681
8715
|
resetsAt: phaseCycleContext.resetsAt,
|
|
8682
|
-
avgContextPct:
|
|
8716
|
+
avgContextPct: sql15`cast(avg(${phaseCycleContext.peakContextPct}) as double precision)`.as(
|
|
8683
8717
|
"avg_context_pct"
|
|
8684
8718
|
),
|
|
8685
8719
|
phaseCount: count().as("phase_count")
|
|
@@ -9447,17 +9481,113 @@ function registerActivityCommands(cmd) {
|
|
|
9447
9481
|
).option("--title <title>", "Title metadata for the ref").option("--url <url>", "URL metadata (auto-filled for branch/commit)").option("--state <state>", "State metadata for the ref").action(addActivity);
|
|
9448
9482
|
}
|
|
9449
9483
|
|
|
9450
|
-
// src/commands/backlog/associate-
|
|
9484
|
+
// src/commands/backlog/associate-github/index.ts
|
|
9451
9485
|
import chalk63 from "chalk";
|
|
9486
|
+
import { eq as eq18 } from "drizzle-orm";
|
|
9487
|
+
|
|
9488
|
+
// src/commands/backlog/beginAssociation.ts
|
|
9489
|
+
import chalk62 from "chalk";
|
|
9452
9490
|
import { eq as eq17 } from "drizzle-orm";
|
|
9491
|
+
async function beginAssociation(id, options2, clearPatch, label2) {
|
|
9492
|
+
const found = await findOneItem(id);
|
|
9493
|
+
if (!found) {
|
|
9494
|
+
process.exitCode = 1;
|
|
9495
|
+
return null;
|
|
9496
|
+
}
|
|
9497
|
+
const { orm } = found;
|
|
9498
|
+
const itemId2 = found.item.id;
|
|
9499
|
+
if (options2.clear) {
|
|
9500
|
+
await orm.update(items).set(clearPatch).where(eq17(items.id, itemId2));
|
|
9501
|
+
console.log(
|
|
9502
|
+
chalk62.green(
|
|
9503
|
+
`Cleared ${label2} association on item ${formatItemId(itemId2)}.`
|
|
9504
|
+
)
|
|
9505
|
+
);
|
|
9506
|
+
return null;
|
|
9507
|
+
}
|
|
9508
|
+
return { orm, itemId: itemId2 };
|
|
9509
|
+
}
|
|
9453
9510
|
|
|
9454
|
-
// src/commands/
|
|
9511
|
+
// src/commands/backlog/associate-github/fetchGithubIssueTitle.ts
|
|
9455
9512
|
import { execSync as execSync30 } from "child_process";
|
|
9456
|
-
|
|
9513
|
+
function fetchGithubIssueTitle(issue) {
|
|
9514
|
+
const match = /^([^/]+)\/([^#]+)#(\d+)$/.exec(issue);
|
|
9515
|
+
if (!match) return void 0;
|
|
9516
|
+
const [, owner, repo, number] = match;
|
|
9517
|
+
try {
|
|
9518
|
+
const result = execSync30(
|
|
9519
|
+
`gh issue view ${number} -R ${owner}/${repo} --json title`,
|
|
9520
|
+
{ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
|
|
9521
|
+
);
|
|
9522
|
+
const parsed = JSON.parse(result);
|
|
9523
|
+
return parsed.title;
|
|
9524
|
+
} catch {
|
|
9525
|
+
return void 0;
|
|
9526
|
+
}
|
|
9527
|
+
}
|
|
9528
|
+
|
|
9529
|
+
// src/commands/backlog/associate-github/normalizeGithubIssue.ts
|
|
9530
|
+
var URL_PATTERN = /^https?:\/\/github\.com\/([^/\s]+)\/([^/\s]+)\/issues\/(\d+)\/?$/;
|
|
9531
|
+
var SHORTHAND_PATTERN = /^([^/\s]+)\/([^/\s#]+)#(\d+)$/;
|
|
9532
|
+
function normalizeGithubIssue(input) {
|
|
9533
|
+
const trimmed = input.trim();
|
|
9534
|
+
const match = URL_PATTERN.exec(trimmed) ?? SHORTHAND_PATTERN.exec(trimmed);
|
|
9535
|
+
if (!match) return null;
|
|
9536
|
+
const [, owner, repo, number] = match;
|
|
9537
|
+
return `${owner}/${repo}#${number}`;
|
|
9538
|
+
}
|
|
9539
|
+
|
|
9540
|
+
// src/commands/backlog/associate-github/index.ts
|
|
9541
|
+
async function associateGithub(id, issue, options2) {
|
|
9542
|
+
const target = await beginAssociation(
|
|
9543
|
+
id,
|
|
9544
|
+
options2,
|
|
9545
|
+
{ githubIssue: null },
|
|
9546
|
+
"GitHub"
|
|
9547
|
+
);
|
|
9548
|
+
if (!target) return;
|
|
9549
|
+
const { orm, itemId: itemId2 } = target;
|
|
9550
|
+
if (!issue) {
|
|
9551
|
+
console.log(
|
|
9552
|
+
chalk63.red("Provide a GitHub issue, or use --clear to remove one.")
|
|
9553
|
+
);
|
|
9554
|
+
process.exitCode = 1;
|
|
9555
|
+
return;
|
|
9556
|
+
}
|
|
9557
|
+
const normalized = normalizeGithubIssue(issue);
|
|
9558
|
+
if (!normalized) {
|
|
9559
|
+
console.log(
|
|
9560
|
+
chalk63.red(
|
|
9561
|
+
`Malformed GitHub issue "${issue}". Expected owner/repo#number or a github.com issue URL.`
|
|
9562
|
+
)
|
|
9563
|
+
);
|
|
9564
|
+
process.exitCode = 1;
|
|
9565
|
+
return;
|
|
9566
|
+
}
|
|
9567
|
+
const title = fetchGithubIssueTitle(normalized);
|
|
9568
|
+
await orm.update(items).set({ githubIssue: normalized, jiraKey: null }).where(eq18(items.id, itemId2));
|
|
9569
|
+
console.log(
|
|
9570
|
+
chalk63.green(`Associated ${normalized} with item ${formatItemId(itemId2)}.`),
|
|
9571
|
+
title ? chalk63.dim(`(${title})`) : ""
|
|
9572
|
+
);
|
|
9573
|
+
}
|
|
9574
|
+
|
|
9575
|
+
// src/commands/backlog/registerAssociateGithubCommand.ts
|
|
9576
|
+
function registerAssociateGithubCommand(cmd) {
|
|
9577
|
+
cmd.command("associate-github <id> [issue]").description("Associate a GitHub issue with a backlog item").option("--clear", "Remove the GitHub association from the item").action(associateGithub);
|
|
9578
|
+
}
|
|
9579
|
+
|
|
9580
|
+
// src/commands/backlog/associate-jira/index.ts
|
|
9581
|
+
import chalk65 from "chalk";
|
|
9582
|
+
import { eq as eq19 } from "drizzle-orm";
|
|
9583
|
+
|
|
9584
|
+
// src/commands/jira/fetchIssue.ts
|
|
9585
|
+
import { execSync as execSync31 } from "child_process";
|
|
9586
|
+
import chalk64 from "chalk";
|
|
9457
9587
|
function fetchIssue(issueKey, fields) {
|
|
9458
9588
|
let result;
|
|
9459
9589
|
try {
|
|
9460
|
-
result =
|
|
9590
|
+
result = execSync31(
|
|
9461
9591
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
9462
9592
|
{ encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }
|
|
9463
9593
|
);
|
|
@@ -9466,15 +9596,15 @@ function fetchIssue(issueKey, fields) {
|
|
|
9466
9596
|
const stderr = error.stderr;
|
|
9467
9597
|
if (stderr.includes("unauthorized")) {
|
|
9468
9598
|
console.error(
|
|
9469
|
-
|
|
9599
|
+
chalk64.red("Jira authentication expired."),
|
|
9470
9600
|
"Run",
|
|
9471
|
-
|
|
9601
|
+
chalk64.cyan("assist jira auth"),
|
|
9472
9602
|
"to re-authenticate."
|
|
9473
9603
|
);
|
|
9474
9604
|
process.exit(1);
|
|
9475
9605
|
}
|
|
9476
9606
|
}
|
|
9477
|
-
console.error(
|
|
9607
|
+
console.error(chalk64.red(`Failed to fetch ${issueKey}.`));
|
|
9478
9608
|
process.exit(1);
|
|
9479
9609
|
}
|
|
9480
9610
|
return JSON.parse(result);
|
|
@@ -9483,28 +9613,17 @@ function fetchIssue(issueKey, fields) {
|
|
|
9483
9613
|
// src/commands/backlog/associate-jira/index.ts
|
|
9484
9614
|
var JIRA_KEY_PATTERN = /^[A-Z]+-\d+$/;
|
|
9485
9615
|
async function associateJira(id, key, options2) {
|
|
9486
|
-
const
|
|
9487
|
-
if (!
|
|
9488
|
-
|
|
9489
|
-
return;
|
|
9490
|
-
}
|
|
9491
|
-
const { orm } = found;
|
|
9492
|
-
const itemId2 = found.item.id;
|
|
9493
|
-
if (options2.clear) {
|
|
9494
|
-
await orm.update(items).set({ jiraKey: null }).where(eq17(items.id, itemId2));
|
|
9495
|
-
console.log(
|
|
9496
|
-
chalk63.green(`Cleared Jira association on item ${formatItemId(itemId2)}.`)
|
|
9497
|
-
);
|
|
9498
|
-
return;
|
|
9499
|
-
}
|
|
9616
|
+
const target = await beginAssociation(id, options2, { jiraKey: null }, "Jira");
|
|
9617
|
+
if (!target) return;
|
|
9618
|
+
const { orm, itemId: itemId2 } = target;
|
|
9500
9619
|
if (!key) {
|
|
9501
|
-
console.log(
|
|
9620
|
+
console.log(chalk65.red("Provide a Jira key, or use --clear to remove one."));
|
|
9502
9621
|
process.exitCode = 1;
|
|
9503
9622
|
return;
|
|
9504
9623
|
}
|
|
9505
9624
|
if (!JIRA_KEY_PATTERN.test(key)) {
|
|
9506
9625
|
console.log(
|
|
9507
|
-
|
|
9626
|
+
chalk65.red(`Malformed Jira key "${key}". Expected a key like PROJ-123.`)
|
|
9508
9627
|
);
|
|
9509
9628
|
process.exitCode = 1;
|
|
9510
9629
|
return;
|
|
@@ -9512,10 +9631,10 @@ async function associateJira(id, key, options2) {
|
|
|
9512
9631
|
const parsed = fetchIssue(key, "summary");
|
|
9513
9632
|
const fields = parsed?.fields;
|
|
9514
9633
|
const summary = fields?.summary;
|
|
9515
|
-
await orm.update(items).set({ jiraKey: key }).where(
|
|
9634
|
+
await orm.update(items).set({ jiraKey: key, githubIssue: null }).where(eq19(items.id, itemId2));
|
|
9516
9635
|
console.log(
|
|
9517
|
-
|
|
9518
|
-
summary ?
|
|
9636
|
+
chalk65.green(`Associated ${key} with item ${formatItemId(itemId2)}.`),
|
|
9637
|
+
summary ? chalk65.dim(`(${summary})`) : ""
|
|
9519
9638
|
);
|
|
9520
9639
|
}
|
|
9521
9640
|
|
|
@@ -9525,29 +9644,29 @@ function registerAssociateJiraCommand(cmd) {
|
|
|
9525
9644
|
}
|
|
9526
9645
|
|
|
9527
9646
|
// src/commands/backlog/comment/index.ts
|
|
9528
|
-
import
|
|
9647
|
+
import chalk66 from "chalk";
|
|
9529
9648
|
async function comment(id, text17) {
|
|
9530
9649
|
const found = await findOneItem(id);
|
|
9531
9650
|
if (!found) process.exit(1);
|
|
9532
9651
|
await appendComment(found.orm, found.item.id, text17);
|
|
9533
9652
|
console.log(
|
|
9534
|
-
|
|
9653
|
+
chalk66.green(`Comment added to item ${formatItemId(found.item.id)}.`)
|
|
9535
9654
|
);
|
|
9536
9655
|
}
|
|
9537
9656
|
|
|
9538
9657
|
// src/commands/backlog/comments/index.ts
|
|
9539
|
-
import
|
|
9658
|
+
import chalk67 from "chalk";
|
|
9540
9659
|
async function comments2(id) {
|
|
9541
9660
|
const found = await findOneItem(id);
|
|
9542
9661
|
if (!found) process.exit(1);
|
|
9543
9662
|
const { item } = found;
|
|
9544
9663
|
const entries = item.comments ?? [];
|
|
9545
9664
|
if (entries.length === 0) {
|
|
9546
|
-
console.log(
|
|
9665
|
+
console.log(chalk67.dim(`No comments on item ${formatItemId(item.id)}.`));
|
|
9547
9666
|
return;
|
|
9548
9667
|
}
|
|
9549
9668
|
console.log(
|
|
9550
|
-
|
|
9669
|
+
chalk67.bold(`Comments for ${formatItemId(item.id)}: ${item.name}
|
|
9551
9670
|
`)
|
|
9552
9671
|
);
|
|
9553
9672
|
for (const entry of entries) {
|
|
@@ -9557,7 +9676,7 @@ async function comments2(id) {
|
|
|
9557
9676
|
}
|
|
9558
9677
|
|
|
9559
9678
|
// src/commands/backlog/delete-comment/index.ts
|
|
9560
|
-
import
|
|
9679
|
+
import chalk68 from "chalk";
|
|
9561
9680
|
async function deleteCommentCmd(id, commentId) {
|
|
9562
9681
|
const found = await findOneItem(id);
|
|
9563
9682
|
if (!found) process.exit(1);
|
|
@@ -9570,14 +9689,14 @@ async function deleteCommentCmd(id, commentId) {
|
|
|
9570
9689
|
switch (outcome) {
|
|
9571
9690
|
case "deleted":
|
|
9572
9691
|
console.log(
|
|
9573
|
-
|
|
9692
|
+
chalk68.green(
|
|
9574
9693
|
`Comment #${commentId} deleted from item ${formatItemId(itemId2)}.`
|
|
9575
9694
|
)
|
|
9576
9695
|
);
|
|
9577
9696
|
break;
|
|
9578
9697
|
case "not-found":
|
|
9579
9698
|
console.log(
|
|
9580
|
-
|
|
9699
|
+
chalk68.red(
|
|
9581
9700
|
`Comment #${commentId} not found on item ${formatItemId(itemId2)}.`
|
|
9582
9701
|
)
|
|
9583
9702
|
);
|
|
@@ -9585,7 +9704,7 @@ async function deleteCommentCmd(id, commentId) {
|
|
|
9585
9704
|
break;
|
|
9586
9705
|
case "is-summary":
|
|
9587
9706
|
console.log(
|
|
9588
|
-
|
|
9707
|
+
chalk68.red(
|
|
9589
9708
|
`Comment #${commentId} is a phase summary and cannot be deleted.`
|
|
9590
9709
|
)
|
|
9591
9710
|
);
|
|
@@ -9610,7 +9729,7 @@ function registerExportCommand(cmd) {
|
|
|
9610
9729
|
|
|
9611
9730
|
// src/commands/backlog/import/index.ts
|
|
9612
9731
|
import { readFile } from "fs/promises";
|
|
9613
|
-
import
|
|
9732
|
+
import chalk70 from "chalk";
|
|
9614
9733
|
|
|
9615
9734
|
// src/commands/backlog/dump/countCopyRows.ts
|
|
9616
9735
|
function countCopyRows(data) {
|
|
@@ -9682,7 +9801,7 @@ function validateDump({ header, sections }) {
|
|
|
9682
9801
|
}
|
|
9683
9802
|
|
|
9684
9803
|
// src/commands/backlog/import/confirmReplace.ts
|
|
9685
|
-
import
|
|
9804
|
+
import chalk69 from "chalk";
|
|
9686
9805
|
async function countRows(client, table) {
|
|
9687
9806
|
const { rows } = await client.query(
|
|
9688
9807
|
`SELECT count(*)::int AS n FROM ${table}`
|
|
@@ -9693,7 +9812,7 @@ function printSummary(tables, current, incoming) {
|
|
|
9693
9812
|
const lines = tables.map(
|
|
9694
9813
|
(t, i) => ` ${t.name}: ${current[i]} \u2192 ${incoming[i]} rows`
|
|
9695
9814
|
);
|
|
9696
|
-
console.error(
|
|
9815
|
+
console.error(chalk69.bold("\nThis will REPLACE all backlog data:"));
|
|
9697
9816
|
console.error(`${lines.join("\n")}
|
|
9698
9817
|
`);
|
|
9699
9818
|
}
|
|
@@ -9723,8 +9842,8 @@ async function readStdinBuffer() {
|
|
|
9723
9842
|
import { finished } from "stream/promises";
|
|
9724
9843
|
import { from as copyFrom } from "pg-copy-streams";
|
|
9725
9844
|
async function copyTableIn(client, table, data) {
|
|
9726
|
-
const
|
|
9727
|
-
const stream = client.query(copyFrom(
|
|
9845
|
+
const sql24 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
|
|
9846
|
+
const stream = client.query(copyFrom(sql24));
|
|
9728
9847
|
stream.end(data);
|
|
9729
9848
|
await finished(stream);
|
|
9730
9849
|
}
|
|
@@ -9795,13 +9914,13 @@ async function importBacklog(file, options2 = {}) {
|
|
|
9795
9914
|
);
|
|
9796
9915
|
await withDbClient(async (client) => {
|
|
9797
9916
|
if (!options2.yes && !await confirmReplace(client, tables, incoming, !file)) {
|
|
9798
|
-
console.error(
|
|
9917
|
+
console.error(chalk70.yellow("Import cancelled; no changes made."));
|
|
9799
9918
|
return;
|
|
9800
9919
|
}
|
|
9801
9920
|
await restore(client, parsed);
|
|
9802
9921
|
const total = incoming.reduce((sum, n) => sum + n, 0);
|
|
9803
9922
|
console.error(
|
|
9804
|
-
|
|
9923
|
+
chalk70.green(
|
|
9805
9924
|
`Imported backlog: ${total} rows restored across ${tables.length} tables.`
|
|
9806
9925
|
)
|
|
9807
9926
|
);
|
|
@@ -9818,18 +9937,18 @@ function registerImportCommand(cmd) {
|
|
|
9818
9937
|
}
|
|
9819
9938
|
|
|
9820
9939
|
// src/commands/backlog/add/index.ts
|
|
9821
|
-
import
|
|
9940
|
+
import chalk72 from "chalk";
|
|
9822
9941
|
|
|
9823
9942
|
// src/commands/backlog/insertPhaseAt.ts
|
|
9824
|
-
import { eq as
|
|
9943
|
+
import { eq as eq21 } from "drizzle-orm";
|
|
9825
9944
|
|
|
9826
9945
|
// src/commands/backlog/shiftPhasesUp.ts
|
|
9827
|
-
import { and as and8, desc as desc3, eq as
|
|
9946
|
+
import { and as and8, desc as desc3, eq as eq20, gte } from "drizzle-orm";
|
|
9828
9947
|
async function shiftPhasesUp(db, itemId2, fromIdx) {
|
|
9829
|
-
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and8(
|
|
9948
|
+
const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and8(eq20(planPhases.itemId, itemId2), gte(planPhases.idx, fromIdx))).orderBy(desc3(planPhases.idx));
|
|
9830
9949
|
for (const p of toShift) {
|
|
9831
|
-
await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and8(
|
|
9832
|
-
await db.update(planPhases).set({ idx: p.idx + 1 }).where(and8(
|
|
9950
|
+
await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and8(eq20(planTasks.itemId, itemId2), eq20(planTasks.phaseIdx, p.idx)));
|
|
9951
|
+
await db.update(planPhases).set({ idx: p.idx + 1 }).where(and8(eq20(planPhases.itemId, itemId2), eq20(planPhases.idx, p.idx)));
|
|
9833
9952
|
}
|
|
9834
9953
|
}
|
|
9835
9954
|
|
|
@@ -9842,17 +9961,17 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
|
|
|
9842
9961
|
await tx.insert(planTasks).values(tasks.map((task, i) => ({ itemId: itemId2, phaseIdx, idx: i, task })));
|
|
9843
9962
|
}
|
|
9844
9963
|
if (currentPhase !== void 0 && currentPhase - 1 >= phaseIdx) {
|
|
9845
|
-
await tx.update(items).set({ currentPhase: phaseIdx + 1 }).where(
|
|
9964
|
+
await tx.update(items).set({ currentPhase: phaseIdx + 1 }).where(eq21(items.id, itemId2));
|
|
9846
9965
|
}
|
|
9847
9966
|
});
|
|
9848
9967
|
}
|
|
9849
9968
|
|
|
9850
9969
|
// src/commands/backlog/insertSubtask.ts
|
|
9851
|
-
import { sql as
|
|
9970
|
+
import { sql as sql16 } from "drizzle-orm";
|
|
9852
9971
|
async function insertSubtask(orm, itemId2, title, description) {
|
|
9853
9972
|
await orm.insert(itemSubtasks).values({
|
|
9854
9973
|
itemId: itemId2,
|
|
9855
|
-
idx:
|
|
9974
|
+
idx: sql16`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
|
|
9856
9975
|
title,
|
|
9857
9976
|
description: description ?? null,
|
|
9858
9977
|
status: "todo"
|
|
@@ -9860,11 +9979,11 @@ async function insertSubtask(orm, itemId2, title, description) {
|
|
|
9860
9979
|
}
|
|
9861
9980
|
|
|
9862
9981
|
// src/commands/backlog/ensureRemoteOrigin.ts
|
|
9863
|
-
import
|
|
9982
|
+
import chalk71 from "chalk";
|
|
9864
9983
|
function ensureRemoteOrigin() {
|
|
9865
9984
|
if (getRemoteOriginUrl(getBacklogDir())) return true;
|
|
9866
9985
|
console.log(
|
|
9867
|
-
|
|
9986
|
+
chalk71.red(
|
|
9868
9987
|
"Backlog requires a git remote so items get a stable origin.\nAdd one with: git remote add origin <url>"
|
|
9869
9988
|
)
|
|
9870
9989
|
);
|
|
@@ -9968,23 +10087,23 @@ async function add(options2) {
|
|
|
9968
10087
|
for (const subtask of loadConfig().subtasks ?? []) {
|
|
9969
10088
|
await insertSubtask(orm, id, subtask.title, subtask.description);
|
|
9970
10089
|
}
|
|
9971
|
-
console.log(
|
|
10090
|
+
console.log(chalk72.green(`Added item ${formatItemId(id)}: ${name}`));
|
|
9972
10091
|
}
|
|
9973
10092
|
|
|
9974
10093
|
// src/commands/backlog/addPhase.ts
|
|
9975
|
-
import
|
|
10094
|
+
import chalk74 from "chalk";
|
|
9976
10095
|
|
|
9977
10096
|
// src/commands/backlog/resolveInsertPosition.ts
|
|
9978
|
-
import
|
|
9979
|
-
import { count as count2, eq as
|
|
10097
|
+
import chalk73 from "chalk";
|
|
10098
|
+
import { count as count2, eq as eq22 } from "drizzle-orm";
|
|
9980
10099
|
async function resolveInsertPosition(orm, itemId2, position) {
|
|
9981
|
-
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(
|
|
10100
|
+
const [row] = await orm.select({ cnt: count2() }).from(planPhases).where(eq22(planPhases.itemId, itemId2));
|
|
9982
10101
|
const phaseCount = row?.cnt ?? 0;
|
|
9983
10102
|
if (position === void 0) return phaseCount;
|
|
9984
10103
|
const pos = Number.parseInt(position, 10);
|
|
9985
10104
|
if (pos < 1 || pos > phaseCount + 1) {
|
|
9986
10105
|
console.log(
|
|
9987
|
-
|
|
10106
|
+
chalk73.red(
|
|
9988
10107
|
`Position ${pos} is out of range. Must be between 1 and ${phaseCount + 1}.`
|
|
9989
10108
|
)
|
|
9990
10109
|
);
|
|
@@ -10006,7 +10125,7 @@ async function addPhase(id, name, options2) {
|
|
|
10006
10125
|
if (!found) return;
|
|
10007
10126
|
const tasks = options2.task ?? [];
|
|
10008
10127
|
if (tasks.length === 0) {
|
|
10009
|
-
console.log(
|
|
10128
|
+
console.log(chalk74.red("At least one --task is required."));
|
|
10010
10129
|
process.exitCode = 1;
|
|
10011
10130
|
return;
|
|
10012
10131
|
}
|
|
@@ -10025,14 +10144,14 @@ async function addPhase(id, name, options2) {
|
|
|
10025
10144
|
);
|
|
10026
10145
|
const verb = options2.position !== void 0 ? "Inserted" : "Added";
|
|
10027
10146
|
console.log(
|
|
10028
|
-
|
|
10147
|
+
chalk74.green(
|
|
10029
10148
|
`${verb} phase ${phaseIdx + 1} "${name}" to item ${formatItemId(itemId2)} with ${tasks.length} task(s).`
|
|
10030
10149
|
)
|
|
10031
10150
|
);
|
|
10032
10151
|
}
|
|
10033
10152
|
|
|
10034
10153
|
// src/commands/backlog/list/index.ts
|
|
10035
|
-
import
|
|
10154
|
+
import chalk75 from "chalk";
|
|
10036
10155
|
function filterItems(items2, options2) {
|
|
10037
10156
|
if (options2.status) return items2.filter((i) => i.status === options2.status);
|
|
10038
10157
|
if (!options2.all)
|
|
@@ -10046,19 +10165,19 @@ function repoPrefixer(items2, allRepos) {
|
|
|
10046
10165
|
);
|
|
10047
10166
|
const repoNameOf = (item) => item.origin ? labels.get(item.origin) ?? "" : "";
|
|
10048
10167
|
const width = Math.max(0, ...items2.map((i) => repoNameOf(i).length));
|
|
10049
|
-
return (item) => `${
|
|
10168
|
+
return (item) => `${chalk75.dim(repoNameOf(item).padEnd(width))} `;
|
|
10050
10169
|
}
|
|
10051
10170
|
async function list2(options2) {
|
|
10052
10171
|
const allItems = await loadBacklog(options2.allRepos);
|
|
10053
10172
|
const items2 = filterItems(allItems, options2);
|
|
10054
10173
|
if (items2.length === 0) {
|
|
10055
|
-
console.log(
|
|
10174
|
+
console.log(chalk75.dim("Backlog is empty."));
|
|
10056
10175
|
return;
|
|
10057
10176
|
}
|
|
10058
10177
|
const prefixOf = repoPrefixer(items2, !!options2.allRepos);
|
|
10059
10178
|
for (const item of items2) {
|
|
10060
10179
|
console.log(
|
|
10061
|
-
`${prefixOf(item)}${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
10180
|
+
`${prefixOf(item)}${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk75.dim(formatItemId(item.id))} ${starMarker(item)}${item.name}${phaseLabel(item)}${dependencyLabel(item, allItems)}`
|
|
10062
10181
|
);
|
|
10063
10182
|
if (options2.verbose) {
|
|
10064
10183
|
printVerboseDetails(item);
|
|
@@ -10086,7 +10205,7 @@ function registerItemCommands(cmd) {
|
|
|
10086
10205
|
}
|
|
10087
10206
|
|
|
10088
10207
|
// src/commands/backlog/link.ts
|
|
10089
|
-
import
|
|
10208
|
+
import chalk77 from "chalk";
|
|
10090
10209
|
|
|
10091
10210
|
// src/commands/backlog/hasCycle.ts
|
|
10092
10211
|
function hasCycle(adjacency, fromId, toId) {
|
|
@@ -10105,9 +10224,9 @@ function hasCycle(adjacency, fromId, toId) {
|
|
|
10105
10224
|
}
|
|
10106
10225
|
|
|
10107
10226
|
// src/commands/backlog/loadDependencyGraph.ts
|
|
10108
|
-
import { eq as
|
|
10227
|
+
import { eq as eq23 } from "drizzle-orm";
|
|
10109
10228
|
async function loadDependencyGraph(orm) {
|
|
10110
|
-
const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(
|
|
10229
|
+
const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq23(links.type, "depends-on"));
|
|
10111
10230
|
const graph = /* @__PURE__ */ new Map();
|
|
10112
10231
|
for (const { itemId: itemId2, targetId } of rows) {
|
|
10113
10232
|
const bucket = graph.get(itemId2);
|
|
@@ -10118,14 +10237,14 @@ async function loadDependencyGraph(orm) {
|
|
|
10118
10237
|
}
|
|
10119
10238
|
|
|
10120
10239
|
// src/commands/backlog/validateLinkTarget.ts
|
|
10121
|
-
import
|
|
10240
|
+
import chalk76 from "chalk";
|
|
10122
10241
|
function validateLinkTarget(fromItem, fromNum, toNum, linkType) {
|
|
10123
10242
|
const duplicate = (fromItem.links ?? []).some(
|
|
10124
10243
|
(l) => l.targetId === toNum && l.type === linkType
|
|
10125
10244
|
);
|
|
10126
10245
|
if (duplicate) {
|
|
10127
10246
|
console.log(
|
|
10128
|
-
|
|
10247
|
+
chalk76.yellow(
|
|
10129
10248
|
`Link already exists: ${formatItemId(fromNum)} ${linkType} ${formatItemId(toNum)}`
|
|
10130
10249
|
)
|
|
10131
10250
|
);
|
|
@@ -10136,7 +10255,7 @@ function validateLinkTarget(fromItem, fromNum, toNum, linkType) {
|
|
|
10136
10255
|
|
|
10137
10256
|
// src/commands/backlog/link.ts
|
|
10138
10257
|
function fail2(message) {
|
|
10139
|
-
console.log(
|
|
10258
|
+
console.log(chalk77.red(message));
|
|
10140
10259
|
return void 0;
|
|
10141
10260
|
}
|
|
10142
10261
|
function parseLinkType(type) {
|
|
@@ -10169,38 +10288,38 @@ async function link(fromId, toId, opts) {
|
|
|
10169
10288
|
if (!validateLinkTarget(fromItem, fromNum, toNum, linkType)) return;
|
|
10170
10289
|
if (await createsCycle(orm, linkType, fromNum, toNum)) return;
|
|
10171
10290
|
await orm.insert(links).values({ itemId: fromNum, type: linkType, targetId: toNum });
|
|
10172
|
-
console.log(
|
|
10291
|
+
console.log(chalk77.green(`Linked ${from} ${linkType} ${to} (${toItem.name})`));
|
|
10173
10292
|
}
|
|
10174
10293
|
|
|
10175
10294
|
// src/commands/backlog/unlink.ts
|
|
10176
|
-
import
|
|
10177
|
-
import { and as and9, eq as
|
|
10295
|
+
import chalk78 from "chalk";
|
|
10296
|
+
import { and as and9, eq as eq24 } from "drizzle-orm";
|
|
10178
10297
|
async function unlink(fromId, toId) {
|
|
10179
10298
|
const fromNum = parseItemId(fromId);
|
|
10180
10299
|
const toNum = parseItemId(toId);
|
|
10181
10300
|
const { orm } = await getReady();
|
|
10182
10301
|
const fromItem = await loadItem(orm, fromNum);
|
|
10183
10302
|
if (!fromItem) {
|
|
10184
|
-
console.log(
|
|
10303
|
+
console.log(chalk78.red(`Item ${formatItemId(fromNum)} not found.`));
|
|
10185
10304
|
return;
|
|
10186
10305
|
}
|
|
10187
10306
|
if (!fromItem.links || fromItem.links.length === 0) {
|
|
10188
10307
|
console.log(
|
|
10189
|
-
|
|
10308
|
+
chalk78.yellow(`No links found on item ${formatItemId(fromNum)}.`)
|
|
10190
10309
|
);
|
|
10191
10310
|
return;
|
|
10192
10311
|
}
|
|
10193
10312
|
if (!fromItem.links.some((l) => l.targetId === toNum)) {
|
|
10194
10313
|
console.log(
|
|
10195
|
-
|
|
10314
|
+
chalk78.yellow(
|
|
10196
10315
|
`No link from ${formatItemId(fromNum)} to ${formatItemId(toNum)} found.`
|
|
10197
10316
|
)
|
|
10198
10317
|
);
|
|
10199
10318
|
return;
|
|
10200
10319
|
}
|
|
10201
|
-
await orm.delete(links).where(and9(
|
|
10320
|
+
await orm.delete(links).where(and9(eq24(links.itemId, fromNum), eq24(links.targetId, toNum)));
|
|
10202
10321
|
console.log(
|
|
10203
|
-
|
|
10322
|
+
chalk78.green(
|
|
10204
10323
|
`Removed link from ${formatItemId(fromNum)} to ${formatItemId(toNum)}.`
|
|
10205
10324
|
)
|
|
10206
10325
|
);
|
|
@@ -10217,25 +10336,25 @@ function registerLinkCommands(cmd) {
|
|
|
10217
10336
|
}
|
|
10218
10337
|
|
|
10219
10338
|
// src/commands/backlog/move-repo/index.ts
|
|
10220
|
-
import
|
|
10221
|
-
import { eq as
|
|
10339
|
+
import chalk80 from "chalk";
|
|
10340
|
+
import { eq as eq26 } from "drizzle-orm";
|
|
10222
10341
|
|
|
10223
10342
|
// src/commands/backlog/move-repo/confirmMove.ts
|
|
10224
|
-
import
|
|
10343
|
+
import chalk79 from "chalk";
|
|
10225
10344
|
function pluralItems(n) {
|
|
10226
10345
|
return `${n} item${n === 1 ? "" : "s"}`;
|
|
10227
10346
|
}
|
|
10228
10347
|
async function confirmMove(cnt, oldOrigin, newOrigin) {
|
|
10229
10348
|
console.log(
|
|
10230
|
-
`${pluralItems(cnt)}: ${
|
|
10349
|
+
`${pluralItems(cnt)}: ${chalk79.cyan(oldOrigin)} \u2192 ${chalk79.cyan(newOrigin)}`
|
|
10231
10350
|
);
|
|
10232
10351
|
return promptConfirm(`Retag ${pluralItems(cnt)}?`);
|
|
10233
10352
|
}
|
|
10234
10353
|
|
|
10235
10354
|
// src/commands/backlog/move-repo/countByOrigin.ts
|
|
10236
|
-
import { count as count3, eq as
|
|
10355
|
+
import { count as count3, eq as eq25 } from "drizzle-orm";
|
|
10237
10356
|
async function countByOrigin(orm, origin) {
|
|
10238
|
-
const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(
|
|
10357
|
+
const [{ cnt }] = await orm.select({ cnt: count3() }).from(items).where(eq25(items.origin, origin));
|
|
10239
10358
|
return cnt;
|
|
10240
10359
|
}
|
|
10241
10360
|
|
|
@@ -10259,7 +10378,7 @@ Pass the full origin.`
|
|
|
10259
10378
|
|
|
10260
10379
|
// src/commands/backlog/move-repo/index.ts
|
|
10261
10380
|
function fail3(message) {
|
|
10262
|
-
console.log(
|
|
10381
|
+
console.log(chalk80.red(message));
|
|
10263
10382
|
process.exitCode = 1;
|
|
10264
10383
|
}
|
|
10265
10384
|
async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
|
|
@@ -10275,12 +10394,12 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
|
|
|
10275
10394
|
}
|
|
10276
10395
|
const cnt = await countByOrigin(orm, oldOrigin);
|
|
10277
10396
|
if (!options2.yes && !await confirmMove(cnt, oldOrigin, newOrigin)) {
|
|
10278
|
-
console.log(
|
|
10397
|
+
console.log(chalk80.yellow("Move cancelled; no changes made."));
|
|
10279
10398
|
return;
|
|
10280
10399
|
}
|
|
10281
|
-
await orm.update(items).set({ origin: newOrigin }).where(
|
|
10400
|
+
await orm.update(items).set({ origin: newOrigin }).where(eq26(items.origin, oldOrigin));
|
|
10282
10401
|
console.log(
|
|
10283
|
-
|
|
10402
|
+
chalk80.green(
|
|
10284
10403
|
`Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
|
|
10285
10404
|
)
|
|
10286
10405
|
);
|
|
@@ -10309,7 +10428,7 @@ function registerPlanCommands(cmd) {
|
|
|
10309
10428
|
}
|
|
10310
10429
|
|
|
10311
10430
|
// src/commands/backlog/refine.ts
|
|
10312
|
-
import
|
|
10431
|
+
import chalk83 from "chalk";
|
|
10313
10432
|
import enquirer7 from "enquirer";
|
|
10314
10433
|
|
|
10315
10434
|
// src/commands/backlog/launchMode.ts
|
|
@@ -10343,7 +10462,7 @@ function spawnHarness(harness, prompt, options2 = {}) {
|
|
|
10343
10462
|
}
|
|
10344
10463
|
|
|
10345
10464
|
// src/commands/backlog/handleLaunchSignal.ts
|
|
10346
|
-
import
|
|
10465
|
+
import chalk82 from "chalk";
|
|
10347
10466
|
|
|
10348
10467
|
// src/commands/backlog/surfaceCreatedItem.ts
|
|
10349
10468
|
async function surfaceCreatedItem(slashCommand, id) {
|
|
@@ -10366,32 +10485,32 @@ async function surfaceCreatedItem(slashCommand, id) {
|
|
|
10366
10485
|
}
|
|
10367
10486
|
|
|
10368
10487
|
// src/commands/backlog/tryRunById.ts
|
|
10369
|
-
import
|
|
10488
|
+
import chalk81 from "chalk";
|
|
10370
10489
|
async function tryRunById(id, options2) {
|
|
10371
10490
|
const numericId = parseItemId(id);
|
|
10372
10491
|
const label2 = formatItemId(numericId);
|
|
10373
10492
|
const { orm } = await getReady();
|
|
10374
10493
|
const item = await loadItem(orm, numericId);
|
|
10375
10494
|
if (!item) {
|
|
10376
|
-
console.log(
|
|
10495
|
+
console.log(chalk81.red(`Item ${label2} not found.`));
|
|
10377
10496
|
return false;
|
|
10378
10497
|
}
|
|
10379
10498
|
if (item.status === "done") {
|
|
10380
|
-
console.log(
|
|
10499
|
+
console.log(chalk81.red(`Item ${label2} is already done.`));
|
|
10381
10500
|
return false;
|
|
10382
10501
|
}
|
|
10383
10502
|
if (item.status === "wontdo") {
|
|
10384
|
-
console.log(
|
|
10503
|
+
console.log(chalk81.red(`Item ${label2} is marked won't do.`));
|
|
10385
10504
|
return false;
|
|
10386
10505
|
}
|
|
10387
10506
|
const hasDeps = (item.links ?? []).some((l) => l.type === "depends-on");
|
|
10388
10507
|
if (hasDeps && isBlocked(item, await loadItemSummaries(orm, getOrigin()))) {
|
|
10389
10508
|
console.log(
|
|
10390
|
-
|
|
10509
|
+
chalk81.red(`Item ${label2} is blocked by unresolved dependencies.`)
|
|
10391
10510
|
);
|
|
10392
10511
|
return false;
|
|
10393
10512
|
}
|
|
10394
|
-
console.log(
|
|
10513
|
+
console.log(chalk81.bold(`
|
|
10395
10514
|
Running backlog item ${label2}...
|
|
10396
10515
|
`));
|
|
10397
10516
|
await run2(id, options2);
|
|
@@ -10410,13 +10529,13 @@ async function handleLaunchSignal(slashCommand, once) {
|
|
|
10410
10529
|
if (typeof signal.id === "string" && signal.id) {
|
|
10411
10530
|
if (await tryRunById(signal.id, { allowEdits: true })) return;
|
|
10412
10531
|
}
|
|
10413
|
-
console.log(
|
|
10532
|
+
console.log(chalk82.bold("\nChaining into assist next...\n"));
|
|
10414
10533
|
await next({ allowEdits: true, once });
|
|
10415
10534
|
}
|
|
10416
10535
|
} catch (error) {
|
|
10417
10536
|
const message = error instanceof Error ? error.message : String(error);
|
|
10418
10537
|
console.error(
|
|
10419
|
-
|
|
10538
|
+
chalk82.yellow(
|
|
10420
10539
|
`
|
|
10421
10540
|
Could not complete post-run step (${message}).
|
|
10422
10541
|
This is usually a transient database/network blip \u2014 the work is saved and the session is safe to resume.`
|
|
@@ -10463,13 +10582,13 @@ async function pickItemForRefine() {
|
|
|
10463
10582
|
(i) => i.status === "todo" || i.status === "in-progress"
|
|
10464
10583
|
);
|
|
10465
10584
|
if (active.length === 0) {
|
|
10466
|
-
console.log(
|
|
10585
|
+
console.log(chalk83.yellow("No active backlog items to refine."));
|
|
10467
10586
|
return void 0;
|
|
10468
10587
|
}
|
|
10469
10588
|
if (active.length === 1) {
|
|
10470
10589
|
const item = active[0];
|
|
10471
10590
|
console.log(
|
|
10472
|
-
|
|
10591
|
+
chalk83.bold(`Auto-selecting item ${formatItemId(item.id)}: ${item.name}`)
|
|
10473
10592
|
);
|
|
10474
10593
|
return formatItemId(item.id);
|
|
10475
10594
|
}
|
|
@@ -10517,7 +10636,7 @@ function registerRefineCommand(cmd) {
|
|
|
10517
10636
|
}
|
|
10518
10637
|
|
|
10519
10638
|
// src/commands/backlog/rewindPhase.ts
|
|
10520
|
-
import
|
|
10639
|
+
import chalk84 from "chalk";
|
|
10521
10640
|
async function rewindPhase(id, phase, opts) {
|
|
10522
10641
|
const phaseNumber = Number.parseInt(phase, 10);
|
|
10523
10642
|
const found = await findOneItem(id);
|
|
@@ -10525,12 +10644,12 @@ async function rewindPhase(id, phase, opts) {
|
|
|
10525
10644
|
const { orm, item } = found;
|
|
10526
10645
|
const result = await rewindItemToPhase(orm, item, phaseNumber, opts.reason);
|
|
10527
10646
|
if (!result.ok) {
|
|
10528
|
-
console.log(
|
|
10647
|
+
console.log(chalk84.red(result.error));
|
|
10529
10648
|
process.exitCode = 1;
|
|
10530
10649
|
return;
|
|
10531
10650
|
}
|
|
10532
10651
|
console.log(
|
|
10533
|
-
|
|
10652
|
+
chalk84.green(
|
|
10534
10653
|
`Rewound item ${formatItemId(item.id)} to phase ${phaseNumber} (${result.phaseName}).`
|
|
10535
10654
|
)
|
|
10536
10655
|
);
|
|
@@ -10558,22 +10677,22 @@ function registerRunCommand(cmd) {
|
|
|
10558
10677
|
}
|
|
10559
10678
|
|
|
10560
10679
|
// src/commands/backlog/search/index.ts
|
|
10561
|
-
import
|
|
10680
|
+
import chalk85 from "chalk";
|
|
10562
10681
|
async function search(query) {
|
|
10563
10682
|
const items2 = await searchBacklog(query);
|
|
10564
10683
|
if (items2.length === 0) {
|
|
10565
|
-
console.log(
|
|
10684
|
+
console.log(chalk85.dim(`No items matching "${query}".`));
|
|
10566
10685
|
return;
|
|
10567
10686
|
}
|
|
10568
10687
|
console.log(
|
|
10569
|
-
|
|
10688
|
+
chalk85.dim(
|
|
10570
10689
|
`${items2.length} item${items2.length === 1 ? "" : "s"} matching "${query}":
|
|
10571
10690
|
`
|
|
10572
10691
|
)
|
|
10573
10692
|
);
|
|
10574
10693
|
for (const item of items2) {
|
|
10575
10694
|
console.log(
|
|
10576
|
-
`${statusIcon(item.status)} ${typeLabel(item.type)} ${
|
|
10695
|
+
`${statusIcon(item.status)} ${typeLabel(item.type)} ${chalk85.dim(formatItemId(item.id))} ${item.name}`
|
|
10577
10696
|
);
|
|
10578
10697
|
}
|
|
10579
10698
|
}
|
|
@@ -10584,18 +10703,18 @@ function registerSearchCommand(cmd) {
|
|
|
10584
10703
|
}
|
|
10585
10704
|
|
|
10586
10705
|
// src/commands/backlog/delete/index.ts
|
|
10587
|
-
import
|
|
10706
|
+
import chalk86 from "chalk";
|
|
10588
10707
|
async function del(id) {
|
|
10589
10708
|
const name = await removeItem(id);
|
|
10590
10709
|
if (name) {
|
|
10591
10710
|
console.log(
|
|
10592
|
-
|
|
10711
|
+
chalk86.green(`Deleted item ${formatItemId(parseItemId(id))}: ${name}`)
|
|
10593
10712
|
);
|
|
10594
10713
|
}
|
|
10595
10714
|
}
|
|
10596
10715
|
|
|
10597
10716
|
// src/commands/backlog/done/index.ts
|
|
10598
|
-
import
|
|
10717
|
+
import chalk87 from "chalk";
|
|
10599
10718
|
async function done(id, summary) {
|
|
10600
10719
|
const found = await findOneItem(id);
|
|
10601
10720
|
if (!found) return;
|
|
@@ -10609,12 +10728,12 @@ async function done(id, summary) {
|
|
|
10609
10728
|
const pending = item.plan.slice(completedCount);
|
|
10610
10729
|
if (pending.length > 0) {
|
|
10611
10730
|
console.log(
|
|
10612
|
-
|
|
10731
|
+
chalk87.red(
|
|
10613
10732
|
`Cannot complete item ${formatItemId(item.id)}: ${pending.length} pending phase(s):`
|
|
10614
10733
|
)
|
|
10615
10734
|
);
|
|
10616
10735
|
for (const phase of pending) {
|
|
10617
|
-
console.log(
|
|
10736
|
+
console.log(chalk87.yellow(` - ${phase.name}`));
|
|
10618
10737
|
}
|
|
10619
10738
|
process.exitCode = 1;
|
|
10620
10739
|
return;
|
|
@@ -10626,12 +10745,12 @@ async function done(id, summary) {
|
|
|
10626
10745
|
await appendComment(orm, item.id, summary, { phase, type: "summary" });
|
|
10627
10746
|
}
|
|
10628
10747
|
console.log(
|
|
10629
|
-
|
|
10748
|
+
chalk87.green(`Completed item ${formatItemId(item.id)}: ${item.name}`)
|
|
10630
10749
|
);
|
|
10631
10750
|
}
|
|
10632
10751
|
|
|
10633
10752
|
// src/commands/backlog/set-status/index.ts
|
|
10634
|
-
import
|
|
10753
|
+
import chalk88 from "chalk";
|
|
10635
10754
|
var allowedStatuses = [
|
|
10636
10755
|
"todo",
|
|
10637
10756
|
"in-progress",
|
|
@@ -10641,7 +10760,7 @@ var allowedStatuses = [
|
|
|
10641
10760
|
async function setStatusCommand(id, status3) {
|
|
10642
10761
|
if (!allowedStatuses.includes(status3)) {
|
|
10643
10762
|
console.log(
|
|
10644
|
-
|
|
10763
|
+
chalk88.red(
|
|
10645
10764
|
`Invalid status "${status3}". Must be one of: ${allowedStatuses.join(", ")}.`
|
|
10646
10765
|
)
|
|
10647
10766
|
);
|
|
@@ -10651,7 +10770,7 @@ async function setStatusCommand(id, status3) {
|
|
|
10651
10770
|
const name = await setStatus(id, status3);
|
|
10652
10771
|
if (name) {
|
|
10653
10772
|
console.log(
|
|
10654
|
-
|
|
10773
|
+
chalk88.green(
|
|
10655
10774
|
`Set item ${formatItemId(parseItemId(id))} to ${status3}: ${name}`
|
|
10656
10775
|
)
|
|
10657
10776
|
);
|
|
@@ -10659,16 +10778,16 @@ async function setStatusCommand(id, status3) {
|
|
|
10659
10778
|
}
|
|
10660
10779
|
|
|
10661
10780
|
// src/commands/backlog/star/index.ts
|
|
10662
|
-
import
|
|
10781
|
+
import chalk90 from "chalk";
|
|
10663
10782
|
|
|
10664
10783
|
// src/commands/backlog/setStarred.ts
|
|
10665
|
-
import
|
|
10784
|
+
import chalk89 from "chalk";
|
|
10666
10785
|
async function setStarred(id, starred) {
|
|
10667
10786
|
const { orm } = await getReady();
|
|
10668
10787
|
const numId = parseItemId(id);
|
|
10669
10788
|
const name = await updateStarred(orm, numId, starred);
|
|
10670
10789
|
if (name === void 0)
|
|
10671
|
-
console.log(
|
|
10790
|
+
console.log(chalk89.red(`Item ${formatItemId(numId)} not found.`));
|
|
10672
10791
|
return name;
|
|
10673
10792
|
}
|
|
10674
10793
|
|
|
@@ -10677,52 +10796,52 @@ async function star(id) {
|
|
|
10677
10796
|
const name = await setStarred(id, true);
|
|
10678
10797
|
if (name) {
|
|
10679
10798
|
console.log(
|
|
10680
|
-
|
|
10799
|
+
chalk90.green(`Starred item ${formatItemId(parseItemId(id))}: ${name}`)
|
|
10681
10800
|
);
|
|
10682
10801
|
}
|
|
10683
10802
|
}
|
|
10684
10803
|
|
|
10685
10804
|
// src/commands/backlog/start/index.ts
|
|
10686
|
-
import
|
|
10805
|
+
import chalk91 from "chalk";
|
|
10687
10806
|
async function start(id) {
|
|
10688
10807
|
const name = await setStatus(id, "in-progress");
|
|
10689
10808
|
if (name) {
|
|
10690
10809
|
console.log(
|
|
10691
|
-
|
|
10810
|
+
chalk91.green(`Started item ${formatItemId(parseItemId(id))}: ${name}`)
|
|
10692
10811
|
);
|
|
10693
10812
|
}
|
|
10694
10813
|
}
|
|
10695
10814
|
|
|
10696
10815
|
// src/commands/backlog/stop/index.ts
|
|
10697
|
-
import
|
|
10698
|
-
import { and as and10, eq as
|
|
10816
|
+
import chalk92 from "chalk";
|
|
10817
|
+
import { and as and10, eq as eq27 } from "drizzle-orm";
|
|
10699
10818
|
async function stop() {
|
|
10700
10819
|
const { orm } = await getReady();
|
|
10701
|
-
const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and10(
|
|
10820
|
+
const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and10(eq27(items.status, "in-progress"), eq27(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
|
|
10702
10821
|
if (stopped.length === 0) {
|
|
10703
|
-
console.log(
|
|
10822
|
+
console.log(chalk92.yellow("No in-progress items to stop."));
|
|
10704
10823
|
return;
|
|
10705
10824
|
}
|
|
10706
10825
|
for (const item of stopped) {
|
|
10707
10826
|
console.log(
|
|
10708
|
-
|
|
10827
|
+
chalk92.yellow(`Stopped item ${formatItemId(item.id)}: ${item.name}`)
|
|
10709
10828
|
);
|
|
10710
10829
|
}
|
|
10711
10830
|
}
|
|
10712
10831
|
|
|
10713
10832
|
// src/commands/backlog/unstar/index.ts
|
|
10714
|
-
import
|
|
10833
|
+
import chalk93 from "chalk";
|
|
10715
10834
|
async function unstar(id) {
|
|
10716
10835
|
const name = await setStarred(id, false);
|
|
10717
10836
|
if (name) {
|
|
10718
10837
|
console.log(
|
|
10719
|
-
|
|
10838
|
+
chalk93.green(`Unstarred item ${formatItemId(parseItemId(id))}: ${name}`)
|
|
10720
10839
|
);
|
|
10721
10840
|
}
|
|
10722
10841
|
}
|
|
10723
10842
|
|
|
10724
10843
|
// src/commands/backlog/wontdo/index.ts
|
|
10725
|
-
import
|
|
10844
|
+
import chalk94 from "chalk";
|
|
10726
10845
|
async function wontdo(id, reason) {
|
|
10727
10846
|
const found = await findOneItem(id);
|
|
10728
10847
|
if (!found) return;
|
|
@@ -10733,7 +10852,7 @@ async function wontdo(id, reason) {
|
|
|
10733
10852
|
await appendComment(orm, item.id, reason, { phase, type: "summary" });
|
|
10734
10853
|
}
|
|
10735
10854
|
console.log(
|
|
10736
|
-
|
|
10855
|
+
chalk94.red(`Won't do item ${formatItemId(item.id)}: ${item.name}`)
|
|
10737
10856
|
);
|
|
10738
10857
|
}
|
|
10739
10858
|
|
|
@@ -10752,17 +10871,17 @@ function registerStatusCommands(cmd) {
|
|
|
10752
10871
|
}
|
|
10753
10872
|
|
|
10754
10873
|
// src/commands/backlog/addSubtask.ts
|
|
10755
|
-
import
|
|
10874
|
+
import chalk95 from "chalk";
|
|
10756
10875
|
async function addSubtask(id, options2) {
|
|
10757
10876
|
const title = options2.title?.trim();
|
|
10758
10877
|
if (!title) {
|
|
10759
|
-
console.log(
|
|
10878
|
+
console.log(chalk95.red("A sub-task title is required (--title)."));
|
|
10760
10879
|
process.exitCode = 1;
|
|
10761
10880
|
return;
|
|
10762
10881
|
}
|
|
10763
10882
|
if (title.length > 50) {
|
|
10764
10883
|
console.log(
|
|
10765
|
-
|
|
10884
|
+
chalk95.red(
|
|
10766
10885
|
"A sub-task title must be 50 characters or fewer. Use --desc for longer detail."
|
|
10767
10886
|
)
|
|
10768
10887
|
);
|
|
@@ -10778,21 +10897,21 @@ async function addSubtask(id, options2) {
|
|
|
10778
10897
|
const description = options2.desc?.replaceAll(String.raw`\n`, "\n");
|
|
10779
10898
|
await insertSubtask(orm, item.id, title, description);
|
|
10780
10899
|
console.log(
|
|
10781
|
-
|
|
10900
|
+
chalk95.green(`Added sub-task to item ${formatItemId(item.id)}: ${title}`)
|
|
10782
10901
|
);
|
|
10783
10902
|
}
|
|
10784
10903
|
|
|
10785
10904
|
// src/commands/backlog/editSubtask.ts
|
|
10786
|
-
import
|
|
10905
|
+
import chalk97 from "chalk";
|
|
10787
10906
|
|
|
10788
10907
|
// src/commands/backlog/resolveSubtaskIndex.ts
|
|
10789
|
-
import
|
|
10908
|
+
import chalk96 from "chalk";
|
|
10790
10909
|
function resolveSubtaskIndex(index3, item) {
|
|
10791
10910
|
const position = Number.parseInt(index3, 10);
|
|
10792
10911
|
const subtasks = item.subtasks ?? [];
|
|
10793
10912
|
if (Number.isNaN(position) || position < 1 || position > subtasks.length) {
|
|
10794
10913
|
console.log(
|
|
10795
|
-
|
|
10914
|
+
chalk96.red(
|
|
10796
10915
|
`Item ${formatItemId(item.id)} has no sub-task ${index3}${subtasks.length > 0 ? ` (1-${subtasks.length})` : ""}.`
|
|
10797
10916
|
)
|
|
10798
10917
|
);
|
|
@@ -10815,13 +10934,13 @@ async function findSubtask(id, index3) {
|
|
|
10815
10934
|
}
|
|
10816
10935
|
|
|
10817
10936
|
// src/commands/backlog/updateSubtask.ts
|
|
10818
|
-
import { and as and11, eq as
|
|
10937
|
+
import { and as and11, eq as eq28 } from "drizzle-orm";
|
|
10819
10938
|
async function updateSubtask(orm, itemId2, idx, fields) {
|
|
10820
10939
|
const set = {};
|
|
10821
10940
|
if (fields.title !== void 0) set.title = fields.title;
|
|
10822
10941
|
if (fields.description !== void 0) set.description = fields.description;
|
|
10823
10942
|
if (fields.status !== void 0) set.status = fields.status;
|
|
10824
|
-
const [row] = await orm.update(itemSubtasks).set(set).where(and11(
|
|
10943
|
+
const [row] = await orm.update(itemSubtasks).set(set).where(and11(eq28(itemSubtasks.itemId, itemId2), eq28(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
|
|
10825
10944
|
return row?.title;
|
|
10826
10945
|
}
|
|
10827
10946
|
|
|
@@ -10859,33 +10978,33 @@ async function editSubtask(id, index3, options2) {
|
|
|
10859
10978
|
if (!found) return;
|
|
10860
10979
|
const fields = buildUpdate(options2);
|
|
10861
10980
|
if (typeof fields === "string") {
|
|
10862
|
-
console.log(
|
|
10981
|
+
console.log(chalk97.red(fields));
|
|
10863
10982
|
process.exitCode = 1;
|
|
10864
10983
|
return;
|
|
10865
10984
|
}
|
|
10866
10985
|
const { orm, item, idx } = found;
|
|
10867
10986
|
const title = await updateSubtask(orm, item.id, idx, fields);
|
|
10868
10987
|
console.log(
|
|
10869
|
-
|
|
10988
|
+
chalk97.green(
|
|
10870
10989
|
`Updated sub-task ${idx + 1} of item ${formatItemId(item.id)}: ${title}`
|
|
10871
10990
|
)
|
|
10872
10991
|
);
|
|
10873
10992
|
}
|
|
10874
10993
|
|
|
10875
10994
|
// src/commands/backlog/removeSubtask.ts
|
|
10876
|
-
import
|
|
10995
|
+
import chalk98 from "chalk";
|
|
10877
10996
|
|
|
10878
10997
|
// src/commands/backlog/deleteSubtask.ts
|
|
10879
|
-
import { and as and12, asc as asc6, eq as
|
|
10998
|
+
import { and as and12, asc as asc6, eq as eq29 } from "drizzle-orm";
|
|
10880
10999
|
async function deleteSubtask(orm, itemId2, idx) {
|
|
10881
|
-
const [row] = await orm.delete(itemSubtasks).where(and12(
|
|
11000
|
+
const [row] = await orm.delete(itemSubtasks).where(and12(eq29(itemSubtasks.itemId, itemId2), eq29(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
|
|
10882
11001
|
if (!row) return void 0;
|
|
10883
|
-
const remaining = await orm.select({ idx: itemSubtasks.idx }).from(itemSubtasks).where(
|
|
11002
|
+
const remaining = await orm.select({ idx: itemSubtasks.idx }).from(itemSubtasks).where(eq29(itemSubtasks.itemId, itemId2)).orderBy(asc6(itemSubtasks.idx));
|
|
10884
11003
|
for (let i = 0; i < remaining.length; i++) {
|
|
10885
11004
|
const oldIdx = remaining[i].idx;
|
|
10886
11005
|
if (oldIdx === i) continue;
|
|
10887
11006
|
await orm.update(itemSubtasks).set({ idx: i }).where(
|
|
10888
|
-
and12(
|
|
11007
|
+
and12(eq29(itemSubtasks.itemId, itemId2), eq29(itemSubtasks.idx, oldIdx))
|
|
10889
11008
|
);
|
|
10890
11009
|
}
|
|
10891
11010
|
return row.title;
|
|
@@ -10898,18 +11017,18 @@ async function removeSubtask(id, index3) {
|
|
|
10898
11017
|
const { orm, item, idx } = found;
|
|
10899
11018
|
const title = await deleteSubtask(orm, item.id, idx);
|
|
10900
11019
|
console.log(
|
|
10901
|
-
|
|
11020
|
+
chalk98.green(
|
|
10902
11021
|
`Removed sub-task ${idx + 1} of item ${formatItemId(item.id)}: ${title}`
|
|
10903
11022
|
)
|
|
10904
11023
|
);
|
|
10905
11024
|
}
|
|
10906
11025
|
|
|
10907
11026
|
// src/commands/backlog/subtaskStatus.ts
|
|
10908
|
-
import
|
|
11027
|
+
import chalk99 from "chalk";
|
|
10909
11028
|
async function subtaskStatus(id, index3, status3) {
|
|
10910
11029
|
if (!validSubtaskStatuses.includes(status3)) {
|
|
10911
11030
|
console.log(
|
|
10912
|
-
|
|
11031
|
+
chalk99.red(
|
|
10913
11032
|
`Invalid status "${status3}". Use one of: ${validSubtaskStatuses.join(", ")}.`
|
|
10914
11033
|
)
|
|
10915
11034
|
);
|
|
@@ -10926,7 +11045,7 @@ async function subtaskStatus(id, index3, status3) {
|
|
|
10926
11045
|
status3
|
|
10927
11046
|
);
|
|
10928
11047
|
console.log(
|
|
10929
|
-
|
|
11048
|
+
chalk99.green(
|
|
10930
11049
|
`Set sub-task ${idx + 1} of item ${formatItemId(item.id)} to ${status3}: ${title}`
|
|
10931
11050
|
)
|
|
10932
11051
|
);
|
|
@@ -10953,21 +11072,21 @@ function registerSubtaskCommands(cmd) {
|
|
|
10953
11072
|
}
|
|
10954
11073
|
|
|
10955
11074
|
// src/commands/backlog/movePhase.ts
|
|
10956
|
-
import
|
|
10957
|
-
import { count as count5, eq as
|
|
11075
|
+
import chalk100 from "chalk";
|
|
11076
|
+
import { count as count5, eq as eq32 } from "drizzle-orm";
|
|
10958
11077
|
|
|
10959
11078
|
// src/commands/backlog/reorderPhaseRows.ts
|
|
10960
|
-
import { and as and14, asc as asc8, eq as
|
|
11079
|
+
import { and as and14, asc as asc8, eq as eq31 } from "drizzle-orm";
|
|
10961
11080
|
|
|
10962
11081
|
// src/commands/backlog/reindexPhases.ts
|
|
10963
|
-
import { and as and13, asc as asc7, count as count4, eq as
|
|
11082
|
+
import { and as and13, asc as asc7, count as count4, eq as eq30 } from "drizzle-orm";
|
|
10964
11083
|
async function reindexPhases(db, itemId2) {
|
|
10965
|
-
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(
|
|
11084
|
+
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq30(planPhases.itemId, itemId2)).orderBy(asc7(planPhases.idx));
|
|
10966
11085
|
for (let i = 0; i < remaining.length; i++) {
|
|
10967
11086
|
const oldIdx = remaining[i].idx;
|
|
10968
11087
|
if (oldIdx === i) continue;
|
|
10969
|
-
await db.update(planTasks).set({ phaseIdx: i }).where(and13(
|
|
10970
|
-
await db.update(planPhases).set({ idx: i }).where(and13(
|
|
11088
|
+
await db.update(planTasks).set({ phaseIdx: i }).where(and13(eq30(planTasks.itemId, itemId2), eq30(planTasks.phaseIdx, oldIdx)));
|
|
11089
|
+
await db.update(planPhases).set({ idx: i }).where(and13(eq30(planPhases.itemId, itemId2), eq30(planPhases.idx, oldIdx)));
|
|
10971
11090
|
}
|
|
10972
11091
|
}
|
|
10973
11092
|
async function adjustCurrentPhase(db, item, removedIdx) {
|
|
@@ -10975,24 +11094,24 @@ async function adjustCurrentPhase(db, item, removedIdx) {
|
|
|
10975
11094
|
if (currentPhase === void 0) return;
|
|
10976
11095
|
const currentIdx = currentPhase - 1;
|
|
10977
11096
|
if (removedIdx < currentIdx) {
|
|
10978
|
-
await db.update(items).set({ currentPhase: currentPhase - 1 }).where(
|
|
11097
|
+
await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq30(items.id, item.id));
|
|
10979
11098
|
return;
|
|
10980
11099
|
}
|
|
10981
11100
|
if (removedIdx !== currentIdx) return;
|
|
10982
|
-
const [row] = await db.select({ cnt: count4() }).from(planPhases).where(
|
|
11101
|
+
const [row] = await db.select({ cnt: count4() }).from(planPhases).where(eq30(planPhases.itemId, item.id));
|
|
10983
11102
|
const cnt = row?.cnt ?? 0;
|
|
10984
|
-
await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(
|
|
11103
|
+
await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq30(items.id, item.id));
|
|
10985
11104
|
}
|
|
10986
11105
|
|
|
10987
11106
|
// src/commands/backlog/reorderPhaseRows.ts
|
|
10988
11107
|
async function reorderPhaseRows(orm, itemId2, fromIdx, toIdx) {
|
|
10989
11108
|
await orm.transaction(async (tx) => {
|
|
10990
|
-
const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and14(
|
|
10991
|
-
const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and14(
|
|
11109
|
+
const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and14(eq31(planPhases.itemId, itemId2), eq31(planPhases.idx, fromIdx)));
|
|
11110
|
+
const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and14(eq31(planTasks.itemId, itemId2), eq31(planTasks.phaseIdx, fromIdx))).orderBy(asc8(planTasks.idx));
|
|
10992
11111
|
await tx.delete(planTasks).where(
|
|
10993
|
-
and14(
|
|
11112
|
+
and14(eq31(planTasks.itemId, itemId2), eq31(planTasks.phaseIdx, fromIdx))
|
|
10994
11113
|
);
|
|
10995
|
-
await tx.delete(planPhases).where(and14(
|
|
11114
|
+
await tx.delete(planPhases).where(and14(eq31(planPhases.itemId, itemId2), eq31(planPhases.idx, fromIdx)));
|
|
10996
11115
|
await reindexPhases(tx, itemId2);
|
|
10997
11116
|
await shiftPhasesUp(tx, itemId2, toIdx);
|
|
10998
11117
|
await tx.insert(planPhases).values({
|
|
@@ -11019,7 +11138,7 @@ function toIndex(value, phaseCount) {
|
|
|
11019
11138
|
const pos = Number.parseInt(value, 10);
|
|
11020
11139
|
if (Number.isNaN(pos) || pos < 1 || pos > phaseCount) {
|
|
11021
11140
|
console.log(
|
|
11022
|
-
|
|
11141
|
+
chalk100.red(
|
|
11023
11142
|
`Position "${value}" is out of range. Must be between 1 and ${phaseCount}.`
|
|
11024
11143
|
)
|
|
11025
11144
|
);
|
|
@@ -11033,7 +11152,7 @@ async function movePhase(id, from, to) {
|
|
|
11033
11152
|
if (!found) return;
|
|
11034
11153
|
const { orm, item } = found;
|
|
11035
11154
|
const itemId2 = item.id;
|
|
11036
|
-
const [row] = await orm.select({ cnt: count5() }).from(planPhases).where(
|
|
11155
|
+
const [row] = await orm.select({ cnt: count5() }).from(planPhases).where(eq32(planPhases.itemId, itemId2));
|
|
11037
11156
|
const phaseCount = row?.cnt ?? 0;
|
|
11038
11157
|
const fromIdx = toIndex(from, phaseCount);
|
|
11039
11158
|
if (fromIdx === void 0) return;
|
|
@@ -11042,29 +11161,29 @@ async function movePhase(id, from, to) {
|
|
|
11042
11161
|
if (fromIdx !== toIdx) {
|
|
11043
11162
|
await reorderPhaseRows(orm, itemId2, fromIdx, toIdx);
|
|
11044
11163
|
}
|
|
11045
|
-
console.log(
|
|
11164
|
+
console.log(chalk100.green(`Moved phase ${from} to position ${to}.`));
|
|
11046
11165
|
}
|
|
11047
11166
|
|
|
11048
11167
|
// src/commands/backlog/updatePhase.ts
|
|
11049
|
-
import
|
|
11168
|
+
import chalk102 from "chalk";
|
|
11050
11169
|
|
|
11051
11170
|
// src/commands/backlog/applyPhaseUpdate.ts
|
|
11052
|
-
import { and as and15, eq as
|
|
11171
|
+
import { and as and15, eq as eq33 } from "drizzle-orm";
|
|
11053
11172
|
async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
|
|
11054
11173
|
await orm.transaction(async (tx) => {
|
|
11055
11174
|
if (fields.name) {
|
|
11056
11175
|
await tx.update(planPhases).set({ name: fields.name }).where(
|
|
11057
|
-
and15(
|
|
11176
|
+
and15(eq33(planPhases.itemId, itemId2), eq33(planPhases.idx, phaseIdx))
|
|
11058
11177
|
);
|
|
11059
11178
|
}
|
|
11060
11179
|
if (fields.manualCheck) {
|
|
11061
11180
|
await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
|
|
11062
|
-
and15(
|
|
11181
|
+
and15(eq33(planPhases.itemId, itemId2), eq33(planPhases.idx, phaseIdx))
|
|
11063
11182
|
);
|
|
11064
11183
|
}
|
|
11065
11184
|
if (fields.task) {
|
|
11066
11185
|
await tx.delete(planTasks).where(
|
|
11067
|
-
and15(
|
|
11186
|
+
and15(eq33(planTasks.itemId, itemId2), eq33(planTasks.phaseIdx, phaseIdx))
|
|
11068
11187
|
);
|
|
11069
11188
|
if (fields.task.length) {
|
|
11070
11189
|
await tx.insert(planTasks).values(
|
|
@@ -11081,18 +11200,18 @@ async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
|
|
|
11081
11200
|
}
|
|
11082
11201
|
|
|
11083
11202
|
// src/commands/backlog/findPhase.ts
|
|
11084
|
-
import
|
|
11085
|
-
import { and as and16, count as count6, eq as
|
|
11203
|
+
import chalk101 from "chalk";
|
|
11204
|
+
import { and as and16, count as count6, eq as eq34 } from "drizzle-orm";
|
|
11086
11205
|
async function findPhase(id, phase) {
|
|
11087
11206
|
const found = await findOneItem(id);
|
|
11088
11207
|
if (!found) return void 0;
|
|
11089
11208
|
const { orm, item } = found;
|
|
11090
11209
|
const itemId2 = item.id;
|
|
11091
11210
|
const phaseIdx = Number.parseInt(phase, 10) - 1;
|
|
11092
|
-
const [row] = await orm.select({ cnt: count6() }).from(planPhases).where(and16(
|
|
11211
|
+
const [row] = await orm.select({ cnt: count6() }).from(planPhases).where(and16(eq34(planPhases.itemId, itemId2), eq34(planPhases.idx, phaseIdx)));
|
|
11093
11212
|
if (!row || row.cnt === 0) {
|
|
11094
11213
|
console.log(
|
|
11095
|
-
|
|
11214
|
+
chalk101.red(
|
|
11096
11215
|
`Phase ${phaseIdx + 1} not found on item ${formatItemId(itemId2)}.`
|
|
11097
11216
|
)
|
|
11098
11217
|
);
|
|
@@ -11226,7 +11345,7 @@ async function updatePhase(id, phase, options2) {
|
|
|
11226
11345
|
const { item, orm, itemId: itemId2, phaseIdx } = found;
|
|
11227
11346
|
const resolved = resolvePhaseFields(options2, item.plan?.[phaseIdx]);
|
|
11228
11347
|
if (!resolved.ok) {
|
|
11229
|
-
console.log(
|
|
11348
|
+
console.log(chalk102.red(resolved.error));
|
|
11230
11349
|
process.exitCode = 1;
|
|
11231
11350
|
return;
|
|
11232
11351
|
}
|
|
@@ -11238,7 +11357,7 @@ async function updatePhase(id, phase, options2) {
|
|
|
11238
11357
|
manualCheck && "manual checks"
|
|
11239
11358
|
].filter(Boolean).join(", ");
|
|
11240
11359
|
console.log(
|
|
11241
|
-
|
|
11360
|
+
chalk102.green(
|
|
11242
11361
|
`Updated ${fields} on phase ${phaseIdx + 1} of item ${formatItemId(itemId2)}.`
|
|
11243
11362
|
)
|
|
11244
11363
|
);
|
|
@@ -11261,30 +11380,30 @@ function registerUpdatePhaseCommand(cmd) {
|
|
|
11261
11380
|
}
|
|
11262
11381
|
|
|
11263
11382
|
// src/commands/backlog/removePhase.ts
|
|
11264
|
-
import
|
|
11265
|
-
import { and as and17, eq as
|
|
11383
|
+
import chalk103 from "chalk";
|
|
11384
|
+
import { and as and17, eq as eq35 } from "drizzle-orm";
|
|
11266
11385
|
async function removePhase(id, phase) {
|
|
11267
11386
|
const found = await findPhase(id, phase);
|
|
11268
11387
|
if (!found) return;
|
|
11269
11388
|
const { item, orm, itemId: itemId2, phaseIdx } = found;
|
|
11270
11389
|
await orm.transaction(async (tx) => {
|
|
11271
11390
|
await tx.delete(planTasks).where(
|
|
11272
|
-
and17(
|
|
11391
|
+
and17(eq35(planTasks.itemId, itemId2), eq35(planTasks.phaseIdx, phaseIdx))
|
|
11273
11392
|
);
|
|
11274
|
-
await tx.delete(planPhases).where(and17(
|
|
11393
|
+
await tx.delete(planPhases).where(and17(eq35(planPhases.itemId, itemId2), eq35(planPhases.idx, phaseIdx)));
|
|
11275
11394
|
await reindexPhases(tx, itemId2);
|
|
11276
11395
|
await adjustCurrentPhase(tx, item, phaseIdx);
|
|
11277
11396
|
});
|
|
11278
11397
|
console.log(
|
|
11279
|
-
|
|
11398
|
+
chalk103.green(
|
|
11280
11399
|
`Removed phase ${phaseIdx + 1} from item ${formatItemId(itemId2)}.`
|
|
11281
11400
|
)
|
|
11282
11401
|
);
|
|
11283
11402
|
}
|
|
11284
11403
|
|
|
11285
11404
|
// src/commands/backlog/update/index.ts
|
|
11286
|
-
import
|
|
11287
|
-
import { eq as
|
|
11405
|
+
import chalk105 from "chalk";
|
|
11406
|
+
import { eq as eq36 } from "drizzle-orm";
|
|
11288
11407
|
|
|
11289
11408
|
// src/commands/backlog/update/applyAcMutations.ts
|
|
11290
11409
|
function hasAcMutations(options2) {
|
|
@@ -11305,16 +11424,16 @@ function applyAcMutations(current, options2) {
|
|
|
11305
11424
|
}
|
|
11306
11425
|
|
|
11307
11426
|
// src/commands/backlog/update/buildUpdateValues.ts
|
|
11308
|
-
import
|
|
11427
|
+
import chalk104 from "chalk";
|
|
11309
11428
|
function buildUpdateValues(options2) {
|
|
11310
11429
|
const { name, desc: desc6, type, ac } = options2;
|
|
11311
11430
|
if (!name && !desc6 && !type && !ac) {
|
|
11312
|
-
console.log(
|
|
11431
|
+
console.log(chalk104.red("Nothing to update. Provide at least one flag."));
|
|
11313
11432
|
process.exitCode = 1;
|
|
11314
11433
|
return void 0;
|
|
11315
11434
|
}
|
|
11316
11435
|
if (type && type !== "story" && type !== "bug") {
|
|
11317
|
-
console.log(
|
|
11436
|
+
console.log(chalk104.red('Invalid type. Must be "story" or "bug".'));
|
|
11318
11437
|
process.exitCode = 1;
|
|
11319
11438
|
return void 0;
|
|
11320
11439
|
}
|
|
@@ -11347,14 +11466,14 @@ async function update(id, options2) {
|
|
|
11347
11466
|
if (hasAcMutations(options2)) {
|
|
11348
11467
|
if (options2.ac) {
|
|
11349
11468
|
console.log(
|
|
11350
|
-
|
|
11469
|
+
chalk105.red("Cannot combine --ac with --add-ac/--edit-ac/--remove-ac.")
|
|
11351
11470
|
);
|
|
11352
11471
|
process.exitCode = 1;
|
|
11353
11472
|
return;
|
|
11354
11473
|
}
|
|
11355
11474
|
const mutation = applyAcMutations(found.item.acceptanceCriteria, options2);
|
|
11356
11475
|
if (!mutation.ok) {
|
|
11357
|
-
console.log(
|
|
11476
|
+
console.log(chalk105.red(mutation.error));
|
|
11358
11477
|
process.exitCode = 1;
|
|
11359
11478
|
return;
|
|
11360
11479
|
}
|
|
@@ -11364,9 +11483,9 @@ async function update(id, options2) {
|
|
|
11364
11483
|
if (!built) return;
|
|
11365
11484
|
const { orm } = found;
|
|
11366
11485
|
const itemId2 = found.item.id;
|
|
11367
|
-
await orm.update(items).set(built.set).where(
|
|
11486
|
+
await orm.update(items).set(built.set).where(eq36(items.id, itemId2));
|
|
11368
11487
|
console.log(
|
|
11369
|
-
|
|
11488
|
+
chalk105.green(`Updated ${built.fields} on item ${formatItemId(itemId2)}.`)
|
|
11370
11489
|
);
|
|
11371
11490
|
}
|
|
11372
11491
|
|
|
@@ -11420,6 +11539,7 @@ var registrars = [
|
|
|
11420
11539
|
registerImportCommand,
|
|
11421
11540
|
registerMoveRepoCommand,
|
|
11422
11541
|
registerAssociateJiraCommand,
|
|
11542
|
+
registerAssociateGithubCommand,
|
|
11423
11543
|
registerActivityCommands
|
|
11424
11544
|
];
|
|
11425
11545
|
function registerBacklog(program2) {
|
|
@@ -12169,11 +12289,11 @@ function assertCliExists(cli) {
|
|
|
12169
12289
|
}
|
|
12170
12290
|
|
|
12171
12291
|
// src/commands/permitCliReads/colorize.ts
|
|
12172
|
-
import
|
|
12292
|
+
import chalk106 from "chalk";
|
|
12173
12293
|
function colorize(plainOutput) {
|
|
12174
12294
|
return plainOutput.split("\n").map((line) => {
|
|
12175
|
-
if (line.startsWith(" R ")) return
|
|
12176
|
-
if (line.startsWith(" W ")) return
|
|
12295
|
+
if (line.startsWith(" R ")) return chalk106.green(line);
|
|
12296
|
+
if (line.startsWith(" W ")) return chalk106.red(line);
|
|
12177
12297
|
return line;
|
|
12178
12298
|
}).join("\n");
|
|
12179
12299
|
}
|
|
@@ -12471,7 +12591,7 @@ async function permitCliReads(cli, options2 = { noCache: false }) {
|
|
|
12471
12591
|
}
|
|
12472
12592
|
|
|
12473
12593
|
// src/commands/deny/denyAdd.ts
|
|
12474
|
-
import
|
|
12594
|
+
import chalk107 from "chalk";
|
|
12475
12595
|
|
|
12476
12596
|
// src/commands/deny/loadDenyConfig.ts
|
|
12477
12597
|
function loadDenyConfig(global) {
|
|
@@ -12491,16 +12611,16 @@ function loadDenyConfig(global) {
|
|
|
12491
12611
|
function denyAdd(pattern2, message, options2) {
|
|
12492
12612
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
12493
12613
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
12494
|
-
console.log(
|
|
12614
|
+
console.log(chalk107.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
12495
12615
|
return;
|
|
12496
12616
|
}
|
|
12497
12617
|
deny.push({ pattern: pattern2, message });
|
|
12498
12618
|
saveDeny(deny);
|
|
12499
|
-
console.log(
|
|
12619
|
+
console.log(chalk107.green(`Added deny rule: ${pattern2} \u2192 ${message}`));
|
|
12500
12620
|
}
|
|
12501
12621
|
|
|
12502
12622
|
// src/commands/deny/denyList.ts
|
|
12503
|
-
import
|
|
12623
|
+
import chalk108 from "chalk";
|
|
12504
12624
|
function denyList() {
|
|
12505
12625
|
const globalRaw = loadGlobalConfigRaw();
|
|
12506
12626
|
const projectRaw = loadProjectConfig();
|
|
@@ -12511,7 +12631,7 @@ function denyList() {
|
|
|
12511
12631
|
projectDeny.length > 0 ? projectDeny : void 0
|
|
12512
12632
|
);
|
|
12513
12633
|
if (!merged || merged.length === 0) {
|
|
12514
|
-
console.log(
|
|
12634
|
+
console.log(chalk108.dim("No deny rules configured."));
|
|
12515
12635
|
return;
|
|
12516
12636
|
}
|
|
12517
12637
|
const projectPatterns = new Set(projectDeny.map((r) => r.pattern));
|
|
@@ -12519,23 +12639,23 @@ function denyList() {
|
|
|
12519
12639
|
for (const rule of merged) {
|
|
12520
12640
|
const inProject = projectPatterns.has(rule.pattern);
|
|
12521
12641
|
const inGlobal = globalPatterns.has(rule.pattern);
|
|
12522
|
-
const label2 = inProject && inGlobal ?
|
|
12523
|
-
console.log(`${
|
|
12642
|
+
const label2 = inProject && inGlobal ? chalk108.dim(" (project, overrides global)") : inGlobal ? chalk108.dim(" (global)") : "";
|
|
12643
|
+
console.log(`${chalk108.red(rule.pattern)} \u2192 ${rule.message}${label2}`);
|
|
12524
12644
|
}
|
|
12525
12645
|
}
|
|
12526
12646
|
|
|
12527
12647
|
// src/commands/deny/denyRemove.ts
|
|
12528
|
-
import
|
|
12648
|
+
import chalk109 from "chalk";
|
|
12529
12649
|
function denyRemove(pattern2, options2) {
|
|
12530
12650
|
const { deny, saveDeny } = loadDenyConfig(options2.global);
|
|
12531
12651
|
const index3 = deny.findIndex((r) => r.pattern === pattern2);
|
|
12532
12652
|
if (index3 === -1) {
|
|
12533
|
-
console.log(
|
|
12653
|
+
console.log(chalk109.yellow(`No deny rule found for: ${pattern2}`));
|
|
12534
12654
|
return;
|
|
12535
12655
|
}
|
|
12536
12656
|
deny.splice(index3, 1);
|
|
12537
12657
|
saveDeny(deny.length > 0 ? deny : void 0);
|
|
12538
|
-
console.log(
|
|
12658
|
+
console.log(chalk109.green(`Removed deny rule: ${pattern2}`));
|
|
12539
12659
|
}
|
|
12540
12660
|
|
|
12541
12661
|
// src/commands/registerDeny.ts
|
|
@@ -12579,7 +12699,7 @@ function registerCliHook(program2) {
|
|
|
12579
12699
|
|
|
12580
12700
|
// src/commands/codeComment/codeCommentConfirm.ts
|
|
12581
12701
|
import { existsSync as existsSync31, readFileSync as readFileSync27, unlinkSync as unlinkSync8, writeFileSync as writeFileSync24 } from "fs";
|
|
12582
|
-
import
|
|
12702
|
+
import chalk110 from "chalk";
|
|
12583
12703
|
|
|
12584
12704
|
// src/commands/codeComment/getRestrictedDir.ts
|
|
12585
12705
|
import { homedir as homedir17 } from "os";
|
|
@@ -12632,12 +12752,12 @@ function codeCommentConfirm(pin) {
|
|
|
12632
12752
|
sweepRestrictedDir();
|
|
12633
12753
|
const state = readPinState(pin);
|
|
12634
12754
|
if (!state) {
|
|
12635
|
-
console.error(
|
|
12755
|
+
console.error(chalk110.red(`No pending comment for pin: ${pin}`));
|
|
12636
12756
|
process.exitCode = 1;
|
|
12637
12757
|
return;
|
|
12638
12758
|
}
|
|
12639
12759
|
if (!existsSync31(state.file)) {
|
|
12640
|
-
console.error(
|
|
12760
|
+
console.error(chalk110.red(`Target file no longer exists: ${state.file}`));
|
|
12641
12761
|
process.exitCode = 1;
|
|
12642
12762
|
return;
|
|
12643
12763
|
}
|
|
@@ -12646,7 +12766,7 @@ function codeCommentConfirm(pin) {
|
|
|
12646
12766
|
const index3 = state.line - 1;
|
|
12647
12767
|
if (index3 > lines.length) {
|
|
12648
12768
|
console.error(
|
|
12649
|
-
|
|
12769
|
+
chalk110.red(
|
|
12650
12770
|
`Line ${state.line} is beyond the end of ${state.file} (${lines.length} lines).`
|
|
12651
12771
|
)
|
|
12652
12772
|
);
|
|
@@ -12660,14 +12780,14 @@ function codeCommentConfirm(pin) {
|
|
|
12660
12780
|
writeFileSync24(state.file, lines.join("\n"));
|
|
12661
12781
|
unlinkSync8(getPinStatePath(pin));
|
|
12662
12782
|
console.log(
|
|
12663
|
-
|
|
12783
|
+
chalk110.green(
|
|
12664
12784
|
`Inserted "${marker} ${state.text}" at ${state.file}:${state.line}`
|
|
12665
12785
|
)
|
|
12666
12786
|
);
|
|
12667
12787
|
}
|
|
12668
12788
|
|
|
12669
12789
|
// src/commands/codeComment/codeCommentSet.ts
|
|
12670
|
-
import
|
|
12790
|
+
import chalk111 from "chalk";
|
|
12671
12791
|
|
|
12672
12792
|
// src/commands/codeComment/validateCommentText.ts
|
|
12673
12793
|
var MAX_COMMENT_LENGTH = 50;
|
|
@@ -12718,7 +12838,7 @@ function generatePin() {
|
|
|
12718
12838
|
function codeCommentSet(file, line, text17) {
|
|
12719
12839
|
const lineNumber = Number.parseInt(line, 10);
|
|
12720
12840
|
if (!Number.isInteger(lineNumber) || lineNumber < 1) {
|
|
12721
|
-
console.error(
|
|
12841
|
+
console.error(chalk111.red(`Invalid line number: ${line}`));
|
|
12722
12842
|
process.exitCode = 1;
|
|
12723
12843
|
return;
|
|
12724
12844
|
}
|
|
@@ -12726,20 +12846,20 @@ function codeCommentSet(file, line, text17) {
|
|
|
12726
12846
|
const marker = hash ? "#" : "//";
|
|
12727
12847
|
const validation = validateCommentText(text17, hash);
|
|
12728
12848
|
if (!validation.ok) {
|
|
12729
|
-
console.error(
|
|
12730
|
-
console.error(
|
|
12849
|
+
console.error(chalk111.red(`Refused: ${validation.reason}`));
|
|
12850
|
+
console.error(chalk111.red("No pin issued."));
|
|
12731
12851
|
process.exitCode = 1;
|
|
12732
12852
|
return;
|
|
12733
12853
|
}
|
|
12734
12854
|
console.error(
|
|
12735
|
-
|
|
12855
|
+
chalk111.yellow.bold(
|
|
12736
12856
|
"THIS IS YOUR LAST CHANCE TO RECONSIDER BEFORE INVOLVING A HUMAN.\nRequesting this pin pages a real person to approve a comment. DO NOT WASTE THEIR TIME.\nYou had BETTER BE RIGHT that this comment is genuinely necessary.\n\nComments are a last resort, not a habit. Almost every comment you reach for is a sign\nthe code should be clearer instead. Before a human is pulled in, ask whether a better\nname, a smaller function, or a test would make the comment redundant. ONLY if you are\ncertain this one line earns its keep should you proceed to the confirm step below."
|
|
12737
12857
|
)
|
|
12738
12858
|
);
|
|
12739
12859
|
const delivered = issuePin(file, lineNumber, validation.text);
|
|
12740
12860
|
if (!delivered) {
|
|
12741
12861
|
console.error(
|
|
12742
|
-
|
|
12862
|
+
chalk111.red(
|
|
12743
12863
|
"Could not deliver the confirmation pin via notification.\nThe comment cannot be confirmed until the notification channel works."
|
|
12744
12864
|
)
|
|
12745
12865
|
);
|
|
@@ -12749,7 +12869,7 @@ function codeCommentSet(file, line, text17) {
|
|
|
12749
12869
|
console.log(
|
|
12750
12870
|
`A confirmation pin was sent to your desktop notifications.
|
|
12751
12871
|
To insert "${marker} ${validation.text}" at ${file}:${lineNumber}, run:
|
|
12752
|
-
${
|
|
12872
|
+
${chalk111.cyan(" assist code-comment confirm <PIN>")}
|
|
12753
12873
|
using the pin from that notification.`
|
|
12754
12874
|
);
|
|
12755
12875
|
}
|
|
@@ -12828,15 +12948,15 @@ function registerCodexHook(program2) {
|
|
|
12828
12948
|
}
|
|
12829
12949
|
|
|
12830
12950
|
// src/commands/complexity/analyze.ts
|
|
12831
|
-
import
|
|
12951
|
+
import chalk120 from "chalk";
|
|
12832
12952
|
|
|
12833
12953
|
// src/commands/complexity/cyclomatic.ts
|
|
12834
|
-
import
|
|
12954
|
+
import chalk113 from "chalk";
|
|
12835
12955
|
|
|
12836
12956
|
// src/commands/complexity/shared/index.ts
|
|
12837
12957
|
import fs20 from "fs";
|
|
12838
12958
|
import path27 from "path";
|
|
12839
|
-
import
|
|
12959
|
+
import chalk112 from "chalk";
|
|
12840
12960
|
import ts5 from "typescript";
|
|
12841
12961
|
|
|
12842
12962
|
// src/commands/complexity/findSourceFiles.ts
|
|
@@ -13087,7 +13207,7 @@ function createSourceFromFile(filePath) {
|
|
|
13087
13207
|
function withSourceFiles(pattern2, callback, extraIgnore = []) {
|
|
13088
13208
|
const files = findSourceFiles2(pattern2, ".", extraIgnore);
|
|
13089
13209
|
if (files.length === 0) {
|
|
13090
|
-
console.log(
|
|
13210
|
+
console.log(chalk112.yellow("No files found matching pattern"));
|
|
13091
13211
|
return void 0;
|
|
13092
13212
|
}
|
|
13093
13213
|
return callback(files);
|
|
@@ -13120,11 +13240,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
13120
13240
|
results.sort((a, b) => b.complexity - a.complexity);
|
|
13121
13241
|
for (const { file, name, complexity } of results) {
|
|
13122
13242
|
const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
|
|
13123
|
-
const color = exceedsThreshold ?
|
|
13124
|
-
console.log(`${color(`${file}:${name}`)} \u2192 ${
|
|
13243
|
+
const color = exceedsThreshold ? chalk113.red : chalk113.white;
|
|
13244
|
+
console.log(`${color(`${file}:${name}`)} \u2192 ${chalk113.cyan(complexity)}`);
|
|
13125
13245
|
}
|
|
13126
13246
|
console.log(
|
|
13127
|
-
|
|
13247
|
+
chalk113.dim(
|
|
13128
13248
|
`
|
|
13129
13249
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
13130
13250
|
)
|
|
@@ -13136,7 +13256,7 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
13136
13256
|
}
|
|
13137
13257
|
|
|
13138
13258
|
// src/commands/complexity/halstead.ts
|
|
13139
|
-
import
|
|
13259
|
+
import chalk114 from "chalk";
|
|
13140
13260
|
async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
13141
13261
|
withSourceFiles(pattern2, (files) => {
|
|
13142
13262
|
const results = [];
|
|
@@ -13151,13 +13271,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
13151
13271
|
results.sort((a, b) => b.metrics.effort - a.metrics.effort);
|
|
13152
13272
|
for (const { file, name, metrics } of results) {
|
|
13153
13273
|
const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
|
|
13154
|
-
const color = exceedsThreshold ?
|
|
13274
|
+
const color = exceedsThreshold ? chalk114.red : chalk114.white;
|
|
13155
13275
|
console.log(
|
|
13156
|
-
`${color(`${file}:${name}`)} \u2192 volume: ${
|
|
13276
|
+
`${color(`${file}:${name}`)} \u2192 volume: ${chalk114.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk114.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk114.magenta(metrics.effort.toFixed(1))}`
|
|
13157
13277
|
);
|
|
13158
13278
|
}
|
|
13159
13279
|
console.log(
|
|
13160
|
-
|
|
13280
|
+
chalk114.dim(
|
|
13161
13281
|
`
|
|
13162
13282
|
Analyzed ${results.length} functions across ${files.length} files`
|
|
13163
13283
|
)
|
|
@@ -13169,27 +13289,27 @@ Analyzed ${results.length} functions across ${files.length} files`
|
|
|
13169
13289
|
}
|
|
13170
13290
|
|
|
13171
13291
|
// src/commands/complexity/maintainability/displayMaintainabilityResults.ts
|
|
13172
|
-
import
|
|
13292
|
+
import chalk117 from "chalk";
|
|
13173
13293
|
|
|
13174
13294
|
// src/commands/complexity/maintainability/formatResultLine.ts
|
|
13175
|
-
import
|
|
13295
|
+
import chalk115 from "chalk";
|
|
13176
13296
|
function formatResultLine(entry, failing) {
|
|
13177
13297
|
const { file, avgMaintainability, minMaintainability, override } = entry;
|
|
13178
|
-
const name = failing ?
|
|
13179
|
-
const suffix = override !== void 0 ?
|
|
13180
|
-
return `${name} \u2192 avg: ${
|
|
13298
|
+
const name = failing ? chalk115.red(file) : chalk115.white(file);
|
|
13299
|
+
const suffix = override !== void 0 ? chalk115.magenta(` (override: ${override})`) : "";
|
|
13300
|
+
return `${name} \u2192 avg: ${chalk115.cyan(avgMaintainability.toFixed(1))}, min: ${chalk115.yellow(minMaintainability.toFixed(1))}${suffix}`;
|
|
13181
13301
|
}
|
|
13182
13302
|
|
|
13183
13303
|
// src/commands/complexity/maintainability/printMaintainabilityFailure.ts
|
|
13184
|
-
import
|
|
13304
|
+
import chalk116 from "chalk";
|
|
13185
13305
|
function printMaintainabilityFailure(failingCount, threshold) {
|
|
13186
13306
|
const thresholdLabel = threshold !== void 0 ? ` ${threshold}` : "";
|
|
13187
13307
|
console.error(
|
|
13188
|
-
|
|
13308
|
+
chalk116.red(
|
|
13189
13309
|
`
|
|
13190
13310
|
Fail: ${failingCount} file(s) below threshold${thresholdLabel} (files marked "(override: N)" were judged against their own marker). Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
|
|
13191
13311
|
|
|
13192
|
-
\u26A0\uFE0F ${
|
|
13312
|
+
\u26A0\uFE0F ${chalk116.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel.
|
|
13193
13313
|
|
|
13194
13314
|
The score is a property of the whole file, not your diff: any existing logic counts, so the fix is to shrink the file \u2014 not to revert or micro-optimize the lines you just changed. Identify the largest cohesive responsibility (often the biggest function, or a related group of functions) and move it to a new file with 'assist refactor extract'. Run 'assist complexity <file>' for per-function metrics only to locate that responsibility, not to tweak individual lines.`
|
|
13195
13315
|
)
|
|
@@ -13201,7 +13321,7 @@ function displayMaintainabilityResults(results, threshold) {
|
|
|
13201
13321
|
const gating = threshold !== void 0 || results.some((r) => r.override !== void 0);
|
|
13202
13322
|
if (!gating) {
|
|
13203
13323
|
for (const entry of results) console.log(formatResultLine(entry, false));
|
|
13204
|
-
console.log(
|
|
13324
|
+
console.log(chalk117.dim(`
|
|
13205
13325
|
Analyzed ${results.length} files`));
|
|
13206
13326
|
return;
|
|
13207
13327
|
}
|
|
@@ -13210,7 +13330,7 @@ Analyzed ${results.length} files`));
|
|
|
13210
13330
|
return limit !== void 0 && r.minMaintainability < limit;
|
|
13211
13331
|
});
|
|
13212
13332
|
if (failing.length === 0) {
|
|
13213
|
-
console.log(
|
|
13333
|
+
console.log(chalk117.green("All files pass maintainability threshold"));
|
|
13214
13334
|
} else {
|
|
13215
13335
|
for (const entry of failing) console.log(formatResultLine(entry, true));
|
|
13216
13336
|
}
|
|
@@ -13219,7 +13339,7 @@ Analyzed ${results.length} files`));
|
|
|
13219
13339
|
);
|
|
13220
13340
|
for (const entry of passingOverrides)
|
|
13221
13341
|
console.log(formatResultLine(entry, false));
|
|
13222
|
-
console.log(
|
|
13342
|
+
console.log(chalk117.dim(`
|
|
13223
13343
|
Analyzed ${results.length} files`));
|
|
13224
13344
|
if (failing.length > 0) {
|
|
13225
13345
|
printMaintainabilityFailure(failing.length, threshold);
|
|
@@ -13228,10 +13348,10 @@ Analyzed ${results.length} files`));
|
|
|
13228
13348
|
}
|
|
13229
13349
|
|
|
13230
13350
|
// src/commands/complexity/maintainability/printMaintainabilityFormula.ts
|
|
13231
|
-
import
|
|
13351
|
+
import chalk118 from "chalk";
|
|
13232
13352
|
var MI_FORMULA = "171 - 5.2*ln(HalsteadVolume) - 0.23*CyclomaticComplexity - 16.2*ln(SLOC), clamped 0-100";
|
|
13233
13353
|
function printMaintainabilityFormula() {
|
|
13234
|
-
console.log(
|
|
13354
|
+
console.log(chalk118.dim(MI_FORMULA));
|
|
13235
13355
|
}
|
|
13236
13356
|
|
|
13237
13357
|
// src/commands/complexity/maintainability/collectFileMetrics.ts
|
|
@@ -13307,7 +13427,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
13307
13427
|
|
|
13308
13428
|
// src/commands/complexity/sloc.ts
|
|
13309
13429
|
import fs22 from "fs";
|
|
13310
|
-
import
|
|
13430
|
+
import chalk119 from "chalk";
|
|
13311
13431
|
async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
13312
13432
|
withSourceFiles(pattern2, (files) => {
|
|
13313
13433
|
const results = [];
|
|
@@ -13323,12 +13443,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
|
|
|
13323
13443
|
results.sort((a, b) => b.lines - a.lines);
|
|
13324
13444
|
for (const { file, lines } of results) {
|
|
13325
13445
|
const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
|
|
13326
|
-
const color = exceedsThreshold ?
|
|
13327
|
-
console.log(`${color(file)} \u2192 ${
|
|
13446
|
+
const color = exceedsThreshold ? chalk119.red : chalk119.white;
|
|
13447
|
+
console.log(`${color(file)} \u2192 ${chalk119.cyan(lines)} lines`);
|
|
13328
13448
|
}
|
|
13329
13449
|
const total = results.reduce((sum, r) => sum + r.lines, 0);
|
|
13330
13450
|
console.log(
|
|
13331
|
-
|
|
13451
|
+
chalk119.dim(`
|
|
13332
13452
|
Total: ${total} lines across ${files.length} files`)
|
|
13333
13453
|
);
|
|
13334
13454
|
if (hasViolation) {
|
|
@@ -13342,25 +13462,25 @@ async function analyze(pattern2) {
|
|
|
13342
13462
|
const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
|
|
13343
13463
|
const files = findSourceFiles2(searchPattern);
|
|
13344
13464
|
if (files.length === 0) {
|
|
13345
|
-
console.log(
|
|
13465
|
+
console.log(chalk120.yellow("No files found matching pattern"));
|
|
13346
13466
|
return;
|
|
13347
13467
|
}
|
|
13348
13468
|
if (files.length === 1) {
|
|
13349
13469
|
const file = files[0];
|
|
13350
|
-
console.log(
|
|
13470
|
+
console.log(chalk120.bold.underline("SLOC"));
|
|
13351
13471
|
await sloc(file);
|
|
13352
13472
|
console.log();
|
|
13353
|
-
console.log(
|
|
13473
|
+
console.log(chalk120.bold.underline("Cyclomatic Complexity"));
|
|
13354
13474
|
await cyclomatic(file);
|
|
13355
13475
|
console.log();
|
|
13356
|
-
console.log(
|
|
13476
|
+
console.log(chalk120.bold.underline("Halstead Metrics"));
|
|
13357
13477
|
await halstead(file);
|
|
13358
13478
|
console.log();
|
|
13359
|
-
console.log(
|
|
13479
|
+
console.log(chalk120.bold.underline("Maintainability Index"));
|
|
13360
13480
|
await maintainability(file);
|
|
13361
13481
|
console.log();
|
|
13362
13482
|
console.log(
|
|
13363
|
-
|
|
13483
|
+
chalk120.dim(
|
|
13364
13484
|
"To improve the maintainability index, extract functions and logic out of this file into separate, smaller modules. Collapsing whitespace or removing comments is not the goal."
|
|
13365
13485
|
)
|
|
13366
13486
|
);
|
|
@@ -13404,7 +13524,7 @@ function registerComplexity(program2) {
|
|
|
13404
13524
|
}
|
|
13405
13525
|
|
|
13406
13526
|
// src/commands/config/index.ts
|
|
13407
|
-
import
|
|
13527
|
+
import chalk121 from "chalk";
|
|
13408
13528
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
13409
13529
|
|
|
13410
13530
|
// src/commands/config/setNestedValue.ts
|
|
@@ -13467,7 +13587,7 @@ function formatIssuePath(issue, key) {
|
|
|
13467
13587
|
function printValidationErrors(issues, key) {
|
|
13468
13588
|
for (const issue of issues) {
|
|
13469
13589
|
console.error(
|
|
13470
|
-
|
|
13590
|
+
chalk121.red(`${formatIssuePath(issue, key)}: ${issue.message}`)
|
|
13471
13591
|
);
|
|
13472
13592
|
}
|
|
13473
13593
|
}
|
|
@@ -13484,7 +13604,7 @@ var GLOBAL_ONLY_KEYS = ["sync.autoConfirm"];
|
|
|
13484
13604
|
function assertNotGlobalOnly(key, global) {
|
|
13485
13605
|
if (!global && GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k))) {
|
|
13486
13606
|
console.error(
|
|
13487
|
-
|
|
13607
|
+
chalk121.red(
|
|
13488
13608
|
`"${key}" is a global-only key. Use --global to set it in ~/.assist.yml`
|
|
13489
13609
|
)
|
|
13490
13610
|
);
|
|
@@ -13507,7 +13627,7 @@ function configSet(key, value, options2 = {}) {
|
|
|
13507
13627
|
applyConfigSet(key, coerced, options2.global ?? false);
|
|
13508
13628
|
const target = options2.global ? "global" : "project";
|
|
13509
13629
|
console.log(
|
|
13510
|
-
|
|
13630
|
+
chalk121.green(`Set ${key} = ${JSON.stringify(coerced)} (${target})`)
|
|
13511
13631
|
);
|
|
13512
13632
|
}
|
|
13513
13633
|
function configList() {
|
|
@@ -13516,7 +13636,7 @@ function configList() {
|
|
|
13516
13636
|
}
|
|
13517
13637
|
|
|
13518
13638
|
// src/commands/config/configGet.ts
|
|
13519
|
-
import
|
|
13639
|
+
import chalk122 from "chalk";
|
|
13520
13640
|
|
|
13521
13641
|
// src/commands/config/getNestedValue.ts
|
|
13522
13642
|
function isTraversable(value) {
|
|
@@ -13548,7 +13668,7 @@ function requireNestedValue(config, key) {
|
|
|
13548
13668
|
return value;
|
|
13549
13669
|
}
|
|
13550
13670
|
function exitKeyNotSet(key) {
|
|
13551
|
-
console.error(
|
|
13671
|
+
console.error(chalk122.red(`Key "${key}" is not set`));
|
|
13552
13672
|
process.exit(1);
|
|
13553
13673
|
}
|
|
13554
13674
|
|
|
@@ -13561,40 +13681,40 @@ function registerConfig(program2) {
|
|
|
13561
13681
|
}
|
|
13562
13682
|
|
|
13563
13683
|
// src/commands/db/reportMigrationStatus.ts
|
|
13564
|
-
import
|
|
13684
|
+
import chalk123 from "chalk";
|
|
13565
13685
|
function reportApplied(applied) {
|
|
13566
13686
|
if (applied.length === 0) {
|
|
13567
|
-
console.error(
|
|
13687
|
+
console.error(chalk123.green("Database is up to date; nothing to apply."));
|
|
13568
13688
|
return;
|
|
13569
13689
|
}
|
|
13570
13690
|
for (const migration of applied) {
|
|
13571
13691
|
console.error(
|
|
13572
|
-
|
|
13692
|
+
chalk123.green(`Applied migration ${migration.id} (${migration.name}).`)
|
|
13573
13693
|
);
|
|
13574
13694
|
}
|
|
13575
13695
|
}
|
|
13576
13696
|
function reportMigrationStatus(status3) {
|
|
13577
13697
|
if (status3.state === "in-sync") {
|
|
13578
13698
|
console.error(
|
|
13579
|
-
|
|
13699
|
+
chalk123.green(`In sync at migration ${status3.version} (latest).`)
|
|
13580
13700
|
);
|
|
13581
13701
|
return;
|
|
13582
13702
|
}
|
|
13583
13703
|
if (status3.state === "behind") {
|
|
13584
13704
|
console.error(
|
|
13585
|
-
|
|
13705
|
+
chalk123.yellow(
|
|
13586
13706
|
`Behind: applied ${status3.applied}, build expects ${status3.expected}.`
|
|
13587
13707
|
)
|
|
13588
13708
|
);
|
|
13589
13709
|
console.error(
|
|
13590
|
-
|
|
13710
|
+
chalk123.yellow(
|
|
13591
13711
|
`Pending: ${status3.pending.join(", ")}. Run \`assist db migrate\`.`
|
|
13592
13712
|
)
|
|
13593
13713
|
);
|
|
13594
13714
|
return;
|
|
13595
13715
|
}
|
|
13596
13716
|
console.error(
|
|
13597
|
-
|
|
13717
|
+
chalk123.red(
|
|
13598
13718
|
`Ahead: applied ${status3.applied}, build knows ${status3.expected}. Update assist.`
|
|
13599
13719
|
)
|
|
13600
13720
|
);
|
|
@@ -13629,7 +13749,7 @@ function registerDb(program2) {
|
|
|
13629
13749
|
|
|
13630
13750
|
// src/commands/deploy/redirect.ts
|
|
13631
13751
|
import { existsSync as existsSync32, readFileSync as readFileSync28, writeFileSync as writeFileSync26 } from "fs";
|
|
13632
|
-
import
|
|
13752
|
+
import chalk124 from "chalk";
|
|
13633
13753
|
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
13634
13754
|
if (!window.location.pathname.endsWith('/')) {
|
|
13635
13755
|
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
@@ -13638,23 +13758,23 @@ var TRAILING_SLASH_SCRIPT = ` <script>
|
|
|
13638
13758
|
function redirect() {
|
|
13639
13759
|
const indexPath = "index.html";
|
|
13640
13760
|
if (!existsSync32(indexPath)) {
|
|
13641
|
-
console.log(
|
|
13761
|
+
console.log(chalk124.yellow("No index.html found"));
|
|
13642
13762
|
return;
|
|
13643
13763
|
}
|
|
13644
13764
|
const content = readFileSync28(indexPath, "utf8");
|
|
13645
13765
|
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
13646
|
-
console.log(
|
|
13766
|
+
console.log(chalk124.dim("Trailing slash script already present"));
|
|
13647
13767
|
return;
|
|
13648
13768
|
}
|
|
13649
13769
|
const headCloseIndex = content.indexOf("</head>");
|
|
13650
13770
|
if (headCloseIndex === -1) {
|
|
13651
|
-
console.log(
|
|
13771
|
+
console.log(chalk124.red("Could not find </head> tag in index.html"));
|
|
13652
13772
|
return;
|
|
13653
13773
|
}
|
|
13654
13774
|
const newContent = `${content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT}
|
|
13655
13775
|
${content.slice(headCloseIndex)}`;
|
|
13656
13776
|
writeFileSync26(indexPath, newContent);
|
|
13657
|
-
console.log(
|
|
13777
|
+
console.log(chalk124.green("Added trailing slash redirect to index.html"));
|
|
13658
13778
|
}
|
|
13659
13779
|
|
|
13660
13780
|
// src/commands/registerDeploy.ts
|
|
@@ -13680,8 +13800,8 @@ function loadBlogSkipDays(repoName) {
|
|
|
13680
13800
|
}
|
|
13681
13801
|
|
|
13682
13802
|
// src/commands/devlog/shared.ts
|
|
13683
|
-
import { execSync as
|
|
13684
|
-
import
|
|
13803
|
+
import { execSync as execSync32 } from "child_process";
|
|
13804
|
+
import chalk125 from "chalk";
|
|
13685
13805
|
|
|
13686
13806
|
// src/shared/getRepoName.ts
|
|
13687
13807
|
import { existsSync as existsSync33, readFileSync as readFileSync29 } from "fs";
|
|
@@ -13772,7 +13892,7 @@ function loadAllDevlogLatestDates() {
|
|
|
13772
13892
|
// src/commands/devlog/shared.ts
|
|
13773
13893
|
function getCommitFiles(hash) {
|
|
13774
13894
|
try {
|
|
13775
|
-
const output =
|
|
13895
|
+
const output = execSync32(`git show --name-only --format="" ${hash}`, {
|
|
13776
13896
|
encoding: "utf8"
|
|
13777
13897
|
});
|
|
13778
13898
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -13790,13 +13910,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
13790
13910
|
}
|
|
13791
13911
|
function printCommitsWithFiles(commits2, ignore3, verbose) {
|
|
13792
13912
|
for (const commit2 of commits2) {
|
|
13793
|
-
console.log(` ${
|
|
13913
|
+
console.log(` ${chalk125.yellow(commit2.hash)} ${commit2.message}`);
|
|
13794
13914
|
if (verbose) {
|
|
13795
13915
|
const visibleFiles = commit2.files.filter(
|
|
13796
13916
|
(file) => !ignore3.some((p) => file.startsWith(p))
|
|
13797
13917
|
);
|
|
13798
13918
|
for (const file of visibleFiles) {
|
|
13799
|
-
console.log(` ${
|
|
13919
|
+
console.log(` ${chalk125.dim(file)}`);
|
|
13800
13920
|
}
|
|
13801
13921
|
}
|
|
13802
13922
|
}
|
|
@@ -13821,15 +13941,15 @@ function parseGitLogCommits(output, ignore3, afterDate) {
|
|
|
13821
13941
|
}
|
|
13822
13942
|
|
|
13823
13943
|
// src/commands/devlog/list/printDateHeader.ts
|
|
13824
|
-
import
|
|
13944
|
+
import chalk126 from "chalk";
|
|
13825
13945
|
function printDateHeader(date, isSkipped, entries) {
|
|
13826
13946
|
if (isSkipped) {
|
|
13827
|
-
console.log(`${
|
|
13947
|
+
console.log(`${chalk126.bold.blue(date)} ${chalk126.dim("skipped")}`);
|
|
13828
13948
|
} else if (entries && entries.length > 0) {
|
|
13829
|
-
const entryInfo = entries.map((e) => `${
|
|
13830
|
-
console.log(`${
|
|
13949
|
+
const entryInfo = entries.map((e) => `${chalk126.green(e.version)} ${e.title}`).join(" | ");
|
|
13950
|
+
console.log(`${chalk126.bold.blue(date)} ${entryInfo}`);
|
|
13831
13951
|
} else {
|
|
13832
|
-
console.log(`${
|
|
13952
|
+
console.log(`${chalk126.bold.blue(date)} ${chalk126.red("\u26A0 devlog missing")}`);
|
|
13833
13953
|
}
|
|
13834
13954
|
}
|
|
13835
13955
|
|
|
@@ -13868,11 +13988,11 @@ function list3(options2) {
|
|
|
13868
13988
|
}
|
|
13869
13989
|
|
|
13870
13990
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
13871
|
-
import { execFileSync as execFileSync3, execSync as
|
|
13991
|
+
import { execFileSync as execFileSync3, execSync as execSync33 } from "child_process";
|
|
13872
13992
|
import semver from "semver";
|
|
13873
13993
|
function getVersionAtCommit(hash) {
|
|
13874
13994
|
try {
|
|
13875
|
-
const content =
|
|
13995
|
+
const content = execSync33(`git show ${hash}:package.json`, {
|
|
13876
13996
|
encoding: "utf8"
|
|
13877
13997
|
});
|
|
13878
13998
|
const pkg = JSON.parse(content);
|
|
@@ -13933,24 +14053,24 @@ function bumpVersion(version2, type) {
|
|
|
13933
14053
|
|
|
13934
14054
|
// src/commands/devlog/next/displayNextEntry/index.ts
|
|
13935
14055
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
13936
|
-
import
|
|
14056
|
+
import chalk128 from "chalk";
|
|
13937
14057
|
|
|
13938
14058
|
// src/commands/devlog/next/displayNextEntry/displayVersion.ts
|
|
13939
|
-
import
|
|
14059
|
+
import chalk127 from "chalk";
|
|
13940
14060
|
function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
|
|
13941
14061
|
if (conventional && firstHash) {
|
|
13942
14062
|
const version2 = getVersionAtCommit(firstHash);
|
|
13943
14063
|
if (version2) {
|
|
13944
|
-
console.log(`${
|
|
14064
|
+
console.log(`${chalk127.bold("version:")} ${stripToMinor(version2)}`);
|
|
13945
14065
|
} else {
|
|
13946
|
-
console.log(`${
|
|
14066
|
+
console.log(`${chalk127.bold("version:")} ${chalk127.red("unknown")}`);
|
|
13947
14067
|
}
|
|
13948
14068
|
} else if (patchVersion && minorVersion) {
|
|
13949
14069
|
console.log(
|
|
13950
|
-
`${
|
|
14070
|
+
`${chalk127.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
13951
14071
|
);
|
|
13952
14072
|
} else {
|
|
13953
|
-
console.log(`${
|
|
14073
|
+
console.log(`${chalk127.bold("version:")} v0.1 (initial)`);
|
|
13954
14074
|
}
|
|
13955
14075
|
}
|
|
13956
14076
|
|
|
@@ -13998,16 +14118,16 @@ function noCommitsMessage(hasLastInfo) {
|
|
|
13998
14118
|
return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
|
|
13999
14119
|
}
|
|
14000
14120
|
function logName(repoName) {
|
|
14001
|
-
console.log(`${
|
|
14121
|
+
console.log(`${chalk128.bold("name:")} ${repoName}`);
|
|
14002
14122
|
}
|
|
14003
14123
|
function displayNextEntry(ctx, targetDate, commits2) {
|
|
14004
14124
|
logName(ctx.repoName);
|
|
14005
14125
|
printVersionInfo(ctx.config, ctx.lastInfo, commits2[0]?.hash);
|
|
14006
|
-
console.log(
|
|
14126
|
+
console.log(chalk128.bold.blue(targetDate));
|
|
14007
14127
|
printCommitsWithFiles(commits2, ctx.ignore, ctx.verbose);
|
|
14008
14128
|
}
|
|
14009
14129
|
function logNoCommits(lastInfo) {
|
|
14010
|
-
console.log(
|
|
14130
|
+
console.log(chalk128.dim(noCommitsMessage(!!lastInfo)));
|
|
14011
14131
|
}
|
|
14012
14132
|
|
|
14013
14133
|
// src/commands/devlog/next/index.ts
|
|
@@ -14045,14 +14165,14 @@ function next2(options2) {
|
|
|
14045
14165
|
}
|
|
14046
14166
|
|
|
14047
14167
|
// src/commands/devlog/repos/index.ts
|
|
14048
|
-
import { execSync as
|
|
14168
|
+
import { execSync as execSync34 } from "child_process";
|
|
14049
14169
|
|
|
14050
14170
|
// src/commands/devlog/repos/printReposTable.ts
|
|
14051
|
-
import
|
|
14171
|
+
import chalk129 from "chalk";
|
|
14052
14172
|
function colorStatus(status3) {
|
|
14053
|
-
if (status3 === "missing") return
|
|
14054
|
-
if (status3 === "outdated") return
|
|
14055
|
-
return
|
|
14173
|
+
if (status3 === "missing") return chalk129.red(status3);
|
|
14174
|
+
if (status3 === "outdated") return chalk129.yellow(status3);
|
|
14175
|
+
return chalk129.green(status3);
|
|
14056
14176
|
}
|
|
14057
14177
|
function formatRow(row, nameWidth) {
|
|
14058
14178
|
const devlog = (row.lastDevlog ?? "-").padEnd(11);
|
|
@@ -14066,8 +14186,8 @@ function printReposTable(rows) {
|
|
|
14066
14186
|
"Last Devlog".padEnd(11),
|
|
14067
14187
|
"Status"
|
|
14068
14188
|
].join(" ");
|
|
14069
|
-
console.log(
|
|
14070
|
-
console.log(
|
|
14189
|
+
console.log(chalk129.dim(header));
|
|
14190
|
+
console.log(chalk129.dim("-".repeat(header.length)));
|
|
14071
14191
|
for (const row of rows) {
|
|
14072
14192
|
console.log(formatRow(row, nameWidth));
|
|
14073
14193
|
}
|
|
@@ -14080,7 +14200,7 @@ function getStatus(lastPush, lastDevlog) {
|
|
|
14080
14200
|
return lastDevlog < lastPush ? "outdated" : "ok";
|
|
14081
14201
|
}
|
|
14082
14202
|
function fetchRepos(days, all) {
|
|
14083
|
-
const json =
|
|
14203
|
+
const json = execSync34(
|
|
14084
14204
|
"gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
|
|
14085
14205
|
{ encoding: "utf8" }
|
|
14086
14206
|
);
|
|
@@ -14125,14 +14245,14 @@ function repos(options2) {
|
|
|
14125
14245
|
// src/commands/devlog/skip.ts
|
|
14126
14246
|
import { writeFileSync as writeFileSync27 } from "fs";
|
|
14127
14247
|
import { join as join36 } from "path";
|
|
14128
|
-
import
|
|
14248
|
+
import chalk130 from "chalk";
|
|
14129
14249
|
import { stringify as stringifyYaml3 } from "yaml";
|
|
14130
14250
|
function getBlogConfigPath() {
|
|
14131
14251
|
return join36(BLOG_REPO_ROOT, "assist.yml");
|
|
14132
14252
|
}
|
|
14133
14253
|
function skip(date) {
|
|
14134
14254
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
14135
|
-
console.log(
|
|
14255
|
+
console.log(chalk130.red("Invalid date format. Use YYYY-MM-DD"));
|
|
14136
14256
|
process.exit(1);
|
|
14137
14257
|
}
|
|
14138
14258
|
const repoName = getRepoName();
|
|
@@ -14143,7 +14263,7 @@ function skip(date) {
|
|
|
14143
14263
|
const skipDays = skip2[repoName] ?? [];
|
|
14144
14264
|
if (skipDays.includes(date)) {
|
|
14145
14265
|
console.log(
|
|
14146
|
-
|
|
14266
|
+
chalk130.yellow(`${date} is already in skip list for ${repoName}`)
|
|
14147
14267
|
);
|
|
14148
14268
|
return;
|
|
14149
14269
|
}
|
|
@@ -14153,20 +14273,20 @@ function skip(date) {
|
|
|
14153
14273
|
devlog.skip = skip2;
|
|
14154
14274
|
config.devlog = devlog;
|
|
14155
14275
|
writeFileSync27(configPath, stringifyYaml3(config, { lineWidth: 0 }));
|
|
14156
|
-
console.log(
|
|
14276
|
+
console.log(chalk130.green(`Added ${date} to skip list for ${repoName}`));
|
|
14157
14277
|
}
|
|
14158
14278
|
|
|
14159
14279
|
// src/commands/devlog/version.ts
|
|
14160
|
-
import
|
|
14280
|
+
import chalk131 from "chalk";
|
|
14161
14281
|
function version() {
|
|
14162
14282
|
const config = loadConfig();
|
|
14163
14283
|
const name = getRepoName();
|
|
14164
14284
|
const lastInfo = getLastVersionInfo(name, config);
|
|
14165
14285
|
const lastVersion = lastInfo?.version ?? null;
|
|
14166
14286
|
const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
|
|
14167
|
-
console.log(`${
|
|
14168
|
-
console.log(`${
|
|
14169
|
-
console.log(`${
|
|
14287
|
+
console.log(`${chalk131.bold("name:")} ${name}`);
|
|
14288
|
+
console.log(`${chalk131.bold("last:")} ${lastVersion ?? chalk131.dim("none")}`);
|
|
14289
|
+
console.log(`${chalk131.bold("next:")} ${nextVersion ?? chalk131.dim("none")}`);
|
|
14170
14290
|
}
|
|
14171
14291
|
|
|
14172
14292
|
// src/commands/devlog/devlogConfigHelp.ts
|
|
@@ -14210,7 +14330,7 @@ function registerDevlog(program2) {
|
|
|
14210
14330
|
// src/commands/dotnet/checkBuildLocks.ts
|
|
14211
14331
|
import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync5 } from "fs";
|
|
14212
14332
|
import { join as join37 } from "path";
|
|
14213
|
-
import
|
|
14333
|
+
import chalk132 from "chalk";
|
|
14214
14334
|
|
|
14215
14335
|
// src/shared/findRepoRoot.ts
|
|
14216
14336
|
import { existsSync as existsSync34 } from "fs";
|
|
@@ -14273,14 +14393,14 @@ function checkBuildLocks(startDir) {
|
|
|
14273
14393
|
const locked = findFirstLockedDll(startDir ?? getSearchRoot());
|
|
14274
14394
|
if (locked) {
|
|
14275
14395
|
console.error(
|
|
14276
|
-
|
|
14396
|
+
chalk132.red("Build output locked (is VS debugging?): ") + locked
|
|
14277
14397
|
);
|
|
14278
14398
|
process.exit(1);
|
|
14279
14399
|
}
|
|
14280
14400
|
}
|
|
14281
14401
|
async function checkBuildLocksCommand() {
|
|
14282
14402
|
checkBuildLocks();
|
|
14283
|
-
console.log(
|
|
14403
|
+
console.log(chalk132.green("No build locks detected"));
|
|
14284
14404
|
}
|
|
14285
14405
|
|
|
14286
14406
|
// src/commands/dotnet/buildTree.ts
|
|
@@ -14379,30 +14499,30 @@ function escapeRegex(s) {
|
|
|
14379
14499
|
}
|
|
14380
14500
|
|
|
14381
14501
|
// src/commands/dotnet/printTree.ts
|
|
14382
|
-
import
|
|
14502
|
+
import chalk133 from "chalk";
|
|
14383
14503
|
function printNodes(nodes, prefix2) {
|
|
14384
14504
|
for (let i = 0; i < nodes.length; i++) {
|
|
14385
14505
|
const isLast = i === nodes.length - 1;
|
|
14386
14506
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
14387
14507
|
const childPrefix = isLast ? " " : "\u2502 ";
|
|
14388
14508
|
const isMissing = nodes[i].relativePath.startsWith("[MISSING]");
|
|
14389
|
-
const label2 = isMissing ?
|
|
14509
|
+
const label2 = isMissing ? chalk133.red(nodes[i].relativePath) : nodes[i].relativePath;
|
|
14390
14510
|
console.log(`${prefix2}${connector}${label2}`);
|
|
14391
14511
|
printNodes(nodes[i].children, prefix2 + childPrefix);
|
|
14392
14512
|
}
|
|
14393
14513
|
}
|
|
14394
14514
|
function printTree(tree, totalCount, solutions) {
|
|
14395
|
-
console.log(
|
|
14396
|
-
console.log(
|
|
14515
|
+
console.log(chalk133.bold("\nProject Dependency Tree"));
|
|
14516
|
+
console.log(chalk133.cyan(tree.relativePath));
|
|
14397
14517
|
printNodes(tree.children, "");
|
|
14398
|
-
console.log(
|
|
14518
|
+
console.log(chalk133.dim(`
|
|
14399
14519
|
${totalCount} projects total (including root)`));
|
|
14400
|
-
console.log(
|
|
14520
|
+
console.log(chalk133.bold("\nSolution Membership"));
|
|
14401
14521
|
if (solutions.length === 0) {
|
|
14402
|
-
console.log(
|
|
14522
|
+
console.log(chalk133.yellow(" Not found in any .sln"));
|
|
14403
14523
|
} else {
|
|
14404
14524
|
for (const sln of solutions) {
|
|
14405
|
-
console.log(` ${
|
|
14525
|
+
console.log(` ${chalk133.green(sln)}`);
|
|
14406
14526
|
}
|
|
14407
14527
|
}
|
|
14408
14528
|
console.log();
|
|
@@ -14431,16 +14551,16 @@ function printJson(tree, totalCount, solutions) {
|
|
|
14431
14551
|
// src/commands/dotnet/resolveCsproj.ts
|
|
14432
14552
|
import { existsSync as existsSync35 } from "fs";
|
|
14433
14553
|
import path31 from "path";
|
|
14434
|
-
import
|
|
14554
|
+
import chalk134 from "chalk";
|
|
14435
14555
|
function resolveCsproj(csprojPath) {
|
|
14436
14556
|
const resolved = path31.resolve(csprojPath);
|
|
14437
14557
|
if (!existsSync35(resolved)) {
|
|
14438
|
-
console.error(
|
|
14558
|
+
console.error(chalk134.red(`File not found: ${resolved}`));
|
|
14439
14559
|
process.exit(1);
|
|
14440
14560
|
}
|
|
14441
14561
|
const repoRoot = findRepoRoot(path31.dirname(resolved));
|
|
14442
14562
|
if (!repoRoot) {
|
|
14443
|
-
console.error(
|
|
14563
|
+
console.error(chalk134.red("Could not find git repository root"));
|
|
14444
14564
|
process.exit(1);
|
|
14445
14565
|
}
|
|
14446
14566
|
return { resolved, repoRoot };
|
|
@@ -14460,7 +14580,7 @@ async function deps(csprojPath, options2) {
|
|
|
14460
14580
|
}
|
|
14461
14581
|
|
|
14462
14582
|
// src/commands/dotnet/getChangedCsFiles.ts
|
|
14463
|
-
import { execSync as
|
|
14583
|
+
import { execSync as execSync35 } from "child_process";
|
|
14464
14584
|
var SCOPE_ALL = "all";
|
|
14465
14585
|
var SCOPE_BASE = "base:";
|
|
14466
14586
|
var SCOPE_COMMIT = "commit:";
|
|
@@ -14484,18 +14604,18 @@ function getChangedCsFiles(scope) {
|
|
|
14484
14604
|
} else {
|
|
14485
14605
|
cmd = "git diff --name-only HEAD";
|
|
14486
14606
|
}
|
|
14487
|
-
const output =
|
|
14607
|
+
const output = execSync35(cmd, { encoding: "utf8" }).trim();
|
|
14488
14608
|
if (output === "") return [];
|
|
14489
14609
|
return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
|
|
14490
14610
|
}
|
|
14491
14611
|
|
|
14492
14612
|
// src/commands/dotnet/inSln.ts
|
|
14493
|
-
import
|
|
14613
|
+
import chalk135 from "chalk";
|
|
14494
14614
|
async function inSln(csprojPath) {
|
|
14495
14615
|
const { resolved, repoRoot } = resolveCsproj(csprojPath);
|
|
14496
14616
|
const solutions = findContainingSolutions(resolved, repoRoot);
|
|
14497
14617
|
if (solutions.length === 0) {
|
|
14498
|
-
console.log(
|
|
14618
|
+
console.log(chalk135.yellow("Not found in any .sln file"));
|
|
14499
14619
|
process.exit(1);
|
|
14500
14620
|
}
|
|
14501
14621
|
for (const sln of solutions) {
|
|
@@ -14504,7 +14624,7 @@ async function inSln(csprojPath) {
|
|
|
14504
14624
|
}
|
|
14505
14625
|
|
|
14506
14626
|
// src/commands/dotnet/inspect.ts
|
|
14507
|
-
import
|
|
14627
|
+
import chalk141 from "chalk";
|
|
14508
14628
|
|
|
14509
14629
|
// src/shared/formatElapsed.ts
|
|
14510
14630
|
function formatElapsed(ms) {
|
|
@@ -14516,12 +14636,12 @@ function formatElapsed(ms) {
|
|
|
14516
14636
|
}
|
|
14517
14637
|
|
|
14518
14638
|
// src/commands/dotnet/displayIssues.ts
|
|
14519
|
-
import
|
|
14639
|
+
import chalk136 from "chalk";
|
|
14520
14640
|
var SEVERITY_COLOR = {
|
|
14521
|
-
ERROR:
|
|
14522
|
-
WARNING:
|
|
14523
|
-
SUGGESTION:
|
|
14524
|
-
HINT:
|
|
14641
|
+
ERROR: chalk136.red,
|
|
14642
|
+
WARNING: chalk136.yellow,
|
|
14643
|
+
SUGGESTION: chalk136.cyan,
|
|
14644
|
+
HINT: chalk136.dim
|
|
14525
14645
|
};
|
|
14526
14646
|
function groupByFile(issues) {
|
|
14527
14647
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -14537,15 +14657,15 @@ function groupByFile(issues) {
|
|
|
14537
14657
|
}
|
|
14538
14658
|
function displayIssues(issues) {
|
|
14539
14659
|
for (const [file, fileIssues] of groupByFile(issues)) {
|
|
14540
|
-
console.log(
|
|
14660
|
+
console.log(chalk136.bold(file));
|
|
14541
14661
|
for (const issue of fileIssues.sort((a, b) => a.line - b.line)) {
|
|
14542
|
-
const color = SEVERITY_COLOR[issue.severity] ??
|
|
14662
|
+
const color = SEVERITY_COLOR[issue.severity] ?? chalk136.white;
|
|
14543
14663
|
console.log(
|
|
14544
|
-
` ${
|
|
14664
|
+
` ${chalk136.dim(`${issue.line}:`)} ${color(issue.severity)} [${issue.typeId}] ${issue.message}`
|
|
14545
14665
|
);
|
|
14546
14666
|
}
|
|
14547
14667
|
}
|
|
14548
|
-
console.log(
|
|
14668
|
+
console.log(chalk136.dim(`
|
|
14549
14669
|
${issues.length} issue(s) found`));
|
|
14550
14670
|
}
|
|
14551
14671
|
|
|
@@ -14604,12 +14724,12 @@ function filterIssues(issues, all, cliOnly, cliSuppress) {
|
|
|
14604
14724
|
// src/commands/dotnet/resolveSolution.ts
|
|
14605
14725
|
import { existsSync as existsSync36 } from "fs";
|
|
14606
14726
|
import path32 from "path";
|
|
14607
|
-
import
|
|
14727
|
+
import chalk138 from "chalk";
|
|
14608
14728
|
|
|
14609
14729
|
// src/commands/dotnet/findSolution.ts
|
|
14610
14730
|
import { readdirSync as readdirSync7 } from "fs";
|
|
14611
14731
|
import { dirname as dirname22, join as join38 } from "path";
|
|
14612
|
-
import
|
|
14732
|
+
import chalk137 from "chalk";
|
|
14613
14733
|
function findSlnInDir(dir) {
|
|
14614
14734
|
try {
|
|
14615
14735
|
return readdirSync7(dir).filter((f) => f.endsWith(".sln")).map((f) => join38(dir, f));
|
|
@@ -14625,17 +14745,17 @@ function findSolution() {
|
|
|
14625
14745
|
const slnFiles = findSlnInDir(current);
|
|
14626
14746
|
if (slnFiles.length === 1) return slnFiles[0];
|
|
14627
14747
|
if (slnFiles.length > 1) {
|
|
14628
|
-
console.error(
|
|
14748
|
+
console.error(chalk137.red(`Multiple .sln files found in ${current}:`));
|
|
14629
14749
|
for (const f of slnFiles) console.error(` ${f}`);
|
|
14630
14750
|
console.error(
|
|
14631
|
-
|
|
14751
|
+
chalk137.yellow("Specify which one: assist dotnet inspect <sln>")
|
|
14632
14752
|
);
|
|
14633
14753
|
process.exit(1);
|
|
14634
14754
|
}
|
|
14635
14755
|
if (current === ceiling) break;
|
|
14636
14756
|
current = dirname22(current);
|
|
14637
14757
|
}
|
|
14638
|
-
console.error(
|
|
14758
|
+
console.error(chalk137.red("No .sln file found between cwd and repo root"));
|
|
14639
14759
|
process.exit(1);
|
|
14640
14760
|
}
|
|
14641
14761
|
|
|
@@ -14644,7 +14764,7 @@ function resolveSolution(sln) {
|
|
|
14644
14764
|
if (sln) {
|
|
14645
14765
|
const resolved = path32.resolve(sln);
|
|
14646
14766
|
if (!existsSync36(resolved)) {
|
|
14647
|
-
console.error(
|
|
14767
|
+
console.error(chalk138.red(`Solution file not found: ${resolved}`));
|
|
14648
14768
|
process.exit(1);
|
|
14649
14769
|
}
|
|
14650
14770
|
return resolved;
|
|
@@ -14682,18 +14802,18 @@ function parseInspectReport(json) {
|
|
|
14682
14802
|
}
|
|
14683
14803
|
|
|
14684
14804
|
// src/commands/dotnet/runInspectCode.ts
|
|
14685
|
-
import { execSync as
|
|
14805
|
+
import { execSync as execSync36 } from "child_process";
|
|
14686
14806
|
import { existsSync as existsSync37, readFileSync as readFileSync33, unlinkSync as unlinkSync9 } from "fs";
|
|
14687
14807
|
import { tmpdir as tmpdir3 } from "os";
|
|
14688
14808
|
import path33 from "path";
|
|
14689
|
-
import
|
|
14809
|
+
import chalk139 from "chalk";
|
|
14690
14810
|
function assertJbInstalled() {
|
|
14691
14811
|
try {
|
|
14692
|
-
|
|
14812
|
+
execSync36("jb inspectcode --version", { stdio: "pipe" });
|
|
14693
14813
|
} catch {
|
|
14694
|
-
console.error(
|
|
14814
|
+
console.error(chalk139.red("jb is not installed. Install with:"));
|
|
14695
14815
|
console.error(
|
|
14696
|
-
|
|
14816
|
+
chalk139.yellow(" dotnet tool install -g JetBrains.ReSharper.GlobalTools")
|
|
14697
14817
|
);
|
|
14698
14818
|
process.exit(1);
|
|
14699
14819
|
}
|
|
@@ -14703,7 +14823,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
14703
14823
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
14704
14824
|
const sweaFlag = swea ? " --swea" : "";
|
|
14705
14825
|
try {
|
|
14706
|
-
|
|
14826
|
+
execSync36(
|
|
14707
14827
|
`jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
|
|
14708
14828
|
{ stdio: "pipe" }
|
|
14709
14829
|
);
|
|
@@ -14711,11 +14831,11 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
14711
14831
|
if (error && typeof error === "object" && "stderr" in error) {
|
|
14712
14832
|
process.stderr.write(error.stderr);
|
|
14713
14833
|
}
|
|
14714
|
-
console.error(
|
|
14834
|
+
console.error(chalk139.red("jb inspectcode failed"));
|
|
14715
14835
|
process.exit(1);
|
|
14716
14836
|
}
|
|
14717
14837
|
if (!existsSync37(reportPath)) {
|
|
14718
|
-
console.error(
|
|
14838
|
+
console.error(chalk139.red("Report file not generated"));
|
|
14719
14839
|
process.exit(1);
|
|
14720
14840
|
}
|
|
14721
14841
|
const xml = readFileSync33(reportPath, "utf8");
|
|
@@ -14724,8 +14844,8 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
14724
14844
|
}
|
|
14725
14845
|
|
|
14726
14846
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
14727
|
-
import { execSync as
|
|
14728
|
-
import
|
|
14847
|
+
import { execSync as execSync37 } from "child_process";
|
|
14848
|
+
import chalk140 from "chalk";
|
|
14729
14849
|
function resolveMsbuildPath() {
|
|
14730
14850
|
const { run: run4 } = loadConfig();
|
|
14731
14851
|
const configs = resolveRunConfigs(run4, getConfigDir());
|
|
@@ -14735,11 +14855,11 @@ function resolveMsbuildPath() {
|
|
|
14735
14855
|
function assertMsbuildInstalled() {
|
|
14736
14856
|
const msbuild = resolveMsbuildPath();
|
|
14737
14857
|
try {
|
|
14738
|
-
|
|
14858
|
+
execSync37(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
14739
14859
|
} catch {
|
|
14740
|
-
console.error(
|
|
14860
|
+
console.error(chalk140.red(`msbuild not found at: ${msbuild}`));
|
|
14741
14861
|
console.error(
|
|
14742
|
-
|
|
14862
|
+
chalk140.yellow(
|
|
14743
14863
|
"Configure it via a 'build' run entry in .claude/assist.yml or add msbuild to PATH."
|
|
14744
14864
|
)
|
|
14745
14865
|
);
|
|
@@ -14761,7 +14881,7 @@ function runRoslynInspect(slnPath) {
|
|
|
14761
14881
|
const msbuild = resolveMsbuildPath();
|
|
14762
14882
|
let output;
|
|
14763
14883
|
try {
|
|
14764
|
-
output =
|
|
14884
|
+
output = execSync37(
|
|
14765
14885
|
`"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
|
|
14766
14886
|
{ encoding: "utf8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
|
|
14767
14887
|
);
|
|
@@ -14786,17 +14906,17 @@ function runEngine(resolved, changedFiles, options2) {
|
|
|
14786
14906
|
// src/commands/dotnet/inspect.ts
|
|
14787
14907
|
function logScope(changedFiles) {
|
|
14788
14908
|
if (changedFiles === null) {
|
|
14789
|
-
console.log(
|
|
14909
|
+
console.log(chalk141.dim("Inspecting full solution..."));
|
|
14790
14910
|
} else {
|
|
14791
14911
|
console.log(
|
|
14792
|
-
|
|
14912
|
+
chalk141.dim(`Inspecting ${changedFiles.length} changed file(s)...`)
|
|
14793
14913
|
);
|
|
14794
14914
|
}
|
|
14795
14915
|
}
|
|
14796
14916
|
function reportResults(issues, elapsed) {
|
|
14797
14917
|
if (issues.length > 0) displayIssues(issues);
|
|
14798
|
-
else console.log(
|
|
14799
|
-
console.log(
|
|
14918
|
+
else console.log(chalk141.green("No issues found"));
|
|
14919
|
+
console.log(chalk141.dim(`Completed in ${formatElapsed(elapsed)}`));
|
|
14800
14920
|
if (issues.length > 0) process.exit(1);
|
|
14801
14921
|
}
|
|
14802
14922
|
async function inspect(sln, options2) {
|
|
@@ -14807,7 +14927,7 @@ async function inspect(sln, options2) {
|
|
|
14807
14927
|
const scope = parseScope(options2.scope);
|
|
14808
14928
|
const changedFiles = getChangedCsFiles(scope);
|
|
14809
14929
|
if (changedFiles !== null && changedFiles.length === 0) {
|
|
14810
|
-
console.log(
|
|
14930
|
+
console.log(chalk141.green("No changed .cs files found"));
|
|
14811
14931
|
return;
|
|
14812
14932
|
}
|
|
14813
14933
|
logScope(changedFiles);
|
|
@@ -15155,25 +15275,25 @@ function fetchRepoCommitAuthors(org, repo, since) {
|
|
|
15155
15275
|
}
|
|
15156
15276
|
|
|
15157
15277
|
// src/commands/github/printCountTable.ts
|
|
15158
|
-
import
|
|
15278
|
+
import chalk142 from "chalk";
|
|
15159
15279
|
function printCountTable(labelHeader, rows) {
|
|
15160
15280
|
const labelWidth = Math.max(
|
|
15161
15281
|
labelHeader.length,
|
|
15162
15282
|
...rows.map((row) => row.label.length)
|
|
15163
15283
|
);
|
|
15164
15284
|
const header = `${labelHeader.padEnd(labelWidth)} Commits`;
|
|
15165
|
-
console.log(
|
|
15166
|
-
console.log(
|
|
15285
|
+
console.log(chalk142.dim(header));
|
|
15286
|
+
console.log(chalk142.dim("-".repeat(header.length)));
|
|
15167
15287
|
for (const row of rows) {
|
|
15168
15288
|
console.log(`${row.label.padEnd(labelWidth)} ${row.count}`);
|
|
15169
15289
|
}
|
|
15170
15290
|
}
|
|
15171
15291
|
|
|
15172
15292
|
// src/commands/github/printRepoAuthorBreakdown.ts
|
|
15173
|
-
import
|
|
15293
|
+
import chalk143 from "chalk";
|
|
15174
15294
|
function printRepoAuthorBreakdown(repos2) {
|
|
15175
15295
|
for (const repo of repos2) {
|
|
15176
|
-
console.log(
|
|
15296
|
+
console.log(chalk143.bold(repo.name));
|
|
15177
15297
|
const authorWidth = Math.max(
|
|
15178
15298
|
0,
|
|
15179
15299
|
...repo.authors.map((a) => a.author.length)
|
|
@@ -15270,9 +15390,9 @@ function registerGithub(program2) {
|
|
|
15270
15390
|
}
|
|
15271
15391
|
|
|
15272
15392
|
// src/commands/handover/countPendingHandovers.ts
|
|
15273
|
-
import { and as and18, eq as
|
|
15393
|
+
import { and as and18, eq as eq37, isNull, sql as sql17 } from "drizzle-orm";
|
|
15274
15394
|
async function countPendingHandovers(orm, origin) {
|
|
15275
|
-
const [row] = await orm.select({ count:
|
|
15395
|
+
const [row] = await orm.select({ count: sql17`count(*)::int` }).from(handovers).where(and18(eq37(handovers.origin, origin), isNull(handovers.recalledAt)));
|
|
15276
15396
|
return row?.count ?? 0;
|
|
15277
15397
|
}
|
|
15278
15398
|
|
|
@@ -15412,13 +15532,13 @@ async function load2(options2 = {}) {
|
|
|
15412
15532
|
}
|
|
15413
15533
|
|
|
15414
15534
|
// src/commands/handover/listPendingHandovers.ts
|
|
15415
|
-
import { and as and19, desc as desc4, eq as
|
|
15535
|
+
import { and as and19, desc as desc4, eq as eq38, isNull as isNull2 } from "drizzle-orm";
|
|
15416
15536
|
async function listPendingHandovers(orm, origin) {
|
|
15417
15537
|
return orm.select({
|
|
15418
15538
|
id: handovers.id,
|
|
15419
15539
|
summary: handovers.summary,
|
|
15420
15540
|
createdAt: handovers.createdAt
|
|
15421
|
-
}).from(handovers).where(and19(
|
|
15541
|
+
}).from(handovers).where(and19(eq38(handovers.origin, origin), isNull2(handovers.recalledAt))).orderBy(desc4(handovers.createdAt), desc4(handovers.id));
|
|
15422
15542
|
}
|
|
15423
15543
|
|
|
15424
15544
|
// src/commands/handover/printPendingHandovers.ts
|
|
@@ -15431,17 +15551,17 @@ async function printPendingHandovers() {
|
|
|
15431
15551
|
}
|
|
15432
15552
|
|
|
15433
15553
|
// src/commands/handover/recallHandover.ts
|
|
15434
|
-
import { and as and20, desc as desc5, eq as
|
|
15554
|
+
import { and as and20, desc as desc5, eq as eq39, isNull as isNull3 } from "drizzle-orm";
|
|
15435
15555
|
async function recallHandover(orm, origin, id) {
|
|
15436
15556
|
const [row] = await orm.select().from(handovers).where(
|
|
15437
15557
|
and20(
|
|
15438
|
-
|
|
15558
|
+
eq39(handovers.origin, origin),
|
|
15439
15559
|
isNull3(handovers.recalledAt),
|
|
15440
|
-
...id === void 0 ? [] : [
|
|
15560
|
+
...id === void 0 ? [] : [eq39(handovers.id, id)]
|
|
15441
15561
|
)
|
|
15442
15562
|
).orderBy(desc5(handovers.createdAt), desc5(handovers.id)).limit(1);
|
|
15443
15563
|
if (!row) return void 0;
|
|
15444
|
-
await orm.update(handovers).set({ recalledAt: /* @__PURE__ */ new Date() }).where(
|
|
15564
|
+
await orm.update(handovers).set({ recalledAt: /* @__PURE__ */ new Date() }).where(eq39(handovers.id, row.id));
|
|
15445
15565
|
return row.content;
|
|
15446
15566
|
}
|
|
15447
15567
|
|
|
@@ -15491,7 +15611,7 @@ function registerHandover(program2) {
|
|
|
15491
15611
|
}
|
|
15492
15612
|
|
|
15493
15613
|
// src/commands/jira/acceptanceCriteria.ts
|
|
15494
|
-
import
|
|
15614
|
+
import chalk144 from "chalk";
|
|
15495
15615
|
|
|
15496
15616
|
// src/commands/jira/adfToText.ts
|
|
15497
15617
|
function renderInline(node) {
|
|
@@ -15558,7 +15678,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
15558
15678
|
const parsed = fetchIssue(issueKey, field);
|
|
15559
15679
|
const acValue = parsed?.fields?.[field];
|
|
15560
15680
|
if (!acValue) {
|
|
15561
|
-
console.log(
|
|
15681
|
+
console.log(chalk144.yellow(`No acceptance criteria found on ${issueKey}.`));
|
|
15562
15682
|
return;
|
|
15563
15683
|
}
|
|
15564
15684
|
if (typeof acValue === "string") {
|
|
@@ -15573,7 +15693,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
15573
15693
|
}
|
|
15574
15694
|
|
|
15575
15695
|
// src/commands/jira/jiraAuth.ts
|
|
15576
|
-
import { execSync as
|
|
15696
|
+
import { execSync as execSync38 } from "child_process";
|
|
15577
15697
|
|
|
15578
15698
|
// src/shared/promptInput.ts
|
|
15579
15699
|
import Enquirer from "enquirer";
|
|
@@ -15608,7 +15728,7 @@ async function jiraAuth() {
|
|
|
15608
15728
|
console.error("All fields are required.");
|
|
15609
15729
|
process.exit(1);
|
|
15610
15730
|
}
|
|
15611
|
-
|
|
15731
|
+
execSync38(`acli jira auth login --site ${site} --email "${email}" --token`, {
|
|
15612
15732
|
encoding: "utf8",
|
|
15613
15733
|
input: token,
|
|
15614
15734
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -15624,14 +15744,14 @@ async function jiraAuth() {
|
|
|
15624
15744
|
}
|
|
15625
15745
|
|
|
15626
15746
|
// src/commands/jira/viewIssue.ts
|
|
15627
|
-
import
|
|
15747
|
+
import chalk145 from "chalk";
|
|
15628
15748
|
function viewIssue(issueKey) {
|
|
15629
15749
|
const parsed = fetchIssue(issueKey, "summary,description");
|
|
15630
15750
|
const fields = parsed?.fields;
|
|
15631
15751
|
const summary = fields?.summary;
|
|
15632
15752
|
const description = fields?.description;
|
|
15633
15753
|
if (summary) {
|
|
15634
|
-
console.log(
|
|
15754
|
+
console.log(chalk145.bold(summary));
|
|
15635
15755
|
}
|
|
15636
15756
|
if (description) {
|
|
15637
15757
|
if (summary) console.log();
|
|
@@ -15645,7 +15765,7 @@ function viewIssue(issueKey) {
|
|
|
15645
15765
|
}
|
|
15646
15766
|
if (!summary && !description) {
|
|
15647
15767
|
console.log(
|
|
15648
|
-
|
|
15768
|
+
chalk145.yellow(`No summary or description found on ${issueKey}.`)
|
|
15649
15769
|
);
|
|
15650
15770
|
}
|
|
15651
15771
|
}
|
|
@@ -15701,13 +15821,13 @@ function registerRefineLaunch(program2, resumeFlag) {
|
|
|
15701
15821
|
// src/commands/reviewPrComments.ts
|
|
15702
15822
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
15703
15823
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
15704
|
-
import
|
|
15824
|
+
import chalk146 from "chalk";
|
|
15705
15825
|
async function reviewPrComments(number) {
|
|
15706
15826
|
if (number) {
|
|
15707
15827
|
try {
|
|
15708
15828
|
execFileSync5("gh", ["pr", "checkout", number], { stdio: "inherit" });
|
|
15709
15829
|
} catch {
|
|
15710
|
-
console.error(
|
|
15830
|
+
console.error(chalk146.red(`gh pr checkout ${number} failed; aborting.`));
|
|
15711
15831
|
process.exit(1);
|
|
15712
15832
|
}
|
|
15713
15833
|
}
|
|
@@ -15780,15 +15900,15 @@ function registerList(program2) {
|
|
|
15780
15900
|
// src/commands/mermaid/index.ts
|
|
15781
15901
|
import { mkdirSync as mkdirSync15, readdirSync as readdirSync9 } from "fs";
|
|
15782
15902
|
import { resolve as resolve11 } from "path";
|
|
15783
|
-
import
|
|
15903
|
+
import chalk149 from "chalk";
|
|
15784
15904
|
|
|
15785
15905
|
// src/commands/mermaid/exportFile.ts
|
|
15786
15906
|
import { readFileSync as readFileSync35, writeFileSync as writeFileSync29 } from "fs";
|
|
15787
15907
|
import { basename as basename11, extname, resolve as resolve10 } from "path";
|
|
15788
|
-
import
|
|
15908
|
+
import chalk148 from "chalk";
|
|
15789
15909
|
|
|
15790
15910
|
// src/commands/mermaid/renderBlock.ts
|
|
15791
|
-
import
|
|
15911
|
+
import chalk147 from "chalk";
|
|
15792
15912
|
async function renderBlock(krokiUrl, source) {
|
|
15793
15913
|
const response = await fetch(`${krokiUrl}/mermaid/svg`, {
|
|
15794
15914
|
method: "POST",
|
|
@@ -15797,7 +15917,7 @@ async function renderBlock(krokiUrl, source) {
|
|
|
15797
15917
|
});
|
|
15798
15918
|
if (!response.ok) {
|
|
15799
15919
|
console.error(
|
|
15800
|
-
|
|
15920
|
+
chalk147.red(
|
|
15801
15921
|
`Kroki request failed: ${response.status} ${response.statusText}`
|
|
15802
15922
|
)
|
|
15803
15923
|
);
|
|
@@ -15815,19 +15935,19 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
15815
15935
|
if (onlyIndex !== void 0) {
|
|
15816
15936
|
if (onlyIndex < 1 || onlyIndex > blocks.length) {
|
|
15817
15937
|
console.error(
|
|
15818
|
-
|
|
15938
|
+
chalk148.red(
|
|
15819
15939
|
`${file}: --index ${onlyIndex} out of range (file has ${blocks.length} diagram(s))`
|
|
15820
15940
|
)
|
|
15821
15941
|
);
|
|
15822
15942
|
process.exit(1);
|
|
15823
15943
|
}
|
|
15824
15944
|
console.log(
|
|
15825
|
-
|
|
15945
|
+
chalk148.gray(
|
|
15826
15946
|
`${file} \u2014 rendering diagram ${onlyIndex} of ${blocks.length}`
|
|
15827
15947
|
)
|
|
15828
15948
|
);
|
|
15829
15949
|
} else {
|
|
15830
|
-
console.log(
|
|
15950
|
+
console.log(chalk148.gray(`${file} \u2014 ${blocks.length} diagram(s)`));
|
|
15831
15951
|
}
|
|
15832
15952
|
for (const [i, source] of blocks.entries()) {
|
|
15833
15953
|
const idx = i + 1;
|
|
@@ -15835,7 +15955,7 @@ async function exportFile(file, outDir, krokiUrl, onlyIndex) {
|
|
|
15835
15955
|
const outPath = resolve10(outDir, `${stem}-${idx}.svg`);
|
|
15836
15956
|
const svg = await renderBlock(krokiUrl, source);
|
|
15837
15957
|
writeFileSync29(outPath, svg, "utf8");
|
|
15838
|
-
console.log(
|
|
15958
|
+
console.log(chalk148.green(` \u2192 ${outPath}`));
|
|
15839
15959
|
}
|
|
15840
15960
|
}
|
|
15841
15961
|
function extractMermaidBlocks(markdown) {
|
|
@@ -15851,18 +15971,18 @@ async function mermaidExport(file, options2 = {}) {
|
|
|
15851
15971
|
if (options2.index !== void 0) {
|
|
15852
15972
|
if (!Number.isInteger(options2.index) || options2.index < 1) {
|
|
15853
15973
|
console.error(
|
|
15854
|
-
|
|
15974
|
+
chalk149.red(`--index must be a positive integer (got ${options2.index})`)
|
|
15855
15975
|
);
|
|
15856
15976
|
process.exit(1);
|
|
15857
15977
|
}
|
|
15858
15978
|
if (!file) {
|
|
15859
|
-
console.error(
|
|
15979
|
+
console.error(chalk149.red("--index requires a file argument"));
|
|
15860
15980
|
process.exit(1);
|
|
15861
15981
|
}
|
|
15862
15982
|
}
|
|
15863
15983
|
const files = file ? [file] : readdirSync9(process.cwd()).filter((name) => name.toLowerCase().endsWith(".md")).sort();
|
|
15864
15984
|
if (files.length === 0) {
|
|
15865
|
-
console.log(
|
|
15985
|
+
console.log(chalk149.gray("No markdown files found in current directory."));
|
|
15866
15986
|
return;
|
|
15867
15987
|
}
|
|
15868
15988
|
for (const f of files) {
|
|
@@ -15895,7 +16015,7 @@ function registerMermaid(program2) {
|
|
|
15895
16015
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
15896
16016
|
import { createServer as createServer2 } from "http";
|
|
15897
16017
|
import { dirname as dirname24 } from "path";
|
|
15898
|
-
import
|
|
16018
|
+
import chalk151 from "chalk";
|
|
15899
16019
|
|
|
15900
16020
|
// src/commands/netcap/corsHeaders.ts
|
|
15901
16021
|
var corsHeaders = {
|
|
@@ -15974,7 +16094,7 @@ function createNetcapHandler(options2) {
|
|
|
15974
16094
|
import { cp, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
15975
16095
|
import { networkInterfaces } from "os";
|
|
15976
16096
|
import { join as join44 } from "path";
|
|
15977
|
-
import
|
|
16097
|
+
import chalk150 from "chalk";
|
|
15978
16098
|
|
|
15979
16099
|
// src/commands/netcap/netcapExtensionDir.ts
|
|
15980
16100
|
import { dirname as dirname23, join as join43 } from "path";
|
|
@@ -16018,7 +16138,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
16018
16138
|
const host = lanIPv4();
|
|
16019
16139
|
if (!host) {
|
|
16020
16140
|
console.log(
|
|
16021
|
-
|
|
16141
|
+
chalk150.yellow("could not determine the WSL IP for the extension")
|
|
16022
16142
|
);
|
|
16023
16143
|
await configureBackground(source, "127.0.0.1", port, filter);
|
|
16024
16144
|
return source;
|
|
@@ -16029,7 +16149,7 @@ async function prepareExtensionForLoad(port, filter = "") {
|
|
|
16029
16149
|
return WSL_WINDOWS_PATH;
|
|
16030
16150
|
} catch {
|
|
16031
16151
|
console.log(
|
|
16032
|
-
|
|
16152
|
+
chalk150.yellow(`could not copy extension to ${WSL_WINDOWS_PATH}`)
|
|
16033
16153
|
);
|
|
16034
16154
|
return source;
|
|
16035
16155
|
}
|
|
@@ -16062,30 +16182,30 @@ async function netcap(options2) {
|
|
|
16062
16182
|
let count7 = 0;
|
|
16063
16183
|
const handler = createNetcapHandler({
|
|
16064
16184
|
outPath,
|
|
16065
|
-
onPing: () => console.log(
|
|
16185
|
+
onPing: () => console.log(chalk151.dim("ping from extension")),
|
|
16066
16186
|
onCapture: (entry) => {
|
|
16067
16187
|
count7 += 1;
|
|
16068
16188
|
console.log(
|
|
16069
|
-
|
|
16070
|
-
|
|
16189
|
+
chalk151.green(`captured #${count7}`),
|
|
16190
|
+
chalk151.dim(`${entry.method ?? "?"} ${entry.url ?? "?"}`)
|
|
16071
16191
|
);
|
|
16072
16192
|
}
|
|
16073
16193
|
});
|
|
16074
16194
|
const server = createServer2(handler);
|
|
16075
16195
|
server.listen(port, () => {
|
|
16076
16196
|
console.log(
|
|
16077
|
-
|
|
16197
|
+
chalk151.bold(`netcap receiver listening on http://127.0.0.1:${port}`)
|
|
16078
16198
|
);
|
|
16079
|
-
console.log(
|
|
16199
|
+
console.log(chalk151.dim(`appending captures to ${outPath}`));
|
|
16080
16200
|
if (filter)
|
|
16081
|
-
console.log(
|
|
16082
|
-
console.log(
|
|
16083
|
-
console.log(
|
|
16201
|
+
console.log(chalk151.dim(`forwarding only URLs matching "${filter}"`));
|
|
16202
|
+
console.log(chalk151.dim(`load the unpacked extension from ${extensionPath}`));
|
|
16203
|
+
console.log(chalk151.dim("press Ctrl-C to stop"));
|
|
16084
16204
|
});
|
|
16085
16205
|
process.on("SIGINT", () => {
|
|
16086
16206
|
server.close();
|
|
16087
16207
|
console.log(
|
|
16088
|
-
|
|
16208
|
+
chalk151.bold(
|
|
16089
16209
|
`
|
|
16090
16210
|
netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} to ${outPath}`
|
|
16091
16211
|
)
|
|
@@ -16097,7 +16217,7 @@ netcap stopped \u2014 captured ${count7} ${count7 === 1 ? "entry" : "entries"} t
|
|
|
16097
16217
|
// src/commands/netcap/netcapExtract.ts
|
|
16098
16218
|
import { writeFileSync as writeFileSync30 } from "fs";
|
|
16099
16219
|
import { join as join47 } from "path";
|
|
16100
|
-
import
|
|
16220
|
+
import chalk152 from "chalk";
|
|
16101
16221
|
|
|
16102
16222
|
// src/commands/netcap/extractPostsFromCapture.ts
|
|
16103
16223
|
import { readFileSync as readFileSync36 } from "fs";
|
|
@@ -16545,8 +16665,8 @@ function netcapExtract(file) {
|
|
|
16545
16665
|
writeFileSync30(outFile, `${JSON.stringify(posts, null, 2)}
|
|
16546
16666
|
`);
|
|
16547
16667
|
console.log(
|
|
16548
|
-
|
|
16549
|
-
|
|
16668
|
+
chalk152.green(`extracted ${posts.length} posts`),
|
|
16669
|
+
chalk152.dim(`-> ${outFile}`)
|
|
16550
16670
|
);
|
|
16551
16671
|
}
|
|
16552
16672
|
|
|
@@ -16567,7 +16687,7 @@ function registerNetcap(program2) {
|
|
|
16567
16687
|
}
|
|
16568
16688
|
|
|
16569
16689
|
// src/commands/news/add/index.ts
|
|
16570
|
-
import
|
|
16690
|
+
import chalk153 from "chalk";
|
|
16571
16691
|
import enquirer8 from "enquirer";
|
|
16572
16692
|
async function add2(url) {
|
|
16573
16693
|
if (!url) {
|
|
@@ -16589,10 +16709,10 @@ async function add2(url) {
|
|
|
16589
16709
|
const { orm } = await getReady();
|
|
16590
16710
|
const added = await addFeed(orm, url);
|
|
16591
16711
|
if (!added) {
|
|
16592
|
-
console.log(
|
|
16712
|
+
console.log(chalk153.yellow("Feed already exists"));
|
|
16593
16713
|
return;
|
|
16594
16714
|
}
|
|
16595
|
-
console.log(
|
|
16715
|
+
console.log(chalk153.green(`Added feed: ${url}`));
|
|
16596
16716
|
}
|
|
16597
16717
|
|
|
16598
16718
|
// src/commands/registerNews.ts
|
|
@@ -16639,7 +16759,7 @@ function registerPiHook(program2) {
|
|
|
16639
16759
|
}
|
|
16640
16760
|
|
|
16641
16761
|
// src/commands/prompts/printPromptsTable.ts
|
|
16642
|
-
import
|
|
16762
|
+
import chalk154 from "chalk";
|
|
16643
16763
|
function truncate(str, max) {
|
|
16644
16764
|
if (str.length <= max) return str;
|
|
16645
16765
|
return `${str.slice(0, max - 1)}\u2026`;
|
|
@@ -16657,14 +16777,14 @@ function printPromptsTable(rows) {
|
|
|
16657
16777
|
"Command".padEnd(commandWidth),
|
|
16658
16778
|
"Repos"
|
|
16659
16779
|
].join(" ");
|
|
16660
|
-
console.log(
|
|
16661
|
-
console.log(
|
|
16780
|
+
console.log(chalk154.dim(header));
|
|
16781
|
+
console.log(chalk154.dim("-".repeat(header.length)));
|
|
16662
16782
|
for (const row of rows) {
|
|
16663
16783
|
const count7 = String(row.count).padStart(countWidth);
|
|
16664
16784
|
const tool = row.tool.padEnd(toolWidth);
|
|
16665
16785
|
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
16666
16786
|
console.log(
|
|
16667
|
-
`${
|
|
16787
|
+
`${chalk154.yellow(count7)} ${tool} ${command} ${chalk154.dim(row.repos)}`
|
|
16668
16788
|
);
|
|
16669
16789
|
}
|
|
16670
16790
|
}
|
|
@@ -16693,7 +16813,7 @@ function registerPrompts(program2) {
|
|
|
16693
16813
|
}
|
|
16694
16814
|
|
|
16695
16815
|
// src/commands/prs/shared.ts
|
|
16696
|
-
import { execSync as
|
|
16816
|
+
import { execSync as execSync39 } from "child_process";
|
|
16697
16817
|
function isGhNotInstalled(error) {
|
|
16698
16818
|
if (error instanceof Error) {
|
|
16699
16819
|
const msg = error.message.toLowerCase();
|
|
@@ -16711,12 +16831,12 @@ function getRepoInfo() {
|
|
|
16711
16831
|
const preferred = getPreferredRemoteRepo();
|
|
16712
16832
|
if (preferred) return preferred;
|
|
16713
16833
|
const repoInfo = JSON.parse(
|
|
16714
|
-
|
|
16834
|
+
execSync39("gh repo view --json owner,name", { encoding: "utf8" })
|
|
16715
16835
|
);
|
|
16716
16836
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
16717
16837
|
}
|
|
16718
16838
|
function getCurrentBranch2() {
|
|
16719
|
-
return
|
|
16839
|
+
return execSync39("git rev-parse --abbrev-ref HEAD", {
|
|
16720
16840
|
encoding: "utf8"
|
|
16721
16841
|
}).trim();
|
|
16722
16842
|
}
|
|
@@ -16724,7 +16844,7 @@ function viewCurrentPr(fields) {
|
|
|
16724
16844
|
const { org, repo } = getRepoInfo();
|
|
16725
16845
|
const branch2 = getCurrentBranch2();
|
|
16726
16846
|
return JSON.parse(
|
|
16727
|
-
|
|
16847
|
+
execSync39(`gh pr view ${branch2} --json ${fields} -R ${org}/${repo}`, {
|
|
16728
16848
|
encoding: "utf8"
|
|
16729
16849
|
})
|
|
16730
16850
|
);
|
|
@@ -17026,10 +17146,10 @@ function edit(options2) {
|
|
|
17026
17146
|
}
|
|
17027
17147
|
|
|
17028
17148
|
// src/commands/prs/fixed.ts
|
|
17029
|
-
import { execSync as
|
|
17149
|
+
import { execSync as execSync42 } from "child_process";
|
|
17030
17150
|
|
|
17031
17151
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
17032
|
-
import { execSync as
|
|
17152
|
+
import { execSync as execSync41 } from "child_process";
|
|
17033
17153
|
import { unlinkSync as unlinkSync12, writeFileSync as writeFileSync31 } from "fs";
|
|
17034
17154
|
import { tmpdir as tmpdir5 } from "os";
|
|
17035
17155
|
import { join as join49 } from "path";
|
|
@@ -17058,9 +17178,9 @@ function deleteCommentsCache(prNumber) {
|
|
|
17058
17178
|
}
|
|
17059
17179
|
|
|
17060
17180
|
// src/commands/prs/replyToComment.ts
|
|
17061
|
-
import { execSync as
|
|
17181
|
+
import { execSync as execSync40 } from "child_process";
|
|
17062
17182
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
17063
|
-
|
|
17183
|
+
execSync40(
|
|
17064
17184
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, String.raw`\"`)}" -F in_reply_to=${commentId}`,
|
|
17065
17185
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
17066
17186
|
);
|
|
@@ -17072,7 +17192,7 @@ function resolveThread(threadId) {
|
|
|
17072
17192
|
const queryFile = join49(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
|
|
17073
17193
|
writeFileSync31(queryFile, mutation);
|
|
17074
17194
|
try {
|
|
17075
|
-
|
|
17195
|
+
execSync41(
|
|
17076
17196
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
17077
17197
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
17078
17198
|
);
|
|
@@ -17124,7 +17244,7 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
17124
17244
|
// src/commands/prs/fixed.ts
|
|
17125
17245
|
function verifySha(sha) {
|
|
17126
17246
|
try {
|
|
17127
|
-
return
|
|
17247
|
+
return execSync42(`git rev-parse --verify ${sha}`, {
|
|
17128
17248
|
encoding: "utf8"
|
|
17129
17249
|
}).trim();
|
|
17130
17250
|
} catch {
|
|
@@ -17138,7 +17258,7 @@ function fixed(commentId, sha) {
|
|
|
17138
17258
|
const { org, repo } = getRepoInfo();
|
|
17139
17259
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
17140
17260
|
const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
17141
|
-
|
|
17261
|
+
execSync42("git push", { stdio: "inherit" });
|
|
17142
17262
|
resolveCommentWithReply(commentId, message);
|
|
17143
17263
|
} catch (error) {
|
|
17144
17264
|
if (isGhNotInstalled(error)) {
|
|
@@ -17156,7 +17276,7 @@ import { join as join51 } from "path";
|
|
|
17156
17276
|
import { stringify } from "yaml";
|
|
17157
17277
|
|
|
17158
17278
|
// src/commands/prs/fetchThreadIds.ts
|
|
17159
|
-
import { execSync as
|
|
17279
|
+
import { execSync as execSync43 } from "child_process";
|
|
17160
17280
|
import { unlinkSync as unlinkSync13, writeFileSync as writeFileSync32 } from "fs";
|
|
17161
17281
|
import { tmpdir as tmpdir6 } from "os";
|
|
17162
17282
|
import { join as join50 } from "path";
|
|
@@ -17165,7 +17285,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
17165
17285
|
const queryFile = join50(tmpdir6(), `gh-query-${Date.now()}.graphql`);
|
|
17166
17286
|
writeFileSync32(queryFile, THREAD_QUERY);
|
|
17167
17287
|
try {
|
|
17168
|
-
const result =
|
|
17288
|
+
const result = execSync43(
|
|
17169
17289
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
17170
17290
|
{ encoding: "utf8" }
|
|
17171
17291
|
);
|
|
@@ -17187,9 +17307,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
17187
17307
|
}
|
|
17188
17308
|
|
|
17189
17309
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
17190
|
-
import { execSync as
|
|
17310
|
+
import { execSync as execSync44 } from "child_process";
|
|
17191
17311
|
function fetchJson(endpoint) {
|
|
17192
|
-
const result =
|
|
17312
|
+
const result = execSync44(`gh api --paginate ${endpoint}`, {
|
|
17193
17313
|
encoding: "utf8"
|
|
17194
17314
|
});
|
|
17195
17315
|
if (!result.trim()) return [];
|
|
@@ -17231,20 +17351,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
17231
17351
|
}
|
|
17232
17352
|
|
|
17233
17353
|
// src/commands/prs/listComments/printComments.ts
|
|
17234
|
-
import
|
|
17354
|
+
import chalk155 from "chalk";
|
|
17235
17355
|
function formatForHuman(comment3) {
|
|
17236
17356
|
if (comment3.type === "review") {
|
|
17237
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
17357
|
+
const stateColor = comment3.state === "APPROVED" ? chalk155.green : comment3.state === "CHANGES_REQUESTED" ? chalk155.red : chalk155.yellow;
|
|
17238
17358
|
return [
|
|
17239
|
-
`${
|
|
17359
|
+
`${chalk155.cyan("Review")} by ${chalk155.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
17240
17360
|
comment3.body,
|
|
17241
17361
|
""
|
|
17242
17362
|
].join("\n");
|
|
17243
17363
|
}
|
|
17244
17364
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
17245
17365
|
return [
|
|
17246
|
-
`${
|
|
17247
|
-
|
|
17366
|
+
`${chalk155.cyan("Line comment")} by ${chalk155.bold(comment3.user)} on ${chalk155.dim(`${comment3.path}${location}`)}`,
|
|
17367
|
+
chalk155.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
17248
17368
|
comment3.body,
|
|
17249
17369
|
""
|
|
17250
17370
|
].join("\n");
|
|
@@ -17328,19 +17448,19 @@ async function listComments() {
|
|
|
17328
17448
|
}
|
|
17329
17449
|
|
|
17330
17450
|
// src/commands/prs/prs/index.ts
|
|
17331
|
-
import { execSync as
|
|
17451
|
+
import { execSync as execSync45 } from "child_process";
|
|
17332
17452
|
|
|
17333
17453
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
17334
17454
|
import enquirer9 from "enquirer";
|
|
17335
17455
|
|
|
17336
17456
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
17337
|
-
import
|
|
17457
|
+
import chalk156 from "chalk";
|
|
17338
17458
|
var STATUS_MAP = {
|
|
17339
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
17340
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
17459
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk156.magenta("merged"), date: pr.mergedAt } : null,
|
|
17460
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk156.red("closed"), date: pr.closedAt } : null
|
|
17341
17461
|
};
|
|
17342
17462
|
function defaultStatus(pr) {
|
|
17343
|
-
return { label:
|
|
17463
|
+
return { label: chalk156.green("opened"), date: pr.createdAt };
|
|
17344
17464
|
}
|
|
17345
17465
|
function getStatus2(pr) {
|
|
17346
17466
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -17349,11 +17469,11 @@ function formatDate(dateStr) {
|
|
|
17349
17469
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
17350
17470
|
}
|
|
17351
17471
|
function formatPrHeader(pr, status3) {
|
|
17352
|
-
return `${
|
|
17472
|
+
return `${chalk156.cyan(`#${pr.number}`)} ${pr.title} ${chalk156.dim(`(${pr.author.login},`)} ${status3.label} ${chalk156.dim(`${formatDate(status3.date)})`)}`;
|
|
17353
17473
|
}
|
|
17354
17474
|
function logPrDetails(pr) {
|
|
17355
17475
|
console.log(
|
|
17356
|
-
|
|
17476
|
+
chalk156.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
17357
17477
|
);
|
|
17358
17478
|
console.log();
|
|
17359
17479
|
}
|
|
@@ -17435,7 +17555,7 @@ async function prs(options2) {
|
|
|
17435
17555
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
17436
17556
|
try {
|
|
17437
17557
|
const { org, repo } = getRepoInfo();
|
|
17438
|
-
const result =
|
|
17558
|
+
const result = execSync45(
|
|
17439
17559
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
|
|
17440
17560
|
{ encoding: "utf8" }
|
|
17441
17561
|
);
|
|
@@ -17490,16 +17610,16 @@ function buildCreateArgs(title, body, options2) {
|
|
|
17490
17610
|
}
|
|
17491
17611
|
|
|
17492
17612
|
// src/commands/prs/readSessionPrRef.ts
|
|
17493
|
-
import { execSync as
|
|
17613
|
+
import { execSync as execSync46 } from "child_process";
|
|
17494
17614
|
function readSessionPrRef() {
|
|
17495
17615
|
try {
|
|
17496
|
-
const branch2 =
|
|
17616
|
+
const branch2 = execSync46("git rev-parse --abbrev-ref HEAD", {
|
|
17497
17617
|
encoding: "utf8",
|
|
17498
17618
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17499
17619
|
}).trim();
|
|
17500
17620
|
if (!branch2 || branch2 === "HEAD") return null;
|
|
17501
17621
|
const pr = JSON.parse(
|
|
17502
|
-
|
|
17622
|
+
execSync46(`gh pr view ${branch2} --json number,title,url,state`, {
|
|
17503
17623
|
encoding: "utf8",
|
|
17504
17624
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17505
17625
|
})
|
|
@@ -17577,7 +17697,7 @@ function reply(commentId, body) {
|
|
|
17577
17697
|
}
|
|
17578
17698
|
|
|
17579
17699
|
// src/commands/prs/wontfix.ts
|
|
17580
|
-
import { execSync as
|
|
17700
|
+
import { execSync as execSync47 } from "child_process";
|
|
17581
17701
|
function validateReason(reason) {
|
|
17582
17702
|
const lowerReason = reason.toLowerCase();
|
|
17583
17703
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -17594,7 +17714,7 @@ function validateShaReferences(reason) {
|
|
|
17594
17714
|
const invalidShas = [];
|
|
17595
17715
|
for (const sha of shas) {
|
|
17596
17716
|
try {
|
|
17597
|
-
|
|
17717
|
+
execSync47(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
17598
17718
|
} catch {
|
|
17599
17719
|
invalidShas.push(sha);
|
|
17600
17720
|
}
|
|
@@ -17702,10 +17822,10 @@ function registerPrs(program2) {
|
|
|
17702
17822
|
}
|
|
17703
17823
|
|
|
17704
17824
|
// src/commands/ravendb/ravendbAuth.ts
|
|
17705
|
-
import
|
|
17825
|
+
import chalk162 from "chalk";
|
|
17706
17826
|
|
|
17707
17827
|
// src/shared/createConnectionAuth.ts
|
|
17708
|
-
import
|
|
17828
|
+
import chalk157 from "chalk";
|
|
17709
17829
|
function listConnections(connections, format) {
|
|
17710
17830
|
if (connections.length === 0) {
|
|
17711
17831
|
console.log("No connections configured.");
|
|
@@ -17718,7 +17838,7 @@ function listConnections(connections, format) {
|
|
|
17718
17838
|
function removeConnection(connections, name, save) {
|
|
17719
17839
|
const filtered = connections.filter((c) => c.name !== name);
|
|
17720
17840
|
if (filtered.length === connections.length) {
|
|
17721
|
-
console.error(
|
|
17841
|
+
console.error(chalk157.red(`Connection "${name}" not found.`));
|
|
17722
17842
|
process.exit(1);
|
|
17723
17843
|
}
|
|
17724
17844
|
save(filtered);
|
|
@@ -17764,17 +17884,17 @@ function saveConnections(connections) {
|
|
|
17764
17884
|
}
|
|
17765
17885
|
|
|
17766
17886
|
// src/commands/ravendb/promptConnection.ts
|
|
17767
|
-
import
|
|
17887
|
+
import chalk160 from "chalk";
|
|
17768
17888
|
|
|
17769
17889
|
// src/commands/ravendb/selectOpSecret.ts
|
|
17770
|
-
import
|
|
17890
|
+
import chalk159 from "chalk";
|
|
17771
17891
|
import Enquirer2 from "enquirer";
|
|
17772
17892
|
|
|
17773
17893
|
// src/commands/ravendb/searchItems.ts
|
|
17774
|
-
import { execSync as
|
|
17775
|
-
import
|
|
17894
|
+
import { execSync as execSync48 } from "child_process";
|
|
17895
|
+
import chalk158 from "chalk";
|
|
17776
17896
|
function opExec(args) {
|
|
17777
|
-
return
|
|
17897
|
+
return execSync48(`op ${args}`, {
|
|
17778
17898
|
encoding: "utf8",
|
|
17779
17899
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17780
17900
|
}).trim();
|
|
@@ -17785,7 +17905,7 @@ function searchItems(search2) {
|
|
|
17785
17905
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
17786
17906
|
} catch {
|
|
17787
17907
|
console.error(
|
|
17788
|
-
|
|
17908
|
+
chalk158.red(
|
|
17789
17909
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
17790
17910
|
)
|
|
17791
17911
|
);
|
|
@@ -17799,7 +17919,7 @@ function getItemFields(itemId2) {
|
|
|
17799
17919
|
const item = JSON.parse(opExec(`item get "${itemId2}" --format=json`));
|
|
17800
17920
|
return item.fields.filter((f) => f.reference && f.label);
|
|
17801
17921
|
} catch {
|
|
17802
|
-
console.error(
|
|
17922
|
+
console.error(chalk158.red("Failed to get item details from 1Password."));
|
|
17803
17923
|
process.exit(1);
|
|
17804
17924
|
}
|
|
17805
17925
|
}
|
|
@@ -17818,7 +17938,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
17818
17938
|
}).run();
|
|
17819
17939
|
const items2 = searchItems(search2);
|
|
17820
17940
|
if (items2.length === 0) {
|
|
17821
|
-
console.error(
|
|
17941
|
+
console.error(chalk159.red(`No items found matching "${search2}".`));
|
|
17822
17942
|
process.exit(1);
|
|
17823
17943
|
}
|
|
17824
17944
|
const itemId2 = await selectOne(
|
|
@@ -17827,7 +17947,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
17827
17947
|
);
|
|
17828
17948
|
const fields = getItemFields(itemId2);
|
|
17829
17949
|
if (fields.length === 0) {
|
|
17830
|
-
console.error(
|
|
17950
|
+
console.error(chalk159.red("No fields with references found on this item."));
|
|
17831
17951
|
process.exit(1);
|
|
17832
17952
|
}
|
|
17833
17953
|
const ref = await selectOne(
|
|
@@ -17841,7 +17961,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
17841
17961
|
async function promptConnection(existingNames) {
|
|
17842
17962
|
const name = await promptInput("name", "Connection name:");
|
|
17843
17963
|
if (existingNames.includes(name)) {
|
|
17844
|
-
console.error(
|
|
17964
|
+
console.error(chalk160.red(`Connection "${name}" already exists.`));
|
|
17845
17965
|
process.exit(1);
|
|
17846
17966
|
}
|
|
17847
17967
|
const url = await promptInput(
|
|
@@ -17850,22 +17970,22 @@ async function promptConnection(existingNames) {
|
|
|
17850
17970
|
);
|
|
17851
17971
|
const database = await promptInput("database", "Database name:");
|
|
17852
17972
|
if (!name || !url || !database) {
|
|
17853
|
-
console.error(
|
|
17973
|
+
console.error(chalk160.red("All fields are required."));
|
|
17854
17974
|
process.exit(1);
|
|
17855
17975
|
}
|
|
17856
17976
|
const apiKeyRef = await selectOpSecret();
|
|
17857
|
-
console.log(
|
|
17977
|
+
console.log(chalk160.dim(`Using: ${apiKeyRef}`));
|
|
17858
17978
|
return { name, url, database, apiKeyRef };
|
|
17859
17979
|
}
|
|
17860
17980
|
|
|
17861
17981
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
17862
|
-
import
|
|
17982
|
+
import chalk161 from "chalk";
|
|
17863
17983
|
function ravendbSetConnection(name) {
|
|
17864
17984
|
const raw = loadGlobalConfigRaw();
|
|
17865
17985
|
const ravendb = raw.ravendb ?? {};
|
|
17866
17986
|
const connections = ravendb.connections ?? [];
|
|
17867
17987
|
if (!connections.some((c) => c.name === name)) {
|
|
17868
|
-
console.error(
|
|
17988
|
+
console.error(chalk161.red(`Connection "${name}" not found.`));
|
|
17869
17989
|
console.error(
|
|
17870
17990
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
17871
17991
|
);
|
|
@@ -17881,16 +18001,16 @@ function ravendbSetConnection(name) {
|
|
|
17881
18001
|
var ravendbAuth = createConnectionAuth({
|
|
17882
18002
|
load: loadConnections,
|
|
17883
18003
|
save: saveConnections,
|
|
17884
|
-
format: (c) => `${
|
|
18004
|
+
format: (c) => `${chalk162.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
17885
18005
|
promptNew: promptConnection,
|
|
17886
18006
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
17887
18007
|
});
|
|
17888
18008
|
|
|
17889
18009
|
// src/commands/ravendb/ravendbCollections.ts
|
|
17890
|
-
import
|
|
18010
|
+
import chalk166 from "chalk";
|
|
17891
18011
|
|
|
17892
18012
|
// src/commands/ravendb/ravenFetch.ts
|
|
17893
|
-
import
|
|
18013
|
+
import chalk164 from "chalk";
|
|
17894
18014
|
|
|
17895
18015
|
// src/commands/ravendb/getAccessToken.ts
|
|
17896
18016
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -17926,21 +18046,21 @@ ${errorText}`
|
|
|
17926
18046
|
}
|
|
17927
18047
|
|
|
17928
18048
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
17929
|
-
import { execSync as
|
|
17930
|
-
import
|
|
18049
|
+
import { execSync as execSync49 } from "child_process";
|
|
18050
|
+
import chalk163 from "chalk";
|
|
17931
18051
|
function resolveOpSecret(reference) {
|
|
17932
18052
|
if (!reference.startsWith("op://")) {
|
|
17933
|
-
console.error(
|
|
18053
|
+
console.error(chalk163.red(`Invalid secret reference: must start with op://`));
|
|
17934
18054
|
process.exit(1);
|
|
17935
18055
|
}
|
|
17936
18056
|
try {
|
|
17937
|
-
return
|
|
18057
|
+
return execSync49(`op read "${reference}"`, {
|
|
17938
18058
|
encoding: "utf8",
|
|
17939
18059
|
stdio: ["pipe", "pipe", "pipe"]
|
|
17940
18060
|
}).trim();
|
|
17941
18061
|
} catch {
|
|
17942
18062
|
console.error(
|
|
17943
|
-
|
|
18063
|
+
chalk163.red(
|
|
17944
18064
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
17945
18065
|
)
|
|
17946
18066
|
);
|
|
@@ -17967,7 +18087,7 @@ async function ravenFetch(connection, path67) {
|
|
|
17967
18087
|
if (!response.ok) {
|
|
17968
18088
|
const body = await response.text();
|
|
17969
18089
|
console.error(
|
|
17970
|
-
|
|
18090
|
+
chalk164.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
17971
18091
|
);
|
|
17972
18092
|
console.error(body.substring(0, 500));
|
|
17973
18093
|
process.exit(1);
|
|
@@ -17976,7 +18096,7 @@ async function ravenFetch(connection, path67) {
|
|
|
17976
18096
|
}
|
|
17977
18097
|
|
|
17978
18098
|
// src/commands/ravendb/resolveConnection.ts
|
|
17979
|
-
import
|
|
18099
|
+
import chalk165 from "chalk";
|
|
17980
18100
|
function loadRavendb() {
|
|
17981
18101
|
const raw = loadGlobalConfigRaw();
|
|
17982
18102
|
const ravendb = raw.ravendb;
|
|
@@ -17990,7 +18110,7 @@ function resolveConnection(name) {
|
|
|
17990
18110
|
const connectionName = name ?? defaultConnection;
|
|
17991
18111
|
if (!connectionName) {
|
|
17992
18112
|
console.error(
|
|
17993
|
-
|
|
18113
|
+
chalk165.red(
|
|
17994
18114
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
17995
18115
|
)
|
|
17996
18116
|
);
|
|
@@ -17998,7 +18118,7 @@ function resolveConnection(name) {
|
|
|
17998
18118
|
}
|
|
17999
18119
|
const connection = connections.find((c) => c.name === connectionName);
|
|
18000
18120
|
if (!connection) {
|
|
18001
|
-
console.error(
|
|
18121
|
+
console.error(chalk165.red(`Connection "${connectionName}" not found.`));
|
|
18002
18122
|
console.error(
|
|
18003
18123
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
18004
18124
|
);
|
|
@@ -18029,7 +18149,7 @@ async function ravendbCollections(connectionName) {
|
|
|
18029
18149
|
return;
|
|
18030
18150
|
}
|
|
18031
18151
|
for (const c of collections) {
|
|
18032
|
-
console.log(`${
|
|
18152
|
+
console.log(`${chalk166.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
18033
18153
|
}
|
|
18034
18154
|
}
|
|
18035
18155
|
|
|
@@ -18048,10 +18168,10 @@ var ravendbConfigHelp = [
|
|
|
18048
18168
|
];
|
|
18049
18169
|
|
|
18050
18170
|
// src/commands/ravendb/ravendbQuery.ts
|
|
18051
|
-
import
|
|
18171
|
+
import chalk168 from "chalk";
|
|
18052
18172
|
|
|
18053
18173
|
// src/commands/ravendb/fetchAllPages.ts
|
|
18054
|
-
import
|
|
18174
|
+
import chalk167 from "chalk";
|
|
18055
18175
|
|
|
18056
18176
|
// src/commands/ravendb/buildQueryPath.ts
|
|
18057
18177
|
function buildQueryPath(opts) {
|
|
@@ -18089,7 +18209,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
18089
18209
|
allResults.push(...results);
|
|
18090
18210
|
start3 += results.length;
|
|
18091
18211
|
process.stderr.write(
|
|
18092
|
-
`\r${
|
|
18212
|
+
`\r${chalk167.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
18093
18213
|
);
|
|
18094
18214
|
if (start3 >= totalResults) break;
|
|
18095
18215
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -18104,7 +18224,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
18104
18224
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
18105
18225
|
const resolved = resolveArgs(connectionName, collection);
|
|
18106
18226
|
if (!resolved.collection && !options2.query) {
|
|
18107
|
-
console.error(
|
|
18227
|
+
console.error(chalk168.red("Provide a collection name or --query filter."));
|
|
18108
18228
|
process.exit(1);
|
|
18109
18229
|
}
|
|
18110
18230
|
const { collection: col } = resolved;
|
|
@@ -18143,7 +18263,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
18143
18263
|
import * as path34 from "path";
|
|
18144
18264
|
|
|
18145
18265
|
// src/commands/refactor/logViolations.ts
|
|
18146
|
-
import
|
|
18266
|
+
import chalk169 from "chalk";
|
|
18147
18267
|
var DEFAULT_MAX_LINES = 100;
|
|
18148
18268
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
18149
18269
|
if (violations.length === 0) {
|
|
@@ -18152,43 +18272,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
18152
18272
|
}
|
|
18153
18273
|
return;
|
|
18154
18274
|
}
|
|
18155
|
-
console.error(
|
|
18275
|
+
console.error(chalk169.red(`
|
|
18156
18276
|
Refactor check failed:
|
|
18157
18277
|
`));
|
|
18158
|
-
console.error(
|
|
18278
|
+
console.error(chalk169.red(` The following files exceed ${maxLines} lines:
|
|
18159
18279
|
`));
|
|
18160
18280
|
for (const violation of violations) {
|
|
18161
|
-
console.error(
|
|
18281
|
+
console.error(chalk169.red(` ${violation.file} (${violation.lines} lines)`));
|
|
18162
18282
|
}
|
|
18163
18283
|
console.error(
|
|
18164
|
-
|
|
18284
|
+
chalk169.yellow(
|
|
18165
18285
|
`
|
|
18166
18286
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
18167
18287
|
way to refactor it, ignore it with:
|
|
18168
18288
|
`
|
|
18169
18289
|
)
|
|
18170
18290
|
);
|
|
18171
|
-
console.error(
|
|
18291
|
+
console.error(chalk169.gray(` assist refactor ignore <file>
|
|
18172
18292
|
`));
|
|
18173
18293
|
if (process.env.CLAUDECODE) {
|
|
18174
|
-
console.error(
|
|
18294
|
+
console.error(chalk169.cyan(`
|
|
18175
18295
|
## Extracting Code to New Files
|
|
18176
18296
|
`));
|
|
18177
18297
|
console.error(
|
|
18178
|
-
|
|
18298
|
+
chalk169.cyan(
|
|
18179
18299
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
18180
18300
|
`
|
|
18181
18301
|
)
|
|
18182
18302
|
);
|
|
18183
18303
|
console.error(
|
|
18184
|
-
|
|
18304
|
+
chalk169.cyan(
|
|
18185
18305
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
18186
18306
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
18187
18307
|
`
|
|
18188
18308
|
)
|
|
18189
18309
|
);
|
|
18190
18310
|
console.error(
|
|
18191
|
-
|
|
18311
|
+
chalk169.cyan(
|
|
18192
18312
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
18193
18313
|
domains, move it to a common/shared folder.
|
|
18194
18314
|
`
|
|
@@ -18198,7 +18318,7 @@ Refactor check failed:
|
|
|
18198
18318
|
}
|
|
18199
18319
|
|
|
18200
18320
|
// src/commands/refactor/check/getViolations/index.ts
|
|
18201
|
-
import { execSync as
|
|
18321
|
+
import { execSync as execSync50 } from "child_process";
|
|
18202
18322
|
import fs25 from "fs";
|
|
18203
18323
|
import { minimatch as minimatch6 } from "minimatch";
|
|
18204
18324
|
|
|
@@ -18248,7 +18368,7 @@ function getGitFiles(options2) {
|
|
|
18248
18368
|
}
|
|
18249
18369
|
const files = /* @__PURE__ */ new Set();
|
|
18250
18370
|
if (options2.staged || options2.modified) {
|
|
18251
|
-
const staged =
|
|
18371
|
+
const staged = execSync50("git diff --cached --name-only", {
|
|
18252
18372
|
encoding: "utf8"
|
|
18253
18373
|
});
|
|
18254
18374
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -18256,7 +18376,7 @@ function getGitFiles(options2) {
|
|
|
18256
18376
|
}
|
|
18257
18377
|
}
|
|
18258
18378
|
if (options2.unstaged || options2.modified) {
|
|
18259
|
-
const unstaged =
|
|
18379
|
+
const unstaged = execSync50("git diff --name-only", { encoding: "utf8" });
|
|
18260
18380
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
18261
18381
|
files.add(file);
|
|
18262
18382
|
}
|
|
@@ -18344,7 +18464,7 @@ async function check(pattern2, options2) {
|
|
|
18344
18464
|
|
|
18345
18465
|
// src/commands/refactor/extract/index.ts
|
|
18346
18466
|
import path41 from "path";
|
|
18347
|
-
import
|
|
18467
|
+
import chalk172 from "chalk";
|
|
18348
18468
|
|
|
18349
18469
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
18350
18470
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -18943,23 +19063,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
18943
19063
|
|
|
18944
19064
|
// src/commands/refactor/extract/displayPlan.ts
|
|
18945
19065
|
import path38 from "path";
|
|
18946
|
-
import
|
|
19066
|
+
import chalk170 from "chalk";
|
|
18947
19067
|
function section2(title) {
|
|
18948
19068
|
return `
|
|
18949
|
-
${
|
|
19069
|
+
${chalk170.cyan(title)}`;
|
|
18950
19070
|
}
|
|
18951
19071
|
function displayImporters(plan2, cwd) {
|
|
18952
19072
|
if (plan2.importersToUpdate.length === 0) return;
|
|
18953
19073
|
console.log(section2("Update importers:"));
|
|
18954
19074
|
for (const imp of plan2.importersToUpdate) {
|
|
18955
19075
|
const rel = path38.relative(cwd, imp.file.getFilePath());
|
|
18956
|
-
console.log(` ${
|
|
19076
|
+
console.log(` ${chalk170.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
18957
19077
|
}
|
|
18958
19078
|
}
|
|
18959
19079
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
18960
|
-
console.log(
|
|
19080
|
+
console.log(chalk170.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
18961
19081
|
`));
|
|
18962
|
-
console.log(` ${
|
|
19082
|
+
console.log(` ${chalk170.cyan("Functions to move:")}`);
|
|
18963
19083
|
for (const name of plan2.extractedNames) {
|
|
18964
19084
|
console.log(` ${name}`);
|
|
18965
19085
|
}
|
|
@@ -18993,7 +19113,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
18993
19113
|
|
|
18994
19114
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
18995
19115
|
import path40 from "path";
|
|
18996
|
-
import
|
|
19116
|
+
import chalk171 from "chalk";
|
|
18997
19117
|
import { Project as Project4 } from "ts-morph";
|
|
18998
19118
|
|
|
18999
19119
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -19053,7 +19173,7 @@ function loadProjectFile(file) {
|
|
|
19053
19173
|
});
|
|
19054
19174
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
19055
19175
|
if (!sourceFile) {
|
|
19056
|
-
console.log(
|
|
19176
|
+
console.log(chalk171.red(`File not found in project: ${file}`));
|
|
19057
19177
|
process.exit(1);
|
|
19058
19178
|
}
|
|
19059
19179
|
return { project, sourceFile };
|
|
@@ -19076,19 +19196,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
19076
19196
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
19077
19197
|
if (options2.apply) {
|
|
19078
19198
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
19079
|
-
console.log(
|
|
19199
|
+
console.log(chalk172.green("\nExtraction complete"));
|
|
19080
19200
|
} else {
|
|
19081
|
-
console.log(
|
|
19201
|
+
console.log(chalk172.dim("\nDry run. Use --apply to execute."));
|
|
19082
19202
|
}
|
|
19083
19203
|
}
|
|
19084
19204
|
|
|
19085
19205
|
// src/commands/refactor/ignore.ts
|
|
19086
19206
|
import fs27 from "fs";
|
|
19087
|
-
import
|
|
19207
|
+
import chalk173 from "chalk";
|
|
19088
19208
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
19089
19209
|
function ignore2(file) {
|
|
19090
19210
|
if (!fs27.existsSync(file)) {
|
|
19091
|
-
console.error(
|
|
19211
|
+
console.error(chalk173.red(`Error: File does not exist: ${file}`));
|
|
19092
19212
|
process.exit(1);
|
|
19093
19213
|
}
|
|
19094
19214
|
const content = fs27.readFileSync(file, "utf8");
|
|
@@ -19104,7 +19224,7 @@ function ignore2(file) {
|
|
|
19104
19224
|
fs27.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
19105
19225
|
}
|
|
19106
19226
|
console.log(
|
|
19107
|
-
|
|
19227
|
+
chalk173.green(
|
|
19108
19228
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
19109
19229
|
)
|
|
19110
19230
|
);
|
|
@@ -19113,12 +19233,12 @@ function ignore2(file) {
|
|
|
19113
19233
|
// src/commands/refactor/rename/index.ts
|
|
19114
19234
|
import fs30 from "fs";
|
|
19115
19235
|
import path46 from "path";
|
|
19116
|
-
import
|
|
19236
|
+
import chalk176 from "chalk";
|
|
19117
19237
|
|
|
19118
19238
|
// src/commands/refactor/rename/applyRename.ts
|
|
19119
19239
|
import fs29 from "fs";
|
|
19120
19240
|
import path43 from "path";
|
|
19121
|
-
import
|
|
19241
|
+
import chalk174 from "chalk";
|
|
19122
19242
|
|
|
19123
19243
|
// src/commands/refactor/restructure/computeRewrites/index.ts
|
|
19124
19244
|
import path42 from "path";
|
|
@@ -19223,13 +19343,13 @@ function applyRename(rewrites, sourcePath, destPath, cwd) {
|
|
|
19223
19343
|
const updatedContents = applyRewrites(rewrites);
|
|
19224
19344
|
for (const [file, content] of updatedContents) {
|
|
19225
19345
|
fs29.writeFileSync(file, content, "utf8");
|
|
19226
|
-
console.log(
|
|
19346
|
+
console.log(chalk174.cyan(` Updated imports in ${path43.relative(cwd, file)}`));
|
|
19227
19347
|
}
|
|
19228
19348
|
const destDir = path43.dirname(destPath);
|
|
19229
19349
|
if (!fs29.existsSync(destDir)) fs29.mkdirSync(destDir, { recursive: true });
|
|
19230
19350
|
fs29.renameSync(sourcePath, destPath);
|
|
19231
19351
|
console.log(
|
|
19232
|
-
|
|
19352
|
+
chalk174.white(
|
|
19233
19353
|
` Moved ${path43.relative(cwd, sourcePath)} \u2192 ${path43.relative(cwd, destPath)}`
|
|
19234
19354
|
)
|
|
19235
19355
|
);
|
|
@@ -19316,16 +19436,16 @@ function computeRenameRewrites(sourcePath, destPath) {
|
|
|
19316
19436
|
|
|
19317
19437
|
// src/commands/refactor/rename/printRenamePreview.ts
|
|
19318
19438
|
import path45 from "path";
|
|
19319
|
-
import
|
|
19439
|
+
import chalk175 from "chalk";
|
|
19320
19440
|
function printRenamePreview(rewrites, cwd) {
|
|
19321
19441
|
for (const rewrite of rewrites) {
|
|
19322
19442
|
console.log(
|
|
19323
|
-
|
|
19443
|
+
chalk175.dim(
|
|
19324
19444
|
` ${path45.relative(cwd, rewrite.file)}: ${rewrite.oldSpecifier} \u2192 ${rewrite.newSpecifier}`
|
|
19325
19445
|
)
|
|
19326
19446
|
);
|
|
19327
19447
|
}
|
|
19328
|
-
console.log(
|
|
19448
|
+
console.log(chalk175.dim("Dry run. Use --apply to execute."));
|
|
19329
19449
|
}
|
|
19330
19450
|
|
|
19331
19451
|
// src/commands/refactor/rename/index.ts
|
|
@@ -19336,20 +19456,20 @@ async function rename(source, destination, options2 = {}) {
|
|
|
19336
19456
|
const relSource = path46.relative(cwd, sourcePath);
|
|
19337
19457
|
const relDest = path46.relative(cwd, destPath);
|
|
19338
19458
|
if (!fs30.existsSync(sourcePath)) {
|
|
19339
|
-
console.log(
|
|
19459
|
+
console.log(chalk176.red(`File not found: ${source}`));
|
|
19340
19460
|
process.exit(1);
|
|
19341
19461
|
}
|
|
19342
19462
|
if (destPath !== sourcePath && fs30.existsSync(destPath)) {
|
|
19343
|
-
console.log(
|
|
19463
|
+
console.log(chalk176.red(`Destination already exists: ${destination}`));
|
|
19344
19464
|
process.exit(1);
|
|
19345
19465
|
}
|
|
19346
|
-
console.log(
|
|
19347
|
-
console.log(
|
|
19348
|
-
console.log(
|
|
19466
|
+
console.log(chalk176.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
19467
|
+
console.log(chalk176.dim("Loading project..."));
|
|
19468
|
+
console.log(chalk176.dim("Scanning imports across the project..."));
|
|
19349
19469
|
const rewrites = computeRenameRewrites(sourcePath, destPath);
|
|
19350
19470
|
const affectedFiles = new Set(rewrites.map((r) => r.file)).size;
|
|
19351
19471
|
console.log(
|
|
19352
|
-
|
|
19472
|
+
chalk176.dim(
|
|
19353
19473
|
`${rewrites.length} import path(s) to update across ${affectedFiles} file(s)`
|
|
19354
19474
|
)
|
|
19355
19475
|
);
|
|
@@ -19358,11 +19478,11 @@ async function rename(source, destination, options2 = {}) {
|
|
|
19358
19478
|
return;
|
|
19359
19479
|
}
|
|
19360
19480
|
applyRename(rewrites, sourcePath, destPath, cwd);
|
|
19361
|
-
console.log(
|
|
19481
|
+
console.log(chalk176.green("Done"));
|
|
19362
19482
|
}
|
|
19363
19483
|
|
|
19364
19484
|
// src/commands/refactor/renameSymbol/index.ts
|
|
19365
|
-
import
|
|
19485
|
+
import chalk177 from "chalk";
|
|
19366
19486
|
|
|
19367
19487
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
19368
19488
|
import { SyntaxKind as SyntaxKind15 } from "ts-morph";
|
|
@@ -19408,33 +19528,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
19408
19528
|
const { project, sourceFile } = loadProjectFile(file);
|
|
19409
19529
|
const symbol = findSymbol(sourceFile, oldName);
|
|
19410
19530
|
if (!symbol) {
|
|
19411
|
-
console.log(
|
|
19531
|
+
console.log(chalk177.red(`Symbol "${oldName}" not found in ${file}`));
|
|
19412
19532
|
process.exit(1);
|
|
19413
19533
|
}
|
|
19414
19534
|
const grouped = groupReferences(symbol, cwd);
|
|
19415
19535
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
19416
19536
|
console.log(
|
|
19417
|
-
|
|
19537
|
+
chalk177.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
19418
19538
|
`)
|
|
19419
19539
|
);
|
|
19420
19540
|
for (const [refFile, lines] of grouped) {
|
|
19421
19541
|
console.log(
|
|
19422
|
-
` ${
|
|
19542
|
+
` ${chalk177.dim(refFile)}: lines ${chalk177.cyan(lines.join(", "))}`
|
|
19423
19543
|
);
|
|
19424
19544
|
}
|
|
19425
19545
|
if (options2.apply) {
|
|
19426
19546
|
symbol.rename(newName);
|
|
19427
19547
|
await project.save();
|
|
19428
|
-
console.log(
|
|
19548
|
+
console.log(chalk177.green(`
|
|
19429
19549
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
19430
19550
|
} else {
|
|
19431
|
-
console.log(
|
|
19551
|
+
console.log(chalk177.dim("\nDry run. Use --apply to execute."));
|
|
19432
19552
|
}
|
|
19433
19553
|
}
|
|
19434
19554
|
|
|
19435
19555
|
// src/commands/refactor/restructure/index.ts
|
|
19436
19556
|
import path54 from "path";
|
|
19437
|
-
import
|
|
19557
|
+
import chalk180 from "chalk";
|
|
19438
19558
|
|
|
19439
19559
|
// src/commands/refactor/restructure/clusterDirectories.ts
|
|
19440
19560
|
import path48 from "path";
|
|
@@ -19513,50 +19633,50 @@ function clusterFiles(graph) {
|
|
|
19513
19633
|
|
|
19514
19634
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
19515
19635
|
import path50 from "path";
|
|
19516
|
-
import
|
|
19636
|
+
import chalk178 from "chalk";
|
|
19517
19637
|
function relPath(filePath) {
|
|
19518
19638
|
return path50.relative(process.cwd(), filePath);
|
|
19519
19639
|
}
|
|
19520
19640
|
function displayMoves(plan2) {
|
|
19521
19641
|
if (plan2.moves.length === 0) return;
|
|
19522
|
-
console.log(
|
|
19642
|
+
console.log(chalk178.bold("\nFile moves:"));
|
|
19523
19643
|
for (const move2 of plan2.moves) {
|
|
19524
19644
|
console.log(
|
|
19525
|
-
` ${
|
|
19645
|
+
` ${chalk178.red(relPath(move2.from))} \u2192 ${chalk178.green(relPath(move2.to))}`
|
|
19526
19646
|
);
|
|
19527
|
-
console.log(
|
|
19647
|
+
console.log(chalk178.dim(` ${move2.reason}`));
|
|
19528
19648
|
}
|
|
19529
19649
|
}
|
|
19530
19650
|
function displayRewrites(rewrites) {
|
|
19531
19651
|
if (rewrites.length === 0) return;
|
|
19532
19652
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
19533
|
-
console.log(
|
|
19653
|
+
console.log(chalk178.bold(`
|
|
19534
19654
|
Import rewrites (${affectedFiles.size} files):`));
|
|
19535
19655
|
for (const file of affectedFiles) {
|
|
19536
|
-
console.log(` ${
|
|
19656
|
+
console.log(` ${chalk178.cyan(relPath(file))}:`);
|
|
19537
19657
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
19538
19658
|
(r) => r.file === file
|
|
19539
19659
|
)) {
|
|
19540
19660
|
console.log(
|
|
19541
|
-
` ${
|
|
19661
|
+
` ${chalk178.red(`"${oldSpecifier}"`)} \u2192 ${chalk178.green(`"${newSpecifier}"`)}`
|
|
19542
19662
|
);
|
|
19543
19663
|
}
|
|
19544
19664
|
}
|
|
19545
19665
|
}
|
|
19546
19666
|
function displayPlan2(plan2) {
|
|
19547
19667
|
if (plan2.warnings.length > 0) {
|
|
19548
|
-
console.log(
|
|
19549
|
-
for (const w of plan2.warnings) console.log(
|
|
19668
|
+
console.log(chalk178.yellow("\nWarnings:"));
|
|
19669
|
+
for (const w of plan2.warnings) console.log(chalk178.yellow(` ${w}`));
|
|
19550
19670
|
}
|
|
19551
19671
|
if (plan2.newDirectories.length > 0) {
|
|
19552
|
-
console.log(
|
|
19672
|
+
console.log(chalk178.bold("\nNew directories:"));
|
|
19553
19673
|
for (const dir of plan2.newDirectories)
|
|
19554
|
-
console.log(
|
|
19674
|
+
console.log(chalk178.green(` ${dir}/`));
|
|
19555
19675
|
}
|
|
19556
19676
|
displayMoves(plan2);
|
|
19557
19677
|
displayRewrites(plan2.rewrites);
|
|
19558
19678
|
console.log(
|
|
19559
|
-
|
|
19679
|
+
chalk178.dim(
|
|
19560
19680
|
`
|
|
19561
19681
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
19562
19682
|
)
|
|
@@ -19566,18 +19686,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
19566
19686
|
// src/commands/refactor/restructure/executePlan.ts
|
|
19567
19687
|
import fs31 from "fs";
|
|
19568
19688
|
import path51 from "path";
|
|
19569
|
-
import
|
|
19689
|
+
import chalk179 from "chalk";
|
|
19570
19690
|
function executePlan(plan2) {
|
|
19571
19691
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
19572
19692
|
for (const [file, content] of updatedContents) {
|
|
19573
19693
|
fs31.writeFileSync(file, content, "utf8");
|
|
19574
19694
|
console.log(
|
|
19575
|
-
|
|
19695
|
+
chalk179.cyan(` Rewrote imports in ${path51.relative(process.cwd(), file)}`)
|
|
19576
19696
|
);
|
|
19577
19697
|
}
|
|
19578
19698
|
for (const dir of plan2.newDirectories) {
|
|
19579
19699
|
fs31.mkdirSync(dir, { recursive: true });
|
|
19580
|
-
console.log(
|
|
19700
|
+
console.log(chalk179.green(` Created ${path51.relative(process.cwd(), dir)}/`));
|
|
19581
19701
|
}
|
|
19582
19702
|
for (const move2 of plan2.moves) {
|
|
19583
19703
|
const targetDir = path51.dirname(move2.to);
|
|
@@ -19586,7 +19706,7 @@ function executePlan(plan2) {
|
|
|
19586
19706
|
}
|
|
19587
19707
|
fs31.renameSync(move2.from, move2.to);
|
|
19588
19708
|
console.log(
|
|
19589
|
-
|
|
19709
|
+
chalk179.white(
|
|
19590
19710
|
` Moved ${path51.relative(process.cwd(), move2.from)} \u2192 ${path51.relative(process.cwd(), move2.to)}`
|
|
19591
19711
|
)
|
|
19592
19712
|
);
|
|
@@ -19601,7 +19721,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
19601
19721
|
if (entries.length === 0) {
|
|
19602
19722
|
fs31.rmdirSync(dir);
|
|
19603
19723
|
console.log(
|
|
19604
|
-
|
|
19724
|
+
chalk179.dim(
|
|
19605
19725
|
` Removed empty directory ${path51.relative(process.cwd(), dir)}`
|
|
19606
19726
|
)
|
|
19607
19727
|
);
|
|
@@ -19734,22 +19854,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
19734
19854
|
const targetPattern = pattern2 ?? "src";
|
|
19735
19855
|
const files = findSourceFiles2(targetPattern);
|
|
19736
19856
|
if (files.length === 0) {
|
|
19737
|
-
console.log(
|
|
19857
|
+
console.log(chalk180.yellow("No files found matching pattern"));
|
|
19738
19858
|
return;
|
|
19739
19859
|
}
|
|
19740
19860
|
const tsConfigPath = path54.resolve("tsconfig.json");
|
|
19741
19861
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
19742
19862
|
if (plan2.moves.length === 0) {
|
|
19743
|
-
console.log(
|
|
19863
|
+
console.log(chalk180.green("No restructuring needed"));
|
|
19744
19864
|
return;
|
|
19745
19865
|
}
|
|
19746
19866
|
displayPlan2(plan2);
|
|
19747
19867
|
if (options2.apply) {
|
|
19748
|
-
console.log(
|
|
19868
|
+
console.log(chalk180.bold("\nApplying changes..."));
|
|
19749
19869
|
executePlan(plan2);
|
|
19750
|
-
console.log(
|
|
19870
|
+
console.log(chalk180.green("\nRestructuring complete"));
|
|
19751
19871
|
} else {
|
|
19752
|
-
console.log(
|
|
19872
|
+
console.log(chalk180.dim("\nDry run. Use --apply to execute."));
|
|
19753
19873
|
}
|
|
19754
19874
|
}
|
|
19755
19875
|
|
|
@@ -19934,9 +20054,9 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
19934
20054
|
}
|
|
19935
20055
|
|
|
19936
20056
|
// src/commands/review/fetchExistingComments.ts
|
|
19937
|
-
import { execSync as
|
|
20057
|
+
import { execSync as execSync51 } from "child_process";
|
|
19938
20058
|
function fetchRawComments(org, repo, prNumber) {
|
|
19939
|
-
const out =
|
|
20059
|
+
const out = execSync51(
|
|
19940
20060
|
`gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
|
|
19941
20061
|
{ encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
|
|
19942
20062
|
);
|
|
@@ -19967,14 +20087,14 @@ function fetchExistingComments() {
|
|
|
19967
20087
|
}
|
|
19968
20088
|
|
|
19969
20089
|
// src/commands/review/gatherContext.ts
|
|
19970
|
-
import { execSync as
|
|
20090
|
+
import { execSync as execSync54 } from "child_process";
|
|
19971
20091
|
|
|
19972
20092
|
// src/commands/review/fetchPrDiff.ts
|
|
19973
|
-
import { execSync as
|
|
20093
|
+
import { execSync as execSync52 } from "child_process";
|
|
19974
20094
|
function fetchPrDiff(prNumber, baseSha, headSha) {
|
|
19975
20095
|
const { org, repo } = getRepoInfo();
|
|
19976
20096
|
try {
|
|
19977
|
-
return
|
|
20097
|
+
return execSync52(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
|
|
19978
20098
|
encoding: "utf8",
|
|
19979
20099
|
maxBuffer: 256 * 1024 * 1024,
|
|
19980
20100
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -19989,19 +20109,19 @@ function isDiffTooLarge(error) {
|
|
|
19989
20109
|
}
|
|
19990
20110
|
function fetchDiffViaGit(baseSha, headSha) {
|
|
19991
20111
|
try {
|
|
19992
|
-
|
|
20112
|
+
execSync52(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
|
|
19993
20113
|
} catch {
|
|
19994
20114
|
}
|
|
19995
|
-
return
|
|
20115
|
+
return execSync52(`git diff ${baseSha}...${headSha}`, {
|
|
19996
20116
|
encoding: "utf8",
|
|
19997
20117
|
maxBuffer: 256 * 1024 * 1024
|
|
19998
20118
|
});
|
|
19999
20119
|
}
|
|
20000
20120
|
|
|
20001
20121
|
// src/commands/review/fetchPrDiffInfo.ts
|
|
20002
|
-
import { execSync as
|
|
20122
|
+
import { execSync as execSync53 } from "child_process";
|
|
20003
20123
|
function getCurrentBranch3() {
|
|
20004
|
-
return
|
|
20124
|
+
return execSync53("git rev-parse --abbrev-ref HEAD", {
|
|
20005
20125
|
encoding: "utf8"
|
|
20006
20126
|
}).trim();
|
|
20007
20127
|
}
|
|
@@ -20009,7 +20129,7 @@ function fetchPrDiffInfo() {
|
|
|
20009
20129
|
const { org, repo } = getRepoInfo();
|
|
20010
20130
|
const branch2 = getCurrentBranch3();
|
|
20011
20131
|
const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
|
|
20012
|
-
const raw =
|
|
20132
|
+
const raw = execSync53(
|
|
20013
20133
|
`gh pr list --state open --head ${branch2} --json ${fields} -R ${org}/${repo}`,
|
|
20014
20134
|
{
|
|
20015
20135
|
encoding: "utf8",
|
|
@@ -20034,7 +20154,7 @@ function fetchPrDiffInfo() {
|
|
|
20034
20154
|
}
|
|
20035
20155
|
function fetchPrChangedFiles(prNumber) {
|
|
20036
20156
|
const { org, repo } = getRepoInfo();
|
|
20037
|
-
const out =
|
|
20157
|
+
const out = execSync53(
|
|
20038
20158
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
|
|
20039
20159
|
{
|
|
20040
20160
|
encoding: "utf8",
|
|
@@ -20046,11 +20166,11 @@ function fetchPrChangedFiles(prNumber) {
|
|
|
20046
20166
|
|
|
20047
20167
|
// src/commands/review/gatherContext.ts
|
|
20048
20168
|
function gatherContext() {
|
|
20049
|
-
const branch2 =
|
|
20169
|
+
const branch2 = execSync54("git rev-parse --abbrev-ref HEAD", {
|
|
20050
20170
|
encoding: "utf8"
|
|
20051
20171
|
}).trim();
|
|
20052
|
-
const sha =
|
|
20053
|
-
const shortSha =
|
|
20172
|
+
const sha = execSync54("git rev-parse HEAD", { encoding: "utf8" }).trim();
|
|
20173
|
+
const shortSha = execSync54("git rev-parse --short=7 HEAD", {
|
|
20054
20174
|
encoding: "utf8"
|
|
20055
20175
|
}).trim();
|
|
20056
20176
|
const prInfo = fetchPrDiffInfo();
|
|
@@ -20332,18 +20452,18 @@ function partitionFindingsByDiff(findings, index3) {
|
|
|
20332
20452
|
}
|
|
20333
20453
|
|
|
20334
20454
|
// src/commands/review/warnOutOfDiff.ts
|
|
20335
|
-
import
|
|
20455
|
+
import chalk181 from "chalk";
|
|
20336
20456
|
function warnOutOfDiff(outOfDiff) {
|
|
20337
20457
|
if (outOfDiff.length === 0) return;
|
|
20338
20458
|
console.warn(
|
|
20339
|
-
|
|
20459
|
+
chalk181.yellow(
|
|
20340
20460
|
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
20341
20461
|
)
|
|
20342
20462
|
);
|
|
20343
20463
|
for (const finding of outOfDiff) {
|
|
20344
20464
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
20345
20465
|
console.warn(
|
|
20346
|
-
` ${
|
|
20466
|
+
` ${chalk181.yellow("\xB7")} ${finding.title} ${chalk181.dim(
|
|
20347
20467
|
`(${finding.file}:${range})`
|
|
20348
20468
|
)}`
|
|
20349
20469
|
);
|
|
@@ -20362,18 +20482,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
20362
20482
|
}
|
|
20363
20483
|
|
|
20364
20484
|
// src/commands/review/warnUnlocated.ts
|
|
20365
|
-
import
|
|
20485
|
+
import chalk182 from "chalk";
|
|
20366
20486
|
function warnUnlocated(unlocated) {
|
|
20367
20487
|
if (unlocated.length === 0) return;
|
|
20368
20488
|
console.warn(
|
|
20369
|
-
|
|
20489
|
+
chalk182.yellow(
|
|
20370
20490
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
20371
20491
|
)
|
|
20372
20492
|
);
|
|
20373
20493
|
for (const finding of unlocated) {
|
|
20374
|
-
const where = finding.location ||
|
|
20494
|
+
const where = finding.location || chalk182.dim("missing");
|
|
20375
20495
|
console.warn(
|
|
20376
|
-
` ${
|
|
20496
|
+
` ${chalk182.yellow("\xB7")} ${finding.title} ${chalk182.dim(`(${where})`)}`
|
|
20377
20497
|
);
|
|
20378
20498
|
}
|
|
20379
20499
|
}
|
|
@@ -21545,7 +21665,7 @@ function registerReview(program2) {
|
|
|
21545
21665
|
}
|
|
21546
21666
|
|
|
21547
21667
|
// src/commands/seq/seqAuth.ts
|
|
21548
|
-
import
|
|
21668
|
+
import chalk184 from "chalk";
|
|
21549
21669
|
|
|
21550
21670
|
// src/commands/seq/loadConnections.ts
|
|
21551
21671
|
function loadConnections2() {
|
|
@@ -21574,10 +21694,10 @@ function setDefaultConnection(name) {
|
|
|
21574
21694
|
}
|
|
21575
21695
|
|
|
21576
21696
|
// src/shared/assertUniqueName.ts
|
|
21577
|
-
import
|
|
21697
|
+
import chalk183 from "chalk";
|
|
21578
21698
|
function assertUniqueName(existingNames, name) {
|
|
21579
21699
|
if (existingNames.includes(name)) {
|
|
21580
|
-
console.error(
|
|
21700
|
+
console.error(chalk183.red(`Connection "${name}" already exists.`));
|
|
21581
21701
|
process.exit(1);
|
|
21582
21702
|
}
|
|
21583
21703
|
}
|
|
@@ -21595,7 +21715,7 @@ async function promptConnection2(existingNames) {
|
|
|
21595
21715
|
var seqAuth = createConnectionAuth({
|
|
21596
21716
|
load: loadConnections2,
|
|
21597
21717
|
save: saveConnections2,
|
|
21598
|
-
format: (c) => `${
|
|
21718
|
+
format: (c) => `${chalk184.bold(c.name)} ${c.url}`,
|
|
21599
21719
|
promptNew: promptConnection2,
|
|
21600
21720
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
21601
21721
|
});
|
|
@@ -21615,10 +21735,10 @@ var seqConfigHelp = [
|
|
|
21615
21735
|
];
|
|
21616
21736
|
|
|
21617
21737
|
// src/commands/seq/seqQuery.ts
|
|
21618
|
-
import
|
|
21738
|
+
import chalk188 from "chalk";
|
|
21619
21739
|
|
|
21620
21740
|
// src/commands/seq/fetchSeq.ts
|
|
21621
|
-
import
|
|
21741
|
+
import chalk185 from "chalk";
|
|
21622
21742
|
async function fetchSeq(conn, path67, params) {
|
|
21623
21743
|
const url = `${conn.url}${path67}?${params}`;
|
|
21624
21744
|
const response = await fetch(url, {
|
|
@@ -21629,7 +21749,7 @@ async function fetchSeq(conn, path67, params) {
|
|
|
21629
21749
|
});
|
|
21630
21750
|
if (!response.ok) {
|
|
21631
21751
|
const body = await response.text();
|
|
21632
|
-
console.error(
|
|
21752
|
+
console.error(chalk185.red(`Seq returned ${response.status}: ${body}`));
|
|
21633
21753
|
process.exit(1);
|
|
21634
21754
|
}
|
|
21635
21755
|
return response;
|
|
@@ -21643,8 +21763,8 @@ function filterToSql(filter) {
|
|
|
21643
21763
|
// src/commands/seq/fetchSeqData.ts
|
|
21644
21764
|
function buildDataParams(filter, count7, from, to) {
|
|
21645
21765
|
const sqlFilter = filterToSql(filter);
|
|
21646
|
-
const
|
|
21647
|
-
const params = new URLSearchParams({ q:
|
|
21766
|
+
const sql24 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count7}`;
|
|
21767
|
+
const params = new URLSearchParams({ q: sql24 });
|
|
21648
21768
|
if (from) params.set("rangeStartUtc", from);
|
|
21649
21769
|
if (to) params.set("rangeEndUtc", to);
|
|
21650
21770
|
return params;
|
|
@@ -21688,23 +21808,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
21688
21808
|
}
|
|
21689
21809
|
|
|
21690
21810
|
// src/commands/seq/formatEvent.ts
|
|
21691
|
-
import
|
|
21811
|
+
import chalk186 from "chalk";
|
|
21692
21812
|
function levelColor(level) {
|
|
21693
21813
|
switch (level) {
|
|
21694
21814
|
case "Fatal":
|
|
21695
|
-
return
|
|
21815
|
+
return chalk186.bgRed.white;
|
|
21696
21816
|
case "Error":
|
|
21697
|
-
return
|
|
21817
|
+
return chalk186.red;
|
|
21698
21818
|
case "Warning":
|
|
21699
|
-
return
|
|
21819
|
+
return chalk186.yellow;
|
|
21700
21820
|
case "Information":
|
|
21701
|
-
return
|
|
21821
|
+
return chalk186.cyan;
|
|
21702
21822
|
case "Debug":
|
|
21703
|
-
return
|
|
21823
|
+
return chalk186.gray;
|
|
21704
21824
|
case "Verbose":
|
|
21705
|
-
return
|
|
21825
|
+
return chalk186.dim;
|
|
21706
21826
|
default:
|
|
21707
|
-
return
|
|
21827
|
+
return chalk186.white;
|
|
21708
21828
|
}
|
|
21709
21829
|
}
|
|
21710
21830
|
function levelAbbrev(level) {
|
|
@@ -21745,12 +21865,12 @@ function formatTimestamp(iso) {
|
|
|
21745
21865
|
function formatEvent(event) {
|
|
21746
21866
|
const color = levelColor(event.Level);
|
|
21747
21867
|
const abbrev = levelAbbrev(event.Level);
|
|
21748
|
-
const ts8 =
|
|
21868
|
+
const ts8 = chalk186.dim(formatTimestamp(event.Timestamp));
|
|
21749
21869
|
const msg = renderMessage(event);
|
|
21750
21870
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
21751
21871
|
if (event.Exception) {
|
|
21752
21872
|
for (const line of event.Exception.split("\n")) {
|
|
21753
|
-
lines.push(
|
|
21873
|
+
lines.push(chalk186.red(` ${line}`));
|
|
21754
21874
|
}
|
|
21755
21875
|
}
|
|
21756
21876
|
return lines.join("\n");
|
|
@@ -21783,11 +21903,11 @@ function rejectTimestampFilter(filter) {
|
|
|
21783
21903
|
}
|
|
21784
21904
|
|
|
21785
21905
|
// src/shared/resolveNamedConnection.ts
|
|
21786
|
-
import
|
|
21906
|
+
import chalk187 from "chalk";
|
|
21787
21907
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
21788
21908
|
if (connections.length === 0) {
|
|
21789
21909
|
console.error(
|
|
21790
|
-
|
|
21910
|
+
chalk187.red(
|
|
21791
21911
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
21792
21912
|
)
|
|
21793
21913
|
);
|
|
@@ -21796,7 +21916,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
21796
21916
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
21797
21917
|
const connection = connections.find((c) => c.name === target);
|
|
21798
21918
|
if (!connection) {
|
|
21799
|
-
console.error(
|
|
21919
|
+
console.error(chalk187.red(`${kind} connection "${target}" not found.`));
|
|
21800
21920
|
process.exit(1);
|
|
21801
21921
|
}
|
|
21802
21922
|
return connection;
|
|
@@ -21825,7 +21945,7 @@ async function seqQuery(filter, options2) {
|
|
|
21825
21945
|
new URLSearchParams({ filter, count: String(count7) })
|
|
21826
21946
|
);
|
|
21827
21947
|
if (events.length === 0) {
|
|
21828
|
-
console.log(
|
|
21948
|
+
console.log(chalk188.yellow("No events found."));
|
|
21829
21949
|
return;
|
|
21830
21950
|
}
|
|
21831
21951
|
if (options2.json) {
|
|
@@ -21836,11 +21956,11 @@ async function seqQuery(filter, options2) {
|
|
|
21836
21956
|
for (const event of chronological) {
|
|
21837
21957
|
console.log(formatEvent(event));
|
|
21838
21958
|
}
|
|
21839
|
-
console.log(
|
|
21959
|
+
console.log(chalk188.dim(`
|
|
21840
21960
|
${events.length} events`));
|
|
21841
21961
|
if (events.length >= count7) {
|
|
21842
21962
|
console.log(
|
|
21843
|
-
|
|
21963
|
+
chalk188.yellow(
|
|
21844
21964
|
`Results limited to ${count7}. Use --count to retrieve more.`
|
|
21845
21965
|
)
|
|
21846
21966
|
);
|
|
@@ -21848,10 +21968,10 @@ ${events.length} events`));
|
|
|
21848
21968
|
}
|
|
21849
21969
|
|
|
21850
21970
|
// src/shared/setNamedDefaultConnection.ts
|
|
21851
|
-
import
|
|
21971
|
+
import chalk189 from "chalk";
|
|
21852
21972
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
21853
21973
|
if (!connections.find((c) => c.name === name)) {
|
|
21854
|
-
console.error(
|
|
21974
|
+
console.error(chalk189.red(`Connection "${name}" not found.`));
|
|
21855
21975
|
process.exit(1);
|
|
21856
21976
|
}
|
|
21857
21977
|
setDefault(name);
|
|
@@ -21900,36 +22020,36 @@ function registerSignal(program2) {
|
|
|
21900
22020
|
}
|
|
21901
22021
|
|
|
21902
22022
|
// src/commands/sql/sqlAuth.ts
|
|
21903
|
-
import
|
|
22023
|
+
import chalk191 from "chalk";
|
|
21904
22024
|
|
|
21905
22025
|
// src/commands/sql/loadConnections.ts
|
|
21906
22026
|
function loadConnections3() {
|
|
21907
22027
|
const raw = loadGlobalConfigRaw();
|
|
21908
|
-
const
|
|
21909
|
-
return
|
|
22028
|
+
const sql24 = raw.sql;
|
|
22029
|
+
return sql24?.connections ?? [];
|
|
21910
22030
|
}
|
|
21911
22031
|
function saveConnections3(connections) {
|
|
21912
22032
|
const raw = loadGlobalConfigRaw();
|
|
21913
|
-
const
|
|
21914
|
-
|
|
21915
|
-
raw.sql =
|
|
22033
|
+
const sql24 = raw.sql ?? {};
|
|
22034
|
+
sql24.connections = connections;
|
|
22035
|
+
raw.sql = sql24;
|
|
21916
22036
|
saveGlobalConfig(raw);
|
|
21917
22037
|
}
|
|
21918
22038
|
function getDefaultConnection2() {
|
|
21919
22039
|
const raw = loadGlobalConfigRaw();
|
|
21920
|
-
const
|
|
21921
|
-
return
|
|
22040
|
+
const sql24 = raw.sql;
|
|
22041
|
+
return sql24?.defaultConnection;
|
|
21922
22042
|
}
|
|
21923
22043
|
function setDefaultConnection2(name) {
|
|
21924
22044
|
const raw = loadGlobalConfigRaw();
|
|
21925
|
-
const
|
|
21926
|
-
|
|
21927
|
-
raw.sql =
|
|
22045
|
+
const sql24 = raw.sql ?? {};
|
|
22046
|
+
sql24.defaultConnection = name;
|
|
22047
|
+
raw.sql = sql24;
|
|
21928
22048
|
saveGlobalConfig(raw);
|
|
21929
22049
|
}
|
|
21930
22050
|
|
|
21931
22051
|
// src/commands/sql/promptConnection.ts
|
|
21932
|
-
import
|
|
22052
|
+
import chalk190 from "chalk";
|
|
21933
22053
|
async function promptConnection3(existingNames) {
|
|
21934
22054
|
const name = await promptInput("name", "Connection name:", "default");
|
|
21935
22055
|
assertUniqueName(existingNames, name);
|
|
@@ -21937,7 +22057,7 @@ async function promptConnection3(existingNames) {
|
|
|
21937
22057
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
21938
22058
|
const port = Number.parseInt(portStr, 10);
|
|
21939
22059
|
if (!Number.isFinite(port)) {
|
|
21940
|
-
console.error(
|
|
22060
|
+
console.error(chalk190.red(`Invalid port "${portStr}".`));
|
|
21941
22061
|
process.exit(1);
|
|
21942
22062
|
}
|
|
21943
22063
|
const user = await promptInput("user", "User:");
|
|
@@ -21950,13 +22070,13 @@ async function promptConnection3(existingNames) {
|
|
|
21950
22070
|
var sqlAuth = createConnectionAuth({
|
|
21951
22071
|
load: loadConnections3,
|
|
21952
22072
|
save: saveConnections3,
|
|
21953
|
-
format: (c) => `${
|
|
22073
|
+
format: (c) => `${chalk191.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
21954
22074
|
promptNew: promptConnection3,
|
|
21955
22075
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
21956
22076
|
});
|
|
21957
22077
|
|
|
21958
22078
|
// src/commands/sql/printTable.ts
|
|
21959
|
-
import
|
|
22079
|
+
import chalk192 from "chalk";
|
|
21960
22080
|
function formatCell(value) {
|
|
21961
22081
|
if (value === null || value === void 0) return "";
|
|
21962
22082
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -21965,7 +22085,7 @@ function formatCell(value) {
|
|
|
21965
22085
|
}
|
|
21966
22086
|
function printTable(rows) {
|
|
21967
22087
|
if (rows.length === 0) {
|
|
21968
|
-
console.log(
|
|
22088
|
+
console.log(chalk192.yellow("(no rows)"));
|
|
21969
22089
|
return;
|
|
21970
22090
|
}
|
|
21971
22091
|
const columns = Object.keys(rows[0]);
|
|
@@ -21973,13 +22093,13 @@ function printTable(rows) {
|
|
|
21973
22093
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
21974
22094
|
);
|
|
21975
22095
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
21976
|
-
console.log(
|
|
21977
|
-
console.log(
|
|
22096
|
+
console.log(chalk192.dim(header));
|
|
22097
|
+
console.log(chalk192.dim("-".repeat(header.length)));
|
|
21978
22098
|
for (const row of rows) {
|
|
21979
22099
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
21980
22100
|
console.log(line);
|
|
21981
22101
|
}
|
|
21982
|
-
console.log(
|
|
22102
|
+
console.log(chalk192.dim(`
|
|
21983
22103
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
21984
22104
|
}
|
|
21985
22105
|
|
|
@@ -21995,9 +22115,9 @@ function resolveConnection3(name) {
|
|
|
21995
22115
|
}
|
|
21996
22116
|
|
|
21997
22117
|
// src/commands/sql/sqlConnect.ts
|
|
21998
|
-
import
|
|
22118
|
+
import sql18 from "mssql";
|
|
21999
22119
|
async function sqlConnect(conn) {
|
|
22000
|
-
return await
|
|
22120
|
+
return await sql18.connect({
|
|
22001
22121
|
server: conn.server,
|
|
22002
22122
|
port: conn.port,
|
|
22003
22123
|
user: conn.user,
|
|
@@ -22053,7 +22173,7 @@ var sqlConfigHelp = [
|
|
|
22053
22173
|
];
|
|
22054
22174
|
|
|
22055
22175
|
// src/commands/sql/sqlMutate.ts
|
|
22056
|
-
import
|
|
22176
|
+
import chalk193 from "chalk";
|
|
22057
22177
|
|
|
22058
22178
|
// src/commands/sql/isMutation.ts
|
|
22059
22179
|
var MUTATION_KEYWORDS = [
|
|
@@ -22074,11 +22194,11 @@ var MUTATION_PATTERN = new RegExp(
|
|
|
22074
22194
|
`\\b(${MUTATION_KEYWORDS.join("|")})\\b`,
|
|
22075
22195
|
"i"
|
|
22076
22196
|
);
|
|
22077
|
-
function stripComments(
|
|
22078
|
-
return
|
|
22197
|
+
function stripComments(sql24) {
|
|
22198
|
+
return sql24.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
|
|
22079
22199
|
}
|
|
22080
|
-
function isMutation(
|
|
22081
|
-
const stripped = stripComments(
|
|
22200
|
+
function isMutation(sql24) {
|
|
22201
|
+
const stripped = stripComments(sql24);
|
|
22082
22202
|
if (MUTATION_PATTERN.test(stripped)) return true;
|
|
22083
22203
|
return /\bSELECT\b[\s\S]+\bINTO\s+\w/i.test(stripped);
|
|
22084
22204
|
}
|
|
@@ -22087,7 +22207,7 @@ function isMutation(sql23) {
|
|
|
22087
22207
|
async function sqlMutate(query, connectionName) {
|
|
22088
22208
|
if (!isMutation(query)) {
|
|
22089
22209
|
console.error(
|
|
22090
|
-
|
|
22210
|
+
chalk193.red(
|
|
22091
22211
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
22092
22212
|
)
|
|
22093
22213
|
);
|
|
@@ -22097,18 +22217,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
22097
22217
|
const pool = await sqlConnect(conn);
|
|
22098
22218
|
try {
|
|
22099
22219
|
const result = await pool.request().query(query);
|
|
22100
|
-
console.log(
|
|
22220
|
+
console.log(chalk193.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
22101
22221
|
} finally {
|
|
22102
22222
|
await pool.close();
|
|
22103
22223
|
}
|
|
22104
22224
|
}
|
|
22105
22225
|
|
|
22106
22226
|
// src/commands/sql/sqlQuery.ts
|
|
22107
|
-
import
|
|
22227
|
+
import chalk194 from "chalk";
|
|
22108
22228
|
async function sqlQuery(query, connectionName) {
|
|
22109
22229
|
if (isMutation(query)) {
|
|
22110
22230
|
console.error(
|
|
22111
|
-
|
|
22231
|
+
chalk194.red(
|
|
22112
22232
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
22113
22233
|
)
|
|
22114
22234
|
);
|
|
@@ -22123,7 +22243,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
22123
22243
|
printTable(rows);
|
|
22124
22244
|
} else {
|
|
22125
22245
|
console.log(
|
|
22126
|
-
|
|
22246
|
+
chalk194.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
22127
22247
|
);
|
|
22128
22248
|
}
|
|
22129
22249
|
} finally {
|
|
@@ -22700,7 +22820,7 @@ import { mkdirSync as mkdirSync20 } from "fs";
|
|
|
22700
22820
|
import { join as join58 } from "path";
|
|
22701
22821
|
|
|
22702
22822
|
// src/commands/voice/checkLockFile.ts
|
|
22703
|
-
import { execSync as
|
|
22823
|
+
import { execSync as execSync55 } from "child_process";
|
|
22704
22824
|
import { existsSync as existsSync47, mkdirSync as mkdirSync19, readFileSync as readFileSync42, writeFileSync as writeFileSync37 } from "fs";
|
|
22705
22825
|
import { join as join57 } from "path";
|
|
22706
22826
|
function isProcessAlive2(pid) {
|
|
@@ -22729,7 +22849,7 @@ function bootstrapVenv() {
|
|
|
22729
22849
|
if (existsSync47(getVenvPython())) return;
|
|
22730
22850
|
console.log("Setting up Python environment...");
|
|
22731
22851
|
const pythonDir = getPythonDir();
|
|
22732
|
-
|
|
22852
|
+
execSync55(
|
|
22733
22853
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
22734
22854
|
{
|
|
22735
22855
|
stdio: "inherit",
|
|
@@ -22938,7 +23058,7 @@ function registerVoice(program2) {
|
|
|
22938
23058
|
|
|
22939
23059
|
// src/commands/roam/auth.ts
|
|
22940
23060
|
import { randomBytes } from "crypto";
|
|
22941
|
-
import
|
|
23061
|
+
import chalk195 from "chalk";
|
|
22942
23062
|
|
|
22943
23063
|
// src/commands/roam/waitForCallback.ts
|
|
22944
23064
|
import { createServer as createServer3 } from "http";
|
|
@@ -23069,13 +23189,13 @@ async function auth() {
|
|
|
23069
23189
|
saveGlobalConfig(config);
|
|
23070
23190
|
const state = randomBytes(16).toString("hex");
|
|
23071
23191
|
console.log(
|
|
23072
|
-
|
|
23192
|
+
chalk195.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
23073
23193
|
);
|
|
23074
|
-
console.log(
|
|
23075
|
-
console.log(
|
|
23076
|
-
console.log(
|
|
23194
|
+
console.log(chalk195.white("http://localhost:14523/callback\n"));
|
|
23195
|
+
console.log(chalk195.blue("Opening browser for authorization..."));
|
|
23196
|
+
console.log(chalk195.dim("Waiting for authorization callback..."));
|
|
23077
23197
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
23078
|
-
console.log(
|
|
23198
|
+
console.log(chalk195.dim("Exchanging code for tokens..."));
|
|
23079
23199
|
const tokens = await exchangeToken({
|
|
23080
23200
|
code,
|
|
23081
23201
|
clientId,
|
|
@@ -23091,7 +23211,7 @@ async function auth() {
|
|
|
23091
23211
|
};
|
|
23092
23212
|
saveGlobalConfig(config);
|
|
23093
23213
|
console.log(
|
|
23094
|
-
|
|
23214
|
+
chalk195.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
23095
23215
|
);
|
|
23096
23216
|
}
|
|
23097
23217
|
|
|
@@ -23325,11 +23445,11 @@ function resolveParams(params, cliArgs) {
|
|
|
23325
23445
|
}
|
|
23326
23446
|
|
|
23327
23447
|
// src/commands/run/runPreCommands.ts
|
|
23328
|
-
import { execSync as
|
|
23448
|
+
import { execSync as execSync56 } from "child_process";
|
|
23329
23449
|
function runPreCommands(pre, cwd) {
|
|
23330
23450
|
for (const cmd of pre) {
|
|
23331
23451
|
try {
|
|
23332
|
-
|
|
23452
|
+
execSync56(cmd, { stdio: "inherit", cwd });
|
|
23333
23453
|
} catch (error) {
|
|
23334
23454
|
const code = error && typeof error === "object" && "status" in error ? error.status : 1;
|
|
23335
23455
|
process.exit(code);
|
|
@@ -23630,11 +23750,11 @@ function registerRun(program2) {
|
|
|
23630
23750
|
}
|
|
23631
23751
|
|
|
23632
23752
|
// src/commands/screenshot/index.ts
|
|
23633
|
-
import { execSync as
|
|
23753
|
+
import { execSync as execSync57 } from "child_process";
|
|
23634
23754
|
import { existsSync as existsSync52, mkdirSync as mkdirSync23, unlinkSync as unlinkSync19, writeFileSync as writeFileSync40 } from "fs";
|
|
23635
23755
|
import { tmpdir as tmpdir7 } from "os";
|
|
23636
23756
|
import { join as join64, resolve as resolve15 } from "path";
|
|
23637
|
-
import
|
|
23757
|
+
import chalk196 from "chalk";
|
|
23638
23758
|
|
|
23639
23759
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
23640
23760
|
var captureWindowPs1 = `
|
|
@@ -23773,7 +23893,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
23773
23893
|
const scriptPath = join64(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
23774
23894
|
writeFileSync40(scriptPath, captureWindowPs1, "utf8");
|
|
23775
23895
|
try {
|
|
23776
|
-
|
|
23896
|
+
execSync57(
|
|
23777
23897
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
23778
23898
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
|
|
23779
23899
|
);
|
|
@@ -23785,13 +23905,13 @@ function screenshot(processName) {
|
|
|
23785
23905
|
const config = loadConfig();
|
|
23786
23906
|
const outputDir = resolve15(config.screenshot.outputDir);
|
|
23787
23907
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
23788
|
-
console.log(
|
|
23908
|
+
console.log(chalk196.gray(`Capturing window for process "${processName}" ...`));
|
|
23789
23909
|
try {
|
|
23790
23910
|
runPowerShellScript(processName, outputPath);
|
|
23791
|
-
console.log(
|
|
23911
|
+
console.log(chalk196.green(`Screenshot saved: ${outputPath}`));
|
|
23792
23912
|
} catch (error) {
|
|
23793
23913
|
const msg = error instanceof Error ? error.message : String(error);
|
|
23794
|
-
console.error(
|
|
23914
|
+
console.error(chalk196.red(`Failed to capture screenshot: ${msg}`));
|
|
23795
23915
|
process.exit(1);
|
|
23796
23916
|
}
|
|
23797
23917
|
}
|
|
@@ -24431,13 +24551,13 @@ function drainSessions(sessions, onDrained) {
|
|
|
24431
24551
|
}
|
|
24432
24552
|
|
|
24433
24553
|
// src/shared/db/recordPhaseActiveMs.ts
|
|
24434
|
-
import { sql as
|
|
24554
|
+
import { sql as sql19 } from "drizzle-orm";
|
|
24435
24555
|
async function recordPhaseActiveMs(db, itemId2, phaseIdx, activeMs) {
|
|
24436
24556
|
if (activeMs <= 0) return;
|
|
24437
24557
|
await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, activeMs }).onConflictDoUpdate({
|
|
24438
24558
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
24439
24559
|
set: {
|
|
24440
|
-
activeMs:
|
|
24560
|
+
activeMs: sql19`${phaseUsage.activeMs} + excluded.active_ms`
|
|
24441
24561
|
}
|
|
24442
24562
|
});
|
|
24443
24563
|
}
|
|
@@ -24629,7 +24749,7 @@ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
|
|
|
24629
24749
|
}
|
|
24630
24750
|
|
|
24631
24751
|
// src/shared/db/recordPhaseCycleContext.ts
|
|
24632
|
-
import { sql as
|
|
24752
|
+
import { sql as sql20 } from "drizzle-orm";
|
|
24633
24753
|
async function recordPhaseCycleContext(db, itemId2, phaseIdx, window, resetsAt, pct) {
|
|
24634
24754
|
if (pct <= 0) return;
|
|
24635
24755
|
await db.insert(phaseCycleContext).values({ itemId: itemId2, phaseIdx, window, resetsAt, peakContextPct: pct }).onConflictDoUpdate({
|
|
@@ -24640,24 +24760,24 @@ async function recordPhaseCycleContext(db, itemId2, phaseIdx, window, resetsAt,
|
|
|
24640
24760
|
phaseCycleContext.resetsAt
|
|
24641
24761
|
],
|
|
24642
24762
|
set: {
|
|
24643
|
-
peakContextPct:
|
|
24763
|
+
peakContextPct: sql20`GREATEST(${phaseCycleContext.peakContextPct}, ${pct})`
|
|
24644
24764
|
}
|
|
24645
24765
|
});
|
|
24646
24766
|
}
|
|
24647
24767
|
|
|
24648
24768
|
// src/shared/db/recordPhasePeakContext.ts
|
|
24649
|
-
import { sql as
|
|
24769
|
+
import { sql as sql21 } from "drizzle-orm";
|
|
24650
24770
|
async function recordPhasePeakContext(db, itemId2, phaseIdx, pct) {
|
|
24651
24771
|
await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, peakContextPct: pct }).onConflictDoUpdate({
|
|
24652
24772
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
24653
24773
|
set: {
|
|
24654
|
-
peakContextPct:
|
|
24774
|
+
peakContextPct: sql21`GREATEST(${phaseUsage.peakContextPct}, ${pct})`
|
|
24655
24775
|
}
|
|
24656
24776
|
});
|
|
24657
24777
|
}
|
|
24658
24778
|
|
|
24659
24779
|
// src/shared/db/recordPhaseTranscriptUsage.ts
|
|
24660
|
-
import { sql as
|
|
24780
|
+
import { sql as sql22 } from "drizzle-orm";
|
|
24661
24781
|
async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
24662
24782
|
const byId = /* @__PURE__ */ new Map();
|
|
24663
24783
|
for (const r of responses) byId.set(r.messageId, r);
|
|
@@ -24677,8 +24797,8 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
|
24677
24797
|
await tx.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, tokensUp, tokensDown }).onConflictDoUpdate({
|
|
24678
24798
|
target: [phaseUsage.itemId, phaseUsage.phaseIdx],
|
|
24679
24799
|
set: {
|
|
24680
|
-
tokensUp:
|
|
24681
|
-
tokensDown:
|
|
24800
|
+
tokensUp: sql22`${phaseUsage.tokensUp} + ${tokensUp}`,
|
|
24801
|
+
tokensDown: sql22`${phaseUsage.tokensDown} + ${tokensDown}`
|
|
24682
24802
|
}
|
|
24683
24803
|
});
|
|
24684
24804
|
return { tokensUp, tokensDown };
|
|
@@ -24686,17 +24806,17 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
|
|
|
24686
24806
|
}
|
|
24687
24807
|
|
|
24688
24808
|
// src/shared/db/recordWindowTokens.ts
|
|
24689
|
-
import { and as and21, eq as
|
|
24809
|
+
import { and as and21, eq as eq40, sql as sql23 } from "drizzle-orm";
|
|
24690
24810
|
async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
|
|
24691
24811
|
if (tokensUp <= 0 && tokensDown <= 0) return;
|
|
24692
24812
|
await db.update(usagePeaks).set({
|
|
24693
|
-
tokensUp:
|
|
24694
|
-
tokensDown:
|
|
24813
|
+
tokensUp: sql23`${usagePeaks.tokensUp} + ${tokensUp}`,
|
|
24814
|
+
tokensDown: sql23`${usagePeaks.tokensDown} + ${tokensDown}`
|
|
24695
24815
|
}).where(
|
|
24696
24816
|
and21(
|
|
24697
|
-
|
|
24698
|
-
|
|
24699
|
-
|
|
24817
|
+
eq40(usagePeaks.window, window),
|
|
24818
|
+
eq40(usagePeaks.resetsAt, resetsAt),
|
|
24819
|
+
eq40(usagePeaks.segment, 0)
|
|
24700
24820
|
)
|
|
24701
24821
|
);
|
|
24702
24822
|
}
|
|
@@ -24820,10 +24940,10 @@ function applyReviewPause(session, activity2) {
|
|
|
24820
24940
|
}
|
|
24821
24941
|
|
|
24822
24942
|
// src/shared/db/getPhaseActiveMs.ts
|
|
24823
|
-
import { and as and22, eq as
|
|
24943
|
+
import { and as and22, eq as eq41 } from "drizzle-orm";
|
|
24824
24944
|
async function getPhaseActiveMs(db, itemId2, phaseIdx) {
|
|
24825
24945
|
const [row] = await db.select({ activeMs: phaseUsage.activeMs }).from(phaseUsage).where(
|
|
24826
|
-
and22(
|
|
24946
|
+
and22(eq41(phaseUsage.itemId, itemId2), eq41(phaseUsage.phaseIdx, phaseIdx))
|
|
24827
24947
|
);
|
|
24828
24948
|
return row?.activeMs ?? 0;
|
|
24829
24949
|
}
|
|
@@ -26597,7 +26717,7 @@ function registerDaemon(program2) {
|
|
|
26597
26717
|
|
|
26598
26718
|
// src/commands/sessions/summarise/index.ts
|
|
26599
26719
|
import * as fs38 from "fs";
|
|
26600
|
-
import
|
|
26720
|
+
import chalk197 from "chalk";
|
|
26601
26721
|
|
|
26602
26722
|
// src/commands/sessions/summarise/shared.ts
|
|
26603
26723
|
import * as fs37 from "fs";
|
|
@@ -26671,22 +26791,22 @@ ${firstMessage}`);
|
|
|
26671
26791
|
async function summarise2(options2) {
|
|
26672
26792
|
const files = await discoverSessionFiles();
|
|
26673
26793
|
if (files.length === 0) {
|
|
26674
|
-
console.log(
|
|
26794
|
+
console.log(chalk197.yellow("No sessions found."));
|
|
26675
26795
|
return;
|
|
26676
26796
|
}
|
|
26677
26797
|
const toProcess = selectCandidates(files, options2);
|
|
26678
26798
|
if (toProcess.length === 0) {
|
|
26679
|
-
console.log(
|
|
26799
|
+
console.log(chalk197.green("All sessions already summarised."));
|
|
26680
26800
|
return;
|
|
26681
26801
|
}
|
|
26682
26802
|
console.log(
|
|
26683
|
-
|
|
26803
|
+
chalk197.cyan(
|
|
26684
26804
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
26685
26805
|
)
|
|
26686
26806
|
);
|
|
26687
26807
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
26688
26808
|
console.log(
|
|
26689
|
-
|
|
26809
|
+
chalk197.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk197.yellow(`, ${failed2} skipped`) : "")
|
|
26690
26810
|
);
|
|
26691
26811
|
}
|
|
26692
26812
|
function selectCandidates(files, options2) {
|
|
@@ -26706,16 +26826,16 @@ function processSessions(files) {
|
|
|
26706
26826
|
let failed2 = 0;
|
|
26707
26827
|
for (let i = 0; i < files.length; i++) {
|
|
26708
26828
|
const file = files[i];
|
|
26709
|
-
process.stdout.write(
|
|
26829
|
+
process.stdout.write(chalk197.dim(` [${i + 1}/${files.length}] `));
|
|
26710
26830
|
const summary = summariseSession(file);
|
|
26711
26831
|
if (summary) {
|
|
26712
26832
|
writeSummary(file, summary);
|
|
26713
26833
|
succeeded++;
|
|
26714
|
-
process.stdout.write(`${
|
|
26834
|
+
process.stdout.write(`${chalk197.green("\u2713")} ${summary}
|
|
26715
26835
|
`);
|
|
26716
26836
|
} else {
|
|
26717
26837
|
failed2++;
|
|
26718
|
-
process.stdout.write(` ${
|
|
26838
|
+
process.stdout.write(` ${chalk197.yellow("skip")}
|
|
26719
26839
|
`);
|
|
26720
26840
|
}
|
|
26721
26841
|
}
|
|
@@ -26759,7 +26879,7 @@ function registerSessions(program2) {
|
|
|
26759
26879
|
}
|
|
26760
26880
|
|
|
26761
26881
|
// src/commands/statusLine.ts
|
|
26762
|
-
import
|
|
26882
|
+
import chalk199 from "chalk";
|
|
26763
26883
|
|
|
26764
26884
|
// src/shared/contextLevel.ts
|
|
26765
26885
|
function contextLevel(pct) {
|
|
@@ -26769,7 +26889,7 @@ function contextLevel(pct) {
|
|
|
26769
26889
|
}
|
|
26770
26890
|
|
|
26771
26891
|
// src/commands/buildLimitsSegment.ts
|
|
26772
|
-
import
|
|
26892
|
+
import chalk198 from "chalk";
|
|
26773
26893
|
|
|
26774
26894
|
// src/shared/rateLimitLevel.ts
|
|
26775
26895
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
@@ -26800,9 +26920,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
|
|
|
26800
26920
|
|
|
26801
26921
|
// src/commands/buildLimitsSegment.ts
|
|
26802
26922
|
var LEVEL_COLOR = {
|
|
26803
|
-
ok:
|
|
26804
|
-
warn:
|
|
26805
|
-
over:
|
|
26923
|
+
ok: chalk198.green,
|
|
26924
|
+
warn: chalk198.yellow,
|
|
26925
|
+
over: chalk198.red
|
|
26806
26926
|
};
|
|
26807
26927
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
|
|
26808
26928
|
const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
|
|
@@ -26898,7 +27018,7 @@ async function relayUsage(claudeSessionId, transcriptPath, usedPct) {
|
|
|
26898
27018
|
}
|
|
26899
27019
|
|
|
26900
27020
|
// src/commands/statusLine.ts
|
|
26901
|
-
|
|
27021
|
+
chalk199.level = 3;
|
|
26902
27022
|
function formatNumber(num) {
|
|
26903
27023
|
return num.toLocaleString("en-US");
|
|
26904
27024
|
}
|
|
@@ -26906,9 +27026,9 @@ function colorizePercent(pct) {
|
|
|
26906
27026
|
const label2 = `${Math.round(pct)}%`;
|
|
26907
27027
|
switch (contextLevel(pct)) {
|
|
26908
27028
|
case "red":
|
|
26909
|
-
return
|
|
27029
|
+
return chalk199.red(label2);
|
|
26910
27030
|
case "yellow":
|
|
26911
|
-
return
|
|
27031
|
+
return chalk199.yellow(label2);
|
|
26912
27032
|
default:
|
|
26913
27033
|
return label2;
|
|
26914
27034
|
}
|
|
@@ -26921,7 +27041,7 @@ async function statusLine() {
|
|
|
26921
27041
|
const usedPct = data.context_window.used_percentage ?? 0;
|
|
26922
27042
|
const dir = data.workspace?.current_dir ?? data.cwd;
|
|
26923
27043
|
const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
|
|
26924
|
-
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${
|
|
27044
|
+
const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk199.cyan(branch2)} | ` : "";
|
|
26925
27045
|
console.log(
|
|
26926
27046
|
`${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
|
|
26927
27047
|
);
|
|
@@ -26942,7 +27062,7 @@ import { fileURLToPath as fileURLToPath9 } from "url";
|
|
|
26942
27062
|
// src/commands/sync/syncClaudeMd.ts
|
|
26943
27063
|
import * as fs39 from "fs";
|
|
26944
27064
|
import * as path57 from "path";
|
|
26945
|
-
import
|
|
27065
|
+
import chalk200 from "chalk";
|
|
26946
27066
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
26947
27067
|
const source = path57.join(claudeDir, "CLAUDE.md");
|
|
26948
27068
|
const target = path57.join(targetBase, "CLAUDE.md");
|
|
@@ -26951,12 +27071,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
26951
27071
|
const targetContent = fs39.readFileSync(target, "utf8");
|
|
26952
27072
|
if (sourceContent !== targetContent) {
|
|
26953
27073
|
console.log(
|
|
26954
|
-
|
|
27074
|
+
chalk200.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
26955
27075
|
);
|
|
26956
27076
|
console.log();
|
|
26957
27077
|
printDiff(targetContent, sourceContent);
|
|
26958
27078
|
const confirm = options2?.yes || await promptConfirm(
|
|
26959
|
-
|
|
27079
|
+
chalk200.red("Overwrite existing CLAUDE.md?"),
|
|
26960
27080
|
false
|
|
26961
27081
|
);
|
|
26962
27082
|
if (!confirm) {
|
|
@@ -27150,7 +27270,7 @@ function syncPi(claudeDir) {
|
|
|
27150
27270
|
// src/commands/sync/syncSettings.ts
|
|
27151
27271
|
import * as fs44 from "fs";
|
|
27152
27272
|
import * as path64 from "path";
|
|
27153
|
-
import
|
|
27273
|
+
import chalk201 from "chalk";
|
|
27154
27274
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
27155
27275
|
const source = path64.join(claudeDir, "settings.json");
|
|
27156
27276
|
const target = path64.join(targetBase, "settings.json");
|
|
@@ -27169,14 +27289,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
27169
27289
|
if (mergedContent !== normalizedTarget) {
|
|
27170
27290
|
if (!options2?.yes) {
|
|
27171
27291
|
console.log(
|
|
27172
|
-
|
|
27292
|
+
chalk201.yellow(
|
|
27173
27293
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
27174
27294
|
)
|
|
27175
27295
|
);
|
|
27176
27296
|
console.log();
|
|
27177
27297
|
printDiff(targetContent, mergedContent);
|
|
27178
27298
|
const confirm = await promptConfirm(
|
|
27179
|
-
|
|
27299
|
+
chalk201.red("Overwrite existing settings.json?"),
|
|
27180
27300
|
false
|
|
27181
27301
|
);
|
|
27182
27302
|
if (!confirm) {
|
|
@@ -27218,7 +27338,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
27218
27338
|
}
|
|
27219
27339
|
|
|
27220
27340
|
// src/commands/update.ts
|
|
27221
|
-
import { execSync as
|
|
27341
|
+
import { execSync as execSync58 } from "child_process";
|
|
27222
27342
|
import * as path66 from "path";
|
|
27223
27343
|
|
|
27224
27344
|
// src/commands/restartDaemonAfterUpdate.ts
|
|
@@ -27242,7 +27362,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
27242
27362
|
if (resolved.split(path66.sep).includes("node_modules")) {
|
|
27243
27363
|
return true;
|
|
27244
27364
|
}
|
|
27245
|
-
const globalPrefix =
|
|
27365
|
+
const globalPrefix = execSync58("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
27246
27366
|
return resolved.toLowerCase().startsWith(path66.resolve(globalPrefix).toLowerCase());
|
|
27247
27367
|
} catch {
|
|
27248
27368
|
return false;
|
|
@@ -27253,18 +27373,18 @@ async function update2() {
|
|
|
27253
27373
|
console.log(`Assist is installed at: ${installDir}`);
|
|
27254
27374
|
if (isGitRepo(installDir)) {
|
|
27255
27375
|
console.log("Detected git repo installation, pulling latest...");
|
|
27256
|
-
|
|
27376
|
+
execSync58("git pull", { cwd: installDir, stdio: "inherit" });
|
|
27257
27377
|
console.log("Installing dependencies...");
|
|
27258
|
-
|
|
27378
|
+
execSync58("npm i", { cwd: installDir, stdio: "inherit" });
|
|
27259
27379
|
console.log("Building...");
|
|
27260
|
-
|
|
27380
|
+
execSync58("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
27261
27381
|
console.log("Syncing commands...");
|
|
27262
|
-
|
|
27382
|
+
execSync58("assist sync", { stdio: "inherit" });
|
|
27263
27383
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
27264
27384
|
console.log("Detected global npm installation, updating...");
|
|
27265
|
-
|
|
27385
|
+
execSync58("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
27266
27386
|
console.log("Syncing commands...");
|
|
27267
|
-
|
|
27387
|
+
execSync58("assist sync", { stdio: "inherit" });
|
|
27268
27388
|
} else {
|
|
27269
27389
|
console.error(
|
|
27270
27390
|
"Could not determine installation method. Expected a git repo or global npm install."
|
|
@@ -27275,10 +27395,10 @@ async function update2() {
|
|
|
27275
27395
|
}
|
|
27276
27396
|
|
|
27277
27397
|
// src/reportCliError.ts
|
|
27278
|
-
import
|
|
27398
|
+
import chalk202 from "chalk";
|
|
27279
27399
|
function reportCliError(error) {
|
|
27280
27400
|
if (error instanceof InvalidItemIdError) {
|
|
27281
|
-
console.error(
|
|
27401
|
+
console.error(chalk202.red(error.message));
|
|
27282
27402
|
} else {
|
|
27283
27403
|
console.error(error);
|
|
27284
27404
|
}
|