@agent-native/toolkit 0.198.4 → 0.198.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 (96) hide show
  1. package/dist/app/agentkit/react/components.d.ts +6 -3
  2. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  3. package/dist/app/agentkit/react/components.js +98 -68
  4. package/dist/app/agentkit/react/components.js.map +1 -1
  5. package/dist/app/agentkit/react/styles.css +36 -24
  6. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  7. package/dist/app/chat/AgentKitAssistantChat.js +32 -15
  8. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  9. package/dist/app/chat/AgentPanel.d.ts +1 -1
  10. package/dist/app/chat/AgentPanel.d.ts.map +1 -1
  11. package/dist/app/chat/AgentPanel.js +11 -38
  12. package/dist/app/chat/AgentPanel.js.map +1 -1
  13. package/dist/app/chat/AgentSidebar.d.ts.map +1 -1
  14. package/dist/app/chat/AgentSidebar.js +3 -11
  15. package/dist/app/chat/AgentSidebar.js.map +1 -1
  16. package/dist/app/chat/chat/tool-call-display.d.ts +2 -1
  17. package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
  18. package/dist/app/chat/chat/tool-call-display.js +83 -55
  19. package/dist/app/chat/chat/tool-call-display.js.map +1 -1
  20. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  21. package/dist/app/i18n/catalogs/ar-SA.js +1 -0
  22. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  23. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  24. package/dist/app/i18n/catalogs/de-DE.js +1 -0
  25. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  26. package/dist/app/i18n/catalogs/en-US.d.ts +1 -0
  27. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  28. package/dist/app/i18n/catalogs/en-US.js +1 -0
  29. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  30. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  31. package/dist/app/i18n/catalogs/es-ES.js +1 -0
  32. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  33. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  34. package/dist/app/i18n/catalogs/fr-FR.js +1 -0
  35. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  36. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  37. package/dist/app/i18n/catalogs/hi-IN.js +1 -0
  38. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  39. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  40. package/dist/app/i18n/catalogs/ja-JP.js +1 -0
  41. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  42. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  43. package/dist/app/i18n/catalogs/ko-KR.js +1 -0
  44. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  45. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  46. package/dist/app/i18n/catalogs/pt-BR.js +1 -0
  47. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  48. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  49. package/dist/app/i18n/catalogs/zh-CN.js +1 -0
  50. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  51. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  52. package/dist/app/i18n/catalogs/zh-TW.js +1 -0
  53. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  54. package/dist/composer/PromptComposer.d.ts +3 -0
  55. package/dist/composer/PromptComposer.d.ts.map +1 -1
  56. package/dist/composer/PromptComposer.js +2 -2
  57. package/dist/composer/PromptComposer.js.map +1 -1
  58. package/dist/composer/TiptapComposer.d.ts +4 -1
  59. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  60. package/dist/composer/TiptapComposer.js +32 -25
  61. package/dist/composer/TiptapComposer.js.map +1 -1
  62. package/dist/ui/sonner.js +1 -1
  63. package/dist/ui/sonner.js.map +1 -1
  64. package/package.json +3 -3
  65. package/src/app/agentkit/react/components.interaction.spec.tsx +93 -0
  66. package/src/app/agentkit/react/components.spec.tsx +1 -2
  67. package/src/app/agentkit/react/components.tsx +185 -132
  68. package/src/app/agentkit/react/composer-context.spec.tsx +7 -0
  69. package/src/app/agentkit/react/lifecycle.spec.tsx +556 -39
  70. package/src/app/agentkit/react/styles.css +36 -24
  71. package/src/app/chat/AgentKitAssistantChat.spec.tsx +60 -1
  72. package/src/app/chat/AgentKitAssistantChat.tsx +45 -14
  73. package/src/app/chat/AgentPanel.overlay.spec.tsx +28 -4
  74. package/src/app/chat/AgentPanel.tsx +51 -168
  75. package/src/app/chat/AgentSidebar.spec.tsx +19 -19
  76. package/src/app/chat/AgentSidebar.tsx +59 -94
  77. package/src/app/chat/chat/tool-call-display.spec.tsx +371 -15
  78. package/src/app/chat/chat/tool-call-display.tsx +154 -80
  79. package/src/app/i18n/catalogs/ar-SA.ts +1 -0
  80. package/src/app/i18n/catalogs/de-DE.ts +1 -0
  81. package/src/app/i18n/catalogs/en-US.ts +1 -0
  82. package/src/app/i18n/catalogs/es-ES.ts +1 -0
  83. package/src/app/i18n/catalogs/fr-FR.ts +1 -0
  84. package/src/app/i18n/catalogs/hi-IN.ts +1 -0
  85. package/src/app/i18n/catalogs/ja-JP.ts +1 -0
  86. package/src/app/i18n/catalogs/ko-KR.ts +1 -0
  87. package/src/app/i18n/catalogs/pt-BR.ts +1 -0
  88. package/src/app/i18n/catalogs/zh-CN.ts +1 -0
  89. package/src/app/i18n/catalogs/zh-TW.ts +1 -0
  90. package/src/app-shell/sidebar-overflow.spec.tsx +2 -1
  91. package/src/composer/PromptComposer.context.spec.tsx +28 -15
  92. package/src/composer/PromptComposer.tsx +7 -0
  93. package/src/composer/TiptapComposer.spec.ts +40 -6
  94. package/src/composer/TiptapComposer.tsx +89 -89
  95. package/src/ui/sonner.spec.ts +15 -0
  96. package/src/ui/sonner.tsx +1 -1
