@staff0rd/assist 0.107.0 → 0.108.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/claude/settings.json +1 -0
- package/dist/commands/news/web/bundle.js +66 -0
- package/dist/index.js +381 -132
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.108.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -40,6 +40,7 @@ var package_default = {
|
|
|
40
40
|
commander: "^14.0.2",
|
|
41
41
|
diff: "^8.0.2",
|
|
42
42
|
enquirer: "^2.4.1",
|
|
43
|
+
entities: "^7.0.1",
|
|
43
44
|
"is-wsl": "^3.1.0",
|
|
44
45
|
minimatch: "^10.1.1",
|
|
45
46
|
"node-notifier": "^10.0.1",
|
|
@@ -156,6 +157,9 @@ var assistConfigSchema = z.strictObject({
|
|
|
156
157
|
run: z.array(runConfigSchema).optional(),
|
|
157
158
|
transcript: transcriptConfigSchema.optional(),
|
|
158
159
|
cliReadVerbs: z.record(z.string(), z.array(z.string())).optional(),
|
|
160
|
+
news: z.strictObject({
|
|
161
|
+
feeds: z.array(z.string()).default([])
|
|
162
|
+
}).default({ feeds: [] }),
|
|
159
163
|
voice: z.strictObject({
|
|
160
164
|
wakeWords: z.array(z.string()).default(DEFAULT_WAKE_WORDS),
|
|
161
165
|
mic: z.string().optional(),
|
|
@@ -2346,15 +2350,63 @@ async function start(id) {
|
|
|
2346
2350
|
}
|
|
2347
2351
|
}
|
|
2348
2352
|
|
|
2349
|
-
// src/
|
|
2353
|
+
// src/shared/web.ts
|
|
2350
2354
|
import { exec } from "child_process";
|
|
2351
|
-
import { createServer } from "http";
|
|
2352
|
-
import chalk29 from "chalk";
|
|
2353
|
-
|
|
2354
|
-
// src/commands/backlog/web/handleRequest.ts
|
|
2355
2355
|
import { readFileSync as readFileSync12 } from "fs";
|
|
2356
|
+
import {
|
|
2357
|
+
createServer
|
|
2358
|
+
} from "http";
|
|
2356
2359
|
import { dirname as dirname11, join as join10 } from "path";
|
|
2357
2360
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2361
|
+
import chalk29 from "chalk";
|
|
2362
|
+
function respondJson(res, status2, data) {
|
|
2363
|
+
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
2364
|
+
res.end(JSON.stringify(data));
|
|
2365
|
+
}
|
|
2366
|
+
function createBundleHandler(importMetaUrl, bundlePath) {
|
|
2367
|
+
const dir = dirname11(fileURLToPath3(importMetaUrl));
|
|
2368
|
+
let cache;
|
|
2369
|
+
return (_req, res) => {
|
|
2370
|
+
if (!cache) {
|
|
2371
|
+
cache = readFileSync12(join10(dir, bundlePath), "utf-8");
|
|
2372
|
+
}
|
|
2373
|
+
res.writeHead(200, { "Content-Type": "application/javascript" });
|
|
2374
|
+
res.end(cache);
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2377
|
+
function createHtmlHandler(getHtml3) {
|
|
2378
|
+
return (_req, res) => {
|
|
2379
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
2380
|
+
res.end(getHtml3());
|
|
2381
|
+
};
|
|
2382
|
+
}
|
|
2383
|
+
function parseRoute(req, port) {
|
|
2384
|
+
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
2385
|
+
return { method: req.method ?? "GET", pathname: url.pathname };
|
|
2386
|
+
}
|
|
2387
|
+
function createRouteHandler(routes3) {
|
|
2388
|
+
return async (req, res, port) => {
|
|
2389
|
+
const { method, pathname } = parseRoute(req, port);
|
|
2390
|
+
const handler = routes3[`${method} ${pathname}`];
|
|
2391
|
+
if (handler) {
|
|
2392
|
+
await handler(req, res);
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
res.writeHead(404);
|
|
2396
|
+
res.end();
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
function startWebServer(label2, port, handler) {
|
|
2400
|
+
const url = `http://localhost:${port}`;
|
|
2401
|
+
const server = createServer((req, res) => {
|
|
2402
|
+
handler(req, res, port);
|
|
2403
|
+
});
|
|
2404
|
+
server.listen(port, () => {
|
|
2405
|
+
console.log(chalk29.green(`${label2}: ${url}`));
|
|
2406
|
+
console.log(chalk29.dim("Press Ctrl+C to stop"));
|
|
2407
|
+
exec(`open ${url}`);
|
|
2408
|
+
});
|
|
2409
|
+
}
|
|
2358
2410
|
|
|
2359
2411
|
// src/commands/backlog/web/getHtml.ts
|
|
2360
2412
|
function getHtml() {
|
|
@@ -2379,11 +2431,7 @@ function getHtml() {
|
|
|
2379
2431
|
</html>`;
|
|
2380
2432
|
}
|
|
2381
2433
|
|
|
2382
|
-
// src/commands/backlog/web/
|
|
2383
|
-
function respondJson(res, status2, data) {
|
|
2384
|
-
res.writeHead(status2, { "Content-Type": "application/json" });
|
|
2385
|
-
res.end(JSON.stringify(data));
|
|
2386
|
-
}
|
|
2434
|
+
// src/commands/backlog/web/parseItemBody.ts
|
|
2387
2435
|
function readBody(req) {
|
|
2388
2436
|
return new Promise((resolve6, reject) => {
|
|
2389
2437
|
let body = "";
|
|
@@ -2451,25 +2499,12 @@ async function updateItem(req, res, id) {
|
|
|
2451
2499
|
}
|
|
2452
2500
|
|
|
2453
2501
|
// src/commands/backlog/web/handleRequest.ts
|
|
2454
|
-
var __dirname4 = dirname11(fileURLToPath3(import.meta.url));
|
|
2455
|
-
var bundleCache;
|
|
2456
|
-
function serveBundle(_req, res) {
|
|
2457
|
-
if (!bundleCache) {
|
|
2458
|
-
bundleCache = readFileSync12(
|
|
2459
|
-
join10(__dirname4, "commands/backlog/web/bundle.js"),
|
|
2460
|
-
"utf-8"
|
|
2461
|
-
);
|
|
2462
|
-
}
|
|
2463
|
-
res.writeHead(200, { "Content-Type": "application/javascript" });
|
|
2464
|
-
res.end(bundleCache);
|
|
2465
|
-
}
|
|
2466
|
-
function serveHtml(_req, res) {
|
|
2467
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
2468
|
-
res.end(getHtml());
|
|
2469
|
-
}
|
|
2470
2502
|
var routes = {
|
|
2471
|
-
"GET /":
|
|
2472
|
-
"GET /bundle.js":
|
|
2503
|
+
"GET /": createHtmlHandler(getHtml),
|
|
2504
|
+
"GET /bundle.js": createBundleHandler(
|
|
2505
|
+
import.meta.url,
|
|
2506
|
+
"commands/backlog/web/bundle.js"
|
|
2507
|
+
),
|
|
2473
2508
|
"GET /api/items": listItems,
|
|
2474
2509
|
"POST /api/items": createItem
|
|
2475
2510
|
};
|
|
@@ -2478,17 +2513,11 @@ var itemRoutes = {
|
|
|
2478
2513
|
PUT: (req, res, id) => updateItem(req, res, id),
|
|
2479
2514
|
DELETE: (_req, res, id) => deleteItem(res, id)
|
|
2480
2515
|
};
|
|
2481
|
-
|
|
2482
|
-
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
2483
|
-
return { method: req.method ?? "GET", pathname: url.pathname };
|
|
2484
|
-
}
|
|
2516
|
+
var baseHandler = createRouteHandler(routes);
|
|
2485
2517
|
async function handleRequest(req, res, port) {
|
|
2486
|
-
const
|
|
2487
|
-
const
|
|
2488
|
-
|
|
2489
|
-
await handler(req, res);
|
|
2490
|
-
return;
|
|
2491
|
-
}
|
|
2518
|
+
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
2519
|
+
const method = req.method ?? "GET";
|
|
2520
|
+
const pathname = url.pathname;
|
|
2492
2521
|
const itemMatch = pathname.match(/^\/api\/items\/(\d+)$/);
|
|
2493
2522
|
if (itemMatch) {
|
|
2494
2523
|
const itemHandler = itemRoutes[method];
|
|
@@ -2497,22 +2526,16 @@ async function handleRequest(req, res, port) {
|
|
|
2497
2526
|
return;
|
|
2498
2527
|
}
|
|
2499
2528
|
}
|
|
2500
|
-
res
|
|
2501
|
-
res.end();
|
|
2529
|
+
await baseHandler(req, res, port);
|
|
2502
2530
|
}
|
|
2503
2531
|
|
|
2504
2532
|
// src/commands/backlog/web/index.ts
|
|
2505
2533
|
async function web(options2) {
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
handleRequest
|
|
2510
|
-
|
|
2511
|
-
server.listen(port, () => {
|
|
2512
|
-
console.log(chalk29.green(`Backlog web view: ${url}`));
|
|
2513
|
-
console.log(chalk29.dim("Press Ctrl+C to stop"));
|
|
2514
|
-
exec(`open ${url}`);
|
|
2515
|
-
});
|
|
2534
|
+
startWebServer(
|
|
2535
|
+
"Backlog web view",
|
|
2536
|
+
Number.parseInt(options2.port, 10),
|
|
2537
|
+
handleRequest
|
|
2538
|
+
);
|
|
2516
2539
|
}
|
|
2517
2540
|
|
|
2518
2541
|
// src/commands/registerBacklog.ts
|
|
@@ -2613,9 +2636,9 @@ import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSy
|
|
|
2613
2636
|
import { dirname as dirname12, resolve as resolve2 } from "path";
|
|
2614
2637
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
2615
2638
|
var __filename2 = fileURLToPath4(import.meta.url);
|
|
2616
|
-
var
|
|
2639
|
+
var __dirname4 = dirname12(__filename2);
|
|
2617
2640
|
function getCliReadsPath() {
|
|
2618
|
-
return resolve2(
|
|
2641
|
+
return resolve2(__dirname4, "..", "assist.cli-reads");
|
|
2619
2642
|
}
|
|
2620
2643
|
var cachedLines;
|
|
2621
2644
|
function getCliReadsLines() {
|
|
@@ -2834,9 +2857,9 @@ import { execSync as execSync13 } from "child_process";
|
|
|
2834
2857
|
import { dirname as dirname13, resolve as resolve4 } from "path";
|
|
2835
2858
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
2836
2859
|
var __filename3 = fileURLToPath5(import.meta.url);
|
|
2837
|
-
var
|
|
2860
|
+
var __dirname5 = dirname13(__filename3);
|
|
2838
2861
|
function getInstallDir() {
|
|
2839
|
-
return resolve4(
|
|
2862
|
+
return resolve4(__dirname5, "..");
|
|
2840
2863
|
}
|
|
2841
2864
|
function isGitRepo(dir) {
|
|
2842
2865
|
try {
|
|
@@ -4614,6 +4637,230 @@ function registerNetframework(program2) {
|
|
|
4614
4637
|
cmd.command("in-sln").description("Check whether a .csproj is referenced by any .sln file").argument("<csproj>", "Path to a .csproj file").action(inSln);
|
|
4615
4638
|
}
|
|
4616
4639
|
|
|
4640
|
+
// src/commands/news/add/index.ts
|
|
4641
|
+
import chalk49 from "chalk";
|
|
4642
|
+
import enquirer5 from "enquirer";
|
|
4643
|
+
async function add2(url) {
|
|
4644
|
+
if (!url) {
|
|
4645
|
+
const response = await enquirer5.prompt({
|
|
4646
|
+
type: "input",
|
|
4647
|
+
name: "url",
|
|
4648
|
+
message: "RSS feed URL:",
|
|
4649
|
+
validate: (value) => {
|
|
4650
|
+
try {
|
|
4651
|
+
new URL(value);
|
|
4652
|
+
return true;
|
|
4653
|
+
} catch {
|
|
4654
|
+
return "Please enter a valid URL";
|
|
4655
|
+
}
|
|
4656
|
+
}
|
|
4657
|
+
});
|
|
4658
|
+
url = response.url;
|
|
4659
|
+
}
|
|
4660
|
+
const config = loadGlobalConfigRaw();
|
|
4661
|
+
const news = config.news ?? {};
|
|
4662
|
+
const feeds = news.feeds ?? [];
|
|
4663
|
+
if (feeds.includes(url)) {
|
|
4664
|
+
console.log(chalk49.yellow("Feed already exists in config"));
|
|
4665
|
+
return;
|
|
4666
|
+
}
|
|
4667
|
+
feeds.push(url);
|
|
4668
|
+
config.news = { ...news, feeds };
|
|
4669
|
+
saveGlobalConfig(config);
|
|
4670
|
+
console.log(chalk49.green(`Added feed: ${url}`));
|
|
4671
|
+
}
|
|
4672
|
+
|
|
4673
|
+
// src/commands/news/web/handleRequest.ts
|
|
4674
|
+
import chalk50 from "chalk";
|
|
4675
|
+
|
|
4676
|
+
// src/commands/news/web/shared.ts
|
|
4677
|
+
import { decodeHTML } from "entities";
|
|
4678
|
+
function extractText(xml, tag) {
|
|
4679
|
+
const cdataMatch = xml.match(
|
|
4680
|
+
new RegExp(`<${tag}>\\s*<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>\\s*</${tag}>`)
|
|
4681
|
+
);
|
|
4682
|
+
if (cdataMatch) return cdataMatch[1].trim();
|
|
4683
|
+
const match = xml.match(new RegExp(`<${tag}[^>]*>([\\s\\S]*?)</${tag}>`));
|
|
4684
|
+
return match ? match[1].trim() : "";
|
|
4685
|
+
}
|
|
4686
|
+
function extractLink(itemXml) {
|
|
4687
|
+
const atomLink = itemXml.match(
|
|
4688
|
+
/<link[^>]*rel=["']alternate["'][^>]*href=["']([^"']+)["']/
|
|
4689
|
+
);
|
|
4690
|
+
if (atomLink) return atomLink[1];
|
|
4691
|
+
const atomLink2 = itemXml.match(/<link[^>]*href=["']([^"']+)["']/);
|
|
4692
|
+
if (atomLink2) return atomLink2[1];
|
|
4693
|
+
return extractText(itemXml, "link");
|
|
4694
|
+
}
|
|
4695
|
+
function parseDate(dateStr) {
|
|
4696
|
+
if (!dateStr) return (/* @__PURE__ */ new Date(0)).toISOString();
|
|
4697
|
+
try {
|
|
4698
|
+
return new Date(dateStr).toISOString();
|
|
4699
|
+
} catch {
|
|
4700
|
+
return (/* @__PURE__ */ new Date(0)).toISOString();
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
function stripHtml(html) {
|
|
4704
|
+
const decoded = decodeHTML(html);
|
|
4705
|
+
const stripped = decoded.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
4706
|
+
return decodeHTML(stripped);
|
|
4707
|
+
}
|
|
4708
|
+
function matchAll(xml, regex) {
|
|
4709
|
+
const results = [];
|
|
4710
|
+
for (const m of xml.matchAll(regex)) {
|
|
4711
|
+
results.push(m[1]);
|
|
4712
|
+
}
|
|
4713
|
+
return results;
|
|
4714
|
+
}
|
|
4715
|
+
var MAX_EXCERPT = 500;
|
|
4716
|
+
function excerpt(xml, ...tags) {
|
|
4717
|
+
for (const tag of tags) {
|
|
4718
|
+
const raw = extractText(xml, tag);
|
|
4719
|
+
if (!raw) continue;
|
|
4720
|
+
const text = stripHtml(raw);
|
|
4721
|
+
if (text.length <= MAX_EXCERPT) return text;
|
|
4722
|
+
return `${text.slice(0, MAX_EXCERPT)}\u2026`;
|
|
4723
|
+
}
|
|
4724
|
+
return "";
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4727
|
+
// src/commands/news/web/parseFeed.ts
|
|
4728
|
+
function parseRss(xml, feedOrigin) {
|
|
4729
|
+
const feedTitle = extractText(xml, "title");
|
|
4730
|
+
return matchAll(xml, /<item[\s>]([\s\S]*?)<\/item>/g).map((itemXml) => ({
|
|
4731
|
+
title: extractText(itemXml, "title"),
|
|
4732
|
+
link: extractLink(itemXml),
|
|
4733
|
+
pubDate: parseDate(
|
|
4734
|
+
extractText(itemXml, "pubDate") || extractText(itemXml, "dc:date")
|
|
4735
|
+
),
|
|
4736
|
+
feedTitle,
|
|
4737
|
+
feedOrigin,
|
|
4738
|
+
excerpt: excerpt(itemXml, "description", "content:encoded")
|
|
4739
|
+
}));
|
|
4740
|
+
}
|
|
4741
|
+
function parseAtom(xml, feedOrigin) {
|
|
4742
|
+
const feedTitle = extractText(xml, "title");
|
|
4743
|
+
return matchAll(xml, /<entry[\s>]([\s\S]*?)<\/entry>/g).map((entryXml) => ({
|
|
4744
|
+
title: extractText(entryXml, "title"),
|
|
4745
|
+
link: extractLink(entryXml),
|
|
4746
|
+
pubDate: parseDate(
|
|
4747
|
+
extractText(entryXml, "published") || extractText(entryXml, "updated")
|
|
4748
|
+
),
|
|
4749
|
+
feedTitle,
|
|
4750
|
+
feedOrigin,
|
|
4751
|
+
excerpt: excerpt(entryXml, "summary", "content")
|
|
4752
|
+
}));
|
|
4753
|
+
}
|
|
4754
|
+
function parseFeed(xml, feedOrigin) {
|
|
4755
|
+
if (xml.includes("<feed")) return parseAtom(xml, feedOrigin);
|
|
4756
|
+
return parseRss(xml, feedOrigin);
|
|
4757
|
+
}
|
|
4758
|
+
|
|
4759
|
+
// src/commands/news/web/fetchFeeds.ts
|
|
4760
|
+
async function fetchFeeds(urls, onProgress) {
|
|
4761
|
+
let done2 = 0;
|
|
4762
|
+
const results = await Promise.allSettled(
|
|
4763
|
+
urls.map(async (url) => {
|
|
4764
|
+
const origin = new URL(url).origin;
|
|
4765
|
+
const res = await fetch(url);
|
|
4766
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
4767
|
+
const items2 = parseFeed(await res.text(), origin);
|
|
4768
|
+
done2++;
|
|
4769
|
+
onProgress?.(done2, urls.length);
|
|
4770
|
+
return items2;
|
|
4771
|
+
})
|
|
4772
|
+
);
|
|
4773
|
+
const items = [];
|
|
4774
|
+
for (const result of results) {
|
|
4775
|
+
if (result.status === "fulfilled") {
|
|
4776
|
+
items.push(...result.value);
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
items.sort(
|
|
4780
|
+
(a, b) => new Date(b.pubDate).getTime() - new Date(a.pubDate).getTime()
|
|
4781
|
+
);
|
|
4782
|
+
return items;
|
|
4783
|
+
}
|
|
4784
|
+
|
|
4785
|
+
// src/commands/news/web/getHtml.ts
|
|
4786
|
+
function getHtml2() {
|
|
4787
|
+
return `<!DOCTYPE html>
|
|
4788
|
+
<html lang="en" class="dark">
|
|
4789
|
+
<head>
|
|
4790
|
+
<meta charset="UTF-8">
|
|
4791
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
4792
|
+
<title>News</title>
|
|
4793
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
4794
|
+
<script>tailwind.config={darkMode:'class'}</script>
|
|
4795
|
+
</head>
|
|
4796
|
+
<body class="font-[-apple-system,BlinkMacSystemFont,'Segoe_UI',Roboto,sans-serif] bg-gray-950 text-gray-200 leading-normal">
|
|
4797
|
+
<div class="max-w-3xl mx-auto px-4 py-6" id="app"></div>
|
|
4798
|
+
<script src="/bundle.js"></script>
|
|
4799
|
+
</body>
|
|
4800
|
+
</html>`;
|
|
4801
|
+
}
|
|
4802
|
+
|
|
4803
|
+
// src/commands/news/web/handleRequest.ts
|
|
4804
|
+
var cachedItems;
|
|
4805
|
+
var prefetchPromise;
|
|
4806
|
+
function prefetch() {
|
|
4807
|
+
const config = loadConfig();
|
|
4808
|
+
const total = config.news.feeds.length;
|
|
4809
|
+
if (total === 0) return;
|
|
4810
|
+
process.stdout.write(chalk50.dim(`Fetching ${total} feed(s)\u2026 `));
|
|
4811
|
+
prefetchPromise = fetchFeeds(config.news.feeds, (done2, t) => {
|
|
4812
|
+
const width = 20;
|
|
4813
|
+
const filled = Math.round(done2 / t * width);
|
|
4814
|
+
const bar = `${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}`;
|
|
4815
|
+
process.stdout.write(
|
|
4816
|
+
`\r${chalk50.dim(`Fetching feeds ${bar} ${done2}/${t}`)}`
|
|
4817
|
+
);
|
|
4818
|
+
}).then((items) => {
|
|
4819
|
+
process.stdout.write(
|
|
4820
|
+
`\r${chalk50.green(`Fetched ${items.length} items from ${total} feed(s)`)}
|
|
4821
|
+
`
|
|
4822
|
+
);
|
|
4823
|
+
cachedItems = items;
|
|
4824
|
+
return items;
|
|
4825
|
+
});
|
|
4826
|
+
}
|
|
4827
|
+
async function listItems2(_req, res) {
|
|
4828
|
+
if (!cachedItems && prefetchPromise) {
|
|
4829
|
+
await prefetchPromise;
|
|
4830
|
+
}
|
|
4831
|
+
if (!cachedItems) {
|
|
4832
|
+
const config = loadConfig();
|
|
4833
|
+
cachedItems = await fetchFeeds(config.news.feeds);
|
|
4834
|
+
}
|
|
4835
|
+
respondJson(res, 200, cachedItems);
|
|
4836
|
+
}
|
|
4837
|
+
var routes2 = {
|
|
4838
|
+
"GET /": createHtmlHandler(getHtml2),
|
|
4839
|
+
"GET /bundle.js": createBundleHandler(
|
|
4840
|
+
import.meta.url,
|
|
4841
|
+
"commands/news/web/bundle.js"
|
|
4842
|
+
),
|
|
4843
|
+
"GET /api/items": listItems2
|
|
4844
|
+
};
|
|
4845
|
+
var handleRequest2 = createRouteHandler(routes2);
|
|
4846
|
+
|
|
4847
|
+
// src/commands/news/web/index.ts
|
|
4848
|
+
async function web2(options2) {
|
|
4849
|
+
prefetch();
|
|
4850
|
+
startWebServer(
|
|
4851
|
+
"News web view",
|
|
4852
|
+
Number.parseInt(options2.port, 10),
|
|
4853
|
+
handleRequest2
|
|
4854
|
+
);
|
|
4855
|
+
}
|
|
4856
|
+
|
|
4857
|
+
// src/commands/registerNews.ts
|
|
4858
|
+
function registerNews(program2) {
|
|
4859
|
+
const newsCommand = program2.command("news").description("View latest news from configured RSS feeds").action(() => web2({ port: "3001" }));
|
|
4860
|
+
newsCommand.command("add").description("Add an RSS feed URL to the config").argument("<url>", "RSS feed URL").action(add2);
|
|
4861
|
+
newsCommand.command("web").description("Start a web view of the news feeds").option("-p, --port <number>", "Port to listen on", "3001").action(web2);
|
|
4862
|
+
}
|
|
4863
|
+
|
|
4617
4864
|
// src/commands/prs/comment.ts
|
|
4618
4865
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
4619
4866
|
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync17 } from "fs";
|
|
@@ -4838,6 +5085,7 @@ function fixed(commentId, sha) {
|
|
|
4838
5085
|
const { org, repo } = getRepoInfo();
|
|
4839
5086
|
const repoUrl = `https://github.com/${org}/${repo}`;
|
|
4840
5087
|
const message = `Fixed in [${fullSha}](${repoUrl}/commit/${fullSha})`;
|
|
5088
|
+
execSync24("git push", { stdio: "inherit" });
|
|
4841
5089
|
resolveCommentWithReply(commentId, message);
|
|
4842
5090
|
} catch (error) {
|
|
4843
5091
|
if (isGhNotInstalled(error)) {
|
|
@@ -4930,20 +5178,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
4930
5178
|
}
|
|
4931
5179
|
|
|
4932
5180
|
// src/commands/prs/listComments/printComments.ts
|
|
4933
|
-
import
|
|
5181
|
+
import chalk51 from "chalk";
|
|
4934
5182
|
function formatForHuman(comment2) {
|
|
4935
5183
|
if (comment2.type === "review") {
|
|
4936
|
-
const stateColor = comment2.state === "APPROVED" ?
|
|
5184
|
+
const stateColor = comment2.state === "APPROVED" ? chalk51.green : comment2.state === "CHANGES_REQUESTED" ? chalk51.red : chalk51.yellow;
|
|
4937
5185
|
return [
|
|
4938
|
-
`${
|
|
5186
|
+
`${chalk51.cyan("Review")} by ${chalk51.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
4939
5187
|
comment2.body,
|
|
4940
5188
|
""
|
|
4941
5189
|
].join("\n");
|
|
4942
5190
|
}
|
|
4943
5191
|
const location = comment2.line ? `:${comment2.line}` : "";
|
|
4944
5192
|
return [
|
|
4945
|
-
`${
|
|
4946
|
-
|
|
5193
|
+
`${chalk51.cyan("Line comment")} by ${chalk51.bold(comment2.user)} on ${chalk51.dim(`${comment2.path}${location}`)}`,
|
|
5194
|
+
chalk51.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
4947
5195
|
comment2.body,
|
|
4948
5196
|
""
|
|
4949
5197
|
].join("\n");
|
|
@@ -5030,16 +5278,16 @@ async function listComments() {
|
|
|
5030
5278
|
import { execSync as execSync27 } from "child_process";
|
|
5031
5279
|
|
|
5032
5280
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
5033
|
-
import
|
|
5281
|
+
import enquirer6 from "enquirer";
|
|
5034
5282
|
|
|
5035
5283
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
5036
|
-
import
|
|
5284
|
+
import chalk52 from "chalk";
|
|
5037
5285
|
var STATUS_MAP = {
|
|
5038
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
5039
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
5286
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk52.magenta("merged"), date: pr.mergedAt } : null,
|
|
5287
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk52.red("closed"), date: pr.closedAt } : null
|
|
5040
5288
|
};
|
|
5041
5289
|
function defaultStatus(pr) {
|
|
5042
|
-
return { label:
|
|
5290
|
+
return { label: chalk52.green("opened"), date: pr.createdAt };
|
|
5043
5291
|
}
|
|
5044
5292
|
function getStatus2(pr) {
|
|
5045
5293
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -5048,11 +5296,11 @@ function formatDate(dateStr) {
|
|
|
5048
5296
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
5049
5297
|
}
|
|
5050
5298
|
function formatPrHeader(pr, status2) {
|
|
5051
|
-
return `${
|
|
5299
|
+
return `${chalk52.cyan(`#${pr.number}`)} ${pr.title} ${chalk52.dim(`(${pr.author.login},`)} ${status2.label} ${chalk52.dim(`${formatDate(status2.date)})`)}`;
|
|
5052
5300
|
}
|
|
5053
5301
|
function logPrDetails(pr) {
|
|
5054
5302
|
console.log(
|
|
5055
|
-
|
|
5303
|
+
chalk52.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
5056
5304
|
);
|
|
5057
5305
|
console.log();
|
|
5058
5306
|
}
|
|
@@ -5100,7 +5348,7 @@ function parseAction(action) {
|
|
|
5100
5348
|
}
|
|
5101
5349
|
async function promptNavigation(currentPage, totalPages) {
|
|
5102
5350
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
5103
|
-
const { action } = await
|
|
5351
|
+
const { action } = await enquirer6.prompt({
|
|
5104
5352
|
type: "select",
|
|
5105
5353
|
name: "action",
|
|
5106
5354
|
message: "Navigate",
|
|
@@ -5222,7 +5470,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
5222
5470
|
import * as path21 from "path";
|
|
5223
5471
|
|
|
5224
5472
|
// src/commands/refactor/logViolations.ts
|
|
5225
|
-
import
|
|
5473
|
+
import chalk53 from "chalk";
|
|
5226
5474
|
var DEFAULT_MAX_LINES = 100;
|
|
5227
5475
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
5228
5476
|
if (violations.length === 0) {
|
|
@@ -5231,43 +5479,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
5231
5479
|
}
|
|
5232
5480
|
return;
|
|
5233
5481
|
}
|
|
5234
|
-
console.error(
|
|
5482
|
+
console.error(chalk53.red(`
|
|
5235
5483
|
Refactor check failed:
|
|
5236
5484
|
`));
|
|
5237
|
-
console.error(
|
|
5485
|
+
console.error(chalk53.red(` The following files exceed ${maxLines} lines:
|
|
5238
5486
|
`));
|
|
5239
5487
|
for (const violation of violations) {
|
|
5240
|
-
console.error(
|
|
5488
|
+
console.error(chalk53.red(` ${violation.file} (${violation.lines} lines)`));
|
|
5241
5489
|
}
|
|
5242
5490
|
console.error(
|
|
5243
|
-
|
|
5491
|
+
chalk53.yellow(
|
|
5244
5492
|
`
|
|
5245
5493
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
5246
5494
|
way to refactor it, ignore it with:
|
|
5247
5495
|
`
|
|
5248
5496
|
)
|
|
5249
5497
|
);
|
|
5250
|
-
console.error(
|
|
5498
|
+
console.error(chalk53.gray(` assist refactor ignore <file>
|
|
5251
5499
|
`));
|
|
5252
5500
|
if (process.env.CLAUDECODE) {
|
|
5253
|
-
console.error(
|
|
5501
|
+
console.error(chalk53.cyan(`
|
|
5254
5502
|
## Extracting Code to New Files
|
|
5255
5503
|
`));
|
|
5256
5504
|
console.error(
|
|
5257
|
-
|
|
5505
|
+
chalk53.cyan(
|
|
5258
5506
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
5259
5507
|
`
|
|
5260
5508
|
)
|
|
5261
5509
|
);
|
|
5262
5510
|
console.error(
|
|
5263
|
-
|
|
5511
|
+
chalk53.cyan(
|
|
5264
5512
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
5265
5513
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
5266
5514
|
`
|
|
5267
5515
|
)
|
|
5268
5516
|
);
|
|
5269
5517
|
console.error(
|
|
5270
|
-
|
|
5518
|
+
chalk53.cyan(
|
|
5271
5519
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
5272
5520
|
domains, move it to a common/shared folder.
|
|
5273
5521
|
`
|
|
@@ -5423,11 +5671,11 @@ async function check(pattern2, options2) {
|
|
|
5423
5671
|
|
|
5424
5672
|
// src/commands/refactor/ignore.ts
|
|
5425
5673
|
import fs16 from "fs";
|
|
5426
|
-
import
|
|
5674
|
+
import chalk54 from "chalk";
|
|
5427
5675
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
5428
5676
|
function ignore(file) {
|
|
5429
5677
|
if (!fs16.existsSync(file)) {
|
|
5430
|
-
console.error(
|
|
5678
|
+
console.error(chalk54.red(`Error: File does not exist: ${file}`));
|
|
5431
5679
|
process.exit(1);
|
|
5432
5680
|
}
|
|
5433
5681
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -5443,7 +5691,7 @@ function ignore(file) {
|
|
|
5443
5691
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
5444
5692
|
}
|
|
5445
5693
|
console.log(
|
|
5446
|
-
|
|
5694
|
+
chalk54.green(
|
|
5447
5695
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
5448
5696
|
)
|
|
5449
5697
|
);
|
|
@@ -5451,7 +5699,7 @@ function ignore(file) {
|
|
|
5451
5699
|
|
|
5452
5700
|
// src/commands/refactor/restructure/index.ts
|
|
5453
5701
|
import path30 from "path";
|
|
5454
|
-
import
|
|
5702
|
+
import chalk57 from "chalk";
|
|
5455
5703
|
|
|
5456
5704
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
5457
5705
|
import path22 from "path";
|
|
@@ -5694,50 +5942,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
5694
5942
|
|
|
5695
5943
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
5696
5944
|
import path26 from "path";
|
|
5697
|
-
import
|
|
5945
|
+
import chalk55 from "chalk";
|
|
5698
5946
|
function relPath(filePath) {
|
|
5699
5947
|
return path26.relative(process.cwd(), filePath);
|
|
5700
5948
|
}
|
|
5701
5949
|
function displayMoves(plan) {
|
|
5702
5950
|
if (plan.moves.length === 0) return;
|
|
5703
|
-
console.log(
|
|
5951
|
+
console.log(chalk55.bold("\nFile moves:"));
|
|
5704
5952
|
for (const move of plan.moves) {
|
|
5705
5953
|
console.log(
|
|
5706
|
-
` ${
|
|
5954
|
+
` ${chalk55.red(relPath(move.from))} \u2192 ${chalk55.green(relPath(move.to))}`
|
|
5707
5955
|
);
|
|
5708
|
-
console.log(
|
|
5956
|
+
console.log(chalk55.dim(` ${move.reason}`));
|
|
5709
5957
|
}
|
|
5710
5958
|
}
|
|
5711
5959
|
function displayRewrites(rewrites) {
|
|
5712
5960
|
if (rewrites.length === 0) return;
|
|
5713
5961
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
5714
|
-
console.log(
|
|
5962
|
+
console.log(chalk55.bold(`
|
|
5715
5963
|
Import rewrites (${affectedFiles.size} files):`));
|
|
5716
5964
|
for (const file of affectedFiles) {
|
|
5717
|
-
console.log(` ${
|
|
5965
|
+
console.log(` ${chalk55.cyan(relPath(file))}:`);
|
|
5718
5966
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
5719
5967
|
(r) => r.file === file
|
|
5720
5968
|
)) {
|
|
5721
5969
|
console.log(
|
|
5722
|
-
` ${
|
|
5970
|
+
` ${chalk55.red(`"${oldSpecifier}"`)} \u2192 ${chalk55.green(`"${newSpecifier}"`)}`
|
|
5723
5971
|
);
|
|
5724
5972
|
}
|
|
5725
5973
|
}
|
|
5726
5974
|
}
|
|
5727
5975
|
function displayPlan(plan) {
|
|
5728
5976
|
if (plan.warnings.length > 0) {
|
|
5729
|
-
console.log(
|
|
5730
|
-
for (const w of plan.warnings) console.log(
|
|
5977
|
+
console.log(chalk55.yellow("\nWarnings:"));
|
|
5978
|
+
for (const w of plan.warnings) console.log(chalk55.yellow(` ${w}`));
|
|
5731
5979
|
}
|
|
5732
5980
|
if (plan.newDirectories.length > 0) {
|
|
5733
|
-
console.log(
|
|
5981
|
+
console.log(chalk55.bold("\nNew directories:"));
|
|
5734
5982
|
for (const dir of plan.newDirectories)
|
|
5735
|
-
console.log(
|
|
5983
|
+
console.log(chalk55.green(` ${dir}/`));
|
|
5736
5984
|
}
|
|
5737
5985
|
displayMoves(plan);
|
|
5738
5986
|
displayRewrites(plan.rewrites);
|
|
5739
5987
|
console.log(
|
|
5740
|
-
|
|
5988
|
+
chalk55.dim(
|
|
5741
5989
|
`
|
|
5742
5990
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
5743
5991
|
)
|
|
@@ -5747,18 +5995,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
5747
5995
|
// src/commands/refactor/restructure/executePlan.ts
|
|
5748
5996
|
import fs18 from "fs";
|
|
5749
5997
|
import path27 from "path";
|
|
5750
|
-
import
|
|
5998
|
+
import chalk56 from "chalk";
|
|
5751
5999
|
function executePlan(plan) {
|
|
5752
6000
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
5753
6001
|
for (const [file, content] of updatedContents) {
|
|
5754
6002
|
fs18.writeFileSync(file, content, "utf-8");
|
|
5755
6003
|
console.log(
|
|
5756
|
-
|
|
6004
|
+
chalk56.cyan(` Rewrote imports in ${path27.relative(process.cwd(), file)}`)
|
|
5757
6005
|
);
|
|
5758
6006
|
}
|
|
5759
6007
|
for (const dir of plan.newDirectories) {
|
|
5760
6008
|
fs18.mkdirSync(dir, { recursive: true });
|
|
5761
|
-
console.log(
|
|
6009
|
+
console.log(chalk56.green(` Created ${path27.relative(process.cwd(), dir)}/`));
|
|
5762
6010
|
}
|
|
5763
6011
|
for (const move of plan.moves) {
|
|
5764
6012
|
const targetDir = path27.dirname(move.to);
|
|
@@ -5767,7 +6015,7 @@ function executePlan(plan) {
|
|
|
5767
6015
|
}
|
|
5768
6016
|
fs18.renameSync(move.from, move.to);
|
|
5769
6017
|
console.log(
|
|
5770
|
-
|
|
6018
|
+
chalk56.white(
|
|
5771
6019
|
` Moved ${path27.relative(process.cwd(), move.from)} \u2192 ${path27.relative(process.cwd(), move.to)}`
|
|
5772
6020
|
)
|
|
5773
6021
|
);
|
|
@@ -5782,7 +6030,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
5782
6030
|
if (entries.length === 0) {
|
|
5783
6031
|
fs18.rmdirSync(dir);
|
|
5784
6032
|
console.log(
|
|
5785
|
-
|
|
6033
|
+
chalk56.dim(
|
|
5786
6034
|
` Removed empty directory ${path27.relative(process.cwd(), dir)}`
|
|
5787
6035
|
)
|
|
5788
6036
|
);
|
|
@@ -5913,22 +6161,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
5913
6161
|
const targetPattern = pattern2 ?? "src";
|
|
5914
6162
|
const files = findSourceFiles2(targetPattern);
|
|
5915
6163
|
if (files.length === 0) {
|
|
5916
|
-
console.log(
|
|
6164
|
+
console.log(chalk57.yellow("No files found matching pattern"));
|
|
5917
6165
|
return;
|
|
5918
6166
|
}
|
|
5919
6167
|
const tsConfigPath = path30.resolve("tsconfig.json");
|
|
5920
6168
|
const plan = buildPlan(files, tsConfigPath);
|
|
5921
6169
|
if (plan.moves.length === 0) {
|
|
5922
|
-
console.log(
|
|
6170
|
+
console.log(chalk57.green("No restructuring needed"));
|
|
5923
6171
|
return;
|
|
5924
6172
|
}
|
|
5925
6173
|
displayPlan(plan);
|
|
5926
6174
|
if (options2.apply) {
|
|
5927
|
-
console.log(
|
|
6175
|
+
console.log(chalk57.bold("\nApplying changes..."));
|
|
5928
6176
|
executePlan(plan);
|
|
5929
|
-
console.log(
|
|
6177
|
+
console.log(chalk57.green("\nRestructuring complete"));
|
|
5930
6178
|
} else {
|
|
5931
|
-
console.log(
|
|
6179
|
+
console.log(chalk57.dim("\nDry run. Use --apply to execute."));
|
|
5932
6180
|
}
|
|
5933
6181
|
}
|
|
5934
6182
|
|
|
@@ -6471,14 +6719,14 @@ import {
|
|
|
6471
6719
|
import { dirname as dirname17, join as join26 } from "path";
|
|
6472
6720
|
|
|
6473
6721
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
6474
|
-
import
|
|
6722
|
+
import chalk58 from "chalk";
|
|
6475
6723
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
6476
6724
|
function validateStagedContent(filename, content) {
|
|
6477
6725
|
const firstLine = content.split("\n")[0];
|
|
6478
6726
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
6479
6727
|
if (!match) {
|
|
6480
6728
|
console.error(
|
|
6481
|
-
|
|
6729
|
+
chalk58.red(
|
|
6482
6730
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
6483
6731
|
)
|
|
6484
6732
|
);
|
|
@@ -6487,7 +6735,7 @@ function validateStagedContent(filename, content) {
|
|
|
6487
6735
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
6488
6736
|
if (!contentAfterLink) {
|
|
6489
6737
|
console.error(
|
|
6490
|
-
|
|
6738
|
+
chalk58.red(
|
|
6491
6739
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
6492
6740
|
)
|
|
6493
6741
|
);
|
|
@@ -6624,7 +6872,7 @@ import { join as join29 } from "path";
|
|
|
6624
6872
|
import { homedir as homedir7 } from "os";
|
|
6625
6873
|
import { dirname as dirname19, join as join28 } from "path";
|
|
6626
6874
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
6627
|
-
var
|
|
6875
|
+
var __dirname6 = dirname19(fileURLToPath6(import.meta.url));
|
|
6628
6876
|
var VOICE_DIR = join28(homedir7(), ".assist", "voice");
|
|
6629
6877
|
var voicePaths = {
|
|
6630
6878
|
dir: VOICE_DIR,
|
|
@@ -6634,7 +6882,7 @@ var voicePaths = {
|
|
|
6634
6882
|
lock: join28(VOICE_DIR, "voice.lock")
|
|
6635
6883
|
};
|
|
6636
6884
|
function getPythonDir() {
|
|
6637
|
-
return join28(
|
|
6885
|
+
return join28(__dirname6, "commands", "voice", "python");
|
|
6638
6886
|
}
|
|
6639
6887
|
function getVenvPython() {
|
|
6640
6888
|
return process.platform === "win32" ? join28(voicePaths.venv, "Scripts", "python.exe") : join28(voicePaths.venv, "bin", "python");
|
|
@@ -6880,7 +7128,7 @@ function registerVoice(program2) {
|
|
|
6880
7128
|
|
|
6881
7129
|
// src/commands/roam/auth.ts
|
|
6882
7130
|
import { randomBytes } from "crypto";
|
|
6883
|
-
import
|
|
7131
|
+
import chalk59 from "chalk";
|
|
6884
7132
|
|
|
6885
7133
|
// src/lib/openBrowser.ts
|
|
6886
7134
|
import { execSync as execSync31 } from "child_process";
|
|
@@ -7015,7 +7263,7 @@ async function exchangeToken(params) {
|
|
|
7015
7263
|
}
|
|
7016
7264
|
|
|
7017
7265
|
// src/commands/roam/promptCredentials.ts
|
|
7018
|
-
import
|
|
7266
|
+
import enquirer7 from "enquirer";
|
|
7019
7267
|
function censor(value) {
|
|
7020
7268
|
const visible = value.slice(-4);
|
|
7021
7269
|
return `${"*".repeat(value.length - 4)}${visible}`;
|
|
@@ -7024,7 +7272,7 @@ function label(name, existing) {
|
|
|
7024
7272
|
return existing ? `${name} (${censor(existing)})` : name;
|
|
7025
7273
|
}
|
|
7026
7274
|
async function promptField(name, existing) {
|
|
7027
|
-
const { value } = await
|
|
7275
|
+
const { value } = await enquirer7.prompt({
|
|
7028
7276
|
type: "input",
|
|
7029
7277
|
name: "value",
|
|
7030
7278
|
message: `${label(name, existing)}:`,
|
|
@@ -7055,13 +7303,13 @@ async function auth() {
|
|
|
7055
7303
|
saveGlobalConfig(config);
|
|
7056
7304
|
const state = randomBytes(16).toString("hex");
|
|
7057
7305
|
console.log(
|
|
7058
|
-
|
|
7306
|
+
chalk59.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
7059
7307
|
);
|
|
7060
|
-
console.log(
|
|
7061
|
-
console.log(
|
|
7062
|
-
console.log(
|
|
7308
|
+
console.log(chalk59.white("http://localhost:14523/callback\n"));
|
|
7309
|
+
console.log(chalk59.blue("Opening browser for authorization..."));
|
|
7310
|
+
console.log(chalk59.dim("Waiting for authorization callback..."));
|
|
7063
7311
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
7064
|
-
console.log(
|
|
7312
|
+
console.log(chalk59.dim("Exchanging code for tokens..."));
|
|
7065
7313
|
const tokens = await exchangeToken({
|
|
7066
7314
|
code,
|
|
7067
7315
|
clientId,
|
|
@@ -7077,7 +7325,7 @@ async function auth() {
|
|
|
7077
7325
|
};
|
|
7078
7326
|
saveGlobalConfig(config);
|
|
7079
7327
|
console.log(
|
|
7080
|
-
|
|
7328
|
+
chalk59.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
7081
7329
|
);
|
|
7082
7330
|
}
|
|
7083
7331
|
|
|
@@ -7191,7 +7439,7 @@ Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
|
7191
7439
|
writeFileSync24(filePath, content);
|
|
7192
7440
|
console.log(`Created command file: ${filePath}`);
|
|
7193
7441
|
}
|
|
7194
|
-
function
|
|
7442
|
+
function add3() {
|
|
7195
7443
|
const { name, command, args } = requireParsedArgs();
|
|
7196
7444
|
saveNewRunConfig(name, command, args);
|
|
7197
7445
|
createCommandFile(name);
|
|
@@ -7265,14 +7513,14 @@ function run2(name, args) {
|
|
|
7265
7513
|
}
|
|
7266
7514
|
|
|
7267
7515
|
// src/commands/statusLine.ts
|
|
7268
|
-
import
|
|
7516
|
+
import chalk60 from "chalk";
|
|
7269
7517
|
function formatNumber(num) {
|
|
7270
7518
|
return num.toLocaleString("en-US");
|
|
7271
7519
|
}
|
|
7272
7520
|
function colorizePercent(pct) {
|
|
7273
7521
|
const label2 = `${pct}%`;
|
|
7274
|
-
if (pct > 80) return
|
|
7275
|
-
if (pct > 40) return
|
|
7522
|
+
if (pct > 80) return chalk60.red(label2);
|
|
7523
|
+
if (pct > 40) return chalk60.yellow(label2);
|
|
7276
7524
|
return label2;
|
|
7277
7525
|
}
|
|
7278
7526
|
async function statusLine() {
|
|
@@ -7298,7 +7546,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
7298
7546
|
// src/commands/sync/syncClaudeMd.ts
|
|
7299
7547
|
import * as fs21 from "fs";
|
|
7300
7548
|
import * as path31 from "path";
|
|
7301
|
-
import
|
|
7549
|
+
import chalk61 from "chalk";
|
|
7302
7550
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
7303
7551
|
const source = path31.join(claudeDir, "CLAUDE.md");
|
|
7304
7552
|
const target = path31.join(targetBase, "CLAUDE.md");
|
|
@@ -7307,12 +7555,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7307
7555
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
7308
7556
|
if (sourceContent !== targetContent) {
|
|
7309
7557
|
console.log(
|
|
7310
|
-
|
|
7558
|
+
chalk61.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
7311
7559
|
);
|
|
7312
7560
|
console.log();
|
|
7313
7561
|
printDiff(targetContent, sourceContent);
|
|
7314
7562
|
const confirm = await promptConfirm(
|
|
7315
|
-
|
|
7563
|
+
chalk61.red("Overwrite existing CLAUDE.md?"),
|
|
7316
7564
|
false
|
|
7317
7565
|
);
|
|
7318
7566
|
if (!confirm) {
|
|
@@ -7328,7 +7576,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7328
7576
|
// src/commands/sync/syncSettings.ts
|
|
7329
7577
|
import * as fs22 from "fs";
|
|
7330
7578
|
import * as path32 from "path";
|
|
7331
|
-
import
|
|
7579
|
+
import chalk62 from "chalk";
|
|
7332
7580
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
7333
7581
|
const source = path32.join(claudeDir, "settings.json");
|
|
7334
7582
|
const target = path32.join(targetBase, "settings.json");
|
|
@@ -7344,14 +7592,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7344
7592
|
if (mergedContent !== normalizedTarget) {
|
|
7345
7593
|
if (!options2?.yes) {
|
|
7346
7594
|
console.log(
|
|
7347
|
-
|
|
7595
|
+
chalk62.yellow(
|
|
7348
7596
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
7349
7597
|
)
|
|
7350
7598
|
);
|
|
7351
7599
|
console.log();
|
|
7352
7600
|
printDiff(targetContent, mergedContent);
|
|
7353
7601
|
const confirm = await promptConfirm(
|
|
7354
|
-
|
|
7602
|
+
chalk62.red("Overwrite existing settings.json?"),
|
|
7355
7603
|
false
|
|
7356
7604
|
);
|
|
7357
7605
|
if (!confirm) {
|
|
@@ -7367,9 +7615,9 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7367
7615
|
|
|
7368
7616
|
// src/commands/sync.ts
|
|
7369
7617
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
7370
|
-
var
|
|
7618
|
+
var __dirname7 = path33.dirname(__filename4);
|
|
7371
7619
|
async function sync(options2) {
|
|
7372
|
-
const claudeDir = path33.join(
|
|
7620
|
+
const claudeDir = path33.join(__dirname7, "..", "claude");
|
|
7373
7621
|
const targetBase = path33.join(os.homedir(), ".claude");
|
|
7374
7622
|
syncCommands(claudeDir, targetBase);
|
|
7375
7623
|
await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
|
|
@@ -7432,7 +7680,7 @@ var program = new Command();
|
|
|
7432
7680
|
program.name("assist").description("CLI application").version(package_default.version);
|
|
7433
7681
|
program.command("sync").description("Copy command files to ~/.claude/commands").option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
|
|
7434
7682
|
program.command("init").description("Initialize VS Code and verify configurations").action(init4);
|
|
7435
|
-
program.command("commit").description("Create a git commit with validation").argument("<args...>", "status | <
|
|
7683
|
+
program.command("commit").description("Create a git commit with validation").argument("<args...>", "status | <message> [files...]").action(commit);
|
|
7436
7684
|
var configCommand = program.command("config").description("View and modify assist.yml configuration");
|
|
7437
7685
|
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").action(configSet);
|
|
7438
7686
|
configCommand.command("get <key>").description("Get a config value").action(configGet);
|
|
@@ -7444,7 +7692,7 @@ runCommand.command("list").description("List configured run commands").action(li
|
|
|
7444
7692
|
runCommand.command("add").description("Add a new run configuration to assist.yml").argument("<name>", "Name for the run configuration").argument("<command>", "Command to execute").argument("[args...]", "Static args to pass to the command").addHelpText(
|
|
7445
7693
|
"after",
|
|
7446
7694
|
'\nPositional params can be added to the config manually:\n params:\n - name: env # assist run deploy prod \u2192 appends "prod"\n required: true\n - name: tag\n default: latest'
|
|
7447
|
-
).allowUnknownOption().allowExcessArguments().action(() =>
|
|
7695
|
+
).allowUnknownOption().allowExcessArguments().action(() => add3());
|
|
7448
7696
|
registerNew(program);
|
|
7449
7697
|
var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
|
|
7450
7698
|
lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
|
|
@@ -7466,6 +7714,7 @@ registerDevlog(program);
|
|
|
7466
7714
|
registerDeploy(program);
|
|
7467
7715
|
registerComplexity(program);
|
|
7468
7716
|
registerNetframework(program);
|
|
7717
|
+
registerNews(program);
|
|
7469
7718
|
registerTranscript(program);
|
|
7470
7719
|
registerVoice(program);
|
|
7471
7720
|
program.parse();
|