Unify branding: VT323 logotype across website, TUI, and OAuth pages

- Add VT323 ASCII art logo to logo.mjs as single source of truth
- Website nav and hero use VT323 font via AsciiLogo.astro component
- TUI header and CLI help render the ASCII logo with block-centered alignment
- OAuth callback pages (Pi and alphaXiv) show branded feynman logotype
- Auto-set recommended model after provider login

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Advait Paliwal
2026-03-23 23:28:54 -07:00
parent cd0e5d953a
commit 779dd2441c
10 changed files with 63 additions and 27 deletions

View File

@@ -28,7 +28,7 @@ import { printSearchStatus } from "./search/commands.js";
import { runDoctor, runStatus } from "./setup/doctor.js";
import { setupPreviewDependencies } from "./setup/preview.js";
import { runSetup } from "./setup/setup.js";
import { printInfo, printPanel, printSection } from "./ui/terminal.js";
import { printAsciiHeader, printInfo, printPanel, printSection } from "./ui/terminal.js";
import {
cliCommandSections,
formatCliWorkflowUsage,
@@ -50,7 +50,7 @@ function printHelp(appRoot: string): void {
(command) => command.section === "Research Workflows" && command.topLevelCli,
);
printPanel("Feynman", [
printAsciiHeader([
"Research-first agent shell built on Pi.",
"Use `feynman setup` first if this is a new machine.",
]);
@@ -123,7 +123,7 @@ async function handleModelCommand(subcommand: string | undefined, args: string[]
}
if (subcommand === "login") {
await loginModelProvider(feynmanAuthPath, args[0]);
await loginModelProvider(feynmanAuthPath, args[0], feynmanSettingsPath);
return;
}

View File

@@ -6,6 +6,7 @@ import { promptChoice, promptText } from "../setup/prompts.js";
import { printInfo, printSection, printSuccess, printWarning } from "../ui/terminal.js";
import {
buildModelStatusSnapshotFromRecords,
chooseRecommendedModel,
getAvailableModelRecords,
getSupportedModelRecords,
type ModelStatusSnapshot,
@@ -109,7 +110,7 @@ export function printModelList(settingsPath: string, authPath: string): void {
}
}
export async function loginModelProvider(authPath: string, providerId?: string): Promise<void> {
export async function loginModelProvider(authPath: string, providerId?: string, settingsPath?: string): Promise<void> {
const provider = providerId ? resolveOAuthProvider(authPath, providerId) : await selectOAuthProvider(authPath, "login");
if (!provider) {
if (providerId) {
@@ -143,6 +144,21 @@ export async function loginModelProvider(authPath: string, providerId?: string):
});
printSuccess(`Model provider login complete: ${provider.id}`);
if (settingsPath) {
const currentSpec = getCurrentModelSpec(settingsPath);
const available = getAvailableModelRecords(authPath);
const currentValid = currentSpec
? available.some((m) => `${m.provider}/${m.id}` === currentSpec)
: false;
if ((!currentSpec || !currentValid) && available.length > 0) {
const recommended = chooseRecommendedModel(authPath);
if (recommended) {
setDefaultModelSpec(settingsPath, authPath, recommended.spec);
}
}
}
}
export async function logoutModelProvider(authPath: string, providerId?: string): Promise<void> {

View File

@@ -1,3 +1,5 @@
import { FEYNMAN_ASCII_LOGO } from "../../logo.mjs";
const RESET = "\x1b[0m";
const BOLD = "\x1b[1m";
const DIM = "\x1b[2m";
@@ -40,6 +42,17 @@ export function printSection(title: string): void {
console.log(paint(`${title}`, TEAL, BOLD));
}
export function printAsciiHeader(subtitleLines: string[] = []): void {
console.log("");
for (const line of FEYNMAN_ASCII_LOGO) {
console.log(paint(` ${line}`, TEAL, BOLD));
}
for (const line of subtitleLines) {
console.log(paint(` ${line}`, ASH));
}
console.log("");
}
export function printPanel(title: string, subtitleLines: string[] = []): void {
const inner = 53;
const border = "─".repeat(inner + 2);