mirror of
https://github.com/aljazceru/goose.git
synced 2025-12-21 16:14:21 +01:00
styles: settings v2 (#2103)
This commit is contained in:
@@ -62,7 +62,7 @@ export default function Modal({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="fixed inset-0 bg-black/20 dark:bg-white/20 backdrop-blur-sm transition-colors animate-[fadein_200ms_ease-in_forwards] flex items-center justify-center p-4 z-[9999]"
|
className="fixed inset-0 bg-black/30 dark:bg-white/20 transition-colors animate-[fadein_200ms_ease-in_forwards] flex items-center justify-center p-4 z-[9999]"
|
||||||
onClick={handleBackdropClick}
|
onClick={handleBackdropClick}
|
||||||
style={{ isolation: 'isolate' }} /* Creates a new stacking context */
|
style={{ isolation: 'isolate' }} /* Creates a new stacking context */
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import { Card } from '../../ui/card';
|
|||||||
import { Button } from '../../ui/button';
|
import { Button } from '../../ui/button';
|
||||||
import { Input } from '../../ui/input';
|
import { Input } from '../../ui/input';
|
||||||
import { FullExtensionConfig, DEFAULT_EXTENSION_TIMEOUT } from '../../../extensions';
|
import { FullExtensionConfig, DEFAULT_EXTENSION_TIMEOUT } from '../../../extensions';
|
||||||
import { toast } from 'react-toastify';
|
import { Select } from '../../ui/Select';
|
||||||
import Select from 'react-select';
|
|
||||||
import { createDarkSelectStyles, darkSelectTheme } from '../../ui/select-styles';
|
import { createDarkSelectStyles, darkSelectTheme } from '../../ui/select-styles';
|
||||||
import { getApiUrl, getSecretKey } from '../../../config';
|
import { getApiUrl, getSecretKey } from '../../../config';
|
||||||
import { toastError } from '../../../toasts';
|
import { toastError } from '../../../toasts';
|
||||||
@@ -147,8 +146,6 @@ export function ManualExtensionModal({ isOpen, onClose, onSubmit }: ManualExtens
|
|||||||
onChange={(option) =>
|
onChange={(option) =>
|
||||||
setFormData({ ...formData, type: option?.value as FullExtensionConfig['type'] })
|
setFormData({ ...formData, type: option?.value as FullExtensionConfig['type'] })
|
||||||
}
|
}
|
||||||
styles={createDarkSelectStyles()}
|
|
||||||
theme={darkSelectTheme}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ export default function SettingsView({
|
|||||||
viewOptions: SettingsViewOptions;
|
viewOptions: SettingsViewOptions;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="h-screen w-full">
|
<div className="h-screen w-full animate-[fadein_200ms_ease-in_forwards]">
|
||||||
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
|
<div className="relative flex items-center h-[36px] w-full bg-bgSubtle"></div>
|
||||||
|
|
||||||
<ScrollArea className="h-full w-full">
|
<ScrollArea className="h-full w-full">
|
||||||
<div className="flex flex-col pb-24">
|
<div className="flex flex-col pb-24">
|
||||||
<div className="px-8 pt-6 pb-4">
|
<div className="px-8 pt-6 pb-4">
|
||||||
<BackButton onClick={() => onClose()} />
|
<BackButton onClick={() => onClose()} />
|
||||||
|
<h1 className="text-3xl font-medium text-textStandard mt-1">Settings</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Content Area */}
|
{/* Content Area */}
|
||||||
|
|||||||
@@ -113,11 +113,11 @@ export default function ExtensionsSection() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="extensions">
|
<section id="extensions" className="px-8">
|
||||||
<div className="flex justify-between items-center mb-6 px-8">
|
<div className="flex justify-between items-center mb-2">
|
||||||
<h1 className="text-3xl font-medium text-textStandard">Extensions</h1>
|
<h2 className="text-xl font-medium text-textStandard">Extensions</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-8">
|
<div className="border-b border-borderSubtle pb-8">
|
||||||
<p className="text-sm text-textStandard mb-6">
|
<p className="text-sm text-textStandard mb-6">
|
||||||
These extensions use the Model Context Protocol (MCP). They can expand Goose's
|
These extensions use the Model Context Protocol (MCP). They can expand Goose's
|
||||||
capabilities using three main components: Prompts, Resources, and Tools.
|
capabilities using three main components: Prompts, Resources, and Tools.
|
||||||
@@ -131,46 +131,46 @@ export default function ExtensionsSection() {
|
|||||||
|
|
||||||
<div className="flex gap-4 pt-4 w-full">
|
<div className="flex gap-4 pt-4 w-full">
|
||||||
<Button
|
<Button
|
||||||
className="flex items-center gap-2 flex-1 justify-center text-white dark:text-textSubtle bg-black dark:bg-white hover:bg-subtle"
|
className="flex items-center gap-2 justify-center text-white dark:text-textSubtle bg-bgAppInverse hover:bg-bgStandardInverse [&>svg]:!size-4"
|
||||||
onClick={() => setIsAddModalOpen(true)}
|
onClick={() => setIsAddModalOpen(true)}
|
||||||
>
|
>
|
||||||
<Plus className="h-4 w-4" />
|
<Plus className="h-4 w-4" />
|
||||||
Add custom extension
|
Add custom extension
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="flex items-center gap-2 flex-1 justify-center text-textSubtle bg-white dark:bg-black hover:bg-subtle dark:border dark:border-gray-500 dark:hover:border-gray-400"
|
className="flex items-center gap-2 justify-center text-textStandard bg-bgApp border border-borderSubtle hover:border-borderProminent hover:bg-bgApp [&>svg]:!size-4"
|
||||||
onClick={() => window.open('https://block.github.io/goose/v1/extensions/', '_blank')}
|
onClick={() => window.open('https://block.github.io/goose/v1/extensions/', '_blank')}
|
||||||
>
|
>
|
||||||
<GPSIcon size={18} />
|
<GPSIcon size={12} />
|
||||||
Visit Extensions
|
Browse extensions
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Modal for updating an existing extension */}
|
||||||
|
{isModalOpen && selectedExtension && (
|
||||||
|
<ExtensionModal
|
||||||
|
title="Update Extension"
|
||||||
|
initialData={extensionToFormData(selectedExtension)}
|
||||||
|
onClose={handleModalClose}
|
||||||
|
onSubmit={handleUpdateExtension}
|
||||||
|
onDelete={handleDeleteExtension}
|
||||||
|
submitLabel="Save Changes"
|
||||||
|
modalType={'edit'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Modal for adding a new extension */}
|
||||||
|
{isAddModalOpen && (
|
||||||
|
<ExtensionModal
|
||||||
|
title="Add custom extension"
|
||||||
|
initialData={getDefaultFormData()}
|
||||||
|
onClose={handleModalClose}
|
||||||
|
onSubmit={handleAddExtension}
|
||||||
|
submitLabel="Add Extension"
|
||||||
|
modalType={'add'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Modal for updating an existing extension */}
|
|
||||||
{isModalOpen && selectedExtension && (
|
|
||||||
<ExtensionModal
|
|
||||||
title="Update Extension"
|
|
||||||
initialData={extensionToFormData(selectedExtension)}
|
|
||||||
onClose={handleModalClose}
|
|
||||||
onSubmit={handleUpdateExtension}
|
|
||||||
onDelete={handleDeleteExtension}
|
|
||||||
submitLabel="Save Changes"
|
|
||||||
modalType={'edit'}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Modal for adding a new extension */}
|
|
||||||
{isAddModalOpen && (
|
|
||||||
<ExtensionModal
|
|
||||||
title="Add New Extension"
|
|
||||||
initialData={getDefaultFormData()}
|
|
||||||
onClose={handleModalClose}
|
|
||||||
onSubmit={handleAddExtension}
|
|
||||||
submitLabel="Add Extension"
|
|
||||||
modalType={'add'}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export default function EnvVarsSection({
|
|||||||
<label className="text-sm font-medium text-textStandard mb-2 block">
|
<label className="text-sm font-medium text-textStandard mb-2 block">
|
||||||
Environment Variables
|
Environment Variables
|
||||||
</label>
|
</label>
|
||||||
<p className="text-xs text-textSubtle mb-2">
|
<p className="text-xs text-textSubtle mb-4">
|
||||||
Add key-value pairs for environment variables. Click the "+" button to add after filling
|
Add key-value pairs for environment variables. Click the "+" button to add after filling
|
||||||
both fields.
|
both fields.
|
||||||
</p>
|
</p>
|
||||||
@@ -89,7 +89,7 @@ export default function EnvVarsSection({
|
|||||||
onChange={(e) => onChange(index, 'key', e.target.value)}
|
onChange={(e) => onChange(index, 'key', e.target.value)}
|
||||||
placeholder="Variable name"
|
placeholder="Variable name"
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-full border-borderSubtle text-textStandard',
|
'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
|
||||||
isFieldInvalid(index, 'key') && 'border-red-500 focus:border-red-500'
|
isFieldInvalid(index, 'key') && 'border-red-500 focus:border-red-500'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -100,7 +100,7 @@ export default function EnvVarsSection({
|
|||||||
onChange={(e) => onChange(index, 'value', e.target.value)}
|
onChange={(e) => onChange(index, 'value', e.target.value)}
|
||||||
placeholder="Value"
|
placeholder="Value"
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-full border-borderSubtle text-textStandard',
|
'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
|
||||||
isFieldInvalid(index, 'value') && 'border-red-500 focus:border-red-500'
|
isFieldInvalid(index, 'value') && 'border-red-500 focus:border-red-500'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -124,7 +124,7 @@ export default function EnvVarsSection({
|
|||||||
}}
|
}}
|
||||||
placeholder="Variable name"
|
placeholder="Variable name"
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-full border-borderStandard text-textStandard',
|
'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
|
||||||
invalidFields.key && 'border-red-500 focus:border-red-500'
|
invalidFields.key && 'border-red-500 focus:border-red-500'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -136,16 +136,16 @@ export default function EnvVarsSection({
|
|||||||
}}
|
}}
|
||||||
placeholder="Value"
|
placeholder="Value"
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-full border-borderStandard text-textStandard',
|
'w-full text-textStandard border-borderSubtle hover:border-borderStandard',
|
||||||
invalidFields.value && 'border-red-500 focus:border-red-500'
|
invalidFields.value && 'border-red-500 focus:border-red-500'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleAdd}
|
onClick={handleAdd}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="flex items-center justify-start gap-1 px-2 pr-4 text-s font-medium rounded-full dark:bg-slate-400 dark:text-gray-300 bg-gray-300 dark:bg-slate text-slate-400 dark:hover:bg-slate-300 hover:bg-gray-500 hover:text-white dark:hover:text-gray-900 transition-colors min-w-[60px] h-9"
|
className="flex items-center justify-start gap-1 px-2 pr-4 text-sm rounded-full text-textStandard bg-bgApp border border-borderSubtle hover:border-borderStandard transition-colors min-w-[60px] h-9 [&>svg]:!size-4"
|
||||||
>
|
>
|
||||||
<Plus className="h-3 w-3" /> Add
|
<Plus /> Add
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{validationError && <div className="mt-2 text-red-500 text-sm">{validationError}</div>}
|
{validationError && <div className="mt-2 text-red-500 text-sm">{validationError}</div>}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Input } from '../../../ui/input';
|
import { Input } from '../../../ui/input';
|
||||||
import Select from 'react-select';
|
import { Select } from '../../../ui/Select';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
interface ExtensionInfoFieldsProps {
|
interface ExtensionInfoFieldsProps {
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export default function ExtensionModal({
|
|||||||
<>
|
<>
|
||||||
<div className="w-full px-6 py-4 bg-red-900/20 border-t border-red-500/30">
|
<div className="w-full px-6 py-4 bg-red-900/20 border-t border-red-500/30">
|
||||||
<p className="text-red-400 text-sm mb-2">
|
<p className="text-red-400 text-sm mb-2">
|
||||||
Are you sure you want to delete "{formData.name}"? This action cannot be undone.
|
Are you sure you want to remove "{formData.name}"? This action cannot be undone.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
@@ -143,7 +143,7 @@ export default function ExtensionModal({
|
|||||||
}}
|
}}
|
||||||
className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-red-900/20 text-red-500 font-medium text-md"
|
className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-red-900/20 text-red-500 font-medium text-md"
|
||||||
>
|
>
|
||||||
<Trash2 className="h-4 w-4 mr-2" /> Confirm Delete
|
<Trash2 className="h-4 w-4 mr-2" /> Confirm removal
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setShowDeleteConfirmation(false)}
|
onClick={() => setShowDeleteConfirmation(false)}
|
||||||
@@ -159,9 +159,9 @@ export default function ExtensionModal({
|
|||||||
{modalType === 'edit' && onDelete && (
|
{modalType === 'edit' && onDelete && (
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setShowDeleteConfirmation(true)}
|
onClick={() => setShowDeleteConfirmation(true)}
|
||||||
className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-bgSubtle text-red-500 font-medium text-md"
|
className="w-full h-[60px] rounded-none border-b border-borderSubtle bg-transparent hover:bg-bgSubtle text-red-500 font-medium text-md [&>svg]:!size-4"
|
||||||
>
|
>
|
||||||
<Trash2 className="h-4 w-4 mr-2" /> Delete Extension
|
<Trash2 className="h-4 w-4 mr-2" /> Remove extension
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -29,25 +29,20 @@ export default function ExtensionTimeoutField({
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4 mb-6">
|
<div className="flex flex-col gap-4 mb-6">
|
||||||
{/* Row with Timeout and timeout input side by side */}
|
{/* Row with Timeout and timeout input side by side */}
|
||||||
<div className="flex justify-between gap-4">
|
<div className="flex flex-col">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<label className="text-sm font-medium mb-2 block text-textStandard">Timeout</label>
|
<label className="text-sm font-medium mb-2 block text-textStandard">Timeout</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Type Dropdown */}
|
<Input
|
||||||
<div className="w-[200px]">
|
value={timeout}
|
||||||
<div className="relative">
|
onChange={(e) => onChange('timeout', e.target.value)}
|
||||||
<Input
|
defaultValue={300}
|
||||||
value={timeout}
|
className={`${!submitAttempted || isTimeoutValid() ? 'border-borderSubtle' : 'border-red-500'} text-textStandard focus:border-borderStandard`}
|
||||||
onChange={(e) => onChange('timeout', e.target.value)}
|
/>
|
||||||
defaultValue={300}
|
{submitAttempted && !isTimeoutValid() && (
|
||||||
className={`${!submitAttempted || isTimeoutValid() ? 'border-borderSubtle' : 'border-red-500'} text-textStandard focus:border-borderStandard`}
|
<div className="absolute text-xs text-red-500 mt-1">Timeout </div>
|
||||||
/>
|
)}
|
||||||
{submitAttempted && !isTimeoutValid() && (
|
|
||||||
<div className="absolute text-xs text-red-500 mt-1">Timeout </div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -57,27 +57,34 @@ export default function ExtensionItem({ extension, onToggle, onConfigure }: Exte
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-lg border border-borderSubtle p-4 mb-2">
|
<div
|
||||||
<div className="flex items-center justify-between mb-2">
|
className="flex justify-between rounded-lg transition-colors border border-borderSubtle p-4 pt-3 hover:border-borderProminent hover:cursor-pointer"
|
||||||
<h3 className="font-medium text-textStandard">{getFriendlyTitle(extension)}</h3>
|
onClick={() => handleToggle(extension)}
|
||||||
<div className="flex items-center gap-2">
|
>
|
||||||
{/* Only show config button for non-builtin extensions */}
|
<div className="flex flex-col w-max-[90%]">
|
||||||
{extension.type !== 'builtin' && (
|
<h3 className="text-textStandard">{getFriendlyTitle(extension)}</h3>
|
||||||
<button
|
<p className="text-xs text-textSubtle">{renderFormattedSubtitle()}</p>
|
||||||
className="text-textSubtle hover:text-textStandard"
|
</div>
|
||||||
onClick={() => onConfigure(extension)}
|
|
||||||
>
|
<div
|
||||||
<Gear className="h-4 w-4" />
|
className="flex items-center justify-end gap-2 w-max-[10%]"
|
||||||
</button>
|
onClick={(e) => e.stopPropagation()}
|
||||||
)}
|
>
|
||||||
<Switch
|
{/* Only show config button for non-builtin extensions */}
|
||||||
checked={(isToggling && visuallyEnabled) || extension.enabled}
|
{extension.type !== 'builtin' && (
|
||||||
onCheckedChange={() => handleToggle(extension)}
|
<button
|
||||||
variant="mono"
|
className="text-textSubtle hover:text-textStandard"
|
||||||
/>
|
onClick={() => onConfigure(extension)}
|
||||||
</div>
|
>
|
||||||
|
<Gear className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<Switch
|
||||||
|
checked={(isToggling && visuallyEnabled) || extension.enabled}
|
||||||
|
onCheckedChange={() => handleToggle(extension)}
|
||||||
|
variant="mono"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-textSubtle">{renderFormattedSubtitle()}</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ interface ExtensionListProps {
|
|||||||
|
|
||||||
export default function ExtensionList({ extensions, onToggle, onConfigure }: ExtensionListProps) {
|
export default function ExtensionList({ extensions, onToggle, onConfigure }: ExtensionListProps) {
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-2 gap-6">
|
<div className="grid grid-cols-2 gap-2 mb-2">
|
||||||
{extensions.map((extension) => (
|
{extensions.map((extension) => (
|
||||||
<ExtensionItem
|
<ExtensionItem
|
||||||
key={extension.name}
|
key={extension.name}
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ export function ConfigureApproveMode({
|
|||||||
const approveModes: GooseMode[] = [
|
const approveModes: GooseMode[] = [
|
||||||
{
|
{
|
||||||
key: 'approve',
|
key: 'approve',
|
||||||
label: 'Manual Approval',
|
label: 'Manual approval',
|
||||||
description: 'All tools, extensions and file modifications will require human approval',
|
description: 'All tools, extensions and file modifications will require human approval',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'smart_approve',
|
key: 'smart_approve',
|
||||||
label: 'Smart Approval',
|
label: 'Smart approval',
|
||||||
description: 'Intelligently determine which actions need approval based on risk level ',
|
description: 'Intelligently determine which actions need approval based on risk level ',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -49,18 +49,16 @@ export function ConfigureApproveMode({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black/20 backdrop-blur-sm">
|
<div className="fixed inset-0 bg-black/30">
|
||||||
<Card className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[440px] bg-white dark:bg-gray-800 rounded-xl shadow-xl overflow-hidden p-[16px] pt-[24px] pb-0">
|
<Card className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[440px] bg-bgApp rounded-xl overflow-hidden p-[16px] pt-[24px] pb-0">
|
||||||
<div className="px-4 pb-0 space-y-6">
|
<div className="px-4 pb-0 space-y-6">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<h2 className="text-2xl font-regular dark:text-white text-gray-900">
|
<h2 className="text-2xl font-regular text-textStandard">Configure approve mode</h2>
|
||||||
Configure Approve Mode
|
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-[24px]">
|
<div className="mt-[24px]">
|
||||||
<p className="text-sm text-gray-500 dark:text-gray-400 mb-6">
|
<p className="text-sm text-textSubtle mb-6">
|
||||||
Approve requests can either be given to all tool requests or determine which actions
|
Approve requests can either be given to all tool requests or determine which actions
|
||||||
may need integration
|
may need integration
|
||||||
</p>
|
</p>
|
||||||
@@ -81,22 +79,22 @@ export function ConfigureApproveMode({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<div className="mt-[8px] ml-[-24px] mr-[-24px] pt-[16px]">
|
<div className="mt-[8px] ml-[-32px] mr-[-32px] pt-[16px]">
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={handleModeSubmit}
|
onClick={handleModeSubmit}
|
||||||
className="w-full h-[60px] rounded-none border-t dark:border-gray-600 text-lg hover:bg-gray-50 hover:dark:text-black dark:text-white dark:border-gray-600 font-regular"
|
className="w-full h-[60px] rounded-none border-t border-borderSubtle hover:bg-bgSubtle text-textStandard dark:border-gray-600 text-base font-regular"
|
||||||
>
|
>
|
||||||
{isSubmitting ? 'Saving...' : 'Save Mode'}
|
{isSubmitting ? 'Saving...' : 'Save'}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="w-full h-[60px] rounded-none border-t dark:border-gray-600 text-gray-400 hover:bg-gray-50 dark:border-gray-600 text-lg font-regular"
|
className="w-full h-[60px] rounded-none border-t border-borderSubtle text-textSubtle hover:bg-bgSubtle dark:border-gray-600 text-base font-regular"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -62,11 +62,11 @@ export const ModeSection = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="mode">
|
<section id="mode" className="px-8">
|
||||||
<div className="flex justify-between items-center mb-6 px-8">
|
<div className="flex justify-between items-center mb-2">
|
||||||
<h1 className="text-3xl font-medium text-textStandard">Mode</h1>
|
<h2 className="text-xl font-medium text-textStandard">Mode</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-8">
|
<div className="border-b border-borderSubtle pb-8">
|
||||||
<p className="text-sm text-textStandard mb-6">
|
<p className="text-sm text-textStandard mb-6">
|
||||||
Configure how Goose interacts with tools and extensions
|
Configure how Goose interacts with tools and extensions
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -11,22 +11,22 @@ export interface GooseMode {
|
|||||||
export const all_goose_modes: GooseMode[] = [
|
export const all_goose_modes: GooseMode[] = [
|
||||||
{
|
{
|
||||||
key: 'auto',
|
key: 'auto',
|
||||||
label: 'Completely Autonomous',
|
label: 'Completely autonomous',
|
||||||
description: 'Full file modification capabilities, edit, create, and delete files freely.',
|
description: 'Full file modification capabilities, edit, create, and delete files freely.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'approve',
|
key: 'approve',
|
||||||
label: 'Manual Approval',
|
label: 'Manual approval',
|
||||||
description: 'All tools, extensions and file modifications will require human approval',
|
description: 'All tools, extensions and file modifications will require human approval',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'smart_approve',
|
key: 'smart_approve',
|
||||||
label: 'Smart Approval',
|
label: 'Smart approval',
|
||||||
description: 'Intelligently determine which actions need approval based on risk level ',
|
description: 'Intelligently determine which actions need approval based on risk level ',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'chat',
|
key: 'chat',
|
||||||
label: 'Chat Only',
|
label: 'Chat only',
|
||||||
description: 'Engage with the selected provider without using tools or extensions.',
|
description: 'Engage with the selected provider without using tools or extensions.',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -89,20 +89,23 @@ export function ModeSelectionItem({
|
|||||||
}, [currentMode, mode.key]);
|
}, [currentMode, mode.key]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="group hover:cursor-pointer">
|
||||||
<div
|
<div
|
||||||
className="flex items-center justify-between p-2 text-textStandard hover:bg-bgSubtle transition-colors"
|
className="flex items-center justify-between text-textStandard mb-4"
|
||||||
onClick={() => handleModeChange(mode.key)}
|
onClick={() => handleModeChange(mode.key)}
|
||||||
>
|
>
|
||||||
<div>
|
<div className="flex">
|
||||||
<h3 className="text-sm font-light text-textStandard dark:text-gray-200">{mode.label}</h3>
|
<div>
|
||||||
{showDescription && (
|
<h3 className="text-textStandard dark:text-gray-200">{mode.label}</h3>
|
||||||
<p className="text-xs text-textSubtle dark:text-gray-400 mt-[2px]">
|
{showDescription && (
|
||||||
{mode.description}
|
<p className="text-xs text-textSubtle dark:text-gray-400 mt-[2px]">
|
||||||
</p>
|
{mode.description}
|
||||||
)}
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex items-center gap-3">
|
|
||||||
|
<div className="relative flex items-center gap-3 mr-4">
|
||||||
{!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && (
|
{!isApproveModeConfigure && (mode.key == 'approve' || mode.key == 'smart_approve') && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -121,10 +124,10 @@ export function ModeSelectionItem({
|
|||||||
className="peer sr-only"
|
className="peer sr-only"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="h-4 w-4 rounded-full border border-gray-400 dark:border-gray-500
|
className="h-4 w-4 rounded-full border border-borderStandard
|
||||||
peer-checked:border-[6px] peer-checked:border-black dark:peer-checked:border-white
|
peer-checked:border-[6px] peer-checked:border-black dark:peer-checked:border-white
|
||||||
peer-checked:bg-white dark:peer-checked:bg-black
|
peer-checked:bg-white dark:peer-checked:bg-black
|
||||||
transition-all duration-200 ease-in-out"
|
transition-all duration-200 ease-in-out group-hover:border-borderProminent"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -58,14 +58,14 @@ export default function ModelsSection({ setView }: ModelsSectionProps) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="models">
|
<section id="models" className="px-8">
|
||||||
<div className="flex justify-between items-center mb-6 px-8">
|
<div className="flex justify-between items-center mb-4">
|
||||||
<h1 className="text-3xl font-medium text-textStandard">Models</h1>
|
<h2 className="text-xl font-medium text-textStandard">Models</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-8">
|
<div className="border-b border-borderSubtle pb-8">
|
||||||
<div className="space-y-2">
|
<div className="">
|
||||||
<h3 className="font-medium text-textStandard">{model}</h3>
|
<h3 className="text-textStandard">{model}</h3>
|
||||||
<h4 className="font-medium text-textSubtle">{provider}</h4>
|
<h4 className="text-xs text-textSubtle">{provider}</h4>
|
||||||
</div>
|
</div>
|
||||||
<ModelSettingsButtons setView={setView} />
|
<ModelSettingsButtons setView={setView} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Button } from '../../../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
import { AddModelModal } from './AddModelModal';
|
import { AddModelModal } from './AddModelModal';
|
||||||
import { Gear } from '../../../icons';
|
|
||||||
import type { View } from '../../../../App';
|
import type { View } from '../../../../App';
|
||||||
|
import { ArrowLeftRight } from 'lucide-react';
|
||||||
|
|
||||||
interface AddModelButtonProps {
|
interface AddModelButtonProps {
|
||||||
setView: (view: View) => void;
|
setView: (view: View) => void;
|
||||||
@@ -14,11 +14,11 @@ export const AddModelButton = ({ setView }: AddModelButtonProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
className="flex items-center gap-2 flex-1 justify-center text-white dark:text-textSubtle bg-black dark:bg-white hover:bg-subtle"
|
className="flex items-center gap-2 justify-center text-white dark:text-textSubtle bg-bgAppInverse hover:bg-bgStandardInverse [&>svg]:!size-4"
|
||||||
onClick={() => setIsAddModelModalOpen(true)}
|
onClick={() => setIsAddModelModalOpen(true)}
|
||||||
>
|
>
|
||||||
<Gear className="h-4 w-4" />
|
<ArrowLeftRight />
|
||||||
Switch Models
|
Switch models
|
||||||
</Button>
|
</Button>
|
||||||
{isAddModelModalOpen ? (
|
{isAddModelModalOpen ? (
|
||||||
<AddModelModal setView={setView} onClose={() => setIsAddModelModalOpen(false)} />
|
<AddModelModal setView={setView} onClose={() => setIsAddModelModalOpen(false)} />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { ExternalLink, Plus } from 'lucide-react';
|
import { ArrowLeftRight, ExternalLink, Plus } from 'lucide-react';
|
||||||
|
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import { Button } from '../../../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
@@ -221,10 +221,10 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center gap-8">
|
<div className="flex flex-col items-center gap-8">
|
||||||
<div className="flex flex-col items-center gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<Plus size={24} className="text-textStandard" />
|
<ArrowLeftRight size={24} className="text-textStandard" />
|
||||||
<div className="text-textStandard font-medium text-base">Switch models</div>
|
<div className="text-textStandard font-medium text-base">Switch models</div>
|
||||||
<div className="text-textSubtle text-center text-md">
|
<div className="text-textSubtle text-md">
|
||||||
Configure your AI model providers by adding their API keys. Your keys are stored
|
Configure your AI model providers by adding their API keys. Your keys are stored
|
||||||
securely and encrypted locally.
|
securely and encrypted locally.
|
||||||
</div>
|
</div>
|
||||||
@@ -233,7 +233,7 @@ export const AddModelModal = ({ onClose, setView }: AddModelModalProps) => {
|
|||||||
href={QUICKSTART_GUIDE_URL}
|
href={QUICKSTART_GUIDE_URL}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="flex items-center justify-center text-textStandard font-medium text-sm"
|
className="flex items-center text-textStandard font-medium text-sm"
|
||||||
>
|
>
|
||||||
<ExternalLink size={16} className="mr-1" />
|
<ExternalLink size={16} className="mr-1" />
|
||||||
View quick start guide
|
View quick start guide
|
||||||
|
|||||||
@@ -10,16 +10,16 @@ interface ConfigureModelButtonsProps {
|
|||||||
|
|
||||||
export default function ModelSettingsButtons({ setView }: ConfigureModelButtonsProps) {
|
export default function ModelSettingsButtons({ setView }: ConfigureModelButtonsProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-4 pt-4 w-full">
|
<div className="flex gap-4 pt-4 ">
|
||||||
<AddModelButton setView={setView} />
|
<AddModelButton setView={setView} />
|
||||||
<Button
|
<Button
|
||||||
className="flex items-center gap-2 flex-1 justify-center text-textSubtle bg-white dark:bg-black hover:bg-subtle dark:border dark:border-gray-500 dark:hover:border-gray-400"
|
className="flex items-center gap-2 justify-center text-textStandard bg-bgApp border border-borderSubtle hover:border-borderProminent hover:bg-bgApp [&>svg]:!size-4"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setView('ConfigureProviders');
|
setView('ConfigureProviders');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Sliders className="h-4 w-4 rotate-90" />
|
<Sliders className="rotate-90" />
|
||||||
Configure Providers
|
Configure providers
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function CardContainer({
|
|||||||
}: CardContainerProps) {
|
}: CardContainerProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`relative h-full p-[2px] overflow-hidden rounded-[9px] group/card
|
className={`relative h-full p-[1px] overflow-hidden rounded-[9px] group/card
|
||||||
${
|
${
|
||||||
grayedOut
|
grayedOut
|
||||||
? 'bg-borderSubtle hover:bg-gray-700'
|
? 'bg-borderSubtle hover:bg-gray-700'
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ export default function SessionSharingSection() {
|
|||||||
return (
|
return (
|
||||||
<section id="session-sharing">
|
<section id="session-sharing">
|
||||||
{/*Title*/}
|
{/*Title*/}
|
||||||
<div className="flex justify-between items-center mb-6 px-8">
|
<div className="flex justify-between items-center mb-2 px-8">
|
||||||
<h1 className="text-3xl font-medium text-textStandard">Session sharing</h1>
|
<h2 className="text-xl font-medium text-textStandard">Session sharing</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="px-8">
|
<div className="px-8">
|
||||||
@@ -103,7 +103,7 @@ export default function SessionSharingSection() {
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Toggle for enabling session sharing */}
|
{/* Toggle for enabling session sharing */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<label className="text-sm font-medium text-textStandard cursor-pointer">
|
<label className="text-textStandard cursor-pointer">
|
||||||
{envBaseUrlShare
|
{envBaseUrlShare
|
||||||
? 'Session sharing has already been configured'
|
? 'Session sharing has already been configured'
|
||||||
: 'Enable session sharing'}
|
: 'Enable session sharing'}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const BackButton: React.FC<BackButtonProps> = ({
|
|||||||
className={`flex items-center text-${textSize} text-textSubtle group hover:text-textStandard ${className}`}
|
className={`flex items-center text-${textSize} text-textSubtle group hover:text-textStandard ${className}`}
|
||||||
>
|
>
|
||||||
<Back className={`${iconSize} group-hover:-translate-x-1 transition-all mr-1`} />
|
<Back className={`${iconSize} group-hover:-translate-x-1 transition-all mr-1`} />
|
||||||
{showText && <span>Exit</span>}
|
{showText && <span>Back</span>}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,12 +10,11 @@ export const Select = (props) => {
|
|||||||
container: () => 'w-full cursor-pointer relative z-[99999]',
|
container: () => 'w-full cursor-pointer relative z-[99999]',
|
||||||
indicatorSeparator: () => 'h-0',
|
indicatorSeparator: () => 'h-0',
|
||||||
control: ({ isFocused }) =>
|
control: ({ isFocused }) =>
|
||||||
`border-2 ${isFocused ? 'border-borderStandard' : 'border-borderSubtle'} focus:border-borderStandard hover:border-borderStandard rounded-md w-full px-4 py-2.5 text-sm text-textSubtle`,
|
`border ${isFocused ? 'border-borderStandard' : 'border-borderSubtle'} focus:border-borderStandard hover:border-borderStandard rounded-md w-full px-4 py-2 text-sm text-textSubtle hover:cursor-pointer`,
|
||||||
menu: () =>
|
menu: () =>
|
||||||
'mt-3 bg-bgStandard shadow-xl rounded-md text-textSubtle overflow-hidden relative z-[99999] select__menu',
|
'mt-1 bg-bgApp border border-borderStandard rounded-md text-textSubtle overflow-hidden relative z-[99999] select__menu',
|
||||||
menuPortal: () => 'z-[99999] select__menu',
|
menuPortal: () => 'z-[99999] select__menu',
|
||||||
option: () =>
|
option: () => 'py-2 px-4 hover:cursor-pointer hover:bg-bgSubtle text-textStandard text-sm',
|
||||||
'py-4 px-4 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 text-textProminent font-medium',
|
|
||||||
}}
|
}}
|
||||||
menuPortalTarget={document.body}
|
menuPortalTarget={document.body}
|
||||||
styles={{
|
styles={{
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
|||||||
import { cn } from '../../utils';
|
import { cn } from '../../utils';
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
'inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-6 [&_svg]:shrink-0',
|
'inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-6 [&_svg]:shrink-0',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'bg-gray-800 text-white rounded-full px-6 py-2 shadow hover:bg-gray-700',
|
default: 'bg-gray-800 text-white rounded-full px-6 py-2 hover:bg-gray-700',
|
||||||
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
||||||
outline:
|
outline:
|
||||||
'border border-gray-300 bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
|
'border border-gray-300 bg-background hover:bg-accent hover:text-accent-foreground',
|
||||||
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
|
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||||
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
||||||
link: 'text-primary underline-offset-4 hover:underline',
|
link: 'text-primary underline-offset-4 hover:underline',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export default {
|
|||||||
|
|
||||||
borderSubtle: 'var(--border-subtle)',
|
borderSubtle: 'var(--border-subtle)',
|
||||||
borderStandard: 'var(--border-standard)',
|
borderStandard: 'var(--border-standard)',
|
||||||
|
borderProminent: 'var(--border-prominent)',
|
||||||
|
|
||||||
textProminent: 'var(--text-prominent)',
|
textProminent: 'var(--text-prominent)',
|
||||||
textStandard: 'var(--text-standard)',
|
textStandard: 'var(--text-standard)',
|
||||||
|
|||||||
Reference in New Issue
Block a user