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
@@ -35,6 +35,7 @@ const COMMAND_TREE = {
35
35
  stop: { desc: "Stop cron task by id or all" },
36
36
  },
37
37
  },
38
+ "/clear": { desc: "Clear chat log on screen" },
38
39
  "/group": {
39
40
  desc: "Agent group orchestration",
40
41
  children: {
@@ -47,13 +48,15 @@ const COMMAND_TREE = {
47
48
  },
48
49
  },
49
50
  "/init": { desc: "Initialize modules" },
51
+ "/multi": { desc: "Toggle multi-window agent view" },
50
52
  "/open": { desc: "Open project path in global mode" },
51
53
  "/launch": {
52
54
  desc: "Launch new agent",
53
55
  children: {
54
- claude: { desc: "Launch Claude agent" },
55
- codex: { desc: "Launch Codex agent" },
56
- ucode: { desc: "Launch ucode core agent" },
56
+ claude: { desc: "Launch Claude agent", order: 1 },
57
+ codex: { desc: "Launch Codex agent", order: 2 },
58
+ agy: { desc: "Launch Antigravity (agy) agent", order: 3 },
59
+ ucode: { desc: "Launch ucode core agent", order: 4 },
57
60
  },
58
61
  },
59
62
  "/project": {
@@ -136,7 +139,7 @@ const COMMAND_TREE = {
136
139
  },
137
140
  },
138
141
  "/status": { desc: "Status display" },
139
- "/ufoo": { desc: "ufoo protocol (session marker)" },
142
+ "/ufoo": { desc: "ufoo protocol" },
140
143
  };
141
144
 
142
145
  const COMMAND_ORDER = ["/launch", "/group", "/bus", "/ctx"];
@@ -196,10 +199,120 @@ function parseCommand(text) {
196
199
  return { command, args };
197
200
  }
198
201
 
