Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
8f0ef58
v0.5.7: combobox selectors, usage indicator, workflow loading race co…
icecrasher321 Nov 18, 2025
31c34b2
v0.5.8: notifications, billing, ui changes, store loading state machine
icecrasher321 Nov 20, 2025
842ef27
v0.5.9: add backwards compatibility for agent messages array
waleedlatif1 Nov 20, 2025
b7e814b
v0.5.10: copilot upgrade, preprocessor, logs search, UI, code hygiene
waleedlatif1 Nov 21, 2025
ebcd243
v0.5.11: stt, videogen, vllm, billing fixes, new models
waleedlatif1 Nov 25, 2025
1d08796
v0.5.12: memory optimizations, sentry, incidentio, posthog, zendesk, …
waleedlatif1 Nov 29, 2025
8c32ad4
v0.5.13: polling fixes, generic agent search tool, status page, smtp,…
waleedlatif1 Dec 1, 2025
54cc937
v0.5.14: fix issue with teams, google selectors + cleanup code
icecrasher321 Dec 1, 2025
774e5d5
v0.5.15: add tools, revert subblock prop change
icecrasher321 Dec 1, 2025
e157ce5
v0.5.16: MCP fixes, code refactors, jira fixes, new mistral models
waleedlatif1 Dec 3, 2025
3187493
v0.5.17: modals, billing fixes, bun update, zoom, dropbox, kalshi, po…
waleedlatif1 Dec 4, 2025
c3afbdd
Superagent poc
Sg312 Nov 26, 2025
04eeb59
Checkpoint brokeN
Sg312 Dec 1, 2025
7913c67
tool call rag
Sg312 Dec 2, 2025
a21b796
Fix
Sg312 Dec 2, 2025
0517d61
Fixes
Sg312 Dec 2, 2025
804c157
Improvements
Sg312 Dec 2, 2025
5ec85be
Creds stuff
Sg312 Dec 2, 2025
09bb84f
Fix
Sg312 Dec 2, 2025
dca8c78
Fix tools
Sg312 Dec 2, 2025
0258ca3
Fix stream
Sg312 Dec 3, 2025
88f5bfb
Prompt
Sg312 Dec 3, 2025
10ae3ed
Update sheets descriptions
Sg312 Dec 3, 2025
63d36b7
Better
Sg312 Dec 3, 2025
1f1a73e
Copilot components
Sg312 Dec 3, 2025
67ad858
Delete stuff
Sg312 Dec 3, 2025
d160090
Remove db migration
Sg312 Dec 3, 2025
9fe4cf4
Fix migrations
Sg312 Dec 3, 2025
5dced7f
Fix things
Sg312 Dec 3, 2025
3b56e01
Copilot side superagent
Sg312 Dec 3, 2025
b6ca604
Build workflow from chat
Sg312 Dec 3, 2025
114a224
Combine superagent into copilkot
Sg312 Dec 3, 2025
70b6a40
Render tools
Sg312 Dec 3, 2025
1c53dd7
Function execution
Sg312 Dec 3, 2025
c77405b
Max mode indicators
Sg312 Dec 3, 2025
e8c4f23
Tool call confirmations
Sg312 Dec 3, 2025
ab07356
Credential settings
Sg312 Dec 3, 2025
06aecd7
Remove betas
Sg312 Dec 3, 2025
67a8485
Bump version
Sg312 Dec 3, 2025
3af1a35
Dropdown options in block metadata
Sg312 Dec 3, 2025
23980a2
Copilot kb tools
Sg312 Dec 3, 2025
308847e
Fix lint
Sg312 Dec 4, 2025
1d22630
Credentials modal
Sg312 Dec 4, 2025
19bb425
Fix lint
Sg312 Dec 4, 2025
b0d27b9
Cleanup
Sg312 Dec 4, 2025
8331cc7
Env var resolution in superagent tools
Sg312 Dec 4, 2025
02b4035
Get id for workflow vars
Sg312 Dec 4, 2025
6e8b18c
Fix insert into subflow
Sg312 Dec 4, 2025
3241daf
Fix executor for while and do while loops
Sg312 Dec 4, 2025
756293b
Fix metadata for parallel
Sg312 Dec 5, 2025
1958448
Remove db migration
Sg312 Dec 5, 2025
de3457f
Rebase
Sg312 Dec 5, 2025
b5a8f1e
Add migrations back
Sg312 Dec 5, 2025
89e7a51
Clean up code
Sg312 Dec 5, 2025
71bcc2d
Fix executor logic issue
Sg312 Dec 5, 2025
8179e49
Cleanup
Sg312 Dec 5, 2025
f8b6e50
Diagram tool
Sg312 Dec 5, 2025
2c5d2e4
Fix tool naems
Sg312 Dec 5, 2025
813f519
Comment out g3p
Sg312 Dec 5, 2025
63a5efc
Remove popup option
Sg312 Dec 5, 2025
2009b0c
Hide o3
Sg312 Dec 5, 2025
8e64a55
Remove db migration
Sg312 Dec 5, 2025
65701c4
Merge remote-tracking branch 'origin' into feat/superagent
Sg312 Dec 5, 2025
95709c5
Merge branch 'staging' into feat/superagent
Sg312 Dec 5, 2025
fa65d31
Fix merge conflicts
Sg312 Dec 5, 2025
3eb448a
Fix lint
Sg312 Dec 5, 2025
f0bc5d0
Fix tests
Sg312 Dec 5, 2025
dafca72
Remove webhook change
Sg312 Dec 5, 2025
adae879
Remove cb change
Sg312 Dec 5, 2025
77de64b
Fix lint
Sg312 Dec 5, 2025
c2a81a6
Fix
Sg312 Dec 5, 2025
7e677d0
Fix lint
Sg312 Dec 5, 2025
833d301
Fix build
Sg312 Dec 5, 2025
3d8796c
comment out gemini
Sg312 Dec 5, 2025
8655975
Add gemini back
Sg312 Dec 5, 2025
dc27220
Merge branch 'staging' into feat/superagent
Sg312 Dec 5, 2025
2deb727
Remove bad test
Sg312 Dec 5, 2025
aca1fa6
Fix
Sg312 Dec 5, 2025
8696baa
Fix test
Sg312 Dec 5, 2025
e4fab34
Fix
Sg312 Dec 5, 2025
3d66f11
Nuke bad test
Sg312 Dec 5, 2025
6e55083
Fix lint
Sg312 Dec 5, 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
Prev Previous commit
Next Next commit
Combine superagent into copilkot
  • Loading branch information
