codingbuddy 4.4.0 → 4.5.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.
Files changed (79) hide show
  1. package/dist/src/agent/agent.service.d.ts +2 -0
  2. package/dist/src/agent/agent.service.js +45 -0
  3. package/dist/src/agent/agent.service.js.map +1 -1
  4. package/dist/src/agent/agent.types.d.ts +13 -0
  5. package/dist/src/agent/agent.types.js.map +1 -1
  6. package/dist/src/keyword/keyword.service.js +7 -0
  7. package/dist/src/keyword/keyword.service.js.map +1 -1
  8. package/dist/src/keyword/keyword.types.d.ts +2 -0
  9. package/dist/src/keyword/taskmaestro-detector.d.ts +1 -0
  10. package/dist/src/keyword/taskmaestro-detector.js +16 -0
  11. package/dist/src/keyword/taskmaestro-detector.js.map +1 -0
  12. package/dist/src/mcp/handlers/agent.handler.js +7 -0
  13. package/dist/src/mcp/handlers/agent.handler.js.map +1 -1
  14. package/dist/src/mcp/sse-auth.guard.js +4 -6
  15. package/dist/src/mcp/sse-auth.guard.js.map +1 -1
  16. package/dist/src/shared/version.d.ts +1 -1
  17. package/dist/src/shared/version.js +1 -1
  18. package/dist/src/tui/components/FlowMap.d.ts +3 -1
  19. package/dist/src/tui/components/FlowMap.js +30 -3
  20. package/dist/src/tui/components/FlowMap.js.map +1 -1
  21. package/dist/src/tui/components/FlowMap.spec.js +88 -0
  22. package/dist/src/tui/components/FlowMap.spec.js.map +1 -1
  23. package/dist/src/tui/components/FocusedAgentPanel.d.ts +3 -1
  24. package/dist/src/tui/components/FocusedAgentPanel.js +8 -3
  25. package/dist/src/tui/components/FocusedAgentPanel.js.map +1 -1
  26. package/dist/src/tui/components/FocusedAgentPanel.spec.js +76 -0
  27. package/dist/src/tui/components/FocusedAgentPanel.spec.js.map +1 -1
  28. package/dist/src/tui/components/HeaderBar.d.ts +3 -1
  29. package/dist/src/tui/components/HeaderBar.js +12 -6
  30. package/dist/src/tui/components/HeaderBar.js.map +1 -1
  31. package/dist/src/tui/components/HeaderBar.spec.js +31 -13
  32. package/dist/src/tui/components/HeaderBar.spec.js.map +1 -1
  33. package/dist/src/tui/components/StageHealthBar.d.ts +5 -1
  34. package/dist/src/tui/components/StageHealthBar.js +6 -1
  35. package/dist/src/tui/components/StageHealthBar.js.map +1 -1
  36. package/dist/src/tui/components/StageHealthBar.spec.js +22 -0
  37. package/dist/src/tui/components/StageHealthBar.spec.js.map +1 -1
  38. package/dist/src/tui/components/focused-agent.pure.d.ts +1 -0
  39. package/dist/src/tui/components/focused-agent.pure.js +11 -0
  40. package/dist/src/tui/components/focused-agent.pure.js.map +1 -1
  41. package/dist/src/tui/components/index.d.ts +3 -1
  42. package/dist/src/tui/components/index.js +10 -1
  43. package/dist/src/tui/components/index.js.map +1 -1
  44. package/dist/src/tui/components/live.pure.d.ts +9 -0
  45. package/dist/src/tui/components/live.pure.js +70 -0
  46. package/dist/src/tui/components/live.pure.js.map +1 -0
  47. package/dist/src/tui/dashboard-app.js +9 -6
  48. package/dist/src/tui/dashboard-app.js.map +1 -1
  49. package/dist/src/tui/dashboard-app.spec.js +14 -0
  50. package/dist/src/tui/dashboard-app.spec.js.map +1 -1
  51. package/dist/src/tui/dashboard-types.d.ts +6 -0
  52. package/dist/src/tui/dashboard-types.js.map +1 -1
  53. package/dist/src/tui/eventbus-ui.integration.spec.js +3 -0
  54. package/dist/src/tui/eventbus-ui.integration.spec.js.map +1 -1
  55. package/dist/src/tui/hooks/index.d.ts +1 -1
  56. package/dist/src/tui/hooks/index.js +3 -3
  57. package/dist/src/tui/hooks/index.js.map +1 -1
  58. package/dist/src/tui/hooks/use-dashboard-state.js +16 -0
  59. package/dist/src/tui/hooks/use-dashboard-state.js.map +1 -1
  60. package/dist/src/tui/hooks/use-tick.d.ts +1 -0
  61. package/dist/src/tui/hooks/use-tick.js +15 -0
  62. package/dist/src/tui/hooks/use-tick.js.map +1 -0
  63. package/dist/src/tui/hooks/use-tick.spec.js +70 -0
  64. package/dist/src/tui/hooks/use-tick.spec.js.map +1 -0
  65. package/dist/src/tui/index.d.ts +1 -1
  66. package/dist/src/tui/index.js +2 -2
  67. package/dist/src/tui/index.js.map +1 -1
  68. package/dist/src/tui-bundle.mjs +175 -51
  69. package/dist/tsconfig.build.tsbuildinfo +1 -1
  70. package/package.json +4 -3
  71. package/dist/src/tui/components/header-bar.pure.d.ts +0 -1
  72. package/dist/src/tui/components/header-bar.pure.js +0 -9
  73. package/dist/src/tui/components/header-bar.pure.js.map +0 -1
  74. package/dist/src/tui/hooks/use-clock.d.ts +0 -1
  75. package/dist/src/tui/hooks/use-clock.js +0 -16
  76. package/dist/src/tui/hooks/use-clock.js.map +0 -1
  77. package/dist/src/tui/hooks/use-clock.spec.js +0 -43
  78. package/dist/src/tui/hooks/use-clock.spec.js.map +0 -1
  79. /package/dist/src/tui/hooks/{use-clock.spec.d.ts → use-tick.spec.d.ts} +0 -0
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const react_1 = require("react");
4
+ const vitest_1 = require("vitest");
5
+ const ink_testing_library_1 = require("ink-testing-library");
6
+ const ink_1 = require("ink");
7
+ const use_tick_1 = require("./use-tick");
8
+ function TestComponent({ intervalMs }) {
9
+ const tick = (0, use_tick_1.useTick)(intervalMs);
10
+ return react_1.default.createElement(ink_1.Text, null, String(tick));
11
+ }
12
+ (0, vitest_1.describe)('tui/hooks/useTick', () => {
13
+ (0, vitest_1.beforeEach)(() => {
14
+ vitest_1.vi.useFakeTimers();
15
+ });
16
+ (0, vitest_1.afterEach)(() => {
17
+ vitest_1.vi.useRealTimers();
18
+ });
19
+ (0, vitest_1.it)('should start at 0', () => {
20
+ const { lastFrame } = (0, ink_testing_library_1.render)(react_1.default.createElement(TestComponent, null));
21
+ (0, vitest_1.expect)(lastFrame()).toBe('0');
22
+ });
23
+ (0, vitest_1.it)('should increment after default interval (1000ms)', () => {
24
+ const { lastFrame } = (0, ink_testing_library_1.render)(react_1.default.createElement(TestComponent, null));
25
+ (0, vitest_1.expect)(lastFrame()).toBe('0');
26
+ (0, react_1.act)(() => {
27
+ vitest_1.vi.advanceTimersByTime(1000);
28
+ });
29
+ (0, vitest_1.expect)(lastFrame()).toBe('1');
30
+ (0, react_1.act)(() => {
31
+ vitest_1.vi.advanceTimersByTime(1000);
32
+ });
33
+ (0, vitest_1.expect)(lastFrame()).toBe('2');
34
+ });
35
+ (0, vitest_1.it)('should support custom interval', () => {
36
+ const { lastFrame } = (0, ink_testing_library_1.render)(react_1.default.createElement(TestComponent, { intervalMs: 500 }));
37
+ (0, vitest_1.expect)(lastFrame()).toBe('0');
38
+ (0, react_1.act)(() => {
39
+ vitest_1.vi.advanceTimersByTime(500);
40
+ });
41
+ (0, vitest_1.expect)(lastFrame()).toBe('1');
42
+ (0, react_1.act)(() => {
43
+ vitest_1.vi.advanceTimersByTime(500);
44
+ });
45
+ (0, vitest_1.expect)(lastFrame()).toBe('2');
46
+ });
47
+ (0, vitest_1.it)('should reset interval when intervalMs prop changes', () => {
48
+ const clearIntervalSpy = vitest_1.vi.spyOn(global, 'clearInterval');
49
+ const { lastFrame, rerender } = (0, ink_testing_library_1.render)(react_1.default.createElement(TestComponent, { intervalMs: 1000 }));
50
+ (0, react_1.act)(() => {
51
+ vitest_1.vi.advanceTimersByTime(1000);
52
+ });
53
+ (0, vitest_1.expect)(lastFrame()).toBe('1');
54
+ rerender(react_1.default.createElement(TestComponent, { intervalMs: 500 }));
55
+ (0, vitest_1.expect)(clearIntervalSpy).toHaveBeenCalled();
56
+ (0, react_1.act)(() => {
57
+ vitest_1.vi.advanceTimersByTime(500);
58
+ });
59
+ (0, vitest_1.expect)(lastFrame()).toBe('2');
60
+ clearIntervalSpy.mockRestore();
61
+ });
62
+ (0, vitest_1.it)('should cleanup interval on unmount', () => {
63
+ const clearIntervalSpy = vitest_1.vi.spyOn(global, 'clearInterval');
64
+ const { unmount } = (0, ink_testing_library_1.render)(react_1.default.createElement(TestComponent, null));
65
+ unmount();
66
+ (0, vitest_1.expect)(clearIntervalSpy).toHaveBeenCalled();
67
+ clearIntervalSpy.mockRestore();
68
+ });
69
+ });
70
+ //# sourceMappingURL=use-tick.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-tick.spec.js","sourceRoot":"","sources":["../../../../src/tui/hooks/use-tick.spec.tsx"],"names":[],"mappings":"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"}
@@ -17,4 +17,4 @@ export * from './types';
17
17
  export * from './dashboard-types';
