Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
aeef2b7
v0.3.19: openai oss models, invite & search modal fixes
waleedlatif1 Aug 5, 2025
9f2ff7e
Merge pull request #883 from simstudioai/staging
icecrasher321 Aug 5, 2025
85cdca2
v0.3.21: gpt-5, copilot files, configurable rate limits, fix deployed…
waleedlatif1 Aug 7, 2025
aedf5e7
v0.3.22: handle files, trigger mode, email validation, tag dropdown t…
waleedlatif1 Aug 9, 2025
1c818b2
v0.3.23: multiplayer variables, api key fixes, kb improvements, trigg…
icecrasher321 Aug 12, 2025
8fccd5c
Merge pull request #948 from simstudioai/staging
icecrasher321 Aug 12, 2025
f7573fa
v0.3.24: api block fixes
waleedlatif1 Aug 13, 2025
4107948
Merge pull request #954 from simstudioai/staging
waleedlatif1 Aug 13, 2025
56ffb53
Merge pull request #964 from simstudioai/staging
icecrasher321 Aug 14, 2025
e1f04f4
v0.3.26: fix billing, bubble up workflow block errors, credentials se…
icecrasher321 Aug 14, 2025
6133db5
v0.3.27: oauth/webhook fixes, whitelabel fixes, code cleanups
icecrasher321 Aug 15, 2025
a0cf003
Merge pull request #986 from simstudioai/staging
icecrasher321 Aug 15, 2025
97b6bcc
v0.3.28: autolayout, export, copilot, kb ui improvements
waleedlatif1 Aug 16, 2025
570c07b
Merge pull request #1004 from simstudioai/staging
icecrasher321 Aug 18, 2025
af60ccd
fix: migration mem issues bypass
icecrasher321 Aug 18, 2025
3873f44
Merge pull request #1007 from simstudioai/staging
icecrasher321 Aug 18, 2025
5c56cbd
Merge pull request #1008 from simstudioai/staging
icecrasher321 Aug 18, 2025
60a9a25
Merge pull request #1009 from simstudioai/staging
icecrasher321 Aug 18, 2025
d75cc1e
v0.3.30: duplication, control bar fixes
waleedlatif1 Aug 18, 2025
1619d63
v0.3.31: webhook fixes, advanced mode parameter filtering, credential…
waleedlatif1 Aug 19, 2025
81969f1
feat(copilot): copilot tool refactor (#1030)
Sg312 Aug 19, 2025
e46045d
improvement(console): increase console max entries for larger workflo…
waleedlatif1 Aug 19, 2025
2009901
improvement(api): add native support for form-urlencoded inputs into …
waleedlatif1 Aug 19, 2025
ec13ad2
Add rate limits (#1034)
Sg312 Aug 19, 2025
1139a35
improvement(supabase): added more verbose error logging for supabase …
waleedlatif1 Aug 19, 2025
334e827
fix(oauth-block): race condition for rendering credential selectors a…
icecrasher321 Aug 19, 2025
625b528
fix(copilot): edit workflow race condition (#1036)
Sg312 Aug 19, 2025
d46d2c2
fix(dev): infinite get-session calls
icecrasher321 Aug 20, 2025
c32ddb8
remove unused code, fix type issue
icecrasher321 Aug 20, 2025
290cf9a
remove unused image
icecrasher321 Aug 20, 2025
e7e944e
remove unused field
icecrasher321 Aug 20, 2025
8daea08
revert singleton changes
icecrasher321 Aug 20, 2025
6b185be
v0.3.32: loop block max increase, url-encoded API calls, subflow logs…
waleedlatif1 Aug 20, 2025
5d74db5
v0.3.33: update copilot docs
icecrasher321 Aug 20, 2025
df0d7e7
Merge branch 'staging', remote-tracking branch 'origin' into fix/infi…
icecrasher321 Aug 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/docs/content/docs/tools/supabase.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ Get a single row from a Supabase table based on filter criteria
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | string | Operation status message |
| `results` | object | The row data if found, null if not found |
| `results` | array | Array containing the row data if found, empty array if not found |

### `supabase_update`

Expand Down
4 changes: 4 additions & 0 deletions apps/sim/app/api/copilot/chat/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ describe('Copilot Chat API Route', () => {
COPILOT_API_KEY: 'test-sim-agent-key',
BETTER_AUTH_URL: 'http://localhost:3000',
},
isTruthy: (value: string | boolean | number | undefined) =>
typeof value === 'string'
? value.toLowerCase() === 'true' || value === '1'
: Boolean(value),
}))

global.fetch = vi.fn()
Expand Down
83 changes: 78 additions & 5 deletions apps/sim/app/api/copilot/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
} from '@/lib/copilot/auth'
import { getCopilotModel } from '@/lib/copilot/config'
import { TITLE_GENERATION_SYSTEM_PROMPT, TITLE_GENERATION_USER_PROMPT } from '@/lib/copilot/prompts'
import { getBlocksAndToolsTool } from '@/lib/copilot/tools/server-tools/blocks/get-blocks-and-tools'
import { getEnvironmentVariablesTool } from '@/lib/copilot/tools/server-tools/user/get-environment-variables'
import { getOAuthCredentialsTool } from '@/lib/copilot/tools/server-tools/user/get-oauth-credentials'
import { env } from '@/lib/env'
import { createLogger } from '@/lib/logs/console/logger'
import { SIM_AGENT_API_URL_DEFAULT } from '@/lib/sim-agent'
Expand Down Expand Up @@ -89,6 +92,7 @@ const ChatMessageSchema = z.object({
fileAttachments: z.array(FileAttachmentSchema).optional(),
provider: z.string().optional().default('openai'),
conversationId: z.string().optional(),
userWorkflow: z.string().optional(),
})

