@agent-native/toolkit 0.200.0 → 0.200.1-nightly-20261002213029

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/app/chat/AgentKitAssistantChat.js +2 -0
  2. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  3. package/dist/app/chat/AgentPanel.d.ts.map +1 -1
  4. package/dist/app/chat/AgentPanel.js +12 -99
  5. package/dist/app/chat/AgentPanel.js.map +1 -1
  6. package/dist/app/chat/ConnectBuilderCard.js +2 -2
  7. package/dist/app/chat/ConnectBuilderCard.js.map +1 -1
  8. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  9. package/dist/app/i18n/catalogs/ar-SA.js +36 -26
  10. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  11. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  12. package/dist/app/i18n/catalogs/de-DE.js +36 -26
  13. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  14. package/dist/app/i18n/catalogs/en-US.d.ts +36 -26
  15. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  16. package/dist/app/i18n/catalogs/en-US.js +36 -26
  17. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  18. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  19. package/dist/app/i18n/catalogs/es-ES.js +36 -26
  20. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  21. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  22. package/dist/app/i18n/catalogs/fr-FR.js +36 -26
  23. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  24. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  25. package/dist/app/i18n/catalogs/hi-IN.js +36 -26
  26. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  27. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  28. package/dist/app/i18n/catalogs/ja-JP.js +36 -26
  29. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  30. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  31. package/dist/app/i18n/catalogs/ko-KR.js +36 -26
  32. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  33. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  34. package/dist/app/i18n/catalogs/pt-BR.js +36 -26
  35. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  36. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  37. package/dist/app/i18n/catalogs/zh-CN.js +36 -26
  38. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  39. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  40. package/dist/app/i18n/catalogs/zh-TW.js +36 -26
  41. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  42. package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
  43. package/dist/app/onboarding/FirstRunOnboarding.js +3 -5
  44. package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
  45. package/dist/app/onboarding/NewWorkspaceAppFlow.d.ts.map +1 -1
  46. package/dist/app/onboarding/NewWorkspaceAppFlow.js +4 -2
  47. package/dist/app/onboarding/NewWorkspaceAppFlow.js.map +1 -1
  48. package/dist/app/onboarding/OnboardingPanel.d.ts.map +1 -1
  49. package/dist/app/onboarding/OnboardingPanel.js +3 -1
  50. package/dist/app/onboarding/OnboardingPanel.js.map +1 -1
  51. package/dist/app/settings/BuilderConnectPopover.d.ts +1 -0
  52. package/dist/app/settings/BuilderConnectPopover.d.ts.map +1 -1
  53. package/dist/app/settings/BuilderConnectPopover.js +11 -4
  54. package/dist/app/settings/BuilderConnectPopover.js.map +1 -1
  55. package/dist/app/settings/SettingsPanel.d.ts.map +1 -1
  56. package/dist/app/settings/SettingsPanel.js +16 -8
  57. package/dist/app/settings/SettingsPanel.js.map +1 -1
  58. package/dist/app/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  59. package/dist/app/settings/VoiceTranscriptionSection.js +7 -6
  60. package/dist/app/settings/VoiceTranscriptionSection.js.map +1 -1
  61. package/dist/app/settings/infra/InfrastructureSettingsPage.js +2 -2
  62. package/dist/app/settings/infra/InfrastructureSettingsPage.js.map +1 -1
  63. package/dist/app/settings/model/ModelSettingsPage.js +4 -2
  64. package/dist/app/settings/model/ModelSettingsPage.js.map +1 -1
  65. package/dist/app/settings/useBuilderStatus.d.ts +1 -0
  66. package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
  67. package/dist/app/settings/useBuilderStatus.js +43 -29
  68. package/dist/app/settings/useBuilderStatus.js.map +1 -1
  69. package/dist/app/setup-connections/SetupConnectionsPage.d.ts.map +1 -1
  70. package/dist/app/setup-connections/SetupConnectionsPage.js +4 -2
  71. package/dist/app/setup-connections/SetupConnectionsPage.js.map +1 -1
  72. package/dist/app/setup-connections/useBuilderConnectCardController.d.ts +1 -1
  73. package/dist/app/setup-connections/useBuilderConnectCardController.d.ts.map +1 -1
  74. package/dist/app/setup-connections/useBuilderConnectCardController.js +7 -6
  75. package/dist/app/setup-connections/useBuilderConnectCardController.js.map +1 -1
  76. package/dist/app/transcription/BuilderTranscriptionCta.d.ts.map +1 -1
  77. package/dist/app/transcription/BuilderTranscriptionCta.js +3 -1
  78. package/dist/app/transcription/BuilderTranscriptionCta.js.map +1 -1
  79. package/dist/composer/MessageQueueDrawer.d.ts +1 -1
  80. package/dist/composer/MessageQueueDrawer.d.ts.map +1 -1
  81. package/dist/composer/MessageQueueDrawer.js +10 -1
  82. package/dist/composer/MessageQueueDrawer.js.map +1 -1
  83. package/dist/composer/PromptComposer.d.ts +1 -1
  84. package/dist/composer/TiptapComposer.d.ts +1 -1
  85. package/dist/composer/TiptapComposer.js +4 -4
  86. package/dist/composer/TiptapComposer.js.map +1 -1
  87. package/dist/composer/useRealtimeVoiceMode.js +2 -2
  88. package/dist/composer/useRealtimeVoiceMode.js.map +1 -1
  89. package/package.json +4 -4
  90. package/src/app/chat/AgentKitAssistantChat.spec.tsx +30 -5
  91. package/src/app/chat/AgentKitAssistantChat.tsx +1 -0
  92. package/src/app/chat/AgentPanel.tsx +33 -112
  93. package/src/app/chat/ConnectBuilderCard.tsx +2 -2
  94. package/src/app/chat/chat/run-recovery.spec.tsx +8 -8
  95. package/src/app/i18n/catalogs/ar-SA.ts +46 -26
  96. package/src/app/i18n/catalogs/de-DE.ts +47 -26
  97. package/src/app/i18n/catalogs/en-US.ts +47 -26
  98. package/src/app/i18n/catalogs/es-ES.ts +47 -26
  99. package/src/app/i18n/catalogs/fr-FR.ts +48 -26
  100. package/src/app/i18n/catalogs/hi-IN.ts +47 -26
  101. package/src/app/i18n/catalogs/ja-JP.ts +47 -26
  102. package/src/app/i18n/catalogs/ko-KR.ts +47 -26
  103. package/src/app/i18n/catalogs/pt-BR.ts +48 -26
  104. package/src/app/i18n/catalogs/zh-CN.ts +47 -26
  105. package/src/app/i18n/catalogs/zh-TW.ts +47 -26
  106. package/src/app/integrations/BuilderIntegrationPage.spec.tsx +11 -7
  107. package/src/app/onboarding/FirstRunOnboarding.spec.tsx +24 -12
  108. package/src/app/onboarding/FirstRunOnboarding.tsx +14 -16
  109. package/src/app/onboarding/NewWorkspaceAppFlow.spec.ts +23 -7
  110. package/src/app/onboarding/NewWorkspaceAppFlow.tsx +4 -2
  111. package/src/app/onboarding/OnboardingPanel.tsx +4 -8
  112. package/src/app/settings/BuilderConnectPopover.spec.tsx +41 -1
  113. package/src/app/settings/BuilderConnectPopover.tsx +21 -4
  114. package/src/app/settings/SettingsPanel.connections.spec.tsx +2 -2
  115. package/src/app/settings/SettingsPanel.tsx +16 -8
  116. package/src/app/settings/VoiceTranscriptionSection.tsx +8 -7
  117. package/src/app/settings/infra/InfrastructureSettingsPage.spec.tsx +4 -4
  118. package/src/app/settings/infra/InfrastructureSettingsPage.tsx +5 -2
  119. package/src/app/settings/model/ModelSettingsPage.spec.tsx +7 -5
  120. package/src/app/settings/model/ModelSettingsPage.tsx +4 -2
  121. package/src/app/settings/useBuilderStatus.spec.tsx +82 -52
  122. package/src/app/settings/useBuilderStatus.ts +44 -54
  123. package/src/app/setup-connections/BuilderConnectCard.spec.tsx +11 -11
  124. package/src/app/setup-connections/SetupConnectionsPage.tsx +4 -2
  125. package/src/app/setup-connections/useBuilderConnectCardController.spec.tsx +19 -6
  126. package/src/app/setup-connections/useBuilderConnectCardController.ts +10 -9
  127. package/src/app/transcription/BuilderTranscriptionCta.tsx +4 -2
  128. package/src/composer/MessageQueueDrawer.spec.tsx +108 -0
  129. package/src/composer/MessageQueueDrawer.tsx +22 -2
  130. package/src/composer/PromptComposer.tsx +1 -1
  131. package/src/composer/RealtimeVoiceMode.spec.tsx +4 -4
  132. package/src/composer/TiptapComposer.tsx +5 -5
  133. package/src/composer/useRealtimeVoiceMode.tsx +2 -2
