apteva 0.4.12 → 0.4.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.jdzxkzm1.js +228 -0
- package/dist/index.html +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/auth/middleware.ts +42 -26
- package/src/crypto.ts +2 -2
- package/src/db-tests.ts +174 -0
- package/src/db.ts +302 -5
- package/src/integrations/agentdojo.ts +168 -42
- package/src/mcp-client.ts +15 -9
- package/src/mcp-platform.ts +160 -0
- package/src/openapi.ts +416 -21
- package/src/routes/api/agent-utils.ts +2 -2
- package/src/routes/api/api-keys.ts +95 -0
- package/src/routes/api/mcp.ts +2 -2
- package/src/routes/api/system.ts +10 -1
- package/src/routes/api/tests.ts +148 -0
- package/src/routes/api.ts +4 -0
- package/src/server.ts +2 -1
- package/src/test-runner.ts +598 -0
- package/src/web/App.tsx +23 -10
- package/src/web/components/agents/AgentPanel.tsx +4 -8
- package/src/web/components/common/Icons.tsx +8 -0
- package/src/web/components/dashboard/Dashboard.tsx +2 -4
- package/src/web/components/index.ts +1 -0
- package/src/web/components/layout/Sidebar.tsx +7 -1
- package/src/web/components/settings/SettingsPage.tsx +288 -5
- package/src/web/components/skills/SkillsPage.tsx +1 -1
- package/src/web/components/tasks/TasksPage.tsx +8 -3
- package/src/web/components/telemetry/TelemetryPage.tsx +2 -5
- package/src/web/components/tests/TestsPage.tsx +580 -0
- package/src/web/context/index.ts +1 -1
- package/src/web/types.ts +1 -1
- package/dist/App.9ph8javh.js +0 -228
package/src/openapi.ts
CHANGED
|
@@ -162,6 +162,110 @@ The new access token will be returned and a new refresh token cookie will be set
|
|
|
162
162
|
},
|
|
163
163
|
},
|
|
164
164
|
},
|
|
165
|
+
"/version/update": {
|
|
166
|
+
post: {
|
|
167
|
+
tags: ["System"],
|
|
168
|
+
summary: "Update agent binary",
|
|
169
|
+
description: "Downloads the latest agent binary. Stops all running agents, updates, then restarts them.",
|
|
170
|
+
responses: {
|
|
171
|
+
"200": {
|
|
172
|
+
description: "Update result",
|
|
173
|
+
content: {
|
|
174
|
+
"application/json": {
|
|
175
|
+
schema: {
|
|
176
|
+
type: "object",
|
|
177
|
+
properties: {
|
|
178
|
+
success: { type: "boolean" },
|
|
179
|
+
version: { type: "string" },
|
|
180
|
+
restarted: {
|
|
181
|
+
type: "array",
|
|
182
|
+
items: {
|
|
183
|
+
type: "object",
|
|
184
|
+
properties: {
|
|
185
|
+
id: { type: "string" },
|
|
186
|
+
name: { type: "string" },
|
|
187
|
+
success: { type: "boolean" },
|
|
188
|
+
error: { type: "string", nullable: true },
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
"500": { description: "Update failed" },
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
"/features": {
|
|
202
|
+
get: {
|
|
203
|
+
tags: ["System"],
|
|
204
|
+
summary: "Get feature flags",
|
|
205
|
+
security: [],
|
|
206
|
+
responses: {
|
|
207
|
+
"200": {
|
|
208
|
+
description: "Feature flags",
|
|
209
|
+
content: {
|
|
210
|
+
"application/json": {
|
|
211
|
+
schema: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
projects: { type: "boolean" },
|
|
215
|
+
metaAgent: { type: "boolean" },
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
"/stats": {
|
|
225
|
+
get: {
|
|
226
|
+
tags: ["System"],
|
|
227
|
+
summary: "Get agent statistics",
|
|
228
|
+
responses: {
|
|
229
|
+
"200": {
|
|
230
|
+
description: "Agent statistics",
|
|
231
|
+
content: {
|
|
232
|
+
"application/json": {
|
|
233
|
+
schema: {
|
|
234
|
+
type: "object",
|
|
235
|
+
properties: {
|
|
236
|
+
totalAgents: { type: "integer" },
|
|
237
|
+
runningAgents: { type: "integer" },
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
"/binary": {
|
|
247
|
+
get: {
|
|
248
|
+
tags: ["System"],
|
|
249
|
+
summary: "Get binary status",
|
|
250
|
+
responses: {
|
|
251
|
+
"200": {
|
|
252
|
+
description: "Binary availability info",
|
|
253
|
+
content: {
|
|
254
|
+
"application/json": {
|
|
255
|
+
schema: {
|
|
256
|
+
type: "object",
|
|
257
|
+
properties: {
|
|
258
|
+
exists: { type: "boolean" },
|
|
259
|
+
platform: { type: "string" },
|
|
260
|
+
arch: { type: "string" },
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
},
|
|
165
269
|
"/dashboard": {
|
|
166
270
|
get: {
|
|
167
271
|
tags: ["System"],
|
|
@@ -546,12 +650,39 @@ while (true) {
|
|
|
546
650
|
},
|
|
547
651
|
},
|
|
548
652
|
},
|
|
653
|
+
"/agents/{agentId}/threads/{threadId}/messages": {
|
|
654
|
+
get: {
|
|
655
|
+
tags: ["Threads"],
|
|
656
|
+
summary: "List thread messages",
|
|
657
|
+
description: "Get all messages in a thread. Agent must be running.",
|
|
658
|
+
parameters: [
|
|
659
|
+
{ name: "agentId", in: "path", required: true, schema: { type: "string" } },
|
|
660
|
+
{ name: "threadId", in: "path", required: true, schema: { type: "string" } },
|
|
661
|
+
],
|
|
662
|
+
responses: {
|
|
663
|
+
"200": {
|
|
664
|
+
description: "List of messages",
|
|
665
|
+
content: {
|
|
666
|
+
"application/json": {
|
|
667
|
+
schema: {
|
|
668
|
+
type: "array",
|
|
669
|
+
items: { $ref: "#/components/schemas/Message" },
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
"400": { description: "Agent is not running" },
|
|
675
|
+
"404": { description: "Agent not found" },
|
|
676
|
+
},
|
|
677
|
+
},
|
|
678
|
+
},
|
|
549
679
|
"/agents/{agentId}/memories": {
|
|
550
680
|
get: {
|
|
551
681
|
tags: ["Memory"],
|
|
552
682
|
summary: "List agent memories",
|
|
553
683
|
parameters: [
|
|
554
684
|
{ name: "agentId", in: "path", required: true, schema: { type: "string" } },
|
|
685
|
+
{ name: "thread_id", in: "query", schema: { type: "string" }, description: "Filter memories by thread ID" },
|
|
555
686
|
],
|
|
556
687
|
responses: {
|
|
557
688
|
"200": {
|
|
@@ -592,6 +723,17 @@ while (true) {
|
|
|
592
723
|
"201": { description: "Memory added" },
|
|
593
724
|
},
|
|
594
725
|
},
|
|
726
|
+
delete: {
|
|
727
|
+
tags: ["Memory"],
|
|
728
|
+
summary: "Clear all memories",
|
|
729
|
+
description: "Deletes all memories for the agent.",
|
|
730
|
+
parameters: [
|
|
731
|
+
{ name: "agentId", in: "path", required: true, schema: { type: "string" } },
|
|
732
|
+
],
|
|
733
|
+
responses: {
|
|
734
|
+
"200": { description: "All memories cleared" },
|
|
735
|
+
},
|
|
736
|
+
},
|
|
595
737
|
},
|
|
596
738
|
"/agents/{agentId}/memories/{memoryId}": {
|
|
597
739
|
delete: {
|
|
@@ -612,6 +754,8 @@ while (true) {
|
|
|
612
754
|
summary: "List agent files",
|
|
613
755
|
parameters: [
|
|
614
756
|
{ name: "agentId", in: "path", required: true, schema: { type: "string" } },
|
|
757
|
+
{ name: "thread_id", in: "query", schema: { type: "string" }, description: "Filter files by thread ID" },
|
|
758
|
+
{ name: "limit", in: "query", schema: { type: "integer" }, description: "Max files to return" },
|
|
615
759
|
],
|
|
616
760
|
responses: {
|
|
617
761
|
"200": {
|
|
@@ -706,6 +850,7 @@ while (true) {
|
|
|
706
850
|
summary: "List agent tasks",
|
|
707
851
|
parameters: [
|
|
708
852
|
{ name: "agentId", in: "path", required: true, schema: { type: "string" } },
|
|
853
|
+
{ name: "status", in: "query", schema: { type: "string", enum: ["all", "pending", "running", "completed", "failed", "cancelled"], default: "all" }, description: "Filter tasks by status" },
|
|
709
854
|
],
|
|
710
855
|
responses: {
|
|
711
856
|
"200": {
|
|
@@ -722,6 +867,58 @@ while (true) {
|
|
|
722
867
|
},
|
|
723
868
|
},
|
|
724
869
|
},
|
|
870
|
+
"/agents/{agentId}/api-key": {
|
|
871
|
+
get: {
|
|
872
|
+
tags: ["Agents"],
|
|
873
|
+
summary: "Get agent API key (masked)",
|
|
874
|
+
description: "Returns the agent's API key with most characters masked for security.",
|
|
875
|
+
parameters: [
|
|
876
|
+
{ name: "agentId", in: "path", required: true, schema: { type: "string" } },
|
|
877
|
+
],
|
|
878
|
+
responses: {
|
|
879
|
+
"200": {
|
|
880
|
+
description: "Masked API key",
|
|
881
|
+
content: {
|
|
882
|
+
"application/json": {
|
|
883
|
+
schema: {
|
|
884
|
+
type: "object",
|
|
885
|
+
properties: {
|
|
886
|
+
apiKey: { type: "string", description: "Masked API key (first 8 chars + last 4)" },
|
|
887
|
+
hasKey: { type: "boolean" },
|
|
888
|
+
},
|
|
889
|
+
},
|
|
890
|
+
},
|
|
891
|
+
},
|
|
892
|
+
},
|
|
893
|
+
"404": { description: "Agent or key not found" },
|
|
894
|
+
},
|
|
895
|
+
},
|
|
896
|
+
post: {
|
|
897
|
+
tags: ["Agents"],
|
|
898
|
+
summary: "Regenerate agent API key",
|
|
899
|
+
description: "Generates a new API key for the agent. The full key is only shown once in the response.",
|
|
900
|
+
parameters: [
|
|
901
|
+
{ name: "agentId", in: "path", required: true, schema: { type: "string" } },
|
|
902
|
+
],
|
|
903
|
+
responses: {
|
|
904
|
+
"200": {
|
|
905
|
+
description: "New API key (only time full key is visible)",
|
|
906
|
+
content: {
|
|
907
|
+
"application/json": {
|
|
908
|
+
schema: {
|
|
909
|
+
type: "object",
|
|
910
|
+
properties: {
|
|
911
|
+
apiKey: { type: "string", description: "Full new API key" },
|
|
912
|
+
message: { type: "string" },
|
|
913
|
+
},
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
},
|
|
917
|
+
},
|
|
918
|
+
"404": { description: "Agent not found" },
|
|
919
|
+
},
|
|
920
|
+
},
|
|
921
|
+
},
|
|
725
922
|
"/agents/{agentId}/peers": {
|
|
726
923
|
get: {
|
|
727
924
|
tags: ["Agents"],
|
|
@@ -744,18 +941,64 @@ while (true) {
|
|
|
744
941
|
},
|
|
745
942
|
},
|
|
746
943
|
},
|
|
944
|
+
"/discovery/agents": {
|
|
945
|
+
get: {
|
|
946
|
+
tags: ["Agents"],
|
|
947
|
+
summary: "Central agent discovery",
|
|
948
|
+
description: "Discovery endpoint for agents to find running peers in the same group.",
|
|
949
|
+
parameters: [
|
|
950
|
+
{ name: "group", in: "query", schema: { type: "string" }, description: "Filter by agent group" },
|
|
951
|
+
{ name: "exclude", in: "query", schema: { type: "string" }, description: "Agent ID to exclude from results" },
|
|
952
|
+
],
|
|
953
|
+
responses: {
|
|
954
|
+
"200": {
|
|
955
|
+
description: "List of discoverable agents",
|
|
956
|
+
content: {
|
|
957
|
+
"application/json": {
|
|
958
|
+
schema: {
|
|
959
|
+
type: "object",
|
|
960
|
+
properties: {
|
|
961
|
+
agents: {
|
|
962
|
+
type: "array",
|
|
963
|
+
items: {
|
|
964
|
+
type: "object",
|
|
965
|
+
properties: {
|
|
966
|
+
id: { type: "string" },
|
|
967
|
+
name: { type: "string" },
|
|
968
|
+
url: { type: "string" },
|
|
969
|
+
mode: { type: "string" },
|
|
970
|
+
group: { type: "string", nullable: true },
|
|
971
|
+
},
|
|
972
|
+
},
|
|
973
|
+
},
|
|
974
|
+
},
|
|
975
|
+
},
|
|
976
|
+
},
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
},
|
|
980
|
+
},
|
|
981
|
+
},
|
|
747
982
|
"/tasks": {
|
|
748
983
|
get: {
|
|
749
984
|
tags: ["Tasks"],
|
|
750
985
|
summary: "List all tasks",
|
|
986
|
+
description: "Fetches tasks from all running agents. Supports filtering by status and project.",
|
|
987
|
+
parameters: [
|
|
988
|
+
{ name: "status", in: "query", schema: { type: "string", enum: ["all", "pending", "running", "completed", "failed", "cancelled"], default: "all" }, description: "Filter tasks by status" },
|
|
989
|
+
{ name: "project_id", in: "query", schema: { type: "string" }, description: "Filter by project ID. Use 'unassigned' for agents without a project." },
|
|
990
|
+
],
|
|
751
991
|
responses: {
|
|
752
992
|
"200": {
|
|
753
993
|
description: "List of tasks",
|
|
754
994
|
content: {
|
|
755
995
|
"application/json": {
|
|
756
996
|
schema: {
|
|
757
|
-
type: "
|
|
758
|
-
|
|
997
|
+
type: "object",
|
|
998
|
+
properties: {
|
|
999
|
+
tasks: { type: "array", items: { $ref: "#/components/schemas/Task" } },
|
|
1000
|
+
count: { type: "integer" },
|
|
1001
|
+
},
|
|
759
1002
|
},
|
|
760
1003
|
},
|
|
761
1004
|
},
|
|
@@ -763,6 +1006,34 @@ while (true) {
|
|
|
763
1006
|
},
|
|
764
1007
|
},
|
|
765
1008
|
},
|
|
1009
|
+
"/tasks/{agentId}/{taskId}": {
|
|
1010
|
+
get: {
|
|
1011
|
+
tags: ["Tasks"],
|
|
1012
|
+
summary: "Get a single task",
|
|
1013
|
+
description: "Get full details for a specific task from a specific agent, including execution trajectory.",
|
|
1014
|
+
parameters: [
|
|
1015
|
+
{ name: "agentId", in: "path", required: true, schema: { type: "string" }, description: "Agent ID that owns the task" },
|
|
1016
|
+
{ name: "taskId", in: "path", required: true, schema: { type: "string" }, description: "Task ID" },
|
|
1017
|
+
],
|
|
1018
|
+
responses: {
|
|
1019
|
+
"200": {
|
|
1020
|
+
description: "Task details with trajectory",
|
|
1021
|
+
content: {
|
|
1022
|
+
"application/json": {
|
|
1023
|
+
schema: {
|
|
1024
|
+
type: "object",
|
|
1025
|
+
properties: {
|
|
1026
|
+
task: { $ref: "#/components/schemas/TaskDetail" },
|
|
1027
|
+
},
|
|
1028
|
+
},
|
|
1029
|
+
},
|
|
1030
|
+
},
|
|
1031
|
+
},
|
|
1032
|
+
"400": { description: "Agent is not running" },
|
|
1033
|
+
"404": { description: "Agent not found" },
|
|
1034
|
+
},
|
|
1035
|
+
},
|
|
1036
|
+
},
|
|
766
1037
|
"/mcp/servers": {
|
|
767
1038
|
get: {
|
|
768
1039
|
tags: ["MCP"],
|
|
@@ -1118,13 +1389,29 @@ Events are batched and sent periodically. Debug-level events are filtered out.`,
|
|
|
1118
1389
|
description: `Server-Sent Events stream for real-time telemetry updates.
|
|
1119
1390
|
|
|
1120
1391
|
Connect to this endpoint to receive live telemetry events as they are received from agents.
|
|
1392
|
+
Events are broadcast immediately when agents send them, enabling real-time activity feeds.
|
|
1121
1393
|
|
|
1122
|
-
**
|
|
1394
|
+
**Initial Connection:**
|
|
1395
|
+
On connect, you'll receive: \`{"connected":true}\`
|
|
1396
|
+
|
|
1397
|
+
**Event Format:**
|
|
1398
|
+
Each event is a JSON object matching the TelemetryEvent schema.
|
|
1399
|
+
|
|
1400
|
+
**Example - React hook for real-time activity:**
|
|
1123
1401
|
\`\`\`javascript
|
|
1124
1402
|
const eventSource = new EventSource('/api/telemetry/stream');
|
|
1403
|
+
|
|
1125
1404
|
eventSource.onmessage = (event) => {
|
|
1126
1405
|
const data = JSON.parse(event.data);
|
|
1127
|
-
|
|
1406
|
+
if (data.type === 'thread_activity') {
|
|
1407
|
+
// Update activity feed
|
|
1408
|
+
console.log(\`[\${data.agent_id}] \${data.data?.activity}\`);
|
|
1409
|
+
}
|
|
1410
|
+
};
|
|
1411
|
+
|
|
1412
|
+
eventSource.onerror = () => {
|
|
1413
|
+
// Reconnect logic
|
|
1414
|
+
eventSource.close();
|
|
1128
1415
|
};
|
|
1129
1416
|
\`\`\``,
|
|
1130
1417
|
responses: {
|
|
@@ -1146,12 +1433,27 @@ eventSource.onmessage = (event) => {
|
|
|
1146
1433
|
get: {
|
|
1147
1434
|
tags: ["Telemetry"],
|
|
1148
1435
|
summary: "Query telemetry events",
|
|
1149
|
-
description:
|
|
1436
|
+
description: `Query stored telemetry events with optional filters.
|
|
1437
|
+
|
|
1438
|
+
**Common Event Types:**
|
|
1439
|
+
- \`thread_activity\` - Agent activity updates (used for dashboard activity feed)
|
|
1440
|
+
- \`llm_request\` / \`llm_response\` - LLM API calls
|
|
1441
|
+
- \`tool_call\` / \`tool_result\` - Tool executions
|
|
1442
|
+
- \`memory_store\` / \`memory_recall\` - Memory operations
|
|
1443
|
+
- \`task_start\` / \`task_complete\` - Task lifecycle
|
|
1444
|
+
- \`agent_start\` / \`agent_stop\` - Agent lifecycle
|
|
1445
|
+
- \`error\` - Error events
|
|
1446
|
+
|
|
1447
|
+
**Example - Get recent activity for dashboard:**
|
|
1448
|
+
\`\`\`
|
|
1449
|
+
GET /api/telemetry/events?type=thread_activity&limit=20
|
|
1450
|
+
\`\`\``,
|
|
1150
1451
|
parameters: [
|
|
1151
1452
|
{ name: "agent_id", in: "query", schema: { type: "string" }, description: "Filter by agent ID" },
|
|
1152
1453
|
{ name: "project_id", in: "query", schema: { type: "string" }, description: "Filter by project ID (use 'null' for unassigned)" },
|
|
1153
|
-
{ name: "category", in: "query", schema: { type: "string"
|
|
1154
|
-
{ name: "
|
|
1454
|
+
{ name: "category", in: "query", schema: { type: "string", enum: ["llm", "tool", "memory", "task", "agent", "mcp", "system"] }, description: "Filter by category" },
|
|
1455
|
+
{ name: "type", in: "query", schema: { type: "string" }, description: "Filter by event type (e.g., thread_activity, llm_request, tool_call)" },
|
|
1456
|
+
{ name: "level", in: "query", schema: { type: "string", enum: ["info", "warn", "error"] }, description: "Filter by level" },
|
|
1155
1457
|
{ name: "trace_id", in: "query", schema: { type: "string" }, description: "Filter by trace ID" },
|
|
1156
1458
|
{ name: "since", in: "query", schema: { type: "string", format: "date-time" }, description: "Events after this timestamp" },
|
|
1157
1459
|
{ name: "until", in: "query", schema: { type: "string", format: "date-time" }, description: "Events before this timestamp" },
|
|
@@ -1640,6 +1942,16 @@ eventSource.onmessage = (event) => {
|
|
|
1640
1942
|
createdAt: { type: "string", format: "date-time" },
|
|
1641
1943
|
},
|
|
1642
1944
|
},
|
|
1945
|
+
Message: {
|
|
1946
|
+
type: "object",
|
|
1947
|
+
properties: {
|
|
1948
|
+
id: { type: "string" },
|
|
1949
|
+
role: { type: "string", enum: ["user", "assistant", "system"] },
|
|
1950
|
+
content: { type: "string" },
|
|
1951
|
+
threadId: { type: "string" },
|
|
1952
|
+
createdAt: { type: "string", format: "date-time" },
|
|
1953
|
+
},
|
|
1954
|
+
},
|
|
1643
1955
|
Task: {
|
|
1644
1956
|
type: "object",
|
|
1645
1957
|
properties: {
|
|
@@ -1650,11 +1962,75 @@ eventSource.onmessage = (event) => {
|
|
|
1650
1962
|
status: { type: "string", enum: ["pending", "running", "completed", "failed", "cancelled"] },
|
|
1651
1963
|
priority: { type: "integer" },
|
|
1652
1964
|
source: { type: "string", enum: ["local", "delegated"] },
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1965
|
+
created_at: { type: "string", format: "date-time" },
|
|
1966
|
+
execute_at: { type: "string", format: "date-time", nullable: true },
|
|
1967
|
+
executed_at: { type: "string", format: "date-time", nullable: true },
|
|
1968
|
+
completed_at: { type: "string", format: "date-time", nullable: true },
|
|
1969
|
+
recurrence: { type: "string", nullable: true, description: "Cron expression for recurring tasks" },
|
|
1970
|
+
next_run: { type: "string", format: "date-time", nullable: true, description: "Next scheduled run for recurring tasks" },
|
|
1971
|
+
result: { type: "object", nullable: true, description: "Task result data (present when completed)" },
|
|
1972
|
+
error: { type: "string", nullable: true, description: "Error message (present when failed)" },
|
|
1973
|
+
agentId: { type: "string", description: "ID of the agent that owns this task" },
|
|
1974
|
+
agentName: { type: "string", description: "Name of the agent that owns this task" },
|
|
1975
|
+
},
|
|
1976
|
+
},
|
|
1977
|
+
TaskDetail: {
|
|
1978
|
+
type: "object",
|
|
1979
|
+
description: "Full task detail including trajectory (returned by single task endpoint)",
|
|
1980
|
+
properties: {
|
|
1981
|
+
id: { type: "string" },
|
|
1982
|
+
title: { type: "string" },
|
|
1983
|
+
description: { type: "string" },
|
|
1984
|
+
type: { type: "string", enum: ["once", "recurring"] },
|
|
1985
|
+
status: { type: "string", enum: ["pending", "running", "completed", "failed", "cancelled"] },
|
|
1986
|
+
priority: { type: "integer" },
|
|
1987
|
+
source: { type: "string", enum: ["local", "delegated"] },
|
|
1988
|
+
created_at: { type: "string", format: "date-time" },
|
|
1989
|
+
execute_at: { type: "string", format: "date-time", nullable: true },
|
|
1990
|
+
executed_at: { type: "string", format: "date-time", nullable: true },
|
|
1991
|
+
completed_at: { type: "string", format: "date-time", nullable: true },
|
|
1992
|
+
recurrence: { type: "string", nullable: true },
|
|
1993
|
+
next_run: { type: "string", format: "date-time", nullable: true },
|
|
1994
|
+
result: { type: "object", nullable: true },
|
|
1995
|
+
error: { type: "string", nullable: true },
|
|
1656
1996
|
agentId: { type: "string" },
|
|
1657
1997
|
agentName: { type: "string" },
|
|
1998
|
+
trajectory: {
|
|
1999
|
+
type: "array",
|
|
2000
|
+
nullable: true,
|
|
2001
|
+
description: "Step-by-step execution trajectory of the task",
|
|
2002
|
+
items: { $ref: "#/components/schemas/TaskTrajectoryStep" },
|
|
2003
|
+
},
|
|
2004
|
+
},
|
|
2005
|
+
},
|
|
2006
|
+
TaskTrajectoryStep: {
|
|
2007
|
+
type: "object",
|
|
2008
|
+
properties: {
|
|
2009
|
+
id: { type: "string" },
|
|
2010
|
+
role: { type: "string", enum: ["user", "assistant"] },
|
|
2011
|
+
content: {
|
|
2012
|
+
description: "Text content or array of tool use/result blocks",
|
|
2013
|
+
oneOf: [
|
|
2014
|
+
{ type: "string" },
|
|
2015
|
+
{
|
|
2016
|
+
type: "array",
|
|
2017
|
+
items: {
|
|
2018
|
+
type: "object",
|
|
2019
|
+
properties: {
|
|
2020
|
+
type: { type: "string", enum: ["tool_use", "tool_result"] },
|
|
2021
|
+
id: { type: "string" },
|
|
2022
|
+
name: { type: "string", description: "Tool name (for tool_use)" },
|
|
2023
|
+
input: { type: "object", description: "Tool input (for tool_use)" },
|
|
2024
|
+
tool_use_id: { type: "string", description: "Referenced tool_use ID (for tool_result)" },
|
|
2025
|
+
content: { type: "string", description: "Result text (for tool_result)" },
|
|
2026
|
+
is_error: { type: "boolean", description: "Whether the tool errored (for tool_result)" },
|
|
2027
|
+
},
|
|
2028
|
+
},
|
|
2029
|
+
},
|
|
2030
|
+
],
|
|
2031
|
+
},
|
|
2032
|
+
created_at: { type: "string", format: "date-time" },
|
|
2033
|
+
model: { type: "string", nullable: true },
|
|
1658
2034
|
},
|
|
1659
2035
|
},
|
|
1660
2036
|
Skill: {
|
|
@@ -1702,6 +2078,12 @@ eventSource.onmessage = (event) => {
|
|
|
1702
2078
|
source: { type: "string", nullable: true },
|
|
1703
2079
|
},
|
|
1704
2080
|
},
|
|
2081
|
+
McpServerResponse: {
|
|
2082
|
+
type: "object",
|
|
2083
|
+
properties: {
|
|
2084
|
+
server: { $ref: "#/components/schemas/McpServer" },
|
|
2085
|
+
},
|
|
2086
|
+
},
|
|
1705
2087
|
McpServerListResponse: {
|
|
1706
2088
|
type: "object",
|
|
1707
2089
|
properties: {
|
|
@@ -1847,18 +2229,31 @@ eventSource.onmessage = (event) => {
|
|
|
1847
2229
|
},
|
|
1848
2230
|
TelemetryEvent: {
|
|
1849
2231
|
type: "object",
|
|
2232
|
+
description: `A telemetry event from an agent. Events capture LLM calls, tool usage, memory operations, and agent activity.
|
|
2233
|
+
|
|
2234
|
+
**Common type values by category:**
|
|
2235
|
+
- **llm**: request, response, error
|
|
2236
|
+
- **tool**: call, result, error
|
|
2237
|
+
- **memory**: store, recall, consolidate
|
|
2238
|
+
- **task**: start, complete, fail
|
|
2239
|
+
- **agent**: start, stop, thread_activity
|
|
2240
|
+
- **system**: startup, shutdown, error`,
|
|
1850
2241
|
properties: {
|
|
1851
|
-
id: { type: "string" },
|
|
1852
|
-
agent_id: { type: "string" },
|
|
1853
|
-
timestamp: { type: "string", format: "date-time" },
|
|
1854
|
-
category: { type: "string" },
|
|
1855
|
-
type: { type: "string" },
|
|
1856
|
-
level: { type: "string" },
|
|
1857
|
-
trace_id: { type: "string", nullable: true },
|
|
1858
|
-
thread_id: { type: "string", nullable: true },
|
|
1859
|
-
data: {
|
|
1860
|
-
|
|
1861
|
-
|
|
2242
|
+
id: { type: "string", description: "Unique event ID" },
|
|
2243
|
+
agent_id: { type: "string", description: "ID of the agent that generated this event" },
|
|
2244
|
+
timestamp: { type: "string", format: "date-time", description: "When the event occurred" },
|
|
2245
|
+
category: { type: "string", enum: ["llm", "tool", "memory", "task", "agent", "mcp", "system"], description: "Event category" },
|
|
2246
|
+
type: { type: "string", description: "Event type within category (e.g., 'thread_activity', 'request', 'call')" },
|
|
2247
|
+
level: { type: "string", enum: ["info", "warn", "error"], description: "Severity level" },
|
|
2248
|
+
trace_id: { type: "string", nullable: true, description: "Trace ID for correlating related events" },
|
|
2249
|
+
thread_id: { type: "string", nullable: true, description: "Conversation thread ID" },
|
|
2250
|
+
data: {
|
|
2251
|
+
type: "object",
|
|
2252
|
+
nullable: true,
|
|
2253
|
+
description: "Event-specific data. For thread_activity: { activity: string }. For llm: { model, tokens, prompt_tokens, completion_tokens }. For tool: { tool_name, input, output }."
|
|
2254
|
+
},
|
|
2255
|
+
duration_ms: { type: "integer", nullable: true, description: "Duration in milliseconds (for timed operations)" },
|
|
2256
|
+
error: { type: "string", nullable: true, description: "Error message if this is an error event" },
|
|
1862
2257
|
},
|
|
1863
2258
|
},
|
|
1864
2259
|
TelemetryUsage: {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { AuthContext } from "../../auth/middleware";
|
|
2
|
+
import { ApiKeyDB } from "../../db";
|
|
3
|
+
import { json } from "./helpers";
|
|
4
|
+
|
|
5
|
+
const MAX_KEYS_PER_USER = 10;
|
|
6
|
+
|
|
7
|
+
export async function handleApiKeyRoutes(
|
|
8
|
+
req: Request,
|
|
9
|
+
path: string,
|
|
10
|
+
method: string,
|
|
11
|
+
authContext?: AuthContext,
|
|
12
|
+
): Promise<Response | null> {
|
|
13
|
+
// All API key routes require authentication
|
|
14
|
+
if (!authContext?.isAuthenticated || !authContext.user) {
|
|
15
|
+
return null; // Let other handlers deal with it
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const userId = authContext.user.id;
|
|
19
|
+
|
|
20
|
+
// POST /api/keys/personal - Create a new API key
|
|
21
|
+
if (path === "/api/keys/personal" && method === "POST") {
|
|
22
|
+
try {
|
|
23
|
+
const body = await req.json();
|
|
24
|
+
const { name, expires_in_days } = body;
|
|
25
|
+
|
|
26
|
+
if (!name || typeof name !== "string" || name.trim().length === 0) {
|
|
27
|
+
return json({ error: "Name is required" }, 400);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (name.length > 100) {
|
|
31
|
+
return json({ error: "Name must be 100 characters or less" }, 400);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Limit keys per user
|
|
35
|
+
const count = ApiKeyDB.countByUser(userId);
|
|
36
|
+
if (count >= MAX_KEYS_PER_USER) {
|
|
37
|
+
return json({ error: `Maximum ${MAX_KEYS_PER_USER} API keys allowed per user` }, 400);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Calculate expiration
|
|
41
|
+
let expires_at: string | null = null;
|
|
42
|
+
if (expires_in_days && typeof expires_in_days === "number" && expires_in_days > 0) {
|
|
43
|
+
const expiry = new Date();
|
|
44
|
+
expiry.setDate(expiry.getDate() + expires_in_days);
|
|
45
|
+
expires_at = expiry.toISOString();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { apiKey, rawKey } = ApiKeyDB.create({
|
|
49
|
+
name: name.trim(),
|
|
50
|
+
user_id: userId,
|
|
51
|
+
expires_at,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return json({
|
|
55
|
+
id: apiKey.id,
|
|
56
|
+
name: apiKey.name,
|
|
57
|
+
key: rawKey,
|
|
58
|
+
prefix: apiKey.key_prefix,
|
|
59
|
+
expires_at: apiKey.expires_at,
|
|
60
|
+
created_at: apiKey.created_at,
|
|
61
|
+
}, 201);
|
|
62
|
+
} catch (e: any) {
|
|
63
|
+
return json({ error: e.message || "Failed to create API key" }, 500);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// GET /api/keys/personal - List user's API keys
|
|
68
|
+
if (path === "/api/keys/personal" && method === "GET") {
|
|
69
|
+
const keys = ApiKeyDB.findByUser(userId);
|
|
70
|
+
return json({
|
|
71
|
+
keys: keys.map(k => ({
|
|
72
|
+
id: k.id,
|
|
73
|
+
name: k.name,
|
|
74
|
+
prefix: k.key_prefix,
|
|
75
|
+
is_active: k.is_active,
|
|
76
|
+
expires_at: k.expires_at,
|
|
77
|
+
last_used_at: k.last_used_at,
|
|
78
|
+
created_at: k.created_at,
|
|
79
|
+
})),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// DELETE /api/keys/personal/:id - Revoke/delete an API key
|
|
84
|
+
const deleteMatch = path.match(/^\/api\/keys\/personal\/([^/]+)$/);
|
|
85
|
+
if (deleteMatch && method === "DELETE") {
|
|
86
|
+
const keyId = deleteMatch[1];
|
|
87
|
+
const deleted = ApiKeyDB.delete(keyId, userId);
|
|
88
|
+
if (!deleted) {
|
|
89
|
+
return json({ error: "API key not found" }, 404);
|
|
90
|
+
}
|
|
91
|
+
return json({ success: true });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return null;
|
|
95
|
+
}
|
package/src/routes/api/mcp.ts
CHANGED
|
@@ -243,8 +243,8 @@ export async function handleMcpRoutes(
|
|
|
243
243
|
return json({ error: "No command or package specified" }, 400);
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
-
//
|
|
247
|
-
const port = await getNextPort();
|
|
246
|
+
// Use permanently assigned port from DB, fallback to dynamic
|
|
247
|
+
const port = server.port || await getNextPort();
|
|
248
248
|
|
|
249
249
|
console.log(`Starting MCP server ${server.name}...`);
|
|
250
250
|
console.log(` Command: ${cmd.join(" ")}`);
|