@12-apps/mcp 3.5.1 → 3.7.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/ADOPTING.md +69 -1
- package/dist/chunk-FBUSSQSK.js +22 -0
- package/dist/chunk-FBUSSQSK.js.map +1 -0
- package/dist/{chunk-FYEVBTDU.js → chunk-HRAQKMDC.js} +12 -20
- package/dist/chunk-HRAQKMDC.js.map +1 -0
- package/dist/{guide-DV5MQbCg.d.ts → guide-KQNcXlMG.d.ts} +32 -17
- package/dist/index.d.ts +2 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/oauth/index.d.ts +1 -1
- package/dist/oauth/index.js +1 -1
- package/dist/pt-BR-e1RnV2v8.d.ts +25 -0
- package/dist/react/index.d.ts +208 -30
- package/dist/react/index.js +341 -151
- package/dist/react/index.js.map +1 -1
- package/package.json +4 -4
- package/src/guide.ts +33 -165
- package/src/index.ts +8 -3
- package/src/pt-BR.ts +195 -0
- package/src/react/ai-capabilities.tsx +10 -6
- package/src/react/ai-connection-utils.ts +18 -13
- package/src/react/ai-flow-steps.tsx +63 -43
- package/src/react/ai-landing.tsx +47 -21
- package/src/react/ai-onboarding.tsx +31 -25
- package/src/react/ai-status-board.tsx +31 -16
- package/src/react/ai-steps.tsx +60 -23
- package/src/react/copy.ts +165 -0
- package/src/react/host-connect-guide.tsx +24 -8
- package/src/react/host-select-step.tsx +4 -1
- package/src/react/index.ts +21 -3
- package/src/react/pt-BR.ts +114 -0
- package/dist/chunk-FYEVBTDU.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import type { McpAiCopy } from "./copy";
|
|
3
4
|
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
|
4
5
|
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
|
|
5
6
|
import { useEffect, useState } from "react";
|
|
@@ -32,21 +33,21 @@ const POLL_INTERVAL_MS = 3000;
|
|
|
32
33
|
function StepNav({
|
|
33
34
|
nav,
|
|
34
35
|
onNext,
|
|
35
|
-
nextLabel
|
|
36
|
+
nextLabel,
|
|
36
37
|
nextDisabled = false,
|
|
37
38
|
nextTestId,
|
|
39
|
+
copy,
|
|
38
40
|
}: {
|
|
39
41
|
nav: GuidedNav;
|
|
40
42
|
onNext: () => void;
|
|
41
43
|
nextLabel?: string;
|
|
42
44
|
nextDisabled?: boolean;
|
|
43
45
|
nextTestId?: string;
|
|
46
|
+
copy: McpAiCopy;
|
|
44
47
|
}): React.JSX.Element {
|
|
45
48
|
return (
|
|
46
49
|
<Stack direction="row" spacing={1} alignItems="center" justifyContent="space-between">
|
|
47
|
-
<Button variant="ghost" onClick={() => nav.back()} data-testid="ai-step-back">
|
|
48
|
-
Voltar
|
|
49
|
-
</Button>
|
|
50
|
+
<Button variant="ghost" onClick={() => nav.back()} data-testid="ai-step-back">{copy.flow.back}</Button>
|
|
50
51
|
<Button onClick={onNext} disabled={nextDisabled} data-testid={nextTestId}>
|
|
51
52
|
{nextLabel}
|
|
52
53
|
</Button>
|
|
@@ -55,39 +56,53 @@ function StepNav({
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
/** Step 2 — copy the store URL; copying is the action that advances the wizard. */
|
|
58
|
-
export function CopyUrlStep({
|
|
59
|
+
export function CopyUrlStep({
|
|
60
|
+
nav,
|
|
61
|
+
endpointUrl,
|
|
62
|
+
copy,
|
|
63
|
+
}: {
|
|
64
|
+
nav: GuidedNav;
|
|
65
|
+
endpointUrl: string;
|
|
66
|
+
copy: McpAiCopy;
|
|
67
|
+
}): React.JSX.Element {
|
|
59
68
|
return (
|
|
60
69
|
<Stack spacing={3} data-testid="ai-copy-step">
|
|
61
70
|
<Box>
|
|
62
71
|
<Text variant="heading" size="sm" as="h2">
|
|
63
|
-
|
|
72
|
+
{copy.flow.copyUrlTitle}
|
|
64
73
|
</Text>
|
|
65
74
|
<Text variant="caption" as="p" color="secondary">
|
|
66
|
-
|
|
75
|
+
{copy.flow.urlCaption}
|
|
67
76
|
</Text>
|
|
68
77
|
</Box>
|
|
69
|
-
<EndpointCopyBlock endpointUrl={endpointUrl} copied={false} onCopy={() => nav.next()} />
|
|
78
|
+
<EndpointCopyBlock copy={copy.connectGuide} flowCopy={copy.flow} endpointUrl={endpointUrl} copied={false} onCopy={() => nav.next()} />
|
|
70
79
|
<Box>
|
|
71
|
-
<Button variant="ghost" onClick={() => nav.back()} data-testid="ai-step-back">
|
|
72
|
-
Voltar
|
|
73
|
-
</Button>
|
|
80
|
+
<Button variant="ghost" onClick={() => nav.back()} data-testid="ai-step-back">{copy.flow.back}</Button>
|
|
74
81
|
</Box>
|
|
75
82
|
</Stack>
|
|
76
83
|
);
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
/** Step 3 — open the host's connectors and add + configure the custom connector. */
|
|
80
|
-
export function ConfigureStep({
|
|
87
|
+
export function ConfigureStep({
|
|
88
|
+
nav,
|
|
89
|
+
host,
|
|
90
|
+
copy,
|
|
91
|
+
}: {
|
|
92
|
+
nav: GuidedNav;
|
|
93
|
+
host: AiHostGuide;
|
|
94
|
+
copy: McpAiCopy;
|
|
95
|
+
}): React.JSX.Element {
|
|
81
96
|
// Hosts with no direct link (e.g. Claude Desktop) have nothing to open, so
|
|
82
97
|
// "Próximo" is available immediately; otherwise it unlocks on the open click.
|
|
83
98
|
const [opened, setOpened] = useState(!host.link);
|
|
84
99
|
return (
|
|
85
100
|
<Stack spacing={2.5} data-testid="ai-configure-step">
|
|
86
|
-
<HostConnectHeader host={host} />
|
|
101
|
+
<HostConnectHeader copy={copy.connectGuide} host={host} />
|
|
87
102
|
<HostOpenButton host={host} onOpen={() => setOpened(true)} />
|
|
88
103
|
<HostStepList steps={host.steps.slice(0, CONFIGURE_STEP_COUNT)} start={1} />
|
|
89
|
-
<HostDocsLink host={host} />
|
|
90
|
-
<StepNav nav={nav} onNext={() => nav.next()} nextDisabled={!opened} nextTestId="ai-configure-next" />
|
|
104
|
+
<HostDocsLink copy={copy.connectGuide} host={host} />
|
|
105
|
+
<StepNav copy={copy} nav={nav} onNext={() => nav.next()} nextDisabled={!opened} nextTestId="ai-configure-next" />
|
|
91
106
|
</Stack>
|
|
92
107
|
);
|
|
93
108
|
}
|
|
@@ -101,15 +116,17 @@ export function ConfigureStageStep({
|
|
|
101
116
|
nav,
|
|
102
117
|
host,
|
|
103
118
|
stage,
|
|
119
|
+
copy,
|
|
104
120
|
}: {
|
|
105
121
|
nav: GuidedNav;
|
|
106
122
|
host: AiHostGuide;
|
|
107
123
|
stage: AiHostConfigureStage;
|
|
124
|
+
copy: McpAiCopy;
|
|
108
125
|
}): React.JSX.Element {
|
|
109
126
|
const [opened, setOpened] = useState(!stage.link);
|
|
110
127
|
return (
|
|
111
128
|
<Stack spacing={2.5} data-testid={`ai-stage-${stage.id}`}>
|
|
112
|
-
<HostConnectHeader host={host} />
|
|
129
|
+
<HostConnectHeader copy={copy.connectGuide} host={host} />
|
|
113
130
|
{stage.link && (
|
|
114
131
|
<Box>
|
|
115
132
|
<Button
|
|
@@ -125,8 +142,8 @@ export function ConfigureStageStep({
|
|
|
125
142
|
</Box>
|
|
126
143
|
)}
|
|
127
144
|
<HostStepList steps={stage.steps} start={1} />
|
|
128
|
-
<HostDocsLink host={host} />
|
|
129
|
-
<StepNav
|
|
145
|
+
<HostDocsLink copy={copy.connectGuide} host={host} />
|
|
146
|
+
<StepNav copy={copy}
|
|
130
147
|
nav={nav}
|
|
131
148
|
onNext={() => nav.next()}
|
|
132
149
|
nextDisabled={!opened}
|
|
@@ -141,22 +158,24 @@ export function ConnectStep({
|
|
|
141
158
|
nav,
|
|
142
159
|
host,
|
|
143
160
|
connectPrompt,
|
|
161
|
+
copy,
|
|
144
162
|
}: {
|
|
145
163
|
nav: GuidedNav;
|
|
146
164
|
host: AiHostGuide;
|
|
147
165
|
connectPrompt: string;
|
|
166
|
+
copy: McpAiCopy;
|
|
148
167
|
}): React.JSX.Element {
|
|
149
168
|
return (
|
|
150
169
|
<Stack spacing={2.5} data-testid="ai-connect-step">
|
|
151
|
-
<HostConnectHeader host={host} />
|
|
170
|
+
<HostConnectHeader copy={copy.connectGuide} host={host} />
|
|
152
171
|
<HostStepList steps={host.steps.slice(CONFIGURE_STEP_COUNT)} start={CONFIGURE_STEP_COUNT + 1} />
|
|
153
|
-
<PromptCopyBlock
|
|
154
|
-
title=
|
|
155
|
-
caption=
|
|
172
|
+
<PromptCopyBlock flowCopy={copy.flow}
|
|
173
|
+
title={copy.flow.pasteTitle}
|
|
174
|
+
caption={copy.flow.promptCaption}
|
|
156
175
|
message={connectPrompt}
|
|
157
176
|
/>
|
|
158
|
-
<HostDocsLink host={host} />
|
|
159
|
-
<StepNav nav={nav} onNext={() => nav.next()} nextLabel=
|
|
177
|
+
<HostDocsLink copy={copy.connectGuide} host={host} />
|
|
178
|
+
<StepNav copy={copy} nav={nav} onNext={() => nav.next()} nextLabel={copy.flow.advance} nextTestId="ai-connect-done" />
|
|
160
179
|
</Stack>
|
|
161
180
|
);
|
|
162
181
|
}
|
|
@@ -170,18 +189,19 @@ export function InstallStep({
|
|
|
170
189
|
nav,
|
|
171
190
|
host,
|
|
172
191
|
connectPrompt,
|
|
192
|
+
copy,
|
|
173
193
|
}: {
|
|
174
194
|
nav: GuidedNav;
|
|
175
195
|
host: AiHostGuide;
|
|
176
196
|
connectPrompt: string;
|
|
197
|
+
copy: McpAiCopy;
|
|
177
198
|
}): React.JSX.Element {
|
|
178
199
|
const [opened, setOpened] = useState(false);
|
|
179
200
|
return (
|
|
180
201
|
<Stack spacing={2.5} data-testid="ai-install-step">
|
|
181
|
-
<HostConnectHeader host={host} />
|
|
202
|
+
<HostConnectHeader copy={copy.connectGuide} host={host} />
|
|
182
203
|
<Text variant="body" as="p" color="secondary">
|
|
183
|
-
|
|
184
|
-
credenciais.
|
|
204
|
+
{copy.flow.installBody}
|
|
185
205
|
</Text>
|
|
186
206
|
{host.pluginUrl && (
|
|
187
207
|
<Box>
|
|
@@ -192,21 +212,21 @@ export function InstallStep({
|
|
|
192
212
|
}}
|
|
193
213
|
data-testid="ai-install-open"
|
|
194
214
|
>
|
|
195
|
-
|
|
215
|
+
{copy.flow.installAction}
|
|
196
216
|
<OpenInNewIcon sx={{ fontSize: 16, ml: 0.5 }} />
|
|
197
217
|
</Button>
|
|
198
218
|
</Box>
|
|
199
219
|
)}
|
|
200
|
-
<PromptCopyBlock
|
|
201
|
-
title=
|
|
202
|
-
caption=
|
|
220
|
+
<PromptCopyBlock flowCopy={copy.flow}
|
|
221
|
+
title={copy.flow.askTitle}
|
|
222
|
+
caption={copy.flow.pasteInstallCaption}
|
|
203
223
|
message={connectPrompt}
|
|
204
224
|
/>
|
|
205
|
-
<HostDocsLink host={host} />
|
|
206
|
-
<StepNav
|
|
225
|
+
<HostDocsLink copy={copy.connectGuide} host={host} />
|
|
226
|
+
<StepNav copy={copy}
|
|
207
227
|
nav={nav}
|
|
208
228
|
onNext={() => nav.next()}
|
|
209
|
-
nextLabel=
|
|
229
|
+
nextLabel={copy.flow.advance}
|
|
210
230
|
nextDisabled={!opened}
|
|
211
231
|
nextTestId="ai-install-done"
|
|
212
232
|
/>
|
|
@@ -225,11 +245,13 @@ export function ConfirmStep({
|
|
|
225
245
|
connections,
|
|
226
246
|
hosts,
|
|
227
247
|
onRetest,
|
|
248
|
+
copy,
|
|
228
249
|
}: {
|
|
229
250
|
nav: GuidedNav;
|
|
230
251
|
connections: readonly AiConnection[];
|
|
231
252
|
hosts: readonly AiHostGuide[];
|
|
232
253
|
onRetest: () => void;
|
|
254
|
+
copy: McpAiCopy;
|
|
233
255
|
}): React.JSX.Element {
|
|
234
256
|
const selectedHostId = nav.data.selectedHost as string | undefined;
|
|
235
257
|
const connection = connectionForHost(connections, selectedHostId);
|
|
@@ -250,15 +272,15 @@ export function ConfirmStep({
|
|
|
250
272
|
<CheckCircleIcon sx={{ color: "success.main" }} />
|
|
251
273
|
<Box>
|
|
252
274
|
<Text variant="body" weight="bold" as="p">
|
|
253
|
-
{label}
|
|
275
|
+
{copy.flow.connectedTo(label)}
|
|
254
276
|
</Text>
|
|
255
277
|
<Text variant="caption" as="p" color="secondary">
|
|
256
|
-
{activeAgo(connection.lastActiveAt)}
|
|
278
|
+
{activeAgo(connection.lastActiveAt, copy.summary)}
|
|
257
279
|
</Text>
|
|
258
280
|
</Box>
|
|
259
281
|
</Stack>
|
|
260
282
|
<Box>
|
|
261
|
-
<Button onClick={() => nav.complete({ connectedHost: selectedHostId })}>
|
|
283
|
+
<Button onClick={() => nav.complete({ connectedHost: selectedHostId })}>{copy.flow.finish}</Button>
|
|
262
284
|
</Box>
|
|
263
285
|
</Stack>
|
|
264
286
|
);
|
|
@@ -270,20 +292,18 @@ export function ConfirmStep({
|
|
|
270
292
|
<Progress variant="circular" circularSize={22} thickness={4} dataTestId="ai-confirm-spinner" />
|
|
271
293
|
<Box>
|
|
272
294
|
<Text variant="body" weight="bold" as="p">
|
|
273
|
-
|
|
295
|
+
{copy.flow.waitingTitle}
|
|
274
296
|
</Text>
|
|
275
297
|
<Text variant="caption" as="p" color="secondary">
|
|
276
|
-
|
|
298
|
+
{copy.flow.waitingBody(label)}
|
|
277
299
|
</Text>
|
|
278
300
|
</Box>
|
|
279
301
|
</Stack>
|
|
280
302
|
<Stack direction="row" spacing={1}>
|
|
281
303
|
<Button variant="ghost" size="sm" onClick={onRetest} data-testid="ai-confirm-retest">
|
|
282
|
-
|
|
283
|
-
</Button>
|
|
284
|
-
<Button variant="ghost" size="sm" onClick={() => nav.back()}>
|
|
285
|
-
Voltar
|
|
304
|
+
{copy.flow.testNow}
|
|
286
305
|
</Button>
|
|
306
|
+
<Button variant="ghost" size="sm" onClick={() => nav.back()}>{copy.flow.back}</Button>
|
|
287
307
|
</Stack>
|
|
288
308
|
</Stack>
|
|
289
309
|
);
|
package/src/react/ai-landing.tsx
CHANGED
|
@@ -10,19 +10,42 @@ import { Box } from "@12-apps/ui/mui/Box";
|
|
|
10
10
|
import { Stack } from "@12-apps/ui/mui/Stack";
|
|
11
11
|
import { Text } from "@12-apps/ui/typography/Text";
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import type { AiCapability } from "../guide";
|
|
14
|
+
import type { AiCapabilitiesCopy, AiLandingCopy } from "./copy";
|
|
14
15
|
import { AiCapabilities } from "./ai-capabilities";
|
|
15
16
|
import { FeatureBadge, type FeatureBadgeItem } from "./feature-badge";
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
/**
|
|
19
|
+
* The ICONS for the landing's reassurance strip, keyed by the copy's own ids.
|
|
20
|
+
*
|
|
21
|
+
* The package keeps the icons and the host keeps the words: an icon is not
|
|
22
|
+
* copy, and a pack that had to ship React elements could not be a plain data
|
|
23
|
+
* file. An id the map does not know renders without an icon rather than
|
|
24
|
+
* throwing — a host adding a fifth point should get its words on screen.
|
|
25
|
+
*/
|
|
26
|
+
const TRUST_ICONS: Readonly<Record<string, React.JSX.Element>> = {
|
|
27
|
+
login: <LockOpenOutlinedIcon />,
|
|
28
|
+
install: <BoltOutlinedIcon />,
|
|
29
|
+
permissions: <VerifiedUserOutlinedIcon />,
|
|
30
|
+
surface: <LanguageOutlinedIcon />,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function trustBadges(trust: AiLandingCopy["trust"]): FeatureBadgeItem[] {
|
|
34
|
+
return trust.map((point) => ({
|
|
35
|
+
icon: TRUST_ICONS[point.id],
|
|
36
|
+
label: point.label,
|
|
37
|
+
caption: point.caption,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
23
40
|
|
|
24
41
|
/** The single-column marketing hero: eyebrow + headline + description + CTA. */
|
|
25
|
-
function Hero({
|
|
42
|
+
function Hero({
|
|
43
|
+
onStart,
|
|
44
|
+
copy,
|
|
45
|
+
}: {
|
|
46
|
+
onStart: () => void;
|
|
47
|
+
copy: AiLandingCopy;
|
|
48
|
+
}): React.JSX.Element {
|
|
26
49
|
return (
|
|
27
50
|
<Stack spacing={2.5} sx={{ maxWidth: 680 }}>
|
|
28
51
|
<Box
|
|
@@ -34,19 +57,17 @@ function Hero({ onStart }: { onStart: () => void }): React.JSX.Element {
|
|
|
34
57
|
textTransform: "uppercase",
|
|
35
58
|
}}
|
|
36
59
|
>
|
|
37
|
-
|
|
60
|
+
{copy.eyebrow}
|
|
38
61
|
</Box>
|
|
39
62
|
<Text variant="heading" size="xl" weight="bold" as="h1">
|
|
40
63
|
Conecte{" "}
|
|
41
64
|
<Box component="span" sx={{ color: "primary.main" }}>
|
|
42
65
|
assistentes de IA
|
|
43
66
|
</Box>{" "}
|
|
44
|
-
|
|
67
|
+
{copy.titleTail}
|
|
45
68
|
</Text>
|
|
46
69
|
<Text variant="body" color="secondary" as="p">
|
|
47
|
-
|
|
48
|
-
pedidos — e executarem ações por você, direto na conversa. Com segurança e sem instalar
|
|
49
|
-
nada.
|
|
70
|
+
{copy.lede}
|
|
50
71
|
</Text>
|
|
51
72
|
<Box sx={{ pt: 1 }}>
|
|
52
73
|
<Button onClick={onStart} data-testid="ai-landing-start">
|
|
@@ -61,20 +82,25 @@ function Hero({ onStart }: { onStart: () => void }): React.JSX.Element {
|
|
|
61
82
|
* Homepage-style marketing landing for the AI integration (shown before the
|
|
62
83
|
* owner starts): a hero, the permission reassurance, a trust/feature strip, and
|
|
63
84
|
* the capability highlights. `onStart` begins the guided flow. `permissionModel`
|
|
64
|
-
* and `capabilities`
|
|
85
|
+
* and `capabilities` are REQUIRED host copy — the package ships no default
|
|
86
|
+
* sentence (FUT-760).
|
|
65
87
|
*/
|
|
66
88
|
export function AiLanding({
|
|
67
89
|
onStart,
|
|
68
|
-
permissionModel
|
|
69
|
-
capabilities
|
|
90
|
+
permissionModel,
|
|
91
|
+
capabilities,
|
|
92
|
+
copy,
|
|
93
|
+
capabilitiesCopy,
|
|
70
94
|
}: {
|
|
71
95
|
onStart: () => void;
|
|
72
|
-
permissionModel
|
|
73
|
-
capabilities
|
|
96
|
+
permissionModel: string;
|
|
97
|
+
capabilities: readonly AiCapability[];
|
|
98
|
+
copy: AiLandingCopy;
|
|
99
|
+
capabilitiesCopy: AiCapabilitiesCopy;
|
|
74
100
|
}): React.JSX.Element {
|
|
75
101
|
return (
|
|
76
102
|
<Stack spacing={6} data-testid="ai-landing">
|
|
77
|
-
<Hero onStart={onStart} />
|
|
103
|
+
<Hero onStart={onStart} copy={copy} />
|
|
78
104
|
|
|
79
105
|
<Stack
|
|
80
106
|
direction="row"
|
|
@@ -111,14 +137,14 @@ export function AiLanding({
|
|
|
111
137
|
gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr", md: "repeat(4, 1fr)" },
|
|
112
138
|
}}
|
|
113
139
|
>
|
|
114
|
-
{
|
|
140
|
+
{trustBadges(copy.trust).map((f) => (
|
|
115
141
|
<FeatureBadge key={f.label} icon={f.icon} label={f.label} caption={f.caption} />
|
|
116
142
|
))}
|
|
117
143
|
</Box>
|
|
118
144
|
</Box>
|
|
119
145
|
|
|
120
146
|
<Box>
|
|
121
|
-
<AiCapabilities capabilities={capabilities} />
|
|
147
|
+
<AiCapabilities capabilities={capabilities} copy={capabilitiesCopy} />
|
|
122
148
|
</Box>
|
|
123
149
|
</Stack>
|
|
124
150
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import type { McpAiCopy } from "./copy";
|
|
3
4
|
import {
|
|
4
5
|
GuidedSection,
|
|
5
6
|
OnboardingProvider,
|
|
@@ -9,9 +10,6 @@ import {
|
|
|
9
10
|
} from "@12-apps/onboarding";
|
|
10
11
|
|
|
11
12
|
import {
|
|
12
|
-
AI_CAPABILITIES,
|
|
13
|
-
aiHostGuides,
|
|
14
|
-
AI_PERMISSION_MODEL,
|
|
15
13
|
type AiCapability,
|
|
16
14
|
type AiHostGuide,
|
|
17
15
|
} from "../guide";
|
|
@@ -44,20 +42,20 @@ export interface AiIntegrationOnboardingProps {
|
|
|
44
42
|
/** Show the dev-only "reset onboarding" button. @default false */
|
|
45
43
|
devReset?: boolean;
|
|
46
44
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
45
|
+
* Assistants offered in the flow, with their step-by-step instructions.
|
|
46
|
+
*
|
|
47
|
+
* REQUIRED since FUT-760. These used to default to this package's own pt-BR
|
|
48
|
+
* walkthrough, so a host that said nothing shipped one product's Portuguese
|
|
49
|
+
* and had no field to decline it. `PT_BR_AI_HOST_GUIDES(platformName)` is that
|
|
50
|
+
* exact content, now chosen by name.
|
|
53
51
|
*/
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
|
|
52
|
+
hosts: readonly AiHostGuide[];
|
|
53
|
+
/** Capability cards on the landing. REQUIRED — see `hosts`. */
|
|
54
|
+
capabilities: readonly AiCapability[];
|
|
55
|
+
/** Permission reassurance copy on the landing. REQUIRED — see `hosts`. */
|
|
56
|
+
permissionModel: string;
|
|
57
|
+
/** Every sentence the screens render. REQUIRED — see `hosts`. */
|
|
58
|
+
copy: McpAiCopy;
|
|
61
59
|
/**
|
|
62
60
|
* Message the owner pastes into the assistant on the Conectar step.
|
|
63
61
|
*
|
|
@@ -97,6 +95,7 @@ interface FlowProps {
|
|
|
97
95
|
onRetest: () => void;
|
|
98
96
|
onDisconnect: DisconnectHandler | undefined;
|
|
99
97
|
devReset: boolean;
|
|
98
|
+
copy: McpAiCopy;
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
/**
|
|
@@ -116,6 +115,7 @@ function AiOnboardingFlow(props: FlowProps): React.JSX.Element {
|
|
|
116
115
|
onRetest,
|
|
117
116
|
onDisconnect,
|
|
118
117
|
devReset,
|
|
118
|
+
copy,
|
|
119
119
|
} = props;
|
|
120
120
|
const { state } = useOnboarding();
|
|
121
121
|
const selectedHost =
|
|
@@ -128,6 +128,7 @@ function AiOnboardingFlow(props: FlowProps): React.JSX.Element {
|
|
|
128
128
|
connectPrompt,
|
|
129
129
|
connections,
|
|
130
130
|
onRetest,
|
|
131
|
+
copy,
|
|
131
132
|
});
|
|
132
133
|
const connectedHostId = (state.data.connectedHost ??
|
|
133
134
|
state.data.selectedHost) as string | undefined;
|
|
@@ -135,24 +136,28 @@ function AiOnboardingFlow(props: FlowProps): React.JSX.Element {
|
|
|
135
136
|
return (
|
|
136
137
|
<GuidedSection
|
|
137
138
|
steps={steps}
|
|
138
|
-
title=
|
|
139
|
-
startLabel=
|
|
139
|
+
title={copy.onboarding.title}
|
|
140
|
+
startLabel={copy.landing.start}
|
|
140
141
|
renderLanding={(start) => (
|
|
141
142
|
<AiLanding
|
|
142
143
|
onStart={start}
|
|
143
144
|
permissionModel={permissionModel}
|
|
144
145
|
capabilities={capabilities}
|
|
146
|
+
copy={copy.landing}
|
|
147
|
+
capabilitiesCopy={copy.capabilities}
|
|
145
148
|
/>
|
|
146
149
|
)}
|
|
147
|
-
configuredTitle={connectedTitle(connections, hosts, connectedHostId)}
|
|
148
|
-
configuredSummary={connectedSummary(connections)}
|
|
149
|
-
editLabel=
|
|
150
|
+
configuredTitle={connectedTitle(connections, hosts, connectedHostId, copy.summary)}
|
|
151
|
+
configuredSummary={connectedSummary(connections, copy.summary)}
|
|
152
|
+
editLabel={copy.onboarding.editLabel}
|
|
153
|
+
collapseLabel={copy.onboarding.collapseLabel}
|
|
150
154
|
completedContent={(nav) => (
|
|
151
155
|
<StatusBoard
|
|
152
156
|
nav={nav}
|
|
153
157
|
connections={connections}
|
|
154
158
|
hosts={hosts}
|
|
155
159
|
onDisconnect={onDisconnect}
|
|
160
|
+
copy={copy}
|
|
156
161
|
/>
|
|
157
162
|
)}
|
|
158
163
|
devReset={devReset}
|
|
@@ -179,15 +184,15 @@ export function AiIntegrationOnboarding({
|
|
|
179
184
|
connections,
|
|
180
185
|
featureKey = DEFAULT_FEATURE_KEY,
|
|
181
186
|
devReset = false,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
permissionModel = AI_PERMISSION_MODEL,
|
|
187
|
+
hosts,
|
|
188
|
+
capabilities,
|
|
189
|
+
permissionModel,
|
|
186
190
|
connectPrompt,
|
|
187
191
|
onRetest = () => {
|
|
188
192
|
if (typeof window !== "undefined") window.location.reload();
|
|
189
193
|
},
|
|
190
194
|
onDisconnect,
|
|
195
|
+
copy,
|
|
191
196
|
}: AiIntegrationOnboardingProps): React.JSX.Element {
|
|
192
197
|
return (
|
|
193
198
|
<OnboardingProvider
|
|
@@ -205,6 +210,7 @@ export function AiIntegrationOnboarding({
|
|
|
205
210
|
onRetest={onRetest}
|
|
206
211
|
onDisconnect={onDisconnect}
|
|
207
212
|
devReset={devReset}
|
|
213
|
+
copy={copy}
|
|
208
214
|
/>
|
|
209
215
|
</OnboardingProvider>
|
|
210
216
|
);
|