Files
cnb/agent/routes/workspace/keep.ts
abearxiong 841ed6ffa7 feat(cnb-board): add cnb-dev-env routes and related functionalities
- Implemented routes for cnb-board to fetch live environment configurations, repository info, build info, pull request info, NPC info, and comment info.
- Created a utility function to execute shell commands.
- Added a check to determine if the environment is a CNB environment.
- Introduced a method to retrieve live markdown content with detailed service access information.
- Enhanced system information retrieval with CPU, memory, and disk usage metrics.
- Established a module structure for better organization of cnb-board related functionalities.
2026-03-06 02:26:13 +08:00

98 lines
3.5 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 { tool } from '@kevisual/router';
import { app, cnb } from '../../app.ts';
import { addKeepAliveData, KeepAliveData, removeKeepAliveData, createLiveData } from '../../../src/workspace/keep-file-live.ts';
import { useKey } from '@kevisual/context';
// 保持工作空间存活技能
app.route({
path: 'cnb',
key: 'keep-workspace-alive',
description: '保持工作空间存活技能参数repo:代码仓库路径,例如 user/repopipelineId:流水线ID例如 cnb-708-1ji9sog7o-001',
middleware: ['admin-auth'],
metadata: {
tags: [],
...({
args: {
repo: tool.schema.string().describe('代码仓库路径,例如 user/repo'),
pipelineId: tool.schema.string().describe('流水线ID例如 cnb-708-1ji9sog7o-001'),
}
})
}
}).define(async (ctx) => {
const repo = ctx.query?.repo as string;
const pipelineId = ctx.query?.pipelineId as string;
if (!repo || !pipelineId) {
ctx.throw(400, '缺少参数 repo 或 pipelineId');
}
const validCookie = await cnb.user.checkCookieValid()
if (validCookie.code !== 200) {
ctx.throw(401, 'CNB_COOKIE 环境变量无效或已过期请重新登录获取新的cookie');
}
const res = await cnb.workspace.getWorkspaceCookie(repo, pipelineId);
let wsUrl = `wss://${pipelineId}.cnb.space:443?skipWebSocketFrames=false`;
let cookie = '';
if (res.code === 200) {
cookie = res.data.value;
console.log(`启动保持工作空间 ${wsUrl} 存活的任务`);
} else {
ctx.throw(500, `获取工作空间访问cookie失败: ${res.message}`);
}
console.log(`启动保持工作空间 ${wsUrl} 存活的任务`);
const config: KeepAliveData = createLiveData({ cookie, repo, pipelineId });
addKeepAliveData(config);
ctx.body = { content: `已启动保持工作空间 ${wsUrl} 存活的任务`, data: config };
}).addTo(app);
// 停止保持工作空间存活技能
app.route({
path: 'cnb',
key: 'stop-keep-workspace-alive',
description: '停止保持工作空间存活技能, 参数repo:代码仓库路径,例如 user/repopipelineId:流水线ID例如 cnb-708-1ji9sog7o-001',
middleware: ['admin-auth'],
metadata: {
tags: [],
...({
args: {
repo: tool.schema.string().describe('代码仓库路径,例如 user/repo'),
pipelineId: tool.schema.string().describe('流水线ID例如 cnb-708-1ji9sog7o-001'),
}
})
}
}).define(async (ctx) => {
const repo = ctx.query?.repo as string;
const pipelineId = ctx.query?.pipelineId as string;
if (!repo || !pipelineId) {
ctx.throw(400, '缺少参数 repo 或 pipelineId');
}
removeKeepAliveData(repo, pipelineId);
ctx.body = { content: `已停止保持工作空间 ${repo}/${pipelineId} 存活的任务` };
}).addTo(app);
app.route({
path: 'cnb',
key: 'keep-alive-current-workspace',
description: '保持当前工作空间存活技能',
middleware: ['admin-auth'],
metadata: {
tags: ['opencode'],
skill: 'keep-alive-current-workspace',
title: '保持当前工作空间存活',
summary: '保持当前工作空间存活,防止被关闭或释放资源',
}
}).define(async (ctx) => {
const pipelineId = useKey('CNB_PIPELINE_ID');
const repo = useKey('CNB_REPO_SLUG_LOWERCASE');
if (!pipelineId || !repo) {
ctx.throw(400, '当前环境缺少 CNB_PIPELINE_ID 或 CNB_REPO_SLUG_LOWERCASE 环境变量,无法保持工作空间存活');
}
const res = await app.run({ path: 'cnb', key: 'keep-workspace-alive', payload: { repo, pipelineId } }, ctx);
ctx.forward(res);
}).addTo(app);