u-foo 2.3.31 → 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 (236) 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 +9 -5
  12. package/scripts/chat-app-smoke.js +30 -0
  13. package/scripts/global-chat-switch-benchmark.js +5 -5
  14. package/scripts/ink-demo.js +23 -0
  15. package/scripts/ink-smoke.js +30 -0
  16. package/scripts/ucode-app-smoke.js +36 -0
  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 +56 -28
  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 +54 -4
  53. package/src/{chat → app/chat}/daemonTransport.js +2 -1
  54. package/src/{chat → app/chat}/dashboardView.js +2 -21
  55. package/src/app/chat/index.js +6 -0
  56. package/src/{chat → app/chat}/inputSubmitHandler.js +38 -13
  57. package/src/{chat → app/chat}/internalAgentLogHistory.js +1 -1
  58. package/src/app/chat/multiWindow/index.js +268 -0
  59. package/src/app/chat/multiWindow/paneLayout.js +84 -0
  60. package/src/app/chat/multiWindow/paneManager.js +299 -0
  61. package/src/app/chat/multiWindow/renderer.js +384 -0
  62. package/src/app/chat/multiWindow/virtualTerminal.js +327 -0
  63. package/src/{chat → app/chat}/projectCloseController.js +1 -1
  64. package/src/app/chat/shellCommand.js +42 -0
  65. package/src/{chat → app/chat}/transport.js +16 -3
  66. package/src/{cli → app/cli}/ctxCoreCommands.js +3 -3
  67. package/src/{doctor/index.js → app/cli/features/doctor.js} +1 -1
  68. package/src/{init/index.js → app/cli/features/init.js} +14 -32
  69. package/src/{cli → app/cli}/groupCoreCommands.js +2 -2
  70. package/src/app/cli/index.js +9 -0
  71. package/src/{cli → app/cli}/onlineCoreCommands.js +5 -5
  72. package/src/{cli.js → app/cli/run.js} +62 -59
  73. package/src/app/index.js +6 -0
  74. package/src/code/agent.js +10 -9
  75. package/src/code/index.js +2 -0
  76. package/src/code/launcher/index.js +9 -0
  77. package/src/{agent → code/launcher}/ucode.js +7 -8
  78. package/src/{agent → code/launcher}/ucodeBootstrap.js +3 -3
  79. package/src/{agent → code/launcher}/ucodeBuild.js +2 -2
  80. package/src/{agent → code/launcher}/ucodeDoctor.js +2 -2
  81. package/src/{agent → code/launcher}/ucodeRuntimeConfig.js +1 -2
  82. package/src/code/nativeRunner.js +4 -4
  83. package/src/code/taskDecomposer.js +5 -4
  84. package/src/code/tui.js +39 -1997
  85. package/src/config.js +15 -2
  86. package/src/{bus → coordination/bus}/activate.js +2 -2
  87. package/src/{bus → coordination/bus}/daemon.js +15 -5
  88. package/src/coordination/bus/envelope.js +173 -0
  89. package/src/{bus → coordination/bus}/index.js +7 -3
  90. package/src/{bus → coordination/bus}/inject.js +11 -3
  91. package/src/{bus → coordination/bus}/message.js +1 -1
  92. package/src/coordination/bus/messageMeta.js +130 -0
  93. package/src/coordination/bus/promptEnvelope.js +65 -0
  94. package/src/{bus → coordination/bus}/shake.js +1 -1
  95. package/src/{bus → coordination/bus}/store.js +3 -3
  96. package/src/{bus → coordination/bus}/subscriber.js +2 -2
  97. package/src/{bus → coordination/bus}/utils.js +2 -2
  98. package/src/{history → coordination/history}/inputTimeline.js +5 -5
  99. package/src/coordination/index.js +10 -0
  100. package/src/{memory → coordination/memory}/historySearch.js +1 -1
  101. package/src/{memory → coordination/memory}/index.js +3 -3
  102. package/src/{report → coordination/report}/store.js +2 -2
  103. package/src/{ufoo → coordination/state}/agentRegistryDiagnostics.js +43 -0
  104. package/src/{status → coordination/status}/index.js +3 -3
  105. package/src/online/bridge.js +2 -2
  106. package/src/{controller → orchestration/controller}/flags.js +1 -1
  107. package/src/{controller → orchestration/controller}/gateRouter.js +1 -1
  108. package/src/orchestration/controller/index.js +10 -0
  109. package/src/{controller → orchestration/controller}/shadowGuard.js +1 -1
  110. package/src/orchestration/groups/bootstrap.js +3 -0
  111. package/src/orchestration/groups/index.js +10 -0
  112. package/src/orchestration/groups/promptProfiles.js +3 -0
  113. package/src/{group → orchestration/groups}/templates.js +1 -1
  114. package/src/{group → orchestration/groups}/validateTemplate.js +1 -1
  115. package/src/orchestration/index.js +7 -0
  116. package/src/orchestration/solo/index.js +3 -0
  117. package/src/{daemon → runtime/daemon}/agentProcessManager.js +1 -1
  118. package/src/{daemon → runtime/daemon}/cronOps.js +3 -2
  119. package/src/{daemon → runtime/daemon}/groupOrchestrator.js +26 -9
  120. package/src/{daemon → runtime/daemon}/index.js +273 -79
  121. package/src/{daemon → runtime/daemon}/ipcServer.js +24 -2
  122. package/src/{daemon → runtime/daemon}/nicknameScope.js +6 -3
  123. package/src/{daemon → runtime/daemon}/ops.js +48 -61
  124. package/src/{daemon → runtime/daemon}/promptLoop.js +1 -1
  125. package/src/{daemon → runtime/daemon}/promptRequest.js +13 -8
  126. package/src/runtime/daemon/providerSessions.js +230 -0
  127. package/src/{daemon → runtime/daemon}/reporting.js +4 -4
  128. package/src/{daemon → runtime/daemon}/run.js +12 -5
  129. package/src/{daemon → runtime/daemon}/soloBootstrap.js +7 -7
  130. package/src/{daemon → runtime/daemon}/status.js +5 -5
  131. package/src/runtime/index.js +10 -0
  132. package/src/runtime/process/nodeExecutable.js +26 -0
  133. package/src/{projects → runtime/projects}/registry.js +1 -1
  134. package/src/{projects → runtime/projects}/runtimes.js +1 -1
  135. package/src/{terminal → runtime/terminal}/adapterRouter.js +0 -10
  136. package/src/{terminal → runtime/terminal}/adapters/internalAdapter.js +0 -4
  137. package/src/tools/handlers/common.js +1 -1
  138. package/src/tools/handlers/listAgents.js +1 -1
  139. package/src/tools/handlers/memory.js +3 -3
  140. package/src/tools/handlers/readBusSummary.js +1 -1
  141. package/src/tools/handlers/readOpenDecisions.js +1 -1
  142. package/src/tools/handlers/readProjectRegistry.js +1 -1
  143. package/src/tools/handlers/readPromptHistory.js +2 -2
  144. package/src/tools/schemaFixtures.js +1 -1
  145. package/src/ui/MIGRATION.md +336 -0
  146. package/src/ui/format/index.js +974 -0
  147. package/src/ui/index.js +9 -0
  148. package/src/ui/ink/ChatApp.js +3674 -0
  149. package/src/ui/ink/DashboardBar.js +685 -0
  150. package/src/ui/ink/InkDemo.js +96 -0
  151. package/src/ui/ink/MultilineInput.js +612 -0
  152. package/src/ui/ink/UcodeApp.js +822 -0
  153. package/src/ui/ink/agentMirror.js +730 -0
  154. package/src/ui/ink/chatReducer.js +359 -0
  155. package/src/ui/runInk.js +57 -0
  156. package/src/bus/messageMeta.js +0 -52
  157. package/src/chat/agentViewController.js +0 -1072
  158. package/src/chat/chatLogController.js +0 -138
  159. package/src/chat/completionController.js +0 -533
  160. package/src/chat/dashboardKeyController.js +0 -573
  161. package/src/chat/index.js +0 -2214
  162. package/src/chat/inputHistoryController.js +0 -135
  163. package/src/chat/inputListenerController.js +0 -470
  164. package/src/chat/layout.js +0 -186
  165. package/src/chat/pasteController.js +0 -81
  166. package/src/chat/statusLineController.js +0 -223
  167. package/src/chat/streamTracker.js +0 -156
  168. package/src/code/config +0 -0
  169. package/src/daemon/providerSessions.js +0 -488
  170. package/src/terminal/adapters/internalPtyAdapter.js +0 -42
  171. /package/src/{code/prompts → agents/prompts/native}/actions.js +0 -0
  172. /package/src/{code/prompts → agents/prompts/native}/efficiency.js +0 -0
  173. /package/src/{code/prompts → agents/prompts/native}/environment.js +0 -0
  174. /package/src/{code/prompts → agents/prompts/native}/identity.js +0 -0
  175. /package/src/{code/prompts → agents/prompts/native}/safety.js +0 -0
  176. /package/src/{code/prompts → agents/prompts/native}/sections.js +0 -0
  177. /package/src/{code/prompts → agents/prompts/native}/system.js +0 -0
  178. /package/src/{code/prompts → agents/prompts/native}/tasks.js +0 -0
  179. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/bash.js +0 -0
  180. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/edit.js +0 -0
  181. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/read.js +0 -0
  182. /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/write.js +0 -0
  183. /package/src/{code/prompts → agents/prompts/native}/ufoo.js +0 -0
  184. /package/src/{group → agents/prompts}/promptProfiles.js +0 -0
  185. /package/src/{agent → agents/providers}/claudeEventTranslator.js +0 -0
  186. /package/src/{agent → agents/providers}/claudeOauthTokenReader.js +0 -0
  187. /package/src/{agent → agents/providers}/claudeSessionFiles.js +0 -0
  188. /package/src/{agent → agents/providers}/codexEventTranslator.js +0 -0
  189. /package/src/{agent → agents/providers}/credentials/claude.js +0 -0
  190. /package/src/{agent → agents/providers}/credentials/codex.js +0 -0
  191. /package/src/{agent → agents/providers}/credentials/index.js +0 -0
  192. /package/src/{chat → app/chat}/agentBar.js +0 -0
  193. /package/src/{chat → app/chat}/agentDirectory.js +0 -0
  194. /package/src/{chat → app/chat}/cronScheduler.js +0 -0
  195. /package/src/{chat → app/chat}/daemonCoordinator.js +0 -0
  196. /package/src/{chat → app/chat}/daemonReconnect.js +0 -0
  197. /package/src/{chat → app/chat}/daemonTransportDefaults.js +0 -0
  198. /package/src/{chat → app/chat}/inputMath.js +0 -0
  199. /package/src/{chat → app/chat}/rawKeyMap.js +0 -0
  200. /package/src/{chat → app/chat}/settingsController.js +0 -0
  201. /package/src/{chat → app/chat}/text.js +0 -0
  202. /package/src/{chat → app/chat}/transientAgentState.js +0 -0
  203. /package/src/{cli → app/cli}/busCoreCommands.js +0 -0
  204. /package/src/{skills/index.js → app/cli/features/skills.js} +0 -0
  205. /package/src/{bus → coordination/bus}/nickname.js +0 -0
  206. /package/src/{bus → coordination/bus}/queue.js +0 -0
  207. /package/src/{context → coordination/context}/decisions.js +0 -0
  208. /package/src/{context → coordination/context}/doctor.js +0 -0
  209. /package/src/{context → coordination/context}/index.js +0 -0
  210. /package/src/{context → coordination/context}/sync.js +0 -0
  211. /package/src/{ufoo → coordination/state}/agentsStore.js +0 -0
  212. /package/src/{ufoo → coordination/state}/paths.js +0 -0
  213. /package/src/{controller → orchestration/controller}/launchRouting.js +0 -0
  214. /package/src/{controller → orchestration/controller}/routerFastPath.js +0 -0
  215. /package/src/{controller → orchestration/controller}/routerFinalize.js +0 -0
  216. /package/src/{group → orchestration/groups}/diagram.js +0 -0
  217. /package/src/{group → orchestration/groups}/templateValidation.js +0 -0
  218. /package/src/{solo → orchestration/solo}/commands.js +0 -0
  219. /package/src/{shared → runtime/contracts}/eventContract.js +0 -0
  220. /package/src/{shared → runtime/contracts}/ptySocketContract.js +0 -0
  221. /package/src/{providerapi → runtime/privacy}/redactor.js +0 -0
  222. /package/src/{providerapi → runtime/privacy}/shadowDiff.js +0 -0
  223. /package/src/{projects → runtime/projects}/identity.js +0 -0
  224. /package/src/{projects → runtime/projects}/index.js +0 -0
  225. /package/src/{projects → runtime/projects}/projectId.js +0 -0
  226. /package/src/{terminal → runtime/terminal}/adapterContract.js +0 -0
  227. /package/src/{terminal → runtime/terminal}/adapters/externalAdapter.js +0 -0
  228. /package/src/{terminal → runtime/terminal}/adapters/hostAdapter.js +0 -0
  229. /package/src/{terminal → runtime/terminal}/adapters/internalQueueAdapter.js +0 -0
  230. /package/src/{terminal → runtime/terminal}/adapters/terminalAdapter.js +0 -0
  231. /package/src/{terminal → runtime/terminal}/adapters/tmuxAdapter.js +0 -0
  232. /package/src/{terminal → runtime/terminal}/detect.js +0 -0
  233. /package/src/{terminal → runtime/terminal}/index.js +0 -0
  234. /package/src/{terminal → runtime/terminal}/iterm2.js +0 -0
  235. /package/src/{utils → ui/format}/banner.js +0 -0
  236. /package/src/{shared → ui/format}/markdownRenderer.js +0 -0
