Foundry UI polish: terminal empty state, history minimap redesign, styling tweaks (#242)

- Hide terminal pane body when no terminal tabs exist
- Redesign history minimap from orange bar to single icon with popover dropdown
- Simplify popover items to single-line user messages with ellipsis
- Adjust min-used badge hover padding
- Add right padding to message list for history icon clearance

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nicholas Kissel 2026-03-12 11:03:04 -07:00 committed by GitHub
parent f09b9090bb
commit fde8b481bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 4164 additions and 1018 deletions

View file

@ -0,0 +1,2 @@
const e = {};
export { e as default };

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
@import"https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap";:root{color-scheme:dark;font-family:IBM Plex Sans,Segoe UI,sans-serif;background:var(--f-surface-primary, #000000);color:var(--f-text-primary, #ffffff)}html,body,#root{height:100%}body{margin:0;background:var(--f-surface-primary, #000000);color:var(--f-text-primary, #ffffff);overflow:hidden}*{box-sizing:border-box;-webkit-user-select:none;user-select:none}input,textarea,pre,code,[data-selectable]{-webkit-user-select:text;user-select:text}a{color:inherit}@keyframes hf-spin{to{transform:rotate(360deg)}}button,input,textarea,select{font:inherit}code,pre{font-family:IBM Plex Mono,SFMono-Regular,monospace}.mock-diff-header{display:flex;align-items:center;gap:8px;padding:8px 14px;border-bottom:1px solid var(--f-border-default, rgba(255, 255, 255, .12));background:var(--f-surface-secondary, #111111)}.mock-diff-path{color:var(--f-text-primary, #fafafa);font-family:IBM Plex Mono,SFMono-Regular,monospace;font-size:13px;font-weight:600}.mock-diff-stats{display:flex;gap:8px;margin-left:4px;font-size:12px}.mock-diff-added{color:var(--f-status-success, #7ee787)}.mock-diff-removed{color:var(--f-status-error, #ffa198)}.mock-diff-body{font-family:IBM Plex Mono,SFMono-Regular,monospace;font-size:12px;line-height:20px}.mock-diff-row{display:flex;align-items:stretch;min-height:20px}.mock-diff-row[data-kind=add]{background:#2ea0431f}.mock-diff-row[data-kind=remove]{background:#f851491a}.mock-diff-row[data-kind=hunk]{background:#ffffff0a;border-bottom:1px solid var(--f-border-default, rgba(255, 255, 255, .12))}.mock-diff-row[data-kind=hunk]:not(:first-child){border-top:1px solid var(--f-border-default, rgba(255, 255, 255, .12))}.mock-diff-gutter{position:relative;width:36px;flex-shrink:0;padding:0 8px 0 0;font-size:11px;line-height:20px;text-align:right;-webkit-user-select:none;user-select:none}.mock-diff-line-number{display:block;color:var(--f-text-tertiary, #71717a);opacity:.5}.mock-diff-line-text{flex:1;padding:0 10px;overflow:hidden;color:var(--f-text-secondary, #a1a1aa);font-size:12px;font-weight:400;line-height:20px;text-overflow:ellipsis;white-space:pre}.mock-diff-row[data-kind=add] .mock-diff-line-text{color:var(--f-status-success, #7ee787)}.mock-diff-row[data-kind=remove] .mock-diff-line-text{color:var(--f-status-error, #ffa198)}.mock-diff-row[data-kind=hunk] .mock-diff-line-text{color:var(--f-text-tertiary, #71717a)}.mock-diff-row[data-kind=hunk] .mock-diff-line-text{font-size:11px;font-weight:600}.mock-diff-attach-button{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:0;border:0;background:transparent;color:var(--f-accent, #ff4f00);cursor:pointer;opacity:0;pointer-events:none;z-index:1}.mock-diff-row:not([data-kind=hunk]):hover{background:#ff4f000f}.mock-diff-row:not([data-kind=hunk]):hover .mock-diff-attach-button{opacity:1;pointer-events:auto;background:var(--f-accent-subtle, rgba(255, 79, 0, .1))}.mock-diff-row:not([data-kind=hunk]):hover .mock-diff-line-number{opacity:0}.mock-diff-empty{padding:40px;text-align:center}.mock-diff-empty-copy{color:var(--f-text-tertiary, #71717a);font-size:14px;line-height:1.4}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,198 @@
import { _ as u } from "./index-D0-B2Qgl.js";
var P = {};
function S() {
return typeof process?.versions?.bun == "string" ? !0 : (P?.npm_config_user_agent || "").includes("bun/");
}
var I = new Set(["EACCES", "EPERM", "ENOEXEC"]);
function A(n) {
if (!n || typeof n != "object") return !1;
const e = n.code;
return typeof e == "string" && I.has(e);
}
function R(n, e) {
if (process.platform === "win32") return !0;
try {
return e.accessSync(n, e.constants.X_OK), !0;
} catch {}
try {
return e.chmodSync(n, 493), !0;
} catch (o) {
if (A(o)) return !1;
throw o;
}
}
function T(n) {
const { binPath: e, trustPackages: o, bunInstallBlocks: s, genericInstallCommands: r, binaryName: a } = n,
t = [`${a ?? "sandbox-agent"} binary is not executable: ${e}`];
if (S()) {
t.push("Allow Bun to run postinstall scripts for native binaries and reinstall:");
for (const c of s) {
t.push(`${c.label}:`);
for (const d of c.commands) t.push(` ${d}`);
}
return (
t.push(`Or run: chmod +x "${e}"`),
t.join(`
`)
);
}
if ((t.push("Postinstall scripts for native packages did not run, so the binary was left non-executable."), r && r.length > 0)) {
t.push("Reinstall with scripts enabled:");
for (const c of r) t.push(` ${c}`);
} else t.push("Reinstall with scripts enabled for:"), t.push(` ${o}`);
return (
t.push(`Or run: chmod +x "${e}"`),
t.join(`
`)
);
}
var x = {},
$ = {
"darwin-arm64": "@sandbox-agent/cli-darwin-arm64",
"darwin-x64": "@sandbox-agent/cli-darwin-x64",
"linux-x64": "@sandbox-agent/cli-linux-x64",
"linux-arm64": "@sandbox-agent/cli-linux-arm64",
"win32-x64": "@sandbox-agent/cli-win32-x64",
},
b = "@sandbox-agent/cli-linux-x64 @sandbox-agent/cli-linux-arm64 @sandbox-agent/cli-darwin-arm64 @sandbox-agent/cli-darwin-x64 @sandbox-agent/cli-win32-x64";
function k() {
return typeof process < "u" && !!process.versions?.node;
}
async function V(n, e) {
if (!k()) throw new Error("Autospawn requires a Node.js runtime.");
const { spawn: o } = await u(async () => {
const { spawn: p } = await import("./__vite-browser-external-BIHI7g3E.js");
return { spawn: p };
}, []),
s = await u(() => import("./__vite-browser-external-BIHI7g3E.js"), []),
r = await u(() => import("./__vite-browser-external-BIHI7g3E.js"), []),
a = await u(() => import("./__vite-browser-external-BIHI7g3E.js"), []),
i = await u(() => import("./__vite-browser-external-BIHI7g3E.js"), []),
{ createRequire: t } = await u(async () => {
const { createRequire: p } = await import("./__vite-browser-external-BIHI7g3E.js");
return { createRequire: p };
}, []),
c = n.host ?? "127.0.0.1",
d = n.port ?? (await C(i, c)),
_ = c === "0.0.0.0" || c === "::" ? "127.0.0.1" : c,
m = n.token ?? s.randomBytes(24).toString("hex"),
E = n.timeoutMs ?? 15e3,
w = n.log ?? "inherit",
f = n.binaryPath ?? B(r, a) ?? O(t(import.meta.url), a, r) ?? N(r, a);
if (!f) throw new Error("sandbox-agent binary not found. Install @sandbox-agent/cli or set SANDBOX_AGENT_BIN.");
if (!R(f, r))
throw new Error(
T({
binPath: f,
trustPackages: b,
bunInstallBlocks: [
{ label: "Project install", commands: [`bun pm trust ${b}`, "bun add sandbox-agent"] },
{ label: "Global install", commands: [`bun pm -g trust ${b}`, "bun add -g sandbox-agent"] },
],
}),
);
const v = w === "inherit" ? "inherit" : w === "silent" ? "ignore" : "pipe",
y = ["server", "--host", c, "--port", String(d), "--token", m],
l = o(f, y, { stdio: v, env: { ...x, ...(n.env ?? {}) } }),
h = D(l),
g = `http://${_}:${d}`;
return (
await G(g, e ?? globalThis.fetch, E, l, m),
{
baseUrl: g,
token: m,
child: l,
dispose: async () => {
if (l.exitCode !== null) {
h.dispose();
return;
}
l.kill("SIGTERM"), (await M(l, 5e3)) || l.kill("SIGKILL"), h.dispose();
},
}
);
}
function B(n, e) {
const o = x.SANDBOX_AGENT_BIN;
if (!o) return null;
const s = e.resolve(o);
return n.existsSync(s) ? s : null;
}
function O(n, e, o) {
const s = `${process.platform}-${process.arch}`,
r = $[s];
if (!r) return null;
try {
const a = n.resolve(`${r}/package.json`),
i = process.platform === "win32" ? "sandbox-agent.exe" : "sandbox-agent",
t = e.join(e.dirname(a), "bin", i);
return o.existsSync(t) ? t : null;
} catch {
return null;
}
}
function N(n, e) {
const o = x.PATH ?? "",
s = process.platform === "win32" ? ";" : ":",
r = o.split(s).filter(Boolean),
a = process.platform === "win32" ? "sandbox-agent.exe" : "sandbox-agent";
for (const i of r) {
const t = e.join(i, a);
if (n.existsSync(t)) return t;
}
return null;
}
async function C(n, e) {
return new Promise((o, s) => {
const r = n.createServer();
r.unref(),
r.on("error", s),
r.listen(0, e, () => {
const a = r.address();
r.close(() => o(a.port));
});
});
}
async function G(n, e, o, s, r) {
if (!e) throw new Error("Fetch API is not available; provide a fetch implementation.");
const a = Date.now();
let i;
for (; Date.now() - a < o; ) {
if (s.exitCode !== null) throw new Error("sandbox-agent exited before becoming healthy.");
try {
const t = await e(`${n}/v1/health`, { headers: { Authorization: `Bearer ${r}` } });
if (t.ok) return;
i = `status ${t.status}`;
} catch (t) {
i = t instanceof Error ? t.message : String(t);
}
await new Promise((t) => setTimeout(t, 200));
}
throw new Error(`Timed out waiting for sandbox-agent health (${i ?? "unknown error"}).`);
}
async function M(n, e) {
return n.exitCode !== null
? !0
: new Promise((o) => {
const s = setTimeout(() => o(!1), e);
n.once("exit", () => {
clearTimeout(s), o(!0);
});
});
}
function D(n) {
const e = () => {
n.exitCode === null && n.kill("SIGTERM");
};
return (
process.once("exit", e),
process.once("SIGINT", e),
process.once("SIGTERM", e),
{
dispose: () => {
process.off("exit", e), process.off("SIGINT", e), process.off("SIGTERM", e);
},
}
);
}
export { k as isNodeRuntime, V as spawnSandboxAgent };