Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed OPENGUI.png
Binary file not shown.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@
"@opencode-ai/sdk": "^1.2.15",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-slot": "^1.2.4",

"@radix-ui/react-tabs": "^1.1.13",
"amadeus": "^11.0.0",

"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"katex": "^0.16.33",
Expand Down
2 changes: 0 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,5 +310,3 @@ export function App() {
</OpenCodeProvider>
);
}

export default App;
31 changes: 21 additions & 10 deletions src/components/AppSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ import { MergeDialog } from "./MergeDialog";
import { getColorBorderClass, SessionContextMenu } from "./SessionContextMenu";
import { WorktreeDialog } from "./WorktreeDialog";

/** @deprecated Use getProjectName from @/lib/utils instead. */
const projectName = (directory: string) => getProjectName(directory, directory);

/** Build a "create pull request" URL from a git remote URL and branch. */
function buildPRUrl(
remoteUrl: string,
Expand Down Expand Up @@ -209,9 +206,19 @@ export function AppSidebar() {
branch: string;
worktreePath: string;
} | null>(null);
const fixWithAiTimeoutRef = useRef<number | null>(null);
// Per-project: remote URL (for PR links)
const [remoteUrls, setRemoteUrls] = useState<Record<string, string>>({});

useEffect(() => {
return () => {
if (fixWithAiTimeoutRef.current !== null) {
window.clearTimeout(fixWithAiTimeoutRef.current);
fixWithAiTimeoutRef.current = null;
}
};
}, []);

/** Refresh git info for a project directory (is repo + worktree list + remote). */
const refreshGitInfo = useCallback(async (directory: string) => {
const git = window.electronAPI?.git;
Expand Down Expand Up @@ -384,7 +391,7 @@ export function AppSidebar() {
/>
)}
<span className="truncate min-w-0 flex-1">
{projectName(directory)}
{getProjectName(directory)}
</span>
{/* New session for this project */}
{isProjectConnected &&
Expand Down Expand Up @@ -537,7 +544,7 @@ export function AppSidebar() {
>
<span className="truncate">
{wt.branch ??
projectName(wt.path)}
getProjectName(wt.path)}
</span>
</ContextMenu.SubTrigger>
<ContextMenu.Portal>
Expand Down Expand Up @@ -672,7 +679,7 @@ export function AppSidebar() {
>
<MessageSquare className="size-3.5 shrink-0" />
<span className="truncate">
{projectName(directory)}
{getProjectName(directory)}
</span>
<span className="ml-auto text-[10px] text-muted-foreground">
main
Expand All @@ -692,7 +699,7 @@ export function AppSidebar() {
>
<GitBranch className="size-3.5 shrink-0" />
<span className="truncate">
{projectName(wtDir)}
{getProjectName(wtDir)}
</span>
</button>
))}
Expand Down Expand Up @@ -730,7 +737,7 @@ export function AppSidebar() {
worktreeParents[session.directory] ===
directory;
const worktreeBranch = isWorktreeSession
? projectName(session.directory)
? getProjectName(session.directory)
: null;
return (
<SessionContextMenu
Expand Down Expand Up @@ -940,7 +947,7 @@ export function AppSidebar() {
>
<div className="mb-1 flex items-center gap-2 px-2 py-1">
<div className="truncate text-sm font-medium">
{projectName(projectPopover.directory)}
{getProjectName(projectPopover.directory)}
</div>
<div className="ml-auto text-xs text-muted-foreground">
{popoverSessions.length}
Expand Down Expand Up @@ -1090,11 +1097,15 @@ export function AppSidebar() {
// Start a new session in the main directory and send the conflict resolution prompt
startDraftSession(mergeInfo.mainDir);
// Use a small delay so the draft session is active before sending
setTimeout(() => {
if (fixWithAiTimeoutRef.current !== null) {
window.clearTimeout(fixWithAiTimeoutRef.current);
}
fixWithAiTimeoutRef.current = window.setTimeout(() => {
const fileList = conflicts.map((f) => `- ${f}`).join("\n");
sendPrompt(
`There are git merge conflicts from merging branch "${mergeInfo.branch}" into the current branch.\n\nThe following files have unresolved conflicts:\n${fileList}\n\nPlease resolve all merge conflicts in these files. Remove all conflict markers (<<<<<<, ======, >>>>>>) and produce the correct merged code. After resolving all conflicts, stage the resolved files with \`git add\` for each file.`,
);
fixWithAiTimeoutRef.current = null;
}, POST_MERGE_DELAY_MS);
}}
/>
Expand Down
4 changes: 1 addition & 3 deletions src/components/ConnectionPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import { Spinner } from "@/components/ui/spinner";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
hasAnyConnection,
NOTIFICATIONS_ENABLED_KEY,
useActions,
useConnectionState,
Expand Down Expand Up @@ -114,9 +113,8 @@ type ServerState =
| "error";

function AddProjectForm({ onDone }: { onDone: () => void }) {
const { addProject, connectToProject, disconnect, clearError } = useActions();
const { addProject, connectToProject, clearError } = useActions();
const { connections } = useConnectionState();
const isConnected = hasAnyConnection(connections);
const isElectron = !!window.electronAPI;

const [url, setUrl] = useState(
Expand Down
2 changes: 1 addition & 1 deletion src/components/MergeDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type MergeState =
| { step: "conflicts"; files: string[] }
| { step: "error"; message: string };

export interface MergeDialogProps {
interface MergeDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
/** The main project directory (merge target). */
Expand Down
2 changes: 1 addition & 1 deletion src/components/QueueList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import * as React from "react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

export interface QueueItem {
interface QueueItem {
id: string;
text: string;
variant?: string;
Expand Down
2 changes: 1 addition & 1 deletion src/components/SessionContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { cn } from "@/lib/utils";
// Color config
// ---------------------------------------------------------------------------

export const SESSION_COLORS: {
const SESSION_COLORS: {
value: SessionColor;
label: string;
className: string;
Expand Down
4 changes: 2 additions & 2 deletions src/components/provider-icons/ProviderIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import type { SVGAttributes } from "react";
import sprite from "./sprite.svg";
import { type ProviderIconName, providerIconNames } from "./types";

export type ProviderIconProps = SVGAttributes<SVGSVGElement> & {
type ProviderIconProps = SVGAttributes<SVGSVGElement> & {
/** Provider ID (must match a key in the sprite sheet). */
provider: string;
};

const iconNameSet = new Set<string>(providerIconNames);

/** Resolve a provider ID to a valid icon name, falling back to "synthetic". */
export function resolveProviderIcon(id: string): ProviderIconName {
function resolveProviderIcon(id: string): ProviderIconName {
if (iconNameSet.has(id)) return id as ProviderIconName;
return "synthetic";
}
Expand Down
5 changes: 1 addition & 4 deletions src/components/provider-icons/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
export type { ProviderIconProps } from "./ProviderIcon";
export { ProviderIcon, resolveProviderIcon } from "./ProviderIcon";
export type { ProviderIconName } from "./types";
export { providerIconNames } from "./types";
export { ProviderIcon } from "./ProviderIcon";
7 changes: 3 additions & 4 deletions src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@ const badgeVariants = cva(
},
);

export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
type BadgeProps = React.HTMLAttributes<HTMLDivElement> &
VariantProps<typeof badgeVariants>;

function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
);
}

export { Badge, badgeVariants };
export { Badge };
2 changes: 1 addition & 1 deletion src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ function Button({
);
}

export { Button, buttonVariants };
export { Button };
30 changes: 1 addition & 29 deletions src/components/ui/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,6 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
);
}

function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
);
}

function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
Expand All @@ -71,22 +61,4 @@ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
);
}

function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-footer"
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
{...props}
/>
);
}

export {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
};
export { Card, CardAction, CardContent, CardHeader, CardTitle };
31 changes: 0 additions & 31 deletions src/components/ui/collapsible.tsx

This file was deleted.

9 changes: 0 additions & 9 deletions src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ function DialogPortal({
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
}

function DialogClose({
...props
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
}

function DialogOverlay({
className,
...props
Expand Down Expand Up @@ -143,13 +137,10 @@ function DialogDescription({

export {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogOverlay,
DialogPortal,
DialogTitle,
DialogTrigger,
};
33 changes: 1 addition & 32 deletions src/components/ui/sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,6 @@ function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />;
}

function SheetTrigger({
...props
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
}

function SheetClose({
...props
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
}

function SheetPortal({
...props
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
Expand Down Expand Up @@ -93,16 +81,6 @@ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
);
}

function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-footer"
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
{...props}
/>
);
}

function SheetTitle({
className,
...props
Expand All @@ -129,13 +107,4 @@ function SheetDescription({
);
}

export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
};
export { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle };
Loading
Loading