agenthud 0.12.3 → 0.13.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
CHANGED
|
@@ -191,12 +191,12 @@ Output:
|
|
|
191
191
|
| Flag | Default | Description |
|
|
192
192
|
|------|---------|-------------|
|
|
193
193
|
| `--date` | today | `YYYY-MM-DD`, `today`, `yesterday`, or `-Nd` (N days ago, local date) |
|
|
194
|
-
| `--include` | `user,response,bash,edit,thinking` | Comma-separated types or `all` |
|
|
194
|
+
| `--include` | `user,response,bash,edit,thinking,task` | Comma-separated types or `all` |
|
|
195
195
|
| `--format` | `markdown` | `markdown` or `json` |
|
|
196
196
|
| `--detail-limit` | `120` | Max chars per detail field; `0` = unlimited |
|
|
197
197
|
| `--with-git` | off | Merge git commits from each session's project into the timeline |
|
|
198
198
|
|
|
199
|
-
`--include` types: `response`, `bash`, `edit`, `thinking`, `read`, `glob`, `user`
|
|
199
|
+
`--include` types: `response`, `bash`, `edit`, `thinking`, `read`, `glob`, `user`, `task` (Task tool delegations to subagents — surfaces the subagent's returned text so the LLM summary can see what the subagent actually did)
|
|
200
200
|
|
|
201
201
|
## Summary
|
|
202
202
|
|
|
@@ -262,7 +262,7 @@ refreshInterval: 2s
|
|
|
262
262
|
|
|
263
263
|
# Activity filter presets (cycle with 'f' key in viewer)
|
|
264
264
|
# Each list is one preset. Use "all" (or "*") to show everything.
|
|
265
|
-
# Types: response, user, bash, edit, thinking, read, glob, commit
|
|
265
|
+
# Types: response, user, bash, edit, thinking, read, glob, commit, task
|
|
266
266
|
filterPresets:
|
|
267
267
|
- ["all"]
|
|
268
268
|
- ["response", "user"]
|
|
@@ -270,7 +270,7 @@ filterPresets:
|
|
|
270
270
|
|
|
271
271
|
# Defaults for `agenthud report` (CLI flags still win per-invocation).
|
|
272
272
|
report:
|
|
273
|
-
include: [user, response, bash, edit, thinking]
|
|
273
|
+
include: [user, response, bash, edit, thinking, task]
|
|
274
274
|
detailLimit: 120
|
|
275
275
|
withGit: false
|
|
276
276
|
format: markdown
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,8 @@ var DEFAULT_INCLUDE_TYPES = [
|
|
|
23
23
|
"response",
|
|
24
24
|
"bash",
|
|
25
25
|
"edit",
|
|
26
|
-
"thinking"
|
|
26
|
+
"thinking",
|
|
27
|
+
"task"
|
|
27
28
|
];
|
|
28
29
|
var ALLOWED_INCLUDE_TYPES = /* @__PURE__ */ new Set([
|
|
29
30
|
"user",
|
|
@@ -33,7 +34,8 @@ var ALLOWED_INCLUDE_TYPES = /* @__PURE__ */ new Set([
|
|
|
33
34
|
"thinking",
|
|
34
35
|
"read",
|
|
35
36
|
"glob",
|
|
36
|
-
"commit"
|
|
37
|
+
"commit",
|
|
38
|
+
"task"
|
|
37
39
|
]);
|
|
38
40
|
var DEFAULT_GLOBAL_CONFIG = {
|
|
39
41
|
refreshIntervalMs: 2e3,
|
|
@@ -949,6 +951,10 @@ function buildToolDetailBody(name, input, result) {
|
|
|
949
951
|
const content = result?.content ?? input?.content;
|
|
950
952
|
if (content) return { text: content, kind: "code" };
|
|
951
953
|
}
|
|
954
|
+
if (name === "Task") {
|
|
955
|
+
const content = result?.content;
|
|
956
|
+
if (content) return { text: content, kind: "code" };
|
|
957
|
+
}
|
|
952
958
|
if (name === "Read") {
|
|
953
959
|
const content = result?.file?.content;
|
|
954
960
|
if (content) {
|
|
@@ -1123,6 +1129,7 @@ function activityMatchesInclude(activity, include) {
|
|
|
1123
1129
|
return true;
|
|
1124
1130
|
if (include.includes("glob") && (label === "glob" || label === "grep"))
|
|
1125
1131
|
return true;
|
|
1132
|
+
if (include.includes("task") && label === "task") return true;
|
|
1126
1133
|
return false;
|
|
1127
1134
|
}
|
|
1128
1135
|
function isSameLocalDay(a, b) {
|
|
@@ -1137,6 +1144,14 @@ function formatActivity(activity, limit) {
|
|
|
1137
1144
|
const suffix = detail ? `: ${detail}` : "";
|
|
1138
1145
|
return `[${time}] ${activity.icon} ${activity.label}${suffix}`;
|
|
1139
1146
|
}
|
|
1147
|
+
function formatTaskBody(activity, limit) {
|
|
1148
|
+
if (activity.label !== "Task") return null;
|
|
1149
|
+
if (!activity.detailBody) return null;
|
|
1150
|
+
const body = truncateRaw(activity.detailBody, limit);
|
|
1151
|
+
return `<task-result>
|
|
1152
|
+
${body}
|
|
1153
|
+
</task-result>`;
|
|
1154
|
+
}
|
|
1140
1155
|
function formatDateString2(date) {
|
|
1141
1156
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
1142
1157
|
}
|
|
@@ -1239,6 +1254,8 @@ function generateReport(sessions, options2) {
|
|
|
1239
1254
|
lines.push("");
|
|
1240
1255
|
for (const activity of activities) {
|
|
1241
1256
|
lines.push(formatActivity(activity, detailLimit));
|
|
1257
|
+
const taskBody = formatTaskBody(activity, detailLimit);
|
|
1258
|
+
if (taskBody) lines.push(taskBody);
|
|
1242
1259
|
}
|
|
1243
1260
|
lines.push("");
|
|
1244
1261
|
}
|
|
@@ -1302,8 +1319,8 @@ function truncateByWidth(text, maxWidth) {
|
|
|
1302
1319
|
}
|
|
1303
1320
|
var widthCache = /* @__PURE__ */ new Map();
|
|
1304
1321
|
function getDisplayWidth(s) {
|
|
1305
|
-
const
|
|
1306
|
-
if (
|
|
1322
|
+
const cached2 = widthCache.get(s);
|
|
1323
|
+
if (cached2 !== void 0) return cached2;
|
|
1307
1324
|
const w = stringWidth(s);
|
|
1308
1325
|
widthCache.set(s, w);
|
|
1309
1326
|
return w;
|
|
@@ -1688,8 +1705,28 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
1688
1705
|
|
|
1689
1706
|
// src/utils/openInDefaultApp.ts
|
|
1690
1707
|
import { spawn } from "child_process";
|
|
1691
|
-
import { existsSync as existsSync4
|
|
1708
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1692
1709
|
import { join as join4 } from "path";
|
|
1710
|
+
|
|
1711
|
+
// src/utils/platform.ts
|
|
1712
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
1713
|
+
var cached = null;
|
|
1714
|
+
function isWSL() {
|
|
1715
|
+
if (cached !== null) return cached;
|
|
1716
|
+
if (process.env.WSL_DISTRO_NAME) {
|
|
1717
|
+
cached = true;
|
|
1718
|
+
return cached;
|
|
1719
|
+
}
|
|
1720
|
+
try {
|
|
1721
|
+
const ver = readFileSync5("/proc/version", "utf-8");
|
|
1722
|
+
cached = /microsoft|wsl/i.test(ver);
|
|
1723
|
+
} catch {
|
|
1724
|
+
cached = false;
|
|
1725
|
+
}
|
|
1726
|
+
return cached;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
// src/utils/openInDefaultApp.ts
|
|
1693
1730
|
function buildOpenCommand(platform, path, opts = {}) {
|
|
1694
1731
|
switch (platform) {
|
|
1695
1732
|
case "darwin":
|
|
@@ -1703,15 +1740,6 @@ function buildOpenCommand(platform, path, opts = {}) {
|
|
|
1703
1740
|
return null;
|
|
1704
1741
|
}
|
|
1705
1742
|
}
|
|
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
1743
|
function commandExists(command) {
|
|
1716
1744
|
const PATH = process.env.PATH ?? "";
|
|
1717
1745
|
const sep = process.platform === "win32" ? ";" : ":";
|
|
@@ -2120,6 +2148,16 @@ function resolvePrompt(kind, override) {
|
|
|
2120
2148
|
return "Summarize the input below.";
|
|
2121
2149
|
}
|
|
2122
2150
|
}
|
|
2151
|
+
function buildRangeMetaInput(dailyMarkdowns) {
|
|
2152
|
+
if (dailyMarkdowns.length === 0) return "";
|
|
2153
|
+
return dailyMarkdowns.map(
|
|
2154
|
+
({ date, markdown }) => `<day date="${dateKey(date)}">
|
|
2155
|
+
|
|
2156
|
+
${markdown}
|
|
2157
|
+
|
|
2158
|
+
</day>`
|
|
2159
|
+
).join("\n\n");
|
|
2160
|
+
}
|
|
2123
2161
|
function shouldUseRangeCache(force, dates, today, cacheExists) {
|
|
2124
2162
|
if (force) return false;
|
|
2125
2163
|
if (!cacheExists) return false;
|
|
@@ -2206,7 +2244,12 @@ function spawnClaude(opts) {
|
|
|
2206
2244
|
resolve2({ code: 1, text: "", usage: null });
|
|
2207
2245
|
}
|
|
2208
2246
|
});
|
|
2247
|
+
let firstChunkFired = false;
|
|
2209
2248
|
const writeText = (text) => {
|
|
2249
|
+
if (!firstChunkFired) {
|
|
2250
|
+
firstChunkFired = true;
|
|
2251
|
+
opts.onFirstChunk?.();
|
|
2252
|
+
}
|
|
2210
2253
|
assembledText += text;
|
|
2211
2254
|
if (opts.streamToStdout) process.stdout.write(text);
|
|
2212
2255
|
cacheStream?.write(text);
|
|
@@ -2289,13 +2332,13 @@ var REPORT_TOKEN_WARN_THRESHOLD = 3e5;
|
|
|
2289
2332
|
async function generateDailySummary(opts) {
|
|
2290
2333
|
ensureUserPromptFile("daily");
|
|
2291
2334
|
const isToday = isSameLocalDay2(opts.date, opts.today);
|
|
2292
|
-
const
|
|
2335
|
+
const cached2 = dailyCachePath(opts.date);
|
|
2293
2336
|
const dateLabel = dateKey(opts.date);
|
|
2294
|
-
if (!isToday && !opts.force && existsSync6(
|
|
2337
|
+
if (!isToday && !opts.force && existsSync6(cached2)) {
|
|
2295
2338
|
try {
|
|
2296
|
-
const content = readFileSync7(
|
|
2339
|
+
const content = readFileSync7(cached2, "utf-8");
|
|
2297
2340
|
if (opts.announce) {
|
|
2298
|
-
process.stderr.write(`cached summary from ${
|
|
2341
|
+
process.stderr.write(`cached summary from ${cached2}
|
|
2299
2342
|
`);
|
|
2300
2343
|
}
|
|
2301
2344
|
if (opts.streamToStdout) {
|
|
@@ -2399,27 +2442,22 @@ async function generateDailySummary(opts) {
|
|
|
2399
2442
|
}
|
|
2400
2443
|
}
|
|
2401
2444
|
}
|
|
2402
|
-
const
|
|
2403
|
-
if (opts.announce && !showTicker) {
|
|
2404
|
-
process.stderr.write(
|
|
2405
|
-
`sending to claude (this may take a minute)...
|
|
2406
|
-
|
|
2407
|
-
`
|
|
2408
|
-
);
|
|
2409
|
-
}
|
|
2410
|
-
const stopTicker = showTicker ? startStderrTicker("sending to claude") : null;
|
|
2445
|
+
const stopTicker = opts.announce ? startStderrTicker("sending to claude") : null;
|
|
2411
2446
|
const prompt = resolvePrompt("daily", opts.promptOverride);
|
|
2412
2447
|
const result = await spawnClaude({
|
|
2413
2448
|
prompt,
|
|
2414
2449
|
stdin: reportMarkdown,
|
|
2415
|
-
cachePath:
|
|
2450
|
+
cachePath: cached2,
|
|
2416
2451
|
streamToStdout: opts.streamToStdout,
|
|
2417
|
-
model: opts.model
|
|
2452
|
+
model: opts.model,
|
|
2453
|
+
onFirstChunk: () => {
|
|
2454
|
+
if (stopTicker) stopTicker();
|
|
2455
|
+
}
|
|
2418
2456
|
});
|
|
2419
2457
|
if (stopTicker) stopTicker();
|
|
2420
2458
|
if (opts.announce && result.code === 0) {
|
|
2421
2459
|
process.stderr.write("\n");
|
|
2422
|
-
process.stderr.write(`saved to ${
|
|
2460
|
+
process.stderr.write(`saved to ${cached2}
|
|
2423
2461
|
`);
|
|
2424
2462
|
if (result.usage) {
|
|
2425
2463
|
process.stderr.write(`${formatUsage(result.usage)}
|
|
@@ -2572,33 +2610,24 @@ async function runRangeSummary(options2) {
|
|
|
2572
2610
|
}
|
|
2573
2611
|
return 0;
|
|
2574
2612
|
}
|
|
2575
|
-
const metaInput = dailyMarkdowns
|
|
2576
|
-
|
|
2577
|
-
${markdown}`).join("\n\n---\n\n");
|
|
2613
|
+
const metaInput = buildRangeMetaInput(dailyMarkdowns);
|
|
2578
2614
|
process.stderr.write(
|
|
2579
2615
|
`
|
|
2580
2616
|
combining ${dailyMarkdowns.length} daily summaries into range summary...
|
|
2581
2617
|
`
|
|
2582
2618
|
);
|
|
2583
2619
|
const metaStreams = !options2.open;
|
|
2584
|
-
|
|
2585
|
-
} else {
|
|
2586
|
-
process.stderr.write(
|
|
2587
|
-
`sending to claude (this may take a minute)...
|
|
2588
|
-
|
|
2589
|
-
`
|
|
2590
|
-
);
|
|
2591
|
-
}
|
|
2592
|
-
const stopMetaTicker = metaStreams ? null : startStderrTicker("sending to claude");
|
|
2620
|
+
const stopMetaTicker = startStderrTicker("sending to claude");
|
|
2593
2621
|
const metaPrompt = resolvePrompt("range");
|
|
2594
2622
|
const metaResult = await spawnClaude({
|
|
2595
2623
|
prompt: metaPrompt,
|
|
2596
2624
|
stdin: metaInput,
|
|
2597
2625
|
cachePath: rangeCache,
|
|
2598
2626
|
streamToStdout: metaStreams,
|
|
2599
|
-
model: options2.model
|
|
2627
|
+
model: options2.model,
|
|
2628
|
+
onFirstChunk: () => stopMetaTicker()
|
|
2600
2629
|
});
|
|
2601
|
-
|
|
2630
|
+
stopMetaTicker();
|
|
2602
2631
|
if (metaResult.code !== 0) {
|
|
2603
2632
|
return metaResult.code;
|
|
2604
2633
|
}
|
|
@@ -4709,10 +4738,14 @@ function installAltScreenCleanup() {
|
|
|
4709
4738
|
|
|
4710
4739
|
// src/utils/legacyConfig.ts
|
|
4711
4740
|
import { join as join7, resolve } from "path";
|
|
4712
|
-
|
|
4741
|
+
var WSL_WINDOWS_USER_HOME = /^\/mnt\/[a-z]\/Users\/[^/]+\/?$/i;
|
|
4742
|
+
function isLegacyProjectConfig(cwd, home, opts = {}) {
|
|
4713
4743
|
const legacy = resolve(join7(cwd, ".agenthud", "config.yaml"));
|
|
4714
4744
|
const global = resolve(join7(home, ".agenthud", "config.yaml"));
|
|
4715
|
-
|
|
4745
|
+
if (legacy === global) return false;
|
|
4746
|
+
const wsl = opts.isWSL ?? isWSL();
|
|
4747
|
+
if (wsl && WSL_WINDOWS_USER_HOME.test(cwd)) return false;
|
|
4748
|
+
return true;
|
|
4716
4749
|
}
|
|
4717
4750
|
|
|
4718
4751
|
// src/main.ts
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
The
|
|
2
|
-
|
|
1
|
+
The input contains daily engineering summaries from a date range.
|
|
2
|
+
|
|
3
|
+
Each day is wrapped in an XML tag with its date as an attribute:
|
|
4
|
+
|
|
5
|
+
<day date="YYYY-MM-DD">
|
|
6
|
+
(that day's summary — markdown using sections like
|
|
7
|
+
Context / Key Accomplishments / Technical Insights /
|
|
8
|
+
Major Code Changes / Open Questions)
|
|
9
|
+
</day>
|
|
10
|
+
|
|
11
|
+
Multiple `<day>` blocks follow in chronological order. Use the
|
|
12
|
+
`date` attribute as the authoritative date for that block — do not
|
|
13
|
+
infer dates from headings or text inside the block. Any `# YYYY-MM-DD`
|
|
14
|
+
heading or `---` line you see inside a `<day>` block is part of the
|
|
15
|
+
day's content, not a structural divider.
|
|
3
16
|
|
|
4
17
|
Write a range-level synthesis in English.
|
|
5
18
|
Aim for roughly 400-700 words total — the value of a range summary is cross-day pattern extraction, not re-summarization.
|
|
@@ -15,6 +28,8 @@ The point of a range summary is to surface what only becomes visible by looking
|
|
|
15
28
|
- outcomes that matter at the range level, not at any single day
|
|
16
29
|
- work that started in one day and continued, completed, or was abandoned later
|
|
17
30
|
|
|
31
|
+
When you reference a specific day, use its `date` attribute value verbatim (`2026-06-07`), not a relative term like "Monday" or "yesterday".
|
|
32
|
+
|
|
18
33
|
Use the following format:
|
|
19
34
|
|
|
20
35
|
## Range Overview
|
|
@@ -32,4 +47,4 @@ Themes that surfaced on more than one day: repeated debugging classes, recurring
|
|
|
32
47
|
## Carried-Over / Unfinished Work
|
|
33
48
|
Work still in progress at the end of the range, or open questions that persisted across multiple days.
|
|
34
49
|
|
|
35
|
-
Daily summaries:
|
|
50
|
+
Daily summaries follow:
|
package/package.json
CHANGED