202
+ function parseCommandOptions(args = []) {
203
+ const options = {};
204
+ const positional = [];
205
+ for (const arg of args) {
206
+ const raw = String(arg || "").trim();
207
+ if (!raw) continue;
208
+ if (raw.includes("=")) {
209
+ const [key, value] = raw.split("=", 2);
210
+ options[String(key || "").trim().toLowerCase()] = String(value || "").trim();
211
+ } else {
212
+ positional.push(raw);
213
+ }
214
+ }
215
+ return { options, positional };
216
+ }
217
+
218
+ function normalizeAgentLabel(value = "") {
219
+ const raw = String(value || "").trim().toLowerCase();
220
+ if (raw === "claude" || raw === "uclaude") return "claude";
221
+ if (raw === "codex" || raw === "ucodex") return "codex";
222
+ if (raw === "agy" || raw === "antigravity" || raw === "uagy") return "agy";
223
+ if (raw === "ucode" || raw === "ufoo") return "ufoo";
224
+ return raw || "agent";
225
+ }
226
+
227
+ function describeCommandForChat(text) {
228
+ const parsed = parseCommand(String(text || "").trim());
229
+ if (!parsed) return "";
230
+ const command = String(parsed.command || "").trim().toLowerCase();
231
+ const args = parsed.args || [];
232
+ const sub = String(args[0] || "").trim().toLowerCase();
233
+ const { options, positional } = parseCommandOptions(args);
234
+
235
+ if (command === "launch") {
236
+ const agent = normalizeAgentLabel(args[0]);
237
+ const nickname = options.nickname || options.nick || options.name || "";
238
+ const profile = options.profile || options.prompt_profile || "";
239
+ const count = parseInt(options.count || "1", 10);
240
+ const scope = options.scope || options.launch_scope || positional.slice(1).find((item) =>
241
+ /^(window|new-window|separate|inplace|same|current|tab|pane)$/i.test(item)
242
+ ) || "";
243
+ const base = nickname
244
+ ? `Launching a ${agent} named ${nickname}`
245
+ : (Number.isFinite(count) && count > 1 ? `Launching ${count} ${agent} agents` : `Launching a ${agent} agent`);
246
+ return `${base}${profile ? ` with profile ${profile}` : ""}${/^(window|new-window|separate)$/i.test(scope) ? " in a new window" : ""}`;
247
+ }
248
+
249
+ if (command === "group") {
250
+ if (sub === "run") return `Launching group ${args[1] || "template"}`;
251
+ if (sub === "status") return `Checking group ${args[1] || "status"}`;
252
+ if (sub === "stop") return `Stopping group ${args[1] || "run"}`;
253
+ if (sub === "diagram") return `Showing group diagram${args[1] ? ` for ${args[1]}` : ""}`;
254
+ if (sub === "template" || sub === "templates") return "Browsing group templates";
255
+ return "Managing agent groups";
256
+ }
257
+
258
+ if (command === "bus") {
259
+ if (sub === "send") return `Sending a message to ${args[1] || "an agent"}`;
260
+ if (sub === "rename") return `Renaming ${args[1] || "an agent"}${args[2] ? ` to ${args[2]}` : ""}`;
261
+ if (sub === "activate") return `Activating ${args[1] || "an agent"}`;
262
+ if (sub === "list") return "Listing active agents";
263
+ if (sub === "status") return "Checking bus status";
264
+ return "Using the event bus";
265
+ }
266
+
267
+ if (command === "daemon") {
268
+ if (sub === "start") return "Starting the ufoo daemon";
269
+ if (sub === "stop") return "Stopping the ufoo daemon";
270
+ if (sub === "restart") return "Restarting the ufoo daemon";
271
+ if (sub === "status") return "Checking daemon status";
272
+ return "Managing the ufoo daemon";
273
+ }
274
+
275
+ if (command === "project") {
276
+ if (sub === "switch") return `Switching to project ${args[1] || ""}`.trim();
277
+ if (sub === "current") return "Showing current project";
278
+ if (sub === "list") return "Listing running projects";
279
+ return "Managing projects";
280
+ }
281
+
282
+ if (command === "solo") {
283
+ if (sub === "run") return `Launching solo role ${args[1] || "agent"}`;
284
+ if (sub === "list") return "Listing solo roles";
285
+ return "Managing solo agents";
286
+ }
287
+
288
+ if (command === "role") {
289
+ if (sub === "assign") return `Assigning role ${args[2] || ""}${args[1] ? ` to ${args[1]}` : ""}`.trim();
290
+ if (sub === "list") return "Listing roles";
291
+ return "Managing roles";
292
+ }
293
+
294
+ if (command === "cron") {
295
+ if (sub === "start") return "Creating a cron task";
296
+ if (sub === "stop") return `Stopping cron task ${args[1] || ""}`.trim();
297
+ if (sub === "list") return "Listing cron tasks";
298
+ return "Managing cron tasks";
299
+ }
300
+
301
+ if (command === "settings") return !sub || sub === "show" ? "Showing settings" : "Updating settings";
302
+ if (command === "ctx") return `Checking context${sub ? ` ${sub}` : ""}`;
303
+ if (command === "doctor") return "Running ufoo diagnostics";
304
+ if (command === "clear") return "Clearing the chat log";
305
+ if (command === "multi") return "Toggling multi-pane view";
306
+ if (command === "open") return `Opening project ${args[0] || ""}`.trim();
307
+ if (command === "resume") return args[0] === "list" ? "Listing recoverable agents" : `Resuming ${args[0] || "agents"}`;
308
+ if (command === "init") return "Initializing ufoo modules";
309
+
310
+ return `Running /${command}`;
311
+ }
312
+
199
313
  function shouldEchoCommandInChat(text) {
200
314
  const parsed = parseCommand(String(text || "").trim());
201
315
  if (!parsed) return true;
202
- if (parsed.command === "group" && parsed.args[0] === "run") return false;
203
316
  return true;
204
317
  }
