From 6e5a642ab209bbf8133a7f5e3d6b07708ad7311b Mon Sep 17 00:00:00 2001 From: abearxiong Date: Sat, 31 Jan 2026 00:30:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B0=86=E6=89=80=E6=9C=89=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E7=9A=84=E4=B8=AD=E9=97=B4=E4=BB=B6=E4=BB=8E=20'auth'?= =?UTF-8?q?=20=E6=9B=B4=E6=96=B0=E4=B8=BA=20'admin-auth'=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC=E8=87=B3=200.0.13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent/routes/call/index.ts | 58 +++++++++++----------- agent/routes/cnb-env/check.ts | 2 +- agent/routes/cnb-env/env.ts | 4 +- agent/routes/cnb-env/vscode.ts | 4 +- agent/routes/issues/issue.ts | 4 +- agent/routes/issues/list.ts | 2 +- agent/routes/knowledge/ai.ts | 4 +- agent/routes/repo/list.ts | 2 +- agent/routes/repo/repo.ts | 6 +-- agent/routes/workspace/index.ts | 10 ++-- agent/routes/workspace/keep.ts | 82 ++++++++++++++++++++++---------- agent/routes/workspace/skills.ts | 2 +- package.json | 2 +- 13 files changed, 109 insertions(+), 73 deletions(-) diff --git a/agent/routes/call/index.ts b/agent/routes/call/index.ts index e0e837d..83fcf98 100644 --- a/agent/routes/call/index.ts +++ b/agent/routes/call/index.ts @@ -2,31 +2,33 @@ import { createSkill } from '@kevisual/router' import { app } from '../../app.ts' import { tool } from '@opencode-ai/plugin/tool' -// "调用 path: cnb key: list-repos" -app.route({ - path: 'call', - key: '', - description: '调用', - middleware: ['auth'], - metadata: { - tags: ['opencode'], - ...createSkill({ - skill: 'call-app', - title: '调用app应用', - summary: '调用router的应用, 参数path, key, payload', - args: { - path: tool.schema.string().describe('应用路径,例如 cnb'), - key: tool.schema.string().optional().describe('应用key,例如 list-repos'), - payload: tool.schema.object({}).optional().describe('调用参数'), - } - }) - }, -}).define(async (ctx) => { - const { path, key } = ctx.query; - console.log('call app', ctx.query); - if (!path) { - ctx.throw('路径path不能为空'); - } - const res = await ctx.run({ path, key, payload: ctx.query.payload || {} }); - ctx.forward(res); -}).addTo(app) \ No newline at end of file +if (!app.hasRoute('call')) { + // "调用 path: cnb key: list-repos" + app.route({ + path: 'call', + key: '', + description: '调用', + middleware: ['admin-auth'], + metadata: { + tags: ['opencode'], + ...createSkill({ + skill: 'call-app', + title: '调用app应用', + summary: '调用router的应用, 参数path, key, payload', + args: { + path: tool.schema.string().describe('应用路径,例如 cnb'), + key: tool.schema.string().optional().describe('应用key,例如 list-repos'), + payload: tool.schema.object({}).optional().describe('调用参数'), + } + }) + }, + }).define(async (ctx) => { + const { path, key } = ctx.query; + console.log('call app', ctx.query); + if (!path) { + ctx.throw('路径path不能为空'); + } + const res = await ctx.run({ path, key, payload: ctx.query.payload || {} }); + ctx.forward(res); + }).addTo(app) +} \ No newline at end of file diff --git a/agent/routes/cnb-env/check.ts b/agent/routes/cnb-env/check.ts index 80f600d..e53f9d3 100644 --- a/agent/routes/cnb-env/check.ts +++ b/agent/routes/cnb-env/check.ts @@ -7,7 +7,7 @@ app.route({ path: 'cnb', key: 'user-check', description: '检查用户登录状态,参数checkToken,default true; checkCookie, default false', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/cnb-env/env.ts b/agent/routes/cnb-env/env.ts index 962a5bb..5ac6fca 100644 --- a/agent/routes/cnb-env/env.ts +++ b/agent/routes/cnb-env/env.ts @@ -6,7 +6,7 @@ app.route({ path: 'cnb', key: 'set-cnb-cookie', description: '设置当前cnb工作空间的cookie环境变量', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -33,7 +33,7 @@ app.route({ path: 'cnb', key: 'get-cnb-cookie', description: '获取当前cnb工作空间的cookie环境变量', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/cnb-env/vscode.ts b/agent/routes/cnb-env/vscode.ts index 5df516a..ed45bca 100644 --- a/agent/routes/cnb-env/vscode.ts +++ b/agent/routes/cnb-env/vscode.ts @@ -11,7 +11,7 @@ app.route({ path: 'cnb', key: 'get-cnb-port-uri', description: '获取当前cnb工作空间的port代理uri', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -40,7 +40,7 @@ app.route({ path: 'cnb', key: 'get-cnb-vscode-uri', description: '获取当前cnb工作空间的vscode代理uri, 包括多种访问方式, 如web、vscode、codebuddy、cursor、ssh', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/issues/issue.ts b/agent/routes/issues/issue.ts index c1016d5..2b5d031 100644 --- a/agent/routes/issues/issue.ts +++ b/agent/routes/issues/issue.ts @@ -7,7 +7,7 @@ app.route({ path: 'cnb', key: 'create-issue', description: '创建 Issue, 参数 repo, title, body, assignees, labels, priority', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -51,7 +51,7 @@ app.route({ path: 'cnb', key: 'complete-issue', description: '完成 Issue, 参数 repo, issueNumber', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/issues/list.ts b/agent/routes/issues/list.ts index 773ae89..9a701fe 100644 --- a/agent/routes/issues/list.ts +++ b/agent/routes/issues/list.ts @@ -6,7 +6,7 @@ app.route({ path: 'cnb', key: 'list-issues', description: '查询 Issue 列表, 参数 repo, state, keyword, labels, page, page_size 等', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/knowledge/ai.ts b/agent/routes/knowledge/ai.ts index 90d001a..622daf9 100644 --- a/agent/routes/knowledge/ai.ts +++ b/agent/routes/knowledge/ai.ts @@ -12,7 +12,7 @@ app.route({ path: 'cnb', key: 'cnb-ai-chat', description: '调用cnb的知识库ai对话功能进行聊天', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -88,7 +88,7 @@ app.route({ path: 'cnb', key: 'cnb-rag-query', description: '调用cnb的知识库RAG查询功能进行问答', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/repo/list.ts b/agent/routes/repo/list.ts index ce6d329..a61d7b7 100644 --- a/agent/routes/repo/list.ts +++ b/agent/routes/repo/list.ts @@ -8,7 +8,7 @@ app.route({ path: 'cnb', key: 'list-repos', description: '列出我的代码仓库', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/repo/repo.ts b/agent/routes/repo/repo.ts index 1ea62ee..7b6455d 100644 --- a/agent/routes/repo/repo.ts +++ b/agent/routes/repo/repo.ts @@ -7,7 +7,7 @@ app.route({ path: 'cnb', key: 'create-repo', description: '创建代码仓库, 参数name, visibility, description', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -47,7 +47,7 @@ app.route({ path: 'cnb', key: 'create-repo-file', description: '在代码仓库中创建文件, repoName, filePath, content, encoding', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -86,7 +86,7 @@ app.route({ path: 'cnb', key: 'delete-repo', description: '删除代码仓库, 参数name', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/workspace/index.ts b/agent/routes/workspace/index.ts index 8075356..a569414 100644 --- a/agent/routes/workspace/index.ts +++ b/agent/routes/workspace/index.ts @@ -9,7 +9,7 @@ app.route({ path: 'cnb', key: 'start-workspace', description: '启动开发工作空间, 参数 repo', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -42,7 +42,7 @@ app.route({ path: 'cnb', key: 'list-workspace', description: '获取cnb开发工作空间列表,可选参数 status=running 获取运行中的环境', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -73,7 +73,7 @@ app.route({ path: 'cnb', key: 'get-workspace', description: '获取工作空间详情,通过 repo 和 sn 获取', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -104,7 +104,7 @@ app.route({ path: 'cnb', key: 'delete-workspace', description: '删除工作空间,通过 pipelineId 或 sn', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ @@ -143,7 +143,7 @@ app.route({ path: 'cnb', key: 'stop-workspace', description: '停止工作空间,通过 pipelineId 或 sn', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/agent/routes/workspace/keep.ts b/agent/routes/workspace/keep.ts index eb11974..da64529 100644 --- a/agent/routes/workspace/keep.ts +++ b/agent/routes/workspace/keep.ts @@ -1,5 +1,6 @@ import { createSkill, tool } from '@kevisual/router'; import { app, cnb } from '../../app.ts'; +import { nanoid } from 'nanoid'; import { createKeepAlive } from '../../../src/keep.ts'; @@ -7,6 +8,7 @@ type AliveInfo = { startTime: number; updatedTime?: number; KeepAlive: ReturnType; + id: string;// 6位唯一标识符 } const keepAliveMap = new Map(); @@ -16,7 +18,7 @@ app.route({ path: 'cnb', key: 'keep-workspace-alive', description: '保持工作空间存活技能,参数wsUrl:工作空间访问URL,cookie:访问工作空间所需的cookie', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: [], ...({ @@ -36,10 +38,10 @@ app.route({ ctx.throw(400, '缺少访问工作空间所需的cookie参数'); } - // 检测是否已在运行 - const existing = keepAliveMap.get(wsUrl); + // 检测是否已在运行(通过 wsUrl 遍历检查) + const existing = Array.from(keepAliveMap.values()).find(info => (info as AliveInfo).id && (info as any).KeepAlive?.wsUrl === wsUrl); if (existing) { - ctx.body = { message: `工作空间 ${wsUrl} 的保持存活任务已在运行中` }; + ctx.body = { message: `工作空间 ${wsUrl} 的保持存活任务已在运行中`, id: (existing as AliveInfo).id }; return; } @@ -53,21 +55,31 @@ app.route({ onMessage: (data) => { // 可选:处理收到的消息 // console.log(`工作空间 ${wsUrl} 收到消息: ${data}`); - const aliveInfo = keepAliveMap.get(wsUrl); - if (aliveInfo) { - aliveInfo.updatedTime = Date.now(); + // 通过 wsUrl 找到对应的 id 并更新时间 + for (const info of keepAliveMap.values()) { + if ((info as any).KeepAlive?.wsUrl === wsUrl) { + info.updatedTime = Date.now(); + break; + } } }, debug: true, onExit: (code) => { console.log(`工作空间 ${wsUrl} 保持存活任务已退出,退出码: ${code}`); - keepAliveMap.delete(wsUrl); + // 通过 wsUrl 找到对应的 id 并删除 + for (const [id, info] of keepAliveMap.entries()) { + if ((info as any).KeepAlive?.wsUrl === wsUrl) { + keepAliveMap.delete(id); + break; + } + } } }); - keepAliveMap.set(wsUrl, { startTime: Date.now(), updatedTime: Date.now(), KeepAlive: keep }); + const id = nanoid(6).toLowerCase(); + keepAliveMap.set(id, { startTime: Date.now(), updatedTime: Date.now(), KeepAlive: keep, id }); - ctx.body = { message: `已启动保持工作空间 ${wsUrl} 存活的任务` }; + ctx.body = { content: `已启动保持工作空间 ${wsUrl} 存活的任务`, id }; }).addTo(app); // 获取保持工作空间存活任务列表技能 @@ -75,13 +87,14 @@ app.route({ path: 'cnb', key: 'list-keep-alive-tasks', description: '获取保持工作空间存活任务列表技能', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: [], } }).define(async (ctx) => { - const list = Array.from(keepAliveMap.entries()).map(([wsUrl, info]) => ({ - wsUrl, + const list = Array.from(keepAliveMap.entries()).map(([id, info]) => ({ + id, + wsUrl: (info as any).KeepAlive?.wsUrl, startTime: info.startTime, updatedTime: info.updatedTime })); @@ -92,30 +105,51 @@ app.route({ app.route({ path: 'cnb', key: 'stop-keep-workspace-alive', - description: '停止保持工作空间存活技能, 参数wsUrl:工作空间访问URL', - middleware: ['auth'], + description: '停止保持工作空间存活技能, 参数wsUrl:工作空间访问URL或者id', + middleware: ['admin-auth'], metadata: { tags: [], ...({ args: { - wsUrl: tool.schema.string().describe('工作空间的访问URL'), + wsUrl: tool.schema.string().optional().describe('工作空间的访问URL'), + id: tool.schema.string().optional().describe('保持存活任务的唯一标识符'), } }) } }).define(async (ctx) => { const wsUrl = ctx.query?.wsUrl as string; - if (!wsUrl) { - ctx.throw(400, '缺少工作空间访问URL参数'); + const id = ctx.query?.id as string; + if (!wsUrl && !id) { + ctx.throw(400, '缺少工作空间访问URL参数或唯一标识符'); } - const keepAlive = keepAliveMap.get(wsUrl); - if (keepAlive) { + let targetId: string | undefined; + let wsUrlFound: string | undefined; + + if (id) { + const info = keepAliveMap.get(id); + if (info) { + targetId = id; + wsUrlFound = (info as any).KeepAlive?.wsUrl; + } + } else if (wsUrl) { + for (const [key, info] of keepAliveMap.entries()) { + if ((info as any).KeepAlive?.wsUrl === wsUrl) { + targetId = key; + wsUrlFound = wsUrl; + break; + } + } + } + + if (targetId) { + const keepAlive = keepAliveMap.get(targetId); const endTime = Date.now(); - const duration = endTime - keepAlive.startTime; + const duration = endTime - keepAlive!.startTime; keepAlive?.KeepAlive?.disconnect(); - keepAliveMap.delete(wsUrl); - ctx.body = { message: `已停止保持工作空间 ${wsUrl} 存活的任务,持续时间: ${duration}ms` }; + keepAliveMap.delete(targetId); + ctx.body = { content: `已停止保持工作空间 ${wsUrlFound} 存活的任务,持续时间: ${duration}ms`, id: targetId }; } else { - ctx.body = { message: `没有找到工作空间 ${wsUrl} 的保持存活任务` }; + ctx.body = { content: `没有找到对应的工作空间保持存活任务` }; } }).addTo(app); diff --git a/agent/routes/workspace/skills.ts b/agent/routes/workspace/skills.ts index 026d1de..cbf7d0b 100644 --- a/agent/routes/workspace/skills.ts +++ b/agent/routes/workspace/skills.ts @@ -35,7 +35,7 @@ app.route({ path: 'cnb', key: 'clean-closed-workspace', description: '批量删除已停止的cnb工作空间', - middleware: ['auth'], + middleware: ['admin-auth'], metadata: { tags: ['opencode'], ...createSkill({ diff --git a/package.json b/package.json index 537b409..6b962f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/cnb", - "version": "0.0.12", + "version": "0.0.13", "description": "", "main": "index.js", "scripts": {