diff --git a/ui/.gitignore b/ui/.gitignore index d782054e..fffa2feb 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -10,5 +10,6 @@ count.txt .wrangler .output .vinxi +dev-dist __unconfig* todos.json diff --git a/ui/public/apple-touch-icon.png b/ui/public/apple-touch-icon.png index e3ac9b26..7622f14b 100644 Binary files a/ui/public/apple-touch-icon.png and b/ui/public/apple-touch-icon.png differ diff --git a/ui/src/client.tsx b/ui/src/client.tsx index 2c1cfd2c..da232592 100644 --- a/ui/src/client.tsx +++ b/ui/src/client.tsx @@ -4,8 +4,11 @@ import { hydrateRoot } from "react-dom/client" import { registerSW } from "virtual:pwa-register" // prompt mode: a new SW installs in the background and takes over on the next -// load, so deploys never reload a tab mid-agent-run. -registerSW() +// load, so deploys never reload a tab mid-agent-run. Skip in dev — the SW +// precaches production-only build artifacts that 404 against the dev server. +if (import.meta.env.PROD) { + registerSW() +} hydrateRoot( document, diff --git a/ui/src/components/agents/AgentsHome.tsx b/ui/src/components/agents/AgentsHome.tsx index f93af9a4..635f209f 100644 --- a/ui/src/components/agents/AgentsHome.tsx +++ b/ui/src/components/agents/AgentsHome.tsx @@ -1,19 +1,15 @@ -import { Link } from "@tanstack/react-router" import { useState } from "react" import type { ModelSelection } from "@/lib/agents/useModelOptions" import { AgentPromptBar } from "@/components/agents/AgentPromptBar" -import { AgentRunCard } from "@/components/agents/AgentRunCard" import { SlackConnectDialog } from "@/components/agents/SlackConnectDialog" import { Logo } from "@/components/agents/ported/Logo" -import { useAgentThreads, useCreateAgentThread } from "@/lib/agents/queries" +import { useCreateAgentThread } from "@/lib/agents/queries" import { useModelOptions } from "@/lib/agents/useModelOptions" import { useProfile, useRepos } from "@/lib/profile" export function AgentsHome() { - const threadsQuery = useAgentThreads() const createThread = useCreateAgentThread() - const recentRuns = (threadsQuery.data ?? []).slice(0, 5) const { models, defaultSelection } = useModelOptions() const [selection, setSelection] = useState(null) const activeSelection = selection ?? defaultSelection @@ -53,35 +49,7 @@ export function AgentsHome() { onRepoChange={setRepoOverride} /> - -
- {threadsQuery.isLoading ? ( -

- Loading agents… -

- ) : recentRuns.length === 0 ? ( - - ) : ( - recentRuns.map((thread) => ( - - )) - )} -
) } - -export function AgentsHomeEmptyState() { - return ( -
-

No agents yet.

- - Start your first agent - -
- ) -} diff --git a/ui/src/components/agents/ported/CloudPromptBar.tsx b/ui/src/components/agents/ported/CloudPromptBar.tsx index 0f549d0f..b22acc21 100644 --- a/ui/src/components/agents/ported/CloudPromptBar.tsx +++ b/ui/src/components/agents/ported/CloudPromptBar.tsx @@ -1,3 +1,4 @@ +import { ArrowUp, ChevronDown, LoaderCircle } from "lucide-react" import { memo, useCallback, @@ -121,7 +122,7 @@ export const CloudPromptBar = memo(function CloudPromptBarComponent({ )}
@@ -134,7 +135,7 @@ export const CloudPromptBar = memo(function CloudPromptBarComponent({ placeholder={busy ? "Send a message to queue next..." : placeholder} disabled={disabled} className={cn( - "w-full min-w-0 resize-none overflow-hidden bg-transparent leading-[1.45] text-[color:var(--ui-text)] outline-none placeholder:text-[color:var(--ui-text-dim)]", + "w-full min-w-0 resize-none overflow-hidden bg-transparent text-[13px] leading-[1.45] text-[color:var(--ui-text)] outline-none placeholder:text-[color:var(--ui-text-dim)]", compact ? "min-h-[36px]" : "min-h-[52px]" )} style={{ maxHeight: PROMPT_TEXTAREA_MAX_HEIGHT }} @@ -146,9 +147,12 @@ export const CloudPromptBar = memo(function CloudPromptBarComponent({ type="button" disabled={pickerDisabled} onClick={() => setModelDropdownOpen((open) => !open)} - className="max-w-[220px] cursor-pointer truncate text-[color:var(--ui-text-muted)] transition-opacity hover:opacity-80 disabled:cursor-default disabled:opacity-60" + className="flex max-w-[220px] cursor-pointer items-center gap-0.5 text-[13px] text-[color:var(--ui-text-muted)] transition-opacity hover:opacity-80 disabled:cursor-default disabled:opacity-60" > - {selectionLabel} + {selectionLabel} + {!pickerDisabled && ( + + )} {modelDropdownOpen && combos.length > 0 && (
@@ -184,6 +188,20 @@ export const CloudPromptBar = memo(function CloudPromptBarComponent({
)}
+ + diff --git a/ui/src/components/agents/ported/Logo.tsx b/ui/src/components/agents/ported/Logo.tsx index 96afd0dc..c154e2ce 100644 --- a/ui/src/components/agents/ported/Logo.tsx +++ b/ui/src/components/agents/ported/Logo.tsx @@ -12,8 +12,13 @@ export function Logo() { ].join("\n"); return ( -
-      {ascii}
-    
+
+
+        {ascii}
+      
+
); } diff --git a/ui/src/routes/__root.tsx b/ui/src/routes/__root.tsx index 22110f4f..92205f66 100644 --- a/ui/src/routes/__root.tsx +++ b/ui/src/routes/__root.tsx @@ -17,7 +17,10 @@ export const Route = createRootRoute({ head: () => ({ meta: [ { charSet: "utf-8" }, - { name: "viewport", content: "width=device-width, initial-scale=1" }, + { + name: "viewport", + content: "width=device-width, initial-scale=1, maximum-scale=1", + }, { name: "theme-color", content: "#000000" }, { title: "open-swe" }, ], diff --git a/ui/vite.config.ts b/ui/vite.config.ts index 3334d38e..4a7948c8 100644 --- a/ui/vite.config.ts +++ b/ui/vite.config.ts @@ -20,6 +20,9 @@ const config = defineConfig({ injectRegister: false, registerType: "prompt", outDir: ".output/public", + devOptions: { + enabled: true, + }, integration: { closeBundleOrder: "pre", },