mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-21 04:57:58 -05:00
feat(server): first backend endpoint
This commit is contained in:
3
rnd/autogpt_server/.vscode/settings.json
vendored
3
rnd/autogpt_server/.vscode/settings.json
vendored
@@ -1,3 +1,6 @@
|
||||
{
|
||||
"python.analysis.typeCheckingMode": "basic",
|
||||
"python.testing.pytestArgs": ["test"],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true
|
||||
}
|
||||
|
||||
@@ -78,128 +78,160 @@ class AgentServer(AppService):
|
||||
from .integrations import integrations_api_router
|
||||
|
||||
api_router.include_router(integrations_api_router, prefix="/integrations")
|
||||
import autogpt_server.server.routers.analytics
|
||||
|
||||
api_router.include_router(
|
||||
autogpt_server.server.routers.analytics.router,
|
||||
prefix="/analytics",
|
||||
tags=["analytics"],
|
||||
dependencies=[Depends(auth_middleware)],
|
||||
)
|
||||
|
||||
api_router.add_api_route(
|
||||
path="/auth/user",
|
||||
endpoint=self.get_or_create_user_route,
|
||||
methods=["POST"],
|
||||
tags=["auth"],
|
||||
)
|
||||
|
||||
api_router.add_api_route(
|
||||
path="/blocks",
|
||||
endpoint=self.get_graph_blocks,
|
||||
methods=["GET"],
|
||||
tags=["blocks"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/blocks/{block_id}/execute",
|
||||
endpoint=self.execute_graph_block,
|
||||
methods=["POST"],
|
||||
tags=["blocks"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs",
|
||||
endpoint=self.get_graphs,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/templates",
|
||||
endpoint=self.get_templates,
|
||||
methods=["GET"],
|
||||
tags=["templates", "graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs",
|
||||
endpoint=self.create_new_graph,
|
||||
methods=["POST"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/templates",
|
||||
endpoint=self.create_new_template,
|
||||
methods=["POST"],
|
||||
tags=["templates", "graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}",
|
||||
endpoint=self.get_graph,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/templates/{graph_id}",
|
||||
endpoint=self.get_template,
|
||||
methods=["GET"],
|
||||
tags=["templates", "graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}",
|
||||
endpoint=self.update_graph,
|
||||
methods=["PUT"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/templates/{graph_id}",
|
||||
endpoint=self.update_graph,
|
||||
methods=["PUT"],
|
||||
tags=["templates", "graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/versions",
|
||||
endpoint=self.get_graph_all_versions,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/templates/{graph_id}/versions",
|
||||
endpoint=self.get_graph_all_versions,
|
||||
methods=["GET"],
|
||||
tags=["templates", "graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/versions/{version}",
|
||||
endpoint=self.get_graph,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/versions/active",
|
||||
endpoint=self.set_graph_active_version,
|
||||
methods=["PUT"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/input_schema",
|
||||
endpoint=self.get_graph_input_schema,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/execute",
|
||||
endpoint=self.execute_graph,
|
||||
methods=["POST"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/executions",
|
||||
endpoint=self.list_graph_runs,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/executions/{graph_exec_id}",
|
||||
endpoint=self.get_graph_run_node_execution_results,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/executions/{graph_exec_id}/stop",
|
||||
endpoint=self.stop_graph_run,
|
||||
methods=["POST"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/schedules",
|
||||
endpoint=self.create_schedule,
|
||||
methods=["POST"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/{graph_id}/schedules",
|
||||
endpoint=self.get_execution_schedules,
|
||||
methods=["GET"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
api_router.add_api_route(
|
||||
path="/graphs/schedules/{schedule_id}",
|
||||
endpoint=self.update_schedule,
|
||||
methods=["PUT"],
|
||||
tags=["graphs"],
|
||||
)
|
||||
|
||||
api_router.add_api_route(
|
||||
path="/settings",
|
||||
endpoint=self.update_configuration,
|
||||
methods=["POST"],
|
||||
tags=["settings"],
|
||||
)
|
||||
|
||||
app.add_exception_handler(500, self.handle_internal_http_error)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Analytics API
|
||||
|
||||
from typing import Annotated
|
||||
import typing
|
||||
import typing_extensions
|
||||
import fastapi
|
||||
import prisma
|
||||
import prisma.enums
|
||||
import pydantic
|
||||
from autogpt_server.server.utils import get_user_id
|
||||
|
||||
router = fastapi.APIRouter()
|
||||
|
||||
|
||||
class UserData(pydantic.BaseModel):
|
||||
user_id: str
|
||||
email: str
|
||||
name: str
|
||||
username: str
|
||||
|
||||
|
||||
class TutorialStepData(pydantic.BaseModel):
|
||||
data: typing.Optional[dict]
|
||||
|
||||
|
||||
@router.post(path="/log_new_user")
|
||||
async def log_create_user(
|
||||
user_id: Annotated[str, fastapi.Depends(get_user_id)],
|
||||
user_data: Annotated[UserData, fastapi.Body(..., embed=True)],
|
||||
):
|
||||
"""
|
||||
Log the user ID for analytics purposes.
|
||||
"""
|
||||
id = await prisma.models.AnalyticsDetails.prisma().create(
|
||||
data={
|
||||
"userId": user_id,
|
||||
"type": prisma.enums.AnalyticsType.CREATE_USER,
|
||||
"data": prisma.Json(user_data.model_dump_json()),
|
||||
}
|
||||
)
|
||||
return id.id
|
||||
|
||||
|
||||
@router.post(path="/log_tutorial_step")
|
||||
async def log_tutorial_step(
|
||||
user_id: Annotated[str, fastapi.Depends(get_user_id)],
|
||||
step: Annotated[int, fastapi.Query(..., embed=True)],
|
||||
data: Annotated[TutorialStepData, fastapi.Body(..., embed=True)],
|
||||
):
|
||||
"""
|
||||
Log the tutorial step completed by the user for analytics purposes.
|
||||
"""
|
||||
id = await prisma.models.AnalyticsDetails.prisma().create(
|
||||
data={
|
||||
"userId": user_id,
|
||||
"type": prisma.enums.AnalyticsType.TUTORIAL_STEP,
|
||||
"data": prisma.Json(data.model_dump_json()),
|
||||
"dataIndex": step,
|
||||
}
|
||||
)
|
||||
return id.id
|
||||
@@ -0,0 +1,53 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AnalyticsType" AS ENUM ('CREATE_USER', 'TUTORIAL_STEP', 'WEB_PAGE', 'AGENT_GRAPH_EXECUTION', 'AGENT_NODE_EXECUTION');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AnalyticsMetric" AS ENUM ('PAGE_VIEW', 'TUTORIAL_STEP_COMPLETION', 'AGENT_GRAPH_EXECUTION', 'AGENT_NODE_EXECUTION');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "AggregationType" AS ENUM ('COUNT', 'SUM', 'AVG', 'MAX', 'MIN', 'NO_AGGREGATION');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AnalyticsDetails" (
|
||||
"id" TEXT NOT NULL DEFAULT gen_random_uuid(),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"userId" TEXT NOT NULL,
|
||||
"type" "AnalyticsType" NOT NULL,
|
||||
"data" JSONB,
|
||||
"dataIndex" INTEGER,
|
||||
|
||||
CONSTRAINT "AnalyticsDetails_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AnalyticsMetrics" (
|
||||
"id" TEXT NOT NULL DEFAULT gen_random_uuid(),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"analyticMetric" "AnalyticsMetric" NOT NULL,
|
||||
"value" DOUBLE PRECISION NOT NULL,
|
||||
"dataString" TEXT,
|
||||
"aggregationType" "AggregationType" NOT NULL DEFAULT 'NO_AGGREGATION',
|
||||
"userId" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "AnalyticsMetrics_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "analyticsDetails" ON "AnalyticsDetails"("userId", "type");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AnalyticsDetails_type_idx" ON "AnalyticsDetails"("type");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "analytics_metric_index" ON "AnalyticsMetrics"("analyticMetric", "userId", "dataString", "aggregationType");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "AnalyticsMetrics_analyticMetric_userId_dataString_aggregati_key" ON "AnalyticsMetrics"("analyticMetric", "userId", "dataString", "aggregationType");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AnalyticsDetails" ADD CONSTRAINT "AnalyticsDetails_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AnalyticsMetrics" ADD CONSTRAINT "AnalyticsMetrics_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "AnalyticsMetrics" ADD COLUMN "aggregationCounter" INTEGER DEFAULT 1;
|
||||
@@ -22,6 +22,8 @@ model User {
|
||||
AgentGraphs AgentGraph[]
|
||||
AgentGraphExecutions AgentGraphExecution[]
|
||||
AgentGraphExecutionSchedules AgentGraphExecutionSchedule[]
|
||||
AnalyticsDetails AnalyticsDetails[]
|
||||
AnalyticsMetrics AnalyticsMetrics[]
|
||||
|
||||
@@index([id])
|
||||
@@index([email])
|
||||
@@ -29,9 +31,9 @@ model User {
|
||||
|
||||
// This model describes the Agent Graph/Flow (Multi Agent System).
|
||||
model AgentGraph {
|
||||
id String @default(uuid())
|
||||
version Int @default(1)
|
||||
createdAt DateTime @default(now())
|
||||
id String @default(uuid())
|
||||
version Int @default(1)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime? @updatedAt
|
||||
|
||||
name String?
|
||||
@@ -115,8 +117,8 @@ model AgentBlock {
|
||||
|
||||
// This model describes the execution of an AgentGraph.
|
||||
model AgentGraphExecution {
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
id String @id @default(uuid())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime? @updatedAt
|
||||
|
||||
agentGraphId String
|
||||
@@ -178,8 +180,8 @@ model AgentNodeExecutionInputOutput {
|
||||
|
||||
// This model describes the recurring execution schedule of an Agent.
|
||||
model AgentGraphExecutionSchedule {
|
||||
id String @id
|
||||
createdAt DateTime @default(now())
|
||||
id String @id
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime? @updatedAt
|
||||
|
||||
agentGraphId String
|
||||
@@ -199,3 +201,79 @@ model AgentGraphExecutionSchedule {
|
||||
|
||||
@@index([isEnabled])
|
||||
}
|
||||
|
||||
enum AnalyticsType {
|
||||
CREATE_USER
|
||||
TUTORIAL_STEP
|
||||
WEB_PAGE
|
||||
|
||||
AGENT_GRAPH_EXECUTION
|
||||
AGENT_NODE_EXECUTION
|
||||
}
|
||||
|
||||
model AnalyticsDetails {
|
||||
// PK uses gen_random_uuid() to allow the db inserts to happen outside of prisma
|
||||
// typical uuid() inserts are handled by prisma
|
||||
id String @id @default(dbgenerated("gen_random_uuid()"))
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
|
||||
// Link to User model
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
// Analytics Categorical data used for filtering (indexable w and w/o userId)
|
||||
type AnalyticsType
|
||||
|
||||
// Analytic Specific Data. We should use a union type here, but prisma doesn't support it.
|
||||
data Json?
|
||||
|
||||
// Indexable field for any count based analytically measures like page order clicking, tutorial step completion, etc.
|
||||
dataIndex Int?
|
||||
|
||||
@@index([userId, type], name: "analyticsDetails")
|
||||
@@index([type])
|
||||
}
|
||||
|
||||
enum AnalyticsMetric {
|
||||
PAGE_VIEW
|
||||
TUTORIAL_STEP_COMPLETION
|
||||
AGENT_GRAPH_EXECUTION
|
||||
AGENT_NODE_EXECUTION
|
||||
}
|
||||
|
||||
enum AggregationType {
|
||||
COUNT
|
||||
SUM
|
||||
AVG
|
||||
MAX
|
||||
MIN
|
||||
NO_AGGREGATION
|
||||
}
|
||||
|
||||
model AnalyticsMetrics {
|
||||
id String @id @default(dbgenerated("gen_random_uuid()"))
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Analytics Categorical data used for filtering (indexable w and w/o userId)
|
||||
analyticMetric AnalyticsMetric
|
||||
// Any numeric data that should be counted upon, summed, or otherwise aggregated.
|
||||
value Float
|
||||
// Any string data that should be used to identify the metric as distinct.
|
||||
// ex: '/build' vs '/market'
|
||||
dataString String?
|
||||
// Data Aggregation Type
|
||||
aggregationType AggregationType @default(NO_AGGREGATION)
|
||||
// Aggregation Counter used for aggregation style events that beenefit from it. (AVG) (not self incrementing)
|
||||
aggregationCounter Int? @default(1)
|
||||
|
||||
// Link to User model
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
// Allows us to have unique but useful user level metrics.
|
||||
@@unique([analyticMetric, userId, dataString, aggregationType])
|
||||
@@index(fields: [analyticMetric, userId, dataString, aggregationType], name: "analytics_metric_index")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user