From e99e80d43c6fb59d9adf3dc72df20667e2c8dcf3 Mon Sep 17 00:00:00 2001 From: Raghav Chari Date: Thu, 9 Jul 2026 11:25:12 -0400 Subject: [PATCH 1/2] =?UTF-8?q?feat(solver):=20show-only=20High-Performanc?= =?UTF-8?q?e=20Solver=20toggle=20=E2=80=94=20[Piccolo=20|=20=E2=9A=A1=20Pi?= =?UTF-8?q?ccolissimo=20+=20Altissimo=20PRO]=20segmented=20control=20on=20?= =?UTF-8?q?home=20(spec-20260709-093000);=20selection=20persists=20in=20lo?= =?UTF-8?q?calStorage,=20changes=20nothing=20about=20solves=20(future=20wi?= =?UTF-8?q?ring:=20executor=20cloud-altissimo=20seam=20+=20issimo=20entitl?= =?UTF-8?q?ement=20as=20the=20subscription=20gate)=20+=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- packages/app/src/pages/home.tsx | 5 + packages/ui/src/amicode/solver-toggle.test.ts | 30 ++++++ packages/ui/src/amicode/solver-toggle.tsx | 102 ++++++++++++++++++ .../src/components/amicode-solver-toggle.tsx | 2 + 4 files changed, 139 insertions(+) create mode 100644 packages/ui/src/amicode/solver-toggle.test.ts create mode 100644 packages/ui/src/amicode/solver-toggle.tsx create mode 100644 packages/ui/src/components/amicode-solver-toggle.tsx diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx index 3ca9e08e4..880f8697b 100644 --- a/packages/app/src/pages/home.tsx +++ b/packages/app/src/pages/home.tsx @@ -63,6 +63,7 @@ import { type ServerHealth } from "@/utils/server-health" import { amicodeGet, amicodePost } from "@/utils/amicode-fetch" import { AmicodeRunGallery } from "@opencode-ai/ui/amicode-run-gallery" import { AmicodeOnboardingWizard, shouldShowWizard } from "@opencode-ai/ui/amicode-onboarding-wizard" +import { AmicodeSolverToggle } from "@opencode-ai/ui/amicode-solver-toggle" import { parseRunCardsResponse } from "@opencode-ai/ui/amicode-run-card" import { AmicodeHomeCards, parseProfileResponse, type HomeLiveRun } from "@opencode-ai/ui/amicode-home-cards" import { parseRunSeriesResponse } from "@opencode-ai/ui/amicode-run-window" @@ -696,6 +697,10 @@ function HomeDesign() { {/* 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" From e24ab1ab51902cbeb4bd00a3be98f9a40bd16a98 Mon Sep 17 00:00:00 2001 From: Raghav Chari Date: Thu, 9 Jul 2026 11:25:12 -0400 Subject: [PATCH 2/2] =?UTF-8?q?fix(brand):=20chat-window=20AMICODE=20wordm?= =?UTF-8?q?ark=20back=20to=20the=20brand=20typeface=20=E2=80=94=20restore?= =?UTF-8?q?=20the=20=20component=20and=20its=20Racing=20Sans=20One?= =?UTF-8?q?=20face=20(straight-sans=20experiment=20reverted=20per=20review?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../src/components/session/session-new-view.tsx | 16 +++------------- packages/ui/src/components/logo.tsx | 5 ++--- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/packages/app/src/components/session/session-new-view.tsx b/packages/app/src/components/session/session-new-view.tsx index b70f8fb9a..a28f1c1dc 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 { Mark } from "@opencode-ai/ui/logo" +import { Logo, Mark } from "@opencode-ai/ui/logo" import { getDirectory, getFilename } from "@opencode-ai/core/util/path" const MAIN_WORKTREE = "main" @@ -79,18 +79,8 @@ 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) */} +
{/* amicode: getting-started block (tagline + how-it-works + starter chips) */} { 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)" >