Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b7e377e
v0.5.91: docs i18n, turborepo upgrade
waleedlatif1 Feb 16, 2026
da46a38
v0.5.92: shortlinks, copilot scrolling stickiness, pagination
waleedlatif1 Feb 17, 2026
fdca736
v0.5.93: NextJS config changes, MCP and Blocks whitelisting, copilot …
waleedlatif1 Feb 18, 2026
15ace5e
v0.5.94: vercel integration, folder insertion, migrated tracking redi…
waleedlatif1 Feb 19, 2026
67aa4bb
v0.5.95: gemini 3.1 pro, cloudflare, dataverse, revenuecat, redis, up…
waleedlatif1 Feb 20, 2026
34d92fa
v0.5.96: sim oauth provider, slack ephemeral message tool and blockki…
waleedlatif1 Feb 21, 2026
115f04e
v0.5.97: oidc discovery for copilot mcp
waleedlatif1 Feb 21, 2026
0d86ea0
v0.5.98: change detection improvements, rate limit and code execution…
waleedlatif1 Feb 22, 2026
af59234
v0.5.99: local dev improvements, live workflow logs in terminal
waleedlatif1 Feb 23, 2026
67f8a68
v0.5.100: multiple credentials, 40% speedup, gong, attio, audit log i…
waleedlatif1 Feb 25, 2026
4fd0989
v0.5.101: circular dependency mitigation, confluence enhancements, go…
waleedlatif1 Feb 26, 2026
0d2e6ff
v0.5.102: new integrations, new tools, ci speedups, memory leak instr…
waleedlatif1 Feb 28, 2026
e07e3c3
v0.5.103: memory util instrumentation, API docs, amplitude, google pa…
waleedlatif1 Mar 2, 2026
f1ec5fe
v0.5.104: memory improvements, nested subflows, careers page redirect…
waleedlatif1 Mar 4, 2026
70c36cb
v0.5.105: slack remove reaction, nested subflow locks fix, servicenow…
waleedlatif1 Mar 5, 2026
3ce9475
v0.5.106: condition block and legacy kbs fixes, GPT 5.4
icecrasher321 Mar 6, 2026
6586c5c
v0.5.107: new reddit, slack tools
waleedlatif1 Mar 6, 2026
8c0a2e0
v0.5.108: workflow input params in agent tools, bun upgrade, dropdown…
icecrasher321 Mar 7, 2026
ecd3536
v0.5.109: obsidian and evernote integrations, slack fixes, remove mem…
waleedlatif1 Mar 9, 2026
1c2c2c6
v0.5.110: webhook execution speedups, SSRF patches
waleedlatif1 Mar 11, 2026
36612ae
v0.5.111: non-polling webhook execs off trigger.dev, gmail subject he…
icecrasher321 Mar 12, 2026
e9bdc57
v0.5.112: trace spans improvements, fathom integration, jira fixes, c…
waleedlatif1 Mar 12, 2026
4c12914
v0.5.113: jira, ashby, google ads, grain updates
icecrasher321 Mar 13, 2026
24526b7
Fix ope
Sg312 Mar 14, 2026
a5d8ce2
File upload fixes
Sg312 Mar 14, 2026
65e99f4
Fix lint
Sg312 Mar 14, 2026
26d0052
Materialization shows up
Sg312 Mar 14, 2026
76f797b
Snapshot
Sg312 Mar 14, 2026
ae2dde5
Merge remote-tracking branch 'origin' into fix/mothership-1
Sg312 Mar 14, 2026
d4b688c
Fix
Sg312 Mar 14, 2026
d817883
Nuke migrations
Sg312 Mar 14, 2026
580a6c8
Merge branch 'staging' into fix/mothership-1
Sg312 Mar 14, 2026
fd7ce70
Add migs
Sg312 Mar 14, 2026
4079144
migs
Sg312 Mar 14, 2026
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
4 changes: 2 additions & 2 deletions apps/sim/app/api/files/authorization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ export async function verifyFileAccess(
return true
}

