169 lines
5.3 KiB
TypeScript
169 lines
5.3 KiB
TypeScript
import { createSkill, tool } from '@kevisual/router';
|
||
import { app, cnb } from '../../app.ts';
|
||
import z from 'zod';
|
||
import './skills.ts';
|
||
import './keep.ts';
|
||
|
||
// 启动工作空间
|
||
app.route({
|
||
path: 'cnb',
|
||
key: 'start-workspace',
|
||
description: '启动开发工作空间, 参数 repo',
|
||
middleware: ['auth'],
|
||
metadata: {
|
||
tags: ['opencode'],
|
||
...createSkill({
|
||
skill: 'start-workspace',
|
||
title: '启动cnb工作空间',
|
||
summary: '启动cnb工作空间',
|
||
args: {
|
||
repo: tool.schema.string().describe('代码仓库路径,例如 user/repo'),
|
||
branch: tool.schema.string().optional().describe('分支名称,默认主分支'),
|
||
ref: tool.schema.string().optional().describe('提交引用,例如 commit sha'),
|
||
},
|
||
})
|
||
}
|
||
}).define(async (ctx) => {
|
||
const repo = ctx.query?.repo;
|
||
const branch = ctx.query?.branch;
|
||
const ref = ctx.query?.ref;
|
||
if (!repo) {
|
||
ctx.throw(400, '缺少参数 repo');
|
||
}
|
||
const res = await cnb.workspace.startWorkspace(repo, {
|
||
branch,
|
||
ref
|
||
});
|
||
ctx.forward(res);
|
||
}).addTo(app);
|
||
|
||
// 获取cnb工作空间列表
|
||
app.route({
|
||
path: 'cnb',
|
||
key: 'list-workspace',
|
||
description: '获取cnb开发工作空间列表,可选参数 status=running 获取运行中的环境',
|
||
middleware: ['auth'],
|
||
metadata: {
|
||
tags: ['opencode'],
|
||
...createSkill({
|
||
skill: 'list-workspace',
|
||
title: '列出cnb工作空间',
|
||
summary: '列出cnb工作空间列表,支持按状态过滤, status 可选值 running 或 closed',
|
||
args: {
|
||
status: tool.schema.string().optional().describe('开发环境状态,running: 运行中,closed: 已关闭和停止的'),
|
||
page: tool.schema.number().optional().describe('分页页码,默认 1'),
|
||
pageSize: tool.schema.number().optional().describe('分页大小,默认 20,最大 100'),
|
||
slug: tool.schema.string().optional().describe('仓库路径,例如 groupname/reponame'),
|
||
branch: tool.schema.string().optional().describe('分支名称'),
|
||
},
|
||
})
|
||
}
|
||
}).define(async (ctx) => {
|
||
const { status = 'running', page, pageSize, slug, branch } = ctx.query || {};
|
||
const res = await cnb.workspace.list({
|
||
status: status as 'running' | 'closed' | undefined,
|
||
page: page ?? 1,
|
||
pageSize: pageSize ?? 100,
|
||
});
|
||
ctx.forward({ code: 200, message: 'success', data: res });
|
||
}).addTo(app);
|
||
|
||
// 获取工作空间详情
|
||
app.route({
|
||
path: 'cnb',
|
||
key: 'get-workspace',
|
||
description: '获取工作空间详情,通过 repo 和 sn 获取',
|
||
middleware: ['auth'],
|
||
metadata: {
|
||
tags: ['opencode'],
|
||
...createSkill({
|
||
skill: 'get-workspace',
|
||
title: '获取工作空间详情',
|
||
summary: '获取工作空间详细信息',
|
||
args: {
|
||
repo: tool.schema.string().describe('代码仓库路径,例如 user/repo'),
|
||
sn: tool.schema.string().describe('工作空间流水线的 sn'),
|
||
},
|
||
})
|
||
}
|
||
}).define(async (ctx) => {
|
||
const repo = ctx.query?.repo;
|
||
const sn = ctx.query?.sn;
|
||
if (!repo) {
|
||
ctx.throw(400, '缺少参数 repo');
|
||
}
|
||
if (!sn) {
|
||
ctx.throw(400, '缺少参数 sn');
|
||
}
|
||
const res = await cnb.workspace.getDetail(repo, sn);
|
||
ctx.forward({ code: 200, message: 'success', data: res });
|
||
}).addTo(app);
|
||
|
||
// 删除工作空间
|
||
app.route({
|
||
path: 'cnb',
|
||
key: 'delete-workspace',
|
||
description: '删除工作空间,通过 pipelineId 或 sn',
|
||
middleware: ['auth'],
|
||
metadata: {
|
||
tags: ['opencode'],
|
||
...createSkill({
|
||
skill: 'delete-workspace',
|
||
title: '删除工作空间',
|
||
summary: '删除工作空间,pipelineId 和 sn 二选一',
|
||
args: {
|
||
pipelineId: tool.schema.string().optional().describe('流水线 ID,优先使用'),
|
||
sn: tool.schema.string().optional().describe('流水线构建号'),
|
||
sns: tool.schema.array(z.string()).optional().describe('批量流水线构建号'),
|
||
},
|
||
})
|
||
}
|
||
}).define(async (ctx) => {
|
||
const pipelineId = ctx.query?.pipelineId;
|
||
const sn = ctx.query?.sn;
|
||
const sns = ctx.query?.sns;
|
||
if (!pipelineId && !sn && (!sns || sns.length === 0)) {
|
||
ctx.throw(400, 'pipelineId 和 sn 必须提供其中一个');
|
||
}
|
||
if (sns && sns.length > 0) {
|
||
const results = [];
|
||
for (const snItem of sns) {
|
||
const res = await cnb.workspace.deleteWorkspace({ sn: snItem });
|
||
results.push(res);
|
||
}
|
||
ctx.forward({ code: 200, message: 'success', data: results });
|
||
return;
|
||
}
|
||
const res = await cnb.workspace.deleteWorkspace({ pipelineId, sn });
|
||
ctx.forward(res);
|
||
}).addTo(app);
|
||
|
||
// 停止工作空间
|
||
app.route({
|
||
path: 'cnb',
|
||
key: 'stop-workspace',
|
||
description: '停止工作空间,通过 pipelineId 或 sn',
|
||
middleware: ['auth'],
|
||
metadata: {
|
||
tags: ['opencode'],
|
||
...createSkill({
|
||
skill: 'stop-workspace',
|
||
title: '停止工作空间',
|
||
summary: '停止运行中的工作空间',
|
||
args: {
|
||
pipelineId: tool.schema.string().optional().describe('流水线 ID,优先使用'),
|
||
sn: tool.schema.string().optional().describe('流水线构建号'),
|
||
},
|
||
})
|
||
}
|
||
}).define(async (ctx) => {
|
||
const pipelineId = ctx.query?.pipelineId;
|
||
const sn = ctx.query?.sn;
|
||
if (!pipelineId && !sn) {
|
||
ctx.throw(400, 'pipelineId 和 sn 必须提供其中一个');
|
||
}
|
||
const res = await cnb.workspace.stopWorkspace({ pipelineId, sn });
|
||
ctx.forward({ code: 200, message: 'success', data: res });
|
||
}).addTo(app);
|
||
|