@staff0rd/assist 0.281.3 → 0.282.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -5
- package/claude/commands/pr.md +14 -2
- package/dist/commands/sessions/web/bundle.js +62 -62
- package/dist/index.js +727 -562
- 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.1",
|
|
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,11 +515,45 @@ 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
524
|
async function ensureSchema(exec3) {
|
|
517
525
|
await exec3(SCHEMA);
|
|
518
526
|
}
|
|
519
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
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
520
557
|
// src/commands/backlog/getBacklogOrm.ts
|
|
521
558
|
var DATABASE_URL_ENV = "ASSIST_BACKLOG_DATABASE_URL";
|
|
522
559
|
var MISSING_URL_MESSAGE = `No backlog database configured.
|
|
@@ -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
|
|
|
@@ -4395,20 +4433,20 @@ function respondJson(res, status2, data) {
|
|
|
4395
4433
|
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
4396
4434
|
res.end(JSON.stringify(data));
|
|
4397
4435
|
}
|
|
4398
|
-
function createHtmlHandler(
|
|
4436
|
+
function createHtmlHandler(getHtml2) {
|
|
4399
4437
|
return (_req, res) => {
|
|
4400
4438
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
4401
|
-
res.end(
|
|
4439
|
+
res.end(getHtml2());
|
|
4402
4440
|
};
|
|
4403
4441
|
}
|
|
4404
4442
|
function parseRoute(req, port) {
|
|
4405
4443
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
4406
4444
|
return { method: req.method ?? "GET", pathname: url.pathname };
|
|
4407
4445
|
}
|
|
4408
|
-
function createRouteHandler(
|
|
4446
|
+
function createRouteHandler(routes2) {
|
|
4409
4447
|
return async (req, res, port) => {
|
|
4410
4448
|
const { method, pathname } = parseRoute(req, port);
|
|
4411
|
-
const handler =
|
|
4449
|
+
const handler = routes2[`${method} ${pathname}`];
|
|
4412
4450
|
if (handler) {
|
|
4413
4451
|
await handler(req, res);
|
|
4414
4452
|
return;
|
|
@@ -4570,12 +4608,12 @@ function createBundleHandler(importMetaUrl, bundlePath) {
|
|
|
4570
4608
|
}
|
|
4571
4609
|
|
|
4572
4610
|
// src/shared/createFallbackHandler.ts
|
|
4573
|
-
function createFallbackHandler(
|
|
4574
|
-
const baseHandler = createRouteHandler(
|
|
4611
|
+
function createFallbackHandler(routes2, htmlHandler2, extra) {
|
|
4612
|
+
const baseHandler = createRouteHandler(routes2);
|
|
4575
4613
|
return async (req, res, port) => {
|
|
4576
4614
|
const { method, pathname } = parseRoute(req, port);
|
|
4577
4615
|
if (extra && await extra(req, res, pathname)) return;
|
|
4578
|
-
if (
|
|
4616
|
+
if (routes2[`${method} ${pathname}`]) {
|
|
4579
4617
|
await baseHandler(req, res, port);
|
|
4580
4618
|
return;
|
|
4581
4619
|
}
|
|
@@ -4634,7 +4672,7 @@ async function createItem(req, res) {
|
|
|
4634
4672
|
import { eq as eq11 } from "drizzle-orm";
|
|
4635
4673
|
|
|
4636
4674
|
// src/commands/backlog/loadItemSummaries.ts
|
|
4637
|
-
import { asc as
|
|
4675
|
+
import { asc as asc5, eq as eq10 } from "drizzle-orm";
|
|
4638
4676
|
async function loadItemSummaries(orm, origin) {
|
|
4639
4677
|
const rows = await orm.select({
|
|
4640
4678
|
id: items.id,
|
|
@@ -4642,7 +4680,7 @@ async function loadItemSummaries(orm, origin) {
|
|
|
4642
4680
|
type: items.type,
|
|
4643
4681
|
name: items.name,
|
|
4644
4682
|
status: items.status
|
|
4645
|
-
}).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));
|
|
4646
4684
|
return rows.map((row) => ({
|
|
4647
4685
|
id: row.id,
|
|
4648
4686
|
origin: row.origin,
|
|
@@ -5008,6 +5046,129 @@ function gitStatus(req, res) {
|
|
|
5008
5046
|
}
|
|
5009
5047
|
}
|
|
5010
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
|
+
|
|
5011
5172
|
// src/commands/sessions/web/openInCode.ts
|
|
5012
5173
|
import { exec } from "child_process";
|
|
5013
5174
|
import { promisify } from "util";
|
|
@@ -5052,7 +5213,8 @@ var routes = {
|
|
|
5052
5213
|
"POST /api/backlog/init": initBacklog,
|
|
5053
5214
|
"POST /api/open-in-code": openInCode,
|
|
5054
5215
|
"GET /api/github-url": githubUrl,
|
|
5055
|
-
"GET /api/git-status": gitStatus
|
|
5216
|
+
"GET /api/git-status": gitStatus,
|
|
5217
|
+
"GET /api/news/items": listNewsItems
|
|
5056
5218
|
};
|
|
5057
5219
|
var handleRequest = createFallbackHandler(
|
|
5058
5220
|
routes,
|
|
@@ -6621,9 +6783,9 @@ async function findPhase(id, phase) {
|
|
|
6621
6783
|
}
|
|
6622
6784
|
|
|
6623
6785
|
// src/commands/backlog/reindexPhases.ts
|
|
6624
|
-
import { and as and7, asc as
|
|
6786
|
+
import { and as and7, asc as asc6, count as count5, eq as eq24 } from "drizzle-orm";
|
|
6625
6787
|
async function reindexPhases(db, itemId) {
|
|
6626
|
-
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));
|
|
6627
6789
|
for (let i = 0; i < remaining.length; i++) {
|
|
6628
6790
|
const oldIdx = remaining[i].idx;
|
|
6629
6791
|
if (oldIdx === i) continue;
|
|
@@ -7111,6 +7273,47 @@ function stripEnvPrefix(parts) {
|
|
|
7111
7273
|
return i > 0 ? parts.slice(i) : parts;
|
|
7112
7274
|
}
|
|
7113
7275
|
|
|
7276
|
+
// src/commands/cliHook/findBuiltinDeny.ts
|
|
7277
|
+
var BUILTIN_DENIES = [
|
|
7278
|
+
{
|
|
7279
|
+
pattern: "gh pr create",
|
|
7280
|
+
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."
|
|
7281
|
+
},
|
|
7282
|
+
{
|
|
7283
|
+
pattern: "git commit",
|
|
7284
|
+
message: `Do not run 'git commit' directly. Use 'assist commit "<message>"' instead.`
|
|
7285
|
+
}
|
|
7286
|
+
];
|
|
7287
|
+
function matchesBuiltinDeny(part) {
|
|
7288
|
+
return BUILTIN_DENIES.find(
|
|
7289
|
+
(rule) => part === rule.pattern || part.startsWith(`${rule.pattern} `)
|
|
7290
|
+
);
|
|
7291
|
+
}
|
|
7292
|
+
function findBuiltinDeny(parts) {
|
|
7293
|
+
const rule = parts.map(matchesBuiltinDeny).find(Boolean);
|
|
7294
|
+
if (!rule) return void 0;
|
|
7295
|
+
return {
|
|
7296
|
+
permissionDecision: "deny",
|
|
7297
|
+
permissionDecisionReason: rule.message
|
|
7298
|
+
};
|
|
7299
|
+
}
|
|
7300
|
+
function rawDenyRegex(pattern2) {
|
|
7301
|
+
const tokens = pattern2.trim().split(/\s+/).map((token) => token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("\\s+");
|
|
7302
|
+
return new RegExp(`(?<=^|\\s)${tokens}(?=\\s|$)`);
|
|
7303
|
+
}
|
|
7304
|
+
var RAW_BUILTIN_DENIES = BUILTIN_DENIES.map((rule) => ({
|
|
7305
|
+
...rule,
|
|
7306
|
+
regex: rawDenyRegex(rule.pattern)
|
|
7307
|
+
}));
|
|
7308
|
+
function findBuiltinDenyRaw(rawCommand) {
|
|
7309
|
+
const rule = RAW_BUILTIN_DENIES.find((r) => r.regex.test(rawCommand));
|
|
7310
|
+
if (!rule) return void 0;
|
|
7311
|
+
return {
|
|
7312
|
+
permissionDecision: "deny",
|
|
7313
|
+
permissionDecisionReason: rule.message
|
|
7314
|
+
};
|
|
7315
|
+
}
|
|
7316
|
+
|
|
7114
7317
|
// src/commands/cliHook/logDeniedToolCall.ts
|
|
7115
7318
|
import { mkdirSync as mkdirSync8 } from "fs";
|
|
7116
7319
|
import { homedir as homedir7 } from "os";
|
|
@@ -7429,31 +7632,6 @@ function matchesConfigDeny(command) {
|
|
|
7429
7632
|
);
|
|
7430
7633
|
}
|
|
7431
7634
|
|
|
7432
|
-
// src/commands/cliHook/findBuiltinDeny.ts
|
|
7433
|
-
var BUILTIN_DENIES = [
|
|
7434
|
-
{
|
|
7435
|
-
pattern: "gh pr create",
|
|
7436
|
-
message: "Do not run 'gh pr create' directly. Use 'assist prs create --title <title> --body <body>' instead \u2014 it validates the title and body before delegating to gh pr create. 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."
|
|
7437
|
-
},
|
|
7438
|
-
{
|
|
7439
|
-
pattern: "git commit",
|
|
7440
|
-
message: `Do not run 'git commit' directly. Use 'assist commit "<message>"' instead.`
|
|
7441
|
-
}
|
|
7442
|
-
];
|
|
7443
|
-
function matchesBuiltinDeny(part) {
|
|
7444
|
-
return BUILTIN_DENIES.find(
|
|
7445
|
-
(rule) => part === rule.pattern || part.startsWith(`${rule.pattern} `)
|
|
7446
|
-
);
|
|
7447
|
-
}
|
|
7448
|
-
function findBuiltinDeny(parts) {
|
|
7449
|
-
const rule = parts.map(matchesBuiltinDeny).find(Boolean);
|
|
7450
|
-
if (!rule) return void 0;
|
|
7451
|
-
return {
|
|
7452
|
-
permissionDecision: "deny",
|
|
7453
|
-
permissionDecisionReason: rule.message
|
|
7454
|
-
};
|
|
7455
|
-
}
|
|
7456
|
-
|
|
7457
7635
|
// src/commands/cliHook/resolvePermission.ts
|
|
7458
7636
|
var SUBCOMMAND_READS = [
|
|
7459
7637
|
{
|
|
@@ -7537,7 +7715,7 @@ function tryParseInput(raw) {
|
|
|
7537
7715
|
function decide(toolName, rawCommand) {
|
|
7538
7716
|
const result = splitCompound(rawCommand);
|
|
7539
7717
|
if (result.ok) return resolvePermission(toolName, result.parts);
|
|
7540
|
-
return findDeny(toolName, [rawCommand]);
|
|
7718
|
+
return findBuiltinDenyRaw(rawCommand) ?? findDeny(toolName, [rawCommand]);
|
|
7541
7719
|
}
|
|
7542
7720
|
async function cliHook() {
|
|
7543
7721
|
const input = tryParseInput(await readStdin());
|
|
@@ -7564,17 +7742,20 @@ async function cliHook() {
|
|
|
7564
7742
|
}
|
|
7565
7743
|
|
|
7566
7744
|
// src/commands/cliHook/cliHookCheck.ts
|
|
7567
|
-
function
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
console.log(`denied: ${denied.permissionDecisionReason}`);
|
|
7745
|
+
function reportDecision(decision) {
|
|
7746
|
+
if (!decision) return false;
|
|
7747
|
+
console.log(`denied: ${decision.permissionDecisionReason}`);
|
|
7571
7748
|
process.exitCode = 1;
|
|
7572
7749
|
return true;
|
|
7573
7750
|
}
|
|
7751
|
+
function reportDeny(toolName, parts) {
|
|
7752
|
+
return reportDecision(findDeny(toolName, parts));
|
|
7753
|
+
}
|
|
7574
7754
|
function cliHookCheck(command, toolName = "Bash") {
|
|
7575
7755
|
const trimmed = command.trim();
|
|
7576
7756
|
const result = splitCompound(trimmed);
|
|
7577
7757
|
if (!result.ok) {
|
|
7758
|
+
if (reportDecision(findBuiltinDenyRaw(trimmed))) return;
|
|
7578
7759
|
if (reportDeny(toolName, [trimmed])) return;
|
|
7579
7760
|
console.log(`not approved (${result.error})`);
|
|
7580
7761
|
process.exitCode = 1;
|
|
@@ -10729,257 +10910,68 @@ async function add2(url) {
|
|
|
10729
10910
|
});
|
|
10730
10911
|
url = response.url;
|
|
10731
10912
|
}
|
|
10732
|
-
const
|
|
10733
|
-
const
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
console.log(chalk118.yellow("Feed already exists in config"));
|
|
10913
|
+
const { orm } = await getReady();
|
|
10914
|
+
const added = await addFeed(orm, url);
|
|
10915
|
+
if (!added) {
|
|
10916
|
+
console.log(chalk118.yellow("Feed already exists"));
|
|
10737
10917
|
return;
|
|
10738
10918
|
}
|
|
10739
|
-
feeds.push(url);
|
|
10740
|
-
config.news = { ...news, feeds };
|
|
10741
|
-
saveGlobalConfig(config);
|
|
10742
10919
|
console.log(chalk118.green(`Added feed: ${url}`));
|
|
10743
10920
|
}
|
|
10744
10921
|
|
|
10745
|
-
// src/commands/
|
|
10746
|
-
|
|
10922
|
+
// src/commands/registerNews.ts
|
|
10923
|
+
function registerNews(program2) {
|
|
10924
|
+
const newsCommand = program2.command("news").description("Manage RSS news feeds");
|
|
10925
|
+
newsCommand.command("add").description("Add an RSS feed URL").argument("<url>", "RSS feed URL").action(add2);
|
|
10926
|
+
}
|
|
10747
10927
|
|
|
10748
|
-
// src/commands/
|
|
10749
|
-
import
|
|
10750
|
-
function
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
);
|
|
10754
|
-
if (cdataMatch) return cdataMatch[1].trim();
|
|
10755
|
-
const match = xml.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`));
|
|
10756
|
-
return match ? match[1].trim() : "";
|
|
10928
|
+
// src/commands/prompts/printPromptsTable.ts
|
|
10929
|
+
import chalk119 from "chalk";
|
|
10930
|
+
function truncate(str, max) {
|
|
10931
|
+
if (str.length <= max) return str;
|
|
10932
|
+
return `${str.slice(0, max - 1)}\u2026`;
|
|
10757
10933
|
}
|
|
10758
|
-
function
|
|
10759
|
-
const
|
|
10760
|
-
|
|
10934
|
+
function printPromptsTable(rows) {
|
|
10935
|
+
const countWidth = 5;
|
|
10936
|
+
const toolWidth = Math.max(4, ...rows.map((r) => r.tool.length));
|
|
10937
|
+
const commandWidth = Math.max(
|
|
10938
|
+
7,
|
|
10939
|
+
...rows.map((r) => truncate(r.command, 60).length)
|
|
10761
10940
|
);
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
|
|
10941
|
+
const header = [
|
|
10942
|
+
"#".padStart(countWidth),
|
|
10943
|
+
"Tool".padEnd(toolWidth),
|
|
10944
|
+
"Command".padEnd(commandWidth),
|
|
10945
|
+
"Repos"
|
|
10946
|
+
].join(" ");
|
|
10947
|
+
console.log(chalk119.dim(header));
|
|
10948
|
+
console.log(chalk119.dim("-".repeat(header.length)));
|
|
10949
|
+
for (const row of rows) {
|
|
10950
|
+
const count6 = String(row.count).padStart(countWidth);
|
|
10951
|
+
const tool = row.tool.padEnd(toolWidth);
|
|
10952
|
+
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
10953
|
+
console.log(
|
|
10954
|
+
`${chalk119.yellow(count6)} ${tool} ${command} ${chalk119.dim(row.repos)}`
|
|
10955
|
+
);
|
|
10956
|
+
}
|
|
10766
10957
|
}
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
10958
|
+
|
|
10959
|
+
// src/commands/prompts/prompts.ts
|
|
10960
|
+
function prompts2() {
|
|
10961
|
+
const db = openPromptsDb();
|
|
10962
|
+
const rows = db.prepare(
|
|
10963
|
+
`SELECT tool, command, COUNT(*) as count,
|
|
10964
|
+
GROUP_CONCAT(DISTINCT repo) as repos
|
|
10965
|
+
FROM denied_tool_calls
|
|
10966
|
+
GROUP BY tool, command
|
|
10967
|
+
ORDER BY count DESC
|
|
10968
|
+
LIMIT 10`
|
|
10969
|
+
).all();
|
|
10970
|
+
if (rows.length === 0) {
|
|
10971
|
+
console.log("No denied tool calls recorded yet.");
|
|
10972
|
+
return;
|
|
10773
10973
|
}
|
|
10774
|
-
|
|
10775
|
-
function stripHtml(html) {
|
|
10776
|
-
const decoded = decodeHTML(html);
|
|
10777
|
-
const stripped = decoded.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
10778
|
-
return decodeHTML(stripped);
|
|
10779
|
-
}
|
|
10780
|
-
function matchAll(xml, regex) {
|
|
10781
|
-
const results = [];
|
|
10782
|
-
for (const m of xml.matchAll(regex)) {
|
|
10783
|
-
results.push(m[1]);
|
|
10784
|
-
}
|
|
10785
|
-
return results;
|
|
10786
|
-
}
|
|
10787
|
-
var MAX_EXCERPT = 500;
|
|
10788
|
-
function excerpt(xml, ...tags) {
|
|
10789
|
-
for (const tag of tags) {
|
|
10790
|
-
const raw = extractText(xml, tag);
|
|
10791
|
-
if (!raw) continue;
|
|
10792
|
-
const text3 = stripHtml(raw);
|
|
10793
|
-
if (text3.length <= MAX_EXCERPT) return text3;
|
|
10794
|
-
return `${text3.slice(0, MAX_EXCERPT)}\u2026`;
|
|
10795
|
-
}
|
|
10796
|
-
return "";
|
|
10797
|
-
}
|
|
10798
|
-
|
|
10799
|
-
// src/commands/news/web/parseFeed.ts
|
|
10800
|
-
function parseRss(xml, feedOrigin) {
|
|
10801
|
-
const feedTitle = extractText(xml, "title");
|
|
10802
|
-
return matchAll(xml, /<item[\s>]([\s\S]*?)<\/item>/g).map((itemXml) => ({
|
|
10803
|
-
title: extractText(itemXml, "title"),
|
|
10804
|
-
link: extractLink(itemXml),
|
|
10805
|
-
pubDate: parseDate(
|
|
10806
|
-
extractText(itemXml, "pubDate") || extractText(itemXml, "dc:date")
|
|
10807
|
-
),
|
|
10808
|
-
feedTitle,
|
|
10809
|
-
feedOrigin,
|
|
10810
|
-
excerpt: excerpt(itemXml, "description", "content:encoded")
|
|
10811
|
-
}));
|
|
10812
|
-
}
|
|
10813
|
-
function parseAtom(xml, feedOrigin) {
|
|
10814
|
-
const feedTitle = extractText(xml, "title");
|
|
10815
|
-
return matchAll(xml, /<entry[\s>]([\s\S]*?)<\/entry>/g).map((entryXml) => ({
|
|
10816
|
-
title: extractText(entryXml, "title"),
|
|
10817
|
-
link: extractLink(entryXml),
|
|
10818
|
-
pubDate: parseDate(
|
|
10819
|
-
extractText(entryXml, "published") || extractText(entryXml, "updated")
|
|
10820
|
-
),
|
|
10821
|
-
feedTitle,
|
|
10822
|
-
feedOrigin,
|
|
10823
|
-
excerpt: excerpt(entryXml, "summary", "content")
|
|
10824
|
-
}));
|
|
10825
|
-
}
|
|
10826
|
-
function parseFeed(xml, feedOrigin) {
|
|
10827
|
-
if (xml.includes("<feed")) return parseAtom(xml, feedOrigin);
|
|
10828
|
-
return parseRss(xml, feedOrigin);
|
|
10829
|
-
}
|
|
10830
|
-
|
|
10831
|
-
// src/commands/news/web/fetchFeeds.ts
|
|
10832
|
-
async function fetchFeeds(urls, onProgress) {
|
|
10833
|
-
let done2 = 0;
|
|
10834
|
-
const results = await Promise.allSettled(
|
|
10835
|
-
urls.map(async (url) => {
|
|
10836
|
-
const origin = new URL(url).origin;
|
|
10837
|
-
const res = await fetch(url);
|
|
10838
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
10839
|
-
const items3 = parseFeed(await res.text(), origin);
|
|
10840
|
-
done2++;
|
|
10841
|
-
onProgress?.(done2, urls.length);
|
|
10842
|
-
return items3;
|
|
10843
|
-
})
|
|
10844
|
-
);
|
|
10845
|
-
const items2 = [];
|
|
10846
|
-
for (const result of results) {
|
|
10847
|
-
if (result.status === "fulfilled") {
|
|
10848
|
-
items2.push(...result.value);
|
|
10849
|
-
}
|
|
10850
|
-
}
|
|
10851
|
-
items2.sort(
|
|
10852
|
-
(a, b) => new Date(b.pubDate).getTime() - new Date(a.pubDate).getTime()
|
|
10853
|
-
);
|
|
10854
|
-
return items2;
|
|
10855
|
-
}
|
|
10856
|
-
|
|
10857
|
-
// src/commands/news/web/getHtml.ts
|
|
10858
|
-
function getHtml2() {
|
|
10859
|
-
return `<!DOCTYPE html>
|
|
10860
|
-
<html lang="en" class="dark">
|
|
10861
|
-
<head>
|
|
10862
|
-
<meta charset="UTF-8">
|
|
10863
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
10864
|
-
<title>News</title>
|
|
10865
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
|
10866
|
-
<script>tailwind.config={darkMode:'class'}</script>
|
|
10867
|
-
</head>
|
|
10868
|
-
<body class="font-[-apple-system,BlinkMacSystemFont,'Segoe_UI',Roboto,sans-serif] bg-gray-950 text-gray-200 leading-normal">
|
|
10869
|
-
<div class="max-w-3xl mx-auto px-4 py-6" id="app"></div>
|
|
10870
|
-
<script src="/bundle.js"></script>
|
|
10871
|
-
</body>
|
|
10872
|
-
</html>`;
|
|
10873
|
-
}
|
|
10874
|
-
|
|
10875
|
-
// src/commands/news/web/handleRequest.ts
|
|
10876
|
-
var cachedItems;
|
|
10877
|
-
var prefetchPromise;
|
|
10878
|
-
function prefetch() {
|
|
10879
|
-
const config = loadConfig();
|
|
10880
|
-
const total = config.news.feeds.length;
|
|
10881
|
-
if (total === 0) return;
|
|
10882
|
-
process.stdout.write(chalk119.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
10883
|
-
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
10884
|
-
const width = 20;
|
|
10885
|
-
const filled = Math.round(done2 / t * width);
|
|
10886
|
-
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
10887
|
-
process.stdout.write(
|
|
10888
|
-
`\r${chalk119.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
10889
|
-
);
|
|
10890
|
-
}).then((items2) => {
|
|
10891
|
-
process.stdout.write(
|
|
10892
|
-
`\r${chalk119.green(`Fetched ${items2.length} items from ${total} feed(s)`)}
|
|
10893
|
-
`
|
|
10894
|
-
);
|
|
10895
|
-
cachedItems = items2;
|
|
10896
|
-
return items2;
|
|
10897
|
-
});
|
|
10898
|
-
}
|
|
10899
|
-
async function listItems2(_req, res) {
|
|
10900
|
-
if (!cachedItems && prefetchPromise) {
|
|
10901
|
-
await prefetchPromise;
|
|
10902
|
-
}
|
|
10903
|
-
if (!cachedItems) {
|
|
10904
|
-
const config = loadConfig();
|
|
10905
|
-
cachedItems = await fetchFeeds(config.news.feeds);
|
|
10906
|
-
}
|
|
10907
|
-
respondJson(res, 200, cachedItems);
|
|
10908
|
-
}
|
|
10909
|
-
var routes2 = {
|
|
10910
|
-
"GET /": createHtmlHandler(getHtml2),
|
|
10911
|
-
"GET /bundle.js": createBundleHandler(
|
|
10912
|
-
import.meta.url,
|
|
10913
|
-
"commands/news/web/bundle.js"
|
|
10914
|
-
),
|
|
10915
|
-
"GET /api/items": listItems2
|
|
10916
|
-
};
|
|
10917
|
-
var handleRequest2 = createRouteHandler(routes2);
|
|
10918
|
-
|
|
10919
|
-
// src/commands/news/web/index.ts
|
|
10920
|
-
async function web3(options2) {
|
|
10921
|
-
prefetch();
|
|
10922
|
-
startWebServer(
|
|
10923
|
-
"News web view",
|
|
10924
|
-
Number.parseInt(options2.port, 10),
|
|
10925
|
-
handleRequest2
|
|
10926
|
-
);
|
|
10927
|
-
}
|
|
10928
|
-
|
|
10929
|
-
// src/commands/registerNews.ts
|
|
10930
|
-
function registerNews(program2) {
|
|
10931
|
-
const newsCommand = program2.command("news").description("View latest news from configured RSS feeds").action(() => web3({ port: "3001" }));
|
|
10932
|
-
newsCommand.command("add").description("Add an RSS feed URL to the config").argument("<url>", "RSS feed URL").action(add2);
|
|
10933
|
-
newsCommand.command("web").description("Start a web view of the news feeds").option("-p, --port <number>", "Port to listen on", "3001").action(web3);
|
|
10934
|
-
}
|
|
10935
|
-
|
|
10936
|
-
// src/commands/prompts/printPromptsTable.ts
|
|
10937
|
-
import chalk120 from "chalk";
|
|
10938
|
-
function truncate(str, max) {
|
|
10939
|
-
if (str.length <= max) return str;
|
|
10940
|
-
return `${str.slice(0, max - 1)}\u2026`;
|
|
10941
|
-
}
|
|
10942
|
-
function printPromptsTable(rows) {
|
|
10943
|
-
const countWidth = 5;
|
|
10944
|
-
const toolWidth = Math.max(4, ...rows.map((r) => r.tool.length));
|
|
10945
|
-
const commandWidth = Math.max(
|
|
10946
|
-
7,
|
|
10947
|
-
...rows.map((r) => truncate(r.command, 60).length)
|
|
10948
|
-
);
|
|
10949
|
-
const header = [
|
|
10950
|
-
"#".padStart(countWidth),
|
|
10951
|
-
"Tool".padEnd(toolWidth),
|
|
10952
|
-
"Command".padEnd(commandWidth),
|
|
10953
|
-
"Repos"
|
|
10954
|
-
].join(" ");
|
|
10955
|
-
console.log(chalk120.dim(header));
|
|
10956
|
-
console.log(chalk120.dim("-".repeat(header.length)));
|
|
10957
|
-
for (const row of rows) {
|
|
10958
|
-
const count6 = String(row.count).padStart(countWidth);
|
|
10959
|
-
const tool = row.tool.padEnd(toolWidth);
|
|
10960
|
-
const command = truncate(row.command, 60).padEnd(commandWidth);
|
|
10961
|
-
console.log(
|
|
10962
|
-
`${chalk120.yellow(count6)} ${tool} ${command} ${chalk120.dim(row.repos)}`
|
|
10963
|
-
);
|
|
10964
|
-
}
|
|
10965
|
-
}
|
|
10966
|
-
|
|
10967
|
-
// src/commands/prompts/prompts.ts
|
|
10968
|
-
function prompts2() {
|
|
10969
|
-
const db = openPromptsDb();
|
|
10970
|
-
const rows = db.prepare(
|
|
10971
|
-
`SELECT tool, command, COUNT(*) as count,
|
|
10972
|
-
GROUP_CONCAT(DISTINCT repo) as repos
|
|
10973
|
-
FROM denied_tool_calls
|
|
10974
|
-
GROUP BY tool, command
|
|
10975
|
-
ORDER BY count DESC
|
|
10976
|
-
LIMIT 10`
|
|
10977
|
-
).all();
|
|
10978
|
-
if (rows.length === 0) {
|
|
10979
|
-
console.log("No denied tool calls recorded yet.");
|
|
10980
|
-
return;
|
|
10981
|
-
}
|
|
10982
|
-
printPromptsTable(rows);
|
|
10974
|
+
printPromptsTable(rows);
|
|
10983
10975
|
}
|
|
10984
10976
|
|
|
10985
10977
|
// src/commands/registerPrompts.ts
|
|
@@ -11035,6 +11027,17 @@ function getCurrentPrNumber() {
|
|
|
11035
11027
|
throw error;
|
|
11036
11028
|
}
|
|
11037
11029
|
}
|
|
11030
|
+
function getCurrentPr() {
|
|
11031
|
+
try {
|
|
11032
|
+
return viewCurrentPr("number,body");
|
|
11033
|
+
} catch (error) {
|
|
11034
|
+
if (error instanceof Error && error.message.includes("no pull requests")) {
|
|
11035
|
+
console.error("Error: No pull request found for the current branch.");
|
|
11036
|
+
process.exit(1);
|
|
11037
|
+
}
|
|
11038
|
+
throw error;
|
|
11039
|
+
}
|
|
11040
|
+
}
|
|
11038
11041
|
function getCurrentPrNodeId() {
|
|
11039
11042
|
try {
|
|
11040
11043
|
return viewCurrentPr("id").id;
|
|
@@ -11111,37 +11114,102 @@ function comment2(path54, line, body, startLine) {
|
|
|
11111
11114
|
}
|
|
11112
11115
|
}
|
|
11113
11116
|
|
|
11114
|
-
// src/commands/prs/
|
|
11117
|
+
// src/commands/prs/edit.ts
|
|
11115
11118
|
import { execSync as execSync33 } from "child_process";
|
|
11116
11119
|
|
|
11117
|
-
// src/commands/prs/
|
|
11118
|
-
function
|
|
11119
|
-
const
|
|
11120
|
-
|
|
11121
|
-
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
|
|
11128
|
-
];
|
|
11129
|
-
for (const [flag, value] of valueFlags) {
|
|
11130
|
-
if (value) args.push(`${flag} ${shellQuote(value)}`);
|
|
11120
|
+
// src/commands/prs/buildPrBody.ts
|
|
11121
|
+
function jiraBrowseUrl(key) {
|
|
11122
|
+
const { site } = loadJson("jira.json");
|
|
11123
|
+
return site ? `https://${site}/browse/${key}` : key;
|
|
11124
|
+
}
|
|
11125
|
+
function renderWhy(why, resolves) {
|
|
11126
|
+
if (resolves && resolves.length > 0) {
|
|
11127
|
+
const urls = resolves.map(jiraBrowseUrl).join(", ");
|
|
11128
|
+
return `${why}
|
|
11129
|
+
|
|
11130
|
+
Resolves ${urls}`;
|
|
11131
11131
|
}
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11137
|
-
|
|
11132
|
+
return why;
|
|
11133
|
+
}
|
|
11134
|
+
function buildPrBody(sections) {
|
|
11135
|
+
const parts = [
|
|
11136
|
+
`## What
|
|
11137
|
+
|
|
11138
|
+
${sections.what}`,
|
|
11139
|
+
`## Why
|
|
11140
|
+
|
|
11141
|
+
${renderWhy(sections.why, sections.resolves)}`
|
|
11138
11142
|
];
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11143
|
+
if (sections.how) {
|
|
11144
|
+
parts.push(`## How
|
|
11145
|
+
|
|
11146
|
+
${sections.how}`);
|
|
11147
|
+
}
|
|
11148
|
+
return parts.join("\n\n");
|
|
11149
|
+
}
|
|
11150
|
+
|
|
11151
|
+
// src/commands/prs/parsePrBody.ts
|
|
11152
|
+
function parsePrBody(body) {
|
|
11153
|
+
const sections = [];
|
|
11154
|
+
let current = null;
|
|
11155
|
+
const flush = () => {
|
|
11156
|
+
if (current) {
|
|
11157
|
+
sections.push({
|
|
11158
|
+
heading: current.heading,
|
|
11159
|
+
content: current.lines.join("\n").trim()
|
|
11160
|
+
});
|
|
11161
|
+
}
|
|
11162
|
+
};
|
|
11163
|
+
for (const line of body.split("\n")) {
|
|
11164
|
+
const match = /^##\s+(.+?)\s*$/.exec(line);
|
|
11165
|
+
if (match) {
|
|
11166
|
+
flush();
|
|
11167
|
+
current = { heading: match[1], lines: [] };
|
|
11168
|
+
} else if (current) {
|
|
11169
|
+
current.lines.push(line);
|
|
11142
11170
|
}
|
|
11143
11171
|
}
|
|
11144
|
-
|
|
11172
|
+
flush();
|
|
11173
|
+
return sections;
|
|
11174
|
+
}
|
|
11175
|
+
function serializePrBody(sections) {
|
|
11176
|
+
return sections.map((section2) => `## ${section2.heading}
|
|
11177
|
+
|
|
11178
|
+
${section2.content}`).join("\n\n");
|
|
11179
|
+
}
|
|
11180
|
+
|
|
11181
|
+
// src/commands/prs/editPrBody.ts
|
|
11182
|
+
function stripResolves(content) {
|
|
11183
|
+
return content.replace(/\n+Resolves [^\n]*$/, "").trimEnd();
|
|
11184
|
+
}
|
|
11185
|
+
function extractResolves(content) {
|
|
11186
|
+
const match = /\n+(Resolves [^\n]*)$/.exec(content);
|
|
11187
|
+
return match ? match[1] : "";
|
|
11188
|
+
}
|
|
11189
|
+
function editPrBody(body, sections) {
|
|
11190
|
+
const parsed = parsePrBody(body);
|
|
11191
|
+
const find = (heading) => parsed.find((s) => s.heading.toLowerCase() === heading.toLowerCase());
|
|
11192
|
+
const upsert = (heading, content) => {
|
|
11193
|
+
const existing = find(heading);
|
|
11194
|
+
if (existing) existing.content = content;
|
|
11195
|
+
else parsed.push({ heading, content });
|
|
11196
|
+
};
|
|
11197
|
+
if (sections.what !== void 0) upsert("What", sections.what);
|
|
11198
|
+
const hasResolves = (sections.resolves?.length ?? 0) > 0;
|
|
11199
|
+
if (sections.why !== void 0 || hasResolves) {
|
|
11200
|
+
const existingWhy = find("Why")?.content ?? "";
|
|
11201
|
+
const baseWhy = sections.why !== void 0 ? sections.why : stripResolves(existingWhy);
|
|
11202
|
+
if (hasResolves) {
|
|
11203
|
+
upsert("Why", renderWhy(baseWhy, sections.resolves));
|
|
11204
|
+
} else {
|
|
11205
|
+
const resolves = extractResolves(existingWhy);
|
|
11206
|
+
upsert("Why", resolves ? `${baseWhy}
|
|
11207
|
+
|
|
11208
|
+
${resolves}` : baseWhy);
|
|
11209
|
+
}
|
|
11210
|
+
}
|
|
11211
|
+
if (sections.how !== void 0) upsert("How", sections.how);
|
|
11212
|
+
return serializePrBody(parsed);
|
|
11145
11213
|
}
|
|
11146
11214
|
|
|
11147
11215
|
// src/commands/prs/validatePrContent.ts
|
|
@@ -11156,16 +11224,22 @@ function validatePrContent(title, body) {
|
|
|
11156
11224
|
}
|
|
11157
11225
|
}
|
|
11158
11226
|
|
|
11159
|
-
// src/commands/prs/
|
|
11160
|
-
function
|
|
11161
|
-
|
|
11227
|
+
// src/commands/prs/edit.ts
|
|
11228
|
+
function edit(options2) {
|
|
11229
|
+
const hasResolves = (options2.resolves?.length ?? 0) > 0;
|
|
11230
|
+
const hasSection = options2.what !== void 0 || options2.why !== void 0 || options2.how !== void 0 || hasResolves;
|
|
11231
|
+
if (!options2.title && !hasSection) {
|
|
11162
11232
|
console.error(
|
|
11163
|
-
"Usage: assist prs
|
|
11233
|
+
"Usage: assist prs edit [--title <title>] [--what <what>] [--why <why>] [--how <how>] [--resolves <key>]"
|
|
11164
11234
|
);
|
|
11165
11235
|
process.exit(1);
|
|
11166
11236
|
}
|
|
11167
|
-
|
|
11168
|
-
const
|
|
11237
|
+
const { number, body } = getCurrentPr();
|
|
11238
|
+
const newBody = editPrBody(body, options2);
|
|
11239
|
+
validatePrContent(options2.title ?? "", newBody);
|
|
11240
|
+
const args = [`gh pr edit ${number}`];
|
|
11241
|
+
if (options2.title) args.push(`--title ${shellQuote(options2.title)}`);
|
|
11242
|
+
args.push(`--body ${shellQuote(newBody)}`);
|
|
11169
11243
|
try {
|
|
11170
11244
|
execSync33(args.join(" "), { stdio: "inherit" });
|
|
11171
11245
|
} catch (_error) {
|
|
@@ -11376,20 +11450,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
11376
11450
|
}
|
|
11377
11451
|
|
|
11378
11452
|
// src/commands/prs/listComments/printComments.ts
|
|
11379
|
-
import
|
|
11453
|
+
import chalk120 from "chalk";
|
|
11380
11454
|
function formatForHuman(comment3) {
|
|
11381
11455
|
if (comment3.type === "review") {
|
|
11382
|
-
const stateColor = comment3.state === "APPROVED" ?
|
|
11456
|
+
const stateColor = comment3.state === "APPROVED" ? chalk120.green : comment3.state === "CHANGES_REQUESTED" ? chalk120.red : chalk120.yellow;
|
|
11383
11457
|
return [
|
|
11384
|
-
`${
|
|
11458
|
+
`${chalk120.cyan("Review")} by ${chalk120.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
|
|
11385
11459
|
comment3.body,
|
|
11386
11460
|
""
|
|
11387
11461
|
].join("\n");
|
|
11388
11462
|
}
|
|
11389
11463
|
const location = comment3.line ? `:${comment3.line}` : "";
|
|
11390
11464
|
return [
|
|
11391
|
-
`${
|
|
11392
|
-
|
|
11465
|
+
`${chalk120.cyan("Line comment")} by ${chalk120.bold(comment3.user)} on ${chalk120.dim(`${comment3.path}${location}`)}`,
|
|
11466
|
+
chalk120.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
11393
11467
|
comment3.body,
|
|
11394
11468
|
""
|
|
11395
11469
|
].join("\n");
|
|
@@ -11479,13 +11553,13 @@ import { execSync as execSync38 } from "child_process";
|
|
|
11479
11553
|
import enquirer9 from "enquirer";
|
|
11480
11554
|
|
|
11481
11555
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
11482
|
-
import
|
|
11556
|
+
import chalk121 from "chalk";
|
|
11483
11557
|
var STATUS_MAP = {
|
|
11484
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
11485
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
11558
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk121.magenta("merged"), date: pr.mergedAt } : null,
|
|
11559
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk121.red("closed"), date: pr.closedAt } : null
|
|
11486
11560
|
};
|
|
11487
11561
|
function defaultStatus(pr) {
|
|
11488
|
-
return { label:
|
|
11562
|
+
return { label: chalk121.green("opened"), date: pr.createdAt };
|
|
11489
11563
|
}
|
|
11490
11564
|
function getStatus2(pr) {
|
|
11491
11565
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -11494,11 +11568,11 @@ function formatDate(dateStr) {
|
|
|
11494
11568
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
11495
11569
|
}
|
|
11496
11570
|
function formatPrHeader(pr, status2) {
|
|
11497
|
-
return `${
|
|
11571
|
+
return `${chalk121.cyan(`#${pr.number}`)} ${pr.title} ${chalk121.dim(`(${pr.author.login},`)} ${status2.label} ${chalk121.dim(`${formatDate(status2.date)})`)}`;
|
|
11498
11572
|
}
|
|
11499
11573
|
function logPrDetails(pr) {
|
|
11500
11574
|
console.log(
|
|
11501
|
-
|
|
11575
|
+
chalk121.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
11502
11576
|
);
|
|
11503
11577
|
console.log();
|
|
11504
11578
|
}
|
|
@@ -11602,8 +11676,75 @@ async function prs(options2) {
|
|
|
11602
11676
|
}
|
|
11603
11677
|
}
|
|
11604
11678
|
|
|
11605
|
-
// src/commands/prs/
|
|
11679
|
+
// src/commands/prs/raise.ts
|
|
11606
11680
|
import { execSync as execSync39 } from "child_process";
|
|
11681
|
+
|
|
11682
|
+
// src/commands/prs/buildCreateArgs.ts
|
|
11683
|
+
function buildCreateArgs(title, body, options2) {
|
|
11684
|
+
const args = [
|
|
11685
|
+
"gh pr create",
|
|
11686
|
+
`--title ${shellQuote(title)}`,
|
|
11687
|
+
`--body ${shellQuote(body)}`
|
|
11688
|
+
];
|
|
11689
|
+
const valueFlags = [
|
|
11690
|
+
["--base", options2.base],
|
|
11691
|
+
["--head", options2.head],
|
|
11692
|
+
["--milestone", options2.milestone]
|
|
11693
|
+
];
|
|
11694
|
+
for (const [flag, value] of valueFlags) {
|
|
11695
|
+
if (value) args.push(`${flag} ${shellQuote(value)}`);
|
|
11696
|
+
}
|
|
11697
|
+
if (options2.draft) args.push("--draft");
|
|
11698
|
+
if (options2.web) args.push("--web");
|
|
11699
|
+
const repeatableFlags = [
|
|
11700
|
+
["--label", options2.label],
|
|
11701
|
+
["--assignee", options2.assignee],
|
|
11702
|
+
["--reviewer", options2.reviewer]
|
|
11703
|
+
];
|
|
11704
|
+
for (const [flag, values] of repeatableFlags) {
|
|
11705
|
+
for (const value of values ?? []) {
|
|
11706
|
+
args.push(`${flag} ${shellQuote(value)}`);
|
|
11707
|
+
}
|
|
11708
|
+
}
|
|
11709
|
+
return args;
|
|
11710
|
+
}
|
|
11711
|
+
|
|
11712
|
+
// src/commands/prs/raise.ts
|
|
11713
|
+
function raise(options2) {
|
|
11714
|
+
if (!options2.title || !options2.what || !options2.why) {
|
|
11715
|
+
console.error(
|
|
11716
|
+
"Usage: assist prs raise --title <title> --what <what> --why <why> [--how <how>] [--resolves <key>] [--force]"
|
|
11717
|
+
);
|
|
11718
|
+
process.exit(1);
|
|
11719
|
+
}
|
|
11720
|
+
const body = buildPrBody({
|
|
11721
|
+
what: options2.what,
|
|
11722
|
+
why: options2.why,
|
|
11723
|
+
how: options2.how,
|
|
11724
|
+
resolves: options2.resolves
|
|
11725
|
+
});
|
|
11726
|
+
validatePrContent(options2.title, body);
|
|
11727
|
+
const existing = findCurrentPrNumber();
|
|
11728
|
+
if (existing !== null && !options2.force) {
|
|
11729
|
+
console.error(
|
|
11730
|
+
`Error: A pull request already exists for this branch (#${existing}). Pass --force to overwrite it, or use 'assist prs edit' to update individual sections.`
|
|
11731
|
+
);
|
|
11732
|
+
process.exit(1);
|
|
11733
|
+
}
|
|
11734
|
+
const args = existing !== null ? [
|
|
11735
|
+
`gh pr edit ${existing}`,
|
|
11736
|
+
`--title ${shellQuote(options2.title)}`,
|
|
11737
|
+
`--body ${shellQuote(body)}`
|
|
11738
|
+
] : buildCreateArgs(options2.title, body, options2);
|
|
11739
|
+
try {
|
|
11740
|
+
execSync39(args.join(" "), { stdio: "inherit" });
|
|
11741
|
+
} catch (_error) {
|
|
11742
|
+
process.exit(1);
|
|
11743
|
+
}
|
|
11744
|
+
}
|
|
11745
|
+
|
|
11746
|
+
// src/commands/prs/wontfix.ts
|
|
11747
|
+
import { execSync as execSync40 } from "child_process";
|
|
11607
11748
|
function validateReason(reason) {
|
|
11608
11749
|
const lowerReason = reason.toLowerCase();
|
|
11609
11750
|
if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
|
|
@@ -11620,7 +11761,7 @@ function validateShaReferences(reason) {
|
|
|
11620
11761
|
const invalidShas = [];
|
|
11621
11762
|
for (const sha of shas) {
|
|
11622
11763
|
try {
|
|
11623
|
-
|
|
11764
|
+
execSync40(`git cat-file -t ${sha}`, { stdio: "pipe" });
|
|
11624
11765
|
} catch {
|
|
11625
11766
|
invalidShas.push(sha);
|
|
11626
11767
|
}
|
|
@@ -11647,30 +11788,54 @@ function wontfix(commentId, reason) {
|
|
|
11647
11788
|
}
|
|
11648
11789
|
}
|
|
11649
11790
|
|
|
11650
|
-
// src/commands/
|
|
11791
|
+
// src/commands/registerPrsEdit.ts
|
|
11651
11792
|
function collect2(value, previous) {
|
|
11652
11793
|
return previous.concat([value]);
|
|
11653
11794
|
}
|
|
11654
|
-
function
|
|
11655
|
-
prsCommand.command("
|
|
11656
|
-
"
|
|
11657
|
-
).option("-t, --title <title>", "
|
|
11795
|
+
function registerPrsEdit(prsCommand) {
|
|
11796
|
+
prsCommand.command("edit").description(
|
|
11797
|
+
"Update individual sections of the current branch's pull request"
|
|
11798
|
+
).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(
|
|
11799
|
+
"--resolves <key>",
|
|
11800
|
+
"Jira issue key resolved by this PR, appended to ## Why (repeatable)",
|
|
11801
|
+
collect2,
|
|
11802
|
+
[]
|
|
11803
|
+
).action(edit);
|
|
11804
|
+
}
|
|
11805
|
+
|
|
11806
|
+
// src/commands/registerPrsRaise.ts
|
|
11807
|
+
function collect3(value, previous) {
|
|
11808
|
+
return previous.concat([value]);
|
|
11809
|
+
}
|
|
11810
|
+
function registerPrsRaise(prsCommand) {
|
|
11811
|
+
prsCommand.command("raise").description(
|
|
11812
|
+
"Raise a pull request, assembling the body from discrete sections"
|
|
11813
|
+
).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(
|
|
11814
|
+
"--resolves <key>",
|
|
11815
|
+
"Jira issue key resolved by this PR, appended to ## Why (repeatable)",
|
|
11816
|
+
collect3,
|
|
11817
|
+
[]
|
|
11818
|
+
).option(
|
|
11819
|
+
"--force",
|
|
11820
|
+
"Overwrite the title and body of an existing pull request"
|
|
11821
|
+
).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(
|
|
11658
11822
|
"-a, --assignee <login>",
|
|
11659
11823
|
"Assign a person by login (repeatable)",
|
|
11660
|
-
|
|
11824
|
+
collect3,
|
|
11661
11825
|
[]
|
|
11662
11826
|
).option(
|
|
11663
11827
|
"-r, --reviewer <handle>",
|
|
11664
11828
|
"Request a review (repeatable)",
|
|
11665
|
-
|
|
11829
|
+
collect3,
|
|
11666
11830
|
[]
|
|
11667
|
-
).option("-m, --milestone <name>", "Add the pull request to a milestone").action(
|
|
11831
|
+
).option("-m, --milestone <name>", "Add the pull request to a milestone").action(raise);
|
|
11668
11832
|
}
|
|
11669
11833
|
|
|
11670
11834
|
// src/commands/registerPrs.ts
|
|
11671
11835
|
function registerPrs(program2) {
|
|
11672
11836
|
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);
|
|
11673
|
-
|
|
11837
|
+
registerPrsRaise(prsCommand);
|
|
11838
|
+
registerPrsEdit(prsCommand);
|
|
11674
11839
|
prsCommand.command("list-comments").description("List all comments on the current branch's pull request").action(() => {
|
|
11675
11840
|
listComments().then(printComments2);
|
|
11676
11841
|
});
|
|
@@ -11686,10 +11851,10 @@ function registerPrs(program2) {
|
|
|
11686
11851
|
}
|
|
11687
11852
|
|
|
11688
11853
|
// src/commands/ravendb/ravendbAuth.ts
|
|
11689
|
-
import
|
|
11854
|
+
import chalk127 from "chalk";
|
|
11690
11855
|
|
|
11691
11856
|
// src/shared/createConnectionAuth.ts
|
|
11692
|
-
import
|
|
11857
|
+
import chalk122 from "chalk";
|
|
11693
11858
|
function listConnections(connections, format2) {
|
|
11694
11859
|
if (connections.length === 0) {
|
|
11695
11860
|
console.log("No connections configured.");
|
|
@@ -11702,7 +11867,7 @@ function listConnections(connections, format2) {
|
|
|
11702
11867
|
function removeConnection(connections, name, save) {
|
|
11703
11868
|
const filtered = connections.filter((c) => c.name !== name);
|
|
11704
11869
|
if (filtered.length === connections.length) {
|
|
11705
|
-
console.error(
|
|
11870
|
+
console.error(chalk122.red(`Connection "${name}" not found.`));
|
|
11706
11871
|
process.exit(1);
|
|
11707
11872
|
}
|
|
11708
11873
|
save(filtered);
|
|
@@ -11748,17 +11913,17 @@ function saveConnections(connections) {
|
|
|
11748
11913
|
}
|
|
11749
11914
|
|
|
11750
11915
|
// src/commands/ravendb/promptConnection.ts
|
|
11751
|
-
import
|
|
11916
|
+
import chalk125 from "chalk";
|
|
11752
11917
|
|
|
11753
11918
|
// src/commands/ravendb/selectOpSecret.ts
|
|
11754
|
-
import
|
|
11919
|
+
import chalk124 from "chalk";
|
|
11755
11920
|
import Enquirer2 from "enquirer";
|
|
11756
11921
|
|
|
11757
11922
|
// src/commands/ravendb/searchItems.ts
|
|
11758
|
-
import { execSync as
|
|
11759
|
-
import
|
|
11923
|
+
import { execSync as execSync41 } from "child_process";
|
|
11924
|
+
import chalk123 from "chalk";
|
|
11760
11925
|
function opExec(args) {
|
|
11761
|
-
return
|
|
11926
|
+
return execSync41(`op ${args}`, {
|
|
11762
11927
|
encoding: "utf-8",
|
|
11763
11928
|
stdio: ["pipe", "pipe", "pipe"]
|
|
11764
11929
|
}).trim();
|
|
@@ -11769,7 +11934,7 @@ function searchItems(search2) {
|
|
|
11769
11934
|
items2 = JSON.parse(opExec("item list --format=json"));
|
|
11770
11935
|
} catch {
|
|
11771
11936
|
console.error(
|
|
11772
|
-
|
|
11937
|
+
chalk123.red(
|
|
11773
11938
|
"Failed to search 1Password. Ensure the CLI is installed and you are signed in."
|
|
11774
11939
|
)
|
|
11775
11940
|
);
|
|
@@ -11783,7 +11948,7 @@ function getItemFields(itemId) {
|
|
|
11783
11948
|
const item = JSON.parse(opExec(`item get "${itemId}" --format=json`));
|
|
11784
11949
|
return item.fields.filter((f) => f.reference && f.label);
|
|
11785
11950
|
} catch {
|
|
11786
|
-
console.error(
|
|
11951
|
+
console.error(chalk123.red("Failed to get item details from 1Password."));
|
|
11787
11952
|
process.exit(1);
|
|
11788
11953
|
}
|
|
11789
11954
|
}
|
|
@@ -11802,7 +11967,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11802
11967
|
}).run();
|
|
11803
11968
|
const items2 = searchItems(search2);
|
|
11804
11969
|
if (items2.length === 0) {
|
|
11805
|
-
console.error(
|
|
11970
|
+
console.error(chalk124.red(`No items found matching "${search2}".`));
|
|
11806
11971
|
process.exit(1);
|
|
11807
11972
|
}
|
|
11808
11973
|
const itemId = await selectOne(
|
|
@@ -11811,7 +11976,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11811
11976
|
);
|
|
11812
11977
|
const fields = getItemFields(itemId);
|
|
11813
11978
|
if (fields.length === 0) {
|
|
11814
|
-
console.error(
|
|
11979
|
+
console.error(chalk124.red("No fields with references found on this item."));
|
|
11815
11980
|
process.exit(1);
|
|
11816
11981
|
}
|
|
11817
11982
|
const ref = await selectOne(
|
|
@@ -11825,7 +11990,7 @@ async function selectOpSecret(searchTerm) {
|
|
|
11825
11990
|
async function promptConnection(existingNames) {
|
|
11826
11991
|
const name = await promptInput("name", "Connection name:");
|
|
11827
11992
|
if (existingNames.includes(name)) {
|
|
11828
|
-
console.error(
|
|
11993
|
+
console.error(chalk125.red(`Connection "${name}" already exists.`));
|
|
11829
11994
|
process.exit(1);
|
|
11830
11995
|
}
|
|
11831
11996
|
const url = await promptInput(
|
|
@@ -11834,22 +11999,22 @@ async function promptConnection(existingNames) {
|
|
|
11834
11999
|
);
|
|
11835
12000
|
const database = await promptInput("database", "Database name:");
|
|
11836
12001
|
if (!name || !url || !database) {
|
|
11837
|
-
console.error(
|
|
12002
|
+
console.error(chalk125.red("All fields are required."));
|
|
11838
12003
|
process.exit(1);
|
|
11839
12004
|
}
|
|
11840
12005
|
const apiKeyRef = await selectOpSecret();
|
|
11841
|
-
console.log(
|
|
12006
|
+
console.log(chalk125.dim(`Using: ${apiKeyRef}`));
|
|
11842
12007
|
return { name, url, database, apiKeyRef };
|
|
11843
12008
|
}
|
|
11844
12009
|
|
|
11845
12010
|
// src/commands/ravendb/ravendbSetConnection.ts
|
|
11846
|
-
import
|
|
12011
|
+
import chalk126 from "chalk";
|
|
11847
12012
|
function ravendbSetConnection(name) {
|
|
11848
12013
|
const raw = loadGlobalConfigRaw();
|
|
11849
12014
|
const ravendb = raw.ravendb ?? {};
|
|
11850
12015
|
const connections = ravendb.connections ?? [];
|
|
11851
12016
|
if (!connections.some((c) => c.name === name)) {
|
|
11852
|
-
console.error(
|
|
12017
|
+
console.error(chalk126.red(`Connection "${name}" not found.`));
|
|
11853
12018
|
console.error(
|
|
11854
12019
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
11855
12020
|
);
|
|
@@ -11865,16 +12030,16 @@ function ravendbSetConnection(name) {
|
|
|
11865
12030
|
var ravendbAuth = createConnectionAuth({
|
|
11866
12031
|
load: loadConnections,
|
|
11867
12032
|
save: saveConnections,
|
|
11868
|
-
format: (c) => `${
|
|
12033
|
+
format: (c) => `${chalk127.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
|
|
11869
12034
|
promptNew: promptConnection,
|
|
11870
12035
|
onFirst: (c) => ravendbSetConnection(c.name)
|
|
11871
12036
|
});
|
|
11872
12037
|
|
|
11873
12038
|
// src/commands/ravendb/ravendbCollections.ts
|
|
11874
|
-
import
|
|
12039
|
+
import chalk131 from "chalk";
|
|
11875
12040
|
|
|
11876
12041
|
// src/commands/ravendb/ravenFetch.ts
|
|
11877
|
-
import
|
|
12042
|
+
import chalk129 from "chalk";
|
|
11878
12043
|
|
|
11879
12044
|
// src/commands/ravendb/getAccessToken.ts
|
|
11880
12045
|
var OAUTH_URL = "https://amazon-useast-1-oauth.ravenhq.com/ApiKeys/OAuth/AccessToken";
|
|
@@ -11910,21 +12075,21 @@ ${errorText}`
|
|
|
11910
12075
|
}
|
|
11911
12076
|
|
|
11912
12077
|
// src/commands/ravendb/resolveOpSecret.ts
|
|
11913
|
-
import { execSync as
|
|
11914
|
-
import
|
|
12078
|
+
import { execSync as execSync42 } from "child_process";
|
|
12079
|
+
import chalk128 from "chalk";
|
|
11915
12080
|
function resolveOpSecret(reference) {
|
|
11916
12081
|
if (!reference.startsWith("op://")) {
|
|
11917
|
-
console.error(
|
|
12082
|
+
console.error(chalk128.red(`Invalid secret reference: must start with op://`));
|
|
11918
12083
|
process.exit(1);
|
|
11919
12084
|
}
|
|
11920
12085
|
try {
|
|
11921
|
-
return
|
|
12086
|
+
return execSync42(`op read "${reference}"`, {
|
|
11922
12087
|
encoding: "utf-8",
|
|
11923
12088
|
stdio: ["pipe", "pipe", "pipe"]
|
|
11924
12089
|
}).trim();
|
|
11925
12090
|
} catch {
|
|
11926
12091
|
console.error(
|
|
11927
|
-
|
|
12092
|
+
chalk128.red(
|
|
11928
12093
|
"Failed to resolve secret reference. Ensure 1Password CLI is installed and you are signed in."
|
|
11929
12094
|
)
|
|
11930
12095
|
);
|
|
@@ -11951,7 +12116,7 @@ async function ravenFetch(connection, path54) {
|
|
|
11951
12116
|
if (!response.ok) {
|
|
11952
12117
|
const body = await response.text();
|
|
11953
12118
|
console.error(
|
|
11954
|
-
|
|
12119
|
+
chalk129.red(`RavenDB error: ${response.status} ${response.statusText}`)
|
|
11955
12120
|
);
|
|
11956
12121
|
console.error(body.substring(0, 500));
|
|
11957
12122
|
process.exit(1);
|
|
@@ -11960,7 +12125,7 @@ async function ravenFetch(connection, path54) {
|
|
|
11960
12125
|
}
|
|
11961
12126
|
|
|
11962
12127
|
// src/commands/ravendb/resolveConnection.ts
|
|
11963
|
-
import
|
|
12128
|
+
import chalk130 from "chalk";
|
|
11964
12129
|
function loadRavendb() {
|
|
11965
12130
|
const raw = loadGlobalConfigRaw();
|
|
11966
12131
|
const ravendb = raw.ravendb;
|
|
@@ -11974,7 +12139,7 @@ function resolveConnection(name) {
|
|
|
11974
12139
|
const connectionName = name ?? defaultConnection;
|
|
11975
12140
|
if (!connectionName) {
|
|
11976
12141
|
console.error(
|
|
11977
|
-
|
|
12142
|
+
chalk130.red(
|
|
11978
12143
|
"No connection specified and no default set. Use assist ravendb set-connection <name> or pass a connection name."
|
|
11979
12144
|
)
|
|
11980
12145
|
);
|
|
@@ -11982,7 +12147,7 @@ function resolveConnection(name) {
|
|
|
11982
12147
|
}
|
|
11983
12148
|
const connection = connections.find((c) => c.name === connectionName);
|
|
11984
12149
|
if (!connection) {
|
|
11985
|
-
console.error(
|
|
12150
|
+
console.error(chalk130.red(`Connection "${connectionName}" not found.`));
|
|
11986
12151
|
console.error(
|
|
11987
12152
|
`Available: ${connections.map((c) => c.name).join(", ") || "(none)"}`
|
|
11988
12153
|
);
|
|
@@ -12013,15 +12178,15 @@ async function ravendbCollections(connectionName) {
|
|
|
12013
12178
|
return;
|
|
12014
12179
|
}
|
|
12015
12180
|
for (const c of collections) {
|
|
12016
|
-
console.log(`${
|
|
12181
|
+
console.log(`${chalk131.bold(c.Name)} ${c.CountOfDocuments} docs`);
|
|
12017
12182
|
}
|
|
12018
12183
|
}
|
|
12019
12184
|
|
|
12020
12185
|
// src/commands/ravendb/ravendbQuery.ts
|
|
12021
|
-
import
|
|
12186
|
+
import chalk133 from "chalk";
|
|
12022
12187
|
|
|
12023
12188
|
// src/commands/ravendb/fetchAllPages.ts
|
|
12024
|
-
import
|
|
12189
|
+
import chalk132 from "chalk";
|
|
12025
12190
|
|
|
12026
12191
|
// src/commands/ravendb/buildQueryPath.ts
|
|
12027
12192
|
function buildQueryPath(opts) {
|
|
@@ -12059,7 +12224,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
12059
12224
|
allResults.push(...results);
|
|
12060
12225
|
start3 += results.length;
|
|
12061
12226
|
process.stderr.write(
|
|
12062
|
-
`\r${
|
|
12227
|
+
`\r${chalk132.dim(`Fetched ${allResults.length}/${totalResults}`)}`
|
|
12063
12228
|
);
|
|
12064
12229
|
if (start3 >= totalResults) break;
|
|
12065
12230
|
if (opts.limit !== void 0 && allResults.length >= opts.limit) break;
|
|
@@ -12074,7 +12239,7 @@ async function fetchAllPages(connection, opts) {
|
|
|
12074
12239
|
async function ravendbQuery(connectionName, collection, options2) {
|
|
12075
12240
|
const resolved = resolveArgs(connectionName, collection);
|
|
12076
12241
|
if (!resolved.collection && !options2.query) {
|
|
12077
|
-
console.error(
|
|
12242
|
+
console.error(chalk133.red("Provide a collection name or --query filter."));
|
|
12078
12243
|
process.exit(1);
|
|
12079
12244
|
}
|
|
12080
12245
|
const { collection: col } = resolved;
|
|
@@ -12112,7 +12277,7 @@ import { spawn as spawn5 } from "child_process";
|
|
|
12112
12277
|
import * as path26 from "path";
|
|
12113
12278
|
|
|
12114
12279
|
// src/commands/refactor/logViolations.ts
|
|
12115
|
-
import
|
|
12280
|
+
import chalk134 from "chalk";
|
|
12116
12281
|
var DEFAULT_MAX_LINES = 100;
|
|
12117
12282
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
12118
12283
|
if (violations.length === 0) {
|
|
@@ -12121,43 +12286,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
12121
12286
|
}
|
|
12122
12287
|
return;
|
|
12123
12288
|
}
|
|
12124
|
-
console.error(
|
|
12289
|
+
console.error(chalk134.red(`
|
|
12125
12290
|
Refactor check failed:
|
|
12126
12291
|
`));
|
|
12127
|
-
console.error(
|
|
12292
|
+
console.error(chalk134.red(` The following files exceed ${maxLines} lines:
|
|
12128
12293
|
`));
|
|
12129
12294
|
for (const violation of violations) {
|
|
12130
|
-
console.error(
|
|
12295
|
+
console.error(chalk134.red(` ${violation.file} (${violation.lines} lines)`));
|
|
12131
12296
|
}
|
|
12132
12297
|
console.error(
|
|
12133
|
-
|
|
12298
|
+
chalk134.yellow(
|
|
12134
12299
|
`
|
|
12135
12300
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
12136
12301
|
way to refactor it, ignore it with:
|
|
12137
12302
|
`
|
|
12138
12303
|
)
|
|
12139
12304
|
);
|
|
12140
|
-
console.error(
|
|
12305
|
+
console.error(chalk134.gray(` assist refactor ignore <file>
|
|
12141
12306
|
`));
|
|
12142
12307
|
if (process.env.CLAUDECODE) {
|
|
12143
|
-
console.error(
|
|
12308
|
+
console.error(chalk134.cyan(`
|
|
12144
12309
|
## Extracting Code to New Files
|
|
12145
12310
|
`));
|
|
12146
12311
|
console.error(
|
|
12147
|
-
|
|
12312
|
+
chalk134.cyan(
|
|
12148
12313
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
12149
12314
|
`
|
|
12150
12315
|
)
|
|
12151
12316
|
);
|
|
12152
12317
|
console.error(
|
|
12153
|
-
|
|
12318
|
+
chalk134.cyan(
|
|
12154
12319
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
12155
12320
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
12156
12321
|
`
|
|
12157
12322
|
)
|
|
12158
12323
|
);
|
|
12159
12324
|
console.error(
|
|
12160
|
-
|
|
12325
|
+
chalk134.cyan(
|
|
12161
12326
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
12162
12327
|
domains, move it to a common/shared folder.
|
|
12163
12328
|
`
|
|
@@ -12167,7 +12332,7 @@ Refactor check failed:
|
|
|
12167
12332
|
}
|
|
12168
12333
|
|
|
12169
12334
|
// src/commands/refactor/check/getViolations/index.ts
|
|
12170
|
-
import { execSync as
|
|
12335
|
+
import { execSync as execSync43 } from "child_process";
|
|
12171
12336
|
import fs18 from "fs";
|
|
12172
12337
|
import { minimatch as minimatch5 } from "minimatch";
|
|
12173
12338
|
|
|
@@ -12217,7 +12382,7 @@ function getGitFiles(options2) {
|
|
|
12217
12382
|
}
|
|
12218
12383
|
const files = /* @__PURE__ */ new Set();
|
|
12219
12384
|
if (options2.staged || options2.modified) {
|
|
12220
|
-
const staged =
|
|
12385
|
+
const staged = execSync43("git diff --cached --name-only", {
|
|
12221
12386
|
encoding: "utf-8"
|
|
12222
12387
|
});
|
|
12223
12388
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -12225,7 +12390,7 @@ function getGitFiles(options2) {
|
|
|
12225
12390
|
}
|
|
12226
12391
|
}
|
|
12227
12392
|
if (options2.unstaged || options2.modified) {
|
|
12228
|
-
const unstaged =
|
|
12393
|
+
const unstaged = execSync43("git diff --name-only", { encoding: "utf-8" });
|
|
12229
12394
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
12230
12395
|
files.add(file);
|
|
12231
12396
|
}
|
|
@@ -12313,7 +12478,7 @@ async function check(pattern2, options2) {
|
|
|
12313
12478
|
|
|
12314
12479
|
// src/commands/refactor/extract/index.ts
|
|
12315
12480
|
import path33 from "path";
|
|
12316
|
-
import
|
|
12481
|
+
import chalk137 from "chalk";
|
|
12317
12482
|
|
|
12318
12483
|
// src/commands/refactor/extract/applyExtraction.ts
|
|
12319
12484
|
import { SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
@@ -12888,23 +13053,23 @@ function buildPlan2(functionName, sourceFile, sourcePath, destPath, project) {
|
|
|
12888
13053
|
|
|
12889
13054
|
// src/commands/refactor/extract/displayPlan.ts
|
|
12890
13055
|
import path30 from "path";
|
|
12891
|
-
import
|
|
13056
|
+
import chalk135 from "chalk";
|
|
12892
13057
|
function section(title) {
|
|
12893
13058
|
return `
|
|
12894
|
-
${
|
|
13059
|
+
${chalk135.cyan(title)}`;
|
|
12895
13060
|
}
|
|
12896
13061
|
function displayImporters(plan2, cwd) {
|
|
12897
13062
|
if (plan2.importersToUpdate.length === 0) return;
|
|
12898
13063
|
console.log(section("Update importers:"));
|
|
12899
13064
|
for (const imp of plan2.importersToUpdate) {
|
|
12900
13065
|
const rel = path30.relative(cwd, imp.file.getFilePath());
|
|
12901
|
-
console.log(` ${
|
|
13066
|
+
console.log(` ${chalk135.dim(rel)}: \u2192 import from "${imp.relPath}"`);
|
|
12902
13067
|
}
|
|
12903
13068
|
}
|
|
12904
13069
|
function displayPlan(functionName, relDest, plan2, cwd) {
|
|
12905
|
-
console.log(
|
|
13070
|
+
console.log(chalk135.bold(`Extract: ${functionName} \u2192 ${relDest}
|
|
12906
13071
|
`));
|
|
12907
|
-
console.log(` ${
|
|
13072
|
+
console.log(` ${chalk135.cyan("Functions to move:")}`);
|
|
12908
13073
|
for (const name of plan2.extractedNames) {
|
|
12909
13074
|
console.log(` ${name}`);
|
|
12910
13075
|
}
|
|
@@ -12938,7 +13103,7 @@ function displayPlan(functionName, relDest, plan2, cwd) {
|
|
|
12938
13103
|
|
|
12939
13104
|
// src/commands/refactor/extract/loadProjectFile.ts
|
|
12940
13105
|
import path32 from "path";
|
|
12941
|
-
import
|
|
13106
|
+
import chalk136 from "chalk";
|
|
12942
13107
|
import { Project as Project4 } from "ts-morph";
|
|
12943
13108
|
|
|
12944
13109
|
// src/commands/refactor/extract/findTsConfig.ts
|
|
@@ -12998,7 +13163,7 @@ function loadProjectFile(file) {
|
|
|
12998
13163
|
});
|
|
12999
13164
|
const sourceFile = project.getSourceFile(sourcePath);
|
|
13000
13165
|
if (!sourceFile) {
|
|
13001
|
-
console.log(
|
|
13166
|
+
console.log(chalk136.red(`File not found in project: ${file}`));
|
|
13002
13167
|
process.exit(1);
|
|
13003
13168
|
}
|
|
13004
13169
|
return { project, sourceFile };
|
|
@@ -13021,19 +13186,19 @@ async function extract(file, functionName, destination, options2 = {}) {
|
|
|
13021
13186
|
displayPlan(functionName, relDest, plan2, cwd);
|
|
13022
13187
|
if (options2.apply) {
|
|
13023
13188
|
await applyExtraction(functionName, sourceFile, destPath, plan2, project);
|
|
13024
|
-
console.log(
|
|
13189
|
+
console.log(chalk137.green("\nExtraction complete"));
|
|
13025
13190
|
} else {
|
|
13026
|
-
console.log(
|
|
13191
|
+
console.log(chalk137.dim("\nDry run. Use --apply to execute."));
|
|
13027
13192
|
}
|
|
13028
13193
|
}
|
|
13029
13194
|
|
|
13030
13195
|
// src/commands/refactor/ignore.ts
|
|
13031
13196
|
import fs20 from "fs";
|
|
13032
|
-
import
|
|
13197
|
+
import chalk138 from "chalk";
|
|
13033
13198
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
13034
13199
|
function ignore(file) {
|
|
13035
13200
|
if (!fs20.existsSync(file)) {
|
|
13036
|
-
console.error(
|
|
13201
|
+
console.error(chalk138.red(`Error: File does not exist: ${file}`));
|
|
13037
13202
|
process.exit(1);
|
|
13038
13203
|
}
|
|
13039
13204
|
const content = fs20.readFileSync(file, "utf-8");
|
|
@@ -13049,7 +13214,7 @@ function ignore(file) {
|
|
|
13049
13214
|
fs20.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
13050
13215
|
}
|
|
13051
13216
|
console.log(
|
|
13052
|
-
|
|
13217
|
+
chalk138.green(
|
|
13053
13218
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
13054
13219
|
)
|
|
13055
13220
|
);
|
|
@@ -13057,25 +13222,25 @@ function ignore(file) {
|
|
|
13057
13222
|
|
|
13058
13223
|
// src/commands/refactor/rename/index.ts
|
|
13059
13224
|
import path34 from "path";
|
|
13060
|
-
import
|
|
13225
|
+
import chalk139 from "chalk";
|
|
13061
13226
|
async function rename(source, destination, options2 = {}) {
|
|
13062
13227
|
const destPath = path34.resolve(destination);
|
|
13063
13228
|
const cwd = process.cwd();
|
|
13064
13229
|
const relSource = path34.relative(cwd, path34.resolve(source));
|
|
13065
13230
|
const relDest = path34.relative(cwd, destPath);
|
|
13066
13231
|
const { project, sourceFile } = loadProjectFile(source);
|
|
13067
|
-
console.log(
|
|
13232
|
+
console.log(chalk139.bold(`Rename: ${relSource} \u2192 ${relDest}`));
|
|
13068
13233
|
if (options2.apply) {
|
|
13069
13234
|
sourceFile.move(destPath);
|
|
13070
13235
|
await project.save();
|
|
13071
|
-
console.log(
|
|
13236
|
+
console.log(chalk139.green("Done"));
|
|
13072
13237
|
} else {
|
|
13073
|
-
console.log(
|
|
13238
|
+
console.log(chalk139.dim("Dry run. Use --apply to execute."));
|
|
13074
13239
|
}
|
|
13075
13240
|
}
|
|
13076
13241
|
|
|
13077
13242
|
// src/commands/refactor/renameSymbol/index.ts
|
|
13078
|
-
import
|
|
13243
|
+
import chalk140 from "chalk";
|
|
13079
13244
|
|
|
13080
13245
|
// src/commands/refactor/renameSymbol/findSymbol.ts
|
|
13081
13246
|
import { SyntaxKind as SyntaxKind14 } from "ts-morph";
|
|
@@ -13121,33 +13286,33 @@ async function renameSymbol(file, oldName, newName, options2 = {}) {
|
|
|
13121
13286
|
const { project, sourceFile } = loadProjectFile(file);
|
|
13122
13287
|
const symbol = findSymbol(sourceFile, oldName);
|
|
13123
13288
|
if (!symbol) {
|
|
13124
|
-
console.log(
|
|
13289
|
+
console.log(chalk140.red(`Symbol "${oldName}" not found in ${file}`));
|
|
13125
13290
|
process.exit(1);
|
|
13126
13291
|
}
|
|
13127
13292
|
const grouped = groupReferences(symbol, cwd);
|
|
13128
13293
|
const totalRefs = [...grouped.values()].reduce((s, l) => s + l.length, 0);
|
|
13129
13294
|
console.log(
|
|
13130
|
-
|
|
13295
|
+
chalk140.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
|
|
13131
13296
|
`)
|
|
13132
13297
|
);
|
|
13133
13298
|
for (const [refFile, lines] of grouped) {
|
|
13134
13299
|
console.log(
|
|
13135
|
-
` ${
|
|
13300
|
+
` ${chalk140.dim(refFile)}: lines ${chalk140.cyan(lines.join(", "))}`
|
|
13136
13301
|
);
|
|
13137
13302
|
}
|
|
13138
13303
|
if (options2.apply) {
|
|
13139
13304
|
symbol.rename(newName);
|
|
13140
13305
|
await project.save();
|
|
13141
|
-
console.log(
|
|
13306
|
+
console.log(chalk140.green(`
|
|
13142
13307
|
Renamed ${oldName} \u2192 ${newName}`));
|
|
13143
13308
|
} else {
|
|
13144
|
-
console.log(
|
|
13309
|
+
console.log(chalk140.dim("\nDry run. Use --apply to execute."));
|
|
13145
13310
|
}
|
|
13146
13311
|
}
|
|
13147
13312
|
|
|
13148
13313
|
// src/commands/refactor/restructure/index.ts
|
|
13149
13314
|
import path44 from "path";
|
|
13150
|
-
import
|
|
13315
|
+
import chalk143 from "chalk";
|
|
13151
13316
|
|
|
13152
13317
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
13153
13318
|
import path36 from "path";
|
|
@@ -13390,50 +13555,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
13390
13555
|
|
|
13391
13556
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
13392
13557
|
import path40 from "path";
|
|
13393
|
-
import
|
|
13558
|
+
import chalk141 from "chalk";
|
|
13394
13559
|
function relPath(filePath) {
|
|
13395
13560
|
return path40.relative(process.cwd(), filePath);
|
|
13396
13561
|
}
|
|
13397
13562
|
function displayMoves(plan2) {
|
|
13398
13563
|
if (plan2.moves.length === 0) return;
|
|
13399
|
-
console.log(
|
|
13564
|
+
console.log(chalk141.bold("\nFile moves:"));
|
|
13400
13565
|
for (const move of plan2.moves) {
|
|
13401
13566
|
console.log(
|
|
13402
|
-
` ${
|
|
13567
|
+
` ${chalk141.red(relPath(move.from))} \u2192 ${chalk141.green(relPath(move.to))}`
|
|
13403
13568
|
);
|
|
13404
|
-
console.log(
|
|
13569
|
+
console.log(chalk141.dim(` ${move.reason}`));
|
|
13405
13570
|
}
|
|
13406
13571
|
}
|
|
13407
13572
|
function displayRewrites(rewrites) {
|
|
13408
13573
|
if (rewrites.length === 0) return;
|
|
13409
13574
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
13410
|
-
console.log(
|
|
13575
|
+
console.log(chalk141.bold(`
|
|
13411
13576
|
Import rewrites (${affectedFiles.size} files):`));
|
|
13412
13577
|
for (const file of affectedFiles) {
|
|
13413
|
-
console.log(` ${
|
|
13578
|
+
console.log(` ${chalk141.cyan(relPath(file))}:`);
|
|
13414
13579
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
13415
13580
|
(r) => r.file === file
|
|
13416
13581
|
)) {
|
|
13417
13582
|
console.log(
|
|
13418
|
-
` ${
|
|
13583
|
+
` ${chalk141.red(`"${oldSpecifier}"`)} \u2192 ${chalk141.green(`"${newSpecifier}"`)}`
|
|
13419
13584
|
);
|
|
13420
13585
|
}
|
|
13421
13586
|
}
|
|
13422
13587
|
}
|
|
13423
13588
|
function displayPlan2(plan2) {
|
|
13424
13589
|
if (plan2.warnings.length > 0) {
|
|
13425
|
-
console.log(
|
|
13426
|
-
for (const w of plan2.warnings) console.log(
|
|
13590
|
+
console.log(chalk141.yellow("\nWarnings:"));
|
|
13591
|
+
for (const w of plan2.warnings) console.log(chalk141.yellow(` ${w}`));
|
|
13427
13592
|
}
|
|
13428
13593
|
if (plan2.newDirectories.length > 0) {
|
|
13429
|
-
console.log(
|
|
13594
|
+
console.log(chalk141.bold("\nNew directories:"));
|
|
13430
13595
|
for (const dir of plan2.newDirectories)
|
|
13431
|
-
console.log(
|
|
13596
|
+
console.log(chalk141.green(` ${dir}/`));
|
|
13432
13597
|
}
|
|
13433
13598
|
displayMoves(plan2);
|
|
13434
13599
|
displayRewrites(plan2.rewrites);
|
|
13435
13600
|
console.log(
|
|
13436
|
-
|
|
13601
|
+
chalk141.dim(
|
|
13437
13602
|
`
|
|
13438
13603
|
Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports rewritten`
|
|
13439
13604
|
)
|
|
@@ -13443,18 +13608,18 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
|
|
|
13443
13608
|
// src/commands/refactor/restructure/executePlan.ts
|
|
13444
13609
|
import fs22 from "fs";
|
|
13445
13610
|
import path41 from "path";
|
|
13446
|
-
import
|
|
13611
|
+
import chalk142 from "chalk";
|
|
13447
13612
|
function executePlan(plan2) {
|
|
13448
13613
|
const updatedContents = applyRewrites(plan2.rewrites);
|
|
13449
13614
|
for (const [file, content] of updatedContents) {
|
|
13450
13615
|
fs22.writeFileSync(file, content, "utf-8");
|
|
13451
13616
|
console.log(
|
|
13452
|
-
|
|
13617
|
+
chalk142.cyan(` Rewrote imports in ${path41.relative(process.cwd(), file)}`)
|
|
13453
13618
|
);
|
|
13454
13619
|
}
|
|
13455
13620
|
for (const dir of plan2.newDirectories) {
|
|
13456
13621
|
fs22.mkdirSync(dir, { recursive: true });
|
|
13457
|
-
console.log(
|
|
13622
|
+
console.log(chalk142.green(` Created ${path41.relative(process.cwd(), dir)}/`));
|
|
13458
13623
|
}
|
|
13459
13624
|
for (const move of plan2.moves) {
|
|
13460
13625
|
const targetDir = path41.dirname(move.to);
|
|
@@ -13463,7 +13628,7 @@ function executePlan(plan2) {
|
|
|
13463
13628
|
}
|
|
13464
13629
|
fs22.renameSync(move.from, move.to);
|
|
13465
13630
|
console.log(
|
|
13466
|
-
|
|
13631
|
+
chalk142.white(
|
|
13467
13632
|
` Moved ${path41.relative(process.cwd(), move.from)} \u2192 ${path41.relative(process.cwd(), move.to)}`
|
|
13468
13633
|
)
|
|
13469
13634
|
);
|
|
@@ -13478,7 +13643,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
13478
13643
|
if (entries.length === 0) {
|
|
13479
13644
|
fs22.rmdirSync(dir);
|
|
13480
13645
|
console.log(
|
|
13481
|
-
|
|
13646
|
+
chalk142.dim(
|
|
13482
13647
|
` Removed empty directory ${path41.relative(process.cwd(), dir)}`
|
|
13483
13648
|
)
|
|
13484
13649
|
);
|
|
@@ -13611,22 +13776,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
13611
13776
|
const targetPattern = pattern2 ?? "src";
|
|
13612
13777
|
const files = findSourceFiles2(targetPattern);
|
|
13613
13778
|
if (files.length === 0) {
|
|
13614
|
-
console.log(
|
|
13779
|
+
console.log(chalk143.yellow("No files found matching pattern"));
|
|
13615
13780
|
return;
|
|
13616
13781
|
}
|
|
13617
13782
|
const tsConfigPath = path44.resolve("tsconfig.json");
|
|
13618
13783
|
const plan2 = buildPlan3(files, tsConfigPath);
|
|
13619
13784
|
if (plan2.moves.length === 0) {
|
|
13620
|
-
console.log(
|
|
13785
|
+
console.log(chalk143.green("No restructuring needed"));
|
|
13621
13786
|
return;
|
|
13622
13787
|
}
|
|
13623
13788
|
displayPlan2(plan2);
|
|
13624
13789
|
if (options2.apply) {
|
|
13625
|
-
console.log(
|
|
13790
|
+
console.log(chalk143.bold("\nApplying changes..."));
|
|
13626
13791
|
executePlan(plan2);
|
|
13627
|
-
console.log(
|
|
13792
|
+
console.log(chalk143.green("\nRestructuring complete"));
|
|
13628
13793
|
} else {
|
|
13629
|
-
console.log(
|
|
13794
|
+
console.log(chalk143.dim("\nDry run. Use --apply to execute."));
|
|
13630
13795
|
}
|
|
13631
13796
|
}
|
|
13632
13797
|
|
|
@@ -13801,9 +13966,9 @@ function buildReviewPaths(repoRoot, key) {
|
|
|
13801
13966
|
}
|
|
13802
13967
|
|
|
13803
13968
|
// src/commands/review/fetchExistingComments.ts
|
|
13804
|
-
import { execSync as
|
|
13969
|
+
import { execSync as execSync44 } from "child_process";
|
|
13805
13970
|
function fetchRawComments(org, repo, prNumber) {
|
|
13806
|
-
const out =
|
|
13971
|
+
const out = execSync44(
|
|
13807
13972
|
`gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
|
|
13808
13973
|
{ encoding: "utf-8", maxBuffer: 64 * 1024 * 1024 }
|
|
13809
13974
|
);
|
|
@@ -13834,14 +13999,14 @@ function fetchExistingComments() {
|
|
|
13834
13999
|
}
|
|
13835
14000
|
|
|
13836
14001
|
// src/commands/review/gatherContext.ts
|
|
13837
|
-
import { execSync as
|
|
14002
|
+
import { execSync as execSync47 } from "child_process";
|
|
13838
14003
|
|
|
13839
14004
|
// src/commands/review/fetchPrDiff.ts
|
|
13840
|
-
import { execSync as
|
|
14005
|
+
import { execSync as execSync45 } from "child_process";
|
|
13841
14006
|
function fetchPrDiff(prNumber, baseSha, headSha) {
|
|
13842
14007
|
const { org, repo } = getRepoInfo();
|
|
13843
14008
|
try {
|
|
13844
|
-
return
|
|
14009
|
+
return execSync45(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
|
|
13845
14010
|
encoding: "utf-8",
|
|
13846
14011
|
maxBuffer: 256 * 1024 * 1024,
|
|
13847
14012
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -13856,19 +14021,19 @@ function isDiffTooLarge(error) {
|
|
|
13856
14021
|
}
|
|
13857
14022
|
function fetchDiffViaGit(baseSha, headSha) {
|
|
13858
14023
|
try {
|
|
13859
|
-
|
|
14024
|
+
execSync45(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
|
|
13860
14025
|
} catch {
|
|
13861
14026
|
}
|
|
13862
|
-
return
|
|
14027
|
+
return execSync45(`git diff ${baseSha}...${headSha}`, {
|
|
13863
14028
|
encoding: "utf-8",
|
|
13864
14029
|
maxBuffer: 256 * 1024 * 1024
|
|
13865
14030
|
});
|
|
13866
14031
|
}
|
|
13867
14032
|
|
|
13868
14033
|
// src/commands/review/fetchPrDiffInfo.ts
|
|
13869
|
-
import { execSync as
|
|
14034
|
+
import { execSync as execSync46 } from "child_process";
|
|
13870
14035
|
function getCurrentBranch2() {
|
|
13871
|
-
return
|
|
14036
|
+
return execSync46("git rev-parse --abbrev-ref HEAD", {
|
|
13872
14037
|
encoding: "utf-8"
|
|
13873
14038
|
}).trim();
|
|
13874
14039
|
}
|
|
@@ -13878,7 +14043,7 @@ function fetchPrDiffInfo() {
|
|
|
13878
14043
|
const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
|
|
13879
14044
|
let raw;
|
|
13880
14045
|
try {
|
|
13881
|
-
raw =
|
|
14046
|
+
raw = execSync46(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
|
|
13882
14047
|
encoding: "utf-8",
|
|
13883
14048
|
stdio: ["ignore", "pipe", "pipe"]
|
|
13884
14049
|
});
|
|
@@ -13902,7 +14067,7 @@ function fetchPrDiffInfo() {
|
|
|
13902
14067
|
}
|
|
13903
14068
|
function fetchPrChangedFiles(prNumber) {
|
|
13904
14069
|
const { org, repo } = getRepoInfo();
|
|
13905
|
-
const out =
|
|
14070
|
+
const out = execSync46(
|
|
13906
14071
|
`gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
|
|
13907
14072
|
{
|
|
13908
14073
|
encoding: "utf-8",
|
|
@@ -13914,11 +14079,11 @@ function fetchPrChangedFiles(prNumber) {
|
|
|
13914
14079
|
|
|
13915
14080
|
// src/commands/review/gatherContext.ts
|
|
13916
14081
|
function gatherContext() {
|
|
13917
|
-
const branch =
|
|
14082
|
+
const branch = execSync47("git rev-parse --abbrev-ref HEAD", {
|
|
13918
14083
|
encoding: "utf-8"
|
|
13919
14084
|
}).trim();
|
|
13920
|
-
const sha =
|
|
13921
|
-
const shortSha =
|
|
14085
|
+
const sha = execSync47("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
14086
|
+
const shortSha = execSync47("git rev-parse --short=7 HEAD", {
|
|
13922
14087
|
encoding: "utf-8"
|
|
13923
14088
|
}).trim();
|
|
13924
14089
|
const prInfo = fetchPrDiffInfo();
|
|
@@ -14195,18 +14360,18 @@ function partitionFindingsByDiff(findings, index2) {
|
|
|
14195
14360
|
}
|
|
14196
14361
|
|
|
14197
14362
|
// src/commands/review/warnOutOfDiff.ts
|
|
14198
|
-
import
|
|
14363
|
+
import chalk144 from "chalk";
|
|
14199
14364
|
function warnOutOfDiff(outOfDiff) {
|
|
14200
14365
|
if (outOfDiff.length === 0) return;
|
|
14201
14366
|
console.warn(
|
|
14202
|
-
|
|
14367
|
+
chalk144.yellow(
|
|
14203
14368
|
`Skipped ${outOfDiff.length} finding(s) whose lines fall outside the PR diff (GitHub would silently drop these):`
|
|
14204
14369
|
)
|
|
14205
14370
|
);
|
|
14206
14371
|
for (const finding of outOfDiff) {
|
|
14207
14372
|
const range = finding.startLine !== void 0 ? `${finding.startLine}-${finding.line}` : `${finding.line}`;
|
|
14208
14373
|
console.warn(
|
|
14209
|
-
` ${
|
|
14374
|
+
` ${chalk144.yellow("\xB7")} ${finding.title} ${chalk144.dim(
|
|
14210
14375
|
`(${finding.file}:${range})`
|
|
14211
14376
|
)}`
|
|
14212
14377
|
);
|
|
@@ -14225,18 +14390,18 @@ function selectInDiffFindings(lineBound, prDiff) {
|
|
|
14225
14390
|
}
|
|
14226
14391
|
|
|
14227
14392
|
// src/commands/review/warnUnlocated.ts
|
|
14228
|
-
import
|
|
14393
|
+
import chalk145 from "chalk";
|
|
14229
14394
|
function warnUnlocated(unlocated) {
|
|
14230
14395
|
if (unlocated.length === 0) return;
|
|
14231
14396
|
console.warn(
|
|
14232
|
-
|
|
14397
|
+
chalk145.yellow(
|
|
14233
14398
|
`Skipped ${unlocated.length} finding(s) without a parseable file:line:`
|
|
14234
14399
|
)
|
|
14235
14400
|
);
|
|
14236
14401
|
for (const finding of unlocated) {
|
|
14237
|
-
const where = finding.location ||
|
|
14402
|
+
const where = finding.location || chalk145.dim("missing");
|
|
14238
14403
|
console.warn(
|
|
14239
|
-
` ${
|
|
14404
|
+
` ${chalk145.yellow("\xB7")} ${finding.title} ${chalk145.dim(`(${where})`)}`
|
|
14240
14405
|
);
|
|
14241
14406
|
}
|
|
14242
14407
|
}
|
|
@@ -15409,7 +15574,7 @@ function registerReview(program2) {
|
|
|
15409
15574
|
}
|
|
15410
15575
|
|
|
15411
15576
|
// src/commands/seq/seqAuth.ts
|
|
15412
|
-
import
|
|
15577
|
+
import chalk147 from "chalk";
|
|
15413
15578
|
|
|
15414
15579
|
// src/commands/seq/loadConnections.ts
|
|
15415
15580
|
function loadConnections2() {
|
|
@@ -15438,10 +15603,10 @@ function setDefaultConnection(name) {
|
|
|
15438
15603
|
}
|
|
15439
15604
|
|
|
15440
15605
|
// src/shared/assertUniqueName.ts
|
|
15441
|
-
import
|
|
15606
|
+
import chalk146 from "chalk";
|
|
15442
15607
|
function assertUniqueName(existingNames, name) {
|
|
15443
15608
|
if (existingNames.includes(name)) {
|
|
15444
|
-
console.error(
|
|
15609
|
+
console.error(chalk146.red(`Connection "${name}" already exists.`));
|
|
15445
15610
|
process.exit(1);
|
|
15446
15611
|
}
|
|
15447
15612
|
}
|
|
@@ -15459,16 +15624,16 @@ async function promptConnection2(existingNames) {
|
|
|
15459
15624
|
var seqAuth = createConnectionAuth({
|
|
15460
15625
|
load: loadConnections2,
|
|
15461
15626
|
save: saveConnections2,
|
|
15462
|
-
format: (c) => `${
|
|
15627
|
+
format: (c) => `${chalk147.bold(c.name)} ${c.url}`,
|
|
15463
15628
|
promptNew: promptConnection2,
|
|
15464
15629
|
onFirst: (c) => setDefaultConnection(c.name)
|
|
15465
15630
|
});
|
|
15466
15631
|
|
|
15467
15632
|
// src/commands/seq/seqQuery.ts
|
|
15468
|
-
import
|
|
15633
|
+
import chalk151 from "chalk";
|
|
15469
15634
|
|
|
15470
15635
|
// src/commands/seq/fetchSeq.ts
|
|
15471
|
-
import
|
|
15636
|
+
import chalk148 from "chalk";
|
|
15472
15637
|
async function fetchSeq(conn, path54, params) {
|
|
15473
15638
|
const url = `${conn.url}${path54}?${params}`;
|
|
15474
15639
|
const response = await fetch(url, {
|
|
@@ -15479,7 +15644,7 @@ async function fetchSeq(conn, path54, params) {
|
|
|
15479
15644
|
});
|
|
15480
15645
|
if (!response.ok) {
|
|
15481
15646
|
const body = await response.text();
|
|
15482
|
-
console.error(
|
|
15647
|
+
console.error(chalk148.red(`Seq returned ${response.status}: ${body}`));
|
|
15483
15648
|
process.exit(1);
|
|
15484
15649
|
}
|
|
15485
15650
|
return response;
|
|
@@ -15534,23 +15699,23 @@ async function fetchSeqEvents(conn, params) {
|
|
|
15534
15699
|
}
|
|
15535
15700
|
|
|
15536
15701
|
// src/commands/seq/formatEvent.ts
|
|
15537
|
-
import
|
|
15702
|
+
import chalk149 from "chalk";
|
|
15538
15703
|
function levelColor(level) {
|
|
15539
15704
|
switch (level) {
|
|
15540
15705
|
case "Fatal":
|
|
15541
|
-
return
|
|
15706
|
+
return chalk149.bgRed.white;
|
|
15542
15707
|
case "Error":
|
|
15543
|
-
return
|
|
15708
|
+
return chalk149.red;
|
|
15544
15709
|
case "Warning":
|
|
15545
|
-
return
|
|
15710
|
+
return chalk149.yellow;
|
|
15546
15711
|
case "Information":
|
|
15547
|
-
return
|
|
15712
|
+
return chalk149.cyan;
|
|
15548
15713
|
case "Debug":
|
|
15549
|
-
return
|
|
15714
|
+
return chalk149.gray;
|
|
15550
15715
|
case "Verbose":
|
|
15551
|
-
return
|
|
15716
|
+
return chalk149.dim;
|
|
15552
15717
|
default:
|
|
15553
|
-
return
|
|
15718
|
+
return chalk149.white;
|
|
15554
15719
|
}
|
|
15555
15720
|
}
|
|
15556
15721
|
function levelAbbrev(level) {
|
|
@@ -15591,12 +15756,12 @@ function formatTimestamp(iso) {
|
|
|
15591
15756
|
function formatEvent(event) {
|
|
15592
15757
|
const color = levelColor(event.Level);
|
|
15593
15758
|
const abbrev = levelAbbrev(event.Level);
|
|
15594
|
-
const ts8 =
|
|
15759
|
+
const ts8 = chalk149.dim(formatTimestamp(event.Timestamp));
|
|
15595
15760
|
const msg = renderMessage(event);
|
|
15596
15761
|
const lines = [`${ts8} ${color(`[${abbrev}]`)} ${msg}`];
|
|
15597
15762
|
if (event.Exception) {
|
|
15598
15763
|
for (const line of event.Exception.split("\n")) {
|
|
15599
|
-
lines.push(
|
|
15764
|
+
lines.push(chalk149.red(` ${line}`));
|
|
15600
15765
|
}
|
|
15601
15766
|
}
|
|
15602
15767
|
return lines.join("\n");
|
|
@@ -15629,11 +15794,11 @@ function rejectTimestampFilter(filter) {
|
|
|
15629
15794
|
}
|
|
15630
15795
|
|
|
15631
15796
|
// src/shared/resolveNamedConnection.ts
|
|
15632
|
-
import
|
|
15797
|
+
import chalk150 from "chalk";
|
|
15633
15798
|
function resolveNamedConnection(connections, requested, defaultName, kind, authCommand) {
|
|
15634
15799
|
if (connections.length === 0) {
|
|
15635
15800
|
console.error(
|
|
15636
|
-
|
|
15801
|
+
chalk150.red(
|
|
15637
15802
|
`No ${kind} connections configured. Run '${authCommand}' first.`
|
|
15638
15803
|
)
|
|
15639
15804
|
);
|
|
@@ -15642,7 +15807,7 @@ function resolveNamedConnection(connections, requested, defaultName, kind, authC
|
|
|
15642
15807
|
const target = requested ?? defaultName ?? connections[0].name;
|
|
15643
15808
|
const connection = connections.find((c) => c.name === target);
|
|
15644
15809
|
if (!connection) {
|
|
15645
|
-
console.error(
|
|
15810
|
+
console.error(chalk150.red(`${kind} connection "${target}" not found.`));
|
|
15646
15811
|
process.exit(1);
|
|
15647
15812
|
}
|
|
15648
15813
|
return connection;
|
|
@@ -15671,7 +15836,7 @@ async function seqQuery(filter, options2) {
|
|
|
15671
15836
|
new URLSearchParams({ filter, count: String(count6) })
|
|
15672
15837
|
);
|
|
15673
15838
|
if (events.length === 0) {
|
|
15674
|
-
console.log(
|
|
15839
|
+
console.log(chalk151.yellow("No events found."));
|
|
15675
15840
|
return;
|
|
15676
15841
|
}
|
|
15677
15842
|
if (options2.json) {
|
|
@@ -15682,11 +15847,11 @@ async function seqQuery(filter, options2) {
|
|
|
15682
15847
|
for (const event of chronological) {
|
|
15683
15848
|
console.log(formatEvent(event));
|
|
15684
15849
|
}
|
|
15685
|
-
console.log(
|
|
15850
|
+
console.log(chalk151.dim(`
|
|
15686
15851
|
${events.length} events`));
|
|
15687
15852
|
if (events.length >= count6) {
|
|
15688
15853
|
console.log(
|
|
15689
|
-
|
|
15854
|
+
chalk151.yellow(
|
|
15690
15855
|
`Results limited to ${count6}. Use --count to retrieve more.`
|
|
15691
15856
|
)
|
|
15692
15857
|
);
|
|
@@ -15694,10 +15859,10 @@ ${events.length} events`));
|
|
|
15694
15859
|
}
|
|
15695
15860
|
|
|
15696
15861
|
// src/shared/setNamedDefaultConnection.ts
|
|
15697
|
-
import
|
|
15862
|
+
import chalk152 from "chalk";
|
|
15698
15863
|
function setNamedDefaultConnection(connections, name, setDefault, kind) {
|
|
15699
15864
|
if (!connections.find((c) => c.name === name)) {
|
|
15700
|
-
console.error(
|
|
15865
|
+
console.error(chalk152.red(`Connection "${name}" not found.`));
|
|
15701
15866
|
process.exit(1);
|
|
15702
15867
|
}
|
|
15703
15868
|
setDefault(name);
|
|
@@ -15745,7 +15910,7 @@ function registerSignal(program2) {
|
|
|
15745
15910
|
}
|
|
15746
15911
|
|
|
15747
15912
|
// src/commands/sql/sqlAuth.ts
|
|
15748
|
-
import
|
|
15913
|
+
import chalk154 from "chalk";
|
|
15749
15914
|
|
|
15750
15915
|
// src/commands/sql/loadConnections.ts
|
|
15751
15916
|
function loadConnections3() {
|
|
@@ -15774,7 +15939,7 @@ function setDefaultConnection2(name) {
|
|
|
15774
15939
|
}
|
|
15775
15940
|
|
|
15776
15941
|
// src/commands/sql/promptConnection.ts
|
|
15777
|
-
import
|
|
15942
|
+
import chalk153 from "chalk";
|
|
15778
15943
|
async function promptConnection3(existingNames) {
|
|
15779
15944
|
const name = await promptInput("name", "Connection name:", "default");
|
|
15780
15945
|
assertUniqueName(existingNames, name);
|
|
@@ -15782,7 +15947,7 @@ async function promptConnection3(existingNames) {
|
|
|
15782
15947
|
const portStr = await promptInput("port", "Port:", "1433");
|
|
15783
15948
|
const port = Number.parseInt(portStr, 10);
|
|
15784
15949
|
if (!Number.isFinite(port)) {
|
|
15785
|
-
console.error(
|
|
15950
|
+
console.error(chalk153.red(`Invalid port "${portStr}".`));
|
|
15786
15951
|
process.exit(1);
|
|
15787
15952
|
}
|
|
15788
15953
|
const user = await promptInput("user", "User:");
|
|
@@ -15795,13 +15960,13 @@ async function promptConnection3(existingNames) {
|
|
|
15795
15960
|
var sqlAuth = createConnectionAuth({
|
|
15796
15961
|
load: loadConnections3,
|
|
15797
15962
|
save: saveConnections3,
|
|
15798
|
-
format: (c) => `${
|
|
15963
|
+
format: (c) => `${chalk154.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
|
|
15799
15964
|
promptNew: promptConnection3,
|
|
15800
15965
|
onFirst: (c) => setDefaultConnection2(c.name)
|
|
15801
15966
|
});
|
|
15802
15967
|
|
|
15803
15968
|
// src/commands/sql/printTable.ts
|
|
15804
|
-
import
|
|
15969
|
+
import chalk155 from "chalk";
|
|
15805
15970
|
function formatCell(value) {
|
|
15806
15971
|
if (value === null || value === void 0) return "";
|
|
15807
15972
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -15810,7 +15975,7 @@ function formatCell(value) {
|
|
|
15810
15975
|
}
|
|
15811
15976
|
function printTable(rows) {
|
|
15812
15977
|
if (rows.length === 0) {
|
|
15813
|
-
console.log(
|
|
15978
|
+
console.log(chalk155.yellow("(no rows)"));
|
|
15814
15979
|
return;
|
|
15815
15980
|
}
|
|
15816
15981
|
const columns = Object.keys(rows[0]);
|
|
@@ -15818,13 +15983,13 @@ function printTable(rows) {
|
|
|
15818
15983
|
(col) => Math.max(col.length, ...rows.map((r) => formatCell(r[col]).length))
|
|
15819
15984
|
);
|
|
15820
15985
|
const header = columns.map((c, i) => c.padEnd(widths[i])).join(" ");
|
|
15821
|
-
console.log(
|
|
15822
|
-
console.log(
|
|
15986
|
+
console.log(chalk155.dim(header));
|
|
15987
|
+
console.log(chalk155.dim("-".repeat(header.length)));
|
|
15823
15988
|
for (const row of rows) {
|
|
15824
15989
|
const line = columns.map((c, i) => formatCell(row[c]).padEnd(widths[i])).join(" ");
|
|
15825
15990
|
console.log(line);
|
|
15826
15991
|
}
|
|
15827
|
-
console.log(
|
|
15992
|
+
console.log(chalk155.dim(`
|
|
15828
15993
|
${rows.length} row${rows.length === 1 ? "" : "s"}`));
|
|
15829
15994
|
}
|
|
15830
15995
|
|
|
@@ -15884,7 +16049,7 @@ async function sqlColumns(table, connectionName) {
|
|
|
15884
16049
|
}
|
|
15885
16050
|
|
|
15886
16051
|
// src/commands/sql/sqlMutate.ts
|
|
15887
|
-
import
|
|
16052
|
+
import chalk156 from "chalk";
|
|
15888
16053
|
|
|
15889
16054
|
// src/commands/sql/isMutation.ts
|
|
15890
16055
|
var MUTATION_KEYWORDS = [
|
|
@@ -15918,7 +16083,7 @@ function isMutation(sql4) {
|
|
|
15918
16083
|
async function sqlMutate(query, connectionName) {
|
|
15919
16084
|
if (!isMutation(query)) {
|
|
15920
16085
|
console.error(
|
|
15921
|
-
|
|
16086
|
+
chalk156.red(
|
|
15922
16087
|
"assist sql mutate refuses non-mutating statements. Use `assist sql query` instead."
|
|
15923
16088
|
)
|
|
15924
16089
|
);
|
|
@@ -15928,18 +16093,18 @@ async function sqlMutate(query, connectionName) {
|
|
|
15928
16093
|
const pool = await sqlConnect(conn);
|
|
15929
16094
|
try {
|
|
15930
16095
|
const result = await pool.request().query(query);
|
|
15931
|
-
console.log(
|
|
16096
|
+
console.log(chalk156.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
|
|
15932
16097
|
} finally {
|
|
15933
16098
|
await pool.close();
|
|
15934
16099
|
}
|
|
15935
16100
|
}
|
|
15936
16101
|
|
|
15937
16102
|
// src/commands/sql/sqlQuery.ts
|
|
15938
|
-
import
|
|
16103
|
+
import chalk157 from "chalk";
|
|
15939
16104
|
async function sqlQuery(query, connectionName) {
|
|
15940
16105
|
if (isMutation(query)) {
|
|
15941
16106
|
console.error(
|
|
15942
|
-
|
|
16107
|
+
chalk157.red(
|
|
15943
16108
|
"assist sql query refuses mutating statements. Use `assist sql mutate` instead."
|
|
15944
16109
|
)
|
|
15945
16110
|
);
|
|
@@ -15954,7 +16119,7 @@ async function sqlQuery(query, connectionName) {
|
|
|
15954
16119
|
printTable(rows);
|
|
15955
16120
|
} else {
|
|
15956
16121
|
console.log(
|
|
15957
|
-
|
|
16122
|
+
chalk157.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
|
|
15958
16123
|
);
|
|
15959
16124
|
}
|
|
15960
16125
|
} finally {
|
|
@@ -16534,14 +16699,14 @@ import {
|
|
|
16534
16699
|
import { dirname as dirname22, join as join42 } from "path";
|
|
16535
16700
|
|
|
16536
16701
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
16537
|
-
import
|
|
16702
|
+
import chalk158 from "chalk";
|
|
16538
16703
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
16539
16704
|
function validateStagedContent(filename, content) {
|
|
16540
16705
|
const firstLine = content.split("\n")[0];
|
|
16541
16706
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
16542
16707
|
if (!match) {
|
|
16543
16708
|
console.error(
|
|
16544
|
-
|
|
16709
|
+
chalk158.red(
|
|
16545
16710
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
16546
16711
|
)
|
|
16547
16712
|
);
|
|
@@ -16550,7 +16715,7 @@ function validateStagedContent(filename, content) {
|
|
|
16550
16715
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
16551
16716
|
if (!contentAfterLink) {
|
|
16552
16717
|
console.error(
|
|
16553
|
-
|
|
16718
|
+
chalk158.red(
|
|
16554
16719
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
16555
16720
|
)
|
|
16556
16721
|
);
|
|
@@ -16754,7 +16919,7 @@ import { mkdirSync as mkdirSync18 } from "fs";
|
|
|
16754
16919
|
import { join as join47 } from "path";
|
|
16755
16920
|
|
|
16756
16921
|
// src/commands/voice/checkLockFile.ts
|
|
16757
|
-
import { execSync as
|
|
16922
|
+
import { execSync as execSync48 } from "child_process";
|
|
16758
16923
|
import { existsSync as existsSync45, mkdirSync as mkdirSync17, readFileSync as readFileSync35, writeFileSync as writeFileSync29 } from "fs";
|
|
16759
16924
|
import { join as join46 } from "path";
|
|
16760
16925
|
function isProcessAlive2(pid) {
|
|
@@ -16783,7 +16948,7 @@ function bootstrapVenv() {
|
|
|
16783
16948
|
if (existsSync45(getVenvPython())) return;
|
|
16784
16949
|
console.log("Setting up Python environment...");
|
|
16785
16950
|
const pythonDir = getPythonDir();
|
|
16786
|
-
|
|
16951
|
+
execSync48(
|
|
16787
16952
|
`uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
|
|
16788
16953
|
{
|
|
16789
16954
|
stdio: "inherit",
|
|
@@ -16947,7 +17112,7 @@ function registerVoice(program2) {
|
|
|
16947
17112
|
|
|
16948
17113
|
// src/commands/roam/auth.ts
|
|
16949
17114
|
import { randomBytes } from "crypto";
|
|
16950
|
-
import
|
|
17115
|
+
import chalk159 from "chalk";
|
|
16951
17116
|
|
|
16952
17117
|
// src/commands/roam/waitForCallback.ts
|
|
16953
17118
|
import { createServer as createServer2 } from "http";
|
|
@@ -17078,13 +17243,13 @@ async function auth() {
|
|
|
17078
17243
|
saveGlobalConfig(config);
|
|
17079
17244
|
const state = randomBytes(16).toString("hex");
|
|
17080
17245
|
console.log(
|
|
17081
|
-
|
|
17246
|
+
chalk159.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
17082
17247
|
);
|
|
17083
|
-
console.log(
|
|
17084
|
-
console.log(
|
|
17085
|
-
console.log(
|
|
17248
|
+
console.log(chalk159.white("http://localhost:14523/callback\n"));
|
|
17249
|
+
console.log(chalk159.blue("Opening browser for authorization..."));
|
|
17250
|
+
console.log(chalk159.dim("Waiting for authorization callback..."));
|
|
17086
17251
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
17087
|
-
console.log(
|
|
17252
|
+
console.log(chalk159.dim("Exchanging code for tokens..."));
|
|
17088
17253
|
const tokens = await exchangeToken({
|
|
17089
17254
|
code,
|
|
17090
17255
|
clientId,
|
|
@@ -17100,7 +17265,7 @@ async function auth() {
|
|
|
17100
17265
|
};
|
|
17101
17266
|
saveGlobalConfig(config);
|
|
17102
17267
|
console.log(
|
|
17103
|
-
|
|
17268
|
+
chalk159.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
17104
17269
|
);
|
|
17105
17270
|
}
|
|
17106
17271
|
|
|
@@ -17260,11 +17425,11 @@ function resolveParams(params, cliArgs) {
|
|
|
17260
17425
|
}
|
|
17261
17426
|
|
|
17262
17427
|
// src/commands/run/runPreCommands.ts
|
|
17263
|
-
import { execSync as
|
|
17428
|
+
import { execSync as execSync49 } from "child_process";
|
|
17264
17429
|
function runPreCommands(pre, cwd) {
|
|
17265
17430
|
for (const cmd of pre) {
|
|
17266
17431
|
try {
|
|
17267
|
-
|
|
17432
|
+
execSync49(cmd, { stdio: "inherit", cwd });
|
|
17268
17433
|
} catch (err) {
|
|
17269
17434
|
const code = err && typeof err === "object" && "status" in err ? err.status : 1;
|
|
17270
17435
|
process.exit(code);
|
|
@@ -17548,11 +17713,11 @@ function registerRun(program2) {
|
|
|
17548
17713
|
}
|
|
17549
17714
|
|
|
17550
17715
|
// src/commands/screenshot/index.ts
|
|
17551
|
-
import { execSync as
|
|
17716
|
+
import { execSync as execSync50 } from "child_process";
|
|
17552
17717
|
import { existsSync as existsSync50, mkdirSync as mkdirSync21, unlinkSync as unlinkSync17, writeFileSync as writeFileSync32 } from "fs";
|
|
17553
17718
|
import { tmpdir as tmpdir7 } from "os";
|
|
17554
17719
|
import { join as join53, resolve as resolve13 } from "path";
|
|
17555
|
-
import
|
|
17720
|
+
import chalk160 from "chalk";
|
|
17556
17721
|
|
|
17557
17722
|
// src/commands/screenshot/captureWindowPs1.ts
|
|
17558
17723
|
var captureWindowPs1 = `
|
|
@@ -17691,7 +17856,7 @@ function runPowerShellScript(processName, outputPath) {
|
|
|
17691
17856
|
const scriptPath = join53(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
17692
17857
|
writeFileSync32(scriptPath, captureWindowPs1, "utf-8");
|
|
17693
17858
|
try {
|
|
17694
|
-
|
|
17859
|
+
execSync50(
|
|
17695
17860
|
`powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
|
|
17696
17861
|
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }
|
|
17697
17862
|
);
|
|
@@ -17703,13 +17868,13 @@ function screenshot(processName) {
|
|
|
17703
17868
|
const config = loadConfig();
|
|
17704
17869
|
const outputDir = resolve13(config.screenshot.outputDir);
|
|
17705
17870
|
const outputPath = buildOutputPath(outputDir, processName);
|
|
17706
|
-
console.log(
|
|
17871
|
+
console.log(chalk160.gray(`Capturing window for process "${processName}" ...`));
|
|
17707
17872
|
try {
|
|
17708
17873
|
runPowerShellScript(processName, outputPath);
|
|
17709
|
-
console.log(
|
|
17874
|
+
console.log(chalk160.green(`Screenshot saved: ${outputPath}`));
|
|
17710
17875
|
} catch (error) {
|
|
17711
17876
|
const msg = error instanceof Error ? error.message : String(error);
|
|
17712
|
-
console.error(
|
|
17877
|
+
console.error(chalk160.red(`Failed to capture screenshot: ${msg}`));
|
|
17713
17878
|
process.exit(1);
|
|
17714
17879
|
}
|
|
17715
17880
|
}
|
|
@@ -18609,8 +18774,8 @@ var SessionManager = class {
|
|
|
18609
18774
|
watchActivity(session, this.notify);
|
|
18610
18775
|
return session.id;
|
|
18611
18776
|
}
|
|
18612
|
-
spawnWith(
|
|
18613
|
-
return this.add(
|
|
18777
|
+
spawnWith(create) {
|
|
18778
|
+
return this.add(create(String(this.nextId++)));
|
|
18614
18779
|
}
|
|
18615
18780
|
spawn(prompt, cwd) {
|
|
18616
18781
|
return this.spawnWith((id) => createSession(id, prompt, cwd));
|
|
@@ -18989,7 +19154,7 @@ function registerDaemon(program2) {
|
|
|
18989
19154
|
|
|
18990
19155
|
// src/commands/sessions/summarise/index.ts
|
|
18991
19156
|
import * as fs31 from "fs";
|
|
18992
|
-
import
|
|
19157
|
+
import chalk161 from "chalk";
|
|
18993
19158
|
|
|
18994
19159
|
// src/commands/sessions/summarise/shared.ts
|
|
18995
19160
|
import * as fs29 from "fs";
|
|
@@ -19116,22 +19281,22 @@ ${firstMessage}`);
|
|
|
19116
19281
|
async function summarise4(options2) {
|
|
19117
19282
|
const files = await discoverSessionJsonlPaths();
|
|
19118
19283
|
if (files.length === 0) {
|
|
19119
|
-
console.log(
|
|
19284
|
+
console.log(chalk161.yellow("No sessions found."));
|
|
19120
19285
|
return;
|
|
19121
19286
|
}
|
|
19122
19287
|
const toProcess = selectCandidates(files, options2);
|
|
19123
19288
|
if (toProcess.length === 0) {
|
|
19124
|
-
console.log(
|
|
19289
|
+
console.log(chalk161.green("All sessions already summarised."));
|
|
19125
19290
|
return;
|
|
19126
19291
|
}
|
|
19127
19292
|
console.log(
|
|
19128
|
-
|
|
19293
|
+
chalk161.cyan(
|
|
19129
19294
|
`Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
|
|
19130
19295
|
)
|
|
19131
19296
|
);
|
|
19132
19297
|
const { succeeded, failed: failed2 } = processSessions(toProcess);
|
|
19133
19298
|
console.log(
|
|
19134
|
-
|
|
19299
|
+
chalk161.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk161.yellow(`, ${failed2} skipped`) : "")
|
|
19135
19300
|
);
|
|
19136
19301
|
}
|
|
19137
19302
|
function selectCandidates(files, options2) {
|
|
@@ -19151,16 +19316,16 @@ function processSessions(files) {
|
|
|
19151
19316
|
let failed2 = 0;
|
|
19152
19317
|
for (let i = 0; i < files.length; i++) {
|
|
19153
19318
|
const file = files[i];
|
|
19154
|
-
process.stdout.write(
|
|
19319
|
+
process.stdout.write(chalk161.dim(` [${i + 1}/${files.length}] `));
|
|
19155
19320
|
const summary = summariseSession(file);
|
|
19156
19321
|
if (summary) {
|
|
19157
19322
|
writeSummary(file, summary);
|
|
19158
19323
|
succeeded++;
|
|
19159
|
-
process.stdout.write(`${
|
|
19324
|
+
process.stdout.write(`${chalk161.green("\u2713")} ${summary}
|
|
19160
19325
|
`);
|
|
19161
19326
|
} else {
|
|
19162
19327
|
failed2++;
|
|
19163
|
-
process.stdout.write(` ${
|
|
19328
|
+
process.stdout.write(` ${chalk161.yellow("skip")}
|
|
19164
19329
|
`);
|
|
19165
19330
|
}
|
|
19166
19331
|
}
|
|
@@ -19175,10 +19340,10 @@ function registerSessions(program2) {
|
|
|
19175
19340
|
}
|
|
19176
19341
|
|
|
19177
19342
|
// src/commands/statusLine.ts
|
|
19178
|
-
import
|
|
19343
|
+
import chalk163 from "chalk";
|
|
19179
19344
|
|
|
19180
19345
|
// src/commands/buildLimitsSegment.ts
|
|
19181
|
-
import
|
|
19346
|
+
import chalk162 from "chalk";
|
|
19182
19347
|
var FIVE_HOUR_SECONDS = 5 * 3600;
|
|
19183
19348
|
var SEVEN_DAY_SECONDS = 7 * 86400;
|
|
19184
19349
|
function formatTimeLeft(resetsAt) {
|
|
@@ -19201,10 +19366,10 @@ function projectUsage(pct, resetsAt, windowSeconds) {
|
|
|
19201
19366
|
function colorizeRateLimit(pct, resetsAt, windowSeconds) {
|
|
19202
19367
|
const label2 = `${Math.round(pct)}%`;
|
|
19203
19368
|
const projected = projectUsage(pct, resetsAt, windowSeconds);
|
|
19204
|
-
if (projected == null) return
|
|
19205
|
-
if (projected > 100) return
|
|
19206
|
-
if (projected > 75) return
|
|
19207
|
-
return
|
|
19369
|
+
if (projected == null) return chalk162.green(label2);
|
|
19370
|
+
if (projected > 100) return chalk162.red(label2);
|
|
19371
|
+
if (projected > 75) return chalk162.yellow(label2);
|
|
19372
|
+
return chalk162.green(label2);
|
|
19208
19373
|
}
|
|
19209
19374
|
function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel) {
|
|
19210
19375
|
const timeLabel = resetsAt ? formatTimeLeft(resetsAt) : fallbackLabel;
|
|
@@ -19230,14 +19395,14 @@ function buildLimitsSegment(rateLimits) {
|
|
|
19230
19395
|
}
|
|
19231
19396
|
|
|
19232
19397
|
// src/commands/statusLine.ts
|
|
19233
|
-
|
|
19398
|
+
chalk163.level = 3;
|
|
19234
19399
|
function formatNumber(num) {
|
|
19235
19400
|
return num.toLocaleString("en-US");
|
|
19236
19401
|
}
|
|
19237
19402
|
function colorizePercent(pct) {
|
|
19238
19403
|
const label2 = `${Math.round(pct)}%`;
|
|
19239
|
-
if (pct > 80) return
|
|
19240
|
-
if (pct > 40) return
|
|
19404
|
+
if (pct > 80) return chalk163.red(label2);
|
|
19405
|
+
if (pct > 40) return chalk163.yellow(label2);
|
|
19241
19406
|
return label2;
|
|
19242
19407
|
}
|
|
19243
19408
|
async function statusLine() {
|
|
@@ -19260,7 +19425,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
19260
19425
|
// src/commands/sync/syncClaudeMd.ts
|
|
19261
19426
|
import * as fs32 from "fs";
|
|
19262
19427
|
import * as path50 from "path";
|
|
19263
|
-
import
|
|
19428
|
+
import chalk164 from "chalk";
|
|
19264
19429
|
async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
19265
19430
|
const source = path50.join(claudeDir, "CLAUDE.md");
|
|
19266
19431
|
const target = path50.join(targetBase, "CLAUDE.md");
|
|
@@ -19269,12 +19434,12 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
19269
19434
|
const targetContent = fs32.readFileSync(target, "utf-8");
|
|
19270
19435
|
if (sourceContent !== targetContent) {
|
|
19271
19436
|
console.log(
|
|
19272
|
-
|
|
19437
|
+
chalk164.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
19273
19438
|
);
|
|
19274
19439
|
console.log();
|
|
19275
19440
|
printDiff(targetContent, sourceContent);
|
|
19276
19441
|
const confirm = options2?.yes || await promptConfirm(
|
|
19277
|
-
|
|
19442
|
+
chalk164.red("Overwrite existing CLAUDE.md?"),
|
|
19278
19443
|
false
|
|
19279
19444
|
);
|
|
19280
19445
|
if (!confirm) {
|
|
@@ -19290,7 +19455,7 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
|
|
|
19290
19455
|
// src/commands/sync/syncSettings.ts
|
|
19291
19456
|
import * as fs33 from "fs";
|
|
19292
19457
|
import * as path51 from "path";
|
|
19293
|
-
import
|
|
19458
|
+
import chalk165 from "chalk";
|
|
19294
19459
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
19295
19460
|
const source = path51.join(claudeDir, "settings.json");
|
|
19296
19461
|
const target = path51.join(targetBase, "settings.json");
|
|
@@ -19306,14 +19471,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
19306
19471
|
if (mergedContent !== normalizedTarget) {
|
|
19307
19472
|
if (!options2?.yes) {
|
|
19308
19473
|
console.log(
|
|
19309
|
-
|
|
19474
|
+
chalk165.yellow(
|
|
19310
19475
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
19311
19476
|
)
|
|
19312
19477
|
);
|
|
19313
19478
|
console.log();
|
|
19314
19479
|
printDiff(targetContent, mergedContent);
|
|
19315
19480
|
const confirm = await promptConfirm(
|
|
19316
|
-
|
|
19481
|
+
chalk165.red("Overwrite existing settings.json?"),
|
|
19317
19482
|
false
|
|
19318
19483
|
);
|
|
19319
19484
|
if (!confirm) {
|
|
@@ -19352,7 +19517,7 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
19352
19517
|
}
|
|
19353
19518
|
|
|
19354
19519
|
// src/commands/update.ts
|
|
19355
|
-
import { execSync as
|
|
19520
|
+
import { execSync as execSync51 } from "child_process";
|
|
19356
19521
|
import * as path53 from "path";
|
|
19357
19522
|
function isGlobalNpmInstall(dir) {
|
|
19358
19523
|
try {
|
|
@@ -19360,7 +19525,7 @@ function isGlobalNpmInstall(dir) {
|
|
|
19360
19525
|
if (resolved.split(path53.sep).includes("node_modules")) {
|
|
19361
19526
|
return true;
|
|
19362
19527
|
}
|
|
19363
|
-
const globalPrefix =
|
|
19528
|
+
const globalPrefix = execSync51("npm prefix -g", { stdio: "pipe" }).toString().trim();
|
|
19364
19529
|
return resolved.toLowerCase().startsWith(path53.resolve(globalPrefix).toLowerCase());
|
|
19365
19530
|
} catch {
|
|
19366
19531
|
return false;
|
|
@@ -19371,18 +19536,18 @@ async function update2() {
|
|
|
19371
19536
|
console.log(`Assist is installed at: ${installDir}`);
|
|
19372
19537
|
if (isGitRepo(installDir)) {
|
|
19373
19538
|
console.log("Detected git repo installation, pulling latest...");
|
|
19374
|
-
|
|
19539
|
+
execSync51("git pull", { cwd: installDir, stdio: "inherit" });
|
|
19375
19540
|
console.log("Installing dependencies...");
|
|
19376
|
-
|
|
19541
|
+
execSync51("npm i", { cwd: installDir, stdio: "inherit" });
|
|
19377
19542
|
console.log("Building...");
|
|
19378
|
-
|
|
19543
|
+
execSync51("npm run build", { cwd: installDir, stdio: "inherit" });
|
|
19379
19544
|
console.log("Syncing commands...");
|
|
19380
|
-
|
|
19545
|
+
execSync51("assist sync", { stdio: "inherit" });
|
|
19381
19546
|
} else if (isGlobalNpmInstall(installDir)) {
|
|
19382
19547
|
console.log("Detected global npm installation, updating...");
|
|
19383
|
-
|
|
19548
|
+
execSync51("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
|
|
19384
19549
|
console.log("Syncing commands...");
|
|
19385
|
-
|
|
19550
|
+
execSync51("assist sync", { stdio: "inherit" });
|
|
19386
19551
|
} else {
|
|
19387
19552
|
console.error(
|
|
19388
19553
|
"Could not determine installation method. Expected a git repo or global npm install."
|