-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add @umijs/copilot (still wip) (#10831)
* feat: add @umijs/copilot (still wip) * chore: update pnpm-lock.yaml * chore: code style * Update copilot/bin/umi-copilot.js Co-authored-by: 咲奈Sakina <59400654+fz6m@users.noreply.github.com> --------- Co-authored-by: 咲奈Sakina <59400654+fz6m@users.noreply.github.com>
- Loading branch information
Showing
17 changed files
with
354 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default { | ||
extends: '../.fatherrc.base.ts', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export default { | ||
extends: '../.fatherrc.base.ts', | ||
prebundle: {}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/dist | ||
/node_modules | ||
/fixtures/*/node_modules | ||
/fixtures/tmp | ||
/fixtures/**/*.out.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/usr/bin/env node | ||
|
||
require('../dist/cli').main().catch((e) => { | ||
console.error(e); | ||
process.exit(1); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"name": "@umijs/copilot", | ||
"version": "0.0.0", | ||
"homepage": "https://github.com/umijs/umi/tree/master/copilot", | ||
"bugs": "https://github.com/umijs/umi/issues", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/umijs/umi" | ||
}, | ||
"bin": { | ||
"umi-copilot": "bin/umi-copilot.js" | ||
}, | ||
"files": [ | ||
"bin", | ||
"dist" | ||
], | ||
"scripts": { | ||
"build": "father build", | ||
"dev": "father dev", | ||
"doctor": "father doctor", | ||
"prebundle": "father prebundle", | ||
"release": "father doctor && esno ../scripts/release.ts --pkg copilot", | ||
"test": "jest" | ||
}, | ||
"dependencies": { | ||
"@umijs/utils": "workspace:*", | ||
"zx": "^7.2.1" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"authors": [ | ||
"chencheng <sorrycc@gmail.com> (https://github.com/sorrycc)" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { axios } from '@umijs/utils'; | ||
|
||
interface IMessage { | ||
role: 'system' | 'user' | 'assistant'; | ||
content: string; | ||
} | ||
|
||
interface IChatGPTResponse { | ||
error?: { | ||
type: string; | ||
code: string; | ||
message: string; | ||
}; | ||
created: number; | ||
choices: { | ||
index: number; | ||
message: IMessage; | ||
finish_reason: string; | ||
}[]; | ||
usage: { | ||
prompt_tokens: number; | ||
completion_tokens: number; | ||
total_tokens: number; | ||
}; | ||
} | ||
|
||
const requestParamsBase = { | ||
model: 'gpt-3.5-turbo', | ||
temperature: 0.5, | ||
top_p: 0.8, | ||
presence_penalty: 1.0, | ||
max_tokens: 500, | ||
}; | ||
|
||
function getApiUrl(proxyUrl?: string) { | ||
if (proxyUrl) { | ||
proxyUrl = proxyUrl.replace(/^https?:\/\//, '').replace(/\/$/, ''); | ||
} | ||
return `https://${proxyUrl || 'api.openai.com'}/v1/chat/completions`; | ||
} | ||
|
||
export async function sendMessage(opts: { | ||
messages: IMessage[]; | ||
token: string; | ||
proxyUrl?: string; | ||
controller?: AbortController; | ||
timeout?: number; | ||
}) { | ||
const apiUrl = getApiUrl(opts.proxyUrl); | ||
let res: any = null; | ||
try { | ||
res = await axios.post<IChatGPTResponse>( | ||
apiUrl, | ||
{ | ||
...requestParamsBase, | ||
messages: opts.messages, | ||
stream: false, | ||
}, | ||
{ | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: `Bearer ${opts.token}`, | ||
}, | ||
validateStatus: () => true, | ||
signal: opts.controller?.signal, | ||
timeout: opts.timeout || 20000, | ||
}, | ||
); | ||
} catch (e: any) { | ||
if (opts.controller?.signal.aborted === true) { | ||
// 用户手动取消了请求 | ||
} else { | ||
throw new Error('Network Error'); | ||
} | ||
} | ||
if (res.data.error) { | ||
throw new Error(res.data.error.message); | ||
} | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { chalk, clackPrompts, logger, resolve, yParser } from '@umijs/utils'; | ||
import { sendMessage } from './chatgpt'; | ||
import { SYSTEM_PROMPT } from './constants'; | ||
import { printHelp } from './printHelp'; | ||
const { confirm, spinner } = clackPrompts; | ||
|
||
export async function main() { | ||
logger.info("🚧 It's in beta, please use it carefully."); | ||
const args = yParser(process.argv.slice(2), { | ||
alias: { | ||
help: ['h'], | ||
}, | ||
}); | ||
const cwd = args.cwd || process.cwd(); | ||
|
||
if (args.help) { | ||
printHelp(); | ||
return; | ||
} | ||
|
||
// --token | ||
const token = process.env.OPENAI_API_KEY || args.token; | ||
if (!token) { | ||
throw new Error('Please set OPENAI_API_KEY or --token'); | ||
} | ||
|
||
const message = args._.join(' '); | ||
const s = spinner(); | ||
s.start('🕖 Hold on, asking OpenAI...'); | ||
const res = await sendMessage({ | ||
messages: [ | ||
{ | ||
role: 'system', | ||
content: SYSTEM_PROMPT, | ||
}, | ||
{ | ||
role: 'user', | ||
content: message, | ||
}, | ||
], | ||
token, | ||
// --proxy-url | ||
proxyUrl: args.proxyUrl, | ||
}); | ||
s.stop(); | ||
const command = res.data.choices[0].message.content; | ||
logger.info('The suggested command is:'); | ||
logger.info(chalk.green(command)); | ||
|
||
const shouldRunCommand = await confirm({ | ||
message: `Run the command?`, | ||
}); | ||
// why equals true? | ||
// since if user press ctrl+c, shouldRunCommand will not be falsy | ||
if (shouldRunCommand === true) { | ||
logger.info('✅ Running the command...'); | ||
process.env.FORCE_COLOR = '1'; | ||
const commandPath = await findUmiCommand({ cwd }); | ||
logger.info(`Command Path: ${commandPath}`); | ||
// why split? | ||
// since zx.$ has problem when parsing command with template string | ||
const { $ } = await import('zx'); | ||
await $`${command.replace('umi', commandPath).split(' ')}`; | ||
} | ||
} | ||
|
||
async function findUmiCommand(opts: { cwd: string }) { | ||
let ret; | ||
// max > umi > global max > global umi | ||
if (!ret) ret = resolveSyncSilently('max/bin/max.js', opts.cwd); | ||
if (!ret) ret = resolveSyncSilently('umi/bin/umi.js', opts.cwd); | ||
const { $ } = await import('zx'); | ||
try { | ||
if (!ret) ret = (await $`which max`).stdout.trim(); | ||
} catch (_e) {} | ||
try { | ||
if (!ret) ret = (await $`which umi`).stdout.trim(); | ||
} catch (_e) {} | ||
return ret; | ||
} | ||
|
||
function resolveSyncSilently(path: string, cwd: string) { | ||
try { | ||
return resolve.sync(path, { | ||
basedir: cwd, | ||
}); | ||
} catch (e) { | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// TODO: IMPROVE THIS | ||
export const SYSTEM_PROMPT = ` | ||
Umi 框架有一些命令如下: | ||
umi dev | ||
umi build | ||
umi dev 可以通过 PORT 环境变量指定端口号。 | ||
umi build 可以通过设置 COMPRESS 环境变量为 none 来让构建不进行压缩。 | ||
环境变量的使用方法是在命令之前加入环境变量,如: | ||
PORT=1234 umi dev | ||
COMPRESS=none umi build | ||
基于以上知识,请基于我的要求给出 umi 相关可执行的命令。只给可执行的命令行,不要做任何额外解释。 | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export function printHelp() { | ||
console.log(` | ||
Usage: umi-copilot [message] | ||
Options: | ||
--token OpenAI API key | ||
--proxy-url Proxy URL for OpenAI API | ||
--cwd Working directory | ||
--timeout Timeout for OpenAI API, Default: 20000 | ||
--help Show help | ||
Examples: | ||
$ umi-copilot "I want to" | ||
`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.