@staff0rd/assist 0.107.0 → 0.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/claude/settings.json +1 -0
- package/dist/commands/news/web/bundle.js +66 -0
- package/dist/index.js +380 -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.0",
|
|
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";
|
|
@@ -4930,20 +5177,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
|
|
|
4930
5177
|
}
|
|
4931
5178
|
|
|
4932
5179
|
// src/commands/prs/listComments/printComments.ts
|
|
4933
|
-
import
|
|
5180
|
+
import chalk51 from "chalk";
|
|
4934
5181
|
function formatForHuman(comment2) {
|
|
4935
5182
|
if (comment2.type === "review") {
|
|
4936
|
-
const stateColor = comment2.state === "APPROVED" ?
|
|
5183
|
+
const stateColor = comment2.state === "APPROVED" ? chalk51.green : comment2.state === "CHANGES_REQUESTED" ? chalk51.red : chalk51.yellow;
|
|
4937
5184
|
return [
|
|
4938
|
-
`${
|
|
5185
|
+
`${chalk51.cyan("Review")} by ${chalk51.bold(comment2.user)} ${stateColor(`[${comment2.state}]`)}`,
|
|
4939
5186
|
comment2.body,
|
|
4940
5187
|
""
|
|
4941
5188
|
].join("\n");
|
|
4942
5189
|
}
|
|
4943
5190
|
const location = comment2.line ? `:${comment2.line}` : "";
|
|
4944
5191
|
return [
|
|
4945
|
-
`${
|
|
4946
|
-
|
|
5192
|
+
`${chalk51.cyan("Line comment")} by ${chalk51.bold(comment2.user)} on ${chalk51.dim(`${comment2.path}${location}`)}`,
|
|
5193
|
+
chalk51.dim(comment2.diff_hunk.split("\n").slice(-3).join("\n")),
|
|
4947
5194
|
comment2.body,
|
|
4948
5195
|
""
|
|
4949
5196
|
].join("\n");
|
|
@@ -5030,16 +5277,16 @@ async function listComments() {
|
|
|
5030
5277
|
import { execSync as execSync27 } from "child_process";
|
|
5031
5278
|
|
|
5032
5279
|
// src/commands/prs/prs/displayPaginated/index.ts
|
|
5033
|
-
import
|
|
5280
|
+
import enquirer6 from "enquirer";
|
|
5034
5281
|
|
|
5035
5282
|
// src/commands/prs/prs/displayPaginated/printPr.ts
|
|
5036
|
-
import
|
|
5283
|
+
import chalk52 from "chalk";
|
|
5037
5284
|
var STATUS_MAP = {
|
|
5038
|
-
MERGED: (pr) => pr.mergedAt ? { label:
|
|
5039
|
-
CLOSED: (pr) => pr.closedAt ? { label:
|
|
5285
|
+
MERGED: (pr) => pr.mergedAt ? { label: chalk52.magenta("merged"), date: pr.mergedAt } : null,
|
|
5286
|
+
CLOSED: (pr) => pr.closedAt ? { label: chalk52.red("closed"), date: pr.closedAt } : null
|
|
5040
5287
|
};
|
|
5041
5288
|
function defaultStatus(pr) {
|
|
5042
|
-
return { label:
|
|
5289
|
+
return { label: chalk52.green("opened"), date: pr.createdAt };
|
|
5043
5290
|
}
|
|
5044
5291
|
function getStatus2(pr) {
|
|
5045
5292
|
return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
|
|
@@ -5048,11 +5295,11 @@ function formatDate(dateStr) {
|
|
|
5048
5295
|
return new Date(dateStr).toISOString().split("T")[0];
|
|
5049
5296
|
}
|
|
5050
5297
|
function formatPrHeader(pr, status2) {
|
|
5051
|
-
return `${
|
|
5298
|
+
return `${chalk52.cyan(`#${pr.number}`)} ${pr.title} ${chalk52.dim(`(${pr.author.login},`)} ${status2.label} ${chalk52.dim(`${formatDate(status2.date)})`)}`;
|
|
5052
5299
|
}
|
|
5053
5300
|
function logPrDetails(pr) {
|
|
5054
5301
|
console.log(
|
|
5055
|
-
|
|
5302
|
+
chalk52.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
|
|
5056
5303
|
);
|
|
5057
5304
|
console.log();
|
|
5058
5305
|
}
|
|
@@ -5100,7 +5347,7 @@ function parseAction(action) {
|
|
|
5100
5347
|
}
|
|
5101
5348
|
async function promptNavigation(currentPage, totalPages) {
|
|
5102
5349
|
const choices = buildNavChoices(currentPage, totalPages);
|
|
5103
|
-
const { action } = await
|
|
5350
|
+
const { action } = await enquirer6.prompt({
|
|
5104
5351
|
type: "select",
|
|
5105
5352
|
name: "action",
|
|
5106
5353
|
message: "Navigate",
|
|
@@ -5222,7 +5469,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
5222
5469
|
import * as path21 from "path";
|
|
5223
5470
|
|
|
5224
5471
|
// src/commands/refactor/logViolations.ts
|
|
5225
|
-
import
|
|
5472
|
+
import chalk53 from "chalk";
|
|
5226
5473
|
var DEFAULT_MAX_LINES = 100;
|
|
5227
5474
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
5228
5475
|
if (violations.length === 0) {
|
|
@@ -5231,43 +5478,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
5231
5478
|
}
|
|
5232
5479
|
return;
|
|
5233
5480
|
}
|
|
5234
|
-
console.error(
|
|
5481
|
+
console.error(chalk53.red(`
|
|
5235
5482
|
Refactor check failed:
|
|
5236
5483
|
`));
|
|
5237
|
-
console.error(
|
|
5484
|
+
console.error(chalk53.red(` The following files exceed ${maxLines} lines:
|
|
5238
5485
|
`));
|
|
5239
5486
|
for (const violation of violations) {
|
|
5240
|
-
console.error(
|
|
5487
|
+
console.error(chalk53.red(` ${violation.file} (${violation.lines} lines)`));
|
|
5241
5488
|
}
|
|
5242
5489
|
console.error(
|
|
5243
|
-
|
|
5490
|
+
chalk53.yellow(
|
|
5244
5491
|
`
|
|
5245
5492
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
5246
5493
|
way to refactor it, ignore it with:
|
|
5247
5494
|
`
|
|
5248
5495
|
)
|
|
5249
5496
|
);
|
|
5250
|
-
console.error(
|
|
5497
|
+
console.error(chalk53.gray(` assist refactor ignore <file>
|
|
5251
5498
|
`));
|
|
5252
5499
|
if (process.env.CLAUDECODE) {
|
|
5253
|
-
console.error(
|
|
5500
|
+
console.error(chalk53.cyan(`
|
|
5254
5501
|
## Extracting Code to New Files
|
|
5255
5502
|
`));
|
|
5256
5503
|
console.error(
|
|
5257
|
-
|
|
5504
|
+
chalk53.cyan(
|
|
5258
5505
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
5259
5506
|
`
|
|
5260
5507
|
)
|
|
5261
5508
|
);
|
|
5262
5509
|
console.error(
|
|
5263
|
-
|
|
5510
|
+
chalk53.cyan(
|
|
5264
5511
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
5265
5512
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
5266
5513
|
`
|
|
5267
5514
|
)
|
|
5268
5515
|
);
|
|
5269
5516
|
console.error(
|
|
5270
|
-
|
|
5517
|
+
chalk53.cyan(
|
|
5271
5518
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
5272
5519
|
domains, move it to a common/shared folder.
|
|
5273
5520
|
`
|
|
@@ -5423,11 +5670,11 @@ async function check(pattern2, options2) {
|
|
|
5423
5670
|
|
|
5424
5671
|
// src/commands/refactor/ignore.ts
|
|
5425
5672
|
import fs16 from "fs";
|
|
5426
|
-
import
|
|
5673
|
+
import chalk54 from "chalk";
|
|
5427
5674
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
5428
5675
|
function ignore(file) {
|
|
5429
5676
|
if (!fs16.existsSync(file)) {
|
|
5430
|
-
console.error(
|
|
5677
|
+
console.error(chalk54.red(`Error: File does not exist: ${file}`));
|
|
5431
5678
|
process.exit(1);
|
|
5432
5679
|
}
|
|
5433
5680
|
const content = fs16.readFileSync(file, "utf-8");
|
|
@@ -5443,7 +5690,7 @@ function ignore(file) {
|
|
|
5443
5690
|
fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
5444
5691
|
}
|
|
5445
5692
|
console.log(
|
|
5446
|
-
|
|
5693
|
+
chalk54.green(
|
|
5447
5694
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
5448
5695
|
)
|
|
5449
5696
|
);
|
|
@@ -5451,7 +5698,7 @@ function ignore(file) {
|
|
|
5451
5698
|
|
|
5452
5699
|
// src/commands/refactor/restructure/index.ts
|
|
5453
5700
|
import path30 from "path";
|
|
5454
|
-
import
|
|
5701
|
+
import chalk57 from "chalk";
|
|
5455
5702
|
|
|
5456
5703
|
// src/commands/refactor/restructure/buildImportGraph/index.ts
|
|
5457
5704
|
import path22 from "path";
|
|
@@ -5694,50 +5941,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
|
|
|
5694
5941
|
|
|
5695
5942
|
// src/commands/refactor/restructure/displayPlan.ts
|
|
5696
5943
|
import path26 from "path";
|
|
5697
|
-
import
|
|
5944
|
+
import chalk55 from "chalk";
|
|
5698
5945
|
function relPath(filePath) {
|
|
5699
5946
|
return path26.relative(process.cwd(), filePath);
|
|
5700
5947
|
}
|
|
5701
5948
|
function displayMoves(plan) {
|
|
5702
5949
|
if (plan.moves.length === 0) return;
|
|
5703
|
-
console.log(
|
|
5950
|
+
console.log(chalk55.bold("\nFile moves:"));
|
|
5704
5951
|
for (const move of plan.moves) {
|
|
5705
5952
|
console.log(
|
|
5706
|
-
` ${
|
|
5953
|
+
` ${chalk55.red(relPath(move.from))} \u2192 ${chalk55.green(relPath(move.to))}`
|
|
5707
5954
|
);
|
|
5708
|
-
console.log(
|
|
5955
|
+
console.log(chalk55.dim(` ${move.reason}`));
|
|
5709
5956
|
}
|
|
5710
5957
|
}
|
|
5711
5958
|
function displayRewrites(rewrites) {
|
|
5712
5959
|
if (rewrites.length === 0) return;
|
|
5713
5960
|
const affectedFiles = new Set(rewrites.map((r) => r.file));
|
|
5714
|
-
console.log(
|
|
5961
|
+
console.log(chalk55.bold(`
|
|
5715
5962
|
Import rewrites (${affectedFiles.size} files):`));
|
|
5716
5963
|
for (const file of affectedFiles) {
|
|
5717
|
-
console.log(` ${
|
|
5964
|
+
console.log(` ${chalk55.cyan(relPath(file))}:`);
|
|
5718
5965
|
for (const { oldSpecifier, newSpecifier } of rewrites.filter(
|
|
5719
5966
|
(r) => r.file === file
|
|
5720
5967
|
)) {
|
|
5721
5968
|
console.log(
|
|
5722
|
-
` ${
|
|
5969
|
+
` ${chalk55.red(`"${oldSpecifier}"`)} \u2192 ${chalk55.green(`"${newSpecifier}"`)}`
|
|
5723
5970
|
);
|
|
5724
5971
|
}
|
|
5725
5972
|
}
|
|
5726
5973
|
}
|
|
5727
5974
|
function displayPlan(plan) {
|
|
5728
5975
|
if (plan.warnings.length > 0) {
|
|
5729
|
-
console.log(
|
|
5730
|
-
for (const w of plan.warnings) console.log(
|
|
5976
|
+
console.log(chalk55.yellow("\nWarnings:"));
|
|
5977
|
+
for (const w of plan.warnings) console.log(chalk55.yellow(` ${w}`));
|
|
5731
5978
|
}
|
|
5732
5979
|
if (plan.newDirectories.length > 0) {
|
|
5733
|
-
console.log(
|
|
5980
|
+
console.log(chalk55.bold("\nNew directories:"));
|
|
5734
5981
|
for (const dir of plan.newDirectories)
|
|
5735
|
-
console.log(
|
|
5982
|
+
console.log(chalk55.green(` ${dir}/`));
|
|
5736
5983
|
}
|
|
5737
5984
|
displayMoves(plan);
|
|
5738
5985
|
displayRewrites(plan.rewrites);
|
|
5739
5986
|
console.log(
|
|
5740
|
-
|
|
5987
|
+
chalk55.dim(
|
|
5741
5988
|
`
|
|
5742
5989
|
Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
|
|
5743
5990
|
)
|
|
@@ -5747,18 +5994,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
|
|
|
5747
5994
|
// src/commands/refactor/restructure/executePlan.ts
|
|
5748
5995
|
import fs18 from "fs";
|
|
5749
5996
|
import path27 from "path";
|
|
5750
|
-
import
|
|
5997
|
+
import chalk56 from "chalk";
|
|
5751
5998
|
function executePlan(plan) {
|
|
5752
5999
|
const updatedContents = applyRewrites(plan.rewrites);
|
|
5753
6000
|
for (const [file, content] of updatedContents) {
|
|
5754
6001
|
fs18.writeFileSync(file, content, "utf-8");
|
|
5755
6002
|
console.log(
|
|
5756
|
-
|
|
6003
|
+
chalk56.cyan(` Rewrote imports in ${path27.relative(process.cwd(), file)}`)
|
|
5757
6004
|
);
|
|
5758
6005
|
}
|
|
5759
6006
|
for (const dir of plan.newDirectories) {
|
|
5760
6007
|
fs18.mkdirSync(dir, { recursive: true });
|
|
5761
|
-
console.log(
|
|
6008
|
+
console.log(chalk56.green(` Created ${path27.relative(process.cwd(), dir)}/`));
|
|
5762
6009
|
}
|
|
5763
6010
|
for (const move of plan.moves) {
|
|
5764
6011
|
const targetDir = path27.dirname(move.to);
|
|
@@ -5767,7 +6014,7 @@ function executePlan(plan) {
|
|
|
5767
6014
|
}
|
|
5768
6015
|
fs18.renameSync(move.from, move.to);
|
|
5769
6016
|
console.log(
|
|
5770
|
-
|
|
6017
|
+
chalk56.white(
|
|
5771
6018
|
` Moved ${path27.relative(process.cwd(), move.from)} \u2192 ${path27.relative(process.cwd(), move.to)}`
|
|
5772
6019
|
)
|
|
5773
6020
|
);
|
|
@@ -5782,7 +6029,7 @@ function removeEmptyDirectories(dirs) {
|
|
|
5782
6029
|
if (entries.length === 0) {
|
|
5783
6030
|
fs18.rmdirSync(dir);
|
|
5784
6031
|
console.log(
|
|
5785
|
-
|
|
6032
|
+
chalk56.dim(
|
|
5786
6033
|
` Removed empty directory ${path27.relative(process.cwd(), dir)}`
|
|
5787
6034
|
)
|
|
5788
6035
|
);
|
|
@@ -5913,22 +6160,22 @@ async function restructure(pattern2, options2 = {}) {
|
|
|
5913
6160
|
const targetPattern = pattern2 ?? "src";
|
|
5914
6161
|
const files = findSourceFiles2(targetPattern);
|
|
5915
6162
|
if (files.length === 0) {
|
|
5916
|
-
console.log(
|
|
6163
|
+
console.log(chalk57.yellow("No files found matching pattern"));
|
|
5917
6164
|
return;
|
|
5918
6165
|
}
|
|
5919
6166
|
const tsConfigPath = path30.resolve("tsconfig.json");
|
|
5920
6167
|
const plan = buildPlan(files, tsConfigPath);
|
|
5921
6168
|
if (plan.moves.length === 0) {
|
|
5922
|
-
console.log(
|
|
6169
|
+
console.log(chalk57.green("No restructuring needed"));
|
|
5923
6170
|
return;
|
|
5924
6171
|
}
|
|
5925
6172
|
displayPlan(plan);
|
|
5926
6173
|
if (options2.apply) {
|
|
5927
|
-
console.log(
|
|
6174
|
+
console.log(chalk57.bold("\nApplying changes..."));
|
|
5928
6175
|
executePlan(plan);
|
|
5929
|
-
console.log(
|
|
6176
|
+
console.log(chalk57.green("\nRestructuring complete"));
|
|
5930
6177
|
} else {
|
|
5931
|
-
console.log(
|
|
6178
|
+
console.log(chalk57.dim("\nDry run. Use --apply to execute."));
|
|
5932
6179
|
}
|
|
5933
6180
|
}
|
|
5934
6181
|
|
|
@@ -6471,14 +6718,14 @@ import {
|
|
|
6471
6718
|
import { dirname as dirname17, join as join26 } from "path";
|
|
6472
6719
|
|
|
6473
6720
|
// src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
|
|
6474
|
-
import
|
|
6721
|
+
import chalk58 from "chalk";
|
|
6475
6722
|
var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
|
|
6476
6723
|
function validateStagedContent(filename, content) {
|
|
6477
6724
|
const firstLine = content.split("\n")[0];
|
|
6478
6725
|
const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
|
|
6479
6726
|
if (!match) {
|
|
6480
6727
|
console.error(
|
|
6481
|
-
|
|
6728
|
+
chalk58.red(
|
|
6482
6729
|
`Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
|
|
6483
6730
|
)
|
|
6484
6731
|
);
|
|
@@ -6487,7 +6734,7 @@ function validateStagedContent(filename, content) {
|
|
|
6487
6734
|
const contentAfterLink = content.slice(firstLine.length).trim();
|
|
6488
6735
|
if (!contentAfterLink) {
|
|
6489
6736
|
console.error(
|
|
6490
|
-
|
|
6737
|
+
chalk58.red(
|
|
6491
6738
|
`Staged file ${filename} has no summary content after the transcript link.`
|
|
6492
6739
|
)
|
|
6493
6740
|
);
|
|
@@ -6624,7 +6871,7 @@ import { join as join29 } from "path";
|
|
|
6624
6871
|
import { homedir as homedir7 } from "os";
|
|
6625
6872
|
import { dirname as dirname19, join as join28 } from "path";
|
|
6626
6873
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
6627
|
-
var
|
|
6874
|
+
var __dirname6 = dirname19(fileURLToPath6(import.meta.url));
|
|
6628
6875
|
var VOICE_DIR = join28(homedir7(), ".assist", "voice");
|
|
6629
6876
|
var voicePaths = {
|
|
6630
6877
|
dir: VOICE_DIR,
|
|
@@ -6634,7 +6881,7 @@ var voicePaths = {
|
|
|
6634
6881
|
lock: join28(VOICE_DIR, "voice.lock")
|
|
6635
6882
|
};
|
|
6636
6883
|
function getPythonDir() {
|
|
6637
|
-
return join28(
|
|
6884
|
+
return join28(__dirname6, "commands", "voice", "python");
|
|
6638
6885
|
}
|
|
6639
6886
|
function getVenvPython() {
|
|
6640
6887
|
return process.platform === "win32" ? join28(voicePaths.venv, "Scripts", "python.exe") : join28(voicePaths.venv, "bin", "python");
|
|
@@ -6880,7 +7127,7 @@ function registerVoice(program2) {
|
|
|
6880
7127
|
|
|
6881
7128
|
// src/commands/roam/auth.ts
|
|
6882
7129
|
import { randomBytes } from "crypto";
|
|
6883
|
-
import
|
|
7130
|
+
import chalk59 from "chalk";
|
|
6884
7131
|
|
|
6885
7132
|
// src/lib/openBrowser.ts
|
|
6886
7133
|
import { execSync as execSync31 } from "child_process";
|
|
@@ -7015,7 +7262,7 @@ async function exchangeToken(params) {
|
|
|
7015
7262
|
}
|
|
7016
7263
|
|
|
7017
7264
|
// src/commands/roam/promptCredentials.ts
|
|
7018
|
-
import
|
|
7265
|
+
import enquirer7 from "enquirer";
|
|
7019
7266
|
function censor(value) {
|
|
7020
7267
|
const visible = value.slice(-4);
|
|
7021
7268
|
return `${"*".repeat(value.length - 4)}${visible}`;
|
|
@@ -7024,7 +7271,7 @@ function label(name, existing) {
|
|
|
7024
7271
|
return existing ? `${name} (${censor(existing)})` : name;
|
|
7025
7272
|
}
|
|
7026
7273
|
async function promptField(name, existing) {
|
|
7027
|
-
const { value } = await
|
|
7274
|
+
const { value } = await enquirer7.prompt({
|
|
7028
7275
|
type: "input",
|
|
7029
7276
|
name: "value",
|
|
7030
7277
|
message: `${label(name, existing)}:`,
|
|
@@ -7055,13 +7302,13 @@ async function auth() {
|
|
|
7055
7302
|
saveGlobalConfig(config);
|
|
7056
7303
|
const state = randomBytes(16).toString("hex");
|
|
7057
7304
|
console.log(
|
|
7058
|
-
|
|
7305
|
+
chalk59.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
|
|
7059
7306
|
);
|
|
7060
|
-
console.log(
|
|
7061
|
-
console.log(
|
|
7062
|
-
console.log(
|
|
7307
|
+
console.log(chalk59.white("http://localhost:14523/callback\n"));
|
|
7308
|
+
console.log(chalk59.blue("Opening browser for authorization..."));
|
|
7309
|
+
console.log(chalk59.dim("Waiting for authorization callback..."));
|
|
7063
7310
|
const { code, redirectUri } = await authorizeInBrowser(clientId, state);
|
|
7064
|
-
console.log(
|
|
7311
|
+
console.log(chalk59.dim("Exchanging code for tokens..."));
|
|
7065
7312
|
const tokens = await exchangeToken({
|
|
7066
7313
|
code,
|
|
7067
7314
|
clientId,
|
|
@@ -7077,7 +7324,7 @@ async function auth() {
|
|
|
7077
7324
|
};
|
|
7078
7325
|
saveGlobalConfig(config);
|
|
7079
7326
|
console.log(
|
|
7080
|
-
|
|
7327
|
+
chalk59.green("Roam credentials and tokens saved to ~/.assist.yml")
|
|
7081
7328
|
);
|
|
7082
7329
|
}
|
|
7083
7330
|
|
|
@@ -7191,7 +7438,7 @@ Run \`assist run ${name} $ARGUMENTS 2>&1\`.
|
|
|
7191
7438
|
writeFileSync24(filePath, content);
|
|
7192
7439
|
console.log(`Created command file: ${filePath}`);
|
|
7193
7440
|
}
|
|
7194
|
-
function
|
|
7441
|
+
function add3() {
|
|
7195
7442
|
const { name, command, args } = requireParsedArgs();
|
|
7196
7443
|
saveNewRunConfig(name, command, args);
|
|
7197
7444
|
createCommandFile(name);
|
|
@@ -7265,14 +7512,14 @@ function run2(name, args) {
|
|
|
7265
7512
|
}
|
|
7266
7513
|
|
|
7267
7514
|
// src/commands/statusLine.ts
|
|
7268
|
-
import
|
|
7515
|
+
import chalk60 from "chalk";
|
|
7269
7516
|
function formatNumber(num) {
|
|
7270
7517
|
return num.toLocaleString("en-US");
|
|
7271
7518
|
}
|
|
7272
7519
|
function colorizePercent(pct) {
|
|
7273
7520
|
const label2 = `${pct}%`;
|
|
7274
|
-
if (pct > 80) return
|
|
7275
|
-
if (pct > 40) return
|
|
7521
|
+
if (pct > 80) return chalk60.red(label2);
|
|
7522
|
+
if (pct > 40) return chalk60.yellow(label2);
|
|
7276
7523
|
return label2;
|
|
7277
7524
|
}
|
|
7278
7525
|
async function statusLine() {
|
|
@@ -7298,7 +7545,7 @@ import { fileURLToPath as fileURLToPath7 } from "url";
|
|
|
7298
7545
|
// src/commands/sync/syncClaudeMd.ts
|
|
7299
7546
|
import * as fs21 from "fs";
|
|
7300
7547
|
import * as path31 from "path";
|
|
7301
|
-
import
|
|
7548
|
+
import chalk61 from "chalk";
|
|
7302
7549
|
async function syncClaudeMd(claudeDir, targetBase) {
|
|
7303
7550
|
const source = path31.join(claudeDir, "CLAUDE.md");
|
|
7304
7551
|
const target = path31.join(targetBase, "CLAUDE.md");
|
|
@@ -7307,12 +7554,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7307
7554
|
const targetContent = fs21.readFileSync(target, "utf-8");
|
|
7308
7555
|
if (sourceContent !== targetContent) {
|
|
7309
7556
|
console.log(
|
|
7310
|
-
|
|
7557
|
+
chalk61.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
|
|
7311
7558
|
);
|
|
7312
7559
|
console.log();
|
|
7313
7560
|
printDiff(targetContent, sourceContent);
|
|
7314
7561
|
const confirm = await promptConfirm(
|
|
7315
|
-
|
|
7562
|
+
chalk61.red("Overwrite existing CLAUDE.md?"),
|
|
7316
7563
|
false
|
|
7317
7564
|
);
|
|
7318
7565
|
if (!confirm) {
|
|
@@ -7328,7 +7575,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
|
|
|
7328
7575
|
// src/commands/sync/syncSettings.ts
|
|
7329
7576
|
import * as fs22 from "fs";
|
|
7330
7577
|
import * as path32 from "path";
|
|
7331
|
-
import
|
|
7578
|
+
import chalk62 from "chalk";
|
|
7332
7579
|
async function syncSettings(claudeDir, targetBase, options2) {
|
|
7333
7580
|
const source = path32.join(claudeDir, "settings.json");
|
|
7334
7581
|
const target = path32.join(targetBase, "settings.json");
|
|
@@ -7344,14 +7591,14 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7344
7591
|
if (mergedContent !== normalizedTarget) {
|
|
7345
7592
|
if (!options2?.yes) {
|
|
7346
7593
|
console.log(
|
|
7347
|
-
|
|
7594
|
+
chalk62.yellow(
|
|
7348
7595
|
"\n\u26A0\uFE0F Warning: settings.json differs from existing file"
|
|
7349
7596
|
)
|
|
7350
7597
|
);
|
|
7351
7598
|
console.log();
|
|
7352
7599
|
printDiff(targetContent, mergedContent);
|
|
7353
7600
|
const confirm = await promptConfirm(
|
|
7354
|
-
|
|
7601
|
+
chalk62.red("Overwrite existing settings.json?"),
|
|
7355
7602
|
false
|
|
7356
7603
|
);
|
|
7357
7604
|
if (!confirm) {
|
|
@@ -7367,9 +7614,9 @@ async function syncSettings(claudeDir, targetBase, options2) {
|
|
|
7367
7614
|
|
|
7368
7615
|
// src/commands/sync.ts
|
|
7369
7616
|
var __filename4 = fileURLToPath7(import.meta.url);
|
|
7370
|
-
var
|
|
7617
|
+
var __dirname7 = path33.dirname(__filename4);
|
|
7371
7618
|
async function sync(options2) {
|
|
7372
|
-
const claudeDir = path33.join(
|
|
7619
|
+
const claudeDir = path33.join(__dirname7, "..", "claude");
|
|
7373
7620
|
const targetBase = path33.join(os.homedir(), ".claude");
|
|
7374
7621
|
syncCommands(claudeDir, targetBase);
|
|
7375
7622
|
await syncSettings(claudeDir, targetBase, { yes: options2?.yes });
|
|
@@ -7432,7 +7679,7 @@ var program = new Command();
|
|
|
7432
7679
|
program.name("assist").description("CLI application").version(package_default.version);
|
|
7433
7680
|
program.command("sync").description("Copy command files to ~/.claude/commands").option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
|
|
7434
7681
|
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 | <
|
|
7682
|
+
program.command("commit").description("Create a git commit with validation").argument("<args...>", "status | <message> [files...]").action(commit);
|
|
7436
7683
|
var configCommand = program.command("config").description("View and modify assist.yml configuration");
|
|
7437
7684
|
configCommand.command("set <key> <value>").description("Set a config value (e.g. commit.push true)").action(configSet);
|
|
7438
7685
|
configCommand.command("get <key>").description("Get a config value").action(configGet);
|
|
@@ -7444,7 +7691,7 @@ runCommand.command("list").description("List configured run commands").action(li
|
|
|
7444
7691
|
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
7692
|
"after",
|
|
7446
7693
|
'\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(() =>
|
|
7694
|
+
).allowUnknownOption().allowExcessArguments().action(() => add3());
|
|
7448
7695
|
registerNew(program);
|
|
7449
7696
|
var lintCommand = program.command("lint").description("Run lint checks for conventions not enforced by biomejs").action(lint);
|
|
7450
7697
|
lintCommand.command("init").description("Initialize Biome with standard linter config").action(init);
|
|
@@ -7466,6 +7713,7 @@ registerDevlog(program);
|
|
|
7466
7713
|
registerDeploy(program);
|
|
7467
7714
|
registerComplexity(program);
|
|
7468
7715
|
registerNetframework(program);
|
|
7716
|
+
registerNews(program);
|
|
7469
7717
|
registerTranscript(program);
|
|
7470
7718
|
registerVoice(program);
|
|
7471
7719
|
program.parse();
|