@@ -546,11 +546,7 @@ export function FirstRunOnboarding({
546
546
  handleFinish(null);
547
547
  return;
548
548
  }
549
- setBuilderConnectionMode(
550
- provisionAccount && canActivateBuilderFreeCredits
551
- ? "provision"
552
- : "existing",
553
- );
549
+ setBuilderConnectionMode(provisionAccount ? "provision" : "existing");
554
550
  setScreen("connecting");
555
551
  connectFlow.start({
556
552
  trackingSource: "first_run_onboarding",
@@ -731,10 +727,10 @@ export function FirstRunOnboarding({
731
727
  </div>
732
728
  <div className="flex flex-col gap-1 rounded-[10px] bg-emerald-50 px-4 py-3 dark:bg-emerald-950/30">
733
729
  <p className="text-[13px] font-semibold text-foreground">
734
- Included free with a Builder.io account
730
+ {t("agentChat.onboarding.builderIncludedFreeWithAccount")}
735
731
  </p>
736
732
  <p className="text-xs font-medium text-emerald-700 dark:text-emerald-400">
737
- 60 monthly Agent Credits
733
+ {t("agentChat.onboarding.builderMonthlyCredits")}
738
734
  </p>
739
735
  </div>
740
736
  <div className="flex flex-col gap-1">
@@ -772,15 +768,17 @@ export function FirstRunOnboarding({
772
768
  })}
773
769
  </div>
774
770
  <div className="flex flex-col gap-2">
775
- <button
776
- type="button"
777
- data-testid="first-run-builder-create-account"
778
- className={cn(ONBOARDING_PRIMARY_BUTTON_CLASS, "w-full")}
779
- onClick={() => handleBuilder(true)}
780
- disabled={connectFlow.connecting}
781
- >
782
- {t("agentChat.onboarding.builderCreateAccount")}
783
- </button>
771
+ {canActivateBuilderFreeCredits && (
772
+ <button
773
+ type="button"
774
+ data-testid="first-run-builder-create-account"
775
+ className={cn(ONBOARDING_PRIMARY_BUTTON_CLASS, "w-full")}
776
+ onClick={() => handleBuilder(true)}
777
+ disabled={connectFlow.connecting}
778
+ >
779
+ {t("agentChat.onboarding.builderCreateAccount")}
780
+ </button>
781
+ )}
784
782
  <button
785
783
  type="button"
786
784
  data-testid="first-run-builder-sign-in"
@@ -1,10 +1,14 @@
1
1
  // @vitest-environment happy-dom
2
+ import { AgentNativeI18nProvider } from "@agent-native/core/client/i18n";
2
3
  import React, { act } from "react";
3
4
  import { createRoot, type Root } from "react-dom/client";
4
5
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
6
 
7
+ import { createToolkitI18nCatalog } from "../i18n.js";
6
8
  import { NewWorkspaceAppFlow } from "./NewWorkspaceAppFlow.js";
7
9
 
10
+ const toolkitI18nCatalog = createToolkitI18nCatalog({ messages: {} });
11
+
8
12
  const sendToAgentChatMock = vi.hoisted(() => vi.fn());
9
13
  const frameState = vi.hoisted(() => ({ inBuilderFrame: false }));
10
14
  const devState = vi.hoisted(() => ({ isDevMode: false }));
@@ -190,7 +194,11 @@ describe("NewWorkspaceAppFlow", () => {
190
194
  async function renderAndSelectAccess() {
191
195
  await act(async () => {
192
196
  root.render(
193
- React.createElement(NewWorkspaceAppFlow, { dispatchBasePath: null }),
197
+ React.createElement(
198
+ AgentNativeI18nProvider,
199
+ { catalog: toolkitI18nCatalog, persistPreference: false },
200
+ React.createElement(NewWorkspaceAppFlow, { dispatchBasePath: null }),
201
+ ),
194
202
  );
195
203
  });
196
204
 
@@ -359,7 +367,11 @@ describe("NewWorkspaceAppFlow", () => {
359
367
  vaultState.mode = "all-apps";
360
368
  await act(async () => {
361
369
  root.render(
362
- React.createElement(NewWorkspaceAppFlow, { dispatchBasePath: null }),
370
+ React.createElement(
371
+ AgentNativeI18nProvider,
372
+ { catalog: toolkitI18nCatalog, persistPreference: false },
373
+ React.createElement(NewWorkspaceAppFlow, { dispatchBasePath: null }),
374
+ ),
363
375
  );
364
376
  });
365
377
 
@@ -388,7 +400,11 @@ describe("NewWorkspaceAppFlow", () => {
388
400
  root.unmount();
389
401
  root = createRoot(container);
390
402
  root.render(
391
- React.createElement(NewWorkspaceAppFlow, { dispatchBasePath: null }),
403
+ React.createElement(
404
+ AgentNativeI18nProvider,
405
+ { catalog: toolkitI18nCatalog, persistPreference: false },
406
+ React.createElement(NewWorkspaceAppFlow, { dispatchBasePath: null }),
407
+ ),
392
408
  );
393
409
  });
394
410
  await act(async () => {
@@ -412,7 +428,7 @@ describe("NewWorkspaceAppFlow", () => {
412
428
  );
413
429
  });
414
430
 
415
- it("renders a Connect Builder control when Builder is not connected", async () => {
431
+ it("renders a Use Builder.io control when Builder is not connected", async () => {
416
432
  startWorkspaceAppCreationResponse.result = {
417
433
  mode: "builder-unavailable",
418
434
  reason: "builder-not-connected",
@@ -430,7 +446,7 @@ describe("NewWorkspaceAppFlow", () => {
430
446
  );
431
447
  });
432
448
 
433
- const connectButton = findButton(container, "Connect Builder");
449
+ const connectButton = findButton(container, "Use Builder.io");
434
450
  act(() => {
435
451
  connectButton.click();
436
452
  });
@@ -464,7 +480,7 @@ describe("NewWorkspaceAppFlow", () => {
464
480
  matchingDivs.some((el) => el.className.includes("border-destructive")),
465
481
  ).toBe(true);
466
482
 
467
- expect(() => findButton(container, "Connect Builder")).toThrow();
483
+ expect(() => findButton(container, "Use Builder.io")).toThrow();
468
484
  expect(findButton(container, "Try again")).toBeTruthy();
469
485
  });
470
486
 
@@ -491,7 +507,7 @@ describe("NewWorkspaceAppFlow", () => {
491
507
  expect(
492
508
  matchingDivs.some((el) => el.className.includes("border-destructive")),
493
509
  ).toBe(false);
494
- expect(() => findButton(container, "Connect Builder")).toThrow();
510
+ expect(() => findButton(container, "Use Builder.io")).toThrow();
495
511
  expect(() => findButton(container, "Try again")).toThrow();
496
512
  });
497
513
  });
@@ -4,6 +4,7 @@ import {
4
4
  appBasePath,
5
5
  } from "@agent-native/core/client/api-path";
6
6
  import { isInBuilderFrame } from "@agent-native/core/client/builder-frame";
7
+ import { useT } from "@agent-native/core/client/i18n";
7
8
  import { useDevMode } from "@agent-native/core/client/use-dev-mode";
8
9
  import { docsUrl } from "@agent-native/core/shared/docs-url";
9
10
  import { getWorkspaceAppIdValidationError } from "@agent-native/core/shared/workspace-app-id";
@@ -173,6 +174,7 @@ export function NewWorkspaceAppFlow({
173
174
  className = "",
174
175
  dispatchBasePath,
175
176
  }: NewWorkspaceAppFlowProps) {
177
+ const t = useT();
176
178
  const [selectedSecretIds, setSelectedSecretIds] = useState<string[]>([]);
177
179
  const [selectedResourceIds, setSelectedResourceIds] = useState<string[]>([]);
178
180
  const [secrets, setSecrets] = useState<VaultSecretOption[]>([]);
@@ -425,8 +427,8 @@ export function NewWorkspaceAppFlow({
425
427
  className="inline-flex w-fit cursor-pointer items-center gap-1 rounded-md border border-border bg-background px-2.5 py-1 text-xs font-medium text-foreground hover:bg-accent/40 disabled:cursor-not-allowed disabled:opacity-60"
426
428
  >
427
429
  {connectFlow.connecting
428
- ? "Connecting..."
429
- : "Connect Builder"}
430
+ ? t("agentChat.composer.connectingBuilder")
431
+ : t("agentChat.setup.connectBuilder")}
430
432
  </button>
431
433
  </DeferredBuilderConnectPopover>
432
434
  <a
@@ -1,5 +1,6 @@
1
1
  import { sendToAgentChat } from "@agent-native/core/client/agent-chat";
2
2
  import { agentNativePath } from "@agent-native/core/client/api-path";
3
+ import { useT } from "@agent-native/core/client/i18n";
3
4
  import {
4
5
  trackOnboardingEvent,
5
6
  useOnboarding,
@@ -703,6 +704,7 @@ function BuilderCliAuthMethod({
703
704
  primary?: boolean;
704
705
  onClick: () => void;
705
706
  }) {
707
+ const t = useT();
706
708
  const connectFlow = useBuilderConnectFlow({
707
709
  provisionAccount: true,
708
710
  trackingSource: "onboarding_builder_cli_auth",
@@ -726,19 +728,13 @@ function BuilderCliAuthMethod({
726
728
  style={{ marginInlineEnd: 4 }}
727
729
  className="animate-spin"
728
730
  />
729
- Waiting for Builder...
731
+ {t("agentChat.onboarding.builderConnecting")}
730
732
  </>
731
733
  ) : (
732
- "Connect Builder"
734
+ t("agentChat.setup.connectBuilder")
733
735
  )}
734
736
  </button>
735
737
  </BuilderConnectPopover>
736
- {connecting && (
737
- <p style={styles.methodHint}>
738
- A Builder tab opened. Choose your team or app space there; setup will
739
- continue here automatically.
740
- </p>
741
- )}
742
738
  {error && <p style={styles.errText}>{error}</p>}
743
739
  </>
744
740
  );
@@ -57,6 +57,30 @@ function trigger() {
57
57
  }
58
58
 
59
59
  describe("BuilderConnectPopover before the status read resolves", () => {
60
+ it("uses existing-account sign-in when provisioning is unavailable", () => {
61
+ const onConnect = vi.fn();
62
+ const flow = {
63
+ connecting: false,
64
+ start: vi.fn(),
65
+ provisionAccount: true,
66
+ statusResolved: true,
67
+ agentNativeProvisioningEnabled: false,
68
+ };
69
+
70
+ render(
71
+ React.createElement(
72
+ BuilderConnectPopover,
73
+ { flow, onConnect },
74
+ trigger(),
75
+ ),
76
+ );
77
+
78
+ click(connectButton());
79
+
80
+ expect(onConnect).toHaveBeenCalledWith(false);
81
+ expect(flow.start).not.toHaveBeenCalled();
82
+ });
83
+
60
84
  it("never replays a queued click into the popup path", () => {
61
85
  const onConnect = vi.fn();
62
86
  const retry = vi.fn(() => true);
@@ -116,7 +140,12 @@ describe("BuilderConnectPopover before the status read resolves", () => {
116
140
  render(
117
141
  React.createElement(
118
142
  BuilderConnectPopover,
119
- { flow, onConnect, contentTestId: "consent" },
143
+ {
144
+ flow,
145
+ onConnect,
146
+ contentTestId: "consent",
147
+ primaryTestId: "create",
148
+ },
120
149
  trigger(),
121
150
  ),
122
151
  );
@@ -135,6 +164,7 @@ describe("BuilderConnectPopover before the status read resolves", () => {
135
164
  },
136
165
  onConnect,
137
166
  contentTestId: "consent",
167
+ primaryTestId: "create",
138
168
  },
139
169
  trigger(),
140
170
  ),
@@ -144,6 +174,12 @@ describe("BuilderConnectPopover before the status read resolves", () => {
144
174
  const consent = document.querySelector("[data-testid='consent']");
145
175
  expect(consent).not.toBeNull();
146
176
  expect(consent?.className).toContain("z-[330]");
177
+ const create = consent?.querySelector<HTMLButtonElement>(
178
+ "[data-testid='create']",
179
+ );
180
+ expect(create).not.toBeNull();
181
+ click(create!);
182
+ expect(onConnect).toHaveBeenCalledWith(true);
147
183
  });
148
184
 
149
185
  it("stacks the create and sign-in buttons together with the terms below them", () => {
@@ -189,6 +225,10 @@ describe("BuilderConnectPopover before the status read resolves", () => {
189
225
  p.querySelector("a"),
190
226
  );
191
227
  expect(create && signIn && terms).toBeTruthy();
228
+ expect(consent?.textContent).toContain(
229
+ "Included free with a Builder.io account",
230
+ );
231
+ expect(consent?.textContent).toContain("60 monthly Agent Credits");
192
232
  expect(signIn?.parentElement).toBe(create?.parentElement);
193
233
  expect(create!.compareDocumentPosition(signIn!)).toBe(
194
234
  Node.DOCUMENT_POSITION_FOLLOWING,
@@ -26,6 +26,7 @@ export interface BuilderConnectPopoverProps {
26
26
  statusResolved?: boolean;
27
27
  statusReadSettledCount?: number;
28
28
  canConnect?: BuilderConnectFlow["canConnect"];
29
+ provisionAccount?: boolean;
29
30
  };
30
31
  children: BuilderConnectTrigger;
31
32
  onConnect?: (provisionAccount: boolean) => void;
@@ -66,14 +67,18 @@ export function BuilderConnectPopover({
66
67
  }
67
68
  }, [accountExists]);
68
69
 
69
- const start = (provisionAccount: boolean) => {
70
+ const start = (provisionAccount?: boolean) => {
71
+ const shouldProvision =
72
+ provisionAccount ??
73
+ (flow.agentNativeProvisioningEnabled === true &&
74
+ (defaultProvisionAccount || flow.provisionAccount === true));
70
75
  initiatedByThisTriggerRef.current = true;
71
76
  setOpen(false);
72
77
  if (onConnect) {
73
- onConnect(provisionAccount);
78
+ onConnect(shouldProvision);
74
79
  return;
75
80
  }
76
- flow.start({ provisionAccount });
81
+ flow.start({ provisionAccount: shouldProvision });
77
82
  };
78
83
 
79
84
  const openQueuedPopoverRef = useRef<() => void>(() => {});
@@ -114,7 +119,7 @@ export function BuilderConnectPopover({
114
119
  }
115
120
  children.props.onClick?.(event);
116
121
  onTriggerClick?.(event);
117
- if (!showPopover && !event.defaultPrevented) start(false);
122
+ if (!showPopover && !event.defaultPrevented) start();
118
123
  },
119
124
  });
120
125
 
@@ -169,6 +174,18 @@ export function BuilderConnectPopover({
169
174
  ? t("agentChat.onboarding.builderOrgActivationDescription")
170
175
  : t("agentChat.onboarding.builderActivationDescription")}
171
176
  </p>
177
+ <div className="flex flex-col gap-1 rounded-[10px] bg-emerald-50 px-4 py-3 dark:bg-emerald-950/30">
178
+ <p className="text-[13px] font-semibold text-foreground">
179
+ {t("agentChat.onboarding.builderIncludedFreeWithAccount", {
180
+ defaultValue: "Included free with a Builder.io account",
181
+ })}
182
+ </p>
183
+ <p className="text-xs font-medium text-emerald-700 dark:text-emerald-400">
184
+ {t("agentChat.onboarding.builderMonthlyCredits", {
185
+ defaultValue: "60 monthly Agent Credits",
186
+ })}
187
+ </p>
188
+ </div>
172
189
  <div className="flex flex-col gap-2">
173
190
  <Button
174
191
  type="button"
@@ -330,7 +330,7 @@ describe("ConnectionsSettingsContent", () => {
330
330
 
331
331
  expect(
332
332
  Array.from(container.querySelectorAll("button")).filter((button) =>
333
- button.textContent?.includes("Connect Builder"),
333
+ button.textContent?.includes("Use Builder.io"),
334
334
  ),
335
335
  ).toHaveLength(0);
336
336
 
@@ -343,7 +343,7 @@ describe("ConnectionsSettingsContent", () => {
343
343
  await vi.waitFor(() => {
344
344
  const connectButtons = Array.from(
345
345
  container.querySelectorAll("button"),
346
- ).filter((button) => button.textContent?.includes("Connect Builder"));
346
+ ).filter((button) => button.textContent?.includes("Use Builder.io"));
347
347
  expect(connectButtons).toHaveLength(5);
348
348
 
349
349
  const solidPrimaryBtn = connectButtons.find((btn) =>
@@ -285,7 +285,7 @@ function UseBuilderCard({
285
285
  credentialSource,
286
286
  trackingSource = "settings_panel_builder_card",
287
287
  trackingFlow = "connect_llm",
288
- label = "Connect Builder.io",
288
+ label,
289
289
  subtitle = "Builder.io free credits to start - no API key needed.",
290
290
  dim,
291
291
  compact = false,
@@ -303,7 +303,9 @@ function UseBuilderCard({
303
303
  dim?: boolean;
304
304
  compact?: boolean;
305
305
  }) {
306
+ const t = useT();
306
307
  const isPage = useSettingsSurface() === "page";
308
+ const connectLabel = label ?? t("agentChat.setup.connectBuilder");
307
309
  const effectiveConnected = connected || builderFlow.configured;
308
310
  const effectiveOrgName = builderFlow.orgName ?? orgName;
309
311
  const effectiveCredentialSource =
@@ -350,7 +352,7 @@ function UseBuilderCard({
350
352
  {envManaged ? (
351
353
  <p className={cn("text-muted-foreground mt-1", bodyCls)}>
352
354
  {credentialSource === "env"
353
- ? "Deployment fallback is available. Connect your own account to override it."
355
+ ? t("agentChat.settingsInfra.builderOverrideDescription")
354
356
  : "Using your connected Builder account. Deployment fallback is still available."}
355
357
  </p>
356
358
  ) : null}
@@ -387,7 +389,9 @@ function UseBuilderCard({
387
389
  disabled={builderFlow.connecting}
388
390
  className="inline-flex shrink-0 items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:cursor-wait disabled:opacity-70"
389
391
  >
390
- {builderFlow.connecting ? "Connecting…" : "Connect Builder.io"}
392
+ {builderFlow.connecting
393
+ ? t("agentChat.composer.connectingBuilder")
394
+ : connectLabel}
391
395
  {builderFlow.connecting ? (
392
396
  <IconLoader2 size={14} className="animate-spin" />
393
397
  ) : null}
@@ -421,7 +425,9 @@ function UseBuilderCard({
421
425
  isPage ? "text-sm" : "text-[12px]",
422
426
  )}
423
427
  >
424
- {builderFlow.connecting ? "Connecting Builder.io..." : label}
428
+ {builderFlow.connecting
429
+ ? t("agentChat.composer.connectingBuilder")
430
+ : connectLabel}
425
431
  </span>
426
432
  {builderFlow.connecting && (
427
433
  <IconLoader2
@@ -465,7 +471,9 @@ function UseBuilderCard({
465
471
  isPage ? "text-sm" : "text-[11px]",
466
472
  )}
467
473
  >
468
- {builderFlow.connecting ? "Connecting…" : "Connect Builder.io"}
474
+ {builderFlow.connecting
475
+ ? t("agentChat.composer.connectingBuilder")
476
+ : connectLabel}
469
477
  {builderFlow.connecting ? (
470
478
  <IconLoader2 size={isPage ? 14 : 12} className="animate-spin" />
471
479
  ) : null}
@@ -1339,7 +1347,7 @@ function LLMSectionInner({
1339
1347
  credentialSource={credentialSource}
1340
1348
  trackingSource="llm_settings"
1341
1349
  trackingFlow="connect_llm"
1342
- label="Connect Builder.io"
1350
+ label={t("agentChat.setup.connectBuilder")}
1343
1351
  compact
1344
1352
  />
1345
1353
  )}
@@ -1372,7 +1380,7 @@ function LLMSectionInner({
1372
1380
  credentialSource={credentialSource}
1373
1381
  trackingSource="llm_settings"
1374
1382
  trackingFlow="connect_llm"
1375
- label="Connect Builder.io"
1383
+ label={t("agentChat.setup.connectBuilder")}
1376
1384
  />
1377
1385
  ) : undefined
1378
1386
  }
@@ -3911,7 +3919,7 @@ function SettingsPanelContent({
3911
3919
  trackingFlow="file_upload"
3912
3920
  />
3913
3921
  <ManualSetupCard
3914
- hint="Object storage keeps uploaded files durable and their URLs reusable throughout the thread. Connect Builder or use an S3-compatible bucket below."
3922
+ hint={t("agentChat.settingsInfra.builderStorageHint")}
3915
3923
  docsUrl={docsUrl("file-uploads", {
3916
3924
  campaign: "onboarding",
3917
3925
  content: "file_upload_settings",
@@ -126,6 +126,7 @@ function batchProvider(provider: Provider | null): Provider {
126
126
  export function VoiceTranscriptionSection({
127
127
  compact = false,
128
128
  }: { compact?: boolean } = {}) {
129
+ const t = useT();
129
130
  const [transcriptionMode, setTranscriptionMode] =
130
131
  useState<TranscriptionMode | null>(null);
131
132
  const [provider, setProvider] = useState<Provider>(DEFAULT_BATCH_PROVIDER);
@@ -445,7 +446,7 @@ export function VoiceTranscriptionSection({
445
446
  googleRealtimeReady
446
447
  ? "BYOK only for v1. Streams live partials and finals through Google Speech-to-Text."
447
448
  : googleRealtimeConfigured
448
- ? "Google credentials are set. Connect Builder completely (free tier available) to mint the managed realtime session."
449
+ ? t("agentChat.voiceMode.googleRealtimeDescription")
449
450
  : "BYOK only for v1. Configure Google service account before selecting this source."
450
451
  }
451
452
  rightSlot={
@@ -463,7 +464,7 @@ export function VoiceTranscriptionSection({
463
464
  type="button"
464
465
  className="inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:bg-accent/40 hover:text-foreground"
465
466
  >
466
- Connect Builder.io
467
+ {t("agentChat.setup.connectBuilder")}
467
468
  </button>
468
469
  </DeferredBuilderConnectPopover>
469
470
  ) : (
@@ -552,7 +553,7 @@ export function VoiceTranscriptionSection({
552
553
  title="Google Speech-to-Text service account"
553
554
  subtitle={
554
555
  googleRealtimeConfigured
555
- ? "Service-account JSON is set. Connect Builder (free tier available) to mint the managed realtime WebSocket session."
556
+ ? t("agentChat.voiceMode.serviceAccountRealtimeDescription")
556
557
  : "Service-account JSON for the dedicated realtime WebSocket to Google StreamingRecognize."
557
558
  }
558
559
  rightSlot={
@@ -571,7 +572,7 @@ export function VoiceTranscriptionSection({
571
572
  type="button"
572
573
  className="inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40"
573
574
  >
574
- Connect Builder.io
575
+ {t("agentChat.setup.connectBuilder")}
575
576
  </button>
576
577
  </DeferredBuilderConnectPopover>
577
578
  ) : (
@@ -605,11 +606,11 @@ export function VoiceTranscriptionSection({
605
606
  }
606
607
  onSelect={() => chooseBatchProvider("builder-gemini")}
607
608
  disabled={!builderStatus?.configured}
608
- title="Builder.io Connect"
609
+ title={t("agentChat.setup.connectBuilder")}
609
610
  subtitle={
610
611
  builderStatus?.configured
611
612
  ? "Use Builder-hosted Gemini Flash-Lite for batch transcription and Luna for text cleanup."
612
- : "One-click connect for Gemini Flash-Lite transcription and Luna text cleanup. No Google key needed."
613
+ : t("agentChat.voiceMode.builderGeminiDescription")
613
614
  }
614
615
  rightSlot={
615
616
  builderStatus?.configured ? (
@@ -626,7 +627,7 @@ export function VoiceTranscriptionSection({
626
627
  type="button"
627
628
  className="inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40"
628
629
  >
629
- Connect Builder.io
630
+ {t("agentChat.setup.connectBuilder")}
630
631
  </button>
631
632
  </DeferredBuilderConnectPopover>
632
633
  )
@@ -406,8 +406,8 @@ describe("InfrastructureSettingsPage", () => {
406
406
  const primaries = [...container.querySelectorAll("button")].filter(
407
407
  (candidate) => candidate.classList.contains("bg-primary"),
408
408
  );
409
- expect(primaries).toEqual([button(row("builder"), "Connect")]);
410
- act(() => button(row("builder"), "Connect").click());
409
+ expect(primaries).toEqual([button(row("builder"), "Use Builder.io")]);
410
+ act(() => button(row("builder"), "Use Builder.io").click());
411
411
  expect(state.builder.start).toHaveBeenCalledWith({
412
412
  provisionAccount: false,
413
413
  scope: "org",
@@ -426,10 +426,10 @@ describe("InfrastructureSettingsPage", () => {
426
426
  );
427
427
  expect(row(id).textContent).toContain("Available with Builder.io · ");
428
428
  expect(row(id).textContent).not.toContain("Not available");
429
- const connect = button(row(id), "Connect Builder.io");
429
+ const connect = button(row(id), "Use Builder.io");
430
430
  expect(connect.classList.contains("border")).toBe(true);
431
431
  }
432
- act(() => button(row("browser-automation"), "Connect Builder.io").click());
432
+ act(() => button(row("browser-automation"), "Use Builder.io").click());
433
433
  expect(state.builder.start).toHaveBeenCalledWith({
434
434
  provisionAccount: false,
435
435
  scope: "org",
@@ -390,7 +390,7 @@ function InfrastructurePageContent({
390
390
  disabled={flow.connecting}
391
391
  >
392
392
  {flow.connecting ? <Spinner aria-hidden /> : null}
393
- {flow.connecting ? t(`${K}connecting`) : label}
393
+ {flow.connecting ? t("agentChat.composer.connectingBuilder") : label}
394
394
  </Button>
395
395
  </DeferredBuilderConnectPopover>
396
396
  );
@@ -414,7 +414,10 @@ function InfrastructurePageContent({
414
414
  );
415
415
  } else if (recommendBuilder) {
416
416
  builderDescription = t(`${K}builderRecommended`);
417
- builderControl = connectBuilder("default", t(`${K}connect`));
417
+ builderControl = connectBuilder(
418
+ "default",
419
+ t("agentChat.setup.connectBuilder"),
420
+ );
418
421
  } else {
419
422
  builderDescription = t(`${K}builderNotConnected`);
420
423
  }
@@ -383,9 +383,11 @@ describe("ModelSettingsPage", () => {
383
383
  expect(buttons(row("provider-org-groq"))).toEqual([]);
384
384
 
385
385
  expect(row("provider-personal-builder").textContent).toContain(
386
- "Connect your own account to use it instead of the organization's.",
386
+ "Use your own Builder.io account instead of the organization's connection.",
387
387
  );
388
- expect(buttons(row("provider-personal-builder"))).toEqual(["Connect"]);
388
+ expect(buttons(row("provider-personal-builder"))).toEqual([
389
+ "Use Builder.io",
390
+ ]);
389
391
  act(() => {
390
392
  (
391
393
  row("provider-personal-builder").querySelector("button") as HTMLElement
@@ -640,7 +642,7 @@ describe("ModelSettingsPage", () => {
640
642
  "The agent needs a provider to respond. We recommend Builder.io for model access, browser automation, file storage, and workspace identity. Free tier available.",
641
643
  );
642
644
  expect(prominence(empty)).toEqual([
643
- "Connect Builder.io:primary",
645
+ "Use Builder.io:primary",
644
646
  "Add provider:outline",
645
647
  ]);
646
648
  // The empty state holds the page's one primary, so the header is empty.
@@ -670,7 +672,7 @@ describe("ModelSettingsPage", () => {
670
672
  act(() => {
671
673
  (
672
674
  [...empty.querySelectorAll("button")].find(
673
- (button) => button.textContent === "Connect Builder.io",
675
+ (button) => button.textContent === "Use Builder.io",
674
676
  ) as HTMLElement
675
677
  ).click();
676
678
  });
@@ -738,7 +740,7 @@ describe("ModelSettingsPage", () => {
738
740
  );
739
741
  const builderRow = row("provider-org-builder");
740
742
  expect(builderRow.textContent).toContain("Recommended");
741
- expect(prominence(builderRow)).toEqual(["Connect:outline"]);
743
+ expect(prominence(builderRow)).toEqual(["Use Builder.io:outline"]);
742
744
  });
743
745
 
744
746
  it("doesn't recommend a member's own Builder.io over the organization's connection", async () => {
@@ -397,7 +397,7 @@ function NoProviderEmpty({
397
397
  <Button type="button" size="sm" disabled={builder.connecting}>
398
398
  {builder.connecting ? <Spinner /> : null}
399
399
  {builder.connecting
400
- ? t(`${K}connecting`)
400
+ ? t("agentChat.composer.connectingBuilder")
401
401
  : t("agentChat.setup.connectBuilder")}
402
402
  </Button>
403
403
  </DeferredBuilderConnectPopover>
@@ -608,7 +608,9 @@ function BuilderRow({
608
608
  disabled={flow.connecting}
609
609
  >
610
610
  {flow.connecting ? <Spinner /> : null}
611
- {flow.connecting ? t(`${K}connecting`) : t(`${K}connect`)}
611
+ {flow.connecting
612
+ ? t("agentChat.composer.connectingBuilder")
613
+ : t("agentChat.setup.connectBuilder")}
612
614
  </Button>
613
615
  </DeferredBuilderConnectPopover>
614
616
  );