// 1. Workspace files: Check database first (most reliable for both local and cloud)
if (inferredContext === 'workspace') {
// 1. Workspace / mothership files: Check database first (most reliable for both local and cloud)
if (inferredContext === 'workspace' || inferredContext === 'mothership') {
return await verifyWorkspaceFileAccess(cloudKey, userId, customConfig, isLocal)
}

Expand Down
48 changes: 48 additions & 0 deletions apps/sim/app/api/files/upload/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { sanitizeFileName } from '@/executor/constants'
import '@/lib/uploads/core/setup.server'
import { getSession } from '@/lib/auth'
import type { StorageContext } from '@/lib/uploads/config'
import { generateWorkspaceFileKey } from '@/lib/uploads/contexts/workspace/workspace-file-manager'
import { isImageFileType, resolveFileType } from '@/lib/uploads/utils/file-utils'
import {
SUPPORTED_AUDIO_EXTENSIONS,
Expand Down Expand Up @@ -232,6 +233,53 @@ export async function POST(request: NextRequest) {
}
}

// Handle mothership context (chat-scoped uploads to workspace S3)
if (context === 'mothership') {
if (!workspaceId) {
throw new InvalidRequestError('Mothership context requires workspaceId parameter')
}

logger.info(`Uploading mothership file: ${originalName}`)

const storageKey = generateWorkspaceFileKey(workspaceId, originalName)

const metadata: Record<string, string> = {
originalName: originalName,
uploadedAt: new Date().toISOString(),
purpose: 'mothership',
userId: session.user.id,
workspaceId,
}

const fileInfo = await storageService.uploadFile({
file: buffer,
fileName: storageKey,
contentType: file.type || 'application/octet-stream',
context: 'mothership',
preserveKey: true,
customKey: storageKey,
metadata,
})

const finalPath = usingCloudStorage ? `${fileInfo.path}?context=mothership` : fileInfo.path

uploadResults.push({
fileName: originalName,
presignedUrl: '',
fileInfo: {
path: finalPath,
key: fileInfo.key,
name: originalName,
size: buffer.length,
type: file.type || 'application/octet-stream',
},
directUploadSupported: false,
})

logger.info(`Successfully uploaded mothership file: ${fileInfo.key}`)
continue
}

// Handle copilot, chat, profile-pictures contexts
if (context === 'copilot' || context === 'chat' || context === 'profile-pictures') {
if (context === 'copilot') {
Expand Down
18 changes: 15 additions & 3 deletions apps/sim/app/api/mothership/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const FileAttachmentSchema = z.object({
const ResourceAttachmentSchema = z.object({
type: z.enum(['workflow', 'table', 'file', 'knowledgebase']),
id: z.string().min(1),
title: z.string().optional(),
active: z.boolean().optional(),
})

const MothershipMessageSchema = z.object({
Expand Down Expand Up @@ -124,9 +126,19 @@ export async function POST(req: NextRequest) {

if (Array.isArray(resourceAttachments) && resourceAttachments.length > 0) {
const results = await Promise.allSettled(
resourceAttachments.map((r) =>
resolveActiveResourceContext(r.type, r.id, workspaceId, authenticatedUserId)
)
resourceAttachments.map(async (r) => {
const ctx = await resolveActiveResourceContext(
r.type,
r.id,
workspaceId,
authenticatedUserId
)
if (!ctx) return null
return {
...ctx,
tag: r.active ? '@active_tab' : '@open_tab',
}
})
)
for (const result of results) {
if (result.status === 'fulfilled' && result.value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export function UserInput({

const files = useFileAttachments({
userId: userId || session?.user?.id,
workspaceId,
disabled: false,
isLoading: isSending,
})
Expand Down
15 changes: 9 additions & 6 deletions apps/sim/app/workspace/[workspaceId]/home/hooks/use-chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -880,12 +880,15 @@ export function useChat(
try {
const currentActiveId = activeResourceIdRef.current
const currentResources = resourcesRef.current
const activeRes = currentActiveId
? currentResources.find((r) => r.id === currentActiveId)
: undefined
const resourceAttachments = activeRes
? [{ type: activeRes.type, id: activeRes.id }]
: undefined
const resourceAttachments =
currentResources.length > 0
? currentResources.map((r) => ({
type: r.type,
id: r.id,
title: r.title,
active: r.id === currentActiveId,
}))
: undefined

const response = await fetch(MOTHERSHIP_CHAT_API_PATH, {
method: 'POST',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface MessageFileAttachment {

interface UseFileAttachmentsProps {
userId?: string
workspaceId?: string
disabled?: boolean
isLoading?: boolean
}
Expand All @@ -55,7 +56,7 @@ interface UseFileAttachmentsProps {
* @returns File attachment state and operations
*/
export function useFileAttachments(props: UseFileAttachmentsProps) {
const { userId, disabled, isLoading } = props
const { userId, workspaceId, disabled, isLoading } = props

const [attachedFiles, setAttachedFiles] = useState<AttachedFile[]>([])
const [isDragging, setIsDragging] = useState(false)
Expand Down Expand Up @@ -135,7 +136,10 @@ export function useFileAttachments(props: UseFileAttachmentsProps) {
try {
const formData = new FormData()
formData.append('file', file)
formData.append('context', 'copilot')
formData.append('context', 'mothership')
if (workspaceId) {
formData.append('workspaceId', workspaceId)
}

const uploadResponse = await fetch('/api/files/upload', {
method: 'POST',
Expand Down Expand Up @@ -171,7 +175,7 @@ export function useFileAttachments(props: UseFileAttachmentsProps) {
}
}
},
[userId]
[userId, workspaceId]
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ const UserInput = forwardRef<UserInputRef, UserInputProps>(

const fileAttachments = useFileAttachments({
userId: session?.user?.id,
workspaceId,
disabled,
isLoading,
})
Expand Down
47 changes: 43 additions & 4 deletions apps/sim/lib/copilot/chat-payload.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createLogger } from '@sim/logger'
import { getUserSubscriptionState } from '@/lib/billing/core/subscription'
import { processFileAttachments } from '@/lib/copilot/chat-context'
import { getCopilotToolDescription } from '@/lib/copilot/tool-descriptions'
import { isHosted } from '@/lib/core/config/feature-flags'
import { createMcpToolId } from '@/lib/mcp/utils'
import { trackChatUpload } from '@/lib/uploads/contexts/workspace/workspace-file-manager'
import { getWorkflowById } from '@/lib/workflows/utils'
import { tools } from '@/tools/registry'
import { getLatestVersionTools, stripVersionSuffix } from '@/tools/utils'
Expand Down Expand Up @@ -126,7 +126,47 @@ export async function buildCopilotRequestPayload(
const effectiveMode = mode === 'agent' ? 'build' : mode
const transportMode = effectiveMode === 'build' ? 'agent' : effectiveMode

const processedFileContents = await processFileAttachments(fileAttachments ?? [], userId)
// Track uploaded files in the DB and build context tags instead of base64 inlining
const uploadContexts: Array<{ type: string; content: string }> = []
if (chatId && params.workspaceId && fileAttachments && fileAttachments.length > 0) {
for (const f of fileAttachments) {
const filename = (f.filename ?? f.name ?? 'file') as string
const mediaType = (f.media_type ?? f.mimeType ?? 'application/octet-stream') as string
try {
await trackChatUpload(
params.workspaceId,
userId,
chatId,
f.key,
filename,
mediaType,
f.size
)
const lines = [
`File "${filename}" (${mediaType}, ${f.size} bytes) uploaded.`,
`Read with: read("uploads/${filename}")`,
`To save permanently: materialize_file(fileName: "${filename}")`,
]
if (filename.endsWith('.json')) {
lines.push(
`To import as a workflow: materialize_file(fileName: "${filename}", operation: "import")`
)
}
uploadContexts.push({
type: 'uploaded_file',
content: lines.join('\n'),
})
} catch (err) {
logger.warn('Failed to track chat upload', {
filename,
chatId,
error: err instanceof Error ? err.message : String(err),
})
}
}
}

const allContexts = [...(contexts ?? []), ...uploadContexts]

let integrationTools: ToolSchema[] = []

Expand Down Expand Up @@ -170,11 +210,10 @@ export async function buildCopilotRequestPayload(
...(provider ? { provider } : {}),
mode: transportMode,
messageId: userMessageId,
...(contexts && contexts.length > 0 ? { context: contexts } : {}),
...(allContexts.length > 0 ? { context: allContexts } : {}),
...(chatId ? { chatId } : {}),
...(typeof prefetch === 'boolean' ? { prefetch } : {}),
...(implicitFeedback ? { implicitFeedback } : {}),
...(processedFileContents.length > 0 ? { fileAttachments: processedFileContents } : {}),
...(integrationTools.length > 0 ? { integrationTools } : {}),
...(commands && commands.length > 0 ? { commands } : {}),
...(params.workspaceContext ? { workspaceContext: params.workspaceContext } : {}),
Expand Down
2 changes: 2 additions & 0 deletions apps/sim/lib/copilot/orchestrator/tool-executor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
executeManageJob,
executeUpdateJobHistory,
} from './job-tools'
import { executeMaterializeFile } from './materialize-file'
import type {
CheckDeploymentStatusParams,
CreateFolderParams,
Expand Down Expand Up @@ -984,6 +985,7 @@ const SIM_WORKFLOW_TOOL_HANDLERS: Record<
},
}
},
materialize_file: (p, c) => executeMaterializeFile(p, c),
manage_custom_tool: (p, c) => executeManageCustomTool(p, c),
manage_mcp_tool: (p, c) => executeManageMcpTool(p, c),
manage_skill: (p, c) => executeManageSkill(p, c),
Expand Down
Loading
Loading