@agent-native/toolkit 0.207.0-nightly-20261011124220 → 0.207.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/agent-native.eject.json +1 -0
- package/dist/app/auth/AuthPage.d.ts.map +1 -1
- package/dist/app/auth/AuthPage.js +24 -55
- package/dist/app/auth/AuthPage.js.map +1 -1
- package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
- package/dist/app/chat/chat/run-recovery.js +21 -5
- package/dist/app/chat/chat/run-recovery.js.map +1 -1
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.d.ts.map +1 -1
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js +3 -2
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +11 -3
- 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 +11 -3
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +11 -3
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +11 -3
- 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 +11 -3
- 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 +11 -3
- 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 +11 -3
- 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 +11 -3
- 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 +11 -3
- 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 +11 -3
- 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 +11 -3
- 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 +11 -3
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.d.ts +2 -3
- package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.js +3 -4
- package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
- package/dist/app/onboarding/OnboardingBanner.d.ts.map +1 -1
- package/dist/app/onboarding/OnboardingBanner.js +37 -3
- package/dist/app/onboarding/OnboardingBanner.js.map +1 -1
- package/dist/app/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/app/onboarding/OnboardingPanel.js +49 -11
- package/dist/app/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/app/progress/RunsTray.d.ts.map +1 -1
- package/dist/app/progress/RunsTray.js +136 -17
- package/dist/app/progress/RunsTray.js.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.d.ts +1 -0
- package/dist/app/settings/BuilderConnectPopover.d.ts.map +1 -1
- package/dist/app/settings/BuilderConnectPopover.js +21 -5
- package/dist/app/settings/BuilderConnectPopover.js.map +1 -1
- package/dist/app/settings/shell/pages/audit.d.ts.map +1 -1
- package/dist/app/settings/shell/pages/audit.js +3 -3
- package/dist/app/settings/shell/pages/audit.js.map +1 -1
- package/dist/app/settings/useBuilderStatus.d.ts +1 -0
- package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/app/settings/useBuilderStatus.js +1 -0
- package/dist/app/settings/useBuilderStatus.js.map +1 -1
- package/dist/app/shared/AgentMark.d.ts +6 -0
- package/dist/app/shared/AgentMark.d.ts.map +1 -0
- package/dist/app/shared/AgentMark.js +5 -0
- package/dist/app/shared/AgentMark.js.map +1 -0
- package/dist/app/shared/index.d.ts +1 -0
- package/dist/app/shared/index.d.ts.map +1 -1
- package/dist/app/shared/index.js +1 -0
- package/dist/app/shared/index.js.map +1 -1
- package/dist/app/sharing/ShareButton.d.ts +1 -0
- package/dist/app/sharing/ShareButton.d.ts.map +1 -1
- package/dist/app/sharing/ShareButton.js +2 -2
- package/dist/app/sharing/ShareButton.js.map +1 -1
- package/dist/app/styles/agent-native.css +1 -0
- package/dist/app-shell/sidebar.d.ts.map +1 -1
- package/dist/app-shell/sidebar.js +3 -3
- package/dist/app-shell/sidebar.js.map +1 -1
- package/dist/sharing/ShareControls.d.ts +1 -0
- package/dist/sharing/ShareControls.d.ts.map +1 -1
- package/dist/sharing/ShareControls.js +5 -2
- package/dist/sharing/ShareControls.js.map +1 -1
- package/package.json +4 -4
- package/src/app/auth/AuthPage.attribution.spec.tsx +268 -0
- package/src/app/auth/AuthPage.tsx +27 -54
- package/src/app/chat/chat/run-recovery.spec.tsx +76 -0
- package/src/app/chat/chat/run-recovery.tsx +101 -23
- package/src/app/chat/chat-first/ChatFirstAgentActivityPanel.tsx +11 -5
- package/src/app/i18n/catalogs/ar-SA.ts +18 -3
- package/src/app/i18n/catalogs/de-DE.ts +19 -3
- package/src/app/i18n/catalogs/en-US.ts +18 -3
- package/src/app/i18n/catalogs/es-ES.ts +18 -3
- package/src/app/i18n/catalogs/fr-FR.ts +19 -3
- package/src/app/i18n/catalogs/hi-IN.ts +18 -3
- package/src/app/i18n/catalogs/ja-JP.ts +18 -3
- package/src/app/i18n/catalogs/ko-KR.ts +18 -3
- package/src/app/i18n/catalogs/pt-BR.ts +18 -3
- package/src/app/i18n/catalogs/zh-CN.ts +17 -3
- package/src/app/i18n/catalogs/zh-TW.ts +17 -3
- package/src/app/onboarding/FirstRunOnboarding.spec.tsx +49 -1
- package/src/app/onboarding/FirstRunOnboarding.tsx +4 -13
- package/src/app/onboarding/OnboardingBanner.tsx +70 -5
- package/src/app/onboarding/OnboardingPanel.save-scope.spec.tsx +143 -2
- package/src/app/onboarding/OnboardingPanel.tsx +72 -5
- package/src/app/progress/RunsTray.spec.tsx +577 -0
- package/src/app/progress/RunsTray.tsx +253 -51
- package/src/app/settings/BuilderConnectPopover.spec.tsx +39 -1
- package/src/app/settings/BuilderConnectPopover.tsx +27 -4
- package/src/app/settings/shell/pages/audit.tsx +7 -3
- package/src/app/settings/useBuilderStatus.spec.tsx +21 -1
- package/src/app/settings/useBuilderStatus.ts +2 -0
- package/src/app/shared/AgentMark.tsx +34 -0
- package/src/app/shared/index.ts +1 -0
- package/src/app/sharing/ShareButton.tsx +3 -0
- package/src/app/styles/agent-native.css +1 -0
- package/src/app-shell/sidebar.tsx +29 -21
- package/src/sharing/ShareControls.spec.tsx +36 -0
- package/src/sharing/ShareControls.tsx +17 -2
|
@@ -132,7 +132,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
132
132
|
"onboarding.roleOtherInputLabel": "Descreva sua função",
|
|
133
133
|
"onboarding.skipForNow": "Pular por enquanto",
|
|
134
134
|
"onboarding.saveRoleError": "Não foi possível salvar sua função.",
|
|
135
|
-
"onboarding.builderCreateAccount": "
|
|
135
|
+
"onboarding.builderCreateAccount": "Usar o Builder.io",
|
|
136
136
|
"onboarding.builderSignInWithAccount": "Entrar com uma conta do Builder.io",
|
|
137
137
|
"onboarding.builderActivateDescription":
|
|
138
138
|
"Crie ou reutilize sua conta do Builder.io e ative os créditos gratuitos com um clique.",
|
|
@@ -153,8 +153,17 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
153
153
|
"onboarding.builderAccountExistsTitle": "Você já tem uma conta do Builder.io",
|
|
154
154
|
"onboarding.builderAccountExistsDescription":
|
|
155
155
|
"Faça login para usar sua conta.",
|
|
156
|
+
"onboarding.builderActivationChecking":
|
|
157
|
+
"Verificando se a criação de uma nova conta está disponível.",
|
|
158
|
+
"onboarding.builderActivationUnavailable":
|
|
159
|
+
"A criação de novas contas não está ativada neste app. Você ainda pode conectar uma conta existente.",
|
|
160
|
+
"onboarding.builderActivationUnavailableInMode":
|
|
161
|
+
"A ativação de uma nova conta não está disponível neste modo. Você ainda pode conectar uma conta existente.",
|
|
162
|
+
"onboarding.builderActivationCheckFailed":
|
|
163
|
+
"Não foi possível verificar se este app pode criar novas contas.",
|
|
164
|
+
|
|
156
165
|
"onboarding.builderActivationDescription":
|
|
157
|
-
"Crie
|
|
166
|
+
"Crie uma nova conta para ativar créditos grátis ou continue com uma conta existente.",
|
|
158
167
|
"onboarding.builderOrgActivationDescription":
|
|
159
168
|
"Criaremos sua conta do Builder.io com um clique para que sua organização possa usá-la.",
|
|
160
169
|
"onboarding.builderCreateAndActivate": "Criar e ativar",
|
|
@@ -163,7 +172,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
163
172
|
"onboarding.builderTerms": "Termos de Serviço",
|
|
164
173
|
"onboarding.builderPrivacy": "Política de Privacidade",
|
|
165
174
|
"onboarding.builderConsentAnd": "e",
|
|
166
|
-
"onboarding.builderExistingAccount": "
|
|
175
|
+
"onboarding.builderExistingAccount": "Tenho uma conta Builder.io",
|
|
167
176
|
"onboarding.builderActivating":
|
|
168
177
|
"Ativando os créditos gratuitos do Builder.io",
|
|
169
178
|
"onboarding.builderConnecting":
|
|
@@ -893,6 +902,12 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
893
902
|
"secrets.usePersonalKey": "Usar uma chave pessoal",
|
|
894
903
|
"selection.attached": "{{formattedCount}} caracteres da seleção anexados",
|
|
895
904
|
"selection.clear": "Limpar contexto da seleção",
|
|
905
|
+
"setup.addKeyInSettings": "Adicionar uma chave nas Configurações",
|
|
906
|
+
"setup.addKeyInSettingsDescription": "Para sua conta ou organização.",
|
|
907
|
+
"setup.setEnvironmentVariable": "Definir uma variável de ambiente",
|
|
908
|
+
"setup.setEnvironmentVariableDescription":
|
|
909
|
+
"Uma chave de provedor para todos neste app.",
|
|
910
|
+
|
|
896
911
|
"setup.addOwnKeys": "Adicionar suas próprias chaves",
|
|
897
912
|
"setup.builderCredits":
|
|
898
913
|
"O Builder.io inclui créditos gratuitos, ou você pode usar sua própria chave de API.",
|
|
@@ -126,7 +126,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
126
126
|
"onboarding.roleOtherInputLabel": "描述你的角色",
|
|
127
127
|
"onboarding.skipForNow": "暂时跳过",
|
|
128
128
|
"onboarding.saveRoleError": "无法保存你的角色。",
|
|
129
|
-
"onboarding.builderCreateAccount": "
|
|
129
|
+
"onboarding.builderCreateAccount": "使用 Builder.io",
|
|
130
130
|
"onboarding.builderSignInWithAccount": "使用 Builder.io 账户登录",
|
|
131
131
|
"onboarding.builderActivateDescription":
|
|
132
132
|
"一键创建或重新使用您的 Builder.io 账户,并激活免费额度。",
|
|
@@ -145,8 +145,16 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
145
145
|
"onboarding.builderActivateTitle": "激活免费额度",
|
|
146
146
|
"onboarding.builderAccountExistsTitle": "您已有 Builder.io 账户",
|
|
147
147
|
"onboarding.builderAccountExistsDescription": "登录以使用你的账户。",
|
|
148
|
+
"onboarding.builderActivationChecking": "正在检查是否可以创建新账户。",
|
|
149
|
+
"onboarding.builderActivationUnavailable":
|
|
150
|
+
"此应用未启用新账户创建功能。你仍可连接现有账户。",
|
|
151
|
+
"onboarding.builderActivationUnavailableInMode":
|
|
152
|
+
"此模式下无法激活新账户。你仍然可以连接现有账户。",
|
|
153
|
+
"onboarding.builderActivationCheckFailed":
|
|
154
|
+
"无法确认此应用是否可以创建新账户。",
|
|
155
|
+
|
|
148
156
|
"onboarding.builderActivationDescription":
|
|
149
|
-
"
|
|
157
|
+
"创建新账户以激活免费额度,或使用现有账户继续。",
|
|
150
158
|
"onboarding.builderOrgActivationDescription":
|
|
151
159
|
"我们会一键创建你的 Builder.io 账户,让你的组织可以使用它。",
|
|
152
160
|
"onboarding.builderCreateAndActivate": "创建并激活",
|
|
@@ -154,7 +162,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
154
162
|
"onboarding.builderTerms": "服务条款",
|
|
155
163
|
"onboarding.builderPrivacy": "隐私政策",
|
|
156
164
|
"onboarding.builderConsentAnd": "和",
|
|
157
|
-
"onboarding.builderExistingAccount": "
|
|
165
|
+
"onboarding.builderExistingAccount": "我有 Builder.io 账户",
|
|
158
166
|
"onboarding.builderActivating": "正在激活 Builder.io 免费额度",
|
|
159
167
|
"onboarding.builderConnecting": "正在设置 Builder.io 免费额度",
|
|
160
168
|
"onboarding.builderProvisioningDescription":
|
|
@@ -1157,6 +1165,12 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
1157
1165
|
"selection.attached": "已附加选中内容的 {{formattedCount}} 个字符",
|
|
1158
1166
|
"selection.attached_other": "已附加选中内容的 {{formattedCount}} 个字符",
|
|
1159
1167
|
"selection.clear": "清除选中内容上下文",
|
|
1168
|
+
"setup.addKeyInSettings": "在设置中添加密钥",
|
|
1169
|
+
"setup.addKeyInSettingsDescription": "用于你的个人账户或组织。",
|
|
1170
|
+
"setup.setEnvironmentVariable": "设置环境变量",
|
|
1171
|
+
"setup.setEnvironmentVariableDescription":
|
|
1172
|
+
"此应用的所有用户共用一个提供商密钥。",
|
|
1173
|
+
|
|
1160
1174
|
"setup.addOwnKeys": "添加您自己的密钥",
|
|
1161
1175
|
"setup.builderCredits":
|
|
1162
1176
|
"Builder.io 提供免费额度,您也可以使用自己的 API 密钥。",
|
|
@@ -127,7 +127,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
127
127
|
"onboarding.roleOtherInputLabel": "描述你的角色",
|
|
128
128
|
"onboarding.skipForNow": "暫時略過",
|
|
129
129
|
"onboarding.saveRoleError": "無法儲存你的角色。",
|
|
130
|
-
"onboarding.builderCreateAccount": "
|
|
130
|
+
"onboarding.builderCreateAccount": "使用 Builder.io",
|
|
131
131
|
"onboarding.builderSignInWithAccount": "使用 Builder.io 帳戶登入",
|
|
132
132
|
"onboarding.builderActivateDescription":
|
|
133
133
|
"只要按一下即可建立或重新使用您的 Builder.io 帳戶,並啟用免費額度。",
|
|
@@ -146,8 +146,16 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
146
146
|
"onboarding.builderActivateTitle": "啟用免費額度",
|
|
147
147
|
"onboarding.builderAccountExistsTitle": "您已有 Builder.io 帳戶",
|
|
148
148
|
"onboarding.builderAccountExistsDescription": "登入以使用您的帳戶。",
|
|
149
|
+
"onboarding.builderActivationChecking": "正在確認是否可以建立新帳戶。",
|
|
150
|
+
"onboarding.builderActivationUnavailable":
|
|
151
|
+
"此應用程式未啟用新帳戶建立功能。你仍可連結現有帳戶。",
|
|
152
|
+
"onboarding.builderActivationUnavailableInMode":
|
|
153
|
+
"此模式無法啟用新帳戶。你仍可連結現有帳戶。",
|
|
154
|
+
"onboarding.builderActivationCheckFailed":
|
|
155
|
+
"無法確認此應用程式是否可以建立新帳戶。",
|
|
156
|
+
|
|
149
157
|
"onboarding.builderActivationDescription":
|
|
150
|
-
"
|
|
158
|
+
"建立新帳戶以啟用免費點數,或使用現有帳戶繼續。",
|
|
151
159
|
"onboarding.builderOrgActivationDescription":
|
|
152
160
|
"我們會一鍵建立您的 Builder.io 帳戶,讓您的組織可以使用。",
|
|
153
161
|
"onboarding.builderCreateAndActivate": "建立並啟用",
|
|
@@ -155,7 +163,7 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
155
163
|
"onboarding.builderTerms": "服務條款",
|
|
156
164
|
"onboarding.builderPrivacy": "隱私權政策",
|
|
157
165
|
"onboarding.builderConsentAnd": "和",
|
|
158
|
-
"onboarding.builderExistingAccount": "
|
|
166
|
+
"onboarding.builderExistingAccount": "我有 Builder.io 帳戶",
|
|
159
167
|
"onboarding.builderActivating": "正在啟用 Builder.io 免費額度",
|
|
160
168
|
"onboarding.builderConnecting": "正在設定 Builder.io 免費額度",
|
|
161
169
|
"onboarding.builderProvisioningDescription":
|
|
@@ -1161,6 +1169,12 @@ const messages: ToolkitAgentChatTranslation = {
|
|
|
1161
1169
|
"selection.attached": "已附加所選內容的 {{formattedCount}} 個字元",
|
|
1162
1170
|
"selection.attached_other": "已附加所選內容的 {{formattedCount}} 個字元",
|
|
1163
1171
|
"selection.clear": "清除所選內容的上下文",
|
|
1172
|
+
"setup.addKeyInSettings": "在設定中新增金鑰",
|
|
1173
|
+
"setup.addKeyInSettingsDescription": "供你的個人帳戶或組織使用。",
|
|
1174
|
+
"setup.setEnvironmentVariable": "設定環境變數",
|
|
1175
|
+
"setup.setEnvironmentVariableDescription":
|
|
1176
|
+
"此應用程式的所有使用者共用一個供應商金鑰。",
|
|
1177
|
+
|
|
1164
1178
|
"setup.addOwnKeys": "加入您自己的金鑰",
|
|
1165
1179
|
"setup.builderCredits":
|
|
1166
1180
|
"Builder.io 提供免費額度,您也可以使用自己的 API 金鑰。",
|
|
@@ -991,7 +991,7 @@ describe("FirstRunOnboarding", () => {
|
|
|
991
991
|
document.body.querySelector(
|
|
992
992
|
'[data-testid="first-run-builder-create-account"]',
|
|
993
993
|
)?.textContent,
|
|
994
|
-
).toBe("
|
|
994
|
+
).toBe("Use Builder.io");
|
|
995
995
|
expect(
|
|
996
996
|
document.body.querySelector('[data-testid="first-run-builder-sign-in"]')
|
|
997
997
|
?.textContent,
|
|
@@ -1567,6 +1567,54 @@ describe("FirstRunOnboarding", () => {
|
|
|
1567
1567
|
expect(document.body.textContent).not.toContain("This app is an agent.");
|
|
1568
1568
|
});
|
|
1569
1569
|
|
|
1570
|
+
it("labels Clips setup as Builder, custom keys, or an optional skip", async () => {
|
|
1571
|
+
mocks.useOnboarding.mockReturnValue({
|
|
1572
|
+
firstRun: true,
|
|
1573
|
+
loading: false,
|
|
1574
|
+
error: null,
|
|
1575
|
+
profile: { appId: "clips", appName: "Clips", capabilities: [] },
|
|
1576
|
+
completeFirstRun: mocks.completeFirstRun,
|
|
1577
|
+
completeFirstRunError: null,
|
|
1578
|
+
});
|
|
1579
|
+
|
|
1580
|
+
await act(async () => {
|
|
1581
|
+
root.render(
|
|
1582
|
+
<TooltipProvider>
|
|
1583
|
+
<FirstRunOnboarding />
|
|
1584
|
+
</TooltipProvider>,
|
|
1585
|
+
);
|
|
1586
|
+
await Promise.resolve();
|
|
1587
|
+
});
|
|
1588
|
+
|
|
1589
|
+
await act(async () => {
|
|
1590
|
+
document.body
|
|
1591
|
+
.querySelector('[data-testid="first-run-role-skip"]')
|
|
1592
|
+
?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
|
|
1593
|
+
await Promise.resolve();
|
|
1594
|
+
});
|
|
1595
|
+
|
|
1596
|
+
const builderButton = document.body.querySelector<HTMLButtonElement>(
|
|
1597
|
+
'[data-testid="first-run-builder-create-account"]',
|
|
1598
|
+
);
|
|
1599
|
+
const customKeysButton = document.body.querySelector<HTMLButtonElement>(
|
|
1600
|
+
'[data-testid="first-run-open-key-settings"]',
|
|
1601
|
+
);
|
|
1602
|
+
const customKeysCard = customKeysButton?.closest("section");
|
|
1603
|
+
|
|
1604
|
+
expect({
|
|
1605
|
+
builder: builderButton?.textContent,
|
|
1606
|
+
customKeys: customKeysCard?.querySelector("h2")?.textContent,
|
|
1607
|
+
customKeysAction: customKeysButton?.textContent,
|
|
1608
|
+
skip: document.body.querySelector('[data-testid="first-run-setup-skip"]')
|
|
1609
|
+
?.textContent,
|
|
1610
|
+
}).toEqual({
|
|
1611
|
+
builder: "Use Builder.io",
|
|
1612
|
+
customKeys: "Custom keys",
|
|
1613
|
+
customKeysAction: "Open AI key settings",
|
|
1614
|
+
skip: "Skip for now",
|
|
1615
|
+
});
|
|
1616
|
+
});
|
|
1617
|
+
|
|
1570
1618
|
it("opens the app directly after a configured Builder connection", () => {
|
|
1571
1619
|
mocks.useBuilderConnectFlow.mockReturnValue({
|
|
1572
1620
|
hasFetchedStatus: true,
|
|
@@ -145,9 +145,8 @@ const FIRST_RUN_ROLE_OPTIONS = [
|
|
|
145
145
|
] as const;
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
|
-
* Where
|
|
149
|
-
*
|
|
150
|
-
* provider is set up. API keys with the redesign off.
|
|
148
|
+
* Where the custom-key choice lands: Agent › Model, whose empty state adds a
|
|
149
|
+
* provider key in one click. API keys with the redesign off.
|
|
151
150
|
*/
|
|
152
151
|
export function manualSetupSettingsRoute({
|
|
153
152
|
redesign,
|
|
@@ -853,17 +852,9 @@ export function FirstRunOnboarding({
|
|
|
853
852
|
<section className="flex flex-col gap-5 rounded-2xl border border-border bg-card p-6">
|
|
854
853
|
<div className="flex flex-col gap-2">
|
|
855
854
|
<h2 className="text-lg font-bold text-foreground">
|
|
856
|
-
|
|
855
|
+
{t("agentChat.composer.addOwnKeys")}
|
|
857
856
|
</h2>
|
|
858
857
|
</div>
|
|
859
|
-
<div className="flex flex-col gap-1 rounded-xl bg-muted px-4 py-3">
|
|
860
|
-
<p className="text-[13px] font-semibold text-foreground">
|
|
861
|
-
You configure and maintain everything
|
|
862
|
-
</p>
|
|
863
|
-
<p className="text-xs text-muted-foreground">
|
|
864
|
-
Full control over your infrastructure
|
|
865
|
-
</p>
|
|
866
|
-
</div>
|
|
867
858
|
<CapabilityList
|
|
868
859
|
capabilities={profile.capabilities}
|
|
869
860
|
className="flex-1"
|
|
@@ -874,7 +865,7 @@ export function FirstRunOnboarding({
|
|
|
874
865
|
className={cn(secondaryButtonClass, "w-full")}
|
|
875
866
|
onClick={() => void handleOpenSettings()}
|
|
876
867
|
>
|
|
877
|
-
|
|
868
|
+
{t("agentChat.onboarding.openAiKeySettings")}
|
|
878
869
|
</button>
|
|
879
870
|
</section>
|
|
880
871
|
</div>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
1
2
|
import { useOnboarding } from "@agent-native/core/client/onboarding/use-onboarding";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
3
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
4
|
+
import {
|
|
5
|
+
IconChecklist,
|
|
6
|
+
IconChevronRight,
|
|
7
|
+
IconLoader2,
|
|
8
|
+
} from "@tabler/icons-react";
|
|
9
|
+
import React, { useState } from "react";
|
|
4
10
|
|
|
5
11
|
interface OnboardingBannerProps {
|
|
6
12
|
onContinue?: () => void;
|
|
@@ -11,9 +17,55 @@ export function OnboardingBanner({
|
|
|
11
17
|
onContinue,
|
|
12
18
|
className,
|
|
13
19
|
}: OnboardingBannerProps) {
|
|
14
|
-
const {
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
const {
|
|
21
|
+
loading,
|
|
22
|
+
totalCount,
|
|
23
|
+
completeCount,
|
|
24
|
+
allComplete,
|
|
25
|
+
dismissed,
|
|
26
|
+
error,
|
|
27
|
+
summaryKnown,
|
|
28
|
+
refresh,
|
|
29
|
+
} = useOnboarding();
|
|
30
|
+
const t = useT();
|
|
31
|
+
const [retrying, setRetrying] = useState(false);
|
|
32
|
+
|
|
33
|
+
if (
|
|
34
|
+
loading ||
|
|
35
|
+
(summaryKnown && (dismissed || (totalCount > 0 && allComplete)))
|
|
36
|
+
) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (error && (!summaryKnown || totalCount > 0)) {
|
|
40
|
+
const retry = async () => {
|
|
41
|
+
setRetrying(true);
|
|
42
|
+
try {
|
|
43
|
+
await refresh();
|
|
44
|
+
} finally {
|
|
45
|
+
setRetrying(false);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div role="alert" className={className} style={styles.error}>
|
|
51
|
+
<span>{t("agentChat.common.chunkLoadFailed")}</span>
|
|
52
|
+
<Button
|
|
53
|
+
type="button"
|
|
54
|
+
variant="outline"
|
|
55
|
+
size="xs"
|
|
56
|
+
data-testid="onboarding-summary-retry"
|
|
57
|
+
disabled={retrying}
|
|
58
|
+
onClick={() => void retry()}
|
|
59
|
+
>
|
|
60
|
+
{retrying ? (
|
|
61
|
+
<IconLoader2 className="animate-spin" aria-hidden />
|
|
62
|
+
) : null}
|
|
63
|
+
{t("agentChat.common.retry")}
|
|
64
|
+
</Button>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
if (!summaryKnown || totalCount === 0) return null;
|
|
17
69
|
|
|
18
70
|
return (
|
|
19
71
|
<button
|
|
@@ -38,6 +90,19 @@ export function OnboardingBanner({
|
|
|
38
90
|
}
|
|
39
91
|
|
|
40
92
|
const styles: Record<string, React.CSSProperties> = {
|
|
93
|
+
error: {
|
|
94
|
+
display: "flex",
|
|
95
|
+
flexWrap: "wrap",
|
|
96
|
+
alignItems: "center",
|
|
97
|
+
justifyContent: "space-between",
|
|
98
|
+
gap: 8,
|
|
99
|
+
width: "100%",
|
|
100
|
+
padding: "8px 12px",
|
|
101
|
+
borderBottom: "1px solid hsl(var(--border) / 0.7)",
|
|
102
|
+
background: "hsl(var(--muted) / 0.25)",
|
|
103
|
+
color: "hsl(var(--muted-foreground))",
|
|
104
|
+
fontSize: 12,
|
|
105
|
+
},
|
|
41
106
|
root: {
|
|
42
107
|
display: "flex",
|
|
43
108
|
alignItems: "center",
|
|
@@ -8,15 +8,26 @@ import { createRoot, type Root } from "react-dom/client";
|
|
|
8
8
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
9
9
|
|
|
10
10
|
let steps: OnboardingStepStatus[] = [];
|
|
11
|
+
let onboardingError: string | null = null;
|
|
12
|
+
let dismissed = false;
|
|
13
|
+
let summaryKnown = true;
|
|
14
|
+
let refresh = vi.fn(async () => {});
|
|
11
15
|
vi.mock("@agent-native/core/client/onboarding/use-onboarding", () => ({
|
|
12
16
|
createOnboardingCorrelationId: () => "test-onboarding-correlation-id",
|
|
13
17
|
trackOnboardingEvent: vi.fn(),
|
|
14
18
|
useOnboarding: () => ({
|
|
15
19
|
steps,
|
|
16
20
|
currentStepId: steps[0]?.id ?? null,
|
|
17
|
-
|
|
21
|
+
completeCount: steps.filter((step) => step.complete).length,
|
|
22
|
+
totalCount: steps.length,
|
|
23
|
+
allComplete:
|
|
24
|
+
steps.length > 0 &&
|
|
25
|
+
steps.filter((step) => step.required).every((step) => step.complete),
|
|
26
|
+
dismissed,
|
|
27
|
+
summaryKnown,
|
|
18
28
|
loading: false,
|
|
19
|
-
|
|
29
|
+
error: onboardingError,
|
|
30
|
+
refresh,
|
|
20
31
|
complete: vi.fn(),
|
|
21
32
|
dismiss: vi.fn(),
|
|
22
33
|
}),
|
|
@@ -28,6 +39,7 @@ vi.mock("@agent-native/core/client/use-dev-mode", () => ({
|
|
|
28
39
|
useDevMode: () => ({ isDevMode: false }),
|
|
29
40
|
}));
|
|
30
41
|
|
|
42
|
+
import { OnboardingBanner } from "./OnboardingBanner.js";
|
|
31
43
|
import { OnboardingPanel } from "./OnboardingPanel.js";
|
|
32
44
|
|
|
33
45
|
function json(body: unknown): Response {
|
|
@@ -69,9 +81,30 @@ afterEach(() => {
|
|
|
69
81
|
container?.remove();
|
|
70
82
|
root = null;
|
|
71
83
|
container = null;
|
|
84
|
+
steps = [];
|
|
85
|
+
onboardingError = null;
|
|
86
|
+
dismissed = false;
|
|
87
|
+
summaryKnown = true;
|
|
88
|
+
refresh = vi.fn(async () => {});
|
|
72
89
|
vi.unstubAllGlobals();
|
|
73
90
|
});
|
|
74
91
|
|
|
92
|
+
async function renderOnboarding(child: React.ReactNode): Promise<void> {
|
|
93
|
+
container = document.createElement("div");
|
|
94
|
+
document.body.appendChild(container);
|
|
95
|
+
root = createRoot(container);
|
|
96
|
+
const queryClient = new QueryClient({
|
|
97
|
+
defaultOptions: { queries: { retry: false } },
|
|
98
|
+
});
|
|
99
|
+
await act(async () => {
|
|
100
|
+
root!.render(
|
|
101
|
+
<QueryClientProvider client={queryClient}>
|
|
102
|
+
<TooltipProvider>{child}</TooltipProvider>
|
|
103
|
+
</QueryClientProvider>,
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
75
108
|
async function saveAs(
|
|
76
109
|
role: "member" | "admin",
|
|
77
110
|
saveTo?: "scoped-secrets",
|
|
@@ -156,4 +189,112 @@ describe("onboarding form save scope", () => {
|
|
|
156
189
|
const [secretSave] = await saveAs("admin", "scoped-secrets");
|
|
157
190
|
expect(secretSave.body.scope).toBe("workspace");
|
|
158
191
|
});
|
|
192
|
+
|
|
193
|
+
it("shows retry only when the initial summary is unavailable", async () => {
|
|
194
|
+
steps = [formStep()];
|
|
195
|
+
onboardingError = "summary: 503";
|
|
196
|
+
summaryKnown = false;
|
|
197
|
+
refresh = vi.fn(async () => {});
|
|
198
|
+
await renderOnboarding(<OnboardingPanel />);
|
|
199
|
+
|
|
200
|
+
const retry = container?.querySelector<HTMLButtonElement>(
|
|
201
|
+
'[data-testid="onboarding-summary-retry"]',
|
|
202
|
+
);
|
|
203
|
+
expect(container?.querySelector('[role="alert"]')).not.toBeNull();
|
|
204
|
+
expect(container?.textContent).not.toContain("Example keys");
|
|
205
|
+
expect(retry).not.toBeNull();
|
|
206
|
+
await act(async () => retry?.click());
|
|
207
|
+
expect(refresh).toHaveBeenCalledOnce();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("keeps known steps visible while showing a summary retry state", async () => {
|
|
211
|
+
steps = [formStep()];
|
|
212
|
+
onboardingError = "summary: 503";
|
|
213
|
+
await renderOnboarding(<OnboardingPanel />);
|
|
214
|
+
|
|
215
|
+
expect(container?.querySelector('[role="alert"]')).not.toBeNull();
|
|
216
|
+
expect(container?.textContent).toContain("Example keys");
|
|
217
|
+
expect(
|
|
218
|
+
container?.querySelector('[data-testid="onboarding-summary-retry"]'),
|
|
219
|
+
).not.toBeNull();
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it("shows a retry-only banner when the initial summary is unavailable", async () => {
|
|
223
|
+
steps = [formStep()];
|
|
224
|
+
onboardingError = "summary: 503";
|
|
225
|
+
summaryKnown = false;
|
|
226
|
+
refresh = vi.fn(async () => {});
|
|
227
|
+
await renderOnboarding(<OnboardingBanner />);
|
|
228
|
+
|
|
229
|
+
const retry = container?.querySelector<HTMLButtonElement>(
|
|
230
|
+
'[data-testid="onboarding-summary-retry"]',
|
|
231
|
+
);
|
|
232
|
+
expect(container?.querySelector('[role="alert"]')).not.toBeNull();
|
|
233
|
+
expect(container?.textContent).not.toContain("Example keys");
|
|
234
|
+
expect(container?.textContent).not.toContain("Continue");
|
|
235
|
+
expect(retry).not.toBeNull();
|
|
236
|
+
await act(async () => retry?.click());
|
|
237
|
+
expect(refresh).toHaveBeenCalledOnce();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("shows a retry action on the banner for a known active summary", async () => {
|
|
241
|
+
steps = [formStep()];
|
|
242
|
+
onboardingError = "summary: 503";
|
|
243
|
+
summaryKnown = true;
|
|
244
|
+
refresh = vi.fn(async () => {});
|
|
245
|
+
await renderOnboarding(<OnboardingBanner />);
|
|
246
|
+
|
|
247
|
+
const retry = container?.querySelector<HTMLButtonElement>(
|
|
248
|
+
'[data-testid="onboarding-summary-retry"]',
|
|
249
|
+
);
|
|
250
|
+
expect(container?.querySelector('[role="alert"]')).not.toBeNull();
|
|
251
|
+
expect(retry).not.toBeNull();
|
|
252
|
+
await act(async () => retry?.click());
|
|
253
|
+
expect(refresh).toHaveBeenCalledOnce();
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it("hides summary errors after onboarding is dismissed", async () => {
|
|
257
|
+
dismissed = true;
|
|
258
|
+
summaryKnown = true;
|
|
259
|
+
onboardingError = "summary: 503";
|
|
260
|
+
|
|
261
|
+
await renderOnboarding(
|
|
262
|
+
<>
|
|
263
|
+
<OnboardingBanner />
|
|
264
|
+
<OnboardingPanel />
|
|
265
|
+
</>,
|
|
266
|
+
);
|
|
267
|
+
expect(container?.querySelector('[role="alert"]')).toBeNull();
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it("hides summary errors after all required steps are complete", async () => {
|
|
271
|
+
steps = [{ ...formStep(), complete: true }];
|
|
272
|
+
summaryKnown = true;
|
|
273
|
+
onboardingError = "summary: 503";
|
|
274
|
+
|
|
275
|
+
await renderOnboarding(
|
|
276
|
+
<>
|
|
277
|
+
<OnboardingBanner />
|
|
278
|
+
<OnboardingPanel />
|
|
279
|
+
</>,
|
|
280
|
+
);
|
|
281
|
+
expect(container?.querySelector('[role="alert"]')).toBeNull();
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it("keeps the retry notice visible while the panel is collapsed", async () => {
|
|
285
|
+
steps = [formStep()];
|
|
286
|
+
summaryKnown = true;
|
|
287
|
+
onboardingError = "summary: 503";
|
|
288
|
+
await renderOnboarding(<OnboardingPanel />);
|
|
289
|
+
|
|
290
|
+
const collapse = container?.querySelector<HTMLButtonElement>(
|
|
291
|
+
'[aria-label="Collapse onboarding"]',
|
|
292
|
+
);
|
|
293
|
+
await act(async () => collapse?.click());
|
|
294
|
+
|
|
295
|
+
expect(container?.querySelector('[role="alert"]')).not.toBeNull();
|
|
296
|
+
expect(
|
|
297
|
+
container?.querySelector('[data-testid="onboarding-summary-retry"]'),
|
|
298
|
+
).not.toBeNull();
|
|
299
|
+
});
|
|
159
300
|
});
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
OnboardingMethod,
|
|
13
13
|
OnboardingStepStatus,
|
|
14
14
|
} from "@agent-native/core/onboarding/types";
|
|
15
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
15
16
|
import {
|
|
16
17
|
Tooltip,
|
|
17
18
|
TooltipContent,
|
|
@@ -56,10 +57,13 @@ export function OnboardingPanel({
|
|
|
56
57
|
currentStepId: rawCurrentStepId,
|
|
57
58
|
dismissed,
|
|
58
59
|
loading,
|
|
60
|
+
error,
|
|
61
|
+
summaryKnown,
|
|
59
62
|
refresh,
|
|
60
63
|
complete,
|
|
61
64
|
dismiss,
|
|
62
65
|
} = onboarding;
|
|
66
|
+
const t = useT();
|
|
63
67
|
const DEV_ONLY_STEP_IDS = new Set(["database", "auth"]);
|
|
64
68
|
const steps = isDevMode
|
|
65
69
|
? rawSteps
|
|
@@ -75,6 +79,7 @@ export function OnboardingPanel({
|
|
|
75
79
|
const checklistVisible =
|
|
76
80
|
!loading && totalCount > 0 && (previewMode || (!dismissed && !allComplete));
|
|
77
81
|
const [expanded, setExpanded] = useState(true);
|
|
82
|
+
const [retrying, setRetrying] = useState(false);
|
|
78
83
|
const stepViewRef = useRef<{ key: string; id: string } | null>(null);
|
|
79
84
|
|
|
80
85
|
useEffect(() => {
|
|
@@ -102,12 +107,58 @@ export function OnboardingPanel({
|
|
|
102
107
|
});
|
|
103
108
|
}, [checklistVisible, currentStepId, expanded, previewMode, steps]);
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
const handleRetry = async () => {
|
|
111
|
+
setRetrying(true);
|
|
112
|
+
try {
|
|
113
|
+
await refresh();
|
|
114
|
+
} finally {
|
|
115
|
+
setRetrying(false);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const errorNotice =
|
|
119
|
+
error &&
|
|
120
|
+
(previewMode ||
|
|
121
|
+
!summaryKnown ||
|
|
122
|
+
(totalCount > 0 && !dismissed && !allComplete)) ? (
|
|
123
|
+
<div role="alert" style={styles.errorNotice}>
|
|
124
|
+
<span>{t("agentChat.common.chunkLoadFailed")}</span>
|
|
125
|
+
<Button
|
|
126
|
+
type="button"
|
|
127
|
+
variant="outline"
|
|
128
|
+
size="xs"
|
|
129
|
+
data-testid="onboarding-summary-retry"
|
|
130
|
+
disabled={retrying}
|
|
131
|
+
onClick={() => void handleRetry()}
|
|
132
|
+
>
|
|
133
|
+
{retrying ? (
|
|
134
|
+
<IconLoader2 className="animate-spin" aria-hidden />
|
|
135
|
+
) : null}
|
|
136
|
+
{t("agentChat.common.retry")}
|
|
137
|
+
</Button>
|
|
138
|
+
</div>
|
|
139
|
+
) : null;
|
|
110
140
|
|
|
141
|
+
if (loading) return null;
|
|
142
|
+
if (!previewMode && !summaryKnown) {
|
|
143
|
+
if (!errorNotice) return null;
|
|
144
|
+
return (
|
|
145
|
+
<div className={className} style={styles.errorOnly}>
|
|
146
|
+
{errorNotice}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
if (!previewMode && (dismissed || (totalCount > 0 && allComplete))) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
if (error && totalCount === 0) {
|
|
154
|
+
if (!errorNotice) return null;
|
|
155
|
+
return (
|
|
156
|
+
<div className={className} style={styles.errorOnly}>
|
|
157
|
+
{errorNotice}
|
|
158
|
+
</div>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
if (totalCount === 0) return null;
|
|
111
162
|
if (!expanded) {
|
|
112
163
|
return (
|
|
113
164
|
<div className={className} style={styles.compactBanner}>
|
|
@@ -139,6 +190,7 @@ export function OnboardingPanel({
|
|
|
139
190
|
</TooltipTrigger>
|
|
140
191
|
<TooltipContent>Expand setup</TooltipContent>
|
|
141
192
|
</Tooltip>
|
|
193
|
+
{errorNotice}
|
|
142
194
|
</div>
|
|
143
195
|
);
|
|
144
196
|
}
|
|
@@ -174,6 +226,8 @@ export function OnboardingPanel({
|
|
|
174
226
|
</Tooltip>
|
|
175
227
|
</div>
|
|
176
228
|
|
|
229
|
+
{errorNotice}
|
|
230
|
+
|
|
177
231
|
<div style={styles.list}>
|
|
178
232
|
{steps.map((step) => (
|
|
179
233
|
<StepCard
|
|
@@ -853,6 +907,19 @@ function badgeStyle(
|
|
|
853
907
|
}
|
|
854
908
|
|
|
855
909
|
const styles: Record<string, React.CSSProperties> = {
|
|
910
|
+
errorOnly: {
|
|
911
|
+
borderBottom: "1px solid hsl(var(--border) / 0.7)",
|
|
912
|
+
background: "hsl(var(--muted) / 0.25)",
|
|
913
|
+
fontSize: 12,
|
|
914
|
+
},
|
|
915
|
+
errorNotice: {
|
|
916
|
+
display: "flex",
|
|
917
|
+
alignItems: "center",
|
|
918
|
+
justifyContent: "space-between",
|
|
919
|
+
gap: 8,
|
|
920
|
+
padding: "8px 12px",
|
|
921
|
+
color: "hsl(var(--muted-foreground))",
|
|
922
|
+
},
|
|
856
923
|
root: {
|
|
857
924
|
borderBottom: "1px solid hsl(var(--border) / 0.7)",
|
|
858
925
|
background: "hsl(var(--muted) / 0.25)",
|