mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-04-28 03:30:06 +00:00
fix: resolve browser cookies login issue after trigger merged (#1397)
Co-authored-by: Tao Sun <168447269+fengju0213@users.noreply.github.com>
This commit is contained in:
parent
a955ff3fe1
commit
ce861755bb
4 changed files with 70 additions and 45 deletions
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
|
@ -712,9 +713,26 @@ async def open_browser_login():
|
|||
f"Electron browser script not found: {electron_script_path}"
|
||||
)
|
||||
|
||||
electron_cmd = "npx"
|
||||
electron_args = [
|
||||
electron_cmd,
|
||||
# Resolve npx path for Windows compatibility.
|
||||
# On Windows, subprocess.Popen uses CreateProcess which cannot
|
||||
# execute .cmd files directly. We resolve the full path and
|
||||
# invoke via cmd.exe.
|
||||
npx_cmd = None
|
||||
if os.name == "nt":
|
||||
eigent_npx = os.path.expanduser("~/.eigent/bin/npx.cmd")
|
||||
if os.path.exists(eigent_npx):
|
||||
npx_cmd = eigent_npx
|
||||
if not npx_cmd:
|
||||
npx_cmd = shutil.which("npx") or shutil.which("npx.cmd")
|
||||
if not npx_cmd:
|
||||
if os.name == "nt":
|
||||
raise FileNotFoundError(
|
||||
"npx not found. Please ensure Node.js is installed and npx is on your PATH."
|
||||
)
|
||||
npx_cmd = "npx"
|
||||
|
||||
base_args = [
|
||||
npx_cmd,
|
||||
"electron",
|
||||
electron_script_path,
|
||||
user_data_dir,
|
||||
|
|
@ -722,6 +740,12 @@ async def open_browser_login():
|
|||
"https://www.google.com",
|
||||
]
|
||||
|
||||
# On Windows, wrap with cmd.exe so .cmd execution is reliable
|
||||
if os.name == "nt":
|
||||
electron_args = ["cmd.exe", "/d", "/s", "/c"] + base_args
|
||||
else:
|
||||
electron_args = base_args
|
||||
|
||||
# Get the app's directory to run npx in the right context
|
||||
app_dir = os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
|
@ -736,10 +760,17 @@ async def open_browser_login():
|
|||
logger.info(f"[PROFILE USER LOGIN] userData path: {user_data_dir}")
|
||||
logger.info(f"[PROFILE USER LOGIN] Electron args: {electron_args}")
|
||||
|
||||
# Ensure ~/.eigent/bin is on PATH for the spawned process
|
||||
env = os.environ.copy()
|
||||
eigent_bin = os.path.expanduser("~/.eigent/bin")
|
||||
if os.path.isdir(eigent_bin):
|
||||
env["PATH"] = eigent_bin + os.pathsep + env.get("PATH", "")
|
||||
|
||||
# Start process and capture output in real-time
|
||||
process = subprocess.Popen(
|
||||
electron_args,
|
||||
cwd=app_dir,
|
||||
env=env,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, # Redirect stderr to stdout
|
||||
text=True,
|
||||
|
|
@ -793,6 +824,20 @@ async def open_browser_login():
|
|||
)
|
||||
|
||||
|
||||
@router.get("/browser/status", name="browser status")
|
||||
async def browser_status():
|
||||
"""Check if the login browser is currently open."""
|
||||
import socket
|
||||
|
||||
cdp_port = 9223
|
||||
|
||||
def is_port_in_use(port):
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||
return s.connect_ex(("localhost", port)) == 0
|
||||
|
||||
return {"is_open": is_port_in_use(cdp_port)}
|
||||
|
||||
|
||||
@router.get("/browser/cookies", name="list cookie domains")
|
||||
async def list_cookie_domains(search: str = None):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -692,9 +692,10 @@ function registerIpcHandlers() {
|
|||
// Launch CDP browser with automatic port assignment
|
||||
ipcMain.handle('launch-cdp-browser', async () => {
|
||||
try {
|
||||
// 1. Find available port (9223–9300) by checking no CDP browser is listening
|
||||
// 1. Find available port (9224–9300) by checking no CDP browser is listening
|
||||
// Port 9223 is reserved for the login browser
|
||||
let port: number | null = null;
|
||||
for (let p = 9223; p < 9300; p++) {
|
||||
for (let p = 9224; p < 9300; p++) {
|
||||
if (
|
||||
!cdp_browser_pool.some((b) => b.port === p) &&
|
||||
!(await isCdpPortAlive(p))
|
||||
|
|
@ -704,7 +705,7 @@ function registerIpcHandlers() {
|
|||
}
|
||||
}
|
||||
if (port === null) {
|
||||
return { success: false, error: 'No available port in 9223-9299' };
|
||||
return { success: false, error: 'No available port in 9224-9299' };
|
||||
}
|
||||
|
||||
// 2. Find Playwright Chromium executable
|
||||
|
|
|
|||
|
|
@ -90,13 +90,11 @@ const Slot = React.forwardRef<HTMLElement, SlotProps>(function Slot<
|
|||
|
||||
if (!React.isValidElement(children)) return null;
|
||||
|
||||
const { ref: childRef, ...childProps } = children.props as AnyProps;
|
||||
const childProps = children.props as AnyProps;
|
||||
|
||||
const mergedProps = mergeProps(childProps, props);
|
||||
|
||||
return (
|
||||
<Base {...mergedProps} ref={mergeRefs(childRef as React.Ref<T>, ref)} />
|
||||
);
|
||||
return <Base {...mergedProps} ref={ref} />;
|
||||
}) as <T extends HTMLElement = HTMLElement>(
|
||||
props: SlotProps<T> & { ref?: React.Ref<T> }
|
||||
) => React.ReactElement | null;
|
||||
|
|
|
|||
|
|
@ -220,39 +220,20 @@ export default function Cookies() {
|
|||
confirmVariant="information"
|
||||
/>
|
||||
|
||||
<div className="px-6 pb-6 pt-8 flex w-full items-center justify-between">
|
||||
<div className="flex w-full items-center justify-between px-6 pb-6 pt-8">
|
||||
<div className="text-heading-sm font-bold text-text-heading">
|
||||
{t('layout.browser-cookie-management')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="gap-4 flex flex-col">
|
||||
<div className="rounded-xl border-border-disabled bg-surface-secondary p-6 relative flex w-full flex-col border">
|
||||
<div className="right-6 top-6 absolute">
|
||||
<Button
|
||||
variant="information"
|
||||
size="xs"
|
||||
onClick={handleRestartApp}
|
||||
className="gap-0 ease-in-out justify-center overflow-hidden rounded-full transition-all duration-300"
|
||||
>
|
||||
<RefreshCw className="flex-shrink-0" />
|
||||
<span
|
||||
className={`ease-in-out overflow-hidden transition-all duration-300 ${
|
||||
hasUnsavedChanges
|
||||
? 'pl-2 max-w-[150px] opacity-100'
|
||||
: 'ml-0 max-w-0 opacity-0'
|
||||
}`}
|
||||
>
|
||||
{t('layout.restart-to-apply')}
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="text-body-sm text-text-label max-w-[600px]">
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="relative flex w-full flex-col rounded-xl border border-border-disabled bg-surface-secondary p-6">
|
||||
<div className="max-w-[600px] text-body-sm text-text-label">
|
||||
{t('layout.browser-cookies-description')}
|
||||
</div>
|
||||
<div className="mt-4 gap-3 border-border-secondary pt-3 flex w-full flex-col border-[0.5px] border-x-0 border-b-0 border-solid">
|
||||
<div className="py-2 flex flex-row items-center justify-between">
|
||||
<div className="gap-2 flex flex-row items-center justify-start">
|
||||
<div className="mt-4 flex w-full flex-col gap-3 border-[0.5px] border-x-0 border-b-0 border-solid border-border-secondary pt-3">
|
||||
<div className="flex flex-row items-center justify-between py-2">
|
||||
<div className="flex flex-row items-center justify-start gap-2">
|
||||
<div className="text-body-base font-bold text-text-body">
|
||||
{t('layout.cookie-domains')}
|
||||
</div>
|
||||
|
|
@ -263,14 +244,14 @@ export default function Cookies() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="gap-2 flex items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
{cookieDomains.length > 0 && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={handleDeleteAll}
|
||||
disabled={deletingAll}
|
||||
className="!text-text-cuation uppercase"
|
||||
className="uppercase !text-text-cuation"
|
||||
>
|
||||
{deletingAll
|
||||
? t('layout.deleting')
|
||||
|
|
@ -302,14 +283,14 @@ export default function Cookies() {
|
|||
</div>
|
||||
|
||||
{cookieDomains.length > 0 ? (
|
||||
<div className="gap-2 flex flex-col">
|
||||
<div className="flex flex-col gap-2">
|
||||
{groupDomainsByMain(cookieDomains).map((group, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="rounded-xl border-border-disabled bg-surface-tertiary px-4 py-2 flex items-center justify-between border-solid"
|
||||
className="flex items-center justify-between rounded-xl border-solid border-border-disabled bg-surface-tertiary px-4 py-2"
|
||||
>
|
||||
<div className="flex w-full flex-col items-start justify-start">
|
||||
<span className="text-body-sm font-bold text-text-body truncate">
|
||||
<span className="truncate text-body-sm font-bold text-text-body">
|
||||
{group.mainDomain}
|
||||
</span>
|
||||
<span className="mt-1 text-label-xs text-text-label">
|
||||
|
|
@ -335,12 +316,12 @@ export default function Cookies() {
|
|||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-4 py-8 flex flex-col items-center justify-center">
|
||||
<div className="flex flex-col items-center justify-center px-4 py-8">
|
||||
<Cookie className="mb-4 h-12 w-12 text-icon-secondary opacity-50" />
|
||||
<div className="text-body-base font-bold text-text-label text-center">
|
||||
<div className="text-body-base text-center font-bold text-text-label">
|
||||
{t('layout.no-cookies-saved-yet')}
|
||||
</div>
|
||||
<p className="text-label-xs font-medium text-text-label text-center">
|
||||
<p className="text-center text-label-xs font-medium text-text-label">
|
||||
{t('layout.no-cookies-saved-yet-description')}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -348,7 +329,7 @@ export default function Cookies() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-label-xs text-text-label w-full text-center">
|
||||
<div className="w-full text-center text-label-xs text-text-label">
|
||||
For more information, check out our
|
||||
<a
|
||||
href="https://www.eigent.ai/privacy-policy"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue