u-foo 1.7.0 → 1.7.2
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/chat/dashboardKeyController.js +3 -2
- package/src/chat/dashboardView.js +1 -1
- package/src/chat/index.js +7 -2
- package/src/chat/settingsController.js +3 -1
- package/src/daemon/ops.js +7 -27
- package/src/init/index.js +7 -6
- package/src/terminal/adapters/hostAdapter.js +2 -1
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const DEFAULT_MODE_OPTIONS = ["terminal", "tmux", "internal"];
|
|
1
|
+
const DEFAULT_MODE_OPTIONS = ["auto", "host", "terminal", "tmux", "internal"];
|
|
2
2
|
|
|
3
3
|
function createDashboardKeyController(options = {}) {
|
|
4
4
|
const {
|
|
@@ -468,7 +468,8 @@ function createDashboardKeyController(options = {}) {
|
|
|
468
468
|
if (key.name === "down") {
|
|
469
469
|
clearTargetAgent();
|
|
470
470
|
state.dashboardView = "mode";
|
|
471
|
-
|
|
471
|
+
const launchModeIndex = modeOptions.indexOf(state.launchMode);
|
|
472
|
+
state.selectedModeIndex = launchModeIndex >= 0 ? launchModeIndex : 0;
|
|
472
473
|
renderDashboardAndScreen();
|
|
473
474
|
return true;
|
|
474
475
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { clampAgentWindowWithSelection } = require("./agentDirectory");
|
|
2
2
|
|
|
3
|
-
const DEFAULT_MODE_OPTIONS = ["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";
|
package/src/chat/index.js
CHANGED
|
@@ -52,6 +52,8 @@ const {
|
|
|
52
52
|
filterVisibleProjectRuntimes,
|
|
53
53
|
} = require("./projectRuntimes");
|
|
54
54
|
|
|
55
|
+
const MODE_OPTIONS = ["auto", "host", "terminal", "tmux", "internal"];
|
|
56
|
+
|
|
55
57
|
async function runChat(projectRoot, options = {}) {
|
|
56
58
|
const globalMode = options && options.globalMode === true;
|
|
57
59
|
const DASHBOARD_HEIGHT = globalMode ? 2 : 1;
|
|
@@ -673,7 +675,7 @@ async function runChat(projectRoot, options = {}) {
|
|
|
673
675
|
let focusMode = "input"; // "input" or "dashboard"
|
|
674
676
|
let dashboardView = "agents"; // "projects" | "agents" | "mode" | "provider" | "assistant" | "cron"
|
|
675
677
|
let reportPendingTotal = 0;
|
|
676
|
-
let selectedModeIndex =
|
|
678
|
+
let selectedModeIndex = Math.max(0, MODE_OPTIONS.indexOf(launchMode));
|
|
677
679
|
const providerOptions = [
|
|
678
680
|
{ label: "codex", value: "codex-cli" },
|
|
679
681
|
{ label: "claude", value: "claude-cli" },
|
|
@@ -1129,6 +1131,7 @@ async function runChat(projectRoot, options = {}) {
|
|
|
1129
1131
|
},
|
|
1130
1132
|
assistantOptions,
|
|
1131
1133
|
providerOptions,
|
|
1134
|
+
modeOptions: MODE_OPTIONS,
|
|
1132
1135
|
getAutoResume: () => autoResume,
|
|
1133
1136
|
setAutoResumeState: (value) => {
|
|
1134
1137
|
autoResume = value;
|
|
@@ -1187,6 +1190,7 @@ async function runChat(projectRoot, options = {}) {
|
|
|
1187
1190
|
resumeOptions,
|
|
1188
1191
|
pendingReports: reportPendingTotal,
|
|
1189
1192
|
dashHints: DASH_HINTS,
|
|
1193
|
+
modeOptions: MODE_OPTIONS,
|
|
1190
1194
|
});
|
|
1191
1195
|
if (globalMode && (focusMode !== "dashboard" || dashboardView === "projects")) {
|
|
1192
1196
|
projectListWindowStart = computed.windowStart;
|
|
@@ -1329,7 +1333,7 @@ async function runChat(projectRoot, options = {}) {
|
|
|
1329
1333
|
agentListWindowStart = 0;
|
|
1330
1334
|
clampAgentWindow();
|
|
1331
1335
|
}
|
|
1332
|
-
selectedModeIndex =
|
|
1336
|
+
selectedModeIndex = Math.max(0, MODE_OPTIONS.indexOf(launchMode));
|
|
1333
1337
|
selectedProviderIndex = Math.max(0, providerOptions.findIndex((opt) => opt.value === agentProvider));
|
|
1334
1338
|
selectedAssistantIndex = Math.max(
|
|
1335
1339
|
0,
|
|
@@ -1421,6 +1425,7 @@ async function runChat(projectRoot, options = {}) {
|
|
|
1421
1425
|
setScreenGrabKeys: (value) => {
|
|
1422
1426
|
screen.grabKeys = Boolean(value);
|
|
1423
1427
|
},
|
|
1428
|
+
modeOptions: MODE_OPTIONS,
|
|
1424
1429
|
});
|
|
1425
1430
|
|
|
1426
1431
|
function handleDashboardKey(key) {
|
|
@@ -24,6 +24,7 @@ function createSettingsController(options = {}) {
|
|
|
24
24
|
setSelectedAssistantIndex = () => {},
|
|
25
25
|
assistantOptions = [],
|
|
26
26
|
providerOptions = [],
|
|
27
|
+
modeOptions = [],
|
|
27
28
|
getAutoResume = () => true,
|
|
28
29
|
setAutoResumeState = () => {},
|
|
29
30
|
setSelectedResumeIndex = () => {},
|
|
@@ -68,7 +69,8 @@ function createSettingsController(options = {}) {
|
|
|
68
69
|
const next = normalizeLaunchMode(mode);
|
|
69
70
|
if (next === getLaunchMode()) return false;
|
|
70
71
|
setLaunchModeState(next);
|
|
71
|
-
|
|
72
|
+
const nextIndex = modeOptions.findIndex((opt) => opt === next);
|
|
73
|
+
setSelectedModeIndex(nextIndex >= 0 ? nextIndex : 0);
|
|
72
74
|
saveConfig(projectRoot, { launchMode: next });
|
|
73
75
|
logMessage("status", `{white-fg}⚙{/white-fg} Launch mode: ${next}`);
|
|
74
76
|
renderDashboard();
|
package/src/daemon/ops.js
CHANGED
|
@@ -9,8 +9,6 @@ const { isITerm2 } = require("../terminal/detect");
|
|
|
9
9
|
const { createTerminalAdapterRouter } = require("../terminal/adapterRouter");
|
|
10
10
|
const {
|
|
11
11
|
createSession: createHostSession,
|
|
12
|
-
closeSession: closeHostSession,
|
|
13
|
-
sendToSocket: sendHostSocketRequest,
|
|
14
12
|
} = require("../terminal/adapters/hostAdapter");
|
|
15
13
|
|
|
16
14
|
function normalizeLaunchAgent(agent = "") {
|
|
@@ -468,27 +466,12 @@ async function spawnManagedHostAgent(
|
|
|
468
466
|
createOptions.source_session_id = hostContext.hostSessionId;
|
|
469
467
|
}
|
|
470
468
|
|
|
471
|
-
const created = await createHostSession(hostContext.hostDaemonSock, createOptions);
|
|
472
|
-
const sessionId = normalizeOptionalString(created?.session_id);
|
|
473
|
-
const injectSock = normalizeOptionalString(created?.inject_sock);
|
|
474
|
-
if (!sessionId || !injectSock) {
|
|
475
|
-
throw new Error("host create_session returned incomplete session info");
|
|
476
|
-
}
|
|
477
|
-
|
|
478
469
|
const args = Array.isArray(extraArgs) ? extraArgs : [];
|
|
479
470
|
const argText = args.length > 0 ? ` ${args.map(shellEscape).join(" ")}` : "";
|
|
480
|
-
const envParts = [
|
|
481
|
-
"UFOO_LAUNCH_MODE=host",
|
|
482
|
-
`UFOO_HOST_DAEMON_SOCK=${shellEscape(hostContext.hostDaemonSock)}`,
|
|
483
|
-
`UFOO_HOST_SESSION_ID=${shellEscape(sessionId)}`,
|
|
484
|
-
`UFOO_HOST_INJECT_SOCK=${shellEscape(injectSock)}`,
|
|
485
|
-
];
|
|
471
|
+
const envParts = ["UFOO_LAUNCH_MODE=host"];
|
|
486
472
|
if (nickname) {
|
|
487
473
|
envParts.push(`UFOO_NICKNAME=${shellEscape(nickname)}`);
|
|
488
474
|
}
|
|
489
|
-
if (hostContext.hostName) {
|
|
490
|
-
envParts.push(`UFOO_HOST_NAME=${shellEscape(hostContext.hostName)}`);
|
|
491
|
-
}
|
|
492
475
|
if (extraEnv) {
|
|
493
476
|
envParts.push(String(extraEnv).trim());
|
|
494
477
|
}
|
|
@@ -498,16 +481,13 @@ async function spawnManagedHostAgent(
|
|
|
498
481
|
const runCmd = titleCmd
|
|
499
482
|
? `cd ${shellEscape(projectRoot)} && ${titleCmd} && ${launchCmd}`
|
|
500
483
|
: `cd ${shellEscape(projectRoot)} && ${launchCmd}`;
|
|
484
|
+
createOptions.command = runCmd;
|
|
501
485
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
} catch {
|
|
508
|
-
// ignore cleanup failures
|
|
509
|
-
}
|
|
510
|
-
throw err;
|
|
486
|
+
const created = await createHostSession(hostContext.hostDaemonSock, createOptions);
|
|
487
|
+
const sessionId = normalizeOptionalString(created?.session_id);
|
|
488
|
+
const injectSock = normalizeOptionalString(created?.inject_sock);
|
|
489
|
+
if (!sessionId || !injectSock) {
|
|
490
|
+
throw new Error("host create_session returned incomplete session info");
|
|
511
491
|
}
|
|
512
492
|
|
|
513
493
|
const subscriberId = await waitForNewSubscriber(projectRoot, agentType, existing, 20000);
|
package/src/init/index.js
CHANGED
|
@@ -90,16 +90,17 @@ class UfooInit {
|
|
|
90
90
|
fs.mkdirSync(ufooDir, { recursive: true });
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
// 创建 docs
|
|
93
|
+
// 创建 docs 符号链接:项目的 docs/ -> .ufoo/docs
|
|
94
94
|
const docsLink = path.join(ufooDir, "docs");
|
|
95
|
-
const
|
|
95
|
+
const projectDocs = path.join(project, "docs");
|
|
96
96
|
|
|
97
|
-
if (fs.existsSync(
|
|
98
|
-
|
|
97
|
+
if (fs.existsSync(projectDocs)) {
|
|
98
|
+
const linkStat = this.safeLstat(docsLink);
|
|
99
|
+
if (linkStat) {
|
|
99
100
|
fs.unlinkSync(docsLink);
|
|
100
101
|
}
|
|
101
|
-
fs.symlinkSync(
|
|
102
|
-
console.log(`[core] Created docs symlink: .ufoo/docs ->
|
|
102
|
+
fs.symlinkSync(projectDocs, docsLink);
|
|
103
|
+
console.log(`[core] Created docs symlink: .ufoo/docs -> docs/`);
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
console.log("[core] Done");
|
|
@@ -334,7 +334,7 @@ async function requestCloseSession(sockPath) {
|
|
|
334
334
|
/**
|
|
335
335
|
* Create a new terminal session via the daemon management socket.
|
|
336
336
|
* @param {string} [daemonSock] - Override daemon socket path (defaults to env)
|
|
337
|
-
* @param {object} [opts] - Options: { group_id, source_session_id }
|
|
337
|
+
* @param {object} [opts] - Options: { group_id, source_session_id, command }
|
|
338
338
|
* @returns {Promise<{session_id: string, inject_sock: string}>}
|
|
339
339
|
*/
|
|
340
340
|
async function createSession(daemonSock, opts = {}) {
|
|
@@ -342,6 +342,7 @@ async function createSession(daemonSock, opts = {}) {
|
|
|
342
342
|
const req = { type: "create_session" };
|
|
343
343
|
if (opts.group_id) req.group_id = opts.group_id;
|
|
344
344
|
if (opts.source_session_id) req.source_session_id = opts.source_session_id;
|
|
345
|
+
if (opts.command) req.command = opts.command;
|
|
345
346
|
return sendToSocket(sock, req);
|
|
346
347
|
}
|
|
347
348
|
|