fix: prefer ~ for home paths in output
This commit is contained in:
@@ -9,6 +9,7 @@ import { danger } from "../../globals.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import type { BrowserParentOpts } from "../browser-cli-shared.js";
|
||||
import { resolveBrowserActionContext } from "./shared.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
export function registerBrowserFilesAndDownloadsCommands(
|
||||
browser: Command,
|
||||
@@ -73,7 +74,7 @@ export function registerBrowserFilesAndDownloadsCommands(
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`downloaded: ${result.download.path}`);
|
||||
defaultRuntime.log(`downloaded: ${shortenHomePath(result.download.path)}`);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -105,7 +106,7 @@ export function registerBrowserFilesAndDownloadsCommands(
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`downloaded: ${result.download.path}`);
|
||||
defaultRuntime.log(`downloaded: ${shortenHomePath(result.download.path)}`);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
|
||||
@@ -9,6 +9,7 @@ import { danger } from "../globals.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import type { BrowserParentOpts } from "./browser-cli-shared.js";
|
||||
import { runCommandWithRuntime } from "./cli-utils.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
|
||||
function runBrowserObserve(action: () => Promise<void>) {
|
||||
return runCommandWithRuntime(defaultRuntime, action, (err) => {
|
||||
@@ -61,7 +62,7 @@ export function registerBrowserActionObserveCommands(
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`PDF: ${result.path}`);
|
||||
defaultRuntime.log(`PDF: ${shortenHomePath(result.path)}`);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { danger } from "../globals.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import type { BrowserParentOpts } from "./browser-cli-shared.js";
|
||||
import { runCommandWithRuntime } from "./cli-utils.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
|
||||
function runBrowserDebug(action: () => Promise<void>) {
|
||||
return runCommandWithRuntime(defaultRuntime, action, (err) => {
|
||||
@@ -164,7 +165,7 @@ export function registerBrowserDebugCommands(
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`TRACE:${result.path}`);
|
||||
defaultRuntime.log(`TRACE:${shortenHomePath(result.path)}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { defaultRuntime } from "../runtime.js";
|
||||
import { movePathToTrash } from "../browser/trash.js";
|
||||
import { formatDocsLink } from "../terminal/links.js";
|
||||
import { theme } from "../terminal/theme.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import { formatCliCommand } from "./command-format.js";
|
||||
|
||||
function bundledExtensionRootDir() {
|
||||
@@ -77,7 +78,8 @@ export function registerBrowserExtensionCommands(
|
||||
defaultRuntime.log(JSON.stringify({ ok: true, path: installed.path }, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(installed.path);
|
||||
const displayPath = shortenHomePath(installed.path);
|
||||
defaultRuntime.log(displayPath);
|
||||
const copied = await copyToClipboard(installed.path).catch(() => false);
|
||||
defaultRuntime.error(
|
||||
info(
|
||||
@@ -85,7 +87,7 @@ export function registerBrowserExtensionCommands(
|
||||
copied ? "Copied to clipboard." : "Copy to clipboard unavailable.",
|
||||
"Next:",
|
||||
`- Chrome → chrome://extensions → enable “Developer mode”`,
|
||||
`- “Load unpacked” → select: ${installed.path}`,
|
||||
`- “Load unpacked” → select: ${displayPath}`,
|
||||
`- Pin “Clawdbot Browser Relay”, then click it on the tab (badge shows ON)`,
|
||||
"",
|
||||
`${theme.muted("Docs:")} ${formatDocsLink("/tools/chrome-extension", "docs.clawd.bot/tools/chrome-extension")}`,
|
||||
@@ -115,7 +117,8 @@ export function registerBrowserExtensionCommands(
|
||||
defaultRuntime.log(JSON.stringify({ path: dir }, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(dir);
|
||||
const displayPath = shortenHomePath(dir);
|
||||
defaultRuntime.log(displayPath);
|
||||
const copied = await copyToClipboard(dir).catch(() => false);
|
||||
if (copied) defaultRuntime.error(info("Copied to clipboard."));
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import { browserScreenshotAction } from "../browser/client-actions.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import { danger } from "../globals.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import type { BrowserParentOpts } from "./browser-cli-shared.js";
|
||||
|
||||
export function registerBrowserInspectCommands(
|
||||
@@ -36,7 +37,7 @@ export function registerBrowserInspectCommands(
|
||||
defaultRuntime.log(JSON.stringify(result, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`MEDIA:${result.path}`);
|
||||
defaultRuntime.log(`MEDIA:${shortenHomePath(result.path)}`);
|
||||
} catch (err) {
|
||||
defaultRuntime.error(danger(String(err)));
|
||||
defaultRuntime.exit(1);
|
||||
@@ -106,9 +107,9 @@ export function registerBrowserInspectCommands(
|
||||
),
|
||||
);
|
||||
} else {
|
||||
defaultRuntime.log(opts.out);
|
||||
defaultRuntime.log(shortenHomePath(opts.out));
|
||||
if (result.format === "ai" && result.imagePath) {
|
||||
defaultRuntime.log(`MEDIA:${result.imagePath}`);
|
||||
defaultRuntime.log(`MEDIA:${shortenHomePath(result.imagePath)}`);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -122,7 +123,7 @@ export function registerBrowserInspectCommands(
|
||||
if (result.format === "ai") {
|
||||
defaultRuntime.log(result.snapshot);
|
||||
if (result.imagePath) {
|
||||
defaultRuntime.log(`MEDIA:${result.imagePath}`);
|
||||
defaultRuntime.log(`MEDIA:${shortenHomePath(result.imagePath)}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import { browserAct } from "../browser/client-actions-core.js";
|
||||
import { danger, info } from "../globals.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import type { BrowserParentOpts } from "./browser-cli-shared.js";
|
||||
import { runCommandWithRuntime } from "./cli-utils.js";
|
||||
|
||||
@@ -46,6 +47,8 @@ export function registerBrowserManageCommands(
|
||||
defaultRuntime.log(JSON.stringify(status, null, 2));
|
||||
return;
|
||||
}
|
||||
const detectedPath = status.detectedExecutablePath ?? status.executablePath;
|
||||
const detectedDisplay = detectedPath ? shortenHomePath(detectedPath) : "auto";
|
||||
defaultRuntime.log(
|
||||
[
|
||||
`profile: ${status.profile ?? "clawd"}`,
|
||||
@@ -56,7 +59,7 @@ export function registerBrowserManageCommands(
|
||||
`cdpUrl: ${status.cdpUrl ?? `http://127.0.0.1:${status.cdpPort}`}`,
|
||||
`browser: ${status.chosenBrowser ?? "unknown"}`,
|
||||
`detectedBrowser: ${status.detectedBrowser ?? "unknown"}`,
|
||||
`detectedPath: ${status.detectedExecutablePath ?? status.executablePath ?? "auto"}`,
|
||||
`detectedPath: ${detectedDisplay}`,
|
||||
`profileColor: ${status.color}`,
|
||||
...(status.detectError ? [`detectError: ${status.detectError}`] : []),
|
||||
].join("\n"),
|
||||
|
||||
@@ -7,6 +7,7 @@ import { defaultRuntime } from "../runtime.js";
|
||||
import { formatDocsLink } from "../terminal/links.js";
|
||||
import { formatCliCommand } from "./command-format.js";
|
||||
import { theme } from "../terminal/theme.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
|
||||
type PathSegment = string;
|
||||
|
||||
@@ -168,7 +169,7 @@ function unsetAtPath(root: Record<string, unknown>, path: PathSegment[]): boolea
|
||||
async function loadValidConfig() {
|
||||
const snapshot = await readConfigFileSnapshot();
|
||||
if (snapshot.valid) return snapshot;
|
||||
defaultRuntime.error(`Config invalid at ${snapshot.path}.`);
|
||||
defaultRuntime.error(`Config invalid at ${shortenHomePath(snapshot.path)}.`);
|
||||
for (const issue of snapshot.issues) {
|
||||
defaultRuntime.error(`- ${issue.path || "<root>"}: ${issue.message}`);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { isWSLEnv } from "../../infra/wsl.js";
|
||||
import { getResolvedLoggerSettings } from "../../logging.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { colorize, isRich, theme } from "../../terminal/theme.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
import { formatCliCommand } from "../command-format.js";
|
||||
import {
|
||||
filterDaemonEnv,
|
||||
@@ -66,7 +67,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
defaultRuntime.log(`${label("Service:")} ${accent(service.label)} (${serviceStatus})`);
|
||||
try {
|
||||
const logFile = getResolvedLoggerSettings().file;
|
||||
defaultRuntime.log(`${label("File logs:")} ${infoText(logFile)}`);
|
||||
defaultRuntime.log(`${label("File logs:")} ${infoText(shortenHomePath(logFile))}`);
|
||||
} catch {
|
||||
// ignore missing config/log resolution
|
||||
}
|
||||
@@ -76,10 +77,14 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
);
|
||||
}
|
||||
if (service.command?.sourcePath) {
|
||||
defaultRuntime.log(`${label("Service file:")} ${infoText(service.command.sourcePath)}`);
|
||||
defaultRuntime.log(
|
||||
`${label("Service file:")} ${infoText(shortenHomePath(service.command.sourcePath))}`,
|
||||
);
|
||||
}
|
||||
if (service.command?.workingDirectory) {
|
||||
defaultRuntime.log(`${label("Working dir:")} ${infoText(service.command.workingDirectory)}`);
|
||||
defaultRuntime.log(
|
||||
`${label("Working dir:")} ${infoText(shortenHomePath(service.command.workingDirectory))}`,
|
||||
);
|
||||
}
|
||||
const daemonEnvLines = safeDaemonEnv(service.command?.environment);
|
||||
if (daemonEnvLines.length > 0) {
|
||||
@@ -101,7 +106,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
}
|
||||
|
||||
if (status.config) {
|
||||
const cliCfg = `${status.config.cli.path}${status.config.cli.exists ? "" : " (missing)"}${status.config.cli.valid ? "" : " (invalid)"}`;
|
||||
const cliCfg = `${shortenHomePath(status.config.cli.path)}${status.config.cli.exists ? "" : " (missing)"}${status.config.cli.valid ? "" : " (invalid)"}`;
|
||||
defaultRuntime.log(`${label("Config (cli):")} ${infoText(cliCfg)}`);
|
||||
if (!status.config.cli.valid && status.config.cli.issues?.length) {
|
||||
for (const issue of status.config.cli.issues.slice(0, 5)) {
|
||||
@@ -111,7 +116,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
}
|
||||
}
|
||||
if (status.config.daemon) {
|
||||
const daemonCfg = `${status.config.daemon.path}${status.config.daemon.exists ? "" : " (missing)"}${status.config.daemon.valid ? "" : " (invalid)"}`;
|
||||
const daemonCfg = `${shortenHomePath(status.config.daemon.path)}${status.config.daemon.exists ? "" : " (missing)"}${status.config.daemon.valid ? "" : " (invalid)"}`;
|
||||
defaultRuntime.log(`${label("Config (service):")} ${infoText(daemonCfg)}`);
|
||||
if (!status.config.daemon.valid && status.config.daemon.issues?.length) {
|
||||
for (const issue of status.config.daemon.issues.slice(0, 5)) {
|
||||
@@ -276,8 +281,8 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
const logs = resolveGatewayLogPaths(
|
||||
(service.command?.environment ?? process.env) as NodeJS.ProcessEnv,
|
||||
);
|
||||
defaultRuntime.error(`${errorText("Logs:")} ${logs.stdoutPath}`);
|
||||
defaultRuntime.error(`${errorText("Errors:")} ${logs.stderrPath}`);
|
||||
defaultRuntime.error(`${errorText("Logs:")} ${shortenHomePath(logs.stdoutPath)}`);
|
||||
defaultRuntime.error(`${errorText("Errors:")} ${shortenHomePath(logs.stderrPath)}`);
|
||||
}
|
||||
spacer();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { resolveDefaultAgentWorkspaceDir } from "../../agents/workspace.js";
|
||||
import { handleReset } from "../../commands/onboard-helpers.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, writeConfigFile } from "../../config/config.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { resolveUserPath } from "../../utils.js";
|
||||
import { resolveUserPath, shortenHomePath } from "../../utils.js";
|
||||
|
||||
const DEV_IDENTITY_NAME = "C3-PO";
|
||||
const DEV_IDENTITY_THEME = "protocol droid";
|
||||
@@ -117,6 +117,6 @@ export async function ensureDevGatewayConfig(opts: { reset?: boolean }) {
|
||||
},
|
||||
});
|
||||
await ensureDevWorkspace(workspace);
|
||||
defaultRuntime.log(`Dev config ready: ${CONFIG_PATH_CLAWDBOT}`);
|
||||
defaultRuntime.log(`Dev workspace ready: ${resolveUserPath(workspace)}`);
|
||||
defaultRuntime.log(`Dev config ready: ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
defaultRuntime.log(`Dev workspace ready: ${shortenHomePath(resolveUserPath(workspace))}`);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import { formatDocsLink } from "../terminal/links.js";
|
||||
import { renderTable } from "../terminal/table.js";
|
||||
import { theme } from "../terminal/theme.js";
|
||||
import { formatCliCommand } from "./command-format.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveUserPath, shortenHomePath } from "../utils.js";
|
||||
|
||||
export type HooksListOptions = {
|
||||
json?: boolean;
|
||||
@@ -224,8 +224,8 @@ export function formatHookInfo(
|
||||
} else {
|
||||
lines.push(`${theme.muted(" Source:")} ${hook.source}`);
|
||||
}
|
||||
lines.push(`${theme.muted(" Path:")} ${hook.filePath}`);
|
||||
lines.push(`${theme.muted(" Handler:")} ${hook.handlerPath}`);
|
||||
lines.push(`${theme.muted(" Path:")} ${shortenHomePath(hook.filePath)}`);
|
||||
lines.push(`${theme.muted(" Handler:")} ${shortenHomePath(hook.handlerPath)}`);
|
||||
if (hook.homepage) {
|
||||
lines.push(`${theme.muted(" Homepage:")} ${hook.homepage}`);
|
||||
}
|
||||
@@ -577,7 +577,7 @@ export function registerHooksCli(program: Command): void {
|
||||
});
|
||||
|
||||
await writeConfigFile(next);
|
||||
defaultRuntime.log(`Linked hook path: ${resolved}`);
|
||||
defaultRuntime.log(`Linked hook path: ${shortenHomePath(resolved)}`);
|
||||
defaultRuntime.log(`Restart the gateway to load hooks.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { defaultRuntime } from "../runtime.js";
|
||||
import { formatDocsLink } from "../terminal/links.js";
|
||||
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import { shortenHomeInString, shortenHomePath } from "../utils.js";
|
||||
|
||||
type MemoryCommandOptions = {
|
||||
agent?: string;
|
||||
@@ -44,11 +45,15 @@ type MemorySourceScan = {
|
||||
|
||||
function formatSourceLabel(source: string, workspaceDir: string, agentId: string): string {
|
||||
if (source === "memory") {
|
||||
return `memory (MEMORY.md + ${path.join(workspaceDir, "memory")}${path.sep}*.md)`;
|
||||
return shortenHomeInString(
|
||||
`memory (MEMORY.md + ${path.join(workspaceDir, "memory")}${path.sep}*.md)`,
|
||||
);
|
||||
}
|
||||
if (source === "sessions") {
|
||||
const stateDir = resolveStateDir(process.env, os.homedir);
|
||||
return `sessions (${path.join(stateDir, "agents", agentId, "sessions")}${path.sep}*.jsonl)`;
|
||||
return shortenHomeInString(
|
||||
`sessions (${path.join(stateDir, "agents", agentId, "sessions")}${path.sep}*.jsonl)`,
|
||||
);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
@@ -76,7 +81,10 @@ async function checkReadableFile(pathname: string): Promise<{ exists: boolean; i
|
||||
} catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException).code;
|
||||
if (code === "ENOENT") return { exists: false };
|
||||
return { exists: true, issue: `${pathname} not readable (${code ?? "error"})` };
|
||||
return {
|
||||
exists: true,
|
||||
issue: `${shortenHomePath(pathname)} not readable (${code ?? "error"})`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,10 +100,12 @@ async function scanSessionFiles(agentId: string): Promise<SourceScan> {
|
||||
} catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException).code;
|
||||
if (code === "ENOENT") {
|
||||
issues.push(`sessions directory missing (${sessionsDir})`);
|
||||
issues.push(`sessions directory missing (${shortenHomePath(sessionsDir)})`);
|
||||
return { source: "sessions", totalFiles: 0, issues };
|
||||
}
|
||||
issues.push(`sessions directory not accessible (${sessionsDir}): ${code ?? "error"}`);
|
||||
issues.push(
|
||||
`sessions directory not accessible (${shortenHomePath(sessionsDir)}): ${code ?? "error"}`,
|
||||
);
|
||||
return { source: "sessions", totalFiles: null, issues };
|
||||
}
|
||||
}
|
||||
@@ -118,10 +128,12 @@ async function scanMemoryFiles(workspaceDir: string): Promise<SourceScan> {
|
||||
} catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException).code;
|
||||
if (code === "ENOENT") {
|
||||
issues.push(`memory directory missing (${memoryDir})`);
|
||||
issues.push(`memory directory missing (${shortenHomePath(memoryDir)})`);
|
||||
dirReadable = false;
|
||||
} else {
|
||||
issues.push(`memory directory not accessible (${memoryDir}): ${code ?? "error"}`);
|
||||
issues.push(
|
||||
`memory directory not accessible (${shortenHomePath(memoryDir)}): ${code ?? "error"}`,
|
||||
);
|
||||
dirReadable = null;
|
||||
}
|
||||
}
|
||||
@@ -134,7 +146,9 @@ async function scanMemoryFiles(workspaceDir: string): Promise<SourceScan> {
|
||||
} catch (err) {
|
||||
const code = (err as NodeJS.ErrnoException).code;
|
||||
if (dirReadable !== null) {
|
||||
issues.push(`memory directory scan failed (${memoryDir}): ${code ?? "error"}`);
|
||||
issues.push(
|
||||
`memory directory scan failed (${shortenHomePath(memoryDir)}): ${code ?? "error"}`,
|
||||
);
|
||||
dirReadable = null;
|
||||
}
|
||||
}
|
||||
@@ -152,7 +166,7 @@ async function scanMemoryFiles(workspaceDir: string): Promise<SourceScan> {
|
||||
}
|
||||
|
||||
if ((totalFiles ?? 0) === 0 && issues.length === 0) {
|
||||
issues.push(`no memory files found in ${workspaceDir}`);
|
||||
issues.push(`no memory files found in ${shortenHomePath(workspaceDir)}`);
|
||||
}
|
||||
|
||||
return { source: "memory", totalFiles, issues };
|
||||
@@ -294,8 +308,8 @@ export async function runMemoryStatus(opts: MemoryCommandOptions) {
|
||||
status.sources?.length ? `${label("Sources")} ${info(status.sources.join(", "))}` : null,
|
||||
`${label("Indexed")} ${success(indexedLabel)}`,
|
||||
`${label("Dirty")} ${status.dirty ? warn("yes") : muted("no")}`,
|
||||
`${label("Store")} ${info(status.dbPath)}`,
|
||||
`${label("Workspace")} ${info(status.workspaceDir)}`,
|
||||
`${label("Store")} ${info(shortenHomePath(status.dbPath))}`,
|
||||
`${label("Workspace")} ${info(shortenHomePath(status.workspaceDir))}`,
|
||||
].filter(Boolean) as string[];
|
||||
if (embeddingProbe) {
|
||||
const state = embeddingProbe.ok ? "ready" : "unavailable";
|
||||
@@ -340,7 +354,7 @@ export async function runMemoryStatus(opts: MemoryCommandOptions) {
|
||||
lines.push(`${label("Vector dims")} ${info(String(status.vector.dims))}`);
|
||||
}
|
||||
if (status.vector.extensionPath) {
|
||||
lines.push(`${label("Vector path")} ${info(status.vector.extensionPath)}`);
|
||||
lines.push(`${label("Vector path")} ${info(shortenHomePath(status.vector.extensionPath))}`);
|
||||
}
|
||||
if (status.vector.loadError) {
|
||||
lines.push(`${label("Vector error")} ${warn(status.vector.loadError)}`);
|
||||
@@ -594,7 +608,7 @@ export function registerMemoryCli(program: Command) {
|
||||
`${colorize(rich, theme.success, result.score.toFixed(3))} ${colorize(
|
||||
rich,
|
||||
theme.accent,
|
||||
`${result.path}:${result.startLine}-${result.endLine}`,
|
||||
`${shortenHomePath(result.path)}:${result.startLine}-${result.endLine}`,
|
||||
)}`,
|
||||
);
|
||||
lines.push(colorize(rich, theme.muted, result.snippet));
|
||||
|
||||
@@ -13,6 +13,7 @@ import { getNodesTheme, runNodesCommand } from "./cli-utils.js";
|
||||
import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js";
|
||||
import type { NodesRpcOpts } from "./types.js";
|
||||
import { renderTable } from "../../terminal/table.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
const parseFacing = (value: string): CameraFacing => {
|
||||
const v = String(value ?? "")
|
||||
@@ -165,7 +166,7 @@ export function registerNodesCameraCommands(nodes: Command) {
|
||||
defaultRuntime.log(JSON.stringify({ files: results }, null, 2));
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(results.map((r) => `MEDIA:${r.path}`).join("\n"));
|
||||
defaultRuntime.log(results.map((r) => `MEDIA:${shortenHomePath(r.path)}`).join("\n"));
|
||||
});
|
||||
}),
|
||||
{ timeoutMs: 60_000 },
|
||||
@@ -239,7 +240,7 @@ export function registerNodesCameraCommands(nodes: Command) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`MEDIA:${filePath}`);
|
||||
defaultRuntime.log(`MEDIA:${shortenHomePath(filePath)}`);
|
||||
});
|
||||
}),
|
||||
{ timeoutMs: 90_000 },
|
||||
|
||||
@@ -9,6 +9,7 @@ import { buildA2UITextJsonl, validateA2UIJsonl } from "./a2ui-jsonl.js";
|
||||
import { getNodesTheme, runNodesCommand } from "./cli-utils.js";
|
||||
import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js";
|
||||
import type { NodesRpcOpts } from "./types.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
async function invokeCanvas(opts: NodesRpcOpts, command: string, params?: Record<string, unknown>) {
|
||||
const nodeId = await resolveNodeId(opts, String(opts.node ?? ""));
|
||||
@@ -85,7 +86,7 @@ export function registerNodesCanvasCommands(nodes: Command) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`MEDIA:${filePath}`);
|
||||
defaultRuntime.log(`MEDIA:${shortenHomePath(filePath)}`);
|
||||
});
|
||||
}),
|
||||
{ timeoutMs: 60_000 },
|
||||
|
||||
@@ -10,6 +10,7 @@ import { parseDurationMs } from "../parse-duration.js";
|
||||
import { runNodesCommand } from "./cli-utils.js";
|
||||
import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js";
|
||||
import type { NodesRpcOpts } from "./types.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
export function registerNodesScreenCommands(nodes: Command) {
|
||||
const screen = nodes
|
||||
@@ -77,7 +78,7 @@ export function registerNodesScreenCommands(nodes: Command) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
defaultRuntime.log(`MEDIA:${written.path}`);
|
||||
defaultRuntime.log(`MEDIA:${shortenHomePath(written.path)}`);
|
||||
});
|
||||
}),
|
||||
{ timeoutMs: 180_000 },
|
||||
|
||||
@@ -6,6 +6,7 @@ import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js";
|
||||
import type { NodesRpcOpts } from "./types.js";
|
||||
import { renderTable } from "../../terminal/table.js";
|
||||
import { parseDurationMs } from "../parse-duration.js";
|
||||
import { shortenHomeInString } from "../../utils.js";
|
||||
|
||||
function formatVersionLabel(raw: string) {
|
||||
const trimmed = raw.trim();
|
||||
@@ -49,8 +50,9 @@ function formatPathEnv(raw?: string): string | null {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return null;
|
||||
const parts = trimmed.split(":").filter(Boolean);
|
||||
if (parts.length <= 3) return trimmed;
|
||||
return `${parts.slice(0, 2).join(":")}:…:${parts.slice(-1)[0]}`;
|
||||
const display =
|
||||
parts.length <= 3 ? trimmed : `${parts.slice(0, 2).join(":")}:…:${parts.slice(-1)[0]}`;
|
||||
return shortenHomeInString(display);
|
||||
}
|
||||
|
||||
function parseSinceMs(raw: unknown, label: string): number | undefined {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { defaultRuntime } from "../runtime.js";
|
||||
import { formatDocsLink } from "../terminal/links.js";
|
||||
import { renderTable } from "../terminal/table.js";
|
||||
import { theme } from "../terminal/theme.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveUserPath, shortenHomeInString, shortenHomePath } from "../utils.js";
|
||||
|
||||
export type PluginsListOptions = {
|
||||
json?: boolean;
|
||||
@@ -55,7 +55,7 @@ function formatPluginLine(plugin: PluginRecord, verbose = false): string {
|
||||
|
||||
const parts = [
|
||||
`${name}${idSuffix} ${status}`,
|
||||
` source: ${theme.muted(plugin.source)}`,
|
||||
` source: ${theme.muted(shortenHomeInString(plugin.source))}`,
|
||||
` origin: ${plugin.origin}`,
|
||||
];
|
||||
if (plugin.version) parts.push(` version: ${plugin.version}`);
|
||||
@@ -201,7 +201,7 @@ export function registerPluginsCli(program: Command) {
|
||||
if (plugin.description) lines.push(plugin.description);
|
||||
lines.push("");
|
||||
lines.push(`${theme.muted("Status:")} ${plugin.status}`);
|
||||
lines.push(`${theme.muted("Source:")} ${plugin.source}`);
|
||||
lines.push(`${theme.muted("Source:")} ${shortenHomeInString(plugin.source)}`);
|
||||
lines.push(`${theme.muted("Origin:")} ${plugin.origin}`);
|
||||
if (plugin.version) lines.push(`${theme.muted("Version:")} ${plugin.version}`);
|
||||
if (plugin.toolNames.length > 0) {
|
||||
@@ -227,9 +227,10 @@ export function registerPluginsCli(program: Command) {
|
||||
lines.push("");
|
||||
lines.push(`${theme.muted("Install:")} ${install.source}`);
|
||||
if (install.spec) lines.push(`${theme.muted("Spec:")} ${install.spec}`);
|
||||
if (install.sourcePath) lines.push(`${theme.muted("Source path:")} ${install.sourcePath}`);
|
||||
if (install.sourcePath)
|
||||
lines.push(`${theme.muted("Source path:")} ${shortenHomePath(install.sourcePath)}`);
|
||||
if (install.installPath)
|
||||
lines.push(`${theme.muted("Install path:")} ${install.installPath}`);
|
||||
lines.push(`${theme.muted("Install path:")} ${shortenHomePath(install.installPath)}`);
|
||||
if (install.version) lines.push(`${theme.muted("Recorded version:")} ${install.version}`);
|
||||
if (install.installedAt)
|
||||
lines.push(`${theme.muted("Installed at:")} ${install.installedAt}`);
|
||||
@@ -333,7 +334,7 @@ export function registerPluginsCli(program: Command) {
|
||||
next = slotResult.config;
|
||||
await writeConfigFile(next);
|
||||
logSlotWarnings(slotResult.warnings);
|
||||
defaultRuntime.log(`Linked plugin path: ${resolved}`);
|
||||
defaultRuntime.log(`Linked plugin path: ${shortenHomePath(resolved)}`);
|
||||
defaultRuntime.log(`Restart the gateway to load plugins.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { loadAndMaybeMigrateDoctorConfig } from "../../commands/doctor-config-fl
|
||||
import { colorize, isRich, theme } from "../../terminal/theme.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { formatCliCommand } from "../command-format.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
const ALLOWED_INVALID_COMMANDS = new Set(["doctor", "logs", "health", "help", "status"]);
|
||||
const ALLOWED_INVALID_GATEWAY_SUBCOMMANDS = new Set([
|
||||
@@ -60,7 +61,7 @@ export async function ensureConfigReady(params: {
|
||||
const commandText = (value: string) => colorize(rich, theme.command, value);
|
||||
|
||||
params.runtime.error(heading("Config invalid"));
|
||||
params.runtime.error(`${muted("File:")} ${muted(snapshot.path)}`);
|
||||
params.runtime.error(`${muted("File:")} ${muted(shortenHomePath(snapshot.path))}`);
|
||||
if (issues.length > 0) {
|
||||
params.runtime.error(muted("Problem:"));
|
||||
params.runtime.error(issues.map((issue) => ` ${error(issue)}`).join("\n"));
|
||||
|
||||
@@ -6,6 +6,7 @@ import { runSecurityAudit } from "../security/audit.js";
|
||||
import { fixSecurityFootguns } from "../security/fix.js";
|
||||
import { formatDocsLink } from "../terminal/links.js";
|
||||
import { isRich, theme } from "../terminal/theme.js";
|
||||
import { shortenHomeInString, shortenHomePath } from "../utils.js";
|
||||
import { formatCliCommand } from "./command-format.js";
|
||||
|
||||
type SecurityAuditOptions = {
|
||||
@@ -83,18 +84,24 @@ export function registerSecurityCli(program: Command) {
|
||||
lines.push("");
|
||||
lines.push(heading("FIX"));
|
||||
for (const change of fixResult.changes) {
|
||||
lines.push(muted(` ${change}`));
|
||||
lines.push(muted(` ${shortenHomeInString(change)}`));
|
||||
}
|
||||
for (const action of fixResult.actions) {
|
||||
const mode = action.mode.toString(8).padStart(3, "0");
|
||||
if (action.ok) lines.push(muted(` chmod ${mode} ${action.path}`));
|
||||
if (action.ok) lines.push(muted(` chmod ${mode} ${shortenHomePath(action.path)}`));
|
||||
else if (action.skipped)
|
||||
lines.push(muted(` skip chmod ${mode} ${action.path} (${action.skipped})`));
|
||||
lines.push(
|
||||
muted(` skip chmod ${mode} ${shortenHomePath(action.path)} (${action.skipped})`),
|
||||
);
|
||||
else if (action.error)
|
||||
lines.push(muted(` chmod ${mode} ${action.path} failed: ${action.error}`));
|
||||
lines.push(
|
||||
muted(` chmod ${mode} ${shortenHomePath(action.path)} failed: ${action.error}`),
|
||||
);
|
||||
}
|
||||
if (fixResult.errors.length > 0) {
|
||||
for (const err of fixResult.errors) lines.push(muted(` error: ${err}`));
|
||||
for (const err of fixResult.errors) {
|
||||
lines.push(muted(` error: ${shortenHomeInString(err)}`));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { defaultRuntime } from "../runtime.js";
|
||||
import { formatDocsLink } from "../terminal/links.js";
|
||||
import { renderTable } from "../terminal/table.js";
|
||||
import { theme } from "../terminal/theme.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import { formatCliCommand } from "./command-format.js";
|
||||
|
||||
export type SkillsListOptions = {
|
||||
@@ -176,7 +177,7 @@ export function formatSkillInfo(
|
||||
// Details
|
||||
lines.push(theme.heading("Details:"));
|
||||
lines.push(`${theme.muted(" Source:")} ${skill.source}`);
|
||||
lines.push(`${theme.muted(" Path:")} ${skill.filePath}`);
|
||||
lines.push(`${theme.muted(" Path:")} ${shortenHomePath(skill.filePath)}`);
|
||||
if (skill.homepage) {
|
||||
lines.push(`${theme.muted(" Homepage:")} ${skill.homepage}`);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { CONFIG_PATH_CLAWDBOT, writeConfigFile } from "../config/config.js";
|
||||
import { DEFAULT_AGENT_ID, normalizeAgentId } from "../routing/session-key.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveUserPath, shortenHomePath } from "../utils.js";
|
||||
import { createClackPrompter } from "../wizard/clack-prompter.js";
|
||||
import { WizardCancelledError } from "../wizard/prompts.js";
|
||||
import {
|
||||
@@ -126,7 +126,7 @@ export async function agentsAddCommand(
|
||||
: { config: nextConfig, added: [], skipped: [], conflicts: [] };
|
||||
|
||||
await writeConfigFile(bindingResult.config);
|
||||
if (!opts.json) runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
if (!opts.json) runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
const quietRuntime = opts.json ? createQuietRuntime(runtime) : runtime;
|
||||
await ensureWorkspaceAndSessions(workspaceDir, quietRuntime, {
|
||||
skipBootstrap: Boolean(bindingResult.config.agents?.defaults?.skipBootstrap),
|
||||
@@ -151,8 +151,8 @@ export async function agentsAddCommand(
|
||||
runtime.log(JSON.stringify(payload, null, 2));
|
||||
} else {
|
||||
runtime.log(`Agent: ${agentId}`);
|
||||
runtime.log(`Workspace: ${workspaceDir}`);
|
||||
runtime.log(`Agent dir: ${agentDir}`);
|
||||
runtime.log(`Workspace: ${shortenHomePath(workspaceDir)}`);
|
||||
runtime.log(`Agent dir: ${shortenHomePath(agentDir)}`);
|
||||
if (model) runtime.log(`Model: ${model}`);
|
||||
if (bindingResult.conflicts.length > 0) {
|
||||
runtime.error(
|
||||
@@ -334,7 +334,7 @@ export async function agentsAddCommand(
|
||||
}
|
||||
|
||||
await writeConfigFile(nextConfig);
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
await ensureWorkspaceAndSessions(workspaceDir, runtime, {
|
||||
skipBootstrap: Boolean(nextConfig.agents?.defaults?.skipBootstrap),
|
||||
agentId,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { resolveSessionTranscriptsDirForAgent } from "../config/sessions.js";
|
||||
import { DEFAULT_AGENT_ID, normalizeAgentId } from "../routing/session-key.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import { createClackPrompter } from "../wizard/clack-prompter.js";
|
||||
|
||||
import { createQuietRuntime, requireValidConfig } from "./agents.command-shared.js";
|
||||
@@ -69,7 +70,7 @@ export async function agentsDeleteCommand(
|
||||
|
||||
const result = pruneAgentConfig(cfg, agentId);
|
||||
await writeConfigFile(result.config);
|
||||
if (!opts.json) runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
if (!opts.json) runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
|
||||
const quietRuntime = opts.json ? createQuietRuntime(runtime) : runtime;
|
||||
await moveToTrash(workspaceDir, quietRuntime);
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { IdentityConfig } from "../config/types.js";
|
||||
import { normalizeAgentId } from "../routing/session-key.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveUserPath, shortenHomePath } from "../utils.js";
|
||||
import { requireValidConfig } from "./agents.command-shared.js";
|
||||
import {
|
||||
type AgentIdentity,
|
||||
@@ -105,14 +105,14 @@ export async function agentsSetIdentityCommand(
|
||||
const matches = resolveAgentIdByWorkspace(cfg, workspaceDir);
|
||||
if (matches.length === 0) {
|
||||
runtime.error(
|
||||
`No agent workspace matches ${workspaceDir}. Pass --agent to target a specific agent.`,
|
||||
`No agent workspace matches ${shortenHomePath(workspaceDir)}. Pass --agent to target a specific agent.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
if (matches.length > 1) {
|
||||
runtime.error(
|
||||
`Multiple agents match ${workspaceDir}: ${matches.join(", ")}. Pass --agent to choose one.`,
|
||||
`Multiple agents match ${shortenHomePath(workspaceDir)}: ${matches.join(", ")}. Pass --agent to choose one.`,
|
||||
);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
@@ -131,7 +131,7 @@ export async function agentsSetIdentityCommand(
|
||||
const targetPath =
|
||||
identityFilePath ??
|
||||
(workspaceDir ? path.join(workspaceDir, DEFAULT_IDENTITY_FILENAME) : "IDENTITY.md");
|
||||
runtime.error(`No identity data found in ${targetPath}.`);
|
||||
runtime.error(`No identity data found in ${shortenHomePath(targetPath)}.`);
|
||||
runtime.exit(1);
|
||||
return;
|
||||
}
|
||||
@@ -211,11 +211,11 @@ export async function agentsSetIdentityCommand(
|
||||
return;
|
||||
}
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Agent: ${agentId}`);
|
||||
if (nextIdentity.name) runtime.log(`Name: ${nextIdentity.name}`);
|
||||
if (nextIdentity.theme) runtime.log(`Theme: ${nextIdentity.theme}`);
|
||||
if (nextIdentity.emoji) runtime.log(`Emoji: ${nextIdentity.emoji}`);
|
||||
if (nextIdentity.avatar) runtime.log(`Avatar: ${nextIdentity.avatar}`);
|
||||
if (workspaceDir) runtime.log(`Workspace: ${workspaceDir}`);
|
||||
if (workspaceDir) runtime.log(`Workspace: ${shortenHomePath(workspaceDir)}`);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { normalizeAgentId } from "../routing/session-key.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import { describeBinding } from "./agents.bindings.js";
|
||||
import { requireValidConfig } from "./agents.command-shared.js";
|
||||
import type { AgentSummary } from "./agents.config.js";
|
||||
@@ -40,8 +41,8 @@ function formatSummary(summary: AgentSummary) {
|
||||
if (identityLine) {
|
||||
lines.push(` Identity: ${identityLine}${identitySource ? ` (${identitySource})` : ""}`);
|
||||
}
|
||||
lines.push(` Workspace: ${summary.workspace}`);
|
||||
lines.push(` Agent dir: ${summary.agentDir}`);
|
||||
lines.push(` Workspace: ${shortenHomePath(summary.workspace)}`);
|
||||
lines.push(` Agent dir: ${shortenHomePath(summary.agentDir)}`);
|
||||
if (summary.model) lines.push(` Model: ${summary.model}`);
|
||||
lines.push(` Routing rules: ${summary.bindings}`);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import path from "node:path";
|
||||
import { resolveDefaultAgentWorkspaceDir } from "../agents/workspace.js";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { resolveHomeDir, resolveUserPath } from "../utils.js";
|
||||
import { resolveHomeDir, resolveUserPath, shortenHomeInString } from "../utils.js";
|
||||
|
||||
export type RemovalResult = {
|
||||
ok: boolean;
|
||||
@@ -53,20 +53,21 @@ export async function removePath(
|
||||
if (!target?.trim()) return { ok: false, skipped: true };
|
||||
const resolved = path.resolve(target);
|
||||
const label = opts?.label ?? resolved;
|
||||
const displayLabel = shortenHomeInString(label);
|
||||
if (isUnsafeRemovalTarget(resolved)) {
|
||||
runtime.error(`Refusing to remove unsafe path: ${label}`);
|
||||
runtime.error(`Refusing to remove unsafe path: ${displayLabel}`);
|
||||
return { ok: false };
|
||||
}
|
||||
if (opts?.dryRun) {
|
||||
runtime.log(`[dry-run] remove ${label}`);
|
||||
runtime.log(`[dry-run] remove ${displayLabel}`);
|
||||
return { ok: true, skipped: true };
|
||||
}
|
||||
try {
|
||||
await fs.rm(resolved, { recursive: true, force: true });
|
||||
runtime.log(`Removed ${label}`);
|
||||
runtime.log(`Removed ${displayLabel}`);
|
||||
return { ok: true };
|
||||
} catch (err) {
|
||||
runtime.error(`Failed to remove ${label}: ${String(err)}`);
|
||||
runtime.error(`Failed to remove ${displayLabel}: ${String(err)}`);
|
||||
return { ok: false };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { ClawdbotConfig } from "../config/config.js";
|
||||
import { CONFIG_PATH_CLAWDBOT } from "../config/config.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import { confirm, select } from "./configure.shared.js";
|
||||
import { guardCancel } from "./onboard-helpers.js";
|
||||
|
||||
@@ -51,7 +52,7 @@ export async function removeChannelConfigWizard(
|
||||
const label = getChannelPlugin(channel)?.meta.label ?? channel;
|
||||
const confirmed = guardCancel(
|
||||
await confirm({
|
||||
message: `Delete ${label} configuration from ${CONFIG_PATH_CLAWDBOT}?`,
|
||||
message: `Delete ${label} configuration from ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}?`,
|
||||
initialValue: false,
|
||||
}),
|
||||
runtime,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { ensureControlUiAssetsBuilt } from "../infra/control-ui-assets.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveUserPath, shortenHomePath } from "../utils.js";
|
||||
import { createClackPrompter } from "../wizard/clack-prompter.js";
|
||||
import { WizardCancelledError } from "../wizard/prompts.js";
|
||||
import { removeChannelConfigWizard } from "./configure.channels.js";
|
||||
@@ -253,7 +253,7 @@ export async function runConfigureWizard(
|
||||
mode,
|
||||
});
|
||||
await writeConfigFile(remoteConfig);
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
outro("Remote gateway configured.");
|
||||
return;
|
||||
}
|
||||
@@ -286,7 +286,7 @@ export async function runConfigureWizard(
|
||||
mode,
|
||||
});
|
||||
await writeConfigFile(nextConfig);
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
};
|
||||
|
||||
if (opts.sections) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { promisify } from "node:util";
|
||||
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
@@ -19,10 +20,11 @@ export async function noteMacLaunchAgentOverrides() {
|
||||
const hasMarker = fs.existsSync(markerPath);
|
||||
if (!hasMarker) return;
|
||||
|
||||
const displayMarkerPath = shortenHomePath(markerPath);
|
||||
const lines = [
|
||||
`- LaunchAgent writes are disabled via ${markerPath}.`,
|
||||
`- LaunchAgent writes are disabled via ${displayMarkerPath}.`,
|
||||
"- To restore default behavior:",
|
||||
` rm ${markerPath}`,
|
||||
` rm ${displayMarkerPath}`,
|
||||
].filter((line): line is string => Boolean(line));
|
||||
note(lines.join("\n"), "Gateway (macOS)");
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
resolveStorePath,
|
||||
} from "../config/sessions.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
|
||||
type DoctorPrompterLike = {
|
||||
confirmSkipInNonInteractive: (params: {
|
||||
@@ -131,11 +132,16 @@ export async function noteStateIntegrity(
|
||||
const sessionsDir = resolveSessionTranscriptsDirForAgent(agentId, env, homedir);
|
||||
const storePath = resolveStorePath(cfg.session?.store, { agentId });
|
||||
const storeDir = path.dirname(storePath);
|
||||
const displayStateDir = shortenHomePath(stateDir);
|
||||
const displayOauthDir = shortenHomePath(oauthDir);
|
||||
const displaySessionsDir = shortenHomePath(sessionsDir);
|
||||
const displayStoreDir = shortenHomePath(storeDir);
|
||||
const displayConfigPath = configPath ? shortenHomePath(configPath) : undefined;
|
||||
|
||||
let stateDirExists = existsDir(stateDir);
|
||||
if (!stateDirExists) {
|
||||
warnings.push(
|
||||
`- CRITICAL: state directory missing (${stateDir}). Sessions, credentials, logs, and config are stored there.`,
|
||||
`- CRITICAL: state directory missing (${displayStateDir}). Sessions, credentials, logs, and config are stored there.`,
|
||||
);
|
||||
if (cfg.gateway?.mode === "remote") {
|
||||
warnings.push(
|
||||
@@ -143,26 +149,26 @@ export async function noteStateIntegrity(
|
||||
);
|
||||
}
|
||||
const create = await prompter.confirmSkipInNonInteractive({
|
||||
message: `Create ${stateDir} now?`,
|
||||
message: `Create ${displayStateDir} now?`,
|
||||
initialValue: false,
|
||||
});
|
||||
if (create) {
|
||||
const created = ensureDir(stateDir);
|
||||
if (created.ok) {
|
||||
changes.push(`- Created ${stateDir}`);
|
||||
changes.push(`- Created ${displayStateDir}`);
|
||||
stateDirExists = true;
|
||||
} else {
|
||||
warnings.push(`- Failed to create ${stateDir}: ${created.error}`);
|
||||
warnings.push(`- Failed to create ${displayStateDir}: ${created.error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stateDirExists && !canWriteDir(stateDir)) {
|
||||
warnings.push(`- State directory not writable (${stateDir}).`);
|
||||
warnings.push(`- State directory not writable (${displayStateDir}).`);
|
||||
const hint = dirPermissionHint(stateDir);
|
||||
if (hint) warnings.push(` ${hint}`);
|
||||
const repair = await prompter.confirmSkipInNonInteractive({
|
||||
message: `Repair permissions on ${stateDir}?`,
|
||||
message: `Repair permissions on ${displayStateDir}?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (repair) {
|
||||
@@ -170,9 +176,9 @@ export async function noteStateIntegrity(
|
||||
const stat = fs.statSync(stateDir);
|
||||
const target = addUserRwx(stat.mode);
|
||||
fs.chmodSync(stateDir, target);
|
||||
changes.push(`- Repaired permissions on ${stateDir}`);
|
||||
changes.push(`- Repaired permissions on ${displayStateDir}`);
|
||||
} catch (err) {
|
||||
warnings.push(`- Failed to repair ${stateDir}: ${String(err)}`);
|
||||
warnings.push(`- Failed to repair ${displayStateDir}: ${String(err)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,19 +187,19 @@ export async function noteStateIntegrity(
|
||||
const stat = fs.statSync(stateDir);
|
||||
if ((stat.mode & 0o077) !== 0) {
|
||||
warnings.push(
|
||||
`- State directory permissions are too open (${stateDir}). Recommend chmod 700.`,
|
||||
`- State directory permissions are too open (${displayStateDir}). Recommend chmod 700.`,
|
||||
);
|
||||
const tighten = await prompter.confirmSkipInNonInteractive({
|
||||
message: `Tighten permissions on ${stateDir} to 700?`,
|
||||
message: `Tighten permissions on ${displayStateDir} to 700?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (tighten) {
|
||||
fs.chmodSync(stateDir, 0o700);
|
||||
changes.push(`- Tightened permissions on ${stateDir} to 700`);
|
||||
changes.push(`- Tightened permissions on ${displayStateDir} to 700`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
warnings.push(`- Failed to read ${stateDir} permissions: ${String(err)}`);
|
||||
warnings.push(`- Failed to read ${displayStateDir} permissions: ${String(err)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,19 +208,21 @@ export async function noteStateIntegrity(
|
||||
const stat = fs.statSync(configPath);
|
||||
if ((stat.mode & 0o077) !== 0) {
|
||||
warnings.push(
|
||||
`- Config file is group/world readable (${configPath}). Recommend chmod 600.`,
|
||||
`- Config file is group/world readable (${displayConfigPath ?? configPath}). Recommend chmod 600.`,
|
||||
);
|
||||
const tighten = await prompter.confirmSkipInNonInteractive({
|
||||
message: `Tighten permissions on ${configPath} to 600?`,
|
||||
message: `Tighten permissions on ${displayConfigPath ?? configPath} to 600?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (tighten) {
|
||||
fs.chmodSync(configPath, 0o600);
|
||||
changes.push(`- Tightened permissions on ${configPath} to 600`);
|
||||
changes.push(`- Tightened permissions on ${displayConfigPath ?? configPath} to 600`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
warnings.push(`- Failed to read config permissions (${configPath}): ${String(err)}`);
|
||||
warnings.push(
|
||||
`- Failed to read config permissions (${displayConfigPath ?? configPath}): ${String(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,26 +231,33 @@ export async function noteStateIntegrity(
|
||||
dirCandidates.set(sessionsDir, "Sessions dir");
|
||||
dirCandidates.set(storeDir, "Session store dir");
|
||||
dirCandidates.set(oauthDir, "OAuth dir");
|
||||
const displayDirFor = (dir: string) => {
|
||||
if (dir === sessionsDir) return displaySessionsDir;
|
||||
if (dir === storeDir) return displayStoreDir;
|
||||
if (dir === oauthDir) return displayOauthDir;
|
||||
return shortenHomePath(dir);
|
||||
};
|
||||
|
||||
for (const [dir, label] of dirCandidates) {
|
||||
const displayDir = displayDirFor(dir);
|
||||
if (!existsDir(dir)) {
|
||||
warnings.push(`- CRITICAL: ${label} missing (${dir}).`);
|
||||
warnings.push(`- CRITICAL: ${label} missing (${displayDir}).`);
|
||||
const create = await prompter.confirmSkipInNonInteractive({
|
||||
message: `Create ${label} at ${dir}?`,
|
||||
message: `Create ${label} at ${displayDir}?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (create) {
|
||||
const created = ensureDir(dir);
|
||||
if (created.ok) {
|
||||
changes.push(`- Created ${label}: ${dir}`);
|
||||
changes.push(`- Created ${label}: ${displayDir}`);
|
||||
} else {
|
||||
warnings.push(`- Failed to create ${dir}: ${created.error}`);
|
||||
warnings.push(`- Failed to create ${displayDir}: ${created.error}`);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!canWriteDir(dir)) {
|
||||
warnings.push(`- ${label} not writable (${dir}).`);
|
||||
warnings.push(`- ${label} not writable (${displayDir}).`);
|
||||
const hint = dirPermissionHint(dir);
|
||||
if (hint) warnings.push(` ${hint}`);
|
||||
const repair = await prompter.confirmSkipInNonInteractive({
|
||||
@@ -254,9 +269,9 @@ export async function noteStateIntegrity(
|
||||
const stat = fs.statSync(dir);
|
||||
const target = addUserRwx(stat.mode);
|
||||
fs.chmodSync(dir, target);
|
||||
changes.push(`- Repaired permissions on ${label}: ${dir}`);
|
||||
changes.push(`- Repaired permissions on ${label}: ${displayDir}`);
|
||||
} catch (err) {
|
||||
warnings.push(`- Failed to repair ${dir}: ${String(err)}`);
|
||||
warnings.push(`- Failed to repair ${displayDir}: ${String(err)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,8 +289,8 @@ export async function noteStateIntegrity(
|
||||
warnings.push(
|
||||
[
|
||||
"- Multiple state directories detected. This can split session history.",
|
||||
...Array.from(extraStateDirs).map((dir) => ` - ${dir}`),
|
||||
` Active state dir: ${stateDir}`,
|
||||
...Array.from(extraStateDirs).map((dir) => ` - ${shortenHomePath(dir)}`),
|
||||
` Active state dir: ${displayStateDir}`,
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
@@ -311,7 +326,7 @@ export async function noteStateIntegrity(
|
||||
const transcriptPath = resolveSessionFilePath(mainEntry.sessionId, mainEntry, { agentId });
|
||||
if (!existsFile(transcriptPath)) {
|
||||
warnings.push(
|
||||
`- Main session transcript missing (${transcriptPath}). History will appear to reset.`,
|
||||
`- Main session transcript missing (${shortenHomePath(transcriptPath)}). History will appear to reset.`,
|
||||
);
|
||||
} else {
|
||||
const lineCount = countJsonlLines(transcriptPath);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
DEFAULT_SOUL_FILENAME,
|
||||
DEFAULT_USER_FILENAME,
|
||||
} from "../agents/workspace.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
|
||||
export const MEMORY_SYSTEM_PROMPT = [
|
||||
"Memory system not found in workspace.",
|
||||
@@ -80,8 +81,8 @@ export function detectLegacyWorkspaceDirs(params: {
|
||||
export function formatLegacyWorkspaceWarning(detection: LegacyWorkspaceDetection): string {
|
||||
return [
|
||||
"Extra workspace directories detected (may contain old agent files):",
|
||||
...detection.legacyDirs.map((dir) => `- ${dir}`),
|
||||
`Active workspace: ${detection.activeWorkspace}`,
|
||||
...detection.legacyDirs.map((dir) => `- ${shortenHomePath(dir)}`),
|
||||
`Active workspace: ${shortenHomePath(detection.activeWorkspace)}`,
|
||||
"If unused, archive or move to Trash (e.g. trash ~/clawdbot).",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { stylePromptTitle } from "../terminal/prompt-style.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
import { maybeRepairAnthropicOAuthProfileId, noteAuthProfileHealth } from "./doctor-auth.js";
|
||||
import { loadAndMaybeMigrateDoctorConfig } from "./doctor-config-flow.js";
|
||||
import { maybeRepairGatewayDaemon } from "./doctor-gateway-daemon-flow.js";
|
||||
@@ -269,10 +270,10 @@ export async function doctorCommand(
|
||||
if (shouldWriteConfig) {
|
||||
cfg = applyWizardMetadata(cfg, { command: "doctor", mode: resolveMode(cfg) });
|
||||
await writeConfigFile(cfg);
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
const backupPath = `${CONFIG_PATH_CLAWDBOT}.bak`;
|
||||
if (fs.existsSync(backupPath)) {
|
||||
runtime.log(`Backup: ${backupPath}`);
|
||||
runtime.log(`Backup: ${shortenHomePath(backupPath)}`);
|
||||
}
|
||||
} else {
|
||||
runtime.log(`Run "${formatCliCommand("clawdbot doctor --fix")}" to apply changes.`);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CONFIG_PATH_CLAWDBOT, loadConfig } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
import {
|
||||
ensureFlagCompatibility,
|
||||
normalizeAlias,
|
||||
@@ -74,7 +75,7 @@ export async function modelsAliasesAddCommand(
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Alias ${alias} -> ${resolved.provider}/${resolved.model}`);
|
||||
}
|
||||
|
||||
@@ -105,7 +106,7 @@ export async function modelsAliasesRemoveCommand(aliasRaw: string, runtime: Runt
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
if (
|
||||
!updated.agents?.defaults?.models ||
|
||||
Object.values(updated.agents.defaults.models).every((entry) => !entry?.alias?.trim())
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
} from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { stylePromptHint, stylePromptMessage } from "../../terminal/prompt-style.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
import { applyAuthProfileConfig } from "../onboard-auth.js";
|
||||
import { isRemoteEnvironment } from "../oauth-env.js";
|
||||
import { openUrl } from "../onboard-helpers.js";
|
||||
@@ -117,7 +118,7 @@ export async function modelsAuthSetupTokenCommand(
|
||||
}),
|
||||
);
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Auth profile: ${CLAUDE_CLI_PROFILE_ID} (anthropic/oauth)`);
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ export async function modelsAuthPasteTokenCommand(
|
||||
|
||||
await updateConfig((cfg) => applyAuthProfileConfig(cfg, { profileId, provider, mode: "token" }));
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Auth profile: ${profileId} (${provider}/token)`);
|
||||
}
|
||||
|
||||
@@ -425,7 +426,7 @@ export async function modelsAuthLoginCommand(opts: LoginOptions, runtime: Runtim
|
||||
return next;
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
for (const profile of result.profiles) {
|
||||
runtime.log(
|
||||
`Auth profile: ${profile.profileId} (${profile.credential.provider}/${credentialMode(profile.credential)})`,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { buildModelAliasIndex, resolveModelRefFromString } from "../../agents/model-selection.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, loadConfig } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
import {
|
||||
DEFAULT_PROVIDER,
|
||||
ensureFlagCompatibility,
|
||||
@@ -78,7 +79,7 @@ export async function modelsFallbacksAddCommand(modelRaw: string, runtime: Runti
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Fallbacks: ${(updated.agents?.defaults?.model?.fallbacks ?? []).join(", ")}`);
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ export async function modelsFallbacksRemoveCommand(modelRaw: string, runtime: Ru
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Fallbacks: ${(updated.agents?.defaults?.model?.fallbacks ?? []).join(", ")}`);
|
||||
}
|
||||
|
||||
@@ -148,6 +149,6 @@ export async function modelsFallbacksClearCommand(runtime: RuntimeEnv) {
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log("Fallback list cleared.");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { buildModelAliasIndex, resolveModelRefFromString } from "../../agents/model-selection.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, loadConfig } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
import {
|
||||
DEFAULT_PROVIDER,
|
||||
ensureFlagCompatibility,
|
||||
@@ -78,7 +79,7 @@ export async function modelsImageFallbacksAddCommand(modelRaw: string, runtime:
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(
|
||||
`Image fallbacks: ${(updated.agents?.defaults?.imageModel?.fallbacks ?? []).join(", ")}`,
|
||||
);
|
||||
@@ -126,7 +127,7 @@ export async function modelsImageFallbacksRemoveCommand(modelRaw: string, runtim
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(
|
||||
`Image fallbacks: ${(updated.agents?.defaults?.imageModel?.fallbacks ?? []).join(", ")}`,
|
||||
);
|
||||
@@ -152,6 +153,6 @@ export async function modelsImageFallbacksClearCommand(runtime: RuntimeEnv) {
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log("Image fallback list cleared.");
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ export async function modelsStatusCommand(
|
||||
rawModel && rawModel !== resolvedLabel ? `${resolvedLabel} (from ${rawModel})` : resolvedLabel;
|
||||
|
||||
runtime.log(
|
||||
`${label("Config")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, CONFIG_PATH_CLAWDBOT)}`,
|
||||
`${label("Config")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(CONFIG_PATH_CLAWDBOT))}`,
|
||||
);
|
||||
runtime.log(
|
||||
`${label("Agent dir")}${colorize(rich, theme.muted, ":")} ${colorize(
|
||||
|
||||
@@ -4,6 +4,7 @@ import { type ModelScanResult, scanOpenRouterModels } from "../../agents/model-s
|
||||
import { withProgressTotals } from "../../cli/progress.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, loadConfig } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
import {
|
||||
stylePromptHint,
|
||||
stylePromptMessage,
|
||||
@@ -343,7 +344,7 @@ export async function modelsScanCommand(
|
||||
return;
|
||||
}
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Fallbacks: ${selected.join(", ")}`);
|
||||
if (selectedImages.length > 0) {
|
||||
runtime.log(`Image fallbacks: ${selectedImages.join(", ")}`);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CONFIG_PATH_CLAWDBOT } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { resolveModelTarget, updateConfig } from "./shared.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
export async function modelsSetImageCommand(modelRaw: string, runtime: RuntimeEnv) {
|
||||
const updated = await updateConfig((cfg) => {
|
||||
@@ -27,6 +28,6 @@ export async function modelsSetImageCommand(modelRaw: string, runtime: RuntimeEn
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Image model: ${updated.agents?.defaults?.imageModel?.primary ?? modelRaw}`);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CONFIG_PATH_CLAWDBOT } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { resolveModelTarget, updateConfig } from "./shared.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
export async function modelsSetCommand(modelRaw: string, runtime: RuntimeEnv) {
|
||||
const updated = await updateConfig((cfg) => {
|
||||
@@ -27,6 +28,6 @@ export async function modelsSetCommand(modelRaw: string, runtime: RuntimeEnv) {
|
||||
};
|
||||
});
|
||||
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
runtime.log(`Default model: ${updated.agents?.defaults?.model?.primary ?? modelRaw}`);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,13 @@ import { runCommandWithTimeout } from "../process/exec.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { stylePromptTitle } from "../terminal/prompt-style.js";
|
||||
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
|
||||
import { CONFIG_DIR, resolveUserPath, sleep } from "../utils.js";
|
||||
import {
|
||||
CONFIG_DIR,
|
||||
resolveUserPath,
|
||||
shortenHomeInString,
|
||||
shortenHomePath,
|
||||
sleep,
|
||||
} from "../utils.js";
|
||||
import { VERSION } from "../version.js";
|
||||
import type { NodeManagerChoice, OnboardMode, ResetScope } from "./onboard-types.js";
|
||||
|
||||
@@ -33,21 +39,21 @@ export function guardCancel<T>(value: T | symbol, runtime: RuntimeEnv): T {
|
||||
export function summarizeExistingConfig(config: ClawdbotConfig): string {
|
||||
const rows: string[] = [];
|
||||
const defaults = config.agents?.defaults;
|
||||
if (defaults?.workspace) rows.push(`workspace: ${defaults.workspace}`);
|
||||
if (defaults?.workspace) rows.push(shortenHomeInString(`workspace: ${defaults.workspace}`));
|
||||
if (defaults?.model) {
|
||||
const model = typeof defaults.model === "string" ? defaults.model : defaults.model.primary;
|
||||
if (model) rows.push(`model: ${model}`);
|
||||
if (model) rows.push(shortenHomeInString(`model: ${model}`));
|
||||
}
|
||||
if (config.gateway?.mode) rows.push(`gateway.mode: ${config.gateway.mode}`);
|
||||
if (config.gateway?.mode) rows.push(shortenHomeInString(`gateway.mode: ${config.gateway.mode}`));
|
||||
if (typeof config.gateway?.port === "number") {
|
||||
rows.push(`gateway.port: ${config.gateway.port}`);
|
||||
rows.push(shortenHomeInString(`gateway.port: ${config.gateway.port}`));
|
||||
}
|
||||
if (config.gateway?.bind) rows.push(`gateway.bind: ${config.gateway.bind}`);
|
||||
if (config.gateway?.bind) rows.push(shortenHomeInString(`gateway.bind: ${config.gateway.bind}`));
|
||||
if (config.gateway?.remote?.url) {
|
||||
rows.push(`gateway.remote.url: ${config.gateway.remote.url}`);
|
||||
rows.push(shortenHomeInString(`gateway.remote.url: ${config.gateway.remote.url}`));
|
||||
}
|
||||
if (config.skills?.install?.nodeManager) {
|
||||
rows.push(`skills.nodeManager: ${config.skills.install.nodeManager}`);
|
||||
rows.push(shortenHomeInString(`skills.nodeManager: ${config.skills.install.nodeManager}`));
|
||||
}
|
||||
return rows.length ? rows.join("\n") : "No key settings detected.";
|
||||
}
|
||||
@@ -220,10 +226,10 @@ export async function ensureWorkspaceAndSessions(
|
||||
dir: workspaceDir,
|
||||
ensureBootstrapFiles: !options?.skipBootstrap,
|
||||
});
|
||||
runtime.log(`Workspace OK: ${ws.dir}`);
|
||||
runtime.log(`Workspace OK: ${shortenHomePath(ws.dir)}`);
|
||||
const sessionsDir = resolveSessionTranscriptsDirForAgent(options?.agentId);
|
||||
await fs.mkdir(sessionsDir, { recursive: true });
|
||||
runtime.log(`Sessions OK: ${sessionsDir}`);
|
||||
runtime.log(`Sessions OK: ${shortenHomePath(sessionsDir)}`);
|
||||
}
|
||||
|
||||
export function resolveNodeManagerOptions(): Array<{
|
||||
@@ -246,9 +252,9 @@ export async function moveToTrash(pathname: string, runtime: RuntimeEnv): Promis
|
||||
}
|
||||
try {
|
||||
await runCommandWithTimeout(["trash", pathname], { timeoutMs: 5000 });
|
||||
runtime.log(`Moved to Trash: ${pathname}`);
|
||||
runtime.log(`Moved to Trash: ${shortenHomePath(pathname)}`);
|
||||
} catch {
|
||||
runtime.log(`Failed to move to Trash (manual delete): ${pathname}`);
|
||||
runtime.log(`Failed to move to Trash (manual delete): ${shortenHomePath(pathname)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, resolveGatewayPort, writeConfigFile } from "../../config/config.js";
|
||||
import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { formatCliCommand } from "../../cli/command-format.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
import { DEFAULT_GATEWAY_DAEMON_RUNTIME } from "../daemon-runtime.js";
|
||||
import { healthCommand } from "../health.js";
|
||||
import {
|
||||
@@ -74,7 +75,7 @@ export async function runNonInteractiveOnboardingLocal(params: {
|
||||
|
||||
nextConfig = applyWizardMetadata(nextConfig, { command: "onboard", mode });
|
||||
await writeConfigFile(nextConfig);
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
|
||||
await ensureWorkspaceAndSessions(workspaceDir, runtime, {
|
||||
skipBootstrap: Boolean(nextConfig.agents?.defaults?.skipBootstrap),
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
import type { AuthChoice, OnboardOptions } from "../../onboard-types.js";
|
||||
import { applyOpenAICodexModelDefault } from "../../openai-codex-model-default.js";
|
||||
import { resolveNonInteractiveApiKey } from "../api-keys.js";
|
||||
import { shortenHomePath } from "../../../utils.js";
|
||||
|
||||
export async function applyNonInteractiveAuthChoice(params: {
|
||||
nextConfig: ClawdbotConfig;
|
||||
@@ -172,7 +173,7 @@ export async function applyNonInteractiveAuthChoice(params: {
|
||||
const key = resolved.key;
|
||||
const result = upsertSharedEnvVar({ key: "OPENAI_API_KEY", value: key });
|
||||
process.env.OPENAI_API_KEY = key;
|
||||
runtime.log(`Saved OPENAI_API_KEY to ${result.path}`);
|
||||
runtime.log(`Saved OPENAI_API_KEY to ${shortenHomePath(result.path)}`);
|
||||
return nextConfig;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { RuntimeEnv } from "../../runtime.js";
|
||||
import { formatCliCommand } from "../../cli/command-format.js";
|
||||
import { applyWizardMetadata } from "../onboard-helpers.js";
|
||||
import type { OnboardOptions } from "../onboard-types.js";
|
||||
import { shortenHomePath } from "../../utils.js";
|
||||
|
||||
export async function runNonInteractiveOnboardingRemote(params: {
|
||||
opts: OnboardOptions;
|
||||
@@ -33,7 +34,7 @@ export async function runNonInteractiveOnboardingRemote(params: {
|
||||
};
|
||||
nextConfig = applyWizardMetadata(nextConfig, { command: "onboard", mode });
|
||||
await writeConfigFile(nextConfig);
|
||||
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
|
||||
const payload = {
|
||||
mode,
|
||||
|
||||
@@ -7,6 +7,7 @@ import { type ClawdbotConfig, CONFIG_PATH_CLAWDBOT, writeConfigFile } from "../c
|
||||
import { resolveSessionTranscriptsDir } from "../config/sessions.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
|
||||
async function readConfigFileRaw(): Promise<{
|
||||
exists: boolean;
|
||||
@@ -54,20 +55,20 @@ export async function setupCommand(
|
||||
await writeConfigFile(next);
|
||||
runtime.log(
|
||||
!existingRaw.exists
|
||||
? `Wrote ${CONFIG_PATH_CLAWDBOT}`
|
||||
: `Updated ${CONFIG_PATH_CLAWDBOT} (set agents.defaults.workspace)`,
|
||||
? `Wrote ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`
|
||||
: `Updated ${shortenHomePath(CONFIG_PATH_CLAWDBOT)} (set agents.defaults.workspace)`,
|
||||
);
|
||||
} else {
|
||||
runtime.log(`Config OK: ${CONFIG_PATH_CLAWDBOT}`);
|
||||
runtime.log(`Config OK: ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
}
|
||||
|
||||
const ws = await ensureAgentWorkspace({
|
||||
dir: workspace,
|
||||
ensureBootstrapFiles: !next.agents?.defaults?.skipBootstrap,
|
||||
});
|
||||
runtime.log(`Workspace OK: ${ws.dir}`);
|
||||
runtime.log(`Workspace OK: ${shortenHomePath(ws.dir)}`);
|
||||
|
||||
const sessionsDir = resolveSessionTranscriptsDir();
|
||||
await fs.mkdir(sessionsDir, { recursive: true });
|
||||
runtime.log(`Sessions OK: ${sessionsDir}`);
|
||||
runtime.log(`Sessions OK: ${shortenHomePath(sessionsDir)}`);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { visibleWidth } from "./ansi.js";
|
||||
import { shortenHomeInString } from "../utils.js";
|
||||
|
||||
type Align = "left" | "right" | "center";
|
||||
|
||||
@@ -168,11 +169,18 @@ function normalizeWidth(n: number | undefined): number | undefined {
|
||||
}
|
||||
|
||||
export function renderTable(opts: RenderTableOptions): string {
|
||||
const rows = opts.rows.map((row) => {
|
||||
const next: Record<string, string> = {};
|
||||
for (const [key, value] of Object.entries(row)) {
|
||||
next[key] = shortenHomeInString(value);
|
||||
}
|
||||
return next;
|
||||
});
|
||||
const border = opts.border ?? "unicode";
|
||||
if (border === "none") {
|
||||
const columns = opts.columns;
|
||||
const header = columns.map((c) => c.header).join(" | ");
|
||||
const lines = [header, ...opts.rows.map((r) => columns.map((c) => r[c.key] ?? "").join(" | "))];
|
||||
const lines = [header, ...rows.map((r) => columns.map((c) => r[c.key] ?? "").join(" | "))];
|
||||
return `${lines.join("\n")}\n`;
|
||||
}
|
||||
|
||||
@@ -181,7 +189,7 @@ export function renderTable(opts: RenderTableOptions): string {
|
||||
|
||||
const metrics = columns.map((c) => {
|
||||
const headerW = visibleWidth(c.header);
|
||||
const cellW = Math.max(0, ...opts.rows.map((r) => visibleWidth(r[c.key] ?? "")));
|
||||
const cellW = Math.max(0, ...rows.map((r) => visibleWidth(r[c.key] ?? "")));
|
||||
return { headerW, cellW };
|
||||
});
|
||||
|
||||
@@ -328,7 +336,7 @@ export function renderTable(opts: RenderTableOptions): string {
|
||||
lines.push(hLine(box.tl, box.t, box.tr));
|
||||
lines.push(...renderRow({}, true));
|
||||
lines.push(hLine(box.ml, box.m, box.mr));
|
||||
for (const row of opts.rows) {
|
||||
for (const row of rows) {
|
||||
lines.push(...renderRow(row, false));
|
||||
}
|
||||
lines.push(hLine(box.bl, box.b, box.br));
|
||||
|
||||
Reference in New Issue
Block a user