@agent-native/toolkit 0.198.5 → 0.198.7-nightly-20260930213124
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.
- package/dist/app/agentkit/react/components.d.ts +2 -1
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +86 -62
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +36 -24
- package/dist/app/chat/AgentKitAssistantChat.js +14 -7
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/AgentPanel.d.ts +1 -1
- package/dist/app/chat/AgentPanel.d.ts.map +1 -1
- package/dist/app/chat/AgentPanel.js +11 -38
- package/dist/app/chat/AgentPanel.js.map +1 -1
- package/dist/app/chat/AgentSidebar.d.ts.map +1 -1
- package/dist/app/chat/AgentSidebar.js +3 -11
- package/dist/app/chat/AgentSidebar.js.map +1 -1
- package/dist/app/chat/chat/tool-call-display.d.ts +2 -1
- package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-call-display.js +83 -55
- package/dist/app/chat/chat/tool-call-display.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +1 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +1 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +1 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +1 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +1 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +1 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +1 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +1 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +1 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +1 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +1 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +1 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +1 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +26 -23
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/ui/sonner.js +1 -1
- package/dist/ui/sonner.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agentkit/react/components.tsx +156 -128
- package/src/app/agentkit/react/lifecycle.spec.tsx +556 -39
- package/src/app/agentkit/react/styles.css +36 -24
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +22 -0
- package/src/app/chat/AgentKitAssistantChat.tsx +19 -9
- package/src/app/chat/AgentPanel.overlay.spec.tsx +28 -4
- package/src/app/chat/AgentPanel.tsx +51 -168
- package/src/app/chat/AgentSidebar.spec.tsx +19 -19
- package/src/app/chat/AgentSidebar.tsx +59 -94
- package/src/app/chat/chat/tool-call-display.spec.tsx +371 -15
- package/src/app/chat/chat/tool-call-display.tsx +154 -80
- package/src/app/i18n/catalogs/ar-SA.ts +1 -0
- package/src/app/i18n/catalogs/de-DE.ts +1 -0
- package/src/app/i18n/catalogs/en-US.ts +1 -0
- package/src/app/i18n/catalogs/es-ES.ts +1 -0
- package/src/app/i18n/catalogs/fr-FR.ts +1 -0
- package/src/app/i18n/catalogs/hi-IN.ts +1 -0
- package/src/app/i18n/catalogs/ja-JP.ts +1 -0
- package/src/app/i18n/catalogs/ko-KR.ts +1 -0
- package/src/app/i18n/catalogs/pt-BR.ts +1 -0
- package/src/app/i18n/catalogs/zh-CN.ts +1 -0
- package/src/app/i18n/catalogs/zh-TW.ts +1 -0
- package/src/app-shell/sidebar-overflow.spec.tsx +2 -1
- package/src/composer/PromptComposer.context.spec.tsx +28 -15
- package/src/composer/TiptapComposer.spec.ts +14 -2
- package/src/composer/TiptapComposer.tsx +77 -86
- package/src/ui/sonner.spec.ts +15 -0
- 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:
|
|
1145
|
+
display: flex;
|
|
1137
1146
|
inline-size: fit-content;
|
|
1138
1147
|
max-inline-size: 100%;
|
|
1139
|
-
|
|
1140
|
-
gap: 0.
|
|
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-
|
|
1309
|
-
.agentkit-activities-summary:
|
|
1310
|
-
|
|
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-
|
|
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,6 +794,12 @@ 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);
|
|
799
805
|
expect(chatMocks.composerProps.announcePendingSubmission).toBe(false);
|
|
@@ -802,6 +808,22 @@ describe("AgentKitAssistantChat host behavior", () => {
|
|
|
802
808
|
);
|
|
803
809
|
});
|
|
804
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
|
+
|
|
805
827
|
it("keeps the pending announcement when the transcript has no visible user message", async () => {
|
|
806
828
|
chatMocks.history = { isSubmissionInFlight: true };
|
|
807
829
|
chatMocks.thread.messages = [
|
|
@@ -3080,6 +3080,12 @@ function AgentKitTranscript({ children, threadId }: AgentKitRegionRenderProps) {
|
|
|
3080
3080
|
const threadMessageIds = new Set(
|
|
3081
3081
|
thread.messages.map((message) => message.id),
|
|
3082
3082
|
);
|
|
3083
|
+
const lastMessage = thread.messages.at(-1);
|
|
3084
|
+
const showThinking =
|
|
3085
|
+
surface.isSubmissionInFlight &&
|
|
3086
|
+
!surface.isRunning &&
|
|
3087
|
+
lastMessage?.role === "user" &&
|
|
3088
|
+
lastMessage.metadata?.hideUserMessage !== true;
|
|
3083
3089
|
const pendingVoiceMessages = surface.voiceTranscriptMessages.filter(
|
|
3084
3090
|
(message) => !threadMessageIds.has(message.id),
|
|
3085
3091
|
);
|
|
@@ -3257,13 +3263,15 @@ function AgentKitTranscript({ children, threadId }: AgentKitRegionRenderProps) {
|
|
|
3257
3263
|
threadId={threadId}
|
|
3258
3264
|
/>
|
|
3259
3265
|
))}
|
|
3260
|
-
{
|
|
3266
|
+
{showThinking ? (
|
|
3261
3267
|
<div
|
|
3268
|
+
className="agent-thinking-indicator"
|
|
3262
3269
|
role="status"
|
|
3263
3270
|
aria-live="polite"
|
|
3264
|
-
className="px-3 py-2 text-sm text-muted-foreground"
|
|
3265
3271
|
>
|
|
3266
|
-
|
|
3272
|
+
<span className="agent-thinking-indicator__text">
|
|
3273
|
+
{t("agentChat.status.thinking")}
|
|
3274
|
+
</span>
|
|
3267
3275
|
</div>
|
|
3268
3276
|
) : null}
|
|
3269
3277
|
{guided.questions?.length ? (
|
|
@@ -4061,11 +4069,13 @@ function AgentKitTool({ value, active }: AgentKitRenderProps<AgentToolCall>) {
|
|
|
4061
4069
|
const metadata = value.metadata ?? {};
|
|
4062
4070
|
const input = asRecord(value.input) ?? {};
|
|
4063
4071
|
const output =
|
|
4064
|
-
|
|
4065
|
-
? value.
|
|
4066
|
-
: value.output ===
|
|
4067
|
-
?
|
|
4068
|
-
:
|
|
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);
|
|
4069
4079
|
return (
|
|
4070
4080
|
<ChatRunningContext.Provider
|
|
4071
4081
|
value={active === true || value.status === "running"}
|
|
@@ -4079,8 +4089,8 @@ function AgentKitTool({ value, active }: AgentKitRenderProps<AgentToolCall>) {
|
|
|
4079
4089
|
args={input}
|
|
4080
4090
|
argsText={JSON.stringify(input)}
|
|
4081
4091
|
result={output}
|
|
4092
|
+
isError={value.status === "failed"}
|
|
4082
4093
|
isRunning={value.status === "running"}
|
|
4083
|
-
outcome={value.status === "failed" ? "unknown" : undefined}
|
|
4084
4094
|
structuredMeta={metadata}
|
|
4085
4095
|
mcpApp={asRecord(metadata.mcpApp) as never}
|
|
4086
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
|
-
|
|
253
|
-
|
|
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
|
-
|
|
301
|
-
|
|
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);
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { getBrowserTabId } from "@agent-native/core/client/hooks";
|
|
2
|
+
import { buildSettingsRoute } from "@agent-native/core/navigation";
|
|
3
|
+
import {
|
|
4
|
+
isSettingsSectionId,
|
|
5
|
+
SETTINGS_SECTION_ALIASES,
|
|
6
|
+
} from "@agent-native/core/navigation";
|
|
2
7
|
import type { AgentRun } from "@agent-native/core/progress";
|
|
8
|
+
import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
|
|
3
9
|
import { Tooltip as DesignSystemTooltip } from "@agent-native/toolkit/design-system";
|
|
4
10
|
import {
|
|
5
11
|
DropdownMenu,
|
|
@@ -36,30 +42,23 @@ import React, {
|
|
|
36
42
|
Suspense,
|
|
37
43
|
startTransition,
|
|
38
44
|
} from "react";
|
|
45
|
+
import { useLocation, useNavigate } from "react-router";
|
|
39
46
|
|
|
40
47
|
import { resolveFeedbackUrl } from "../feedback/FeedbackButton.js";
|
|
41
48
|
import { ErrorReportActions, FeedbackButton } from "../feedback/index.js";
|
|
42
49
|
import { RunsTrayMenuItem } from "../progress/index.js";
|
|
43
50
|
import { ShareButton } from "../sharing/index.js";
|
|
44
|
-
import { ThinkingDisplayProvider } from "./thinking-display.js";
|
|
45
|
-
const loadMultiTabAssistantChat = () =>
|
|
46
|
-
import("./MultiTabAssistantChat.js").then((m) => ({
|
|
47
|
-
default: m.MultiTabAssistantChat,
|
|
48
|
-
}));
|
|
49
|
-
const MultiTabAssistantChatLazy = lazy(loadMultiTabAssistantChat);
|
|
50
|
-
import { buildSettingsRoute } from "@agent-native/core/navigation";
|
|
51
|
-
import {
|
|
52
|
-
isSettingsSectionId,
|
|
53
|
-
SETTINGS_SECTION_ALIASES,
|
|
54
|
-
} from "@agent-native/core/navigation";
|
|
55
|
-
import { withBuilderUtmTrackingParams } from "@agent-native/core/shared/builder-link-tracking";
|
|
56
|
-
import { useLocation, useNavigate } from "react-router";
|
|
57
|
-
|
|
58
51
|
import {
|
|
59
52
|
AGENT_PANEL_OPEN_SETTINGS_EVENT,
|
|
60
53
|
AGENT_PANEL_SET_MODE_EVENT,
|
|
61
54
|
} from "./agent-sidebar-events.js";
|
|
62
55
|
import type { AgentChatSurfaceKind } from "./chat/surface-types.js";
|
|
56
|
+
import {
|
|
57
|
+
MultiTabAssistantChat,
|
|
58
|
+
type MultiTabAssistantChatHeaderProps,
|
|
59
|
+
type MultiTabAssistantChatProps,
|
|
60
|
+
} from "./MultiTabAssistantChat.js";
|
|
61
|
+
import { ThinkingDisplayProvider } from "./thinking-display.js";
|
|
63
62
|
export {
|
|
64
63
|
shouldHandleAgentPanelChatShortcut,
|
|
65
64
|
shouldHandleAgentSidebarToggle,
|
|
@@ -99,11 +98,6 @@ import {
|
|
|
99
98
|
} from "./agent-sidebar-url-sync.js";
|
|
100
99
|
import type { AssistantChatProps } from "./chat/surface-types.js";
|
|
101
100
|
import { assistantUiRecoverableRenderErrorKind } from "./composer/assistant-ui-recovery.js";
|
|
102
|
-
import type {
|
|
103
|
-
MultiTabAssistantChatHeaderProps,
|
|
104
|
-
MultiTabAssistantChatProps,
|
|
105
|
-
} from "./MultiTabAssistantChat.js";
|
|
106
|
-
|
|
107
101
|
function parentFrameTargetOrigin(): string {
|
|
108
102
|
return getFramePostMessageTargetOrigin() ?? window.location.origin;
|
|
109
103
|
}
|
|
@@ -293,6 +287,7 @@ const AGENT_PANEL_CONTROL_STYLE = {
|
|
|
293
287
|
lineHeight: 1,
|
|
294
288
|
} satisfies React.CSSProperties;
|
|
295
289
|
const ACTIVATE_KEYS = new Set(["Enter", " "]);
|
|
290
|
+
const AGENT_PANEL_MENU_EXIT_DURATION_MS = 100;
|
|
296
291
|
type AgentPanelOverlayOpenTiming = "animation-frame" | "timeout";
|
|
297
292
|
|
|
298
293
|
export function deferAgentPanelOverlayOpen(
|
|
@@ -304,7 +299,7 @@ export function deferAgentPanelOverlayOpen(
|
|
|
304
299
|
event.preventDefault();
|
|
305
300
|
closeMenu();
|
|
306
301
|
if (timing === "timeout") {
|
|
307
|
-
setTimeout(openOverlay,
|
|
302
|
+
setTimeout(openOverlay, AGENT_PANEL_MENU_EXIT_DURATION_MS);
|
|
308
303
|
return;
|
|
309
304
|
}
|
|
310
305
|
if (
|
|
@@ -379,96 +374,6 @@ function IconTooltip({
|
|
|
379
374
|
);
|
|
380
375
|
}
|
|
381
376
|
|
|
382
|
-
type ChatHeaderRenderer = (
|
|
383
|
-
props: MultiTabAssistantChatHeaderProps,
|
|
384
|
-
) => React.ReactNode;
|
|
385
|
-
|
|
386
|
-
function ChatLoadingSkeleton({
|
|
387
|
-
renderHeader,
|
|
388
|
-
centerComposerWhenEmpty = false,
|
|
389
|
-
composerSlot,
|
|
390
|
-
composerAreaClassName,
|
|
391
|
-
composerLayoutVariant = "default",
|
|
392
|
-
}: {
|
|
393
|
-
renderHeader?: ChatHeaderRenderer;
|
|
394
|
-
centerComposerWhenEmpty?: boolean;
|
|
395
|
-
composerSlot?: React.ReactNode;
|
|
396
|
-
composerAreaClassName?: string;
|
|
397
|
-
composerLayoutVariant?: AssistantChatProps["composerLayoutVariant"];
|
|
398
|
-
}) {
|
|
399
|
-
const t = useT();
|
|
400
|
-
const noop = useCallback(() => {}, []);
|
|
401
|
-
const noopStr = useCallback((_id: string) => {}, []);
|
|
402
|
-
const stubProps: MultiTabAssistantChatHeaderProps = {
|
|
403
|
-
tabs: [],
|
|
404
|
-
activeTabId: "",
|
|
405
|
-
activeTabMessageCount: 0,
|
|
406
|
-
setActiveTabId: noopStr,
|
|
407
|
-
addTab: noop,
|
|
408
|
-
closeTab: noopStr,
|
|
409
|
-
closeOtherTabs: noopStr,
|
|
410
|
-
closeAllTabs: noop,
|
|
411
|
-
clearActiveTab: noop,
|
|
412
|
-
showHistory: false,
|
|
413
|
-
tabCount: 0,
|
|
414
|
-
toggleHistory: noop,
|
|
415
|
-
};
|
|
416
|
-
if (centerComposerWhenEmpty) {
|
|
417
|
-
return (
|
|
418
|
-
<div className="flex flex-col flex-1 min-h-0">
|
|
419
|
-
{renderHeader ? renderHeader(stubProps) : null}
|
|
420
|
-
<div
|
|
421
|
-
data-agent-empty-state="centered"
|
|
422
|
-
className="relative flex flex-1 flex-col h-full min-h-0 text-foreground"
|
|
423
|
-
>
|
|
424
|
-
<div className="agent-chat-scroll flex-1 overflow-y-auto overflow-x-hidden min-h-0">
|
|
425
|
-
<div className="agent-empty-state sr-only" aria-busy="true">
|
|
426
|
-
{t("agentChat.empty.loadingChat")}
|
|
427
|
-
</div>
|
|
428
|
-
</div>
|
|
429
|
-
{composerSlot}
|
|
430
|
-
<div className="agent-composer-stack">
|
|
431
|
-
<div
|
|
432
|
-
className={cn(
|
|
433
|
-
"agent-composer-area shrink-0 px-3 py-2",
|
|
434
|
-
composerLayoutVariant !== "default" &&
|
|
435
|
-
`agent-composer-area--${composerLayoutVariant}`,
|
|
436
|
-
composerAreaClassName,
|
|
437
|
-
)}
|
|
438
|
-
>
|
|
439
|
-
<div
|
|
440
|
-
className={cn(
|
|
441
|
-
"agent-composer-root flex flex-col rounded-lg border border-input bg-muted/45 transition-colors",
|
|
442
|
-
composerLayoutVariant !== "default" &&
|
|
443
|
-
`agent-composer-root--${composerLayoutVariant}`,
|
|
444
|
-
)}
|
|
445
|
-
>
|
|
446
|
-
<div className="px-3 pt-3">
|
|
447
|
-
<div className="h-5 w-3/5 rounded bg-muted animate-pulse motion-reduce:animate-none" />
|
|
448
|
-
</div>
|
|
449
|
-
<div className="mt-auto flex items-center gap-2 px-3 py-2">
|
|
450
|
-
<div className="h-5 w-5 rounded bg-muted animate-pulse motion-reduce:animate-none" />
|
|
451
|
-
<div className="ml-auto h-4 w-28 rounded bg-muted animate-pulse motion-reduce:animate-none" />
|
|
452
|
-
<div className="h-7 w-7 rounded-md bg-muted animate-pulse motion-reduce:animate-none" />
|
|
453
|
-
</div>
|
|
454
|
-
</div>
|
|
455
|
-
</div>
|
|
456
|
-
</div>
|
|
457
|
-
</div>
|
|
458
|
-
</div>
|
|
459
|
-
);
|
|
460
|
-
}
|
|
461
|
-
return (
|
|
462
|
-
<div className="flex flex-col flex-1 min-h-0">
|
|
463
|
-
{renderHeader ? renderHeader(stubProps) : null}
|
|
464
|
-
{/* Composer-shaped placeholder keeps layout stable during chunk load */}
|
|
465
|
-
<div className="mt-auto shrink-0 border-t border-border p-3">
|
|
466
|
-
<div className="h-16 rounded-xl bg-muted/40 animate-pulse motion-reduce:animate-none" />
|
|
467
|
-
</div>
|
|
468
|
-
</div>
|
|
469
|
-
);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
377
|
export function getAgentPanelChatTabGroups(
|
|
473
378
|
tabs: MultiTabAssistantChatHeaderProps["tabs"],
|
|
474
379
|
activeTabId: string,
|
|
@@ -2544,13 +2449,9 @@ function AgentPanelInner({
|
|
|
2544
2449
|
</Suspense>
|
|
2545
2450
|
)}
|
|
2546
2451
|
|
|
2547
|
-
{/* Chat view
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
The wrapper collapses (no flex-1) when another mode is active
|
|
2551
|
-
so it only takes the height of its header.
|
|
2552
|
-
The Suspense boundary renders the header chrome immediately while
|
|
2553
|
-
the lazy assistant-ui chunk loads in the background. */}
|
|
2452
|
+
{/* Chat view stays mounted to preserve state. MultiTabAssistantChat
|
|
2453
|
+
owns its transcript loading state; mounting it here keeps the
|
|
2454
|
+
interactive composer available while that data loads. */}
|
|
2554
2455
|
<div
|
|
2555
2456
|
className={cn(
|
|
2556
2457
|
"flex flex-col min-h-0",
|
|
@@ -2558,58 +2459,40 @@ function AgentPanelInner({
|
|
|
2558
2459
|
)}
|
|
2559
2460
|
>
|
|
2560
2461
|
{mounted && (
|
|
2561
|
-
<
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
assistantChatProps.composerLayoutVariant
|
|
2574
|
-
}
|
|
2575
|
-
/>
|
|
2462
|
+
<MultiTabAssistantChat
|
|
2463
|
+
{...assistantChatProps}
|
|
2464
|
+
threadContentSlot={assistantChatProps.threadContentSlot}
|
|
2465
|
+
agentChatSurface={effectiveAgentChatSurface}
|
|
2466
|
+
apiUrl={apiUrl}
|
|
2467
|
+
showHeader={false}
|
|
2468
|
+
renderHeader={showHeader ? renderChatHeader : undefined}
|
|
2469
|
+
showTabBar={showTabBar}
|
|
2470
|
+
renderOverlay={
|
|
2471
|
+
showPageHeader && !showHeader
|
|
2472
|
+
? renderPageChatOverlay
|
|
2473
|
+
: undefined
|
|
2576
2474
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
suggestionPlacement={
|
|
2599
|
-
assistantChatProps.suggestionPlacement ?? "context-chips"
|
|
2600
|
-
}
|
|
2601
|
-
onSwitchToCli={() => switchMode("cli")}
|
|
2602
|
-
execMode={execMode}
|
|
2603
|
-
onExecModeChange={switchExecMode}
|
|
2604
|
-
storageKey={storageKey}
|
|
2605
|
-
restoreActiveThread={restoreActiveThread}
|
|
2606
|
-
scope={scope}
|
|
2607
|
-
isolateHistoryByScope={isolateHistoryByScope}
|
|
2608
|
-
showScopeBadge={showScopeBadge}
|
|
2609
|
-
browserTabId={browserTabId}
|
|
2610
|
-
threadUrlSync={threadUrlSync}
|
|
2611
|
-
/>
|
|
2612
|
-
</Suspense>
|
|
2475
|
+
contentHidden={mode !== "chat"}
|
|
2476
|
+
emptyStateText={emptyStateText}
|
|
2477
|
+
emptyStateAddon={emptyStateAddon}
|
|
2478
|
+
emptyStateFooter={emptyStateFooter}
|
|
2479
|
+
onMessageCountChange={onMessageCountChange}
|
|
2480
|
+
suggestions={suggestions}
|
|
2481
|
+
dynamicSuggestions={dynamicSuggestions}
|
|
2482
|
+
suggestionPlacement={
|
|
2483
|
+
assistantChatProps.suggestionPlacement ?? "context-chips"
|
|
2484
|
+
}
|
|
2485
|
+
onSwitchToCli={() => switchMode("cli")}
|
|
2486
|
+
execMode={execMode}
|
|
2487
|
+
onExecModeChange={switchExecMode}
|
|
2488
|
+
storageKey={storageKey}
|
|
2489
|
+
restoreActiveThread={restoreActiveThread}
|
|
2490
|
+
scope={scope}
|
|
2491
|
+
isolateHistoryByScope={isolateHistoryByScope}
|
|
2492
|
+
showScopeBadge={showScopeBadge}
|
|
2493
|
+
browserTabId={browserTabId}
|
|
2494
|
+
threadUrlSync={threadUrlSync}
|
|
2495
|
+
/>
|
|
2613
2496
|
)}
|
|
2614
2497
|
</div>
|
|
2615
2498
|
|
|
@@ -12,7 +12,11 @@ const mockHostedHarness = vi.hoisted(() => ({
|
|
|
12
12
|
}));
|
|
13
13
|
|
|
14
14
|
vi.mock("./AgentSidebarPanel.js", () => ({
|
|
15
|
-
AgentSidebarPanel: () =>
|
|
15
|
+
AgentSidebarPanel: () => (
|
|
16
|
+
<div data-agent-sidebar-panel-loaded="true">
|
|
17
|
+
<textarea aria-label="Chat composer" />
|
|
18
|
+
</div>
|
|
19
|
+
),
|
|
16
20
|
}));
|
|
17
21
|
vi.mock("./agent-sidebar-url-sync.js", () => ({
|
|
18
22
|
ScreenRefreshBoundary: ({
|
|
@@ -146,7 +150,7 @@ beforeEach(() => {
|
|
|
146
150
|
});
|
|
147
151
|
});
|
|
148
152
|
|
|
149
|
-
describe("AgentSidebar
|
|
153
|
+
describe("AgentSidebar panel", () => {
|
|
150
154
|
it("pauses screen refresh until the panel is active", () => {
|
|
151
155
|
renderSidebar(false);
|
|
152
156
|
|
|
@@ -229,7 +233,7 @@ describe("AgentSidebar lazy panel boundary", () => {
|
|
|
229
233
|
).toBeTruthy();
|
|
230
234
|
});
|
|
231
235
|
|
|
232
|
-
it("
|
|
236
|
+
it("renders an interactive composer without a loading skeleton", () => {
|
|
233
237
|
localStorage.setItem("agent-native-sidebar-open", "true");
|
|
234
238
|
renderSidebar(true);
|
|
235
239
|
|
|
@@ -238,10 +242,11 @@ describe("AgentSidebar lazy panel boundary", () => {
|
|
|
238
242
|
).toBeTruthy();
|
|
239
243
|
expect(
|
|
240
244
|
container?.querySelector("[data-agent-sidebar-panel-skeleton='true']"),
|
|
241
|
-
).toBeTruthy();
|
|
242
|
-
expect(
|
|
243
|
-
container?.querySelector("[data-agent-sidebar-panel-loaded='true']"),
|
|
244
245
|
).toBeNull();
|
|
246
|
+
const composer = container?.querySelector<HTMLTextAreaElement>(
|
|
247
|
+
"textarea[aria-label='Chat composer']",
|
|
248
|
+
);
|
|
249
|
+
expect(composer).toBeTruthy();
|
|
245
250
|
const panel = container?.querySelector<HTMLElement>(
|
|
246
251
|
".agent-sidebar-panel[data-agent-sidebar-layout='desktop']",
|
|
247
252
|
);
|
|
@@ -249,16 +254,13 @@ describe("AgentSidebar lazy panel boundary", () => {
|
|
|
249
254
|
"var(--agent-kit-nav-surface)",
|
|
250
255
|
);
|
|
251
256
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
expect(
|
|
257
|
-
container?.querySelector("[data-agent-sidebar-panel-loaded='true']"),
|
|
258
|
-
).toBeTruthy();
|
|
257
|
+
expect(composer?.isConnected).toBe(true);
|
|
258
|
+
expect(composer?.disabled).toBe(false);
|
|
259
|
+
composer!.value = "hello";
|
|
260
|
+
expect(composer?.value).toBe("hello");
|
|
259
261
|
});
|
|
260
262
|
|
|
261
|
-
it("opens from the global shortcut
|
|
263
|
+
it("opens from the global shortcut with the composer available", async () => {
|
|
262
264
|
renderSidebar(false);
|
|
263
265
|
await act(async () => {});
|
|
264
266
|
|
|
@@ -278,14 +280,12 @@ describe("AgentSidebar lazy panel boundary", () => {
|
|
|
278
280
|
".agent-sidebar-panel[data-agent-sidebar-state='open']",
|
|
279
281
|
),
|
|
280
282
|
).toBeTruthy();
|
|
281
|
-
|
|
282
|
-
await act(async () => {
|
|
283
|
-
await Promise.resolve();
|
|
284
|
-
});
|
|
285
|
-
|
|
286
283
|
expect(
|
|
287
284
|
container?.querySelector("[data-agent-sidebar-panel-loaded='true']"),
|
|
288
285
|
).toBeTruthy();
|
|
286
|
+
expect(
|
|
287
|
+
container?.querySelector("textarea[aria-label='Chat composer']"),
|
|
288
|
+
).toBeTruthy();
|
|
289
289
|
});
|
|
290
290
|
|
|
291
291
|
it("leaves Cmd+I available to the app when the chat shortcut is disabled", async () => {
|