chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
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

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,96 @@
import type { SSHCheckCommandExistsParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const checkCommandExistsTool: ToolConfig<SSHCheckCommandExistsParams, SSHResponse> = {
id: 'ssh_check_command_exists',
name: 'SSH Check Command Exists',
description: 'Check if a command/program exists on the remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
commandName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Command name to check (e.g., docker, git, python3)',
},
},
request: {
url: '/api/tools/ssh/check-command-exists',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
commandName: params.commandName,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH check command exists failed')
}
return {
success: true,
output: {
commandExists: data.exists ?? false,
commandPath: data.path,
version: data.version,
message: data.message,
},
}
},
outputs: {
commandExists: { type: 'boolean', description: 'Whether the command exists' },
commandPath: { type: 'string', description: 'Full path to the command (if found)' },
version: { type: 'string', description: 'Command version output (if applicable)' },
message: { type: 'string', description: 'Operation status message' },
},
}
+107
View File
@@ -0,0 +1,107 @@
import type { SSHCheckFileExistsParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const checkFileExistsTool: ToolConfig<SSHCheckFileExistsParams, SSHResponse> = {
id: 'ssh_check_file_exists',
name: 'SSH Check File Exists',
description: 'Check if a file or directory exists on the remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Remote file or directory path to check',
},
type: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Expected type: file, directory, or any (default: any)',
},
},
request: {
url: '/api/tools/ssh/check-file-exists',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
path: params.path,
type: params.type || 'any',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH check file exists failed')
}
return {
success: true,
output: {
exists: data.exists ?? false,
type: data.type || 'not_found',
size: data.size,
permissions: data.permissions,
modified: data.modified,
message: data.message,
},
}
},
outputs: {
exists: { type: 'boolean', description: 'Whether the path exists' },
type: { type: 'string', description: 'Type of path (file, directory, symlink, not_found)' },
size: { type: 'number', description: 'File size if it is a file' },
permissions: { type: 'string', description: 'File permissions (e.g., 0755)' },
modified: { type: 'string', description: 'Last modified timestamp' },
message: { type: 'string', description: 'Operation status message' },
},
}
+110
View File
@@ -0,0 +1,110 @@
import type { SSHCreateDirectoryParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const createDirectoryTool: ToolConfig<SSHCreateDirectoryParams, SSHResponse> = {
id: 'ssh_create_directory',
name: 'SSH Create Directory',
description: 'Create a directory on the remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Directory path to create',
},
recursive: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Create parent directories if they do not exist (default: true)',
},
permissions: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Directory permissions (default: 0755)',
},
},
request: {
url: '/api/tools/ssh/create-directory',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
path: params.path,
recursive: params.recursive !== false,
permissions: params.permissions || '0755',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH create directory failed')
}
return {
success: true,
output: {
created: data.created ?? true,
remotePath: data.path,
alreadyExists: data.alreadyExists ?? false,
message: data.message,
},
}
},
outputs: {
created: { type: 'boolean', description: 'Whether the directory was created successfully' },
remotePath: { type: 'string', description: 'Created directory path' },
alreadyExists: { type: 'boolean', description: 'Whether the directory already existed' },
message: { type: 'string', description: 'Operation status message' },
},
}
+108
View File
@@ -0,0 +1,108 @@
import type { SSHDeleteFileParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const deleteFileTool: ToolConfig<SSHDeleteFileParams, SSHResponse> = {
id: 'ssh_delete_file',
name: 'SSH Delete File',
description: 'Delete a file or directory from the remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Path to delete',
},
recursive: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Recursively delete directories (default: false)',
},
force: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Force deletion without confirmation (default: false)',
},
},
request: {
url: '/api/tools/ssh/delete-file',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
path: params.path,
recursive: params.recursive === true,
force: params.force === true,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH delete file failed')
}
return {
success: true,
output: {
deleted: data.deleted ?? true,
remotePath: data.path,
message: data.message,
},
}
},
outputs: {
deleted: { type: 'boolean', description: 'Whether the path was deleted successfully' },
remotePath: { type: 'string', description: 'Deleted path' },
message: { type: 'string', description: 'Operation status message' },
},
}
+102
View File
@@ -0,0 +1,102 @@
import type { SSHDownloadFileParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const downloadFileTool: ToolConfig<SSHDownloadFileParams, SSHResponse> = {
id: 'ssh_download_file',
name: 'SSH Download File',
description: 'Download a file from a remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
remotePath: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Path of the file on the remote server',
},
},
request: {
url: '/api/tools/ssh/download-file',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
remotePath: params.remotePath,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH file download failed')
}
return {
success: true,
output: {
downloaded: true,
file: data.file,
fileContent: data.content,
fileName: data.fileName,
remotePath: data.remotePath,
size: data.size,
message: data.message,
},
}
},
outputs: {
downloaded: { type: 'boolean', description: 'Whether the file was downloaded successfully' },
file: { type: 'file', description: 'Downloaded file stored in execution files' },
fileContent: { type: 'string', description: 'File content (base64 encoded for binary files)' },
fileName: { type: 'string', description: 'Name of the downloaded file' },
remotePath: { type: 'string', description: 'Source path on the remote server' },
size: { type: 'number', description: 'File size in bytes' },
message: { type: 'string', description: 'Operation status message' },
},
}
+105
View File
@@ -0,0 +1,105 @@
import type { SSHExecuteCommandParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const executeCommandTool: ToolConfig<SSHExecuteCommandParams, SSHResponse> = {
id: 'ssh_execute_command',
name: 'SSH Execute Command',
description: 'Execute a shell command on a remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
command: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Shell command to execute on the remote server',
},
workingDirectory: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Working directory for command execution',
},
},
request: {
url: '/api/tools/ssh/execute-command',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
command: params.command,
workingDirectory: params.workingDirectory,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH command execution failed')
}
return {
success: true,
output: {
stdout: data.stdout || '',
stderr: data.stderr || '',
exitCode: data.exitCode ?? 0,
success: data.exitCode === 0,
message: data.message,
},
}
},
outputs: {
stdout: { type: 'string', description: 'Standard output from command' },
stderr: { type: 'string', description: 'Standard error output' },
exitCode: { type: 'number', description: 'Command exit code' },
success: { type: 'boolean', description: 'Whether command succeeded (exit code 0)' },
message: { type: 'string', description: 'Operation status message' },
},
}
+114
View File
@@ -0,0 +1,114 @@
import type { SSHExecuteScriptParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const executeScriptTool: ToolConfig<SSHExecuteScriptParams, SSHResponse> = {
id: 'ssh_execute_script',
name: 'SSH Execute Script',
description: 'Upload and execute a multi-line script on a remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
script: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Script content to execute (bash, python, etc.)',
},
interpreter: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Script interpreter (default: /bin/bash)',
},
workingDirectory: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Working directory for script execution',
},
},
request: {
url: '/api/tools/ssh/execute-script',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
script: params.script,
interpreter: params.interpreter || '/bin/bash',
workingDirectory: params.workingDirectory,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH script execution failed')
}
return {
success: true,
output: {
stdout: data.stdout || '',
stderr: data.stderr || '',
exitCode: data.exitCode ?? 0,
success: data.exitCode === 0,
scriptPath: data.scriptPath,
message: data.message,
},
}
},
outputs: {
stdout: { type: 'string', description: 'Standard output from script' },
stderr: { type: 'string', description: 'Standard error output' },
exitCode: { type: 'number', description: 'Script exit code' },
success: { type: 'boolean', description: 'Whether script succeeded (exit code 0)' },
scriptPath: { type: 'string', description: 'Temporary path where script was uploaded' },
message: { type: 'string', description: 'Operation status message' },
},
}
+101
View File
@@ -0,0 +1,101 @@
import type { SSHGetSystemInfoParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const getSystemInfoTool: ToolConfig<SSHGetSystemInfoParams, SSHResponse> = {
id: 'ssh_get_system_info',
name: 'SSH Get System Info',
description: 'Retrieve system information from the remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
},
request: {
url: '/api/tools/ssh/get-system-info',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH get system info failed')
}
return {
success: true,
output: {
hostname: data.hostname,
os: data.os,
architecture: data.architecture,
uptime: data.uptime,
memory: data.memory,
diskSpace: data.diskSpace,
message: data.message,
},
}
},
outputs: {
hostname: { type: 'string', description: 'Server hostname' },
os: { type: 'string', description: 'Operating system (e.g., Linux, Darwin)' },
architecture: { type: 'string', description: 'CPU architecture (e.g., x64, arm64)' },
uptime: { type: 'number', description: 'System uptime in seconds' },
memory: {
type: 'json',
description: 'Memory information (total, free, used)',
},
diskSpace: {
type: 'json',
description: 'Disk space information (total, free, used)',
},
message: { type: 'string', description: 'Operation status message' },
},
}
+27
View File
@@ -0,0 +1,27 @@
import { checkCommandExistsTool } from './check_command_exists'
import { checkFileExistsTool } from './check_file_exists'
import { createDirectoryTool } from './create_directory'
import { deleteFileTool } from './delete_file'
import { downloadFileTool } from './download_file'
import { executeCommandTool } from './execute_command'
import { executeScriptTool } from './execute_script'
import { getSystemInfoTool } from './get_system_info'
import { listDirectoryTool } from './list_directory'
import { moveRenameTool } from './move_rename'
import { readFileContentTool } from './read_file_content'
import { uploadFileTool } from './upload_file'
import { writeFileContentTool } from './write_file_content'
export const sshCheckCommandExistsTool = checkCommandExistsTool
export const sshCheckFileExistsTool = checkFileExistsTool
export const sshCreateDirectoryTool = createDirectoryTool
export const sshDeleteFileTool = deleteFileTool
export const sshDownloadFileTool = downloadFileTool
export const sshExecuteCommandTool = executeCommandTool
export const sshExecuteScriptTool = executeScriptTool
export const sshGetSystemInfoTool = getSystemInfoTool
export const sshListDirectoryTool = listDirectoryTool
export const sshMoveRenameTool = moveRenameTool
export const sshReadFileContentTool = readFileContentTool
export const sshUploadFileTool = uploadFileTool
export const sshWriteFileContentTool = writeFileContentTool
+123
View File
@@ -0,0 +1,123 @@
import type { SSHListDirectoryParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const listDirectoryTool: ToolConfig<SSHListDirectoryParams, SSHResponse> = {
id: 'ssh_list_directory',
name: 'SSH List Directory',
description: 'List files and directories in a remote directory',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Remote directory path to list',
},
detailed: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Include file details (size, permissions, modified date)',
},
recursive: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'List subdirectories recursively (default: false)',
},
},
request: {
url: '/api/tools/ssh/list-directory',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
path: params.path,
detailed: params.detailed !== false,
recursive: params.recursive === true,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH list directory failed')
}
return {
success: true,
output: {
entries: data.entries || [],
totalFiles: data.totalFiles || 0,
totalDirectories: data.totalDirectories || 0,
message: data.message,
},
}
},
outputs: {
entries: {
type: 'array',
description: 'Array of file and directory entries',
items: {
type: 'object',
properties: {
name: { type: 'string', description: 'File or directory name' },
type: { type: 'string', description: 'Entry type (file, directory, symlink)' },
size: { type: 'number', description: 'File size in bytes' },
permissions: { type: 'string', description: 'File permissions' },
modified: { type: 'string', description: 'Last modified timestamp' },
},
},
},
totalFiles: { type: 'number', description: 'Total number of files' },
totalDirectories: { type: 'number', description: 'Total number of directories' },
message: { type: 'string', description: 'Operation status message' },
},
}
+110
View File
@@ -0,0 +1,110 @@
import type { SSHMoveRenameParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const moveRenameTool: ToolConfig<SSHMoveRenameParams, SSHResponse> = {
id: 'ssh_move_rename',
name: 'SSH Move/Rename',
description: 'Move or rename a file or directory on the remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
sourcePath: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Current path of the file or directory',
},
destinationPath: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'New path for the file or directory',
},
overwrite: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Overwrite destination if it exists (default: false)',
},
},
request: {
url: '/api/tools/ssh/move-rename',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
sourcePath: params.sourcePath,
destinationPath: params.destinationPath,
overwrite: params.overwrite === true,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH move/rename failed')
}
return {
success: true,
output: {
moved: data.success ?? true,
sourcePath: data.sourcePath,
destinationPath: data.destinationPath,
message: data.message,
},
}
},
outputs: {
moved: { type: 'boolean', description: 'Whether the operation was successful' },
sourcePath: { type: 'string', description: 'Original path' },
destinationPath: { type: 'string', description: 'New path' },
message: { type: 'string', description: 'Operation status message' },
},
}
+112
View File
@@ -0,0 +1,112 @@
import type { SSHReadFileContentParams, SSHResponse } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const readFileContentTool: ToolConfig<SSHReadFileContentParams, SSHResponse> = {
id: 'ssh_read_file_content',
name: 'SSH Read File Content',
description: 'Read the contents of a remote file',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Remote file path to read',
},
encoding: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'File encoding (default: utf-8)',
},
maxSize: {
type: 'number',
required: false,
visibility: 'user-only',
description: 'Maximum file size to read in MB (default: 10)',
},
},
request: {
url: '/api/tools/ssh/read-file-content',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
path: params.path,
encoding: params.encoding || 'utf-8',
maxSize: params.maxSize || 10,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH read file content failed')
}
return {
success: true,
output: {
content: data.content,
size: data.size,
lines: data.lines,
remotePath: data.path,
message: data.message,
},
}
},
outputs: {
content: { type: 'string', description: 'File content as string' },
size: { type: 'number', description: 'File size in bytes' },
lines: { type: 'number', description: 'Number of lines in file' },
remotePath: { type: 'string', description: 'Remote file path' },
message: { type: 'string', description: 'Operation status message' },
},
}
+219
View File
@@ -0,0 +1,219 @@
import type { ToolFileData, ToolResponse } from '@/tools/types'
// Base SSH connection configuration
interface SSHConnectionConfig {
host: string
port: number
username: string
password?: string
privateKey?: string
passphrase?: string
timeout?: number
keepaliveInterval?: number
readyTimeout?: number
}
// Execute Command parameters
export interface SSHExecuteCommandParams extends SSHConnectionConfig {
command: string
workingDirectory?: string
}
// Execute Script parameters
export interface SSHExecuteScriptParams extends SSHConnectionConfig {
script: string
interpreter?: string
workingDirectory?: string
}
// Check Command Exists parameters
export interface SSHCheckCommandExistsParams extends SSHConnectionConfig {
commandName: string
}
// Upload File parameters
export interface SSHUploadFileParams extends SSHConnectionConfig {
fileContent: string
fileName: string
remotePath: string
permissions?: string
overwrite?: boolean
}
// Upload Directory parameters
interface SSHUploadDirectoryParams extends SSHConnectionConfig {
localDirectory: string
remoteDirectory: string
recursive?: boolean
concurrency?: number
}
// Download File parameters
export interface SSHDownloadFileParams extends SSHConnectionConfig {
remotePath: string
}
// Download Directory parameters
interface SSHDownloadDirectoryParams extends SSHConnectionConfig {
remotePath: string
recursive?: boolean
}
// List Directory parameters
export interface SSHListDirectoryParams extends SSHConnectionConfig {
path: string
detailed?: boolean
recursive?: boolean
}
// Check File Exists parameters
export interface SSHCheckFileExistsParams extends SSHConnectionConfig {
path: string
type?: 'file' | 'directory' | 'any'
}
// Create Directory parameters
export interface SSHCreateDirectoryParams extends SSHConnectionConfig {
path: string
recursive?: boolean
permissions?: string
}
// Delete File parameters
export interface SSHDeleteFileParams extends SSHConnectionConfig {
path: string
recursive?: boolean
force?: boolean
}
// Move/Rename parameters
export interface SSHMoveRenameParams extends SSHConnectionConfig {
sourcePath: string
destinationPath: string
overwrite?: boolean
}
// Get System Info parameters
export interface SSHGetSystemInfoParams extends SSHConnectionConfig {}
// Read File Content parameters
export interface SSHReadFileContentParams extends SSHConnectionConfig {
path: string
encoding?: string
maxSize?: number
}
// Write File Content parameters
export interface SSHWriteFileContentParams extends SSHConnectionConfig {
path: string
content: string
mode?: 'overwrite' | 'append' | 'create'
permissions?: string
}
// File info interface
interface SSHFileInfo {
name: string
type: 'file' | 'directory' | 'symlink' | 'other'
size: number
permissions: string
modified: string
owner?: string
group?: string
}
// System info interface
interface SSHSystemInfo {
hostname: string
os: string
architecture: string
uptime: number
memory: {
total: number
free: number
used: number
}
diskSpace: {
total: number
free: number
used: number
}
}
export interface SSHResponse extends ToolResponse {
output: {
stdout?: string
stderr?: string
exitCode?: number
success?: boolean
uploaded?: boolean
downloaded?: boolean
file?: ToolFileData
fileContent?: string
fileName?: string
remotePath?: string
localPath?: string
size?: number
entries?: SSHFileInfo[]
totalFiles?: number
totalDirectories?: number
exists?: boolean
type?: 'file' | 'directory' | 'symlink' | 'not_found'
permissions?: string
modified?: string
hostname?: string
os?: string
architecture?: string
uptime?: number
memory?: {
total: number
free: number
used: number
}
diskSpace?: {
total: number
free: number
used: number
}
content?: string
lines?: number
created?: boolean
deleted?: boolean
written?: boolean
moved?: boolean
alreadyExists?: boolean
commandExists?: boolean
commandPath?: string
version?: string
scriptPath?: string
message?: string
metadata?: Record<string, unknown>
}
}
// Union type for all SSH parameters
export type SSHParams =
| SSHExecuteCommandParams
| SSHExecuteScriptParams
| SSHCheckCommandExistsParams
| SSHUploadFileParams
| SSHUploadDirectoryParams
| SSHDownloadFileParams
| SSHDownloadDirectoryParams
| SSHListDirectoryParams
| SSHCheckFileExistsParams
| SSHCreateDirectoryParams
| SSHDeleteFileParams
| SSHMoveRenameParams
| SSHGetSystemInfoParams
| SSHReadFileContentParams
| SSHWriteFileContentParams
+124
View File
@@ -0,0 +1,124 @@
import type { SSHResponse, SSHUploadFileParams } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const uploadFileTool: ToolConfig<SSHUploadFileParams, SSHResponse> = {
id: 'ssh_upload_file',
name: 'SSH Upload File',
description: 'Upload a file to a remote SSH server',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
fileContent: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'File content to upload (base64 encoded for binary files)',
},
fileName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Name of the file being uploaded',
},
remotePath: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Destination path on the remote server',
},
permissions: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'File permissions (e.g., 0644)',
},
overwrite: {
type: 'boolean',
required: false,
visibility: 'user-only',
description: 'Whether to overwrite existing files (default: true)',
},
},
request: {
url: '/api/tools/ssh/upload-file',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
fileContent: params.fileContent,
fileName: params.fileName,
remotePath: params.remotePath,
permissions: params.permissions,
overwrite: params.overwrite !== false,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH file upload failed')
}
return {
success: true,
output: {
uploaded: true,
remotePath: data.remotePath,
size: data.size,
message: data.message,
},
}
},
outputs: {
uploaded: { type: 'boolean', description: 'Whether the file was uploaded successfully' },
remotePath: { type: 'string', description: 'Final path on the remote server' },
size: { type: 'number', description: 'File size in bytes' },
message: { type: 'string', description: 'Operation status message' },
},
}
+117
View File
@@ -0,0 +1,117 @@
import type { SSHResponse, SSHWriteFileContentParams } from '@/tools/ssh/types'
import type { ToolConfig } from '@/tools/types'
export const writeFileContentTool: ToolConfig<SSHWriteFileContentParams, SSHResponse> = {
id: 'ssh_write_file_content',
name: 'SSH Write File Content',
description: 'Write or append content to a remote file',
version: '1.0.0',
params: {
host: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH server hostname or IP address',
},
port: {
type: 'number',
required: true,
visibility: 'user-only',
description: 'SSH server port (default: 22)',
},
username: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'SSH username',
},
password: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Password for authentication (if not using private key)',
},
privateKey: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Private key for authentication (OpenSSH format)',
},
passphrase: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Passphrase for encrypted private key',
},
path: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Remote file path to write to',
},
content: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Content to write to the file',
},
mode: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'Write mode: overwrite, append, or create (default: overwrite)',
},
permissions: {
type: 'string',
required: false,
visibility: 'user-only',
description: 'File permissions (e.g., 0644)',
},
},
request: {
url: '/api/tools/ssh/write-file-content',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (params) => ({
host: params.host,
port: Number(params.port) || 22,
username: params.username,
password: params.password,
privateKey: params.privateKey,
passphrase: params.passphrase,
path: params.path,
content: params.content,
mode: params.mode || 'overwrite',
permissions: params.permissions,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.error || 'SSH write file content failed')
}
return {
success: true,
output: {
written: data.written ?? true,
remotePath: data.path,
size: data.size,
message: data.message,
},
}
},
outputs: {
written: { type: 'boolean', description: 'Whether the file was written successfully' },
remotePath: { type: 'string', description: 'File path' },
size: { type: 'number', description: 'Final file size in bytes' },
message: { type: 'string', description: 'Operation status message' },
},
}