Skip to content
Open
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
88 changes: 88 additions & 0 deletions electron/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
Menu,
nativeTheme,
protocol,
safeStorage,
session,
shell,
} from 'electron';
Expand Down Expand Up @@ -2298,6 +2299,93 @@ function registerIpcHandlers() {
}
});

// ==================== saved credentials handler ====================
const CREDENTIALS_FILE = path.join(
os.homedir(),
'.eigent',
'saved_credentials.enc'
);

const readSavedCredentials = (): Array<{
email: string;
password: string;
}> => {
try {
if (
!fs.existsSync(CREDENTIALS_FILE) ||
!safeStorage.isEncryptionAvailable()
) {
return [];
}
const encrypted = fs.readFileSync(CREDENTIALS_FILE);
const decrypted = safeStorage.decryptString(encrypted);
return JSON.parse(decrypted);
} catch {
return [];
}
};

const writeSavedCredentials = (
credentials: Array<{ email: string; password: string }>
) => {
if (!safeStorage.isEncryptionAvailable()) {
throw new Error('Encryption not available');
}
const dir = path.dirname(CREDENTIALS_FILE);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
const encrypted = safeStorage.encryptString(JSON.stringify(credentials));
fs.writeFileSync(CREDENTIALS_FILE, encrypted);
fs.chmodSync(CREDENTIALS_FILE, 0o600);
};

ipcMain.handle(
'credentials-save',
async (_event, email: string, password: string) => {
try {
const credentials = readSavedCredentials();
const index = credentials.findIndex((c) => c.email === email);
if (index >= 0) {
credentials[index].password = password;
} else {
credentials.push({ email, password });
}
writeSavedCredentials(credentials);
return { success: true };
} catch (error) {
return { success: false, error: (error as Error).message };
}
}
);

ipcMain.handle('credentials-load', async () => {
try {
const credentials = readSavedCredentials();
return {
success: true,
credentials: credentials.map((c) => ({
email: c.email,
password: c.password,
})),
};
} catch (error) {
return { success: false, credentials: [] };
}
});

ipcMain.handle('credentials-remove', async (_event, email: string) => {
try {
const credentials = readSavedCredentials().filter(
(c) => c.email !== email
);
writeSavedCredentials(credentials);
return { success: true };
} catch (error) {
return { success: false, error: (error as Error).message };
}
});

// ==================== register update related handler ====================
registerUpdateIpcHandlers();
}
Expand Down
6 changes: 6 additions & 0 deletions electron/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,12 @@ contextBridge.exposeInMainWorld('electronAPI', {
ipcRenderer.invoke('skill-config-update', userId, skillName, skillConfig),
skillConfigDelete: (userId: string, skillName: string) =>
ipcRenderer.invoke('skill-config-delete', userId, skillName),
// Saved credentials
credentialsSave: (email: string, password: string) =>
ipcRenderer.invoke('credentials-save', email, password),
credentialsLoad: () => ipcRenderer.invoke('credentials-load'),
credentialsRemove: (email: string) =>
ipcRenderer.invoke('credentials-remove', email),
});

