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
4 changes: 2 additions & 2 deletions frontend/app/aipanel/aidroppedfiles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const AIDroppedFiles = memo(({ model }: AIDroppedFilesProps) => {
<div className="p-2 border-b border-gray-600">
<div className="flex gap-2 overflow-x-auto pb-1">
{droppedFiles.map((file) => (
<div key={file.id} className="relative bg-gray-700 rounded-lg p-2 min-w-20 flex-shrink-0 group">
<div key={file.id} className="relative bg-zinc-700 rounded-lg p-2 min-w-20 flex-shrink-0 group">
<button
onClick={() => model.removeFile(file.id)}
className="absolute top-1 right-1 w-4 h-4 bg-red-500 hover:bg-red-600 rounded-full flex items-center justify-center text-white text-xs opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer"
Expand All @@ -40,7 +40,7 @@ export const AIDroppedFiles = memo(({ model }: AIDroppedFilesProps) => {
/>
</div>
) : (
<div className="w-12 h-12 mb-1 flex items-center justify-center bg-gray-600 rounded">
<div className="w-12 h-12 mb-1 flex items-center justify-center bg-zinc-600 rounded">
<i
className={cn("fa text-lg text-gray-300", getFileIcon(file.name, file.type))}
></i>
Expand Down
6 changes: 3 additions & 3 deletions frontend/app/aipanel/aifeedbackbuttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const AIFeedbackButtons = memo(({ messageText }: AIFeedbackButtonsProps)
"p-1.5 rounded cursor-pointer transition-colors",
thumbsUpClicked
? "text-accent"
: "text-secondary hover:bg-gray-700 hover:text-primary"
: "text-secondary hover:bg-zinc-700 hover:text-primary"
)}
title="Good Response"
>
Expand All @@ -60,7 +60,7 @@ export const AIFeedbackButtons = memo(({ messageText }: AIFeedbackButtonsProps)
"p-1.5 rounded cursor-pointer transition-colors",
thumbsDownClicked
? "text-accent"
: "text-secondary hover:bg-gray-700 hover:text-primary"
: "text-secondary hover:bg-zinc-700 hover:text-primary"
)}
title="Bad Response"
>
Expand All @@ -73,7 +73,7 @@ export const AIFeedbackButtons = memo(({ messageText }: AIFeedbackButtonsProps)
"p-1.5 rounded cursor-pointer transition-colors",
copied
? "text-success"
: "text-secondary hover:bg-gray-700 hover:text-primary"
: "text-secondary hover:bg-zinc-700 hover:text-primary"
)}
title="Copy Message"
>
Expand Down
6 changes: 3 additions & 3 deletions frontend/app/aipanel/aimessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ const UserMessageFiles = memo(({ fileParts }: UserMessageFilesProps) => {
<div className="mt-2 pt-2 border-t border-gray-600">
<div className="flex gap-2 overflow-x-auto pb-1">
{fileParts.map((file, index) => (
<div key={index} className="relative bg-gray-700 rounded-lg p-2 min-w-20 flex-shrink-0">
<div key={index} className="relative bg-zinc-700 rounded-lg p-2 min-w-20 flex-shrink-0">
<div className="flex flex-col items-center text-center">
<div className="w-12 h-12 mb-1 flex items-center justify-center bg-gray-600 rounded overflow-hidden">
<div className="w-12 h-12 mb-1 flex items-center justify-center bg-zinc-600 rounded overflow-hidden">
{file.data?.previewurl ? (
<img
src={file.data.previewurl}
Expand Down Expand Up @@ -223,7 +223,7 @@ export const AIMessage = memo(({ message, isStreaming }: AIMessageProps) => {
className={cn(
"px-2 rounded-lg [&>*:first-child]:!mt-0",
message.role === "user"
? "py-2 bg-accent-800 text-white max-w-[calc(100%-50px)]"
? "py-2 bg-zinc-700/60 text-white max-w-[calc(100%-50px)]"
: "min-w-[min(100%,500px)]"
)}
>
Expand Down
13 changes: 8 additions & 5 deletions frontend/app/aipanel/aimode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const AIModeMenuItem = memo(({ config, isSelected, isDisabled, onClick, isFirst,
className={cn(
"w-full flex flex-col gap-0.5 px-3 transition-colors text-left",
isFirst ? "pt-1 pb-0.5" : isLast ? "pt-0.5 pb-1" : "pt-0.5 pb-0.5",
isDisabled ? "text-gray-500" : "text-gray-300 hover:bg-gray-700 cursor-pointer"
isDisabled ? "text-zinc-500" : "text-zinc-300 hover:bg-zinc-700 cursor-pointer"
)}
>
<div className="flex items-center gap-2 w-full">
Expand Down Expand Up @@ -109,7 +109,10 @@ function computeCompatibleSections(
return sections;
}

function computeWaveCloudSections(waveProviderConfigs: AIModeConfigWithMode[], otherProviderConfigs: AIModeConfigWithMode[]): ConfigSection[] {
function computeWaveCloudSections(
waveProviderConfigs: AIModeConfigWithMode[],
otherProviderConfigs: AIModeConfigWithMode[]
): ConfigSection[] {
const sections: ConfigSection[] = [];

if (waveProviderConfigs.length > 0) {
Expand Down Expand Up @@ -204,7 +207,7 @@ export const AIModeDropdown = memo(({ compatibilityMode = false }: AIModeDropdow
onClick={() => setIsOpen(!isOpen)}
className={cn(
"group flex items-center gap-1.5 px-2 py-1 text-xs text-gray-300 hover:text-white rounded transition-colors cursor-pointer border border-gray-600/50",
isOpen ? "bg-gray-700" : "bg-gray-800/50 hover:bg-gray-700"
isOpen ? "bg-zinc-700" : "bg-zinc-800/50 hover:bg-zinc-700"
)}
title={`AI Mode: ${displayName}`}
>
Expand Down Expand Up @@ -234,7 +237,7 @@ export const AIModeDropdown = memo(({ compatibilityMode = false }: AIModeDropdow
{isOpen && (
<>
<div className="fixed inset-0 z-40" onClick={() => setIsOpen(false)} />
<div className="absolute top-full left-0 mt-1 bg-gray-800 border border-gray-600 rounded shadow-lg z-50 min-w-[280px]">
<div className="absolute top-full left-0 mt-1 bg-zinc-800 border border-zinc-600 rounded shadow-lg z-50 min-w-[280px]">
{sections.map((section, sectionIndex) => {
const isFirstSection = sectionIndex === 0;
const isLastSection = sectionIndex === sections.length - 1;
Expand Down Expand Up @@ -284,7 +287,7 @@ export const AIModeDropdown = memo(({ compatibilityMode = false }: AIModeDropdow
<div className="border-t border-gray-600 my-1" />
<button
onClick={handleConfigureClick}
className="w-full flex items-center gap-2 px-3 pt-1 pb-2 text-gray-300 hover:bg-gray-700 cursor-pointer transition-colors text-left"
className="w-full flex items-center gap-2 px-3 pt-1 pb-2 text-gray-300 hover:bg-zinc-700 cursor-pointer transition-colors text-left"
>
<i className={makeIconClass("gear", false)}></i>
<span className="text-sm">Configure Modes</span>
Expand Down
6 changes: 3 additions & 3 deletions frontend/app/aipanel/aipanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const KeyCap = memo(({ children, className }: { children: React.ReactNode; class
return (
<kbd
className={cn(
"px-1.5 py-0.5 text-xs bg-gray-700 border border-gray-600 rounded-sm shadow-sm font-mono",
"px-1.5 py-0.5 text-xs bg-zinc-700 border border-zinc-600 rounded-sm shadow-sm font-mono",
className
)}
>
Expand Down Expand Up @@ -483,9 +483,9 @@ const AIPanelComponentInner = memo(() => {
ref={containerRef}
data-waveai-panel="true"
className={cn(
"@container bg-gray-900 flex flex-col relative",
"@container bg-zinc-900/70 flex flex-col relative",
model.inBuilder ? "mt-0 h-full" : "mt-1 h-[calc(100%-4px)]",
(isDragOver || isReactDndDragOver) && "bg-gray-800 border-accent",
(isDragOver || isReactDndDragOver) && "bg-zinc-800 border-accent",
isFocused ? "border-2 border-accent" : "border-2 border-transparent"
)}
style={{
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/aipanel/aipanelheader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const AIPanelHeader = memo(() => {
}, 0);
}}
className={`relative inline-flex h-6 w-14 items-center rounded-full transition-colors cursor-pointer ${
widgetAccess ? "bg-accent-500" : "bg-gray-600"
widgetAccess ? "bg-accent-600" : "bg-zinc-600"
}`}
title={`Widget Access ${widgetAccess ? "ON" : "OFF"}`}
>
Expand All @@ -53,7 +53,7 @@ export const AIPanelHeader = memo(() => {
/>
<span
className={`relative z-10 text-xs text-white transition-all ${
widgetAccess ? "ml-2.5 mr-6 text-left font-bold" : "ml-6 mr-1 text-right"
widgetAccess ? "ml-2.5 mr-6 text-left" : "ml-6 mr-1 text-right"
}`}
>
{widgetAccess ? "ON" : "OFF"}
Expand Down
24 changes: 13 additions & 11 deletions frontend/app/aipanel/aipanelinput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,20 @@ export const AIPanelInput = memo(({ onSubmit, status, model }: AIPanelInputProps
model.requestWaveAIFocus();
}, [model]);

const handleBlur = useCallback((e: React.FocusEvent) => {
if (e.relatedTarget === null) {
return;
}
const handleBlur = useCallback(
(e: React.FocusEvent) => {
if (e.relatedTarget === null) {
return;
}

if (waveAIHasFocusWithin(e.relatedTarget)) {
return;
}
if (waveAIHasFocusWithin(e.relatedTarget)) {
return;
}

model.requestNodeFocus();
}, [model]);
model.requestNodeFocus();
},
[model]
);

useEffect(() => {
resizeTextarea();
Expand Down Expand Up @@ -140,8 +143,7 @@ export const AIPanelInput = memo(({ onSubmit, status, model }: AIPanelInputProps
onBlur={handleBlur}
placeholder={model.inBuilder ? "What would you like to build..." : "Ask Wave AI anything..."}
className={cn(
"w-full text-white px-2 py-2 pr-5 focus:outline-none resize-none overflow-auto",
isFocused ? "bg-accent-900/50" : "bg-gray-800"
"w-full text-white px-2 py-2 pr-5 focus:outline-none resize-none overflow-auto bg-zinc-800/50"
)}
style={{ fontSize: "13px" }}
rows={2}
Expand Down
99 changes: 6 additions & 93 deletions frontend/app/aipanel/aitooluse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { cn, fireAndForget } from "@/util/util";
import { useAtomValue } from "jotai";
import { memo, useEffect, useRef, useState } from "react";
import { WaveUIMessagePart } from "./aitypes";
import { RestoreBackupModal } from "./restorebackupmodal";
import { WaveAIModel } from "./waveai-model";

// matches pkg/filebackup/filebackup.go
Expand Down Expand Up @@ -180,7 +181,7 @@ const AIToolUseBatch = memo(({ parts, isStreaming }: AIToolUseBatchProps) => {
};

return (
<div className="flex items-start gap-2 p-2 rounded bg-gray-800 border border-gray-700">
<div className="flex items-start gap-2 p-2 rounded bg-zinc-800/60 border border-zinc-700">
<div className="flex-1">
<div className="font-semibold">Reading Files</div>
<div className="mt-1 space-y-0.5">
Expand All @@ -198,94 +199,6 @@ const AIToolUseBatch = memo(({ parts, isStreaming }: AIToolUseBatchProps) => {

AIToolUseBatch.displayName = "AIToolUseBatch";

interface RestoreBackupModalProps {
part: WaveUIMessagePart & { type: "data-tooluse" };
}

const RestoreBackupModal = memo(({ part }: RestoreBackupModalProps) => {
const model = WaveAIModel.getInstance();
const toolData = part.data;
const status = useAtomValue(model.restoreBackupStatus);
const error = useAtomValue(model.restoreBackupError);

const formatTimestamp = (ts: number) => {
if (!ts) return "";
const date = new Date(ts);
return date.toLocaleString();
};

const handleConfirm = () => {
recordTEvent("waveai:revertfile", { "waveai:action": "revertfile:confirm" });
model.restoreBackup(toolData.toolcallid, toolData.writebackupfilename, toolData.inputfilename);
};

const handleCancel = () => {
recordTEvent("waveai:revertfile", { "waveai:action": "revertfile:cancel" });
model.closeRestoreBackupModal();
};

const handleClose = () => {
model.closeRestoreBackupModal();
};

if (status === "success") {
return (
<Modal className="restore-backup-modal pb-5 pr-5" onClose={handleClose} onOk={handleClose} okLabel="Close">
<div className="flex flex-col gap-4 pt-4 pb-4 max-w-xl">
<div className="font-semibold text-lg text-green-500">Backup Successfully Restored</div>
<div className="text-sm text-gray-300 leading-relaxed">
The file <span className="font-mono text-white break-all">{toolData.inputfilename}</span> has
been restored to its previous state.
</div>
</div>
</Modal>
);
}

if (status === "error") {
return (
<Modal className="restore-backup-modal pb-5 pr-5" onClose={handleClose} onOk={handleClose} okLabel="Close">
<div className="flex flex-col gap-4 pt-4 pb-4 max-w-xl">
<div className="font-semibold text-lg text-red-500">Failed to Restore Backup</div>
<div className="text-sm text-gray-300 leading-relaxed">
An error occurred while restoring the backup:
</div>
<div className="text-sm text-red-400 font-mono bg-gray-800 p-3 rounded break-all">{error}</div>
</div>
</Modal>
);
}

const isProcessing = status === "processing";

return (
<Modal
className="restore-backup-modal pb-5 pr-5"
onClose={handleCancel}
onCancel={handleCancel}
onOk={handleConfirm}
okLabel={isProcessing ? "Restoring..." : "Confirm Restore"}
cancelLabel="Cancel"
okDisabled={isProcessing}
cancelDisabled={isProcessing}
>
<div className="flex flex-col gap-4 pt-4 pb-4 max-w-xl">
<div className="font-semibold text-lg">Restore File Backup</div>
<div className="text-sm text-gray-300 leading-relaxed">
This will restore <span className="font-mono text-white break-all">{toolData.inputfilename}</span>{" "}
to its state before this edit was made
{toolData.runts && <span> ({formatTimestamp(toolData.runts)})</span>}.
</div>
<div className="text-sm text-gray-300 leading-relaxed">
Any changes made by this edit and subsequent edits will be lost.
</div>
</div>
</Modal>
);
});

RestoreBackupModal.displayName = "RestoreBackupModal";

interface AIToolUseProps {
part: WaveUIMessagePart & { type: "data-tooluse" };
isStreaming: boolean;
Expand Down Expand Up @@ -381,7 +294,7 @@ const AIToolUse = memo(({ part, isStreaming }: AIToolUseProps) => {

return (
<div
className={cn("flex flex-col gap-1 p-2 rounded bg-gray-800 border border-gray-700", statusColor)}
className={cn("flex flex-col gap-1 p-2 rounded bg-zinc-800/60 border border-zinc-700", statusColor)}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
Expand All @@ -399,7 +312,7 @@ const AIToolUse = memo(({ part, isStreaming }: AIToolUseProps) => {
recordTEvent("waveai:revertfile", { "waveai:action": "revertfile:open" });
model.openRestoreBackupModal(toolData.toolcallid);
}}
className="flex-shrink-0 px-1.5 py-0.5 border border-gray-600 hover:border-gray-500 hover:bg-gray-700 rounded cursor-pointer transition-colors flex items-center gap-1 text-gray-400"
className="flex-shrink-0 px-1.5 py-0.5 border border-zinc-600 hover:border-zinc-500 hover:bg-zinc-700 rounded cursor-pointer transition-colors flex items-center gap-1 text-zinc-400"
title="Restore backup file"
>
<span className="text-xs">Revert File</span>
Expand All @@ -409,7 +322,7 @@ const AIToolUse = memo(({ part, isStreaming }: AIToolUseProps) => {
{isFileWriteTool && toolData.inputfilename && (
<button
onClick={handleOpenDiff}
className="flex-shrink-0 px-1.5 py-0.5 border border-gray-600 hover:border-gray-500 hover:bg-gray-700 rounded cursor-pointer transition-colors flex items-center gap-1 text-gray-400"
className="flex-shrink-0 px-1.5 py-0.5 border border-zinc-600 hover:border-zinc-500 hover:bg-zinc-700 rounded cursor-pointer transition-colors flex items-center gap-1 text-zinc-400"
title="Open in diff viewer"
>
<span className="text-xs">Show Diff</span>
Expand Down Expand Up @@ -441,7 +354,7 @@ const AIToolProgress = memo(({ part }: AIToolProgressProps) => {
const progressData = part.data;

return (
<div className="flex flex-col gap-1 p-2 rounded bg-gray-800 border border-gray-700">
<div className="flex flex-col gap-1 p-2 rounded bg-zinc-800/60 border border-zinc-700">
<div className="flex items-center gap-2">
<i className="fa fa-spinner fa-spin text-gray-400"></i>
<div className="font-semibold">{progressData.toolname}</div>
Expand Down
Loading
Loading