- Added support for new configuration sections: relationship, database, maisaka, mcp, and plugin_runtime. - Introduced complex field hooks for handling JSON configurations in chat talk value rules, expression learning lists, and more. - Updated the field hooks to include schema metadata for better UI representation. - Refactored the bot configuration page to utilize a more dynamic approach for managing section values and state. - Improved the configuration schema generation to ensure all top-level sections have UI metadata. - Added tests to validate the new configuration schema and ensure proper functionality of the JSON field hooks.
102 lines
2.4 KiB
TypeScript
102 lines
2.4 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
import type { ConfigSchema, FieldSchema } from '@/types/config-schema'
|
|
|
|
/**
|
|
* Hook type for field-level customization
|
|
*/
|
|
export type FieldHookType = 'replace' | 'wrapper'
|
|
|
|
/**
|
|
* Props passed to a FieldHookComponent
|
|
*/
|
|
export interface FieldHookComponentProps {
|
|
fieldPath: string
|
|
value: unknown
|
|
onChange?: (value: unknown) => void
|
|
children?: ReactNode
|
|
schema?: ConfigSchema | FieldSchema
|
|
}
|
|
|
|
/**
|
|
* A React component that can be registered as a field hook
|
|
*/
|
|
export type FieldHookComponent = React.FC<FieldHookComponentProps>
|
|
|
|
/**
|
|
* Registry entry for a field hook
|
|
*/
|
|
interface FieldHookEntry {
|
|
component: FieldHookComponent
|
|
type: FieldHookType
|
|
}
|
|
|
|
/**
|
|
* Registry for managing field-level hooks
|
|
* Supports two types of hooks:
|
|
* - replace: Completely replaces the default field renderer
|
|
* - wrapper: Wraps the default field renderer with additional functionality
|
|
*/
|
|
export class FieldHookRegistry {
|
|
private hooks: Map<string, FieldHookEntry> = new Map()
|
|
|
|
/**
|
|
* Register a hook for a specific field path
|
|
* @param fieldPath The field path (e.g., 'chat.talk_value')
|
|
* @param component The React component to register
|
|
* @param type The hook type ('replace' or 'wrapper')
|
|
*/
|
|
register(
|
|
fieldPath: string,
|
|
component: FieldHookComponent,
|
|
type: FieldHookType = 'replace'
|
|
): void {
|
|
this.hooks.set(fieldPath, { component, type })
|
|
}
|
|
|
|
/**
|
|
* Get a registered hook for a specific field path
|
|
* @param fieldPath The field path to look up
|
|
* @returns The hook entry if found, undefined otherwise
|
|
*/
|
|
get(fieldPath: string): FieldHookEntry | undefined {
|
|
return this.hooks.get(fieldPath)
|
|
}
|
|
|
|
/**
|
|
* Check if a hook is registered for a specific field path
|
|
* @param fieldPath The field path to check
|
|
* @returns True if a hook is registered, false otherwise
|
|
*/
|
|
has(fieldPath: string): boolean {
|
|
return this.hooks.has(fieldPath)
|
|
}
|
|
|
|
/**
|
|
* Unregister a hook for a specific field path
|
|
* @param fieldPath The field path to unregister
|
|
*/
|
|
unregister(fieldPath: string): void {
|
|
this.hooks.delete(fieldPath)
|
|
}
|
|
|
|
/**
|
|
* Clear all registered hooks
|
|
*/
|
|
clear(): void {
|
|
this.hooks.clear()
|
|
}
|
|
|
|
/**
|
|
* Get all registered field paths
|
|
* @returns Array of registered field paths
|
|
*/
|
|
getAllPaths(): string[] {
|
|
return Array.from(this.hooks.keys())
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Singleton instance of the field hook registry
|
|
*/
|
|
export const fieldHooks = new FieldHookRegistry()
|