Skip to content

Commit 39444af

Browse files
Merge pull request #688 from simstudioai/staging
v0.2.14: fix + improvement
2 parents 7192cde + a030329 commit 39444af

Some content is hidden

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

56 files changed

+278
-200
lines changed

apps/docs/app/global.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
@import "tailwindcss";
22
@import "fumadocs-ui/css/neutral.css";
33
@import "fumadocs-ui/css/preset.css";
4-
:root {
4+
5+
@theme {
56
--color-fd-primary: #802fff; /* Purple from control-bar component */
67
}
78

@@ -15,4 +16,9 @@
1516
color: var(--color-fd-primary);
1617
}
1718

19+
/* Tailwind v4 content sources */
20+
@source '../app/**/*.{js,ts,jsx,tsx,mdx}';
21+
@source '../components/**/*.{js,ts,jsx,tsx,mdx}';
22+
@source '../content/**/*.{js,ts,jsx,tsx,mdx}';
23+
@source '../mdx-components.tsx';
1824
@source '../node_modules/fumadocs-ui/dist/**/*.js';

apps/sim/app/api/knowledge/[id]/documents/route.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { type NextRequest, NextResponse } from 'next/server'
44
import { z } from 'zod'
55
import { getSession } from '@/lib/auth'
66
import { createLogger } from '@/lib/logs/console-logger'
7+
import { getUserId } from '@/app/api/auth/oauth/utils'
78
import { db } from '@/db'
89
import { document } from '@/db/schema'
910
import { checkKnowledgeBaseAccess, processDocumentAsync } from '../../utils'
@@ -269,27 +270,41 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
269270
const { id: knowledgeBaseId } = await params
270271

