feat: add zod dependency and implement kevisual routes for CLI commands
- Added zod as a dependency in package.json. - Enhanced assistant configuration to include skills and plugins directories. - Implemented runCmd function to execute CLI commands in run.ts. - Updated light-code module to use node:child_process. - Created new kevisual routes for checking CLI login status and deploying web pages. - Added restart functionality for OpenCode client in opencode module.
This commit is contained in:
@@ -9,6 +9,7 @@ import './call/index.ts'
|
||||
// import './hot-api/key-sender/index.ts';
|
||||
import './opencode/index.ts';
|
||||
import './remote/index.ts';
|
||||
import './kevisual/index.ts'
|
||||
|
||||
import os from 'node:os';
|
||||
import { authCache } from '@/module/cache/auth.ts';
|
||||
@@ -160,6 +161,7 @@ app
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
// 调用 path: client key: system
|
||||
app
|
||||
.route({
|
||||
path: 'client',
|
||||
|
||||
67
assistant/src/routes/kevisual/auth.ts
Normal file
67
assistant/src/routes/kevisual/auth.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { app } from '@/app.ts'
|
||||
import { runCmd } from '@/module/cmd/run.ts';
|
||||
import { createSkill, tool } from "@kevisual/router";
|
||||
import { useKey } from '@kevisual/use-config';
|
||||
|
||||
// 查看 ev cli 是否登录
|
||||
app.route({
|
||||
path: 'kevisual',
|
||||
key: ' me',
|
||||
description: '查看 ev cli 是否登录',
|
||||
middleware: ['admin-auth'],
|
||||
metadata: {
|
||||
tags: ['opencode'],
|
||||
...createSkill({
|
||||
skill: 'kevisual-me',
|
||||
title: '查看 ev cli 是否登录',
|
||||
summary: '查看 ev cli 是否登录',
|
||||
args: {
|
||||
}
|
||||
})
|
||||
},
|
||||
}).define(async (ctx) => {
|
||||
const cmd = 'ev me';
|
||||
const res = await runCmd({ cmd })
|
||||
if (res.code === 200) {
|
||||
ctx.body = { content: res.data };
|
||||
} else {
|
||||
ctx.throw(500, res.data);
|
||||
}
|
||||
}).addTo(app);
|
||||
|
||||
// 执行工具 kevisual-login-by-admin
|
||||
// 执行工具 通过当前登录用户 ev cl
|
||||
// 调用 path: kevisual key: loginByAdmin
|
||||
app.route({
|
||||
path: 'kevisual',
|
||||
key: 'loginByAdmin',
|
||||
description: '通过当前登录用户 ev cli',
|
||||
middleware: ['admin-auth'],
|
||||
metadata: {
|
||||
tags: ['opencode'],
|
||||
...createSkill({
|
||||
skill: 'kevisual-login-by-admin',
|
||||
title: '通过当前登录用户 ev cli',
|
||||
summary: '通过当前登录用户登录 ev cli, 直接用当前的用户的 token 直接设置 token 给 ev cli, 登录失败直接停止任务',
|
||||
args: {}
|
||||
})
|
||||
},
|
||||
}).define(async (ctx) => {
|
||||
const token = ctx.query?.token || useKey('KEVISUAL_TOKEN');
|
||||
if (!token) {
|
||||
ctx.throw(400, '登录的 token 不能为空,请传入 token 参数');
|
||||
return;
|
||||
}
|
||||
const cmd = `ev login -e `;
|
||||
const res = await runCmd({
|
||||
cmd,
|
||||
env: {
|
||||
'KEVISUAL_TOKEN': token
|
||||
}
|
||||
})
|
||||
if (res.code === 200) {
|
||||
ctx.body = { content: res.data };
|
||||
} else {
|
||||
ctx.throw(500, res.data);
|
||||
}
|
||||
}).addTo(app);
|
||||
45
assistant/src/routes/kevisual/deploy.ts
Normal file
45
assistant/src/routes/kevisual/deploy.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { app } from '@/app.ts'
|
||||
import { runCmd } from '@/module/cmd/run.ts';
|
||||
import { createSkill, tool } from "@kevisual/router";
|
||||
|
||||
// 调用 path: kevisual key: deploy
|
||||
app.route({
|
||||
path: 'kevisual',
|
||||
key: 'deploy',
|
||||
description: '部署一个网页',
|
||||
middleware: ['admin-auth'],
|
||||
metadata: {
|
||||
tags: ['kevisual'],
|
||||
...createSkill({
|
||||
skill: 'kevisual-deploy',
|
||||
title: '部署一个网页',
|
||||
summary: '部署一个网页到 kevisual 平台',
|
||||
args: {
|
||||
filepath: tool.schema.string().describe('要部署的网页文件路径'),
|
||||
appKey: tool.schema.string().optional().describe('应用的 appKey,如果不传则创建一个新的应用'),
|
||||
version: tool.schema.string().optional().describe('应用的版本号,默认为 1.0.0'),
|
||||
update: tool.schema.boolean().optional().describe('是否同时更新部署,默认为 false'),
|
||||
}
|
||||
})
|
||||
},
|
||||
}).define(async (ctx) => {
|
||||
const { filepath, appKey, update } = ctx.query;
|
||||
console.log('部署网页,filepath:', filepath, 'appKey:', appKey);
|
||||
|
||||
ctx.body = { content: '部署功能正在开发中,敬请期待!' };
|
||||
// ev deloly ${filepath} -k ${appKey} -v 1.0.0 -u -y y
|
||||
// if (!filepath) {
|
||||
// ctx.throw(400, '文件路径 filepath 不能为空');
|
||||
// return;
|
||||
// }
|
||||
// let cmd = `ev deploy ${filepath} --type web`;
|
||||
// if (appKey) {
|
||||
// cmd += ` --appKey ${appKey}`;
|
||||
// }
|
||||
// const res = await runCmd({ cmd });
|
||||
// if (res.code === 200) {
|
||||
// ctx.body = { content: res.data };
|
||||
// } else {
|
||||
// ctx.throw(500, res.data);
|
||||
// }
|
||||
}).addTo(app);
|
||||
2
assistant/src/routes/kevisual/index.ts
Normal file
2
assistant/src/routes/kevisual/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import './auth.ts'
|
||||
import './deploy.ts'
|
||||
@@ -1,8 +1,6 @@
|
||||
import { app } from '@/app.ts'
|
||||
import { createSkill, tool } from "@kevisual/router";
|
||||
import { opencodeManager } from './module/open.ts'
|
||||
import path from "node:path";
|
||||
import { execSync } from "node:child_process";
|
||||
import { useKey } from '@kevisual/use-config';
|
||||
|
||||
// 创建一个opencode 客户端
|
||||
@@ -27,7 +25,7 @@ app.route({
|
||||
ctx.body = { content: `${opencodeManager.url} OpenCode 客户端已就绪` };
|
||||
}).addTo(app);
|
||||
|
||||
// 关闭 opencode 客户端
|
||||
// 关闭 opencode 客户端 5000
|
||||
app.route({
|
||||
path: 'opencode',
|
||||
key: 'close',
|
||||
@@ -38,17 +36,39 @@ app.route({
|
||||
...createSkill({
|
||||
skill: 'close-opencode-client',
|
||||
title: '关闭 OpenCode 客户端',
|
||||
summary: '关闭 OpenCode 客户端',
|
||||
summary: '关闭 OpenCode 客户端, 未提供端口则关闭默认端口',
|
||||
args: {
|
||||
|
||||
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 5000')
|
||||
}
|
||||
})
|
||||
},
|
||||
}).define(async (ctx) => {
|
||||
await opencodeManager.close();
|
||||
const port = ctx.query.port;
|
||||
await opencodeManager.close({ port });
|
||||
ctx.body = { content: 'OpenCode 客户端已关闭' };
|
||||
}).addTo(app);
|
||||
|
||||
app.route({
|
||||
path: 'opencode',
|
||||
key: 'restart',
|
||||
middleware: ['auth'],
|
||||
description: '重启 OpenCode 客户端',
|
||||
metadata: {
|
||||
tags: ['opencode'],
|
||||
...createSkill({
|
||||
skill: 'restart-opencode-client',
|
||||
title: '重启 OpenCode 客户端',
|
||||
summary: '重启 OpenCode 客户端',
|
||||
args: {
|
||||
port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 5000')
|
||||
}
|
||||
})
|
||||
},
|
||||
}).define(async (ctx) => {
|
||||
const port = ctx.query.port;
|
||||
const res = await opencodeManager.restart({ port });
|
||||
ctx.body = { content: `${opencodeManager.url} OpenCode 客户端已经重启` };
|
||||
}).addTo(app);
|
||||
// 调用 path: opencode key: getUrl
|
||||
app.route({
|
||||
path: 'opencode',
|
||||
|
||||
@@ -122,6 +122,11 @@ export class OpencodeManager {
|
||||
}
|
||||
return `http://localhost:${port}`;
|
||||
}
|
||||
async restart(opts?: { port?: number }): Promise<OpencodeClient> {
|
||||
const port = opts?.port ?? DEFAULT_PORT;
|
||||
await this.close({ port });
|
||||
return await this.getClient({ port });
|
||||
}
|
||||
}
|
||||
|
||||
export const opencodeManager = OpencodeManager.getInstance();
|
||||
|
||||
Reference in New Issue
Block a user