Skip to content

Commit 570c07b

Browse files
Merge pull request #1004 from simstudioai/staging
v0.3.29: copilot fixes, remove block from subflow, code cleanups
2 parents 97b6bcc + 5c16e7d commit 570c07b

File tree

64 files changed

+14132
-2681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+14132
-2681
lines changed

apps/sim/app/api/copilot/api-keys/validate/route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export async function POST(req: NextRequest) {
6565

6666
if (!Number.isNaN(limit) && limit > 0 && currentUsage >= limit) {
6767
// Usage exceeded
68+
logger.info('[API VALIDATION] Usage exceeded', { userId, currentUsage, limit })
6869
return new NextResponse(null, { status: 402 })
6970
}
7071
}

apps/sim/app/api/copilot/chat/route.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -371,26 +371,50 @@ export async function POST(req: NextRequest) {
371371
(currentChat?.conversationId as string | undefined) || conversationId
372372

373373
// If we have a conversationId, only send the most recent user message; else send full history
374-
const messagesForAgent = effectiveConversationId ? [messages[messages.length - 1]] : messages
374+
const latestUserMessage =
375+
[...messages].reverse().find((m) => m?.role === 'user') || messages[messages.length - 1]
376+
const messagesForAgent = effectiveConversationId ? [latestUserMessage] : messages
377+
378+
const requestPayload = {
379+
messages: messagesForAgent,
380+
workflowId,
381+
userId: authenticatedUserId,
382+
stream: stream,
383+
streamToolCalls: true,
384+
mode: mode,
385+
provider: providerToUse,
386+
...(effectiveConversationId ? { conversationId: effectiveConversationId } : {}),
387+
...(typeof depth === 'number' ? { depth } : {}),
388+
...(session?.user?.name && { userName: session.user.name }),
389+
}
390+
391+
// Log the payload being sent to the streaming endpoint
392+
try {
393+
logger.info(`[${tracker.requestId}] Sending payload to sim agent streaming endpoint`, {
394+
url: `${SIM_AGENT_API_URL}/api/chat-completion-streaming`,
395+
provider: providerToUse,
396+
mode,
397+
stream,
398+
workflowId,
399+
hasConversationId: !!effectiveConversationId,
400+
depth: typeof depth === 'number' ? depth : undefined,
401+
messagesCount: requestPayload.messages.length,
402+
})
403+
// Full payload as JSON string
404+
logger.info(
405+
`[${tracker.requestId}] Full streaming payload: ${JSON.stringify(requestPayload)}`
406+
)
407+
} catch (e) {
408+
logger.warn(`[${tracker.requestId}] Failed to log payload preview for streaming endpoint`, e)
409+
}
375410

376411
const simAgentResponse = await fetch(`${SIM_AGENT_API_URL}/api/chat-completion-streaming`, {
377412
method: 'POST',
378413
headers: {
379414
'Content-Type': 'application/json',
380415
...(env.COPILOT_API_KEY ? { 'x-api-key': env.COPILOT_API_KEY } : {}),
381416
},
382-
body: JSON.stringify({
383-
messages: messagesForAgent,
384-
workflowId,
385-
userId: authenticatedUserId,
386-
stream: stream,
387-
streamToolCalls: true,
388-
mode: mode,
389-
provider: providerToUse,
390-
...(effectiveConversationId ? { conversationId: effectiveConversationId } : {}),
391-
...(typeof depth === 'number' ? { depth } : {}),
392-
...(session?.user?.name && { userName: session.user.name }),
393-
}),
417+
body: JSON.stringify(requestPayload),
394418
})
395419

396420
if (!simAgentResponse.ok) {
@@ -690,7 +714,7 @@ export async function POST(req: NextRequest) {
690714
)
691715
}
692716

693-
const responseId = responseIdFromDone || responseIdFromStart
717+
const responseId = responseIdFromDone
694718

695719
// Update chat in database immediately (without title)
696720
await db

apps/sim/app/api/logs/[executionId]/frozen-canvas/route.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,7 @@ export async function GET(
4646
startedAt: workflowLog.startedAt.toISOString(),
4747
endedAt: workflowLog.endedAt?.toISOString(),
4848
totalDurationMs: workflowLog.totalDurationMs,
49-
blockStats: {
50-
total: workflowLog.blockCount,
51-
success: workflowLog.successCount,
52-
error: workflowLog.errorCount,
53-
skipped: workflowLog.skippedCount,
54-
},
55-
cost: {
56-
total: workflowLog.totalCost ? Number.parseFloat(workflowLog.totalCost) : null,
57-
input: workflowLog.totalInputCost ? Number.parseFloat(workflowLog.totalInputCost) : null,
58-
output: workflowLog.totalOutputCost
59-
? Number.parseFloat(workflowLog.totalOutputCost)
60-
: null,
61-
},
62-
totalTokens: workflowLog.totalTokens,
49+
cost: workflowLog.cost || null,
6350
},
6451
}
6552

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { and, eq } from 'drizzle-orm'
2+
import { type NextRequest, NextResponse } from 'next/server'
3+
import { getSession } from '@/lib/auth'
4+
import { createLogger } from '@/lib/logs/console/logger'
5+
import { db } from '@/db'
6+
import { permissions, workflow, workflowExecutionLogs } from '@/db/schema'
7+
8+
const logger = createLogger('LogDetailsByIdAPI')
9+
10+
export const revalidate = 0
11+
12+
export async function GET(_request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
13+
const requestId = crypto.randomUUID().slice(0, 8)
14+
15+
try {
16+
const session = await getSession()
17+
if (!session?.user?.id) {
18+
logger.warn(`[${requestId}] Unauthorized log details access attempt`)
19+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
20+
}
21+
22+
const userId = session.user.id
23+
const { id } = await params
24+
25+
const rows = await db
26+
.select({
27+
id: workflowExecutionLogs.id,
28+
workflowId: workflowExecutionLogs.workflowId,
29+
executionId: workflowExecutionLogs.executionId,
30+
stateSnapshotId: workflowExecutionLogs.stateSnapshotId,
31+
level: workflowExecutionLogs.level,
32+
trigger: workflowExecutionLogs.trigger,
33+
startedAt: workflowExecutionLogs.startedAt,
34+
endedAt: workflowExecutionLogs.endedAt,
35+
totalDurationMs: workflowExecutionLogs.totalDurationMs,
36+
executionData: workflowExecutionLogs.executionData,
37+
cost: workflowExecutionLogs.cost,
38+
files: workflowExecutionLogs.files,
39+
createdAt: workflowExecutionLogs.createdAt,
40+
workflowName: workflow.name,
41+
workflowDescription: workflow.description,
42+
workflowColor: workflow.color,
43+
workflowFolderId: workflow.folderId,
44+
workflowUserId: workflow.userId,
45+
workflowWorkspaceId: workflow.workspaceId,
46+
workflowCreatedAt: workflow.createdAt,
47+
workflowUpdatedAt: workflow.updatedAt,
48+
})
49+
.from(workflowExecutionLogs)
50+
.innerJoin(workflow, eq(workflowExecutionLogs.workflowId, workflow.id))
51+
.innerJoin(
52+
permissions,
53+
and(
54+
eq(permissions.entityType, 'workspace'),
55+
eq(permissions.entityId, workflow.workspaceId),
56+
eq(permissions.userId, userId)
57+
)
58+
)
59+
.where(eq(workflowExecutionLogs.id, id))
60+
.limit(1)
61+
62+
const log = rows[0]
63+
if (!log) {
64+
return NextResponse.json({ error: 'Not found' }, { status: 404 })
65+
}
66+
67+
const workflowSummary = {
68+
id: log.workflowId,
69+
name: log.workflowName,
70+
description: log.workflowDescription,
71+
color: log.workflowColor,
72+
folderId: log.workflowFolderId,
73+
userId: log.workflowUserId,
74+
workspaceId: log.workflowWorkspaceId,
75+
createdAt: log.workflowCreatedAt,
76+
updatedAt: log.workflowUpdatedAt,
77+
}
78+
79+
const response = {
80+
id: log.id,
81+
workflowId: log.workflowId,
82+
executionId: log.executionId,
83+
level: log.level,
84+
duration: log.totalDurationMs ? `${log.totalDurationMs}ms` : null,
85+
trigger: log.trigger,
86+
createdAt: log.startedAt.toISOString(),
87+
files: log.files || undefined,
88+
workflow: workflowSummary,
89+
executionData: {
90+
totalDuration: log.totalDurationMs,
91+
...(log.executionData as any),
92+
enhanced: true,
93+
},
94+
cost: log.cost as any,
95+
}
96+
97+
return NextResponse.json({ data: response })
98+
} catch (error: any) {
99+
logger.error(`[${requestId}] log details fetch error`, error)
100+
return NextResponse.json({ error: error.message }, { status: 500 })
101+
}
102+
}

