apteva 0.4.54 → 0.4.57
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/ActivityPage.kxzzb4yc.js +3 -0
- package/dist/ApiDocsPage.zq998hbm.js +4 -0
- package/dist/App.55rea8mn.js +61 -0
- package/dist/App.5ywb23z4.js +53 -0
- package/dist/App.6thds120.js +4 -0
- package/dist/{App.ccs4g85x.js → App.9tctxzqm.js} +3 -3
- package/dist/App.a8r8ttaz.js +4 -0
- package/dist/App.agsv5bje.js +4 -0
- package/dist/App.cepapqmx.js +4 -0
- package/dist/App.dp041gb3.js +221 -0
- package/dist/App.fds72zb5.js +4 -0
- package/dist/App.fg9qj2dq.js +4 -0
- package/dist/App.ndfejbm9.js +4 -0
- package/dist/App.nxmfmq1h.js +13 -0
- package/dist/App.qdfyt8ba.js +4 -0
- package/dist/{App.g1qhcmpc.js → App.x2d0ygt6.js} +2 -2
- package/dist/App.yt9p4nr3.js +20 -0
- package/dist/{App.wghtdzsk.js → App.zn4mw16t.js} +1 -1
- package/dist/ConnectionsPage.8r96ryw7.js +3 -0
- package/dist/McpPage.3cwh0gnd.js +3 -0
- package/dist/SettingsPage.ykgdh5ev.js +3 -0
- package/dist/SkillsPage.4np1s65b.js +3 -0
- package/dist/TasksPage.4g08t7p6.js +3 -0
- package/dist/TelemetryPage.72w9pwcp.js +3 -0
- package/dist/TestsPage.z4fk3r7r.js +3 -0
- package/dist/ThreadsPage.63tcajeh.js +3 -0
- package/dist/apteva-kit.css +1 -1
- package/dist/index.html +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
- package/src/crypto.ts +25 -4
- package/src/db.ts +24 -1
- package/src/mcp-platform.ts +235 -39
- package/src/providers.ts +125 -5
- package/src/routes/api/agent-utils.ts +105 -8
- package/src/routes/api/providers.ts +64 -0
- package/src/routes/share.ts +3 -2
- package/src/server.ts +53 -7
- package/src/test-runner.ts +1 -1
- package/src/web/App.tsx +37 -22
- package/src/web/components/agents/AgentCard.tsx +12 -9
- package/src/web/components/agents/AgentPanel.tsx +126 -7
- package/src/web/components/agents/AgentsView.tsx +30 -8
- package/src/web/components/agents/CreateAgentModal.tsx +155 -5
- package/src/web/components/dashboard/Dashboard.tsx +9 -7
- package/src/web/components/layout/Sidebar.tsx +43 -32
- package/src/web/components/meta-agent/MetaAgent.tsx +6 -2
- package/src/web/components/settings/SettingsPage.tsx +172 -43
- package/src/web/components/telemetry/TelemetryPage.tsx +41 -36
- package/src/web/components/tests/TestsPage.tsx +91 -76
- package/src/web/context/UIModeContext.tsx +49 -0
- package/src/web/context/index.ts +3 -0
- package/src/web/types.ts +67 -3
- package/dist/ActivityPage.k33hj12v.js +0 -3
- package/dist/ApiDocsPage.q37747gr.js +0 -4
- package/dist/App.3hp80jc2.js +0 -53
- package/dist/App.5ebcd85d.js +0 -4
- package/dist/App.6fefs2d5.js +0 -4
- package/dist/App.794kjn6a.js +0 -4
- package/dist/App.c5ebgvec.js +0 -61
- package/dist/App.cb1np6f0.js +0 -20
- package/dist/App.jemr4v3a.js +0 -221
- package/dist/App.kpyf0grm.js +0 -4
- package/dist/App.p7zc1bv2.js +0 -13
- package/dist/App.qx4wdtjg.js +0 -4
- package/dist/App.wjxmwjrp.js +0 -4
- package/dist/App.wq1f2jke.js +0 -4
- package/dist/App.zx6x0gk2.js +0 -4
- package/dist/ConnectionsPage.8b2v07qp.js +0 -3
- package/dist/McpPage.3800a82c.js +0 -3
- package/dist/SettingsPage.88nj3hbv.js +0 -3
- package/dist/SkillsPage.b8pxj5mb.js +0 -3
- package/dist/TasksPage.6b3y4b1n.js +0 -3
- package/dist/TelemetryPage.7q4d69wj.js +0 -3
- package/dist/TestsPage.dpevv5xb.js +0 -3
- package/dist/ThreadsPage.1h15363y.js +0 -3
package/src/mcp-platform.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { AgentDB, ProjectDB, McpServerDB, McpServerToolDB, SkillDB, TelemetryDB,
|
|
|
5
5
|
import { TestCaseDB, TestRunDB } from "./db-tests";
|
|
6
6
|
import { runTest, runAll } from "./test-runner";
|
|
7
7
|
import { getProvidersWithStatus, PROVIDERS, ProviderKeys } from "./providers";
|
|
8
|
-
import { startAgentProcess, setAgentStatus, toApiAgent, META_AGENT_ID, agentFetch, fetchFromAgent } from "./routes/api/agent-utils";
|
|
8
|
+
import { startAgentProcess, setAgentStatus, toApiAgent, META_AGENT_ID, agentFetch, fetchFromAgent, buildAgentConfig, pushConfigToAgent, pushSkillsToAgent } from "./routes/api/agent-utils";
|
|
9
9
|
import { agentProcesses } from "./server";
|
|
10
10
|
import { getTriggerProvider, getTriggerProviderIds, registerTriggerProvider } from "./triggers";
|
|
11
11
|
import { ComposioTriggerProvider } from "./triggers/composio";
|
|
@@ -94,6 +94,7 @@ FEATURES (all optional, default false):
|
|
|
94
94
|
- vision: Image & PDF understanding — agent can analyze uploaded images and PDFs.
|
|
95
95
|
- mcp: MCP tool use — agent can use tools from assigned MCP servers. Enable this if you plan to assign MCP servers.
|
|
96
96
|
- files: File management — agent can read, write, and manage files in its workspace.
|
|
97
|
+
- agents: Multi-agent communication — agent can call and delegate tasks to peer agents in the same project. Enables call_agent and list_available_agents tools.
|
|
97
98
|
|
|
98
99
|
TIPS:
|
|
99
100
|
- Always provide a descriptive system_prompt that tells the agent what it does and how to behave.
|
|
@@ -116,6 +117,7 @@ TIPS:
|
|
|
116
117
|
vision: { type: "boolean", description: "Image and PDF understanding" },
|
|
117
118
|
mcp: { type: "boolean", description: "MCP tool use — required if assigning MCP servers" },
|
|
118
119
|
files: { type: "boolean", description: "File read/write in agent workspace" },
|
|
120
|
+
agents: { type: "boolean", description: "Multi-agent communication — call and delegate to peer agents in the same project" },
|
|
119
121
|
},
|
|
120
122
|
},
|
|
121
123
|
},
|
|
@@ -124,7 +126,7 @@ TIPS:
|
|
|
124
126
|
},
|
|
125
127
|
{
|
|
126
128
|
name: "update_agent",
|
|
127
|
-
description: `Update an existing agent's configuration. Only provide fields you want to change.
|
|
129
|
+
description: `Update an existing agent's configuration. Only provide fields you want to change. Changes are applied live — if the agent is running, the new config is pushed automatically. No restart needed.
|
|
128
130
|
|
|
129
131
|
SKILLS & MCP SERVERS:
|
|
130
132
|
- Pass skill_ids or mcp_server_ids to SET the full list (replaces existing).
|
|
@@ -150,6 +152,7 @@ SKILLS & MCP SERVERS:
|
|
|
150
152
|
vision: { type: "boolean" },
|
|
151
153
|
mcp: { type: "boolean" },
|
|
152
154
|
files: { type: "boolean" },
|
|
155
|
+
agents: { type: "boolean" },
|
|
153
156
|
},
|
|
154
157
|
},
|
|
155
158
|
skill_ids: { type: "array", items: { type: "string" }, description: "Set the full list of skill IDs (replaces existing)" },
|
|
@@ -382,9 +385,20 @@ EXAMPLES:
|
|
|
382
385
|
},
|
|
383
386
|
},
|
|
384
387
|
// Task management on agents
|
|
388
|
+
{
|
|
389
|
+
name: "list_tasks",
|
|
390
|
+
description: "List all tasks across ALL running agents in the project. Returns tasks from every agent, each tagged with agentId and agentName. Use this to get a project-wide overview of all tasks.",
|
|
391
|
+
inputSchema: {
|
|
392
|
+
type: "object",
|
|
393
|
+
properties: {
|
|
394
|
+
project_id: { type: "string", description: "Filter to a specific project (optional). If omitted, returns tasks from all running agents." },
|
|
395
|
+
status: { type: "string", description: "Filter by status: all, pending, running, completed, failed, cancelled (default: all)" },
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
},
|
|
385
399
|
{
|
|
386
400
|
name: "list_agent_tasks",
|
|
387
|
-
description: "List tasks on a running agent.
|
|
401
|
+
description: "List tasks on a specific running agent. Use list_tasks instead for a project-wide view.",
|
|
388
402
|
inputSchema: {
|
|
389
403
|
type: "object",
|
|
390
404
|
properties: {
|
|
@@ -532,18 +546,17 @@ EXAMPLES:
|
|
|
532
546
|
},
|
|
533
547
|
{
|
|
534
548
|
name: "create_test",
|
|
535
|
-
description: "Create a
|
|
549
|
+
description: "Create a behavior-driven test case. Describe what the agent should do in natural language — the system will auto-select the best agent and generate the test message. Optionally pin to a specific agent.",
|
|
536
550
|
inputSchema: {
|
|
537
551
|
type: "object",
|
|
538
552
|
properties: {
|
|
539
553
|
name: { type: "string", description: "Test name" },
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
timeout_ms: { type: "number", description: "Timeout in ms (default 60000)" },
|
|
554
|
+
behavior: { type: "string", description: "Natural language description of what the agent should do. E.g. 'Search the web for the latest news about AI and summarize it'" },
|
|
555
|
+
agent_id: { type: "string", description: "Optional: pin to a specific agent ID. If omitted, the AI planner auto-selects the best agent." },
|
|
556
|
+
project_id: { type: "string", description: "Optional: project ID to scope agent selection" },
|
|
557
|
+
timeout_ms: { type: "number", description: "Timeout in ms (default 300000 = 5 min)" },
|
|
545
558
|
},
|
|
546
|
-
required: ["name", "
|
|
559
|
+
required: ["name", "behavior"],
|
|
547
560
|
},
|
|
548
561
|
},
|
|
549
562
|
{
|
|
@@ -828,6 +841,43 @@ After adding, use assign_mcp_server_to_agent to give an agent access to these to
|
|
|
828
841
|
required: ["provider", "config_id"],
|
|
829
842
|
},
|
|
830
843
|
},
|
|
844
|
+
// Provider key management
|
|
845
|
+
{
|
|
846
|
+
name: "set_provider_key",
|
|
847
|
+
description: "Set or update an API key for a provider (LLM or integration). Use list_providers or list_integration_providers to see which providers need keys. Ask the user for the key — never guess or fabricate one.",
|
|
848
|
+
inputSchema: {
|
|
849
|
+
type: "object",
|
|
850
|
+
properties: {
|
|
851
|
+
provider_id: { type: "string", description: "Provider ID (e.g. 'anthropic', 'openai', 'agentdojo', 'composio')" },
|
|
852
|
+
key: { type: "string", description: "The API key value" },
|
|
853
|
+
project_id: { type: "string", description: "Project ID to scope the key to (optional — omit for global key)" },
|
|
854
|
+
},
|
|
855
|
+
required: ["provider_id", "key"],
|
|
856
|
+
},
|
|
857
|
+
},
|
|
858
|
+
// MCP server lifecycle
|
|
859
|
+
{
|
|
860
|
+
name: "start_mcp_server",
|
|
861
|
+
description: "Start an MCP server. npm/pip servers will be installed and launched; local servers are activated immediately; HTTP servers are always available.",
|
|
862
|
+
inputSchema: {
|
|
863
|
+
type: "object",
|
|
864
|
+
properties: {
|
|
865
|
+
server_id: { type: "string", description: "The MCP server ID to start" },
|
|
866
|
+
},
|
|
867
|
+
required: ["server_id"],
|
|
868
|
+
},
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
name: "stop_mcp_server",
|
|
872
|
+
description: "Stop a running MCP server.",
|
|
873
|
+
inputSchema: {
|
|
874
|
+
type: "object",
|
|
875
|
+
properties: {
|
|
876
|
+
server_id: { type: "string", description: "The MCP server ID to stop" },
|
|
877
|
+
},
|
|
878
|
+
required: ["server_id"],
|
|
879
|
+
},
|
|
880
|
+
},
|
|
831
881
|
// Analytics
|
|
832
882
|
{
|
|
833
883
|
name: "get_analytics",
|
|
@@ -952,14 +1002,17 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
952
1002
|
mcp: args.features?.mcp ?? false,
|
|
953
1003
|
realtime: false,
|
|
954
1004
|
files: args.features?.files ?? false,
|
|
955
|
-
agents: false,
|
|
1005
|
+
agents: args.features?.agents ? { enabled: true, group: args.project_id || undefined } : false,
|
|
956
1006
|
},
|
|
957
1007
|
mcp_servers: [],
|
|
958
1008
|
skills: [],
|
|
959
1009
|
project_id: args.project_id || null,
|
|
960
1010
|
});
|
|
961
1011
|
|
|
962
|
-
|
|
1012
|
+
const enabledFeatures = Object.entries(agent.features)
|
|
1013
|
+
.filter(([_, v]) => v === true || (typeof v === "object" && v?.enabled))
|
|
1014
|
+
.map(([k]) => k === "agents" ? "multi-agent (call_agent, delegate_task, list_available_agents)" : k);
|
|
1015
|
+
return { content: [{ type: "text", text: `Agent created successfully:\n${JSON.stringify({ id: agent.id, name: agent.name, provider: agent.provider, model: agent.model, features: enabledFeatures.length > 0 ? enabledFeatures.join(", ") : "none" }, null, 2)}` }] };
|
|
963
1016
|
}
|
|
964
1017
|
|
|
965
1018
|
case "update_agent": {
|
|
@@ -975,7 +1028,14 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
975
1028
|
if (args.system_prompt !== undefined) updates.system_prompt = args.system_prompt;
|
|
976
1029
|
if (args.project_id !== undefined) updates.project_id = args.project_id;
|
|
977
1030
|
if (args.features !== undefined) {
|
|
978
|
-
|
|
1031
|
+
const mergedFeatures = { ...agent.features, ...args.features };
|
|
1032
|
+
// Convert agents boolean to MultiAgentConfig
|
|
1033
|
+
if (typeof mergedFeatures.agents === "boolean") {
|
|
1034
|
+
mergedFeatures.agents = mergedFeatures.agents
|
|
1035
|
+
? { enabled: true, group: args.project_id || agent.project_id || undefined }
|
|
1036
|
+
: false;
|
|
1037
|
+
}
|
|
1038
|
+
updates.features = mergedFeatures;
|
|
979
1039
|
}
|
|
980
1040
|
|
|
981
1041
|
// Skills: set, add, or remove
|
|
@@ -1017,7 +1077,37 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1017
1077
|
}
|
|
1018
1078
|
|
|
1019
1079
|
const updated = AgentDB.update(args.agent_id, updates);
|
|
1020
|
-
|
|
1080
|
+
|
|
1081
|
+
// Push config to running agent (live update, no restart needed)
|
|
1082
|
+
let configPushed = false;
|
|
1083
|
+
if (updated && updated.status === "running" && updated.port) {
|
|
1084
|
+
const providerKey = ProviderKeys.getDecrypted(updated.provider);
|
|
1085
|
+
if (providerKey) {
|
|
1086
|
+
const config = buildAgentConfig(updated, providerKey);
|
|
1087
|
+
const configResult = await pushConfigToAgent(updated.id, updated.port, config);
|
|
1088
|
+
configPushed = configResult.success;
|
|
1089
|
+
// Push skills if any
|
|
1090
|
+
if (config.skills?.definitions?.length > 0) {
|
|
1091
|
+
await pushSkillsToAgent(updated.id, updated.port, config.skills.definitions);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// Build a clear summary of what changed
|
|
1097
|
+
const summary: Record<string, any> = { id: updated?.id, name: updated?.name };
|
|
1098
|
+
if (updates.features) {
|
|
1099
|
+
const enabledFeatures = Object.entries(updates.features)
|
|
1100
|
+
.filter(([_, v]) => v === true || (typeof v === "object" && v?.enabled))
|
|
1101
|
+
.map(([k]) => k === "agents" ? "multi-agent (call_agent, delegate_task, list_available_agents)" : k);
|
|
1102
|
+
summary.features = enabledFeatures.join(", ") || "none";
|
|
1103
|
+
}
|
|
1104
|
+
if (updates.skills !== undefined) summary.skills = updates.skills.length + " skills";
|
|
1105
|
+
if (updates.mcp_servers !== undefined) summary.mcp_servers = updates.mcp_servers.length + " servers";
|
|
1106
|
+
if (updates.name) summary.name = updates.name;
|
|
1107
|
+
if (updates.model) summary.model = updates.model;
|
|
1108
|
+
if (updates.system_prompt) summary.system_prompt = "updated";
|
|
1109
|
+
if (configPushed) summary.config_status = "applied live (no restart needed)";
|
|
1110
|
+
return { content: [{ type: "text", text: `Agent updated: ${JSON.stringify(summary, null, 2)}` }] };
|
|
1021
1111
|
}
|
|
1022
1112
|
|
|
1023
1113
|
case "delete_agent": {
|
|
@@ -1354,6 +1444,42 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1354
1444
|
}
|
|
1355
1445
|
}
|
|
1356
1446
|
|
|
1447
|
+
case "list_tasks": {
|
|
1448
|
+
const status = args.status || "all";
|
|
1449
|
+
let runningAgents = AgentDB.findAll().filter(a => a.status === "running" && a.port);
|
|
1450
|
+
|
|
1451
|
+
if (args.project_id === "unassigned") {
|
|
1452
|
+
runningAgents = runningAgents.filter(a => !a.project_id);
|
|
1453
|
+
} else if (args.project_id) {
|
|
1454
|
+
runningAgents = runningAgents.filter(a => a.project_id === args.project_id);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
const allTasks: any[] = [];
|
|
1458
|
+
const results = await Promise.all(
|
|
1459
|
+
runningAgents.map(async (agent) => {
|
|
1460
|
+
try {
|
|
1461
|
+
const data = await fetchFromAgent(agent.id, agent.port!, `/tasks?status=${status}`);
|
|
1462
|
+
return { agent, tasks: data?.tasks || [] };
|
|
1463
|
+
} catch {
|
|
1464
|
+
return { agent, tasks: [] };
|
|
1465
|
+
}
|
|
1466
|
+
})
|
|
1467
|
+
);
|
|
1468
|
+
|
|
1469
|
+
for (const { agent, tasks } of results) {
|
|
1470
|
+
for (const task of tasks) {
|
|
1471
|
+
allTasks.push({
|
|
1472
|
+
id: task.id, title: task.title, type: task.type, status: task.status, priority: task.priority,
|
|
1473
|
+
recurrence: task.recurrence, next_run: task.next_run, execute_at: task.execute_at, created_at: task.created_at,
|
|
1474
|
+
agentId: agent.id, agentName: agent.name,
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
allTasks.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
1480
|
+
return { content: [{ type: "text", text: JSON.stringify({ tasks: allTasks, count: allTasks.length }, null, 2) }] };
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1357
1483
|
case "list_agent_tasks": {
|
|
1358
1484
|
const agent = AgentDB.findById(args.agent_id);
|
|
1359
1485
|
if (!agent) return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
@@ -1533,37 +1659,44 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1533
1659
|
case "list_tests": {
|
|
1534
1660
|
const tests = TestCaseDB.findAll(args.project_id);
|
|
1535
1661
|
const result = tests.map(tc => {
|
|
1536
|
-
const agent = AgentDB.findById(tc.agent_id);
|
|
1662
|
+
const agent = tc.agent_id ? AgentDB.findById(tc.agent_id) : null;
|
|
1537
1663
|
const lastRun = TestRunDB.getLatestByTestCase(tc.id);
|
|
1538
1664
|
return {
|
|
1539
1665
|
id: tc.id,
|
|
1540
1666
|
name: tc.name,
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
eval_criteria: tc.eval_criteria,
|
|
1545
|
-
timeout_ms: tc.timeout_ms,
|
|
1667
|
+
behavior: tc.behavior || null,
|
|
1668
|
+
agent_id: tc.agent_id || null,
|
|
1669
|
+
agent_name: agent?.name || (tc.agent_id ? "Unknown" : "Auto-select"),
|
|
1546
1670
|
last_status: lastRun?.status || null,
|
|
1671
|
+
last_score: lastRun?.score || null,
|
|
1547
1672
|
last_reasoning: lastRun?.judge_reasoning || null,
|
|
1673
|
+
last_selected_agent: lastRun?.selected_agent_name || null,
|
|
1548
1674
|
};
|
|
1549
1675
|
});
|
|
1550
1676
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1551
1677
|
}
|
|
1552
1678
|
|
|
1553
1679
|
case "create_test": {
|
|
1554
|
-
|
|
1555
|
-
if (
|
|
1556
|
-
|
|
1680
|
+
// Validate agent if explicitly provided
|
|
1681
|
+
if (args.agent_id) {
|
|
1682
|
+
const agent = AgentDB.findById(args.agent_id);
|
|
1683
|
+
if (!agent) {
|
|
1684
|
+
return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
1685
|
+
}
|
|
1557
1686
|
}
|
|
1558
1687
|
const tc = TestCaseDB.create({
|
|
1559
1688
|
name: args.name,
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
timeout_ms: args.timeout_ms,
|
|
1689
|
+
behavior: args.behavior,
|
|
1690
|
+
agent_id: args.agent_id || null,
|
|
1691
|
+
input_message: null,
|
|
1692
|
+
eval_criteria: args.behavior,
|
|
1693
|
+
timeout_ms: args.timeout_ms || 300000,
|
|
1694
|
+
project_id: args.project_id || null,
|
|
1565
1695
|
});
|
|
1566
|
-
|
|
1696
|
+
const agentNote = args.agent_id
|
|
1697
|
+
? `pinned to agent "${AgentDB.findById(args.agent_id)?.name}"`
|
|
1698
|
+
: "AI will auto-select the best agent";
|
|
1699
|
+
return { content: [{ type: "text", text: `Test "${tc.name}" created (id: ${tc.id}). ${agentNote}. Use run_test to execute it.` }] };
|
|
1567
1700
|
}
|
|
1568
1701
|
|
|
1569
1702
|
case "run_test": {
|
|
@@ -1572,8 +1705,10 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1572
1705
|
return { content: [{ type: "text", text: `Test not found: ${args.test_id}` }], isError: true };
|
|
1573
1706
|
}
|
|
1574
1707
|
const result = await runTest(tc);
|
|
1575
|
-
const
|
|
1576
|
-
|
|
1708
|
+
const agentName = result.selected_agent_name || (tc.agent_id ? AgentDB.findById(tc.agent_id)?.name : null) || "unknown";
|
|
1709
|
+
const score = result.score != null ? ` (score: ${result.score}/10)` : "";
|
|
1710
|
+
const duration = result.duration_ms ? ` in ${(result.duration_ms / 1000).toFixed(1)}s` : "";
|
|
1711
|
+
return { content: [{ type: "text", text: `Test "${tc.name}" → ${result.status.toUpperCase()}${score}${duration}\nAgent: ${agentName}\n\nJudge: ${result.judge_reasoning || result.error || "No reasoning"}` }] };
|
|
1577
1712
|
}
|
|
1578
1713
|
|
|
1579
1714
|
case "run_all_tests": {
|
|
@@ -1597,8 +1732,11 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1597
1732
|
const result = runs.map(r => ({
|
|
1598
1733
|
id: r.id,
|
|
1599
1734
|
status: r.status,
|
|
1735
|
+
score: r.score,
|
|
1600
1736
|
duration_ms: r.duration_ms,
|
|
1601
1737
|
judge_reasoning: r.judge_reasoning,
|
|
1738
|
+
selected_agent: r.selected_agent_name || null,
|
|
1739
|
+
generated_message: r.generated_message || null,
|
|
1602
1740
|
error: r.error,
|
|
1603
1741
|
created_at: r.created_at,
|
|
1604
1742
|
}));
|
|
@@ -2077,6 +2215,64 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
2077
2215
|
return { content: [{ type: "text", text: `Local add not supported for provider: ${providerId}` }], isError: true };
|
|
2078
2216
|
}
|
|
2079
2217
|
|
|
2218
|
+
case "set_provider_key": {
|
|
2219
|
+
const providerId = args.provider_id;
|
|
2220
|
+
if (!PROVIDERS[providerId as keyof typeof PROVIDERS]) {
|
|
2221
|
+
return { content: [{ type: "text", text: `Unknown provider: ${providerId}. Use list_providers or list_integration_providers to see available providers.` }], isError: true };
|
|
2222
|
+
}
|
|
2223
|
+
if (!args.key) {
|
|
2224
|
+
return { content: [{ type: "text", text: "API key is required" }], isError: true };
|
|
2225
|
+
}
|
|
2226
|
+
const result = await ProviderKeys.save(providerId, args.key, args.project_id || null, null);
|
|
2227
|
+
if (!result.success) {
|
|
2228
|
+
return { content: [{ type: "text", text: `Failed to save key: ${result.error}` }], isError: true };
|
|
2229
|
+
}
|
|
2230
|
+
const provider = PROVIDERS[providerId as keyof typeof PROVIDERS];
|
|
2231
|
+
return { content: [{ type: "text", text: `API key saved for ${provider.name}.` }] };
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
case "start_mcp_server": {
|
|
2235
|
+
const server = McpServerDB.findById(args.server_id);
|
|
2236
|
+
if (!server) {
|
|
2237
|
+
return { content: [{ type: "text", text: `MCP server not found: ${args.server_id}` }], isError: true };
|
|
2238
|
+
}
|
|
2239
|
+
if (server.status === "running") {
|
|
2240
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" is already running` }] };
|
|
2241
|
+
}
|
|
2242
|
+
try {
|
|
2243
|
+
const port = process.env.PORT || "4280";
|
|
2244
|
+
const res = await fetch(`http://localhost:${port}/api/mcp/servers/${args.server_id}/start`, { method: "POST" });
|
|
2245
|
+
const data = await res.json() as Record<string, unknown>;
|
|
2246
|
+
if (!res.ok) {
|
|
2247
|
+
return { content: [{ type: "text", text: `Failed to start: ${data.error || "unknown error"}` }], isError: true };
|
|
2248
|
+
}
|
|
2249
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" started. ${data.message || ""}` }] };
|
|
2250
|
+
} catch (err) {
|
|
2251
|
+
return { content: [{ type: "text", text: `Failed to start MCP server: ${err}` }], isError: true };
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
case "stop_mcp_server": {
|
|
2256
|
+
const server = McpServerDB.findById(args.server_id);
|
|
2257
|
+
if (!server) {
|
|
2258
|
+
return { content: [{ type: "text", text: `MCP server not found: ${args.server_id}` }], isError: true };
|
|
2259
|
+
}
|
|
2260
|
+
if (server.status !== "running") {
|
|
2261
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" is not running` }] };
|
|
2262
|
+
}
|
|
2263
|
+
try {
|
|
2264
|
+
const port = process.env.PORT || "4280";
|
|
2265
|
+
const res = await fetch(`http://localhost:${port}/api/mcp/servers/${args.server_id}/stop`, { method: "POST" });
|
|
2266
|
+
const data = await res.json() as Record<string, unknown>;
|
|
2267
|
+
if (!res.ok) {
|
|
2268
|
+
return { content: [{ type: "text", text: `Failed to stop: ${data.error || "unknown error"}` }], isError: true };
|
|
2269
|
+
}
|
|
2270
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" stopped.` }] };
|
|
2271
|
+
} catch (err) {
|
|
2272
|
+
return { content: [{ type: "text", text: `Failed to stop MCP server: ${err}` }], isError: true };
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2080
2276
|
case "get_analytics": {
|
|
2081
2277
|
const stats = TelemetryDB.getStats({
|
|
2082
2278
|
agentId: args.agent_id || undefined,
|
|
@@ -2150,24 +2346,24 @@ export async function handlePlatformMcpRequest(req: Request): Promise<Response>
|
|
|
2150
2346
|
instructions: `This MCP server controls the Apteva AI agent management platform.
|
|
2151
2347
|
|
|
2152
2348
|
You can manage:
|
|
2153
|
-
- AGENTS: Create, configure, start, stop, and delete AI agents. Each agent has a provider (LLM), model, system prompt, and optional features (memory, tasks, vision, MCP tools, files). Use update_agent to assign/remove MCP servers (add_mcp_servers, remove_mcp_servers) and skills (add_skills, remove_skills).
|
|
2154
|
-
- TASKS: List, create, delete, and execute tasks
|
|
2349
|
+
- AGENTS: Create, configure, start, stop, and delete AI agents. Each agent has a provider (LLM), model, system prompt, and optional features (memory, tasks, vision, MCP tools, files, agents/multi-agent). The "agents" feature enables multi-agent communication — agents can call and delegate tasks to peer agents in the same project. Use update_agent to assign/remove MCP servers (add_mcp_servers, remove_mcp_servers) and skills (add_skills, remove_skills).
|
|
2350
|
+
- TASKS: List, create, delete, and execute tasks. Use list_tasks for a project-wide overview of all tasks across all running agents. Use list_agent_tasks for tasks on a specific agent. Agents must have the tasks feature enabled. Tools: list_tasks, list_agent_tasks, create_agent_task, delete_agent_task, execute_agent_task.
|
|
2155
2351
|
- PROJECTS: Organize agents into projects. Tools: list_projects, create_project, update_project, delete_project. Use project tools when the user is viewing All Projects. Deleting a project unassigns its agents (does not delete them).
|
|
2156
|
-
- MCP SERVERS: Tool integrations that give agents capabilities (web search, file access, APIs). Use update_agent with add_mcp_servers to assign servers to agents.
|
|
2352
|
+
- MCP SERVERS: Tool integrations that give agents capabilities (web search, file access, APIs). Use update_agent with add_mcp_servers to assign servers to agents. Use start_mcp_server/stop_mcp_server to activate/deactivate servers.
|
|
2157
2353
|
- SKILLS: Reusable instruction sets that specialize agent behavior. Use create_skill to create new skills (pass project_id from context to scope to the current project). Use update_agent with add_skills/remove_skills to assign/unassign skills to agents. Tools: list_skills, get_skill, create_skill, update_skill, toggle_skill, delete_skill.
|
|
2158
2354
|
- ANALYTICS: View token usage, costs, and activity stats across agents. Tools: get_analytics (summary totals), get_usage_by_agent (per-agent breakdown). Both support filtering by agent, project, or time range.
|
|
2159
|
-
- PROVIDERS: View
|
|
2160
|
-
- TESTS: Create
|
|
2355
|
+
- PROVIDERS: View and configure API keys for LLM and integration providers. Tools: list_providers, set_provider_key. If a provider key is missing, ask the user for it and save with set_provider_key.
|
|
2356
|
+
- TESTS: Create behavior-driven tests for agent workflows. Describe what the agent should do in natural language — the system auto-selects the best agent and generates a test message. An LLM judge evaluates the result and scores 1-10. Tools: list_tests, create_test, run_test, run_all_tests, get_test_results, delete_test.
|
|
2161
2357
|
- SUBSCRIPTIONS & TRIGGERS: Subscribe agents to external events (webhooks). Supports multiple providers (composio, agentdojo). Use list_trigger_providers → list_trigger_types → list_integration_connections → create_subscription. Manage with enable_subscription, disable_subscription, delete_subscription, list_subscriptions.
|
|
2162
2358
|
- INTEGRATIONS: Connect third-party apps and create MCP servers from them. Supports agentdojo and composio providers. Use list_integration_providers → list_integration_apps → connect_integration_app (API key) → create_integration_config → add_integration_config_locally → then update_agent with add_mcp_servers to assign to an agent. For OAuth apps, direct the user to the Browse Toolkits UI.
|
|
2163
2359
|
|
|
2164
2360
|
CRITICAL: ALWAYS pass project_id to every tool call that accepts it. API keys and resources are scoped per project — calls without project_id will fail. The chat context tells you the current project id.
|
|
2165
2361
|
|
|
2166
2362
|
Typical workflow: list_providers → create_agent → update_agent (add_mcp_servers/add_skills) → start_agent.
|
|
2167
|
-
Task workflow: list_agent_tasks → create_agent_task (schedule work) → execute_agent_task (run immediately).
|
|
2168
|
-
Integration workflow: list_integration_providers → list_integration_apps (browse) → connect_integration_app (API key) → create_integration_config → add_integration_config_locally → update_agent (add_mcp_servers).
|
|
2363
|
+
Task workflow: list_tasks (project-wide overview) or list_agent_tasks (single agent) → create_agent_task (schedule work) → execute_agent_task (run immediately).
|
|
2364
|
+
Integration workflow: list_integration_providers → if no key, ask user and set_provider_key → list_integration_apps (browse) → connect_integration_app (API key) → create_integration_config → add_integration_config_locally → start_mcp_server → update_agent (add_mcp_servers).
|
|
2169
2365
|
Subscription workflow: list_trigger_providers → list_trigger_types (pick trigger) → list_integration_connections (pick account) → create_subscription (link trigger to agent).
|
|
2170
|
-
Test workflow: create_test (
|
|
2366
|
+
Test workflow: create_test (describe behavior) → run_test (AI picks agent, generates message, judges result) → get_test_results.
|
|
2171
2367
|
Always use list_providers first to check which providers have API keys before creating agents.`,
|
|
2172
2368
|
};
|
|
2173
2369
|
break;
|
package/src/providers.ts
CHANGED
|
@@ -13,7 +13,6 @@ export const PROVIDERS = {
|
|
|
13
13
|
testEndpoint: "https://api.anthropic.com/v1/messages",
|
|
14
14
|
models: [
|
|
15
15
|
{ value: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", recommended: true, input_cost: 3, output_cost: 15, cache_creation_cost: 3.75, cache_read_cost: 0.3 },
|
|
16
|
-
{ value: "claude-sonnet-4-5", label: "Claude Sonnet 4.5", input_cost: 3, output_cost: 15, cache_creation_cost: 3.75, cache_read_cost: 0.3 },
|
|
17
16
|
{ value: "claude-haiku-4-5", label: "Claude Haiku 4.5 (Fast)", input_cost: 0.8, output_cost: 4, cache_creation_cost: 1, cache_read_cost: 0.08 },
|
|
18
17
|
],
|
|
19
18
|
},
|
|
@@ -26,8 +25,7 @@ export const PROVIDERS = {
|
|
|
26
25
|
docsUrl: "https://platform.openai.com/api-keys",
|
|
27
26
|
testEndpoint: "https://api.openai.com/v1/models",
|
|
28
27
|
models: [
|
|
29
|
-
{ value: "gpt-
|
|
30
|
-
{ value: "gpt-4o-mini", label: "GPT-4o Mini (Fast)", input_cost: 0.15, output_cost: 0.6 },
|
|
28
|
+
{ value: "gpt-5.4", label: "GPT-5.4 (Latest)", recommended: true, input_cost: 2.5, output_cost: 10 },
|
|
31
29
|
],
|
|
32
30
|
},
|
|
33
31
|
groq: {
|
|
@@ -52,8 +50,10 @@ export const PROVIDERS = {
|
|
|
52
50
|
docsUrl: "https://aistudio.google.com/app/apikey",
|
|
53
51
|
testEndpoint: "https://generativelanguage.googleapis.com/v1/models",
|
|
54
52
|
models: [
|
|
55
|
-
{ value: "gemini-3-pro-preview", label: "Gemini 3 Pro Preview (Latest)", recommended: true, input_cost: 2, output_cost: 12 },
|
|
56
|
-
{ value: "gemini-3-
|
|
53
|
+
{ value: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro Preview (Latest)", recommended: true, input_cost: 2, output_cost: 12 },
|
|
54
|
+
{ value: "gemini-3-pro-preview", label: "Gemini 3 Pro Preview", input_cost: 2, output_cost: 12 },
|
|
55
|
+
{ value: "gemini-3.1-flash-lite-preview", label: "Gemini 3.1 Flash Lite Preview (Fast)", input_cost: 0.25, output_cost: 1.5 },
|
|
56
|
+
{ value: "gemini-3-flash-preview", label: "Gemini 3 Flash Preview", input_cost: 0.5, output_cost: 3 },
|
|
57
57
|
],
|
|
58
58
|
},
|
|
59
59
|
xai: {
|
|
@@ -126,6 +126,20 @@ export const PROVIDERS = {
|
|
|
126
126
|
{ value: "venice-uncensored", label: "Venice Uncensored 1.1", input_cost: 0.2, output_cost: 0.9 },
|
|
127
127
|
],
|
|
128
128
|
},
|
|
129
|
+
cerebras: {
|
|
130
|
+
id: "cerebras",
|
|
131
|
+
name: "Cerebras",
|
|
132
|
+
displayName: "Cerebras",
|
|
133
|
+
type: "llm" as const,
|
|
134
|
+
envVar: "CEREBRAS_API_KEY",
|
|
135
|
+
docsUrl: "https://cloud.cerebras.ai/",
|
|
136
|
+
testEndpoint: "https://api.cerebras.ai/v1/models",
|
|
137
|
+
models: [
|
|
138
|
+
{ value: "gpt-oss-120b", label: "GPT-OSS 120B", recommended: true, input_cost: 0.2, output_cost: 1 },
|
|
139
|
+
{ value: "llama-4-scout-17b-16e-instruct", label: "Llama 4 Scout 17B (Fast)", input_cost: 0.05, output_cost: 0.25 },
|
|
140
|
+
{ value: "llama3.3-70b", label: "Llama 3.3 70B", input_cost: 0.1, output_cost: 0.5 },
|
|
141
|
+
],
|
|
142
|
+
},
|
|
129
143
|
ollama: {
|
|
130
144
|
id: "ollama",
|
|
131
145
|
name: "Ollama",
|
|
@@ -187,6 +201,110 @@ export const PROVIDERS = {
|
|
|
187
201
|
isLocal: true,
|
|
188
202
|
models: [],
|
|
189
203
|
},
|
|
204
|
+
// Voice Providers
|
|
205
|
+
elevenlabs: {
|
|
206
|
+
id: "elevenlabs",
|
|
207
|
+
name: "ElevenLabs",
|
|
208
|
+
displayName: "ElevenLabs",
|
|
209
|
+
type: "voice" as const,
|
|
210
|
+
envVar: "ELEVENLABS_API_KEY",
|
|
211
|
+
docsUrl: "https://elevenlabs.io/app/settings/api-keys",
|
|
212
|
+
description: "Speech-to-text and text-to-speech for voice conversations",
|
|
213
|
+
models: [],
|
|
214
|
+
},
|
|
215
|
+
deepgram: {
|
|
216
|
+
id: "deepgram",
|
|
217
|
+
name: "Deepgram",
|
|
218
|
+
displayName: "Deepgram",
|
|
219
|
+
type: "voice" as const,
|
|
220
|
+
envVar: "DEEPGRAM_API_KEY",
|
|
221
|
+
docsUrl: "https://console.deepgram.com/",
|
|
222
|
+
description: "Fast speech-to-text and text-to-speech with low latency",
|
|
223
|
+
models: [],
|
|
224
|
+
},
|
|
225
|
+
// Local Voice Providers
|
|
226
|
+
speaches: {
|
|
227
|
+
id: "speaches",
|
|
228
|
+
name: "Speaches",
|
|
229
|
+
displayName: "Speaches (Local)",
|
|
230
|
+
type: "voice" as const,
|
|
231
|
+
voiceSubtype: "both" as const,
|
|
232
|
+
envVar: "SPEACHES_BASE_URL",
|
|
233
|
+
docsUrl: "https://github.com/speaches-ai/speaches",
|
|
234
|
+
description: "Local STT + TTS server with OpenAI-compatible API",
|
|
235
|
+
isLocal: true,
|
|
236
|
+
defaultBaseUrl: "http://localhost:8000",
|
|
237
|
+
models: [
|
|
238
|
+
{ value: "Systran/faster-whisper-large-v3", label: "Whisper Large V3 (STT)", recommended: true, input_cost: 0, output_cost: 0 },
|
|
239
|
+
{ value: "Systran/faster-whisper-medium", label: "Whisper Medium (STT)", input_cost: 0, output_cost: 0 },
|
|
240
|
+
{ value: "hexgrad/Kokoro-82M", label: "Kokoro 82M (TTS)", recommended: true, input_cost: 0, output_cost: 0 },
|
|
241
|
+
],
|
|
242
|
+
},
|
|
243
|
+
whisper_cpp: {
|
|
244
|
+
id: "whisper_cpp",
|
|
245
|
+
name: "Whisper.cpp",
|
|
246
|
+
displayName: "Whisper.cpp (Local)",
|
|
247
|
+
type: "voice" as const,
|
|
248
|
+
voiceSubtype: "stt" as const,
|
|
249
|
+
envVar: "WHISPER_CPP_BASE_URL",
|
|
250
|
+
docsUrl: "https://github.com/ggerganov/whisper.cpp",
|
|
251
|
+
description: "High-performance local speech-to-text",
|
|
252
|
+
isLocal: true,
|
|
253
|
+
defaultBaseUrl: "http://localhost:8080",
|
|
254
|
+
models: [
|
|
255
|
+
{ value: "large-v3", label: "Large V3", recommended: true, input_cost: 0, output_cost: 0 },
|
|
256
|
+
{ value: "large-v3-turbo", label: "Large V3 Turbo (Fast)", input_cost: 0, output_cost: 0 },
|
|
257
|
+
{ value: "medium", label: "Medium", input_cost: 0, output_cost: 0 },
|
|
258
|
+
{ value: "small", label: "Small (Fast)", input_cost: 0, output_cost: 0 },
|
|
259
|
+
{ value: "base", label: "Base (Fastest)", input_cost: 0, output_cost: 0 },
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
kokoro: {
|
|
263
|
+
id: "kokoro",
|
|
264
|
+
name: "Kokoro",
|
|
265
|
+
displayName: "Kokoro (Local)",
|
|
266
|
+
type: "voice" as const,
|
|
267
|
+
voiceSubtype: "tts" as const,
|
|
268
|
+
envVar: "KOKORO_BASE_URL",
|
|
269
|
+
docsUrl: "https://github.com/remsky/Kokoro-FastAPI",
|
|
270
|
+
description: "High-quality local text-to-speech, CPU-only, 82M params",
|
|
271
|
+
isLocal: true,
|
|
272
|
+
defaultBaseUrl: "http://localhost:8880",
|
|
273
|
+
models: [
|
|
274
|
+
{ value: "kokoro", label: "Kokoro 82M", recommended: true, input_cost: 0, output_cost: 0 },
|
|
275
|
+
],
|
|
276
|
+
},
|
|
277
|
+
piper: {
|
|
278
|
+
id: "piper",
|
|
279
|
+
name: "Piper",
|
|
280
|
+
displayName: "Piper (Local)",
|
|
281
|
+
type: "voice" as const,
|
|
282
|
+
voiceSubtype: "tts" as const,
|
|
283
|
+
envVar: "PIPER_BASE_URL",
|
|
284
|
+
docsUrl: "https://github.com/rhasspy/piper",
|
|
285
|
+
description: "Fast local text-to-speech, runs on any hardware",
|
|
286
|
+
isLocal: true,
|
|
287
|
+
defaultBaseUrl: "http://localhost:5000",
|
|
288
|
+
models: [
|
|
289
|
+
{ value: "en_US-amy-medium", label: "Amy (Medium)", recommended: true, input_cost: 0, output_cost: 0 },
|
|
290
|
+
{ value: "en_US-lessac-medium", label: "Lessac (Medium)", input_cost: 0, output_cost: 0 },
|
|
291
|
+
],
|
|
292
|
+
},
|
|
293
|
+
fish_speech: {
|
|
294
|
+
id: "fish_speech",
|
|
295
|
+
name: "Fish Speech",
|
|
296
|
+
displayName: "Fish Speech (Local)",
|
|
297
|
+
type: "voice" as const,
|
|
298
|
+
voiceSubtype: "tts" as const,
|
|
299
|
+
envVar: "FISH_SPEECH_BASE_URL",
|
|
300
|
+
docsUrl: "https://github.com/fishaudio/fish-speech",
|
|
301
|
+
description: "High-quality local TTS with voice cloning",
|
|
302
|
+
isLocal: true,
|
|
303
|
+
defaultBaseUrl: "http://localhost:8180",
|
|
304
|
+
models: [
|
|
305
|
+
{ value: "fish-speech-1.5", label: "Fish Speech 1.5", recommended: true, input_cost: 0, output_cost: 0 },
|
|
306
|
+
],
|
|
307
|
+
},
|
|
190
308
|
// MCP Integrations
|
|
191
309
|
composio: {
|
|
192
310
|
id: "composio",
|
|
@@ -473,5 +591,7 @@ export function getProvidersWithStatus() {
|
|
|
473
591
|
keyHint: keyStatuses.get(provider.id)?.key_hint || null,
|
|
474
592
|
isValid: keyStatuses.get(provider.id)?.is_valid ?? null,
|
|
475
593
|
isLocal: "isLocal" in provider ? provider.isLocal : undefined,
|
|
594
|
+
voiceSubtype: "voiceSubtype" in provider ? provider.voiceSubtype : undefined,
|
|
595
|
+
defaultBaseUrl: "defaultBaseUrl" in provider ? provider.defaultBaseUrl : undefined,
|
|
476
596
|
}));
|
|
477
597
|
}
|