Merge branch 'test' into feat/remote-control

This commit is contained in:
4pmtong 2026-06-12 19:57:53 +08:00
commit d0b50c7642
196 changed files with 10824 additions and 10424 deletions

18
.claude/launch.json Normal file
View file

@ -0,0 +1,18 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "web-dev",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev:web"],
"port": 5173,
"autoPort": false
},
{
"name": "animation-preview",
"runtimeExecutable": "npx",
"runtimeArgs": ["vite", "--config", "vite.config.animation.ts"],
"port": 5199
}
]
}

View file

@ -0,0 +1,380 @@
---
name: animation-interface-demo
description: Generate a self-contained TSX + CSS Module looping interface animation demo. Use when the user describes a workflow, product process, or UI flow that should be visualized as an animated interface preview on the Eigent website.
---
# Animation Interface Demo Generator
## Goal
Generate a complete, self-contained looping interface animation demo as three files:
1. `{Name}Display.tsx` — server-renderable React component (structure + data attributes)
2. `{Name}Cycler.tsx` — client-side animation island (DOM mutations only, no re-renders)
3. `{Name}Display.module.css` — all styles, no Tailwind, no CSS variables from the host app
Output files go in `animation/` at the project root.
---
## Workflow
When the user describes a workflow or process:
1. **Parse the workflow** into a flat ordered list of tasks (typically 36). Each task belongs to an agent or role.
2. **Identify agents/roles** and their tools/capabilities (shown as tags).
3. **Decide on interface layout** — the canonical layout has a left chat panel + right workspace with agent cards.
4. **Generate all three files** at once.
---
## Architecture Rules
### No dependencies
- Only `react`, `react/jsx-runtime`, `next/image` (for workspace previews), and `lucide-react` icons are allowed.
- No Tailwind classes. No CSS variables from the host project. No `framer-motion`. No state management.
- The `Display` component must be fully server-renderable (no `"use client"` directive).
- The `Cycler` component gets `"use client"` and is the ONLY interactive island.
### Responsive scaling shell
Every display uses this exact scaling pattern:
```css
.container {
position: relative;
width: 100%;
aspect-ratio: 1600 / 960; /* matches the inner canvas */
container-type: inline-size;
--ui-scale: calc(100cqw / 1600px); /* scales everything proportionally */
pointer-events: none;
user-select: none;
-webkit-user-select: none;
touch-action: pan-y;
}
.inner {
position: absolute;
top: 0; left: 0;
width: 1600px;
height: 960px;
transform-origin: top left;
transform: scale(var(--ui-scale, 1));
/* …border, background, overflow: hidden */
}
```
The inner canvas is always **1600×960 px** at design scale. The container scales it to fill whatever width the parent provides. All child sizes use plain `px` values — they scale automatically.
### Animation data attributes
The Cycler drives the animation entirely via `data-*` attribute mutations and `textContent` updates. No React state. No re-renders.
| Attribute | Where | Purpose |
|-----------|-------|---------|
| `data-cycle-root` | root container | Cycler `querySelector` anchor |
| `data-task-index={n}` | each task item | Marks the task's global index (0-based) |
| `data-done="true\|false"` | each task item | CSS toggles icon + background |
| `data-cycle-summary="done\|ongoing"` | badge text `<span>` | Cycler updates count text |
| `data-cycle-chip="done\|ongoing"` | filter chip `<span>` | Wrapper for per-agent chip |
| `data-agent-indexes="0,1"` | filter chip | Comma-separated global task indexes this agent owns |
| `data-cycle-count="done\|ongoing"` | count `<span>` inside chip | Cycler updates count text |
### CSS icon toggle pattern
Both the "done" and "ongoing" icons are always in the DOM. CSS hides the inactive one:
```css
.iconDone, .iconOngoing { display: none; }
.taskItem[data-done="true"] .iconDone { display: inline-block; }
.taskItem[data-done="false"] .iconOngoing { display: inline-block; }
```
The Cycler only sets `el.dataset.done = idx < step ? "true" : "false"` — no class toggling needed.
---
## Display Component Template
```tsx
// {Name}Display.tsx (NO "use client" — server-renderable)
import Image from "next/image";
import { /* lucide icons */ } from "lucide-react";
import s from "./{Name}Display.module.css";
import {Name}Cycler from "./{Name}Cycler";
const TOTAL_TASKS = N; // total number of animated tasks
function TaskItem({ done, text, index }: { done?: boolean; text: string; index: number }) {
return (
<div className={s.taskItem} data-done={done ? "true" : "false"} data-task-index={index}>
<div className={s.taskIcon}>
<CircleCheckBig size={16} color="#00a63e" className={s.iconDone} />
<Loader2 size={16} color="#155dfc" className={`${s.spinner} ${s.iconOngoing}`} />
</div>
<p className={s.taskText}>{text}</p>
</div>
);
}
export default function {Name}Display() {
const completedTaskCount = 2; // initial snapshot for SSR
const isTaskDone = (i: number) => i < completedTaskCount;
const getDoneCount = (indexes: number[]) => indexes.filter(isTaskDone).length;
const getOngoingCount = (indexes: number[]) => indexes.length - getDoneCount(indexes);
return (
<div className={s.container} data-cycle-root aria-hidden="true">
<{Name}Cycler totalTasks={TOTAL_TASKS} />
<div className={s.inner}>
{/* … layout … */}
</div>
</div>
);
}
```
---
## Cycler Component Template
The Cycler template below is reusable across all demos. Copy it verbatim and adjust only:
- `CYCLE_MS` — how long each step holds (default 1500ms)
- `PAUSE_AT_FULL_MS` — pause when all tasks done before resetting (default 1800ms)
- `ROOT_MARGIN` — IntersectionObserver margin for early wake-up (default "200px")
```tsx
"use client";
import { useEffect, useRef } from "react";
const CYCLE_MS = 1500;
const PAUSE_AT_FULL_MS = 1800;
const ROOT_MARGIN = "200px";
export default function {Name}Cycler({ totalTasks }: { totalTasks: number }) {
const anchorRef = useRef<HTMLSpanElement>(null);
useEffect(() => {
const anchor = anchorRef.current;
if (!anchor) return;
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return;
const root = anchor.closest<HTMLElement>("[data-cycle-root]");
if (!root) return;
const taskItems = Array.from(root.querySelectorAll<HTMLElement>("[data-task-index]"));
const summarySpans = Array.from(root.querySelectorAll<HTMLElement>("[data-cycle-summary]"));
const chipCountSpans = Array.from(root.querySelectorAll<HTMLElement>("[data-cycle-count]"));
if (taskItems.length === 0) return;
let step = 0;
let timer: ReturnType<typeof setTimeout> | null = null;
let isVisible = true;
let isTabVisible = !document.hidden;
const applyStep = () => {
for (const el of taskItems) {
const idx = Number(el.dataset.taskIndex);
el.dataset.done = idx < step ? "true" : "false";
}
for (const el of summarySpans) {
const role = el.dataset.cycleSummary;
if (role === "done") el.textContent = String(step);
else if (role === "ongoing") el.textContent = String(totalTasks - step);
}
for (const el of chipCountSpans) {
const chip = el.closest<HTMLElement>("[data-cycle-chip]");
const indexesAttr = chip?.dataset.agentIndexes;
if (!chip || !indexesAttr) continue;
const indexes = indexesAttr.split(",").map(Number);
const doneCount = indexes.filter((i) => i < step).length;
const role = el.dataset.cycleCount;
el.textContent = String(role === "done" ? doneCount : indexes.length - doneCount);
}
};
const tick = () => {
if (!isVisible || !isTabVisible) { timer = setTimeout(tick, CYCLE_MS); return; }
step = (step + 1) % (totalTasks + 1);
applyStep();
timer = setTimeout(tick, step === totalTasks ? PAUSE_AT_FULL_MS : CYCLE_MS);
};
step = 0;
applyStep();
let idleHandle: number | null = null;
let idleTimeout: ReturnType<typeof setTimeout> | null = null;
const start = () => { timer = setTimeout(tick, CYCLE_MS); };
if (typeof window.requestIdleCallback === "function") {
idleHandle = window.requestIdleCallback(start, { timeout: 2500 });
} else {
idleTimeout = setTimeout(start, 500);
}
const io = new IntersectionObserver(([e]) => { isVisible = e.isIntersecting; }, { rootMargin: ROOT_MARGIN });
io.observe(root);
const onVisibility = () => { isTabVisible = !document.hidden; };
document.addEventListener("visibilitychange", onVisibility);
return () => {
if (timer !== null) clearTimeout(timer);
if (idleHandle !== null && typeof window.cancelIdleCallback === "function") window.cancelIdleCallback(idleHandle);
if (idleTimeout !== null) clearTimeout(idleTimeout);
io.disconnect();
document.removeEventListener("visibilitychange", onVisibility);
};
}, [totalTasks]);
return <span ref={anchorRef} aria-hidden="true" style={{ display: "none" }} />;
}
```
---
## CSS Module Guidelines
### Required sections (include all)
```
/* ── Responsive scaling shell ─── */
.container, .inner
/* ── Top Bar ─── */
.topBar, .trafficLights, .dot, .dotRed/Yellow/Green, .topBarNav, .navBackBtn, .navTitleBtn, .navTitleText, .topBarIconGroup, .iconBtn
/* ── Body ─── */
.body, .mainContent (12-col grid, 4-row grid)
/* ── Chat Panel (col 13) ─── */
.chatPanel, .chatHeader, .chatTitle, .tokenBadge, .tokenText
.chatContent, .userMessage, .userMessageText, .userMessageLink
.agentMessage, .agentMessageText, .thinkingRow, .thinkingText
.taskCard, .taskCardInner, .progressBar, .progressFill
.taskCardBody, .taskCardTitle, .taskCardMeta, .taskCardBadges
.taskBadge, .taskBadgeText, .taskBadgeTextBlue, .taskCardChevronBtn
.chatScrollbar, .chatBottomBar (input area)
/* ── Workspace Area (col 412) ─── */
.workspaceArea, .workspaceTopBar, .workspaceTabs, .wsTab, .wsTabActive, .newWorkerBtn
/* ── Agent Cards ─── */
.agentCardsArea, .agentCard, .agentCardCustom
.agentCardHeader, .agentCardTitleRow, .agentCardTitle
.agentTitleBlue/Green/Orange/Gray, .agentCardMenuBtn
.agentCardTags, .agentTag
/* ── Task items ─── */
.taskFiltersSection, .taskFiltersDivider, .taskFilters
.filterChip, .filterChipActive, .filterChipDefault, .filterChipGreen, .filterChipBlue
.taskListSection, .taskItem, .taskItem[data-done="true"]
.iconDone, .iconOngoing (display:none pattern)
.taskIcon, .taskText, .cardScrollbar
/* ── Bottom Menu Bar ─── */
.menuBar, .menuBarCenter, .botIconBtn, .botBadge, .menuBarRight, .menuNavBtn
/* ── Spinner ─── */
@keyframes spin + .spinner
```
### Color tokens (use these values, no CSS variables)
| Token | Value |
|-------|-------|
| Text primary | `#111111` / `#222222` |
| Text secondary | `#666666` |
| Text muted | `#cccccc` |
| Border | `#eeeeee` / `#cccccc` |
| Blue accent | `#155dfc` |
| Green accent | `#00a63e` |
| Orange accent | `#e17100` |
| Background card | `#ffffff` |
| Background subtle | `#f5f5f5` |
| Done bg | `#f0fdf4` |
| Progress green | `#016630` |
### Grid layout
```css
.mainContent {
display: grid;
grid-template-columns: repeat(12, minmax(0, 1fr));
grid-template-rows: repeat(4, minmax(0, 1fr));
}
.chatPanel { grid-column: 1 / span 3; grid-row: 1 / span 4; }
.workspaceArea { grid-column: 4 / span 9; grid-row: 1 / span 4; }
```
---
## Agent Card Anatomy
Each agent card follows this structure:
```
AgentCard
├── Header (title + MoreHorizontal menu btn)
│ └── Tags row (# Tool1, # Tool2, …)
├── [optional] Workspace preview image
├── Filter chips (All | Done N | Ongoing N)
│ └── Done/Ongoing chips carry data-cycle-chip + data-agent-indexes
└── Task list
└── TaskItem × n (data-task-index, data-done)
```
Agent title colors:
- Browser/Web agent → `#0084d1` (blue)
- Developer/Code agent → `#009966` (green)
- Document/Report agent → `#e17100` (orange)
- Custom/placeholder agent → `#222222` (gray) + opacity 0.4
---
## Steps to Generate a New Demo
Given a user's workflow description:
1. **Extract tasks** — write each as a single imperative sentence (12 lines, detail OK). Number them globally from 0.
2. **Group tasks by agent** — assign each task to the most fitting agent type. Create 24 real agents + 1 ghost "Custom Agent" placeholder.
3. **Set `TOTAL_TASKS`** to the total task count.
4. **Set initial `completedTaskCount`** — pick roughly half (e.g. `TOTAL_TASKS = 4` → start at `2`).
5. **Build `browserTaskIndexes`, `developerTaskIndexes`, etc.** — arrays of global task indexes per agent.
6. **Write the task text** — the existing example uses verbose, realistic task descriptions. Match that tone.
7. **Choose workspace preview** — include a `showPreview` card if the workflow involves web browsing or visual output. Use `/home/demo.png` as placeholder or the appropriate public image path.
8. **Write chat panel content** — user message rephrasing the workflow goal, short agent reply, "Thinking Xs", and the Task card with animated badges.
9. **Generate CSS** — copy the full CSS structure above, adjusting any unique layout needs.
10. **Generate Cycler** — copy verbatim, substituting `{Name}`.
---
## Output Checklist
Before delivering files, verify:
- [ ] `{Name}Display.tsx` has NO `"use client"` directive
- [ ] `{Name}Cycler.tsx` has `"use client"` at top
- [ ] `data-cycle-root` is on the root `<div>` of Display
- [ ] Every `<TaskItem>` has a unique `data-task-index` starting at 0
- [ ] Filter chip `data-agent-indexes` covers all tasks for that agent
- [ ] `TOTAL_TASKS` matches the count of TaskItems across all cards
- [ ] CSS uses `#` hex values only — no `var()` referencing host app tokens
- [ ] `.container` has `aspect-ratio: 1600 / 960` and `container-type: inline-size`
- [ ] `.inner` is 1600×960 with `transform: scale(var(--ui-scale, 1))`
- [ ] `aria-hidden="true"` on root container
- [ ] `pointer-events: none` on root container
- [ ] Spinner animation defined as `@keyframes spin` in the CSS module
---
## Usage
Trigger this skill when the user says things like:
- "Create an interface demo for [workflow]"
- "Build an animation for [process]"
- "Make a website demo showing [product feature]"
- "Add an interface preview for [use case]"
Ask for (or infer from context):
- The workflow name (for file naming)
- The workflow steps / process description
- Any specific agents or tools to feature
- Whether a workspace preview image should be included

View file

@ -1,23 +1,36 @@
VITE_BASE_URL=/api
# =======Production environment variables=======
# =======Production environment variables start=======
# SERVER_URL=https://dev.eigent.ai
# VITE_PROXY_URL=https://dev.eigent.ai
# VITE_SITE_URL=https://www.eigent.ai
# VITE_USE_LOCAL_PROXY=false
# VITE_REMOTE_CONTROL_WEB_ORIGIN=https://remote.eigent.ai
# REMOTE_CONTROL_WEB_ORIGIN=https://remote.eigent.ai
# VITE_REMOTE_CONTROL_LOCAL_API_URL=https://dev.eigent.ai
# =======Production environment variables end =======
# =======Test environment variables=======
# SERVER_URL=https://test-dev.eigent.ai
# VITE_PROXY_URL=https://test-dev.eigent.ai
# VITE_SITE_URL=https://test.eigent.ai
# VITE_USE_LOCAL_PROXY=false
# =======Test environment variables start =======
SERVER_URL=https://test-dev.eigent.ai
VITE_PROXY_URL=https://test-dev.eigent.ai
VITE_SITE_URL=https://test.eigent.ai
VITE_USE_LOCAL_PROXY=false
VITE_REMOTE_CONTROL_WEB_ORIGIN=https://test-remote.eigent.ai
REMOTE_CONTROL_WEB_ORIGIN=https://test-remote.eigent.ai
VITE_REMOTE_CONTROL_LOCAL_API_URL=https://test-dev.eigent.ai
# =======Test environment variables end=======
# =======Local environment variables=======
VITE_PROXY_URL=http://localhost:3001
VITE_USE_LOCAL_PROXY=true
# =======Local environment variables start =======
# SERVER_URL=http://localhost:3001
# VITE_PROXY_URL=http://localhost:3001
# VITE_USE_LOCAL_PROXY=true
# VITE_REMOTE_CONTROL_WEB_ORIGIN=http://localhost:5174
# REMOTE_CONTROL_WEB_ORIGIN=http://localhost:5174
# VITE_REMOTE_CONTROL_LOCAL_API_URL=http://localhost:3001
# =======Local environment variables end=======
# Dummy Stack Auth keys for local dev (enables StackProvider gating).
# Replace with real values from Stack dashboard when needed.
VITE_STACK_PROJECT_ID=dummy_project_id
VITE_STACK_PUBLISHABLE_CLIENT_KEY=dummy_publishable_key
VITE_STACK_SECRET_SERVER_KEY=dummy_secret_server_key
VITE_STACK_SECRET_SERVER_KEY=dummy_secret_server_key

1
.gitignore vendored
View file

@ -42,6 +42,7 @@ yarn.lock
.env.local
.env.production
.env.development
client_secret_*.json
.cursor

View file

