@kiwa-test/agent 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/state-machine.ts","../src/langgraph.ts","../src/openai-assistants.ts"],"sourcesContent":["export type {\n AgentState,\n Assistant,\n AssistantHandler,\n AssistantHandlerContext,\n AssistantHandlerResult,\n EndNode,\n GraphEdge,\n GraphStep,\n NodeHandler,\n Run,\n RunStatus,\n StartNode,\n Thread,\n ThreadMessage,\n ThreadMessageRole,\n ToolCall,\n ToolOutput,\n} from './types.js';\n\nexport { END, START } from './types.js';\n\nexport {\n DEFAULT_MAX_STEPS,\n GraphCompileError,\n MaxStepsExceededError,\n StateMachine,\n} from './state-machine.js';\nexport type { RunOptions } from './state-machine.js';\n\nexport { CompiledGraph, StateGraph } from './langgraph.js';\n\nexport { AssistantsClient, toolCall } from './openai-assistants.js';\nexport type { AssistantsClientConfig } from './openai-assistants.js';\n","/**\n * Agent orchestration mock — 2 系統 (LangGraph 型 state machine + OpenAI Assistants v2)\n * を 1 統一 API で扱う。 real LangGraph は Python + TS の 2 SDK があり、\n * StateGraph(addNode + addEdge + compile → invoke / stream) が中核。\n * real OpenAI Assistants v2 は Thread + Run + Message + polling が中核で、\n * run status が queued → in_progress → completed / failed / requires_action の\n * 5 状態を遷移する。\n *\n * ### 対応する mock 表現 (v1.15-3 対象)\n *\n * 1. **LangGraph 型 state machine** — `StateGraph` で node + edge を組み、\n * `compile()` で `CompiledGraph` を得て、 `invoke(initialState)` で最終 state を、\n * `stream(initialState)` で 中間 state を順次得る。\n * 2. **OpenAI Assistants v2** — `AssistantsClient` で `createAssistant` /\n * `createThread` / `addMessage` / `createRun` / `run.poll` を実行、 run status を\n * 決定的に遷移させる。\n *\n * ### 対応しない (v0.2 以降)\n *\n * - Vector store / file 系 (Assistants v2 の `file_search` tool)\n * - real streaming API (SSE / websocket) — mock は同期的 stream generator\n * - LangGraph の `conditional_edges` / `interrupt` — v0.1 は addEdge + END の 2 辺のみ\n */\n\n/**\n * 状態を持つ graph node の generic state 型。 実 test では project 側で narrow する。\n * shape は `object` に緩めて index signature 要求を避ける (real LangGraph も any-typed\n * TypedDict を許容する)。 handler / stream の内部で `{ ...state, ...patch }` で shallow\n * merge するため、 実質的な shape 制約は各 project 側の TState で narrow される。\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AgentState = object;\n\n/** Node handler — 現 state を受け取り、 更新分 (partial state) を返す。 同期 or 非同期。 */\nexport type NodeHandler<TState extends AgentState = AgentState> = (\n state: TState,\n) => Partial<TState> | Promise<Partial<TState>>;\n\n/** END sentinel — graph の終端を示す reserved node name。 real LangGraph の `END` に対応。 */\nexport const END = '__end__' as const;\nexport type EndNode = typeof END;\n\n/** START sentinel — graph の起点を示す reserved node name。 real LangGraph の `START` に対応。 */\nexport const START = '__start__' as const;\nexport type StartNode = typeof START;\n\n/**\n * Graph edge — `from` node の実行後に `to` node を実行する矢印。 `to === END`\n * で graph 終了。 v0.1 は unconditional edge のみ、 `conditional_edges` は v0.2 以降。\n */\nexport interface GraphEdge {\n from: string | StartNode;\n to: string | EndNode;\n}\n\n/** 1 step の実行 trace — stream / debug 用。 */\nexport interface GraphStep<TState extends AgentState = AgentState> {\n /** 実行した node 名。 START edge の直後は最初の node 名。 */\n node: string;\n /** node handler が返した partial state (merge 前)。 */\n patch: Partial<TState>;\n /** patch merge 後の state。 */\n state: TState;\n}\n\n/**\n * OpenAI Assistants v2 の Message role — real API に整合。 v0.1 は user + assistant\n * の 2 種、 tool_message は v0.2 以降。\n */\nexport type ThreadMessageRole = 'user' | 'assistant';\n\n/** Thread message — real Assistants v2 の Message resource に対応。 */\nexport interface ThreadMessage {\n id: string;\n role: ThreadMessageRole;\n content: string;\n createdAt: number;\n}\n\n/**\n * Assistants v2 の Run status SSOT — real API と同じ 5 状態。 v0.1 mock は\n * queued → in_progress → completed / failed / requires_action の deterministic\n * transition を model する。\n *\n * | status | 意味 |\n * |---|---|\n * | queued | createRun 直後、 まだ polling で 1 回も進んでいない |\n * | in_progress | polling 1 回で queued から遷移、 assistant が work 中 |\n * | completed | assistant が response 生成完了、 final message が thread に append 済 |\n * | failed | handler が throw、 final error は run.lastError に格納 |\n * | requires_action | tool_calls が pending、 submit_tool_outputs で解除 |\n */\nexport type RunStatus =\n | 'queued'\n | 'in_progress'\n | 'completed'\n | 'failed'\n | 'requires_action';\n\n/**\n * Assistant handler — 1 run で assistant が「thread 履歴を見て次の action を決める」\n * 1 step 分の logic。 return が string なら completed で assistant message として append、\n * return が `{ toolCalls }` なら requires_action に遷移して pending tool_calls を保持。\n */\nexport type AssistantHandler = (\n ctx: AssistantHandlerContext,\n) => Promise<AssistantHandlerResult> | AssistantHandlerResult;\n\n/** handler に渡す context — thread 履歴 + 現在の run。 */\nexport interface AssistantHandlerContext {\n thread: readonly ThreadMessage[];\n runId: string;\n assistantId: string;\n /**\n * 前 step の tool 実行結果 (submit_tool_outputs で受け取ったもの)、 requires_action\n * を解除した直後の再呼出でのみ set される。 それ以外は undefined。\n */\n toolOutputs?: readonly ToolOutput[];\n}\n\n/** handler が返す result — completed か requires_action の 2 種。 */\nexport type AssistantHandlerResult =\n | { kind: 'message'; content: string }\n | { kind: 'tool_calls'; toolCalls: ToolCall[] };\n\n/**\n * Assistants v2 の tool_call — real API と同じ shape (function only)。\n * v0.1 は `type: 'function'` の 1 種のみ、 code_interpreter / file_search は v0.2 以降。\n */\nexport interface ToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n /** JSON string、 real API に整合。 */\n arguments: string;\n };\n}\n\n/** submit_tool_outputs で client が返す 1 tool 実行結果。 */\nexport interface ToolOutput {\n toolCallId: string;\n output: string;\n}\n\n/**\n * Run entity — real Assistants v2 の Run resource に対応。 v0.1 は mock なので\n * `created_at` / `expires_at` 等の unix ts は number epoch ms で近似する。\n */\nexport interface Run {\n id: string;\n threadId: string;\n assistantId: string;\n status: RunStatus;\n createdAt: number;\n completedAt?: number;\n failedAt?: number;\n /** requires_action 時に pending の tool_calls、 それ以外は undefined。 */\n requiredAction?: {\n type: 'submit_tool_outputs';\n toolCalls: ToolCall[];\n };\n /** failed 時のみ set、 real API の Run.last_error に整合。 */\n lastError?: {\n code: string;\n message: string;\n };\n}\n\n/** Assistant resource — real API と同じく id + name + instructions を保持。 */\nexport interface Assistant {\n id: string;\n name: string;\n instructions: string;\n createdAt: number;\n}\n\n/** Thread resource — id + createdAt + messages 配列。 */\nexport interface Thread {\n id: string;\n createdAt: number;\n messages: ThreadMessage[];\n}\n","import {\n END,\n START,\n type AgentState,\n type GraphEdge,\n type NodeHandler,\n} from './types.js';\n\n/**\n * Low-level state machine primitives — LangGraph 型 API (langgraph.ts) の\n * backing store。 `StateMachine` は node registry + edge registry + validation\n * + execution runner に責務分離、 langgraph.ts は SSOT 語彙 (StateGraph +\n * addNode + addEdge + compile) を wrapping する。\n *\n * ### 責務分離\n *\n * - `StateMachine` — node / edge の登録 + validate + 実行 (invoke / stream)\n * - `StateGraph` (langgraph.ts) — real LangGraph に整合した API + compile 語彙\n *\n * ### validate 項目 (compile 時 fail-fast)\n *\n * 1. START edge が最低 1 本存在する\n * 2. START edge の to が存在する node (or END)\n * 3. 全 edge の to が存在する node (or END)\n * 4. 全 edge の from が存在する node (or START)\n * 5. 全 node に out-edge が最低 1 本存在する (isolated node 検出)\n * 6. START edge は 1 本のみ (v0.1 は multi-entry 未対応)\n */\n\n/**\n * runtime cycle 検出 — 同一 node が 2 回以上 visit されたら循環と判定する。 real\n * LangGraph は cycle 許容だが (agent loop の中核)、 v0.1 mock は simplicity 優先で\n * 「visit 上限を突破したら halt + throw」 に倒す。 default 上限は 100 step。\n */\nexport const DEFAULT_MAX_STEPS = 100;\n\n/** invoke / stream 実行時 config。 */\nexport interface RunOptions {\n /** 最大 step 数、 突破したら `MaxStepsExceededError` を throw。 default 100。 */\n maxSteps?: number;\n}\n\n/** compile 失敗 error — validate 時に投げる。 */\nexport class GraphCompileError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'GraphCompileError';\n }\n}\n\n/** runtime 最大 step 突破 error。 */\nexport class MaxStepsExceededError extends Error {\n readonly steps: number;\n constructor(steps: number) {\n super(`state machine exceeded max steps: ${steps}`);\n this.name = 'MaxStepsExceededError';\n this.steps = steps;\n }\n}\n\n/**\n * StateMachine — pure state graph 実行 engine。 langgraph.ts の StateGraph が\n * 内部で使う。 直接叩くのも可 (低水準 API として export)。\n */\nexport class StateMachine<TState extends AgentState = AgentState> {\n private readonly nodes = new Map<string, NodeHandler<TState>>();\n private readonly edges: GraphEdge[] = [];\n private compiled = false;\n\n /** node を登録。 同名 node は上書きする。 */\n addNode(name: string, handler: NodeHandler<TState>): this {\n if (!name || name.trim() === '') {\n throw new GraphCompileError('node name must be a non-empty string');\n }\n if (name === START || name === END) {\n throw new GraphCompileError(`node name \"${name}\" is reserved`);\n }\n this.nodes.set(name, handler);\n this.compiled = false;\n return this;\n }\n\n /** edge を追加。 from / to は node 名 or START / END sentinel。 */\n addEdge(from: string, to: string): this {\n if (!from || !to) {\n throw new GraphCompileError('edge from/to must be non-empty strings');\n }\n this.edges.push({ from, to });\n this.compiled = false;\n return this;\n }\n\n /** node 数 (test / debug 用)。 */\n get nodeCount(): number {\n return this.nodes.size;\n }\n\n /** edge 数 (test / debug 用)。 */\n get edgeCount(): number {\n return this.edges.length;\n }\n\n /** compile 済かどうか (test / debug 用)。 */\n get isCompiled(): boolean {\n return this.compiled;\n }\n\n /**\n * validate + compile — validate 6 項目を fail-fast で確認、 pass なら\n * `compiled = true` を立てて invoke / stream 可能状態にする。\n */\n compile(): this {\n // (1) START edge の存在\n const startEdges = this.edges.filter((e) => e.from === START);\n if (startEdges.length === 0) {\n throw new GraphCompileError(\n 'graph has no START edge — addEdge(START, \"first_node\") is required',\n );\n }\n // (6) START edge は 1 本のみ\n if (startEdges.length > 1) {\n throw new GraphCompileError(\n `graph has ${startEdges.length} START edges — v0.1 supports only 1 entry`,\n );\n }\n // (2) START edge の to が存在する node (or END)\n const startTo = startEdges[0]!.to;\n if (startTo !== END && !this.nodes.has(startTo)) {\n throw new GraphCompileError(`START edge targets unknown node: ${startTo}`);\n }\n // (3) (4) (5) edge の endpoints validate + isolated node 検出\n const nodesWithOutEdge = new Set<string>();\n for (const edge of this.edges) {\n if (edge.from !== START && !this.nodes.has(edge.from)) {\n throw new GraphCompileError(`edge.from references unknown node: ${edge.from}`);\n }\n if (edge.to !== END && !this.nodes.has(edge.to)) {\n throw new GraphCompileError(`edge.to references unknown node: ${edge.to}`);\n }\n if (edge.from !== START) {\n nodesWithOutEdge.add(edge.from);\n }\n }\n for (const nodeName of this.nodes.keys()) {\n if (!nodesWithOutEdge.has(nodeName)) {\n throw new GraphCompileError(\n `node \"${nodeName}\" has no outgoing edge — every node must connect to at least END`,\n );\n }\n }\n this.compiled = true;\n return this;\n }\n\n /**\n * invoke — 初期 state から実行、 END に到達した final state を返す。 compile\n * 未実施なら throw。\n */\n async invoke(initialState: TState, options: RunOptions = {}): Promise<TState> {\n let last: TState = initialState;\n for await (const step of this.stream(initialState, options)) {\n last = step.state;\n }\n return last;\n }\n\n /**\n * stream — 各 node 実行後の {node, patch, state} を順次 yield。 END に到達した\n * 時点で generator は終了する。\n */\n async *stream(\n initialState: TState,\n options: RunOptions = {},\n ): AsyncGenerator<{ node: string; patch: Partial<TState>; state: TState }, void, void> {\n if (!this.compiled) {\n throw new GraphCompileError('state machine not compiled — call compile() before invoke/stream');\n }\n const maxSteps = options.maxSteps ?? DEFAULT_MAX_STEPS;\n let currentState: TState = { ...initialState };\n let currentNode: string | typeof END = this.startNode();\n let stepCount = 0;\n\n while (currentNode !== END) {\n stepCount += 1;\n if (stepCount > maxSteps) {\n throw new MaxStepsExceededError(stepCount);\n }\n const handler = this.nodes.get(currentNode);\n if (!handler) {\n // compile 済なら現実的には到達不可、 defensive。\n throw new GraphCompileError(`runtime: node not found: ${currentNode}`);\n }\n const patch = await handler(currentState);\n currentState = { ...currentState, ...patch };\n yield { node: currentNode, patch, state: currentState };\n\n const next = this.nextNode(currentNode);\n if (next === undefined) {\n throw new GraphCompileError(`runtime: no outgoing edge from node: ${currentNode}`);\n }\n currentNode = next;\n }\n }\n\n private startNode(): string | typeof END {\n const startEdge = this.edges.find((e) => e.from === START);\n // compile validate 済なら常に存在\n return startEdge!.to as string | typeof END;\n }\n\n private nextNode(from: string): string | typeof END | undefined {\n // v0.1 は unconditional edge のみ、 1 node = 1 out-edge を仮定する。\n // 複数 out-edge がある場合は最初の 1 本を採用 (v0.2 の conditional_edges で\n // proper 対応する)。\n const edge = this.edges.find((e) => e.from === from);\n return edge?.to as string | typeof END | undefined;\n }\n}\n","import {\n StateMachine,\n type RunOptions,\n} from './state-machine.js';\nimport {\n END,\n START,\n type AgentState,\n type GraphStep,\n type NodeHandler,\n} from './types.js';\n\n/**\n * LangGraph 型 API wrapper — real LangGraph (langchain-ai/langgraphjs) の\n * `StateGraph` に整合した SSOT 語彙で kiwa mock を提供する。 内部は\n * state-machine.ts の `StateMachine` を使う (2 layer 責務分離、 実装 SSOT は\n * state-machine.ts、 語彙 SSOT は本 file)。\n *\n * ### real LangGraph との対応表\n *\n * | real LangGraph API | kiwa mock 対応 |\n * |---|---|\n * | `new StateGraph(channels)` | `new StateGraph<TState>()` (v0.1 は channels 不要、 shallow merge) |\n * | `graph.addNode(name, fn)` | `graph.addNode(name, handler)` |\n * | `graph.addEdge(from, to)` | `graph.addEdge(from, to)` (unconditional edge) |\n * | `graph.setEntryPoint(name)` | `graph.addEdge(START, name)` に統一 |\n * | `graph.setFinishPoint(name)` | `graph.addEdge(name, END)` に統一 |\n * | `graph.compile()` | `graph.compile()` → `CompiledGraph` を返す |\n * | `compiled.invoke(state)` | `compiled.invoke(state)` |\n * | `compiled.stream(state)` | `compiled.stream(state)` async generator |\n *\n * ### 未対応 (v0.2 以降)\n *\n * - `addConditionalEdges(from, router, mapping)` — conditional routing\n * - `channels` の reducer (LastValue / Topic / Ephemeral)、 v0.1 は shallow merge default\n * - `interrupt` / `checkpointer` — human-in-the-loop + persist\n */\n\n/** START / END sentinel を re-export、 langgraph 使用側で 1 import で済むように。 */\nexport { END, START } from './types.js';\n\n/**\n * StateGraph builder — node / edge を組んで compile() で `CompiledGraph` を得る。\n * real LangGraph の `StateGraph` に対応。\n */\nexport class StateGraph<TState extends AgentState = AgentState> {\n private readonly machine = new StateMachine<TState>();\n\n /** node を追加。 handler は現 state から partial state を返す (同期 / 非同期両対応)。 */\n addNode(name: string, handler: NodeHandler<TState>): this {\n this.machine.addNode(name, handler);\n return this;\n }\n\n /**\n * edge を追加。 `from` は node 名 or `START`、 `to` は node 名 or `END`。\n * v0.1 は unconditional edge のみ (conditional_edges は v0.2)。\n */\n addEdge(from: string | typeof START, to: string | typeof END): this {\n this.machine.addEdge(from, to);\n return this;\n }\n\n /** compile + validate、 CompiledGraph を返す。 */\n compile(): CompiledGraph<TState> {\n this.machine.compile();\n return new CompiledGraph<TState>(this.machine);\n }\n\n /** node 数 (test / debug 用)。 */\n get nodeCount(): number {\n return this.machine.nodeCount;\n }\n\n /** edge 数 (test / debug 用)。 */\n get edgeCount(): number {\n return this.machine.edgeCount;\n }\n}\n\n/**\n * CompiledGraph — StateGraph.compile() 後の実行可能 graph。 real LangGraph の\n * compiled graph に対応、 invoke + stream の 2 実行モード。\n */\nexport class CompiledGraph<TState extends AgentState = AgentState> {\n constructor(private readonly machine: StateMachine<TState>) {}\n\n /**\n * invoke — 初期 state から実行し END 到達時の final state を返す。 中間 step\n * を捨てて final だけ欲しい場合の shortcut。\n */\n async invoke(initialState: TState, options?: RunOptions): Promise<TState> {\n return this.machine.invoke(initialState, options);\n }\n\n /**\n * stream — 各 node 実行後の GraphStep (node 名 + patch + merge 後 state) を\n * 順次 yield。 END 到達時点で generator 終了。 real LangGraph の `stream()`\n * (default mode = \"values\") に整合。\n */\n async *stream(\n initialState: TState,\n options?: RunOptions,\n ): AsyncGenerator<GraphStep<TState>, void, void> {\n for await (const step of this.machine.stream(initialState, options)) {\n yield step;\n }\n }\n}\n","import type {\n Assistant,\n AssistantHandler,\n AssistantHandlerResult,\n Run,\n RunStatus,\n Thread,\n ThreadMessage,\n ThreadMessageRole,\n ToolCall,\n ToolOutput,\n} from './types.js';\n\n/**\n * OpenAI Assistants v2 mock — real Assistants v2 API (openai.beta.assistants /\n * openai.beta.threads / openai.beta.threads.runs) の client 表面を kiwa test で\n * 再現するための in-process mock。 real API と同じ SSOT 用語 (Assistant / Thread /\n * Message / Run) を採用、 run status transition (queued → in_progress →\n * completed / failed / requires_action) を deterministic に model する。\n *\n * ### 対応 op (v0.1 対象)\n *\n * | op | 対応 |\n * |---|---|\n * | createAssistant | Assistant resource + id を発行 |\n * | createThread | Thread resource + id を発行、 初期 messages 受入れ可 |\n * | addMessage | 既存 Thread に user role message を append |\n * | createRun | Thread + Assistant を紐付けて Run resource (queued) を発行 |\n * | run.poll (retrieveRun) | 1 tick 進行、 status を deterministic に遷移 |\n * | submitToolOutputs | requires_action 中の Run に tool 実行結果を差し込む |\n * | cancel | in_progress / queued の Run を強制 cancelled 相当 (failed) にする |\n *\n * ### run status transition\n *\n * 1. `createRun()` → status = **queued**\n * 2. 1 回目の `poll()` → assistant handler を呼び、 結果が\n * - `{ kind: 'message' }` → status = **completed**、 message を thread に append\n * - `{ kind: 'tool_calls' }` → status = **requires_action**、 pending tool_calls を保持\n * - handler が throw → status = **failed**、 lastError を set\n * 3. **requires_action** 中に `submitToolOutputs()` → status = **queued** に戻り、\n * 次の `poll()` で handler が再度呼ばれる (context.toolOutputs で結果参照可能)。\n *\n * ### 未対応 (v0.2 以降)\n *\n * - Vector store / file_search / code_interpreter tool\n * - streaming (SSE) run event\n * - `assistant_message` の中間 tool_calls (real API では 1 run で複数 message が append される)、\n * v0.1 は 1 run = 1 assistant message として単純化\n */\n\n/** AssistantsClient config。 handler は必須 (registerHandler で後付けも可)。 */\nexport interface AssistantsClientConfig {\n /** id 生成の deterministic 化用 seed prefix (test の snapshot 用)、 default random。 */\n idSeed?: string;\n}\n\n/**\n * Assistants v2 client mock — real openai.beta.assistants の thin wrapper API。\n * assistant / thread / run resource を in-memory Map で保持、 id は seed 付き\n * incrementing で generate する。\n */\nexport class AssistantsClient {\n private readonly assistants = new Map<string, Assistant>();\n private readonly threads = new Map<string, Thread>();\n private readonly runs = new Map<string, Run>();\n private readonly handlers = new Map<string, AssistantHandler>();\n private nextId = 1;\n private readonly idSeed: string;\n\n constructor(config: AssistantsClientConfig = {}) {\n this.idSeed = config.idSeed ?? 'kiwa';\n }\n\n // ---- Assistant CRUD ------------------------------------------------\n\n /**\n * Assistant resource を発行。 real API と同じく id + name + instructions を持つ。\n * handler は必須ではないが、 createRun() までに registerHandler() で紐付け必要。\n */\n createAssistant(params: { name: string; instructions: string; handler?: AssistantHandler }): Assistant {\n const id = this.mintId('asst');\n const assistant: Assistant = {\n id,\n name: params.name,\n instructions: params.instructions,\n createdAt: Date.now(),\n };\n this.assistants.set(id, assistant);\n if (params.handler) {\n this.handlers.set(id, params.handler);\n }\n return assistant;\n }\n\n /**\n * assistant に handler を後付け登録。 test で「先に assistant を作って後で handler\n * を差し替える」 シナリオ (behavior injection) 用。\n */\n registerHandler(assistantId: string, handler: AssistantHandler): void {\n if (!this.assistants.has(assistantId)) {\n throw new Error(`unknown assistant id: ${assistantId}`);\n }\n this.handlers.set(assistantId, handler);\n }\n\n /** assistant 参照 (test / debug 用)。 */\n getAssistant(id: string): Assistant | undefined {\n return this.assistants.get(id);\n }\n\n // ---- Thread CRUD ---------------------------------------------------\n\n /**\n * Thread resource を発行。 初期 messages を渡すと user message として append される\n * (real API と同じ挙動)。\n */\n createThread(params: { messages?: Array<{ role: ThreadMessageRole; content: string }> } = {}): Thread {\n const id = this.mintId('thread');\n const thread: Thread = {\n id,\n createdAt: Date.now(),\n messages: [],\n };\n this.threads.set(id, thread);\n if (params.messages) {\n for (const m of params.messages) {\n this.addMessage(id, { role: m.role, content: m.content });\n }\n }\n return thread;\n }\n\n /**\n * Thread に message を append。 real API と同じく role は user / assistant、\n * v0.1 は tool role 未対応 (Assistants v2 の tool message は submitToolOutputs\n * 経路に統一)。\n */\n addMessage(threadId: string, params: { role: ThreadMessageRole; content: string }): ThreadMessage {\n const thread = this.threads.get(threadId);\n if (!thread) {\n throw new Error(`unknown thread id: ${threadId}`);\n }\n const message: ThreadMessage = {\n id: this.mintId('msg'),\n role: params.role,\n content: params.content,\n createdAt: Date.now(),\n };\n thread.messages.push(message);\n return message;\n }\n\n /** thread 参照 (test / debug 用、 messages は readonly view として返す)。 */\n getThread(id: string): Thread | undefined {\n return this.threads.get(id);\n }\n\n // ---- Run lifecycle -------------------------------------------------\n\n /**\n * Run 発行 — thread + assistant を紐付けた Run resource (queued) を返す。 実際の\n * assistant 実行は `poll(runId)` を呼び出した時に走る (real API の polling model と\n * 同構造、 real でも create 直後は queued で 1 tick 後に進行する)。\n */\n createRun(params: { threadId: string; assistantId: string }): Run {\n if (!this.threads.has(params.threadId)) {\n throw new Error(`unknown thread id: ${params.threadId}`);\n }\n if (!this.assistants.has(params.assistantId)) {\n throw new Error(`unknown assistant id: ${params.assistantId}`);\n }\n if (!this.handlers.has(params.assistantId)) {\n throw new Error(\n `assistant ${params.assistantId} has no handler registered — call registerHandler() first`,\n );\n }\n const id = this.mintId('run');\n const run: Run = {\n id,\n threadId: params.threadId,\n assistantId: params.assistantId,\n status: 'queued',\n createdAt: Date.now(),\n };\n this.runs.set(id, run);\n return run;\n }\n\n /**\n * poll — Run の 1 tick を進める。 real API polling は同じ retrieveRun で status\n * を確認する model、 mock は「poll 呼出 = 1 tick 進行」 と扱う。 呼出後の Run\n * (copy) を返す。 呼出前 status に応じて next status が deterministic に決まる。\n *\n * 1. queued → poll 1 回目で handler 呼出、 result に応じて completed / requires_action / failed\n * 2. in_progress → poll 呼出でも遷移しない (v0.1 は 1 tick = 1 handler 呼出 model、\n * in_progress は queued → completed の間の transient state として使用しない)、\n * そのまま返す。 実質 queued と completed / requires_action / failed の 3 状態が\n * caller に見える。\n * 3. requires_action → poll でも遷移しない (submitToolOutputs 待ち)\n * 4. completed / failed → 変化なし、 そのまま返す\n */\n async poll(runId: string): Promise<Run> {\n const run = this.runs.get(runId);\n if (!run) {\n throw new Error(`unknown run id: ${runId}`);\n }\n if (run.status !== 'queued') {\n return { ...run };\n }\n return this.executeRun(run);\n }\n\n /**\n * pollUntilFinal — completed / failed / requires_action に到達するまで poll を\n * 繰り返す utility。 requires_action は「final ではない」 が「client 側 action 待ち」\n * なので、 これも終端扱いで返す (client 側で submitToolOutputs → 再度 pollUntilFinal\n * を呼ぶ想定)。 real API では intervalMs で backoff するが、 mock は同期実行のため\n * poll = 1 tick 進行 model で maxAttempts のみ意味を持つ。\n */\n async pollUntilFinal(runId: string, options: { maxAttempts?: number } = {}): Promise<Run> {\n const maxAttempts = options.maxAttempts ?? 20;\n let attempts = 0;\n let run = await this.poll(runId);\n while (run.status === 'queued' || run.status === 'in_progress') {\n attempts += 1;\n if (attempts > maxAttempts) {\n throw new Error(`pollUntilFinal exceeded ${maxAttempts} attempts for run ${runId}`);\n }\n run = await this.poll(runId);\n }\n return run;\n }\n\n /**\n * submitToolOutputs — requires_action 中の Run に tool 実行結果を差し込む。 status\n * を queued に戻し、 次 poll で handler が再度呼び出される (context.toolOutputs\n * で結果参照可能)。 real API と同じ semantic。\n */\n submitToolOutputs(runId: string, params: { toolOutputs: ToolOutput[] }): Run {\n const run = this.runs.get(runId);\n if (!run) {\n throw new Error(`unknown run id: ${runId}`);\n }\n if (run.status !== 'requires_action') {\n throw new Error(\n `run ${runId} is not requires_action (current: ${run.status}), cannot submit tool outputs`,\n );\n }\n // 次 poll 時に context.toolOutputs で参照するため run 内に一時保持する。\n // requiredAction を消し queued に戻す (exactOptionalPropertyTypes 準拠のため\n // property 自体を落とす)。\n const { requiredAction: _dropped, ...rest } = run;\n void _dropped;\n const updated: Run = {\n ...rest,\n status: 'queued',\n };\n this.runs.set(runId, updated);\n this.pendingToolOutputs.set(runId, params.toolOutputs);\n return { ...updated };\n }\n\n /**\n * cancel — queued / in_progress の Run を強制終了させる。 status は failed に倒す\n * (real API は cancelled status を持つが v0.1 は failed に統合、 lastError.code =\n * 'cancelled' で識別可能)。\n */\n cancel(runId: string): Run {\n const run = this.runs.get(runId);\n if (!run) {\n throw new Error(`unknown run id: ${runId}`);\n }\n if (run.status === 'completed' || run.status === 'failed') {\n return { ...run };\n }\n const { requiredAction: _dropped, ...rest } = run;\n void _dropped;\n const updated: Run = {\n ...rest,\n status: 'failed',\n failedAt: Date.now(),\n lastError: { code: 'cancelled', message: 'run cancelled by client' },\n };\n this.runs.set(runId, updated);\n return { ...updated };\n }\n\n /** run 参照 (test / debug 用)。 */\n getRun(id: string): Run | undefined {\n const run = this.runs.get(id);\n return run ? { ...run } : undefined;\n }\n\n // ---- internal helpers ----------------------------------------------\n\n private readonly pendingToolOutputs = new Map<string, readonly ToolOutput[]>();\n\n private async executeRun(run: Run): Promise<Run> {\n const thread = this.threads.get(run.threadId);\n const handler = this.handlers.get(run.assistantId);\n if (!thread || !handler) {\n // registerHandler / createThread validate 済なので defensive。\n throw new Error(`run ${run.id} references missing thread or handler`);\n }\n const toolOutputs = this.pendingToolOutputs.get(run.id);\n let result: AssistantHandlerResult;\n try {\n const ctx =\n toolOutputs !== undefined\n ? {\n thread: [...thread.messages],\n runId: run.id,\n assistantId: run.assistantId,\n toolOutputs,\n }\n : {\n thread: [...thread.messages],\n runId: run.id,\n assistantId: run.assistantId,\n };\n result = await handler(ctx);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const updated: Run = {\n ...run,\n status: 'failed',\n failedAt: Date.now(),\n lastError: { code: 'handler_error', message },\n };\n this.runs.set(run.id, updated);\n this.pendingToolOutputs.delete(run.id);\n return { ...updated };\n }\n this.pendingToolOutputs.delete(run.id);\n if (result.kind === 'message') {\n // assistant message を thread に append。\n this.addMessage(run.threadId, { role: 'assistant', content: result.content });\n const updated: Run = {\n ...run,\n status: 'completed',\n completedAt: Date.now(),\n };\n this.runs.set(run.id, updated);\n return { ...updated };\n }\n // tool_calls 分岐 = requires_action\n const updated: Run = {\n ...run,\n status: 'requires_action',\n requiredAction: { type: 'submit_tool_outputs', toolCalls: result.toolCalls },\n };\n this.runs.set(run.id, updated);\n return { ...updated };\n }\n\n private mintId(kind: string): string {\n const id = `${this.idSeed}_${kind}_${this.nextId}`;\n this.nextId += 1;\n return id;\n }\n}\n\n/**\n * ToolCall builder shortcut — test で `{ id, type: 'function', function: { name, arguments: JSON } }`\n * を書くのは冗長なので helper を出す。\n */\nexport function toolCall(params: {\n id: string;\n name: string;\n arguments: Record<string, unknown>;\n}): ToolCall {\n return {\n id: params.id,\n type: 'function',\n function: {\n name: params.name,\n arguments: JSON.stringify(params.arguments),\n },\n };\n}\n\n/** RunStatus SSOT re-export (client 側で 1 import で status literal を扱える)。 */\nexport type { RunStatus };\n"],"mappings":"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","names":["updated"]}
@@ -0,0 +1,437 @@
1
+ /**
2
+ * Agent orchestration mock — 2 系統 (LangGraph 型 state machine + OpenAI Assistants v2)
3
+ * を 1 統一 API で扱う。 real LangGraph は Python + TS の 2 SDK があり、
4
+ * StateGraph(addNode + addEdge + compile → invoke / stream) が中核。
5
+ * real OpenAI Assistants v2 は Thread + Run + Message + polling が中核で、
6
+ * run status が queued → in_progress → completed / failed / requires_action の
7
+ * 5 状態を遷移する。
8
+ *
9
+ * ### 対応する mock 表現 (v1.15-3 対象)
10
+ *
11
+ * 1. **LangGraph 型 state machine** — `StateGraph` で node + edge を組み、
12
+ * `compile()` で `CompiledGraph` を得て、 `invoke(initialState)` で最終 state を、
13
+ * `stream(initialState)` で 中間 state を順次得る。
14
+ * 2. **OpenAI Assistants v2** — `AssistantsClient` で `createAssistant` /
15
+ * `createThread` / `addMessage` / `createRun` / `run.poll` を実行、 run status を
16
+ * 決定的に遷移させる。
17
+ *
18
+ * ### 対応しない (v0.2 以降)
19
+ *
20
+ * - Vector store / file 系 (Assistants v2 の `file_search` tool)
21
+ * - real streaming API (SSE / websocket) — mock は同期的 stream generator
22
+ * - LangGraph の `conditional_edges` / `interrupt` — v0.1 は addEdge + END の 2 辺のみ
23
+ */
24
+ /**
25
+ * 状態を持つ graph node の generic state 型。 実 test では project 側で narrow する。
26
+ * shape は `object` に緩めて index signature 要求を避ける (real LangGraph も any-typed
27
+ * TypedDict を許容する)。 handler / stream の内部で `{ ...state, ...patch }` で shallow
28
+ * merge するため、 実質的な shape 制約は各 project 側の TState で narrow される。
29
+ */
30
+ type AgentState = object;
31
+ /** Node handler — 現 state を受け取り、 更新分 (partial state) を返す。 同期 or 非同期。 */
32
+ type NodeHandler<TState extends AgentState = AgentState> = (state: TState) => Partial<TState> | Promise<Partial<TState>>;
33
+ /** END sentinel — graph の終端を示す reserved node name。 real LangGraph の `END` に対応。 */
34
+ declare const END: "__end__";
35
+ type EndNode = typeof END;
36
+ /** START sentinel — graph の起点を示す reserved node name。 real LangGraph の `START` に対応。 */
37
+ declare const START: "__start__";
38
+ type StartNode = typeof START;
39
+ /**
40
+ * Graph edge — `from` node の実行後に `to` node を実行する矢印。 `to === END`
41
+ * で graph 終了。 v0.1 は unconditional edge のみ、 `conditional_edges` は v0.2 以降。
42
+ */
43
+ interface GraphEdge {
44
+ from: string | StartNode;
45
+ to: string | EndNode;
46
+ }
47
+ /** 1 step の実行 trace — stream / debug 用。 */
48
+ interface GraphStep<TState extends AgentState = AgentState> {
49
+ /** 実行した node 名。 START edge の直後は最初の node 名。 */
50
+ node: string;
51
+ /** node handler が返した partial state (merge 前)。 */
52
+ patch: Partial<TState>;
53
+ /** patch merge 後の state。 */
54
+ state: TState;
55
+ }
56
+ /**
57
+ * OpenAI Assistants v2 の Message role — real API に整合。 v0.1 は user + assistant
58
+ * の 2 種、 tool_message は v0.2 以降。
59
+ */
60
+ type ThreadMessageRole = 'user' | 'assistant';
61
+ /** Thread message — real Assistants v2 の Message resource に対応。 */
62
+ interface ThreadMessage {
63
+ id: string;
64
+ role: ThreadMessageRole;
65
+ content: string;
66
+ createdAt: number;
67
+ }
68
+ /**
69
+ * Assistants v2 の Run status SSOT — real API と同じ 5 状態。 v0.1 mock は
70
+ * queued → in_progress → completed / failed / requires_action の deterministic
71
+ * transition を model する。
72
+ *
73
+ * | status | 意味 |
74
+ * |---|---|
75
+ * | queued | createRun 直後、 まだ polling で 1 回も進んでいない |
76
+ * | in_progress | polling 1 回で queued から遷移、 assistant が work 中 |
77
+ * | completed | assistant が response 生成完了、 final message が thread に append 済 |
78
+ * | failed | handler が throw、 final error は run.lastError に格納 |
79
+ * | requires_action | tool_calls が pending、 submit_tool_outputs で解除 |
80
+ */
81
+ type RunStatus = 'queued' | 'in_progress' | 'completed' | 'failed' | 'requires_action';
82
+ /**
83
+ * Assistant handler — 1 run で assistant が「thread 履歴を見て次の action を決める」
84
+ * 1 step 分の logic。 return が string なら completed で assistant message として append、
85
+ * return が `{ toolCalls }` なら requires_action に遷移して pending tool_calls を保持。
86
+ */
87
+ type AssistantHandler = (ctx: AssistantHandlerContext) => Promise<AssistantHandlerResult> | AssistantHandlerResult;
88
+ /** handler に渡す context — thread 履歴 + 現在の run。 */
89
+ interface AssistantHandlerContext {
90
+ thread: readonly ThreadMessage[];
91
+ runId: string;
92
+ assistantId: string;
93
+ /**
94
+ * 前 step の tool 実行結果 (submit_tool_outputs で受け取ったもの)、 requires_action
95
+ * を解除した直後の再呼出でのみ set される。 それ以外は undefined。
96
+ */
97
+ toolOutputs?: readonly ToolOutput[];
98
+ }
99
+ /** handler が返す result — completed か requires_action の 2 種。 */
100
+ type AssistantHandlerResult = {
101
+ kind: 'message';
102
+ content: string;
103
+ } | {
104
+ kind: 'tool_calls';
105
+ toolCalls: ToolCall[];
106
+ };
107
+ /**
108
+ * Assistants v2 の tool_call — real API と同じ shape (function only)。
109
+ * v0.1 は `type: 'function'` の 1 種のみ、 code_interpreter / file_search は v0.2 以降。
110
+ */
111
+ interface ToolCall {
112
+ id: string;
113
+ type: 'function';
114
+ function: {
115
+ name: string;
116
+ /** JSON string、 real API に整合。 */
117
+ arguments: string;
118
+ };
119
+ }
120
+ /** submit_tool_outputs で client が返す 1 tool 実行結果。 */
121
+ interface ToolOutput {
122
+ toolCallId: string;
123
+ output: string;
124
+ }
125
+ /**
126
+ * Run entity — real Assistants v2 の Run resource に対応。 v0.1 は mock なので
127
+ * `created_at` / `expires_at` 等の unix ts は number epoch ms で近似する。
128
+ */
129
+ interface Run {
130
+ id: string;
131
+ threadId: string;
132
+ assistantId: string;
133
+ status: RunStatus;
134
+ createdAt: number;
135
+ completedAt?: number;
136
+ failedAt?: number;
137
+ /** requires_action 時に pending の tool_calls、 それ以外は undefined。 */
138
+ requiredAction?: {
139
+ type: 'submit_tool_outputs';
140
+ toolCalls: ToolCall[];
141
+ };
142
+ /** failed 時のみ set、 real API の Run.last_error に整合。 */
143
+ lastError?: {
144
+ code: string;
145
+ message: string;
146
+ };
147
+ }
148
+ /** Assistant resource — real API と同じく id + name + instructions を保持。 */
149
+ interface Assistant {
150
+ id: string;
151
+ name: string;
152
+ instructions: string;
153
+ createdAt: number;
154
+ }
155
+ /** Thread resource — id + createdAt + messages 配列。 */
156
+ interface Thread {
157
+ id: string;
158
+ createdAt: number;
159
+ messages: ThreadMessage[];
160
+ }
161
+
162
+ /**
163
+ * Low-level state machine primitives — LangGraph 型 API (langgraph.ts) の
164
+ * backing store。 `StateMachine` は node registry + edge registry + validation
165
+ * + execution runner に責務分離、 langgraph.ts は SSOT 語彙 (StateGraph +
166
+ * addNode + addEdge + compile) を wrapping する。
167
+ *
168
+ * ### 責務分離
169
+ *
170
+ * - `StateMachine` — node / edge の登録 + validate + 実行 (invoke / stream)
171
+ * - `StateGraph` (langgraph.ts) — real LangGraph に整合した API + compile 語彙
172
+ *
173
+ * ### validate 項目 (compile 時 fail-fast)
174
+ *
175
+ * 1. START edge が最低 1 本存在する
176
+ * 2. START edge の to が存在する node (or END)
177
+ * 3. 全 edge の to が存在する node (or END)
178
+ * 4. 全 edge の from が存在する node (or START)
179
+ * 5. 全 node に out-edge が最低 1 本存在する (isolated node 検出)
180
+ * 6. START edge は 1 本のみ (v0.1 は multi-entry 未対応)
181
+ */
182
+ /**
183
+ * runtime cycle 検出 — 同一 node が 2 回以上 visit されたら循環と判定する。 real
184
+ * LangGraph は cycle 許容だが (agent loop の中核)、 v0.1 mock は simplicity 優先で
185
+ * 「visit 上限を突破したら halt + throw」 に倒す。 default 上限は 100 step。
186
+ */
187
+ declare const DEFAULT_MAX_STEPS = 100;
188
+ /** invoke / stream 実行時 config。 */
189
+ interface RunOptions {
190
+ /** 最大 step 数、 突破したら `MaxStepsExceededError` を throw。 default 100。 */
191
+ maxSteps?: number;
192
+ }
193
+ /** compile 失敗 error — validate 時に投げる。 */
194
+ declare class GraphCompileError extends Error {
195
+ constructor(message: string);
196
+ }
197
+ /** runtime 最大 step 突破 error。 */
198
+ declare class MaxStepsExceededError extends Error {
199
+ readonly steps: number;
200
+ constructor(steps: number);
201
+ }
202
+ /**
203
+ * StateMachine — pure state graph 実行 engine。 langgraph.ts の StateGraph が
204
+ * 内部で使う。 直接叩くのも可 (低水準 API として export)。
205
+ */
206
+ declare class StateMachine<TState extends AgentState = AgentState> {
207
+ private readonly nodes;
208
+ private readonly edges;
209
+ private compiled;
210
+ /** node を登録。 同名 node は上書きする。 */
211
+ addNode(name: string, handler: NodeHandler<TState>): this;
212
+ /** edge を追加。 from / to は node 名 or START / END sentinel。 */
213
+ addEdge(from: string, to: string): this;
214
+ /** node 数 (test / debug 用)。 */
215
+ get nodeCount(): number;
216
+ /** edge 数 (test / debug 用)。 */
217
+ get edgeCount(): number;
218
+ /** compile 済かどうか (test / debug 用)。 */
219
+ get isCompiled(): boolean;
220
+ /**
221
+ * validate + compile — validate 6 項目を fail-fast で確認、 pass なら
222
+ * `compiled = true` を立てて invoke / stream 可能状態にする。
223
+ */
224
+ compile(): this;
225
+ /**
226
+ * invoke — 初期 state から実行、 END に到達した final state を返す。 compile
227
+ * 未実施なら throw。
228
+ */
229
+ invoke(initialState: TState, options?: RunOptions): Promise<TState>;
230
+ /**
231
+ * stream — 各 node 実行後の {node, patch, state} を順次 yield。 END に到達した
232
+ * 時点で generator は終了する。
233
+ */
234
+ stream(initialState: TState, options?: RunOptions): AsyncGenerator<{
235
+ node: string;
236
+ patch: Partial<TState>;
237
+ state: TState;
238
+ }, void, void>;
239
+ private startNode;
240
+ private nextNode;
241
+ }
242
+
243
+ /**
244
+ * StateGraph builder — node / edge を組んで compile() で `CompiledGraph` を得る。
245
+ * real LangGraph の `StateGraph` に対応。
246
+ */
247
+ declare class StateGraph<TState extends AgentState = AgentState> {
248
+ private readonly machine;
249
+ /** node を追加。 handler は現 state から partial state を返す (同期 / 非同期両対応)。 */
250
+ addNode(name: string, handler: NodeHandler<TState>): this;
251
+ /**
252
+ * edge を追加。 `from` は node 名 or `START`、 `to` は node 名 or `END`。
253
+ * v0.1 は unconditional edge のみ (conditional_edges は v0.2)。
254
+ */
255
+ addEdge(from: string | typeof START, to: string | typeof END): this;
256
+ /** compile + validate、 CompiledGraph を返す。 */
257
+ compile(): CompiledGraph<TState>;
258
+ /** node 数 (test / debug 用)。 */
259
+ get nodeCount(): number;
260
+ /** edge 数 (test / debug 用)。 */
261
+ get edgeCount(): number;
262
+ }
263
+ /**
264
+ * CompiledGraph — StateGraph.compile() 後の実行可能 graph。 real LangGraph の
265
+ * compiled graph に対応、 invoke + stream の 2 実行モード。
266
+ */
267
+ declare class CompiledGraph<TState extends AgentState = AgentState> {
268
+ private readonly machine;
269
+ constructor(machine: StateMachine<TState>);
270
+ /**
271
+ * invoke — 初期 state から実行し END 到達時の final state を返す。 中間 step
272
+ * を捨てて final だけ欲しい場合の shortcut。
273
+ */
274
+ invoke(initialState: TState, options?: RunOptions): Promise<TState>;
275
+ /**
276
+ * stream — 各 node 実行後の GraphStep (node 名 + patch + merge 後 state) を
277
+ * 順次 yield。 END 到達時点で generator 終了。 real LangGraph の `stream()`
278
+ * (default mode = "values") に整合。
279
+ */
280
+ stream(initialState: TState, options?: RunOptions): AsyncGenerator<GraphStep<TState>, void, void>;
281
+ }
282
+
283
+ /**
284
+ * OpenAI Assistants v2 mock — real Assistants v2 API (openai.beta.assistants /
285
+ * openai.beta.threads / openai.beta.threads.runs) の client 表面を kiwa test で
286
+ * 再現するための in-process mock。 real API と同じ SSOT 用語 (Assistant / Thread /
287
+ * Message / Run) を採用、 run status transition (queued → in_progress →
288
+ * completed / failed / requires_action) を deterministic に model する。
289
+ *
290
+ * ### 対応 op (v0.1 対象)
291
+ *
292
+ * | op | 対応 |
293
+ * |---|---|
294
+ * | createAssistant | Assistant resource + id を発行 |
295
+ * | createThread | Thread resource + id を発行、 初期 messages 受入れ可 |
296
+ * | addMessage | 既存 Thread に user role message を append |
297
+ * | createRun | Thread + Assistant を紐付けて Run resource (queued) を発行 |
298
+ * | run.poll (retrieveRun) | 1 tick 進行、 status を deterministic に遷移 |
299
+ * | submitToolOutputs | requires_action 中の Run に tool 実行結果を差し込む |
300
+ * | cancel | in_progress / queued の Run を強制 cancelled 相当 (failed) にする |
301
+ *
302
+ * ### run status transition
303
+ *
304
+ * 1. `createRun()` → status = **queued**
305
+ * 2. 1 回目の `poll()` → assistant handler を呼び、 結果が
306
+ * - `{ kind: 'message' }` → status = **completed**、 message を thread に append
307
+ * - `{ kind: 'tool_calls' }` → status = **requires_action**、 pending tool_calls を保持
308
+ * - handler が throw → status = **failed**、 lastError を set
309
+ * 3. **requires_action** 中に `submitToolOutputs()` → status = **queued** に戻り、
310
+ * 次の `poll()` で handler が再度呼ばれる (context.toolOutputs で結果参照可能)。
311
+ *
312
+ * ### 未対応 (v0.2 以降)
313
+ *
314
+ * - Vector store / file_search / code_interpreter tool
315
+ * - streaming (SSE) run event
316
+ * - `assistant_message` の中間 tool_calls (real API では 1 run で複数 message が append される)、
317
+ * v0.1 は 1 run = 1 assistant message として単純化
318
+ */
319
+ /** AssistantsClient config。 handler は必須 (registerHandler で後付けも可)。 */
320
+ interface AssistantsClientConfig {
321
+ /** id 生成の deterministic 化用 seed prefix (test の snapshot 用)、 default random。 */
322
+ idSeed?: string;
323
+ }
324
+ /**
325
+ * Assistants v2 client mock — real openai.beta.assistants の thin wrapper API。
326
+ * assistant / thread / run resource を in-memory Map で保持、 id は seed 付き
327
+ * incrementing で generate する。
328
+ */
329
+ declare class AssistantsClient {
330
+ private readonly assistants;
331
+ private readonly threads;
332
+ private readonly runs;
333
+ private readonly handlers;
334
+ private nextId;
335
+ private readonly idSeed;
336
+ constructor(config?: AssistantsClientConfig);
337
+ /**
338
+ * Assistant resource を発行。 real API と同じく id + name + instructions を持つ。
339
+ * handler は必須ではないが、 createRun() までに registerHandler() で紐付け必要。
340
+ */
341
+ createAssistant(params: {
342
+ name: string;
343
+ instructions: string;
344
+ handler?: AssistantHandler;
345
+ }): Assistant;
346
+ /**
347
+ * assistant に handler を後付け登録。 test で「先に assistant を作って後で handler
348
+ * を差し替える」 シナリオ (behavior injection) 用。
349
+ */
350
+ registerHandler(assistantId: string, handler: AssistantHandler): void;
351
+ /** assistant 参照 (test / debug 用)。 */
352
+ getAssistant(id: string): Assistant | undefined;
353
+ /**
354
+ * Thread resource を発行。 初期 messages を渡すと user message として append される
355
+ * (real API と同じ挙動)。
356
+ */
357
+ createThread(params?: {
358
+ messages?: Array<{
359
+ role: ThreadMessageRole;
360
+ content: string;
361
+ }>;
362
+ }): Thread;
363
+ /**
364
+ * Thread に message を append。 real API と同じく role は user / assistant、
365
+ * v0.1 は tool role 未対応 (Assistants v2 の tool message は submitToolOutputs
366
+ * 経路に統一)。
367
+ */
368
+ addMessage(threadId: string, params: {
369
+ role: ThreadMessageRole;
370
+ content: string;
371
+ }): ThreadMessage;
372
+ /** thread 参照 (test / debug 用、 messages は readonly view として返す)。 */
373
+ getThread(id: string): Thread | undefined;
374
+ /**
375
+ * Run 発行 — thread + assistant を紐付けた Run resource (queued) を返す。 実際の
376
+ * assistant 実行は `poll(runId)` を呼び出した時に走る (real API の polling model と
377
+ * 同構造、 real でも create 直後は queued で 1 tick 後に進行する)。
378
+ */
379
+ createRun(params: {
380
+ threadId: string;
381
+ assistantId: string;
382
+ }): Run;
383
+ /**
384
+ * poll — Run の 1 tick を進める。 real API polling は同じ retrieveRun で status
385
+ * を確認する model、 mock は「poll 呼出 = 1 tick 進行」 と扱う。 呼出後の Run
386
+ * (copy) を返す。 呼出前 status に応じて next status が deterministic に決まる。
387
+ *
388
+ * 1. queued → poll 1 回目で handler 呼出、 result に応じて completed / requires_action / failed
389
+ * 2. in_progress → poll 呼出でも遷移しない (v0.1 は 1 tick = 1 handler 呼出 model、
390
+ * in_progress は queued → completed の間の transient state として使用しない)、
391
+ * そのまま返す。 実質 queued と completed / requires_action / failed の 3 状態が
392
+ * caller に見える。
393
+ * 3. requires_action → poll でも遷移しない (submitToolOutputs 待ち)
394
+ * 4. completed / failed → 変化なし、 そのまま返す
395
+ */
396
+ poll(runId: string): Promise<Run>;
397
+ /**
398
+ * pollUntilFinal — completed / failed / requires_action に到達するまで poll を
399
+ * 繰り返す utility。 requires_action は「final ではない」 が「client 側 action 待ち」
400
+ * なので、 これも終端扱いで返す (client 側で submitToolOutputs → 再度 pollUntilFinal
401
+ * を呼ぶ想定)。 real API では intervalMs で backoff するが、 mock は同期実行のため
402
+ * poll = 1 tick 進行 model で maxAttempts のみ意味を持つ。
403
+ */
404
+ pollUntilFinal(runId: string, options?: {
405
+ maxAttempts?: number;
406
+ }): Promise<Run>;
407
+ /**
408
+ * submitToolOutputs — requires_action 中の Run に tool 実行結果を差し込む。 status
409
+ * を queued に戻し、 次 poll で handler が再度呼び出される (context.toolOutputs
410
+ * で結果参照可能)。 real API と同じ semantic。
411
+ */
412
+ submitToolOutputs(runId: string, params: {
413
+ toolOutputs: ToolOutput[];
414
+ }): Run;
415
+ /**
416
+ * cancel — queued / in_progress の Run を強制終了させる。 status は failed に倒す
417
+ * (real API は cancelled status を持つが v0.1 は failed に統合、 lastError.code =
418
+ * 'cancelled' で識別可能)。
419
+ */
420
+ cancel(runId: string): Run;
421
+ /** run 参照 (test / debug 用)。 */
422
+ getRun(id: string): Run | undefined;
423
+ private readonly pendingToolOutputs;
424
+ private executeRun;
425
+ private mintId;
426
+ }
427
+ /**
428
+ * ToolCall builder shortcut — test で `{ id, type: 'function', function: { name, arguments: JSON } }`
429
+ * を書くのは冗長なので helper を出す。
430
+ */
431
+ declare function toolCall(params: {
432
+ id: string;
433
+ name: string;
434
+ arguments: Record<string, unknown>;
435
+ }): ToolCall;
436
+
437
+ export { type AgentState, type Assistant, type AssistantHandler, type AssistantHandlerContext, type AssistantHandlerResult, AssistantsClient, type AssistantsClientConfig, CompiledGraph, DEFAULT_MAX_STEPS, END, type EndNode, GraphCompileError, type GraphEdge, type GraphStep, MaxStepsExceededError, type NodeHandler, type Run, type RunOptions, type RunStatus, START, type StartNode, StateGraph, StateMachine, type Thread, type ThreadMessage, type ThreadMessageRole, type ToolCall, type ToolOutput, toolCall };