@12-apps/mcp 3.8.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react/index.d.ts
CHANGED
|
@@ -128,6 +128,8 @@ interface AiConnectionSummaryCopy {
|
|
|
128
128
|
connectedGeneric: string;
|
|
129
129
|
}
|
|
130
130
|
interface AiHostSelectCopy {
|
|
131
|
+
/** The step's own heading, above the host tiles. */
|
|
132
|
+
heading: string;
|
|
131
133
|
/** Why the owner is picking, under the host tiles. */
|
|
132
134
|
caption: string;
|
|
133
135
|
}
|
package/dist/react/index.js
CHANGED
|
@@ -245,7 +245,7 @@ function Hero({
|
|
|
245
245
|
copy.titleTail
|
|
246
246
|
] }),
|
|
247
247
|
/* @__PURE__ */ jsx4(Text3, { variant: "body", color: "secondary", as: "p", children: copy.lede }),
|
|
248
|
-
/* @__PURE__ */ jsx4(Box4, { sx: { pt: 1 }, children: /* @__PURE__ */ jsx4(Button, { onClick: onStart, "data-testid": "ai-landing-start", children:
|
|
248
|
+
/* @__PURE__ */ jsx4(Box4, { sx: { pt: 1 }, children: /* @__PURE__ */ jsx4(Button, { onClick: onStart, "data-testid": "ai-landing-start", children: copy.start }) })
|
|
249
249
|
] });
|
|
250
250
|
}
|
|
251
251
|
__name(Hero, "Hero");
|
|
@@ -970,7 +970,7 @@ function HostSelectStep({
|
|
|
970
970
|
}) {
|
|
971
971
|
return /* @__PURE__ */ jsxs7(Stack6, { spacing: 3, "data-testid": "ai-host-select", children: [
|
|
972
972
|
/* @__PURE__ */ jsxs7(Box8, { children: [
|
|
973
|
-
/* @__PURE__ */ jsx9(Text7, { variant: "heading", size: "sm", as: "h2", children:
|
|
973
|
+
/* @__PURE__ */ jsx9(Text7, { variant: "heading", size: "sm", as: "h2", children: copy.heading }),
|
|
974
974
|
/* @__PURE__ */ jsx9(Text7, { variant: "caption", as: "p", color: "secondary", children: copy.caption })
|
|
975
975
|
] }),
|
|
976
976
|
/* @__PURE__ */ jsx9(
|
|
@@ -1332,6 +1332,7 @@ var PT_BR_MCP_AI_COPY = {
|
|
|
1332
1332
|
connectedGeneric: "IA conectada"
|
|
1333
1333
|
},
|
|
1334
1334
|
hostSelect: {
|
|
1335
|
+
heading: "Escolha o seu assistente",
|
|
1335
1336
|
caption: "Selecione onde voc\xEA usa a IA \u2014 o passo a passo \xE9 feito sob medida para ele."
|
|
1336
1337
|
},
|
|
1337
1338
|
connectGuide: {
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/ai-onboarding.tsx","../../src/react/ai-landing.tsx","../../src/react/ai-capabilities.tsx","../../src/react/ai-icons.tsx","../../src/react/feature-badge.tsx","../../src/react/ai-connection-utils.ts","../../src/react/ai-flow-steps.tsx","../../src/react/host-connect-guide.tsx","../../src/react/mcp-endpoint-url.tsx","../../src/react/ai-status-board.tsx","../../src/react/host-select-step.tsx","../../src/react/ai-steps.tsx","../../src/react/pt-BR.ts"],"sourcesContent":["\"use client\";\n\nimport type { McpAiCopy } from \"./copy\";\nimport {\n GuidedSection,\n OnboardingProvider,\n useOnboarding,\n type OnboardingStateSnapshot,\n type OnboardingStore,\n} from \"@12-apps/onboarding\";\n\nimport {\n type AiCapability,\n type AiHostGuide,\n} from \"../guide\";\nimport { AiLanding } from \"./ai-landing\";\nimport type { DisconnectHandler } from \"./ai-status-board\";\nimport {\n buildFlowSteps,\n connectedSummary,\n connectedTitle,\n StatusBoard,\n type AiConnection,\n} from \"./ai-steps\";\n\nexport type { AiConnection } from \"./ai-steps\";\n\n/** Props for the reusable AI-connect onboarding flow. */\nexport interface AiIntegrationOnboardingProps {\n /** Persistence seam — the app wires this to its own backend (server actions). */\n store: OnboardingStore;\n /** The MCP endpoint URL to paste (derived by the app from its public origin). */\n endpointUrl: string;\n /** The owner's saved progress (null → first run / landing). */\n initialState: OnboardingStateSnapshot | null;\n /** The live MCP connections (one per connected assistant; empty when none). */\n connections: readonly AiConnection[];\n /**\n * The onboarding namespace this flow's progress is stored under — the key\n * `@12-apps/onboarding` reads and writes, and the one the host's own\n * `featureKeys` allow-list has to contain.\n *\n * REQUIRED, on the same grounds as `hosts` and `copy` below. It defaulted to\n * `\"ai_integration\"`, which is one adopter's key: a host whose backend\n * declares `ai` or `mcp_connect` and says nothing here writes to a namespace\n * its own API rejects, so the wizard loses every step it saves and resumes\n * from nothing. Nothing warns, because a silent default is indistinguishable\n * from a deliberate one — and the failure only shows up as a refresh that\n * forgets, which reads as a bug in the host's persistence rather than as a\n * key nobody chose.\n */\n featureKey: string;\n /** Show the dev-only \"reset onboarding\" button. @default false */\n devReset?: boolean;\n /**\n * Assistants offered in the flow, with their step-by-step instructions.\n *\n * REQUIRED since FUT-760. These used to default to this package's own pt-BR\n * walkthrough, so a host that said nothing shipped one product's Portuguese\n * and had no field to decline it. `PT_BR_AI_HOST_GUIDES(platformName)` is that\n * exact content, now chosen by name.\n */\n hosts: readonly AiHostGuide[];\n /** Capability cards on the landing. REQUIRED — see `hosts`. */\n capabilities: readonly AiCapability[];\n /** Permission reassurance copy on the landing. REQUIRED — see `hosts`. */\n permissionModel: string;\n /** Every sentence the screens render. REQUIRED — see `hosts`. */\n copy: McpAiCopy;\n /**\n * Message the owner pastes into the assistant on the Conectar step.\n *\n * REQUIRED, with no default, because the useful version of it names TOOLS —\n * one to register the connection, one to read something real — and this\n * package neither defines nor serves any. It shipped a constant naming two\n * tools from one adopter's surface, so another host handed its owner a prompt\n * that called two things that did not exist, and the confirm step then waited\n * forever for a registration that could never happen. Build it with\n * `aiConnectPrompt({ … })`.\n */\n connectPrompt: string;\n /**\n * Re-check the live connection on the verify step's \"Testar conexão\" button —\n * apps pass a router refresh (e.g. Next's `router.refresh`). @default a full\n * `window.location.reload()`.\n */\n onRetest?: () => void;\n /**\n * Revoke a connected assistant's access, from the completed status board. The\n * host ID is the board's card, NOT the connection — `claude` and\n * `claude-desktop` share one provider, so the app resolves which stored\n * connection it owns (`providerForHostId`) and revokes that. Omitted → the\n * board stays read-only, which is the pre-existing behavior.\n */\n onDisconnect?: DisconnectHandler;\n}\n\n/** Resolved (defaults-applied) props threaded to the in-provider flow body. */\ninterface FlowProps {\n endpointUrl: string;\n connections: readonly AiConnection[];\n hosts: readonly AiHostGuide[];\n capabilities: readonly AiCapability[];\n permissionModel: string;\n connectPrompt: string;\n onRetest: () => void;\n onDisconnect: DisconnectHandler | undefined;\n devReset: boolean;\n copy: McpAiCopy;\n}\n\n/**\n * The flow body — inside the OnboardingProvider so it can read the selected host\n * and pick the path. A host with a published `pluginUrl` gets the simplified\n * Escolher → Instalar → Confirmar flow (no URL to copy); otherwise the full\n * Escolher → Copiar URL → Configurar → Conectar → Confirmar flow.\n */\nfunction AiOnboardingFlow(props: FlowProps): React.JSX.Element {\n const {\n endpointUrl,\n connections,\n hosts,\n capabilities,\n permissionModel,\n connectPrompt,\n onRetest,\n onDisconnect,\n devReset,\n copy,\n } = props;\n const { state } = useOnboarding();\n const selectedHost =\n hosts.find((h) => h.id === state.data.selectedHost) ?? hosts[0]!;\n\n const steps = buildFlowSteps({\n host: selectedHost,\n hosts,\n endpointUrl,\n connectPrompt,\n connections,\n onRetest,\n copy,\n });\n const connectedHostId = (state.data.connectedHost ??\n state.data.selectedHost) as string | undefined;\n\n return (\n <GuidedSection\n steps={steps}\n title={copy.onboarding.title}\n startLabel={copy.landing.start}\n renderLanding={(start) => (\n <AiLanding\n onStart={start}\n permissionModel={permissionModel}\n capabilities={capabilities}\n copy={copy.landing}\n capabilitiesCopy={copy.capabilities}\n />\n )}\n configuredTitle={connectedTitle(connections, hosts, connectedHostId, copy.summary)}\n configuredSummary={connectedSummary(connections, copy.summary)}\n editLabel={copy.onboarding.editLabel}\n collapseLabel={copy.onboarding.collapseLabel}\n completedContent={(nav) => (\n <StatusBoard\n nav={nav}\n connections={connections}\n hosts={hosts}\n onDisconnect={onDisconnect}\n copy={copy}\n />\n )}\n devReset={devReset}\n dataTestId=\"ai-onboarding\"\n />\n );\n}\n\n/**\n * URL-free, persisted onboarding for the AI/MCP integration — a five-step wizard\n * (pick an assistant, copy the store URL, configure the connector, connect, then\n * verify) whose position + chosen assistant are saved via `@12-apps/onboarding`, so\n * a refresh resumes exactly where the owner left off. The live MCP connection\n * signal drives the verify step and the completed status board.\n *\n * App-agnostic: the app supplies the persistence `store`, the `endpointUrl`, the\n * `featureKey` its own onboarding API serves, the live `connections` (one per\n * connected assistant), and every word on screen (`hosts`, `capabilities`,\n * `permissionModel`, `copy`). Nothing here has a default, because each of those\n * is a fact only the host holds and a default for it is silently wrong rather\n * than loudly missing.\n */\nexport function AiIntegrationOnboarding({\n store,\n endpointUrl,\n initialState,\n connections,\n featureKey,\n devReset = false,\n hosts,\n capabilities,\n permissionModel,\n connectPrompt,\n onRetest = () => {\n if (typeof window !== \"undefined\") window.location.reload();\n },\n onDisconnect,\n copy,\n}: AiIntegrationOnboardingProps): React.JSX.Element {\n return (\n <OnboardingProvider\n featureKey={featureKey}\n store={store}\n initialState={initialState}\n >\n <AiOnboardingFlow\n endpointUrl={endpointUrl}\n connections={connections}\n hosts={hosts}\n capabilities={capabilities}\n permissionModel={permissionModel}\n connectPrompt={connectPrompt}\n onRetest={onRetest}\n onDisconnect={onDisconnect}\n devReset={devReset}\n copy={copy}\n />\n </OnboardingProvider>\n );\n}\n","\"use client\";\n\nimport BoltOutlinedIcon from \"@mui/icons-material/BoltOutlined\";\nimport LanguageOutlinedIcon from \"@mui/icons-material/LanguageOutlined\";\nimport LockOpenOutlinedIcon from \"@mui/icons-material/LockOpenOutlined\";\nimport VerifiedUserOutlinedIcon from \"@mui/icons-material/VerifiedUserOutlined\";\n\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiCapability } from \"../guide\";\nimport type { AiCapabilitiesCopy, AiLandingCopy } from \"./copy\";\nimport { AiCapabilities } from \"./ai-capabilities\";\nimport { FeatureBadge, type FeatureBadgeItem } from \"./feature-badge\";\n\n/**\n * The ICONS for the landing's reassurance strip, keyed by the copy's own ids.\n *\n * The package keeps the icons and the host keeps the words: an icon is not\n * copy, and a pack that had to ship React elements could not be a plain data\n * file. An id the map does not know renders without an icon rather than\n * throwing — a host adding a fifth point should get its words on screen.\n */\nconst TRUST_ICONS: Readonly<Record<string, React.JSX.Element>> = {\n login: <LockOpenOutlinedIcon />,\n install: <BoltOutlinedIcon />,\n permissions: <VerifiedUserOutlinedIcon />,\n surface: <LanguageOutlinedIcon />,\n};\n\nfunction trustBadges(trust: AiLandingCopy[\"trust\"]): FeatureBadgeItem[] {\n return trust.map((point) => ({\n icon: TRUST_ICONS[point.id],\n label: point.label,\n caption: point.caption,\n }));\n}\n\n/** The single-column marketing hero: eyebrow + headline + description + CTA. */\nfunction Hero({\n onStart,\n copy,\n}: {\n onStart: () => void;\n copy: AiLandingCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={2.5} sx={{ maxWidth: 680 }}>\n <Box\n sx={{\n color: \"primary.main\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 1.2,\n textTransform: \"uppercase\",\n }}\n >\n {copy.eyebrow}\n </Box>\n <Text variant=\"heading\" size=\"xl\" weight=\"bold\" as=\"h1\">\n Conecte{\" \"}\n <Box component=\"span\" sx={{ color: \"primary.main\" }}>\n assistentes de IA\n </Box>{\" \"}\n {copy.titleTail}\n </Text>\n <Text variant=\"body\" color=\"secondary\" as=\"p\">\n {copy.lede}\n </Text>\n <Box sx={{ pt: 1 }}>\n <Button onClick={onStart} data-testid=\"ai-landing-start\">\n Ver como conectar\n </Button>\n </Box>\n </Stack>\n );\n}\n\n/**\n * Homepage-style marketing landing for the AI integration (shown before the\n * owner starts): a hero, the permission reassurance, a trust/feature strip, and\n * the capability highlights. `onStart` begins the guided flow. `permissionModel`\n * and `capabilities` are REQUIRED host copy — the package ships no default\n * sentence (FUT-760).\n */\nexport function AiLanding({\n onStart,\n permissionModel,\n capabilities,\n copy,\n capabilitiesCopy,\n}: {\n onStart: () => void;\n permissionModel: string;\n capabilities: readonly AiCapability[];\n copy: AiLandingCopy;\n capabilitiesCopy: AiCapabilitiesCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={6} data-testid=\"ai-landing\">\n <Hero onStart={onStart} copy={copy} />\n\n <Stack\n direction=\"row\"\n spacing={1.5}\n alignItems=\"flex-start\"\n data-testid=\"ai-permission-callout\"\n sx={{\n p: 2,\n borderRadius: 2,\n bgcolor: \"action.hover\",\n border: 1,\n borderColor: \"divider\",\n }}\n >\n <VerifiedUserOutlinedIcon sx={{ color: \"success.main\", mt: 0.25 }} />\n <Text variant=\"body\" as=\"p\">\n {permissionModel}\n </Text>\n </Stack>\n\n <Box\n sx={{\n p: { xs: 2.5, md: 3 },\n borderRadius: 3,\n bgcolor: \"action.hover\",\n border: 1,\n borderColor: \"divider\",\n }}\n >\n <Box\n sx={{\n display: \"grid\",\n gap: 3,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\", md: \"repeat(4, 1fr)\" },\n }}\n >\n {trustBadges(copy.trust).map((f) => (\n <FeatureBadge key={f.label} icon={f.icon} label={f.label} caption={f.caption} />\n ))}\n </Box>\n </Box>\n\n <Box>\n <AiCapabilities capabilities={capabilities} copy={capabilitiesCopy} />\n </Box>\n </Stack>\n );\n}\n","import { Box } from \"@12-apps/ui/mui/Box\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiCapability } from \"../guide\";\nimport type { AiCapabilitiesCopy } from \"./copy\";\nimport { CapabilityIcon } from \"./ai-icons\";\n\n/** One marketing card: an icon, a headline and an example prompt (as a bubble). */\nfunction CapabilityCard({ capability }: { capability: AiCapability }): React.JSX.Element {\n return (\n <Box\n data-testid={`ai-capability-${capability.id}`}\n sx={{\n p: 2.5,\n borderRadius: 3,\n border: 1,\n borderColor: \"divider\",\n bgcolor: \"background.paper\",\n height: \"100%\",\n // Static transition string: safe to cross the server→client boundary.\n transition: \"border-color 200ms, box-shadow 200ms, transform 200ms\",\n \"&:hover\": { borderColor: \"primary.main\", boxShadow: 3, transform: \"translateY(-3px)\" },\n }}\n >\n <Box\n sx={{\n width: 44,\n height: 44,\n borderRadius: 2,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n bgcolor: \"primary.main\",\n color: \"primary.contrastText\",\n mb: 1.5,\n }}\n >\n <CapabilityIcon id={capability.id} fontSize={26} />\n </Box>\n <Text variant=\"body\" weight=\"bold\" as=\"h3\">\n {capability.title}\n </Text>\n <Box\n data-testid={`ai-capability-prompt-${capability.id}`}\n sx={{\n mt: 1,\n px: 1.5,\n py: 1,\n borderRadius: 2,\n borderBottomLeftRadius: 4,\n bgcolor: \"action.hover\",\n border: 1,\n borderColor: \"divider\",\n }}\n >\n <Text variant=\"body\" size=\"sm\" as=\"p\" color=\"secondary\">\n {capability.detail}\n </Text>\n </Box>\n </Box>\n );\n}\n\n/**\n * Marketing block for the AI integration: a headline + a responsive grid of\n * capability cards. Shown on the onboarding landing (before the owner starts) to\n * sell the feature — \"here's what the assistant does for you\". `capabilities`\n * and `copy` are REQUIRED host copy — the package ships no default sentence\n * (FUT-760).\n */\nexport function AiCapabilities({\n capabilities,\n copy,\n}: {\n capabilities: readonly AiCapability[];\n copy: AiCapabilitiesCopy;\n}): React.JSX.Element {\n return (\n <Box data-testid=\"ai-capability-examples\" sx={{ width: \"100%\" }}>\n <Box sx={{ mb: 3 }}>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n {copy.heading}\n </Text>\n <Box sx={{ mt: 0.5 }}>\n <Text variant=\"body\" size=\"sm\" as=\"p\" color=\"secondary\">\n {copy.subheading}\n </Text>\n </Box>\n </Box>\n <Box\n sx={{\n display: \"grid\",\n gap: 3,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\", md: \"repeat(4, 1fr)\" },\n }}\n >\n {capabilities.map((capability) => (\n <CapabilityCard key={capability.id} capability={capability} />\n ))}\n </Box>\n </Box>\n );\n}\n","import AutoAwesomeIcon from \"@mui/icons-material/AutoAwesome\";\nimport CategoryIcon from \"@mui/icons-material/Category\";\nimport HubIcon from \"@mui/icons-material/Hub\";\nimport Inventory2Icon from \"@mui/icons-material/Inventory2\";\nimport QueryStatsIcon from \"@mui/icons-material/QueryStats\";\nimport ReceiptLongIcon from \"@mui/icons-material/ReceiptLong\";\n\nimport { Box } from \"@12-apps/ui/mui/Box\";\n\nimport type { AiHostBrand } from \"../guide\";\n\n/**\n * Brand accents for the host avatars. These are deliberately hardcoded (not\n * theme tokens): they are BRAND marks whose recognizability depends on the\n * vendor's own accent colour, so the \"always semantic colours\" rule doesn't\n * apply here. The glyphs are simple, original stand-ins — not the vendors'\n * proprietary logo artwork.\n */\nconst BRAND: Record<AiHostBrand, { bg: string; Icon: typeof AutoAwesomeIcon; label: string }> = {\n claude: { bg: \"#D97757\", Icon: AutoAwesomeIcon, label: \"Claude (Anthropic)\" },\n openai: { bg: \"#10A37F\", Icon: HubIcon, label: \"OpenAI\" },\n};\n\n/** A round brand chip: the vendor accent + a simple glyph. */\nexport function HostBrandAvatar({\n brand,\n size = 40,\n}: {\n brand: AiHostBrand;\n size?: number;\n}): React.JSX.Element {\n const { bg, Icon, label } = BRAND[brand];\n return (\n <Box\n aria-label={label}\n sx={{\n width: size,\n height: size,\n borderRadius: \"50%\",\n bgcolor: bg,\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n }}\n >\n <Icon sx={{ fontSize: size * 0.55 }} />\n </Box>\n );\n}\n\nconst CAPABILITY_ICON: Record<string, typeof AutoAwesomeIcon> = {\n orders: ReceiptLongIcon,\n inventory: Inventory2Icon,\n catalog: CategoryIcon,\n sales: QueryStatsIcon,\n};\n\n/** The icon for a capability card, by capability id (falls back to a sparkle). */\nexport function CapabilityIcon({\n id,\n fontSize = 24,\n}: {\n id: string;\n fontSize?: number;\n}): React.JSX.Element {\n const Icon = CAPABILITY_ICON[id] ?? AutoAwesomeIcon;\n return <Icon sx={{ fontSize }} />;\n}\n","import { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\n/** One entry of a landing's trust/feature strip. */\nexport interface FeatureBadgeItem {\n icon: React.ReactNode;\n label: string;\n caption: string;\n}\n\n/**\n * One item of an onboarding landing's trust/feature strip: a paper icon tile\n * (primary-coloured glyph) with a two-line label + caption.\n */\nexport function FeatureBadge({ icon, label, caption }: FeatureBadgeItem): React.JSX.Element {\n return (\n <Stack direction=\"row\" spacing={1.5} alignItems=\"flex-start\">\n <Box\n sx={{\n width: 36,\n height: 36,\n borderRadius: 2,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n bgcolor: \"background.paper\",\n color: \"primary.main\",\n border: 1,\n borderColor: \"divider\",\n flexShrink: 0,\n }}\n >\n {icon}\n </Box>\n <Box>\n <Text variant=\"body\" size=\"sm\" weight=\"bold\" as=\"p\">\n {label}\n </Text>\n <Text variant=\"caption\" color=\"secondary\" as=\"p\">\n {caption}\n </Text>\n </Box>\n </Stack>\n );\n}\n","import type { AiConnectionSummaryCopy } from \"./copy\";\nimport { providerForHostId, type AiHostGuide, type AiProvider } from \"../guide\";\n\n/**\n * Pure helpers + the connection type shared by the AI-onboarding flow steps\n * (`ai-flow-steps.tsx`) and the orchestration/status board (`ai-steps.tsx`),\n * kept here so neither JSX module has to import the other (no import cycle).\n */\n\n/** The live connection surfaced from the server (empty list when none). */\nexport interface AiConnection {\n clientName: string | null;\n /**\n * The provider this connection is attributed to (derived server-side from the\n * OAuth client's redirect URIs / confirmed by `announceAiConnection`). `null`\n * for a legacy connection recorded before attribution existed — matched\n * best-effort to whichever host the owner is connecting.\n */\n host: AiProvider | null;\n lastActiveAt: Date;\n}\n\n/** Friendly provider names for the connected-state title (\"Claude Conectado\"). */\nconst PROVIDER_LABEL: Record<AiProvider, string> = {\n claude: \"Claude\",\n chatgpt: \"ChatGPT\",\n codex: \"Codex\",\n};\n\n/** Resolve a persisted host id to its guide (falls back to the first host). */\nexport function resolveHost(hosts: readonly AiHostGuide[], hostId: unknown): AiHostGuide {\n const found = hosts.find((h) => h.id === hostId) ?? hosts[0];\n if (!found) throw new Error(\"resolveHost: hosts array must not be empty\");\n return found;\n}\n\n/** Friendly label for a persisted host id (falls back to a generic word). */\nexport function hostLabel(hosts: readonly AiHostGuide[], hostId: unknown): string {\n return hosts.find((h) => h.id === hostId)?.label ?? \"seu assistente\";\n}\n\n/**\n * The live connection for a given host, or null. A connection is matched by its\n * derived provider; a legacy `null`-host connection matches best-effort (so the\n * pre-attribution single-connection behavior still works).\n */\nexport function connectionForHost(\n connections: readonly AiConnection[],\n hostId: unknown,\n): AiConnection | null {\n const provider = typeof hostId === \"string\" ? providerForHostId(hostId) : null;\n if (!provider) return connections.find((c) => c.host === null) ?? connections[0] ?? null;\n return (\n connections.find((c) => c.host === provider) ?? connections.find((c) => c.host === null) ?? null\n );\n}\n\n/** The recency line from a timestamp, in the host's own words. */\nexport function activeAgo(date: Date, copy: AiConnectionSummaryCopy): string {\n const minutes = Math.max(0, Math.floor((Date.now() - date.getTime()) / 60_000));\n if (minutes < 1) return copy.activeNow;\n if (minutes < 60) return copy.activeMinutes(minutes);\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return copy.activeHours(hours);\n return copy.activeDays(Math.floor(hours / 24));\n}\n\n/** The most-recently-active connection across all providers (null when none). */\nfunction mostRecent(connections: readonly AiConnection[]): AiConnection | null {\n return connections.reduce<AiConnection | null>(\n (best, c) => (!best || c.lastActiveAt.getTime() > best.lastActiveAt.getTime() ? c : best),\n null,\n );\n}\n\n/** The configured-state TITLE, naming the connected assistant(s) — FUT req (F). */\nexport function connectedTitle(\n connections: readonly AiConnection[],\n hosts: readonly AiHostGuide[],\n connectedHostId: string | undefined,\n copy: AiConnectionSummaryCopy,\n): string {\n const providers = [...new Set(connections.map((c) => c.host).filter((h): h is AiProvider => h !== null))];\n if (providers.length === 1) return `${PROVIDER_LABEL[providers[0]!]} ${copy.connectedSuffix}`;\n if (providers.length > 1) {\n return copy.connectedSeveral(providers.map((p) => PROVIDER_LABEL[p]).join(\", \"));\n }\n // Legacy connection with no attributed provider — name the completed host.\n if (connections.length > 0) return `${hostLabel(hosts, connectedHostId)} ${copy.connectedSuffix}`;\n return copy.connectedGeneric;\n}\n\n/** The completed summary line (second line) for the configured-state header. */\nexport function connectedSummary(\n connections: readonly AiConnection[],\n copy: AiConnectionSummaryCopy,\n): string {\n const recent = mostRecent(connections);\n if (!recent) return copy.configured;\n return activeAgo(recent.lastActiveAt, copy);\n}\n","\"use client\";\n\nimport type { McpAiCopy } from \"./copy\";\nimport CheckCircleIcon from \"@mui/icons-material/CheckCircle\";\nimport OpenInNewIcon from \"@mui/icons-material/OpenInNew\";\nimport { useEffect, useState } from \"react\";\n\nimport { type GuidedNav } from \"@12-apps/onboarding\";\nimport { Progress } from \"@12-apps/ui/data-display/Progress\";\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostConfigureStage, AiHostGuide } from \"../guide\";\nimport { activeAgo, connectionForHost, hostLabel, type AiConnection } from \"./ai-connection-utils\";\nimport {\n EndpointCopyBlock,\n HostConnectHeader,\n HostDocsLink,\n HostOpenButton,\n HostStepList,\n PromptCopyBlock,\n} from \"./host-connect-guide\";\n\n/** The host's connect steps split across the Configurar / Conectar stages. */\nconst CONFIGURE_STEP_COUNT = 3;\n\n/** How often the Confirmar step re-checks the live connection while waiting. */\nconst POLL_INTERVAL_MS = 3000;\n\n/** A step's continue/back controls (Voltar left, primary next right). */\nfunction StepNav({\n nav,\n onNext,\n nextLabel,\n nextDisabled = false,\n nextTestId,\n copy,\n}: {\n nav: GuidedNav;\n onNext: () => void;\n nextLabel?: string;\n nextDisabled?: boolean;\n nextTestId?: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n return (\n <Stack direction=\"row\" spacing={1} alignItems=\"center\" justifyContent=\"space-between\">\n <Button variant=\"ghost\" onClick={() => nav.back()} data-testid=\"ai-step-back\">{copy.flow.back}</Button>\n <Button onClick={onNext} disabled={nextDisabled} data-testid={nextTestId}>\n {nextLabel}\n </Button>\n </Stack>\n );\n}\n\n/** Step 2 — copy the store URL; copying is the action that advances the wizard. */\nexport function CopyUrlStep({\n nav,\n endpointUrl,\n copy,\n}: {\n nav: GuidedNav;\n endpointUrl: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={3} data-testid=\"ai-copy-step\">\n <Box>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n {copy.flow.copyUrlTitle}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.flow.urlCaption}\n </Text>\n </Box>\n <EndpointCopyBlock copy={copy.connectGuide} flowCopy={copy.flow} endpointUrl={endpointUrl} copied={false} onCopy={() => nav.next()} />\n <Box>\n <Button variant=\"ghost\" onClick={() => nav.back()} data-testid=\"ai-step-back\">{copy.flow.back}</Button>\n </Box>\n </Stack>\n );\n}\n\n/** Step 3 — open the host's connectors and add + configure the custom connector. */\nexport function ConfigureStep({\n nav,\n host,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n copy: McpAiCopy;\n}): React.JSX.Element {\n // Hosts with no direct link (e.g. Claude Desktop) have nothing to open, so\n // \"Próximo\" is available immediately; otherwise it unlocks on the open click.\n const [opened, setOpened] = useState(!host.link);\n return (\n <Stack spacing={2.5} data-testid=\"ai-configure-step\">\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n <HostOpenButton host={host} onOpen={() => setOpened(true)} />\n <HostStepList steps={host.steps.slice(0, CONFIGURE_STEP_COUNT)} start={1} />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy} nav={nav} onNext={() => nav.next()} nextDisabled={!opened} nextTestId=\"ai-configure-next\" />\n </Stack>\n );\n}\n\n/**\n * One stage of a host's per-stage configuration (e.g. ChatGPT's \"enable\n * developer mode\" then \"configurar\"). Each stage has its OWN deep link — opening\n * it unlocks \"Próximo\" — and its own instructions.\n */\nexport function ConfigureStageStep({\n nav,\n host,\n stage,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n stage: AiHostConfigureStage;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const [opened, setOpened] = useState(!stage.link);\n return (\n <Stack spacing={2.5} data-testid={`ai-stage-${stage.id}`}>\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n {stage.link && (\n <Box>\n <Button\n onClick={() => {\n window.open(stage.link!.url, \"_blank\", \"noopener,noreferrer\");\n setOpened(true);\n }}\n data-testid={`ai-stage-link-${stage.id}`}\n >\n {stage.link.label}\n <OpenInNewIcon sx={{ fontSize: 16, ml: 0.5 }} />\n </Button>\n </Box>\n )}\n <HostStepList steps={stage.steps} start={1} />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy}\n nav={nav}\n onNext={() => nav.next()}\n nextDisabled={!opened}\n nextTestId={`ai-stage-next-${stage.id}`}\n />\n </Stack>\n );\n}\n\n/** Step 4 — connect: log in, authorize and activate the connector. */\nexport function ConnectStep({\n nav,\n host,\n connectPrompt,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n connectPrompt: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={2.5} data-testid=\"ai-connect-step\">\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n <HostStepList steps={host.steps.slice(CONFIGURE_STEP_COUNT)} start={CONFIGURE_STEP_COUNT + 1} />\n <PromptCopyBlock flowCopy={copy.flow}\n title={copy.flow.pasteTitle}\n caption={copy.flow.promptCaption}\n message={connectPrompt}\n />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy} nav={nav} onNext={() => nav.next()} nextLabel={copy.flow.advance} nextTestId=\"ai-connect-done\" />\n </Stack>\n );\n}\n\n/**\n * Simplified-flow step (host has a published `pluginUrl`): open the one-click\n * plugin (install + authorize), then paste the prompt asking the assistant to\n * connect. No URL to copy, no manual connector. The next step (Confirmar) waits.\n */\nexport function InstallStep({\n nav,\n host,\n connectPrompt,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n connectPrompt: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const [opened, setOpened] = useState(false);\n return (\n <Stack spacing={2.5} data-testid=\"ai-install-step\">\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n <Text variant=\"body\" as=\"p\" color=\"secondary\">\n {copy.flow.installBody}\n </Text>\n {host.pluginUrl && (\n <Box>\n <Button\n onClick={() => {\n window.open(host.pluginUrl!, \"_blank\", \"noopener,noreferrer\");\n setOpened(true);\n }}\n data-testid=\"ai-install-open\"\n >\n {copy.flow.installAction}\n <OpenInNewIcon sx={{ fontSize: 16, ml: 0.5 }} />\n </Button>\n </Box>\n )}\n <PromptCopyBlock flowCopy={copy.flow}\n title={copy.flow.askTitle}\n caption={copy.flow.pasteInstallCaption}\n message={connectPrompt}\n />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy}\n nav={nav}\n onNext={() => nav.next()}\n nextLabel={copy.flow.advance}\n nextDisabled={!opened}\n nextTestId=\"ai-install-done\"\n />\n </Stack>\n );\n}\n\n/**\n * Step 5: auto-detect the live connection. While waiting it polls the server\n * (the sign-in / `announceAiConnection` tool call registers the connection\n * server-side), showing a spinner — the owner never clicks \"verify\". Completes\n * when the selected host's connection appears.\n */\nexport function ConfirmStep({\n nav,\n connections,\n hosts,\n onRetest,\n copy,\n}: {\n nav: GuidedNav;\n connections: readonly AiConnection[];\n hosts: readonly AiHostGuide[];\n onRetest: () => void;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const selectedHostId = nav.data.selectedHost as string | undefined;\n const connection = connectionForHost(connections, selectedHostId);\n const label = connection?.clientName ?? hostLabel(hosts, selectedHostId);\n\n // Auto-detect: re-check on an interval until the connection shows up. The\n // interval is cleared as soon as `connection` is non-null (and on unmount).\n useEffect(() => {\n if (connection) return undefined;\n const id = setInterval(() => onRetest(), POLL_INTERVAL_MS);\n return () => clearInterval(id);\n }, [connection, onRetest]);\n\n if (connection) {\n return (\n <Stack spacing={2} data-testid=\"ai-confirm-connected\">\n <Stack direction=\"row\" spacing={1.5} alignItems=\"center\">\n <CheckCircleIcon sx={{ color: \"success.main\" }} />\n <Box>\n <Text variant=\"body\" weight=\"bold\" as=\"p\">\n {copy.flow.connectedTo(label)}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {activeAgo(connection.lastActiveAt, copy.summary)}\n </Text>\n </Box>\n </Stack>\n <Box>\n <Button onClick={() => nav.complete({ connectedHost: selectedHostId })}>{copy.flow.finish}</Button>\n </Box>\n </Stack>\n );\n }\n\n return (\n <Stack spacing={2.5} data-testid=\"ai-confirm-waiting\">\n <Stack direction=\"row\" spacing={1.5} alignItems=\"center\">\n <Progress variant=\"circular\" circularSize={22} thickness={4} dataTestId=\"ai-confirm-spinner\" />\n <Box>\n <Text variant=\"body\" weight=\"bold\" as=\"p\">\n {copy.flow.waitingTitle}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.flow.waitingBody(label)}\n </Text>\n </Box>\n </Stack>\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRetest} data-testid=\"ai-confirm-retest\">\n {copy.flow.testNow}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => nav.back()}>{copy.flow.back}</Button>\n </Stack>\n </Stack>\n );\n}\n","\"use client\";\n\nimport type { AiConnectGuideCopy, AiFlowCopy } from \"./copy\";\nimport CheckIcon from \"@mui/icons-material/Check\";\nimport ContentCopyOutlinedIcon from \"@mui/icons-material/ContentCopyOutlined\";\nimport OpenInNewIcon from \"@mui/icons-material/OpenInNew\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostGuide } from \"../guide\";\nimport { HostBrandAvatar } from \"./ai-icons\";\nimport { McpEndpointUrl } from \"./mcp-endpoint-url\";\n\n/**\n * The store's MCP endpoint URL with a blue \"Copiar\" button (the display-only\n * field defers the copy to this button). Controlled: `copied` flips the label to\n * \"Copiado\" and `onCopy` fires after the clipboard write — the wizard uses it to\n * unlock the \"Próximo\" button on the Copiar-URL step.\n */\nexport function EndpointCopyBlock({\n endpointUrl,\n copied,\n onCopy,\n flowCopy,\n copy,\n}: {\n endpointUrl: string;\n copied: boolean;\n onCopy: () => void;\n flowCopy: AiFlowCopy;\n copy: AiConnectGuideCopy;\n}): React.JSX.Element {\n const handleClick = (): void => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n void navigator.clipboard.writeText(endpointUrl).catch(() => undefined);\n }\n onCopy();\n };\n\n return (\n <Box\n sx={{\n p: 2,\n borderRadius: 2,\n border: 1,\n borderColor: \"primary.main\",\n bgcolor: \"action.hover\",\n }}\n >\n <Text variant=\"caption\" as=\"p\" weight=\"bold\">\n {copy.urlLabel}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.urlHint}\n </Text>\n <Box sx={{ mt: 1 }}>\n <McpEndpointUrl url={endpointUrl} copyable={false} />\n </Box>\n <Box sx={{ mt: 1.5 }}>\n <Button onClick={handleClick} data-testid=\"ai-copy-endpoint\">\n {copied ? (\n <CheckIcon sx={{ fontSize: 18, mr: 0.5 }} />\n ) : (\n <ContentCopyOutlinedIcon sx={{ fontSize: 18, mr: 0.5 }} />\n )}\n {copied ? flowCopy.copied : flowCopy.copyUrl}\n </Button>\n </Box>\n </Box>\n );\n}\n\n/**\n * A copyable multi-line message block (preserves line breaks). Used on the\n * Conectar step for the prompt the owner pastes into the assistant so it\n * identifies itself and calls a tool (which registers the connection).\n */\nexport function PromptCopyBlock({\n title,\n caption,\n message,\n flowCopy,\n}: {\n title: string;\n caption: string;\n message: string;\n flowCopy: AiFlowCopy;\n}): React.JSX.Element {\n const [copied, setCopied] = useState(false);\n\n const handleClick = (): void => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n void navigator.clipboard.writeText(message).catch(() => undefined);\n }\n setCopied(true);\n };\n\n return (\n <Box\n sx={{\n p: 2,\n borderRadius: 2,\n border: 1,\n borderColor: \"primary.main\",\n bgcolor: \"action.hover\",\n }}\n >\n <Text variant=\"caption\" as=\"p\" weight=\"bold\">\n {title}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {caption}\n </Text>\n <Box\n sx={{\n mt: 1,\n p: 1.5,\n borderRadius: 1,\n border: 1,\n borderColor: \"divider\",\n bgcolor: \"background.paper\",\n whiteSpace: \"pre-line\",\n }}\n >\n <Text variant=\"body\" size=\"sm\" as=\"p\">\n {message}\n </Text>\n </Box>\n <Box sx={{ mt: 1.5 }}>\n <Button onClick={handleClick} data-testid=\"ai-copy-prompt\">\n {copied ? (\n <CheckIcon sx={{ fontSize: 18, mr: 0.5 }} />\n ) : (\n <ContentCopyOutlinedIcon sx={{ fontSize: 18, mr: 0.5 }} />\n )}\n {copied ? flowCopy.copied : flowCopy.copyMessage}\n </Button>\n </Box>\n </Box>\n );\n}\n\n/** The brand mark + \"Conectar no <host>\" header shared by the connect sub-steps. */\nexport function HostConnectHeader({\n host,\n copy,\n}: {\n host: AiHostGuide;\n copy: AiConnectGuideCopy;\n}): React.JSX.Element {\n return (\n <Stack direction=\"row\" spacing={1.5} alignItems=\"center\">\n <HostBrandAvatar brand={host.brand} size={36} />\n <Text variant=\"heading\" size=\"sm\" as=\"h3\">\n {copy.connectOn(host.label)}\n </Text>\n </Stack>\n );\n}\n\n/**\n * The primary direct-link button to a host's connector settings (nothing when it\n * has none). `onOpen` fires after the link opens so the Configurar step can\n * unlock its \"Próximo\" only once the owner has actually gone to the connectors.\n */\nexport function HostOpenButton({\n host,\n onOpen,\n}: {\n host: AiHostGuide;\n onOpen?: () => void;\n}): React.JSX.Element | null {\n if (!host.link) return null;\n return (\n <Box>\n <Button\n onClick={() => {\n window.open(host.link!.url, \"_blank\", \"noopener,noreferrer\");\n onOpen?.();\n }}\n data-testid={`ai-host-link-${host.id}`}\n >\n {host.link.label}\n <OpenInNewIcon sx={{ fontSize: 16, ml: 0.5 }} />\n </Button>\n </Box>\n );\n}\n\n/** A \"Para mais informações\" reference to the host's official connector docs. */\nexport function HostDocsLink({ host,\n copy,\n}: { host: AiHostGuide;\n copy: AiConnectGuideCopy;}): React.JSX.Element | null {\n if (!host.docs) return null;\n return (\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.moreInfo}{\" \"}\n <Box\n component=\"a\"\n href={host.docs.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-testid={`ai-host-docs-${host.id}`}\n sx={{ color: \"primary.main\", textDecoration: \"underline\" }}\n >\n {host.docs.label}\n </Box>\n .\n </Text>\n );\n}\n\n/**\n * A numbered slice of a host's connect steps. `start` keeps the numbering\n * continuous when the steps are split across wizard stages (e.g. the Conectar\n * stage continues at 4 after Configurar showed 1–3).\n */\nexport function HostStepList({\n steps,\n start = 1,\n}: {\n steps: readonly string[];\n start?: number;\n}): React.JSX.Element {\n return (\n <Box component=\"ol\" start={start} sx={{ m: 0, pl: 3 }}>\n {steps.map((step, index) => (\n <Box component=\"li\" key={index} sx={{ mb: 1 }}>\n <Text variant=\"body\" as=\"span\">\n {step}\n </Text>\n </Box>\n ))}\n </Box>\n );\n}\n","\"use client\";\n\nimport { Code } from \"@12-apps/ui/typography/Code\";\n\n/**\n * The store's MCP endpoint URL. Client component because the copy interaction\n * needs the browser clipboard — the `@12-apps/ui` Code component provides the copy\n * affordance (`copyable`). Pass `copyable={false}` for a display-only field when\n * an external control owns the copy action (e.g. the connect flow's blue Copiar\n * button, which also gates the following steps on the copy).\n */\nexport function McpEndpointUrl({\n url,\n copyable = true,\n}: {\n url: string;\n copyable?: boolean;\n}): React.JSX.Element {\n return (\n <Code variant=\"block\" copyable={copyable} data-testid=\"mcp-endpoint-url\">\n {url}\n </Code>\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { AiStatusBoardCopy } from \"./copy\";\nimport AddLinkOutlinedIcon from \"@mui/icons-material/AddLinkOutlined\";\nimport CheckCircleIcon from \"@mui/icons-material/CheckCircle\";\nimport LinkOffOutlinedIcon from \"@mui/icons-material/LinkOffOutlined\";\nimport MenuBookOutlinedIcon from \"@mui/icons-material/MenuBookOutlined\";\n\nimport { createConfirmButton } from \"@12-apps/ui/feedback/ConfirmAction\";\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostGuide } from \"../guide\";\nimport { HostBrandAvatar } from \"./ai-icons\";\n\n/**\n * Revoke a host's access. Returning a promise holds the confirmation popup in\n * its pending state until the write settles, and a rejection keeps it open\n * carrying the reason — so the owner sees the disconnect finish or fail.\n */\nexport type DisconnectHandler = (hostId: string) => void | Promise<unknown>;\n\n/** One assistant's connection state. */\nexport interface HostStatus {\n host: AiHostGuide;\n connected: boolean;\n /** Freeform activity line for a connected host (e.g. \"ativo há 3 min\"). */\n detail?: string;\n}\n\n/**\n * The right-hand side of a CONNECTED box: the green pill, then the two things\n * the pill alone left the owner unable to do.\n *\n * \"{copy.instructions}\" exists because the setup steps were reachable ONLY from a RED\n * card's \"Conectar\" — so on an all-green board there was no way to re-read how\n * any of them was connected, which is exactly when someone re-doing the setup on\n * a second machine needs them. It re-enters the same flow that button does.\n *\n * \"Desconectar\" is only drawn when the app supplies a revoke path: a board with\n * nowhere to send the revoke must not offer a button that does nothing.\n */\nfunction ConnectedControls({\n host,\n onConnect,\n onDisconnect,\n copy,\n}: {\n host: AiHostGuide;\n onConnect: (hostId: string) => void;\n onDisconnect?: DisconnectHandler;\n copy: AiStatusBoardCopy;\n}): React.JSX.Element {\n // Built from the copy rather than at module scope: `createConfirmButton`\n // takes the words, and they only arrive as a prop. Memoised so the wrapped\n // component keeps its identity across renders and React does not remount it.\n const DisconnectButton = useMemo(\n () => createConfirmButton(copy.confirmAction, copy.disconnectError),\n [copy.confirmAction, copy.disconnectError],\n );\n return (\n <Stack\n direction=\"row\"\n spacing={1}\n alignItems=\"center\"\n justifyContent=\"flex-end\"\n // Wraps rather than squeezing: three controls do not fit a half-width\n // card at every breakpoint.\n sx={{ flexShrink: 0, flexWrap: \"wrap\", rowGap: 0.5 }}\n >\n <Box\n sx={{\n px: 1,\n py: 0.25,\n borderRadius: 999,\n bgcolor: \"success.main\",\n color: \"success.contrastText\",\n }}\n >\n <Text variant=\"caption\" weight=\"bold\" as=\"span\">\n {copy.connected}\n </Text>\n </Box>\n <Button\n variant=\"text\"\n size=\"sm\"\n onClick={() => onConnect(host.id)}\n data-testid={`ai-status-instructions-${host.id}`}\n >\n <MenuBookOutlinedIcon sx={{ fontSize: 16, mr: 0.5 }} />\n {copy.instructions}\n </Button>\n {onDisconnect ? (\n <DisconnectButton\n variant=\"outline\"\n color=\"danger\"\n size=\"sm\"\n onClick={() => onDisconnect(host.id)}\n confirm={{\n title: copy.disconnectTitle,\n entityName: host.label,\n description:\n copy.disconnectBody,\n confirmText: copy.disconnectConfirm,\n dataTestId: `ai-status-disconnect-confirm-${host.id}`,\n }}\n data-testid={`ai-status-disconnect-${host.id}`}\n >\n <LinkOffOutlinedIcon sx={{ fontSize: 16, mr: 0.5 }} />\n {copy.disconnect}\n </DisconnectButton>\n ) : null}\n </Stack>\n );\n}\n\n/** A single green (connected) / red (to connect) status box for one assistant. */\nfunction StatusBox({\n status,\n onConnect,\n onDisconnect,\n copy,\n}: {\n status: HostStatus;\n onConnect: (hostId: string) => void;\n onDisconnect?: DisconnectHandler;\n copy: AiStatusBoardCopy;\n}): React.JSX.Element {\n const { host, connected, detail } = status;\n return (\n <Box\n data-testid={`ai-status-${host.id}`}\n data-connected={connected}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 1.5,\n p: 2,\n borderRadius: 3,\n border: 1,\n borderColor: connected ? \"success.main\" : \"error.main\",\n bgcolor: \"background.paper\",\n }}\n >\n <HostBrandAvatar brand={host.brand} size={36} />\n <Box sx={{ minWidth: 0, flexGrow: 1 }}>\n <Stack direction=\"row\" spacing={0.75} alignItems=\"center\">\n <Text variant=\"body\" weight=\"bold\" as=\"span\">\n {host.label}\n </Text>\n {connected ? <CheckCircleIcon sx={{ fontSize: 18, color: \"success.main\" }} /> : null}\n </Stack>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {connected ? (detail ?? copy.connected) : copy.notConnected}\n </Text>\n </Box>\n {connected ? (\n <ConnectedControls copy={copy} host={host} onConnect={onConnect} onDisconnect={onDisconnect} />\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onConnect(host.id)}\n data-testid={`ai-status-connect-${host.id}`}\n >\n <AddLinkOutlinedIcon sx={{ fontSize: 16, mr: 0.5 }} />\n Conectar\n </Button>\n )}\n </Box>\n );\n}\n\n/**\n * The completed-state status board for the AI integration: every assistant as a\n * box — green when connected, red when still to connect (with a \"Conectar\"\n * button that re-enters the guided flow for that host). Each connection is\n * attributed to its provider (derived from the OAuth client + confirmed by\n * `announceAiConnection`), so several assistants can show connected at once.\n *\n * A connected box carries two more controls, because the pill it used to show\n * alone was a dead end in both directions: \"{copy.instructions}\" re-enters the host's\n * setup steps (previously reachable only from a RED card, so an all-green board\n * hid them entirely), and \"Desconectar\" — when the app passes `onDisconnect` —\n * revokes access, which nothing in the UI could do at all.\n */\nexport function AiStatusBoard({\n statuses,\n onConnect,\n onDisconnect,\n copy,\n}: {\n statuses: readonly HostStatus[];\n onConnect: (hostId: string) => void;\n /** Revoke this host's access. Omit to render a read-only board. */\n onDisconnect?: DisconnectHandler;\n copy: AiStatusBoardCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={2} data-testid=\"ai-status-board\">\n <Box>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n {copy.boardTitle}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.boardCaption}\n </Text>\n </Box>\n <Box\n sx={{\n display: \"grid\",\n gap: 2,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\" },\n }}\n >\n {statuses.map((status) => (\n <StatusBox copy={copy}\n key={status.host.id}\n status={status}\n onConnect={onConnect}\n onDisconnect={onDisconnect}\n />\n ))}\n </Box>\n </Stack>\n );\n}\n","\"use client\";\n\nimport type { AiHostSelectCopy } from \"./copy\";\nimport CheckCircleIcon from \"@mui/icons-material/CheckCircle\";\n\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostGuide } from \"../guide\";\nimport { HostBrandAvatar } from \"./ai-icons\";\n\n/** One selectable assistant card (brand mark + name + kind, checked when active). */\nfunction HostCard({\n host,\n active,\n onSelect,\n}: {\n host: AiHostGuide;\n active: boolean;\n onSelect: () => void;\n}): React.JSX.Element {\n return (\n <Box\n component=\"button\"\n type=\"button\"\n onClick={onSelect}\n aria-pressed={active}\n data-testid={`ai-host-card-${host.id}`}\n sx={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 1.5,\n p: 2,\n borderRadius: 3,\n cursor: \"pointer\",\n textAlign: \"left\",\n width: \"100%\",\n border: 2,\n borderColor: active ? \"primary.main\" : \"divider\",\n bgcolor: active ? \"action.selected\" : \"background.paper\",\n transition: (theme) => theme.transitions.create([\"border-color\", \"background-color\"]),\n \"&:hover\": { borderColor: \"primary.main\" },\n }}\n >\n <HostBrandAvatar brand={host.brand} size={40} />\n <Box sx={{ minWidth: 0 }}>\n <Text variant=\"body\" weight=\"bold\" as=\"span\">\n {host.label}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {host.kind}\n </Text>\n </Box>\n {active && (\n <CheckCircleIcon\n sx={{ position: \"absolute\", top: 10, right: 10, fontSize: 20, color: \"primary.main\" }}\n />\n )}\n </Box>\n );\n}\n\n/**\n * Step 1 of the guided AI connect flow: the owner picks a single assistant\n * (Claude.ai, Claude Desktop, ChatGPT, Codex) from a card grid. Picking a card\n * advances straight to the next step — no separate \"Próximo\" button. Selection\n * is controlled (persisted by the onboarding flow) so a refresh resumes with the\n * same assistant highlighted.\n */\nexport function HostSelectStep({\n hosts,\n selectedId,\n onSelect,\n copy,\n}: {\n hosts: readonly AiHostGuide[];\n selectedId: string | null;\n onSelect: (hostId: string) => void;\n copy: AiHostSelectCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={3} data-testid=\"ai-host-select\">\n <Box>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n Escolha o seu assistente\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.caption}\n </Text>\n </Box>\n\n <Box\n sx={{\n display: \"grid\",\n gap: 2,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\" },\n }}\n >\n {hosts.map((host) => (\n <HostCard\n key={host.id}\n host={host}\n active={host.id === selectedId}\n onSelect={() => onSelect(host.id)}\n />\n ))}\n </Box>\n </Stack>\n );\n}\n","\"use client\";\n\nimport type { McpAiCopy } from \"./copy\";\nimport { type GuidedNav, type GuidedStep } from \"@12-apps/onboarding\";\n\nimport { providerForHostId, type AiHostGuide } from \"../guide\";\nimport { activeAgo, resolveHost, type AiConnection } from \"./ai-connection-utils\";\nimport {\n ConfigureStageStep,\n ConfigureStep,\n ConfirmStep,\n ConnectStep,\n CopyUrlStep,\n InstallStep,\n} from \"./ai-flow-steps\";\nimport { AiStatusBoard, type DisconnectHandler, type HostStatus } from \"./ai-status-board\";\nimport { HostSelectStep } from \"./host-select-step\";\n\nexport type { AiConnection } from \"./ai-connection-utils\";\nexport { connectedSummary, connectedTitle } from \"./ai-connection-utils\";\n\n/** The completed status board: green for each connected host, red for the rest. */\nexport function StatusBoard({\n nav,\n connections,\n hosts,\n onDisconnect,\n copy,\n}: {\n nav: GuidedNav;\n connections: readonly AiConnection[];\n hosts: readonly AiHostGuide[];\n onDisconnect?: DisconnectHandler;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const legacyHostId = (nav.data.connectedHost ?? nav.data.selectedHost) as string | undefined;\n\n const statuses: HostStatus[] = hosts.map((host) => {\n const provider = providerForHostId(host.id);\n // Prefer a provider-attributed connection; fall back to a legacy null-host\n // connection only for the host the owner completed the flow with.\n const connection =\n (provider ? connections.find((c) => c.host === provider) : undefined) ??\n (host.id === legacyHostId ? connections.find((c) => c.host === null) : undefined) ??\n null;\n return {\n host,\n connected: connection !== null,\n detail: connection ? activeAgo(connection.lastActiveAt, copy.summary) : undefined,\n };\n });\n\n /** Re-enter this host's setup — the manual copy path, or its one-click install. */\n const goToConnect = (hostId: string): void => {\n nav.goTo(hosts.find((h) => h.id === hostId)?.pluginUrl ? \"install\" : \"copy\", {\n selectedHost: hostId,\n });\n };\n\n /**\n * Disconnecting the LAST assistant leaves the section configured with nothing\n * configured: a collapsed \"IA conectada\" summary hiding an all-red board, with\n * the setup instructions two clicks away. So when the revoke empties the\n * board, walk straight back into that host's instructions — the owner who just\n * cut an assistant off is the likeliest person to reconnect one, and the steps\n * are the only thing left worth showing.\n *\n * Cutting one of SEVERAL leaves the board meaningful, so it stays put.\n * `statuses` is the pre-revoke picture, which is what makes \"was that the last\n * one?\" answerable here without waiting for the app to re-read.\n */\n const disconnect: DisconnectHandler | undefined = onDisconnect\n ? async (hostId) => {\n await onDisconnect(hostId);\n const revoked = providerForHostId(hostId);\n const othersLive = statuses.some(\n (status) => status.connected && providerForHostId(status.host.id) !== revoked,\n );\n if (!othersLive) goToConnect(hostId);\n }\n : undefined;\n\n return (\n <AiStatusBoard copy={copy.statusBoard} statuses={statuses} onConnect={goToConnect} onDisconnect={disconnect} />\n );\n}\n\n/** The first step (host picker) — picking a card advances to the right path. */\nfunction selectStep(hosts: readonly AiHostGuide[], copy: McpAiCopy): GuidedStep {\n return {\n id: \"select\",\n label: copy.flow.steps.select,\n render: (nav: GuidedNav) => (\n <HostSelectStep\n hosts={hosts}\n selectedId={(nav.data.selectedHost as string | undefined) ?? null}\n copy={copy.hostSelect}\n onSelect={(hostId) =>\n nav.goTo(hosts.find((h) => h.id === hostId)?.pluginUrl ? \"install\" : \"copy\", {\n selectedHost: hostId,\n })\n }\n />\n ),\n };\n}\n\n/** The Copiar-URL step, shared by every manual flow. */\nfunction copyStep(endpointUrl: string, copy: McpAiCopy): GuidedStep {\n return {\n id: \"copy\",\n label: copy.flow.steps.copyUrl,\n render: (nav: GuidedNav) => <CopyUrlStep copy={copy} nav={nav} endpointUrl={endpointUrl} />,\n };\n}\n\n/**\n * The middle steps for the full manual flow. A host with `configureStages`\n * (e.g. ChatGPT) gets one step per stage — each with its own deep link — after\n * Copiar URL; otherwise the default copy → configure → connect split.\n */\nfunction manualMiddle(\n host: AiHostGuide,\n hosts: readonly AiHostGuide[],\n endpointUrl: string,\n connectPrompt: string,\n copy: McpAiCopy,\n): GuidedStep[] {\n if (host.configureStages && host.configureStages.length > 0) {\n return [\n copyStep(endpointUrl, copy),\n ...host.configureStages.map((stage) => ({\n id: stage.id,\n label: stage.label,\n render: (nav: GuidedNav) => (\n <ConfigureStageStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n stage={stage}\n copy={copy}\n />\n ),\n })),\n ];\n }\n return [\n copyStep(endpointUrl, copy),\n {\n id: \"configure\",\n label: copy.flow.steps.configure,\n render: (nav: GuidedNav) => (\n <ConfigureStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n copy={copy}\n />\n ),\n },\n {\n id: \"connect\",\n label: copy.flow.steps.connect,\n render: (nav: GuidedNav) => (\n <ConnectStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n connectPrompt={connectPrompt}\n copy={copy}\n />\n ),\n },\n ];\n}\n\n/** The single middle step for the simplified plugin flow: install. */\nfunction simpleMiddle(\n hosts: readonly AiHostGuide[],\n connectPrompt: string,\n copy: McpAiCopy,\n): GuidedStep[] {\n return [\n {\n id: \"install\",\n label: copy.flow.steps.install,\n render: (nav: GuidedNav) => (\n <InstallStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n connectPrompt={connectPrompt}\n copy={copy}\n />\n ),\n },\n ];\n}\n\n/**\n * Build the wizard's steps for the selected host's path: the simplified\n * `install` flow when the host has a published `pluginUrl`, the per-stage flow\n * when it declares `configureStages`, otherwise the full copy → configure →\n * connect flow. `select` and `confirm` bookend all of them.\n */\nexport function buildFlowSteps(opts: {\n host: AiHostGuide;\n hosts: readonly AiHostGuide[];\n endpointUrl: string;\n connectPrompt: string;\n connections: readonly AiConnection[];\n onRetest: () => void;\n copy: McpAiCopy;\n}): GuidedStep[] {\n const { host, hosts, endpointUrl, connectPrompt, connections, onRetest, copy } = opts;\n const middle = host.pluginUrl\n ? simpleMiddle(hosts, connectPrompt, copy)\n : manualMiddle(host, hosts, endpointUrl, connectPrompt, copy);\n const confirm: GuidedStep = {\n id: \"confirm\",\n label: copy.flow.steps.confirm,\n render: (nav: GuidedNav) => (\n <ConfirmStep\n nav={nav}\n connections={connections}\n hosts={hosts}\n onRetest={onRetest}\n copy={copy}\n />\n ),\n };\n return [selectStep(hosts, copy), ...middle, confirm];\n}\n","import { PT_BR_CONFIRM_ACTION_COPY } from \"@12-apps/ui/pt-BR\";\n\nimport type { McpAiCopy } from \"./copy\";\n\n/**\n * The pt-BR pack for the AI-integration screens — a NAMED constant a host\n * passes by hand, never a default.\n *\n * The filename is what exempts this file from the copy-portability gate:\n * Portuguese may ship, it may not be silent. Every sentence is VERBATIM what\n * the components used to render, so a host adopting it sees no change on\n * screen — what changes is that the words are chosen in a diff.\n */\nexport const PT_BR_MCP_AI_COPY: McpAiCopy = {\n capabilities: {\n heading: \"O que o assistente faz por você\",\n subheading: \"Sem planilhas, sem cliques — é só perguntar na conversa.\",\n },\n landing: {\n eyebrow: \"Integração com IA\",\n titleTail: \"à sua loja\",\n lede:\n \"Deixe o Claude, o ChatGPT e outros assistentes responderem sobre o seu cardápio, estoque e \" +\n \"pedidos — e executarem ações por você, direto na conversa. Com segurança e sem instalar nada.\",\n trust: [\n {\n id: \"login\",\n label: \"Usa o seu próprio login\",\n caption: \"Sem chaves ou credenciais extras\",\n },\n { id: \"install\", label: \"Sem instalar nada\", caption: \"Conecta em poucos minutos\" },\n {\n id: \"permissions\",\n label: \"Só o que você pode\",\n caption: \"As suas permissões, nada além\",\n },\n { id: \"surface\", label: \"Navegador ou app\", caption: \"Claude, ChatGPT, Codex\" },\n ],\n start: \"Começar\",\n },\n flow: {\n steps: {\n select: \"Escolher\",\n copyUrl: \"Copiar URL\",\n configure: \"Configurar\",\n connect: \"Conectar\",\n install: \"Instalar\",\n confirm: \"Confirmar\",\n },\n back: \"Voltar\",\n next: \"Próximo\",\n advance: \"Continuar\",\n finish: \"Concluir\",\n copyUrl: \"Copiar URL\",\n copied: \"Copiado\",\n copyMessage: \"Copiar mensagem\",\n copyUrlTitle: \"Copie a URL da sua loja\",\n urlCaption:\n \"É o único dado que você cola no assistente — ao copiar, seguimos para o próximo passo.\",\n promptCaption:\n \"Assim ele se conecta, se identifica (Claude, ChatGPT…) e registramos a conexão.\",\n askTitle: \"Peça ao assistente para conectar\",\n installBody:\n \"Abra o plugin da sua loja, clique em Instalar e autorize o acesso — sem copiar URL nem gerar credenciais.\",\n installAction: \"Instalar o plugin da loja\",\n pasteTitle: \"Cole esta mensagem no assistente\",\n pasteInstallCaption:\n \"Cole no assistente para ele se conectar, se identificar e confirmar o acesso.\",\n connectedTo: (hostLabel) => `${hostLabel} está conectado à sua loja.`,\n waitingTitle: \"Esperando conexão\",\n waitingBody: (hostLabel) =>\n `Assim que você autorizar o acesso no ${hostLabel}, ela aparece aqui automaticamente.`,\n testNow: \"Testar agora\",\n },\n statusBoard: {\n instructions: \"Instruções\",\n connected: \"Conectado\",\n notConnected: \"Ainda não conectado\",\n connect: \"Conectar\",\n disconnect: \"Desconectar\",\n disconnectTitle: \"Desconectar o assistente?\",\n disconnectBody:\n \"Ele perde o acesso à sua loja na hora. Para voltar a usar, será preciso conectar de novo.\",\n disconnectConfirm: \"Desconectar\",\n disconnectError: \"Não foi possível desconectar. Tente de novo.\",\n boardTitle: \"Assistentes conectados\",\n boardCaption: \"Em verde os que já operam a sua loja; em vermelho os que faltam conectar.\",\n confirmAction: PT_BR_CONFIRM_ACTION_COPY,\n },\n summary: {\n activeNow: \"ativo agora\",\n activeMinutes: (minutes) => `ativo há ${minutes} min`,\n activeHours: (hours) => `ativo há ${hours} h`,\n activeDays: (days) => `ativo há ${days} dias`,\n configured: \"Integração configurada\",\n connectedSuffix: \"Conectado\",\n connectedSeveral: (names) => `${names} conectados`,\n connectedGeneric: \"IA conectada\",\n },\n hostSelect: {\n caption: \"Selecione onde você usa a IA — o passo a passo é feito sob medida para ele.\",\n },\n connectGuide: {\n urlLabel: \"URL do servidor da sua loja\",\n urlHint: \"Copie esta URL e cole no seu assistente para conectá-lo à loja.\",\n moreInfo: \"Para mais informações, consulte a\",\n connectOn: (hostLabel) => `Conectar no ${hostLabel}`,\n },\n onboarding: {\n title: \"Conecte assistentes de IA à sua loja\",\n editLabel: \"Conectar IA\",\n collapseLabel: \"Ocultar\",\n },\n};\n"],"mappings":"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","names":["Box","Stack","Text","Box","jsx","Box","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Stack","Box","Text","OpenInNewIcon","useState","Button","Box","Stack","Text","Button","Box","Stack","Text","jsx","jsx","jsxs","Box","Text","Button","Stack","jsx","jsxs","Stack","Button","Box","Text","useState","OpenInNewIcon","CheckCircleIcon","Button","Box","Stack","Text","jsx","jsxs","Stack","Box","Text","Button","CheckCircleIcon","CheckCircleIcon","Box","Stack","Text","jsx","jsxs","Box","Text","CheckCircleIcon","Stack","jsx","jsx","hostLabel"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/ai-onboarding.tsx","../../src/react/ai-landing.tsx","../../src/react/ai-capabilities.tsx","../../src/react/ai-icons.tsx","../../src/react/feature-badge.tsx","../../src/react/ai-connection-utils.ts","../../src/react/ai-flow-steps.tsx","../../src/react/host-connect-guide.tsx","../../src/react/mcp-endpoint-url.tsx","../../src/react/ai-status-board.tsx","../../src/react/host-select-step.tsx","../../src/react/ai-steps.tsx","../../src/react/pt-BR.ts"],"sourcesContent":["\"use client\";\n\nimport type { McpAiCopy } from \"./copy\";\nimport {\n GuidedSection,\n OnboardingProvider,\n useOnboarding,\n type OnboardingStateSnapshot,\n type OnboardingStore,\n} from \"@12-apps/onboarding\";\n\nimport {\n type AiCapability,\n type AiHostGuide,\n} from \"../guide\";\nimport { AiLanding } from \"./ai-landing\";\nimport type { DisconnectHandler } from \"./ai-status-board\";\nimport {\n buildFlowSteps,\n connectedSummary,\n connectedTitle,\n StatusBoard,\n type AiConnection,\n} from \"./ai-steps\";\n\nexport type { AiConnection } from \"./ai-steps\";\n\n/** Props for the reusable AI-connect onboarding flow. */\nexport interface AiIntegrationOnboardingProps {\n /** Persistence seam — the app wires this to its own backend (server actions). */\n store: OnboardingStore;\n /** The MCP endpoint URL to paste (derived by the app from its public origin). */\n endpointUrl: string;\n /** The owner's saved progress (null → first run / landing). */\n initialState: OnboardingStateSnapshot | null;\n /** The live MCP connections (one per connected assistant; empty when none). */\n connections: readonly AiConnection[];\n /**\n * The onboarding namespace this flow's progress is stored under — the key\n * `@12-apps/onboarding` reads and writes, and the one the host's own\n * `featureKeys` allow-list has to contain.\n *\n * REQUIRED, on the same grounds as `hosts` and `copy` below. It defaulted to\n * `\"ai_integration\"`, which is one adopter's key: a host whose backend\n * declares `ai` or `mcp_connect` and says nothing here writes to a namespace\n * its own API rejects, so the wizard loses every step it saves and resumes\n * from nothing. Nothing warns, because a silent default is indistinguishable\n * from a deliberate one — and the failure only shows up as a refresh that\n * forgets, which reads as a bug in the host's persistence rather than as a\n * key nobody chose.\n */\n featureKey: string;\n /** Show the dev-only \"reset onboarding\" button. @default false */\n devReset?: boolean;\n /**\n * Assistants offered in the flow, with their step-by-step instructions.\n *\n * REQUIRED since FUT-760. These used to default to this package's own pt-BR\n * walkthrough, so a host that said nothing shipped one product's Portuguese\n * and had no field to decline it. `PT_BR_AI_HOST_GUIDES(platformName)` is that\n * exact content, now chosen by name.\n */\n hosts: readonly AiHostGuide[];\n /** Capability cards on the landing. REQUIRED — see `hosts`. */\n capabilities: readonly AiCapability[];\n /** Permission reassurance copy on the landing. REQUIRED — see `hosts`. */\n permissionModel: string;\n /** Every sentence the screens render. REQUIRED — see `hosts`. */\n copy: McpAiCopy;\n /**\n * Message the owner pastes into the assistant on the Conectar step.\n *\n * REQUIRED, with no default, because the useful version of it names TOOLS —\n * one to register the connection, one to read something real — and this\n * package neither defines nor serves any. It shipped a constant naming two\n * tools from one adopter's surface, so another host handed its owner a prompt\n * that called two things that did not exist, and the confirm step then waited\n * forever for a registration that could never happen. Build it with\n * `aiConnectPrompt({ … })`.\n */\n connectPrompt: string;\n /**\n * Re-check the live connection on the verify step's \"Testar conexão\" button —\n * apps pass a router refresh (e.g. Next's `router.refresh`). @default a full\n * `window.location.reload()`.\n */\n onRetest?: () => void;\n /**\n * Revoke a connected assistant's access, from the completed status board. The\n * host ID is the board's card, NOT the connection — `claude` and\n * `claude-desktop` share one provider, so the app resolves which stored\n * connection it owns (`providerForHostId`) and revokes that. Omitted → the\n * board stays read-only, which is the pre-existing behavior.\n */\n onDisconnect?: DisconnectHandler;\n}\n\n/** Resolved (defaults-applied) props threaded to the in-provider flow body. */\ninterface FlowProps {\n endpointUrl: string;\n connections: readonly AiConnection[];\n hosts: readonly AiHostGuide[];\n capabilities: readonly AiCapability[];\n permissionModel: string;\n connectPrompt: string;\n onRetest: () => void;\n onDisconnect: DisconnectHandler | undefined;\n devReset: boolean;\n copy: McpAiCopy;\n}\n\n/**\n * The flow body — inside the OnboardingProvider so it can read the selected host\n * and pick the path. A host with a published `pluginUrl` gets the simplified\n * Escolher → Instalar → Confirmar flow (no URL to copy); otherwise the full\n * Escolher → Copiar URL → Configurar → Conectar → Confirmar flow.\n */\nfunction AiOnboardingFlow(props: FlowProps): React.JSX.Element {\n const {\n endpointUrl,\n connections,\n hosts,\n capabilities,\n permissionModel,\n connectPrompt,\n onRetest,\n onDisconnect,\n devReset,\n copy,\n } = props;\n const { state } = useOnboarding();\n const selectedHost =\n hosts.find((h) => h.id === state.data.selectedHost) ?? hosts[0]!;\n\n const steps = buildFlowSteps({\n host: selectedHost,\n hosts,\n endpointUrl,\n connectPrompt,\n connections,\n onRetest,\n copy,\n });\n const connectedHostId = (state.data.connectedHost ??\n state.data.selectedHost) as string | undefined;\n\n return (\n <GuidedSection\n steps={steps}\n title={copy.onboarding.title}\n startLabel={copy.landing.start}\n renderLanding={(start) => (\n <AiLanding\n onStart={start}\n permissionModel={permissionModel}\n capabilities={capabilities}\n copy={copy.landing}\n capabilitiesCopy={copy.capabilities}\n />\n )}\n configuredTitle={connectedTitle(connections, hosts, connectedHostId, copy.summary)}\n configuredSummary={connectedSummary(connections, copy.summary)}\n editLabel={copy.onboarding.editLabel}\n collapseLabel={copy.onboarding.collapseLabel}\n completedContent={(nav) => (\n <StatusBoard\n nav={nav}\n connections={connections}\n hosts={hosts}\n onDisconnect={onDisconnect}\n copy={copy}\n />\n )}\n devReset={devReset}\n dataTestId=\"ai-onboarding\"\n />\n );\n}\n\n/**\n * URL-free, persisted onboarding for the AI/MCP integration — a five-step wizard\n * (pick an assistant, copy the store URL, configure the connector, connect, then\n * verify) whose position + chosen assistant are saved via `@12-apps/onboarding`, so\n * a refresh resumes exactly where the owner left off. The live MCP connection\n * signal drives the verify step and the completed status board.\n *\n * App-agnostic: the app supplies the persistence `store`, the `endpointUrl`, the\n * `featureKey` its own onboarding API serves, the live `connections` (one per\n * connected assistant), and every word on screen (`hosts`, `capabilities`,\n * `permissionModel`, `copy`). Nothing here has a default, because each of those\n * is a fact only the host holds and a default for it is silently wrong rather\n * than loudly missing.\n */\nexport function AiIntegrationOnboarding({\n store,\n endpointUrl,\n initialState,\n connections,\n featureKey,\n devReset = false,\n hosts,\n capabilities,\n permissionModel,\n connectPrompt,\n onRetest = () => {\n if (typeof window !== \"undefined\") window.location.reload();\n },\n onDisconnect,\n copy,\n}: AiIntegrationOnboardingProps): React.JSX.Element {\n return (\n <OnboardingProvider\n featureKey={featureKey}\n store={store}\n initialState={initialState}\n >\n <AiOnboardingFlow\n endpointUrl={endpointUrl}\n connections={connections}\n hosts={hosts}\n capabilities={capabilities}\n permissionModel={permissionModel}\n connectPrompt={connectPrompt}\n onRetest={onRetest}\n onDisconnect={onDisconnect}\n devReset={devReset}\n copy={copy}\n />\n </OnboardingProvider>\n );\n}\n","\"use client\";\n\nimport BoltOutlinedIcon from \"@mui/icons-material/BoltOutlined\";\nimport LanguageOutlinedIcon from \"@mui/icons-material/LanguageOutlined\";\nimport LockOpenOutlinedIcon from \"@mui/icons-material/LockOpenOutlined\";\nimport VerifiedUserOutlinedIcon from \"@mui/icons-material/VerifiedUserOutlined\";\n\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiCapability } from \"../guide\";\nimport type { AiCapabilitiesCopy, AiLandingCopy } from \"./copy\";\nimport { AiCapabilities } from \"./ai-capabilities\";\nimport { FeatureBadge, type FeatureBadgeItem } from \"./feature-badge\";\n\n/**\n * The ICONS for the landing's reassurance strip, keyed by the copy's own ids.\n *\n * The package keeps the icons and the host keeps the words: an icon is not\n * copy, and a pack that had to ship React elements could not be a plain data\n * file. An id the map does not know renders without an icon rather than\n * throwing — a host adding a fifth point should get its words on screen.\n */\nconst TRUST_ICONS: Readonly<Record<string, React.JSX.Element>> = {\n login: <LockOpenOutlinedIcon />,\n install: <BoltOutlinedIcon />,\n permissions: <VerifiedUserOutlinedIcon />,\n surface: <LanguageOutlinedIcon />,\n};\n\nfunction trustBadges(trust: AiLandingCopy[\"trust\"]): FeatureBadgeItem[] {\n return trust.map((point) => ({\n icon: TRUST_ICONS[point.id],\n label: point.label,\n caption: point.caption,\n }));\n}\n\n/** The single-column marketing hero: eyebrow + headline + description + CTA. */\nfunction Hero({\n onStart,\n copy,\n}: {\n onStart: () => void;\n copy: AiLandingCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={2.5} sx={{ maxWidth: 680 }}>\n <Box\n sx={{\n color: \"primary.main\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 1.2,\n textTransform: \"uppercase\",\n }}\n >\n {copy.eyebrow}\n </Box>\n <Text variant=\"heading\" size=\"xl\" weight=\"bold\" as=\"h1\">\n Conecte{\" \"}\n <Box component=\"span\" sx={{ color: \"primary.main\" }}>\n assistentes de IA\n </Box>{\" \"}\n {copy.titleTail}\n </Text>\n <Text variant=\"body\" color=\"secondary\" as=\"p\">\n {copy.lede}\n </Text>\n <Box sx={{ pt: 1 }}>\n <Button onClick={onStart} data-testid=\"ai-landing-start\">\n {copy.start}\n </Button>\n </Box>\n </Stack>\n );\n}\n\n/**\n * Homepage-style marketing landing for the AI integration (shown before the\n * owner starts): a hero, the permission reassurance, a trust/feature strip, and\n * the capability highlights. `onStart` begins the guided flow. `permissionModel`\n * and `capabilities` are REQUIRED host copy — the package ships no default\n * sentence (FUT-760).\n */\nexport function AiLanding({\n onStart,\n permissionModel,\n capabilities,\n copy,\n capabilitiesCopy,\n}: {\n onStart: () => void;\n permissionModel: string;\n capabilities: readonly AiCapability[];\n copy: AiLandingCopy;\n capabilitiesCopy: AiCapabilitiesCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={6} data-testid=\"ai-landing\">\n <Hero onStart={onStart} copy={copy} />\n\n <Stack\n direction=\"row\"\n spacing={1.5}\n alignItems=\"flex-start\"\n data-testid=\"ai-permission-callout\"\n sx={{\n p: 2,\n borderRadius: 2,\n bgcolor: \"action.hover\",\n border: 1,\n borderColor: \"divider\",\n }}\n >\n <VerifiedUserOutlinedIcon sx={{ color: \"success.main\", mt: 0.25 }} />\n <Text variant=\"body\" as=\"p\">\n {permissionModel}\n </Text>\n </Stack>\n\n <Box\n sx={{\n p: { xs: 2.5, md: 3 },\n borderRadius: 3,\n bgcolor: \"action.hover\",\n border: 1,\n borderColor: \"divider\",\n }}\n >\n <Box\n sx={{\n display: \"grid\",\n gap: 3,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\", md: \"repeat(4, 1fr)\" },\n }}\n >\n {trustBadges(copy.trust).map((f) => (\n <FeatureBadge key={f.label} icon={f.icon} label={f.label} caption={f.caption} />\n ))}\n </Box>\n </Box>\n\n <Box>\n <AiCapabilities capabilities={capabilities} copy={capabilitiesCopy} />\n </Box>\n </Stack>\n );\n}\n","import { Box } from \"@12-apps/ui/mui/Box\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiCapability } from \"../guide\";\nimport type { AiCapabilitiesCopy } from \"./copy\";\nimport { CapabilityIcon } from \"./ai-icons\";\n\n/** One marketing card: an icon, a headline and an example prompt (as a bubble). */\nfunction CapabilityCard({ capability }: { capability: AiCapability }): React.JSX.Element {\n return (\n <Box\n data-testid={`ai-capability-${capability.id}`}\n sx={{\n p: 2.5,\n borderRadius: 3,\n border: 1,\n borderColor: \"divider\",\n bgcolor: \"background.paper\",\n height: \"100%\",\n // Static transition string: safe to cross the server→client boundary.\n transition: \"border-color 200ms, box-shadow 200ms, transform 200ms\",\n \"&:hover\": { borderColor: \"primary.main\", boxShadow: 3, transform: \"translateY(-3px)\" },\n }}\n >\n <Box\n sx={{\n width: 44,\n height: 44,\n borderRadius: 2,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n bgcolor: \"primary.main\",\n color: \"primary.contrastText\",\n mb: 1.5,\n }}\n >\n <CapabilityIcon id={capability.id} fontSize={26} />\n </Box>\n <Text variant=\"body\" weight=\"bold\" as=\"h3\">\n {capability.title}\n </Text>\n <Box\n data-testid={`ai-capability-prompt-${capability.id}`}\n sx={{\n mt: 1,\n px: 1.5,\n py: 1,\n borderRadius: 2,\n borderBottomLeftRadius: 4,\n bgcolor: \"action.hover\",\n border: 1,\n borderColor: \"divider\",\n }}\n >\n <Text variant=\"body\" size=\"sm\" as=\"p\" color=\"secondary\">\n {capability.detail}\n </Text>\n </Box>\n </Box>\n );\n}\n\n/**\n * Marketing block for the AI integration: a headline + a responsive grid of\n * capability cards. Shown on the onboarding landing (before the owner starts) to\n * sell the feature — \"here's what the assistant does for you\". `capabilities`\n * and `copy` are REQUIRED host copy — the package ships no default sentence\n * (FUT-760).\n */\nexport function AiCapabilities({\n capabilities,\n copy,\n}: {\n capabilities: readonly AiCapability[];\n copy: AiCapabilitiesCopy;\n}): React.JSX.Element {\n return (\n <Box data-testid=\"ai-capability-examples\" sx={{ width: \"100%\" }}>\n <Box sx={{ mb: 3 }}>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n {copy.heading}\n </Text>\n <Box sx={{ mt: 0.5 }}>\n <Text variant=\"body\" size=\"sm\" as=\"p\" color=\"secondary\">\n {copy.subheading}\n </Text>\n </Box>\n </Box>\n <Box\n sx={{\n display: \"grid\",\n gap: 3,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\", md: \"repeat(4, 1fr)\" },\n }}\n >\n {capabilities.map((capability) => (\n <CapabilityCard key={capability.id} capability={capability} />\n ))}\n </Box>\n </Box>\n );\n}\n","import AutoAwesomeIcon from \"@mui/icons-material/AutoAwesome\";\nimport CategoryIcon from \"@mui/icons-material/Category\";\nimport HubIcon from \"@mui/icons-material/Hub\";\nimport Inventory2Icon from \"@mui/icons-material/Inventory2\";\nimport QueryStatsIcon from \"@mui/icons-material/QueryStats\";\nimport ReceiptLongIcon from \"@mui/icons-material/ReceiptLong\";\n\nimport { Box } from \"@12-apps/ui/mui/Box\";\n\nimport type { AiHostBrand } from \"../guide\";\n\n/**\n * Brand accents for the host avatars. These are deliberately hardcoded (not\n * theme tokens): they are BRAND marks whose recognizability depends on the\n * vendor's own accent colour, so the \"always semantic colours\" rule doesn't\n * apply here. The glyphs are simple, original stand-ins — not the vendors'\n * proprietary logo artwork.\n */\nconst BRAND: Record<AiHostBrand, { bg: string; Icon: typeof AutoAwesomeIcon; label: string }> = {\n claude: { bg: \"#D97757\", Icon: AutoAwesomeIcon, label: \"Claude (Anthropic)\" },\n openai: { bg: \"#10A37F\", Icon: HubIcon, label: \"OpenAI\" },\n};\n\n/** A round brand chip: the vendor accent + a simple glyph. */\nexport function HostBrandAvatar({\n brand,\n size = 40,\n}: {\n brand: AiHostBrand;\n size?: number;\n}): React.JSX.Element {\n const { bg, Icon, label } = BRAND[brand];\n return (\n <Box\n aria-label={label}\n sx={{\n width: size,\n height: size,\n borderRadius: \"50%\",\n bgcolor: bg,\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n }}\n >\n <Icon sx={{ fontSize: size * 0.55 }} />\n </Box>\n );\n}\n\nconst CAPABILITY_ICON: Record<string, typeof AutoAwesomeIcon> = {\n orders: ReceiptLongIcon,\n inventory: Inventory2Icon,\n catalog: CategoryIcon,\n sales: QueryStatsIcon,\n};\n\n/** The icon for a capability card, by capability id (falls back to a sparkle). */\nexport function CapabilityIcon({\n id,\n fontSize = 24,\n}: {\n id: string;\n fontSize?: number;\n}): React.JSX.Element {\n const Icon = CAPABILITY_ICON[id] ?? AutoAwesomeIcon;\n return <Icon sx={{ fontSize }} />;\n}\n","import { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\n/** One entry of a landing's trust/feature strip. */\nexport interface FeatureBadgeItem {\n icon: React.ReactNode;\n label: string;\n caption: string;\n}\n\n/**\n * One item of an onboarding landing's trust/feature strip: a paper icon tile\n * (primary-coloured glyph) with a two-line label + caption.\n */\nexport function FeatureBadge({ icon, label, caption }: FeatureBadgeItem): React.JSX.Element {\n return (\n <Stack direction=\"row\" spacing={1.5} alignItems=\"flex-start\">\n <Box\n sx={{\n width: 36,\n height: 36,\n borderRadius: 2,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n bgcolor: \"background.paper\",\n color: \"primary.main\",\n border: 1,\n borderColor: \"divider\",\n flexShrink: 0,\n }}\n >\n {icon}\n </Box>\n <Box>\n <Text variant=\"body\" size=\"sm\" weight=\"bold\" as=\"p\">\n {label}\n </Text>\n <Text variant=\"caption\" color=\"secondary\" as=\"p\">\n {caption}\n </Text>\n </Box>\n </Stack>\n );\n}\n","import type { AiConnectionSummaryCopy } from \"./copy\";\nimport { providerForHostId, type AiHostGuide, type AiProvider } from \"../guide\";\n\n/**\n * Pure helpers + the connection type shared by the AI-onboarding flow steps\n * (`ai-flow-steps.tsx`) and the orchestration/status board (`ai-steps.tsx`),\n * kept here so neither JSX module has to import the other (no import cycle).\n */\n\n/** The live connection surfaced from the server (empty list when none). */\nexport interface AiConnection {\n clientName: string | null;\n /**\n * The provider this connection is attributed to (derived server-side from the\n * OAuth client's redirect URIs / confirmed by `announceAiConnection`). `null`\n * for a legacy connection recorded before attribution existed — matched\n * best-effort to whichever host the owner is connecting.\n */\n host: AiProvider | null;\n lastActiveAt: Date;\n}\n\n/** Friendly provider names for the connected-state title (\"Claude Conectado\"). */\nconst PROVIDER_LABEL: Record<AiProvider, string> = {\n claude: \"Claude\",\n chatgpt: \"ChatGPT\",\n codex: \"Codex\",\n};\n\n/** Resolve a persisted host id to its guide (falls back to the first host). */\nexport function resolveHost(hosts: readonly AiHostGuide[], hostId: unknown): AiHostGuide {\n const found = hosts.find((h) => h.id === hostId) ?? hosts[0];\n if (!found) throw new Error(\"resolveHost: hosts array must not be empty\");\n return found;\n}\n\n/** Friendly label for a persisted host id (falls back to a generic word). */\nexport function hostLabel(hosts: readonly AiHostGuide[], hostId: unknown): string {\n return hosts.find((h) => h.id === hostId)?.label ?? \"seu assistente\";\n}\n\n/**\n * The live connection for a given host, or null. A connection is matched by its\n * derived provider; a legacy `null`-host connection matches best-effort (so the\n * pre-attribution single-connection behavior still works).\n */\nexport function connectionForHost(\n connections: readonly AiConnection[],\n hostId: unknown,\n): AiConnection | null {\n const provider = typeof hostId === \"string\" ? providerForHostId(hostId) : null;\n if (!provider) return connections.find((c) => c.host === null) ?? connections[0] ?? null;\n return (\n connections.find((c) => c.host === provider) ?? connections.find((c) => c.host === null) ?? null\n );\n}\n\n/** The recency line from a timestamp, in the host's own words. */\nexport function activeAgo(date: Date, copy: AiConnectionSummaryCopy): string {\n const minutes = Math.max(0, Math.floor((Date.now() - date.getTime()) / 60_000));\n if (minutes < 1) return copy.activeNow;\n if (minutes < 60) return copy.activeMinutes(minutes);\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return copy.activeHours(hours);\n return copy.activeDays(Math.floor(hours / 24));\n}\n\n/** The most-recently-active connection across all providers (null when none). */\nfunction mostRecent(connections: readonly AiConnection[]): AiConnection | null {\n return connections.reduce<AiConnection | null>(\n (best, c) => (!best || c.lastActiveAt.getTime() > best.lastActiveAt.getTime() ? c : best),\n null,\n );\n}\n\n/** The configured-state TITLE, naming the connected assistant(s) — FUT req (F). */\nexport function connectedTitle(\n connections: readonly AiConnection[],\n hosts: readonly AiHostGuide[],\n connectedHostId: string | undefined,\n copy: AiConnectionSummaryCopy,\n): string {\n const providers = [...new Set(connections.map((c) => c.host).filter((h): h is AiProvider => h !== null))];\n if (providers.length === 1) return `${PROVIDER_LABEL[providers[0]!]} ${copy.connectedSuffix}`;\n if (providers.length > 1) {\n return copy.connectedSeveral(providers.map((p) => PROVIDER_LABEL[p]).join(\", \"));\n }\n // Legacy connection with no attributed provider — name the completed host.\n if (connections.length > 0) return `${hostLabel(hosts, connectedHostId)} ${copy.connectedSuffix}`;\n return copy.connectedGeneric;\n}\n\n/** The completed summary line (second line) for the configured-state header. */\nexport function connectedSummary(\n connections: readonly AiConnection[],\n copy: AiConnectionSummaryCopy,\n): string {\n const recent = mostRecent(connections);\n if (!recent) return copy.configured;\n return activeAgo(recent.lastActiveAt, copy);\n}\n","\"use client\";\n\nimport type { McpAiCopy } from \"./copy\";\nimport CheckCircleIcon from \"@mui/icons-material/CheckCircle\";\nimport OpenInNewIcon from \"@mui/icons-material/OpenInNew\";\nimport { useEffect, useState } from \"react\";\n\nimport { type GuidedNav } from \"@12-apps/onboarding\";\nimport { Progress } from \"@12-apps/ui/data-display/Progress\";\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostConfigureStage, AiHostGuide } from \"../guide\";\nimport { activeAgo, connectionForHost, hostLabel, type AiConnection } from \"./ai-connection-utils\";\nimport {\n EndpointCopyBlock,\n HostConnectHeader,\n HostDocsLink,\n HostOpenButton,\n HostStepList,\n PromptCopyBlock,\n} from \"./host-connect-guide\";\n\n/** The host's connect steps split across the Configurar / Conectar stages. */\nconst CONFIGURE_STEP_COUNT = 3;\n\n/** How often the Confirmar step re-checks the live connection while waiting. */\nconst POLL_INTERVAL_MS = 3000;\n\n/** A step's continue/back controls (Voltar left, primary next right). */\nfunction StepNav({\n nav,\n onNext,\n nextLabel,\n nextDisabled = false,\n nextTestId,\n copy,\n}: {\n nav: GuidedNav;\n onNext: () => void;\n nextLabel?: string;\n nextDisabled?: boolean;\n nextTestId?: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n return (\n <Stack direction=\"row\" spacing={1} alignItems=\"center\" justifyContent=\"space-between\">\n <Button variant=\"ghost\" onClick={() => nav.back()} data-testid=\"ai-step-back\">{copy.flow.back}</Button>\n <Button onClick={onNext} disabled={nextDisabled} data-testid={nextTestId}>\n {nextLabel}\n </Button>\n </Stack>\n );\n}\n\n/** Step 2 — copy the store URL; copying is the action that advances the wizard. */\nexport function CopyUrlStep({\n nav,\n endpointUrl,\n copy,\n}: {\n nav: GuidedNav;\n endpointUrl: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={3} data-testid=\"ai-copy-step\">\n <Box>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n {copy.flow.copyUrlTitle}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.flow.urlCaption}\n </Text>\n </Box>\n <EndpointCopyBlock copy={copy.connectGuide} flowCopy={copy.flow} endpointUrl={endpointUrl} copied={false} onCopy={() => nav.next()} />\n <Box>\n <Button variant=\"ghost\" onClick={() => nav.back()} data-testid=\"ai-step-back\">{copy.flow.back}</Button>\n </Box>\n </Stack>\n );\n}\n\n/** Step 3 — open the host's connectors and add + configure the custom connector. */\nexport function ConfigureStep({\n nav,\n host,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n copy: McpAiCopy;\n}): React.JSX.Element {\n // Hosts with no direct link (e.g. Claude Desktop) have nothing to open, so\n // \"Próximo\" is available immediately; otherwise it unlocks on the open click.\n const [opened, setOpened] = useState(!host.link);\n return (\n <Stack spacing={2.5} data-testid=\"ai-configure-step\">\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n <HostOpenButton host={host} onOpen={() => setOpened(true)} />\n <HostStepList steps={host.steps.slice(0, CONFIGURE_STEP_COUNT)} start={1} />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy} nav={nav} onNext={() => nav.next()} nextDisabled={!opened} nextTestId=\"ai-configure-next\" />\n </Stack>\n );\n}\n\n/**\n * One stage of a host's per-stage configuration (e.g. ChatGPT's \"enable\n * developer mode\" then \"configurar\"). Each stage has its OWN deep link — opening\n * it unlocks \"Próximo\" — and its own instructions.\n */\nexport function ConfigureStageStep({\n nav,\n host,\n stage,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n stage: AiHostConfigureStage;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const [opened, setOpened] = useState(!stage.link);\n return (\n <Stack spacing={2.5} data-testid={`ai-stage-${stage.id}`}>\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n {stage.link && (\n <Box>\n <Button\n onClick={() => {\n window.open(stage.link!.url, \"_blank\", \"noopener,noreferrer\");\n setOpened(true);\n }}\n data-testid={`ai-stage-link-${stage.id}`}\n >\n {stage.link.label}\n <OpenInNewIcon sx={{ fontSize: 16, ml: 0.5 }} />\n </Button>\n </Box>\n )}\n <HostStepList steps={stage.steps} start={1} />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy}\n nav={nav}\n onNext={() => nav.next()}\n nextDisabled={!opened}\n nextTestId={`ai-stage-next-${stage.id}`}\n />\n </Stack>\n );\n}\n\n/** Step 4 — connect: log in, authorize and activate the connector. */\nexport function ConnectStep({\n nav,\n host,\n connectPrompt,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n connectPrompt: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={2.5} data-testid=\"ai-connect-step\">\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n <HostStepList steps={host.steps.slice(CONFIGURE_STEP_COUNT)} start={CONFIGURE_STEP_COUNT + 1} />\n <PromptCopyBlock flowCopy={copy.flow}\n title={copy.flow.pasteTitle}\n caption={copy.flow.promptCaption}\n message={connectPrompt}\n />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy} nav={nav} onNext={() => nav.next()} nextLabel={copy.flow.advance} nextTestId=\"ai-connect-done\" />\n </Stack>\n );\n}\n\n/**\n * Simplified-flow step (host has a published `pluginUrl`): open the one-click\n * plugin (install + authorize), then paste the prompt asking the assistant to\n * connect. No URL to copy, no manual connector. The next step (Confirmar) waits.\n */\nexport function InstallStep({\n nav,\n host,\n connectPrompt,\n copy,\n}: {\n nav: GuidedNav;\n host: AiHostGuide;\n connectPrompt: string;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const [opened, setOpened] = useState(false);\n return (\n <Stack spacing={2.5} data-testid=\"ai-install-step\">\n <HostConnectHeader copy={copy.connectGuide} host={host} />\n <Text variant=\"body\" as=\"p\" color=\"secondary\">\n {copy.flow.installBody}\n </Text>\n {host.pluginUrl && (\n <Box>\n <Button\n onClick={() => {\n window.open(host.pluginUrl!, \"_blank\", \"noopener,noreferrer\");\n setOpened(true);\n }}\n data-testid=\"ai-install-open\"\n >\n {copy.flow.installAction}\n <OpenInNewIcon sx={{ fontSize: 16, ml: 0.5 }} />\n </Button>\n </Box>\n )}\n <PromptCopyBlock flowCopy={copy.flow}\n title={copy.flow.askTitle}\n caption={copy.flow.pasteInstallCaption}\n message={connectPrompt}\n />\n <HostDocsLink copy={copy.connectGuide} host={host} />\n <StepNav copy={copy}\n nav={nav}\n onNext={() => nav.next()}\n nextLabel={copy.flow.advance}\n nextDisabled={!opened}\n nextTestId=\"ai-install-done\"\n />\n </Stack>\n );\n}\n\n/**\n * Step 5: auto-detect the live connection. While waiting it polls the server\n * (the sign-in / `announceAiConnection` tool call registers the connection\n * server-side), showing a spinner — the owner never clicks \"verify\". Completes\n * when the selected host's connection appears.\n */\nexport function ConfirmStep({\n nav,\n connections,\n hosts,\n onRetest,\n copy,\n}: {\n nav: GuidedNav;\n connections: readonly AiConnection[];\n hosts: readonly AiHostGuide[];\n onRetest: () => void;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const selectedHostId = nav.data.selectedHost as string | undefined;\n const connection = connectionForHost(connections, selectedHostId);\n const label = connection?.clientName ?? hostLabel(hosts, selectedHostId);\n\n // Auto-detect: re-check on an interval until the connection shows up. The\n // interval is cleared as soon as `connection` is non-null (and on unmount).\n useEffect(() => {\n if (connection) return undefined;\n const id = setInterval(() => onRetest(), POLL_INTERVAL_MS);\n return () => clearInterval(id);\n }, [connection, onRetest]);\n\n if (connection) {\n return (\n <Stack spacing={2} data-testid=\"ai-confirm-connected\">\n <Stack direction=\"row\" spacing={1.5} alignItems=\"center\">\n <CheckCircleIcon sx={{ color: \"success.main\" }} />\n <Box>\n <Text variant=\"body\" weight=\"bold\" as=\"p\">\n {copy.flow.connectedTo(label)}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {activeAgo(connection.lastActiveAt, copy.summary)}\n </Text>\n </Box>\n </Stack>\n <Box>\n <Button onClick={() => nav.complete({ connectedHost: selectedHostId })}>{copy.flow.finish}</Button>\n </Box>\n </Stack>\n );\n }\n\n return (\n <Stack spacing={2.5} data-testid=\"ai-confirm-waiting\">\n <Stack direction=\"row\" spacing={1.5} alignItems=\"center\">\n <Progress variant=\"circular\" circularSize={22} thickness={4} dataTestId=\"ai-confirm-spinner\" />\n <Box>\n <Text variant=\"body\" weight=\"bold\" as=\"p\">\n {copy.flow.waitingTitle}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.flow.waitingBody(label)}\n </Text>\n </Box>\n </Stack>\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRetest} data-testid=\"ai-confirm-retest\">\n {copy.flow.testNow}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => nav.back()}>{copy.flow.back}</Button>\n </Stack>\n </Stack>\n );\n}\n","\"use client\";\n\nimport type { AiConnectGuideCopy, AiFlowCopy } from \"./copy\";\nimport CheckIcon from \"@mui/icons-material/Check\";\nimport ContentCopyOutlinedIcon from \"@mui/icons-material/ContentCopyOutlined\";\nimport OpenInNewIcon from \"@mui/icons-material/OpenInNew\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostGuide } from \"../guide\";\nimport { HostBrandAvatar } from \"./ai-icons\";\nimport { McpEndpointUrl } from \"./mcp-endpoint-url\";\n\n/**\n * The store's MCP endpoint URL with a blue \"Copiar\" button (the display-only\n * field defers the copy to this button). Controlled: `copied` flips the label to\n * \"Copiado\" and `onCopy` fires after the clipboard write — the wizard uses it to\n * unlock the \"Próximo\" button on the Copiar-URL step.\n */\nexport function EndpointCopyBlock({\n endpointUrl,\n copied,\n onCopy,\n flowCopy,\n copy,\n}: {\n endpointUrl: string;\n copied: boolean;\n onCopy: () => void;\n flowCopy: AiFlowCopy;\n copy: AiConnectGuideCopy;\n}): React.JSX.Element {\n const handleClick = (): void => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n void navigator.clipboard.writeText(endpointUrl).catch(() => undefined);\n }\n onCopy();\n };\n\n return (\n <Box\n sx={{\n p: 2,\n borderRadius: 2,\n border: 1,\n borderColor: \"primary.main\",\n bgcolor: \"action.hover\",\n }}\n >\n <Text variant=\"caption\" as=\"p\" weight=\"bold\">\n {copy.urlLabel}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.urlHint}\n </Text>\n <Box sx={{ mt: 1 }}>\n <McpEndpointUrl url={endpointUrl} copyable={false} />\n </Box>\n <Box sx={{ mt: 1.5 }}>\n <Button onClick={handleClick} data-testid=\"ai-copy-endpoint\">\n {copied ? (\n <CheckIcon sx={{ fontSize: 18, mr: 0.5 }} />\n ) : (\n <ContentCopyOutlinedIcon sx={{ fontSize: 18, mr: 0.5 }} />\n )}\n {copied ? flowCopy.copied : flowCopy.copyUrl}\n </Button>\n </Box>\n </Box>\n );\n}\n\n/**\n * A copyable multi-line message block (preserves line breaks). Used on the\n * Conectar step for the prompt the owner pastes into the assistant so it\n * identifies itself and calls a tool (which registers the connection).\n */\nexport function PromptCopyBlock({\n title,\n caption,\n message,\n flowCopy,\n}: {\n title: string;\n caption: string;\n message: string;\n flowCopy: AiFlowCopy;\n}): React.JSX.Element {\n const [copied, setCopied] = useState(false);\n\n const handleClick = (): void => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n void navigator.clipboard.writeText(message).catch(() => undefined);\n }\n setCopied(true);\n };\n\n return (\n <Box\n sx={{\n p: 2,\n borderRadius: 2,\n border: 1,\n borderColor: \"primary.main\",\n bgcolor: \"action.hover\",\n }}\n >\n <Text variant=\"caption\" as=\"p\" weight=\"bold\">\n {title}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {caption}\n </Text>\n <Box\n sx={{\n mt: 1,\n p: 1.5,\n borderRadius: 1,\n border: 1,\n borderColor: \"divider\",\n bgcolor: \"background.paper\",\n whiteSpace: \"pre-line\",\n }}\n >\n <Text variant=\"body\" size=\"sm\" as=\"p\">\n {message}\n </Text>\n </Box>\n <Box sx={{ mt: 1.5 }}>\n <Button onClick={handleClick} data-testid=\"ai-copy-prompt\">\n {copied ? (\n <CheckIcon sx={{ fontSize: 18, mr: 0.5 }} />\n ) : (\n <ContentCopyOutlinedIcon sx={{ fontSize: 18, mr: 0.5 }} />\n )}\n {copied ? flowCopy.copied : flowCopy.copyMessage}\n </Button>\n </Box>\n </Box>\n );\n}\n\n/** The brand mark + \"Conectar no <host>\" header shared by the connect sub-steps. */\nexport function HostConnectHeader({\n host,\n copy,\n}: {\n host: AiHostGuide;\n copy: AiConnectGuideCopy;\n}): React.JSX.Element {\n return (\n <Stack direction=\"row\" spacing={1.5} alignItems=\"center\">\n <HostBrandAvatar brand={host.brand} size={36} />\n <Text variant=\"heading\" size=\"sm\" as=\"h3\">\n {copy.connectOn(host.label)}\n </Text>\n </Stack>\n );\n}\n\n/**\n * The primary direct-link button to a host's connector settings (nothing when it\n * has none). `onOpen` fires after the link opens so the Configurar step can\n * unlock its \"Próximo\" only once the owner has actually gone to the connectors.\n */\nexport function HostOpenButton({\n host,\n onOpen,\n}: {\n host: AiHostGuide;\n onOpen?: () => void;\n}): React.JSX.Element | null {\n if (!host.link) return null;\n return (\n <Box>\n <Button\n onClick={() => {\n window.open(host.link!.url, \"_blank\", \"noopener,noreferrer\");\n onOpen?.();\n }}\n data-testid={`ai-host-link-${host.id}`}\n >\n {host.link.label}\n <OpenInNewIcon sx={{ fontSize: 16, ml: 0.5 }} />\n </Button>\n </Box>\n );\n}\n\n/** A \"Para mais informações\" reference to the host's official connector docs. */\nexport function HostDocsLink({ host,\n copy,\n}: { host: AiHostGuide;\n copy: AiConnectGuideCopy;}): React.JSX.Element | null {\n if (!host.docs) return null;\n return (\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.moreInfo}{\" \"}\n <Box\n component=\"a\"\n href={host.docs.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-testid={`ai-host-docs-${host.id}`}\n sx={{ color: \"primary.main\", textDecoration: \"underline\" }}\n >\n {host.docs.label}\n </Box>\n .\n </Text>\n );\n}\n\n/**\n * A numbered slice of a host's connect steps. `start` keeps the numbering\n * continuous when the steps are split across wizard stages (e.g. the Conectar\n * stage continues at 4 after Configurar showed 1–3).\n */\nexport function HostStepList({\n steps,\n start = 1,\n}: {\n steps: readonly string[];\n start?: number;\n}): React.JSX.Element {\n return (\n <Box component=\"ol\" start={start} sx={{ m: 0, pl: 3 }}>\n {steps.map((step, index) => (\n <Box component=\"li\" key={index} sx={{ mb: 1 }}>\n <Text variant=\"body\" as=\"span\">\n {step}\n </Text>\n </Box>\n ))}\n </Box>\n );\n}\n","\"use client\";\n\nimport { Code } from \"@12-apps/ui/typography/Code\";\n\n/**\n * The store's MCP endpoint URL. Client component because the copy interaction\n * needs the browser clipboard — the `@12-apps/ui` Code component provides the copy\n * affordance (`copyable`). Pass `copyable={false}` for a display-only field when\n * an external control owns the copy action (e.g. the connect flow's blue Copiar\n * button, which also gates the following steps on the copy).\n */\nexport function McpEndpointUrl({\n url,\n copyable = true,\n}: {\n url: string;\n copyable?: boolean;\n}): React.JSX.Element {\n return (\n <Code variant=\"block\" copyable={copyable} data-testid=\"mcp-endpoint-url\">\n {url}\n </Code>\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { AiStatusBoardCopy } from \"./copy\";\nimport AddLinkOutlinedIcon from \"@mui/icons-material/AddLinkOutlined\";\nimport CheckCircleIcon from \"@mui/icons-material/CheckCircle\";\nimport LinkOffOutlinedIcon from \"@mui/icons-material/LinkOffOutlined\";\nimport MenuBookOutlinedIcon from \"@mui/icons-material/MenuBookOutlined\";\n\nimport { createConfirmButton } from \"@12-apps/ui/feedback/ConfirmAction\";\nimport { Button } from \"@12-apps/ui/form/Button\";\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostGuide } from \"../guide\";\nimport { HostBrandAvatar } from \"./ai-icons\";\n\n/**\n * Revoke a host's access. Returning a promise holds the confirmation popup in\n * its pending state until the write settles, and a rejection keeps it open\n * carrying the reason — so the owner sees the disconnect finish or fail.\n */\nexport type DisconnectHandler = (hostId: string) => void | Promise<unknown>;\n\n/** One assistant's connection state. */\nexport interface HostStatus {\n host: AiHostGuide;\n connected: boolean;\n /** Freeform activity line for a connected host (e.g. \"ativo há 3 min\"). */\n detail?: string;\n}\n\n/**\n * The right-hand side of a CONNECTED box: the green pill, then the two things\n * the pill alone left the owner unable to do.\n *\n * \"{copy.instructions}\" exists because the setup steps were reachable ONLY from a RED\n * card's \"Conectar\" — so on an all-green board there was no way to re-read how\n * any of them was connected, which is exactly when someone re-doing the setup on\n * a second machine needs them. It re-enters the same flow that button does.\n *\n * \"Desconectar\" is only drawn when the app supplies a revoke path: a board with\n * nowhere to send the revoke must not offer a button that does nothing.\n */\nfunction ConnectedControls({\n host,\n onConnect,\n onDisconnect,\n copy,\n}: {\n host: AiHostGuide;\n onConnect: (hostId: string) => void;\n onDisconnect?: DisconnectHandler;\n copy: AiStatusBoardCopy;\n}): React.JSX.Element {\n // Built from the copy rather than at module scope: `createConfirmButton`\n // takes the words, and they only arrive as a prop. Memoised so the wrapped\n // component keeps its identity across renders and React does not remount it.\n const DisconnectButton = useMemo(\n () => createConfirmButton(copy.confirmAction, copy.disconnectError),\n [copy.confirmAction, copy.disconnectError],\n );\n return (\n <Stack\n direction=\"row\"\n spacing={1}\n alignItems=\"center\"\n justifyContent=\"flex-end\"\n // Wraps rather than squeezing: three controls do not fit a half-width\n // card at every breakpoint.\n sx={{ flexShrink: 0, flexWrap: \"wrap\", rowGap: 0.5 }}\n >\n <Box\n sx={{\n px: 1,\n py: 0.25,\n borderRadius: 999,\n bgcolor: \"success.main\",\n color: \"success.contrastText\",\n }}\n >\n <Text variant=\"caption\" weight=\"bold\" as=\"span\">\n {copy.connected}\n </Text>\n </Box>\n <Button\n variant=\"text\"\n size=\"sm\"\n onClick={() => onConnect(host.id)}\n data-testid={`ai-status-instructions-${host.id}`}\n >\n <MenuBookOutlinedIcon sx={{ fontSize: 16, mr: 0.5 }} />\n {copy.instructions}\n </Button>\n {onDisconnect ? (\n <DisconnectButton\n variant=\"outline\"\n color=\"danger\"\n size=\"sm\"\n onClick={() => onDisconnect(host.id)}\n confirm={{\n title: copy.disconnectTitle,\n entityName: host.label,\n description:\n copy.disconnectBody,\n confirmText: copy.disconnectConfirm,\n dataTestId: `ai-status-disconnect-confirm-${host.id}`,\n }}\n data-testid={`ai-status-disconnect-${host.id}`}\n >\n <LinkOffOutlinedIcon sx={{ fontSize: 16, mr: 0.5 }} />\n {copy.disconnect}\n </DisconnectButton>\n ) : null}\n </Stack>\n );\n}\n\n/** A single green (connected) / red (to connect) status box for one assistant. */\nfunction StatusBox({\n status,\n onConnect,\n onDisconnect,\n copy,\n}: {\n status: HostStatus;\n onConnect: (hostId: string) => void;\n onDisconnect?: DisconnectHandler;\n copy: AiStatusBoardCopy;\n}): React.JSX.Element {\n const { host, connected, detail } = status;\n return (\n <Box\n data-testid={`ai-status-${host.id}`}\n data-connected={connected}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 1.5,\n p: 2,\n borderRadius: 3,\n border: 1,\n borderColor: connected ? \"success.main\" : \"error.main\",\n bgcolor: \"background.paper\",\n }}\n >\n <HostBrandAvatar brand={host.brand} size={36} />\n <Box sx={{ minWidth: 0, flexGrow: 1 }}>\n <Stack direction=\"row\" spacing={0.75} alignItems=\"center\">\n <Text variant=\"body\" weight=\"bold\" as=\"span\">\n {host.label}\n </Text>\n {connected ? <CheckCircleIcon sx={{ fontSize: 18, color: \"success.main\" }} /> : null}\n </Stack>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {connected ? (detail ?? copy.connected) : copy.notConnected}\n </Text>\n </Box>\n {connected ? (\n <ConnectedControls copy={copy} host={host} onConnect={onConnect} onDisconnect={onDisconnect} />\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onConnect(host.id)}\n data-testid={`ai-status-connect-${host.id}`}\n >\n <AddLinkOutlinedIcon sx={{ fontSize: 16, mr: 0.5 }} />\n Conectar\n </Button>\n )}\n </Box>\n );\n}\n\n/**\n * The completed-state status board for the AI integration: every assistant as a\n * box — green when connected, red when still to connect (with a \"Conectar\"\n * button that re-enters the guided flow for that host). Each connection is\n * attributed to its provider (derived from the OAuth client + confirmed by\n * `announceAiConnection`), so several assistants can show connected at once.\n *\n * A connected box carries two more controls, because the pill it used to show\n * alone was a dead end in both directions: \"{copy.instructions}\" re-enters the host's\n * setup steps (previously reachable only from a RED card, so an all-green board\n * hid them entirely), and \"Desconectar\" — when the app passes `onDisconnect` —\n * revokes access, which nothing in the UI could do at all.\n */\nexport function AiStatusBoard({\n statuses,\n onConnect,\n onDisconnect,\n copy,\n}: {\n statuses: readonly HostStatus[];\n onConnect: (hostId: string) => void;\n /** Revoke this host's access. Omit to render a read-only board. */\n onDisconnect?: DisconnectHandler;\n copy: AiStatusBoardCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={2} data-testid=\"ai-status-board\">\n <Box>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n {copy.boardTitle}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.boardCaption}\n </Text>\n </Box>\n <Box\n sx={{\n display: \"grid\",\n gap: 2,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\" },\n }}\n >\n {statuses.map((status) => (\n <StatusBox copy={copy}\n key={status.host.id}\n status={status}\n onConnect={onConnect}\n onDisconnect={onDisconnect}\n />\n ))}\n </Box>\n </Stack>\n );\n}\n","\"use client\";\n\nimport type { AiHostSelectCopy } from \"./copy\";\nimport CheckCircleIcon from \"@mui/icons-material/CheckCircle\";\n\nimport { Box } from \"@12-apps/ui/mui/Box\";\nimport { Stack } from \"@12-apps/ui/mui/Stack\";\nimport { Text } from \"@12-apps/ui/typography/Text\";\n\nimport type { AiHostGuide } from \"../guide\";\nimport { HostBrandAvatar } from \"./ai-icons\";\n\n/** One selectable assistant card (brand mark + name + kind, checked when active). */\nfunction HostCard({\n host,\n active,\n onSelect,\n}: {\n host: AiHostGuide;\n active: boolean;\n onSelect: () => void;\n}): React.JSX.Element {\n return (\n <Box\n component=\"button\"\n type=\"button\"\n onClick={onSelect}\n aria-pressed={active}\n data-testid={`ai-host-card-${host.id}`}\n sx={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 1.5,\n p: 2,\n borderRadius: 3,\n cursor: \"pointer\",\n textAlign: \"left\",\n width: \"100%\",\n border: 2,\n borderColor: active ? \"primary.main\" : \"divider\",\n bgcolor: active ? \"action.selected\" : \"background.paper\",\n transition: (theme) => theme.transitions.create([\"border-color\", \"background-color\"]),\n \"&:hover\": { borderColor: \"primary.main\" },\n }}\n >\n <HostBrandAvatar brand={host.brand} size={40} />\n <Box sx={{ minWidth: 0 }}>\n <Text variant=\"body\" weight=\"bold\" as=\"span\">\n {host.label}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {host.kind}\n </Text>\n </Box>\n {active && (\n <CheckCircleIcon\n sx={{ position: \"absolute\", top: 10, right: 10, fontSize: 20, color: \"primary.main\" }}\n />\n )}\n </Box>\n );\n}\n\n/**\n * Step 1 of the guided AI connect flow: the owner picks a single assistant\n * (Claude.ai, Claude Desktop, ChatGPT, Codex) from a card grid. Picking a card\n * advances straight to the next step — no separate \"Próximo\" button. Selection\n * is controlled (persisted by the onboarding flow) so a refresh resumes with the\n * same assistant highlighted.\n */\nexport function HostSelectStep({\n hosts,\n selectedId,\n onSelect,\n copy,\n}: {\n hosts: readonly AiHostGuide[];\n selectedId: string | null;\n onSelect: (hostId: string) => void;\n copy: AiHostSelectCopy;\n}): React.JSX.Element {\n return (\n <Stack spacing={3} data-testid=\"ai-host-select\">\n <Box>\n <Text variant=\"heading\" size=\"sm\" as=\"h2\">\n {copy.heading}\n </Text>\n <Text variant=\"caption\" as=\"p\" color=\"secondary\">\n {copy.caption}\n </Text>\n </Box>\n\n <Box\n sx={{\n display: \"grid\",\n gap: 2,\n gridTemplateColumns: { xs: \"1fr\", sm: \"1fr 1fr\" },\n }}\n >\n {hosts.map((host) => (\n <HostCard\n key={host.id}\n host={host}\n active={host.id === selectedId}\n onSelect={() => onSelect(host.id)}\n />\n ))}\n </Box>\n </Stack>\n );\n}\n","\"use client\";\n\nimport type { McpAiCopy } from \"./copy\";\nimport { type GuidedNav, type GuidedStep } from \"@12-apps/onboarding\";\n\nimport { providerForHostId, type AiHostGuide } from \"../guide\";\nimport { activeAgo, resolveHost, type AiConnection } from \"./ai-connection-utils\";\nimport {\n ConfigureStageStep,\n ConfigureStep,\n ConfirmStep,\n ConnectStep,\n CopyUrlStep,\n InstallStep,\n} from \"./ai-flow-steps\";\nimport { AiStatusBoard, type DisconnectHandler, type HostStatus } from \"./ai-status-board\";\nimport { HostSelectStep } from \"./host-select-step\";\n\nexport type { AiConnection } from \"./ai-connection-utils\";\nexport { connectedSummary, connectedTitle } from \"./ai-connection-utils\";\n\n/** The completed status board: green for each connected host, red for the rest. */\nexport function StatusBoard({\n nav,\n connections,\n hosts,\n onDisconnect,\n copy,\n}: {\n nav: GuidedNav;\n connections: readonly AiConnection[];\n hosts: readonly AiHostGuide[];\n onDisconnect?: DisconnectHandler;\n copy: McpAiCopy;\n}): React.JSX.Element {\n const legacyHostId = (nav.data.connectedHost ?? nav.data.selectedHost) as string | undefined;\n\n const statuses: HostStatus[] = hosts.map((host) => {\n const provider = providerForHostId(host.id);\n // Prefer a provider-attributed connection; fall back to a legacy null-host\n // connection only for the host the owner completed the flow with.\n const connection =\n (provider ? connections.find((c) => c.host === provider) : undefined) ??\n (host.id === legacyHostId ? connections.find((c) => c.host === null) : undefined) ??\n null;\n return {\n host,\n connected: connection !== null,\n detail: connection ? activeAgo(connection.lastActiveAt, copy.summary) : undefined,\n };\n });\n\n /** Re-enter this host's setup — the manual copy path, or its one-click install. */\n const goToConnect = (hostId: string): void => {\n nav.goTo(hosts.find((h) => h.id === hostId)?.pluginUrl ? \"install\" : \"copy\", {\n selectedHost: hostId,\n });\n };\n\n /**\n * Disconnecting the LAST assistant leaves the section configured with nothing\n * configured: a collapsed \"IA conectada\" summary hiding an all-red board, with\n * the setup instructions two clicks away. So when the revoke empties the\n * board, walk straight back into that host's instructions — the owner who just\n * cut an assistant off is the likeliest person to reconnect one, and the steps\n * are the only thing left worth showing.\n *\n * Cutting one of SEVERAL leaves the board meaningful, so it stays put.\n * `statuses` is the pre-revoke picture, which is what makes \"was that the last\n * one?\" answerable here without waiting for the app to re-read.\n */\n const disconnect: DisconnectHandler | undefined = onDisconnect\n ? async (hostId) => {\n await onDisconnect(hostId);\n const revoked = providerForHostId(hostId);\n const othersLive = statuses.some(\n (status) => status.connected && providerForHostId(status.host.id) !== revoked,\n );\n if (!othersLive) goToConnect(hostId);\n }\n : undefined;\n\n return (\n <AiStatusBoard copy={copy.statusBoard} statuses={statuses} onConnect={goToConnect} onDisconnect={disconnect} />\n );\n}\n\n/** The first step (host picker) — picking a card advances to the right path. */\nfunction selectStep(hosts: readonly AiHostGuide[], copy: McpAiCopy): GuidedStep {\n return {\n id: \"select\",\n label: copy.flow.steps.select,\n render: (nav: GuidedNav) => (\n <HostSelectStep\n hosts={hosts}\n selectedId={(nav.data.selectedHost as string | undefined) ?? null}\n copy={copy.hostSelect}\n onSelect={(hostId) =>\n nav.goTo(hosts.find((h) => h.id === hostId)?.pluginUrl ? \"install\" : \"copy\", {\n selectedHost: hostId,\n })\n }\n />\n ),\n };\n}\n\n/** The Copiar-URL step, shared by every manual flow. */\nfunction copyStep(endpointUrl: string, copy: McpAiCopy): GuidedStep {\n return {\n id: \"copy\",\n label: copy.flow.steps.copyUrl,\n render: (nav: GuidedNav) => <CopyUrlStep copy={copy} nav={nav} endpointUrl={endpointUrl} />,\n };\n}\n\n/**\n * The middle steps for the full manual flow. A host with `configureStages`\n * (e.g. ChatGPT) gets one step per stage — each with its own deep link — after\n * Copiar URL; otherwise the default copy → configure → connect split.\n */\nfunction manualMiddle(\n host: AiHostGuide,\n hosts: readonly AiHostGuide[],\n endpointUrl: string,\n connectPrompt: string,\n copy: McpAiCopy,\n): GuidedStep[] {\n if (host.configureStages && host.configureStages.length > 0) {\n return [\n copyStep(endpointUrl, copy),\n ...host.configureStages.map((stage) => ({\n id: stage.id,\n label: stage.label,\n render: (nav: GuidedNav) => (\n <ConfigureStageStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n stage={stage}\n copy={copy}\n />\n ),\n })),\n ];\n }\n return [\n copyStep(endpointUrl, copy),\n {\n id: \"configure\",\n label: copy.flow.steps.configure,\n render: (nav: GuidedNav) => (\n <ConfigureStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n copy={copy}\n />\n ),\n },\n {\n id: \"connect\",\n label: copy.flow.steps.connect,\n render: (nav: GuidedNav) => (\n <ConnectStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n connectPrompt={connectPrompt}\n copy={copy}\n />\n ),\n },\n ];\n}\n\n/** The single middle step for the simplified plugin flow: install. */\nfunction simpleMiddle(\n hosts: readonly AiHostGuide[],\n connectPrompt: string,\n copy: McpAiCopy,\n): GuidedStep[] {\n return [\n {\n id: \"install\",\n label: copy.flow.steps.install,\n render: (nav: GuidedNav) => (\n <InstallStep\n nav={nav}\n host={resolveHost(hosts, nav.data.selectedHost)}\n connectPrompt={connectPrompt}\n copy={copy}\n />\n ),\n },\n ];\n}\n\n/**\n * Build the wizard's steps for the selected host's path: the simplified\n * `install` flow when the host has a published `pluginUrl`, the per-stage flow\n * when it declares `configureStages`, otherwise the full copy → configure →\n * connect flow. `select` and `confirm` bookend all of them.\n */\nexport function buildFlowSteps(opts: {\n host: AiHostGuide;\n hosts: readonly AiHostGuide[];\n endpointUrl: string;\n connectPrompt: string;\n connections: readonly AiConnection[];\n onRetest: () => void;\n copy: McpAiCopy;\n}): GuidedStep[] {\n const { host, hosts, endpointUrl, connectPrompt, connections, onRetest, copy } = opts;\n const middle = host.pluginUrl\n ? simpleMiddle(hosts, connectPrompt, copy)\n : manualMiddle(host, hosts, endpointUrl, connectPrompt, copy);\n const confirm: GuidedStep = {\n id: \"confirm\",\n label: copy.flow.steps.confirm,\n render: (nav: GuidedNav) => (\n <ConfirmStep\n nav={nav}\n connections={connections}\n hosts={hosts}\n onRetest={onRetest}\n copy={copy}\n />\n ),\n };\n return [selectStep(hosts, copy), ...middle, confirm];\n}\n","import { PT_BR_CONFIRM_ACTION_COPY } from \"@12-apps/ui/pt-BR\";\n\nimport type { McpAiCopy } from \"./copy\";\n\n/**\n * The pt-BR pack for the AI-integration screens — a NAMED constant a host\n * passes by hand, never a default.\n *\n * The filename is what exempts this file from the copy-portability gate:\n * Portuguese may ship, it may not be silent. Every sentence is VERBATIM what\n * the components used to render, so a host adopting it sees no change on\n * screen — what changes is that the words are chosen in a diff.\n */\nexport const PT_BR_MCP_AI_COPY: McpAiCopy = {\n capabilities: {\n heading: \"O que o assistente faz por você\",\n subheading: \"Sem planilhas, sem cliques — é só perguntar na conversa.\",\n },\n landing: {\n eyebrow: \"Integração com IA\",\n titleTail: \"à sua loja\",\n lede:\n \"Deixe o Claude, o ChatGPT e outros assistentes responderem sobre o seu cardápio, estoque e \" +\n \"pedidos — e executarem ações por você, direto na conversa. Com segurança e sem instalar nada.\",\n trust: [\n {\n id: \"login\",\n label: \"Usa o seu próprio login\",\n caption: \"Sem chaves ou credenciais extras\",\n },\n { id: \"install\", label: \"Sem instalar nada\", caption: \"Conecta em poucos minutos\" },\n {\n id: \"permissions\",\n label: \"Só o que você pode\",\n caption: \"As suas permissões, nada além\",\n },\n { id: \"surface\", label: \"Navegador ou app\", caption: \"Claude, ChatGPT, Codex\" },\n ],\n start: \"Começar\",\n },\n flow: {\n steps: {\n select: \"Escolher\",\n copyUrl: \"Copiar URL\",\n configure: \"Configurar\",\n connect: \"Conectar\",\n install: \"Instalar\",\n confirm: \"Confirmar\",\n },\n back: \"Voltar\",\n next: \"Próximo\",\n advance: \"Continuar\",\n finish: \"Concluir\",\n copyUrl: \"Copiar URL\",\n copied: \"Copiado\",\n copyMessage: \"Copiar mensagem\",\n copyUrlTitle: \"Copie a URL da sua loja\",\n urlCaption:\n \"É o único dado que você cola no assistente — ao copiar, seguimos para o próximo passo.\",\n promptCaption:\n \"Assim ele se conecta, se identifica (Claude, ChatGPT…) e registramos a conexão.\",\n askTitle: \"Peça ao assistente para conectar\",\n installBody:\n \"Abra o plugin da sua loja, clique em Instalar e autorize o acesso — sem copiar URL nem gerar credenciais.\",\n installAction: \"Instalar o plugin da loja\",\n pasteTitle: \"Cole esta mensagem no assistente\",\n pasteInstallCaption:\n \"Cole no assistente para ele se conectar, se identificar e confirmar o acesso.\",\n connectedTo: (hostLabel) => `${hostLabel} está conectado à sua loja.`,\n waitingTitle: \"Esperando conexão\",\n waitingBody: (hostLabel) =>\n `Assim que você autorizar o acesso no ${hostLabel}, ela aparece aqui automaticamente.`,\n testNow: \"Testar agora\",\n },\n statusBoard: {\n instructions: \"Instruções\",\n connected: \"Conectado\",\n notConnected: \"Ainda não conectado\",\n connect: \"Conectar\",\n disconnect: \"Desconectar\",\n disconnectTitle: \"Desconectar o assistente?\",\n disconnectBody:\n \"Ele perde o acesso à sua loja na hora. Para voltar a usar, será preciso conectar de novo.\",\n disconnectConfirm: \"Desconectar\",\n disconnectError: \"Não foi possível desconectar. Tente de novo.\",\n boardTitle: \"Assistentes conectados\",\n boardCaption: \"Em verde os que já operam a sua loja; em vermelho os que faltam conectar.\",\n confirmAction: PT_BR_CONFIRM_ACTION_COPY,\n },\n summary: {\n activeNow: \"ativo agora\",\n activeMinutes: (minutes) => `ativo há ${minutes} min`,\n activeHours: (hours) => `ativo há ${hours} h`,\n activeDays: (days) => `ativo há ${days} dias`,\n configured: \"Integração configurada\",\n connectedSuffix: \"Conectado\",\n connectedSeveral: (names) => `${names} conectados`,\n connectedGeneric: \"IA conectada\",\n },\n hostSelect: {\n heading: 'Escolha o seu assistente',\n caption: \"Selecione onde você usa a IA — o passo a passo é feito sob medida para ele.\",\n },\n connectGuide: {\n urlLabel: \"URL do servidor da sua loja\",\n urlHint: \"Copie esta URL e cole no seu assistente para conectá-lo à loja.\",\n moreInfo: \"Para mais informações, consulte a\",\n connectOn: (hostLabel) => `Conectar no ${hostLabel}`,\n },\n onboarding: {\n title: \"Conecte assistentes de IA à sua loja\",\n editLabel: \"Conectar IA\",\n collapseLabel: \"Ocultar\",\n },\n};\n"],"mappings":"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","names":["Box","Stack","Text","Box","jsx","Box","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Stack","Box","Text","OpenInNewIcon","useState","Button","Box","Stack","Text","Button","Box","Stack","Text","jsx","jsx","jsxs","Box","Text","Button","Stack","jsx","jsxs","Stack","Button","Box","Text","useState","OpenInNewIcon","CheckCircleIcon","Button","Box","Stack","Text","jsx","jsxs","Stack","Box","Text","Button","CheckCircleIcon","CheckCircleIcon","Box","Stack","Text","jsx","jsxs","Box","Text","CheckCircleIcon","Stack","jsx","jsx","hostLabel"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "App-agnostic MCP server core: generate one MCP tool per OpenAPI operation and proxy each call carrying the caller's bearer token (permission passthrough). Also ships the OAuth 2.1 authorization server (./oauth, ./hono: register/authorize/token, JWKS and both .well-known documents), the package-owned Prisma partial + migration for its three tables, the mcp:generate/mcp:check (./generate) and mcp:coverage (./coverage) gates, and the reusable AI-connect onboarding UI (./react).",
|
|
6
6
|
"exports": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@12-apps/onboarding": "^2.3.0",
|
|
46
46
|
"@12-apps/rbac": "^4.3.1",
|
|
47
|
-
"@12-apps/ui": "^6.
|
|
47
|
+
"@12-apps/ui": "^6.4.0",
|
|
48
48
|
"@mui/icons-material": "^6.5.0",
|
|
49
49
|
"jose": "^6.1.3",
|
|
50
50
|
"react": "^19.2.0"
|
package/src/react/ai-landing.tsx
CHANGED
package/src/react/copy.ts
CHANGED
|
@@ -131,6 +131,8 @@ export interface AiConnectionSummaryCopy {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export interface AiHostSelectCopy {
|
|
134
|
+
/** The step's own heading, above the host tiles. */
|
|
135
|
+
heading: string;
|
|
134
136
|
/** Why the owner is picking, under the host tiles. */
|
|
135
137
|
caption: string;
|
|
136
138
|
}
|
|
@@ -84,7 +84,7 @@ export function HostSelectStep({
|
|
|
84
84
|
<Stack spacing={3} data-testid="ai-host-select">
|
|
85
85
|
<Box>
|
|
86
86
|
<Text variant="heading" size="sm" as="h2">
|
|
87
|
-
|
|
87
|
+
{copy.heading}
|
|
88
88
|
</Text>
|
|
89
89
|
<Text variant="caption" as="p" color="secondary">
|
|
90
90
|
{copy.caption}
|
package/src/react/pt-BR.ts
CHANGED
|
@@ -98,6 +98,7 @@ export const PT_BR_MCP_AI_COPY: McpAiCopy = {
|
|
|
98
98
|
connectedGeneric: "IA conectada",
|
|
99
99
|
},
|
|
100
100
|
hostSelect: {
|
|
101
|
+
heading: 'Escolha o seu assistente',
|
|
101
102
|
caption: "Selecione onde você usa a IA — o passo a passo é feito sob medida para ele.",
|
|
102
103
|
},
|
|
103
104
|
connectGuide: {
|