205
318
 
@@ -222,6 +335,7 @@ module.exports = {
222
335
  sortCommands,
223
336
  buildCommandRegistry,
224
337
  parseCommand,
338
+ describeCommandForChat,
225
339
  shouldEchoCommandInChat,
226
340
  parseAtTarget,
227
341
  };
@@ -1,4 +1,4 @@
1
- const { IPC_REQUEST_TYPES } = require("../shared/eventContract");
1
+ const { IPC_REQUEST_TYPES } = require("../../runtime/contracts/eventContract");
2
2
 
3
3
  function createDaemonConnection(options = {}) {
4
4
  const {
@@ -1,5 +1,5 @@
1
- const { IPC_RESPONSE_TYPES, BUS_STATUS_PHASES } = require("../shared/eventContract");
2
- const { renderMarkdownLines } = require("../shared/markdownRenderer");
1
+ const { IPC_RESPONSE_TYPES, BUS_STATUS_PHASES } = require("../../runtime/contracts/eventContract");
2
+ const { renderMarkdownLines } = require("../../ui/format/markdownRenderer");
3
3
  const { decodeEscapedNewlines } = require("./text");
4
4
 
5
5
  function createDaemonMessageRouter(options = {}) {
@@ -47,6 +47,45 @@ function createDaemonMessageRouter(options = {}) {
47
47
  return `{cyan-fg}${escapedLabel}{/cyan-fg} {gray-fg}·{/gray-fg} `;
48
48
  }
49
49
 
50
+ function launchTargetLabel(result = {}, renameResult = null) {
51
+ const nickname = (renameResult && renameResult.ok && renameResult.nickname)
52
+ || result.nickname
53
+ || "";
54
+ if (nickname) return nickname;
55
+ const ids = Array.isArray(result.subscriber_ids) ? result.subscriber_ids : [];
56
+ return ids[0] || result.agent_id || "";
57
+ }
58
+
59
+ function buildLifecycleSummary(payload = {}, msg = {}) {
60
+ const ops = Array.isArray(payload.ops) ? payload.ops : [];
61
+ const results = Array.isArray(msg.opsResults) ? msg.opsResults : [];
62
+ if (ops.length === 0) return "";
63
+ const launchOp = ops.find((op) => op && op.action === "launch");
64
+ if (launchOp) {
65
+ const launchResult = results.find((item) => item && item.action === "launch") || {};
66
+ const renameResult = results.find((item) => item && item.action === "rename" && item.ok);
67
+ if (launchResult.ok === false) {
68
+ return `Launch failed: ${launchResult.error || "unknown error"}`;
69
+ }
70
+ const agent = String(launchResult.agent || launchOp.agent || "agent").trim();
71
+ const count = Number(launchResult.count || launchOp.count || 1);
72
+ const ids = Array.isArray(launchResult.subscriber_ids) ? launchResult.subscriber_ids.filter(Boolean) : [];
73
+ const target = launchTargetLabel(launchResult, renameResult);
74
+ if (launchResult.skipped && target) return `Reused ${agent}:${target}`;
75
+ if (ids.length > 1) return `Launched ${ids.length} ${agent} agents: ${ids.join(", ")}`;
76
+ if (target) return `Launched ${agent}:${target}`;
77
+ if (count > 1) return `Launched ${count} ${agent} agents`;
78
+ return `Launched a ${agent} agent`;
79
+ }
80
+ const closeOp = ops.find((op) => op && op.action === "close");
81
+ if (closeOp) {
82
+ const closeResult = results.find((item) => item && item.action === "close") || {};
83
+ if (closeResult.ok === false) return `Close failed: ${closeResult.error || "unknown error"}`;
84
+ return `Closed ${closeResult.agent_id || closeOp.agent_id || closeOp.target || "agent"}`;
85
+ }
86
+ return "";
87
+ }
88
+
50
89
  function normalizeDisplayMessage(raw) {
51
90
  let displayMessage = raw || "";
52
91
  let streamPayload = null;
@@ -223,7 +262,10 @@ function createDaemonMessageRouter(options = {}) {
223
262
  /^Group started\b/i.test(replyText)
224
263
  );
225
264
  // Suppress lifecycle confirmations from chat history — status line plus structured payload is enough.
226
- if (!isLifecycleStatusOnly && !isGroupStartedConfirmation) {
265
+ if (isLifecycleStatusOnly) {
266
+ const summary = buildLifecycleSummary(payload, msg);
267
+ if (summary) logMessage("reply", `${speakerPrefix("ufoo", "white")}${escapeBlessed(summary)}`);
268
+ } else if (!isGroupStartedConfirmation) {
227
269
  logMessage("reply", `${speakerPrefix("ufoo", "white")}${escapeBlessed(replyText)}`);
228
270
  }
229
271
  }
@@ -415,7 +457,15 @@ function createDaemonMessageRouter(options = {}) {
415
457
  const delta = typeof streamPayload.delta === "string"
416
458
  ? decodeEscapedNewlines(streamPayload.delta)
417
459
  : "";
418
- if (delta) writeToAgentTerm(delta);
460
+ if (delta || streamPayload.done) {
461
+ writeToAgentTerm(delta, {
462
+ data,
463
+ publisher,
464
+ streamPayload,
465
+ done: Boolean(streamPayload.done),
466
+ reason: streamPayload.reason || "",
467
+ });
468
+ }
419
469
  } else if (displayMessage) {
420
470
  writeToAgentTerm(`${displayMessage}\r\n`);
421
471
  }
@@ -29,6 +29,7 @@ function createDaemonTransport(options = {}) {
29
29
 
30
30
  async function connectClientForTarget(override = {}) {
31
31
  const target = resolveTarget(override);
32
+ const autoStart = override.autoStart !== false;
32
33
  let client = await connectWithRetry(
33
34
  target.sockPath,
34
35
  primaryRetries,
@@ -39,7 +40,7 @@ function createDaemonTransport(options = {}) {
39
40
  // Retry once with a fresh daemon start and longer wait.
40
41
  // Check if a restart is already in progress via the explicit restart flow.
41
42
  const isExplicitRestartInProgress = restartLocks.get(target.projectRoot);
42
- if (!isExplicitRestartInProgress && !isRunning(target.projectRoot)) {
43
+ if (autoStart && !isExplicitRestartInProgress && !isRunning(target.projectRoot)) {
43
44
  startDaemon(target.projectRoot);
44
45
  await new Promise((resolve) => setTimeout(resolve, restartDelayMs));
45
46
  }
@@ -1,9 +1,10 @@
1
1
  const { clampAgentWindowWithSelection } = require("./agentDirectory");
2
2
 
3
- const DEFAULT_MODE_OPTIONS = ["auto", "host", "terminal", "tmux", "internal-pty", "internal"];
3
+ const DEFAULT_MODE_OPTIONS = ["auto", "host", "terminal", "tmux", "internal"];
4
4
 
5
5
  function providerLabel(value) {
6
6
  if (value === "claude-cli") return "claude";
7
+ if (value === "agy-cli" || value === "agy" || value === "antigravity") return "agy";
7
8
  if (value === "ucode" || value === "ufoo" || value === "ufoo-code") return "ucode";
8
9
  return "codex";
9
10
  }
@@ -174,11 +175,9 @@ function buildDashboardDetailLine(options = {}) {
174
175
  getAgentState = () => "",
175
176
  selectedModeIndex = 0,
176
177
  selectedProviderIndex = 0,
177
- selectedResumeIndex = 0,
178
178
  selectedCronIndex = -1,
179
179
  cronTasks = [],
180
180
  providerOptions = [],
181
- resumeOptions = [],
182
181
  dashHints = {},
183
182
  modeOptions = DEFAULT_MODE_OPTIONS,
184
183
  } = options;
@@ -210,18 +209,6 @@ function buildDashboardDetailLine(options = {}) {
210
209
  return { content, windowStart };
211
210
  }
212
211
 
213
- if (dashboardView === "resume") {
214
- const resumeParts = resumeOptions.map((opt, i) => {
215
- if (i === selectedResumeIndex) {
216
- return `{inverse}${opt.label}{/inverse}`;
217
- }
218
- return `{cyan-fg}${opt.label}{/cyan-fg}`;
219
- });
220
- content += `{gray-fg}Resume:{/gray-fg} ${resumeParts.join(" ")}`;
221
- content += ` {gray-fg}│ ${dashHints.resume || ""}{/gray-fg}`;
222
- return { content, windowStart };
223
- }
224
-
225
212
  if (dashboardView === "cron") {
226
213
  const items = Array.isArray(cronTasks) ? cronTasks : [];
227
214
  const summary = items.length > 0
@@ -295,13 +282,11 @@ function computeDashboardContent(options = {}) {
295
282
  agentProvider = "codex-cli",
296
283
  selectedModeIndex = 0,
297
284
  selectedProviderIndex = 0,
298
- selectedResumeIndex = 0,
299
285
  selectedCronIndex = -1,
300
286
  cronTasks = [],
301
287
  loopSummary = null,
302
288
  pendingReports = 0,
303
289
  providerOptions = [],
304
- resumeOptions = [],
305
290
  dashHints = {},
306
291
  modeOptions = DEFAULT_MODE_OPTIONS,
307
292
  } = options;
@@ -357,11 +342,9 @@ function computeDashboardContent(options = {}) {
357
342
  getAgentState,
358
343
  selectedModeIndex,
359
344
  selectedProviderIndex,
360
- selectedResumeIndex,
361
345
  selectedCronIndex,
362
346
  cronTasks,
363
347
  providerOptions,
364
- resumeOptions,
365
348
  dashHints,
366
349
  modeOptions,
367
350
  });
@@ -383,11 +366,9 @@ function computeDashboardContent(options = {}) {
383
366
  getAgentState,
384
367
  selectedModeIndex,
385
368
  selectedProviderIndex,
386
- selectedResumeIndex,
387
369
  selectedCronIndex,
388
370
  cronTasks,
389
371
  providerOptions,
390
- resumeOptions,
391
372
  dashHints,
392
373
  modeOptions,
393
374
  });
@@ -0,0 +1,6 @@
1
+ async function runChat(projectRoot, options = {}) {
2
+ const { runChatInk } = require("../../ui/ink/ChatApp");
3
+ return runChatInk(projectRoot, options);
4
+ }
5
+
6
+ module.exports = { runChat };
@@ -1,6 +1,7 @@
1
- const { IPC_REQUEST_TYPES } = require("../shared/eventContract");
1
+ const { IPC_REQUEST_TYPES } = require("../../runtime/contracts/eventContract");
2
2
  const { decodeEscapedNewlines } = require("./text");
3
- const { shouldEchoCommandInChat } = require("./commands");
3
+ const { describeCommandForChat, shouldEchoCommandInChat } = require("./commands");
4
+ const { parseShellCommand, runShellCommand: defaultRunShellCommand } = require("./shellCommand");
4
5
 
5
6
  function createInputSubmitHandler(options = {}) {
6
7
  const {
@@ -19,11 +20,11 @@ function createInputSubmitHandler(options = {}) {
19
20
  enterAgentView = () => {},
20
21
  getAgentAdapter = () => null,
21
22
  activateAgent = async () => {},
22
- getInjectSockPath = () => "",
23
- existsSync = () => false,
24
23
  commitInputHistory = () => {},
25
24
  focusInput = () => {},
26
25
  renderScreen = () => {}, // Add renderScreen callback
26
+ runShellCommand = defaultRunShellCommand,
27
+ getShellCwd = () => process.cwd(),
27
28
  } = options;
28
29
 
29
30
  if (!state || typeof state !== "object") {
@@ -39,17 +40,9 @@ function createInputSubmitHandler(options = {}) {
39
40
  async function tryActivateTargetAgent(agentId) {
40
41
  const adapter = getAgentAdapter(agentId);
41
42
  const capabilities = adapter && adapter.capabilities ? adapter.capabilities : null;
42
- const sockPath = getInjectSockPath(agentId);
43
- const supportsSocket = Boolean(capabilities && capabilities.supportsSocketProtocol);
44
43
  const supportsActivate = Boolean(capabilities && capabilities.supportsActivate);
45
44
  const supportsInternalQueue = Boolean(capabilities && capabilities.supportsInternalQueueLoop);
46
45
 
47
- if (existsSync(sockPath) && supportsSocket) {
48
- clearTargetAgent();
49
- enterAgentView(agentId);
50
- return true;
51
- }
52
-
53
46
  if (supportsActivate) {
54
47
  clearTargetAgent();
55
48
  try {
@@ -90,6 +83,37 @@ function createInputSubmitHandler(options = {}) {
90
83
 
91
84
  commitInputHistory(text);
92
85
 
86
+ const shellCommand = parseShellCommand(text);
87
+ if (shellCommand) {
88
+ logMessage("user", `{gray-fg}!{/gray-fg} ${escapeBlessed(shellCommand)}`);
89
+ queueStatusLine(`Running: ${escapeBlessed(shellCommand)}`);
90
+ renderScreen();
91
+ try {
92
+ const result = await runShellCommand(shellCommand, { cwd: getShellCwd() });
93
+ const stdout = String(result && result.stdout ? result.stdout : "").trimEnd();
94
+ const stderr = String(result && result.stderr ? result.stderr : "").trimEnd();
95
+ if (stdout) {
96
+ stdout.split(/\r?\n/).forEach((line) => logMessage("system", escapeBlessed(line)));
97
+ }
98
+ if (stderr) {
99
+ stderr.split(/\r?\n/).forEach((line) => logMessage(result && result.ok ? "system" : "error", escapeBlessed(line)));
100
+ }
101
+ if (!stdout && !stderr) {
102
+ logMessage("system", "{gray-fg}(no output){/gray-fg}");
103
+ }
104
+ if (result && result.ok) {
105
+ queueStatusLine(`Done: ${escapeBlessed(shellCommand)}`);
106
+ } else {
107
+ const suffix = result && result.signal ? ` signal ${result.signal}` : ` exit ${result && result.code != null ? result.code : 1}`;
108
+ logMessage("error", `{white-fg}✗{/white-fg} Command failed:${escapeBlessed(suffix)}`);
109
+ }
110
+ } catch (err) {
111
+ logMessage("error", `{white-fg}✗{/white-fg} Command error: ${escapeBlessed(err && err.message ? err.message : err)}`);
112
+ }
113
+ focusInput();
114
+ return;
115
+ }
116
+
93
117
  if (state.targetAgent) {
94
118
  const label = getAgentLabel(state.targetAgent);
95
119
  logMessage(
@@ -145,7 +169,8 @@ function createInputSubmitHandler(options = {}) {
145
169
 
146
170
  if (text.startsWith("/")) {
147
171
  if (shouldEchoCommandInChat(text)) {
148
- logMessage("user", userEcho(text));
172
+ const commandSummary = describeCommandForChat(text);
173
+ logMessage("user", userEcho(commandSummary || text));
149
174
  renderScreen(); // Render slash command immediately
150
175
  }
151
176
  try {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require("fs");
4
4
  const path = require("path");
5
- const { getUfooPaths } = require("../ufoo/paths");
5
+ const { getUfooPaths } = require("../../coordination/state/paths");
6
6
 
7
7
  function stripAnsi(text = "") {
8
8
  return String(text || "").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "")