You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/AI/Workflow/WorkflowState.cs

152 lines
4.4 KiB
C#

1 month ago
using System;
using System.Collections.Generic;
using System.Text.Json;
namespace AI.Workflow
{
/// <summary>
/// 工作流状态,在整个流程中唯一,我们使用它来负责节点之间传递数据,避免每个节点添加输入输出接口
/// </summary>
public class WorkflowState : ICloneable
{
private readonly Dictionary<string, object> _slots = new();
/// <summary>
/// 关联的工作流 ID
/// </summary>
public string? WorkflowId { get; set; }
/// <summary>
/// 当前执行的节点 ID
/// </summary>
public string? CurrentNodeId { get; set; }
/// <summary>
/// 状态创建时间
/// </summary>
public DateTime CreatedAt { get; set; } = DateTime.Now;
/// <summary>
/// 获取指定键的值
/// </summary>
/// <typeparam name="T">值类型</typeparam>
/// <param name="key">键名</param>
/// <returns>值</returns>
/// <exception cref="KeyNotFoundException">当键不存在时抛出</exception>
public T Get<T>(string key) where T : class
{
if (!_slots.TryGetValue(key, out var value))
{
throw new KeyNotFoundException($"Key '{key}' not found in workflow state");
}
return (T)value;
}
/// <summary>
/// 尝试获取指定键的值
/// </summary>
/// <typeparam name="T">值类型</typeparam>
/// <param name="key">键名</param>
/// <param name="value">输出值</param>
/// <returns>如果键存在返回 true否则返回 false</returns>
public bool TryGet<T>(string key, out T? value) where T : class
{
if (_slots.TryGetValue(key, out var obj) && obj is T typedValue)
{
value = typedValue;
return true;
}
value = null;
return false;
}
/// <summary>
/// 设置指定键的值
/// </summary>
/// <typeparam name="T">值类型</typeparam>
/// <param name="key">键名</param>
/// <param name="value">值</param>
/// <exception cref="ArgumentNullException">当键或值为空时抛出</exception>
public void Set<T>(string key, T value) where T : class
{
if (string.IsNullOrWhiteSpace(key))
{
throw new ArgumentNullException(nameof(key), "Key cannot be null or whitespace");
}
if (value == null)
{
throw new ArgumentNullException(nameof(value), "Value cannot be null");
}
_slots[key] = value;
}
/// <summary>
/// 检查指定键是否存在
/// </summary>
/// <param name="key">键名</param>
/// <returns>如果键存在返回 true</returns>
public bool ContainsKey(string key)
{
return _slots.ContainsKey(key);
}
/// <summary>
/// 移除指定键
/// </summary>
/// <param name="key">键名</param>
/// <returns>如果成功移除返回 true</returns>
public bool Remove(string key)
{
return _slots.Remove(key);
}
/// <summary>
/// 清空所有数据
/// </summary>
public void Clear()
{
_slots.Clear();
}
/// <summary>
/// 获取所有键
/// </summary>
/// <returns>键集合</returns>
public IEnumerable<string> GetKeys()
{
return _slots.Keys;
}
/// <summary>
/// 克隆工作流状态
/// </summary>
/// <returns>新的工作流状态副本</returns>
public object Clone()
{
var json = JsonSerializer.Serialize(_slots);
var copySlots = JsonSerializer.Deserialize<Dictionary<string, object>>(json);
var copy = new WorkflowState
{
WorkflowId = WorkflowId,
CurrentNodeId = CurrentNodeId,
CreatedAt = CreatedAt
};
if (copySlots != null)
{
foreach (var kvp in copySlots)
{
copy._slots[kvp.Key] = kvp.Value;
}
}
return copy;
}
}
}