diff --git a/README.md b/README.md index 235a72b..89116f2 100755 --- a/README.md +++ b/README.md @@ -4,4 +4,6 @@ ## 自动识别并修复指令 -目前支持 `Win` +目前支持 `Win、Mac` + +![](./image/gpt-cli-fix.gif) diff --git a/image/gpt-cli-fix.gif b/image/gpt-cli-fix.gif new file mode 100644 index 0000000..1256c89 Binary files /dev/null and b/image/gpt-cli-fix.gif differ diff --git a/package.json b/package.json index d2a0abb..a53d318 100755 --- a/package.json +++ b/package.json @@ -54,7 +54,8 @@ "consola": "^3.2.3", "execa": "^8.0.1", "inquirer": "^9.1.4", - "ora": "^7.0.1" + "ora": "^7.0.1", + "shell-history": "^2.0.0" }, "devDependencies": { "@antfu/eslint-config": "^0.40.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 79efbed..36f623b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,6 +28,9 @@ dependencies: ora: specifier: ^7.0.1 version: 7.0.1 + shell-history: + specifier: ^2.0.0 + version: 2.0.0 devDependencies: '@antfu/eslint-config': @@ -2948,6 +2951,11 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + /shell-history@2.0.0: + resolution: {integrity: sha512-gk7ORkNTLZHmxD6K6vcyijxmYwlI2vVr8clvgKFqazHQKMI9wBXrze4u4af0PQ1uY86XB6JT8WKcmiVGW93KUQ==} + engines: {node: '>=12'} + dev: false + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} diff --git a/src/command/index.ts b/src/command/index.ts index c9a3902..7405cbc 100644 --- a/src/command/index.ts +++ b/src/command/index.ts @@ -1,6 +1,13 @@ /* eslint-disable no-console */ +import { platform } from 'node:os' +import { readFileSync } from 'node:fs' import { printColorLogs, printErrorLogs, scanDirFile } from '@winches/utils' import { consola } from 'consola' +import { oraPromise } from 'ora' + +// @ts-expect-error 包不存在类型声明 +import { shellHistory } from 'shell-history' + import { getIsExecuteSelect, getQuestion, getReloadSelect } from '../inquirer' import { fetchQuestion } from '../utils' import { normalizeDesc, normalizeOutput } from '../utils/log' @@ -8,10 +15,7 @@ import { convertCmd } from '../utils/transform' import { exec, execFn } from '../utils/execa' import { readEnv, writeEnv } from '../utils/env' import type { AnswerArr } from '../types' -import { platform } from 'os' import { excludeList } from '../const' -import { readFileSync } from 'fs' -import { oraPromise } from 'ora' const defaultBanner = '欢迎使用 cli-gpt 智能终端应用' const gradientBanner = printColorLogs(defaultBanner) @@ -38,33 +42,47 @@ export async function start(question?: ({} & string) | 'fix') { // 执行修复功能 if (question === 'fix') { - // 验证是否有PowerShell记录 - if (isWin && !powerShellHistory) { - powerShellHistory = scanDirFile('C:/Users', ['.txt'], excludeList).filter(item => item.includes('ConsoleHost_history'))?.[0] + let errorInfo = '' + if (isWin) { + // 验证是否有PowerShell记录 if (!powerShellHistory) { - printErrorLogs('无法找到终端历史记录文件') - process.exit(1) + powerShellHistory = scanDirFile('C:/Users', ['.txt'], excludeList).filter(item => item.includes('ConsoleHost_history'))?.[0] + + if (!powerShellHistory) { + printErrorLogs('无法找到终端历史记录文件') + process.exit(1) + } + + // 写入env + writeEnv({ + powerShellHistory, + }) } - // 写入env - writeEnv({ - powerShellHistory - }) - } + const historyList = readFileSync(powerShellHistory, 'utf8').split('\n').filter(i => i) + const lastHistory = historyList[historyList.length - 2] + const transformHistory = lastHistory.replace(/\r/g, '') - const historyList = readFileSync(powerShellHistory, 'utf8').split('\n').filter(i => i) - const lastHistory = historyList[historyList.length - 2] - const transformHistory = lastHistory.replace(/\r/g, '') - let errorInfo = '' + await runCmd(transformHistory) - await runCmd(transformHistory) + await fetchQuestion(question, [transformHistory, errorInfo]) + process.exit(0) + } + else { + // mac + const historyList = shellHistory() + const lastHistory = historyList[historyList.length - 2] + const transformHistory = lastHistory.replace(/\r/g, '') - await fetchAnswer(question, [transformHistory, errorInfo]) - process.exit(1) + await runCmd(transformHistory) + + await generateAnswer(question, [transformHistory, errorInfo]) + process.exit(0) + } async function runCmd(cmd: string) { - return new Promise(resolve => { + return new Promise((resolve) => { execFn(cmd, (err: any, stdout: string) => { errorInfo = `Error: ${err?.message}\n${stdout || ''}` resolve(true) @@ -123,7 +141,7 @@ export async function start(question?: ({} & string) | 'fix') { for (const cmd of cmdList) { await oraPromise(exec(cmd), { text: `正在运行 ${cmd}...`, - successText: `✨ ${cmd} 运行成功!` + successText: `✨ ${cmd} 运行成功!`, }) } } diff --git a/src/utils/fetch.ts b/src/utils/fetch.ts index 8a52a25..ace6ea2 100644 --- a/src/utils/fetch.ts +++ b/src/utils/fetch.ts @@ -103,12 +103,21 @@ export async function fetchQuestion(question: string, errorInfo: string[] = []) const isError = !!errorInfo.length const [cmd, info] = errorInfo - const errorPrompt = `运行\`${cmd}\`指令的时候报错了,我要怎么修复它,下面三个反引号圈起来的是错误信息,你可以根据错误信息思考出对应的解决办法。 + const errorPrompt = `运行\`${cmd}\`指令的时候报错了,我要怎么修复它,下面三个反引号圈起来的是错误信息,你可以根据错误信息思考出对应的解决办法,并且按照之前要求的JSON格式回复。 错误信息: \`\`\` ${info} - \`\`\`` + \`\`\` + + 回答直接输出JSON类型,若有其他可能,也放到一个数组里输出: + [ + { + execute: true, + desc: '示例的描述', + cmd: 'git branch' + } + ]` const res = await oraPromise(_cmdRunner.cmdRunner(isError ? errorPrompt : question), { text: isError ? `正在分析错误(${cmd})...` : question, @@ -116,7 +125,7 @@ export async function fetchQuestion(question: string, errorInfo: string[] = []) try { const text = res.text - const matchReg = /\[.*\]/ms + const matchReg = /\[.*?\]/ms const matchJson = text.match(matchReg)?.[0] if (!matchJson) {