271272
try {
272-
const session = await getSession()
273-
if (!session?.user?.id) {
274-
logger.warn(`[${requestId}] Unauthorized document creation attempt`)
275-
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
273+
const body = await req.json()
274+
const { workflowId } = body
275+
276+
logger.info(`[${requestId}] Knowledge base document creation request`, {
277+
knowledgeBaseId,
278+
workflowId,
279+
hasWorkflowId: !!workflowId,
280+
bodyKeys: Object.keys(body),
281+
})
282+
283+
const userId = await getUserId(requestId, workflowId)
284+
285+
if (!userId) {
286+
const errorMessage = workflowId ? 'Workflow not found' : 'Unauthorized'
287+
const statusCode = workflowId ? 404 : 401
288+
logger.warn(`[${requestId}] Authentication failed: ${errorMessage}`, {
289+
workflowId,
290+
hasWorkflowId: !!workflowId,
291+
})
292+
return NextResponse.json({ error: errorMessage }, { status: statusCode })
276293
}
277294

278-
const accessCheck = await checkKnowledgeBaseAccess(knowledgeBaseId, session.user.id)
295+
const accessCheck = await checkKnowledgeBaseAccess(knowledgeBaseId, userId)
279296

280297
if (!accessCheck.hasAccess) {
281298
if ('notFound' in accessCheck && accessCheck.notFound) {
282299
logger.warn(`[${requestId}] Knowledge base not found: ${knowledgeBaseId}`)
283300
return NextResponse.json({ error: 'Knowledge base not found' }, { status: 404 })
284301
}
285302
logger.warn(
286-
`[${requestId}] User ${session.user.id} attempted to create document in unauthorized knowledge base ${knowledgeBaseId}`
303+
`[${requestId}] User ${userId} attempted to create document in unauthorized knowledge base ${knowledgeBaseId}`
287304
)
288305
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
289306
}
290307

291-
const body = await req.json()
292-
293308
// Check if this is a bulk operation
294309
if (body.bulk === true) {
295310
// Handle bulk processing (replaces process-documents endpoint)

apps/sim/app/unsubscribe/page.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { useEffect, useState } from 'react'
3+
import { Suspense, useEffect, useState } from 'react'
44
import { CheckCircle, Heart, Info, Loader2, XCircle } from 'lucide-react'
55
import { useSearchParams } from 'next/navigation'
66
import { Button } from '@/components/ui/button'
@@ -20,7 +20,7 @@ interface UnsubscribeData {
2020
}
2121
}
2222

23-
export default function UnsubscribePage() {
23+
function UnsubscribeContent() {
2424
const searchParams = useSearchParams()
2525
const [loading, setLoading] = useState(true)
2626
const [data, setData] = useState<UnsubscribeData | null>(null)
@@ -380,3 +380,21 @@ export default function UnsubscribePage() {
380380
</div>
381381
)
382382
}
383+
384+
export default function UnsubscribePage() {
385+
return (
386+
<Suspense
387+
fallback={
388+
<div className='flex min-h-screen items-center justify-center bg-background'>
389+
<Card className='w-full max-w-md border shadow-sm'>
390+
<CardContent className='flex items-center justify-center p-8'>
391+
<Loader2 className='h-8 w-8 animate-spin text-muted-foreground' />
392+
</CardContent>
393+
</Card>
394+
</div>
395+
}
396+
>
397+
<UnsubscribeContent />
398+
</Suspense>
399+
)
400+
}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts

Lines changed: 4 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ export function useSubBlockValue<T = any>(
181181
triggerWorkflowUpdate = false,
182182
options?: UseSubBlockValueOptions
183183
): readonly [T | null, (value: T) => void] {
184-
const { debounceMs = 150, isStreaming = false, onStreamingEnd } = options || {}
184+
const { isStreaming = false, onStreamingEnd } = options || {}
185185

186186
const { collaborativeSetSubblockValue } = useCollaborativeWorkflow()
187187

@@ -202,8 +202,7 @@ export function useSubBlockValue<T = any>(
202202
// Previous model reference for detecting model changes
203203
const prevModelRef = useRef<string | null>(null)
204204

205-
// Debouncing refs
206-
const debounceTimerRef = useRef<NodeJS.Timeout | null>(null)
205+
// Streaming refs
207206
const lastEmittedValueRef = useRef<T | null>(null)
208207
const streamingValueRef = useRef<T | null>(null)
209208
const wasStreamingRef = useRef<boolean>(false)
@@ -232,15 +231,6 @@ export function useSubBlockValue<T = any>(
232231
// Compute the modelValue based on block type
233232
const modelValue = isProviderBasedBlock ? (modelSubBlockValue as string) : null
234233

235-
// Cleanup timer on unmount
236-
useEffect(() => {
237-
return () => {
238-
if (debounceTimerRef.current) {
239-
clearTimeout(debounceTimerRef.current)
240-
}
241-
}
242-
}, [])
243-
244234
// Emit the value to socket/DB
245235
const emitValue = useCallback(
246236
(value: T) => {
@@ -299,26 +289,12 @@ export function useSubBlockValue<T = any>(
299289
storeApiKeyValue(blockId, blockType, modelValue, newValue, storeValue)
300290
}
301291

302-
// Clear any existing debounce timer
303-
if (debounceTimerRef.current) {
304-
clearTimeout(debounceTimerRef.current)
305-
debounceTimerRef.current = null
306-
}
307-
308292
// If streaming, just store the value without emitting
309293
if (isStreaming) {
310294
streamingValueRef.current = valueCopy
311295
} else {
312-
// Detect large changes for extended debounce
313-
const isLargeChange = detectLargeChange(lastEmittedValueRef.current, valueCopy)
314-
const effectiveDebounceMs = isLargeChange ? debounceMs * 2 : debounceMs
315-
316-
// Debounce the socket emission
317-
debounceTimerRef.current = setTimeout(() => {
318-
if (valueRef.current !== null && valueRef.current !== lastEmittedValueRef.current) {
319-
emitValue(valueCopy)
320-
}
321-
}, effectiveDebounceMs)
296+
// Emit immediately - let the operation queue handle debouncing and deduplication
297+
emitValue(valueCopy)
322298
}
323299

324300
if (triggerWorkflowUpdate) {
@@ -335,7 +311,6 @@ export function useSubBlockValue<T = any>(
335311
triggerWorkflowUpdate,
336312
modelValue,
337313
isStreaming,
338-
debounceMs,
339314
emitValue,
340315
]
341316
)
@@ -412,26 +387,3 @@ export function useSubBlockValue<T = any>(
412387
// Return appropriate tuple based on whether options were provided
413388
return [storeValue !== undefined ? storeValue : initialValue, setValue] as const
414389
}
415-
416-
// Helper function to detect large changes
417-
function detectLargeChange(oldValue: any, newValue: any): boolean {
418-
// Handle null/undefined
419-
if (oldValue == null && newValue == null) return false
420-
if (oldValue == null || newValue == null) return true
421-
422-
// For strings, check if it's a large paste or deletion
423-
if (typeof oldValue === 'string' && typeof newValue === 'string') {
424-
const sizeDiff = Math.abs(newValue.length - oldValue.length)
425-
// Consider it a large change if more than 50 characters changed at once
426-
return sizeDiff > 50
427-
}
428-
429-
// For arrays, check length difference
430-
if (Array.isArray(oldValue) && Array.isArray(newValue)) {
431-
const sizeDiff = Math.abs(newValue.length - oldValue.length)
432-
return sizeDiff > 5
433-
}
434-
435-
// For other types, always treat as small change
436-
return false
437-
}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ const WorkflowContent = React.memo(() => {
500500
let autoConnectEdge
501501
if (isAutoConnectEnabled && type !== 'starter') {
502502
const closestBlock = findClosestOutput(centerPosition)
503-
console.log('🎯 Closest block found:', closestBlock)
503+
logger.info('🎯 Closest block found:', closestBlock)
504504
if (closestBlock) {
505505
// Get appropriate source handle
506506
const sourceHandle = determineSourceHandle(closestBlock)
@@ -513,7 +513,7 @@ const WorkflowContent = React.memo(() => {
513513
targetHandle: 'target',
514514
type: 'workflowEdge',
515515
}
516-
console.log('✅ Auto-connect edge created:', autoConnectEdge)
516+
logger.info('✅ Auto-connect edge created:', autoConnectEdge)
517517
}
518518
}
519519

apps/sim/lib/auth-client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { stripeClient } from '@better-auth/stripe/client'
22
import { emailOTPClient, genericOAuthClient, organizationClient } from 'better-auth/client/plugins'
33
import { createAuthClient } from 'better-auth/react'
4-
import { env } from './env'
5-
import { isDev, isProd } from './environment'
4+
import { env } from '@/lib/env'
5+
import { isDev, isProd } from '@/lib/environment'
66

77
export function getBaseURL() {
88
let baseURL

apps/sim/lib/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ import {
1919
renderOTPEmail,
2020
renderPasswordResetEmail,
2121
} from '@/components/emails/render-email'
22+
import { getBaseURL } from '@/lib/auth-client'
2223
import { env, isTruthy } from '@/lib/env'
2324
import { isProd } from '@/lib/environment'
2425
import { createLogger } from '@/lib/logs/console-logger'
2526
import { getEmailDomain } from '@/lib/urls/utils'
2627
import { db } from '@/db'
2728
import * as schema from '@/db/schema'
28-
import { getBaseURL } from './auth-client'
2929

3030
const logger = createLogger('Auth')
3131

apps/sim/lib/billing/calculations/usage-monitor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { eq } from 'drizzle-orm'
2+
import { getUserUsageLimit } from '@/lib/billing/core/usage'
23
import { isProd } from '@/lib/environment'
34
import { createLogger } from '@/lib/logs/console-logger'
45
import { db } from '@/db'
56
import { userStats } from '@/db/schema'
6-
import { getUserUsageLimit } from '../core/usage'
77

88
const logger = createLogger('UsageMonitor')
99

apps/sim/lib/billing/core/billing.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { and, eq } from 'drizzle-orm'
2+
import {
3+
resetOrganizationBillingPeriod,
4+
resetUserBillingPeriod,
5+
} from '@/lib/billing/core/billing-periods'
6+
import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription'
7+
import { getUserUsageData } from '@/lib/billing/core/usage'
8+
import { requireStripeClient } from '@/lib/billing/stripe-client'
29
import { createLogger } from '@/lib/logs/console-logger'
310
import { db } from '@/db'
411
import { member, organization, subscription, user, userStats } from '@/db/schema'
5-
import { requireStripeClient } from '../stripe-client'
6-
import { resetOrganizationBillingPeriod, resetUserBillingPeriod } from './billing-periods'
7-
import { getHighestPrioritySubscription } from './subscription'
8-
import { getUserUsageData } from './usage'
912

1013
const logger = createLogger('Billing')
1114

apps/sim/lib/billing/core/organization-billing.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { and, eq } from 'drizzle-orm'
2+
import { getPlanPricing } from '@/lib/billing/core/billing'
3+
import { getHighestPrioritySubscription } from '@/lib/billing/core/subscription'
24
import { createLogger } from '@/lib/logs/console-logger'
35
import { db } from '@/db'
46
import { member, organization, user, userStats } from '@/db/schema'
5-
import { getPlanPricing } from './billing'
6-
import { getHighestPrioritySubscription } from './subscription'
77

88
const logger = createLogger('OrganizationBilling')
99

0 commit comments

Comments
 (0)