@agent-native/toolkit 0.203.2-nightly-20261007213109 → 0.204.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/chat/AgentKitAssistantChat.js +2 -2
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +1 -1
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +1 -1
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +1 -1
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.js +12 -4
- package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
- package/dist/app/settings/useBuilderStatus.d.ts +4 -0
- package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/app/settings/useBuilderStatus.js +56 -16
- package/dist/app/settings/useBuilderStatus.js.map +1 -1
- package/package.json +4 -4
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +7 -0
- package/src/app/chat/AgentKitAssistantChat.tsx +3 -3
- package/src/app/i18n/catalogs/ar-SA.ts +1 -1
- package/src/app/i18n/catalogs/de-DE.ts +1 -1
- package/src/app/i18n/catalogs/en-US.ts +1 -1
- package/src/app/i18n/catalogs/es-ES.ts +1 -1
- package/src/app/i18n/catalogs/fr-FR.ts +1 -1
- package/src/app/i18n/catalogs/hi-IN.ts +1 -1
- package/src/app/i18n/catalogs/ja-JP.ts +1 -1
- package/src/app/i18n/catalogs/ko-KR.ts +1 -1
- package/src/app/i18n/catalogs/pt-BR.ts +1 -1
- package/src/app/i18n/catalogs/zh-CN.ts +1 -1
- package/src/app/i18n/catalogs/zh-TW.ts +1 -1
- package/src/app/onboarding/FirstRunOnboarding.spec.tsx +163 -27
- package/src/app/onboarding/FirstRunOnboarding.tsx +39 -22
- package/src/app/settings/useBuilderStatus.spec.tsx +24 -2
- package/src/app/settings/useBuilderStatus.ts +57 -17
|
@@ -587,6 +587,159 @@ describe("FirstRunOnboarding", () => {
|
|
|
587
587
|
expect(flow.cancel).toHaveBeenCalledOnce();
|
|
588
588
|
});
|
|
589
589
|
|
|
590
|
+
it("keeps Cancel during a failed status poll without offering a fake retry", () => {
|
|
591
|
+
const flow = {
|
|
592
|
+
hasFetchedStatus: true,
|
|
593
|
+
statusResolved: false,
|
|
594
|
+
configured: false,
|
|
595
|
+
agentNativeProvisioningEnabled: true,
|
|
596
|
+
connecting: false,
|
|
597
|
+
statusUnavailable: true,
|
|
598
|
+
terminalError: null,
|
|
599
|
+
error: "Couldn't check the Builder.io connection.",
|
|
600
|
+
start: vi.fn(),
|
|
601
|
+
cancel: vi.fn(),
|
|
602
|
+
retry: vi.fn(),
|
|
603
|
+
};
|
|
604
|
+
flow.start.mockImplementation(() => {
|
|
605
|
+
flow.connecting = true;
|
|
606
|
+
});
|
|
607
|
+
mocks.useBuilderConnectFlow.mockReturnValue(flow);
|
|
608
|
+
|
|
609
|
+
act(() => {
|
|
610
|
+
root.render(
|
|
611
|
+
<TooltipProvider>
|
|
612
|
+
<FirstRunOnboarding />
|
|
613
|
+
</TooltipProvider>,
|
|
614
|
+
);
|
|
615
|
+
});
|
|
616
|
+
act(() => {
|
|
617
|
+
document.body
|
|
618
|
+
.querySelector("[data-testid='first-run-role-skip']")
|
|
619
|
+
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
620
|
+
});
|
|
621
|
+
act(() => {
|
|
622
|
+
document.body
|
|
623
|
+
.querySelector("[data-testid='first-run-builder-create-account']")
|
|
624
|
+
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
expect(document.body.textContent).toContain(
|
|
628
|
+
"Couldn't check the Builder.io connection.",
|
|
629
|
+
);
|
|
630
|
+
expect(
|
|
631
|
+
document.body.querySelector('[data-testid="first-run-cancel-builder"]'),
|
|
632
|
+
).not.toBeNull();
|
|
633
|
+
expect(
|
|
634
|
+
[...document.body.querySelectorAll("button")].some(
|
|
635
|
+
(button) => button.textContent === "Try again",
|
|
636
|
+
),
|
|
637
|
+
).toBe(false);
|
|
638
|
+
|
|
639
|
+
act(() => {
|
|
640
|
+
document.body
|
|
641
|
+
.querySelector<HTMLButtonElement>(
|
|
642
|
+
'[data-testid="first-run-cancel-builder"]',
|
|
643
|
+
)
|
|
644
|
+
?.click();
|
|
645
|
+
});
|
|
646
|
+
expect(flow.cancel).toHaveBeenCalledOnce();
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
it.each([
|
|
650
|
+
{
|
|
651
|
+
mode: "provision",
|
|
652
|
+
choiceId: "first-run-builder-create-account",
|
|
653
|
+
provisionAccount: true,
|
|
654
|
+
failure: "transient status read failure",
|
|
655
|
+
statusUnavailable: true,
|
|
656
|
+
terminalError: null,
|
|
657
|
+
error: "Couldn't check the Builder.io connection.",
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
mode: "existing",
|
|
661
|
+
choiceId: "first-run-builder-sign-in",
|
|
662
|
+
provisionAccount: false,
|
|
663
|
+
failure: "transient status read failure",
|
|
664
|
+
statusUnavailable: true,
|
|
665
|
+
terminalError: null,
|
|
666
|
+
error: "Couldn't check the Builder.io connection.",
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
mode: "provision",
|
|
670
|
+
choiceId: "first-run-builder-create-account",
|
|
671
|
+
provisionAccount: true,
|
|
672
|
+
failure: "terminal connection error",
|
|
673
|
+
statusUnavailable: true,
|
|
674
|
+
terminalError: "Builder connection failed.",
|
|
675
|
+
error: "Builder connection failed.",
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
mode: "existing",
|
|
679
|
+
choiceId: "first-run-builder-sign-in",
|
|
680
|
+
provisionAccount: false,
|
|
681
|
+
failure: "terminal connection error",
|
|
682
|
+
statusUnavailable: true,
|
|
683
|
+
terminalError: "Builder connection failed.",
|
|
684
|
+
error: "Builder connection failed.",
|
|
685
|
+
},
|
|
686
|
+
])(
|
|
687
|
+
"restarts the prior $mode mode after a $failure",
|
|
688
|
+
({
|
|
689
|
+
choiceId,
|
|
690
|
+
provisionAccount,
|
|
691
|
+
statusUnavailable,
|
|
692
|
+
terminalError,
|
|
693
|
+
error,
|
|
694
|
+
}) => {
|
|
695
|
+
const start = vi.fn();
|
|
696
|
+
mocks.useBuilderConnectFlow.mockReturnValue({
|
|
697
|
+
hasFetchedStatus: true,
|
|
698
|
+
statusResolved: true,
|
|
699
|
+
configured: false,
|
|
700
|
+
agentNativeProvisioningEnabled: true,
|
|
701
|
+
connecting: false,
|
|
702
|
+
statusUnavailable,
|
|
703
|
+
terminalError,
|
|
704
|
+
error,
|
|
705
|
+
start,
|
|
706
|
+
cancel: vi.fn(),
|
|
707
|
+
retry: vi.fn(),
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
act(() => {
|
|
711
|
+
root.render(
|
|
712
|
+
<TooltipProvider>
|
|
713
|
+
<FirstRunOnboarding />
|
|
714
|
+
</TooltipProvider>,
|
|
715
|
+
);
|
|
716
|
+
});
|
|
717
|
+
act(() => {
|
|
718
|
+
document.body
|
|
719
|
+
.querySelector("[data-testid='first-run-role-skip']")
|
|
720
|
+
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
721
|
+
});
|
|
722
|
+
act(() => {
|
|
723
|
+
document.body
|
|
724
|
+
.querySelector(`[data-testid='${choiceId}']`)
|
|
725
|
+
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
expect(start).toHaveBeenCalledOnce();
|
|
729
|
+
expect(document.body.textContent).toContain(error);
|
|
730
|
+
act(() => {
|
|
731
|
+
[...document.body.querySelectorAll("button")]
|
|
732
|
+
.find((button) => button.textContent === "Try again")
|
|
733
|
+
?.click();
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
expect(start).toHaveBeenCalledTimes(2);
|
|
737
|
+
expect(start).toHaveBeenLastCalledWith(
|
|
738
|
+
expect.objectContaining({ provisionAccount }),
|
|
739
|
+
);
|
|
740
|
+
},
|
|
741
|
+
);
|
|
742
|
+
|
|
590
743
|
it("creates a Builder account from the primary button and shows its loading state", () => {
|
|
591
744
|
const flow = {
|
|
592
745
|
hasFetchedStatus: true,
|
|
@@ -760,7 +913,7 @@ describe("FirstRunOnboarding", () => {
|
|
|
760
913
|
expect(JSON.stringify(outcome)).not.toContain("Error:");
|
|
761
914
|
});
|
|
762
915
|
|
|
763
|
-
it("does not attach a
|
|
916
|
+
it("does not attach a status-read failure to a manual setup attempt", async () => {
|
|
764
917
|
const flow = {
|
|
765
918
|
hasFetchedStatus: true,
|
|
766
919
|
statusResolved: true,
|
|
@@ -768,8 +921,9 @@ describe("FirstRunOnboarding", () => {
|
|
|
768
921
|
agentNativeProvisioningEnabled: true,
|
|
769
922
|
accountExists: false,
|
|
770
923
|
connecting: false,
|
|
771
|
-
|
|
772
|
-
|
|
924
|
+
statusUnavailable: true,
|
|
925
|
+
terminalError: null,
|
|
926
|
+
error: "Couldn't check the Builder.io connection.",
|
|
773
927
|
};
|
|
774
928
|
let resolveCompletion: (() => void) | undefined;
|
|
775
929
|
mocks.completeFirstRun.mockImplementation(
|
|
@@ -792,25 +946,6 @@ describe("FirstRunOnboarding", () => {
|
|
|
792
946
|
.querySelector("[data-testid='first-run-role-skip']")
|
|
793
947
|
?.click();
|
|
794
948
|
});
|
|
795
|
-
act(() => {
|
|
796
|
-
document.body
|
|
797
|
-
.querySelector("[data-testid='first-run-builder-create-account']")
|
|
798
|
-
?.click();
|
|
799
|
-
});
|
|
800
|
-
|
|
801
|
-
flow.error = "stale Builder error";
|
|
802
|
-
act(() => {
|
|
803
|
-
root.render(
|
|
804
|
-
<TooltipProvider>
|
|
805
|
-
<FirstRunOnboarding />
|
|
806
|
-
</TooltipProvider>,
|
|
807
|
-
);
|
|
808
|
-
});
|
|
809
|
-
act(() => {
|
|
810
|
-
[...document.body.querySelectorAll("button")]
|
|
811
|
-
.find((button) => button.textContent === "Try again")
|
|
812
|
-
?.click();
|
|
813
|
-
});
|
|
814
949
|
|
|
815
950
|
await act(async () => {
|
|
816
951
|
document.body
|
|
@@ -818,7 +953,7 @@ describe("FirstRunOnboarding", () => {
|
|
|
818
953
|
?.click();
|
|
819
954
|
await Promise.resolve();
|
|
820
955
|
});
|
|
821
|
-
flow.error = "
|
|
956
|
+
flow.error = "Builder status still unavailable.";
|
|
822
957
|
act(() => {
|
|
823
958
|
root.render(
|
|
824
959
|
<TooltipProvider>
|
|
@@ -1534,7 +1669,7 @@ describe("FirstRunOnboarding", () => {
|
|
|
1534
1669
|
expect(document.body.textContent).not.toMatch(/\bProduct\b/);
|
|
1535
1670
|
});
|
|
1536
1671
|
|
|
1537
|
-
it("keeps
|
|
1672
|
+
it("keeps setup choices clear and actionable after a failed status read", () => {
|
|
1538
1673
|
const start = vi.fn();
|
|
1539
1674
|
const retry = vi.fn();
|
|
1540
1675
|
mocks.useBuilderConnectFlow.mockReturnValue({
|
|
@@ -1544,7 +1679,8 @@ describe("FirstRunOnboarding", () => {
|
|
|
1544
1679
|
agentNativeProvisioningEnabled: true,
|
|
1545
1680
|
accountExists: false,
|
|
1546
1681
|
connecting: false,
|
|
1547
|
-
|
|
1682
|
+
statusUnavailable: true,
|
|
1683
|
+
error: "Couldn't check the Builder.io connection.",
|
|
1548
1684
|
retry,
|
|
1549
1685
|
start,
|
|
1550
1686
|
});
|
|
@@ -1565,8 +1701,8 @@ describe("FirstRunOnboarding", () => {
|
|
|
1565
1701
|
expect(
|
|
1566
1702
|
document.body.querySelector(
|
|
1567
1703
|
'[data-testid="first-run-builder-status-error"]',
|
|
1568
|
-
)
|
|
1569
|
-
).
|
|
1704
|
+
),
|
|
1705
|
+
).toBeNull();
|
|
1570
1706
|
|
|
1571
1707
|
const cta = document.body.querySelector(
|
|
1572
1708
|
'[data-testid="first-run-builder-create-account"]',
|
|
@@ -464,10 +464,14 @@ export function FirstRunOnboarding({
|
|
|
464
464
|
trackFirstRunSetupOutcome(attempt, "failed", "account_exists");
|
|
465
465
|
return;
|
|
466
466
|
}
|
|
467
|
-
if (connectFlow.
|
|
467
|
+
if (connectFlow.terminalError) {
|
|
468
468
|
trackFirstRunSetupOutcome(attempt, "failed", "connection_error");
|
|
469
469
|
}
|
|
470
|
-
}, [
|
|
470
|
+
}, [
|
|
471
|
+
connectFlow.accountExists,
|
|
472
|
+
connectFlow.connecting,
|
|
473
|
+
connectFlow.terminalError,
|
|
474
|
+
]);
|
|
471
475
|
const canActivateBuilderFreeCredits =
|
|
472
476
|
connectFlow.agentNativeProvisioningEnabled;
|
|
473
477
|
const retryOnboardingCompletion = useCallback(() => {
|
|
@@ -746,15 +750,6 @@ export function FirstRunOnboarding({
|
|
|
746
750
|
{t("agentChat.onboarding.builderSignInWithAccount")}
|
|
747
751
|
</button>
|
|
748
752
|
</div>
|
|
749
|
-
{connectFlow.error && !connectFlow.statusResolved && (
|
|
750
|
-
<p
|
|
751
|
-
role="status"
|
|
752
|
-
data-testid="first-run-builder-status-error"
|
|
753
|
-
className="text-center text-xs text-destructive"
|
|
754
|
-
>
|
|
755
|
-
{connectFlow.error}
|
|
756
|
-
</p>
|
|
757
|
-
)}
|
|
758
753
|
</section>
|
|
759
754
|
|
|
760
755
|
<section className="flex flex-col gap-5 rounded-2xl border border-border bg-card p-6">
|
|
@@ -996,18 +991,40 @@ export function FirstRunOnboarding({
|
|
|
996
991
|
{t("common.cancel")}
|
|
997
992
|
</button>
|
|
998
993
|
)}
|
|
999
|
-
{connectFlow.
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
<
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
>
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
994
|
+
{connectFlow.statusUnavailable &&
|
|
995
|
+
connectFlow.connecting &&
|
|
996
|
+
!connectFlow.terminalError && (
|
|
997
|
+
<p className="mt-4 text-xs text-destructive" role="alert">
|
|
998
|
+
{t(
|
|
999
|
+
"agentChat.settingsShell.integrations.builderStatusFailed",
|
|
1000
|
+
)}
|
|
1001
|
+
</p>
|
|
1002
|
+
)}
|
|
1003
|
+
{connectFlow.terminalError && connectFlow.connecting && (
|
|
1004
|
+
<p className="mt-4 text-xs text-destructive" role="alert">
|
|
1005
|
+
{connectFlow.terminalError}
|
|
1006
|
+
</p>
|
|
1010
1007
|
)}
|
|
1008
|
+
{!connectFlow.connecting &&
|
|
1009
|
+
(connectFlow.statusUnavailable || connectFlow.terminalError) && (
|
|
1010
|
+
<div className="mt-4 flex flex-col items-center gap-2">
|
|
1011
|
+
<p className="text-xs text-destructive" role="alert">
|
|
1012
|
+
{connectFlow.terminalError ??
|
|
1013
|
+
t(
|
|
1014
|
+
"agentChat.settingsShell.integrations.builderStatusFailed",
|
|
1015
|
+
)}
|
|
1016
|
+
</p>
|
|
1017
|
+
<button
|
|
1018
|
+
type="button"
|
|
1019
|
+
className={secondaryButtonClass}
|
|
1020
|
+
onClick={() =>
|
|
1021
|
+
handleBuilder(builderConnectionMode === "provision")
|
|
1022
|
+
}
|
|
1023
|
+
>
|
|
1024
|
+
Try again
|
|
1025
|
+
</button>
|
|
1026
|
+
</div>
|
|
1027
|
+
)}
|
|
1011
1028
|
</>
|
|
1012
1029
|
)}
|
|
1013
1030
|
</div>
|
|
@@ -103,6 +103,12 @@ function BuilderConnectProbeContent({
|
|
|
103
103
|
<output data-testid="credential-source">
|
|
104
104
|
{flow.credentialSource ?? "none"}
|
|
105
105
|
</output>
|
|
106
|
+
<output data-testid="status-unavailable">
|
|
107
|
+
{flow.statusUnavailable ? "unavailable" : "available"}
|
|
108
|
+
</output>
|
|
109
|
+
<output data-testid="terminal-error">
|
|
110
|
+
{flow.terminalError ?? "none"}
|
|
111
|
+
</output>
|
|
106
112
|
<output>{flow.error ?? ""}</output>
|
|
107
113
|
</div>
|
|
108
114
|
);
|
|
@@ -1644,8 +1650,15 @@ describe("useBuilderConnectFlow", () => {
|
|
|
1644
1650
|
await flushAfterPaint();
|
|
1645
1651
|
|
|
1646
1652
|
expect(container.textContent).toContain("not-configured idle unresolved");
|
|
1653
|
+
expect(
|
|
1654
|
+
container.querySelector('[data-testid="status-unavailable"]')
|
|
1655
|
+
?.textContent,
|
|
1656
|
+
).toBe("unavailable");
|
|
1657
|
+
expect(
|
|
1658
|
+
container.querySelector('[data-testid="terminal-error"]')?.textContent,
|
|
1659
|
+
).toBe("none");
|
|
1647
1660
|
expect(container.textContent).toContain(
|
|
1648
|
-
"Couldn't
|
|
1661
|
+
"Couldn't check the Builder.io connection.",
|
|
1649
1662
|
);
|
|
1650
1663
|
|
|
1651
1664
|
await act(async () => {
|
|
@@ -1655,7 +1668,16 @@ describe("useBuilderConnectFlow", () => {
|
|
|
1655
1668
|
});
|
|
1656
1669
|
|
|
1657
1670
|
expect(container.textContent).toContain("not-configured idle resolved");
|
|
1658
|
-
expect(
|
|
1671
|
+
expect(
|
|
1672
|
+
container.querySelector('[data-testid="status-unavailable"]')
|
|
1673
|
+
?.textContent,
|
|
1674
|
+
).toBe("available");
|
|
1675
|
+
expect(
|
|
1676
|
+
container.querySelector('[data-testid="terminal-error"]')?.textContent,
|
|
1677
|
+
).toBe("none");
|
|
1678
|
+
expect(container.textContent).not.toContain(
|
|
1679
|
+
"Couldn't check the Builder.io connection.",
|
|
1680
|
+
);
|
|
1659
1681
|
});
|
|
1660
1682
|
|
|
1661
1683
|
it("shows the chooser without navigating when status cannot be resolved", async () => {
|
|
@@ -268,6 +268,10 @@ export interface BuilderConnectFlow {
|
|
|
268
268
|
orgName: string | null;
|
|
269
269
|
connecting: boolean;
|
|
270
270
|
error: string | null;
|
|
271
|
+
/** The most recent terminal Builder connection attempt error, if any. */
|
|
272
|
+
terminalError: string | null;
|
|
273
|
+
/** The most recent Builder connection-status read failed. */
|
|
274
|
+
statusUnavailable: boolean;
|
|
271
275
|
accountExists: boolean;
|
|
272
276
|
hasFetchedStatus: boolean;
|
|
273
277
|
start: (options?: BuilderConnectStartOptions) => void;
|
|
@@ -281,8 +285,6 @@ const POLL_TIMEOUT_MS = 5 * 60 * 1000;
|
|
|
281
285
|
export const POPUP_CLOSED_CONFIRMATION_GRACE_MS = 20_000;
|
|
282
286
|
const POPUP_LOAD_TIMEOUT_MS = 20_000;
|
|
283
287
|
const STATUS_FETCH_ABORT_MS = 10_000;
|
|
284
|
-
const BUILDER_STATUS_UNAVAILABLE_MESSAGE =
|
|
285
|
-
"Couldn't reach Builder to check your account. Retrying.";
|
|
286
288
|
const CALLBACK_SUCCESS_STATUS_RETRY_MS = 500;
|
|
287
289
|
const CALLBACK_SUCCESS_STATUS_RETRIES = 10;
|
|
288
290
|
const BUILDER_CONNECT_PARAM = "_an_connect";
|
|
@@ -841,6 +843,7 @@ export function useBuilderConnectFlow(
|
|
|
841
843
|
const [orgName, setOrgName] = useState<string | null>(null);
|
|
842
844
|
const [connecting, setConnecting] = useState(false);
|
|
843
845
|
const [error, setError] = useState<string | null>(null);
|
|
846
|
+
const [statusUnavailable, setStatusUnavailable] = useState(false);
|
|
844
847
|
const [accountExists, setAccountExists] = useState(false);
|
|
845
848
|
const [hasFetchedStatus, setHasFetchedStatus] = useState(false);
|
|
846
849
|
const [statusResolved, setStatusResolved] = useState(false);
|
|
@@ -868,6 +871,14 @@ export function useBuilderConnectFlow(
|
|
|
868
871
|
} | null>(null);
|
|
869
872
|
const retryStatusRef = useRef<() => boolean>(() => false);
|
|
870
873
|
const statusUnavailableRef = useRef(false);
|
|
874
|
+
const markStatusUnavailable = useCallback(() => {
|
|
875
|
+
statusUnavailableRef.current = true;
|
|
876
|
+
setStatusUnavailable(true);
|
|
877
|
+
}, []);
|
|
878
|
+
const markStatusAvailable = useCallback(() => {
|
|
879
|
+
statusUnavailableRef.current = false;
|
|
880
|
+
setStatusUnavailable(false);
|
|
881
|
+
}, []);
|
|
871
882
|
const statusPollFailuresRef = useRef(0);
|
|
872
883
|
const mountedRef = useRef(true);
|
|
873
884
|
const notifiedConnectedRef = useRef(false);
|
|
@@ -1018,6 +1029,7 @@ export function useBuilderConnectFlow(
|
|
|
1018
1029
|
setOrgName(null);
|
|
1019
1030
|
setConnecting(false);
|
|
1020
1031
|
setError(null);
|
|
1032
|
+
markStatusAvailable();
|
|
1021
1033
|
setAccountExists(false);
|
|
1022
1034
|
setHasFetchedStatus(false);
|
|
1023
1035
|
setStatusResolved(false);
|
|
@@ -1039,13 +1051,11 @@ export function useBuilderConnectFlow(
|
|
|
1039
1051
|
setHasFetchedStatus(true);
|
|
1040
1052
|
setStatusReadSettledCount((count) => count + 1);
|
|
1041
1053
|
if (!s) {
|
|
1042
|
-
|
|
1043
|
-
setError(BUILDER_STATUS_UNAVAILABLE_MESSAGE);
|
|
1054
|
+
markStatusUnavailable();
|
|
1044
1055
|
return;
|
|
1045
1056
|
}
|
|
1046
1057
|
if (statusUnavailableRef.current) {
|
|
1047
|
-
|
|
1048
|
-
setError(null);
|
|
1058
|
+
markStatusAvailable();
|
|
1049
1059
|
}
|
|
1050
1060
|
setStatusResolved(true);
|
|
1051
1061
|
setConfigured(!!s.configured);
|
|
@@ -1123,7 +1133,13 @@ export function useBuilderConnectFlow(
|
|
|
1123
1133
|
document.removeEventListener("visibilitychange", onVisible);
|
|
1124
1134
|
window.removeEventListener("agent-engine:configured-changed", refreshNow);
|
|
1125
1135
|
};
|
|
1126
|
-
}, [
|
|
1136
|
+
}, [
|
|
1137
|
+
enabled,
|
|
1138
|
+
fetchStatus,
|
|
1139
|
+
markStatusAvailable,
|
|
1140
|
+
markStatusUnavailable,
|
|
1141
|
+
notifyProvisionedAccount,
|
|
1142
|
+
]);
|
|
1127
1143
|
|
|
1128
1144
|
const retry = useCallback(() => retryStatusRef.current(), []);
|
|
1129
1145
|
const cancel = useCallback(() => {
|
|
@@ -1254,6 +1270,11 @@ export function useBuilderConnectFlow(
|
|
|
1254
1270
|
const freshProvisioningCredentials = async () => {
|
|
1255
1271
|
// coercion-ok: no fresh token is sent as none and refused as provision_token_invalid
|
|
1256
1272
|
const status = await fetchStatus();
|
|
1273
|
+
if (!status) {
|
|
1274
|
+
markStatusUnavailable();
|
|
1275
|
+
return null;
|
|
1276
|
+
}
|
|
1277
|
+
markStatusAvailable();
|
|
1257
1278
|
if (!status?.agentNativeProvisioningEnabled) return null;
|
|
1258
1279
|
const freshUrl = status?.connectUrl ?? null;
|
|
1259
1280
|
const freshConnectToken = freshUrl
|
|
@@ -1283,7 +1304,9 @@ export function useBuilderConnectFlow(
|
|
|
1283
1304
|
if (!credentials) {
|
|
1284
1305
|
connectStartedAtRef.current = null;
|
|
1285
1306
|
setConnecting(false);
|
|
1286
|
-
|
|
1307
|
+
if (!statusUnavailableRef.current) {
|
|
1308
|
+
setError(t("agentChat.settingsShell.builder.setupStartFailed"));
|
|
1309
|
+
}
|
|
1287
1310
|
return;
|
|
1288
1311
|
}
|
|
1289
1312
|
let result = await activate(credentials);
|
|
@@ -1317,6 +1340,8 @@ export function useBuilderConnectFlow(
|
|
|
1317
1340
|
// attempt with a retryable error.
|
|
1318
1341
|
const status = await fetchStatus();
|
|
1319
1342
|
if (!isCurrentAttempt()) return;
|
|
1343
|
+
if (status) markStatusAvailable();
|
|
1344
|
+
else markStatusUnavailable();
|
|
1320
1345
|
if (
|
|
1321
1346
|
status &&
|
|
1322
1347
|
isBuilderConnectComplete(status, connectTargetRef.current)
|
|
@@ -1393,11 +1418,12 @@ export function useBuilderConnectFlow(
|
|
|
1393
1418
|
cancelledConnectAttemptIdRef.current !== connectAttemptId;
|
|
1394
1419
|
if (!isCurrentAttempt()) return;
|
|
1395
1420
|
if (!status) {
|
|
1421
|
+
markStatusUnavailable();
|
|
1396
1422
|
connectStartedAtRef.current = null;
|
|
1397
1423
|
setConnecting(false);
|
|
1398
|
-
setError(BUILDER_STATUS_UNAVAILABLE_MESSAGE);
|
|
1399
1424
|
return;
|
|
1400
1425
|
}
|
|
1426
|
+
markStatusAvailable();
|
|
1401
1427
|
setHasFetchedStatus(true);
|
|
1402
1428
|
setStatusResolved(true);
|
|
1403
1429
|
setConfigured(!!status.configured);
|
|
@@ -1432,7 +1458,7 @@ export function useBuilderConnectFlow(
|
|
|
1432
1458
|
) {
|
|
1433
1459
|
connectStartedAtRef.current = null;
|
|
1434
1460
|
setConnecting(false);
|
|
1435
|
-
setError(
|
|
1461
|
+
setError(t("agentChat.settingsShell.builder.setupStartFailed"));
|
|
1436
1462
|
return;
|
|
1437
1463
|
}
|
|
1438
1464
|
const result = await openDesktopConnectUrl({
|
|
@@ -1445,7 +1471,10 @@ export function useBuilderConnectFlow(
|
|
|
1445
1471
|
if (!result?.ok) {
|
|
1446
1472
|
connectStartedAtRef.current = null;
|
|
1447
1473
|
setConnecting(false);
|
|
1448
|
-
setError(
|
|
1474
|
+
setError(
|
|
1475
|
+
result?.error ??
|
|
1476
|
+
t("agentChat.settingsShell.builder.setupStartFailed"),
|
|
1477
|
+
);
|
|
1449
1478
|
}
|
|
1450
1479
|
})();
|
|
1451
1480
|
} else {
|
|
@@ -1474,6 +1503,8 @@ export function useBuilderConnectFlow(
|
|
|
1474
1503
|
) {
|
|
1475
1504
|
return;
|
|
1476
1505
|
}
|
|
1506
|
+
if (s) markStatusAvailable();
|
|
1507
|
+
else markStatusUnavailable();
|
|
1477
1508
|
if (s) {
|
|
1478
1509
|
setHasFetchedStatus(true);
|
|
1479
1510
|
setStatusResolved(true);
|
|
@@ -1537,6 +1568,8 @@ export function useBuilderConnectFlow(
|
|
|
1537
1568
|
}
|
|
1538
1569
|
return;
|
|
1539
1570
|
}
|
|
1571
|
+
if (s) markStatusAvailable();
|
|
1572
|
+
else markStatusUnavailable();
|
|
1540
1573
|
if (s) {
|
|
1541
1574
|
setHasFetchedStatus(true);
|
|
1542
1575
|
setStatusResolved(true);
|
|
@@ -1619,6 +1652,8 @@ export function useBuilderConnectFlow(
|
|
|
1619
1652
|
enabled,
|
|
1620
1653
|
t,
|
|
1621
1654
|
fetchStatus,
|
|
1655
|
+
markStatusAvailable,
|
|
1656
|
+
markStatusUnavailable,
|
|
1622
1657
|
transport,
|
|
1623
1658
|
agentNativeProvisioningEnabled,
|
|
1624
1659
|
agentNativeProvisioningToken,
|
|
@@ -1645,14 +1680,12 @@ export function useBuilderConnectFlow(
|
|
|
1645
1680
|
statusPollFailuresRef.current = 0;
|
|
1646
1681
|
} else {
|
|
1647
1682
|
statusPollFailuresRef.current += 1;
|
|
1648
|
-
|
|
1649
|
-
setError(BUILDER_STATUS_UNAVAILABLE_MESSAGE);
|
|
1683
|
+
markStatusUnavailable();
|
|
1650
1684
|
}
|
|
1651
1685
|
const orgName = s?.orgName ?? null;
|
|
1652
1686
|
if (s) {
|
|
1653
1687
|
if (statusUnavailableRef.current) {
|
|
1654
|
-
|
|
1655
|
-
setError(null);
|
|
1688
|
+
markStatusAvailable();
|
|
1656
1689
|
}
|
|
1657
1690
|
setHasFetchedStatus(true);
|
|
1658
1691
|
setStatusResolved(true);
|
|
@@ -1862,6 +1895,7 @@ export function useBuilderConnectFlow(
|
|
|
1862
1895
|
return;
|
|
1863
1896
|
}
|
|
1864
1897
|
if (!s) return;
|
|
1898
|
+
markStatusAvailable();
|
|
1865
1899
|
if (!isBuilderConnectComplete(s, connectTargetRef.current)) {
|
|
1866
1900
|
const connectError = isCurrentConnectError(s?.connectError, started)
|
|
1867
1901
|
? s?.connectError
|
|
@@ -1981,7 +2015,7 @@ export function useBuilderConnectFlow(
|
|
|
1981
2015
|
channel?.close();
|
|
1982
2016
|
window.removeEventListener("message", handler);
|
|
1983
2017
|
};
|
|
1984
|
-
}, [fetchStatus, notifyProvisionedAccount]);
|
|
2018
|
+
}, [fetchStatus, markStatusAvailable, notifyProvisionedAccount]);
|
|
1985
2019
|
|
|
1986
2020
|
return {
|
|
1987
2021
|
configured,
|
|
@@ -1999,7 +2033,13 @@ export function useBuilderConnectFlow(
|
|
|
1999
2033
|
builderEnabled,
|
|
2000
2034
|
orgName,
|
|
2001
2035
|
connecting,
|
|
2002
|
-
error,
|
|
2036
|
+
terminalError: error,
|
|
2037
|
+
error:
|
|
2038
|
+
error ??
|
|
2039
|
+
(statusUnavailable
|
|
2040
|
+
? t("agentChat.settingsShell.integrations.builderStatusFailed")
|
|
2041
|
+
: null),
|
|
2042
|
+
statusUnavailable,
|
|
2003
2043
|
accountExists,
|
|
2004
2044
|
hasFetchedStatus,
|
|
2005
2045
|
start,
|