agenthud 0.12.1 → 0.12.3
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 +2 -0
- package/dist/index.js +1 -1
- package/dist/{main-CRTF5EHN.js → main-WHDPTTTD.js} +173 -70
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,8 @@ npx agenthud
|
|
|
24
24
|
|
|
25
25
|
Run this in a separate terminal while using Claude Code. Press `?` inside the TUI any time for in-app help.
|
|
26
26
|
|
|
27
|
+
> **Platform support.** Primary development is on macOS and Linux; the full test suite runs on all three platforms in CI (including Windows). Windows runtime behavior is exercised by a manual smoke job but isn't daily-driven — issues there are valued bug reports.
|
|
28
|
+
|
|
27
29
|
Pass `--cwd` to scope the view to the Claude project that contains your current directory — useful when you have many projects but only care about the one you're in right now. Exits 1 with a stderr message if no such project is registered.
|
|
28
30
|
|
|
29
31
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/main.ts
|
|
2
|
-
import { existsSync as
|
|
2
|
+
import { existsSync as existsSync8, readdirSync as readdirSync3, realpathSync, rmSync } from "fs";
|
|
3
3
|
import { homedir as homedir5 } from "os";
|
|
4
|
-
import { join as
|
|
4
|
+
import { join as join8 } from "path";
|
|
5
5
|
import { createInterface as createInterface2 } from "readline";
|
|
6
6
|
import { render } from "ink";
|
|
7
7
|
import React from "react";
|
|
@@ -465,12 +465,21 @@ function formatEffectiveOptionsLine(command, fields) {
|
|
|
465
465
|
if (fields.model) parts.push(`model=${fields.model}`);
|
|
466
466
|
return `${command} \u2192 ${parts.join(" ")}`;
|
|
467
467
|
}
|
|
468
|
+
function expandCombinedShortFlags(args) {
|
|
469
|
+
return args.flatMap((arg) => {
|
|
470
|
+
if (/^-[a-zA-Z]{2,}$/.test(arg)) {
|
|
471
|
+
return arg.slice(1).split("").map((ch) => `-${ch}`);
|
|
472
|
+
}
|
|
473
|
+
return arg;
|
|
474
|
+
});
|
|
475
|
+
}
|
|
468
476
|
function todayLocalMidnight() {
|
|
469
477
|
const now = /* @__PURE__ */ new Date();
|
|
470
478
|
return new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
471
479
|
}
|
|
472
480
|
function parseArgs(args, config) {
|
|
473
481
|
if (args[0] === "watch") args = args.slice(1);
|
|
482
|
+
args = expandCombinedShortFlags(args);
|
|
474
483
|
if (args.includes("--help") || args.includes("-h")) {
|
|
475
484
|
return { mode: "watch", command: "help" };
|
|
476
485
|
}
|
|
@@ -1667,23 +1676,26 @@ import { spawn as spawn2 } from "child_process";
|
|
|
1667
1676
|
import {
|
|
1668
1677
|
copyFileSync,
|
|
1669
1678
|
createWriteStream,
|
|
1670
|
-
existsSync as
|
|
1679
|
+
existsSync as existsSync6,
|
|
1671
1680
|
mkdirSync as mkdirSync2,
|
|
1672
|
-
readFileSync as
|
|
1681
|
+
readFileSync as readFileSync7,
|
|
1673
1682
|
unlinkSync
|
|
1674
1683
|
} from "fs";
|
|
1675
1684
|
import { homedir as homedir3 } from "os";
|
|
1676
|
-
import { dirname as dirname2, join as
|
|
1685
|
+
import { dirname as dirname2, join as join6 } from "path";
|
|
1677
1686
|
import { createInterface } from "readline";
|
|
1678
1687
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1679
1688
|
|
|
1680
1689
|
// src/utils/openInDefaultApp.ts
|
|
1681
1690
|
import { spawn } from "child_process";
|
|
1682
|
-
|
|
1691
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5 } from "fs";
|
|
1692
|
+
import { join as join4 } from "path";
|
|
1693
|
+
function buildOpenCommand(platform, path, opts = {}) {
|
|
1683
1694
|
switch (platform) {
|
|
1684
1695
|
case "darwin":
|
|
1685
1696
|
return { command: "open", args: [path] };
|
|
1686
1697
|
case "linux":
|
|
1698
|
+
if (opts.wslView) return { command: "wslview", args: [path] };
|
|
1687
1699
|
return { command: "xdg-open", args: [path] };
|
|
1688
1700
|
case "win32":
|
|
1689
1701
|
return { command: "cmd", args: ["/c", "start", "", path] };
|
|
@@ -1691,8 +1703,36 @@ function buildOpenCommand(platform, path) {
|
|
|
1691
1703
|
return null;
|
|
1692
1704
|
}
|
|
1693
1705
|
}
|
|
1694
|
-
function
|
|
1695
|
-
|
|
1706
|
+
function isWSL() {
|
|
1707
|
+
if (process.env.WSL_DISTRO_NAME) return true;
|
|
1708
|
+
try {
|
|
1709
|
+
const ver = readFileSync5("/proc/version", "utf-8");
|
|
1710
|
+
return /microsoft|wsl/i.test(ver);
|
|
1711
|
+
} catch {
|
|
1712
|
+
return false;
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
function commandExists(command) {
|
|
1716
|
+
const PATH = process.env.PATH ?? "";
|
|
1717
|
+
const sep = process.platform === "win32" ? ";" : ":";
|
|
1718
|
+
const exts = process.platform === "win32" ? (process.env.PATHEXT?.split(";") ?? [".EXE", ".CMD", ".BAT"]).map(
|
|
1719
|
+
(e) => e.toLowerCase()
|
|
1720
|
+
) : [""];
|
|
1721
|
+
for (const dir of PATH.split(sep)) {
|
|
1722
|
+
if (!dir) continue;
|
|
1723
|
+
const full = join4(dir, command);
|
|
1724
|
+
for (const ext of exts) {
|
|
1725
|
+
try {
|
|
1726
|
+
if (existsSync4(full + ext)) return true;
|
|
1727
|
+
} catch {
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
return false;
|
|
1732
|
+
}
|
|
1733
|
+
async function openInDefaultApp(path) {
|
|
1734
|
+
const wslView = isWSL() && commandExists("wslview");
|
|
1735
|
+
const cmd = buildOpenCommand(process.platform, path, { wslView });
|
|
1696
1736
|
if (!cmd) {
|
|
1697
1737
|
process.stderr.write(
|
|
1698
1738
|
`agenthud: --open: no known opener for platform "${process.platform}"
|
|
@@ -1700,26 +1740,64 @@ function openInDefaultApp(path) {
|
|
|
1700
1740
|
);
|
|
1701
1741
|
return;
|
|
1702
1742
|
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1743
|
+
if (!commandExists(cmd.command)) {
|
|
1744
|
+
process.stderr.write(
|
|
1745
|
+
`agenthud: --open: '${cmd.command}' is not on PATH; cannot open ${path}
|
|
1746
|
+
`
|
|
1747
|
+
);
|
|
1748
|
+
if (isWSL()) {
|
|
1749
|
+
process.stderr.write(
|
|
1750
|
+
"agenthud: hint: on WSL install `wslu` (provides wslview) so files open with the Windows host's default app \u2014 e.g. `sudo apt install wslu`\n"
|
|
1751
|
+
);
|
|
1752
|
+
}
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
await new Promise((resolve2) => {
|
|
1756
|
+
let settled = false;
|
|
1757
|
+
const finish = () => {
|
|
1758
|
+
if (settled) return;
|
|
1759
|
+
settled = true;
|
|
1760
|
+
resolve2();
|
|
1761
|
+
};
|
|
1762
|
+
let child;
|
|
1763
|
+
try {
|
|
1764
|
+
child = spawn(cmd.command, cmd.args, {
|
|
1765
|
+
detached: true,
|
|
1766
|
+
stdio: "ignore"
|
|
1767
|
+
});
|
|
1768
|
+
} catch (err) {
|
|
1769
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1770
|
+
process.stderr.write(`agenthud: --open failed: ${msg}
|
|
1771
|
+
`);
|
|
1772
|
+
finish();
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1708
1775
|
child.on("error", (err) => {
|
|
1709
1776
|
process.stderr.write(`agenthud: --open failed: ${err.message}
|
|
1710
1777
|
`);
|
|
1778
|
+
finish();
|
|
1711
1779
|
});
|
|
1712
|
-
child.
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
`
|
|
1717
|
-
|
|
1780
|
+
child.on("exit", (code) => {
|
|
1781
|
+
if (code !== null && code !== 0) {
|
|
1782
|
+
process.stderr.write(
|
|
1783
|
+
`agenthud: --open: '${cmd.command}' exited with code ${code}
|
|
1784
|
+
`
|
|
1785
|
+
);
|
|
1786
|
+
}
|
|
1787
|
+
finish();
|
|
1788
|
+
});
|
|
1789
|
+
setTimeout(() => {
|
|
1790
|
+
if (!settled) {
|
|
1791
|
+
child.unref();
|
|
1792
|
+
finish();
|
|
1793
|
+
}
|
|
1794
|
+
}, 200).unref();
|
|
1795
|
+
});
|
|
1718
1796
|
}
|
|
1719
1797
|
|
|
1720
1798
|
// src/data/summariesIndex.ts
|
|
1721
|
-
import { existsSync as
|
|
1722
|
-
import { join as
|
|
1799
|
+
import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
|
|
1800
|
+
import { join as join5 } from "path";
|
|
1723
1801
|
var INDEX_HEADER_MARKER = "<!-- agenthud-summaries-index -->";
|
|
1724
1802
|
var BACKLINK_START_MARKER = "<!-- agenthud-backlinks-start -->";
|
|
1725
1803
|
var BACKLINK_END_MARKER = "<!-- agenthud-backlinks-end -->";
|
|
@@ -1761,7 +1839,7 @@ function parseSummaryFilename(name) {
|
|
|
1761
1839
|
return null;
|
|
1762
1840
|
}
|
|
1763
1841
|
function listSummaries(dir) {
|
|
1764
|
-
if (!
|
|
1842
|
+
if (!existsSync5(dir)) return [];
|
|
1765
1843
|
let names;
|
|
1766
1844
|
try {
|
|
1767
1845
|
names = readdirSync2(dir);
|
|
@@ -1926,9 +2004,9 @@ function regenerateIndex(summariesDir2) {
|
|
|
1926
2004
|
const entries = listSummaries(summariesDir2);
|
|
1927
2005
|
const snippets = /* @__PURE__ */ new Map();
|
|
1928
2006
|
for (const entry of entries) {
|
|
1929
|
-
const path =
|
|
2007
|
+
const path = join5(summariesDir2, entry.filename);
|
|
1930
2008
|
try {
|
|
1931
|
-
const content =
|
|
2009
|
+
const content = readFileSync6(path, "utf-8");
|
|
1932
2010
|
const snippet = extractContextSnippet(content);
|
|
1933
2011
|
if (snippet) snippets.set(entry.filename, snippet);
|
|
1934
2012
|
const block = buildHeaderBlock(entry.filename, entries);
|
|
@@ -1939,7 +2017,7 @@ function regenerateIndex(summariesDir2) {
|
|
|
1939
2017
|
} catch {
|
|
1940
2018
|
}
|
|
1941
2019
|
}
|
|
1942
|
-
const indexPath =
|
|
2020
|
+
const indexPath = join5(summariesDir2, "index.md");
|
|
1943
2021
|
try {
|
|
1944
2022
|
writeFileSync2(
|
|
1945
2023
|
indexPath,
|
|
@@ -1977,20 +2055,20 @@ function startStderrTicker(label, options2 = {}) {
|
|
|
1977
2055
|
|
|
1978
2056
|
// src/data/summaryRunner.ts
|
|
1979
2057
|
function agenthudHomeDir() {
|
|
1980
|
-
const dir =
|
|
1981
|
-
if (!
|
|
2058
|
+
const dir = join6(homedir3(), ".agenthud");
|
|
2059
|
+
if (!existsSync6(dir)) mkdirSync2(dir, { recursive: true });
|
|
1982
2060
|
return dir;
|
|
1983
2061
|
}
|
|
1984
2062
|
function summariesDir() {
|
|
1985
|
-
const dir =
|
|
1986
|
-
if (!
|
|
2063
|
+
const dir = join6(agenthudHomeDir(), "summaries");
|
|
2064
|
+
if (!existsSync6(dir)) mkdirSync2(dir, { recursive: true });
|
|
1987
2065
|
return dir;
|
|
1988
2066
|
}
|
|
1989
2067
|
function promptFilename(kind) {
|
|
1990
2068
|
return kind === "daily" ? "summary-prompt.md" : "summary-range-prompt.md";
|
|
1991
2069
|
}
|
|
1992
2070
|
function userPromptPath(kind) {
|
|
1993
|
-
return
|
|
2071
|
+
return join6(homedir3(), ".agenthud", promptFilename(kind));
|
|
1994
2072
|
}
|
|
1995
2073
|
function formatPromptSource(kind, override) {
|
|
1996
2074
|
if (kind === "daily" && override) {
|
|
@@ -2003,25 +2081,25 @@ function formatPromptSource(kind, override) {
|
|
|
2003
2081
|
}
|
|
2004
2082
|
function templatePath(kind) {
|
|
2005
2083
|
const here = dirname2(fileURLToPath2(import.meta.url));
|
|
2006
|
-
return
|
|
2084
|
+
return join6(here, "templates", promptFilename(kind));
|
|
2007
2085
|
}
|
|
2008
2086
|
function dateKey(d) {
|
|
2009
2087
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
2010
2088
|
}
|
|
2011
2089
|
function dailyCachePath(date) {
|
|
2012
|
-
return
|
|
2090
|
+
return join6(summariesDir(), `${dateKey(date)}.md`);
|
|
2013
2091
|
}
|
|
2014
2092
|
function rangeCachePath(from, to) {
|
|
2015
|
-
return
|
|
2093
|
+
return join6(summariesDir(), `range-${dateKey(from)}_${dateKey(to)}.md`);
|
|
2016
2094
|
}
|
|
2017
2095
|
function isSameLocalDay2(a, b) {
|
|
2018
2096
|
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
2019
2097
|
}
|
|
2020
2098
|
function ensureUserPromptFile(kind) {
|
|
2021
2099
|
const p = userPromptPath(kind);
|
|
2022
|
-
if (
|
|
2100
|
+
if (existsSync6(p)) return;
|
|
2023
2101
|
const dir = dirname2(p);
|
|
2024
|
-
if (!
|
|
2102
|
+
if (!existsSync6(dir)) mkdirSync2(dir, { recursive: true });
|
|
2025
2103
|
try {
|
|
2026
2104
|
copyFileSync(templatePath(kind), p);
|
|
2027
2105
|
} catch {
|
|
@@ -2030,14 +2108,14 @@ function ensureUserPromptFile(kind) {
|
|
|
2030
2108
|
function resolvePrompt(kind, override) {
|
|
2031
2109
|
if (override) return override;
|
|
2032
2110
|
const p = userPromptPath(kind);
|
|
2033
|
-
if (
|
|
2111
|
+
if (existsSync6(p)) {
|
|
2034
2112
|
try {
|
|
2035
|
-
return
|
|
2113
|
+
return readFileSync7(p, "utf-8");
|
|
2036
2114
|
} catch {
|
|
2037
2115
|
}
|
|
2038
2116
|
}
|
|
2039
2117
|
try {
|
|
2040
|
-
return
|
|
2118
|
+
return readFileSync7(templatePath(kind), "utf-8");
|
|
2041
2119
|
} catch {
|
|
2042
2120
|
return "Summarize the input below.";
|
|
2043
2121
|
}
|
|
@@ -2213,9 +2291,9 @@ async function generateDailySummary(opts) {
|
|
|
2213
2291
|
const isToday = isSameLocalDay2(opts.date, opts.today);
|
|
2214
2292
|
const cached = dailyCachePath(opts.date);
|
|
2215
2293
|
const dateLabel = dateKey(opts.date);
|
|
2216
|
-
if (!isToday && !opts.force &&
|
|
2294
|
+
if (!isToday && !opts.force && existsSync6(cached)) {
|
|
2217
2295
|
try {
|
|
2218
|
-
const content =
|
|
2296
|
+
const content = readFileSync7(cached, "utf-8");
|
|
2219
2297
|
if (opts.announce) {
|
|
2220
2298
|
process.stderr.write(`cached summary from ${cached}
|
|
2221
2299
|
`);
|
|
@@ -2256,21 +2334,36 @@ async function generateDailySummary(opts) {
|
|
|
2256
2334
|
});
|
|
2257
2335
|
const reportBytes = Buffer.byteLength(reportMarkdown, "utf-8");
|
|
2258
2336
|
const estimatedTokens = Math.ceil(reportBytes / 4);
|
|
2337
|
+
const reportLines = reportMarkdown.split("\n");
|
|
2338
|
+
const sessionCount = reportLines.filter((l) => l.startsWith("## ")).length;
|
|
2339
|
+
const activityCount = reportLines.filter(
|
|
2340
|
+
(l) => /^\[\d{2}:\d{2}\]/.test(l)
|
|
2341
|
+
).length;
|
|
2342
|
+
const commitCount = reportLines.filter(
|
|
2343
|
+
(l) => /^\[\d{2}:\d{2}\] ◆/.test(l)
|
|
2344
|
+
).length;
|
|
2259
2345
|
if (opts.announce) {
|
|
2260
|
-
const reportLines = reportMarkdown.split("\n");
|
|
2261
|
-
const sessionCount = reportLines.filter((l) => l.startsWith("## ")).length;
|
|
2262
|
-
const activityCount = reportLines.filter(
|
|
2263
|
-
(l) => /^\[\d{2}:\d{2}\]/.test(l)
|
|
2264
|
-
).length;
|
|
2265
|
-
const commitCount = reportLines.filter(
|
|
2266
|
-
(l) => /^\[\d{2}:\d{2}\] ◆/.test(l)
|
|
2267
|
-
).length;
|
|
2268
2346
|
const sizeKb = (reportBytes / 1024).toFixed(1);
|
|
2269
2347
|
process.stderr.write(
|
|
2270
2348
|
`input: ${sessionCount} sessions, ${activityCount} activities, ${commitCount} commits (${reportLines.length} lines, ${sizeKb}KB \u2248 ${estimatedTokens.toLocaleString()} tokens)
|
|
2271
2349
|
`
|
|
2272
2350
|
);
|
|
2273
2351
|
}
|
|
2352
|
+
if (sessionCount === 0 && activityCount === 0 && commitCount === 0) {
|
|
2353
|
+
if (opts.announce) {
|
|
2354
|
+
process.stderr.write(
|
|
2355
|
+
`${dateLabel} has no activity \u2014 skipping (no file written)
|
|
2356
|
+
`
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2359
|
+
return {
|
|
2360
|
+
code: 0,
|
|
2361
|
+
markdown: "",
|
|
2362
|
+
fromCache: false,
|
|
2363
|
+
skipped: true,
|
|
2364
|
+
usage: null
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2274
2367
|
if (opts.confirmBeforeSpawn) {
|
|
2275
2368
|
const proceed = await opts.confirmBeforeSpawn();
|
|
2276
2369
|
if (!proceed) {
|
|
@@ -2354,17 +2447,18 @@ async function runSummary(options2) {
|
|
|
2354
2447
|
detailLimit: options2.detailLimit,
|
|
2355
2448
|
withGit: options2.withGit
|
|
2356
2449
|
});
|
|
2357
|
-
|
|
2450
|
+
const indexRefreshNeeded = res.code === 0 && (!res.skipped || options2.openIndex === true);
|
|
2451
|
+
if (indexRefreshNeeded) {
|
|
2358
2452
|
try {
|
|
2359
2453
|
regenerateIndex(summariesDir());
|
|
2360
2454
|
} catch {
|
|
2361
2455
|
}
|
|
2362
2456
|
}
|
|
2363
2457
|
if (options2.open && res.code === 0 && !res.skipped) {
|
|
2364
|
-
openInDefaultApp(dailyCachePath(options2.date));
|
|
2458
|
+
await openInDefaultApp(dailyCachePath(options2.date));
|
|
2365
2459
|
}
|
|
2366
|
-
if (options2.openIndex && res.code === 0
|
|
2367
|
-
openInDefaultApp(
|
|
2460
|
+
if (options2.openIndex && res.code === 0) {
|
|
2461
|
+
await openInDefaultApp(join6(summariesDir(), "index.md"));
|
|
2368
2462
|
}
|
|
2369
2463
|
return res.code;
|
|
2370
2464
|
}
|
|
@@ -2379,10 +2473,10 @@ async function runRangeSummary(options2) {
|
|
|
2379
2473
|
options2.force,
|
|
2380
2474
|
dates,
|
|
2381
2475
|
options2.today,
|
|
2382
|
-
|
|
2476
|
+
existsSync6(rangeCache)
|
|
2383
2477
|
)) {
|
|
2384
2478
|
try {
|
|
2385
|
-
const content =
|
|
2479
|
+
const content = readFileSync7(rangeCache, "utf-8");
|
|
2386
2480
|
process.stderr.write(
|
|
2387
2481
|
`cached range summary from ${rangeCache}
|
|
2388
2482
|
`
|
|
@@ -2395,9 +2489,9 @@ async function runRangeSummary(options2) {
|
|
|
2395
2489
|
regenerateIndex(summariesDir());
|
|
2396
2490
|
} catch {
|
|
2397
2491
|
}
|
|
2398
|
-
if (options2.open) openInDefaultApp(rangeCache);
|
|
2492
|
+
if (options2.open) await openInDefaultApp(rangeCache);
|
|
2399
2493
|
if (options2.openIndex) {
|
|
2400
|
-
openInDefaultApp(
|
|
2494
|
+
await openInDefaultApp(join6(summariesDir(), "index.md"));
|
|
2401
2495
|
}
|
|
2402
2496
|
return 0;
|
|
2403
2497
|
} catch {
|
|
@@ -2407,7 +2501,7 @@ async function runRangeSummary(options2) {
|
|
|
2407
2501
|
let missingCount = 0;
|
|
2408
2502
|
for (const d of dates) {
|
|
2409
2503
|
const isToday = isSameLocalDay2(d, options2.today);
|
|
2410
|
-
if (!isToday &&
|
|
2504
|
+
if (!isToday && existsSync6(dailyCachePath(d))) cachedCount++;
|
|
2411
2505
|
else missingCount++;
|
|
2412
2506
|
}
|
|
2413
2507
|
process.stderr.write(
|
|
@@ -2426,7 +2520,7 @@ async function runRangeSummary(options2) {
|
|
|
2426
2520
|
process.stderr.write(`
|
|
2427
2521
|
--- ${label} ---
|
|
2428
2522
|
`);
|
|
2429
|
-
const willPrompt = !options2.assumeYes && (isToday || !
|
|
2523
|
+
const willPrompt = !options2.assumeYes && (isToday || !existsSync6(dailyCachePath(d)));
|
|
2430
2524
|
const confirmer = willPrompt ? async () => {
|
|
2431
2525
|
const hint = isToday ? " (today \u2014 regenerated every time)" : "";
|
|
2432
2526
|
return ask(`Generate this summary${hint}? [Y/n] `, true);
|
|
@@ -2445,7 +2539,7 @@ async function runRangeSummary(options2) {
|
|
|
2445
2539
|
withGit: options2.withGit
|
|
2446
2540
|
});
|
|
2447
2541
|
if (res.skipped) {
|
|
2448
|
-
process.stderr.write(`agenthud: ${label} \u2014 skipped
|
|
2542
|
+
process.stderr.write(`agenthud: ${label} \u2014 skipped.
|
|
2449
2543
|
`);
|
|
2450
2544
|
skippedCount++;
|
|
2451
2545
|
continue;
|
|
@@ -2466,8 +2560,17 @@ async function runRangeSummary(options2) {
|
|
|
2466
2560
|
dailyMarkdowns.push({ date: d, markdown: text });
|
|
2467
2561
|
}
|
|
2468
2562
|
if (dailyMarkdowns.length === 0) {
|
|
2469
|
-
process.stderr.write(
|
|
2470
|
-
|
|
2563
|
+
process.stderr.write(
|
|
2564
|
+
"no daily activity in this range \u2014 nothing to combine\n"
|
|
2565
|
+
);
|
|
2566
|
+
if (options2.openIndex) {
|
|
2567
|
+
try {
|
|
2568
|
+
regenerateIndex(summariesDir());
|
|
2569
|
+
} catch {
|
|
2570
|
+
}
|
|
2571
|
+
await openInDefaultApp(join6(summariesDir(), "index.md"));
|
|
2572
|
+
}
|
|
2573
|
+
return 0;
|
|
2471
2574
|
}
|
|
2472
2575
|
const metaInput = dailyMarkdowns.map(({ date, markdown }) => `# ${dateKey(date)}
|
|
2473
2576
|
|
|
@@ -2510,15 +2613,15 @@ combining ${dailyMarkdowns.length} daily summaries into range summary...
|
|
|
2510
2613
|
regenerateIndex(summariesDir());
|
|
2511
2614
|
} catch {
|
|
2512
2615
|
}
|
|
2513
|
-
if (options2.open) openInDefaultApp(rangeCache);
|
|
2616
|
+
if (options2.open) await openInDefaultApp(rangeCache);
|
|
2514
2617
|
if (options2.openIndex) {
|
|
2515
|
-
openInDefaultApp(
|
|
2618
|
+
await openInDefaultApp(join6(summariesDir(), "index.md"));
|
|
2516
2619
|
}
|
|
2517
2620
|
return 0;
|
|
2518
2621
|
}
|
|
2519
2622
|
|
|
2520
2623
|
// src/ui/App.tsx
|
|
2521
|
-
import { existsSync as
|
|
2624
|
+
import { existsSync as existsSync7, watch } from "fs";
|
|
2522
2625
|
import { basename as basename3 } from "path";
|
|
2523
2626
|
import { Box as Box5, Text as Text5, useApp, useInput, useStdout } from "ink";
|
|
2524
2627
|
import { useCallback, useEffect as useEffect3, useMemo, useRef, useState as useState3 } from "react";
|
|
@@ -4063,7 +4166,7 @@ function App({
|
|
|
4063
4166
|
useEffect3(() => {
|
|
4064
4167
|
if (!isWatchMode) return;
|
|
4065
4168
|
const projectsDir = getProjectsDir();
|
|
4066
|
-
const usePolling = process.platform === "linux" || !
|
|
4169
|
+
const usePolling = process.platform === "linux" || !existsSync7(projectsDir);
|
|
4067
4170
|
if (usePolling) {
|
|
4068
4171
|
const timer = setInterval(
|
|
4069
4172
|
() => refreshRef.current(),
|
|
@@ -4605,10 +4708,10 @@ function installAltScreenCleanup() {
|
|
|
4605
4708
|
}
|
|
4606
4709
|
|
|
4607
4710
|
// src/utils/legacyConfig.ts
|
|
4608
|
-
import { join as
|
|
4711
|
+
import { join as join7, resolve } from "path";
|
|
4609
4712
|
function isLegacyProjectConfig(cwd, home) {
|
|
4610
|
-
const legacy = resolve(
|
|
4611
|
-
const global = resolve(
|
|
4713
|
+
const legacy = resolve(join7(cwd, ".agenthud", "config.yaml"));
|
|
4714
|
+
const global = resolve(join7(home, ".agenthud", "config.yaml"));
|
|
4612
4715
|
return legacy !== global;
|
|
4613
4716
|
}
|
|
4614
4717
|
|
|
@@ -4628,8 +4731,8 @@ if (options.command === "version") {
|
|
|
4628
4731
|
console.log(getVersion());
|
|
4629
4732
|
process.exit(0);
|
|
4630
4733
|
}
|
|
4631
|
-
var legacyConfig =
|
|
4632
|
-
if (isLegacyProjectConfig(process.cwd(), homedir5()) &&
|
|
4734
|
+
var legacyConfig = join8(process.cwd(), ".agenthud", "config.yaml");
|
|
4735
|
+
if (isLegacyProjectConfig(process.cwd(), homedir5()) && existsSync8(legacyConfig)) {
|
|
4633
4736
|
console.log(
|
|
4634
4737
|
"The project-level config file (.agenthud/config.yaml) is no longer supported."
|
|
4635
4738
|
);
|
package/package.json
CHANGED