@staff0rd/assist 0.281.2 → 0.282.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 +6 -6
- package/claude/commands/jira.md +1 -1
- package/claude/commands/pr.md +14 -2
- package/dist/commands/sessions/web/bundle.js +62 -62
- package/dist/index.js +779 -628
- package/package.json +1 -1
- package/dist/commands/news/web/bundle.js +0 -66
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.282.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -230,9 +230,6 @@ var assistConfigSchema = z2.strictObject({
|
|
|
230
230
|
run: z2.array(z2.union([runConfigSchema, runLinkSchema])).optional(),
|
|
231
231
|
transcript: transcriptConfigSchema.optional(),
|
|
232
232
|
cliReadVerbs: z2.record(z2.string(), z2.array(z2.string())).optional(),
|
|
233
|
-
news: z2.strictObject({
|
|
234
|
-
feeds: z2.array(z2.string()).default([])
|
|
235
|
-
}).default({ feeds: [] }),
|
|
236
233
|
dotnet: z2.strictObject({
|
|
237
234
|
inspect: z2.strictObject({
|
|
238
235
|
suppress: z2.array(z2.string()).default([])
|
|
@@ -340,6 +337,7 @@ function loadConfig() {
|
|
|
340
337
|
const globalRaw = loadRawYaml(getGlobalConfigPath());
|
|
341
338
|
const projectRaw = loadRawYaml(getConfigPath());
|
|
342
339
|
const merged = mergeRawConfigs(globalRaw, projectRaw);
|
|
340
|
+
delete merged.news;
|
|
343
341
|
return assistConfigSchema.parse(merged);
|
|
344
342
|
}
|
|
345
343
|
function loadProjectConfig() {
|
|
@@ -444,13 +442,18 @@ var metadata = pgTable("metadata", {
|
|
|
444
442
|
key: text().primaryKey(),
|
|
445
443
|
value: text().notNull()
|
|
446
444
|
});
|
|
445
|
+
var feeds = pgTable("feeds", {
|
|
446
|
+
id: integer().generatedByDefaultAsIdentity().primaryKey(),
|
|
447
|
+
url: text().notNull().unique()
|
|
448
|
+
});
|
|
447
449
|
var backlogSchema = {
|
|
448
450
|
items,
|
|
449
451
|
comments,
|
|
450
452
|
links,
|
|
451
453
|
planPhases,
|
|
452
454
|
planTasks,
|
|
453
|
-
metadata
|
|
455
|
+
metadata,
|
|
456
|
+
feeds
|
|
454
457
|
};
|
|
455
458
|
|
|
456
459
|
// src/commands/backlog/BacklogOrm.ts
|
|
@@ -512,9 +515,43 @@ var SCHEMA = `
|
|
|
512
515
|
key TEXT PRIMARY KEY,
|
|
513
516
|
value TEXT NOT NULL
|
|
514
517
|
);
|
|
518
|
+
|
|
519
|
+
CREATE TABLE IF NOT EXISTS feeds (
|
|
520
|
+
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
521
|
+
url TEXT NOT NULL UNIQUE
|
|
522
|
+
);
|
|
515
523
|
`;
|
|
516
|
-
async function ensureSchema(
|
|
517
|
-
await
|
|
524
|
+
async function ensureSchema(exec3) {
|
|
525
|
+
await exec3(SCHEMA);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// src/commands/backlog/addFeed.ts
|
|
529
|
+
async function addFeed(db, url) {
|
|
530
|
+
const inserted = await db.insert(feeds).values({ url }).onConflictDoNothing({ target: feeds.url }).returning({ id: feeds.id });
|
|
531
|
+
return inserted.length > 0;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// src/commands/backlog/listFeeds.ts
|
|
535
|
+
import { asc } from "drizzle-orm";
|
|
536
|
+
async function listFeeds(db) {
|
|
537
|
+
const rows = await db.select({ url: feeds.url }).from(feeds).orderBy(asc(feeds.id));
|
|
538
|
+
return rows.map((r) => r.url);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/commands/backlog/seedNewsFeeds.ts
|
|
542
|
+
function legacyFeeds(raw) {
|
|
543
|
+
const news = raw.news;
|
|
544
|
+
const feeds2 = news?.feeds;
|
|
545
|
+
return Array.isArray(feeds2) ? feeds2.filter((f) => typeof f === "string") : [];
|
|
546
|
+
}
|
|
547
|
+
async function seedNewsFeeds(db) {
|
|
548
|
+
const existing = await listFeeds(db);
|
|
549
|
+
if (existing.length > 0) return;
|
|
550
|
+
const projectFeeds = legacyFeeds(loadProjectConfig());
|
|
551
|
+
const configFeeds = projectFeeds.length > 0 ? projectFeeds : legacyFeeds(loadGlobalConfigRaw());
|
|
552
|
+
for (const url of configFeeds) {
|
|
553
|
+
await addFeed(db, url);
|
|
554
|
+
}
|
|
518
555
|
}
|
|
519
556
|
|
|
520
557
|
// src/commands/backlog/getBacklogOrm.ts
|
|
@@ -549,6 +586,7 @@ function getBacklogOrm() {
|
|
|
549
586
|
_pool = pool;
|
|
550
587
|
await ensureSchema((sql4) => pool.query(sql4));
|
|
551
588
|
_orm = makeOrmFromPool(pool);
|
|
589
|
+
await seedNewsFeeds(_orm);
|
|
552
590
|
return _orm;
|
|
553
591
|
})();
|
|
554
592
|
return _connecting;
|
|
@@ -1835,7 +1873,7 @@ import { Project as Project2 } from "ts-morph";
|
|
|
1835
1873
|
function collectComments(sourceFile) {
|
|
1836
1874
|
const seen = /* @__PURE__ */ new Set();
|
|
1837
1875
|
const comments3 = [];
|
|
1838
|
-
const
|
|
1876
|
+
const collect4 = (node) => {
|
|
1839
1877
|
for (const range of [
|
|
1840
1878
|
...node.getLeadingCommentRanges(),
|
|
1841
1879
|
...node.getTrailingCommentRanges()
|
|
@@ -1846,8 +1884,8 @@ function collectComments(sourceFile) {
|
|
|
1846
1884
|
comments3.push({ pos, text: range.getText() });
|
|
1847
1885
|
}
|
|
1848
1886
|
};
|
|
1849
|
-
|
|
1850
|
-
sourceFile.forEachDescendant(
|
|
1887
|
+
collect4(sourceFile);
|
|
1888
|
+
sourceFile.forEachDescendant(collect4);
|
|
1851
1889
|
return comments3;
|
|
1852
1890
|
}
|
|
1853
1891
|
|
|
@@ -3190,10 +3228,10 @@ async function importItemsRemapped(orm, items2, origin) {
|
|
|
3190
3228
|
}
|
|
3191
3229
|
|
|
3192
3230
|
// src/commands/backlog/loadAllItems.ts
|
|
3193
|
-
import { asc as
|
|
3231
|
+
import { asc as asc3, eq as eq2 } from "drizzle-orm";
|
|
3194
3232
|
|
|
3195
3233
|
// src/commands/backlog/loadRelations.ts
|
|
3196
|
-
import { asc, inArray } from "drizzle-orm";
|
|
3234
|
+
import { asc as asc2, inArray } from "drizzle-orm";
|
|
3197
3235
|
function groupByItem(rows) {
|
|
3198
3236
|
const map = /* @__PURE__ */ new Map();
|
|
3199
3237
|
for (const row of rows) {
|
|
@@ -3203,13 +3241,13 @@ function groupByItem(rows) {
|
|
|
3203
3241
|
}
|
|
3204
3242
|
return map;
|
|
3205
3243
|
}
|
|
3206
|
-
var selectComments = (orm, ids) => orm.select().from(comments).where(inArray(comments.itemId, ids)).orderBy(
|
|
3207
|
-
var selectLinks = (orm, ids) => orm.select().from(links).where(inArray(links.itemId, ids)).orderBy(
|
|
3208
|
-
var selectPhases = (orm, ids) => orm.select().from(planPhases).where(inArray(planPhases.itemId, ids)).orderBy(
|
|
3244
|
+
var selectComments = (orm, ids) => orm.select().from(comments).where(inArray(comments.itemId, ids)).orderBy(asc2(comments.itemId), asc2(comments.idx));
|
|
3245
|
+
var selectLinks = (orm, ids) => orm.select().from(links).where(inArray(links.itemId, ids)).orderBy(asc2(links.itemId));
|
|
3246
|
+
var selectPhases = (orm, ids) => orm.select().from(planPhases).where(inArray(planPhases.itemId, ids)).orderBy(asc2(planPhases.itemId), asc2(planPhases.idx));
|
|
3209
3247
|
var selectTasks = (orm, ids) => orm.select().from(planTasks).where(inArray(planTasks.itemId, ids)).orderBy(
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3248
|
+
asc2(planTasks.itemId),
|
|
3249
|
+
asc2(planTasks.phaseIdx),
|
|
3250
|
+
asc2(planTasks.idx)
|
|
3213
3251
|
);
|
|
3214
3252
|
async function loadRelations(orm, ids, { includeComments = true, includeTasks = true } = {}) {
|
|
3215
3253
|
const [commentRows, linkRows, phaseRows, taskRows] = await Promise.all([
|
|
@@ -3299,7 +3337,7 @@ function rowToItem(row, rel) {
|
|
|
3299
3337
|
|
|
3300
3338
|
// src/commands/backlog/loadAllItems.ts
|
|
3301
3339
|
async function loadAllItems(orm, origin) {
|
|
3302
|
-
const rows = await orm.select().from(items).where(origin === void 0 ? void 0 : eq2(items.origin, origin)).orderBy(
|
|
3340
|
+
const rows = await orm.select().from(items).where(origin === void 0 ? void 0 : eq2(items.origin, origin)).orderBy(asc3(items.id));
|
|
3303
3341
|
if (rows.length === 0) return [];
|
|
3304
3342
|
const rel = await loadRelations(
|
|
3305
3343
|
orm,
|
|
@@ -3492,7 +3530,7 @@ import { eq as eq5, sql } from "drizzle-orm";
|
|
|
3492
3530
|
import { eq as eq4 } from "drizzle-orm";
|
|
3493
3531
|
|
|
3494
3532
|
// src/commands/backlog/searchItemIds.ts
|
|
3495
|
-
import { and, asc as
|
|
3533
|
+
import { and, asc as asc4, eq as eq6, ilike, or } from "drizzle-orm";
|
|
3496
3534
|
async function searchItemIds(orm, query, origin) {
|
|
3497
3535
|
const pattern2 = `%${query}%`;
|
|
3498
3536
|
const rows = await orm.selectDistinct({ id: items.id }).from(items).leftJoin(comments, eq6(comments.itemId, items.id)).leftJoin(planPhases, eq6(planPhases.itemId, items.id)).where(
|
|
@@ -3506,7 +3544,7 @@ async function searchItemIds(orm, query, origin) {
|
|
|
3506
3544
|
ilike(planPhases.name, pattern2)
|
|
3507
3545
|
)
|
|
3508
3546
|
)
|
|
3509
|
-
).orderBy(
|
|
3547
|
+
).orderBy(asc4(items.id));
|
|
3510
3548
|
return rows.map((r) => r.id);
|
|
3511
3549
|
}
|
|
3512
3550
|
|
|
@@ -4346,11 +4384,48 @@ import {
|
|
|
4346
4384
|
} from "http";
|
|
4347
4385
|
import chalk43 from "chalk";
|
|
4348
4386
|
|
|
4349
|
-
// src/
|
|
4350
|
-
import {
|
|
4387
|
+
// src/lib/openBrowser.ts
|
|
4388
|
+
import { execSync as execSync20 } from "child_process";
|
|
4389
|
+
function tryExec(commands) {
|
|
4390
|
+
for (const cmd of commands) {
|
|
4391
|
+
try {
|
|
4392
|
+
execSync20(cmd, { stdio: "ignore" });
|
|
4393
|
+
return true;
|
|
4394
|
+
} catch {
|
|
4395
|
+
}
|
|
4396
|
+
}
|
|
4397
|
+
return false;
|
|
4398
|
+
}
|
|
4351
4399
|
function openBrowser(url) {
|
|
4352
|
-
const
|
|
4353
|
-
|
|
4400
|
+
const platform = detectPlatform();
|
|
4401
|
+
const quoted = JSON.stringify(url);
|
|
4402
|
+
const commands = [];
|
|
4403
|
+
switch (platform) {
|
|
4404
|
+
case "macos":
|
|
4405
|
+
commands.push(
|
|
4406
|
+
`open -a "Google Chrome" ${quoted}`,
|
|
4407
|
+
`open -a "Microsoft Edge" ${quoted}`,
|
|
4408
|
+
`open -a "Safari" ${quoted}`
|
|
4409
|
+
);
|
|
4410
|
+
break;
|
|
4411
|
+
case "linux":
|
|
4412
|
+
commands.push(
|
|
4413
|
+
`google-chrome ${quoted}`,
|
|
4414
|
+
`chromium-browser ${quoted}`,
|
|
4415
|
+
`microsoft-edge ${quoted}`
|
|
4416
|
+
);
|
|
4417
|
+
break;
|
|
4418
|
+
case "windows":
|
|
4419
|
+
commands.push(`start chrome ${quoted}`, `start msedge ${quoted}`);
|
|
4420
|
+
break;
|
|
4421
|
+
case "wsl":
|
|
4422
|
+
commands.push(`xdg-open ${quoted}`);
|
|
4423
|
+
break;
|
|
4424
|
+
}
|
|
4425
|
+
if (!tryExec(commands)) {
|
|
4426
|
+
console.log(`Open this URL in Chrome, Edge, or Safari:
|
|
4427
|
+
${url}`);
|
|
4428
|
+
}
|
|
4354
4429
|
}
|
|
4355
4430
|
|
|
4356
4431
|
// src/shared/web.ts
|
|
@@ -4358,20 +4433,20 @@ function respondJson(res, status2, data) {
|
|
|
4358
4433
|
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
4359
4434
|
res.end(JSON.stringify(data));
|
|
4360
4435
|
}
|
|
4361
|
-
function createHtmlHandler(
|
|
4436
|
+
function createHtmlHandler(getHtml2) {
|
|
4362
4437
|
return (_req, res) => {
|
|
4363
4438
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
4364
|
-
res.end(
|
|
4439
|
+
res.end(getHtml2());
|
|
4365
4440
|
};
|
|
4366
4441
|
}
|
|
4367
4442
|
function parseRoute(req, port) {
|
|
4368
4443
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
4369
4444
|
return { method: req.method ?? "GET", pathname: url.pathname };
|
|
4370
4445
|
}
|
|
4371
|
-
function createRouteHandler(
|
|
4446
|
+
function createRouteHandler(routes2) {
|
|
4372
4447
|
return async (req, res, port) => {
|
|
4373
4448
|
const { method, pathname } = parseRoute(req, port);
|
|
4374
|
-
const handler =
|
|
4449
|
+
const handler = routes2[`${method} ${pathname}`];
|
|
4375
4450
|
if (handler) {
|
|
4376
4451
|
await handler(req, res);
|
|
4377
4452
|
return;
|
|
@@ -4384,7 +4459,7 @@ function buildUrl(port, initialPath) {
|
|
|
4384
4459
|
const base = `http://localhost:${port}`;
|
|
4385
4460
|
return initialPath ? `${base}${initialPath}` : base;
|
|
4386
4461
|
}
|
|
4387
|
-
function startWebServer(label2, port, handler, initialPath) {
|
|
4462
|
+
function startWebServer(label2, port, handler, initialPath, open = true) {
|
|
4388
4463
|
const url = buildUrl(port, initialPath);
|
|
4389
4464
|
const server = createServer((req, res) => {
|
|
4390
4465
|
handler(req, res, port);
|
|
@@ -4392,7 +4467,9 @@ function startWebServer(label2, port, handler, initialPath) {
|
|
|
4392
4467
|
server.listen(port, () => {
|
|
4393
4468
|
console.log(chalk43.green(`${label2}: ${url}`));
|
|
4394
4469
|
console.log(chalk43.dim("Press Ctrl+C to stop"));
|
|
4395
|
-
|
|
4470
|
+
if (open) {
|
|
4471
|
+
openBrowser(url);
|
|
4472
|
+
}
|
|
4396
4473
|
});
|
|
4397
4474
|
return server;
|
|
4398
4475
|
}
|
|
@@ -4531,12 +4608,12 @@ function createBundleHandler(importMetaUrl, bundlePath) {
|
|
|
4531
4608
|
}
|
|
4532
4609
|
|
|
4533
4610
|
// src/shared/createFallbackHandler.ts
|
|
4534
|
-
function createFallbackHandler(
|
|
4535
|
-
const baseHandler = createRouteHandler(
|
|
4611
|
+
function createFallbackHandler(routes2, htmlHandler2, extra) {
|
|
4612
|
+
const baseHandler = createRouteHandler(routes2);
|
|
4536
4613
|
return async (req, res, port) => {
|
|
4537
4614
|
const { method, pathname } = parseRoute(req, port);
|
|
4538
4615
|
if (extra && await extra(req, res, pathname)) return;
|
|
4539
|
-
if (
|
|
4616
|
+
if (routes2[`${method} ${pathname}`]) {
|
|
4540
4617
|
await baseHandler(req, res, port);
|
|
4541
4618
|
return;
|
|
4542
4619
|
}
|
|
@@ -4595,7 +4672,7 @@ async function createItem(req, res) {
|
|
|
4595
4672
|
import { eq as eq11 } from "drizzle-orm";
|
|
4596
4673
|
|
|
4597
4674
|
// src/commands/backlog/loadItemSummaries.ts
|
|
4598
|
-
import { asc as
|
|
4675
|
+
import { asc as asc5, eq as eq10 } from "drizzle-orm";
|
|
4599
4676
|
async function loadItemSummaries(orm, origin) {
|
|
4600
4677
|
const rows = await orm.select({
|
|
4601
4678
|
id: items.id,
|
|
@@ -4603,7 +4680,7 @@ async function loadItemSummaries(orm, origin) {
|
|
|
4603
4680
|
type: items.type,
|
|
4604
4681
|
name: items.name,
|
|
4605
4682
|
status: items.status
|
|
4606
|
-
}).from(items).where(origin === void 0 ? void 0 : eq10(items.origin, origin)).orderBy(
|
|
4683
|
+
}).from(items).where(origin === void 0 ? void 0 : eq10(items.origin, origin)).orderBy(asc5(items.id));
|
|
4607
4684
|
return rows.map((row) => ({
|
|
4608
4685
|
id: row.id,
|
|
4609
4686
|
origin: row.origin,
|
|
@@ -4844,7 +4921,7 @@ function getHtml() {
|
|
|
4844
4921
|
}
|
|
4845
4922
|
|
|
4846
4923
|
// src/commands/prs/getPreferredRemoteRepo.ts
|
|
4847
|
-
import { execSync as
|
|
4924
|
+
import { execSync as execSync21 } from "child_process";
|
|
4848
4925
|
var GITHUB_URL_PATTERN = /(?:git@github\.com:|https:\/\/github\.com\/)([^/]+)\/([^/]+?)(?:\.git)?\/?$/;
|
|
4849
4926
|
function parseGitHubUrl(url) {
|
|
4850
4927
|
const match = url.match(GITHUB_URL_PATTERN);
|
|
@@ -4853,7 +4930,7 @@ function parseGitHubUrl(url) {
|
|
|
4853
4930
|
}
|
|
4854
4931
|
function tryGetRemoteUrl(remote, cwd) {
|
|
4855
4932
|
try {
|
|
4856
|
-
return
|
|
4933
|
+
return execSync21(`git remote get-url ${remote}`, {
|
|
4857
4934
|
encoding: "utf-8",
|
|
4858
4935
|
stdio: ["pipe", "pipe", "pipe"],
|
|
4859
4936
|
cwd
|
|
@@ -4864,7 +4941,7 @@ function tryGetRemoteUrl(remote, cwd) {
|
|
|
4864
4941
|
}
|
|
4865
4942
|
function getCurrentBranchRemote(cwd) {
|
|
4866
4943
|
try {
|
|
4867
|
-
const ref =
|
|
4944
|
+
const ref = execSync21(
|
|
4868
4945
|
"git rev-parse --abbrev-ref --symbolic-full-name @{u}",
|
|
4869
4946
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], cwd }
|
|
4870
4947
|
).trim();
|
|
@@ -4876,7 +4953,7 @@ function getCurrentBranchRemote(cwd) {
|
|
|
4876
4953
|
}
|
|
4877
4954
|
function listRemotes(cwd) {
|
|
4878
4955
|
try {
|
|
4879
|
-
return
|
|
4956
|
+
return execSync21("git remote", {
|
|
4880
4957
|
encoding: "utf-8",
|
|
4881
4958
|
stdio: ["pipe", "pipe", "pipe"],
|
|
4882
4959
|
cwd
|
|
@@ -4926,7 +5003,7 @@ function githubUrl(req, res) {
|
|
|
4926
5003
|
}
|
|
4927
5004
|
|
|
4928
5005
|
// src/commands/sessions/web/gitStatus.ts
|
|
4929
|
-
import { execSync as
|
|
5006
|
+
import { execSync as execSync22 } from "child_process";
|
|
4930
5007
|
|
|
4931
5008
|
// src/commands/sessions/web/parseGitStatus.ts
|
|
4932
5009
|
function extractPath(rest) {
|
|
@@ -4958,7 +5035,7 @@ function gitStatus(req, res) {
|
|
|
4958
5035
|
const cwd = getCwdParam(req, res);
|
|
4959
5036
|
if (!cwd) return;
|
|
4960
5037
|
try {
|
|
4961
|
-
const output =
|
|
5038
|
+
const output = execSync22("git status --porcelain", {
|
|
4962
5039
|
encoding: "utf-8",
|
|
4963
5040
|
stdio: ["pipe", "pipe", "pipe"],
|
|
4964
5041
|
cwd
|
|
@@ -4969,10 +5046,133 @@ function gitStatus(req, res) {
|
|
|
4969
5046
|
}
|
|
4970
5047
|
}
|
|
4971
5048
|
|
|
5049
|
+
// src/commands/news/shared.ts
|
|
5050
|
+
import { decodeHTML } from "entities";
|
|
5051
|
+
function extractText(xml, tag) {
|
|
5052
|
+
const cdataMatch = xml.match(
|
|
5053
|
+
new RegExp(`<${tag}>\\s*<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>\\s*</${tag}>`)
|
|
5054
|
+
);
|
|
5055
|
+
if (cdataMatch) return cdataMatch[1].trim();
|
|
5056
|
+
const match = xml.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`));
|
|
5057
|
+
return match ? match[1].trim() : "";
|
|
5058
|
+
}
|
|
5059
|
+
function extractLink(itemXml) {
|
|
5060
|
+
const atomLink = itemXml.match(
|
|
5061
|
+
/<link[^>]*rel=["']alternate["'][^>]*href=["']([^"']+)["']/
|
|
5062
|
+
);
|
|
5063
|
+
if (atomLink) return atomLink[1];
|
|
5064
|
+
const atomLink2 = itemXml.match(/<link[^>]*href=["']([^"']+)["']/);
|
|
5065
|
+
if (atomLink2) return atomLink2[1];
|
|
5066
|
+
return extractText(itemXml, "link");
|
|
5067
|
+
}
|
|
5068
|
+
function parseDate(dateStr) {
|
|
5069
|
+
if (!dateStr) return (/* @__PURE__ */ new Date(0)).toISOString();
|
|
5070
|
+
try {
|
|
5071
|
+
return new Date(dateStr).toISOString();
|
|
5072
|
+
} catch {
|
|
5073
|
+
return (/* @__PURE__ */ new Date(0)).toISOString();
|
|
5074
|
+
}
|
|
5075
|
+
}
|
|
5076
|
+
function stripHtml(html) {
|
|
5077
|
+
const decoded = decodeHTML(html);
|
|
5078
|
+
const stripped = decoded.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
5079
|
+
return decodeHTML(stripped);
|
|
5080
|
+
}
|
|
5081
|
+
function matchAll(xml, regex) {
|
|
5082
|
+
const results = [];
|
|
5083
|
+
for (const m of xml.matchAll(regex)) {
|
|
5084
|
+
results.push(m[1]);
|
|
5085
|
+
}
|
|
5086
|
+
return results;
|
|
5087
|
+
}
|
|
5088
|
+
var MAX_EXCERPT = 500;
|
|
5089
|
+
function excerpt(xml, ...tags) {
|
|
5090
|
+
for (const tag of tags) {
|
|
5091
|
+
const raw = extractText(xml, tag);
|
|
5092
|
+
if (!raw) continue;
|
|
5093
|
+
const text3 = stripHtml(raw);
|
|
5094
|
+
if (text3.length <= MAX_EXCERPT) return text3;
|
|
5095
|
+
return `${text3.slice(0, MAX_EXCERPT)}\u2026`;
|
|
5096
|
+
}
|
|
5097
|
+
return "";
|
|
5098
|
+
}
|
|
5099
|
+
|
|
5100
|
+
// src/commands/news/parseFeed.ts
|
|
5101
|
+
function parseRss(xml, feedOrigin) {
|
|
5102
|
+
const feedTitle = extractText(xml, "title");
|
|
5103
|
+
return matchAll(xml, /<item[\s>]([\s\S]*?)<\/item>/g).map((itemXml) => ({
|
|
5104
|
+
title: extractText(itemXml, "title"),
|
|
5105
|
+
link: extractLink(itemXml),
|
|
5106
|
+
pubDate: parseDate(
|
|
5107
|
+
extractText(itemXml, "pubDate") || extractText(itemXml, "dc:date")
|
|
5108
|
+
),
|
|
5109
|
+
feedTitle,
|
|
5110
|
+
feedOrigin,
|
|
5111
|
+
excerpt: excerpt(itemXml, "description", "content:encoded")
|
|
5112
|
+
}));
|
|
5113
|
+
}
|
|
5114
|
+
function parseAtom(xml, feedOrigin) {
|
|
5115
|
+
const feedTitle = extractText(xml, "title");
|
|
5116
|
+
return matchAll(xml, /<entry[\s>]([\s\S]*?)<\/entry>/g).map((entryXml) => ({
|
|
5117
|
+
title: extractText(entryXml, "title"),
|
|
5118
|
+
link: extractLink(entryXml),
|
|
5119
|
+
pubDate: parseDate(
|
|
5120
|
+
extractText(entryXml, "published") || extractText(entryXml, "updated")
|
|
5121
|
+
),
|
|
5122
|
+
feedTitle,
|
|
5123
|
+
feedOrigin,
|
|
5124
|
+
excerpt: excerpt(entryXml, "summary", "content")
|
|
5125
|
+
}));
|
|
5126
|
+
}
|
|
5127
|
+
function parseFeed(xml, feedOrigin) {
|
|
5128
|
+
if (xml.includes("<feed")) return parseAtom(xml, feedOrigin);
|
|
5129
|
+
return parseRss(xml, feedOrigin);
|
|
5130
|
+
}
|
|
5131
|
+
|
|
5132
|
+
// src/commands/news/fetchFeeds.ts
|
|
5133
|
+
async function fetchFeeds(urls, onProgress) {
|
|
5134
|
+
let done2 = 0;
|
|
5135
|
+
const results = await Promise.allSettled(
|
|
5136
|
+
urls.map(async (url) => {
|
|
5137
|
+
const origin = new URL(url).origin;
|
|
5138
|
+
const res = await fetch(url);
|
|
5139
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
5140
|
+
const items3 = parseFeed(await res.text(), origin);
|
|
5141
|
+
done2++;
|
|
5142
|
+
onProgress?.(done2, urls.length);
|
|
5143
|
+
return items3;
|
|
5144
|
+
})
|
|
5145
|
+
);
|
|
5146
|
+
const items2 = [];
|
|
5147
|
+
for (const result of results) {
|
|
5148
|
+
if (result.status === "fulfilled") {
|
|
5149
|
+
items2.push(...result.value);
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
items2.sort(
|
|
5153
|
+
(a, b) => new Date(b.pubDate).getTime() - new Date(a.pubDate).getTime()
|
|
5154
|
+
);
|
|
5155
|
+
return items2;
|
|
5156
|
+
}
|
|
5157
|
+
|
|
5158
|
+
// src/commands/sessions/web/listNewsItems.ts
|
|
5159
|
+
var cachedItems;
|
|
5160
|
+
var inflight;
|
|
5161
|
+
async function listNewsItems(_req, res) {
|
|
5162
|
+
if (!cachedItems) {
|
|
5163
|
+
if (!inflight)
|
|
5164
|
+
inflight = getReady().then(
|
|
5165
|
+
({ orm }) => listFeeds(orm).then((urls) => fetchFeeds(urls))
|
|
5166
|
+
);
|
|
5167
|
+
cachedItems = await inflight;
|
|
5168
|
+
}
|
|
5169
|
+
respondJson(res, 200, cachedItems);
|
|
5170
|
+
}
|
|
5171
|
+
|
|
4972
5172
|
// src/commands/sessions/web/openInCode.ts
|
|
4973
|
-
import { exec
|
|
5173
|
+
import { exec } from "child_process";
|
|
4974
5174
|
import { promisify } from "util";
|
|
4975
|
-
var execAsync = promisify(
|
|
5175
|
+
var execAsync = promisify(exec);
|
|
4976
5176
|
async function openInCode(req, res) {
|
|
4977
5177
|
const cwd = getCwdParam(req, res);
|
|
4978
5178
|
if (!cwd) return;
|
|
@@ -5013,7 +5213,8 @@ var routes = {
|
|
|
5013
5213
|
"POST /api/backlog/init": initBacklog,
|
|
5014
5214
|
"POST /api/open-in-code": openInCode,
|
|
5015
5215
|
"GET /api/github-url": githubUrl,
|
|
5016
|
-
"GET /api/git-status": gitStatus
|
|
5216
|
+
"GET /api/git-status": gitStatus,
|
|
5217
|
+
"GET /api/news/items": listNewsItems
|
|
5017
5218
|
};
|
|
5018
5219
|
var handleRequest = createFallbackHandler(
|
|
5019
5220
|
routes,
|
|
@@ -5313,6 +5514,9 @@ import { spawnSync } from "child_process";
|
|
|
5313
5514
|
function resolveExecve() {
|
|
5314
5515
|
return typeof process.execve === "function" ? process.execve.bind(process) : null;
|
|
5315
5516
|
}
|
|
5517
|
+
function withNoOpen(args) {
|
|
5518
|
+
return args.includes("--no-open") ? args : [...args, "--no-open"];
|
|
5519
|
+
}
|
|
5316
5520
|
function reExecWebServer(deps2 = {}) {
|
|
5317
5521
|
const {
|
|
5318
5522
|
beforeExec,
|
|
@@ -5322,11 +5526,13 @@ function reExecWebServer(deps2 = {}) {
|
|
|
5322
5526
|
} = deps2;
|
|
5323
5527
|
beforeExec?.();
|
|
5324
5528
|
if (execveFn) {
|
|
5325
|
-
execveFn(process.execPath, process.argv, process.env);
|
|
5529
|
+
execveFn(process.execPath, withNoOpen(process.argv), process.env);
|
|
5326
5530
|
return;
|
|
5327
5531
|
}
|
|
5328
5532
|
const [, ...args] = process.argv;
|
|
5329
|
-
const result = spawnSyncFn(process.execPath, args, {
|
|
5533
|
+
const result = spawnSyncFn(process.execPath, withNoOpen(args), {
|
|
5534
|
+
stdio: "inherit"
|
|
5535
|
+
});
|
|
5330
5536
|
exit(result.status ?? 0);
|
|
5331
5537
|
}
|
|
5332
5538
|
|
|
@@ -5388,7 +5594,8 @@ async function web(options2) {
|
|
|
5388
5594
|
"Assist",
|
|
5389
5595
|
port,
|
|
5390
5596
|
handleRequest,
|
|
5391
|
-
options2.initialPath
|
|
5597
|
+
options2.initialPath,
|
|
5598
|
+
options2.open !== false
|
|
5392
5599
|
);
|
|
5393
5600
|
const serverCwd = process.cwd();
|
|
5394
5601
|
const ctx = {
|
|
@@ -5410,7 +5617,11 @@ async function web(options2) {
|
|
|
5410
5617
|
|
|
5411
5618
|
// src/commands/backlog/web/index.ts
|
|
5412
5619
|
async function web2(options2) {
|
|
5413
|
-
await web({
|
|
5620
|
+
await web({
|
|
5621
|
+
port: options2.port,
|
|
5622
|
+
initialPath: "/backlog",
|
|
5623
|
+
open: options2.open
|
|
5624
|
+
});
|
|
5414
5625
|
}
|
|
5415
5626
|
|
|
5416
5627
|
// src/commands/backlog/comment/index.ts
|
|
@@ -6572,9 +6783,9 @@ async function findPhase(id, phase) {
|
|
|
6572
6783
|
}
|
|
6573
6784
|
|
|
6574
6785
|
// src/commands/backlog/reindexPhases.ts
|
|
6575
|
-
import { and as and7, asc as
|
|
6786
|
+
import { and as and7, asc as asc6, count as count5, eq as eq24 } from "drizzle-orm";
|
|
6576
6787
|
async function reindexPhases(db, itemId) {
|
|
6577
|
-
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq24(planPhases.itemId, itemId)).orderBy(
|
|
6788
|
+
const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq24(planPhases.itemId, itemId)).orderBy(asc6(planPhases.idx));
|
|
6578
6789
|
for (let i = 0; i < remaining.length; i++) {
|
|
6579
6790
|
const oldIdx = remaining[i].idx;
|
|
6580
6791
|
if (oldIdx === i) continue;
|
|
@@ -6908,7 +7119,7 @@ function registerShowCommands(cmd) {
|
|
|
6908
7119
|
cmd.command("show <id>").alias("view").description("Show full detail for a backlog item").action(show);
|
|
6909
7120
|
}
|
|
6910
7121
|
function registerWebCommand(cmd) {
|
|
6911
|
-
cmd.command("web").description("Open the backlog tab in the web dashboard").option("-p, --port <number>", "Port to listen on", "3100").action(web2);
|
|
7122
|
+
cmd.command("web").description("Open the backlog tab in the web dashboard").option("-p, --port <number>", "Port to listen on", "3100").option("--no-open", "Do not open a browser on startup").action(web2);
|
|
6912
7123
|
}
|
|
6913
7124
|
var registrars = [
|
|
6914
7125
|
registerItemCommands,
|
|
@@ -6929,9 +7140,9 @@ var registrars = [
|
|
|
6929
7140
|
registerMoveRepoCommand
|
|
6930
7141
|
];
|
|
6931
7142
|
function registerBacklog(program2) {
|
|
6932
|
-
const cmd = program2.command("backlog").description("Manage a backlog of work items").option("--dir <path>", "Override directory for backlog file discovery").hook("preAction", (thisCommand) => {
|
|
7143
|
+
const cmd = program2.command("backlog").description("Manage a backlog of work items").option("--dir <path>", "Override directory for backlog file discovery").option("--no-open", "Do not open a browser on startup").hook("preAction", (thisCommand) => {
|
|
6933
7144
|
setBacklogDir(thisCommand.opts().dir);
|
|
6934
|
-
}).action(() => web2({ port: "3100" }));
|
|
7145
|
+
}).action((options2) => web2({ port: "3100", open: options2.open }));
|
|
6935
7146
|
for (const register of registrars) {
|
|
6936
7147
|
register(cmd);
|
|
6937
7148
|
}
|
|
@@ -7384,7 +7595,7 @@ function matchesConfigDeny(command) {
|
|
|
7384
7595
|
var BUILTIN_DENIES = [
|
|
7385
7596
|
{
|
|
7386
7597
|
pattern: "gh pr create",
|
|
7387
|
-
message: "Do not run 'gh pr create' directly. Use 'assist prs
|
|
7598
|
+
message: "Do not run 'gh pr create' directly. Use 'assist prs raise --title <title> --what <what> --why <why>' instead \u2014 it assembles and validates the body before delegating to gh. Before running it, get explicit approval via the AskUserQuestion tool, regardless of permission mode, with the full proposed title and body in the approve option's preview field so the user actually sees them."
|
|
7388
7599
|
},
|
|
7389
7600
|
{
|
|
7390
7601
|
pattern: "git commit",
|
|
@@ -7553,7 +7764,7 @@ import { homedir as homedir9 } from "os";
|
|
|
7553
7764
|
import { join as join22 } from "path";
|
|
7554
7765
|
|
|
7555
7766
|
// src/shared/checkCliAvailable.ts
|
|
7556
|
-
import { execSync as
|
|
7767
|
+
import { execSync as execSync23 } from "child_process";
|
|
7557
7768
|
function checkCliAvailable(cli) {
|
|
7558
7769
|
const binary = cli.split(/\s+/)[0];
|
|
7559
7770
|
const opts = {
|
|
@@ -7561,11 +7772,11 @@ function checkCliAvailable(cli) {
|
|
|
7561
7772
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7562
7773
|
};
|
|
7563
7774
|
try {
|
|
7564
|
-
|
|
7775
|
+
execSync23(`command -v ${binary}`, opts);
|
|
7565
7776
|
return true;
|
|
7566
7777
|
} catch {
|
|
7567
7778
|
try {
|
|
7568
|
-
|
|
7779
|
+
execSync23(`where ${binary}`, opts);
|
|
7569
7780
|
return true;
|
|
7570
7781
|
} catch {
|
|
7571
7782
|
return false;
|
|
@@ -7665,10 +7876,10 @@ function hasSubcommands(helpText) {
|
|
|
7665
7876
|
}
|
|
7666
7877
|
|
|
7667
7878
|
// src/commands/permitCliReads/runHelp.ts
|
|
7668
|
-
import { exec as
|
|
7879
|
+
import { exec as exec2 } from "child_process";
|
|
7669
7880
|
function runHelp(args) {
|
|
7670
7881
|
return new Promise((resolve16) => {
|
|
7671
|
-
|
|
7882
|
+
exec2(
|
|
7672
7883
|
`${args.join(" ")} --help`,
|
|
7673
7884
|
{ encoding: "utf-8", timeout: 3e4 },
|
|
7674
7885
|
(_err, stdout, stderr) => {
|
|
@@ -8701,7 +8912,7 @@ function loadBlogSkipDays(repoName) {
|
|
|
8701
8912
|
}
|
|
8702
8913
|
|
|
8703
8914
|
// src/commands/devlog/shared.ts
|
|
8704
|
-
import { execSync as
|
|
8915
|
+
import { execSync as execSync24 } from "child_process";
|
|
8705
8916
|
import chalk92 from "chalk";
|
|
8706
8917
|
|
|
8707
8918
|
// src/shared/getRepoName.ts
|
|
@@ -8793,7 +9004,7 @@ function loadAllDevlogLatestDates() {
|
|
|
8793
9004
|
// src/commands/devlog/shared.ts
|
|
8794
9005
|
function getCommitFiles(hash) {
|
|
8795
9006
|
try {
|
|
8796
|
-
const output =
|
|
9007
|
+
const output = execSync24(`git show --name-only --format="" ${hash}`, {
|
|
8797
9008
|
encoding: "utf-8"
|
|
8798
9009
|
});
|
|
8799
9010
|
return output.trim().split("\n").filter(Boolean);
|
|
@@ -8889,11 +9100,11 @@ function list3(options2) {
|
|
|
8889
9100
|
}
|
|
8890
9101
|
|
|
8891
9102
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
8892
|
-
import { execFileSync as execFileSync2, execSync as
|
|
9103
|
+
import { execFileSync as execFileSync2, execSync as execSync25 } from "child_process";
|
|
8893
9104
|
import semver from "semver";
|
|
8894
9105
|
function getVersionAtCommit(hash) {
|
|
8895
9106
|
try {
|
|
8896
|
-
const content =
|
|
9107
|
+
const content = execSync25(`git show ${hash}:package.json`, {
|
|
8897
9108
|
encoding: "utf-8"
|
|
8898
9109
|
});
|
|
8899
9110
|
const pkg = JSON.parse(content);
|
|
@@ -9066,7 +9277,7 @@ function next2(options2) {
|
|
|
9066
9277
|
}
|
|
9067
9278
|
|
|
9068
9279
|
// src/commands/devlog/repos/index.ts
|
|
9069
|
-
import { execSync as
|
|
9280
|
+
import { execSync as execSync26 } from "child_process";
|
|
9070
9281
|
|
|
9071
9282
|
// src/commands/devlog/repos/printReposTable.ts
|
|
9072
9283
|
import chalk96 from "chalk";
|
|
@@ -9101,7 +9312,7 @@ function getStatus(lastPush, lastDevlog) {
|
|
|
9101
9312
|
return lastDevlog < lastPush ? "outdated" : "ok";
|
|
9102
9313
|
}
|
|
9103
9314
|
function fetchRepos(days, all) {
|
|
9104
|
-
const json =
|
|
9315
|
+
const json = execSync26(
|
|
9105
9316
|
"gh repo list staff0rd --json name,pushedAt,isArchived --limit 200",
|
|
9106
9317
|
{ encoding: "utf-8" }
|
|
9107
9318
|
);
|
|
@@ -9461,7 +9672,7 @@ async function deps(csprojPath, options2) {
|
|
|
9461
9672
|
}
|
|
9462
9673
|
|
|
9463
9674
|
// src/commands/dotnet/getChangedCsFiles.ts
|
|
9464
|
-
import { execSync as
|
|
9675
|
+
import { execSync as execSync27 } from "child_process";
|
|
9465
9676
|
var SCOPE_ALL = "all";
|
|
9466
9677
|
var SCOPE_BASE = "base:";
|
|
9467
9678
|
var SCOPE_COMMIT = "commit:";
|
|
@@ -9485,7 +9696,7 @@ function getChangedCsFiles(scope) {
|
|
|
9485
9696
|
} else {
|
|
9486
9697
|
cmd = "git diff --name-only HEAD";
|
|
9487
9698
|
}
|
|
9488
|
-
const output =
|
|
9699
|
+
const output = execSync27(cmd, { encoding: "utf-8" }).trim();
|
|
9489
9700
|
if (output === "") return [];
|
|
9490
9701
|
return output.split("\n").filter((f) => f.toLowerCase().endsWith(".cs"));
|
|
9491
9702
|
}
|
|
@@ -9683,14 +9894,14 @@ function parseInspectReport(json) {
|
|
|
9683
9894
|
}
|
|
9684
9895
|
|
|
9685
9896
|
// src/commands/dotnet/runInspectCode.ts
|
|
9686
|
-
import { execSync as
|
|
9897
|
+
import { execSync as execSync28 } from "child_process";
|
|
9687
9898
|
import { existsSync as existsSync30, readFileSync as readFileSync24, unlinkSync as unlinkSync7 } from "fs";
|
|
9688
9899
|
import { tmpdir as tmpdir3 } from "os";
|
|
9689
9900
|
import path25 from "path";
|
|
9690
9901
|
import chalk106 from "chalk";
|
|
9691
9902
|
function assertJbInstalled() {
|
|
9692
9903
|
try {
|
|
9693
|
-
|
|
9904
|
+
execSync28("jb inspectcode --version", { stdio: "pipe" });
|
|
9694
9905
|
} catch {
|
|
9695
9906
|
console.error(chalk106.red("jb is not installed. Install with:"));
|
|
9696
9907
|
console.error(
|
|
@@ -9704,7 +9915,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
9704
9915
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
9705
9916
|
const sweaFlag = swea ? " --swea" : "";
|
|
9706
9917
|
try {
|
|
9707
|
-
|
|
9918
|
+
execSync28(
|
|
9708
9919
|
`jb inspectcode "${slnPath}" -o="${reportPath}"${includeFlag}${sweaFlag} --verbosity=OFF`,
|
|
9709
9920
|
{ stdio: "pipe" }
|
|
9710
9921
|
);
|
|
@@ -9725,7 +9936,7 @@ function runInspectCode(slnPath, include, swea) {
|
|
|
9725
9936
|
}
|
|
9726
9937
|
|
|
9727
9938
|
// src/commands/dotnet/runRoslynInspect.ts
|
|
9728
|
-
import { execSync as
|
|
9939
|
+
import { execSync as execSync29 } from "child_process";
|
|
9729
9940
|
import chalk107 from "chalk";
|
|
9730
9941
|
function resolveMsbuildPath() {
|
|
9731
9942
|
const { run: run4 } = loadConfig();
|
|
@@ -9736,7 +9947,7 @@ function resolveMsbuildPath() {
|
|
|
9736
9947
|
function assertMsbuildInstalled() {
|
|
9737
9948
|
const msbuild = resolveMsbuildPath();
|
|
9738
9949
|
try {
|
|
9739
|
-
|
|
9950
|
+
execSync29(`"${msbuild}" -version`, { stdio: "pipe" });
|
|
9740
9951
|
} catch {
|
|
9741
9952
|
console.error(chalk107.red(`msbuild not found at: ${msbuild}`));
|
|
9742
9953
|
console.error(
|
|
@@ -9762,7 +9973,7 @@ function runRoslynInspect(slnPath) {
|
|
|
9762
9973
|
const msbuild = resolveMsbuildPath();
|
|
9763
9974
|
let output;
|
|
9764
9975
|
try {
|
|
9765
|
-
output =
|
|
9976
|
+
output = execSync29(
|
|
9766
9977
|
`"${msbuild}" "${slnPath}" -t:Build -v:minimal -maxcpucount -p:EnforceCodeStyleInBuild=true -p:RunAnalyzersDuringBuild=true 2>&1`,
|
|
9767
9978
|
{ encoding: "utf-8", stdio: "pipe", maxBuffer: 50 * 1024 * 1024 }
|
|
9768
9979
|
);
|
|
@@ -10340,12 +10551,12 @@ function adfToText(doc) {
|
|
|
10340
10551
|
}
|
|
10341
10552
|
|
|
10342
10553
|
// src/commands/jira/fetchIssue.ts
|
|
10343
|
-
import { execSync as
|
|
10554
|
+
import { execSync as execSync30 } from "child_process";
|
|
10344
10555
|
import chalk111 from "chalk";
|
|
10345
10556
|
function fetchIssue(issueKey, fields) {
|
|
10346
10557
|
let result;
|
|
10347
10558
|
try {
|
|
10348
|
-
result =
|
|
10559
|
+
result = execSync30(
|
|
10349
10560
|
`acli jira workitem view ${issueKey} -f ${fields} --json`,
|
|
10350
10561
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
10351
10562
|
);
|
|
@@ -10391,7 +10602,7 @@ function acceptanceCriteria(issueKey) {
|
|
|
10391
10602
|
}
|
|
10392
10603
|
|
|
10393
10604
|
// src/commands/jira/jiraAuth.ts
|
|
10394
|
-
import { execSync as
|
|
10605
|
+
import { execSync as execSync31 } from "child_process";
|
|
10395
10606
|
|
|
10396
10607
|
// src/shared/loadJson.ts
|
|
10397
10608
|
import { existsSync as existsSync33, mkdirSync as mkdirSync11, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
|
|
@@ -10455,7 +10666,7 @@ async function jiraAuth() {
|
|
|
10455
10666
|
console.error("All fields are required.");
|
|
10456
10667
|
process.exit(1);
|
|
10457
10668
|
}
|
|
10458
|
-
|
|
10669
|
+
execSync31(`acli jira auth login --site ${site} --email "${email}" --token`, {
|
|
10459
10670
|
encoding: "utf-8",
|
|
10460
10671
|
input: token,
|
|
10461
10672
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -10680,238 +10891,49 @@ async function add2(url) {
|
|
|
10680
10891
|
});
|
|
10681
10892
|
url = response.url;
|
|
10682
10893
|
}
|
|
10683
|
-
const
|
|
10684
|
-
const
|
|
10685
|
-
|
|
10686
|
-
|
|
10687
|
-
console.log(chalk118.yellow("Feed already exists in config"));
|
|
10894
|
+
const { orm } = await getReady();
|
|
10895
|
+
const added = await addFeed(orm, url);
|
|
10896
|
+
if (!added) {
|
|
10897
|
+
console.log(chalk118.yellow("Feed already exists"));
|
|
10688
10898
|
return;
|
|
10689
10899
|
}
|
|
10690
|
-
feeds.push(url);
|
|
10691
|
-
config.news = { ...news, feeds };
|
|
10692
|
-
saveGlobalConfig(config);
|
|
10693
10900
|
console.log(chalk118.green(`Added feed: ${url}`));
|
|
10694
10901
|
}
|
|
10695
10902
|
|
|
10696
|
-
// src/commands/
|
|
10697
|
-
|
|
10903
|
+
// src/commands/registerNews.ts
|
|
10904
|
+
function registerNews(program2) {
|
|
10905
|
+
const newsCommand = program2.command("news").description("Manage RSS news feeds");
|
|
10906
|
+
newsCommand.command("add").description("Add an RSS feed URL").argument("<url>", "RSS feed URL").action(add2);
|
|
10907
|
+
}
|
|
10698
10908
|
|
|
10699
|
-
// src/commands/
|
|
10700
|
-
import
|
|
10701
|
-
function
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
);
|
|
10705
|
-
if (cdataMatch) return cdataMatch[1].trim();
|
|
10706
|
-
const match = xml.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`));
|
|
10707
|
-
return match ? match[1].trim() : "";
|
|
10909
|
+
// src/commands/prompts/printPromptsTable.ts
|
|
10910
|
+
import chalk119 from "chalk";
|
|
10911
|
+
function truncate(str, max) {
|
|
10912
|
+
if (str.length <= max) return str;
|
|
10913
|
+
return `${str.slice(0, max - 1)}\u2026`;
|
|
10708
10914
|
}
|
|
10709
|
-
function
|
|
10710
|
-
const
|
|
10711
|
-
|
|
10915
|
+
function printPromptsTable(rows) {
|
|
10916
|
+
const countWidth = 5;
|
|
10917
|
+
const toolWidth = Math.max(4, ...rows.map((r) => r.tool.length));
|
|
10918
|
+
const commandWidth = Math.max(
|
|
10919
|
+
7,
|
|
10920
|
+
...rows.map((r) => truncate(r.command, 60).length)
|
|
10712
10921
|
);
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
const stripped = decoded.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
10729
|
-
return decodeHTML(stripped);
|
|
10730
|
-
}
|
|
10731
|
-
function matchAll(xml, regex) {
|
|
10732
|
-
const results = [];
|
|
10733
|
-
for (const m of xml.matchAll(regex)) {
|
|
10734
|
-
results.push(m[1]);
|
|
10735
|
-
}
|
|
10736
|
-
return results;
|
|
10737
|
-
}
|
|
10738
|
-
var MAX_EXCERPT = 500;
|
|
10739
|
-
function excerpt(xml, ...tags) {
|
|
10740
|
-
for (const tag of tags) {
|
|
10741
|
-
const raw = extractText(xml, tag);
|
|
10742
|
-
if (!raw) continue;
|
|
10743
|
-
const text3 = stripHtml(raw);
|
|
10744
|
-
if (text3.length <= MAX_EXCERPT) return text3;
|
|
10745
|
-
return `${text3.slice(0, MAX_EXCERPT)}\u2026`;
|
|
10746
|
-
}
|
|
10747
|
-
return "";
|
|
10748
|
-
}
|
|
10749
|
-
|
|
10750
|
-
// src/commands/news/web/parseFeed.ts
|
|
10751
|
-
function parseRss(xml, feedOrigin) {
|
|
10752
|
-
const feedTitle = extractText(xml, "title");
|
|
10753
|
-
return matchAll(xml, /<item[\s>]([\s\S]*?)<\/item>/g).map((itemXml) => ({
|
|
10754
|
-
title: extractText(itemXml, "title"),
|
|
10755
|
-
link: extractLink(itemXml),
|
|
10756
|
-
pubDate: parseDate(
|
|
10757
|
-
extractText(itemXml, "pubDate") || extractText(itemXml, "dc:date")
|
|
10758
|
-
),
|
|
10759
|
-
feedTitle,
|
|
10760
|
-
feedOrigin,
|
|
10761
|
-
excerpt: excerpt(itemXml, "description", "content:encoded")
|
|
10762
|
-
}));
|
|
10763
|
-
}
|
|
10764
|
-
function parseAtom(xml, feedOrigin) {
|
|
10765
|
-
const feedTitle = extractText(xml, "title");
|
|
10766
|
-
return matchAll(xml, /<entry[\s>]([\s\S]*?)<\/entry>/g).map((entryXml) => ({
|
|
10767
|
-
title: extractText(entryXml, "title"),
|
|
10768
|
-
link: extractLink(entryXml),
|
|
10769
|
-
pubDate: parseDate(
|
|
10770
|
-
extractText(entryXml, "published") || extractText(entryXml, "updated")
|
|
10771
|
-
),
|
|
10772
|
-
feedTitle,
|
|
10773
|
-
feedOrigin,
|
|
10774
|
-
excerpt: excerpt(entryXml, "summary", "content")
|
|
10775
|
-
}));
|
|
10776
|
-
}
|
|
10777
|
-
function parseFeed(xml, feedOrigin) {
|
|
10778
|
-
if (xml.includes("<feed")) return parseAtom(xml, feedOrigin);
|
|
10779
|
-
return parseRss(xml, feedOrigin);
|
|
10780
|
-
}
|
|
10781
|
-
|
|
10782
|
-
// src/commands/news/web/fetchFeeds.ts
|
|
10783
|
-
async function fetchFeeds(urls, onProgress) {
|
|
10784
|
-
let done2 = 0;
|
|
10785
|
-
const results = await Promise.allSettled(
|
|
10786
|
-
urls.map(async (url) => {
|
|
10787
|
-
const origin = new URL(url).origin;
|
|
10788
|
-
const res = await fetch(url);
|
|
10789
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
10790
|
-
const items3 = parseFeed(await res.text(), origin);
|
|
10791
|
-
done2++;
|
|
10792
|
-
onProgress?.(done2, urls.length);
|
|
10793
|
-
return items3;
|
|
10794
|
-
})
|
|
10795
|
-
);
|
|
10796
|
-
const items2 = [];
|
|
10797
|
-
for (const result of results) {
|
|
10798
|
-
if (result.status === "fulfilled") {
|
|
10799
|
-
items2.push(...result.value);
|
|
10800
|
-
}
|
|
10801
|
-
}
|
|
10802
|
-
items2.sort(
|
|
10803
|
-
(a, b) => new Date(b.pubDate).getTime() - new Date(a.pubDate).getTime()
|
|
10804
|
-
);
|
|
10805
|
-
return items2;
|
|
10806
|
-
}
|
|
10807
|
-
|
|
10808
|
-
// src/commands/news/web/getHtml.ts
|
|
10809
|
-
function getHtml2() {
|
|
10810
|
-
return `<!DOCTYPE html>
|
|
10811
|
-
<html lang="en" class="dark">
|
|
10812
|
-
<head>
|
|
10813
|
-
<meta charset="UTF-8">
|
|
10814
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
10815
|
-
<title>News</title>
|
|
10816
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
|
10817
|
-
<script>tailwind.config={darkMode:'class'}</script>
|
|
10818
|
-
</head>
|
|
10819
|
-
<body class="font-[-apple-system,BlinkMacSystemFont,'Segoe_UI',Roboto,sans-serif] bg-gray-950 text-gray-200 leading-normal">
|
|
10820
|
-
<div class="max-w-3xl mx-auto px-4 py-6" id="app"></div>
|
|
10821
|
-
<script src="/bundle.js"></script>
|
|
10822
|
-
</body>
|
|
10823
|
-
</html>`;
|
|
10824
|
-
}
|
|
10825
|
-
|
|
10826
|
-
// src/commands/news/web/handleRequest.ts
|
|
10827
|
-
var cachedItems;
|
|
10828
|
-
var prefetchPromise;
|
|
10829
|
-
function prefetch() {
|
|
10830
|
-
const config = loadConfig();
|
|
10831
|
-
const total = config.news.feeds.length;
|
|
10832
|
-
if (total === 0) return;
|
|
10833
|
-
process.stdout.write(chalk119.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
10834
|
-
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
10835
|
-
const width = 20;
|
|
10836
|
-
const filled = Math.round(done2 / t * width);
|
|
10837
|
-
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
10838
|
-
process.stdout.write(
|
|
10839
|
-
`\r${chalk119.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
10840
|
-
);
|
|
10841
|
-
}).then((items2) => {
|
|
10842
|
-
process.stdout.write(
|
|
10843
|
-
`\r${chalk119.green(`Fetched ${items2.length} items from ${total} feed(s)`)}
|
|
10844
|
-
`
|
|
10845
|
-
);
|
|
10846
|
-
cachedItems = items2;
|
|
10847
|
-
return items2;
|
|
10848
|
-
});
|
|
10849
|
-
}
|
|
10850
|
-
async function listItems2(_req, res) {
|
|
10851
|
-
if (!cachedItems && prefetchPromise) {
|
|
10852
|
-
await prefetchPromise;
|
|
10853
|
-
}
|
|
10854
|
-
if (!cachedItems) {
|
|
10855
|
-
const config = loadConfig();
|
|
10856
|
-
cachedItems = await fetchFeeds(config.news.feeds);
|
|
10857
|
-
}
|
|
10858
|
-
respondJson(res, 200, cachedItems);
|
|
10859
|
-
}
|
|
10860
|
-
var routes2 = {
|
|
10861
|
-
"GET /": createHtmlHandler(getHtml2),
|
|
10862
|
-
"GET /bundle.js": createBundleHandler(
|
|
10863
|
-
import.meta.url,
|
|
10864
|
-
"commands/news/web/bundle.js"
|
|
10865
|
-
),
|
|
10866
|
-
"GET /api/items": listItems2
|
|
10867
|
-
};
|
|
10868
|
-
var handleRequest2 = createRouteHandler(routes2);
|
|
10869
|
-
|
|
10870
|
-
// src/commands/news/web/index.ts
|
|
10871
|
-
async function web3(options2) {
|
|
10872
|
-
prefetch();
|
|
10873
|
-
startWebServer(
|
|
10874
|
-
"News web view",
|
|
10875
|
-
Number.parseInt(options2.port, 10),
|
|
10876
|
-
handleRequest2
|
|
10877
|
-
);
|
|
10878
|
-
}
|
|
10879
|
-
|
|
10880
|
-
// src/commands/registerNews.ts
|
|
10881
|
-
function registerNews(program2) {
|
|
10882
|
-
const newsCommand = program2.command("news").description("View latest news from configured RSS feeds").action(() => web3({ port: "3001" }));
|
|
10883
|
-
newsCommand.command("add").description("Add an RSS feed URL to the config").argument("<url>", "RSS feed URL").action(add2);
|
|
10884
|
-
newsCommand.command("web").description("Start a web view of the news feeds").option("-p, --port <number>", "Port to listen on", "3001").action(web3);
|
|
10885
|
-
}
|
|
10886
|
-
|
|
10887
|
-
// src/commands/prompts/printPromptsTable.ts
|
|
10888
|
-
import chalk120 from "chalk";
|
|
10889
|
-
function truncate(str, max) {
|
|
10890
|
-
if (str.length <= max) return str;
|
|
10891
|
-
return `${str.slice(0, max - 1)}\u2026`;
|
|
10892
|
-
}
|
|
10893
|
-
function printPromptsTable(rows) {
|
|
10894
|
-
const countWidth = 5;
|
|
10895
|
-
const toolWidth = Math.max(4, ...rows.map((r) => r.tool.length));
|
|
10896
|
-
const commandWidth = Math.max(
|
|
10897
|
-
7,
|
|
10898
|
-
...rows.map((r) => truncate(r.command, 60).length)
|
|
10899
|
-
);
|
|
10900
|
-
const header = [
|
|
10901
|
-
"#".padStart(countWidth),
|
|
10902
|
-
"Tool".padEnd(toolWidth),
|
|
10903
|
-
"Command".padEnd(commandWidth),
|
|
10904
|
-
"Repos"
|
|
10905
|
-
].join(" ");
|
|
10906
|
-
console.log(chalk120.dim(header));
|
|
10907
|
-
console.log(chalk120.dim("-".repeat(header.length)));
|
|
10908
|
-
for (const row of rows) {
|
|
10909
|
-
const count6 = String(row.count).padStart(countWidth);
|
|
10910
|
-
const tool = row.tool.padEnd(toolWidth);
|
|
10911
|
-
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
10912
|
-
console.log(
|
|
10913
|
-
`${chalk120.yellow(count6)} ${tool} ${command} ${chalk120.dim(row.repos)}`
|
|
10914
|
-
);
|
|
10922
|
+
const header = [
|
|
10923
|
+
"#".padStart(countWidth),
|
|
10924
|
+
"Tool".padEnd(toolWidth),
|
|
10925
|
+
"Command".padEnd(commandWidth),
|
|
10926
|
+
"Repos"
|
|
10927
|
+
].join(" ");
|
|
10928
|
+
console.log(chalk119.dim(header));
|
|
10929
|
+
console.log(chalk119.dim("-".repeat(header.length)));
|
|
10930
|
+
for (const row of rows) {
|
|
10931
|
+
const count6 = String(row.count).padStart(countWidth);
|
|
10932
|
+
const tool = row.tool.padEnd(toolWidth);
|
|
10933
|
+
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
10934
|
+
console.log(
|
|
10935
|
+
`${chalk119.yellow(count6)} ${tool} ${command} ${chalk119.dim(row.repos)}`
|
|
10936
|
+
);
|
|
10915
10937
|
}
|
|
10916
10938
|
}
|
|
10917
10939
|
|
|
@@ -10939,7 +10961,7 @@ function registerPrompts(program2) {
|
|
|
10939
10961
|
}
|
|
10940
10962
|
|
|
10941
10963
|
// src/commands/prs/shared.ts
|
|
10942
|
-
import { execSync as
|
|
10964
|
+
import { execSync as execSync32 } from "child_process";
|
|
10943
10965
|
function isGhNotInstalled(error) {
|
|
10944
10966
|
if (error instanceof Error) {
|
|
10945
10967
|
const msg = error.message.toLowerCase();
|
|
@@ -10957,12 +10979,12 @@ function getRepoInfo() {
|
|
|
10957
10979
|
const preferred = getPreferredRemoteRepo();
|
|
10958
10980
|
if (preferred) return preferred;
|
|
10959
10981
|
const repoInfo = JSON.parse(
|
|
10960
|
-
|
|
10982
|
+
execSync32("gh repo view --json owner,name", { encoding: "utf-8" })
|
|
10961
10983
|
);
|
|
10962
10984
|
return { org: repoInfo.owner.login, repo: repoInfo.name };
|
|
10963
10985
|
}
|
|
10964
10986
|
function getCurrentBranch() {
|
|
10965
|
-
return
|
|
10987
|
+
return execSync32("git rev-parse --abbrev-ref HEAD", {
|
|
10966
10988
|
encoding: "utf-8"
|
|
10967
10989
|
}).trim();
|
|
10968
10990
|
}
|
|
@@ -10970,7 +10992,7 @@ function viewCurrentPr(fields) {
|
|
|
10970
10992
|
const { org, repo } = getRepoInfo();
|
|
10971
10993
|
const branch = getCurrentBranch();
|
|
10972
10994
|
return JSON.parse(
|
|
10973
|
-
|
|
10995
|
+
execSync32(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
|
|
10974
10996
|
encoding: "utf-8"
|
|
10975
10997
|
})
|
|
10976
10998
|
);
|
|
@@ -10986,6 +11008,17 @@ function getCurrentPrNumber() {
|
|
|
10986
11008
|
throw error;
|
|
10987
11009
|
}
|
|
10988
11010
|
}
|
|
11011
|
+
function getCurrentPr() {
|
|
11012
|
+
try {
|
|
11013
|
+
return viewCurrentPr("number,body");
|
|
11014
|
+
} catch (error) {
|
|
11015
|
+
if (error instanceof Error && error.message.includes("no pull requests")) {
|
|
11016
|
+
console.error("Error: No pull request found for the current branch.");
|
|
11017
|
+
process.exit(1);
|
|
11018
|
+
}
|
|
11019
|
+
throw error;
|
|
11020
|
+
}
|
|
11021
|
+
}
|
|
10989
11022
|
function getCurrentPrNodeId() {
|
|
10990
11023
|
try {
|
|
10991
11024
|
return viewCurrentPr("id").id;
|
|
@@ -11062,37 +11095,102 @@ function comment2(path54, line, body, startLine) {
|
|
|
11062
11095
|
}
|
|
11063
11096
|
}
|
|
11064
11097
|
|
|
11065
|
-
// src/commands/prs/
|
|
11066
|
-
import { execSync as
|
|
11098
|
+
// src/commands/prs/edit.ts
|
|
11099
|
+
import { execSync as execSync33 } from "child_process";
|
|
11067
11100
|
|
|
11068
|
-
// src/commands/prs/
|
|
11069
|
-
function
|
|
11070
|
-
const
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
];
|
|
11080
|
-
for (const [flag, value] of valueFlags) {
|
|
11081
|
-
if (value) args.push(`${flag} ${shellQuote(value)}`);
|
|
11101
|
+
// src/commands/prs/buildPrBody.ts
|
|
11102
|
+
function jiraBrowseUrl(key) {
|
|
11103
|
+
const { site } = loadJson("jira.json");
|
|
11104
|
+
return site ? `https://${site}/browse/${key}` : key;
|
|
11105
|
+
}
|
|
11106
|
+
function renderWhy(why, resolves) {
|
|
11107
|
+
if (resolves && resolves.length > 0) {
|
|
11108
|
+
const urls = resolves.map(jiraBrowseUrl).join(", ");
|
|
11109
|
+
return `${why}
|
|
11110
|
+
|
|
11111
|
+
Resolves ${urls}`;
|
|
11082
11112
|
}
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11113
|
+
return why;
|
|
11114
|
+
}
|
|
11115
|
+
function buildPrBody(sections) {
|
|
11116
|
+
const parts = [
|
|
11117
|
+
`## What
|
|
11118
|
+
|
|
11119
|
+
${sections.what}`,
|
|
11120
|
+
`## Why
|
|
11121
|
+
|
|
11122
|
+
${renderWhy(sections.why, sections.resolves)}`
|
|
11089
11123
|
];
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11124
|
+
if (sections.how) {
|
|
11125
|
+
parts.push(`## How
|
|
11126
|
+
|
|
11127
|
+
${sections.how}`);
|
|
11128
|
+
}
|
|
11129
|
+
return parts.join("\n\n");
|
|
11130
|
+
}
|
|
11131
|
+
|
|
11132
|
+
// src/commands/prs/parsePrBody.ts
|
|
11133
|
+
function parsePrBody(body) {
|
|
11134
|
+
const sections = [];
|
|
11135
|
+
let current = null;
|
|
11136
|
+
const flush = () => {
|
|
11137
|
+
if (current) {
|
|
11138
|
+
sections.push({
|
|
11139
|
+
heading: current.heading,
|
|
11140
|
+
content: current.lines.join("\n").trim()
|
|
11141
|
+
});
|
|
11142
|
+
}
|
|
11143
|
+
};
|
|
11144
|
+
for (const line of body.split("\n")) {
|
|
11145
|
+
const match = /^##\s+(.+?)\s*$/.exec(line);
|
|
11146
|
+
if (match) {
|
|
11147
|
+
flush();
|
|
11148
|
+
current = { heading: match[1], lines: [] };
|
|
11149
|
+
} else if (current) {
|
|
11150
|
+
current.lines.push(line);
|
|
11093
11151
|
}
|
|
11094
11152
|
}
|
|
11095
|
-
|
|
11153
|
+
flush();
|
|
11154
|
+
return sections;
|
|
11155
|
+
}
|
|
11156
|
+
function serializePrBody(sections) {
|
|
11157
|
+
return sections.map((section2) => `## ${section2.heading}
|
|
11158
|
+
|
|
11159
|
+
${section2.content}`).join("\n\n");
|
|
11160
|
+
}
|
|
11161
|
+
|
|
11162
|
+
// src/commands/prs/editPrBody.ts
|
|
11163
|
+
function stripResolves(content) {
|
|
11164
|
+
return content.replace(/\n+Resolves [^\n]*$/, "").trimEnd();
|
|
11165
|
+
}
|
|
11166
|
+
function extractResolves(content) {
|
|
11167
|
+
const match = /\n+(Resolves [^\n]*)$/.exec(content);
|
|
11168
|
+
return match ? match[1] : "";
|
|
11169
|
+
}
|
|
11170
|
+
function editPrBody(body, sections) {
|
|
11171
|
+
const parsed = parsePrBody(body);
|
|
11172
|
+
const find = (heading) => parsed.find((s) => s.heading.toLowerCase() === heading.toLowerCase());
|
|
11173
|
+
const upsert = (heading, content) => {
|
|
11174
|
+
const existing = find(heading);
|
|
11175
|
+
if (existing) existing.content = content;
|
|
11176
|
+
else parsed.push({ heading, content });
|
|
11177
|
+
};
|
|
11178
|
+
if (sections.what !== void 0) upsert("What", sections.what);
|
|
11179
|
+
const hasResolves = (sections.resolves?.length ?? 0) > 0;
|
|
11180
|
+
if (sections.why !== void 0 || hasResolves) {
|
|
11181
|
+
const existingWhy = find("Why")?.content ?? "";
|
|
11182
|
+
const baseWhy = sections.why !== void 0 ? sections.why : stripResolves(existingWhy);
|
|
11183
|
+
if (hasResolves) {
|
|
11184
|
+
upsert("Why", renderWhy(baseWhy, sections.resolves));
|
|
11185
|
+
} else {
|
|
11186
|
+
const resolves = extractResolves(existingWhy);
|
|
11187
|
+
upsert("Why", resolves ? `${baseWhy}
|
|
11188
|
+
|
|
11189
|
+
${resolves}` : baseWhy);
|
|
11190
|
+
}
|
|
11191
|
+
}
|
|
11192
|
+
if (sections.how !== void 0) upsert("How", sections.how);
|
|
11193
|
+
return serializePrBody(parsed);
|
|
11096
11194
|
}
|
|
11097
11195
|
|
|
11098
11196
|
// src/commands/prs/validatePrContent.ts
|
|
@@ -11107,28 +11205,34 @@ function validatePrContent(title, body) {
|
|
|
11107
11205
|
}
|
|
11108
11206
|
}
|
|
11109
11207
|
|
|
11110
|
-
// src/commands/prs/
|
|
11111
|
-
function
|
|
11112
|
-
|
|
11208
|
+
// src/commands/prs/edit.ts
|
|
11209
|
+
function edit(options2) {
|
|
11210
|
+
const hasResolves = (options2.resolves?.length ?? 0) > 0;
|
|
11211
|
+
const hasSection = options2.what !== void 0 || options2.why !== void 0 || options2.how !== void 0 || hasResolves;
|
|
11212
|
+
if (!options2.title && !hasSection) {
|
|
11113
11213
|
console.error(
|
|
11114
|
-
"Usage: assist prs
|
|
11214
|
+
"Usage: assist prs edit [--title <title>] [--what <what>] [--why <why>] [--how <how>] [--resolves <key>]"
|
|
11115
11215
|
);
|
|
11116
11216
|
process.exit(1);
|
|
11117
11217
|
}
|
|
11118
|
-
|
|
11119
|
-
const
|
|
11218
|
+
const { number, body } = getCurrentPr();
|
|
11219
|
+
const newBody = editPrBody(body, options2);
|
|
11220
|
+
validatePrContent(options2.title ?? "", newBody);
|
|
11221
|
+
const args = [`gh pr edit ${number}`];
|
|
11222
|
+
if (options2.title) args.push(`--title ${shellQuote(options2.title)}`);
|
|
11223
|
+
args.push(`--body ${shellQuote(newBody)}`);
|
|
11120
11224
|
try {
|
|
11121
|
-
|
|
11225
|
+
execSync33(args.join(" "), { stdio: "inherit" });
|
|
11122
11226
|
} catch (_error) {
|
|
11123
11227
|
process.exit(1);
|
|
11124
11228
|
}
|
|
11125
11229
|
}
|
|
11126
11230
|
|
|
11127
11231
|
// src/commands/prs/fixed.ts
|
|
11128
|
-
import { execSync as
|
|
11232
|
+
import { execSync as execSync35 } from "child_process";
|
|
11129
11233
|
|
|
11130
11234
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
11131
|
-
import { execSync as
|
|
11235
|
+
import { execSync as execSync34 } from "child_process";
|
|
11132
11236
|
import { unlinkSync as unlinkSync10, writeFileSync as writeFileSync23 } from "fs";
|
|
11133
11237
|
import { tmpdir as tmpdir5 } from "os";
|
|
11134
11238
|
import { join as join34 } from "path";
|
|
@@ -11158,7 +11262,7 @@ function deleteCommentsCache(prNumber) {
|
|
|
11158
11262
|
|
|
11159
11263
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
11160
11264
|
function replyToComment(org, repo, prNumber, commentId, message) {
|
|
11161
|
-
|
|
11265
|
+
execSync34(
|
|
11162
11266
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message.replace(/"/g, '\\"')}" -F in_reply_to=${commentId}`,
|
|
11163
11267
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
11164
11268
|
);
|
|
@@ -11168,7 +11272,7 @@ function resolveThread(threadId) {
|
|
|
11168
11272
|
const queryFile = join34(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
|
|
11169
11273
|
writeFileSync23(queryFile, mutation);
|
|
11170
11274
|
try {
|
|
11171
|
-
|
|
11275
|
+
execSync34(
|
|
11172
11276
|
`gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
|
|
11173
11277
|
{ stdio: ["inherit", "pipe", "inherit"] }
|
|
11174
11278
|
);
|
|
@@ -11220,7 +11324,7 @@ function resolveCommentWithReply(commentId, message) {
|
|
|
11220
11324
|
// src/commands/prs/fixed.ts
|
|
11221
11325
|
function verifySha(sha) {
|
|
11222
11326
|
try {
|
|
11223
|
-
return
|
|
11327
|
+
return execSync35(`git rev-parse --verify ${sha}`, {
|
|
11224
11328
|
encoding: "utf-8"
|
|
11225
11329
|
}).trim();
|
|
11226
11330
|
} catch {
|
|
@@ -11234,7 +11338,7 @@ function fixed(commentId, sha) {
|
|
|
11234
11338
|
const { org, repo } = getRepoInfo();
|
|
11235
11339
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
11236
11340
|
const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
11237
|
-
|
|
11341
|
+
execSync35("git push", { stdio: "inherit" });
|
|
11238
11342
|
resolveCommentWithReply(commentId, message);
|
|
11239
11343
|
} catch (error) {
|
|
11240
11344
|
if (isGhNotInstalled(error)) {
|
|
@@ -11252,7 +11356,7 @@ import { join as join36 } from "path";
|
|
|
11252
11356
|
import { stringify } from "yaml";
|
|
11253
11357
|
|
|
11254
11358
|
// src/commands/prs/fetchThreadIds.ts
|
|
11255
|
-
import { execSync as
|
|
11359
|
+
import { execSync as execSync36 } from "child_process";
|
|
11256
11360
|
import { unlinkSync as unlinkSync11, writeFileSync as writeFileSync24 } from "fs";
|
|
11257
11361
|
import { tmpdir as tmpdir6 } from "os";
|
|
11258
11362
|
import { join as join35 } from "path";
|
|
@@ -11261,7 +11365,7 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
11261
11365
|
const queryFile = join35(tmpdir6(), `gh-query-${Date.now()}.graphql`);
|
|
11262
11366
|
writeFileSync24(queryFile, THREAD_QUERY);
|
|
11263
11367
|
try {
|
|
11264
|
-
const result =
|
|
11368
|
+
const result = execSync36(
|
|
11265
11369
|
`gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
|
|
11266
11370
|
{ encoding: "utf-8" }
|
|
11267
11371
|
);
|
|
@@ -11283,9 +11387,9 @@ function fetchThreadIds(org, repo, prNumber) {
|
|
|
11283
11387
|
}
|
|
11284
11388
|
|
|
11285
11389
|
// src/commands/prs/listComments/fetchReviewComments.ts
|
|
11286
|
-
import { execSync as
|
|
11390
|
+
import { execSync as execSync37 } from "child_process";
|
|
11287
11391
|
function fetchJson(endpoint) {
|
|
11288
|
-
const result =
|
|
11392
|
+
const result = execSync37(`gh api --paginate ${endpoint}`, {
|
|
11289
11393
|
encoding: "utf-8"
|
|
11290
11394
|
});
|
|
11291
11395
|
if (!result.trim()) return [];
|
|
@@ -11327,20 +11431,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
11327
11431
|
}
|
|
11328
11432
|
|
|
11329
11433
|
// src/commands/prs/listComments/printComments.ts
|
|
11330
|
-
import
|
|
11434
|
+
import chalk120 from "chalk";
|
|
11331
11435
|
function formatForHuman(comment3) {
|
|
11332
11436
|
if (comment3.type === "review") {
|
|
11333
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
11437
|
+
const stateColor = comment3.state === "APPROVED" ? chalk120.green : comment3.state === "CHANGES_REQUESTED" ? chalk120.red : chalk120.yellow;
|
|
11334
11438
|
return [
|
|
11335
|
-
`${
|
|
11439
|
+
`${chalk120.cyan("Review")} by ${chalk120.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
11336
11440
|
comment3.body,
|
|
11337
11441
|
""
|
|
11338
11442
|
].join("\n");
|
|
11339
11443
|
}
|
|
11340
11444
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
11341
11445
|
return [
|
|
11342
|
-
`${
|
|
11343
|
-
|
|
11446
|
+
`${chalk120.cyan("Line comment")} by ${chalk120.bold(comment3.user)} on ${chalk120.dim(`${comment3.path}${location}`)}`,
|
|
11447
|
+
chalk120.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
11344
11448
|
comment3.body,
|
|
11345
11449
|
""
|
|
11346
11450
|
].join("\n");
|
|
@@ -11424,19 +11528,19 @@ async function listComments() {
|
|
|
11424
11528
|
}
|
|
11425
11529
|
|
|
11426
11530
|
// src/commands/prs/prs/index.ts
|
|
11427
|
-
import { execSync as
|
|
11531
|
+
import { execSync as execSync38 } from "child_process";
|
|
11428
11532
|
|
|
11429
11533
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
11430
11534
|
import enquirer9 from "enquirer";
|
|
11431
11535
|
|
|
11432
11536
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
11433
|
-
import
|
|
11537
|
+
import chalk121 from "chalk";
|
|
11434
11538
|
var STATUS_MAP = {
|
|
11435
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
11436
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
11539
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk121.magenta("merged"), date: pr.mergedAt } : null,
|
|
11540
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk121.red("closed"), date: pr.closedAt } : null
|
|
11437
11541
|
};
|
|
11438
11542
|
function defaultStatus(pr) {
|
|
11439
|
-
return { label:
|
|
11543
|
+
return { label: chalk121.green("opened"), date: pr.createdAt };
|
|
11440
11544
|
}
|
|
11441
11545
|
function getStatus2(pr) {
|
|
11442
11546
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -11445,11 +11549,11 @@ function formatDate(dateStr) {
|
|
|
11445
11549
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
11446
11550
|
}
|
|
11447
11551
|
function formatPrHeader(pr, status2) {
|
|
11448
|
-
return `${
|
|
11552
|
+
return `${chalk121.cyan(`#${pr.number}`)} ${pr.title} ${chalk121.dim(`(${pr.author.login},`)} ${status2.label} ${chalk121.dim(`${formatDate(status2.date)})`)}`;
|
|
11449
11553
|
}
|
|
11450
11554
|
function logPrDetails(pr) {
|
|
11451
11555
|
console.log(
|
|
11452
|
-
|
|
11556
|
+
chalk121.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
11453
11557
|
);
|
|
11454
11558
|
console.log();
|
|
11455
11559
|
}
|
|
@@ -11531,7 +11635,7 @@ async function prs(options2) {
|
|
|
11531
11635
|
const state = options2.open ? "open" : options2.closed ? "closed" : "all";
|
|
11532
11636
|
try {
|
|
11533
11637
|
const { org, repo } = getRepoInfo();
|
|
11534
|
-
const result =
|
|
11638
|
+
const result = execSync38(
|
|
11535
11639
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
|
|
11536
11640
|
{ encoding: "utf-8" }
|
|
11537
11641
|
);
|
|
@@ -11553,8 +11657,75 @@ async function prs(options2) {
|
|
|
11553
11657
|
}
|
|
11554
11658
|
}
|
|
11555
11659
|
|
|
11660
|
+
// src/commands/prs/raise.ts
|
|
11661
|
+
import { execSync as execSync39 } from "child_process";
|
|
11662
|
+
|
|
11663
|
+
// src/commands/prs/buildCreateArgs.ts
|
|
11664
|
+
function buildCreateArgs(title, body, options2) {
|
|
11665
|
+
const args = [
|
|
11666
|
+
"gh pr create",
|
|
11667
|
+
`--title ${shellQuote(title)}`,
|
|
11668
|
+
`--body ${shellQuote(body)}`
|
|
11669
|
+
];
|
|
11670
|
+
const valueFlags = [
|
|
11671
|
+
["--base", options2.base],
|
|
11672
|
+
["--head", options2.head],
|
|
11673
|
+
["--milestone", options2.milestone]
|
|
11674
|
+
];
|
|
11675
|
+
for (const [flag, value] of valueFlags) {
|
|
11676
|
+
if (value) args.push(`${flag} ${shellQuote(value)}`);
|
|
11677
|
+
}
|
|
11678
|
+
if (options2.draft) args.push("--draft");
|
|
11679
|
+
if (options2.web) args.push("--web");
|
|
11680
|
+
const repeatableFlags = [
|
|
11681
|
+
["--label", options2.label],
|
|
11682
|
+
["--assignee", options2.assignee],
|
|
11683
|
+
["--reviewer", options2.reviewer]
|
|
11684
|
+
];
|
|
11685
|
+
for (const [flag, values] of repeatableFlags) {
|
|
11686
|
+
for (const value of values ?? []) {
|
|
11687
|
+
args.push(`${flag} ${shellQuote(value)}`);
|
|
11688
|
+
}
|
|
11689
|
+
}
|
|
11690
|
+
return args;
|
|
11691
|
+
}
|
|
11692
|
+
|
|
11693
|
+
// src/commands/prs/raise.ts
|
|
11694
|
+
function raise(options2) {
|
|
11695
|
+
if (!options2.title || !options2.what || !options2.why) {
|
|
11696
|
+
console.error(
|
|
11697
|
+
"Usage: assist prs raise --title <title> --what <what> --why <why> [--how <how>] [--resolves <key>] [--force]"
|
|
11698
|
+
);
|
|
11699
|
+
process.exit(1);
|
|
11700
|
+
}
|
|
11701
|
+
const body = buildPrBody({
|
|
11702
|
+
what: options2.what,
|
|
11703
|
+
why: options2.why,
|
|
11704
|
+
how: options2.how,
|
|
11705
|
+
resolves: options2.resolves
|
|
11706
|
+
});
|
|
11707
|
+
validatePrContent(options2.title, body);
|
|
11708
|
+
const existing = findCurrentPrNumber();
|
|
11709
|
+
if (existing !== null && !options2.force) {
|
|
11710
|
+
console.error(
|
|
11711
|
+
`Error: A pull request already exists for this branch (#${existing}). Pass --force to overwrite it, or use 'assist prs edit' to update individual sections.`
|
|
11712
|
+
);
|
|
11713
|
+
process.exit(1);
|
|
11714
|
+
}
|
|
11715
|
+
const args = existing !== null ? [
|
|
11716
|
+
`gh pr edit ${existing}`,
|
|
11717
|
+
`--title ${shellQuote(options2.title)}`,
|
|
11718
|
+
`--body ${shellQuote(body)}`
|
|
11719
|
+
] : buildCreateArgs(options2.title, body, options2);
|
|
11720
|
+
try {
|
|
11721
|
+
execSync39(args.join(" "), { stdio: "inherit" });
|
|
11722
|
+
} catch (_error) {
|
|
11723
|
+
process.exit(1);
|
|
11724
|
+
}
|
|
11725
|
+
}
|
|
11726
|
+
|
|
11556
11727
|
// src/commands/prs/wontfix.ts
|
|
11557
|
-
import { execSync as
|
|
11728
|
+
import { execSync as execSync40 } from "child_process";
|
|
11558
11729
|
function validateReason(reason) {
|
|
11559
11730
|
const lowerReason = reason.toLowerCase();
|
|
11560
11731
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -11571,7 +11742,7 @@ function validateShaReferences(reason) {
|
|
|
11571
11742
|
const invalidShas = [];
|
|
11572
11743
|
for (const sha of shas) {
|
|
11573
11744
|
try {
|
|
11574
|
-
|
|
11745
|
+
execSync40(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
11575
11746
|
} catch {
|
|
11576
11747
|
invalidShas.push(sha);
|
|
11577
11748
|
}
|
|
@@ -11598,30 +11769,54 @@ function wontfix(commentId, reason) {
|
|
|
11598
11769
|
}
|
|
11599
11770
|
}
|
|
11600
11771
|
|
|
11601
|
-
// src/commands/
|
|
11772
|
+
// src/commands/registerPrsEdit.ts
|
|
11602
11773
|
function collect2(value, previous) {
|
|
11603
11774
|
return previous.concat([value]);
|
|
11604
11775
|
}
|
|
11605
|
-
function
|
|
11606
|
-
prsCommand.command("
|
|
11607
|
-
"
|
|
11608
|
-
).option("-t, --title <title>", "
|
|
11776
|
+
function registerPrsEdit(prsCommand) {
|
|
11777
|
+
prsCommand.command("edit").description(
|
|
11778
|
+
"Update individual sections of the current branch's pull request"
|
|
11779
|
+
).option("-t, --title <title>", "New title for the pull request").option("--what <what>", "Replace the ## What section").option("--why <why>", "Replace the ## Why section").option("--how <how>", "Replace the ## How section").option(
|
|
11780
|
+
"--resolves <key>",
|
|
11781
|
+
"Jira issue key resolved by this PR, appended to ## Why (repeatable)",
|
|
11782
|
+
collect2,
|
|
11783
|
+
[]
|
|
11784
|
+
).action(edit);
|
|
11785
|
+
}
|
|
11786
|
+
|
|
11787
|
+
// src/commands/registerPrsRaise.ts
|
|
11788
|
+
function collect3(value, previous) {
|
|
11789
|
+
return previous.concat([value]);
|
|
11790
|
+
}
|
|
11791
|
+
function registerPrsRaise(prsCommand) {
|
|
11792
|
+
prsCommand.command("raise").description(
|
|
11793
|
+
"Raise a pull request, assembling the body from discrete sections"
|
|
11794
|
+
).option("-t, --title <title>", "Title for the pull request").option("--what <what>", "What the change does (## What section)").option("--why <why>", "Why the change is needed (## Why section)").option("--how <how>", "How the change works (optional ## How section)").option(
|
|
11795
|
+
"--resolves <key>",
|
|
11796
|
+
"Jira issue key resolved by this PR, appended to ## Why (repeatable)",
|
|
11797
|
+
collect3,
|
|
11798
|
+
[]
|
|
11799
|
+
).option(
|
|
11800
|
+
"--force",
|
|
11801
|
+
"Overwrite the title and body of an existing pull request"
|
|
11802
|
+
).option("-B, --base <branch>", "Branch into which the pull request merges").option("-H, --head <branch>", "Branch that contains the commits").option("-d, --draft", "Mark the pull request as a draft").option("-w, --web", "Open the browser to create the pull request").option("-l, --label <label>", "Add a label (repeatable)", collect3, []).option(
|
|
11609
11803
|
"-a, --assignee <login>",
|
|
11610
11804
|
"Assign a person by login (repeatable)",
|
|
11611
|
-
|
|
11805
|
+
collect3,
|
|
11612
11806
|
[]
|
|
11613
11807
|
).option(
|
|
11614
11808
|
"-r, --reviewer <handle>",
|
|
11615
11809
|
"Request a review (repeatable)",
|
|
11616
|
-
|
|
11810
|
+
collect3,
|
|
11617
11811
|
[]
|
|
11618
|
-
).option("-m, --milestone <name>", "Add the pull request to a milestone").action(
|
|
11812
|
+
).option("-m, --milestone <name>", "Add the pull request to a milestone").action(raise);
|
|
11619
11813
|
}
|
|
11620
11814
|
|
|
11621
11815
|
// src/commands/registerPrs.ts
|
|
11622
11816
|
function registerPrs(program2) {
|
|
11623
11817
|
const prsCommand = program2.command("prs").description("Pull request utilities").option("--open", "List only open pull requests").option("--closed", "List only closed pull requests").action(prs);
|
|
11624
|
-
|
|
11818
|
+
registerPrsRaise(prsCommand);
|
|
11819
|
+
registerPrsEdit(prsCommand);
|
|
11625
11820
|
prsCommand.command("list-comments").description("List all comments on the current branch's pull request").action(() => {
|
|
11626
11821
|
listComments().then(printComments2);
|
|
11627
11822
|
});
|
|
@@ -11637,10 +11832,10 @@ function registerPrs(program2) {
|
|
|
11637
11832
|
}
|
|
11638
11833
|
|
|
11639
11834
|
// src/commands/ravendb/ravendbAuth.ts
|
|
11640
|
-
import
|
|
11835
|
+
import chalk127 from "chalk";
|
|
11641
11836
|
|
|
11642
11837
|
// src/shared/createConnectionAuth.ts
|
|
11643
|
-
import
|
|
11838
|
+
import chalk122 from "chalk";
|
|
11644
11839
|
function listConnections(connections, format2) {
|
|
11645
11840
|
if (connections.length === 0) {
|
|
11646
11841
|
console.log("No connections configured.");
|
|
@@ -11653,7 +11848,7 @@ function listConnections(connections, format2) {
|
|
|
11653
11848
|
function removeConnection(connections, name, save) {
|
|
11654
11849
|
const filtered = connections.filter((c) => c.name !== name);
|
|
11655
11850
|
if (filtered.length === connections.length) {
|
|
11656
|
-
console.error(
|
|
11851
|
+
console.error(chalk122.red(`Connection "${name}" not found.`));
|
|
11657
11852
|
process.exit(1);
|
|
11658
11853
|
}
|
|
11659
11854
|
save(filtered);
|
|
@@ -11699,17 +11894,17 @@ function saveConnections(connections) {
|
|
|
11699
11894
|
}
|
|
11700
11895
|
|
|
11701
11896
|
// src/commands/ravendb/promptConnection.ts
|
|
11702
|
-
import
|
|
11897
|
+
import chalk125 from "chalk";
|
|
11703
11898
|
|
|
11704
11899
|
// src/commands/ravendb/selectOpSecret.ts
|
|
11705
|
-
import
|
|
11900
|
+
import chalk124 from "chalk";
|
|
11706
11901
|
import Enquirer2 from "enquirer";
|
|
11707
11902
|
|
|
11708
11903
|
// src/commands/ravendb/searchItems.ts
|
|
11709
|
-
import { execSync as
|
|
11710
|
-
import
|
|
11904
|
+
import { execSync as execSync41 } from "child_process";
|
|
11905
|
+
import chalk123 from "chalk";
|
|
11711
11906
|
function opExec(args) {
|
|
11712
|
-
return
|
|
11907
|
+
return execSync41(`op ${args}`, {
|
|
11713
11908
|
encoding: "utf-8",
|
|
11714
11909
|
stdio: ["pipe", "pipe", "pipe"]
|
|
11715
11910
|
}).trim();
|
|
@@ -11720,7 +11915,7 @@ function searchItems(search2) {
|
|
|
11720
11915
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
11721
11916
|
} catch {
|
|
11722
11917
|
console.error(
|
|
11723
|
-
|
|
11918
|
+
chalk123.red(
|
|
11724
11919
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
11725
11920
|
)
|
|
11726
11921
|
);
|
|
@@ -11734,7 +11929,7 @@ function getItemFields(itemId) {
|
|
|
11734
11929
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
11735
11930
|
return item.fields.filter((f) => f.reference && f.label);
|
|
11736
11931
|
} catch {
|
|
11737
|
-
console.error(
|
|
11932
|
+
console.error(chalk123.red("Failed to get item details from 1Password."));
|
|
11738
11933
|
process.exit(1);
|
|
11739
11934
|
}
|
|
11740
11935
|
}
|
|
@@ -11753,7 +11948,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11753
11948
|
}).run();
|
|
11754
11949
|
const items2 = searchItems(search2);
|
|
11755
11950
|
if (items2.length === 0) {
|
|
11756
|
-
console.error(
|
|
11951
|
+
console.error(chalk124.red(`No items found matching "${search2}".`));
|
|
11757
11952
|
process.exit(1);
|
|
11758
11953
|
}
|
|
11759
11954
|
const itemId = await selectOne(
|
|
@@ -11762,7 +11957,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11762
11957
|
);
|
|
11763
11958
|
const fields = getItemFields(itemId);
|
|
11764
11959
|
if (fields.length === 0) {
|
|
11765
|
-
console.error(
|
|
11960
|
+
console.error(chalk124.red("No fields with references found on this item."));
|
|
11766
11961
|
process.exit(1);
|
|
11767
11962
|
}
|
|
11768
11963
|
const ref = await selectOne(
|
|
@@ -11776,7 +11971,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11776
11971
|
async function promptConnection(existingNames) {
|
|
11777
11972
|
const name = await promptInput("name", "Connection name:");
|
|
11778
11973
|
if (existingNames.includes(name)) {
|
|
11779
|
-
console.error(
|
|
11974
|
+
console.error(chalk125.red(`Connection "${name}" already exists.`));
|
|
11780
11975
|
process.exit(1);
|
|
11781
11976
|
}
|
|
11782
11977
|
const url = await promptInput(
|
|
@@ -11785,22 +11980,22 @@ async function promptConnection(existingNames) {
|
|
|
11785
11980
|
);
|
|
11786
11981
|
const database = await promptInput("database", "Database name:");
|
|
11787
11982
|
if (!name || !url || !database) {
|
|
11788
|
-
console.error(
|
|
11983
|
+
console.error(chalk125.red("All fields are required."));
|
|
11789
11984
|
process.exit(1);
|
|
11790
11985
|
}
|
|
11791
11986
|
const apiKeyRef = await selectOpSecret();
|
|
11792
|
-
console.log(
|
|
11987
|
+
console.log(chalk125.dim(`Using: ${apiKeyRef}`));
|
|
11793
11988
|
return { name, url, database, apiKeyRef };
|
|
11794
11989
|
}
|
|
11795
11990
|
|
|
11796
11991
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
11797
|
-
import
|
|
11992
|
+
import chalk126 from "chalk";
|
|
11798
11993
|
function ravendbSetConnection(name) {
|
|
11799
11994
|
const raw = loadGlobalConfigRaw();
|
|
11800
11995
|
const ravendb = raw.ravendb ?? {};
|
|
11801
11996
|
const connections = ravendb.connections ?? [];
|
|
11802
11997
|
if (!connections.some((c) => c.name === name)) {
|
|
11803
|
-
console.error(
|
|
11998
|
+
console.error(chalk126.red(`Connection "${name}" not found.`));
|
|
11804
11999
|
console.error(
|
|
11805
12000
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
11806
12001
|
);
|
|
@@ -11816,16 +12011,16 @@ function ravendbSetConnection(name) {
|
|
|
11816
12011
|
var ravendbAuth = createConnectionAuth({
|
|
11817
12012
|
load: loadConnections,
|
|
11818
12013
|
save: saveConnections,
|
|
11819
|
-
format: (c) => `${
|
|
12014
|
+
format: (c) => `${chalk127.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
11820
12015
|
promptNew: promptConnection,
|
|
11821
12016
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
11822
12017
|
});
|
|
11823
12018
|
|
|
11824
12019
|
// src/commands/ravendb/ravendbCollections.ts
|
|
11825
|
-
import
|
|
12020
|
+
import chalk131 from "chalk";
|
|
11826
12021
|
|
|
11827
12022
|
// src/commands/ravendb/ravenFetch.ts
|
|
11828
|
-
import
|
|
12023
|
+
import chalk129 from "chalk";
|
|
11829
12024
|
|
|
11830
12025
|
// src/commands/ravendb/getAccessToken.ts
|
|
11831
12026
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -11861,21 +12056,21 @@ ${errorText}`
|
|
|
11861
12056
|
}
|
|
11862
12057
|
|
|
11863
12058
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
11864
|
-
import { execSync as
|
|
11865
|
-
import
|
|
12059
|
+
import { execSync as execSync42 } from "child_process";
|
|
12060
|
+
import chalk128 from "chalk";
|
|
11866
12061
|
function resolveOpSecret(reference) {
|
|
11867
12062
|
if (!reference.startsWith("op://")) {
|
|
11868
|
-
console.error(
|
|
12063
|
+
console.error(chalk128.red(`Invalid secret reference: must start with op://`));
|
|
11869
12064
|
process.exit(1);
|
|
11870
12065
|
}
|
|
11871
12066
|
try {
|
|
11872
|
-
return
|
|
12067
|
+
return execSync42(`op read "${reference}"`, {
|
|
11873
12068
|
encoding: "utf-8",
|
|
11874
12069
|
stdio: ["pipe", "pipe", "pipe"]
|
|
11875
12070
|
}).trim();
|
|
11876
12071
|
} catch {
|
|
11877
12072
|
console.error(
|
|
11878
|
-
|
|
12073
|
+
chalk128.red(
|
|
11879
12074
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
11880
12075
|
)
|
|
11881
12076
|
);
|
|
@@ -11902,7 +12097,7 @@ async function ravenFetch(connection, path54) {
|
|
|
11902
12097
|
if (!response.ok) {
|
|
11903
12098
|
const body = await response.text();
|
|
11904
12099
|
console.error(
|
|
11905
|
-
|
|
12100
|
+
chalk129.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
11906
12101
|
);
|
|
11907
12102
|
console.error(body.substring(0, 500));
|
|
11908
12103
|
process.exit(1);
|
|
@@ -11911,7 +12106,7 @@ async function ravenFetch(connection, path54) {
|
|
|
11911
12106
|
}
|
|
11912
12107
|
|
|
11913
12108
|
// src/commands/ravendb/resolveConnection.ts
|
|
11914
|
-
import
|
|
12109
|
+
import chalk130 from "chalk";
|
|
11915
12110
|
function loadRavendb() {
|
|
11916
12111
|
const raw = loadGlobalConfigRaw();
|
|
11917
12112
|
const ravendb = raw.ravendb;
|
|
@@ -11925,7 +12120,7 @@ function resolveConnection(name) {
|
|
|
11925
12120
|
const connectionName = name ?? defaultConnection;
|
|
11926
12121
|
if (!connectionName) {
|
|
11927
12122
|
console.error(
|
|
11928
|
-
|
|
12123
|
+
chalk130.red(
|
|
11929
12124
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
11930
12125
|
)
|
|
11931
12126
|
);
|
|
@@ -11933,7 +12128,7 @@ function resolveConnection(name) {
|
|
|
11933
12128
|
}
|
|
11934
12129
|
const connection = connections.find((c) => c.name === connectionName);
|
|
11935
12130
|
if (!connection) {
|
|
11936
|
-
console.error(
|
|
12131
|
+
console.error(chalk130.red(`Connection "${connectionName}" not found.`));
|
|
11937
12132
|
console.error(
|
|
11938
12133
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
11939
12134
|
);
|
|
@@ -11964,15 +12159,15 @@ async function ravendbCollections(connectionName) {
|
|
|
11964
12159
|
return;
|
|
11965
12160
|
}
|
|
11966
12161
|
for (const c of collections) {
|
|
11967
|
-
console.log(`${
|
|
12162
|
+
console.log(`${chalk131.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
11968
12163
|
}
|
|
11969
12164
|
}
|
|
11970
12165
|
|
|
11971
12166
|
// src/commands/ravendb/ravendbQuery.ts
|
|
11972
|
-
import
|
|
12167
|
+
import chalk133 from "chalk";
|
|
11973
12168
|
|
|
11974
12169
|
// src/commands/ravendb/fetchAllPages.ts
|
|
11975
|
-
import
|
|
12170
|
+
import chalk132 from "chalk";
|
|
11976
12171
|
|
|
11977
12172
|
// src/commands/ravendb/buildQueryPath.ts
|
|
11978
12173
|
function buildQueryPath(opts) {
|
|
@@ -12010,7 +12205,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
12010
12205
|
allResults.push(...results);
|
|
12011
12206
|
start3 += results.length;
|
|
12012
12207
|
process.stderr.write(
|
|
12013
|
-
`\r${
|
|
12208
|
+
`\r${chalk132.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
12014
12209
|
);
|
|
12015
12210
|
if (start3 >= totalResults) break;
|
|
12016
12211
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -12025,7 +12220,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
12025
12220
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
12026
12221
|
const resolved = resolveArgs(connectionName, collection);
|
|
12027
12222
|
if (!resolved.collection && !options2.query) {
|
|
12028
|
-
console.error(
|
|
12223
|
+
console.error(chalk133.red("Provide a collection name or --query filter."));
|
|
12029
12224
|
process.exit(1);
|
|
12030
12225
|
}
|
|
12031
12226
|
const { collection: col } = resolved;
|
|
@@ -12063,7 +12258,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
12063
12258
|
import * as path26 from "path";
|
|
12064
12259
|
|
|
12065
12260
|
// src/commands/refactor/logViolations.ts
|
|
12066
|
-
import
|
|
12261
|
+
import chalk134 from "chalk";
|
|
12067
12262
|
var DEFAULT_MAX_LINES = 100;
|
|
12068
12263
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
12069
12264
|
if (violations.length === 0) {
|
|
@@ -12072,43 +12267,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
12072
12267
|
}
|
|
12073
12268
|
return;
|
|
12074
12269
|
}
|
|
12075
|
-
console.error(
|
|
12270
|
+
console.error(chalk134.red(`
|
|
12076
12271
|
Refactor check failed:
|
|
12077
12272
|
`));
|
|
12078
|
-
console.error(
|
|
12273
|
+
console.error(chalk134.red(` The following files exceed ${maxLines} lines:
|
|
12079
12274
|
`));
|
|
12080
12275
|
for (const violation of violations) {
|
|
12081
|
-
console.error(
|
|
12276
|
+
console.error(chalk134.red(` ${violation.file} (${violation.lines} lines)`));
|
|
12082
12277
|
}
|
|
12083
12278
|
console.error(
|
|
12084
|
-
|
|
12279
|
+
chalk134.yellow(
|
|
12085
12280
|
`
|
|
12086
12281
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
12087
12282
|
way to refactor it, ignore it with:
|
|
12088
12283
|
`
|
|
12089
12284
|
)
|
|
12090
12285
|
);
|
|
12091
|
-
console.error(
|
|
12286
|
+
console.error(chalk134.gray(` assist refactor ignore <file>
|
|
12092
12287
|
`));
|
|
12093
12288
|
if (process.env.CLAUDECODE) {
|
|
12094
|
-
console.error(
|
|
12289
|
+
console.error(chalk134.cyan(`
|
|
12095
12290
|
## Extracting Code to New Files
|
|
12096
12291
|
`));
|
|
12097
12292
|
console.error(
|
|
12098
|
-
|
|
12293
|
+
chalk134.cyan(
|
|
12099
12294
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
12100
12295
|
`
|
|
12101
12296
|
)
|
|
12102
12297
|
);
|
|
12103
12298
|
console.error(
|
|
12104
|
-
|
|
12299
|
+
chalk134.cyan(
|
|
12105
12300
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
12106
12301
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
12107
12302
|
`
|
|
12108
12303
|
)
|
|
12109
12304
|
);
|
|
12110
12305
|
console.error(
|
|
12111
|
-
|
|
12306
|
+
chalk134.cyan(
|
|
12112
12307
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
12113
12308
|
domains, move it to a common/shared folder.
|
|
12114
12309
|
`
|
|
@@ -12118,7 +12313,7 @@ Refactor check failed:
|
|
|
12118
12313
|
}
|
|
12119
12314
|
|
|
12120
12315
|
// src/commands/refactor/check/getViolations/index.ts
|
|
12121
|
-
import { execSync as
|
|
12316
|
+
import { execSync as execSync43 } from "child_process";
|
|
12122
12317
|
import fs18 from "fs";
|
|
12123
12318
|
import { minimatch as minimatch5 } from "minimatch";
|
|
12124
12319
|
|
|
@@ -12168,7 +12363,7 @@ function getGitFiles(options2) {
|
|
|
12168
12363
|
}
|
|
12169
12364
|
const files = /* @__PURE__ */ new Set();
|
|
12170
12365
|
if (options2.staged || options2.modified) {
|
|
12171
|
-
const staged =
|
|
12366
|
+
const staged = execSync43("git diff --cached --name-only", {
|
|
12172
12367
|
encoding: "utf-8"
|
|
12173
12368
|
});
|
|
12174
12369
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -12176,7 +12371,7 @@ function getGitFiles(options2) {
|
|
|
12176
12371
|
}
|
|
12177
12372
|
}
|
|
12178
12373
|
if (options2.unstaged || options2.modified) {
|
|
12179
|
-
const unstaged =
|
|
12374
|
+
const unstaged = execSync43("git diff --name-only", { encoding: "utf-8" });
|
|
12180
12375
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
12181
12376
|
files.add(file);
|
|
12182
12377
|
}
|
|
@@ -12264,7 +12459,7 @@ async function check(pattern2, options2) {
|
|
|
12264
12459
|
|
|
12265
12460
|
// src/commands/refactor/extract/index.ts
|
|
12266
12461
|
import path33 from "path";
|
|
12267
|
-
import
|
|
12462
|
+
import chalk137 from "chalk";
|
|
12268
12463
|
|
|
12269
12464
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
12270
12465
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -12839,23 +13034,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
12839
13034
|
|
|
12840
13035
|
// src/commands/refactor/extract/displayPlan.ts
|
|
12841
13036
|
import path30 from "path";
|
|
12842
|
-
import
|
|
13037
|
+
import chalk135 from "chalk";
|
|
12843
13038
|
function section(title) {
|
|
12844
13039
|
return `
|
|
12845
|
-
${
|
|
13040
|
+
${chalk135.cyan(title)}`;
|
|
12846
13041
|
}
|
|
12847
13042
|
function displayImporters(plan2, cwd) {
|
|
12848
13043
|
if (plan2.importersToUpdate.length === 0) return;
|
|
12849
13044
|
console.log(section("Update importers:"));
|
|
12850
13045
|
for (const imp of plan2.importersToUpdate) {
|
|
12851
13046
|
const rel = path30.relative(cwd, imp.file.getFilePath());
|
|
12852
|
-
console.log(` ${
|
|
13047
|
+
console.log(` ${chalk135.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
12853
13048
|
}
|
|
12854
13049
|
}
|
|
12855
13050
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
12856
|
-
console.log(
|
|
13051
|
+
console.log(chalk135.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
12857
13052
|
`));
|
|
12858
|
-
console.log(` ${
|
|
13053
|
+
console.log(` ${chalk135.cyan("Functions to move:")}`);
|
|
12859
13054
|
for (const name of plan2.extractedNames) {
|
|
12860
13055
|
console.log(` ${name}`);
|
|
12861
13056
|
}
|
|
@@ -12889,7 +13084,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
12889
13084
|
|
|
12890
13085
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
12891
13086
|
import path32 from "path";
|
|
12892
|
-
import
|
|
13087
|
+
import chalk136 from "chalk";
|
|
12893
13088
|
import { Project as Project4 } from "ts-morph";
|
|
12894
13089
|
|
|
12895
13090
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -12949,7 +13144,7 @@ function loadProjectFile(file) {
|
|
|
12949
13144
|
});
|
|
12950
13145
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
12951
13146
|
if (!sourceFile) {
|
|
12952
|
-
console.log(
|
|
13147
|
+
console.log(chalk136.red(`File not found in project: ${file}`));
|
|
12953
13148
|
process.exit(1);
|
|
12954
13149
|
}
|
|
12955
13150
|
return { project, sourceFile };
|
|
@@ -12972,19 +13167,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
12972
13167
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
12973
13168
|
if (options2.apply) {
|
|
12974
13169
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
12975
|
-
console.log(
|
|
13170
|
+
console.log(chalk137.green("\nExtraction complete"));
|
|
12976
13171
|
} else {
|
|
12977
|
-
console.log(
|
|
13172
|
+
console.log(chalk137.dim("\nDry run. Use --apply to execute."));
|
|
12978
13173
|
}
|
|
12979
13174
|
}
|
|
12980
13175
|
|
|
12981
13176
|
// src/commands/refactor/ignore.ts
|
|
12982
13177
|
import fs20 from "fs";
|
|
12983
|
-
import
|
|
13178
|
+
import chalk138 from "chalk";
|
|
12984
13179
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
12985
13180
|
function ignore(file) {
|
|
12986
13181
|
if (!fs20.existsSync(file)) {
|
|
12987
|
-
console.error(
|
|
13182
|
+
console.error(chalk138.red(`Error: File does not exist: ${file}`));
|
|
12988
13183
|
process.exit(1);
|
|
12989
13184
|
}
|
|
12990
13185
|
const content = fs20.readFileSync(file, "utf-8");
|
|
@@ -13000,7 +13195,7 @@ function ignore(file) {
|
|
|
13000
13195
|
fs20.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
13001
13196
|
}
|
|
13002
13197
|
console.log(
|
|
13003
|
-
|
|
13198
|
+
chalk138.green(
|
|
13004
13199
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
13005
13200
|
)
|
|
13006
13201
|
);
|
|
@@ -13008,25 +13203,25 @@ function ignore(file) {
|
|
|
13008
13203
|
|
|
13009
13204
|
// src/commands/refactor/rename/index.ts
|
|
13010
13205
|
import path34 from "path";
|
|
13011
|
-
import
|
|
13206
|
+
import chalk139 from "chalk";
|
|
13012
13207
|
async function rename(source, destination, options2 = {}) {
|
|
13013
13208
|
const destPath = path34.resolve(destination);
|
|
13014
13209
|
const cwd = process.cwd();
|
|
13015
13210
|
const relSource = path34.relative(cwd, path34.resolve(source));
|
|
13016
13211
|
const relDest = path34.relative(cwd, destPath);
|
|
13017
13212
|
const { project, sourceFile } = loadProjectFile(source);
|
|
13018
|
-
console.log(
|
|
13213
|
+
console.log(chalk139.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
13019
13214
|
if (options2.apply) {
|
|
13020
13215
|
sourceFile.move(destPath);
|
|
13021
13216
|
await project.save();
|
|
13022
|
-
console.log(
|
|
13217
|
+
console.log(chalk139.green("Done"));
|
|
13023
13218
|
} else {
|
|
13024
|
-
console.log(
|
|
13219
|
+
console.log(chalk139.dim("Dry run. Use --apply to execute."));
|
|
13025
13220
|
}
|
|
13026
13221
|
}
|
|
13027
13222
|
|
|
13028
13223
|
// src/commands/refactor/renameSymbol/index.ts
|
|
13029
|
-
import
|
|
13224
|
+
import chalk140 from "chalk";
|
|
13030
13225
|
|
|
13031
13226
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
13032
13227
|
import { SyntaxKind as SyntaxKind14 } from "ts-morph";
|
|
@@ -13072,33 +13267,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
13072
13267
|
const { project, sourceFile } = loadProjectFile(file);
|
|
13073
13268
|
const symbol = findSymbol(sourceFile, oldName);
|
|
13074
13269
|
if (!symbol) {
|
|
13075
|
-
console.log(
|
|
13270
|
+
console.log(chalk140.red(`Symbol "${oldName}" not found in ${file}`));
|
|
13076
13271
|
process.exit(1);
|
|
13077
13272
|
}
|
|
13078
13273
|
const grouped = groupReferences(symbol, cwd);
|
|
13079
13274
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
13080
13275
|
console.log(
|
|
13081
|
-
|
|
13276
|
+
chalk140.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
13082
13277
|
`)
|
|
13083
13278
|
);
|
|
13084
13279
|
for (const [refFile, lines] of grouped) {
|
|
13085
13280
|
console.log(
|
|
13086
|
-
` ${
|
|
13281
|
+
` ${chalk140.dim(refFile)}: lines ${chalk140.cyan(lines.join(", "))}`
|
|
13087
13282
|
);
|
|
13088
13283
|
}
|
|
13089
13284
|
if (options2.apply) {
|
|
13090
13285
|
symbol.rename(newName);
|
|
13091
13286
|
await project.save();
|
|
13092
|
-
console.log(
|
|
13287
|
+
console.log(chalk140.green(`
|
|
13093
13288
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
13094
13289
|
} else {
|
|
13095
|
-
console.log(
|
|
13290
|
+
console.log(chalk140.dim("\nDry run. Use --apply to execute."));
|
|
13096
13291
|
}
|
|
13097
13292
|
}
|
|
13098
13293
|
|
|
13099
13294
|
// src/commands/refactor/restructure/index.ts
|
|
13100
13295
|
import path44 from "path";
|
|
13101
|
-
import
|
|
13296
|
+
import chalk143 from "chalk";
|
|
13102
13297
|
|
|
13103
13298
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
13104
13299
|
import path36 from "path";
|
|
@@ -13341,50 +13536,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
13341
13536
|
|
|
13342
13537
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
13343
13538
|
import path40 from "path";
|
|
13344
|
-
import
|
|
13539
|
+
import chalk141 from "chalk";
|
|
13345
13540
|
function relPath(filePath) {
|
|
13346
13541
|
return path40.relative(process.cwd(), filePath);
|
|
13347
13542
|
}
|
|
13348
13543
|
function displayMoves(plan2) {
|
|
13349
13544
|
if (plan2.moves.length === 0) return;
|
|
13350
|
-
console.log(
|
|
13545
|
+
console.log(chalk141.bold("\nFile moves:"));
|
|
13351
13546
|
for (const move of plan2.moves) {
|
|
13352
13547
|
console.log(
|
|
13353
|
-
` ${
|
|
13548
|
+
` ${chalk141.red(relPath(move.from))} \u2192 ${chalk141.green(relPath(move.to))}`
|
|
13354
13549
|
);
|
|
13355
|
-
console.log(
|
|
13550
|
+
console.log(chalk141.dim(` ${move.reason}`));
|
|
13356
13551
|
}
|
|
13357
13552
|
}
|
|
13358
13553
|
function displayRewrites(rewrites) {
|
|
13359
13554
|
if (rewrites.length === 0) return;
|
|
13360
13555
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
13361
|
-
console.log(
|
|
13556
|
+
console.log(chalk141.bold(`
|
|
13362
13557
|
Import rewrites (${affectedFiles.size} files):`));
|
|
13363
13558
|
for (const file of affectedFiles) {
|
|
13364
|
-
console.log(` ${
|
|
13559
|
+
console.log(` ${chalk141.cyan(relPath(file))}:`);
|
|
13365
13560
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
13366
13561
|
(r) => r.file === file
|
|
13367
13562
|
)) {
|
|
13368
13563
|
console.log(
|
|
13369
|
-
` ${
|
|
13564
|
+
` ${chalk141.red(`"${oldSpecifier}"`)} \u2192 ${chalk141.green(`"${newSpecifier}"`)}`
|
|
13370
13565
|
);
|
|
13371
13566
|
}
|
|
13372
13567
|
}
|
|
13373
13568
|
}
|
|
13374
13569
|
function displayPlan2(plan2) {
|
|
13375
13570
|
if (plan2.warnings.length > 0) {
|
|
13376
|
-
console.log(
|
|
13377
|
-
for (const w of plan2.warnings) console.log(
|
|
13571
|
+
console.log(chalk141.yellow("\nWarnings:"));
|
|
13572
|
+
for (const w of plan2.warnings) console.log(chalk141.yellow(` ${w}`));
|
|
13378
13573
|
}
|
|
13379
13574
|
if (plan2.newDirectories.length > 0) {
|
|
13380
|
-
console.log(
|
|
13575
|
+
console.log(chalk141.bold("\nNew directories:"));
|
|
13381
13576
|
for (const dir of plan2.newDirectories)
|
|
13382
|
-
console.log(
|
|
13577
|
+
console.log(chalk141.green(` ${dir}/`));
|
|
13383
13578
|
}
|
|
13384
13579
|
displayMoves(plan2);
|
|
13385
13580
|
displayRewrites(plan2.rewrites);
|
|
13386
13581
|
console.log(
|
|
13387
|
-
|
|
13582
|
+
chalk141.dim(
|
|
13388
13583
|
`
|
|
13389
13584
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
13390
13585
|
)
|
|
@@ -13394,18 +13589,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
13394
13589
|
// src/commands/refactor/restructure/executePlan.ts
|
|
13395
13590
|
import fs22 from "fs";
|
|
13396
13591
|
import path41 from "path";
|
|
13397
|
-
import
|
|
13592
|
+
import chalk142 from "chalk";
|
|
13398
13593
|
function executePlan(plan2) {
|
|
13399
13594
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
13400
13595
|
for (const [file, content] of updatedContents) {
|
|
13401
13596
|
fs22.writeFileSync(file, content, "utf-8");
|
|
13402
13597
|
console.log(
|
|
13403
|
-
|
|
13598
|
+
chalk142.cyan(` Rewrote imports in ${path41.relative(process.cwd(), file)}`)
|
|
13404
13599
|
);
|
|
13405
13600
|
}
|
|
13406
13601
|
for (const dir of plan2.newDirectories) {
|
|
13407
13602
|
fs22.mkdirSync(dir, { recursive: true });
|
|
13408
|
-
console.log(
|
|
13603
|
+
console.log(chalk142.green(` Created ${path41.relative(process.cwd(), dir)}/`));
|
|
13409
13604
|
}
|
|
13410
13605
|
for (const move of plan2.moves) {
|
|
13411
13606
|
const targetDir = path41.dirname(move.to);
|
|
@@ -13414,7 +13609,7 @@ function executePlan(plan2) {
|
|
|
13414
13609
|
}
|
|
13415
13610
|
fs22.renameSync(move.from, move.to);
|
|
13416
13611
|
console.log(
|
|
13417
|
-
|
|
13612
|
+
chalk142.white(
|
|
13418
13613
|
` Moved ${path41.relative(process.cwd(), move.from)} \u2192 ${path41.relative(process.cwd(), move.to)}`
|
|
13419
13614
|
)
|
|
13420
13615
|
);
|
|
@@ -13429,7 +13624,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
13429
13624
|
if (entries.length === 0) {
|
|
13430
13625
|
fs22.rmdirSync(dir);
|
|
13431
13626
|
console.log(
|
|
13432
|
-
|
|
13627
|
+
chalk142.dim(
|
|
13433
13628
|
` Removed empty directory ${path41.relative(process.cwd(), dir)}`
|
|
13434
13629
|
)
|
|
13435
13630
|
);
|
|
@@ -13562,22 +13757,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
13562
13757
|
const targetPattern = pattern2 ?? "src";
|
|
13563
13758
|
const files = findSourceFiles2(targetPattern);
|
|
13564
13759
|
if (files.length === 0) {
|
|
13565
|
-
console.log(
|
|
13760
|
+
console.log(chalk143.yellow("No files found matching pattern"));
|
|
13566
13761
|
return;
|
|
13567
13762
|
}
|
|
13568
13763
|
const tsConfigPath = path44.resolve("tsconfig.json");
|
|
13569
13764
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
13570
13765
|
if (plan2.moves.length === 0) {
|
|
13571
|
-
console.log(
|
|
13766
|
+
console.log(chalk143.green("No restructuring needed"));
|
|
13572
13767
|
return;
|
|
13573
13768
|
}
|
|
13574
13769
|
displayPlan2(plan2);
|
|
13575
13770
|
if (options2.apply) {
|
|
13576
|
-
console.log(
|
|
13771
|
+
console.log(chalk143.bold("\nApplying changes..."));
|
|
13577
13772
|
executePlan(plan2);
|
|
13578
|
-
console.log(
|
|
13773
|
+
console.log(chalk143.green("\nRestructuring complete"));
|
|
13579
13774
|
} else {
|
|
13580
|
-
console.log(
|
|
13775
|
+
console.log(chalk143.dim("\nDry run. Use --apply to execute."));
|
|
13581
13776
|
}
|
|
13582
13777
|
}
|
|
13583
13778
|
|
|
@@ -13752,9 +13947,9 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
13752
13947
|
}
|
|
13753
13948
|
|
|
13754
13949
|
// src/commands/review/fetchExistingComments.ts
|
|
13755
|
-
import { execSync as
|
|
13950
|
+
import { execSync as execSync44 } from "child_process";
|
|
13756
13951
|
function fetchRawComments(org, repo, prNumber) {
|
|
13757
|
-
const out =
|
|
13952
|
+
const out = execSync44(
|
|
13758
13953
|
`gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
|
|
13759
13954
|
{ encoding: "utf-8", maxBuffer: 64 * 1024 * 1024 }
|
|
13760
13955
|
);
|
|
@@ -13785,14 +13980,14 @@ function fetchExistingComments() {
|
|
|
13785
13980
|
}
|
|
13786
13981
|
|
|
13787
13982
|
// src/commands/review/gatherContext.ts
|
|
13788
|
-
import { execSync as
|
|
13983
|
+
import { execSync as execSync47 } from "child_process";
|
|
13789
13984
|
|
|
13790
13985
|
// src/commands/review/fetchPrDiff.ts
|
|
13791
|
-
import { execSync as
|
|
13986
|
+
import { execSync as execSync45 } from "child_process";
|
|
13792
13987
|
function fetchPrDiff(prNumber, baseSha, headSha) {
|
|
13793
13988
|
const { org, repo } = getRepoInfo();
|
|
13794
13989
|
try {
|
|
13795
|
-
return
|
|
13990
|
+
return execSync45(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
|
|
13796
13991
|
encoding: "utf-8",
|
|
13797
13992
|
maxBuffer: 256 * 1024 * 1024,
|
|
13798
13993
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -13807,19 +14002,19 @@ function isDiffTooLarge(error) {
|
|
|
13807
14002
|
}
|
|
13808
14003
|
function fetchDiffViaGit(baseSha, headSha) {
|
|
13809
14004
|
try {
|
|
13810
|
-
|
|
14005
|
+
execSync45(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
|
|
13811
14006
|
} catch {
|
|
13812
14007
|
}
|
|
13813
|
-
return
|
|
14008
|
+
return execSync45(`git diff ${baseSha}...${headSha}`, {
|
|
13814
14009
|
encoding: "utf-8",
|
|
13815
14010
|
maxBuffer: 256 * 1024 * 1024
|
|
13816
14011
|
});
|
|
13817
14012
|
}
|
|
13818
14013
|
|
|
13819
14014
|
// src/commands/review/fetchPrDiffInfo.ts
|
|
13820
|
-
import { execSync as
|
|
14015
|
+
import { execSync as execSync46 } from "child_process";
|
|
13821
14016
|
function getCurrentBranch2() {
|
|
13822
|
-
return
|
|
14017
|
+
return execSync46("git rev-parse --abbrev-ref HEAD", {
|
|
13823
14018
|
encoding: "utf-8"
|
|
13824
14019
|
}).trim();
|
|
13825
14020
|
}
|
|
@@ -13829,7 +14024,7 @@ function fetchPrDiffInfo() {
|
|
|
13829
14024
|
const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
|
|
13830
14025
|
let raw;
|
|
13831
14026
|
try {
|
|
13832
|
-
raw =
|
|
14027
|
+
raw = execSync46(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
|
|
13833
14028
|
encoding: "utf-8",
|
|
13834
14029
|
stdio: ["ignore", "pipe", "pipe"]
|
|
13835
14030
|
});
|
|
@@ -13853,7 +14048,7 @@ function fetchPrDiffInfo() {
|
|
|
13853
14048
|
}
|
|
13854
14049
|
function fetchPrChangedFiles(prNumber) {
|
|
13855
14050
|
const { org, repo } = getRepoInfo();
|
|
13856
|
-
const out =
|
|
14051
|
+
const out = execSync46(
|
|
13857
14052
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
|
|
13858
14053
|
{
|
|
13859
14054
|
encoding: "utf-8",
|
|
@@ -13865,11 +14060,11 @@ function fetchPrChangedFiles(prNumber) {
|
|
|
13865
14060
|
|
|
13866
14061
|
// src/commands/review/gatherContext.ts
|
|
13867
14062
|
function gatherContext() {
|
|
13868
|
-
const branch =
|
|
14063
|
+
const branch = execSync47("git rev-parse --abbrev-ref HEAD", {
|
|
13869
14064
|
encoding: "utf-8"
|
|
13870
14065
|
}).trim();
|
|
13871
|
-
const sha =
|
|
13872
|
-
const shortSha =
|
|
14066
|
+
const sha = execSync47("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
14067
|
+
const shortSha = execSync47("git rev-parse --short=7 HEAD", {
|
|
13873
14068
|
encoding: "utf-8"
|
|
13874
14069
|
}).trim();
|
|
13875
14070
|
const prInfo = fetchPrDiffInfo();
|
|
@@ -14146,18 +14341,18 @@ function partitionFindingsByDiff(findings, index2) {
|
|
|
14146
14341
|
}
|
|
14147
14342
|
|
|
14148
14343
|
// src/commands/review/warnOutOfDiff.ts
|
|
14149
|
-
import
|
|
14344
|
+
import chalk144 from "chalk";
|
|
14150
14345
|
function warnOutOfDiff(outOfDiff) {
|
|
14151
14346
|
if (outOfDiff.length === 0) return;
|
|
14152
14347
|
console.warn(
|
|
14153
|
-
|
|
14348
|
+
chalk144.yellow(
|
|
14154
14349
|
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
14155
14350
|
)
|
|
14156
14351
|
);
|
|
14157
14352
|
for (const finding of outOfDiff) {
|
|
14158
14353
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
14159
14354
|
console.warn(
|
|
14160
|
-
` ${
|
|
14355
|
+
` ${chalk144.yellow("\xB7")} ${finding.title} ${chalk144.dim(
|
|
14161
14356
|
`(${finding.file}:${range})`
|
|
14162
14357
|
)}`
|
|
14163
14358
|
);
|
|
@@ -14176,18 +14371,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
14176
14371
|
}
|
|
14177
14372
|
|
|
14178
14373
|
// src/commands/review/warnUnlocated.ts
|
|
14179
|
-
import
|
|
14374
|
+
import chalk145 from "chalk";
|
|
14180
14375
|
function warnUnlocated(unlocated) {
|
|
14181
14376
|
if (unlocated.length === 0) return;
|
|
14182
14377
|
console.warn(
|
|
14183
|
-
|
|
14378
|
+
chalk145.yellow(
|
|
14184
14379
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
14185
14380
|
)
|
|
14186
14381
|
);
|
|
14187
14382
|
for (const finding of unlocated) {
|
|
14188
|
-
const where = finding.location ||
|
|
14383
|
+
const where = finding.location || chalk145.dim("missing");
|
|
14189
14384
|
console.warn(
|
|
14190
|
-
` ${
|
|
14385
|
+
` ${chalk145.yellow("\xB7")} ${finding.title} ${chalk145.dim(`(${where})`)}`
|
|
14191
14386
|
);
|
|
14192
14387
|
}
|
|
14193
14388
|
}
|
|
@@ -15360,7 +15555,7 @@ function registerReview(program2) {
|
|
|
15360
15555
|
}
|
|
15361
15556
|
|
|
15362
15557
|
// src/commands/seq/seqAuth.ts
|
|
15363
|
-
import
|
|
15558
|
+
import chalk147 from "chalk";
|
|
15364
15559
|
|
|
15365
15560
|
// src/commands/seq/loadConnections.ts
|
|
15366
15561
|
function loadConnections2() {
|
|
@@ -15389,10 +15584,10 @@ function setDefaultConnection(name) {
|
|
|
15389
15584
|
}
|
|
15390
15585
|
|
|
15391
15586
|
// src/shared/assertUniqueName.ts
|
|
15392
|
-
import
|
|
15587
|
+
import chalk146 from "chalk";
|
|
15393
15588
|
function assertUniqueName(existingNames, name) {
|
|
15394
15589
|
if (existingNames.includes(name)) {
|
|
15395
|
-
console.error(
|
|
15590
|
+
console.error(chalk146.red(`Connection "${name}" already exists.`));
|
|
15396
15591
|
process.exit(1);
|
|
15397
15592
|
}
|
|
15398
15593
|
}
|
|
@@ -15410,16 +15605,16 @@ async function promptConnection2(existingNames) {
|
|
|
15410
15605
|
var seqAuth = createConnectionAuth({
|
|
15411
15606
|
load: loadConnections2,
|
|
15412
15607
|
save: saveConnections2,
|
|
15413
|
-
format: (c) => `${
|
|
15608
|
+
format: (c) => `${chalk147.bold(c.name)} ${c.url}`,
|
|
15414
15609
|
promptNew: promptConnection2,
|
|
15415
15610
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
15416
15611
|
});
|
|
15417
15612
|
|
|
15418
15613
|
// src/commands/seq/seqQuery.ts
|
|
15419
|
-
import
|
|
15614
|
+
import chalk151 from "chalk";
|
|
15420
15615
|
|
|
15421
15616
|
// src/commands/seq/fetchSeq.ts
|
|
15422
|
-
import
|
|
15617
|
+
import chalk148 from "chalk";
|
|
15423
15618
|
async function fetchSeq(conn, path54, params) {
|
|
15424
15619
|
const url = `${conn.url}${path54}?${params}`;
|
|
15425
15620
|
const response = await fetch(url, {
|
|
@@ -15430,7 +15625,7 @@ async function fetchSeq(conn, path54, params) {
|
|
|
15430
15625
|
});
|
|
15431
15626
|
if (!response.ok) {
|
|
15432
15627
|
const body = await response.text();
|
|
15433
|
-
console.error(
|
|
15628
|
+
console.error(chalk148.red(`Seq returned ${response.status}: ${body}`));
|
|
15434
15629
|
process.exit(1);
|
|
15435
15630
|
}
|
|
15436
15631
|
return response;
|
|
@@ -15485,23 +15680,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
15485
15680
|
}
|
|
15486
15681
|
|
|
15487
15682
|
// src/commands/seq/formatEvent.ts
|
|
15488
|
-
import
|
|
15683
|
+
import chalk149 from "chalk";
|
|
15489
15684
|
function levelColor(level) {
|
|
15490
15685
|
switch (level) {
|
|
15491
15686
|
case "Fatal":
|
|
15492
|
-
return
|
|
15687
|
+
return chalk149.bgRed.white;
|
|
15493
15688
|
case "Error":
|
|
15494
|
-
return
|
|
15689
|
+
return chalk149.red;
|
|
15495
15690
|
case "Warning":
|
|
15496
|
-
return
|
|
15691
|
+
return chalk149.yellow;
|
|
15497
15692
|
case "Information":
|
|
15498
|
-
return
|
|
15693
|
+
return chalk149.cyan;
|
|
15499
15694
|
case "Debug":
|
|
15500
|
-
return
|
|
15695
|
+
return chalk149.gray;
|
|
15501
15696
|
case "Verbose":
|
|
15502
|
-
return
|
|
15697
|
+
return chalk149.dim;
|
|
15503
15698
|
default:
|
|
15504
|
-
return
|
|
15699
|
+
return chalk149.white;
|
|
15505
15700
|
}
|
|
15506
15701
|
}
|
|
15507
15702
|
function levelAbbrev(level) {
|
|
@@ -15542,12 +15737,12 @@ function formatTimestamp(iso) {
|
|
|
15542
15737
|
function formatEvent(event) {
|
|
15543
15738
|
const color = levelColor(event.Level);
|
|
15544
15739
|
const abbrev = levelAbbrev(event.Level);
|
|
15545
|
-
const ts8 =
|
|
15740
|
+
const ts8 = chalk149.dim(formatTimestamp(event.Timestamp));
|
|
15546
15741
|
const msg = renderMessage(event);
|
|
15547
15742
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
15548
15743
|
if (event.Exception) {
|
|
15549
15744
|
for (const line of event.Exception.split("\n")) {
|
|
15550
|
-
lines.push(
|
|
15745
|
+
lines.push(chalk149.red(` ${line}`));
|
|
15551
15746
|
}
|
|
15552
15747
|
}
|
|
15553
15748
|
return lines.join("\n");
|
|
@@ -15580,11 +15775,11 @@ function rejectTimestampFilter(filter) {
|
|
|
15580
15775
|
}
|
|
15581
15776
|
|
|
15582
15777
|
// src/shared/resolveNamedConnection.ts
|
|
15583
|
-
import
|
|
15778
|
+
import chalk150 from "chalk";
|
|
15584
15779
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
15585
15780
|
if (connections.length === 0) {
|
|
15586
15781
|
console.error(
|
|
15587
|
-
|
|
15782
|
+
chalk150.red(
|
|
15588
15783
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
15589
15784
|
)
|
|
15590
15785
|
);
|
|
@@ -15593,7 +15788,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
15593
15788
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
15594
15789
|
const connection = connections.find((c) => c.name === target);
|
|
15595
15790
|
if (!connection) {
|
|
15596
|
-
console.error(
|
|
15791
|
+
console.error(chalk150.red(`${kind} connection "${target}" not found.`));
|
|
15597
15792
|
process.exit(1);
|
|
15598
15793
|
}
|
|
15599
15794
|
return connection;
|
|
@@ -15622,7 +15817,7 @@ async function seqQuery(filter, options2) {
|
|
|
15622
15817
|
new URLSearchParams({ filter, count: String(count6) })
|
|
15623
15818
|
);
|
|
15624
15819
|
if (events.length === 0) {
|
|
15625
|
-
console.log(
|
|
15820
|
+
console.log(chalk151.yellow("No events found."));
|
|
15626
15821
|
return;
|
|
15627
15822
|
}
|
|
15628
15823
|
if (options2.json) {
|
|
@@ -15633,11 +15828,11 @@ async function seqQuery(filter, options2) {
|
|
|
15633
15828
|
for (const event of chronological) {
|
|
15634
15829
|
console.log(formatEvent(event));
|
|
15635
15830
|
}
|
|
15636
|
-
console.log(
|
|
15831
|
+
console.log(chalk151.dim(`
|
|
15637
15832
|
${events.length} events`));
|
|
15638
15833
|
if (events.length >= count6) {
|
|
15639
15834
|
console.log(
|
|
15640
|
-
|
|
15835
|
+
chalk151.yellow(
|
|
15641
15836
|
`Results limited to ${count6}. Use --count to retrieve more.`
|
|
15642
15837
|
)
|
|
15643
15838
|
);
|
|
@@ -15645,10 +15840,10 @@ ${events.length} events`));
|
|
|
15645
15840
|
}
|
|
15646
15841
|
|
|
15647
15842
|
// src/shared/setNamedDefaultConnection.ts
|
|
15648
|
-
import
|
|
15843
|
+
import chalk152 from "chalk";
|
|
15649
15844
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
15650
15845
|
if (!connections.find((c) => c.name === name)) {
|
|
15651
|
-
console.error(
|
|
15846
|
+
console.error(chalk152.red(`Connection "${name}" not found.`));
|
|
15652
15847
|
process.exit(1);
|
|
15653
15848
|
}
|
|
15654
15849
|
setDefault(name);
|
|
@@ -15696,7 +15891,7 @@ function registerSignal(program2) {
|
|
|
15696
15891
|
}
|
|
15697
15892
|
|
|
15698
15893
|
// src/commands/sql/sqlAuth.ts
|
|
15699
|
-
import
|
|
15894
|
+
import chalk154 from "chalk";
|
|
15700
15895
|
|
|
15701
15896
|
// src/commands/sql/loadConnections.ts
|
|
15702
15897
|
function loadConnections3() {
|
|
@@ -15725,7 +15920,7 @@ function setDefaultConnection2(name) {
|
|
|
15725
15920
|
}
|
|
15726
15921
|
|
|
15727
15922
|
// src/commands/sql/promptConnection.ts
|
|
15728
|
-
import
|
|
15923
|
+
import chalk153 from "chalk";
|
|
15729
15924
|
async function promptConnection3(existingNames) {
|
|
15730
15925
|
const name = await promptInput("name", "Connection name:", "default");
|
|
15731
15926
|
assertUniqueName(existingNames, name);
|
|
@@ -15733,7 +15928,7 @@ async function promptConnection3(existingNames) {
|
|
|
15733
15928
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
15734
15929
|
const port = Number.parseInt(portStr, 10);
|
|
15735
15930
|
if (!Number.isFinite(port)) {
|
|
15736
|
-
console.error(
|
|
15931
|
+
console.error(chalk153.red(`Invalid port "${portStr}".`));
|
|
15737
15932
|
process.exit(1);
|
|
15738
15933
|
}
|
|
15739
15934
|
const user = await promptInput("user", "User:");
|
|
@@ -15746,13 +15941,13 @@ async function promptConnection3(existingNames) {
|
|
|
15746
15941
|
var sqlAuth = createConnectionAuth({
|
|
15747
15942
|
load: loadConnections3,
|
|
15748
15943
|
save: saveConnections3,
|
|
15749
|
-
format: (c) => `${
|
|
15944
|
+
format: (c) => `${chalk154.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
15750
15945
|
promptNew: promptConnection3,
|
|
15751
15946
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
15752
15947
|
});
|
|
15753
15948
|
|
|
15754
15949
|
// src/commands/sql/printTable.ts
|
|
15755
|
-
import
|
|
15950
|
+
import chalk155 from "chalk";
|
|
15756
15951
|
function formatCell(value) {
|
|
15757
15952
|
if (value === null || value === void 0) return "";
|
|
15758
15953
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -15761,7 +15956,7 @@ function formatCell(value) {
|
|
|
15761
15956
|
}
|
|
15762
15957
|
function printTable(rows) {
|
|
15763
15958
|
if (rows.length === 0) {
|
|
15764
|
-
console.log(
|
|
15959
|
+
console.log(chalk155.yellow("(no rows)"));
|
|
15765
15960
|
return;
|
|
15766
15961
|
}
|
|
15767
15962
|
const columns = Object.keys(rows[0]);
|
|
@@ -15769,13 +15964,13 @@ function printTable(rows) {
|
|
|
15769
15964
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
15770
15965
|
);
|
|
15771
15966
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
15772
|
-
console.log(
|
|
15773
|
-
console.log(
|
|
15967
|
+
console.log(chalk155.dim(header));
|
|
15968
|
+
console.log(chalk155.dim("-".repeat(header.length)));
|
|
15774
15969
|
for (const row of rows) {
|
|
15775
15970
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
15776
15971
|
console.log(line);
|
|
15777
15972
|
}
|
|
15778
|
-
console.log(
|
|
15973
|
+
console.log(chalk155.dim(`
|
|
15779
15974
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
15780
15975
|
}
|
|
15781
15976
|
|
|
@@ -15835,7 +16030,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
15835
16030
|
}
|
|
15836
16031
|
|
|
15837
16032
|
// src/commands/sql/sqlMutate.ts
|
|
15838
|
-
import
|
|
16033
|
+
import chalk156 from "chalk";
|
|
15839
16034
|
|
|
15840
16035
|
// src/commands/sql/isMutation.ts
|
|
15841
16036
|
var MUTATION_KEYWORDS = [
|
|
@@ -15869,7 +16064,7 @@ function isMutation(sql4) {
|
|
|
15869
16064
|
async function sqlMutate(query, connectionName) {
|
|
15870
16065
|
if (!isMutation(query)) {
|
|
15871
16066
|
console.error(
|
|
15872
|
-
|
|
16067
|
+
chalk156.red(
|
|
15873
16068
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
15874
16069
|
)
|
|
15875
16070
|
);
|
|
@@ -15879,18 +16074,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
15879
16074
|
const pool = await sqlConnect(conn);
|
|
15880
16075
|
try {
|
|
15881
16076
|
const result = await pool.request().query(query);
|
|
15882
|
-
console.log(
|
|
16077
|
+
console.log(chalk156.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
15883
16078
|
} finally {
|
|
15884
16079
|
await pool.close();
|
|
15885
16080
|
}
|
|
15886
16081
|
}
|
|
15887
16082
|
|
|
15888
16083
|
// src/commands/sql/sqlQuery.ts
|
|
15889
|
-
import
|
|
16084
|
+
import chalk157 from "chalk";
|
|
15890
16085
|
async function sqlQuery(query, connectionName) {
|
|
15891
16086
|
if (isMutation(query)) {
|
|
15892
16087
|
console.error(
|
|
15893
|
-
|
|
16088
|
+
chalk157.red(
|
|
15894
16089
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
15895
16090
|
)
|
|
15896
16091
|
);
|
|
@@ -15905,7 +16100,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
15905
16100
|
printTable(rows);
|
|
15906
16101
|
} else {
|
|
15907
16102
|
console.log(
|
|
15908
|
-
|
|
16103
|
+
chalk157.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
15909
16104
|
);
|
|
15910
16105
|
}
|
|
15911
16106
|
} finally {
|
|
@@ -16485,14 +16680,14 @@ import {
|
|
|
16485
16680
|
import { dirname as dirname22, join as join42 } from "path";
|
|
16486
16681
|
|
|
16487
16682
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
16488
|
-
import
|
|
16683
|
+
import chalk158 from "chalk";
|
|
16489
16684
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
16490
16685
|
function validateStagedContent(filename, content) {
|
|
16491
16686
|
const firstLine = content.split("\n")[0];
|
|
16492
16687
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
16493
16688
|
if (!match) {
|
|
16494
16689
|
console.error(
|
|
16495
|
-
|
|
16690
|
+
chalk158.red(
|
|
16496
16691
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
16497
16692
|
)
|
|
16498
16693
|
);
|
|
@@ -16501,7 +16696,7 @@ function validateStagedContent(filename, content) {
|
|
|
16501
16696
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
16502
16697
|
if (!contentAfterLink) {
|
|
16503
16698
|
console.error(
|
|
16504
|
-
|
|
16699
|
+
chalk158.red(
|
|
16505
16700
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
16506
16701
|
)
|
|
16507
16702
|
);
|
|
@@ -16705,7 +16900,7 @@ import { mkdirSync as mkdirSync18 } from "fs";
|
|
|
16705
16900
|
import { join as join47 } from "path";
|
|
16706
16901
|
|
|
16707
16902
|
// src/commands/voice/checkLockFile.ts
|
|
16708
|
-
import { execSync as
|
|
16903
|
+
import { execSync as execSync48 } from "child_process";
|
|
16709
16904
|
import { existsSync as existsSync45, mkdirSync as mkdirSync17, readFileSync as readFileSync35, writeFileSync as writeFileSync29 } from "fs";
|
|
16710
16905
|
import { join as join46 } from "path";
|
|
16711
16906
|
function isProcessAlive2(pid) {
|
|
@@ -16734,7 +16929,7 @@ function bootstrapVenv() {
|
|
|
16734
16929
|
if (existsSync45(getVenvPython())) return;
|
|
16735
16930
|
console.log("Setting up Python environment...");
|
|
16736
16931
|
const pythonDir = getPythonDir();
|
|
16737
|
-
|
|
16932
|
+
execSync48(
|
|
16738
16933
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
16739
16934
|
{
|
|
16740
16935
|
stdio: "inherit",
|
|
@@ -16898,51 +17093,7 @@ function registerVoice(program2) {
|
|
|
16898
17093
|
|
|
16899
17094
|
// src/commands/roam/auth.ts
|
|
16900
17095
|
import { randomBytes } from "crypto";
|
|
16901
|
-
import
|
|
16902
|
-
|
|
16903
|
-
// src/lib/openBrowser.ts
|
|
16904
|
-
import { execSync as execSync47 } from "child_process";
|
|
16905
|
-
function tryExec(commands) {
|
|
16906
|
-
for (const cmd of commands) {
|
|
16907
|
-
try {
|
|
16908
|
-
execSync47(cmd);
|
|
16909
|
-
return true;
|
|
16910
|
-
} catch {
|
|
16911
|
-
}
|
|
16912
|
-
}
|
|
16913
|
-
return false;
|
|
16914
|
-
}
|
|
16915
|
-
function openBrowser2(url) {
|
|
16916
|
-
const platform = detectPlatform();
|
|
16917
|
-
const quoted = JSON.stringify(url);
|
|
16918
|
-
const commands = [];
|
|
16919
|
-
switch (platform) {
|
|
16920
|
-
case "macos":
|
|
16921
|
-
commands.push(
|
|
16922
|
-
`open -a "Google Chrome" ${quoted}`,
|
|
16923
|
-
`open -a "Microsoft Edge" ${quoted}`,
|
|
16924
|
-
`open -a "Safari" ${quoted}`
|
|
16925
|
-
);
|
|
16926
|
-
break;
|
|
16927
|
-
case "linux":
|
|
16928
|
-
commands.push(
|
|
16929
|
-
`google-chrome ${quoted}`,
|
|
16930
|
-
`chromium-browser ${quoted}`,
|
|
16931
|
-
`microsoft-edge ${quoted}`
|
|
16932
|
-
);
|
|
16933
|
-
break;
|
|
16934
|
-
case "windows":
|
|
16935
|
-
commands.push(`start chrome ${quoted}`, `start msedge ${quoted}`);
|
|
16936
|
-
break;
|
|
16937
|
-
case "wsl":
|
|
16938
|
-
commands.push(`wslview ${quoted}`);
|
|
16939
|
-
break;
|
|
16940
|
-
}
|
|
16941
|
-
if (!tryExec(commands)) {
|
|
16942
|
-
console.log(`Open this URL in Chrome, Edge, or Safari:
|
|
16943
|
-
${url}`);
|
|
16944
|
-
}
|
|
16945
|
-
}
|
|
17096
|
+
import chalk159 from "chalk";
|
|
16946
17097
|
|
|
16947
17098
|
// src/commands/roam/waitForCallback.ts
|
|
16948
17099
|
import { createServer as createServer2 } from "http";
|
|
@@ -17006,7 +17157,7 @@ function buildAuthorizeUrl(clientId, state) {
|
|
|
17006
17157
|
return `https://ro.am/oauth/authorize?${params}`;
|
|
17007
17158
|
}
|
|
17008
17159
|
async function authorizeInBrowser(clientId, state) {
|
|
17009
|
-
|
|
17160
|
+
openBrowser(buildAuthorizeUrl(clientId, state));
|
|
17010
17161
|
const code = await waitForCallback(PORT, state);
|
|
17011
17162
|
return { code, redirectUri: REDIRECT_URI };
|
|
17012
17163
|
}
|
|
@@ -17073,13 +17224,13 @@ async function auth() {
|
|
|
17073
17224
|
saveGlobalConfig(config);
|
|
17074
17225
|
const state = randomBytes(16).toString("hex");
|
|
17075
17226
|
console.log(
|
|
17076
|
-
|
|
17227
|
+
chalk159.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
17077
17228
|
);
|
|
17078
|
-
console.log(
|
|
17079
|
-
console.log(
|
|
17080
|
-
console.log(
|
|
17229
|
+
console.log(chalk159.white("http://localhost:14523/callback\n"));
|
|
17230
|
+
console.log(chalk159.blue("Opening browser for authorization..."));
|
|
17231
|
+
console.log(chalk159.dim("Waiting for authorization callback..."));
|
|
17081
17232
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
17082
|
-
console.log(
|
|
17233
|
+
console.log(chalk159.dim("Exchanging code for tokens..."));
|
|
17083
17234
|
const tokens = await exchangeToken({
|
|
17084
17235
|
code,
|
|
17085
17236
|
clientId,
|
|
@@ -17095,7 +17246,7 @@ async function auth() {
|
|
|
17095
17246
|
};
|
|
17096
17247
|
saveGlobalConfig(config);
|
|
17097
17248
|
console.log(
|
|
17098
|
-
|
|
17249
|
+
chalk159.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
17099
17250
|
);
|
|
17100
17251
|
}
|
|
17101
17252
|
|
|
@@ -17255,11 +17406,11 @@ function resolveParams(params, cliArgs) {
|
|
|
17255
17406
|
}
|
|
17256
17407
|
|
|
17257
17408
|
// src/commands/run/runPreCommands.ts
|
|
17258
|
-
import { execSync as
|
|
17409
|
+
import { execSync as execSync49 } from "child_process";
|
|
17259
17410
|
function runPreCommands(pre, cwd) {
|
|
17260
17411
|
for (const cmd of pre) {
|
|
17261
17412
|
try {
|
|
17262
|
-
|
|
17413
|
+
execSync49(cmd, { stdio: "inherit", cwd });
|
|
17263
17414
|
} catch (err) {
|
|
17264
17415
|
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
17265
17416
|
process.exit(code);
|
|
@@ -17543,11 +17694,11 @@ function registerRun(program2) {
|
|
|
17543
17694
|
}
|
|
17544
17695
|
|
|
17545
17696
|
// src/commands/screenshot/index.ts
|
|
17546
|
-
import { execSync as
|
|
17697
|
+
import { execSync as execSync50 } from "child_process";
|
|
17547
17698
|
import { existsSync as existsSync50, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
|
|
17548
17699
|
import { tmpdir as tmpdir7 } from "os";
|
|
17549
17700
|
import { join as join53, resolve as resolve13 } from "path";
|
|
17550
|
-
import
|
|
17701
|
+
import chalk160 from "chalk";
|
|
17551
17702
|
|
|
17552
17703
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
17553
17704
|
var captureWindowPs1 = `
|
|
@@ -17686,7 +17837,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
17686
17837
|
const scriptPath = join53(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
17687
17838
|
writeFileSync32(scriptPath, captureWindowPs1, "utf-8");
|
|
17688
17839
|
try {
|
|
17689
|
-
|
|
17840
|
+
execSync50(
|
|
17690
17841
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
17691
17842
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
17692
17843
|
);
|
|
@@ -17698,13 +17849,13 @@ function screenshot(processName) {
|
|
|
17698
17849
|
const config = loadConfig();
|
|
17699
17850
|
const outputDir = resolve13(config.screenshot.outputDir);
|
|
17700
17851
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
17701
|
-
console.log(
|
|
17852
|
+
console.log(chalk160.gray(`Capturing window for process "${processName}" ...`));
|
|
17702
17853
|
try {
|
|
17703
17854
|
runPowerShellScript(processName, outputPath);
|
|
17704
|
-
console.log(
|
|
17855
|
+
console.log(chalk160.green(`Screenshot saved: ${outputPath}`));
|
|
17705
17856
|
} catch (error) {
|
|
17706
17857
|
const msg = error instanceof Error ? error.message : String(error);
|
|
17707
|
-
console.error(
|
|
17858
|
+
console.error(chalk160.red(`Failed to capture screenshot: ${msg}`));
|
|
17708
17859
|
process.exit(1);
|
|
17709
17860
|
}
|
|
17710
17861
|
}
|
|
@@ -18604,8 +18755,8 @@ var SessionManager = class {
|
|
|
18604
18755
|
watchActivity(session, this.notify);
|
|
18605
18756
|
return session.id;
|
|
18606
18757
|
}
|
|
18607
|
-
spawnWith(
|
|
18608
|
-
return this.add(
|
|
18758
|
+
spawnWith(create) {
|
|
18759
|
+
return this.add(create(String(this.nextId++)));
|
|
18609
18760
|
}
|
|
18610
18761
|
spawn(prompt, cwd) {
|
|
18611
18762
|
return this.spawnWith((id) => createSession(id, prompt, cwd));
|
|
@@ -18984,7 +19135,7 @@ function registerDaemon(program2) {
|
|
|
18984
19135
|
|
|
18985
19136
|
// src/commands/sessions/summarise/index.ts
|
|
18986
19137
|
import * as fs31 from "fs";
|
|
18987
|
-
import
|
|
19138
|
+
import chalk161 from "chalk";
|
|
18988
19139
|
|
|
18989
19140
|
// src/commands/sessions/summarise/shared.ts
|
|
18990
19141
|
import * as fs29 from "fs";
|
|
@@ -19111,22 +19262,22 @@ ${firstMessage}`);
|
|
|
19111
19262
|
async function summarise4(options2) {
|
|
19112
19263
|
const files = await discoverSessionJsonlPaths();
|
|
19113
19264
|
if (files.length === 0) {
|
|
19114
|
-
console.log(
|
|
19265
|
+
console.log(chalk161.yellow("No sessions found."));
|
|
19115
19266
|
return;
|
|
19116
19267
|
}
|
|
19117
19268
|
const toProcess = selectCandidates(files, options2);
|
|
19118
19269
|
if (toProcess.length === 0) {
|
|
19119
|
-
console.log(
|
|
19270
|
+
console.log(chalk161.green("All sessions already summarised."));
|
|
19120
19271
|
return;
|
|
19121
19272
|
}
|
|
19122
19273
|
console.log(
|
|
19123
|
-
|
|
19274
|
+
chalk161.cyan(
|
|
19124
19275
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
19125
19276
|
)
|
|
19126
19277
|
);
|
|
19127
19278
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
19128
19279
|
console.log(
|
|
19129
|
-
|
|
19280
|
+
chalk161.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk161.yellow(`, ${failed2} skipped`) : "")
|
|
19130
19281
|
);
|
|
19131
19282
|
}
|
|
19132
19283
|
function selectCandidates(files, options2) {
|
|
@@ -19146,16 +19297,16 @@ function processSessions(files) {
|
|
|
19146
19297
|
let failed2 = 0;
|
|
19147
19298
|
for (let i = 0; i < files.length; i++) {
|
|
19148
19299
|
const file = files[i];
|
|
19149
|
-
process.stdout.write(
|
|
19300
|
+
process.stdout.write(chalk161.dim(` [${i + 1}/${files.length}] `));
|
|
19150
19301
|
const summary = summariseSession(file);
|
|
19151
19302
|
if (summary) {
|
|
19152
19303
|
writeSummary(file, summary);
|
|
19153
19304
|
succeeded++;
|
|
19154
|
-
process.stdout.write(`${
|
|
19305
|
+
process.stdout.write(`${chalk161.green("\u2713")} ${summary}
|
|
19155
19306
|
`);
|
|
19156
19307
|
} else {
|
|
19157
19308
|
failed2++;
|
|
19158
|
-
process.stdout.write(` ${
|
|
19309
|
+
process.stdout.write(` ${chalk161.yellow("skip")}
|
|
19159
19310
|
`);
|
|
19160
19311
|
}
|
|
19161
19312
|
}
|
|
@@ -19164,16 +19315,16 @@ function processSessions(files) {
|
|
|
19164
19315
|
|
|
19165
19316
|
// src/commands/sessions/registerSessions.ts
|
|
19166
19317
|
function registerSessions(program2) {
|
|
19167
|
-
const cmd = program2.command("sessions").description("Web dashboard for Claude Code sessions").action(() => web({ port: "3100" }));
|
|
19168
|
-
cmd.command("web").description("Start the sessions web dashboard").option("-p, --port <number>", "Port to listen on", "3100").action(web);
|
|
19318
|
+
const cmd = program2.command("sessions").description("Web dashboard for Claude Code sessions").option("--no-open", "Do not open a browser on startup").action((options2) => web({ port: "3100", open: options2.open }));
|
|
19319
|
+
cmd.command("web").description("Start the sessions web dashboard").option("-p, --port <number>", "Port to listen on", "3100").option("--no-open", "Do not open a browser on startup").action(web);
|
|
19169
19320
|
cmd.command("summarise").description("Generate one-line summaries for Claude sessions").option("-f, --force", "Re-generate all summaries, even existing ones").option("-n, --limit <count>", "Maximum number of sessions to summarise").action(summarise4);
|
|
19170
19321
|
}
|
|
19171
19322
|
|
|
19172
19323
|
// src/commands/statusLine.ts
|
|
19173
|
-
import
|
|
19324
|
+
import chalk163 from "chalk";
|
|
19174
19325
|
|
|
19175
19326
|
// src/commands/buildLimitsSegment.ts
|
|
19176
|
-
import
|
|
19327
|
+
import chalk162 from "chalk";
|
|
19177
19328
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
19178
19329
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
19179
19330
|
function formatTimeLeft(resetsAt) {
|
|
@@ -19196,10 +19347,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
19196
19347
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
19197
19348
|
const label2 = `${Math.round(pct)}%`;
|
|
19198
19349
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
19199
|
-
if (projected == null) return
|
|
19200
|
-
if (projected > 100) return
|
|
19201
|
-
if (projected > 75) return
|
|
19202
|
-
return
|
|
19350
|
+
if (projected == null) return chalk162.green(label2);
|
|
19351
|
+
if (projected > 100) return chalk162.red(label2);
|
|
19352
|
+
if (projected > 75) return chalk162.yellow(label2);
|
|
19353
|
+
return chalk162.green(label2);
|
|
19203
19354
|
}
|
|
19204
19355
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
19205
19356
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -19225,14 +19376,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
19225
19376
|
}
|
|
19226
19377
|
|
|
19227
19378
|
// src/commands/statusLine.ts
|
|
19228
|
-
|
|
19379
|
+
chalk163.level = 3;
|
|
19229
19380
|
function formatNumber(num) {
|
|
19230
19381
|
return num.toLocaleString("en-US");
|
|
19231
19382
|
}
|
|
19232
19383
|
function colorizePercent(pct) {
|
|
19233
19384
|
const label2 = `${Math.round(pct)}%`;
|
|
19234
|
-
if (pct > 80) return
|
|
19235
|
-
if (pct > 40) return
|
|
19385
|
+
if (pct > 80) return chalk163.red(label2);
|
|
19386
|
+
if (pct > 40) return chalk163.yellow(label2);
|
|
19236
19387
|
return label2;
|
|
19237
19388
|
}
|
|
19238
19389
|
async function statusLine() {
|
|
@@ -19255,7 +19406,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
19255
19406
|
// src/commands/sync/syncClaudeMd.ts
|
|
19256
19407
|
import * as fs32 from "fs";
|
|
19257
19408
|
import * as path50 from "path";
|
|
19258
|
-
import
|
|
19409
|
+
import chalk164 from "chalk";
|
|
19259
19410
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
19260
19411
|
const source = path50.join(claudeDir, "CLAUDE.md");
|
|
19261
19412
|
const target = path50.join(targetBase, "CLAUDE.md");
|
|
@@ -19264,12 +19415,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
19264
19415
|
const targetContent = fs32.readFileSync(target, "utf-8");
|
|
19265
19416
|
if (sourceContent !== targetContent) {
|
|
19266
19417
|
console.log(
|
|
19267
|
-
|
|
19418
|
+
chalk164.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
19268
19419
|
);
|
|
19269
19420
|
console.log();
|
|
19270
19421
|
printDiff(targetContent, sourceContent);
|
|
19271
19422
|
const confirm = options2?.yes || await promptConfirm(
|
|
19272
|
-
|
|
19423
|
+
chalk164.red("Overwrite existing CLAUDE.md?"),
|
|
19273
19424
|
false
|
|
19274
19425
|
);
|
|
19275
19426
|
if (!confirm) {
|
|
@@ -19285,7 +19436,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
19285
19436
|
// src/commands/sync/syncSettings.ts
|
|
19286
19437
|
import * as fs33 from "fs";
|
|
19287
19438
|
import * as path51 from "path";
|
|
19288
|
-
import
|
|
19439
|
+
import chalk165 from "chalk";
|
|
19289
19440
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
19290
19441
|
const source = path51.join(claudeDir, "settings.json");
|
|
19291
19442
|
const target = path51.join(targetBase, "settings.json");
|
|
@@ -19301,14 +19452,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
19301
19452
|
if (mergedContent !== normalizedTarget) {
|
|
19302
19453
|
if (!options2?.yes) {
|
|
19303
19454
|
console.log(
|
|
19304
|
-
|
|
19455
|
+
chalk165.yellow(
|
|
19305
19456
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
19306
19457
|
)
|
|
19307
19458
|
);
|
|
19308
19459
|
console.log();
|
|
19309
19460
|
printDiff(targetContent, mergedContent);
|
|
19310
19461
|
const confirm = await promptConfirm(
|
|
19311
|
-
|
|
19462
|
+
chalk165.red("Overwrite existing settings.json?"),
|
|
19312
19463
|
false
|
|
19313
19464
|
);
|
|
19314
19465
|
if (!confirm) {
|
|
@@ -19347,7 +19498,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
19347
19498
|
}
|
|
19348
19499
|
|
|
19349
19500
|
// src/commands/update.ts
|
|
19350
|
-
import { execSync as
|
|
19501
|
+
import { execSync as execSync51 } from "child_process";
|
|
19351
19502
|
import * as path53 from "path";
|
|
19352
19503
|
function isGlobalNpmInstall(dir) {
|
|
19353
19504
|
try {
|
|
@@ -19355,7 +19506,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
19355
19506
|
if (resolved.split(path53.sep).includes("node_modules")) {
|
|
19356
19507
|
return true;
|
|
19357
19508
|
}
|
|
19358
|
-
const globalPrefix =
|
|
19509
|
+
const globalPrefix = execSync51("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
19359
19510
|
return resolved.toLowerCase().startsWith(path53.resolve(globalPrefix).toLowerCase());
|
|
19360
19511
|
} catch {
|
|
19361
19512
|
return false;
|
|
@@ -19366,18 +19517,18 @@ async function update2() {
|
|
|
19366
19517
|
console.log(`Assist is installed at: ${installDir}`);
|
|
19367
19518
|
if (isGitRepo(installDir)) {
|
|
19368
19519
|
console.log("Detected git repo installation, pulling latest...");
|
|
19369
|
-
|
|
19520
|
+
execSync51("git pull", { cwd: installDir, stdio: "inherit" });
|
|
19370
19521
|
console.log("Installing dependencies...");
|
|
19371
|
-
|
|
19522
|
+
execSync51("npm i", { cwd: installDir, stdio: "inherit" });
|
|
19372
19523
|
console.log("Building...");
|
|
19373
|
-
|
|
19524
|
+
execSync51("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
19374
19525
|
console.log("Syncing commands...");
|
|
19375
|
-
|
|
19526
|
+
execSync51("assist sync", { stdio: "inherit" });
|
|
19376
19527
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
19377
19528
|
console.log("Detected global npm installation, updating...");
|
|
19378
|
-
|
|
19529
|
+
execSync51("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
19379
19530
|
console.log("Syncing commands...");
|
|
19380
|
-
|
|
19531
|
+
execSync51("assist sync", { stdio: "inherit" });
|
|
19381
19532
|
} else {
|
|
19382
19533
|
console.error(
|
|
19383
19534
|
"Could not determine installation method. Expected a git repo or global npm install."
|
|
@@ -19388,7 +19539,7 @@ async function update2() {
|
|
|
19388
19539
|
|
|
19389
19540
|
// src/index.ts
|
|
19390
19541
|
var program = new Command();
|
|
19391
|
-
program.name("assist").description("CLI application").version(package_default.version).action(() => web({ port: "3100" }));
|
|
19542
|
+
program.name("assist").description("CLI application").version(package_default.version).option("--no-open", "Do not open a browser on startup").action((options2) => web({ port: "3100", open: options2.open }));
|
|
19392
19543
|
program.command("sync").description("Copy command files to ~/.claude/commands").option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
|
|
19393
19544
|
program.command("init").description("Initialize VS Code and verify configurations").action(init4);
|
|
19394
19545
|
program.command("commit").description("Create a git commit with validation").argument("<args...>", "status | <message> [files...]").action(commit);
|