diff --git a/packages/app/src/components/session/session-new-view.tsx b/packages/app/src/components/session/session-new-view.tsx index b0df2b278..f3c7d4081 100644 --- a/packages/app/src/components/session/session-new-view.tsx +++ b/packages/app/src/components/session/session-new-view.tsx @@ -10,7 +10,7 @@ import { amicodeGet } from "@/utils/amicode-fetch" import { parseProblemsResponse } from "@opencode-ai/ui/amicode-problem-switcher" import { Icon } from "@opencode-ai/ui/icon" import { AmicodeGettingStarted } from "@opencode-ai/ui/amicode-getting-started" -import { MarkDetailed } from "@opencode-ai/ui/logo" +import { Logo, MarkDetailed } from "@opencode-ai/ui/logo" import { getDirectory, getFilename } from "@opencode-ai/core/util/path" const MAIN_WORKTREE = "main" @@ -79,18 +79,9 @@ export function NewSessionView(props: NewSessionViewProps) {
- {/* amicode: straight wordmark (the Logo's Racing Sans One face reads as - italic); byline keeps the brand attribution. */} -
- AMICODE -
+ {/* amicode: brand wordmark in the brand typeface (Racing Sans One — restored per review); + MarkDetailed is the redesign's detailed mark (kept from trunk) */} +
{/* amicode: getting-started block (tagline + how-it-works + starter chips) */} {/* Cards: full width across, sized to content so they never scroll */}
+ {/* solver mode (show-only v1, spec-20260709-093000): right-aligned above the cards */} +
+ +
{ + const m = new Map() + return { getItem: (k: string) => m.get(k) ?? null, setItem: (k: string, v: string) => void m.set(k, v) } +} + +describe("solver mode persistence", () => { + test("defaults to piccolo; hp round-trips; garbage → piccolo", () => { + const s = mem() + expect(loadSolverMode(s)).toBe("piccolo") + saveSolverMode("hp", s) + expect(loadSolverMode(s)).toBe("hp") + s.setItem("amicode-solver-mode", "nonsense") + expect(loadSolverMode(s)).toBe("piccolo") + }) + test("storage failures fail soft", () => { + const broken = { + getItem: () => { + throw new Error("nope") + }, + setItem: () => { + throw new Error("nope") + }, + } + expect(loadSolverMode(broken)).toBe("piccolo") + expect(() => saveSolverMode("hp", broken)).not.toThrow() + }) +}) diff --git a/packages/ui/src/amicode/solver-toggle.tsx b/packages/ui/src/amicode/solver-toggle.tsx new file mode 100644 index 000000000..89e906489 --- /dev/null +++ b/packages/ui/src/amicode/solver-toggle.tsx @@ -0,0 +1,102 @@ +import { createSignal } from "solid-js" + +// AMICODE: solver mode toggle — SHOW-ONLY v1 (spec-20260709-093000). Presents +// the future High-Performance path (Piccolissimo splines + Altissimo GPU +// solver on Harmoniqs cloud) as a selectable mode so demos can tell the story +// today. It deliberately changes NOTHING about solves: the future wiring is +// the scores schema's `executor: "cloud-altissimo" | local` seam, and the +// existing `issimo` entitlement tier becomes the subscription gate. + +export type SolverMode = "piccolo" | "hp" +const KEY = "amicode-solver-mode" + +export function loadSolverMode(storage: Pick = localStorage): SolverMode { + try { + return storage.getItem(KEY) === "hp" ? "hp" : "piccolo" + } catch { + return "piccolo" + } +} + +export function saveSolverMode(mode: SolverMode, storage: Pick = localStorage): void { + try { + storage.setItem(KEY, mode) + } catch { + /* storage unavailable — selection just won't persist */ + } +} + +export function AmicodeSolverToggle() { + const [mode, setMode] = createSignal(loadSolverMode()) + const pick = (m: SolverMode) => { + setMode(m) + saveSolverMode(m) + } + const seg = (active: boolean): Record => ({ + display: "inline-flex", + "align-items": "center", + gap: "6px", + padding: "5px 12px", + "font-size": "12px", + "font-weight": active ? "650" : "450", + border: "none", + cursor: "pointer", + background: active ? "color-mix(in srgb, var(--v2-icon-icon-accent) 14%, transparent)" : "transparent", + color: active ? "var(--v2-text-text-base)" : "var(--v2-text-text-muted)", + }) + return ( +
+ + Solver + +
+ + +
+ High Performance Solver +
+ ) +} diff --git a/packages/ui/src/components/amicode-solver-toggle.tsx b/packages/ui/src/components/amicode-solver-toggle.tsx new file mode 100644 index 000000000..994f5e084 --- /dev/null +++ b/packages/ui/src/components/amicode-solver-toggle.tsx @@ -0,0 +1,2 @@ +// AMICODE: re-export shim (wildcard export path) — logic in ../amicode/solver-toggle.tsx. +export { AmicodeSolverToggle, loadSolverMode, saveSolverMode, type SolverMode } from "../amicode/solver-toggle" diff --git a/packages/ui/src/components/logo.tsx b/packages/ui/src/components/logo.tsx index f0d1b7b5a..ff2f1411d 100644 --- a/packages/ui/src/components/logo.tsx +++ b/packages/ui/src/components/logo.tsx @@ -109,9 +109,8 @@ export const Logo = (props: { class?: string }) => { dominant-baseline="central" textLength="230" lengthAdjust="spacingAndGlyphs" - font-family="var(--font-family-sans, ui-sans-serif, system-ui, -apple-system, sans-serif)" - font-weight="750" - letter-spacing="4" + font-family="'Racing Sans One', var(--font-family-mono, ui-monospace, monospace)" + font-weight="400" font-size="36" fill="var(--icon-base)" >