/**
Expand Down Expand Up @@ -206,6 +210,7 @@ export async function POST(req: NextRequest) {
fileAttachments,
provider,
conversationId,
userWorkflow,
} = ChatMessageSchema.parse(body)

// Derive request origin for downstream service
Expand Down Expand Up @@ -243,6 +248,7 @@ export async function POST(req: NextRequest) {
depth,
prefetch,
origin: requestOrigin,
hasUserWorkflow: !!userWorkflow,
})

// Handle chat context
Expand Down Expand Up @@ -409,6 +415,63 @@ export async function POST(req: NextRequest) {
[...messages].reverse().find((m) => m?.role === 'user') || messages[messages.length - 1]
const messagesForAgent = effectiveConversationId ? [latestUserMessage] : messages

// Prepare optional prefetch results
let prefetchResults: Record<string, any> | undefined
if (effectivePrefetch === true) {
try {
const [blocksAndToolsResp, envVarsResp, oauthResp] = await Promise.all([
getBlocksAndToolsTool.execute({}),
getEnvironmentVariablesTool.execute({ userId: authenticatedUserId, workflowId }),
getOAuthCredentialsTool.execute({ userId: authenticatedUserId }),
])

prefetchResults = {}

if (blocksAndToolsResp.success) {
prefetchResults.get_blocks_and_tools = blocksAndToolsResp.data
} else {
logger.warn(`[${tracker.requestId}] Failed to prefetch get_blocks_and_tools`, {
error: blocksAndToolsResp.error,
})
}

if (envVarsResp.success) {
prefetchResults.get_environment_variables = envVarsResp.data
} else {
logger.warn(`[${tracker.requestId}] Failed to prefetch get_environment_variables`, {
error: envVarsResp.error,
})
}

if (oauthResp.success) {
prefetchResults.get_oauth_credentials = oauthResp.data
} else {
logger.warn(`[${tracker.requestId}] Failed to prefetch get_oauth_credentials`, {
error: oauthResp.error,
})
}

if (userWorkflow && typeof userWorkflow === 'string' && userWorkflow.trim().length > 0) {
prefetchResults.get_user_workflow = userWorkflow
const uwLength = userWorkflow.length
const uwPreview = userWorkflow.substring(0, 10000)
logger.info(`[${tracker.requestId}] Included client-provided userWorkflow in prefetch`, {
length: uwLength,
preview: `${uwPreview}${uwLength > 10000 ? '...' : ''}`,
})
}

logger.info(`[${tracker.requestId}] Prepared prefetchResults for streaming payload`, {
hasBlocksAndTools: !!prefetchResults.get_blocks_and_tools,
hasEnvVars: !!prefetchResults.get_environment_variables,
hasOAuthCreds: !!prefetchResults.get_oauth_credentials,
hasUserWorkflow: !!prefetchResults.get_user_workflow,
})
} catch (e) {
logger.error(`[${tracker.requestId}] Error while preparing prefetchResults`, e)
}
}

const requestPayload = {
messages: messagesForAgent,
workflowId,
Expand All @@ -422,6 +485,7 @@ export async function POST(req: NextRequest) {
...(typeof effectivePrefetch === 'boolean' ? { prefetch: effectivePrefetch } : {}),
...(session?.user?.name && { userName: session.user.name }),
...(requestOrigin ? { origin: requestOrigin } : {}),
...(prefetchResults ? { prefetchResults } : {}),
}

// Log the payload being sent to the streaming endpoint
Expand All @@ -438,10 +502,6 @@ export async function POST(req: NextRequest) {
messagesCount: requestPayload.messages.length,
...(requestOrigin ? { origin: requestOrigin } : {}),
})
// Full payload as JSON string
logger.info(
`[${tracker.requestId}] Full streaming payload: ${JSON.stringify(requestPayload)}`
)
} catch (e) {
logger.warn(`[${tracker.requestId}] Failed to log payload preview for streaming endpoint`, e)
}
Expand All @@ -456,7 +516,11 @@ export async function POST(req: NextRequest) {
})

if (!simAgentResponse.ok) {
if (simAgentResponse.status === 401 || simAgentResponse.status === 402) {
if (
simAgentResponse.status === 401 ||
simAgentResponse.status === 402 ||
simAgentResponse.status === 429
) {
// Rethrow status only; client will render appropriate assistant message
return new NextResponse(null, { status: simAgentResponse.status })
}
Expand Down Expand Up @@ -622,6 +686,15 @@ export async function POST(req: NextRequest) {
if (event.data?.id) {
announcedToolCallIds.add(event.data.id)
}
if (event.data?.name === 'get_user_workflow') {
logger.info(
`[${tracker.requestId}] get_user_workflow tool call received in stream; client will execute locally and post to /api/copilot/methods`,
{
toolCallId: event.data?.id,
hasArgs: !!event.data?.arguments,
}
)
}
}
break

Expand Down
Loading
Loading