@agent-native/toolkit 0.204.0 → 0.204.1-nightly-20261008065100
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/agent-native.eject.json +2 -0
- package/dist/app/agent-page/AgentJobsTab.d.ts.map +1 -1
- package/dist/app/agent-page/AgentJobsTab.js +4 -2
- package/dist/app/agent-page/AgentJobsTab.js.map +1 -1
- package/dist/app/agent-page/AutomationDetailsDialog.d.ts +2 -1
- package/dist/app/agent-page/AutomationDetailsDialog.d.ts.map +1 -1
- package/dist/app/agent-page/AutomationDetailsDialog.js +8 -4
- package/dist/app/agent-page/AutomationDetailsDialog.js.map +1 -1
- package/dist/app/agent-page/ScheduledTriggerNotice.d.ts.map +1 -1
- package/dist/app/agent-page/ScheduledTriggerNotice.js +41 -19
- package/dist/app/agent-page/ScheduledTriggerNotice.js.map +1 -1
- package/dist/app/agent-page/use-jobs.d.ts +1 -1
- package/dist/app/agent-page/use-jobs.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +124 -45
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/agentkit/react/context.d.ts +22 -1
- package/dist/app/agentkit/react/context.d.ts.map +1 -1
- package/dist/app/agentkit/react/context.js +14 -1
- package/dist/app/agentkit/react/context.js.map +1 -1
- package/dist/app/agentkit/react/root.d.ts +3 -2
- package/dist/app/agentkit/react/root.d.ts.map +1 -1
- package/dist/app/agentkit/react/root.js +2 -2
- package/dist/app/agentkit/react/root.js.map +1 -1
- package/dist/app/agentkit/react/styles.css +32 -2
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +74 -7
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/AgentPanel.js +1 -1
- package/dist/app/chat/AgentPanel.js.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.js +10 -9
- package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
- package/dist/app/chat/RunStuckBanner.d.ts +8 -1
- package/dist/app/chat/RunStuckBanner.d.ts.map +1 -1
- package/dist/app/chat/RunStuckBanner.js +68 -6
- package/dist/app/chat/RunStuckBanner.js.map +1 -1
- package/dist/app/chat/chat/run-recovery.d.ts +4 -2
- package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
- package/dist/app/chat/chat/run-recovery.js +3 -3
- package/dist/app/chat/chat/run-recovery.js.map +1 -1
- package/dist/app/chat/chat/surface-types.d.ts +1 -0
- package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
- package/dist/app/chat/composer/use-mention-search.d.ts +1 -0
- package/dist/app/chat/composer/use-mention-search.d.ts.map +1 -1
- package/dist/app/chat/fallback-chat-title.d.ts +2 -0
- package/dist/app/chat/fallback-chat-title.d.ts.map +1 -0
- package/dist/app/chat/fallback-chat-title.js +11 -0
- package/dist/app/chat/fallback-chat-title.js.map +1 -0
- package/dist/app/chat/feedback-report.d.ts +12 -0
- package/dist/app/chat/feedback-report.d.ts.map +1 -0
- package/dist/app/chat/feedback-report.js +21 -0
- package/dist/app/chat/feedback-report.js.map +1 -0
- package/dist/app/chat/reconcile-settled-run.d.ts +15 -0
- package/dist/app/chat/reconcile-settled-run.d.ts.map +1 -0
- package/dist/app/chat/reconcile-settled-run.js +41 -0
- package/dist/app/chat/reconcile-settled-run.js.map +1 -0
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +9 -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 +9 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +9 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -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 +9 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/providers/AppProviders.d.ts.map +1 -1
- package/dist/app/providers/AppProviders.js +7 -1
- package/dist/app/providers/AppProviders.js.map +1 -1
- package/dist/app/settings/shell/pages/audit.d.ts.map +1 -1
- package/dist/app/settings/shell/pages/audit.js +11 -2
- package/dist/app/settings/shell/pages/audit.js.map +1 -1
- package/dist/app/shared/AppShellSkeleton.d.ts.map +1 -1
- package/dist/app/shared/AppShellSkeleton.js +4 -0
- package/dist/app/shared/AppShellSkeleton.js.map +1 -1
- package/dist/composer/ComposerContextMenu.d.ts +14 -1
- package/dist/composer/ComposerContextMenu.d.ts.map +1 -1
- package/dist/composer/ComposerContextMenu.js +65 -19
- package/dist/composer/ComposerContextMenu.js.map +1 -1
- package/dist/composer/MentionPopover.d.ts.map +1 -1
- package/dist/composer/MentionPopover.js +3 -3
- package/dist/composer/MentionPopover.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts +1 -1
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.d.ts +2 -2
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +92 -36
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/composer/use-mention-search.d.ts +1 -0
- package/dist/composer/use-mention-search.d.ts.map +1 -1
- package/dist/composer/use-mention-search.js +8 -1
- package/dist/composer/use-mention-search.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agent-page/AgentJobsTab.blocked.spec.tsx +43 -0
- package/src/app/agent-page/AgentJobsTab.tsx +14 -5
- package/src/app/agent-page/AutomationDetailsDialog.tsx +22 -8
- package/src/app/agent-page/ScheduledTriggerNotice.spec.tsx +45 -3
- package/src/app/agent-page/ScheduledTriggerNotice.tsx +52 -31
- package/src/app/agent-page/use-jobs.ts +1 -1
- package/src/app/agentkit/react/components.interaction.spec.tsx +311 -1
- package/src/app/agentkit/react/components.spec.tsx +106 -2
- package/src/app/agentkit/react/components.tsx +217 -80
- package/src/app/agentkit/react/context.tsx +36 -0
- package/src/app/agentkit/react/root.tsx +4 -0
- package/src/app/agentkit/react/styles.css +32 -2
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +140 -18
- package/src/app/chat/AgentKitAssistantChat.tsx +123 -7
- package/src/app/chat/AgentPanel.header.spec.ts +43 -7
- package/src/app/chat/AgentPanel.tsx +1 -1
- package/src/app/chat/MultiTabAssistantChat.spec.tsx +34 -0
- package/src/app/chat/MultiTabAssistantChat.tsx +10 -9
- package/src/app/chat/RunStuckBanner.spec.tsx +258 -17
- package/src/app/chat/RunStuckBanner.tsx +107 -5
- package/src/app/chat/chat/run-recovery.tsx +10 -2
- package/src/app/chat/chat/surface-types.ts +1 -0
- package/src/app/chat/fallback-chat-title.ts +10 -0
- package/src/app/chat/feedback-report.spec.ts +45 -0
- package/src/app/chat/feedback-report.ts +27 -0
- package/src/app/chat/reconcile-settled-run.spec.ts +112 -0
- package/src/app/chat/reconcile-settled-run.ts +57 -0
- package/src/app/i18n/catalogs/ar-SA.ts +12 -0
- package/src/app/i18n/catalogs/de-DE.ts +12 -0
- package/src/app/i18n/catalogs/en-US.ts +12 -0
- package/src/app/i18n/catalogs/es-ES.ts +12 -0
- package/src/app/i18n/catalogs/fr-FR.ts +12 -0
- package/src/app/i18n/catalogs/hi-IN.ts +12 -0
- package/src/app/i18n/catalogs/ja-JP.ts +12 -0
- package/src/app/i18n/catalogs/ko-KR.ts +12 -0
- package/src/app/i18n/catalogs/pt-BR.ts +12 -0
- package/src/app/i18n/catalogs/zh-CN.ts +10 -0
- package/src/app/i18n/catalogs/zh-TW.ts +10 -0
- package/src/app/providers/AppProviders.spec.tsx +29 -0
- package/src/app/providers/AppProviders.tsx +13 -0
- package/src/app/settings/shell/pages/audit.spec.tsx +30 -0
- package/src/app/settings/shell/pages/audit.tsx +12 -1
- package/src/app/shared/AppShellSkeleton.tsx +4 -0
- package/src/composer/ComposerContextMenu.tsx +94 -22
- package/src/composer/ComposerPlusMenu.parity.spec.tsx +218 -233
- package/src/composer/MentionPopover.tsx +12 -3
- package/src/composer/PromptComposer.context.spec.tsx +527 -195
- package/src/composer/PromptComposer.tsx +1 -1
- package/src/composer/TiptapComposer.tsx +105 -37
- package/src/composer/use-mention-search.ts +8 -1
|
@@ -28,7 +28,17 @@ vi.mock("../../../design-system/index.js", async (importOriginal) => {
|
|
|
28
28
|
"div",
|
|
29
29
|
{ className, onClick: () => onOpenChange?.(!open) },
|
|
30
30
|
trigger,
|
|
31
|
-
open
|
|
31
|
+
// Clicks inside an open popover never toggle it, as in the real one.
|
|
32
|
+
open
|
|
33
|
+
? createElement(
|
|
34
|
+
"div",
|
|
35
|
+
{
|
|
36
|
+
onClick: (event: { stopPropagation: () => void }) =>
|
|
37
|
+
event.stopPropagation(),
|
|
38
|
+
},
|
|
39
|
+
children,
|
|
40
|
+
)
|
|
41
|
+
: null,
|
|
32
42
|
),
|
|
33
43
|
};
|
|
34
44
|
});
|
|
@@ -719,6 +729,103 @@ describe("AgentKitChat interactions", () => {
|
|
|
719
729
|
}
|
|
720
730
|
});
|
|
721
731
|
|
|
732
|
+
it.each([
|
|
733
|
+
["resumes the stopped run's turn", true],
|
|
734
|
+
["says so when the run can no longer be continued", false],
|
|
735
|
+
])("Continue on a stopped run %s", async (_, accepted) => {
|
|
736
|
+
const continueRun = vi.fn(
|
|
737
|
+
async (
|
|
738
|
+
_input: Parameters<NonNullable<AgentTransport["continueRun"]>>[0],
|
|
739
|
+
) => {
|
|
740
|
+
if (!accepted) throw new Error("This turn can no longer be continued.");
|
|
741
|
+
return { runId: "run-continued" };
|
|
742
|
+
},
|
|
743
|
+
);
|
|
744
|
+
const transport: AgentTransport = {
|
|
745
|
+
async startRun() {
|
|
746
|
+
return { runId: "run-crashed" };
|
|
747
|
+
},
|
|
748
|
+
async *subscribeToRun(input) {
|
|
749
|
+
if (input.runId !== "run-crashed") return;
|
|
750
|
+
const base = {
|
|
751
|
+
threadId: "thread-continue",
|
|
752
|
+
runId: "run-crashed",
|
|
753
|
+
occurredAt: "2026-10-05T00:00:00.000Z",
|
|
754
|
+
};
|
|
755
|
+
yield { ...base, id: "e1", sequence: 1, type: "run.started" };
|
|
756
|
+
yield {
|
|
757
|
+
...base,
|
|
758
|
+
id: "e2",
|
|
759
|
+
sequence: 2,
|
|
760
|
+
type: "run.failed",
|
|
761
|
+
error: {
|
|
762
|
+
code: "stale_run",
|
|
763
|
+
message: "The agent stopped before it could finish.",
|
|
764
|
+
retryable: true,
|
|
765
|
+
},
|
|
766
|
+
};
|
|
767
|
+
},
|
|
768
|
+
continueRun,
|
|
769
|
+
async cancelRun() {},
|
|
770
|
+
};
|
|
771
|
+
const client = new AgentKitClient({ transport });
|
|
772
|
+
const run = await client.sendMessage({
|
|
773
|
+
threadId: "thread-continue",
|
|
774
|
+
text: "Bill Ana and email her the invoice",
|
|
775
|
+
});
|
|
776
|
+
await run.completed.catch(() => undefined);
|
|
777
|
+
const container = document.createElement("div");
|
|
778
|
+
document.body.appendChild(container);
|
|
779
|
+
const root = createRoot(container);
|
|
780
|
+
const actEnvironment = globalThis as typeof globalThis & {
|
|
781
|
+
IS_REACT_ACT_ENVIRONMENT?: boolean;
|
|
782
|
+
};
|
|
783
|
+
const previousActEnvironment = actEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
784
|
+
actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
|
|
785
|
+
const continueButton = () =>
|
|
786
|
+
[
|
|
787
|
+
...container.querySelectorAll<HTMLButtonElement>(
|
|
788
|
+
".agentkit-run-failure button",
|
|
789
|
+
),
|
|
790
|
+
].find((button) => button.textContent === "Continue");
|
|
791
|
+
|
|
792
|
+
try {
|
|
793
|
+
await act(async () => {
|
|
794
|
+
root.render(
|
|
795
|
+
<AgentKitProvider controller={client} threadId="thread-continue">
|
|
796
|
+
<AgentKitChat composer={false} />
|
|
797
|
+
</AgentKitProvider>,
|
|
798
|
+
);
|
|
799
|
+
await Promise.resolve();
|
|
800
|
+
});
|
|
801
|
+
expect(continueButton()).toBeDefined();
|
|
802
|
+
|
|
803
|
+
await act(async () => {
|
|
804
|
+
continueButton()?.click();
|
|
805
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
expect(continueRun).toHaveBeenCalledWith(
|
|
809
|
+
{ threadId: "thread-continue", runId: "run-crashed" },
|
|
810
|
+
expect.anything(),
|
|
811
|
+
);
|
|
812
|
+
expect(container.textContent?.includes("can't be continued")).toBe(
|
|
813
|
+
!accepted,
|
|
814
|
+
);
|
|
815
|
+
} finally {
|
|
816
|
+
await act(async () => {
|
|
817
|
+
root.unmount();
|
|
818
|
+
await Promise.resolve();
|
|
819
|
+
});
|
|
820
|
+
container.remove();
|
|
821
|
+
if (previousActEnvironment === undefined) {
|
|
822
|
+
delete actEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
823
|
+
} else {
|
|
824
|
+
actEnvironment.IS_REACT_ACT_ENVIRONMENT = previousActEnvironment;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
|
|
722
829
|
it("renders the default plus control and routes chat-wide file drops to the composer", async () => {
|
|
723
830
|
const transport: AgentTransport = {
|
|
724
831
|
capabilities: { uploads: true },
|
|
@@ -1190,6 +1297,209 @@ describe("AgentKitChat interactions", () => {
|
|
|
1190
1297
|
}
|
|
1191
1298
|
});
|
|
1192
1299
|
|
|
1300
|
+
it("fills the thumbs-down reason from chips and copies a report with the run, thread and note", async () => {
|
|
1301
|
+
const assistantMessage = {
|
|
1302
|
+
id: "assistant-report",
|
|
1303
|
+
role: "assistant" as const,
|
|
1304
|
+
status: "complete" as const,
|
|
1305
|
+
createdAt: "2026-09-26T00:00:00.000Z",
|
|
1306
|
+
parts: [{ type: "text" as const, text: "All done" }],
|
|
1307
|
+
};
|
|
1308
|
+
const transport: AgentTransport = {
|
|
1309
|
+
capabilities: { feedback: true },
|
|
1310
|
+
async submitFeedback() {},
|
|
1311
|
+
async startRun() {
|
|
1312
|
+
return { runId: "run-report" };
|
|
1313
|
+
},
|
|
1314
|
+
async *subscribeToRun() {},
|
|
1315
|
+
async cancelRun() {},
|
|
1316
|
+
async getThreadSnapshot(threadId) {
|
|
1317
|
+
return {
|
|
1318
|
+
id: threadId,
|
|
1319
|
+
createdAt: "2026-09-26T00:00:00.000Z",
|
|
1320
|
+
updatedAt: "2026-09-26T00:00:00.000Z",
|
|
1321
|
+
messages: [assistantMessage],
|
|
1322
|
+
events: [
|
|
1323
|
+
{
|
|
1324
|
+
id: "event-report",
|
|
1325
|
+
threadId,
|
|
1326
|
+
runId: "run-report",
|
|
1327
|
+
sequence: 1,
|
|
1328
|
+
occurredAt: "2026-09-26T00:00:00.000Z",
|
|
1329
|
+
type: "message.completed",
|
|
1330
|
+
message: assistantMessage,
|
|
1331
|
+
},
|
|
1332
|
+
],
|
|
1333
|
+
};
|
|
1334
|
+
},
|
|
1335
|
+
};
|
|
1336
|
+
const client = new AgentKitClient({ transport });
|
|
1337
|
+
await client.loadThread("thread-report");
|
|
1338
|
+
const buildFeedbackReport = vi.fn(
|
|
1339
|
+
({ runId, note }: { runId?: string; note: string }) =>
|
|
1340
|
+
`report run=${runId} note=${note}`,
|
|
1341
|
+
);
|
|
1342
|
+
const writeText = vi.fn(async () => undefined);
|
|
1343
|
+
const clipboardDescriptor = Object.getOwnPropertyDescriptor(
|
|
1344
|
+
navigator,
|
|
1345
|
+
"clipboard",
|
|
1346
|
+
);
|
|
1347
|
+
Object.defineProperty(navigator, "clipboard", {
|
|
1348
|
+
configurable: true,
|
|
1349
|
+
value: { writeText },
|
|
1350
|
+
});
|
|
1351
|
+
const container = document.createElement("div");
|
|
1352
|
+
document.body.appendChild(container);
|
|
1353
|
+
const root = createRoot(container);
|
|
1354
|
+
const actEnvironment = globalThis as typeof globalThis & {
|
|
1355
|
+
IS_REACT_ACT_ENVIRONMENT?: boolean;
|
|
1356
|
+
};
|
|
1357
|
+
const previousActEnvironment = actEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
1358
|
+
actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
|
|
1359
|
+
const buttonByText = (text: string) =>
|
|
1360
|
+
Array.from(
|
|
1361
|
+
document.body.querySelectorAll<HTMLButtonElement>("button"),
|
|
1362
|
+
).find((button) => button.textContent?.includes(text));
|
|
1363
|
+
|
|
1364
|
+
try {
|
|
1365
|
+
await act(async () => {
|
|
1366
|
+
root.render(
|
|
1367
|
+
<AgentKitProvider
|
|
1368
|
+
controller={client}
|
|
1369
|
+
threadId="thread-report"
|
|
1370
|
+
buildFeedbackReport={buildFeedbackReport}
|
|
1371
|
+
>
|
|
1372
|
+
<AgentKitChat composer={false} />
|
|
1373
|
+
</AgentKitProvider>,
|
|
1374
|
+
);
|
|
1375
|
+
await Promise.resolve();
|
|
1376
|
+
});
|
|
1377
|
+
await act(async () => {
|
|
1378
|
+
container
|
|
1379
|
+
.querySelector<HTMLButtonElement>('button[aria-label="Not helpful"]')
|
|
1380
|
+
?.click();
|
|
1381
|
+
await Promise.resolve();
|
|
1382
|
+
});
|
|
1383
|
+
|
|
1384
|
+
// They sit inside the feedback form, so none may submit it.
|
|
1385
|
+
expect(buttonByText("Misread my ask")?.type).toBe("button");
|
|
1386
|
+
expect(buttonByText("Copy details")?.type).toBe("button");
|
|
1387
|
+
await act(async () => {
|
|
1388
|
+
buttonByText("Misread my ask")?.click();
|
|
1389
|
+
buttonByText("Wrong numbers")?.click();
|
|
1390
|
+
buttonByText("Misread my ask")?.click();
|
|
1391
|
+
});
|
|
1392
|
+
const textarea = document.body.querySelector<HTMLTextAreaElement>(
|
|
1393
|
+
".agentkit-feedback-popover textarea",
|
|
1394
|
+
);
|
|
1395
|
+
expect(textarea?.value).toBe("Misread my ask. Wrong numbers");
|
|
1396
|
+
|
|
1397
|
+
await act(async () => {
|
|
1398
|
+
buttonByText("Copy details")?.click();
|
|
1399
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1400
|
+
});
|
|
1401
|
+
expect(buildFeedbackReport).toHaveBeenCalledWith({
|
|
1402
|
+
threadId: "thread-report",
|
|
1403
|
+
runId: "run-report",
|
|
1404
|
+
messageId: "assistant-report",
|
|
1405
|
+
note: "Misread my ask. Wrong numbers",
|
|
1406
|
+
});
|
|
1407
|
+
expect(writeText).toHaveBeenCalledWith(
|
|
1408
|
+
"report run=run-report note=Misread my ask. Wrong numbers",
|
|
1409
|
+
);
|
|
1410
|
+
expect(buttonByText("Copied")).toBeDefined();
|
|
1411
|
+
} finally {
|
|
1412
|
+
await act(async () => {
|
|
1413
|
+
root.unmount();
|
|
1414
|
+
await Promise.resolve();
|
|
1415
|
+
});
|
|
1416
|
+
await client.shutdown();
|
|
1417
|
+
container.remove();
|
|
1418
|
+
if (clipboardDescriptor) {
|
|
1419
|
+
Object.defineProperty(navigator, "clipboard", clipboardDescriptor);
|
|
1420
|
+
} else {
|
|
1421
|
+
Reflect.deleteProperty(navigator, "clipboard");
|
|
1422
|
+
}
|
|
1423
|
+
if (previousActEnvironment === undefined) {
|
|
1424
|
+
delete actEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
1425
|
+
} else {
|
|
1426
|
+
actEnvironment.IS_REACT_ACT_ENVIRONMENT = previousActEnvironment;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
|
|
1431
|
+
it("offers no Copy details without a report builder", async () => {
|
|
1432
|
+
const assistantMessage = {
|
|
1433
|
+
id: "assistant-no-report",
|
|
1434
|
+
role: "assistant" as const,
|
|
1435
|
+
status: "complete" as const,
|
|
1436
|
+
createdAt: "2026-09-26T00:00:00.000Z",
|
|
1437
|
+
parts: [{ type: "text" as const, text: "Answer" }],
|
|
1438
|
+
};
|
|
1439
|
+
const client = new AgentKitClient({
|
|
1440
|
+
transport: {
|
|
1441
|
+
capabilities: { feedback: true },
|
|
1442
|
+
async submitFeedback() {},
|
|
1443
|
+
async startRun() {
|
|
1444
|
+
return { runId: "run-no-report" };
|
|
1445
|
+
},
|
|
1446
|
+
async *subscribeToRun() {},
|
|
1447
|
+
async cancelRun() {},
|
|
1448
|
+
async getThreadSnapshot(threadId) {
|
|
1449
|
+
return {
|
|
1450
|
+
id: threadId,
|
|
1451
|
+
createdAt: "2026-09-26T00:00:00.000Z",
|
|
1452
|
+
updatedAt: "2026-09-26T00:00:00.000Z",
|
|
1453
|
+
messages: [assistantMessage],
|
|
1454
|
+
};
|
|
1455
|
+
},
|
|
1456
|
+
},
|
|
1457
|
+
});
|
|
1458
|
+
await client.loadThread("thread-no-report");
|
|
1459
|
+
const container = document.createElement("div");
|
|
1460
|
+
document.body.appendChild(container);
|
|
1461
|
+
const root = createRoot(container);
|
|
1462
|
+
const actEnvironment = globalThis as typeof globalThis & {
|
|
1463
|
+
IS_REACT_ACT_ENVIRONMENT?: boolean;
|
|
1464
|
+
};
|
|
1465
|
+
const previousActEnvironment = actEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
1466
|
+
actEnvironment.IS_REACT_ACT_ENVIRONMENT = true;
|
|
1467
|
+
|
|
1468
|
+
try {
|
|
1469
|
+
await act(async () => {
|
|
1470
|
+
root.render(
|
|
1471
|
+
<AgentKitProvider controller={client} threadId="thread-no-report">
|
|
1472
|
+
<AgentKitChat composer={false} />
|
|
1473
|
+
</AgentKitProvider>,
|
|
1474
|
+
);
|
|
1475
|
+
await Promise.resolve();
|
|
1476
|
+
});
|
|
1477
|
+
await act(async () => {
|
|
1478
|
+
container
|
|
1479
|
+
.querySelector<HTMLButtonElement>('button[aria-label="Not helpful"]')
|
|
1480
|
+
?.click();
|
|
1481
|
+
await Promise.resolve();
|
|
1482
|
+
});
|
|
1483
|
+
|
|
1484
|
+
expect(
|
|
1485
|
+
document.body.querySelector(".agentkit-feedback-popover"),
|
|
1486
|
+
).not.toBeNull();
|
|
1487
|
+
expect(document.body.textContent).not.toContain("Copy details");
|
|
1488
|
+
} finally {
|
|
1489
|
+
await act(async () => {
|
|
1490
|
+
root.unmount();
|
|
1491
|
+
await Promise.resolve();
|
|
1492
|
+
});
|
|
1493
|
+
await client.shutdown();
|
|
1494
|
+
container.remove();
|
|
1495
|
+
if (previousActEnvironment === undefined) {
|
|
1496
|
+
delete actEnvironment.IS_REACT_ACT_ENVIRONMENT;
|
|
1497
|
+
} else {
|
|
1498
|
+
actEnvironment.IS_REACT_ACT_ENVIRONMENT = previousActEnvironment;
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
});
|
|
1502
|
+
|
|
1193
1503
|
it("falls back to plain-text clipboard copy when the host declines handling", async () => {
|
|
1194
1504
|
const message = {
|
|
1195
1505
|
id: "assistant-copy-fallback",
|
|
@@ -971,7 +971,7 @@ describe("AgentKitChat", () => {
|
|
|
971
971
|
},
|
|
972
972
|
{
|
|
973
973
|
type: "text",
|
|
974
|
-
text: "Also tell @Steve.",
|
|
974
|
+
text: "Also tell @Steve about any @builder.io booking.",
|
|
975
975
|
},
|
|
976
976
|
{
|
|
977
977
|
type: "file",
|
|
@@ -1050,7 +1050,12 @@ describe("AgentKitChat", () => {
|
|
|
1050
1050
|
|
|
1051
1051
|
expect(htmlWithComposer).toContain('aria-label="Edit message"');
|
|
1052
1052
|
expect(htmlWithComposer).toContain('data-mention-label="latest run"');
|
|
1053
|
-
|
|
1053
|
+
// Plain "@word" text is not a reference, so it stays literal text.
|
|
1054
|
+
expect(htmlWithComposer).not.toContain('data-mention-label="Steve"');
|
|
1055
|
+
expect(htmlWithComposer).not.toContain('data-mention-label="builder"');
|
|
1056
|
+
expect(htmlWithComposer).toContain(
|
|
1057
|
+
"Also tell @Steve about any @builder.io booking.",
|
|
1058
|
+
);
|
|
1054
1059
|
expect(htmlWithComposer).toContain('aria-label="Preview latest-run.png"');
|
|
1055
1060
|
expect(htmlWithComposer).toContain("Pasted text");
|
|
1056
1061
|
expect(htmlWithComposer).toContain("agentkit-file--pasted-text");
|
|
@@ -1801,4 +1806,103 @@ describe("AgentKitChat", () => {
|
|
|
1801
1806
|
{ error: failure, runId: "run-failure", threadId: "thread-1" },
|
|
1802
1807
|
]);
|
|
1803
1808
|
});
|
|
1809
|
+
|
|
1810
|
+
it.each([
|
|
1811
|
+
{ label: "with no work", work: false },
|
|
1812
|
+
{ label: "after its last work", work: true },
|
|
1813
|
+
])(
|
|
1814
|
+
"keeps a failed run's card in its own turn, above a newer turn ($label)",
|
|
1815
|
+
async ({ work }) => {
|
|
1816
|
+
const transport: AgentTransport = {
|
|
1817
|
+
async startRun(input) {
|
|
1818
|
+
return {
|
|
1819
|
+
runId: input.messages.length === 1 ? "run-failed" : "run-next",
|
|
1820
|
+
};
|
|
1821
|
+
},
|
|
1822
|
+
async *subscribeToRun({ runId }) {
|
|
1823
|
+
const base = {
|
|
1824
|
+
threadId: "thread-1",
|
|
1825
|
+
runId,
|
|
1826
|
+
occurredAt:
|
|
1827
|
+
runId === "run-failed"
|
|
1828
|
+
? "2026-10-05T17:01:00.000Z"
|
|
1829
|
+
: "2026-10-05T17:11:00.000Z",
|
|
1830
|
+
};
|
|
1831
|
+
yield { ...base, id: `${runId}-1`, sequence: 1, type: "run.started" };
|
|
1832
|
+
if (runId === "run-failed") {
|
|
1833
|
+
let sequence = 1;
|
|
1834
|
+
if (work) {
|
|
1835
|
+
yield {
|
|
1836
|
+
...base,
|
|
1837
|
+
id: `${runId}-work`,
|
|
1838
|
+
sequence: ++sequence,
|
|
1839
|
+
type: "activity.started",
|
|
1840
|
+
activity: {
|
|
1841
|
+
id: "activity-1",
|
|
1842
|
+
kind: "tool",
|
|
1843
|
+
label: "Charging the card",
|
|
1844
|
+
status: "running",
|
|
1845
|
+
},
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
yield {
|
|
1849
|
+
...base,
|
|
1850
|
+
id: `${runId}-failed`,
|
|
1851
|
+
sequence: ++sequence,
|
|
1852
|
+
type: "run.failed",
|
|
1853
|
+
error: {
|
|
1854
|
+
code: "stale_run",
|
|
1855
|
+
message: "The agent stopped before it could finish.",
|
|
1856
|
+
retryable: true,
|
|
1857
|
+
},
|
|
1858
|
+
};
|
|
1859
|
+
return;
|
|
1860
|
+
}
|
|
1861
|
+
yield {
|
|
1862
|
+
...base,
|
|
1863
|
+
id: `${runId}-reply`,
|
|
1864
|
+
sequence: 2,
|
|
1865
|
+
type: "message.completed",
|
|
1866
|
+
message: {
|
|
1867
|
+
id: "assistant-next",
|
|
1868
|
+
role: "assistant",
|
|
1869
|
+
parts: [{ type: "text", text: "Newer answer" }],
|
|
1870
|
+
},
|
|
1871
|
+
};
|
|
1872
|
+
yield {
|
|
1873
|
+
...base,
|
|
1874
|
+
id: `${runId}-done`,
|
|
1875
|
+
sequence: 3,
|
|
1876
|
+
type: "run.completed",
|
|
1877
|
+
};
|
|
1878
|
+
},
|
|
1879
|
+
async cancelRun() {},
|
|
1880
|
+
};
|
|
1881
|
+
let clock = "2026-10-05T17:00:00.000Z";
|
|
1882
|
+
const client = new AgentKitClient({ transport, now: () => clock });
|
|
1883
|
+
await (
|
|
1884
|
+
await client.sendMessage({ threadId: "thread-1", text: "First turn" })
|
|
1885
|
+
).completed;
|
|
1886
|
+
clock = "2026-10-05T17:10:00.000Z";
|
|
1887
|
+
await (
|
|
1888
|
+
await client.sendMessage({ threadId: "thread-1", text: "Next turn" })
|
|
1889
|
+
).completed;
|
|
1890
|
+
|
|
1891
|
+
const html = renderToStaticMarkup(
|
|
1892
|
+
<AgentKitProvider controller={client} threadId="thread-1">
|
|
1893
|
+
<AgentKitChat composer={false} />
|
|
1894
|
+
</AgentKitProvider>,
|
|
1895
|
+
);
|
|
1896
|
+
|
|
1897
|
+
const order = [
|
|
1898
|
+
"First turn",
|
|
1899
|
+
...(work ? ["Charging the card"] : []),
|
|
1900
|
+
'data-run-id="run-failed"',
|
|
1901
|
+
"Next turn",
|
|
1902
|
+
"Newer answer",
|
|
1903
|
+
].map((text) => html.indexOf(text));
|
|
1904
|
+
expect(order.every((index) => index >= 0)).toBe(true);
|
|
1905
|
+
expect(order).toEqual([...order].sort((left, right) => left - right));
|
|
1906
|
+
},
|
|
1907
|
+
);
|
|
1804
1908
|
});
|