Skip to content

Commit 72eed27

Browse files
committed
Clean code, fix bugs
1 parent 82a8aa5 commit 72eed27

File tree

27 files changed

+634
-2931
lines changed

27 files changed

+634
-2931
lines changed

apps/sim/app/api/workflows/[id]/deployments/[version]/revert/route.ts

Lines changed: 15 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
import { db, workflow, workflowDeploymentVersion } from '@sim/db'
21
import { createLogger } from '@sim/logger'
3-
import { and, eq } from 'drizzle-orm'
42
import type { NextRequest } from 'next/server'
5-
import { AuditAction, AuditResourceType, recordAudit } from '@/lib/audit/log'
6-
import { env } from '@/lib/core/config/env'
73
import { generateRequestId } from '@/lib/core/utils/request'
8-
import { captureServerEvent } from '@/lib/posthog/server'
9-
import { saveWorkflowToNormalizedTables } from '@/lib/workflows/persistence/utils'
4+
import { performRevertToVersion } from '@/lib/workflows/orchestration'
105
import { validateWorkflowPermissions } from '@/lib/workflows/utils'
116
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
127

@@ -37,105 +32,26 @@ export async function POST(
3732
return createErrorResponse('Invalid version', 400)
3833
}
3934

40-
let stateRow: { state: any } | null = null
41-
if (version === 'active') {
42-
const [row] = await db
43-
.select({ state: workflowDeploymentVersion.state })
44-
.from(workflowDeploymentVersion)
45-
.where(
46-
and(
47-
eq(workflowDeploymentVersion.workflowId, id),
48-
eq(workflowDeploymentVersion.isActive, true)
49-
)
50-
)
51-
.limit(1)
52-
stateRow = row || null
53-
} else {
54-
const [row] = await db
55-
.select({ state: workflowDeploymentVersion.state })
56-
.from(workflowDeploymentVersion)
57-
.where(
58-
and(
59-
eq(workflowDeploymentVersion.workflowId, id),
60-
eq(workflowDeploymentVersion.version, versionSelector as number)
61-
)
62-
)
63-
.limit(1)
64-
stateRow = row || null
65-
}
66-
67-
if (!stateRow?.state) {
68-
return createErrorResponse('Deployment version not found', 404)
69-
}
70-
71-
const deployedState = stateRow.state
72-
if (!deployedState.blocks || !deployedState.edges) {
73-
return createErrorResponse('Invalid deployed state structure', 500)
74-
}
75-
76-
const saveResult = await saveWorkflowToNormalizedTables(id, {
77-
blocks: deployedState.blocks,
78-
edges: deployedState.edges,
79-
loops: deployedState.loops || {},
80-
parallels: deployedState.parallels || {},
81-
lastSaved: Date.now(),
82-
})
83-
84-
if (!saveResult.success) {
85-
return createErrorResponse(saveResult.error || 'Failed to save deployed state', 500)
86-
}
87-
88-
await db
89-
.update(workflow)
90-
.set({ lastSynced: new Date(), updatedAt: new Date() })
91-
.where(eq(workflow.id, id))
92-
93-
try {
94-
const socketServerUrl = env.SOCKET_SERVER_URL || 'http://localhost:3002'
95-
await fetch(`${socketServerUrl}/api/workflow-reverted`, {
96-
method: 'POST',
97-
headers: {
98-
'Content-Type': 'application/json',
99-
'x-api-key': env.INTERNAL_API_SECRET,
100-
},
101-
body: JSON.stringify({ workflowId: id, timestamp: Date.now() }),
102-
})
103-
} catch (e) {
104-
logger.error('Error sending workflow reverted event to socket server', e)
105-
}
106-
107-
captureServerEvent(
108-
session!.user.id,
109-
'workflow_deployment_reverted',
110-
{
111-
workflow_id: id,
112-
workspace_id: workflowRecord?.workspaceId ?? '',
113-
version,
114-
},
115-
workflowRecord?.workspaceId
116-
? { groups: { workspace: workflowRecord.workspaceId } }
117-
: undefined
118-
)
119-
120-
recordAudit({
121-
workspaceId: workflowRecord?.workspaceId ?? null,
122-
actorId: session!.user.id,
123-
action: AuditAction.WORKFLOW_DEPLOYMENT_REVERTED,
124-
resourceType: AuditResourceType.WORKFLOW,
125-
resourceId: id,
35+
const result = await performRevertToVersion({
36+
workflowId: id,
37+
version: version === 'active' ? 'active' : (versionSelector as number),
38+
userId: session!.user.id,
39+
workflow: (workflowRecord ?? {}) as Record<string, unknown>,
40+
request,
12641
actorName: session!.user.name ?? undefined,
12742
actorEmail: session!.user.email ?? undefined,
128-
resourceName: workflowRecord?.name ?? undefined,
129-
description: `Reverted workflow to deployment version ${version}`,
130-
metadata: {
131-
targetVersion: version,
132-
},
133-
request,
13443
})
13544

45+
if (!result.success) {
46+
return createErrorResponse(
47+
result.error || 'Failed to revert',
48+
result.errorCode === 'not_found' ? 404 : 500
49+
)
50+
}
51+
13652
return createSuccessResponse({
13753
message: 'Reverted to deployment version',
138-
lastSaved: Date.now(),
54+
lastSaved: result.lastSaved,
13955
})
14056
} catch (error: any) {
14157
logger.error('Error reverting to deployment version', error)

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/tool-call-item.tsx

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useMemo } from 'react'
22
import { PillsRing } from '@/components/emcn'
3-
import { FunctionExecute, WorkspaceFile } from '@/lib/copilot/generated/tool-catalog-v1'
3+
import { WorkspaceFile } from '@/lib/copilot/generated/tool-catalog-v1'
44
import type { ToolCallStatus } from '../../../../types'
55
import { getToolIcon } from '../../utils'
66

@@ -56,42 +56,6 @@ function StatusIcon({ status, toolName }: { status: ToolCallStatus; toolName: st
5656
return <CircleCheck className='h-[15px] w-[15px] text-[var(--text-tertiary)]' />
5757
}
5858

59-
const LANG_ALIASES: Record<string, string> = {
60-
javascript: 'javascript',
61-
python: 'python',
62-
shell: 'bash',
63-
bash: 'bash',
64-
}
65-
66-
function extractFunctionExecutePreview(raw: string): { code: string; lang: string } | null {
67-
if (!raw) return null
68-
const langMatch = raw.match(/"language"\s*:\s*"(\w+)"/)
69-
const lang = langMatch ? (LANG_ALIASES[langMatch[1]] ?? langMatch[1]) : 'javascript'
70-
71-
const codeStart = raw.indexOf('"code"')
72-
if (codeStart === -1) return null
73-
const colonIdx = raw.indexOf(':', codeStart + 6)
74-
if (colonIdx === -1) return null
75-
const quoteIdx = raw.indexOf('"', colonIdx + 1)
76-
if (quoteIdx === -1) return null
77-
78-
let value = raw.slice(quoteIdx + 1)
79-
if (value.endsWith('"}') || value.endsWith('"\n}')) {
80-
value = value.replace(/"\s*\}?\s*$/, '')
81-
}
82-
if (value.endsWith('"')) {
83-
value = value.slice(0, -1)
84-
}
85-
86-
const code = value
87-
.replace(/\\n/g, '\n')
88-
.replace(/\\t/g, '\t')
89-
.replace(/\\"/g, '"')
90-
.replace(/\\\\/g, '\\')
91-
92-
return code.length > 0 ? { code, lang } : null
93-
}
94-
9559
interface ToolCallItemProps {
9660
toolName: string
9761
displayTitle: string
@@ -128,14 +92,6 @@ export function ToolCallItem({ toolName, displayTitle, status, streamingArgs }:
12892
.replace(/\\\\/g, '\\')
12993
return `${verb} ${unescaped}`
13094
}, [toolName, streamingArgs])
131-
const extracted = useMemo(() => {
132-
if (toolName !== FunctionExecute.id || !streamingArgs) return null
133-
return extractFunctionExecutePreview(streamingArgs)
134-
}, [toolName, streamingArgs])
135-
const markdown = useMemo(
136-
() => (extracted ? `\`\`\`${extracted.lang}\n${extracted.code}\n\`\`\`` : null),
137-
[extracted]
138-
)
13995

14096
return (
14197
<div className='flex items-center gap-[8px] pl-[24px]'>

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
WorkspaceFile,
77
} from '@/lib/copilot/generated/tool-catalog-v1'
88
import { resolveToolDisplay } from '@/lib/copilot/tools/client/store-utils'
9-
import { ClientToolCallState } from '@/lib/copilot/tools/client/tool-display-registry'
9+
import { ClientToolCallState } from '@/lib/copilot/tools/client/tool-call-state'
1010
import type { ContentBlock, MothershipResource, OptionItem, ToolCallData } from '../../types'
1111
import { SUBAGENT_LABELS, TOOL_UI_METADATA } from '../../types'
1212
import type { AgentGroupItem } from './components'
@@ -94,8 +94,7 @@ function mapToolStatusToClientState(
9494

9595
function getOverrideDisplayTitle(tc: NonNullable<ContentBlock['toolCall']>): string | undefined {
9696
if (tc.name === ReadTool.id || tc.name === 'respond' || tc.name.endsWith('_respond')) {
97-
return resolveToolDisplay(tc.name, mapToolStatusToClientState(tc.status), tc.id, tc.params)
98-
?.text
97+
return resolveToolDisplay(tc.name, mapToolStatusToClientState(tc.status), tc.params)?.text
9998
}
10099
return undefined
101100
}

apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,6 @@ function resolveStreamingToolDisplayTitle(name: string, streamingArgs: string):
494494
type StreamToolUI = {
495495
hidden?: boolean
496496
title?: string
497-
phaseLabel?: string
498497
clientExecutable?: boolean
499498
}
500499

@@ -597,10 +596,16 @@ function getToolUI(ui?: MothershipStreamV1ToolUI): StreamToolUI | undefined {
597596
return undefined
598597
}
599598

599+
const title =
600+
typeof ui.title === 'string'
601+
? ui.title
602+
: typeof ui.phaseLabel === 'string'
603+
? ui.phaseLabel
604+
: undefined
605+
600606
return {
601607
...(typeof ui.hidden === 'boolean' ? { hidden: ui.hidden } : {}),
602-
...(typeof ui.title === 'string' ? { title: ui.title } : {}),
603-
...(typeof ui.phaseLabel === 'string' ? { phaseLabel: ui.phaseLabel } : {}),
608+
...(title ? { title } : {}),
604609
...(typeof ui.clientExecutable === 'boolean' ? { clientExecutable: ui.clientExecutable } : {}),
605610
}
606611
}
@@ -1934,8 +1939,7 @@ export function useChat(
19341939
}
19351940
const ui = getToolUI(payload.ui)
19361941
if (ui?.hidden) break
1937-
let displayTitle = ui?.title || ui?.phaseLabel
1938-
const phaseLabel = ui?.phaseLabel
1942+
let displayTitle = ui?.title
19391943
const args = payload.arguments as Record<string, unknown> | undefined
19401944

19411945
displayTitle = resolveToolDisplayTitle(name, args) ?? displayTitle
@@ -1966,7 +1970,6 @@ export function useChat(
19661970
name,
19671971
status: 'executing',
19681972
displayTitle,
1969-
phaseLabel,
19701973
params: args,
19711974
calledBy: activeSubagent,
19721975
},
@@ -1980,7 +1983,6 @@ export function useChat(
19801983
if (tc) {
19811984
tc.name = name
19821985
if (displayTitle) tc.displayTitle = displayTitle
1983-
if (phaseLabel) tc.phaseLabel = phaseLabel
19841986
if (args) tc.params = args
19851987
}
19861988
}
@@ -2525,13 +2527,7 @@ export function useChat(
25252527
const isCancelled =
25262528
block.toolCall.status === 'executing' || block.toolCall.status === 'cancelled'
25272529
const displayTitle = isCancelled ? 'Stopped by user' : block.toolCall.displayTitle
2528-
const display =
2529-
displayTitle || block.toolCall.phaseLabel
2530-
? {
2531-
...(displayTitle ? { title: displayTitle } : {}),
2532-
...(block.toolCall.phaseLabel ? { phaseLabel: block.toolCall.phaseLabel } : {}),
2533-
}
2534-
: undefined
2530+
const display = displayTitle ? { title: displayTitle } : undefined
25352531
return {
25362532
type: block.type,
25372533
content: block.content,

0 commit comments

Comments
 (0)