u-foo 2.3.20 → 2.3.22
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/package.json +1 -1
- package/src/agent/upstreamTransport.js +27 -4
- package/src/chat/agentViewController.js +4 -3
- package/src/chat/commandExecutor.js +4 -17
- package/src/chat/commands.js +1 -1
- package/src/chat/daemonMessageRouter.js +12 -13
- package/src/chat/index.js +2 -1
- package/src/code/agent.js +6 -4
- package/src/code/nativeRunner.js +6 -4
- package/src/code/tui.js +3 -3
- package/src/config.js +66 -2
- package/src/controller/gateRouter.js +18 -9
- package/src/daemon/index.js +0 -17
- package/src/daemon/run.js +6 -3
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const { randomUUID } = require("crypto");
|
|
4
|
-
const {
|
|
4
|
+
const {
|
|
5
|
+
loadConfig,
|
|
6
|
+
defaultAgentModelForProvider,
|
|
7
|
+
defaultRouterModelForProvider,
|
|
8
|
+
sameModelProvider,
|
|
9
|
+
} = require("../config");
|
|
5
10
|
const {
|
|
6
11
|
resolveRuntimeConfig,
|
|
7
12
|
resolveCompletionUrl,
|
|
@@ -30,6 +35,16 @@ const CODEX_DEFAULT_BASE_URL = "https://chatgpt.com/backend-api/codex";
|
|
|
30
35
|
const CODEX_DEFAULT_USER_AGENT = "codex-tui/0.118.0 (Mac OS 26.3.1; arm64) iTerm.app/3.6.9 (codex-tui; 0.118.0)";
|
|
31
36
|
const CODEX_DEFAULT_ORIGINATOR = "codex-tui";
|
|
32
37
|
|
|
38
|
+
function resolveConfiguredModelForProvider(config = {}, provider = "") {
|
|
39
|
+
if (config.routerProvider && sameModelProvider(config.routerProvider, provider)) {
|
|
40
|
+
return config.routerModel;
|
|
41
|
+
}
|
|
42
|
+
if (config.agentProvider && sameModelProvider(config.agentProvider, provider)) {
|
|
43
|
+
return config.agentModel;
|
|
44
|
+
}
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
function buildOpenAiChatRequest({
|
|
34
49
|
model = "",
|
|
35
50
|
systemPrompt = "",
|
|
@@ -217,7 +232,11 @@ async function resolveUpstreamRuntime({
|
|
|
217
232
|
const baseUrl = useCodexResponses
|
|
218
233
|
? String(env.UFOO_CODEX_BASE_URL || "").trim() || CODEX_DEFAULT_BASE_URL
|
|
219
234
|
: String(env.OPENAI_BASE_URL || "").trim() || "https://api.openai.com/v1";
|
|
220
|
-
const resolvedModel = String(
|
|
235
|
+
const resolvedModel = String(
|
|
236
|
+
model
|
|
237
|
+
|| resolveConfiguredModelForProvider(config, "codex")
|
|
238
|
+
|| defaultRouterModelForProvider("codex")
|
|
239
|
+
).trim();
|
|
221
240
|
return {
|
|
222
241
|
provider: "codex",
|
|
223
242
|
transport: useCodexResponses ? "codex-responses" : "openai-chat",
|
|
@@ -237,7 +256,11 @@ async function resolveUpstreamRuntime({
|
|
|
237
256
|
env,
|
|
238
257
|
});
|
|
239
258
|
const baseUrl = String(env.ANTHROPIC_BASE_URL || "").trim() || "https://api.anthropic.com/v1";
|
|
240
|
-
const resolvedModel = String(
|
|
259
|
+
const resolvedModel = String(
|
|
260
|
+
model
|
|
261
|
+
|| resolveConfiguredModelForProvider(config, "claude")
|
|
262
|
+
|| defaultRouterModelForProvider("claude")
|
|
263
|
+
).trim();
|
|
241
264
|
return {
|
|
242
265
|
provider: "claude",
|
|
243
266
|
transport: "anthropic-messages",
|
|
@@ -252,7 +275,7 @@ async function resolveUpstreamRuntime({
|
|
|
252
275
|
const runtime = resolveRuntimeConfig({
|
|
253
276
|
workspaceRoot: projectRoot,
|
|
254
277
|
provider: normalizedProvider === "ucode" ? "" : normalizedProvider,
|
|
255
|
-
model,
|
|
278
|
+
model: model || resolveConfiguredModelForProvider(config, normalizedProvider) || defaultAgentModelForProvider(config.agentProvider),
|
|
256
279
|
});
|
|
257
280
|
const auth = runtime.apiKey ? { apiKey: String(runtime.apiKey || "").trim() } : { headers: {} };
|
|
258
281
|
return {
|
|
@@ -306,14 +306,15 @@ function createAgentViewController(options = {}) {
|
|
|
306
306
|
const product = "ClaudeCode";
|
|
307
307
|
const detail = label ? `${label} · managed headless` : "managed headless";
|
|
308
308
|
const iconWidth = 9;
|
|
309
|
+
const iconGap = " ";
|
|
309
310
|
const iconLine = (icon = "", text = "") => {
|
|
310
311
|
const pad = " ".repeat(Math.max(0, iconWidth - displayWidth(icon)));
|
|
311
|
-
return `${CLAUDE_ORANGE}${icon}${ANSI_RESET}${pad}${text}`;
|
|
312
|
+
return `${CLAUDE_ORANGE}${icon}${ANSI_RESET}${pad}${iconGap}${text}`;
|
|
312
313
|
};
|
|
313
314
|
const lines = [
|
|
314
|
-
iconLine("▐▛███▜▌", `${product}v${packageVersion}`),
|
|
315
|
+
iconLine(" ▐▛███▜▌", `${product}v${packageVersion}`),
|
|
315
316
|
iconLine("▝▜█████▛▘", detail),
|
|
316
|
-
iconLine("
|
|
317
|
+
iconLine(" ▘▘ ▝▝ ", projectPath),
|
|
317
318
|
"",
|
|
318
319
|
];
|
|
319
320
|
if (width < 44) return lines;
|
|
@@ -9,6 +9,9 @@ const {
|
|
|
9
9
|
loadGlobalUcodeConfig,
|
|
10
10
|
saveGlobalUcodeConfig,
|
|
11
11
|
normalizeControllerMode,
|
|
12
|
+
SETTINGS_MODEL_DEFAULTS,
|
|
13
|
+
defaultAgentModelForProvider,
|
|
14
|
+
defaultRouterModelForProvider,
|
|
12
15
|
} = require("../config");
|
|
13
16
|
const { resolveTransport } = require("../code/nativeRunner");
|
|
14
17
|
const { resolveDisplayNickname } = require("../daemon/nicknameScope");
|
|
@@ -43,17 +46,6 @@ function defaultResolveTerminalApp() {
|
|
|
43
46
|
return "";
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
const SETTINGS_MODEL_DEFAULTS = Object.freeze({
|
|
47
|
-
agent: Object.freeze({
|
|
48
|
-
codex: "gpt-5.5",
|
|
49
|
-
claude: "opus-4.7",
|
|
50
|
-
}),
|
|
51
|
-
router: Object.freeze({
|
|
52
|
-
codex: "gpt-5.4-mini",
|
|
53
|
-
claude: "sonnet-4.7",
|
|
54
|
-
}),
|
|
55
|
-
});
|
|
56
|
-
|
|
57
49
|
function normalizeSettingsProvider(value = "", fallback = "codex-cli") {
|
|
58
50
|
const text = String(value || "").trim().toLowerCase();
|
|
59
51
|
if (text === "claude" || text === "claude-cli" || text === "claude-code" || text === "anthropic") {
|
|
@@ -69,13 +61,8 @@ function agentProviderKey(value = "") {
|
|
|
69
61
|
return normalizeSettingsProvider(value) === "claude-cli" ? "claude" : "codex";
|
|
70
62
|
}
|
|
71
63
|
|
|
72
|
-
function defaultAgentModelForProvider(value = "") {
|
|
73
|
-
return SETTINGS_MODEL_DEFAULTS.agent[agentProviderKey(value)] || SETTINGS_MODEL_DEFAULTS.agent.codex;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
64
|
function defaultGateModelForProvider(value = "") {
|
|
77
|
-
|
|
78
|
-
return SETTINGS_MODEL_DEFAULTS.router[key] || SETTINGS_MODEL_DEFAULTS.router.codex;
|
|
65
|
+
return defaultRouterModelForProvider(value);
|
|
79
66
|
}
|
|
80
67
|
|
|
81
68
|
function collectHostLaunchRequestContext(env = process.env) {
|
package/src/chat/commands.js
CHANGED
|
@@ -113,7 +113,7 @@ const COMMAND_TREE = {
|
|
|
113
113
|
loop: { desc: "Set router mode to loop", order: 5 },
|
|
114
114
|
legacy: { desc: "Set router mode to legacy", order: 6 },
|
|
115
115
|
shadow: { desc: "Set router mode to shadow", order: 7 },
|
|
116
|
-
codex: { desc: "Use Codex gate model (gpt-5.
|
|
116
|
+
codex: { desc: "Use Codex gate model (gpt-5.3-codex-spark)", order: 8 },
|
|
117
117
|
claude: { desc: "Use Claude gate model (sonnet-4.7)", order: 9 },
|
|
118
118
|
},
|
|
119
119
|
},
|
|
@@ -354,19 +354,6 @@ function createDaemonMessageRouter(options = {}) {
|
|
|
354
354
|
function handleBusMessage(msg) {
|
|
355
355
|
const data = msg.data || {};
|
|
356
356
|
if (data.event === "activity_state_changed") {
|
|
357
|
-
const publisher = data.publisher && data.publisher !== "unknown"
|
|
358
|
-
? data.publisher
|
|
359
|
-
: (data.subscriber || "bus");
|
|
360
|
-
const viewingAgent = getViewingAgent();
|
|
361
|
-
if (
|
|
362
|
-
getCurrentView() === "agent" &&
|
|
363
|
-
isAgentViewUsesBus() &&
|
|
364
|
-
viewingAgent &&
|
|
365
|
-
isAgentEventForViewingAgent(data, viewingAgent, publisher)
|
|
366
|
-
) {
|
|
367
|
-
const state = data.state || (data.data && data.data.state) || "";
|
|
368
|
-
if (state) writeToAgentTerm(`[state] ${state}\r\n`);
|
|
369
|
-
}
|
|
370
357
|
requestStatus();
|
|
371
358
|
return true;
|
|
372
359
|
}
|
|
@@ -391,6 +378,18 @@ function createDaemonMessageRouter(options = {}) {
|
|
|
391
378
|
if (!displayMessage && !streamPayload) return true;
|
|
392
379
|
|
|
393
380
|
const viewingAgent = getViewingAgent();
|
|
381
|
+
const isOwnInternalPrompt =
|
|
382
|
+
data.source === "chat-internal-agent-view" &&
|
|
383
|
+
viewingAgent &&
|
|
384
|
+
data.target === viewingAgent &&
|
|
385
|
+
publisher !== viewingAgent;
|
|
386
|
+
if (
|
|
387
|
+
getCurrentView() === "agent" &&
|
|
388
|
+
isAgentViewUsesBus() &&
|
|
389
|
+
isOwnInternalPrompt
|
|
390
|
+
) {
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
394
393
|
const isAgentViewTarget =
|
|
395
394
|
getCurrentView() === "agent" &&
|
|
396
395
|
isAgentViewUsesBus() &&
|
package/src/chat/index.js
CHANGED
|
@@ -1062,11 +1062,12 @@ async function runChat(projectRoot, options = {}) {
|
|
|
1062
1062
|
: `${prefix}>`;
|
|
1063
1063
|
|
|
1064
1064
|
promptBox.setContent(content);
|
|
1065
|
+
if (!input.parent || !promptBox.parent) return;
|
|
1066
|
+
|
|
1065
1067
|
promptBox.width = content.length + 1; // content + spacer
|
|
1066
1068
|
input.left = promptBox.width;
|
|
1067
1069
|
input.width = `100%-${promptBox.width}`;
|
|
1068
1070
|
|
|
1069
|
-
if (!input.parent || !promptBox.parent) return;
|
|
1070
1071
|
resizeInput();
|
|
1071
1072
|
if (typeof input._updateCursor === "function") {
|
|
1072
1073
|
input._updateCursor();
|
package/src/code/agent.js
CHANGED
|
@@ -17,7 +17,7 @@ const {
|
|
|
17
17
|
stripLeakedEscapeTags,
|
|
18
18
|
} = require("./tui");
|
|
19
19
|
const { stripBlessedTags } = require("../chat/text");
|
|
20
|
-
const { loadConfig } = require("../config");
|
|
20
|
+
const { loadConfig, defaultAgentModelForProvider, sameModelProvider } = require("../config");
|
|
21
21
|
const {
|
|
22
22
|
resolveSessionId,
|
|
23
23
|
normalizeSessionId,
|
|
@@ -109,12 +109,14 @@ function resolveUcodeProviderModel({
|
|
|
109
109
|
|| ""
|
|
110
110
|
).trim();
|
|
111
111
|
const resolvedProvider = resolvePlannerProvider(explicitProvider || fallbackProviderFromAgent);
|
|
112
|
+
const configuredModel = sameModelProvider(config.ucodeProvider || config.agentProvider, resolvedProvider)
|
|
113
|
+
? (config.ucodeModel || config.agentModel)
|
|
114
|
+
: "";
|
|
112
115
|
const resolvedModel = String(
|
|
113
116
|
model
|
|
114
117
|
|| process.env.UFOO_UCODE_MODEL
|
|
115
|
-
||
|
|
116
|
-
||
|
|
117
|
-
|| ""
|
|
118
|
+
|| configuredModel
|
|
119
|
+
|| defaultAgentModelForProvider(resolvedProvider)
|
|
118
120
|
).trim();
|
|
119
121
|
return {
|
|
120
122
|
provider: resolvedProvider,
|
package/src/code/nativeRunner.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { randomUUID } = require("crypto");
|
|
2
|
-
const { loadConfig } = require("../config");
|
|
2
|
+
const { loadConfig, defaultAgentModelForProvider, sameModelProvider } = require("../config");
|
|
3
3
|
const { runToolCall } = require("./dispatch");
|
|
4
4
|
const { getReadToolDescription } = require("./prompts/toolDescriptions/read");
|
|
5
5
|
const { getWriteToolDescription } = require("./prompts/toolDescriptions/write");
|
|
@@ -219,13 +219,15 @@ function resolveRuntimeConfig({ workspaceRoot = process.cwd(), provider = "", mo
|
|
|
219
219
|
|| configuredProvider
|
|
220
220
|
|| "openai"
|
|
221
221
|
) || "openai";
|
|
222
|
+
const configuredModel = sameModelProvider(config.ucodeProvider || config.agentProvider, selectedProvider)
|
|
223
|
+
? (config.ucodeModel || config.agentModel)
|
|
224
|
+
: "";
|
|
222
225
|
|
|
223
226
|
const selectedModel = String(
|
|
224
227
|
model
|
|
225
228
|
|| process.env.UFOO_UCODE_MODEL
|
|
226
|
-
||
|
|
227
|
-
||
|
|
228
|
-
|| ""
|
|
229
|
+
|| configuredModel
|
|
230
|
+
|| defaultAgentModelForProvider(selectedProvider)
|
|
229
231
|
).trim();
|
|
230
232
|
|
|
231
233
|
const defaultBaseUrl = selectedProvider === "anthropic"
|
package/src/code/tui.js
CHANGED
|
@@ -627,8 +627,8 @@ function runUcodeTui({
|
|
|
627
627
|
blessed,
|
|
628
628
|
currentInputHeight: 4,
|
|
629
629
|
version: UCODE_VERSION,
|
|
630
|
-
logBorder:
|
|
631
|
-
logScrollbar:
|
|
630
|
+
logBorder: false,
|
|
631
|
+
logScrollbar: false,
|
|
632
632
|
});
|
|
633
633
|
|
|
634
634
|
if (completionPanel && typeof completionPanel.hide === "function") {
|
|
@@ -1031,7 +1031,7 @@ function runUcodeTui({
|
|
|
1031
1031
|
if (!plain) return;
|
|
1032
1032
|
const content = ` → ${escapeBlessed(plain)} `;
|
|
1033
1033
|
const visibleLen = plain.length + 4; // " → " + text + " "
|
|
1034
|
-
const boxWidth =
|
|
1034
|
+
const boxWidth = logBox.width || 80;
|
|
1035
1035
|
const pad = boxWidth > visibleLen ? " ".repeat(boxWidth - visibleLen) : "";
|
|
1036
1036
|
logBox.log(`{cyan-bg}{white-fg}${content}${pad}{/white-fg}{/cyan-bg}`);
|
|
1037
1037
|
logBox.log(""); // Add line break after user input
|
package/src/config.js
CHANGED
|
@@ -4,6 +4,17 @@ const path = require("path");
|
|
|
4
4
|
|
|
5
5
|
const UCODE_FIELDS = ["ucodeProvider", "ucodeModel", "ucodeBaseUrl", "ucodeApiKey", "ucodeAgentDir"];
|
|
6
6
|
|
|
7
|
+
const SETTINGS_MODEL_DEFAULTS = Object.freeze({
|
|
8
|
+
agent: Object.freeze({
|
|
9
|
+
codex: "gpt-5.5",
|
|
10
|
+
claude: "opus-4.7",
|
|
11
|
+
}),
|
|
12
|
+
router: Object.freeze({
|
|
13
|
+
codex: "gpt-5.3-codex-spark",
|
|
14
|
+
claude: "sonnet-4.7",
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
|
|
7
18
|
const DEFAULT_CONFIG = {
|
|
8
19
|
launchMode: "auto",
|
|
9
20
|
agentProvider: "codex-cli",
|
|
@@ -15,6 +26,8 @@ const DEFAULT_CONFIG = {
|
|
|
15
26
|
claudeOauthTokenPath: "",
|
|
16
27
|
claudeOauthRefreshWindowSec: 300,
|
|
17
28
|
agentModel: "",
|
|
29
|
+
routerProvider: "",
|
|
30
|
+
routerModel: "",
|
|
18
31
|
autoResume: false,
|
|
19
32
|
};
|
|
20
33
|
|
|
@@ -41,6 +54,33 @@ function normalizeAgentProvider(value) {
|
|
|
41
54
|
return "codex-cli";
|
|
42
55
|
}
|
|
43
56
|
|
|
57
|
+
function providerKey(value = "") {
|
|
58
|
+
const text = String(value || "").trim().toLowerCase();
|
|
59
|
+
if (text === "claude" || text === "claude-cli" || text === "claude-code" || text === "anthropic") return "claude";
|
|
60
|
+
return "codex";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function sameModelProvider(left = "", right = "") {
|
|
64
|
+
return providerKey(left) === providerKey(right);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function defaultAgentModelForProvider(value = "") {
|
|
68
|
+
return SETTINGS_MODEL_DEFAULTS.agent[providerKey(value)] || SETTINGS_MODEL_DEFAULTS.agent.codex;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function defaultRouterProviderForAgentProvider(value = "") {
|
|
72
|
+
return providerKey(value) === "claude" ? "claude" : "codex";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function defaultRouterModelForProvider(value = "") {
|
|
76
|
+
return SETTINGS_MODEL_DEFAULTS.router[providerKey(value)] || SETTINGS_MODEL_DEFAULTS.router.codex;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function normalizeModel(value, fallback = "") {
|
|
80
|
+
const text = typeof value === "string" ? value.trim() : "";
|
|
81
|
+
return text || fallback;
|
|
82
|
+
}
|
|
83
|
+
|
|
44
84
|
function normalizeControllerMode(value) {
|
|
45
85
|
const raw = String(value || "").trim().toLowerCase();
|
|
46
86
|
if (raw === "shadow") return "shadow";
|
|
@@ -100,11 +140,19 @@ function loadJsonSafe(filePath) {
|
|
|
100
140
|
function loadConfig(projectRoot) {
|
|
101
141
|
try {
|
|
102
142
|
const raw = loadJsonSafe(configPath(projectRoot));
|
|
143
|
+
const agentProvider = normalizeAgentProvider(raw.agentProvider);
|
|
144
|
+
const routerProvider = normalizeModel(
|
|
145
|
+
raw.routerProvider,
|
|
146
|
+
defaultRouterProviderForAgentProvider(agentProvider)
|
|
147
|
+
);
|
|
103
148
|
return {
|
|
104
149
|
...DEFAULT_CONFIG,
|
|
105
150
|
...raw,
|
|
106
151
|
launchMode: normalizeLaunchMode(raw.launchMode),
|
|
107
|
-
agentProvider
|
|
152
|
+
agentProvider,
|
|
153
|
+
agentModel: normalizeModel(raw.agentModel, defaultAgentModelForProvider(agentProvider)),
|
|
154
|
+
routerProvider,
|
|
155
|
+
routerModel: normalizeModel(raw.routerModel, defaultRouterModelForProvider(routerProvider)),
|
|
108
156
|
controllerMode: Object.prototype.hasOwnProperty.call(raw, "controllerMode")
|
|
109
157
|
? normalizeControllerMode(raw.controllerMode)
|
|
110
158
|
: DEFAULT_CONFIG.controllerMode,
|
|
@@ -121,7 +169,15 @@ function loadConfig(projectRoot) {
|
|
|
121
169
|
...loadGlobalUcodeConfig(),
|
|
122
170
|
};
|
|
123
171
|
} catch {
|
|
124
|
-
|
|
172
|
+
const agentProvider = DEFAULT_CONFIG.agentProvider;
|
|
173
|
+
const routerProvider = defaultRouterProviderForAgentProvider(agentProvider);
|
|
174
|
+
return {
|
|
175
|
+
...DEFAULT_CONFIG,
|
|
176
|
+
agentModel: defaultAgentModelForProvider(agentProvider),
|
|
177
|
+
routerProvider,
|
|
178
|
+
routerModel: defaultRouterModelForProvider(routerProvider),
|
|
179
|
+
...DEFAULT_UCODE_CONFIG,
|
|
180
|
+
};
|
|
125
181
|
}
|
|
126
182
|
}
|
|
127
183
|
|
|
@@ -152,6 +208,9 @@ function saveConfig(projectRoot, config) {
|
|
|
152
208
|
}
|
|
153
209
|
merged.launchMode = normalizeLaunchMode(merged.launchMode);
|
|
154
210
|
merged.agentProvider = normalizeAgentProvider(merged.agentProvider);
|
|
211
|
+
merged.agentModel = typeof merged.agentModel === "string" ? merged.agentModel.trim() : "";
|
|
212
|
+
merged.routerProvider = typeof merged.routerProvider === "string" ? merged.routerProvider.trim() : "";
|
|
213
|
+
merged.routerModel = typeof merged.routerModel === "string" ? merged.routerModel.trim() : "";
|
|
155
214
|
merged.controllerMode = normalizeControllerMode(merged.controllerMode);
|
|
156
215
|
merged.codexInternalThreadMode = normalizeCodexInternalThreadMode(merged.codexInternalThreadMode);
|
|
157
216
|
merged.codexAuthPath = normalizeCodexAuthPath(merged.codexAuthPath);
|
|
@@ -190,12 +249,17 @@ function saveGlobalUcodeConfig(updates = {}) {
|
|
|
190
249
|
}
|
|
191
250
|
|
|
192
251
|
module.exports = {
|
|
252
|
+
SETTINGS_MODEL_DEFAULTS,
|
|
193
253
|
loadConfig,
|
|
194
254
|
saveConfig,
|
|
195
255
|
loadGlobalUcodeConfig,
|
|
196
256
|
saveGlobalUcodeConfig,
|
|
197
257
|
normalizeLaunchMode,
|
|
198
258
|
normalizeAgentProvider,
|
|
259
|
+
sameModelProvider,
|
|
260
|
+
defaultAgentModelForProvider,
|
|
261
|
+
defaultRouterProviderForAgentProvider,
|
|
262
|
+
defaultRouterModelForProvider,
|
|
199
263
|
normalizeControllerMode,
|
|
200
264
|
normalizeCodexInternalThreadMode,
|
|
201
265
|
normalizeCodexAuthPath,
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
loadConfig,
|
|
5
|
+
defaultRouterProviderForAgentProvider,
|
|
6
|
+
defaultRouterModelForProvider,
|
|
7
|
+
sameModelProvider,
|
|
8
|
+
} = require("../config");
|
|
4
9
|
|
|
5
10
|
const DEFAULT_EXECUTION_PATH = "main";
|
|
6
11
|
const DEFAULT_CONFIDENCE_THRESHOLD = 0.6;
|
|
@@ -122,18 +127,22 @@ function resolveGateRouterConfig({
|
|
|
122
127
|
loadConfigImpl = loadConfig,
|
|
123
128
|
} = {}) {
|
|
124
129
|
const config = loadConfigImpl(projectRoot || process.cwd());
|
|
130
|
+
const requestProvider = requestMeta.router_provider || env.UFOO_AGENT_ROUTER_PROVIDER;
|
|
131
|
+
const provider = String(
|
|
132
|
+
requestProvider
|
|
133
|
+
|| config.routerProvider
|
|
134
|
+
|| defaultRouterProviderForAgentProvider(config.agentProvider)
|
|
135
|
+
).trim();
|
|
136
|
+
const configuredRouterModel = !requestProvider || sameModelProvider(config.routerProvider, provider)
|
|
137
|
+
? config.routerModel
|
|
138
|
+
: "";
|
|
125
139
|
return {
|
|
126
|
-
provider
|
|
127
|
-
requestMeta.router_provider
|
|
128
|
-
|| env.UFOO_AGENT_ROUTER_PROVIDER
|
|
129
|
-
|| config.routerProvider
|
|
130
|
-
|| "ucode"
|
|
131
|
-
).trim(),
|
|
140
|
+
provider,
|
|
132
141
|
model: String(
|
|
133
142
|
requestMeta.router_model
|
|
134
143
|
|| env.UFOO_AGENT_ROUTER_MODEL
|
|
135
|
-
||
|
|
136
|
-
||
|
|
144
|
+
|| configuredRouterModel
|
|
145
|
+
|| defaultRouterModelForProvider(provider)
|
|
137
146
|
).trim(),
|
|
138
147
|
timeoutMs: toPositiveNumber(
|
|
139
148
|
requestMeta.router_timeout_ms
|
package/src/daemon/index.js
CHANGED
|
@@ -889,22 +889,6 @@ function startBusBridge(projectRoot, provider, onEvent, onStatus, shouldDrain) {
|
|
|
889
889
|
}
|
|
890
890
|
}
|
|
891
891
|
|
|
892
|
-
function emitRecentWatchedEvents(agentId, limit = 80) {
|
|
893
|
-
if (!agentId) return;
|
|
894
|
-
const previous = new Set(state.watchedAgents);
|
|
895
|
-
state.watchedAgents.add(agentId);
|
|
896
|
-
const aliases = buildWatchedAliases();
|
|
897
|
-
state.watchedAgents = previous;
|
|
898
|
-
const matches = [];
|
|
899
|
-
const files = getEventFiles().slice(-3);
|
|
900
|
-
for (const file of files) {
|
|
901
|
-
for (const evt of readEventFile(file)) {
|
|
902
|
-
if (isWatchedEvent(evt, aliases)) matches.push(evt);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
for (const evt of matches.slice(-limit)) emitBusEvent(evt);
|
|
906
|
-
}
|
|
907
|
-
|
|
908
892
|
function pollWatchedEvents() {
|
|
909
893
|
if (state.watchedAgents.size === 0) {
|
|
910
894
|
state.lastEventSeq = readCurrentSeq();
|
|
@@ -1032,7 +1016,6 @@ function startBusBridge(projectRoot, provider, onEvent, onStatus, shouldDrain) {
|
|
|
1032
1016
|
watchAgent(agentId, enabled = true) {
|
|
1033
1017
|
if (!agentId) return;
|
|
1034
1018
|
if (enabled) {
|
|
1035
|
-
emitRecentWatchedEvents(agentId);
|
|
1036
1019
|
state.watchedAgents.add(agentId);
|
|
1037
1020
|
state.lastEventSeq = Math.max(state.lastEventSeq, readCurrentSeq());
|
|
1038
1021
|
} else {
|
package/src/daemon/run.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
2
|
const { startDaemon, stopDaemon, isRunning } = require("./index");
|
|
3
|
-
const { loadConfig } = require("../config");
|
|
3
|
+
const { loadConfig, defaultAgentModelForProvider } = require("../config");
|
|
4
4
|
|
|
5
5
|
function runDaemonCli(argv) {
|
|
6
6
|
const cmd = argv[1] || "start";
|
|
7
7
|
const projectRoot = process.cwd();
|
|
8
8
|
const config = loadConfig(projectRoot);
|
|
9
|
-
const
|
|
9
|
+
const envProvider = process.env.UFOO_AGENT_PROVIDER;
|
|
10
|
+
const provider = envProvider || config.agentProvider || "codex-cli";
|
|
10
11
|
const model =
|
|
11
|
-
process.env.UFOO_AGENT_MODEL
|
|
12
|
+
process.env.UFOO_AGENT_MODEL
|
|
13
|
+
|| (envProvider && envProvider !== config.agentProvider ? "" : config.agentModel)
|
|
14
|
+
|| defaultAgentModelForProvider(provider);
|
|
12
15
|
const resumeMode = process.env.UFOO_FORCE_RESUME === "1" ? "force" : "auto";
|
|
13
16
|
const launchMode = config.launchMode || "terminal";
|
|
14
17
|
|