@truefoundry/trueforge-ui 0.2.4 → 0.3.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +41 -17
  3. package/dist/{ConnectorSettings-ODC3LVHN.js → ConnectorSettings-FXQ5B7TN.js} +5 -5
  4. package/dist/{DockLayout-TEOWEMSV.js → DockLayout-LBNQJZNF.js} +9 -9
  5. package/dist/{DrawerLayout-2JOQ4EDZ.js → DrawerLayout-Q6UK4VMI.js} +9 -9
  6. package/dist/{ModelSettings-CKQ5CVAC.js → ModelSettings-4L4LOQJA.js} +5 -5
  7. package/dist/OpenUiFenceBlock-6UIIAVBX.js +9 -0
  8. package/dist/{SandboxSettings-HSCPYUOC.js → SandboxSettings-Z4ZG6ZX4.js} +5 -5
  9. package/dist/{SettingsBuilder-MYWRFXRI.js → SettingsBuilder-WF7ZWKQW.js} +7 -7
  10. package/dist/{SidebarLayout-6MHQYW45.js → SidebarLayout-3WZ3CVON.js} +31 -14
  11. package/dist/SidebarLayout-3WZ3CVON.js.map +1 -0
  12. package/dist/{SkillSettings-ECH6SHZ7.js → SkillSettings-3EPPC3IT.js} +5 -5
  13. package/dist/{TrueForgeUIWithRouter-KMHPOKLN.js → TrueForgeUIWithRouter-NZ4FGPE4.js} +7 -7
  14. package/dist/{WidgetLayout-4ZIG3RXV.js → WidgetLayout-3QZ357FL.js} +10 -10
  15. package/dist/{WidgetLayout-4ZIG3RXV.js.map → WidgetLayout-3QZ357FL.js.map} +1 -1
  16. package/dist/chunk-36KOSC2J.js +567 -0
  17. package/dist/chunk-36KOSC2J.js.map +1 -0
  18. package/dist/{chunk-IWPDSPVA.js → chunk-3S6KHO7H.js} +292 -239
  19. package/dist/chunk-3S6KHO7H.js.map +1 -0
  20. package/dist/{chunk-PUFYHFND.js → chunk-7L63OK3O.js} +7 -7
  21. package/dist/{chunk-JRRCAKEP.js → chunk-B52K63AW.js} +2 -2
  22. package/dist/{chunk-FXCYLEFB.js → chunk-BSIPI3KV.js} +18 -2
  23. package/dist/chunk-BSIPI3KV.js.map +1 -0
  24. package/dist/{chunk-IFLE7OMM.js → chunk-FJ5RSSMA.js} +4 -4
  25. package/dist/{chunk-IFLE7OMM.js.map → chunk-FJ5RSSMA.js.map} +1 -1
  26. package/dist/{chunk-XRTTKGKN.js → chunk-OSV3HI5M.js} +746 -680
  27. package/dist/chunk-OSV3HI5M.js.map +1 -0
  28. package/dist/{chunk-255AE5NI.js → chunk-WREC7D54.js} +13 -11
  29. package/dist/chunk-WREC7D54.js.map +1 -0
  30. package/dist/{chunk-OZTNBS6V.js → chunk-ZXOADNF3.js} +4 -4
  31. package/dist/index.d.ts +179 -121
  32. package/dist/index.js +17 -9
  33. package/dist/index.js.map +1 -1
  34. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +1 -5
  35. package/dist/plugins/trueforge-agent-server-adapter/index.js +3 -0
  36. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  37. package/dist/styles.css +1 -1
  38. package/package.json +5 -5
  39. package/dist/OpenUiFenceBlock-3EFPY4JW.js +0 -9
  40. package/dist/SidebarLayout-6MHQYW45.js.map +0 -1
  41. package/dist/chunk-255AE5NI.js.map +0 -1
  42. package/dist/chunk-72LC2M3R.js +0 -567
  43. package/dist/chunk-72LC2M3R.js.map +0 -1
  44. package/dist/chunk-FXCYLEFB.js.map +0 -1
  45. package/dist/chunk-IWPDSPVA.js.map +0 -1
  46. package/dist/chunk-XRTTKGKN.js.map +0 -1
  47. /package/dist/{ConnectorSettings-ODC3LVHN.js.map → ConnectorSettings-FXQ5B7TN.js.map} +0 -0
  48. /package/dist/{DockLayout-TEOWEMSV.js.map → DockLayout-LBNQJZNF.js.map} +0 -0
  49. /package/dist/{DrawerLayout-2JOQ4EDZ.js.map → DrawerLayout-Q6UK4VMI.js.map} +0 -0
  50. /package/dist/{ModelSettings-CKQ5CVAC.js.map → ModelSettings-4L4LOQJA.js.map} +0 -0
  51. /package/dist/{OpenUiFenceBlock-3EFPY4JW.js.map → OpenUiFenceBlock-6UIIAVBX.js.map} +0 -0
  52. /package/dist/{SandboxSettings-HSCPYUOC.js.map → SandboxSettings-Z4ZG6ZX4.js.map} +0 -0
  53. /package/dist/{SettingsBuilder-MYWRFXRI.js.map → SettingsBuilder-WF7ZWKQW.js.map} +0 -0
  54. /package/dist/{SkillSettings-ECH6SHZ7.js.map → SkillSettings-3EPPC3IT.js.map} +0 -0
  55. /package/dist/{TrueForgeUIWithRouter-KMHPOKLN.js.map → TrueForgeUIWithRouter-NZ4FGPE4.js.map} +0 -0
  56. /package/dist/{chunk-PUFYHFND.js.map → chunk-7L63OK3O.js.map} +0 -0
  57. /package/dist/{chunk-JRRCAKEP.js.map → chunk-B52K63AW.js.map} +0 -0
  58. /package/dist/{chunk-OZTNBS6V.js.map → chunk-ZXOADNF3.js.map} +0 -0
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  ComposerBusyProvider,
3
- useComposerBusyState
4
- } from "./chunk-FXCYLEFB.js";
3
+ useComposerBusyState,
4
+ useOptionalCustomActionRenderers
5
+ } from "./chunk-BSIPI3KV.js";
5
6
  import {
6
7
  useAui,
7
8
  useAuiState
@@ -24,14 +25,14 @@ import {
24
25
  useSlot,
25
26
  useSlotIsDefault,
26
27
  useToasterOptional
27
- } from "./chunk-XRTTKGKN.js";
28
+ } from "./chunk-OSV3HI5M.js";
28
29
  import {
29
30
  DraftCatalogProvider,
30
31
  Icon,
31
32
  auiButtonClass,
32
33
  useCompactLayout,
33
34
  useDraftCatalog
34
- } from "./chunk-IFLE7OMM.js";
35
+ } from "./chunk-FJ5RSSMA.js";
35
36
  import {
36
37
  libraryAgentId,
37
38
  useOptionalCatalogServer,
@@ -40,7 +41,7 @@ import {
40
41
  } from "./chunk-WQULF5AT.js";
41
42
  import {
42
43
  cn
43
- } from "./chunk-72LC2M3R.js";
44
+ } from "./chunk-36KOSC2J.js";
44
45
 
45
46
  // src/containers/AgentStepsContainer.tsx
46
47
  import { useEffect, useRef, useState } from "react";
