Files
simstudioai--sim/apps/sim/lib/api/contracts/storage-transfer.ts
T
wehub-resource-sync d25d482dc2
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

793 lines
26 KiB
TypeScript

import { z } from 'zod'
import {
batchPresignedUploadResponseSchema,
presignedUploadResponseSchema,
} from '@/lib/api/contracts/file-uploads'
import { workspaceFileIdSchema } from '@/lib/api/contracts/primitives'
import {
type ContractBodyInput,
type ContractJsonResponse,
type ContractParamsInput,
type ContractQueryInput,
defineRouteContract,
} from '@/lib/api/contracts/types'
import {
FileInputSchema,
RawFileInputArraySchema,
RawFileInputSchema,
} from '@/lib/uploads/utils/file-schemas'
const jsonResponseSchema = z.unknown()
function formatFileSize(bytes: number): string {
if (!Number.isFinite(bytes) || bytes <= 0) return '0 Bytes'
const k = 1024
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1)
const value = bytes / k ** i
return `${value.toFixed(value >= 100 || i === 0 ? 0 : 1)} ${sizes[i]}`
}
const multipartPartUrlSchema = z.object({
partNumber: z.number(),
url: z.string(),
blockId: z.string().optional(),
})
const multipartCompletedUploadSchema = z.object({
success: z.literal(true),
location: z.string(),
path: z.string(),
key: z.string(),
})
export const initiateMultipartResponseSchema = z.object({
uploadId: z.string(),
key: z.string(),
uploadToken: z.string(),
})
export const getMultipartPartUrlsResponseSchema = z.object({
presignedUrls: z.array(multipartPartUrlSchema),
})
export const completeMultipartResponseSchema = z.union([
multipartCompletedUploadSchema,
z.object({
results: z.array(multipartCompletedUploadSchema),
}),
])
export const abortMultipartResponseSchema = z.object({
success: z.literal(true),
})
export const multipartUploadResponseSchema = z.union([
initiateMultipartResponseSchema,
getMultipartPartUrlsResponseSchema,
completeMultipartResponseSchema,
abortMultipartResponseSchema,
])
const connectionFields = {
host: z.string().min(1, 'Host is required'),
port: z.coerce.number().int().positive().default(22),
username: z.string().min(1, 'Username is required'),
password: z.string().nullish(),
privateKey: z.string().nullish(),
passphrase: z.string().nullish(),
}
export function requirePasswordOrPrivateKey<S extends z.ZodType>(schema: S): S {
return schema.refine(
(value) => {
const connection = value as { password?: string | null; privateKey?: string | null }
return Boolean(connection.password || connection.privateKey)
},
{ message: 'Either password or privateKey must be provided' }
) as S
}
export const boxUploadBodySchema = z.object({
accessToken: z.string().min(1, 'Access token is required'),
parentFolderId: z.string().min(1, 'Parent folder ID is required'),
file: FileInputSchema.optional().nullable(),
fileContent: z.string().optional().nullable(),
fileName: z.string().optional().nullable(),
})
export const dropboxUploadBodySchema = z.object({
accessToken: z.string().min(1, 'Access token is required'),
path: z.string().min(1, 'Destination path is required'),
file: FileInputSchema.optional().nullable(),
fileContent: z.string().optional().nullable(),
fileName: z.string().optional().nullable(),
mode: z.enum(['add', 'overwrite']).optional().nullable(),
autorename: z.boolean().optional().nullable(),
mute: z.boolean().optional().nullable(),
})
export const jupyterUploadBodySchema = z.object({
serverUrl: z.string().min(1, 'Server URL is required'),
token: z.string().min(1, 'Token is required'),
directory: z.string().optional().nullable(),
file: FileInputSchema.optional().nullable(),
fileContent: z.string().optional().nullable(),
fileName: z.string().optional().nullable(),
})
export const wordpressUploadBodySchema = z.object({
accessToken: z.string().min(1, 'Access token is required'),
siteId: z.string().min(1, 'Site ID is required'),
file: RawFileInputSchema.optional().nullable(),
filename: z.string().optional().nullable(),
title: z.string().optional().nullable(),
caption: z.string().optional().nullable(),
altText: z.string().optional().nullable(),
description: z.string().optional().nullable(),
})
export const sftpListBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
remotePath: z.string().min(1, 'Remote path is required'),
detailed: z.boolean().default(false),
})
)
export const sftpDeleteBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
remotePath: z.string().min(1, 'Remote path is required'),
recursive: z.boolean().default(false),
})
)
export const sftpMkdirBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
remotePath: z.string().min(1, 'Remote path is required'),
recursive: z.boolean().default(false),
})
)
export const sftpDownloadBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
remotePath: z.string().min(1, 'Remote path is required'),
encoding: z.enum(['utf-8', 'base64']).default('utf-8'),
})
)
export const sftpUploadBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
remotePath: z.string().min(1, 'Remote path is required'),
files: RawFileInputArraySchema.optional().nullable(),
fileContent: z.string().nullish(),
fileName: z.string().nullish(),
overwrite: z.boolean().default(true),
permissions: z.string().nullish(),
})
)
export const sshCheckCommandExistsBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
commandName: z.string().min(1, 'Command name is required'),
})
)
export const sshCheckFileExistsBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
path: z.string().min(1, 'Path is required'),
type: z.enum(['file', 'directory', 'any']).default('any'),
})
)
export const sshCreateDirectoryBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
path: z.string().min(1, 'Path is required'),
recursive: z.boolean().default(true),
permissions: z.string().default('0755'),
})
)
export const sshDeleteFileBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
path: z.string().min(1, 'Path is required'),
recursive: z.boolean().default(false),
force: z.boolean().default(false),
})
)
export const sshDownloadFileBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
remotePath: z.string().min(1, 'Remote path is required'),
})
)
export const sshExecuteCommandBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
command: z.string().min(1, 'Command is required'),
workingDirectory: z.string().nullish(),
})
)
export const sshExecuteScriptBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
script: z.string().min(1, 'Script content is required'),
interpreter: z.string().default('/bin/bash'),
workingDirectory: z.string().nullish(),
})
)
export const sshGetSystemInfoBodySchema = requirePasswordOrPrivateKey(z.object(connectionFields))
export const sshListDirectoryBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
path: z.string().min(1, 'Path is required'),
detailed: z.boolean().default(true),
recursive: z.boolean().default(false),
})
)
export const sshMoveRenameBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
sourcePath: z.string().min(1, 'Source path is required'),
destinationPath: z.string().min(1, 'Destination path is required'),
overwrite: z.boolean().default(false),
})
)
export const sshReadFileContentBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
path: z.string().min(1, 'Path is required'),
encoding: z.string().default('utf-8'),
maxSize: z.coerce.number().min(0.01).max(50).default(10),
})
)
export const sshUploadFileBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
fileContent: z.string().min(1, 'File content is required'),
fileName: z.string().min(1, 'File name is required'),
remotePath: z.string().min(1, 'Remote path is required'),
permissions: z.string().nullish(),
overwrite: z.boolean().default(true),
})
)
export const sshWriteFileContentBodySchema = requirePasswordOrPrivateKey(
z.object({
...connectionFields,
path: z.string().min(1, 'Path is required'),
content: z.string(),
mode: z.enum(['overwrite', 'append', 'create']).default('overwrite'),
permissions: z.string().nullish(),
})
)
export const storageContextSchema = z.enum([
'knowledge-base',
'chat',
'copilot',
'mothership',
'execution',
'workspace',
'profile-pictures',
'og-images',
'logs',
'workspace-logos',
])
export const fileDownloadBodySchema = z
.object({
key: z.string().optional(),
name: z.string().optional(),
url: z
.string()
.url()
.refine((value) => ['http:', 'https:'].includes(new URL(value).protocol), {
message: 'URL must use http or https',
})
.optional(),
})
.passthrough()
export const fileParseBodySchema = z
.object({
filePath: z
.union([z.string(), z.array(z.string()).max(10, 'At most 10 files can be parsed at once')])
.optional(),
fileType: z.string().optional().default(''),
headers: z.record(z.string(), z.string()).optional(),
workspaceId: z.string().optional().default(''),
workflowId: z.string().optional(),
executionId: z.string().optional(),
})
.passthrough()
export const fileDeleteBodySchema = z
.object({
filePath: z.string().optional(),
context: storageContextSchema.optional(),
})
.passthrough()
const MAX_FILE_SIZE = 100 * 1024 * 1024
export const validUploadTypes = [
'knowledge-base',
'chat',
'copilot',
'profile-pictures',
'mothership',
'workspace-logos',
'execution',
] as const
export const uploadTypeSchema = z.enum(validUploadTypes)
export const presignedUploadQuerySchema = z.object({
type: uploadTypeSchema,
})
export const presignedUrlBodySchema = z
.object({
fileName: z
.string({ error: 'fileName is required and cannot be empty' })
.refine((value) => value.trim().length > 0, {
message: 'fileName is required and cannot be empty',
}),
contentType: z
.string({ error: 'contentType is required and cannot be empty' })
.refine((value) => value.trim().length > 0, {
message: 'contentType is required and cannot be empty',
}),
fileSize: z
.number({ error: 'fileSize must be a positive number' })
.positive('fileSize must be a positive number')
.superRefine((val, ctx) => {
if (val > MAX_FILE_SIZE) {
ctx.addIssue({
code: 'custom',
message: `File size ${formatFileSize(val)} exceeds maximum allowed size of ${formatFileSize(MAX_FILE_SIZE)}`,
})
}
}),
userId: z.string().optional(),
chatId: z.string().optional(),
})
.passthrough()
export const batchPresignedUrlBodySchema = z
.object({
files: z
.array(
z
.object({
fileName: z.string().refine((value) => value.trim().length > 0, {
message: 'fileName is required for all files',
}),
contentType: z.string().refine((value) => value.trim().length > 0, {
message: 'contentType is required for all files',
}),
fileSize: z.number(),
})
.passthrough()
.superRefine((file, ctx) => {
const name = typeof file.fileName === 'string' ? file.fileName : 'file'
if (!Number.isFinite(file.fileSize) || file.fileSize <= 0) {
ctx.addIssue({
code: 'custom',
path: ['fileSize'],
message: `${name} is empty (fileSize must be greater than 0)`,
})
} else if (file.fileSize > MAX_FILE_SIZE) {
ctx.addIssue({
code: 'custom',
path: ['fileSize'],
message: `${name} (${formatFileSize(file.fileSize)}) exceeds maximum allowed size of ${formatFileSize(MAX_FILE_SIZE)}`,
})
}
})
)
.min(1, 'files array is required and cannot be empty')
.max(100, 'Cannot process more than 100 files at once'),
})
.passthrough()
export const multipartActionSchema = z.enum(['initiate', 'get-part-urls', 'complete', 'abort'])
export const initiateMultipartBodySchema = z
.object({
fileName: z.string(),
contentType: z.string(),
fileSize: z.number(),
workspaceId: z.string({ error: 'workspaceId is required' }).min(1, 'workspaceId is required'),
context: z.string().optional(),
})
.passthrough()
export const tokenBoundMultipartBodySchema = z
.object({
uploadToken: z.string().optional(),
})
.passthrough()
export const getMultipartPartUrlsBodySchema = tokenBoundMultipartBodySchema.extend({
partNumbers: z.array(z.number()),
})
export const completeMultipartBodySchema = z
.object({
uploadToken: z.string().optional(),
parts: z.unknown().optional(),
uploads: z
.array(
z
.object({
uploadToken: z.string().optional(),
parts: z.unknown().optional(),
})
.passthrough()
)
.optional(),
})
.passthrough()
export type CompleteMultipartBody = z.output<typeof completeMultipartBodySchema>
export const uploadFilesFormFilesSchema = z.preprocess(
(value) => (Array.isArray(value) ? value.filter((entry) => entry instanceof File) : value),
z.array(z.custom<File>((value) => value instanceof File)).min(1, 'No files provided')
)
export const uploadFilesFormFieldsSchema = z.object({
workflowId: z.string().nullable(),
executionId: z.string().nullable(),
workspaceId: z.string().nullable(),
context: z.string().nullable(),
})
export const fileServeParamsSchema = z.object({
path: z.array(z.string()).min(1),
})
export const fileServeQuerySchema = z.object({
raw: z.string().nullish(),
/** Content version (the file record's `updatedAt`). Present => the URL is content-immutable and may be cached indefinitely by the browser. */
v: z.string().nullish(),
})
export const fileViewParamsSchema = z.object({
id: workspaceFileIdSchema,
})
export const fileExportParamsSchema = z.object({
id: workspaceFileIdSchema,
})
export const boxUploadContract = defineRouteContract({
method: 'POST',
path: '/api/tools/box/upload',
body: boxUploadBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const dropboxUploadContract = defineRouteContract({
method: 'POST',
path: '/api/tools/dropbox/upload',
body: dropboxUploadBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const jupyterUploadContract = defineRouteContract({
method: 'POST',
path: '/api/tools/jupyter/upload',
body: jupyterUploadBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const wordpressUploadContract = defineRouteContract({
method: 'POST',
path: '/api/tools/wordpress/upload',
body: wordpressUploadBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sftpListContract = defineRouteContract({
method: 'POST',
path: '/api/tools/sftp/list',
body: sftpListBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sftpDeleteContract = defineRouteContract({
method: 'POST',
path: '/api/tools/sftp/delete',
body: sftpDeleteBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sftpMkdirContract = defineRouteContract({
method: 'POST',
path: '/api/tools/sftp/mkdir',
body: sftpMkdirBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sftpDownloadContract = defineRouteContract({
method: 'POST',
path: '/api/tools/sftp/download',
body: sftpDownloadBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sftpUploadContract = defineRouteContract({
method: 'POST',
path: '/api/tools/sftp/upload',
body: sftpUploadBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshCheckCommandExistsContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/check-command-exists',
body: sshCheckCommandExistsBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshCheckFileExistsContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/check-file-exists',
body: sshCheckFileExistsBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshCreateDirectoryContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/create-directory',
body: sshCreateDirectoryBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshDeleteFileContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/delete-file',
body: sshDeleteFileBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshDownloadFileContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/download-file',
body: sshDownloadFileBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshExecuteCommandContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/execute-command',
body: sshExecuteCommandBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshExecuteScriptContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/execute-script',
body: sshExecuteScriptBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshGetSystemInfoContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/get-system-info',
body: sshGetSystemInfoBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshListDirectoryContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/list-directory',
body: sshListDirectoryBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshMoveRenameContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/move-rename',
body: sshMoveRenameBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshReadFileContentContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/read-file-content',
body: sshReadFileContentBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshUploadFileContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/upload-file',
body: sshUploadFileBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const sshWriteFileContentContract = defineRouteContract({
method: 'POST',
path: '/api/tools/ssh/write-file-content',
body: sshWriteFileContentBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const fileDownloadContract = defineRouteContract({
method: 'POST',
path: '/api/files/download',
body: fileDownloadBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const fileParseContract = defineRouteContract({
method: 'POST',
path: '/api/files/parse',
body: fileParseBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const fileDeleteContract = defineRouteContract({
method: 'POST',
path: '/api/files/delete',
body: fileDeleteBodySchema,
response: { mode: 'json', schema: jsonResponseSchema },
})
export const fileUploadContract = defineRouteContract({
method: 'POST',
path: '/api/files/upload',
response: { mode: 'json', schema: jsonResponseSchema },
})
export const presignedUploadContract = defineRouteContract({
method: 'POST',
path: '/api/files/presigned',
query: presignedUploadQuerySchema,
body: presignedUrlBodySchema,
response: { mode: 'json', schema: presignedUploadResponseSchema },
})
export const presignedUploadBodyContract = defineRouteContract({
method: 'POST',
path: '/api/files/presigned',
body: presignedUrlBodySchema,
response: { mode: 'json', schema: presignedUploadResponseSchema },
})
export const batchPresignedUploadContract = defineRouteContract({
method: 'POST',
path: '/api/files/presigned/batch',
query: presignedUploadQuerySchema,
body: batchPresignedUrlBodySchema,
response: { mode: 'json', schema: batchPresignedUploadResponseSchema },
})
export const batchPresignedUploadBodyContract = defineRouteContract({
method: 'POST',
path: '/api/files/presigned/batch',
body: batchPresignedUrlBodySchema,
response: { mode: 'json', schema: batchPresignedUploadResponseSchema },
})
export const multipartUploadContract = defineRouteContract({
method: 'POST',
path: '/api/files/multipart',
response: { mode: 'json', schema: multipartUploadResponseSchema },
})
export const initiateMultipartUploadContract = defineRouteContract({
method: 'POST',
path: '/api/files/multipart',
body: initiateMultipartBodySchema,
response: { mode: 'json', schema: initiateMultipartResponseSchema },
})
export const getMultipartPartUrlsContract = defineRouteContract({
method: 'POST',
path: '/api/files/multipart',
body: getMultipartPartUrlsBodySchema,
response: { mode: 'json', schema: getMultipartPartUrlsResponseSchema },
})
export const completeMultipartUploadContract = defineRouteContract({
method: 'POST',
path: '/api/files/multipart',
body: completeMultipartBodySchema,
response: { mode: 'json', schema: completeMultipartResponseSchema },
})
export const abortMultipartUploadContract = defineRouteContract({
method: 'POST',
path: '/api/files/multipart',
body: tokenBoundMultipartBodySchema,
response: { mode: 'json', schema: abortMultipartResponseSchema },
})
export const fileServeContract = defineRouteContract({
method: 'GET',
path: '/api/files/serve/[...path]',
params: fileServeParamsSchema,
query: fileServeQuerySchema,
response: { mode: 'binary' },
})
export const fileViewContract = defineRouteContract({
method: 'GET',
path: '/api/files/view/[id]',
params: fileViewParamsSchema,
response: { mode: 'binary' },
})
export const fileExportContract = defineRouteContract({
method: 'GET',
path: '/api/files/export/[id]',
params: fileExportParamsSchema,
response: { mode: 'binary' },
})
export type BoxUploadBody = ContractBodyInput<typeof boxUploadContract>
export type BoxUploadResponse = ContractJsonResponse<typeof boxUploadContract>
export type DropboxUploadBody = ContractBodyInput<typeof dropboxUploadContract>
export type DropboxUploadResponse = ContractJsonResponse<typeof dropboxUploadContract>
export type JupyterUploadBody = ContractBodyInput<typeof jupyterUploadContract>
export type JupyterUploadResponse = ContractJsonResponse<typeof jupyterUploadContract>
export type WordPressUploadBody = ContractBodyInput<typeof wordpressUploadContract>
export type WordPressUploadResponse = ContractJsonResponse<typeof wordpressUploadContract>
export type SftpDownloadBody = ContractBodyInput<typeof sftpDownloadContract>
export type SftpUploadBody = ContractBodyInput<typeof sftpUploadContract>
export type SftpDeleteBody = ContractBodyInput<typeof sftpDeleteContract>
export type SftpMkdirBody = ContractBodyInput<typeof sftpMkdirContract>
export type SshCheckCommandExistsBody = ContractBodyInput<typeof sshCheckCommandExistsContract>
export type SshCheckFileExistsBody = ContractBodyInput<typeof sshCheckFileExistsContract>
export type SshCreateDirectoryBody = ContractBodyInput<typeof sshCreateDirectoryContract>
export type SshDeleteFileBody = ContractBodyInput<typeof sshDeleteFileContract>
export type SshDownloadFileBody = ContractBodyInput<typeof sshDownloadFileContract>
export type SshExecuteCommandBody = ContractBodyInput<typeof sshExecuteCommandContract>
export type SshExecuteScriptBody = ContractBodyInput<typeof sshExecuteScriptContract>
export type SshGetSystemInfoBody = ContractBodyInput<typeof sshGetSystemInfoContract>
export type SshListDirectoryBody = ContractBodyInput<typeof sshListDirectoryContract>
export type SshMoveRenameBody = ContractBodyInput<typeof sshMoveRenameContract>
export type SshReadFileContentBody = ContractBodyInput<typeof sshReadFileContentContract>
export type SshUploadFileBody = ContractBodyInput<typeof sshUploadFileContract>
export type SshWriteFileContentBody = ContractBodyInput<typeof sshWriteFileContentContract>
export type FileDownloadBody = ContractBodyInput<typeof fileDownloadContract>
export type FileDownloadResponse = ContractJsonResponse<typeof fileDownloadContract>
export type FileParseBody = ContractBodyInput<typeof fileParseContract>
export type FileParseResponse = ContractJsonResponse<typeof fileParseContract>
export type FileDeleteBody = ContractBodyInput<typeof fileDeleteContract>
export type FileDeleteResponse = ContractJsonResponse<typeof fileDeleteContract>
export type PresignedUploadQuery = ContractQueryInput<typeof presignedUploadContract>
export type PresignedUploadBody = ContractBodyInput<typeof presignedUploadContract>
export type PresignedUploadResponse = ContractJsonResponse<typeof presignedUploadContract>
export type BatchPresignedUploadQuery = ContractQueryInput<typeof batchPresignedUploadContract>
export type BatchPresignedUploadBody = ContractBodyInput<typeof batchPresignedUploadContract>
export type BatchPresignedUploadResponse = ContractJsonResponse<typeof batchPresignedUploadContract>
export type MultipartAction = z.output<typeof multipartActionSchema>
export type InitiateMultipartBody = z.output<typeof initiateMultipartBodySchema>
export type TokenBoundMultipartBody = z.output<typeof tokenBoundMultipartBodySchema>
export type GetMultipartPartUrlsBody = z.output<typeof getMultipartPartUrlsBodySchema>
export type FileServeParams = ContractParamsInput<typeof fileServeContract>
export type FileServeQuery = ContractQueryInput<typeof fileServeContract>
export type FileViewParams = ContractParamsInput<typeof fileViewContract>
export type FileExportParams = ContractParamsInput<typeof fileExportContract>