// --------- Preload scripts loading ---------
Expand Down
12 changes: 6 additions & 6 deletions src/components/IntegrationList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ export default function IntegrationList({
}
>
{isSelectMode ? (
<div className="gap-xs flex items-center">
<div className="flex items-center gap-xs">
{(isSelectMode || showStatusDot) && (
<img
src={ellipseIcon}
Expand All @@ -361,8 +361,8 @@ export default function IntegrationList({
</div>
</div>
) : (
<div className="gap-xs flex w-full flex-row items-center justify-between">
<div className="gap-xs flex flex-row items-center">
<div className="flex w-full flex-row items-center justify-between gap-xs">
<div className="flex flex-row items-center gap-xs">
{showStatusDot && (
<img
src={ellipseIcon}
Expand All @@ -387,7 +387,7 @@ export default function IntegrationList({
</Tooltip>
</div>
</div>
<div className="gap-md flex flex-row items-center">
<div className="flex flex-row items-center gap-md">
{showConfigButton && (
<Button
type="button"
Expand Down Expand Up @@ -455,8 +455,8 @@ export default function IntegrationList({
</div>

{!isSelectMode && showSelect && (
<div className="mt-6 gap-md border-border-secondary pt-6 flex w-full flex-row items-center border-x-0 border-b-0 border-solid">
<div className="gap-md flex w-full flex-row items-center justify-between">
<div className="mt-6 flex w-full flex-row items-center gap-md border-x-0 border-b-0 border-solid border-border-secondary pt-6">
<div className="flex w-full flex-row items-center justify-between gap-md">
<div className="text-body-md text-text-body">
{' '}
Default {item.name}
Expand Down
12 changes: 6 additions & 6 deletions src/components/SearchInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ export default function SearchInput({
return (
<motion.div
className={cn(
'rounded-lg py-0.5 flex items-center justify-center overflow-hidden border border-solid border-transparent bg-transparent',
'flex items-center justify-center overflow-hidden rounded-lg border border-solid border-transparent bg-transparent py-0.5',
'focus-within:border-input-border-focus focus-within:bg-input-bg-input',
'hover:bg-surface-tertiary hover:border-transparent'
'hover:border-transparent hover:bg-surface-tertiary'
)}
initial={false}
animate={{ width: isExpanded ? EXPANDED_WIDTH : COLLAPSED_WIDTH }}
Expand Down Expand Up @@ -117,13 +117,13 @@ export default function SearchInput({
) : (
<motion.div
key="input"
className="min-w-0 gap-0 pr-1 flex flex-1 items-center"
className="flex min-w-0 flex-1 items-center gap-0 pr-1"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.15 }}
>
<span className="ml-2 h-4 w-4 text-icon-secondary pointer-events-none inline-flex shrink-0 items-center justify-center">
<span className="pointer-events-none ml-2 inline-flex h-4 w-4 shrink-0 items-center justify-center text-icon-secondary">
<Search className="h-4 w-4" />
</span>
<input
Expand All @@ -140,14 +140,14 @@ export default function SearchInput({
onSearch?.();
}
}}
className="h-6 min-w-0 pl-2 text-label-sm text-text-heading placeholder:text-text-label flex-1 bg-transparent outline-none"
className="h-6 min-w-0 flex-1 bg-transparent pl-2 text-label-sm text-text-heading outline-none placeholder:text-text-label"
/>
<TooltipSimple content={clearLabel}>
<Button
type="button"
variant="ghost"
size="icon"
className="text-icon-secondary shrink-0 rounded-full"
className="shrink-0 rounded-full text-icon-secondary"
onClick={collapse}
aria-label={clearLabel}
>
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/ar/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "حذف المشروع",
"delete-project-confirmation": "هل أنت متأكد من أنك تريد حذف هذا المشروع وجميع مهامه؟ لا يمكن التراجع عن هذا الإجراء.",
"please-select-model": "يرجى اختيار نموذج في الإعدادات > النماذج للمتابعة.",
"remember-me": "تذكرني",
"saved-accounts": "الحسابات المحفوظة",
"remove-account": "إزالة",
"cdp-browser-connection": "اتصال متصفح CDP",
"cdp-browser-connection-description": "الاتصال بمتصفح Chrome مع تمكين التصحيح عن بُعد",
"current-port": "المنفذ الحالي:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/de/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "Projekt löschen",
"delete-project-confirmation": "Sind Sie sicher, dass Sie dieses Projekt und alle seine Aufgaben löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
"please-select-model": "Bitte wählen Sie ein Modell unter Einstellungen > Modelle aus, um fortzufahren.",
"remember-me": "Angemeldet bleiben",
"saved-accounts": "Gespeicherte Konten",
"remove-account": "Entfernen",
"cdp-browser-connection": "CDP-Browser-Verbindung",
"cdp-browser-connection-description": "Verbindung zu einem Chrome-Browser mit aktiviertem Remote-Debugging herstellen",
"current-port": "Aktueller Port:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/en-us/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@
"delete-project": "Delete Project",
"delete-project-confirmation": "Are you sure you want to delete this project and all its tasks? This action cannot be undone.",
"please-select-model": "Please select a model in Settings > Models to continue.",
"remember-me": "Remember me",
"saved-accounts": "Saved accounts",
"remove-account": "Remove",
"cdp-browser-connection": "CDP Browser Connection",
"cdp-browser-connection-description": "Connect to a Chrome browser with remote debugging enabled",
"current-port": "Current Electron Port:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/es/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "Eliminar Proyecto",
"delete-project-confirmation": "¿Estás seguro de que quieres eliminar este proyecto y todas sus tareas? Esta acción no se puede deshacer.",
"please-select-model": "Por favor, selecciona un modelo en Configuración > Modelos para continuar.",
"remember-me": "Recordarme",
"saved-accounts": "Cuentas guardadas",
"remove-account": "Eliminar",
"cdp-browser-connection": "Conexión de navegador CDP",
"cdp-browser-connection-description": "Conectar a un navegador Chrome con depuración remota habilitada",
"current-port": "Puerto actual:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/fr/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "Supprimer le Projet",
"delete-project-confirmation": "Êtes-vous sûr de vouloir supprimer ce projet et toutes ses tâches ? Cette action ne peut pas être annulée.",
"please-select-model": "Veuillez sélectionner un modèle dans Paramètres > Modèles pour continuer.",
"remember-me": "Se souvenir de moi",
"saved-accounts": "Comptes enregistrés",
"remove-account": "Supprimer",
"cdp-browser-connection": "Connexion navigateur CDP",
"cdp-browser-connection-description": "Se connecter à un navigateur Chrome avec le débogage à distance activé",
"current-port": "Port actuel :",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/it/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "Elimina Progetto",
"delete-project-confirmation": "Sei sicuro di voler eliminare questo progetto e tutte le sue attività? Questa azione non può essere annullata.",
"please-select-model": "Seleziona un modello in Impostazioni > Modelli per continuare.",
"remember-me": "Ricordami",
"saved-accounts": "Account salvati",
"remove-account": "Rimuovi",
"cdp-browser-connection": "Connessione browser CDP",
"cdp-browser-connection-description": "Connetti a un browser Chrome con il debug remoto abilitato",
"current-port": "Porta attuale:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/ja/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "プロジェクトを削除",
"delete-project-confirmation": "このプロジェクトとそのすべてのタスクを削除してもよろしいですか?この操作は元に戻せません。",
"please-select-model": "続行するには、設定 > モデルでモデルを選択してください。",
"remember-me": "ログイン情報を保存",
"saved-accounts": "保存済みアカウント",
"remove-account": "削除",
"cdp-browser-connection": "CDP ブラウザ接続",
"cdp-browser-connection-description": "リモートデバッグが有効な Chrome ブラウザに接続",
"current-port": "現在のポート:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/ko/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "프로젝트 삭제",
"delete-project-confirmation": "이 프로젝트와 모든 작업을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.",
"please-select-model": "계속하려면 설정 > 모델에서 모델을 선택하세요.",
"remember-me": "로그인 정보 저장",
"saved-accounts": "저장된 계정",
"remove-account": "삭제",
"cdp-browser-connection": "CDP 브라우저 연결",
"cdp-browser-connection-description": "원격 디버깅이 활성화된 Chrome 브라우저에 연결",
"current-port": "현재 포트:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/ru/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
"delete-project": "Удалить проект",
"delete-project-confirmation": "Вы уверены, что хотите удалить этот проект и все его задачи? Это действие нельзя отменить.",
"please-select-model": "Пожалуйста, выберите модель в Настройки > Модели, чтобы продолжить.",
"remember-me": "Запомнить меня",
"saved-accounts": "Сохранённые аккаунты",
"remove-account": "Удалить",
"cdp-browser-connection": "Подключение CDP-браузера",
"cdp-browser-connection-description": "Подключиться к браузеру Chrome с включённой удалённой отладкой",
"current-port": "Текущий порт:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/zh-Hans/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@
"delete-project": "删除项目",
"delete-project-confirmation": "您确定要删除此项目及其所有任务吗?此操作无法撤销。",
"please-select-model": "请在设置 > 模型中选择一个模型以继续。",
"remember-me": "记住我",
"saved-accounts": "已保存账号",
"remove-account": "移除",
"cdp-browser-connection": "CDP 浏览器连接",
"cdp-browser-connection-description": "连接到启用了远程调试的 Chrome 浏览器",
"current-port": "当前端口:",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/zh-Hant/layout.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@
"delete-project": "刪除專案",
"delete-project-confirmation": "您確定要刪除此專案及其所有任務嗎?此操作無法撤銷。",
"please-select-model": "請在設定 > 模型中選擇一個模型以繼續。",
"remember-me": "記住我",
"saved-accounts": "已儲存帳號",
"remove-account": "移除",
"cdp-browser-connection": "CDP 瀏覽器連接",
"cdp-browser-connection-description": "連接到啟用了遠端偵錯的 Chrome 瀏覽器",
"current-port": "目前連接埠:",
Expand Down
Loading