@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/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.281.3",
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 collect3 = (node) => {
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
- collect3(sourceFile);
1850
- sourceFile.forEachDescendant(collect3);
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 asc2, eq as eq2 } from "drizzle-orm";
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(asc(comments.itemId), asc(comments.idx));
3207
- var selectLinks = (orm, ids) => orm.select().from(links).where(inArray(links.itemId, ids)).orderBy(asc(links.itemId));
3208
- var selectPhases = (orm, ids) => orm.select().from(planPhases).where(inArray(planPhases.itemId, ids)).orderBy(asc(planPhases.itemId), asc(planPhases.idx));
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
- asc(planTasks.itemId),
3211
- asc(planTasks.phaseIdx),
3212
- asc(planTasks.idx)
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(asc2(items.id));
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 asc3, eq as eq6, ilike, or } from "drizzle-orm";
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(asc3(items.id));
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(getHtml3) {
4436
+ function createHtmlHandler(getHtml2) {
4399
4437
  return (_req, res) => {
4400
4438
  res.writeHead(200, { "Content-Type": "text/html" });
4401
- res.end(getHtml3());
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(routes3) {
4446
+ function createRouteHandler(routes2) {
4409
4447
  return async (req, res, port) => {
4410
4448
  const { method, pathname } = parseRoute(req, port);
4411
- const handler = routes3[`${method} ${pathname}`];
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(routes3, htmlHandler2, extra) {
4574
- const baseHandler = createRouteHandler(routes3);
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 (routes3[`${method} ${pathname}`]) {
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 asc4, eq as eq10 } from "drizzle-orm";
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(asc4(items.id));
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 asc5, count as count5, eq as eq24 } from "drizzle-orm";
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(asc5(planPhases.idx));
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 reportDeny(toolName, parts) {
7568
- const denied = findDeny(toolName, parts);
7569
- if (!denied) return false;
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 config = loadGlobalConfigRaw();
10733
- const news = config.news ?? {};
10734
- const feeds = news.feeds ?? [];
10735
- if (feeds.includes(url)) {
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/news/web/handleRequest.ts
10746
- import chalk119 from "chalk";
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/news/web/shared.ts
10749
- import { decodeHTML } from "entities";
10750
- function extractText(xml, tag) {
10751
- const cdataMatch = xml.match(
10752
- new RegExp(`<${tag}>\\s*<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>\\s*</${tag}>`)
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 extractLink(itemXml) {
10759
- const atomLink = itemXml.match(
10760
- /<link[^>]*rel=["']alternate["'][^>]*href=["']([^"']+)["']/
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
- if (atomLink) return atomLink[1];
10763
- const atomLink2 = itemXml.match(/<link[^>]*href=["']([^"']+)["']/);
10764
- if (atomLink2) return atomLink2[1];
10765
- return extractText(itemXml, "link");
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
- function parseDate(dateStr) {
10768
- if (!dateStr) return (/* @__PURE__ */ new Date(0)).toISOString();
10769
- try {
10770
- return new Date(dateStr).toISOString();
10771
- } catch {
10772
- return (/* @__PURE__ */ new Date(0)).toISOString();
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/create.ts
11117
+ // src/commands/prs/edit.ts
11115
11118
  import { execSync as execSync33 } from "child_process";
11116
11119
 
11117
- // src/commands/prs/buildCreateArgs.ts
11118
- function buildCreateArgs(title, body, options2) {
11119
- const args = [
11120
- "gh pr create",
11121
- `--title ${shellQuote(title)}`,
11122
- `--body ${shellQuote(body)}`
11123
- ];
11124
- const valueFlags = [
11125
- ["--base", options2.base],
11126
- ["--head", options2.head],
11127
- ["--milestone", options2.milestone]
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
- if (options2.draft) args.push("--draft");
11133
- if (options2.web) args.push("--web");
11134
- const repeatableFlags = [
11135
- ["--label", options2.label],
11136
- ["--assignee", options2.assignee],
11137
- ["--reviewer", options2.reviewer]
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
- for (const [flag, values] of repeatableFlags) {
11140
- for (const value of values ?? []) {
11141
- args.push(`${flag} ${shellQuote(value)}`);
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
- return args;
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/create.ts
11160
- function create(options2) {
11161
- if (!options2.title || !options2.body) {
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 create --title <title> --body <body> [--base <branch>] [--head <branch>] [--draft] [--web] [--label <label>] [--assignee <login>] [--reviewer <handle>] [--milestone <name>]"
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
- validatePrContent(options2.title, options2.body);
11168
- const args = buildCreateArgs(options2.title, options2.body, options2);
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 chalk121 from "chalk";
11453
+ import chalk120 from "chalk";
11380
11454
  function formatForHuman(comment3) {
11381
11455
  if (comment3.type === "review") {
11382
- const stateColor = comment3.state === "APPROVED" ? chalk121.green : comment3.state === "CHANGES_REQUESTED" ? chalk121.red : chalk121.yellow;
11456
+ const stateColor = comment3.state === "APPROVED" ? chalk120.green : comment3.state === "CHANGES_REQUESTED" ? chalk120.red : chalk120.yellow;
11383
11457
  return [
11384
- `${chalk121.cyan("Review")} by ${chalk121.bold(comment3.user)} ${stateColor(`[${comment3.state}]`)}`,
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
- `${chalk121.cyan("Line comment")} by ${chalk121.bold(comment3.user)} on ${chalk121.dim(`${comment3.path}${location}`)}`,
11392
- chalk121.dim(comment3.diff_hunk.split("\n").slice(-3).join("\n")),
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 chalk122 from "chalk";
11556
+ import chalk121 from "chalk";
11483
11557
  var STATUS_MAP = {
11484
- MERGED: (pr) => pr.mergedAt ? { label: chalk122.magenta("merged"), date: pr.mergedAt } : null,
11485
- CLOSED: (pr) => pr.closedAt ? { label: chalk122.red("closed"), date: pr.closedAt } : null
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: chalk122.green("opened"), date: pr.createdAt };
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 `${chalk122.cyan(`#${pr.number}`)} ${pr.title} ${chalk122.dim(`(${pr.author.login},`)} ${status2.label} ${chalk122.dim(`${formatDate(status2.date)})`)}`;
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
- chalk122.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
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/wontfix.ts
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
- execSync39(`git cat-file -t ${sha}`, { stdio: "pipe" });
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/registerPrsCreate.ts
11791
+ // src/commands/registerPrsEdit.ts
11651
11792
  function collect2(value, previous) {
11652
11793
  return previous.concat([value]);
11653
11794
  }
11654
- function registerPrsCreate(prsCommand) {
11655
- prsCommand.command("create").description(
11656
- "Create a pull request via gh pr create, validating the title and body first"
11657
- ).option("-t, --title <title>", "Title for the pull request").option("-b, --body <body>", "Body for the pull request").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)", collect2, []).option(
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
- collect2,
11824
+ collect3,
11661
11825
  []
11662
11826
  ).option(
11663
11827
  "-r, --reviewer <handle>",
11664
11828
  "Request a review (repeatable)",
11665
- collect2,
11829
+ collect3,
11666
11830
  []
11667
- ).option("-m, --milestone <name>", "Add the pull request to a milestone").action(create);
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
- registerPrsCreate(prsCommand);
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 chalk128 from "chalk";
11854
+ import chalk127 from "chalk";
11690
11855
 
11691
11856
  // src/shared/createConnectionAuth.ts
11692
- import chalk123 from "chalk";
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(chalk123.red(`Connection "${name}" not found.`));
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 chalk126 from "chalk";
11916
+ import chalk125 from "chalk";
11752
11917
 
11753
11918
  // src/commands/ravendb/selectOpSecret.ts
11754
- import chalk125 from "chalk";
11919
+ import chalk124 from "chalk";
11755
11920
  import Enquirer2 from "enquirer";
11756
11921
 
11757
11922
  // src/commands/ravendb/searchItems.ts
11758
- import { execSync as execSync40 } from "child_process";
11759
- import chalk124 from "chalk";
11923
+ import { execSync as execSync41 } from "child_process";
11924
+ import chalk123 from "chalk";
11760
11925
  function opExec(args) {
11761
- return execSync40(`op ${args}`, {
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
- chalk124.red(
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(chalk124.red("Failed to get item details from 1Password."));
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(chalk125.red(`No items found matching "${search2}".`));
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(chalk125.red("No fields with references found on this item."));
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(chalk126.red(`Connection "${name}" already exists.`));
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(chalk126.red("All fields are required."));
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(chalk126.dim(`Using: ${apiKeyRef}`));
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 chalk127 from "chalk";
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(chalk127.red(`Connection "${name}" not found.`));
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) => `${chalk128.bold(c.name)} ${c.url} db=${c.database} key=${c.apiKeyRef}`,
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 chalk132 from "chalk";
12039
+ import chalk131 from "chalk";
11875
12040
 
11876
12041
  // src/commands/ravendb/ravenFetch.ts
11877
- import chalk130 from "chalk";
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 execSync41 } from "child_process";
11914
- import chalk129 from "chalk";
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(chalk129.red(`Invalid secret reference: must start with op://`));
12082
+ console.error(chalk128.red(`Invalid secret reference: must start with op://`));
11918
12083
  process.exit(1);
11919
12084
  }
11920
12085
  try {
11921
- return execSync41(`op read "${reference}"`, {
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
- chalk129.red(
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
- chalk130.red(`RavenDB error: ${response.status} ${response.statusText}`)
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 chalk131 from "chalk";
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
- chalk131.red(
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(chalk131.red(`Connection "${connectionName}" not found.`));
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(`${chalk132.bold(c.Name)} ${c.CountOfDocuments} docs`);
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 chalk134 from "chalk";
12186
+ import chalk133 from "chalk";
12022
12187
 
12023
12188
  // src/commands/ravendb/fetchAllPages.ts
12024
- import chalk133 from "chalk";
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${chalk133.dim(`Fetched ${allResults.length}/${totalResults}`)}`
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(chalk134.red("Provide a collection name or --query filter."));
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 chalk135 from "chalk";
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(chalk135.red(`
12289
+ console.error(chalk134.red(`
12125
12290
  Refactor check failed:
12126
12291
  `));
12127
- console.error(chalk135.red(` The following files exceed ${maxLines} lines:
12292
+ console.error(chalk134.red(` The following files exceed ${maxLines} lines:
12128
12293
  `));
12129
12294
  for (const violation of violations) {
12130
- console.error(chalk135.red(` ${violation.file} (${violation.lines} lines)`));
12295
+ console.error(chalk134.red(` ${violation.file} (${violation.lines} lines)`));
12131
12296
  }
12132
12297
  console.error(
12133
- chalk135.yellow(
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(chalk135.gray(` assist refactor ignore <file>
12305
+ console.error(chalk134.gray(` assist refactor ignore <file>
12141
12306
  `));
12142
12307
  if (process.env.CLAUDECODE) {
12143
- console.error(chalk135.cyan(`
12308
+ console.error(chalk134.cyan(`
12144
12309
  ## Extracting Code to New Files
12145
12310
  `));
12146
12311
  console.error(
12147
- chalk135.cyan(
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
- chalk135.cyan(
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
- chalk135.cyan(
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 execSync42 } from "child_process";
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 = execSync42("git diff --cached --name-only", {
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 = execSync42("git diff --name-only", { encoding: "utf-8" });
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 chalk138 from "chalk";
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 chalk136 from "chalk";
13056
+ import chalk135 from "chalk";
12892
13057
  function section(title) {
12893
13058
  return `
12894
- ${chalk136.cyan(title)}`;
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(` ${chalk136.dim(rel)}: \u2192 import from "${imp.relPath}"`);
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(chalk136.bold(`Extract: ${functionName} \u2192 ${relDest}
13070
+ console.log(chalk135.bold(`Extract: ${functionName} \u2192 ${relDest}
12906
13071
  `));
12907
- console.log(` ${chalk136.cyan("Functions to move:")}`);
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 chalk137 from "chalk";
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(chalk137.red(`File not found in project: ${file}`));
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(chalk138.green("\nExtraction complete"));
13189
+ console.log(chalk137.green("\nExtraction complete"));
13025
13190
  } else {
13026
- console.log(chalk138.dim("\nDry run. Use --apply to execute."));
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 chalk139 from "chalk";
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(chalk139.red(`Error: File does not exist: ${file}`));
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
- chalk139.green(
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 chalk140 from "chalk";
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(chalk140.bold(`Rename: ${relSource} \u2192 ${relDest}`));
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(chalk140.green("Done"));
13236
+ console.log(chalk139.green("Done"));
13072
13237
  } else {
13073
- console.log(chalk140.dim("Dry run. Use --apply to execute."));
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 chalk141 from "chalk";
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(chalk141.red(`Symbol "${oldName}" not found in ${file}`));
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
- chalk141.bold(`Rename: ${oldName} \u2192 ${newName} (${totalRefs} references)
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
- ` ${chalk141.dim(refFile)}: lines ${chalk141.cyan(lines.join(", "))}`
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(chalk141.green(`
13306
+ console.log(chalk140.green(`
13142
13307
  Renamed ${oldName} \u2192 ${newName}`));
13143
13308
  } else {
13144
- console.log(chalk141.dim("\nDry run. Use --apply to execute."));
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 chalk144 from "chalk";
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 chalk142 from "chalk";
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(chalk142.bold("\nFile moves:"));
13564
+ console.log(chalk141.bold("\nFile moves:"));
13400
13565
  for (const move of plan2.moves) {
13401
13566
  console.log(
13402
- ` ${chalk142.red(relPath(move.from))} \u2192 ${chalk142.green(relPath(move.to))}`
13567
+ ` ${chalk141.red(relPath(move.from))} \u2192 ${chalk141.green(relPath(move.to))}`
13403
13568
  );
13404
- console.log(chalk142.dim(` ${move.reason}`));
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(chalk142.bold(`
13575
+ console.log(chalk141.bold(`
13411
13576
  Import rewrites (${affectedFiles.size} files):`));
13412
13577
  for (const file of affectedFiles) {
13413
- console.log(` ${chalk142.cyan(relPath(file))}:`);
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
- ` ${chalk142.red(`"${oldSpecifier}"`)} \u2192 ${chalk142.green(`"${newSpecifier}"`)}`
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(chalk142.yellow("\nWarnings:"));
13426
- for (const w of plan2.warnings) console.log(chalk142.yellow(` ${w}`));
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(chalk142.bold("\nNew directories:"));
13594
+ console.log(chalk141.bold("\nNew directories:"));
13430
13595
  for (const dir of plan2.newDirectories)
13431
- console.log(chalk142.green(` ${dir}/`));
13596
+ console.log(chalk141.green(` ${dir}/`));
13432
13597
  }
13433
13598
  displayMoves(plan2);
13434
13599
  displayRewrites(plan2.rewrites);
13435
13600
  console.log(
13436
- chalk142.dim(
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 chalk143 from "chalk";
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
- chalk143.cyan(` Rewrote imports in ${path41.relative(process.cwd(), file)}`)
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(chalk143.green(` Created ${path41.relative(process.cwd(), dir)}/`));
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
- chalk143.white(
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
- chalk143.dim(
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(chalk144.yellow("No files found matching pattern"));
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(chalk144.green("No restructuring needed"));
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(chalk144.bold("\nApplying changes..."));
13790
+ console.log(chalk143.bold("\nApplying changes..."));
13626
13791
  executePlan(plan2);
13627
- console.log(chalk144.green("\nRestructuring complete"));
13792
+ console.log(chalk143.green("\nRestructuring complete"));
13628
13793
  } else {
13629
- console.log(chalk144.dim("\nDry run. Use --apply to execute."));
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 execSync43 } from "child_process";
13969
+ import { execSync as execSync44 } from "child_process";
13805
13970
  function fetchRawComments(org, repo, prNumber) {
13806
- const out = execSync43(
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 execSync46 } from "child_process";
14002
+ import { execSync as execSync47 } from "child_process";
13838
14003
 
13839
14004
  // src/commands/review/fetchPrDiff.ts
13840
- import { execSync as execSync44 } from "child_process";
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 execSync44(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
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
- execSync44(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
14024
+ execSync45(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
13860
14025
  } catch {
13861
14026
  }
13862
- return execSync44(`git diff ${baseSha}...${headSha}`, {
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 execSync45 } from "child_process";
14034
+ import { execSync as execSync46 } from "child_process";
13870
14035
  function getCurrentBranch2() {
13871
- return execSync45("git rev-parse --abbrev-ref HEAD", {
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 = execSync45(`gh pr view ${branch} --json ${fields} -R ${org}/${repo}`, {
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 = execSync45(
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 = execSync46("git rev-parse --abbrev-ref HEAD", {
14082
+ const branch = execSync47("git rev-parse --abbrev-ref HEAD", {
13918
14083
  encoding: "utf-8"
13919
14084
  }).trim();
13920
- const sha = execSync46("git rev-parse HEAD", { encoding: "utf-8" }).trim();
13921
- const shortSha = execSync46("git rev-parse --short=7 HEAD", {
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 chalk145 from "chalk";
14363
+ import chalk144 from "chalk";
14199
14364
  function warnOutOfDiff(outOfDiff) {
14200
14365
  if (outOfDiff.length === 0) return;
14201
14366
  console.warn(
14202
- chalk145.yellow(
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
- ` ${chalk145.yellow("\xB7")} ${finding.title} ${chalk145.dim(
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 chalk146 from "chalk";
14393
+ import chalk145 from "chalk";
14229
14394
  function warnUnlocated(unlocated) {
14230
14395
  if (unlocated.length === 0) return;
14231
14396
  console.warn(
14232
- chalk146.yellow(
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 || chalk146.dim("missing");
14402
+ const where = finding.location || chalk145.dim("missing");
14238
14403
  console.warn(
14239
- ` ${chalk146.yellow("\xB7")} ${finding.title} ${chalk146.dim(`(${where})`)}`
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 chalk148 from "chalk";
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 chalk147 from "chalk";
15606
+ import chalk146 from "chalk";
15442
15607
  function assertUniqueName(existingNames, name) {
15443
15608
  if (existingNames.includes(name)) {
15444
- console.error(chalk147.red(`Connection "${name}" already exists.`));
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) => `${chalk148.bold(c.name)} ${c.url}`,
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 chalk152 from "chalk";
15633
+ import chalk151 from "chalk";
15469
15634
 
15470
15635
  // src/commands/seq/fetchSeq.ts
15471
- import chalk149 from "chalk";
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(chalk149.red(`Seq returned ${response.status}: ${body}`));
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 chalk150 from "chalk";
15702
+ import chalk149 from "chalk";
15538
15703
  function levelColor(level) {
15539
15704
  switch (level) {
15540
15705
  case "Fatal":
15541
- return chalk150.bgRed.white;
15706
+ return chalk149.bgRed.white;
15542
15707
  case "Error":
15543
- return chalk150.red;
15708
+ return chalk149.red;
15544
15709
  case "Warning":
15545
- return chalk150.yellow;
15710
+ return chalk149.yellow;
15546
15711
  case "Information":
15547
- return chalk150.cyan;
15712
+ return chalk149.cyan;
15548
15713
  case "Debug":
15549
- return chalk150.gray;
15714
+ return chalk149.gray;
15550
15715
  case "Verbose":
15551
- return chalk150.dim;
15716
+ return chalk149.dim;
15552
15717
  default:
15553
- return chalk150.white;
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 = chalk150.dim(formatTimestamp(event.Timestamp));
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(chalk150.red(` ${line}`));
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 chalk151 from "chalk";
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
- chalk151.red(
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(chalk151.red(`${kind} connection "${target}" not found.`));
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(chalk152.yellow("No events found."));
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(chalk152.dim(`
15850
+ console.log(chalk151.dim(`
15686
15851
  ${events.length} events`));
15687
15852
  if (events.length >= count6) {
15688
15853
  console.log(
15689
- chalk152.yellow(
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 chalk153 from "chalk";
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(chalk153.red(`Connection "${name}" not found.`));
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 chalk155 from "chalk";
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 chalk154 from "chalk";
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(chalk154.red(`Invalid port "${portStr}".`));
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) => `${chalk155.bold(c.name)} ${c.server}:${c.port}/${c.database} (${c.user})`,
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 chalk156 from "chalk";
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(chalk156.yellow("(no rows)"));
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(chalk156.dim(header));
15822
- console.log(chalk156.dim("-".repeat(header.length)));
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(chalk156.dim(`
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 chalk157 from "chalk";
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
- chalk157.red(
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(chalk157.dim(`${result.rowsAffected.join(", ")} row(s) affected`));
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 chalk158 from "chalk";
16103
+ import chalk157 from "chalk";
15939
16104
  async function sqlQuery(query, connectionName) {
15940
16105
  if (isMutation(query)) {
15941
16106
  console.error(
15942
- chalk158.red(
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
- chalk158.dim(`${result.rowsAffected.join(", ")} row(s) affected`)
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 chalk159 from "chalk";
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
- chalk159.red(
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
- chalk159.red(
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 execSync47 } from "child_process";
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
- execSync47(
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 chalk160 from "chalk";
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
- chalk160.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
17246
+ chalk159.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
17082
17247
  );
17083
- console.log(chalk160.white("http://localhost:14523/callback\n"));
17084
- console.log(chalk160.blue("Opening browser for authorization..."));
17085
- console.log(chalk160.dim("Waiting for authorization callback..."));
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(chalk160.dim("Exchanging code for tokens..."));
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
- chalk160.green("Roam credentials and tokens saved to ~/.assist.yml")
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 execSync48 } from "child_process";
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
- execSync48(cmd, { stdio: "inherit", cwd });
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 execSync49 } from "child_process";
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 chalk161 from "chalk";
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
- execSync49(
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(chalk161.gray(`Capturing window for process "${processName}" ...`));
17871
+ console.log(chalk160.gray(`Capturing window for process "${processName}" ...`));
17707
17872
  try {
17708
17873
  runPowerShellScript(processName, outputPath);
17709
- console.log(chalk161.green(`Screenshot saved: ${outputPath}`));
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(chalk161.red(`Failed to capture screenshot: ${msg}`));
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(create2) {
18613
- return this.add(create2(String(this.nextId++)));
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 chalk162 from "chalk";
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(chalk162.yellow("No sessions found."));
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(chalk162.green("All sessions already summarised."));
19289
+ console.log(chalk161.green("All sessions already summarised."));
19125
19290
  return;
19126
19291
  }
19127
19292
  console.log(
19128
- chalk162.cyan(
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
- chalk162.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk162.yellow(`, ${failed2} skipped`) : "")
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(chalk162.dim(` [${i + 1}/${files.length}] `));
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(`${chalk162.green("\u2713")} ${summary}
19324
+ process.stdout.write(`${chalk161.green("\u2713")} ${summary}
19160
19325
  `);
19161
19326
  } else {
19162
19327
  failed2++;
19163
- process.stdout.write(` ${chalk162.yellow("skip")}
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 chalk164 from "chalk";
19343
+ import chalk163 from "chalk";
19179
19344
 
19180
19345
  // src/commands/buildLimitsSegment.ts
19181
- import chalk163 from "chalk";
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 chalk163.green(label2);
19205
- if (projected > 100) return chalk163.red(label2);
19206
- if (projected > 75) return chalk163.yellow(label2);
19207
- return chalk163.green(label2);
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
- chalk164.level = 3;
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 chalk164.red(label2);
19240
- if (pct > 40) return chalk164.yellow(label2);
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 chalk165 from "chalk";
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
- chalk165.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
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
- chalk165.red("Overwrite existing CLAUDE.md?"),
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 chalk166 from "chalk";
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
- chalk166.yellow(
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
- chalk166.red("Overwrite existing settings.json?"),
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 execSync50 } from "child_process";
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 = execSync50("npm prefix -g", { stdio: "pipe" }).toString().trim();
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
- execSync50("git pull", { cwd: installDir, stdio: "inherit" });
19539
+ execSync51("git pull", { cwd: installDir, stdio: "inherit" });
19375
19540
  console.log("Installing dependencies...");
19376
- execSync50("npm i", { cwd: installDir, stdio: "inherit" });
19541
+ execSync51("npm i", { cwd: installDir, stdio: "inherit" });
19377
19542
  console.log("Building...");
19378
- execSync50("npm run build", { cwd: installDir, stdio: "inherit" });
19543
+ execSync51("npm run build", { cwd: installDir, stdio: "inherit" });
19379
19544
  console.log("Syncing commands...");
19380
- execSync50("assist sync", { stdio: "inherit" });
19545
+ execSync51("assist sync", { stdio: "inherit" });
19381
19546
  } else if (isGlobalNpmInstall(installDir)) {
19382
19547
  console.log("Detected global npm installation, updating...");
19383
- execSync50("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
19548
+ execSync51("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
19384
19549
  console.log("Syncing commands...");
19385
- execSync50("assist sync", { stdio: "inherit" });
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."