@toolprint/hypertool-mcp
Version:
HyperTool MCP proxy server for routing requests between clients and multiple underlying MCP servers
293 lines • 10.2 kB
TypeScript
/**
* PersonaManager Implementation
*
* This module implements the main PersonaManager class that orchestrates persona lifecycle,
* activation/deactivation, and state management with event emission. The manager ensures
* only one persona is active at a time and handles the complete activation workflow
* including toolset application and MCP configuration integration.
*
* @fileoverview Main persona management orchestration with state and event handling
*/
import { EventEmitter } from "events";
import type { IToolDiscoveryEngine } from "../discovery/types.js";
import type { LoadedPersona, PersonaReference, PersonaDiscoveryResult, PersonaDiscoveryConfig, ActivationResult, PersonaToolset, PersonaCacheConfig } from "./types.js";
import { type PersonaLoadOptions } from "./loader.js";
import { PersonaCache } from "./cache.js";
import { PersonaDiscovery } from "./discovery.js";
import { PersonaToolsetBridge, type BridgeOptions } from "./toolset-bridge.js";
import type { ToolsetManager } from "../server/tools/toolset/manager.js";
import { type McpConfigMergeOptions } from "./mcp-integration.js";
import type { MCPConfig } from "../types/config.js";
import { IToolsetDelegate } from "../server/tools/interfaces/toolset-delegate.js";
import type { ListSavedToolsetsResponse, EquipToolsetResponse, GetActiveToolsetResponse } from "../server/tools/schemas.js";
import { ToolsProvider } from "../server/types.js";
import { Tool } from "@modelcontextprotocol/sdk/types.js";
/**
* Persona manager configuration options
*/
export interface PersonaManagerConfig {
/** Tool discovery engine getter for validation - returns current instance */
getToolDiscoveryEngine?: () => IToolDiscoveryEngine | undefined;
/** Toolset manager for integration with existing toolset system */
toolsetManager?: ToolsetManager;
/** Cache configuration for loaded personas */
cacheConfig?: PersonaCacheConfig;
/** Discovery configuration for finding personas */
discoveryConfig?: PersonaDiscoveryConfig;
/** Default loading options for personas */
defaultLoadOptions?: PersonaLoadOptions;
/** Whether to auto-discover personas on initialization */
autoDiscover?: boolean;
/** Whether to validate personas on activation */
validateOnActivation?: boolean;
/** Whether to persist state across sessions */
persistState?: boolean;
/** State persistence key for local storage */
stateKey?: string;
/** Bridge configuration options for toolset conversion */
bridgeOptions?: BridgeOptions;
/** MCP configuration handlers for persona integration */
mcpConfigHandlers?: {
getCurrentConfig: () => Promise<MCPConfig | null>;
setCurrentConfig: (config: MCPConfig) => Promise<void>;
restartConnections?: () => Promise<void>;
};
/** MCP configuration merge options */
mcpMergeOptions?: Partial<McpConfigMergeOptions>;
}
/**
* Active persona state information
*/
export interface ActivePersonaState {
/** Currently active loaded persona */
persona: LoadedPersona;
/** Active toolset name if any */
activeToolset?: string;
/** Activation timestamp */
activatedAt: Date;
/** Previous state for restoration */
previousState?: {
toolsetName?: string;
mcpConfig?: any;
customState?: Record<string, any>;
};
/** Activation metadata */
metadata: {
activationSource: "manual" | "automatic" | "restored";
validationPassed: boolean;
toolsResolved: number;
warnings: string[];
mcpConfigApplied?: boolean;
mcpConfigWarnings?: string[];
};
}
/**
* Persona listing options
*/
export interface PersonaListOptions {
/** Include invalid personas in results */
includeInvalid?: boolean;
/** Filter by persona name pattern */
namePattern?: string;
/** Filter by tags */
tags?: string[];
/** Sort order */
sortBy?: "name" | "lastModified" | "created";
/** Sort direction */
sortDirection?: "asc" | "desc";
/** Maximum number of results */
limit?: number;
/** Refresh discovery before listing */
refresh?: boolean;
}
/**
* Persona activation options
*/
export interface PersonaActivationOptions {
/** Specific toolset to activate (defaults to defaultToolset) */
toolsetName?: string;
/** Whether to force activation even if validation fails */
force?: boolean;
/** Whether to backup current state for restoration */
backupState?: boolean;
/** Custom state to preserve during activation */
preserveState?: Record<string, any>;
/** Whether to emit events for this activation */
silent?: boolean;
}
/**
* Main PersonaManager class for lifecycle orchestration
*
* Manages persona activation, deactivation, state tracking, and event emission.
* Ensures only one persona is active at a time and provides comprehensive
* state management with cleanup and restoration capabilities.
*/
export declare class PersonaManager extends EventEmitter implements ToolsProvider, IToolsetDelegate {
private readonly logger;
private readonly loader;
private readonly cache;
private readonly discovery;
private readonly toolsetBridge;
private readonly mcpIntegration;
private readonly config;
private activeState;
private discoveredPersonas;
private lastDiscovery;
private initializationPromise;
constructor(config?: PersonaManagerConfig);
/**
* Initialize the persona manager
*/
initialize(): Promise<void>;
/**
* Get MCP tools from the active persona's active toolset
* This makes PersonaManager a ToolsProvider like ToolsetManager
*/
getMcpTools(): Tool[];
/**
* Activate a persona by name with optional toolset selection
*/
activatePersona(personaName: string, options?: PersonaActivationOptions): Promise<ActivationResult>;
/**
* Deactivate the currently active persona
*/
deactivatePersona(options?: {
silent?: boolean;
}): Promise<ActivationResult>;
/**
* Get currently active persona state
*/
getActivePersona(): ActivePersonaState | null;
/**
* Check if a persona is currently active
*/
isPersonaActive(personaName?: string): boolean;
/**
* List available personas with filtering options
*/
listPersonas(options?: PersonaListOptions): Promise<PersonaReference[]>;
/**
* Refresh persona discovery
*/
refreshDiscovery(): Promise<PersonaDiscoveryResult>;
/**
* Get discovery and manager statistics
*/
getStats(): {
discovery: ReturnType<PersonaDiscovery["getDiscoveryStats"]>;
cache: ReturnType<PersonaCache["getStats"]>;
activePersona: string | null;
discoveredCount: number;
lastDiscovery: Date | null;
bridge: ReturnType<PersonaToolsetBridge["getConfiguration"]>;
};
/**
* Dispose of the manager and clean up resources
*/
dispose(): Promise<void>;
/**
* Perform manager initialization
*/
private performInitialization;
/**
* Find and load a persona by name
*/
private findAndLoadPersona;
/**
* Perform persona activation workflow
*/
private performActivation;
/**
* Switch active toolset within current persona
*/
private switchToolset;
/**
* Apply toolset configuration via the toolset bridge
*/
private applyToolset;
/**
* Capture current state for restoration
*/
private captureCurrentState;
/**
* Restore previous state
*/
private restorePreviousState;
/**
* Persist active state for session restoration
*/
private persistActiveState;
/**
* Restore persisted state
*/
private restorePersistedState;
/**
* Clear persisted state
*/
clearPersistedState(): Promise<void>;
/**
* Get the file path for persisted state
*/
private getStateFilePath;
/**
* Setup event handling between components
*/
private setupEventHandling;
/**
* Format load errors for better readability
*/
private formatLoadErrors;
/**
* Get MCP server configurations for a persona without applying them
* This method loads a persona and extracts its MCP server configs for inclusion
* in the unified boot sequence, rather than applying them directly.
*/
getPersonaMcpServers(personaName: string): Promise<{
success: boolean;
serverConfigs?: Record<string, any>;
error?: string;
}>;
/**
* Get toolsets for a specific persona
* @param personaName - Name of the persona to get toolsets for
* @returns Array of persona toolsets
*/
getPersonaToolsets(personaName: string): PersonaToolset[];
/**
* Helper function to extract server and tool names from namespacedName
* @param namespacedName - Tool name in format {server_name}.{tool_name}
* @returns Object with serverName and toolName
*/
private extractToolInfo;
/**
* List available toolsets for the active persona
* Returns persona toolsets when a persona is active, empty array otherwise
*/
listSavedToolsets(): Promise<ListSavedToolsetsResponse>;
/**
* Equip a persona toolset by name
* This activates the specified toolset within the currently active persona
*/
equipToolset(name: string): Promise<EquipToolsetResponse>;
/**
* Get information about the currently active persona toolset
*/
getActiveToolset(): Promise<GetActiveToolsetResponse>;
/**
* Check if a persona toolset is currently active
*/
hasActiveToolset(): boolean;
/**
* Get the delegate type for routing context
*/
getDelegateType(): "regular" | "persona";
}
/**
* Create a PersonaManager instance with default configuration
*/
export declare function createPersonaManager(config?: PersonaManagerConfig): PersonaManager;
/**
* Default PersonaManager instance for application-wide use
*/
export declare const defaultPersonaManager: PersonaManager;
//# sourceMappingURL=manager.d.ts.map