ToolComponentResolver 工具组件解析器
ToolComponentResolver 是一个用于动态解析和管理工具组件的核心类,它提供了灵活的组件注册、解析和管理机制,主要用于聊天应用中的工具组件动态渲染。
安装和导入
import {
ToolComponentResolver,
defaultToolResolver,
resolveToolComponent,
type ToolComponentMap,
} from "@pt/common-ui/utils";类型定义
ToolComponentMap
工具组件映射接口,定义了工具名称到 Vue 组件的映射关系。
interface ToolComponentMap {
[key: string]: Component;
}API 文档
ToolComponentResolver 类
工具组件解析器的主要类,提供完整的组件管理功能。
构造函数
constructor(
customComponents: ToolComponentMap = {},
fallbackComponent: Component = UnmatchedTool
)参数
customComponents(ToolComponentMap, 可选): 自定义工具组件映射,默认为空对象fallbackComponent(Component, 可选): 当找不到匹配组件时使用的回退组件,默认为UnmatchedTool
示例
import { ToolComponentResolver } from "@pt/common-ui/utils";
import MyCustomTool from "./MyCustomTool.vue";
import MyFallback from "./MyFallback.vue";
// 使用默认配置
const resolver = new ToolComponentResolver();
// 使用自定义组件
const customResolver = new ToolComponentResolver(
{
MyCustomTool,
AnotherTool: MyCustomTool,
},
MyFallback
);register(name, component)
注册单个工具组件。
register(name: string, component: Component): void参数
name(string): 工具名称,用作组件标识符component(Component): Vue 组件
示例
import CustomSearchTool from "./CustomSearchTool.vue";
const resolver = new ToolComponentResolver();
resolver.register("CustomSearch", CustomSearchTool);registerBatch(components)
批量注册多个工具组件。
registerBatch(components: ToolComponentMap): void参数
components(ToolComponentMap): 包含多个工具组件的映射对象
示例
import SearchTool from "./SearchTool.vue";
import CalculatorTool from "./CalculatorTool.vue";
import WeatherTool from "./WeatherTool.vue";
const resolver = new ToolComponentResolver();
resolver.registerBatch({
Search: SearchTool,
Calculator: CalculatorTool,
Weather: WeatherTool,
});unregister(name)
注销指定的工具组件。
unregister(name: string): void参数
name(string): 要注销的工具名称
示例
const resolver = new ToolComponentResolver();
resolver.register("TempTool", SomeTempComponent);
// 稍后注销
resolver.unregister("TempTool");resolve(toolPart)
解析工具组件,根据工具部分对象返回对应的 Vue 组件。
resolve(toolPart: any): Component参数
toolPart(any): 工具部分对象,包含工具的名称和类别信息
返回值
Component: 匹配的 Vue 组件,如果找不到匹配的组件则返回回退组件
解析规则
- 如果
toolPart.category === 'workflow',返回Workflow组件 - 如果
toolPart.category === 'external',返回ExternalSkill组件 - 否则使用
toolPart.name作为组件名称进行匹配
示例
const resolver = new ToolComponentResolver();
// 普通工具
const toolPart1 = {
name: "WebFetch",
input: { url: "https://example.com" },
};
const component1 = resolver.resolve(toolPart1); // 返回 WebFetch 组件
// 工作流工具
const toolPart2 = {
category: "workflow",
name: "MyWorkflow",
};
const component2 = resolver.resolve(toolPart2); // 返回 Workflow 组件
// 外部技能工具
const toolPart3 = {
category: "external",
name: "CustomSkill",
};
const component3 = resolver.resolve(toolPart3); // 返回 ExternalSkill 组件
// 未知工具
const toolPart4 = {
name: "UnknownTool",
};
const component4 = resolver.resolve(toolPart4); // 返回回退组件 (UnmatchedTool)getRegisteredTools()
获取所有已注册的工具组件名称。
getRegisteredTools(): string[]返回值
string[]: 包含所有已注册工具名称的数组
示例
const resolver = new ToolComponentResolver();
resolver.register("CustomTool", SomeComponent);
const tools = resolver.getRegisteredTools();
console.log(tools); // ['AdvancedSearch', 'PythonCodeSandbox', 'TodoRead', ..., 'CustomTool']isRegistered(name)
检查指定的工具组件是否已注册。
isRegistered(name: string): boolean参数
name(string): 要检查的工具名称
返回值
boolean: 如果工具已注册返回true,否则返回false
示例
const resolver = new ToolComponentResolver();
console.log(resolver.isRegistered("WebFetch")); // true (默认工具)
console.log(resolver.isRegistered("CustomTool")); // false
resolver.register("CustomTool", SomeComponent);
console.log(resolver.isRegistered("CustomTool")); // true默认工具组件
系统预置了以下默认工具组件:
AdvancedSearch: 高级搜索工具PythonCodeSandbox: Python 代码沙箱TodoRead: 待办事项读取工具TodoWrite: 待办事项写入工具Task: 任务管理工具WebFetch: 网页抓取工具SqlExecute: SQL 执行工具ExternalSkill: 外部技能工具ExitPlan: 退出计划工具Think: 思考工具Thinking: 思考过程工具
默认解析器实例
export const defaultToolResolver: ToolComponentResolver;预配置的默认工具解析器实例,包含所有默认工具组件。
示例
import { defaultToolResolver } from "@pt/common-ui/utils";
// 直接使用默认解析器
const component = defaultToolResolver.resolve({
name: "WebFetch",
input: { url: "https://example.com" },
});
// 扩展默认解析器
defaultToolResolver.register("MyCustomTool", MyCustomComponent);resolveToolComponent 便捷函数
快速解析工具组件的便捷函数,内部使用默认解析器。
function resolveToolComponent(toolPart: any): Component;参数
toolPart(any): 工具部分对象
返回值
Component: 解析得到的 Vue 组件
示例
import { resolveToolComponent } from "@pt/common-ui/utils";
const toolPart = {
name: "PythonCodeSandbox",
input: { code: "print('Hello, World!')" },
};
const component = resolveToolComponent(toolPart);使用场景
1. 聊天应用中的工具渲染
// ChatMessage.vue
<template>
<div class="chat-message">
<div v-for="part in message.parts" :key="part.id">
<component
v-if="part.type === 'tool_use'"
:is="resolveToolComponent(part)"
v-bind="getToolProps(part, message.parts, { message_id: message.id })"
/>
<div v-else-if="part.type === 'text'" class="text-content">
{{ part.text }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { resolveToolComponent, getToolProps } from "@pt/common-ui/utils";
interface Props {
message: {
id: string;
parts: any[];
};
}
defineProps<Props>();
</script>2. 自定义工具组件管理
// ToolManager.ts
import { ToolComponentResolver } from "@pt/common-ui/utils";
import CustomAnalyticsTool from "./tools/CustomAnalyticsTool.vue";
import CustomReportTool from "./tools/CustomReportTool.vue";
class ToolManager {
private resolver: ToolComponentResolver;
constructor() {
this.resolver = new ToolComponentResolver();
this.initializeCustomTools();
}
private initializeCustomTools() {
// 注册自定义工具
this.resolver.registerBatch({
Analytics: CustomAnalyticsTool,
Report: CustomReportTool,
});
}
// 动态加载工具
async loadTool(toolName: string, toolModule: string) {
try {
const module = await import(`./tools/${toolModule}.vue`);
this.resolver.register(toolName, module.default);
return true;
} catch (error) {
console.error(`Failed to load tool ${toolName}:`, error);
return false;
}
}
// 获取工具组件
getToolComponent(toolPart: any) {
return this.resolver.resolve(toolPart);
}
// 获取可用工具列表
getAvailableTools() {
return this.resolver.getRegisteredTools();
}
}
export const toolManager = new ToolManager();3. 插件化工具系统
// PluginSystem.ts
import { ToolComponentResolver } from "@pt/common-ui/utils";
interface ToolPlugin {
name: string;
component: Component;
version: string;
dependencies?: string[];
}
class PluginSystem {
private resolver: ToolComponentResolver;
private plugins: Map<string, ToolPlugin> = new Map();
constructor() {
this.resolver = new ToolComponentResolver();
}
// 安装插件
installPlugin(plugin: ToolPlugin): boolean {
try {
// 检查依赖
if (plugin.dependencies) {
for (const dep of plugin.dependencies) {
if (!this.plugins.has(dep)) {
throw new Error(`Missing dependency: ${dep}`);
}
}
}
// 注册组件
this.resolver.register(plugin.name, plugin.component);
this.plugins.set(plugin.name, plugin);
console.log(
`Plugin ${plugin.name} v${plugin.version} installed successfully`
);
return true;
} catch (error) {
console.error(`Failed to install plugin ${plugin.name}:`, error);
return false;
}
}
// 卸载插件
uninstallPlugin(pluginName: string): boolean {
try {
// 检查是否有其他插件依赖此插件
for (const [name, plugin] of this.plugins) {
if (plugin.dependencies?.includes(pluginName)) {
throw new Error(
`Cannot uninstall ${pluginName}: ${name} depends on it`
);
}
}
this.resolver.unregister(pluginName);
this.plugins.delete(pluginName);
console.log(`Plugin ${pluginName} uninstalled successfully`);
return true;
} catch (error) {
console.error(`Failed to uninstall plugin ${pluginName}:`, error);
return false;
}
}
// 获取插件信息
getPluginInfo(pluginName: string): ToolPlugin | undefined {
return this.plugins.get(pluginName);
}
// 列出所有插件
listPlugins(): ToolPlugin[] {
return Array.from(this.plugins.values());
}
// 解析工具组件
resolveComponent(toolPart: any) {
return this.resolver.resolve(toolPart);
}
}
// 使用示例
const pluginSystem = new PluginSystem();
// 安装自定义插件
pluginSystem.installPlugin({
name: "WeatherTool",
component: WeatherToolComponent,
version: "1.0.0",
dependencies: ["HttpClient"],
});4. 条件工具加载
// ConditionalToolLoader.ts
import { ToolComponentResolver } from "@pt/common-ui/utils";
class ConditionalToolLoader {
private resolver: ToolComponentResolver;
private userPermissions: Set<string>;
constructor(permissions: string[] = []) {
this.resolver = new ToolComponentResolver();
this.userPermissions = new Set(permissions);
this.loadToolsBasedOnPermissions();
}
private loadToolsBasedOnPermissions() {
// 根据权限加载不同的工具
if (this.userPermissions.has("admin")) {
this.loadAdminTools();
}
if (this.userPermissions.has("developer")) {
this.loadDeveloperTools();
}
if (this.userPermissions.has("analyst")) {
this.loadAnalystTools();
}
}
private async loadAdminTools() {
const AdminPanel = await import("./tools/AdminPanel.vue");
const SystemMonitor = await import("./tools/SystemMonitor.vue");
this.resolver.registerBatch({
AdminPanel: AdminPanel.default,
SystemMonitor: SystemMonitor.default,
});
}
private async loadDeveloperTools() {
const CodeEditor = await import("./tools/CodeEditor.vue");
const APITester = await import("./tools/APITester.vue");
this.resolver.registerBatch({
CodeEditor: CodeEditor.default,
APITester: APITester.default,
});
}
private async loadAnalystTools() {
const DataVisualizer = await import("./tools/DataVisualizer.vue");
const ReportGenerator = await import("./tools/ReportGenerator.vue");
this.resolver.registerBatch({
DataVisualizer: DataVisualizer.default,
ReportGenerator: ReportGenerator.default,
});
}
// 检查用户是否有权限使用某个工具
canUseTool(toolName: string): boolean {
return this.resolver.isRegistered(toolName);
}
// 获取用户可用的工具列表
getAvailableTools(): string[] {
return this.resolver.getRegisteredTools();
}
// 解析工具组件
resolveComponent(toolPart: any) {
const component = this.resolver.resolve(toolPart);
// 如果返回的是回退组件,说明用户没有权限或工具不存在
if (component === this.resolver["fallbackComponent"]) {
console.warn(`Tool ${toolPart.name} not available for current user`);
}
return component;
}
}
// 使用示例
const userPermissions = ["developer", "analyst"];
const conditionalLoader = new ConditionalToolLoader(userPermissions);
// 检查工具可用性
console.log(conditionalLoader.canUseTool("CodeEditor")); // true
console.log(conditionalLoader.canUseTool("AdminPanel")); // false高级用法
1. 工具组件懒加载
// LazyToolResolver.ts
import { ToolComponentResolver, type ToolComponentMap } from "@pt/common-ui/utils";
class LazyToolResolver extends ToolComponentResolver {
private lazyComponents: Map<string, () => Promise<any>> = new Map();
// 注册懒加载组件
registerLazy(name: string, loader: () => Promise<any>) {
this.lazyComponents.set(name, loader);
}
// 重写 resolve 方法以支持懒加载
async resolveAsync(toolPart: any): Promise<Component> {
const name = this.getToolName(toolPart);
// 检查是否已经加载
if (this.isRegistered(name)) {
return this.resolve(toolPart);
}
// 检查是否有懒加载定义
const loader = this.lazyComponents.get(name);
if (loader) {
try {
const module = await loader();
const component = module.default || module;
this.register(name, component);
return component;
} catch (error) {
console.error(`Failed to load lazy component ${name}:`, error);
return this.fallbackComponent;
}
}
return this.fallbackComponent;
}
// 预加载指定工具
async preload(toolNames: string[]): Promise<void> {
const promises = toolNames.map(async (name) => {
const loader = this.lazyComponents.get(name);
if (loader && !this.isRegistered(name)) {
try {
const module = await loader();
const component = module.default || module;
this.register(name, component);
} catch (error) {
console.error(`Failed to preload component ${name}:`, error);
}
}
});
await Promise.all(promises);
}
}
// 使用示例
const lazyResolver = new LazyToolResolver();
// 注册懒加载组件
lazyResolver.registerLazy('HeavyAnalyticsTool', () =>
import('./tools/HeavyAnalyticsTool.vue')
);
lazyResolver.registerLazy('ComplexVisualization', () =>
import('./tools/ComplexVisualization.vue')
);
// 异步解析
const component = await lazyResolver.resolveAsync({
name: 'HeavyAnalyticsTool',
input: { data: [...] }
});
// 预加载关键工具
await lazyResolver.preload(['HeavyAnalyticsTool', 'ComplexVisualization']);2. 工具组件版本管理
// VersionedToolResolver.ts
interface VersionedComponent {
component: Component;
version: string;
deprecated?: boolean;
migration?: string;
}
class VersionedToolResolver extends ToolComponentResolver {
private versionedComponents: Map<string, Map<string, VersionedComponent>> = new Map();
private defaultVersions: Map<string, string> = new Map();
// 注册版本化组件
registerVersioned(
name: string,
version: string,
component: Component,
options: { deprecated?: boolean; migration?: string } = {}
) {
if (!this.versionedComponents.has(name)) {
this.versionedComponents.set(name, new Map());
}
const versions = this.versionedComponents.get(name)!;
versions.set(version, {
component,
version,
deprecated: options.deprecated,
migration: options.migration,
});
// 如果是第一个版本或者不是废弃版本,设为默认版本
if (!this.defaultVersions.has(name) || !options.deprecated) {
this.defaultVersions.set(name, version);
this.register(name, component);
}
}
// 获取特定版本的组件
resolveVersion(toolPart: any, version?: string): Component {
const name = this.getToolName(toolPart);
const versions = this.versionedComponents.get(name);
if (!versions) {
return this.resolve(toolPart);
}
const targetVersion = version || this.defaultVersions.get(name);
if (!targetVersion) {
return this.fallbackComponent;
}
const versionedComponent = versions.get(targetVersion);
if (!versionedComponent) {
console.warn(`Version ${targetVersion} not found for tool ${name}`);
return this.fallbackComponent;
}
if (versionedComponent.deprecated) {
console.warn(
`Tool ${name} v${targetVersion} is deprecated. ${versionedComponent.migration || ''}`
);
}
return versionedComponent.component;
}
// 获取工具的所有版本
getVersions(toolName: string): string[] {
const versions = this.versionedComponents.get(toolName);
return versions ? Array.from(versions.keys()) : [];
}
// 获取工具的默认版本
getDefaultVersion(toolName: string): string | undefined {
return this.defaultVersions.get(toolName);
}
// 迁移到新版本
migrateToVersion(toolName: string, newVersion: string): boolean {
const versions = this.versionedComponents.get(toolName);
if (!versions || !versions.has(newVersion)) { return false; }
const newVersionComponent = versions.get(newVersion)!;
this.defaultVersions.set(toolName, newVersion);
this.register(toolName, newVersionComponent.component);
return true;
} }
// 使用示例 const versionedResolver = new VersionedToolResolver();
// 注册不同版本的组件 versionedResolver.registerVersioned('DataChart', '1.0.0', DataChartV1); versionedResolver.registerVersioned('DataChart', '2.0.0', DataChartV2); versionedResolver.registerVersioned('DataChart', '1.5.0', DataChartV15, { deprecated: true, migration: 'Please upgrade to version 2.0.0 for better performance' });
// 使用特定版本 const chartV1 = versionedResolver.resolveVersion({ name: 'DataChart' }, '1.0.0'); const chartLatest = versionedResolver.resolveVersion({ name: 'DataChart' }); // 使用默认版本
// 迁移到新版本 versionedResolver.migrateToVersion('DataChart', '2.0.0');
## 最佳实践
### 1. 类型安全
建议在 TypeScript 项目中定义明确的类型接口:
```typescript
// types/tool.ts
import type { Component } from 'vue';
export interface ToolPart {
name: string;
id?: string;
category?: 'workflow' | 'external' | 'default';
input?: Record<string, any>;
type?: string;
}
export interface ToolComponentMap {
[key: string]: Component;
}
export interface ToolResolver {
register(name: string, component: Component): void;
resolve(toolPart: ToolPart): Component;
isRegistered(name: string): boolean;
}
// 使用类型化的解析器
class TypedToolResolver implements ToolResolver {
private resolver: ToolComponentResolver;
constructor() {
this.resolver = new ToolComponentResolver();
}
register(name: string, component: Component): void {
this.resolver.register(name, component);
}
resolve(toolPart: ToolPart): Component {
return this.resolver.resolve(toolPart);
}
isRegistered(name: string): boolean {
return this.resolver.isRegistered(name);
}
}2. 错误处理和日志
// SafeToolResolver.ts
import { ToolComponentResolver } from "@pt/common-ui/utils";
class SafeToolResolver extends ToolComponentResolver {
private logger: (message: string, level: "info" | "warn" | "error") => void;
constructor(
customComponents = {},
fallbackComponent = UnmatchedTool,
logger = console.log
) {
super(customComponents, fallbackComponent);
this.logger = logger;
}
register(name: string, component: Component): void {
try {
if (!name || typeof name !== "string") {
throw new Error("Tool name must be a non-empty string");
}
if (!component) {
throw new Error("Component cannot be null or undefined");
}
super.register(name, component);
this.logger(`Tool "${name}" registered successfully`, "info");
} catch (error) {
this.logger(
`Failed to register tool "${name}": ${error.message}`,
"error"
);
throw error;
}
}
resolve(toolPart: any): Component {
try {
if (!toolPart) {
this.logger("Tool part is null or undefined", "warn");
return this.fallbackComponent;
}
const component = super.resolve(toolPart);
const toolName = this.getToolName(toolPart);
if (component === this.fallbackComponent) {
this.logger(
`Tool "${toolName}" not found, using fallback component`,
"warn"
);
} else {
this.logger(`Tool "${toolName}" resolved successfully`, "info");
}
return component;
} catch (error) {
this.logger(`Error resolving tool: ${error.message}`, "error");
return this.fallbackComponent;
}
}
unregister(name: string): void {
try {
if (this.isRegistered(name)) {
super.unregister(name);
this.logger(`Tool "${name}" unregistered successfully`, "info");
} else {
this.logger(`Tool "${name}" was not registered`, "warn");
}
} catch (error) {
this.logger(
`Failed to unregister tool "${name}": ${error.message}`,
"error"
);
throw error;
}
}
}3. 性能优化
// PerformantToolResolver.ts
class PerformantToolResolver extends ToolComponentResolver {
private resolveCache: Map<string, Component> = new Map();
private cacheEnabled: boolean = true;
// 启用/禁用缓存
setCacheEnabled(enabled: boolean): void {
this.cacheEnabled = enabled;
if (!enabled) {
this.clearCache();
}
}
// 清除缓存
clearCache(): void {
this.resolveCache.clear();
}
// 重写 resolve 方法以支持缓存
resolve(toolPart: any): Component {
if (!this.cacheEnabled) {
return super.resolve(toolPart);
}
const toolName = this.getToolName(toolPart);
const cacheKey = `${toolName}_${toolPart.category || "default"}`;
if (this.resolveCache.has(cacheKey)) {
return this.resolveCache.get(cacheKey)!;
}
const component = super.resolve(toolPart);
this.resolveCache.set(cacheKey, component);
return component;
}
// 重写 register 方法以清除相关缓存
register(name: string, component: Component): void {
super.register(name, component);
if (this.cacheEnabled) {
// 清除相关的缓存条目
const keysToDelete = Array.from(this.resolveCache.keys()).filter((key) =>
key.startsWith(`${name}_`)
);
keysToDelete.forEach((key) => this.resolveCache.delete(key));
}
}
// 重写 unregister 方法以清除相关缓存
unregister(name: string): void {
super.unregister(name);
if (this.cacheEnabled) {
// 清除相关的缓存条目
const keysToDelete = Array.from(this.resolveCache.keys()).filter((key) =>
key.startsWith(`${name}_`)
);
keysToDelete.forEach((key) => this.resolveCache.delete(key));
}
}
// 获取缓存统计信息
getCacheStats(): { size: number; hitRate: number } {
return {
size: this.resolveCache.size,
hitRate: 0, // 可以实现命中率统计
};
}
}4. 测试支持
// MockToolResolver.ts
class MockToolResolver extends ToolComponentResolver {
private mockComponents: Map<string, Component> = new Map();
// 添加模拟组件
addMock(name: string, mockComponent: Component): void {
this.mockComponents.set(name, mockComponent);
this.register(name, mockComponent);
}
// 移除模拟组件
removeMock(name: string): void {
this.mockComponents.delete(name);
this.unregister(name);
}
// 清除所有模拟组件
clearMocks(): void {
for (const name of this.mockComponents.keys()) {
this.unregister(name);
}
this.mockComponents.clear();
}
// 检查是否为模拟组件
isMock(name: string): boolean {
return this.mockComponents.has(name);
}
// 获取所有模拟组件
getMocks(): string[] {
return Array.from(this.mockComponents.keys());
}
}
// 测试示例
describe("ToolComponentResolver", () => {
let mockResolver: MockToolResolver;
let MockComponent: Component;
beforeEach(() => {
mockResolver = new MockToolResolver();
MockComponent = {
name: "MockComponent",
template: "<div>Mock Tool</div>",
};
});
afterEach(() => {
mockResolver.clearMocks();
});
test("should resolve mock component", () => {
mockResolver.addMock("TestTool", MockComponent);
const resolved = mockResolver.resolve({ name: "TestTool" });
expect(resolved).toBe(MockComponent);
});
test("should return fallback for unknown tool", () => {
const resolved = mockResolver.resolve({ name: "UnknownTool" });
expect(resolved).toBe(mockResolver["fallbackComponent"]);
});
});故障排除
常见问题
1. 组件未找到
问题: 调用 resolve() 时返回 UnmatchedTool 组件
原因:
- 工具名称不匹配
- 组件未正确注册
- 工具部分对象格式不正确
解决方案:
// 检查工具是否已注册
console.log(resolver.isRegistered("MyTool")); // false
// 检查已注册的工具列表
console.log(resolver.getRegisteredTools());
// 确保正确注册组件
resolver.register("MyTool", MyToolComponent);
// 检查工具部分对象格式
const toolPart = {
name: "MyTool", // 确保名称正确
// category: 'workflow', // 如果是工作流工具
input: {
/* ... */
},
};2. 组件加载失败
问题: 异步组件加载失败
原因:
- 组件文件路径错误
- 组件导出格式不正确
- 网络或模块加载错误
解决方案:
// 使用 try-catch 处理加载错误
try {
const module = await import("./tools/MyTool.vue");
const component = module.default || module;
resolver.register("MyTool", component);
} catch (error) {
console.error("Failed to load component:", error);
// 使用备用组件或显示错误信息
}
// 检查组件导出格式
// 正确的导出方式:
export default defineComponent({
name: "MyTool",
// ...
});3. 类型错误
问题: TypeScript 类型检查失败
解决方案:
// 确保正确的类型定义
import type { Component } from "vue";
import type { ToolComponentMap } from "@pt/common-ui/utils";
// 使用类型断言
const myComponent = MyToolComponent as Component;
resolver.register("MyTool", myComponent);
// 或者定义明确的接口
interface MyToolPart {
name: string;
category?: string;
input?: any;
}
const toolPart: MyToolPart = {
name: "MyTool",
input: { data: "test" },
};调试技巧
1. 启用详细日志
// 创建带日志的解析器
const resolver = new SafeToolResolver({}, UnmatchedTool, (message, level) => {
console.log(`[${level.toUpperCase()}] ${message}`);
});2. 检查组件状态
// 检查解析器状态
function debugResolver(resolver: ToolComponentResolver) {
console.log("Registered tools:", resolver.getRegisteredTools());
// 测试特定工具
const testTools = ["WebFetch", "PythonCodeSandbox", "CustomTool"];
testTools.forEach((tool) => {
console.log(`${tool}: ${resolver.isRegistered(tool) ? "✓" : "✗"}`);
});
}
debugResolver(myResolver);3. 组件解析追踪
// 创建追踪解析器
class TracingResolver extends ToolComponentResolver {
resolve(toolPart: any): Component {
const toolName = this.getToolName(toolPart);
console.log(`Resolving tool: ${toolName}`, toolPart);
const component = super.resolve(toolPart);
console.log(`Resolved to:`, component.name || "Anonymous Component");
return component;
}
}注意事项
- 组件注册时机: 确保在使用前注册所有需要的组件
- 内存管理: 在不需要时及时注销组件,避免内存泄漏
- 异步加载: 对于大型组件,考虑使用懒加载以提高性能
- 错误处理: 始终为组件加载和解析添加适当的错误处理
- 类型安全: 在 TypeScript 项目中使用明确的类型定义
- 测试覆盖: 为自定义解析器和组件编写充分的测试
性能考虑
- 缓存策略: 对于频繁解析的组件,考虑实现缓存机制
- 懒加载: 使用
defineAsyncComponent进行按需加载 - 批量操作: 使用
registerBatch()进行批量注册 - 内存优化: 定期清理不需要的组件注册