@agents24/chat-react 0.5.4 → 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.
Files changed (34) hide show
  1. package/README.md +8 -2
  2. package/compatibility.json +4 -4
  3. package/dist/runtime/index.cjs +127 -18
  4. package/dist/runtime/index.cjs.map +1 -1
  5. package/dist/runtime/index.js +125 -18
  6. package/dist/runtime/index.js.map +1 -1
  7. package/dist/runtime/use-agent-chat-runtime.d.ts +17 -2
  8. package/dist/scaffold/app.d.ts +1 -0
  9. package/dist/scaffold/components/chat/chat-composer.d.ts +10 -2
  10. package/dist/scaffold/components/chat/chat-message.d.ts +3 -1
  11. package/dist/scaffold/components/chat/chat-shell.d.ts +3 -1
  12. package/dist/scaffold/index.cjs +415 -253
  13. package/dist/scaffold/index.cjs.map +1 -1
  14. package/dist/scaffold/index.js +408 -240
  15. package/dist/scaffold/index.js.map +1 -1
  16. package/dist/styles.css +18 -4
  17. package/dist/ui/adapters.d.ts +14 -2
  18. package/dist/ui/agent-chat-composer.d.ts +2 -9
  19. package/dist/ui/agent-chat-message.d.ts +3 -1
  20. package/dist/ui/composer-attachments.d.ts +11 -0
  21. package/dist/ui/index.cjs +653 -343
  22. package/dist/ui/index.cjs.map +1 -1
  23. package/dist/ui/index.d.ts +1 -0
  24. package/dist/ui/index.js +638 -328
  25. package/dist/ui/index.js.map +1 -1
  26. package/package.json +4 -3
  27. package/scaffold/src/app.tsx +2 -1
  28. package/scaffold/src/chat.css +13 -1
  29. package/scaffold/src/components/chat/chat-composer.tsx +107 -27
  30. package/scaffold/src/components/chat/chat-message.tsx +8 -9
  31. package/scaffold/src/components/chat/chat-shell.tsx +24 -11
  32. package/scaffold/src/components/ui/button.tsx +1 -1
  33. package/scaffold/src/components/ui/dropdown-menu.tsx +1 -1
  34. package/scaffold/src/components/ui/sidebar.tsx +4 -4
@@ -109,6 +109,14 @@ function agentChatRuntimeErrorMessage(error) {
109
109
  if (!error) return null;
110
110
  return error instanceof Error ? error.message : String(error);
111
111
  }
