* refactor(behavior-tree)!: 迁移到 Runtime 执行器架构 * fix(behavior-tree): 修复LogAction中的ReDoS安全漏洞 * feat(behavior-tree): 完善行为树核心功能并修复类型错误
72 lines
2.2 KiB
TypeScript
72 lines
2.2 KiB
TypeScript
import { TaskStatus, NodeType } from '../../Types/TaskStatus';
|
||
import { INodeExecutor, NodeExecutionContext, BindingHelper } from '../NodeExecutor';
|
||
import { NodeExecutorMetadata } from '../NodeMetadata';
|
||
|
||
/**
|
||
* 日志动作执行器
|
||
*
|
||
* 输出日志信息
|
||
*/
|
||
@NodeExecutorMetadata({
|
||
implementationType: 'Log',
|
||
nodeType: NodeType.Action,
|
||
displayName: '日志',
|
||
description: '输出日志信息',
|
||
category: 'Action',
|
||
configSchema: {
|
||
message: {
|
||
type: 'string',
|
||
default: '',
|
||
description: '日志消息,支持{key}占位符引用黑板变量',
|
||
supportBinding: true
|
||
},
|
||
logLevel: {
|
||
type: 'string',
|
||
default: 'info',
|
||
description: '日志级别',
|
||
options: ['info', 'warn', 'error']
|
||
}
|
||
}
|
||
})
|
||
export class LogAction implements INodeExecutor {
|
||
execute(context: NodeExecutionContext): TaskStatus {
|
||
const { runtime } = context;
|
||
const message = BindingHelper.getValue<string>(context, 'message', '');
|
||
const logLevel = BindingHelper.getValue<string>(context, 'logLevel', 'info');
|
||
|
||
const finalMessage = this.replaceBlackboardVariables(message, runtime);
|
||
|
||
this.log(finalMessage, logLevel);
|
||
|
||
return TaskStatus.Success;
|
||
}
|
||
|
||
private replaceBlackboardVariables(message: string, runtime: NodeExecutionContext['runtime']): string {
|
||
if (!message.includes('{') || !message.includes('}')) {
|
||
return message;
|
||
}
|
||
|
||
// 使用限制长度的正则表达式避免 ReDoS 攻击
|
||
// 限制占位符名称最多100个字符,只允许字母、数字、下划线和点号
|
||
return message.replace(/\{([\w.]{1,100})\}/g, (_, key) => {
|
||
const value = runtime.getBlackboardValue(key.trim());
|
||
return value !== undefined ? String(value) : `{${key}}`;
|
||
});
|
||
}
|
||
|
||
private log(message: string, level: string): void {
|
||
switch (level) {
|
||
case 'error':
|
||
console.error(message);
|
||
break;
|
||
case 'warn':
|
||
console.warn(message);
|
||
break;
|
||
case 'info':
|
||
default:
|
||
console.log(message);
|
||
break;
|
||
}
|
||
}
|
||
}
|