apteva 0.4.54 → 0.4.56
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 +198 -35
- 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
|
@@ -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
|
},
|
|
@@ -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,7 +1002,7 @@ 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: [],
|
|
@@ -975,7 +1025,14 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
975
1025
|
if (args.system_prompt !== undefined) updates.system_prompt = args.system_prompt;
|
|
976
1026
|
if (args.project_id !== undefined) updates.project_id = args.project_id;
|
|
977
1027
|
if (args.features !== undefined) {
|
|
978
|
-
|
|
1028
|
+
const mergedFeatures = { ...agent.features, ...args.features };
|
|
1029
|
+
// Convert agents boolean to MultiAgentConfig
|
|
1030
|
+
if (typeof mergedFeatures.agents === "boolean") {
|
|
1031
|
+
mergedFeatures.agents = mergedFeatures.agents
|
|
1032
|
+
? { enabled: true, group: args.project_id || agent.project_id || undefined }
|
|
1033
|
+
: false;
|
|
1034
|
+
}
|
|
1035
|
+
updates.features = mergedFeatures;
|
|
979
1036
|
}
|
|
980
1037
|
|
|
981
1038
|
// Skills: set, add, or remove
|
|
@@ -1354,6 +1411,42 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1354
1411
|
}
|
|
1355
1412
|
}
|
|
1356
1413
|
|
|
1414
|
+
case "list_tasks": {
|
|
1415
|
+
const status = args.status || "all";
|
|
1416
|
+
let runningAgents = AgentDB.findAll().filter(a => a.status === "running" && a.port);
|
|
1417
|
+
|
|
1418
|
+
if (args.project_id === "unassigned") {
|
|
1419
|
+
runningAgents = runningAgents.filter(a => !a.project_id);
|
|
1420
|
+
} else if (args.project_id) {
|
|
1421
|
+
runningAgents = runningAgents.filter(a => a.project_id === args.project_id);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
const allTasks: any[] = [];
|
|
1425
|
+
const results = await Promise.all(
|
|
1426
|
+
runningAgents.map(async (agent) => {
|
|
1427
|
+
try {
|
|
1428
|
+
const data = await fetchFromAgent(agent.id, agent.port!, `/tasks?status=${status}`);
|
|
1429
|
+
return { agent, tasks: data?.tasks || [] };
|
|
1430
|
+
} catch {
|
|
1431
|
+
return { agent, tasks: [] };
|
|
1432
|
+
}
|
|
1433
|
+
})
|
|
1434
|
+
);
|
|
1435
|
+
|
|
1436
|
+
for (const { agent, tasks } of results) {
|
|
1437
|
+
for (const task of tasks) {
|
|
1438
|
+
allTasks.push({
|
|
1439
|
+
id: task.id, title: task.title, type: task.type, status: task.status, priority: task.priority,
|
|
1440
|
+
recurrence: task.recurrence, next_run: task.next_run, execute_at: task.execute_at, created_at: task.created_at,
|
|
1441
|
+
agentId: agent.id, agentName: agent.name,
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
allTasks.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
1447
|
+
return { content: [{ type: "text", text: JSON.stringify({ tasks: allTasks, count: allTasks.length }, null, 2) }] };
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1357
1450
|
case "list_agent_tasks": {
|
|
1358
1451
|
const agent = AgentDB.findById(args.agent_id);
|
|
1359
1452
|
if (!agent) return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
@@ -1533,37 +1626,44 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1533
1626
|
case "list_tests": {
|
|
1534
1627
|
const tests = TestCaseDB.findAll(args.project_id);
|
|
1535
1628
|
const result = tests.map(tc => {
|
|
1536
|
-
const agent = AgentDB.findById(tc.agent_id);
|
|
1629
|
+
const agent = tc.agent_id ? AgentDB.findById(tc.agent_id) : null;
|
|
1537
1630
|
const lastRun = TestRunDB.getLatestByTestCase(tc.id);
|
|
1538
1631
|
return {
|
|
1539
1632
|
id: tc.id,
|
|
1540
1633
|
name: tc.name,
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
eval_criteria: tc.eval_criteria,
|
|
1545
|
-
timeout_ms: tc.timeout_ms,
|
|
1634
|
+
behavior: tc.behavior || null,
|
|
1635
|
+
agent_id: tc.agent_id || null,
|
|
1636
|
+
agent_name: agent?.name || (tc.agent_id ? "Unknown" : "Auto-select"),
|
|
1546
1637
|
last_status: lastRun?.status || null,
|
|
1638
|
+
last_score: lastRun?.score || null,
|
|
1547
1639
|
last_reasoning: lastRun?.judge_reasoning || null,
|
|
1640
|
+
last_selected_agent: lastRun?.selected_agent_name || null,
|
|
1548
1641
|
};
|
|
1549
1642
|
});
|
|
1550
1643
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1551
1644
|
}
|
|
1552
1645
|
|
|
1553
1646
|
case "create_test": {
|
|
1554
|
-
|
|
1555
|
-
if (
|
|
1556
|
-
|
|
1647
|
+
// Validate agent if explicitly provided
|
|
1648
|
+
if (args.agent_id) {
|
|
1649
|
+
const agent = AgentDB.findById(args.agent_id);
|
|
1650
|
+
if (!agent) {
|
|
1651
|
+
return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
1652
|
+
}
|
|
1557
1653
|
}
|
|
1558
1654
|
const tc = TestCaseDB.create({
|
|
1559
1655
|
name: args.name,
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
timeout_ms: args.timeout_ms,
|
|
1656
|
+
behavior: args.behavior,
|
|
1657
|
+
agent_id: args.agent_id || null,
|
|
1658
|
+
input_message: null,
|
|
1659
|
+
eval_criteria: args.behavior,
|
|
1660
|
+
timeout_ms: args.timeout_ms || 300000,
|
|
1661
|
+
project_id: args.project_id || null,
|
|
1565
1662
|
});
|
|
1566
|
-
|
|
1663
|
+
const agentNote = args.agent_id
|
|
1664
|
+
? `pinned to agent "${AgentDB.findById(args.agent_id)?.name}"`
|
|
1665
|
+
: "AI will auto-select the best agent";
|
|
1666
|
+
return { content: [{ type: "text", text: `Test "${tc.name}" created (id: ${tc.id}). ${agentNote}. Use run_test to execute it.` }] };
|
|
1567
1667
|
}
|
|
1568
1668
|
|
|
1569
1669
|
case "run_test": {
|
|
@@ -1572,8 +1672,10 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1572
1672
|
return { content: [{ type: "text", text: `Test not found: ${args.test_id}` }], isError: true };
|
|
1573
1673
|
}
|
|
1574
1674
|
const result = await runTest(tc);
|
|
1575
|
-
const
|
|
1576
|
-
|
|
1675
|
+
const agentName = result.selected_agent_name || (tc.agent_id ? AgentDB.findById(tc.agent_id)?.name : null) || "unknown";
|
|
1676
|
+
const score = result.score != null ? ` (score: ${result.score}/10)` : "";
|
|
1677
|
+
const duration = result.duration_ms ? ` in ${(result.duration_ms / 1000).toFixed(1)}s` : "";
|
|
1678
|
+
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
1679
|
}
|
|
1578
1680
|
|
|
1579
1681
|
case "run_all_tests": {
|
|
@@ -1597,8 +1699,11 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1597
1699
|
const result = runs.map(r => ({
|
|
1598
1700
|
id: r.id,
|
|
1599
1701
|
status: r.status,
|
|
1702
|
+
score: r.score,
|
|
1600
1703
|
duration_ms: r.duration_ms,
|
|
1601
1704
|
judge_reasoning: r.judge_reasoning,
|
|
1705
|
+
selected_agent: r.selected_agent_name || null,
|
|
1706
|
+
generated_message: r.generated_message || null,
|
|
1602
1707
|
error: r.error,
|
|
1603
1708
|
created_at: r.created_at,
|
|
1604
1709
|
}));
|
|
@@ -2077,6 +2182,64 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
2077
2182
|
return { content: [{ type: "text", text: `Local add not supported for provider: ${providerId}` }], isError: true };
|
|
2078
2183
|
}
|
|
2079
2184
|
|
|
2185
|
+
case "set_provider_key": {
|
|
2186
|
+
const providerId = args.provider_id;
|
|
2187
|
+
if (!PROVIDERS[providerId as keyof typeof PROVIDERS]) {
|
|
2188
|
+
return { content: [{ type: "text", text: `Unknown provider: ${providerId}. Use list_providers or list_integration_providers to see available providers.` }], isError: true };
|
|
2189
|
+
}
|
|
2190
|
+
if (!args.key) {
|
|
2191
|
+
return { content: [{ type: "text", text: "API key is required" }], isError: true };
|
|
2192
|
+
}
|
|
2193
|
+
const result = await ProviderKeys.save(providerId, args.key, args.project_id || null, null);
|
|
2194
|
+
if (!result.success) {
|
|
2195
|
+
return { content: [{ type: "text", text: `Failed to save key: ${result.error}` }], isError: true };
|
|
2196
|
+
}
|
|
2197
|
+
const provider = PROVIDERS[providerId as keyof typeof PROVIDERS];
|
|
2198
|
+
return { content: [{ type: "text", text: `API key saved for ${provider.name}.` }] };
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
case "start_mcp_server": {
|
|
2202
|
+
const server = McpServerDB.findById(args.server_id);
|
|
2203
|
+
if (!server) {
|
|
2204
|
+
return { content: [{ type: "text", text: `MCP server not found: ${args.server_id}` }], isError: true };
|
|
2205
|
+
}
|
|
2206
|
+
if (server.status === "running") {
|
|
2207
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" is already running` }] };
|
|
2208
|
+
}
|
|
2209
|
+
try {
|
|
2210
|
+
const port = process.env.PORT || "4280";
|
|
2211
|
+
const res = await fetch(`http://localhost:${port}/api/mcp/servers/${args.server_id}/start`, { method: "POST" });
|
|
2212
|
+
const data = await res.json() as Record<string, unknown>;
|
|
2213
|
+
if (!res.ok) {
|
|
2214
|
+
return { content: [{ type: "text", text: `Failed to start: ${data.error || "unknown error"}` }], isError: true };
|
|
2215
|
+
}
|
|
2216
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" started. ${data.message || ""}` }] };
|
|
2217
|
+
} catch (err) {
|
|
2218
|
+
return { content: [{ type: "text", text: `Failed to start MCP server: ${err}` }], isError: true };
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
case "stop_mcp_server": {
|
|
2223
|
+
const server = McpServerDB.findById(args.server_id);
|
|
2224
|
+
if (!server) {
|
|
2225
|
+
return { content: [{ type: "text", text: `MCP server not found: ${args.server_id}` }], isError: true };
|
|
2226
|
+
}
|
|
2227
|
+
if (server.status !== "running") {
|
|
2228
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" is not running` }] };
|
|
2229
|
+
}
|
|
2230
|
+
try {
|
|
2231
|
+
const port = process.env.PORT || "4280";
|
|
2232
|
+
const res = await fetch(`http://localhost:${port}/api/mcp/servers/${args.server_id}/stop`, { method: "POST" });
|
|
2233
|
+
const data = await res.json() as Record<string, unknown>;
|
|
2234
|
+
if (!res.ok) {
|
|
2235
|
+
return { content: [{ type: "text", text: `Failed to stop: ${data.error || "unknown error"}` }], isError: true };
|
|
2236
|
+
}
|
|
2237
|
+
return { content: [{ type: "text", text: `MCP server "${server.name}" stopped.` }] };
|
|
2238
|
+
} catch (err) {
|
|
2239
|
+
return { content: [{ type: "text", text: `Failed to stop MCP server: ${err}` }], isError: true };
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2080
2243
|
case "get_analytics": {
|
|
2081
2244
|
const stats = TelemetryDB.getStats({
|
|
2082
2245
|
agentId: args.agent_id || undefined,
|
|
@@ -2150,24 +2313,24 @@ export async function handlePlatformMcpRequest(req: Request): Promise<Response>
|
|
|
2150
2313
|
instructions: `This MCP server controls the Apteva AI agent management platform.
|
|
2151
2314
|
|
|
2152
2315
|
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
|
|
2316
|
+
- 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).
|
|
2317
|
+
- 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
2318
|
- 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.
|
|
2319
|
+
- 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
2320
|
- 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
2321
|
- 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
|
|
2322
|
+
- 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.
|
|
2323
|
+
- 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
2324
|
- 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
2325
|
- 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
2326
|
|
|
2164
2327
|
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
2328
|
|
|
2166
2329
|
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).
|
|
2330
|
+
Task workflow: list_tasks (project-wide overview) or list_agent_tasks (single agent) → create_agent_task (schedule work) → execute_agent_task (run immediately).
|
|
2331
|
+
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
2332
|
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 (
|
|
2333
|
+
Test workflow: create_test (describe behavior) → run_test (AI picks agent, generates message, judges result) → get_test_results.
|
|
2171
2334
|
Always use list_providers first to check which providers have API keys before creating agents.`,
|
|
2172
2335
|
};
|
|
2173
2336
|
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
|
}
|