112
+ function canChangeAgentRuntime(runState, activeRunId) {
113
+ return !activeRunId && !["uploading", "streaming", "reconnecting", "paused", "cancelling"].includes(runState);
114
+ }
115
+ function agentIdFromBootstrap(bootstrap, requestedAgentId) {
116
+ const feature = bootstrap.features.agents;
117
+ if (!feature) return null;
118
+ return feature.options.some((item) => item.id === requestedAgentId) ? requestedAgentId : feature.default_id || null;
119
+ }
112
120
  function modelsFromAgentChatBootstrap(bootstrap) {
113
121
  const modelFeatures = bootstrap.features.models;
114
122
  const selectable = bootstrap.capabilities.includes("models.select") && modelFeatures?.selectable === true;
@@ -147,11 +155,20 @@ function useAgentChatRuntime(options) {
147
155
  const attachments = useAgentAttachments();
148
156
  const mcp = useAgentMcp();
149
157
  const [bootstrap, setBootstrap] = React.useState(null);
158
+ const bootstrapRef = React.useRef(bootstrap);
159
+ bootstrapRef.current = bootstrap;
150
160
  const [effectivePolicy, setEffectivePolicy] = React.useState(null);
151
161
  const [isBootstrapping, setIsBootstrapping] = React.useState(true);
152
162
  const [bootstrapError, setBootstrapError] = React.useState(null);
153
163
  const [localOperationError, setLocalOperationError] = React.useState(null);
154
164
  const [selectedModelId, setSelectedModelId] = React.useState(modelId ?? null);
165
+ const selectedModelIdRef = React.useRef(selectedModelId);
166
+ selectedModelIdRef.current = selectedModelId;
167
+ const [selectedAgentId, setSelectedAgentId] = React.useState(null);
168
+ const selectedAgentIdRef = React.useRef(null);
169
+ selectedAgentIdRef.current = selectedAgentId;
170
+ const [isChangingAgent, setIsChangingAgent] = React.useState(false);
171
+ const agentChangePromiseRef = React.useRef(null);
155
172
  const [isSubmitting, setIsSubmitting] = React.useState(false);
156
173
  const submitPromiseRef = React.useRef(null);
157
174
  const [hitlStates, setHitlStates] = React.useState({});
@@ -195,13 +212,17 @@ function useAgentChatRuntime(options) {
195
212
  setEffectivePolicy(null);
196
213
  }
197
214
  try {
198
- const result = await requestClient.bootstrap();
215
+ const requestedAgentId = selectedAgentIdRef.current;
216
+ const result = await requestClient.bootstrap({ agentId: requestedAgentId || void 0 });
199
217
  if (!mountedRef.current || clientRef.current !== requestClient) return;
200
218
  setBootstrap(result);
201
- const entitlement = await requestClient.resourcePolicies.getEffective();
219
+ const agentFeature = result.features.agents;
220
+ const resolvedAgentId = agentIdFromBootstrap(result, requestedAgentId);
221
+ setSelectedAgentId(resolvedAgentId);
222
+ const entitlement = agentFeature ? null : await requestClient.resourcePolicies.getEffective();
202
223
  if (!mountedRef.current || clientRef.current !== requestClient) return;
203
224
  setEffectivePolicy(entitlement);
204
- const availableModels = modelsFromEffectivePolicy(entitlement);
225
+ const availableModels = entitlement ? modelsFromEffectivePolicy(entitlement) : modelsFromAgentChatBootstrap(result);
205
226
  if (modelId === void 0) {
206
227
  setSelectedModelId((current) => availableModels.models.some((item) => item.id === current) ? current : availableModels.defaultModelId);
207
228
  }
@@ -219,6 +240,14 @@ function useAgentChatRuntime(options) {
219
240
  return request;
220
241
  }, [client, controller.refreshThreads, modelId]);
221
242
  const refreshEffectivePolicy = React.useCallback(async () => {
243
+ if (bootstrap?.features.agents) {
244
+ const refreshed = await client.bootstrap({ agentId: selectedAgentIdRef.current || void 0 });
245
+ if (!mountedRef.current || clientRef.current !== client) return;
246
+ setBootstrap(refreshed);
247
+ const available = modelsFromAgentChatBootstrap(refreshed);
248
+ setSelectedModelId((current) => available.models.some((item) => item.id === current) ? current : available.defaultModelId);
249
+ return;
250
+ }
222
251
  const entitlement = await client.resourcePolicies.getEffective();
223
252
  if (!mountedRef.current || clientRef.current !== client) return;
224
253
  setEffectivePolicy(entitlement);
@@ -226,7 +255,7 @@ function useAgentChatRuntime(options) {
226
255
  const available = modelsFromEffectivePolicy(entitlement);
227
256
  setSelectedModelId((current) => available.models.some((item) => item.id === current) ? current : available.defaultModelId);
228
257
  }
229
- }, [client, modelId]);
258
+ }, [bootstrap, client, modelId]);
230
259
  React.useEffect(() => {
231
260
  void retryBootstrap();
232
261
  }, [retryBootstrap]);
