2026-06-06 20:12:40 +07:00
parent de84b2bf48
commit 97ac0f71f5
13682 changed files with 1125938 additions and 0 deletions
@@ -0,0 +1,383 @@
// utils/tool-loader.js - Tool categorization and filtering
import { getEmbedding, cosineSimilarity } from './embedding.js';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Tool categories mapping (tool name pattern -> category)
const categoryPatterns = {
GameObject: [
'create_gameobject', 'update_gameobject', 'delete_gameobject', 'destroy_gameobject',
'get_gameobject', 'find_gameobject', 'set_active', 'set_parent', 'set_tag',
'set_layer', 'duplicate_gameobject', 'get_children', 'get_parent', 'add_component',
'update_component', 'remove_component'
],
Transform: [
'set_position', 'set_rotation', 'set_scale', 'get_position', 'get_rotation',
'get_scale', 'move_', 'rotate_', 'look_at', 'set_transform'
],
Material: [
'create_material', 'setup_material', 'set_material', 'get_material', 'set_color',
'set_shader', 'set_texture', 'material_property', 'assign_material', 'advanced_material'
],
Lighting: [
'lighting', 'setup_lighting', 'create_light', 'set_light', 'get_light',
'light_intensity', 'light_color', 'light_shadow', 'reflection_probe',
'lightmap', 'ambient_', 'skybox', 'volumetric', 'fog'
],
Camera: [
'camera', 'setup_camera', 'create_camera', 'set_camera', 'get_camera',
'camera_fov', 'camera_depth', 'camera_target', 'camera_viewport',
'camera_priority', 'camera_enabled', 'active_camera'
],
Physics: [
'physics', 'setup_physics', 'add_rigidbody', 'add_collider', 'set_rigidbody',
'set_collider', 'raycast', 'overlap_', 'apply_force', 'set_velocity',
'navmesh', 'navigation'
],
UI: [
'create_ui', 'ui_', 'canvas', 'create_button', 'create_text', 'create_image',
'set_anchor', 'set_pivot', 'rect_transform', 'layout', 'panel'
],
Animation: [
'animation', 'create_animation', 'create_animator', 'add_animation',
'play_animation', 'animator_', 'animation_clip', 'animation_curve'
],
Cinemachine: [
'cinemachine', 'vcam', 'virtual_camera', 'freelook', 'dolly', 'track',
'brain', 'blend', 'state_driven', 'clear_shot', 'impulse', 'confiner',
'collider_extension', 'target_group', 'mixing_camera', 'blend_list'
],
Scene: [
'scene', 'get_scene', 'scene_info', 'scene_summary', 'gameobjects_list',
'gameobject_detail', 'load_scene', 'unload_scene', 'save_scene', 'new_scene',
'set_active_scene', 'list_all_scenes', 'add_scene_to_build', 'manage_scene'
],
GOAP: [
'goap_', 'create_agent', 'add_action', 'add_goal', 'planner', 'sensor',
'ai_agent', 'behavior'
],
Audio: [
'audio', 'create_audio', 'setup_audio', 'play_sound', 'stop_sound',
'audio_mixer', 'audio_source', 'audio_clip', 'audio_effects',
'reverb', '3d_audio', 'music_', 'adaptive_music', 'sound_pool'
],
Input: [
'input', 'gesture', 'touch', 'haptic', 'multitouch', 'swipe', 'pinch',
'drag_drop', 'input_validation', 'input_recording', 'accessibility_input'
],
VFX: [
'vfx', 'visual_effect', 'post_processing', 'bloom', 'vignette', 'chromatic',
'lens_flare', 'screen_shake', 'screen_fade', 'film_grain', 'motion_blur',
'depth_of_field', 'lens_distortion', 'color_grading', 'urp_settings',
'hdrp_settings', 'vfx_graph', 'decal'
],
Shader: [
'shader', 'shader_property', 'shader_graph', 'shader_texture', 'shader_gradient',
'shader_animator', 'water_material', 'toon_material', 'hair_material', 'skin_material',
'eye_material', 'fabric_material'
],
Weather: [
'weather', 'rain', 'snow', 'wind', 'storm', 'fog', 'clouds', 'weather_preset'
],
TimeOfDay: [
'time_of_day', 'day_night', 'time_event', 'sunrise', 'sunset'
],
Editor: [
'inspector', 'selected_object', 'component_details', 'console', 'analyze_console',
'context_menu', 'force_refresh', 'editor_'
],
Package: [
'package', 'install_package', 'list_packages', 'check_package'
],
Build: [
'build_settings', 'player_settings', 'quality_settings', 'project_summary'
],
Monitoring: [
'monitor', 'subscribe_events', 'get_events', 'monitoring_status', 'play_state',
'file_changes', 'compile', 'operation_history', 'checkpoint'
],
AssetManagement: [
'folder', 'rename_asset', 'delete_asset', 'organize_folder', 'cleanup_empty',
'project_snapshot', 'dependencies', 'export_project', 'naming_conventions'
],
Optimization: [
'optimize', 'analyze_draw', 'performance_report', 'estimate_build_size',
'auto_atlas', 'generate_lod', 'best_practices'
],
Batch: [
'batch_rename', 'batch_prefab', 'batch_material', 'extract_all'
],
GameSystems: [
'game_controller', 'state_machine', 'inventory', 'game_template', 'prototype'
],
AI: [
'ml_agent', 'neural_network', 'pathfinding', 'ai_'
],
Debug: [
'debug', 'profile', 'run_tests', 'breakpoint', 'control_game_speed'
],
Timeline: [
'timeline', 'avatar'
],
Scripting: [
'modify_script', 'edit_script', 'add_script', 'update_script', 'read_script',
'grep_scripts', 'list_script', 'analyze_script'
],
Screenshot: [
'capture', 'screenshot', 'get_screenshot'
],
Utility: [
'undo', 'redo', 'search', 'find_', 'get_asset', 'import_', 'create_prefab',
'create_script', 'particle', 'terrain', 'modify_terrain', 'create_terrain',
'place_objects', 'list_assets', 'group_gameobjects', 'add_target_to_group',
'responsive_ui', 'scroll_view', 'safe_area', 'auto_attach'
]
};
/**
* Detect category for a tool name
* @param {string} toolName - Tool name
* @returns {string} - Category name
*/
export function detectCategory(toolName) {
const lowerName = toolName.toLowerCase();
for (const [category, patterns] of Object.entries(categoryPatterns)) {
for (const pattern of patterns) {
if (lowerName.includes(pattern.toLowerCase())) {
return category;
}
}
}
return 'Other';
}
/**
* Load tool registry from file
* @returns {Object} - Tool registry
*/
export function loadToolRegistry() {
try {
const registryPath = path.join(__dirname, '..', 'tool-registry.json');
if (!fs.existsSync(registryPath)) {
console.warn('[ToolLoader] tool-registry.json not found, will need to generate');
return null;
}
const data = fs.readFileSync(registryPath, 'utf-8');
return JSON.parse(data);
} catch (error) {
console.error('[ToolLoader] Error loading tool registry:', error.message);
return null;
}
}
/**
* Filter tools by categories
* @param {string[]} categories - Categories to include
* @param {Object} toolRegistry - Tool registry
* @returns {string[]} - Filtered tool names
*/
export function filterToolsByCategories(categories, toolRegistry) {
if (!toolRegistry) {
return [];
}
const toolNames = [];
for (const [toolName, meta] of Object.entries(toolRegistry)) {
if (categories.includes(meta.category)) {
toolNames.push(toolName);
}
}
return toolNames;
}
/**
* Search tools by keyword using embeddings or text matching
* @param {string} query - Search query
* @param {number} limit - Max results
* @param {Object} toolRegistry - Tool registry
* @returns {Promise<Array>} - Results with scores
*/
export async function searchToolsByKeywords(query, limit, toolRegistry) {
if (!toolRegistry) {
return [];
}
const queryLower = query.toLowerCase();
const results = [];
// Check if embeddings are available
const hasEmbeddings = Object.values(toolRegistry).some(meta => meta.embedding);
if (hasEmbeddings) {
// Use semantic search with embeddings
try {
const queryEmbedding = await getEmbedding(query);
for (const [toolName, meta] of Object.entries(toolRegistry)) {
if (!meta.embedding) {
continue;
}
const similarity = cosineSimilarity(queryEmbedding, meta.embedding);
results.push({
name: toolName,
description: meta.description,
category: meta.category,
score: similarity
});
}
} catch (error) {
console.error('[ToolLoader] Embedding search error:', error.message);
// Fall through to text matching
}
}
// Fallback to simple text matching if no embeddings or error
if (results.length === 0) {
// Split query into keywords for OR search
const keywords = queryLower.split(/\s+/).filter(k => k.length > 0);
for (const [toolName, meta] of Object.entries(toolRegistry)) {
const toolNameLower = toolName.toLowerCase();
const descLower = (meta.description || '').toLowerCase();
const categoryLower = (meta.category || '').toLowerCase();
let score = 0;
let matchCount = 0;
// Check each keyword
for (const keyword of keywords) {
// Exact match in tool name (highest priority)
if (toolNameLower === keyword) {
score = Math.max(score, 1.0);
matchCount++;
}
// Tool name contains keyword
else if (toolNameLower.includes(keyword)) {
score = Math.max(score, 0.8);
matchCount++;
}
// Description contains keyword
else if (descLower.includes(keyword)) {
score = Math.max(score, 0.6);
matchCount++;
}
// Category contains keyword
else if (categoryLower.includes(keyword)) {
score = Math.max(score, 0.4);
matchCount++;
}
}
// Boost score if multiple keywords match
if (matchCount > 1) {
score = Math.min(1.0, score + (matchCount - 1) * 0.1);
}
if (score > 0) {
results.push({
name: toolName,
description: meta.description,
category: meta.category,
score: score
});
}
}
}
// Sort by similarity and limit
results.sort((a, b) => b.score - a.score);
return results.slice(0, limit);
}
/**
* Get all available categories
* @returns {Object} - Category descriptions
*/
export function getAvailableCategories() {
const registry = loadToolRegistry();
if (!registry) {
// Fallback to categoryPatterns if registry not available
const categories = {};
for (const [name, patterns] of Object.entries(categoryPatterns)) {
categories[name] = {
count: patterns.length,
description: getCategoryDescription(name)
};
}
return categories;
}
// Count tools by category from registry
const categoryCounts = {};
for (const [toolName, meta] of Object.entries(registry)) {
const category = meta.category;
if (!categoryCounts[category]) {
categoryCounts[category] = 0;
}
categoryCounts[category]++;
}
// Build category info
const categories = {};
for (const [category, count] of Object.entries(categoryCounts)) {
categories[category] = {
count: count,
description: getCategoryDescription(category)
};
}
return categories;
}
function getCategoryDescription(category) {
const descriptions = {
GameObject: 'Create, destroy, find, parent, tag, layer operations',
Transform: 'Position, rotation, scale manipulation',
Material: 'Create materials, set colors, shaders, textures, properties',
Lighting: 'Lights, reflection probes, lightmaps, ambient lighting',
Camera: 'Camera creation and configuration',
Physics: 'Rigidbody, colliders, physics simulation, raycasts',
UI: 'Canvas, UI elements, anchors, text, buttons, images',
Animation: 'Animator, animation clips, state machines, curves',
Cinemachine: 'Virtual cameras, follow, dolly, brain, blending',
Scene: 'Scene management, loading, saving, building, info',
GOAP: 'AI agents, goals, actions, planners, sensors',
Audio: 'Audio sources, clips, mixers, spatial audio, music',
Input: 'Touch, gesture, haptic, multitouch input handling',
VFX: 'Visual effects, post-processing, bloom, particles',
Shader: 'Shader creation, properties, textures, materials',
Weather: 'Weather systems, rain, snow, fog, clouds',
TimeOfDay: 'Day/night cycle, time events, sunrise/sunset',
Editor: 'Unity Editor operations, inspector, console',
Package: 'Package management, installation, updates',
Build: 'Build settings, player settings, quality settings',
Monitoring: 'Performance monitoring, events, file changes',
AssetManagement: 'Asset organization, folders, naming, cleanup',
Optimization: 'Performance optimization, draw calls, profiling',
Batch: 'Batch operations on multiple objects',
GameSystems: 'Game controllers, state machines, inventory',
AI: 'AI pathfinding, neural networks, ML agents',
Debug: 'Debugging tools, profiling, testing',
Timeline: 'Timeline and avatar setup',
Scripting: 'Script editing, analysis, modification',
Screenshot: 'Screenshot capture tools',
Utility: 'Undo, redo, search, find, asset management',
Other: 'Miscellaneous tools'
};
return descriptions[category] || 'Various Unity tools';
}