u-foo 2.3.32 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -213
- package/README.zh-CN.md +151 -197
- package/SKILLS/ufoo/SKILL.md +8 -8
- package/bin/uagy.js +69 -0
- package/bin/uclaude.js +2 -2
- package/bin/ucode.js +4 -4
- package/bin/ucodex.js +2 -2
- package/bin/ufoo.js +5 -23
- package/modules/AGENTS.template.md +1 -1
- package/modules/bus/SKILLS/ubus/SKILL.md +35 -10
- package/package.json +5 -5
- package/scripts/chat-app-smoke.js +1 -1
- package/scripts/global-chat-switch-benchmark.js +5 -5
- package/scripts/ink-demo.js +1 -1
- package/scripts/ink-smoke.js +1 -1
- package/scripts/ucode-app-smoke.js +1 -1
- package/src/{agent → agents/activity}/activityDetector.js +39 -2
- package/src/{agent → agents/activity}/activityStatePublisher.js +1 -1
- package/src/{agent → agents/activity}/activityStateWriter.js +2 -2
- package/src/{agent → agents/activity}/activityTracker.js +1 -1
- package/src/agents/activity/index.js +8 -0
- package/src/{agent → agents/controller}/controllerToolExecutor.js +4 -4
- package/src/agents/controller/index.js +8 -0
- package/src/{agent → agents/controller}/loopObservability.js +2 -2
- package/src/{agent → agents/controller}/loopRuntime.js +1 -1
- package/src/{agent → agents/controller}/ufooAgent.js +9 -9
- package/src/agents/index.js +10 -0
- package/src/agents/internal/index.js +3 -0
- package/src/{agent → agents/internal}/internalRunner.js +45 -22
- package/src/agents/launch/agyConversation.js +159 -0
- package/src/agents/launch/index.js +12 -0
- package/src/{agent → agents/launch}/launchEnvironment.js +2 -3
- package/src/{agent → agents/launch}/launcher.js +64 -21
- package/src/{agent → agents/launch}/notifier.js +23 -12
- package/src/{agent → agents/launch}/ptyRunner.js +44 -12
- package/src/{agent → agents/launch}/ptyWrapper.js +2 -2
- package/src/{agent → agents/launch}/publisherRouting.js +1 -1
- package/src/{agent → agents/launch}/readyDetector.js +23 -0
- package/src/{agent → agents/prompts}/defaultBootstrap.js +63 -4
- package/src/{group/bootstrap.js → agents/prompts/groupBootstrap.js} +41 -6
- package/src/agents/prompts/index.js +8 -0
- package/src/{code/prompts → agents/prompts/native}/index.js +1 -1
- package/src/{agent → agents/providers}/claudeThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/codexThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/directAuthStatus.js +184 -1
- package/src/agents/providers/index.js +13 -0
- package/src/{agent → agents/providers}/upstreamTransport.js +2 -2
- package/src/{chat → app/chat}/agentSockets.js +1 -1
- package/src/{chat → app/chat}/commandExecutor.js +50 -26
- package/src/{chat → app/chat}/commands.js +119 -5
- package/src/{chat → app/chat}/daemonConnection.js +1 -1
- package/src/{chat → app/chat}/daemonMessageRouter.js +45 -3
- package/src/{chat → app/chat}/dashboardView.js +2 -1
- package/src/app/chat/index.js +6 -0
- package/src/{chat → app/chat}/inputSubmitHandler.js +4 -13
- package/src/{chat → app/chat}/internalAgentLogHistory.js +1 -1
- package/src/app/chat/multiWindow/index.js +268 -0
- package/src/app/chat/multiWindow/paneLayout.js +84 -0
- package/src/app/chat/multiWindow/paneManager.js +299 -0
- package/src/app/chat/multiWindow/renderer.js +384 -0
- package/src/app/chat/multiWindow/virtualTerminal.js +327 -0
- package/src/{chat → app/chat}/transport.js +1 -1
- package/src/{cli → app/cli}/ctxCoreCommands.js +3 -3
- package/src/{doctor/index.js → app/cli/features/doctor.js} +1 -1
- package/src/{init/index.js → app/cli/features/init.js} +14 -32
- package/src/{cli → app/cli}/groupCoreCommands.js +2 -2
- package/src/app/cli/index.js +9 -0
- package/src/{cli → app/cli}/onlineCoreCommands.js +5 -5
- package/src/{cli.js → app/cli/run.js} +59 -57
- package/src/app/index.js +6 -0
- package/src/code/agent.js +10 -9
- package/src/code/index.js +2 -0
- package/src/code/launcher/index.js +9 -0
- package/src/{agent → code/launcher}/ucode.js +7 -8
- package/src/{agent → code/launcher}/ucodeBootstrap.js +3 -3
- package/src/{agent → code/launcher}/ucodeBuild.js +2 -2
- package/src/{agent → code/launcher}/ucodeDoctor.js +2 -2
- package/src/{agent → code/launcher}/ucodeRuntimeConfig.js +1 -2
- package/src/code/nativeRunner.js +4 -4
- package/src/code/tui.js +3 -1454
- package/src/config.js +15 -2
- package/src/{bus → coordination/bus}/activate.js +2 -2
- package/src/{bus → coordination/bus}/daemon.js +15 -5
- package/src/coordination/bus/envelope.js +173 -0
- package/src/{bus → coordination/bus}/index.js +7 -3
- package/src/{bus → coordination/bus}/inject.js +11 -3
- package/src/{bus → coordination/bus}/message.js +1 -1
- package/src/coordination/bus/messageMeta.js +130 -0
- package/src/coordination/bus/promptEnvelope.js +65 -0
- package/src/{bus → coordination/bus}/shake.js +1 -1
- package/src/{bus → coordination/bus}/store.js +3 -3
- package/src/{bus → coordination/bus}/subscriber.js +2 -2
- package/src/{bus → coordination/bus}/utils.js +2 -2
- package/src/{history → coordination/history}/inputTimeline.js +5 -5
- package/src/coordination/index.js +10 -0
- package/src/{memory → coordination/memory}/historySearch.js +1 -1
- package/src/{memory → coordination/memory}/index.js +3 -3
- package/src/{report → coordination/report}/store.js +2 -2
- package/src/{status → coordination/status}/index.js +3 -3
- package/src/online/bridge.js +2 -2
- package/src/{controller → orchestration/controller}/flags.js +1 -1
- package/src/{controller → orchestration/controller}/gateRouter.js +1 -1
- package/src/orchestration/controller/index.js +10 -0
- package/src/{controller → orchestration/controller}/shadowGuard.js +1 -1
- package/src/orchestration/groups/bootstrap.js +3 -0
- package/src/orchestration/groups/index.js +10 -0
- package/src/orchestration/groups/promptProfiles.js +3 -0
- package/src/{group → orchestration/groups}/templates.js +1 -1
- package/src/{group → orchestration/groups}/validateTemplate.js +1 -1
- package/src/orchestration/index.js +7 -0
- package/src/orchestration/solo/index.js +3 -0
- package/src/{daemon → runtime/daemon}/agentProcessManager.js +1 -1
- package/src/{daemon → runtime/daemon}/cronOps.js +3 -2
- package/src/{daemon → runtime/daemon}/groupOrchestrator.js +26 -9
- package/src/{daemon → runtime/daemon}/index.js +105 -53
- package/src/{daemon → runtime/daemon}/ipcServer.js +1 -1
- package/src/{daemon → runtime/daemon}/nicknameScope.js +6 -3
- package/src/{daemon → runtime/daemon}/ops.js +48 -61
- package/src/{daemon → runtime/daemon}/promptLoop.js +1 -1
- package/src/{daemon → runtime/daemon}/promptRequest.js +7 -7
- package/src/runtime/daemon/providerSessions.js +230 -0
- package/src/{daemon → runtime/daemon}/reporting.js +4 -4
- package/src/{daemon → runtime/daemon}/run.js +4 -4
- package/src/{daemon → runtime/daemon}/soloBootstrap.js +7 -7
- package/src/{daemon → runtime/daemon}/status.js +5 -5
- package/src/runtime/index.js +10 -0
- package/src/{projects → runtime/projects}/registry.js +1 -1
- package/src/{terminal → runtime/terminal}/adapterRouter.js +0 -10
- package/src/{terminal → runtime/terminal}/adapters/internalAdapter.js +0 -4
- package/src/tools/handlers/common.js +1 -1
- package/src/tools/handlers/listAgents.js +1 -1
- package/src/tools/handlers/memory.js +3 -3
- package/src/tools/handlers/readBusSummary.js +1 -1
- package/src/tools/handlers/readOpenDecisions.js +1 -1
- package/src/tools/handlers/readProjectRegistry.js +1 -1
- package/src/tools/handlers/readPromptHistory.js +2 -2
- package/src/tools/schemaFixtures.js +1 -1
- package/src/ui/MIGRATION.md +42 -88
- package/src/ui/format/index.js +5 -28
- package/src/ui/index.js +1 -1
- package/src/ui/{components → ink}/ChatApp.js +812 -88
- package/src/ui/ink/DashboardBar.js +685 -0
- package/src/ui/{components → ink}/MultilineInput.js +230 -5
- package/src/ui/{components → ink}/UcodeApp.js +16 -7
- package/src/ui/{components → ink}/agentMirror.js +24 -19
- package/src/ui/{components → ink}/chatReducer.js +29 -7
- package/src/bus/messageMeta.js +0 -52
- package/src/chat/agentViewController.js +0 -1072
- package/src/chat/chatLogController.js +0 -138
- package/src/chat/completionController.js +0 -533
- package/src/chat/dashboardKeyController.js +0 -533
- package/src/chat/index.js +0 -2222
- package/src/chat/inputHistoryController.js +0 -135
- package/src/chat/inputListenerController.js +0 -470
- package/src/chat/layout.js +0 -186
- package/src/chat/pasteController.js +0 -81
- package/src/chat/statusLineController.js +0 -223
- package/src/chat/streamTracker.js +0 -156
- package/src/code/config +0 -0
- package/src/daemon/providerSessions.js +0 -488
- package/src/terminal/adapters/internalPtyAdapter.js +0 -42
- package/src/ui/components/DashboardBar.js +0 -417
- /package/src/{code/prompts → agents/prompts/native}/actions.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/efficiency.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/environment.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/identity.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/safety.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/sections.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/system.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/tasks.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/bash.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/edit.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/read.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/write.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/ufoo.js +0 -0
- /package/src/{group → agents/prompts}/promptProfiles.js +0 -0
- /package/src/{agent → agents/providers}/claudeEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/claudeOauthTokenReader.js +0 -0
- /package/src/{agent → agents/providers}/claudeSessionFiles.js +0 -0
- /package/src/{agent → agents/providers}/codexEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/credentials/claude.js +0 -0
- /package/src/{agent → agents/providers}/credentials/codex.js +0 -0
- /package/src/{agent → agents/providers}/credentials/index.js +0 -0
- /package/src/{chat → app/chat}/agentBar.js +0 -0
- /package/src/{chat → app/chat}/agentDirectory.js +0 -0
- /package/src/{chat → app/chat}/cronScheduler.js +0 -0
- /package/src/{chat → app/chat}/daemonCoordinator.js +0 -0
- /package/src/{chat → app/chat}/daemonReconnect.js +0 -0
- /package/src/{chat → app/chat}/daemonTransport.js +0 -0
- /package/src/{chat → app/chat}/daemonTransportDefaults.js +0 -0
- /package/src/{chat → app/chat}/inputMath.js +0 -0
- /package/src/{chat → app/chat}/projectCloseController.js +0 -0
- /package/src/{chat → app/chat}/rawKeyMap.js +0 -0
- /package/src/{chat → app/chat}/settingsController.js +0 -0
- /package/src/{chat → app/chat}/shellCommand.js +0 -0
- /package/src/{chat → app/chat}/text.js +0 -0
- /package/src/{chat → app/chat}/transientAgentState.js +0 -0
- /package/src/{cli → app/cli}/busCoreCommands.js +0 -0
- /package/src/{skills/index.js → app/cli/features/skills.js} +0 -0
- /package/src/{bus → coordination/bus}/nickname.js +0 -0
- /package/src/{bus → coordination/bus}/queue.js +0 -0
- /package/src/{context → coordination/context}/decisions.js +0 -0
- /package/src/{context → coordination/context}/doctor.js +0 -0
- /package/src/{context → coordination/context}/index.js +0 -0
- /package/src/{context → coordination/context}/sync.js +0 -0
- /package/src/{ufoo → coordination/state}/agentRegistryDiagnostics.js +0 -0
- /package/src/{ufoo → coordination/state}/agentsStore.js +0 -0
- /package/src/{ufoo → coordination/state}/paths.js +0 -0
- /package/src/{controller → orchestration/controller}/launchRouting.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFastPath.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFinalize.js +0 -0
- /package/src/{group → orchestration/groups}/diagram.js +0 -0
- /package/src/{group → orchestration/groups}/templateValidation.js +0 -0
- /package/src/{solo → orchestration/solo}/commands.js +0 -0
- /package/src/{shared → runtime/contracts}/eventContract.js +0 -0
- /package/src/{shared → runtime/contracts}/ptySocketContract.js +0 -0
- /package/src/{providerapi → runtime/privacy}/redactor.js +0 -0
- /package/src/{providerapi → runtime/privacy}/shadowDiff.js +0 -0
- /package/src/{utils → runtime/process}/nodeExecutable.js +0 -0
- /package/src/{projects → runtime/projects}/identity.js +0 -0
- /package/src/{projects → runtime/projects}/index.js +0 -0
- /package/src/{projects → runtime/projects}/projectId.js +0 -0
- /package/src/{projects → runtime/projects}/runtimes.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapterContract.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/externalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/hostAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/internalQueueAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/terminalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/tmuxAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/detect.js +0 -0
- /package/src/{terminal → runtime/terminal}/index.js +0 -0
- /package/src/{terminal → runtime/terminal}/iterm2.js +0 -0
- /package/src/{utils → ui/format}/banner.js +0 -0
- /package/src/{shared → ui/format}/markdownRenderer.js +0 -0
- /package/src/ui/{components → ink}/InkDemo.js +0 -0
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
|
-
const { SHARED_UFOO_PROTOCOL } = require("
|
|
6
|
-
const { getUfooPaths } = require("
|
|
5
|
+
const { SHARED_UFOO_PROTOCOL } = require("./groupBootstrap");
|
|
6
|
+
const { getUfooPaths } = require("../../coordination/state/paths");
|
|
7
7
|
|
|
8
8
|
function asTrimmedString(value) {
|
|
9
9
|
return typeof value === "string" ? value.trim() : "";
|
|
@@ -43,7 +43,7 @@ function readOptionalFile(filePath) {
|
|
|
43
43
|
*/
|
|
44
44
|
function loadTeamActivityContext(projectRoot) {
|
|
45
45
|
try {
|
|
46
|
-
const { renderTimelineForPrompt } = require("
|
|
46
|
+
const { renderTimelineForPrompt } = require("../../coordination/history/inputTimeline");
|
|
47
47
|
return renderTimelineForPrompt(projectRoot, 20) || "";
|
|
48
48
|
} catch {
|
|
49
49
|
return "";
|
|
@@ -54,7 +54,11 @@ function buildDefaultStartupBootstrapPrompt({ agentType = "", projectRoot = "" }
|
|
|
54
54
|
const normalizedAgent = asTrimmedString(agentType).toLowerCase();
|
|
55
55
|
const displayAgent = normalizedAgent === "claude-code"
|
|
56
56
|
? "Claude"
|
|
57
|
-
: (normalizedAgent === "codex"
|
|
57
|
+
: (normalizedAgent === "codex"
|
|
58
|
+
? "Codex"
|
|
59
|
+
: (normalizedAgent === "ufoo-code"
|
|
60
|
+
? "ucode"
|
|
61
|
+
: (normalizedAgent === "agy" ? "Agy" : "agent")));
|
|
58
62
|
|
|
59
63
|
const segments = [
|
|
60
64
|
`Session bootstrap for ${displayAgent}.`,
|
|
@@ -196,6 +200,35 @@ function mergeCodexPromptArgs({ args = [], bootstrapText = "" } = {}) {
|
|
|
196
200
|
};
|
|
197
201
|
}
|
|
198
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Merge bootstrap text into an existing `-i <text>` / `--prompt-interactive
|
|
205
|
+
* <text>` / `--prompt-interactive=<text>` argument. Returns null if no such
|
|
206
|
+
* argument exists (caller should then prepend a fresh `-i <bootstrap>`).
|
|
207
|
+
*
|
|
208
|
+
* Agy treats `-i` as a single initial prompt that drops the user into an
|
|
209
|
+
* interactive session — same intent as codex's positional prompt.
|
|
210
|
+
*/
|
|
211
|
+
function mergeAgyPromptArgs({ args = [], bootstrapText = "" } = {}) {
|
|
212
|
+
const currentArgs = Array.isArray(args) ? args.slice() : [];
|
|
213
|
+
for (let index = 0; index < currentArgs.length; index += 1) {
|
|
214
|
+
const item = asTrimmedString(currentArgs[index]);
|
|
215
|
+
if (!item) continue;
|
|
216
|
+
if (item === "-i" || item === "--prompt-interactive") {
|
|
217
|
+
const existing = String(currentArgs[index + 1] || "");
|
|
218
|
+
const merged = mergePromptSegments(bootstrapText, existing);
|
|
219
|
+
currentArgs[index + 1] = merged;
|
|
220
|
+
return { args: currentArgs, promptText: merged };
|
|
221
|
+
}
|
|
222
|
+
if (item.startsWith("--prompt-interactive=")) {
|
|
223
|
+
const existing = item.slice("--prompt-interactive=".length);
|
|
224
|
+
const merged = mergePromptSegments(bootstrapText, existing);
|
|
225
|
+
currentArgs[index] = `--prompt-interactive=${merged}`;
|
|
226
|
+
return { args: currentArgs, promptText: merged };
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
|
|
199
232
|
function resolveDefaultManualBootstrap({
|
|
200
233
|
projectRoot,
|
|
201
234
|
agentType = "",
|
|
@@ -280,6 +313,31 @@ function resolveDefaultManualBootstrap({
|
|
|
280
313
|
};
|
|
281
314
|
}
|
|
282
315
|
|
|
316
|
+
if (normalizedAgent === "agy") {
|
|
317
|
+
const promptText = buildDefaultStartupBootstrapPrompt({ agentType: normalizedAgent, projectRoot });
|
|
318
|
+
// If the user passed -i / --prompt-interactive, fold the bootstrap into
|
|
319
|
+
// their text. Otherwise prepend a fresh `-i <bootstrap>` pair so the
|
|
320
|
+
// session starts with our protocol message already delivered.
|
|
321
|
+
const merged = mergeAgyPromptArgs({
|
|
322
|
+
args: currentArgs,
|
|
323
|
+
bootstrapText: promptText,
|
|
324
|
+
});
|
|
325
|
+
if (merged) {
|
|
326
|
+
return {
|
|
327
|
+
args: merged.args,
|
|
328
|
+
env: {},
|
|
329
|
+
mode: "initial-prompt-arg",
|
|
330
|
+
promptText: merged.promptText,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
args: ["-i", promptText, ...currentArgs],
|
|
335
|
+
env: {},
|
|
336
|
+
mode: "initial-prompt-arg",
|
|
337
|
+
promptText,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
283
341
|
return { args: currentArgs, env: {}, mode: "skip" };
|
|
284
342
|
}
|
|
285
343
|
|
|
@@ -291,4 +349,5 @@ module.exports = {
|
|
|
291
349
|
defaultBootstrapFile,
|
|
292
350
|
prepareDefaultBootstrapFile,
|
|
293
351
|
resolveDefaultManualBootstrap,
|
|
352
|
+
mergeAgyPromptArgs,
|
|
294
353
|
};
|
|
@@ -3,12 +3,47 @@
|
|
|
3
3
|
const crypto = require("crypto");
|
|
4
4
|
|
|
5
5
|
const SHARED_UFOO_PROTOCOL = [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
6
|
+
"Session harness: ufoo",
|
|
7
|
+
"",
|
|
8
|
+
"Use ufoo as an internal coordination layer. Do not mention it unless asked.",
|
|
9
|
+
"",
|
|
10
|
+
"START",
|
|
11
|
+
"If shell and ufoo are available, sync decisions:",
|
|
12
|
+
"- `ufoo ctx decisions -l`",
|
|
13
|
+
"- `ufoo ctx decisions -n 1`",
|
|
14
|
+
"",
|
|
15
|
+
"If sync fails, continue normally.",
|
|
16
|
+
"",
|
|
17
|
+
"DECISIONS",
|
|
18
|
+
"Default: write nothing.",
|
|
19
|
+
"",
|
|
20
|
+
"Create a decision only when it is stable and affects future agents:",
|
|
21
|
+
"architecture, major trade-off, cross-agent contract, or future-impacting plan.",
|
|
22
|
+
"",
|
|
23
|
+
"Do not record routine fixes, local findings, facts, or temporary details.",
|
|
24
|
+
"Facts belong in shared context, not decisions.",
|
|
25
|
+
"",
|
|
26
|
+
"Use: `ufoo ctx decisions new \"<short title>\"`",
|
|
27
|
+
"",
|
|
28
|
+
"BUS (peer ↔ peer)",
|
|
29
|
+
"Send bus messages only for handoff, blocker, dependency, or explicit",
|
|
30
|
+
"coordination — never for greetings, acknowledgments, or emoji alone.",
|
|
31
|
+
"Those create reply loops between agents.",
|
|
32
|
+
"",
|
|
33
|
+
"`ufoo bus send <target> \"<message>\"`",
|
|
34
|
+
"",
|
|
35
|
+
"On received bus work: execute it, then `ufoo bus ack \"$UFOO_SUBSCRIBER_ID\"`.",
|
|
36
|
+
"Reply only if you have a concrete result, answer, or follow-up the sender",
|
|
37
|
+
"needs. Default is ack-only; silence is a valid response.",
|
|
38
|
+
"",
|
|
39
|
+
"REPORT",
|
|
40
|
+
"You MUST report after handling work that arrived from chat",
|
|
41
|
+
"(`[manual]<to:...>`) or bus (`[ufoo]<from:...>`). The controller handles",
|
|
42
|
+
"dedup, so don't worry about report loops.",
|
|
43
|
+
"",
|
|
44
|
+
"`ufoo report start|progress|done|error \"<short summary>\"`",
|
|
45
|
+
"",
|
|
46
|
+
"Then continue the active task.",
|
|
12
47
|
].join("\n");
|
|
13
48
|
|
|
14
49
|
const SHARED_GROUP_PREFIX = [
|
|
@@ -6,7 +6,7 @@ const {
|
|
|
6
6
|
normalizeClaudeMessage,
|
|
7
7
|
normalizeClaudeUsage,
|
|
8
8
|
} = require("./claudeEventTranslator");
|
|
9
|
-
const { redactUfooEvent } = require("
|
|
9
|
+
const { redactUfooEvent } = require("../../runtime/privacy/redactor");
|
|
10
10
|
|
|
11
11
|
const CACHE_CONTROL = Object.freeze({ type: "ephemeral" });
|
|
12
12
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const os = require("os");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const { loadConfig } = require("../../config");
|
|
4
7
|
const {
|
|
5
8
|
resolveCodexAuthPaths,
|
|
6
9
|
resolveCodexUpstreamCredentials,
|
|
@@ -23,6 +26,7 @@ function normalizeErrorCode(err, fallback = "DIRECT_AUTH_STATUS_FAILED") {
|
|
|
23
26
|
function normalizeDirectAuthProvider(value = "") {
|
|
24
27
|
const text = String(value || "").trim().toLowerCase();
|
|
25
28
|
if (text === "claude" || text === "claude-cli" || text === "claude-code" || text === "anthropic") return "claude";
|
|
29
|
+
if (text === "agy" || text === "agy-cli" || text === "antigravity") return "agy";
|
|
26
30
|
return "codex";
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -136,6 +140,138 @@ async function inspectClaudeDirectAuth({
|
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Default agy log directory: ~/.gemini/antigravity-cli/log
|
|
145
|
+
* Agy doesn't expose an API for auth status, so we tail its own structured
|
|
146
|
+
* server-side log and grep for the markers it prints during the OAuth
|
|
147
|
+
* handshake. This is best-effort observability, not a real credential
|
|
148
|
+
* check — agy owns the keyring, not us.
|
|
149
|
+
*/
|
|
150
|
+
function resolveAgyLogDir(env = process.env) {
|
|
151
|
+
const home = String(env.HOME || os.homedir() || "").trim();
|
|
152
|
+
if (!home) return "";
|
|
153
|
+
return path.join(home, ".gemini", "antigravity-cli", "log");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function findMostRecentAgyLog(logDir = "") {
|
|
157
|
+
try {
|
|
158
|
+
if (!logDir || !fs.existsSync(logDir)) return "";
|
|
159
|
+
const entries = fs.readdirSync(logDir)
|
|
160
|
+
.filter((name) => name.startsWith("cli-") && name.endsWith(".log"));
|
|
161
|
+
if (entries.length === 0) return "";
|
|
162
|
+
// Filenames are cli-YYYYMMDD_HHMMSS.log — lexicographic sort matches mtime.
|
|
163
|
+
entries.sort();
|
|
164
|
+
return path.join(logDir, entries[entries.length - 1]);
|
|
165
|
+
} catch {
|
|
166
|
+
return "";
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function readAgyLogTail(file = "", maxBytes = 32 * 1024) {
|
|
171
|
+
try {
|
|
172
|
+
if (!file || !fs.existsSync(file)) return "";
|
|
173
|
+
const stat = fs.statSync(file);
|
|
174
|
+
const offset = Math.max(0, stat.size - maxBytes);
|
|
175
|
+
const fd = fs.openSync(file, "r");
|
|
176
|
+
try {
|
|
177
|
+
const length = stat.size - offset;
|
|
178
|
+
const buffer = Buffer.alloc(length);
|
|
179
|
+
fs.readSync(fd, buffer, 0, length, offset);
|
|
180
|
+
return buffer.toString("utf8");
|
|
181
|
+
} finally {
|
|
182
|
+
fs.closeSync(fd);
|
|
183
|
+
}
|
|
184
|
+
} catch {
|
|
185
|
+
return "";
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function classifyAgyLogTail(text = "") {
|
|
190
|
+
const str = String(text || "");
|
|
191
|
+
if (!str) {
|
|
192
|
+
return {
|
|
193
|
+
ok: false,
|
|
194
|
+
state: "unknown",
|
|
195
|
+
errorCode: "AGY_AUTH_NO_LOG",
|
|
196
|
+
message: "no agy log file found yet — launch agy at least once to produce one",
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (/Eligibility check failed/i.test(str) || /Account ineligible/i.test(str)) {
|
|
200
|
+
const emailMatch = str.match(/authenticated successfully as ([^\s]+)/);
|
|
201
|
+
return {
|
|
202
|
+
ok: false,
|
|
203
|
+
state: "ineligible",
|
|
204
|
+
errorCode: "AGY_ACCOUNT_INELIGIBLE",
|
|
205
|
+
message: "agy account is signed in but not eligible (18+ / supported region required)",
|
|
206
|
+
accountEmail: emailMatch ? emailMatch[1] : "",
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
if (/User location is not supported/i.test(str)) {
|
|
210
|
+
const emailMatch = str.match(/authenticated successfully as ([^\s]+)/);
|
|
211
|
+
return {
|
|
212
|
+
ok: false,
|
|
213
|
+
state: "region_blocked",
|
|
214
|
+
errorCode: "AGY_REGION_BLOCKED",
|
|
215
|
+
message: "agy backend rejected this region (FAILED_PRECONDITION)",
|
|
216
|
+
accountEmail: emailMatch ? emailMatch[1] : "",
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const authMatch = str.match(/OAuth: authenticated successfully as ([^\s]+)/);
|
|
220
|
+
if (authMatch) {
|
|
221
|
+
return {
|
|
222
|
+
ok: true,
|
|
223
|
+
state: "fresh",
|
|
224
|
+
accountEmail: authMatch[1],
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
ok: false,
|
|
229
|
+
state: "unknown",
|
|
230
|
+
errorCode: "AGY_AUTH_UNVERIFIED",
|
|
231
|
+
message: "no successful OAuth handshake found in recent agy log",
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function inspectAgyDirectAuth({
|
|
236
|
+
env = process.env,
|
|
237
|
+
readLogTailImpl = readAgyLogTail,
|
|
238
|
+
findLogImpl = findMostRecentAgyLog,
|
|
239
|
+
resolveLogDirImpl = resolveAgyLogDir,
|
|
240
|
+
} = {}) {
|
|
241
|
+
const logDir = resolveLogDirImpl(env);
|
|
242
|
+
const file = findLogImpl(logDir);
|
|
243
|
+
const tail = file ? readLogTailImpl(file) : "";
|
|
244
|
+
const classification = classifyAgyLogTail(tail);
|
|
245
|
+
const base = {
|
|
246
|
+
provider: "agy",
|
|
247
|
+
transport: "antigravity-tui", // No API mode — TUI is the only path.
|
|
248
|
+
credentialKind: "oauth",
|
|
249
|
+
source: "google-keyring",
|
|
250
|
+
credentialPath: file || logDir || "",
|
|
251
|
+
};
|
|
252
|
+
if (classification.ok) {
|
|
253
|
+
return {
|
|
254
|
+
...base,
|
|
255
|
+
ok: true,
|
|
256
|
+
state: classification.state,
|
|
257
|
+
accountEmail: classification.accountEmail || "",
|
|
258
|
+
account: classification.accountEmail || "",
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
...base,
|
|
263
|
+
ok: false,
|
|
264
|
+
state: classification.state,
|
|
265
|
+
errorCode: classification.errorCode,
|
|
266
|
+
error: classification.message,
|
|
267
|
+
accountEmail: classification.accountEmail || "",
|
|
268
|
+
hint: classification.errorCode === "AGY_ACCOUNT_INELIGIBLE"
|
|
269
|
+
|| classification.errorCode === "AGY_REGION_BLOCKED"
|
|
270
|
+
? "Antigravity requires an 18+ Google account in a supported region. Try a different account or wait for broader rollout."
|
|
271
|
+
: "Run `agy` once to produce an authentication handshake log.",
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
139
275
|
async function inspectDirectAuthStatus(options = {}) {
|
|
140
276
|
const { projectRoot, loadConfigImpl = loadConfig, provider = "" } = options;
|
|
141
277
|
const config = loadConfigImpl(projectRoot) || {};
|
|
@@ -147,6 +283,9 @@ async function inspectDirectAuthStatus(options = {}) {
|
|
|
147
283
|
if (selected === "claude") {
|
|
148
284
|
return inspectClaudeDirectAuth(nextOptions);
|
|
149
285
|
}
|
|
286
|
+
if (selected === "agy") {
|
|
287
|
+
return inspectAgyDirectAuth(nextOptions);
|
|
288
|
+
}
|
|
150
289
|
return inspectCodexDirectAuth(nextOptions);
|
|
151
290
|
}
|
|
152
291
|
|
|
@@ -246,10 +385,51 @@ function formatClaudeDirectAuthStatus(status = {}, options = {}) {
|
|
|
246
385
|
return lines;
|
|
247
386
|
}
|
|
248
387
|
|
|
388
|
+
function formatAgyDirectAuthStatus(status = {}, options = {}) {
|
|
389
|
+
if (options.compact === true) {
|
|
390
|
+
if (status.ok) {
|
|
391
|
+
const details = [
|
|
392
|
+
status.accountEmail ? status.accountEmail : "",
|
|
393
|
+
status.source || "google-keyring",
|
|
394
|
+
].filter(Boolean);
|
|
395
|
+
const lines = [`Agy: OK · keyring · ${status.state || "fresh"}`];
|
|
396
|
+
if (details.length > 0) lines.push(` ${details.join(" · ")}`);
|
|
397
|
+
return lines;
|
|
398
|
+
}
|
|
399
|
+
const hint = String(status.hint || "Run `agy` once to verify the OAuth handshake.").replace(/;.*$/, ".");
|
|
400
|
+
return [
|
|
401
|
+
`Agy: FAIL · ${status.errorCode || "AGY_AUTH_STATUS_FAILED"}`,
|
|
402
|
+
` ${status.error || "agy authentication state unknown"} · ${hint}`,
|
|
403
|
+
];
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (status.ok) {
|
|
407
|
+
const lines = [
|
|
408
|
+
`Agy CLI: OK (keyring, ${status.state || "fresh"})`,
|
|
409
|
+
` - source: ${status.source || "google-keyring"}`,
|
|
410
|
+
];
|
|
411
|
+
if (status.accountEmail) lines.push(` - account: ${status.accountEmail}`);
|
|
412
|
+
if (status.credentialPath) lines.push(` - log: ${status.credentialPath}`);
|
|
413
|
+
return lines;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const lines = [
|
|
417
|
+
`Agy CLI: FAIL (${status.errorCode || "AGY_AUTH_STATUS_FAILED"})`,
|
|
418
|
+
` - ${status.error || "agy authentication state unknown"}`,
|
|
419
|
+
];
|
|
420
|
+
if (status.accountEmail) lines.push(` - account: ${status.accountEmail}`);
|
|
421
|
+
if (status.credentialPath) lines.push(` - log: ${status.credentialPath}`);
|
|
422
|
+
if (status.hint) lines.push(` - ${status.hint}`);
|
|
423
|
+
return lines;
|
|
424
|
+
}
|
|
425
|
+
|
|
249
426
|
function formatDirectAuthStatus(status = {}, options = {}) {
|
|
250
427
|
if (status.provider === "claude") {
|
|
251
428
|
return formatClaudeDirectAuthStatus(status, options);
|
|
252
429
|
}
|
|
430
|
+
if (status.provider === "agy") {
|
|
431
|
+
return formatAgyDirectAuthStatus(status, options);
|
|
432
|
+
}
|
|
253
433
|
return formatCodexDirectAuthStatus(status, options);
|
|
254
434
|
}
|
|
255
435
|
|
|
@@ -257,8 +437,11 @@ module.exports = {
|
|
|
257
437
|
inspectDirectAuthStatus,
|
|
258
438
|
inspectCodexDirectAuth,
|
|
259
439
|
inspectClaudeDirectAuth,
|
|
440
|
+
inspectAgyDirectAuth,
|
|
260
441
|
formatDirectAuthStatus,
|
|
261
442
|
formatCodexDirectAuthStatus,
|
|
262
443
|
formatClaudeDirectAuthStatus,
|
|
444
|
+
formatAgyDirectAuthStatus,
|
|
263
445
|
normalizeDirectAuthProvider,
|
|
446
|
+
classifyAgyLogTail,
|
|
264
447
|
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...require("./claudeEventTranslator"),
|
|
5
|
+
...require("./claudeOauthTokenReader"),
|
|
6
|
+
...require("./claudeSessionFiles"),
|
|
7
|
+
...require("./claudeThreadProvider"),
|
|
8
|
+
...require("./codexEventTranslator"),
|
|
9
|
+
...require("./codexThreadProvider"),
|
|
10
|
+
...require("./directAuthStatus"),
|
|
11
|
+
...require("./upstreamTransport"),
|
|
12
|
+
credentials: require("./credentials"),
|
|
13
|
+
};
|
|
@@ -6,12 +6,12 @@ const {
|
|
|
6
6
|
defaultAgentModelForProvider,
|
|
7
7
|
defaultRouterModelForProvider,
|
|
8
8
|
sameModelProvider,
|
|
9
|
-
} = require("
|
|
9
|
+
} = require("../../config");
|
|
10
10
|
const {
|
|
11
11
|
resolveRuntimeConfig,
|
|
12
12
|
resolveCompletionUrl,
|
|
13
13
|
resolveAnthropicMessagesUrl,
|
|
14
|
-
} = require("
|
|
14
|
+
} = require("../../code/nativeRunner");
|
|
15
15
|
const { resolveClaudeUpstreamCredentials } = require("./credentials/claude");
|
|
16
16
|
const { resolveCodexUpstreamCredentials } = require("./credentials/codex");
|
|
17
17
|
const { buildUpstreamAuthFromCredential } = require("./credentials");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const net = require("net");
|
|
3
|
-
const { PTY_SOCKET_MESSAGE_TYPES, PTY_SOCKET_SUBSCRIBE_MODES } = require("
|
|
3
|
+
const { PTY_SOCKET_MESSAGE_TYPES, PTY_SOCKET_SUBSCRIBE_MODES } = require("../../runtime/contracts/ptySocketContract");
|
|
4
4
|
|
|
5
5
|
function createAgentSockets(options = {}) {
|
|
6
6
|
const {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const EventBus = require("
|
|
3
|
-
const { IPC_REQUEST_TYPES } = require("
|
|
4
|
-
const UfooInit = require("../init");
|
|
2
|
+
const EventBus = require("../../coordination/bus");
|
|
3
|
+
const { IPC_REQUEST_TYPES } = require("../../runtime/contracts/eventContract");
|
|
4
|
+
const UfooInit = require("../cli/features/init");
|
|
5
5
|
const { runGroupCoreCommand } = require("../cli/groupCoreCommands");
|
|
6
6
|
const {
|
|
7
7
|
loadConfig: loadProjectConfig,
|
|
@@ -12,30 +12,30 @@ const {
|
|
|
12
12
|
SETTINGS_MODEL_DEFAULTS,
|
|
13
13
|
defaultAgentModelForProvider,
|
|
14
14
|
defaultRouterModelForProvider,
|
|
15
|
-
} = require("
|
|
16
|
-
const { resolveTransport } = require("
|
|
17
|
-
const { resolveDisplayNickname } = require("
|
|
15
|
+
} = require("../../config");
|
|
16
|
+
const { resolveTransport } = require("../../code/nativeRunner");
|
|
17
|
+
const { resolveDisplayNickname } = require("../../runtime/daemon/nicknameScope");
|
|
18
18
|
const { parseIntervalMs, formatIntervalMs } = require("./cronScheduler");
|
|
19
|
-
const { isGlobalControllerProjectRoot, resolveGlobalControllerUfooDir } = require("
|
|
20
|
-
const { loadPromptProfileRegistry } = require("
|
|
21
|
-
const { resolveSoloAgentType } = require("
|
|
19
|
+
const { isGlobalControllerProjectRoot, resolveGlobalControllerUfooDir } = require("../../runtime/projects");
|
|
20
|
+
const { loadPromptProfileRegistry } = require("../../orchestration/groups/promptProfiles");
|
|
21
|
+
const { resolveSoloAgentType } = require("../../orchestration/solo/commands");
|
|
22
22
|
const {
|
|
23
23
|
inspectDirectAuthStatus,
|
|
24
24
|
formatDirectAuthStatus,
|
|
25
|
-
} = require("
|
|
25
|
+
} = require("../../agents/providers/directAuthStatus");
|
|
26
26
|
|
|
27
27
|
function defaultCreateDoctor(projectRoot) {
|
|
28
|
-
const UfooDoctor = require("../doctor");
|
|
28
|
+
const UfooDoctor = require("../cli/features/doctor");
|
|
29
29
|
return new UfooDoctor(projectRoot);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function defaultCreateContext(projectRoot) {
|
|
33
|
-
const UfooContext = require("
|
|
33
|
+
const UfooContext = require("../../coordination/context");
|
|
34
34
|
return new UfooContext(projectRoot);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function defaultCreateSkills(projectRoot) {
|
|
38
|
-
const UfooSkills = require("../skills");
|
|
38
|
+
const UfooSkills = require("../cli/features/skills");
|
|
39
39
|
return new UfooSkills(projectRoot);
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -51,6 +51,9 @@ function normalizeSettingsProvider(value = "", fallback = "codex-cli") {
|
|
|
51
51
|
if (text === "claude" || text === "claude-cli" || text === "claude-code" || text === "anthropic") {
|
|
52
52
|
return "claude-cli";
|
|
53
53
|
}
|
|
54
|
+
if (text === "agy" || text === "agy-cli" || text === "antigravity") {
|
|
55
|
+
return "agy-cli";
|
|
56
|
+
}
|
|
54
57
|
if (text === "codex" || text === "codex-cli" || text === "codex-code" || text === "openai") {
|
|
55
58
|
return "codex-cli";
|
|
56
59
|
}
|
|
@@ -58,7 +61,10 @@ function normalizeSettingsProvider(value = "", fallback = "codex-cli") {
|
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
function agentProviderKey(value = "") {
|
|
61
|
-
|
|
64
|
+
const provider = normalizeSettingsProvider(value);
|
|
65
|
+
if (provider === "claude-cli") return "claude";
|
|
66
|
+
if (provider === "agy-cli") return "agy";
|
|
67
|
+
return "codex";
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
function defaultGateModelForProvider(value = "") {
|
|
@@ -147,6 +153,7 @@ function createCommandExecutor(options = {}) {
|
|
|
147
153
|
resolveTerminalApp = defaultResolveTerminalApp,
|
|
148
154
|
sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
149
155
|
schedule = (fn, ms) => setTimeout(fn, ms),
|
|
156
|
+
clearLog = null,
|
|
150
157
|
} = options;
|
|
151
158
|
|
|
152
159
|
if (!projectRoot) {
|
|
@@ -479,14 +486,17 @@ function createCommandExecutor(options = {}) {
|
|
|
479
486
|
if (args.length === 0) {
|
|
480
487
|
logMessage(
|
|
481
488
|
"error",
|
|
482
|
-
"{white-fg}✗{/white-fg} Usage: /launch <claude|codex|ucode> [nickname=<name>] [profile=<id>] [count=<n>] [scope=inplace|window]"
|
|
489
|
+
"{white-fg}✗{/white-fg} Usage: /launch <claude|codex|agy|ucode> [nickname=<name>] [profile=<id>] [count=<n>] [scope=inplace|window]"
|
|
483
490
|
);
|
|
484
491
|
return;
|
|
485
492
|
}
|
|
486
493
|
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
|
|
494
|
+
const agentTypeInput = String(args[0] || "").trim().toLowerCase();
|
|
495
|
+
// Accept friendly aliases the same way `ufoo launch` does in cli.js.
|
|
496
|
+
let agentType = agentTypeInput;
|
|
497
|
+
if (agentTypeInput === "antigravity" || agentTypeInput === "uagy") agentType = "agy";
|
|
498
|
+
if (agentType !== "claude" && agentType !== "codex" && agentType !== "agy" && agentType !== "ucode") {
|
|
499
|
+
logMessage("error", "{white-fg}✗{/white-fg} Unknown agent type. Use: claude, codex, agy, or ucode");
|
|
490
500
|
return;
|
|
491
501
|
}
|
|
492
502
|
const normalizedAgent = agentType === "ucode" ? "ufoo" : agentType;
|
|
@@ -661,7 +671,7 @@ function createCommandExecutor(options = {}) {
|
|
|
661
671
|
|
|
662
672
|
const profile = String(args[1] || "").trim();
|
|
663
673
|
if (!profile) {
|
|
664
|
-
logMessage("error", "{white-fg}✗{/white-fg} Usage: /solo run <prompt-profile> [agent=codex|claude|ucode] [nickname=<name>] [scope=inplace|window]");
|
|
674
|
+
logMessage("error", "{white-fg}✗{/white-fg} Usage: /solo run <prompt-profile> [agent=codex|claude|agy|ucode] [nickname=<name>] [scope=inplace|window]");
|
|
665
675
|
return;
|
|
666
676
|
}
|
|
667
677
|
|
|
@@ -1255,13 +1265,15 @@ function createCommandExecutor(options = {}) {
|
|
|
1255
1265
|
logMessage("system", ` • provider: ${key}`);
|
|
1256
1266
|
logMessage("system", ` • model: ${model || `(unset, recommended ${defaultAgentModelForProvider(provider)})`}`);
|
|
1257
1267
|
logMessage("system", ` • defaults: codex=${SETTINGS_MODEL_DEFAULTS.agent.codex}, claude=${SETTINGS_MODEL_DEFAULTS.agent.claude}`);
|
|
1258
|
-
logMessage("system", " • use: /settings agent set provider=<codex|claude> model=<id>");
|
|
1268
|
+
logMessage("system", " • use: /settings agent set provider=<codex|claude|agy> model=<id>");
|
|
1259
1269
|
return;
|
|
1260
1270
|
}
|
|
1261
1271
|
|
|
1262
|
-
if (action === "codex" || action === "claude") {
|
|
1272
|
+
if (action === "codex" || action === "claude" || action === "agy") {
|
|
1263
1273
|
const kv = parseKeyValueArgs(args.slice(1));
|
|
1264
|
-
const provider = action === "claude"
|
|
1274
|
+
const provider = action === "claude"
|
|
1275
|
+
? "claude-cli"
|
|
1276
|
+
: (action === "agy" ? "agy-cli" : "codex-cli");
|
|
1265
1277
|
const model = String(kv.model || defaultAgentModelForProvider(provider)).trim();
|
|
1266
1278
|
saveConfig(projectRoot, {
|
|
1267
1279
|
agentProvider: provider,
|
|
@@ -1447,10 +1459,8 @@ function createCommandExecutor(options = {}) {
|
|
|
1447
1459
|
}
|
|
1448
1460
|
|
|
1449
1461
|
async function handleUfooCommand(args = []) {
|
|
1450
|
-
//
|
|
1451
|
-
// When daemon sends /ufoo <marker>, we should just check for pending messages
|
|
1462
|
+
// Legacy /ufoo <single-token> compatibility: check pending messages silently.
|
|
1452
1463
|
if (args.length > 0) {
|
|
1453
|
-
// This is a probe marker, check for pending messages
|
|
1454
1464
|
const subscriberId = process.env.UFOO_SUBSCRIBER_ID;
|
|
1455
1465
|
if (subscriberId) {
|
|
1456
1466
|
try {
|
|
@@ -1464,7 +1474,7 @@ function createCommandExecutor(options = {}) {
|
|
|
1464
1474
|
// Ignore errors when checking messages
|
|
1465
1475
|
}
|
|
1466
1476
|
}
|
|
1467
|
-
//
|
|
1477
|
+
// Do not log anything else for legacy single-token input.
|
|
1468
1478
|
return;
|
|
1469
1479
|
}
|
|
1470
1480
|
|
|
@@ -1566,6 +1576,20 @@ function createCommandExecutor(options = {}) {
|
|
|
1566
1576
|
const { command, args } = parsed;
|
|
1567
1577
|
|
|
1568
1578
|
switch (command) {
|
|
1579
|
+
case "clear":
|
|
1580
|
+
if (typeof clearLog === "function") {
|
|
1581
|
+
clearLog();
|
|
1582
|
+
} else {
|
|
1583
|
+
logMessage("error", "{white-fg}✗{/white-fg} /clear is not available in this view");
|
|
1584
|
+
}
|
|
1585
|
+
return true;
|
|
1586
|
+
case "multi":
|
|
1587
|
+
if (typeof options.toggleMultiWindow === "function") {
|
|
1588
|
+
options.toggleMultiWindow();
|
|
1589
|
+
} else {
|
|
1590
|
+
logMessage("error", "{white-fg}✗{/white-fg} Multi-window mode is not available");
|
|
1591
|
+
}
|
|
1592
|
+
return true;
|
|
1569
1593
|
case "doctor":
|
|
1570
1594
|
await handleDoctorCommand();
|
|
1571
1595
|
return true;
|