@@ -265,18 +294,17 @@ function useAgentChatRuntime(options) {
265
294
  setIsSubmitting(true);
266
295
  const request = (async () => {
267
296
  try {
268
- if (!bootstrap) throw new Error("The agent input contract is unavailable.");
269
- const inputError = validateAgentChatSubmission(bootstrap.features.inputs, input.text, input.files || []);
297
+ await agentChangePromiseRef.current;
298
+ const activeBootstrap = bootstrapRef.current;
299
+ if (!activeBootstrap) throw new Error("The agent input contract is unavailable.");
300
+ const inputError = validateAgentChatSubmission(activeBootstrap.features.inputs, input.text, input.files || []);
270
301
  if (inputError) throw new Error(inputError);
271
- const uploaded = input.files?.length ? await attachments.uploadBatch({
272
- uploads: input.files,
273
- threadId: controller.activeThreadId || void 0
274
- }) : [];
275
302
  await controller.submit({
276
303
  text: input.text,
277
- attachmentIds: uploaded.flatMap((attachment) => attachment.id ? [attachment.id] : []),
278
- attachments: uploaded,
279
- requestedModelId: selectedModelId || void 0
304
+ attachments: input.attachments,
305
+ uploads: input.files,
306
+ requestedModelId: selectedModelIdRef.current || void 0,
307
+ requestedAgentId: selectedAgentIdRef.current || void 0
280
308
  });
281
309
  } catch (error) {
282
310
  setLocalOperationError(error);
@@ -295,7 +323,7 @@ function useAgentChatRuntime(options) {
295
323
  };
296
324
  void request.then(clearRequest, clearRequest);
297
325
  return request;
298
- }, [attachments, bootstrap, clearOperationError, controller.activeThreadId, controller.submit, refreshEffectivePolicy, selectedModelId]);
326
+ }, [bootstrap, clearOperationError, controller.activeThreadId, controller.submit, refreshEffectivePolicy]);
299
327
  const completeMcp = React.useCallback(async (part) => {
300
328
  if (!mcpRedirectUri) throw new Error("mcpRedirectUri is required for MCP Connect.");
301
329
  const serverId = String(part.presentation.server_id || "").trim();
@@ -378,6 +406,18 @@ function useAgentChatRuntime(options) {
378
406
  clearOperationError();
379
407
  pendingThreadTransitionRef.current = { reason: "opened", value: threadId };
380
408
  try {
409
+ const detail = await client.threads.get({ threadId });
410
+ const preferredAgentId = detail.runtime_selection?.agent_alias || detail.runtime_selection?.agent_id || null;
411
+ if (preferredAgentId) {
412
+ const result = await client.bootstrap({ agentId: preferredAgentId });
413
+ const resolvedAgentId = agentIdFromBootstrap(result, preferredAgentId);
414
+ setBootstrap(result);
415
+ setEffectivePolicy(null);
416
+ setSelectedAgentId(resolvedAgentId);
417
+ const available = modelsFromAgentChatBootstrap(result);
418
+ const preferredModelId = detail.runtime_selection?.model_id || null;
419
+ setSelectedModelId(available.models.some((item) => item.id === preferredModelId) ? preferredModelId : available.defaultModelId);
420
+ }
381
421
  await controller.openThread(threadId);
382
422
  reportActiveThread(threadId, "opened");
383
423
  } catch (error) {
@@ -386,7 +426,7 @@ function useAgentChatRuntime(options) {
386
426
  } finally {
387
427
  if (pendingThreadTransitionRef.current?.value === threadId) pendingThreadTransitionRef.current = null;
388
428
  }
389
- }, [clearOperationError, controller.openThread, reportActiveThread]);
429
+ }, [clearOperationError, client, controller.openThread, reportActiveThread]);
390
430
  const deleteThread = React.useCallback(async (threadId) => {
391
431
  clearOperationError();
392
432
  const wasActive = controller.activeThreadId === threadId;
@@ -406,11 +446,71 @@ function useAgentChatRuntime(options) {
406
446
  const changeModel = React.useCallback((nextModelId) => {
407
447
  if (modelId === void 0) setSelectedModelId(nextModelId);
408
448
  onModelChange?.(nextModelId);
409
- }, [modelId, onModelChange]);
449
+ if (controller.activeThreadId && selectedAgentId && client.threads.setRuntimeSelection) {
450
+ void client.threads.setRuntimeSelection({
451
+ threadId: controller.activeThreadId,
452
+ preferredAgentId: selectedAgentId,
453
+ preferredModelId: nextModelId
454
+ }).catch(setLocalOperationError);
455
+ }
456
+ }, [client.threads, controller.activeThreadId, modelId, onModelChange, selectedAgentId]);
457
+ const resolveAttachmentContent = React.useCallback(async (attachment, signal) => {
458
+ const attachmentId = typeof attachment.id === "string" ? attachment.id.trim() : "";
459
+ if (!attachmentId) throw new Error("Attachment content identity is unavailable.");
460
+ const access = await attachments.createContentAccess({
461
+ attachmentId,
462
+ disposition: "inline",
463
+ signal
464
+ });
465
+ return { url: access.url, validUntil: access.valid_until || null };
466
+ }, [attachments.createContentAccess]);
467
+ const changeAgent = React.useCallback((nextAgentId) => {
468
+ if (agentChangePromiseRef.current) return agentChangePromiseRef.current;
469
+ if (nextAgentId === selectedAgentIdRef.current || !canChangeAgentRuntime(controller.runState, controller.activeRunId)) return Promise.resolve();
470
+ clearOperationError();
471
+ setIsChangingAgent(true);
472
+ const request = (async () => {
473
+ try {
474
+ const result = await client.bootstrap({ agentId: nextAgentId });
475
+ const resolvedAgentId = agentIdFromBootstrap(result, nextAgentId);
476
+ if (!resolvedAgentId) throw new Error("The requested Agent is no longer available.");
477
+ const available = modelsFromAgentChatBootstrap(result);
478
+ const currentModelId = selectedModelIdRef.current;
479
+ const nextModelId = available.models.some((item) => item.id === currentModelId) ? currentModelId : available.defaultModelId;
480
+ if (controller.activeThreadId && client.threads.setRuntimeSelection) {
481
+ const persisted = await client.threads.setRuntimeSelection({
482
+ threadId: controller.activeThreadId,
483
+ preferredAgentId: resolvedAgentId,
484
+ preferredModelId: nextModelId
485
+ });
486
+ selectedModelIdRef.current = persisted.runtime_selection.model_id;
487
+ setSelectedModelId(persisted.runtime_selection.model_id);
488
+ } else {
489
+ selectedModelIdRef.current = nextModelId;
490
+ setSelectedModelId(nextModelId);
491
+ }
492
+ selectedAgentIdRef.current = resolvedAgentId;
493
+ bootstrapRef.current = result;
494
+ setSelectedAgentId(resolvedAgentId);
495
+ setBootstrap(result);
496
+ setEffectivePolicy(null);
497
+ } catch (error) {
498
+ setLocalOperationError(error);
499
+ throw error;
500
+ }
501
+ })();
502
+ agentChangePromiseRef.current = request;
503
+ const clearRequest = () => {
504
+ if (agentChangePromiseRef.current === request) agentChangePromiseRef.current = null;
505
+ if (mountedRef.current) setIsChangingAgent(false);
506
+ };
507
+ void request.then(clearRequest, clearRequest);
508
+ return request;
509
+ }, [clearOperationError, client, controller.activeRunId, controller.activeThreadId, controller.runState]);
410
510
  const modelOptions = effectivePolicy ? modelsFromEffectivePolicy(effectivePolicy).models : bootstrap ? modelsFromAgentChatBootstrap(bootstrap).models : [];
411
511
  const fatalError = bootstrapError || controller.error;
412
512
  const operationError = localOperationError || controller.operationError?.cause;
413
- const state = isBootstrapping ? "loading" : fatalError ? agentChatRuntimeStateFromError(fatalError) : controller.runState === "streaming" ? "streaming" : controller.runState === "reconnecting" ? "reconnecting" : controller.runState === "paused" ? "paused" : controller.runState === "cancelling" ? "cancelling" : controller.runState === "cancelled" ? "cancelled" : "ready";
513
+ const state = isBootstrapping ? "loading" : fatalError ? agentChatRuntimeStateFromError(fatalError) : controller.runState === "uploading" ? "uploading" : controller.runState === "streaming" ? "streaming" : controller.runState === "reconnecting" ? "reconnecting" : controller.runState === "paused" ? "paused" : controller.runState === "cancelling" ? "cancelling" : controller.runState === "cancelled" ? "cancelled" : "ready";
414
514
  const connectionState = state === "offline" ? "offline" : state === "expired" ? "expired" : state === "reconnecting" ? "reconnecting" : isBootstrapping ? "connecting" : "connected";
415
515
  return {
416
516
  agent: agentOverride || { name: bootstrap?.deployment.name || "Agent" },
@@ -419,6 +519,9 @@ function useAgentChatRuntime(options) {
419
519
  backgroundError: controller.backgroundError?.cause || null,
420
520
  bootstrap,
421
521
  capabilities: bootstrap?.capabilities || [],
522
+ agentId: selectedAgentId,
523
+ agents: bootstrap?.features.agents?.options.map((item) => ({ id: item.id, label: item.label })) || [],
524
+ changeAgent,
422
525
  changeModel,
423
526
  clearOperationError,
424
527
  connectionState,
@@ -430,8 +533,9 @@ function useAgentChatRuntime(options) {
430
533
  fatalError,
431
534
  getHitlActionState: (part) => hitlStates[hitlKey(part)],
432
535
  isBootstrapping,
536
+ isChangingAgent,
433
537
  isSubmitting: isSubmitting || controller.isSubmitting,
434
- isUploading: attachments.isUploading,
538
+ isUploading: attachments.isUploading || controller.runState === "uploading",
435
539
  modelId: selectedModelId,
436
540
  models: modelOptions,
437
541
  newThread,
@@ -439,6 +543,7 @@ function useAgentChatRuntime(options) {
439
543
  openThread,
440
544
  operationError,
441
545
  retryBootstrap,
546
+ resolveAttachmentContent,
442
547
  state,
443
548
  submit
444
549
  };
@@ -447,6 +552,8 @@ export {
447
552
  SUPPORTED_INPUT_MIME_TYPES,
448
553
  agentChatRuntimeErrorMessage,
449
554
  agentChatRuntimeStateFromError,
555
+ agentIdFromBootstrap,
556
+ canChangeAgentRuntime,
450
557
  canonicalInputMimeType,
451
558
  inputMimeTypes,
452
559
  modelsFromAgentChatBootstrap,
@@ -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 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 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 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 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 [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 [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 result = await requestClient.bootstrap();\n if (!mountedRef.current || clientRef.current !== requestClient) return;\n setBootstrap(result);\n const entitlement = await requestClient.resourcePolicies.getEffective();\n if (!mountedRef.current || clientRef.current !== requestClient) return;\n setEffectivePolicy(entitlement);\n const availableModels = modelsFromEffectivePolicy(entitlement);\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 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 }, [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 if (!bootstrap) throw new Error(\"The agent input contract is unavailable.\");\n const inputError = validateAgentChatSubmission(bootstrap.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 })\n : [];\n await controller.submit({\n text: input.text,\n attachmentIds: uploaded.flatMap((attachment) => attachment.id ? [attachment.id] : []),\n attachments: uploaded,\n requestedModelId: selectedModelId || 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, selectedModelId]);\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 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, 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 }, [modelId, onModelChange]);\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 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 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;
@@ -12,7 +12,11 @@ export type AgentChatRuntimeModel = {
12
12
  id: string;
13
13
  label: string;
14
14
  };
15
- export type AgentChatRuntimeViewState = "ready" | "loading" | "streaming" | "reconnecting" | "paused" | "cancelling" | "cancelled" | "offline" | "denied" | "quota" | "failed" | "expired";
15
+ export type AgentChatRuntimeAgentOption = {
16
+ id: string;
17
+ label: string;
18
+ };
19
+ export type AgentChatRuntimeViewState = "ready" | "loading" | "uploading" | "streaming" | "reconnecting" | "paused" | "cancelling" | "cancelled" | "offline" | "denied" | "quota" | "failed" | "expired";
16
20
  export type AgentChatRuntimeConnectionState = "connected" | "connecting" | "reconnecting" | "offline" | "expired";
17
21
  export type AgentChatThreadChangeReason = "created" | "opened" | "new" | "deleted";
18
22
  export type AgentChatActiveThreadChange = {
@@ -28,6 +32,7 @@ export type AgentChatMcpAuthorizationCompletion = (input: {
28
32
  export type AgentChatRuntimeSubmit = {
29
33
  text: string;
30
34
  files?: readonly PortableUpload[];
35
+ attachments?: ChatAttachment[];
31
36
  };
32
37
  export type AgentChatRuntimeHitlActionState = {
33
38
  action: string;
@@ -51,6 +56,9 @@ export type AgentChatRuntime = {
51
56
  backgroundError: unknown;
52
57
  bootstrap: ClientBootstrap | null;
53
58
  capabilities: readonly string[];
59
+ agentId: string | null;
60
+ agents: AgentChatRuntimeAgentOption[];
61
+ changeAgent(agentId: string): Promise<void>;
54
62
  changeModel(modelId: string): void;
55
63
  clearOperationError(): void;
56
64
  connectionState: AgentChatRuntimeConnectionState;
@@ -62,6 +70,7 @@ export type AgentChatRuntime = {
62
70
  fatalError: unknown;
63
71
  getHitlActionState(part: ChatHitlPart): AgentChatRuntimeHitlActionState | undefined;
64
72
  isBootstrapping: boolean;
73
+ isChangingAgent: boolean;
65
74
  isSubmitting: boolean;
66
75
  isUploading: boolean;
67
76
  modelId: string | null;
@@ -71,11 +80,17 @@ export type AgentChatRuntime = {
71
80
  openThread(threadId: string): Promise<void>;
72
81
  operationError: unknown;
73
82
  retryBootstrap(): Promise<void>;
83
+ resolveAttachmentContent(attachment: ChatAttachment, signal: AbortSignal): Promise<{
84
+ url: string;
85
+ validUntil: string | null;
86
+ }>;
74
87
  state: AgentChatRuntimeViewState;
75
88
  submit(input: AgentChatRuntimeSubmit): Promise<void>;
76
89
  };
77
90
  export declare function agentChatRuntimeStateFromError(error: unknown): AgentChatRuntimeViewState;
78
91
  export declare function agentChatRuntimeErrorMessage(error: unknown): string | null;
92
+ export declare function canChangeAgentRuntime(runState: AgentChatController["runState"], activeRunId: string | null): boolean;
93
+ export declare function agentIdFromBootstrap(bootstrap: ClientBootstrap, requestedAgentId: string | null): string | null;
79
94
  export declare function modelsFromAgentChatBootstrap(bootstrap: ClientBootstrap): {
80
95
  defaultModelId: string | null;
81
96
  models: AgentChatRuntimeModel[];
@@ -15,6 +15,7 @@ export type Agents24ChatAppProps = {
15
15
  onModelChange?: (modelId: string) => void;
16
16
  identity?: Agents24ChatIdentity;
17
17
  components?: Agents24ChatScaffoldComponents;
18
+ sidebar?: React.ReactNode;
18
19
  };
19
20
  export type Agents24ChatScaffoldComponents = {
20
21
  Timeline?: React.ComponentType<Agents24ChatTimelineSlotProps>;
@@ -1,21 +1,29 @@
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 = {
4
5
  inputContract: AgentChatInputContract;
5
6
  disabled?: boolean;
6
7
  contextWindow?: ContextWindow | null;
8
+ focusKey?: string | null;
7
9
  forceExpanded?: boolean;
8
10
  isCancelling?: boolean;
9
11
  isRunning: boolean;
12
+ agentId: string | null;
13
+ agents: Array<{
14
+ id: string;
15
+ label: string;
16
+ }>;
10
17
  modelId: string | null;
11
18
  models: Array<{
12
19
  id: string;
13
20
  label: string;
14
21
  }>;
15
22
  onModelChange: (modelId: string) => void;
23
+ onAgentChange: (agentId: string) => void;
16
24
  onStop: () => void;
17
- onSubmit: (text: string, files: File[]) => Promise<void>;
25
+ onSubmit: (text: string, files: AgentChatComposerFile[]) => Promise<void>;
18
26
  utilityRow?: "inline" | "below";
19
27
  };
20
- export declare function ChatComposer({ inputContract, disabled, contextWindow, forceExpanded, isCancelling, isRunning, modelId, models, onModelChange, onStop, onSubmit, utilityRow, }: ChatComposerProps): import("react/jsx-runtime").JSX.Element;
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;
21
29
  export {};
@@ -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 {};
@@ -1,8 +1,10 @@
1
1
  import { type AgentChatRuntime } from "@agents24/chat-react/runtime";
2
2
  import type { Agents24ChatScaffoldComponents } from "../../app";
3
+ import * as React from "react";
3
4
  import type { Agents24ChatIdentity } from "../../identity";
4
- export declare function ChatShell({ components, identity, runtime, }: {
5
+ export declare function ChatShell({ components, identity, runtime, sidebar, }: {
5
6
  components?: Agents24ChatScaffoldComponents;
6
7
  identity: Agents24ChatIdentity;
7
8
  runtime: AgentChatRuntime;
9
+ sidebar?: React.ReactNode;
8
10
  }): import("react/jsx-runtime").JSX.Element;