codingbuddy 4.4.0 → 5.0.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.module.js +3 -1
- package/dist/src/agent/agent.module.js.map +1 -1
- package/dist/src/agent/agent.service.d.ts +13 -4
- package/dist/src/agent/agent.service.js +125 -12
- package/dist/src/agent/agent.service.js.map +1 -1
- package/dist/src/agent/agent.types.d.ts +53 -0
- package/dist/src/agent/agent.types.js.map +1 -1
- package/dist/src/collaboration/discussion-engine.d.ts +14 -0
- package/dist/src/collaboration/discussion-engine.js +49 -0
- package/dist/src/collaboration/discussion-engine.js.map +1 -0
- package/dist/src/collaboration/index.d.ts +5 -0
- package/dist/src/collaboration/index.js +22 -0
- package/dist/src/collaboration/index.js.map +1 -0
- package/dist/src/collaboration/opinion-adapter.d.ts +14 -0
- package/dist/src/collaboration/opinion-adapter.js +56 -0
- package/dist/src/collaboration/opinion-adapter.js.map +1 -0
- package/dist/src/collaboration/terminal-formatter.d.ts +5 -0
- package/dist/src/collaboration/terminal-formatter.js +57 -0
- package/dist/src/collaboration/terminal-formatter.js.map +1 -0
- package/dist/src/collaboration/types.d.ts +50 -0
- package/dist/src/collaboration/types.js +53 -0
- package/dist/src/collaboration/types.js.map +1 -0
- package/dist/src/config/config.schema.d.ts +8 -0
- package/dist/src/config/config.schema.js +4 -0
- package/dist/src/config/config.schema.js.map +1 -1
- package/dist/src/context/context-document.service.d.ts +1 -1
- package/dist/src/context/context-document.service.js +6 -2
- package/dist/src/context/context-document.service.js.map +1 -1
- package/dist/src/context/context-document.types.d.ts +18 -0
- package/dist/src/context/context-document.types.js +13 -1
- package/dist/src/context/context-document.types.js.map +1 -1
- package/dist/src/context/context-parser.utils.js +32 -0
- package/dist/src/context/context-parser.utils.js.map +1 -1
- package/dist/src/context/context-serializer.utils.d.ts +3 -2
- package/dist/src/context/context-serializer.utils.js +25 -1
- package/dist/src/context/context-serializer.utils.js.map +1 -1
- package/dist/src/keyword/explicit-pattern-matcher.d.ts +3 -0
- package/dist/src/keyword/explicit-pattern-matcher.js +34 -0
- package/dist/src/keyword/explicit-pattern-matcher.js.map +1 -0
- package/dist/src/keyword/keyword.module.js +17 -1
- package/dist/src/keyword/keyword.module.js.map +1 -1
- package/dist/src/keyword/keyword.service.d.ts +2 -0
- package/dist/src/keyword/keyword.service.js +15 -0
- package/dist/src/keyword/keyword.service.js.map +1 -1
- package/dist/src/keyword/keyword.types.d.ts +6 -1
- package/dist/src/keyword/keyword.types.js +7 -1
- package/dist/src/keyword/keyword.types.js.map +1 -1
- package/dist/src/keyword/primary-agent-resolver.d.ts +5 -2
- package/dist/src/keyword/primary-agent-resolver.js +22 -1
- package/dist/src/keyword/primary-agent-resolver.js.map +1 -1
- package/dist/src/keyword/strategies/act-agent.strategy.js +8 -0
- package/dist/src/keyword/strategies/act-agent.strategy.js.map +1 -1
- package/dist/src/keyword/strategies/index.d.ts +1 -1
- package/dist/src/keyword/strategies/index.js.map +1 -1
- package/dist/src/keyword/strategies/resolution-strategy.interface.d.ts +3 -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.d.ts +1 -0
- package/dist/src/mcp/handlers/agent.handler.js +51 -2
- package/dist/src/mcp/handlers/agent.handler.js.map +1 -1
- package/dist/src/mcp/handlers/context-document.handler.d.ts +3 -0
- package/dist/src/mcp/handlers/context-document.handler.js +91 -10
- package/dist/src/mcp/handlers/context-document.handler.js.map +1 -1
- package/dist/src/mcp/handlers/discussion.handler.d.ts +14 -0
- package/dist/src/mcp/handlers/discussion.handler.js +168 -0
- package/dist/src/mcp/handlers/discussion.handler.js.map +1 -0
- package/dist/src/mcp/handlers/discussion.types.d.ts +18 -0
- package/dist/src/mcp/handlers/discussion.types.js +11 -0
- package/dist/src/mcp/handlers/discussion.types.js.map +1 -0
- package/dist/src/mcp/handlers/index.d.ts +3 -0
- package/dist/src/mcp/handlers/index.js +7 -1
- package/dist/src/mcp/handlers/index.js.map +1 -1
- package/dist/src/mcp/handlers/mode.handler.d.ts +3 -0
- package/dist/src/mcp/handlers/mode.handler.js +58 -0
- package/dist/src/mcp/handlers/mode.handler.js.map +1 -1
- package/dist/src/mcp/handlers/pipeline.handler.d.ts +14 -0
- package/dist/src/mcp/handlers/pipeline.handler.js +137 -0
- package/dist/src/mcp/handlers/pipeline.handler.js.map +1 -0
- package/dist/src/mcp/mcp.module.js +5 -0
- package/dist/src/mcp/mcp.module.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/parallel-validation/extract-file-paths.d.ts +1 -0
- package/dist/src/parallel-validation/extract-file-paths.js +19 -0
- package/dist/src/parallel-validation/extract-file-paths.js.map +1 -0
- package/dist/src/parallel-validation/index.d.ts +5 -0
- package/dist/src/parallel-validation/index.js +12 -0
- package/dist/src/parallel-validation/index.js.map +1 -0
- package/dist/src/parallel-validation/overlap-matrix.d.ts +10 -0
- package/dist/src/parallel-validation/overlap-matrix.js +23 -0
- package/dist/src/parallel-validation/overlap-matrix.js.map +1 -0
- package/dist/src/parallel-validation/parallel-validation.handler.d.ts +8 -0
- package/dist/src/parallel-validation/parallel-validation.handler.js +84 -0
- package/dist/src/parallel-validation/parallel-validation.handler.js.map +1 -0
- package/dist/src/parallel-validation/parallel-validation.types.d.ts +12 -0
- package/dist/src/parallel-validation/parallel-validation.types.js +3 -0
- package/dist/src/parallel-validation/parallel-validation.types.js.map +1 -0
- package/dist/src/parallel-validation/wave-splitter.d.ts +2 -0
- package/dist/src/parallel-validation/wave-splitter.js +39 -0
- package/dist/src/parallel-validation/wave-splitter.js.map +1 -0
- package/dist/src/pipeline/index.d.ts +5 -0
- package/dist/src/pipeline/index.js +14 -0
- package/dist/src/pipeline/index.js.map +1 -0
- package/dist/src/pipeline/pipeline.executors.d.ts +2 -0
- package/dist/src/pipeline/pipeline.executors.js +79 -0
- package/dist/src/pipeline/pipeline.executors.js.map +1 -0
- package/dist/src/pipeline/pipeline.module.d.ts +2 -0
- package/dist/src/pipeline/pipeline.module.js +21 -0
- package/dist/src/pipeline/pipeline.module.js.map +1 -0
- package/dist/src/pipeline/pipeline.service.d.ts +8 -0
- package/dist/src/pipeline/pipeline.service.js +89 -0
- package/dist/src/pipeline/pipeline.service.js.map +1 -0
- package/dist/src/pipeline/pipeline.types.d.ts +47 -0
- package/dist/src/pipeline/pipeline.types.js +33 -0
- package/dist/src/pipeline/pipeline.types.js.map +1 -0
- package/dist/src/rules/rule-tracker.d.ts +24 -0
- package/dist/src/rules/rule-tracker.js +74 -0
- package/dist/src/rules/rule-tracker.js.map +1 -0
- package/dist/src/shared/event-bridge-reader.d.ts +17 -0
- package/dist/src/shared/event-bridge-reader.js +56 -0
- package/dist/src/shared/event-bridge-reader.js.map +1 -0
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/dist/src/tui/components/AgentDiscussionPanel.d.ts +8 -0
- package/dist/src/tui/components/AgentDiscussionPanel.js +21 -0
- package/dist/src/tui/components/AgentDiscussionPanel.js.map +1 -0
- package/dist/src/tui/components/AgentDiscussionPanel.spec.js +85 -0
- package/dist/src/tui/components/AgentDiscussionPanel.spec.js.map +1 -0
- 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/agent-discussion-panel.pure.d.ts +10 -0
- package/dist/src/tui/components/agent-discussion-panel.pure.js +94 -0
- package/dist/src/tui/components/agent-discussion-panel.pure.js.map +1 -0
- 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 +5 -1
- package/dist/src/tui/components/index.js +18 -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 +10 -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 +8 -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/events/index.d.ts +1 -1
- package/dist/src/tui/events/index.js.map +1 -1
- package/dist/src/tui/events/types.d.ts +6 -0
- package/dist/src/tui/events/types.js +1 -0
- package/dist/src/tui/events/types.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.d.ts +4 -1
- package/dist/src/tui/hooks/use-dashboard-state.js +26 -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.d.ts +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 +468 -133
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +15 -14
- 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 → components/AgentDiscussionPanel.spec.d.ts} +0 -0
package/dist/src/tui-bundle.mjs
CHANGED
|
@@ -1371,12 +1371,12 @@ var require_eventemitter2 = __commonJS({
|
|
|
1371
1371
|
});
|
|
1372
1372
|
|
|
1373
1373
|
// src/tui/index.tsx
|
|
1374
|
-
import
|
|
1374
|
+
import React12 from "react";
|
|
1375
1375
|
import { render } from "ink";
|
|
1376
1376
|
|
|
1377
1377
|
// src/tui/dashboard-app.tsx
|
|
1378
|
-
import
|
|
1379
|
-
import { Box as
|
|
1378
|
+
import React9, { useMemo as useMemo4 } from "react";
|
|
1379
|
+
import { Box as Box9 } from "ink";
|
|
1380
1380
|
|
|
1381
1381
|
// src/tui/hooks/use-terminal-size.ts
|
|
1382
1382
|
import { useState, useEffect } from "react";
|
|
@@ -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());
|
|
@@ -1483,7 +1496,8 @@ var TUI_EVENTS = Object.freeze({
|
|
|
1483
1496
|
TOOL_INVOKED: "tool:invoked",
|
|
1484
1497
|
OBJECTIVE_SET: "objective:set",
|
|
1485
1498
|
SESSION_RESET: "session:reset",
|
|
1486
|
-
CONTEXT_UPDATED: "context:updated"
|
|
1499
|
+
CONTEXT_UPDATED: "context:updated",
|
|
1500
|
+
DISCUSSION_ROUND_ADDED: "discussion:round-added"
|
|
1487
1501
|
});
|
|
1488
1502
|
|
|
1489
1503
|
// src/tui/events/parse-agent.ts
|
|
@@ -2824,6 +2838,22 @@ var TestStrategyConfigSchema = z3.object({
|
|
|
2824
2838
|
var AIConfigSchema = z3.object({
|
|
2825
2839
|
defaultModel: z3.string().optional(),
|
|
2826
2840
|
primaryAgent: z3.string().optional(),
|
|
2841
|
+
/**
|
|
2842
|
+
* Override default dispatch strength for parallel specialist agents.
|
|
2843
|
+
* - "auto": Always dispatch specialists automatically
|
|
2844
|
+
* - "recommend": Suggest dispatch (default for PLAN/ACT)
|
|
2845
|
+
* - "skip": Do not dispatch specialists
|
|
2846
|
+
*
|
|
2847
|
+
* Default varies by mode: EVAL="auto", PLAN/ACT="recommend"
|
|
2848
|
+
*
|
|
2849
|
+
* @example
|
|
2850
|
+
* ```javascript
|
|
2851
|
+
* ai: {
|
|
2852
|
+
* dispatchStrength: 'auto',
|
|
2853
|
+
* }
|
|
2854
|
+
* ```
|
|
2855
|
+
*/
|
|
2856
|
+
dispatchStrength: z3.enum(["auto", "recommend", "skip"]).optional(),
|
|
2827
2857
|
/**
|
|
2828
2858
|
* List of agent names to exclude from automatic resolution.
|
|
2829
2859
|
* Useful for project-specific exclusions (e.g., exclude mobile-developer for backend-only projects).
|
|
@@ -2849,7 +2879,27 @@ var AIConfigSchema = z3.object({
|
|
|
2849
2879
|
* }
|
|
2850
2880
|
* ```
|
|
2851
2881
|
*/
|
|
2852
|
-
maxIncludedSkills: z3.number().int().min(0).max(10).optional()
|
|
2882
|
+
maxIncludedSkills: z3.number().int().min(0).max(10).optional(),
|
|
2883
|
+
/**
|
|
2884
|
+
* Enable/disable automatic plan-reviewer gate after PLAN completion.
|
|
2885
|
+
* When enabled, parse_mode PLAN response includes a planReviewGate recommendation.
|
|
2886
|
+
* Default: true (enabled)
|
|
2887
|
+
*
|
|
2888
|
+
* @example
|
|
2889
|
+
* ```javascript
|
|
2890
|
+
* ai: {
|
|
2891
|
+
* planReviewGate: false, // disable plan review gate
|
|
2892
|
+
* }
|
|
2893
|
+
* ```
|
|
2894
|
+
*/
|
|
2895
|
+
planReviewGate: z3.boolean().optional(),
|
|
2896
|
+
/**
|
|
2897
|
+
* Enable/disable agent discussion integration in EVAL mode.
|
|
2898
|
+
* When enabled, parse_mode EVAL response includes agentDiscussion config
|
|
2899
|
+
* for structuring specialist findings as AgentOpinion protocol.
|
|
2900
|
+
* Default: true (enabled)
|
|
2901
|
+
*/
|
|
2902
|
+
agentDiscussion: z3.boolean().optional()
|
|
2853
2903
|
});
|
|
2854
2904
|
var AutoConfigSchema = z3.object({
|
|
2855
2905
|
maxIterations: z3.number().int().min(1).max(10).default(3)
|
|
@@ -2877,6 +2927,8 @@ var CodingBuddyConfigSchema = z3.object({
|
|
|
2877
2927
|
auto: AutoConfigSchema.optional(),
|
|
2878
2928
|
// Context document limits (DoS prevention)
|
|
2879
2929
|
context: ContextConfigSchema.optional(),
|
|
2930
|
+
// Upstream Repository Mapping (for cross-repo issue creation)
|
|
2931
|
+
upstreamRepos: z3.record(z3.string(), z3.string()).optional(),
|
|
2880
2932
|
// Additional Context
|
|
2881
2933
|
keyFiles: z3.array(z3.string()).optional(),
|
|
2882
2934
|
avoid: z3.array(z3.string()).optional(),
|
|
@@ -3974,6 +4026,7 @@ function createInitialDashboardState() {
|
|
|
3974
4026
|
tasks: [],
|
|
3975
4027
|
eventLog: [],
|
|
3976
4028
|
toolCalls: [],
|
|
4029
|
+
activityHistory: [],
|
|
3977
4030
|
objectives: [],
|
|
3978
4031
|
activeSkills: [],
|
|
3979
4032
|
toolInvokeCount: 0,
|
|
@@ -3983,7 +4036,8 @@ function createInitialDashboardState() {
|
|
|
3983
4036
|
contextDecisions: [],
|
|
3984
4037
|
contextNotes: [],
|
|
3985
4038
|
contextMode: null,
|
|
3986
|
-
contextStatus: null
|
|
4039
|
+
contextStatus: null,
|
|
4040
|
+
discussionRounds: []
|
|
3987
4041
|
};
|
|
3988
4042
|
}
|
|
3989
4043
|
function cloneAgents(agents) {
|
|
@@ -4075,7 +4129,8 @@ function dashboardReducer(state, action) {
|
|
|
4075
4129
|
const entry = {
|
|
4076
4130
|
timestamp: new Date(action.payload.timestamp).toTimeString().slice(0, 8),
|
|
4077
4131
|
message: `${action.payload.toolName}${action.payload.agentId ? ` [${action.payload.agentId}]` : ""}`,
|
|
4078
|
-
level: "info"
|
|
4132
|
+
level: "info",
|
|
4133
|
+
rawTimestamp: action.payload.timestamp
|
|
4079
4134
|
};
|
|
4080
4135
|
const base = state.eventLog.length >= EVENT_LOG_MAX ? state.eventLog.slice(1) : state.eventLog;
|
|
4081
4136
|
const invokedAgentId = action.payload.agentId;
|
|
@@ -4103,11 +4158,24 @@ function dashboardReducer(state, action) {
|
|
|
4103
4158
|
status: "completed"
|
|
4104
4159
|
};
|
|
4105
4160
|
const toolCallsBase = state.toolCalls.length >= TOOL_CALLS_MAX ? state.toolCalls.slice(1) : state.toolCalls;
|
|
4161
|
+
const sec = Math.floor(action.payload.timestamp / 1e3);
|
|
4162
|
+
const history = state.activityHistory;
|
|
4163
|
+
const last = history.length > 0 ? history[history.length - 1] : null;
|
|
4164
|
+
let activityHistory;
|
|
4165
|
+
if (last && last.timestamp === sec) {
|
|
4166
|
+
activityHistory = [
|
|
4167
|
+
...history.slice(0, -1),
|
|
4168
|
+
{ timestamp: sec, toolCalls: last.toolCalls + 1 }
|
|
4169
|
+
];
|
|
4170
|
+
} else {
|
|
4171
|
+
activityHistory = [...history.slice(-59), { timestamp: sec, toolCalls: 1 }];
|
|
4172
|
+
}
|
|
4106
4173
|
return {
|
|
4107
4174
|
...state,
|
|
4108
4175
|
agents,
|
|
4109
4176
|
eventLog: [...base, entry],
|
|
4110
4177
|
toolCalls: [...toolCallsBase, toolCall],
|
|
4178
|
+
activityHistory,
|
|
4111
4179
|
toolInvokeCount: state.toolInvokeCount + 1
|
|
4112
4180
|
};
|
|
4113
4181
|
}
|
|
@@ -4152,6 +4220,12 @@ function dashboardReducer(state, action) {
|
|
|
4152
4220
|
contextStatus: status
|
|
4153
4221
|
};
|
|
4154
4222
|
}
|
|
4223
|
+
case "ADD_DISCUSSION_ROUND": {
|
|
4224
|
+
return {
|
|
4225
|
+
...state,
|
|
4226
|
+
discussionRounds: [...state.discussionRounds, action.payload.round]
|
|
4227
|
+
};
|
|
4228
|
+
}
|
|
4155
4229
|
case "SESSION_RESET":
|
|
4156
4230
|
return createInitialDashboardState();
|
|
4157
4231
|
case "CLEANUP_STALE_AGENTS": {
|
|
@@ -4181,7 +4255,7 @@ function dashboardReducer(state, action) {
|
|
|
4181
4255
|
}
|
|
4182
4256
|
function useDashboardState(eventBus) {
|
|
4183
4257
|
const [state, dispatch] = useReducer(dashboardReducer, void 0, createInitialDashboardState);
|
|
4184
|
-
|
|
4258
|
+
useEffect3(() => {
|
|
4185
4259
|
if (!eventBus) return;
|
|
4186
4260
|
const onActivated = (p) => dispatch({ type: "AGENT_ACTIVATED", payload: p });
|
|
4187
4261
|
const onDeactivated = (p) => dispatch({ type: "AGENT_DEACTIVATED", payload: p });
|
|
@@ -4196,6 +4270,7 @@ function useDashboardState(eventBus) {
|
|
|
4196
4270
|
const onObjectiveSet = (p) => dispatch({ type: "OBJECTIVE_SET", payload: p });
|
|
4197
4271
|
const onSessionReset = (p) => dispatch({ type: "SESSION_RESET", payload: p });
|
|
4198
4272
|
const onContextUpdated = (p) => dispatch({ type: "CONTEXT_UPDATED", payload: p });
|
|
4273
|
+
const onDiscussionRoundAdded = (p) => dispatch({ type: "ADD_DISCUSSION_ROUND", payload: p });
|
|
4199
4274
|
eventBus.on(TUI_EVENTS.AGENT_ACTIVATED, onActivated);
|
|
4200
4275
|
eventBus.on(TUI_EVENTS.AGENT_DEACTIVATED, onDeactivated);
|
|
4201
4276
|
eventBus.on(TUI_EVENTS.MODE_CHANGED, onModeChanged);
|
|
@@ -4209,6 +4284,7 @@ function useDashboardState(eventBus) {
|
|
|
4209
4284
|
eventBus.on(TUI_EVENTS.OBJECTIVE_SET, onObjectiveSet);
|
|
4210
4285
|
eventBus.on(TUI_EVENTS.SESSION_RESET, onSessionReset);
|
|
4211
4286
|
eventBus.on(TUI_EVENTS.CONTEXT_UPDATED, onContextUpdated);
|
|
4287
|
+
eventBus.on(TUI_EVENTS.DISCUSSION_ROUND_ADDED, onDiscussionRoundAdded);
|
|
4212
4288
|
return () => {
|
|
4213
4289
|
eventBus.off(TUI_EVENTS.AGENT_ACTIVATED, onActivated);
|
|
4214
4290
|
eventBus.off(TUI_EVENTS.AGENT_DEACTIVATED, onDeactivated);
|
|
@@ -4223,9 +4299,10 @@ function useDashboardState(eventBus) {
|
|
|
4223
4299
|
eventBus.off(TUI_EVENTS.OBJECTIVE_SET, onObjectiveSet);
|
|
4224
4300
|
eventBus.off(TUI_EVENTS.SESSION_RESET, onSessionReset);
|
|
4225
4301
|
eventBus.off(TUI_EVENTS.CONTEXT_UPDATED, onContextUpdated);
|
|
4302
|
+
eventBus.off(TUI_EVENTS.DISCUSSION_ROUND_ADDED, onDiscussionRoundAdded);
|
|
4226
4303
|
};
|
|
4227
4304
|
}, [eventBus]);
|
|
4228
|
-
|
|
4305
|
+
useEffect3(() => {
|
|
4229
4306
|
const cleanupInterval = setInterval(() => {
|
|
4230
4307
|
dispatch({ type: "CLEANUP_STALE_AGENTS", payload: { now: Date.now(), ttlMs: 3e4 } });
|
|
4231
4308
|
}, 1e4);
|
|
@@ -4348,6 +4425,59 @@ function getAgentAvatar(agentName) {
|
|
|
4348
4425
|
return "\u{1F916}";
|
|
4349
4426
|
}
|
|
4350
4427
|
|
|
4428
|
+
// src/tui/components/live.pure.ts
|
|
4429
|
+
function formatElapsed(startedAt, now) {
|
|
4430
|
+
const totalSec = Math.max(0, Math.floor((now - startedAt) / 1e3));
|
|
4431
|
+
const min = Math.floor(totalSec / 60);
|
|
4432
|
+
const sec = totalSec % 60;
|
|
4433
|
+
return min > 0 ? `${min}m ${sec}s` : `${sec}s`;
|
|
4434
|
+
}
|
|
4435
|
+
function formatRelativeTime(timestamp, now) {
|
|
4436
|
+
const diffSec = Math.max(0, Math.floor((now - timestamp) / 1e3));
|
|
4437
|
+
if (diffSec <= 2) return "just now";
|
|
4438
|
+
if (diffSec < 60) return `${diffSec}s ago`;
|
|
4439
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
4440
|
+
if (diffMin < 60) return `${diffMin}m ago`;
|
|
4441
|
+
const diffHr = Math.floor(diffMin / 60);
|
|
4442
|
+
return `${diffHr}h ago`;
|
|
4443
|
+
}
|
|
4444
|
+
var SPINNER_FRAMES = "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827";
|
|
4445
|
+
function spinnerFrame(tick) {
|
|
4446
|
+
return SPINNER_FRAMES[tick % 8];
|
|
4447
|
+
}
|
|
4448
|
+
function pulseIcon(tick) {
|
|
4449
|
+
return tick % 2 === 0 ? "\u25CF" : "\u25C9";
|
|
4450
|
+
}
|
|
4451
|
+
var SPARK_CHARS = "\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
|
|
4452
|
+
function renderSparkline(samples, width) {
|
|
4453
|
+
if (samples.length === 0) return "";
|
|
4454
|
+
const visible = samples.slice(-width);
|
|
4455
|
+
const min = Math.min(...visible);
|
|
4456
|
+
const max = Math.max(...visible);
|
|
4457
|
+
const range = max - min;
|
|
4458
|
+
return visible.map((v) => {
|
|
4459
|
+
if (range === 0) return SPARK_CHARS[0];
|
|
4460
|
+
const idx = Math.round((v - min) / range * 7);
|
|
4461
|
+
return SPARK_CHARS[idx];
|
|
4462
|
+
}).join("");
|
|
4463
|
+
}
|
|
4464
|
+
function computeThroughput(samples) {
|
|
4465
|
+
if (samples.length <= 1) return "0.0/min";
|
|
4466
|
+
const first = samples[0];
|
|
4467
|
+
const last = samples[samples.length - 1];
|
|
4468
|
+
const durationMin = (last.timestamp - first.timestamp) / 60;
|
|
4469
|
+
if (durationMin <= 0) return "0.0/min";
|
|
4470
|
+
const totalCalls = samples.reduce((sum, s) => sum + s.toolCalls, 0);
|
|
4471
|
+
return `${(totalCalls / durationMin).toFixed(1)}/min`;
|
|
4472
|
+
}
|
|
4473
|
+
function formatTimeWithSeconds(now) {
|
|
4474
|
+
const d = new Date(now);
|
|
4475
|
+
const h = String(d.getHours()).padStart(2, "0");
|
|
4476
|
+
const m = String(d.getMinutes()).padStart(2, "0");
|
|
4477
|
+
const s = String(d.getSeconds()).padStart(2, "0");
|
|
4478
|
+
return `${h}:${m}:${s}`;
|
|
4479
|
+
}
|
|
4480
|
+
|
|
4351
4481
|
// src/tui/components/HeaderBar.tsx
|
|
4352
4482
|
var PROCESS_MODES = ["PLAN", "ACT", "EVAL"];
|
|
4353
4483
|
function ModeFlow({ currentMode }) {
|
|
@@ -4358,17 +4488,23 @@ function ModeFlow({ currentMode }) {
|
|
|
4358
4488
|
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
4489
|
}));
|
|
4360
4490
|
}
|
|
4361
|
-
function StateIndicator({
|
|
4362
|
-
|
|
4491
|
+
function StateIndicator({
|
|
4492
|
+
globalState,
|
|
4493
|
+
tick
|
|
4494
|
+
}) {
|
|
4495
|
+
const isRunning = globalState === "RUNNING";
|
|
4496
|
+
const icon = isRunning && tick !== void 0 ? spinnerFrame(tick) : GLOBAL_STATE_ICONS[globalState];
|
|
4363
4497
|
const color = GLOBAL_STATE_COLORS[globalState];
|
|
4364
|
-
return /* @__PURE__ */ React.createElement(Text, { color, bold:
|
|
4498
|
+
return /* @__PURE__ */ React.createElement(Text, { color, bold: isRunning || globalState === "ERROR" }, icon, " ", globalState);
|
|
4365
4499
|
}
|
|
4366
4500
|
function HeaderBar({
|
|
4367
4501
|
workspace,
|
|
4368
4502
|
currentMode,
|
|
4369
4503
|
globalState,
|
|
4370
4504
|
layoutMode,
|
|
4371
|
-
width
|
|
4505
|
+
width,
|
|
4506
|
+
tick,
|
|
4507
|
+
now
|
|
4372
4508
|
}) {
|
|
4373
4509
|
if (layoutMode === "narrow") {
|
|
4374
4510
|
return /* @__PURE__ */ React.createElement(
|
|
@@ -4384,7 +4520,8 @@ function HeaderBar({
|
|
|
4384
4520
|
/* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
|
|
4385
4521
|
/* @__PURE__ */ React.createElement(ModeFlow, { currentMode }),
|
|
4386
4522
|
/* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
|
|
4387
|
-
/* @__PURE__ */ React.createElement(StateIndicator, { globalState })
|
|
4523
|
+
/* @__PURE__ */ React.createElement(StateIndicator, { globalState, tick }),
|
|
4524
|
+
now !== void 0 && /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " ", formatTimeWithSeconds(now))
|
|
4388
4525
|
);
|
|
4389
4526
|
}
|
|
4390
4527
|
return /* @__PURE__ */ React.createElement(
|
|
@@ -4396,7 +4533,7 @@ function HeaderBar({
|
|
|
4396
4533
|
overflowX: "hidden",
|
|
4397
4534
|
flexDirection: "row"
|
|
4398
4535
|
},
|
|
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 })),
|
|
4536
|
+
/* @__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
4537
|
/* @__PURE__ */ React.createElement(Box, { flexGrow: 1 }),
|
|
4401
4538
|
/* @__PURE__ */ React.createElement(Box, { flexShrink: 1, overflowX: "hidden" }, /* @__PURE__ */ React.createElement(Text, { dimColor: true, wrap: "truncate" }, workspace))
|
|
4402
4539
|
);
|
|
@@ -4915,10 +5052,18 @@ function FlowMap({
|
|
|
4915
5052
|
layoutMode,
|
|
4916
5053
|
width,
|
|
4917
5054
|
height,
|
|
4918
|
-
activeStage = null
|
|
5055
|
+
activeStage = null,
|
|
5056
|
+
tick,
|
|
5057
|
+
now
|
|
4919
5058
|
}) {
|
|
4920
5059
|
const contentWidth = Math.max(1, width - 2);
|
|
4921
5060
|
const contentHeight = Math.max(1, height - 3);
|
|
5061
|
+
const hasRunningAgents = useMemo(
|
|
5062
|
+
() => [...agents.values()].some((a) => a.status === "running"),
|
|
5063
|
+
[agents]
|
|
5064
|
+
);
|
|
5065
|
+
const liveTick = hasRunningAgents ? tick ?? 0 : 0;
|
|
5066
|
+
const liveNow = hasRunningAgents ? now : void 0;
|
|
4922
5067
|
const compactContent = useMemo(() => {
|
|
4923
5068
|
if (layoutMode !== "narrow") return null;
|
|
4924
5069
|
return renderFlowMapCompact(agents);
|
|
@@ -4928,6 +5073,20 @@ function FlowMap({
|
|
|
4928
5073
|
const buf = layoutMode === "wide" ? renderFlowMap(agents, edges, contentWidth, contentHeight, activeStage) : renderFlowMapSimplified(agents, contentWidth, contentHeight);
|
|
4929
5074
|
return buf.toLinesDirect();
|
|
4930
5075
|
}, [agents, edges, contentWidth, contentHeight, layoutMode, activeStage]);
|
|
5076
|
+
const liveOverlays = useMemo(() => {
|
|
5077
|
+
if (liveNow === void 0) return null;
|
|
5078
|
+
const overlays = [];
|
|
5079
|
+
for (const [id, agent] of agents) {
|
|
5080
|
+
if (agent.status === "running" && agent.startedAt != null) {
|
|
5081
|
+
overlays.push({
|
|
5082
|
+
id,
|
|
5083
|
+
icon: pulseIcon(liveTick),
|
|
5084
|
+
elapsed: formatElapsed(agent.startedAt, liveNow)
|
|
5085
|
+
});
|
|
5086
|
+
}
|
|
5087
|
+
}
|
|
5088
|
+
return overlays.length > 0 ? overlays : null;
|
|
5089
|
+
}, [agents, liveTick, liveNow]);
|
|
4931
5090
|
if (layoutMode === "narrow") {
|
|
4932
5091
|
return /* @__PURE__ */ React2.createElement(
|
|
4933
5092
|
Box2,
|
|
@@ -4939,7 +5098,8 @@ function FlowMap({
|
|
|
4939
5098
|
height
|
|
4940
5099
|
},
|
|
4941
5100
|
/* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "FLOW MAP"),
|
|
4942
|
-
/* @__PURE__ */ React2.createElement(Text2, null, compactContent)
|
|
5101
|
+
/* @__PURE__ */ React2.createElement(Text2, null, compactContent),
|
|
5102
|
+
liveOverlays?.map((o) => /* @__PURE__ */ React2.createElement(Text2, { key: o.id, color: "yellow" }, o.icon, " ", o.elapsed))
|
|
4943
5103
|
);
|
|
4944
5104
|
}
|
|
4945
5105
|
if (!lines) {
|
|
@@ -4965,13 +5125,162 @@ function FlowMap({
|
|
|
4965
5125
|
height
|
|
4966
5126
|
},
|
|
4967
5127
|
/* @__PURE__ */ React2.createElement(Text2, { bold: true, color: "cyan" }, "FLOW MAP"),
|
|
4968
|
-
lines.map((row, y) => /* @__PURE__ */ React2.createElement(ColorRow, { key: y, cells: row }))
|
|
5128
|
+
lines.map((row, y) => /* @__PURE__ */ React2.createElement(ColorRow, { key: y, cells: row })),
|
|
5129
|
+
liveOverlays?.map((o) => /* @__PURE__ */ React2.createElement(Text2, { key: o.id, color: "yellow" }, o.icon, " ", o.elapsed))
|
|
5130
|
+
);
|
|
5131
|
+
}
|
|
5132
|
+
|
|
5133
|
+
// src/tui/components/AgentDiscussionPanel.tsx
|
|
5134
|
+
import React3, { useMemo as useMemo2 } from "react";
|
|
5135
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
5136
|
+
|
|
5137
|
+
// src/collaboration/types.ts
|
|
5138
|
+
var STANCES = Object.freeze(["approve", "concern", "reject"]);
|
|
5139
|
+
var STANCE_ICONS = Object.freeze({
|
|
5140
|
+
approve: "\u2705",
|
|
5141
|
+
concern: "\u26A0\uFE0F",
|
|
5142
|
+
reject: "\u274C"
|
|
5143
|
+
});
|
|
5144
|
+
function calculateConsensus(opinions) {
|
|
5145
|
+
const approveCount = opinions.filter((o) => o.stance === "approve").length;
|
|
5146
|
+
const concernCount = opinions.filter((o) => o.stance === "concern").length;
|
|
5147
|
+
const rejectCount = opinions.filter((o) => o.stance === "reject").length;
|
|
5148
|
+
return {
|
|
5149
|
+
totalAgents: opinions.length,
|
|
5150
|
+
approveCount,
|
|
5151
|
+
concernCount,
|
|
5152
|
+
rejectCount,
|
|
5153
|
+
reached: opinions.length > 0 && rejectCount === 0,
|
|
5154
|
+
criticalCount: rejectCount
|
|
5155
|
+
};
|
|
5156
|
+
}
|
|
5157
|
+
|
|
5158
|
+
// src/tui/components/agent-discussion-panel.pure.ts
|
|
5159
|
+
var CROSS_REVIEW_VERBS = {
|
|
5160
|
+
approve: "agrees",
|
|
5161
|
+
concern: "notes",
|
|
5162
|
+
reject: "disagrees"
|
|
5163
|
+
};
|
|
5164
|
+
function renderOpinionLine(opinion, stanceHistory) {
|
|
5165
|
+
const avatar = getAgentAvatar(opinion.agentName);
|
|
5166
|
+
const icon = STANCE_ICONS[opinion.stance];
|
|
5167
|
+
let suffix = "";
|
|
5168
|
+
if (stanceHistory && stanceHistory.length > 1) {
|
|
5169
|
+
const lastStance = stanceHistory[stanceHistory.length - 1];
|
|
5170
|
+
const prevStance = stanceHistory[stanceHistory.length - 2];
|
|
5171
|
+
if (lastStance !== prevStance) {
|
|
5172
|
+
suffix = ` (${prevStance === "reject" || prevStance === "concern" ? "revised" : "alt"})`;
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
return {
|
|
5176
|
+
text: `${avatar} ${opinion.agentName} ${icon} ${opinion.stance}${suffix}: "${opinion.reasoning}"`,
|
|
5177
|
+
type: "opinion"
|
|
5178
|
+
};
|
|
5179
|
+
}
|
|
5180
|
+
function renderCrossReviewLine(review, agentNames) {
|
|
5181
|
+
const fromAvatar = getAgentAvatar(agentNames[review.fromAgentId] ?? "unknown");
|
|
5182
|
+
const fromName = agentNames[review.fromAgentId] ?? review.fromAgentId;
|
|
5183
|
+
const toAvatar = getAgentAvatar(agentNames[review.toAgentId] ?? "unknown");
|
|
5184
|
+
const toName = agentNames[review.toAgentId] ?? review.toAgentId;
|
|
5185
|
+
const verb = CROSS_REVIEW_VERBS[review.stance];
|
|
5186
|
+
return {
|
|
5187
|
+
text: `${fromAvatar} ${fromName} \u2192 ${toAvatar} ${toName} ${verb}: "${review.comment}"`,
|
|
5188
|
+
type: "cross-review"
|
|
5189
|
+
};
|
|
5190
|
+
}
|
|
5191
|
+
function renderConsensusLine(consensus) {
|
|
5192
|
+
const icon = consensus.reached ? "\u2705" : "\u274C";
|
|
5193
|
+
return {
|
|
5194
|
+
text: `${icon} Consensus: ${consensus.approveCount}/${consensus.totalAgents} | Critical: ${consensus.criticalCount}`,
|
|
5195
|
+
type: "consensus"
|
|
5196
|
+
};
|
|
5197
|
+
}
|
|
5198
|
+
function buildAgentNameMap(rounds) {
|
|
5199
|
+
const map = {};
|
|
5200
|
+
for (const round of rounds) {
|
|
5201
|
+
for (const opinion of round.opinions) {
|
|
5202
|
+
map[opinion.agentId] = opinion.agentName;
|
|
5203
|
+
}
|
|
5204
|
+
}
|
|
5205
|
+
return map;
|
|
5206
|
+
}
|
|
5207
|
+
function buildStanceHistories(rounds) {
|
|
5208
|
+
const histories = {};
|
|
5209
|
+
for (const round of rounds) {
|
|
5210
|
+
for (const opinion of round.opinions) {
|
|
5211
|
+
if (!histories[opinion.agentId]) {
|
|
5212
|
+
histories[opinion.agentId] = [];
|
|
5213
|
+
}
|
|
5214
|
+
histories[opinion.agentId].push(opinion.stance);
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
return histories;
|
|
5218
|
+
}
|
|
5219
|
+
function renderDiscussionPanel(rounds, _width) {
|
|
5220
|
+
if (rounds.length === 0) {
|
|
5221
|
+
return [{ text: "No agent discussion yet", type: "empty" }];
|
|
5222
|
+
}
|
|
5223
|
+
const lines = [];
|
|
5224
|
+
const agentNames = buildAgentNameMap(rounds);
|
|
5225
|
+
const stanceHistories = buildStanceHistories(rounds);
|
|
5226
|
+
const latestRound = rounds[rounds.length - 1];
|
|
5227
|
+
lines.push({ text: `\u2500\u2500 Agent Discussion \u2500\u2500`, type: "header" });
|
|
5228
|
+
for (const opinion of latestRound.opinions) {
|
|
5229
|
+
lines.push(renderOpinionLine(opinion, stanceHistories[opinion.agentId]));
|
|
5230
|
+
}
|
|
5231
|
+
for (const review of latestRound.crossReviews) {
|
|
5232
|
+
lines.push(renderCrossReviewLine(review, agentNames));
|
|
5233
|
+
}
|
|
5234
|
+
const consensus = calculateConsensus(latestRound.opinions);
|
|
5235
|
+
lines.push(renderConsensusLine(consensus));
|
|
5236
|
+
return lines;
|
|
5237
|
+
}
|
|
5238
|
+
|
|
5239
|
+
// src/tui/components/AgentDiscussionPanel.tsx
|
|
5240
|
+
var LINE_COLORS = {
|
|
5241
|
+
opinion: "white",
|
|
5242
|
+
"cross-review": "cyan",
|
|
5243
|
+
consensus: "green",
|
|
5244
|
+
header: "magenta",
|
|
5245
|
+
empty: "gray"
|
|
5246
|
+
};
|
|
5247
|
+
function AgentDiscussionPanel({
|
|
5248
|
+
rounds,
|
|
5249
|
+
width,
|
|
5250
|
+
height
|
|
5251
|
+
}) {
|
|
5252
|
+
const lines = useMemo2(
|
|
5253
|
+
() => renderDiscussionPanel(rounds, width),
|
|
5254
|
+
[rounds, width]
|
|
5255
|
+
);
|
|
5256
|
+
const maxLines = Math.max(0, height - 2);
|
|
5257
|
+
const visibleLines = lines.slice(0, maxLines);
|
|
5258
|
+
return /* @__PURE__ */ React3.createElement(
|
|
5259
|
+
Box3,
|
|
5260
|
+
{
|
|
5261
|
+
flexDirection: "column",
|
|
5262
|
+
width,
|
|
5263
|
+
height,
|
|
5264
|
+
borderStyle: "round",
|
|
5265
|
+
borderColor: BORDER_COLORS.panel
|
|
5266
|
+
},
|
|
5267
|
+
visibleLines.map((line, i) => /* @__PURE__ */ React3.createElement(
|
|
5268
|
+
Text3,
|
|
5269
|
+
{
|
|
5270
|
+
key: i,
|
|
5271
|
+
color: LINE_COLORS[line.type],
|
|
5272
|
+
bold: line.type === "header" || line.type === "consensus",
|
|
5273
|
+
dimColor: line.type === "empty",
|
|
5274
|
+
wrap: "truncate"
|
|
5275
|
+
},
|
|
5276
|
+
line.text
|
|
5277
|
+
))
|
|
4969
5278
|
);
|
|
4970
5279
|
}
|
|
4971
5280
|
|
|
4972
5281
|
// src/tui/components/FocusedAgentPanel.tsx
|
|
4973
|
-
import
|
|
4974
|
-
import { Box as
|
|
5282
|
+
import React5 from "react";
|
|
5283
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
4975
5284
|
|
|
4976
5285
|
// src/tui/components/focused-agent.pure.ts
|
|
4977
5286
|
function formatObjective(objectives, maxLines = 3) {
|
|
@@ -4985,6 +5294,13 @@ function formatLogTail(events, maxLines = 10) {
|
|
|
4985
5294
|
const tail = events.slice(-maxLines);
|
|
4986
5295
|
return tail.map((e) => `${e.timestamp} ${e.message}`).join("\n");
|
|
4987
5296
|
}
|
|
5297
|
+
function formatLogTailRelative(events, now, maxLines = 10) {
|
|
5298
|
+
const tail = events.slice(-maxLines);
|
|
5299
|
+
return tail.map((e) => {
|
|
5300
|
+
const ts = e.rawTimestamp != null ? formatRelativeTime(e.rawTimestamp, now) : e.timestamp;
|
|
5301
|
+
return `${ts} ${e.message}`;
|
|
5302
|
+
}).join("\n");
|
|
5303
|
+
}
|
|
4988
5304
|
function formatSectionDivider(title, width = 50) {
|
|
4989
5305
|
const prefix = "\u2500\u2500\u2500 ";
|
|
4990
5306
|
const suffix = " ";
|
|
@@ -5010,8 +5326,8 @@ function formatEnhancedChecklist(tasks, maxItems = 6) {
|
|
|
5010
5326
|
}
|
|
5011
5327
|
|
|
5012
5328
|
// src/tui/components/ContextSection.tsx
|
|
5013
|
-
import
|
|
5014
|
-
import { Box as
|
|
5329
|
+
import React4 from "react";
|
|
5330
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
5015
5331
|
|
|
5016
5332
|
// src/tui/components/context-section.pure.ts
|
|
5017
5333
|
function formatContextDecisions(decisions, maxItems = 5) {
|
|
@@ -5041,27 +5357,27 @@ function ContextSection({
|
|
|
5041
5357
|
const hasDecisions = decisions.length > 0;
|
|
5042
5358
|
const hasNotes = notes.length > 0;
|
|
5043
5359
|
if (!hasDecisions && !hasNotes) return null;
|
|
5044
|
-
return /* @__PURE__ */
|
|
5360
|
+
return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, hasDecisions && /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true, bold: true }, "Decisions"), formatContextDecisions(decisions)?.split("\n").map((line, i) => /* @__PURE__ */ React4.createElement(Text4, { key: i, color: "cyan" }, line))), hasNotes && /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true, bold: true }, "Notes"), formatContextNotes(notes)?.split("\n").map((line, i) => /* @__PURE__ */ React4.createElement(Text4, { key: i, dimColor: true }, line))));
|
|
5045
5361
|
}
|
|
5046
5362
|
|
|
5047
5363
|
// src/tui/components/FocusedAgentPanel.tsx
|
|
5048
5364
|
function SectionDivider({ title }) {
|
|
5049
|
-
return /* @__PURE__ */
|
|
5365
|
+
return /* @__PURE__ */ React5.createElement(Text5, { color: "magenta" }, formatSectionDivider(title));
|
|
5050
5366
|
}
|
|
5051
5367
|
function LogSection({
|
|
5052
5368
|
logs,
|
|
5053
5369
|
eventLog
|
|
5054
5370
|
}) {
|
|
5055
|
-
if (!logs) return /* @__PURE__ */
|
|
5371
|
+
if (!logs) return /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "No events");
|
|
5056
5372
|
const logLines = logs.split("\n");
|
|
5057
5373
|
const offset = eventLog.length - logLines.length;
|
|
5058
|
-
return /* @__PURE__ */
|
|
5374
|
+
return /* @__PURE__ */ React5.createElement(React5.Fragment, null, logLines.map((line, i) => {
|
|
5059
5375
|
const ev = eventLog[offset + i];
|
|
5060
5376
|
const isError = ev?.level === "error";
|
|
5061
5377
|
const spaceIdx = line.indexOf(" ");
|
|
5062
5378
|
const timestamp = spaceIdx > 0 ? line.slice(0, spaceIdx) : line;
|
|
5063
5379
|
const message = spaceIdx > 0 ? line.slice(spaceIdx + 1) : "";
|
|
5064
|
-
return /* @__PURE__ */
|
|
5380
|
+
return /* @__PURE__ */ React5.createElement(Box5, { key: i, gap: 1 }, /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, timestamp), /* @__PURE__ */ React5.createElement(Text5, { color: isError ? "red" : void 0 }, message));
|
|
5065
5381
|
}));
|
|
5066
5382
|
}
|
|
5067
5383
|
function FocusedAgentPanel({
|
|
@@ -5071,12 +5387,14 @@ function FocusedAgentPanel({
|
|
|
5071
5387
|
eventLog,
|
|
5072
5388
|
contextDecisions = [],
|
|
5073
5389
|
contextNotes = [],
|
|
5390
|
+
tick,
|
|
5391
|
+
now,
|
|
5074
5392
|
width,
|
|
5075
5393
|
height
|
|
5076
5394
|
}) {
|
|
5077
5395
|
if (!agent) {
|
|
5078
|
-
return /* @__PURE__ */
|
|
5079
|
-
|
|
5396
|
+
return /* @__PURE__ */ React5.createElement(
|
|
5397
|
+
Box5,
|
|
5080
5398
|
{
|
|
5081
5399
|
borderStyle: "single",
|
|
5082
5400
|
borderColor: BORDER_COLORS.panel,
|
|
@@ -5084,7 +5402,7 @@ function FocusedAgentPanel({
|
|
|
5084
5402
|
width,
|
|
5085
5403
|
height
|
|
5086
5404
|
},
|
|
5087
|
-
/* @__PURE__ */
|
|
5405
|
+
/* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "No agent focused")
|
|
5088
5406
|
);
|
|
5089
5407
|
}
|
|
5090
5408
|
const avatar = getAgentAvatar(agent.name);
|
|
@@ -5093,9 +5411,12 @@ function FocusedAgentPanel({
|
|
|
5093
5411
|
const statusLabel = agent.status.toUpperCase();
|
|
5094
5412
|
const progressBar = formatEnhancedProgressBar(agent.progress);
|
|
5095
5413
|
const objective = formatObjective(objectives);
|
|
5096
|
-
const logs = formatLogTail(eventLog);
|
|
5097
|
-
|
|
5098
|
-
|
|
5414
|
+
const logs = now != null ? formatLogTailRelative(eventLog, now) : formatLogTail(eventLog);
|
|
5415
|
+
const isRunning = agent.status === "running";
|
|
5416
|
+
const showSpinner = isRunning && tick != null;
|
|
5417
|
+
const showElapsed = isRunning && now != null && agent.startedAt != null;
|
|
5418
|
+
return /* @__PURE__ */ React5.createElement(
|
|
5419
|
+
Box5,
|
|
5099
5420
|
{
|
|
5100
5421
|
borderStyle: "single",
|
|
5101
5422
|
borderColor: BORDER_COLORS.panel,
|
|
@@ -5103,22 +5424,22 @@ function FocusedAgentPanel({
|
|
|
5103
5424
|
width,
|
|
5104
5425
|
height
|
|
5105
5426
|
},
|
|
5106
|
-
/* @__PURE__ */
|
|
5107
|
-
/* @__PURE__ */
|
|
5108
|
-
/* @__PURE__ */
|
|
5109
|
-
objective ? /* @__PURE__ */
|
|
5110
|
-
/* @__PURE__ */
|
|
5111
|
-
activeSkills.length > 0 ? activeSkills.map((s, i) => /* @__PURE__ */
|
|
5112
|
-
/* @__PURE__ */
|
|
5113
|
-
contextDecisions.length > 0 || contextNotes.length > 0 ? /* @__PURE__ */
|
|
5114
|
-
/* @__PURE__ */
|
|
5115
|
-
/* @__PURE__ */
|
|
5427
|
+
/* @__PURE__ */ React5.createElement(Box5, { gap: 2 }, /* @__PURE__ */ React5.createElement(Text5, null, avatar), /* @__PURE__ */ React5.createElement(Text5, { bold: true }, agent.name), showSpinner ? /* @__PURE__ */ React5.createElement(Text5, { color: "cyan" }, spinnerFrame(tick)) : /* @__PURE__ */ React5.createElement(Text5, { color: statusColor, bold: true }, icon), /* @__PURE__ */ React5.createElement(Text5, { color: statusColor }, statusLabel), showElapsed && /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, formatElapsed(agent.startedAt, now)), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, agent.stage)),
|
|
5428
|
+
/* @__PURE__ */ React5.createElement(Box5, { gap: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "magenta" }, progressBar.bar), /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, progressBar.label)),
|
|
5429
|
+
/* @__PURE__ */ React5.createElement(SectionDivider, { title: "Objective" }),
|
|
5430
|
+
objective ? /* @__PURE__ */ React5.createElement(Text5, null, objective) : /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "No objectives"),
|
|
5431
|
+
/* @__PURE__ */ React5.createElement(SectionDivider, { title: "Skills" }),
|
|
5432
|
+
activeSkills.length > 0 ? activeSkills.map((s, i) => /* @__PURE__ */ React5.createElement(Text5, { key: i }, " ", s)) : /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "No skills"),
|
|
5433
|
+
/* @__PURE__ */ React5.createElement(SectionDivider, { title: "Context" }),
|
|
5434
|
+
contextDecisions.length > 0 || contextNotes.length > 0 ? /* @__PURE__ */ React5.createElement(ContextSection, { decisions: contextDecisions, notes: contextNotes, width }) : /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, "No context"),
|
|
5435
|
+
/* @__PURE__ */ React5.createElement(SectionDivider, { title: "Event Log" }),
|
|
5436
|
+
/* @__PURE__ */ React5.createElement(LogSection, { logs, eventLog })
|
|
5116
5437
|
);
|
|
5117
5438
|
}
|
|
5118
5439
|
|
|
5119
5440
|
// src/tui/components/ChecklistPanel.tsx
|
|
5120
|
-
import
|
|
5121
|
-
import { Box as
|
|
5441
|
+
import React6 from "react";
|
|
5442
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
5122
5443
|
|
|
5123
5444
|
// src/tui/components/checklist-panel.pure.ts
|
|
5124
5445
|
function resolveChecklistTasks(tasks, contextDecisions, contextNotes) {
|
|
@@ -5146,8 +5467,8 @@ function ChecklistPanel({
|
|
|
5146
5467
|
}) {
|
|
5147
5468
|
const resolvedTasks = resolveChecklistTasks(tasks, contextDecisions, contextNotes);
|
|
5148
5469
|
const checklist = formatEnhancedChecklist(resolvedTasks);
|
|
5149
|
-
return /* @__PURE__ */
|
|
5150
|
-
|
|
5470
|
+
return /* @__PURE__ */ React6.createElement(
|
|
5471
|
+
Box6,
|
|
5151
5472
|
{
|
|
5152
5473
|
borderStyle: "single",
|
|
5153
5474
|
borderColor: BORDER_COLORS.panel,
|
|
@@ -5155,17 +5476,17 @@ function ChecklistPanel({
|
|
|
5155
5476
|
width,
|
|
5156
5477
|
height
|
|
5157
5478
|
},
|
|
5158
|
-
/* @__PURE__ */
|
|
5479
|
+
/* @__PURE__ */ React6.createElement(Text6, { bold: true, dimColor: true }, "\u2500\u2500\u2500 Checklist"),
|
|
5159
5480
|
checklist.split("\n").map((line, i) => {
|
|
5160
5481
|
const isCompleted = line.includes("\u2714");
|
|
5161
|
-
return /* @__PURE__ */
|
|
5482
|
+
return /* @__PURE__ */ React6.createElement(Text6, { key: i, color: isCompleted ? "green" : void 0 }, line);
|
|
5162
5483
|
})
|
|
5163
5484
|
);
|
|
5164
5485
|
}
|
|
5165
5486
|
|
|
5166
5487
|
// src/tui/components/StageHealthBar.tsx
|
|
5167
|
-
import
|
|
5168
|
-
import { Box as
|
|
5488
|
+
import React7 from "react";
|
|
5489
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
5169
5490
|
|
|
5170
5491
|
// src/tui/components/stage-health.pure.ts
|
|
5171
5492
|
function formatCount(n) {
|
|
@@ -5233,29 +5554,29 @@ function StageStatDisplay({
|
|
|
5233
5554
|
const parts = [];
|
|
5234
5555
|
if (stats.running > 0)
|
|
5235
5556
|
parts.push(
|
|
5236
|
-
/* @__PURE__ */
|
|
5557
|
+
/* @__PURE__ */ React7.createElement(Text7, { key: "r", color: "green" }, " ", "\u25CF ", stats.running, " running")
|
|
5237
5558
|
);
|
|
5238
5559
|
if (stats.blocked > 0)
|
|
5239
5560
|
parts.push(
|
|
5240
|
-
/* @__PURE__ */
|
|
5561
|
+
/* @__PURE__ */ React7.createElement(Text7, { key: "b", color: "yellow" }, " ", "\u23F8 ", stats.blocked, " blocked")
|
|
5241
5562
|
);
|
|
5242
5563
|
if (stats.waiting > 0)
|
|
5243
5564
|
parts.push(
|
|
5244
|
-
/* @__PURE__ */
|
|
5565
|
+
/* @__PURE__ */ React7.createElement(Text7, { key: "w", dimColor: true }, " ", "\u25CB ", stats.waiting, " waiting")
|
|
5245
5566
|
);
|
|
5246
5567
|
if (stats.done > 0)
|
|
5247
5568
|
parts.push(
|
|
5248
|
-
/* @__PURE__ */
|
|
5569
|
+
/* @__PURE__ */ React7.createElement(Text7, { key: "d", color: "green" }, " ", "\u2713 ", stats.done)
|
|
5249
5570
|
);
|
|
5250
5571
|
if (stats.error > 0)
|
|
5251
5572
|
parts.push(
|
|
5252
|
-
/* @__PURE__ */
|
|
5573
|
+
/* @__PURE__ */ React7.createElement(Text7, { key: "e", color: "red", bold: true }, " ", "! ", stats.error, " err")
|
|
5253
5574
|
);
|
|
5254
5575
|
if (parts.length === 0)
|
|
5255
5576
|
parts.push(
|
|
5256
|
-
/* @__PURE__ */
|
|
5577
|
+
/* @__PURE__ */ React7.createElement(Text7, { key: "idle", dimColor: true }, " ", "idle")
|
|
5257
5578
|
);
|
|
5258
|
-
return /* @__PURE__ */
|
|
5579
|
+
return /* @__PURE__ */ React7.createElement(Box7, null, /* @__PURE__ */ React7.createElement(Text7, { color, bold: true }, mode, ":"), parts);
|
|
5259
5580
|
}
|
|
5260
5581
|
function StageHealthBar({
|
|
5261
5582
|
stageHealth,
|
|
@@ -5263,23 +5584,30 @@ function StageHealthBar({
|
|
|
5263
5584
|
toolCount,
|
|
5264
5585
|
agentCount,
|
|
5265
5586
|
skillCount,
|
|
5266
|
-
width
|
|
5587
|
+
width,
|
|
5588
|
+
activityHistory,
|
|
5589
|
+
tick: _tick,
|
|
5590
|
+
now: _now
|
|
5267
5591
|
}) {
|
|
5268
|
-
|
|
5269
|
-
|
|
5592
|
+
const hasActivity = activityHistory && activityHistory.length > 0;
|
|
5593
|
+
return /* @__PURE__ */ React7.createElement(
|
|
5594
|
+
Box7,
|
|
5270
5595
|
{
|
|
5271
5596
|
borderStyle: "double",
|
|
5272
5597
|
borderColor: BORDER_COLORS.panel,
|
|
5273
5598
|
width,
|
|
5274
5599
|
flexDirection: "column"
|
|
5275
5600
|
},
|
|
5276
|
-
/* @__PURE__ */
|
|
5601
|
+
/* @__PURE__ */ React7.createElement(Box7, null, hasActivity && /* @__PURE__ */ React7.createElement(Box7, { gap: 1, marginRight: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "cyan" }, renderSparkline(
|
|
5602
|
+
activityHistory.map((s) => s.toolCalls),
|
|
5603
|
+
10
|
|
5604
|
+
)), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, computeThroughput(activityHistory))), /* @__PURE__ */ React7.createElement(Box7, { gap: 2 }, ["PLAN", "ACT", "EVAL"].map((mode) => /* @__PURE__ */ React7.createElement(StageStatDisplay, { key: mode, mode, stats: stageHealth[mode] }))), /* @__PURE__ */ React7.createElement(Box7, { flexGrow: 1 }), /* @__PURE__ */ React7.createElement(Box7, { gap: 2 }, bottlenecks.length > 0 && /* @__PURE__ */ React7.createElement(Text7, { color: "red", bold: true }, "\u26A1 Bottlenecks: ", bottlenecks.join(" / ")), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "\u{1F916} ", formatCount(agentCount)), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "\u2699 ", formatCount(skillCount)), /* @__PURE__ */ React7.createElement(Text7, { dimColor: true }, "\u{1F527} ", formatCount(toolCount))))
|
|
5277
5605
|
);
|
|
5278
5606
|
}
|
|
5279
5607
|
|
|
5280
5608
|
// src/tui/components/ActivityVisualizer.tsx
|
|
5281
|
-
import
|
|
5282
|
-
import { Box as
|
|
5609
|
+
import React8, { useMemo as useMemo3 } from "react";
|
|
5610
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
5283
5611
|
|
|
5284
5612
|
// src/tui/utils/display-width.ts
|
|
5285
5613
|
function isWide(code) {
|
|
@@ -5448,11 +5776,11 @@ function ActivityVisualizer({
|
|
|
5448
5776
|
const treeWidth = Math.floor(width * 0.6);
|
|
5449
5777
|
const cardWidth = width - treeWidth;
|
|
5450
5778
|
const contentHeight = Math.max(1, height - 2);
|
|
5451
|
-
const treeLines =
|
|
5779
|
+
const treeLines = useMemo3(
|
|
5452
5780
|
() => renderAgentTree(agents, edges, activeSkills, Math.max(1, treeWidth - 2), contentHeight),
|
|
5453
5781
|
[agents, edges, activeSkills, treeWidth, contentHeight]
|
|
5454
5782
|
);
|
|
5455
|
-
const cardLines =
|
|
5783
|
+
const cardLines = useMemo3(
|
|
5456
5784
|
() => renderAgentStatusCard(
|
|
5457
5785
|
focusedAgent,
|
|
5458
5786
|
currentMode,
|
|
@@ -5464,10 +5792,10 @@ function ActivityVisualizer({
|
|
|
5464
5792
|
[focusedAgent, currentMode, objectives, activeSkills, cardWidth, contentHeight]
|
|
5465
5793
|
);
|
|
5466
5794
|
if (width <= 0 || height <= 0) {
|
|
5467
|
-
return /* @__PURE__ */
|
|
5795
|
+
return /* @__PURE__ */ React8.createElement(Box8, null);
|
|
5468
5796
|
}
|
|
5469
|
-
return /* @__PURE__ */
|
|
5470
|
-
|
|
5797
|
+
return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "row", width, height }, /* @__PURE__ */ React8.createElement(
|
|
5798
|
+
Box8,
|
|
5471
5799
|
{
|
|
5472
5800
|
borderStyle: "single",
|
|
5473
5801
|
borderColor: BORDER_COLORS.panel,
|
|
@@ -5475,9 +5803,9 @@ function ActivityVisualizer({
|
|
|
5475
5803
|
width: treeWidth,
|
|
5476
5804
|
height
|
|
5477
5805
|
},
|
|
5478
|
-
treeLines.map((line, i) => /* @__PURE__ */
|
|
5479
|
-
), /* @__PURE__ */
|
|
5480
|
-
|
|
5806
|
+
treeLines.map((line, i) => /* @__PURE__ */ React8.createElement(Text8, { key: i }, line))
|
|
5807
|
+
), /* @__PURE__ */ React8.createElement(
|
|
5808
|
+
Box8,
|
|
5481
5809
|
{
|
|
5482
5810
|
borderStyle: "single",
|
|
5483
5811
|
borderColor: BORDER_COLORS.panel,
|
|
@@ -5485,7 +5813,7 @@ function ActivityVisualizer({
|
|
|
5485
5813
|
width: cardWidth,
|
|
5486
5814
|
height
|
|
5487
5815
|
},
|
|
5488
|
-
cardLines.map((line, i) => /* @__PURE__ */
|
|
5816
|
+
cardLines.map((line, i) => /* @__PURE__ */ React8.createElement(Text8, { key: i }, line))
|
|
5489
5817
|
));
|
|
5490
5818
|
}
|
|
5491
5819
|
|
|
@@ -5571,25 +5899,29 @@ function DashboardApp({
|
|
|
5571
5899
|
workspace: workspaceProp
|
|
5572
5900
|
}) {
|
|
5573
5901
|
const { columns, rows, layoutMode } = useTerminalSize();
|
|
5902
|
+
const tick = useTick(1e3);
|
|
5903
|
+
const now = useMemo4(() => Date.now(), [tick]);
|
|
5574
5904
|
const internalState = useDashboardState(externalState ? void 0 : eventBus);
|
|
5575
5905
|
const state = externalState ?? internalState;
|
|
5576
5906
|
const focusedAgent = state.focusedAgentId ? state.agents.get(state.focusedAgentId) ?? null : null;
|
|
5577
|
-
const stageHealth =
|
|
5578
|
-
const bottlenecks =
|
|
5579
|
-
const grid =
|
|
5907
|
+
const stageHealth = useMemo4(() => computeStageHealth(state.agents), [state.agents]);
|
|
5908
|
+
const bottlenecks = useMemo4(() => detectBottlenecks(state.eventLog), [state.eventLog]);
|
|
5909
|
+
const grid = useMemo4(
|
|
5580
5910
|
() => computeGridLayout(columns, rows, layoutMode),
|
|
5581
5911
|
[columns, rows, layoutMode]
|
|
5582
5912
|
);
|
|
5583
|
-
return /* @__PURE__ */
|
|
5913
|
+
return /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", width: grid.total.width, height: grid.total.height }, /* @__PURE__ */ React9.createElement(
|
|
5584
5914
|
HeaderBar,
|
|
5585
5915
|
{
|
|
5586
5916
|
workspace: workspaceProp ?? state.workspace,
|
|
5587
5917
|
currentMode: state.currentMode,
|
|
5588
5918
|
globalState: state.globalState,
|
|
5589
5919
|
layoutMode,
|
|
5590
|
-
width: grid.header.width
|
|
5920
|
+
width: grid.header.width,
|
|
5921
|
+
tick,
|
|
5922
|
+
now
|
|
5591
5923
|
}
|
|
5592
|
-
), layoutMode === "narrow" ? /* @__PURE__ */
|
|
5924
|
+
), layoutMode === "narrow" ? /* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column" }, grid.checklistPanel.height > 0 && /* @__PURE__ */ React9.createElement(
|
|
5593
5925
|
ChecklistPanel,
|
|
5594
5926
|
{
|
|
5595
5927
|
tasks: state.tasks,
|
|
@@ -5598,7 +5930,7 @@ function DashboardApp({
|
|
|
5598
5930
|
width: grid.checklistPanel.width,
|
|
5599
5931
|
height: grid.checklistPanel.height
|
|
5600
5932
|
}
|
|
5601
|
-
), /* @__PURE__ */
|
|
5933
|
+
), /* @__PURE__ */ React9.createElement(
|
|
5602
5934
|
FocusedAgentPanel,
|
|
5603
5935
|
{
|
|
5604
5936
|
agent: focusedAgent,
|
|
@@ -5608,9 +5940,18 @@ function DashboardApp({
|
|
|
5608
5940
|
contextDecisions: state.contextDecisions,
|
|
5609
5941
|
contextNotes: state.contextNotes,
|
|
5610
5942
|
width: grid.focusedAgent.width,
|
|
5611
|
-
height: grid.focusedAgent.height
|
|
5943
|
+
height: grid.focusedAgent.height,
|
|
5944
|
+
tick,
|
|
5945
|
+
now
|
|
5612
5946
|
}
|
|
5613
|
-
), /* @__PURE__ */
|
|
5947
|
+
), state.discussionRounds.length > 0 ? /* @__PURE__ */ React9.createElement(
|
|
5948
|
+
AgentDiscussionPanel,
|
|
5949
|
+
{
|
|
5950
|
+
rounds: state.discussionRounds,
|
|
5951
|
+
width: grid.flowMap.width,
|
|
5952
|
+
height: grid.flowMap.height
|
|
5953
|
+
}
|
|
5954
|
+
) : /* @__PURE__ */ React9.createElement(
|
|
5614
5955
|
FlowMap,
|
|
5615
5956
|
{
|
|
5616
5957
|
agents: state.agents,
|
|
@@ -5618,16 +5959,25 @@ function DashboardApp({
|
|
|
5618
5959
|
layoutMode,
|
|
5619
5960
|
width: grid.flowMap.width,
|
|
5620
5961
|
height: grid.flowMap.height,
|
|
5621
|
-
activeStage: state.currentMode
|
|
5962
|
+
activeStage: state.currentMode,
|
|
5963
|
+
tick,
|
|
5964
|
+
now
|
|
5622
5965
|
}
|
|
5623
|
-
)) : /* @__PURE__ */
|
|
5624
|
-
|
|
5966
|
+
)) : /* @__PURE__ */ React9.createElement(
|
|
5967
|
+
Box9,
|
|
5625
5968
|
{
|
|
5626
5969
|
flexDirection: "row",
|
|
5627
5970
|
width: grid.total.width,
|
|
5628
5971
|
height: grid.checklistPanel.height + grid.focusedAgent.height
|
|
5629
5972
|
},
|
|
5630
|
-
/* @__PURE__ */
|
|
5973
|
+
/* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", width: grid.flowMap.width }, state.discussionRounds.length > 0 ? /* @__PURE__ */ React9.createElement(
|
|
5974
|
+
AgentDiscussionPanel,
|
|
5975
|
+
{
|
|
5976
|
+
rounds: state.discussionRounds,
|
|
5977
|
+
width: grid.flowMap.width,
|
|
5978
|
+
height: grid.flowMap.height
|
|
5979
|
+
}
|
|
5980
|
+
) : /* @__PURE__ */ React9.createElement(
|
|
5631
5981
|
FlowMap,
|
|
5632
5982
|
{
|
|
5633
5983
|
agents: state.agents,
|
|
@@ -5635,9 +5985,11 @@ function DashboardApp({
|
|
|
5635
5985
|
layoutMode,
|
|
5636
5986
|
width: grid.flowMap.width,
|
|
5637
5987
|
height: grid.flowMap.height,
|
|
5638
|
-
activeStage: state.currentMode
|
|
5988
|
+
activeStage: state.currentMode,
|
|
5989
|
+
tick,
|
|
5990
|
+
now
|
|
5639
5991
|
}
|
|
5640
|
-
), /* @__PURE__ */
|
|
5992
|
+
), /* @__PURE__ */ React9.createElement(
|
|
5641
5993
|
ActivityVisualizer,
|
|
5642
5994
|
{
|
|
5643
5995
|
currentMode: state.currentMode,
|
|
@@ -5650,7 +6002,7 @@ function DashboardApp({
|
|
|
5650
6002
|
height: grid.monitorPanel.height
|
|
5651
6003
|
}
|
|
5652
6004
|
)),
|
|
5653
|
-
/* @__PURE__ */
|
|
6005
|
+
/* @__PURE__ */ React9.createElement(Box9, { flexDirection: "column", width: grid.checklistPanel.width }, /* @__PURE__ */ React9.createElement(
|
|
5654
6006
|
ChecklistPanel,
|
|
5655
6007
|
{
|
|
5656
6008
|
tasks: state.tasks,
|
|
@@ -5659,7 +6011,7 @@ function DashboardApp({
|
|
|
5659
6011
|
width: grid.checklistPanel.width,
|
|
5660
6012
|
height: grid.checklistPanel.height
|
|
5661
6013
|
}
|
|
5662
|
-
), /* @__PURE__ */
|
|
6014
|
+
), /* @__PURE__ */ React9.createElement(
|
|
5663
6015
|
FocusedAgentPanel,
|
|
5664
6016
|
{
|
|
5665
6017
|
agent: focusedAgent,
|
|
@@ -5669,10 +6021,12 @@ function DashboardApp({
|
|
|
5669
6021
|
contextDecisions: state.contextDecisions,
|
|
5670
6022
|
contextNotes: state.contextNotes,
|
|
5671
6023
|
width: grid.focusedAgent.width,
|
|
5672
|
-
height: grid.focusedAgent.height
|
|
6024
|
+
height: grid.focusedAgent.height,
|
|
6025
|
+
tick,
|
|
6026
|
+
now
|
|
5673
6027
|
}
|
|
5674
6028
|
))
|
|
5675
|
-
), /* @__PURE__ */
|
|
6029
|
+
), /* @__PURE__ */ React9.createElement(
|
|
5676
6030
|
StageHealthBar,
|
|
5677
6031
|
{
|
|
5678
6032
|
stageHealth,
|
|
@@ -5680,18 +6034,21 @@ function DashboardApp({
|
|
|
5680
6034
|
toolCount: state.toolInvokeCount,
|
|
5681
6035
|
agentCount: state.agentActivateCount,
|
|
5682
6036
|
skillCount: state.skillInvokeCount,
|
|
5683
|
-
width: grid.stageHealth.width
|
|
6037
|
+
width: grid.stageHealth.width,
|
|
6038
|
+
activityHistory: state.activityHistory,
|
|
6039
|
+
tick,
|
|
6040
|
+
now
|
|
5684
6041
|
}
|
|
5685
6042
|
));
|
|
5686
6043
|
}
|
|
5687
6044
|
|
|
5688
6045
|
// src/tui/multi-session-app.tsx
|
|
5689
|
-
import
|
|
5690
|
-
import { Box as
|
|
6046
|
+
import React11, { useMemo as useMemo5, useCallback as useCallback2 } from "react";
|
|
6047
|
+
import { Box as Box11, useInput } from "ink";
|
|
5691
6048
|
import * as path8 from "path";
|
|
5692
6049
|
|
|
5693
6050
|
// src/tui/hooks/use-multi-session-state.ts
|
|
5694
|
-
import { useState as
|
|
6051
|
+
import { useState as useState3, useCallback, useEffect as useEffect4, useRef } from "react";
|
|
5695
6052
|
function toSessionState(managed) {
|
|
5696
6053
|
return {
|
|
5697
6054
|
pid: managed.instance.pid,
|
|
@@ -5711,10 +6068,10 @@ function getPidArray(sessions) {
|
|
|
5711
6068
|
return [...sessions.keys()];
|
|
5712
6069
|
}
|
|
5713
6070
|
function useMultiSessionState(manager) {
|
|
5714
|
-
const [sessions, setSessions] =
|
|
6071
|
+
const [sessions, setSessions] = useState3(
|
|
5715
6072
|
() => buildInitialSessions(manager)
|
|
5716
6073
|
);
|
|
5717
|
-
const [activeSessionPid, setActiveSessionPid] =
|
|
6074
|
+
const [activeSessionPid, setActiveSessionPid] = useState3(() => {
|
|
5718
6075
|
const initial = manager.getSessions();
|
|
5719
6076
|
return initial.length > 0 ? initial[0].instance.pid : null;
|
|
5720
6077
|
});
|
|
@@ -5789,7 +6146,7 @@ function useMultiSessionState(manager) {
|
|
|
5789
6146
|
eventCleanupRef.current.delete(pid);
|
|
5790
6147
|
}
|
|
5791
6148
|
}, []);
|
|
5792
|
-
|
|
6149
|
+
useEffect4(() => {
|
|
5793
6150
|
for (const managed of manager.getSessions()) {
|
|
5794
6151
|
subscribeSession(managed.instance.pid, managed.eventBus);
|
|
5795
6152
|
}
|
|
@@ -5843,8 +6200,8 @@ function useMultiSessionState(manager) {
|
|
|
5843
6200
|
}
|
|
5844
6201
|
|
|
5845
6202
|
// src/tui/components/SessionTabBar.tsx
|
|
5846
|
-
import
|
|
5847
|
-
import { Box as
|
|
6203
|
+
import React10 from "react";
|
|
6204
|
+
import { Box as Box10, Text as Text9 } from "ink";
|
|
5848
6205
|
|
|
5849
6206
|
// src/tui/components/session-tab-bar.pure.ts
|
|
5850
6207
|
var STATUS_ICONS2 = {
|
|
@@ -5898,14 +6255,14 @@ function SessionTabBar({
|
|
|
5898
6255
|
if (formatted === "") {
|
|
5899
6256
|
return null;
|
|
5900
6257
|
}
|
|
5901
|
-
return /* @__PURE__ */
|
|
6258
|
+
return /* @__PURE__ */ React10.createElement(Box10, { width, height: 1 }, /* @__PURE__ */ React10.createElement(Text9, null, formatted));
|
|
5902
6259
|
}
|
|
5903
6260
|
|
|
5904
6261
|
// src/tui/multi-session-app.tsx
|
|
5905
6262
|
function MultiSessionApp({ manager }) {
|
|
5906
6263
|
const { columns, layoutMode } = useTerminalSize();
|
|
5907
6264
|
const { sessions, activeSessionPid, switchNext, switchPrev, switchByIndex } = useMultiSessionState(manager);
|
|
5908
|
-
const tabs =
|
|
6265
|
+
const tabs = useMemo5(() => {
|
|
5909
6266
|
let index = 0;
|
|
5910
6267
|
const result = [];
|
|
5911
6268
|
for (const [pid, sessionState] of sessions) {
|
|
@@ -5920,13 +6277,13 @@ function MultiSessionApp({ manager }) {
|
|
|
5920
6277
|
}
|
|
5921
6278
|
return result;
|
|
5922
6279
|
}, [sessions, activeSessionPid]);
|
|
5923
|
-
const activeEventBus =
|
|
6280
|
+
const activeEventBus = useMemo5(() => {
|
|
5924
6281
|
if (activeSessionPid === null) return void 0;
|
|
5925
6282
|
const managedSessions = manager.getSessions();
|
|
5926
6283
|
const found = managedSessions.find((s) => s.instance.pid === activeSessionPid);
|
|
5927
6284
|
return found?.eventBus;
|
|
5928
6285
|
}, [manager, activeSessionPid]);
|
|
5929
|
-
const activeProjectRoot =
|
|
6286
|
+
const activeProjectRoot = useMemo5(() => {
|
|
5930
6287
|
if (activeSessionPid === null) return void 0;
|
|
5931
6288
|
return sessions.get(activeSessionPid)?.projectRoot;
|
|
5932
6289
|
}, [sessions, activeSessionPid]);
|
|
@@ -5948,7 +6305,7 @@ function MultiSessionApp({ manager }) {
|
|
|
5948
6305
|
[switchNext, switchPrev, switchByIndex]
|
|
5949
6306
|
);
|
|
5950
6307
|
useInput(handleInput);
|
|
5951
|
-
return /* @__PURE__ */
|
|
6308
|
+
return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(SessionTabBar, { sessions: tabs, width: columns, layoutMode }), /* @__PURE__ */ React11.createElement(
|
|
5952
6309
|
DashboardApp,
|
|
5953
6310
|
{
|
|
5954
6311
|
key: activeSessionPid ?? "none",
|
|
@@ -5993,35 +6350,13 @@ function createDefaultAgentState(params) {
|
|
|
5993
6350
|
return state;
|
|
5994
6351
|
}
|
|
5995
6352
|
|
|
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
6353
|
// src/tui/index.tsx
|
|
6019
6354
|
function startTui(options) {
|
|
6020
6355
|
const renderOptions = options.stdout ? { stdout: options.stdout } : {};
|
|
6021
|
-
return render(/* @__PURE__ */
|
|
6356
|
+
return render(/* @__PURE__ */ React12.createElement(DashboardApp, { eventBus: options.eventBus }), renderOptions);
|
|
6022
6357
|
}
|
|
6023
6358
|
function renderMultiSession(options) {
|
|
6024
|
-
return render(/* @__PURE__ */
|
|
6359
|
+
return render(/* @__PURE__ */ React12.createElement(MultiSessionApp, { manager: options.manager }));
|
|
6025
6360
|
}
|
|
6026
6361
|
export {
|
|
6027
6362
|
AGENT_STATUSES,
|
|
@@ -6035,9 +6370,9 @@ export {
|
|
|
6035
6370
|
getLayoutMode,
|
|
6036
6371
|
renderMultiSession,
|
|
6037
6372
|
startTui,
|
|
6038
|
-
useClock,
|
|
6039
6373
|
useDashboardState,
|
|
6040
|
-
useTerminalSize
|
|
6374
|
+
useTerminalSize,
|
|
6375
|
+
useTick
|
|
6041
6376
|
};
|
|
6042
6377
|
/*! Bundled license information:
|
|
6043
6378
|
|