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.
Files changed (235) hide show
  1. package/README.md +157 -213
  2. package/README.zh-CN.md +151 -197
  3. package/SKILLS/ufoo/SKILL.md +8 -8
  4. package/bin/uagy.js +69 -0
  5. package/bin/uclaude.js +2 -2
  6. package/bin/ucode.js +4 -4
  7. package/bin/ucodex.js +2 -2
  8. package/bin/ufoo.js +5 -23
  9. package/modules/AGENTS.template.md +1 -1
  10. package/modules/bus/SKILLS/ubus/SKILL.md +35 -10
  11. package/package.json +5 -5
  12. package/scripts/chat-app-smoke.js +1 -1
  13. package/scripts/global-chat-switch-benchmark.js +5 -5
  14. package/scripts/ink-demo.js +1 -1
  15. package/scripts/ink-smoke.js +1 -1
  16. package/scripts/ucode-app-smoke.js +1 -1
  17. package/src/{agent → agents/activity}/activityDetector.js +39 -2
  18. package/src/{agent → agents/activity}/activityStatePublisher.js +1 -1
  19. package/src/{agent → agents/activity}/activityStateWriter.js +2 -2
  20. package/src/{agent → agents/activity}/activityTracker.js +1 -1
  21. package/src/agents/activity/index.js +8 -0
  22. package/src/{agent → agents/controller}/controllerToolExecutor.js +4 -4
  23. package/src/agents/controller/index.js +8 -0
  24. package/src/{agent → agents/controller}/loopObservability.js +2 -2
  25. package/src/{agent → agents/controller}/loopRuntime.js +1 -1
  26. package/src/{agent → agents/controller}/ufooAgent.js +9 -9
  27. package/src/agents/index.js +10 -0
  28. package/src/agents/internal/index.js +3 -0
  29. package/src/{agent → agents/internal}/internalRunner.js +45 -22
  30. package/src/agents/launch/agyConversation.js +159 -0
  31. package/src/agents/launch/index.js +12 -0
  32. package/src/{agent → agents/launch}/launchEnvironment.js +2 -3
  33. package/src/{agent → agents/launch}/launcher.js +64 -21
  34. package/src/{agent → agents/launch}/notifier.js +23 -12
  35. package/src/{agent → agents/launch}/ptyRunner.js +44 -12
  36. package/src/{agent → agents/launch}/ptyWrapper.js +2 -2
  37. package/src/{agent → agents/launch}/publisherRouting.js +1 -1
  38. package/src/{agent → agents/launch}/readyDetector.js +23 -0
  39. package/src/{agent → agents/prompts}/defaultBootstrap.js +63 -4
  40. package/src/{group/bootstrap.js → agents/prompts/groupBootstrap.js} +41 -6
  41. package/src/agents/prompts/index.js +8 -0
  42. package/src/{code/prompts → agents/prompts/native}/index.js +1 -1
  43. package/src/{agent → agents/providers}/claudeThreadProvider.js +1 -1
  44. package/src/{agent → agents/providers}/codexThreadProvider.js +1 -1
  45. package/src/{agent → agents/providers}/directAuthStatus.js +184 -1
  46. package/src/agents/providers/index.js +13 -0
  47. package/src/{agent → agents/providers}/upstreamTransport.js +2 -2
  48. package/src/{chat → app/chat}/agentSockets.js +1 -1
  49. package/src/{chat → app/chat}/commandExecutor.js +50 -26
  50. package/src/{chat → app/chat}/commands.js +119 -5
  51. package/src/{chat → app/chat}/daemonConnection.js +1 -1
  52. package/src/{chat → app/chat}/daemonMessageRouter.js +45 -3
  53. package/src/{chat → app/chat}/dashboardView.js +2 -1
  54. package/src/app/chat/index.js +6 -0
  55. package/src/{chat → app/chat}/inputSubmitHandler.js +4 -13
  56. package/src/{chat → app/chat}/internalAgentLogHistory.js +1 -1
  57. package/src/app/chat/multiWindow/index.js +268 -0
  58. package/src/app/chat/multiWindow/paneLayout.js +84 -0
  59. package/src/app/chat/multiWindow/paneManager.js +299 -0
  60. package/src/app/chat/multiWindow/renderer.js +384 -0
  61. package/src/app/chat/multiWindow/virtualTerminal.js +327 -0
  62. package/src/{chat → app/chat}/transport.js +1 -1
  63. package/src/{cli → app/cli}/ctxCoreCommands.js +3 -3
  64. package/src/{doctor/index.js → app/cli/features/doctor.js} +1 -1
  65. package/src/{init/index.js → app/cli/features/init.js} +14 -32
  66. package/src/{cli → app/cli}/groupCoreCommands.js +2 -2
  67. package/src/app/cli/index.js +9 -0
  68. package/src/{cli → app/cli}/onlineCoreCommands.js +5 -5
  69. package/src/{cli.js → app/cli/run.js} +59 -57
  70. package/src/app/index.js +6 -0
  71. package/src/code/agent.js +10 -9
  72. package/src/code/index.js +2 -0
  73. package/src/code/launcher/index.js +9 -0
  74. package/src/{agent → code/launcher}/ucode.js +7 -8
  75. package/src/{agent → code/launcher}/ucodeBootstrap.js +3 -3
  76. package/src/{agent → code/launcher}/ucodeBuild.js +2 -2
  77. package/src/{agent → code/launcher}/ucodeDoctor.js +2 -2
  78. package/src/{agent → code/launcher}/ucodeRuntimeConfig.js +1 -2
  79. package/src/code/nativeRunner.js +4 -4
  80. package/src/code/tui.js +3 -1454
  81. package/src/config.js +15 -2
  82. package/src/{bus → coordination/bus}/activate.js +2 -2
  83. package/src/{bus → coordination/bus}/daemon.js +15 -5
  84. package/src/coordination/bus/envelope.js +173 -0
  85. package/src/{bus → coordination/bus}/index.js +7 -3
  86. package/src/{bus → coordination/bus}/inject.js +11 -3
  87. package/src/{bus → coordination/bus}/message.js +1 -1
  88. package/src/coordination/bus/messageMeta.js +130 -0
  89. package/src/coordination/bus/promptEnvelope.js +65 -0
  90. package/src/{bus → coordination/bus}/shake.js +1 -1
  91. package/src/{bus → coordination/bus}/store.js +3 -3
  92. package/src/{bus → coordination/bus}/subscriber.js +2 -2
  93. package/src/{bus → coordination/bus}/utils.js +2 -2
  94. package/src/{history → coordination/history}/inputTimeline.js +5 -5
  95. package/src/coordination/index.js +10 -0
  96. package/src/{memory → coordination/memory}/historySearch.js +1 -1
  97. package/src/{memory → coordination/memory}/index.js +3 -3
  98. package/src/{report → coordination/report}/store.js +2 -2
  99. package/src/{status → coordination/status}/index.js +3 -3
  100. package/src/online/bridge.js +2 -2
  101. package/src/{controller → orchestration/controller}/flags.js +1 -1
  102. package/src/{controller → orchestration/controller}/gateRouter.js +1 -1
  103. package/src/orchestration/controller/index.js +10 -0
  104. package/src/{controller → orchestration/controller}/shadowGuard.js +1 -1
  105. package/src/orchestration/groups/bootstrap.js +3 -0
  106. package/src/orchestration/groups/index.js +10 -0
  107. package/src/orchestration/groups/promptProfiles.js +3 -0
  108. package/src/{group → orchestration/groups}/templates.js +1 -1
  109. package/src/{group → orchestration/groups}/validateTemplate.js +1 -1
  110. package/src/orchestration/index.js +7 -0
  111. package/src/orchestration/solo/index.js +3 -0
  112. package/src/{daemon → runtime/daemon}/agentProcessManager.js +1 -1
  113. package/src/{daemon → runtime/daemon}/cronOps.js +3 -2
  114. package/src/{daemon → runtime/daemon}/groupOrchestrator.js +26 -9
  115. package/src/{daemon → runtime/daemon}/index.js +105 -53
  116. package/src/{daemon → runtime/daemon}/ipcServer.js +1 -1
  117. package/src/{daemon → runtime/daemon}/nicknameScope.js +6 -3
  118. package/src/{daemon → runtime/daemon}/ops.js +48 -61
  119. package/src/{daemon → runtime/daemon}/promptLoop.js +1 -1
  120. package/src/{daemon → runtime/daemon}/promptRequest.js +7 -7
  121. package/src/runtime/daemon/providerSessions.js +230 -0
  122. package/src/{daemon → runtime/daemon}/reporting.js +4 -4
  123. package/src/{daemon → runtime/daemon}/run.js +4 -4
  124. package/src/{daemon → runtime/daemon}/soloBootstrap.js +7 -7
  125. package/src/{daemon → runtime/daemon}/status.js +5 -5
  126. package/src/runtime/index.js +10 -0
  127. package/src/{projects → runtime/projects}/registry.js +1 -1
  128. package/src/{terminal → runtime/terminal}/adapterRouter.js +0 -10
  129. package/src/{terminal → runtime/terminal}/adapters/internalAdapter.js +0 -4
  130. package/src/tools/handlers/common.js +1 -1
  131. package/src/tools/handlers/listAgents.js +1 -1
  132. package/src/tools/handlers/memory.js +3 -3
  133. package/src/tools/handlers/readBusSummary.js +1 -1
  134. package/src/tools/handlers/readOpenDecisions.js +1 -1
  135. package/src/tools/handlers/readProjectRegistry.js +1 -1
  136. package/src/tools/handlers/readPromptHistory.js +2 -2
  137. package/src/tools/schemaFixtures.js +1 -1
  138. package/src/ui/MIGRATION.md +42 -88
  139. package/src/ui/format/index.js +5 -28
  140. package/src/ui/index.js +1 -1
  141. package/src/ui/{components → ink}/ChatApp.js +812 -88
  142. package/src/ui/ink/DashboardBar.js +685 -0
  143. package/src/ui/{components → ink}/MultilineInput.js +230 -5
  144. package/src/ui/{components → ink}/UcodeApp.js +16 -7
  145. package/src/ui/{components → ink}/agentMirror.js +24 -19
  146. package/src/ui/{components → ink}/chatReducer.js +29 -7
  147. package/src/bus/messageMeta.js +0 -52
  148. package/src/chat/agentViewController.js +0 -1072
  149. package/src/chat/chatLogController.js +0 -138
  150. package/src/chat/completionController.js +0 -533
  151. package/src/chat/dashboardKeyController.js +0 -533
  152. package/src/chat/index.js +0 -2222
  153. package/src/chat/inputHistoryController.js +0 -135
  154. package/src/chat/inputListenerController.js +0 -470
  155. package/src/chat/layout.js +0 -186
  156. package/src/chat/pasteController.js +0 -81
  157. package/src/chat/statusLineController.js +0 -223
  158. package/src/chat/streamTracker.js +0 -156
  159. package/src/code/config +0 -0
  160. package/src/daemon/providerSessions.js +0 -488
  161. package/src/terminal/adapters/internalPtyAdapter.js +0 -42
  162. package/src/ui/components/DashboardBar.js +0 -417
  163. /package/src/{code/prompts → agents/prompts/native}/actions.js +0 -0
  164. /package/src/{code/prompts → agents/prompts/native}/efficiency.js +0 -0
  165. /package/src/{code/prompts → agents/prompts/native}/environment.js +0 -0
  166. /package/src/{code/prompts → agents/prompts/native}/identity.js +0 -0
  167. /package/src/{code/prompts → agents/prompts/native}/safety.js +0 -0
  168. /package/src/{code/prompts → agents/prompts/native}/sections.js +0 -0
  169. /package/src/{code/prompts → agents/prompts/native}/system.js +0 -0
  170. /package/src/{code/prompts → agents/prompts/native}/tasks.js +0 -0
  171. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/bash.js +0 -0
  172. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/edit.js +0 -0
  173. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/read.js +0 -0
  174. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/write.js +0 -0
  175. /package/src/{code/prompts → agents/prompts/native}/ufoo.js +0 -0
  176. /package/src/{group → agents/prompts}/promptProfiles.js +0 -0
  177. /package/src/{agent → agents/providers}/claudeEventTranslator.js +0 -0
  178. /package/src/{agent → agents/providers}/claudeOauthTokenReader.js +0 -0
  179. /package/src/{agent → agents/providers}/claudeSessionFiles.js +0 -0
  180. /package/src/{agent → agents/providers}/codexEventTranslator.js +0 -0
  181. /package/src/{agent → agents/providers}/credentials/claude.js +0 -0
  182. /package/src/{agent → agents/providers}/credentials/codex.js +0 -0
  183. /package/src/{agent → agents/providers}/credentials/index.js +0 -0
  184. /package/src/{chat → app/chat}/agentBar.js +0 -0
  185. /package/src/{chat → app/chat}/agentDirectory.js +0 -0
  186. /package/src/{chat → app/chat}/cronScheduler.js +0 -0
  187. /package/src/{chat → app/chat}/daemonCoordinator.js +0 -0
  188. /package/src/{chat → app/chat}/daemonReconnect.js +0 -0
  189. /package/src/{chat → app/chat}/daemonTransport.js +0 -0
  190. /package/src/{chat → app/chat}/daemonTransportDefaults.js +0 -0
  191. /package/src/{chat → app/chat}/inputMath.js +0 -0
  192. /package/src/{chat → app/chat}/projectCloseController.js +0 -0
  193. /package/src/{chat → app/chat}/rawKeyMap.js +0 -0
  194. /package/src/{chat → app/chat}/settingsController.js +0 -0
  195. /package/src/{chat → app/chat}/shellCommand.js +0 -0
  196. /package/src/{chat → app/chat}/text.js +0 -0
  197. /package/src/{chat → app/chat}/transientAgentState.js +0 -0
  198. /package/src/{cli → app/cli}/busCoreCommands.js +0 -0
  199. /package/src/{skills/index.js → app/cli/features/skills.js} +0 -0
  200. /package/src/{bus → coordination/bus}/nickname.js +0 -0
  201. /package/src/{bus → coordination/bus}/queue.js +0 -0
  202. /package/src/{context → coordination/context}/decisions.js +0 -0
  203. /package/src/{context → coordination/context}/doctor.js +0 -0
  204. /package/src/{context → coordination/context}/index.js +0 -0
  205. /package/src/{context → coordination/context}/sync.js +0 -0
  206. /package/src/{ufoo → coordination/state}/agentRegistryDiagnostics.js +0 -0
  207. /package/src/{ufoo → coordination/state}/agentsStore.js +0 -0
  208. /package/src/{ufoo → coordination/state}/paths.js +0 -0
  209. /package/src/{controller → orchestration/controller}/launchRouting.js +0 -0
  210. /package/src/{controller → orchestration/controller}/routerFastPath.js +0 -0
  211. /package/src/{controller → orchestration/controller}/routerFinalize.js +0 -0
  212. /package/src/{group → orchestration/groups}/diagram.js +0 -0
  213. /package/src/{group → orchestration/groups}/templateValidation.js +0 -0
  214. /package/src/{solo → orchestration/solo}/commands.js +0 -0
  215. /package/src/{shared → runtime/contracts}/eventContract.js +0 -0
  216. /package/src/{shared → runtime/contracts}/ptySocketContract.js +0 -0
  217. /package/src/{providerapi → runtime/privacy}/redactor.js +0 -0
  218. /package/src/{providerapi → runtime/privacy}/shadowDiff.js +0 -0
  219. /package/src/{utils → runtime/process}/nodeExecutable.js +0 -0
  220. /package/src/{projects → runtime/projects}/identity.js +0 -0
  221. /package/src/{projects → runtime/projects}/index.js +0 -0
  222. /package/src/{projects → runtime/projects}/projectId.js +0 -0
  223. /package/src/{projects → runtime/projects}/runtimes.js +0 -0
  224. /package/src/{terminal → runtime/terminal}/adapterContract.js +0 -0
  225. /package/src/{terminal → runtime/terminal}/adapters/externalAdapter.js +0 -0
  226. /package/src/{terminal → runtime/terminal}/adapters/hostAdapter.js +0 -0
  227. /package/src/{terminal → runtime/terminal}/adapters/internalQueueAdapter.js +0 -0
  228. /package/src/{terminal → runtime/terminal}/adapters/terminalAdapter.js +0 -0
  229. /package/src/{terminal → runtime/terminal}/adapters/tmuxAdapter.js +0 -0
  230. /package/src/{terminal → runtime/terminal}/detect.js +0 -0
  231. /package/src/{terminal → runtime/terminal}/index.js +0 -0
  232. /package/src/{terminal → runtime/terminal}/iterm2.js +0 -0
  233. /package/src/{utils → ui/format}/banner.js +0 -0
  234. /package/src/{shared → ui/format}/markdownRenderer.js +0 -0
  235. /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