feat: initial monorepo scaffold - Next.js 15 + Prisma + Python SDK stubs

- Turborepo monorepo with apps/web and packages/database, sdk-python
- Next.js 15 app with professional landing page (dark theme, emerald accent)
- Prisma schema: Trace, DecisionPoint, Span, Event models with full indexing
- Docker Compose: web (port 4200), postgres:16, redis:7, migrate service
- Python SDK package stubs: init, trace decorator, log_decision, integrations
- Multi-stage Dockerfile for standalone Next.js production build
This commit is contained in:
Vectry
2026-02-09 22:46:16 +00:00
parent 572fd7e234
commit 9264866d1f
31 changed files with 3244 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
{
"name": "@agentlens/database",
"version": "0.0.1",
"private": true,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsc",
"clean": "rm -rf dist",
"db:generate": "prisma generate",
"db:push": "prisma db push",
"db:migrate": "prisma migrate dev"
},
"dependencies": {
"@prisma/client": "^6.3.0"
},
"devDependencies": {
"prisma": "^6.3.0",
"typescript": "^5.7"
}
}

View File

@@ -0,0 +1,154 @@
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model Trace {
id String @id @default(cuid())
sessionId String?
name String
status TraceStatus @default(RUNNING)
tags String[] @default([])
metadata Json?
totalCost Float?
totalTokens Int?
totalDuration Int?
startedAt DateTime @default(now())
endedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
decisionPoints DecisionPoint[]
spans Span[]
events Event[]
@@index([sessionId])
@@index([status])
@@index([createdAt])
@@index([name])
}
model DecisionPoint {
id String @id @default(cuid())
traceId String
trace Trace @relation(fields: [traceId], references: [id], onDelete: Cascade)
type DecisionType
reasoning String?
chosen Json
alternatives Json[]
contextSnapshot Json?
durationMs Int?
costUsd Float?
parentSpanId String?
span Span? @relation(fields: [parentSpanId], references: [id])
timestamp DateTime @default(now())
@@index([traceId])
@@index([type])
@@index([timestamp])
}
model Span {
id String @id @default(cuid())
traceId String
trace Trace @relation(fields: [traceId], references: [id], onDelete: Cascade)
parentSpanId String?
parentSpan Span? @relation("SpanTree", fields: [parentSpanId], references: [id])
childSpans Span[] @relation("SpanTree")
name String
type SpanType
input Json?
output Json?
tokenCount Int?
costUsd Float?
durationMs Int?
status SpanStatus @default(RUNNING)
statusMessage String?
startedAt DateTime @default(now())
endedAt DateTime?
metadata Json?
decisionPoints DecisionPoint[]
@@index([traceId])
@@index([parentSpanId])
@@index([type])
@@index([startedAt])
}
model Event {
id String @id @default(cuid())
traceId String
trace Trace @relation(fields: [traceId], references: [id], onDelete: Cascade)
spanId String?
type EventType
name String
metadata Json?
timestamp DateTime @default(now())
@@index([traceId])
@@index([type])
@@index([timestamp])
}
enum TraceStatus {
RUNNING
COMPLETED
ERROR
}
enum DecisionType {
TOOL_SELECTION
ROUTING
RETRY
ESCALATION
MEMORY_RETRIEVAL
PLANNING
CUSTOM
}
enum SpanType {
LLM_CALL
TOOL_CALL
MEMORY_OP
CHAIN
AGENT
CUSTOM
}
enum SpanStatus {
RUNNING
COMPLETED
ERROR
}
enum EventType {
ERROR
RETRY
FALLBACK
CONTEXT_OVERFLOW
USER_FEEDBACK
CUSTOM
}

View File

@@ -0,0 +1,2 @@
export { PrismaClient } from "@prisma/client";
export type * from "@prisma/client";

View File

@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}