u-foo 2.3.32 → 2.4.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/README.md +157 -213
- package/README.zh-CN.md +151 -197
- package/SKILLS/ufoo/SKILL.md +8 -8
- package/bin/uagy.js +69 -0
- package/bin/uclaude.js +2 -2
- package/bin/ucode.js +4 -4
- package/bin/ucodex.js +2 -2
- package/bin/ufoo.js +5 -23
- package/modules/AGENTS.template.md +1 -1
- package/modules/bus/SKILLS/ubus/SKILL.md +35 -10
- package/package.json +5 -5
- package/scripts/chat-app-smoke.js +1 -1
- package/scripts/global-chat-switch-benchmark.js +5 -5
- package/scripts/ink-demo.js +1 -1
- package/scripts/ink-smoke.js +1 -1
- package/scripts/ucode-app-smoke.js +1 -1
- package/src/{agent → agents/activity}/activityDetector.js +39 -2
- package/src/{agent → agents/activity}/activityStatePublisher.js +1 -1
- package/src/{agent → agents/activity}/activityStateWriter.js +2 -2
- package/src/{agent → agents/activity}/activityTracker.js +1 -1
- package/src/agents/activity/index.js +8 -0
- package/src/{agent → agents/controller}/controllerToolExecutor.js +4 -4
- package/src/agents/controller/index.js +8 -0
- package/src/{agent → agents/controller}/loopObservability.js +2 -2
- package/src/{agent → agents/controller}/loopRuntime.js +1 -1
- package/src/{agent → agents/controller}/ufooAgent.js +9 -9
- package/src/agents/index.js +10 -0
- package/src/agents/internal/index.js +3 -0
- package/src/{agent → agents/internal}/internalRunner.js +45 -22
- package/src/agents/launch/agyConversation.js +159 -0
- package/src/agents/launch/index.js +12 -0
- package/src/{agent → agents/launch}/launchEnvironment.js +2 -3
- package/src/{agent → agents/launch}/launcher.js +64 -21
- package/src/{agent → agents/launch}/notifier.js +23 -12
- package/src/{agent → agents/launch}/ptyRunner.js +44 -12
- package/src/{agent → agents/launch}/ptyWrapper.js +2 -2
- package/src/{agent → agents/launch}/publisherRouting.js +1 -1
- package/src/{agent → agents/launch}/readyDetector.js +23 -0
- package/src/{agent → agents/prompts}/defaultBootstrap.js +63 -4
- package/src/{group/bootstrap.js → agents/prompts/groupBootstrap.js} +41 -6
- package/src/agents/prompts/index.js +8 -0
- package/src/{code/prompts → agents/prompts/native}/index.js +1 -1
- package/src/{agent → agents/providers}/claudeThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/codexThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/directAuthStatus.js +184 -1
- package/src/agents/providers/index.js +13 -0
- package/src/{agent → agents/providers}/upstreamTransport.js +2 -2
- package/src/{chat → app/chat}/agentSockets.js +1 -1
- package/src/{chat → app/chat}/commandExecutor.js +50 -26
- package/src/{chat → app/chat}/commands.js +119 -5
- package/src/{chat → app/chat}/daemonConnection.js +1 -1
- package/src/{chat → app/chat}/daemonMessageRouter.js +45 -3
- package/src/{chat → app/chat}/dashboardView.js +2 -1
- package/src/app/chat/index.js +6 -0
- package/src/{chat → app/chat}/inputSubmitHandler.js +4 -13
- package/src/{chat → app/chat}/internalAgentLogHistory.js +1 -1
- package/src/app/chat/multiWindow/index.js +268 -0
- package/src/app/chat/multiWindow/paneLayout.js +84 -0
- package/src/app/chat/multiWindow/paneManager.js +299 -0
- package/src/app/chat/multiWindow/renderer.js +384 -0
- package/src/app/chat/multiWindow/virtualTerminal.js +327 -0
- package/src/{chat → app/chat}/transport.js +1 -1
- package/src/{cli → app/cli}/ctxCoreCommands.js +3 -3
- package/src/{doctor/index.js → app/cli/features/doctor.js} +1 -1
- package/src/{init/index.js → app/cli/features/init.js} +14 -32
- package/src/{cli → app/cli}/groupCoreCommands.js +2 -2
- package/src/app/cli/index.js +9 -0
- package/src/{cli → app/cli}/onlineCoreCommands.js +5 -5
- package/src/{cli.js → app/cli/run.js} +59 -57
- package/src/app/index.js +6 -0
- package/src/code/agent.js +10 -9
- package/src/code/index.js +2 -0
- package/src/code/launcher/index.js +9 -0
- package/src/{agent → code/launcher}/ucode.js +7 -8
- package/src/{agent → code/launcher}/ucodeBootstrap.js +3 -3
- package/src/{agent → code/launcher}/ucodeBuild.js +2 -2
- package/src/{agent → code/launcher}/ucodeDoctor.js +2 -2
- package/src/{agent → code/launcher}/ucodeRuntimeConfig.js +1 -2
- package/src/code/nativeRunner.js +4 -4
- package/src/code/tui.js +3 -1454
- package/src/config.js +15 -2
- package/src/{bus → coordination/bus}/activate.js +2 -2
- package/src/{bus → coordination/bus}/daemon.js +15 -5
- package/src/coordination/bus/envelope.js +173 -0
- package/src/{bus → coordination/bus}/index.js +7 -3
- package/src/{bus → coordination/bus}/inject.js +11 -3
- package/src/{bus → coordination/bus}/message.js +1 -1
- package/src/coordination/bus/messageMeta.js +130 -0
- package/src/coordination/bus/promptEnvelope.js +65 -0
- package/src/{bus → coordination/bus}/shake.js +1 -1
- package/src/{bus → coordination/bus}/store.js +3 -3
- package/src/{bus → coordination/bus}/subscriber.js +2 -2
- package/src/{bus → coordination/bus}/utils.js +2 -2
- package/src/{history → coordination/history}/inputTimeline.js +5 -5
- package/src/coordination/index.js +10 -0
- package/src/{memory → coordination/memory}/historySearch.js +1 -1
- package/src/{memory → coordination/memory}/index.js +3 -3
- package/src/{report → coordination/report}/store.js +2 -2
- package/src/{status → coordination/status}/index.js +3 -3
- package/src/online/bridge.js +2 -2
- package/src/{controller → orchestration/controller}/flags.js +1 -1
- package/src/{controller → orchestration/controller}/gateRouter.js +1 -1
- package/src/orchestration/controller/index.js +10 -0
- package/src/{controller → orchestration/controller}/shadowGuard.js +1 -1
- package/src/orchestration/groups/bootstrap.js +3 -0
- package/src/orchestration/groups/index.js +10 -0
- package/src/orchestration/groups/promptProfiles.js +3 -0
- package/src/{group → orchestration/groups}/templates.js +1 -1
- package/src/{group → orchestration/groups}/validateTemplate.js +1 -1
- package/src/orchestration/index.js +7 -0
- package/src/orchestration/solo/index.js +3 -0
- package/src/{daemon → runtime/daemon}/agentProcessManager.js +1 -1
- package/src/{daemon → runtime/daemon}/cronOps.js +3 -2
- package/src/{daemon → runtime/daemon}/groupOrchestrator.js +26 -9
- package/src/{daemon → runtime/daemon}/index.js +105 -53
- package/src/{daemon → runtime/daemon}/ipcServer.js +1 -1
- package/src/{daemon → runtime/daemon}/nicknameScope.js +6 -3
- package/src/{daemon → runtime/daemon}/ops.js +48 -61
- package/src/{daemon → runtime/daemon}/promptLoop.js +1 -1
- package/src/{daemon → runtime/daemon}/promptRequest.js +7 -7
- package/src/runtime/daemon/providerSessions.js +230 -0
- package/src/{daemon → runtime/daemon}/reporting.js +4 -4
- package/src/{daemon → runtime/daemon}/run.js +4 -4
- package/src/{daemon → runtime/daemon}/soloBootstrap.js +7 -7
- package/src/{daemon → runtime/daemon}/status.js +5 -5
- package/src/runtime/index.js +10 -0
- package/src/{projects → runtime/projects}/registry.js +1 -1
- package/src/{terminal → runtime/terminal}/adapterRouter.js +0 -10
- package/src/{terminal → runtime/terminal}/adapters/internalAdapter.js +0 -4
- package/src/tools/handlers/common.js +1 -1
- package/src/tools/handlers/listAgents.js +1 -1
- package/src/tools/handlers/memory.js +3 -3
- package/src/tools/handlers/readBusSummary.js +1 -1
- package/src/tools/handlers/readOpenDecisions.js +1 -1
- package/src/tools/handlers/readProjectRegistry.js +1 -1
- package/src/tools/handlers/readPromptHistory.js +2 -2
- package/src/tools/schemaFixtures.js +1 -1
- package/src/ui/MIGRATION.md +42 -88
- package/src/ui/format/index.js +5 -28
- package/src/ui/index.js +1 -1
- package/src/ui/{components → ink}/ChatApp.js +812 -88
- package/src/ui/ink/DashboardBar.js +685 -0
- package/src/ui/{components → ink}/MultilineInput.js +230 -5
- package/src/ui/{components → ink}/UcodeApp.js +16 -7
- package/src/ui/{components → ink}/agentMirror.js +24 -19
- package/src/ui/{components → ink}/chatReducer.js +29 -7
- package/src/bus/messageMeta.js +0 -52
- package/src/chat/agentViewController.js +0 -1072
- package/src/chat/chatLogController.js +0 -138
- package/src/chat/completionController.js +0 -533
- package/src/chat/dashboardKeyController.js +0 -533
- package/src/chat/index.js +0 -2222
- package/src/chat/inputHistoryController.js +0 -135
- package/src/chat/inputListenerController.js +0 -470
- package/src/chat/layout.js +0 -186
- package/src/chat/pasteController.js +0 -81
- package/src/chat/statusLineController.js +0 -223
- package/src/chat/streamTracker.js +0 -156
- package/src/code/config +0 -0
- package/src/daemon/providerSessions.js +0 -488
- package/src/terminal/adapters/internalPtyAdapter.js +0 -42
- package/src/ui/components/DashboardBar.js +0 -417
- /package/src/{code/prompts → agents/prompts/native}/actions.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/efficiency.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/environment.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/identity.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/safety.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/sections.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/system.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/tasks.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/bash.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/edit.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/read.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/write.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/ufoo.js +0 -0
- /package/src/{group → agents/prompts}/promptProfiles.js +0 -0
- /package/src/{agent → agents/providers}/claudeEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/claudeOauthTokenReader.js +0 -0
- /package/src/{agent → agents/providers}/claudeSessionFiles.js +0 -0
- /package/src/{agent → agents/providers}/codexEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/credentials/claude.js +0 -0
- /package/src/{agent → agents/providers}/credentials/codex.js +0 -0
- /package/src/{agent → agents/providers}/credentials/index.js +0 -0
- /package/src/{chat → app/chat}/agentBar.js +0 -0
- /package/src/{chat → app/chat}/agentDirectory.js +0 -0
- /package/src/{chat → app/chat}/cronScheduler.js +0 -0
- /package/src/{chat → app/chat}/daemonCoordinator.js +0 -0
- /package/src/{chat → app/chat}/daemonReconnect.js +0 -0
- /package/src/{chat → app/chat}/daemonTransport.js +0 -0
- /package/src/{chat → app/chat}/daemonTransportDefaults.js +0 -0
- /package/src/{chat → app/chat}/inputMath.js +0 -0
- /package/src/{chat → app/chat}/projectCloseController.js +0 -0
- /package/src/{chat → app/chat}/rawKeyMap.js +0 -0
- /package/src/{chat → app/chat}/settingsController.js +0 -0
- /package/src/{chat → app/chat}/shellCommand.js +0 -0
- /package/src/{chat → app/chat}/text.js +0 -0
- /package/src/{chat → app/chat}/transientAgentState.js +0 -0
- /package/src/{cli → app/cli}/busCoreCommands.js +0 -0
- /package/src/{skills/index.js → app/cli/features/skills.js} +0 -0
- /package/src/{bus → coordination/bus}/nickname.js +0 -0
- /package/src/{bus → coordination/bus}/queue.js +0 -0
- /package/src/{context → coordination/context}/decisions.js +0 -0
- /package/src/{context → coordination/context}/doctor.js +0 -0
- /package/src/{context → coordination/context}/index.js +0 -0
- /package/src/{context → coordination/context}/sync.js +0 -0
- /package/src/{ufoo → coordination/state}/agentRegistryDiagnostics.js +0 -0
- /package/src/{ufoo → coordination/state}/agentsStore.js +0 -0
- /package/src/{ufoo → coordination/state}/paths.js +0 -0
- /package/src/{controller → orchestration/controller}/launchRouting.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFastPath.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFinalize.js +0 -0
- /package/src/{group → orchestration/groups}/diagram.js +0 -0
- /package/src/{group → orchestration/groups}/templateValidation.js +0 -0
- /package/src/{solo → orchestration/solo}/commands.js +0 -0
- /package/src/{shared → runtime/contracts}/eventContract.js +0 -0
- /package/src/{shared → runtime/contracts}/ptySocketContract.js +0 -0
- /package/src/{providerapi → runtime/privacy}/redactor.js +0 -0
- /package/src/{providerapi → runtime/privacy}/shadowDiff.js +0 -0
- /package/src/{utils → runtime/process}/nodeExecutable.js +0 -0
- /package/src/{projects → runtime/projects}/identity.js +0 -0
- /package/src/{projects → runtime/projects}/index.js +0 -0
- /package/src/{projects → runtime/projects}/projectId.js +0 -0
- /package/src/{projects → runtime/projects}/runtimes.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapterContract.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/externalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/hostAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/internalQueueAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/terminalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/tmuxAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/detect.js +0 -0
- /package/src/{terminal → runtime/terminal}/index.js +0 -0
- /package/src/{terminal → runtime/terminal}/iterm2.js +0 -0
- /package/src/{utils → ui/format}/banner.js +0 -0
- /package/src/{shared → ui/format}/markdownRenderer.js +0 -0
- /package/src/ui/{components → ink}/InkDemo.js +0 -0
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* DashboardBar — the bottom 1-2 rows in chat showing the current dashboard
|
|
5
|
-
* mode (projects rail in global mode + one of agents/mode/provider/cron).
|
|
6
|
-
* Renders directly with ink primitives instead of going through
|
|
7
|
-
* computeDashboardContent (which emits blessed-tag strings) so we don't
|
|
8
|
-
* have to translate "{cyan-fg}…{/cyan-fg}" at render time.
|
|
9
|
-
*
|
|
10
|
-
* The agents window math (clamping the visible slice around the selection
|
|
11
|
-
* cursor) is reused from src/chat/agentDirectory.js so the two TUIs scroll
|
|
12
|
-
* the strip the same way.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const { clampAgentWindowWithSelection } = require("../../chat/agentDirectory");
|
|
16
|
-
const { providerLabel } = require("../../chat/dashboardView");
|
|
17
|
-
const { displayCellWidth, planProjectsRail } = require("../format");
|
|
18
|
-
|
|
19
|
-
function ensureAtPrefix(value) {
|
|
20
|
-
const text = String(value || "").trim();
|
|
21
|
-
if (!text) return text;
|
|
22
|
-
return text.startsWith("@") ? text : `@${text}`;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function activityMarker(state = "") {
|
|
26
|
-
const normalized = String(state || "").trim().toLowerCase();
|
|
27
|
-
if (normalized === "working") return "*";
|
|
28
|
-
if (normalized === "waiting_input") return "?";
|
|
29
|
-
if (normalized === "blocked") return "!";
|
|
30
|
-
return "";
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function withActivityMarker(label = "", state = "") {
|
|
34
|
-
const marker = activityMarker(state);
|
|
35
|
-
return marker ? `${marker}${label}` : label;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function formatToolDistribution(items = []) {
|
|
39
|
-
const tools = Array.isArray(items) ? items : [];
|
|
40
|
-
if (tools.length === 0) return "";
|
|
41
|
-
const visible = tools.slice(0, 2).map((item) => `${item.name}x${item.count}`);
|
|
42
|
-
if (tools.length > 2) visible.push(`+${tools.length - 2}`);
|
|
43
|
-
return visible.join(",");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function formatLoopSummary(loopSummary) {
|
|
47
|
-
if (!loopSummary || typeof loopSummary !== "object") return "";
|
|
48
|
-
const rounds = Number(loopSummary.rounds) || 0;
|
|
49
|
-
const toolCalls = Number(loopSummary.tool_calls) || 0;
|
|
50
|
-
const totalTokens = Number(loopSummary.total_tokens) || 0;
|
|
51
|
-
const cacheReadTokens = Number(loopSummary.cache_read_tokens) || 0;
|
|
52
|
-
const cacheCreationTokens = Number(loopSummary.cache_creation_tokens) || 0;
|
|
53
|
-
const terminalReason = String(loopSummary.terminal_reason || "").trim();
|
|
54
|
-
const toolDistribution = formatToolDistribution(loopSummary.tools);
|
|
55
|
-
if (rounds <= 0 && toolCalls <= 0 && totalTokens <= 0 && !terminalReason && !toolDistribution) return "";
|
|
56
|
-
const parts = [`r${rounds}`, `tc${toolCalls}`, `tok${totalTokens}`];
|
|
57
|
-
if (cacheReadTokens > 0 || cacheCreationTokens > 0) {
|
|
58
|
-
parts.push(`cache${cacheReadTokens}/${cacheCreationTokens}`);
|
|
59
|
-
}
|
|
60
|
-
if (toolDistribution) parts.push(toolDistribution);
|
|
61
|
-
if (terminalReason) parts.push(terminalReason);
|
|
62
|
-
return parts.join(" ");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function projectName(row) {
|
|
66
|
-
return String(
|
|
67
|
-
(row && (row.project_name || row.label || row.id || row.project_root || row.root)) || "-"
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function projectRoot(row) {
|
|
72
|
-
return String((row && (row.project_root || row.root)) || "");
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function buildSummaryRow(options = {}) {
|
|
76
|
-
const {
|
|
77
|
-
activeAgents = [],
|
|
78
|
-
activeAgentId = "",
|
|
79
|
-
getAgentLabel = (id) => id,
|
|
80
|
-
getAgentState = () => "",
|
|
81
|
-
launchMode = "terminal",
|
|
82
|
-
agentProvider = "codex-cli",
|
|
83
|
-
cronTasks = [],
|
|
84
|
-
loopSummary = null,
|
|
85
|
-
} = options;
|
|
86
|
-
const visibleAgentIds = activeAgents.slice(0, 3);
|
|
87
|
-
const agentItems = visibleAgentIds.map((id) => {
|
|
88
|
-
const active = Boolean(activeAgentId && id === activeAgentId);
|
|
89
|
-
return {
|
|
90
|
-
label: withActivityMarker(ensureAtPrefix(getAgentLabel(id)), getAgentState(id)),
|
|
91
|
-
selected: false,
|
|
92
|
-
active,
|
|
93
|
-
};
|
|
94
|
-
});
|
|
95
|
-
const agents = activeAgents.length > 0
|
|
96
|
-
? agentItems.map((item) => item.label).join(", ") + (activeAgents.length > 3 ? ` +${activeAgents.length - 3}` : "")
|
|
97
|
-
: "none";
|
|
98
|
-
const parts = [
|
|
99
|
-
{ label: "Agents", value: agents },
|
|
100
|
-
{ label: "Mode", value: launchMode },
|
|
101
|
-
{ label: "Agent", value: providerLabel(agentProvider) },
|
|
102
|
-
{ label: "Cron", value: String(Array.isArray(cronTasks) ? cronTasks.length : 0) },
|
|
103
|
-
];
|
|
104
|
-
const loopPart = formatLoopSummary(loopSummary);
|
|
105
|
-
if (loopPart) parts.push({ label: "Loop", value: loopPart });
|
|
106
|
-
return {
|
|
107
|
-
kind: "summary",
|
|
108
|
-
agentItems,
|
|
109
|
-
agentExtraCount: Math.max(0, activeAgents.length - visibleAgentIds.length),
|
|
110
|
-
parts,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function buildProjectRow(options = {}) {
|
|
115
|
-
const {
|
|
116
|
-
projects = [],
|
|
117
|
-
selectedProjectIndex = -1,
|
|
118
|
-
projectListWindowStart = 0,
|
|
119
|
-
maxProjectWindow = 5,
|
|
120
|
-
maxWidth = 80,
|
|
121
|
-
activeProjectRoot = "",
|
|
122
|
-
focused = false,
|
|
123
|
-
globalScope = "controller",
|
|
124
|
-
} = options;
|
|
125
|
-
const rows = Array.isArray(projects) ? projects : [];
|
|
126
|
-
if (rows.length === 0) {
|
|
127
|
-
return {
|
|
128
|
-
kind: "chips",
|
|
129
|
-
caption: "Projects",
|
|
130
|
-
items: [],
|
|
131
|
-
emptyLabel: "none",
|
|
132
|
-
hint: options.dashHints && options.dashHints.projectsEmpty
|
|
133
|
-
? options.dashHints.projectsEmpty
|
|
134
|
-
: "Run ufoo chat or ufoo daemon start in project directories",
|
|
135
|
-
windowStart: projectListWindowStart,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
const fallbackIndex = rows.findIndex((row) => projectRoot(row) === String(activeProjectRoot || ""));
|
|
139
|
-
const selected = selectedProjectIndex >= 0 && selectedProjectIndex < rows.length
|
|
140
|
-
? selectedProjectIndex
|
|
141
|
-
: (fallbackIndex >= 0 ? fallbackIndex : 0);
|
|
142
|
-
const requestedHint = focused ? (globalScope === "controller" ? "Enter→project" : "Esc→global") : "";
|
|
143
|
-
const availableAfterCaption = Math.max(
|
|
144
|
-
1,
|
|
145
|
-
Math.floor(Number(maxWidth) || 80) - displayCellWidth("Projects: ")
|
|
146
|
-
);
|
|
147
|
-
const hintWidth = requestedHint ? displayCellWidth(` · ${requestedHint}`) : 0;
|
|
148
|
-
const minFocusedChipWidth = focused ? 4 : 1;
|
|
149
|
-
const canShowHint = requestedHint && availableAfterCaption - hintWidth >= minFocusedChipWidth;
|
|
150
|
-
const hint = canShowHint ? requestedHint : "";
|
|
151
|
-
const railBudget = Math.max(1, availableAfterCaption - (hint ? hintWidth : 0));
|
|
152
|
-
const planned = planProjectsRail({
|
|
153
|
-
labels: rows.map(projectName),
|
|
154
|
-
selectedIndex: focused ? selected : -1,
|
|
155
|
-
windowStart: projectListWindowStart || 0,
|
|
156
|
-
maxCells: railBudget,
|
|
157
|
-
});
|
|
158
|
-
return {
|
|
159
|
-
kind: "chips",
|
|
160
|
-
caption: "Projects",
|
|
161
|
-
leftMore: planned.leftMore,
|
|
162
|
-
rightMore: planned.rightMore,
|
|
163
|
-
windowStart: planned.windowStart,
|
|
164
|
-
hint,
|
|
165
|
-
items: planned.items.map((item) => {
|
|
166
|
-
const idx = item.absoluteIndex;
|
|
167
|
-
const row = rows[idx];
|
|
168
|
-
const root = projectRoot(row);
|
|
169
|
-
return {
|
|
170
|
-
label: item.label,
|
|
171
|
-
selected: focused && idx === selected,
|
|
172
|
-
active: Boolean(activeProjectRoot && root === activeProjectRoot),
|
|
173
|
-
};
|
|
174
|
-
}),
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function buildDetailRow(options = {}) {
|
|
179
|
-
const {
|
|
180
|
-
dashboardView = "agents",
|
|
181
|
-
globalMode = false,
|
|
182
|
-
activeAgents = [],
|
|
183
|
-
activeAgentId = "",
|
|
184
|
-
selectedAgentIndex = -1,
|
|
185
|
-
agentListWindowStart = 0,
|
|
186
|
-
maxAgentWindow = 4,
|
|
187
|
-
getAgentLabel = (id) => id,
|
|
188
|
-
getAgentState = () => "",
|
|
189
|
-
selectedModeIndex = 0,
|
|
190
|
-
selectedProviderIndex = 0,
|
|
191
|
-
selectedCronIndex = -1,
|
|
192
|
-
modeOptions = [],
|
|
193
|
-
providerOptions = [],
|
|
194
|
-
cronTasks = [],
|
|
195
|
-
loopSummary = null,
|
|
196
|
-
dashHints = {},
|
|
197
|
-
focused = false,
|
|
198
|
-
} = options;
|
|
199
|
-
|
|
200
|
-
if (dashboardView === "mode") {
|
|
201
|
-
return {
|
|
202
|
-
kind: "chips",
|
|
203
|
-
caption: "Mode",
|
|
204
|
-
hint: dashHints.mode || "",
|
|
205
|
-
items: (modeOptions || []).map((label, i) => ({ label, selected: focused && i === selectedModeIndex })),
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
if (dashboardView === "provider") {
|
|
209
|
-
return {
|
|
210
|
-
kind: "chips",
|
|
211
|
-
caption: "Agent",
|
|
212
|
-
hint: dashHints.provider || "",
|
|
213
|
-
items: (providerOptions || []).map((opt, i) => ({ label: opt.label || opt, selected: focused && i === selectedProviderIndex })),
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
if (dashboardView === "cron") {
|
|
217
|
-
const items = Array.isArray(cronTasks) ? cronTasks : [];
|
|
218
|
-
return {
|
|
219
|
-
kind: "chips",
|
|
220
|
-
caption: "Cron",
|
|
221
|
-
hint: dashHints.cron || "",
|
|
222
|
-
emptyLabel: "none",
|
|
223
|
-
items: items.map((item, i) => ({
|
|
224
|
-
label: item.label || item.summary || item.id || "",
|
|
225
|
-
selected: focused && i === selectedCronIndex,
|
|
226
|
-
})).filter((item) => item.label),
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (!activeAgents.length) {
|
|
231
|
-
return {
|
|
232
|
-
kind: "chips",
|
|
233
|
-
caption: "Agents",
|
|
234
|
-
emptyLabel: "none",
|
|
235
|
-
hint: dashHints.agentsEmpty || "",
|
|
236
|
-
items: [],
|
|
237
|
-
windowStart: agentListWindowStart,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
const maxItems = Math.max(1, Math.min(maxAgentWindow || 4, activeAgents.length));
|
|
241
|
-
const windowStart = clampAgentWindowWithSelection({
|
|
242
|
-
activeCount: activeAgents.length,
|
|
243
|
-
maxWindow: maxItems,
|
|
244
|
-
windowStart: agentListWindowStart || 0,
|
|
245
|
-
selectionIndex: selectedAgentIndex,
|
|
246
|
-
});
|
|
247
|
-
const visible = activeAgents.slice(windowStart, windowStart + maxItems);
|
|
248
|
-
return {
|
|
249
|
-
kind: "chips",
|
|
250
|
-
caption: "Agents",
|
|
251
|
-
leftMore: windowStart > 0,
|
|
252
|
-
rightMore: windowStart + maxItems < activeAgents.length,
|
|
253
|
-
windowStart,
|
|
254
|
-
hint: globalMode ? (dashHints.agentsGlobal || dashHints.agents || "") : (dashHints.agents || ""),
|
|
255
|
-
items: visible.map((agentId, i) => {
|
|
256
|
-
const active = Boolean(activeAgentId && agentId === activeAgentId);
|
|
257
|
-
return {
|
|
258
|
-
label: withActivityMarker(ensureAtPrefix(getAgentLabel(agentId)), getAgentState(agentId)),
|
|
259
|
-
selected: focused && (windowStart + i) === selectedAgentIndex,
|
|
260
|
-
...(active ? { active: true } : {}),
|
|
261
|
-
};
|
|
262
|
-
}),
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function buildDashboardRows(options = {}) {
|
|
267
|
-
const {
|
|
268
|
-
globalMode = false,
|
|
269
|
-
globalScope = "controller",
|
|
270
|
-
focusMode = "input",
|
|
271
|
-
dashboardView = "agents",
|
|
272
|
-
projects = [],
|
|
273
|
-
dashHints = {},
|
|
274
|
-
} = options;
|
|
275
|
-
const focused = focusMode === "dashboard";
|
|
276
|
-
if (globalMode) {
|
|
277
|
-
const projectsFocused = focused && dashboardView === "projects";
|
|
278
|
-
const projectRow = buildProjectRow({
|
|
279
|
-
...options,
|
|
280
|
-
focused: projectsFocused,
|
|
281
|
-
globalScope,
|
|
282
|
-
});
|
|
283
|
-
if (!focused || projectsFocused) {
|
|
284
|
-
return [projectRow, buildSummaryRow(options)];
|
|
285
|
-
}
|
|
286
|
-
return [projectRow, buildDetailRow({ ...options, focused })];
|
|
287
|
-
}
|
|
288
|
-
if (focused) return [buildDetailRow({ ...options, focused })];
|
|
289
|
-
return [buildSummaryRow(options)];
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function createDashboardBar({ React, ink }) {
|
|
293
|
-
const { Box, Text } = ink;
|
|
294
|
-
const h = React.createElement;
|
|
295
|
-
|
|
296
|
-
const sep = (key) =>
|
|
297
|
-
h(Text, { key, color: "gray", wrap: "truncate" }, " ");
|
|
298
|
-
|
|
299
|
-
const renderItem = (item, key) =>
|
|
300
|
-
h(Text, {
|
|
301
|
-
key,
|
|
302
|
-
color: item.selected || item.active ? undefined : "cyan",
|
|
303
|
-
inverse: item.selected,
|
|
304
|
-
bold: Boolean(item.active),
|
|
305
|
-
wrap: "truncate",
|
|
306
|
-
}, item.label);
|
|
307
|
-
|
|
308
|
-
const renderHint = (hint) =>
|
|
309
|
-
hint ? h(Text, { color: "gray", wrap: "truncate" }, ` · ${hint}`) : null;
|
|
310
|
-
|
|
311
|
-
const ChipsRow = ({ caption, items, hint, leftMore, rightMore, emptyLabel }) =>
|
|
312
|
-
h(Box, { width: "100%", flexWrap: "nowrap" },
|
|
313
|
-
h(Text, { color: "gray", wrap: "truncate" }, `${caption}: `),
|
|
314
|
-
leftMore ? h(Text, { color: "gray", wrap: "truncate" }, "< ") : null,
|
|
315
|
-
items.length === 0 && emptyLabel ? h(Text, { color: "cyan", wrap: "truncate" }, emptyLabel) : null,
|
|
316
|
-
...items.map((item, idx) => h(React.Fragment, { key: idx },
|
|
317
|
-
idx > 0 ? sep(`s-${idx}`) : null,
|
|
318
|
-
renderItem(item, `c-${idx}`),
|
|
319
|
-
)),
|
|
320
|
-
rightMore ? h(Text, { color: "gray", wrap: "truncate" }, " >") : null,
|
|
321
|
-
renderHint(hint),
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
const SummaryRow = ({ parts, agentItems = [], agentExtraCount = 0 }) =>
|
|
325
|
-
h(Box, { width: "100%", flexWrap: "nowrap" },
|
|
326
|
-
...parts.map((part, idx) => {
|
|
327
|
-
const isAgents = part.label === "Agents" && agentItems.length > 0;
|
|
328
|
-
return h(React.Fragment, { key: part.label },
|
|
329
|
-
idx > 0 ? h(Text, { color: "gray", wrap: "truncate" }, " ") : null,
|
|
330
|
-
h(Text, { color: "gray", wrap: "truncate" }, `${part.label}: `),
|
|
331
|
-
isAgents
|
|
332
|
-
? h(React.Fragment, { key: "agents-summary" },
|
|
333
|
-
...agentItems.map((item, itemIdx) => h(React.Fragment, { key: `agent-${itemIdx}` },
|
|
334
|
-
itemIdx > 0 ? h(Text, { color: "gray", wrap: "truncate" }, ", ") : null,
|
|
335
|
-
renderItem(item, `agent-value-${itemIdx}`),
|
|
336
|
-
)),
|
|
337
|
-
agentExtraCount > 0 ? h(Text, { color: "cyan", wrap: "truncate" }, ` +${agentExtraCount}`) : null,
|
|
338
|
-
)
|
|
339
|
-
: h(Text, { color: "cyan", wrap: "truncate" }, part.value),
|
|
340
|
-
);
|
|
341
|
-
}),
|
|
342
|
-
);
|
|
343
|
-
|
|
344
|
-
return function DashboardBar({
|
|
345
|
-
dashboardView = "agents",
|
|
346
|
-
focusMode = "input",
|
|
347
|
-
globalMode = false,
|
|
348
|
-
globalScope = "controller",
|
|
349
|
-
activeAgents = [],
|
|
350
|
-
activeAgentId = "",
|
|
351
|
-
selectedAgentIndex = -1,
|
|
352
|
-
agentListWindowStart = 0,
|
|
353
|
-
maxAgentWindow = 4,
|
|
354
|
-
projectListWindowStart = 0,
|
|
355
|
-
maxProjectWindow = 5,
|
|
356
|
-
maxWidth = 80,
|
|
357
|
-
getAgentLabel = (id) => id,
|
|
358
|
-
getAgentState = () => "",
|
|
359
|
-
launchMode = "terminal",
|
|
360
|
-
agentProvider = "codex-cli",
|
|
361
|
-
modeOptions = [],
|
|
362
|
-
selectedModeIndex = 0,
|
|
363
|
-
providerOptions = [],
|
|
364
|
-
selectedProviderIndex = 0,
|
|
365
|
-
cronTasks = [],
|
|
366
|
-
loopSummary = null,
|
|
367
|
-
selectedCronIndex = -1,
|
|
368
|
-
projects = [],
|
|
369
|
-
selectedProjectIndex = -1,
|
|
370
|
-
activeProjectRoot = "",
|
|
371
|
-
dashHints = {},
|
|
372
|
-
}) {
|
|
373
|
-
const rows = buildDashboardRows({
|
|
374
|
-
dashboardView,
|
|
375
|
-
focusMode,
|
|
376
|
-
globalMode,
|
|
377
|
-
globalScope,
|
|
378
|
-
activeAgents,
|
|
379
|
-
activeAgentId,
|
|
380
|
-
selectedAgentIndex,
|
|
381
|
-
agentListWindowStart,
|
|
382
|
-
maxAgentWindow,
|
|
383
|
-
projectListWindowStart,
|
|
384
|
-
maxProjectWindow,
|
|
385
|
-
maxWidth,
|
|
386
|
-
getAgentLabel,
|
|
387
|
-
getAgentState,
|
|
388
|
-
launchMode,
|
|
389
|
-
agentProvider,
|
|
390
|
-
modeOptions,
|
|
391
|
-
selectedModeIndex,
|
|
392
|
-
providerOptions,
|
|
393
|
-
selectedProviderIndex,
|
|
394
|
-
cronTasks,
|
|
395
|
-
loopSummary,
|
|
396
|
-
selectedCronIndex,
|
|
397
|
-
projects,
|
|
398
|
-
selectedProjectIndex,
|
|
399
|
-
activeProjectRoot,
|
|
400
|
-
dashHints,
|
|
401
|
-
}).map((row, idx) => {
|
|
402
|
-
if (row.kind === "summary") {
|
|
403
|
-
return h(Box, { key: `dr-${idx}`, width: "100%", flexWrap: "nowrap" }, h(SummaryRow, row));
|
|
404
|
-
}
|
|
405
|
-
if (row.kind === "message") {
|
|
406
|
-
return h(Box, { key: `dr-${idx}`, width: "100%", flexWrap: "nowrap" },
|
|
407
|
-
h(Text, { color: "gray", wrap: "truncate" }, row.text));
|
|
408
|
-
}
|
|
409
|
-
return h(Box, { key: `dr-${idx}`, width: "100%", flexWrap: "nowrap" }, h(ChipsRow, row));
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
if (rows.length === 1) return h(Box, { width: "100%" }, rows[0]);
|
|
413
|
-
return h(Box, { flexDirection: "column", width: "100%", flexWrap: "nowrap" }, ...rows);
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
module.exports = { createDashboardBar, buildDashboardRows, formatLoopSummary };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|