Update show env

This commit is contained in:
nguyentrungthat 2026-01-21 13:23:41 +07:00
parent 638a19e314
commit b9fde3c5e7
5 changed files with 99 additions and 21 deletions

View File

@ -494,7 +494,7 @@ export default class LineConnection {
const data = textfsmResults(logScenarios, '')
let pid = this.config.inventory?.pid || ''
try {
data.forEach((item) => {
for (const item of data) {
if (item?.textfsm && isValidJson(item?.textfsm)) {
if (
['show inventory', 'sh inventory', 'show inv', 'sh inv'].includes(item.command)
@ -521,9 +521,16 @@ export default class LineConnection {
? { ...this.config.inventory, ...dataVer }
: dataVer
}
if (
item.command?.trim()?.includes('show env') ||
item.command?.trim()?.includes('sh env')
) {
const dataEnv = await this.detectShowEnvWithAI(item.output)
item.dataAI = dataEnv
}
item.textfsm = JSON.parse(item.textfsm)
}
})
}
const scenario = await detectScenarioByModel(pid, this.listScenarios)
console.log(pid, scenario?.title, this.listScenarios)
if (
@ -1522,4 +1529,66 @@ export default class LineConnection {
await this.runScript(script as any, userName)
await this.sendEmailLoadLicense(licenseFileName, startTime)
}
/**
* Detect log by call api gpt, return string[]
*/
async detectShowEnvWithAI(log: string) {
try {
const payload = {
model: 'gpt-4o-mini',
max_tokens: 1000,
messages: [
{
role: 'user',
content: `You are a network log parser.
Input is the raw output of Cisco "show environment" or "show environment all".
Your task:
- Focus ONLY on FAN and POWER related information.
- Ignore TEMPERATURE, VOLTAGE, and other sensors unless they relate to FAN or POWER.
- Extract each FAN or POWER component and its state.
- Normalize each item into the format:
"<NAME>: <STATE>"
Examples:
- "FAN is OK" -> "FAN: OK"
- "FAN 2 is FAILED" -> "FAN 2: FAILED"
- "POWER SUPPLY A is NOT PRESENT" -> "POWER SUPPLY A: NOT PRESENT"
- "PSU 1 Absent" -> "PSU 1: ABSENT"
Output requirements:
- Return ONLY a valid JSON array of strings.
- Do NOT include any explanation or extra text.
- Do NOT include code block.
- JSON must be directly parsable.
Here is the input log:
${log}
`,
},
],
}
const remoteUrl = process.env.ERP_URL || 'https://stage.nswteam.net'
const remoteResp = await axios.post(
remoteUrl + '/api/transferPostData',
{
urlAPI: '/api/open-ai-sfp/model-image-info',
data: payload,
},
{
headers: {
Authorization: 'Bearer ' + process.env.ERP_TOKEN,
},
}
)
return remoteResp.data?.Status === 'OK' ? remoteResp.data?.data : ''
} catch (error: any) {
console.log('[ERROR] Detect log show env from AI', error)
}
return ''
}
}

View File

@ -56,6 +56,7 @@ export const textfsmResults = (logContent: string, cmd: string) => {
command: cmd,
output: logContent,
textfsm: JSON.stringify(structuredOutput).replace(/[\x00-\x1f\x7f-\x9f]/g, ''),
dataAI: [],
},
]
} else {
@ -101,6 +102,7 @@ export const textfsmResults = (logContent: string, cmd: string) => {
command,
output,
textfsm: JSON.stringify(structuredOutput).replace(/[\x00-\x1f\x7f-\x9f]/g, ''), // Clean special characters
dataAI: [],
}
})
.filter((el) => el.command)

View File

@ -42,14 +42,15 @@ const parseShowEnvironment = (data: string) => {
for (const p of patterns) {
const m = XRegExp.exec(line, p)
if (m?.groups) {
const record: any = {
TYPE: m.groups.TYPE?.trim() || '',
NAME: m.groups.NAME?.trim() || '',
LOCATION: m.groups.LOCATION?.trim() || '',
STATE: m.groups.STATE?.trim() || '',
VALUE: m.groups.VALUE?.trim() || '',
RAW: line,
}
// const record: any = {
// TYPE: m.groups.TYPE?.trim() || '',
// NAME: m.groups.NAME?.trim() || '',
// LOCATION: m.groups.LOCATION?.trim() || '',
// STATE: m.groups.STATE?.trim() || '',
// VALUE: m.groups.VALUE?.trim() || '',
// RAW: line,
// }
const record: any = line // Lưu nguyên dòng
records.push(record)
break

View File

@ -479,8 +479,11 @@ const ModalTerminal = ({
d.command?.trim()?.includes("show env") ||
d.command?.trim()?.includes("sh env")
);
console.log("showEnv", showEnv);
return showEnv?.textfsm && Array.isArray(showEnv?.textfsm)
return showEnv?.dataAI &&
Array.isArray(showEnv?.dataAI) &&
showEnv?.dataAI?.length > 0
? showEnv?.dataAI
: showEnv?.textfsm && Array.isArray(showEnv?.textfsm)
? showEnv?.textfsm
: null;
};
@ -823,7 +826,7 @@ const ModalTerminal = ({
{findDataShowEnv()
? findDataShowEnv()?.map((v: TextTSMEnvironment, i) => (
<Text fz={"14.5px"} key={i}>
- {v.RAW}
- {v}
</Text>
))
: ""}

View File

@ -223,6 +223,7 @@ export type TextFSM = {
command: string;
output: string;
textfsm: any;
dataAI: any;
};
export type TDataTicket = {
@ -255,14 +256,16 @@ export type TextTSMLicense = {
LICENSE_PRIORITY: string;
};
export type TextTSMEnvironment = {
TYPE: string;
NAME: string;
LOCATION: string;
STATE: string;
VALUE: string;
RAW: string;
};
// export type TextTSMEnvironment = {
// TYPE: string;
// NAME: string;
// LOCATION: string;
// STATE: string;
// VALUE: string;
// RAW: string;
// };
export type TextTSMEnvironment = string;
export type TBrands = {
id: number;