{"version":3,"sources":["../../src/voice/tool_executor.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport { z } from 'zod';\nimport type { ChatContext, FunctionCallOutput } from '../llm/chat_context.js';\nimport { FunctionCall } from '../llm/chat_context.js';\nimport {\n  CONFIRM_DUPLICATE_PARAM,\n  type DuplicateMode,\n  type FunctionTool,\n  type JSONObject,\n  type ToolContextEntry,\n  ToolError,\n  ToolFlag,\n  Toolset,\n  isFunctionTool,\n  tool,\n} from '../llm/tool_context.js';\nimport { log } from '../log.js';\nimport { Future } from '../utils.js';\nimport type { AgentSession } from './agent_session.js';\nimport type { PromptTemplate, RunContext, UpdatePromptArgs } from './run_context.js';\n\n// Upper bound on how long `drain()` waits for in-flight tool promises to settle\n// after the executor has signalled abort.\nconst DRAIN_TOOL_TIMEOUT_MS = Number(process.env.LK_DRAIN_PLAYOUT_TIMEOUT_MS) || 5_000;\n\nexport interface DuplicatePromptArgs {\n  functionName: string;\n  functionCallsJson: string[];\n  functionCallsText: string;\n}\n\nexport interface ReplyPromptArgs {\n  callIds: string[];\n}\n\nexport interface AsyncToolOptions {\n  updateTemplate: PromptTemplate<UpdatePromptArgs>;\n  duplicateRejectTemplate: PromptTemplate<DuplicatePromptArgs>;\n  duplicateConfirmTemplate: PromptTemplate<DuplicatePromptArgs>;\n  replyAtTailTemplate: PromptTemplate<ReplyPromptArgs>;\n  replyMaybeCoveredTemplate: PromptTemplate<ReplyPromptArgs>;\n}\n\nexport interface ToolHandlingOptions {\n  asyncOptions?: Partial<AsyncToolOptions>;\n}\n\nexport const UPDATE_TEMPLATE =\n  'The tool `{functionName}` has updated, message: {message}\\n' +\n  \"The task is still running, so DON'T make up or give information not included in the message above.\";\n\nexport const DUPLICATE_REJECT =\n  'Same tool `{functionName}` is already running:\\n' +\n  '{functionCallsText}\\n' +\n  'If you want to cancel the existing one, call `lk_agents_cancel_task` with call_id.';\n\nexport const DUPLICATE_CONFIRM =\n  'Same tool `{functionName}` is already running:\\n' +\n  '{functionCallsText}\\n' +\n  'Re-call with confirm duplicate True to run a duplicate if needed,\\n' +\n  'or if you want to cancel the existing one, call `lk_agents_cancel_task` with call_id.';\n\nexport const REPLY_INSTRUCTIONS_AT_TAIL =\n  'New results arrived from background tool calls (call_ids: {callIds}).\\n' +\n  'Summarize the results naturally. Do NOT repeat information you have already told the user.';\n\nexport const REPLY_INSTRUCTIONS_MAYBE_COVERED =\n  'New results arrived from background tool calls (call_ids: {callIds}).\\n' +\n  'You may have already mentioned them in your most recent replies.\\n' +\n  'If you already told the user everything in these results, reply with an empty response (no text at all).\\n' +\n  'Otherwise, summarize only what you have not said yet, with a natural transition.\\n' +\n  'Never repeat information you have already told the user.';\n\nexport function resolveAsyncToolOptions(options?: Partial<AsyncToolOptions>): AsyncToolOptions {\n  return {\n    updateTemplate: options?.updateTemplate ?? UPDATE_TEMPLATE,\n    duplicateRejectTemplate: options?.duplicateRejectTemplate ?? DUPLICATE_REJECT,\n    duplicateConfirmTemplate: options?.duplicateConfirmTemplate ?? DUPLICATE_CONFIRM,\n    replyAtTailTemplate: options?.replyAtTailTemplate ?? REPLY_INSTRUCTIONS_AT_TAIL,\n    replyMaybeCoveredTemplate:\n      options?.replyMaybeCoveredTemplate ?? REPLY_INSTRUCTIONS_MAYBE_COVERED,\n  };\n}\n\nexport function renderTemplate<Args extends Record<string, unknown>>(\n  template: PromptTemplate<Args>,\n  args: Args,\n): string {\n  if (typeof template === 'function') return template(args);\n  return Object.entries(args).reduce(\n    (result, [key, value]) => result.replaceAll(`{${key}}`, String(value)),\n    template,\n  );\n}\n\ntype ToolExecutorAgent = {\n  chatCtx: ChatContext;\n  updateChatCtx(chatCtx: ChatContext): Promise<void> | void;\n};\n\ntype ToolExecutorActivity = {\n  agent: ToolExecutorAgent;\n  waitForIdle(): Promise<void>;\n};\n\ntype RunningTask = {\n  ctx: RunContext<any>;\n  promise: Promise<void>;\n  controller: AbortController;\n  firstUpdateFuture: Future<unknown>;\n  executor: ToolExecutor;\n  attachment: object;\n  allowCancellation: boolean;\n  // Guarded handle to the raw user `execute()` promise (never rejects). `drain()`\n  // waits on this to detect tools that keep running after being aborted.\n  toolPromiseRef: { promise?: Promise<unknown> };\n};\n\ntype PendingUpdate = {\n  ctx: RunContext<any>;\n  items: [FunctionCall, FunctionCallOutput];\n  target: ToolExecutorAgent;\n};\n\nconst runningTasks = new WeakMap<AgentSession<any>, Map<string, RunningTask>>();\n\nexport const getRunningTasksTool = tool({\n  name: 'lk_agents_get_running_tasks',\n  description: 'Get the list of running tool calls that are cancellable.',\n  execute: async (_, { ctx }) =>\n    _getCancellableRunningTasks(ctx.session).map((call) => call.toJSON(true)),\n});\n\nexport const cancelTaskTool = tool({\n  name: 'lk_agents_cancel_task',\n  description: 'Cancel a running tool call by call_id.',\n  parameters: z.object({\n    call_id: z.string(),\n  }),\n  execute: async ({ call_id }, { ctx }) => {\n    const task = runningTasks.get(ctx.session)?.get(call_id);\n    if (!task) {\n      throw new ToolError(`Task ${call_id} not found`);\n    }\n    const cancelled = await task.executor.cancel(call_id);\n    if (!cancelled) {\n      throw new ToolError(`Task ${call_id} not found or already completed`);\n    }\n    return `Task ${call_id} cancelled successfully.`;\n  },\n});\n\nexport class ToolExecutor {\n  private runningTasks = new Map<string, RunningTask>();\n  private duplicateLock = new Mutex();\n  private pendingUpdates: PendingUpdate[] = [];\n  private _replyTask?: Promise<void>;\n  private _replyTaskDone = false;\n  toolOptions: AsyncToolOptions;\n\n  constructor({\n    owningActivity,\n    asyncToolOptions,\n  }: {\n    owningActivity?: ToolExecutorActivity | null;\n    asyncToolOptions?: Partial<AsyncToolOptions>;\n  } = {}) {\n    this.owningActivity = owningActivity ?? null;\n    this.toolOptions = resolveAsyncToolOptions(asyncToolOptions);\n  }\n\n  private owningActivity: ToolExecutorActivity | null;\n\n  get replyTask(): Promise<void> | undefined {\n    return this._replyTask;\n  }\n\n  setOwningActivity(activity: ToolExecutorActivity | null): void {\n    this.owningActivity = activity;\n  }\n\n  setToolOptions(options?: Partial<AsyncToolOptions>): void {\n    this.toolOptions = resolveAsyncToolOptions(options);\n  }\n\n  get hasRunningTasks(): boolean {\n    return this.runningTasks.size > 0;\n  }\n\n  get hasCancellableRunningTasks(): boolean {\n    return [...this.runningTasks.values()].some((task) => task.allowCancellation);\n  }\n\n  async execute<Parameters extends JSONObject, UserData, Result>({\n    tool,\n    runCtx,\n    rawArguments,\n    abortSignal,\n  }: {\n    tool: FunctionTool<Parameters, UserData, Result>;\n    runCtx: RunContext<UserData>;\n    rawArguments: Parameters;\n    abortSignal?: AbortSignal;\n  }): Promise<unknown> {\n    const callId = runCtx.functionCall.callId;\n    const functionName = runCtx.functionCall.name;\n    const args = { ...rawArguments } as Parameters & Record<string, unknown>;\n    const confirmDuplicate =\n      tool.onDuplicate === 'confirm' ? Boolean(args[CONFIRM_DUPLICATE_PARAM]) : undefined;\n    delete args[CONFIRM_DUPLICATE_PARAM];\n\n    const unlock = await this.duplicateLock.lock();\n    try {\n      const duplicateResult = await this.checkDuplicate(functionName, {\n        onDuplicate: tool.onDuplicate,\n        confirmDuplicate,\n      });\n      if (duplicateResult !== undefined) return duplicateResult;\n\n      if (this.runningTasks.has(callId)) {\n        throw new Error(`Task already running for call_id: ${callId}`);\n      }\n\n      const firstUpdateFuture = new Future<unknown>();\n      const attachment = runCtx._attachExecutor(this, firstUpdateFuture);\n\n      const controller = new AbortController();\n      const abort = () => {\n        queueMicrotask(() => {\n          controller.abort();\n          if (!firstUpdateFuture.done) {\n            firstUpdateFuture.reject(new Error('tool call was aborted'));\n          }\n        });\n      };\n      abortSignal?.addEventListener('abort', abort, { once: true });\n\n      // Once a tool goes non-blocking (it called ctx.update and detached from its\n      // owning speech), a speech interruption must NOT abort it — async tools are\n      // meant to survive interruptions and deliver their result later (matches\n      // Python, where the exe_task is independent and only cancel()/drain() stop it).\n      // Stop forwarding the speech abort to this tool; explicit cancel()/drain()/\n      // aclose() still abort it directly via task.controller.\n      void firstUpdateFuture.await\n        .then(() => {\n          if (runCtx.functionCall.extra.__livekit_agents_tool_non_blocking === true) {\n            abortSignal?.removeEventListener('abort', abort);\n          }\n        })\n        .catch(() => {});\n\n      const toolPromiseRef: { promise?: Promise<unknown> } = {};\n      const promise = this.runTool({\n        tool,\n        runCtx,\n        rawArguments: args as Parameters,\n        firstUpdateFuture,\n        controller,\n        toolPromiseRef,\n      }).finally(() => {\n        if (this.runningTasks.get(callId)?.attachment === attachment) {\n          this.runningTasks.delete(callId);\n        }\n        const sessionTasks = runningTasks.get(runCtx.session);\n        if (sessionTasks?.get(callId)?.attachment === attachment) {\n          sessionTasks.delete(callId);\n        }\n        abortSignal?.removeEventListener('abort', abort);\n        runCtx._detachExecutor(attachment);\n      });\n\n      const task: RunningTask = {\n        ctx: runCtx,\n        promise,\n        controller,\n        firstUpdateFuture,\n        executor: this,\n        attachment,\n        allowCancellation: Boolean(tool.flags & ToolFlag.CANCELLABLE),\n        toolPromiseRef,\n      };\n      this.runningTasks.set(callId, task);\n      let sessionTasks = runningTasks.get(runCtx.session);\n      if (!sessionTasks) {\n        sessionTasks = new Map();\n        runningTasks.set(runCtx.session, sessionTasks);\n      }\n      sessionTasks.set(callId, task);\n\n      return firstUpdateFuture.await;\n    } finally {\n      unlock();\n    }\n  }\n\n  async waitForAll(): Promise<void> {\n    await Promise.allSettled([...this.runningTasks.values()].map((task) => task.promise));\n    if (this._replyTask) await this._replyTask;\n  }\n\n  async cancel(callId: string): Promise<boolean> {\n    const task = this.runningTasks.get(callId);\n    if (!task) return false;\n    if (!task.allowCancellation) {\n      throw new ToolError(`Tool call ${callId} is not cancellable`);\n    }\n    if (!task.ctx.speechHandle.allowInterruptions) {\n      throw new ToolError(\n        `Tool call ${callId} is not cancellable because interruptions are disallowed`,\n      );\n    }\n    this.forceCancelTask(task);\n    return true;\n  }\n\n  /**\n   * Abort + detach a running task unconditionally. `cancel()` gates on cancellability and\n   * interruptibility (LLM/user-initiated path); teardown via `drain()` must skip those guards —\n   * the activity is going away, and `cancel()`'s `allowInterruptions` throw would otherwise abort\n   * the drain loop and strand the remaining tasks.\n   */\n  private forceCancelTask(task: RunningTask): void {\n    const { callId } = task.ctx.functionCall;\n    task.controller.abort();\n    if (!task.firstUpdateFuture.done) {\n      task.firstUpdateFuture.resolve(undefined);\n    }\n    task.ctx._detachExecutor(task.attachment);\n\n    this.runningTasks.delete(callId);\n    void task.promise.catch(() => undefined);\n    // We've abandoned the wait, but the user's execute() may ignore the abort\n    // signal and keep running. Error if it hasn't stopped by the deadline.\n    this.errorIfCancelledToolKeepsRunning(task.ctx.functionCall, task.toolPromiseRef.promise);\n  }\n\n  /**\n   * Fire-and-forget watcher: a cancelled tool whose `execute()` hasn't settled by the\n   * deadline is ignoring its abort signal. Surface it so the dev can make execute abortable —\n   * abandoning the promise alone leaves the work running invisibly.\n   */\n  private errorIfCancelledToolKeepsRunning(\n    call: FunctionCall,\n    rawPromise: Promise<unknown> | undefined,\n  ): void {\n    if (!rawPromise) return;\n    let settled = false;\n    void rawPromise.then(() => {\n      settled = true;\n    });\n    const timer = setTimeout(() => {\n      if (settled) return;\n      log().error(\n        { tool: call.name, callId: call.callId, timeoutMs: DRAIN_TOOL_TIMEOUT_MS },\n        `tool ${call.name} was cancelled but its execute() is still running after the deadline; it likely ` +\n          'does not honor the abort signal. Observe the provided abortSignal in execute() so ' +\n          'cancellation actually stops the work.',\n      );\n    }, DRAIN_TOOL_TIMEOUT_MS);\n    timer.unref?.();\n    void rawPromise.finally(() => clearTimeout(timer));\n  }\n\n  async drain(): Promise<void> {\n    const tasks = [...this.runningTasks.values()];\n\n    // Cancellable tools: signal abort + abandon (force, bypassing the allowInterruptions guard\n    // that `cancel()` enforces for the LLM path — at teardown it would throw and strand the rest).\n    // Non-cancellable: let them run (awaited below).\n    for (const task of tasks) {\n      if (task.allowCancellation) {\n        this.forceCancelTask(task);\n      }\n    }\n\n    const inflight = tasks\n      .filter((task) => !task.allowCancellation)\n      .map((task) => ({ name: task.ctx.functionCall.name, promise: task.toolPromiseRef.promise }))\n      .filter((t): t is { name: string; promise: Promise<unknown> } => t.promise !== undefined);\n    if (inflight.length === 0) return;\n\n    const settled = new Set<number>();\n    inflight.forEach((t, i) => void t.promise.then(() => settled.add(i)));\n\n    const timer = setTimeout(() => {\n      const slow = inflight.filter((_, i) => !settled.has(i)).map((t) => t.name);\n      if (slow.length > 0) {\n        log().warn(\n          { tools: slow, timeoutMs: DRAIN_TOOL_TIMEOUT_MS },\n          'non-cancellable tool(s) still running after the drain deadline; awaiting their ' +\n            'completion so the deferred result is not dropped. Keep non-cancellable tool work ' +\n            'short, or mark the tool cancellable if it should stop on handoff.',\n        );\n      }\n    }, DRAIN_TOOL_TIMEOUT_MS);\n    timer.unref?.();\n\n    await Promise.allSettled(inflight.map((t) => t.promise));\n    clearTimeout(timer);\n  }\n\n  async aclose(): Promise<void> {\n    this.pendingUpdates = [];\n    const tasks = [...this.runningTasks.values()];\n    for (const task of tasks) {\n      task.controller.abort();\n      if (!task.firstUpdateFuture.done) {\n        task.firstUpdateFuture.resolve(undefined);\n      }\n      task.ctx._detachExecutor(task.attachment);\n      void task.promise.catch(() => undefined);\n    }\n    this.runningTasks.clear();\n  }\n\n  async enqueueReply(\n    ctx: RunContext<any>,\n    items: [FunctionCall, FunctionCallOutput],\n  ): Promise<void> {\n    const target = this.owningActivity?.agent ?? getCurrentAgent(ctx.session);\n    const chatCtx = target.chatCtx.copy();\n    chatCtx.insert(items);\n    await target.updateChatCtx(chatCtx);\n    ctx.session.history.insert(items);\n\n    this.pendingUpdates.push({ ctx, items, target });\n    if (this._replyTask === undefined || this._replyTaskDone) {\n      this._replyTaskDone = false;\n      this._replyTask = this.deliverReply(ctx.session).catch((error) => {\n        log().warn(\n          { error },\n          'deliverReply failed; async tool result may not trigger a follow-up reply',\n        );\n      });\n      const runState = (\n        ctx.session as unknown as {\n          _globalRunState?: { _watchHandle?: (p: Promise<void>) => void };\n        }\n      )._globalRunState;\n      runState?._watchHandle?.(this._replyTask);\n    }\n  }\n\n  private async runTool<Parameters extends JSONObject, UserData, Result>({\n    tool,\n    runCtx,\n    rawArguments,\n    firstUpdateFuture,\n    controller,\n    toolPromiseRef,\n  }: {\n    tool: FunctionTool<Parameters, UserData, Result>;\n    runCtx: RunContext<UserData>;\n    rawArguments: Parameters;\n    firstUpdateFuture: Future<unknown>;\n    controller: AbortController;\n    toolPromiseRef: { promise?: Promise<unknown> };\n  }): Promise<void> {\n    let output: unknown;\n    let exception: unknown;\n\n    // Wrap so a synchronous throw inside execute() also becomes a rejection.\n    const toolPromise = (async () =>\n      tool.execute(rawArguments, {\n        ctx: runCtx,\n        toolCallId: runCtx.functionCall.callId,\n        abortSignal: controller.signal,\n      }))();\n\n    // Guarded handle for drain() — never rejects, so abandoning it can't surface\n    // as an unhandled rejection.\n    toolPromiseRef.promise = toolPromise.then(\n      () => undefined,\n      () => undefined,\n    );\n\n    // Await the tool to completion. Cancellation responsiveness is handled by\n    // `cancel()` (abandons this wait) and `drain()` (bounds the wait on the raw\n    // promise via `toolPromiseRef`), so we must NOT abandon a tool that finishes\n    // around the same time an abort fires — doing so dropped its output and left\n    // the function call without an output (dangling), wedging later turns.\n    try {\n      output = await toolPromise;\n    } catch (error) {\n      exception = error;\n    }\n\n    if (controller.signal.aborted) {\n      if (!firstUpdateFuture.done) {\n        firstUpdateFuture.resolve(undefined);\n      }\n      return;\n    }\n\n    if (!firstUpdateFuture.done) {\n      if (exception !== undefined) {\n        // Propagate non-Error throws too (e.g. `throw \"boom\"`), otherwise the tool would be\n        // reported as succeeding with an `undefined` output.\n        firstUpdateFuture.reject(\n          exception instanceof Error ? exception : new Error(String(exception)),\n        );\n      } else {\n        firstUpdateFuture.resolve(output);\n      }\n      return;\n    }\n\n    if (exception !== undefined) {\n      log().error(\n        {\n          function: runCtx.functionCall.name,\n          callId: runCtx.functionCall.callId,\n          error: exception,\n        },\n        'exception occurred while executing tool after a progress update',\n      );\n      return;\n    }\n    if (output === undefined || output === null) {\n      return;\n    }\n    if (!this.runningTasks.has(runCtx.functionCall.callId)) {\n      return;\n    }\n    const pair = runCtx._makeUpdatePair(output, '_final');\n    runCtx._recordUpdatePair(pair);\n    await this.enqueueReply(runCtx, pair);\n  }\n\n  private async checkDuplicate(\n    functionName: string,\n    {\n      onDuplicate,\n      confirmDuplicate,\n    }: {\n      onDuplicate: DuplicateMode;\n      confirmDuplicate?: boolean;\n    },\n  ): Promise<string | undefined> {\n    const runningFunctionCalls = [...this.runningTasks.values()]\n      .map((task) => task.ctx.functionCall)\n      .filter((call) => call.name === functionName);\n    if (runningFunctionCalls.length === 0) return undefined;\n\n    if (onDuplicate === 'allow') {\n      return undefined;\n    }\n\n    if (onDuplicate === 'replace') {\n      const nonCancellable = runningFunctionCalls.filter(\n        (call) => !this.runningTasks.get(call.callId)?.allowCancellation,\n      );\n      if (nonCancellable.length > 0) {\n        throw new ToolError(\n          `cannot replace duplicate call of \\`${functionName}\\`: running call is not cancellable`,\n        );\n      }\n      await Promise.all(runningFunctionCalls.map((call) => this.cancel(call.callId)));\n      return undefined;\n    }\n\n    const functionCallsJson = runningFunctionCalls.map((call) => JSON.stringify(call.toJSON(true)));\n    const args = {\n      functionName,\n      functionCallsJson,\n      functionCallsText: functionCallsJson.join('\\n'),\n    };\n\n    if (onDuplicate === 'reject') {\n      return renderTemplate(this.toolOptions.duplicateRejectTemplate, args);\n    }\n\n    if (onDuplicate === 'confirm' && !confirmDuplicate) {\n      return renderTemplate(this.toolOptions.duplicateConfirmTemplate, args);\n    }\n\n    return undefined;\n  }\n\n  private async deliverReply(session: AgentSession): Promise<void> {\n    try {\n      if (this.owningActivity) {\n        await this.owningActivity.waitForIdle();\n      } else if ('waitForIdle' in session && typeof session.waitForIdle === 'function') {\n        await session.waitForIdle();\n      }\n\n      const updates = [...this.pendingUpdates];\n      this.pendingUpdates = [];\n      const pendingItems = updates.flatMap((update) => update.items);\n      if (pendingItems.length === 0) return;\n\n      const targetAgent = this.owningActivity?.agent ?? getCurrentAgent(session);\n\n      const itemsToInsert = updates\n        .filter((update) => update.target !== targetAgent)\n        .flatMap((update) => update.items);\n\n      let chatCtx: ChatContext | undefined;\n      if (itemsToInsert.length > 0) {\n        chatCtx = targetAgent.chatCtx.copy();\n        chatCtx.insert(itemsToInsert);\n      }\n\n      const lastItem = pendingItems[pendingItems.length - 1]!;\n      const targetItems = targetAgent.chatCtx.items;\n      const atTail =\n        targetItems.length > 0 && targetItems[targetItems.length - 1]!.id === lastItem.id;\n      const callIds = pendingItems\n        .filter((item): item is FunctionCallOutput => item.type === 'function_call_output')\n        .map((item) => item.callId);\n      const instructions = renderTemplate(\n        atTail ? this.toolOptions.replyAtTailTemplate : this.toolOptions.replyMaybeCoveredTemplate,\n        { callIds },\n      );\n\n      session.generateReply({\n        instructions,\n        toolChoice: 'none',\n        chatCtx,\n      });\n    } finally {\n      this._replyTaskDone = true;\n    }\n  }\n}\n\nexport function hasCancellableTool(tools: readonly ToolContextEntry[]): boolean {\n  for (const entry of tools) {\n    if (isFunctionTool(entry) && entry.flags & ToolFlag.CANCELLABLE) return true;\n    if (entry instanceof Toolset && hasCancellableTool(entry.tools)) return true;\n  }\n  return false;\n}\n\nexport function buildExecutorMap({\n  toolsets,\n  defaultExecutor,\n}: {\n  toolsets: readonly Toolset[];\n  defaultExecutor: ToolExecutor;\n}): Map<string, ToolExecutor> {\n  const mapping = new Map<string, ToolExecutor>();\n\n  const walk = (toolset: Toolset, current: ToolExecutor): void => {\n    const scopedExecutor =\n      '_executor' in toolset && toolset._executor instanceof ToolExecutor\n        ? toolset._executor\n        : current;\n    for (const child of toolset.tools) {\n      if (isFunctionTool(child)) {\n        mapping.set(child.name, scopedExecutor);\n      } else if (child instanceof Toolset) {\n        walk(child, scopedExecutor);\n      }\n    }\n  };\n\n  for (const toolset of toolsets) {\n    walk(toolset, defaultExecutor);\n  }\n  return mapping;\n}\n\nexport function getRunningTasks(session: AgentSession): FunctionCall[] {\n  return [...(runningTasks.get(session)?.values() ?? [])].map((task) =>\n    FunctionCall.create({ ...task.ctx.functionCall }),\n  );\n}\n\n/** @internal */\nexport function _getCancellableRunningTasks(session: AgentSession): FunctionCall[] {\n  return [...(runningTasks.get(session)?.values() ?? [])]\n    .filter((task) => task.allowCancellation && !task.controller.signal.aborted)\n    .map((task) => FunctionCall.create({ ...task.ctx.functionCall }));\n}\n\nfunction getCurrentAgent(session: AgentSession): ToolExecutorAgent {\n  return (session as unknown as { currentAgent: ToolExecutorAgent }).currentAgent;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,mBAAsB;AACtB,iBAAkB;AAElB,0BAA6B;AAC7B,0BAWO;AACP,iBAAoB;AACpB,mBAAuB;AAMvB,MAAM,wBAAwB,OAAO,QAAQ,IAAI,2BAA2B,KAAK;AAwB1E,MAAM,kBACX;AAGK,MAAM,mBACX;AAIK,MAAM,oBACX;AAKK,MAAM,6BACX;AAGK,MAAM,mCACX;AAMK,SAAS,wBAAwB,SAAuD;AAC7F,SAAO;AAAA,IACL,iBAAgB,mCAAS,mBAAkB;AAAA,IAC3C,0BAAyB,mCAAS,4BAA2B;AAAA,IAC7D,2BAA0B,mCAAS,6BAA4B;AAAA,IAC/D,sBAAqB,mCAAS,wBAAuB;AAAA,IACrD,4BACE,mCAAS,8BAA6B;AAAA,EAC1C;AACF;AAEO,SAAS,eACd,UACA,MACQ;AACR,MAAI,OAAO,aAAa,WAAY,QAAO,SAAS,IAAI;AACxD,SAAO,OAAO,QAAQ,IAAI,EAAE;AAAA,IAC1B,CAAC,QAAQ,CAAC,KAAK,KAAK,MAAM,OAAO,WAAW,IAAI,GAAG,KAAK,OAAO,KAAK,CAAC;AAAA,IACrE;AAAA,EACF;AACF;AA+BA,MAAM,eAAe,oBAAI,QAAqD;AAEvE,MAAM,0BAAsB,0BAAK;AAAA,EACtC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,SAAS,OAAO,GAAG,EAAE,IAAI,MACvB,4BAA4B,IAAI,OAAO,EAAE,IAAI,CAAC,SAAS,KAAK,OAAO,IAAI,CAAC;AAC5E,CAAC;AAEM,MAAM,qBAAiB,0BAAK;AAAA,EACjC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY,aAAE,OAAO;AAAA,IACnB,SAAS,aAAE,OAAO;AAAA,EACpB,CAAC;AAAA,EACD,SAAS,OAAO,EAAE,QAAQ,GAAG,EAAE,IAAI,MAAM;AA9I3C;AA+II,UAAM,QAAO,kBAAa,IAAI,IAAI,OAAO,MAA5B,mBAA+B,IAAI;AAChD,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,8BAAU,QAAQ,OAAO,YAAY;AAAA,IACjD;AACA,UAAM,YAAY,MAAM,KAAK,SAAS,OAAO,OAAO;AACpD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,8BAAU,QAAQ,OAAO,iCAAiC;AAAA,IACtE;AACA,WAAO,QAAQ,OAAO;AAAA,EACxB;AACF,CAAC;AAEM,MAAM,aAAa;AAAA,EAChB,eAAe,oBAAI,IAAyB;AAAA,EAC5C,gBAAgB,IAAI,mBAAM;AAAA,EAC1B,iBAAkC,CAAC;AAAA,EACnC;AAAA,EACA,iBAAiB;AAAA,EACzB;AAAA,EAEA,YAAY;AAAA,IACV;AAAA,IACA;AAAA,EACF,IAGI,CAAC,GAAG;AACN,SAAK,iBAAiB,kBAAkB;AACxC,SAAK,cAAc,wBAAwB,gBAAgB;AAAA,EAC7D;AAAA,EAEQ;AAAA,EAER,IAAI,YAAuC;AACzC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAAkB,UAA6C;AAC7D,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,eAAe,SAA2C;AACxD,SAAK,cAAc,wBAAwB,OAAO;AAAA,EACpD;AAAA,EAEA,IAAI,kBAA2B;AAC7B,WAAO,KAAK,aAAa,OAAO;AAAA,EAClC;AAAA,EAEA,IAAI,6BAAsC;AACxC,WAAO,CAAC,GAAG,KAAK,aAAa,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,KAAK,iBAAiB;AAAA,EAC9E;AAAA,EAEA,MAAM,QAAyD;AAAA,IAC7D,MAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAKqB;AACnB,UAAM,SAAS,OAAO,aAAa;AACnC,UAAM,eAAe,OAAO,aAAa;AACzC,UAAM,OAAO,EAAE,GAAG,aAAa;AAC/B,UAAM,mBACJA,MAAK,gBAAgB,YAAY,QAAQ,KAAK,2CAAuB,CAAC,IAAI;AAC5E,WAAO,KAAK,2CAAuB;AAEnC,UAAM,SAAS,MAAM,KAAK,cAAc,KAAK;AAC7C,QAAI;AACF,YAAM,kBAAkB,MAAM,KAAK,eAAe,cAAc;AAAA,QAC9D,aAAaA,MAAK;AAAA,QAClB;AAAA,MACF,CAAC;AACD,UAAI,oBAAoB,OAAW,QAAO;AAE1C,UAAI,KAAK,aAAa,IAAI,MAAM,GAAG;AACjC,cAAM,IAAI,MAAM,qCAAqC,MAAM,EAAE;AAAA,MAC/D;AAEA,YAAM,oBAAoB,IAAI,oBAAgB;AAC9C,YAAM,aAAa,OAAO,gBAAgB,MAAM,iBAAiB;AAEjE,YAAM,aAAa,IAAI,gBAAgB;AACvC,YAAM,QAAQ,MAAM;AAClB,uBAAe,MAAM;AACnB,qBAAW,MAAM;AACjB,cAAI,CAAC,kBAAkB,MAAM;AAC3B,8BAAkB,OAAO,IAAI,MAAM,uBAAuB,CAAC;AAAA,UAC7D;AAAA,QACF,CAAC;AAAA,MACH;AACA,iDAAa,iBAAiB,SAAS,OAAO,EAAE,MAAM,KAAK;AAQ3D,WAAK,kBAAkB,MACpB,KAAK,MAAM;AACV,YAAI,OAAO,aAAa,MAAM,uCAAuC,MAAM;AACzE,qDAAa,oBAAoB,SAAS;AAAA,QAC5C;AAAA,MACF,CAAC,EACA,MAAM,MAAM;AAAA,MAAC,CAAC;AAEjB,YAAM,iBAAiD,CAAC;AACxD,YAAM,UAAU,KAAK,QAAQ;AAAA,QAC3B,MAAAA;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,EAAE,QAAQ,MAAM;AAtQvB;AAuQQ,cAAI,UAAK,aAAa,IAAI,MAAM,MAA5B,mBAA+B,gBAAe,YAAY;AAC5D,eAAK,aAAa,OAAO,MAAM;AAAA,QACjC;AACA,cAAMC,gBAAe,aAAa,IAAI,OAAO,OAAO;AACpD,cAAI,KAAAA,iBAAA,gBAAAA,cAAc,IAAI,YAAlB,mBAA2B,gBAAe,YAAY;AACxD,UAAAA,cAAa,OAAO,MAAM;AAAA,QAC5B;AACA,mDAAa,oBAAoB,SAAS;AAC1C,eAAO,gBAAgB,UAAU;AAAA,MACnC,CAAC;AAED,YAAM,OAAoB;AAAA,QACxB,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,mBAAmB,QAAQD,MAAK,QAAQ,6BAAS,WAAW;AAAA,QAC5D;AAAA,MACF;AACA,WAAK,aAAa,IAAI,QAAQ,IAAI;AAClC,UAAI,eAAe,aAAa,IAAI,OAAO,OAAO;AAClD,UAAI,CAAC,cAAc;AACjB,uBAAe,oBAAI,IAAI;AACvB,qBAAa,IAAI,OAAO,SAAS,YAAY;AAAA,MAC/C;AACA,mBAAa,IAAI,QAAQ,IAAI;AAE7B,aAAO,kBAAkB;AAAA,IAC3B,UAAE;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,QAAQ,WAAW,CAAC,GAAG,KAAK,aAAa,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC;AACpF,QAAI,KAAK,WAAY,OAAM,KAAK;AAAA,EAClC;AAAA,EAEA,MAAM,OAAO,QAAkC;AAC7C,UAAM,OAAO,KAAK,aAAa,IAAI,MAAM;AACzC,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,CAAC,KAAK,mBAAmB;AAC3B,YAAM,IAAI,8BAAU,aAAa,MAAM,qBAAqB;AAAA,IAC9D;AACA,QAAI,CAAC,KAAK,IAAI,aAAa,oBAAoB;AAC7C,YAAM,IAAI;AAAA,QACR,aAAa,MAAM;AAAA,MACrB;AAAA,IACF;AACA,SAAK,gBAAgB,IAAI;AACzB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,gBAAgB,MAAyB;AAC/C,UAAM,EAAE,OAAO,IAAI,KAAK,IAAI;AAC5B,SAAK,WAAW,MAAM;AACtB,QAAI,CAAC,KAAK,kBAAkB,MAAM;AAChC,WAAK,kBAAkB,QAAQ,MAAS;AAAA,IAC1C;AACA,SAAK,IAAI,gBAAgB,KAAK,UAAU;AAExC,SAAK,aAAa,OAAO,MAAM;AAC/B,SAAK,KAAK,QAAQ,MAAM,MAAM,MAAS;AAGvC,SAAK,iCAAiC,KAAK,IAAI,cAAc,KAAK,eAAe,OAAO;AAAA,EAC1F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iCACN,MACA,YACM;AA3VV;AA4VI,QAAI,CAAC,WAAY;AACjB,QAAI,UAAU;AACd,SAAK,WAAW,KAAK,MAAM;AACzB,gBAAU;AAAA,IACZ,CAAC;AACD,UAAM,QAAQ,WAAW,MAAM;AAC7B,UAAI,QAAS;AACb,0BAAI,EAAE;AAAA,QACJ,EAAE,MAAM,KAAK,MAAM,QAAQ,KAAK,QAAQ,WAAW,sBAAsB;AAAA,QACzE,QAAQ,KAAK,IAAI;AAAA,MAGnB;AAAA,IACF,GAAG,qBAAqB;AACxB,gBAAM,UAAN;AACA,SAAK,WAAW,QAAQ,MAAM,aAAa,KAAK,CAAC;AAAA,EACnD;AAAA,EAEA,MAAM,QAAuB;AA9W/B;AA+WI,UAAM,QAAQ,CAAC,GAAG,KAAK,aAAa,OAAO,CAAC;AAK5C,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,mBAAmB;AAC1B,aAAK,gBAAgB,IAAI;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,WAAW,MACd,OAAO,CAAC,SAAS,CAAC,KAAK,iBAAiB,EACxC,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,aAAa,MAAM,SAAS,KAAK,eAAe,QAAQ,EAAE,EAC1F,OAAO,CAAC,MAAwD,EAAE,YAAY,MAAS;AAC1F,QAAI,SAAS,WAAW,EAAG;AAE3B,UAAM,UAAU,oBAAI,IAAY;AAChC,aAAS,QAAQ,CAAC,GAAG,MAAM,KAAK,EAAE,QAAQ,KAAK,MAAM,QAAQ,IAAI,CAAC,CAAC,CAAC;AAEpE,UAAM,QAAQ,WAAW,MAAM;AAC7B,YAAM,OAAO,SAAS,OAAO,CAAC,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AACzE,UAAI,KAAK,SAAS,GAAG;AACnB,4BAAI,EAAE;AAAA,UACJ,EAAE,OAAO,MAAM,WAAW,sBAAsB;AAAA,UAChD;AAAA,QAGF;AAAA,MACF;AAAA,IACF,GAAG,qBAAqB;AACxB,gBAAM,UAAN;AAEA,UAAM,QAAQ,WAAW,SAAS,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AACvD,iBAAa,KAAK;AAAA,EACpB;AAAA,EAEA,MAAM,SAAwB;AAC5B,SAAK,iBAAiB,CAAC;AACvB,UAAM,QAAQ,CAAC,GAAG,KAAK,aAAa,OAAO,CAAC;AAC5C,eAAW,QAAQ,OAAO;AACxB,WAAK,WAAW,MAAM;AACtB,UAAI,CAAC,KAAK,kBAAkB,MAAM;AAChC,aAAK,kBAAkB,QAAQ,MAAS;AAAA,MAC1C;AACA,WAAK,IAAI,gBAAgB,KAAK,UAAU;AACxC,WAAK,KAAK,QAAQ,MAAM,MAAM,MAAS;AAAA,IACzC;AACA,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEA,MAAM,aACJ,KACA,OACe;AAranB;AAsaI,UAAM,WAAS,UAAK,mBAAL,mBAAqB,UAAS,gBAAgB,IAAI,OAAO;AACxE,UAAM,UAAU,OAAO,QAAQ,KAAK;AACpC,YAAQ,OAAO,KAAK;AACpB,UAAM,OAAO,cAAc,OAAO;AAClC,QAAI,QAAQ,QAAQ,OAAO,KAAK;AAEhC,SAAK,eAAe,KAAK,EAAE,KAAK,OAAO,OAAO,CAAC;AAC/C,QAAI,KAAK,eAAe,UAAa,KAAK,gBAAgB;AACxD,WAAK,iBAAiB;AACtB,WAAK,aAAa,KAAK,aAAa,IAAI,OAAO,EAAE,MAAM,CAAC,UAAU;AAChE,4BAAI,EAAE;AAAA,UACJ,EAAE,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF,CAAC;AACD,YAAM,WACJ,IAAI,QAGJ;AACF,iDAAU,iBAAV,kCAAyB,KAAK;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAc,QAAyD;AAAA,IACrE,MAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAOkB;AAChB,QAAI;AACJ,QAAI;AAGJ,UAAM,eAAe,YACnBA,MAAK,QAAQ,cAAc;AAAA,MACzB,KAAK;AAAA,MACL,YAAY,OAAO,aAAa;AAAA,MAChC,aAAa,WAAW;AAAA,IAC1B,CAAC,GAAG;AAIN,mBAAe,UAAU,YAAY;AAAA,MACnC,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAOA,QAAI;AACF,eAAS,MAAM;AAAA,IACjB,SAAS,OAAO;AACd,kBAAY;AAAA,IACd;AAEA,QAAI,WAAW,OAAO,SAAS;AAC7B,UAAI,CAAC,kBAAkB,MAAM;AAC3B,0BAAkB,QAAQ,MAAS;AAAA,MACrC;AACA;AAAA,IACF;AAEA,QAAI,CAAC,kBAAkB,MAAM;AAC3B,UAAI,cAAc,QAAW;AAG3B,0BAAkB;AAAA,UAChB,qBAAqB,QAAQ,YAAY,IAAI,MAAM,OAAO,SAAS,CAAC;AAAA,QACtE;AAAA,MACF,OAAO;AACL,0BAAkB,QAAQ,MAAM;AAAA,MAClC;AACA;AAAA,IACF;AAEA,QAAI,cAAc,QAAW;AAC3B,0BAAI,EAAE;AAAA,QACJ;AAAA,UACE,UAAU,OAAO,aAAa;AAAA,UAC9B,QAAQ,OAAO,aAAa;AAAA,UAC5B,OAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,WAAW,UAAa,WAAW,MAAM;AAC3C;AAAA,IACF;AACA,QAAI,CAAC,KAAK,aAAa,IAAI,OAAO,aAAa,MAAM,GAAG;AACtD;AAAA,IACF;AACA,UAAM,OAAO,OAAO,gBAAgB,QAAQ,QAAQ;AACpD,WAAO,kBAAkB,IAAI;AAC7B,UAAM,KAAK,aAAa,QAAQ,IAAI;AAAA,EACtC;AAAA,EAEA,MAAc,eACZ,cACA;AAAA,IACE;AAAA,IACA;AAAA,EACF,GAI6B;AAC7B,UAAM,uBAAuB,CAAC,GAAG,KAAK,aAAa,OAAO,CAAC,EACxD,IAAI,CAAC,SAAS,KAAK,IAAI,YAAY,EACnC,OAAO,CAAC,SAAS,KAAK,SAAS,YAAY;AAC9C,QAAI,qBAAqB,WAAW,EAAG,QAAO;AAE9C,QAAI,gBAAgB,SAAS;AAC3B,aAAO;AAAA,IACT;AAEA,QAAI,gBAAgB,WAAW;AAC7B,YAAM,iBAAiB,qBAAqB;AAAA,QAC1C,CAAC,SAAM;AAziBf;AAyiBkB,oBAAC,UAAK,aAAa,IAAI,KAAK,MAAM,MAAjC,mBAAoC;AAAA;AAAA,MACjD;AACA,UAAI,eAAe,SAAS,GAAG;AAC7B,cAAM,IAAI;AAAA,UACR,sCAAsC,YAAY;AAAA,QACpD;AAAA,MACF;AACA,YAAM,QAAQ,IAAI,qBAAqB,IAAI,CAAC,SAAS,KAAK,OAAO,KAAK,MAAM,CAAC,CAAC;AAC9E,aAAO;AAAA,IACT;AAEA,UAAM,oBAAoB,qBAAqB,IAAI,CAAC,SAAS,KAAK,UAAU,KAAK,OAAO,IAAI,CAAC,CAAC;AAC9F,UAAM,OAAO;AAAA,MACX;AAAA,MACA;AAAA,MACA,mBAAmB,kBAAkB,KAAK,IAAI;AAAA,IAChD;AAEA,QAAI,gBAAgB,UAAU;AAC5B,aAAO,eAAe,KAAK,YAAY,yBAAyB,IAAI;AAAA,IACtE;AAEA,QAAI,gBAAgB,aAAa,CAAC,kBAAkB;AAClD,aAAO,eAAe,KAAK,YAAY,0BAA0B,IAAI;AAAA,IACvE;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAa,SAAsC;AAtkBnE;AAukBI,QAAI;AACF,UAAI,KAAK,gBAAgB;AACvB,cAAM,KAAK,eAAe,YAAY;AAAA,MACxC,WAAW,iBAAiB,WAAW,OAAO,QAAQ,gBAAgB,YAAY;AAChF,cAAM,QAAQ,YAAY;AAAA,MAC5B;AAEA,YAAM,UAAU,CAAC,GAAG,KAAK,cAAc;AACvC,WAAK,iBAAiB,CAAC;AACvB,YAAM,eAAe,QAAQ,QAAQ,CAAC,WAAW,OAAO,KAAK;AAC7D,UAAI,aAAa,WAAW,EAAG;AAE/B,YAAM,gBAAc,UAAK,mBAAL,mBAAqB,UAAS,gBAAgB,OAAO;AAEzE,YAAM,gBAAgB,QACnB,OAAO,CAAC,WAAW,OAAO,WAAW,WAAW,EAChD,QAAQ,CAAC,WAAW,OAAO,KAAK;AAEnC,UAAI;AACJ,UAAI,cAAc,SAAS,GAAG;AAC5B,kBAAU,YAAY,QAAQ,KAAK;AACnC,gBAAQ,OAAO,aAAa;AAAA,MAC9B;AAEA,YAAM,WAAW,aAAa,aAAa,SAAS,CAAC;AACrD,YAAM,cAAc,YAAY,QAAQ;AACxC,YAAM,SACJ,YAAY,SAAS,KAAK,YAAY,YAAY,SAAS,CAAC,EAAG,OAAO,SAAS;AACjF,YAAM,UAAU,aACb,OAAO,CAAC,SAAqC,KAAK,SAAS,sBAAsB,EACjF,IAAI,CAAC,SAAS,KAAK,MAAM;AAC5B,YAAM,eAAe;AAAA,QACnB,SAAS,KAAK,YAAY,sBAAsB,KAAK,YAAY;AAAA,QACjE,EAAE,QAAQ;AAAA,MACZ;AAEA,cAAQ,cAAc;AAAA,QACpB;AAAA,QACA,YAAY;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,UAAE;AACA,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,OAA6C;AAC9E,aAAW,SAAS,OAAO;AACzB,YAAI,oCAAe,KAAK,KAAK,MAAM,QAAQ,6BAAS,YAAa,QAAO;AACxE,QAAI,iBAAiB,+BAAW,mBAAmB,MAAM,KAAK,EAAG,QAAO;AAAA,EAC1E;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AACF,GAG8B;AAC5B,QAAM,UAAU,oBAAI,IAA0B;AAE9C,QAAM,OAAO,CAAC,SAAkB,YAAgC;AAC9D,UAAM,iBACJ,eAAe,WAAW,QAAQ,qBAAqB,eACnD,QAAQ,YACR;AACN,eAAW,SAAS,QAAQ,OAAO;AACjC,cAAI,oCAAe,KAAK,GAAG;AACzB,gBAAQ,IAAI,MAAM,MAAM,cAAc;AAAA,MACxC,WAAW,iBAAiB,6BAAS;AACnC,aAAK,OAAO,cAAc;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,aAAW,WAAW,UAAU;AAC9B,SAAK,SAAS,eAAe;AAAA,EAC/B;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,SAAuC;AA3pBvE;AA4pBE,SAAO,CAAC,KAAI,kBAAa,IAAI,OAAO,MAAxB,mBAA2B,aAAY,CAAC,CAAE,EAAE;AAAA,IAAI,CAAC,SAC3D,iCAAa,OAAO,EAAE,GAAG,KAAK,IAAI,aAAa,CAAC;AAAA,EAClD;AACF;AAGO,SAAS,4BAA4B,SAAuC;AAlqBnF;AAmqBE,SAAO,CAAC,KAAI,kBAAa,IAAI,OAAO,MAAxB,mBAA2B,aAAY,CAAC,CAAE,EACnD,OAAO,CAAC,SAAS,KAAK,qBAAqB,CAAC,KAAK,WAAW,OAAO,OAAO,EAC1E,IAAI,CAAC,SAAS,iCAAa,OAAO,EAAE,GAAG,KAAK,IAAI,aAAa,CAAC,CAAC;AACpE;AAEA,SAAS,gBAAgB,SAA0C;AACjE,SAAQ,QAA2D;AACrE;","names":["tool","sessionTasks"]}