Improve CLI check path resolution and sticky agent detail tabs

Resolve relative paths in database and log checks against the config file
directory with fallback candidates. Make the AgentDetail tab bar sticky
with backdrop blur for better navigation on long pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-18 16:47:15 -06:00
parent f9abab662c
commit 5a2703a86c
3 changed files with 37 additions and 11 deletions

View File

@@ -3,7 +3,19 @@ import path from "node:path";
import type { PaperclipConfig } from "../config/schema.js";
import type { CheckResult } from "./index.js";
export async function databaseCheck(config: PaperclipConfig): Promise<CheckResult> {
function resolveConfigRelativePath(value: string, configPath?: string): string {
if (path.isAbsolute(value)) return value;
const candidates = [path.resolve(value)];
if (configPath) {
candidates.unshift(path.resolve(path.dirname(configPath), "..", "server", value));
candidates.unshift(path.resolve(path.dirname(configPath), value));
}
candidates.push(path.resolve(process.cwd(), "server", value));
const uniqueCandidates = Array.from(new Set(candidates));
return uniqueCandidates.find((candidate) => fs.existsSync(candidate)) ?? uniqueCandidates[0];
}
export async function databaseCheck(config: PaperclipConfig, configPath?: string): Promise<CheckResult> {
if (config.database.mode === "postgres") {
if (!config.database.connectionString) {
return {
@@ -36,15 +48,16 @@ export async function databaseCheck(config: PaperclipConfig): Promise<CheckResul
}
if (config.database.mode === "embedded-postgres") {
const dataDir = path.resolve(config.database.embeddedPostgresDataDir);
const dataDir = resolveConfigRelativePath(config.database.embeddedPostgresDataDir, configPath);
const reportedPath = dataDir;
if (!fs.existsSync(dataDir)) {
return {
name: "Database",
status: "warn",
message: `Embedded PostgreSQL data directory does not exist: ${dataDir}`,
message: `Embedded PostgreSQL data directory does not exist: ${reportedPath}`,
canRepair: true,
repair: () => {
fs.mkdirSync(dataDir, { recursive: true });
fs.mkdirSync(reportedPath, { recursive: true });
},
};
}

View File

@@ -3,27 +3,40 @@ import path from "node:path";
import type { PaperclipConfig } from "../config/schema.js";
import type { CheckResult } from "./index.js";
export function logCheck(config: PaperclipConfig): CheckResult {
const logDir = path.resolve(config.logging.logDir);
function resolveConfigRelativePath(value: string, configPath?: string): string {
if (path.isAbsolute(value)) return value;
const candidates = [path.resolve(value)];
if (configPath) {
candidates.unshift(path.resolve(path.dirname(configPath), "..", "server", value));
candidates.unshift(path.resolve(path.dirname(configPath), value));
}
candidates.push(path.resolve(process.cwd(), "server", value));
const uniqueCandidates = Array.from(new Set(candidates));
return uniqueCandidates.find((candidate) => fs.existsSync(candidate)) ?? uniqueCandidates[0];
}
export function logCheck(config: PaperclipConfig, configPath?: string): CheckResult {
const logDir = resolveConfigRelativePath(config.logging.logDir, configPath);
const reportedDir = logDir;
if (!fs.existsSync(logDir)) {
return {
name: "Log directory",
status: "warn",
message: `Log directory does not exist: ${logDir}`,
message: `Log directory does not exist: ${reportedDir}`,
canRepair: true,
repair: () => {
fs.mkdirSync(logDir, { recursive: true });
fs.mkdirSync(reportedDir, { recursive: true });
},
};
}
try {
fs.accessSync(logDir, fs.constants.W_OK);
fs.accessSync(reportedDir, fs.constants.W_OK);
return {
name: "Log directory",
status: "pass",
message: `Log directory is writable: ${logDir}`,
message: `Log directory is writable: ${reportedDir}`,
};
} catch {
return {

View File

@@ -363,7 +363,7 @@ export function AgentDetail() {
{actionError && <p className="text-sm text-destructive">{actionError}</p>}
<Tabs value={activeTab} onValueChange={setActiveTab}>
<div className="flex items-center justify-between">
<div className="sticky top-0 z-10 -mx-6 px-6 py-2 bg-background/90 backdrop-blur-sm flex items-center justify-between">
<PageTabBar
items={[
{ value: "overview", label: "Overview" },