"feat: 增加助手应用配置管理功能与服务器守护进程支持"
This commit is contained in:
@@ -15,8 +15,10 @@ const Init = new Command('init')
|
||||
} else if (opts.path) {
|
||||
opts.path = path.resolve(opts.path);
|
||||
}
|
||||
const configDir = AssistantInit.detectConfigDir(opts.path);
|
||||
console.log('configDir', configDir);
|
||||
const assistantInit = new AssistantInit({
|
||||
path: opts.path,
|
||||
path: configDir,
|
||||
});
|
||||
assistantInit.init();
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import { program, runProgram } from '@/program.ts';
|
||||
import './command/init/index.ts';
|
||||
import './command/config-manager/index.ts';
|
||||
import './command/app-manager/index.ts';
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,7 +37,7 @@ export const initConfig = (configRootPath: string) => {
|
||||
*/
|
||||
appsDir,
|
||||
/**
|
||||
* 服务配置文件路径 assistant-service-config.json
|
||||
* 服务配置文件路径 assistant-apps-config.json
|
||||
*/
|
||||
appsConfigPath,
|
||||
/**
|
||||
@@ -65,6 +65,15 @@ type AssistantConfigData = {
|
||||
proxy?: ProxyInfo[];
|
||||
apiProxyList?: ProxyInfo[];
|
||||
description?: string;
|
||||
/**
|
||||
* 首页
|
||||
*/
|
||||
home?: string;
|
||||
ai?: {
|
||||
provider?: string | 'DeepSeek' | 'SiliconFlow';
|
||||
apiKey?: string;
|
||||
model?: string;
|
||||
};
|
||||
};
|
||||
let assistantConfig: AssistantConfigData;
|
||||
type AssistantConfigOptions = {
|
||||
@@ -142,7 +151,7 @@ export class AssistantConfig {
|
||||
fs.writeFileSync(pageConfigPath, JSON.stringify(_saveConfig, null, 2));
|
||||
return _saveConfig;
|
||||
}
|
||||
assAppConfig(app: any) {
|
||||
addAppConfig(app: any) {
|
||||
const config = this.getPageConfig();
|
||||
const assistantConfig = this.getCacheAssistantConfig();
|
||||
const _apps = config.list;
|
||||
|
||||
3
assistant/src/run-server.ts
Normal file
3
assistant/src/run-server.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { runServer } from "./server.ts";
|
||||
|
||||
runServer();
|
||||
@@ -1,10 +1,71 @@
|
||||
import { app } from './app.ts';
|
||||
import { proxyRoute, proxyWs } from './services/proxy/proxy-page-index.ts';
|
||||
import getPort, { portNumbers } from 'get-port';
|
||||
import { program } from 'commander';
|
||||
import { spawnSync } from 'child_process';
|
||||
export const runServer = async (port?: number) => {
|
||||
let _port: number | undefined;
|
||||
if (port) {
|
||||
_port = await getPort({ port });
|
||||
if (_port !== port) {
|
||||
console.log(`Port ${port} is not available`);
|
||||
_port = undefined;
|
||||
}
|
||||
}
|
||||
if (!_port) {
|
||||
// 检车端口可用性
|
||||
const isPortAvailable = await getPort({ port: portNumbers(51015, 52000) });
|
||||
if (!isPortAvailable) {
|
||||
console.log(`Port ${isPortAvailable} is not available`);
|
||||
process.exit(1);
|
||||
}
|
||||
_port = isPortAvailable;
|
||||
}
|
||||
app.listen(_port, () => {
|
||||
console.log(`Server is running on https://localhost:${_port}`);
|
||||
});
|
||||
app.server.on(proxyRoute);
|
||||
proxyWs();
|
||||
return {
|
||||
app,
|
||||
port: _port,
|
||||
};
|
||||
};
|
||||
program
|
||||
.description('启动服务')
|
||||
.option('-d, --daemon', '是否以守护进程方式运行')
|
||||
.option('-n, --name <name>', '服务名称', 'assistant-server')
|
||||
.option('-p, --port <port>', '服务端口')
|
||||
.option('-s, --start', '是否启动服务')
|
||||
.action(async (options) => {
|
||||
// console.log('当前执行路径:', execPath, inte);
|
||||
if (options.daemon) {
|
||||
const [_interpreter, execPath] = process.argv;
|
||||
const name = options.name;
|
||||
const port = options.port;
|
||||
let pm2Command = `pm2 start ${execPath} --name ${name} -- -s `;
|
||||
if (port) {
|
||||
pm2Command += ` -p ${port}`;
|
||||
}
|
||||
const result = spawnSync(pm2Command, {
|
||||
shell: true,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
if (result.error) {
|
||||
console.error('Error starting server:', result.error);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('以守护进程方式运行');
|
||||
} else if (options.start) {
|
||||
console.log('启动服务');
|
||||
const server = await runServer(options.port);
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(51015, () => {
|
||||
console.log('Server is running on http://localhost:51015');
|
||||
});
|
||||
|
||||
app.server.on(proxyRoute);
|
||||
|
||||
proxyWs();
|
||||
export const runParser = async (argv: string[]) => {
|
||||
try {
|
||||
program.parse(argv);
|
||||
} catch (error) {
|
||||
console.error('执行错误:', error.message);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import { checkFileExists, AssistantConfig } from '@/module/assistant/index.ts';
|
||||
import { chalk } from '@/module/chalk.ts';
|
||||
export type AssistantInitOptions = {
|
||||
path?: string;
|
||||
init?: boolean;
|
||||
};
|
||||
/**
|
||||
* 助手初始化类
|
||||
@@ -14,6 +15,7 @@ export class AssistantInit extends AssistantConfig {
|
||||
const configDir = opts?.path || process.cwd();
|
||||
super({
|
||||
configDir,
|
||||
init: opts?.init ?? false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,21 +32,30 @@ export class AssistantInit extends AssistantConfig {
|
||||
}
|
||||
}
|
||||
checkConfigPath() {
|
||||
const assistantPath = path.join(this.configDir, 'assistant-config.json');
|
||||
const assistantPath = path.join(this.configDir, 'assistant-app', 'assistant-config.json');
|
||||
return checkFileExists(assistantPath);
|
||||
}
|
||||
createAssistantConfig() {
|
||||
const assistantPath = this.configPath?.configPath;
|
||||
// 创建助手配置文件 assistant-config.json
|
||||
if (!checkFileExists(assistantPath, true)) {
|
||||
this.setConfig({
|
||||
description: '助手配置文件',
|
||||
});
|
||||
console.log(chalk.green('助手配置文件创建成功'));
|
||||
console.log(chalk.green('助手配置文件assistant-config.json创建成功'));
|
||||
}
|
||||
const env = this.configPath?.envConfigPath;
|
||||
// 创建助手环境配置文件 env
|
||||
if (!checkFileExists(env, true)) {
|
||||
fs.writeFileSync(env, '# 环境配置文件\n');
|
||||
console.log(chalk.green('助手环境配置文件创建成功'));
|
||||
console.log(chalk.green('助手环境配置.env文件创建成功'));
|
||||
}
|
||||
|
||||
const appsConfig = this.configPath?.appsConfigPath;
|
||||
// 创建助手应用配置文件 apps
|
||||
if (!checkFileExists(appsConfig, true)) {
|
||||
fs.writeFileSync(appsConfig, JSON.stringify({ description: 'apps manager.', list: [] }));
|
||||
console.log(chalk.green('助手应用配置文件apps.json创建成功'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
||||
const appDir = assistantConfig.configPath?.pageDir;
|
||||
const url = new URL(req.url, 'http://localhost');
|
||||
const pathname = url.pathname;
|
||||
if (pathname === '/' && _assistantConfig?.home) {
|
||||
res.writeHead(302, { Location: `${_assistantConfig?.home}/` });
|
||||
return res.end();
|
||||
}
|
||||
if (pathname.startsWith('/favicon.ico')) {
|
||||
res.statusCode = 404;
|
||||
res.end('Not Found Favicon');
|
||||
|
||||
53
assistant/src/test/chat.ts
Normal file
53
assistant/src/test/chat.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
// import { AssistantConfig } from '@/module/assistant/index.ts';
|
||||
import { assistantConfig } from '../config.ts';
|
||||
|
||||
import { ProviderManager, SiliconFlowProvider } from '@kevisual/ai-center';
|
||||
|
||||
const config = assistantConfig.getConfig();
|
||||
console.log('aiConfig', config.ai);
|
||||
const providerManager = new ProviderManager({
|
||||
provider: config.ai.provider,
|
||||
apiKey: config.ai.apiKey!,
|
||||
model: config.ai.model!,
|
||||
});
|
||||
|
||||
const chatTest = async (text: string) => {
|
||||
const result = await providerManager.provider.chat([
|
||||
{
|
||||
role: 'user',
|
||||
content: text,
|
||||
},
|
||||
]);
|
||||
console.log('result', result);
|
||||
return result.choices[0].message.content;
|
||||
};
|
||||
|
||||
chatTest('你好').then((res) => {
|
||||
console.log('chatTest', res);
|
||||
});
|
||||
|
||||
// providerManager.provider.test().then((res) => {
|
||||
// console.log('test', res);
|
||||
// });
|
||||
// const siliconflow = providerManager.provider as any;
|
||||
const siliconflow = new SiliconFlowProvider({
|
||||
apiKey: config.ai.apiKey!,
|
||||
model: config.ai.model!,
|
||||
});
|
||||
const main = async () => {
|
||||
const usage = await siliconflow.getUsageInfo();
|
||||
console.log(usage);
|
||||
};
|
||||
|
||||
// main();
|
||||
const test = async () => {
|
||||
const result = await siliconflow.chat([
|
||||
{
|
||||
role: 'user',
|
||||
content: '你好',
|
||||
},
|
||||
]);
|
||||
console.log('result', result, 'result.choices[0].message.content', result.choices[0].message.content);
|
||||
return result.choices[0].message.content;
|
||||
};
|
||||
// test();
|
||||
22
assistant/src/test/provider/model-scope.ts
Normal file
22
assistant/src/test/provider/model-scope.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ProviderManager, SiliconFlowProvider, ModelScopeProvider } from '@kevisual/ai-center';
|
||||
|
||||
import { config } from 'dotenv';
|
||||
config();
|
||||
const providerTest = async () => {
|
||||
const providerConfig = { provider: 'ModelScope', model: 'Qwen/Qwen2.5-Coder-32B-Instruct', apiKey: process.env.MODEL_SCOPE_API_KEY };
|
||||
const provider = await ProviderManager.createProvider(providerConfig);
|
||||
const result = await provider.chat([{ role: 'user', content: '你好' }]);
|
||||
console.log(result);
|
||||
};
|
||||
|
||||
providerTest();
|
||||
|
||||
const modelScopeTest = async () => {
|
||||
const provider = new ModelScopeProvider({
|
||||
apiKey: process.env.MODEL_SCOPE_API_KEY,
|
||||
model: 'Qwen/Qwen2.5-Coder-32B-Instruct',
|
||||
});
|
||||
const result = await provider.chat([{ role: 'user', content: '你好' }]);
|
||||
console.log(result);
|
||||
};
|
||||
// modelScopeTest();
|
||||
Reference in New Issue
Block a user