Sg312 committed Dec 5, 2025
commit 114a2246b96322d2c7b0c4321ed22a10afdc1103
95 changes: 95 additions & 0 deletions apps/sim/app/api/copilot/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import {
createRequestTracker,
createUnauthorizedResponse,
} from '@/lib/copilot/request-helpers'
import { getCredentialsServerTool } from '@/lib/copilot/tools/server/user/get-credentials'
import type { CopilotProviderConfig } from '@/lib/copilot/types'
import { env } from '@/lib/core/config/env'
import { createLogger } from '@/lib/logs/console/logger'
import { CopilotFiles } from '@/lib/uploads'
import { createFileContent } from '@/lib/uploads/utils/file-utils'
import { tools } from '@/tools/registry'

const logger = createLogger('CopilotChatAPI')

Expand Down Expand Up @@ -313,6 +315,94 @@ export async function POST(req: NextRequest) {
const effectiveConversationId =
(currentChat?.conversationId as string | undefined) || conversationId

// For agent/build mode, fetch credentials and build tool definitions
let integrationTools: any[] = []
let credentials: {
oauth: Record<string, { accessToken: string; accountId: string; name: string; expiresAt?: string }>
apiKeys: string[]
metadata?: {
connectedOAuth: Array<{ provider: string; name: string; scopes?: string[] }>
configuredApiKeys: string[]
}
} | null = null

if (mode === 'agent') {
// Fetch user credentials (OAuth + API keys)
try {
const rawCredentials = await getCredentialsServerTool.execute(
{ userId: authenticatedUserId },
{ userId: authenticatedUserId }
)

// Transform OAuth credentials to map format: { [provider]: { accessToken, accountId, ... } }
const oauthMap: Record<
string,
{ accessToken: string; accountId: string; name: string; expiresAt?: string }
> = {}
const connectedOAuth: Array<{ provider: string; name: string; scopes?: string[] }> = []
for (const cred of rawCredentials?.oauth?.credentials || []) {
if (cred.accessToken) {
oauthMap[cred.provider] = {
accessToken: cred.accessToken,
accountId: cred.id,
name: cred.name,
}
connectedOAuth.push({
provider: cred.provider,
name: cred.name,
})
}
}

credentials = {
oauth: oauthMap,
apiKeys: rawCredentials?.environment?.variableNames || [],
metadata: {
connectedOAuth,
configuredApiKeys: rawCredentials?.environment?.variableNames || [],
},
}

logger.info(`[${tracker.requestId}] Fetched credentials for build mode`, {
oauthProviders: Object.keys(oauthMap),
apiKeyCount: credentials.apiKeys.length,
})
} catch (error) {
logger.warn(`[${tracker.requestId}] Failed to fetch credentials`, {
error: error instanceof Error ? error.message : String(error),
})
}

// Build tool definitions (schemas only)
try {
const { createUserToolSchema } = await import('@/tools/params')

integrationTools = Object.entries(tools).map(([toolId, toolConfig]) => {
const userSchema = createUserToolSchema(toolConfig)
return {
name: toolId,
description: toolConfig.description || toolConfig.name || toolId,
input_schema: userSchema,
defer_loading: true, // Anthropic Advanced Tool Use
...(toolConfig.oauth?.required && {
oauth: {
required: true,
provider: toolConfig.oauth.provider,
},
}),
}
})

logger.info(`[${tracker.requestId}] Built tool definitions for build mode`, {
integrationToolCount: integrationTools.length,
})
} catch (error) {
logger.warn(`[${tracker.requestId}] Failed to build tool definitions`, {
error: error instanceof Error ? error.message : String(error),
})
}
}

const requestPayload = {
message: message, // Just send the current user message text
workflowId,
Expand All @@ -330,6 +420,11 @@ export async function POST(req: NextRequest) {
...(agentContexts.length > 0 && { context: agentContexts }),
...(actualChatId ? { chatId: actualChatId } : {}),
...(processedFileContents.length > 0 && { fileAttachments: processedFileContents }),
// For build/agent mode, include tools and credentials
...(integrationTools.length > 0 && { tools: integrationTools }),
...(credentials && { credentials }),
// Anthropic beta features for advanced tool use
...(mode === 'agent' && { betas: ['advanced-tool-use-2025-11-20'] }),
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ import { createLogger } from '@/lib/logs/console/logger'
import { executeTool } from '@/tools'
import { getTool } from '@/tools/utils'

const logger = createLogger('SuperagentExecuteToolAPI')
const logger = createLogger('CopilotExecuteToolAPI')

const ExecuteToolSchema = z.object({
toolCallId: z.string(),
toolName: z.string(),
arguments: z.record(z.any()).optional().default({}),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Using z.any() bypasses type safety - consider defining specific argument schemas or at least using z.unknown() for better type safety. Would it be possible to define more specific schemas for common tool argument patterns?

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/sim/app/api/copilot/execute-tool/route.ts
Line: 25:25

Comment:
**style:** Using `z.any()` bypasses type safety - consider defining specific argument schemas or at least using `z.unknown()` for better type safety. Would it be possible to define more specific schemas for common tool argument patterns?

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

workspaceId: z.string(),
workflowId: z.string().optional(),
})

/**
Expand All @@ -49,11 +49,7 @@ function mapEnvVarsToToolParams(
const toolPrefix = toolId.split('_')[0]?.toUpperCase()

// Common API key environment variable patterns to check
const envKeyPatterns = [
`${toolPrefix}_API_KEY`,
`${toolPrefix}AI_API_KEY`,
`${toolPrefix}_KEY`,
]
const envKeyPatterns = [`${toolPrefix}_API_KEY`, `${toolPrefix}AI_API_KEY`, `${toolPrefix}_KEY`]

// Special mappings for tools with non-standard naming
const specialMappings: Record<string, string[]> = {
Expand Down Expand Up @@ -93,8 +89,9 @@ function mapEnvVarsToToolParams(
}

/**
* POST /api/superagent/execute-tool
* POST /api/copilot/execute-tool
* Execute an integration tool with resolved credentials
* Called by the sim-agent service when it needs to execute a tool
*/
export async function POST(req: NextRequest) {
const tracker = createRequestTracker()
Expand All @@ -113,12 +110,12 @@ export async function POST(req: NextRequest) {
logger.debug(`[${tracker.requestId}] Incoming execute-tool request`, { preview })
} catch {}

const { toolCallId, toolName, arguments: toolArgs, workspaceId } = ExecuteToolSchema.parse(body)
const { toolCallId, toolName, arguments: toolArgs, workflowId } = ExecuteToolSchema.parse(body)

logger.info(`[${tracker.requestId}] Executing tool`, {
toolCallId,
toolName,
workspaceId,
workflowId,
hasArgs: Object.keys(toolArgs).length > 0,
})

Expand All @@ -128,12 +125,12 @@ export async function POST(req: NextRequest) {
// Find similar tool names to help debug
const { tools: allTools } = await import('@/tools/registry')
const allToolNames = Object.keys(allTools)
const prefix = toolName.split('_').slice(0, 2).join('_') // e.g., "linear_list"
const similarTools = allToolNames.filter((name) =>
name.startsWith(prefix.split('_')[0] + '_') // Same provider prefix
).slice(0, 10)
logger.warn(`[${tracker.requestId}] Tool not found in registry`, {
const prefix = toolName.split('_').slice(0, 2).join('_')
const similarTools = allToolNames
.filter((name) => name.startsWith(prefix.split('_')[0] + '_'))
.slice(0, 10)

logger.warn(`[${tracker.requestId}] Tool not found in registry`, {
toolName,
prefix,
similarTools,
Expand Down Expand Up @@ -216,32 +213,34 @@ export async function POST(req: NextRequest) {
const llmProvidedApiKey = executionParams.apiKey as string | undefined

if (needsApiKey || llmProvidedApiKey) {
logger.info(`[${tracker.requestId}] Resolving API key for tool`, {
toolName,
logger.info(`[${tracker.requestId}] Resolving API key for tool`, {
toolName,
needsApiKey,
hasLlmProvidedKey: !!llmProvidedApiKey,
llmProvidedKeyPreview: llmProvidedApiKey ? `${llmProvidedApiKey.substring(0, 20)}...` : null,
llmProvidedKeyPreview: llmProvidedApiKey
? `${llmProvidedApiKey.substring(0, 20)}...`
: null,
})

try {
const decryptedEnvVars = await getEffectiveDecryptedEnv(userId, workspaceId)
const decryptedEnvVars = await getEffectiveDecryptedEnv(userId, workflowId)

// Case 1: LLM provided an API key name (e.g., "EXA_API_KEY") - resolve it
if (llmProvidedApiKey) {
// Check if it looks like an env var name (uppercase with underscores, ends with _KEY or _API_KEY)
const looksLikeEnvVar = /^[A-Z][A-Z0-9_]*(_KEY|_API_KEY)$/.test(llmProvidedApiKey)

if (looksLikeEnvVar && decryptedEnvVars[llmProvidedApiKey]) {
// Resolve the env var name to its actual value
executionParams.apiKey = decryptedEnvVars[llmProvidedApiKey]
logger.info(`[${tracker.requestId}] Resolved API key from LLM-provided name`, {
toolName,
logger.info(`[${tracker.requestId}] Resolved API key from LLM-provided name`, {
toolName,
envVarName: llmProvidedApiKey,
})
} else if (looksLikeEnvVar) {
// LLM provided an env var name but it's not configured
logger.warn(`[${tracker.requestId}] LLM provided API key name not found in env vars`, {
toolName,
logger.warn(`[${tracker.requestId}] LLM provided API key name not found in env vars`, {
toolName,
envVarName: llmProvidedApiKey,
availableKeys: Object.keys(decryptedEnvVars),
})
Expand All @@ -256,7 +255,7 @@ export async function POST(req: NextRequest) {
}
// else: LLM provided what looks like an actual API key value, keep it as-is
}

// Case 2: No API key yet but tool requires one - resolve from tool prefix convention
if (!executionParams.apiKey && needsApiKey) {
const apiKeyParams = mapEnvVarsToToolParams(toolName, toolConfig, decryptedEnvVars)
Expand Down Expand Up @@ -294,7 +293,7 @@ export async function POST(req: NextRequest) {

// Add execution context
executionParams._context = {
workspaceId,
workflowId,
userId,
}

Expand Down
Loading