@agents24/chat-react 0.5.5 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/runtime/use-agent-chat-runtime.ts","../../src/runtime/input-contract.ts"],"sourcesContent":["import type {\n AgentClient,\n Agents24ClientError,\n ClientBootstrap,\n EffectiveResourcePolicy,\n HitlResponse,\n PortableUpload,\n} from \"@agents24/client\";\nimport type { ContextCompression, ContextWindow } from \"@agents24/client/protocol\";\nimport {\n type AgentChatController,\n type ChatHitlPart,\n useAgentAttachments,\n useAgentChat,\n useAgentMcp,\n} from \"@agents24/react\";\nimport * as React from \"react\";\n\nimport {\n browserChatCrypto,\n createMcpPkceProof,\n validateMcpCallbackResult,\n waitForMcpOauthComplete,\n} from \"../mcp-oauth\";\nimport type { ChatMcpOauthCompletion } from \"../types\";\nimport { validateAgentChatSubmission } from \"./input-contract\";\n\nexport type AgentChatRuntimeAgent = {\n name: string;\n description?: string | null;\n handle?: string | null;\n avatarUrl?: string | null;\n};\n\nexport type AgentChatRuntimeModel = {\n id: string;\n label: string;\n};\n\nexport type AgentChatRuntimeAgentOption = { id: string; label: string };\n\nexport type AgentChatRuntimeViewState =\n | \"ready\"\n | \"loading\"\n | \"streaming\"\n | \"reconnecting\"\n | \"paused\"\n | \"cancelling\"\n | \"cancelled\"\n | \"offline\"\n | \"denied\"\n | \"quota\"\n | \"failed\"\n | \"expired\";\n\nexport type AgentChatRuntimeConnectionState =\n | \"connected\"\n | \"connecting\"\n | \"reconnecting\"\n | \"offline\"\n | \"expired\";\n\nexport type AgentChatThreadChangeReason = \"created\" | \"opened\" | \"new\" | \"deleted\";\n\nexport type AgentChatActiveThreadChange = {\n threadId: string | null;\n reason: AgentChatThreadChangeReason;\n};\n\nexport type AgentChatActiveThreadChangeHandler = (\n change: AgentChatActiveThreadChange,\n) => void;\n\nexport type AgentChatMcpAuthorizationCompletion = (input: {\n completion: ChatMcpOauthCompletion;\n codeVerifier: string;\n serverId: string;\n}) => Promise<void>;\n\nexport type AgentChatRuntimeSubmit = {\n text: string;\n files?: readonly PortableUpload[];\n};\n\nexport type AgentChatRuntimeHitlActionState = {\n action: string;\n error?: string | null;\n status: \"connecting\" | \"resuming\" | \"error\";\n};\n\nexport type UseAgentChatRuntimeOptions = {\n activeThreadId?: string | null;\n agent?: AgentChatRuntimeAgent;\n client: AgentClient;\n completeMcpAuthorization?: AgentChatMcpAuthorizationCompletion;\n mcpRedirectUri?: string;\n modelId?: string | null;\n onActiveThreadIdChange?: AgentChatActiveThreadChangeHandler;\n onModelChange?: (modelId: string) => void;\n};\n\nexport type AgentChatRuntime = {\n agent: AgentChatRuntimeAgent;\n inputContract: ClientBootstrap[\"features\"][\"inputs\"] | null;\n allowFeedback: boolean;\n backgroundError: unknown;\n bootstrap: ClientBootstrap | null;\n capabilities: readonly string[];\n agentId: string | null;\n agents: AgentChatRuntimeAgentOption[];\n changeAgent(agentId: string): Promise<void>;\n changeModel(modelId: string): void;\n clearOperationError(): void;\n connectionState: AgentChatRuntimeConnectionState;\n contextWindow: ContextWindow | null;\n contextCompression: ContextCompression | null;\n controller: AgentChatController;\n deleteThread(threadId: string): Promise<void>;\n errorMessage: string | null;\n fatalError: unknown;\n getHitlActionState(part: ChatHitlPart): AgentChatRuntimeHitlActionState | undefined;\n isBootstrapping: boolean;\n isChangingAgent: boolean;\n isSubmitting: boolean;\n isUploading: boolean;\n modelId: string | null;\n models: AgentChatRuntimeModel[];\n newThread(): void;\n onHitlAction(part: ChatHitlPart, response: HitlResponse): Promise<void>;\n openThread(threadId: string): Promise<void>;\n operationError: unknown;\n retryBootstrap(): Promise<void>;\n state: AgentChatRuntimeViewState;\n submit(input: AgentChatRuntimeSubmit): Promise<void>;\n};\n\ntype PendingThreadTransition = {\n reason: \"opened\" | \"deleted\";\n value: string | null;\n};\n\nexport function agentChatRuntimeStateFromError(error: unknown): AgentChatRuntimeViewState {\n const typed = error as Partial<Agents24ClientError> | null;\n if (typed?.kind === \"authentication\") return \"expired\";\n if (typed?.kind === \"authorization\") return \"denied\";\n if (typed?.kind === \"quota\" || typed?.kind === \"rate_limit\") return \"quota\";\n if (typed?.kind === \"network\") return \"offline\";\n return \"failed\";\n}\n\nexport function agentChatRuntimeErrorMessage(error: unknown): string | null {\n if (!error) return null;\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function canChangeAgentRuntime(\n runState: AgentChatController[\"runState\"],\n activeRunId: string | null,\n): boolean {\n return !activeRunId && ![\"streaming\", \"reconnecting\", \"paused\", \"cancelling\"].includes(runState);\n}\n\nexport function agentIdFromBootstrap(\n bootstrap: ClientBootstrap,\n requestedAgentId: string | null,\n): string | null {\n const feature = bootstrap.features.agents;\n if (!feature) return null;\n return feature.options.some((item) => item.id === requestedAgentId)\n ? requestedAgentId\n : feature.default_id || null;\n}\n\nexport function modelsFromAgentChatBootstrap(bootstrap: ClientBootstrap): {\n defaultModelId: string | null;\n models: AgentChatRuntimeModel[];\n} {\n const modelFeatures = bootstrap.features.models;\n const selectable = bootstrap.capabilities.includes(\"models.select\") && modelFeatures?.selectable === true;\n if (!selectable) return { defaultModelId: null, models: [] };\n const models = Array.isArray(modelFeatures.options)\n ? modelFeatures.options.flatMap((option) => (\n typeof option?.id === \"string\" && option.id.trim()\n ? [{ id: option.id, label: typeof option.label === \"string\" && option.label.trim() ? option.label : option.id }]\n : []\n ))\n : [];\n const configuredDefault = models.some((model) => model.id === modelFeatures.default_id)\n ? modelFeatures.default_id\n : null;\n return {\n defaultModelId: configuredDefault,\n models,\n };\n}\n\nfunction modelsFromEffectivePolicy(policy: EffectiveResourcePolicy): {\n defaultModelId: string | null;\n models: AgentChatRuntimeModel[];\n} {\n const models = policy.model_selection.selectable\n ? policy.model_selection.options.map((option) => ({ id: option.id, label: option.label }))\n : [];\n return {\n defaultModelId: models.some((model) => model.id === policy.model_selection.default_id)\n ? policy.model_selection.default_id\n : null,\n models,\n };\n}\n\nfunction hitlKey(part: ChatHitlPart): string {\n return part.interruptId || part.id;\n}\n\nexport function useAgentChatRuntime(options: UseAgentChatRuntimeOptions): AgentChatRuntime {\n const {\n activeThreadId,\n agent: agentOverride,\n client,\n completeMcpAuthorization,\n mcpRedirectUri,\n modelId,\n onActiveThreadIdChange,\n onModelChange,\n } = options;\n const controller = useAgentChat(\n activeThreadId === undefined ? { client } : { activeThreadId, client },\n );\n const attachments = useAgentAttachments();\n const mcp = useAgentMcp();\n const [bootstrap, setBootstrap] = React.useState<ClientBootstrap | null>(null);\n const bootstrapRef = React.useRef<ClientBootstrap | null>(bootstrap);\n bootstrapRef.current = bootstrap;\n const [effectivePolicy, setEffectivePolicy] = React.useState<EffectiveResourcePolicy | null>(null);\n const [isBootstrapping, setIsBootstrapping] = React.useState(true);\n const [bootstrapError, setBootstrapError] = React.useState<unknown>(null);\n const [localOperationError, setLocalOperationError] = React.useState<unknown>(null);\n const [selectedModelId, setSelectedModelId] = React.useState<string | null>(modelId ?? null);\n const selectedModelIdRef = React.useRef<string | null>(selectedModelId);\n selectedModelIdRef.current = selectedModelId;\n const [selectedAgentId, setSelectedAgentId] = React.useState<string | null>(null);\n const selectedAgentIdRef = React.useRef<string | null>(null);\n selectedAgentIdRef.current = selectedAgentId;\n const [isChangingAgent, setIsChangingAgent] = React.useState(false);\n const agentChangePromiseRef = React.useRef<Promise<void> | null>(null);\n const [isSubmitting, setIsSubmitting] = React.useState(false);\n const submitPromiseRef = React.useRef<Promise<void> | null>(null);\n const [hitlStates, setHitlStates] = React.useState<Record<string, AgentChatRuntimeHitlActionState>>({});\n const hitlStatesRef = React.useRef(hitlStates);\n hitlStatesRef.current = hitlStates;\n\n const mountedRef = React.useRef(true);\n const clientRef = React.useRef(client);\n clientRef.current = client;\n const bootstrapPromiseRef = React.useRef<{ client: AgentClient; promise: Promise<void> } | null>(null);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => { mountedRef.current = false; };\n }, []);\n\n const previousControlledThreadRef = React.useRef(activeThreadId);\n const controlledSyncTargetRef = React.useRef<{ value: string | null } | null>(null);\n const previousControllerThreadRef = React.useRef(controller.activeThreadId);\n const pendingThreadTransitionRef = React.useRef<PendingThreadTransition | null>(null);\n const lastReportedThreadRef = React.useRef<string | null>(activeThreadId ?? controller.activeThreadId);\n if (activeThreadId !== previousControlledThreadRef.current) {\n previousControlledThreadRef.current = activeThreadId;\n if (activeThreadId !== undefined) {\n controlledSyncTargetRef.current = { value: activeThreadId };\n lastReportedThreadRef.current = activeThreadId;\n }\n }\n\n const reportActiveThread = React.useCallback((\n threadId: string | null,\n reason: AgentChatThreadChangeReason,\n ) => {\n if (lastReportedThreadRef.current === threadId) return;\n lastReportedThreadRef.current = threadId;\n onActiveThreadIdChange?.({ threadId, reason });\n }, [onActiveThreadIdChange]);\n\n const retryBootstrap = React.useCallback((): Promise<void> => {\n if (bootstrapPromiseRef.current?.client === client) return bootstrapPromiseRef.current.promise;\n const requestClient = client;\n const request = (async () => {\n if (mountedRef.current) {\n setIsBootstrapping(true);\n setBootstrapError(null);\n setBootstrap(null);\n setEffectivePolicy(null);\n }\n try {\n const requestedAgentId = selectedAgentIdRef.current;\n const result = await requestClient.bootstrap({ agentId: requestedAgentId || undefined });\n if (!mountedRef.current || clientRef.current !== requestClient) return;\n setBootstrap(result);\n const agentFeature = result.features.agents;\n const resolvedAgentId = agentIdFromBootstrap(result, requestedAgentId);\n setSelectedAgentId(resolvedAgentId);\n const entitlement = agentFeature ? null : await requestClient.resourcePolicies.getEffective();\n if (!mountedRef.current || clientRef.current !== requestClient) return;\n setEffectivePolicy(entitlement);\n const availableModels = entitlement ? modelsFromEffectivePolicy(entitlement) : modelsFromAgentChatBootstrap(result);\n if (modelId === undefined) {\n setSelectedModelId((current) => availableModels.models.some((item) => item.id === current)\n ? current\n : availableModels.defaultModelId);\n }\n await controller.refreshThreads().catch(() => undefined);\n } catch (error) {\n if (mountedRef.current && clientRef.current === requestClient) setBootstrapError(error);\n } finally {\n if (mountedRef.current && clientRef.current === requestClient) setIsBootstrapping(false);\n }\n })();\n bootstrapPromiseRef.current = { client: requestClient, promise: request };\n void request.finally(() => {\n if (bootstrapPromiseRef.current?.promise === request) bootstrapPromiseRef.current = null;\n });\n return request;\n }, [client, controller.refreshThreads, modelId]);\n\n const refreshEffectivePolicy = React.useCallback(async () => {\n if (bootstrap?.features.agents) {\n const refreshed = await client.bootstrap({ agentId: selectedAgentIdRef.current || undefined });\n if (!mountedRef.current || clientRef.current !== client) return;\n setBootstrap(refreshed);\n const available = modelsFromAgentChatBootstrap(refreshed);\n setSelectedModelId((current) => available.models.some((item) => item.id === current)\n ? current\n : available.defaultModelId);\n return;\n }\n const entitlement = await client.resourcePolicies.getEffective();\n if (!mountedRef.current || clientRef.current !== client) return;\n setEffectivePolicy(entitlement);\n if (modelId === undefined) {\n const available = modelsFromEffectivePolicy(entitlement);\n setSelectedModelId((current) => available.models.some((item) => item.id === current)\n ? current\n : available.defaultModelId);\n }\n }, [bootstrap, client, modelId]);\n\n React.useEffect(() => {\n void retryBootstrap();\n }, [retryBootstrap]);\n\n React.useEffect(() => {\n if (modelId !== undefined) setSelectedModelId(modelId);\n }, [modelId]);\n\n React.useEffect(() => {\n hitlStatesRef.current = {};\n setHitlStates({});\n }, [client, controller.activeThreadId]);\n\n React.useEffect(() => {\n if (controlledSyncTargetRef.current?.value === null && controller.activeThreadId) {\n controller.startNewThread();\n }\n }, [activeThreadId, controller.activeThreadId, controller.startNewThread]);\n\n React.useEffect(() => {\n const previous = previousControllerThreadRef.current;\n const current = controller.activeThreadId;\n previousControllerThreadRef.current = current;\n const controlledTarget = controlledSyncTargetRef.current;\n if (controlledTarget) {\n if (current === controlledTarget.value) controlledSyncTargetRef.current = null;\n return;\n }\n const pendingTransition = pendingThreadTransitionRef.current;\n if (pendingTransition && current === pendingTransition.value) return;\n if (previous === null && current !== null) reportActiveThread(current, \"created\");\n }, [activeThreadId, controller.activeThreadId, reportActiveThread]);\n\n const clearOperationError = React.useCallback(() => {\n setLocalOperationError(null);\n controller.clearOperationError();\n }, [controller.clearOperationError]);\n\n const submit = React.useCallback((input: AgentChatRuntimeSubmit): Promise<void> => {\n if (submitPromiseRef.current) return submitPromiseRef.current;\n clearOperationError();\n setIsSubmitting(true);\n const request = (async () => {\n try {\n await agentChangePromiseRef.current;\n const activeBootstrap = bootstrapRef.current;\n if (!activeBootstrap) throw new Error(\"The agent input contract is unavailable.\");\n const inputError = validateAgentChatSubmission(activeBootstrap.features.inputs, input.text, input.files || []);\n if (inputError) throw new Error(inputError);\n const uploaded = input.files?.length\n ? await attachments.uploadBatch({\n uploads: input.files,\n threadId: controller.activeThreadId || undefined,\n requestedAgentId: selectedAgentIdRef.current || undefined,\n })\n : [];\n await controller.submit({\n text: input.text,\n attachmentIds: uploaded.flatMap((attachment) => attachment.id ? [attachment.id] : []),\n attachments: uploaded,\n requestedModelId: selectedModelIdRef.current || undefined,\n requestedAgentId: selectedAgentIdRef.current || undefined,\n });\n } catch (error) {\n setLocalOperationError(error);\n const typed = error as Partial<Agents24ClientError>;\n if (typed.kind === \"quota\" || typed.kind === \"authorization\") {\n await refreshEffectivePolicy().catch(() => undefined);\n }\n throw error;\n } finally {\n setIsSubmitting(false);\n }\n })();\n submitPromiseRef.current = request;\n const clearRequest = () => {\n if (submitPromiseRef.current === request) submitPromiseRef.current = null;\n };\n void request.then(clearRequest, clearRequest);\n return request;\n }, [attachments, bootstrap, clearOperationError, controller.activeThreadId, controller.submit, refreshEffectivePolicy]);\n\n const completeMcp = React.useCallback(async (part: ChatHitlPart) => {\n if (!mcpRedirectUri) throw new Error(\"mcpRedirectUri is required for MCP Connect.\");\n const serverId = String(part.presentation.server_id || \"\").trim();\n if (!serverId) throw new Error(\"MCP authorization is missing its server identity.\");\n const runId = controller.activeRunId || controller.messages.find((message) => message.parts.includes(part))?.runId;\n if (!runId) throw new Error(\"MCP authorization is missing its paused run.\");\n const popupNonce = browserChatCrypto().randomUUID();\n const proof = await createMcpPkceProof();\n const popup = window.open(\"about:blank\", \"agents24-mcp\", \"popup,width=560,height=720\");\n if (!popup) throw new Error(\"Allow popups to connect this MCP account.\");\n popup.document.title = \"Connecting to MCP\";\n popup.document.body.textContent = \"Opening secure connection…\";\n try {\n const started = await mcp.startAuthorization({\n runId,\n serverId,\n interruptId: part.interruptId,\n redirectUri: mcpRedirectUri,\n popupNonce,\n codeChallenge: proof.challenge,\n });\n if (!started.callback_origin) throw new Error(\"MCP authorization did not return a callback origin.\");\n popup.location.replace(started.authorization_url);\n const completion = await waitForMcpOauthComplete({\n popup,\n callbackOrigin: started.callback_origin,\n popupNonce,\n requireConnectionId: Boolean(completeMcpAuthorization),\n serverId,\n });\n if (completeMcpAuthorization) {\n await completeMcpAuthorization({ completion, codeVerifier: proof.verifier, serverId });\n } else {\n const redeemed = await mcp.redeemCallback({ code: completion.code, codeVerifier: proof.verifier });\n validateMcpCallbackResult(redeemed, serverId);\n }\n } finally {\n popup.close();\n }\n }, [completeMcpAuthorization, controller.activeRunId, controller.messages, mcp, mcpRedirectUri]);\n\n const onHitlAction = React.useCallback(async (part: ChatHitlPart, response: HitlResponse) => {\n const action = response.action;\n const key = hitlKey(part);\n const current = hitlStatesRef.current[key];\n if (current?.status === \"connecting\" || current?.status === \"resuming\") return;\n clearOperationError();\n const pending: AgentChatRuntimeHitlActionState = {\n action,\n status: part.hitlKind === \"mcp_auth\" && action === \"connect\" ? \"connecting\" : \"resuming\",\n };\n hitlStatesRef.current = { ...hitlStatesRef.current, [key]: pending };\n setHitlStates(hitlStatesRef.current);\n try {\n if (part.hitlKind === \"mcp_auth\" && action === \"connect\") await completeMcp(part);\n await controller.resumeHitl(part, response);\n setHitlStates((states) => {\n const next = { ...states };\n delete next[key];\n hitlStatesRef.current = next;\n return next;\n });\n } catch (error) {\n setLocalOperationError(error);\n const failedState = {\n ...hitlStatesRef.current,\n [key]: { action, error: agentChatRuntimeErrorMessage(error), status: \"error\" },\n } satisfies Record<string, AgentChatRuntimeHitlActionState>;\n hitlStatesRef.current = failedState;\n setHitlStates(failedState);\n throw error;\n }\n }, [clearOperationError, completeMcp, controller.resumeHitl]);\n\n const newThread = React.useCallback(() => {\n clearOperationError();\n pendingThreadTransitionRef.current = null;\n reportActiveThread(null, \"new\");\n controller.startNewThread();\n }, [clearOperationError, controller.startNewThread, reportActiveThread]);\n\n const openThread = React.useCallback(async (threadId: string) => {\n clearOperationError();\n pendingThreadTransitionRef.current = { reason: \"opened\", value: threadId };\n try {\n const detail = await client.threads.get({ threadId });\n const preferredAgentId = detail.runtime_selection?.agent_alias || detail.runtime_selection?.agent_id || null;\n if (preferredAgentId) {\n const result = await client.bootstrap({ agentId: preferredAgentId });\n const resolvedAgentId = agentIdFromBootstrap(result, preferredAgentId);\n setBootstrap(result);\n setEffectivePolicy(null);\n setSelectedAgentId(resolvedAgentId);\n const available = modelsFromAgentChatBootstrap(result);\n const preferredModelId = detail.runtime_selection?.model_id || null;\n setSelectedModelId(available.models.some((item) => item.id === preferredModelId)\n ? preferredModelId\n : available.defaultModelId);\n }\n await controller.openThread(threadId);\n reportActiveThread(threadId, \"opened\");\n } catch (error) {\n setLocalOperationError(error);\n throw error;\n } finally {\n if (pendingThreadTransitionRef.current?.value === threadId) pendingThreadTransitionRef.current = null;\n }\n }, [clearOperationError, client, controller.openThread, reportActiveThread]);\n\n const deleteThread = React.useCallback(async (threadId: string) => {\n clearOperationError();\n const wasActive = controller.activeThreadId === threadId;\n if (wasActive) pendingThreadTransitionRef.current = { reason: \"deleted\", value: null };\n try {\n await controller.deleteThread(threadId);\n if (wasActive) reportActiveThread(null, \"deleted\");\n } catch (error) {\n setLocalOperationError(error);\n throw error;\n } finally {\n if (wasActive && pendingThreadTransitionRef.current?.reason === \"deleted\") {\n pendingThreadTransitionRef.current = null;\n }\n }\n }, [clearOperationError, controller.activeThreadId, controller.deleteThread, reportActiveThread]);\n\n const changeModel = React.useCallback((nextModelId: string) => {\n if (modelId === undefined) setSelectedModelId(nextModelId);\n onModelChange?.(nextModelId);\n if (controller.activeThreadId && selectedAgentId && client.threads.setRuntimeSelection) {\n void client.threads.setRuntimeSelection({\n threadId: controller.activeThreadId,\n preferredAgentId: selectedAgentId,\n preferredModelId: nextModelId,\n }).catch(setLocalOperationError);\n }\n }, [client.threads, controller.activeThreadId, modelId, onModelChange, selectedAgentId]);\n\n const changeAgent = React.useCallback((nextAgentId: string): Promise<void> => {\n if (agentChangePromiseRef.current) return agentChangePromiseRef.current;\n if (\n nextAgentId === selectedAgentIdRef.current\n || !canChangeAgentRuntime(controller.runState, controller.activeRunId)\n ) return Promise.resolve();\n clearOperationError();\n setIsChangingAgent(true);\n const request = (async () => {\n try {\n const result = await client.bootstrap({ agentId: nextAgentId });\n const resolvedAgentId = agentIdFromBootstrap(result, nextAgentId);\n if (!resolvedAgentId) throw new Error(\"The requested Agent is no longer available.\");\n const available = modelsFromAgentChatBootstrap(result);\n const currentModelId = selectedModelIdRef.current;\n const nextModelId = available.models.some((item) => item.id === currentModelId)\n ? currentModelId\n : available.defaultModelId;\n if (controller.activeThreadId && client.threads.setRuntimeSelection) {\n const persisted = await client.threads.setRuntimeSelection({\n threadId: controller.activeThreadId,\n preferredAgentId: resolvedAgentId,\n preferredModelId: nextModelId,\n });\n selectedModelIdRef.current = persisted.runtime_selection.model_id;\n setSelectedModelId(persisted.runtime_selection.model_id);\n } else {\n selectedModelIdRef.current = nextModelId;\n setSelectedModelId(nextModelId);\n }\n selectedAgentIdRef.current = resolvedAgentId;\n bootstrapRef.current = result;\n setSelectedAgentId(resolvedAgentId);\n setBootstrap(result);\n setEffectivePolicy(null);\n } catch (error) {\n setLocalOperationError(error);\n throw error;\n }\n })();\n agentChangePromiseRef.current = request;\n const clearRequest = () => {\n if (agentChangePromiseRef.current === request) agentChangePromiseRef.current = null;\n if (mountedRef.current) setIsChangingAgent(false);\n };\n void request.then(clearRequest, clearRequest);\n return request;\n }, [clearOperationError, client, controller.activeRunId, controller.activeThreadId, controller.runState]);\n\n const modelOptions = effectivePolicy\n ? modelsFromEffectivePolicy(effectivePolicy).models\n : bootstrap\n ? modelsFromAgentChatBootstrap(bootstrap).models\n : [];\n const fatalError = bootstrapError || controller.error;\n const operationError = localOperationError || controller.operationError?.cause;\n const state: AgentChatRuntimeViewState = isBootstrapping\n ? \"loading\"\n : fatalError\n ? agentChatRuntimeStateFromError(fatalError)\n : controller.runState === \"streaming\"\n ? \"streaming\"\n : controller.runState === \"reconnecting\"\n ? \"reconnecting\"\n : controller.runState === \"paused\"\n ? \"paused\"\n : controller.runState === \"cancelling\"\n ? \"cancelling\"\n : controller.runState === \"cancelled\"\n ? \"cancelled\"\n : \"ready\";\n const connectionState: AgentChatRuntimeConnectionState = state === \"offline\"\n ? \"offline\"\n : state === \"expired\"\n ? \"expired\"\n : state === \"reconnecting\"\n ? \"reconnecting\"\n : isBootstrapping\n ? \"connecting\"\n : \"connected\";\n return {\n agent: agentOverride || { name: bootstrap?.deployment.name || \"Agent\" },\n inputContract: bootstrap?.features.inputs || null,\n allowFeedback: Boolean(bootstrap?.capabilities.includes(\"feedback.write\")),\n backgroundError: controller.backgroundError?.cause || null,\n bootstrap,\n capabilities: bootstrap?.capabilities || [],\n agentId: selectedAgentId,\n agents: bootstrap?.features.agents?.options.map((item) => ({ id: item.id, label: item.label })) || [],\n changeAgent,\n changeModel,\n clearOperationError,\n connectionState,\n contextWindow: controller.contextWindow,\n contextCompression: controller.contextCompression,\n controller,\n deleteThread,\n errorMessage: agentChatRuntimeErrorMessage(fatalError || operationError),\n fatalError,\n getHitlActionState: (part) => hitlStates[hitlKey(part)],\n isBootstrapping,\n isChangingAgent,\n isSubmitting: isSubmitting || controller.isSubmitting,\n isUploading: attachments.isUploading,\n modelId: selectedModelId,\n models: modelOptions,\n newThread,\n onHitlAction,\n openThread,\n operationError,\n retryBootstrap,\n state,\n submit,\n };\n}\n","import type { ClientInputFeature, PortableUpload } from \"@agents24/client\";\n\nexport type AgentChatInputContract = ClientInputFeature;\n\nexport const SUPPORTED_INPUT_MIME_TYPES = {\n files: [\"application/pdf\", \"text/plain\", \"text/markdown\", \"text/csv\", \"application/json\"],\n images: [\"image/png\", \"image/jpeg\", \"image/webp\"],\n audio: [\"audio/wav\", \"audio/mpeg\", \"audio/webm\", \"audio/mp4\"],\n} as const;\n\nexport type WorkflowInputRule = {\n key: string;\n enabled?: boolean;\n required?: boolean;\n};\n\nexport function workflowInputRule(\n inputs: readonly WorkflowInputRule[] | null | undefined,\n key: string,\n): { enabled: boolean; required: boolean } {\n const input = inputs?.find((candidate) => candidate.key === key);\n return {\n enabled: input?.enabled !== false,\n required: input?.required === true,\n };\n}\n\nexport function validateWorkflowInputSubmission(\n inputs: readonly WorkflowInputRule[] | null | undefined,\n text: string,\n attachmentMimeTypes: readonly string[],\n): string | null {\n const present = { files: false, images: false, audio: false };\n if (text.trim() && !workflowInputRule(inputs, \"text\").enabled) {\n return \"This workflow does not accept text input.\";\n }\n for (const rawMimeType of attachmentMimeTypes) {\n const mimeType = canonicalInputMimeType(rawMimeType);\n const modality = mimeType.startsWith(\"image/\") ? \"images\" : mimeType.startsWith(\"audio/\") ? \"audio\" : \"files\";\n const supported = (SUPPORTED_INPUT_MIME_TYPES[modality] as readonly string[]).includes(mimeType);\n if (!supported || !workflowInputRule(inputs, modality).enabled) {\n return `The attachment type ${mimeType || \"unknown\"} is not accepted.`;\n }\n present[modality] = true;\n }\n if (workflowInputRule(inputs, \"text\").required && !text.trim()) return \"Text input is required.\";\n for (const modality of [\"files\", \"images\", \"audio\"] as const) {\n if (workflowInputRule(inputs, modality).required && !present[modality]) {\n return `${modality[0].toUpperCase()}${modality.slice(1)} input is required.`;\n }\n }\n return null;\n}\n\nexport function canonicalInputMimeType(value: string): string {\n const normalized = value.split(\";\", 1)[0]?.trim().toLowerCase() || \"\";\n if (normalized === \"image/jpg\") return \"image/jpeg\";\n if ([\"audio/x-wav\"].includes(normalized)) return \"audio/wav\";\n if ([\"audio/x-m4a\", \"audio/m4a\"].includes(normalized)) return \"audio/mp4\";\n return normalized;\n}\n\nfunction uploadByteSize(data: PortableUpload[\"data\"]): number {\n if (data instanceof Uint8Array || data instanceof ArrayBuffer) return data.byteLength;\n return data.size;\n}\n\nexport function inputMimeTypes(contract: AgentChatInputContract | null | undefined): string[] {\n if (!contract) return [];\n return [\n ...contract.modalities.files.allowed_mime_types,\n ...contract.modalities.images.allowed_mime_types,\n ...contract.modalities.audio.allowed_mime_types,\n ];\n}\n\nexport function validateAgentChatSubmission(\n contract: AgentChatInputContract,\n text: string,\n files: readonly Pick<PortableUpload, \"mediaType\" | \"data\">[],\n): string | null {\n const { modalities, limits } = contract;\n const normalizedText = text.trim();\n if (normalizedText && !modalities.text.enabled) return \"This agent does not accept text input.\";\n if (modalities.text.required && !normalizedText) return \"Text input is required.\";\n if (files.length > limits.max_attachments_per_turn) {\n return `You can attach up to ${limits.max_attachments_per_turn} items per message.`;\n }\n let totalBytes = 0;\n const present = { files: false, images: false, audio: false };\n for (const file of files) {\n const mediaType = canonicalInputMimeType(file.mediaType);\n const modality = mediaType.startsWith(\"image/\") ? \"images\" : mediaType.startsWith(\"audio/\") ? \"audio\" : \"files\";\n const rule = modalities[modality];\n if (!rule.enabled || !rule.allowed_mime_types.includes(mediaType)) {\n return `The attachment type ${mediaType || \"unknown\"} is not accepted.`;\n }\n const byteSize = uploadByteSize(file.data);\n if (byteSize > limits.max_file_bytes) return \"An attachment exceeds the per-file size limit.\";\n totalBytes += byteSize;\n present[modality] = true;\n }\n if (totalBytes > limits.max_total_bytes) return \"Attachments exceed the total size limit.\";\n for (const modality of [\"files\", \"images\", \"audio\"] as const) {\n if (modalities[modality].required && !present[modality]) return `${modality[0].toUpperCase()}${modality.slice(1)} input is required.`;\n }\n return null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/runtime/use-agent-chat-runtime.ts","../../src/runtime/input-contract.ts"],"sourcesContent":["import type {\n AgentClient,\n Agents24ClientError,\n ClientBootstrap,\n EffectiveResourcePolicy,\n HitlResponse,\n PortableUpload,\n} from \"@agents24/client\";\nimport type { ContextCompression, ContextWindow } from \"@agents24/client/protocol\";\nimport {\n type AgentChatController,\n type ChatAttachment,\n type ChatHitlPart,\n useAgentAttachments,\n useAgentChat,\n useAgentMcp,\n} from \"@agents24/react\";\nimport * as React from \"react\";\n\nimport {\n browserChatCrypto,\n createMcpPkceProof,\n validateMcpCallbackResult,\n waitForMcpOauthComplete,\n} from \"../mcp-oauth\";\nimport type { ChatMcpOauthCompletion } from \"../types\";\nimport { validateAgentChatSubmission } from \"./input-contract\";\n\nexport type AgentChatRuntimeAgent = {\n name: string;\n description?: string | null;\n handle?: string | null;\n avatarUrl?: string | null;\n};\n\nexport type AgentChatRuntimeModel = {\n id: string;\n label: string;\n};\n\nexport type AgentChatRuntimeAgentOption = { id: string; label: string };\n\nexport type AgentChatRuntimeViewState =\n | \"ready\"\n | \"loading\"\n | \"uploading\"\n | \"streaming\"\n | \"reconnecting\"\n | \"paused\"\n | \"cancelling\"\n | \"cancelled\"\n | \"offline\"\n | \"denied\"\n | \"quota\"\n | \"failed\"\n | \"expired\";\n\nexport type AgentChatRuntimeConnectionState =\n | \"connected\"\n | \"connecting\"\n | \"reconnecting\"\n | \"offline\"\n | \"expired\";\n\nexport type AgentChatThreadChangeReason = \"created\" | \"opened\" | \"new\" | \"deleted\";\n\nexport type AgentChatActiveThreadChange = {\n threadId: string | null;\n reason: AgentChatThreadChangeReason;\n};\n\nexport type AgentChatActiveThreadChangeHandler = (\n change: AgentChatActiveThreadChange,\n) => void;\n\nexport type AgentChatMcpAuthorizationCompletion = (input: {\n completion: ChatMcpOauthCompletion;\n codeVerifier: string;\n serverId: string;\n}) => Promise<void>;\n\nexport type AgentChatRuntimeSubmit = {\n text: string;\n files?: readonly PortableUpload[];\n attachments?: ChatAttachment[];\n};\n\nexport type AgentChatRuntimeHitlActionState = {\n action: string;\n error?: string | null;\n status: \"connecting\" | \"resuming\" | \"error\";\n};\n\nexport type UseAgentChatRuntimeOptions = {\n activeThreadId?: string | null;\n agent?: AgentChatRuntimeAgent;\n client: AgentClient;\n completeMcpAuthorization?: AgentChatMcpAuthorizationCompletion;\n mcpRedirectUri?: string;\n modelId?: string | null;\n onActiveThreadIdChange?: AgentChatActiveThreadChangeHandler;\n onModelChange?: (modelId: string) => void;\n};\n\nexport type AgentChatRuntime = {\n agent: AgentChatRuntimeAgent;\n inputContract: ClientBootstrap[\"features\"][\"inputs\"] | null;\n allowFeedback: boolean;\n backgroundError: unknown;\n bootstrap: ClientBootstrap | null;\n capabilities: readonly string[];\n agentId: string | null;\n agents: AgentChatRuntimeAgentOption[];\n changeAgent(agentId: string): Promise<void>;\n changeModel(modelId: string): void;\n clearOperationError(): void;\n connectionState: AgentChatRuntimeConnectionState;\n contextWindow: ContextWindow | null;\n contextCompression: ContextCompression | null;\n controller: AgentChatController;\n deleteThread(threadId: string): Promise<void>;\n errorMessage: string | null;\n fatalError: unknown;\n getHitlActionState(part: ChatHitlPart): AgentChatRuntimeHitlActionState | undefined;\n isBootstrapping: boolean;\n isChangingAgent: boolean;\n isSubmitting: boolean;\n isUploading: boolean;\n modelId: string | null;\n models: AgentChatRuntimeModel[];\n newThread(): void;\n onHitlAction(part: ChatHitlPart, response: HitlResponse): Promise<void>;\n openThread(threadId: string): Promise<void>;\n operationError: unknown;\n retryBootstrap(): Promise<void>;\n resolveAttachmentContent(\n attachment: ChatAttachment,\n signal: AbortSignal,\n ): Promise<{ url: string; validUntil: string | null }>;\n state: AgentChatRuntimeViewState;\n submit(input: AgentChatRuntimeSubmit): Promise<void>;\n};\n\ntype PendingThreadTransition = {\n reason: \"opened\" | \"deleted\";\n value: string | null;\n};\n\nexport function agentChatRuntimeStateFromError(error: unknown): AgentChatRuntimeViewState {\n const typed = error as Partial<Agents24ClientError> | null;\n if (typed?.kind === \"authentication\") return \"expired\";\n if (typed?.kind === \"authorization\") return \"denied\";\n if (typed?.kind === \"quota\" || typed?.kind === \"rate_limit\") return \"quota\";\n if (typed?.kind === \"network\") return \"offline\";\n return \"failed\";\n}\n\nexport function agentChatRuntimeErrorMessage(error: unknown): string | null {\n if (!error) return null;\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function canChangeAgentRuntime(\n runState: AgentChatController[\"runState\"],\n activeRunId: string | null,\n): boolean {\n return !activeRunId && ![\"uploading\", \"streaming\", \"reconnecting\", \"paused\", \"cancelling\"].includes(runState);\n}\n\nexport function agentIdFromBootstrap(\n bootstrap: ClientBootstrap,\n requestedAgentId: string | null,\n): string | null {\n const feature = bootstrap.features.agents;\n if (!feature) return null;\n return feature.options.some((item) => item.id === requestedAgentId)\n ? requestedAgentId\n : feature.default_id || null;\n}\n\nexport function modelsFromAgentChatBootstrap(bootstrap: ClientBootstrap): {\n defaultModelId: string | null;\n models: AgentChatRuntimeModel[];\n} {\n const modelFeatures = bootstrap.features.models;\n const selectable = bootstrap.capabilities.includes(\"models.select\") && modelFeatures?.selectable === true;\n if (!selectable) return { defaultModelId: null, models: [] };\n const models = Array.isArray(modelFeatures.options)\n ? modelFeatures.options.flatMap((option) => (\n typeof option?.id === \"string\" && option.id.trim()\n ? [{ id: option.id, label: typeof option.label === \"string\" && option.label.trim() ? option.label : option.id }]\n : []\n ))\n : [];\n const configuredDefault = models.some((model) => model.id === modelFeatures.default_id)\n ? modelFeatures.default_id\n : null;\n return {\n defaultModelId: configuredDefault,\n models,\n };\n}\n\nfunction modelsFromEffectivePolicy(policy: EffectiveResourcePolicy): {\n defaultModelId: string | null;\n models: AgentChatRuntimeModel[];\n} {\n const models = policy.model_selection.selectable\n ? policy.model_selection.options.map((option) => ({ id: option.id, label: option.label }))\n : [];\n return {\n defaultModelId: models.some((model) => model.id === policy.model_selection.default_id)\n ? policy.model_selection.default_id\n : null,\n models,\n };\n}\n\nfunction hitlKey(part: ChatHitlPart): string {\n return part.interruptId || part.id;\n}\n\nexport function useAgentChatRuntime(options: UseAgentChatRuntimeOptions): AgentChatRuntime {\n const {\n activeThreadId,\n agent: agentOverride,\n client,\n completeMcpAuthorization,\n mcpRedirectUri,\n modelId,\n onActiveThreadIdChange,\n onModelChange,\n } = options;\n const controller = useAgentChat(\n activeThreadId === undefined ? { client } : { activeThreadId, client },\n );\n const attachments = useAgentAttachments();\n const mcp = useAgentMcp();\n const [bootstrap, setBootstrap] = React.useState<ClientBootstrap | null>(null);\n const bootstrapRef = React.useRef<ClientBootstrap | null>(bootstrap);\n bootstrapRef.current = bootstrap;\n const [effectivePolicy, setEffectivePolicy] = React.useState<EffectiveResourcePolicy | null>(null);\n const [isBootstrapping, setIsBootstrapping] = React.useState(true);\n const [bootstrapError, setBootstrapError] = React.useState<unknown>(null);\n const [localOperationError, setLocalOperationError] = React.useState<unknown>(null);\n const [selectedModelId, setSelectedModelId] = React.useState<string | null>(modelId ?? null);\n const selectedModelIdRef = React.useRef<string | null>(selectedModelId);\n selectedModelIdRef.current = selectedModelId;\n const [selectedAgentId, setSelectedAgentId] = React.useState<string | null>(null);\n const selectedAgentIdRef = React.useRef<string | null>(null);\n selectedAgentIdRef.current = selectedAgentId;\n const [isChangingAgent, setIsChangingAgent] = React.useState(false);\n const agentChangePromiseRef = React.useRef<Promise<void> | null>(null);\n const [isSubmitting, setIsSubmitting] = React.useState(false);\n const submitPromiseRef = React.useRef<Promise<void> | null>(null);\n const [hitlStates, setHitlStates] = React.useState<Record<string, AgentChatRuntimeHitlActionState>>({});\n const hitlStatesRef = React.useRef(hitlStates);\n hitlStatesRef.current = hitlStates;\n\n const mountedRef = React.useRef(true);\n const clientRef = React.useRef(client);\n clientRef.current = client;\n const bootstrapPromiseRef = React.useRef<{ client: AgentClient; promise: Promise<void> } | null>(null);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => { mountedRef.current = false; };\n }, []);\n\n const previousControlledThreadRef = React.useRef(activeThreadId);\n const controlledSyncTargetRef = React.useRef<{ value: string | null } | null>(null);\n const previousControllerThreadRef = React.useRef(controller.activeThreadId);\n const pendingThreadTransitionRef = React.useRef<PendingThreadTransition | null>(null);\n const lastReportedThreadRef = React.useRef<string | null>(activeThreadId ?? controller.activeThreadId);\n if (activeThreadId !== previousControlledThreadRef.current) {\n previousControlledThreadRef.current = activeThreadId;\n if (activeThreadId !== undefined) {\n controlledSyncTargetRef.current = { value: activeThreadId };\n lastReportedThreadRef.current = activeThreadId;\n }\n }\n\n const reportActiveThread = React.useCallback((\n threadId: string | null,\n reason: AgentChatThreadChangeReason,\n ) => {\n if (lastReportedThreadRef.current === threadId) return;\n lastReportedThreadRef.current = threadId;\n onActiveThreadIdChange?.({ threadId, reason });\n }, [onActiveThreadIdChange]);\n\n const retryBootstrap = React.useCallback((): Promise<void> => {\n if (bootstrapPromiseRef.current?.client === client) return bootstrapPromiseRef.current.promise;\n const requestClient = client;\n const request = (async () => {\n if (mountedRef.current) {\n setIsBootstrapping(true);\n setBootstrapError(null);\n setBootstrap(null);\n setEffectivePolicy(null);\n }\n try {\n const requestedAgentId = selectedAgentIdRef.current;\n const result = await requestClient.bootstrap({ agentId: requestedAgentId || undefined });\n if (!mountedRef.current || clientRef.current !== requestClient) return;\n setBootstrap(result);\n const agentFeature = result.features.agents;\n const resolvedAgentId = agentIdFromBootstrap(result, requestedAgentId);\n setSelectedAgentId(resolvedAgentId);\n const entitlement = agentFeature ? null : await requestClient.resourcePolicies.getEffective();\n if (!mountedRef.current || clientRef.current !== requestClient) return;\n setEffectivePolicy(entitlement);\n const availableModels = entitlement ? modelsFromEffectivePolicy(entitlement) : modelsFromAgentChatBootstrap(result);\n if (modelId === undefined) {\n setSelectedModelId((current) => availableModels.models.some((item) => item.id === current)\n ? current\n : availableModels.defaultModelId);\n }\n await controller.refreshThreads().catch(() => undefined);\n } catch (error) {\n if (mountedRef.current && clientRef.current === requestClient) setBootstrapError(error);\n } finally {\n if (mountedRef.current && clientRef.current === requestClient) setIsBootstrapping(false);\n }\n })();\n bootstrapPromiseRef.current = { client: requestClient, promise: request };\n void request.finally(() => {\n if (bootstrapPromiseRef.current?.promise === request) bootstrapPromiseRef.current = null;\n });\n return request;\n }, [client, controller.refreshThreads, modelId]);\n\n const refreshEffectivePolicy = React.useCallback(async () => {\n if (bootstrap?.features.agents) {\n const refreshed = await client.bootstrap({ agentId: selectedAgentIdRef.current || undefined });\n if (!mountedRef.current || clientRef.current !== client) return;\n setBootstrap(refreshed);\n const available = modelsFromAgentChatBootstrap(refreshed);\n setSelectedModelId((current) => available.models.some((item) => item.id === current)\n ? current\n : available.defaultModelId);\n return;\n }\n const entitlement = await client.resourcePolicies.getEffective();\n if (!mountedRef.current || clientRef.current !== client) return;\n setEffectivePolicy(entitlement);\n if (modelId === undefined) {\n const available = modelsFromEffectivePolicy(entitlement);\n setSelectedModelId((current) => available.models.some((item) => item.id === current)\n ? current\n : available.defaultModelId);\n }\n }, [bootstrap, client, modelId]);\n\n React.useEffect(() => {\n void retryBootstrap();\n }, [retryBootstrap]);\n\n React.useEffect(() => {\n if (modelId !== undefined) setSelectedModelId(modelId);\n }, [modelId]);\n\n React.useEffect(() => {\n hitlStatesRef.current = {};\n setHitlStates({});\n }, [client, controller.activeThreadId]);\n\n React.useEffect(() => {\n if (controlledSyncTargetRef.current?.value === null && controller.activeThreadId) {\n controller.startNewThread();\n }\n }, [activeThreadId, controller.activeThreadId, controller.startNewThread]);\n\n React.useEffect(() => {\n const previous = previousControllerThreadRef.current;\n const current = controller.activeThreadId;\n previousControllerThreadRef.current = current;\n const controlledTarget = controlledSyncTargetRef.current;\n if (controlledTarget) {\n if (current === controlledTarget.value) controlledSyncTargetRef.current = null;\n return;\n }\n const pendingTransition = pendingThreadTransitionRef.current;\n if (pendingTransition && current === pendingTransition.value) return;\n if (previous === null && current !== null) reportActiveThread(current, \"created\");\n }, [activeThreadId, controller.activeThreadId, reportActiveThread]);\n\n const clearOperationError = React.useCallback(() => {\n setLocalOperationError(null);\n controller.clearOperationError();\n }, [controller.clearOperationError]);\n\n const submit = React.useCallback((input: AgentChatRuntimeSubmit): Promise<void> => {\n if (submitPromiseRef.current) return submitPromiseRef.current;\n clearOperationError();\n setIsSubmitting(true);\n const request = (async () => {\n try {\n await agentChangePromiseRef.current;\n const activeBootstrap = bootstrapRef.current;\n if (!activeBootstrap) throw new Error(\"The agent input contract is unavailable.\");\n const inputError = validateAgentChatSubmission(activeBootstrap.features.inputs, input.text, input.files || []);\n if (inputError) throw new Error(inputError);\n await controller.submit({\n text: input.text,\n attachments: input.attachments,\n uploads: input.files,\n requestedModelId: selectedModelIdRef.current || undefined,\n requestedAgentId: selectedAgentIdRef.current || undefined,\n });\n } catch (error) {\n setLocalOperationError(error);\n const typed = error as Partial<Agents24ClientError>;\n if (typed.kind === \"quota\" || typed.kind === \"authorization\") {\n await refreshEffectivePolicy().catch(() => undefined);\n }\n throw error;\n } finally {\n setIsSubmitting(false);\n }\n })();\n submitPromiseRef.current = request;\n const clearRequest = () => {\n if (submitPromiseRef.current === request) submitPromiseRef.current = null;\n };\n void request.then(clearRequest, clearRequest);\n return request;\n }, [bootstrap, clearOperationError, controller.activeThreadId, controller.submit, refreshEffectivePolicy]);\n\n const completeMcp = React.useCallback(async (part: ChatHitlPart) => {\n if (!mcpRedirectUri) throw new Error(\"mcpRedirectUri is required for MCP Connect.\");\n const serverId = String(part.presentation.server_id || \"\").trim();\n if (!serverId) throw new Error(\"MCP authorization is missing its server identity.\");\n const runId = controller.activeRunId || controller.messages.find((message) => message.parts.includes(part))?.runId;\n if (!runId) throw new Error(\"MCP authorization is missing its paused run.\");\n const popupNonce = browserChatCrypto().randomUUID();\n const proof = await createMcpPkceProof();\n const popup = window.open(\"about:blank\", \"agents24-mcp\", \"popup,width=560,height=720\");\n if (!popup) throw new Error(\"Allow popups to connect this MCP account.\");\n popup.document.title = \"Connecting to MCP\";\n popup.document.body.textContent = \"Opening secure connection…\";\n try {\n const started = await mcp.startAuthorization({\n runId,\n serverId,\n interruptId: part.interruptId,\n redirectUri: mcpRedirectUri,\n popupNonce,\n codeChallenge: proof.challenge,\n });\n if (!started.callback_origin) throw new Error(\"MCP authorization did not return a callback origin.\");\n popup.location.replace(started.authorization_url);\n const completion = await waitForMcpOauthComplete({\n popup,\n callbackOrigin: started.callback_origin,\n popupNonce,\n requireConnectionId: Boolean(completeMcpAuthorization),\n serverId,\n });\n if (completeMcpAuthorization) {\n await completeMcpAuthorization({ completion, codeVerifier: proof.verifier, serverId });\n } else {\n const redeemed = await mcp.redeemCallback({ code: completion.code, codeVerifier: proof.verifier });\n validateMcpCallbackResult(redeemed, serverId);\n }\n } finally {\n popup.close();\n }\n }, [completeMcpAuthorization, controller.activeRunId, controller.messages, mcp, mcpRedirectUri]);\n\n const onHitlAction = React.useCallback(async (part: ChatHitlPart, response: HitlResponse) => {\n const action = response.action;\n const key = hitlKey(part);\n const current = hitlStatesRef.current[key];\n if (current?.status === \"connecting\" || current?.status === \"resuming\") return;\n clearOperationError();\n const pending: AgentChatRuntimeHitlActionState = {\n action,\n status: part.hitlKind === \"mcp_auth\" && action === \"connect\" ? \"connecting\" : \"resuming\",\n };\n hitlStatesRef.current = { ...hitlStatesRef.current, [key]: pending };\n setHitlStates(hitlStatesRef.current);\n try {\n if (part.hitlKind === \"mcp_auth\" && action === \"connect\") await completeMcp(part);\n await controller.resumeHitl(part, response);\n setHitlStates((states) => {\n const next = { ...states };\n delete next[key];\n hitlStatesRef.current = next;\n return next;\n });\n } catch (error) {\n setLocalOperationError(error);\n const failedState = {\n ...hitlStatesRef.current,\n [key]: { action, error: agentChatRuntimeErrorMessage(error), status: \"error\" },\n } satisfies Record<string, AgentChatRuntimeHitlActionState>;\n hitlStatesRef.current = failedState;\n setHitlStates(failedState);\n throw error;\n }\n }, [clearOperationError, completeMcp, controller.resumeHitl]);\n\n const newThread = React.useCallback(() => {\n clearOperationError();\n pendingThreadTransitionRef.current = null;\n reportActiveThread(null, \"new\");\n controller.startNewThread();\n }, [clearOperationError, controller.startNewThread, reportActiveThread]);\n\n const openThread = React.useCallback(async (threadId: string) => {\n clearOperationError();\n pendingThreadTransitionRef.current = { reason: \"opened\", value: threadId };\n try {\n const detail = await client.threads.get({ threadId });\n const preferredAgentId = detail.runtime_selection?.agent_alias || detail.runtime_selection?.agent_id || null;\n if (preferredAgentId) {\n const result = await client.bootstrap({ agentId: preferredAgentId });\n const resolvedAgentId = agentIdFromBootstrap(result, preferredAgentId);\n setBootstrap(result);\n setEffectivePolicy(null);\n setSelectedAgentId(resolvedAgentId);\n const available = modelsFromAgentChatBootstrap(result);\n const preferredModelId = detail.runtime_selection?.model_id || null;\n setSelectedModelId(available.models.some((item) => item.id === preferredModelId)\n ? preferredModelId\n : available.defaultModelId);\n }\n await controller.openThread(threadId);\n reportActiveThread(threadId, \"opened\");\n } catch (error) {\n setLocalOperationError(error);\n throw error;\n } finally {\n if (pendingThreadTransitionRef.current?.value === threadId) pendingThreadTransitionRef.current = null;\n }\n }, [clearOperationError, client, controller.openThread, reportActiveThread]);\n\n const deleteThread = React.useCallback(async (threadId: string) => {\n clearOperationError();\n const wasActive = controller.activeThreadId === threadId;\n if (wasActive) pendingThreadTransitionRef.current = { reason: \"deleted\", value: null };\n try {\n await controller.deleteThread(threadId);\n if (wasActive) reportActiveThread(null, \"deleted\");\n } catch (error) {\n setLocalOperationError(error);\n throw error;\n } finally {\n if (wasActive && pendingThreadTransitionRef.current?.reason === \"deleted\") {\n pendingThreadTransitionRef.current = null;\n }\n }\n }, [clearOperationError, controller.activeThreadId, controller.deleteThread, reportActiveThread]);\n\n const changeModel = React.useCallback((nextModelId: string) => {\n if (modelId === undefined) setSelectedModelId(nextModelId);\n onModelChange?.(nextModelId);\n if (controller.activeThreadId && selectedAgentId && client.threads.setRuntimeSelection) {\n void client.threads.setRuntimeSelection({\n threadId: controller.activeThreadId,\n preferredAgentId: selectedAgentId,\n preferredModelId: nextModelId,\n }).catch(setLocalOperationError);\n }\n }, [client.threads, controller.activeThreadId, modelId, onModelChange, selectedAgentId]);\n\n const resolveAttachmentContent = React.useCallback(async (\n attachment: ChatAttachment,\n signal: AbortSignal,\n ) => {\n const attachmentId = typeof attachment.id === \"string\" ? attachment.id.trim() : \"\";\n if (!attachmentId) throw new Error(\"Attachment content identity is unavailable.\");\n const access = await attachments.createContentAccess({\n attachmentId,\n disposition: \"inline\",\n signal,\n });\n return { url: access.url, validUntil: access.valid_until || null };\n }, [attachments.createContentAccess]);\n\n const changeAgent = React.useCallback((nextAgentId: string): Promise<void> => {\n if (agentChangePromiseRef.current) return agentChangePromiseRef.current;\n if (\n nextAgentId === selectedAgentIdRef.current\n || !canChangeAgentRuntime(controller.runState, controller.activeRunId)\n ) return Promise.resolve();\n clearOperationError();\n setIsChangingAgent(true);\n const request = (async () => {\n try {\n const result = await client.bootstrap({ agentId: nextAgentId });\n const resolvedAgentId = agentIdFromBootstrap(result, nextAgentId);\n if (!resolvedAgentId) throw new Error(\"The requested Agent is no longer available.\");\n const available = modelsFromAgentChatBootstrap(result);\n const currentModelId = selectedModelIdRef.current;\n const nextModelId = available.models.some((item) => item.id === currentModelId)\n ? currentModelId\n : available.defaultModelId;\n if (controller.activeThreadId && client.threads.setRuntimeSelection) {\n const persisted = await client.threads.setRuntimeSelection({\n threadId: controller.activeThreadId,\n preferredAgentId: resolvedAgentId,\n preferredModelId: nextModelId,\n });\n selectedModelIdRef.current = persisted.runtime_selection.model_id;\n setSelectedModelId(persisted.runtime_selection.model_id);\n } else {\n selectedModelIdRef.current = nextModelId;\n setSelectedModelId(nextModelId);\n }\n selectedAgentIdRef.current = resolvedAgentId;\n bootstrapRef.current = result;\n setSelectedAgentId(resolvedAgentId);\n setBootstrap(result);\n setEffectivePolicy(null);\n } catch (error) {\n setLocalOperationError(error);\n throw error;\n }\n })();\n agentChangePromiseRef.current = request;\n const clearRequest = () => {\n if (agentChangePromiseRef.current === request) agentChangePromiseRef.current = null;\n if (mountedRef.current) setIsChangingAgent(false);\n };\n void request.then(clearRequest, clearRequest);\n return request;\n }, [clearOperationError, client, controller.activeRunId, controller.activeThreadId, controller.runState]);\n\n const modelOptions = effectivePolicy\n ? modelsFromEffectivePolicy(effectivePolicy).models\n : bootstrap\n ? modelsFromAgentChatBootstrap(bootstrap).models\n : [];\n const fatalError = bootstrapError || controller.error;\n const operationError = localOperationError || controller.operationError?.cause;\n const state: AgentChatRuntimeViewState = isBootstrapping\n ? \"loading\"\n : fatalError\n ? agentChatRuntimeStateFromError(fatalError)\n : controller.runState === \"uploading\"\n ? \"uploading\"\n : controller.runState === \"streaming\"\n ? \"streaming\"\n : controller.runState === \"reconnecting\"\n ? \"reconnecting\"\n : controller.runState === \"paused\"\n ? \"paused\"\n : controller.runState === \"cancelling\"\n ? \"cancelling\"\n : controller.runState === \"cancelled\"\n ? \"cancelled\"\n : \"ready\";\n const connectionState: AgentChatRuntimeConnectionState = state === \"offline\"\n ? \"offline\"\n : state === \"expired\"\n ? \"expired\"\n : state === \"reconnecting\"\n ? \"reconnecting\"\n : isBootstrapping\n ? \"connecting\"\n : \"connected\";\n return {\n agent: agentOverride || { name: bootstrap?.deployment.name || \"Agent\" },\n inputContract: bootstrap?.features.inputs || null,\n allowFeedback: Boolean(bootstrap?.capabilities.includes(\"feedback.write\")),\n backgroundError: controller.backgroundError?.cause || null,\n bootstrap,\n capabilities: bootstrap?.capabilities || [],\n agentId: selectedAgentId,\n agents: bootstrap?.features.agents?.options.map((item) => ({ id: item.id, label: item.label })) || [],\n changeAgent,\n changeModel,\n clearOperationError,\n connectionState,\n contextWindow: controller.contextWindow,\n contextCompression: controller.contextCompression,\n controller,\n deleteThread,\n errorMessage: agentChatRuntimeErrorMessage(fatalError || operationError),\n fatalError,\n getHitlActionState: (part) => hitlStates[hitlKey(part)],\n isBootstrapping,\n isChangingAgent,\n isSubmitting: isSubmitting || controller.isSubmitting,\n isUploading: attachments.isUploading || controller.runState === \"uploading\",\n modelId: selectedModelId,\n models: modelOptions,\n newThread,\n onHitlAction,\n openThread,\n operationError,\n retryBootstrap,\n resolveAttachmentContent,\n state,\n submit,\n };\n}\n","import type { ClientInputFeature, PortableUpload } from \"@agents24/client\";\n\nexport type AgentChatInputContract = ClientInputFeature;\n\nexport const SUPPORTED_INPUT_MIME_TYPES = {\n files: [\"application/pdf\", \"text/plain\", \"text/markdown\", \"text/csv\", \"application/json\"],\n images: [\"image/png\", \"image/jpeg\", \"image/webp\"],\n audio: [\"audio/wav\", \"audio/mpeg\", \"audio/webm\", \"audio/mp4\"],\n} as const;\n\nexport type WorkflowInputRule = {\n key: string;\n enabled?: boolean;\n required?: boolean;\n};\n\nexport function workflowInputRule(\n inputs: readonly WorkflowInputRule[] | null | undefined,\n key: string,\n): { enabled: boolean; required: boolean } {\n const input = inputs?.find((candidate) => candidate.key === key);\n return {\n enabled: input?.enabled !== false,\n required: input?.required === true,\n };\n}\n\nexport function validateWorkflowInputSubmission(\n inputs: readonly WorkflowInputRule[] | null | undefined,\n text: string,\n attachmentMimeTypes: readonly string[],\n): string | null {\n const present = { files: false, images: false, audio: false };\n if (text.trim() && !workflowInputRule(inputs, \"text\").enabled) {\n return \"This workflow does not accept text input.\";\n }\n for (const rawMimeType of attachmentMimeTypes) {\n const mimeType = canonicalInputMimeType(rawMimeType);\n const modality = mimeType.startsWith(\"image/\") ? \"images\" : mimeType.startsWith(\"audio/\") ? \"audio\" : \"files\";\n const supported = (SUPPORTED_INPUT_MIME_TYPES[modality] as readonly string[]).includes(mimeType);\n if (!supported || !workflowInputRule(inputs, modality).enabled) {\n return `The attachment type ${mimeType || \"unknown\"} is not accepted.`;\n }\n present[modality] = true;\n }\n if (workflowInputRule(inputs, \"text\").required && !text.trim()) return \"Text input is required.\";\n for (const modality of [\"files\", \"images\", \"audio\"] as const) {\n if (workflowInputRule(inputs, modality).required && !present[modality]) {\n return `${modality[0].toUpperCase()}${modality.slice(1)} input is required.`;\n }\n }\n return null;\n}\n\nexport function canonicalInputMimeType(value: string): string {\n const normalized = value.split(\";\", 1)[0]?.trim().toLowerCase() || \"\";\n if (normalized === \"image/jpg\") return \"image/jpeg\";\n if ([\"audio/x-wav\"].includes(normalized)) return \"audio/wav\";\n if ([\"audio/x-m4a\", \"audio/m4a\"].includes(normalized)) return \"audio/mp4\";\n return normalized;\n}\n\nfunction uploadByteSize(data: PortableUpload[\"data\"]): number {\n if (data instanceof Uint8Array || data instanceof ArrayBuffer) return data.byteLength;\n return data.size;\n}\n\nexport function inputMimeTypes(contract: AgentChatInputContract | null | undefined): string[] {\n if (!contract) return [];\n return [\n ...contract.modalities.files.allowed_mime_types,\n ...contract.modalities.images.allowed_mime_types,\n ...contract.modalities.audio.allowed_mime_types,\n ];\n}\n\nexport function validateAgentChatSubmission(\n contract: AgentChatInputContract,\n text: string,\n files: readonly Pick<PortableUpload, \"mediaType\" | \"data\">[],\n): string | null {\n const { modalities, limits } = contract;\n const normalizedText = text.trim();\n if (normalizedText && !modalities.text.enabled) return \"This agent does not accept text input.\";\n if (modalities.text.required && !normalizedText) return \"Text input is required.\";\n if (files.length > limits.max_attachments_per_turn) {\n return `You can attach up to ${limits.max_attachments_per_turn} items per message.`;\n }\n let totalBytes = 0;\n const present = { files: false, images: false, audio: false };\n for (const file of files) {\n const mediaType = canonicalInputMimeType(file.mediaType);\n const modality = mediaType.startsWith(\"image/\") ? \"images\" : mediaType.startsWith(\"audio/\") ? \"audio\" : \"files\";\n const rule = modalities[modality];\n if (!rule.enabled || !rule.allowed_mime_types.includes(mediaType)) {\n return `The attachment type ${mediaType || \"unknown\"} is not accepted.`;\n }\n const byteSize = uploadByteSize(file.data);\n if (byteSize > limits.max_file_bytes) return \"An attachment exceeds the per-file size limit.\";\n totalBytes += byteSize;\n present[modality] = true;\n }\n if (totalBytes > limits.max_total_bytes) return \"Attachments exceed the total size limit.\";\n for (const modality of [\"files\", \"images\", \"audio\"] as const) {\n if (modalities[modality].required && !present[modality]) return `${modality[0].toUpperCase()}${modality.slice(1)} input is required.`;\n }\n return null;\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import type { AgentClient, ClientBootstrap, HitlResponse, PortableUpload } from "@agents24/client";
2
2
  import type { ContextCompression, ContextWindow } from "@agents24/client/protocol";
3
- import { type AgentChatController, type ChatHitlPart } from "@agents24/react";
3
+ import { type AgentChatController, type ChatAttachment, type ChatHitlPart } from "@agents24/react";
4
4
  import type { ChatMcpOauthCompletion } from "../types";
5
5
  export type AgentChatRuntimeAgent = {
6
6
  name: string;
@@ -16,7 +16,7 @@ export type AgentChatRuntimeAgentOption = {
16
16
  id: string;
17
17
  label: string;
18
18
  };
19
- export type AgentChatRuntimeViewState = "ready" | "loading" | "streaming" | "reconnecting" | "paused" | "cancelling" | "cancelled" | "offline" | "denied" | "quota" | "failed" | "expired";
19
+ export type AgentChatRuntimeViewState = "ready" | "loading" | "uploading" | "streaming" | "reconnecting" | "paused" | "cancelling" | "cancelled" | "offline" | "denied" | "quota" | "failed" | "expired";
20
20
  export type AgentChatRuntimeConnectionState = "connected" | "connecting" | "reconnecting" | "offline" | "expired";
21
21
  export type AgentChatThreadChangeReason = "created" | "opened" | "new" | "deleted";
22
22
  export type AgentChatActiveThreadChange = {
@@ -32,6 +32,7 @@ export type AgentChatMcpAuthorizationCompletion = (input: {
32
32
  export type AgentChatRuntimeSubmit = {
33
33
  text: string;
34
34
  files?: readonly PortableUpload[];
35
+ attachments?: ChatAttachment[];
35
36
  };
36
37
  export type AgentChatRuntimeHitlActionState = {
37
38
  action: string;
@@ -79,6 +80,10 @@ export type AgentChatRuntime = {
79
80
  openThread(threadId: string): Promise<void>;
80
81
  operationError: unknown;
81
82
  retryBootstrap(): Promise<void>;
83
+ resolveAttachmentContent(attachment: ChatAttachment, signal: AbortSignal): Promise<{
84
+ url: string;
85
+ validUntil: string | null;
86
+ }>;
82
87
  state: AgentChatRuntimeViewState;
83
88
  submit(input: AgentChatRuntimeSubmit): Promise<void>;
84
89
  };
@@ -1,3 +1,4 @@
1
+ import { type AgentChatComposerFile } from "@agents24/chat-react/ui";
1
2
  import { type AgentChatInputContract } from "@agents24/chat-react/runtime";
2
3
  import type { ContextWindow } from "@agents24/client/protocol";
3
4
  type ChatComposerProps = {
@@ -21,7 +22,7 @@ type ChatComposerProps = {
21
22
  onModelChange: (modelId: string) => void;
22
23
  onAgentChange: (agentId: string) => void;
23
24
  onStop: () => void;
24
- onSubmit: (text: string, files: File[]) => Promise<void>;
25
+ onSubmit: (text: string, files: AgentChatComposerFile[]) => Promise<void>;
25
26
  utilityRow?: "inline" | "below";
26
27
  };
27
28
  export declare function ChatComposer({ inputContract, disabled, contextWindow, focusKey, forceExpanded, isCancelling, isRunning, agentId, agents, modelId, models, onModelChange, onAgentChange, onStop, onSubmit, utilityRow, }: ChatComposerProps): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,7 @@
1
1
  import type { ChatHitlPart, ChatMessage as ChatMessageModel } from "@agents24/react";
2
2
  import type { FeedbackReason, HitlResponse } from "@agents24/client";
3
3
  import type { AgentChatRuntimeHitlActionState } from "@agents24/chat-react/runtime";
4
+ import { type ChatAttachmentContentResolver } from "@agents24/chat-react/ui";
4
5
  import * as React from "react";
5
6
  import type { Agents24ChatTimelineSlotProps } from "../../app";
6
7
  type Props = {
@@ -16,6 +17,7 @@ type Props = {
16
17
  comment?: string | null;
17
18
  }) => Promise<void>;
18
19
  Timeline?: React.ComponentType<Agents24ChatTimelineSlotProps>;
20
+ resolveAttachmentContent?: ChatAttachmentContentResolver;
19
21
  };
20
- export declare function ChatMessage({ allowFeedback, getHitlActionState, isLoading, message, onHitlAction, onRegenerate, onSetFeedback, Timeline, }: Props): import("react/jsx-runtime").JSX.Element;
22
+ export declare function ChatMessage({ allowFeedback, getHitlActionState, isLoading, message, onHitlAction, onRegenerate, onSetFeedback, resolveAttachmentContent, Timeline, }: Props): import("react/jsx-runtime").JSX.Element;
21
23
  export {};
@@ -524,11 +524,20 @@ function ChatComposer({
524
524
  const [attachmentError, setAttachmentError] = React2.useState(null);
525
525
  const inputRef = React2.useRef(null);
526
526
  const textareaRef = React2.useRef(null);
527
+ const filesRef = React2.useRef([]);
528
+ const inFlightFilesRef = React2.useRef([]);
527
529
  const submittingRef = React2.useRef(false);
528
530
  const draftRevisionRef = React2.useRef(0);
529
531
  const attachmentMimeTypes = (0, import_runtime.inputMimeTypes)(inputContract);
530
532
  const allowAttachments = attachmentMimeTypes.length > 0;
531
533
  const recordingAllowed = inputContract.modalities.audio.recording_enabled;
534
+ React2.useEffect(() => {
535
+ filesRef.current = files;
536
+ }, [files]);
537
+ React2.useEffect(() => () => {
538
+ (0, import_ui.revokeAgentChatComposerFiles)(filesRef.current);
539
+ (0, import_ui.revokeAgentChatComposerFiles)(inFlightFilesRef.current);
540
+ }, []);
532
541
  React2.useEffect(() => {
533
542
  if (disabled || isRunning) return;
534
543
  const frame = window.requestAnimationFrame(() => textareaRef.current?.focus({ preventScroll: true }));
@@ -536,14 +545,14 @@ function ChatComposer({
536
545
  }, [disabled, focusKey, isRunning]);
537
546
  const addRecording = React2.useCallback((file) => {
538
547
  draftRevisionRef.current += 1;
539
- setFiles((current) => [...current, file]);
548
+ setFiles((current) => [...current, (0, import_ui.createAgentChatComposerFile)(file)]);
540
549
  }, []);
541
550
  const recorder = (0, import_ui.useAudioRecorder)(addRecording);
542
551
  const isExpanded = forceExpanded || text.includes("\n") || text.length > 62;
543
552
  const validationError = (0, import_runtime.validateAgentChatSubmission)(
544
553
  inputContract,
545
554
  text,
546
- files.map((file) => ({ data: file, mediaType: file.type }))
555
+ files.map((file) => ({ data: file.source, mediaType: file.mediaType }))
547
556
  );
548
557
  const selectedAgent = agents.find((item) => item.id === agentId);
549
558
  const selectedModel = models.find((item) => item.id === modelId);
@@ -591,16 +600,23 @@ function ChatComposer({
591
600
  const clearedRevision = draftRevisionRef.current + 1;
592
601
  draftRevisionRef.current = clearedRevision;
593
602
  submittingRef.current = true;
603
+ inFlightFilesRef.current = selectedFiles;
594
604
  setText("");
595
605
  setFiles([]);
596
606
  textareaRef.current?.focus();
597
607
  try {
598
608
  await onSubmit(value, selectedFiles);
609
+ (0, import_ui.revokeAgentChatComposerFiles)(selectedFiles);
610
+ inFlightFilesRef.current = [];
599
611
  } catch {
600
612
  if (draftRevisionRef.current === clearedRevision) {
601
613
  draftRevisionRef.current += 1;
602
614
  setText(value);
603
615
  setFiles(selectedFiles);
616
+ inFlightFilesRef.current = [];
617
+ } else {
618
+ (0, import_ui.revokeAgentChatComposerFiles)(selectedFiles);
619
+ inFlightFilesRef.current = [];
604
620
  }
605
621
  } finally {
606
622
  submittingRef.current = false;
@@ -612,13 +628,21 @@ function ChatComposer({
612
628
  className: "mx-auto w-full max-w-3xl px-4 pb-[max(1rem,env(safe-area-inset-bottom))] sm:px-6",
613
629
  "data-agents24-chat-composer": "",
614
630
  children: [
615
- allowAttachments && files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mb-2 flex min-w-0 gap-2 overflow-x-auto", children: files.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex max-w-48 items-center gap-2 border bg-card px-2 py-1 text-xs", children: [
616
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: file.name }),
617
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Button, { variant: "ghost", size: "icon-xs", "aria-label": `Remove ${file.name}`, onClick: () => {
618
- draftRevisionRef.current += 1;
619
- setFiles((current) => current.filter((_, itemIndex) => itemIndex !== index));
620
- }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react3.X, {}) })
621
- ] }, `${file.name}-${index}`)) }),
631
+ allowAttachments && files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mb-2 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
632
+ import_ui.ChatAttachmentRows,
633
+ {
634
+ attachments: files,
635
+ onRemove: (attachment) => {
636
+ if (!attachment.id) return;
637
+ draftRevisionRef.current += 1;
638
+ setFiles((current) => {
639
+ const removed = current.find((file) => file.id === attachment.id);
640
+ if (removed) (0, import_ui.revokeAgentChatComposerFiles)([removed]);
641
+ return current.filter((file) => file.id !== attachment.id);
642
+ });
643
+ }
644
+ }
645
+ ) }),
622
646
  attachmentError || recorder.error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mb-2 text-xs text-destructive", role: "alert", children: attachmentError || recorder.error }) : null,
623
647
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
624
648
  "div",
@@ -642,7 +666,7 @@ function ChatComposer({
642
666
  const selected = Array.from(event.target.files ?? []);
643
667
  const accepted = selected.filter((file) => attachmentMimeTypes.includes((0, import_runtime.canonicalInputMimeType)(file.type)));
644
668
  draftRevisionRef.current += 1;
645
- setFiles((current) => [...current, ...accepted]);
669
+ setFiles((current) => [...current, ...accepted.map(import_ui.createAgentChatComposerFile)]);
646
670
  setAttachmentError(
647
671
  accepted.length === selected.length ? null : "One or more selected file types are not supported by this Agent."
648
672
  );
@@ -1134,17 +1158,19 @@ function ChatMessage({
1134
1158
  onHitlAction,
1135
1159
  onRegenerate,
1136
1160
  onSetFeedback,
1161
+ resolveAttachmentContent,
1137
1162
  Timeline
1138
1163
  }) {
1139
1164
  const isUser = message.role === "user";
1140
1165
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Message, { align: isUser ? "end" : "start", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(MessageContent, { children: [
1141
- isUser && message.attachments?.length ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_ui3.ChatAttachments, { className: "mb-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1142
- import_ui3.ChatAttachment,
1166
+ isUser && message.attachments?.length ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1167
+ import_ui3.ChatAttachmentRows,
1143
1168
  {
1144
- data: attachment
1145
- },
1146
- String(attachment.id || attachment.url || attachment.filename || index)
1147
- )) }) : null,
1169
+ attachments: message.attachments,
1170
+ className: "mb-2",
1171
+ resolveContent: resolveAttachmentContent
1172
+ }
1173
+ ) : null,
1148
1174
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Bubble, { variant: isUser ? "secondary" : "ghost", align: isUser ? "end" : "start", className: isUser ? "max-w-[min(75%,42rem)]" : "max-w-full overflow-visible", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(BubbleContent, { className: isUser ? "px-4 py-2.5" : "w-full overflow-visible", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1149
1175
  MessageParts,
1150
1176
  {
@@ -2179,7 +2205,8 @@ function ChatShell({
2179
2205
  sidebar
2180
2206
  }) {
2181
2207
  const { controller } = runtime;
2182
- const isRunning = controller.runState === "streaming" || controller.runState === "reconnecting" || controller.runState === "paused" || controller.runState === "cancelling" || runtime.isSubmitting;
2208
+ const isRunning = controller.runState === "streaming" || controller.runState === "reconnecting" || controller.runState === "paused" || controller.runState === "cancelling";
2209
+ const isUploading = controller.runState === "uploading" || runtime.isUploading;
2183
2210
  const isCancelling = controller.runState === "cancelling";
2184
2211
  const activeTitle = controller.threads.find((thread) => thread.id === controller.activeThreadId)?.title;
2185
2212
  const hasBlockingError = Boolean(runtime.fatalError && controller.messages.length === 0);
@@ -2235,7 +2262,7 @@ function ChatShell({
2235
2262
  {
2236
2263
  inputContract: runtime.inputContract || LOADING_INPUT_CONTRACT,
2237
2264
  contextWindow: runtime.contextWindow,
2238
- disabled: runtime.isBootstrapping || runtime.isChangingAgent,
2265
+ disabled: runtime.isBootstrapping || runtime.isChangingAgent || isUploading,
2239
2266
  focusKey: controller.activeThreadId,
2240
2267
  forceExpanded: true,
2241
2268
  isCancelling,
@@ -2254,10 +2281,11 @@ function ChatShell({
2254
2281
  onSubmit: (text, files) => runtime.submit({
2255
2282
  text,
2256
2283
  files: files.map((file) => ({
2257
- data: file,
2258
- mediaType: file.type || "application/octet-stream",
2259
- name: file.name
2260
- }))
2284
+ data: file.source,
2285
+ mediaType: file.mediaType,
2286
+ name: file.filename
2287
+ })),
2288
+ attachments: files
2261
2289
  })
2262
2290
  }
2263
2291
  )
@@ -2310,6 +2338,7 @@ function ChatShell({
2310
2338
  onHitlAction: runtime.onHitlAction,
2311
2339
  onRegenerate: () => controller.regenerate(message),
2312
2340
  onSetFeedback: (input) => controller.setFeedback(message, input),
2341
+ resolveAttachmentContent: runtime.resolveAttachmentContent,
2313
2342
  Timeline: components?.Timeline
2314
2343
  }
2315
2344
  )
@@ -2329,7 +2358,7 @@ function ChatShell({
2329
2358
  {
2330
2359
  inputContract: runtime.inputContract || LOADING_INPUT_CONTRACT,
2331
2360
  contextWindow: runtime.contextWindow,
2332
- disabled: runtime.isBootstrapping || runtime.isChangingAgent || hasBlockingError,
2361
+ disabled: runtime.isBootstrapping || runtime.isChangingAgent || hasBlockingError || isUploading,
2333
2362
  focusKey: controller.activeThreadId,
2334
2363
  isCancelling,
2335
2364
  isRunning,
@@ -2347,10 +2376,11 @@ function ChatShell({
2347
2376
  onSubmit: (text, files) => runtime.submit({
2348
2377
  text,
2349
2378
  files: files.map((file) => ({
2350
- data: file,
2351
- mediaType: file.type || "application/octet-stream",
2352
- name: file.name
2353
- }))
2379
+ data: file.source,
2380
+ mediaType: file.mediaType,
2381
+ name: file.filename
2382
+ })),
2383
+ attachments: files
2354
2384
  }),
2355
2385
  utilityRow: "below"
2356
2386
  }