chore: initial commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import type {bot_event_name, bot_instance_context} from '../../instance/bot_instance_init.ts';
|
||||
import type {BranchState} from '../../../types/bot/workflow/runtime.ts';
|
||||
import type {Json, workflow_config} from '../../../types/bot/workflow/workflow.ts';
|
||||
import type {WorkflowStartTemplate} from '../../../types/bot/workflow/metadata.ts';
|
||||
import {assert_json, evaluate_condition} from '../runtime/value.ts';
|
||||
import {normalize_event} from '../node_action/event_node/registry.ts';
|
||||
import {describe, output} from '../metadata.ts';
|
||||
|
||||
export const config_template: WorkflowStartTemplate = {
|
||||
name: 'event', version: '1.0.0',
|
||||
i18n: describe('事件启动', '机器人出生并就绪后,监听指定事件并按可选条件启动工作流。'),
|
||||
config: [
|
||||
{name: 'auto_start', type: 'boolean', required: false, default: true,
|
||||
i18n: describe('自动监听', '机器人连接并出生后自动监听事件。')},
|
||||
{name: 'mode', type: 'select', required: false, default: 'continuous',
|
||||
i18n: describe('监听模式', '持续监听,或在一次启动被接受后停止监听。'), options: [
|
||||
{value: 'continuous', i18n: describe('持续', '持续接受匹配的事件。')},
|
||||
{value: 'once', i18n: describe('一次', '接受一次启动或排队后停止;忙碌跳过时继续监听。')},
|
||||
]},
|
||||
{name: 'event', type: 'string', required: true, provider: 'event',
|
||||
i18n: describe('事件名称', '选择已描述的事件或填写自定义事件名称;不允许 workflow_update。')},
|
||||
{name: 'condition', type: 'condition', required: false,
|
||||
i18n: describe('触发条件', '使用标准化后的 trigger 数据判断;支持多个条件全部满足(and/且)、任一满足(or/或)和嵌套分组。条件为真时启动,引用缺失时跳过。')},
|
||||
],
|
||||
output: {
|
||||
...output('object', '事件数据', '具体字段由所选事件模板定义;未知事件输出 {event, args}。'),
|
||||
properties: {event: output('string', '事件名称', '当前订阅的事件名称。')},
|
||||
additional_properties: output('json', '事件字段', '事件适配器提供的有界 JSON 数据。'),
|
||||
},
|
||||
};
|
||||
|
||||
export function create_event_handler(definition: workflow_config,
|
||||
start: (trigger: Record<string, Json>) => void): (...args: unknown[]) => void {
|
||||
if (definition.start.type !== 'event' || definition.start.event === 'workflow_update') {
|
||||
throw new Error('Invalid workflow event trigger');
|
||||
}
|
||||
const config = definition.start;
|
||||
return (...args: unknown[]) => {
|
||||
if (config.event === 'any' && args[0] === 'workflow_update') return;
|
||||
try {
|
||||
if (args.length > 32) return;
|
||||
const trigger = normalize_event(config.event, args);
|
||||
if (!trigger) return;
|
||||
assert_json(trigger);
|
||||
if (Buffer.byteLength(JSON.stringify(trigger)) > 65_536) return;
|
||||
if (config.condition) {
|
||||
const state: BranchState = {trigger, vars: structuredClone(definition.initial_vars ?? {}),
|
||||
outputs: {}, last_result: null, inputs: {}, retry_counts: {}};
|
||||
if (!evaluate_condition(config.condition, state)) return;
|
||||
}
|
||||
start(trigger);
|
||||
} catch { /* Unsupported payloads and missing condition references skip this occurrence. */ }
|
||||
};
|
||||
}
|
||||
|
||||
export function register_event_start(context: Pick<bot_instance_context<any>, 'on' | 'off'>,
|
||||
definition: workflow_config, start: (trigger: Record<string, Json>) => void): () => void {
|
||||
const callback = create_event_handler(definition, start);
|
||||
const event = (definition.start as {event: string}).event as bot_event_name;
|
||||
try { context.on(event, callback); }
|
||||
catch (error) { context.off(event, callback); throw error; }
|
||||
let disposed = false;
|
||||
return () => {
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
context.off(event, callback);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user