apteva 0.4.53 → 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.jhb45d7r.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.9sryp183.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 +273 -44
- 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/api/telemetry.ts +0 -7
- 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 +54 -46
- package/src/web/components/tests/TestsPage.tsx +91 -76
- package/src/web/context/TelemetryContext.tsx +4 -1
- 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.sw9p594m.js +0 -3
- package/dist/ApiDocsPage.90e03bz7.js +0 -4
- package/dist/App.3vnrera5.js +0 -4
- package/dist/App.94x6mh7f.js +0 -20
- package/dist/App.9t1zc5r7.js +0 -53
- package/dist/App.p7jjw1zf.js +0 -4
- package/dist/App.pfbdzrhh.js +0 -4
- package/dist/App.pse0pzar.js +0 -4
- package/dist/App.r43t58w6.js +0 -221
- package/dist/App.stgng5bx.js +0 -13
- package/dist/App.tm3k7h4b.js +0 -4
- package/dist/App.vkg121c6.js +0 -4
- package/dist/App.xva0tfzh.js +0 -4
- package/dist/App.ysxy7akk.js +0 -61
- package/dist/App.yzkh4gq2.js +0 -4
- package/dist/ConnectionsPage.q5f9fd37.js +0 -3
- package/dist/McpPage.f3ccrezb.js +0 -3
- package/dist/SettingsPage.zmzm1pp6.js +0 -3
- package/dist/SkillsPage.whxnez67.js +0 -3
- package/dist/TasksPage.zp4jfevw.js +0 -3
- package/dist/TelemetryPage.an0ky78c.js +0 -3
- package/dist/TestsPage.18krj0d1.js +0 -3
- package/dist/ThreadsPage.nnphgy98.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,67 @@ 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
|
+
},
|
|
881
|
+
// Analytics
|
|
882
|
+
{
|
|
883
|
+
name: "get_analytics",
|
|
884
|
+
description: "Get analytics summary: total events, LLM calls, tool calls, errors, token usage (input/output/cache/reasoning), and cost. Optionally filter by agent, project, or time range.",
|
|
885
|
+
inputSchema: {
|
|
886
|
+
type: "object",
|
|
887
|
+
properties: {
|
|
888
|
+
agent_id: { type: "string", description: "Filter by agent ID (optional)" },
|
|
889
|
+
project_id: { type: "string", description: "Filter by project ID (optional)" },
|
|
890
|
+
since: { type: "string", description: "ISO timestamp — only include events after this time (optional)" },
|
|
891
|
+
},
|
|
892
|
+
},
|
|
893
|
+
},
|
|
894
|
+
{
|
|
895
|
+
name: "get_usage_by_agent",
|
|
896
|
+
description: "Get token usage and cost breakdown per agent. Returns LLM calls, tool calls, input/output/cache/reasoning tokens, errors, and cost for each agent.",
|
|
897
|
+
inputSchema: {
|
|
898
|
+
type: "object",
|
|
899
|
+
properties: {
|
|
900
|
+
project_id: { type: "string", description: "Filter by project ID (optional)" },
|
|
901
|
+
since: { type: "string", description: "ISO timestamp — only include events after this time (optional)" },
|
|
902
|
+
},
|
|
903
|
+
},
|
|
904
|
+
},
|
|
831
905
|
];
|
|
832
906
|
|
|
833
907
|
// Project-only tools — hidden entirely when PROJECTS_ENABLED is not set
|
|
@@ -867,15 +941,33 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
867
941
|
: AgentDB.findAll();
|
|
868
942
|
// Exclude meta agent from list
|
|
869
943
|
const filtered = agents.filter(a => a.id !== META_AGENT_ID);
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
944
|
+
const mcpIds = [...new Set(filtered.flatMap(a => a.mcp_servers || []))];
|
|
945
|
+
const skillIds = [...new Set(filtered.flatMap(a => a.skills || []))];
|
|
946
|
+
const mcpMap = McpServerDB.findByIdsLight(mcpIds);
|
|
947
|
+
const skillMap = SkillDB.findByIds(skillIds);
|
|
948
|
+
const result = filtered.map(a => {
|
|
949
|
+
const mcpNames = (a.mcp_servers || [])
|
|
950
|
+
.map(id => mcpMap.get(id)?.name)
|
|
951
|
+
.filter(Boolean);
|
|
952
|
+
const skillNames = (a.skills || [])
|
|
953
|
+
.map(id => skillMap.get(id)?.name)
|
|
954
|
+
.filter(Boolean);
|
|
955
|
+
const enabledFeatures = Object.entries(a.features || {})
|
|
956
|
+
.filter(([, v]) => v === true || (typeof v === "object" && v !== null && (v as any).enabled))
|
|
957
|
+
.map(([k]) => k);
|
|
958
|
+
return {
|
|
959
|
+
id: a.id,
|
|
960
|
+
name: a.name,
|
|
961
|
+
provider: a.provider,
|
|
962
|
+
model: a.model,
|
|
963
|
+
status: a.status,
|
|
964
|
+
projectId: a.project_id,
|
|
965
|
+
features: enabledFeatures,
|
|
966
|
+
mcpServers: mcpNames,
|
|
967
|
+
skills: skillNames,
|
|
968
|
+
systemPrompt: a.system_prompt?.slice(0, 200) + (a.system_prompt && a.system_prompt.length > 200 ? "..." : ""),
|
|
969
|
+
};
|
|
970
|
+
});
|
|
879
971
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
880
972
|
}
|
|
881
973
|
|
|
@@ -910,7 +1002,7 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
910
1002
|
mcp: args.features?.mcp ?? false,
|
|
911
1003
|
realtime: false,
|
|
912
1004
|
files: args.features?.files ?? false,
|
|
913
|
-
agents: false,
|
|
1005
|
+
agents: args.features?.agents ? { enabled: true, group: args.project_id || undefined } : false,
|
|
914
1006
|
},
|
|
915
1007
|
mcp_servers: [],
|
|
916
1008
|
skills: [],
|
|
@@ -933,7 +1025,14 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
933
1025
|
if (args.system_prompt !== undefined) updates.system_prompt = args.system_prompt;
|
|
934
1026
|
if (args.project_id !== undefined) updates.project_id = args.project_id;
|
|
935
1027
|
if (args.features !== undefined) {
|
|
936
|
-
|
|
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;
|
|
937
1036
|
}
|
|
938
1037
|
|
|
939
1038
|
// Skills: set, add, or remove
|
|
@@ -1312,6 +1411,42 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1312
1411
|
}
|
|
1313
1412
|
}
|
|
1314
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
|
+
|
|
1315
1450
|
case "list_agent_tasks": {
|
|
1316
1451
|
const agent = AgentDB.findById(args.agent_id);
|
|
1317
1452
|
if (!agent) return { content: [{ type: "text", text: `Agent not found: ${args.agent_id}` }], isError: true };
|
|
@@ -1491,37 +1626,44 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1491
1626
|
case "list_tests": {
|
|
1492
1627
|
const tests = TestCaseDB.findAll(args.project_id);
|
|
1493
1628
|
const result = tests.map(tc => {
|
|
1494
|
-
const agent = AgentDB.findById(tc.agent_id);
|
|
1629
|
+
const agent = tc.agent_id ? AgentDB.findById(tc.agent_id) : null;
|
|
1495
1630
|
const lastRun = TestRunDB.getLatestByTestCase(tc.id);
|
|
1496
1631
|
return {
|
|
1497
1632
|
id: tc.id,
|
|
1498
1633
|
name: tc.name,
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
eval_criteria: tc.eval_criteria,
|
|
1503
|
-
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"),
|
|
1504
1637
|
last_status: lastRun?.status || null,
|
|
1638
|
+
last_score: lastRun?.score || null,
|
|
1505
1639
|
last_reasoning: lastRun?.judge_reasoning || null,
|
|
1640
|
+
last_selected_agent: lastRun?.selected_agent_name || null,
|
|
1506
1641
|
};
|
|
1507
1642
|
});
|
|
1508
1643
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1509
1644
|
}
|
|
1510
1645
|
|
|
1511
1646
|
case "create_test": {
|
|
1512
|
-
|
|
1513
|
-
if (
|
|
1514
|
-
|
|
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
|
+
}
|
|
1515
1653
|
}
|
|
1516
1654
|
const tc = TestCaseDB.create({
|
|
1517
1655
|
name: args.name,
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
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,
|
|
1523
1662
|
});
|
|
1524
|
-
|
|
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.` }] };
|
|
1525
1667
|
}
|
|
1526
1668
|
|
|
1527
1669
|
case "run_test": {
|
|
@@ -1530,8 +1672,10 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1530
1672
|
return { content: [{ type: "text", text: `Test not found: ${args.test_id}` }], isError: true };
|
|
1531
1673
|
}
|
|
1532
1674
|
const result = await runTest(tc);
|
|
1533
|
-
const
|
|
1534
|
-
|
|
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"}` }] };
|
|
1535
1679
|
}
|
|
1536
1680
|
|
|
1537
1681
|
case "run_all_tests": {
|
|
@@ -1555,8 +1699,11 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
1555
1699
|
const result = runs.map(r => ({
|
|
1556
1700
|
id: r.id,
|
|
1557
1701
|
status: r.status,
|
|
1702
|
+
score: r.score,
|
|
1558
1703
|
duration_ms: r.duration_ms,
|
|
1559
1704
|
judge_reasoning: r.judge_reasoning,
|
|
1705
|
+
selected_agent: r.selected_agent_name || null,
|
|
1706
|
+
generated_message: r.generated_message || null,
|
|
1560
1707
|
error: r.error,
|
|
1561
1708
|
created_at: r.created_at,
|
|
1562
1709
|
}));
|
|
@@ -2035,6 +2182,87 @@ async function executeTool(name: string, args: Record<string, any>): Promise<{ c
|
|
|
2035
2182
|
return { content: [{ type: "text", text: `Local add not supported for provider: ${providerId}` }], isError: true };
|
|
2036
2183
|
}
|
|
2037
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
|
+
|
|
2243
|
+
case "get_analytics": {
|
|
2244
|
+
const stats = TelemetryDB.getStats({
|
|
2245
|
+
agentId: args.agent_id || undefined,
|
|
2246
|
+
projectId: args.project_id || undefined,
|
|
2247
|
+
since: args.since || undefined,
|
|
2248
|
+
});
|
|
2249
|
+
return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] };
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
case "get_usage_by_agent": {
|
|
2253
|
+
const usage = TelemetryDB.getUsage({
|
|
2254
|
+
project_id: args.project_id || undefined,
|
|
2255
|
+
since: args.since || undefined,
|
|
2256
|
+
group_by: "agent",
|
|
2257
|
+
});
|
|
2258
|
+
// Enrich with agent names
|
|
2259
|
+
const enriched = usage.map(u => {
|
|
2260
|
+
const agent = AgentDB.findById(u.agent_id || "");
|
|
2261
|
+
return { ...u, agent_name: agent?.name || u.agent_id };
|
|
2262
|
+
});
|
|
2263
|
+
return { content: [{ type: "text", text: JSON.stringify(enriched, null, 2) }] };
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2038
2266
|
default:
|
|
2039
2267
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
2040
2268
|
}
|
|
@@ -2085,23 +2313,24 @@ export async function handlePlatformMcpRequest(req: Request): Promise<Response>
|
|
|
2085
2313
|
instructions: `This MCP server controls the Apteva AI agent management platform.
|
|
2086
2314
|
|
|
2087
2315
|
You can manage:
|
|
2088
|
-
- 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).
|
|
2089
|
-
- 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.
|
|
2090
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).
|
|
2091
|
-
- 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.
|
|
2092
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.
|
|
2093
|
-
-
|
|
2094
|
-
-
|
|
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.
|
|
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.
|
|
2095
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.
|
|
2096
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.
|
|
2097
2326
|
|
|
2098
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.
|
|
2099
2328
|
|
|
2100
2329
|
Typical workflow: list_providers → create_agent → update_agent (add_mcp_servers/add_skills) → start_agent.
|
|
2101
|
-
Task workflow: list_agent_tasks → create_agent_task (schedule work) → execute_agent_task (run immediately).
|
|
2102
|
-
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).
|
|
2103
2332
|
Subscription workflow: list_trigger_providers → list_trigger_types (pick trigger) → list_integration_connections (pick account) → create_subscription (link trigger to agent).
|
|
2104
|
-
Test workflow: create_test (
|
|
2333
|
+
Test workflow: create_test (describe behavior) → run_test (AI picks agent, generates message, judges result) → get_test_results.
|
|
2105
2334
|
Always use list_providers first to check which providers have API keys before creating agents.`,
|
|
2106
2335
|
};
|
|
2107
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
|
}
|