@@ -984,6 +984,15 @@ body:has(> [data-agent-native-composer-popover="true"]) > .fixed.inset-0 {
984
984
  opacity: 1;
985
985
  }
986
986
 
987
+ .agentkit-message .agentkit-message-actions[data-streaming="true"],
988
+ .agentkit-message:hover .agentkit-message-actions[data-streaming="true"],
989
+ .agentkit-message:focus-within
990
+ .agentkit-message-actions[data-streaming="true"] {
991
+ opacity: 0;
992
+ visibility: hidden;
993
+ pointer-events: none;
994
+ }
995
+
987
996
  @media (hover: none), (any-pointer: coarse) {
988
997
  .agentkit-message-actions[data-role="user"] {
989
998
  opacity: 1;
@@ -1133,11 +1142,11 @@ body:has(> [data-agent-native-composer-popover="true"]) > .fixed.inset-0 {
1133
1142
  }
1134
1143
 
1135
1144
  .agentkit-activities-summary {
1136
- display: grid;
1145
+ display: flex;
1137
1146
  inline-size: fit-content;
1138
1147
  max-inline-size: 100%;
1139
- justify-items: start;
1140
- gap: 0.125rem;
1148
+ align-items: center;
1149
+ gap: 0.375rem;
1141
1150
  }
1142
1151
 
1143
1152
  .agentkit-activities {
@@ -1263,6 +1272,12 @@ body:has(> [data-agent-native-composer-popover="true"]) > .fixed.inset-0 {
1263
1272
  gap: 0.375rem;
1264
1273
  }
1265
1274
 
1275
+ .agentkit-activities-summary-content {
1276
+ display: grid;
1277
+ min-inline-size: 0;
1278
+ gap: 0.125rem;
1279
+ }
1280
+
1266
1281
  .agentkit-activities-current {
1267
1282
  display: flex;
1268
1283
  align-items: center;
@@ -1280,20 +1295,6 @@ body:has(> [data-agent-native-composer-popover="true"]) > .fixed.inset-0 {
1280
1295
  white-space: nowrap;
1281
1296
  }
1282
1297
 
1283
- .agentkit-activities-current[data-running="true"]
1284
- .agentkit-activities-current-label {
1285
- color: transparent;
1286
- background: linear-gradient(
1287
- 90deg,
1288
- var(--agentkit-text),
1289
- color-mix(in srgb, var(--agentkit-text) 32%, transparent),
1290
- var(--agentkit-text)
1291
- );
1292
- background-size: 200% 100%;
1293
- background-clip: text;
1294
- animation: agentkit-shimmer 1.8s linear infinite;
1295
- }
1296
-
1297
1298
  .agentkit-summary-chevron,
1298
1299
  .agentkit-disclosure-icon {
1299
1300
  transition:
@@ -1301,16 +1302,24 @@ body:has(> [data-agent-native-composer-popover="true"]) > .fixed.inset-0 {
1301
1302
  transform 160ms ease;
1302
1303
  }
1303
1304
 
1304
- .agentkit-activities-summary .agentkit-summary-chevron {
1305
+ .agentkit-activities-summary > .agentkit-summary-chevron {
1305
1306
  opacity: 0;
1306
1307
  }
1307
1308
 
1308
- .agentkit-activities-summary:hover .agentkit-summary-chevron,
1309
- .agentkit-activities-summary:focus-visible .agentkit-summary-chevron,
1310
- .agentkit-activities[open] .agentkit-summary-chevron {
1309
+ .agentkit-activities[data-expandable="true"]
1310
+ .agentkit-activities-summary:hover
1311
+ > .agentkit-summary-chevron,
1312
+ .agentkit-activities[data-expandable="true"]
1313
+ .agentkit-activities-summary:focus-visible
1314
+ > .agentkit-summary-chevron,
1315
+ .agentkit-activities[data-expandable="true"][open] .agentkit-summary-chevron {
1311
1316
  opacity: 1;
1312
1317
  }
1313
1318
 
1319
+ .agentkit-activities[data-expandable="false"] .agentkit-activities-summary {
1320
+ cursor: default;
1321
+ }
1322
+
1314
1323
  .agentkit-activities-static {
1315
1324
  display: grid;
1316
1325
  min-inline-size: 0;
@@ -1346,7 +1355,10 @@ body:has(> [data-agent-native-composer-popover="true"]) > .fixed.inset-0 {
1346
1355
 
1347
1356
  .agentkit-activities-list {
1348
1357
  display: grid;
1358
+ max-block-size: 15.625rem;
1349
1359
  gap: 0.5rem;
1360
+ overflow: auto;
1361
+ overscroll-behavior: contain;
1350
1362
  padding-block-start: 0.25rem;
1351
1363
  }
1352
1364
 
@@ -1384,7 +1396,9 @@ body:has(> [data-agent-native-composer-popover="true"]) > .fixed.inset-0 {
1384
1396
 
1385
1397
  @media (hover: none) {
1386
1398
  .agentkit-message-actions[data-role="user"],
1387
- .agentkit-activities-summary .agentkit-summary-chevron {
1399
+ .agentkit-activities[data-expandable="true"]
1400
+ .agentkit-activities-summary
1401
+ .agentkit-summary-chevron {
1388
1402
  opacity: 1;
1389
1403
  }
1390
1404
  }
@@ -1844,8 +1858,6 @@ button.agentkit-object {
1844
1858
  }
1845
1859
 
1846
1860
  @media (prefers-reduced-motion: reduce) {
1847
- .agentkit-activities-current[data-running="true"]
1848
- .agentkit-activities-current-label,
1849
1861
  .agentkit-activity-item[data-status="running"] .agentkit-activity-label,
1850
1862
  .agentkit-agent[data-status="working"] .agentkit-agent-name,
1851
1863
  .agentkit-reasoning[data-active="true"] .agentkit-reasoning-label {
@@ -794,13 +794,51 @@ describe("AgentKitAssistantChat host behavior", () => {
794
794
  ];
795
795
  await mount(baseProps());
796
796
 
797
+ const thinking = container.querySelector('[role="status"]');
798
+ expect(thinking?.textContent).toBe("agentChat.status.thinking");
799
+ expect(thinking?.classList.contains("agent-thinking-indicator")).toBe(true);
800
+ expect(
801
+ thinking?.querySelector(".agent-thinking-indicator__text"),
802
+ ).not.toBeNull();
797
803
  expect(chatMocks.composerProps.disabled).toBe(false);
798
804
  expect(chatMocks.composerProps.submissionDisabled).toBe(true);
805
+ expect(chatMocks.composerProps.announcePendingSubmission).toBe(false);
799
806
  expect(container.querySelector('[role="status"]')?.textContent).toBe(
800
807
  "agentChat.status.thinking",
801
808
  );
802
809
  });
803
810
 
811
+ it("does not duplicate Thinking after the run becomes active", async () => {
812
+ chatMocks.history = { isSubmissionInFlight: true };
813
+ chatMocks.thread.activeRunIds = ["run-active"];
814
+ chatMocks.thread.messages = [
815
+ {
816
+ id: "user-pending",
817
+ role: "user",
818
+ parts: [{ type: "text", text: "Summarize my inbox" }],
819
+ metadata: {},
820
+ },
821
+ ];
822
+ await mount(baseProps());
823
+
824
+ expect(container.querySelector(".agent-thinking-indicator")).toBeNull();
825
+ });
826
+
827
+ it("keeps the pending announcement when the transcript has no visible user message", async () => {
828
+ chatMocks.history = { isSubmissionInFlight: true };
829
+ chatMocks.thread.messages = [
830
+ {
831
+ id: "assistant-last",
832
+ role: "assistant",
833
+ parts: [{ type: "text", text: "Earlier response" }],
834
+ },
835
+ ];
836
+ await mount(baseProps());
837
+
838
+ expect(chatMocks.composerProps.announcePendingSubmission).toBe(true);
839
+ expect(container.querySelector('[role="status"]')).toBeNull();
840
+ });
841
+
804
842
  it("gives JS callers a migration error for the removed createAdapter prop", async () => {
805
843
  const errors: Error[] = [];
806
844
  container = document.createElement("div");
@@ -957,7 +995,6 @@ describe("AgentKitAssistantChat host behavior", () => {
957
995
  .querySelector<HTMLElement>("[contenteditable]")
958
996
  ?.getAttribute("contenteditable"),
959
997
  ).toBe("true");
960
-
961
998
  await act(async () => composer.setText("Next draft"));
962
999
  await act(async () => started.resolve({ runId: "run-latency" }));
963
1000
 
@@ -1007,6 +1044,28 @@ describe("AgentKitAssistantChat host behavior", () => {
1007
1044
  },
1008
1045
  );
1009
1046
 
1047
+ it("disables host suggestions while async submission is pending", async () => {
1048
+ const suggestion = seedFollowup();
1049
+ await mount(baseProps());
1050
+ const chips = () =>
1051
+ [...container.querySelectorAll("button")].filter(
1052
+ (button) => button.textContent === suggestion.label,
1053
+ );
1054
+ expect(chips().length).toBeGreaterThan(0);
1055
+ expect(chips().some((button) => button.disabled)).toBe(false);
1056
+
1057
+ await act(async () => {
1058
+ chatMocks.composerProps.onSubmissionPendingChange(true);
1059
+ });
1060
+
1061
+ expect(chips().every((button) => button.disabled)).toBe(true);
1062
+
1063
+ await act(async () => {
1064
+ chatMocks.composerProps.onSubmissionPendingChange(false);
1065
+ });
1066
+ expect(chips().every((button) => !button.disabled)).toBe(true);
1067
+ });
1068
+
1010
1069
  it.each([undefined, "context-chips", "after-composer", "hidden"] as const)(
1011
1070
  "preserves initial starters with the real composer (placement: %s)",
1012
1071
  async (suggestionPlacement) => {
@@ -511,6 +511,9 @@ interface AgentKitSurfaceContextValue {
511
511
  setupBouncePulse: number;
512
512
  bounceSetupCard: () => void;
513
513
  isSubmissionInFlight: boolean;
514
+ composerSubmissionPending: boolean;
515
+ onComposerSubmissionPendingChange: (pending: boolean) => void;
516
+ isThinkingVisibleInTranscript: boolean;
514
517
  contextItems: AgentChatContextItem[];
515
518
  suggestions: AgentSuggestionInput[];
516
519
  showSuggestions: boolean;
@@ -1149,6 +1152,8 @@ const AgentKitAssistantChatBody = forwardRef<
1149
1152
  const isRestoring =
1150
1153
  history?.isRestoring === true || props.threadRestore.status === "loading";
1151
1154
  const isSubmissionInFlight = history?.isSubmissionInFlight === true;
1155
+ const [composerSubmissionPending, setComposerSubmissionPending] =
1156
+ useState(false);
1152
1157
  const [authError, setAuthError] = useState<{
1153
1158
  sessionExpired?: boolean;
1154
1159
  } | null>(null);
@@ -1295,6 +1300,11 @@ const AgentKitAssistantChatBody = forwardRef<
1295
1300
  [thread.messages],
1296
1301
  );
1297
1302
  const isRunning = hasActiveAgentRuns(thread);
1303
+ const lastMessage = thread.messages.at(-1);
1304
+ const isThinkingVisibleInTranscript =
1305
+ (isRunning || isSubmissionInFlight) &&
1306
+ lastMessage?.role === "user" &&
1307
+ lastMessage.metadata?.hideUserMessage !== true;
1298
1308
  const isThreadRunning = useCallback(
1299
1309
  () => hasActiveAgentRuns(controller.getThread(threadId)),
1300
1310
  [controller, threadId],
@@ -2597,13 +2607,14 @@ const AgentKitAssistantChatBody = forwardRef<
2597
2607
  );
2598
2608
  const submitSuggestion = useCallback(
2599
2609
  (suggestion: AgentSuggestionInput) => {
2610
+ if (composerSubmissionPending) return;
2600
2611
  const handler = suggestionSubmitRef.current;
2601
2612
  if (!handler || handler.threadId !== threadId) return;
2602
2613
  void handler.submit(suggestion).catch((error) => {
2603
2614
  dispatchSetupRequiredEvent(error, props.tabId, threadId);
2604
2615
  });
2605
2616
  },
2606
- [props.tabId, threadId],
2617
+ [composerSubmissionPending, props.tabId, threadId],
2607
2618
  );
2608
2619
  const retryDeferredSubmission = useCallback(async () => {
2609
2620
  if (!deferredProviderSubmissionFailureId) return;
@@ -2783,6 +2794,9 @@ const AgentKitAssistantChatBody = forwardRef<
2783
2794
  setupBouncePulse,
2784
2795
  bounceSetupCard,
2785
2796
  isSubmissionInFlight,
2797
+ composerSubmissionPending,
2798
+ onComposerSubmissionPendingChange: setComposerSubmissionPending,
2799
+ isThinkingVisibleInTranscript,
2786
2800
  contextItems,
2787
2801
  voiceTranscriptMessages,
2788
2802
  selectionLength,
@@ -2967,7 +2981,8 @@ function AgentKitEmptyState({ threadId }: { threadId: string }) {
2967
2981
  disabled={
2968
2982
  !surface.canChat ||
2969
2983
  surface.props.composerDisabled ||
2970
- surface.props.composerSubmissionDisabled
2984
+ surface.props.composerSubmissionDisabled ||
2985
+ surface.composerSubmissionPending
2971
2986
  }
2972
2987
  onClick={() => surface.submitSuggestion(suggestion)}
2973
2988
  className="w-full rounded-xl border border-border/70 bg-card/60 px-3 py-2.5 text-left text-[13px] text-muted-foreground shadow-sm transition-colors hover:border-border hover:bg-card hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
@@ -3067,7 +3082,8 @@ function AgentKitTranscript({ children, threadId }: AgentKitRegionRenderProps) {
3067
3082
  );
3068
3083
  const lastMessage = thread.messages.at(-1);
3069
3084
  const showThinking =
3070
- (surface.isRunning || surface.isSubmissionInFlight) &&
3085
+ surface.isSubmissionInFlight &&
3086
+ !surface.isRunning &&
3071
3087
  lastMessage?.role === "user" &&
3072
3088
  lastMessage.metadata?.hideUserMessage !== true;
3073
3089
  const pendingVoiceMessages = surface.voiceTranscriptMessages.filter(
@@ -3090,7 +3106,8 @@ function AgentKitTranscript({ children, threadId }: AgentKitRegionRenderProps) {
3090
3106
  !surface.canChat ||
3091
3107
  surface.props.composerDisabled ||
3092
3108
  surface.props.composerSubmissionDisabled ||
3093
- surface.isSubmissionInFlight
3109
+ surface.isSubmissionInFlight ||
3110
+ surface.composerSubmissionPending
3094
3111
  }
3095
3112
  onSelect={surface.submitSuggestion}
3096
3113
  className="agentkit-host-suggestions"
@@ -3248,11 +3265,13 @@ function AgentKitTranscript({ children, threadId }: AgentKitRegionRenderProps) {
3248
3265
  ))}
3249
3266
  {showThinking ? (
3250
3267
  <div
3268
+ className="agent-thinking-indicator"
3251
3269
  role="status"
3252
3270
  aria-live="polite"
3253
- className="px-3 py-2 text-sm text-muted-foreground"
3254
3271
  >
3255
- {t("agentChat.status.thinking")}
3272
+ <span className="agent-thinking-indicator__text">
3273
+ {t("agentChat.status.thinking")}
3274
+ </span>
3256
3275
  </div>
3257
3276
  ) : null}
3258
3277
  {guided.questions?.length ? (
@@ -3395,6 +3414,9 @@ function AgentKitComposerSurface({
3395
3414
  isRunning,
3396
3415
  isRestoring,
3397
3416
  isSubmissionInFlight,
3417
+ composerSubmissionPending,
3418
+ onComposerSubmissionPendingChange,
3419
+ isThinkingVisibleInTranscript,
3398
3420
  hasRenderedMessages,
3399
3421
  threadRestore,
3400
3422
  suggestions,
@@ -3430,6 +3452,9 @@ function AgentKitComposerSurface({
3430
3452
  isRunning: boolean;
3431
3453
  isRestoring: boolean;
3432
3454
  isSubmissionInFlight: boolean;
3455
+ composerSubmissionPending: boolean;
3456
+ onComposerSubmissionPendingChange: (pending: boolean) => void;
3457
+ isThinkingVisibleInTranscript: boolean;
3433
3458
  hasRenderedMessages: boolean;
3434
3459
  setupBouncePulse: number;
3435
3460
  bounceSetupCard: () => void;
@@ -3675,7 +3700,8 @@ function AgentKitComposerSurface({
3675
3700
  !canChat ||
3676
3701
  props.composerDisabled ||
3677
3702
  props.composerSubmissionDisabled ||
3678
- isSubmissionInFlight
3703
+ isSubmissionInFlight ||
3704
+ composerSubmissionPending
3679
3705
  }
3680
3706
  onSelect={submitSuggestion}
3681
3707
  className="agentkit-home-suggestions"
@@ -3749,6 +3775,8 @@ function AgentKitComposerSurface({
3749
3775
  requireAgentEngine={false}
3750
3776
  onTextChange={onTextChange}
3751
3777
  onBeforeSubmit={onBeforeSubmit}
3778
+ announcePendingSubmission={!isThinkingVisibleInTranscript}
3779
+ onSubmissionPendingChange={onComposerSubmissionPendingChange}
3752
3780
  contextItems={visibleContextItems}
3753
3781
  contextMenuItems={composerContext?.menuItems}
3754
3782
  onRemoveContextItem={(key) => {
@@ -3892,7 +3920,8 @@ function AgentKitComposerSurface({
3892
3920
  !canChat ||
3893
3921
  props.composerDisabled ||
3894
3922
  props.composerSubmissionDisabled ||
3895
- isSubmissionInFlight
3923
+ isSubmissionInFlight ||
3924
+ composerSubmissionPending
3896
3925
  }
3897
3926
  onSelect={submitSuggestion}
3898
3927
  className="agentkit-home-suggestions"
@@ -4040,11 +4069,13 @@ function AgentKitTool({ value, active }: AgentKitRenderProps<AgentToolCall>) {
4040
4069
  const metadata = value.metadata ?? {};
4041
4070
  const input = asRecord(value.input) ?? {};
4042
4071
  const output =
4043
- typeof value.output === "string"
4044
- ? value.output
4045
- : value.output === undefined
4046
- ? undefined
4047
- : JSON.stringify(value.output);
4072
+ value.status === "failed" && value.error?.message
4073
+ ? value.error.message
4074
+ : typeof value.output === "string"
4075
+ ? value.output
4076
+ : value.output === undefined
4077
+ ? undefined
4078
+ : JSON.stringify(value.output);
4048
4079
  return (
4049
4080
  <ChatRunningContext.Provider
4050
4081
  value={active === true || value.status === "running"}
@@ -4058,8 +4089,8 @@ function AgentKitTool({ value, active }: AgentKitRenderProps<AgentToolCall>) {
4058
4089
  args={input}
4059
4090
  argsText={JSON.stringify(input)}
4060
4091
  result={output}
4092
+ isError={value.status === "failed"}
4061
4093
  isRunning={value.status === "running"}
4062
- outcome={value.status === "failed" ? "unknown" : undefined}
4063
4094
  structuredMeta={metadata}
4064
4095
  mcpApp={asRecord(metadata.mcpApp) as never}
4065
4096
  chatUI={asRecord(metadata.chatUI) as never}
@@ -160,6 +160,7 @@ describe("AgentPanel sibling overlay handoff", () => {
160
160
  container.remove();
161
161
  document.body.innerHTML = "";
162
162
  window.requestAnimationFrame = requestAnimationFrame;
163
+ vi.useRealTimers();
163
164
  vi.unstubAllGlobals();
164
165
  });
165
166
 
@@ -216,6 +217,7 @@ describe("AgentPanel sibling overlay handoff", () => {
216
217
 
217
218
  it("keeps All chats open after the menu restores focus", async () => {
218
219
  const focusRestorePrevented = vi.fn();
220
+ vi.useFakeTimers();
219
221
 
220
222
  await act(async () => {
221
223
  root.render(
@@ -249,8 +251,19 @@ describe("AgentPanel sibling overlay handoff", () => {
249
251
  );
250
252
  });
251
253
 
252
- await act(async () => {
253
- await new Promise<void>((resolve) => setTimeout(resolve, 0));
254
+ expect(
255
+ document.body.querySelector('[data-testid="history-content"]'),
256
+ ).toBeNull();
257
+
258
+ act(() => {
259
+ vi.advanceTimersByTime(99);
260
+ });
261
+ expect(
262
+ document.body.querySelector('[data-testid="history-content"]'),
263
+ ).toBeNull();
264
+
265
+ act(() => {
266
+ vi.advanceTimersByTime(1);
254
267
  });
255
268
 
256
269
  expect(focusRestorePrevented).toHaveBeenCalledWith(true);
@@ -261,6 +274,7 @@ describe("AgentPanel sibling overlay handoff", () => {
261
274
 
262
275
  it("opens the share popover after clicking Share in the overflow menu", async () => {
263
276
  const focusRestorePrevented = vi.fn();
277
+ vi.useFakeTimers();
264
278
 
265
279
  await act(async () => {
266
280
  root.render(
@@ -296,9 +310,19 @@ describe("AgentPanel sibling overlay handoff", () => {
296
310
  });
297
311
 
298
312
  expect(frames).toHaveLength(0);
313
+ expect(
314
+ document.body.querySelector('[data-testid="share-content"]'),
315
+ ).toBeNull();
299
316
 
300
- await act(async () => {
301
- await new Promise<void>((resolve) => setTimeout(resolve, 0));
317
+ act(() => {
318
+ vi.advanceTimersByTime(99);
319
+ });
320
+ expect(
321
+ document.body.querySelector('[data-testid="share-content"]'),
322
+ ).toBeNull();
323
+
324
+ act(() => {
325
+ vi.advanceTimersByTime(1);
302
326
  });
303
327
 
304
328
  expect(focusRestorePrevented).toHaveBeenCalledWith(true);