@@ -1,573 +0,0 @@
1
- const DEFAULT_MODE_OPTIONS = ["auto", "host", "terminal", "tmux", "internal-pty", "internal"];
2
-
3
- function createDashboardKeyController(options = {}) {
4
- const {
5
- state,
6
- globalMode = false,
7
- existsSync = () => false,
8
- getInjectSockPath = () => "",
9
- getAgentAdapter = () => null,
10
- activateAgent = () => {},
11
- requestCloseAgent = () => {},
12
- enterAgentView = () => {},
13
- exitAgentView = () => {},
14
- setAgentBarVisible = () => {},
15
- requestAgentSnapshot = () => {},
16
- clearTargetAgent = () => {},
17
- restoreTargetFromSelection = () => {},
18
- exitDashboardMode = () => {},
19
- setLaunchMode = () => {},
20
- setAgentProvider = () => {},
21
- setAutoResume = () => {},
22
- clampAgentWindow = () => {},
23
- clampAgentWindowWithSelection = () => {},
24
- requestProjectSwitch = () => {},
25
- requestCloseProject = () => {},
26
- requestCron = () => {},
27
- setGlobalScope = () => {},
28
- getGlobalScope = () => "",
29
- renderDashboard = () => {},
30
- renderAgentDashboard = () => {},
31
- renderScreen = () => {},
32
- setScreenGrabKeys = () => {},
33
- modeOptions = DEFAULT_MODE_OPTIONS,
34
- } = options;
35
-
36
- if (!state || typeof state !== "object") {
37
- throw new Error("createDashboardKeyController requires a mutable state object");
38
- }
39
-
40
- function renderDashboardAndScreen() {
41
- renderDashboard();
42
- renderScreen();
43
- }
44
-
45
- function getAgentCapabilities(agentId) {
46
- const adapter = getAgentAdapter(agentId);
47
- return adapter && adapter.capabilities ? adapter.capabilities : null;
48
- }
49
-
50
- function supportsActivate(agentId) {
51
- const caps = getAgentCapabilities(agentId);
52
- return Boolean(caps && caps.supportsActivate);
53
- }
54
-
55
- function supportsSocket(agentId) {
56
- const caps = getAgentCapabilities(agentId);
57
- return Boolean(caps && caps.supportsSocketProtocol);
58
- }
59
-
60
- function supportsInternalQueue(agentId) {
61
- const caps = getAgentCapabilities(agentId);
62
- return Boolean(caps && caps.supportsInternalQueueLoop);
63
- }
64
-
65
- function withAgentInputFocus() {
66
- state.focusMode = "input";
67
- state.agentOutputSuppressed = false;
68
- setAgentBarVisible(true);
69
- }
70
-
71
- function activateExternalAgent(agentId) {
72
- try {
73
- activateAgent(agentId);
74
- } catch {
75
- // Activation is best-effort.
76
- }
77
- }
78
-
79
- function switchAgentView(agentId) {
80
- withAgentInputFocus();
81
- enterAgentView(agentId, { useBus: supportsInternalQueue(agentId) && !supportsSocket(agentId) });
82
- }
83
-
84
- function exitAgentDashboardToInput() {
85
- withAgentInputFocus();
86
- renderAgentDashboard();
87
- requestAgentSnapshot();
88
- }
89
-
90
- function handleAgentDashboardKey(key) {
91
- const totalItems = 1 + state.activeAgents.length;
92
-
93
- if (key.name === "left") {
94
- if (state.selectedAgentIndex > 0) {
95
- state.selectedAgentIndex -= 1;
96
- }
97
- clampAgentWindowWithSelection(state.selectedAgentIndex > 0 ? state.selectedAgentIndex - 1 : -1);
98
- renderAgentDashboard();
99
- return true;
100
- }
101
-
102
- if (key.name === "right") {
103
- if (state.selectedAgentIndex < totalItems - 1) {
104
- state.selectedAgentIndex += 1;
105
- }
106
- clampAgentWindowWithSelection(state.selectedAgentIndex > 0 ? state.selectedAgentIndex - 1 : -1);
107
- renderAgentDashboard();
108
- return true;
109
- }
110
-
111
- if (key.name === "enter" || key.name === "return") {
112
- if (state.selectedAgentIndex === 0) {
113
- exitAgentView();
114
- return true;
115
- }
116
-
117
- const agentId = state.activeAgents[state.selectedAgentIndex - 1];
118
- if (!agentId) {
119
- return true;
120
- }
121
-
122
- if (agentId === state.viewingAgent) {
123
- exitAgentDashboardToInput();
124
- return true;
125
- }
126
-
127
- if (supportsActivate(agentId)) {
128
- exitAgentView();
129
- activateExternalAgent(agentId);
130
- return true;
131
- }
132
-
133
- switchAgentView(agentId);
134
- return true;
135
- }
136
-
137
- if (key.name === "up") {
138
- exitAgentDashboardToInput();
139
- return true;
140
- }
141
-
142
- if (key.name === "x" && key.ctrl) {
143
- if (state.selectedAgentIndex <= 0 || state.selectedAgentIndex > state.activeAgents.length) {
144
- return true;
145
- }
146
-
147
- const agentId = state.activeAgents[state.selectedAgentIndex - 1];
148
- const remaining = state.activeAgents.filter((id) => id !== agentId);
149
- const nextIndex = remaining.length > 0
150
- ? Math.min(state.selectedAgentIndex - 1, remaining.length - 1)
151
- : -1;
152
- const nextAgent = nextIndex >= 0 ? remaining[nextIndex] : null;
153
-
154
- if (agentId === state.viewingAgent) {
155
- if (nextAgent) {
156
- if (supportsActivate(nextAgent)) {
157
- exitAgentView();
158
- activateExternalAgent(nextAgent);
159
- } else {
160
- withAgentInputFocus();
161
- state.selectedAgentIndex = nextIndex + 1;
162
- enterAgentView(nextAgent, { useBus: supportsInternalQueue(nextAgent) && !supportsSocket(nextAgent) });
163
- }
164
- } else {
165
- exitAgentView();
166
- }
167
- } else if (nextAgent) {
168
- state.selectedAgentIndex = nextIndex + 1;
169
- renderAgentDashboard();
170
- } else {
171
- state.selectedAgentIndex = 0;
172
- renderAgentDashboard();
173
- }
174
-
175
- requestCloseAgent(agentId);
176
- return true;
177
- }
178
-
179
- return true;
180
- }
181
-
182
- function handleModeKey(key) {
183
- if (key.name === "left") {
184
- state.selectedModeIndex = state.selectedModeIndex <= 0 ? modeOptions.length - 1 : state.selectedModeIndex - 1;
185
- renderDashboardAndScreen();
186
- return true;
187
- }
188
-
189
- if (key.name === "right") {
190
- state.selectedModeIndex = state.selectedModeIndex >= modeOptions.length - 1 ? 0 : state.selectedModeIndex + 1;
191
- renderDashboardAndScreen();
192
- return true;
193
- }
194
-
195
- if (key.name === "down") {
196
- state.dashboardView = "provider";
197
- state.selectedProviderIndex = Math.max(0, (state.providerOptions || []).findIndex((opt) => opt.value === state.agentProvider));
198
- renderDashboardAndScreen();
199
- return true;
200
- }
201
-
202
- if (key.name === "up") {
203
- state.dashboardView = "agents";
204
- restoreTargetFromSelection();
205
- renderDashboardAndScreen();
206
- return true;
207
- }
208
-
209
- if (key.name === "enter" || key.name === "return") {
210
- const mode = modeOptions[state.selectedModeIndex];
211
- if (mode) setLaunchMode(mode);
212
- exitDashboardMode(false);
213
- return true;
214
- }
215
-
216
- if (key.name === "escape") {
217
- exitDashboardMode(false);
218
- return true;
219
- }
220
-
221
- return true;
222
- }
223
-
224
- function handleProviderKey(key) {
225
- if (key.name === "left") {
226
- state.selectedProviderIndex = state.selectedProviderIndex <= 0
227
- ? state.providerOptions.length - 1
228
- : state.selectedProviderIndex - 1;
229
- renderDashboardAndScreen();
230
- return true;
231
- }
232
-
233
- if (key.name === "right") {
234
- state.selectedProviderIndex = state.selectedProviderIndex >= state.providerOptions.length - 1
235
- ? 0
236
- : state.selectedProviderIndex + 1;
237
- renderDashboardAndScreen();
238
- return true;
239
- }
240
-
241
- if (key.name === "down") {
242
- state.dashboardView = "cron";
243
- const cronTasks = Array.isArray(state.cronTasks) ? state.cronTasks : [];
244
- state.selectedCronIndex = cronTasks.length > 0 ? 0 : -1;
245
- renderDashboardAndScreen();
246
- return true;
247
- }
248
-
249
- if (key.name === "up") {
250
- state.dashboardView = "mode";
251
- renderDashboardAndScreen();
252
- return true;
253
- }
254
-
255
- if (key.name === "enter" || key.name === "return") {
256
- const selected = state.providerOptions[state.selectedProviderIndex];
257
- if (selected) setAgentProvider(selected.value);
258
- exitDashboardMode(false);
259
- return true;
260
- }
261
-
262
- if (key.name === "escape") {
263
- exitDashboardMode(false);
264
- return true;
265
- }
266
-
267
- return true;
268
- }
269
-
270
- function handleCronKey(key) {
271
- const cronTasks = Array.isArray(state.cronTasks) ? state.cronTasks : [];
272
- const maxIndex = cronTasks.length - 1;
273
-
274
- if (key.name === "left") {
275
- if (maxIndex >= 0 && state.selectedCronIndex > 0) {
276
- state.selectedCronIndex -= 1;
277
- renderDashboardAndScreen();
278
- }
279
- return true;
280
- }
281
-
282
- if (key.name === "right") {
283
- if (maxIndex >= 0 && state.selectedCronIndex < maxIndex) {
284
- state.selectedCronIndex += 1;
285
- renderDashboardAndScreen();
286
- }
287
- return true;
288
- }
289
-
290
- if (key.name === "up") {
291
- state.dashboardView = "provider";
292
- renderDashboardAndScreen();
293
- return true;
294
- }
295
-
296
- if (key.name === "x" && key.ctrl) {
297
- if (maxIndex >= 0 && state.selectedCronIndex >= 0 && state.selectedCronIndex <= maxIndex) {
298
- const task = cronTasks[state.selectedCronIndex];
299
- const id = task && task.id ? String(task.id).trim() : "";
300
- if (id) {
301
- requestCron({ operation: "stop", id });
302
- return true;
303
- }
304
- }
305
- exitDashboardMode(false);
306
- return true;
307
- }
308
-
309
- if (key.name === "escape" || key.name === "enter" || key.name === "return") {
310
- exitDashboardMode(false);
311
- return true;
312
- }
313
-
314
- return true;
315
- }
316
-
317
- function handleResumeKey(key) {
318
- if (key.name === "left") {
319
- state.selectedResumeIndex = state.selectedResumeIndex <= 0
320
- ? state.resumeOptions.length - 1
321
- : state.selectedResumeIndex - 1;
322
- renderDashboardAndScreen();
323
- return true;
324
- }
325
-
326
- if (key.name === "right") {
327
- state.selectedResumeIndex = state.selectedResumeIndex >= state.resumeOptions.length - 1
328
- ? 0
329
- : state.selectedResumeIndex + 1;
330
- renderDashboardAndScreen();
331
- return true;
332
- }
333
-
334
- if (key.name === "up") {
335
- state.dashboardView = "provider";
336
- renderDashboardAndScreen();
337
- return true;
338
- }
339
-
340
- if (key.name === "enter" || key.name === "return") {
341
- const selected = state.resumeOptions[state.selectedResumeIndex];
342
- if (selected) setAutoResume(selected.value);
343
- exitDashboardMode(false);
344
- return true;
345
- }
346
-
347
- if (key.name === "escape") {
348
- exitDashboardMode(false);
349
- return true;
350
- }
351
-
352
- return true;
353
- }
354
-
355
- function handleProjectsKey(key) {
356
- const projects = Array.isArray(state.projects) ? state.projects : [];
357
- if (projects.length === 0) {
358
- if (key.name === "up" || key.name === "enter" || key.name === "return" || key.name === "escape") {
359
- exitDashboardMode(false);
360
- }
361
- return true;
362
- }
363
-
364
- if (key.name === "x" && key.ctrl) {
365
- const current = Number.isFinite(state.selectedProjectIndex) ? state.selectedProjectIndex : 0;
366
- if (current >= 0 && current < projects.length) {
367
- requestCloseProject(current);
368
- }
369
- return true;
370
- }
371
-
372
- if (key.name === "down") {
373
- state.dashboardView = "agents";
374
- if (!Array.isArray(state.activeAgents) || state.activeAgents.length === 0) {
375
- state.selectedAgentIndex = -1;
376
- } else if (!Number.isFinite(state.selectedAgentIndex) || state.selectedAgentIndex < 0) {
377
- state.selectedAgentIndex = 0;
378
- } else if (state.selectedAgentIndex >= state.activeAgents.length) {
379
- state.selectedAgentIndex = state.activeAgents.length - 1;
380
- }
381
- clampAgentWindow();
382
- syncTargetFromSelection();
383
- renderDashboardAndScreen();
384
- return true;
385
- }
386
-
387
- if (key.name === "left") {
388
- const current = Number.isFinite(state.selectedProjectIndex) ? state.selectedProjectIndex : 0;
389
- if (current > 0) {
390
- const next = current - 1;
391
- state.selectedProjectIndex = next;
392
- renderDashboardAndScreen();
393
- if (getGlobalScope() === "project") {
394
- requestProjectSwitch(next);
395
- }
396
- }
397
- return true;
398
- }
399
-
400
- if (key.name === "right") {
401
- const current = Number.isFinite(state.selectedProjectIndex) ? state.selectedProjectIndex : 0;
402
- if (current < projects.length - 1) {
403
- const next = current + 1;
404
- state.selectedProjectIndex = next;
405
- renderDashboardAndScreen();
406
- if (getGlobalScope() === "project") {
407
- requestProjectSwitch(next);
408
- }
409
- }
410
- return true;
411
- }
412
-
413
- if (key.name === "up") {
414
- exitDashboardMode(false);
415
- return true;
416
- }
417
-
418
- if (key.name === "escape") {
419
- if (getGlobalScope() === "project") {
420
- setGlobalScope("controller");
421
- }
422
- exitDashboardMode(false);
423
- return true;
424
- }
425
-
426
- if (key.name === "enter" || key.name === "return") {
427
- const current = Number.isFinite(state.selectedProjectIndex) ? state.selectedProjectIndex : 0;
428
- if (current >= 0 && current < projects.length) {
429
- const selectedRow = projects[current];
430
- const selectedProjectRoot = String((selectedRow && selectedRow.project_root) || "");
431
- if (selectedProjectRoot) {
432
- setGlobalScope("project", selectedProjectRoot);
433
- }
434
- }
435
- exitDashboardMode(false);
436
- return true;
437
- }
438
-
439
- return true;
440
- }
441
-
442
- function handleAgentsKey(key) {
443
- if (key.name === "left") {
444
- if (state.activeAgents.length > 0 && state.selectedAgentIndex > 0) {
445
- state.selectedAgentIndex -= 1;
446
- clampAgentWindow();
447
- syncTargetFromSelection();
448
- renderDashboardAndScreen();
449
- }
450
- return true;
451
- }
452
-
453
- if (key.name === "right") {
454
- if (state.activeAgents.length > 0 && state.selectedAgentIndex < state.activeAgents.length - 1) {
455
- state.selectedAgentIndex += 1;
456
- clampAgentWindow();
457
- syncTargetFromSelection();
458
- renderDashboardAndScreen();
459
- }
460
- return true;
461
- }
462
-
463
- if (key.name === "down") {
464
- clearTargetAgent();
465
- state.dashboardView = "mode";
466
- const launchModeIndex = modeOptions.indexOf(state.launchMode);
467
- state.selectedModeIndex = launchModeIndex >= 0 ? launchModeIndex : 0;
468
- renderDashboardAndScreen();
469
- return true;
470
- }
471
-
472
- if (key.name === "up") {
473
- clearTargetAgent();
474
- if (globalMode) {
475
- state.dashboardView = "projects";
476
- renderDashboardAndScreen();
477
- return true;
478
- }
479
- exitDashboardMode(false);
480
- return true;
481
- }
482
-
483
- if (key.name === "escape") {
484
- clearTargetAgent();
485
- exitDashboardMode(false);
486
- return true;
487
- }
488
-
489
- if (key.name === "x" && key.ctrl) {
490
- if (state.selectedAgentIndex >= 0 && state.selectedAgentIndex < state.activeAgents.length) {
491
- const agentId = state.activeAgents[state.selectedAgentIndex];
492
- requestCloseAgent(agentId);
493
- clearTargetAgent();
494
- exitDashboardMode(false);
495
- }
496
- return true;
497
- }
498
-
499
- if (key.name === "enter" || key.name === "return") {
500
- if (state.selectedAgentIndex >= 0 && state.selectedAgentIndex < state.activeAgents.length) {
501
- const agentId = state.activeAgents[state.selectedAgentIndex];
502
- if (supportsActivate(agentId)) {
503
- clearTargetAgent();
504
- exitDashboardMode(false);
505
- activateExternalAgent(agentId);
506
- return true;
507
- }
508
-
509
- const sockPath = getInjectSockPath(agentId);
510
- if (supportsSocket(agentId) && existsSync(sockPath)) {
511
- clearTargetAgent();
512
- state.focusMode = "input";
513
- state.dashboardView = "agents";
514
- state.selectedAgentIndex = -1;
515
- setScreenGrabKeys(false);
516
- enterAgentView(agentId);
517
- return true;
518
- }
519
-
520
- if (supportsInternalQueue(agentId)) {
521
- clearTargetAgent();
522
- state.focusMode = "input";
523
- state.dashboardView = "agents";
524
- state.selectedAgentIndex = -1;
525
- setScreenGrabKeys(false);
526
- enterAgentView(agentId, { useBus: true });
527
- return true;
528
- }
529
- }
530
-
531
- exitDashboardMode(false);
532
- return true;
533
- }
534
-
535
- return false;
536
- }
537
-
538
- function syncTargetFromSelection() {
539
- if (typeof options.syncTargetFromSelection === "function") {
540
- options.syncTargetFromSelection();
541
- }
542
- }
543
-
544
- function handleDashboardKey(key) {
545
- if (!key || state.focusMode !== "dashboard") return false;
546
-
547
- if (state.currentView === "agent") {
548
- return handleAgentDashboardKey(key);
549
- }
550
-
551
- if (globalMode && state.dashboardView === "projects") {
552
- return handleProjectsKey(key);
553
- }
554
- if (!globalMode && state.dashboardView === "projects") {
555
- return true;
556
- }
557
-
558
- if (state.dashboardView === "mode") return handleModeKey(key);
559
- if (state.dashboardView === "provider") return handleProviderKey(key);
560
- if (state.dashboardView === "resume") return handleResumeKey(key);
561
- if (state.dashboardView === "cron") return handleCronKey(key);
562
-
563
- return handleAgentsKey(key);
564
- }
565
-
566
- return {
567
- handleDashboardKey,
568
- };
569
- }
570
-
571
- module.exports = {
572
- createDashboardKeyController,
573
- };