完善了agent

This commit is contained in:
lik
2026-05-30 16:41:26 +08:00
parent 797e69a0c2
commit b92853a717
30 changed files with 1972 additions and 22 deletions

View File

@@ -0,0 +1,257 @@
import * as z from "zod"
import { tool } from "langchain"
import os from 'os'
import { promisify } from 'util'
import { exec } from 'child_process'
const execPromise = promisify(exec)
/**
* 获取系统文件信息工具
* @returns {string} - 返回系统文件信息的 JSON 字符串,包括分区信息和各分区剩余空间
*/
export const getSystemFileInfoTool = tool(
async (input) => {
try {
const fileSystemInfo = {
platform: os.platform(),
partitions: [],
volumeInfo: [],
diskHealth: [],
inodeInfo: []
}
// 获取文件系统信息Windows
if (os.platform() === 'win32') {
try {
const { stdout } = await execPromise('powershell -Command "Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID,Description,FileSystem,Size,FreeSpace,VolumeName | ConvertTo-Json"')
const partitionData = JSON.parse(stdout)
const partitionsArray = Array.isArray(partitionData) ? partitionData : [partitionData]
fileSystemInfo.partitions = partitionsArray.map(disk => {
const size = disk.Size ? parseInt(disk.Size) : 0
const freeSpace = disk.FreeSpace ? parseInt(disk.FreeSpace) : 0
const usedSpace = size - freeSpace
return {
device: disk.DeviceID || 'N/A',
description: disk.Description || 'N/A',
filesystem: disk.FileSystem || 'N/A',
volumeName: disk.VolumeName || 'N/A',
size: size > 0 ? `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB` : 'N/A',
freeSpace: freeSpace > 0 ? `${(freeSpace / (1024 * 1024 * 1024)).toFixed(2)} GB` : 'N/A',
usedSpace: usedSpace > 0 ? `${(usedSpace / (1024 * 1024 * 1024)).toFixed(2)} GB` : 'N/A',
usePercent: size > 0 ? `${((usedSpace / size) * 100).toFixed(2)}%` : 'N/A'
}
}).filter(item => item)
// 获取卷详细信息Windows
try {
const { stdout } = await execPromise('powershell -Command "Get-WmiObject Win32_LogicalDisk | Select-Object VolumeName,VolumeSerialNumber,FileSystem,MaximumComponentLength,DeviceID,DriveType | ConvertTo-Json"')
const allVolumeData = JSON.parse(stdout)
const volumeArray = Array.isArray(allVolumeData) ? allVolumeData : [allVolumeData]
fileSystemInfo.volumeInfo = volumeArray.map(vol => ({
device: vol.DeviceID || 'N/A',
volumeName: vol.VolumeName || 'N/A',
serialNumber: vol.VolumeSerialNumber || 'N/A',
fileSystem: vol.FileSystem || 'N/A',
maxComponentLength: vol.MaximumComponentLength || 'N/A',
deviceID: vol.DeviceID || 'N/A',
driveType: vol.DriveType === 2 ? 'Removable' : vol.DriveType === 3 ? 'Local' : vol.DriveType === 4 ? 'Network' : vol.DriveType === 5 ? 'CD-ROM' : 'Unknown'
})).filter(item => item)
} catch (error) {
console.error('Error getting volume info:', error)
}
// 获取磁盘健康状态Windows SMART
try {
const { stdout } = await execPromise('powershell -Command "Get-WmiObject Win32_DiskDrive | Select-Object Model,Status,SerialNumber,Size,MediaType | ConvertTo-Json"')
const diskData = JSON.parse(stdout)
const diskArray = Array.isArray(diskData) ? diskData : [diskData]
fileSystemInfo.diskHealth = diskArray.map(disk => {
return {
model: disk.Model || 'N/A',
status: disk.Status || 'N/A',
serialNumber: disk.SerialNumber || 'N/A',
size: disk.Size ? `${(parseInt(disk.Size) / (1024 * 1024 * 1024)).toFixed(2)} GB` : 'N/A'
}
}).filter(item => item)
} catch (error) {
console.error('Error getting disk health:', error)
}
} catch (error) {
console.error('Error getting file system info:', error)
fileSystemInfo.error = 'Error getting file system info'
}
}
// 获取文件系统信息Linux
else if (os.platform() === 'linux') {
try {
const { stdout } = await execPromise('df -h')
fileSystemInfo.partitions = stdout.trim().split('\n').slice(1).map(line => {
const parts = line.trim().split(/\s+/)
if (parts.length >= 6) {
return {
device: parts[0],
size: parts[1],
usedSpace: parts[2],
freeSpace: parts[3],
usePercent: parts[4],
mountedOn: parts[5]
}
}
return null
}).filter(item => item)
// 获取挂载选项和文件系统类型Linux
try {
const { stdout } = await execPromise('mount | column -t')
const mountLines = stdout.trim().split('\n')
const mountInfo = {}
mountLines.forEach(line => {
const match = line.match(/^(.+?)\s+on\s+(.+?)\s+type\s+(.+?)\s+\((.*)\)$/)
if (match) {
mountInfo[match[2]] = {
device: match[1],
filesystem: match[3],
options: match[4]
}
}
})
fileSystemInfo.mountInfo = mountInfo
} catch (error) {
console.error('Error getting mount info:', error)
}
// 获取inode信息Linux
try {
const { stdout } = await execPromise('df -i')
fileSystemInfo.inodeInfo = stdout.trim().split('\n').slice(1).map(line => {
const parts = line.trim().split(/\s+/)
if (parts.length >= 6) {
return {
device: parts[0],
totalInodes: parts[1],
usedInodes: parts[2],
freeInodes: parts[3],
usePercent: parts[4],
mountedOn: parts[5]
}
}
return null
}).filter(item => item)
} catch (error) {
console.error('Error getting inode info:', error)
}
// 获取磁盘健康状态Linux SMART
try {
const { stdout } = await execPromise('smartctl --health --json /dev/sda 2>/dev/null || echo "{}"')
if (stdout && stdout.includes('smart_status')) {
const healthData = JSON.parse(stdout)
fileSystemInfo.diskHealth.push({
device: '/dev/sda',
status: healthData.smart_status?.passed ? 'OK' : 'Failed',
powerOnHours: healthData.power_on_time?.hours || 'N/A',
temperature: healthData.temperature?.current || 'N/A'
})
}
} catch (error) {
console.log('SMART info not available or requires root')
}
} catch (error) {
console.error('Error getting file system info:', error)
fileSystemInfo.error = 'Error getting file system info'
}
}
// 获取文件系统信息macOS
else if (os.platform() === 'darwin') {
try {
const { stdout } = await execPromise('df -h')
fileSystemInfo.partitions = stdout.trim().split('\n').slice(1).map(line => {
const parts = line.trim().split(/\s+/)
if (parts.length >= 6) {
return {
device: parts[0],
size: parts[1],
usedSpace: parts[2],
freeSpace: parts[3],
usePercent: parts[4],
mountedOn: parts[5]
}
}
return null
}).filter(item => item)
// 获取卷详细信息macOS
try {
const diskInfo = await execPromise('diskutil info -all')
const diskLines = diskInfo.stdout.trim().split('\n\n')
diskLines.forEach(disk => {
const volMatch = disk.match(/Volume Name:\s+(.+)/)
const devMatch = disk.match(/Device Node:\s+(.+)/)
const fsMatch = disk.match(/File System Personality:\s+(.+)/)
const serialMatch = disk.match(/Disk UUID:\s+(.+)/)
if (devMatch) {
fileSystemInfo.volumeInfo.push({
device: devMatch[1],
volumeName: volMatch ? volMatch[1] : 'N/A',
filesystem: fsMatch ? fsMatch[1] : 'N/A',
serialNumber: serialMatch ? serialMatch[1] : 'N/A'
})
}
})
} catch (error) {
console.error('Error getting volume info:', error)
}
// 获取inode信息macOS
try {
const { stdout } = await execPromise('df -i')
fileSystemInfo.inodeInfo = stdout.trim().split('\n').slice(1).map(line => {
const parts = line.trim().split(/\s+/)
if (parts.length >= 6) {
return {
device: parts[0],
totalInodes: parts[1],
usedInodes: parts[2],
freeInodes: parts[3],
usePercent: parts[4],
mountedOn: parts[5]
}
}
return null
}).filter(item => item)
} catch (error) {
console.error('Error getting inode info:', error)
}
// 获取磁盘健康状态macOS
try {
const { stdout } = await execPromise('diskutil smartStatus -all 2>/dev/null || echo "N/A"')
if (stdout && stdout !== 'N/A') {
fileSystemInfo.diskHealth = stdout.trim()
}
} catch (error) {
console.log('SMART status not available')
}
} catch (error) {
console.error('Error getting file system info:', error)
fileSystemInfo.error = 'Error getting file system info'
}
}
return JSON.stringify(fileSystemInfo, null, 2)
} catch (error) {
console.error('Error getting file system info:', error)
return JSON.stringify({ error: error.message }, null, 2)
}
},
{
name: "get_system_file_info",
description: `获取系统硬盘分区和文件系统信息包括分区信息、卷标、序列号、磁盘健康状态、inode信息等`,
schema: z.object({})
}
)