apteva 0.4.57 → 0.7.1

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.
Files changed (142) hide show
  1. package/README.md +216 -54
  2. package/cli.js +35 -0
  3. package/install.js +92 -0
  4. package/package.json +15 -76
  5. package/LICENSE +0 -63
  6. package/bin/apteva.js +0 -196
  7. package/dist/ActivityPage.kxzzb4yc.js +0 -3
  8. package/dist/ApiDocsPage.zq998hbm.js +0 -4
  9. package/dist/App.55rea8mn.js +0 -61
  10. package/dist/App.5ywb23z4.js +0 -53
  11. package/dist/App.6thds120.js +0 -4
  12. package/dist/App.9tctxzqm.js +0 -8
  13. package/dist/App.a8r8ttaz.js +0 -4
  14. package/dist/App.agsv5bje.js +0 -4
  15. package/dist/App.cepapqmx.js +0 -4
  16. package/dist/App.dp041gb3.js +0 -221
  17. package/dist/App.fds72zb5.js +0 -4
  18. package/dist/App.fg9qj2dq.js +0 -4
  19. package/dist/App.ndfejbm9.js +0 -4
  20. package/dist/App.nxmfmq1h.js +0 -13
  21. package/dist/App.qdfyt8ba.js +0 -4
  22. package/dist/App.x2d0ygt6.js +0 -4
  23. package/dist/App.yt9p4nr3.js +0 -20
  24. package/dist/App.zn4mw16t.js +0 -1
  25. package/dist/ConnectionsPage.8r96ryw7.js +0 -3
  26. package/dist/McpPage.3cwh0gnd.js +0 -3
  27. package/dist/SettingsPage.ykgdh5ev.js +0 -3
  28. package/dist/SkillsPage.4np1s65b.js +0 -3
  29. package/dist/TasksPage.4g08t7p6.js +0 -3
  30. package/dist/TelemetryPage.72w9pwcp.js +0 -3
  31. package/dist/TestsPage.z4fk3r7r.js +0 -3
  32. package/dist/ThreadsPage.63tcajeh.js +0 -3
  33. package/dist/apteva-kit.css +0 -1
  34. package/dist/icon.png +0 -0
  35. package/dist/index.html +0 -16
  36. package/dist/styles.css +0 -1
  37. package/scripts/postinstall.mjs +0 -102
  38. package/src/auth/index.ts +0 -394
  39. package/src/auth/middleware.ts +0 -213
  40. package/src/binary.ts +0 -536
  41. package/src/channels/index.ts +0 -40
  42. package/src/channels/telegram.ts +0 -311
  43. package/src/crypto.ts +0 -301
  44. package/src/db-tests.ts +0 -174
  45. package/src/db.ts +0 -3133
  46. package/src/integrations/agentdojo.ts +0 -559
  47. package/src/integrations/composio.ts +0 -437
  48. package/src/integrations/index.ts +0 -87
  49. package/src/integrations/skillsmp.ts +0 -318
  50. package/src/mcp-client.ts +0 -605
  51. package/src/mcp-handler.ts +0 -394
  52. package/src/mcp-platform.ts +0 -2403
  53. package/src/openapi.ts +0 -2410
  54. package/src/providers.ts +0 -597
  55. package/src/routes/api/agent-utils.ts +0 -890
  56. package/src/routes/api/agents.ts +0 -916
  57. package/src/routes/api/api-keys.ts +0 -95
  58. package/src/routes/api/channels.ts +0 -182
  59. package/src/routes/api/helpers.ts +0 -12
  60. package/src/routes/api/integrations.ts +0 -639
  61. package/src/routes/api/mcp.ts +0 -574
  62. package/src/routes/api/meta-agent.ts +0 -195
  63. package/src/routes/api/projects.ts +0 -112
  64. package/src/routes/api/providers.ts +0 -424
  65. package/src/routes/api/skills.ts +0 -537
  66. package/src/routes/api/system.ts +0 -333
  67. package/src/routes/api/telemetry.ts +0 -203
  68. package/src/routes/api/tests.ts +0 -148
  69. package/src/routes/api/triggers.ts +0 -518
  70. package/src/routes/api/users.ts +0 -148
  71. package/src/routes/api/webhooks.ts +0 -171
  72. package/src/routes/api.ts +0 -53
  73. package/src/routes/auth.ts +0 -251
  74. package/src/routes/share.ts +0 -86
  75. package/src/routes/static.ts +0 -131
  76. package/src/server.ts +0 -642
  77. package/src/test-runner.ts +0 -598
  78. package/src/triggers/agentdojo.ts +0 -253
  79. package/src/triggers/composio.ts +0 -264
  80. package/src/triggers/index.ts +0 -71
  81. package/src/tui/AgentList.tsx +0 -145
  82. package/src/tui/App.tsx +0 -102
  83. package/src/tui/Login.tsx +0 -104
  84. package/src/tui/api.ts +0 -72
  85. package/src/tui/index.tsx +0 -7
  86. package/src/web/App.tsx +0 -455
  87. package/src/web/components/activity/ActivityPage.tsx +0 -314
  88. package/src/web/components/activity/index.ts +0 -1
  89. package/src/web/components/agents/AgentCard.tsx +0 -189
  90. package/src/web/components/agents/AgentPanel.tsx +0 -2244
  91. package/src/web/components/agents/AgentsView.tsx +0 -180
  92. package/src/web/components/agents/CreateAgentModal.tsx +0 -475
  93. package/src/web/components/agents/index.ts +0 -4
  94. package/src/web/components/api/ApiDocsPage.tsx +0 -842
  95. package/src/web/components/auth/CreateAccountStep.tsx +0 -176
  96. package/src/web/components/auth/LoginPage.tsx +0 -91
  97. package/src/web/components/auth/index.ts +0 -2
  98. package/src/web/components/common/Icons.tsx +0 -250
  99. package/src/web/components/common/LoadingSpinner.tsx +0 -44
  100. package/src/web/components/common/Modal.tsx +0 -199
  101. package/src/web/components/common/Select.tsx +0 -97
  102. package/src/web/components/common/index.ts +0 -20
  103. package/src/web/components/connections/ConnectionsPage.tsx +0 -54
  104. package/src/web/components/connections/IntegrationsTab.tsx +0 -170
  105. package/src/web/components/connections/OverviewTab.tsx +0 -137
  106. package/src/web/components/connections/TriggersTab.tsx +0 -1346
  107. package/src/web/components/dashboard/Dashboard.tsx +0 -572
  108. package/src/web/components/dashboard/index.ts +0 -1
  109. package/src/web/components/index.ts +0 -21
  110. package/src/web/components/layout/ErrorBanner.tsx +0 -18
  111. package/src/web/components/layout/Header.tsx +0 -332
  112. package/src/web/components/layout/Sidebar.tsx +0 -231
  113. package/src/web/components/layout/index.ts +0 -3
  114. package/src/web/components/mcp/IntegrationsPanel.tsx +0 -857
  115. package/src/web/components/mcp/McpPage.tsx +0 -2515
  116. package/src/web/components/mcp/index.ts +0 -1
  117. package/src/web/components/meta-agent/MetaAgent.tsx +0 -245
  118. package/src/web/components/onboarding/OnboardingWizard.tsx +0 -404
  119. package/src/web/components/onboarding/index.ts +0 -1
  120. package/src/web/components/settings/SettingsPage.tsx +0 -2776
  121. package/src/web/components/settings/index.ts +0 -1
  122. package/src/web/components/skills/SkillsPage.tsx +0 -1200
  123. package/src/web/components/tasks/TasksPage.tsx +0 -1116
  124. package/src/web/components/tasks/index.ts +0 -1
  125. package/src/web/components/telemetry/TelemetryPage.tsx +0 -1129
  126. package/src/web/components/tests/TestsPage.tsx +0 -594
  127. package/src/web/components/threads/ThreadsPage.tsx +0 -315
  128. package/src/web/context/AuthContext.tsx +0 -242
  129. package/src/web/context/ProjectContext.tsx +0 -214
  130. package/src/web/context/TelemetryContext.tsx +0 -299
  131. package/src/web/context/ThemeContext.tsx +0 -90
  132. package/src/web/context/UIModeContext.tsx +0 -49
  133. package/src/web/context/index.ts +0 -12
  134. package/src/web/hooks/index.ts +0 -3
  135. package/src/web/hooks/useAgents.ts +0 -115
  136. package/src/web/hooks/useOnboarding.ts +0 -20
  137. package/src/web/hooks/useProviders.ts +0 -75
  138. package/src/web/icon.png +0 -0
  139. package/src/web/index.html +0 -16
  140. package/src/web/styles.css +0 -118
  141. package/src/web/themes.ts +0 -162
  142. 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)]">&rarr;</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
- }