@ -21,7 +21,7 @@ from collections.abc import Iterable
from pathlib import Path
from typing import Any, overload
from dotenv import load_dotenv
from dotenv import dotenv_values, load_dotenv
from fastapi import APIRouter, FastAPI
logger = logging.getLogger("env")
@ -29,6 +29,10 @@ logger = logging.getLogger("env")
# Thread-local storage for user-specific environment
_thread_local = threading.local()
# Keys present before dotenv files are loaded remain authoritative. Values
# loaded from dotenv files can be refreshed from disk by env().
_process_env_keys = set(os.environ.keys())
# Safe base directory for user environment files
env_base_dir = os.path.join(os.path.expanduser("~"), ".eigent")
@ -58,6 +62,8 @@ def _load_initial_env_files(paths: Iterable[Path]) -> list[Path]:
3. Earlier files in `paths`.
"""
original_env = dict(os.environ)
global _process_env_keys
_process_env_keys = set(original_env.keys())
loaded_paths: list[Path] = []
seen: set[str] = set()
@ -84,6 +90,26 @@ def _load_initial_env_files(paths: Iterable[Path]) -> list[Path]:
return loaded_paths
def _load_live_env_values(paths: Iterable[Path]) -> dict[str, str]:
values: dict[str, str] = {}
seen: set[str] = set()
for path in paths:
resolved = path.expanduser().resolve()
resolved_key = str(resolved)
if resolved_key in seen:
continue
seen.add(resolved_key)
if not resolved.exists():
continue
for key, value in dotenv_values(resolved).items():
if value is not None:
values[key] = value
return values
_load_initial_env_files(_resolve_initial_env_paths())
@ -258,8 +284,27 @@ def env(key: str, default=None):
)
delattr(_thread_local, "env_path")
# Fall back to global environment
value = os.getenv(key, default)
# Keep real process / service-manager env vars authoritative, but allow
# dotenv-backed values to be refreshed after Electron writes them.
if key in _process_env_keys and key in os.environ:
value = os.environ[key]
logger.debug(
f"Environment variable retrieved from process env: key={key}, "
f"has_value={value is not None}"
)
return value
live_env_values = _load_live_env_values(_resolve_initial_env_paths())
if key in live_env_values:
value = live_env_values[key]
logger.debug(
f"Environment variable retrieved from live dotenv config: "
f"key={key}, has_value={value is not None}"
)
return value
# Fall back to any value set programmatically after startup.
value = os.environ.get(key, default)
logger.debug(
f"Environment variable retrieved from global config: key={key}, "
f"has_value={value is not None}, using_default={value == default}"

View file

@ -12,16 +12,19 @@
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
import asyncio
import logging
import mimetypes
import re
import time
from functools import partial
from pathlib import Path
from typing import Annotated
from urllib.parse import quote
from fastapi import APIRouter, File, Header, HTTPException, Query, UploadFile
from fastapi.responses import FileResponse
from starlette.concurrency import run_in_threadpool
from app.component.environment import env
from app.utils.file_utils import list_files, resolve_under_base
@ -35,6 +38,8 @@ MAX_FILE_SIZE_BYTES = 50 * 1024 * 1024 # 50MB
MAX_FILES_PER_SESSION = 20
WORKSPACE_ROOT = env("EIGENT_WORKSPACE", "~/.eigent/workspace")
SESSION_ID_PATTERN = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
FILE_LIST_SEMAPHORE = asyncio.Semaphore(4)
SLOW_FILE_LIST_LOG_MS = 300
def _get_eigent_root() -> Path:
@ -78,6 +83,11 @@ def _count_session_uploads(session_id: str) -> int:
return len(list(uploads_dir.iterdir()))
def _redacted_path_suffix(path: Path) -> str:
parts = path.parts[-2:]
return (".../" + "/".join(parts)) if parts else "..."
@router.post("/files")
async def upload_file(
file: Annotated[UploadFile, File()],
@ -242,11 +252,41 @@ async def list_project_files(
)
return []
base_path = str(project_root.resolve())
stats: dict[str, float | int] = {}
started = time.perf_counter()
try:
paths = list_files(list_dir, base=base_path, max_entries=500)
async with FILE_LIST_SEMAPHORE:
paths = await run_in_threadpool(
partial(
list_files,
list_dir,
base=base_path,
max_entries=500,
stats=stats,
)
)
except Exception as e:
file_logger.warning("list_project_files failed: %s", e)
return []
elapsed_ms = (time.perf_counter() - started) * 1000
log = (
file_logger.info
if elapsed_ms >= SLOW_FILE_LIST_LOG_MS
else file_logger.debug
)
log(
"list_project_files: project_id=%s space_id=%s task_id=%s count=%d "
"elapsed_ms=%.1f scan_ms=%.1f realpath_ms=%.1f symlinks=%d root=%s",
project_id,
space_id,
task_id,
len(paths),
elapsed_ms,
float(stats.get("scan_elapsed_ms", 0)),
float(stats.get("realpath_elapsed_ms", 0)),
int(stats.get("symlink_count", 0)),
_redacted_path_suffix(project_root),
)
result: list[dict] = []
for abs_path in paths:
try:

View file

@ -23,6 +23,11 @@ from app.model.enums import Status
from app.router_layer.hands_resolver import get_environment_hands
from app.service.task import get_task_lock_if_exists
from app.utils.space_overlay_client import overlay_sync_failure_count
from app.utils.workspace_paths import (
get_eigent_root,
runtime_owner_key,
sanitize_identity,
)
from app.utils.workspace_resolver import (
_same_workspace_path,
get_workspace_resolver,
@ -46,6 +51,12 @@ class WorkspaceReconcileRequest(BaseModel):
active_space_ids: list[str]
class WorkspaceScratchRequest(BaseModel):
space_id: str
email: str
user_id: str | int | None = None
class WorkspaceProjectRefreshRequest(BaseModel):
email: str
user_id: str | int | None = None
@ -167,6 +178,17 @@ def _effective_space_id(payload: WorkspaceBindRequest) -> str:
return space_id
def _scratch_space_root(
email: str, space_id: str, user_id: str | int | None = None
) -> Path:
safe_space_id = sanitize_identity(space_id).removeprefix("space_")
return (
get_eigent_root()
/ runtime_owner_key(email, user_id)
/ f"space_{safe_space_id or 'scratch'}"
)
@router.get("/workspace/capabilities")
async def workspace_capabilities(request: Request) -> dict[str, Any]:
return _capability_payload(_manifest_from_request(request))
@ -203,6 +225,59 @@ async def workspace_current(
}
@router.post("/workspace/scratch")
async def workspace_scratch(
payload: WorkspaceScratchRequest, request: Request
) -> dict[str, Any]:
# Creates a Brain-owned local folder for a blank Space. This keeps
# frontend/backend separation intact: renderers ask Brain for a workspace
# root instead of relying on Electron-only filesystem IPC.
manifest = _manifest_from_request(request)
if not _binding_enabled(manifest):
raise HTTPException(
status_code=412,
detail={
"code": "workspace_binding_disabled",
"capabilities": _capability_payload(manifest),
},
)
resolver = get_workspace_resolver()
existing = resolver.store.get_binding(
payload.email, payload.space_id, payload.user_id
)
if existing is not None:
existing_path = Path(existing.workspace_root).expanduser()
existing_path.mkdir(parents=True, exist_ok=True)
return {
"space_id": payload.space_id,
"email": payload.email,
"user_id": payload.user_id,
"bound": existing_path.is_dir(),
"workspace_root": existing.workspace_root,
"binding": existing.__dict__.copy(),
}
root = _scratch_space_root(
payload.email, payload.space_id, payload.user_id
).resolve()
root.mkdir(parents=True, exist_ok=True)
binding = resolver.ensure_space_binding(
payload.email,
payload.space_id,
str(root),
user_id=payload.user_id,
)
return {
"space_id": payload.space_id,
"email": payload.email,
"user_id": payload.user_id,
"bound": True,
"workspace_root": binding.workspace_root,
"binding": binding.__dict__.copy(),
}
@router.post("/workspace/bind")
async def workspace_bind(
payload: WorkspaceBindRequest, request: Request

View file

@ -17,11 +17,12 @@ from typing import Annotated, Final
from pydantic import BeforeValidator
PLATFORM_ALIAS_MAPPING: Final[dict[str, str]] = {
"z.ai": "zhipu",
"z.ai": "zhipuai",
"ModelArk": "openai-compatible-model",
"grok": "openai-compatible-model",
"ernie": "qianfan",
"llama.cpp": "openai-compatible-model",
"nebius": "openai-compatible-model",
"orcarouter": "openai-compatible-model",
}

View file

@ -115,6 +115,43 @@ def normalize_summary_task(
return f"{name or 'Task'}|{summary or name or 'Task'}"
def _extract_stream_chunk_content(chunk: Any) -> str:
"""Return user-visible text from a streaming chunk.
Some CAMEL streaming chunks carry planning text in ``reasoning_content``.
Falling back to ``str(chunk)`` leaks internal ``BaseMessage(...)``
representations to the UI, so only explicit text fields are displayable.
"""
if chunk is None:
return ""
if isinstance(chunk, str):
return chunk
def message_text(message: Any) -> str:
for attr in ("content", "reasoning_content"):
value = getattr(message, attr, None)
if isinstance(value, str) and value:
return value
return ""
msg = getattr(chunk, "msg", None)
content = message_text(msg)
if content:
return content
msgs = getattr(chunk, "msgs", None)
if msgs:
contents = [
item_content
for item in msgs
if (item_content := message_text(item))
]
if contents:
return "".join(contents)
return ""
def format_task_context(
task_data: dict, seen_files: set | None = None, skip_files: bool = False
) -> str:
@ -838,10 +875,10 @@ async def step_solve(options: Chat, request: Request, task_lock: TaskLock):
def on_stream_text(chunk):
try:
accumulated_content = (
chunk.msg.content
if hasattr(chunk, "msg") and chunk.msg
else str(chunk)
_extract_stream_chunk_content(chunk)
)
if not accumulated_content:
return
last_content = stream_state["last_content"]
# Calculate delta: new content
@ -1516,12 +1553,11 @@ async def step_solve(options: Chat, request: Request, task_lock: TaskLock):
def on_stream_text(chunk):
try:
has_msg = hasattr(chunk, "msg") and chunk.msg
accumulated_content = (
chunk.msg.content
if has_msg
else str(chunk)
_extract_stream_chunk_content(chunk)
)
if not accumulated_content:
return
last_content = stream_state["last_content"]
if accumulated_content.startswith(

View file

@ -18,6 +18,7 @@ import logging
import os
import platform
import shutil
import time
from pathlib import Path
from app.component.environment import env
@ -196,6 +197,7 @@ def list_files(
skip_dirs: set[str] | None = None,
skip_extensions: tuple[str, ...] = DEFAULT_SKIP_EXTENSIONS,
skip_prefix: str = ".",
stats: dict[str, float | int] | None = None,
) -> list[str]:
"""List files under dir_path with optional base confinement and filters.
If base is set, only returns paths that resolve under base (no traversal).
@ -231,6 +233,17 @@ def list_files(
base_real = os.path.realpath(resolve_base)
skip_dirs = set(DEFAULT_SKIP_DIRS).union(skip_dirs or set())
result: list[str] = []
scan_started = time.perf_counter()
realpath_elapsed = 0.0
symlink_count = 0
def record_stats() -> None:
if stats is None:
return
stats["scan_elapsed_ms"] = (time.perf_counter() - scan_started) * 1000
stats["realpath_elapsed_ms"] = realpath_elapsed * 1000
stats["symlink_count"] = symlink_count
try:
for root, dirs, files in os.walk(resolved_dir, followlinks=False):
dirs[:] = [
@ -243,22 +256,33 @@ def list_files(
continue
try:
file_path = os.path.join(root, name)
real_path = os.path.realpath(file_path)
if not _is_under_base(real_path, base_real):
logger.debug(
"list_files: skipping %r (escapes base)", file_path
if os.path.islink(file_path):
symlink_count += 1
realpath_started = time.perf_counter()
real_path = os.path.realpath(file_path)
realpath_elapsed += (
time.perf_counter() - realpath_started
)
continue
result.append(real_path)
if not _is_under_base(real_path, base_real):
logger.debug(
"list_files: skipping %r (escapes base)",
file_path,
)
continue
result.append(real_path)
else:
result.append(os.path.normpath(file_path))
if len(result) >= max_entries:
logger.debug(
"list_files hit max_entries=%d", max_entries
)
record_stats()
return result
except OSError:
continue
except OSError as e:
logger.warning("list_files failed for %r: %s", dir_path, e)
record_stats()
return result

View file

@ -18,8 +18,10 @@ from pathlib import Path
import pytest
import app.component.environment as environment
from app.component.environment import (
_load_initial_env_files,
env,
env_base_dir,
sanitize_env_path,
)
@ -226,3 +228,39 @@ def test_initial_env_files_precedence(monkeypatch, temp_dir: Path):
assert os.environ["GLOBAL_ONLY"] == "from_global"
assert os.environ["DEVELOPMENT_ONLY"] == "from_development"
assert os.environ["PROCESS_KEY"] == "from_process"
def test_env_reads_live_dotenv_updates(monkeypatch, temp_dir: Path):
"""env() should see dotenv changes written after process startup."""
env_file = temp_dir / ".env"
env_file.write_text("DYNAMIC_ENV_KEY=first")
monkeypatch.delenv("DYNAMIC_ENV_KEY", raising=False)
monkeypatch.setattr(
environment, "_resolve_initial_env_paths", lambda: (env_file,)
)
monkeypatch.setattr(
environment, "_process_env_keys", set(os.environ.keys())
)
assert env("DYNAMIC_ENV_KEY") == "first"
env_file.write_text("DYNAMIC_ENV_KEY=second")
assert env("DYNAMIC_ENV_KEY") == "second"
def test_env_process_value_overrides_live_dotenv(monkeypatch, temp_dir: Path):
"""Real process env remains higher priority than dotenv files."""
env_file = temp_dir / ".env"
env_file.write_text("PROCESS_PRIORITY_KEY=from_file")
monkeypatch.setenv("PROCESS_PRIORITY_KEY", "from_process")
monkeypatch.setattr(
environment, "_resolve_initial_env_paths", lambda: (env_file,)
)
monkeypatch.setattr(
environment, "_process_env_keys", {"PROCESS_PRIORITY_KEY"}
)
assert env("PROCESS_PRIORITY_KEY") == "from_process"

View file

@ -43,6 +43,15 @@ class TestModelControllerEnhanced:
)
assert request_data.model_platform == "openai-compatible-model"
def test_validate_model_request_maps_nebius_alias(self):
"""Test request model maps Nebius alias to openai-compatible-model."""
request_data = ValidateModelRequest(
model_platform="nebius",
model_type="meta-llama/Llama-3.3-70B-Instruct",
api_key="test_key",
)
assert request_data.model_platform == "openai-compatible-model"
def test_validate_model_request_keeps_supported_platforms_unchanged(self):
"""Test request model keeps native camel-ai platforms unchanged."""
request_data = ValidateModelRequest(

View file

@ -142,6 +142,11 @@ class TestModelPlatformMapping:
chat = self._create_chat("grok")
assert chat.model_platform == "openai-compatible-model"
def test_chat_maps_nebius_to_openai_compatible_model(self):
"""Test Chat maps Nebius platform alias correctly."""
chat = self._create_chat("nebius")
assert chat.model_platform == "openai-compatible-model"
def test_chat_keeps_supported_platforms_unchanged(self):
"""Test Chat keeps native camel-ai platforms unchanged."""
chat = self._create_chat("mistral")
@ -154,6 +159,11 @@ class TestModelPlatformMapping:
config = AgentModelConfig(model_platform="grok")
assert config.model_platform == "openai-compatible-model"
def test_agent_model_config_maps_nebius_alias(self):
"""Test AgentModelConfig also maps Nebius alias."""
config = AgentModelConfig(model_platform="nebius")
assert config.model_platform == "openai-compatible-model"
def test_agent_model_config_keeps_supported_platforms_unchanged(self):
"""Test AgentModelConfig keeps native camel-ai platforms unchanged."""
config = AgentModelConfig(model_platform="mistral")

View file

@ -24,10 +24,11 @@ from app.model.model_platform import (
def test_normalize_model_platform_maps_known_aliases():
assert normalize_model_platform("grok") == "openai-compatible-model"
assert normalize_model_platform("z.ai") == "zhipu"
assert normalize_model_platform("z.ai") == "zhipuai"
assert normalize_model_platform("ModelArk") == "openai-compatible-model"
assert normalize_model_platform("ernie") == "qianfan"
assert normalize_model_platform("llama.cpp") == "openai-compatible-model"
assert normalize_model_platform("nebius") == "openai-compatible-model"
def test_normalize_model_platform_keeps_non_alias_unchanged():

View file

@ -20,6 +20,7 @@ from camel.tasks.task import TaskState
from app.model.chat import Chat, NewAgent
from app.service.chat_service import (
_extract_stream_chunk_content,
_render_subtask_report,
_trim_in_process_history,
add_sub_tasks,
@ -49,6 +50,60 @@ from app.service.task import (
)
class _StreamMsg:
def __init__(self, content="", reasoning_content=""):
self.content = content
self.reasoning_content = reasoning_content
class _StreamChunk:
def __init__(self, msg=None, msgs=None):
self.msg = msg
self.msgs = msgs
def __str__(self):
return "msgs=[BaseMessage(role_name='System', reasoning_content='We')]"
@pytest.mark.unit
class TestExtractStreamChunkContent:
def test_extracts_single_message_content(self):
chunk = _StreamChunk(msg=_StreamMsg("<task>Clean desktop</task>"))
assert _extract_stream_chunk_content(chunk) == (
"<task>Clean desktop</task>"
)
def test_extracts_single_message_reasoning_content(self):
chunk = _StreamChunk(
msg=_StreamMsg(
reasoning_content="We need to organize the desktop."
)
)
assert (
_extract_stream_chunk_content(chunk)
== "We need to organize the desktop."
)
def test_extracts_message_list_content(self):
chunk = _StreamChunk(
msgs=[
_StreamMsg(reasoning_content="We need "),
_StreamMsg("<task>Group files</task>"),
]
)
assert _extract_stream_chunk_content(chunk) == (
"We need <task>Group files</task>"
)
def test_ignores_metadata_only_chunk(self):
chunk = _StreamChunk()
assert _extract_stream_chunk_content(chunk) == ""
@pytest.mark.unit
class TestFormatTaskContext:
"""Test cases for format_task_context function."""

136
docs/CONTENT_STRUCTURE.md Normal file
View file

@ -0,0 +1,136 @@
# Eigent Documentation Structure
This file is the editorial map for the public Mintlify documentation. Navigation is defined in `docs/docs.json`. Writing and media conventions are defined in `docs/STYLE_GUIDE.md`.
## Information Architecture
### Get Started
- Welcome and product positioning
- Installation
- Quick start
- Self-hosting
- Core concepts
### Dashboard
- Dashboard overview
- Spaces
- Projects
- Tasks
- Search, sort, grid, list, and board views
### Projects
- Space, Project, Session, and Run hierarchy
- Project creation
- Workspace landing
- Context and files
- Live sessions
- Multi-run follow-ups
- Single Agent mode
- Workforce mode
### Agents
- Agent capabilities
- Workers
- Agent Skills
- Remote sub-agents
- Memory roadmap
### Models
- Model selection overview
- Eigent Cloud
- Bring Your Own Key
- Local models
- Provider reference
- Provider-specific setup guides
### Connectors
- Connector overview
- MCP marketplace
- Custom local and remote MCP servers
- Google Search
- Tool assignment
### Browser
- Browser automation overview
- CDP browser connections
- Browser cookie management
- Browser Plugins roadmap
### Automation
- Automation overview
- Scheduled triggers
- Webhook and Slack triggers
- Dispatch and remote control
- Execution logs and retries
### Settings
- Account, language, proxy, and updates
- Appearance and custom themes
- Privacy and data handling
### Open Source
- Repository and contribution overview
- Self-hosting
- Brain architecture
## Provider Coverage
The provider reference must remain synchronized with `src/lib/llm.ts` and `src/pages/Agents/localModels.ts`.
Cloud and BYOK coverage:
- Gemini
- OpenAI
- Anthropic
- OrcaRouter
- OpenRouter
- Qwen
- DeepSeek
- MiniMax
- Z.ai
- Moonshot
- ModelArk
- SambaNova
- Grok
- Mistral
- AWS Bedrock
- AWS Bedrock Converse
- Azure
- ERNIE
- OpenAI-compatible endpoints
Local runtime coverage:
- Ollama
- vLLM
- SGLang
- LM Studio
- LLaMA.cpp
## Editorial Priorities
1. Capture current screenshots for Dashboard, Workspace, Context, Models, Connectors, Browser, and Triggers.
2. Replace outline language with task-focused procedures.
3. Add provider credential and endpoint examples.
4. Add self-hosting commands and environment configuration.
5. Add troubleshooting links from every setup guide.
6. Mark coming-soon features clearly and remove those labels only when shipped.
## Maintenance Checks
- Every route in `docs/docs.json` must resolve to a Markdown file.
- Every page must include `title` and `description` frontmatter.
- Feature names should match current UI labels.
- Model providers should be audited whenever `src/lib/llm.ts` changes.
- Local runtimes should be audited whenever `src/pages/Agents/localModels.ts` changes.
- Coming-soon features must not be described as generally available.

117
docs/STYLE_GUIDE.md Normal file
View file

@ -0,0 +1,117 @@
# Eigent Documentation Style Guide
Use this guide when writing or reviewing pages in `docs/`.
## Documentation types
Organize content around the reader's goal:
- **Tutorial:** Helps a new user complete a guided learning experience.
- **How-to guide:** Provides the shortest reliable procedure for a specific goal.
- **Reference:** Describes available options, fields, statuses, or providers.
- **Explanation:** Clarifies concepts, architecture, or design decisions.
Most product pages can combine a short explanation with one or more focused how-to procedures and a compact reference section.
## Standard page structure
Use the following order when it fits the topic:
1. Frontmatter with `title` and `description`
2. One-paragraph overview
3. Prerequisites or **Before you begin**
4. Primary task procedure
5. Feature or option reference
6. Security, privacy, or limitations
7. Troubleshooting
8. Related guides or next steps
Avoid adding sections that do not help the reader complete or understand the task.
## Procedures
- Use numbered steps for multi-step tasks.
- Start each step with an imperative verb.
- State where the action happens before the action.
- Keep one primary action in each step.
- Explain the result after the action when it helps the reader continue.
- Document the shortest accessible path.
- Link to repeated procedures instead of copying them.
## Headings
- Use sentence case.
- Make headings describe the section's content or task.
- Keep headings short.
- Do not skip heading levels.
- Avoid identical headings on the same page.
## Product language
- Match current interface labels.
- Use **Space**, **Project**, **Session**, **Run**, **Context**, **Single Agent**, and **Workforce** consistently.
- Use second person for instructions.
- Prefer present tense and active voice.
- Avoid claims such as “always,” “never,” “best,” or “secure” unless the product guarantees them.
- Mark unavailable features as **Coming soon** and do not provide procedures for them.
## Screenshots
Use a screenshot only when it clarifies a visual UI or a control that is difficult to locate.
When the asset is not ready, leave this visible note:
```md
> **Screenshot placeholder:** Add a screenshot of the relevant UI. Hide credentials and personal data.
```
When adding the final screenshot:
- Crop it to the relevant UI.
- Use consistent operating-system and theme settings.
- Remove personal information with an opaque overlay.
- Add concise, contextual alt text.
- Describe complex information in the surrounding text.
- Do not use a screenshot for code, commands, or terminal output.
## Videos
Prefer MP4 over animated GIF for product walkthroughs.
When the asset is not ready, leave this visible note:
```md
> **Video placeholder:** Add a short MP4 walkthrough. Include captions.
```
When adding the final video:
- Keep it focused on one workflow.
- Include captions.
- Provide a transcript for longer or instructional videos.
- Avoid unnecessary cursor movement and waiting time.
- Use test data and accounts.
## Security and privacy
- Never publish API keys, tokens, cookies, private endpoints, or webhook secrets.
- Use sample data in screenshots and videos.
- State when an action sends data to an external provider.
- Include least-privilege and credential-revocation guidance where relevant.
## Open-source documentation
Keep product docs connected to repository onboarding:
- Explain what the project does and why it is useful.
- Provide a clear setup path.
- Link to support and troubleshooting.
- Document how to run tests and contribute.
- Keep license, README, contributing guidance, and code-of-conduct information discoverable.
## Research references
- [Diátaxis documentation framework](https://diataxis.fr/)
- [Google developer documentation: Procedures](https://developers.google.com/style/procedures)
- [Google developer documentation: Images](https://developers.google.com/style/images)
- [Open Source Guides: Starting an Open Source Project](https://opensource.guide/starting-a-project/)

58
docs/agents/memory.md Normal file
View file

@ -0,0 +1,58 @@
---
title: Agent Memory
description: Understand the context Eigent uses today and the planned direction for persistent agent memory.
icon: brain
---
The Agent Memory page is present in the Agents dashboard but is currently marked **Coming soon**.
<Warning>
Do not rely on this page for persistent cross-project memory. The feature is not generally available in the current product.
</Warning>
## What Eigent remembers today
Current context can come from:
- The active Project conversation
- Earlier Runs in the same Project
- Files in the active Space
- Uploaded task attachments
- Project instructions, rules, and tone
- Enabled Agent Skills
- Tool and connector configuration
These sources are different from a dedicated long-term memory system.
## Expected memory controls
The final feature design is not yet available. Persistent memory is expected to
include controls for:
- What information an agent can store
- Whether memory is scoped to a user, Space, Project, or agent
- How a memory is created
- How users review and edit memories
- How users delete or disable memories
- Retention and synchronization behavior
- Sensitive-data controls
- How memory affects prompts and model usage
> **Screenshot placeholder:** Add a screenshot only after the Memory page contains active controls. Do not use the current Coming soon screen as the primary product image.
> **Video placeholder:** Add a video only after users can create, review, and delete a memory. The video should include all three actions and explain scope.
## Use current alternatives
Until Agent Memory is available:
- Put stable project behavior in project instructions.
- Put reusable expertise in Agent Skills.
- Keep related follow-ups in one Project.
- Store durable reference material in the Space workspace.
## Related guides
- [Workspace instructions](/projects/workspace)
- [Agent Skills](/core/agent-skills)
- [Project runs](/core/project-runs)

98
docs/agents/overview.md Normal file
View file

@ -0,0 +1,98 @@
---
title: Agents overview
description: Configure the models, Skills, sub-agents, tools, and workers that execute Eigent tasks.
icon: bot
---
Agents perform the work requested in an Eigent Project. Their behavior depends on the selected model, assigned tools, Skills, project context, and execution mode.
Use the Agents dashboard to configure reusable capabilities before starting a task.
## Open the Agents dashboard
1. Open the Eigent dashboard.
2. Select **Agents**.
3. Choose **Models**, **Skills**, **Sub-agents**, or **Memory**.
> **Screenshot placeholder:** Add a screenshot of the Agents dashboard with the four navigation items visible. Use a configured model and example Skills, but hide all API keys.
## Configure models
Models provide reasoning and generation capabilities.
Eigent supports:
- Eigent Cloud models
- Cloud providers using your own API keys
- OpenAI-compatible endpoints
- Local inference runtimes
Configure at least one valid model before starting a task. See [Models overview](/models/overview).
## Add Agent Skills
Skills are reusable packages that provide instructions, scripts, templates, and domain knowledge. Eigent loads relevant Skills when a task matches their description.
Use Skills for repeatable workflows such as:
- Writing a specific report format
- Following an engineering process
- Creating branded presentations
- Operating a specialized tool
- Applying organization-specific rules
See [Agent Skills](/core/agent-skills).
## Configure workers
Workers are specialized roles used by Workforce mode. A worker combines:
- Name and role description
- One or more tools
- Model access
- Instructions and Skills
Eigent includes built-in Developer, Browser, Document, and Multimodal workers. Add custom workers when a task needs a recurring role or connector.
## Connect remote sub-agents
Remote sub-agents let Eigent delegate work to an externally hosted agent. The current interface supports a Gemini remote sub-agent configuration.
Use a remote sub-agent when the external system has capabilities or context that should remain outside the local Eigent runtime.
## Agent Memory status
The Memory page is currently marked **Coming soon**. Project conversation history, instructions, files, and Skills are available today, but the separate persistent Agent Memory configuration is not generally available.
## Recommended setup order
1. Configure and validate a model.
2. Install required connectors or MCP servers.
3. Add Skills for reusable workflows.
4. Create or edit Workforce workers.
5. Optional: Configure a remote sub-agent.
6. Start a test Project with a small task.
> **Video placeholder:** Add a 90-second MP4 showing a model setup, Skill upload, custom worker creation, and a successful Workforce task. Include captions and a transcript.
## Security
- Use least-privilege credentials for models and tools.
- Audit untrusted Skills before enabling them.
- Review MCP commands and remote URLs.
- Limit local-folder Spaces to directories the agents should access.
- Remove unused provider keys, cookies, and connector credentials.
## Related guides
<CardGroup>
<Card title="Workers" icon="bot" href="/core/workers">
Create specialized Workforce roles and assign tools.
</Card>
<Card title="Agent Skills" icon="sparkles" href="/core/agent-skills">
Add reusable instructions, scripts, and resources.
</Card>
<Card title="Models overview" icon="brain" href="/models/overview">
Choose managed, BYOK, or local models.
</Card>
</CardGroup>

View file

@ -0,0 +1,93 @@
---
title: Remote sub-agents
description: Connect a remote Gemini agent and delegate work from Eigent.
icon: network-wired
---
Remote sub-agents let Eigent delegate a unit of work to an externally hosted agent and poll for the result. Use them when another agent platform provides specialized capabilities or isolated execution.
The current interface supports a Gemini remote sub-agent provider.
## Before you begin
Prepare:
- A Gemini API key
- The remote service base URL
- The configured remote agent name
- A maximum wall-time value
- A polling interval
Use a dedicated credential with the minimum required permissions.
## Open Sub-agents
1. Open the Eigent dashboard.
2. Select **Agents**.
3. Select **Sub-agents**.
4. Select the Gemini provider.
> **Screenshot placeholder:** Add a screenshot of the Sub-agents configuration page. Blur the API key and any private endpoint.
## Configure the provider
1. Enter the Gemini API key.
2. Confirm or change the base URL.
3. Enter the remote agent name.
4. Set the maximum wall time in seconds.
5. Set the polling interval in seconds.
6. Select **Save**.
Eigent validates the connection before saving an enabled provider.
## Enable the provider
Use the provider switch to enable or disable delegation.
When enabling an existing provider, Eigent validates required fields and the remote connection. If validation fails, the provider returns to its previous state.
## Choose timing values
### Maximum wall time
Maximum wall time limits how long Eigent waits for the remote task to finish. Set it high enough for the expected work, but low enough to prevent indefinite jobs.
### Poll interval
Poll interval controls how frequently Eigent checks the remote task. Short intervals produce faster updates but increase request volume.
Start with conservative values and adjust them after observing typical task duration.
## Reset the provider
1. Open the remote sub-agent configuration.
2. Select the reset action.
3. Confirm the removal.
Reset deletes the stored provider record and restores the default form.
> **Video placeholder:** Add a 45-60 second MP4 showing provider configuration, validation, enable and disable, and reset. Use test credentials and include captions.
## Troubleshooting
### Required-fields error
Confirm the API key, base URL, agent name, maximum wall time, and polling interval. Timing values must be positive numbers.
### Validation fails
Check the API key, endpoint, agent name, network proxy, and provider availability.
### Remote tasks time out
Increase maximum wall time or reduce the scope of delegated work.
### Polling causes rate limits
Increase the polling interval.
## Related guides
- [Agents overview](/agents/overview)
- [General settings](/settings/general)
- [Privacy](/settings/privacy)

View file

@ -0,0 +1,96 @@
---
title: Dispatch and remote control
description: Control an active Eigent Space from a shareable remote web session.
icon: tower-broadcast
---
Dispatch provides channels for interacting with Eigent away from the desktop application.
The currently implemented channel is Remote Control. Telegram, Lark, and WhatsApp appear as future channels.
## Open Dispatch
1. Open a Space.
2. In the project sidebar, select **Dispatch**.
Remote Control requires an active Space because commands and desktop targets are scoped to that Space.
> **Screenshot placeholder:** Add a screenshot of Dispatch with the Remote Control card, connection status, and activity log visible.
## Start a Remote Control session
1. In Dispatch, find **Remote Control**.
2. Select **Start**.
3. Wait for Eigent to create the session.
4. Select **Copy link**.
5. Open the link on the remote device.
The remote page connects to the desktop bridge and targets the selected Space.
## Send a remote follow-up
1. Open the remote link.
2. Confirm the connected desktop target.
3. Enter a follow-up command.
4. Send it.
5. Review status updates on the remote page or desktop.
Remote commands become task input on the desktop side.
## Review activity
The Dispatch activity log can show:
- Session creation
- Remote connection
- Command delivery
- Command status
- Errors
- Session stop
Use it to determine whether a problem occurred in the remote page, server, desktop bridge, or active task.
## Stop a session
1. Return to Dispatch.
2. Select **Stop**.
Stop sessions when remote access is no longer required. A copied link should not be treated as permanent access.
> **Video placeholder:** Add a 60-90 second MP4 showing session creation on desktop, opening the link on mobile, sending a follow-up, receiving it on desktop, and stopping the session. Include captions.
## Messaging channels
Telegram, Lark, and WhatsApp are displayed as Coming soon. The separate Channels dashboard also marks channel support as Coming soon.
<Warning>
Do not document these messaging channels as available until setup and connection controls are enabled.
</Warning>
## Security
- Share remote links only with intended users.
- Stop the session after use.
- Avoid sending credentials through remote prompts.
- Confirm the active Space before creating the link.
- Review activity logs for unexpected commands.
## Troubleshooting
### Remote Control cannot start
Open a Space and confirm the desktop can reach the Eigent server.
### The remote page is disconnected
Confirm that the desktop application is running and the bridge is connected.
### A command does not reach the task
Review Dispatch logs, confirm the target, and retry after the desktop bridge reconnects.
## Related guides
- [Automation overview](/automation/overview)
- [Projects overview](/projects/overview)
- [Privacy](/settings/privacy)

View file

@ -0,0 +1,99 @@
---
title: Automation overview
description: Run Eigent tasks on schedules, webhooks, app events, or remote-control commands.
icon: bolt
---
Automation turns a project prompt into reusable work that can run without manually opening the task composer.
Eigent supports scheduled triggers, webhooks, selected application events, and remote-control commands.
## Open Automations
Use either entry point:
- In the project sidebar, select **Scheduled**.
- In the Home dashboard, select **Triggers**.
The project sidebar focuses on the active Space and Project. The Home dashboard provides a cross-project trigger view.
> **Screenshot placeholder:** Add a screenshot of the Scheduled tab with the trigger list and execution log panel visible.
## Choose an automation type
### Scheduled trigger
Runs a prompt once or on a daily, weekly, monthly, or custom cron schedule.
### Webhook trigger
Creates an HTTP endpoint that starts a task when an external system sends a request.
### Slack trigger
Starts a task from a configured Slack event. Availability depends on connector and trigger configuration.
### Remote control
Dispatch creates a shareable web session that can send follow-up commands to a desktop task in the selected Space.
## Create a trigger
1. Open **Scheduled**.
2. Select **Create**.
3. Enter a trigger name.
4. Select the Project.
5. Enter the task prompt.
6. Choose Schedule or App.
7. Configure timing, event, or webhook values.
8. Save the trigger.
## Manage triggers
You can:
- Edit a trigger
- Activate or deactivate it
- Delete it
- Sort by created time, last execution, or token cost
- Review execution history
- Retry a failed execution
## Review execution logs
Open the execution log panel to see:
- Trigger lifecycle events
- Execution start and completion
- Errors and cancellations
- Webhook receipt
- Token or task metadata when available
Use the logs to distinguish trigger-delivery failures from task-execution failures.
## Control execution
Set:
- Maximum failure count
- Hourly execution limits
- Daily execution limits
- Expiration date for recurring schedules
These controls help prevent a misconfigured trigger from generating unbounded work.
> **Video placeholder:** Add a 90-second MP4 showing a scheduled trigger creation, automatic execution, log review, deactivation, and retry. Include captions.
## Security
- Treat webhook URLs as credentials.
- Restrict app-trigger permissions.
- Review task prompts before enabling recurring execution.
- Add rate limits to event-driven triggers.
- Disable triggers that are no longer monitored.
## Related guides
- [Scheduled triggers](/automation/scheduled-triggers)
- [Webhook and app triggers](/automation/webhook-triggers)
- [Dispatch and remote control](/automation/dispatch)

View file

@ -0,0 +1,103 @@
---
title: Scheduled triggers
description: Run project tasks once or on daily, weekly, and monthly schedules.
icon: clock
---
Scheduled triggers run a saved task prompt at a configured time. Use them for recurring reports, monitoring, content updates, reminders, and other predictable work.
## Before you begin
Prepare:
- A Project in the active Space
- A model and required tools
- A prompt that can run without additional clarification
- A schedule and time zone
Test the prompt manually before automating it.
## Create a one-time schedule
1. Open **Scheduled**.
2. Select **Create**.
3. Enter a trigger name and task prompt.
4. Select **Schedule**.
5. Choose **One time**.
6. Select the date, hour, and minute.
7. Set the maximum failure count.
8. Create the trigger.
## Create a recurring schedule
Choose one of:
- **Daily:** Runs every day at the selected time.
- **Weekly:** Runs on selected weekdays.
- **Monthly:** Runs on a selected day of the month.
- **Custom cron:** Uses a five-part cron expression.
Optional: Set an expiration date so the trigger stops creating new executions.
> **Screenshot placeholder:** Add a screenshot of the schedule picker with weekly frequency, selected weekdays, execution time, expiration, and upcoming-run preview visible.
## Understand time conversion
The schedule picker displays local time and converts it to a UTC cron expression for storage.
Review the upcoming execution preview before saving. Daylight-saving changes can affect local-time expectations for long-running schedules.
## Use a custom cron expression
A standard five-part expression contains:
```text
minute hour day-of-month month day-of-week
```
Example:
```text
0 9 * * 1-5
```
This represents 09:00 on weekdays in the cron time zone used by the system.
Use the visual schedule options when possible because they also provide validation and execution previews.
## Activate or deactivate a schedule
Use the trigger switch to stop or resume future executions without deleting the configuration.
Deactivating a trigger does not cancel a task that already started.
## Review executions
Open execution logs to review:
- Scheduled time
- Start and completion
- Failure details
- Retry status
- Token cost when available
> **Video placeholder:** Add a 60-second MP4 showing weekly schedule creation, upcoming execution preview, activation, and execution-log review. Include captions.
## Troubleshooting
### The trigger ran at the wrong local time
Review the time zone, UTC conversion, and daylight-saving changes.
### No execution was created
Confirm that the trigger is active, has not expired, and still belongs to an available Project.
### Repeated failures stop the trigger
Review the maximum failure count, task prompt, model, and connector availability.
## Related guides
- [Automation overview](/automation/overview)
- [Webhook and app triggers](/automation/webhook-triggers)

View file

@ -0,0 +1,96 @@
---
title: Webhook and app triggers
description: Start Eigent tasks from HTTP requests or supported application events.
icon: webhook
---
Webhook and app triggers start tasks when an external event occurs.
Use a webhook for a custom system. Use an application trigger when Eigent provides a guided integration for the event source.
## Create a webhook trigger
1. Open **Scheduled**.
2. Select **Create**.
3. Enter a trigger name and task prompt.
4. Select **App**.
5. Choose **Webhook**.
6. Select the HTTP method.
7. Configure optional execution settings.
8. Create the trigger.
Eigent generates the webhook URL after creation.
> **Screenshot placeholder:** Add a screenshot of the webhook configuration and the post-creation URL dialog. Obscure most of the URL token.
## Call the webhook
Use the generated URL from the external service. A simplified request can look like:
```bash
curl -X POST "https://example.com/api/your-webhook-url" \
-H "Content-Type: application/json" \
-d '{"event":"new_record","id":"123"}'
```
The real URL and accepted payload depend on the deployment and trigger configuration.
Treat the URL as a credential. Do not commit it to a public repository.
## Configure execution limits
For event-driven triggers, configure:
- Maximum executions per hour
- Maximum executions per day
- Authentication or verification values
- Other dynamically loaded provider settings
Rate limits reduce the impact of loops or high-volume events.
## Create a Slack trigger
1. Install and authenticate the Slack connector.
2. Create a new App trigger.
3. Select **Slack**.
4. Complete the dynamically loaded event configuration.
5. Enter the task prompt.
6. Save and activate the trigger.
A pending-authentication state means additional verification is required.
## Use event data in the task
Write the trigger prompt so the agent understands:
- What the event represents
- Which fields are relevant
- What output to create
- Where to send or store the result
- When to stop or request review
## Review and retry executions
Use execution logs to review event receipt, task creation, completion, and errors. Retry only after fixing the underlying model, credential, prompt, or connector issue.
> **Video placeholder:** Add a 90-second MP4 showing webhook creation, a test `curl` request, execution logs, and a Slack trigger configuration. Include captions.
## Troubleshooting
### The webhook returns an error
Confirm the method, URL, authentication, and deployment base address.
### The event creates too many tasks
Deactivate the trigger, add hourly and daily limits, and fix the external event rule.
### Slack remains pending authentication
Reconnect Slack and complete the required verification fields.
## Related guides
- [Automation overview](/automation/overview)
- [MCP Marketplace](/connectors/mcp-marketplace)
- [Privacy](/settings/privacy)

View file

@ -0,0 +1,84 @@
---
title: Browser connections
description: Launch a managed browser or connect an existing CDP-enabled browser.
icon: globe
---
The browser pool contains Chrome DevTools Protocol sessions that Eigent agents can use.
## Open a new browser
1. Open **Browser > Connections**.
2. Select **Open new browser**.
3. Wait for Eigent to launch the browser and add it to the pool.
The browser item displays its name and debugging port.
> **Screenshot placeholder:** Add a screenshot of the browser pool with two active browsers and their ports.
## Connect an existing browser
Start Chrome or Chromium with remote debugging enabled. For example:
```bash
google-chrome --remote-debugging-port=9222
```
The executable name differs by operating system and installation.
Then:
1. Open **Browser > Connections**.
2. Select **Connect existing browser**.
3. Enter the remote-debugging port.
4. Select **Connect**.
Eigent checks `http://localhost:<port>/json/version` before adding the browser.
## Choose a port
Use a port from `1` to `65535`. The port must:
- Belong to a running CDP-enabled browser
- Not already exist in the Eigent browser pool
- Be reachable from the Eigent application
## Remove a browser
1. Find the browser in the pool.
2. Select its delete action.
3. Confirm the removal.
Removing a browser disconnects it from Eigent. It does not necessarily close an external browser process.
## Use the browser in a task
1. Ensure a Browser worker is available.
2. Start a task that requires web interaction.
3. Open the Browser agent workspace in the Session.
4. Use Take Control when the agent requests manual interaction.
> **Video placeholder:** Add a 60-second MP4 showing Chrome started with remote debugging, connection through port `9222`, and a successful Browser-agent navigation. Include captions.
## Troubleshooting
### Invalid port
Enter a whole number between `1` and `65535`.
### Port already in use
The port is already registered in the browser pool. Use the existing item or start another browser on a different port.
### No browser found
Confirm that the browser is running with remote debugging and that `/json/version` responds.
### The browser disappears after restart
External browser processes and ports can change. Start the browser again and reconnect it.
## Related guides
- [Browser overview](/browser/overview)
- [Browser cookies](/browser/cookies)

81
docs/browser/cookies.md Normal file
View file

@ -0,0 +1,81 @@
---
title: Browser cookies
description: Add authenticated browser sessions and manage cookies by domain.
icon: cookie
---
Browser cookies let agents use authenticated websites without entering credentials during every task.
Cookies can grant account access. Use a dedicated profile and remove sessions that are no longer required.
## Open Cookie management
1. Open the Eigent dashboard.
2. Select **Browser**.
3. Select **Cookies**.
The page groups cookie records by main domain and shows the total cookie count for each group.
> **Screenshot placeholder:** Add a screenshot of the Cookies page with several sample domains and cookie counts. Do not show real customer or personal domains.
## Add authenticated cookies
1. Select **Open browser**.
2. Sign in to the required websites.
3. Close the login browser when finished.
4. Wait for Eigent to refresh the cookie list.
5. Restart Eigent when prompted.
The restart makes the new cookie state available to browser automation.
## Refresh the cookie list
Select the refresh control to reload available domains and counts.
Use refresh after completing another login or when the list appears stale.
## Delete a domain
1. Find the main domain.
2. Select its delete action.
3. Confirm the deletion.
Eigent deletes cookies for the main domain and its listed subdomains.
## Delete all cookies
1. Select **Delete all**.
2. Confirm the action.
3. Restart Eigent when prompted.
This removes all browser cookie records managed by this feature.
> **Video placeholder:** Add a 60-second MP4 showing login, cookie import, domain deletion, and restart. Use a test account and include captions.
## Security guidance
- Prefer test or dedicated automation accounts.
- Do not import sessions with broad administrative access unless required.
- Remove cookies after temporary work.
- Protect local user data and backups containing browser state.
- Never include cookie values in screenshots or support requests.
## Troubleshooting
### No new cookies appear
Confirm that login completed, the login browser was closed, and the target site actually stored cookies.
### A website still asks for login
Restart Eigent, confirm the domain appears in the list, and check whether the website uses another domain or additional authentication.
### Deleting cookies does not sign out immediately
Restart Eigent and close other browser sessions. The service can also maintain server-side sessions until they expire or are revoked.
## Related guides
- [Browser overview](/browser/overview)
- [Browser connections](/browser/connections)
- [Privacy](/settings/privacy)

70
docs/browser/overview.md Normal file
View file

@ -0,0 +1,70 @@
---
title: Browser overview
description: Give Eigent agents controlled access to browser sessions and authenticated websites.
icon: compass
---
Eigent can launch or connect to Chrome DevTools Protocol browsers for research and browser automation. Browser agents can navigate pages, interact with controls, capture screenshots, and maintain session state.
## Open Browser settings
1. Open the Eigent dashboard.
2. Select **Browser**.
3. Choose **Connections**, **Plugins**, or **Cookies**.
> **Screenshot placeholder:** Add a screenshot of the Browser settings page with the three navigation items and an active browser pool.
## Browser Connections
Connections manage browsers available to agents. You can:
- Open a new managed browser
- Connect an existing CDP-enabled browser
- Review browser names and ports
- Remove a browser from the pool
See [Browser connections](/browser/connections).
## Browser Cookies
Cookies let agents use authenticated sessions. Open a dedicated login browser, sign in to required services, then let Eigent import the resulting cookie domains.
See [Browser cookies](/browser/cookies).
## Browser Plugins
Browser Plugins are currently marked **Coming soon**.
<Note>
Do not present browser extension or plugin features as available until the product page includes active installation controls.
</Note>
## Use a browser in a Session
When a Browser agent starts work, its workspace appears in the Project Session.
The agent can:
- Search and navigate
- Click and type
- Read page content
- Capture visual state
- Use available authenticated cookies
When manual interaction is required, use **Take Control**, complete the action, and return control to the agent.
## Security
- Use a dedicated browser profile.
- Avoid storing unnecessary privileged sessions.
- Delete cookies when a task no longer needs them.
- Review actions before giving an agent access to sensitive services.
- Do not connect a remote-debugging port to an untrusted network.
> **Video placeholder:** Add a 60-second MP4 showing a browser connection, a Browser-agent task, Take Control, and return of control. Include captions.
## Related guides
- [Browser connections](/browser/connections)
- [Browser cookies](/browser/cookies)
- [Google Search](/connectors/google-search)

View file

@ -0,0 +1,107 @@
---
title: Custom MCP servers
description: Add local command-based or remote URL-based Model Context Protocol servers.
icon: wrench
---
Use a custom Model Context Protocol server when you need a tool that is not included in Eigent's supported integration catalog.
Eigent supports:
- Local MCP servers started with a command
- Remote MCP servers reached through a URL
## Review the server before installation
An MCP server can read data, call APIs, or execute actions. Before adding one:
- Read its source code or trusted documentation.
- Review requested permissions.
- Inspect commands and arguments.
- Confirm how credentials are stored.
- Test it with a restricted account.
## Add a local MCP server
1. Open **Connectors**.
2. Select **Add MCP**.
3. Choose **Local**.
4. Paste the MCP JSON configuration.
5. Review the command and arguments.
6. Select **Install**.
Example:
```json
{
"mcpServers": {
"sequential-thinking": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
}
}
}
```
Use an absolute executable path when the Electron process cannot resolve the command through the normal shell environment.
> **Screenshot placeholder:** Add a screenshot of the local MCP JSON dialog with a safe example server configuration.
## Add a remote MCP server
1. Open **Connectors**.
2. Select **Add MCP**.
3. Choose **Remote**.
4. Enter a display name.
5. Enter the remote server URL.
6. Save the configuration.
Use HTTPS for remote servers outside a trusted local network.
## Configure environment variables
1. Select the MCP server.
2. Open its environment configuration.
3. Add the required keys and values.
4. Save.
Never place production secrets directly in public configuration examples.
## Enable and test the server
1. Enable the MCP server.
2. Add it to a test worker.
3. Start a small task that uses one tool.
4. Review the task log for the tool call and result.
## Edit or delete a server
Use the server actions to update command arguments, URL, description, or environment values. Delete the server when it is no longer required.
Deleting an MCP entry does not revoke credentials at the external service.
> **Video placeholder:** Add a 90-second MP4 showing local and remote MCP setup, environment configuration, worker assignment, and a test call. Include captions.
## Troubleshooting
### The local command is not found
Use an absolute path or ensure the executable is installed in the environment used by Eigent.
### The process exits immediately
Run the command in a terminal and inspect its output. Confirm arguments and required environment variables.
### A remote URL cannot be reached
Check DNS, TLS, authentication, proxy settings, and firewall rules.
### Tools do not appear
Enable the MCP server, restart it if required, and assign it to the worker.
## Related guides
- [Connectors overview](/connectors/overview)
- [MCP Marketplace](/connectors/mcp-marketplace)
- [Workers](/core/workers)

View file

@ -0,0 +1,78 @@
---
title: Google Search
description: Configure web search for managed and self-hosted Eigent deployments.
icon: magnifying-glass
---
Google Search provides current web results for Browser agents and research workflows.
## Determine your setup
### Managed Eigent mode
Google Search can be enabled by default and does not require user credentials.
### Self-hosted or custom mode
Provide:
- Google API key
- Google Custom Search Engine ID
## Create Google credentials
1. In Google Cloud, create or select a project.
2. Enable the Custom Search JSON API.
3. Create an API key with appropriate restrictions.
4. Create or select a Programmable Search Engine.
5. Copy its Search Engine ID.
Use Google's current Custom Search documentation for account-specific steps and quota information.
## Configure Search in Eigent
1. Open **Connectors**.
2. Select **Google Search**.
3. Enter the Google API key.
4. Enter the Search Engine ID.
5. Save the configuration.
> **Screenshot placeholder:** Add a screenshot of the Google Search configuration form. Blur the complete API key and Search Engine ID.
## Test Search
Start a small Browser-agent task, for example:
> Find the three most recent official release notes for Eigent and return their publication dates and source links.
Review the task log to confirm that the search tool returned results.
## Control cost and quota
Google Custom Search can enforce daily quotas or billing limits. Use a restricted key and monitor usage in Google Cloud.
## Troubleshooting
### Invalid API key
Confirm that the key is active, the Custom Search JSON API is enabled, and API restrictions allow the service.
### Invalid Search Engine ID
Copy the identifier from the Programmable Search Engine control panel, not the display name.
### Empty results
Review the search engine's site scope and settings. A search engine restricted to selected sites will not return the full web.
### Quota exceeded
Review the current quota and billing settings in Google Cloud.
> **Video placeholder:** Add a 45-second MP4 showing credential entry, saving, and a successful Browser-agent search. Include captions.
## Related guides
- [Connectors overview](/connectors/overview)
- [Browser overview](/browser/overview)
- [Self-hosting](/get_started/self-hosting)

View file

@ -0,0 +1,92 @@
---
title: MCP Marketplace
description: Install, configure, enable, and remove supported connector integrations.
icon: store
---
The MCP Marketplace provides guided installation for supported services. Use it before creating a custom MCP configuration because marketplace integrations include service-specific defaults and credential fields.
## Browse integrations
1. Open **Connectors**.
2. Expand the supported integration section.
3. Use search to find a service.
4. Select the integration.
Connected services appear before unconnected services. Coming-soon services appear after available integrations.
> **Screenshot placeholder:** Add a screenshot of the connector catalog with one connected integration, one available integration, and one Coming soon item.
## Install an integration
The exact flow depends on the service:
1. Select the integration.
2. Select **Install** or **Connect**.
3. Complete OAuth or enter required environment variables.
4. Save the configuration.
5. Enable the connector.
Notion and other services can open a dedicated authentication flow. Other integrations request keys or tokens directly.
## Configure environment variables
1. Select a connected integration.
2. Open its configuration.
3. Enter each required environment value.
4. Save the changes.
Use credentials created specifically for Eigent. Avoid personal administrator tokens.
## Enable or disable an integration
Use the connector switch to control whether its tools are available.
Disabling a connector preserves its configuration but prevents new agent use. Existing external sessions can remain active at the provider until revoked.
## Edit an integration
1. Open the integration actions.
2. Select **Edit** or **Configure**.
3. Update the required values.
4. Save.
5. Run a test task.
## Uninstall an integration
1. Open the integration actions.
2. Select **Uninstall**.
3. Confirm the action.
Uninstalling removes the Eigent connector configuration. Revoke OAuth grants or provider tokens separately when required.
## Assign the integration to a worker
1. Open the Workspace.
2. Add or edit a worker.
3. Select the integration from **Agent Tool**.
4. Save the worker.
The worker can use only the tools assigned to it.
> **Video placeholder:** Add a 60-second MP4 showing installation, credential configuration, enable and disable, and worker assignment for one integration. Include captions.
## Troubleshooting
### Installation completes but the connector is not shown as connected
Refresh the connector list and confirm that required credentials were saved.
### A tool returns an authorization error
Reconnect the integration or replace the expired credential.
### The desired service is not listed
Use [Custom MCP servers](/connectors/custom-mcp).
## Related guides
- [Connectors overview](/connectors/overview)
- [Workers](/core/workers)
- [Privacy](/settings/privacy)

103
docs/connectors/overview.md Normal file
View file

@ -0,0 +1,103 @@
---
title: Connectors overview
description: Extend Eigent with hosted integrations, Google Search, and custom MCP servers.
icon: plug
---
Connectors give agents access to external services and tools. A connector can search data, read or write records, send messages, access calendars, or expose a custom capability through the Model Context Protocol (MCP).
## Open Connectors
1. Open the Eigent dashboard.
2. Select **Connectors**.
The page combines supported integrations, Google Search, and user-managed MCP servers.
> **Screenshot placeholder:** Add a screenshot of the Connectors page showing connected integrations, available integrations, and the Your MCP section. Hide account names and credentials.
## Connector types
### Supported integrations
Supported integrations provide a guided setup for known services. The current interface can include:
- Notion
- Slack
- Google Calendar
- Gmail
- LinkedIn
- Lark
- Telegram
- Cursor
- VS Code
Catalog availability can vary by deployment.
### Google Search
Google Search provides current web results for Browser agents and research workflows. Managed mode can enable it by default; self-hosted mode requires Google Custom Search credentials.
### Custom MCP servers
Add a local command-based server or a remote MCP URL when the required service is not in the supported catalog.
## Understand connector status
Connected integrations appear before unconnected ones. A connector can provide:
- Install or authentication action
- Enable or disable switch
- Configuration form
- Environment variables
- Edit and delete actions
Some items remain visible as future integrations.
<Note>
X, WhatsApp, Reddit, and GitHub are marked Coming soon in the current connector interface. Do not describe them as generally available until their controls are enabled.
</Note>
## Assign tools to agents
Installing a connector makes its tools available to Eigent. To use it in Workforce:
1. Open the Workspace.
2. Add or edit a worker.
3. Open the tool selector.
4. Select the connector.
5. Save the worker.
Describe the service and expected operation in the task prompt.
## Security
Connectors can perform actions in external systems.
- Use accounts and credentials with minimum permissions.
- Review OAuth consent and environment variables.
- Audit custom MCP commands and remote URLs.
- Disable connectors that are not required.
- Remove credentials before sharing screenshots or logs.
> **Video placeholder:** Add a 90-second MP4 showing a supported integration install, a custom MCP server, worker assignment, and a successful tool call. Include captions.
## Troubleshooting
### A connector is installed but unused
Assign it to the relevant worker and make the intended action explicit in the task.
### Authentication expires
Open the connector configuration and repeat its authentication flow.
### An MCP server does not start
Run the configured command independently and review its environment variables and executable path.
## Related guides
- [MCP Marketplace](/connectors/mcp-marketplace)
- [Custom MCP servers](/connectors/custom-mcp)
- [Google Search](/connectors/google-search)
- [Workers](/core/workers)

View file

@ -27,19 +27,19 @@ Eigent provides pre-built Agent Skills for common tasks, and you can create or u
- **Example Skills:** These are pre-built Agent Skills available to all users on Eigent. They operate seamlessly behind the scenes, and Eigent utilizes them without requiring any manual setup. You have the option to manually enable or disable it.
<video controls className="w-full aspect-video rounded-xl" src="/docs/images/agent_skills_example_skills_04.mp4"></video>
<video controls className="w-full aspect-video rounded-xl" src="/images/agent_skills_example_skills_04.mp4" alt="Enable or disable example Agent Skills in Eigent"></video>
- **Custom Skills:** These allow you to package your specific domain expertise and organizational knowledge. They are available across your Eigent workforce, and you can assign them to specific agents. You can create them directly within the Skill interface or add them via Eigent's settings.
![Screenshot 2026-02-24 at 21.58.11.png](/docs/images/agent_skills_settings_screenshot.png)
![Screenshot 2026-02-24 at 21.58.11.png](/images/agent_skills_settings_screenshot.png)
Upload your own Skills as zip files through Homepage > Agents > Skills. Custom Skills are individual to each user and saved locally.
<video controls className="w-full aspect-video rounded-xl" src="/docs/images/agent_skills_skill01.mp4"></video>
<video controls className="w-full aspect-video rounded-xl" src="/images/agent_skills_skill01.mp4" alt="Upload a custom Agent Skill in Eigent"></video>
You can upload a standalone `SKILL.md` file or a complete `.zip` skill package. If uploading a package, it must contain a `SKILL.md` file in its root directory. In either case, the `SKILL.md` file must define the Skill's name and description using YAML formatting.
<video controls className="w-full aspect-video rounded-xl" src="/docs/images/agent_skills_skill02.mp4"></video>
<video controls className="w-full aspect-video rounded-xl" src="/images/agent_skills_skill02.mp4" alt="Configure the metadata for a custom Agent Skill"></video>
Every Skill requires a `SKILL.md` file with YAML frontmatter:
@ -60,12 +60,12 @@ description: Brief description of what this Skill does and when to use it
Eigent supports uploading multiple skills within one zip file, but please ensure the contents of each skill folder are complete.
<video controls className="w-full aspect-video rounded-xl" src="/docs/images/agent_skills_skills_05.mp4"></video>
<video controls className="w-full aspect-video rounded-xl" src="/images/agent_skills_skills_05.mp4" alt="Upload multiple Agent Skills from a package"></video>
## Using Skills
To test your Skill file immediately, click the **Try in chat** button.
<video controls className="w-full aspect-video rounded-xl" src="/docs/images/agent_skills_skill03.mp4"></video>
<video controls className="w-full aspect-video rounded-xl" src="/images/agent_skills_skill03.mp4" alt="Test an Agent Skill using Try in chat"></video>
Use Skills only from trusted sources. Malicious Skills can misuse tools or execute unintended actions, potentially causing data leaks or unauthorized access—so carefully audit any untrusted Skill before use.

View file

@ -10,7 +10,7 @@ Autonomous agents tailored to specific roles that run tasks independently or tog
Each Worker is designed with specific capabilities and can be customized to handle particular types of tasks efficiently.
![Workers concept illustration](/docs/images/concepts_worker.png)
> **Screenshot placeholder:** Add a current screenshot for “Workers concept illustration”.
## Workforce
@ -18,7 +18,7 @@ A coordinated team of Workers that collaborate to complete complex workflows. Th
The Workforce orchestrates multiple Workers, ensuring they work together seamlessly to achieve your goals.
![Workforce collaboration illustration](/docs/images/concepts_workforce.gif)
> **Video placeholder:** Add a current video walkthrough for “Workforce collaboration illustration”. Include captions.
## Workspace
@ -26,7 +26,7 @@ A live window into a Worker's process where you can watch or take control. For e
Workspaces provide real-time visibility into what your Workers are doing, allowing you to monitor progress and intervene when needed.
![Workspace interface illustration](/docs/images/concepts_workspace.gif)
> **Video placeholder:** Add a current video walkthrough for “Workspace interface illustration”. Include captions.
## Tasks & Subtasks
@ -34,7 +34,7 @@ You define a mission (task), the Workforce breaks it into components (subtasks),
This hierarchical approach ensures complex projects are broken down into manageable pieces and executed efficiently.
![Tasks and subtasks breakdown illustration](/docs/images/concepts_tasks_subtasks.gif)
> **Video placeholder:** Add a current video walkthrough for “Tasks and subtasks breakdown illustration”. Include captions.
## Chat
@ -42,7 +42,7 @@ Your primary interface for communicating with your Workforce. You use it to defi
The Chat interface serves as your command center, where you can give instructions, ask questions, and receive updates from your AI team.
![Chat interface illustration](/docs/images/concepts_chat.png)
> **Screenshot placeholder:** Add a current screenshot for “Chat interface illustration”.
## MCP
@ -50,7 +50,7 @@ Model Context Protocol that allows Workers to use external tools. It connects yo
MCP extends your Workers' capabilities by providing access to real-world data and tools, making them more powerful and versatile.
![MCP protocol illustration](/docs/images/concepts_mcp.png)
> **Screenshot placeholder:** Add a current screenshot for “MCP protocol illustration”.
## Models
@ -58,4 +58,4 @@ Different AI "brains" that power your Workers. Eigent allows you to choose from
Choose the right model for each task based on your specific needs for performance, accuracy, or cost efficiency.
![AI models illustration](/docs/images/concepts_models.png)
> **Screenshot placeholder:** Add a current screenshot for “AI models illustration”.

View file

@ -25,7 +25,7 @@ description: Configure your own API keys to use various LLM providers with Eigen
1. Find the **OpenAI** card in the Custom Model section
![byok_1](/docs/images/byok_1.png)
![byok_1](/images/byok_1.png)
1. Fill in the following fields:
@ -68,20 +68,28 @@ When saving your configuration, Eigent validates your API key and model. Here ar
Eigent supports the following BYOK providers:
| Provider | Default API Host | Official Documentation |
| --------------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| **OpenAI** | `https://api.openai.com/v1` | [OpenAI API Docs](https://platform.openai.com/docs/api-reference) |
| **Anthropic** | `https://api.anthropic.com/` | [Anthropic API Docs](https://docs.anthropic.com/en/api/getting-started) |
| **Google Gemini** | `https://generativelanguage.googleapis.com/v1beta/openai/` | [Gemini API Docs](https://ai.google.dev/gemini-api/docs) |
| **OpenRouter** | `https://openrouter.ai/api/v1` | [OpenRouter Docs](https://openrouter.ai/docs) |
| **OrcaRouter** | `https://api.orcarouter.ai/v1` | [OrcaRouter Docs](https://docs.orcarouter.ai/) |
| **Qwen (Alibaba)** | `https://dashscope.aliyuncs.com/compatible-mode/v1` | [Qwen API Docs](https://help.aliyun.com/zh/dashscope/developer-reference/api-details) |
| **DeepSeek** | `https://api.deepseek.com` | [DeepSeek API Docs](https://platform.deepseek.com/api-docs) |
| **Minimax** | `https://api.minimax.io/v1` | [Minimax API Docs](https://platform.minimaxi.com/document/Announcement) |
| **Z.ai** | `https://api.z.ai/api/coding/paas/v4/` | [Z.ai Platform](https://z.ai) |
| **Azure OpenAI** | _(user-provided)_ | [Azure OpenAI Docs](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference) |
| **AWS Bedrock** | _(user-provided)_ | [AWS Bedrock Docs](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html) |
| **OpenAI Compatible** | _(user-provided)_ | For custom endpoints (e.g., xAI, local servers) |
| Provider | Default API Host | Official Documentation |
| ------------------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| **Google Gemini** | `https://generativelanguage.googleapis.com/v1beta/openai/` | [Gemini API Docs](https://ai.google.dev/gemini-api/docs) |
| **OpenAI** | `https://api.openai.com/v1` | [OpenAI API Docs](https://platform.openai.com/docs/api-reference) |
| **Anthropic** | `https://api.anthropic.com` | [Anthropic API Docs](https://docs.anthropic.com/en/api/getting-started) |
| **OrcaRouter** | `https://api.orcarouter.ai/v1` | [OrcaRouter Docs](https://docs.orcarouter.ai/) |
| **OpenRouter** | `https://openrouter.ai/api/v1` | [OpenRouter Docs](https://openrouter.ai/docs) |
| **Nebius Token Factory** | `https://api.tokenfactory.nebius.com/v1` | [Nebius Token Factory Docs](https://docs.tokenfactory.nebius.com/quickstart) |
| **Qwen (Alibaba)** | `https://dashscope.aliyuncs.com/compatible-mode/v1` | [Qwen API Docs](https://help.aliyun.com/zh/dashscope/developer-reference/api-details) |
| **DeepSeek** | `https://api.deepseek.com` | [DeepSeek API Docs](https://platform.deepseek.com/api-docs) |
| **MiniMax** | `https://api.minimax.io/v1` | [MiniMax API Docs](https://platform.minimax.io/docs/api-reference/api-overview) |
| **Z.ai** | `https://api.z.ai/api/coding/paas/v4/` | [Z.ai Developer Docs](https://zhipu-32152247.mintlify.app/api-reference/introduction) |
| **Moonshot** | `https://api.moonshot.ai/v1` | [Moonshot AI Platform](https://platform.moonshot.ai/) |
| **ModelArk** | `https://ark.ap-southeast.bytepluses.com/api/v3` | [ModelArk Docs](https://docs.byteplus.com/en/docs/ModelArk/1298459) |
| **SambaNova** | `https://api.sambanova.ai/v1` | [SambaNova API Reference](https://docs.sambanova.ai/docs/en/api-reference/overview) |
| **Grok** | `https://api.x.ai/v1` | [xAI Docs](https://docs.x.ai/docs/introduction) |
| **Mistral** | `https://api.mistral.ai` | [Mistral API Docs](https://docs.mistral.ai/api) |
| **AWS Bedrock** | `https://bedrock-mantle.us-east-1.api.aws/v1` | [AWS Bedrock Docs](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html) |
| **AWS Bedrock Converse** | `https://bedrock-runtime.us-east-1.amazonaws.com` | [Bedrock Converse API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html) |
| **Azure OpenAI** | _(user-provided)_ | [Azure OpenAI Docs](https://learn.microsoft.com/en-us/azure/ai-services/openai/reference) |
| **Baidu ERNIE** | `https://qianfan.baidubce.com/v2` | [Baidu Qianfan Docs](https://intl.cloud.baidu.com/doc/qianfan/index.html) |
| **OpenAI Compatible** | _(user-provided)_ | For custom endpoints (e.g., xAI, local servers) |
## Tips

View file

@ -16,7 +16,7 @@ description: This guide walks you through setting up your Baidu ERNIE API key wi
- Launch Eigent and navigate to the **Home Page**.
- Click on the **Agent** tab, then click on the **Models** button.
![Ernie 1 Pn](/docs/images/model_setting.png)
![Ernie 1 Pn](/images/model_setting.png)
#### 2. Locate Model Configuration
@ -34,7 +34,7 @@ Click on the Ernie card and fill in the following fields:
- _Example:_ `ernie-5.0`
- **Save:** Click the **Save** button to apply your changes.
![Ernie 2 Pn](/docs/images/ernie.png)
![Ernie 2 Pn](/images/ernie.png)
#### 4. Set as Default & Verify

View file

@ -16,7 +16,7 @@ description: This guide walks you through setting up your Google Gemini API key
- Launch Eigent and navigate to the **Home Page**.
- Click on the **Agent** tab, then click on the **Models** button.
![Gemini 1 Pn](/docs/images/model_setting.png)
![Gemini 1 Pn](/images/model_setting.png)
#### 2. Locate Model Configuration
@ -34,7 +34,7 @@ Click on the Gemini Config card and fill in the following fields:
- _Example:_ `gemini-3-pro-preview`
- **Save:** Click the **Save** button to apply your changes.
![Gemini 3 Pn](/docs/images/gemini.png)
![Gemini 3 Pn](/images/gemini.png)
#### 4. Set as Default & Verify

View file

@ -16,7 +16,7 @@ description: This guide walks you through setting up your Kimi (Moonshot AI) API
- Launch Eigent and navigate to the **Home Page**.
- Click on the **Agent** tab, then click on the **Models** button.
![Kimi 1 Pn](/docs/images/model_setting.png)
![Kimi 1 Pn](/images/model_setting.png)
#### 2. Locate Model Configuration
@ -34,7 +34,7 @@ Click on the Moonshot card and fill in the following fields:
- _Example:_ `kimi-k2.5`
- **Save:** Click the **Save** button to apply your changes.
![Kimi 3 Pn](/docs/images/kimi.png)
![Kimi 3 Pn](/images/kimi.png)
#### 4. Set as Default & Verify

View file

@ -45,13 +45,13 @@ ollama pull qwen2.5:7b
2. Setting your model
![set_local_model](/docs/images/models_local_model.png)
> **Screenshot placeholder:** Add a current screenshot for “set_local_model”.
3. Configure the Google Search toolkit
![configure_searchtools](/docs/images/models_configure_tools.png)
> **Screenshot placeholder:** Add a current screenshot for “configure_searchtools”.
<img src="/docs/images/models_configure_tools_key.png" alt="configure_searchtoolsapi" /> You can refer to the following document for detailed information on how to configure **GOOGLE_API_KEY** and **SEARCH_ENGINE_ID :** https://developers.google.com/custom-search/v1/overview
> **Screenshot placeholder:** Add a current screenshot for “configure_searchtoolsapi”. You can refer to the following document for detailed information on how to configure **GOOGLE_API_KEY** and **SEARCH_ENGINE_ID :** https://developers.google.com/custom-search/v1/overview
## **API KEY Reference**

View file

@ -17,7 +17,7 @@ description: This guide walks you through setting up your MiniMax API key within
- Click on the **Settings** tab (usually located in the sidebar or top
navigation).
![Minimax 1 Pn](/docs/images/model_setting.png)
![Minimax 1 Pn](/images/model_setting.png)
#### 2. Locate Model Configuration
@ -25,7 +25,7 @@ description: This guide walks you through setting up your MiniMax API key within
- Scroll down to the **Custom Model** area.
- Look for the **Minimax Config** card.
![Minimax 2 Pn](/docs/images/minimax_1.png)
> **Screenshot placeholder:** Add a current screenshot for “Minimax 2 Pn”.
#### 3. Enter API Details
@ -37,7 +37,7 @@ Click on the Minimax Config card and fill in the following fields:
- _Example:_ `MiniMax-M2.1`
- **Save:** Click the **Save** button to apply your changes.
![Minimax 3 Pn](/docs/images/minimax_2.png)
> **Screenshot placeholder:** Add a current screenshot for “Minimax 3 Pn”.
#### 4. Set as Default & Verify
@ -45,6 +45,6 @@ Click on the Minimax Config card and fill in the following fields:
selected/active.
- **You are ready to go.** Your Eigent agents can now utilize the Minimax model.
![Minimax 4 Pn](/docs/images/minimax_3.png)
> **Screenshot placeholder:** Add a current screenshot for “Minimax 4 Pn”.
---

View file

@ -16,7 +16,7 @@ description: This guide walks you through setting up your SambaNova API key with
- Launch Eigent and navigate to the **Home Page**.
- Click on the **Agent** tabthen click on the **Models** button.
![SambaNova 1 Pn](/docs/images/model_setting.png)
![SambaNova 1 Pn](/images/model_setting.png)
#### 2. Locate Model Configuration
@ -34,7 +34,7 @@ Click on the SambaNova card and fill in the following fields:
- _Example:_ `DeepSeek-V3.1`
- **Save:** Click the **Save** button to apply your changes.
![SambaNova 2 Pn](/docs/images/sambanova.png)
![SambaNova 2 Pn](/images/sambanova.png)
#### 4. Set as Default & Verify

121
docs/core/project-runs.md Normal file
View file

@ -0,0 +1,121 @@
---
title: Project runs
description: Continue a project with follow-up requests and switch between each run's progress, context, and outputs.
icon: rotate
---
Use follow-up requests to continue working in the same Project without losing earlier history. Eigent saves the original task and each follow-up as a separate **Run**.
The Run selector appears in the Session side panel after a Project contains at least two Runs.
## Understand Runs
The first request in a Project is **Run 1**. The first follow-up is **Run 2**, and later follow-ups continue in chronological order.
Each Run can have its own:
- Prompt and attachments
- Status
- Plan and subtasks
- Assigned agents
- Execution context
- Browser and terminal state
- Generated files
> **Screenshot placeholder:** Add a screenshot of a Project with **Run 2** selected and the Run dropdown open. Show at least one completed Run and one active Run.
## Create another Run
1. Open a Project.
2. In the Session composer, enter a follow-up request.
3. Attach any new files.
4. Send the request.
5. In Workforce mode, review and start the new plan.
Eigent adds the request to the same conversation and updates the Run selector.
Use a follow-up when the new request depends on previous work. Create another Project when the goal, file boundary, or audience is unrelated.
## Switch Runs
1. Open the Session side panel.
2. Select **Run N** in the panel header.
3. Select a Run from the dropdown.
The dropdown lists the newest Run first. Each item includes:
- Run number
- Prompt preview
- Status indicator
- Checkmark for the selected Run
Selecting a Run scrolls the conversation to that request and updates the Session side panel.
## Understand status indicators
| Indicator | Meaning |
| ----------------- | --------------------------- |
| Pulsing brand dot | Pending or running |
| Green dot | Finished |
| Red dot | Failed |
| Neutral dot | Inactive or no final status |
## Review Run-specific content
Selecting a Run updates the available:
- Workforce or Single Agent progress
- Agents and subtasks
- Execution context
- Uploaded and generated files
- Browser workspace
- Terminal workspace
- Expanded Workforce view
Opening a file or selecting a subtask acts on the selected Run instead of automatically using the latest Run.
## Scroll through Run history
The Run selector and conversation remain synchronized:
- Selecting a Run scrolls the conversation to it.
- Manually scrolling to another Run updates the Run label.
- After a dropdown selection, Eigent keeps the selected Run while smooth scrolling reaches the requested position.
> **Video placeholder:** Add a 45-60 second MP4 showing Run selection, automatic chat scrolling, manual scrolling, and the side panel changing between two Runs. Include captions.
## Example workflow
Suppose Run 1 asks Eigent to research a market and create a report.
1. Add competitor pricing as Run 2.
2. Turn the updated findings into a presentation as Run 3.
3. Select Run 1 to review the original research.
4. Select Run 2 to inspect pricing outputs.
5. Select Run 3 to monitor presentation creation.
All three Runs remain in one Project.
## Troubleshooting
### The Run selector is not visible
The Project contains only one Run, or the follow-up has not been added to the conversation.
### The side panel changes while you scroll
The selected Run follows the Run most visible in the conversation. Select a Run from the dropdown to return to it.
### An older Run has no workspace
That Run might not have used the selected agent, browser, terminal, or output type.
### A Run does not appear
A Run needs a user prompt. Wait for the follow-up to appear in the conversation, then reopen the selector.
## Related guides
- [Projects overview](/projects/overview)
- [Sessions](/projects/sessions)
- [Context and files](/projects/context-and-files)

View file

@ -10,20 +10,20 @@ icon: plug
1. Click Settings
![click_settings](/docs/images/models_settings.png)
> **Screenshot placeholder:** Add a current screenshot for “click_settings”.
2. Click Add MCP Server
![add_mcp](/docs/images/tools_add_mcp.png)
> **Screenshot placeholder:** Add a current screenshot for “add_mcp”.
3. Configure Your MCP Server and install
![configure_mcp](/docs/images/tools_configure_mcp.png)
> **Screenshot placeholder:** Add a current screenshot for “configure_mcp”.
4.Add external servers to your own Agent
- You can check the installed mcp server in the Added external servers column
![check_mcp](/docs/images/tools_check.png)
> **Screenshot placeholder:** Add a current screenshot for “check_mcp”.
- After configuring your mcp server, you can add it to a Custom Agent.

View file

@ -26,7 +26,7 @@ Always treat your API keys and access tokens like passwords. Eigent stores them
</aside>
![add mcp servers.gif](/docs/images/add_mcp_servers.gif)
> **Video placeholder:** Add a current video walkthrough for “add mcp servers.gif”. Include captions.
## Creating and Equipping a Custom Worker
@ -39,7 +39,7 @@ Once you've configured a new MCP server, you need to create a worker that knows
- Select the custom MCP server you just configured (e.g., Github MCP). You can also add any other tools you want this worker to have.
- Click **Save**.
![add worker.gif](/docs/images/add_worker.gif)
> **Video placeholder:** Add a current video walkthrough for “add worker.gif”. Include captions.
## Whats next?

View file

@ -27,7 +27,8 @@ With Workforce, agents plan, solve, and verify work together—like a project te
### **Architecture: How Workforce Works**
Workforce uses a **hierarchical, modular design** for real-world team problem-solving.
![Workforce](/docs/images/workforce.jpg)
> **Screenshot placeholder:** Add a current screenshot for “Workforce”.
See how the coordinator and task planner agents orchestrate a multi-agent workflow:
@ -77,6 +78,7 @@ _A skilled coding assistant that can write and execute code, run terminal comman
- TerminalToolkit
- NoteTakingToolkit
- WebDeployToolkit
- SkillToolkit
### BrowserAgent
@ -89,6 +91,7 @@ _Can search the web, extract webpage content, simulate browser actions, and prov
- HumanToolkit
- NoteTakingToolkit
- TerminalToolkit
- SkillToolkit
### DocumentAgent
@ -105,6 +108,7 @@ _A document processing assistant for creating, modifying, and managing various d
- TerminalToolkit
- GoogleDriveMCPToolkit
- SearchToolkit
- SkillToolkit
### Multi-ModalAgent
@ -114,12 +118,12 @@ _A multi-modal processing assistant for analyzing and generating media content l
- VideoDownloaderToolkit
- AudioAnalysisToolkit
- ImageAnalysisToolkit
- OpenAIImageToolkit
- HumanToolkit
- TerminalToolkit
- NoteTakingToolkit
- SearchToolkit
- SkillToolkit
## Toolkit Reference
@ -163,12 +167,6 @@ _Provides a powerful, stateful browser for web navigation and interaction._
This toolkit gives an agent a fully-featured web browser that it can control programmatically. Unlike simple web scraping, this toolkit maintains a session, allowing the agent to click, type, hover, screenshot, and live _Take Control_ from the UI.
### [ImageAnalysisToolkit](https://docs.camel-ai.org/reference/camel.toolkits.image_analysis_toolkit)
_Provides tools for understanding the content of images._
This toolkit enables an agent to "see" and interpret images. It can generate a detailed text description of an image or answer specific questions about what an image contains. This is crucial for tasks that involve visual data, such as describing products, analyzing charts, or identifying objects in a photo.
### [MarkItDownToolkit](https://docs.camel-ai.org/reference/camel.toolkits.markitdown_toolkit)
_A specialized toolkit for converting content into clean Markdown._
@ -199,6 +197,12 @@ _Provides access to various web search engines._
This toolkit is the primary tool for web research. It allows an agent to search information on engines like Google, Wikipedia, Bing, and Baidu. The agent can submit a query and receive a list of relevant URLs and snippets, which it can then use as a starting point for deeper investigation with the `HybridBrowserToolkit`.
### [SkillToolkit](https://docs.camel-ai.org/reference/camel.toolkits.skill_toolkit)
_Loads custom Skills assigned to the current agent._
This toolkit gives agents access to enabled Skills from the user's or project's Skill configuration. Skills can add reusable instructions, domain knowledge, or procedures, and can be scoped globally or to selected agents.
### [TerminalToolkit](https://docs.camel-ai.org/reference/camel.toolkits.terminal_toolkit)
_A toolkit for terminal operations across multiple operating systems._
@ -209,7 +213,7 @@ This toolkit gives an agent access to a command-line interface. It supports term
_Allows an agent to download and process videos from popular platforms._
This toolkit enables an agent to download video content from URLs (e.g., from YouTube) and optionally split them into chunks. The saved video can then be analyzed by other toolkits, such as the `AudioAnalysisToolkit` for transcription, or `ImageAnalysisToolkit` for object detection.
This toolkit enables an agent to download video content from URLs (e.g., from YouTube) and optionally split them into chunks. The saved video can then be analyzed by other tools, such as the `AudioAnalysisToolkit` for transcription.
### [WebDeployToolkit](https://docs.camel-ai.org/reference/camel.toolkits.web_deploy_toolkit)

View file

@ -0,0 +1,93 @@
---
title: Dashboard overview
description: Navigate Eigent's Home dashboard and manage Spaces, Projects, Tasks, and Triggers.
icon: grid-2
---
The Home dashboard is the management surface for work across Eigent. Use it to find active work, review history, organize projects, and manage automations without opening each project first.
## Open the dashboard
1. Open Eigent.
2. In the main navigation, select **Home**.
3. Select **Spaces**, **Projects**, **Tasks**, or **Triggers**.
The active section appears in the URL, so returning to the same link restores that section.
> **Screenshot placeholder:** Add a full-width screenshot of the Home dashboard with the four section tabs and toolbar visible. Use sample data that does not contain customer information.
## Dashboard sections
### Spaces
Spaces are top-level work areas. A Space can use an Eigent-managed scratch folder or connect directly to a local folder. Each Space contains projects, tasks, files, and triggers.
### Projects
Projects group related tasks and follow-up runs. Open a project to continue its conversation, review files, or inspect agent activity.
### Tasks
Tasks provide a cross-project history of requests. Use this view when you know the prompt or task status but not the containing project.
### Triggers
Triggers run project prompts on a schedule, through a webhook, or from a supported application event.
## Use the toolbar
The toolbar changes the active dashboard section without changing how its items are managed.
| Control | Purpose |
| ------- | ----------------------------------------------------------- |
| Search | Filters the active section by name or prompt |
| Sort | Sorts by created time, updated time, or name |
| Grid | Shows visual cards with key metadata |
| List | Shows compact rows for scanning many items |
| Board | Groups items into status columns |
| Create | Starts a blank Space or a Space connected to a local folder |
Search and sort reset when you move to another section. The selected layout persists for future visits.
## Understand board status
Board view organizes work into three operational groups:
- **Default:** Work that is not currently executing or waiting for review.
- **Running:** Work with an active task or execution.
- **Awaiting review:** Work that needs user input or a decision.
The exact status of a card still appears in its metadata.
## Start new work
1. In the Home toolbar, open the create menu.
2. Choose **Start from scratch** for an Eigent-managed workspace, or **Use local folder** to connect existing files.
3. Eigent opens the new Space in the Workspace.
4. Enter a task, select Single Agent or Workforce mode, and send the request.
> **Video placeholder:** Add a short MP4 showing a user creating a Space, starting a task, and returning to the dashboard to find the new Project and Task. Include captions.
## Manage existing work
Cards and rows expose actions appropriate to their type:
- Rename or delete a project.
- Open, share, or delete a task.
- Pause or resume an ongoing task.
- Edit, enable, disable, or delete a trigger.
- Open a Space and continue work in its Workspace.
## Next steps
<CardGroup>
<Card title="Spaces" icon="folder-tree" href="/dashboard/spaces">
Learn how Spaces define file and project boundaries.
</Card>
<Card title="Projects" icon="folder-kanban" href="/dashboard/projects">
Manage persistent project workstreams.
</Card>
<Card title="Views and search" icon="table-columns" href="/dashboard/views-and-search">
Find work and choose the best dashboard layout.
</Card>
</CardGroup>

View file

@ -0,0 +1,77 @@
---
title: Projects
description: Find, rename, review, and manage projects across your Spaces.
icon: folder-kanban
---
Projects are persistent workstreams inside a Space. A project can contain multiple task runs, file outputs, agent workspaces, and triggers.
## Find a project
1. In the Home dashboard, select **Projects**.
2. Use search when you know part of the project name.
3. Sort by created time, updated time, or name.
4. Select a project card or row to open it.
The project opens in its Space and loads the available session history.
> **Screenshot placeholder:** Add a screenshot of the Projects dashboard in board view with default, running, and awaiting-review columns.
## Understand project metadata
A project item can show:
- Project name
- Containing Space
- Number of tasks
- Number of triggers
- Latest activity
- Current execution or review state
Use the Space label to distinguish projects with similar names.
## Rename a project
1. Open the project actions.
2. Select **Rename**.
3. Enter the new name.
4. Save the change.
Choose a name that describes the ongoing goal rather than only the first task. For example, use “Q3 competitor research” instead of “Search the web.”
## Continue a project
1. Open the project.
2. In the chat input, enter a follow-up request.
3. Send the request.
4. Review the generated plan when Workforce planning is enabled.
5. Start the task.
Eigent adds the request as another run in the same project. See [Project runs](/core/project-runs).
## End a project
Ending, or achieving, a project marks the work as complete.
1. In the project sidebar, open the project actions.
2. Select the end-project action.
3. Confirm the action.
If a run is active, Eigent stops it before marking the project achieved. The project remains available in history.
## Delete a project
1. Open the project actions.
2. Select **Delete**.
3. Review the confirmation message.
4. Confirm the deletion.
Deleting a project removes it from the active project list and can archive its server-backed record. Export or copy required outputs before deletion.
> **Video placeholder:** Add a short MP4 showing project search, rename, follow-up run creation, and project completion. Include captions.
## Related guides
- [Projects overview](/projects/overview)
- [Sessions](/projects/sessions)
- [Tasks dashboard](/dashboard/tasks)

105
docs/dashboard/spaces.md Normal file
View file

@ -0,0 +1,105 @@
---
title: Spaces
description: Organize projects and local folders into persistent Eigent work areas.
icon: folder-tree
---
A Space is the top-level boundary for work in Eigent. It groups projects, tasks, triggers, and files so that related work stays together.
## Choose a Space type
### Blank Space
A blank Space starts with an Eigent-managed scratch workspace. Use it for research, writing, planning, or tasks that should not modify an existing local folder.
### Local-folder Space
A local-folder Space binds Eigent to a folder on your computer. Use it when agents need to inspect or modify an existing codebase, document set, or project directory.
### Legacy Space
A legacy Space contains work created before the current Space system. Eigent keeps these projects available so that older task history remains accessible.
## Create a blank Space
1. In the Home dashboard, select **Spaces**.
2. Open the create menu.
3. Select **Start from scratch**.
4. Eigent creates a Space and opens its Workspace.
5. Optional: Rename the Space from the Space switcher.
Blank Spaces use artifact-only storage. Agents create outputs in Eigent-managed project storage rather than writing directly to a user-selected folder.
## Create a Space from a local folder
1. In the Home dashboard, select **Spaces**.
2. Open the create menu.
3. Select **Use local folder**.
4. In the folder picker, select the directory that Eigent can access.
5. Confirm the selection.
The Space name initially follows the selected folder name. The **Context** tab shows the folder binding.
> **Screenshot placeholder:** Add a screenshot of the Space creation menu with **Start from scratch** and **Use local folder** visible.
## Switch Spaces
1. In the project sidebar, select the current Space name.
2. Select another Space.
Eigent loads that Space's projects and restores its most recently visited project when possible.
## Rename a Space
1. Open the Space switcher.
2. Open the actions for the active Space.
3. Select **Rename**.
4. Enter a non-empty name and select **Save**.
Legacy Spaces and some system-managed Spaces cannot be renamed.
## Work with local changes
Local-folder Spaces can show pending workspace changes. Depending on the current state, the Space menu can provide actions to:
- Load or refresh the working directory.
- Apply pending changes.
- Discard pending changes.
- Resolve a stale workspace state.
Review changed files before applying or discarding them.
> **Video placeholder:** Add a short MP4 showing a local-folder Space, agent-generated file changes, review in Context, and the apply or discard workflow. Include captions.
## Review Space status
The Spaces dashboard shows:
- Space name and source type
- Local folder name when applicable
- Project count
- Task count
- Trigger count
- Current operational status
Use board view to group Spaces by default, running, and awaiting-review state.
## Troubleshooting
### Context is unavailable
The active Space might not have a workspace binding. Create a Space from a local folder or wait for Eigent to finish preparing the scratch workspace.
### A local folder does not appear
Confirm that the folder still exists and that Eigent has operating-system permission to access it.
### A blank Space disappeared
Eigent can hide unused placeholder Spaces. Start a project or give the Space a meaningful name to keep it in the dashboard.
## Related guides
- [Create a project](/projects/create-project)
- [Context and files](/projects/context-and-files)
- [Dashboard projects](/dashboard/projects)

72
docs/dashboard/tasks.md Normal file
View file

@ -0,0 +1,72 @@
---
title: Tasks
description: Review and manage individual tasks across all Eigent projects.
icon: list-check
---
The Tasks dashboard provides a cross-project view of every request submitted to Eigent. Use it to find work by prompt, status, or date when you do not need to browse the project hierarchy first.
## Find a task
1. In the Home dashboard, select **Tasks**.
2. Search for text from the original request.
3. Optional: Sort by created time, updated time, or name.
4. Select the task to open its containing project.
Task search matches the request text. The project and Space labels identify where the task belongs.
> **Screenshot placeholder:** Add a screenshot of the Tasks dashboard in list view with prompt, project, Space, date, and status visible.
## Understand task status
Tasks can move through the following states:
- **Pending:** The request exists but execution has not started.
- **Planning:** Eigent is preparing or splitting the task.
- **Running:** One or more agents are working.
- **Paused:** Execution is temporarily stopped.
- **Awaiting review:** Eigent needs user input, confirmation, or plan approval.
- **Completed:** The task reached a successful final state.
- **Failed:** Execution ended with an error.
Status names can vary slightly between the dashboard and live session, but they represent the same task lifecycle.
## Pause an ongoing task
1. Find the running task.
2. Open its task actions.
3. Select **Pause**.
Eigent records elapsed time and sends a pause request to the active task.
## Resume a paused task
1. Find the paused task.
2. Open its task actions.
3. Select **Resume**.
The task returns to a running state and continues from its preserved context when supported.
## Share a task
1. Open the actions for a completed task.
2. Select **Share**.
3. Copy the generated link.
Review the shared content before distributing the link. Shared tasks can contain prompts, outputs, and project context.
## Delete a task
1. Open the task actions.
2. Select **Delete**.
3. Confirm the deletion.
Deleting a task removes it from task history and its containing project. Save required outputs first.
> **Video placeholder:** Add a short MP4 showing task search, pause, resume, and share actions. Include captions.
## Related guides
- [Sessions](/projects/sessions)
- [Project runs](/core/project-runs)
- [Views and search](/dashboard/views-and-search)

View file

@ -0,0 +1,80 @@
---
title: Views and search
description: Search, sort, and change layouts across the Eigent dashboard.
icon: table-columns
---
The Home dashboard provides the same search, sort, and layout controls for Spaces, Projects, Tasks, and Triggers. Use these controls to move from a visual overview to a compact operational list without changing the underlying data.
## Search the active section
1. Select **Spaces**, **Projects**, **Tasks**, or **Triggers**.
2. Select the search control.
3. Enter part of a name or task prompt.
Search applies only to the active section:
| Section | Search target |
| -------- | --------------------- |
| Spaces | Space name |
| Projects | Project name |
| Tasks | Original task request |
| Triggers | Trigger name |
Changing sections clears the search query.
## Sort dashboard items
1. Select the sort control.
2. Choose **Created**, **Updated**, or **Name**.
3. To reverse the direction, select the same field again.
Created and updated fields default to newest first. Name defaults to alphabetical order.
## Choose a layout
### Grid view
Grid view uses cards and emphasizes names, status, counts, and primary actions. Use it for a visual overview of a smaller set of items.
### List view
List view uses compact rows. Use it to scan many items and compare metadata across the same columns.
### Board view
Board view groups items into:
- Default
- Running
- Awaiting review
Use board view as an operational queue for active work.
> **Screenshot placeholder:** Add one composite image showing the same Projects data in grid, list, and board layouts. Label each layout in surrounding text rather than inside the image.
## Choose the right view
| Goal | Recommended view |
| ------------------------------- | -------------------- |
| Browse a few recent items | Grid |
| Scan a large history | List |
| Monitor active and blocked work | Board |
| Find one known item | Any view with search |
## Current limitations
The filter control appears in the toolbar but is currently disabled. Use section search, sort, and board status grouping until advanced filters are available.
<Note>
Do not document advanced dashboard filters as available until the control is enabled in the product.
</Note>
> **Video placeholder:** Add a 30-45 second MP4 showing search, sort-direction changes, and switching between all three layouts. Include captions.
## Related guides
- [Dashboard overview](/dashboard/overview)
- [Spaces](/dashboard/spaces)
- [Projects](/dashboard/projects)
- [Tasks](/dashboard/tasks)

View file

@ -4,15 +4,15 @@
"theme": "aspen",
"defaultPage": "/get_started/welcome",
"logo": {
"light": "images/logo-light.png",
"dark": "images/logo-dark.png",
"light": "/images/logo-light.png",
"dark": "/images/logo-dark.png",
"href": "https://www.eigent.ai"
},
"favicon": "images/favicon.png",
"colors": {
"primary": "#1d1d1d",
"light": "#F5F4F0",
"dark": "#363AF5"
"dark": "#5F63FF"
},
"background": {
"color": {
@ -20,12 +20,6 @@
"dark": "#1d1d1d"
}
},
"styling": {
"logo": {
"width": "auto",
"height": "100%"
}
},
"navbar": {
"links": [
{
@ -36,7 +30,7 @@
],
"primary": {
"type": "button",
"label": "Get Started",
"label": "Download",
"href": "https://www.eigent.ai/download"
}
},
@ -51,35 +45,113 @@
"pages": [
"/get_started/welcome",
"/get_started/installation",
"/get_started/quick_start"
"/get_started/quick_start",
"/get_started/self-hosting",
"/core/concepts"
]
},
{
"group": "Core",
"icon": "key",
"group": "Dashboard",
"icon": "grid-2",
"pages": [
"/core/concepts",
"/core/brain-architecture",
"/core/workforce",
"/dashboard/overview",
"/dashboard/spaces",
"/dashboard/projects",
"/dashboard/tasks",
"/dashboard/views-and-search"
]
},
{
"group": "Projects",
"icon": "folder-kanban",
"pages": [
"/projects/overview",
"/projects/create-project",
"/projects/workspace",
"/projects/context-and-files",
"/projects/sessions",
"/core/project-runs",
"/projects/single-agent",
"/core/workforce"
]
},
{
"group": "Agents",
"icon": "bot",
"pages": [
"/agents/overview",
"/core/workers",
"/core/agent-skills",
"/agents/remote-sub-agents",
"/agents/memory"
]
},
{
"group": "Models",
"icon": "brain",
"pages": [
"/models/overview",
"/models/eigent-cloud",
"/core/models/byok",
"/core/models/local-model",
"/models/provider-reference",
{
"group": "Models",
"icon": "brain",
"expanded": true,
"group": "Provider Guides",
"expanded": false,
"pages": [
"/core/models/byok",
"/core/models/local-model",
"/core/models/gemini",
"/core/models/ernie",
"/core/models/minimax",
"/core/models/kimi",
"/core/models/sambanova"
]
},
"/core/tools",
"/core/workers",
"/core/agent-skills"
}
]
},
{
"group": "Connectors",
"icon": "plug",
"pages": [
"/connectors/overview",
"/connectors/mcp-marketplace",
"/connectors/custom-mcp",
"/connectors/google-search",
"/core/tools"
]
},
{
"group": "Browser",
"icon": "compass",
"pages": [
"/browser/overview",
"/browser/connections",
"/browser/cookies"
]
},
{
"group": "Automation",
"icon": "bolt",
"pages": [
"/automation/overview",
"/automation/scheduled-triggers",
"/automation/webhook-triggers",
"/automation/dispatch"
]
},
{
"group": "Settings",
"icon": "gear",
"pages": [
"/settings/general",
"/settings/appearance",
"/settings/privacy"
]
},
{
"group": "Open Source",
"icon": "code-branch",
"pages": ["/open-source/overview", "/core/brain-architecture"]
},
{
"group": "Troubleshooting",
"icon": "question-circle",
@ -91,9 +163,14 @@
"global": {
"anchors": [
{
"anchor": "Download Here",
"href": "https://www.eigent.ai",
"icon": "gift"
"anchor": "Download Eigent",
"href": "https://www.eigent.ai/download",
"icon": "download"
},
{
"anchor": "GitHub",
"href": "https://github.com/eigent-ai/eigent",
"icon": "github"
}
]
}

View file

@ -10,12 +10,11 @@ icon: wrench
- Download for macOS
- Download for Windows
```
<Warning>
**macOS Prerequisite**
Please ensure you are running macOS 11 (Big Sur) or a newer version to install Eigent.
</Warning>
```
</Step>
<Step title="Install the Application">

View file

@ -10,7 +10,7 @@ This guide will walk you through building your first multi-agent workforce using
Once opened, you'll land on the **Task** page. Its a clean space designed to turn your ideas into action. Let's break down what you see.
![Layout](/docs/images/quickstart_firsttask.png)
> **Screenshot placeholder:** Add a current screenshot for “Layout”.
### The Top Bar
@ -21,7 +21,7 @@ At the very top of the window is your main navigation bar. You'll access:
- Ongoing Tasks
- **Settings:** where you can configure the app to your liking.
![Task Hub](/docs/images/quickstart_thetopbar.png)
> **Screenshot placeholder:** Add a current screenshot for “Task Hub”.
### The Main View
@ -30,23 +30,24 @@ Your workspace is split into two panels:
**Message Box (Left):** where you'll chat with your AI workforce to start a job.
- Before running the task, you can Add, Edit, or Delete any subtask or Back to Edit your request, then resume. When tasks complete, you can use Replay to re-run the flow.
![Message](/docs/images/quickstart_themainview.gif)
- You can pause anytime—hit **Pause**, edit via **Back to Edit**, then resume. When tasks complete, use **Replay** to re-run the flow.![Message 2](/docs/images/quickstart_pause.gif)
> **Video placeholder:** Add a current video walkthrough for “Message”. Include captions.
- You can pause anytime—hit **Pause**, edit via **Back to Edit**, then resume. When tasks complete, use **Replay** to re-run the flow.> **Video placeholder:** Add a current video walkthrough for “Message 2”. Include captions.
**Canvas (Right):** where your AI agents get to work.
- **Before a Task:** You'll see your pre-built agents and and their tools. You can also click **+ New Worker** to add your own. These workers will always be on standby for your task.
- **During a Task:** The Canvas shows the live status of all subtasks (`Done / In Progress / Unfinished`). Click any subtask to view detailed logs (reasoning steps, tool calls, results). More on this below.
![Task in Progress](/docs/images/quickstart_canvas_inprogress.png)
> **Screenshot placeholder:** Add a current screenshot for “Task in Progress”.
- **Canvas Toolbar:** At the bottom of the Canvas, you'll see a toolbar. This is where you manage your views of agents. You can switch between different task views, such as **Home**, **Agent Folder**, or a specific worker's **Workspace**.
![Add Worker](/docs/images/quickstart_canvas_bottom.png)
> **Screenshot placeholder:** Add a current screenshot for “Add Worker”.
### Agent Folder
This is the filing cabinet for your workforce. Any files your agents create or use (like documents, spreadsheets, code, pictures, or presentations) are automatically saved here. These files are also stored locally on your computer and/or in your cloud for easy access.
![Agent Folder](/docs/images/quickstart_agentfolder.png)
> **Screenshot placeholder:** Add a current screenshot for “Agent Folder”.
#### 📌 Note on File Storage
@ -66,7 +67,7 @@ Eigent comes with four ready-to-work agents. Each is equipped with a specific se
1. **Multimodal Agent** ideals with images, videos and more
1. **Document Agent** reads, writes and manages files (Markdown, PDF, Word, etc.)
![Pre-build Agents](/docs/images/quickstart_prebuiltagents.gif)
> **Video placeholder:** Add a current video walkthrough for “Pre-build Agents”. Include captions.
### Add your own workers
@ -75,8 +76,9 @@ Click **“+ Add Workers”**, provide:
- **Name** (required)
- **Description** (optional): the role of your customized agent
- **Agent Tool**: install any tool available from our MCP Servers to give your agent the exact skills it needs.
- **Custom Model Configuration**: use the "Use custom model configuration" option to assign a specific model to this new worker.
![Add Your Own Workers](/docs/images/quickstart_addworker.gif)
> **Video placeholder:** Add a current video walkthrough for “Add Your Own Workers”. Include captions.
## Start Your First Task
@ -97,7 +99,7 @@ Once you send your task, our **Coordinator Agent** and **Task Agent** kick in to
Once you're happy with the plan, hit **Start Task.** Eigent will automatically assign each subtask to the best agent for the job based on the tools they have.
![Launch the Task](/docs/images/quickstart_lauchtask.gif)
> **Video placeholder:** Add a current video walkthrough for “Launch the Task”. Include captions.
## Watch Agents Work
@ -109,18 +111,18 @@ Once the task starts, your agents will run in parallel on the Canvas:
- **Task Results:** The output or conclusion of the subtask.
- Hover over tasks to see status details
![Watch Agents Work](/docs/images/quickstart_subtasklog.gif)
> **Video placeholder:** Add a current video walkthrough for “Watch Agents Work”. Include captions.
Click on an agent icon to open its **Workspace**:
- Example 1: open **Browser Agent**, launch embedded browser
- Use **“Take Control”** to take over browsing (e.g., accept cookies), then return control to the agent
![Browser Agent](/docs/images/quickstart_takecontrol.gif)
> **Video placeholder:** Add a current video walkthrough for “Browser Agent”. Include captions.
- Example 2: open **Developer Agent**, lauch **Terminal**
![Developer Agent](/docs/images/quickstart_terminal.gif)
> **Video placeholder:** Add a current video walkthrough for “Developer Agent”. Include captions.
<aside>
@ -148,10 +150,10 @@ Click the gear icon in the top-right corner to open Settings. Heres a brief o
### **General**
- **Account:** Manage your subscription or log out.
- **Language:** Choose between English, Simplified Chinese, or your System Default.
- **Appearance:** Switch between Light mode. On macOS, a Transparent mode is also available.
- **Language:** Eigent supports multiple languages, including English, Simplified Chinese (简体中文), Traditional Chinese (繁體中文), Japanese (日本語), Korean (한국어), French (Français), German (Deutsch), Spanish (Español), Italian (Italiano), Russian (Русский), and Arabic (العربية).
- **Appearance:** Eigent now supports custom themes, allowing you to personalize the look and feel of your workspace.
![General](/docs/images/quickstart_settings_general.png)
> **Screenshot placeholder:** Add a current screenshot for “General”.
### **Models**
@ -162,22 +164,22 @@ Eigent can run in two modes. Your choice here affects how you are billed and wha
</aside>
![Models](/docs/images/quickstart_settings_localmodel.png)
> **Screenshot placeholder:** Add a current screenshot for “Models”.
- **Cloud Version:** We provide pre-configured, state-of-the-art models, including GPT-4.1, GPT-4.1 mini and Gemini 2.5 Pro. Using these models is the easiest way to get started and will be billed to your account based on usage (credits).
- **Cloud Version:** We provide pre-configured, state-of-the-art models from leading providers including OpenAI, Anthropic, Google, DeepSeek, and Minimax. Using these models is the easiest way to get started and will be billed to your account based on usage (credits).
- **Self-hosted Version:** You can connect your own models.
- **Cloud Models:** Connect your personal accounts from providers like OpenAI, Anthropic, Qwen, Deepseek and Azure by entering your own API key.
- **Cloud Models:** Connect your personal accounts from providers like OpenAI, Anthropic, Qwen, Deepseek, Nebius Token Factory and Azure by entering your own API key.
- **Local Models:** For advanced users, you can run models locally using Ollama, vLLM, SGLang, LM Studio, or LLaMA.cpp server.
### **MCP Servers**
MCPs are the **tools** that give your agents their skills. We've pre-configured popular tools like Slack, Notion, Google Calendar, GitHub, and more in **MCP Market**, which you can install for your agents with a single click.
![MCP Markets](/docs/images/quickstart_settings_mcp.png)
> **Screenshot placeholder:** Add a current screenshot for “MCP Markets”.
For advanced users, you can click **Add MCP Server** to configure and install custom tools from third-party sources.
![MCP Servers](/docs/images/quickstart_settings_addmcp.png)
> **Screenshot placeholder:** Add a current screenshot for “MCP Servers”.
## Next Steps

View file

@ -0,0 +1,150 @@
---
title: Self-hosting
description: Run Eigent with your own backend, model providers, and local workspace.
icon: server
---
Self-host Eigent when you need control over model providers, credentials, project files, or the infrastructure that runs your agents. A self-hosted installation uses the open-source Eigent application and lets you connect cloud APIs, OpenAI-compatible endpoints, or local inference servers.
This page describes the recommended setup path. Exact deployment requirements can change between releases, so use the repository files and release notes as the source of truth for version-specific values.
## Before you begin
Prepare the following:
- A supported desktop operating system or Linux development environment
- Git
- Node.js `18` through `22`
- The Python version required by the repository backend
- Enough disk space for dependencies, generated files, and optional local models
- Credentials for at least one cloud provider, or a running local model server
<Note>
Local model requirements depend on the model and runtime. Large models can require substantial memory or GPU capacity.
</Note>
## Choose a deployment model
Eigent supports three common arrangements:
| Arrangement | Model execution | Best for |
| --------------------- | --------------------------------------------- | ------------------------------------------------ |
| Managed application | Eigent Cloud | Fast evaluation with minimal setup |
| Self-hosted with BYOK | External provider APIs | Infrastructure control with hosted model quality |
| Fully local | Ollama, vLLM, SGLang, LM Studio, or LLaMA.cpp | Private environments and local experimentation |
You can configure more than one provider and change the preferred model later.
## Set up the repository
1. Clone the Eigent repository:
```bash
git clone https://github.com/eigent-ai/eigent.git
cd eigent
```
2. Install the frontend dependencies:
```bash
npm install
```
3. Review `.env.development`, `backend/README.md`, and the root `README.md` for the current backend and environment configuration.
4. Start the development application:
```bash
npm run dev
```
5. In Eigent, open **Agents > Models** and configure a model provider.
<Note>
The first development start can take longer because Eigent prepares frontend and backend dependencies.
</Note>
> **Screenshot placeholder:** Add a screenshot of Eigent running locally with **Agents > Models** open. Crop the image to the application window and hide credentials.
## Configure a model
For the fastest self-hosted setup, connect an existing provider:
1. In Eigent, open **Agents > Models**.
2. Expand **Bring Your Own Key**.
3. Select a provider.
4. Enter the API key, endpoint, and model name required by that provider.
5. Select **Validate** or **Save**.
6. Enable the provider and mark it as preferred when you want it to be the default.
To keep inference local, start one of the supported runtimes and follow [Local models](/core/models/local-model).
## Configure tools and browser access
A model can reason about a task, but tools let it act.
- Add hosted integrations from [MCP Marketplace](/connectors/mcp-marketplace).
- Add your own local or remote server from [Custom MCP servers](/connectors/custom-mcp).
- Configure a CDP browser from [Browser connections](/browser/connections).
- Create a Space from a local folder when agents need direct access to project files.
> **Video placeholder:** Add a 60-90 second MP4 showing a local installation, model configuration, local-folder Space creation, and the first successful task. Include captions and a short transcript.
## Build a distributable application
Use the build script for the target platform:
```bash
npm run build
```
Platform-specific scripts include:
```bash
npm run build:mac
npm run build:win
npm run build:linux
```
Review the Electron signing, packaging, and backend dependency requirements before distributing a build to other users.
## Update a self-hosted installation
1. Commit or back up local configuration changes.
2. Pull the target release or branch.
3. Review release notes and environment changes.
4. Reinstall dependencies when lockfiles changed.
5. Run the relevant tests and build command.
6. Start Eigent and validate models, connectors, browser sessions, and existing Spaces.
## Troubleshooting
### The application starts without a model
Open **Agents > Models** and configure at least one cloud, BYOK, or local provider. Eigent blocks new tasks when no valid model is available.
### A local model cannot be reached
Confirm that the runtime is running, the endpoint includes the expected `/v1` path, and the port is accessible from the Eigent process.
### MCP tools fail during startup
Review the MCP command, arguments, environment variables, and executable path. Run the server independently to confirm that it starts before adding it to Eigent.
### Browser connection fails
Confirm that Chrome or Chromium was started with remote debugging and that the configured port exposes `/json/version`.
## Next steps
<CardGroup>
<Card title="Provider reference" icon="list" href="/models/provider-reference">
Compare every cloud and local model provider supported by Eigent.
</Card>
<Card title="Open-source Eigent" icon="code-branch" href="/open-source/overview">
Review the repository architecture and extension points.
</Card>
<Card title="Brain architecture" icon="diagram-project" href="/core/brain-architecture">
Understand how the frontend, Brain backend, and services work together.
</Card>
</CardGroup>

View file

@ -4,16 +4,11 @@ description: Learn about Eigent and Unlock Your Exceptional Productivity now
icon: wave
---
**Eigent** is the worlds first **Multi-agent Workforce** desktop application, empowering you to build, manage, and deploy a custom AI workforce that can turn your most complex workflows into automated tasks.
**Eigent** is the first open-source, general-agent desktop app. Easily build, manage, and deploy a custom AI workforce or orchestrate a master agent with specialized sub-agents to turn your most complex workflows into automated tasks.
Built on CAMEL-AI's acclaimed open-source project (CAMEL with 13k⭐ on GitHub, #1 on GitHub Daily Trending), our system introduces a **Multi-Agent Workforce** that **boosts productivity** through parallel execution, customization, and privacy protection. Previously #1 opensource project on GAIA.
Built on CAMEL-AI's acclaimed open-source project (CAMEL with 17k⭐ on GitHub, #1 on GitHub Daily Trending), our system introduces a **Multi-Agent Workforce** that **boosts productivity** through parallel execution, customization, and privacy protection. Previously #1 opensource project on GAIA.
<img
src="/docs/images/thumbnail.png"
alt="Dynamic Workforce"
width="100%"
height="auto"
/>
> **Screenshot placeholder:** Add a current screenshot for “Dynamic Workforce”.
## Core Features and Capabilities
@ -48,4 +43,14 @@ height="auto"
icon="server">
Deploy Eigent locally with your preferred models. Your data stays on **your own device**, addressing privacy and security concerns. You can use personal API keys or local LLMs so that sensitive information never leaves your environment.
</Card>
<Card
title="Agent Skills"
icon="wand-magic-sparkles">
To boost Eigent's efficiency and reliability, we provide a flexible Skills system for agents. Skills can be dynamically generated from tasks (so agents quickly gain the right tools for the job) or manually added by users for precise control and governance.
</Card>
<Card
title="Task Trigger"
icon="clock-rotate-left">
Eigent also supports powerful Triggers to automate when agents should run. This includes Schedule Triggers for recurring jobs, Webhook/Event Triggers for real-time actions from external systems, and Agentic Triggers where agents can trigger follow-up work based on context and outcomes.
</Card>
</CardGroup>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before After
Before After

View file

@ -0,0 +1,92 @@
---
title: Eigent Cloud models
description: Use managed models and credits without configuring provider API keys.
icon: cloud
---
Eigent Cloud provides managed model access for users who do not want to configure provider credentials or local inference.
## When to use Eigent Cloud
Choose Eigent Cloud when you want:
- The fastest setup path
- A curated model catalog
- No provider API-key management
- Usage tracked through Eigent credits
- A managed fallback while testing BYOK or local models
## Enable a Cloud model
1. Open **Agents > Models**.
2. Select **Cloud**.
3. Review the available models.
4. Select the model to use.
5. Enable Cloud and mark it as preferred when it should be the default.
> **Screenshot placeholder:** Add a screenshot of the Cloud model catalog and preferred-model control. Use an account with non-sensitive sample credit data.
## Available model families
The current application catalog can include managed options from:
- Google Gemini
- OpenAI
- Anthropic Claude
- DeepSeek
- MiniMax
Exact models can change as providers release new versions. Treat the in-product catalog as the source of truth for current availability.
## Understand credits
Cloud usage consumes Eigent credits. Credit consumption depends on the selected model and task usage.
The product can show:
- Current plan
- Available credit balance
- Links for plan management
- Model availability based on the account
Review the current pricing and plan page before running large or automated workloads.
## Change the Cloud model
1. Open the Cloud model selector.
2. Choose another available model.
3. Save or apply the selection.
New tasks use the new preference. Running tasks are not migrated automatically.
## Use Cloud with other providers
You can keep Cloud enabled while also configuring BYOK and local providers. Mark one provider as preferred, then select another model for individual tasks when needed.
This supports workflows such as:
- Cloud as the default, local model for private files
- BYOK as the default, Cloud as a fallback
- Different model families for coding, research, and writing
> **Video placeholder:** Add a 45-second MP4 showing Cloud model selection, preferred-provider changes, and selecting a different model for a new task. Include captions.
## Troubleshooting
### No Cloud models are available
Confirm the account is signed in, the application can reach Eigent services, and the current plan includes model access.
### Credits are unavailable
Open account management to review the plan or add credits.
### The selected model changed
Model availability can change. Open the Cloud catalog and select another supported model.
## Related guides
- [Models overview](/models/overview)
- [Provider reference](/models/provider-reference)
- [Privacy](/settings/privacy)

96
docs/models/overview.md Normal file
View file

@ -0,0 +1,96 @@
---
title: Models overview
description: Choose between Eigent Cloud, your own provider keys, and local inference servers.
icon: brain
---
Eigent is model-flexible by design. You can use managed Eigent Cloud models, connect provider accounts with your own keys, or run open models on local infrastructure.
At least one valid model is required before Eigent can start a task.
## Open Models
1. Open the Eigent dashboard.
2. Select **Agents**.
3. Select **Models**.
The Models page separates managed cloud, bring-your-own-key, and local providers.
> **Screenshot placeholder:** Add a screenshot of the Models page with the Cloud, BYOK, and Local sections visible. Hide all credential values.
## Choose a model source
### Eigent Cloud
Use managed models without configuring provider credentials. This is the quickest way to evaluate Eigent and is billed through Eigent credits.
### Bring Your Own Key
Connect a supported cloud provider with your own API key and endpoint. Provider billing and data handling follow the provider account.
### Local models
Connect Eigent to Ollama, vLLM, SGLang, LM Studio, or LLaMA.cpp. Local models can keep inference on infrastructure you control.
## Configure a provider
1. Select the provider.
2. Enter the required key, endpoint, model name, and provider-specific fields.
3. Validate or save the configuration.
4. Enable the provider.
5. Optional: Mark it as preferred.
Some providers can load their model catalog dynamically. Others require a model name.
## Select a default model
The preferred provider becomes the default choice for new tasks. You can also choose a model from the task composer when model selection is available there.
Changing the default affects future tasks. It does not replace the model already used by an active Run.
## Compare model options
Consider:
- Reasoning quality
- Tool-use reliability
- Context window
- Input and output modalities
- Latency
- Cost
- Data residency
- Local hardware requirements
Use a representative task to validate a model before making it the default for all work.
> **Video placeholder:** Add a 60-second MP4 showing one BYOK provider and one local runtime being configured, validated, enabled, and selected. Include captions.
## Remove a provider
1. Open the provider.
2. Disable it.
3. Select the delete or reset action.
4. Confirm the removal.
Removing a provider deletes its stored Eigent configuration. It does not delete the provider account or local model.
## Troubleshooting
### Validation fails
Check the key, endpoint, model name, provider region, API version, and network proxy.
### No local models appear
Confirm the local runtime is running and supports model listing. Some runtimes require entering the model name manually.
### A task still uses another model
Confirm the preferred provider and the model selected in the task composer. Existing active Runs keep their current configuration.
## Related guides
- [Eigent Cloud models](/models/eigent-cloud)
- [Bring Your Own Key](/core/models/byok)
- [Local models](/core/models/local-model)
- [Provider reference](/models/provider-reference)

View file

@ -0,0 +1,110 @@
---
title: Provider reference
description: Review every cloud and local model provider supported by Eigent.
icon: list
---
Eigent supports multiple provider types so open-source deployments can choose models based on capability, cost, privacy, and infrastructure.
Provider availability and required fields are defined by the current application. Use this page as an overview and the provider's official documentation for account, model, and billing details.
## Cloud and BYOK providers
| Provider | Typical required values | Notes |
| -------------------- | ------------------------------------------ | ------------------------------------- |
| Google Gemini | API key, endpoint, model | Google model family |
| OpenAI | API key, endpoint, model | OpenAI API |
| Anthropic | API key, endpoint, model | Claude model family |
| OrcaRouter | API key, endpoint | Can load a grouped model catalog |
| OpenRouter | API key, endpoint, model | Routes models from multiple providers |
| Qwen | API key, endpoint, model | Tongyi Qianwen provider |
| DeepSeek | API key, endpoint, model | DeepSeek model family |
| MiniMax | API key, endpoint, model | MiniMax model family |
| Z.ai | API key, endpoint, model | Z.ai model family |
| Moonshot | API key, endpoint, model | Moonshot model family |
| ModelArk | API key, endpoint, model | ModelArk service |
| SambaNova | API key, endpoint, model | SambaNova hosted inference |
| Grok | API key, endpoint, model | xAI model family |
| Mistral | API key, endpoint, model | Mistral model family |
| AWS Bedrock | Region, access key, secret, model | Optional session token |
| AWS Bedrock Converse | Region, access key, secret, model | Uses Bedrock Converse integration |
| Microsoft Azure | API key, endpoint, API version, deployment | Deployment name is required |
| Baidu ERNIE | API key, endpoint, model | ERNIE model family |
| OpenAI-compatible | Endpoint, optional key, model | For compatible third-party services |
<Note>
Provider fields can change. Confirm required values in **Agents > Models** after updating Eigent.
</Note>
## Local runtimes
| Runtime | Default endpoint | Model discovery |
| --------- | --------------------------- | ------------------------------------------- |
| Ollama | `http://localhost:11434/v1` | Reads the Ollama tags API |
| vLLM | `http://localhost:8000/v1` | Enter the served model when not listed |
| SGLang | `http://localhost:30000/v1` | Enter the served model when not listed |
| LM Studio | `http://localhost:1234/v1` | Enter the loaded model when not listed |
| LLaMA.cpp | `http://localhost:8080/v1` | Reads the OpenAI-compatible models endpoint |
## Configure a cloud provider
1. Create an account with the provider.
2. Create a restricted API credential.
3. Confirm the provider endpoint and model identifier.
4. In Eigent, open **Agents > Models**.
5. Select the provider and enter the values.
6. Validate and save.
7. Run a small test task.
## Configure an OpenAI-compatible endpoint
Use the OpenAI-compatible provider for services that implement compatible chat APIs.
Provide:
- Base endpoint
- API key when required
- Exact model identifier exposed by the service
Compatibility can vary. Test streaming, tool calls, and structured responses before using the provider for production work.
## Configure a local runtime
1. Install and start the runtime.
2. Load or serve a model.
3. Confirm the endpoint responds locally.
4. In Eigent, open **Agents > Models > Local**.
5. Select the runtime.
6. Enter the endpoint and model.
7. Validate and enable it.
> **Screenshot placeholder:** Add a composite screenshot showing one cloud provider form, Azure provider-specific fields, and one local runtime form. Blur credentials.
> **Video placeholder:** Add a 90-second MP4 showing an Ollama model and an OpenAI-compatible cloud endpoint being configured and tested. Include captions.
## Provider page checklist
Each dedicated provider guide should include:
1. Account or runtime prerequisites
2. Credential creation
3. Endpoint format
4. Model identifier examples
5. Eigent configuration
6. Validation
7. Common errors
8. Billing and privacy notes
## Security guidance
- Do not include credentials in screenshots, logs, or issue reports.
- Use least-privilege cloud credentials.
- Restrict local endpoints to trusted networks.
- Rotate keys after accidental exposure.
- Review the provider's data-retention policy.
## Related guides
- [Bring Your Own Key](/core/models/byok)
- [Local models](/core/models/local-model)
- [Self-hosting](/get_started/self-hosting)

View file

@ -0,0 +1,135 @@
---
title: Open-source Eigent
description: Build, inspect, extend, and self-host Eigent from its public source code.
icon: code-branch
---
Eigent is an open-source agent workspace built around model choice, extensible tools, and local control. You can inspect the implementation, run the application yourself, connect private infrastructure, and contribute changes.
## Why open source matters
Open source lets teams:
- Choose managed, BYOK, or local models
- Inspect agent and tool assembly
- Connect local files and browsers
- Add MCP servers and custom integrations
- Modify the React and Electron application
- Extend the Python Brain and server APIs
- Operate with their own security controls
## Repository structure
The repository contains several major areas:
| Area | Purpose |
| ---------------- | ------------------------------------------------------------- |
| `src/` | React application, stores, pages, and components |
| `electron/` | Desktop host, IPC, windows, and local integrations |
| `backend/` | Brain backend, agents, tools, memory, and workspace services |
| `server/` | Server APIs, domains, persistence, remote control, and Spaces |
| `test/` | Frontend and Electron tests |
| `backend/tests/` | Brain backend tests |
| `server/tests/` | Server tests |
| `docs/` | Mintlify product documentation |
> **Screenshot placeholder:** Add a repository tree diagram or screenshot that highlights the major directories without exposing local paths or unrelated files.
## Set up a development environment
1. Clone the repository.
2. Install the required Node.js and Python versions.
3. Install dependencies.
4. Review development environment files.
5. Start the application.
6. Configure a test model.
See [Self-hosting](/get_started/self-hosting) for the setup workflow.
## Run quality checks
Common frontend checks include:
```bash
npm run type-check
npm run lint
npm test
npm run format:check
```
Run focused backend and server tests for the modules you change.
## Extend Eigent
Common extension points include:
- Add a model provider.
- Add a local inference runtime.
- Add an MCP integration.
- Create an Agent Skill.
- Add or modify a worker.
- Add a trigger type.
- Add a dashboard or Workspace surface.
- Extend Space, Project, or remote-control APIs.
Follow existing module boundaries and add tests for shared behavior.
## Contribute changes
A useful contribution should include:
- A clear problem statement
- Focused implementation
- Tests proportional to risk
- Documentation for user-facing behavior
- Screenshots or recordings for UI changes
- Migration notes for schema or configuration changes
Before opening a pull request:
1. Review the repository contribution guidance.
2. Rebase or update from the target branch.
3. Run relevant checks.
4. Remove secrets and local-only files.
5. Describe verification steps.
> **Video placeholder:** Add a 90-second contributor onboarding MP4 showing repository setup, a small UI or documentation change, tests, and a pull request. Include captions.
## Documentation contributions
Product documentation lives in `docs/`.
- Add pages to `docs/docs.json`.
- Include `title` and `description` frontmatter.
- Use task-based procedures.
- Add visible screenshot and video placeholders when assets are not ready.
- Keep provider docs synchronized with model configuration source files.
- Mark coming-soon functionality clearly.
## Community and support
<CardGroup cols={3}>
<Card title="GitHub Issues" icon="github" href="https://github.com/eigent-ai/eigent/issues">
Report reproducible bugs and feature requests. Please include Eigent version, operating system, deployment mode, model provider, reproduction steps, expected and actual behavior, and sanitized logs.
</Card>
<Card title="Discord Community" icon="discord" href="https://discord.camel-ai.org/">
Join our Discord community to ask questions, share ideas, and connect with other Eigent users and contributors.
</Card>
<Card title="Email" icon="envelope" href="mailto:info@eigent.ai">
Reach out to us at info@eigent.ai for general inquiries and support.
</Card>
</CardGroup>
## Related guides
<CardGroup>
<Card title="Brain architecture" icon="diagram-project" href="/core/brain-architecture">
Understand the main runtime and service boundaries.
</Card>
<Card title="Self-hosting" icon="server" href="/get_started/self-hosting">
Run Eigent with your own infrastructure.
</Card>
<Card title="Custom MCP servers" icon="wrench" href="/connectors/custom-mcp">
Extend agents with new tools.
</Card>
</CardGroup>

View file

@ -0,0 +1,94 @@
---
title: Context and files
description: Manage local workspace files, uploaded context, and generated project outputs.
icon: inbox
---
The Context tab is the file surface for the active Space and Project. It combines workspace files, user attachments, and outputs generated by agents.
## Open Context
1. Select a Space.
2. In the project sidebar, select **Context**.
If Context is disabled, the Space does not yet have a usable workspace binding.
> **Screenshot placeholder:** Add a screenshot of the Context tab with the file tree, preview area, and an unread-file notification visible.
## Understand file sources
Context can include:
- Files from a local-folder Space
- Files stored in an Eigent scratch workspace
- Files attached to user requests
- Files generated by agents
- Agent-specific working folders
- Selected output files from a task run
The project Session side panel can also list uploaded and generated files for the selected Run.
## Open and preview a file
1. In Context, browse or search the file tree.
2. Select a file.
3. Review the preview.
Eigent supports previews for common text, source code, Markdown, image, HTML, document, and data formats. Unsupported formats remain available in the workspace even when they cannot be previewed.
## Use a local-folder Space
Local-folder Spaces use direct-write mode. Agents can read and modify files inside the selected folder, subject to available tools and permissions.
Before starting a task:
1. Confirm the folder shown by the Space binding.
2. Commit or back up important work.
3. Limit the request to the intended files.
4. Review generated changes before accepting them.
## Use a blank Space
Blank Spaces use artifact-only mode. Eigent stores generated outputs in managed project storage instead of modifying an existing user folder.
Use this mode for research, reports, presentations, and tasks that should produce isolated deliverables.
## Review pending changes
When the Space reports pending changes:
1. Open the Space switcher or Context.
2. Refresh the workspace when the displayed state is stale.
3. Review the changed files.
4. Apply the changes to keep them, or discard them to return to the previous state.
> **Video placeholder:** Add a 60-90 second MP4 showing an agent creating a file, the unread Context indicator, file preview, and the apply or discard workflow. Include captions.
## Open a run output
1. Open the Project Session.
2. Select the required Run.
3. In the side panel, expand the file section.
4. Select an output.
Eigent opens Context and selects the file belonging to that Run.
## Troubleshooting
### A generated file does not appear immediately
Wait a few seconds and refresh Context. Some outputs are written after the task sends its finished event.
### Context shows the wrong project file
Confirm the selected Project and Run. File selection is scoped to the selected Run when possible.
### A local file cannot be opened
Confirm that the file still exists and that Eigent has permission to access the containing folder.
## Related guides
- [Spaces](/dashboard/spaces)
- [Sessions](/projects/sessions)
- [Project runs](/core/project-runs)

View file

@ -0,0 +1,101 @@
---
title: Create a project
description: Start a project, choose an execution mode, attach files, and submit the first task.
icon: plus
---
Create a Project when you want Eigent to keep related tasks, files, and follow-up requests together.
## Before you begin
Confirm the following:
- A Space is selected.
- At least one model is configured.
- The task goal is clear enough to plan or execute.
- Required source files are available.
If no model is configured, Eigent opens the Models page instead of starting the task.
## Open the project composer
Use one of these entry points:
- In the project sidebar, select **New**.
- In the project sidebar, select **Workspace**.
- From the Home dashboard, create or open a Space.
The composer displays the active Space and lets you select a project mode.
> **Screenshot placeholder:** Add a screenshot of the new-project composer with the Space, project picker, Single Agent or Workforce toggle, attachment control, and send action visible.
## Choose an execution mode
### Single Agent
Single Agent mode uses one CAMEL-based agent with the available tools. Choose it for focused tasks that benefit from one continuous context.
### Workforce
Workforce mode plans the request and distributes subtasks across specialized agents. Choose it for research, software, documents, or other work that benefits from parallel roles.
You cannot change the execution mode of a run after it starts. Create another run or project when you need a different mode.
## Attach source files
1. In the composer, select the attachment control.
2. Choose one or more files.
3. Confirm that the file names appear in the composer.
4. Mention the files and their purpose in the request.
Attachments become part of the first run's execution context.
## Write the first request
Describe:
- The desired outcome
- Required source material
- Constraints or acceptance criteria
- Preferred output format
- Any service or tool the agents should use
For example:
> Analyze the attached customer interview notes. Group the findings into themes, identify the five highest-impact problems, and create a Markdown report with supporting quotes and recommended product actions.
## Start the project
1. Review the selected Space, mode, files, and request.
2. Select **Send**.
Eigent creates a server-backed Project in the active Space, opens the Session, and starts the first Run.
In Workforce mode, Eigent can show a task plan before execution. Review, edit, add, or remove subtasks before starting the plan.
> **Video placeholder:** Add a 60-90 second MP4 showing project creation in both Single Agent and Workforce modes. Include captions and pause briefly on the Workforce plan review.
## Troubleshooting
### The send action does nothing
Confirm that the request contains text and that project startup is not already in progress.
### Eigent asks for a model
Open **Agents > Models**, configure a provider, and return to the composer.
### A file is missing
Attach it again before sending, or add it from the Context tab in an existing project.
### The wrong Space is selected
Cancel the draft, select the correct Space, and start the project there. Space selection defines the project and file boundary.
## Next steps
- [Workspace](/projects/workspace)
- [Sessions](/projects/sessions)
- [Single Agent mode](/projects/single-agent)
- [Workforce](/core/workforce)

88
docs/projects/overview.md Normal file
View file

@ -0,0 +1,88 @@
---
title: Projects overview
description: Understand how Spaces, Projects, Sessions, and Runs organize work in Eigent.
icon: folder-kanban
---
Projects are persistent workstreams inside a Space. A project keeps related conversations, task runs, agents, files, browser activity, terminal state, and automations together.
## Product hierarchy
Eigent organizes work into four levels:
| Level | Purpose |
| ------- | ------------------------------------------------- |
| Space | Defines the top-level workspace and file boundary |
| Project | Groups related work around an ongoing goal |
| Session | Presents the conversation and execution surfaces |
| Run | Represents one request or follow-up task |
For example, a Space called “Marketing” can contain a “Product launch” project. The project session can include separate runs for research, copywriting, and presentation creation.
## Use the project sidebar
The project sidebar is available in the main Workspace. It provides access to:
- The Space switcher
- Workspace
- Context
- Scheduled triggers
- Dispatch
- New project
- Projects in the active Space
- Project actions
The sidebar can be resized or folded into an icon rail.
> **Screenshot placeholder:** Add a screenshot of the expanded project sidebar. Annotate the Space switcher, Workspace, Context, Scheduled, Dispatch, New, and project list in surrounding text.
## Start a project
1. Select a Space from the sidebar.
2. Select **New** or open the Workspace.
3. Enter the first task.
4. Choose Single Agent or Workforce mode.
5. Attach required files.
6. Send the task.
Eigent creates the Project and opens its live Session.
## Continue a project
Submit a follow-up request in the same conversation. Eigent adds a new Run while preserving earlier prompts, progress, and outputs.
Use this approach when the new request contributes to the same goal. Create another Project when the work needs a separate history, file context, or lifecycle.
## Manage project status
### Active
An active project can accept new runs, execute triggers, and appear in the project sidebar.
### Achieved
An achieved project is complete. If a run is still active when you end the project, Eigent stops that run before saving the achieved state.
### Archived or deleted
Archived projects leave the active workflow. Deleting a project can also remove its local project data. Save important output files before deletion.
## Search across projects
Use `Command/Ctrl + K` from the Workspace to open global search. Search can help locate existing projects and sessions without returning to the Home dashboard.
> **Video placeholder:** Add a 60-second MP4 showing project creation, a follow-up run, global search, and project completion. Include captions.
## Related guides
<CardGroup>
<Card title="Create a project" icon="plus" href="/projects/create-project">
Start the first run and choose an execution mode.
</Card>
<Card title="Sessions" icon="messages" href="/projects/sessions">
Follow agent execution and review outputs.
</Card>
<Card title="Project runs" icon="rotate" href="/core/project-runs">
Continue work with follow-up requests.
</Card>
</CardGroup>

105
docs/projects/sessions.md Normal file
View file

@ -0,0 +1,105 @@
---
title: Sessions
description: Follow task execution through chat, progress, agents, logs, files, browser, and terminal views.
icon: messages
---
A Session combines the project conversation with live execution details. It is the main surface for reviewing what Eigent understood, what its agents are doing, and what they produced.
## Session layout
The Session contains:
- A chat and task timeline
- A task composer for follow-up requests
- A session side panel
- Workspace surfaces for files, browser, terminal, or workflow
- Controls for pausing, resuming, stopping, or expanding work
> **Screenshot placeholder:** Add a screenshot of an active Workforce Session. Show the chat, task log, Run selector, progress, agent pool, and workspace surface.
## Review the conversation
The chat timeline can contain:
- User prompts and attachments
- Planning status
- Workforce task plans
- Agent tool calls and logs
- Human-in-the-loop questions
- Completion summaries
- Follow-up runs
Expand task logs when you need operational detail. Use summaries and generated files for the final result.
## Review a Workforce plan
Before execution, Workforce can split the request into subtasks.
1. Review each subtask.
2. Edit unclear or overly broad items.
3. Add missing work.
4. Delete unnecessary work.
5. Start the task.
The coordinator assigns each subtask to an appropriate worker.
## Use the session side panel
In Workforce mode, the side panel can show:
- Agent pool
- Progress
- Execution context
- Uploaded files
- Generated files
- Skills and tools
- Expanded Workforce canvas
In Single Agent mode, it shows the selected agent's progress, context, and outputs without the multi-agent canvas.
## Open an agent workspace
Select an agent or subtask to open its workspace:
- Browser agents use an embedded browser.
- Developer agents use a terminal.
- Document and file work appears in Context.
- Workflow view shows the agent and task structure.
When a browser needs manual help, use the available take-control flow, complete the action, and return control to the agent.
## Pause, resume, or stop work
- **Pause** preserves the task state and elapsed time.
- **Resume** continues a paused task.
- **Stop** ends the current execution while preserving the Project history.
Use Stop when the task is no longer useful or is consuming resources without making progress.
## Continue with a follow-up
Enter another request in the composer. Eigent adds the request as a new Run. Use the Run selector to switch the side panel and workspaces between runs.
> **Video placeholder:** Add a 90-second MP4 showing plan review, task execution, a browser or terminal workspace, pause and resume, and a follow-up Run. Include captions and a transcript.
## Troubleshooting
### Progress and chat show different runs
Use the Run selector. The side panel follows the selected or visible Run.
### An agent workspace is empty
The selected Run might not have used that agent or workspace. Select another agent, return to workflow view, or choose the relevant Run.
### A task is waiting
Check the chat for a human-in-the-loop request, plan approval, authentication step, or unavailable tool.
## Related guides
- [Project runs](/core/project-runs)
- [Single Agent mode](/projects/single-agent)
- [Workforce](/core/workforce)
- [Context and files](/projects/context-and-files)

View file

@ -0,0 +1,88 @@
---
title: Single Agent mode
description: Run a task with one CAMEL agent and monitor its progress, context, and outputs.
icon: user-robot
---
Single Agent mode assigns a task to one CAMEL-based agent instead of creating a coordinated multi-agent Workforce. The agent can still use models, tools, Skills, files, browser sessions, and terminal access.
## Choose Single Agent mode
Use Single Agent mode for:
- Focused tasks with one clear goal
- Work that benefits from a continuous context
- Short tool-driven workflows
- Tasks where coordination overhead would add little value
- Iterative follow-ups handled by the same execution pattern
Use Workforce for broad tasks that benefit from specialized roles or parallel subtasks.
## Start a Single Agent project
1. Open the Workspace or select **New**.
2. Select **Single Agent**.
3. Enter the task.
4. Attach required files.
5. Send the request.
Eigent opens a Session and starts the task without a Workforce planning stage.
> **Screenshot placeholder:** Add a screenshot of the new-project composer with Single Agent mode selected.
## Monitor the agent
The Session side panel can show:
- Task progress
- Execution context
- Uploaded files
- Generated output files
- Skills and tools
The chat timeline shows tool calls, status updates, requests for user input, and the final response.
## Use browser and terminal workspaces
When the agent uses browser or terminal tools, the corresponding workspace becomes available in the Session. The workspace is scoped to the selected Run.
## Continue with follow-ups
1. Enter a follow-up request in the Session.
2. Send the request.
3. Use the Run selector to review earlier work.
Each follow-up remains part of the same Project.
## Compare execution modes
| Capability | Single Agent | Workforce |
| ------------------------------------ | ------------ | ----------------------- |
| One continuous agent context | Yes | No, work is distributed |
| Task planning and splitting | Limited | Yes |
| Parallel specialized agents | No | Yes |
| Agent pool and workflow canvas | No | Yes |
| Browser, terminal, files, and Skills | Yes | Yes |
| Best for | Focused work | Complex multi-step work |
> **Video placeholder:** Add a side-by-side MP4 comparison of the same focused request in Single Agent and Workforce mode. Keep the example short and include captions.
## Troubleshooting
### The task needs another specialty
Add the required tool to the agent, install a connector, or start a Workforce Project with specialized workers.
### The agent cannot access a file
Attach the file, add it to the Space workspace, and confirm that the active Space has the correct folder binding.
### The task is too broad
Split the request into smaller follow-up Runs or use Workforce mode.
## Related guides
- [Create a project](/projects/create-project)
- [Agents overview](/agents/overview)
- [Workforce](/core/workforce)

View file

@ -0,0 +1,84 @@
---
title: Workspace
description: Use the Workspace landing page, project picker, instructions, agents, and recent sessions.
icon: desktop
---
The Workspace is the starting surface for the active Space. Use it to start work, select a project, review recent sessions, configure project behavior, and manage the agents available to Workforce mode.
## Open the Workspace
1. In the project sidebar, select **Workspace**.
2. Confirm the active Space in the sidebar.
The main composer starts a new project unless you select an existing project.
> **Screenshot placeholder:** Add a screenshot of the complete Workspace landing page with the composer, mode toggle, recent sessions, agent list, and instructions panel visible.
## Select a project
The project picker behaves differently depending on the current state:
- In a fresh Workspace, select an existing project before submitting a task.
- After work has started, the selected project is displayed as context.
- Selecting a recent session opens that Project's live Session.
Use **All sessions** to review more projects than the recent-session list shows.
## Start a task
1. Enter a request in the composer.
2. Select Single Agent or Workforce mode.
3. Attach required files.
4. Select **Send**.
Eigent creates a Project when no existing Project is selected.
## Use example prompts
Example prompts appear for an empty Project that does not use a custom agent folder or replayed history. Select a prompt to understand the expected level of task detail, then adapt it to your goal.
## Manage Workforce agents
The Workspace shows built-in and custom workers available to Workforce mode.
You can:
- Review the built-in Developer, Browser, Document, and Multimodal roles.
- Add a worker.
- Edit a custom worker.
- Assign tools to a worker.
- Remove workers that are no longer required.
See [Workers](/core/workers) for configuration details.
## Configure instructions, rules, and tone
Project instructions provide persistent guidance for work in the active Space or Project. Use them for:
- Output conventions
- Brand or writing tone
- Coding standards
- Required files or workflows
- Safety and approval rules
Keep instructions focused and actionable. Put step-by-step reusable expertise in an Agent Skill instead of one large instruction file.
> **Screenshot placeholder:** Add a screenshot of the instructions panel with a short example instruction. Do not include private repository rules.
## Toggle workspace memory
The Workspace includes a memory toggle for instruction behavior. This local setting is separate from the Agent Memory page, which is currently marked coming soon.
## Open recent sessions
Recent sessions display project names and current state. Select one to open its Session. Use the project sidebar or Home dashboard for the complete project history.
> **Video placeholder:** Add a 60-second MP4 showing project selection, instruction editing, worker management, and opening a recent session. Include captions.
## Related guides
- [Create a project](/projects/create-project)
- [Agents overview](/agents/overview)
- [Agent Skills](/core/agent-skills)
- [Sessions](/projects/sessions)

View file

@ -0,0 +1,85 @@
---
title: Appearance
description: Customize color mode, themes, contrast, and workspace backgrounds.
icon: palette
---
Appearance settings control Eigent's color mode, theme palette, contrast, and Workspace background.
## Open Appearance
1. Open the Eigent dashboard.
2. Select **Settings**.
3. Select **Appearance**.
> **Screenshot placeholder:** Add a screenshot of Appearance settings with color mode, theme selection, color controls, contrast, and Workspace background visible.
## Choose a color mode
Select:
- **Light**
- **Dark**
- **System**
System mode follows the operating-system appearance.
## Choose a theme
Built-in theme families include:
- Eigent
- CAMEL
- Claw
- Starfish
Additional customizable slots include Whale and Custom.
Light and dark mode can use different selected themes.
## Edit theme colors
Depending on the theme, configure:
- Accent
- Background
- Ink
Enter a six-digit hexadecimal color or use the color picker. Select **Apply** to keep the pending color.
## Adjust contrast
Use the contrast slider to increase or reduce separation between generated theme colors.
Review text, controls, borders, status colors, and focus indicators after changing contrast.
## Reset a theme
Use Reset to restore the selected theme to its default values. Custom values for that theme are removed.
## Choose a Workspace background
Available backgrounds include:
- Plain
- Grid
- Dot pattern
- Dashed lines
- Dotted lines
- Ruled lines
The background changes the main Workspace canvas and does not affect project files or agent output.
> **Video placeholder:** Add a 45-second MP4 showing light and dark mode, theme selection, custom accent color, contrast changes, and all Workspace backgrounds. Include captions.
## Accessibility guidance
- Keep text contrast high enough for comfortable reading.
- Check status colors in both light and dark mode.
- Avoid background patterns that reduce focus.
- Use System mode when the operating system manages accessibility preferences.
## Related guides
- [General settings](/settings/general)
- [Privacy](/settings/privacy)

94
docs/settings/general.md Normal file
View file

@ -0,0 +1,94 @@
---
title: General settings
description: Manage your account, language, application version, and network proxy.
icon: gear
---
General settings control the signed-in account, interface language, network proxy, and application version.
## Open General settings
1. Open the Eigent dashboard.
2. Select **Settings**.
3. Select **General**.
> **Screenshot placeholder:** Add a screenshot of General settings with Profile, Language, and Network Proxy sections visible. Hide the full email address if required.
## Manage the account
The Profile section shows the current account.
- Select **Manage** to open Eigent account management.
- Select **Log out** to clear active task state, reset local installation state, and return to login.
Save or finish important work before logging out.
## Change the language
1. Open the Language selector.
2. Choose a language or **System default**.
Current interface languages include:
- English
- Simplified Chinese
- Traditional Chinese
- Japanese
- Arabic
- French
- German
- Russian
- Spanish
- Korean
- Italian
Some third-party tool output and generated content can remain in another language.
## Configure a network proxy
1. Enter the proxy URL in **Network Proxy**.
2. Select **Save**.
3. Select **Restart to apply**.
Supported schemes:
- `http://`
- `https://`
- `socks4://`
- `socks5://`
Example:
```text
http://127.0.0.1:8080
```
Clear the field and save to remove the proxy.
## Review updates
The Settings sidebar shows the installed version. When an update is available, select the update action to start the package download.
Self-hosted development builds should update through Git and the repository build process instead.
> **Video placeholder:** Add a 45-second MP4 showing language change, proxy save and restart, and the version or update control. Include captions.
## Troubleshooting
### Proxy URL is rejected
Include a supported scheme and valid host. Credentials, when required, must use valid URL encoding.
### Network changes do not apply
Restart Eigent after saving or removing the proxy.
### Language changes only part of the interface
Restart the application and report missing translation keys with the current version and locale.
## Related guides
- [Appearance](/settings/appearance)
- [Privacy](/settings/privacy)
- [Self-hosting](/get_started/self-hosting)

104
docs/settings/privacy.md Normal file
View file

@ -0,0 +1,104 @@
---
title: Privacy
description: Understand Eigent's privacy controls and data-handling boundaries.
icon: fingerprint
---
Eigent can process prompts, files, credentials, browser sessions, and external service data. Where that data goes depends on the selected model, deployment mode, Space type, and connectors.
This page provides a practical privacy checklist. Review the current privacy policy and source code for deployment-specific guarantees.
## Understand model data flow
### Eigent Cloud
Prompts and relevant context are sent through Eigent's managed model service.
### Bring Your Own Key
Prompts and relevant context are sent to the configured provider endpoint using your credentials.
### Local models
Model requests are sent to the configured local endpoint. Data can remain on infrastructure you control when all other tools and services are also local.
<Note>
A local model does not make the entire workflow local if the task also uses cloud connectors, search, remote MCP servers, or external browser services.
</Note>
## Understand file storage
- Local-folder Spaces can let agents read and modify the selected directory.
- Blank Spaces store generated artifacts in Eigent-managed project storage.
- Uploaded files become task context.
- Generated outputs can remain in project or workspace folders.
Limit each Space to the files required for its work.
## Protect credentials
Credentials can include:
- Model API keys
- MCP environment variables
- OAuth grants
- Search credentials
- Browser cookies
- Remote-control links
Use restricted credentials, rotate exposed values, and remove unused configurations.
## Manage browser sessions
Browser cookies can grant access to external accounts.
- Use a dedicated automation profile.
- Delete unused cookie domains.
- Avoid privileged sessions.
- Restart after changing cookie state.
## Share tasks and remote links safely
Before sharing:
- Review prompts and generated outputs.
- Remove personal or confidential data.
- Confirm the active Space and Project.
- Stop remote-control sessions after use.
## Delete data
Eigent provides deletion or removal actions for:
- Tasks
- Projects
- Some Space records
- Model providers
- Connectors and MCP servers
- Browser cookies
- Remote-control sessions
Deletion in Eigent does not automatically revoke data or credentials stored by an external provider.
> **Screenshot placeholder:** Add a privacy-oriented composite screenshot showing provider removal, connector removal, cookie deletion, and project deletion confirmations. Do not include real data.
> **Video placeholder:** Add a 60-second privacy walkthrough covering local versus cloud models, Space file boundaries, credential removal, and browser-cookie cleanup. Include captions.
## Open-source deployments
Self-hosting gives you control over the application and infrastructure, but you remain responsible for:
- Network security
- Database access
- Secret storage
- Logs and backups
- User permissions
- Provider configuration
- Update and vulnerability management
## Related guides
- [Self-hosting](/get_started/self-hosting)
- [Provider reference](/models/provider-reference)
- [Custom MCP servers](/connectors/custom-mcp)
- [Browser cookies](/browser/cookies)

View file

@ -3,12 +3,7 @@ title: Bug
description: 'Follow these simple steps to report bugs and help improve our product for everyone:'
---
<img
src="/docs/images/bug_report.gif"
alt="Bug Report"
width="100%"
height="auto"
/>
> **Video placeholder:** Add a current video walkthrough for “Bug Report”. Include captions.
### Step 1: Open Report a bug

View file

@ -55,7 +55,7 @@ For inquiries about our Scalable and Custom plans, please please refer to our [*
- Click **Upgrade** to move to a higher tier with more monthly Credits.
- Click **+ Add Credits** to purchase an Add-On Pack when you've used up your monthly allowance.
![Support Dashboard](/docs/images/support_dashboard.png)
> **Screenshot placeholder:** Add a current screenshot for “Support Dashboard”.
### Invitation Code

View file

@ -2225,7 +2225,7 @@ async function createWindow() {
: '#f5f5f580',
// macOS-specific title bar styling
titleBarStyle: isMac ? 'hidden' : undefined,
trafficLightPosition: isMac ? { x: 10, y: 10 } : undefined,
trafficLightPosition: isMac ? { x: 10, y: 12 } : undefined,
icon: path.join(VITE_PUBLIC, 'favicon.ico'),
// Rounded corners on macOS and Linux (as original)
roundedCorners: !isWindows,

View file

@ -17,3 +17,10 @@ src/components/ui/colorPicker.tsx
electron/main/index.ts
electron/main/fileReader.ts
electron/preload/index.ts
#
# Animation assets — demo/preview components use hardcoded colors intentionally for visual fidelity.
src/assets/animation/project/ProjectWorkspaceDisplay.tsx
src/assets/animation/workspace/WorkspaceDisplay.tsx
#
# OnboardingSteps — theme accent swatches must reference exact brand hex values from the theme catalog.
src/components/InstallStep/OnboardingSteps.tsx

View file

@ -55,10 +55,11 @@ from app.model.space.apply import SpaceOverlayListResponse
from app.domains.remote_control.service.remote_control_service import (
COMMAND_ACKNOWLEDGED,
COMMAND_FAILED,
COMMAND_PENDING,
RemoteControlRedis,
RemoteControlService,
)
from app.model.remote_control import RemoteControlSession
from app.model.remote_control import RemoteControlCommand, RemoteControlSession
from app.model.user.user import User
from app.shared.auth import auth_must
from app.shared.auth.token_blacklist import BLACKLIST_PUBSUB_PREFIX, is_blacklisted
@ -376,6 +377,97 @@ async def _auth_token(token: str | None, db: Session) -> V1UserAuth:
return auth
def _pending_bridge_commands(
desktop_instance_id: str,
user_id: int,
db: Session,
*,
limit: int = 50,
) -> list[tuple[RemoteControlSession, RemoteControlCommand]]:
sessions = db.exec(
select(RemoteControlSession).where(
RemoteControlSession.user_id == user_id,
RemoteControlSession.desktop_instance_id == desktop_instance_id,
RemoteControlSession.status == "active",
)
).all()
if not sessions:
return []
sessions_by_id = {rc_session.id: rc_session for rc_session in sessions}
commands = db.exec(
select(RemoteControlCommand)
.where(
RemoteControlCommand.session_id.in_(sessions_by_id.keys()),
RemoteControlCommand.status == COMMAND_PENDING,
)
.order_by(RemoteControlCommand.created_at)
.limit(limit)
).all()
return [
(sessions_by_id[command.session_id], command)
for command in commands
if command.session_id in sessions_by_id
]
async def _send_bridge_command(
websocket: WebSocket,
rc_session: RemoteControlSession,
command: RemoteControlCommand,
) -> bool:
try:
await websocket.send_json(RemoteControlService.command_payload(rc_session, command))
return True
except Exception as exc:
logger.warning(
"Failed to send remote-control command to desktop bridge",
extra={
"desktop_instance_id": rc_session.desktop_instance_id,
"command_id": command.id,
"error": str(exc),
},
)
return False
async def _flush_pending_bridge_commands(
desktop_instance_id: str,
user_id: int,
db: Session,
*,
websocket: WebSocket | None = None,
) -> int:
target_ws = websocket or bridge_websockets.get(desktop_instance_id)
if target_ws is None:
return 0
if websocket is None and bridge_users.get(desktop_instance_id) != user_id:
return 0
delivered_count = 0
for rc_session, command in _pending_bridge_commands(desktop_instance_id, user_id, db):
if await _send_bridge_command(target_ws, rc_session, command):
delivered_count += 1
return delivered_count
async def _flush_pending_for_session(rc_session: RemoteControlSession, db: Session) -> None:
delivered_count = await _flush_pending_bridge_commands(
rc_session.desktop_instance_id,
rc_session.user_id,
db,
)
if delivered_count:
logger.info(
"Flushed pending remote-control commands to local bridge",
extra={
"session_id": rc_session.id,
"desktop_instance_id": rc_session.desktop_instance_id,
"delivered_count": delivered_count,
},
)
@router.post(
"/sessions",
response_model=RemoteControlCreateSessionOut,
@ -478,7 +570,7 @@ def extend_session(
@router.patch("/sessions/{session_id}/target", response_model=RemoteControlPatchTargetOut)
def patch_target(
async def patch_target(
session_id: str,
data: RemoteControlPatchTargetIn,
t: str | None = Query(None),
@ -494,12 +586,14 @@ def patch_target(
None,
db_session,
)
return RemoteControlService.patch_target(
result = RemoteControlService.patch_target(
session_id,
rc_session.user_id,
data,
db_session,
)
await _flush_pending_for_session(rc_session, db_session)
return result
@router.delete("/sessions/{session_id}")
@ -528,7 +622,7 @@ def revoke_session(
response_model_exclude_none=True,
dependencies=[remote_command_burst_rate_limiter, remote_command_minute_rate_limiter],
)
def send_command(
async def send_command(
session_id: str,
data: RemoteControlCommandIn,
t: str | None = Query(None),
@ -544,12 +638,14 @@ def send_command(
None,
db_session,
)
return RemoteControlService.send_command(
result = RemoteControlService.send_command(
session_id,
rc_session.user_id,
data,
db_session,
)
await _flush_pending_for_session(rc_session, db_session)
return result
@router.get(
@ -625,7 +721,7 @@ def list_session_project_overlays(
response_model=RemoteControlFolderOperationOut,
dependencies=[remote_command_burst_rate_limiter, remote_command_minute_rate_limiter],
)
def apply_session_project_run(
async def apply_session_project_run(
session_id: str,
project_id: str,
data: RemoteControlFolderApplyIn,
@ -642,13 +738,15 @@ def apply_session_project_run(
None,
db_session,
)
return RemoteControlService.enqueue_apply_project(
result = RemoteControlService.enqueue_apply_project(
session_id,
rc_session.user_id,
project_id,
data,
db_session,
)
await _flush_pending_for_session(rc_session, db_session)
return result
@router.post(
@ -656,7 +754,7 @@ def apply_session_project_run(
response_model=RemoteControlFolderOperationOut,
dependencies=[remote_command_burst_rate_limiter, remote_command_minute_rate_limiter],
)
def discard_session_project_overlays(
async def discard_session_project_overlays(
session_id: str,
project_id: str,
data: RemoteControlFolderDiscardIn,
@ -673,13 +771,15 @@ def discard_session_project_overlays(
None,
db_session,
)
return RemoteControlService.enqueue_discard_project_overlays(
result = RemoteControlService.enqueue_discard_project_overlays(
session_id,
rc_session.user_id,
project_id,
data,
db_session,
)
await _flush_pending_for_session(rc_session, db_session)
return result
@router.post(
@ -687,7 +787,7 @@ def discard_session_project_overlays(
response_model=RemoteControlFolderOperationOut,
dependencies=[remote_command_burst_rate_limiter, remote_command_minute_rate_limiter],
)
def refresh_session_project(
async def refresh_session_project(
session_id: str,
project_id: str,
data: RemoteControlFolderRefreshIn,
@ -704,13 +804,15 @@ def refresh_session_project(
None,
db_session,
)
return RemoteControlService.enqueue_refresh_project(
result = RemoteControlService.enqueue_refresh_project(
session_id,
rc_session.user_id,
project_id,
data,
db_session,
)
await _flush_pending_for_session(rc_session, db_session)
return result
async def _validate_bridge_token(
@ -813,6 +915,12 @@ async def bridge_subscribe(websocket: WebSocket):
db.commit()
await websocket.send_json({"type": "connected", "desktop_instance_id": desktop_instance_id})
await _flush_pending_bridge_commands(
desktop_instance_id,
user_id,
db,
websocket=websocket,
)
while True:
msg = await websocket.receive_json()
@ -855,6 +963,12 @@ async def bridge_subscribe(websocket: WebSocket):
return
next_blacklist_check_at = now + timedelta(seconds=blacklist_check_interval)
RemoteControlRedis.refresh_bridge(desktop_instance_id, user_id, worker_id)
await _flush_pending_bridge_commands(
desktop_instance_id,
user_id,
db,
websocket=websocket,
)
await websocket.send_json({"type": "pong", "timestamp": datetime.utcnow().isoformat()})
elif msg_type == "reauth" and msg.get("auth_token"):
try:
@ -1113,6 +1227,14 @@ async def _handle_pubsub_message(channel: str, payload: dict[str, Any]) -> None:
ws = bridge_websockets.get(desktop_instance_id)
if ws:
await ws.send_json(payload)
else:
logger.warning(
"Remote-control command pub/sub arrived without a local bridge websocket",
extra={
"desktop_instance_id": desktop_instance_id,
"command_id": payload.get("command", {}).get("id"),
},
)
return
if channel.startswith("rc:ack:"):

View file

@ -226,8 +226,13 @@ class RemoteControlRedis:
@staticmethod
def publish(channel: str, payload: dict[str, Any]) -> bool:
try:
get_redis_manager().client.publish(channel, json.dumps(payload))
return True
subscriber_count = get_redis_manager().client.publish(channel, json.dumps(payload))
if subscriber_count == 0 and channel.startswith("rc:cmd:"):
logger.warning(
"Remote control command publish had no Redis subscribers",
extra={"channel": channel},
)
return subscriber_count > 0
except Exception as exc:
logger.warning("Remote control Redis publish failed", extra={"channel": channel, "error": str(exc)})
return False

View file

@ -110,11 +110,16 @@ export async function getBaseURL() {
return '';
}
type FetchRequestOptions = {
signal?: AbortSignal;
};
async function fetchRequest(
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
url: string,
data?: Record<string, any>,
customHeaders: Record<string, string> = {}
customHeaders: Record<string, string> = {},
requestOptions: FetchRequestOptions = {}
): Promise<any> {
const baseURL = await getBaseURL();
const fullUrl = `${baseURL}${url}`;
@ -123,6 +128,7 @@ async function fetchRequest(
const options: RequestInit = {
method,
headers,
signal: requestOptions.signal,
};
if (method === 'GET') {
@ -155,6 +161,9 @@ async function handleResponse(
if (res.status === 204) {
return { code: 0, text: '' };
}
if (res.status === 304) {
return { code: 0, not_modified: true };
}
const contentType = res.headers.get('content-type') || '';
if (!contentType.includes('application/json')) {
@ -228,6 +237,10 @@ async function handleResponse(
return resData;
} catch (err: any) {
if (err?.name === 'AbortError') {
throw err;
}
// Only show traffic toast for cloud model requests
const isCloudRequest = requestData?.api_url === 'cloud';
if (isCloudRequest) {
@ -247,8 +260,12 @@ async function handleResponse(
}
// Encapsulate common methods
export const fetchGet = (url: string, params?: any, headers?: any) =>
fetchRequest('GET', url, params, headers);
export const fetchGet = (
url: string,
params?: any,
headers?: any,
options?: FetchRequestOptions
) => fetchRequest('GET', url, params, headers, options);
export const fetchPost = (url: string, data?: any, headers?: any) =>
fetchRequest('POST', url, data, headers);

View file

@ -1,6 +0,0 @@
<svg width="49" height="48" viewBox="0 0 49 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.12872 8.36141C17.2857 -4.62357 37.9728 -2.06041 45.7065 13.1074C40.2625 13.1094 31.7376 13.1057 27.1205 13.1074C23.7718 13.1085 21.6096 13.0324 19.2682 14.265C16.5155 15.714 14.4385 18.3999 13.7135 21.5547L6.12872 8.36141Z" fill="#EA4335"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.3492 23.9992C16.3492 28.4 19.9274 31.9803 24.3258 31.9803C28.724 31.9803 32.3023 28.4 32.3023 23.9992C32.3023 19.5985 28.724 16.0182 24.3258 16.0182C19.9274 16.0182 16.3492 19.5985 16.3492 23.9992Z" fill="#4285F4"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.4213 34.4463C22.9442 35.7769 17.7049 34.3013 14.835 29.3475C12.6443 25.5662 6.85628 15.4828 4.22545 10.8978C-4.98858 25.0201 2.95261 44.265 19.68 47.5498L27.4213 34.4463Z" fill="#34A853"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M31.735 16.0182C35.4639 19.4864 36.2763 25.1023 33.7505 29.4569C31.8474 32.7376 25.7737 42.9888 22.8301 47.9527C40.0645 49.0152 52.6282 32.124 46.9533 16.0182H31.735Z" fill="#FBBC05"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,20 +0,0 @@
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.5779 16.5309C17.2342 20.1403 13.4373 21.1246 11.9373 21.0309C2.98417 20.609 4.34354 8.74965 9.73417 8.79653C5.89042 11.234 11.1404 19.2965 18.8748 16.1559C19.6717 15.5934 19.8123 16.2965 19.5779 16.5309Z" fill="url(#paint0_radial_2832_43625)"/>
<path d="M13.5781 10.9526C14.4219 7.10889 12.125 4.62451 7.53125 4.62451C2.9375 4.62451 0.78125 8.93701 0.78125 11.1401C0.78125 16.9526 6.64062 22.9995 14.2344 20.6558C7.95312 22.4839 4.20312 15.2183 7.39062 10.812C9.54688 7.71826 13.1562 7.62451 13.5781 10.9526ZM18.2656 3.64014H18.3125H18.2656Z" fill="url(#paint1_radial_2832_43625)"/>
<path d="M0.827637 10.8586C1.39014 -1.70389 18.6401 -2.40702 21.1245 8.46798C21.7808 13.4836 17.0933 15.4524 13.3433 13.8586C11.3745 12.6399 14.562 12.9211 13.2026 9.21798C10.9526 3.96798 1.43701 4.38986 0.827637 10.8586Z" fill="url(#paint2_linear_2832_43625)"/>
<defs>
<radialGradient id="paint0_radial_2832_43625" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(13.9891 14.9166) scale(7.11414 6.12025)">
<stop offset="0.8" stop-color="#114488"/>
<stop offset="1" stop-color="#113377"/>
</radialGradient>
<radialGradient id="paint1_radial_2832_43625" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(9.54688 14.16) scale(8.76562 8.76655)">
<stop offset="0.8" stop-color="#3388CC"/>
<stop offset="1" stop-color="#226699"/>
</radialGradient>
<linearGradient id="paint2_linear_2832_43625" x1="0.827637" y1="7.6176" x2="17.1067" y2="19.8352" gradientUnits="userSpaceOnUse">
<stop offset="0.1" stop-color="#55AADD"/>
<stop offset="0.6" stop-color="#55CC88"/>
<stop offset="0.8" stop-color="#77DD55"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -1,33 +0,0 @@
<svg width="38" height="39" viewBox="0 0 38 39" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_ddi_3582_82715)">
<rect x="3" y="1" width="32" height="32" rx="8" fill="#1D1D1D"/>
<path d="M17.0229 8.55373C17.2431 8.84968 17.4278 9.39533 17.5769 10.1907L18.994 17.8761C19.7327 22.0471 20.2476 24.6089 20.5389 25.5615C20.8301 26.5141 21.3024 26.9904 21.9559 26.9904H22.9368C23.3658 26.9904 24.2492 27 25 27V26.1875C24.6782 26.1986 24.142 26.0186 23.9275 25.8798C23.6057 25.6716 23.1767 25.3245 23.0318 25.1315C22.8329 24.8664 22.5878 24.5396 22.3819 23.9662C22.1759 23.3928 21.8953 22.3246 21.5402 20.7616C21.185 19.1986 20.734 16.8865 20.1871 13.8253C19.6401 10.7548 19.3205 8.94216 19.2282 8.38726C19.15 7.89709 19.0399 7.54565 18.8979 7.33294C18.7629 7.11098 18.5498 7 18.2586 7C17.8537 7 16.5016 7.13882 15 7.55529V8.11721C15.429 8.11721 15.755 8.10981 15.9255 8.10981C16.4369 8.10981 16.8027 8.25778 17.0229 8.55373Z" fill="white"/>
<path d="M24.0229 8.55373C24.2431 8.84968 24.4278 9.39533 24.5769 10.1907L25.994 17.8761C26.7327 22.0471 27.2476 24.6089 27.5389 25.5615C27.8301 26.5141 28.3024 26.9904 28.9559 26.9904H29.9368C30.3658 26.9904 31.2492 27 32 27V26.1875C31.6782 26.1986 31.142 26.0186 30.9275 25.8798C30.6057 25.6716 30.1767 25.3245 30.0318 25.1315C29.8329 24.8664 29.5878 24.5396 29.3819 23.9662C29.1759 23.3928 28.8953 22.3246 28.5402 20.7616C28.185 19.1986 27.734 16.8865 27.1871 13.8253C26.6401 10.7548 26.3205 8.94216 26.2282 8.38726C26.15 7.89709 26.0399 7.54565 25.8979 7.33294C25.7629 7.11098 25.5498 7 25.2586 7C24.8537 7 23.5016 7.13882 22 7.55529V8.11721C22.429 8.11721 22.755 8.10981 22.9255 8.10981C23.4369 8.10981 23.8027 8.25778 24.0229 8.55373Z" fill="white"/>
<path d="M10.0229 8.55373C10.2431 8.84968 10.4278 9.39533 10.5769 10.1907L11.994 17.8761C12.7327 22.0471 13.2476 24.6089 13.5389 25.5615C13.8301 26.5141 14.3024 26.9904 14.9559 26.9904H15.9368C16.3658 26.9904 17.2492 27 18 27V26.1875C17.6782 26.1986 17.142 26.0186 16.9275 25.8798C16.6057 25.6716 16.1767 25.3245 16.0318 25.1315C15.8329 24.8664 15.5878 24.5396 15.3819 23.9662C15.1759 23.3928 14.8953 22.3246 14.5402 20.7616C14.185 19.1986 13.734 16.8865 13.1871 13.8253C12.6401 10.7548 12.3205 8.94216 12.2282 8.38726C12.15 7.89709 12.0399 7.54565 11.8979 7.33294C11.7629 7.11098 11.5498 7 11.2586 7C10.8537 7 9.50156 7.13882 8 7.55529V8.11721C8.42902 8.11721 8.75504 8.10981 8.92551 8.10981C9.43692 8.10981 9.80273 8.25778 10.0229 8.55373Z" fill="white"/>
</g>
<defs>
<filter id="filter0_ddi_3582_82715" x="0" y="0" width="38" height="39" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="1" operator="dilate" in="SourceAlpha" result="effect1_dropShadow_3582_82715"/>
<feOffset/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.831373 0 0 0 0 0.831373 0 0 0 0 0.831373 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3582_82715"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="1" operator="erode" in="SourceAlpha" result="effect2_dropShadow_3582_82715"/>
<feOffset dy="3"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_3582_82715" result="effect2_dropShadow_3582_82715"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_3582_82715" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="1"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.33 0"/>
<feBlend mode="normal" in2="shape" result="effect3_innerShadow_3582_82715"/>
</filter>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -1,6 +0,0 @@
<svg width="49" height="48" viewBox="0 0 49 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M45.3355 24.4663C45.3355 22.7397 45.1925 21.4797 44.8831 20.173H24.764V27.9663H36.5735C36.3355 29.9031 35.0497 32.8197 32.1925 34.7796L32.1524 35.0406L38.5138 39.87L38.9545 39.913C43.0021 36.2497 45.3355 30.8596 45.3355 24.4663Z" fill="#4285F4"/>
<path d="M24.7628 44.9997C30.5485 44.9997 35.4054 43.1329 38.9532 39.9129L32.1912 34.7794C30.3818 36.0162 27.9531 36.8794 24.7628 36.8794C19.0963 36.8794 14.2867 33.2161 12.5723 28.1529L12.321 28.1737L5.70647 33.1905L5.61996 33.4261C9.14373 40.2861 16.3819 44.9997 24.7628 44.9997Z" fill="#34A853"/>
<path d="M12.5728 28.1535C12.1204 26.8469 11.8586 25.4468 11.8586 24.0002C11.8586 22.5534 12.1204 21.1535 12.549 19.8468L12.537 19.5684L5.83958 14.4712L5.62046 14.5733C4.16815 17.4201 3.33481 20.6168 3.33481 24.0002C3.33481 27.3834 4.16815 30.5801 5.62046 33.4268L12.5728 28.1535Z" fill="#FBBC05"/>
<path d="M24.7629 11.12C28.7867 11.12 31.5009 12.8233 33.0486 14.2467L39.0962 8.46C35.382 5.07668 30.5486 3 24.7629 3C16.3818 3 9.14375 7.7133 5.61996 14.5732L12.5485 19.8467C14.2868 14.7833 19.0962 11.12 24.7629 11.12Z" fill="#EB4335"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
import react from '@vitejs/plugin-react';
import path from 'node:path';
import { defineConfig } from 'vite';
export default defineConfig({
root: path.join(__dirname, 'preview'),
plugins: [react()],
resolve: {
alias: {
'@': path.join(__dirname, '../..'),
},
},
server: {
port: 5199,
open: false,
},
});

View file

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before After
Before After

Binary file not shown.

View file

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.7329 5.07599C13.0623 4.7984 15.4185 5.29081 17.4418 6.47804C19.465 7.66527 21.0441 9.48207 21.9379 11.651C22.0213 11.8755 22.0213 12.1225 21.9379 12.347C21.5704 13.238 21.0847 14.0755 20.4939 14.837M14.0839 14.158C13.5181 14.7045 12.7603 15.0069 11.9737 15C11.1871 14.9932 10.4347 14.6777 9.87844 14.1215C9.32221 13.5652 9.0067 12.8128 8.99987 12.0262C8.99303 11.2396 9.29542 10.4818 9.84189 9.91602M17.479 17.499C16.1525 18.2848 14.6725 18.776 13.1394 18.9394C11.6063 19.1028 10.056 18.9345 8.59365 18.4459C7.13133 17.9573 5.79121 17.1599 4.66423 16.1078C3.53725 15.0556 2.64977 13.7734 2.06202 12.348C1.97868 12.1235 1.97868 11.8765 2.06202 11.652C2.94865 9.50189 4.50869 7.69728 6.50802 6.50903M2 2L22 22" stroke="#222222" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 908 B

View file

@ -1,4 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.06202 12.3484C1.97868 12.1238 1.97868 11.8769 2.06202 11.6524C2.87372 9.68421 4.25153 8.0014 6.02079 6.81726C7.79004 5.63312 9.87106 5.00098 12 5.00098C14.129 5.00098 16.21 5.63312 17.9792 6.81726C19.7485 8.0014 21.1263 9.68421 21.938 11.6524C22.0214 11.8769 22.0214 12.1238 21.938 12.3484C21.1263 14.3165 19.7485 15.9993 17.9792 17.1835C16.21 18.3676 14.129 18.9997 12 18.9997C9.87106 18.9997 7.79004 18.3676 6.02079 17.1835C4.25153 15.9993 2.87372 14.3165 2.06202 12.3484Z" stroke="#222222" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 15.0002C13.6569 15.0002 15 13.6571 15 12.0002C15 10.3434 13.6569 9.00024 12 9.00024C10.3431 9.00024 9 10.3434 9 12.0002C9 13.6571 10.3431 15.0002 12 15.0002Z" stroke="#222222" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 929 B

View file

@ -1,8 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747711765316"
class="icon" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12436"
xmlns:xlink="http://www.w3.org/1999/xlink" width="21.0205078125" height="21">
<path
d="M0 525q0 166 95.5 298.5T343 1009q6 1 10 1t6.5-1.5 4-3 2-5 0.5-5V895q-37 4-66-0.5t-45.5-14-29-23.5-17-25.5-9-24T194 793q-9-15-27-27.5t-27-20-2-14.5q50-26 113 66 34 51 119 30 10-41 40-70-116-21-172-86t-56-158q0-87 55-151-22-65 6-137 29-2 65 11.5t50.5 23T384 277q57-16 128.5-16T642 277q13-9 29-19t49-21.5 61-9.5q27 71 7 135 56 64 56 151 0 93-57 158.5T615 757q43 43 43 104v129q0 1 1 3 0 6 0.5 9t4.5 6 12 3q153-52 250.5-185.5T1024 525q0-104-40.5-199t-109-163.5T711 53.5 512 13 313 53.5t-163.5 109T40.5 326 0 525z"
fill="currentColor" p-id="12437"></path>
</svg>

Before

Width:  |  Height:  |  Size: 916 B

View file

@ -1,3 +0,0 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.5001 22V18C15.6392 16.7473 15.28 15.4901 14.5001 14.5C17.5001 14.5 20.5001 12.5 20.5001 9C20.5801 7.75 20.2301 6.52 19.5001 5.5C19.7801 4.35 19.7801 3.15 19.5001 2C19.5001 2 18.5001 2 16.5001 3.5C13.8601 3 11.1401 3 8.5001 3.5C6.5001 2 5.5001 2 5.5001 2C5.2001 3.15 5.2001 4.35 5.5001 5.5C4.77197 6.51588 4.41857 7.75279 4.5001 9C4.5001 12.5 7.5001 14.5 10.5001 14.5C10.1101 14.99 9.8201 15.55 9.6501 16.15C9.4801 16.75 9.4301 17.38 9.5001 18M9.5001 18V22M9.5001 18C4.9901 20 4.50006 16 2.50006 16" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 696 B

View file

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1747711187655" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6068" xmlns:xlink="http://www.w3.org/1999/xlink" width="21" height="21"><path d="M214.101333 512c0-32.512 5.546667-63.701333 15.36-92.928L57.173333 290.218667A491.861333 491.861333 0 0 0 4.693333 512c0 79.701333 18.858667 154.88 52.394667 221.610667l172.202667-129.066667A290.56 290.56 0 0 1 214.101333 512" fill="#FBBC05" p-id="6069"></path><path d="M516.693333 216.192c72.106667 0 137.258667 25.002667 188.458667 65.962667L854.101333 136.533333C763.349333 59.178667 646.997333 11.392 516.693333 11.392c-202.325333 0-376.234667 113.28-459.52 278.826667l172.373334 128.853333c39.68-118.016 152.832-202.88 287.146666-202.88" fill="#EA4335" p-id="6070"></path><path d="M516.693333 807.808c-134.357333 0-247.509333-84.864-287.232-202.88l-172.288 128.853333c83.242667 165.546667 257.152 278.826667 459.52 278.826667 124.842667 0 244.053333-43.392 333.568-124.757333l-163.584-123.818667c-46.122667 28.458667-104.234667 43.776-170.026666 43.776" fill="#34A853" p-id="6071"></path><path d="M1005.397333 512c0-29.568-4.693333-61.44-11.648-91.008H516.650667V614.4h274.602666c-13.696 65.962667-51.072 116.650667-104.533333 149.632l163.541333 123.818667c93.994667-85.418667 155.136-212.650667 155.136-375.850667" fill="#4285F4" p-id="6072"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 621 KiB

View file

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Before After
Before After

View file

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 8.5H14C14.8284 8.5 15.5 9.17157 15.5 10V14C15.5 14.8284 14.8284 15.5 14 15.5H10C9.17157 15.5 8.5 14.8284 8.5 14V10C8.5 9.17157 9.17157 8.5 10 8.5Z" fill="#fff" stroke="#fff"/>
</svg>

Before

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Some files were not shown because too many files have changed in this diff Show more