@@ -381,137 +382,6 @@ function ReasoningContainer({ group }) {
381
382
 
382
383
  // src/containers/ToolApprovalContainer.tsx
383
384
  import { useCallback as useCallback4, useMemo as useMemo3, useState as useState5 } from "react";
384
- import { jsx as jsx5 } from "react/jsx-runtime";
385
- function ToolApprovalContainer({ toolName = "", options, onSelectOption }) {
386
- const ToolApprovalBar = useSlot("ToolApprovalBar");
387
- const [selectedDenyOptionId, setSelectedDenyOptionId] = useState5(null);
388
- const [denialReason, setDenialReason] = useState5("");
389
- const [showReasonError, setShowReasonError] = useState5(false);
390
- const approveOptions = useMemo3(
391
- () => options.filter((option) => option.isAllow).map((option, index) => ({
392
- ...option,
393
- variant: index === 0 ? "primary" : "secondary",
394
- requiresReason: false
395
- })),
396
- [options]
397
- );
398
- const denyOptions = useMemo3(
399
- () => options.filter((option) => !option.isAllow).map((option) => ({
400
- ...option,
401
- variant: "secondary",
402
- requiresReason: option.confirm != null
403
- })),
404
- [options]
405
- );
406
- const selectedDenyOption = denyOptions.find((option) => option.id === selectedDenyOptionId);
407
- const onDenyOptionChange = useCallback4((optionId) => {
408
- setSelectedDenyOptionId(optionId);
409
- setDenialReason("");
410
- setShowReasonError(false);
411
- }, []);
412
- const onDenialReasonChange = useCallback4((reason) => {
413
- setDenialReason(reason);
414
- setShowReasonError(false);
415
- }, []);
416
- const onReasonSubmit = useCallback4(() => {
417
- const reason = denialReason.trim();
418
- if (!reason) {
419
- setShowReasonError(true);
420
- return;
421
- }
422
- if (selectedDenyOptionId) {
423
- onSelectOption(selectedDenyOptionId, reason);
424
- onDenyOptionChange(null);
425
- }
426
- }, [denialReason, onDenyOptionChange, onSelectOption, selectedDenyOptionId]);
427
- return /* @__PURE__ */ jsx5(
428
- ToolApprovalBar,
429
- {
430
- toolName,
431
- approveOptions: approveOptions.length > 0 ? approveOptions : void 0,
432
- denyOptions: denyOptions.length > 0 ? denyOptions : void 0,
433
- selectedDenyOption,
434
- denialReason,
435
- showReasonError,
436
- onSelect: onSelectOption,
437
- onDenyOptionChange,
438
- onDenialReasonChange,
439
- onReasonSubmit
440
- }
441
- );
442
- }
443
-
444
- // src/containers/ToolCallContentBlockContainer.tsx
445
- import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef5, useState as useState6 } from "react";
446
- import { jsx as jsx6 } from "react/jsx-runtime";
447
- function ToolCallContentBlockContainer(props) {
448
- const ToolCallContentBlock = useSlot("ToolCallContentBlock");
449
- const { isJson, onContentHeightChange: notifyContentHeightChange, resizable } = props;
450
- const [fullscreen, setFullscreen] = useState6(false);
451
- const [contentHeightRem, setContentHeightRem] = useState6();
452
- const observerRef = useRef5(null);
453
- const contentNodeRef = useRef5(null);
454
- const hasMeasuredRef = useRef5(false);
455
- const contentRef = useCallback5(
456
- (node) => {
457
- observerRef.current?.disconnect();
458
- observerRef.current = null;
459
- contentNodeRef.current = node;
460
- hasMeasuredRef.current = false;
461
- if (node == null) return;
462
- setContentHeightRem(void 0);
463
- if (!resizable) return;
464
- const updateHeight = () => {
465
- if (!hasMeasuredRef.current && isJson !== false) return;
466
- const renderedHeight = node.getBoundingClientRect().height;
467
- const height = hasMeasuredRef.current && renderedHeight > 0 ? renderedHeight : node.scrollHeight;
468
- hasMeasuredRef.current = true;
469
- setContentHeightRem(height / 16);
470
- };
471
- updateHeight();
472
- observerRef.current = new ResizeObserver(updateHeight);
473
- observerRef.current.observe(node);
474
- },
475
- [isJson, resizable]
476
- );
477
- const onContentHeightChange = useCallback5(
478
- (height) => {
479
- const node = contentNodeRef.current;
480
- if (node == null) return;
481
- const renderedHeight = node.getBoundingClientRect().height;
482
- hasMeasuredRef.current = true;
483
- setContentHeightRem((renderedHeight > 0 ? renderedHeight : Math.max(height, node.scrollHeight)) / 16);
484
- notifyContentHeightChange?.(height);
485
- },
486
- [notifyContentHeightChange]
487
- );
488
- useEffect4(
489
- () => () => {
490
- observerRef.current?.disconnect();
491
- },
492
- []
493
- );
494
- return /* @__PURE__ */ jsx6(
495
- ToolCallContentBlock,
496
- {
497
- ...props,
498
- fullscreen,
499
- onFullscreenChange: setFullscreen,
500
- contentHeightRem,
501
- contentRef,
502
- onContentHeightChange
503
- }
504
- );
505
- }
506
-
507
- // src/containers/ToolCallContainer.tsx
508
- import {
509
- MessagePartPrimitive,
510
- MessagePrimitive,
511
- useToolCallElapsed
512
- } from "@assistant-ui/react";
513
- import { useTrueFoundryRespondToToolApproval } from "@truefoundry/assistant-ui-runtime";
514
- import { useState as useState8 } from "react";
515
385
 
516
386
  // src/utils/toolCallParsing.ts
517
387
  import { parse as parsePartialJson } from "partial-json";
@@ -695,6 +565,146 @@ function mcpDisplayName(toolName, mcpServer, innerToolName) {
695
565
  return toolName;
696
566
  }
697
567
 
568
+ // src/containers/ToolApprovalContainer.tsx
569
+ import { jsx as jsx5 } from "react/jsx-runtime";
570
+ function ToolApprovalContainer({
571
+ toolName = "",
572
+ argsText,
573
+ options,
574
+ onSelectOption
575
+ }) {
576
+ const ToolApprovalBar = useSlot("ToolApprovalBar");
577
+ const { mcpServer, innerToolName } = parseMcpToolArgs(argsText);
578
+ const displayToolName = innerToolName && mcpServer ? `${innerToolName} (${mcpServer})` : toolName;
579
+ const [selectedDenyOptionId, setSelectedDenyOptionId] = useState5(null);
580
+ const [denialReason, setDenialReason] = useState5("");
581
+ const [showReasonError, setShowReasonError] = useState5(false);
582
+ const approveOptions = useMemo3(
583
+ () => options.filter((option) => option.isAllow).map((option, index) => ({
584
+ ...option,
585
+ variant: index === 0 ? "primary" : "secondary",
586
+ requiresReason: false
587
+ })),
588
+ [options]
589
+ );
590
+ const denyOptions = useMemo3(
591
+ () => options.filter((option) => !option.isAllow).map((option) => ({
592
+ ...option,
593
+ variant: "secondary",
594
+ requiresReason: option.confirm != null
595
+ })),
596
+ [options]
597
+ );
598
+ const selectedDenyOption = denyOptions.find((option) => option.id === selectedDenyOptionId);
599
+ const onDenyOptionChange = useCallback4((optionId) => {
600
+ setSelectedDenyOptionId(optionId);
601
+ setDenialReason("");
602
+ setShowReasonError(false);
603
+ }, []);
604
+ const onDenialReasonChange = useCallback4((reason) => {
605
+ setDenialReason(reason);
606
+ setShowReasonError(false);
607
+ }, []);
608
+ const onReasonSubmit = useCallback4(() => {
609
+ const reason = denialReason.trim();
610
+ if (!reason) {
611
+ setShowReasonError(true);
612
+ return;
613
+ }
614
+ if (selectedDenyOptionId) {
615
+ onSelectOption(selectedDenyOptionId, reason);
616
+ onDenyOptionChange(null);
617
+ }
618
+ }, [denialReason, onDenyOptionChange, onSelectOption, selectedDenyOptionId]);
619
+ return /* @__PURE__ */ jsx5(
620
+ ToolApprovalBar,
621
+ {
622
+ toolName: displayToolName,
623
+ approveOptions: approveOptions.length > 0 ? approveOptions : void 0,
624
+ denyOptions: denyOptions.length > 0 ? denyOptions : void 0,
625
+ selectedDenyOption,
626
+ denialReason,
627
+ showReasonError,
628
+ onSelect: onSelectOption,
629
+ onDenyOptionChange,
630
+ onDenialReasonChange,
631
+ onReasonSubmit
632
+ }
633
+ );
634
+ }
635
+
636
+ // src/containers/ToolCallContentBlockContainer.tsx
637
+ import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef5, useState as useState6 } from "react";
638
+ import { jsx as jsx6 } from "react/jsx-runtime";
639
+ function ToolCallContentBlockContainer(props) {
640
+ const ToolCallContentBlock = useSlot("ToolCallContentBlock");
641
+ const { isJson, onContentHeightChange: notifyContentHeightChange, resizable } = props;
642
+ const [fullscreen, setFullscreen] = useState6(false);
643
+ const [contentHeightRem, setContentHeightRem] = useState6();
644
+ const observerRef = useRef5(null);
645
+ const contentNodeRef = useRef5(null);
646
+ const hasMeasuredRef = useRef5(false);
647
+ const contentRef = useCallback5(
648
+ (node) => {
649
+ observerRef.current?.disconnect();
650
+ observerRef.current = null;
651
+ contentNodeRef.current = node;
652
+ hasMeasuredRef.current = false;
653
+ if (node == null) return;
654
+ setContentHeightRem(void 0);
655
+ if (!resizable) return;
656
+ const updateHeight = () => {
657
+ if (!hasMeasuredRef.current && isJson !== false) return;
658
+ const renderedHeight = node.getBoundingClientRect().height;
659
+ const height = hasMeasuredRef.current && renderedHeight > 0 ? renderedHeight : node.scrollHeight;
660
+ hasMeasuredRef.current = true;
661
+ setContentHeightRem(height / 16);
662
+ };
663
+ updateHeight();
664
+ observerRef.current = new ResizeObserver(updateHeight);
665
+ observerRef.current.observe(node);
666
+ },
667
+ [isJson, resizable]
668
+ );
669
+ const onContentHeightChange = useCallback5(
670
+ (height) => {
671
+ const node = contentNodeRef.current;
672
+ if (node == null) return;
673
+ const renderedHeight = node.getBoundingClientRect().height;
674
+ hasMeasuredRef.current = true;
675
+ setContentHeightRem((renderedHeight > 0 ? renderedHeight : Math.max(height, node.scrollHeight)) / 16);
676
+ notifyContentHeightChange?.(height);
677
+ },
678
+ [notifyContentHeightChange]
679
+ );
680
+ useEffect4(
681
+ () => () => {
682
+ observerRef.current?.disconnect();
683
+ },
684
+ []
685
+ );
686
+ return /* @__PURE__ */ jsx6(
687
+ ToolCallContentBlock,
688
+ {
689
+ ...props,
690
+ fullscreen,
691
+ onFullscreenChange: setFullscreen,
692
+ contentHeightRem,
693
+ contentRef,
694
+ onContentHeightChange
695
+ }
696
+ );
697
+ }
698
+
699
+ // src/containers/ToolCallContainer.tsx
700
+ import {
701
+ MessagePartPrimitive,
702
+ MessagePrimitive,
703
+ useToolCallElapsed
704
+ } from "@assistant-ui/react";
705
+ import { useTrueFoundryRespondToToolApproval } from "@truefoundry/assistant-ui-runtime";
706
+ import { useState as useState8 } from "react";
707
+
698
708
  // src/containers/nestedApprovalBridge.ts
