From c3bc0d2465e83bb67ce6aea938c60f3f03cc6d09 Mon Sep 17 00:00:00 2001 From: xiongxiao Date: Mon, 16 Mar 2026 01:35:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20OpenCode=20?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=88=97=E5=87=BA=E3=80=81=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E3=80=81=E5=88=9B=E5=BB=BA=E3=80=81=E6=9B=B4=E6=96=B0=E5=92=8C?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BC=9A=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assistant/src/routes/opencode/index.ts | 3 +- .../src/routes/opencode/session/index.ts | 282 ++++++++++++++++++ package.json | 2 +- readme.md | 1 + 4 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 assistant/src/routes/opencode/session/index.ts diff --git a/assistant/src/routes/opencode/index.ts b/assistant/src/routes/opencode/index.ts index f2734ac..5ef36e4 100644 --- a/assistant/src/routes/opencode/index.ts +++ b/assistant/src/routes/opencode/index.ts @@ -1,2 +1,3 @@ import './ls.ts' -import './cnb.ts' \ No newline at end of file +import './cnb.ts' +import './session/index.ts' \ No newline at end of file diff --git a/assistant/src/routes/opencode/session/index.ts b/assistant/src/routes/opencode/session/index.ts new file mode 100644 index 0000000..7a56468 --- /dev/null +++ b/assistant/src/routes/opencode/session/index.ts @@ -0,0 +1,282 @@ +import { app } from '@/app.ts' +import { createSkill, tool } from '@kevisual/router'; +import { opencodeManager } from '../module/open.ts'; + +// 查询 - 列出所有 session +app.route({ + path: 'opencode-session', + key: 'list', + middleware: ['auth-admin'], + description: '列出所有 OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'list-opencode-sessions', + title: '列出所有 Session', + summary: '列出 OpenCode 中的所有会话,可按目录过滤', + args: { + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { port } = ctx.query; + const client = await opencodeManager.getClient({ port }); + const result = await client.session.list(); + ctx.body = { data: result.data, content: `共 ${(result.data as any[])?.length ?? 0} 个 Session` }; +}).addTo(app); + +// 查询 - 获取单个 session +app.route({ + path: 'opencode-session', + key: 'get', + middleware: ['auth-admin'], + description: '获取指定 OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'get-opencode-session', + title: '获取 Session', + summary: '根据 ID 获取指定的 OpenCode 会话信息', + args: { + id: tool.schema.string().describe('Session ID'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { id, port } = ctx.query; + if (!id) { + ctx.throw(400, 'Session ID 不能为空'); + return; + } + const client = await opencodeManager.getClient({ port }); + const result = await client.session.get({ path: { id } }); + ctx.body = { data: result.data, content: `已获取 Session: ${id}` }; +}).addTo(app); + +// 查询 - 获取 session 状态 +app.route({ + path: 'opencode-session', + key: 'status', + middleware: ['auth-admin'], + description: '获取 OpenCode Session 状态', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'get-opencode-session-status', + title: '获取 Session 状态', + summary: '获取当前 OpenCode 会话的运行状态,可按目录过滤', + args: { + directory: tool.schema.string().optional().describe('工作目录'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { directory, port } = ctx.query; + const client = await opencodeManager.getClient({ port }); + const result = await client.session.status(directory ? { query: { directory } } : undefined); + ctx.body = { data: result.data, content: `Session 状态已获取` }; +}).addTo(app); + +// 查询 - 列出 session 消息 +app.route({ + path: 'opencode-session', + key: 'messages', + middleware: ['auth-admin'], + description: '列出 OpenCode Session 消息', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'list-opencode-session-messages', + title: '列出 Session 消息', + summary: '列出指定 OpenCode 会话的所有消息记录', + args: { + id: tool.schema.string().describe('Session ID'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { id, port } = ctx.query; + if (!id) { + ctx.throw(400, 'Session ID 不能为空'); + return; + } + const client = await opencodeManager.getClient({ port }); + const result = await client.session.messages({ path: { id } }); + ctx.body = { data: result.data, content: `Session ${id} 共 ${(result.data as any[])?.length ?? 0} 条消息` }; +}).addTo(app); + +// 新增 - 创建 session +app.route({ + path: 'opencode-session', + key: 'create', + middleware: ['auth-admin'], + description: '创建 OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'create-opencode-session', + title: '创建 Session', + summary: '在指定目录创建一个新的 OpenCode 会话', + args: { + directory: tool.schema.string().optional().describe('工作目录,默认为 /workspace'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { directory = '/workspace', port } = ctx.query; + const client = await opencodeManager.getClient({ port }); + const result = await client.session.create({ query: { directory } }); + ctx.body = { data: result.data, content: `Session 已创建,ID: ${(result.data as any)?.id}` }; +}).addTo(app); + +// 修改 - 更新 session +app.route({ + path: 'opencode-session', + key: 'update', + middleware: ['auth-admin'], + description: '更新 OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'update-opencode-session', + title: '更新 Session', + summary: '更新指定 OpenCode 会话的属性,如标题', + args: { + id: tool.schema.string().describe('Session ID'), + title: tool.schema.string().optional().describe('新的会话标题'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { id, title, port } = ctx.query; + if (!id) { + ctx.throw(400, 'Session ID 不能为空'); + return; + } + const client = await opencodeManager.getClient({ port }); + const result = await client.session.update({ path: { id }, body: { title } }); + ctx.body = { data: result.data, content: `Session ${id} 已更新` }; +}).addTo(app); + +// 删除 - 删除 session +app.route({ + path: 'opencode-session', + key: 'delete', + middleware: ['auth-admin'], + description: '删除 OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'delete-opencode-session', + title: '删除 Session', + summary: '根据 ID 删除指定的 OpenCode 会话及其所有数据', + args: { + id: tool.schema.string().describe('Session ID'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { id, port } = ctx.query; + if (!id) { + ctx.throw(400, 'Session ID 不能为空'); + return; + } + const client = await opencodeManager.getClient({ port }); + await client.session.delete({ path: { id } }); + ctx.body = { content: `Session ${id} 已删除` }; +}).addTo(app); + +// 操作 - 中止 session +app.route({ + path: 'opencode-session', + key: 'abort', + middleware: ['auth-admin'], + description: '中止 OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'abort-opencode-session', + title: '中止 Session', + summary: '中止正在运行的 OpenCode 会话', + args: { + id: tool.schema.string().describe('Session ID'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { id, port } = ctx.query; + if (!id) { + ctx.throw(400, 'Session ID 不能为空'); + return; + } + const client = await opencodeManager.getClient({ port }); + await client.session.abort({ path: { id } }); + ctx.body = { content: `Session ${id} 已中止` }; +}).addTo(app); + +// 操作 - Fork session +app.route({ + path: 'opencode-session', + key: 'fork', + middleware: ['auth-admin'], + description: 'Fork OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'fork-opencode-session', + title: 'Fork Session', + summary: '从指定消息处 Fork 一个 OpenCode 会话', + args: { + id: tool.schema.string().describe('Session ID'), + messageId: tool.schema.string().describe('从该消息处开始 Fork'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { id, messageId, port } = ctx.query; + if (!id || !messageId) { + ctx.throw(400, 'Session ID 和 messageId 不能为空'); + return; + } + const client = await opencodeManager.getClient({ port }); + const result = await client.session.fork({ path: { id }, body: { messageID: messageId } }); + ctx.body = { data: result.data, content: `Session ${id} 已从消息 ${messageId} Fork` }; +}).addTo(app); + +// 操作 - 总结 session +app.route({ + path: 'opencode-session', + key: 'summarize', + middleware: ['auth-admin'], + description: '总结 OpenCode Session', + metadata: { + tags: ['session'], + ...createSkill({ + skill: 'summarize-opencode-session', + title: '总结 Session', + summary: '对指定的 OpenCode 会话进行内容总结', + args: { + id: tool.schema.string().describe('Session ID'), + port: tool.schema.number().optional().describe('OpenCode 服务端口,默认为 4096'), + } + }) + } +}).define(async (ctx) => { + const { id, port } = ctx.query; + if (!id) { + ctx.throw(400, 'Session ID 不能为空'); + return; + } + const client = await opencodeManager.getClient({ port }); + const result = await client.session.summarize({ path: { id } }); + ctx.body = { data: result.data, content: `Session ${id} 总结完成` }; +}).addTo(app); diff --git a/package.json b/package.json index 490caf3..4854487 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevisual/cli", - "version": "0.1.25", + "version": "0.1.26", "description": "envision 命令行工具", "type": "module", "basename": "/root/cli", diff --git a/readme.md b/readme.md index deb9565..bdca991 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,6 @@ # 一个简单的cli工具 ``` +pnpm i npm i -g @kevisual/cli ``` \ No newline at end of file