Files
cnb/agent/npc.ts

116 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { app } from './index.ts';
import { parse } from '@kevisual/router/src/commander.ts';
import { useIssueEnv, useCommentEnv, useRepoInfoEnv, IssueLabel } from '../src/index.ts'
import { pick } from 'es-toolkit';
import z from 'zod';
const writeToProcess = (message: string) => {
if (process.send) {
process.send(message);
} else {
console.log(message);
}
}
const getIssuesLabels = async () => {
const issueEnv = useIssueEnv();
const repoInfoEnv = useRepoInfoEnv();
const issueId = issueEnv.issueId;
const repoSlug = repoInfoEnv.repoSlug;
if (!issueId || !repoSlug) {
return [];
}
const res = await app.run({
path: 'cnb',
key: 'getIssue',
payload: {
repo: repoSlug,
issueNumber: issueId
}
});
if (res.code === 200) {
const issueData = res.data as any;
const labels = issueData.labels || [];
return labels as IssueLabel[];
}
console.error('获取 Issue 详情失败', res);
return []
}
const main = async ({ exit }: { exit: (code: number) => void }) => {
const repoInfoEnv = useRepoInfoEnv();
const commentEnv = useCommentEnv();
const issueEnv = useIssueEnv();
const pickCommentEnv = pick(commentEnv, ['commentId', 'commentIdLabel']);
const pickIssueEnv = pick(issueEnv, ['issueId', 'issueIdLabel', 'issueIid', 'issueIidLabel', 'issueTitle', 'issueTitleLabel', 'issueDescription', 'issueDescriptionLabel']);
const pickRepoInfoEnv = pick(repoInfoEnv, ['repoId', 'repoIdLabel', 'repoName', 'repoNameLabel', 'repoSlug', 'repoSlugLabel']);
// const issueLabels = issueEnv.issueLabels || [];
const isComment = !!commentEnv.commentId;
const envList = [
...Object.entries(pickRepoInfoEnv).map(([key, value]) => `${key}: ${value}`),
...Object.entries(issueEnv).map(([key, value]) => `${key}: ${value}`),
...Object.entries(pickCommentEnv).map(([key, value]) => `${key}: ${value}`),
]
writeToProcess('当前环境变量:');
const issueLabels = await getIssuesLabels();
const issueLabelsNames = issueLabels.map(label => label.name) || [];
envList.forEach(item => writeToProcess(item));
if (!isComment && !issueLabelsNames.includes('Run')) {
writeToProcess('当前 Issue 不包含 Run 标签,跳过执行');
return exit(0);
}
const messages = [
{
role: 'system',
content: `你是一个智能的代码助手, 根据用户提供的上下文信息,提供有用的建议和帮助, 如果用户的要求和执行工具不一致请说出你不能这么做。并把最后的结果提交一个评论到对应的issue中,提交的内容必须不能包含 @ 提及。用户提供的上下文信息如下:`
},
{
role: 'system',
content: `相关变量:${JSON.stringify({ ...pickCommentEnv, ...pickIssueEnv, ...pickRepoInfoEnv })}`
}, {
role: 'user',
content: commentEnv.commentBody || pickIssueEnv.issueDescription || '无'
}
]
writeToProcess('输入消息:');
writeToProcess(JSON.stringify(messages, null, 2));
const result = await app.run({
path: 'cnb',
key: 'chat',
payload: {
messages
}
}, { appId: app.appId })
if (result.code === 200) {
let _message = result.data.message || []
writeToProcess('执行完成')
writeToProcess(JSON.stringify(_message, null, 2))
exit(0);
} else {
writeToProcess(result.message || '执行错误')
exit(1);
}
}
app.route({
path: 'cnb',
key: 'npc',
description: 'CNB智能助手,提供智能建议和帮助, 程序入口',
metadata: {
tags: ['notInNpcAgent'],
args: {
needExit: z.boolean().optional().describe('是否需要在执行完成后退出进程')
}
}
}).define(async (ctx) => {
const exit = (code: number) => {
if (ctx.args.needExit) {
process.exit(code);
}
}
await main({ exit });
}).addTo(app)
parse({ app: app, description: 'CNB控制台命令行工具', parse: true })