699
709
  import { createContext, useContext } from "react";
700
710
  var NestedApprovalBridgeContext = createContext(false);
@@ -766,6 +776,7 @@ function ToolApprovalSlot({ part }) {
766
776
  ToolApprovalContainer,
767
777
  {
768
778
  toolName: part.toolName,
779
+ argsText: part.argsText,
769
780
  options: buildApprovalOptions(part.approval?.options),
770
781
  onSelectOption
771
782
  }
@@ -1161,19 +1172,50 @@ function threadHasPendingMcpAuth(s) {
1161
1172
  function useComposerPauseView() {
1162
1173
  const mcpPending = useAuiState8(threadHasPendingMcpAuth);
1163
1174
  const { pending: toolResponsesPending } = useTrueFoundryToolResponses2();
1175
+ const customActionRenderers = useOptionalCustomActionRenderers();
1164
1176
  if (mcpPending) {
1165
1177
  return { kind: "mcp" };
1166
1178
  }
1167
- if (toolResponsesPending.length > 0) {
1179
+ const firstPending = toolResponsesPending[0];
1180
+ if (firstPending != null) {
1181
+ const toolName = firstPending.toolName;
1182
+ if (toolName != null && customActionRenderers?.[toolName] != null) {
1183
+ return { kind: "custom", toolName };
1184
+ }
1168
1185
  return { kind: "ask-user" };
1169
1186
  }
1170
1187
  return { kind: "compose" };
1171
1188
  }
1172
1189
 
1173
- // src/containers/McpAuthContainer.tsx
1190
+ // src/containers/CustomActionContainer.tsx
1174
1191
  import { useThreadIsRunning as useThreadIsRunning3 } from "@assistant-ui/core/react";
1175
- import { useTrueFoundryMcpAuth } from "@truefoundry/assistant-ui-runtime";
1192
+ import { useTrueFoundryToolResponses as useTrueFoundryToolResponses3 } from "@truefoundry/assistant-ui-runtime";
1193
+ import { useCallback as useCallback6 } from "react";
1176
1194
  import { jsx as jsx12 } from "react/jsx-runtime";
1195
+ function CustomActionContainer() {
1196
+ const renderers = useOptionalCustomActionRenderers();
1197
+ const { pending, respond } = useTrueFoundryToolResponses3();
1198
+ const isRunning = useThreadIsRunning3();
1199
+ const item = pending[0];
1200
+ const onSubmit = useCallback6(
1201
+ (content) => {
1202
+ if (item == null) return;
1203
+ const trimmed = content.trim();
1204
+ if (!trimmed) return;
1205
+ respond({ toolCallId: item.toolCallId, content: trimmed });
1206
+ },
1207
+ [item, respond]
1208
+ );
1209
+ if (item == null || item.toolName == null) return null;
1210
+ const Renderer = renderers?.[item.toolName];
1211
+ if (Renderer == null) return null;
1212
+ return /* @__PURE__ */ jsx12(Renderer, { args: item.args ?? {}, disabled: isRunning, onSubmit });
1213
+ }
1214
+
1215
+ // src/containers/McpAuthContainer.tsx
1216
+ import { useThreadIsRunning as useThreadIsRunning4 } from "@assistant-ui/core/react";
1217
+ import { useTrueFoundryMcpAuth } from "@truefoundry/assistant-ui-runtime";
1218
+ import { jsx as jsx13 } from "react/jsx-runtime";
1177
1219
  function CatalogMcpAuthPrompt({ servers, onContinue, readOnly }) {
1178
1220
  const McpAuthPrompt = useSlot("McpAuthPrompt");
1179
1221
  const { handleAuthorize } = useMCPAuth();
@@ -1185,16 +1227,16 @@ function CatalogMcpAuthPrompt({ servers, onContinue, readOnly }) {
1185
1227
  }
1186
1228
  });
1187
1229
  };
1188
- return /* @__PURE__ */ jsx12(McpAuthPrompt, { servers, onConnect: handleConnect, onContinue, readOnly });
1230
+ return /* @__PURE__ */ jsx13(McpAuthPrompt, { servers, onConnect: handleConnect, onContinue, readOnly });
1189
1231
  }
