@agent-native/core 0.193.0 → 0.193.1-nightly-20260926220417
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/corpus/README.md +1 -1
- package/corpus/templates/assets/changelog/2026-09-26-builder-is-the-primary-first-run-setup.md +6 -0
- package/corpus/templates/chat/app/components/chat/ChatRouteContent.tsx +93 -0
- package/corpus/templates/chat/app/i18n/en-US.ts +2 -0
- package/corpus/templates/chat/changelog/2026-09-26-builder-setup-retry.md +6 -0
- package/corpus/templates/clips/changelog/2026-09-26-builder-is-the-primary-first-run-setup.md +6 -0
- package/corpus/templates/design/changelog/2026-09-26-builder-is-the-primary-first-run-setup.md +6 -0
- package/corpus/templates/slides/changelog/2026-09-26-builder-is-the-primary-first-run-setup.md +6 -0
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/chat/agentkit-protocol.js +18 -1
- package/dist/client/chat/run-recovery.d.ts +1 -0
- package/dist/client/chat/run-recovery.js +1 -1
- package/dist/client/onboarding/FirstRunOnboarding.js +59 -22
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.js +1 -0
- package/dist/localization/core-messages/de-DE.js +1 -0
- package/dist/localization/core-messages/en-US.d.ts +1 -0
- package/dist/localization/core-messages/en-US.js +1 -0
- package/dist/localization/core-messages/es-ES.js +1 -0
- package/dist/localization/core-messages/fr-FR.js +1 -0
- package/dist/localization/core-messages/hi-IN.js +1 -0
- package/dist/localization/core-messages/ja-JP.js +1 -0
- package/dist/localization/core-messages/ko-KR.js +1 -0
- package/dist/localization/core-messages/pt-BR.js +1 -0
- package/dist/localization/core-messages/zh-CN.js +1 -0
- package/dist/localization/core-messages/zh-TW.js +1 -0
- package/dist/localization/core-messages.d.ts +1 -0
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/templates/chat/app/components/chat/ChatRouteContent.tsx +93 -0
- package/dist/templates/chat/app/i18n/ar-SA.ts +1 -0
- package/dist/templates/chat/app/i18n/de-DE.ts +2 -0
- package/dist/templates/chat/app/i18n/en-US.ts +2 -0
- package/dist/templates/chat/app/i18n/es-ES.ts +2 -0
- package/dist/templates/chat/app/i18n/fr-FR.ts +2 -0
- package/dist/templates/chat/app/i18n/hi-IN.ts +2 -0
- package/dist/templates/chat/app/i18n/ja-JP.ts +2 -0
- package/dist/templates/chat/app/i18n/ko-KR.ts +2 -0
- package/dist/templates/chat/app/i18n/pt-BR.ts +2 -0
- package/dist/templates/chat/app/i18n/zh-CN.ts +1 -0
- package/dist/templates/chat/app/i18n/zh-TW.ts +1 -0
- package/dist/templates/chat/changelog/2026-09-26-builder-setup-retry.md +6 -0
- package/package.json +1 -1
- package/src/templates/chat/app/components/chat/ChatRouteContent.tsx +93 -0
- package/src/templates/chat/app/i18n/ar-SA.ts +1 -0
- package/src/templates/chat/app/i18n/de-DE.ts +2 -0
- package/src/templates/chat/app/i18n/en-US.ts +2 -0
- package/src/templates/chat/app/i18n/es-ES.ts +2 -0
- package/src/templates/chat/app/i18n/fr-FR.ts +2 -0
- package/src/templates/chat/app/i18n/hi-IN.ts +2 -0
- package/src/templates/chat/app/i18n/ja-JP.ts +2 -0
- package/src/templates/chat/app/i18n/ko-KR.ts +2 -0
- package/src/templates/chat/app/i18n/pt-BR.ts +2 -0
- package/src/templates/chat/app/i18n/zh-CN.ts +1 -0
- package/src/templates/chat/app/i18n/zh-TW.ts +1 -0
- package/src/templates/chat/changelog/2026-09-26-builder-setup-retry.md +6 -0
package/corpus/README.md
CHANGED
|
@@ -3,6 +3,8 @@ import type {
|
|
|
3
3
|
AgentMessage,
|
|
4
4
|
} from "@agent-native/agentkit";
|
|
5
5
|
import {
|
|
6
|
+
AgentMessageView,
|
|
7
|
+
AgentRunFailure,
|
|
6
8
|
AgentConnectionRequestCard,
|
|
7
9
|
AgentKitChat,
|
|
8
10
|
} from "@agent-native/agentkit/react/components";
|
|
@@ -10,9 +12,14 @@ import {
|
|
|
10
12
|
useAgentKit,
|
|
11
13
|
useAgentKitControl,
|
|
12
14
|
useAgentThread,
|
|
15
|
+
type AgentRunFailureRenderProps,
|
|
13
16
|
type AgentKitRenderProps,
|
|
14
17
|
} from "@agent-native/agentkit/react/context";
|
|
15
18
|
import { AgentKitRoot } from "@agent-native/agentkit/react/root";
|
|
19
|
+
import {
|
|
20
|
+
BuilderSetupCard,
|
|
21
|
+
isMissingLlmProviderRunError,
|
|
22
|
+
} from "@agent-native/core/client/agent-chat";
|
|
16
23
|
import { CoreComposerRuntimeProvider } from "@agent-native/core/client/agentkit-chat/composer";
|
|
17
24
|
import {
|
|
18
25
|
McpAgentKitConnectionRequestCard,
|
|
@@ -120,7 +127,9 @@ function ChatThreadRouteContent({
|
|
|
120
127
|
labels={{ composerPlaceholder: t("chat.composerPlaceholder") }}
|
|
121
128
|
slots={{
|
|
122
129
|
emptyState: ChatEmptyState,
|
|
130
|
+
message: ChatMessage,
|
|
123
131
|
messageSupplement: ChatMcpConnectionSuggestion,
|
|
132
|
+
runFailure: ChatRunFailure,
|
|
124
133
|
connectionRequest: ChatMcpConnectionRequest,
|
|
125
134
|
footer: ChatAgentFooter,
|
|
126
135
|
}}
|
|
@@ -153,6 +162,90 @@ function ChatThreadRouteContent({
|
|
|
153
162
|
);
|
|
154
163
|
}
|
|
155
164
|
|
|
165
|
+
function ChatMessage({ value, threadId }: AgentKitRenderProps<AgentMessage>) {
|
|
166
|
+
const metadata = value.metadata as
|
|
167
|
+
| { custom?: { agentNativeRecoveryAction?: unknown } }
|
|
168
|
+
| undefined;
|
|
169
|
+
const recoveryAction = metadata?.custom?.agentNativeRecoveryAction;
|
|
170
|
+
if (
|
|
171
|
+
value.role === "user" &&
|
|
172
|
+
(recoveryAction === "continue" || recoveryAction === "retry")
|
|
173
|
+
) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
return <AgentMessageView value={value} threadId={threadId} />;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function ChatRunFailure({
|
|
180
|
+
error,
|
|
181
|
+
runId,
|
|
182
|
+
threadId,
|
|
183
|
+
}: AgentRunFailureRenderProps) {
|
|
184
|
+
const thread = useAgentThread(threadId);
|
|
185
|
+
const { controller } = useAgentKit();
|
|
186
|
+
const t = useT();
|
|
187
|
+
const recoveryMetadata = (message: (typeof thread.messages)[number]) =>
|
|
188
|
+
(
|
|
189
|
+
message.metadata as
|
|
190
|
+
| {
|
|
191
|
+
custom?: {
|
|
192
|
+
agentNativeRecoveryAction?: unknown;
|
|
193
|
+
agentNativeRecoveryOfRunId?: unknown;
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
| undefined
|
|
197
|
+
)?.custom;
|
|
198
|
+
const userRequests = thread.messages.filter((message) => {
|
|
199
|
+
if (message.role !== "user") return false;
|
|
200
|
+
const action = recoveryMetadata(message)?.agentNativeRecoveryAction;
|
|
201
|
+
return action !== "continue" && action !== "retry";
|
|
202
|
+
});
|
|
203
|
+
const originalRequest = userRequests[0];
|
|
204
|
+
const hasRetryForThisRun = thread.messages.some(
|
|
205
|
+
(message) =>
|
|
206
|
+
recoveryMetadata(message)?.agentNativeRecoveryAction === "retry" &&
|
|
207
|
+
recoveryMetadata(message)?.agentNativeRecoveryOfRunId === runId,
|
|
208
|
+
);
|
|
209
|
+
const retryFirstMessage = useCallback(() => {
|
|
210
|
+
const prompt =
|
|
211
|
+
originalRequest?.parts
|
|
212
|
+
.filter((part) => part.type === "text")
|
|
213
|
+
.map((part) => part.text)
|
|
214
|
+
.join("\n") ?? "";
|
|
215
|
+
const attachments =
|
|
216
|
+
originalRequest?.parts.filter((part) => part.type === "file") ?? [];
|
|
217
|
+
void controller.sendMessage({
|
|
218
|
+
threadId,
|
|
219
|
+
text: prompt || t("chat.retryPreviousRequest"),
|
|
220
|
+
...(attachments.length ? { attachments } : {}),
|
|
221
|
+
metadata: {
|
|
222
|
+
custom: {
|
|
223
|
+
agentNativeRecoveryAction: "retry",
|
|
224
|
+
agentNativeRecoveryOfRunId: runId,
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
}, [controller, originalRequest, runId, t, threadId]);
|
|
229
|
+
const isFirstMessage = userRequests.length === 1 && !hasRetryForThisRun;
|
|
230
|
+
if (
|
|
231
|
+
isFirstMessage &&
|
|
232
|
+
isMissingLlmProviderRunError({
|
|
233
|
+
message: error.message,
|
|
234
|
+
details: typeof error.details === "string" ? error.details : undefined,
|
|
235
|
+
errorCode: error.code,
|
|
236
|
+
})
|
|
237
|
+
) {
|
|
238
|
+
return (
|
|
239
|
+
<BuilderSetupCard
|
|
240
|
+
fullWidth
|
|
241
|
+
layout="sidebar"
|
|
242
|
+
onRetry={retryFirstMessage}
|
|
243
|
+
/>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return <AgentRunFailure error={error} runId={runId} threadId={threadId} />;
|
|
247
|
+
}
|
|
248
|
+
|
|
156
249
|
function ChatLifecycleTracking({ threadId }: { threadId: string }) {
|
|
157
250
|
const thread = useAgentThread(threadId);
|
|
158
251
|
const lifecycleRef = useRef({
|
|
@@ -33,6 +33,8 @@ const messages = {
|
|
|
33
33
|
pinChat: "Pin Chat",
|
|
34
34
|
pinned: "Pinned",
|
|
35
35
|
recents: "Recents",
|
|
36
|
+
retryPreviousRequest:
|
|
37
|
+
"Retry my previous request now that the model provider is connected.",
|
|
36
38
|
renameChat: "Rename Chat",
|
|
37
39
|
renameFailed: "Rename Failed",
|
|
38
40
|
renameThread: "Rename Thread",
|
|
@@ -18,7 +18,7 @@ export { CodeRequiredDialog, type CodeRequiredDialogProps, } from "../components
|
|
|
18
18
|
export { ChatFirstAgentActivityPanel, type ChatFirstAgentActivityPanelProps, } from "../chat-first-agent-activity.js";
|
|
19
19
|
export { ChatFirstSurfacePanelToggle } from "../chat-first-surface-panel-toggle.js";
|
|
20
20
|
export { useAgentEngineConfigured, type AgentEngineConfiguredState, type UseAgentEngineConfiguredResult, } from "../use-agent-engine-configured.js";
|
|
21
|
-
export { BuilderSetupCard } from "../chat/run-recovery.js";
|
|
21
|
+
export { BuilderSetupCard, isMissingLlmProviderRunError, type RunErrorInfo, } from "../chat/run-recovery.js";
|
|
22
22
|
export { AgentConversation, AgentConversationMessageView, normalizeCodeAgentTranscriptForConversation, useNearBottomAutoscroll, type CodeAgentConversationTranscriptEvent, type CodeAgentConversationTranscriptEventType, type NormalizeCodeAgentTranscriptOptions, type AgentConversationArtifact, type AgentConversationAttachment, type AgentConversationMessage, type AgentConversationMessagePart, type AgentConversationMessageRole, type AgentConversationNotice, type AgentConversationNoticeTone, type AgentConversationToolCall, type AgentConversationToolState, } from "../conversation/index.js";
|
|
23
23
|
export { McpAppRenderer } from "../mcp-apps/McpAppRenderer.js";
|
|
24
24
|
export { AGENT_NATIVE_MCP_APP_HOST_MESSAGE_TYPES, getMcpAppHostContext, initializeMcpAppHost, openMcpAppHostLink, requestMcpAppDisplayMode, sendMcpAppHostMessage, updateMcpAppModelContext, useMcpAppHostContext, type AgentNativeMcpAppHostMessageType, type McpAppDisplayMode, type McpAppHostChatMessage, type McpAppHostCapabilities, type McpAppHostContext, type McpAppHostInfo, type McpAppHostContextSnapshot, type McpAppModelContextContentPart, type McpAppModelContextUpdate, } from "../mcp-app-host.js";
|
|
@@ -18,7 +18,7 @@ export { CodeRequiredDialog, } from "../components/CodeRequiredDialog.js";
|
|
|
18
18
|
export { ChatFirstAgentActivityPanel, } from "../chat-first-agent-activity.js";
|
|
19
19
|
export { ChatFirstSurfacePanelToggle } from "../chat-first-surface-panel-toggle.js";
|
|
20
20
|
export { useAgentEngineConfigured, } from "../use-agent-engine-configured.js";
|
|
21
|
-
export { BuilderSetupCard } from "../chat/run-recovery.js";
|
|
21
|
+
export { BuilderSetupCard, isMissingLlmProviderRunError, } from "../chat/run-recovery.js";
|
|
22
22
|
export { AgentConversation, AgentConversationMessageView, normalizeCodeAgentTranscriptForConversation, useNearBottomAutoscroll, } from "../conversation/index.js";
|
|
23
23
|
export { McpAppRenderer } from "../mcp-apps/McpAppRenderer.js";
|
|
24
24
|
export { AGENT_NATIVE_MCP_APP_HOST_MESSAGE_TYPES, getMcpAppHostContext, initializeMcpAppHost, openMcpAppHostLink, requestMcpAppDisplayMode, sendMcpAppHostMessage, updateMcpAppModelContext, useMcpAppHostContext, } from "../mcp-app-host.js";
|
|
@@ -1852,12 +1852,29 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
1852
1852
|
if (input.resume !== undefined) {
|
|
1853
1853
|
throw new AgentProtocolValidationError("startRun.resume", "Core requires approval continuations to use resumeRun");
|
|
1854
1854
|
}
|
|
1855
|
-
const
|
|
1855
|
+
const latestUserMessage = [...input.messages]
|
|
1856
|
+
.reverse()
|
|
1857
|
+
.find((message) => message.role === "user");
|
|
1858
|
+
const latestUserMetadata = asRecord(latestUserMessage?.metadata);
|
|
1859
|
+
const recoveryMetadata = asRecord(latestUserMetadata?.custom);
|
|
1860
|
+
const isRecoveryRetry = recoveryMetadata?.agentNativeRecoveryAction === "retry";
|
|
1861
|
+
const turnMetadata = mergeTrustedProtocolMetadata(options.metadata, input.metadata, input.options?.metadata, input.options?.agentId ? { agentId: input.options.agentId } : undefined, input.options?.locale ? { locale: input.options.locale } : undefined, input.options?.mode ? { mode: input.options.mode } : undefined, isRecoveryRetry ? { agentNativeInternalContinuation: true } : undefined);
|
|
1856
1862
|
const session = await getSession(input.threadId, turnMetadata);
|
|
1857
1863
|
const messages = input.messages.map(protocolMessageToRuntimeMessage);
|
|
1864
|
+
const attachments = latestUserMessage?.parts.flatMap((part) => part.type === "file"
|
|
1865
|
+
? [
|
|
1866
|
+
{
|
|
1867
|
+
name: part.name,
|
|
1868
|
+
...(part.fileId ? { id: part.fileId } : {}),
|
|
1869
|
+
...(part.mediaType ? { mediaType: part.mediaType } : {}),
|
|
1870
|
+
...(part.url ? { url: part.url } : {}),
|
|
1871
|
+
},
|
|
1872
|
+
]
|
|
1873
|
+
: []) ?? [];
|
|
1858
1874
|
const turn = await session.startTurn({
|
|
1859
1875
|
prompt: latestUserPrompt(input.messages),
|
|
1860
1876
|
messages,
|
|
1877
|
+
...(attachments.length ? { attachments } : {}),
|
|
1861
1878
|
model: input.options?.model,
|
|
1862
1879
|
reasoningEffort: input.options?.reasoningEffort,
|
|
1863
1880
|
temperature: input.options?.temperature,
|
|
@@ -22,6 +22,7 @@ export declare function runErrorHeadline(info: RunErrorInfo, labels?: {
|
|
|
22
22
|
}): string;
|
|
23
23
|
export declare function getRequestModeMetadata(message: unknown): "act" | "plan" | null;
|
|
24
24
|
export declare function isBuilderReconnectRunError(info: RunErrorInfo): boolean;
|
|
25
|
+
export declare function isMissingLlmProviderRunError(info: RunErrorInfo): boolean;
|
|
25
26
|
export declare function BuilderConnectCta({ variant, onConnected, reconnect, }: {
|
|
26
27
|
variant?: "primary" | "compact";
|
|
27
28
|
onConnected?: () => void;
|
|
@@ -119,7 +119,7 @@ function isConnectionRecoveryRunError(info) {
|
|
|
119
119
|
message.includes("connection kept failing") ||
|
|
120
120
|
message.includes("automatic recovery attempts"));
|
|
121
121
|
}
|
|
122
|
-
function isMissingLlmProviderRunError(info) {
|
|
122
|
+
export function isMissingLlmProviderRunError(info) {
|
|
123
123
|
const code = (info.errorCode ?? "").toLowerCase();
|
|
124
124
|
const text = [info.message, info.details].filter(Boolean).join("\n");
|
|
125
125
|
const hasCredentialSetupText = /no llm provider(?: key)? (?:is connected|was found)|missing credentials|missing api key|missing_api_key|(?:api[_ -]?key|auth[_ -]?token)\s*(?:(?:is|was)\s+)?(?:not\s+(?:set|configured|available|present|provided|found)|missing|unavailable|empty|unset|unconfigured)/i.test(text);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Badge } from "@agent-native/toolkit/ui/badge";
|
|
3
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
3
4
|
import { Skeleton } from "@agent-native/toolkit/ui/skeleton";
|
|
4
5
|
import { IconArrowRight, IconCheck, IconInfoCircle, IconKey, IconLoader2, IconX, } from "@tabler/icons-react";
|
|
5
6
|
import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
@@ -10,6 +11,7 @@ import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/toolt
|
|
|
10
11
|
import { useT } from "../i18n.js";
|
|
11
12
|
import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
|
|
12
13
|
import { cn } from "../utils.js";
|
|
14
|
+
import { resolveFirstRunOnboardingMode } from "./first-run-enabled.js";
|
|
13
15
|
import { listFirstRunOnboardingExtensions } from "./first-run-registry.js";
|
|
14
16
|
import { saveFirstRunOnboardingRole } from "./first-run-status.js";
|
|
15
17
|
import { trackOnboardingEvent, useOnboarding } from "./use-onboarding.js";
|
|
@@ -70,6 +72,7 @@ const BUILDER_MORE_SERVICES = [
|
|
|
70
72
|
];
|
|
71
73
|
export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
72
74
|
const t = useT();
|
|
75
|
+
const connectFirstRun = resolveFirstRunOnboardingMode() === "connect";
|
|
73
76
|
const { pathname } = useLocation();
|
|
74
77
|
const previewMode = useOnboardingPreviewMode();
|
|
75
78
|
const previewStep = useOnboardingPreviewStep();
|
|
@@ -108,17 +111,27 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
108
111
|
const completionInFlightRef = useRef(false);
|
|
109
112
|
const onboardingTerminalRef = useRef(false);
|
|
110
113
|
const abandonmentTrackedRef = useRef(false);
|
|
111
|
-
const setupAttemptRef = useRef(null);
|
|
112
114
|
const builderSetupAttemptRef = useRef(null);
|
|
115
|
+
const pendingHandoffFailureRef = useRef(null);
|
|
116
|
+
const flushPendingHandoffFailure = useCallback(() => {
|
|
117
|
+
const attempt = pendingHandoffFailureRef.current;
|
|
118
|
+
if (!attempt)
|
|
119
|
+
return;
|
|
120
|
+
pendingHandoffFailureRef.current = null;
|
|
121
|
+
trackFirstRunSetupOutcome(attempt, "handoff_failed", "onboarding_completion_error");
|
|
122
|
+
}, []);
|
|
113
123
|
const startSetupMethod = useCallback((methodId, methodKind) => {
|
|
114
124
|
if (previewMode || typeof window === "undefined")
|
|
115
125
|
return null;
|
|
126
|
+
flushPendingHandoffFailure();
|
|
116
127
|
const attempt = {
|
|
117
128
|
id: window.crypto.randomUUID(),
|
|
118
129
|
methodId,
|
|
119
130
|
outcomeTracked: false,
|
|
120
131
|
};
|
|
121
|
-
|
|
132
|
+
if (methodKind !== "builder") {
|
|
133
|
+
pendingHandoffFailureRef.current = attempt;
|
|
134
|
+
}
|
|
122
135
|
const properties = {
|
|
123
136
|
flow: "first_run",
|
|
124
137
|
step_id: "choice",
|
|
@@ -129,20 +142,23 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
129
142
|
trackOnboardingEvent("onboarding_method_clicked", properties);
|
|
130
143
|
trackOnboardingEvent("onboarding_method_started", properties);
|
|
131
144
|
return attempt;
|
|
132
|
-
}, [previewMode]);
|
|
133
|
-
const finishOnboarding = useCallback(async (completedScreen, completedExtensionIndex = extensionIndex) => {
|
|
134
|
-
completionAttemptRef.current =
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
}, [flushPendingHandoffFailure, previewMode]);
|
|
146
|
+
const finishOnboarding = useCallback(async (completedScreen, completedExtensionIndex = extensionIndex, onSuccess) => {
|
|
147
|
+
completionAttemptRef.current = {
|
|
148
|
+
screen: completedScreen,
|
|
149
|
+
extensionIndex: completedExtensionIndex,
|
|
150
|
+
...(onSuccess ? { onSuccess } : {}),
|
|
151
|
+
};
|
|
137
152
|
completionInFlightRef.current = true;
|
|
153
|
+
let onSuccessAfterCompletion;
|
|
138
154
|
try {
|
|
139
155
|
await completeFirstRun();
|
|
140
156
|
if (completedScreen) {
|
|
141
157
|
trackFirstRunStepCompleted(completedScreen, completedExtensionIndex);
|
|
142
158
|
}
|
|
143
159
|
onboardingTerminalRef.current = true;
|
|
160
|
+
onSuccessAfterCompletion = completionAttemptRef.current?.onSuccess;
|
|
144
161
|
completionAttemptRef.current = null;
|
|
145
|
-
return true;
|
|
146
162
|
}
|
|
147
163
|
catch {
|
|
148
164
|
// coercion-ok: completeFirstRun exposes this failure as the inline retry state.
|
|
@@ -151,6 +167,8 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
151
167
|
finally {
|
|
152
168
|
completionInFlightRef.current = false;
|
|
153
169
|
}
|
|
170
|
+
onSuccessAfterCompletion?.();
|
|
171
|
+
return true;
|
|
154
172
|
}, [completeFirstRun, extensionIndex, trackFirstRunStepCompleted]);
|
|
155
173
|
useEffect(() => {
|
|
156
174
|
if (!previewMode && firstRun && !loading && profile) {
|
|
@@ -182,6 +200,7 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
182
200
|
completionInFlightRef.current)
|
|
183
201
|
return;
|
|
184
202
|
abandonmentTrackedRef.current = true;
|
|
203
|
+
flushPendingHandoffFailure();
|
|
185
204
|
trackOnboardingEvent("onboarding_abandoned", {
|
|
186
205
|
...firstRunStepProperties(screen, extensions, extensionIndex),
|
|
187
206
|
reason: "page_exit",
|
|
@@ -197,6 +216,7 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
197
216
|
previewMode,
|
|
198
217
|
profile,
|
|
199
218
|
screen,
|
|
219
|
+
flushPendingHandoffFailure,
|
|
200
220
|
]);
|
|
201
221
|
const handleFinish = useCallback((completedScreen, track = true) => {
|
|
202
222
|
if (extensions.length === 0) {
|
|
@@ -211,7 +231,6 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
211
231
|
const handleBuilderConnected = useCallback(() => {
|
|
212
232
|
trackFirstRunSetupOutcome(builderSetupAttemptRef.current, "connected");
|
|
213
233
|
builderSetupAttemptRef.current = null;
|
|
214
|
-
setupAttemptRef.current = null;
|
|
215
234
|
trackFirstRunStepCompleted("choice");
|
|
216
235
|
trackFirstRunStepCompleted("connecting");
|
|
217
236
|
handleFinish(null);
|
|
@@ -238,7 +257,7 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
238
257
|
const canActivateBuilderFreeCredits = connectFlow.agentNativeProvisioningEnabled;
|
|
239
258
|
const retryOnboardingCompletion = useCallback(() => {
|
|
240
259
|
const attempt = completionAttemptRef.current;
|
|
241
|
-
void finishOnboarding(attempt?.screen ?? null, attempt?.extensionIndex ?? extensionIndex);
|
|
260
|
+
void finishOnboarding(attempt?.screen ?? null, attempt?.extensionIndex ?? extensionIndex, attempt?.onSuccess);
|
|
242
261
|
}, [extensionIndex, finishOnboarding]);
|
|
243
262
|
const completionErrorProps = {
|
|
244
263
|
completionError: completeFirstRunError,
|
|
@@ -263,7 +282,6 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
263
282
|
if (connectFlow.hasFetchedStatus && connectFlow.configured) {
|
|
264
283
|
trackFirstRunSetupOutcome(attempt, "already_connected");
|
|
265
284
|
builderSetupAttemptRef.current = null;
|
|
266
|
-
setupAttemptRef.current = null;
|
|
267
285
|
trackFirstRunStepCompleted("choice");
|
|
268
286
|
handleFinish(null);
|
|
269
287
|
return;
|
|
@@ -278,16 +296,7 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
278
296
|
provisionAccount,
|
|
279
297
|
});
|
|
280
298
|
};
|
|
281
|
-
const
|
|
282
|
-
if (completionInFlightRef.current)
|
|
283
|
-
return;
|
|
284
|
-
const attempt = startSetupMethod("custom_keys", "manual");
|
|
285
|
-
const completed = await finishOnboarding("choice");
|
|
286
|
-
if (!completed) {
|
|
287
|
-
trackFirstRunSetupOutcome(attempt, "handoff_failed", "onboarding_completion_error");
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
trackFirstRunSetupOutcome(attempt, "settings_opened");
|
|
299
|
+
const navigateToKeySettings = () => {
|
|
291
300
|
if (typeof window === "undefined")
|
|
292
301
|
return;
|
|
293
302
|
// Drop the onboarding preview params — useOnboardingPreviewMode() reads
|
|
@@ -300,6 +309,31 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
300
309
|
window.history.pushState(null, "", `${appMountedPath(buildSettingsRoute("keys"), pathname || STANDARD_APP_ROUTES.home)}${query ? `?${query}` : ""}`);
|
|
301
310
|
window.dispatchEvent(new Event("popstate"));
|
|
302
311
|
};
|
|
312
|
+
const handleOpenSettings = async () => {
|
|
313
|
+
if (completionInFlightRef.current)
|
|
314
|
+
return;
|
|
315
|
+
const attempt = startSetupMethod("custom_keys", "manual");
|
|
316
|
+
await finishOnboarding("choice", extensionIndex, () => {
|
|
317
|
+
if (pendingHandoffFailureRef.current === attempt) {
|
|
318
|
+
pendingHandoffFailureRef.current = null;
|
|
319
|
+
}
|
|
320
|
+
trackFirstRunSetupOutcome(attempt, "settings_opened");
|
|
321
|
+
navigateToKeySettings();
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
const handleSkipToApp = async () => {
|
|
325
|
+
if (completionInFlightRef.current)
|
|
326
|
+
return;
|
|
327
|
+
const attempt = startSetupMethod("skip_to_app", "skip");
|
|
328
|
+
await finishOnboarding(null, extensionIndex, () => {
|
|
329
|
+
if (pendingHandoffFailureRef.current === attempt) {
|
|
330
|
+
pendingHandoffFailureRef.current = null;
|
|
331
|
+
}
|
|
332
|
+
trackFirstRunStepSkipped("choice", "skip_to_app");
|
|
333
|
+
trackFirstRunSetupOutcome(attempt, "skipped_to_app");
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
const builderStatusPending = !previewMode && !connectFlow.statusResolved;
|
|
303
337
|
const handleRoleContinue = async () => {
|
|
304
338
|
const roleToSave = selectedRole === "other" ? customRole.trim() : selectedRole;
|
|
305
339
|
if (!roleToSave || savingRole)
|
|
@@ -348,6 +382,9 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
348
382
|
void finishOnboarding(null);
|
|
349
383
|
} }) }));
|
|
350
384
|
}
|
|
385
|
+
if (screen === "choice" && connectFirstRun) {
|
|
386
|
+
return (_jsx(OnboardingShell, { profile: profile, screen: "choice", ...completionErrorProps, children: _jsxs("div", { className: "mx-auto flex w-full max-w-md flex-col items-center gap-6", children: [_jsx("h1", { className: "text-xl font-semibold tracking-[-0.03em] text-foreground", children: t("agentChat.setup.connectBuilder") }), _jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs(Button, { type: "button", "data-testid": "first-run-builder-continue", className: cn(primaryButtonClass, "w-full"), onClick: () => handleBuilder(canActivateBuilderFreeCredits), disabled: builderStatusPending || connectFlow.connecting, children: [t("agentChat.common.continue"), builderStatusPending || connectFlow.connecting ? (_jsx(IconLoader2, { size: 15, className: "animate-spin" })) : (_jsx(IconArrowRight, { size: 15 }))] }), _jsxs("p", { className: "text-center text-xs leading-5 text-muted-foreground", children: [t("agentChat.onboarding.builderConsentPrefix"), " ", _jsx("a", { href: "https://www.builder.io/legal/terms", target: "_blank", rel: "noreferrer", className: "text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: t("agentChat.onboarding.builderTerms") }), " ", t("agentChat.onboarding.builderConsentAnd"), " ", _jsx("a", { href: "https://www.builder.io/legal/privacy", target: "_blank", rel: "noreferrer", className: "text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: t("agentChat.onboarding.builderPrivacy") }), "."] })] }), connectFlow.error && !connectFlow.statusResolved && !previewMode && (_jsxs("div", { className: "flex flex-col items-center gap-2", children: [_jsx("p", { role: "status", "data-testid": "first-run-builder-status-error", className: "text-center text-xs text-destructive", children: t("agentChat.setup.providerStatusUnavailable") }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "min-h-8 rounded-lg px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: () => connectFlow.retry(), children: t("agentChat.common.retry") })] })), _jsxs("div", { className: "flex flex-col items-center gap-2", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", "data-testid": "first-run-open-key-settings", className: "min-h-9 rounded-lg px-2.5 text-sm font-medium text-muted-foreground underline underline-offset-4 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: () => void handleOpenSettings(), children: t("agentChat.onboarding.useOwnApiKeys") }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", "data-testid": "first-run-skip-to-app", className: "min-h-8 rounded-lg px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", onClick: () => void handleSkipToApp(), children: t("agentChat.onboarding.skipForNow") })] })] }) }));
|
|
387
|
+
}
|
|
351
388
|
if (screen === "choice") {
|
|
352
389
|
return (_jsx(OnboardingShell, { profile: profile, screen: "choice", ...completionErrorProps, children: _jsxs("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-9", children: [_jsxs("div", { className: "flex flex-col gap-6", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("h1", { className: "text-[28px] font-bold leading-tight tracking-[-0.02em] text-foreground", children: "Choose your setup" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "We recommend starting with Builder.io for the fastest setup." })] }), _jsxs("div", { className: "grid gap-6 sm:grid-cols-2", children: [_jsxs("section", { className: "flex flex-col gap-5 rounded-2xl border border-border bg-card p-6", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-lg font-bold text-foreground", children: "Use Builder.io" }), _jsx(Badge, { variant: "secondary", className: "font-medium", children: "Recommended" })] }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Configure using Builder.io and use your account credits to power the app\u2019s services." })] }), _jsxs("div", { className: "flex flex-col gap-1 rounded-[10px] bg-emerald-50 px-4 py-3 dark:bg-emerald-950/30", children: [_jsx("p", { className: "text-[13px] font-semibold text-foreground", children: "Included free with a Builder.io account" }), _jsx("p", { className: "text-xs font-medium text-emerald-700 dark:text-emerald-400", children: "60 monthly Agent Credits" })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("p", { className: "text-sm text-muted-foreground/70", children: "What\u2019s included" }), builderCapabilities.map((capability) => {
|
|
353
390
|
const copy = getCapabilityCopy(t, capability);
|
|
@@ -355,7 +392,7 @@ export function FirstRunOnboarding({ initialFirstRun = false, } = {}) {
|
|
|
355
392
|
defaultValue: "About {{label}}",
|
|
356
393
|
label: copy.label,
|
|
357
394
|
}) }))] }, capability.id));
|
|
358
|
-
}), BUILDER_MORE_SERVICES.filter((service) => !builderCapabilities.some((capability) => getCapabilityCopy(t, capability).label.toLowerCase() === service.toLowerCase())).map((service) => (_jsxs("div", { className: "flex items-center gap-2 rounded-md px-2 py-1", children: [_jsx(IconCheck, { className: "shrink-0 text-muted-foreground", size: 15 }), _jsx("span", { className: "text-xs text-foreground", children: service })] }, service)))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("button", { type: "button", "data-testid": "first-run-builder-create-account", className: cn(primaryButtonClass, "w-full"), onClick: () => handleBuilder(true), disabled: connectFlow.connecting, children: t("agentChat.onboarding.builderCreateAccount") }), _jsx("button", { type: "button", "data-testid": "first-run-builder-sign-in", className: cn(mutedButtonClass, "w-full"), onClick: () => handleBuilder(false), disabled: connectFlow.connecting, children: t("agentChat.onboarding.builderSignInWithAccount") })] }), connectFlow.error && !connectFlow.statusResolved && (_jsx("p", { role: "status", "data-testid": "first-run-builder-status-error", className: "text-center text-xs text-destructive", children:
|
|
395
|
+
}), BUILDER_MORE_SERVICES.filter((service) => !builderCapabilities.some((capability) => getCapabilityCopy(t, capability).label.toLowerCase() === service.toLowerCase())).map((service) => (_jsxs("div", { className: "flex items-center gap-2 rounded-md px-2 py-1", children: [_jsx(IconCheck, { className: "shrink-0 text-muted-foreground", size: 15 }), _jsx("span", { className: "text-xs text-foreground", children: service })] }, service)))] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("button", { type: "button", "data-testid": "first-run-builder-create-account", className: cn(primaryButtonClass, "w-full"), onClick: () => handleBuilder(true), disabled: connectFlow.connecting, children: t("agentChat.onboarding.builderCreateAccount") }), _jsx("button", { type: "button", "data-testid": "first-run-builder-sign-in", className: cn(mutedButtonClass, "w-full"), onClick: () => handleBuilder(false), disabled: connectFlow.connecting, children: t("agentChat.onboarding.builderSignInWithAccount") })] }), connectFlow.error && !connectFlow.statusResolved && (_jsx("p", { role: "status", "data-testid": "first-run-builder-status-error", className: "text-center text-xs text-destructive", children: t("agentChat.setup.providerStatusUnavailable") }))] }), _jsxs("section", { className: "flex flex-col gap-5 rounded-2xl border border-border bg-card p-6", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("h2", { className: "text-lg font-bold text-foreground", children: "Configure manually" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Configure your own API keys and credentials to power the app\u2019s services." })] }), _jsxs("div", { className: "flex flex-col gap-1 rounded-xl bg-muted px-4 py-3", children: [_jsx("p", { className: "text-[13px] font-semibold text-foreground", children: "You configure and maintain everything" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Full control over your infrastructure" })] }), _jsx(CapabilityList, { capabilities: profile.capabilities, className: "flex-1" }), _jsx("button", { type: "button", "data-testid": "first-run-open-key-settings", className: cn(secondaryButtonClass, "w-full"), onClick: () => void handleOpenSettings(), children: "Skip and configure manually" })] })] })] }), _jsxs("p", { className: "text-center text-xs leading-5 text-muted-foreground", children: [t("agentChat.onboarding.builderConsentPrefix"), " ", _jsx("a", { href: "https://www.builder.io/legal/terms", target: "_blank", rel: "noreferrer", className: "text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: t("agentChat.onboarding.builderTerms") }), " ", t("agentChat.onboarding.builderConsentAnd"), " ", _jsx("a", { href: "https://www.builder.io/legal/privacy", target: "_blank", rel: "noreferrer", className: "text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: t("agentChat.onboarding.builderPrivacy") }), "."] })] }) }));
|
|
359
396
|
}
|
|
360
397
|
if (screen === "role") {
|
|
361
398
|
return (_jsx(OnboardingShell, { profile: profile, screen: "role", ...completionErrorProps, children: _jsxs("div", { className: "mx-auto flex w-full max-w-2xl flex-col", "data-testid": "first-run-role", children: [_jsxs("div", { className: "flex flex-col gap-2 pt-2", children: [_jsx("h1", { className: "text-[28px] font-bold leading-tight tracking-[-0.02em] text-foreground", children: t("agentChat.onboarding.roleQuestion") }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("agentChat.onboarding.roleHelperText") })] }), _jsxs("fieldset", { className: "mt-7 flex flex-col gap-3", children: [_jsx("legend", { className: "sr-only", children: t("agentChat.onboarding.chooseRole") }), FIRST_RUN_ROLE_OPTIONS.map(({ value, labelKey }) => (_jsxs("label", { "data-testid": `first-run-role-${value}`, className: cn("flex cursor-pointer items-center gap-3 rounded-lg border border-border bg-card p-3 text-sm transition-colors focus-within:ring-2 focus-within:ring-ring", selectedRole === value
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
-
error?: undefined;
|
|
66
65
|
states: {
|
|
67
66
|
clientId: number;
|
|
68
67
|
state: string;
|
|
69
68
|
}[];
|
|
69
|
+
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
-
error?: undefined;
|
|
81
80
|
users: {
|
|
82
81
|
clientId: number;
|
|
83
82
|
lastSeen: number;
|
|
84
83
|
}[];
|
|
84
|
+
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -44,9 +44,9 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
44
44
|
url: string;
|
|
45
45
|
id: string;
|
|
46
46
|
provider: string;
|
|
47
|
+
error?: undefined;
|
|
47
48
|
configured?: undefined;
|
|
48
49
|
connectPath?: undefined;
|
|
49
|
-
error?: undefined;
|
|
50
50
|
} | {
|
|
51
51
|
url?: undefined;
|
|
52
52
|
id?: undefined;
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "أخرى",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "صف دورك",
|
|
72
72
|
"onboarding.skipForNow": "تخطي الآن",
|
|
73
|
+
"onboarding.useOwnApiKeys": "استخدام مفاتيح API الخاصة بي",
|
|
73
74
|
"onboarding.saveRoleError": "تعذر حفظ دورك.",
|
|
74
75
|
"onboarding.builderCreateAccount": "إنشاء حساب Builder.io",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "تسجيل الدخول بحساب Builder.io",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "Andere",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "Beschreibe deine Rolle",
|
|
72
72
|
"onboarding.skipForNow": "Vorerst überspringen",
|
|
73
|
+
"onboarding.useOwnApiKeys": "Meine eigenen API-Schlüssel verwenden",
|
|
73
74
|
"onboarding.saveRoleError": "Deine Rolle konnte nicht gespeichert werden.",
|
|
74
75
|
"onboarding.builderCreateAccount": "Builder.io-Konto erstellen",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Mit Builder.io-Konto anmelden",
|
|
@@ -70,6 +70,7 @@ declare const messages: {
|
|
|
70
70
|
readonly "onboarding.roleOther": "Other";
|
|
71
71
|
readonly "onboarding.roleOtherInputLabel": "Describe your role";
|
|
72
72
|
readonly "onboarding.skipForNow": "Skip for now";
|
|
73
|
+
readonly "onboarding.useOwnApiKeys": "Use my own API keys";
|
|
73
74
|
readonly "onboarding.saveRoleError": "Could not save your role.";
|
|
74
75
|
readonly "onboarding.builderCreateAccount": "Create Builder.io account";
|
|
75
76
|
readonly "onboarding.builderSignInWithAccount": "Sign in with Builder.io account";
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "Other",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "Describe your role",
|
|
72
72
|
"onboarding.skipForNow": "Skip for now",
|
|
73
|
+
"onboarding.useOwnApiKeys": "Use my own API keys",
|
|
73
74
|
"onboarding.saveRoleError": "Could not save your role.",
|
|
74
75
|
"onboarding.builderCreateAccount": "Create Builder.io account",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Sign in with Builder.io account",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "Otro",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "Describe tu función",
|
|
72
72
|
"onboarding.skipForNow": "Omitir por ahora",
|
|
73
|
+
"onboarding.useOwnApiKeys": "Usar mis propias claves de API",
|
|
73
74
|
"onboarding.saveRoleError": "No se pudo guardar tu rol.",
|
|
74
75
|
"onboarding.builderCreateAccount": "Crear cuenta de Builder.io",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Iniciar sesión con una cuenta de Builder.io",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "Autre",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "Décrivez votre rôle",
|
|
72
72
|
"onboarding.skipForNow": "Ignorer pour l’instant",
|
|
73
|
+
"onboarding.useOwnApiKeys": "Utiliser mes propres clés API",
|
|
73
74
|
"onboarding.saveRoleError": "Impossible d’enregistrer votre rôle.",
|
|
74
75
|
"onboarding.builderCreateAccount": "Créer un compte Builder.io",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Se connecter avec un compte Builder.io",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "अन्य",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "अपनी भूमिका बताएं",
|
|
72
72
|
"onboarding.skipForNow": "अभी छोड़ें",
|
|
73
|
+
"onboarding.useOwnApiKeys": "मेरी अपनी API कुंजियाँ इस्तेमाल करें",
|
|
73
74
|
"onboarding.saveRoleError": "आपकी भूमिका सहेजी नहीं जा सकी।",
|
|
74
75
|
"onboarding.builderCreateAccount": "Builder.io खाता बनाएँ",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Builder.io खाते से साइन इन करें",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "その他",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "役割を入力してください",
|
|
72
72
|
"onboarding.skipForNow": "今はスキップ",
|
|
73
|
+
"onboarding.useOwnApiKeys": "自分の API キーを使う",
|
|
73
74
|
"onboarding.saveRoleError": "役割を保存できませんでした。",
|
|
74
75
|
"onboarding.builderCreateAccount": "Builder.io アカウントを作成",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Builder.io アカウントでサインイン",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "기타",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "역할을 입력해 주세요",
|
|
72
72
|
"onboarding.skipForNow": "지금 건너뛰기",
|
|
73
|
+
"onboarding.useOwnApiKeys": "내 API 키 사용",
|
|
73
74
|
"onboarding.saveRoleError": "역할을 저장하지 못했습니다.",
|
|
74
75
|
"onboarding.builderCreateAccount": "Builder.io 계정 만들기",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Builder.io 계정으로 로그인",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "Outro",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "Descreva sua função",
|
|
72
72
|
"onboarding.skipForNow": "Pular por enquanto",
|
|
73
|
+
"onboarding.useOwnApiKeys": "Usar minhas próprias chaves de API",
|
|
73
74
|
"onboarding.saveRoleError": "Não foi possível salvar sua função.",
|
|
74
75
|
"onboarding.builderCreateAccount": "Criar conta do Builder.io",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "Entrar com uma conta do Builder.io",
|
|
@@ -70,6 +70,7 @@ const messages = {
|
|
|
70
70
|
"onboarding.roleOther": "其他",
|
|
71
71
|
"onboarding.roleOtherInputLabel": "描述你的角色",
|
|
72
72
|
"onboarding.skipForNow": "暂时跳过",
|
|
73
|
+
"onboarding.useOwnApiKeys": "使用我自己的 API 密钥",
|
|
73
74
|
"onboarding.saveRoleError": "无法保存你的角色。",
|
|
74
75
|
"onboarding.builderCreateAccount": "创建 Builder.io 账户",
|
|
75
76
|
"onboarding.builderSignInWithAccount": "使用 Builder.io 账户登录",
|