Skip to content
Open
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
5f14a50
feat: server side trigger
a7m-1st Nov 27, 2025
88f8065
chore(temp): enhance deps
a7m-1st Nov 27, 2025
fd360a9
feat: eigent side updates on trigger
a7m-1st Nov 27, 2025
9615b8a
layout redesign for trigger
Douglasymlai Dec 2, 2025
3e4f139
restructure navigation
Douglasymlai Dec 2, 2025
3659e23
update trigger
Douglasymlai Dec 8, 2025
c9477e9
update design
Douglasymlai Dec 11, 2025
fa80b65
feat: server side trigger
a7m-1st Nov 27, 2025
3d18e91
chore(temp): enhance deps
a7m-1st Nov 27, 2025
6b929ed
feat: eigent side updates on trigger
a7m-1st Nov 27, 2025
839829b
Merge branch 'feat-trigger' of https://github.com/eigent-ai/eigent in…
a7m-1st Dec 12, 2025
2babe43
revert trigger
Jan 8, 2026
5962a74
Merge branch 'feat-trigger-ui' into feat-trigger
a7m-1st Jan 8, 2026
bee9d9b
feat: init update UI
a7m-1st Jan 11, 2026
3019186
fix: manage single websocket connection
a7m-1st Jan 11, 2026
247033b
chore: update dialog
a7m-1st Jan 11, 2026
71c8e0f
enhance: double click to edit
a7m-1st Jan 11, 2026
e3a6dd5
chore: update ux and remove mock data
a7m-1st Jan 11, 2026
3486bd5
chore: webhook_method and cleanup
a7m-1st Jan 11, 2026
fb177d3
chore: delete trigger
a7m-1st Jan 11, 2026
4c49ba6
enhance: webhook dialog + execution logs
a7m-1st Jan 12, 2026
d96bed0
chore: translation
a7m-1st Jan 12, 2026
0c1cea0
chore: fetch per project
a7m-1st Jan 12, 2026
8a1cb86
feat: trigger task executor
a7m-1st Jan 12, 2026
236acbc
revert local trigger backend
a7m-1st Jan 12, 2026
b5ab23d
chore: revert packages
a7m-1st Jan 12, 2026
2091e0d
update trigger UI
Douglasymlai Jan 13, 2026
2258b6d
update trigger layout style
Douglasymlai Jan 13, 2026
62b3100
remove mock data
Douglasymlai Jan 13, 2026
41fb01d
update content
Douglasymlai Jan 13, 2026
9ecdb2b
enhance: add gap between list items and english translation
a7m-1st Jan 13, 2026
eb0cba1
Feat trigger ux improvement (#841)
a7m-1st Jan 13, 2026
d771c29
enhance: convert to local time on client
a7m-1st Jan 13, 2026
10f7551
Merge remote-tracking branch 'origin/main' into feat-trigger
a7m-1st Jan 13, 2026
17fd145
fix: uv lock
a7m-1st Jan 14, 2026
41992cd
fix: edit trigger
a7m-1st Jan 14, 2026
4244e1e
fix: remove duplicate code block in UserQueryGroup component
Douglasymlai Jan 15, 2026
8c863eb
ux final iteration and language check
Douglasymlai Jan 15, 2026
5b46ab5
chore: enhance trigger_count
a7m-1st Jan 17, 2026
c5893ee
feat: Dynamic Trigger Config 🥳
a7m-1st Jan 17, 2026
98f6316
enhance: titles and look in webhook type
a7m-1st Jan 17, 2026
927fb5c
feat: validation config
a7m-1st Jan 17, 2026
551364e
enhance: exclude schema type
a7m-1st Jan 17, 2026
f25eb64
chore: update typings
a7m-1st Jan 17, 2026
ea47ef8
enhance: warning on non-verified status
a7m-1st Jan 17, 2026
deac156
feat: TanStackQuery 🚀
a7m-1st Jan 17, 2026
0d529b7
enhance: cache trigger config requests
a7m-1st Jan 17, 2026
dec2fb5
chore: ping pong and trigger websocket status
a7m-1st Jan 17, 2026
db0f039
chore: remove stuff
a7m-1st Jan 18, 2026
faa6aeb
enhance: task executor pipeline and isolate handleSend
a7m-1st Jan 18, 2026
eadd406
enhance: update subscription mechanism
a7m-1st Jan 18, 2026
2ccb1c2
enhance: update execution status per sse and introduce executionIdMap
a7m-1st Jan 18, 2026
dacf81e
chore: Duplicate event_id detected as missed
a7m-1st Jan 18, 2026
203ffb2
Merge remote-tracking branch 'origin/main' into feat-trigger
a7m-1st Jan 19, 2026
9260439
chore: update uv
a7m-1st Jan 19, 2026
4ed5b5d
feat: enhance trigger schedule picker and UI components
Douglasymlai Jan 23, 2026
e3fd40a
time picker bug fix
Douglasymlai Jan 26, 2026
b25b246
update schedule setting design
Douglasymlai Jan 27, 2026
b0c2bd7
enhance: update trigger dialog structure
a7m-1st Jan 28, 2026
d627a9d
chore: update endpoint
a7m-1st Jan 29, 2026
257554e
Merge remote-tracking branch 'origin/main' into feat-trigger
a7m-1st Jan 31, 2026
7b33bfe
chore: continue incoming merge
a7m-1st Jan 31, 2026
f3458be
enhance: input size limits
a7m-1st Jan 31, 2026
5535a20
chore: update merge
a7m-1st Jan 31, 2026
8a2e892
chore: simplify webhook url ui
a7m-1st Feb 1, 2026
cda89ff
fix: task completed shortcut
a7m-1st Feb 1, 2026
679f327
fix: slack dialog not opening
a7m-1st Feb 1, 2026
9c40ab6
fix: edit secrets
a7m-1st Feb 1, 2026
781e2cc
chore: simplify trigger crud flow
a7m-1st Feb 1, 2026
aed3124
enhance: input optional lable
a7m-1st Feb 1, 2026
867a18d
chore: add consecutive_failures type to trigger
a7m-1st Feb 2, 2026
7748705
chore: update dynamic fields configs
a7m-1st Feb 2, 2026
c98988e
enhance: support date, expirationDate & max_failure_count of schedules
a7m-1st Feb 2, 2026
15dff69
chore: update format
a7m-1st Feb 2, 2026
e191f11
feat: generative inputNumberField with min max validation
a7m-1st Feb 2, 2026
21c6b0a
Merge remote-tracking branch 'origin/main' into feat-trigger
a7m-1st Feb 4, 2026
900089b
Merge remote-tracking branch 'origin/main' into feat-trigger
a7m-1st Feb 4, 2026
f8fd4f5
chore: fix app.tsx
a7m-1st Feb 4, 2026
9509286
chore: hide ExpandedInputBox
a7m-1st Feb 4, 2026
34cad7d
fix: popover aschild recursive loop
a7m-1st Feb 4, 2026
25e5c30
chore: splitting tasks translation
a7m-1st Feb 4, 2026
1ae2ca8
chore: add missing translation keys
a7m-1st Feb 5, 2026
231947d
chore: enhance task queue
a7m-1st Feb 5, 2026
6189fd8
chore: enhance task queue
a7m-1st Feb 5, 2026
1daca29
chore: fix infinite rerender
a7m-1st Feb 5, 2026
559615d
enhance: update status atomically
a7m-1st Feb 5, 2026
b71d5de
enhance: refine the task trigger flow in replay, and normal flow
a7m-1st Feb 5, 2026
d08d77f
chore: fix linting errors
a7m-1st Feb 5, 2026
9119c66
Merge remote-tracking branch 'origin/main' into feat-trigger-server
a7m-1st Feb 9, 2026
ec93e2f
Merge remote-tracking branch 'origin/main' into feat-trigger
a7m-1st Feb 9, 2026
8455419
Merge branch 'feat-trigger' of https://github.com/eigent-ai/eigent in…
a7m-1st Feb 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ dependencies = [
"nodejs-wheel>=22.18.0",
"numpy>=1.23.0,<2.0.0",
"debugpy>=1.8.17",
"camel-ai>=0.2.82",
]


Expand Down
1,609 changes: 805 additions & 804 deletions backend/uv.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion electron/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,7 @@ async function createWindow() {
transparent: true,
vibrancy: 'sidebar',
visualEffectState: 'active',
backgroundColor: '#f5f5f580',
backgroundColor: '#F5F5F5',
titleBarStyle: isMac ? 'hidden' : undefined,
trafficLightPosition: isMac ? { x: 10, y: 10 } : undefined,
icon: path.join(VITE_PUBLIC, 'favicon.ico'),
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@radix-ui/react-toggle-group": "^1.1.10",
"@radix-ui/react-tooltip": "^1.2.7",
"@stackframe/react": "file:package/@stackframe/react",
"@tanstack/react-query": "^5.90.19",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/xterm": "^5.5.0",
Expand All @@ -65,6 +66,7 @@
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"csv-parser": "^3.2.0",
"date-fns": "^3.6.0",
"dompurify": "^3.2.7",
"electron-log": "^5.4.0",
"electron-updater": "^6.3.9",
Expand Down
1 change: 1 addition & 0 deletions server/alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
auto_import("app.model.config")
auto_import("app.model.chat")
auto_import("app.model.provider")
auto_import("app.model.trigger")


# target_metadata = mymodel.Base.metadata
Expand Down
37 changes: 27 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,30 @@ import { useNavigate } from "react-router-dom";
import { AnimationJson } from "@/components/AnimationJson";
import animationData from "@/assets/animation/openning_animaiton.json";
import { useAuthStore } from "./store/authStore";
import { useTriggerStore } from "./store/triggerStore";
import { useExecutionSubscription } from "./hooks/useExecutionSubscription";
import { useTriggerTaskExecutor } from "./hooks/useTriggerTaskExecutor";
import { Toaster } from "sonner";
import { hasStackKeys } from "./lib";
import { QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "@/lib/queryClient";

const HAS_STACK_KEYS = hasStackKeys();

function App() {
const navigate = useNavigate();
const { setInitState } = useAuthStore();
const [animationFinished, setAnimationFinished] = useState(false);
const { isFirstLaunch } = useAuthStore();
const { isFirstLaunch, token } = useAuthStore();
const { triggers } = useTriggerStore();

// Subscribe to execution events when user is authenticated
// Note: Removed triggers.length check to prevent reconnection on every trigger update
const shouldSubscribe = !!token;
useExecutionSubscription(shouldSubscribe);

// Execute triggered tasks automatically when WebSocket events are received
useTriggerTaskExecutor();

useEffect(() => {
const handleShareCode = (event: any, share_token: string) => {
Expand Down Expand Up @@ -68,20 +82,23 @@ function App() {

// render wrapper
const renderWrapper = (children: React.ReactNode) => {
if (HAS_STACK_KEYS) {
return (
<StackProvider app={stackClientApp}>
<StackTheme>{children}</StackTheme>
<Toaster style={{ zIndex: '999999 !important', position: "fixed" }} />
</StackProvider>
);
}
return (
const content = HAS_STACK_KEYS ? (
<StackProvider app={stackClientApp}>
<StackTheme>{children}</StackTheme>
<Toaster style={{ zIndex: '999999 !important', position: "fixed" }} />
</StackProvider>
) : (
<>
{children}
<Toaster style={{ zIndex: "999999 !important", position: "fixed" }} />
</>
);

return (
<QueryClientProvider client={queryClient}>
{content}
</QueryClientProvider>
);
};

return renderWrapper(renderMainContent());
Expand Down
105 changes: 66 additions & 39 deletions src/components/AddWorker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { fetchPost } from "@/api/http";
import { useAuthStore, useWorkerList } from "@/store/authStore";
import { useTranslation } from "react-i18next";
import useChatStoreAdapter from "@/hooks/useChatStoreAdapter";
import { MenuToggleGroup, MenuToggleItem } from "@/components/MenuButton/MenuButton";
import { TooltipSimple } from "@/components/ui/tooltip";

interface EnvValue {
value: string;
Expand All @@ -49,12 +51,23 @@ interface McpItem {
export function AddWorker({
edit = false,
workerInfo = null,
variant = "default",
isOpen,
onOpenChange,
}: {
edit?: boolean;
workerInfo?: Agent | null;
variant?: "default" | "icon";
isOpen?: boolean;
onOpenChange?: (open: boolean) => void;
}) {
const { t } = useTranslation();
const [dialogOpen, setDialogOpen] = useState(false);
const [internalOpen, setInternalOpen] = useState(false);

// Use controlled state if provided, otherwise internal state
const isControlled = typeof isOpen !== 'undefined' && typeof onOpenChange !== 'undefined';
const dialogOpen = isControlled ? isOpen : internalOpen;
const setDialogOpen = isControlled ? onOpenChange : setInternalOpen;
const { chatStore, projectStore } = useChatStoreAdapter();
if (!chatStore) {
return <div>Loading...</div>;
Expand All @@ -76,7 +89,7 @@ export function AddWorker({
const [workerName, setWorkerName] = useState("");
const [workerDescription, setWorkerDescription] = useState("");
const [selectedTools, setSelectedTools] = useState<McpItem[]>([]);

// error status management
const [nameError, setNameError] = useState<string>("");

Expand Down Expand Up @@ -242,7 +255,7 @@ export function AddWorker({
const handleAddWorker = async () => {
// clear previous errors
setNameError("");

if (!workerName) {
setNameError(t("workforce.worker-name-cannot-be-empty"));
return;
Expand All @@ -267,7 +280,7 @@ export function AddWorker({
});
console.log("mcpLocal.mcpServers", mcpLocal.mcpServers);
if (mcpLocal.mcpServers && typeof mcpLocal.mcpServers === 'object') {
for(const key of Object.keys(mcpLocal.mcpServers)) {
for (const key of Object.keys(mcpLocal.mcpServers)) {
if (!mcpList.includes(key)) {
delete mcpLocal.mcpServers[key];
}
Expand Down Expand Up @@ -357,32 +370,46 @@ export function AddWorker({
return (
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
<form>
<DialogTrigger asChild>
{edit ? (
<Button
variant="ghost"
size="sm"
className="w-full"
onClick={(e) => {
e.stopPropagation();
setDialogOpen(true);
setWorkerName(workerInfo?.workerInfo?.name || "");
setWorkerDescription(workerInfo?.workerInfo?.description || "");
setSelectedTools(workerInfo?.workerInfo?.selectedTools || []);
}}
>
<Edit size={16} />
{t("workforce.edit")}
</Button>
) : (
<Button onClick={() => setDialogOpen(true)} variant="ghost">
<Plus className="w-6 h-6 text-icon-primary" />
<span className="text-text-body text-[13px] leading-13 font-bold">
{t("workforce.new-worker")}
</span>
</Button>
)}
</DialogTrigger>
{!isControlled && (
<DialogTrigger asChild>
{edit ? (
<Button
variant="ghost"
size="sm"
className="w-full"
onClick={(e) => {
e.stopPropagation();
setDialogOpen(true);
setWorkerName(workerInfo?.workerInfo?.name || "");
setWorkerDescription(workerInfo?.workerInfo?.description || "");
setSelectedTools(workerInfo?.workerInfo?.selectedTools || []);
}}
>
<Edit size={16} />
{t("workforce.edit")}
</Button>
) : variant === "icon" ? (
<Button
variant="ghost"
size="icon"
className="h-6 w-6 rounded-full bg-surface-tertiary hover:bg-surface-tertiary-hover"
onClick={() => setDialogOpen(true)}
>
<Plus size={12} />
</Button>
) : (
<MenuToggleGroup type="single" value="add-worker">
<MenuToggleItem
value="add-worker"
variant="clear"
size="md"
icon={<Plus />}
onClick={() => setDialogOpen(true)}
/>
</MenuToggleGroup>
)}
</DialogTrigger>
)}
<DialogContent
size="sm"
className="p-0 gap-0"
Expand Down Expand Up @@ -460,7 +487,7 @@ export function AddWorker({
))}
</div>
</DialogContentSection>
<DialogFooter
<DialogFooter
className="bg-white-100% !rounded-b-xl p-md"
showCancelButton={true}
showConfirmButton={true}
Expand Down Expand Up @@ -489,7 +516,7 @@ export function AddWorker({
<div className="flex flex-col gap-4">
<div className="flex items-center gap-sm">
<div className="flex w-16 h-16 items-center justify-center">
<Bot size={32} className="text-icon-primary" />
<Bot size={32} className="text-icon-primary" />
</div>
<Input
size="sm"
Expand All @@ -509,12 +536,12 @@ export function AddWorker({
</div>

<Textarea
variant="enhanced"
size="sm"
title={t("workforce.description-optional")}
placeholder={t("layout.im-an-agent-specially-designed-for")}
value={workerDescription}
onChange={(e) => setWorkerDescription(e.target.value)}
variant="enhanced"
size="sm"
title={t("workforce.description-optional")}
placeholder={t("layout.im-an-agent-specially-designed-for")}
value={workerDescription}
onChange={(e) => setWorkerDescription(e.target.value)}
/>

<ToolSelect
Expand All @@ -524,7 +551,7 @@ export function AddWorker({
ref={toolSelectRef}
/>
</DialogContentSection>
<DialogFooter
<DialogFooter
className="bg-white-100% !rounded-b-xl p-md"
showCancelButton={true}
showConfirmButton={true}
Expand Down
47 changes: 44 additions & 3 deletions src/components/BottomBar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,50 @@
import { WorkSpaceMenu } from "@/components/WorkSpaceMenu";
import { MenuToggleGroup, MenuToggleItem } from "@/components/MenuButton/MenuButton";
import { Inbox } from "lucide-react";
import { TooltipSimple } from "@/components/ui/tooltip";
import useChatStoreAdapter from "@/hooks/useChatStoreAdapter";
import { useTranslation } from "react-i18next";

interface BottomBarProps {
onToggleChatBox?: () => void;
isChatBoxVisible?: boolean;
}

// Red dot notification indicator
const RedDotIcon = () => (
<div className="w-2 h-2 bg-red-500 rounded-full shrink-0" />
);

function BottomBar({ onToggleChatBox, isChatBoxVisible }: BottomBarProps) {
const { t } = useTranslation();
const { chatStore } = useChatStoreAdapter();

// Check if there are new files
const nuwFileNum = chatStore?.activeTaskId
? (chatStore.tasks[chatStore.activeTaskId]?.nuwFileNum || 0)
: 0;
const hasNewFiles = nuwFileNum > 0;

// Handle inbox click and reset notification
const handleInboxClick = () => {
if (chatStore?.activeTaskId) {
// Reset the new file counter when user views inbox
chatStore.setNuwFileNum(chatStore.activeTaskId, 0);
// Set active workspace to inbox
chatStore.setActiveWorkSpace(chatStore.activeTaskId, "inbox");
}
};

const activeWorkspace = chatStore?.activeTaskId
? chatStore.tasks[chatStore.activeTaskId]?.activeWorkSpace
: null;

function BottomBar() {
return (
<div className="flex h-12 items-center justify-center pb-2 z-50 relative">
<WorkSpaceMenu />
<div className="flex h-12 items-center justify-center z-50 relative pt-2">
<WorkSpaceMenu
onToggleChatBox={onToggleChatBox}
isChatBoxVisible={isChatBoxVisible}
/>
</div>
);
}
Expand Down
Loading