agenthud 0.6.4 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +143 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -602,6 +602,68 @@ function getToolDetail(_toolName, input) {
|
|
|
602
602
|
}
|
|
603
603
|
return "";
|
|
604
604
|
}
|
|
605
|
+
var MAX_SUB_ACTIVITIES = 3;
|
|
606
|
+
function getSubagentFiles(sessionFile) {
|
|
607
|
+
const subagentsDir = join3(sessionFile.replace(/\.jsonl$/, ""), "subagents");
|
|
608
|
+
if (!existsSync4(subagentsDir)) {
|
|
609
|
+
return [];
|
|
610
|
+
}
|
|
611
|
+
try {
|
|
612
|
+
const files = readdirSync(subagentsDir).filter(
|
|
613
|
+
(f) => f.endsWith(".jsonl")
|
|
614
|
+
);
|
|
615
|
+
const fileInfos = files.map((file) => {
|
|
616
|
+
const filePath = join3(subagentsDir, file);
|
|
617
|
+
const stat = statSync(filePath);
|
|
618
|
+
return { filePath, mtimeMs: stat.mtimeMs };
|
|
619
|
+
});
|
|
620
|
+
fileInfos.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
621
|
+
return fileInfos;
|
|
622
|
+
} catch {
|
|
623
|
+
return [];
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function parseSubagentFile(filePath) {
|
|
627
|
+
try {
|
|
628
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
629
|
+
const lines = content.trim().split("\n").filter(Boolean);
|
|
630
|
+
const allActivities = [];
|
|
631
|
+
for (const line of lines) {
|
|
632
|
+
try {
|
|
633
|
+
const entry = JSON.parse(line);
|
|
634
|
+
if (entry.type === "assistant" && entry.message?.content) {
|
|
635
|
+
const messageContent = entry.message.content;
|
|
636
|
+
if (Array.isArray(messageContent)) {
|
|
637
|
+
for (const block of messageContent) {
|
|
638
|
+
if (block.type === "tool_use" && block.name) {
|
|
639
|
+
const toolName = block.name;
|
|
640
|
+
if (toolName === "TodoWrite") continue;
|
|
641
|
+
const icon = ICONS[toolName] || ICONS.Default;
|
|
642
|
+
const detail = getToolDetail(toolName, block.input);
|
|
643
|
+
const timestamp = entry.timestamp ? new Date(entry.timestamp) : /* @__PURE__ */ new Date();
|
|
644
|
+
allActivities.push({
|
|
645
|
+
timestamp,
|
|
646
|
+
type: "tool",
|
|
647
|
+
icon,
|
|
648
|
+
label: toolName,
|
|
649
|
+
detail
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
} catch {
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
allActivities.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
|
|
659
|
+
return {
|
|
660
|
+
activities: allActivities.slice(0, MAX_SUB_ACTIVITIES),
|
|
661
|
+
totalCount: allActivities.length
|
|
662
|
+
};
|
|
663
|
+
} catch {
|
|
664
|
+
return { activities: [], totalCount: 0 };
|
|
665
|
+
}
|
|
666
|
+
}
|
|
605
667
|
function parseSessionState(sessionFile, maxActivities = DEFAULT_MAX_ACTIVITIES) {
|
|
606
668
|
const defaultState = {
|
|
607
669
|
status: "none",
|
|
@@ -699,13 +761,14 @@ function parseSessionState(sessionFile, maxActivities = DEFAULT_MAX_ACTIVITIES)
|
|
|
699
761
|
lastActivity.count = (lastActivity.count || 1) + 1;
|
|
700
762
|
lastActivity.timestamp = lastTimestamp || /* @__PURE__ */ new Date();
|
|
701
763
|
} else {
|
|
702
|
-
|
|
764
|
+
const activity = {
|
|
703
765
|
timestamp: lastTimestamp || /* @__PURE__ */ new Date(),
|
|
704
766
|
type: "tool",
|
|
705
767
|
icon,
|
|
706
768
|
label: toolName,
|
|
707
769
|
detail
|
|
708
|
-
}
|
|
770
|
+
};
|
|
771
|
+
activities.push(activity);
|
|
709
772
|
}
|
|
710
773
|
lastType = "tool";
|
|
711
774
|
} else if (block.type === "text" && block.text) {
|
|
@@ -755,10 +818,10 @@ function parseSessionState(sessionFile, maxActivities = DEFAULT_MAX_ACTIVITIES)
|
|
|
755
818
|
const subagentsDir = join3(sessionFile.replace(/\.jsonl$/, ""), "subagents");
|
|
756
819
|
if (existsSync4(subagentsDir)) {
|
|
757
820
|
try {
|
|
758
|
-
const
|
|
821
|
+
const subagentFiles2 = readdirSync(subagentsDir).filter(
|
|
759
822
|
(f) => f.endsWith(".jsonl")
|
|
760
823
|
);
|
|
761
|
-
for (const file of
|
|
824
|
+
for (const file of subagentFiles2) {
|
|
762
825
|
const filePath = join3(subagentsDir, file);
|
|
763
826
|
try {
|
|
764
827
|
const subContent = readFileSync5(filePath, "utf-8");
|
|
@@ -779,9 +842,22 @@ function parseSessionState(sessionFile, maxActivities = DEFAULT_MAX_ACTIVITIES)
|
|
|
779
842
|
} catch {
|
|
780
843
|
}
|
|
781
844
|
}
|
|
845
|
+
const finalActivities = activities.slice(-maxActivities).reverse();
|
|
846
|
+
const subagentFiles = getSubagentFiles(sessionFile);
|
|
847
|
+
let taskIndex = 0;
|
|
848
|
+
for (const activity of finalActivities) {
|
|
849
|
+
if (activity.label === "Task" && taskIndex < subagentFiles.length) {
|
|
850
|
+
const subagentData = parseSubagentFile(subagentFiles[taskIndex].filePath);
|
|
851
|
+
if (subagentData.totalCount > 0) {
|
|
852
|
+
activity.subActivities = subagentData.activities;
|
|
853
|
+
activity.subActivityCount = subagentData.totalCount;
|
|
854
|
+
}
|
|
855
|
+
taskIndex++;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
782
858
|
return {
|
|
783
859
|
status,
|
|
784
|
-
activities:
|
|
860
|
+
activities: finalActivities,
|
|
785
861
|
tokenCount,
|
|
786
862
|
sessionStartTime,
|
|
787
863
|
todos
|
|
@@ -2111,8 +2187,15 @@ function ClaudePanel({
|
|
|
2111
2187
|
const lines = [];
|
|
2112
2188
|
for (let i = 0; i < state.activities.length; i++) {
|
|
2113
2189
|
const activity = state.activities[i];
|
|
2190
|
+
let modifiedActivity = activity;
|
|
2191
|
+
if (activity.label === "Task" && activity.subActivityCount && activity.subActivityCount > 0) {
|
|
2192
|
+
modifiedActivity = {
|
|
2193
|
+
...activity,
|
|
2194
|
+
detail: activity.detail ? `${activity.detail} (${activity.subActivityCount})` : `(${activity.subActivityCount})`
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2114
2197
|
const { timestamp, icon, labelContent, displayWidth } = formatActivityParts(
|
|
2115
|
-
|
|
2198
|
+
modifiedActivity,
|
|
2116
2199
|
contentWidth
|
|
2117
2200
|
);
|
|
2118
2201
|
const padding = Math.max(0, contentWidth - displayWidth);
|
|
@@ -2131,6 +2214,60 @@ function ClaudePanel({
|
|
|
2131
2214
|
clearEOL
|
|
2132
2215
|
] }, `activity-${i}`)
|
|
2133
2216
|
);
|
|
2217
|
+
if (activity.subActivities && activity.subActivities.length > 0) {
|
|
2218
|
+
const subPrefix = " \u2514 ";
|
|
2219
|
+
const subPrefixWidth = getDisplayWidth(subPrefix);
|
|
2220
|
+
for (let j = 0; j < activity.subActivities.length; j++) {
|
|
2221
|
+
const sub = activity.subActivities[j];
|
|
2222
|
+
const subStyle = getActivityStyle(sub);
|
|
2223
|
+
const subIcon = sub.icon;
|
|
2224
|
+
const subIconWidth = getDisplayWidth(subIcon);
|
|
2225
|
+
const subLabel = sub.label;
|
|
2226
|
+
const subDetail = sub.detail;
|
|
2227
|
+
const subContentPrefixWidth = subPrefixWidth + subIconWidth + 1;
|
|
2228
|
+
const availableWidth = contentWidth - subContentPrefixWidth;
|
|
2229
|
+
let subLabelContent;
|
|
2230
|
+
let subDisplayWidth;
|
|
2231
|
+
if (subDetail) {
|
|
2232
|
+
const labelPart = `${subLabel}: `;
|
|
2233
|
+
const detailAvailable = availableWidth - labelPart.length;
|
|
2234
|
+
let truncatedDetail = subDetail;
|
|
2235
|
+
if (getDisplayWidth(subDetail) > detailAvailable) {
|
|
2236
|
+
truncatedDetail = "";
|
|
2237
|
+
let currentWidth = 0;
|
|
2238
|
+
for (const char of subDetail) {
|
|
2239
|
+
const charWidth = getDisplayWidth(char);
|
|
2240
|
+
if (currentWidth + charWidth > detailAvailable - 3) {
|
|
2241
|
+
truncatedDetail += "...";
|
|
2242
|
+
currentWidth += 3;
|
|
2243
|
+
break;
|
|
2244
|
+
}
|
|
2245
|
+
truncatedDetail += char;
|
|
2246
|
+
currentWidth += charWidth;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
subLabelContent = labelPart + truncatedDetail;
|
|
2250
|
+
subDisplayWidth = subContentPrefixWidth + labelPart.length + getDisplayWidth(truncatedDetail);
|
|
2251
|
+
} else {
|
|
2252
|
+
subLabelContent = subLabel;
|
|
2253
|
+
subDisplayWidth = subContentPrefixWidth + subLabel.length;
|
|
2254
|
+
}
|
|
2255
|
+
const subPadding = Math.max(0, contentWidth - subDisplayWidth);
|
|
2256
|
+
lines.push(
|
|
2257
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2258
|
+
BOX.v,
|
|
2259
|
+
" ",
|
|
2260
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: subPrefix }),
|
|
2261
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: subIcon }),
|
|
2262
|
+
" ",
|
|
2263
|
+
/* @__PURE__ */ jsx(Text, { color: subStyle.color, dimColor: subStyle.dimColor, children: subLabelContent }),
|
|
2264
|
+
" ".repeat(subPadding),
|
|
2265
|
+
BOX.v,
|
|
2266
|
+
clearEOL
|
|
2267
|
+
] }, `activity-${i}-sub-${j}`)
|
|
2268
|
+
);
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2134
2271
|
}
|
|
2135
2272
|
const hasTodos = state.todos && state.todos.length > 0;
|
|
2136
2273
|
const allCompleted = hasTodos && state.todos?.every((t) => t.status === "completed");
|
package/package.json
CHANGED