{hasMessages ? (
diff --git a/ui/src/components/agents/AgentsHome.tsx b/ui/src/components/agents/AgentsHome.tsx
index ce2f69c0..5b6b5368 100644
--- a/ui/src/components/agents/AgentsHome.tsx
+++ b/ui/src/components/agents/AgentsHome.tsx
@@ -8,6 +8,7 @@ import { SlackConnectDialog } from "@/components/agents/SlackConnectDialog"
import { Logo } from "@/components/agents/ported/Logo"
import { useAgentThreads, useCreateAgentThread } from "@/lib/agents/queries"
import { useModelOptions } from "@/lib/agents/useModelOptions"
+import { useProfile, useRepos } from "@/lib/profile"
export function AgentsHome() {
const threadsQuery = useAgentThreads()
@@ -16,6 +17,13 @@ export function AgentsHome() {
const { models, defaultSelection } = useModelOptions()
const [selection, setSelection] = useState(null)
+ const reposQuery = useRepos()
+ const profileQuery = useProfile()
+ // undefined = untouched (fall back to the profile default); null = explicitly "no repo".
+ const [repoOverride, setRepoOverride] = useState(undefined)
+ const repo =
+ repoOverride === undefined ? (profileQuery.data?.default_repo ?? null) : repoOverride
+
useEffect(() => {
if (selection === null && defaultSelection) setSelection(defaultSelection)
}, [defaultSelection, selection])
@@ -30,6 +38,7 @@ export function AgentsHome() {
onSubmit={(prompt) =>
createThread.mutate({
prompt,
+ repo,
model_id: selection?.modelId ?? null,
effort: selection?.effort ?? null,
})
@@ -38,6 +47,9 @@ export function AgentsHome() {
models={models}
selection={selection ?? defaultSelection}
onSelectionChange={setSelection}
+ repos={reposQuery.data?.repositories}
+ selectedRepo={repo}
+ onRepoChange={setRepoOverride}
/>
diff --git a/ui/src/components/agents/ported/CloudPromptBar.tsx b/ui/src/components/agents/ported/CloudPromptBar.tsx
index 598f4bd4..4bb973ea 100644
--- a/ui/src/components/agents/ported/CloudPromptBar.tsx
+++ b/ui/src/components/agents/ported/CloudPromptBar.tsx
@@ -1,4 +1,5 @@
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
+import { CaretDownIcon, FolderIcon } from "@phosphor-icons/react";
import type { ModelOption } from "@/lib/api";
import {
@@ -18,6 +19,10 @@ export interface CloudPromptBarProps {
models?: ModelOption[];
selection?: ModelSelection | null;
onSelectionChange?: (next: ModelSelection) => void;
+ /** Repos the user can target. When provided with onRepoChange, a repo picker is shown. */
+ repos?: Array<{ full_name: string }>;
+ selectedRepo?: string | null;
+ onRepoChange?: (repo: string | null) => void;
}
/** Web-adapted PromptBar from open-swe-app — local state, no Electron/Zustand deps. */
@@ -30,11 +35,25 @@ export const CloudPromptBar = memo(function CloudPromptBar({
models = [],
selection = null,
onSelectionChange,
+ repos,
+ selectedRepo = null,
+ onRepoChange,
}: CloudPromptBarProps) {
const [value, setValue] = useState("");
const [modelDropdownOpen, setModelDropdownOpen] = useState(false);
+ const [repoDropdownOpen, setRepoDropdownOpen] = useState(false);
+ const [repoQuery, setRepoQuery] = useState("");
const inputRef = useRef
(null);
const modelDropdownRef = useRef(null);
+ const repoDropdownRef = useRef(null);
+
+ const repoPickerEnabled = !!onRepoChange;
+ const filteredRepos = useMemo(() => {
+ const all = repos ?? [];
+ const q = repoQuery.trim().toLowerCase();
+ if (!q) return all;
+ return all.filter((r) => r.full_name.toLowerCase().includes(q));
+ }, [repos, repoQuery]);
const combos = useMemo(() => {
const list: ModelSelection[] = [];
@@ -67,9 +86,13 @@ export const CloudPromptBar = memo(function CloudPromptBar({
useEffect(() => {
function handleClickOutside(e: MouseEvent) {
- if (modelDropdownRef.current && !modelDropdownRef.current.contains(e.target as Node)) {
+ const target = e.target as Node;
+ if (modelDropdownRef.current && !modelDropdownRef.current.contains(target)) {
setModelDropdownOpen(false);
}
+ if (repoDropdownRef.current && !repoDropdownRef.current.contains(target)) {
+ setRepoDropdownOpen(false);
+ }
}
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
@@ -86,6 +109,82 @@ export const CloudPromptBar = memo(function CloudPromptBar({
return (
+ {repoPickerEnabled && (
+
+
+
+ {repoDropdownOpen && (
+
+
setRepoQuery(e.target.value)}
+ placeholder="Search repositories…"
+ className="w-full border-b border-[var(--ui-border)] bg-transparent px-3 py-2 text-[color:var(--ui-text)] outline-none placeholder:text-[color:var(--ui-text-dim)]"
+ />
+
+
+ {filteredRepos.length === 0 ? (
+
No matches
+ ) : (
+ filteredRepos.map((repo) => {
+ const selected = repo.full_name === selectedRepo;
+ return (
+
+ );
+ })
+ )}
+
+
+ )}
+
+
+ )}