feat(auth): add authentication routes and user token handling
- Implemented user authentication routes in `auth.ts` for fetching current user info and admin verification. - Added caching mechanism for user tokens to improve performance. - Created middleware for admin authentication. feat(opencode): create OpenCode client route - Added `opencode-cnb` route for creating OpenCode clients with session management. - Integrated OpenCode SDK for client operations and session handling. refactor(client): encapsulate OpenCode client creation - Created a utility function `getClient` in `client.ts` to initialize OpenCode clients. test(opencode): add tests for OpenCode routes - Implemented test cases for OpenCode routes in `list.ts` to validate functionality. - Created common utilities for testing in `common.ts`.
This commit is contained in:
68
assistant/src/routes/opencode/cnb.ts
Normal file
68
assistant/src/routes/opencode/cnb.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { app } from '@/app.ts'
|
||||
import { z } from 'zod';
|
||||
import { getClient } from './module/client.ts';
|
||||
import dayjs from 'dayjs';
|
||||
import { Session } from '@opencode-ai/sdk';
|
||||
|
||||
app.route({
|
||||
path: 'opencode-cnb',
|
||||
key: 'question',
|
||||
middleware: ['auth-admin'],
|
||||
description: '创建 OpenCode 客户端',
|
||||
metadata: {
|
||||
args: {
|
||||
question: z.string().describe('问题'),
|
||||
baseUrl: z.string().optional().describe('OpenCode 服务地址,默认为 http://localhost:4096'),
|
||||
directory: z.string().optional().describe('运行目录,默认为根目录'),
|
||||
messageID: z.string().optional().describe('消息 ID,选填'),
|
||||
sessionId: z.string().optional().describe('会话 ID,选填'),
|
||||
parts: z.array(z.any()).optional().describe('消息内容的分块,优先于 question 参数'),
|
||||
}
|
||||
}
|
||||
}).define(async (ctx) => {
|
||||
const { question, baseUrl, directory = '/workspace', messageID, sessionId, parts } = ctx.query;
|
||||
const client = await getClient({ baseUrl: baseUrl });
|
||||
if (!client) {
|
||||
ctx.body = { content: `OpenCode 客户端获取失败` };
|
||||
return;
|
||||
}
|
||||
if (!question) {
|
||||
ctx.body = { content: `问题不能为空` };
|
||||
return;
|
||||
}
|
||||
// const sessionList = await client.session.list()
|
||||
let session: Session | null = null;
|
||||
// const hasSession = sessionList.data.find(s => s.directory === directory);
|
||||
// if (hasSession) {
|
||||
// session = hasSession;
|
||||
// } else {
|
||||
if (sessionId) {
|
||||
try {
|
||||
const getSession = await client.session.get({ path: { id: sessionId } });
|
||||
session = getSession.data;
|
||||
} catch (error) {
|
||||
// 无法获取会话,继续往下走创建会话的逻辑
|
||||
}
|
||||
}
|
||||
if (!session) {
|
||||
const createSession = await client.session.create({
|
||||
query: {
|
||||
directory,
|
||||
},
|
||||
})
|
||||
session = createSession.data;
|
||||
}
|
||||
let _parts: any[] = parts ?? [{ type: "text", text: question }];
|
||||
const message = await client.session.prompt({
|
||||
body: {
|
||||
messageID: messageID,
|
||||
parts: _parts,
|
||||
},
|
||||
path: {
|
||||
id: sessionId || session.id,
|
||||
},
|
||||
})
|
||||
const data = message.data;
|
||||
|
||||
ctx.body = { content: `已经启动`, data };
|
||||
}).addTo(app);
|
||||
Reference in New Issue
Block a user