UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

174 lines (173 loc) 6.38 kB
/** * AgentState — 类型安全的 Agent 状态机 * * 借鉴 LangGraph StateGraph + Anthropic Agentic Patterns: * - 每个 Agent 拥有独立的 typed state * - 状态转移通过声明式 transitions 定义 * - 支持 guard 条件(类似 XState) * - 内置事件发射(状态变更通知) * * 设计原则: * 1. 不可变更新 — 每次 transition 返回新 state snapshot * 2. 可溯源 — 保留完整状态历史(可选) * 3. 可序列化 — state 可 JSON 化,支持持久化/恢复 * * @module AgentState */ import { EventEmitter } from 'node:events'; /** Agent 执行阶段枚举 */ export const AgentPhase = Object.freeze({ IDLE: 'idle', PLANNING: 'planning', EXECUTING: 'executing', REFLECTING: 'reflecting', WAITING_INPUT: 'waiting_input', HANDOFF: 'handoff', COMPLETED: 'completed', FAILED: 'failed', ABORTED: 'aborted', }); /** 状态转移定义 */ /** 默认状态转移图(适用于所有 Agent 模式,可在子类中扩展) */ const DEFAULT_TRANSITIONS = [ { from: AgentPhase.IDLE, to: AgentPhase.PLANNING, event: 'start' }, { from: AgentPhase.PLANNING, to: AgentPhase.EXECUTING, event: 'plan_ready' }, { from: AgentPhase.EXECUTING, to: AgentPhase.REFLECTING, event: 'step_done' }, { from: AgentPhase.REFLECTING, to: AgentPhase.EXECUTING, event: 'continue' }, { from: AgentPhase.REFLECTING, to: AgentPhase.COMPLETED, event: 'finish' }, { from: AgentPhase.EXECUTING, to: AgentPhase.COMPLETED, event: 'finish' }, { from: AgentPhase.EXECUTING, to: AgentPhase.WAITING_INPUT, event: 'need_input' }, { from: AgentPhase.WAITING_INPUT, to: AgentPhase.EXECUTING, event: 'input_received' }, { from: AgentPhase.EXECUTING, to: AgentPhase.HANDOFF, event: 'handoff' }, { from: AgentPhase.HANDOFF, to: AgentPhase.EXECUTING, event: 'handoff_done' }, // 任意阶段可中止/失败 { from: '*', to: AgentPhase.ABORTED, event: 'abort' }, { from: '*', to: AgentPhase.FAILED, event: 'error' }, ]; export class AgentState extends EventEmitter { /** 当前阶段 */ #phase; /** 用户自定义状态数据 */ #data; #transitions; /** >} */ #history; /** 是否保留历史 */ #keepHistory; /** * @param [opts.initialData={}] 初始状态数据 * @param [opts.initialPhase='idle'] 初始阶段 * @param [opts.transitions] 自定义转移定义(合并到默认转移上) * @param [opts.keepHistory=true] 是否保留状态历史 */ constructor({ initialData = {}, initialPhase = AgentPhase.IDLE, transitions = [], keepHistory = true, } = {}) { super(); this.#phase = initialPhase; this.#data = { ...initialData }; this.#transitions = [...DEFAULT_TRANSITIONS, ...transitions]; this.#keepHistory = keepHistory; this.#history = keepHistory ? [{ phase: initialPhase, data: { ...initialData }, timestamp: Date.now() }] : []; } // ─── 公共 API ──────────────────────────────── /** 当前阶段 */ get phase() { return this.#phase; } /** 当前状态数据(只读 copy) */ get data() { return { ...this.#data }; } /** 状态历史 */ get history() { return [...this.#history]; } /** Agent 是否处于终态 */ get isTerminal() { return [AgentPhase.COMPLETED, AgentPhase.FAILED, AgentPhase.ABORTED].includes(this.#phase); } /** * 触发事件,尝试状态转移 * @param event 事件名 * @param [payload={}] 附加数据(合并到 state.data) * @returns 是否成功转移 */ send(event, payload = {}) { const transition = this.#findTransition(event); if (!transition) { return false; } // Guard 检查 if (transition.guard && !transition.guard(this.#data)) { return false; } const prevPhase = this.#phase; this.#phase = transition.to; this.#data = { ...this.#data, ...payload }; // 执行副作用 if (transition.action) { transition.action(this.#data, payload); } // 记录历史 if (this.#keepHistory) { this.#history.push({ phase: this.#phase, data: { ...this.#data }, timestamp: Date.now(), event, from: prevPhase, }); } // 发射事件 this.emit('transition', { from: prevPhase, to: this.#phase, event, payload }); this.emit(`phase:${this.#phase}`, { from: prevPhase, event, payload }); return true; } /** * 直接更新状态数据(不触发阶段转移) * @param patch 要合并的数据 */ update(patch) { this.#data = { ...this.#data, ...patch }; this.emit('update', { phase: this.#phase, patch }); } /** 获取当前阶段可用的事件列表 */ availableEvents() { return this.#transitions .filter((t) => t.from === this.#phase || t.from === '*') .map((t) => t.event); } /** 导出为可序列化对象 */ toJSON() { return { phase: this.#phase, data: this.#data, history: this.#history, }; } /** 从序列化数据恢复 */ static fromJSON(snapshot, opts = {}) { const state = new AgentState({ initialData: snapshot.data || {}, initialPhase: snapshot.phase || AgentPhase.IDLE, transitions: opts.transitions || [], keepHistory: opts.keepHistory ?? true, }); if (snapshot.history) { state.#history = snapshot.history; } return state; } // ─── 私有方法 ──────────────────────────────── #findTransition(event) { // 精确匹配优先 const exact = this.#transitions.find((t) => t.from === this.#phase && t.event === event); if (exact) { return exact; } // 通配符匹配 return this.#transitions.find((t) => t.from === '*' && t.event === event); } } export default AgentState;