This commit is contained in:
2026-03-11 16:53:01 +08:00
parent 460979b577
commit a551cbe79d
4 changed files with 49 additions and 21 deletions

View File

@@ -8,6 +8,18 @@ include:
imports: imports:
- https://cnb.cool/kevisual/env/-/blob/main/.env.development - https://cnb.cool/kevisual/env/-/blob/main/.env.development
.npc: &npc
- docker:
image: docker.cnb.cool/kevisual/dev-env/bun:latest
services:
- docker
env: !reference [.common_env, env]
imports: !reference [.common_env, imports]
stages:
- name: "task"
script: |
bun install
bun run agent/npc.ts
$: $:
vscode: vscode:
- docker: - docker:
@@ -18,15 +30,6 @@ $:
env: !reference [.common_env, env] env: !reference [.common_env, env]
imports: !reference [.common_env, imports] imports: !reference [.common_env, imports]
issue.comment@npc: issue.comment@npc: *npc
- docker: issue.open@npc: *npc
image: docker.cnb.cool/kevisual/dev-env/bun:latest issue.reopen@npc: *npc
services:
- docker
env: !reference [.common_env, env]
imports: !reference [.common_env, imports]
stages:
- name: "task"
script: |
bun install
bun run agent/npc.ts

View File

@@ -3,6 +3,13 @@ import { app } from './index.ts';
import { useIssueEnv, useCommentEnv, useRepoInfoEnv } from '../src/index.ts' import { useIssueEnv, useCommentEnv, useRepoInfoEnv } from '../src/index.ts'
import { pick } from 'es-toolkit'; import { pick } from 'es-toolkit';
const writeToProcess = (message: string) => {
if (process.send) {
process.send(message);
} else {
console.log(message);
}
}
const main = async () => { const main = async () => {
const repoInfoEnv = useRepoInfoEnv(); const repoInfoEnv = useRepoInfoEnv();
const commentEnv = useCommentEnv(); const commentEnv = useCommentEnv();
@@ -10,10 +17,17 @@ const main = async () => {
const pickCommentEnv = pick(commentEnv, ['commentId', 'commentIdLabel']); const pickCommentEnv = pick(commentEnv, ['commentId', 'commentIdLabel']);
const pickIssueEnv = pick(issueEnv, ['issueId', 'issueIdLabel', 'issueIid', 'issueIidLabel', 'issueTitle', 'issueTitleLabel', 'issueDescription', 'issueDescriptionLabel']); const pickIssueEnv = pick(issueEnv, ['issueId', 'issueIdLabel', 'issueIid', 'issueIidLabel', 'issueTitle', 'issueTitleLabel', 'issueDescription', 'issueDescriptionLabel']);
const pickRepoInfoEnv = pick(repoInfoEnv, ['repoId', 'repoIdLabel', 'repoName', 'repoNameLabel', 'repoSlug', 'repoSlugLabel']); const pickRepoInfoEnv = pick(repoInfoEnv, ['repoId', 'repoIdLabel', 'repoName', 'repoNameLabel', 'repoSlug', 'repoSlugLabel']);
const issueLabels = issueEnv.issueLabels || [];
const isComment = !!commentEnv.commentId;
if (!isComment && !issueLabels.includes('Run')) {
writeToProcess('当前 Issue 不包含 Run 标签,跳过执行');
process.exit(0);
}
const messages = [ const messages = [
{ {
role: 'system', role: 'system',
content: `你是一个智能的代码助手, 根据用户提供的上下文信息,提供有用的建议和帮助, 如果用户的要求和执行工具不一致请说出你不能这么做。并把最后的结果提交一个评论到对应的issue中。用户提供的上下文信息如下` content: `你是一个智能的代码助手, 根据用户提供的上下文信息,提供有用的建议和帮助, 如果用户的要求和执行工具不一致请说出你不能这么做。并把最后的结果提交一个评论到对应的issue中,提交的内容必须不能包含 @ 提及。用户提供的上下文信息如下:`
}, },
{ {
role: 'system', role: 'system',
@@ -33,10 +47,11 @@ const main = async () => {
}, { appId: app.appId }) }, { appId: app.appId })
if (result.code === 200) { if (result.code === 200) {
let _message = result.data.message || [] let _message = result.data.message || []
console.log('执行完成', JSON.stringify(_message, null, 2)) writeToProcess('执行完成')
writeToProcess(JSON.stringify(_message, null, 2))
process.exit(0) process.exit(0)
} else { } else {
console.log(result.message || '执行错误') writeToProcess(result.message || '执行错误')
process.exit(1) process.exit(1)
} }
} }

View File

@@ -59,6 +59,7 @@ app.route({
repo: tool.schema.string().optional().describe('代码仓库名称, 如 my-user/my-repo'), repo: tool.schema.string().optional().describe('代码仓库名称, 如 my-user/my-repo'),
issueNumber: tool.schema.number().describe('Issue 编号'), issueNumber: tool.schema.number().describe('Issue 编号'),
body: tool.schema.string().describe('评论内容'), body: tool.schema.string().describe('评论内容'),
clearAt: tool.schema.boolean().optional().describe('是否清除评论内容中的 @ 提及,默认: true'),
}, },
summary: '创建 Issue 评论', summary: '创建 Issue 评论',
}) })
@@ -67,7 +68,8 @@ app.route({
const cnb = await cnbManager.getContext(ctx); const cnb = await cnbManager.getContext(ctx);
let repo = ctx.query?.repo || useKey('CNB_REPO_SLUG_LOWERCASE'); let repo = ctx.query?.repo || useKey('CNB_REPO_SLUG_LOWERCASE');
const issueNumber = ctx.query?.issueNumber; const issueNumber = ctx.query?.issueNumber;
const body = ctx.query?.body; let body = ctx.query?.body;
const clearAt = ctx.query?.clearAt ?? true;
if (!repo) { if (!repo) {
ctx.throw(400, '缺少参数 repo'); ctx.throw(400, '缺少参数 repo');
@@ -78,6 +80,10 @@ app.route({
if (!body) { if (!body) {
ctx.throw(400, '缺少参数 body'); ctx.throw(400, '缺少参数 body');
} }
if (clearAt && body) {
// 清除评论内容中的 @ 提及
body = body.replace(/@/g, '');
}
const res = await cnb.issue.createComment(repo, issueNumber, body); const res = await cnb.issue.createComment(repo, issueNumber, body);
ctx.forward(res); ctx.forward(res);
@@ -138,6 +144,7 @@ app.route({
issueNumber: tool.schema.number().describe('Issue 编号'), issueNumber: tool.schema.number().describe('Issue 编号'),
commentId: tool.schema.number().describe('评论 ID'), commentId: tool.schema.number().describe('评论 ID'),
body: tool.schema.string().describe('评论内容'), body: tool.schema.string().describe('评论内容'),
clearAt: tool.schema.boolean().optional().describe('是否清除评论内容中的 @ 提及,默认: true'),
}, },
summary: '修改 Issue 评论', summary: '修改 Issue 评论',
}) })
@@ -147,8 +154,8 @@ app.route({
let repo = ctx.query?.repo || useKey('CNB_REPO_SLUG_LOWERCASE'); let repo = ctx.query?.repo || useKey('CNB_REPO_SLUG_LOWERCASE');
const issueNumber = ctx.query?.issueNumber; const issueNumber = ctx.query?.issueNumber;
const commentId = ctx.query?.commentId; const commentId = ctx.query?.commentId;
const body = ctx.query?.body; let body = ctx.query?.body;
const clearAt = ctx.query?.clearAt ?? true;
if (!repo) { if (!repo) {
ctx.throw(400, '缺少参数 repo'); ctx.throw(400, '缺少参数 repo');
} }
@@ -161,7 +168,10 @@ app.route({
if (!body) { if (!body) {
ctx.throw(400, '缺少参数 body'); ctx.throw(400, '缺少参数 body');
} }
if (clearAt && body) {
// 清除评论内容中的 @ 提及
body = body.replace(/@/g, '');
}
const res = await cnb.issue.updateComment(repo, issueNumber, commentId, body); const res = await cnb.issue.updateComment(repo, issueNumber, commentId, body);
ctx.forward(res); ctx.forward(res);
}).addTo(app); }).addTo(app);

View File

@@ -182,10 +182,10 @@ export const useIssueEnv = () => {
issueAssigneesLabel: "Issue 处理人列表", issueAssigneesLabel: "Issue 处理人列表",
/** /**
* @key CNB_ISSUE_LABELS * @key CNB_ISSUE_LABELS
* @description:Issue 标签列表 * @description:Issue 标签列表, 多个以 , 分隔。
*/ */
issueLabels, issueLabels,
issueLabelsLabel: "Issue 标签列表", issueLabelsLabel: "Issue 标签列表, 多个以 , 分隔。",
/** /**
* @key CNB_ISSUE_PRIORITY * @key CNB_ISSUE_PRIORITY
* @description:Issue 优先级 * @description:Issue 优先级