diff --git a/extensions/research-tools/header.ts b/extensions/research-tools/header.ts
index 6591499..d0baf31 100644
--- a/extensions/research-tools/header.ts
+++ b/extensions/research-tools/header.ts
@@ -1,5 +1,5 @@
import { readdir } from "node:fs/promises";
-import { cpus, freemem, homedir, totalmem } from "node:os";
+import { cpus, homedir, totalmem } from "node:os";
import { execSync } from "node:child_process";
import { resolve as resolvePath } from "node:path";
@@ -133,33 +133,30 @@ type SystemResources = {
docker: boolean;
};
-function detectSystemResources(): SystemResources {
- const cores = cpus().length;
- const cpu = cpus()[0]?.model?.trim() ?? "unknown";
- const totalBytes = totalmem();
- const freeBytes = freemem();
- const ramTotal = `${Math.round(totalBytes / (1024 ** 3))}GB`;
- const ramFree = `${Math.round(freeBytes / (1024 ** 3))}GB`;
+let cachedResources: SystemResources | null = null;
+
+function detectSystemResources(): SystemResources {
+ if (cachedResources) return cachedResources;
+
+ const cores = cpus().length;
+ const totalBytes = totalmem();
+ const ramTotal = `${Math.round(totalBytes / (1024 ** 3))}GB`;
+
+ cachedResources = { cpu: "", cores, ramTotal, ramFree: "", gpu: null, docker: false };
- let gpu: string | null = null;
try {
if (process.platform === "darwin") {
- const out = execSync("system_profiler SPDisplaysDataType 2>/dev/null | grep 'Chipset Model\\|Chip Model'", { encoding: "utf8", timeout: 3000 }).trim();
- const match = out.match(/:\s*(.+)/);
- if (match) gpu = match[1]!.trim();
- } else {
- const out = execSync("nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null", { encoding: "utf8", timeout: 3000 }).trim();
- if (out) gpu = out.split("\n")[0]!.trim();
+ const out = execSync("sysctl -n machdep.cpu.brand_string 2>/dev/null", { encoding: "utf8", timeout: 1000 }).trim();
+ if (out) cachedResources.cpu = out;
}
} catch {}
- let docker = false;
try {
- execSync("docker info 2>/dev/null", { timeout: 3000 });
- docker = true;
+ execSync("command -v docker >/dev/null 2>&1", { timeout: 500 });
+ cachedResources.docker = true;
} catch {}
- return { cpu, cores, ramTotal, ramFree, gpu, docker };
+ return cachedResources;
}
type WorkflowInfo = { name: string; description: string };
@@ -268,10 +265,9 @@ export function installFeynmanHeader(
pushLabeled("directory", dirLabel, "text");
pushLabeled("session", sessionId, "dim");
leftLines.push("");
- pushLabeled("cpu", `${resources.cores} cores`, "dim");
- pushLabeled("ram", `${resources.ramFree} free / ${resources.ramTotal}`, "dim");
- if (resources.gpu) pushLabeled("gpu", resources.gpu, "dim");
- pushLabeled("docker", resources.docker ? "available" : "not found", "dim");
+ const sysParts = [`${resources.cores} cores`, resources.ramTotal];
+ if (resources.docker) sysParts.push("docker");
+ pushLabeled("system", sysParts.join(" · "), "dim");
leftLines.push("");
leftLines.push(theme.fg("dim", `${toolCount} tools · ${agentCount} agents`));
@@ -343,7 +339,7 @@ export function installFeynmanHeader(
push(row(`${theme.fg("dim", "model".padEnd(10))} ${theme.fg("text", truncateVisible(modelLabel, narrowValW))}`));
push(row(`${theme.fg("dim", "directory".padEnd(10))} ${theme.fg("text", truncateVisible(dirLabel, narrowValW))}`));
push(row(`${theme.fg("dim", "session".padEnd(10))} ${theme.fg("dim", truncateVisible(sessionId, narrowValW))}`));
- const resourceLine = `${resources.cores} cores · ${resources.ramTotal} ram${resources.gpu ? ` · ${resources.gpu}` : ""}${resources.docker ? " · docker" : ""}`;
+ const resourceLine = `${resources.cores} cores · ${resources.ramTotal}${resources.docker ? " · docker" : ""}`;
push(row(theme.fg("dim", truncateVisible(resourceLine, contentW))));
push(row(theme.fg("dim", truncateVisible(`${toolCount} tools · ${agentCount} agents · ${commandCount} commands`, contentW))));
push(emptyRow());
diff --git a/package-lock.json b/package-lock.json
index d6430da..c82ef41 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@companion-ai/feynman",
- "version": "0.2.2",
+ "version": "0.2.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@companion-ai/feynman",
- "version": "0.2.2",
+ "version": "0.2.3",
"hasInstallScript": true,
"dependencies": {
"@companion-ai/alpha-hub": "^0.1.2",
diff --git a/package.json b/package.json
index aacecb5..3a62ce7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@companion-ai/feynman",
- "version": "0.2.2",
+ "version": "0.2.3",
"description": "Research-first CLI agent built on Pi and alphaXiv",
"type": "module",
"bin": {
diff --git a/scripts/patch-embedded-pi.mjs b/scripts/patch-embedded-pi.mjs
index 5dc2009..37ee257 100644
--- a/scripts/patch-embedded-pi.mjs
+++ b/scripts/patch-embedded-pi.mjs
@@ -250,6 +250,18 @@ if (existsSync(sessionSearchIndexerPath)) {
}
}
+const oauthPagePath = resolve(appRoot, "node_modules", "@mariozechner", "pi-ai", "dist", "utils", "oauth", "oauth-page.js");
+
+if (existsSync(oauthPagePath)) {
+ let source = readFileSync(oauthPagePath, "utf8");
+ const piLogo = 'const LOGO_SVG = ``;';
+ if (source.includes(piLogo)) {
+ const feynmanLogo = 'const LOGO_SVG = `feynman`;';
+ source = source.replace(piLogo, feynmanLogo);
+ writeFileSync(oauthPagePath, source, "utf8");
+ }
+}
+
if (existsSync(piMemoryPath)) {
let source = readFileSync(piMemoryPath, "utf8");
const memoryOriginal = 'const MEMORY_DIR = join(homedir(), ".pi", "memory");';