agenthud 0.5.0 → 0.5.2

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.
Files changed (2) hide show
  1. package/dist/index.js +65 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7,13 +7,16 @@ import { existsSync } from "fs";
7
7
 
8
8
  // src/ui/App.tsx
9
9
  import React, { useState, useEffect, useCallback, useMemo } from "react";
10
- import { Box as Box7, Text as Text7, useApp, useInput } from "ink";
10
+ import { Box as Box7, Text as Text7, useApp, useInput, useStdout } from "ink";
11
11
 
12
12
  // src/ui/GitPanel.tsx
13
13
  import { Box, Text } from "ink";
14
14
 
15
15
  // src/ui/constants.ts
16
16
  var DEFAULT_PANEL_WIDTH = 70;
17
+ var MIN_TERMINAL_WIDTH = 50;
18
+ var MAX_TERMINAL_WIDTH = 120;
19
+ var DEFAULT_FALLBACK_WIDTH = 80;
17
20
  var CONTENT_WIDTH = DEFAULT_PANEL_WIDTH - 4;
18
21
  var INNER_WIDTH = DEFAULT_PANEL_WIDTH - 2;
19
22
  function getContentWidth(panelWidth) {
@@ -447,6 +450,21 @@ function ProjectPanel({
447
450
  // src/ui/ClaudePanel.tsx
448
451
  import { Box as Box4, Text as Text4 } from "ink";
449
452
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
453
+ function getActivityStyle(activity) {
454
+ if (activity.type === "user") {
455
+ return { color: "white", dimColor: false };
456
+ }
457
+ if (activity.type === "response") {
458
+ return { color: "green", dimColor: false };
459
+ }
460
+ if (activity.type === "tool") {
461
+ if (activity.label === "Bash") {
462
+ return { color: "gray", dimColor: false };
463
+ }
464
+ return { dimColor: true };
465
+ }
466
+ return { dimColor: true };
467
+ }
450
468
  function formatCountdown3(seconds) {
451
469
  if (seconds == null) return "";
452
470
  const padded = String(seconds).padStart(2, " ");
@@ -471,19 +489,20 @@ function formatActivityTime(date) {
471
489
  const seconds = String(date.getSeconds()).padStart(2, "0");
472
490
  return `${hours}:${minutes}:${seconds}`;
473
491
  }
474
- function formatActivityLine(activity, maxWidth) {
492
+ function formatActivityParts(activity, maxWidth) {
475
493
  const time = formatActivityTime(activity.timestamp);
476
494
  const icon = activity.icon;
477
495
  const label = activity.label;
478
496
  const detail = activity.detail;
479
- const fixedPrefix = `[${time}] `;
480
- const fixedPrefixWidth = fixedPrefix.length;
481
- const iconWidth = 2;
497
+ const timestamp = `[${time}] `;
498
+ const timestampWidth = timestamp.length;
499
+ const iconWidth = getDisplayWidth(icon);
482
500
  const labelWidth = label.length;
483
501
  const separatorWidth = detail ? 2 : 0;
484
- const prefixDisplayWidth = fixedPrefixWidth + iconWidth + 1 + labelWidth + separatorWidth;
502
+ const contentPrefixWidth = iconWidth + 1 + labelWidth + separatorWidth;
503
+ const totalPrefixWidth = timestampWidth + contentPrefixWidth;
485
504
  if (detail) {
486
- const availableWidth = maxWidth - prefixDisplayWidth;
505
+ const availableWidth = maxWidth - totalPrefixWidth;
487
506
  let truncatedDetail = detail;
488
507
  let detailDisplayWidth = getDisplayWidth(detail);
489
508
  if (detailDisplayWidth > availableWidth) {
@@ -501,13 +520,13 @@ function formatActivityLine(activity, maxWidth) {
501
520
  }
502
521
  detailDisplayWidth = currentWidth;
503
522
  }
504
- const text2 = `${fixedPrefix}${icon} ${label}: ${truncatedDetail}`;
505
- const displayWidth2 = prefixDisplayWidth + detailDisplayWidth;
506
- return { text: text2, displayWidth: displayWidth2 };
523
+ const content2 = `${icon} ${label}: ${truncatedDetail}`;
524
+ const displayWidth2 = totalPrefixWidth + detailDisplayWidth;
525
+ return { timestamp, content: content2, displayWidth: displayWidth2 };
507
526
  }
508
- const text = `${fixedPrefix}${icon} ${label}`;
509
- const displayWidth = prefixDisplayWidth;
510
- return { text, displayWidth };
527
+ const content = `${icon} ${label}`;
528
+ const displayWidth = totalPrefixWidth;
529
+ return { timestamp, content, displayWidth };
511
530
  }
512
531
  function ClaudePanel({
513
532
  data,
@@ -569,13 +588,15 @@ function ClaudePanel({
569
588
  const lines = [];
570
589
  for (let i = 0; i < state.activities.length; i++) {
571
590
  const activity = state.activities[i];
572
- const { text: lineText, displayWidth } = formatActivityLine(activity, contentWidth);
591
+ const { timestamp, content, displayWidth } = formatActivityParts(activity, contentWidth);
573
592
  const padding = Math.max(0, contentWidth - displayWidth);
593
+ const style = getActivityStyle(activity);
574
594
  lines.push(
575
595
  /* @__PURE__ */ jsxs4(Text4, { children: [
576
596
  BOX.v,
577
597
  " ",
578
- lineText,
598
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: timestamp }),
599
+ /* @__PURE__ */ jsx4(Text4, { color: style.color, dimColor: style.dimColor, children: content }),
579
600
  " ".repeat(padding),
580
601
  BOX.v
581
602
  ] }, `activity-${i}`)
@@ -2073,9 +2094,32 @@ function formatRelativeTime2(timestamp) {
2073
2094
  function WelcomeApp() {
2074
2095
  return /* @__PURE__ */ jsx7(WelcomePanel, {});
2075
2096
  }
2097
+ function getClampedWidth(columns) {
2098
+ if (!columns || columns <= 0) {
2099
+ return DEFAULT_FALLBACK_WIDTH;
2100
+ }
2101
+ return Math.min(Math.max(columns, MIN_TERMINAL_WIDTH), MAX_TERMINAL_WIDTH);
2102
+ }
2076
2103
  function DashboardApp({ mode }) {
2077
2104
  const { exit } = useApp();
2105
+ const { stdout } = useStdout();
2078
2106
  const { config, warnings } = useMemo(() => parseConfig(), []);
2107
+ const [width, setWidth] = useState(() => getClampedWidth(stdout?.columns));
2108
+ useEffect(() => {
2109
+ const newWidth = getClampedWidth(stdout?.columns);
2110
+ if (newWidth !== width) {
2111
+ setWidth(newWidth);
2112
+ }
2113
+ }, [stdout?.columns, width]);
2114
+ useEffect(() => {
2115
+ const handleResize = () => {
2116
+ setWidth(getClampedWidth(stdout?.columns));
2117
+ };
2118
+ stdout?.on("resize", handleResize);
2119
+ return () => {
2120
+ stdout?.off("resize", handleResize);
2121
+ };
2122
+ }, [stdout]);
2079
2123
  const projectIntervalSeconds = config.panels.project.interval ? config.panels.project.interval / 1e3 : null;
2080
2124
  const gitIntervalSeconds = config.panels.git.interval ? config.panels.git.interval / 1e3 : null;
2081
2125
  const claudeIntervalSeconds = config.panels.claude.interval ? config.panels.claude.interval / 1e3 : null;
@@ -2380,7 +2424,7 @@ function DashboardApp({ mode }) {
2380
2424
  {
2381
2425
  data: projectData,
2382
2426
  countdown: mode === "watch" ? countdowns.project : null,
2383
- width: config.width,
2427
+ width,
2384
2428
  justRefreshed: projectVisual.justRefreshed
2385
2429
  }
2386
2430
  ) }, `panel-project-${index}`);
@@ -2395,7 +2439,7 @@ function DashboardApp({ mode }) {
2395
2439
  stats: gitData.stats,
2396
2440
  uncommitted: gitData.uncommitted,
2397
2441
  countdown: mode === "watch" ? countdowns.git : null,
2398
- width: config.width,
2442
+ width,
2399
2443
  isRunning: gitVisual.isRunning,
2400
2444
  justRefreshed: gitVisual.justRefreshed
2401
2445
  }
@@ -2410,7 +2454,7 @@ function DashboardApp({ mode }) {
2410
2454
  isOutdated: testData.isOutdated,
2411
2455
  commitsBehind: testData.commitsBehind,
2412
2456
  error: testData.error,
2413
- width: config.width,
2457
+ width,
2414
2458
  isRunning: testsVisual.isRunning,
2415
2459
  justCompleted: testsVisual.justCompleted
2416
2460
  }
@@ -2423,7 +2467,7 @@ function DashboardApp({ mode }) {
2423
2467
  {
2424
2468
  data: claudeData,
2425
2469
  countdown: mode === "watch" ? countdowns.claude : null,
2426
- width: config.width,
2470
+ width,
2427
2471
  justRefreshed: claudeVisual.justRefreshed
2428
2472
  }
2429
2473
  ) }, `panel-claude-${index}`);
@@ -2444,7 +2488,7 @@ function DashboardApp({ mode }) {
2444
2488
  countdown,
2445
2489
  relativeTime,
2446
2490
  error: result.error,
2447
- width: config.width,
2491
+ width,
2448
2492
  isRunning: customVisual.isRunning,
2449
2493
  justRefreshed: customVisual.justRefreshed
2450
2494
  }
@@ -2452,7 +2496,7 @@ function DashboardApp({ mode }) {
2452
2496
  }
2453
2497
  return null;
2454
2498
  }),
2455
- mode === "watch" && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, width: config.width, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: statusBarItems.map((item, index) => /* @__PURE__ */ jsxs7(React.Fragment, { children: [
2499
+ mode === "watch" && /* @__PURE__ */ jsx7(Box7, { marginTop: 1, width, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: statusBarItems.map((item, index) => /* @__PURE__ */ jsxs7(React.Fragment, { children: [
2456
2500
  index > 0 && " \xB7 ",
2457
2501
  /* @__PURE__ */ jsxs7(Text7, { color: "cyan", children: [
2458
2502
  item.split(":")[0],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agenthud",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "CLI tool to monitor agent status in real-time. Works with Claude Code, multi-agent workflows, and any AI agent system.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",