mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
chore(biome): removed prettier, added biome (#407)
* chore: replace prettier with biome and add linting * chore: update devcontainer settings to use biome for linting and remove eslint, prettier * chore: update docker-compose to use Postgres 17-alpine and standardize quotes * chore: fixed more BUT disabled most rules due to limit * added additional rules, fixed linting & ts errors * added additional rules * rebased & linted * fixed oauth * updated biome & minor modifications --------- Co-authored-by: Aditya Tripathi <aditya@climactic.co>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { and, eq, isNull } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { db } from '@/db'
|
||||
import { memory } from '@/db/schema'
|
||||
@@ -12,20 +12,17 @@ export const runtime = 'nodejs'
|
||||
/**
|
||||
* GET handler for retrieving a specific memory by ID
|
||||
*/
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
const { id } = await params
|
||||
|
||||
|
||||
try {
|
||||
logger.info(`[${requestId}] Processing memory get request for ID: ${id}`)
|
||||
|
||||
|
||||
// Get workflowId from query parameter (required)
|
||||
const url = new URL(request.url)
|
||||
const workflowId = url.searchParams.get('workflowId')
|
||||
|
||||
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required parameter: workflowId`)
|
||||
return NextResponse.json(
|
||||
@@ -38,18 +35,12 @@ export async function GET(
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Query the database for the memory
|
||||
const memories = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, id),
|
||||
eq(memory.workflowId, workflowId),
|
||||
isNull(memory.deletedAt)
|
||||
)
|
||||
)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId), isNull(memory.deletedAt)))
|
||||
.orderBy(memory.createdAt)
|
||||
.limit(1)
|
||||
|
||||
@@ -74,7 +65,6 @@ export async function GET(
|
||||
},
|
||||
{ status: 200 }
|
||||
)
|
||||
|
||||
} catch (error: any) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
@@ -97,14 +87,14 @@ export async function DELETE(
|
||||
) {
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
const { id } = await params
|
||||
|
||||
|
||||
try {
|
||||
logger.info(`[${requestId}] Processing memory delete request for ID: ${id}`)
|
||||
|
||||
|
||||
// Get workflowId from query parameter (required)
|
||||
const url = new URL(request.url)
|
||||
const workflowId = url.searchParams.get('workflowId')
|
||||
|
||||
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required parameter: workflowId`)
|
||||
return NextResponse.json(
|
||||
@@ -117,20 +107,14 @@ export async function DELETE(
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Verify memory exists before attempting to delete
|
||||
const existingMemory = await db
|
||||
.select({ id: memory.id })
|
||||
.from(memory)
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, id),
|
||||
eq(memory.workflowId, workflowId),
|
||||
isNull(memory.deletedAt)
|
||||
)
|
||||
)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId), isNull(memory.deletedAt)))
|
||||
.limit(1)
|
||||
|
||||
|
||||
if (existingMemory.length === 0) {
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${workflowId}`)
|
||||
return NextResponse.json(
|
||||
@@ -143,21 +127,16 @@ export async function DELETE(
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Soft delete by setting deletedAt timestamp
|
||||
await db
|
||||
.update(memory)
|
||||
.set({
|
||||
.set({
|
||||
deletedAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, id),
|
||||
eq(memory.workflowId, workflowId)
|
||||
)
|
||||
)
|
||||
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
|
||||
logger.info(`[${requestId}] Memory deleted successfully: ${id} for workflow: ${workflowId}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
@@ -166,7 +145,6 @@ export async function DELETE(
|
||||
},
|
||||
{ status: 200 }
|
||||
)
|
||||
|
||||
} catch (error: any) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
@@ -183,20 +161,17 @@ export async function DELETE(
|
||||
/**
|
||||
* PUT handler for updating a specific memory
|
||||
*/
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
const { id } = await params
|
||||
|
||||
|
||||
try {
|
||||
logger.info(`[${requestId}] Processing memory update request for ID: ${id}`)
|
||||
|
||||
|
||||
// Parse request body
|
||||
const body = await request.json()
|
||||
const { data, workflowId } = body
|
||||
|
||||
|
||||
if (!data) {
|
||||
logger.warn(`[${requestId}] Missing required field: data`)
|
||||
return NextResponse.json(
|
||||
@@ -209,7 +184,7 @@ export async function PUT(
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required field: workflowId`)
|
||||
return NextResponse.json(
|
||||
@@ -222,20 +197,14 @@ export async function PUT(
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Verify memory exists before attempting to update
|
||||
const existingMemories = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, id),
|
||||
eq(memory.workflowId, workflowId),
|
||||
isNull(memory.deletedAt)
|
||||
)
|
||||
)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId), isNull(memory.deletedAt)))
|
||||
.limit(1)
|
||||
|
||||
|
||||
if (existingMemories.length === 0) {
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${workflowId}`)
|
||||
return NextResponse.json(
|
||||
@@ -248,9 +217,9 @@ export async function PUT(
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
const existingMemory = existingMemories[0]
|
||||
|
||||
|
||||
// Validate memory data based on the existing memory type
|
||||
if (existingMemory.type === 'agent') {
|
||||
if (!data.role || !data.content) {
|
||||
@@ -265,7 +234,7 @@ export async function PUT(
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if (!['user', 'assistant', 'system'].includes(data.role)) {
|
||||
logger.warn(`[${requestId}] Invalid agent role: ${data.role}`)
|
||||
return NextResponse.json(
|
||||
@@ -279,33 +248,23 @@ export async function PUT(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update the memory with new data
|
||||
await db
|
||||
.update(memory)
|
||||
.set({
|
||||
.set({
|
||||
data,
|
||||
updatedAt: new Date()
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, id),
|
||||
eq(memory.workflowId, workflowId)
|
||||
)
|
||||
)
|
||||
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
|
||||
// Fetch the updated memory
|
||||
const updatedMemories = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, id),
|
||||
eq(memory.workflowId, workflowId)
|
||||
)
|
||||
)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
.limit(1)
|
||||
|
||||
|
||||
logger.info(`[${requestId}] Memory updated successfully: ${id} for workflow: ${workflowId}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
@@ -314,7 +273,6 @@ export async function PUT(
|
||||
},
|
||||
{ status: 200 }
|
||||
)
|
||||
|
||||
} catch (error: any) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
@@ -326,4 +284,4 @@ export async function PUT(
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { and, eq, like, isNull } from 'drizzle-orm'
|
||||
import { and, eq, isNull, like } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
import { db } from '@/db'
|
||||
import { memory } from '@/db/schema'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
|
||||
const logger = createLogger('MemoryAPI')
|
||||
|
||||
@@ -19,17 +19,17 @@ export const runtime = 'nodejs'
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
|
||||
|
||||
try {
|
||||
logger.info(`[${requestId}] Processing memory search request`)
|
||||
|
||||
|
||||
// Extract workflowId from query parameters
|
||||
const url = new URL(request.url)
|
||||
const workflowId = url.searchParams.get('workflowId')
|
||||
const searchQuery = url.searchParams.get('query')
|
||||
const type = url.searchParams.get('type')
|
||||
const limit = parseInt(url.searchParams.get('limit') || '50')
|
||||
|
||||
const limit = Number.parseInt(url.searchParams.get('limit') || '50')
|
||||
|
||||
// Require workflowId for security
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required parameter: workflowId`)
|
||||
@@ -43,26 +43,26 @@ export async function GET(request: NextRequest) {
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Build query conditions
|
||||
const conditions = []
|
||||
|
||||
|
||||
// Only include non-deleted memories
|
||||
conditions.push(isNull(memory.deletedAt))
|
||||
|
||||
|
||||
// Filter by workflow ID (required)
|
||||
conditions.push(eq(memory.workflowId, workflowId))
|
||||
|
||||
|
||||
// Add type filter if provided
|
||||
if (type) {
|
||||
conditions.push(eq(memory.type, type))
|
||||
}
|
||||
|
||||
|
||||
// Add search query if provided (leverages index on key field)
|
||||
if (searchQuery) {
|
||||
conditions.push(like(memory.key, `%${searchQuery}%`))
|
||||
}
|
||||
|
||||
|
||||
// Execute the query
|
||||
const memories = await db
|
||||
.select()
|
||||
@@ -70,16 +70,15 @@ export async function GET(request: NextRequest) {
|
||||
.where(and(...conditions))
|
||||
.orderBy(memory.createdAt)
|
||||
.limit(limit)
|
||||
|
||||
|
||||
logger.info(`[${requestId}] Found ${memories.length} memories for workflow: ${workflowId}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
data: { memories }
|
||||
data: { memories },
|
||||
},
|
||||
{ status: 200 }
|
||||
)
|
||||
|
||||
} catch (error: any) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
@@ -103,14 +102,14 @@ export async function GET(request: NextRequest) {
|
||||
*/
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = crypto.randomUUID().slice(0, 8)
|
||||
|
||||
|
||||
try {
|
||||
logger.info(`[${requestId}] Processing memory creation request`)
|
||||
|
||||
|
||||
// Parse request body
|
||||
const body = await request.json()
|
||||
const { key, type, data, workflowId } = body
|
||||
|
||||
|
||||
// Validate required fields
|
||||
if (!key) {
|
||||
logger.warn(`[${requestId}] Missing required field: key`)
|
||||
@@ -124,7 +123,7 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if (!type || !['agent', 'raw'].includes(type)) {
|
||||
logger.warn(`[${requestId}] Invalid memory type: ${type}`)
|
||||
return NextResponse.json(
|
||||
@@ -137,7 +136,7 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if (!data) {
|
||||
logger.warn(`[${requestId}] Missing required field: data`)
|
||||
return NextResponse.json(
|
||||
@@ -150,7 +149,7 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required field: workflowId`)
|
||||
return NextResponse.json(
|
||||
@@ -163,7 +162,7 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Additional validation for agent type
|
||||
if (type === 'agent') {
|
||||
if (!data.role || !data.content) {
|
||||
@@ -178,7 +177,7 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if (!['user', 'assistant', 'system'].includes(data.role)) {
|
||||
logger.warn(`[${requestId}] Invalid agent role: ${data.role}`)
|
||||
return NextResponse.json(
|
||||
@@ -192,28 +191,24 @@ export async function POST(request: NextRequest) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if memory with the same key already exists for this workflow
|
||||
const existingMemory = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, key),
|
||||
eq(memory.workflowId, workflowId),
|
||||
isNull(memory.deletedAt)
|
||||
)
|
||||
)
|
||||
.where(and(eq(memory.key, key), eq(memory.workflowId, workflowId), isNull(memory.deletedAt)))
|
||||
.limit(1)
|
||||
|
||||
|
||||
let statusCode = 201 // Default status code for new memory
|
||||
|
||||
|
||||
if (existingMemory.length > 0) {
|
||||
logger.info(`[${requestId}] Memory with key ${key} exists, checking if we can append`)
|
||||
|
||||
|
||||
// Check if types match
|
||||
if (existingMemory[0].type !== type) {
|
||||
logger.warn(`[${requestId}] Memory type mismatch: existing=${existingMemory[0].type}, new=${type}`)
|
||||
logger.warn(
|
||||
`[${requestId}] Memory type mismatch: existing=${existingMemory[0].type}, new=${type}`
|
||||
)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
@@ -224,47 +219,42 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Handle appending based on memory type
|
||||
let updatedData;
|
||||
|
||||
let updatedData
|
||||
|
||||
if (type === 'agent') {
|
||||
// For agent type
|
||||
const newMessage = data;
|
||||
const existingData = existingMemory[0].data;
|
||||
|
||||
const newMessage = data
|
||||
const existingData = existingMemory[0].data
|
||||
|
||||
// If existing data is an array, append to it
|
||||
if (Array.isArray(existingData)) {
|
||||
updatedData = [...existingData, newMessage];
|
||||
}
|
||||
updatedData = [...existingData, newMessage]
|
||||
}
|
||||
// If existing data is a single message object, convert to array
|
||||
else {
|
||||
updatedData = [existingData, newMessage];
|
||||
updatedData = [existingData, newMessage]
|
||||
}
|
||||
} else {
|
||||
// For raw type
|
||||
// Merge objects if they're objects, otherwise use the new data
|
||||
if (typeof existingMemory[0].data === 'object' && typeof data === 'object') {
|
||||
updatedData = { ...existingMemory[0].data, ...data };
|
||||
updatedData = { ...existingMemory[0].data, ...data }
|
||||
} else {
|
||||
updatedData = data;
|
||||
updatedData = data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update the existing memory with appended data
|
||||
await db
|
||||
.update(memory)
|
||||
.set({
|
||||
.set({
|
||||
data: updatedData,
|
||||
updatedAt: new Date()
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, key),
|
||||
eq(memory.workflowId, workflowId)
|
||||
)
|
||||
)
|
||||
|
||||
.where(and(eq(memory.key, key), eq(memory.workflowId, workflowId)))
|
||||
|
||||
statusCode = 200 // Status code for updated memory
|
||||
} else {
|
||||
// Insert the new memory
|
||||
@@ -273,28 +263,22 @@ export async function POST(request: NextRequest) {
|
||||
workflowId,
|
||||
key,
|
||||
type,
|
||||
data: type === 'agent' ? Array.isArray(data) ? data : [data] : data,
|
||||
data: type === 'agent' ? (Array.isArray(data) ? data : [data]) : data,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
updatedAt: new Date(),
|
||||
}
|
||||
|
||||
|
||||
await db.insert(memory).values(newMemory)
|
||||
logger.info(`[${requestId}] Memory created successfully: ${key} for workflow: ${workflowId}`)
|
||||
}
|
||||
|
||||
|
||||
// Fetch all memories with the same key for this workflow to return the complete list
|
||||
const allMemories = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(
|
||||
and(
|
||||
eq(memory.key, key),
|
||||
eq(memory.workflowId, workflowId),
|
||||
isNull(memory.deletedAt)
|
||||
)
|
||||
)
|
||||
.where(and(eq(memory.key, key), eq(memory.workflowId, workflowId), isNull(memory.deletedAt)))
|
||||
.orderBy(memory.createdAt)
|
||||
|
||||
|
||||
if (allMemories.length === 0) {
|
||||
// This shouldn't happen but handle it just in case
|
||||
logger.warn(`[${requestId}] No memories found after creating/updating memory: ${key}`)
|
||||
@@ -308,19 +292,18 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
// Get the memory object to return
|
||||
const memoryRecord = allMemories[0];
|
||||
|
||||
const memoryRecord = allMemories[0]
|
||||
|
||||
logger.info(`[${requestId}] Memory operation successful: ${key} for workflow: ${workflowId}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
data: memoryRecord
|
||||
data: memoryRecord,
|
||||
},
|
||||
{ status: statusCode }
|
||||
)
|
||||
|
||||
} catch (error: any) {
|
||||
// Handle unique constraint violation
|
||||
if (error.code === '23505') {
|
||||
@@ -335,7 +318,7 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 409 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
@@ -346,4 +329,4 @@ export async function POST(request: NextRequest) {
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user