{"version":3,"file":"agent-controller-DAv0pT5D.cjs","names":["MASTRA_MESSAGE_AUTHOR_KEY","getTransformedToolPayload","hasTransformedToolPayload","isRecord","getServerSideFallbackInfo","addOptionalUsageField","#session","#machinery","MessagePartSpans","isSpanChunk","getTransformedToolPayload","hasTransformedToolPayload","getErrorFromUnknown","createRunScopeKey","#defaultResourceId","#id","#ownerId","#resourceId","#getResourceId","#store","#session","#owner","#threadId","#cloneThread","#requireOwnedThread","TITLE_PINNED_THREAD_METADATA_KEY","#teardownWaiters","#key","#subscription","#agent","#notifyTeardown","#pending","#toolName","#toolCallId","#resolve","#abortRequestWaiters","#abortRequested","#runId","#traceId","#abortController","#operationId","#notifyAbortRequested","#bus","#getCurrentModeId","#trackModelUse","#model","#resolveMode","#switchVersion","#config","#getState","#setState","#setSetting","#omConfig","#gateways","ModelRouterLanguageModel","resolveDeliveryAttributes","#schema","#capturePersistSetting","#state","#updateQueue","safeStringify","#listeners","#displayState","#lastWorkspaceEvents","#flushDisplayState","#dispatch","#scheduleDisplayState","#displayStateTimer","#displayStatePending","#beforeAgentEndListeners","#grantedCategories","#grantedTools","#preparingFollowUps","#tags","#workspace","#resolveSubagentName","Workspace","#resolveCategory","#machinery","#engine","#localOnlyAbort","getErrorFromUnknown","createSignal","#watchStreamTeardown","#followUpBinding","#followUpGeneration","#tokenUsage","createTool","z","RequestContext","CHAT_CHANNEL_RENDER_CONTEXT_KEY","Agent","createWorkspaceTools","summarizeTaskCheck","#defaultMode","#sessionsByResource","#sessionCreatedListeners","#sessionDeletedListeners","#deletionsInProgress","#sessionsBeingDeleted","#sessionDeletionPromises","#sessionScopes","#instructions","#channels","AgentControllerChannels","#gatewayManager","GatewayManager","defaultGateways","#notifySessionCreated","#createSessionForResource","RequestContext","#wireSession","#dropSessionFromRegistry","#notifySessionDeleted","#externalMastra","#internalMastra","#storageInitPromise","Mastra","#resolveStorage","isUserAuthoredMessage","MessageList","TITLE_PINNED_THREAD_METADATA_KEY","#legacyAgentMode","Agent","askUserTool","submitPlanTool","taskWriteTool","taskUpdateTool","taskCompleteTool","taskCheckTool"],"sources":["../src/agent-controller/message-author.ts","../src/agent-controller/stream-content.ts","../src/agent-controller/session-run-engine.ts","../src/agent-controller/types.ts","../src/agent-controller/session.ts","../src/agent-controller/tools.ts","../src/agent-controller/agent-controller.ts"],"sourcesContent":["import type { MastraProviderMetadata } from '../agent/message-list/state/types';\nimport { MASTRA_MESSAGE_AUTHOR_KEY } from '../request-context';\nimport type { RequestContext } from '../request-context';\n\n/** Who sent a user message, as stamped by the host that authenticated them. */\nexport type MessageAuthor = { id: string; name?: string; avatarUrl?: string };\n\nexport function readMessageAuthor(requestContext?: RequestContext): MessageAuthor | undefined {\n  const value = requestContext?.get(MASTRA_MESSAGE_AUTHOR_KEY);\n  if (!value || typeof value !== 'object') return undefined;\n  const { id, name, avatarUrl } = value as Partial<Record<keyof MessageAuthor, unknown>>;\n  if (typeof id !== 'string' || !id) return undefined;\n  return {\n    id,\n    ...(typeof name === 'string' ? { name } : {}),\n    ...(typeof avatarUrl === 'string' ? { avatarUrl } : {}),\n  };\n}\n\nexport function withMessageAuthor(\n  providerOptions: MastraProviderMetadata | undefined,\n  author: MessageAuthor | undefined,\n): MastraProviderMetadata | undefined {\n  if (!author) return providerOptions;\n  return { ...providerOptions, mastra: { ...providerOptions?.mastra, author } };\n}\n","import { getServerSideFallbackInfo } from '../llm/model/server-side-fallback';\nimport { getTransformedToolPayload, hasTransformedToolPayload } from '../tools/payload-transform';\nimport type { ToolPayloadTransformPhase } from '../tools/types';\nimport type { TokenUsage } from './types';\n\n/**\n * Pure transforms shared by the run engine for folding raw agent-stream chunk\n * payloads into the `MastraDBMessage` shape a Session renders, plus terminal\n * finish-reason and server-side-fallback diagnostics. They hold no\n * AgentController or Session state, so they live in their own module.\n */\n\nexport function getDisplayTransform(metadata: unknown, phase: ToolPayloadTransformPhase, fallback: unknown) {\n  const transform = getTransformedToolPayload(metadata, 'display', phase);\n  return hasTransformedToolPayload(transform) ? transform.transformed : fallback;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null;\n}\n\nfunction getAnthropicStopDetails(providerMetadata: unknown): Record<string, unknown> | undefined {\n  if (!isRecord(providerMetadata)) {\n    return undefined;\n  }\n  const anthropic = providerMetadata.anthropic;\n  if (!isRecord(anthropic)) {\n    return undefined;\n  }\n  const stopDetails = anthropic.stopDetails;\n  return isRecord(stopDetails) ? stopDetails : undefined;\n}\n\n/**\n * Map a non-success terminal finish reason (content-filter, error, length) to a\n * user-facing message, or `undefined` for success reasons. A non-success finish\n * must become an explicit terminal error rather than a silent `complete`.\n */\nexport function describeNonSuccessFinishReason(reason: string, providerMetadata: unknown): string | undefined {\n  switch (reason) {\n    case 'content-filter': {\n      const stopDetails = getAnthropicStopDetails(providerMetadata);\n      const explanation =\n        stopDetails && typeof stopDetails.explanation === 'string' ? stopDetails.explanation : undefined;\n      const category = stopDetails && typeof stopDetails.category === 'string' ? stopDetails.category : undefined;\n      const detail = explanation ?? (category ? `category: ${category}` : undefined);\n      return detail ? `The model stopped on a content filter (${detail}).` : 'The model stopped on a content filter.';\n    }\n    case 'error':\n      return 'The model stream ended with an error before producing a final response.';\n    case 'length':\n      return 'The model stopped because it reached its maximum output length before finishing.';\n    default:\n      return undefined;\n  }\n}\n\n/**\n * Build a user-facing notice when a turn was served by an Anthropic server-side\n * fallback model instead of the primary model. Without a notice the user has no\n * way to tell the response did not come from the model they selected.\n */\nexport function describeServerSideFallback(providerMetadata: unknown): string | undefined {\n  const fallback = getServerSideFallbackInfo(providerMetadata);\n  if (!fallback) {\n    return undefined;\n  }\n  return fallback.model\n    ? `The selected model declined this turn; the response was generated by fallback model ${fallback.model}.`\n    : 'The selected model declined this turn; the response was generated by a fallback model.';\n}\n\n/** Coerce a usage field to a finite number, accepting numeric strings. */\nexport function getUsageNumber(usage: Record<string, unknown>, key: string): number | undefined {\n  const value = usage[key];\n  if (typeof value === 'number' && Number.isFinite(value)) {\n    return value;\n  }\n  if (typeof value === 'string' && value.trim() !== '') {\n    const numericValue = Number(value);\n    if (Number.isFinite(numericValue)) {\n      return numericValue;\n    }\n  }\n  return undefined;\n}\n\n/** Fold an optional usage field into a tally when present. */\nexport function addOptionalUsageField(\n  usage: TokenUsage,\n  key: keyof Pick<\n    TokenUsage,\n    | 'reasoningTokens'\n    | 'cachedInputTokens'\n    | 'cacheCreationInputTokens'\n    | 'cacheCreationInputTokens5m'\n    | 'cacheCreationInputTokens1h'\n  >,\n  value: number | undefined,\n): void {\n  if (value !== undefined) {\n    usage[key] = (usage[key] ?? 0) + value;\n  }\n}\n","import type { Agent } from '../agent';\nimport type { SpanChunk } from '../agent/message-list/message-part-spans';\nimport { isSpanChunk, MessagePartSpans } from '../agent/message-list/message-part-spans';\nimport type {\n  MastraDBMessage,\n  MastraMessagePart,\n  MastraProviderMetadata,\n  MastraToolInvocationPart,\n} from '../agent/message-list/state/types';\nimport type { AgentThreadSubscription } from '../agent/types';\nimport { getErrorFromUnknown } from '../error';\nimport type { RequestContext } from '../request-context';\nimport type { GoalEvaluationPayload } from '../stream/types';\nimport { getTransformedToolPayload, hasTransformedToolPayload } from '../tools/payload-transform';\nimport type { Session, SessionMachinery } from './session';\nimport { ABORTED_BY_USER_REASON, SUSPENDED_RUN_AGENT_KEY, SUSPENDED_RUN_MEMORY_KEY } from './session';\nimport {\n  addOptionalUsageField,\n  describeNonSuccessFinishReason,\n  describeServerSideFallback,\n  getDisplayTransform,\n  getUsageNumber,\n} from './stream-content';\nimport type { TokenUsage } from './types';\n\n/**\n * The transient state of a single in-flight agent stream: the assistant message\n * being assembled, content indices for streaming deltas, and suspend/terminal\n * flags. One per run; recreated per run within a subscribed thread stream.\n */\ntype StreamDataPart = MastraMessagePart & { type: `data-${string}`; data: unknown };\ntype StreamChunkPayload = Record<string, unknown>;\ntype StreamChunkBase<TType extends string> = {\n  type: TType;\n  runId?: string | null;\n  metadata?: unknown;\n};\ntype StreamPayloadChunk<TType extends string> = StreamChunkBase<TType> & { payload?: unknown };\ntype StreamObjectChunk<TType extends string> = StreamChunkBase<TType> & { object?: unknown };\ntype StreamDataChunk<TType extends `data-${string}`> = StreamChunkBase<TType> & { data?: unknown };\ntype StreamIgnoredChunk =\n  | StreamPayloadChunk<'start'>\n  | StreamPayloadChunk<'abort'>\n  | StreamPayloadChunk<'response-metadata'>\n  | StreamPayloadChunk<'reasoning-signature'>\n  | StreamPayloadChunk<'source'>\n  | StreamPayloadChunk<'file'>\n  | StreamPayloadChunk<'reasoning-file'>\n  | StreamPayloadChunk<'custom'>\n  | StreamPayloadChunk<'raw'>\n  | StreamPayloadChunk<'step-start'>\n  | StreamPayloadChunk<'tool-output'>\n  | StreamPayloadChunk<'step-output'>\n  | StreamPayloadChunk<'watch'>\n  | StreamPayloadChunk<'tripwire'>\n  | StreamPayloadChunk<'is-task-complete'>\n  | StreamPayloadChunk<'background-task-started'>\n  | StreamPayloadChunk<'background-task-completed'>\n  | StreamPayloadChunk<'background-task-failed'>\n  | StreamPayloadChunk<'background-task-progress'>\n  | StreamPayloadChunk<'background-task-running'>\n  | StreamPayloadChunk<'background-task-cancelled'>\n  | StreamPayloadChunk<'background-task-output'>\n  | StreamPayloadChunk<'background-task-suspended'>\n  | StreamPayloadChunk<'background-task-resumed'>\n  | StreamObjectChunk<'object'>\n  | StreamObjectChunk<'object-result'>;\ntype StreamChunk =\n  | StreamIgnoredChunk\n  | SpanChunk\n  | StreamPayloadChunk<'tool-call-input-streaming-start'>\n  | StreamPayloadChunk<'tool-call-delta'>\n  | StreamPayloadChunk<'tool-call-input-streaming-end'>\n  | StreamPayloadChunk<'tool-call'>\n  | StreamPayloadChunk<'tool-result'>\n  | StreamPayloadChunk<'tool-error'>\n  | StreamPayloadChunk<'tool-output-denied'>\n  | StreamPayloadChunk<'tool-call-approval'>\n  | StreamPayloadChunk<'tool-call-suspended'>\n  | StreamPayloadChunk<'error'>\n  | StreamPayloadChunk<'step-finish'>\n  | StreamPayloadChunk<'finish'>\n  | StreamPayloadChunk<'goal'>\n  | StreamDataChunk<'data-om-status'>\n  | StreamDataChunk<'data-om-observation-start'>\n  | StreamDataChunk<'data-om-observation-end'>\n  | StreamDataChunk<'data-om-observation-failed'>\n  | StreamDataChunk<'data-om-buffering-start'>\n  | StreamDataChunk<'data-om-buffering-end'>\n  | StreamDataChunk<'data-om-buffering-failed'>\n  | StreamDataChunk<'data-signal'>\n  | StreamDataChunk<'data-user-message'>\n  | StreamDataChunk<'data-system-reminder'>\n  | StreamDataChunk<'data-om-activation'>\n  | StreamDataChunk<'data-om-thread-update'>\n  | StreamDataChunk<'data-mastracode-tool-progress'>\n  | StreamDataChunk<'data-sandbox-stdout'>\n  | StreamDataChunk<'data-sandbox-stderr'>\n  | StreamDataChunk<'data-sandbox-exit'>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null;\n}\n\nfunction isProviderMetadata(value: unknown): value is MastraProviderMetadata {\n  return isRecord(value);\n}\n\nfunction getString(value: unknown): string | undefined {\n  return typeof value === 'string' ? value : undefined;\n}\n\nfunction getNumber(value: unknown, fallback: number): number {\n  return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\nfunction getOptionalNumber(value: unknown): number | undefined {\n  return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getBoolean(value: unknown, fallback: boolean): boolean {\n  return typeof value === 'boolean' ? value : fallback;\n}\n\nfunction getRecord(value: unknown): Record<string, unknown> | undefined {\n  return isRecord(value) ? value : undefined;\n}\n\nfunction getPayload(chunk: StreamChunk): StreamChunkPayload {\n  return 'payload' in chunk ? (getRecord(chunk.payload) ?? {}) : {};\n}\n\nfunction getDataRecord(chunk: StreamChunk): Record<string, unknown> | undefined {\n  return 'data' in chunk ? getRecord(chunk.data) : undefined;\n}\n\nfunction getNestedRecord(\n  record: Record<string, unknown> | undefined,\n  key: string,\n): Record<string, unknown> | undefined {\n  return record ? getRecord(record[key]) : undefined;\n}\n\nfunction isGoalEvaluationPayload(value: unknown): value is GoalEvaluationPayload {\n  const record = getRecord(value);\n  return Boolean(\n    record &&\n    typeof record.objective === 'string' &&\n    typeof record.iteration === 'number' &&\n    typeof record.maxRuns === 'number' &&\n    typeof record.passed === 'boolean' &&\n    (record.status === 'active' || record.status === 'paused' || record.status === 'done') &&\n    Array.isArray(record.results) &&\n    typeof record.duration === 'number' &&\n    typeof record.timedOut === 'boolean' &&\n    typeof record.maxRunsReached === 'boolean' &&\n    typeof record.suppressFeedback === 'boolean',\n  );\n}\n\nfunction getOperationType(value: unknown): 'observation' | 'reflection' {\n  return value === 'reflection' ? 'reflection' : 'observation';\n}\n\nfunction getActivationTrigger(value: unknown): 'ttl' | 'threshold' | 'provider_change' | undefined {\n  if (value === 'ttl' || value === 'threshold' || value === 'provider_change') return value;\n  return undefined;\n}\n\nfunction getOmStatus(value: unknown): 'idle' | 'running' | 'complete' {\n  if (value === 'running' || value === 'complete') return value;\n  return 'idle';\n}\n\nfunction formatToolProgressOutput(progress: unknown): string {\n  if (typeof progress === 'string') return progress.endsWith('\\n') ? progress : `${progress}\\n`;\n  if (typeof progress !== 'object' || progress === null) return `${String(progress)}\\n`;\n\n  const record = progress as { status?: unknown; detail?: unknown };\n  const parts = [record.status, record.detail].filter(\n    (part): part is string => typeof part === 'string' && part.length > 0,\n  );\n  return parts.length > 0 ? `${parts.join(': ')}\\n` : `${JSON.stringify(progress)}\\n`;\n}\n\nconst ABORT_STREAM_GRACE_MS = 5_000;\nconst abortBailed = Symbol('abort-bailed');\n\n/**\n * Resolves `graceMs` after an abort is requested for the session's run, but\n * only while that abort is still pending. Raced against the chunk-consuming\n * loop: a hung upstream await (e.g. a model call that never settles) ignores\n * the abort signal and would otherwise leave the loop suspended forever with\n * the session stuck in `running` — the only recovery being a server restart.\n *\n * The deadline is scoped to the abort request that armed it: if the aborted\n * run settles on its own during the grace (terminal chunk → `run.reset()`,\n * observed via teardown), the deadline re-arms for the next abort instead of\n * firing. A persistent consumer (subscribed thread stream) outlives many runs,\n * and a stale deadline must never bail a follow-up run. `guard` cancels the\n * deadline once the consuming loop settles (the value still resolves, but the\n * race is already won).\n */\nasync function abortDeadline(run: Session['run'], guard: AbortSignal, graceMs: number): Promise<typeof abortBailed> {\n  while (!guard.aborted) {\n    await run.waitForAbortRequest(guard);\n    if (guard.aborted) break;\n    if (!run.isAbortRequested()) continue;\n    const graceExpired = await new Promise<boolean>(resolve => {\n      const timer = setTimeout(() => resolve(true), graceMs);\n      void run.waitForTeardown(guard).then(() => {\n        clearTimeout(timer);\n        resolve(false);\n      });\n    });\n    if (graceExpired && run.isAbortRequested()) break;\n  }\n  return abortBailed;\n}\n\ntype StreamState = {\n  threadId?: string;\n  currentMessage: MastraDBMessage;\n  lastFinishedMessage?: MastraDBMessage;\n  messageStarted: boolean;\n  isSuspended: boolean;\n  spans: MessagePartSpans;\n  announcedTextSpans: Set<string>;\n  announcedReasoningSpans: Set<string>;\n  messageIdObserved: boolean;\n  toolPartById: Map<string, number>;\n  /** Response ids offered by `step-start` — an id binds to at most one display message. */\n  offeredResponseIds: Set<string>;\n  completedToolPrelude: boolean;\n  /**\n   * Set when a stream ends on a non-success finish reason (e.g. `content-filter`,\n   * `error`, `length`). Carries the user-facing message so the run finalizes\n   * into an explicit terminal error state instead of silently completing.\n   */\n  terminalError?: string;\n};\n\n/**\n * The per-session agent run engine: it consumes an agent's event stream, folds\n * each chunk into the session's display messages and token usage, drives tool\n * approval/suspension, and finalizes the run. In the multi-user host the run\n * loop, run state, and thread stream are per-session and cannot be shared, so\n * they live on the Session — this engine is owned by exactly one Session.\n *\n * It reaches the host only through the narrow {@link SessionMachinery} it is\n * constructed with (resolve the agent, build run/stream options, persist usage,\n * drive tool approval/resume, drain follow-ups). It never reaches back into the\n * AgentController or another session: all per-run state is read and written on its own\n * {@link Session}.\n */\nexport class SessionRunEngine {\n  readonly #session: Session;\n  readonly #machinery: SessionMachinery;\n\n  constructor(session: Session, machinery: SessionMachinery) {\n    this.#session = session;\n    this.#machinery = machinery;\n  }\n\n  private createEmptyAssistantMessage(threadId?: string): MastraDBMessage {\n    return {\n      id: this.#machinery.generateId(),\n      ...(threadId ? { threadId } : {}),\n      role: 'assistant',\n      content: { format: 2, parts: [] },\n      createdAt: new Date(),\n    };\n  }\n\n  /**\n   * Build a DB-native signal message from a streamed `data-signal` /\n   * `data-user-message` / `data-system-reminder` chunk. The raw data-part is\n   * carried verbatim on `content.parts` and the signal identity is preserved on\n   * `content.metadata.signal` so consumers read the native shape (no flattening).\n   */\n  private createSignalMessage(partType: `data-${string}`, payload: Record<string, unknown>): MastraDBMessage {\n    const part: StreamDataPart = { type: partType, data: payload };\n    const signalId = typeof payload.id === 'string' ? payload.id : this.#machinery.generateId();\n    const createdAt =\n      typeof payload.createdAt === 'string' && !Number.isNaN(Date.parse(payload.createdAt))\n        ? new Date(payload.createdAt)\n        : new Date();\n    return {\n      id: signalId,\n      role: 'signal',\n      content: {\n        format: 2,\n        parts: [part],\n        metadata: { signal: payload },\n      },\n      createdAt,\n    };\n  }\n\n  private hasCurrentMessageContent(state: StreamState): boolean {\n    return state.currentMessage.content.parts.length > 0;\n  }\n\n  private isCurrentMessageObserved(state: StreamState): boolean {\n    return this.hasCurrentMessageContent(state) || state.messageIdObserved;\n  }\n\n  private setStopReason(message: MastraDBMessage, stopReason: string, force = false): void {\n    message.content.metadata ??= {};\n    const metadata = message.content.metadata;\n    if (force) {\n      metadata.stopReason = stopReason;\n    } else {\n      metadata.stopReason ??= stopReason;\n    }\n  }\n\n  private setErrorMessage(message: MastraDBMessage, errorMessage: string): void {\n    message.content.metadata ??= {};\n    message.content.metadata.errorMessage = errorMessage;\n  }\n\n  private startCurrentMessage(state: StreamState): boolean {\n    if (state.messageStarted) return false;\n    this.#session.emit({ type: 'message_start', message: structuredClone(state.currentMessage) });\n    state.messageStarted = true;\n    return true;\n  }\n\n  private emitMessagePart(state: StreamState, index: number): void {\n    if (this.startCurrentMessage(state)) return;\n    const part = state.currentMessage.content.parts[index];\n    if (!part) return;\n    this.#session.emit({\n      type: 'message_update',\n      id: state.currentMessage.id,\n      event: { type: 'part', index, part: structuredClone(part) },\n    });\n  }\n\n  private emitInitialPart(state: StreamState, index: number, part: MastraMessagePart): void {\n    if (!state.messageStarted) {\n      const message = structuredClone(state.currentMessage);\n      message.content.parts[index] = part;\n      state.messageIdObserved = true;\n      this.#session.emit({ type: 'message_start', message });\n      state.messageStarted = true;\n      return;\n    }\n\n    this.#session.emit({\n      type: 'message_update',\n      id: state.currentMessage.id,\n      event: { type: 'part', index, part },\n    });\n  }\n\n  private finishCurrentMessage(state: StreamState): void {\n    if (!state.messageStarted) return;\n    this.#session.emit({ type: 'message_end', id: state.currentMessage.id });\n    state.messageStarted = false;\n  }\n\n  private finishCurrentMessageAndRotate(state: StreamState): void {\n    if (!this.isCurrentMessageObserved(state)) return;\n    this.setStopReason(state.currentMessage, 'complete');\n    this.finishCurrentMessage(state);\n    state.lastFinishedMessage = state.currentMessage;\n    state.currentMessage = this.createEmptyAssistantMessage(state.threadId);\n    state.spans.clear();\n    state.announcedTextSpans.clear();\n    state.announcedReasoningSpans.clear();\n    state.messageIdObserved = false;\n    state.toolPartById.clear();\n    state.completedToolPrelude = false;\n  }\n\n  createStreamState(threadId = this.#session.thread.getId() ?? undefined): StreamState {\n    return {\n      threadId,\n      currentMessage: this.createEmptyAssistantMessage(threadId),\n      messageStarted: false,\n      isSuspended: false,\n      spans: new MessagePartSpans({ providerMetadata: false }),\n      announcedTextSpans: new Set(),\n      announcedReasoningSpans: new Set(),\n      messageIdObserved: false,\n      toolPartById: new Map<string, number>(),\n      offeredResponseIds: new Set<string>(),\n      completedToolPrelude: false,\n    };\n  }\n\n  /**\n   * Fold a `tool-result`/`tool-error` chunk into the invocation part and\n   * notify — an errored tool must reach a terminal state or clients spin forever.\n   */\n  private applyToolOutcome(\n    state: StreamState,\n    outcome: {\n      toolCallId: string;\n      toolName: string;\n      result: unknown;\n      isError: boolean;\n      providerMetadata?: MastraProviderMetadata;\n    },\n  ): void {\n    const { toolCallId, toolName, result, isError, providerMetadata } = outcome;\n    const toolIndex = state.toolPartById.get(toolCallId);\n    const existing = toolIndex !== undefined ? state.currentMessage.content.parts[toolIndex] : undefined;\n    const partIndex = toolIndex ?? state.currentMessage.content.parts.length;\n    if (existing && existing.type === 'tool-invocation') {\n      existing.toolInvocation = Object.assign(existing.toolInvocation, {\n        state: 'result' as const,\n        result,\n        isError,\n      });\n      if (providerMetadata) {\n        existing.providerMetadata = providerMetadata;\n      }\n    } else {\n      const toolInvocationPart: MastraToolInvocationPart = {\n        type: 'tool-invocation',\n        toolInvocation: {\n          state: 'result',\n          toolCallId,\n          toolName,\n          args: {},\n          result,\n          isError,\n        },\n      };\n      if (providerMetadata) {\n        toolInvocationPart.providerMetadata = providerMetadata;\n      }\n      state.currentMessage.content.parts.push(toolInvocationPart);\n      state.toolPartById.set(toolCallId, partIndex);\n    }\n    this.emitMessagePart(state, partIndex);\n    this.#session.emit({\n      type: 'tool_end',\n      threadId: state.threadId,\n      toolCallId,\n      result,\n      isError,\n      ...(providerMetadata ? { providerMetadata } : {}),\n    });\n  }\n\n  private abortForOmFailure({ operationType, stage, error }: { operationType: string; stage: string; error: string }) {\n    this.#session.emit({\n      type: 'error',\n      error: new Error(`Observational memory ${operationType} ${stage} failed: ${error}`),\n    });\n    this.#session.abortRun();\n  }\n\n  /**\n   * Process a stream response. Production runs stream through\n   * `processSubscribedThreadStream`; only tests call this entry directly.\n   */\n  async processStream(\n    response: { fullStream: AsyncIterable<StreamChunk> },\n    requestContextInput?: RequestContext,\n  ): Promise<{ message: MastraDBMessage; suspended?: boolean } | undefined> {\n    const state = this.createStreamState();\n    const requestContext = await this.#machinery.buildRequestContext(requestContextInput);\n    this.#session.run.nextOperation();\n    this.#session.emit({ type: 'agent_start' });\n\n    let result: { message: MastraDBMessage; suspended?: boolean } | undefined;\n    let error = false;\n    let aborted = false;\n    let bailed = false;\n\n    const consume = async (): Promise<void> => {\n      for await (const chunk of response.fullStream) {\n        if (bailed) return;\n        result = await this.processStreamChunk(state, chunk, requestContext);\n        if (chunk.type === 'error') {\n          error = true;\n        }\n        if (chunk.type === 'abort') {\n          aborted = true;\n        }\n        if (\n          result ||\n          chunk.type === 'finish' ||\n          chunk.type === 'error' ||\n          chunk.type === 'abort' ||\n          chunk.type === 'tool-call-suspended' ||\n          this.#session.run.isAbortRequested()\n        ) {\n          result ??= this.finishStreamState(state);\n          break;\n        }\n      }\n    };\n\n    const bailGuard = new AbortController();\n    try {\n      const outcome = await Promise.race([\n        consume(),\n        abortDeadline(this.#session.run, bailGuard.signal, ABORT_STREAM_GRACE_MS),\n      ]);\n      bailed = outcome === abortBailed;\n    } finally {\n      bailGuard.abort();\n    }\n\n    result ??= this.finishStreamState(state);\n\n    // A non-success terminal finish reason (e.g. a `claude-fable-5`\n    // content-filter refusal) becomes an explicit error so the run never\n    // silently stops without a visible terminal state.\n    if (state.terminalError && !error && !aborted && !this.#session.run.isAbortRequested() && !result.suspended) {\n      error = true;\n      this.#session.emit({ type: 'error', error: new Error(state.terminalError) });\n    }\n\n    await this.#session.finishAgentRun(\n      error\n        ? 'error'\n        : result.suspended\n          ? 'suspended'\n          : aborted || this.#session.run.isAbortRequested()\n            ? 'aborted'\n            : 'complete',\n    );\n\n    this.#session.run.reset();\n\n    return result;\n  }\n\n  /**\n   * Mutates and emits one live accumulated message throughout the assistant turn.\n   * Consumers that require a point-in-time value must copy or serialize at their\n   * ownership boundary. Do not restore producer-side per-delta snapshots: even\n   * selective snapshots retain growing historical text and allocate message/part\n   * shells for every token.\n   */\n  async processStreamChunk(\n    state: StreamState,\n    chunk: StreamChunk,\n    requestContext: RequestContext,\n    agent: Agent = this.#machinery.getAgent(),\n  ): Promise<{ message: MastraDBMessage; suspended?: boolean } | undefined> {\n    if ('runId' in chunk && chunk.runId) {\n      this.#session.run.setRunId({ runId: chunk.runId });\n    }\n\n    if (isSpanChunk(chunk)) {\n      const partIndex = state.currentMessage.content.parts.length;\n      if (chunk.type === 'text-start') {\n        state.spans.fold(state.currentMessage.content.parts, chunk);\n        const part = state.spans.openTextSpan(state.currentMessage.content.parts, chunk.payload.id);\n        state.announcedTextSpans.add(chunk.payload.id);\n        this.emitInitialPart(state, partIndex, structuredClone(part));\n        return undefined;\n      }\n      if (chunk.type === 'reasoning-start') {\n        state.spans.fold(state.currentMessage.content.parts, chunk);\n        const part = state.spans.openReasoningSpan(state.currentMessage.content.parts, chunk.payload.id);\n        state.announcedReasoningSpans.add(chunk.payload.id);\n        this.emitInitialPart(state, partIndex, structuredClone(part));\n        return undefined;\n      }\n\n      const folded = state.spans.fold(state.currentMessage.content.parts, chunk);\n      if (!folded) return undefined;\n\n      const index = state.currentMessage.content.parts.indexOf(folded.part);\n      if (index === -1) return undefined;\n\n      if (chunk.type === 'text-delta' && folded.part.type === 'text') {\n        if (!state.announcedTextSpans.delete(chunk.payload.id) && folded.created) {\n          this.emitInitialPart(state, index, { ...folded.part, text: '' });\n        }\n        this.#session.emit({\n          type: 'message_update',\n          id: state.currentMessage.id,\n          event: { type: 'text-delta', delta: chunk.payload.text },\n        });\n      } else if (chunk.type === 'reasoning-delta' && folded.part.type === 'reasoning') {\n        if (!state.announcedReasoningSpans.delete(chunk.payload.id) && folded.created) {\n          this.emitMessagePart(state, index);\n        } else {\n          this.#session.emit({\n            type: 'message_update',\n            id: state.currentMessage.id,\n            event: { type: 'reasoning-delta', index, delta: chunk.payload.text },\n          });\n        }\n      } else {\n        this.emitMessagePart(state, index);\n      }\n      return undefined;\n    }\n\n    switch (chunk.type) {\n      case 'step-start': {\n        // Adopt the loop's response message id so the streamed turn and its\n        // persisted copy share one identity (clients dedupe by id). The loop\n        // mints a new id only when it seals one persisted response and opens\n        // the next, so every id after the first marks that boundary — rotate\n        // with it, or the persisted tail comes back as a duplicate on reload.\n        // An emitted id never changes, and an id binds to one message only.\n        const messageId = getString(getPayload(chunk).messageId);\n        if (!messageId || state.offeredResponseIds.has(messageId)) break;\n        // A resumed tool can finish before the first model step starts. Seal\n        // that tool-only prelude without changing its already observable id.\n        if (\n          state.offeredResponseIds.size > 0 ||\n          (state.completedToolPrelude &&\n            state.currentMessage.content.parts.every(\n              part => part.type === 'tool-invocation' && part.toolInvocation.state === 'result',\n            ))\n        ) {\n          this.finishCurrentMessageAndRotate(state);\n        }\n        state.completedToolPrelude = false;\n        state.offeredResponseIds.add(messageId);\n        if (!this.isCurrentMessageObserved(state)) {\n          state.currentMessage.id = messageId;\n        }\n        break;\n      }\n\n      case 'tool-call-input-streaming-start': {\n        const payload = getPayload(chunk);\n        const toolCallId = getString(payload.toolCallId) ?? '';\n        const toolName = getString(payload.toolName) ?? '';\n        this.#session.emit({ type: 'tool_input_start', threadId: state.threadId, toolCallId, toolName });\n        break;\n      }\n\n      case 'tool-call-delta': {\n        const payload = getPayload(chunk);\n        const toolCallId = getString(payload.toolCallId) ?? '';\n        const argsTextDelta = getString(payload.argsTextDelta) ?? '';\n        const toolName = getString(payload.toolName);\n        const transform = getTransformedToolPayload(chunk.metadata, 'display', 'input-delta');\n        if (!transform?.suppress) {\n          this.#session.emit({\n            type: 'tool_input_delta',\n            threadId: state.threadId,\n            toolCallId,\n            argsTextDelta: hasTransformedToolPayload(transform) ? transform.transformed : argsTextDelta,\n            toolName,\n          });\n        }\n        break;\n      }\n\n      case 'tool-call-input-streaming-end': {\n        const toolCallId = getString(getPayload(chunk).toolCallId) ?? '';\n        this.#session.emit({ type: 'tool_input_end', threadId: state.threadId, toolCallId });\n        break;\n      }\n\n      case 'tool-call': {\n        const toolCall = getPayload(chunk);\n        const toolCallId = getString(toolCall.toolCallId) ?? '';\n        const toolName = getString(toolCall.toolName) ?? '';\n        const args = getDisplayTransform(chunk.metadata, 'input-available', toolCall.args);\n        const toolIndex = state.currentMessage.content.parts.length;\n        state.currentMessage.content.parts.push({\n          type: 'tool-invocation',\n          toolInvocation: {\n            state: 'call',\n            toolCallId,\n            toolName,\n            args,\n          },\n        });\n        state.toolPartById.set(toolCallId, toolIndex);\n        this.emitMessagePart(state, toolIndex);\n        this.#session.emit({\n          type: 'tool_start',\n          threadId: state.threadId,\n          toolCallId,\n          toolName,\n          args,\n        });\n        break;\n      }\n\n      case 'tool-result': {\n        const toolResult = getPayload(chunk);\n        this.applyToolOutcome(state, {\n          toolCallId: getString(toolResult.toolCallId) ?? '',\n          toolName: getString(toolResult.toolName) ?? '',\n          result: getDisplayTransform(chunk.metadata, 'output-available', toolResult.result),\n          isError: getBoolean(toolResult.isError, false),\n          providerMetadata: isProviderMetadata(toolResult.providerMetadata) ? toolResult.providerMetadata : undefined,\n        });\n        break;\n      }\n\n      case 'tool-error': {\n        const toolError = getPayload(chunk);\n        // Error instances JSON-serialize to `{}`; keep the message so failure text survives SSE + persistence.\n        this.applyToolOutcome(state, {\n          toolCallId: getString(toolError.toolCallId) ?? '',\n          toolName: getString(toolError.toolName) ?? '',\n          result: getDisplayTransform(chunk.metadata, 'error', getErrorFromUnknown(toolError.error).message),\n          isError: true,\n          providerMetadata: isProviderMetadata(toolError.providerMetadata) ? toolError.providerMetadata : undefined,\n        });\n        break;\n      }\n\n      case 'tool-output-denied': {\n        const payload = getPayload(chunk);\n        const toolCallId = getString(payload.toolCallId) ?? '';\n        const toolName = getString(payload.toolName) ?? '';\n        const approval = getRecord(payload.approval);\n        const reason = getString(approval?.reason);\n        const approvalTransform = getTransformedToolPayload(chunk.metadata, 'display', 'approval');\n        const args = hasTransformedToolPayload(approvalTransform)\n          ? approvalTransform.transformed\n          : getDisplayTransform(chunk.metadata, 'input-available', payload.args);\n        const toolIndex = state.toolPartById.get(toolCallId);\n        const existing = toolIndex !== undefined ? state.currentMessage.content.parts[toolIndex] : undefined;\n        const toolInvocation = {\n          state: 'output-denied' as const,\n          toolCallId,\n          toolName,\n          args,\n          approval: {\n            id: getString(approval?.id) ?? '',\n            approved: false as const,\n            ...(reason ? { reason } : {}),\n          },\n        };\n\n        const partIndex = toolIndex ?? state.currentMessage.content.parts.length;\n        if (existing && existing.type === 'tool-invocation') {\n          existing.toolInvocation = Object.assign(existing.toolInvocation, toolInvocation);\n        } else {\n          state.currentMessage.content.parts.push({ type: 'tool-invocation', toolInvocation });\n          state.toolPartById.set(toolCallId, partIndex);\n        }\n\n        this.emitMessagePart(state, partIndex);\n        this.#session.emit({\n          type: 'tool_end',\n          threadId: state.threadId,\n          toolCallId,\n          result: reason,\n          isError: false,\n          denied: true,\n        });\n        break;\n      }\n\n      case 'tool-call-approval': {\n        const toolCallId = getString(getPayload(chunk).toolCallId) ?? '';\n        const toolName = getString(getPayload(chunk).toolName) ?? '';\n        const approvalTransform = getTransformedToolPayload(chunk.metadata, 'display', 'approval');\n        const toolArgs = hasTransformedToolPayload(approvalTransform)\n          ? approvalTransform.transformed\n          : getDisplayTransform(chunk.metadata, 'input-available', getPayload(chunk).args);\n\n        const policy = this.#session.resolveToolApproval(toolName);\n\n        if (policy === 'allow') {\n          await this.#session.approveToolCall({ toolCallId, requestContext });\n          break;\n        }\n\n        if (policy === 'deny') {\n          await this.#session.declineToolCall({ toolCallId, requestContext });\n          break;\n        }\n\n        const approvalPromise = this.#session.approval.arm({ toolName, toolCallId });\n        this.#session.emit({\n          type: 'tool_approval_required',\n          threadId: state.threadId,\n          toolCallId,\n          toolName,\n          args: toolArgs,\n        });\n\n        const approval = await approvalPromise;\n        this.#session.approval.clearToolName();\n\n        // `session.abort()` releases a parked gate as a decline and defers the\n        // stream/signal teardown to us, so the decline can still be driven\n        // through the (live) agent run and persist an `output-denied` result.\n        // Once it lands we finish the teardown, which stops the run rather than\n        // letting the model continue past the denied call.\n        const deferredAbort = this.#session.run.isAbortRequested();\n\n        if (!deferredAbort && approval.decision === 'approve') {\n          await this.#session.approveToolCall({\n            toolCallId,\n            requestContext: approval.requestContext ?? requestContext,\n          });\n        } else {\n          await this.#session.declineToolCall({\n            toolCallId,\n            requestContext: approval.requestContext ?? requestContext,\n            declineContext: deferredAbort\n              ? { reason: ABORTED_BY_USER_REASON, message: ABORTED_BY_USER_REASON }\n              : approval.declineContext,\n          });\n        }\n\n        if (deferredAbort) {\n          // The denial chunk the agent emits for this decline can never reach\n          // us: we are blocking the consumer loop that would read it, and the\n          // teardown below ends the loop. Settle the call locally so the\n          // display state shows the denied result instead of a call stuck\n          // mid-flight.\n          this.settleToolCallAsDenied(state, { toolCallId, toolName, args: toolArgs });\n          this.#session.completeDeferredAbort();\n        }\n        break;\n      }\n\n      case 'tool-call-suspended': {\n        const suspToolCallId = getString(getPayload(chunk).toolCallId) ?? '';\n        const suspToolName = getString(getPayload(chunk).toolName) ?? '';\n        const suspArgs = getDisplayTransform(chunk.metadata, 'input-available', getPayload(chunk).args);\n        const suspPayload = getDisplayTransform(chunk.metadata, 'suspend', getPayload(chunk).suspendPayload);\n        const suspResumeSchema = getString(getPayload(chunk).resumeSchema);\n\n        // Capture the whole binding before the memory-resolution await below:\n        // a rebind during that await must not pair this run with the new\n        // session's resource.\n        const suspRunId = this.#session.run.getRunId();\n        const suspThreadId = this.#session.thread.getId();\n        const suspResourceId = this.#session.identity.getResourceId();\n        if (suspRunId) {\n          const runScope = this.#machinery.getRunScope(suspRunId);\n          // A subscription restored for the current mode can replay this\n          // suspension after a plan→build transition. Keep the agent that first\n          // owned the run so a later resume reaches its original snapshot.\n          if (!runScope?.get(SUSPENDED_RUN_AGENT_KEY)) {\n            runScope?.set(SUSPENDED_RUN_AGENT_KEY, agent);\n          }\n          // Resolve the run's memory with its own RequestContext while the\n          // stream is still live: abort settlement runs after the context is\n          // gone, and a dynamic memory config would resolve differently (or\n          // not at all) against an empty context. A resolution failure is not\n          // fatal — settlement falls back to a bare getMemory().\n          if (runScope && !runScope.get(SUSPENDED_RUN_MEMORY_KEY)) {\n            try {\n              const suspMemory = await agent.getMemory({ requestContext });\n              if (suspMemory) runScope.set(SUSPENDED_RUN_MEMORY_KEY, suspMemory);\n            } catch {\n              // Leave the key unset; settlement uses its fallback path.\n            }\n          }\n          if (suspThreadId) {\n            // Record the thread/resource the stream is bound to right now: if\n            // the session is later rebound while this run stays suspended,\n            // abort settlement must still target where the suspended\n            // invocation was persisted. register() preserves the original\n            // binding when a replayed stream re-emits the same suspension.\n            this.#session.suspensions.register({\n              toolCallId: suspToolCallId,\n              runId: suspRunId,\n              toolName: suspToolName,\n              threadId: suspThreadId,\n              resourceId: suspResourceId,\n            });\n          }\n        }\n        state.isSuspended = true;\n\n        this.#session.emit({\n          type: 'tool_suspended',\n          threadId: state.threadId,\n          toolCallId: suspToolCallId,\n          toolName: suspToolName,\n          args: suspArgs,\n          suspendPayload: suspPayload,\n          resumeSchema: suspResumeSchema,\n        });\n\n        break;\n      }\n\n      case 'error': {\n        const streamError = getErrorFromUnknown(getPayload(chunk).error);\n        this.#session.emit({ type: 'error', error: streamError });\n        this.retractFailedRunSuspensions({\n          runId: chunk.runId ?? this.#session.run.getRunId(),\n          reason: streamError.message,\n        });\n        break;\n      }\n\n      case 'step-finish': {\n        state.completedToolPrelude =\n          state.offeredResponseIds.size === 0 &&\n          this.hasCurrentMessageContent(state) &&\n          state.currentMessage.content.parts.every(\n            part => part.type === 'tool-invocation' && part.toolInvocation.state === 'result',\n          );\n        const usage = getRecord(getPayload(chunk).output)?.usage;\n        const usageRecord = getRecord(usage);\n        if (usageRecord) {\n          // A step whose usage payload carries no usable primary count (missing,\n          // nested-object, or all-undefined shapes) must NOT be coerced into a\n          // {0,0,0} tally: doing so fabricates a false `usage_update` event and\n          // persists a false zero that is indistinguishable from a measured zero.\n          // Only fold/persist/emit when at least one primary count is present.\n          // A genuine measured zero arrives as an explicit numeric 0, which\n          // `getUsageNumber` reports as present.\n          const rawPrompt = getUsageNumber(usageRecord, 'promptTokens') ?? getUsageNumber(usageRecord, 'inputTokens');\n          const rawCompletion =\n            getUsageNumber(usageRecord, 'completionTokens') ?? getUsageNumber(usageRecord, 'outputTokens');\n          const rawTotal = getUsageNumber(usageRecord, 'totalTokens');\n          const hasPrimaryCount = rawPrompt !== undefined || rawCompletion !== undefined || rawTotal !== undefined;\n          if (hasPrimaryCount) {\n            const promptTokens = rawPrompt ?? 0;\n            const completionTokens = rawCompletion ?? 0;\n            const totalTokens = rawTotal ?? promptTokens + completionTokens;\n            const stepUsage: TokenUsage = {\n              promptTokens,\n              completionTokens,\n              totalTokens,\n            };\n            addOptionalUsageField(stepUsage, 'reasoningTokens', getUsageNumber(usageRecord, 'reasoningTokens'));\n            addOptionalUsageField(stepUsage, 'cachedInputTokens', getUsageNumber(usageRecord, 'cachedInputTokens'));\n            addOptionalUsageField(\n              stepUsage,\n              'cacheCreationInputTokens',\n              getUsageNumber(usageRecord, 'cacheCreationInputTokens'),\n            );\n            addOptionalUsageField(\n              stepUsage,\n              'cacheCreationInputTokens5m',\n              getUsageNumber(usageRecord, 'cacheCreationInputTokens5m'),\n            );\n            addOptionalUsageField(\n              stepUsage,\n              'cacheCreationInputTokens1h',\n              getUsageNumber(usageRecord, 'cacheCreationInputTokens1h'),\n            );\n            if (usageRecord.raw !== undefined) {\n              stepUsage.raw = usageRecord.raw;\n            }\n\n            this.#session.addUsage(stepUsage);\n\n            this.#machinery.persistTokenUsage().catch(() => {});\n            this.#session.emit({ type: 'usage_update', usage: stepUsage });\n          }\n        }\n        break;\n      }\n\n      case 'finish': {\n        const finishReason = getString(getRecord(getPayload(chunk).stepResult)?.reason) ?? '';\n        const finishProviderMetadata =\n          getRecord(getPayload(chunk).metadata)?.providerMetadata ?? getPayload(chunk).providerMetadata;\n        // A server-side fallback means the turn was answered by a different\n        // model than the one the user selected (e.g. fable-5 declined and the\n        // fallback served the response). Surface that, otherwise the\n        // substitution is invisible.\n        const fallbackNotice = describeServerSideFallback(finishProviderMetadata);\n        if (fallbackNotice) {\n          this.#session.emit({ type: 'info', message: fallbackNotice });\n        }\n        if (finishReason === 'stop' || finishReason === 'end-turn') {\n          this.setStopReason(state.currentMessage, 'complete', true);\n        } else if (finishReason === 'tool-calls') {\n          this.setStopReason(state.currentMessage, 'tool_use', true);\n        } else {\n          // Non-success terminal reasons (e.g. `content-filter` from a\n          // `claude-fable-5` refusal, `error`, or `length`) must become an\n          // explicit terminal error rather than a silent `complete`. Otherwise\n          // the run ends with no final message and no error, leaving the user\n          // unable to tell whether it completed, failed, or is still active.\n          const errorMessage = describeNonSuccessFinishReason(finishReason, finishProviderMetadata);\n          if (errorMessage) {\n            this.setStopReason(state.currentMessage, 'error', true);\n            this.setErrorMessage(state.currentMessage, errorMessage);\n            state.terminalError = errorMessage;\n          } else {\n            this.setStopReason(state.currentMessage, 'complete', true);\n          }\n        }\n        break;\n      }\n\n      case 'goal': {\n        // In-loop goal evaluation marks a boundary between assistant attempts.\n        // Close the current assistant message before rendering the judge result\n        // so a continuation starts a fresh message instead of overwriting the\n        // previous attempt in streaming UIs.\n        this.finishCurrentMessageAndRotate(state);\n        // Forward the payload so consumers (the TUI's judge display) can render\n        // judge progress and the decision.\n        const goalPayload = getPayload(chunk);\n        if (isGoalEvaluationPayload(goalPayload)) {\n          this.#session.emit({ type: 'goal_evaluation', payload: goalPayload });\n        }\n        break;\n      }\n\n      // Observational Memory data parts\n      // NOTE: OM data parts arrive in { type, data: { ... } } form — NOT { type, payload }\n      case 'data-om-status': {\n        const d = getDataRecord(chunk);\n        const w = getRecord(d?.windows);\n        if (d && w) {\n          const active = getNestedRecord(w, 'active');\n          const msgs = getNestedRecord(active, 'messages');\n          const obs = getNestedRecord(active, 'observations');\n          const buffered = getNestedRecord(w, 'buffered');\n          const buffObs = getNestedRecord(buffered, 'observations');\n          const buffRef = getNestedRecord(buffered, 'reflection');\n\n          this.#session.emit({\n            type: 'om_status',\n            windows: {\n              active: {\n                messages: { tokens: getNumber(msgs?.tokens, 0), threshold: getNumber(msgs?.threshold, 0) },\n                observations: { tokens: getNumber(obs?.tokens, 0), threshold: getNumber(obs?.threshold, 0) },\n              },\n              buffered: {\n                observations: {\n                  status: getOmStatus(buffObs?.status),\n                  chunks: getNumber(buffObs?.chunks, 0),\n                  messageTokens: getNumber(buffObs?.messageTokens, 0),\n                  projectedMessageRemoval: getNumber(buffObs?.projectedMessageRemoval, 0),\n                  observationTokens: getNumber(buffObs?.observationTokens, 0),\n                },\n                reflection: {\n                  status: getOmStatus(buffRef?.status),\n                  inputObservationTokens: getNumber(buffRef?.inputObservationTokens, 0),\n                  observationTokens: getNumber(buffRef?.observationTokens, 0),\n                },\n              },\n            },\n            recordId: getString(d.recordId) ?? '',\n            threadId: getString(d.threadId) ?? '',\n            stepNumber: getNumber(d.stepNumber, 0),\n            generationCount: getNumber(d.generationCount, 0),\n          });\n        }\n        break;\n      }\n      case 'data-om-observation-start': {\n        const payload = getDataRecord(chunk);\n        const cycleId = getString(payload?.cycleId);\n        if (payload && cycleId) {\n          const operationType = getOperationType(payload.operationType);\n          if (operationType === 'observation') {\n            this.#session.emit({\n              type: 'om_observation_start',\n              cycleId,\n              operationType,\n              tokensToObserve: getNumber(payload.tokensToObserve, 0),\n            });\n          } else {\n            this.#session.emit({\n              type: 'om_reflection_start',\n              cycleId,\n              tokensToReflect: getNumber(payload.tokensToObserve, 0),\n            });\n          }\n        }\n        break;\n      }\n      case 'data-om-observation-end': {\n        const payload = getDataRecord(chunk);\n        const cycleId = getString(payload?.cycleId);\n        if (payload && cycleId) {\n          if (payload.operationType === 'reflection') {\n            this.#session.emit({\n              type: 'om_reflection_end',\n              cycleId,\n              durationMs: getNumber(payload.durationMs, 0),\n              compressedTokens: getNumber(payload.observationTokens, 0),\n              observations: getString(payload.observations),\n            });\n          } else {\n            this.#session.emit({\n              type: 'om_observation_end',\n              cycleId,\n              durationMs: getNumber(payload.durationMs, 0),\n              tokensObserved: getNumber(payload.tokensObserved, 0),\n              observationTokens: getNumber(payload.observationTokens, 0),\n              observations: getString(payload.observations),\n              currentTask: getString(payload.currentTask),\n              suggestedResponse: getString(payload.suggestedResponse),\n            });\n          }\n        }\n        break;\n      }\n      case 'data-om-observation-failed': {\n        const payload = getDataRecord(chunk);\n        if (payload) {\n          const operationType = getOperationType(payload.operationType);\n          const error = getString(payload.error) ?? 'Unknown error';\n\n          if (operationType === 'reflection') {\n            this.#session.emit({\n              type: 'om_reflection_failed',\n              cycleId: getString(payload.cycleId) ?? 'unknown',\n              error,\n              durationMs: getNumber(payload.durationMs, 0),\n            });\n          } else {\n            this.#session.emit({\n              type: 'om_observation_failed',\n              cycleId: getString(payload.cycleId) ?? 'unknown',\n              error,\n              durationMs: getNumber(payload.durationMs, 0),\n            });\n          }\n\n          this.abortForOmFailure({ operationType, stage: 'run', error });\n          return { message: state.currentMessage };\n        }\n        break;\n      }\n      // Async buffering lifecycle\n      case 'data-om-buffering-start': {\n        const payload = getDataRecord(chunk);\n        const cycleId = getString(payload?.cycleId);\n        if (payload && cycleId) {\n          this.#session.emit({\n            type: 'om_buffering_start',\n            cycleId,\n            operationType: getOperationType(payload.operationType),\n            tokensToBuffer: getNumber(payload.tokensToBuffer, 0),\n          });\n        }\n        break;\n      }\n      case 'data-om-buffering-end': {\n        const payload = getDataRecord(chunk);\n        const cycleId = getString(payload?.cycleId);\n        if (payload && cycleId) {\n          this.#session.emit({\n            type: 'om_buffering_end',\n            cycleId,\n            operationType: getOperationType(payload.operationType),\n            tokensBuffered: getNumber(payload.tokensBuffered, 0),\n            bufferedTokens: getNumber(payload.bufferedTokens, 0),\n            observations: getString(payload.observations),\n          });\n        }\n        break;\n      }\n      case 'data-om-buffering-failed': {\n        const payload = getDataRecord(chunk);\n        if (payload) {\n          const operationType = getOperationType(payload.operationType);\n          const error = getString(payload.error) ?? 'Unknown error';\n\n          this.#session.emit({\n            type: 'om_buffering_failed',\n            cycleId: getString(payload.cycleId) ?? 'unknown',\n            operationType,\n            error,\n          });\n\n          this.abortForOmFailure({ operationType, stage: 'buffering', error });\n          return { message: state.currentMessage };\n        }\n        break;\n      }\n      case 'data-signal': {\n        const payload = getDataRecord(chunk);\n        if (payload) {\n          const message = this.createSignalMessage('data-signal', payload);\n          this.#session.emit({ type: 'message_start', message });\n          this.#session.emit({ type: 'message_end', id: message.id });\n        }\n        break;\n      }\n      case 'data-user-message': {\n        const payload = getDataRecord(chunk);\n        if (payload) {\n          this.finishCurrentMessageAndRotate(state);\n          const message = this.createSignalMessage('data-user-message', payload);\n          this.#session.emit({ type: 'message_start', message });\n          this.#session.emit({ type: 'message_end', id: message.id });\n        }\n        break;\n      }\n      // Back-compat: persisted streams may still contain data-system-reminder parts\n      case 'data-system-reminder': {\n        const payload = getDataRecord(chunk);\n        if (payload) {\n          const message = this.createSignalMessage('data-system-reminder', payload);\n          this.#session.emit({ type: 'message_start', message });\n          this.#session.emit({ type: 'message_end', id: message.id });\n        }\n        break;\n      }\n      case 'data-om-activation': {\n        const payload = getDataRecord(chunk);\n        const cycleId = getString(payload?.cycleId);\n        if (payload && cycleId) {\n          this.#session.emit({\n            type: 'om_activation',\n            cycleId,\n            operationType: getOperationType(payload.operationType),\n            chunksActivated: getNumber(payload.chunksActivated, 0),\n            tokensActivated: getNumber(payload.tokensActivated, 0),\n            observationTokens: getNumber(payload.observationTokens, 0),\n            messagesActivated: getNumber(payload.messagesActivated, 0),\n            generationCount: getNumber(payload.generationCount, 0),\n            triggeredBy: getActivationTrigger(payload.triggeredBy),\n            lastActivityAt: getOptionalNumber(payload.lastActivityAt),\n            ttlExpiredMs: getOptionalNumber(payload.ttlExpiredMs),\n            activateAfterIdle: getOptionalNumber(getRecord(payload.config)?.activateAfterIdle),\n            previousModel: getString(payload.previousModel),\n            currentModel: getString(payload.currentModel),\n          });\n        }\n        break;\n      }\n      case 'data-om-thread-update': {\n        const payload = getDataRecord(chunk);\n        const newTitle = getString(payload?.newTitle);\n        if (payload && newTitle) {\n          this.#session.emit({\n            type: 'om_thread_title_updated',\n            cycleId: getString(payload.cycleId) ?? 'unknown',\n            threadId: getString(payload.threadId) ?? this.#session.thread.getId() ?? 'unknown',\n            oldTitle: getString(payload.oldTitle),\n            newTitle,\n          });\n        }\n        break;\n      }\n\n      case 'data-mastracode-tool-progress': {\n        const d = (chunk as any).data as Record<string, any> | undefined;\n        if (d?.toolCallId && d?.progress !== undefined) {\n          this.#session.emit({\n            type: 'tool_update',\n            threadId: state.threadId,\n            toolCallId: d.toolCallId,\n            partialResult: d.progress,\n          });\n          const output = formatToolProgressOutput(d.progress);\n          if (output) {\n            this.#session.emit({\n              type: 'shell_output',\n              threadId: state.threadId,\n              toolCallId: d.toolCallId,\n              output,\n              stream: 'stdout',\n            });\n          }\n        }\n        break;\n      }\n\n      // Sandbox streaming data chunks (from workspace execute_command tool)\n      case 'data-sandbox-stdout': {\n        const d = getDataRecord(chunk);\n        const output = getString(d?.output);\n        const toolCallId = getString(d?.toolCallId);\n        if (output && toolCallId) {\n          this.#session.emit({ type: 'shell_output', threadId: state.threadId, toolCallId, output, stream: 'stdout' });\n        }\n        break;\n      }\n      case 'data-sandbox-stderr': {\n        const d = getDataRecord(chunk);\n        const output = getString(d?.output);\n        const toolCallId = getString(d?.toolCallId);\n        if (output && toolCallId) {\n          this.#session.emit({ type: 'shell_output', threadId: state.threadId, toolCallId, output, stream: 'stderr' });\n        }\n        break;\n      }\n      case 'data-sandbox-exit': {\n        const d = getDataRecord(chunk);\n        const toolCallId = getString(d?.toolCallId);\n        const exitCode = getOptionalNumber(d?.exitCode);\n        if (toolCallId && exitCode !== undefined) {\n          this.#session.emit({\n            type: 'command_exit',\n            threadId: state.threadId,\n            toolCallId,\n            exitCode,\n            success: getBoolean(d?.success, exitCode === 0),\n          });\n        }\n        break;\n      }\n\n      default:\n        break;\n    }\n  }\n\n  /**\n   * Settle parked native tool suspensions before aborting their suspended run.\n   * The run cannot emit another chunk after `suspend()`, so update the saved\n   * assistant message directly instead of leaving its tool invocation in\n   * `state: 'call'` forever.\n   *\n   * Each suspension is settled through its own originating binding: the agent\n   * retained on its run scope and the thread/resource it was persisted under.\n   * The session may have been rebound (new thread, resource, or agent) while\n   * the run stayed suspended, so the current binding cannot be assumed. If one\n   * suspension fails to settle, the rest are still attempted and the first\n   * error is rethrown for the caller to surface.\n   */\n  async settleSuspendedToolCallsAsDenied(\n    suspensions: Array<{ toolCallId: string; runId: string; toolName: string; threadId: string; resourceId: string }>,\n  ): Promise<void> {\n    if (suspensions.length === 0) return;\n\n    const currentMessage = this.#session.displayState.get().currentMessage;\n    const currentThreadId = this.#session.thread.getId();\n    const currentResourceId = this.#session.identity.getResourceId();\n    const currentMessageUpdates = new Map<number, MastraMessagePart>();\n    let firstError: Error | undefined;\n\n    for (const suspension of suspensions) {\n      try {\n        const runScope = this.#machinery.getRunScope(suspension.runId);\n        const agent = runScope?.get(SUSPENDED_RUN_AGENT_KEY) ?? this.#machinery.getAgent();\n        // Prefer the memory resolved with the run's own RequestContext at\n        // suspension time; a bare getMemory() cannot see context-dependent\n        // (dynamic or inherited) memory configs.\n        const memory = runScope?.get(SUSPENDED_RUN_MEMORY_KEY) ?? (await agent.getMemory());\n        const persistedMessages = memory\n          ? (await memory.recall({ threadId: suspension.threadId, resourceId: suspension.resourceId })).messages\n          : [];\n        // The live display message belongs to the session's current binding;\n        // only treat it as a candidate when this suspension originated there.\n        const candidates =\n          currentMessage && suspension.threadId === currentThreadId && suspension.resourceId === currentResourceId\n            ? [currentMessage, ...persistedMessages]\n            : persistedMessages;\n        const changedMessages = new Map<string, MastraDBMessage>();\n        let settled = false;\n\n        for (const message of candidates) {\n          const partIndex = message.content.parts.findIndex(\n            part => part.type === 'tool-invocation' && part.toolInvocation.toolCallId === suspension.toolCallId,\n          );\n          const part = message.content.parts[partIndex];\n          if (!part || part.type !== 'tool-invocation' || part.toolInvocation.state !== 'call') continue;\n\n          part.toolInvocation = Object.assign(part.toolInvocation, {\n            state: 'output-denied' as const,\n            approval: { id: suspension.toolCallId, approved: false as const, reason: ABORTED_BY_USER_REASON },\n          });\n          if (message.threadId) changedMessages.set(message.id, message);\n          if (message === currentMessage) currentMessageUpdates.set(partIndex, part);\n          settled = true;\n        }\n\n        if (settled) {\n          this.#session.emit({\n            type: 'tool_end',\n            threadId: suspension.threadId,\n            toolCallId: suspension.toolCallId,\n            result: ABORTED_BY_USER_REASON,\n            isError: false,\n            denied: true,\n          });\n        }\n        if (changedMessages.size > 0) {\n          await memory?.saveMessages({ messages: [...changedMessages.values()] });\n        }\n      } catch (error) {\n        firstError ??= getErrorFromUnknown(error);\n      }\n    }\n\n    if (currentMessage) {\n      for (const [index, part] of currentMessageUpdates) {\n        this.#session.emit({\n          type: 'message_update',\n          id: currentMessage.id,\n          event: { type: 'part', index, part: structuredClone(part) },\n        });\n      }\n    }\n\n    if (firstError) throw firstError;\n  }\n\n  /**\n   * Mark a tool call as denied on the in-flight assistant message and notify\n   * subscribers, mirroring what the `tool-output-denied` chunk would do. Used\n   * when the run is torn down before that chunk can be consumed (abort while a\n   * tool-approval gate is parked).\n   */\n  private settleToolCallAsDenied(\n    state: StreamState,\n    { toolCallId, toolName, args }: { toolCallId: string; toolName: string; args: unknown },\n  ): void {\n    const toolInvocation: MastraToolInvocationPart['toolInvocation'] = {\n      state: 'output-denied',\n      toolCallId,\n      toolName,\n      args,\n      approval: { id: toolCallId, approved: false, reason: ABORTED_BY_USER_REASON },\n    };\n\n    const toolIndex = state.toolPartById.get(toolCallId);\n    const existing = toolIndex !== undefined ? state.currentMessage.content.parts[toolIndex] : undefined;\n    const partIndex = toolIndex ?? state.currentMessage.content.parts.length;\n    if (existing && existing.type === 'tool-invocation') {\n      existing.toolInvocation = Object.assign(existing.toolInvocation, toolInvocation);\n    } else {\n      state.currentMessage.content.parts.push({ type: 'tool-invocation', toolInvocation });\n      state.toolPartById.set(toolCallId, partIndex);\n    }\n\n    this.emitMessagePart(state, partIndex);\n    this.#session.emit({\n      type: 'tool_end',\n      threadId: state.threadId,\n      toolCallId,\n      result: ABORTED_BY_USER_REASON,\n      isError: false,\n      denied: true,\n    });\n  }\n\n  private finishStreamState(state: StreamState): { message: MastraDBMessage; suspended?: boolean } {\n    if (this.hasCurrentMessageContent(state) || !state.lastFinishedMessage) {\n      this.finishCurrentMessage(state);\n      return { message: state.currentMessage, suspended: state.isSuspended || undefined };\n    }\n\n    return { message: state.lastFinishedMessage, suspended: state.isSuspended || undefined };\n  }\n\n  private async finishSubscribedStreamRun({\n    suspended,\n    error,\n    aborted,\n  }: {\n    suspended?: boolean;\n    error?: boolean;\n    aborted?: boolean;\n  }): Promise<void> {\n    const reason = error\n      ? 'error'\n      : suspended\n        ? 'suspended'\n        : aborted || this.#session.run.isAbortRequested()\n          ? 'aborted'\n          : 'complete';\n    await this.#session.finishAgentRun(reason);\n    this.#session.run.reset();\n  }\n\n  private retractFailedRunSuspensions({ runId, reason }: { runId: string | null; reason: string }): void {\n    if (!runId) return;\n\n    for (const { toolCallId, toolName } of this.#session.suspensions.deleteForRun({ runId })) {\n      this.#session.emit({\n        type: 'tool_suspension_cancelled',\n        toolCallId,\n        toolName,\n        reason,\n      });\n    }\n  }\n\n  private async handleSubscribedStreamError(error: unknown): Promise<void> {\n    if (error instanceof Error && error.name === 'AbortError') {\n      await this.#session.finishAgentRun('aborted');\n    } else {\n      const streamError = getErrorFromUnknown(error);\n      this.#session.emit({ type: 'error', error: streamError });\n      this.retractFailedRunSuspensions({ runId: this.#session.run.getRunId(), reason: streamError.message });\n      await this.#session.finishAgentRun('error');\n    }\n    this.#session.stream.detach();\n    this.#session.run.reset();\n  }\n\n  async processSubscribedThreadStream(subscription: AgentThreadSubscription<StreamChunk>): Promise<void> {\n    const threadId = this.#session.thread.getId() ?? undefined;\n    const agent = this.#session.stream.getAgent({ subscription }) ?? this.#machinery.getAgent();\n    let currentRun: StreamState | undefined;\n    let requestContext!: RequestContext;\n    let bailed = false;\n    let abortedRunId: string | undefined;\n\n    const consume = async (): Promise<void> => {\n      for await (const chunk of subscription.stream) {\n        if (bailed) return;\n        if (!this.#session.stream.isCurrent({ subscription })) {\n          subscription.unsubscribe();\n          break;\n        }\n\n        const runId = ('runId' in chunk ? chunk.runId : undefined) ?? subscription.activeRunId();\n        if (runId && runId === abortedRunId) continue;\n        if (runId && abortedRunId) abortedRunId = undefined;\n\n        if (!currentRun) {\n          currentRun = this.createStreamState(threadId);\n          this.#session.run.nextOperation();\n          this.#session.run.ensureAbortController();\n          this.#session.run.setRunId({ runId });\n          this.#session.run.setTraceId({ traceId: null });\n          requestContext = await this.#machinery.buildRequestContext(subscription.__getCurrentRunRequestContext?.());\n          this.#session.emit({ type: 'agent_start' });\n        }\n\n        if (chunk.type === 'start') {\n          continue;\n        }\n\n        try {\n          const streamResult = await this.processStreamChunk(currentRun, chunk, requestContext, agent);\n          if (\n            streamResult ||\n            chunk.type === 'finish' ||\n            chunk.type === 'error' ||\n            chunk.type === 'abort' ||\n            chunk.type === 'tool-call-suspended'\n          ) {\n            const suspended =\n              chunk.type === 'tool-call-suspended' ||\n              (streamResult ?? this.finishStreamState(currentRun)).suspended ||\n              undefined;\n            const aborted = chunk.type === 'abort';\n            // A non-success terminal finish reason (e.g. a `claude-fable-5`\n            // content-filter refusal) becomes an explicit error so the\n            // run never silently stops without a visible terminal state.\n            let isError = chunk.type === 'error';\n            if (\n              currentRun.terminalError &&\n              !isError &&\n              !aborted &&\n              !this.#session.run.isAbortRequested() &&\n              !suspended\n            ) {\n              isError = true;\n              this.#session.emit({ type: 'error', error: new Error(currentRun.terminalError) });\n            }\n            await this.finishSubscribedStreamRun({\n              suspended,\n              error: isError,\n              aborted,\n            });\n            currentRun = undefined;\n            if (aborted) {\n              // The thread subscription remains live across runs. Ignore any\n              // trailing chunks from the aborted run while continuing to drain\n              // later signals on this same subscription.\n              abortedRunId = runId ?? undefined;\n            }\n          }\n        } catch (error) {\n          await this.handleSubscribedStreamError(error);\n          currentRun = undefined;\n        }\n      }\n    };\n\n    try {\n      const bailGuard = new AbortController();\n      try {\n        const outcome = await Promise.race([\n          consume(),\n          abortDeadline(this.#session.run, bailGuard.signal, ABORT_STREAM_GRACE_MS),\n        ]);\n        bailed = outcome === abortBailed;\n      } finally {\n        bailGuard.abort();\n      }\n\n      // Graceful stream close without explicit terminal chunk.\n      if (currentRun && this.#session.stream.isCurrent({ subscription })) {\n        const streamResult = this.finishStreamState(currentRun);\n        await this.finishSubscribedStreamRun({ suspended: streamResult.suspended });\n        currentRun = undefined;\n      }\n\n      // A closed or hung subscription cannot observe later runs. Detach it so\n      // the next message creates a fresh consumer. A persistent subscription\n      // stays attached after an abort and continues draining later signals.\n      if ((bailed || abortedRunId) && this.#session.stream.isCurrent({ subscription })) {\n        this.#session.stream.detach();\n      }\n    } catch (error) {\n      if (this.#session.stream.isCurrent({ subscription })) {\n        await this.handleSubscribedStreamError(error);\n      }\n    }\n  }\n}\n","import type { Agent } from '../agent';\nimport type { MastraDBMessage, MastraMessagePart } from '../agent/message-list/state/types';\nimport type { AgentInstructions, ToolsInput } from '../agent/types';\nimport type { BackgroundTaskManagerConfig } from '../background-tasks';\nimport type { MastraBrowser } from '../browser/browser';\nimport type { AgentControllerChannelsConfig } from '../channels/agent-controller-channels';\nimport type { PubSub } from '../events/pubsub';\nimport type { MastraModelGatewayInterface } from '../llm/model/gateways';\nimport type { LoopOptions } from '../loop/types';\nimport type { MastraMemory } from '../memory/memory';\nimport type { ObservabilityEntrypoint } from '../observability/types/core';\nimport type { PublicSchema } from '../schema';\nimport type { MastraCompositeStore } from '../storage/base';\nimport type { GoalEvaluationPayload } from '../stream/types';\nimport type { DynamicArgument } from '../types';\nimport type { Workspace, WorkspaceStatus } from '../workspace';\nimport type { Session } from './session';\nimport type { TaskItemSnapshot } from './tools';\n\n// =============================================================================\n// Interval Handlers\n// =============================================================================\n\n/**\n * A periodic task that the AgentController runs on a timer.\n * Interval handlers start during `init()` and are cleaned up on `stopIntervals()`.\n */\nexport interface IntervalHandler {\n  /** Unique identifier for this handler (used for dedup and logging) */\n  id: string;\n  /** Interval in milliseconds between invocations */\n  intervalMs: number;\n  /** The function to run on each tick */\n  handler: () => void | Promise<void>;\n  /** Whether to run the handler immediately on start (default: true) */\n  immediate?: boolean;\n  /** Called when the handler is removed or all intervals are stopped */\n  shutdown?: () => void | Promise<void>;\n}\n\n// =============================================================================\n// AgentController Configuration\n// ===================\n\n/**\n * Configuration for a single agent mode within the controller.\n * Each mode represents a different \"personality\" or capability set.\n */\ninterface AgentControllerModeBase {\n  /** Unique within `AgentControllerConfig.modes`. Validated at construction. */\n  id: string;\n\n  name?: string;\n\n  /** bootstrap model default when a session enters this mode. */\n  defaultModelId?: string;\n\n  /** Surfaced in mode pickers / Studio UI. Free text. */\n  description?: string;\n\n  /**\n   * Layered above the backing agent's own instructions for the duration\n   * of this mode. Plain text by design — modes carve operating profile,\n   * not full system-message overrides.\n   */\n  instructions?: string;\n\n  /** @deprecated Use AgentControllerConfig.agent as the shared backing agent. */\n  agent?: Agent<any, any, any, any>;\n\n  /** @deprecated Prefer metadata.default. */\n  default?: boolean;\n\n  /**\n   * Optional plan→build target. When `submit_plan` runs in this mode, the\n   * registered `PendingResume` freezes this value as `transitionModeId`.\n   * On approval, the session flips to this mode\n   * idempotently (§5.1, §5.7). If unset, plan approval resumes with no\n   * mode change. Must reference another mode's `id`.\n   */\n  transitionsTo?: string;\n\n  /**\n   * Unified per-mode tool visibility allowlist. When set, only tools whose\n   * final exposed names appear in this list are visible to the model and\n   * executable during this mode's runs. Workspace tools use the same list\n   * as all other tools — configure them by exposed tool names such as\n   * `view`, `write_file`, `find_files`, etc. (after workspace tool renaming\n   * via `TOOL_NAME_OVERRIDES`).\n   *\n   * - `undefined` (default): no mode-level restriction; all tools are visible.\n   * - `[]`: no tools are available for this mode.\n   * - Per-tool permission `deny` and category `deny` still win — a denied\n   *   tool is hidden even if it appears in this list.\n   * - `tools` / `additionalTools` remain toolset composition inputs (which\n   *   tools are added to the run), not visibility gates.\n   *\n   * Enforced at LLM-call time via `activeTools`, matching the existing\n   * execution-time enforcement in the durable tool-call step.\n   */\n  availableTools?: string[];\n\n  /**\n   * Arbitrary user-defined metadata. `metadata.default === true` is a\n   * reserved controller hint for choosing the default mode when `defaultModeId`\n   * is unset; all other metadata is pass-through and unvalidated. Use for UI\n   * affordances like display color, icon, display name overrides, or any\n   * per-mode configuration that isn't part of the controller's own contract.\n   *\n   * Surfaced verbatim on `getCurrentMode()` and `listModes()`.\n   */\n  metadata?: Record<string, unknown>;\n}\n\ntype AgentControllerModeToolOverrides =\n  | {\n      /**\n       * Mode-level tools added as a separate toolset alongside the backing\n       * agent's own tools. With a shared backing agent (`AgentControllerConfig.agent`),\n       * these are layered as an augment — the agent's own tools are **not**\n       * masked. To restrict which tools are visible, use `availableTools`\n       * instead. Mutually exclusive with `additionalTools`.\n       */\n      tools?: ToolsInput;\n      additionalTools?: never;\n    }\n  | {\n      tools?: never;\n      /**\n       * Tools layered on top of the backing agent's tools. The agent's tools\n       * stay; these are added. Mutually exclusive with `tools`.\n       */\n      additionalTools?: ToolsInput;\n    };\n\nexport type AgentControllerMode = AgentControllerModeBase & AgentControllerModeToolOverrides;\n\n// =============================================================================\n// Subagents\n// =============================================================================\n\n/**\n * Definition of a subagent that the AgentController can spawn via the built-in `subagent` tool.\n * Each subagent runs as a fresh Agent with constrained tools and its own instructions.\n */\nexport interface AgentControllerSubagent {\n  /** Unique identifier for this subagent type (e.g., \"explore\", \"plan\", \"execute\") */\n  id: string;\n\n  /** Human-readable name shown in tool output (e.g., \"Explore\") */\n  name: string;\n\n  /** Description of what this subagent does (used in auto-generated tool description) */\n  description: string;\n\n  /**\n   * Instructions that guide the agent's behavior. Can be a string, array of strings, system message object,\n   * array of system messages, or a function that returns any of these types dynamically.\n   */\n  instructions: DynamicArgument<AgentInstructions>;\n\n  /** Tools this subagent has direct access to */\n  tools?: ToolsInput;\n\n  /**\n   * Tool IDs to pull from the controller's shared `tools` config.\n   * Merged with `tools` above — allows subagents to use a subset of controller tools.\n   */\n  allowedControllerTools?: string[];\n\n  /** Default model ID for this subagent type (e.g., \"anthropic/claude-sonnet-4-20250514\") */\n  defaultModelId?: string;\n\n  /** Optional maximum number of steps for this subagent's execution loop */\n  maxSteps?: number;\n\n  /** Optional stop condition for this subagent's execution loop */\n  stopWhen?: LoopOptions['stopWhen'];\n\n  /**\n   * Workspace tool keys (after any renames) the model is allowed to call.\n   * When set, workspace tools not in this list are hidden via `prepareStep`.\n   * Non-workspace tools are never affected. When omitted, all workspace\n   * tools are visible.\n   */\n  allowedWorkspaceTools?: string[];\n\n  /**\n   * Default \"forked\" mode for this subagent type. When `true`, invocations\n   * inherit the parent agent's conversation context: the parent thread is\n   * cloned and the subagent runs on the fork with the parent agent's\n   * instructions and tools, preserving prompt-cache prefix.\n   *\n   * The parent's `instructions`, `tools`, `allowedControllerTools`,\n   * `allowedWorkspaceTools`, and `defaultModelId` fields on the definition\n   * are ignored when a run is forked — the parent agent is used as-is.\n   *\n   * Callers can override per-invocation by passing `forked` in the tool\n   * input. Forked subagents require memory to be configured on the AgentController.\n   *\n   * @default false\n   */\n  forked?: boolean;\n}\n\n/**\n * State data type for the AgentController generic parameter.\n */\nexport type AgentControllerStateSchema<T> = T;\n\n/**\n * Configuration for creating a AgentController instance.\n */\n/**\n * Identifiers for the built-in controller tools that can be selectively disabled.\n */\nexport type BuiltinToolId =\n  | 'ask_user'\n  | 'submit_plan'\n  | 'task_write'\n  | 'task_update'\n  | 'task_complete'\n  | 'task_check'\n  | 'subagent';\n\n/** Process-local listener notified after AgentController materializes a live session. */\nexport type AgentControllerSessionCreatedListener<TState = {}> = (session: Session<TState>) => void | Promise<void>;\n\n/** Options for {@link AgentController.onSessionCreated}. */\nexport interface AgentControllerSessionCreatedOptions {\n  /**\n   * Make `createSession()` await this listener before resolving a newly\n   * materialized session. Blocking listeners run sequentially in registration\n   * order, before fire-and-forget listeners are notified. Failures are\n   * isolated and logged, never thrown. Keep the work short — it holds up every\n   * caller awaiting that session's creation.\n   */\n  blocking?: boolean;\n}\n\n/** Process-local listener notified after AgentController tears down a live session. */\nexport type AgentControllerSessionDeletedListener<TState = {}> = (session: Session<TState>) => void | Promise<void>;\n\nexport interface AgentControllerConfig<TState = {}> {\n  /** Unique identifier for this controller instance */\n  id: string;\n\n  /**\n   * Resource ID for grouping threads (e.g., project identifier).\n   * Threads are scoped to this resource ID.\n   */\n  resourceId?: string;\n\n  /** Storage backend for persistence (threads, messages, state) */\n  storage?: MastraCompositeStore;\n\n  /** Background task configuration for the controller's standalone internal Mastra instance. */\n  backgroundTasks?: BackgroundTaskManagerConfig;\n\n  /** Schema defining the shape of controller state (Zod, JSON Schema, Standard Schema, etc.) */\n  stateSchema?: PublicSchema<TState, any>;\n\n  /** Initial state values (must conform to schema) */\n  initialState?: Partial<TState>;\n\n  /** Memory configuration (shared across all modes) */\n  memory?: DynamicArgument<MastraMemory>;\n\n  /** Available agent modes */\n  modes: AgentControllerMode[];\n\n  /** Shared backing agent that each mode forks and decorates on the controller. */\n  agent?: Agent<any, any, any, any>;\n\n  /**\n   * Chat channel adapters (Slack, Discord, ...) that run this controller\n   * inside messaging threads. Inbound platform messages route into a\n   * controller `Session` (one durable session per chat thread) and the\n   * streamed output renders back to the platform through the channels\n   * output processor (native streaming, tool cards, typing status).\n   * Tool approvals resolve through the session's approval gate.\n   *\n   * V1 expects manually constructed adapters and a long-lived server\n   * (controller sessions are in-memory and don't survive restarts).\n   */\n  channels?: AgentControllerChannelsConfig;\n\n  /** Default mode to enter when a thread has no persisted mode. */\n  defaultModeId?: string;\n\n  instructions?: string;\n\n  /**\n   * Tools available to all agents across all modes.\n   * Can be a static tools object or a dynamic function that receives\n   * the request context and returns tools per-request.\n   */\n  tools?: DynamicArgument<ToolsInput | undefined>;\n\n  /**\n   * Workspace configuration.\n   * Accepts a pre-constructed Workspace instance or a dynamic factory\n   * function that receives the request context and returns a Workspace\n   * per-request.\n   */\n  workspace?: DynamicArgument<Workspace | undefined>;\n\n  /**\n   * Browser automation configuration.\n   * Accepts a pre-constructed MastraBrowser instance or a dynamic factory\n   * function that receives the request context and returns a browser per-request.\n   * Propagated to mode agents that don't have their own browser configured.\n   */\n  browser?: DynamicArgument<MastraBrowser | undefined>;\n\n  /**\n   * Periodic interval handlers started during `init()`.\n   * Use for background tasks like gateway sync, cache refresh, etc.\n   */\n  intervalHandlers?: IntervalHandler[];\n\n  /**\n   * Custom ID generator for AgentController-managed IDs such as threads and mode-run identifiers.\n   * Defaults to a timestamp + random string generator.\n   */\n  idGenerator?: () => string;\n\n  /**\n   * Provides per-model use counts for `listAvailableModels()` sorting/display.\n   * Lets the app layer track and report how often each model has been used.\n   */\n  modelUseCountProvider?: ModelUseCountProvider;\n\n  /**\n   * Callback invoked when a model is selected via switchModel().\n   * Lets the app layer track and persist model usage for ranking.\n   */\n  modelUseCountTracker?: ModelUseCountTracker;\n\n  /**\n   * Subagent definitions. The AgentController auto-creates a `subagent` built-in tool\n   * that parent agents can call to spawn focused subagents.\n   */\n  subagents?: AgentControllerSubagent[];\n\n  /**\n   * Model gateways registered on AgentController' internal Mastra instance.\n   * The AgentController resolves every model — mode agents, Observational Memory,\n   * subagents — and builds the `listAvailableModels()` catalog through these\n   * gateways. Provider auth (API keys, OAuth, stored credentials) is resolved\n   * via each gateway's `resolveAuth()` / env-var configuration.\n   */\n  gateways?: MastraModelGatewayInterface[];\n\n  /**\n   * Observational Memory configuration defaults.\n   * The AgentController auto-manages OM state (model IDs, thresholds) internally\n   * and provides accessors that Memory's dynamic model functions can close over.\n   */\n  omConfig?: AgentControllerOMConfig;\n\n  /**\n   * Built-in tool IDs to disable.\n   * Any tool listed here will be excluded from the `controllerBuiltIn` toolset.\n   * Valid values: 'ask_user', 'submit_plan', 'task_write', 'task_update',\n   * 'task_complete', 'task_check', 'subagent'.\n   */\n  disableBuiltinTools?: BuiltinToolId[];\n\n  /**\n   * Maps tool names to permission categories.\n   * Used by the permission system to resolve category-level policies.\n   * If not provided, all tools default to the \"other\" category.\n   */\n  toolCategoryResolver?: (toolName: string) => ToolCategory | null;\n\n  /**\n   * PubSub instance used by the internal Mastra instance and mode agents.\n   */\n  pubsub?: PubSub;\n\n  /**\n   * Optional thread locking callbacks.\n   * Called during selectOrCreateThread, createThread, and switchThread\n   * to prevent concurrent access to the same thread from multiple processes.\n   * `acquire` should throw if the lock is held by another process.\n   */\n  threadLock?: {\n    acquire: (threadId: string) => void | Promise<void>;\n    release: (threadId: string) => void | Promise<void>;\n  };\n\n  /**\n   * Observability entrypoint for tracing, scoring, and feedback.\n   * When provided, the internal Mastra instance is configured with this\n   * observability backend so that agent runs produce trace spans.\n   */\n  observability?: ObservabilityEntrypoint;\n}\n\n/**\n * Default configuration for Observational Memory.\n * These values are used when controller state doesn't have explicit OM values\n * (e.g., fresh thread with no persisted OM settings).\n */\nexport interface AgentControllerOMConfig {\n  /** Default model ID for the observer agent */\n  defaultObserverModelId?: string;\n  /** Default model ID for the reflector agent */\n  defaultReflectorModelId?: string;\n  /** Default observation threshold in tokens */\n  defaultObservationThreshold?: number;\n  /** Default reflection threshold in tokens */\n  defaultReflectionThreshold?: number;\n}\n\n// =============================================================================\n// Permissions\n// =============================================================================\n\n/**\n * Tool category for permission grouping.\n * Consumers define how tool names map to categories via `toolCategoryResolver`.\n */\nexport type ToolCategory = 'read' | 'edit' | 'execute' | 'mcp' | 'other';\n\n/**\n * Permission policy for a tool or category.\n */\nexport type PermissionPolicy = 'allow' | 'ask' | 'deny';\n\n/**\n * Permission rules for controlling tool approval behavior.\n * Per-tool overrides take precedence over category policies.\n */\nexport interface PermissionRules {\n  categories: Partial<Record<ToolCategory, PermissionPolicy>>;\n  tools: Partial<Record<string, PermissionPolicy>>;\n}\n\n// =============================================================================\n// Model Discovery\n// =============================================================================\n\n/**\n * Auth status for a model's provider.\n */\nexport interface ModelAuthStatus {\n  hasAuth: boolean;\n  apiKeyEnvVar?: string;\n}\n\n/**\n * Info about an available model from the provider registry.\n */\nexport interface AvailableModel {\n  /** Full model ID (e.g., \"anthropic/claude-sonnet-4-20250514\") */\n  id: string;\n  /** Provider prefix (e.g., \"anthropic\") */\n  provider: string;\n  /** Model name without provider prefix */\n  modelName: string;\n  /** Whether the provider has valid authentication */\n  hasApiKey: boolean;\n  /** Environment variable for the provider's API key */\n  apiKeyEnvVar?: string;\n  /** Number of times this model has been used (from external tracking) */\n  useCount: number;\n}\n\n/**\n * Same as {@link AvailableModel} but without the runtime `useCount` field.\n * Used by providers that supply catalog entries before use-count tracking.\n */\nexport type CustomAvailableModel = Omit<AvailableModel, 'useCount'>;\n\n/**\n * Function that returns a list of custom available models (without use counts).\n */\nexport type CustomModelCatalogProvider = () => Promise<CustomAvailableModel[]>;\n\n/**\n * Provides per-model use counts for sorting in `listAvailableModels()`.\n * Return a map of model ID → use count.\n */\nexport type ModelUseCountProvider = () => Record<string, number>;\n\n/**\n * Callback invoked when a model is selected via switchModel().\n * Lets the app layer track and persist model usage for ranking.\n */\nexport type ModelUseCountTracker = (modelId: string) => void;\n\n// =============================================================================\n// AgentController State\n// =============================================================================\n\n/**\n * Thread metadata stored in the controller.\n */\nexport interface AgentControllerThread {\n  id: string;\n  resourceId: string;\n  title?: string;\n  createdAt: Date;\n  updatedAt: Date;\n  tokenUsage?: TokenUsage;\n  metadata?: Record<string, unknown>;\n}\n\n// =============================================================================\n// Events\n// =============================================================================\n\n/**\n * Token usage statistics from the model.\n */\nexport interface TokenUsage {\n  promptTokens: number;\n  completionTokens: number;\n  totalTokens: number;\n  reasoningTokens?: number;\n  cachedInputTokens?: number;\n  cacheCreationInputTokens?: number;\n  cacheCreationInputTokens5m?: number;\n  cacheCreationInputTokens1h?: number;\n  raw?: unknown;\n}\n\n/** Creates a zero-initialized TokenUsage object. */\nexport function createEmptyTokenUsage(): TokenUsage {\n  return {\n    promptTokens: 0,\n    completionTokens: 0,\n    totalTokens: 0,\n    cachedInputTokens: 0,\n    cacheCreationInputTokens: 0,\n  };\n}\n\n// =============================================================================\n// Observational Memory Progress\n// =============================================================================\n\n/**\n * Status of the Observational Memory system.\n */\nexport type OMStatus = 'idle' | 'observing' | 'reflecting';\n\n/**\n * Status of a buffered OM operation (observation or reflection).\n */\nexport type OMBufferedStatus = 'idle' | 'running' | 'complete';\n\n/**\n * Full progress state for Observational Memory.\n * Maintained by the AgentController and exposed via `AgentControllerDisplayState`.\n */\nexport interface OMProgressState {\n  status: OMStatus;\n  // Active window tokens/thresholds (from om_status events)\n  pendingTokens: number;\n  threshold: number;\n  thresholdPercent: number;\n  observationTokens: number;\n  reflectionThreshold: number;\n  reflectionThresholdPercent: number;\n  // Buffered state (from om_status events)\n  buffered: {\n    observations: {\n      status: OMBufferedStatus;\n      chunks: number;\n      messageTokens: number;\n      projectedMessageRemoval: number;\n      observationTokens: number;\n    };\n    reflection: {\n      status: OMBufferedStatus;\n      inputObservationTokens: number;\n      observationTokens: number;\n    };\n  };\n  generationCount: number;\n  stepNumber: number;\n  cycleId?: string;\n  startTime?: number;\n  /** Observation tokens before reflection compression (set on om_reflection_start) */\n  preReflectionTokens: number;\n}\n\n// =============================================================================\n// Display State\n// =============================================================================\n\n/**\n * State of an active tool execution, tracked by the AgentController for UI consumption.\n */\nexport interface ActiveToolState {\n  name: string;\n  args: unknown;\n  status: 'streaming_input' | 'running' | 'completed' | 'error';\n  partialResult?: string;\n  result?: unknown;\n  isError?: boolean;\n  shellOutput?: string;\n}\n\n/**\n * State of an active subagent execution, tracked by the AgentController for UI consumption.\n */\nexport interface ActiveSubagentState {\n  agentType: string;\n  displayName?: string;\n  task: string;\n  modelId?: string;\n  forked?: boolean;\n  toolCalls: Array<{ name: string; isError: boolean }>;\n  textDelta: string;\n  status: 'running' | 'completed' | 'error';\n  durationMs?: number;\n  result?: string;\n}\n\nexport type AgentControllerSubagentHistoryEntry = Omit<ActiveSubagentState, 'status'>;\n\n/**\n * Canonical display state maintained by the AgentController.\n *\n * This is the single source of truth for *what to display*.\n * Any UI (TUI, web, desktop) can subscribe to updates of this state instead\n * of interpreting 35+ raw event types.\n *\n * The AgentController updates this state alongside every event emission,\n * then emits a `display_state_changed` event so UIs can react.\n */\nexport interface AgentControllerDisplayState {\n  // ── Agent lifecycle ──────────────────────────────────────────────────\n  /** Whether an agent operation is currently in progress */\n  isRunning: boolean;\n\n  // ── Current streaming message ────────────────────────────────────────\n  /**\n   * The live message currently being streamed (null when idle). Its content\n   * mutates as deltas arrive; copy it before retaining a point-in-time value.\n   */\n  currentMessage: MastraDBMessage | null;\n\n  // ── Follow-up queue ──────────────────────────────────────────────────\n  /** Number of follow-up messages queued locally by the AgentController */\n  queuedFollowUps: number;\n\n  // ── Token usage ──────────────────────────────────────────────────────\n  /** Cumulative token usage for the current thread */\n  tokenUsage: TokenUsage;\n\n  // ── Tool execution tracking ──────────────────────────────────────────\n  /** Active tool executions keyed by toolCallId */\n  activeTools: Map<string, ActiveToolState>;\n\n  // ── Streaming tool input ─────────────────────────────────────────────\n  /** Partial JSON buffers for tools whose arguments are being streamed */\n  toolInputBuffers: Map<string, { text: string; toolName: string }>;\n\n  // ── Tool approval ────────────────────────────────────────────────────\n  /** A tool awaiting user approval (null when no approval pending) */\n  pendingApproval: {\n    toolCallId: string;\n    toolName: string;\n    args: unknown;\n  } | null;\n\n  // ── Tool suspension ─────────────────────────────────────────────────\n  /**\n   * Tools awaiting resume data after calling suspend(), keyed by toolCallId.\n   * Multiple tools can be parked at once (e.g. parallel `ask_user` prompts), so\n   * resuming one leaves the others intact for the UI to keep rendering.\n   */\n  pendingSuspensions: Map<\n    string,\n    {\n      toolCallId: string;\n      toolName: string;\n      args: unknown;\n      suspendPayload: unknown;\n      resumeSchema?: string;\n    }\n  >;\n\n  // ── Subagent tracking ────────────────────────────────────────────────\n  /** Active subagent executions keyed by parent toolCallId */\n  activeSubagents: Map<string, ActiveSubagentState>;\n\n  // ── Observational Memory ─────────────────────────────────────────────\n  /** Full OM progress state (status, tokens, thresholds, buffered) */\n  omProgress: OMProgressState;\n\n  /** Whether message buffering is currently running */\n  bufferingMessages: boolean;\n\n  /** Whether observation buffering is currently running */\n  bufferingObservations: boolean;\n\n  // ── File modifications ───────────────────────────────────────────────\n  /** Files modified by tool executions (for /diff and similar features) */\n  modifiedFiles: Map<string, { operations: string[]; firstModified: Date }>;\n\n  // ── Tasks ────────────────────────────────────────────────────────────\n  /** Current task list (from task tools) */\n  tasks: TaskItemSnapshot[];\n\n  /** Previous task list snapshot (for diff detection) */\n  previousTasks: TaskItemSnapshot[];\n}\n\n/**\n * Creates the default/initial `AgentControllerDisplayState`.\n */\nexport function defaultDisplayState(): AgentControllerDisplayState {\n  return {\n    isRunning: false,\n    currentMessage: null,\n    queuedFollowUps: 0,\n    tokenUsage: createEmptyTokenUsage(),\n    activeTools: new Map(),\n    toolInputBuffers: new Map(),\n    pendingApproval: null,\n    pendingSuspensions: new Map(),\n    activeSubagents: new Map(),\n    omProgress: defaultOMProgressState(),\n    bufferingMessages: false,\n    bufferingObservations: false,\n    modifiedFiles: new Map(),\n    tasks: [],\n    previousTasks: [],\n  };\n}\n\n/**\n * Creates the default OM progress state.\n */\nexport function defaultOMProgressState(): OMProgressState {\n  return {\n    status: 'idle',\n    pendingTokens: 0,\n    threshold: 30000,\n    thresholdPercent: 0,\n    observationTokens: 0,\n    reflectionThreshold: 40000,\n    reflectionThresholdPercent: 0,\n    buffered: {\n      observations: {\n        status: 'idle',\n        chunks: 0,\n        messageTokens: 0,\n        projectedMessageRemoval: 0,\n        observationTokens: 0,\n      },\n      reflection: {\n        status: 'idle',\n        inputObservationTokens: 0,\n        observationTokens: 0,\n      },\n    },\n    generationCount: 0,\n    stepNumber: 0,\n    preReflectionTokens: 0,\n  };\n}\n\n// =============================================================================\n// Events\n// =============================================================================\n\n/**\n * Events emitted by the controller that UIs can subscribe to.\n *\n * A logical message emits one `message_start` containing its initial\n * `MastraDBMessage`, zero or more compact id-addressed `message_update` deltas,\n * and one id-only `message_end` after terminal metadata has been applied.\n * Consumers reconstruct streamed text, reasoning, and non-text message parts\n * from ordered deltas, then use the id-only end to finalize the matching entry.\n */\nexport type AgentControllerEvent =\n  | { type: 'mode_changed'; modeId: string; previousModeId: string }\n  | { type: 'model_changed'; modelId: string; scope?: 'global' | 'thread' | 'mode'; modeId?: string }\n  | { type: 'thread_changed'; threadId: string; previousThreadId: string | null }\n  | { type: 'thread_created'; thread: AgentControllerThread }\n  | { type: 'thread_deleted'; threadId: string }\n  | { type: 'state_changed'; state: Record<string, unknown>; changedKeys: string[] }\n  | { type: 'agent_start' }\n  | { type: 'agent_end'; reason?: 'complete' | 'aborted' | 'error' | 'suspended' }\n  | { type: 'message_start'; message: MastraDBMessage }\n  | {\n      type: 'message_update';\n      id: string;\n      event:\n        | { type: 'text-delta'; delta: string }\n        | { type: 'reasoning-delta'; index: number; delta: string }\n        | { type: 'part'; index: number; part: MastraMessagePart };\n    }\n  | { type: 'message_end'; id: string }\n  | ({ threadId?: string } & (\n      | { type: 'tool_start'; toolCallId: string; toolName: string; args: unknown }\n      | { type: 'tool_approval_required'; toolCallId: string; toolName: string; args: unknown }\n      | {\n          type: 'tool_suspended';\n          toolCallId: string;\n          toolName: string;\n          args: unknown;\n          suspendPayload: unknown;\n          resumeSchema?: string;\n        }\n      | { type: 'tool_suspension_cancelled'; toolCallId: string; toolName: string; reason: string }\n      | { type: 'tool_update'; toolCallId: string; partialResult: unknown }\n      | {\n          type: 'tool_end';\n          toolCallId: string;\n          result: unknown;\n          isError: boolean;\n          /**\n           * True when the tool call resolved without ever running because the user\n           * denied its approval gate or the run was aborted while it was parked\n           * waiting for approval. `isError` stays `false` in that case (the tool\n           * did not fail — it simply never executed), so subscribers that gate on\n           * \"the tool actually did work\" must exclude `denied === true`.\n           */\n          denied?: boolean;\n          providerMetadata?: Record<string, unknown>;\n        }\n      | { type: 'tool_input_start'; toolCallId: string; toolName: string }\n      | { type: 'tool_input_delta'; toolCallId: string; argsTextDelta: unknown; toolName?: string }\n      | { type: 'tool_input_end'; toolCallId: string }\n      | { type: 'shell_output'; toolCallId: string; output: string; stream: 'stdout' | 'stderr' }\n      | { type: 'command_exit'; toolCallId: string; exitCode: number; success: boolean }\n    ))\n  | { type: 'usage_update'; usage: TokenUsage }\n  | { type: 'info'; message: string }\n  | {\n      type: 'error';\n      error: Error;\n      errorType?: string;\n      retryable?: boolean;\n      retryDelay?: number;\n      retryAttempt?: number;\n      maxRetries?: number;\n    }\n  | { type: 'follow_up_queued'; count: number; runId?: string }\n  | { type: 'workspace_status_changed'; status: WorkspaceStatus; error?: Error }\n  | { type: 'workspace_ready'; workspaceId: string; workspaceName: string }\n  | { type: 'workspace_error'; error: Error }\n  | {\n      type: 'om_status';\n      windows: {\n        active: {\n          messages: { tokens: number; threshold: number };\n          observations: { tokens: number; threshold: number };\n        };\n        buffered: {\n          observations: {\n            status: 'idle' | 'running' | 'complete';\n            chunks: number;\n            messageTokens: number;\n            projectedMessageRemoval: number;\n            observationTokens: number;\n          };\n          reflection: {\n            status: 'idle' | 'running' | 'complete';\n            inputObservationTokens: number;\n            observationTokens: number;\n          };\n        };\n      };\n      recordId: string;\n      threadId: string;\n      stepNumber: number;\n      generationCount: number;\n    }\n  | {\n      type: 'om_observation_start';\n      cycleId: string;\n      operationType: 'observation' | 'reflection';\n      tokensToObserve: number;\n    }\n  | {\n      type: 'om_observation_end';\n      cycleId: string;\n      durationMs: number;\n      tokensObserved: number;\n      observationTokens: number;\n      observations?: string;\n      currentTask?: string;\n      suggestedResponse?: string;\n    }\n  | { type: 'om_observation_failed'; cycleId: string; error: string; durationMs: number }\n  | { type: 'om_reflection_start'; cycleId: string; tokensToReflect: number }\n  | {\n      type: 'om_reflection_end';\n      cycleId: string;\n      durationMs: number;\n      compressedTokens: number;\n      observations?: string;\n    }\n  | { type: 'om_reflection_failed'; cycleId: string; error: string; durationMs: number }\n  | { type: 'om_model_changed'; role: 'observer' | 'reflector'; modelId: string }\n  | {\n      type: 'om_buffering_start';\n      cycleId: string;\n      operationType: 'observation' | 'reflection';\n      tokensToBuffer: number;\n    }\n  | {\n      type: 'om_buffering_end';\n      cycleId: string;\n      operationType: 'observation' | 'reflection';\n      tokensBuffered: number;\n      bufferedTokens: number;\n      observations?: string;\n    }\n  | {\n      type: 'om_buffering_failed';\n      cycleId: string;\n      operationType: 'observation' | 'reflection';\n      error: string;\n    }\n  | {\n      type: 'om_activation';\n      cycleId: string;\n      operationType: 'observation' | 'reflection';\n      chunksActivated: number;\n      tokensActivated: number;\n      observationTokens: number;\n      messagesActivated: number;\n      generationCount: number;\n      triggeredBy?: 'threshold' | 'ttl' | 'provider_change';\n      lastActivityAt?: number;\n      ttlExpiredMs?: number;\n      activateAfterIdle?: number;\n      previousModel?: string;\n      currentModel?: string;\n    }\n  | { type: 'om_thread_title_updated'; cycleId: string; threadId: string; oldTitle?: string; newTitle: string }\n  | { type: 'thread_title_updated'; threadId: string; title: string }\n  | { type: 'subagent_start'; toolCallId: string; agentType: string; task: string; modelId: string; forked?: boolean }\n  | { type: 'subagent_text_delta'; toolCallId: string; agentType: string; textDelta: string }\n  | {\n      type: 'subagent_tool_start';\n      toolCallId: string;\n      agentType: string;\n      subToolName: string;\n      subToolArgs: unknown;\n    }\n  | {\n      type: 'subagent_tool_end';\n      toolCallId: string;\n      agentType: string;\n      subToolName: string;\n      subToolResult: unknown;\n      isError: boolean;\n    }\n  | {\n      type: 'subagent_end';\n      toolCallId: string;\n      agentType: string;\n      result: string;\n      isError: boolean;\n      durationMs: number;\n    }\n  | { type: 'subagent_model_changed'; modelId: string; scope: 'global' | 'thread'; agentType?: string }\n  | {\n      type: 'task_updated';\n      tasks: TaskItemSnapshot[];\n    }\n  | {\n      type: 'goal_evaluation';\n      payload: GoalEvaluationPayload;\n    }\n  | { type: 'display_state_changed'; displayState: AgentControllerDisplayState };\n\n/**\n * Listener function for controller events.\n */\nexport type AgentControllerEventListener = (event: AgentControllerEvent) => void | Promise<void>;\n\n// =============================================================================\n// Request Context\n// =============================================================================\n\n/**\n * Controller-specific context set on the RequestContext under the 'controller' key.\n * Tools can access controller state and methods through requestContext.get('controller').\n */\n/**\n * Snapshot of the session-owned values exposed to request-context consumers.\n * Plain data captured per request; mutating it does not affect the Session.\n */\nexport type AgentControllerRequestStateUpdateResult<TState, TResult> = {\n  updates?: Partial<TState>;\n  events?: AgentControllerEvent[];\n  result: TResult;\n};\n\nexport type AgentControllerRequestStateUpdater<TState, TResult> = (\n  state: Readonly<TState>,\n) =>\n  | AgentControllerRequestStateUpdateResult<TState, TResult>\n  | Promise<AgentControllerRequestStateUpdateResult<TState, TResult>>;\n\nexport interface AgentControllerRequestState<TState = unknown> {\n  /** Get the current session-owned controller state (live, not request-context snapshot). */\n  get: () => Readonly<TState>;\n  /** Update session-owned controller state. */\n  set: (updates: Partial<TState>) => Promise<void>;\n  /** Apply an update only while a caller-owned identity still matches. */\n  setIf?: (updates: Partial<TState>, shouldApply: () => boolean) => Promise<boolean>;\n  /** Update session-owned controller state from the latest snapshot in a serialized transaction. */\n  update: <TResult>(updater: AgentControllerRequestStateUpdater<TState, TResult>) => Promise<TResult>;\n}\n\nexport interface AgentControllerRequestSession<TState = unknown> {\n  /** Stable session identifier (mirrors SessionRecord.id in storage). */\n  id: string;\n  /** Stable session owner (mirrors SessionRecord.ownerId in storage). */\n  ownerId: string;\n  /** Currently-selected mode ID */\n  modeId: string;\n  /** Currently-selected model ID ('' when none selected yet) */\n  modelId: string;\n  /**\n   * Live session-owned controller state accessors.\n   * @deprecated Prefer the top-level `getState()` / `setState()` / `updateState()`\n   * on the {@link AgentControllerRequestContext} instead.\n   */\n  state: AgentControllerRequestState<TState>;\n}\n\nexport interface AgentControllerRequestContext<TState = unknown> {\n  /** The agent controller instance ID */\n  controllerId: string;\n\n  /**\n   * The agent controller instance ID.\n   * @deprecated Renamed to `controllerId`. Kept for backwards compatibility.\n   */\n  harnessId?: string;\n\n  /**\n   * Current controller state (read-only snapshot captured when the request context is built).\n   * @deprecated Prefer `getState()` for live state reads.\n   */\n  state: Readonly<TState>;\n\n  /** Get the current controller state (live, not snapshot). */\n  getState: () => Readonly<TState>;\n\n  /** Update controller state. */\n  setState: (updates: Partial<TState>) => Promise<void>;\n\n  /** Update controller state from the latest state snapshot in a serialized transaction. */\n  updateState?: <TResult>(updater: AgentControllerRequestStateUpdater<TState, TResult>) => Promise<TResult>;\n\n  /** Read a setting from the thread captured for this request. */\n  getThreadSetting?: (key: string) => Promise<unknown>;\n\n  /** Persist a setting on the thread captured for this request. */\n  setThreadSetting?: (setting: { key: string; value: unknown }) => Promise<void>;\n\n  /** Whether the thread captured for this request is still active in the session. */\n  isThreadActive?: () => boolean;\n\n  /** Thread ID captured for this request. */\n  threadId: string | null;\n\n  /** Current resource ID */\n  resourceId: string;\n\n  /** Optional isolation scope used to identify this session within its resource. */\n  scope?: string;\n\n  /**\n   * Snapshot of the relevant session-owned values for this request.\n   * Plain data (not the live Session); read-only at the point of use.\n   */\n  session: AgentControllerRequestSession<TState>;\n\n  /** Abort signal for the current operation */\n  abortSignal?: AbortSignal;\n\n  /** Workspace instance (if configured on the AgentController) */\n  workspace?: Workspace;\n\n  /** Emit a controller event (used by tools to forward events) */\n  emitEvent?: (event: AgentControllerEvent) => void;\n\n  /** Get the configured subagent model ID for a specific agent type */\n  getSubagentModelId?: (params?: { agentType?: string }) => string | null;\n}\n","import type { Agent } from '../agent';\nimport type { MastraDBMessage, MastraProviderMetadata } from '../agent/message-list/state/types';\nimport { createSignal, resolveDeliveryAttributes } from '../agent/signals';\nimport type {\n  AgentSignalAttributes,\n  AgentSignalContents,\n  AgentSignalInput,\n  CreatedAgentSignal,\n} from '../agent/signals';\nimport type {\n  AgentSignalActiveBehavior,\n  AgentSignalIdleBehavior,\n  AgentThreadSubscription,\n  MastraBrowser,\n  SendAgentNotificationSignalOptions,\n  SendAgentNotificationSignalResult,\n  SendAgentSignalAccepted,\n  ToolsetsInput,\n} from '../agent/types';\nimport { getErrorFromUnknown } from '../error';\nimport type { MastraModelGatewayInterface } from '../llm/model/gateways';\nimport { ModelRouterLanguageModel } from '../llm/model/router';\nimport type { MastraModelConfig } from '../llm/model/shared.types';\nimport { createRunScopeKey } from '../mastra/run-scope';\nimport type { RunScope } from '../mastra/run-scope';\nimport { TITLE_PINNED_THREAD_METADATA_KEY } from '../memory';\nimport type { MastraMemory } from '../memory/memory';\nimport type { SendNotificationSignalInput } from '../notifications';\nimport type { TracingContext, TracingOptions } from '../observability';\nimport type { RequestContext } from '../request-context';\nimport { toStandardSchema } from '../schema';\nimport type { PublicSchema, StandardSchemaWithJSON } from '../schema';\nimport type { StorageListMessagesOutput } from '../storage/types';\nimport type { SubmitPlanResumeData } from '../tools/builtin/submit-plan';\nimport { safeStringify } from '../utils';\nimport { Workspace } from '../workspace';\n\nimport { readMessageAuthor, withMessageAuthor } from './message-author';\nimport { SessionRunEngine } from './session-run-engine';\nimport type { TaskItemSnapshot } from './tools';\nimport { createEmptyTokenUsage, defaultDisplayState, defaultOMProgressState } from './types';\nimport type {\n  AgentControllerDisplayState,\n  AgentControllerEvent,\n  AgentControllerEventListener,\n  AgentControllerMode,\n  AgentControllerOMConfig,\n  AgentControllerRequestState,\n  AgentControllerRequestStateUpdater,\n  AgentControllerThread,\n  ModelUseCountTracker,\n  PermissionPolicy,\n  PermissionRules,\n  TokenUsage,\n  ToolCategory,\n} from './types';\n\nexport const SUSPENDED_RUN_AGENT_KEY = createRunScopeKey<Agent>('agent-controller.suspendedRunAgent');\n\n/**\n * Memory the suspended run persisted its messages under, resolved with the\n * run's own RequestContext while the stream was live. Abort settlement cannot\n * rebuild that context later (dynamic `memory: ({ requestContext }) => …`\n * configs would resolve differently against an empty context), so the resolved\n * instance is retained beside the owning agent for the life of the run scope.\n */\nexport const SUSPENDED_RUN_MEMORY_KEY = createRunScopeKey<MastraMemory>('agent-controller.suspendedRunMemory');\n\n/**\n * Minimal persistence surface the Session uses to read and write per-thread\n * settings (mode id, per-mode model id, …). The AgentController backs this with thread\n * metadata; when no storage is configured it is absent and the Session keeps\n * its state purely in memory.\n */\nexport interface ThreadSettingsStore {\n  /** Read a setting for the active thread, or undefined when unset/unavailable. */\n  get(key: string): Promise<unknown>;\n  /** Persist a setting for the active thread (no-op when storage is unavailable). */\n  set(key: string, value: unknown): Promise<void>;\n}\n\n/** Process-local listener awaited before a terminal agent event is emitted. */\nexport type SessionBeforeAgentEndListener = (\n  event: Extract<AgentControllerEvent, { type: 'agent_end' }>,\n) => void | Promise<void>;\n\n/** Options for {@link Session.sendNotificationSignal}. */\nexport type SessionSendNotificationSignalOptions = {\n  ifActive?: SendAgentNotificationSignalOptions['ifActive'];\n  ifIdle?: SendAgentNotificationSignalOptions['ifIdle'];\n  tracingContext?: TracingContext;\n  tracingOptions?: TracingOptions;\n  requestContext?: RequestContext;\n};\n\n/** Usage fields that are summed across steps when present on a step's usage. */\ntype OptionalUsageField =\n  | 'reasoningTokens'\n  | 'cachedInputTokens'\n  | 'cacheCreationInputTokens'\n  | 'cacheCreationInputTokens5m'\n  | 'cacheCreationInputTokens1h';\n\nfunction addOptionalUsageField(usage: TokenUsage, key: OptionalUsageField, value: number | undefined): void {\n  if (value !== undefined) {\n    usage[key] = (usage[key] ?? 0) + value;\n  }\n}\n\n/** Persisted thread-setting key for the currently-selected mode. */\nconst MODE_ID_KEY = 'currentModeId';\n\n/**\n * Reason attached to tool prompts retracted because the user aborted the run.\n * Shared by the parked-suspension retraction and the gated-approval decline so\n * both render the same \"the user interrupted this\" explanation.\n */\nexport const ABORTED_BY_USER_REASON = 'Aborted by the user';\n\n/**\n * Session-state keys that are transparently persisted to thread metadata on\n * every state update and restored by `Session.loadMetadata()`. These are user\n * preferences that must survive a host restart (sessions themselves are\n * in-memory only).\n */\nconst PERSISTED_STATE_KEYS = ['thinkingLevel', 'notifications'] as const;\n/** Persisted thread-setting key prefix for a mode's last-used model. */\nconst modeModelKey = (modeId: string) => `modeModelId_${modeId}`;\n\n/**\n * Internal thread-metadata keys used by `Session.loadMetadata()` to persist\n * runtime bookkeeping (selected model/mode, observer/reflector config, token\n * usage). These share the flat thread `metadata` bag with user-provided\n * session scoping tags, so they must never be treated as tags: they are\n * skipped when stamping tags onto a thread and excluded when reading tags\n * back out of thread metadata.\n */\nconst RESERVED_THREAD_METADATA_KEYS = [\n  'currentModelId',\n  MODE_ID_KEY,\n  'observerModelId',\n  'reflectorModelId',\n  'observationThreshold',\n  'reflectionThreshold',\n  'tokenUsage',\n  ...PERSISTED_STATE_KEYS,\n] as const;\n\n/** Packages that cannot import the list as a value pin their copy to it with `satisfies Record<ReservedThreadMetadataKey, true>`. */\nexport type ReservedThreadMetadataKey = (typeof RESERVED_THREAD_METADATA_KEYS)[number];\n\nfunction isReservedThreadMetadataKey(key: string): boolean {\n  return RESERVED_THREAD_METADATA_KEYS.some(reserved => reserved === key) || key.startsWith('modeModelId_');\n}\n\n/**\n * Owns the session's identity: the memory `resourceId` and the active\n * `threadId` this session reads and writes under. Together they form the memory\n * binding (`{ thread, resource }`) every run uses. In a multi-user host one\n * AgentController serves many sessions, so this identity — \"whose session is this, and\n * which thread is it on\" — belongs to the Session, not the AgentController.\n *\n * `defaultResourceId` is the resourceId the session started with; switching to a\n * different resource (e.g. impersonation, or browsing another user's threads)\n * updates the current resourceId while the default is retained so the session\n * can return to its own identity.\n *\n * `id` is the stable identifier for this session (mirrors `SessionRecord.id` in\n * storage) and `ownerId` is the owner of this session (mirrors\n * `SessionRecord.ownerId`). Both are stable for the life of the session and do\n * not change when the resourceId is switched.\n *\n * The active thread the session is bound to lives on {@link SessionThread}, not\n * here — identity is the stable \"who\", the thread is the navigational \"where\".\n */\nexport class SessionIdentity {\n  /** The memory resourceId the session currently reads/writes under. */\n  #resourceId: string;\n  /** The resourceId the session started with, retained across resource switches. */\n  readonly #defaultResourceId: string;\n  /** Stable session identifier (mirrors SessionRecord.id in storage). */\n  readonly #id: string;\n  /** Stable session owner (mirrors SessionRecord.ownerId in storage). */\n  readonly #ownerId: string;\n\n  constructor({ resourceId, id, ownerId }: { resourceId: string; id: string; ownerId: string }) {\n    this.#resourceId = resourceId;\n    this.#defaultResourceId = resourceId;\n    this.#id = id;\n    this.#ownerId = ownerId;\n  }\n\n  /** The resourceId the session currently reads/writes under. */\n  getResourceId(): string {\n    return this.#resourceId;\n  }\n\n  /** The resourceId the session started with. */\n  getDefaultResourceId(): string {\n    return this.#defaultResourceId;\n  }\n\n  /** The stable session identifier for this session. */\n  getId(): string {\n    return this.#id;\n  }\n\n  /** The stable owner identifier for this session. */\n  getOwnerId(): string {\n    return this.#ownerId;\n  }\n\n  /** Point the session at a different resourceId (the default is unchanged). */\n  setResourceId({ resourceId }: { resourceId: string }): void {\n    this.#resourceId = resourceId;\n  }\n}\n\n/**\n * The shared-host storage surface the Session's thread domain leverages to read\n * and write threads. The AgentController backs this with its memory storage (mapping raw\n * storage rows to {@link AgentControllerThread}/{@link MastraDBMessage}); when no storage\n * is configured the handle is absent and the data methods degrade gracefully\n * (empty lists, undefined settings, no-op writes).\n *\n * This is a gateway to shared infrastructure — not a callback into AgentController\n * orchestration. The Session owns the thread-domain logic; the host owns the DB.\n */\nexport interface ThreadDataStore {\n  /** List threads for a resource (or all resources), already mapped + filtered of forked subagents unless asked. */\n  listThreads(input: {\n    resourceId?: string;\n    includeForkedSubagents?: boolean;\n    metadata?: Record<string, unknown>;\n  }): Promise<AgentControllerThread[]>;\n  /** Fetch a single thread by id, or null when it doesn't exist. */\n  getById(input: { threadId: string }): Promise<AgentControllerThread | null>;\n  /** List messages for a thread, newest-`limit` (returned oldest-first) or all. */\n  listMessages(input: { threadId: string; limit?: number }): Promise<StorageListMessagesOutput>;\n  /** The first user message for each given thread id. */\n  firstUserMessages(input: { threadIds: string[] }): Promise<Map<string, MastraDBMessage>>;\n  /** Read a value from a thread's metadata. */\n  getMetadata(input: { threadId: string; key: string }): Promise<unknown>;\n  /** Write a value into a thread's metadata. */\n  setMetadata(input: { threadId: string; key: string; value: unknown }): Promise<void>;\n  /** Delete a value from a thread's metadata. */\n  deleteMetadata(input: { threadId: string; key: string }): Promise<void>;\n  /** Whether the host has thread storage configured. When false, lifecycle persistence is a no-op. */\n  hasStorage(): boolean;\n  /** Persist a new or updated thread row. No-op when storage is unavailable. */\n  saveThread(input: { thread: AgentControllerThread }): Promise<void>;\n  /** Delete a thread row by id. No-op when storage is unavailable. */\n  deleteThread(input: { threadId: string }): Promise<void>;\n  /** Clone a thread (and its messages) via the host's memory, returning the new thread. */\n  cloneThread(input: {\n    sourceThreadId: string;\n    resourceId: string;\n    title?: string;\n    metadata?: Record<string, unknown>;\n  }): Promise<AgentControllerThread>;\n  /** Acquire the host thread lock for a thread id. No-op when no lock is configured. */\n  acquireLock(threadId: string): Promise<void>;\n  /** Release the host thread lock for a thread id. No-op when no lock is configured. */\n  releaseLock(threadId: string): Promise<void>;\n  /** The host's configured mode ids, used to validate a thread's persisted mode on restore. */\n  getModeIds(): string[];\n}\n\n/**\n * The AgentController-owned machinery a Session leverages to drive an agent run. In the\n * multi-user host one AgentController serves many sessions; the run loop, run state, and\n * thread stream are per-session (they cannot be shared) and so belong on the\n * Session. But *how* a run is produced — which agent answers, the config-backed\n * run/stream options, the toolset, the request context, the tool-approval\n * policy, usage persistence, id generation — is shared infrastructure the\n * AgentController owns. The AgentController injects this machinery into each Session it\n * constructs (via {@link Session.setMachinery}); the Session calls into it but\n * never reaches back into the AgentController or another session.\n *\n * This is the formalized DI boundary: the Session receives exactly the\n * capabilities it is allowed to use, nothing more.\n */\nexport interface SessionMachinery {\n  /** Resolve the agent that should answer for the session's current mode/model. */\n  getAgent(): Agent;\n  /** Get the ephemeral state associated with an active or suspended run. */\n  getRunScope(runId: string): RunScope | undefined;\n  /** Open a fresh subscription to a thread's agent event stream. */\n  subscribeToThread(input: {\n    agent?: Agent;\n    resourceId: string;\n    threadId: string;\n  }): Promise<AgentThreadSubscription<any>>;\n  /** Build the per-call stream options (instructions, memory, toolsets, abort signal, tracing). */\n  buildStreamOptions(input: {\n    requestContext?: RequestContext;\n    tracingContext?: TracingContext;\n    tracingOptions?: TracingOptions;\n    untilIdle?: boolean | { maxIdleMs?: number };\n    /** Queue preparation owns this signal instead of mutating the active Session run. */\n    abortSignal?: AbortSignal;\n    /**\n     * Thread the run should read and write, when it is not the session's current\n     * one — a claimed thread being woken by a peer, for instance. Memory and\n     * request-context thread bindings follow this value.\n     */\n    threadId?: string;\n  }): Promise<Record<string, unknown>>;\n  /** The run budget every initial stream and resume must carry (maxSteps, provider fallbacks, …). */\n  buildSharedRunOptions(): Record<string, unknown>;\n  /** Resolve the toolset (built-in controller  tools + user/subagent tools) for a run. */\n  buildToolsets(requestContext: RequestContext): Promise<ToolsetsInput>;\n  /** Resolve the effective request context for a run, layering controller defaults. */\n  buildRequestContext(requestContext?: RequestContext): Promise<RequestContext>;\n  /** Persist the session's running token usage to thread metadata. */\n  persistTokenUsage(): Promise<void>;\n  /** Generate a new id (thread ids, message ids) using the host's id strategy. */\n  generateId(): string;\n  /**\n   * Resolve the mode the session transitions to when a plan is approved: the\n   * current mode's `transitionsTo`, else the host's default mode. Returns\n   * `undefined` when the host has no default mode. The mode catalog is AgentController\n   * config, so this is genuinely host-owned.\n   */\n  resolveTransitionModeId(): string | undefined;\n  /**\n   * Persist a system-reminder message to a thread, returning the saved message\n   * (or `null` when no storage is configured). Pure host-owned persistence\n   * (storage handle + id strategy).\n   */\n  saveSystemReminder(input: {\n    threadId: string;\n    resourceId: string;\n    message: string;\n    reminderType: string;\n    role: 'user' | 'assistant' | 'system';\n    metadata?: Record<string, unknown>;\n  }): Promise<MastraDBMessage | null>;\n}\n\n/**\n * Owns the session's thread domain: the navigational binding (which thread the\n * session is currently on) plus the data reads/queries scoped to it. `null`\n * until the session is bound (a thread is created, switched to, or reacquired on\n * startup); switching/deleting updates it.\n *\n * In the multi-user model each session has its own current thread and reads its\n * own threads, while the AgentController host shares storage, the thread lock, and the\n * event bus. So the binding + data queries are per-session and live here; the\n * session leverages the host's storage via an injected {@link ThreadDataStore}.\n * Lifecycle *transitions* (create/switch/clone/delete) remain host machinery\n * because they drive the shared event bus and rebind the shared agent stream.\n */\nexport class SessionThread {\n  /** The active thread id, or null when the session is not bound to a thread. */\n  #threadId: string | null = null;\n  /** Gateway to the host's shared thread storage, injected via {@link connect}. */\n  #store: ThreadDataStore | undefined;\n  /** Reads the session's current resourceId (sibling identity state). */\n  readonly #getResourceId: () => string;\n  /**\n   * The owning session, injected via {@link connect}. Thread lifecycle\n   * transitions (create/switch/clone/delete) orchestrate sibling session\n   * subsystems (model/mode/om/state/stream/run/usage/event bus) plus rebind the\n   * agent subscription, so the thread domain reaches its peers through this\n   * back-reference. Host-owned primitives (storage, lock, clone) stay behind the\n   * injected {@link ThreadDataStore}.\n   */\n  #session: Session | undefined;\n\n  constructor(getResourceId: () => string) {\n    this.#getResourceId = getResourceId;\n  }\n\n  /**\n   * Attach the shared-host storage gateway the thread domain reads/writes\n   * through and the owning session whose subsystems lifecycle transitions\n   * orchestrate. The AgentController calls this once during wiring; without a store the\n   * data methods degrade gracefully.\n   */\n  connect(store: ThreadDataStore | undefined, session: Session): void {\n    this.#store = store;\n    this.#session = session;\n  }\n\n  /** The owning session, throwing when accessed before {@link connect}. */\n  get #owner(): Session {\n    if (!this.#session) {\n      throw new Error('SessionThread has not been connected to its session');\n    }\n    return this.#session;\n  }\n\n  /** The active thread id, or null when the session is not bound to a thread. */\n  getId(): string | null {\n    return this.#threadId;\n  }\n\n  /** Whether the session is currently bound to a thread. */\n  isSet(): boolean {\n    return this.#threadId !== null;\n  }\n\n  /** The active thread id, throwing when the session is not bound to a thread. */\n  requireId(): string {\n    if (this.#threadId === null) {\n      throw new Error('No active thread on this session');\n    }\n    return this.#threadId;\n  }\n\n  /** Bind the session to a thread. */\n  set({ threadId }: { threadId: string }): void {\n    this.#threadId = threadId;\n  }\n\n  /** Clear the session's thread binding. */\n  clear(): void {\n    this.#threadId = null;\n  }\n\n  /** Clear the session's thread binding and release its lock when one is held. */\n  async clearAndReleaseLock(): Promise<void> {\n    const threadId = this.#threadId;\n    this.#threadId = null;\n    if (threadId) {\n      await this.#store?.releaseLock(threadId);\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // Data domain: reads/queries scoped to this session, backed by host storage.\n  // ---------------------------------------------------------------------------\n\n  /** List this session's threads (its own resource by default, or all resources). */\n  async list(options?: {\n    allResources?: boolean;\n    includeForkedSubagents?: boolean;\n    metadata?: Record<string, unknown>;\n  }): Promise<AgentControllerThread[]> {\n    if (!this.#store) {\n      return [];\n    }\n    const resourceId = options?.allResources ? undefined : this.#getResourceId();\n    const threads = await this.#store.listThreads({\n      resourceId,\n      includeForkedSubagents: options?.includeForkedSubagents,\n      metadata: options?.metadata,\n    });\n    return threads;\n  }\n\n  /** Fetch a single thread by id, or null when it doesn't exist / no storage. */\n  async getById({ threadId }: { threadId: string }): Promise<AgentControllerThread | null> {\n    if (!this.#store) return null;\n    return this.#store.getById({ threadId });\n  }\n\n  /** Clone a detected cross-resource project thread into this session's resource. */\n  async cloneToCurrentResource({\n    threadId,\n    expectedResourceId,\n    expectedProjectPath,\n  }: {\n    threadId: string;\n    expectedResourceId: string;\n    expectedProjectPath: string;\n  }): Promise<AgentControllerThread> {\n    if (!this.#store?.hasStorage()) {\n      throw new Error('Memory is not configured on this AgentController');\n    }\n    const thread = await this.#store.getById({ threadId });\n    if (\n      !thread ||\n      thread.resourceId !== expectedResourceId ||\n      thread.metadata?.projectPath !== expectedProjectPath ||\n      expectedResourceId === this.#getResourceId()\n    ) {\n      throw new Error(`Thread not found: ${threadId}`);\n    }\n    return this.#cloneThread({\n      sourceThreadId: thread.id,\n      resourceId: this.#getResourceId(),\n      title: thread.title,\n      metadata: thread.metadata,\n    });\n  }\n\n  /**\n   * Load a thread and verify it belongs to this session's resourceId before\n   * allowing access. Threads owned by another resource are treated as missing\n   * so a session can never read, switch to, rename, or delete a thread it does\n   * not own (the thread id is otherwise an unguessable but unscoped key). Throws\n   * `Thread not found: <id>` when the thread is absent or owned by someone else.\n   */\n  async #requireOwnedThread({ threadId }: { threadId: string }): Promise<AgentControllerThread> {\n    const thread = await this.#store?.getById({ threadId });\n    if (!thread || thread.resourceId !== this.#getResourceId()) {\n      throw new Error(`Thread not found: ${threadId}`);\n    }\n    return thread;\n  }\n\n  /** List messages for a thread (newest-`limit`, returned oldest-first), or all. */\n  async listMessages({ threadId, limit }: { threadId: string; limit?: number }): Promise<MastraDBMessage[]> {\n    if (!this.#store) return [];\n    // Only expose messages for threads this session owns.\n    await this.#requireOwnedThread({ threadId });\n    return (await this.#store.listMessages({ threadId, limit })).messages;\n  }\n\n  /** List messages for the session's active thread (empty when not bound). */\n  async listActiveMessages({ limit }: { limit?: number } = {}): Promise<MastraDBMessage[]> {\n    if (this.#threadId === null) return [];\n    return this.listMessages({ threadId: this.#threadId, limit });\n  }\n\n  /** The first user message for a single thread, or null. */\n  async firstUserMessage({ threadId }: { threadId: string }): Promise<MastraDBMessage | null> {\n    const messages = await this.firstUserMessages({ threadIds: [threadId] });\n    return messages.get(threadId) ?? null;\n  }\n\n  /** The first user message for each given thread id. */\n  async firstUserMessages({ threadIds }: { threadIds: string[] }): Promise<Map<string, MastraDBMessage>> {\n    if (!this.#store || threadIds.length === 0) return new Map();\n    return this.#store.firstUserMessages({ threadIds });\n  }\n\n  /** Read a setting (metadata value) for the active thread. */\n  async getSetting({ key }: { key: string }): Promise<unknown> {\n    if (this.#threadId === null) return undefined;\n    return this.getSettingOn({ threadId: this.#threadId, key });\n  }\n\n  /** Read a setting from a specific thread, regardless of the current binding. */\n  async getSettingOn({ threadId, key }: { threadId: string; key: string }): Promise<unknown> {\n    if (!this.#store) return undefined;\n    return this.#store.getMetadata({ threadId, key });\n  }\n\n  /** Persist a setting (metadata value) for the active thread. */\n  async setSetting({ key, value }: { key: string; value: unknown }): Promise<void> {\n    if (this.#threadId === null) return;\n    await this.setSettingOn({ threadId: this.#threadId, key, value });\n  }\n\n  /** Persist a setting to a specific thread, regardless of the current binding. */\n  async setSettingOn({ threadId, key, value }: { threadId: string; key: string; value: unknown }): Promise<void> {\n    if (!this.#store) return;\n    if (value === undefined) {\n      await this.#store.deleteMetadata({ threadId, key });\n      return;\n    }\n    await this.#store.setMetadata({ threadId, key, value });\n  }\n\n  /** Delete a setting (metadata value) for the active thread. */\n  async deleteSetting({ key }: { key: string }): Promise<void> {\n    if (!this.#store || this.#threadId === null) return;\n    await this.#store.deleteMetadata({ threadId: this.#threadId, key });\n  }\n\n  // ---------------------------------------------------------------------------\n  // Lifecycle: transitions that bind/rebind this session to a thread. These\n  // orchestrate sibling subsystems (model/mode/om/state/usage/event bus) and the\n  // agent subscription via the owning session, and reach host storage/lock/clone\n  // through the injected gateway.\n  // ---------------------------------------------------------------------------\n\n  /** Tear down the current agent subscription and reset the run tracker. */\n  cleanupSubscription(): void {\n    this.#owner.cleanupFollowUpBinding();\n    this.#owner.stream.cleanup();\n    this.#owner.run.reset();\n  }\n\n  /**\n   * Ensure the session is subscribed to the given agent/thread stream, opening a\n   * fresh subscription (and driving its run loop) when the binding changed.\n   */\n  async ensureSubscription(threadId: string, agent = this.#owner.machinery.getAgent()): Promise<void> {\n    const session = this.#owner;\n    const resourceId = this.#getResourceId();\n    const key = SessionStream.keyFor({ agent, resourceId, threadId });\n    if (session.stream.matches({ key })) {\n      session.ensureFollowUpBinding(agent, resourceId, threadId);\n      return;\n    }\n\n    this.cleanupSubscription();\n    const subscription = await session.machinery.subscribeToThread({ agent, resourceId, threadId });\n    session.stream.attach({ subscription, agent, key });\n    session.ensureFollowUpBinding(agent, resourceId, threadId);\n    void session.processSubscribedThreadStream(subscription);\n  }\n\n  /** Ensure a subscription for the session's active thread (no-op when unbound). */\n  async ensureCurrentSubscription(): Promise<void> {\n    if (this.#threadId === null) return;\n    await this.ensureSubscription(this.#threadId);\n  }\n\n  /**\n   * Detach from the current thread: stop this process's run and tear down the\n   * subscription. The abort is local — unbinding a thread must not reach a remote\n   * owner and kill its run (another instance on the same thread may be the one\n   * actually running it).\n   */\n  detachFromCurrent(): void {\n    this.#owner.abort({ localOnly: true });\n    this.cleanupSubscription();\n  }\n\n  /** Create a new thread, bind the session to it, and rebind the agent stream. */\n  async create({ title, id }: { title?: string; id?: string } = {}): Promise<AgentControllerThread> {\n    const session = this.#owner;\n    const store = this.#store;\n    this.cleanupSubscription();\n    const now = new Date();\n    const thread: AgentControllerThread = {\n      id: id ?? session.machinery.generateId(),\n      resourceId: session.identity.getResourceId(),\n      title: title || '',\n      createdAt: now,\n      updatedAt: now,\n    };\n\n    const currentStateModel = session.model.get();\n    const currentMode = session.mode.resolve();\n    const modelId = currentStateModel || currentMode.defaultModelId;\n\n    const metadata: Record<string, unknown> = {};\n    if (modelId) {\n      metadata.currentModelId = modelId;\n      metadata[`modeModelId_${session.mode.get()}`] = modelId;\n    }\n\n    // Stamp the session's scope so thread selection can filter listings back to\n    // it (e.g. a `projectPath` per git worktree).\n    Object.assign(metadata, session.getThreadScope());\n\n    // Acquire lock on new thread before releasing old one.\n    // If acquire fails, attempt to re-acquire the old lock before rethrowing.\n    const oldThreadId = this.#threadId;\n    if (store) {\n      try {\n        await store.acquireLock(thread.id);\n      } catch (err) {\n        if (oldThreadId) {\n          try {\n            await store.acquireLock(oldThreadId);\n          } catch {\n            // Best-effort re-acquire; original error is more important\n          }\n        }\n        throw err;\n      }\n      if (oldThreadId) {\n        try {\n          await store.releaseLock(oldThreadId);\n        } catch {\n          // Best-effort release of the old lock; the new lock is already held.\n        }\n      }\n    }\n\n    if (store?.hasStorage()) {\n      try {\n        await store.saveThread({\n          thread: {\n            id: thread.id,\n            resourceId: thread.resourceId,\n            title: thread.title!,\n            createdAt: thread.createdAt,\n            updatedAt: thread.updatedAt,\n            metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n          },\n        });\n      } catch (err) {\n        // saveThread failed after lock was swapped; restore previous lock state\n        let reacquired = false;\n        try {\n          await store.releaseLock(thread.id);\n        } catch {\n          // Best-effort release of new thread lock\n        }\n        if (oldThreadId) {\n          try {\n            await store.acquireLock(oldThreadId);\n            reacquired = true;\n          } catch {\n            // Re-acquire failed; no lock is held\n          }\n        }\n        if (reacquired && oldThreadId) {\n          this.set({ threadId: oldThreadId });\n        } else {\n          this.clear();\n        }\n        throw err;\n      }\n    }\n\n    this.set({ threadId: thread.id });\n\n    if (modelId && !currentStateModel) {\n      session.model.set({ modelId });\n    }\n\n    session.resetTokenUsage();\n    session.emit({ type: 'thread_created', thread });\n    await this.ensureCurrentSubscription();\n\n    return thread;\n  }\n\n  /**\n   * Rename the session's active thread. No-op when unbound or storageless.\n   *\n   * Renames pin the title by default (`metadata.titlePinned`) so Observational\n   * Memory's title extractor cannot overwrite a user's manual rename. Pass\n   * `pin: false` for programmatic title writes that should keep auto-naming.\n   */\n  async rename({ title, pin = true }: { title: string; pin?: boolean }): Promise<void> {\n    const store = this.#store;\n    const threadId = this.#threadId;\n    if (!threadId || !store?.hasStorage()) return;\n\n    const thread = await store.getById({ threadId });\n    if (thread) {\n      await store.saveThread({\n        thread: {\n          ...thread,\n          title,\n          metadata: { ...thread.metadata, [TITLE_PINNED_THREAD_METADATA_KEY]: pin },\n          updatedAt: new Date(),\n        },\n      });\n      this.#owner.emit({ type: 'thread_title_updated', threadId, title });\n    }\n  }\n\n  /** Clone a thread (and its messages), bind the session to the clone, and rebind the stream. */\n  async clone({\n    sourceThreadId,\n    title,\n    resourceId,\n  }: {\n    sourceThreadId?: string;\n    title?: string;\n    resourceId?: string;\n  } = {}): Promise<AgentControllerThread> {\n    const sourceId = sourceThreadId ?? this.#threadId;\n    if (!sourceId) {\n      throw new Error('No source thread to clone');\n    }\n    // Only allow cloning from a source thread this session owns.\n    if (this.#store?.hasStorage()) {\n      await this.#requireOwnedThread({ threadId: sourceId });\n    }\n    return this.#cloneThread({\n      sourceThreadId: sourceId,\n      resourceId: resourceId ?? this.#owner.identity.getResourceId(),\n      title,\n    });\n  }\n\n  async #cloneThread({\n    sourceThreadId,\n    resourceId,\n    title,\n    metadata,\n  }: {\n    sourceThreadId: string;\n    resourceId: string;\n    title?: string;\n    metadata?: Record<string, unknown>;\n  }): Promise<AgentControllerThread> {\n    const session = this.#owner;\n    const store = this.#store;\n    if (!store) {\n      throw new Error('Memory is not configured on this AgentController');\n    }\n\n    const clonedThread = await store.cloneThread({ sourceThreadId, resourceId, title, metadata });\n\n    // Acquire lock on new thread before releasing old one\n    const oldThreadId = this.#threadId;\n    try {\n      await store.acquireLock(clonedThread.id);\n    } catch (err) {\n      if (oldThreadId) {\n        try {\n          await store.acquireLock(oldThreadId);\n        } catch {\n          // Best-effort re-acquire; original error is more important\n        }\n      }\n      throw err;\n    }\n    if (oldThreadId) {\n      await store.releaseLock(oldThreadId);\n    }\n\n    this.cleanupSubscription();\n    this.set({ threadId: clonedThread.id });\n    await this.loadMetadata();\n    session.resetTokenUsage();\n    session.emit({ type: 'thread_created', thread: clonedThread });\n    await this.ensureCurrentSubscription();\n\n    return clonedThread;\n  }\n\n  /** Switch the session to an existing thread, hydrating its persisted settings and rebinding the stream. */\n  async switch({ threadId, emitEvent = true }: { threadId: string; emitEvent?: boolean }): Promise<void> {\n    const session = this.#owner;\n    const store = this.#store;\n    session.abort({ localOnly: true });\n    this.cleanupSubscription();\n\n    // Acquire lock on new thread before releasing old one.\n    // Lock operations must be adjacent (no intermediate awaits) so callers\n    // can rely on a single microtask tick to observe both acquire and release.\n    await store?.acquireLock(threadId);\n    const previousThreadId = this.#threadId;\n    if (previousThreadId) {\n      await store?.releaseLock(previousThreadId);\n    }\n\n    // Verify the thread exists and belongs to this session's resourceId before\n    // binding to it, so a session can never switch onto a thread owned by\n    // another resource. Release the just-acquired lock if the check fails so we\n    // never leave a foreign thread locked.\n    if (store?.hasStorage()) {\n      try {\n        await this.#requireOwnedThread({ threadId });\n      } catch (err) {\n        // Release the just-acquired foreign lock and restore the previous\n        // thread's lock so the still-bound session is not left unlocked.\n        await store.releaseLock(threadId).catch(() => {});\n        if (previousThreadId) {\n          await store.acquireLock(previousThreadId).catch(() => {});\n        }\n        throw err;\n      }\n    }\n\n    this.set({ threadId });\n\n    await this.loadMetadata();\n\n    if (emitEvent) {\n      session.emit({ type: 'thread_changed', threadId, previousThreadId });\n    }\n    await this.ensureCurrentSubscription();\n  }\n\n  /** Delete a thread; when it's the active thread, clear the binding and tear down the run. */\n  async delete({ threadId }: { threadId: string }): Promise<void> {\n    const session = this.#owner;\n    const store = this.#store;\n    if (!store?.hasStorage()) return;\n\n    // Only allow deleting threads this session owns.\n    await this.#requireOwnedThread({ threadId });\n\n    const isDeletingCurrentThread = this.#threadId === threadId;\n\n    await store.deleteThread({ threadId });\n\n    if (isDeletingCurrentThread) {\n      try {\n        await store.releaseLock(threadId);\n      } catch {\n        // Lock release failed; proceed with state cleanup regardless\n      }\n      this.cleanupSubscription();\n      this.clear();\n      session.resetTokenUsage();\n    }\n\n    session.emit({ type: 'thread_deleted', threadId });\n  }\n\n  /**\n   * Hydrate the session's per-thread settings from the active thread's metadata:\n   * token usage, the persisted mode (restored first), the per-mode model, and\n   * observer/reflector model ids + thresholds. Best-effort: on any failure the\n   * token tally is reset and the rest is left at defaults.\n   */\n  async loadMetadata(): Promise<void> {\n    const session = this.#owner;\n    const store = this.#store;\n    const threadId = this.#threadId;\n    if (!threadId || !store?.hasStorage()) {\n      session.resetTokenUsage();\n      return;\n    }\n\n    try {\n      const thread = await store.getById({ threadId });\n\n      // Load token usage\n      const savedUsage = thread?.metadata?.tokenUsage as TokenUsage | undefined;\n      if (savedUsage) {\n        session.setTokenUsage({\n          ...createEmptyTokenUsage(),\n          ...savedUsage,\n          promptTokens: savedUsage.promptTokens ?? 0,\n          completionTokens: savedUsage.completionTokens ?? 0,\n          totalTokens: savedUsage.totalTokens ?? 0,\n          cachedInputTokens: savedUsage.cachedInputTokens ?? 0,\n          cacheCreationInputTokens: savedUsage.cacheCreationInputTokens ?? 0,\n        });\n      } else {\n        session.resetTokenUsage();\n      }\n\n      const meta = thread?.metadata as Record<string, unknown> | undefined;\n      const updates: Record<string, unknown> = {};\n\n      // Restore the saved mode FIRST so we resolve currentModelId for the\n      // correct mode. Otherwise we'd look up modeModelId_<defaultMode> first\n      // and then never overwrite it when the saved mode has no per-mode\n      // override persisted (e.g. user only ever used the mode's default\n      // model), leaving the wrong mode's model active on restart.\n      let previousModeIdForEmit: string | undefined;\n      if (meta?.currentModeId) {\n        const savedModeId = meta.currentModeId as string;\n        const modeExists = store.getModeIds().includes(savedModeId);\n        if (modeExists && savedModeId !== session.mode.get()) {\n          previousModeIdForEmit = session.mode.get();\n          session.mode.set({ modeId: savedModeId });\n        }\n      }\n\n      // Resolve the model for the (now-restored) current mode and apply it to\n      // the session (source of truth for the selected model).\n      // Order: per-mode thread metadata → mode's defaultModelId → legacy\n      // global currentModelId (set by create()).\n      const currentModeId = session.mode.get();\n      const modeModelKey = `modeModelId_${currentModeId}`;\n      if (meta?.[modeModelKey]) {\n        session.model.set({ modelId: meta[modeModelKey] as string });\n      } else {\n        const currentMode = session.mode.resolve();\n        if (currentMode.defaultModelId) {\n          session.model.set({ modelId: currentMode.defaultModelId });\n        } else if (meta?.currentModelId) {\n          session.model.set({ modelId: meta.currentModelId as string });\n        }\n      }\n\n      if (previousModeIdForEmit !== undefined) {\n        session.emit({\n          type: 'mode_changed',\n          modeId: session.mode.get(),\n          previousModeId: previousModeIdForEmit,\n        });\n      }\n\n      // Restore observer/reflector model IDs\n      if (meta?.observerModelId) {\n        updates.observerModelId = meta.observerModelId;\n      }\n      if (meta?.reflectorModelId) {\n        updates.reflectorModelId = meta.reflectorModelId;\n      }\n      const hasObservationThreshold = typeof meta?.observationThreshold === 'number';\n      const hasReflectionThreshold = typeof meta?.reflectionThreshold === 'number';\n\n      if (hasObservationThreshold) {\n        updates.observationThreshold = meta.observationThreshold;\n      }\n      if (hasReflectionThreshold) {\n        updates.reflectionThreshold = meta.reflectionThreshold;\n      }\n\n      if (Object.keys(updates).length > 0) {\n        await session.state.set(updates as Record<string, unknown>);\n      }\n\n      // Restore restart-surviving preferences (thinking level, notifications).\n      // Applied one key at a time so an invalid persisted value fails schema\n      // validation without discarding the mode/model/OM restoration above or\n      // the other, still-valid preference.\n      for (const key of PERSISTED_STATE_KEYS) {\n        const value = meta?.[key];\n        if (value === undefined) continue;\n        try {\n          await session.state.set({ [key]: value } as Record<string, unknown>);\n        } catch {\n          // Persisted preference no longer valid for the current state schema.\n        }\n      }\n\n      if (!hasObservationThreshold) {\n        const observationThreshold = session.om.observer.threshold();\n        if (observationThreshold !== undefined) {\n          await this.setSetting({ key: 'observationThreshold', value: observationThreshold });\n        }\n      }\n      if (!hasReflectionThreshold) {\n        const reflectionThreshold = session.om.reflector.threshold();\n        if (reflectionThreshold !== undefined) {\n          await this.setSetting({ key: 'reflectionThreshold', value: reflectionThreshold });\n        }\n      }\n    } catch {\n      // A transient metadata read failure must NOT destroy the running tally:\n      // resetting here would replace measured token usage with a false zero.\n      // Preserve the existing in-memory tally and leave other settings at their\n      // current values.\n    }\n  }\n}\n\n/**\n * Owns the session's live subscription to the active thread's agent event\n * stream. A subscription is created per `(agent, resource, thread)` and reused\n * while that triple is unchanged (tracked by {@link key}); switching threads or\n * agents tears the old one down and opens a new one.\n *\n * The Session owns the subscription *handle* and its dedup key plus the\n * mechanical lifecycle (reuse check, teardown, identity check, run-id read).\n * The AgentController still owns *how* a subscription is produced (calling the agent)\n * and *how* its stream is consumed, passing the resolved handle in via\n * {@link attach}.\n */\nexport class SessionStream {\n  /** The live subscription to the active thread, or null when none is open. */\n  #subscription: AgentThreadSubscription<any> | null = null;\n  /** Agent that created the live subscription, or null when none is open. */\n  #agent: Agent | null = null;\n  /** Dedup key (`agentId:resourceId:threadId`) for the open subscription, or null. */\n  #key: string | null = null;\n  readonly #teardownWaiters = new Set<() => void>();\n\n  #notifyTeardown(): void {\n    const waiters = [...this.#teardownWaiters];\n    this.#teardownWaiters.clear();\n    for (const waiter of waiters) waiter();\n  }\n\n  waitForTeardown(signal: AbortSignal): Promise<void> {\n    return new Promise(resolve => {\n      const done = () => {\n        signal.removeEventListener('abort', abort);\n        resolve();\n      };\n      const abort = () => {\n        this.#teardownWaiters.delete(done);\n        resolve();\n      };\n      if (signal.aborted) return resolve();\n      this.#teardownWaiters.add(done);\n      signal.addEventListener('abort', abort, { once: true });\n    });\n  }\n\n  /** Build the dedup key identifying a subscription to `threadId` for `agent`. */\n  static keyFor({ agent, resourceId, threadId }: { agent: Agent; resourceId: string; threadId: string }): string {\n    return `${agent.id}:${resourceId}:${threadId}`;\n  }\n\n  /** Whether the open subscription already targets `key` (so it can be reused). */\n  matches({ key }: { key: string }): boolean {\n    return this.#key === key && this.#subscription !== null;\n  }\n\n  /** Adopt `subscription` as the live one, recording its owning agent and dedup `key`. */\n  attach({\n    subscription,\n    agent,\n    key,\n  }: {\n    subscription: AgentThreadSubscription<any>;\n    agent?: Agent;\n    key: string;\n  }): void {\n    this.#subscription = subscription;\n    this.#agent = agent ?? null;\n    this.#key = key;\n  }\n\n  /** Agent that owns `subscription`, when it is the live subscription. */\n  getAgent({ subscription }: { subscription: AgentThreadSubscription<any> }): Agent | null {\n    return this.#subscription === subscription ? this.#agent : null;\n  }\n\n  /** Whether a subscription is currently open. */\n  isOpen(): boolean {\n    return this.#subscription !== null;\n  }\n\n  /** Whether `subscription` is the one currently adopted (identity check). */\n  isCurrent({ subscription }: { subscription: AgentThreadSubscription<any> }): boolean {\n    return this.#subscription === subscription;\n  }\n\n  /** The run id the live subscription reports as active, or null when none/idle. */\n  activeRunId(): string | null {\n    return this.#subscription?.activeRunId() ?? null;\n  }\n\n  /** Whether the live subscription currently has a run in flight. */\n  isActive(): boolean {\n    return this.activeRunId() !== null;\n  }\n\n  /**\n   * Abort the live subscription's in-flight run, if any. Swallows errors.\n   * `localOnly` keeps an abort caused by a thread lifecycle transition (detach,\n   * switch) from asking a remote thread owner to stop its run.\n   */\n  abort(options?: { localOnly?: boolean }): void {\n    try {\n      this.#subscription?.abort(options);\n    } catch {}\n  }\n\n  /** Detach the live subscription without aborting (e.g. on stream error). */\n  detach(): void {\n    this.#subscription?.unsubscribe();\n    this.#subscription = null;\n    this.#agent = null;\n    this.#key = null;\n    this.#notifyTeardown();\n  }\n\n  /**\n   * Fully tear down the live subscription: abort, unsubscribe, and clear. This is\n   * a lifecycle teardown, so the abort stays local — the binding is being dropped,\n   * not the run cancelled, and a remote owner's run must survive it.\n   */\n  cleanup(): void {\n    this.#subscription?.abort({ localOnly: true });\n    this.#subscription?.unsubscribe();\n    this.#subscription = null;\n    this.#agent = null;\n    this.#key = null;\n    this.#notifyTeardown();\n  }\n}\n\n/** A tool call parked awaiting a resume, keyed in {@link SessionSuspensions}. */\nexport interface PendingSuspension {\n  /** The run id to resume when this tool call is answered. */\n  runId: string;\n  /** The suspended tool's name (e.g. `ask_user`, `submit_plan`). */\n  toolName: string;\n  /** The thread the suspended invocation was persisted under. */\n  threadId: string;\n  /** The memory resource the suspended invocation was persisted under. */\n  resourceId: string;\n}\n\n/**\n * Owns the session's parked tool suspensions: tool calls paused via the native\n * tool-suspension primitive (e.g. `ask_user` / `request_access` / `submit_plan`)\n * that are awaiting a resume, keyed by `toolCallId`. Each entry records the run\n * id to resume and the tool name. A Map (rather than single fields) lets several\n * tools — e.g. parallel `ask_user` calls in one step — stay suspended and be\n * resumed independently.\n *\n * This is the resume *data* the AgentController reads to drive a resume. The richer\n * per-suspension UI snapshot lives on the AgentController display state; the Session\n * owns only what's needed to resume.\n */\nexport class SessionSuspensions {\n  /** Parked tool calls awaiting a resume, keyed by `toolCallId`. */\n  readonly #pending = new Map<string, PendingSuspension>();\n\n  /**\n   * Park `toolCallId` as awaiting a resume on `runId` for `toolName`, recording\n   * the thread/resource the suspended invocation was persisted under. When the\n   * same tool call is replayed for the same run (e.g. a resumed stream re-emits\n   * the suspension), the original thread/resource binding is preserved so later\n   * settlement still targets where the invocation was first persisted.\n   */\n  register({\n    toolCallId,\n    runId,\n    toolName,\n    threadId,\n    resourceId,\n  }: {\n    toolCallId: string;\n    runId: string;\n    toolName: string;\n    threadId: string;\n    resourceId: string;\n  }): void {\n    const existing = this.#pending.get(toolCallId);\n    if (existing && existing.runId === runId) {\n      this.#pending.set(toolCallId, { ...existing, toolName });\n      return;\n    }\n    this.#pending.set(toolCallId, { runId, toolName, threadId, resourceId });\n  }\n\n  /** The parked suspension for `toolCallId`, or undefined when none. */\n  get({ toolCallId }: { toolCallId: string }): PendingSuspension | undefined {\n    return this.#pending.get(toolCallId);\n  }\n\n  /** Whether `toolCallId` is currently parked. */\n  has({ toolCallId }: { toolCallId: string }): boolean {\n    return this.#pending.has(toolCallId);\n  }\n\n  /** Drop `toolCallId` from the parked set (e.g. once resumed). */\n  delete({ toolCallId }: { toolCallId: string }): void {\n    this.#pending.delete(toolCallId);\n  }\n\n  /**\n   * Drop every suspension parked on `runId`, returning the dropped toolCallIds.\n   * Used when a run reaches a terminal failure after emitting `tool_suspended`\n   * (e.g. persisting the suspended snapshot failed): those suspensions can never\n   * be resumed, so keeping them parked would leave the user with prompts whose\n   * answers fail with a misleading \"could not find a suspended run\" error.\n   * Suspensions parked on other runs are left intact.\n   */\n  deleteForRun({ runId }: { runId: string }): Array<{ toolCallId: string; toolName: string }> {\n    const dropped: Array<{ toolCallId: string; toolName: string }> = [];\n    for (const [toolCallId, suspension] of this.#pending) {\n      if (suspension.runId === runId) {\n        this.#pending.delete(toolCallId);\n        dropped.push({ toolCallId, toolName: suspension.toolName });\n      }\n    }\n    return dropped;\n  }\n\n  /**\n   * Drop all parked suspensions (e.g. on abort or thread switch), returning the\n   * dropped entries — including each suspension's original thread/resource\n   * binding — so callers can retract the corresponding prompts and settle each\n   * invocation where it was persisted.\n   */\n  clear(): Array<{ toolCallId: string } & PendingSuspension> {\n    const dropped = [...this.#pending].map(([toolCallId, suspension]) => ({ toolCallId, ...suspension }));\n    this.#pending.clear();\n    return dropped;\n  }\n\n  /** Whether any tool calls are parked awaiting a resume. */\n  hasPending(): boolean {\n    return this.#pending.size > 0;\n  }\n\n  /**\n   * Resolve which parked suspension to act on. With an explicit `toolCallId` it\n   * must match a parked suspension; without one it returns the single parked\n   * suspension (or undefined when there are zero or several).\n   */\n  resolveToolCallId(toolCallId?: string): string | undefined {\n    if (toolCallId) {\n      return this.#pending.has(toolCallId) ? toolCallId : undefined;\n    }\n    if (this.#pending.size === 1) {\n      return this.#pending.keys().next().value;\n    }\n    return undefined;\n  }\n}\n\n/** A message queued to send once the active run finishes, held in {@link SessionFollowUps}. */\nexport interface FollowUp {\n  /** The message text to send. */\n  content: string;\n  /** Optional request context to apply when the queued message is sent. */\n  requestContext?: RequestContext;\n}\n\n/**\n * Owns the session's follow-up queue: messages a user submits while a run is in\n * progress, held FIFO until the active run finishes and the queue is drained.\n *\n * This owns the queue *data* (enqueue/dequeue/requeue/clear/count). The AgentController\n * still drives draining — sending each message and emitting `follow_up_queued`\n * as the count changes — and keeps the display-state mirror (`queuedFollowUps`).\n */\nexport class SessionFollowUps {\n  /** Messages waiting to be sent after the current run, in arrival order. */\n  #queue: FollowUp[] = [];\n\n  /** Number of messages currently queued. */\n  count(): number {\n    return this.#queue.length;\n  }\n\n  /** Whether the queue is empty. */\n  isEmpty(): boolean {\n    return this.#queue.length === 0;\n  }\n\n  /** Append a follow-up to the back of the queue. */\n  enqueue(followUp: FollowUp): void {\n    this.#queue.push(followUp);\n  }\n\n  /** Remove and return the next follow-up, or undefined when empty. */\n  dequeue(): FollowUp | undefined {\n    return this.#queue.shift();\n  }\n\n  /** Put a follow-up back at the front (e.g. when draining it failed). */\n  requeue(followUp: FollowUp): void {\n    this.#queue.unshift(followUp);\n  }\n\n  /** Drop all queued follow-ups (e.g. on steer or thread switch). */\n  clear(): void {\n    this.#queue = [];\n  }\n}\n\n/** The decision a user returns to resolve a parked tool-approval gate. */\nexport interface ApprovalDecision {\n  /** Whether to run the gated tool or reject it. */\n  decision: 'approve' | 'decline';\n  /** Optional request context to apply when the gated tool resumes. */\n  requestContext?: RequestContext;\n  /** Optional context explaining why a tool approval was declined. */\n  declineContext?: { reason?: string; message?: string };\n}\n\n/**\n * A user's response to a parked approval. `always_allow_category` approves the\n * tool and additionally grants its category for the rest of the session.\n */\nexport interface ApprovalResponse {\n  decision: 'approve' | 'decline' | 'always_allow_category';\n  requestContext?: RequestContext;\n  declineContext?: { reason?: string; message?: string };\n}\n\n/**\n * Owns the session's interactive tool-approval gate: when a tool requires user\n * approval, the run parks on a promise here until the UI responds approve or\n * decline. Holds the pending resolver and the name of the tool being gated.\n *\n * At most one approval is in flight at a time. The Session owns the gate\n * mechanics (arm / resolve / clear); the AgentController still maps a decision to its\n * effects (running vs declining the tool, and any \"always allow\" grant), since\n * those touch config-derived tool categories.\n */\nexport class SessionApproval {\n  /** Resolver for the parked approval promise, or null when nothing is gated. */\n  #resolve: ((decision: ApprovalDecision) => void) | null = null;\n  /** Name of the tool currently awaiting approval, or null when none. */\n  #toolName: string | null = null;\n  /** Id of the tool call currently awaiting approval, or null when none. */\n  #toolCallId: string | null = null;\n\n  /**\n   * Park a new approval for `toolName`/`toolCallId` and return a promise that\n   * resolves once {@link respond} is called with the user's decision. The caller\n   * awaits this while the run is suspended on the gate.\n   */\n  arm({ toolName, toolCallId }: { toolName: string; toolCallId?: string }): Promise<ApprovalDecision> {\n    this.#toolName = toolName;\n    this.#toolCallId = toolCallId ?? null;\n    return new Promise<ApprovalDecision>(resolve => {\n      this.#resolve = resolve;\n    });\n  }\n\n  /** Id of the tool call currently awaiting approval, or null when none. */\n  getToolCallId(): string | null {\n    return this.#toolCallId;\n  }\n\n  /** Whether an approval is currently parked awaiting a decision. */\n  isArmed(): boolean {\n    return this.#resolve !== null;\n  }\n\n  /**\n   * Apply a user's {@link ApprovalResponse} to the parked gate. A no-op when\n   * nothing is armed. When `toolCallId` is supplied it must match the gated\n   * call; a mismatch is ignored so a stale/delayed response cannot resolve a\n   * different pending gate. `always_allow_category` runs `onAlwaysAllow` with the\n   * gated tool name (so the caller can grant the tool's category — a lookup that\n   * needs AgentController config) and then approves; `approve`/`decline` resolve as-is.\n   */\n  respond({\n    decision,\n    toolCallId,\n    requestContext,\n    declineContext,\n    onAlwaysAllow,\n  }: ApprovalResponse & { toolCallId?: string; onAlwaysAllow?: (toolName: string) => void }): void {\n    if (!this.isArmed()) return;\n    if (toolCallId !== undefined && this.#toolCallId !== null && toolCallId !== this.#toolCallId) return;\n\n    if (decision === 'always_allow_category' && this.#toolName) {\n      onAlwaysAllow?.(this.#toolName);\n    }\n\n    const resolved: ApprovalDecision = {\n      decision: decision === 'decline' ? 'decline' : 'approve',\n      requestContext,\n      declineContext,\n    };\n    this.#resolve?.(resolved);\n    this.#resolve = null;\n    this.#toolName = null;\n    this.#toolCallId = null;\n  }\n\n  /**\n   * Release a parked gate without a user decision — used when the run is\n   * aborted. Resolves the awaiting producer as a `decline` so the gated tool is\n   * rejected (not run) and the run can finalize. A no-op when nothing is armed.\n   */\n  cancel(): void {\n    if (!this.isArmed()) return;\n    this.#resolve?.({ decision: 'decline' });\n    this.#resolve = null;\n    this.#toolName = null;\n    this.#toolCallId = null;\n  }\n\n  /** Clear the gated tool name/call id once a parked approval has been consumed. */\n  clearToolName(): void {\n    this.#toolName = null;\n    this.#toolCallId = null;\n  }\n}\n\n/**\n * Owns the session's transient run identity and abort control: the id of the\n * run currently streaming on the active thread, its trace id, a monotonic\n * operation counter bumped each time a new operation starts, and the\n * AbortController/abort-requested flag governing cancellation. All of this is\n * per-run scratch state — it is never persisted and resets between runs.\n *\n * The live agent subscription itself lives on {@link SessionStream}\n * (`session.stream`); this holds the last run id observed on a chunk so callers\n * have a stable value once the subscription has settled.\n */\nexport class SessionRun {\n  /** Id of the run currently streaming on the active thread, or null when idle. */\n  #runId: string | null = null;\n  /** Trace id for the current run, or null when unset. */\n  #traceId: string | null = null;\n  /** Monotonic counter bumped at the start of each operation. */\n  #operationId = 0;\n  /** Controller whose signal cancels the active run; null when no run is armed. */\n  #abortController: AbortController | null = null;\n  /** Whether an abort has been requested for the current run. */\n  #abortRequested = false;\n  readonly #teardownWaiters = new Set<() => void>();\n  readonly #abortRequestWaiters = new Set<() => void>();\n\n  #notifyTeardown(): void {\n    const waiters = [...this.#teardownWaiters];\n    this.#teardownWaiters.clear();\n    for (const waiter of waiters) waiter();\n  }\n\n  waitForTeardown(signal: AbortSignal): Promise<void> {\n    return new Promise(resolve => {\n      const done = () => {\n        signal.removeEventListener('abort', abort);\n        resolve();\n      };\n      const abort = () => {\n        this.#teardownWaiters.delete(done);\n        resolve();\n      };\n      if (signal.aborted) return resolve();\n      this.#teardownWaiters.add(done);\n      signal.addEventListener('abort', abort, { once: true });\n    });\n  }\n\n  #notifyAbortRequested(): void {\n    const waiters = [...this.#abortRequestWaiters];\n    this.#abortRequestWaiters.clear();\n    for (const waiter of waiters) waiter();\n  }\n\n  /**\n   * Resolves once an abort is requested for the current run (immediately if\n   * one already was), or when `signal` cancels the wait.\n   */\n  waitForAbortRequest(signal: AbortSignal): Promise<void> {\n    return new Promise(resolve => {\n      const done = () => {\n        signal.removeEventListener('abort', abort);\n        resolve();\n      };\n      const abort = () => {\n        this.#abortRequestWaiters.delete(done);\n        resolve();\n      };\n      if (this.#abortRequested || signal.aborted) return resolve();\n      this.#abortRequestWaiters.add(done);\n      signal.addEventListener('abort', abort, { once: true });\n    });\n  }\n\n  /** The current run id (null when idle). */\n  getRunId(): string | null {\n    return this.#runId;\n  }\n\n  /** Set the current run id. */\n  setRunId({ runId }: { runId: string | null }): void {\n    this.#runId = runId;\n  }\n\n  /** The current trace id (null when unset). */\n  getTraceId(): string | null {\n    return this.#traceId;\n  }\n\n  /** Set the current trace id. */\n  setTraceId({ traceId }: { traceId: string | null }): void {\n    this.#traceId = traceId;\n  }\n\n  /**\n   * Clear all run state (run id, trace id, abort controller + requested flag)\n   * when a run ends or is reset. Does not touch the operation counter.\n   */\n  reset(): void {\n    this.#runId = null;\n    this.#traceId = null;\n    this.#abortController = null;\n    this.#abortRequested = false;\n    this.#notifyTeardown();\n  }\n\n  /** Bump and return the operation counter at the start of a new operation. */\n  nextOperation(): number {\n    this.#operationId += 1;\n    return this.#operationId;\n  }\n\n  /**\n   * Lazily create (if needed) and return the AbortController for the current\n   * run. Callers pass its `.signal` into the underlying stream.\n   */\n  ensureAbortController(): AbortController {\n    this.#abortController ??= new AbortController();\n    return this.#abortController;\n  }\n\n  /** Signal for the current run's AbortController, or undefined when none is armed. */\n  getAbortSignal(): AbortSignal | undefined {\n    return this.#abortController?.signal;\n  }\n\n  /**\n   * Whether a run is currently in progress. A run is armed with an\n   * AbortController for its duration, so the presence of one is what \"running\"\n   * means; this is the semantic accessor callers should use.\n   */\n  isRunning(): boolean {\n    return this.#abortController !== null;\n  }\n\n  /**\n   * Whether an AbortController is currently armed. Equivalent to\n   * {@link isRunning} today; kept for callers that assert on the controller's\n   * lifecycle specifically (e.g. that it was cleared after an abort).\n   */\n  hasAbortController(): boolean {\n    return this.#abortController !== null;\n  }\n\n  /** Clear the abort-requested flag at the start of a fresh run. */\n  clearAbortRequested(): void {\n    this.#abortRequested = false;\n  }\n\n  /** Whether an abort has been requested for the current run. */\n  isAbortRequested(): boolean {\n    return this.#abortRequested;\n  }\n\n  /**\n   * Request an abort: mark the run as aborting and fire the AbortController (if\n   * armed), then drop the controller. Leaves the requested flag set so the\n   * run-end path can resolve its reason as 'aborted'; {@link reset} clears it.\n   *\n   * `deferSignal` marks the run as aborting without firing the controller. Used\n   * when the abort interrupts a parked tool-approval gate: the gated call still\n   * has to be declined through the (still live) agent run so the denial is\n   * persisted, and firing the signal first would tear that run down underneath\n   * the decline. The engine fires the signal itself once the decline lands.\n   */\n  requestAbort({ deferSignal }: { deferSignal?: boolean } = {}): void {\n    this.#abortRequested = true;\n    if (deferSignal) {\n      this.#notifyAbortRequested();\n      return;\n    }\n    if (this.#abortController) {\n      try {\n        this.#abortController.abort();\n      } catch {}\n      this.#abortController = null;\n    }\n    this.#notifyAbortRequested();\n  }\n}\n\n/**\n * Owns the session's currently-selected model. Source of truth for \"which model\n * is active\", plus the per-mode model memory persisted to the thread-settings\n * store (so each mode remembers the model it was last used with).\n */\nexport class SessionModel {\n  #id = '';\n  readonly #store: () => ThreadSettingsStore | undefined;\n  /** This session's event bus; {@link switch} emits `model_changed` here. */\n  readonly #bus: SessionBus;\n  /**\n   * Reads the active mode id. Injected by the AgentController via {@link setResolver},\n   * since {@link switch} defaults a model change to the current mode.\n   */\n  #getCurrentModeId: (() => string) | undefined;\n  /** App hook to track model usage for ranking. Injected via {@link setResolver}. */\n  #trackModelUse: ModelUseCountTracker | undefined;\n\n  constructor(store: () => ThreadSettingsStore | undefined, bus: SessionBus) {\n    this.#store = store;\n    this.#bus = bus;\n  }\n\n  /**\n   * Attach the AgentController-owned dependencies {@link switch} needs: the active-mode\n   * accessor and the optional model-use tracker. The AgentController injects these once.\n   */\n  setResolver(options: { getCurrentModeId: () => string; trackModelUse?: ModelUseCountTracker }): void {\n    this.#getCurrentModeId = options.getCurrentModeId;\n    this.#trackModelUse = options.trackModelUse;\n  }\n\n  /** The currently-selected model id ('' when none selected yet). */\n  get(): string {\n    return this.#id;\n  }\n\n  /** Whether a model is currently selected. */\n  hasSelection(): boolean {\n    return this.#id !== '';\n  }\n\n  /**\n   * A short display name for the selected model: the last segment of the model\n   * id (e.g. `__GATEWAY_ANTHROPIC_MODEL_SONNET__` -> `claude-sonnet-4-6`). Returns\n   * `'unknown'` when no model is selected.\n   */\n  displayName(): string {\n    const modelId = this.#id;\n    if (!modelId || modelId === 'unknown') return modelId || 'unknown';\n    const parts = modelId.split('/');\n    return parts[parts.length - 1] || modelId;\n  }\n\n  /** Set the in-memory selected model id (no persistence). */\n  set({ modelId }: { modelId: string }): void {\n    this.#id = modelId;\n  }\n\n  /** Persist `modelId` as the last-used model for `modeId`. */\n  async saveForMode({ modeId, modelId }: { modeId: string; modelId: string }): Promise<void> {\n    await this.#store()?.set(modeModelKey(modeId), modelId);\n  }\n\n  /**\n   * Re-sync the in-memory selection from the persisted per-mode model.\n   *\n   * The persisted `modeModelId_<mode>` thread setting is the source of truth for\n   * \"which model this mode runs\". The in-memory {@link get} value is only a\n   * per-instance cache, so in multiplayer deployments (multiple processes or a\n   * fresh Session for an existing thread) it can drift from what another actor\n   * persisted. Calling this at run start reconciles the cache with storage.\n   *\n   * Only overrides when a persisted value exists (so brand-new threads keep\n   * their seeded/default selection) and only emits `model_changed` when the\n   * value actually changes (a no-op in the single-player TUI, where the cache\n   * and the persisted value are always written together).\n   */\n  async syncFromPersisted({ modeId }: { modeId: string }): Promise<void> {\n    const stored = (await this.#store()?.get(modeModelKey(modeId))) as string | undefined;\n    if (!stored || stored === this.#id) return;\n    this.#id = stored;\n    this.#bus.emit({ type: 'model_changed', modelId: stored, scope: 'thread', modeId });\n  }\n\n  /**\n   * Resolve the model for `modeId`: the persisted per-mode model if present,\n   * else `defaultModelId`, else null.\n   */\n  async resolveForMode({\n    modeId,\n    defaultModelId,\n  }: {\n    modeId: string;\n    defaultModelId?: string;\n  }): Promise<string | null> {\n    const stored = (await this.#store()?.get(modeModelKey(modeId))) as string | undefined;\n    if (stored) return stored;\n    return defaultModelId ?? null;\n  }\n\n  /**\n   * Switch to a different model at runtime.\n   *\n   * When `scope` is `'thread'` (the default), the model is persisted as the\n   * per-mode model for `modeId` so it's restored when switching back. The\n   * in-memory selection only updates when the target mode is the active mode.\n   * Reports the selection to the model-use tracker and emits `model_changed`.\n   */\n  async switch({\n    modelId,\n    scope = 'thread',\n    modeId,\n  }: {\n    modelId: string;\n    scope?: 'global' | 'thread';\n    modeId?: string;\n  }): Promise<void> {\n    const currentModeId = this.#getCurrentModeId?.() ?? '';\n    const targetModeId = modeId ?? currentModeId;\n\n    if (targetModeId === currentModeId) {\n      this.set({ modelId });\n    }\n\n    if (scope === 'thread') {\n      await this.saveForMode({ modeId: targetModeId, modelId });\n    }\n\n    try {\n      await Promise.resolve(this.#trackModelUse?.(modelId));\n    } catch (error) {\n      console.error('Failed to track model usage count', error);\n    }\n\n    this.#bus.emit({ type: 'model_changed', modelId, scope, modeId: targetModeId });\n  }\n}\n\n/**\n * Owns the session's currently-selected mode and the logic for switching modes.\n * Holds the active mode id and runs the version-guarded switch sequence —\n * persisting the selection and coordinating the per-mode model with\n * {@link SessionModel}. The AgentController still owns the mode *definitions*\n * (`config.modes`); this owns \"which mode is active\" and how a switch unfolds.\n */\nexport class SessionMode {\n  /** Id of the currently-selected mode. Empty until the AgentController resolves its default mode. */\n  #id = '';\n  /**\n   * Monotonically increasing counter bumped on each switch. A slower in-flight\n   * switch detects it was superseded by a newer one and bails.\n   */\n  #switchVersion = 0;\n  readonly #store: () => ThreadSettingsStore | undefined;\n  readonly #model: SessionModel;\n  /** This session's event bus; {@link switch} emits mode_changed / model_changed here. */\n  readonly #bus: SessionBus;\n  /**\n   * Resolves a mode id to its full definition. Injected by the AgentController via\n   * {@link setResolver}, since the mode *catalog* (`config.modes`) is host config.\n   */\n  #resolveMode: ((modeId: string) => AgentControllerMode | null) | undefined;\n  constructor(store: () => ThreadSettingsStore | undefined, model: SessionModel, bus: SessionBus) {\n    this.#store = store;\n    this.#model = model;\n    this.#bus = bus;\n  }\n\n  /**\n   * Attach the resolver that maps a mode id to its definition. The AgentController owns\n   * the mode catalog (`config.modes`) and injects this once.\n   */\n  setResolver(resolve: (modeId: string) => AgentControllerMode | null): void {\n    this.#resolveMode = resolve;\n  }\n\n  /** The currently-selected mode id. */\n  get(): string {\n    return this.#id;\n  }\n\n  /**\n   * Resolve the currently-selected mode id to its full definition against the\n   * host's mode catalog. Throws if the selected mode id isn't in the catalog.\n   */\n  resolve(): AgentControllerMode {\n    const mode = this.#resolveMode?.(this.#id) ?? null;\n    if (!mode) {\n      throw new Error(`Mode not found: ${this.#id}`);\n    }\n    return mode;\n  }\n\n  /** Set the currently-selected mode id (on default resolution or hydration). */\n  set({ modeId }: { modeId: string }): void {\n    this.#id = modeId;\n  }\n\n  /**\n   * Switch to a different mode.\n   *\n   * Emits `mode_changed`, then runs the version-guarded sequence: remember the\n   * outgoing mode's model, persist the new mode, then resolve and apply the\n   * incoming mode's model — emitting `model_changed` once applied. A newer\n   * switch starting mid-flight supersedes this one, which then bails before\n   * emitting `model_changed`.\n   */\n  async switch({ modeId }: { modeId: string }): Promise<void> {\n    const mode = this.#resolveMode?.(modeId) ?? null;\n    if (!mode) {\n      throw new Error(`Mode not found: ${modeId}`);\n    }\n\n    const previousModeId = this.#id;\n    const previousModelId = this.#model.get();\n    const version = ++this.#switchVersion;\n    this.#id = modeId;\n\n    // Emit the mode change immediately so UIs can update without waiting for\n    // the storage round-trips below.\n    this.#bus.emit({ type: 'mode_changed', modeId, previousModeId });\n\n    // Remember the outgoing mode's model before moving on.\n    if (previousModelId) {\n      await this.#model.saveForMode({ modeId: previousModeId, modelId: previousModelId });\n    }\n    if (this.#switchVersion !== version) return;\n\n    await this.#store()?.set(MODE_ID_KEY, modeId);\n    if (this.#switchVersion !== version) return;\n\n    const modelId = await this.#model.resolveForMode({ modeId, defaultModelId: mode.defaultModelId });\n    if (this.#switchVersion !== version) return;\n    if (modelId) {\n      this.#model.set({ modelId });\n      this.#bus.emit({ type: 'model_changed', modelId });\n    }\n  }\n}\n\n/** Per-role wiring + state/config keys a {@link SessionOMRole} reads and writes. */\ninterface SessionOMRoleConfig {\n  /** The event `role` and `om_model_changed` discriminator for this role. */\n  role: 'observer' | 'reflector';\n  /** Session-state / thread-settings key holding this role's model id. */\n  modelIdKey: 'observerModelId' | 'reflectorModelId';\n  /** Session-state key holding this role's threshold. */\n  thresholdKey: 'observationThreshold' | 'reflectionThreshold';\n  /** Resolve this role's default model id from `omConfig`. */\n  defaultModelId: (omConfig: AgentControllerOMConfig | undefined) => string | undefined;\n  /** Resolve this role's default threshold from `omConfig`. */\n  defaultThreshold: (omConfig: AgentControllerOMConfig | undefined) => number | undefined;\n}\n\n/**\n * One observational-memory role (observer or reflector): its model id, resolved\n * model instance, threshold, and model switch. Reads return the session-state\n * value when set, falling back to the AgentController's `omConfig` defaults. The shared\n * wiring is injected by {@link SessionOM.setResolver}.\n */\nclass SessionOMRole {\n  readonly #config: SessionOMRoleConfig;\n  readonly #bus: SessionBus;\n  #getState: (() => Record<string, unknown>) | undefined;\n  #setState: ((updates: Record<string, unknown>) => void) | undefined;\n  #setSetting: ((args: { key: string; value: unknown }) => Promise<void>) | undefined;\n  #omConfig: AgentControllerOMConfig | undefined;\n  #gateways: MastraModelGatewayInterface[] | undefined;\n\n  constructor(config: SessionOMRoleConfig, bus: SessionBus) {\n    this.#config = config;\n    this.#bus = bus;\n  }\n\n  /** @internal Injected by {@link SessionOM.setResolver}. */\n  setWiring(wiring: {\n    getState: () => Record<string, unknown>;\n    setState: (updates: Record<string, unknown>) => void;\n    setSetting: (args: { key: string; value: unknown }) => Promise<void>;\n    omConfig?: AgentControllerOMConfig;\n    gateways?: MastraModelGatewayInterface[];\n  }): void {\n    this.#getState = wiring.getState;\n    this.#setState = wiring.setState;\n    this.#setSetting = wiring.setSetting;\n    this.#omConfig = wiring.omConfig;\n    this.#gateways = wiring.gateways;\n  }\n\n  /** This role's model id from session state, falling back to `omConfig`. */\n  modelId(): string | undefined {\n    const fromState = this.#getState?.()[this.#config.modelIdKey];\n    return (typeof fromState === 'string' ? fromState : undefined) ?? this.#config.defaultModelId(this.#omConfig);\n  }\n\n  /** This role's threshold from session state, falling back to `omConfig`. */\n  threshold(): number | undefined {\n    const fromState = this.#getState?.()[this.#config.thresholdKey];\n    return (typeof fromState === 'number' ? fromState : undefined) ?? this.#config.defaultThreshold(this.#omConfig);\n  }\n\n  /**\n   * Resolve this role's model id to a model instance via the configured\n   * gateways, or undefined when unset. The bare model id string is routed\n   * through {@link ModelRouterLanguageModel}, which selects the matching\n   * gateway (or the built-in defaults) and resolves provider auth.\n   */\n  resolvedModel(): MastraModelConfig | undefined {\n    const modelId = this.modelId();\n    if (!modelId) return undefined;\n    return new ModelRouterLanguageModel(modelId as `${string}/${string}`, this.#gateways);\n  }\n\n  /** Switch this role's model: update session state, persist, and emit. */\n  async switchModel({ modelId }: { modelId: string }): Promise<void> {\n    this.#setState?.({ [this.#config.modelIdKey]: modelId });\n    await this.#setSetting?.({ key: this.#config.modelIdKey, value: modelId });\n    this.#bus.emit({ type: 'om_model_changed', role: this.#config.role, modelId });\n  }\n}\n\n/**\n * Owns the session's observational-memory model selection, grouped by role:\n * {@link SessionOM.observer} and {@link SessionOM.reflector}. The AgentController owns\n * `omConfig` and the model resolver, so it injects them — plus the session-state\n * read/write and thread-settings persistence — once via {@link setResolver},\n * which fans the wiring out to both roles.\n */\nclass SessionOM {\n  readonly observer: SessionOMRole;\n  readonly reflector: SessionOMRole;\n\n  constructor(bus: SessionBus) {\n    this.observer = new SessionOMRole(\n      {\n        role: 'observer',\n        modelIdKey: 'observerModelId',\n        thresholdKey: 'observationThreshold',\n        defaultModelId: omConfig => omConfig?.defaultObserverModelId,\n        defaultThreshold: omConfig => omConfig?.defaultObservationThreshold,\n      },\n      bus,\n    );\n    this.reflector = new SessionOMRole(\n      {\n        role: 'reflector',\n        modelIdKey: 'reflectorModelId',\n        thresholdKey: 'reflectionThreshold',\n        defaultModelId: omConfig => omConfig?.defaultReflectorModelId,\n        defaultThreshold: omConfig => omConfig?.defaultReflectionThreshold,\n      },\n      bus,\n    );\n  }\n\n  /**\n   * Attach the session-state read/write, thread-settings persistence, and the\n   * AgentController-owned `omConfig` defaults plus model resolver. The AgentController injects\n   * these once; the wiring is shared by both roles.\n   */\n  setResolver(options: {\n    getState: () => Record<string, unknown>;\n    setState: (updates: Record<string, unknown>) => void;\n    setSetting: (args: { key: string; value: unknown }) => Promise<void>;\n    omConfig?: AgentControllerOMConfig;\n    gateways?: MastraModelGatewayInterface[];\n  }): void {\n    this.observer.setWiring(options);\n    this.reflector.setWiring(options);\n  }\n}\n\n/**\n * Owns the session's tool-permission rules: the per-category and per-tool\n * approval policies persisted in session state under `permissionRules`. The\n * AgentController injects the session-state read/write once via {@link setResolver}.\n *\n * These are the persisted rules consulted during tool-approval resolution; they\n * are distinct from the in-memory \"allow for this session\" grants on the\n * Session.\n */\nclass SessionPermissions {\n  #getState: (() => Record<string, unknown>) | undefined;\n  #setState: ((updates: Record<string, unknown>) => Promise<void>) | undefined;\n\n  /** Attach the session-state read/write. The AgentController injects these once. */\n  setResolver(options: {\n    getState: () => Record<string, unknown>;\n    setState: (updates: Record<string, unknown>) => Promise<void>;\n  }): void {\n    this.#getState = options.getState;\n    this.#setState = options.setState;\n  }\n\n  /** The current permission rules, or empty rules when none are set. */\n  getRules(): PermissionRules {\n    const rules = this.#getState?.().permissionRules as PermissionRules | undefined;\n    return rules ?? { categories: {}, tools: {} };\n  }\n\n  /** Set the approval policy for a tool category. Resolves once persisted. */\n  setForCategory({ category, policy }: { category: ToolCategory; policy: PermissionPolicy }): Promise<void> {\n    const rules = this.getRules();\n    rules.categories[category] = policy;\n    return this.#setState?.({ permissionRules: rules }) ?? Promise.resolve();\n  }\n\n  /** Set the approval policy for an individual tool. Resolves once persisted. */\n  setForTool({ toolName, policy }: { toolName: string; policy: PermissionPolicy }): Promise<void> {\n    const rules = this.getRules();\n    rules.tools[toolName] = policy;\n    return this.#setState?.({ permissionRules: rules }) ?? Promise.resolve();\n  }\n}\n\n/**\n * How long a message submitted right after an abort waits for the aborted run\n * to finish tearing down before it is dispatched anyway. Real teardown includes\n * stream cancellation and every output processor; a few seconds is normal.\n */\nconst POST_ABORT_TEARDOWN_TIMEOUT_MS = 30_000;\n\n/** Stamp at submit time: a steer aborts its own run, so the route resolved downstream reads idle. */\nfunction asInterjection(signal: CreatedAgentSignal): CreatedAgentSignal {\n  if (signal.type !== 'user' || signal.attributes?.delivery !== undefined) return signal;\n  return resolveDeliveryAttributes(signal, { delivery: 'while-active' });\n}\n\n/** The session-state / thread-settings key holding a subagent model id. */\nfunction subagentModelKey(agentType?: string): string {\n  return agentType ? `subagentModelId_${agentType}` : 'subagentModelId';\n}\n\n/**\n * The subagent model selection. Reads prefer the per-`agentType` value and fall\n * back to the global subagent model; writes persist to thread settings and emit\n * a `subagent_model_changed` event. Wiring is injected by\n * {@link SessionSubagents.setResolver}.\n */\nclass SessionSubagentModel {\n  readonly #bus: SessionBus;\n  #getState: (() => Record<string, unknown>) | undefined;\n  #setState: ((updates: Record<string, unknown>) => void) | undefined;\n  #setSetting: ((args: { key: string; value: unknown }) => Promise<void>) | undefined;\n\n  constructor(bus: SessionBus) {\n    this.#bus = bus;\n  }\n\n  /** @internal Injected by {@link SessionSubagents.setResolver}. */\n  setWiring(wiring: {\n    getState: () => Record<string, unknown>;\n    setState: (updates: Record<string, unknown>) => void;\n    setSetting: (args: { key: string; value: unknown }) => Promise<void>;\n  }): void {\n    this.#getState = wiring.getState;\n    this.#setState = wiring.setState;\n    this.#setSetting = wiring.setSetting;\n  }\n\n  /**\n   * The subagent model id, preferring the `agentType`-specific value when one is\n   * given, then the global subagent model, or `null` when neither is set.\n   */\n  get({ agentType }: { agentType?: string } = {}): string | null {\n    const state = this.#getState?.() ?? {};\n    if (agentType) {\n      const perType = state[subagentModelKey(agentType)];\n      if (typeof perType === 'string') return perType;\n    }\n    const global = state.subagentModelId;\n    return typeof global === 'string' ? global : null;\n  }\n\n  /**\n   * Set the subagent model id (per-`agentType` when given, otherwise global).\n   * Persists to thread settings and emits `subagent_model_changed`.\n   */\n  async set({ modelId, agentType }: { modelId: string; agentType?: string }): Promise<void> {\n    const key = subagentModelKey(agentType);\n    this.#setState?.({ [key]: modelId });\n    await this.#setSetting?.({ key, value: modelId });\n    this.#bus.emit({ type: 'subagent_model_changed', modelId, scope: 'thread', agentType });\n  }\n}\n\n/**\n * The session's subagent configuration. Currently exposes the subagent model\n * selection under {@link SessionSubagents.model}; grouped under `subagents` to\n * leave room for additional subagent settings. The AgentController injects the\n * session-state read/write, thread-settings persistence, and event emitter once\n * via {@link setResolver}.\n */\nclass SessionSubagents {\n  readonly model: SessionSubagentModel;\n\n  constructor(bus: SessionBus) {\n    this.model = new SessionSubagentModel(bus);\n  }\n\n  /**\n   * Attach the session-state read/write and thread-settings persistence. The\n   * AgentController injects these once.\n   */\n  setResolver(options: {\n    getState: () => Record<string, unknown>;\n    setState: (updates: Record<string, unknown>) => void;\n    setSetting: (args: { key: string; value: unknown }) => Promise<void>;\n  }): void {\n    this.model.setWiring(options);\n  }\n}\n\ntype SessionStateUpdater<TState, TResult> = AgentControllerRequestStateUpdater<TState, TResult>;\n\ninterface SessionStateOptions<TState> {\n  initialState?: Partial<TState>;\n  stateSchema?: PublicSchema<TState, any>;\n}\n\n/**\n * Owns the live AgentController state for a single Session.\n *\n * Reads return shallow snapshots, writes are serialized through a promise queue,\n * and validated updates emit the same `state_changed` event the AgentController used to\n * emit when it owned state directly.\n */\ntype PersistSettingFn = (args: { key: string; value: unknown }) => Promise<void>;\n\nclass SessionState<TState = unknown> {\n  #state: TState;\n  #updateQueue: Promise<void> = Promise.resolve();\n  readonly #schema: StandardSchemaWithJSON | undefined;\n  readonly #bus: SessionBus;\n  readonly #capturePersistSetting: (() => PersistSettingFn | undefined) | undefined;\n\n  constructor(\n    { initialState, stateSchema }: SessionStateOptions<TState>,\n    bus: SessionBus,\n    capturePersistSetting?: () => PersistSettingFn | undefined,\n  ) {\n    this.#schema = stateSchema ? toStandardSchema(stateSchema) : undefined;\n    this.#state = {\n      ...this.getSchemaDefaults(),\n      ...(initialState as Record<string, unknown> | undefined),\n    } as TState;\n    this.#bus = bus;\n    this.#capturePersistSetting = capturePersistSetting;\n  }\n\n  get(): Readonly<TState> {\n    return { ...(this.#state as Record<string, unknown>) } as TState;\n  }\n\n  private getSchemaDefaults(): Partial<TState> {\n    if (!this.#schema) return {};\n\n    const defaults: Record<string, unknown> = {};\n\n    try {\n      // Extract defaults from the JSON Schema representation.\n      const jsonSchema = this.#schema['~standard'].jsonSchema.output({ target: 'draft-07' }) as {\n        properties?: Record<string, { default?: unknown }>;\n      };\n      if (jsonSchema?.properties) {\n        for (const [key, prop] of Object.entries(jsonSchema.properties)) {\n          if (prop.default !== undefined) {\n            defaults[key] = prop.default;\n          }\n        }\n      }\n    } catch {\n      // Schema doesn't support JSON Schema extraction — skip defaults.\n    }\n\n    return defaults as Partial<TState>;\n  }\n\n  private async apply(\n    updates: Partial<TState>,\n    persistSetting?: PersistSettingFn,\n    shouldApply?: () => boolean,\n  ): Promise<boolean> {\n    const changedKeys = Object.keys(updates as Record<string, unknown>);\n    const newState = { ...(this.#state as Record<string, unknown>), ...(updates as Record<string, unknown>) };\n    let validatedState: TState;\n\n    if (this.#schema) {\n      const result = await this.#schema['~standard'].validate(newState);\n      if (result.issues) {\n        const messages = result.issues.map(i => i.message).join('; ');\n        throw new Error(`Invalid state update: ${messages}`);\n      }\n      validatedState = result.value as TState;\n    } else {\n      validatedState = newState as TState;\n    }\n\n    // Re-check after async schema validation, immediately before mutating the\n    // live session. Callers use this to prevent a queued update from crossing\n    // a session/thread ownership boundary while validation was in flight.\n    if (shouldApply && !shouldApply()) return false;\n    this.#state = validatedState;\n\n    this.#bus.emit({ type: 'state_changed', state: this.get() as Record<string, unknown>, changedKeys });\n\n    // Mirror restart-surviving preferences into thread metadata so they can be\n    // restored by `Session.loadMetadata()` after the host process restarts.\n    // Persistence failures never fail the in-memory state update.\n    if (persistSetting) {\n      const state = this.#state as Record<string, unknown>;\n      for (const key of PERSISTED_STATE_KEYS) {\n        if (!changedKeys.includes(key)) continue;\n        try {\n          await persistSetting({ key, value: state[key] });\n        } catch {\n          // Storage unavailable or write failed — keep the in-memory update.\n        }\n      }\n    }\n    return true;\n  }\n\n  set(updates: Partial<TState>): Promise<void> {\n    const updateSnapshot = { ...(updates as Record<string, unknown>) } as Partial<TState>;\n    // Captured now, not at apply time: an update queued behind a thread switch\n    // must persist to the thread that was active when the update was requested.\n    const persistSetting = this.#capturePersistSetting?.();\n    const run = this.#updateQueue.then(async () => {\n      await this.apply(updateSnapshot, persistSetting);\n    });\n    this.#updateQueue = run.then(\n      () => undefined,\n      () => undefined,\n    );\n    return run;\n  }\n\n  /** Apply an update only while a caller-owned identity still matches. */\n  setIf(updates: Partial<TState>, shouldApply: () => boolean): Promise<boolean> {\n    const updateSnapshot = { ...(updates as Record<string, unknown>) } as Partial<TState>;\n    const persistSetting = this.#capturePersistSetting?.();\n    const run = this.#updateQueue.then(() => this.apply(updateSnapshot, persistSetting, shouldApply));\n    this.#updateQueue = run.then(\n      () => undefined,\n      () => undefined,\n    );\n    return run;\n  }\n\n  update<TResult>(updater: SessionStateUpdater<TState, TResult>): Promise<TResult> {\n    const persistSetting = this.#capturePersistSetting?.();\n    const run = this.#updateQueue.then(async () => {\n      const update = await updater(this.get());\n      if (update.updates && Object.keys(update.updates as Record<string, unknown>).length > 0) {\n        await this.apply(update.updates, persistSetting);\n      }\n      for (const event of update.events ?? []) {\n        this.#bus.emit(event);\n      }\n      return update.result;\n    });\n\n    this.#updateQueue = run.then(\n      () => undefined,\n      () => undefined,\n    );\n    return run;\n  }\n}\n\n/**\n * A AgentController session owns the per-conversation runtime state that today lives\n * flattened on the {@link AgentController} instance. This class is the seam we extract\n * that state into, one concern at a time, so the AgentController can eventually own a\n * `Session` rather than the state itself.\n *\n * Currently owns:\n * - the live AgentController state (`session.state`): schema-validated snapshots and\n *   serialized updates that emit `state_changed`.\n * - session-scoped permission grants — the \"allow for this session\" approvals a\n *   user makes when a tool or tool category is gated behind the permission check.\n * - the live token-usage counter for the active thread. The Session holds the\n *   in-memory running tally; the AgentController remains responsible for persisting it\n *   to (and hydrating it from) thread metadata, because usage is thread-scoped.\n * - the currently-selected mode (`session.mode`) and model (`session.model`).\n *   The Session is the source of truth for which mode/model is active and owns\n *   the mode-switch sequence and per-mode model memory. The AgentController still owns\n *   the mode *definitions* (`config.modes`).\n * - transient run identity and abort control (`session.run`): the current run\n *   id, trace id, monotonic operation counter, and the AbortController/\n *   abort-requested flag. This is per-run scratch state and is never persisted.\n * - the live agent thread subscription (`session.stream`): the open\n *   subscription to the active thread's event stream and its dedup key. The\n *   AgentController still produces the subscription (calling the agent) and consumes its\n *   stream; the Session owns the handle and its lifecycle.\n * - the parked tool suspensions (`session.suspensions`): tool calls paused via\n *   the native tool-suspension primitive awaiting a resume, keyed by toolCallId.\n *   The Session owns the resume data; the AgentController keeps the richer per-suspension\n *   UI snapshot on its display state.\n * - follow-up queue observation: a subscription to the Agent-owned FIFO for\n *   the active resource/thread. The Agent runtime schedules messages; the\n *   Session renders its current shared `queuedFollowUps` count. * - the interactive tool-approval gate (`session.approval`): when a tool needs\n *   user approval, the run parks on a promise here until the UI responds. The\n *   Session owns the gate; the AgentController maps the decision to its effects (run vs\n *   decline, any \"always allow\" grant), which touch config-derived categories.\n *\n * It also exposes a couple of accessors that compose `run` and `stream`:\n * {@link getCurrentRunId} (the active run id, preferring the live subscription)\n * and {@link abortRun} (abort the live run and mark it aborting).\n *\n * Mode/model persistence is thread-scoped, so the Session writes through a\n * {@link ThreadSettingsStore} the AgentController backs with thread metadata; when no\n * storage is configured the store is absent and state stays in memory.\n */\n/**\n * Owns the session's canonical display state — the projection a UI renders from\n * instead of folding raw events itself. The Session holds the snapshot and the\n * reducer ({@link apply}) that keeps it in sync with every AgentController event; the\n * AgentController still owns the event bus and dispatches `display_state_changed` to\n * listeners after applying.\n *\n * The reducer needs a few read-only host/session facts it doesn't own: the live\n * token-usage tally, a subagent display-name lookup (AgentController config), and the\n * active thread id (to decide whether a `thread_deleted` clears the view). Those\n * are injected at construction so the reducer stays self-contained.\n */\nexport class SessionDisplayState {\n  #state: AgentControllerDisplayState = defaultDisplayState();\n\n  constructor(\n    private readonly deps: {\n      /** The session's live token-usage tally, mirrored into the view on usage/thread events. */\n      getTokenUsage: () => TokenUsage;\n      /** Resolve a subagent's display name from AgentController config, or undefined when unnamed. */\n      getSubagentDisplayName: (agentType: string) => string | undefined;\n      /** The active thread id, used to gate `thread_deleted` resets. */\n      getThreadId: () => string | null;\n      /** Clear the session's follow-up queue when thread-scoped display state resets. */\n      clearFollowUps: () => void;\n    },\n  ) {}\n\n  /**\n   * A read-only snapshot of the canonical display state. UIs should render from\n   * this instead of building state up from raw events.\n   */\n  get(): Readonly<AgentControllerDisplayState> {\n    return this.#state;\n  }\n\n  /**\n   * Drop the display mirror of every parked tool suspension. Used on abort,\n   * which abandons the run's parked suspensions; the caller dispatches\n   * `display_state_changed`.\n   */\n  clearPendingSuspensions(): void {\n    this.#state.pendingSuspensions.clear();\n  }\n\n  /**\n   * Clear the modified-files tally without touching the rest of the snapshot.\n   * Used after a clone, which starts the cloned thread with a clean working set\n   * while the surrounding UI reset handles tasks/tools explicitly.\n   */\n  clearModifiedFiles(): void {\n    this.#state.modifiedFiles.clear();\n  }\n\n  /**\n   * Drop the display mirror of a single parked tool suspension once it has been\n   * resumed, so the UI stops rendering only the resolved prompt while any other\n   * parked suspensions stay visible.\n   */\n  deletePendingSuspension(toolCallId: string): void {\n    this.#state.pendingSuspensions.delete(toolCallId);\n  }\n\n  /**\n   * Restore task display state after a UI replays persisted task-tool history.\n   * Updates the snapshot without emitting a live `task_updated` event, since no\n   * task tool just ran. The caller dispatches `display_state_changed`.\n   */\n  restoreTasks(tasks: TaskItemSnapshot[]): void {\n    this.#state.previousTasks = [...this.#state.tasks];\n    this.#state.tasks = [...tasks];\n  }\n\n  /**\n   * Reset display fields scoped to a thread. Called on thread switch/creation.\n   * Also clears the session's follow-up queue (mirrored by `queuedFollowUps`).\n   */\n  resetThread(): void {\n    const ds = this.#state;\n    ds.activeTools = new Map();\n    ds.toolInputBuffers = new Map();\n    ds.pendingApproval = null;\n    ds.pendingSuspensions = new Map();\n    ds.activeSubagents = new Map();\n    ds.currentMessage = null;\n    this.deps.clearFollowUps();\n    ds.queuedFollowUps = 0;\n    ds.modifiedFiles = new Map();\n    ds.tasks = [];\n    ds.previousTasks = [];\n    ds.omProgress = defaultOMProgressState();\n    ds.bufferingMessages = false;\n    ds.bufferingObservations = false;\n  }\n\n  /**\n   * Apply a display-state update based on an incoming event. The centralized\n   * state machine that keeps {@link AgentControllerDisplayState} in sync with every\n   * event the AgentController emits.\n   */\n  apply(event: AgentControllerEvent): void {\n    const ds = this.#state;\n\n    switch (event.type) {\n      // ── Agent lifecycle ────────────────────────────────────────────────\n      case 'agent_start':\n        ds.isRunning = true;\n        ds.activeTools = new Map();\n        ds.toolInputBuffers = new Map();\n        ds.currentMessage = null;\n        ds.pendingApproval = null;\n        // Parked tool suspensions are intentionally NOT cleared here: resuming\n        // one parked tool restarts the run (a fresh agent_start) and the other\n        // parallel prompts must stay rendered until they are resolved.\n        break;\n\n      case 'agent_end':\n        ds.isRunning = false;\n        ds.pendingApproval = null;\n        // A suspended run keeps its pending tool suspensions alive so the UI can\n        // still render the prompts (e.g. `ask_user`, which pauses via the native\n        // tool-suspension primitive). When the run ends for any other reason the\n        // parked suspensions are abandoned, so clear them all.\n        if (event.reason !== 'suspended') {\n          ds.pendingSuspensions.clear();\n        }\n        // Mark any still-running tools as errored (handles abort mid-run)\n        for (const [, tool] of ds.activeTools) {\n          if (tool.status === 'running' || tool.status === 'streaming_input') {\n            tool.status = 'error';\n          }\n        }\n        ds.activeSubagents = new Map();\n        break;\n\n      // ── Message streaming ──────────────────────────────────────────────\n      case 'message_start':\n        // The run engine keeps the source message mutable while it folds stream\n        // chunks. Display state applies compact deltas independently, so isolate\n        // text parts once here rather than appending each delta twice.\n        ds.currentMessage = {\n          ...event.message,\n          content: {\n            ...event.message.content,\n            parts: event.message.content.parts.map(part => (part.type === 'text' ? { ...part } : part)),\n          },\n        };\n        break;\n\n      case 'message_update': {\n        if (ds.currentMessage?.id !== event.id) break;\n\n        const parts = [...ds.currentMessage.content.parts];\n        if (event.event.type === 'text-delta') {\n          const textIndex = parts.findLastIndex(part => part.type === 'text');\n          const textPart = parts[textIndex];\n          if (textPart?.type === 'text') {\n            parts[textIndex] = { ...textPart, text: textPart.text + event.event.delta };\n          } else {\n            parts.push({ type: 'text', text: event.event.delta });\n          }\n        } else if (event.event.type === 'reasoning-delta') {\n          const reasoningPart = parts[event.event.index];\n          if (reasoningPart?.type === 'reasoning') {\n            const reasoning = reasoningPart.reasoning + event.event.delta;\n            parts[event.event.index] = { ...reasoningPart, reasoning, details: [{ type: 'text', text: reasoning }] };\n          }\n        } else {\n          parts[event.event.index] = structuredClone(event.event.part);\n        }\n\n        ds.currentMessage = {\n          ...ds.currentMessage,\n          content: { ...ds.currentMessage.content, parts },\n        };\n        break;\n      }\n\n      case 'message_end':\n        break;\n\n      // ── Tool lifecycle ─────────────────────────────────────────────────\n      case 'tool_input_start': {\n        ds.toolInputBuffers.set(event.toolCallId, { text: '', toolName: event.toolName });\n        const existing = ds.activeTools.get(event.toolCallId);\n        if (existing) {\n          existing.status = 'streaming_input';\n        } else {\n          ds.activeTools.set(event.toolCallId, {\n            name: event.toolName,\n            args: {},\n            status: 'streaming_input',\n          });\n        }\n        break;\n      }\n\n      case 'tool_input_delta': {\n        const buf = ds.toolInputBuffers.get(event.toolCallId);\n        if (buf && typeof event.argsTextDelta === 'string') {\n          buf.text += event.argsTextDelta;\n        }\n        break;\n      }\n\n      case 'tool_input_end':\n        ds.toolInputBuffers.delete(event.toolCallId);\n        break;\n\n      case 'tool_start': {\n        const existingTool = ds.activeTools.get(event.toolCallId);\n        if (existingTool) {\n          existingTool.name = event.toolName;\n          existingTool.args = event.args;\n          existingTool.status = 'running';\n        } else {\n          ds.activeTools.set(event.toolCallId, {\n            name: event.toolName,\n            args: event.args,\n            status: 'running',\n          });\n        }\n        break;\n      }\n\n      case 'tool_update': {\n        const tool = ds.activeTools.get(event.toolCallId);\n        if (tool) {\n          tool.partialResult =\n            typeof event.partialResult === 'string' ? event.partialResult : safeStringify(event.partialResult);\n        }\n        break;\n      }\n\n      case 'tool_end': {\n        const endedTool = ds.activeTools.get(event.toolCallId);\n        if (endedTool) {\n          endedTool.status = event.isError ? 'error' : 'completed';\n          endedTool.result = event.result;\n          endedTool.isError = event.isError;\n        }\n        // Track file modifications\n        if (!event.isError) {\n          const FILE_TOOLS = ['string_replace_lsp', 'write_file', 'ast_smart_edit'];\n          const toolState = ds.activeTools.get(event.toolCallId);\n          if (toolState && FILE_TOOLS.includes(toolState.name)) {\n            const toolArgs = toolState.args as Record<string, unknown>;\n            const filePath = toolArgs?.path as string;\n            if (filePath) {\n              const existing = ds.modifiedFiles.get(filePath);\n              if (existing) {\n                existing.operations.push(toolState.name);\n              } else {\n                ds.modifiedFiles.set(filePath, {\n                  operations: [toolState.name],\n                  firstModified: new Date(),\n                });\n              }\n            }\n          }\n        }\n        break;\n      }\n\n      case 'shell_output': {\n        const shellTool = ds.activeTools.get(event.toolCallId);\n        if (shellTool) {\n          shellTool.shellOutput = (shellTool.shellOutput ?? '') + event.output;\n        }\n        break;\n      }\n\n      case 'tool_approval_required':\n        ds.pendingApproval = {\n          toolCallId: event.toolCallId,\n          toolName: event.toolName,\n          args: event.args,\n        };\n        break;\n\n      case 'tool_suspended':\n        ds.pendingSuspensions.set(event.toolCallId, {\n          toolCallId: event.toolCallId,\n          toolName: event.toolName,\n          args: event.args,\n          suspendPayload: event.suspendPayload,\n          resumeSchema: event.resumeSchema,\n        });\n        break;\n\n      case 'tool_suspension_cancelled':\n        ds.pendingSuspensions.delete(event.toolCallId);\n        break;\n\n      // ── Subagent tracking ──────────────────────────────────────────────\n      case 'subagent_start': {\n        const displayName = this.deps.getSubagentDisplayName(event.agentType);\n        ds.activeSubagents.set(event.toolCallId, {\n          agentType: event.agentType,\n          ...(displayName !== undefined ? { displayName } : {}),\n          task: event.task,\n          modelId: event.modelId,\n          forked: event.forked,\n          toolCalls: [],\n          textDelta: '',\n          status: 'running',\n        });\n        break;\n      }\n\n      case 'subagent_text_delta': {\n        const sub = ds.activeSubagents.get(event.toolCallId);\n        if (sub) {\n          sub.textDelta += event.textDelta;\n        }\n        break;\n      }\n\n      case 'subagent_tool_start': {\n        const subAgent = ds.activeSubagents.get(event.toolCallId);\n        if (subAgent) {\n          subAgent.toolCalls.push({ name: event.subToolName, isError: false });\n        }\n        break;\n      }\n\n      case 'subagent_tool_end': {\n        const subTool = ds.activeSubagents.get(event.toolCallId);\n        if (subTool) {\n          const tc = subTool.toolCalls.find(t => t.name === event.subToolName && !t.isError);\n          if (tc) {\n            tc.isError = event.isError;\n          }\n        }\n        break;\n      }\n\n      case 'subagent_end': {\n        const endedSub = ds.activeSubagents.get(event.toolCallId);\n        if (endedSub) {\n          endedSub.status = event.isError ? 'error' : 'completed';\n          endedSub.durationMs = event.durationMs;\n          endedSub.result = event.result;\n        }\n        break;\n      }\n\n      // ── Observational Memory ───────────────────────────────────────────\n      case 'om_status': {\n        const w = event.windows;\n        ds.omProgress.pendingTokens = w.active.messages.tokens;\n        ds.omProgress.threshold = w.active.messages.threshold;\n        ds.omProgress.thresholdPercent =\n          w.active.messages.threshold > 0 ? (w.active.messages.tokens / w.active.messages.threshold) * 100 : 0;\n        ds.omProgress.observationTokens = w.active.observations.tokens;\n        ds.omProgress.reflectionThreshold = w.active.observations.threshold;\n        ds.omProgress.reflectionThresholdPercent =\n          w.active.observations.threshold > 0\n            ? (w.active.observations.tokens / w.active.observations.threshold) * 100\n            : 0;\n        ds.omProgress.buffered = {\n          observations: { ...w.buffered.observations },\n          reflection: { ...w.buffered.reflection },\n        };\n        ds.omProgress.generationCount = event.generationCount;\n        ds.omProgress.stepNumber = event.stepNumber;\n        // Drive buffering animation flags from status fields\n        ds.bufferingMessages = w.buffered.observations.status === 'running';\n        ds.bufferingObservations = w.buffered.reflection.status === 'running';\n        break;\n      }\n\n      case 'om_observation_start':\n        ds.omProgress.status = 'observing';\n        ds.omProgress.cycleId = event.cycleId;\n        ds.omProgress.startTime = Date.now();\n        break;\n\n      case 'om_observation_end':\n        ds.omProgress.status = 'idle';\n        ds.omProgress.cycleId = undefined;\n        ds.omProgress.startTime = undefined;\n        ds.omProgress.observationTokens = event.observationTokens;\n        // Messages have been observed — reset pending tokens\n        ds.omProgress.pendingTokens = 0;\n        ds.omProgress.thresholdPercent = 0;\n        break;\n\n      case 'om_observation_failed':\n        ds.omProgress.status = 'idle';\n        ds.omProgress.cycleId = undefined;\n        ds.omProgress.startTime = undefined;\n        break;\n\n      case 'om_reflection_start':\n        ds.omProgress.status = 'reflecting';\n        ds.omProgress.cycleId = event.cycleId;\n        ds.omProgress.startTime = Date.now();\n        ds.omProgress.preReflectionTokens = ds.omProgress.observationTokens;\n        ds.omProgress.observationTokens = event.tokensToReflect;\n        ds.omProgress.reflectionThresholdPercent =\n          ds.omProgress.reflectionThreshold > 0 ? (event.tokensToReflect / ds.omProgress.reflectionThreshold) * 100 : 0;\n        break;\n\n      case 'om_reflection_end':\n        ds.omProgress.status = 'idle';\n        ds.omProgress.cycleId = undefined;\n        ds.omProgress.startTime = undefined;\n        ds.omProgress.observationTokens = event.compressedTokens;\n        ds.omProgress.reflectionThresholdPercent =\n          ds.omProgress.reflectionThreshold > 0\n            ? (event.compressedTokens / ds.omProgress.reflectionThreshold) * 100\n            : 0;\n        break;\n\n      case 'om_reflection_failed':\n        ds.omProgress.status = 'idle';\n        ds.omProgress.cycleId = undefined;\n        ds.omProgress.startTime = undefined;\n        break;\n\n      case 'om_buffering_start':\n        if (event.operationType === 'observation') {\n          ds.bufferingMessages = true;\n        } else {\n          ds.bufferingObservations = true;\n        }\n        break;\n\n      case 'om_buffering_end':\n        if (event.operationType === 'observation') {\n          ds.bufferingMessages = false;\n        } else {\n          ds.bufferingObservations = false;\n        }\n        break;\n\n      case 'om_buffering_failed':\n        if (event.operationType === 'observation') {\n          ds.bufferingMessages = false;\n        } else {\n          ds.bufferingObservations = false;\n        }\n        break;\n\n      case 'om_activation':\n        if (event.operationType === 'observation') {\n          ds.bufferingMessages = false;\n        } else {\n          ds.bufferingObservations = false;\n        }\n        break;\n\n      // ── Token usage ────────────────────────────────────────────────────\n      case 'usage_update':\n        ds.tokenUsage = this.deps.getTokenUsage();\n        break;\n\n      // ── Tasks ──────────────────────────────────────────────────────────\n      case 'task_updated':\n        ds.previousTasks = [...ds.tasks];\n        ds.tasks = event.tasks;\n        break;\n\n      // ── Follow-up queue ────────────────────────────────────────────────\n      case 'follow_up_queued':\n        ds.queuedFollowUps = event.count;\n        break;\n\n      // ── Thread lifecycle ───────────────────────────────────────────────\n      case 'thread_changed':\n        this.resetThread();\n        ds.tokenUsage = this.deps.getTokenUsage();\n        break;\n\n      case 'thread_created':\n        this.resetThread();\n        ds.tokenUsage = createEmptyTokenUsage();\n        break;\n\n      case 'thread_deleted':\n        if (!this.deps.getThreadId()) {\n          this.resetThread();\n          ds.tokenUsage = createEmptyTokenUsage();\n        }\n        break;\n\n      // ── State changes (for OM threshold overrides) ──────────────────────\n      case 'state_changed': {\n        const keys = event.changedKeys;\n        if (keys.includes('observationThreshold')) {\n          const value = (event.state as Record<string, unknown>).observationThreshold;\n          if (typeof value === 'number') {\n            ds.omProgress.threshold = value;\n            ds.omProgress.thresholdPercent = value > 0 ? (ds.omProgress.pendingTokens / value) * 100 : 0;\n          }\n        }\n        if (keys.includes('reflectionThreshold')) {\n          const value = (event.state as Record<string, unknown>).reflectionThreshold;\n          if (typeof value === 'number') {\n            ds.omProgress.reflectionThreshold = value;\n            ds.omProgress.reflectionThresholdPercent = value > 0 ? (ds.omProgress.observationTokens / value) * 100 : 0;\n          }\n        }\n        break;\n      }\n\n      default:\n        break;\n    }\n  }\n}\n\n/**\n * A session's event bus. Owns the listener list and the full emit pipeline:\n * fold the event into the canonical display state, dispatch to this session's\n * listeners, then fan out a synthetic `display_state_changed`. Each session\n * has its own bus, so events never cross between sessions. Subsystems hold a\n * reference to their session's bus and call {@link emit} directly.\n */\n/**\n * Event types emitted once per streamed chunk. Their display-state snapshots are\n * coalesced, since a snapshot always carries the full state and intermediate\n * ones are immediately superseded.\n */\nconst COALESCIBLE_DISPLAY_STATE_EVENTS = new Set<AgentControllerEvent['type']>(['message_update', 'tool_input_delta']);\n\n/** Upper bound on coalesced display-state snapshots: one per this many ms, plus a leading one. */\nconst DISPLAY_STATE_COALESCE_MS = 16;\n\nexport class SessionBus {\n  readonly #listeners: AgentControllerEventListener[] = [];\n  #displayState: SessionDisplayState | undefined;\n  /** Timer for the trailing snapshot of the current coalescing window. */\n  #displayStateTimer: ReturnType<typeof setTimeout> | undefined;\n  /** Whether a snapshot was withheld during the current window and still owes a dispatch. */\n  #displayStatePending = false;\n  /**\n   * The last workspace lifecycle event group emitted on this bus, replayed to\n   * subscribers that attach after the status changed so they receive the current\n   * workspace ready or error state.\n   */\n  #lastWorkspaceEvents: AgentControllerEvent[] = [];\n\n  /** Attach the display-state reducer the bus folds events into. Set once by the Session. */\n  setDisplayState(displayState: SessionDisplayState): void {\n    this.#displayState = displayState;\n  }\n\n  subscribe(listener: AgentControllerEventListener): () => void {\n    // Replay buffered workspace lifecycle events so late subscribers learn the\n    // current workspace status regardless of when initialization occurs.\n    for (const event of this.#lastWorkspaceEvents) {\n      try {\n        const result = listener(event);\n        if (result && typeof result === 'object' && 'catch' in result) {\n          (result as Promise<void>).catch(err => console.error('Error in session event listener:', err));\n        }\n      } catch (err) {\n        console.error('Error in session event listener:', err);\n      }\n    }\n    this.#listeners.push(listener);\n    return () => {\n      const index = this.#listeners.indexOf(listener);\n      if (index !== -1) {\n        this.#listeners.splice(index, 1);\n      }\n    };\n  }\n\n  /** Whether anything is currently listening. Lets emitters skip snapshot work nobody reads. */\n  hasListeners(): boolean {\n    return this.#listeners.length > 0;\n  }\n\n  emit(event: AgentControllerEvent): void {\n    if (\n      event.type === 'workspace_status_changed' ||\n      event.type === 'workspace_ready' ||\n      event.type === 'workspace_error'\n    ) {\n      if (event.type === 'workspace_status_changed') {\n        this.#lastWorkspaceEvents = [event];\n      } else {\n        this.#lastWorkspaceEvents.push(event);\n      }\n    }\n    this.#displayState?.apply(event);\n\n    // A pending snapshot describes state that predates this event, so it must\n    // reach listeners before the event itself does. Flushing here also means a\n    // coalesced snapshot can never arrive after the event that superseded it.\n    if (!COALESCIBLE_DISPLAY_STATE_EVENTS.has(event.type)) {\n      this.#flushDisplayState();\n    }\n\n    this.#dispatch(event);\n\n    if (event.type === 'display_state_changed' || !this.#displayState) return;\n\n    if (COALESCIBLE_DISPLAY_STATE_EVENTS.has(event.type)) {\n      this.#scheduleDisplayState();\n      return;\n    }\n    this.#dispatch({ type: 'display_state_changed', displayState: this.#displayState.get() });\n  }\n\n  /**\n   * Queue a display-state snapshot for a high-frequency event. Streaming a\n   * single message emits thousands of deltas, and dispatching a full snapshot\n   * per delta re-serializes the whole message (plus every completed tool's args\n   * and result) on each one. Snapshots are state-of-the-world rather than\n   * incremental, so dropping intermediate ones loses nothing: the trailing\n   * flush carries the latest state.\n   *\n   * The first delta of a burst dispatches immediately so UIs stay responsive;\n   * the rest collapse into one trailing snapshot per interval.\n   */\n  #scheduleDisplayState(): void {\n    if (this.#displayStateTimer) {\n      this.#displayStatePending = true;\n      return;\n    }\n    this.#dispatch({ type: 'display_state_changed', displayState: this.#displayState!.get() });\n    this.#displayStateTimer = setTimeout(() => {\n      this.#displayStateTimer = undefined;\n      this.#flushDisplayState();\n    }, DISPLAY_STATE_COALESCE_MS);\n    // Never hold the process open for a snapshot that only mirrors state.\n    (this.#displayStateTimer as { unref?: () => void }).unref?.();\n  }\n\n  /** Dispatch any snapshot withheld by coalescing and clear the pending timer. */\n  #flushDisplayState(): void {\n    if (this.#displayStateTimer) {\n      clearTimeout(this.#displayStateTimer);\n      this.#displayStateTimer = undefined;\n    }\n    if (!this.#displayStatePending) return;\n    this.#displayStatePending = false;\n    if (this.#displayState) {\n      this.#dispatch({ type: 'display_state_changed', displayState: this.#displayState.get() });\n    }\n  }\n\n  #dispatch(event: AgentControllerEvent): void {\n    for (const listener of [...this.#listeners]) {\n      try {\n        const result = listener(event);\n        if (result && typeof result === 'object' && 'catch' in result) {\n          (result as Promise<void>).catch(err => console.error('Error in session event listener:', err));\n        }\n      } catch (err) {\n        console.error('Error in session event listener:', err);\n      }\n    }\n  }\n}\n\nexport class Session<TState = unknown> {\n  /** This session's event bus. Constructed first so every subsystem can route its events here. */\n  readonly #bus = new SessionBus();\n  /** Process-local hooks that must finish before the session exposes a terminal agent event. */\n  readonly #beforeAgentEndListeners = new Set<SessionBeforeAgentEndListener>();\n  /** Tool categories the user has granted \"allow\" for the lifetime of this session. */\n  readonly #grantedCategories = new Set<string>();\n  /** Individual tool names the user has granted \"allow\" for the lifetime of this session. */\n  readonly #grantedTools = new Set<string>();\n  /** Running token-usage tally for the active thread. */\n  #tokenUsage: TokenUsage = createEmptyTokenUsage();\n  /** Whether the in-flight abort teardown must stay local to this process. */\n  #localOnlyAbort = false;\n  /** Thread-settings persistence handle, injected by the AgentController via {@link setStore}. */\n  #store: ThreadSettingsStore | undefined;\n  /** Resolves a tool name to its category, injected by the AgentController via {@link setCategoryResolver} (the category map is AgentController config). */\n  #resolveCategory: ((toolName: string) => ToolCategory | null) | undefined;\n  /** Resolves a subagent's display name from AgentController config, injected via {@link setSubagentNameResolver}. */\n  #resolveSubagentName: ((agentType: string) => string | undefined) | undefined;\n  /** AgentController-owned run machinery (agent, run/stream option builders, …), injected via {@link setMachinery}. */\n  #machinery: SessionMachinery | undefined;\n  /** The per-session agent run engine, constructed once machinery is wired via {@link setMachinery}. */\n  #engine: SessionRunEngine | undefined;\n  /** The session's currently-selected model (source of truth) + per-mode memory. */\n  readonly model = new SessionModel(() => this.#store, this.#bus);\n  /** The session's currently-selected mode and switch sequence. */\n  readonly mode = new SessionMode(() => this.#store, this.model, this.#bus);\n  /** The session's observational-memory model selection (observer/reflector). */\n  readonly om = new SessionOM(this.#bus);\n  /** The session's persisted tool-permission rules (per-category / per-tool). */\n  readonly permissions = new SessionPermissions();\n  /** The session's subagent configuration (currently the subagent model). */\n  readonly subagents = new SessionSubagents(this.#bus);\n  /** Transient run identity (run id, trace id, operation counter) for the active run. */\n  readonly run = new SessionRun();\n  /** Live subscription to the active thread's agent event stream. */\n  readonly stream = new SessionStream();\n  /** Tool calls parked awaiting a resume (the resume data, keyed by toolCallId). */\n  readonly suspensions = new SessionSuspensions();\n  /** Captured Agent queue scope for this session binding. */\n  #followUpBinding?: { agent: Agent; resourceId: string; threadId: string; unsubscribe?: () => void };\n  /** Follow-up preparation that can finish after the session's active run changes. */\n  readonly #preparingFollowUps = new Set<{ generation: number; controller: AbortController }>();\n  /** Invalidates asynchronous follow-up preparation when the session unbinds. */\n  #followUpGeneration = 0;\n  /** The interactive tool-approval gate the current run parks on. */\n  readonly approval = new SessionApproval();\n  /** The session's identity: the memory resourceId it reads/writes under. */\n  readonly identity: SessionIdentity;\n  /** The session's thread domain: current binding + reads scoped to it. */\n  readonly thread: SessionThread;\n  /** The canonical display state a UI renders, plus the reducer that maintains it. */\n  readonly displayState: SessionDisplayState;\n  /** The session-owned AgentController state domain. */\n  readonly state: AgentControllerRequestState<TState>;\n  /**\n   * Scoping tags for this session (e.g. `{ projectPath }`). Seeded at creation\n   * and stamped onto every thread this session creates so thread listings can be\n   * filtered back to the session's scope. Empty when the session is unscoped.\n   */\n  readonly #tags: Record<string, string>;\n  readonly #workspace: Workspace | undefined;\n  browser?: MastraBrowser;\n\n  constructor({\n    resourceId,\n    state,\n    id,\n    ownerId,\n    tags,\n    workspace,\n    browser,\n  }: {\n    resourceId: string;\n    state?: SessionStateOptions<TState>;\n    id: string;\n    ownerId: string;\n    tags?: Record<string, string>;\n    workspace?: Workspace;\n    browser?: MastraBrowser;\n  }) {\n    this.#tags = tags && Object.keys(tags).length > 0 ? { ...tags } : {};\n    this.identity = new SessionIdentity({ resourceId, id, ownerId });\n    this.thread = new SessionThread(() => this.identity.getResourceId());\n    this.displayState = new SessionDisplayState({\n      getTokenUsage: () => this.getTokenUsage(),\n      getSubagentDisplayName: agentType => this.#resolveSubagentName?.(agentType),\n      getThreadId: () => this.thread.getId(),\n      clearFollowUps: () => this.cleanupFollowUpBinding(),\n    });\n    this.#bus.setDisplayState(this.displayState);\n    this.state = new SessionState(state ?? { initialState: {} as TState }, this.#bus, () => {\n      // Pin persistence to the thread active when the state update was\n      // requested — a queued preference update must not land in the metadata\n      // of a thread the session switched to in the meantime.\n      const threadId = this.thread.getId();\n      if (threadId === null) return undefined;\n      return args => this.thread.setSettingOn({ threadId, ...args });\n    });\n\n    if (workspace !== undefined && !(workspace instanceof Workspace)) {\n      throw new Error(`A session workspace must be a valid Workspace instance.`);\n    }\n\n    this.#workspace = workspace;\n    this.browser = browser;\n  }\n\n  /**\n   * This session's scoping tags (e.g. `{ projectPath }`), stamped onto every\n   * thread it creates. Returns a copy; empty when the session is unscoped.\n   */\n  getTags(): Record<string, string> {\n    return { ...this.#tags };\n  }\n\n  /**\n   * The scope this session's threads carry: what `thread.create()` stamps and\n   * what thread selection filters on. Both must read it here — computing it on\n   * each side is what let selection drift off the controller-global state while\n   * creation stamped the session's own.\n   */\n  getThreadScope(): Record<string, string> {\n    const tags = Object.fromEntries(Object.entries(this.#tags).filter(([key]) => !isReservedThreadMetadataKey(key)));\n    if (Object.keys(tags).length > 0) return tags;\n    const { projectPath } = this.state.get() as { projectPath?: string };\n    return projectPath ? { projectPath } : {};\n  }\n\n  /**\n   * The workspace resolved for this session, or `undefined` when the session\n   * runs without one. A workspace is optional: sessions that only need threads,\n   * state, and agent runs (chat-style usage) do not have to configure\n   * filesystem or sandbox access.\n   *\n   * Dynamic workspace factories are evaluated independently when each session\n   * is created. Use this accessor for operations that must stay bound to the\n   * session's workspace rather than resolving through controller-global state.\n   */\n  getWorkspace(): Workspace | undefined {\n    return this.#workspace;\n  }\n\n  // ===========================================================================\n  // Event bus\n  // ===========================================================================\n\n  /**\n   * Subscribe to this session's events. Returns an unsubscribe function.\n   * Listeners are scoped to this session: a session never delivers its events\n   * to another session's subscribers.\n   */\n  subscribe(listener: AgentControllerEventListener): () => void {\n    return this.#bus.subscribe(listener);\n  }\n\n  /** Subscribe to work that must complete before the terminal agent event is exposed. */\n  onBeforeAgentEnd(listener: SessionBeforeAgentEndListener): () => void {\n    this.#beforeAgentEndListeners.add(listener);\n    return () => this.#beforeAgentEndListeners.delete(listener);\n  }\n\n  /** Await terminal hooks, then emit the terminal event to subscribers. */\n  async finishAgentRun(\n    reason: NonNullable<Extract<AgentControllerEvent, { type: 'agent_end' }>['reason']>,\n  ): Promise<void> {\n    const event = { type: 'agent_end', reason } as const;\n    for (const listener of this.#beforeAgentEndListeners) {\n      try {\n        await listener(event);\n      } catch (error) {\n        console.error('Error in before-agent-end listener:', error);\n      }\n    }\n    this.emit(event);\n  }\n\n  /** Await the terminal event for a specific accepted agent run. */\n  private async waitForAcceptedRunCompletion<OUTPUT>(\n    accepted: Promise<{ action?: SendAgentSignalAccepted<OUTPUT>['action']; runId?: string }>,\n    { waitForDelivery = true }: { waitForDelivery?: boolean } = {},\n  ): Promise<void> {\n    const completedRunIds = new Set<string>();\n    let runId: string | undefined;\n    let resolveCompletion!: () => void;\n    const completion = new Promise<void>(resolve => {\n      resolveCompletion = resolve;\n    });\n    const unsubscribe = this.onBeforeAgentEnd(() => {\n      const endingRunId = this.run.getRunId();\n      if (!endingRunId) return;\n      completedRunIds.add(endingRunId);\n      if (endingRunId === runId) resolveCompletion();\n    });\n\n    try {\n      const result = await accepted;\n      if (result.action !== 'wake' && !waitForDelivery) return;\n      runId = 'runId' in result ? result.runId : undefined;\n      if (!runId || completedRunIds.has(runId)) return;\n      await completion;\n    } finally {\n      unsubscribe();\n    }\n  }\n\n  /**\n   * Emit an event on this session. Delegates to this session's bus, which folds\n   * the event into the canonical display state, dispatches to this session's\n   * listeners, then fans out a synthetic `display_state_changed`.\n   */\n  emit(event: AgentControllerEvent): void {\n    this.#bus.emit(event);\n  }\n\n  /**\n   * Whether this session has any event subscribers. Emitters use this to skip\n   * building per-event snapshots that nothing would read.\n   */\n  hasListeners(): boolean {\n    return this.#bus.hasListeners();\n  }\n\n  /**\n   * Attach the thread-settings store the Session persists mode/model through.\n   * The AgentController calls this once storage is available; without it, mode/model\n   * state lives purely in memory.\n   */\n  setStore(store: ThreadSettingsStore | undefined): void {\n    this.#store = store;\n  }\n\n  /**\n   * Attach the tool→category resolver used when a user picks \"always allow\n   * category\". The category map is AgentController config, so the AgentController injects this\n   * once; without it, an \"always_allow_category\" decision simply approves.\n   */\n  setCategoryResolver(resolveCategory: (toolName: string) => ToolCategory | null): void {\n    this.#resolveCategory = resolveCategory;\n  }\n\n  /**\n   * Attach the subagent display-name resolver the display-state reducer uses to\n   * label active subagents. The subagent catalog is AgentController config, so the\n   * AgentController injects this once; without it, subagents render without a name.\n   */\n  setSubagentNameResolver(resolveSubagentName: (agentType: string) => string | undefined): void {\n    this.#resolveSubagentName = resolveSubagentName;\n  }\n\n  /**\n   * Attach the AgentController-owned run machinery this session leverages to drive agent\n   * runs (resolve the agent, build run/stream options + toolsets + request\n   * context, persist usage, generate ids). The AgentController injects this once when it\n   * constructs the session. The run loop, run state, and thread stream live on\n   * the session; this is the narrow set of shared capabilities it reaches back\n   * into the host for — see {@link SessionMachinery}.\n   */\n  setMachinery(machinery: SessionMachinery): void {\n    this.#machinery = machinery;\n    this.#engine = new SessionRunEngine(this as Session, machinery);\n  }\n\n  /**\n   * The AgentController-owned run machinery injected via {@link setMachinery}, throwing\n   * when accessed before wiring (a run can never be driven without it).\n   */\n  get machinery(): SessionMachinery {\n    if (!this.#machinery) {\n      throw new Error('Session run machinery has not been wired by the AgentController');\n    }\n    return this.#machinery;\n  }\n\n  /** The per-session run engine, throwing when accessed before machinery is wired. */\n  get runEngine(): SessionRunEngine {\n    if (!this.#engine) {\n      throw new Error('Session run engine has not been wired by the AgentController');\n    }\n    return this.#engine;\n  }\n\n  /**\n   * Consume an agent stream response, folding chunks into this session's display\n   * messages and usage and driving tool approval. Delegates to the per-session\n   * run engine. Production runs go through `processSubscribedThreadStream`;\n   * only tests call this directly.\n   */\n  processStream(\n    response: { fullStream: AsyncIterable<any> },\n    requestContext?: RequestContext,\n  ): Promise<{ message: MastraDBMessage; suspended?: boolean } | undefined> {\n    return this.runEngine.processStream(response, requestContext);\n  }\n\n  /**\n   * Drive the run loop for a subscribed thread stream: process each run's chunks\n   * and finalize it. Delegates to the per-session run engine.\n   */\n  processSubscribedThreadStream(subscription: AgentThreadSubscription<any>): Promise<void> {\n    return this.runEngine.processSubscribedThreadStream(subscription);\n  }\n\n  /**\n   * The id of the run currently active on this session: the live subscription's\n   * active run id when it is streaming, falling back to the last run id the run\n   * tracker observed. Null when the session is idle.\n   */\n  getCurrentRunId(): string | null {\n    return this.stream.activeRunId() ?? this.run.getRunId();\n  }\n\n  /**\n   * Abort the session's active run: drop any parked tool suspensions, abort the\n   * live subscription's in-flight run, and mark the run as aborting so the\n   * run-end path resolves its reason as 'aborted'.\n   *\n   * Dropping the parked suspensions matters because a run sitting in a tool\n   * `suspend()` (e.g. `ask_user` / `request_access`) is not actively streaming,\n   * so aborting the controller alone would leave it orphaned. The AgentController still\n   * clears its own display-state mirror of those suspensions separately.\n   *\n   * Releasing a parked tool-approval gate matters for the same reason: a run\n   * awaiting `approval.arm()` is not streaming, so we resolve it as a decline so\n   * the gated tool is rejected and the run can finalize rather than hang.\n   */\n  abortRun(options: { localOnly?: boolean } = {}): void {\n    // Aborting twice while a gate is parked would tear the stream down before\n    // the deferred decline lands (the second call sees the gate already\n    // cancelled), which is the exact failure the deferral exists to avoid. Two\n    // `tool_approval_required` subscribers each calling abort() is enough.\n    if (this.run.isAbortRequested()) return;\n\n    // Retract the prompts for every parked suspension. Dropping them silently\n    // left the UI rendering `ask_user` / `request_access` prompts whose answers\n    // could never land, since the run they belong to is gone.\n    const suspendedToolCalls = this.suspensions.clear();\n    for (const { toolCallId, toolName } of suspendedToolCalls) {\n      this.emit({ type: 'tool_suspension_cancelled', toolCallId, toolName, reason: ABORTED_BY_USER_REASON });\n    }\n\n    // The teardown may be deferred (below), so remember whether this abort should\n    // stay local for when it actually runs.\n    this.#localOnlyAbort = options.localOnly === true;\n\n    // A parked approval gate is special: the agent-side run is still alive and\n    // waiting for the decision, so the gated call must be declined through it\n    // (that is what persists the `output-denied` tool result). Tearing the\n    // stream down first would make that decline fail with \"could not find an\n    // active or suspended run\". Defer both the stream abort and the abort\n    // signal to the engine, which fires them once the decline has landed.\n    const wasGated = this.approval.isArmed();\n    if (wasGated) {\n      this.run.requestAbort({ deferSignal: true });\n      if (suspendedToolCalls.length === 0) {\n        this.approval.cancel();\n        return;\n      }\n      void this.runEngine\n        .settleSuspendedToolCallsAsDenied(suspendedToolCalls)\n        .catch(error => this.emit({ type: 'error', error: getErrorFromUnknown(error) }))\n        .finally(() => this.approval.cancel());\n      return;\n    }\n\n    if (suspendedToolCalls.length > 0) {\n      this.run.requestAbort({ deferSignal: true });\n      void this.runEngine\n        .settleSuspendedToolCallsAsDenied(suspendedToolCalls)\n        .catch(error => this.emit({ type: 'error', error: getErrorFromUnknown(error) }))\n        .finally(() => this.completeDeferredAbort());\n      return;\n    }\n\n    this.stream.abort({ localOnly: this.#localOnlyAbort });\n    this.run.requestAbort();\n  }\n\n  /**\n   * Fire the deferred abort teardown for a run that was aborted while parked on\n   * a tool-approval gate: abort the live subscription and the run's controller.\n   * Called by the run engine once the gated call's decline has been driven\n   * through the agent, so the denial is persisted before the run is torn down.\n   */\n  completeDeferredAbort(): void {\n    this.stream.abort({ localOnly: this.#localOnlyAbort });\n    this.run.requestAbort();\n  }\n\n  /**\n   * Abort the session's active run and clear the display-state mirror of any\n   * parked tool suspensions. {@link abortRun} drops the parked suspensions (so a\n   * run sitting in a tool suspend() like ask_user / request_access isn't left\n   * orphaned), aborts the live subscription, and marks the run as aborting; this\n   * additionally clears the display-state mirror of those suspensions and\n   * notifies subscribers so stale suspension UI doesn't linger.\n   */\n  abort(options: { localOnly?: boolean } = {}): void {\n    const hadPendingSuspensions = this.displayState.get().pendingSuspensions.size > 0;\n    this.displayState.clearPendingSuspensions();\n    this.abortRun(options);\n    // Clearing the suspension mirror is a direct mutation, so it doesn't flow\n    // through the display-state reducer. Notify subscribers explicitly when we\n    // actually removed something, otherwise stale suspension UI can linger.\n    if (hadPendingSuspensions) {\n      this.emit({ type: 'display_state_changed', displayState: this.displayState.get() });\n    }\n  }\n\n  /**\n   * Resolve the effective approval policy for a tool: explicit per-tool deny\n   * wins, then session-wide yolo, then an explicit per-tool policy, then a\n   * session-scoped grant, then the tool's category grant/policy, falling back to\n   * \"ask\". Pure session state plus the injected category resolver.\n   */\n  resolveToolApproval(toolName: string): PermissionPolicy {\n    const state = this.state.get() as Record<string, unknown>;\n    const rules = this.permissions.getRules();\n\n    const toolPolicy = rules.tools[toolName];\n    if (toolPolicy === 'deny') return 'deny';\n\n    if (state.yolo === true) return 'allow';\n\n    if (toolPolicy) return toolPolicy;\n\n    if (this.hasToolGrant(toolName)) return 'allow';\n\n    const category = this.#resolveCategory?.(toolName);\n    if (category) {\n      if (this.hasCategoryGrant(category)) return 'allow';\n      const categoryPolicy = rules.categories[category];\n      if (categoryPolicy) return categoryPolicy;\n    }\n\n    return 'ask';\n  }\n\n  /**\n   * Respond to the parked tool-approval gate with the user's decision. A no-op\n   * when nothing is awaiting approval or the run is already aborting.\n   * \"always_allow_category\" grants the gated tool's category for the rest of\n   * the session (resolved via the injected {@link setCategoryResolver}) and then\n   * approves; \"approve\"/\"decline\" release\n   * the run as-is.\n   */\n  respondToToolApproval({\n    decision,\n    toolCallId,\n    requestContext,\n    declineContext,\n  }: {\n    decision: 'approve' | 'decline' | 'always_allow_category';\n    toolCallId?: string;\n    requestContext?: RequestContext;\n    declineContext?: { reason?: string; message?: string };\n  }): void {\n    if (this.run.isAbortRequested()) return;\n    this.approval.respond({\n      decision,\n      toolCallId,\n      requestContext,\n      declineContext,\n      onAlwaysAllow: toolName => {\n        const category = this.#resolveCategory?.(toolName);\n        if (category) this.grantCategory(category);\n      },\n    });\n  }\n\n  // ===========================================================================\n  // Run control\n  // ===========================================================================\n\n  /**\n   * Build the agent message input for a user turn, attaching any files as\n   * additional message parts (text files inlined as fenced code, binary files\n   * as `file` parts). Returns the plain string when there are no files.\n   */\n  private createMessageInput({\n    content,\n    files,\n  }: {\n    content: string;\n    files?: Array<{ data: string; mediaType: string; filename?: string }>;\n  }): AgentSignalContents {\n    if (!files?.length) return content;\n\n    const fileParts = files.map(f => {\n      const isText = f.mediaType.startsWith('text/') || f.mediaType === 'application/json';\n      if (isText) {\n        let textContent = f.data;\n        const base64Match = f.data.match(/^data:[^;]*;base64,(.*)$/);\n        if (base64Match) {\n          try {\n            textContent = Buffer.from(base64Match[1]!, 'base64').toString('utf-8');\n          } catch {\n            // Fall through with raw data\n          }\n        }\n        const label = f.filename ? `[File: ${f.filename}]` : '[Attached file]';\n        const maxBacktickRun = Math.max(0, ...Array.from(textContent.matchAll(/`+/g), match => match[0].length));\n        const fence = '`'.repeat(Math.max(3, maxBacktickRun + 1));\n        return { type: 'text' as const, text: `${label}\\n${fence}\\n${textContent}\\n${fence}` };\n      }\n      return {\n        type: 'file' as const,\n        data: f.data,\n        mediaType: f.mediaType,\n        ...(f.filename ? { filename: f.filename } : {}),\n      };\n    });\n\n    return [{ type: 'text', text: content }, ...fileParts];\n  }\n\n  /**\n   * Watch for the live subscription's next teardown (detach or cleanup). The run\n   * engine detaches an aborted subscription only after that run has ended, so\n   * work that must land on a fresh subscription waits for this first. Register\n   * it before awaiting anything, while the aborted handle is still attached.\n   */\n  #watchStreamTeardown(): { wait: (timeoutMs: number) => Promise<void>; cancel: () => void } {\n    const watcher = new AbortController();\n    const teardown = this.stream.waitForTeardown(watcher.signal);\n    return {\n      wait: async timeoutMs => {\n        let timer: ReturnType<typeof setTimeout> | undefined;\n        try {\n          await Promise.race([\n            teardown,\n            new Promise<void>(resolve => {\n              timer = setTimeout(resolve, timeoutMs);\n            }),\n          ]);\n        } finally {\n          if (timer) clearTimeout(timer);\n          watcher.abort();\n        }\n      },\n      cancel: () => watcher.abort(),\n    };\n  }\n\n  /**\n   * Resolve once this session's stream is fully idle.\n   *\n   * After `abort()` is called the run's status can still be `'running'` for a\n   * few microtasks while the underlying model stream finalizes. Callers that\n   * need to send a fresh signal after an abort (e.g. plan approval → mode\n   * switch → trigger reminder) should await this before calling `sendSignal`\n   * to avoid the new signal being queued onto the dying run, which would then\n   * be drained with the previous run's already-aborted abortSignal.\n   */\n  private async waitForStreamIdle(timeoutMs = 1_000): Promise<boolean> {\n    if (!this.stream.isActive() && this.run.getRunId() === null) return true;\n\n    let lifecycleWait: AbortController | undefined;\n    let timeout: ReturnType<typeof setTimeout> | undefined;\n    const timeoutPromise = new Promise<'timeout'>(resolve => {\n      timeout = setTimeout(() => resolve('timeout'), timeoutMs);\n    });\n\n    try {\n      while (this.stream.isActive() || this.run.getRunId() !== null) {\n        lifecycleWait = new AbortController();\n        const result = await Promise.race([\n          this.stream.waitForTeardown(lifecycleWait.signal),\n          this.run.waitForTeardown(lifecycleWait.signal),\n          timeoutPromise,\n        ]);\n        lifecycleWait.abort();\n        lifecycleWait = undefined;\n        // Teardown did not complete within the timeout: the old run is still\n        // finalizing and its live subscription still matches, so the caller\n        // must force a fresh subscription rather than trusting `matches`.\n        if (result === 'timeout') return false;\n      }\n    } finally {\n      lifecycleWait?.abort();\n      if (timeout) clearTimeout(timeout);\n    }\n    return true;\n  }\n\n  /** Persist a signal to an explicit conversation without changing this session's current thread. */\n  sendSignalToThread(\n    input: AgentSignalInput,\n    target: { resourceId: string; threadId: string },\n  ): { id: string; type: AgentSignalInput['type']; accepted: Promise<{ accepted: true }> } {\n    const signal = createSignal(input);\n    const accepted = Promise.resolve().then(async () => {\n      const resourceId = this.identity.getResourceId();\n      const thread = target.resourceId === resourceId ? await this.thread.getById({ threadId: target.threadId }) : null;\n      if (!thread || thread.resourceId !== resourceId) {\n        throw new Error(`Thread not found: ${target.threadId}`);\n      }\n\n      const result = this.machinery.getAgent().sendSignal(signal, {\n        ...target,\n        ifActive: { behavior: 'persist' },\n        ifIdle: { behavior: 'persist' },\n      });\n      const settled = await result.accepted;\n\n      if (settled.action === 'persist') {\n        await result.persisted;\n        if (this.identity.getResourceId() === target.resourceId && this.thread.getId() === target.threadId) {\n          const message = signal.toDBMessage(target);\n          this.emit({ type: 'message_start', message });\n          this.emit({ type: 'message_end', id: message.id });\n        }\n      }\n\n      return { accepted: true as const };\n    });\n\n    return { id: signal.id, type: signal.type, accepted };\n  }\n\n  /**\n   * Send a signal to this session's current agent/thread. Creates a thread when\n   * the session is not yet bound. When a run is already active the signal is\n   * dispatched onto it; otherwise the signal carries fresh stream options that\n   * start a new run.\n   */\n  sendSignal(\n    input:\n      | AgentSignalInput\n      | {\n          content: AgentSignalContents;\n          ifActive?: { behavior?: AgentSignalActiveBehavior; attributes?: AgentSignalAttributes };\n          ifIdle?: { behavior?: AgentSignalIdleBehavior; attributes?: AgentSignalAttributes };\n          tracingContext?: TracingContext;\n          tracingOptions?: TracingOptions;\n          requestContext?: RequestContext;\n          untilIdle?: boolean | { maxIdleMs?: number };\n          /**\n           * Provider options attached to the resulting prompt turn. Surfaces as\n           * `providerOptions` on the `UserModelMessage` sent to the model and as\n           * `content.providerMetadata` on the persisted DB message (see\n           * {@link AgentSignalInput.providerOptions}).\n           */\n          providerOptions?: MastraProviderMetadata;\n        },\n    options?: {\n      ifActive?: { behavior?: AgentSignalActiveBehavior; attributes?: AgentSignalAttributes };\n      ifIdle?: { behavior?: AgentSignalIdleBehavior; attributes?: AgentSignalAttributes };\n      tracingContext?: TracingContext;\n      tracingOptions?: TracingOptions;\n      requestContext?: RequestContext;\n      untilIdle?: boolean | { maxIdleMs?: number };\n      /**\n       * When true, the returned `accepted` promise awaits the agent's real\n       * acceptance decision (`wake`/`deliver`/…) and propagates routing or\n       * stream-setup failures as rejections instead of resolving on the next\n       * tick. Callers that need delivery guarantees (e.g. the Factory rule\n       * dispatcher) use this so a failed wake is retried rather than silently\n       * treated as sent.\n       */\n      requireDelivery?: boolean;\n    },\n  ): {\n    id: string;\n    type: AgentSignalInput['type'];\n    accepted: Promise<{ accepted: true; runId?: string; action?: SendAgentSignalAccepted['action'] }>;\n  } {\n    const settleRunId = async <T>(result: {\n      accepted: Promise<SendAgentSignalAccepted<T>>;\n    }): Promise<string | undefined> => {\n      // Best-effort run id for telemetry. A wake whose stream setup fails rejects\n      // `accepted`; that error surfaces to the controller through the thread subscription\n      // as an error event, so we must not let it reject the session send here.\n      const settled = await result.accepted.catch(() => undefined);\n      return settled && 'runId' in settled ? settled.runId : undefined;\n    };\n    const contentOptions = 'content' in input ? input : undefined;\n    const tracingContext = options?.tracingContext ?? contentOptions?.tracingContext;\n    const tracingOptions = options?.tracingOptions ?? contentOptions?.tracingOptions;\n    const requestContextInput = options?.requestContext ?? contentOptions?.requestContext;\n    const untilIdle = options?.untilIdle ?? contentOptions?.untilIdle;\n    const requireDelivery = options?.requireDelivery ?? false;\n    const ifActive = options?.ifActive ?? ('content' in input ? input.ifActive : undefined);\n    const ifIdle = options?.ifIdle ?? ('content' in input ? input.ifIdle : undefined);\n    const submittedRunId = this.run.getRunId();\n    const submittedActiveRunId = this.stream.activeRunId();\n    // After `abort()` the AbortController is cleared immediately but the run id\n    // and active-run id linger until `run.reset()` runs (after `agent_end`).\n    // Without this guard, a signal sent right after an interrupt is dispatched\n    // onto the dying run and lost — the follow-up message never gets a response.\n    const submittedIsRunning = this.run.isRunning();\n    // An abort was requested but the previous run hasn't finished tearing down\n    // yet (the flag stays set until `run.reset()` after `agent_end`). This is\n    // the post-interrupt window where a fresh signal must wait for the dying\n    // run to fully idle before starting a new run.\n    const submittedAbortRequested = this.run.isAbortRequested();\n    const submittedWhileWorking =\n      submittedIsRunning || (submittedAbortRequested && Boolean(submittedRunId || submittedActiveRunId));\n    // Registered before any await: resolves when the aborted live subscription is\n    // detached, which the run engine does only after that run has ended.\n    const abortedStreamTeardown =\n      submittedAbortRequested && !submittedIsRunning && this.stream.isOpen() ? this.#watchStreamTeardown() : undefined;\n    const submitted = createSignal(\n      'content' in input\n        ? {\n            type: 'user',\n            tagName: 'user',\n            contents: input.content,\n            providerOptions: withMessageAuthor(input.providerOptions, readMessageAuthor(requestContextInput)),\n          }\n        : input,\n    );\n    const signal = submittedWhileWorking ? asInterjection(submitted) : submitted;\n    const accepted = Promise.resolve().then(async () => {\n      if (!this.thread.getId()) {\n        const thread = await this.thread.create();\n        this.thread.set({ threadId: thread.id });\n      }\n      const threadId = this.thread.getId()!;\n\n      const agent = this.machinery.getAgent();\n      await this.thread.ensureSubscription(threadId, agent);\n\n      // A deferred abort (parked approval gate) leaves the AbortController\n      // armed until the decline lands, so `submittedIsRunning` stays true for a\n      // run that is already on its way out. Routing a signal to it would hand\n      // the message to a run that `completeDeferredAbort()` then terminates.\n      if (!submittedAbortRequested && submittedRunId && submittedActiveRunId && submittedIsRunning) {\n        if (signal.type === 'user') {\n          this.approval.respond({\n            decision: 'decline',\n            declineContext: {\n              reason: 'interrupted_by_user_message',\n              message: 'The pending tool approval was declined because the user sent a new message.',\n            },\n          });\n        }\n        const result = agent.sendSignal(signal, {\n          resourceId: this.identity.getResourceId(),\n          threadId,\n          ifActive,\n          ifIdle,\n        });\n        const shouldObservePersistence = ifActive?.behavior === 'persist' || ifIdle?.behavior === 'persist';\n        const settled = shouldObservePersistence || requireDelivery ? await result.accepted : undefined;\n        if (settled?.action === 'persist') {\n          await result.persisted;\n          const message = signal.toDBMessage({\n            resourceId: this.identity.getResourceId(),\n            threadId,\n          });\n          this.emit({ type: 'message_start', message });\n          this.emit({ type: 'message_end', id: message.id });\n        }\n        if (requireDelivery) {\n          const acceptedResult = settled ?? (await result.accepted);\n          return {\n            accepted: true as const,\n            runId: 'runId' in acceptedResult ? acceptedResult.runId : undefined,\n            action: acceptedResult.action,\n          };\n        }\n        return { accepted: true as const, runId: await settleRunId(result) };\n      }\n\n      // Post-abort lingering state: the AbortController was cleared (so\n      // `submittedIsRunning` is false) but the previous run is still finalizing\n      // — its run id / active-run id linger until `run.reset()` runs after\n      // `agent_end`. Dispatching a fresh signal now would let the agent queue it\n      // onto the dying run instead of starting a new run, and the follow-up\n      // would never get a response. Wait for the stream to fully idle first.\n      // Only do this in the post-abort window (an abort was requested but the\n      // run hasn't reset yet) so normal idle signals aren't delayed.\n      if (submittedAbortRequested && (submittedRunId || submittedActiveRunId)) {\n        // A deferred abort (parked approval gate) streams nothing and only\n        // leaves once the gated call is declined, so the short wait is enough.\n        // A normal abort tears down for real: the model stream has to cancel\n        // and the output processors (memory, billing, ...) still run on the\n        // partial result, which takes longer than a second. Dispatching before\n        // that completes hands the new message to the dying run, which drops\n        // it, so wait for the real teardown before falling back below.\n        const teardownDeadline = Date.now() + POST_ABORT_TEARDOWN_TIMEOUT_MS;\n        const idle = await this.waitForStreamIdle(submittedIsRunning ? undefined : POST_ABORT_TEARDOWN_TIMEOUT_MS);\n        // The stream can read idle before the run engine detaches the aborted\n        // subscription (it detaches, then resets the run). Ensuring the\n        // subscription in that gap reuses the handle about to be detached, and\n        // the new run's events never reach this session: wait for the detach.\n        if (idle && abortedStreamTeardown && this.run.isAbortRequested()) {\n          await abortedStreamTeardown.wait(Math.max(0, teardownDeadline - Date.now()));\n        }\n        if (!idle) {\n          // On the normal path the abort teardown detached the live subscription\n          // while we waited, so the handle captured by the earlier\n          // `ensureSubscription` is now dead and re-ensuring genuinely\n          // re-subscribes. But when `waitForStreamIdle` times out the old run is\n          // still finalizing with its subscription live and matching, so\n          // `ensureSubscription` would short-circuit to a no-op and dispatch onto\n          // the still-aborting run. Force teardown of the stale subscription first\n          // so the re-ensure always attaches a fresh one — otherwise the new run\n          // starts with no native subscription and its `agent_start`/`agent_end`\n          // never reach the session, leaving `run.isRunning()` stuck true.\n          this.thread.cleanupSubscription();\n        }\n        await this.thread.ensureSubscription(threadId, agent);\n      } else if (abortedStreamTeardown) {\n        // Stop on a run parked on a tool suspension leaves no run id behind,\n        // but the stopped run's subscription is still attached and is about to\n        // deliver the Stop and detach. Sending on it hands the new run's first\n        // event to the stopped run, which is ended as aborted and detached, so\n        // the new run's end never reaches this session. Wait briefly for that\n        // detach; if it never comes, drop the subscription and the abort state\n        // here. Either way the new run starts on a fresh subscription.\n        await abortedStreamTeardown.wait(1_000);\n        if (this.stream.isOpen() && this.run.isAbortRequested()) {\n          this.thread.cleanupSubscription();\n          this.run.reset();\n        }\n        await this.thread.ensureSubscription(threadId, agent);\n      }\n      abortedStreamTeardown?.cancel();\n\n      const streamOptions = await this.machinery.buildStreamOptions({\n        requestContext: requestContextInput,\n        tracingContext,\n        tracingOptions,\n        untilIdle,\n      });\n\n      const result = agent.sendSignal(signal, {\n        resourceId: this.identity.getResourceId(),\n        threadId,\n        ifActive,\n        ifIdle: { ...ifIdle, streamOptions: streamOptions as any },\n      });\n      if (requireDelivery) {\n        // Delivery-guaranteed path: surface the real acceptance decision and\n        // propagate routing/stream-setup failures to the caller.\n        const settled = await result.accepted;\n        return {\n          accepted: true as const,\n          runId: 'runId' in settled ? settled.runId : undefined,\n          action: settled.action,\n        };\n      }\n      try {\n        await Promise.race([\n          result.accepted.then(() => undefined),\n          new Promise<void>(resolve => setTimeout(resolve, 0)),\n        ]);\n      } catch (error) {\n        throw error;\n      }\n      void result.accepted.catch(() => {});\n      if (ifIdle?.behavior === 'persist') {\n        await result.persisted;\n      }\n      return { accepted: true as const, runId: undefined };\n    });\n\n    return { id: signal.id, type: signal.type, accepted };\n  }\n\n  /**\n   * Send a notification signal to this session's current agent/thread.\n   */\n  async sendNotificationSignal(\n    input: SendNotificationSignalInput,\n    options: SessionSendNotificationSignalOptions = {},\n  ): Promise<SendAgentNotificationSignalResult> {\n    const { ifActive, ifIdle, requestContext: requestContextInput, tracingContext, tracingOptions } = options;\n    if (!this.thread.getId()) {\n      const thread = await this.thread.create();\n      this.thread.set({ threadId: thread.id });\n    }\n    const threadId = this.thread.getId()!;\n\n    const agent = this.machinery.getAgent();\n    await this.thread.ensureSubscription(threadId);\n\n    if (this.run.getRunId() && this.stream.activeRunId()) {\n      return agent.sendNotificationSignal(input, {\n        resourceId: this.identity.getResourceId(),\n        threadId,\n        ifActive,\n        ifIdle,\n      });\n    }\n\n    const streamOptions = await this.machinery.buildStreamOptions({\n      requestContext: requestContextInput,\n      tracingContext,\n      tracingOptions,\n    });\n\n    return agent.sendNotificationSignal(input, {\n      resourceId: this.identity.getResourceId(),\n      threadId,\n      ifActive,\n      ifIdle: { ...ifIdle, streamOptions: streamOptions as any },\n    });\n  }\n\n  private async prepareMessageTarget({\n    requestContext,\n    tracingContext,\n    tracingOptions,\n    untilIdle,\n    includeStreamOptions = true,\n  }: {\n    requestContext?: RequestContext;\n    tracingContext?: TracingContext;\n    tracingOptions?: TracingOptions;\n    untilIdle?: boolean | { maxIdleMs?: number };\n    includeStreamOptions?: boolean;\n  }) {\n    if (!this.thread.getId()) {\n      const thread = await this.thread.create();\n      this.thread.set({ threadId: thread.id });\n    }\n    const threadId = this.thread.getId()!;\n    await this.thread.ensureSubscription(threadId);\n\n    if (!includeStreamOptions) {\n      return { resourceId: this.identity.getResourceId(), threadId };\n    }\n\n    const streamOptions = await this.machinery.buildStreamOptions({\n      requestContext,\n      tracingContext,\n      tracingOptions,\n      untilIdle,\n    });\n\n    return {\n      resourceId: this.identity.getResourceId(),\n      threadId,\n      ifIdle: { streamOptions: streamOptions as any },\n    };\n  }\n\n  /**\n   * Send a message to this session's current agent and await the run. Streams\n   * the response and emits events.\n   */\n  async sendMessage({\n    content,\n    files,\n    tracingContext,\n    tracingOptions,\n    requestContext: requestContextInput,\n    untilIdle,\n  }: {\n    content: string;\n    files?: Array<{ data: string; mediaType: string; filename?: string }>;\n    tracingContext?: TracingContext;\n    tracingOptions?: TracingOptions;\n    requestContext?: RequestContext;\n    untilIdle?: boolean | { maxIdleMs?: number };\n  }): Promise<void> {\n    const wasActive = this.stream.isActive();\n    const signal = this.sendSignal(\n      {\n        content: this.createMessageInput({ content, files }),\n        tracingContext,\n        tracingOptions,\n        requestContext: requestContextInput,\n        untilIdle,\n      },\n      { requireDelivery: true },\n    );\n\n    if (wasActive) {\n      await signal.accepted;\n    } else {\n      await this.waitForAcceptedRunCompletion(signal.accepted);\n    }\n  }\n\n  /**\n   * Queue a message for the next run, or send it immediately when this session\n   * is idle. Queue ordering and retry behavior are owned by the Agent runtime.\n   */\n  async queueMessage({\n    content,\n    files,\n    tracingContext,\n    tracingOptions,\n    requestContext: requestContextInput,\n  }: {\n    content: string;\n    files?: Array<{ data: string; mediaType: string; filename?: string }>;\n    tracingContext?: TracingContext;\n    tracingOptions?: TracingOptions;\n    requestContext?: RequestContext;\n  }): Promise<void> {\n    const wasActive = this.stream.isActive();\n    const target = await this.prepareMessageTarget({\n      requestContext: requestContextInput,\n      tracingContext,\n      tracingOptions,\n    });\n    const messageInput = this.createMessageInput({ content, files });\n    const providerOptions = withMessageAuthor(undefined, readMessageAuthor(requestContextInput));\n    const result = this.machinery\n      .getAgent()\n      .queueMessage(providerOptions ? { contents: messageInput, providerOptions } : messageInput, target);\n\n    if (wasActive) {\n      await result.accepted;\n    } else {\n      await this.waitForAcceptedRunCompletion(result.accepted, { waitForDelivery: false });\n    }\n  }\n\n  /** Abort the current run and send steering input without clearing queued follow-ups. */\n  async steer({ content, requestContext }: { content: string; requestContext?: RequestContext }): Promise<void> {\n    this.abort();\n    await this.sendMessage({ content, requestContext });\n  }\n\n  ensureFollowUpBinding(agent: Agent, resourceId: string, threadId: string) {\n    const existing = this.#followUpBinding;\n    if (existing?.agent === agent && existing.resourceId === resourceId && existing.threadId === threadId)\n      return existing;\n    this.cleanupFollowUpBinding();\n    const binding: {\n      agent: Agent;\n      resourceId: string;\n      threadId: string;\n      unsubscribe?: () => void;\n    } = {\n      agent,\n      resourceId,\n      threadId,\n    };\n    this.#followUpBinding = binding;\n    try {\n      const unsubscribe = agent.subscribeThreadEvents({ resourceId, threadId }, event => {\n        if (event.type === 'queue-count-changed' && this.#followUpBinding === binding) {\n          this.emit({ type: 'follow_up_queued', count: event.count });\n        }\n      });\n      binding.unsubscribe = unsubscribe;\n      if (this.#followUpBinding !== binding) {\n        unsubscribe();\n        return undefined;\n      }\n      return binding;\n    } catch (error) {\n      if (this.#followUpBinding === binding) this.#followUpBinding = undefined;\n      throw error;\n    }\n  }\n\n  /** Queue a follow-up through the Agent runtime, or send it immediately while idle. */\n  async followUp({ content, requestContext }: { content: string; requestContext?: RequestContext }): Promise<void> {\n    if (!this.run.isRunning()) return this.sendMessage({ content, requestContext });\n    const threadId = this.thread.getId();\n    if (!threadId) return;\n    const resourceId = this.identity.getResourceId();\n    const agent = this.machinery.getAgent();\n    const binding = this.ensureFollowUpBinding(agent, resourceId, threadId);\n    if (!binding) return;\n    const operation = { generation: this.#followUpGeneration, controller: new AbortController() };\n    this.#preparingFollowUps.add(operation);\n    try {\n      const streamOptions = await this.machinery.buildStreamOptions({\n        requestContext,\n        abortSignal: operation.controller.signal,\n      });\n      if (operation.controller.signal.aborted || operation.generation !== this.#followUpGeneration) return;\n      // Once submitted, the Agent owns this work independently of the Session.\n      this.#preparingFollowUps.delete(operation);\n      await agent.queueMessage(\n        {\n          contents: this.createMessageInput({ content }),\n          providerOptions: withMessageAuthor(undefined, readMessageAuthor(requestContext)),\n        },\n        {\n          resourceId,\n          threadId,\n          ifIdle: { streamOptions: streamOptions as any },\n        },\n      ).accepted;\n    } finally {\n      this.#preparingFollowUps.delete(operation);\n    }\n  }\n\n  cleanupFollowUpBinding(): void {\n    this.#followUpGeneration += 1;\n    for (const operation of this.#preparingFollowUps) operation.controller.abort();\n    this.#preparingFollowUps.clear();\n    const binding = this.#followUpBinding;\n    this.#followUpBinding = undefined;\n    binding?.unsubscribe?.();\n    this.emit({ type: 'follow_up_queued', count: 0 });\n  }\n\n  /**\n   * Persist a system-reminder message to this session's current thread. Returns\n   * the saved message, or `null` when the session has no thread or no storage.\n   */\n  async saveSystemReminderMessage({\n    message,\n    reminderType,\n    role = 'user',\n    metadata,\n  }: {\n    message: string;\n    reminderType: string;\n    role?: 'user' | 'assistant' | 'system';\n    metadata?: Record<string, unknown>;\n  }): Promise<MastraDBMessage | null> {\n    const threadId = this.thread.getId();\n    if (!threadId) return null;\n    return this.machinery.saveSystemReminder({\n      threadId,\n      resourceId: this.identity.getResourceId(),\n      message,\n      reminderType,\n      role,\n      metadata,\n    });\n  }\n\n  /**\n   * Respond to a pending tool suspension. Provides resume data so the suspended\n   * tool can continue. `toolCallId` selects which suspended tool to resume —\n   * required when more than one is suspended concurrently; when omitted it\n   * resolves to the sole pending suspension. `submit_plan` resumes are routed\n   * through the plan-approval path (approval switches to the default mode).\n   */\n  async respondToToolSuspension({\n    resumeData,\n    toolCallId,\n    requestContext,\n  }: {\n    resumeData: any;\n    toolCallId?: string;\n    requestContext?: RequestContext;\n  }): Promise<void> {\n    const resolvedToolCallId = this.suspensions.resolveToolCallId(toolCallId);\n    if (!resolvedToolCallId) return;\n\n    const suspension = this.suspensions.get({ toolCallId: resolvedToolCallId });\n\n    try {\n      if (suspension?.toolName === 'submit_plan') {\n        await this.handlePlanApprovalResume({\n          toolCallId: resolvedToolCallId,\n          response: resumeData as SubmitPlanResumeData,\n          requestContext,\n        });\n        return;\n      }\n\n      await this.resumeToolCall({\n        resumeData,\n        toolCallId: resolvedToolCallId,\n        requestContext,\n      });\n    } catch (error) {\n      const err = getErrorFromUnknown(error);\n      this.emit({ type: 'error', error: err });\n      await this.finishAgentRun('error');\n    }\n  }\n\n  /**\n   * Respond to a suspended `submit_plan` tool call. Rejections resume the plan\n   * tool with feedback. Approvals switch to the transition mode when needed,\n   * then resume the same suspended tool so the approved tool result is persisted\n   * and the model continues naturally in the target mode.\n   */\n  private async handlePlanApprovalResume({\n    toolCallId,\n    response,\n    requestContext,\n  }: {\n    toolCallId: string;\n    response: SubmitPlanResumeData;\n    requestContext?: RequestContext;\n  }): Promise<void> {\n    if (response.action === 'rejected') {\n      // The caller aborts once the rejected tool result is persisted. Waiting for\n      // the run to terminate here would prevent that abort from ever being sent.\n      await this.resumeToolCall({\n        resumeData: response,\n        toolCallId,\n        requestContext,\n        resolveOnToolEnd: true,\n      });\n      return;\n    }\n\n    const transitionModeId = this.machinery.resolveTransitionModeId();\n    if (transitionModeId && transitionModeId !== this.mode.get()) {\n      await new Promise(resolveTimeout => setTimeout(resolveTimeout, 0));\n      await this.mode.switch({ modeId: transitionModeId });\n    }\n\n    await this.resumeToolCall({ resumeData: response, toolCallId, requestContext });\n  }\n\n  /**\n   * Approve a parked tool call: drive the agent to execute it. Throws when there\n   * is no active run.\n   */\n  async approveToolCall({\n    toolCallId,\n    requestContext: requestContextInput,\n  }: {\n    toolCallId?: string;\n    requestContext?: RequestContext;\n  }): Promise<void> {\n    const runId = this.run.getRunId();\n    if (!runId) {\n      throw new Error('No active run to approve tool call for');\n    }\n\n    const agent = this.machinery.getAgent();\n    const requestContext = await this.machinery.buildRequestContext(requestContextInput);\n    const isYolo = (this.state.get() as Record<string, unknown>).yolo === true;\n    const threadId = this.thread.getId();\n    if (!threadId) {\n      throw new Error('Cannot approve a tool call without a current thread');\n    }\n    const resourceId = this.identity.getResourceId();\n    await agent.sendToolApproval({\n      threadId,\n      resourceId,\n      runId,\n      toolCallId,\n      approved: true,\n      requireToolApproval: !isYolo,\n      memory: { thread: threadId, resource: resourceId },\n      abortSignal: this.run.ensureAbortController().signal,\n      requestContext,\n      toolsets: await this.machinery.buildToolsets(requestContext),\n    });\n  }\n\n  /**\n   * Decline a parked tool call: drive the agent to reject it. Throws when there\n   * is no active run.\n   */\n  async declineToolCall({\n    toolCallId,\n    requestContext: requestContextInput,\n    declineContext,\n  }: {\n    toolCallId?: string;\n    requestContext?: RequestContext;\n    declineContext?: { reason?: string; message?: string };\n  }): Promise<void> {\n    const runId = this.run.getRunId();\n    if (!runId) {\n      throw new Error('No active run to decline tool call for');\n    }\n\n    const agent = this.machinery.getAgent();\n    const requestContext = await this.machinery.buildRequestContext(requestContextInput);\n    const isYolo = (this.state.get() as Record<string, unknown>).yolo === true;\n    const threadId = this.thread.getId();\n    if (!threadId) {\n      throw new Error('Cannot decline a tool call without a current thread');\n    }\n    const resourceId = this.identity.getResourceId();\n    await agent.sendToolApproval({\n      threadId,\n      resourceId,\n      runId,\n      toolCallId,\n      approved: false,\n      declineContext,\n      requireToolApproval: !isYolo,\n      memory: { thread: threadId, resource: resourceId },\n      abortSignal: this.run.ensureAbortController().signal,\n      requestContext,\n      toolsets: await this.machinery.buildToolsets(requestContext),\n    });\n  }\n\n  private createSubscribedResumeBoundaryWaiter({\n    toolCallId,\n    resolveOnToolEnd = false,\n  }: {\n    toolCallId: string;\n    resolveOnToolEnd?: boolean;\n  }): { promise: Promise<void>; cancel: () => void } {\n    let unsubscribe: (() => void) | undefined;\n    const promise = new Promise<void>(resolve => {\n      unsubscribe = this.subscribe(event => {\n        const isTerminal = event.type === 'tool_suspended' || event.type === 'agent_end' || event.type === 'error';\n        const completedResumedTool = resolveOnToolEnd && event.type === 'tool_end' && event.toolCallId === toolCallId;\n        if (isTerminal || completedResumedTool) {\n          unsubscribe?.();\n          resolve();\n        }\n      });\n    });\n\n    return { promise, cancel: () => unsubscribe?.() };\n  }\n\n  /**\n   * Resume a suspended tool call through the active thread subscription.\n   * Re-supplies the shared run budget so the resumed run doesn't stop mid-task\n   * on the agent's small default maxSteps.\n   *\n   * Interactive builtins (`ask_user`, `request_access`) are exempted from the\n   * approval re-check on resume: their resume schema is `z.string()` /\n   * `z.array(z.string())` which cannot carry the `{ approved }` field the\n   * approval gate demands, so re-entering the approval branch would always\n   * reject the answer. The caller already handled approval (setForTool policy,\n   * yolo mode, or a prior explicit approval gate).\n   */\n  async resumeToolCall({\n    resumeData,\n    toolCallId,\n    requestContext: requestContextInput,\n    resolveOnToolEnd = false,\n  }: {\n    resumeData: any;\n    toolCallId: string;\n    requestContext?: RequestContext;\n    resolveOnToolEnd?: boolean;\n  }): Promise<void> {\n    const suspension = this.suspensions.get({ toolCallId });\n    if (!suspension) {\n      throw new Error('No active suspension to resume');\n    }\n\n    // Resume through the agent that suspended the run. A `submit_plan` approval\n    // switches modes before resuming, but suspended snapshots are owned by their\n    // originating agent so another mode's agent cannot reclaim one by run id.\n    // An explicit, authorized run-handoff would be required to transfer ownership.\n    const agent =\n      this.machinery.getRunScope(suspension.runId)?.get(SUSPENDED_RUN_AGENT_KEY) ?? this.machinery.getAgent();\n\n    // Remove before resuming so a re-suspend during the resumed run can\n    // re-register the same toolCallId without being clobbered by this cleanup.\n    // Drop the matching display-state entry too so the UI stops rendering the\n    // resolved prompt while any other parked suspensions stay visible.\n    this.suspensions.delete({ toolCallId });\n    this.displayState.deletePendingSuspension(toolCallId);\n\n    const requestContext = await this.machinery.buildRequestContext(requestContextInput);\n    const threadId = this.thread.getId();\n    if (!threadId) {\n      throw new Error('Cannot resume a suspended tool without a current thread');\n    }\n\n    await this.thread.ensureSubscription(threadId, agent);\n    const resumedSubscriptionBoundary = this.createSubscribedResumeBoundaryWaiter({ toolCallId, resolveOnToolEnd });\n\n    try {\n      const resourceId = this.identity.getResourceId();\n      const sharedOptions = this.machinery.buildSharedRunOptions();\n      // Interactive builtins suspend to collect user input, not for approval.\n      // The resume data is the user's answer (a bare string), which the approval\n      // re-check would reject because it cannot carry an `{ approved }` field.\n      // Exempt these tools so the answer reaches the model as-is.\n      const isInteractive = suspension.toolName === 'ask_user' || suspension.toolName === 'request_access';\n      if (isInteractive) {\n        sharedOptions.requireToolApproval = false;\n      }\n      await agent.sendStreamResume({\n        threadId,\n        resourceId,\n        runId: suspension.runId,\n        toolCallId,\n        resumeData,\n        streamOptions: {\n          ...sharedOptions,\n          memory: { thread: threadId, resource: resourceId },\n          abortSignal: this.run.ensureAbortController().signal,\n          requestContext,\n          toolsets: await this.machinery.buildToolsets(requestContext),\n        },\n      });\n      await resumedSubscriptionBoundary.promise;\n    } finally {\n      resumedSubscriptionBoundary.cancel();\n      await this.thread.ensureSubscription(threadId);\n    }\n  }\n\n  /** Grant a tool category \"allow\" for the remainder of the session. */\n  grantCategory(category: ToolCategory): void {\n    this.#grantedCategories.add(category);\n  }\n\n  /** Grant an individual tool \"allow\" for the remainder of the session. */\n  grantTool(toolName: string): void {\n    this.#grantedTools.add(toolName);\n  }\n\n  /** Whether the given tool category has been granted for the session. */\n  hasCategoryGrant(category: ToolCategory): boolean {\n    return this.#grantedCategories.has(category);\n  }\n\n  /** Whether the given tool has been granted for the session. */\n  hasToolGrant(toolName: string): boolean {\n    return this.#grantedTools.has(toolName);\n  }\n\n  /** Snapshot of all session-scoped grants. */\n  getGrants(): { categories: ToolCategory[]; tools: string[] } {\n    return {\n      categories: [...this.#grantedCategories] as ToolCategory[],\n      tools: [...this.#grantedTools],\n    };\n  }\n\n  /** A copy of the running token-usage tally for the active thread. */\n  getTokenUsage(): TokenUsage {\n    return { ...this.#tokenUsage };\n  }\n\n  /**\n   * Replace the running tally, e.g. when hydrating from persisted thread\n   * metadata on thread switch.\n   */\n  setTokenUsage(usage: TokenUsage): void {\n    this.#tokenUsage = { ...usage };\n  }\n\n  /** Reset the running tally to zero, e.g. on a new/empty thread. */\n  resetTokenUsage(): void {\n    this.#tokenUsage = createEmptyTokenUsage();\n  }\n\n  /** Fold a single step's usage into the running tally. */\n  addUsage(stepUsage: TokenUsage): void {\n    this.#tokenUsage.promptTokens += stepUsage.promptTokens;\n    this.#tokenUsage.completionTokens += stepUsage.completionTokens;\n    this.#tokenUsage.totalTokens += stepUsage.totalTokens;\n    addOptionalUsageField(this.#tokenUsage, 'reasoningTokens', stepUsage.reasoningTokens);\n    addOptionalUsageField(this.#tokenUsage, 'cachedInputTokens', stepUsage.cachedInputTokens);\n    addOptionalUsageField(this.#tokenUsage, 'cacheCreationInputTokens', stepUsage.cacheCreationInputTokens);\n    addOptionalUsageField(this.#tokenUsage, 'cacheCreationInputTokens5m', stepUsage.cacheCreationInputTokens5m);\n    addOptionalUsageField(this.#tokenUsage, 'cacheCreationInputTokens1h', stepUsage.cacheCreationInputTokens1h);\n    if (stepUsage.raw !== undefined) {\n      this.#tokenUsage.raw = stepUsage.raw;\n    }\n  }\n}\n","import { z } from 'zod/v4';\n\nimport { Agent } from '../agent';\nimport type { ToolsInput, ToolsetsInput } from '../agent/types';\nimport { CHAT_CHANNEL_RENDER_CONTEXT_KEY } from '../channels/output-processor';\nimport type { MastraModelConfig } from '../llm/model/shared.types';\nimport type { Mastra } from '../mastra';\nimport { RequestContext } from '../request-context';\nimport { askUserTool } from '../tools/builtin/ask-user';\nimport { submitPlanTool } from '../tools/builtin/submit-plan';\nimport { summarizeTaskCheck } from '../tools/builtin/task-tools';\nimport { createTool } from '../tools/tool';\nimport { createWorkspaceTools } from '../workspace/tools/tools';\n\nimport type { AgentControllerRequestContext, AgentControllerSubagent } from './types';\n\n// `ask_user` is an agent-agnostic built-in tool. It is defined in\n// `../tools/builtin/ask-user` and re-exported here so the AgentController toolset and\n// existing imports keep referencing the same tool object (preserving toolset\n// identity and the prompt-cache prefix). It pauses via the native tool\n// suspension primitive rather than any controller-specific request context.\nexport { askUserTool };\n\nconst FORKED_SUBAGENT_NESTING_NOTICE =\n  'Do not call the `subagent` tool. You are currently running inside a forked subagent, and this is the maximum allowed subagent nesting level. Further subagent calls will return an error. Answer the task directly using the conversation history and the other tools available to you.';\n\nconst FORKED_SUBAGENT_TASK_NOTICE =\n  'Do not call `task_write`, `task_update`, `task_complete`, or `task_check` inside a forked subagent. Forked subagents keep the parent task-tool schemas for prompt-cache stability, but the parent agent owns the visible task list. Track forked subagent work in your final answer instead.';\n\n// `submit_plan` is an agent-agnostic built-in tool. It is defined in\n// `../tools/builtin/submit-plan` and re-exported here so the AgentController toolset and\n// existing imports keep referencing the same tool object (preserving toolset\n// identity and the prompt-cache prefix). It pauses via the native tool\n// suspension primitive rather than any controller-specific request context; the\n// AgentController layers its plan→default mode switch on top of the approval in its own\n// `respondToToolSuspension` handling.\nexport { submitPlanTool };\n\n// =============================================================================\n// Task Tools\n// =============================================================================\n//\n// The four task tools are agent-agnostic built-ins defined in\n// `../tools/builtin/task-tools`. They persist the task list through the agent\n// state-signal lane (see `../tools/builtin/task-state-processor`) and no longer\n// depend on the AgentController request context. They are re-exported here so the\n// AgentController toolset and existing imports keep referencing the same tool objects\n// (preserving toolset identity and the prompt-cache prefix).\nexport {\n  taskWriteTool,\n  taskUpdateTool,\n  taskCompleteTool,\n  taskCheckTool,\n  assignTaskIds,\n  summarizeTaskCheck,\n} from '../tools/builtin/task-tools';\nexport type {\n  TaskItem,\n  TaskItemInput,\n  TaskItemSnapshot,\n  TaskCheckResult,\n  TaskCheckSummary,\n} from '../tools/builtin/task-tools';\nexport { TaskStateProcessor } from '../tools/builtin/task-state-processor';\n\n// =============================================================================\n// Subagent Tool\n// =============================================================================\n\nexport interface CreateSubagentToolOptions {\n  subagents: AgentControllerSubagent[];\n  resolveModel: (modelId: string) => MastraModelConfig;\n  /** Resolved controller tools (already evaluated from DynamicArgument) */\n  controllerTools?: ToolsInput;\n  /** Fallback model ID when subagent definition has no defaultModelId */\n  fallbackModelId?: string;\n  /** Returns the parent model ID for display when a subagent call is forked. */\n  getParentModelId?: () => string;\n  /**\n   * Returns the parent Agent that owns the current run. Invoked when a\n   * subagent call is forked so the fork can reuse the parent's\n   * instructions, tools, and model to preserve prompt-cache prefix.\n   */\n  getParentAgent?: () => Agent | undefined;\n  /**\n   * Clones the parent thread so a forked subagent can run on a copy\n   * without polluting the parent conversation. Typically delegates to\n   * `AgentController.cloneThread`. Returns the new thread metadata.\n   */\n  cloneThreadForFork?: (opts: {\n    sourceThreadId: string;\n    resourceId?: string;\n    title?: string;\n  }) => Promise<{ id: string; resourceId: string }>;\n  /**\n   * Resolves the toolsets the parent agent runs with for the current request.\n   * When set, forked subagents inherit the parent's toolsets so controller-injected\n   * tools like `ask_user` / `submit_plan` / user-configured controller tools remain\n   * available inside the fork. The `subagent` entry is preserved for prompt-cache\n   * stability, but its runtime execute function is patched to block recursion.\n   */\n  getParentToolsets?: (requestContext?: RequestContext) => Promise<ToolsetsInput | undefined>;\n  /**\n   * Internal Mastra instance passed to each subagent Agent constructor so the\n   * bare model id resolves through the same gateways as the parent and the\n   * agent inherits pubsub/observability.\n   */\n  mastra?: Mastra;\n}\n\n/**\n * Creates a `subagent` tool from registered subagent definitions.\n * The tool spawns a fresh Agent per invocation with constrained tools,\n * streams the response, and forwards events to the controller.\n */\nexport function createSubagentTool(opts: CreateSubagentToolOptions) {\n  const { subagents, resolveModel, controllerTools, fallbackModelId, mastra } = opts;\n\n  if (subagents.length === 0) {\n    throw new Error('createSubagentTool requires at least one subagent');\n  }\n\n  const subagentIds = subagents.map(s => s.id);\n\n  const typeDescriptions = subagents.map(s => `- **${s.id}** (${s.name}): ${s.description}`).join('\\n');\n\n  return createTool({\n    id: 'subagent',\n    description: `Delegate a focused task to a specialized subagent. The subagent runs independently with a constrained toolset, then returns its findings as text.\n\nAvailable agent types:\n${typeDescriptions}\n\nBy default the subagent runs in its own context — it does NOT see the parent conversation history. Write a clear, self-contained task description.\n\nSet \\`forked: true\\` for context-dependent parallel work that needs the parent conversation, prior tool results, or the parent tool environment. Omit it for self-contained delegation. A forked subagent reuses the parent agent's instructions and tools so the prompt prefix stays cache-friendly.\n\nUse this tool when:\n- You want to run multiple investigations in parallel\n- The task is self-contained and can be delegated`,\n    inputSchema: z.object({\n      agentType: z.enum(subagentIds as [string, ...string[]]).describe('Type of subagent to spawn'),\n      task: z\n        .string()\n        .describe(\n          'Clear, self-contained description of what the subagent should do. For non-forked subagents include all relevant context — the subagent cannot see the parent conversation.',\n        ),\n      modelId: z\n        .string()\n        .optional()\n        .describe(\n          \"Optional model ID override for this task. Ignored when `forked: true` (the parent agent's model is used).\",\n        ),\n      forked: z\n        .boolean()\n        .optional()\n        .describe(\n          \"If true, fork the parent conversation: clone the parent thread and run with the parent agent's instructions/tools so prompt cache is preserved. Requires memory to be configured on the AgentController. Defaults to the subagent definition's `forked` setting.\",\n        ),\n    }),\n    execute: async (input, context) => {\n      const { agentType, modelId, forked } = input;\n      let { task } = input;\n      const displayTask = task;\n      const definition = subagents.find(s => s.id === agentType);\n      if (!definition) {\n        return {\n          content: `Unknown agent type: ${agentType}. Valid types: ${subagentIds.join(', ')}`,\n          isError: true,\n        };\n      }\n\n      const controllerCtx = context?.requestContext?.get('controller') as AgentControllerRequestContext | undefined;\n      const emitEvent = controllerCtx?.emitEvent;\n      const abortSignal = controllerCtx?.abortSignal;\n      const toolCallId = context?.agent?.toolCallId ?? 'unknown';\n      const workspace = context?.workspace;\n\n      const runAsForked = forked ?? definition.forked ?? false;\n\n      // Per-invocation state produced by either the forked or non-forked setup path.\n      let subagentToRun: Agent;\n      let resolvedModelId: string;\n      let subagentRequestContext: RequestContext | undefined;\n      let streamMemory: { thread: string; resource?: string } | undefined;\n      let streamMaxSteps: number | undefined;\n      let streamStopWhen: AgentControllerSubagent['stopWhen'];\n      let streamPrepareStep: ((args: { tools?: Record<string, unknown> }) => { activeTools: string[] }) | undefined;\n      let forkedToolsets: ToolsetsInput | undefined;\n\n      if (runAsForked) {\n        // Forked path: reuse the parent agent + a clone of the parent thread so the\n        // request prefix (system prompt + tool schemas + history) stays identical and\n        // the prompt cache hits. The subagent definition's instructions/tools/model\n        // are intentionally ignored in this path.\n        const parentAgent = opts.getParentAgent?.();\n        if (!parentAgent) {\n          return {\n            content: 'Forked subagent requires a parent agent. None is configured on this AgentController.',\n            isError: true,\n          };\n        }\n        const parentThreadId = controllerCtx?.threadId;\n        if (!parentThreadId) {\n          return {\n            content: 'Forked subagent requires an active parent thread; none is set on the AgentController.',\n            isError: true,\n          };\n        }\n        if (!opts.cloneThreadForFork) {\n          return {\n            content:\n              'Forked subagent requires memory to be configured on the AgentController so the parent thread can be cloned.',\n            isError: true,\n          };\n        }\n\n        // The parent stream batches message saves through a debounced save\n        // queue (see SaveQueueManager). If we clone straight away, the parent's\n        // user message (and the assistant turn that produced this tool call)\n        // are still in-memory, not in the store — and the clone ends up empty.\n        // Drain the queue first so the fork actually carries the prior\n        // conversation.\n        await context?.agent?.flushMessages?.().catch(() => {\n          // Non-fatal: a failed flush just means the fork may be missing the\n          // very latest turn. Still proceed with the clone.\n        });\n\n        let forkedThread: { id: string; resourceId: string };\n        try {\n          forkedThread = await opts.cloneThreadForFork({\n            sourceThreadId: parentThreadId,\n            resourceId: controllerCtx?.resourceId,\n            title: `Fork: ${definition.name} subagent`,\n          });\n        } catch (err) {\n          return {\n            content: `Failed to clone parent thread for forked subagent: ${err instanceof Error ? err.message : String(err)}`,\n            isError: true,\n          };\n        }\n\n        subagentToRun = parentAgent;\n        // Display value only; forked runs use the parent agent's configured model.\n        resolvedModelId = opts.getParentModelId?.() || 'parent-agent';\n        task = `${task}\\n\\n${FORKED_SUBAGENT_NESTING_NOTICE}\\n\\n${FORKED_SUBAGENT_TASK_NOTICE}`;\n        streamMemory = { thread: forkedThread.id, resource: forkedThread.resourceId };\n        // Allow a recovery step if the forked model accidentally calls the\n        // inherited-but-disabled `subagent` tool. Without this, the single-step\n        // default can return only the stub tool result instead of the answer.\n        streamMaxSteps = 1000;\n        streamStopWhen = undefined;\n        streamPrepareStep = undefined;\n\n        if (context?.requestContext) {\n          subagentRequestContext = new RequestContext(context.requestContext.entries());\n          if (controllerCtx) {\n            // Point at the fork so inherited tools (recall, browser, OM, memory writes, etc.)\n            // operate on the cloned thread instead of the active parent thread.\n            subagentRequestContext.set('controller', {\n              ...controllerCtx,\n              threadId: forkedThread.id,\n              resourceId: forkedThread.resourceId,\n            });\n          }\n          // The fork runs on the channel-bearing parent agent instance, so the\n          // ChatChannelOutputProcessor is attached. Clear the inherited render\n          // key so the subagent's stream never renders back to the chat\n          // platform — without this the fork would post to Slack.\n          subagentRequestContext.delete(CHAT_CHANNEL_RENDER_CONTEXT_KEY);\n        }\n\n        // Inherit the parent's toolsets with the fork request context so tools that\n        // close over request-scoped state use the cloned thread/resource. Preserve\n        // `subagent` in the tool schema to keep the prompt-cache prefix stable, but\n        // patch its runtime execute function so nested forks fail gracefully.\n        const inheritedToolsets = await opts.getParentToolsets?.(subagentRequestContext);\n        if (inheritedToolsets) {\n          forkedToolsets = {};\n          for (const [setName, setTools] of Object.entries(inheritedToolsets)) {\n            const patched: ToolsInput = {};\n            for (const [toolId, tool] of Object.entries(setTools as ToolsInput)) {\n              if (toolId === 'subagent') {\n                patched[toolId] = patchSubagentToolForFork(tool);\n              } else if (isForkedTaskToolId(toolId)) {\n                patched[toolId] = patchTaskToolForFork(tool, toolId);\n              } else {\n                patched[toolId] = tool;\n              }\n            }\n            forkedToolsets[setName] = patched;\n          }\n        }\n      } else {\n        // Non-forked path: fresh Agent with the subagent's own instructions/tools/model.\n        // Merge tools: subagent's own tools + filtered controller tools\n        const mergedTools: ToolsInput = { ...definition.tools };\n        if (definition.allowedControllerTools && controllerTools) {\n          for (const toolId of definition.allowedControllerTools) {\n            if (controllerTools[toolId] && !mergedTools[toolId]) {\n              mergedTools[toolId] = controllerTools[toolId];\n            }\n          }\n        }\n\n        // Resolve model: explicit arg → controller setting → subagent default → fallback\n        const controllerModelId = controllerCtx?.getSubagentModelId?.({ agentType }) ?? undefined;\n        const maybeModelId = modelId ?? controllerModelId ?? definition.defaultModelId ?? fallbackModelId;\n        if (!maybeModelId) {\n          return { content: 'No model ID available for subagent. Configure defaultModelId.', isError: true };\n        }\n        resolvedModelId = maybeModelId;\n\n        let model: MastraModelConfig;\n        try {\n          model = resolveModel(resolvedModelId);\n        } catch (err) {\n          return {\n            content: `Failed to resolve model \"${resolvedModelId}\": ${err instanceof Error ? err.message : String(err)}`,\n            isError: true,\n          };\n        }\n\n        subagentToRun = new Agent({\n          id: `subagent-${definition.id}`,\n          name: `${definition.name} Subagent`,\n          instructions: definition.instructions,\n          model,\n          tools: mergedTools,\n          workspace,\n          mastra,\n        });\n\n        // Only resolve workspace tool names when an allowlist is configured,\n        // avoiding unnecessary createWorkspaceTools overhead for subagents\n        // that don't restrict workspace tools.\n        const allowedWs = definition.allowedWorkspaceTools ? new Set(definition.allowedWorkspaceTools) : undefined;\n        const allWorkspaceToolNames =\n          workspace && allowedWs\n            ? new Set(\n                Object.keys(\n                  await createWorkspaceTools(workspace, {\n                    requestContext: context?.requestContext ?? {},\n                    workspace,\n                  }),\n                ),\n              )\n            : undefined;\n\n        streamMaxSteps = definition.maxSteps ?? (definition.stopWhen ? undefined : 50);\n        streamStopWhen = definition.stopWhen;\n        streamPrepareStep =\n          allowedWs && allWorkspaceToolNames\n            ? ({ tools }) => ({\n                activeTools: Object.keys(tools ?? {}).filter(k => !allWorkspaceToolNames.has(k) || allowedWs.has(k)),\n              })\n            : undefined;\n\n        // Build a request context for the subagent that inherits sandbox paths\n        // and controller state but strips threadId/resourceId so the subagent\n        // doesn't trigger OM enrichment on the parent's memory thread. This\n        // subagent runs on a fresh Agent with no channels, so no output\n        // processor attaches and it never renders to the chat platform.\n        if (context?.requestContext) {\n          subagentRequestContext = new RequestContext(context.requestContext.entries());\n          if (controllerCtx) {\n            subagentRequestContext.set('controller', {\n              ...controllerCtx,\n              threadId: null,\n              resourceId: '',\n            });\n          }\n        }\n      }\n\n      const startTime = Date.now();\n\n      emitEvent?.({\n        type: 'subagent_start',\n        toolCallId,\n        agentType,\n        task: displayTask,\n        modelId: resolvedModelId,\n        forked: runAsForked,\n      });\n\n      let partialText = '';\n\n      try {\n        const response = await subagentToRun.stream(task, {\n          maxSteps: streamMaxSteps,\n          stopWhen: streamStopWhen,\n          abortSignal,\n          requireToolApproval: false,\n          requestContext: subagentRequestContext,\n          ...(streamMemory && { memory: streamMemory }),\n          ...(forkedToolsets && { toolsets: forkedToolsets }),\n          ...(context?.tracingContext && { tracingContext: context.tracingContext }),\n          prepareStep: streamPrepareStep,\n        });\n\n        for await (const chunk of response.fullStream) {\n          switch (chunk.type) {\n            case 'text-delta':\n              partialText += chunk.payload.text;\n              emitEvent?.({\n                type: 'subagent_text_delta',\n                toolCallId,\n                agentType,\n                textDelta: chunk.payload.text,\n              });\n              break;\n\n            case 'tool-call':\n              if (!(runAsForked && chunk.payload.toolName === 'subagent')) {\n                emitEvent?.({\n                  type: 'subagent_tool_start',\n                  toolCallId,\n                  agentType,\n                  subToolName: chunk.payload.toolName,\n                  subToolArgs: chunk.payload.args,\n                });\n              }\n              break;\n\n            case 'tool-result': {\n              const isErr = chunk.payload.isError ?? false;\n              if (!(runAsForked && chunk.payload.toolName === 'subagent')) {\n                emitEvent?.({\n                  type: 'subagent_tool_end',\n                  toolCallId,\n                  agentType,\n                  subToolName: chunk.payload.toolName,\n                  subToolResult: chunk.payload.result,\n                  isError: isErr,\n                });\n              }\n              break;\n            }\n          }\n        }\n\n        if (abortSignal?.aborted) {\n          const durationMs = Date.now() - startTime;\n          const abortResult = partialText\n            ? `[Aborted by user]\\n\\nPartial output:\\n${partialText}`\n            : '[Aborted by user]';\n\n          emitEvent?.({ type: 'subagent_end', toolCallId, agentType, result: abortResult, isError: false, durationMs });\n          // Intentionally do NOT append `<subagent-meta />` to model-facing\n          // content: when the parent model can see the tag in a tool result\n          // it sometimes echoes the literal markup back into its own assistant\n          // text on the next turn. Live UIs get model/duration/tool data from\n          // the structured `subagent_*` events emitted above; history UIs read\n          // the persisted `tool_call.args.modelId`. Older persisted threads\n          // that still carry the tag are handled by `parseSubagentMeta` for\n          // backward compatibility.\n          return { content: abortResult, isError: false };\n        }\n\n        const fullOutput = await response.getFullOutput();\n        const resultText = fullOutput.text || partialText;\n\n        const durationMs = Date.now() - startTime;\n        emitEvent?.({ type: 'subagent_end', toolCallId, agentType, result: resultText, isError: false, durationMs });\n\n        return { content: resultText, isError: false };\n      } catch (err) {\n        const isAbort =\n          err instanceof Error &&\n          (err.name === 'AbortError' || err.message?.includes('abort') || err.message?.includes('cancel'));\n        const durationMs = Date.now() - startTime;\n\n        if (isAbort) {\n          const abortResult = partialText\n            ? `[Aborted by user]\\n\\nPartial output:\\n${partialText}`\n            : '[Aborted by user]';\n\n          emitEvent?.({ type: 'subagent_end', toolCallId, agentType, result: abortResult, isError: false, durationMs });\n\n          return { content: abortResult, isError: false };\n        }\n\n        const message = err instanceof Error ? err.message : String(err);\n        emitEvent?.({ type: 'subagent_end', toolCallId, agentType, result: message, isError: true, durationMs });\n\n        return { content: `Subagent \"${definition.name}\" failed: ${message}`, isError: true };\n      }\n    },\n  });\n}\n\n/**\n * Returns a copy of the parent's `subagent` tool with `execute` replaced by a\n * stub that refuses to dispatch a nested fork.\n *\n * Why patch instead of remove or replace wholesale:\n *  - Forked subagents reuse the parent Agent's `stream()` so the LLM request\n *    prefix (system prompt + tool list + tool schemas + tool descriptions)\n *    matches the parent byte-for-byte. This is what makes prompt-cache hits\n *    possible inside a fork, which is the whole reason forked mode exists.\n *  - Removing the `subagent` entry from the inherited toolset, or replacing\n *    its description / parameters with anything else, perturbs that prefix\n *    and invalidates the cache.\n *  - Replacing only `execute` is invisible to the LLM (execute lives in the\n *    runtime, not in the request payload) but lets us reject recursive\n *    invocations cleanly at runtime.\n *\n * The stub returns a tool-level error result with a clear human-readable\n * recovery instruction. This does not fail the outer subagent run; the model\n * receives the tool error and can continue with a direct answer.\n */\nfunction patchSubagentToolForFork(tool: unknown): any {\n  const stubExecute = async () => ({\n    content: FORKED_SUBAGENT_NESTING_NOTICE,\n    isError: true,\n  });\n  // Spread preserves id / description / inputSchema / parameters / outputSchema\n  // / providerOptions / strict / requireApproval / etc. on whatever shape the\n  // tool came in as (Mastra `Tool` instance, AI SDK v4/v5 `tool({ ... })`\n  // object, provider-defined tool). `Object.assign` on a fresh object keeps\n  // own enumerable props; that is enough for the toolset-merge layer to\n  // serialize the same schema/description into the model request.\n  return Object.assign({}, tool as Record<string, unknown>, { execute: stubExecute });\n}\n\nfunction isForkedTaskToolId(toolId: string): boolean {\n  return toolId === 'task_write' || toolId === 'task_update' || toolId === 'task_complete' || toolId === 'task_check';\n}\n\nfunction patchTaskToolForFork(tool: unknown, toolId: string): any {\n  const stubExecute = async () => {\n    const baseResult = {\n      content: FORKED_SUBAGENT_TASK_NOTICE,\n      tasks: [],\n      isError: true,\n    };\n\n    if (toolId === 'task_check') {\n      const taskCheck = summarizeTaskCheck([]);\n      return {\n        ...baseResult,\n        summary: taskCheck.summary,\n        incompleteTasks: taskCheck.incompleteTasks,\n      };\n    }\n\n    return baseResult;\n  };\n\n  return Object.assign({}, tool as Record<string, unknown>, { execute: stubExecute });\n}\n\n/**\n * Parse subagent metadata from a tool result string.\n *\n * Older persisted threads may have an internal `<subagent-meta />` tag\n * appended to the subagent tool result content (carrying modelId / durationMs\n * / sub-tool-call summary, used by history-render UIs to reconstruct the\n * subagent activity box when live events aren't available).\n *\n * New runs no longer append the tag — the metadata leaked into model context\n * and could be echoed back as visible assistant text — but this parser is\n * retained so existing threads continue to render cleanly. It also strips the\n * tag so callers never display it to users.\n *\n * Returns the cleaned text plus any parsed metadata.\n */\nexport function parseSubagentMeta(content: string): {\n  text: string;\n  modelId?: string;\n  durationMs?: number;\n  toolCalls?: Array<{ name: string; isError: boolean }>;\n} {\n  const match = content.match(/\\n<subagent-meta modelId=\"([^\"]*)\" durationMs=\"(\\d+)\" tools=\"([^\"]*)\" \\/>$/);\n  if (!match) return { text: content };\n\n  const text = content.slice(0, match.index!);\n  const modelId = match[1];\n  const durationMs = parseInt(match[2]!, 10);\n  const toolCalls = match[3]\n    ? match[3]\n        .split(',')\n        .filter(Boolean)\n        .map(entry => {\n          const [name, status] = entry.split(':');\n          return { name: name!, isError: status === 'err' };\n        })\n    : [];\n\n  return { text, modelId, durationMs, toolCalls };\n}\n","import { Agent } from '../agent';\nimport { MessageList } from '../agent/message-list';\nimport type { MastraDBMessage, MastraMessageContentV2 } from '../agent/message-list/state/types';\nimport { isUserAuthoredMessage } from '../agent/signals';\nimport type { ActiveThreadRun } from '../agent/thread-stream-runtime';\nimport type { AgentInstructions, ToolsInput, ToolsetsInput } from '../agent/types';\nimport type { MastraBrowser } from '../browser/browser';\nimport { AgentControllerChannels } from '../channels/agent-controller-channels';\nimport { GatewayManager } from '../llm/model/gateways';\nimport { defaultGateways } from '../llm/model/gateways/defaults';\nimport type { MastraModelConfig } from '../llm/model/shared.types';\nimport { Mastra } from '../mastra';\nimport { TITLE_PINNED_THREAD_METADATA_KEY } from '../memory';\nimport type { MastraMemory } from '../memory/memory';\nimport type { StorageThreadType } from '../memory/types';\nimport type { TracingContext, TracingOptions } from '../observability';\nimport { RequestContext } from '../request-context';\nimport type { MastraCompositeStore } from '../storage/base';\nimport type { MemoryStorage } from '../storage/domains/memory/base';\nimport type { ObservationalMemoryRecord, StorageListMessagesInput, StorageListMessagesOutput } from '../storage/types';\nimport type { DynamicArgument } from '../types';\nimport { Workspace } from '../workspace/workspace';\n\nimport { Session } from './session';\nimport type { ThreadDataStore } from './session';\nimport {\n  askUserTool,\n  createSubagentTool,\n  submitPlanTool,\n  taskCheckTool,\n  taskCompleteTool,\n  taskUpdateTool,\n  taskWriteTool,\n} from './tools';\nimport type {\n  AvailableModel,\n  IntervalHandler,\n  AgentControllerConfig,\n  AgentControllerMode,\n  AgentControllerRequestContext,\n  AgentControllerRequestStateUpdater,\n  AgentControllerSessionCreatedListener,\n  AgentControllerSessionCreatedOptions,\n  AgentControllerSessionDeletedListener,\n  AgentControllerThread,\n  ModelAuthStatus,\n  ToolCategory,\n} from './types';\n\n/**\n * Registry key for the session map. JSON-encodes the (resourceId, scope) pair\n * so the key is collision-proof for arbitrary strings: a scoped session can\n * never collide with an unscoped one or with a different resource/scope split\n * (e.g. `(\"a\\0b\", \"c\")` vs `(\"a\", \"b\\0c\")`).\n */\nfunction sessionRegistryKey(resourceId: string, scope?: string): string {\n  return JSON.stringify([resourceId, scope ?? null]);\n}\n\nfunction validateModes(modes: AgentControllerMode[]): void {\n  const modeIds = new Set<string>();\n\n  for (const mode of modes) {\n    if (modeIds.has(mode.id)) {\n      throw new Error(`Duplicate mode id \"${mode.id}\" found when creating the AgentController`);\n    }\n\n    modeIds.add(mode.id);\n\n    const modeRecord = mode as unknown as { id: string; tools?: unknown; additionalTools?: unknown };\n    if (modeRecord.tools && modeRecord.additionalTools) {\n      throw new Error(\n        `Mode \"${modeRecord.id}\" cannot set both \"tools\" and \"additionalTools\" - choose replace OR augment`,\n      );\n    }\n  }\n\n  for (const mode of modes) {\n    if (mode.transitionsTo === mode.id) {\n      throw new Error(`Mode \"${mode.id}\" transitionsTo cannot reference itself`);\n    }\n    if (mode.transitionsTo && !modeIds.has(mode.transitionsTo)) {\n      throw new Error(`Mode \"${mode.id}\" transitionsTo references unknown mode \"${mode.transitionsTo}\"`);\n    }\n  }\n}\n\n/**\n * Build a user-facing message for a non-success stream finish reason.\n *\n * Anthropic's classifier blocks / model refusals (e.g. `claude-fable-5`) surface\n * through the AI SDK as a `content-filter` finish reason, with details on\n * `providerMetadata.anthropic.stopDetails`. Without explicit handling these\n * runs end on an empty assistant message with no error, so the run appears to\n * silently stop. Returning a message here lets the controller finalize the run\n * into an explicit terminal error state.\n */\n/**\n * The Anthropic model that `claude-fable-5` runs are automatically retried on\n * server-side when fable-5's safety classifiers block a turn. See\n * {@link buildFableFallbackProviderOptions}.\n */\nconst FABLE_FALLBACK_MODEL = 'claude-opus-4-8';\n\n/**\n * Step budget applied to every controller-driven agent run.\n *\n * This MUST be passed to both the initial stream and `resumeStream`: when a run\n * suspends on an interactive tool (e.g. `ask_user`) and then resumes, the\n * resumed call merges over the agent's *default* options, whose `maxSteps` is\n * small (~5). Without re-supplying this budget the resumed run is silently\n * capped and ends with `reason:\"complete\"` after a few steps — the agent stops\n * mid-task even though it promised to continue. See {@link buildSharedRunOptions}.\n */\nconst CONTROLLER_MAX_STEPS = 1000;\n\n/**\n * Returns Anthropic `providerOptions` that enable a server-side fallback to\n * {@link FABLE_FALLBACK_MODEL} when the active model is `claude-fable-5`, and\n * `undefined` otherwise.\n *\n * fable-5 can have a turn blocked server-side by its safety classifiers. With\n * a fallback configured, Anthropic transparently retries the blocked turn on\n * the fallback model and returns that model's answer instead of refusing. If\n * the whole chain refuses, the run still ends on a `content-filter` finish\n * reason, which is handled as a terminal error.\n *\n * The match is suffix-based so it covers `anthropic/claude-fable-5`, a bare\n * `claude-fable-5`, and any pack/provider-prefixed form.\n */\nexport function buildFableFallbackProviderOptions(\n  modelId: string,\n): { anthropic: { fallbacks: { model: string }[] } } | undefined {\n  if (!/(^|\\/)claude-fable-5$/.test(modelId)) {\n    return undefined;\n  }\n  return { anthropic: { fallbacks: [{ model: FABLE_FALLBACK_MODEL }] } };\n}\n\n/**\n * Build a user-facing notice when a turn was served by an Anthropic\n * server-side fallback model instead of the primary model.\n *\n * When the primary model's safety classifiers decline a turn and a fallback\n * chain is configured (see {@link buildFableFallbackProviderOptions}), the API\n * transparently retries on the fallback model and reports this via\n * `fallback_message` entries in `providerMetadata.anthropic.iterations`.\n * Without a notice the user has no way to tell that the response did not come\n * from the model they selected.\n */\n\n/** How much of the tail a rename reads: enough to say where the thread went, bounded so a long thread costs no more than a short one. */\nconst TITLE_WINDOW_MESSAGES = 20;\n\n/**\n * The AgentController orchestrates multiple agent modes, shared state, memory, and storage.\n * It's the core abstraction that a TUI (or other UI) controls.\n *\n * @example\n * ```ts\n * const controller = new AgentController({\n *   id: \"my-coding-agent\",\n *   storage: new LibSQLStore({ url: \"file:./data.db\" }),\n *   stateSchema: z.object({\n *     currentModelId: z.string().optional(),\n *   }),\n *   modes: [\n *     { id: \"plan\", name: \"Plan\", default: true, agent: planAgent },\n *     { id: \"build\", name: \"Build\", agent: buildAgent },\n *   ],\n * })\n *\n * controller.subscribe((event) => {\n *   if (event.type === \"message_update\") appendText(event.id, event.event.delta)\n * })\n *\n * await controller.init()\n * await controller.sendMessage({ content: \"Hello!\" })\n * ```\n */\nexport class AgentController<TState = {}> {\n  readonly id: string;\n\n  private config: AgentControllerConfig<TState>;\n  private initPromise: Promise<void> | undefined = undefined;\n  private browser: DynamicArgument<MastraBrowser | undefined> = undefined;\n  private workspace: DynamicArgument<Workspace | undefined> = undefined;\n  private intervalTimers = new Map<string, { timer: NodeJS.Timeout; shutdown?: () => void | Promise<void> }>();\n  /**\n   * The mode every new session starts in. Resolved once at construction from\n   * `config.defaultModeId` (or the configured default/first mode) and reused by\n   * every {@link createSession} call. The AgentController itself holds no session.\n   */\n  readonly #defaultMode: AgentControllerMode;\n  /**\n   * Live sessions created by {@link createSession}, keyed by resourceId plus an\n   * optional caller-provided scope (see {@link sessionRegistryKey}). A\n   * (resourceId, scope) pair maps to exactly one session per AgentController\n   * (get-or-create). Stores the in-flight creation promise so concurrent calls\n   * share one session. Lets AgentController-external callers (e.g. notification\n   * delivery) resolve \"the session that owns this resource\" so a woken run uses\n   * that session's model/mode/state instead of an arbitrary one.\n   */\n  readonly #sessionsByResource = new Map<string, Promise<Session<TState>>>();\n  readonly #sessionCreatedListeners: Array<{\n    listener: AgentControllerSessionCreatedListener<TState>;\n    blocking: boolean;\n  }> = [];\n  readonly #sessionDeletedListeners: AgentControllerSessionDeletedListener<TState>[] = [];\n  /**\n   * In-progress deletions keyed by registry key, so {@link createSession} can\n   * wait for a concurrent deletion to finish before returning a (torn-down)\n   * session. Set synchronously before any await so the flag is visible to\n   * concurrent callers.\n   */\n  readonly #deletionsInProgress = new Map<string, Promise<void>>();\n  /**\n   * Sessions currently being torn down, so {@link setResourceId} can refuse to\n   * re-key a dying session and {@link createSession} can avoid returning one.\n   * Populated inside the deletion IIFE after `await pending` resolves the\n   * session.\n   */\n  readonly #sessionsBeingDeleted = new WeakSet<Session<TState>>();\n  /**\n   * Per-session deletion promise (rejection-tolerant), keyed by the Session\n   * object so {@link createSession} and {@link setResourceId} can wait on a\n   * deletion they discovered via {@link #sessionsBeingDeleted} without knowing\n   * the original registry key.\n   */\n  readonly #sessionDeletionPromises = new WeakMap<Session<TState>, Promise<void>>();\n  /**\n   * The scope each live session was created under, so re-keying operations\n   * (e.g. {@link setResourceId}) preserve the session's registry scope.\n   */\n  readonly #sessionScopes = new WeakMap<Session<TState>, string>();\n  private availableModelsCache: AvailableModel[] | null = null;\n  private availableModelsCacheTime: number = 0;\n  readonly #instructions?: string;\n  #internalMastra: Mastra | undefined = undefined;\n  /**\n   * Set when this AgentController is registered on a parent Mastra (via\n   * {@link __registerMastra}). When present it is used in place of the\n   * lazily-created internal Mastra, so a server-hosted AgentController shares the\n   * server's storage/agents/gateways instead of spinning up its own.\n   */\n  #externalMastra: Mastra | undefined = undefined;\n  #gatewayManager: GatewayManager | undefined = undefined;\n  #legacyAgentMode: Record<string, Agent<any, any, any, any>> = {};\n  /** Chat channels running this controller inside messaging threads (from `config.channels`). */\n  #channels: AgentControllerChannels | null = null;\n\n  constructor(config: AgentControllerConfig<TState>) {\n    validateModes(config.modes);\n\n    this.id = config.id;\n    this.config = config;\n    this.#instructions = config.instructions;\n    if (config.channels) {\n      this.#channels = new AgentControllerChannels(config.channels);\n      this.#channels.__setController(this);\n    }\n    // Gateway manager merges configured gateways with the router defaults\n    // (custom takes precedence). Shared by listAvailableModels,\n    // getCurrentModelAuthStatus, and the OM model resolver.\n    this.#gatewayManager = new GatewayManager([...(config.gateways ?? []), ...defaultGateways]);\n\n    const defaultMode = config.defaultModeId\n      ? config.modes.find(mode => mode.id === config.defaultModeId)\n      : (config.modes.find(mode => mode.default || mode.metadata?.default === true) ?? config.modes[0]);\n    if (!defaultMode) {\n      throw new Error(\n        config.defaultModeId\n          ? `Default mode not found: ${config.defaultModeId}`\n          : 'AgentController requires at least one agent mode',\n      );\n    }\n\n    this.#defaultMode = defaultMode;\n\n    this.workspace = config.workspace;\n    this.browser = config.browser;\n  }\n\n  /**\n   * Subscribe to process-local notifications for newly materialized sessions.\n   * Cached `createSession()` calls do not notify listeners again.\n   *\n   * Async listeners are fire-and-forget by default. Pass `blocking: true` to\n   * make `createSession()` await the listener before resolving — for setup that\n   * must land before the caller can start a run (e.g. seeding session state\n   * from storage). Blocking listeners run sequentially in registration order,\n   * before fire-and-forget listeners are notified. Failures are isolated and\n   * logged, never thrown — session creation stays best-effort with respect to\n   * listener setup. A blocking listener must not call `createSession()` for\n   * the same `(resourceId, scope)` it is initializing: that lookup awaits the\n   * in-flight creation that is awaiting the listener, which deadlocks.\n   */\n  onSessionCreated(\n    listener: AgentControllerSessionCreatedListener<TState>,\n    options?: AgentControllerSessionCreatedOptions,\n  ): () => void {\n    const entry = { listener, blocking: options?.blocking === true };\n    this.#sessionCreatedListeners.push(entry);\n    return () => {\n      const index = this.#sessionCreatedListeners.indexOf(entry);\n      if (index !== -1) {\n        this.#sessionCreatedListeners.splice(index, 1);\n      }\n    };\n  }\n\n  async #notifySessionCreated(session: Session<TState>): Promise<void> {\n    const entries = [...this.#sessionCreatedListeners];\n    // Blocking listeners complete sequentially, in registration order, before\n    // fire-and-forget listeners can observe the session.\n    for (const { listener, blocking } of entries) {\n      if (!blocking) continue;\n      try {\n        await listener(session);\n      } catch (error) {\n        console.error('Error in session-created listener:', error);\n      }\n    }\n    for (const { listener, blocking } of entries) {\n      if (blocking) continue;\n      try {\n        const result = listener(session);\n        if (result && typeof result === 'object' && 'catch' in result) {\n          (result as Promise<void>).catch(error => console.error('Error in session-created listener:', error));\n        }\n      } catch (error) {\n        console.error('Error in session-created listener:', error);\n      }\n    }\n  }\n\n  /**\n   * Subscribe to process-local notifications after live sessions are torn\n   * down. Fires even when teardown cleanup fails — the session is\n   * deregistered either way.\n   */\n  onSessionDeleted(listener: AgentControllerSessionDeletedListener<TState>): () => void {\n    this.#sessionDeletedListeners.push(listener);\n    return () => {\n      const index = this.#sessionDeletedListeners.indexOf(listener);\n      if (index !== -1) {\n        this.#sessionDeletedListeners.splice(index, 1);\n      }\n    };\n  }\n\n  #notifySessionDeleted(session: Session<TState>): void {\n    for (const listener of [...this.#sessionDeletedListeners]) {\n      try {\n        const result = listener(session);\n        if (result && typeof result === 'object' && 'catch' in result) {\n          (result as Promise<void>).catch(error => console.error('Error in session-deleted listener:', error));\n        }\n      } catch (error) {\n        console.error('Error in session-deleted listener:', error);\n      }\n    }\n  }\n\n  /**\n   * Wire a freshly-constructed {@link Session} to this AgentController: install the\n   * thread-settings store, resolvers (mode/model/om/permissions/subagents),\n   * thread data store, and seed the initial mode + model. Returns the same\n   * session for convenient assignment.\n   *\n   * The session owns its own event bus, so the AgentController no longer injects an\n   * `emit` callback — `#wireSession` only injects genuinely AgentController-owned\n   * dependencies (config catalog, resolvers, tracker, thread store). Extracted\n   * from the constructor so additional sessions can be wired the same way.\n   */\n  #wireSession(session: Session<TState>): Session<TState> {\n    const defaultMode = this.#defaultMode;\n    session.mode.set({ modeId: defaultMode.id });\n    session.setStore({\n      get: key => session.thread.getSetting({ key }),\n      set: (key, value) => session.thread.setSetting({ key, value }),\n    });\n    session.setCategoryResolver(toolName => this.getToolCategory({ toolName }));\n    session.setSubagentNameResolver(agentType => this.getSubagentDisplayName(agentType));\n    session.mode.setResolver(modeId => this.config.modes.find(m => m.id === modeId) ?? null);\n    session.model.setResolver({\n      getCurrentModeId: () => session.mode.get(),\n      trackModelUse: this.config.modelUseCountTracker,\n    });\n    session.om.setResolver({\n      getState: () => session.state.get() as Record<string, unknown>,\n      setState: updates => void session.state.set(updates as Partial<TState>),\n      setSetting: ({ key, value }) => session.thread.setSetting({ key, value }),\n      omConfig: this.config.omConfig,\n      gateways: this.config.gateways ?? [],\n    });\n    session.permissions.setResolver({\n      getState: () => session.state.get() as Record<string, unknown>,\n      setState: updates => session.state.set(updates as Partial<TState>),\n    });\n    session.subagents.setResolver({\n      getState: () => session.state.get() as Record<string, unknown>,\n      setState: updates => void session.state.set(updates as Partial<TState>),\n      setSetting: ({ key, value }) => session.thread.setSetting({ key, value }),\n    });\n    session.thread.connect(this.createThreadDataStore(session), session as Session);\n    session.setMachinery({\n      getAgent: () => this.getCurrentAgent(session),\n      getRunScope: runId => this.getMastra()?.__getRunScope(runId),\n      subscribeToThread: ({ agent, resourceId, threadId }) =>\n        (agent ?? this.getCurrentAgent(session)).subscribeToThread({ resourceId, threadId }),\n      buildStreamOptions: input => this.buildAgentMessageStreamOptions({ session, ...input }),\n      buildSharedRunOptions: () => this.buildSharedRunOptions(session),\n      buildToolsets: requestContext => this.buildToolsets(session, requestContext),\n      buildRequestContext: requestContext => this.buildRequestContext(session, requestContext),\n      persistTokenUsage: () => this.persistTokenUsage(session),\n      generateId: () => this.generateId(),\n      resolveTransitionModeId: () => this.resolveTransitionModeId(session),\n      saveSystemReminder: input => this.saveSystemReminder(input),\n    });\n\n    // Seed the selected model: an explicit initialState.currentModelId wins,\n    // otherwise fall back to the default mode's model. The model lives on the\n    // session, not in persisted state, so initialState.currentModelId is read\n    // here as a construction-time input only.\n    const initialModelId = (this.config.initialState as { currentModelId?: string } | undefined)?.currentModelId;\n    if (initialModelId) {\n      session.model.set({ modelId: initialModelId });\n    } else if (defaultMode.defaultModelId) {\n      session.model.set({ modelId: defaultMode.defaultModelId });\n    }\n\n    return session;\n  }\n\n  /**\n   * Create a new, fully-wired {@link Session} and bring it online: it starts in\n   * the default mode with the seeded model, is connected to the AgentController's shared\n   * machinery (agent, storage/lock, config catalog), and has a current thread\n   * (the most recent thread for `resourceId`, or a freshly created one).\n   *\n   * The AgentController owns no session of its own — every consumer creates its own\n   * session and drives all work through it (`session.sendMessage`,\n   * `session.mode.switch`, `session.thread.*`, `session.subscribe`, ...). In a\n   * server / multiplayer setting, each request / thread / user gets its own\n   * session, isolated from every other: independent event bus, mode, model,\n   * state, and current thread.\n   *\n   * Call {@link init} once before creating sessions so shared storage and\n   * workspace are ready.\n   *\n   * @param id - Stable session identifier (mirrors `SessionRecord.id`). Defaults to the controller `id`.\n   * @param ownerId - Stable session owner (mirrors `SessionRecord.ownerId`). Defaults to the controller `id`.\n   * @param resourceId - Memory resource to bind this session to. Defaults to the controller `resourceId` or `id`.\n   */\n  async createSession({\n    resourceId,\n    ownerId,\n    id,\n    scope,\n    tags,\n    threadId,\n    workspace,\n    browser,\n    requestContext,\n  }: {\n    resourceId?: string;\n    id?: string;\n    ownerId?: string;\n    /**\n     * Optional isolation scope within a resourceId. Two `createSession` calls\n     * with the same resourceId but different scopes get two independent\n     * sessions (own run loop, thread binding, mode/model/state) instead of\n     * resolving to the same one. Memory/threads still belong to the shared\n     * resourceId. Used by hosts that run parallel sessions over one resource —\n     * e.g. one session per git worktree, with the worktree path as the scope.\n     */\n    scope?: string;\n    /**\n     * Arbitrary string tags that scope this session. Each tag is seeded into the\n     * session's state and used to filter initial thread selection: a thread is a\n     * resume candidate only when its metadata matches every provided tag. This\n     * lets worktrees sharing a resourceId each resume their own thread (via a\n     * `projectPath` tag) and leaves room for future scoping dimensions without\n     * changing the API. Falls back to `initialState` when omitted.\n     */\n    tags?: Record<string, string>;\n    /** Exact thread id to bind during session creation. Existing threads are resumed; missing threads are created with this id. */\n    threadId?: string;\n    workspace?: Workspace;\n    browser?: MastraBrowser;\n    requestContext?: RequestContext;\n  } = {}): Promise<Session<TState>> {\n    const effectiveResourceId = resourceId ?? this.config.resourceId ?? this.config.id;\n    const effectiveSessionId = id ?? this.config.id;\n    const effectiveOwnerId = ownerId ?? this.config.id;\n    const registryKey = sessionRegistryKey(effectiveResourceId, scope);\n\n    // Get-or-create loop: a (resourceId, scope) pair maps to exactly one\n    // durable session per AgentController. Asking for the same resource+scope\n    // twice returns the same session, so a user/thread always resumes their own\n    // session and notification delivery reuses it rather than spawning a\n    // split-brain duplicate. Cache the in-flight promise so concurrent calls\n    // for the same resource+scope resolve to one session.\n    //\n    // The loop also serializes against concurrent deleteSession: if a deletion\n    // is in progress (or starts during an await), wait for it to finish, then\n    // retry so the caller gets a fresh session instead of a torn-down one.\n    for (;;) {\n      // Wait for any in-progress deletion before looking up the registry.\n      let pendingDeletion = this.#deletionsInProgress.get(registryKey);\n      if (pendingDeletion) await pendingDeletion;\n\n      const existing = this.#sessionsByResource.get(registryKey);\n      if (existing) {\n        const session = await existing;\n        // A deletion may have started during the await — either for this key\n        // (tracked in #deletionsInProgress) or for a previous key if\n        // setResourceId re-registered the session (tracked in\n        // #sessionsBeingDeleted + #sessionDeletionPromises).\n        pendingDeletion = this.#deletionsInProgress.get(registryKey);\n        if (pendingDeletion) {\n          await pendingDeletion;\n          continue;\n        }\n        if (this.#sessionsBeingDeleted.has(session)) {\n          const sessionDeletion = this.#sessionDeletionPromises.get(session);\n          if (sessionDeletion) await sessionDeletion;\n          // Evict the dead session's registry entry so the retry finds a\n          // fresh slot instead of the same dead session forever.\n          this.#sessionsByResource.delete(registryKey);\n          continue;\n        }\n        // An exact thread binding is part of the createSession contract\n        // (\"existing threads are resumed; missing threads are created with this\n        // id\"), so honor it on cached sessions too. Without this, whichever\n        // request creates the session first wins: a thread-agnostic caller (SSE\n        // subscribe, message listing) racing ahead of an exact-thread create\n        // would leave the session bound to a different thread and the requested\n        // thread never created.\n        if (threadId && session.thread.getId() !== threadId) {\n          const existingThread = await session.thread.getById({ threadId });\n          if (existingThread) {\n            if (existingThread.resourceId !== effectiveResourceId) {\n              throw new Error(`Thread not found: ${threadId}`);\n            }\n            await session.thread.switch({ threadId });\n          } else {\n            await session.thread.create({ id: threadId });\n          }\n        }\n        // A deletion may have started during the thread-rebinding awaits.\n        pendingDeletion = this.#deletionsInProgress.get(registryKey);\n        if (pendingDeletion) {\n          await pendingDeletion;\n          continue;\n        }\n        if (this.#sessionsBeingDeleted.has(session)) {\n          const sessionDeletion = this.#sessionDeletionPromises.get(session);\n          if (sessionDeletion) await sessionDeletion;\n          // Evict the dead session's registry entry so the retry finds a\n          // fresh slot instead of the same dead session forever.\n          this.#sessionsByResource.delete(registryKey);\n          continue;\n        }\n        return session;\n      }\n\n      const creation = this.#createSessionForResource(effectiveOwnerId, effectiveSessionId, effectiveResourceId, tags, {\n        scope,\n        threadId,\n        workspace,\n        browser,\n        requestContext,\n      });\n      this.#sessionsByResource.set(registryKey, creation);\n      try {\n        const session = await creation;\n        // A deletion may have started during creation.\n        pendingDeletion = this.#deletionsInProgress.get(registryKey);\n        if (pendingDeletion) {\n          await pendingDeletion;\n          continue;\n        }\n        if (scope !== undefined) this.#sessionScopes.set(session, scope);\n        return session;\n      } catch (error) {\n        // Don't cache a failed creation — let the next call retry.\n        if (this.#sessionsByResource.get(registryKey) === creation) {\n          this.#sessionsByResource.delete(registryKey);\n        }\n        throw error;\n      }\n    }\n  }\n\n  async #createSessionForResource(\n    ownerId: string,\n    id: string,\n    effectiveResourceId: string,\n    tags?: Record<string, string>,\n    overrides?: {\n      scope?: string;\n      threadId?: string;\n      workspace?: Workspace;\n      browser?: MastraBrowser;\n      requestContext?: RequestContext;\n    },\n  ): Promise<Session<TState>> {\n    // Seed the session's tags into its state so thread tagging + the workspace\n    // factory resolve against this session's scope (e.g. its `projectPath`), not\n    // the controller-global default (which, on a multi-session server, may point at\n    // a different repo).\n    const requestContext = overrides?.requestContext ?? new RequestContext();\n    let initialState = structuredClone(this.config.initialState);\n    if (tags && Object.keys(tags).length > 0) {\n      initialState = { ...initialState, ...tags } as TState;\n    }\n    const defaultMode = this.#defaultMode;\n    requestContext.set('controller', {\n      controllerId: this.id,\n      harnessId: this.id,\n      state: initialState,\n      getState: () => initialState,\n      setState: (updates: Partial<TState>) => {\n        initialState = { ...initialState, ...updates };\n      },\n      updateState: (updater: AgentControllerRequestStateUpdater<TState, unknown>) => {\n        return Promise.resolve(updater(initialState as Readonly<TState>)).then(result => {\n          if (result.updates) {\n            initialState = { ...initialState, ...result.updates };\n          }\n          return result.result;\n        });\n      },\n      threadId: null,\n      resourceId: effectiveResourceId,\n      scope: overrides?.scope,\n      session: {\n        id,\n        ownerId,\n        resourceId: effectiveResourceId,\n        modeId: defaultMode.id,\n        modelId: defaultMode.defaultModelId ?? '',\n        state: {\n          get: () => initialState as Readonly<TState>,\n          set: (updates: Partial<TState>) => {\n            initialState = { ...initialState, ...updates };\n            return Promise.resolve();\n          },\n          update: <TResult>(updater: AgentControllerRequestStateUpdater<TState, TResult>) => {\n            return Promise.resolve(updater(initialState as Readonly<TState>)).then(result => {\n              if (result.updates) {\n                initialState = { ...initialState, ...result.updates };\n              }\n              return result.result;\n            });\n          },\n        },\n      },\n      getSubagentModelId: (params?: { agentType?: string }) => {\n        const sub = this.config.subagents?.find(s => s.id === params?.agentType);\n        return sub?.defaultModelId ?? null;\n      },\n    });\n\n    let workspaceToConnect = overrides?.workspace ?? this.workspace;\n    if (typeof workspaceToConnect === 'function') {\n      workspaceToConnect = await workspaceToConnect({ requestContext, mastra: this.getMastra() });\n    }\n\n    let browserToConnect = overrides?.browser ?? this.browser;\n    if (typeof browserToConnect === 'function') {\n      browserToConnect = await browserToConnect({ requestContext, mastra: this.getMastra() });\n    }\n\n    const session = this.#wireSession(\n      new Session({\n        resourceId: effectiveResourceId,\n        id,\n        ownerId,\n        tags,\n        state: {\n          initialState,\n          stateSchema: this.config.stateSchema,\n        },\n        workspace: workspaceToConnect,\n        browser: browserToConnect,\n      }),\n    );\n\n    if (overrides?.threadId) {\n      const existingThread = await session.thread.getById({ threadId: overrides.threadId });\n      if (existingThread) {\n        if (existingThread.resourceId !== effectiveResourceId) {\n          throw new Error(`Thread not found: ${overrides.threadId}`);\n        }\n        await this.config.threadLock?.acquire(existingThread.id);\n        session.thread.set({ threadId: existingThread.id });\n        await session.thread.loadMetadata();\n        await session.thread.ensureCurrentSubscription();\n      } else {\n        await session.thread.create({ id: overrides.threadId });\n      }\n    } else {\n      // Same scope `thread.create()` stamps, matched strictly: a thread outside\n      // this session's scope — including one carrying no scope at all — belongs\n      // to nobody here and must not be auto-resumed.\n      const scopeEntries = Object.entries(session.getThreadScope());\n\n      const threads = await session.thread.list();\n      const candidates = threads.filter(t => {\n        const metadata = (t.metadata as Record<string, unknown> | undefined) ?? {};\n        return scopeEntries.every(([key, value]) => metadata[key] === value);\n      });\n\n      if (candidates.length === 0) {\n        await session.thread.create();\n      } else {\n        const mostRecent = [...candidates].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())[0]!;\n        await this.config.threadLock?.acquire(mostRecent.id);\n        session.thread.set({ threadId: mostRecent.id });\n        await session.thread.loadMetadata();\n        await session.thread.ensureCurrentSubscription();\n      }\n    }\n\n    await this.#notifySessionCreated(session);\n    return session;\n  }\n\n  /**\n   * Resolve a live session by resourceId (and optional scope), if one was\n   * created for it via {@link createSession}. Returns `undefined` when no\n   * session owns the resource. Used by notification delivery to run woken\n   * signals as the session that owns the target thread, rather than an\n   * arbitrary session.\n   */\n  async getSessionByResource(resourceId: string, scope?: string): Promise<Session<TState> | undefined> {\n    return this.#sessionsByResource.get(sessionRegistryKey(resourceId, scope));\n  }\n\n  /**\n   * Tear down the live session registered for a resource and optional scope.\n   * This only removes runtime state; persisted threads and messages remain.\n   * Returns `false` when no live session is registered.\n   */\n  async deleteSession({ resourceId, scope }: { resourceId: string; scope?: string }): Promise<boolean> {\n    const registryKey = sessionRegistryKey(resourceId, scope);\n\n    // Don't start a second deletion for the same key.\n    if (this.#deletionsInProgress.has(registryKey)) return false;\n\n    const pending = this.#sessionsByResource.get(registryKey);\n    if (!pending) return false;\n\n    // Track the deletion by registry key and set it synchronously, before any\n    // await, so a concurrent createSession that resumes from `await existing`\n    // sees the flag and waits instead of returning a session being torn down.\n    const deletion: { tolerantPromise?: Promise<void> } = {};\n    const deletionPromise = (async () => {\n      const session = await pending;\n      this.#sessionsBeingDeleted.add(session);\n      // tolerantPromise is set synchronously below before this microtask runs.\n      this.#sessionDeletionPromises.set(session, deletion.tolerantPromise!);\n      session.abort({ localOnly: true });\n      session.thread.cleanupSubscription();\n      try {\n        await session.thread.clearAndReleaseLock();\n      } finally {\n        // Notify inside the finally: even when lock release fails the session\n        // is deregistered for good, and listeners mirror the registry.\n        await this.#dropSessionFromRegistry(registryKey, session);\n        this.#notifySessionDeleted(session);\n      }\n    })();\n    // Waiters only need to know when teardown finished, not why it failed.\n    // Without this, a clearAndReleaseLock rejection would propagate to every\n    // createSession caller that happened to await the in-progress deletion.\n    const tolerantPromise = deletionPromise.then(\n      () => undefined,\n      () => undefined,\n    );\n    deletion.tolerantPromise = tolerantPromise;\n    this.#deletionsInProgress.set(registryKey, tolerantPromise);\n    try {\n      await deletionPromise;\n      return true;\n    } finally {\n      this.#deletionsInProgress.delete(registryKey);\n    }\n  }\n\n  // ===========================================================================\n  // Accessors\n  // ===========================================================================\n\n  /**\n   * Access the Mastra instance backing this AgentController.\n   *\n   * Returns the parent Mastra when this AgentController is registered on one (see\n   * {@link __registerMastra}); otherwise the internal Mastra created during\n   * `init()` when storage is configured.\n   *\n   * Useful for scorer registration, observability access, and eval tooling.\n   */\n  getMastra(): Mastra | undefined {\n    return this.#externalMastra ?? this.#internalMastra;\n  }\n\n  /**\n   * Whether a workspace is configured on this AgentController (static instance, dynamic\n   * factory, or config object). Sessions without an explicit workspace override\n   * fall back to this.\n   */\n  hasWorkspace(): boolean {\n    return this.workspace !== undefined;\n  }\n\n  /**\n   * Whether the AgentController-level static workspace has been explicitly initialized.\n   * Dynamic factory workspaces have no controller-level readiness state.\n   */\n  isWorkspaceReady(): boolean {\n    if (typeof this.workspace === 'function') return true;\n    return this.workspace?.status === 'ready';\n  }\n\n  /**\n   * The AgentController-level workspace, if it is a static instance. Dynamic factory\n   * workspaces are not resolved here — use {@link resolveWorkspace} to resolve\n   * a factory against a session's request context.\n   */\n  getWorkspace(): Workspace | undefined {\n    return typeof this.workspace === 'function' ? undefined : (this.workspace ?? undefined);\n  }\n\n  /**\n   * The workspace this session runs against, for code paths outside the request\n   * flow (e.g. slash commands). Sessions resolve their workspace once at\n   * creation — dynamic factories included — so this returns that instance\n   * rather than re-resolving, and only falls back to the factory for a session\n   * created without one.\n   */\n  async resolveWorkspace({\n    session,\n    requestContext,\n  }: {\n    session: Session<TState>;\n    requestContext?: RequestContext;\n  }): Promise<Workspace | undefined> {\n    const sessionWorkspace = session.getWorkspace();\n    if (sessionWorkspace) return sessionWorkspace;\n    if (typeof this.workspace !== 'function') return this.workspace ?? undefined;\n    const ctx = await this.buildRequestContext(session, requestContext);\n    return (await this.workspace({ requestContext: ctx, mastra: this.getMastra() })) ?? undefined;\n  }\n\n  /**\n   * Register this AgentController on a parent Mastra. Called by Mastra during\n   * construction when a harness is passed in its config. Once registered, the\n   * AgentController uses the parent Mastra (its storage, agents, gateways, and\n   * observability) instead of building its own internal one during `init()`.\n   *\n   * @internal\n   */\n  __registerMastra(mastra: Mastra): void {\n    this.#externalMastra = mastra;\n\n    // If `init()` already built an internal Mastra before we were wired to a\n    // parent, drop it: the parent now owns storage/agents/observability, but the\n    // orphaned internal instance still holds a global scorer hook that fires\n    // (and fails to resolve the scorer) on every scorer run. Release it.\n    if (this.#internalMastra) {\n      this.#internalMastra.__unregisterHooks();\n      this.#internalMastra = undefined;\n    }\n  }\n\n  /**\n   * Resolve the storage this AgentController reads and writes through.\n   *\n   * When registered on a parent Mastra, the AgentController inherits that Mastra's\n   * configured storage so the host and its Harnesses persist to a single store.\n   * A standalone AgentController falls back to its own `config.storage`.\n   */\n  #resolveStorage(): MastraCompositeStore | undefined {\n    return this.#externalMastra?.getStorage() ?? this.config.storage;\n  }\n\n  /**\n   * Sets or updates the harness-level browser and propagates it to mode agents.\n   */\n  setBrowser(browser: MastraBrowser | undefined): void {\n    this.browser = browser;\n\n    for (const agent of this.backingAgents()) {\n      agent.setBrowser(browser);\n    }\n  }\n\n  // ===========================================================================\n  // Initialization\n  // ===========================================================================\n\n  /**\n   * Initialize the harness by loading storage and propagating runtime services.\n   * Workspaces initialize lazily when used. Must be called before using the harness. Idempotent: repeated calls\n   * return the same in-flight/completed initialization instead of rebuilding\n   * the internal Mastra instance (which would orphan registered agents).\n   */\n  async init(): Promise<void> {\n    this.initPromise ??= this.runInit();\n    return this.initPromise;\n  }\n\n  /**\n   * Initialize only what read-only queries need: the storage layer (either a\n   * fresh internal Mastra wrapping the configured storage, or the inherited\n   * parent Mastra's storage). Skips workspace/sandbox provisioning entirely.\n   *\n   * Idempotent and safe to call from every read query; the underlying\n   * MastraCompositeStore init dedupes.\n   */\n  async initStorage(): Promise<void> {\n    this.#storageInitPromise ??= this.runStorageInit();\n    return this.#storageInitPromise;\n  }\n\n  #storageInitPromise?: Promise<void>;\n\n  private async runStorageInit(): Promise<void> {\n    // Create an internal Mastra instance so mode agents share the run state\n    // needed to persist and resume tool approvals, even without configured storage.\n    // We init storage through Mastra's proxied storage so augmentWithInit\n    // tracks it and won't double-init.\n    //\n    // Skip this when registered on a parent Mastra: that Mastra already owns\n    // storage/agents/gateways, and getMastra() resolves to it.\n    if (!this.#externalMastra) {\n      const enabledGateways = this.config.gateways?.filter(gateway => gateway.shouldEnable?.() ?? true);\n      const gateways = enabledGateways?.length\n        ? Object.fromEntries(enabledGateways.map(gateway => [gateway.id, gateway]))\n        : undefined;\n\n      this.#internalMastra = new Mastra({\n        logger: false,\n        ...(this.config.storage ? { storage: this.config.storage } : {}),\n        ...(this.config.backgroundTasks ? { backgroundTasks: this.config.backgroundTasks } : {}),\n        ...(this.config.pubsub ? { pubsub: this.config.pubsub } : {}),\n        ...(this.config.observability ? { observability: this.config.observability } : {}),\n        ...(gateways ? { gateways } : {}),\n      });\n      await this.#internalMastra.getStorage()!.init();\n    } else if (this.#externalMastra) {\n      // Registered on a parent Mastra: don't build an internal Mastra, but make\n      // sure the inherited storage is initialized before any session reads or\n      // writes through it. Init is idempotent on MastraCompositeStore, so this\n      // is safe even when the parent already initialized it.\n      await this.#externalMastra.getStorage()?.init();\n    }\n  }\n\n  private async runInit(): Promise<void> {\n    await this.initStorage();\n\n    // Propagate harness-level Mastra, memory, workspace, browser, and pubsub\n    // to the agent(s) that back each mode. Workspaces initialize lazily when used.\n    for (const agent of this.backingAgents()) {\n      this.propagateRuntimeServicesToAgent(agent);\n    }\n\n    this.startIntervals();\n  }\n\n  private async getMemoryStorage(): Promise<MemoryStorage> {\n    const storage = this.#resolveStorage();\n    if (!storage) {\n      throw new Error('Storage is not configured on this AgentController');\n    }\n    const memoryStorage = await storage.getStore('memory');\n    if (!memoryStorage) {\n      throw new Error('Storage does not have a memory domain configured');\n    }\n    return memoryStorage;\n  }\n\n  /**\n   * The shared-host storage gateway the Session's thread domain reads/writes\n   * through. The Session owns the thread-domain logic; this adapter maps raw\n   * storage rows to AgentController types and uses the active session only when\n   * resolving configured memory for a clone.\n   */\n  private createThreadDataStore(session: Session<TState>): ThreadDataStore {\n    return {\n      listThreads: ({ resourceId, includeForkedSubagents, metadata }) =>\n        this.queryThreads({ resourceId, includeForkedSubagents, metadata }),\n      getById: ({ threadId }) => this.queryThreadById({ threadId }),\n      listMessages: async ({ threadId, limit }) => {\n        if (limit !== undefined) {\n          const result = await this.queryThreadMessages({\n            threadId,\n            perPage: limit,\n            page: 0,\n            orderBy: { field: 'createdAt', direction: 'DESC' },\n          });\n          return { ...result, messages: result.messages.reverse() };\n        }\n\n        return this.queryThreadMessages({\n          threadId,\n          perPage: false,\n          orderBy: { field: 'createdAt', direction: 'ASC' },\n        });\n      },\n      firstUserMessages: ({ threadIds }) => this.queryFirstUserMessages({ threadIds }),\n      getMetadata: ({ threadId, key }) => this.readThreadMetadataValue({ threadId, key }),\n      setMetadata: ({ threadId, key, value }) => this.writeThreadMetadataValue({ threadId, key, value }),\n      deleteMetadata: ({ threadId, key }) => this.removeThreadMetadataValue({ threadId, key }),\n      hasStorage: () => !!this.#resolveStorage(),\n      saveThread: ({ thread }) => this.persistThreadRow(thread),\n      deleteThread: ({ threadId }) => this.deleteThreadRow(threadId),\n      cloneThread: ({ sourceThreadId, resourceId, title, metadata }) =>\n        this.cloneThreadRow({ session, sourceThreadId, resourceId, title, metadata }),\n      acquireLock: threadId => this.config.threadLock?.acquire(threadId) ?? Promise.resolve(),\n      releaseLock: threadId => this.config.threadLock?.release(threadId) ?? Promise.resolve(),\n      getModeIds: () => this.config.modes.map(m => m.id),\n    };\n  }\n\n  /** Persist a thread row to memory storage (gateway primitive for the Session thread domain). */\n  private async persistThreadRow(thread: AgentControllerThread): Promise<void> {\n    if (!this.#resolveStorage()) return;\n    const memoryStorage = await this.getMemoryStorage();\n    await memoryStorage.saveThread({\n      thread: {\n        id: thread.id,\n        resourceId: thread.resourceId,\n        title: thread.title ?? '',\n        createdAt: thread.createdAt,\n        updatedAt: thread.updatedAt,\n        metadata: thread.metadata,\n      },\n    });\n  }\n\n  /** Delete a thread row from memory storage (gateway primitive for the Session thread domain). */\n  private async deleteThreadRow(threadId: string): Promise<void> {\n    if (!this.#resolveStorage()) return;\n    const memoryStorage = await this.getMemoryStorage();\n    await memoryStorage.deleteThread({ threadId });\n  }\n\n  /** Clone a thread (and messages) via the host's memory (gateway primitive for the Session thread domain). */\n  private async cloneThreadRow({\n    session,\n    sourceThreadId,\n    resourceId,\n    title,\n    metadata,\n  }: {\n    session: Session<TState>;\n    sourceThreadId: string;\n    resourceId: string;\n    title?: string;\n    metadata?: Record<string, unknown>;\n  }): Promise<AgentControllerThread> {\n    const storage = this.#resolveStorage();\n    const memory = this.config.memory\n      ? await this.resolveMemory(session)\n      : storage\n        ? await storage.getStore('memory')\n        : undefined;\n    if (!memory) {\n      throw new Error(\n        storage ? 'Storage does not have a memory domain configured' : 'Memory is not configured on this Harness',\n      );\n    }\n\n    const result = await memory.cloneThread({ sourceThreadId, resourceId, title, metadata });\n    return {\n      id: result.thread.id,\n      resourceId: result.thread.resourceId,\n      title: result.thread.title ?? 'Cloned Thread',\n      createdAt: result.thread.createdAt,\n      updatedAt: result.thread.updatedAt,\n      metadata: result.thread.metadata,\n    };\n  }\n\n  private async readThreadMetadataValue({ threadId, key }: { threadId: string; key: string }): Promise<unknown> {\n    if (!this.#resolveStorage()) return undefined;\n    try {\n      const memoryStorage = await this.getMemoryStorage();\n      const thread = await memoryStorage.getThreadById({ threadId });\n      const metadata = thread?.metadata as Record<string, unknown> | undefined;\n      return metadata?.[key];\n    } catch {\n      // Settings reads are not critical\n      return undefined;\n    }\n  }\n\n  private async writeThreadMetadataValue({\n    threadId,\n    key,\n    value,\n  }: {\n    threadId: string;\n    key: string;\n    value: unknown;\n  }): Promise<void> {\n    if (!this.#resolveStorage()) return;\n    try {\n      const memoryStorage = await this.getMemoryStorage();\n      const thread = await memoryStorage.getThreadById({ threadId });\n      if (thread) {\n        await memoryStorage.saveThread({\n          thread: { ...thread, metadata: { ...thread.metadata, [key]: value }, updatedAt: new Date() },\n        });\n      }\n    } catch {\n      // Settings persistence is not critical\n    }\n  }\n\n  private async removeThreadMetadataValue({ threadId, key }: { threadId: string; key: string }): Promise<void> {\n    if (!this.#resolveStorage()) return;\n    try {\n      const memoryStorage = await this.getMemoryStorage();\n      const thread = await memoryStorage.getThreadById({ threadId });\n      if (thread && thread.metadata) {\n        const metadata = { ...thread.metadata };\n        delete metadata[key];\n        await memoryStorage.saveThread({\n          thread: {\n            ...thread,\n            metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n            updatedAt: new Date(),\n          },\n        });\n      }\n    } catch {\n      // Settings removal is not critical\n    }\n  }\n\n  /**\n   * Read a single thread by id directly from storage, without constructing a\n   * {@link Session}. Read-only server endpoints use this so a GET request for a\n   * thread doesn't spin up a workspace/sandbox as a side effect of session\n   * creation. Returns `null` when the thread doesn't exist or no storage is\n   * configured.\n   */\n  async queryThreadById({ threadId }: { threadId: string }): Promise<AgentControllerThread | null> {\n    await this.initStorage();\n    if (!this.#resolveStorage()) return null;\n    const memoryStorage = await this.getMemoryStorage();\n    const thread = await memoryStorage.getThreadById({ threadId });\n    if (!thread) return null;\n    return {\n      id: thread.id,\n      resourceId: thread.resourceId,\n      title: thread.title,\n      createdAt: thread.createdAt,\n      updatedAt: thread.updatedAt,\n      metadata: thread.metadata,\n    };\n  }\n\n  /**\n   * List threads directly from storage, without constructing a {@link Session}.\n   * Read-only server endpoints use this so a GET on `/threads` doesn't spin up\n   * a workspace/sandbox as a side effect of session creation.\n   */\n  async queryThreads({\n    resourceId,\n    includeForkedSubagents,\n    metadata,\n  }: {\n    resourceId?: string;\n    includeForkedSubagents?: boolean;\n    metadata?: Record<string, unknown>;\n  }): Promise<AgentControllerThread[]> {\n    await this.initStorage();\n    if (!this.#resolveStorage()) {\n      return [];\n    }\n\n    const memoryStorage = await this.getMemoryStorage();\n    const filter =\n      resourceId === undefined && metadata === undefined\n        ? undefined\n        : {\n            ...(resourceId === undefined ? {} : { resourceId }),\n            ...(metadata === undefined ? {} : { metadata }),\n          };\n\n    const result = await memoryStorage.listThreads({ filter, perPage: false });\n\n    const threads = includeForkedSubagents\n      ? result.threads\n      : result.threads.filter(thread => {\n          const metadata = thread.metadata as Record<string, unknown> | undefined;\n          return metadata?.forkedSubagent !== true;\n        });\n\n    return threads.map((thread: StorageThreadType) => ({\n      id: thread.id,\n      resourceId: thread.resourceId,\n      title: thread.title,\n      createdAt: thread.createdAt,\n      updatedAt: thread.updatedAt,\n      metadata: thread.metadata,\n    }));\n  }\n\n  /**\n   * List messages for a thread directly from storage, without constructing a\n   * {@link Session}. The session thread-data adapter and read-only server\n   * endpoints use this shared path so message reads never provision a\n   * workspace/sandbox.\n   */\n  async queryThreadMessages({\n    threadId,\n    resourceId,\n    perPage,\n    page,\n    orderBy = { field: 'createdAt', direction: 'DESC' },\n    include,\n    filter,\n  }: Omit<StorageListMessagesInput, 'threadId'> & { threadId: string }): Promise<StorageListMessagesOutput> {\n    await this.initStorage();\n    if (!this.#resolveStorage()) {\n      return {\n        messages: [],\n        total: 0,\n        page: page ?? 0,\n        perPage: perPage ?? 40,\n        hasMore: false,\n      };\n    }\n\n    const result = await (\n      await this.getMemoryStorage()\n    ).listMessages({\n      threadId,\n      ...(resourceId !== undefined ? { resourceId } : {}),\n      ...(perPage !== undefined ? { perPage } : {}),\n      ...(page !== undefined ? { page } : {}),\n      ...(orderBy !== undefined ? { orderBy } : {}),\n      ...(include !== undefined ? { include } : {}),\n      ...(filter !== undefined ? { filter } : {}),\n    });\n\n    return { ...result, messages: result.messages.map(msg => this.convertToControllerMessage(msg)) };\n  }\n\n  private async queryFirstUserMessages({ threadIds }: { threadIds: string[] }): Promise<Map<string, MastraDBMessage>> {\n    if (!this.#resolveStorage() || threadIds.length === 0) return new Map();\n\n    const memoryStorage = await this.getMemoryStorage();\n    const result = await memoryStorage.listMessages({\n      threadId: threadIds,\n      perPage: false,\n      orderBy: { field: 'createdAt', direction: 'ASC' },\n    });\n\n    const firstUserMessages = new Map<string, MastraDBMessage>();\n    for (const message of result.messages) {\n      if (!isUserAuthoredMessage(message) || !message.threadId || firstUserMessages.has(message.threadId)) continue;\n      firstUserMessages.set(message.threadId, this.convertToControllerMessage(message));\n\n      if (firstUserMessages.size === threadIds.length) {\n        break;\n      }\n    }\n\n    return firstUserMessages;\n  }\n\n  /**\n   * Name a thread from where its conversation went, with the model and\n   * instructions `generateTitle` gives the first-turn namer — so a title asked\n   * for by hand reads like one the thread would have been given on its own.\n   *\n   * Runs without constructing a {@link Session}: naming reads a window of recent\n   * messages and writes the thread row, so asking for a title never spins up a\n   * workspace or sandbox. A session already live for the resource lends its agent, request\n   * context and event stream; otherwise the default mode answers — and with no\n   * session state to read, a `generateTitle.model` that resolves from it falls\n   * back to its own default, which is why hosts that store the choice elsewhere\n   * pass `model`. Resolves to the new title, or `undefined` when the model\n   * returns nothing and the current title stands.\n   */\n  async generateThreadTitle({\n    threadId,\n    resourceId,\n    scope,\n    model,\n    requestContext: callerContext,\n  }: {\n    threadId: string;\n    resourceId?: string;\n    scope?: string;\n    /** Overrides the memory-configured title model — for hosts that resolve it themselves. */\n    model?: DynamicArgument<MastraModelConfig>;\n    /** The caller's context — carries the identity model resolution bills to. */\n    requestContext?: RequestContext;\n  }): Promise<string | undefined> {\n    const thread = await this.queryThreadById({ threadId });\n    if (!thread) throw new Error(`Thread not found: ${threadId}`);\n\n    const recent = await this.queryThreadMessages({\n      threadId,\n      perPage: TITLE_WINDOW_MESSAGES,\n      page: 0,\n      orderBy: { field: 'createdAt', direction: 'DESC' },\n    });\n    const messages = new MessageList().add(recent.messages.reverse(), 'memory').get.all.ui();\n    if (!messages.some(message => message.role === 'user')) {\n      throw new Error('This conversation has no message to name it from yet.');\n    }\n\n    const session = resourceId ? await this.getSessionByResource(resourceId, scope) : undefined;\n    const agent = session\n      ? this.getCurrentAgent(session)\n      : this.propagateRuntimeServicesToAgent(this.getAgentForMode(this.#defaultMode));\n    const requestContext = session\n      ? await this.buildRequestContext(session, callerContext)\n      : (callerContext ?? new RequestContext());\n    const configured = (await agent.getMemory({ requestContext }))?.getMergedThreadConfig().generateTitle;\n    const titleConfig = typeof configured === 'object' ? configured : undefined;\n\n    const title = (\n      await agent.generateTitleFromUserMessage({\n        messages,\n        requestContext,\n        model: model ?? titleConfig?.model,\n        instructions: titleConfig?.instructions,\n      })\n    )?.trim();\n    if (!title) return undefined;\n\n    // An explicit regenerate un-pins the title: auto-naming resumes from here.\n    await this.persistThreadRow({\n      ...thread,\n      title,\n      metadata: { ...thread.metadata, [TITLE_PINNED_THREAD_METADATA_KEY]: false },\n      updatedAt: new Date(),\n    });\n    session?.emit({ type: 'thread_title_updated', threadId, title });\n    return title;\n  }\n\n  // ===========================================================================\n  // Mode Management\n  // ===========================================================================\n\n  listModes(): AgentControllerMode[] {\n    return this.config.modes;\n  }\n\n  private propagateRuntimeServicesToAgent(agent: Agent, _session?: Session<TState>): Agent {\n    if (this.config.memory && !agent.hasOwnMemory()) {\n      agent.__setMemory(this.config.memory);\n    }\n    if (this.config.pubsub && !agent.hasOwnPubSub()) {\n      agent.__setPubSub(this.config.pubsub);\n    }\n\n    // Register the agent on the resolved Mastra (the parent when registered,\n    // otherwise the internal one). Re-bind when the agent currently has no\n    // Mastra OR is bound to a different instance — e.g. an agent that built its\n    // own internal Mastra before this AgentController was registered on a parent.\n    // Done before workspace/browser propagation so that addAgent — which may\n    // resolve agent.getWorkspace() — does not prematurely invoke a workspace\n    // factory before the per-session request context is available.\n    const mastra = this.getMastra();\n    if (mastra && agent.getMastraInstance() !== mastra) {\n      mastra.addAgent(agent);\n    }\n\n    if (this.workspace && typeof agent.hasOwnWorkspace === 'function' && !agent.hasOwnWorkspace()) {\n      agent.__setWorkspace(this.workspace);\n    }\n    if (\n      this.browser &&\n      typeof agent.hasOwnBrowser === 'function' &&\n      !agent.hasOwnBrowser() &&\n      typeof this.browser !== 'function'\n    ) {\n      agent.setBrowser(this.browser);\n    }\n\n    // Propagate controller channels onto the resolved (possibly lazily-built)\n    // mode agent so its run renders back through the controller's adapters.\n    // Unconditional: a controller's mode agents never carry their own channels,\n    // and `Agent.setChannels` is idempotent for the same instance. There is no\n    // `hasOwnChannels()` guard equivalent to `hasOwnBrowser()`.\n    if (this.#channels && agent.getChannels() !== this.#channels) {\n      agent.setChannels(this.#channels);\n    }\n\n    return agent;\n  }\n\n  /**\n   * Chat channels configured on this controller (from `config.channels`),\n   * or null when the controller has no channels.\n   */\n  getChannels(): AgentControllerChannels | null {\n    return this.#channels;\n  }\n\n  /**\n   * Sets the AgentControllerChannels instance for this controller and\n   * propagates it onto every backing agent so their runs render back through\n   * the controller's adapters. Used by ChannelProvider implementations (e.g.\n   * SlackProvider) to inject channels they create for dynamic installations.\n   * Mirrors {@link setBrowser}: the instance is attached to the shared backing\n   * agent plus any per-mode agents via `Agent.setChannels`, and lazily-built\n   * mode agents pick it up on their first run via\n   * `propagateRuntimeServicesToAgent`.\n   *\n   * Replacing an existing instance is expected on provider reconnect (the\n   * provider rebuilds channels as a superset merge rather than mutating the\n   * live instance), so it logs at debug level only. Note the replaced\n   * instance's in-memory `autoApproveResourceIds` tracking is discarded with\n   * it — harmless, since it is refreshed on every inbound message.\n   * @internal\n   */\n  setChannels(channels: AgentControllerChannels): void {\n    if (this.#channels && this.#channels !== channels) {\n      this.getMastra()?.getLogger()?.debug(`[AgentController:${this.id}] Replacing existing AgentControllerChannels`);\n    }\n    this.#channels = channels;\n    channels.__setController(this);\n\n    for (const agent of this.backingAgents()) {\n      agent.setChannels(channels);\n    }\n  }\n\n  /** The distinct agents backing this controller: the shared one plus any deprecated per-mode agent. */\n  private backingAgents(): Set<Agent<any, any, any, any>> {\n    const agents = new Set<Agent<any, any, any, any>>();\n    if (this.config.agent) {\n      agents.add(this.config.agent);\n    }\n    for (const mode of this.config.modes) {\n      if (mode.agent || !this.config.agent) {\n        agents.add(this.getAgentForMode(mode));\n      }\n    }\n    return agents;\n  }\n\n  private getAgentForMode(mode: AgentControllerMode): Agent<any, any, any, any> {\n    // Deprecated per-mode agent — use directly, no forking.\n    if (mode.agent) {\n      if (!this.#legacyAgentMode[mode.id]) {\n        this.#legacyAgentMode[mode.id] = mode.agent;\n      }\n      return this.#legacyAgentMode[mode.id]!;\n    }\n\n    // Shared backing agent — reuse the single instance.\n    // The harness never mutates the agent's own instructions or tools.\n    // Mode instructions are passed at call time via buildAgentMessageStreamOptions;\n    // mode tools are resolved at execution time via buildToolsets.\n    if (this.config.agent) {\n      return this.config.agent;\n    }\n\n    // No backing agent — construct one per mode (cached).\n    if (!this.#legacyAgentMode[mode.id]) {\n      if (!mode.defaultModelId) {\n        throw new Error(`Mode ${mode.id} requires a defaultModelId when no backing agent is configured`);\n      }\n\n      const instructions = [this.#instructions ?? '', mode.instructions].filter(Boolean).join('\\n');\n      const modeTools = {\n        ...mode.tools,\n        ...mode.additionalTools,\n      };\n\n      // Model resolution flows through the gateways registered on the internal\n      // Mastra instance: the bare model id string is handed to the Agent, and\n      // `propagateRuntimeServicesToAgent` attaches the internal Mastra so the\n      // model router resolves it via the configured gateways (auth included).\n      const model = mode.defaultModelId;\n      this.#legacyAgentMode[mode.id] = new Agent({\n        id: `${this.id}-agent`,\n        name: `Harness ${this.id} agent`,\n        model,\n        instructions,\n        tools: modeTools,\n      });\n    }\n    return this.#legacyAgentMode[mode.id]!;\n  }\n\n  /**\n   * Resolve the combined instructions for the current mode: harness-level\n   * instructions + mode-specific instructions. Passed at call time via\n   * `buildAgentMessageStreamOptions` so the agent's own instructions are\n   * never mutated.\n   */\n  private resolveCurrentModeInstructions(session: Session<TState>): string | undefined {\n    const mode = session.mode.resolve();\n    const combined = [this.#instructions ?? '', mode?.instructions ?? ''].filter(Boolean).join('\\n');\n    return combined || undefined;\n  }\n\n  /**\n   * Convert AgentInstructions (string | string[] | system message objects) to\n   * a plain string for combining with mode instructions.\n   */\n  private instructionsToString(instructions: AgentInstructions): string {\n    if (typeof instructions === 'string') return instructions;\n    if (Array.isArray(instructions)) {\n      return instructions\n        .map(msg => (typeof msg === 'string' ? msg : typeof msg.content === 'string' ? msg.content : ''))\n        .filter(Boolean)\n        .join('\\n\\n');\n    }\n    return typeof instructions.content === 'string' ? instructions.content : '';\n  }\n\n  /**\n   * Get the agent for the current mode.\n   */\n  /**\n   * Resolve the Agent backing the current mode, with runtime services (storage,\n   * pubsub, telemetry) propagated. Public so consumers like MastraCode's\n   * GoalManager can drive the agent's native objective methods\n   * (`setObjective`/`getObjective`/`clearObjective`/`updateObjectiveOptions`),\n   * which read/write the durable `threadState` `'goal'` slot.\n   */\n  getCurrentAgent(session: Session<TState>): Agent {\n    const mode = session.mode.resolve();\n\n    return this.propagateRuntimeServicesToAgent(this.getAgentForMode(mode), session);\n  }\n\n  listActiveThreadRuns(): ActiveThreadRun[] {\n    const byRunId = new Map<string, ActiveThreadRun>();\n    for (const agent of this.backingAgents()) {\n      for (const run of this.propagateRuntimeServicesToAgent(agent).listActiveThreadRuns()) {\n        byRunId.set(run.runId, run);\n      }\n    }\n    return [...byRunId.values()];\n  }\n\n  /**\n   * Check if the current model's provider has authentication configured.\n   * Delegates to the {@link GatewayManager} auth chain (the same resolution\n   * the model router uses at run time). Returns `hasAuth: true` only when no\n   * model is selected; gateway-chain failures return `hasAuth: false` so the\n   * auth-status endpoint stays stable instead of erroring.\n   */\n  async getCurrentModelAuthStatus(session: Session<TState>): Promise<ModelAuthStatus> {\n    const modelId = session.model.get();\n    if (!modelId) return { hasAuth: true };\n\n    // hasAuth returns false for expected missing-auth/missing-gateway cases.\n    // It rethrows unexpected gateway failures (token exchange errors, network\n    // bugs) — catch those here so the UI auth-status endpoint stays stable\n    // and falls back to \"no auth\" instead of erroring.\n    let hasAuth = true;\n    try {\n      hasAuth = this.#gatewayManager ? await this.#gatewayManager.hasAuth(modelId) : true;\n    } catch {\n      hasAuth = false;\n    }\n    if (hasAuth) return { hasAuth: true };\n\n    // Surface the env-var hint from the catalog when available.\n    try {\n      const availableModels = await this.listAvailableModels();\n      const currentModel = availableModels.find(model => model.id === modelId);\n      if (currentModel) {\n        return { hasAuth: false, apiKeyEnvVar: currentModel.apiKeyEnvVar };\n      }\n    } catch {\n      // Ignore catalog lookup errors.\n    }\n\n    return { hasAuth: false };\n  }\n\n  /**\n   * Get available models from the app-provided catalog hook with use counts applied.\n   */\n  async listAvailableModels(): Promise<AvailableModel[]> {\n    const now = Date.now();\n    if (this.availableModelsCache && now - this.availableModelsCacheTime < 10_000) {\n      return this.availableModelsCache;\n    }\n\n    const useCounts = this.config.modelUseCountProvider?.() ?? {};\n    const modelsById = new Map<string, AvailableModel>();\n\n    const upsertModel = (model: Omit<AvailableModel, 'useCount'>): void => {\n      if (!model.id || !model.provider || !model.modelName) return;\n      modelsById.set(model.id, {\n        ...model,\n        useCount: useCounts[model.id] ?? 0,\n      });\n    };\n\n    const catalog = await this.#gatewayManager!.listAvailableModels();\n    for (const model of catalog) {\n      upsertModel(model);\n    }\n\n    const result = [...modelsById.values()];\n    this.availableModelsCache = result;\n    this.availableModelsCacheTime = Date.now();\n    return result;\n  }\n\n  invalidateAvailableModelsCache(): void {\n    this.availableModelsCache = null;\n    this.availableModelsCacheTime = 0;\n  }\n\n  // ===========================================================================\n  // Thread Management\n  // ===========================================================================\n\n  /**\n   * Point the session at a different memory resourceId. The resourceId itself\n   * lives on the session (`session.identity`); the AgentController orchestrates the\n   * surrounding teardown — dropping the current thread subscription and clearing\n   * the active thread — since those are AgentController-owned.\n   *\n   * If a deletion is in progress for the session's current resource (or starts\n   * during the re-key), the session is being torn down and re-keying is skipped\n   * — the deletion's {@link #dropSessionFromRegistry} cleans up all keys.\n   */\n  async setResourceId(session: Session<TState>, { resourceId }: { resourceId: string }): Promise<void> {\n    // If the session was already deleted (or deletion is in progress), don't\n    // re-key it — a dead session must never be registered under a new key.\n    if (this.#sessionsBeingDeleted.has(session)) return;\n\n    const previousResourceId = session.identity.getResourceId();\n    const scope = this.#sessionScopes.get(session);\n    const oldKey = sessionRegistryKey(previousResourceId, scope);\n    const newKey = sessionRegistryKey(resourceId, scope);\n\n    // Wait for any in-progress deletion on the old key before touching the\n    // session. If the session was deleted while we waited, skip re-keying\n    // entirely — the session is dead and the deletion already cleaned up.\n    const oldDeletion = this.#deletionsInProgress.get(oldKey);\n    if (oldDeletion) {\n      await oldDeletion;\n      if (this.#sessionsBeingDeleted.has(session)) return;\n    }\n\n    session.thread.cleanupSubscription();\n    session.identity.setResourceId({ resourceId });\n    const releasePreviousThreadLock = session.thread.clearAndReleaseLock();\n\n    // Re-key the resource registry so this session is the one resolved for its\n    // new resourceId (and is no longer resolved for the old one). This session\n    // becomes the authoritative owner of the target resource, replacing any\n    // prior session registered there. The session keeps its creation scope, so\n    // a scoped session re-keys under the same scope on the new resource.\n    const dropPreviousResource = this.#dropSessionFromRegistry(oldKey, session);\n    // Re-check that a deletion didn't start during the awaits above. If it\n    // did, the session is being torn down — don't register it under the new\n    // key; the deletion's #dropSessionFromRegistry cleans up all keys.\n    if (this.#sessionsBeingDeleted.has(session)) {\n      await releasePreviousThreadLock;\n      await dropPreviousResource;\n      const postDeletion = this.#deletionsInProgress.get(newKey) ?? this.#deletionsInProgress.get(oldKey);\n      if (postDeletion) await postDeletion;\n      return;\n    }\n    this.#sessionsByResource.set(newKey, Promise.resolve(session));\n    await releasePreviousThreadLock;\n    await dropPreviousResource;\n\n    // A deletion may have started during the awaits. If so, the deletion's\n    // #dropSessionFromRegistry already drops the new key (via the session's\n    // current resourceId), but wait for it to finish so the caller sees a\n    // consistent state.\n    const postDeletion = this.#deletionsInProgress.get(newKey);\n    if (postDeletion) await postDeletion;\n  }\n\n  /**\n   * Remove `registryKey` from the registry only if it still resolves to\n   * `session`. When the session is being torn down (tracked in\n   * {@link #sessionsBeingDeleted}), also checks the session's current\n   * resourceId (which may differ if {@link setResourceId} re-keyed the session\n   * during deletion) and drops that key too, so an aborted session can't be\n   * re-resolved by a subsequent {@link createSession} call.\n   */\n  async #dropSessionFromRegistry(registryKey: string, session: Session<TState>): Promise<void> {\n    const pending = this.#sessionsByResource.get(registryKey);\n    if (pending) {\n      const resolved = await pending.catch(() => undefined);\n      if (resolved === session && this.#sessionsByResource.get(registryKey) === pending) {\n        this.#sessionsByResource.delete(registryKey);\n      }\n    }\n    // When tearing down a session, also drop from the session's current\n    // resourceId key, which may differ if setResourceId re-keyed the session\n    // during deletion. Skip this for non-deletion calls (setResourceId itself\n    // drops the old key and registers the new one — we must not undo that).\n    if (!this.#sessionsBeingDeleted.has(session)) return;\n    const scope = this.#sessionScopes.get(session);\n    const currentKey = sessionRegistryKey(session.identity.getResourceId(), scope);\n    if (currentKey !== registryKey) {\n      const currentPending = this.#sessionsByResource.get(currentKey);\n      if (currentPending) {\n        const currentResolved = await currentPending.catch(() => undefined);\n        if (currentResolved === session && this.#sessionsByResource.get(currentKey) === currentPending) {\n          this.#sessionsByResource.delete(currentKey);\n        }\n      }\n    }\n  }\n\n  async getKnownResourceIds(session: Session<TState>): Promise<string[]> {\n    const threads = await session.thread.list({ allResources: true });\n    const ids = new Set(threads.map(t => t.resourceId));\n    return [...ids].sort();\n  }\n\n  // ===========================================================================\n  // Observational Memory\n  // ===========================================================================\n\n  /**\n   * Load observational memory progress for the current thread.\n   * Reconstructs status from the durable OM record, then emits an `om_status` event for the UI.\n   */\n  async loadOMProgress(session: Session<TState>): Promise<void> {\n    const threadId = session.thread.getId();\n    if (!threadId) return;\n\n    try {\n      const memoryStorage = await this.getMemoryStorage();\n      const record = await memoryStorage.getObservationalMemory(threadId, session.identity.getResourceId());\n\n      if (!record) return;\n\n      const config = record.config as\n        | {\n            observation?: { messageTokens?: number | { min: number; max: number } };\n            reflection?: { observationTokens?: number | { min: number; max: number } };\n            _overrides?: {\n              observation?: { messageTokens?: number | { min: number; max: number } };\n              reflection?: { observationTokens?: number | { min: number; max: number } };\n            };\n          }\n        | undefined;\n\n      const getThreshold = (val: number | { min: number; max: number } | undefined, fallback: number): number => {\n        if (!val) return fallback;\n        if (typeof val === 'number') return val;\n        return val.max;\n      };\n\n      const observationThreshold = getThreshold(\n        config?._overrides?.observation?.messageTokens ?? config?.observation?.messageTokens,\n        30_000,\n      );\n      const reflectionThreshold = getThreshold(\n        config?._overrides?.reflection?.observationTokens ?? config?.reflection?.observationTokens,\n        40_000,\n      );\n      const messageTokens = record.pendingMessageTokens ?? 0;\n      const observationTokens = record.observationTokenCount ?? 0;\n      // Some storage backends return the chunk list serialized, so parse defensively\n      // (mirrors the OM processor's own `getBufferedChunks` helper).\n      const rawChunks = record.bufferedObservationChunks;\n      let bufferedChunks: { messageTokens?: number; tokenCount?: number }[] = [];\n      if (Array.isArray(rawChunks)) {\n        bufferedChunks = rawChunks;\n      } else if (typeof rawChunks === 'string') {\n        try {\n          const parsed = JSON.parse(rawChunks);\n          if (Array.isArray(parsed)) bufferedChunks = parsed;\n        } catch {\n          bufferedChunks = [];\n        }\n      }\n      const bufferedMessageTokens = Math.min(\n        bufferedChunks.reduce((sum, chunk) => sum + (chunk.messageTokens ?? 0), 0),\n        messageTokens,\n      );\n      const bufferedObservationTokens = bufferedChunks.reduce((sum, chunk) => sum + (chunk.tokenCount ?? 0), 0);\n      const bufferedObs = {\n        status: record.isBufferingObservation\n          ? ('running' as const)\n          : bufferedChunks.length\n            ? ('complete' as const)\n            : ('idle' as const),\n        chunks: bufferedChunks.length,\n        messageTokens: bufferedMessageTokens,\n        // The real projection depends on the OM processor's activation boundary math,\n        // which isn't reproducible from the record alone. Report 0 until the first live\n        // status arrives rather than an authoritative-looking approximation.\n        projectedMessageRemoval: 0,\n        observationTokens: bufferedObservationTokens,\n      };\n      const bufferedRef = {\n        status: record.isBufferingReflection\n          ? ('running' as const)\n          : record.bufferedReflection\n            ? ('complete' as const)\n            : ('idle' as const),\n        inputObservationTokens: record.bufferedReflectionInputTokens ?? 0,\n        observationTokens: record.bufferedReflectionTokens ?? 0,\n      };\n      const generationCount = record.generationCount ?? 0;\n      // Step index is per-run and intentionally not durable — a restored thread starts at 0\n      // and picks up the real step number from the next live status update.\n      const stepNumber = 0;\n\n      session.emit({\n        type: 'om_status',\n        windows: {\n          active: {\n            messages: { tokens: messageTokens, threshold: observationThreshold },\n            observations: { tokens: observationTokens, threshold: reflectionThreshold },\n          },\n          buffered: { observations: bufferedObs, reflection: bufferedRef },\n        },\n        recordId: record.id ?? '',\n        threadId,\n        stepNumber,\n        generationCount,\n      });\n    } catch {\n      // OM not available or not initialized — that's fine\n    }\n  }\n\n  async getObservationalMemoryRecord(session: Session<TState>): Promise<ObservationalMemoryRecord | null> {\n    if (!session.thread.getId()) return null;\n\n    try {\n      const memoryStorage = await this.getMemoryStorage();\n      return await memoryStorage.getObservationalMemory(session.thread.getId(), session.identity.getResourceId());\n    } catch {\n      return null;\n    }\n  }\n\n  // ===========================================================================\n  // Permissions\n  // ===========================================================================\n\n  getToolCategory({ toolName }: { toolName: string }): ToolCategory | null {\n    return this.config.toolCategoryResolver?.(toolName) ?? null;\n  }\n\n  // ===========================================================================\n  // Message Handling\n  // ===========================================================================\n\n  /**\n   * Resolve the `activeTools` allowlist for the current mode's run.\n   *\n   * Returns `undefined` when the mode has no `availableTools` configured\n   * (no restriction — all tools visible). When the mode declares\n   * `availableTools`, returns that list filtered to remove tools whose\n   * permission category is denied.\n   *\n   * Per-tool `deny` is already handled by `buildToolsets` (denied tools are\n   * deleted from the toolsets), so those tools won't exist at execution time\n   * regardless of whether they appear in the allowlist.\n   *\n   * The returned list uses the same exposed tool names the execution pipeline\n   * checks against (e.g. `view`, `write_file`, `ask_user`), which matches the\n   * names workspace tools are renamed to via `TOOL_NAME_OVERRIDES`.\n   */\n  private resolveModeActiveTools(session: Session<TState>): string[] | undefined {\n    const currentMode = session.mode.resolve();\n    const availableTools = currentMode?.availableTools;\n    if (!availableTools) {\n      return undefined;\n    }\n    if (availableTools.length === 0) {\n      return [];\n    }\n\n    const permissionRules = session.permissions.getRules();\n    const deniedTools = new Set(\n      Object.entries(permissionRules.tools)\n        .filter(([, policy]) => policy === 'deny')\n        .map(([tool]) => tool),\n    );\n    const deniedCategories = new Set(\n      Object.entries(permissionRules.categories)\n        .filter(([, policy]) => policy === 'deny')\n        .map(([cat]) => cat),\n    );\n\n    if (deniedTools.size === 0 && deniedCategories.size === 0) {\n      return availableTools;\n    }\n\n    return availableTools.filter(toolName => {\n      // Per-tool deny always wins — even over the mode allowlist.\n      if (deniedTools.has(toolName)) {\n        return false;\n      }\n      // Category deny: tools with no category (null — always-allowed tools\n      // like ask_user) are not subject to category deny.\n      const category = this.getToolCategory({ toolName });\n      return !category || !deniedCategories.has(category);\n    });\n  }\n\n  private async buildAgentMessageStreamOptions({\n    session,\n    requestContext: requestContextInput,\n    tracingContext,\n    tracingOptions,\n    untilIdle,\n    abortSignal,\n    threadId,\n  }: {\n    session: Session<TState>;\n    requestContext?: RequestContext;\n    tracingContext?: TracingContext;\n    tracingOptions?: TracingOptions;\n    untilIdle?: boolean | { maxIdleMs?: number };\n    abortSignal?: AbortSignal;\n    threadId?: string;\n  }): Promise<Record<string, unknown>> {\n    // A caller may name the thread the run belongs to (a claimed thread woken by\n    // a peer); otherwise the run belongs to whichever thread the session holds.\n    const runThreadId = threadId ?? session.thread.getId();\n    if (!runThreadId) {\n      throw new Error('Cannot build stream options without a current thread');\n    }\n    const resourceId = session.identity.getResourceId();\n    const modeId = session.mode.get();\n\n    if (!abortSignal) {\n      session.run.clearAbortRequested();\n    }\n    // Reconcile the in-memory model selection with the persisted per-mode model\n    // before snapshotting it into the request context. In multiplayer\n    // deployments another process (or a freshly-created Session for an existing\n    // thread) may have persisted a different model; the per-instance cache would\n    // otherwise run with a stale selection. No-op in the single-player TUI.\n    await session.model.syncFromPersisted({ modeId });\n    const requestContext = await this.buildRequestContext(session, requestContextInput, {\n      abortSignal,\n      resourceId,\n      threadId: runThreadId,\n      modeId,\n    });\n    // Resolve mode-aware instructions at call time so the agent's own\n    // instructions are never mutated by the harness.\n    // When mode/harness instructions exist, combine them with the agent's\n    // own instructions so dynamic instructions (e.g. AGENTS.md, project\n    // context) aren't lost — the agent treats options.instructions as a\n    // full override.\n    let callTimeInstructions: string | undefined;\n    if (this.config.agent) {\n      const modeInstructions = this.resolveCurrentModeInstructions(session);\n      if (modeInstructions) {\n        const agent = this.getCurrentAgent(session);\n        const agentInstructions = await agent.getInstructions({ requestContext });\n        const agentStr = this.instructionsToString(agentInstructions);\n        callTimeInstructions = [agentStr, modeInstructions].filter(Boolean).join('\\n') || undefined;\n      }\n      // When no mode instructions, don't pass instructions — the agent\n      // uses its own getInstructions() naturally.\n    }\n\n    const streamOptions: Record<string, unknown> = {\n      ...this.buildSharedRunOptions(session),\n      memory: {\n        thread: runThreadId,\n        resource: resourceId,\n        // Titling outlives the run, so the thread it named is the one captured here,\n        // not whichever thread the session happens to hold when the model answers.\n        onTitleGenerated: (title: string) =>\n          session.emit({ type: 'thread_title_updated', threadId: runThreadId, title }),\n      },\n      abortSignal: abortSignal ?? session.run.ensureAbortController().signal,\n      requestContext,\n      outputWriter: async (chunk: { type?: string; data?: unknown }) => {\n        if (chunk.type !== 'data-mastracode-tool-progress') return;\n        const data = chunk.data as { toolCallId?: string; progress?: unknown } | undefined;\n        if (!data?.toolCallId || data.progress === undefined) return;\n\n        session.emit({\n          type: 'tool_update',\n          threadId: runThreadId,\n          toolCallId: data.toolCallId,\n          partialResult: data.progress,\n        });\n        const output = this.formatToolProgressOutput(data.progress);\n        if (output) {\n          session.emit({\n            type: 'shell_output',\n            threadId: runThreadId,\n            toolCallId: data.toolCallId,\n            output,\n            stream: 'stdout',\n          });\n        }\n      },\n      ...(tracingContext && { tracingContext }),\n      ...(tracingOptions && { tracingOptions }),\n      ...(untilIdle !== undefined && { untilIdle }),\n      ...(callTimeInstructions && { instructions: callTimeInstructions }),\n    };\n    streamOptions.toolsets = await this.buildToolsets(session, requestContext);\n\n    // Apply mode-level tool visibility via `activeTools` — the same mechanism\n    // the execution pipeline already enforces at tool-call time.  Only set\n    // when the helper returns a concrete list so modes without\n    // `availableTools` keep unrestricted behaviour.\n    const activeTools = this.resolveModeActiveTools(session);\n    if (activeTools !== undefined) {\n      streamOptions.activeTools = activeTools;\n    }\n\n    return streamOptions;\n  }\n\n  private formatToolProgressOutput(progress: unknown): string {\n    if (typeof progress === 'string') return progress.endsWith('\\n') ? progress : `${progress}\\n`;\n    if (typeof progress !== 'object' || progress === null) return `${String(progress)}\\n`;\n\n    const record = progress as { status?: unknown; detail?: unknown };\n    const parts = [record.status, record.detail].filter(\n      (part): part is string => typeof part === 'string' && part.length > 0,\n    );\n    return parts.length > 0 ? `${parts.join(': ')}\\n` : '';\n  }\n\n  /**\n   * Options that every harness-driven agent run must carry — the initial stream\n   * AND every `resumeStream`. Centralized so the two paths can't drift: a\n   * missing `maxSteps` on resume silently caps the resumed run at the agent's\n   * small default and ends it mid-task (see {@link HARNESS_MAX_STEPS}).\n   */\n  private buildSharedRunOptions(session: Session<TState>): Record<string, unknown> {\n    const isYolo = (session.state.get() as Record<string, unknown>).yolo === true;\n    // Channel sessions on adapters that can't render approval buttons must\n    // auto-approve tools — a required approval would park the run forever on\n    // a card nobody can answer. Tracked on the channels instance rather than\n    // session state so the controller's `stateSchema` never sees it.\n    const channelAutoApprove = this.#channels?.__isAutoApproveResource(session.identity.getResourceId()) === true;\n    const shared: Record<string, unknown> = {\n      maxSteps: CONTROLLER_MAX_STEPS,\n      savePerStep: false,\n      requireToolApproval: !isYolo && !channelAutoApprove,\n    };\n\n    // Auto-enable Anthropic server-side fallbacks for fable-5 so a classifier\n    // block is transparently retried on the fallback model instead of failing.\n    const fableFallback = buildFableFallbackProviderOptions(session.model.get());\n    if (fableFallback) {\n      shared.providerOptions = { anthropic: { ...fableFallback.anthropic } };\n    }\n\n    return shared;\n  }\n\n  /**\n   * Persist a system-reminder message for a thread (host-owned storage). Throws\n   * when no storage is configured — the Session guards the no-thread case before\n   * calling. Returns the saved {@link MastraDBMessage}.\n   */\n  private async saveSystemReminder({\n    threadId,\n    resourceId,\n    message,\n    reminderType,\n    role,\n    metadata,\n  }: {\n    threadId: string;\n    resourceId: string;\n    message: string;\n    reminderType: string;\n    role: 'user' | 'assistant' | 'system';\n    metadata?: Record<string, unknown>;\n  }): Promise<MastraDBMessage | null> {\n    if (!this.#resolveStorage()) return null;\n    const memoryStorage = await this.getMemoryStorage();\n    const dbMessage = {\n      id: globalThis.crypto.randomUUID(),\n      role,\n      threadId,\n      resourceId,\n      createdAt: new Date(),\n      content: {\n        format: 2 as const,\n        parts: [],\n        content: '',\n        metadata: {\n          systemReminder: {\n            type: reminderType,\n            message,\n            ...metadata,\n          },\n        },\n      },\n    };\n\n    const result = await memoryStorage.saveMessages({ messages: [dbMessage] });\n    const saved = result.messages[0] ?? dbMessage;\n    return this.convertToControllerMessage(saved);\n  }\n\n  /**\n   * Resolve the mode the session transitions to when a plan is approved: the\n   * current mode's `transitionsTo`, else the configured default mode. The mode\n   * catalog is AgentController config, so this is host-owned. Returns `undefined` when\n   * no default mode is configured.\n   */\n  private resolveTransitionModeId(session: Session<TState>): string | undefined {\n    const currentMode = session.mode.resolve();\n    const transitionModeId =\n      currentMode.transitionsTo ??\n      this.config.defaultModeId ??\n      this.config.modes.find(mode => mode.default || mode.metadata?.default === true)?.id ??\n      this.config.modes[0]?.id;\n    return this.listModes().find(mode => mode.id === transitionModeId)?.id;\n  }\n\n  private convertToControllerMessage(msg: {\n    id: string;\n    role: MastraDBMessage['role'];\n    createdAt: Date;\n    threadId?: string;\n    resourceId?: string;\n    type?: string;\n    content: MastraMessageContentV2;\n  }): MastraDBMessage {\n    // DB-native passthrough: the agent-controller now exposes the canonical persisted\n    // MastraDBMessage shape directly. No flattening into a UI content union — consumers\n    // read content.parts (and role === \"signal\" + content.metadata.signal) themselves.\n    return {\n      id: msg.id,\n      role: msg.role,\n      createdAt: msg.createdAt,\n      ...(msg.threadId !== undefined ? { threadId: msg.threadId } : {}),\n      ...(msg.resourceId !== undefined ? { resourceId: msg.resourceId } : {}),\n      ...(msg.type !== undefined ? { type: msg.type } : {}),\n      content: msg.content,\n    };\n  }\n\n  // ===========================================================================\n  // Control\n  // ===========================================================================\n\n  private getSubagentDisplayName(agentType: string): string | undefined {\n    return this.config.subagents?.find(subagent => subagent.id === agentType)?.name;\n  }\n\n  // ===========================================================================\n  // Event System\n  // ===========================================================================\n  //\n  // The Session owns the event bus. To observe events, subscribe on a session:\n  // `harness.session.subscribe(listener)`. Internal orchestration emits on the\n  // session it is driving via `session.emit(...)`.\n\n  // ===========================================================================\n  // Runtime Context\n  // ===========================================================================\n\n  /**\n   * Build the toolsets object that includes built-in harness tools (ask_user, submit_plan,\n   * and optionally subagent) plus any user-configured tools.\n   * Used by sendMessage, handleToolApprove, and handleToolDecline.\n   */\n  private async buildToolsets(session: Session<TState>, requestContext: RequestContext): Promise<ToolsetsInput> {\n    const builtInTools: ToolsInput = {\n      ask_user: askUserTool,\n      submit_plan: submitPlanTool,\n      task_write: taskWriteTool,\n      task_update: taskUpdateTool,\n      task_complete: taskCompleteTool,\n      task_check: taskCheckTool,\n    };\n\n    // Resolve user-configured controller tools (needed for both the controller toolset and subagent allowedControllerTools)\n    let resolvedControllerTools: ToolsInput | undefined = undefined;\n    if (this.config.tools) {\n      const tools =\n        typeof this.config.tools === 'function' ? await this.config.tools({ requestContext }) : this.config.tools;\n      if (tools) {\n        resolvedControllerTools = { ...tools };\n      }\n    }\n\n    // Auto-create subagent tool if subagent definitions are configured.\n    // Model resolution flows through the gateways registered on the internal\n    // Mastra instance: `resolveModel` returns the bare model id string and the\n    // created subagent Agent receives the internal Mastra via its constructor\n    // so the model router resolves through the same gateways as the parent.\n    if (this.config.subagents?.length) {\n      const currentMode = session.mode.resolve();\n      const hasMemory = Boolean(this.config.memory);\n      builtInTools.subagent = createSubagentTool({\n        subagents: this.config.subagents,\n        resolveModel: (modelId: string) => modelId,\n        mastra: this.getMastra(),\n        controllerTools: resolvedControllerTools,\n        fallbackModelId: currentMode?.defaultModelId,\n        getParentModelId: () => session.model.get(),\n        // Resolved lazily so forked subagents see the current mode's agent\n        // even if the mode switches between tool-call scheduling and execution.\n        getParentAgent: () => {\n          try {\n            return this.getCurrentAgent(session);\n          } catch {\n            return undefined;\n          }\n        },\n        // Only wired up when memory is configured. Clones at the memory layer\n        // (not via AgentController.cloneThread) so the parent thread stays the active\n        // thread while the forked subagent runs on the clone.\n        //\n        // The clone is tagged with `forkedSubagent: true` + `parentThreadId` so\n        // that thread pickers / startup flows can hide transient fork threads —\n        // see `listThreads` (filtered by default).\n        cloneThreadForFork: hasMemory\n          ? async ({ sourceThreadId, resourceId, title }) => {\n              const memory = await this.resolveMemory(session);\n              // The fork only needs the new thread id, so copy without loading\n              // the message payloads into the Node heap.\n              const result = await memory.copyThread({\n                sourceThreadId,\n                resourceId: resourceId ?? session.identity.getResourceId(),\n                title,\n                metadata: {\n                  forkedSubagent: true,\n                  parentThreadId: sourceThreadId,\n                },\n              });\n              return { id: result.thread.id, resourceId: result.thread.resourceId };\n            }\n          : undefined,\n        // Forks inherit the parent's toolsets verbatim so harness-injected\n        // tools (`ask_user`, `submit_plan`, user-configured harness tools, etc.)\n        // remain available inside the fork. The `subagent` entry itself is\n        // deliberately kept — its schema/description are part of the parent's\n        // prompt-cache prefix, and stripping it would invalidate the cache.\n        // Recursive forking is blocked at runtime instead: see the patched\n        // `subagent` execute that the forked tool path installs in `tools.ts`.\n        getParentToolsets: forkRequestContext => this.buildToolsets(session, forkRequestContext ?? requestContext),\n      });\n    }\n\n    // Remove any explicitly disabled built-in tools\n    if (this.config.disableBuiltinTools?.length) {\n      for (const toolId of this.config.disableBuiltinTools) {\n        delete builtInTools[toolId];\n      }\n    }\n\n    const permissionRules = session.permissions.getRules();\n    for (const [toolId, policy] of Object.entries(permissionRules.tools)) {\n      if (policy === 'deny') {\n        delete builtInTools[toolId];\n        delete resolvedControllerTools?.[toolId];\n      }\n    }\n\n    const result: ToolsetsInput = { controllerBuiltIn: builtInTools };\n    if (resolvedControllerTools) {\n      result.controller = resolvedControllerTools;\n    }\n\n    // When using a shared backing agent, mode-specific tool overrides are\n    // delivered through toolsets (not baked into the agent) so the agent's\n    // own tools (including signal-provider tools) are never lost.\n    //\n    // Note: both `mode.tools` and `mode.additionalTools` are added as a\n    // toolset (augment).  True \"replace\" semantics (masking the agent's own\n    // tools) would require per-run tool filtering in the Agent, which isn't\n    // supported yet.  validateModes() already prevents setting both on the\n    // same mode.\n    if (this.config.agent) {\n      const currentMode = session.mode.resolve();\n      const modeTools = currentMode.tools ?? currentMode.additionalTools;\n      if (modeTools) {\n        result.modeTools = modeTools;\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Build request context for agent execution.\n   * Tools can access controller state via requestContext.get('controller').\n   */\n  private async buildRequestContext(\n    session: Session<TState>,\n    requestContext?: RequestContext,\n    scope?: { abortSignal?: AbortSignal; resourceId?: string; threadId?: string; modeId?: string },\n  ): Promise<RequestContext> {\n    requestContext = new RequestContext(requestContext?.entries());\n    const threadId = scope?.threadId ?? session.thread.getId();\n    const controllerContext: AgentControllerRequestContext<TState> = {\n      controllerId: this.id,\n      harnessId: this.id,\n      state: session.state.get(),\n      getState: () => session.state.get(),\n      setState: updates => session.state.set(updates),\n      updateState: updater => session.state.update(updater),\n      getThreadSetting: key => (threadId ? session.thread.getSettingOn({ threadId, key }) : Promise.resolve(undefined)),\n      setThreadSetting: setting =>\n        threadId\n          ? session.thread.setSettingOn({ threadId, key: setting.key, value: setting.value })\n          : Promise.resolve(),\n      isThreadActive: () => session.thread.getId() === threadId,\n      threadId,\n      resourceId: scope?.resourceId ?? session.identity.getResourceId(),\n      scope: this.#sessionScopes.get(session),\n      session: {\n        id: session.identity.getId(),\n        ownerId: session.identity.getOwnerId(),\n        modeId: scope?.modeId ?? session.mode.get(),\n        modelId: session.model.get(),\n        state: {\n          get: () => session.state.get(),\n          set: updates => session.state.set(updates),\n          update: updater => session.state.update(updater),\n        },\n      },\n      abortSignal: scope?.abortSignal ?? session.run.getAbortSignal(),\n      emitEvent: event => session.emit(event),\n      getSubagentModelId: params => session.subagents.model.get(params ?? {}),\n    };\n\n    requestContext.set('controller', controllerContext);\n\n    return requestContext;\n  }\n\n  /**\n   * Resolve memory from config — handles both static instances and dynamic factory functions.\n   */\n  private async resolveMemory(session: Session<TState>): Promise<MastraMemory> {\n    const mem = this.config.memory;\n    if (!mem) {\n      throw new Error('Memory is not configured on this AgentController');\n    }\n    if (typeof mem !== 'function') {\n      return mem;\n    }\n    const requestContext = await this.buildRequestContext(session);\n    const resolved = await Promise.resolve(mem({ requestContext }));\n    if (!resolved) {\n      throw new Error('Dynamic memory factory returned empty value');\n    }\n    return resolved;\n  }\n\n  // ===========================================================================\n  // Token Usage\n  // ===========================================================================\n\n  private async persistTokenUsage(session: Session<TState>): Promise<void> {\n    const threadId = session.thread.getId();\n    if (!threadId || !this.#resolveStorage()) return;\n\n    try {\n      const memoryStorage = await this.getMemoryStorage();\n      const thread = await memoryStorage.getThreadById({ threadId });\n      if (thread) {\n        await memoryStorage.saveThread({\n          thread: {\n            ...thread,\n            metadata: { ...thread.metadata, tokenUsage: session.getTokenUsage() },\n            updatedAt: new Date(),\n          },\n        });\n      }\n    } catch {\n      // Token persistence is not critical\n    }\n  }\n\n  // ===========================================================================\n  // Interval Handlers\n  // ===========================================================================\n\n  private startIntervals(): void {\n    const handlers = [...(this.config.intervalHandlers ?? [])];\n    if (!handlers.length) return;\n\n    for (const iv of handlers) {\n      if (this.intervalTimers.has(iv.id)) continue;\n\n      const run = async () => {\n        try {\n          await iv.handler();\n        } catch (error) {\n          console.error(`[Interval:${iv.id}] failed:`, error);\n        }\n      };\n\n      if (iv.immediate !== false) {\n        void run();\n      }\n\n      const timer = setInterval(run, iv.intervalMs);\n      timer.unref();\n      this.intervalTimers.set(iv.id, { timer, shutdown: iv.shutdown });\n    }\n  }\n\n  registerInterval(handler: IntervalHandler): void {\n    void this.removeInterval({ id: handler.id });\n\n    const run = async () => {\n      try {\n        await handler.handler();\n      } catch (error) {\n        console.error(`[Interval:${handler.id}] failed:`, error);\n      }\n    };\n\n    if (handler.immediate !== false) {\n      void run();\n    }\n\n    const timer = setInterval(run, handler.intervalMs);\n    timer.unref();\n    this.intervalTimers.set(handler.id, { timer, shutdown: handler.shutdown });\n  }\n\n  async removeInterval({ id }: { id: string }): Promise<void> {\n    const entry = this.intervalTimers.get(id);\n    if (entry) {\n      clearInterval(entry.timer);\n      this.intervalTimers.delete(id);\n      try {\n        await entry.shutdown?.();\n      } catch (error) {\n        console.error(`[Interval:${id}] shutdown failed:`, error);\n      }\n    }\n  }\n\n  async stopIntervals(): Promise<void> {\n    const entries = [...this.intervalTimers.entries()];\n    this.intervalTimers.clear();\n\n    for (const [id, entry] of entries) {\n      clearInterval(entry.timer);\n      try {\n        await entry.shutdown?.();\n      } catch (error) {\n        console.error(`[Interval:${id}] shutdown failed:`, error);\n      }\n    }\n  }\n\n  // ===========================================================================\n  // Lifecycle\n  // ===========================================================================\n\n  async destroy(): Promise<void> {\n    // The AgentController owns no session; per-session teardown (thread-subscription\n    // cleanup) is the caller's responsibility via `session.thread.*`. Here we\n    // only tear down AgentController-shared resources.\n    await this.stopIntervals();\n  }\n\n  // ===========================================================================\n  // Utilities\n  // ===========================================================================\n\n  private generateId(): string {\n    if (this.config.idGenerator) {\n      return this.config.idGenerator();\n    }\n    return globalThis.crypto.randomUUID();\n  }\n}\n"],"mappings":"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"}