18
18
  export { useDashboardState } from './hooks';
19
19
  export { useTerminalSize } from './hooks';
20
- export { useClock } from './hooks';
20
+ export { useTick } from './hooks';
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.useClock = exports.useTerminalSize = exports.useDashboardState = exports.MultiSessionApp = exports.DashboardApp = void 0;
17
+ exports.useTick = exports.useTerminalSize = exports.useDashboardState = exports.MultiSessionApp = exports.DashboardApp = void 0;
18
18
  exports.startTui = startTui;
19
19
  exports.renderMultiSession = renderMultiSession;
20
20
  const react_1 = require("react");
@@ -39,5 +39,5 @@ Object.defineProperty(exports, "useDashboardState", { enumerable: true, get: fun
39
39
  var hooks_2 = require("./hooks");
40
40
  Object.defineProperty(exports, "useTerminalSize", { enumerable: true, get: function () { return hooks_2.useTerminalSize; } });
41
41
  var hooks_3 = require("./hooks");
42
- Object.defineProperty(exports, "useClock", { enumerable: true, get: function () { return hooks_3.useClock; } });
42
+ Object.defineProperty(exports, "useTick", { enumerable: true, get: function () { return hooks_3.useTick; } });
43
43
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tui/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAiBA,4BAGC;AAMD,gDAEC;AA5BD,iCAA0B;AAC1B,6BAA6B;AAE7B,mDAA+C;AAC/C,2DAAsD;AAatD,SAAgB,QAAQ,CAAC,OAAwB;IAC/C,MAAM,aAAa,GAAkB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,OAAO,IAAA,YAAM,EAAC,8BAAC,4BAAY,IAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAI,EAAE,aAAa,CAAC,CAAC;AAC7E,CAAC;AAMD,SAAgB,kBAAkB,CAAC,OAAyC;IAC1E,OAAO,IAAA,YAAM,EAAC,8BAAC,mCAAe,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAI,CAAC,CAAC;AAC/D,CAAC;AAED,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAErB,yDAAsD;AAA7C,oHAAA,eAAe,OAAA;AAExB,0CAAwB;AACxB,oDAAkC;AAClC,iCAA4C;AAAnC,0GAAA,iBAAiB,OAAA;AAC1B,iCAA0C;AAAjC,wGAAA,eAAe,OAAA;AACxB,iCAAmC;AAA1B,iGAAA,QAAQ,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tui/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAiBA,4BAGC;AAMD,gDAEC;AA5BD,iCAA0B;AAC1B,6BAA6B;AAE7B,mDAA+C;AAC/C,2DAAsD;AAatD,SAAgB,QAAQ,CAAC,OAAwB;IAC/C,MAAM,aAAa,GAAkB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,OAAO,IAAA,YAAM,EAAC,8BAAC,4BAAY,IAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAI,EAAE,aAAa,CAAC,CAAC;AAC7E,CAAC;AAMD,SAAgB,kBAAkB,CAAC,OAAyC;IAC1E,OAAO,IAAA,YAAM,EAAC,8BAAC,mCAAe,IAAC,OAAO,EAAE,OAAO,CAAC,OAAO,GAAI,CAAC,CAAC;AAC/D,CAAC;AAED,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAErB,yDAAsD;AAA7C,oHAAA,eAAe,OAAA;AAExB,0CAAwB;AACxB,oDAAkC;AAClC,iCAA4C;AAAnC,0GAAA,iBAAiB,OAAA;AAC1B,iCAA0C;AAAjC,wGAAA,eAAe,OAAA;AACxB,iCAAkC;AAAzB,gGAAA,OAAO,OAAA"}
@@ -1431,8 +1431,21 @@ function useTerminalSize() {
1431
1431
  return { ...size, layoutMode: getLayoutMode(size.columns) };
1432
1432
  }
1433
1433
 
1434
+ // src/tui/hooks/use-tick.ts
1435
+ import { useState as useState2, useEffect as useEffect2 } from "react";
1436
+ function useTick(intervalMs = 1e3) {
1437
+ const [tick, setTick] = useState2(0);
1438
+ useEffect2(() => {
1439
+ const id = setInterval(() => {
1440
+ setTick((prev) => prev + 1);
1441
+ }, intervalMs);
1442
+ return () => clearInterval(id);
1443
+ }, [intervalMs]);
1444
+ return tick;
1445
+ }
1446
+
1434
1447
  // src/tui/hooks/use-dashboard-state.ts
1435
- import { useReducer, useEffect as useEffect2 } from "react";
1448
+ import { useReducer, useEffect as useEffect3 } from "react";
1436
1449
 
1437
1450
  // src/tui/events/event-bus.ts
1438
1451
  var import_eventemitter2 = __toESM(require_eventemitter2());
@@ -3974,6 +3987,7 @@ function createInitialDashboardState() {
3974
3987
  tasks: [],
3975
3988
  eventLog: [],
3976
3989
  toolCalls: [],
3990
+ activityHistory: [],
3977
3991
  objectives: [],
3978
3992
  activeSkills: [],
3979
3993
  toolInvokeCount: 0,
@@ -4075,7 +4089,8 @@ function dashboardReducer(state, action) {
4075
4089
  const entry = {
4076
4090
  timestamp: new Date(action.payload.timestamp).toTimeString().slice(0, 8),
4077
4091
  message: `${action.payload.toolName}${action.payload.agentId ? ` [${action.payload.agentId}]` : ""}`,
4078
- level: "info"
4092
+ level: "info",
4093
+ rawTimestamp: action.payload.timestamp
4079
4094
  };
4080
4095
  const base = state.eventLog.length >= EVENT_LOG_MAX ? state.eventLog.slice(1) : state.eventLog;
4081
4096
  const invokedAgentId = action.payload.agentId;
@@ -4103,11 +4118,24 @@ function dashboardReducer(state, action) {
4103
4118
  status: "completed"
4104
4119
  };
4105
4120
  const toolCallsBase = state.toolCalls.length >= TOOL_CALLS_MAX ? state.toolCalls.slice(1) : state.toolCalls;
4121
+ const sec = Math.floor(action.payload.timestamp / 1e3);
4122
+ const history = state.activityHistory;
4123
+ const last = history.length > 0 ? history[history.length - 1] : null;
4124
+ let activityHistory;
4125
+ if (last && last.timestamp === sec) {
4126
+ activityHistory = [
4127
+ ...history.slice(0, -1),
4128
+ { timestamp: sec, toolCalls: last.toolCalls + 1 }
4129
+ ];
4130
+ } else {
4131
+ activityHistory = [...history.slice(-59), { timestamp: sec, toolCalls: 1 }];
4132
+ }
4106
4133
  return {
4107
4134
  ...state,
4108
4135
  agents,
4109
4136
  eventLog: [...base, entry],
4110
4137
  toolCalls: [...toolCallsBase, toolCall],
4138
+ activityHistory,
4111
4139
  toolInvokeCount: state.toolInvokeCount + 1
4112
4140
  };
4113
4141
  }
@@ -4181,7 +4209,7 @@ function dashboardReducer(state, action) {
4181
4209
  }
4182
4210
  function useDashboardState(eventBus) {
4183
4211
  const [state, dispatch] = useReducer(dashboardReducer, void 0, createInitialDashboardState);
4184
- useEffect2(() => {
4212
+ useEffect3(() => {
4185
4213
  if (!eventBus) return;
4186
4214
  const onActivated = (p) => dispatch({ type: "AGENT_ACTIVATED", payload: p });
4187
4215
  const onDeactivated = (p) => dispatch({ type: "AGENT_DEACTIVATED", payload: p });
@@ -4225,7 +4253,7 @@ function useDashboardState(eventBus) {
4225
4253
  eventBus.off(TUI_EVENTS.CONTEXT_UPDATED, onContextUpdated);
4226
4254
  };
4227
4255
  }, [eventBus]);
4228
- useEffect2(() => {
4256
+ useEffect3(() => {
4229
4257
  const cleanupInterval = setInterval(() => {
4230
4258
  dispatch({ type: "CLEANUP_STALE_AGENTS", payload: { now: Date.now(), ttlMs: 3e4 } });
4231
4259
  }, 1e4);
@@ -4348,6 +4376,59 @@ function getAgentAvatar(agentName) {
4348
4376
  return "\u{1F916}";
4349
4377
  }
4350
4378
 
4379
+ // src/tui/components/live.pure.ts
4380
+ function formatElapsed(startedAt, now) {
4381
+ const totalSec = Math.max(0, Math.floor((now - startedAt) / 1e3));
4382
+ const min = Math.floor(totalSec / 60);
4383
+ const sec = totalSec % 60;
4384
+ return min > 0 ? `${min}m ${sec}s` : `${sec}s`;
4385
+ }
4386
+ function formatRelativeTime(timestamp, now) {
4387
+ const diffSec = Math.max(0, Math.floor((now - timestamp) / 1e3));
4388
+ if (diffSec <= 2) return "just now";
4389
+ if (diffSec < 60) return `${diffSec}s ago`;
4390
+ const diffMin = Math.floor(diffSec / 60);
4391
+ if (diffMin < 60) return `${diffMin}m ago`;
4392
+ const diffHr = Math.floor(diffMin / 60);
4393
+ return `${diffHr}h ago`;
4394
+ }
4395
+ var SPINNER_FRAMES = "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827";
4396
+ function spinnerFrame(tick) {
4397
+ return SPINNER_FRAMES[tick % 8];
4398
+ }
4399
+ function pulseIcon(tick) {
4400
+ return tick % 2 === 0 ? "\u25CF" : "\u25C9";
4401
+ }
4402
+ var SPARK_CHARS = "\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
4403
+ function renderSparkline(samples, width) {
4404
+ if (samples.length === 0) return "";
4405
+ const visible = samples.slice(-width);
4406
+ const min = Math.min(...visible);
4407
+ const max = Math.max(...visible);
4408
+ const range = max - min;
4409
+ return visible.map((v) => {
4410
+ if (range === 0) return SPARK_CHARS[0];
4411
+ const idx = Math.round((v - min) / range * 7);
4412
+ return SPARK_CHARS[idx];
4413
+ }).join("");
4414
+ }
4415
+ function computeThroughput(samples) {
4416
+ if (samples.length <= 1) return "0.0/min";
4417
+ const first = samples[0];
4418
+ const last = samples[samples.length - 1];
4419
+ const durationMin = (last.timestamp - first.timestamp) / 60;
4420
+ if (durationMin <= 0) return "0.0/min";
4421
+ const totalCalls = samples.reduce((sum, s) => sum + s.toolCalls, 0);
4422
+ return `${(totalCalls / durationMin).toFixed(1)}/min`;
4423
+ }
4424
+ function formatTimeWithSeconds(now) {
4425
+ const d = new Date(now);
4426
+ const h = String(d.getHours()).padStart(2, "0");
4427
+ const m = String(d.getMinutes()).padStart(2, "0");
4428
+ const s = String(d.getSeconds()).padStart(2, "0");
4429
+ return `${h}:${m}:${s}`;
4430
+ }
4431
+
4351
4432
  // src/tui/components/HeaderBar.tsx
4352
4433
  var PROCESS_MODES = ["PLAN", "ACT", "EVAL"];
4353
4434
  function ModeFlow({ currentMode }) {
@@ -4358,17 +4439,23 @@ function ModeFlow({ currentMode }) {
4358
4439
  return /* @__PURE__ */ React.createElement(React.Fragment, { key: mode }, i > 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " \u2192 "), isActive ? /* @__PURE__ */ React.createElement(Text, { color, bold: true }, "[", mode, "]") : /* @__PURE__ */ React.createElement(Text, { dimColor: true }, mode));
4359
4440
  }));
4360
4441
  }
4361
- function StateIndicator({ globalState }) {
4362
- const icon = GLOBAL_STATE_ICONS[globalState];
4442
+ function StateIndicator({
4443
+ globalState,
4444
+ tick
4445
+ }) {
4446
+ const isRunning = globalState === "RUNNING";
4447
+ const icon = isRunning && tick !== void 0 ? spinnerFrame(tick) : GLOBAL_STATE_ICONS[globalState];
4363
4448
  const color = GLOBAL_STATE_COLORS[globalState];
4364
- return /* @__PURE__ */ React.createElement(Text, { color, bold: globalState === "RUNNING" || globalState === "ERROR" }, icon, " ", globalState);
4449
+ return /* @__PURE__ */ React.createElement(Text, { color, bold: isRunning || globalState === "ERROR" }, icon, " ", globalState);
4365
4450
  }
4366
4451
  function HeaderBar({
4367
4452
  workspace,
4368
4453
  currentMode,
4369
4454
  globalState,
4370
4455
  layoutMode,
4371
- width
4456
+ width,
4457
+ tick,
4458
+ now
4372
4459
  }) {
4373
4460
  if (layoutMode === "narrow") {
4374
4461
  return /* @__PURE__ */ React.createElement(
@@ -4384,7 +4471,8 @@ function HeaderBar({
4384
4471
  /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
4385
4472
  /* @__PURE__ */ React.createElement(ModeFlow, { currentMode }),
4386
4473
  /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
4387
- /* @__PURE__ */ React.createElement(StateIndicator, { globalState })
4474
+ /* @__PURE__ */ React.createElement(StateIndicator, { globalState, tick }),
4475
+ now !== void 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " ", formatTimeWithSeconds(now))
4388
4476
  );
4389
4477
  }
4390
4478
  return /* @__PURE__ */ React.createElement(
@@ -4396,7 +4484,7 @@ function HeaderBar({
4396
4484
  overflowX: "hidden",
4397
4485
  flexDirection: "row"
4398
4486
  },
4399
- /* @__PURE__ */ React.createElement(Box, { gap: 2, flexShrink: 1, minWidth: 0 }, /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, "\u27E8\u27E9 CODINGBUDDY AGENT DASHBOARD"), /* @__PURE__ */ React.createElement(ModeFlow, { currentMode }), /* @__PURE__ */ React.createElement(StateIndicator, { globalState })),
4487
+ /* @__PURE__ */ React.createElement(Box, { gap: 2, flexShrink: 1, minWidth: 0 }, /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, "\u27E8\u27E9 CODINGBUDDY AGENT DASHBOARD"), /* @__PURE__ */ React.createElement(ModeFlow, { currentMode }), /* @__PURE__ */ React.createElement(StateIndicator, { globalState, tick }), now !== void 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, formatTimeWithSeconds(now))),
4400
4488
  /* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
4401
4489
  /* @__PURE__ */ React.createElement(Box, { flexShrink: 1, overflowX: "hidden" }, /* @__PURE__ */ React.createElement(Text, { dimColor: true, wrap: "truncate" }, workspace))
4402
4490
  );
@@ -4915,10 +5003,18 @@ function FlowMap({
4915
5003
  layoutMode,
4916
5004
  width,
4917
5005
  height,
4918
- activeStage = null
5006
+ activeStage = null,
5007
+ tick,
5008
+ now
4919
5009
  }) {
4920
5010
  const contentWidth = Math.max(1, width - 2);
4921
5011
  const contentHeight = Math.max(1, height - 3);
5012
+ const hasRunningAgents = useMemo(
5013
+ () => [...agents.values()].some((a) => a.status === "running"),
5014
+ [agents]
5015
+ );
5016
+ const liveTick = hasRunningAgents ? tick ?? 0 : 0;
5017
+ const liveNow = hasRunningAgents ? now : void 0;
4922
5018
  const compactContent = useMemo(() => {
4923
5019
  if (layoutMode !== "narrow") return null;
4924
5020
  return renderFlowMapCompact(agents);
@@ -4928,6 +5024,20 @@ function FlowMap({
4928
5024
  const buf = layoutMode === "wide" ? renderFlowMap(agents, edges, contentWidth, contentHeight, activeStage) : renderFlowMapSimplified(agents, contentWidth, contentHeight);
4929
5025
  return buf.toLinesDirect();
4930
5026
  }, [agents, edges, contentWidth, contentHeight, layoutMode, activeStage]);
5027
+ const liveOverlays = useMemo(() => {
5028
+ if (liveNow === void 0) return null;
5029
+ const overlays = [];
5030
+ for (const [id, agent] of agents) {
5031
+ if (agent.status === "running" && agent.startedAt != null) {
5032
+ overlays.push({
5033
+ id,
5034
+ icon: pulseIcon(liveTick),
5035
+ elapsed: formatElapsed(agent.startedAt, liveNow)
5036
+ });
5037
+ }
5038
+ }
5039
+ return overlays.length > 0 ? overlays : null;
5040
+ }, [agents, liveTick, liveNow]);
4931
5041
  if (layoutMode === "narrow") {
4932
5042
  return /* @__PURE__ */ React2.createElement(
4933
5043
  Box2,
@@ -4939,7 +5049,8 @@ function FlowMap({
4939
5049
  height
4940
5050
  },
4941
5051
  /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "FLOW MAP"),
4942
- /* @__PURE__ */ React2.createElement(Text2, null, compactContent)
5052
+ /* @__PURE__ */ React2.createElement(Text2, null, compactContent),
5053
+ liveOverlays?.map((o) => /* @__PURE__ */ React2.createElement(Text2, { key: o.id, color: "yellow" }, o.icon, " ", o.elapsed))
4943
5054
  );
4944
5055
  }
4945
5056
  if (!lines) {
@@ -4965,7 +5076,8 @@ function FlowMap({
4965
5076
  height
4966
5077
  },
4967
5078
  /* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "FLOW MAP"),
4968
- lines.map((row, y) => /* @__PURE__ */ React2.createElement(ColorRow, { key: y, cells: row }))
5079
+ lines.map((row, y) => /* @__PURE__ */ React2.createElement(ColorRow, { key: y, cells: row })),
5080
+ liveOverlays?.map((o) => /* @__PURE__ */ React2.createElement(Text2, { key: o.id, color: "yellow" }, o.icon, " ", o.elapsed))
4969
5081
  );
4970
5082
  }
4971
5083
 
@@ -4985,6 +5097,13 @@ function formatLogTail(events, maxLines = 10) {
4985
5097
  const tail = events.slice(-maxLines);
4986
5098
  return tail.map((e) => `${e.timestamp} ${e.message}`).join("\n");
4987
5099
  }
5100
+ function formatLogTailRelative(events, now, maxLines = 10) {
5101
+ const tail = events.slice(-maxLines);
5102
+ return tail.map((e) => {
5103
+ const ts = e.rawTimestamp != null ? formatRelativeTime(e.rawTimestamp, now) : e.timestamp;
5104
+ return `${ts} ${e.message}`;
5105
+ }).join("\n");
5106
+ }
4988
5107
  function formatSectionDivider(title, width = 50) {
4989
5108
  const prefix = "\u2500\u2500\u2500 ";
4990
5109
  const suffix = " ";
@@ -5071,6 +5190,8 @@ function FocusedAgentPanel({
5071
5190
  eventLog,
5072
5191
  contextDecisions = [],
5073
5192
  contextNotes = [],
5193
+ tick,
5194
+ now,
5074
5195
  width,
5075
5196
  height
5076
5197
  }) {
@@ -5093,7 +5214,10 @@ function FocusedAgentPanel({
5093
5214
  const statusLabel = agent.status.toUpperCase();
5094
5215
  const progressBar = formatEnhancedProgressBar(agent.progress);
5095
5216
  const objective = formatObjective(objectives);
5096
- const logs = formatLogTail(eventLog);
5217
+ const logs = now != null ? formatLogTailRelative(eventLog, now) : formatLogTail(eventLog);
5218
+ const isRunning = agent.status === "running";
5219
+ const showSpinner = isRunning && tick != null;
5220
+ const showElapsed = isRunning && now != null && agent.startedAt != null;
5097
5221
  return /* @__PURE__ */ React4.createElement(
5098
5222
  Box4,
5099
5223
  {
@@ -5103,7 +5227,7 @@ function FocusedAgentPanel({
5103
5227
  width,
5104
5228
  height
5105
5229
  },
5106
- /* @__PURE__ */ React4.createElement(Box4, { gap: 2 }, /* @__PURE__ */ React4.createElement(Text4, null, avatar), /* @__PURE__ */ React4.createElement(Text4, { bold: true }, agent.name), /* @__PURE__ */ React4.createElement(Text4, { color: statusColor, bold: true }, icon), /* @__PURE__ */ React4.createElement(Text4, { color: statusColor }, statusLabel), /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, agent.stage)),
5230
+ /* @__PURE__ */ React4.createElement(Box4, { gap: 2 }, /* @__PURE__ */ React4.createElement(Text4, null, avatar), /* @__PURE__ */ React4.createElement(Text4, { bold: true }, agent.name), showSpinner ? /* @__PURE__ */ React4.createElement(Text4, { color: "cyan" }, spinnerFrame(tick)) : /* @__PURE__ */ React4.createElement(Text4, { color: statusColor, bold: true }, icon), /* @__PURE__ */ React4.createElement(Text4, { color: statusColor }, statusLabel), showElapsed && /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, formatElapsed(agent.startedAt, now)), /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, agent.stage)),
5107
5231
  /* @__PURE__ */ React4.createElement(Box4, { gap: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "magenta" }, progressBar.bar), /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, progressBar.label)),
5108
5232
  /* @__PURE__ */ React4.createElement(SectionDivider, { title: "Objective" }),
5109
5233
  objective ? /* @__PURE__ */ React4.createElement(Text4, null, objective) : /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "No objectives"),
@@ -5263,8 +5387,12 @@ function StageHealthBar({
5263
5387
  toolCount,
5264
5388
  agentCount,
5265
5389
  skillCount,
5266
- width
5390
+ width,
5391
+ activityHistory,
5392
+ tick: _tick,
5393
+ now: _now
5267
5394
  }) {
5395
+ const hasActivity = activityHistory && activityHistory.length > 0;
5268
5396
  return /* @__PURE__ */ React6.createElement(
5269
5397
  Box6,
5270
5398
  {
@@ -5273,7 +5401,10 @@ function StageHealthBar({
5273
5401
  width,
5274
5402
  flexDirection: "column"
5275
5403
  },
5276
- /* @__PURE__ */ React6.createElement(Box6, null, /* @__PURE__ */ React6.createElement(Box6, { gap: 2 }, ["PLAN", "ACT", "EVAL"].map((mode) => /* @__PURE__ */ React6.createElement(StageStatDisplay, { key: mode, mode, stats: stageHealth[mode] }))), /* @__PURE__ */ React6.createElement(Box6, { flexGrow: 1 }), /* @__PURE__ */ React6.createElement(Box6, { gap: 2 }, bottlenecks.length > 0 && /* @__PURE__ */ React6.createElement(Text6, { color: "red", bold: true }, "\u26A1 Bottlenecks: ", bottlenecks.join(" / ")), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u{1F916} ", formatCount(agentCount)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u2699 ", formatCount(skillCount)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u{1F527} ", formatCount(toolCount))))
5404
+ /* @__PURE__ */ React6.createElement(Box6, null, hasActivity && /* @__PURE__ */ React6.createElement(Box6, { gap: 1, marginRight: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, renderSparkline(
5405
+ activityHistory.map((s) => s.toolCalls),
5406
+ 10
5407
+ )), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, computeThroughput(activityHistory))), /* @__PURE__ */ React6.createElement(Box6, { gap: 2 }, ["PLAN", "ACT", "EVAL"].map((mode) => /* @__PURE__ */ React6.createElement(StageStatDisplay, { key: mode, mode, stats: stageHealth[mode] }))), /* @__PURE__ */ React6.createElement(Box6, { flexGrow: 1 }), /* @__PURE__ */ React6.createElement(Box6, { gap: 2 }, bottlenecks.length > 0 && /* @__PURE__ */ React6.createElement(Text6, { color: "red", bold: true }, "\u26A1 Bottlenecks: ", bottlenecks.join(" / ")), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u{1F916} ", formatCount(agentCount)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u2699 ", formatCount(skillCount)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "\u{1F527} ", formatCount(toolCount))))
5277
5408
  );
5278
5409
  }
5279
5410
 
@@ -5571,6 +5702,8 @@ function DashboardApp({
5571
5702
  workspace: workspaceProp
5572
5703
  }) {
5573
5704
  const { columns, rows, layoutMode } = useTerminalSize();
5705
+ const tick = useTick(1e3);
5706
+ const now = useMemo3(() => Date.now(), [tick]);
5574
5707
  const internalState = useDashboardState(externalState ? void 0 : eventBus);
5575
5708
  const state = externalState ?? internalState;
5576
5709
  const focusedAgent = state.focusedAgentId ? state.agents.get(state.focusedAgentId) ?? null : null;
@@ -5587,7 +5720,9 @@ function DashboardApp({
5587
5720
  currentMode: state.currentMode,
5588
5721
  globalState: state.globalState,
5589
5722
  layoutMode,
5590
- width: grid.header.width
5723
+ width: grid.header.width,
5724
+ tick,
5725
+ now
5591
5726
  }
5592
5727
  ), layoutMode === "narrow" ? /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, grid.checklistPanel.height > 0 && /* @__PURE__ */ React8.createElement(
5593
5728
  ChecklistPanel,
@@ -5608,7 +5743,9 @@ function DashboardApp({
5608
5743
  contextDecisions: state.contextDecisions,
5609
5744
  contextNotes: state.contextNotes,
5610
5745
  width: grid.focusedAgent.width,
5611
- height: grid.focusedAgent.height
5746
+ height: grid.focusedAgent.height,
5747
+ tick,
5748
+ now
5612
5749
  }
5613
5750
  ), /* @__PURE__ */ React8.createElement(
5614
5751
  FlowMap,
@@ -5618,7 +5755,9 @@ function DashboardApp({
5618
5755
  layoutMode,
5619
5756
  width: grid.flowMap.width,
5620
5757
  height: grid.flowMap.height,
5621
- activeStage: state.currentMode
5758
+ activeStage: state.currentMode,
5759
+ tick,
5760
+ now
5622
5761
  }
5623
5762
  )) : /* @__PURE__ */ React8.createElement(
5624
5763
  Box8,
@@ -5635,7 +5774,9 @@ function DashboardApp({
5635
5774
  layoutMode,
5636
5775
  width: grid.flowMap.width,
5637
5776
  height: grid.flowMap.height,
5638
- activeStage: state.currentMode
5777
+ activeStage: state.currentMode,
5778
+ tick,
5779
+ now
5639
5780
  }
5640
5781
  ), /* @__PURE__ */ React8.createElement(
5641
5782
  ActivityVisualizer,
@@ -5669,7 +5810,9 @@ function DashboardApp({
5669
5810
  contextDecisions: state.contextDecisions,
5670
5811
  contextNotes: state.contextNotes,
5671
5812
  width: grid.focusedAgent.width,
5672
- height: grid.focusedAgent.height
5813
+ height: grid.focusedAgent.height,
5814
+ tick,
5815
+ now
5673
5816
  }
5674
5817
  ))
5675
5818
  ), /* @__PURE__ */ React8.createElement(
@@ -5680,7 +5823,10 @@ function DashboardApp({
5680
5823
  toolCount: state.toolInvokeCount,
5681
5824
  agentCount: state.agentActivateCount,
5682
5825
  skillCount: state.skillInvokeCount,
5683
- width: grid.stageHealth.width
5826
+ width: grid.stageHealth.width,
5827
+ activityHistory: state.activityHistory,
5828
+ tick,
5829
+ now
5684
5830
  }
5685
5831
  ));
5686
5832
  }
@@ -5691,7 +5837,7 @@ import { Box as Box10, useInput } from "ink";
5691
5837
  import * as path8 from "path";
5692
5838
 
5693
5839
  // src/tui/hooks/use-multi-session-state.ts
5694
- import { useState as useState2, useCallback, useEffect as useEffect3, useRef } from "react";
5840
+ import { useState as useState3, useCallback, useEffect as useEffect4, useRef } from "react";
5695
5841
  function toSessionState(managed) {
5696
5842
  return {
5697
5843
  pid: managed.instance.pid,
@@ -5711,10 +5857,10 @@ function getPidArray(sessions) {
5711
5857
  return [...sessions.keys()];
5712
5858
  }
5713
5859
  function useMultiSessionState(manager) {
5714
- const [sessions, setSessions] = useState2(
5860
+ const [sessions, setSessions] = useState3(
5715
5861
  () => buildInitialSessions(manager)
5716
5862
  );
5717
- const [activeSessionPid, setActiveSessionPid] = useState2(() => {
5863
+ const [activeSessionPid, setActiveSessionPid] = useState3(() => {
5718
5864
  const initial = manager.getSessions();
5719
5865
  return initial.length > 0 ? initial[0].instance.pid : null;
5720
5866
  });
@@ -5789,7 +5935,7 @@ function useMultiSessionState(manager) {
5789
5935
  eventCleanupRef.current.delete(pid);
5790
5936
  }
5791
5937
  }, []);
5792
- useEffect3(() => {
5938
+ useEffect4(() => {
5793
5939
  for (const managed of manager.getSessions()) {
5794
5940
  subscribeSession(managed.instance.pid, managed.eventBus);
5795
5941
  }
@@ -5993,28 +6139,6 @@ function createDefaultAgentState(params) {
5993
6139
  return state;
5994
6140
  }
5995
6141
 
5996
- // src/tui/hooks/use-clock.ts
5997
- import { useState as useState3, useEffect as useEffect4 } from "react";
5998
-
5999
- // src/tui/components/header-bar.pure.ts
6000
- function formatTime(date) {
6001
- const hours = String(date.getHours()).padStart(2, "0");
6002
- const minutes = String(date.getMinutes()).padStart(2, "0");
6003
- return `${hours}:${minutes}`;
6004
- }
6005
-
6006
- // src/tui/hooks/use-clock.ts
6007
- function useClock() {
6008
- const [time, setTime] = useState3(() => formatTime(/* @__PURE__ */ new Date()));
6009
- useEffect4(() => {
6010
- const interval = setInterval(() => {
6011
- setTime(formatTime(/* @__PURE__ */ new Date()));
6012
- }, 1e3);
6013
- return () => clearInterval(interval);
6014
- }, []);
6015
- return time;
6016
- }
6017
-
6018
6142
  // src/tui/index.tsx
6019
6143
  function startTui(options) {
6020
6144
  const renderOptions = options.stdout ? { stdout: options.stdout } : {};
@@ -6035,9 +6159,9 @@ export {
6035
6159
  getLayoutMode,
6036
6160
  renderMultiSession,
6037
6161
  startTui,
6038
- useClock,
6039
6162
  useDashboardState,
6040
- useTerminalSize
6163
+ useTerminalSize,
6164
+ useTick
6041
6165
  };
6042
6166
  /*! Bundled license information:
6043
6167