codingbuddy 4.3.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.
- package/dist/src/agent/agent.service.d.ts +2 -0
- package/dist/src/agent/agent.service.js +45 -0
- package/dist/src/agent/agent.service.js.map +1 -1
- package/dist/src/agent/agent.types.d.ts +13 -0
- package/dist/src/agent/agent.types.js.map +1 -1
- package/dist/src/cli/init/prompts/model-prompt.js +48 -6
- package/dist/src/cli/init/prompts/model-prompt.js.map +1 -1
- package/dist/src/config/config.service.d.ts +7 -1
- package/dist/src/config/config.service.js +13 -1
- package/dist/src/config/config.service.js.map +1 -1
- package/dist/src/keyword/keyword.module.js +2 -0
- package/dist/src/keyword/keyword.module.js.map +1 -1
- package/dist/src/keyword/keyword.service.d.ts +3 -0
- package/dist/src/keyword/keyword.service.js +20 -1
- package/dist/src/keyword/keyword.service.js.map +1 -1
- package/dist/src/keyword/keyword.types.d.ts +2 -0
- package/dist/src/keyword/taskmaestro-detector.d.ts +1 -0
- package/dist/src/keyword/taskmaestro-detector.js +16 -0
- package/dist/src/keyword/taskmaestro-detector.js.map +1 -0
- package/dist/src/mcp/handlers/agent.handler.js +7 -0
- package/dist/src/mcp/handlers/agent.handler.js.map +1 -1
- package/dist/src/mcp/handlers/mode.handler.js +11 -0
- package/dist/src/mcp/handlers/mode.handler.js.map +1 -1
- package/dist/src/mcp/handlers/skill.handler.js +9 -2
- package/dist/src/mcp/handlers/skill.handler.js.map +1 -1
- package/dist/src/mcp/mcp.service.d.ts +1 -0
- package/dist/src/mcp/mcp.service.js +17 -0
- package/dist/src/mcp/mcp.service.js.map +1 -1
- package/dist/src/mcp/sse-auth.guard.js +4 -6
- package/dist/src/mcp/sse-auth.guard.js.map +1 -1
- package/dist/src/model/model.constants.d.ts +11 -0
- package/dist/src/model/model.constants.js +12 -1
- package/dist/src/model/model.constants.js.map +1 -1
- package/dist/src/model/model.resolver.d.ts +1 -1
- package/dist/src/model/model.resolver.js +15 -4
- package/dist/src/model/model.resolver.js.map +1 -1
- package/dist/src/shared/client-type.d.ts +6 -0
- package/dist/src/shared/client-type.js +21 -0
- package/dist/src/shared/client-type.js.map +1 -0
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/dist/src/skill/i18n/keywords.js +1466 -15
- package/dist/src/skill/i18n/keywords.js.map +1 -1
- package/dist/src/tui/components/FlowMap.d.ts +3 -1
- package/dist/src/tui/components/FlowMap.js +30 -3
- package/dist/src/tui/components/FlowMap.js.map +1 -1
- package/dist/src/tui/components/FlowMap.spec.js +88 -0
- package/dist/src/tui/components/FlowMap.spec.js.map +1 -1
- package/dist/src/tui/components/FocusedAgentPanel.d.ts +3 -1
- package/dist/src/tui/components/FocusedAgentPanel.js +8 -3
- package/dist/src/tui/components/FocusedAgentPanel.js.map +1 -1
- package/dist/src/tui/components/FocusedAgentPanel.spec.js +76 -0
- package/dist/src/tui/components/FocusedAgentPanel.spec.js.map +1 -1
- package/dist/src/tui/components/HeaderBar.d.ts +3 -1
- package/dist/src/tui/components/HeaderBar.js +12 -6
- package/dist/src/tui/components/HeaderBar.js.map +1 -1
- package/dist/src/tui/components/HeaderBar.spec.js +31 -13
- package/dist/src/tui/components/HeaderBar.spec.js.map +1 -1
- package/dist/src/tui/components/StageHealthBar.d.ts +5 -1
- package/dist/src/tui/components/StageHealthBar.js +6 -1
- package/dist/src/tui/components/StageHealthBar.js.map +1 -1
- package/dist/src/tui/components/StageHealthBar.spec.js +22 -0
- package/dist/src/tui/components/StageHealthBar.spec.js.map +1 -1
- package/dist/src/tui/components/focused-agent.pure.d.ts +1 -0
- package/dist/src/tui/components/focused-agent.pure.js +11 -0
- package/dist/src/tui/components/focused-agent.pure.js.map +1 -1
- package/dist/src/tui/components/index.d.ts +3 -1
- package/dist/src/tui/components/index.js +10 -1
- package/dist/src/tui/components/index.js.map +1 -1
- package/dist/src/tui/components/live.pure.d.ts +9 -0
- package/dist/src/tui/components/live.pure.js +70 -0
- package/dist/src/tui/components/live.pure.js.map +1 -0
- package/dist/src/tui/dashboard-app.js +9 -6
- package/dist/src/tui/dashboard-app.js.map +1 -1
- package/dist/src/tui/dashboard-app.spec.js +14 -0
- package/dist/src/tui/dashboard-app.spec.js.map +1 -1
- package/dist/src/tui/dashboard-types.d.ts +6 -0
- package/dist/src/tui/dashboard-types.js.map +1 -1
- package/dist/src/tui/eventbus-ui.integration.spec.js +3 -0
- package/dist/src/tui/eventbus-ui.integration.spec.js.map +1 -1
- package/dist/src/tui/hooks/index.d.ts +1 -1
- package/dist/src/tui/hooks/index.js +3 -3
- package/dist/src/tui/hooks/index.js.map +1 -1
- package/dist/src/tui/hooks/use-dashboard-state.js +16 -0
- package/dist/src/tui/hooks/use-dashboard-state.js.map +1 -1
- package/dist/src/tui/hooks/use-tick.d.ts +1 -0
- package/dist/src/tui/hooks/use-tick.js +15 -0
- package/dist/src/tui/hooks/use-tick.js.map +1 -0
- package/dist/src/tui/hooks/use-tick.spec.js +70 -0
- package/dist/src/tui/hooks/use-tick.spec.js.map +1 -0
- package/dist/src/tui/index.d.ts +1 -1
- package/dist/src/tui/index.js +2 -2
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui-bundle.mjs +191 -52
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -4
- package/dist/src/tui/components/header-bar.pure.d.ts +0 -1
- package/dist/src/tui/components/header-bar.pure.js +0 -9
- package/dist/src/tui/components/header-bar.pure.js.map +0 -1
- package/dist/src/tui/hooks/use-clock.d.ts +0 -1
- package/dist/src/tui/hooks/use-clock.js +0 -16
- package/dist/src/tui/hooks/use-clock.js.map +0 -1
- package/dist/src/tui/hooks/use-clock.spec.js +0 -43
- package/dist/src/tui/hooks/use-clock.spec.js.map +0 -1
- /package/dist/src/tui/hooks/{use-clock.spec.d.ts → use-tick.spec.d.ts} +0 -0
package/dist/src/tui-bundle.mjs
CHANGED
|
@@ -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
|
|
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());
|
|
@@ -3489,6 +3502,7 @@ ${file.content}
|
|
|
3489
3502
|
var ConfigService = class {
|
|
3490
3503
|
constructor() {
|
|
3491
3504
|
this.logger = new Logger6(ConfigService.name);
|
|
3505
|
+
this.projectRootSource = "auto_detect";
|
|
3492
3506
|
this.projectConfig = null;
|
|
3493
3507
|
this.isLoaded = false;
|
|
3494
3508
|
this.projectRoot = this.resolveProjectRoot();
|
|
@@ -3506,6 +3520,7 @@ var ConfigService = class {
|
|
|
3506
3520
|
const stat2 = statSync(normalizedPath);
|
|
3507
3521
|
if (stat2.isDirectory()) {
|
|
3508
3522
|
this.logger.log(`Using project root from CODINGBUDDY_PROJECT_ROOT: ${normalizedPath}`);
|
|
3523
|
+
this.projectRootSource = "env";
|
|
3509
3524
|
return normalizedPath;
|
|
3510
3525
|
}
|
|
3511
3526
|
this.logger.warn(
|
|
@@ -3543,7 +3558,7 @@ var ConfigService = class {
|
|
|
3543
3558
|
* @param root - Path to the project root directory
|
|
3544
3559
|
* @throws Error if path does not exist, is not a directory, or contains invalid characters
|
|
3545
3560
|
*/
|
|
3546
|
-
async setProjectRootAndReload(root) {
|
|
3561
|
+
async setProjectRootAndReload(root, source = "roots_list") {
|
|
3547
3562
|
if (root.includes("\0")) {
|
|
3548
3563
|
throw new Error("Path contains null bytes (possible null byte injection)");
|
|
3549
3564
|
}
|
|
@@ -3569,6 +3584,7 @@ var ConfigService = class {
|
|
|
3569
3584
|
}
|
|
3570
3585
|
clearProjectRootCache();
|
|
3571
3586
|
this.projectRoot = resolvedPath;
|
|
3587
|
+
this.projectRootSource = source;
|
|
3572
3588
|
this.isLoaded = false;
|
|
3573
3589
|
this.projectConfig = null;
|
|
3574
3590
|
await this.loadProjectConfig();
|
|
@@ -3580,6 +3596,18 @@ var ConfigService = class {
|
|
|
3580
3596
|
getProjectRoot() {
|
|
3581
3597
|
return this.projectRoot;
|
|
3582
3598
|
}
|
|
3599
|
+
/**
|
|
3600
|
+
* Get how the project root was resolved
|
|
3601
|
+
*/
|
|
3602
|
+
getProjectRootSource() {
|
|
3603
|
+
return this.projectRootSource;
|
|
3604
|
+
}
|
|
3605
|
+
getClientName() {
|
|
3606
|
+
return this.clientName;
|
|
3607
|
+
}
|
|
3608
|
+
setClientName(name) {
|
|
3609
|
+
this.clientName = name;
|
|
3610
|
+
}
|
|
3583
3611
|
/**
|
|
3584
3612
|
* Load all project configuration
|
|
3585
3613
|
*/
|
|
@@ -3959,6 +3987,7 @@ function createInitialDashboardState() {
|
|
|
3959
3987
|
tasks: [],
|
|
3960
3988
|
eventLog: [],
|
|
3961
3989
|
toolCalls: [],
|
|
3990
|
+
activityHistory: [],
|
|
3962
3991
|
objectives: [],
|
|
3963
3992
|
activeSkills: [],
|
|
3964
3993
|
toolInvokeCount: 0,
|
|
@@ -4060,7 +4089,8 @@ function dashboardReducer(state, action) {
|
|
|
4060
4089
|
const entry = {
|
|
4061
4090
|
timestamp: new Date(action.payload.timestamp).toTimeString().slice(0, 8),
|
|
4062
4091
|
message: `${action.payload.toolName}${action.payload.agentId ? ` [${action.payload.agentId}]` : ""}`,
|
|
4063
|
-
level: "info"
|
|
4092
|
+
level: "info",
|
|
4093
|
+
rawTimestamp: action.payload.timestamp
|
|
4064
4094
|
};
|
|
4065
4095
|
const base = state.eventLog.length >= EVENT_LOG_MAX ? state.eventLog.slice(1) : state.eventLog;
|
|
4066
4096
|
const invokedAgentId = action.payload.agentId;
|
|
@@ -4088,11 +4118,24 @@ function dashboardReducer(state, action) {
|
|
|
4088
4118
|
status: "completed"
|
|
4089
4119
|
};
|
|
4090
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
|
+
}
|
|
4091
4133
|
return {
|
|
4092
4134
|
...state,
|
|
4093
4135
|
agents,
|
|
4094
4136
|
eventLog: [...base, entry],
|
|
4095
4137
|
toolCalls: [...toolCallsBase, toolCall],
|
|
4138
|
+
activityHistory,
|
|
4096
4139
|
toolInvokeCount: state.toolInvokeCount + 1
|
|
4097
4140
|
};
|
|
4098
4141
|
}
|
|
@@ -4166,7 +4209,7 @@ function dashboardReducer(state, action) {
|
|
|
4166
4209
|
}
|
|
4167
4210
|
function useDashboardState(eventBus) {
|
|
4168
4211
|
const [state, dispatch] = useReducer(dashboardReducer, void 0, createInitialDashboardState);
|
|
4169
|
-
|
|
4212
|
+
useEffect3(() => {
|
|
4170
4213
|
if (!eventBus) return;
|
|
4171
4214
|
const onActivated = (p) => dispatch({ type: "AGENT_ACTIVATED", payload: p });
|
|
4172
4215
|
const onDeactivated = (p) => dispatch({ type: "AGENT_DEACTIVATED", payload: p });
|
|
@@ -4210,7 +4253,7 @@ function useDashboardState(eventBus) {
|
|
|
4210
4253
|
eventBus.off(TUI_EVENTS.CONTEXT_UPDATED, onContextUpdated);
|
|
4211
4254
|
};
|
|
4212
4255
|
}, [eventBus]);
|
|
4213
|
-
|
|
4256
|
+
useEffect3(() => {
|
|
4214
4257
|
const cleanupInterval = setInterval(() => {
|
|
4215
4258
|
dispatch({ type: "CLEANUP_STALE_AGENTS", payload: { now: Date.now(), ttlMs: 3e4 } });
|
|
4216
4259
|
}, 1e4);
|
|
@@ -4333,6 +4376,59 @@ function getAgentAvatar(agentName) {
|
|
|
4333
4376
|
return "\u{1F916}";
|
|
4334
4377
|
}
|
|
4335
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
|
+
|
|
4336
4432
|
// src/tui/components/HeaderBar.tsx
|
|
4337
4433
|
var PROCESS_MODES = ["PLAN", "ACT", "EVAL"];
|
|
4338
4434
|
function ModeFlow({ currentMode }) {
|
|
@@ -4343,17 +4439,23 @@ function ModeFlow({ currentMode }) {
|
|
|
4343
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));
|
|
4344
4440
|
}));
|
|
4345
4441
|
}
|
|
4346
|
-
function StateIndicator({
|
|
4347
|
-
|
|
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];
|
|
4348
4448
|
const color = GLOBAL_STATE_COLORS[globalState];
|
|
4349
|
-
return /* @__PURE__ */ React.createElement(Text, { color, bold:
|
|
4449
|
+
return /* @__PURE__ */ React.createElement(Text, { color, bold: isRunning || globalState === "ERROR" }, icon, " ", globalState);
|
|
4350
4450
|
}
|
|
4351
4451
|
function HeaderBar({
|
|
4352
4452
|
workspace,
|
|
4353
4453
|
currentMode,
|
|
4354
4454
|
globalState,
|
|
4355
4455
|
layoutMode,
|
|
4356
|
-
width
|
|
4456
|
+
width,
|
|
4457
|
+
tick,
|
|
4458
|
+
now
|
|
4357
4459
|
}) {
|
|
4358
4460
|
if (layoutMode === "narrow") {
|
|
4359
4461
|
return /* @__PURE__ */ React.createElement(
|
|
@@ -4369,7 +4471,8 @@ function HeaderBar({
|
|
|
4369
4471
|
/* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
|
|
4370
4472
|
/* @__PURE__ */ React.createElement(ModeFlow, { currentMode }),
|
|
4371
4473
|
/* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
|
|
4372
|
-
/* @__PURE__ */ React.createElement(StateIndicator, { globalState })
|
|
4474
|
+
/* @__PURE__ */ React.createElement(StateIndicator, { globalState, tick }),
|
|
4475
|
+
now !== void 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " ", formatTimeWithSeconds(now))
|
|
4373
4476
|
);
|
|
4374
4477
|
}
|
|
4375
4478
|
return /* @__PURE__ */ React.createElement(
|
|
@@ -4381,7 +4484,7 @@ function HeaderBar({
|
|
|
4381
4484
|
overflowX: "hidden",
|
|
4382
4485
|
flexDirection: "row"
|
|
4383
4486
|
},
|
|
4384
|
-
/* @__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))),
|
|
4385
4488
|
/* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
|
|
4386
4489
|
/* @__PURE__ */ React.createElement(Box, { flexShrink: 1, overflowX: "hidden" }, /* @__PURE__ */ React.createElement(Text, { dimColor: true, wrap: "truncate" }, workspace))
|
|
4387
4490
|
);
|
|
@@ -4900,10 +5003,18 @@ function FlowMap({
|
|
|
4900
5003
|
layoutMode,
|
|
4901
5004
|
width,
|
|
4902
5005
|
height,
|
|
4903
|
-
activeStage = null
|
|
5006
|
+
activeStage = null,
|
|
5007
|
+
tick,
|
|
5008
|
+
now
|
|
4904
5009
|
}) {
|
|
4905
5010
|
const contentWidth = Math.max(1, width - 2);
|
|
4906
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;
|
|
4907
5018
|
const compactContent = useMemo(() => {
|
|
4908
5019
|
if (layoutMode !== "narrow") return null;
|
|
4909
5020
|
return renderFlowMapCompact(agents);
|
|
@@ -4913,6 +5024,20 @@ function FlowMap({
|
|
|
4913
5024
|
const buf = layoutMode === "wide" ? renderFlowMap(agents, edges, contentWidth, contentHeight, activeStage) : renderFlowMapSimplified(agents, contentWidth, contentHeight);
|
|
4914
5025
|
return buf.toLinesDirect();
|
|
4915
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]);
|
|
4916
5041
|
if (layoutMode === "narrow") {
|
|
4917
5042
|
return /* @__PURE__ */ React2.createElement(
|
|
4918
5043
|
Box2,
|
|
@@ -4924,7 +5049,8 @@ function FlowMap({
|
|
|
4924
5049
|
height
|
|
4925
5050
|
},
|
|
4926
5051
|
/* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "FLOW MAP"),
|
|
4927
|
-
/* @__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))
|
|
4928
5054
|
);
|
|
4929
5055
|
}
|
|
4930
5056
|
if (!lines) {
|
|
@@ -4950,7 +5076,8 @@ function FlowMap({
|
|
|
4950
5076
|
height
|
|
4951
5077
|
},
|
|
4952
5078
|
/* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "FLOW MAP"),
|
|
4953
|
-
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))
|
|
4954
5081
|
);
|
|
4955
5082
|
}
|
|
4956
5083
|
|
|
@@ -4970,6 +5097,13 @@ function formatLogTail(events, maxLines = 10) {
|
|
|
4970
5097
|
const tail = events.slice(-maxLines);
|
|
4971
5098
|
return tail.map((e) => `${e.timestamp} ${e.message}`).join("\n");
|
|
4972
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
|
+
}
|
|
4973
5107
|
function formatSectionDivider(title, width = 50) {
|
|
4974
5108
|
const prefix = "\u2500\u2500\u2500 ";
|
|
4975
5109
|
const suffix = " ";
|
|
@@ -5056,6 +5190,8 @@ function FocusedAgentPanel({
|
|
|
5056
5190
|
eventLog,
|
|
5057
5191
|
contextDecisions = [],
|
|
5058
5192
|
contextNotes = [],
|
|
5193
|
+
tick,
|
|
5194
|
+
now,
|
|
5059
5195
|
width,
|
|
5060
5196
|
height
|
|
5061
5197
|
}) {
|
|
@@ -5078,7 +5214,10 @@ function FocusedAgentPanel({
|
|
|
5078
5214
|
const statusLabel = agent.status.toUpperCase();
|
|
5079
5215
|
const progressBar = formatEnhancedProgressBar(agent.progress);
|
|
5080
5216
|
const objective = formatObjective(objectives);
|
|
5081
|
-
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;
|
|
5082
5221
|
return /* @__PURE__ */ React4.createElement(
|
|
5083
5222
|
Box4,
|
|
5084
5223
|
{
|
|
@@ -5088,7 +5227,7 @@ function FocusedAgentPanel({
|
|
|
5088
5227
|
width,
|
|
5089
5228
|
height
|
|
5090
5229
|
},
|
|
5091
|
-
/* @__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)),
|
|
5092
5231
|
/* @__PURE__ */ React4.createElement(Box4, { gap: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "magenta" }, progressBar.bar), /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, progressBar.label)),
|
|
5093
5232
|
/* @__PURE__ */ React4.createElement(SectionDivider, { title: "Objective" }),
|
|
5094
5233
|
objective ? /* @__PURE__ */ React4.createElement(Text4, null, objective) : /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "No objectives"),
|
|
@@ -5248,8 +5387,12 @@ function StageHealthBar({
|
|
|
5248
5387
|
toolCount,
|
|
5249
5388
|
agentCount,
|
|
5250
5389
|
skillCount,
|
|
5251
|
-
width
|
|
5390
|
+
width,
|
|
5391
|
+
activityHistory,
|
|
5392
|
+
tick: _tick,
|
|
5393
|
+
now: _now
|
|
5252
5394
|
}) {
|
|
5395
|
+
const hasActivity = activityHistory && activityHistory.length > 0;
|
|
5253
5396
|
return /* @__PURE__ */ React6.createElement(
|
|
5254
5397
|
Box6,
|
|
5255
5398
|
{
|
|
@@ -5258,7 +5401,10 @@ function StageHealthBar({
|
|
|
5258
5401
|
width,
|
|
5259
5402
|
flexDirection: "column"
|
|
5260
5403
|
},
|
|
5261
|
-
/* @__PURE__ */ React6.createElement(Box6, null,
|
|
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))))
|
|
5262
5408
|
);
|
|
5263
5409
|
}
|
|
5264
5410
|
|
|
@@ -5556,6 +5702,8 @@ function DashboardApp({
|
|
|
5556
5702
|
workspace: workspaceProp
|
|
5557
5703
|
}) {
|
|
5558
5704
|
const { columns, rows, layoutMode } = useTerminalSize();
|
|
5705
|
+
const tick = useTick(1e3);
|
|
5706
|
+
const now = useMemo3(() => Date.now(), [tick]);
|
|
5559
5707
|
const internalState = useDashboardState(externalState ? void 0 : eventBus);
|
|
5560
5708
|
const state = externalState ?? internalState;
|
|
5561
5709
|
const focusedAgent = state.focusedAgentId ? state.agents.get(state.focusedAgentId) ?? null : null;
|
|
@@ -5572,7 +5720,9 @@ function DashboardApp({
|
|
|
5572
5720
|
currentMode: state.currentMode,
|
|
5573
5721
|
globalState: state.globalState,
|
|
5574
5722
|
layoutMode,
|
|
5575
|
-
width: grid.header.width
|
|
5723
|
+
width: grid.header.width,
|
|
5724
|
+
tick,
|
|
5725
|
+
now
|
|
5576
5726
|
}
|
|
5577
5727
|
), layoutMode === "narrow" ? /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, grid.checklistPanel.height > 0 && /* @__PURE__ */ React8.createElement(
|
|
5578
5728
|
ChecklistPanel,
|
|
@@ -5593,7 +5743,9 @@ function DashboardApp({
|
|
|
5593
5743
|
contextDecisions: state.contextDecisions,
|
|
5594
5744
|
contextNotes: state.contextNotes,
|
|
5595
5745
|
width: grid.focusedAgent.width,
|
|
5596
|
-
height: grid.focusedAgent.height
|
|
5746
|
+
height: grid.focusedAgent.height,
|
|
5747
|
+
tick,
|
|
5748
|
+
now
|
|
5597
5749
|
}
|
|
5598
5750
|
), /* @__PURE__ */ React8.createElement(
|
|
5599
5751
|
FlowMap,
|
|
@@ -5603,7 +5755,9 @@ function DashboardApp({
|
|
|
5603
5755
|
layoutMode,
|
|
5604
5756
|
width: grid.flowMap.width,
|
|
5605
5757
|
height: grid.flowMap.height,
|
|
5606
|
-
activeStage: state.currentMode
|
|
5758
|
+
activeStage: state.currentMode,
|
|
5759
|
+
tick,
|
|
5760
|
+
now
|
|
5607
5761
|
}
|
|
5608
5762
|
)) : /* @__PURE__ */ React8.createElement(
|
|
5609
5763
|
Box8,
|
|
@@ -5620,7 +5774,9 @@ function DashboardApp({
|
|
|
5620
5774
|
layoutMode,
|
|
5621
5775
|
width: grid.flowMap.width,
|
|
5622
5776
|
height: grid.flowMap.height,
|
|
5623
|
-
activeStage: state.currentMode
|
|
5777
|
+
activeStage: state.currentMode,
|
|
5778
|
+
tick,
|
|
5779
|
+
now
|
|
5624
5780
|
}
|
|
5625
5781
|
), /* @__PURE__ */ React8.createElement(
|
|
5626
5782
|
ActivityVisualizer,
|
|
@@ -5654,7 +5810,9 @@ function DashboardApp({
|
|
|
5654
5810
|
contextDecisions: state.contextDecisions,
|
|
5655
5811
|
contextNotes: state.contextNotes,
|
|
5656
5812
|
width: grid.focusedAgent.width,
|
|
5657
|
-
height: grid.focusedAgent.height
|
|
5813
|
+
height: grid.focusedAgent.height,
|
|
5814
|
+
tick,
|
|
5815
|
+
now
|
|
5658
5816
|
}
|
|
5659
5817
|
))
|
|
5660
5818
|
), /* @__PURE__ */ React8.createElement(
|
|
@@ -5665,7 +5823,10 @@ function DashboardApp({
|
|
|
5665
5823
|
toolCount: state.toolInvokeCount,
|
|
5666
5824
|
agentCount: state.agentActivateCount,
|
|
5667
5825
|
skillCount: state.skillInvokeCount,
|
|
5668
|
-
width: grid.stageHealth.width
|
|
5826
|
+
width: grid.stageHealth.width,
|
|
5827
|
+
activityHistory: state.activityHistory,
|
|
5828
|
+
tick,
|
|
5829
|
+
now
|
|
5669
5830
|
}
|
|
5670
5831
|
));
|
|
5671
5832
|
}
|
|
@@ -5676,7 +5837,7 @@ import { Box as Box10, useInput } from "ink";
|
|
|
5676
5837
|
import * as path8 from "path";
|
|
5677
5838
|
|
|
5678
5839
|
// src/tui/hooks/use-multi-session-state.ts
|
|
5679
|
-
import { useState as
|
|
5840
|
+
import { useState as useState3, useCallback, useEffect as useEffect4, useRef } from "react";
|
|
5680
5841
|
function toSessionState(managed) {
|
|
5681
5842
|
return {
|
|
5682
5843
|
pid: managed.instance.pid,
|
|
@@ -5696,10 +5857,10 @@ function getPidArray(sessions) {
|
|
|
5696
5857
|
return [...sessions.keys()];
|
|
5697
5858
|
}
|
|
5698
5859
|
function useMultiSessionState(manager) {
|
|
5699
|
-
const [sessions, setSessions] =
|
|
5860
|
+
const [sessions, setSessions] = useState3(
|
|
5700
5861
|
() => buildInitialSessions(manager)
|
|
5701
5862
|
);
|
|
5702
|
-
const [activeSessionPid, setActiveSessionPid] =
|
|
5863
|
+
const [activeSessionPid, setActiveSessionPid] = useState3(() => {
|
|
5703
5864
|
const initial = manager.getSessions();
|
|
5704
5865
|
return initial.length > 0 ? initial[0].instance.pid : null;
|
|
5705
5866
|
});
|
|
@@ -5774,7 +5935,7 @@ function useMultiSessionState(manager) {
|
|
|
5774
5935
|
eventCleanupRef.current.delete(pid);
|
|
5775
5936
|
}
|
|
5776
5937
|
}, []);
|
|
5777
|
-
|
|
5938
|
+
useEffect4(() => {
|
|
5778
5939
|
for (const managed of manager.getSessions()) {
|
|
5779
5940
|
subscribeSession(managed.instance.pid, managed.eventBus);
|
|
5780
5941
|
}
|
|
@@ -5978,28 +6139,6 @@ function createDefaultAgentState(params) {
|
|
|
5978
6139
|
return state;
|
|
5979
6140
|
}
|
|
5980
6141
|
|
|
5981
|
-
// src/tui/hooks/use-clock.ts
|
|
5982
|
-
import { useState as useState3, useEffect as useEffect4 } from "react";
|
|
5983
|
-
|
|
5984
|
-
// src/tui/components/header-bar.pure.ts
|
|
5985
|
-
function formatTime(date) {
|
|
5986
|
-
const hours = String(date.getHours()).padStart(2, "0");
|
|
5987
|
-
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
5988
|
-
return `${hours}:${minutes}`;
|
|
5989
|
-
}
|
|
5990
|
-
|
|
5991
|
-
// src/tui/hooks/use-clock.ts
|
|
5992
|
-
function useClock() {
|
|
5993
|
-
const [time, setTime] = useState3(() => formatTime(/* @__PURE__ */ new Date()));
|
|
5994
|
-
useEffect4(() => {
|
|
5995
|
-
const interval = setInterval(() => {
|
|
5996
|
-
setTime(formatTime(/* @__PURE__ */ new Date()));
|
|
5997
|
-
}, 1e3);
|
|
5998
|
-
return () => clearInterval(interval);
|
|
5999
|
-
}, []);
|
|
6000
|
-
return time;
|
|
6001
|
-
}
|
|
6002
|
-
|
|
6003
6142
|
// src/tui/index.tsx
|
|
6004
6143
|
function startTui(options) {
|
|
6005
6144
|
const renderOptions = options.stdout ? { stdout: options.stdout } : {};
|
|
@@ -6020,9 +6159,9 @@ export {
|
|
|
6020
6159
|
getLayoutMode,
|
|
6021
6160
|
renderMultiSession,
|
|
6022
6161
|
startTui,
|
|
6023
|
-
useClock,
|
|
6024
6162
|
useDashboardState,
|
|
6025
|
-
useTerminalSize
|
|
6163
|
+
useTerminalSize,
|
|
6164
|
+
useTick
|
|
6026
6165
|
};
|
|
6027
6166
|
/*! Bundled license information:
|
|
6028
6167
|
|