apteva 0.4.57 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -54
- package/cli.js +35 -0
- package/install.js +92 -0
- package/package.json +12 -79
- package/LICENSE +0 -63
- package/bin/apteva.js +0 -196
- package/dist/ActivityPage.kxzzb4yc.js +0 -3
- package/dist/ApiDocsPage.zq998hbm.js +0 -4
- package/dist/App.55rea8mn.js +0 -61
- package/dist/App.5ywb23z4.js +0 -53
- package/dist/App.6thds120.js +0 -4
- package/dist/App.9tctxzqm.js +0 -8
- package/dist/App.a8r8ttaz.js +0 -4
- package/dist/App.agsv5bje.js +0 -4
- package/dist/App.cepapqmx.js +0 -4
- package/dist/App.dp041gb3.js +0 -221
- package/dist/App.fds72zb5.js +0 -4
- package/dist/App.fg9qj2dq.js +0 -4
- package/dist/App.ndfejbm9.js +0 -4
- package/dist/App.nxmfmq1h.js +0 -13
- package/dist/App.qdfyt8ba.js +0 -4
- package/dist/App.x2d0ygt6.js +0 -4
- package/dist/App.yt9p4nr3.js +0 -20
- package/dist/App.zn4mw16t.js +0 -1
- package/dist/ConnectionsPage.8r96ryw7.js +0 -3
- package/dist/McpPage.3cwh0gnd.js +0 -3
- package/dist/SettingsPage.ykgdh5ev.js +0 -3
- package/dist/SkillsPage.4np1s65b.js +0 -3
- package/dist/TasksPage.4g08t7p6.js +0 -3
- package/dist/TelemetryPage.72w9pwcp.js +0 -3
- package/dist/TestsPage.z4fk3r7r.js +0 -3
- package/dist/ThreadsPage.63tcajeh.js +0 -3
- package/dist/apteva-kit.css +0 -1
- package/dist/icon.png +0 -0
- package/dist/index.html +0 -16
- package/dist/styles.css +0 -1
- package/scripts/postinstall.mjs +0 -102
- package/src/auth/index.ts +0 -394
- package/src/auth/middleware.ts +0 -213
- package/src/binary.ts +0 -536
- package/src/channels/index.ts +0 -40
- package/src/channels/telegram.ts +0 -311
- package/src/crypto.ts +0 -301
- package/src/db-tests.ts +0 -174
- package/src/db.ts +0 -3133
- package/src/integrations/agentdojo.ts +0 -559
- package/src/integrations/composio.ts +0 -437
- package/src/integrations/index.ts +0 -87
- package/src/integrations/skillsmp.ts +0 -318
- package/src/mcp-client.ts +0 -605
- package/src/mcp-handler.ts +0 -394
- package/src/mcp-platform.ts +0 -2403
- package/src/openapi.ts +0 -2410
- package/src/providers.ts +0 -597
- package/src/routes/api/agent-utils.ts +0 -890
- package/src/routes/api/agents.ts +0 -916
- package/src/routes/api/api-keys.ts +0 -95
- package/src/routes/api/channels.ts +0 -182
- package/src/routes/api/helpers.ts +0 -12
- package/src/routes/api/integrations.ts +0 -639
- package/src/routes/api/mcp.ts +0 -574
- package/src/routes/api/meta-agent.ts +0 -195
- package/src/routes/api/projects.ts +0 -112
- package/src/routes/api/providers.ts +0 -424
- package/src/routes/api/skills.ts +0 -537
- package/src/routes/api/system.ts +0 -333
- package/src/routes/api/telemetry.ts +0 -203
- package/src/routes/api/tests.ts +0 -148
- package/src/routes/api/triggers.ts +0 -518
- package/src/routes/api/users.ts +0 -148
- package/src/routes/api/webhooks.ts +0 -171
- package/src/routes/api.ts +0 -53
- package/src/routes/auth.ts +0 -251
- package/src/routes/share.ts +0 -86
- package/src/routes/static.ts +0 -131
- package/src/server.ts +0 -642
- package/src/test-runner.ts +0 -598
- package/src/triggers/agentdojo.ts +0 -253
- package/src/triggers/composio.ts +0 -264
- package/src/triggers/index.ts +0 -71
- package/src/tui/AgentList.tsx +0 -145
- package/src/tui/App.tsx +0 -102
- package/src/tui/Login.tsx +0 -104
- package/src/tui/api.ts +0 -72
- package/src/tui/index.tsx +0 -7
- package/src/web/App.tsx +0 -455
- package/src/web/components/activity/ActivityPage.tsx +0 -314
- package/src/web/components/activity/index.ts +0 -1
- package/src/web/components/agents/AgentCard.tsx +0 -189
- package/src/web/components/agents/AgentPanel.tsx +0 -2244
- package/src/web/components/agents/AgentsView.tsx +0 -180
- package/src/web/components/agents/CreateAgentModal.tsx +0 -475
- package/src/web/components/agents/index.ts +0 -4
- package/src/web/components/api/ApiDocsPage.tsx +0 -842
- package/src/web/components/auth/CreateAccountStep.tsx +0 -176
- package/src/web/components/auth/LoginPage.tsx +0 -91
- package/src/web/components/auth/index.ts +0 -2
- package/src/web/components/common/Icons.tsx +0 -250
- package/src/web/components/common/LoadingSpinner.tsx +0 -44
- package/src/web/components/common/Modal.tsx +0 -199
- package/src/web/components/common/Select.tsx +0 -97
- package/src/web/components/common/index.ts +0 -20
- package/src/web/components/connections/ConnectionsPage.tsx +0 -54
- package/src/web/components/connections/IntegrationsTab.tsx +0 -170
- package/src/web/components/connections/OverviewTab.tsx +0 -137
- package/src/web/components/connections/TriggersTab.tsx +0 -1346
- package/src/web/components/dashboard/Dashboard.tsx +0 -572
- package/src/web/components/dashboard/index.ts +0 -1
- package/src/web/components/index.ts +0 -21
- package/src/web/components/layout/ErrorBanner.tsx +0 -18
- package/src/web/components/layout/Header.tsx +0 -332
- package/src/web/components/layout/Sidebar.tsx +0 -231
- package/src/web/components/layout/index.ts +0 -3
- package/src/web/components/mcp/IntegrationsPanel.tsx +0 -857
- package/src/web/components/mcp/McpPage.tsx +0 -2515
- package/src/web/components/mcp/index.ts +0 -1
- package/src/web/components/meta-agent/MetaAgent.tsx +0 -245
- package/src/web/components/onboarding/OnboardingWizard.tsx +0 -404
- package/src/web/components/onboarding/index.ts +0 -1
- package/src/web/components/settings/SettingsPage.tsx +0 -2776
- package/src/web/components/settings/index.ts +0 -1
- package/src/web/components/skills/SkillsPage.tsx +0 -1200
- package/src/web/components/tasks/TasksPage.tsx +0 -1116
- package/src/web/components/tasks/index.ts +0 -1
- package/src/web/components/telemetry/TelemetryPage.tsx +0 -1129
- package/src/web/components/tests/TestsPage.tsx +0 -594
- package/src/web/components/threads/ThreadsPage.tsx +0 -315
- package/src/web/context/AuthContext.tsx +0 -242
- package/src/web/context/ProjectContext.tsx +0 -214
- package/src/web/context/TelemetryContext.tsx +0 -299
- package/src/web/context/ThemeContext.tsx +0 -90
- package/src/web/context/UIModeContext.tsx +0 -49
- package/src/web/context/index.ts +0 -12
- package/src/web/hooks/index.ts +0 -3
- package/src/web/hooks/useAgents.ts +0 -115
- package/src/web/hooks/useOnboarding.ts +0 -20
- package/src/web/hooks/useProviders.ts +0 -75
- package/src/web/icon.png +0 -0
- package/src/web/index.html +0 -16
- package/src/web/styles.css +0 -118
- package/src/web/themes.ts +0 -162
- package/src/web/types.ts +0 -298
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
interface ModalProps {
|
|
4
|
-
children: React.ReactNode;
|
|
5
|
-
onClose?: () => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function Modal({ children, onClose }: ModalProps) {
|
|
9
|
-
return (
|
|
10
|
-
<div className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4">
|
|
11
|
-
<div className="bg-[var(--color-surface)] card p-6 w-full max-w-xl lg:max-w-2xl max-h-[90vh] overflow-y-auto">
|
|
12
|
-
{children}
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Confirmation Modal - replaces browser confirm()
|
|
19
|
-
interface ConfirmModalProps {
|
|
20
|
-
title?: string;
|
|
21
|
-
message: string;
|
|
22
|
-
confirmText?: string;
|
|
23
|
-
cancelText?: string;
|
|
24
|
-
confirmVariant?: "danger" | "primary";
|
|
25
|
-
onConfirm: () => void;
|
|
26
|
-
onCancel: () => void;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function ConfirmModal({
|
|
30
|
-
title,
|
|
31
|
-
message,
|
|
32
|
-
confirmText = "Confirm",
|
|
33
|
-
cancelText = "Cancel",
|
|
34
|
-
confirmVariant = "danger",
|
|
35
|
-
onConfirm,
|
|
36
|
-
onCancel,
|
|
37
|
-
}: ConfirmModalProps) {
|
|
38
|
-
return (
|
|
39
|
-
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
|
40
|
-
<div className="bg-[var(--color-surface)] card p-6 w-full max-w-sm">
|
|
41
|
-
{title && <h3 className="font-medium mb-2">{title}</h3>}
|
|
42
|
-
<p className="text-sm text-[var(--color-text)] mb-4">{message}</p>
|
|
43
|
-
<div className="flex gap-2">
|
|
44
|
-
<button
|
|
45
|
-
onClick={onCancel}
|
|
46
|
-
className="flex-1 text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] btn px-4 py-2 transition"
|
|
47
|
-
>
|
|
48
|
-
{cancelText}
|
|
49
|
-
</button>
|
|
50
|
-
<button
|
|
51
|
-
onClick={onConfirm}
|
|
52
|
-
className={`flex-1 text-sm text-white px-4 py-2 btn transition ${
|
|
53
|
-
confirmVariant === "danger"
|
|
54
|
-
? "bg-red-500 hover:bg-red-600"
|
|
55
|
-
: "bg-[var(--color-accent)] hover:bg-[var(--color-accent-hover)]"
|
|
56
|
-
}`}
|
|
57
|
-
>
|
|
58
|
-
{confirmText}
|
|
59
|
-
</button>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Alert Modal - replaces browser alert()
|
|
67
|
-
interface AlertModalProps {
|
|
68
|
-
title?: string;
|
|
69
|
-
message: string;
|
|
70
|
-
buttonText?: string;
|
|
71
|
-
variant?: "error" | "success" | "info";
|
|
72
|
-
onClose: () => void;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function AlertModal({
|
|
76
|
-
title,
|
|
77
|
-
message,
|
|
78
|
-
buttonText = "OK",
|
|
79
|
-
variant = "info",
|
|
80
|
-
onClose,
|
|
81
|
-
}: AlertModalProps) {
|
|
82
|
-
const iconColors = {
|
|
83
|
-
error: "bg-red-500/20 text-red-400",
|
|
84
|
-
success: "bg-green-500/20 text-green-400",
|
|
85
|
-
info: "bg-blue-500/20 text-blue-400",
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const icons = {
|
|
89
|
-
error: "✕",
|
|
90
|
-
success: "✓",
|
|
91
|
-
info: "ℹ",
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
|
96
|
-
<div className="bg-[var(--color-surface)] card p-6 w-full max-w-sm text-center">
|
|
97
|
-
<div
|
|
98
|
-
className={`w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-3 ${iconColors[variant]}`}
|
|
99
|
-
>
|
|
100
|
-
<span className="text-xl">{icons[variant]}</span>
|
|
101
|
-
</div>
|
|
102
|
-
{title && <h3 className="font-medium mb-2">{title}</h3>}
|
|
103
|
-
<p className="text-sm text-[var(--color-text)] mb-4">{message}</p>
|
|
104
|
-
<button
|
|
105
|
-
onClick={onClose}
|
|
106
|
-
className="w-full text-sm bg-[var(--color-surface-raised)] hover:bg-[var(--color-surface-raised)] border border-[var(--color-border-light)] px-4 py-2 btn transition"
|
|
107
|
-
>
|
|
108
|
-
{buttonText}
|
|
109
|
-
</button>
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Hook for using confirmation dialogs
|
|
116
|
-
import { useState, useCallback } from "react";
|
|
117
|
-
|
|
118
|
-
interface UseConfirmOptions {
|
|
119
|
-
title?: string;
|
|
120
|
-
confirmText?: string;
|
|
121
|
-
cancelText?: string;
|
|
122
|
-
confirmVariant?: "danger" | "primary";
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function useConfirm() {
|
|
126
|
-
const [state, setState] = useState<{
|
|
127
|
-
message: string;
|
|
128
|
-
options: UseConfirmOptions;
|
|
129
|
-
resolve: (value: boolean) => void;
|
|
130
|
-
} | null>(null);
|
|
131
|
-
|
|
132
|
-
const confirm = useCallback((message: string, options: UseConfirmOptions = {}) => {
|
|
133
|
-
return new Promise<boolean>((resolve) => {
|
|
134
|
-
setState({ message, options, resolve });
|
|
135
|
-
});
|
|
136
|
-
}, []);
|
|
137
|
-
|
|
138
|
-
const handleConfirm = useCallback(() => {
|
|
139
|
-
state?.resolve(true);
|
|
140
|
-
setState(null);
|
|
141
|
-
}, [state]);
|
|
142
|
-
|
|
143
|
-
const handleCancel = useCallback(() => {
|
|
144
|
-
state?.resolve(false);
|
|
145
|
-
setState(null);
|
|
146
|
-
}, [state]);
|
|
147
|
-
|
|
148
|
-
const ConfirmDialog = state ? (
|
|
149
|
-
<ConfirmModal
|
|
150
|
-
title={state.options.title}
|
|
151
|
-
message={state.message}
|
|
152
|
-
confirmText={state.options.confirmText}
|
|
153
|
-
cancelText={state.options.cancelText}
|
|
154
|
-
confirmVariant={state.options.confirmVariant}
|
|
155
|
-
onConfirm={handleConfirm}
|
|
156
|
-
onCancel={handleCancel}
|
|
157
|
-
/>
|
|
158
|
-
) : null;
|
|
159
|
-
|
|
160
|
-
return { confirm, ConfirmDialog };
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Hook for using alert dialogs
|
|
164
|
-
interface UseAlertOptions {
|
|
165
|
-
title?: string;
|
|
166
|
-
buttonText?: string;
|
|
167
|
-
variant?: "error" | "success" | "info";
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export function useAlert() {
|
|
171
|
-
const [state, setState] = useState<{
|
|
172
|
-
message: string;
|
|
173
|
-
options: UseAlertOptions;
|
|
174
|
-
resolve: () => void;
|
|
175
|
-
} | null>(null);
|
|
176
|
-
|
|
177
|
-
const alert = useCallback((message: string, options: UseAlertOptions = {}) => {
|
|
178
|
-
return new Promise<void>((resolve) => {
|
|
179
|
-
setState({ message, options, resolve });
|
|
180
|
-
});
|
|
181
|
-
}, []);
|
|
182
|
-
|
|
183
|
-
const handleClose = useCallback(() => {
|
|
184
|
-
state?.resolve();
|
|
185
|
-
setState(null);
|
|
186
|
-
}, [state]);
|
|
187
|
-
|
|
188
|
-
const AlertDialog = state ? (
|
|
189
|
-
<AlertModal
|
|
190
|
-
title={state.options.title}
|
|
191
|
-
message={state.message}
|
|
192
|
-
buttonText={state.options.buttonText}
|
|
193
|
-
variant={state.options.variant}
|
|
194
|
-
onClose={handleClose}
|
|
195
|
-
/>
|
|
196
|
-
) : null;
|
|
197
|
-
|
|
198
|
-
return { alert, AlertDialog };
|
|
199
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect } from "react";
|
|
2
|
-
|
|
3
|
-
interface SelectOption {
|
|
4
|
-
value: string;
|
|
5
|
-
label: string;
|
|
6
|
-
recommended?: boolean;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface SelectProps {
|
|
10
|
-
value: string;
|
|
11
|
-
options: SelectOption[];
|
|
12
|
-
onChange: (value: string) => void;
|
|
13
|
-
placeholder?: string;
|
|
14
|
-
compact?: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function Select({ value, options, onChange, placeholder = "Select...", compact }: SelectProps) {
|
|
18
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
19
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
20
|
-
|
|
21
|
-
const selectedOption = options.find(o => o.value === value);
|
|
22
|
-
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
function handleClickOutside(event: MouseEvent) {
|
|
25
|
-
if (ref.current && !ref.current.contains(event.target as Node)) {
|
|
26
|
-
setIsOpen(false);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
30
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
31
|
-
}, []);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<div ref={ref} className="relative">
|
|
35
|
-
<button
|
|
36
|
-
type="button"
|
|
37
|
-
onClick={() => setIsOpen(!isOpen)}
|
|
38
|
-
className={`w-full bg-[var(--color-bg)] border border-[var(--color-border-light)] btn ${compact ? "px-2.5 py-1.5 text-sm" : "px-3 py-2"} text-left flex items-center justify-between focus:outline-none focus:border-[var(--color-accent)] text-[var(--color-text)] hover:border-[var(--color-border-light)] transition`}
|
|
39
|
-
>
|
|
40
|
-
<span className={selectedOption ? "text-[var(--color-text)]" : "text-[var(--color-text-muted)]"}>
|
|
41
|
-
{selectedOption ? (
|
|
42
|
-
<>
|
|
43
|
-
{selectedOption.label}
|
|
44
|
-
{selectedOption.recommended && (
|
|
45
|
-
<span className="text-[var(--color-accent)] text-xs ml-2">(Recommended)</span>
|
|
46
|
-
)}
|
|
47
|
-
</>
|
|
48
|
-
) : placeholder}
|
|
49
|
-
</span>
|
|
50
|
-
<ChevronIcon isOpen={isOpen} />
|
|
51
|
-
</button>
|
|
52
|
-
|
|
53
|
-
{isOpen && (
|
|
54
|
-
<div className="absolute z-50 w-full min-w-max mt-1 bg-[var(--color-surface)] border border-[var(--color-border-light)] shadow-lg max-h-60 overflow-y-auto scrollbar-hide" style={{ borderRadius: "var(--radius-button)" }}>
|
|
55
|
-
{options.map((option) => (
|
|
56
|
-
<button
|
|
57
|
-
key={option.value}
|
|
58
|
-
type="button"
|
|
59
|
-
onClick={() => {
|
|
60
|
-
onChange(option.value);
|
|
61
|
-
setIsOpen(false);
|
|
62
|
-
}}
|
|
63
|
-
className={`w-full ${compact ? "px-2.5 py-1.5 text-sm" : "px-3 py-2"} text-left flex items-center justify-between hover:bg-[var(--color-surface-raised)] transition ${
|
|
64
|
-
option.value === value ? "bg-[var(--color-surface-raised)] text-[var(--color-accent)]" : "text-[var(--color-text)]"
|
|
65
|
-
}`}
|
|
66
|
-
>
|
|
67
|
-
<span>
|
|
68
|
-
{option.label}
|
|
69
|
-
{option.recommended && (
|
|
70
|
-
<span className="text-[var(--color-accent)] text-xs ml-2">(Recommended)</span>
|
|
71
|
-
)}
|
|
72
|
-
</span>
|
|
73
|
-
{option.value === value && (
|
|
74
|
-
<svg className="w-4 h-4 text-[var(--color-accent)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
75
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
76
|
-
</svg>
|
|
77
|
-
)}
|
|
78
|
-
</button>
|
|
79
|
-
))}
|
|
80
|
-
</div>
|
|
81
|
-
)}
|
|
82
|
-
</div>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function ChevronIcon({ isOpen }: { isOpen: boolean }) {
|
|
87
|
-
return (
|
|
88
|
-
<svg
|
|
89
|
-
className={`w-4 h-4 text-[var(--color-text-muted)] transition-transform ${isOpen ? "rotate-180" : ""}`}
|
|
90
|
-
fill="none"
|
|
91
|
-
stroke="currentColor"
|
|
92
|
-
viewBox="0 0 24 24"
|
|
93
|
-
>
|
|
94
|
-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
95
|
-
</svg>
|
|
96
|
-
);
|
|
97
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export { LoadingSpinner } from "./LoadingSpinner";
|
|
2
|
-
export { Modal } from "./Modal";
|
|
3
|
-
export { Select } from "./Select";
|
|
4
|
-
export {
|
|
5
|
-
CheckIcon,
|
|
6
|
-
CloseIcon,
|
|
7
|
-
DashboardIcon,
|
|
8
|
-
AgentsIcon,
|
|
9
|
-
SettingsIcon,
|
|
10
|
-
MemoryIcon,
|
|
11
|
-
TasksIcon,
|
|
12
|
-
VisionIcon,
|
|
13
|
-
OperatorIcon,
|
|
14
|
-
McpIcon,
|
|
15
|
-
SkillsIcon,
|
|
16
|
-
RealtimeIcon,
|
|
17
|
-
TelemetryIcon,
|
|
18
|
-
ActivityIcon,
|
|
19
|
-
ConnectionsIcon,
|
|
20
|
-
} from "./Icons";
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { OverviewTab } from "./OverviewTab";
|
|
3
|
-
import { TriggersTab } from "./TriggersTab";
|
|
4
|
-
import { IntegrationsTab } from "./IntegrationsTab";
|
|
5
|
-
|
|
6
|
-
type Tab = "overview" | "triggers" | "integrations";
|
|
7
|
-
|
|
8
|
-
export function ConnectionsPage() {
|
|
9
|
-
const [activeTab, setActiveTab] = useState<Tab>("overview");
|
|
10
|
-
|
|
11
|
-
const tabs: { id: Tab; label: string }[] = [
|
|
12
|
-
{ id: "overview", label: "Overview" },
|
|
13
|
-
{ id: "triggers", label: "Triggers" },
|
|
14
|
-
{ id: "integrations", label: "Integrations" },
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<div className="flex-1 overflow-auto p-6">
|
|
19
|
-
<div className="max-w-6xl">
|
|
20
|
-
{/* Header */}
|
|
21
|
-
<div className="flex items-center justify-between mb-6">
|
|
22
|
-
<div>
|
|
23
|
-
<h1 className="text-2xl font-semibold mb-1">Connections</h1>
|
|
24
|
-
<p className="text-[var(--color-text-muted)]">
|
|
25
|
-
Manage external app connections, triggers, and webhooks.
|
|
26
|
-
</p>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
{/* Tabs */}
|
|
31
|
-
<div className="flex gap-1 mb-6 bg-[var(--color-surface)] card p-1 w-fit">
|
|
32
|
-
{tabs.map(tab => (
|
|
33
|
-
<button
|
|
34
|
-
key={tab.id}
|
|
35
|
-
onClick={() => setActiveTab(tab.id)}
|
|
36
|
-
className={`px-4 py-2 rounded text-sm font-medium transition ${
|
|
37
|
-
activeTab === tab.id
|
|
38
|
-
? "bg-[var(--color-surface-raised)] text-white"
|
|
39
|
-
: "text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)]"
|
|
40
|
-
}`}
|
|
41
|
-
>
|
|
42
|
-
{tab.label}
|
|
43
|
-
</button>
|
|
44
|
-
))}
|
|
45
|
-
</div>
|
|
46
|
-
|
|
47
|
-
{/* Tab Content */}
|
|
48
|
-
{activeTab === "overview" && <OverviewTab />}
|
|
49
|
-
{activeTab === "triggers" && <TriggersTab />}
|
|
50
|
-
{activeTab === "integrations" && <IntegrationsTab />}
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback } from "react";
|
|
2
|
-
import { useAuth, useProjects } from "../../context";
|
|
3
|
-
import { IntegrationsPanel } from "../mcp/IntegrationsPanel";
|
|
4
|
-
|
|
5
|
-
interface TriggerType {
|
|
6
|
-
slug: string;
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
type: "webhook" | "poll";
|
|
10
|
-
toolkit_slug: string;
|
|
11
|
-
toolkit_name: string;
|
|
12
|
-
logo: string | null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface ProviderInfo {
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
connected: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function IntegrationsTab() {
|
|
22
|
-
const { authFetch } = useAuth();
|
|
23
|
-
const { currentProjectId } = useProjects();
|
|
24
|
-
|
|
25
|
-
const projectId = currentProjectId && currentProjectId !== "unassigned" ? currentProjectId : null;
|
|
26
|
-
const projectParam = projectId ? `?project_id=${projectId}` : "";
|
|
27
|
-
|
|
28
|
-
// Provider selection — only show configured providers
|
|
29
|
-
const [providers, setProviders] = useState<ProviderInfo[]>([]);
|
|
30
|
-
const [selectedProvider, setSelectedProvider] = useState("");
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
authFetch(`/api/triggers/providers${projectParam}`)
|
|
34
|
-
.then(r => r.json())
|
|
35
|
-
.then(data => {
|
|
36
|
-
const connected = (data.providers || []).filter((p: ProviderInfo) => p.connected);
|
|
37
|
-
setProviders(connected);
|
|
38
|
-
if (connected.length > 0 && !connected.find((p: ProviderInfo) => p.id === selectedProvider)) {
|
|
39
|
-
setSelectedProvider(connected[0].id);
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
.catch(() => {});
|
|
43
|
-
}, [authFetch]);
|
|
44
|
-
|
|
45
|
-
// Trigger type browsing
|
|
46
|
-
const [browsingToolkit, setBrowsingToolkit] = useState<string | null>(null);
|
|
47
|
-
const [triggerTypes, setTriggerTypes] = useState<TriggerType[]>([]);
|
|
48
|
-
const [typesLoading, setTypesLoading] = useState(false);
|
|
49
|
-
|
|
50
|
-
const handleBrowseTriggers = useCallback(async (toolkitSlug: string) => {
|
|
51
|
-
setBrowsingToolkit(toolkitSlug);
|
|
52
|
-
setTypesLoading(true);
|
|
53
|
-
try {
|
|
54
|
-
let url = `/api/triggers/types?provider=${selectedProvider}&toolkit_slugs=${toolkitSlug}`;
|
|
55
|
-
if (projectId) url += `&project_id=${projectId}`;
|
|
56
|
-
const res = await authFetch(url);
|
|
57
|
-
if (res.ok) {
|
|
58
|
-
const data = await res.json();
|
|
59
|
-
setTriggerTypes(data.types || []);
|
|
60
|
-
}
|
|
61
|
-
} catch (e) {
|
|
62
|
-
console.error("Failed to fetch trigger types:", e);
|
|
63
|
-
}
|
|
64
|
-
setTypesLoading(false);
|
|
65
|
-
}, [authFetch, projectId, selectedProvider]);
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<div>
|
|
69
|
-
<p className="text-sm text-[var(--color-text-muted)] mb-4">
|
|
70
|
-
Connect external apps via OAuth or API Key. Connected apps can be used for triggers and MCP integrations.
|
|
71
|
-
</p>
|
|
72
|
-
|
|
73
|
-
{/* Provider Selector — only show if multiple configured */}
|
|
74
|
-
{providers.length > 1 && (
|
|
75
|
-
<div className="flex items-center gap-2 mb-4">
|
|
76
|
-
<span className="text-xs text-[var(--color-text-muted)]">Provider:</span>
|
|
77
|
-
<div className="flex gap-1 bg-[var(--color-surface)] card p-0.5">
|
|
78
|
-
{providers.map(p => (
|
|
79
|
-
<button
|
|
80
|
-
key={p.id}
|
|
81
|
-
onClick={() => setSelectedProvider(p.id)}
|
|
82
|
-
className={`px-3 py-1 rounded text-xs font-medium transition ${
|
|
83
|
-
selectedProvider === p.id
|
|
84
|
-
? "bg-[var(--color-surface-raised)] text-white"
|
|
85
|
-
: "text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)]"
|
|
86
|
-
}`}
|
|
87
|
-
>
|
|
88
|
-
{p.name}
|
|
89
|
-
</button>
|
|
90
|
-
))}
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
)}
|
|
94
|
-
|
|
95
|
-
{providers.length === 0 ? (
|
|
96
|
-
<div className="bg-[var(--color-surface)] card p-8 text-center">
|
|
97
|
-
<p className="text-[var(--color-text-muted)]">No integration providers configured.</p>
|
|
98
|
-
<p className="text-sm text-[var(--color-text-faint)] mt-1">Add API keys for Composio or AgentDojo in Settings.</p>
|
|
99
|
-
</div>
|
|
100
|
-
) : (
|
|
101
|
-
<IntegrationsPanel
|
|
102
|
-
providerId={selectedProvider}
|
|
103
|
-
projectId={projectId}
|
|
104
|
-
hideMcpConfig
|
|
105
|
-
onBrowseTriggers={handleBrowseTriggers}
|
|
106
|
-
/>
|
|
107
|
-
)}
|
|
108
|
-
|
|
109
|
-
{/* Trigger Types Panel */}
|
|
110
|
-
{browsingToolkit && (
|
|
111
|
-
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
|
|
112
|
-
<div className="bg-[var(--color-surface)] border border-[var(--color-border-light)] rounded-lg w-full max-w-2xl mx-4 max-h-[80vh] flex flex-col">
|
|
113
|
-
<div className="p-4 border-b border-[var(--color-border)] flex items-center justify-between">
|
|
114
|
-
<div>
|
|
115
|
-
<h3 className="font-medium">Trigger Types</h3>
|
|
116
|
-
<p className="text-xs text-[var(--color-text-muted)]">{browsingToolkit}</p>
|
|
117
|
-
</div>
|
|
118
|
-
<button
|
|
119
|
-
onClick={() => { setBrowsingToolkit(null); setTriggerTypes([]); }}
|
|
120
|
-
className="text-[var(--color-text-muted)] hover:text-white transition text-lg px-2"
|
|
121
|
-
>
|
|
122
|
-
x
|
|
123
|
-
</button>
|
|
124
|
-
</div>
|
|
125
|
-
|
|
126
|
-
<div className="flex-1 overflow-auto p-4">
|
|
127
|
-
{typesLoading ? (
|
|
128
|
-
<div className="text-center py-8 text-[var(--color-text-muted)]">Loading trigger types...</div>
|
|
129
|
-
) : triggerTypes.length === 0 ? (
|
|
130
|
-
<div className="text-center py-8 text-[var(--color-text-muted)]">
|
|
131
|
-
No trigger types available for this app.
|
|
132
|
-
</div>
|
|
133
|
-
) : (
|
|
134
|
-
<div className="space-y-2">
|
|
135
|
-
{triggerTypes.map(tt => (
|
|
136
|
-
<div key={tt.slug} className="bg-[var(--color-bg)] card p-3">
|
|
137
|
-
<div className="flex items-start gap-3">
|
|
138
|
-
{tt.logo ? (
|
|
139
|
-
<img src={tt.logo} alt={tt.toolkit_name} className="w-6 h-6 rounded object-contain flex-shrink-0 mt-0.5" />
|
|
140
|
-
) : (
|
|
141
|
-
<div className="w-6 h-6 rounded bg-[var(--color-surface-raised)] flex items-center justify-center text-[10px] flex-shrink-0 mt-0.5">
|
|
142
|
-
{tt.toolkit_name?.[0]?.toUpperCase() || "?"}
|
|
143
|
-
</div>
|
|
144
|
-
)}
|
|
145
|
-
<div className="flex-1 min-w-0">
|
|
146
|
-
<div className="text-sm font-medium">{tt.name}</div>
|
|
147
|
-
<div className="text-xs text-[var(--color-text-muted)] mt-0.5">{tt.description}</div>
|
|
148
|
-
<div className="flex items-center gap-2 mt-1.5">
|
|
149
|
-
<span className="text-[10px] bg-[var(--color-surface-raised)] text-[var(--color-text-faint)] px-1.5 py-0.5 rounded font-mono">
|
|
150
|
-
{tt.slug}
|
|
151
|
-
</span>
|
|
152
|
-
<span className={`text-[10px] px-1.5 py-0.5 rounded ${
|
|
153
|
-
tt.type === "webhook" ? "bg-blue-500/10 text-blue-400" : "bg-yellow-500/10 text-yellow-400"
|
|
154
|
-
}`}>
|
|
155
|
-
{tt.type}
|
|
156
|
-
</span>
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
))}
|
|
162
|
-
</div>
|
|
163
|
-
)}
|
|
164
|
-
</div>
|
|
165
|
-
</div>
|
|
166
|
-
</div>
|
|
167
|
-
)}
|
|
168
|
-
</div>
|
|
169
|
-
);
|
|
170
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from "react";
|
|
2
|
-
import { useAuth, useProjects } from "../../context";
|
|
3
|
-
|
|
4
|
-
interface Subscription {
|
|
5
|
-
id: string;
|
|
6
|
-
trigger_slug: string;
|
|
7
|
-
trigger_instance_id: string | null;
|
|
8
|
-
agent_id: string;
|
|
9
|
-
enabled: boolean;
|
|
10
|
-
project_id: string | null;
|
|
11
|
-
created_at: string;
|
|
12
|
-
updated_at: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface Agent {
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
status: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function OverviewTab() {
|
|
22
|
-
const { authFetch } = useAuth();
|
|
23
|
-
const { currentProjectId } = useProjects();
|
|
24
|
-
|
|
25
|
-
const [subscriptions, setSubscriptions] = useState<Subscription[]>([]);
|
|
26
|
-
const [agents, setAgents] = useState<Agent[]>([]);
|
|
27
|
-
const [loading, setLoading] = useState(true);
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
const fetchAll = async () => {
|
|
31
|
-
setLoading(true);
|
|
32
|
-
const projectParam = currentProjectId && currentProjectId !== "unassigned" ? `?project_id=${currentProjectId}` : "";
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const [subsRes, agentsRes] = await Promise.all([
|
|
36
|
-
authFetch(`/api/subscriptions${projectParam}`).catch(() => null),
|
|
37
|
-
authFetch(`/api/agents`).catch(() => null),
|
|
38
|
-
]);
|
|
39
|
-
|
|
40
|
-
if (subsRes?.ok) {
|
|
41
|
-
const data = await subsRes.json();
|
|
42
|
-
setSubscriptions(data.subscriptions || []);
|
|
43
|
-
}
|
|
44
|
-
if (agentsRes?.ok) {
|
|
45
|
-
const data = await agentsRes.json();
|
|
46
|
-
setAgents(data.agents || []);
|
|
47
|
-
}
|
|
48
|
-
} catch (e) {
|
|
49
|
-
console.error("Failed to fetch overview data:", e);
|
|
50
|
-
}
|
|
51
|
-
setLoading(false);
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
fetchAll();
|
|
55
|
-
}, [authFetch, currentProjectId]);
|
|
56
|
-
|
|
57
|
-
if (loading) {
|
|
58
|
-
return <div className="text-center py-12 text-[var(--color-text-muted)]">Loading...</div>;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const enabledSubs = subscriptions.filter(s => s.enabled);
|
|
62
|
-
const disabledSubs = subscriptions.filter(s => !s.enabled);
|
|
63
|
-
const agentMap = new Map(agents.map(a => [a.id, a]));
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<div className="space-y-6">
|
|
67
|
-
{/* Stats */}
|
|
68
|
-
<div className="grid grid-cols-3 gap-4">
|
|
69
|
-
<StatCard label="Active" value={enabledSubs.length} />
|
|
70
|
-
<StatCard label="Disabled" value={disabledSubs.length} />
|
|
71
|
-
<StatCard label="Total" value={subscriptions.length} />
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
{/* Subscriptions */}
|
|
75
|
-
<section>
|
|
76
|
-
<h3 className="text-sm font-medium text-[var(--color-text-secondary)] mb-3">Subscriptions ({subscriptions.length})</h3>
|
|
77
|
-
{subscriptions.length === 0 ? (
|
|
78
|
-
<div className="bg-[var(--color-surface)] card p-6 text-center text-[var(--color-text-muted)] text-sm">
|
|
79
|
-
No subscriptions yet. Go to the Triggers tab to create one.
|
|
80
|
-
</div>
|
|
81
|
-
) : (
|
|
82
|
-
<div className="space-y-2">
|
|
83
|
-
{subscriptions.map(sub => {
|
|
84
|
-
const agent = agentMap.get(sub.agent_id);
|
|
85
|
-
return (
|
|
86
|
-
<div key={sub.id} className="bg-[var(--color-surface)] card p-3 flex items-center gap-3">
|
|
87
|
-
<div className={`w-2 h-2 rounded-full flex-shrink-0 ${sub.enabled ? "bg-green-400" : "bg-[var(--color-text-faint)]"}`} />
|
|
88
|
-
<div className="flex-1 min-w-0">
|
|
89
|
-
<div className="text-sm font-medium truncate">
|
|
90
|
-
{sub.trigger_slug.replace(/_/g, " ").replace(/-/g, " ")}
|
|
91
|
-
</div>
|
|
92
|
-
<div className="text-xs text-[var(--color-text-muted)]">
|
|
93
|
-
{sub.trigger_instance_id
|
|
94
|
-
? `ID: ${sub.trigger_instance_id.slice(0, 12)}...`
|
|
95
|
-
: "All instances"
|
|
96
|
-
}
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
<div className="text-xs text-[var(--color-text-secondary)] flex-shrink-0">
|
|
100
|
-
<span className="text-[var(--color-text-faint)]">→</span>{" "}
|
|
101
|
-
<span className="text-[var(--color-accent)]">{agent?.name || "Unknown Agent"}</span>
|
|
102
|
-
</div>
|
|
103
|
-
<span className={`text-xs px-2 py-0.5 rounded flex-shrink-0 ${
|
|
104
|
-
sub.enabled
|
|
105
|
-
? "bg-green-500/10 text-green-400"
|
|
106
|
-
: "bg-[var(--color-surface-raised)] text-[var(--color-text-faint)]"
|
|
107
|
-
}`}>
|
|
108
|
-
{sub.enabled ? "active" : "disabled"}
|
|
109
|
-
</span>
|
|
110
|
-
</div>
|
|
111
|
-
);
|
|
112
|
-
})}
|
|
113
|
-
</div>
|
|
114
|
-
)}
|
|
115
|
-
</section>
|
|
116
|
-
</div>
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function StatCard({
|
|
121
|
-
label,
|
|
122
|
-
value,
|
|
123
|
-
valueColor,
|
|
124
|
-
}: {
|
|
125
|
-
label: string;
|
|
126
|
-
value: string | number;
|
|
127
|
-
valueColor?: string;
|
|
128
|
-
}) {
|
|
129
|
-
return (
|
|
130
|
-
<div className="bg-[var(--color-surface)] card p-4">
|
|
131
|
-
<div className="text-xs text-[var(--color-text-muted)] mb-1">{label}</div>
|
|
132
|
-
<div className={`text-2xl font-bold ${valueColor || "text-[var(--color-text)]"}`}>
|
|
133
|
-
{value}
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
);
|
|
137
|
-
}
|