Skip to content
Merged
1 change: 1 addition & 0 deletions apps/sim/app/api/chat/manage/[id]/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ vi.mock('@/lib/workflows/persistence/utils', () => ({
}))
vi.mock('@/lib/workflows/orchestration', () => ({
performChatUndeploy: mockPerformChatUndeploy,
notifySocketDeploymentChanged: vi.fn().mockResolvedValue(undefined),
}))
vi.mock('drizzle-orm', () => ({
and: vi.fn((...conditions: unknown[]) => ({ type: 'and', conditions })),
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/app/api/chat/manage/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getSession } from '@/lib/auth'
import { isDev } from '@/lib/core/config/feature-flags'
import { encryptSecret } from '@/lib/core/security/encryption'
import { getEmailDomain } from '@/lib/core/utils/urls'
import { performChatUndeploy } from '@/lib/workflows/orchestration'
import { notifySocketDeploymentChanged, performChatUndeploy } from '@/lib/workflows/orchestration'
import { deployWorkflow } from '@/lib/workflows/persistence/utils'
import { checkChatAccess } from '@/app/api/chat/utils'
import { createErrorResponse, createSuccessResponse } from '@/app/api/workflows/utils'
Expand Down Expand Up @@ -155,6 +155,7 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
logger.info(
`Redeployed workflow ${existingChat[0].workflowId} for chat update (v${deployResult.version})`
)
await notifySocketDeploymentChanged(existingChat[0].workflowId)
}

let encryptedPassword
Expand Down
3 changes: 3 additions & 0 deletions apps/sim/app/api/form/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { isDev } from '@/lib/core/config/feature-flags'
import { encryptSecret } from '@/lib/core/security/encryption'
import { getEmailDomain } from '@/lib/core/utils/urls'
import { generateId } from '@/lib/core/utils/uuid'
import { notifySocketDeploymentChanged } from '@/lib/workflows/orchestration'
import { deployWorkflow } from '@/lib/workflows/persistence/utils'
import {
checkWorkflowAccessForFormCreation,
Expand Down Expand Up @@ -152,6 +153,8 @@ export async function POST(request: NextRequest) {
`${workflowRecord.isDeployed ? 'Redeployed' : 'Auto-deployed'} workflow ${workflowId} for form (v${result.version})`
)

await notifySocketDeploymentChanged(workflowId)

let encryptedPassword = null
if (authType === 'password' && password) {
const { encrypted } = await encryptSecret(password)
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/app/api/providers/ollama/models/route.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server'
import { env } from '@/lib/core/config/env'
import { getOllamaUrl } from '@/lib/core/utils/urls'
import type { ModelsObject } from '@/providers/ollama/types'
import { filterBlacklistedModels, isProviderBlacklisted } from '@/providers/utils'

const logger = createLogger('OllamaModelsAPI')
const OLLAMA_HOST = env.OLLAMA_URL || 'http://localhost:11434'
const OLLAMA_HOST = getOllamaUrl()

/**
* Get available Ollama models
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ vi.mock('@/lib/core/utils/request', () => ({

vi.mock('@/lib/core/utils/urls', () => ({
getBaseUrl: vi.fn().mockReturnValue('http://localhost:3000'),
getOllamaUrl: vi.fn().mockReturnValue('http://localhost:11434'),
}))

vi.mock('@/lib/execution/call-chain', () => ({
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/app/api/workflows/[id]/state/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { z } from 'zod'
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
import { env } from '@/lib/core/config/env'
import { generateRequestId } from '@/lib/core/utils/request'
import { getSocketServerUrl } from '@/lib/core/utils/urls'
import { extractAndPersistCustomTools } from '@/lib/workflows/persistence/custom-tools-persistence'
import {
loadWorkflowFromNormalizedTables,
Expand Down Expand Up @@ -305,8 +306,7 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
logger.info(`[${requestId}] Successfully saved workflow ${workflowId} state in ${elapsed}ms`)

try {
const socketUrl = env.SOCKET_SERVER_URL || 'http://localhost:3002'
const notifyResponse = await fetch(`${socketUrl}/api/workflow-updated`, {
const notifyResponse = await fetch(`${getSocketServerUrl()}/api/workflow-updated`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ function LineChartComponent({
className='inline-block h-[6px] w-[6px] rounded-xs'
style={{ backgroundColor: resolvedColors[s.id || ''] || s.color }}
/>
<span style={{ color: 'hsl(var(--muted-foreground))' }}>{s.label}</span>
<span className='text-[var(--text-muted)]'>{s.label}</span>
</button>
)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ export const LogsToolbar = memo(function LogsToolbar({

const [datePickerOpen, setDatePickerOpen] = useState(false)
const [previousTimeRange, setPreviousTimeRange] = useState(timeRange)
const dateRangeAppliedRef = useRef(false)
const { data: folders = {} } = useFolderMap(workspaceId)

const { data: allWorkflowList = [] } = useWorkflows(workspaceId)
Expand All @@ -249,11 +250,13 @@ export const LogsToolbar = memo(function LogsToolbar({

const statusOptions: ComboboxOption[] = useMemo(
() =>
(Object.keys(STATUS_CONFIG) as LogStatus[]).map((status) => ({
value: status,
label: STATUS_CONFIG[status].label,
icon: getColorIcon(STATUS_CONFIG[status].color),
})),
(Object.keys(STATUS_CONFIG) as LogStatus[])
.filter((status) => STATUS_CONFIG[status].filterable)
.map((status) => ({
value: status,
label: STATUS_CONFIG[status].label,
icon: getColorIcon(STATUS_CONFIG[status].color),
})),
[]
)

Expand Down Expand Up @@ -305,34 +308,29 @@ export const LogsToolbar = memo(function LogsToolbar({
[setTriggers, workspaceId]
)

const statusDisplayLabel = useMemo(() => {
if (selectedStatuses.length === 0) return 'Status'
if (selectedStatuses.length === 1) {
const status = statusOptions.find((s) => s.value === selectedStatuses[0])
return status?.label || '1 selected'
}
return `${selectedStatuses.length} selected`
}, [selectedStatuses, statusOptions])
const statusDisplayLabel =
selectedStatuses.length === 0
? 'Status'
: selectedStatuses.length === 1
? (statusOptions.find((s) => s.value === selectedStatuses[0])?.label ?? '1 selected')
: `${selectedStatuses.length} selected`

const selectedStatusColor = useMemo(() => {
if (selectedStatuses.length !== 1) return null
const status = selectedStatuses[0] as LogStatus
return STATUS_CONFIG[status]?.color ?? null
}, [selectedStatuses])
const selectedStatusColor =
selectedStatuses.length === 1
? (STATUS_CONFIG[selectedStatuses[0] as LogStatus]?.color ?? null)
: null

const workflowOptions: ComboboxOption[] = useMemo(
() => workflows.map((w) => ({ value: w.id, label: w.name, icon: getColorIcon(w.color, true) })),
[workflows]
)

const workflowDisplayLabel = useMemo(() => {
if (workflowIds.length === 0) return 'Workflow'
if (workflowIds.length === 1) {
const workflow = workflows.find((w) => w.id === workflowIds[0])
return workflow?.name || '1 selected'
}
return `${workflowIds.length} workflows`
}, [workflowIds, workflows])
const workflowDisplayLabel =
workflowIds.length === 0
? 'Workflow'
: workflowIds.length === 1
? (workflows.find((w) => w.id === workflowIds[0])?.name ?? '1 selected')
: `${workflowIds.length} workflows`

const selectedWorkflow =
workflowIds.length === 1 ? workflows.find((w) => w.id === workflowIds[0]) : null
Expand All @@ -342,14 +340,12 @@ export const LogsToolbar = memo(function LogsToolbar({
[folderList]
)

const folderDisplayLabel = useMemo(() => {
if (folderIds.length === 0) return 'Folder'
if (folderIds.length === 1) {
const folder = folderList.find((f) => f.id === folderIds[0])
return folder?.name || '1 selected'
}
return `${folderIds.length} folders`
}, [folderIds, folderList])
const folderDisplayLabel =
folderIds.length === 0
? 'Folder'
: folderIds.length === 1
? (folderList.find((f) => f.id === folderIds[0])?.name ?? '1 selected')
: `${folderIds.length} folders`

const triggerOptions: ComboboxOption[] = useMemo(
() =>
Expand All @@ -361,23 +357,21 @@ export const LogsToolbar = memo(function LogsToolbar({
[]
)

const triggerDisplayLabel = useMemo(() => {
if (triggers.length === 0) return 'Trigger'
if (triggers.length === 1) {
const trigger = triggerOptions.find((t) => t.value === triggers[0])
return trigger?.label || '1 selected'
}
return `${triggers.length} triggers`
}, [triggers, triggerOptions])

const timeDisplayLabel = useMemo(() => {
if (timeRange === 'All time') return 'Time'
if (timeRange === 'Custom range' && startDate && endDate) {
return `${formatDateShort(startDate)} - ${formatDateShort(endDate)}`
}
if (timeRange === 'Custom range') return 'Custom range'
return timeRange
}, [timeRange, startDate, endDate])
const triggerDisplayLabel =
triggers.length === 0
? 'Trigger'
: triggers.length === 1
? (triggerOptions.find((t) => t.value === triggers[0])?.label ?? '1 selected')
: `${triggers.length} triggers`

const timeDisplayLabel =
timeRange === 'All time'
? 'Time'
: timeRange === 'Custom range' && startDate && endDate
? `${formatDateShort(startDate)} - ${formatDateShort(endDate)}`
: timeRange === 'Custom range'
? 'Custom range'
: timeRange

/**
* Handles time range selection from combobox.
Expand Down Expand Up @@ -405,6 +399,7 @@ export const LogsToolbar = memo(function LogsToolbar({
*/
const handleDateRangeApply = useCallback(
(start: string, end: string) => {
dateRangeAppliedRef.current = true
setDateRange(start, end)
setDatePickerOpen(false)
captureEvent(posthogRef.current, 'logs_filter_applied', {
Expand Down Expand Up @@ -792,42 +787,38 @@ export const LogsToolbar = memo(function LogsToolbar({
/>

{/* Timeline Filter */}
<DropdownMenu open={datePickerOpen} onOpenChange={setDatePickerOpen}>
<DropdownMenuTrigger asChild>
<div>
<Combobox
options={TIME_RANGE_OPTIONS as unknown as ComboboxOption[]}
value={timeRange}
onChange={handleTimeRangeChange}
placeholder='Time'
overlayContent={
<span className='truncate text-[var(--text-primary)]'>
{timeDisplayLabel}
</span>
}
size='sm'
align='end'
className='h-[32px] w-[120px] rounded-md'
/>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent
side='bottom'
<div className='relative'>
<Combobox
options={TIME_RANGE_OPTIONS as unknown as ComboboxOption[]}
value={timeRange}
onChange={handleTimeRangeChange}
placeholder='Time'
overlayContent={
<span className='truncate text-[var(--text-primary)]'>{timeDisplayLabel}</span>
}
size='sm'
align='end'
sideOffset={4}
collisionPadding={16}
className='w-auto p-0'
>
<DatePicker
mode='range'
startDate={startDate}
endDate={endDate}
onRangeChange={handleDateRangeApply}
onCancel={handleDatePickerCancel}
inline
/>
</DropdownMenuContent>
</DropdownMenu>
className='h-[32px] w-[120px] rounded-md'
/>
<DatePicker
mode='range'
showTrigger={false}
open={datePickerOpen}
onOpenChange={(isOpen) => {
if (!isOpen) {
if (dateRangeAppliedRef.current) {
dateRangeAppliedRef.current = false
} else {
handleDatePickerCancel()
}
}
}}
startDate={startDate}
endDate={endDate}
onRangeChange={handleDateRangeApply}
onCancel={handleDatePickerCancel}
/>
</div>
</div>
</div>
</div>
Expand Down
Loading
Loading