1190
1232
  function McpAuthContainer() {
1191
1233
  const McpAuthPrompt = useSlot("McpAuthPrompt");
1192
1234
  const { pending, resume } = useTrueFoundryMcpAuth();
1193
- const isRunning = useThreadIsRunning3();
1235
+ const isRunning = useThreadIsRunning4();
1194
1236
  const catalog = useOptionalCatalogServer();
1195
1237
  if (!pending) return null;
1196
1238
  if (catalog) {
1197
- return /* @__PURE__ */ jsx12(CatalogMcpAuthPrompt, { servers: pending.mcpServers, onContinue: () => void resume(), readOnly: isRunning });
1239
+ return /* @__PURE__ */ jsx13(CatalogMcpAuthPrompt, { servers: pending.mcpServers, onContinue: () => void resume(), readOnly: isRunning });
1198
1240
  }
1199
1241
  const handleConnect = (serverId) => {
1200
1242
  const server = pending.mcpServers.find((s) => s.id === serverId);
@@ -1202,7 +1244,7 @@ function McpAuthContainer() {
1202
1244
  window.open(server.authUrl, "_blank", "noopener,noreferrer");
1203
1245
  }
1204
1246
  };
1205
- return /* @__PURE__ */ jsx12(
1247
+ return /* @__PURE__ */ jsx13(
1206
1248
  McpAuthPrompt,
1207
1249
  {
1208
1250
  servers: pending.mcpServers,
@@ -1217,7 +1259,7 @@ function McpAuthContainer() {
1217
1259
  import { ComposerPrimitive as ComposerPrimitive2, useAui as useAui3, useAuiState as useAuiState9 } from "@assistant-ui/react";
1218
1260
  import { useTrueFoundryAgentSpec, useTrueFoundryCancel } from "@truefoundry/assistant-ui-runtime";
1219
1261
  import { useRef as useRef6 } from "react";
1220
- import { Fragment, jsx as jsx13, jsxs } from "react/jsx-runtime";
1262
+ import { Fragment, jsx as jsx14, jsxs } from "react/jsx-runtime";
1221
1263
  function ComposerBody({ placeholder }) {
1222
1264
  const ComposerShell = useSlot("ComposerShell");
1223
1265
  const aui = useAui3();
@@ -1235,7 +1277,7 @@ function ComposerBody({ placeholder }) {
1235
1277
  send(() => aui.composer().send());
1236
1278
  };
1237
1279
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1238
- /* @__PURE__ */ jsx13(
1280
+ /* @__PURE__ */ jsx14(
1239
1281
  "input",
1240
1282
  {
1241
1283
  ref: fileInputRef,
@@ -1253,13 +1295,13 @@ function ComposerBody({ placeholder }) {
1253
1295
  }
1254
1296
  }
1255
1297
  ),
1256
- /* @__PURE__ */ jsx13(
1298
+ /* @__PURE__ */ jsx14(
1257
1299
  ComposerPrimitive2.AttachmentDropzone,
1258
1300
  {
1259
1301
  disabled: isBusy,
1260
1302
  "data-slot": "aui_composer-attachment-dropzone",
1261
1303
  className: "w-full rounded-[var(--composer-radius,1.5rem)] transition-[box-shadow] data-[dragging=true]:ring-focus-ring/20 data-[dragging=true]:ring-3",
1262
- children: /* @__PURE__ */ jsx13(
1304
+ children: /* @__PURE__ */ jsx14(
1263
1305
  ComposerPrimitive2.Root,
1264
1306
  {
1265
1307
  "data-slot": "aui_composer-root",
@@ -1268,11 +1310,11 @@ function ComposerBody({ placeholder }) {
1268
1310
  event.preventDefault();
1269
1311
  submit();
1270
1312
  },
1271
- children: /* @__PURE__ */ jsx13(
1313
+ children: /* @__PURE__ */ jsx14(
1272
1314
  ComposerShell,
1273
1315
  {
1274
- attachments: /* @__PURE__ */ jsx13(ComposerAttachmentsContainer, {}),
1275
- input: /* @__PURE__ */ jsx13(
1316
+ attachments: /* @__PURE__ */ jsx14(ComposerAttachmentsContainer, {}),
1317
+ input: /* @__PURE__ */ jsx14(
1276
1318
  ComposerPrimitive2.Input,
1277
1319
  {
1278
1320
  "data-slot": "aui_composer-input",
@@ -1313,30 +1355,33 @@ function ComposerContainer({
1313
1355
  const DraftComposerRightSection = useSlot("DraftComposerRightSection");
1314
1356
  const canMutateSpec = shell?.mode.status === "active" && shell.mode.isMutable;
1315
1357
  if (pauseView.kind === "mcp") {
1316
- return /* @__PURE__ */ jsx13(McpAuthContainer, {});
1358
+ return /* @__PURE__ */ jsx14(McpAuthContainer, {});
1359
+ }
1360
+ if (pauseView.kind === "custom") {
1361
+ return /* @__PURE__ */ jsx14(CustomActionContainer, {});
1317
1362
  }
1318
1363
  if (pauseView.kind === "ask-user") {
1319
- return /* @__PURE__ */ jsx13(AskUserContainer, {});
1364
+ return /* @__PURE__ */ jsx14(AskUserContainer, {});
1320
1365
  }
1321
1366
  if (canMutateSpec) {
1322
- return /* @__PURE__ */ jsx13(DraftCatalogProvider, { children: /* @__PURE__ */ jsx13(
1367
+ return /* @__PURE__ */ jsx14(DraftCatalogProvider, { children: /* @__PURE__ */ jsx14(
1323
1368
  SlotsProvider,
1324
1369
  {
1325
1370
  overrides: {
1326
1371
  ComposerLeftSection: usesDefaultLeftSection ? DraftComposerLeftSection : parentLeftSection,
1327
1372
  ComposerRightSection: usesDefaultRightSection ? DraftComposerRightSection : parentRightSection
1328
1373
  },
1329
- children: /* @__PURE__ */ jsx13(ComposerBody, { placeholder })
1374
+ children: /* @__PURE__ */ jsx14(ComposerBody, { placeholder })
1330
1375
  }
1331
1376
  ) });
1332
1377
  }
1333
- return /* @__PURE__ */ jsx13(ComposerBody, { placeholder });
1378
+ return /* @__PURE__ */ jsx14(ComposerBody, { placeholder });
1334
1379
  }
1335
1380
 
1336
1381
  // src/containers/HistoryLoaderContainer.tsx
1337
1382
  import { useTrueFoundryHistoryPagination } from "@truefoundry/assistant-ui-runtime";
1338
- import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef7, useState as useState10 } from "react";
1339
- import { jsx as jsx14 } from "react/jsx-runtime";
1383
+ import { useCallback as useCallback7, useEffect as useEffect6, useRef as useRef7, useState as useState10 } from "react";
1384
+ import { jsx as jsx15 } from "react/jsx-runtime";
1340
1385
  var TOP_THRESHOLD_PX = 200;
1341
1386
  var VIEWPORT_SELECTOR = '[data-slot="aui_thread-viewport"]';
1342
1387
  function HistoryLoaderContainer() {
@@ -1344,7 +1389,7 @@ function HistoryLoaderContainer() {
1344
1389
  const { hasOlderHistory, isLoadingOlderHistory, loadOlderHistory } = useTrueFoundryHistoryPagination();
1345
1390
  const [sentinel, setSentinel] = useState10(null);
1346
1391
  const inflightRef = useRef7(false);
1347
- const maybeLoadOlder = useCallback6(async () => {
1392
+ const maybeLoadOlder = useCallback7(async () => {
1348
1393
  if (inflightRef.current) return;
1349
1394
  inflightRef.current = true;
1350
1395
  const viewport = sentinel?.closest(VIEWPORT_SELECTOR) ?? null;
@@ -1379,48 +1424,48 @@ function HistoryLoaderContainer() {
1379
1424
  return () => observer.disconnect();
1380
1425
  }, [sentinel, hasOlderHistory, maybeLoadOlder]);
1381
1426
  if (!hasOlderHistory) return null;
1382
- return /* @__PURE__ */ jsx14(HistoryLoader, { ref: setSentinel, isLoading: isLoadingOlderHistory });
1427
+ return /* @__PURE__ */ jsx15(HistoryLoader, { ref: setSentinel, isLoading: isLoadingOlderHistory });
1383
1428
  }
1384
1429
 
1385
1430
  // src/containers/ResumeUnavailableContainer.tsx
1386
1431
  import { useTrueFoundryResumeUnavailable as useTrueFoundryResumeUnavailable2 } from "@truefoundry/assistant-ui-runtime";
1387
- import { jsx as jsx15 } from "react/jsx-runtime";
1432
+ import { jsx as jsx16 } from "react/jsx-runtime";
1388
1433
  function ResumeUnavailableContainer() {
1389
1434
  const ResumeUnavailable = useSlot("ResumeUnavailable");
1390
1435
  const resumeUnavailable = useTrueFoundryResumeUnavailable2();
1391
1436
  if (!resumeUnavailable) return null;
1392
- return /* @__PURE__ */ jsx15(ResumeUnavailable, {});
1437
+ return /* @__PURE__ */ jsx16(ResumeUnavailable, {});
1393
1438
  }
1394
1439
 
1395
1440
  // src/containers/UserEditComposerContainer.tsx
1396
- import { useComposerCancel, useComposerSend, useThreadIsRunning as useThreadIsRunning4 } from "@assistant-ui/core/react";
1441
+ import { useComposerCancel, useComposerSend, useThreadIsRunning as useThreadIsRunning5 } from "@assistant-ui/core/react";
1397
1442
  import { ComposerPrimitive as ComposerPrimitive3, MessagePrimitive as MessagePrimitive4, useAuiState as useAuiState10 } from "@assistant-ui/react";
1398
- import { jsx as jsx16, jsxs as jsxs2 } from "react/jsx-runtime";
1443
+ import { jsx as jsx17, jsxs as jsxs2 } from "react/jsx-runtime";
1399
1444
  function ReadOnlyMessageAttachments() {
1400
1445
  const hasAttachments = useAuiState10((s) => (s.message.attachments?.length ?? 0) > 0);
1401
1446
  if (!hasAttachments) {
1402
1447
  return null;
1403
1448
  }
1404
- return /* @__PURE__ */ jsx16("div", { className: "pointer-events-none mb-2 opacity-90", children: /* @__PURE__ */ jsx16(MessageAttachmentsContainer, {}) });
1449
+ return /* @__PURE__ */ jsx17("div", { className: "pointer-events-none mb-2 opacity-90", children: /* @__PURE__ */ jsx17(MessageAttachmentsContainer, {}) });
1405
1450
  }
1406
1451
  function UserEditComposerContainer() {
1407
1452
  const UserMessageEdit = useSlot("UserMessageEdit");
1408
1453
  const MessageTimestamp = useSlot("MessageTimestamp");
1409
- const isRunning = useThreadIsRunning4();
1454
+ const isRunning = useThreadIsRunning5();
1410
1455
  const createdAt = useAuiState10((s) => s.message.createdAt);
1411
1456
  const { cancel, disabled: cancelDisabled } = useComposerCancel();
1412
1457
  const { disabled: sendDisabled } = useComposerSend();
1413
- return /* @__PURE__ */ jsx16(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsx16(
1458
+ return /* @__PURE__ */ jsx17(MessagePrimitive4.Root, { "data-role": "user", children: /* @__PURE__ */ jsx17(
1414
1459
  ComposerPrimitive3.Root,
1415
1460
  {
1416
1461
  "data-slot": "aui_user-edit-composer-root",
1417
1462
  className: "fade-in slide-in-from-bottom-1 animate-in flex w-full justify-end px-2 duration-150",
1418
- children: /* @__PURE__ */ jsx16(
1463
+ children: /* @__PURE__ */ jsx17(
1419
1464
  UserMessageEdit,
1420
1465
  {
1421
- timestamp: /* @__PURE__ */ jsx16(MessageTimestamp, { createdAt }),
1422
- attachments: /* @__PURE__ */ jsx16(ReadOnlyMessageAttachments, {}),
1423
- input: /* @__PURE__ */ jsx16("div", { className: "mt-1 rounded border border-border bg-secondary-bg p-2 text-text-primary", children: /* @__PURE__ */ jsx16(
1466
+ timestamp: /* @__PURE__ */ jsx17(MessageTimestamp, { createdAt }),
1467
+ attachments: /* @__PURE__ */ jsx17(ReadOnlyMessageAttachments, {}),
1468
+ input: /* @__PURE__ */ jsx17("div", { className: "mt-1 rounded border border-border bg-secondary-bg p-2 text-text-primary", children: /* @__PURE__ */ jsx17(
1424
1469
  ComposerPrimitive3.Input,
1425
1470
  {
1426
1471
  "data-slot": "aui_user-edit-input",
@@ -1431,8 +1476,8 @@ function UserEditComposerContainer() {
1431
1476
  }
1432
1477
  ) }),
1433
1478
  footer: /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-end gap-2", children: [
1434
- /* @__PURE__ */ jsx16(Button, { variant: "secondary", type: "button", disabled: cancelDisabled, onClick: cancel, children: "Cancel" }),
1435
- /* @__PURE__ */ jsx16(ComposerPrimitive3.Send, { asChild: true, children: /* @__PURE__ */ jsx16(Button, { type: "submit", disabled: sendDisabled || isRunning, children: "Save & Rerun" }) })
1479
+ /* @__PURE__ */ jsx17(Button, { variant: "secondary", type: "button", disabled: cancelDisabled, onClick: cancel, children: "Cancel" }),
1480
+ /* @__PURE__ */ jsx17(ComposerPrimitive3.Send, { asChild: true, children: /* @__PURE__ */ jsx17(Button, { type: "submit", disabled: sendDisabled || isRunning, children: "Save & Rerun" }) })
1436
1481
  ] })
1437
1482
  }
1438
1483
  )
@@ -1441,13 +1486,13 @@ function UserEditComposerContainer() {
1441
1486
  }
1442
1487
 
1443
1488
  // src/containers/UserMessageContainer.tsx
1444
- import { useActionBarCopy as useActionBarCopy2, useActionBarEdit, useThreadIsRunning as useThreadIsRunning5 } from "@assistant-ui/core/react";
1489
+ import { useActionBarCopy as useActionBarCopy2, useActionBarEdit, useThreadIsRunning as useThreadIsRunning6 } from "@assistant-ui/core/react";
1445
1490
  import { MessagePrimitive as MessagePrimitive5, useAui as useAui4, useAuiState as useAuiState11 } from "@assistant-ui/react";
1446
- import { jsx as jsx17 } from "react/jsx-runtime";
1491
+ import { jsx as jsx18 } from "react/jsx-runtime";
1447
1492
  function UserMessageContainer() {
1448
1493
  const UserMessageBubble = useSlot("UserMessageBubble");
1449
1494
  const UserMessageActionBar = useSlot("UserMessageActionBar");
1450
- const isRunning = useThreadIsRunning5();
1495
+ const isRunning = useThreadIsRunning6();
1451
1496
  const aui = useAui4();
1452
1497
  const createdAt = useAuiState11((s) => s.message.createdAt);
1453
1498
  const text = useAuiState11(
@@ -1457,12 +1502,12 @@ function UserMessageContainer() {
1457
1502
  const { copy, isCopied } = useActionBarCopy2({
1458
1503
  copyToClipboard: (value) => navigator.clipboard.writeText(value)
1459
1504
  });
1460
- return /* @__PURE__ */ jsx17(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx17(
1505
+ return /* @__PURE__ */ jsx18(MessagePrimitive5.Root, { "data-role": "user", children: /* @__PURE__ */ jsx18(
1461
1506
  UserMessageBubble,
1462
1507
  {
1463
1508
  text,
1464
- attachments: /* @__PURE__ */ jsx17(MessageAttachmentsContainer, {}),
1465
- editAction: !isRunning ? /* @__PURE__ */ jsx17(
1509
+ attachments: /* @__PURE__ */ jsx18(MessageAttachmentsContainer, {}),
1510
+ editAction: !isRunning ? /* @__PURE__ */ jsx18(
1466
1511
  UserMessageActionBar,
1467
1512
  {
1468
1513
  isCopied,
@@ -1485,14 +1530,14 @@ import { ThreadPrimitive, useAuiState as useAuiState12 } from "@assistant-ui/rea
1485
1530
  import { useEffect as useEffect8 } from "react";
1486
1531
 
1487
1532
  // src/hooks/useSyncSessionTitle.ts
1488
- import { useThreadIsRunning as useThreadIsRunning6 } from "@assistant-ui/core/react";
1533
+ import { useThreadIsRunning as useThreadIsRunning7 } from "@assistant-ui/core/react";
1489
1534
  import { useEffect as useEffect7, useRef as useRef8 } from "react";
1490
1535
  function useSyncSessionTitle() {
1491
1536
  const server = useOptionalServer();
1492
1537
  const aui = useAui();
1493
1538
  const remoteId = useAuiState((s) => s.threadListItem.remoteId);
1494
1539
  const title = useAuiState((s) => s.threadListItem.title);
1495
- const isRunning = useThreadIsRunning6();
1540
+ const isRunning = useThreadIsRunning7();
1496
1541
  const wasRunningRef = useRef8(false);
1497
1542
  const syncedRemoteIdRef = useRef8(void 0);
1498
1543
  useEffect7(() => {
@@ -1529,19 +1574,19 @@ function useSyncSessionTitle() {
1529
1574
  var isNewChatView = (s) => s.thread.messages.length === 0 && (!s.thread.isLoading || s.threads.isLoading) && s.threadListItem.remoteId == null;
1530
1575
 
1531
1576
  // src/containers/ThreadContainer.tsx
1532
- import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs3 } from "react/jsx-runtime";
1577
+ import { Fragment as Fragment2, jsx as jsx19, jsxs as jsxs3 } from "react/jsx-runtime";
1533
1578
  function AnimatedMessageShell({ children }) {
1534
- return /* @__PURE__ */ jsx18("div", { className: "animate-in fade-in slide-in-from-bottom-1 fill-mode-both duration-200", children });
1579
+ return /* @__PURE__ */ jsx19("div", { className: "animate-in fade-in slide-in-from-bottom-1 fill-mode-both duration-200", children });
1535
1580
  }
1536
1581
  function ThreadMessage({ isEditing }) {
1537
1582
  const role = useAuiState12((s) => s.message.role);
1538
1583
  if (role === "user") {
1539
1584
  if (isEditing) {
1540
- return /* @__PURE__ */ jsx18(UserEditComposerContainer, {});
1585
+ return /* @__PURE__ */ jsx19(UserEditComposerContainer, {});
1541
1586
  }
1542
- return /* @__PURE__ */ jsx18(UserMessageContainer, {});
1587
+ return /* @__PURE__ */ jsx19(UserMessageContainer, {});
1543
1588
  }
1544
- return /* @__PURE__ */ jsx18(AssistantMessageContainer, {});
1589
+ return /* @__PURE__ */ jsx19(AssistantMessageContainer, {});
1545
1590
  }
1546
1591
  function ThreadContainer({ composer }) {
1547
1592
  useEffect8(() => {
@@ -1559,29 +1604,29 @@ function ThreadContainer({ composer }) {
1559
1604
  const isEmpty = useAuiState12(isNewChatView);
1560
1605
  const isLoading = useAuiState12((s) => s.thread.isLoading);
1561
1606
  const welcomeHeading = shell?.mode.status === "active" ? shell.mode.agentName : void 0;
1562
- return /* @__PURE__ */ jsx18(ComposerBusyProvider, { children: /* @__PURE__ */ jsx18(ThreadPrimitive.Root, { asChild: true, children: /* @__PURE__ */ jsxs3(ThreadRootShell, { children: [
1563
- /* @__PURE__ */ jsx18(ThreadPrimitive.Viewport, { asChild: true, autoScroll: true, children: /* @__PURE__ */ jsxs3(ThreadViewportShell, { isEmpty, children: [
1564
- isEmpty && /* @__PURE__ */ jsx18(WelcomeScreen, { heading: welcomeHeading }),
1607
+ return /* @__PURE__ */ jsx19(ComposerBusyProvider, { children: /* @__PURE__ */ jsx19(ThreadPrimitive.Root, { asChild: true, children: /* @__PURE__ */ jsxs3(ThreadRootShell, { children: [
1608
+ /* @__PURE__ */ jsx19(ThreadPrimitive.Viewport, { asChild: true, autoScroll: true, children: /* @__PURE__ */ jsxs3(ThreadViewportShell, { isEmpty, children: [
1609
+ isEmpty && /* @__PURE__ */ jsx19(WelcomeScreen, { heading: welcomeHeading }),
1565
1610
  isEmpty && !isLoading && composer,
1566
- isLoading ? /* @__PURE__ */ jsx18(MessageListSkeleton, {}) : !isEmpty && /* @__PURE__ */ jsxs3(Fragment2, { children: [
1567
- /* @__PURE__ */ jsx18(HistoryLoaderContainer, {}),
1611
+ isLoading ? /* @__PURE__ */ jsx19(MessageListSkeleton, {}) : !isEmpty && /* @__PURE__ */ jsxs3(Fragment2, { children: [
1612
+ /* @__PURE__ */ jsx19(HistoryLoaderContainer, {}),
1568
1613
  /* @__PURE__ */ jsxs3(MessageGroup, { children: [
1569
- /* @__PURE__ */ jsx18(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx18(AnimatedMessageShell, { children: /* @__PURE__ */ jsx18(ThreadMessage, { isEditing: message.role === "user" && message.composer.isEditing }) }) }),
1570
- /* @__PURE__ */ jsx18(ResumeUnavailableContainer, {})
1614
+ /* @__PURE__ */ jsx19(ThreadPrimitive.Messages, { children: ({ message }) => /* @__PURE__ */ jsx19(AnimatedMessageShell, { children: /* @__PURE__ */ jsx19(ThreadMessage, { isEditing: message.role === "user" && message.composer.isEditing }) }) }),
1615
+ /* @__PURE__ */ jsx19(ResumeUnavailableContainer, {})
1571
1616
  ] })
1572
1617
  ] })
1573
1618
  ] }) }),
1574
1619
  !isLoading && !isEmpty && /* @__PURE__ */ jsxs3(ThreadComposerAreaShell, { isEmpty, children: [
1575
- /* @__PURE__ */ jsx18(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx18(ScrollToBottomButton, {}) }),
1620
+ /* @__PURE__ */ jsx19(ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx19(ScrollToBottomButton, {}) }),
1576
1621
  composer
1577
1622
  ] })
1578
1623
  ] }) }) });
1579
1624
  }
1580
1625
 
1581
1626
  // src/containers/Thread.tsx
1582
- import { jsx as jsx19 } from "react/jsx-runtime";
1627
+ import { jsx as jsx20 } from "react/jsx-runtime";
1583
1628
  function Thread() {
1584
- return /* @__PURE__ */ jsx19(ThreadContainer, { composer: /* @__PURE__ */ jsx19(ComposerContainer, {}) });
1629
+ return /* @__PURE__ */ jsx20(ThreadContainer, { composer: /* @__PURE__ */ jsx20(ComposerContainer, {}) });
1585
1630
  }
1586
1631
 
1587
1632
  // src/containers/ThreadListContainer.tsx
@@ -1593,7 +1638,7 @@ import {
1593
1638
  useAui as useAui5,
1594
1639
  useAuiState as useAuiState13
1595
1640
  } from "@assistant-ui/react";
1596
- import { useEffect as useEffect11, useMemo as useMemo5, useRef as useRef11, useState as useState13 } from "react";
1641
+ import { useCallback as useCallback8, useEffect as useEffect11, useMemo as useMemo5, useRef as useRef11, useState as useState13 } from "react";
1597
1642
 
1598
1643
  // src/atoms/AgentHistoryFilterButton.tsx
1599
1644
  import { useEffect as useEffect10, useId as useId2, useLayoutEffect, useRef as useRef10, useState as useState12 } from "react";
@@ -1601,9 +1646,9 @@ import { createPortal } from "react-dom";
1601
1646
 
1602
1647
  // src/atoms/primitives/DropdownMenu.tsx
1603
1648
  import React, { useEffect as useEffect9, useId, useRef as useRef9, useState as useState11 } from "react";
1604
- import { jsx as jsx20, jsxs as jsxs4 } from "react/jsx-runtime";
1649
+ import { jsx as jsx21, jsxs as jsxs4 } from "react/jsx-runtime";
1605
1650
  function DropdownMenuItem({ className, ...props }) {
1606
- return /* @__PURE__ */ jsx20(
1651
+ return /* @__PURE__ */ jsx21(
1607
1652
  "button",
1608
1653
  {
1609
1654
  role: "menuitem",
@@ -1622,7 +1667,7 @@ function DropdownMenuItem({ className, ...props }) {
1622
1667
  }
1623
1668
 
1624
1669
  // src/atoms/AgentHistoryFilterButton.tsx
1625
- import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs5 } from "react/jsx-runtime";
1670
+ import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs5 } from "react/jsx-runtime";
1626
1671
  function themePortalRoot(from) {
1627
1672
  return from?.closest(".aui-theme-root") ?? document.body;
1628
1673
  }
@@ -1682,8 +1727,8 @@ function AgentHistoryFilterButton() {
1682
1727
  };
1683
1728
  const filterBody = /* @__PURE__ */ jsxs5(Fragment3, { children: [
1684
1729
  /* @__PURE__ */ jsxs5("div", { className: "p-1", onMouseDown: (e) => e.stopPropagation(), children: [
1685
- /* @__PURE__ */ jsx21(SearchInput_default, { query, setQuery, placeholder: "Search agents" }),
1686
- isSearching ? /* @__PURE__ */ jsx21("p", { className: "text-text-secondary px-1 pt-1 text-[11px]", role: "status", children: "Searching\u2026" }) : null
1730
+ /* @__PURE__ */ jsx22(SearchInput_default, { query, setQuery, placeholder: "Search agents" }),
1731
+ isSearching ? /* @__PURE__ */ jsx22("p", { className: "text-text-secondary px-1 pt-1 text-[11px]", role: "status", children: "Searching\u2026" }) : null
1687
1732
  ] }),
1688
1733
  /* @__PURE__ */ jsxs5(
1689
1734
  "div",
@@ -1701,11 +1746,11 @@ function AgentHistoryFilterButton() {
1701
1746
  onClick: () => pick(null),
1702
1747
  children: [
1703
1748
  "All chats",
1704
- selected == null ? /* @__PURE__ */ jsx21(Icon, { name: "check", className: "size-3.5 shrink-0" }) : null
1749
+ selected == null ? /* @__PURE__ */ jsx22(Icon, { name: "check", className: "size-3.5 shrink-0" }) : null
1705
1750
  ]
1706
1751
  }
1707
1752
  ) : null,
1708
- isInitialLoading ? /* @__PURE__ */ jsx21("p", { className: "px-2 py-3 text-center text-xs text-text-secondary", children: "Loading\u2026" }) : agents.length === 0 ? /* @__PURE__ */ jsx21("p", { className: "text-text-secondary px-2 py-6 text-center text-xs", role: "status", children: query.trim() ? `No agents match "${query.trim()}".` : "No agents yet." }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
1753
+ isInitialLoading ? /* @__PURE__ */ jsx22("p", { className: "px-2 py-3 text-center text-xs text-text-secondary", children: "Loading\u2026" }) : agents.length === 0 ? /* @__PURE__ */ jsx22("p", { className: "text-text-secondary px-2 py-6 text-center text-xs", role: "status", children: query.trim() ? `No agents match "${query.trim()}".` : "No agents yet." }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
1709
1754
  agents.map((agent) => {
1710
1755
  const id = libraryAgentId(agent);
1711
1756
  const active = selected === id;
@@ -1718,14 +1763,14 @@ function AgentHistoryFilterButton() {
1718
1763
  ),
1719
1764
  onClick: () => pick(id),
1720
1765
  children: [
1721
- /* @__PURE__ */ jsx21("span", { className: "min-w-0 truncate", children: agent.name }),
1722
- active ? /* @__PURE__ */ jsx21(Icon, { name: "check", className: "size-3.5 shrink-0" }) : null
1766
+ /* @__PURE__ */ jsx22("span", { className: "min-w-0 truncate", children: agent.name }),
1767
+ active ? /* @__PURE__ */ jsx22(Icon, { name: "check", className: "size-3.5 shrink-0" }) : null
1723
1768
  ]
1724
1769
  },
1725
1770
  id
1726
1771
  );
1727
1772
  }),
1728
- hasMore ? /* @__PURE__ */ jsx21("div", { ref: sentinelRef, className: "flex h-6 shrink-0 items-center justify-center", "aria-hidden": true, children: loadingMore ? /* @__PURE__ */ jsx21("span", { className: "text-text-secondary text-[11px]", role: "status", children: "Loading more\u2026" }) : null }) : null
1773
+ hasMore ? /* @__PURE__ */ jsx22("div", { ref: sentinelRef, className: "flex h-6 shrink-0 items-center justify-center", "aria-hidden": true, children: loadingMore ? /* @__PURE__ */ jsx22("span", { className: "text-text-secondary text-[11px]", role: "status", children: "Loading more\u2026" }) : null }) : null
1729
1774
  ] })
1730
1775
  ]
1731
1776
  }
@@ -1752,8 +1797,8 @@ function AgentHistoryFilterButton() {
1752
1797
  }),
1753
1798
  onClick: () => setOpen((v) => !v),
1754
1799
  children: [
1755
- /* @__PURE__ */ jsx21(Icon, { name: "funnel", className: "size-3.5" }),
1756
- selected != null ? /* @__PURE__ */ jsx21(
1800
+ /* @__PURE__ */ jsx22(Icon, { name: "funnel", className: "size-3.5" }),
1801
+ selected != null ? /* @__PURE__ */ jsx22(
1757
1802
  "span",
1758
1803
  {
1759
1804
  className: "bg-primary-button-bg absolute top-1 right-1 size-1.5 rounded-full",
@@ -1764,9 +1809,9 @@ function AgentHistoryFilterButton() {
1764
1809
  ]
1765
1810
  }
1766
1811
  ),
1767
- useSheet && open ? /* @__PURE__ */ jsx21(BottomSheet, { open: true, onOpenChange: setOpen, id: menuId, "aria-label": "Filter agents", children: /* @__PURE__ */ jsx21("div", { className: "flex min-h-0 flex-1 flex-col p-2", role: "menu", children: filterBody }) }) : null,
1812
+ useSheet && open ? /* @__PURE__ */ jsx22(BottomSheet, { open: true, onOpenChange: setOpen, id: menuId, "aria-label": "Filter agents", children: /* @__PURE__ */ jsx22("div", { className: "flex min-h-0 flex-1 flex-col p-2", role: "menu", children: filterBody }) }) : null,
1768
1813
  !useSheet && open && menuPos != null ? createPortal(
1769
- /* @__PURE__ */ jsx21(
1814
+ /* @__PURE__ */ jsx22(
1770
1815
  "div",
1771
1816
  {
1772
1817
  ref: menuRef,
@@ -1784,13 +1829,18 @@ function AgentHistoryFilterButton() {
1784
1829
  }
1785
1830
 
1786
1831
  // src/containers/ThreadListContainer.tsx
1787
- import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs6 } from "react/jsx-runtime";
1788
- var deleteItemClass = "flex w-full cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none text-failure-bg hover:bg-ghost-button-hover hover:text-failure-bg focus:bg-ghost-button-hover focus:text-failure-bg data-[highlighted]:bg-ghost-button-hover data-[highlighted]:text-failure-bg";
1832
+ import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs6 } from "react/jsx-runtime";
1833
+ var deleteItemClass = "flex w-full cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium text-failure-bg outline-none transition-colors hover:bg-failure-bg/12 hover:text-failure-bg focus:bg-failure-bg/12 focus:text-failure-bg data-[highlighted]:bg-failure-bg/12 data-[highlighted]:text-failure-bg";
1789
1834
  function ThreadListItemDeleteMenu() {
1790
1835
  const compact = useCompactLayout();
1791
1836
  const isMobile = useIsMobile();
1792
1837
  const [sheetOpen, setSheetOpen] = useState13(false);
1838
+ const [portalContainer, setPortalContainer] = useState13();
1793
1839
  const useSheet = isMobile || compact;
1840
+ const setTriggerElement = useCallback8((element) => {
1841
+ const themeRoot = element?.closest(".aui-theme-root");
1842
+ setPortalContainer(themeRoot instanceof HTMLElement ? themeRoot : void 0);
1843
+ }, []);
1794
1844
  const moreButtonClass = auiButtonClass({
1795
1845
  variant: "ghost",
1796
1846
  size: "icon",
@@ -1798,7 +1848,7 @@ function ThreadListItemDeleteMenu() {
1798
1848
  });
1799
1849
  if (useSheet) {
1800
1850
  return /* @__PURE__ */ jsxs6(Fragment4, { children: [
1801
- /* @__PURE__ */ jsx22(
1851
+ /* @__PURE__ */ jsx23(
1802
1852
  "button",
1803
1853
  {
1804
1854
  type: "button",
@@ -1808,33 +1858,35 @@ function ThreadListItemDeleteMenu() {
1808
1858
  "aria-expanded": sheetOpen,
1809
1859
  className: moreButtonClass,
1810
1860
  onClick: () => setSheetOpen(true),
1811
- children: /* @__PURE__ */ jsx22(Icon, { name: "ellipsis", className: "size-3.5" })
1861
+ children: /* @__PURE__ */ jsx23(Icon, { name: "ellipsis", className: "size-3.5" })
1812
1862
  }
1813
1863
  ),
1814
- sheetOpen ? /* @__PURE__ */ jsx22(BottomSheet, { open: true, onOpenChange: setSheetOpen, "aria-label": "Session actions", children: /* @__PURE__ */ jsx22("div", { className: "flex flex-col gap-1 p-2", role: "menu", children: /* @__PURE__ */ jsxs6(ThreadListItemPrimitive.Delete, { className: deleteItemClass, onClick: () => setSheetOpen(false), children: [
1815
- /* @__PURE__ */ jsx22(Icon, { name: "trash", className: "size-3.5" }),
1864
+ sheetOpen ? /* @__PURE__ */ jsx23(BottomSheet, { open: true, onOpenChange: setSheetOpen, "aria-label": "Session actions", children: /* @__PURE__ */ jsx23("div", { className: "flex flex-col gap-1 p-2", role: "menu", children: /* @__PURE__ */ jsxs6(ThreadListItemPrimitive.Delete, { className: deleteItemClass, onClick: () => setSheetOpen(false), children: [
1865
+ /* @__PURE__ */ jsx23(Icon, { name: "trash", className: "size-3.5" }),
1816
1866
  "Delete"
1817
1867
  ] }) }) }) : null
1818
1868
  ] });
1819
1869
  }
1820
1870
  return /* @__PURE__ */ jsxs6(ThreadListItemMorePrimitive.Root, { sharedFocusGroup: true, children: [
1821
- /* @__PURE__ */ jsx22(
1871
+ /* @__PURE__ */ jsx23(
1822
1872
  ThreadListItemMorePrimitive.Trigger,
1823
1873
  {
1874
+ ref: setTriggerElement,
1824
1875
  "aria-label": "Session actions",
1825
1876
  title: "Session actions",
1826
1877
  className: moreButtonClass,
1827
- children: /* @__PURE__ */ jsx22(Icon, { name: "ellipsis", className: "size-3.5" })
1878
+ children: /* @__PURE__ */ jsx23(Icon, { name: "ellipsis", className: "size-3.5" })
1828
1879
  }
1829
1880
  ),
1830
- /* @__PURE__ */ jsx22(
1881
+ /* @__PURE__ */ jsx23(
1831
1882
  ThreadListItemMorePrimitive.Content,
1832
1883
  {
1884
+ portalProps: { container: portalContainer },
1833
1885
  align: "end",
1834
1886
  sideOffset: 4,
1835
- className: "z-50 min-w-[8rem] rounded-md border border-border bg-card-bg p-1 text-text-primary shadow-md",
1836
- children: /* @__PURE__ */ jsx22(ThreadListItemPrimitive.Delete, { asChild: true, children: /* @__PURE__ */ jsxs6(ThreadListItemMorePrimitive.Item, { className: deleteItemClass, children: [
1837
- /* @__PURE__ */ jsx22(Icon, { name: "trash", className: "size-3.5" }),
1887
+ className: "font-sans-flex z-50 min-w-[8rem] rounded-md border border-border bg-card-bg p-1 text-text-primary shadow-md",
1888
+ children: /* @__PURE__ */ jsx23(ThreadListItemPrimitive.Delete, { asChild: true, children: /* @__PURE__ */ jsxs6(ThreadListItemMorePrimitive.Item, { className: deleteItemClass, children: [
1889
+ /* @__PURE__ */ jsx23(Icon, { name: "trash", className: "size-3.5" }),
1838
1890
  "Delete"
1839
1891
  ] }) })
1840
1892
  }
@@ -1856,7 +1908,7 @@ function ThreadListItemRow({
1856
1908
  const mainThreadId = useAuiState13((s) => s.threads.mainThreadId);
1857
1909
  const agentName = readThreadAgentName(custom);
1858
1910
  const showDelete = canDeleteSession && remoteId != null;
1859
- return /* @__PURE__ */ jsx22(ThreadListItemPrimitive.Root, { className: "min-w-0", children: /* @__PURE__ */ jsx22(
1911
+ return /* @__PURE__ */ jsx23(ThreadListItemPrimitive.Root, { className: "min-w-0", children: /* @__PURE__ */ jsx23(
1860
1912
  ThreadListRow,
1861
1913
  {
1862
1914
  title: title ?? "New Chat",
@@ -1889,7 +1941,7 @@ function ThreadListItemRow({
1889
1941
  }
1890
1942
  void Promise.resolve(aui.threads().switchToThread(id)).catch(() => void 0);
1891
1943
  },
1892
- actions: showDelete ? /* @__PURE__ */ jsx22(ThreadListItemDeleteMenu, {}) : void 0
1944
+ actions: showDelete ? /* @__PURE__ */ jsx23(ThreadListItemDeleteMenu, {}) : void 0
1893
1945
  }
1894
1946
  ) });
1895
1947
  }
@@ -1904,9 +1956,9 @@ function ThreadListItemsByRecency({
1904
1956
  }) {
1905
1957
  const indices = useThreadListIndicesByRecency();
1906
1958
  const threadIds = useAuiState13((s) => s.threads.threadIds);
1907
- return /* @__PURE__ */ jsx22(Fragment4, { children: indices.map((index) => {
1959
+ return /* @__PURE__ */ jsx23(Fragment4, { children: indices.map((index) => {
1908
1960
  const key = threadIds[index] ?? String(index);
1909
- return /* @__PURE__ */ jsx22(ThreadListItemByIndexProvider, { index, archived: false, children: /* @__PURE__ */ jsx22(ThreadListItemRow, { onThreadOpen, canDeleteSession }) }, key);
1961
+ return /* @__PURE__ */ jsx23(ThreadListItemByIndexProvider, { index, archived: false, children: /* @__PURE__ */ jsx23(ThreadListItemRow, { onThreadOpen, canDeleteSession }) }, key);
1910
1962
  }) });
1911
1963
  }
1912
1964
  var THREAD_LIST_VIEWPORT_SLOT = "aui_thread-list-viewport";
@@ -1925,8 +1977,8 @@ function ChatHistorySection({ children, viewportRef }) {
1925
1977
  className: "flex min-w-0 flex-1 items-center gap-1 rounded-md px-1.5 py-1 text-left text-sm font-medium text-text-secondary hover:bg-ghost-button-hover hover:text-text-primary",
1926
1978
  onClick: () => setExpanded((v) => !v),
1927
1979
  children: [
1928
- /* @__PURE__ */ jsx22("span", { className: "truncate", children: "Chat History" }),
1929
- /* @__PURE__ */ jsx22(
1980
+ /* @__PURE__ */ jsx23("span", { className: "truncate", children: "Chat History" }),
1981
+ /* @__PURE__ */ jsx23(
1930
1982
  Icon,
1931
1983
  {
1932
1984
  name: "chevron-down",
@@ -1936,9 +1988,9 @@ function ChatHistorySection({ children, viewportRef }) {
1936
1988
  ]
1937
1989
  }
1938
1990
  ),
1939
- showFilter ? /* @__PURE__ */ jsx22(AgentHistoryFilterButton, {}) : null
1991
+ showFilter ? /* @__PURE__ */ jsx23(AgentHistoryFilterButton, {}) : null
1940
1992
  ] }),
1941
- expanded ? /* @__PURE__ */ jsx22(
1993
+ expanded ? /* @__PURE__ */ jsx23(
1942
1994
  "div",
1943
1995
  {
1944
1996
  ref: viewportRef,
@@ -2010,20 +2062,20 @@ function ThreadListContainer({ onThreadOpen } = {}) {
2010
2062
  };
2011
2063
  let listBody;
2012
2064
  if (isIdle) {
2013
- listBody = /* @__PURE__ */ jsx22(ThreadListEmptyState, {});
2065
+ listBody = /* @__PURE__ */ jsx23(ThreadListEmptyState, {});
2014
2066
  } else if (isLoading) {
2015
- listBody = /* @__PURE__ */ jsx22(ThreadListRowSkeleton, {});
2067
+ listBody = /* @__PURE__ */ jsx23(ThreadListRowSkeleton, {});
2016
2068
  } else if (threadIds.length === 0) {
2017
- listBody = /* @__PURE__ */ jsx22(ThreadListEmptyState, {});
2069
+ listBody = /* @__PURE__ */ jsx23(ThreadListEmptyState, {});
2018
2070
  } else {
2019
- listBody = /* @__PURE__ */ jsx22(ThreadListPrimitive.Root, { className: "flex min-h-0 flex-col gap-0.5", children: /* @__PURE__ */ jsx22(ThreadListItemsByRecency, { onThreadOpen, canDeleteSession }) });
2071
+ listBody = /* @__PURE__ */ jsx23(ThreadListPrimitive.Root, { className: "flex min-h-0 flex-col gap-0.5", children: /* @__PURE__ */ jsx23(ThreadListItemsByRecency, { onThreadOpen, canDeleteSession }) });
2020
2072
  }
2021
- return /* @__PURE__ */ jsx22(
2073
+ return /* @__PURE__ */ jsx23(
2022
2074
  ThreadListShell,
2023
2075
  {
2024
2076
  header: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-1", children: [
2025
- showNewChat ? /* @__PURE__ */ jsx22(ThreadListNewButton, { onClick: handleNewChat }) : null,
2026
- /* @__PURE__ */ jsx22(
2077
+ showNewChat ? /* @__PURE__ */ jsx23(ThreadListNewButton, { onClick: handleNewChat }) : null,
2078
+ /* @__PURE__ */ jsx23(
2027
2079
  AgentsLibraryButton,
2028
2080
  {
2029
2081
  onSelectAgent: () => {
@@ -2034,7 +2086,7 @@ function ThreadListContainer({ onThreadOpen } = {}) {
2034
2086
  ] }),
2035
2087
  children: /* @__PURE__ */ jsxs6(ChatHistorySection, { viewportRef, children: [
2036
2088
  listBody,
2037
- !isIdle && hasMore ? /* @__PURE__ */ jsx22("div", { className: "h-4 shrink-0", "aria-hidden": true }) : null
2089
+ !isIdle && hasMore ? /* @__PURE__ */ jsx23("div", { className: "h-4 shrink-0", "aria-hidden": true }) : null
2038
2090
  ] })
2039
2091
  }
2040
2092
  );
@@ -2055,6 +2107,7 @@ export {
2055
2107
  ComposerAttachmentPickerContainer,
2056
2108
  threadHasPendingMcpAuth,
2057
2109
  useComposerPauseView,
2110
+ CustomActionContainer,
2058
2111
  McpAuthContainer,
2059
2112
  ComposerContainer,
2060
2113
  HistoryLoaderContainer,
@@ -2065,4 +2118,4 @@ export {
2065
2118
  Thread,
2066
2119
  ThreadListContainer
2067
2120
  };
2068
- //# sourceMappingURL=chunk-IWPDSPVA.js.map
2121
+ //# sourceMappingURL=chunk-3S6KHO7H.js.map