add plugin system

This commit is contained in:
musistudio
2025-12-31 08:42:37 +08:00
parent 3cb1275e0c
commit 38cc5feadb
20 changed files with 1544 additions and 0 deletions

View File

@@ -15,6 +15,7 @@ import JSON5 from "json5";
import { IAgent, ITool } from "./agents/type";
import agentsManager from "./agents";
import { EventEmitter } from "node:events";
import { pluginManager, tokenSpeedPlugin } from "@musistudio/llms";
const event = new EventEmitter()
@@ -43,6 +44,44 @@ interface RunOptions {
logger?: any;
}
/**
* Plugin configuration from config file
*/
interface PluginConfig {
name: string;
enabled?: boolean;
options?: Record<string, any>;
}
/**
* Register plugins from configuration
* @param serverInstance Server instance
* @param config Application configuration
*/
async function registerPluginsFromConfig(serverInstance: any, config: any): Promise<void> {
// Get plugins configuration from config file
const pluginsConfig: PluginConfig[] = config.plugins || config.Plugins || [];
for (const pluginConfig of pluginsConfig) {
const { name, enabled = false, options = {} } = pluginConfig;
switch (name) {
case 'token-speed':
pluginManager.registerPlugin(tokenSpeedPlugin, {
enabled,
...options
});
break;
default:
console.warn(`Unknown plugin: ${name}`);
break;
}
}
// Enable all registered plugins
await pluginManager.enablePlugins(serverInstance);
}
async function getServer(options: RunOptions = {}) {
await initializeClaudeConfig();
await initDir();
@@ -141,6 +180,9 @@ async function getServer(options: RunOptions = {}) {
presets.map(async preset => await serverInstance.registerNamespace(`/preset/${preset.name}`, preset.config))
)
// Register and configure plugins from config
await registerPluginsFromConfig(serverInstance, config);
// Add async preHandler hook for authentication
serverInstance.addHook("preHandler", async (req: any, reply: any) => {
return new Promise<void>((resolve, reject) => {
@@ -404,6 +446,7 @@ export { getServer };
export type { RunOptions };
export type { IAgent, ITool } from "./agents/type";
export { initDir, initConfig, readConfigFile, writeConfigFile, backupConfigFile } from "./utils";
export { pluginManager, tokenSpeedPlugin } from "@musistudio/llms";
// Start service if this file is run directly
if (require.main === module) {

View File

@@ -8,6 +8,15 @@ declare module "@musistudio/llms" {
logger?: any;
}
/**
* Plugin configuration from config file
*/
export interface PluginConfig {
name: string;
enabled?: boolean;
options?: Record<string, any>;
}
export interface Server {
app: FastifyInstance;
logger: FastifyBaseLogger;

View File

@@ -0,0 +1,62 @@
import { FastifyPluginAsync } from 'fastify';
declare module '@musistudio/llms' {
export interface CCRPluginOptions {
enabled?: boolean;
[key: string]: any;
}
export interface CCRPlugin {
name: string;
version?: string;
description?: string;
register: FastifyPluginAsync<CCRPluginOptions>;
}
export interface PluginMetadata {
name: string;
enabled: boolean;
options?: any;
}
export class PluginManager {
private plugins;
private pluginInstances;
registerPlugin(plugin: CCRPlugin, options?: any): void;
enablePlugin(name: string, fastify: import('fastify').FastifyInstance): Promise<void>;
enablePlugins(fastify: import('fastify').FastifyInstance): Promise<void>;
getPlugins(): PluginMetadata[];
getPlugin(name: string): CCRPlugin | undefined;
hasPlugin(name: string): boolean;
isPluginEnabled(name: string): boolean;
setPluginEnabled(name: string, enabled: boolean): void;
removePlugin(name: string): void;
clear(): void;
}
export const pluginManager: PluginManager;
export const tokenSpeedPlugin: CCRPlugin;
export class SSEParserTransform extends TransformStream<string, any> {
constructor();
}
export class SSESerializerTransform extends TransformStream<any, string> {
constructor();
}
export function rewriteStream(
stream: ReadableStream,
processor: (data: any, controller: ReadableStreamController<any>) => Promise<any>
): ReadableStream;
}