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.
- package/README.md +157 -213
- package/README.zh-CN.md +151 -197
- package/SKILLS/ufoo/SKILL.md +8 -8
- package/bin/uagy.js +69 -0
- package/bin/uclaude.js +2 -2
- package/bin/ucode.js +4 -4
- package/bin/ucodex.js +2 -2
- package/bin/ufoo.js +5 -23
- package/modules/AGENTS.template.md +1 -1
- package/modules/bus/SKILLS/ubus/SKILL.md +35 -10
- package/package.json +9 -5
- package/scripts/chat-app-smoke.js +30 -0
- package/scripts/global-chat-switch-benchmark.js +5 -5
- package/scripts/ink-demo.js +23 -0
- package/scripts/ink-smoke.js +30 -0
- package/scripts/ucode-app-smoke.js +36 -0
- package/src/{agent → agents/activity}/activityDetector.js +39 -2
- package/src/{agent → agents/activity}/activityStatePublisher.js +1 -1
- package/src/{agent → agents/activity}/activityStateWriter.js +2 -2
- package/src/{agent → agents/activity}/activityTracker.js +1 -1
- package/src/agents/activity/index.js +8 -0
- package/src/{agent → agents/controller}/controllerToolExecutor.js +4 -4
- package/src/agents/controller/index.js +8 -0
- package/src/{agent → agents/controller}/loopObservability.js +2 -2
- package/src/{agent → agents/controller}/loopRuntime.js +1 -1
- package/src/{agent → agents/controller}/ufooAgent.js +9 -9
- package/src/agents/index.js +10 -0
- package/src/agents/internal/index.js +3 -0
- package/src/{agent → agents/internal}/internalRunner.js +45 -22
- package/src/agents/launch/agyConversation.js +159 -0
- package/src/agents/launch/index.js +12 -0
- package/src/{agent → agents/launch}/launchEnvironment.js +2 -3
- package/src/{agent → agents/launch}/launcher.js +64 -21
- package/src/{agent → agents/launch}/notifier.js +23 -12
- package/src/{agent → agents/launch}/ptyRunner.js +44 -12
- package/src/{agent → agents/launch}/ptyWrapper.js +2 -2
- package/src/{agent → agents/launch}/publisherRouting.js +1 -1
- package/src/{agent → agents/launch}/readyDetector.js +23 -0
- package/src/{agent → agents/prompts}/defaultBootstrap.js +63 -4
- package/src/{group/bootstrap.js → agents/prompts/groupBootstrap.js} +41 -6
- package/src/agents/prompts/index.js +8 -0
- package/src/{code/prompts → agents/prompts/native}/index.js +1 -1
- package/src/{agent → agents/providers}/claudeThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/codexThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/directAuthStatus.js +184 -1
- package/src/agents/providers/index.js +13 -0
- package/src/{agent → agents/providers}/upstreamTransport.js +2 -2
- package/src/{chat → app/chat}/agentSockets.js +1 -1
- package/src/{chat → app/chat}/commandExecutor.js +56 -28
- package/src/{chat → app/chat}/commands.js +119 -5
- package/src/{chat → app/chat}/daemonConnection.js +1 -1
- package/src/{chat → app/chat}/daemonMessageRouter.js +54 -4
- package/src/{chat → app/chat}/daemonTransport.js +2 -1
- package/src/{chat → app/chat}/dashboardView.js +2 -21
- package/src/app/chat/index.js +6 -0
- package/src/{chat → app/chat}/inputSubmitHandler.js +38 -13
- package/src/{chat → app/chat}/internalAgentLogHistory.js +1 -1
- package/src/app/chat/multiWindow/index.js +268 -0
- package/src/app/chat/multiWindow/paneLayout.js +84 -0
- package/src/app/chat/multiWindow/paneManager.js +299 -0
- package/src/app/chat/multiWindow/renderer.js +384 -0
- package/src/app/chat/multiWindow/virtualTerminal.js +327 -0
- package/src/{chat → app/chat}/projectCloseController.js +1 -1
- package/src/app/chat/shellCommand.js +42 -0
- package/src/{chat → app/chat}/transport.js +16 -3
- package/src/{cli → app/cli}/ctxCoreCommands.js +3 -3
- package/src/{doctor/index.js → app/cli/features/doctor.js} +1 -1
- package/src/{init/index.js → app/cli/features/init.js} +14 -32
- package/src/{cli → app/cli}/groupCoreCommands.js +2 -2
- package/src/app/cli/index.js +9 -0
- package/src/{cli → app/cli}/onlineCoreCommands.js +5 -5
- package/src/{cli.js → app/cli/run.js} +62 -59
- package/src/app/index.js +6 -0
- package/src/code/agent.js +10 -9
- package/src/code/index.js +2 -0
- package/src/code/launcher/index.js +9 -0
- package/src/{agent → code/launcher}/ucode.js +7 -8
- package/src/{agent → code/launcher}/ucodeBootstrap.js +3 -3
- package/src/{agent → code/launcher}/ucodeBuild.js +2 -2
- package/src/{agent → code/launcher}/ucodeDoctor.js +2 -2
- package/src/{agent → code/launcher}/ucodeRuntimeConfig.js +1 -2
- package/src/code/nativeRunner.js +4 -4
- package/src/code/taskDecomposer.js +5 -4
- package/src/code/tui.js +39 -1997
- package/src/config.js +15 -2
- package/src/{bus → coordination/bus}/activate.js +2 -2
- package/src/{bus → coordination/bus}/daemon.js +15 -5
- package/src/coordination/bus/envelope.js +173 -0
- package/src/{bus → coordination/bus}/index.js +7 -3
- package/src/{bus → coordination/bus}/inject.js +11 -3
- package/src/{bus → coordination/bus}/message.js +1 -1
- package/src/coordination/bus/messageMeta.js +130 -0
- package/src/coordination/bus/promptEnvelope.js +65 -0
- package/src/{bus → coordination/bus}/shake.js +1 -1
- package/src/{bus → coordination/bus}/store.js +3 -3
- package/src/{bus → coordination/bus}/subscriber.js +2 -2
- package/src/{bus → coordination/bus}/utils.js +2 -2
- package/src/{history → coordination/history}/inputTimeline.js +5 -5
- package/src/coordination/index.js +10 -0
- package/src/{memory → coordination/memory}/historySearch.js +1 -1
- package/src/{memory → coordination/memory}/index.js +3 -3
- package/src/{report → coordination/report}/store.js +2 -2
- package/src/{ufoo → coordination/state}/agentRegistryDiagnostics.js +43 -0
- package/src/{status → coordination/status}/index.js +3 -3
- package/src/online/bridge.js +2 -2
- package/src/{controller → orchestration/controller}/flags.js +1 -1
- package/src/{controller → orchestration/controller}/gateRouter.js +1 -1
- package/src/orchestration/controller/index.js +10 -0
- package/src/{controller → orchestration/controller}/shadowGuard.js +1 -1
- package/src/orchestration/groups/bootstrap.js +3 -0
- package/src/orchestration/groups/index.js +10 -0
- package/src/orchestration/groups/promptProfiles.js +3 -0
- package/src/{group → orchestration/groups}/templates.js +1 -1
- package/src/{group → orchestration/groups}/validateTemplate.js +1 -1
- package/src/orchestration/index.js +7 -0
- package/src/orchestration/solo/index.js +3 -0
- package/src/{daemon → runtime/daemon}/agentProcessManager.js +1 -1
- package/src/{daemon → runtime/daemon}/cronOps.js +3 -2
- package/src/{daemon → runtime/daemon}/groupOrchestrator.js +26 -9
- package/src/{daemon → runtime/daemon}/index.js +273 -79
- package/src/{daemon → runtime/daemon}/ipcServer.js +24 -2
- package/src/{daemon → runtime/daemon}/nicknameScope.js +6 -3
- package/src/{daemon → runtime/daemon}/ops.js +48 -61
- package/src/{daemon → runtime/daemon}/promptLoop.js +1 -1
- package/src/{daemon → runtime/daemon}/promptRequest.js +13 -8
- package/src/runtime/daemon/providerSessions.js +230 -0
- package/src/{daemon → runtime/daemon}/reporting.js +4 -4
- package/src/{daemon → runtime/daemon}/run.js +12 -5
- package/src/{daemon → runtime/daemon}/soloBootstrap.js +7 -7
- package/src/{daemon → runtime/daemon}/status.js +5 -5
- package/src/runtime/index.js +10 -0
- package/src/runtime/process/nodeExecutable.js +26 -0
- package/src/{projects → runtime/projects}/registry.js +1 -1
- package/src/{projects → runtime/projects}/runtimes.js +1 -1
- package/src/{terminal → runtime/terminal}/adapterRouter.js +0 -10
- package/src/{terminal → runtime/terminal}/adapters/internalAdapter.js +0 -4
- package/src/tools/handlers/common.js +1 -1
- package/src/tools/handlers/listAgents.js +1 -1
- package/src/tools/handlers/memory.js +3 -3
- package/src/tools/handlers/readBusSummary.js +1 -1
- package/src/tools/handlers/readOpenDecisions.js +1 -1
- package/src/tools/handlers/readProjectRegistry.js +1 -1
- package/src/tools/handlers/readPromptHistory.js +2 -2
- package/src/tools/schemaFixtures.js +1 -1
- package/src/ui/MIGRATION.md +336 -0
- package/src/ui/format/index.js +974 -0
- package/src/ui/index.js +9 -0
- package/src/ui/ink/ChatApp.js +3674 -0
- package/src/ui/ink/DashboardBar.js +685 -0
- package/src/ui/ink/InkDemo.js +96 -0
- package/src/ui/ink/MultilineInput.js +612 -0
- package/src/ui/ink/UcodeApp.js +822 -0
- package/src/ui/ink/agentMirror.js +730 -0
- package/src/ui/ink/chatReducer.js +359 -0
- package/src/ui/runInk.js +57 -0
- package/src/bus/messageMeta.js +0 -52
- package/src/chat/agentViewController.js +0 -1072
- package/src/chat/chatLogController.js +0 -138
- package/src/chat/completionController.js +0 -533
- package/src/chat/dashboardKeyController.js +0 -573
- package/src/chat/index.js +0 -2214
- package/src/chat/inputHistoryController.js +0 -135
- package/src/chat/inputListenerController.js +0 -470
- package/src/chat/layout.js +0 -186
- package/src/chat/pasteController.js +0 -81
- package/src/chat/statusLineController.js +0 -223
- package/src/chat/streamTracker.js +0 -156
- package/src/code/config +0 -0
- package/src/daemon/providerSessions.js +0 -488
- package/src/terminal/adapters/internalPtyAdapter.js +0 -42
- /package/src/{code/prompts → agents/prompts/native}/actions.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/efficiency.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/environment.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/identity.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/safety.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/sections.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/system.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/tasks.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/bash.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/edit.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/read.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/write.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/ufoo.js +0 -0
- /package/src/{group → agents/prompts}/promptProfiles.js +0 -0
- /package/src/{agent → agents/providers}/claudeEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/claudeOauthTokenReader.js +0 -0
- /package/src/{agent → agents/providers}/claudeSessionFiles.js +0 -0
- /package/src/{agent → agents/providers}/codexEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/credentials/claude.js +0 -0
- /package/src/{agent → agents/providers}/credentials/codex.js +0 -0
- /package/src/{agent → agents/providers}/credentials/index.js +0 -0
- /package/src/{chat → app/chat}/agentBar.js +0 -0
- /package/src/{chat → app/chat}/agentDirectory.js +0 -0
- /package/src/{chat → app/chat}/cronScheduler.js +0 -0
- /package/src/{chat → app/chat}/daemonCoordinator.js +0 -0
- /package/src/{chat → app/chat}/daemonReconnect.js +0 -0
- /package/src/{chat → app/chat}/daemonTransportDefaults.js +0 -0
- /package/src/{chat → app/chat}/inputMath.js +0 -0
- /package/src/{chat → app/chat}/rawKeyMap.js +0 -0
- /package/src/{chat → app/chat}/settingsController.js +0 -0
- /package/src/{chat → app/chat}/text.js +0 -0
- /package/src/{chat → app/chat}/transientAgentState.js +0 -0
- /package/src/{cli → app/cli}/busCoreCommands.js +0 -0
- /package/src/{skills/index.js → app/cli/features/skills.js} +0 -0
- /package/src/{bus → coordination/bus}/nickname.js +0 -0
- /package/src/{bus → coordination/bus}/queue.js +0 -0
- /package/src/{context → coordination/context}/decisions.js +0 -0
- /package/src/{context → coordination/context}/doctor.js +0 -0
- /package/src/{context → coordination/context}/index.js +0 -0
- /package/src/{context → coordination/context}/sync.js +0 -0
- /package/src/{ufoo → coordination/state}/agentsStore.js +0 -0
- /package/src/{ufoo → coordination/state}/paths.js +0 -0
- /package/src/{controller → orchestration/controller}/launchRouting.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFastPath.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFinalize.js +0 -0
- /package/src/{group → orchestration/groups}/diagram.js +0 -0
- /package/src/{group → orchestration/groups}/templateValidation.js +0 -0
- /package/src/{solo → orchestration/solo}/commands.js +0 -0
- /package/src/{shared → runtime/contracts}/eventContract.js +0 -0
- /package/src/{shared → runtime/contracts}/ptySocketContract.js +0 -0
- /package/src/{providerapi → runtime/privacy}/redactor.js +0 -0
- /package/src/{providerapi → runtime/privacy}/shadowDiff.js +0 -0
- /package/src/{projects → runtime/projects}/identity.js +0 -0
- /package/src/{projects → runtime/projects}/index.js +0 -0
- /package/src/{projects → runtime/projects}/projectId.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapterContract.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/externalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/hostAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/internalQueueAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/terminalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/tmuxAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/detect.js +0 -0
- /package/src/{terminal → runtime/terminal}/index.js +0 -0
- /package/src/{terminal → runtime/terminal}/iterm2.js +0 -0
- /package/src/{utils → ui/format}/banner.js +0 -0
- /package/src/{shared → ui/format}/markdownRenderer.js +0 -0
|
@@ -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
|
-
|
|
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
|
|
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,5 +1,5 @@
|
|
|
1
|
-
const { IPC_RESPONSE_TYPES, BUS_STATUS_PHASES } = require("
|
|
2
|
-
const { renderMarkdownLines } = require("
|
|
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 (
|
|
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)
|
|
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
|
|
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
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
const { IPC_REQUEST_TYPES } = require("
|
|
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
|
-
|
|
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("
|
|
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, "")
|