apteva 0.2.10 → 0.3.6
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/dist/App.mvbdnw89.js +227 -0
- package/dist/index.html +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/auth/index.ts +11 -3
- package/src/auth/middleware.ts +1 -0
- package/src/binary.ts +7 -5
- package/src/crypto.ts +4 -0
- package/src/db.ts +437 -14
- package/src/integrations/skillsmp.ts +318 -0
- package/src/providers.ts +21 -0
- package/src/routes/api.ts +836 -16
- package/src/server.ts +58 -7
- package/src/web/App.tsx +24 -8
- package/src/web/components/agents/AgentCard.tsx +36 -11
- package/src/web/components/agents/AgentPanel.tsx +333 -24
- package/src/web/components/agents/AgentsView.tsx +1 -1
- package/src/web/components/agents/CreateAgentModal.tsx +169 -23
- package/src/web/components/common/Icons.tsx +8 -0
- package/src/web/components/common/index.ts +1 -0
- package/src/web/components/index.ts +1 -0
- package/src/web/components/layout/Header.tsx +4 -2
- package/src/web/components/layout/Sidebar.tsx +7 -1
- package/src/web/components/mcp/McpPage.tsx +602 -19
- package/src/web/components/meta-agent/MetaAgent.tsx +222 -0
- package/src/web/components/settings/SettingsPage.tsx +212 -150
- package/src/web/components/skills/SkillsPage.tsx +871 -0
- package/src/web/context/AuthContext.tsx +5 -0
- package/src/web/context/ProjectContext.tsx +26 -4
- package/src/web/types.ts +48 -3
- package/dist/App.44ge5b89.js +0 -218
|
@@ -3,7 +3,8 @@ import { Modal } from "../common/Modal";
|
|
|
3
3
|
import { Select } from "../common/Select";
|
|
4
4
|
import { MemoryIcon, TasksIcon, FilesIcon, VisionIcon, OperatorIcon, McpIcon, RealtimeIcon, MultiAgentIcon } from "../common/Icons";
|
|
5
5
|
import { useProjects } from "../../context";
|
|
6
|
-
import type { Provider, NewAgentForm, AgentFeatures } from "../../types";
|
|
6
|
+
import type { Provider, NewAgentForm, AgentFeatures, AgentMode, MultiAgentConfig } from "../../types";
|
|
7
|
+
import { getMultiAgentConfig } from "../../types";
|
|
7
8
|
|
|
8
9
|
interface CreateAgentModalProps {
|
|
9
10
|
form: NewAgentForm;
|
|
@@ -40,10 +41,12 @@ export function CreateAgentModal({
|
|
|
40
41
|
const { projects, currentProjectId } = useProjects();
|
|
41
42
|
const selectedProvider = providers.find(p => p.id === form.provider);
|
|
42
43
|
|
|
43
|
-
const providerOptions = configuredProviders
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const providerOptions = configuredProviders
|
|
45
|
+
.filter(p => p.type === "llm")
|
|
46
|
+
.map(p => ({
|
|
47
|
+
value: p.id,
|
|
48
|
+
label: p.name,
|
|
49
|
+
}));
|
|
47
50
|
|
|
48
51
|
const modelOptions = selectedProvider?.models.map(m => ({
|
|
49
52
|
value: m.value,
|
|
@@ -51,10 +54,7 @@ export function CreateAgentModal({
|
|
|
51
54
|
recommended: m.recommended,
|
|
52
55
|
})) || [];
|
|
53
56
|
|
|
54
|
-
const projectOptions =
|
|
55
|
-
{ value: "", label: "No Project" },
|
|
56
|
-
...projects.map(p => ({ value: p.id, label: p.name })),
|
|
57
|
-
];
|
|
57
|
+
const projectOptions = projects.map(p => ({ value: p.id, label: p.name }));
|
|
58
58
|
|
|
59
59
|
// Set default project from current selection (but not "unassigned" or "all")
|
|
60
60
|
React.useEffect(() => {
|
|
@@ -64,11 +64,56 @@ export function CreateAgentModal({
|
|
|
64
64
|
}, [currentProjectId]);
|
|
65
65
|
|
|
66
66
|
const toggleFeature = (key: keyof AgentFeatures) => {
|
|
67
|
+
if (key === "agents") {
|
|
68
|
+
// Special handling for agents feature
|
|
69
|
+
const isEnabled = typeof form.features.agents === "boolean"
|
|
70
|
+
? form.features.agents
|
|
71
|
+
: (form.features.agents as MultiAgentConfig)?.enabled ?? false;
|
|
72
|
+
if (isEnabled) {
|
|
73
|
+
// Turning off
|
|
74
|
+
onFormChange({ ...form, features: { ...form.features, agents: false } });
|
|
75
|
+
} else {
|
|
76
|
+
// Turning on with defaults - use project as group
|
|
77
|
+
onFormChange({
|
|
78
|
+
...form,
|
|
79
|
+
features: {
|
|
80
|
+
...form.features,
|
|
81
|
+
agents: { enabled: true, mode: "worker" as AgentMode, group: form.projectId || undefined },
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
onFormChange({
|
|
87
|
+
...form,
|
|
88
|
+
features: {
|
|
89
|
+
...form.features,
|
|
90
|
+
[key]: !form.features[key],
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Helper to check if agents feature is enabled
|
|
97
|
+
const isAgentsEnabled = () => {
|
|
98
|
+
const agentsVal = form.features.agents;
|
|
99
|
+
if (typeof agentsVal === "boolean") return agentsVal;
|
|
100
|
+
return (agentsVal as MultiAgentConfig)?.enabled ?? false;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// Get current agent mode
|
|
104
|
+
const getAgentMode = (): AgentMode => {
|
|
105
|
+
const config = getMultiAgentConfig(form.features, form.projectId);
|
|
106
|
+
return config.mode || "worker";
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Set multi-agent mode
|
|
110
|
+
const setAgentMode = (mode: AgentMode) => {
|
|
111
|
+
const currentConfig = getMultiAgentConfig(form.features, form.projectId);
|
|
67
112
|
onFormChange({
|
|
68
113
|
...form,
|
|
69
114
|
features: {
|
|
70
115
|
...form.features,
|
|
71
|
-
|
|
116
|
+
agents: { ...currentConfig, enabled: true, mode },
|
|
72
117
|
},
|
|
73
118
|
});
|
|
74
119
|
};
|
|
@@ -77,7 +122,7 @@ export function CreateAgentModal({
|
|
|
77
122
|
<Modal>
|
|
78
123
|
<h2 className="text-xl font-semibold mb-4">Create New Agent</h2>
|
|
79
124
|
|
|
80
|
-
{
|
|
125
|
+
{providerOptions.length === 0 ? (
|
|
81
126
|
<NoProvidersMessage onGoToSettings={onGoToSettings} />
|
|
82
127
|
) : (
|
|
83
128
|
<>
|
|
@@ -131,28 +176,129 @@ export function CreateAgentModal({
|
|
|
131
176
|
|
|
132
177
|
<FormField label="Features">
|
|
133
178
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
|
134
|
-
{FEATURE_CONFIG.map(({ key, label, description, icon: Icon }) =>
|
|
179
|
+
{FEATURE_CONFIG.map(({ key, label, description, icon: Icon }) => {
|
|
180
|
+
const isEnabled = key === "agents" ? isAgentsEnabled() : !!form.features[key];
|
|
181
|
+
return (
|
|
182
|
+
<button
|
|
183
|
+
key={key}
|
|
184
|
+
type="button"
|
|
185
|
+
onClick={() => toggleFeature(key)}
|
|
186
|
+
className={`flex items-center gap-3 p-3 rounded border text-left transition ${
|
|
187
|
+
isEnabled
|
|
188
|
+
? "border-[#f97316] bg-[#f97316]/10"
|
|
189
|
+
: "border-[#222] hover:border-[#333]"
|
|
190
|
+
}`}
|
|
191
|
+
>
|
|
192
|
+
<Icon className={`w-5 h-5 flex-shrink-0 ${isEnabled ? "text-[#f97316]" : "text-[#666]"}`} />
|
|
193
|
+
<div className="flex-1 min-w-0">
|
|
194
|
+
<div className={`text-sm font-medium ${isEnabled ? "text-[#f97316]" : ""}`}>
|
|
195
|
+
{label}
|
|
196
|
+
</div>
|
|
197
|
+
<div className="text-xs text-[#666]">{description}</div>
|
|
198
|
+
</div>
|
|
199
|
+
</button>
|
|
200
|
+
);
|
|
201
|
+
})}
|
|
202
|
+
</div>
|
|
203
|
+
</FormField>
|
|
204
|
+
|
|
205
|
+
{/* Multi-Agent Mode Selection */}
|
|
206
|
+
{isAgentsEnabled() && (
|
|
207
|
+
<FormField label="Multi-Agent Mode">
|
|
208
|
+
<div className="flex gap-2">
|
|
135
209
|
<button
|
|
136
|
-
key={key}
|
|
137
210
|
type="button"
|
|
138
|
-
onClick={() =>
|
|
139
|
-
className={`flex
|
|
140
|
-
|
|
211
|
+
onClick={() => setAgentMode("coordinator")}
|
|
212
|
+
className={`flex-1 p-3 rounded border text-left transition ${
|
|
213
|
+
getAgentMode() === "coordinator"
|
|
141
214
|
? "border-[#f97316] bg-[#f97316]/10"
|
|
142
215
|
: "border-[#222] hover:border-[#333]"
|
|
143
216
|
}`}
|
|
144
217
|
>
|
|
145
|
-
<
|
|
146
|
-
|
|
147
|
-
<div className={`text-sm font-medium ${form.features[key] ? "text-[#f97316]" : ""}`}>
|
|
148
|
-
{label}
|
|
149
|
-
</div>
|
|
150
|
-
<div className="text-xs text-[#666]">{description}</div>
|
|
218
|
+
<div className={`text-sm font-medium ${getAgentMode() === "coordinator" ? "text-[#f97316]" : ""}`}>
|
|
219
|
+
Coordinator
|
|
151
220
|
</div>
|
|
221
|
+
<div className="text-xs text-[#666]">Orchestrates and delegates</div>
|
|
152
222
|
</button>
|
|
153
|
-
|
|
223
|
+
<button
|
|
224
|
+
type="button"
|
|
225
|
+
onClick={() => setAgentMode("worker")}
|
|
226
|
+
className={`flex-1 p-3 rounded border text-left transition ${
|
|
227
|
+
getAgentMode() === "worker"
|
|
228
|
+
? "border-[#f97316] bg-[#f97316]/10"
|
|
229
|
+
: "border-[#222] hover:border-[#333]"
|
|
230
|
+
}`}
|
|
231
|
+
>
|
|
232
|
+
<div className={`text-sm font-medium ${getAgentMode() === "worker" ? "text-[#f97316]" : ""}`}>
|
|
233
|
+
Worker
|
|
234
|
+
</div>
|
|
235
|
+
<div className="text-xs text-[#666]">Receives delegated tasks</div>
|
|
236
|
+
</button>
|
|
237
|
+
</div>
|
|
238
|
+
{form.projectId && (
|
|
239
|
+
<p className="text-xs text-[#555] mt-2">
|
|
240
|
+
Group: Using project as agent group
|
|
241
|
+
</p>
|
|
242
|
+
)}
|
|
243
|
+
</FormField>
|
|
244
|
+
)}
|
|
245
|
+
|
|
246
|
+
{/* Agent Built-in Tools - Anthropic only */}
|
|
247
|
+
{form.provider === "anthropic" && (
|
|
248
|
+
<FormField label="Agent Built-in Tools">
|
|
249
|
+
<div className="flex flex-wrap gap-2">
|
|
250
|
+
<button
|
|
251
|
+
type="button"
|
|
252
|
+
onClick={() => onFormChange({
|
|
253
|
+
...form,
|
|
254
|
+
features: {
|
|
255
|
+
...form.features,
|
|
256
|
+
builtinTools: {
|
|
257
|
+
...form.features.builtinTools,
|
|
258
|
+
webSearch: !form.features.builtinTools?.webSearch,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
})}
|
|
262
|
+
className={`flex items-center gap-2 px-3 py-2 rounded border transition ${
|
|
263
|
+
form.features.builtinTools?.webSearch
|
|
264
|
+
? "border-[#f97316] bg-[#f97316]/10 text-[#f97316]"
|
|
265
|
+
: "border-[#222] hover:border-[#333] text-[#888]"
|
|
266
|
+
}`}
|
|
267
|
+
>
|
|
268
|
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
269
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
270
|
+
</svg>
|
|
271
|
+
<span className="text-sm">Web Search</span>
|
|
272
|
+
</button>
|
|
273
|
+
<button
|
|
274
|
+
type="button"
|
|
275
|
+
onClick={() => onFormChange({
|
|
276
|
+
...form,
|
|
277
|
+
features: {
|
|
278
|
+
...form.features,
|
|
279
|
+
builtinTools: {
|
|
280
|
+
...form.features.builtinTools,
|
|
281
|
+
webFetch: !form.features.builtinTools?.webFetch,
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
})}
|
|
285
|
+
className={`flex items-center gap-2 px-3 py-2 rounded border transition ${
|
|
286
|
+
form.features.builtinTools?.webFetch
|
|
287
|
+
? "border-[#f97316] bg-[#f97316]/10 text-[#f97316]"
|
|
288
|
+
: "border-[#222] hover:border-[#333] text-[#888]"
|
|
289
|
+
}`}
|
|
290
|
+
>
|
|
291
|
+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
292
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
|
|
293
|
+
</svg>
|
|
294
|
+
<span className="text-sm">Web Fetch</span>
|
|
295
|
+
</button>
|
|
154
296
|
</div>
|
|
297
|
+
<p className="text-xs text-[#555] mt-2">
|
|
298
|
+
Provider-native tools for real-time web access
|
|
299
|
+
</p>
|
|
155
300
|
</FormField>
|
|
301
|
+
)}
|
|
156
302
|
</div>
|
|
157
303
|
|
|
158
304
|
<div className="flex gap-3 mt-6">
|
|
@@ -102,6 +102,14 @@ export function McpIcon({ className = "w-4 h-4" }: IconProps) {
|
|
|
102
102
|
);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
export function SkillsIcon({ className = "w-4 h-4" }: IconProps) {
|
|
106
|
+
return (
|
|
107
|
+
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
108
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
|
|
109
|
+
</svg>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
105
113
|
export function RealtimeIcon({ className = "w-4 h-4" }: IconProps) {
|
|
106
114
|
return (
|
|
107
115
|
<svg className={className} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -14,4 +14,5 @@ export { AgentCard, CreateAgentModal, AgentPanel, AgentsView } from "./agents";
|
|
|
14
14
|
export { Dashboard } from "./dashboard";
|
|
15
15
|
export { TasksPage } from "./tasks";
|
|
16
16
|
export { McpPage } from "./mcp";
|
|
17
|
+
export { SkillsPage } from "./skills/SkillsPage";
|
|
17
18
|
export { TelemetryPage } from "./telemetry/TelemetryPage";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
2
|
import { useTelemetryContext, useAuth, useProjects } from "../../context";
|
|
3
3
|
import { MenuIcon, ChevronDownIcon } from "../common/Icons";
|
|
4
|
+
import { MetaAgentButton } from "../meta-agent/MetaAgent";
|
|
4
5
|
|
|
5
6
|
interface HeaderProps {
|
|
6
7
|
onMenuClick?: () => void;
|
|
@@ -9,7 +10,7 @@ interface HeaderProps {
|
|
|
9
10
|
export function Header({ onMenuClick }: HeaderProps) {
|
|
10
11
|
const { connected } = useTelemetryContext();
|
|
11
12
|
const { user, logout } = useAuth();
|
|
12
|
-
const { projects, currentProjectId, currentProject, setCurrentProjectId, unassignedCount } = useProjects();
|
|
13
|
+
const { projects, currentProjectId, currentProject, setCurrentProjectId, unassignedCount, projectsEnabled } = useProjects();
|
|
13
14
|
const [showUserMenu, setShowUserMenu] = useState(false);
|
|
14
15
|
const [showProjectMenu, setShowProjectMenu] = useState(false);
|
|
15
16
|
|
|
@@ -52,7 +53,7 @@ export function Header({ onMenuClick }: HeaderProps) {
|
|
|
52
53
|
</div>
|
|
53
54
|
|
|
54
55
|
{/* Project Selector */}
|
|
55
|
-
{projects.length > 0 && (
|
|
56
|
+
{projectsEnabled && projects.length > 0 && (
|
|
56
57
|
<div className="relative ml-2 md:ml-4">
|
|
57
58
|
<button
|
|
58
59
|
onClick={() => setShowProjectMenu(!showProjectMenu)}
|
|
@@ -122,6 +123,7 @@ export function Header({ onMenuClick }: HeaderProps) {
|
|
|
122
123
|
{connected ? "Live" : "Offline"}
|
|
123
124
|
</span>
|
|
124
125
|
</div>
|
|
126
|
+
<MetaAgentButton />
|
|
125
127
|
{user && (
|
|
126
128
|
<div className="relative">
|
|
127
129
|
<button
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { DashboardIcon, AgentsIcon, TasksIcon, McpIcon, TelemetryIcon, ApiIcon, SettingsIcon, CloseIcon } from "../common/Icons";
|
|
2
|
+
import { DashboardIcon, AgentsIcon, TasksIcon, McpIcon, SkillsIcon, TelemetryIcon, ApiIcon, SettingsIcon, CloseIcon } from "../common/Icons";
|
|
3
3
|
import type { Route } from "../../types";
|
|
4
4
|
|
|
5
5
|
interface SidebarProps {
|
|
@@ -76,6 +76,12 @@ export function Sidebar({ route, agentCount, taskCount, onNavigate, isOpen, onCl
|
|
|
76
76
|
active={route === "mcp"}
|
|
77
77
|
onClick={() => handleNavigate("mcp")}
|
|
78
78
|
/>
|
|
79
|
+
<NavButton
|
|
80
|
+
icon={<SkillsIcon />}
|
|
81
|
+
label="Skills"
|
|
82
|
+
active={route === "skills"}
|
|
83
|
+
onClick={() => handleNavigate("skills")}
|
|
84
|
+
/>
|
|
79
85
|
<NavButton
|
|
80
86
|
icon={<TelemetryIcon />}
|
|
81
87
|
label="Telemetry"
|