@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.
- package/dist/app/agentkit/react/components.d.ts +6 -3
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +98 -68
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +36 -24
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +32 -15
- 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/PromptComposer.d.ts +3 -0
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +2 -2
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +4 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +32 -25
- 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 +3 -3
- package/src/app/agentkit/react/components.interaction.spec.tsx +93 -0
- package/src/app/agentkit/react/components.spec.tsx +1 -2
- package/src/app/agentkit/react/components.tsx +185 -132
- package/src/app/agentkit/react/composer-context.spec.tsx +7 -0
- 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 +60 -1
- package/src/app/chat/AgentKitAssistantChat.tsx +45 -14
- 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/PromptComposer.tsx +7 -0
- package/src/composer/TiptapComposer.spec.ts +40 -6
- package/src/composer/TiptapComposer.tsx +89 -89
- package/src/ui/sonner.spec.ts +15 -0
- package/src/ui/sonner.tsx +1 -1
|
@@ -718,7 +718,7 @@ describe("AgentChat lifecycle", () => {
|
|
|
718
718
|
type: "activity.started" as const,
|
|
719
719
|
activity: {
|
|
720
720
|
id: "activity-1",
|
|
721
|
-
kind: "
|
|
721
|
+
kind: "model",
|
|
722
722
|
label: "Contacting model",
|
|
723
723
|
status: "running" as const,
|
|
724
724
|
},
|
|
@@ -760,7 +760,12 @@ describe("AgentChat lifecycle", () => {
|
|
|
760
760
|
expect(
|
|
761
761
|
runWorkBefore?.querySelector("[data-agentkit-current-activity]")
|
|
762
762
|
?.textContent,
|
|
763
|
-
).toBe("
|
|
763
|
+
).toBe("Thinking");
|
|
764
|
+
expect(
|
|
765
|
+
runWorkBefore?.querySelector(
|
|
766
|
+
"[data-agentkit-current-activity] .agent-running-shimmer",
|
|
767
|
+
),
|
|
768
|
+
).not.toBeNull();
|
|
764
769
|
|
|
765
770
|
const assistantMessage = {
|
|
766
771
|
id: "assistant-1",
|
|
@@ -863,12 +868,19 @@ describe("AgentChat lifecycle", () => {
|
|
|
863
868
|
const response = tree.container.querySelector(
|
|
864
869
|
'[data-message-id="assistant-1"]',
|
|
865
870
|
);
|
|
866
|
-
expect(runWorkAfter).toBe(runWorkBefore);
|
|
867
|
-
expect(runWorkAfter?.open).toBe(false);
|
|
868
871
|
expect(
|
|
869
|
-
|
|
872
|
+
response
|
|
873
|
+
?.querySelector(".agentkit-message-actions")
|
|
874
|
+
?.getAttribute("data-streaming"),
|
|
875
|
+
).toBe("true");
|
|
876
|
+
expect(runWorkAfter).not.toBeNull();
|
|
877
|
+
expect(
|
|
878
|
+
runWorkAfter?.querySelector(".agentkit-activities-label")?.textContent,
|
|
870
879
|
).toBe("Worked for 4s");
|
|
871
|
-
expect(runWorkAfter?.
|
|
880
|
+
expect(runWorkAfter?.textContent).not.toContain("Thinking");
|
|
881
|
+
expect(
|
|
882
|
+
runWorkAfter?.querySelector("[data-agentkit-current-activity]"),
|
|
883
|
+
).toBeNull();
|
|
872
884
|
expect(runWorkAfter?.querySelector('[data-status="running"]')).toBeNull();
|
|
873
885
|
expect(
|
|
874
886
|
runWorkAfter && response
|
|
@@ -921,19 +933,20 @@ describe("AgentChat lifecycle", () => {
|
|
|
921
933
|
});
|
|
922
934
|
await flush();
|
|
923
935
|
expect(
|
|
924
|
-
|
|
936
|
+
tree.container.querySelector(
|
|
937
|
+
".agentkit-activities-summary .agentkit-activities-label",
|
|
938
|
+
)?.textContent,
|
|
925
939
|
).toBe("Worked for 4s");
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
?.querySelector("
|
|
930
|
-
?.
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
expect(runWorkAfter?.open).toBe(true);
|
|
940
|
+
expect(
|
|
941
|
+
tree.container
|
|
942
|
+
.querySelector('[data-message-id="assistant-1"]')
|
|
943
|
+
?.querySelector(".agentkit-message-actions")
|
|
944
|
+
?.hasAttribute("data-streaming"),
|
|
945
|
+
).toBe(false);
|
|
946
|
+
expect(tree.container.querySelector(".agentkit-reasoning")).toBeNull();
|
|
934
947
|
});
|
|
935
948
|
|
|
936
|
-
it("keeps thoughts
|
|
949
|
+
it("keeps thoughts in active history and omits them after completion", async () => {
|
|
937
950
|
const threadId = "thread-reasoning-work";
|
|
938
951
|
const runId = "run-reasoning-work";
|
|
939
952
|
const base = (sequence: number, seconds: number = sequence) => ({
|
|
@@ -1019,10 +1032,10 @@ describe("AgentChat lifecycle", () => {
|
|
|
1019
1032
|
work.querySelector("[data-agentkit-current-activity]")?.textContent,
|
|
1020
1033
|
).toBe("Searching documentation");
|
|
1021
1034
|
expect(
|
|
1022
|
-
work
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
).
|
|
1035
|
+
work.querySelector(
|
|
1036
|
+
".agentkit-activities-summary > .agentkit-summary-chevron",
|
|
1037
|
+
),
|
|
1038
|
+
).not.toBeNull();
|
|
1026
1039
|
expect(
|
|
1027
1040
|
work
|
|
1028
1041
|
.querySelector('[data-thought="thread-reasoning-work:assistant-2:0"]')
|
|
@@ -1063,11 +1076,223 @@ describe("AgentChat lifecycle", () => {
|
|
|
1063
1076
|
).not.toBe(0);
|
|
1064
1077
|
await act(async () => work.querySelector("summary")!.click());
|
|
1065
1078
|
expect(work.open).toBe(true);
|
|
1066
|
-
expect(work.querySelectorAll("[data-thought]")).toHaveLength(
|
|
1079
|
+
expect(work.querySelectorAll("[data-thought]")).toHaveLength(0);
|
|
1080
|
+
expect(work.querySelector('[data-activity-bucket="thinking"]')).toBeNull();
|
|
1067
1081
|
await act(async () => work.querySelector("summary")!.click());
|
|
1068
1082
|
expect(work.open).toBe(false);
|
|
1069
1083
|
});
|
|
1070
1084
|
|
|
1085
|
+
it("shows localized Thinking before the first activity arrives", async () => {
|
|
1086
|
+
const threadId = "thread-no-activity-yet";
|
|
1087
|
+
const runId = "run-no-activity-yet";
|
|
1088
|
+
const thread = {
|
|
1089
|
+
...createAgentThreadState(threadId),
|
|
1090
|
+
runs: {
|
|
1091
|
+
[runId]: {
|
|
1092
|
+
id: runId,
|
|
1093
|
+
status: "running" as const,
|
|
1094
|
+
lastSequence: 0,
|
|
1095
|
+
startedAt: "2026-09-28T00:00:00.000Z",
|
|
1096
|
+
},
|
|
1097
|
+
},
|
|
1098
|
+
activeRunIds: [runId],
|
|
1099
|
+
};
|
|
1100
|
+
const observable = observableController({
|
|
1101
|
+
connection: "connected",
|
|
1102
|
+
capabilities: {},
|
|
1103
|
+
capabilitiesStatus: "ready",
|
|
1104
|
+
threads: { [threadId]: thread },
|
|
1105
|
+
revision: 0,
|
|
1106
|
+
});
|
|
1107
|
+
const tree = mount();
|
|
1108
|
+
|
|
1109
|
+
await tree.render(
|
|
1110
|
+
<AgentKitProvider
|
|
1111
|
+
controller={observable.controller}
|
|
1112
|
+
threadId={threadId}
|
|
1113
|
+
labels={{ reasoning: "Thinking in Spanish" }}
|
|
1114
|
+
>
|
|
1115
|
+
<AgentActivityGroup runId={runId} />
|
|
1116
|
+
</AgentKitProvider>,
|
|
1117
|
+
);
|
|
1118
|
+
|
|
1119
|
+
expect(
|
|
1120
|
+
tree.container.querySelectorAll("[data-agentkit-current-activity]"),
|
|
1121
|
+
).toHaveLength(1);
|
|
1122
|
+
expect(
|
|
1123
|
+
tree.container.querySelector(
|
|
1124
|
+
"[data-agentkit-current-activity] .agent-running-shimmer",
|
|
1125
|
+
)?.textContent,
|
|
1126
|
+
).toBe("Thinking in Spanish");
|
|
1127
|
+
expect(tree.container.textContent).not.toContain("Working for");
|
|
1128
|
+
const work = tree.container.querySelector<HTMLDetailsElement>(
|
|
1129
|
+
".agentkit-activities",
|
|
1130
|
+
);
|
|
1131
|
+
expect(work?.dataset.expandable).toBe("false");
|
|
1132
|
+
expect(
|
|
1133
|
+
work?.querySelector(".agentkit-activities-summary")?.textContent,
|
|
1134
|
+
).toBe("Thinking in Spanish");
|
|
1135
|
+
await tree.unmount();
|
|
1136
|
+
});
|
|
1137
|
+
|
|
1138
|
+
it("falls back to Thinking when the newest activity has completed", async () => {
|
|
1139
|
+
const threadId = "thread-completed-latest-activity";
|
|
1140
|
+
const runId = "run-completed-latest-activity";
|
|
1141
|
+
const thread = {
|
|
1142
|
+
...createAgentThreadState(threadId),
|
|
1143
|
+
events: [
|
|
1144
|
+
{
|
|
1145
|
+
id: "activity-started",
|
|
1146
|
+
threadId,
|
|
1147
|
+
runId,
|
|
1148
|
+
sequence: 1,
|
|
1149
|
+
occurredAt: "2026-09-28T00:00:01.000Z",
|
|
1150
|
+
type: "activity.started" as const,
|
|
1151
|
+
activity: {
|
|
1152
|
+
id: "read-components",
|
|
1153
|
+
kind: "read",
|
|
1154
|
+
label: "Reading components.tsx",
|
|
1155
|
+
status: "running" as const,
|
|
1156
|
+
},
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
id: "activity-completed",
|
|
1160
|
+
threadId,
|
|
1161
|
+
runId,
|
|
1162
|
+
sequence: 2,
|
|
1163
|
+
occurredAt: "2026-09-28T00:00:02.000Z",
|
|
1164
|
+
type: "activity.completed" as const,
|
|
1165
|
+
activity: {
|
|
1166
|
+
id: "read-components",
|
|
1167
|
+
kind: "read",
|
|
1168
|
+
label: "Reading components.tsx",
|
|
1169
|
+
status: "completed" as const,
|
|
1170
|
+
completedAt: "2026-09-28T00:00:02.000Z",
|
|
1171
|
+
},
|
|
1172
|
+
},
|
|
1173
|
+
],
|
|
1174
|
+
runs: {
|
|
1175
|
+
[runId]: {
|
|
1176
|
+
id: runId,
|
|
1177
|
+
status: "running" as const,
|
|
1178
|
+
lastSequence: 2,
|
|
1179
|
+
startedAt: "2026-09-28T00:00:00.000Z",
|
|
1180
|
+
},
|
|
1181
|
+
},
|
|
1182
|
+
activeRunIds: [runId],
|
|
1183
|
+
};
|
|
1184
|
+
const observable = observableController({
|
|
1185
|
+
connection: "connected",
|
|
1186
|
+
capabilities: {},
|
|
1187
|
+
capabilitiesStatus: "ready",
|
|
1188
|
+
threads: { [threadId]: thread },
|
|
1189
|
+
revision: 0,
|
|
1190
|
+
});
|
|
1191
|
+
const tree = mount();
|
|
1192
|
+
|
|
1193
|
+
await tree.render(
|
|
1194
|
+
<AgentKitProvider controller={observable.controller} threadId={threadId}>
|
|
1195
|
+
<AgentKitChat composer={false} />
|
|
1196
|
+
</AgentKitProvider>,
|
|
1197
|
+
);
|
|
1198
|
+
|
|
1199
|
+
const current = tree.container.querySelector(
|
|
1200
|
+
"[data-agentkit-current-activity]",
|
|
1201
|
+
);
|
|
1202
|
+
expect(current?.textContent).toBe("Thinking");
|
|
1203
|
+
expect(current?.querySelector(".agent-running-shimmer")).not.toBeNull();
|
|
1204
|
+
expect(
|
|
1205
|
+
tree.container.querySelector(".agentkit-activities-summary")?.textContent,
|
|
1206
|
+
).not.toContain("Reading components.tsx");
|
|
1207
|
+
await tree.unmount();
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
it("keeps bounded activity history settled while its run continues", async () => {
|
|
1211
|
+
const threadId = "thread-settled-segment";
|
|
1212
|
+
const runId = "run-settled-segment";
|
|
1213
|
+
const thread = {
|
|
1214
|
+
...createAgentThreadState(threadId),
|
|
1215
|
+
events: [
|
|
1216
|
+
{
|
|
1217
|
+
id: "activity-started",
|
|
1218
|
+
threadId,
|
|
1219
|
+
runId,
|
|
1220
|
+
sequence: 1,
|
|
1221
|
+
occurredAt: "2026-09-30T00:00:00.000Z",
|
|
1222
|
+
type: "activity.started" as const,
|
|
1223
|
+
activity: {
|
|
1224
|
+
id: "read-files",
|
|
1225
|
+
kind: "read",
|
|
1226
|
+
label: "Read files",
|
|
1227
|
+
status: "running" as const,
|
|
1228
|
+
},
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
id: "activity-completed",
|
|
1232
|
+
threadId,
|
|
1233
|
+
runId,
|
|
1234
|
+
sequence: 2,
|
|
1235
|
+
occurredAt: "2026-09-30T00:00:01.000Z",
|
|
1236
|
+
type: "activity.completed" as const,
|
|
1237
|
+
activity: {
|
|
1238
|
+
id: "read-files",
|
|
1239
|
+
kind: "read",
|
|
1240
|
+
label: "Read files",
|
|
1241
|
+
status: "completed" as const,
|
|
1242
|
+
},
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
id: "response-started",
|
|
1246
|
+
threadId,
|
|
1247
|
+
runId,
|
|
1248
|
+
sequence: 3,
|
|
1249
|
+
occurredAt: "2026-09-30T00:00:01.000Z",
|
|
1250
|
+
type: "message.completed" as const,
|
|
1251
|
+
message: {
|
|
1252
|
+
id: "assistant-response",
|
|
1253
|
+
role: "assistant" as const,
|
|
1254
|
+
status: "complete" as const,
|
|
1255
|
+
parts: [{ type: "text" as const, text: "I found the files." }],
|
|
1256
|
+
},
|
|
1257
|
+
},
|
|
1258
|
+
],
|
|
1259
|
+
runs: {
|
|
1260
|
+
[runId]: {
|
|
1261
|
+
id: runId,
|
|
1262
|
+
status: "running" as const,
|
|
1263
|
+
lastSequence: 3,
|
|
1264
|
+
startedAt: "2026-09-30T00:00:00.000Z",
|
|
1265
|
+
},
|
|
1266
|
+
},
|
|
1267
|
+
};
|
|
1268
|
+
const observable = observableController({
|
|
1269
|
+
connection: "connected",
|
|
1270
|
+
capabilities: {},
|
|
1271
|
+
capabilitiesStatus: "ready",
|
|
1272
|
+
threads: { [threadId]: thread },
|
|
1273
|
+
revision: 0,
|
|
1274
|
+
});
|
|
1275
|
+
const tree = mount();
|
|
1276
|
+
|
|
1277
|
+
await tree.render(
|
|
1278
|
+
<AgentKitProvider controller={observable.controller} threadId={threadId}>
|
|
1279
|
+
<AgentActivityGroup
|
|
1280
|
+
runId={runId}
|
|
1281
|
+
throughSequence={3}
|
|
1282
|
+
isCurrentSegment={false}
|
|
1283
|
+
/>
|
|
1284
|
+
</AgentKitProvider>,
|
|
1285
|
+
);
|
|
1286
|
+
|
|
1287
|
+
const work = tree.container.querySelector<HTMLDetailsElement>(
|
|
1288
|
+
".agentkit-activities",
|
|
1289
|
+
);
|
|
1290
|
+
expect(work?.querySelector("summary")?.textContent).toBe("Worked for 1s");
|
|
1291
|
+
expect(work?.hasAttribute("data-running")).toBe(false);
|
|
1292
|
+
expect(work?.querySelector("[data-agentkit-current-activity]")).toBeNull();
|
|
1293
|
+
await tree.unmount();
|
|
1294
|
+
});
|
|
1295
|
+
|
|
1071
1296
|
it.each(["completed", "cancelled"] as const)(
|
|
1072
1297
|
"keeps reasoning-only %s runs collapsed without empty message rows",
|
|
1073
1298
|
async (status) => {
|
|
@@ -1119,13 +1344,10 @@ describe("AgentChat lifecycle", () => {
|
|
|
1119
1344
|
);
|
|
1120
1345
|
const work = tree.container.querySelector<HTMLDetailsElement>(
|
|
1121
1346
|
".agentkit-activities",
|
|
1122
|
-
)
|
|
1123
|
-
expect(work
|
|
1124
|
-
expect(
|
|
1125
|
-
expect(
|
|
1126
|
-
expect(
|
|
1127
|
-
work.querySelector("[data-active], [data-agentkit-current-activity]"),
|
|
1128
|
-
).toBeNull();
|
|
1347
|
+
);
|
|
1348
|
+
expect(work).toBeNull();
|
|
1349
|
+
expect(tree.container.textContent).toContain("Worked for 18s");
|
|
1350
|
+
expect(tree.container.querySelector(".agentkit-reasoning")).toBeNull();
|
|
1129
1351
|
expect(tree.container.querySelector("article")).toBeNull();
|
|
1130
1352
|
},
|
|
1131
1353
|
);
|
|
@@ -1182,6 +1404,156 @@ describe("AgentChat lifecycle", () => {
|
|
|
1182
1404
|
expect(tree.container.querySelector("article")).toBeNull();
|
|
1183
1405
|
});
|
|
1184
1406
|
|
|
1407
|
+
it("keeps completed status and model history while hiding reasoning and expanding tool diagnostics", async () => {
|
|
1408
|
+
const threadId = "thread-completed-activity-history";
|
|
1409
|
+
const runId = "run-completed-activity-history";
|
|
1410
|
+
const diagnostic = {
|
|
1411
|
+
code: "slide_content_edit_failed",
|
|
1412
|
+
closestMatch: { slide: 1, text: "existing heading" },
|
|
1413
|
+
};
|
|
1414
|
+
const failedTool: AgentToolCall = {
|
|
1415
|
+
id: "tool-update-slide",
|
|
1416
|
+
name: "update-slide",
|
|
1417
|
+
status: "failed",
|
|
1418
|
+
output: diagnostic,
|
|
1419
|
+
};
|
|
1420
|
+
const thread = {
|
|
1421
|
+
...createAgentThreadState(threadId),
|
|
1422
|
+
messages: [
|
|
1423
|
+
{
|
|
1424
|
+
id: "assistant-reasoning",
|
|
1425
|
+
role: "assistant" as const,
|
|
1426
|
+
status: "complete" as const,
|
|
1427
|
+
parts: [
|
|
1428
|
+
{ type: "reasoning" as const, text: "Private reasoning text" },
|
|
1429
|
+
],
|
|
1430
|
+
},
|
|
1431
|
+
],
|
|
1432
|
+
tools: { [failedTool.id]: failedTool },
|
|
1433
|
+
events: [
|
|
1434
|
+
{
|
|
1435
|
+
id: "event-model",
|
|
1436
|
+
threadId,
|
|
1437
|
+
runId,
|
|
1438
|
+
sequence: 1,
|
|
1439
|
+
occurredAt: "2026-09-30T00:00:01.000Z",
|
|
1440
|
+
type: "activity.completed" as const,
|
|
1441
|
+
activity: {
|
|
1442
|
+
id: "activity-model",
|
|
1443
|
+
kind: "model",
|
|
1444
|
+
label: "Claude Sonnet 5",
|
|
1445
|
+
status: "completed" as const,
|
|
1446
|
+
},
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
id: "event-status",
|
|
1450
|
+
threadId,
|
|
1451
|
+
runId,
|
|
1452
|
+
sequence: 2,
|
|
1453
|
+
occurredAt: "2026-09-30T00:00:02.000Z",
|
|
1454
|
+
type: "activity.completed" as const,
|
|
1455
|
+
activity: {
|
|
1456
|
+
id: "activity-status",
|
|
1457
|
+
kind: "status",
|
|
1458
|
+
label: "Updated the active slide",
|
|
1459
|
+
status: "completed" as const,
|
|
1460
|
+
},
|
|
1461
|
+
},
|
|
1462
|
+
{
|
|
1463
|
+
id: "event-reasoning",
|
|
1464
|
+
threadId,
|
|
1465
|
+
runId,
|
|
1466
|
+
sequence: 3,
|
|
1467
|
+
occurredAt: "2026-09-30T00:00:03.000Z",
|
|
1468
|
+
type: "reasoning.delta" as const,
|
|
1469
|
+
messageId: "assistant-reasoning",
|
|
1470
|
+
text: "Private reasoning text",
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
id: "event-tool",
|
|
1474
|
+
threadId,
|
|
1475
|
+
runId,
|
|
1476
|
+
sequence: 4,
|
|
1477
|
+
occurredAt: "2026-09-30T00:00:04.000Z",
|
|
1478
|
+
type: "tool.updated" as const,
|
|
1479
|
+
toolCall: failedTool,
|
|
1480
|
+
},
|
|
1481
|
+
{
|
|
1482
|
+
id: "event-completed",
|
|
1483
|
+
threadId,
|
|
1484
|
+
runId,
|
|
1485
|
+
sequence: 5,
|
|
1486
|
+
occurredAt: "2026-09-30T00:00:05.000Z",
|
|
1487
|
+
type: "run.completed" as const,
|
|
1488
|
+
},
|
|
1489
|
+
],
|
|
1490
|
+
runs: {
|
|
1491
|
+
[runId]: {
|
|
1492
|
+
id: runId,
|
|
1493
|
+
status: "completed" as const,
|
|
1494
|
+
lastSequence: 5,
|
|
1495
|
+
startedAt: "2026-09-30T00:00:00.000Z",
|
|
1496
|
+
completedAt: "2026-09-30T00:00:05.000Z",
|
|
1497
|
+
},
|
|
1498
|
+
},
|
|
1499
|
+
};
|
|
1500
|
+
const observable = observableController({
|
|
1501
|
+
connection: "connected",
|
|
1502
|
+
capabilities: {},
|
|
1503
|
+
capabilitiesStatus: "ready",
|
|
1504
|
+
threads: { [threadId]: thread },
|
|
1505
|
+
revision: 0,
|
|
1506
|
+
});
|
|
1507
|
+
const tree = mount();
|
|
1508
|
+
|
|
1509
|
+
await tree.render(
|
|
1510
|
+
<AgentKitProvider controller={observable.controller} threadId={threadId}>
|
|
1511
|
+
<AgentActivityGroup runId={runId} />
|
|
1512
|
+
</AgentKitProvider>,
|
|
1513
|
+
);
|
|
1514
|
+
|
|
1515
|
+
const work = tree.container.querySelector<HTMLDetailsElement>(
|
|
1516
|
+
".agentkit-activities",
|
|
1517
|
+
);
|
|
1518
|
+
expect(
|
|
1519
|
+
work?.querySelector(".agentkit-activities-summary")?.textContent,
|
|
1520
|
+
).toContain("Worked");
|
|
1521
|
+
await act(async () => {
|
|
1522
|
+
work
|
|
1523
|
+
?.querySelector<HTMLElement>(".agentkit-activities-summary")
|
|
1524
|
+
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
expect(work?.querySelector('[data-activity-bucket="thinking"]')).toBeNull();
|
|
1528
|
+
const other = work?.querySelector('[data-activity-bucket="other"]');
|
|
1529
|
+
expect(other?.textContent).toContain("Claude Sonnet 5");
|
|
1530
|
+
expect(other?.textContent).toContain("Updated the active slide");
|
|
1531
|
+
expect(work?.textContent).not.toContain("Private reasoning text");
|
|
1532
|
+
|
|
1533
|
+
const failedToolRow = Array.from(
|
|
1534
|
+
work?.querySelectorAll<HTMLElement>(".agentkit-activity-item") ?? [],
|
|
1535
|
+
).find(
|
|
1536
|
+
(row) =>
|
|
1537
|
+
row.querySelector(".agentkit-activity-label")?.textContent ===
|
|
1538
|
+
"update-slide",
|
|
1539
|
+
);
|
|
1540
|
+
expect(failedToolRow?.textContent).not.toContain(
|
|
1541
|
+
"slide_content_edit_failed",
|
|
1542
|
+
);
|
|
1543
|
+
await act(async () => {
|
|
1544
|
+
failedToolRow
|
|
1545
|
+
?.querySelector<HTMLElement>(".agentkit-activity-disclosure")
|
|
1546
|
+
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
1547
|
+
});
|
|
1548
|
+
expect(
|
|
1549
|
+
failedToolRow?.querySelector(".agentkit-activity-summary")?.textContent,
|
|
1550
|
+
).toContain("slide_content_edit_failed");
|
|
1551
|
+
expect(
|
|
1552
|
+
failedToolRow?.querySelector(".agentkit-activity-summary")?.textContent,
|
|
1553
|
+
).toContain("existing heading");
|
|
1554
|
+
await tree.unmount();
|
|
1555
|
+
});
|
|
1556
|
+
|
|
1185
1557
|
it("keeps active work compact and groups expanded history by purpose", async () => {
|
|
1186
1558
|
vi.useFakeTimers();
|
|
1187
1559
|
vi.setSystemTime(new Date("2026-08-31T00:00:15.000Z"));
|
|
@@ -1292,7 +1664,7 @@ describe("AgentChat lifecycle", () => {
|
|
|
1292
1664
|
);
|
|
1293
1665
|
expect(
|
|
1294
1666
|
work?.querySelector(".agentkit-activities-summary")?.textContent,
|
|
1295
|
-
).
|
|
1667
|
+
).toBe("Reviewing results");
|
|
1296
1668
|
expect(work?.open).toBe(false);
|
|
1297
1669
|
expect(
|
|
1298
1670
|
work?.querySelector("[data-agentkit-current-activity]")?.textContent,
|
|
@@ -1303,7 +1675,7 @@ describe("AgentChat lifecycle", () => {
|
|
|
1303
1675
|
work?.querySelectorAll("[data-activity-bucket]") ?? [],
|
|
1304
1676
|
(bucket) => bucket.getAttribute("data-activity-bucket"),
|
|
1305
1677
|
),
|
|
1306
|
-
).toEqual(["
|
|
1678
|
+
).toEqual(["research", "other"]);
|
|
1307
1679
|
expect(cluster?.open).toBe(false);
|
|
1308
1680
|
expect(cluster?.querySelector("summary")?.textContent).toContain(
|
|
1309
1681
|
"Docs search×3",
|
|
@@ -1330,7 +1702,7 @@ describe("AgentChat lifecycle", () => {
|
|
|
1330
1702
|
).toHaveLength(3);
|
|
1331
1703
|
expect(
|
|
1332
1704
|
work?.querySelectorAll(
|
|
1333
|
-
'[data-activity-bucket="
|
|
1705
|
+
'[data-activity-bucket="other"] [data-status="running"]',
|
|
1334
1706
|
),
|
|
1335
1707
|
).toHaveLength(1);
|
|
1336
1708
|
|
|
@@ -1339,12 +1711,96 @@ describe("AgentChat lifecycle", () => {
|
|
|
1339
1711
|
});
|
|
1340
1712
|
expect(
|
|
1341
1713
|
work?.querySelector(".agentkit-activities-summary")?.textContent,
|
|
1342
|
-
).
|
|
1714
|
+
).toBe("Reviewing results");
|
|
1343
1715
|
} finally {
|
|
1344
1716
|
vi.useRealTimers();
|
|
1345
1717
|
}
|
|
1346
1718
|
});
|
|
1347
1719
|
|
|
1720
|
+
it("keeps the live status row mounted as activity details arrive", async () => {
|
|
1721
|
+
const threadId = "thread-live-status-row";
|
|
1722
|
+
const runId = "run-live-status-row";
|
|
1723
|
+
const thread = {
|
|
1724
|
+
...createAgentThreadState(threadId),
|
|
1725
|
+
runs: {
|
|
1726
|
+
[runId]: {
|
|
1727
|
+
id: runId,
|
|
1728
|
+
status: "running" as const,
|
|
1729
|
+
lastSequence: 0,
|
|
1730
|
+
startedAt: "2026-09-30T00:00:00.000Z",
|
|
1731
|
+
},
|
|
1732
|
+
},
|
|
1733
|
+
activeRunIds: [runId],
|
|
1734
|
+
};
|
|
1735
|
+
const observable = observableController({
|
|
1736
|
+
connection: "connected",
|
|
1737
|
+
capabilities: {},
|
|
1738
|
+
capabilitiesStatus: "ready",
|
|
1739
|
+
threads: { [threadId]: thread },
|
|
1740
|
+
revision: 0,
|
|
1741
|
+
});
|
|
1742
|
+
const tree = mount();
|
|
1743
|
+
|
|
1744
|
+
await tree.render(
|
|
1745
|
+
<AgentKitProvider controller={observable.controller} threadId={threadId}>
|
|
1746
|
+
<AgentActivityGroup runId={runId} />
|
|
1747
|
+
</AgentKitProvider>,
|
|
1748
|
+
);
|
|
1749
|
+
|
|
1750
|
+
const work = tree.container.querySelector<HTMLDetailsElement>(
|
|
1751
|
+
".agentkit-activities",
|
|
1752
|
+
);
|
|
1753
|
+
expect(work?.dataset.expandable).toBe("false");
|
|
1754
|
+
expect(
|
|
1755
|
+
work?.querySelector("[data-agentkit-current-activity]")?.textContent,
|
|
1756
|
+
).toBe("Thinking");
|
|
1757
|
+
|
|
1758
|
+
observable.update({
|
|
1759
|
+
connection: "connected",
|
|
1760
|
+
capabilities: {},
|
|
1761
|
+
capabilitiesStatus: "ready",
|
|
1762
|
+
threads: {
|
|
1763
|
+
[threadId]: {
|
|
1764
|
+
...thread,
|
|
1765
|
+
events: [
|
|
1766
|
+
{
|
|
1767
|
+
id: "event-reading-file",
|
|
1768
|
+
threadId,
|
|
1769
|
+
runId,
|
|
1770
|
+
sequence: 1,
|
|
1771
|
+
occurredAt: "2026-09-30T00:00:01.000Z",
|
|
1772
|
+
type: "activity.started",
|
|
1773
|
+
activity: {
|
|
1774
|
+
id: "activity-reading-file",
|
|
1775
|
+
kind: "read",
|
|
1776
|
+
label: "Reading a file",
|
|
1777
|
+
status: "running",
|
|
1778
|
+
},
|
|
1779
|
+
},
|
|
1780
|
+
],
|
|
1781
|
+
runs: {
|
|
1782
|
+
[runId]: {
|
|
1783
|
+
...thread.runs[runId],
|
|
1784
|
+
lastSequence: 1,
|
|
1785
|
+
},
|
|
1786
|
+
},
|
|
1787
|
+
},
|
|
1788
|
+
},
|
|
1789
|
+
revision: 1,
|
|
1790
|
+
});
|
|
1791
|
+
await flush();
|
|
1792
|
+
|
|
1793
|
+
expect(tree.container.querySelector(".agentkit-activities")).toBe(work);
|
|
1794
|
+
expect(work?.dataset.expandable).toBe("true");
|
|
1795
|
+
expect(
|
|
1796
|
+
work?.querySelector(".agentkit-activities-summary")?.textContent,
|
|
1797
|
+
).toBe("Reading a file");
|
|
1798
|
+
expect(
|
|
1799
|
+
work?.querySelectorAll("[data-agentkit-current-activity]"),
|
|
1800
|
+
).toHaveLength(1);
|
|
1801
|
+
await tree.unmount();
|
|
1802
|
+
});
|
|
1803
|
+
|
|
1348
1804
|
it("shares integration badges between current work and history without mixing providers", async () => {
|
|
1349
1805
|
const threadId = "thread-tool-sources";
|
|
1350
1806
|
const runId = "run-tool-sources";
|
|
@@ -1514,7 +1970,7 @@ describe("AgentChat lifecycle", () => {
|
|
|
1514
1970
|
await tree.unmount();
|
|
1515
1971
|
});
|
|
1516
1972
|
|
|
1517
|
-
it("keeps failed
|
|
1973
|
+
it("keeps failed tool errors inside explicitly expanded history", async () => {
|
|
1518
1974
|
const threadId = "thread-tool-failure";
|
|
1519
1975
|
const runId = "run-tool-failure";
|
|
1520
1976
|
const tools: AgentToolCall[] = [
|
|
@@ -1562,13 +2018,24 @@ describe("AgentChat lifecycle", () => {
|
|
|
1562
2018
|
<AgentKitChat composer={false} />
|
|
1563
2019
|
</AgentKitProvider>,
|
|
1564
2020
|
);
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
|
|
2021
|
+
const work = tree.container.querySelector<HTMLDetailsElement>(
|
|
2022
|
+
".agentkit-activities",
|
|
2023
|
+
);
|
|
2024
|
+
expect(tree.container.querySelector(".agentkit-run-failure")).toBeNull();
|
|
2025
|
+
expect(work?.open).toBe(false);
|
|
2026
|
+
expect(work?.querySelector(".agentkit-activity-summary")).toBeNull();
|
|
2027
|
+
await act(async () => work?.querySelector("summary")?.click());
|
|
2028
|
+
expect(work?.open).toBe(true);
|
|
2029
|
+
const failedTool = work?.querySelector(
|
|
2030
|
+
'.agentkit-activity-item[data-status="failed"]',
|
|
2031
|
+
);
|
|
2032
|
+
expect(failedTool?.textContent).not.toContain(
|
|
2033
|
+
"The file could not be saved.",
|
|
2034
|
+
);
|
|
2035
|
+
await act(async () => failedTool?.querySelector("button")?.click());
|
|
1568
2036
|
expect(
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
).toBe(false);
|
|
2037
|
+
failedTool?.querySelector(".agentkit-activity-summary")?.textContent,
|
|
2038
|
+
).toBe("The file could not be saved.");
|
|
1572
2039
|
});
|
|
1573
2040
|
|
|
1574
2041
|
it("resets disclosure state when switching threads with reused run ids", async () => {
|
|
@@ -1755,6 +2222,14 @@ describe("AgentChat lifecycle", () => {
|
|
|
1755
2222
|
...createAgentThreadState(threadId),
|
|
1756
2223
|
messages: [firstResponse, secondResponse],
|
|
1757
2224
|
events,
|
|
2225
|
+
runs: {
|
|
2226
|
+
[runId]: {
|
|
2227
|
+
id: runId,
|
|
2228
|
+
status: "running" as const,
|
|
2229
|
+
lastSequence: 6,
|
|
2230
|
+
startedAt: "2026-08-31T00:00:00.000Z",
|
|
2231
|
+
},
|
|
2232
|
+
},
|
|
1758
2233
|
};
|
|
1759
2234
|
const observable = observableController({
|
|
1760
2235
|
connection: "connected",
|
|
@@ -1794,6 +2269,7 @@ describe("AgentChat lifecycle", () => {
|
|
|
1794
2269
|
expect(work[1]?.textContent).toContain("Edited transcript model");
|
|
1795
2270
|
expect(work[1]?.textContent).not.toContain("Read framework files");
|
|
1796
2271
|
expect(work[0]?.hasAttribute("data-running")).toBe(false);
|
|
2272
|
+
expect(work[1]?.hasAttribute("data-running")).toBe(false);
|
|
1797
2273
|
expect(
|
|
1798
2274
|
work[0] && firstMessage
|
|
1799
2275
|
? work[0].compareDocumentPosition(firstMessage) &
|
|
@@ -2781,6 +3257,47 @@ describe("AgentKit subscriptions and recovery", () => {
|
|
|
2781
3257
|
}
|
|
2782
3258
|
});
|
|
2783
3259
|
|
|
3260
|
+
it("omits the message menu when no actions are available", async () => {
|
|
3261
|
+
const thread = createAgentThreadState("thread-no-request-id");
|
|
3262
|
+
thread.messages = [
|
|
3263
|
+
{
|
|
3264
|
+
id: "assistant-no-request-id",
|
|
3265
|
+
role: "assistant",
|
|
3266
|
+
parts: [{ type: "text", text: "Ready." }],
|
|
3267
|
+
},
|
|
3268
|
+
];
|
|
3269
|
+
const store = observableController({
|
|
3270
|
+
connection: "connected",
|
|
3271
|
+
capabilities: {},
|
|
3272
|
+
capabilitiesStatus: "ready",
|
|
3273
|
+
threads: { [thread.id]: thread },
|
|
3274
|
+
revision: 0,
|
|
3275
|
+
});
|
|
3276
|
+
const tree = mount();
|
|
3277
|
+
|
|
3278
|
+
try {
|
|
3279
|
+
await tree.render(
|
|
3280
|
+
<AgentKitProvider
|
|
3281
|
+
controller={store.controller}
|
|
3282
|
+
threadId="thread-no-request-id"
|
|
3283
|
+
>
|
|
3284
|
+
<AgentMessageActions
|
|
3285
|
+
threadId="thread-no-request-id"
|
|
3286
|
+
value={thread.messages[0]!}
|
|
3287
|
+
/>
|
|
3288
|
+
</AgentKitProvider>,
|
|
3289
|
+
);
|
|
3290
|
+
expect(
|
|
3291
|
+
tree.container.querySelector('button[aria-label="Message actions"]'),
|
|
3292
|
+
).toBeNull();
|
|
3293
|
+
expect(
|
|
3294
|
+
document.body.querySelector('.agentkit-message-menu[role="menu"]'),
|
|
3295
|
+
).toBeNull();
|
|
3296
|
+
} finally {
|
|
3297
|
+
await tree.unmount();
|
|
3298
|
+
}
|
|
3299
|
+
});
|
|
3300
|
+
|
|
2784
3301
|
it("uses selector equality without caching a changed selector", async () => {
|
|
2785
3302
|
const initial: AgentKitSnapshot = {
|
|
2786
3303
|
connection: "idle",
|