apps/sim/app/api/logs/cleanup/route.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,13 @@ export async function GET(request: NextRequest) {
9999
executionId: workflowExecutionLogs.executionId,
100100
stateSnapshotId: workflowExecutionLogs.stateSnapshotId,
101101
level: workflowExecutionLogs.level,
102-
message: workflowExecutionLogs.message,
103102
trigger: workflowExecutionLogs.trigger,
104103
startedAt: workflowExecutionLogs.startedAt,
105104
endedAt: workflowExecutionLogs.endedAt,
106105
totalDurationMs: workflowExecutionLogs.totalDurationMs,
107-
blockCount: workflowExecutionLogs.blockCount,
108-
successCount: workflowExecutionLogs.successCount,
109-
errorCount: workflowExecutionLogs.errorCount,
110-
skippedCount: workflowExecutionLogs.skippedCount,
111-
totalCost: workflowExecutionLogs.totalCost,
112-
totalInputCost: workflowExecutionLogs.totalInputCost,
113-
totalOutputCost: workflowExecutionLogs.totalOutputCost,
114-
totalTokens: workflowExecutionLogs.totalTokens,
106+
executionData: workflowExecutionLogs.executionData,
107+
cost: workflowExecutionLogs.cost,
115108
files: workflowExecutionLogs.files,
116-
metadata: workflowExecutionLogs.metadata,
117109
createdAt: workflowExecutionLogs.createdAt,
118110
})
119111
.from(workflowExecutionLogs)

0 commit comments

Comments
 (0)