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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}