@wireai/activation 0.13.6-next.0 → 0.13.6
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/AGENTS.md +1 -1
- package/CHANGELOG.md +87 -3
- package/README.md +32 -34
- package/dist/analytics/index.d.mts +2 -2
- package/dist/analytics/index.d.ts +2 -2
- package/dist/{currentSession-DD6dKB0i.d.ts → currentSession-C5976akx.d.ts} +27 -1
- package/dist/{currentSession-Cs3lweFZ.d.mts → currentSession-DngW-QoD.d.mts} +27 -1
- package/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -3
- package/dist/index.mjs.map +1 -1
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/src/OnboardingFlow.tsx +19 -2
- package/src/types.ts +27 -2
- package/src/utils/readPlan.ts +18 -5
- package/src/utils/readProgress.ts +5 -0
package/AGENTS.md
CHANGED
|
@@ -60,7 +60,7 @@ subpaths are optional secondary feature modules; import one only if you use it.
|
|
|
60
60
|
| Prop | Type | Required | Notes |
|
|
61
61
|
|---|---|---|---|
|
|
62
62
|
| `config` | `WireOnboardingConfig` | yes | A2A transport + tenant. See the `config` fields table below. |
|
|
63
|
-
| `onComplete` | `(result:
|
|
63
|
+
| `onComplete` | `(result: OnboardingResult) => void` | yes | Terminal recap CTA tapped. Persist `answers` via your profile-update path, then navigate on. `result` always has `answers` + `raw`; since 0.13.6 it also carries `plan` (the backend's onboarding plan, AI path only) and `variant` (the assigned experiment arm) when the backend sent them. Both keys are ABSENT otherwise, so an integration written before 0.13.6 sees no change. The kit does not interpret either one: validate `plan` before applying it. |
|
|
64
64
|
| `theme` | `Partial<OnboardingTheme>` | no | Colors + font family names + radius/spacing, deep-merged over a neutral default. For dark/light, pass a different theme per app theme-state. |
|
|
65
65
|
| `components` | `WireAIComponent[]` | no | Override registered cards (default `onboardingComponents`). |
|
|
66
66
|
| `illustrations` | `Record<string, ReactNode>` | no | Host artwork for `InterstitialCard`, keyed by name. `{ ...defaultIllustrations, ...myArt }`. |
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,81 @@
|
|
|
3
3
|
All notable changes to `@wireai/activation` (formerly `wireai-onboarding`).
|
|
4
4
|
Historical entries below the rename keep the old package name on purpose.
|
|
5
5
|
|
|
6
|
+
## [0.13.6] - 2026-08-09
|
|
7
|
+
|
|
8
|
+
Two things the backend already decides, handed to the host instead of guessed at. Both ride the
|
|
9
|
+
same boundary: the kit reads a payload the server sent, carries it out through `onComplete`, and
|
|
10
|
+
stops. It does not interpret either one, does not validate their contents, does not log them and
|
|
11
|
+
never attaches them to an analytics event.
|
|
12
|
+
|
|
13
|
+
The `plan` half of this release was published as `0.13.6-next.0` on 2026-08-08 with no changelog
|
|
14
|
+
entry. This entry is that debt paid, plus the `variant` half, released together as 0.13.6.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **`OnboardingResult.plan`, the backend's onboarding plan reaching the host uninterpreted.**
|
|
19
|
+
On the AI path the server appends a SECOND A2A DataPart to the turn it finishes on,
|
|
20
|
+
`{ kind: "onboarding_plan", plan: {...} }`, alongside the component envelope the renderer already
|
|
21
|
+
consumes. A new pure reader, `src/utils/readPlan.ts`, lifts it off the thread and `handleFinish`
|
|
22
|
+
puts it on the result. The static (non-AI) flow carries no plan and is unchanged.
|
|
23
|
+
|
|
24
|
+
The one thing the reader is allowed to reject is a structural fact: a plan is an object. A scalar,
|
|
25
|
+
an array, a misspelled marker or a missing payload yields `undefined` and the host falls back to
|
|
26
|
+
exactly its pre-plan behaviour. No field is required and no unknown field is stripped, because a
|
|
27
|
+
kit-side schema would make the kit the thing that rejects a plan the host could have used, and the
|
|
28
|
+
server's lenient path adds markers the kit must neither read nor strip. **The host must validate
|
|
29
|
+
the payload before applying it.**
|
|
30
|
+
|
|
31
|
+
**It finds the plan by MARKER, never by position**, and that is the load-bearing part of the read.
|
|
32
|
+
The kit walks the thread newest turn first and, inside a turn, returns the first part whose `kind`
|
|
33
|
+
is `onboarding_plan` and whose payload is an object. Anything else is skipped rather than treated
|
|
34
|
+
as a terminator, so a thread carrying two plans resolves to the last one, the turn the flow
|
|
35
|
+
completes on, and a malformed part can never shadow a good one. Position would be the wrong tool
|
|
36
|
+
here: the SDK collects a task's parts across agent messages LATEST-FIRST, so on a task that
|
|
37
|
+
carries history a previous turn's envelope can sit in the same array as this turn's plan. The
|
|
38
|
+
marker makes that harmless, and it is also why nothing in this pipe promises wire order.
|
|
39
|
+
|
|
40
|
+
It needs an SDK that surfaces the DataParts PAST the first one. The first DataPart is the
|
|
41
|
+
component envelope the renderer already consumes, and it is the one the SDK turns into the string
|
|
42
|
+
it returns for the turn, so the plan is one of the parts left behind after it.
|
|
43
|
+
`wireai-rn@0.2.5-next.1` hands those over on `Message.dataParts`, and a turn that carried nothing
|
|
44
|
+
but the envelope leaves the member ABSENT rather than an empty array (checked against the
|
|
45
|
+
published tarball, not against a paraphrase of it). The peer range here is unchanged at `>=0.2.3`,
|
|
46
|
+
so this degrades rather than breaks: an older SDK, `0.2.4` included, sets no `dataParts`, the kit
|
|
47
|
+
reads no plan, and the host lands on exactly the path a tenant that sends none already takes.
|
|
48
|
+
|
|
49
|
+
- **`OnboardingResult.variant`, the experiment arm the backend assigned, surfaced to the host.**
|
|
50
|
+
The server rides the arm key on the render envelope at `props.progress.variant`, a sibling of
|
|
51
|
+
`step` / `total` / `key` / `slot_id`. The kit had no way to hand it over, so a host that wanted to
|
|
52
|
+
branch on the arm had to INFER it from the shape of the flow (counting answers against a
|
|
53
|
+
hard-coded maximum), an inference that goes silently wrong the day the server changes a flow
|
|
54
|
+
length.
|
|
55
|
+
|
|
56
|
+
`readProgress` whitelists `variant` exactly the way it already whitelists `slot_id`: a non-string
|
|
57
|
+
or absent key reads as "no experiment", never as an error. `OnboardingFlow` latches the arm at
|
|
58
|
+
first sight into a ref that is never cleared, because the assignment is sticky per session but
|
|
59
|
+
only rides the render envelope, and a later card that omits it must not un-assign it.
|
|
60
|
+
|
|
61
|
+
It is also available DURING the flow: the `turn` event carries `variant` from the first card that
|
|
62
|
+
declares one onwards, reusing an event hosts already subscribe to instead of adding a prop for a
|
|
63
|
+
scalar. What an arm key MEANS is the host's decision; the kit does not map it to a name, brand it,
|
|
64
|
+
default it or log it. **It is deliberately never attached to an analytics event either**, on
|
|
65
|
+
either surface, so a host that wants arm-segmented funnels has to put the arm on its own events.
|
|
66
|
+
|
|
67
|
+
### Unchanged
|
|
68
|
+
|
|
69
|
+
- **Both keys are byte-identical no-ops when the backend sends nothing.** `plan` and `variant` are
|
|
70
|
+
each set on the result ONLY when one was actually seen, so a run without them leaves
|
|
71
|
+
`Object.keys(result)` as `["answers", "raw"]` and `"plan" in result` / `"variant" in result`
|
|
72
|
+
false. Setting a key to `undefined` would pass an `=== undefined` check while breaking every host
|
|
73
|
+
deep-equality assertion, so the canaries assert the KEY SET, not the value. The same rule governs
|
|
74
|
+
the `turn` event.
|
|
75
|
+
- **Neither read can throw.** Both sit on the single code path to `onComplete`, where a throw would
|
|
76
|
+
cost the user the completion of an onboarding they already finished. Every read is runtime-guarded
|
|
77
|
+
and `readPlan` declares its own structural type rather than casting: an `as` cast silences the
|
|
78
|
+
compiler in both directions, including the day the published SDK type disagrees.
|
|
79
|
+
- No new runtime dependency, no export renamed or removed, no change to the exports map.
|
|
80
|
+
|
|
6
81
|
## [0.13.5] - 2026-08-03
|
|
7
82
|
|
|
8
83
|
Two halves of one idea: stop finding out about a broken events integration from a funnel report.
|
|
@@ -866,7 +941,11 @@ true, and pins the wire with tests.
|
|
|
866
941
|
- Version reset to `0.1.0` to mark the start of the new package line. The GitHub repository
|
|
867
942
|
stays `chohra-med/wireai-onboarding`.
|
|
868
943
|
|
|
869
|
-
## [
|
|
944
|
+
## [0.9.0] — 2026-07-17
|
|
945
|
+
|
|
946
|
+
*This section carried the title `[Unreleased]` until 2026-08-09, long after it shipped. Everything
|
|
947
|
+
below went out in 0.9.0; the three analytics/device items it also held belong to 0.8.0 and have been
|
|
948
|
+
moved to their own section under this one.*
|
|
870
949
|
|
|
871
950
|
### Added: `fetchReviewDecision` — the kit now owns the review firing decision (live user harm)
|
|
872
951
|
|
|
@@ -1025,6 +1104,11 @@ All four from Malik's on-device test, 2026-07-16. The **review** gate's chrome i
|
|
|
1025
1104
|
button. The 5-star → native store review route (`routeRating`) is untouched.
|
|
1026
1105
|
- `theme/mergeThemeOver` extracts the helper both gates had copy-pasted.
|
|
1027
1106
|
|
|
1107
|
+
## [0.8.0] — 2026-07-15
|
|
1108
|
+
|
|
1109
|
+
*Also mis-filed under `[Unreleased]` until 2026-08-09. These three items shipped in 0.8.0, one
|
|
1110
|
+
release before everything in the section above.*
|
|
1111
|
+
|
|
1028
1112
|
### Added: "device" is now fully automatic — auto-minted, persisted per-install `device_key`
|
|
1029
1113
|
|
|
1030
1114
|
- The analytics façade (`createAnalytics`) now auto-mints a stable, NON-PII per-install `device_key`
|
|
@@ -1058,7 +1142,7 @@ All four from Malik's on-device test, 2026-07-16. The **review** gate's chrome i
|
|
|
1058
1142
|
- Backward compatible: no existing export renamed or removed; zero new dependencies. The one
|
|
1059
1143
|
behavior change is intentional — events now carry an auto `device_key` when the host omits one.
|
|
1060
1144
|
|
|
1061
|
-
## [0.7.0] —
|
|
1145
|
+
## [0.7.0] — 2026-07-15
|
|
1062
1146
|
|
|
1063
1147
|
### Added: `WireUserContext` — one rich user-context object → every event's `user_context`
|
|
1064
1148
|
|
|
@@ -1439,7 +1523,7 @@ All four from Malik's on-device test, 2026-07-16. The **review** gate's chrome i
|
|
|
1439
1523
|
`showcaseColorsFromTheme(theme, accent)` (new `src/showcase/showcaseColors.ts`) with a
|
|
1440
1524
|
regression test asserting the primary button is the accent and never the background.
|
|
1441
1525
|
|
|
1442
|
-
## [0.3.0] —
|
|
1526
|
+
## [0.3.0] — 2026-07-12
|
|
1443
1527
|
|
|
1444
1528
|
> Pending release. `0.2.1` is already published on npm (coachmarks + showcase, no
|
|
1445
1529
|
> identity API), so this identity surface — alongside the unpublished `/reviews`
|
package/README.md
CHANGED
|
@@ -231,7 +231,7 @@ import { WireOnboarding } from "@wireai/activation";
|
|
|
231
231
|
| Prop | Type | Notes |
|
|
232
232
|
|---|---|---|
|
|
233
233
|
| `config` | `{ apiKey, serverUrl, appId, metadata?, appVersion? }` | A2A transport; the key resolves the tenant server-side. `appVersion` is host-injected (e.g. `Constants.expoConfig?.version`) and forwarded for analytics segmentation. **Required.** |
|
|
234
|
-
| `onComplete` | `(result:
|
|
234
|
+
| `onComplete` | `(result: OnboardingResult) => void` | Fires when the user taps the terminal recap's CTA. `result` always carries `answers` and `raw`. Since 0.13.6 it may also carry `plan` (the backend's onboarding plan, AI path only) and `variant` (the experiment arm the backend assigned, when the tenant runs one). Each of those two keys is set ONLY when the backend actually sent one, so a run without them returns exactly the object earlier versions returned: `"plan" in result` and `"variant" in result` both stay false. The kit does not interpret either: **validate `plan` before you apply it.** **Required.** |
|
|
235
235
|
| `theme` | `Partial<OnboardingTheme>` | Brand colors/fonts/radius/spacing, deep-merged over a neutral default. |
|
|
236
236
|
| `illustrations` | `Record<string, ReactNode>` | App artwork for `InterstitialCard`, keyed by name. |
|
|
237
237
|
| `icons` | `Record<string, ReactNode>` | Your own icon nodes, keyed by the semantic name the AI emits (`{ instagram: <BrandIg/> }`). Checked first, so use it to put your brand mark on a choice card, to add names the vocabulary does not carry, or to get icons at all without installing `@expo/vector-icons`. Anything you leave out falls back to that optional peer, then to no icon. Never a crash. See [Icons](#icons). |
|
|
@@ -241,7 +241,7 @@ import { WireOnboarding } from "@wireai/activation";
|
|
|
241
241
|
| `onError` | `(err) => void` | Backend error or first-card timeout, fired **after retries are exhausted**, not on the first failure. When `fallbackFlow` is not supplied, the host owns recovery (e.g. route to a static flow). With neither, the kit shows an inline retry. `fallbackFlow` takes precedence over this. |
|
|
242
242
|
| `fallbackFlow` | `ReactNode` | Your predefined STATIC onboarding, rendered in place once the AI flow fails and retries are exhausted. **Takes precedence over `onError`.** This is the "it can never break your onboarding" guarantee: pass the same flow you shipped before adding Wire AI and the user always keeps moving. |
|
|
243
243
|
| `maxRetries` | `number` | Consecutive failures to auto-retry before degrading to `fallbackFlow`/`onError`. Default `1` (one silent retry, then degrade). `0` degrades on the first failure. Budget it deliberately: each retry restarts the flow, so with `startTimeoutMs` at its `15000` default the default `maxRetries` puts 30s of loader in front of a user before they see the fallback. A retry also sends a skip sentinel, so the user loses one question and a retry is never recorded as their first answer. |
|
|
244
|
-
| `onEvent` | `(e: OnboardingEvent) => void` | `started` / `turn` / `error`
|
|
244
|
+
| `onEvent` | `(e: OnboardingEvent) => void` | `started` / `resumed` / `turn` / `error` / `retry` / `fallback` / `permission`, the full union in `OnboardingEvent`. Recover per-turn analytics since the kit owns the loop. See the note under the helpers table. |
|
|
245
245
|
| `copy` | `Partial<OnboardingCopy>` | Localize the kit's built-in English loader/completion strings. |
|
|
246
246
|
| `approxScreens` | `number` | Approx total screens — paces the bar as `step/total` (capped, never shown). A backend `progress.total` (the screen budget, sent every turn incl. init) wins, so usually unnecessary. |
|
|
247
247
|
| `components` | `WireAIComponent[]` | Override the registered cards (defaults to `onboardingComponents`). |
|
|
@@ -271,7 +271,7 @@ You rarely hand-roll config, gating, analytics, or attribution — the kit ships
|
|
|
271
271
|
| `themeFromBrand({ primary })` · `defaultIllustrations` | One-color theme; dependency-free fallback artwork. |
|
|
272
272
|
| `motionSpec` | The motion constants behind every kit animation (durations, springs, the design ease). Read-only for hosts. `setMotionDurationScale` / `getMotionDurationScale` are QA tools for the playground's animation-speed knob: never call them in production code. |
|
|
273
273
|
|
|
274
|
-
> **`onEvent`** fires `started` / `resumed` / `turn` / `error` / `retry` / `fallback` (the kit owns the loop, so this is how you recover per-turn analytics). `resumed` fires INSTEAD of `started` when a persisted session was restored (see the `storage` prop) — don't count both as flow starts. Completion is signalled via `onComplete`, not `onEvent` — log `WIRE_ONBOARDING_EVENTS.completed` there. `started` and `resumed` also carry a `contextId` (the A2A session id): capture it if you might bind a `userId` after the flow finishes (see [User identity](#user-identity)).
|
|
274
|
+
> **`onEvent`** fires `started` / `resumed` / `turn` / `error` / `retry` / `fallback` / `permission` (the kit owns the loop, so this is how you recover per-turn analytics). `resumed` fires INSTEAD of `started` when a persisted session was restored (see the `storage` prop) — don't count both as flow starts. Since 0.13.6 the `turn` event also carries `variant`, the experiment arm the backend assigned, from the first card that declares one onwards; that is how you read the arm DURING the flow rather than waiting for `onComplete`. The key is absent when no experiment is running, and the kit never attaches the arm to an analytics event, so arm-segmented funnels are the host's job. Completion is signalled via `onComplete`, not `onEvent` — log `WIRE_ONBOARDING_EVENTS.completed` there. `started` and `resumed` also carry a `contextId` (the A2A session id): capture it if you might bind a `userId` after the flow finishes (see [User identity](#user-identity)).
|
|
275
275
|
|
|
276
276
|
**Integrating with an AI agent?** See [`INTEGRATION_PROMPT.md`](./INTEGRATION_PROMPT.md) (copy-paste prompt for Claude Code) and [`llms.txt`](./llms.txt). Fastest of all: the `wire-rn-integration` Claude skill.
|
|
277
277
|
|
|
@@ -1310,49 +1310,47 @@ then *improve* Wire AI, not just eyeball it.
|
|
|
1310
1310
|
|
|
1311
1311
|
### MCP server (`mcp/`)
|
|
1312
1312
|
|
|
1313
|
-
A
|
|
1314
|
-
|
|
1315
|
-
allowlist). Build it in place:
|
|
1313
|
+
A Model Context Protocol server (`@wireai/mcp`, TypeScript) that exposes the whole
|
|
1314
|
+
onboarding control plane as agent tools. It runs two ways, same tools either way:
|
|
1316
1315
|
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1316
|
+
1. **Hosted, and this is the default.** `https://wireai-mcp.fly.dev/mcp` over Streamable
|
|
1317
|
+
HTTP. You authenticate per request with an `Authorization: Bearer` header, so there is
|
|
1318
|
+
no build step, no login step, and nothing on disk.
|
|
1319
|
+
2. **Local stdio.** `cd mcp && npm install && npm run build`, then point your client at
|
|
1320
|
+
`mcp/dist/index.js`. Auth is a one-time `node dist/index.js login`, or raw keys via
|
|
1321
|
+
`WIREAI_SERVER_URL` / `WIREAI_API_KEY` / `WIREAI_ADMIN_KEY`. This package is repo-local
|
|
1322
|
+
and **not** published to npm (it is excluded from the kit's `files` allowlist).
|
|
1322
1323
|
|
|
1323
1324
|
```json
|
|
1324
1325
|
{
|
|
1325
1326
|
"mcpServers": {
|
|
1326
1327
|
"wireai": {
|
|
1327
|
-
"
|
|
1328
|
-
"
|
|
1329
|
-
"
|
|
1330
|
-
"WIREAI_SERVER_URL": "https://<your-backend>.fly.dev",
|
|
1331
|
-
"WIREAI_API_KEY": "wai_<tenant-key>",
|
|
1332
|
-
"WIREAI_ADMIN_KEY": "wai_admin_<operator-key>"
|
|
1333
|
-
}
|
|
1328
|
+
"type": "http",
|
|
1329
|
+
"url": "https://wireai-mcp.fly.dev/mcp",
|
|
1330
|
+
"headers": { "Authorization": "Bearer <your-token>" }
|
|
1334
1331
|
}
|
|
1335
1332
|
}
|
|
1336
1333
|
}
|
|
1337
1334
|
```
|
|
1338
1335
|
|
|
1339
|
-
|
|
1336
|
+
**Three credential classes, and you probably want the third.** A tenant `wai_` key reads
|
|
1337
|
+
your own app's funnel and files learning reports. The operator admin key reaches the
|
|
1338
|
+
cross-tenant management surface. A **client console token** (minted from a Wire console
|
|
1339
|
+
session) drives your own apps over the `/v1/me/*` console routes, which means a customer
|
|
1340
|
+
runs the full management surface from an agent *without* holding the platform admin key.
|
|
1340
1341
|
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
Least privilege: for the read-only loop, hand the agent just `WIREAI_SERVER_URL` +
|
|
1355
|
-
`WIREAI_API_KEY` (tenant) and skip the admin key. Full detail: [`mcp/README.md`](./mcp/README.md).
|
|
1342
|
+
**Where the tool list lives.** Ask the server: a connected client's `tools/list` is the
|
|
1343
|
+
only copy that is current by construction, and it is already scoped to the credential you
|
|
1344
|
+
presented. `wireai_get_integration_guide` needs no auth at all and returns the recipe.
|
|
1345
|
+
Inside the repo the written table is `mcp/README.md`, and `mcp/src/toolAccess.test.ts`
|
|
1346
|
+
re-derives it from the handlers and goes red when the two disagree.
|
|
1347
|
+
|
|
1348
|
+
This section deliberately does not restate that table. It used to, and the copy drifted to
|
|
1349
|
+
10 tools of 21 with a "the only writes are register/update" line the code had stopped
|
|
1350
|
+
honouring, because nothing gated it. A duplicated list with no test on it goes stale.
|
|
1351
|
+
|
|
1352
|
+
Least privilege still applies: for the read-only improve loop, hand the agent a tenant
|
|
1353
|
+
credential and skip the admin key entirely.
|
|
1356
1354
|
|
|
1357
1355
|
### `wire-ai` skill (`.claude/skills/wire-ai`)
|
|
1358
1356
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { R as ReportAppEventOptions, r as reportAppEvent } from '../transport-j5gFfJhK.mjs';
|
|
2
|
-
import { C as ClientEventTarget, W as WireUserContext, E as EventQueueOptions } from '../currentSession-
|
|
3
|
-
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, c as ClientEvent, d as ClientEventType, e as ContextEnvelope, f as ContextEnvelopeInput, D as DeviceKeyStorage, g as EnvelopeSource, h as EventQueue, R as ResolveAutoDeviceKeyOptions, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, k as analyticsUserIdStorageKey, l as buildContextEnvelope, m as clearPiiFromContext, n as clearUserContext, o as createEventQueue, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, s as looksLikeEmail, t as makeSessionId, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, B as resetEventQueueKeys, F as resolveAutoDeviceKey, G as setCurrentSessionId, H as toAnalyticsEvent } from '../currentSession-
|
|
2
|
+
import { C as ClientEventTarget, W as WireUserContext, E as EventQueueOptions } from '../currentSession-DngW-QoD.mjs';
|
|
3
|
+
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, c as ClientEvent, d as ClientEventType, e as ContextEnvelope, f as ContextEnvelopeInput, D as DeviceKeyStorage, g as EnvelopeSource, h as EventQueue, R as ResolveAutoDeviceKeyOptions, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, k as analyticsUserIdStorageKey, l as buildContextEnvelope, m as clearPiiFromContext, n as clearUserContext, o as createEventQueue, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, s as looksLikeEmail, t as makeSessionId, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, B as resetEventQueueKeys, F as resolveAutoDeviceKey, G as setCurrentSessionId, H as toAnalyticsEvent } from '../currentSession-DngW-QoD.mjs';
|
|
4
4
|
import { W as WireOnboardingStorage } from '../types-BpwiRpA8.mjs';
|
|
5
5
|
import '../types-Cju-1_jT.mjs';
|
|
6
6
|
import '../types-BKfpdZzX.mjs';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { R as ReportAppEventOptions, r as reportAppEvent } from '../transport-B_0SgCBe.js';
|
|
2
|
-
import { C as ClientEventTarget, W as WireUserContext, E as EventQueueOptions } from '../currentSession-
|
|
3
|
-
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, c as ClientEvent, d as ClientEventType, e as ContextEnvelope, f as ContextEnvelopeInput, D as DeviceKeyStorage, g as EnvelopeSource, h as EventQueue, R as ResolveAutoDeviceKeyOptions, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, k as analyticsUserIdStorageKey, l as buildContextEnvelope, m as clearPiiFromContext, n as clearUserContext, o as createEventQueue, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, s as looksLikeEmail, t as makeSessionId, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, B as resetEventQueueKeys, F as resolveAutoDeviceKey, G as setCurrentSessionId, H as toAnalyticsEvent } from '../currentSession-
|
|
2
|
+
import { C as ClientEventTarget, W as WireUserContext, E as EventQueueOptions } from '../currentSession-C5976akx.js';
|
|
3
|
+
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, c as ClientEvent, d as ClientEventType, e as ContextEnvelope, f as ContextEnvelopeInput, D as DeviceKeyStorage, g as EnvelopeSource, h as EventQueue, R as ResolveAutoDeviceKeyOptions, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, k as analyticsUserIdStorageKey, l as buildContextEnvelope, m as clearPiiFromContext, n as clearUserContext, o as createEventQueue, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, s as looksLikeEmail, t as makeSessionId, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, B as resetEventQueueKeys, F as resolveAutoDeviceKey, G as setCurrentSessionId, H as toAnalyticsEvent } from '../currentSession-C5976akx.js';
|
|
4
4
|
import { W as WireOnboardingStorage } from '../types-BpwiRpA8.js';
|
|
5
5
|
import '../types-h2BZvl1t.js';
|
|
6
6
|
import '../types-BKfpdZzX.js';
|
|
@@ -484,6 +484,16 @@ type OnboardingResult = {
|
|
|
484
484
|
* the host's decision, not the kit's.
|
|
485
485
|
*/
|
|
486
486
|
plan?: unknown;
|
|
487
|
+
/**
|
|
488
|
+
* The experiment ARM the backend assigned this session, when it is running one. Absent when
|
|
489
|
+
* the tenant runs no experiment, which is the common case, and absent is NOT an error.
|
|
490
|
+
* The kit does NOT interpret it, does not log it, does not brand it and never attaches it
|
|
491
|
+
* to an analytics event. What an arm key MEANS is the host's decision.
|
|
492
|
+
*
|
|
493
|
+
* Like {@link plan}, the KEY is set only when an arm was actually seen, so a run with no
|
|
494
|
+
* experiment leaves the result byte-identical to what every host already reads.
|
|
495
|
+
*/
|
|
496
|
+
variant?: string;
|
|
487
497
|
};
|
|
488
498
|
/**
|
|
489
499
|
* Lifecycle events emitted as the flow runs, for host-side analytics. The kit owns
|
|
@@ -495,7 +505,11 @@ type OnboardingResult = {
|
|
|
495
505
|
* - `resumed`: a persisted session was restored after an app kill (fires INSTEAD of
|
|
496
506
|
* `started`, so host funnels don't double-count the same session). Also carries
|
|
497
507
|
* `contextId`. Requires the `storage` prop.
|
|
498
|
-
* - `turn`: a new assistant card arrived (`step` = 1-based index of cards seen).
|
|
508
|
+
* - `turn`: a new assistant card arrived (`step` = 1-based index of cards seen). Carries
|
|
509
|
+
* `variant`, the backend's experiment arm for this session, from the first card that
|
|
510
|
+
* declared one onwards — this is how the arm is available DURING the flow rather than
|
|
511
|
+
* only at completion. The key is absent whenever no arm has been seen, which is every
|
|
512
|
+
* turn of every tenant running no experiment.
|
|
499
513
|
* - `error`: the backend errored or the first-card watchdog timed out.
|
|
500
514
|
* - `retry`: a transient failure is being auto-retried (`attempt` = 1-based).
|
|
501
515
|
* - `fallback`: retries are exhausted; the kit degraded to the static `fallbackFlow`
|
|
@@ -516,6 +530,7 @@ type OnboardingEvent = {
|
|
|
516
530
|
type: "turn";
|
|
517
531
|
step: number;
|
|
518
532
|
component?: string;
|
|
533
|
+
variant?: string;
|
|
519
534
|
} | {
|
|
520
535
|
type: "error";
|
|
521
536
|
reason: "backend" | "timeout";
|
|
@@ -790,6 +805,17 @@ type OnboardingProgress = {
|
|
|
790
805
|
slot_id?: string;
|
|
791
806
|
/** Whether the CURRENT screen may be skipped (backend-marked; default false → no Skip shown). */
|
|
792
807
|
skippable?: boolean;
|
|
808
|
+
/**
|
|
809
|
+
* The EXPERIMENT ARM the backend assigned this session, when the tenant is running one. Rides the
|
|
810
|
+
* render envelope as a sibling of {@link step}/{@link total}/{@link key}/{@link slot_id}, and is
|
|
811
|
+
* OMITTED entirely for a tenant running no experiment — which is the common case, and is not an
|
|
812
|
+
* error. The assignment is sticky for the session, so a later card that omits it does not
|
|
813
|
+
* un-assign it.
|
|
814
|
+
*
|
|
815
|
+
* The kit does NOT interpret this. It is whitelisted, latched and handed to the host exactly as
|
|
816
|
+
* received; what an arm key MEANS is the host's decision. See {@link OnboardingResult.variant}.
|
|
817
|
+
*/
|
|
818
|
+
variant?: string;
|
|
793
819
|
};
|
|
794
820
|
|
|
795
821
|
/**
|
|
@@ -484,6 +484,16 @@ type OnboardingResult = {
|
|
|
484
484
|
* the host's decision, not the kit's.
|
|
485
485
|
*/
|
|
486
486
|
plan?: unknown;
|
|
487
|
+
/**
|
|
488
|
+
* The experiment ARM the backend assigned this session, when it is running one. Absent when
|
|
489
|
+
* the tenant runs no experiment, which is the common case, and absent is NOT an error.
|
|
490
|
+
* The kit does NOT interpret it, does not log it, does not brand it and never attaches it
|
|
491
|
+
* to an analytics event. What an arm key MEANS is the host's decision.
|
|
492
|
+
*
|
|
493
|
+
* Like {@link plan}, the KEY is set only when an arm was actually seen, so a run with no
|
|
494
|
+
* experiment leaves the result byte-identical to what every host already reads.
|
|
495
|
+
*/
|
|
496
|
+
variant?: string;
|
|
487
497
|
};
|
|
488
498
|
/**
|
|
489
499
|
* Lifecycle events emitted as the flow runs, for host-side analytics. The kit owns
|
|
@@ -495,7 +505,11 @@ type OnboardingResult = {
|
|
|
495
505
|
* - `resumed`: a persisted session was restored after an app kill (fires INSTEAD of
|
|
496
506
|
* `started`, so host funnels don't double-count the same session). Also carries
|
|
497
507
|
* `contextId`. Requires the `storage` prop.
|
|
498
|
-
* - `turn`: a new assistant card arrived (`step` = 1-based index of cards seen).
|
|
508
|
+
* - `turn`: a new assistant card arrived (`step` = 1-based index of cards seen). Carries
|
|
509
|
+
* `variant`, the backend's experiment arm for this session, from the first card that
|
|
510
|
+
* declared one onwards — this is how the arm is available DURING the flow rather than
|
|
511
|
+
* only at completion. The key is absent whenever no arm has been seen, which is every
|
|
512
|
+
* turn of every tenant running no experiment.
|
|
499
513
|
* - `error`: the backend errored or the first-card watchdog timed out.
|
|
500
514
|
* - `retry`: a transient failure is being auto-retried (`attempt` = 1-based).
|
|
501
515
|
* - `fallback`: retries are exhausted; the kit degraded to the static `fallbackFlow`
|
|
@@ -516,6 +530,7 @@ type OnboardingEvent = {
|
|
|
516
530
|
type: "turn";
|
|
517
531
|
step: number;
|
|
518
532
|
component?: string;
|
|
533
|
+
variant?: string;
|
|
519
534
|
} | {
|
|
520
535
|
type: "error";
|
|
521
536
|
reason: "backend" | "timeout";
|
|
@@ -790,6 +805,17 @@ type OnboardingProgress = {
|
|
|
790
805
|
slot_id?: string;
|
|
791
806
|
/** Whether the CURRENT screen may be skipped (backend-marked; default false → no Skip shown). */
|
|
792
807
|
skippable?: boolean;
|
|
808
|
+
/**
|
|
809
|
+
* The EXPERIMENT ARM the backend assigned this session, when the tenant is running one. Rides the
|
|
810
|
+
* render envelope as a sibling of {@link step}/{@link total}/{@link key}/{@link slot_id}, and is
|
|
811
|
+
* OMITTED entirely for a tenant running no experiment — which is the common case, and is not an
|
|
812
|
+
* error. The assignment is sticky for the session, so a later card that omits it does not
|
|
813
|
+
* un-assign it.
|
|
814
|
+
*
|
|
815
|
+
* The kit does NOT interpret this. It is whitelisted, latched and handed to the host exactly as
|
|
816
|
+
* received; what an arm key MEANS is the host's decision. See {@link OnboardingResult.variant}.
|
|
817
|
+
*/
|
|
818
|
+
variant?: string;
|
|
793
819
|
};
|
|
794
820
|
|
|
795
821
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
|
-
import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, U as PermissionPlacement, c as ClientEvent, g as EnvelopeSource } from './currentSession-
|
|
4
|
-
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-
|
|
3
|
+
import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, U as PermissionPlacement, c as ClientEvent, g as EnvelopeSource } from './currentSession-DngW-QoD.mjs';
|
|
4
|
+
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-DngW-QoD.mjs';
|
|
5
5
|
import { O as OnboardingTheme } from './types-BKfpdZzX.mjs';
|
|
6
6
|
export { a as OnboardingButtonStyle, b as OnboardingColors, c as OnboardingFonts, d as OnboardingRadius, e as OnboardingSpacing } from './types-BKfpdZzX.mjs';
|
|
7
7
|
export { C as CenteredModal, a as CenteredModalHandle, b as CenteredModalProps } from './CenteredModal-C3qQBHsA.mjs';
|
|
@@ -1286,6 +1286,8 @@ type PartialProgress = {
|
|
|
1286
1286
|
/** The stable per-slot identity, when the backend sends one. See `OnboardingProgress.slot_id`. */
|
|
1287
1287
|
slot_id?: string;
|
|
1288
1288
|
skippable?: boolean;
|
|
1289
|
+
/** The experiment arm assigned to this session, when the tenant runs one. See `OnboardingProgress.variant`. */
|
|
1290
|
+
variant?: string;
|
|
1289
1291
|
};
|
|
1290
1292
|
declare const readProgress: (response?: WireAIResponse) => PartialProgress;
|
|
1291
1293
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
|
-
import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, U as PermissionPlacement, c as ClientEvent, g as EnvelopeSource } from './currentSession-
|
|
4
|
-
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-
|
|
3
|
+
import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, U as PermissionPlacement, c as ClientEvent, g as EnvelopeSource } from './currentSession-C5976akx.js';
|
|
4
|
+
export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-C5976akx.js';
|
|
5
5
|
import { O as OnboardingTheme } from './types-BKfpdZzX.js';
|
|
6
6
|
export { a as OnboardingButtonStyle, b as OnboardingColors, c as OnboardingFonts, d as OnboardingRadius, e as OnboardingSpacing } from './types-BKfpdZzX.js';
|
|
7
7
|
export { C as CenteredModal, a as CenteredModalHandle, b as CenteredModalProps } from './CenteredModal-Cdgns6--.js';
|
|
@@ -1286,6 +1286,8 @@ type PartialProgress = {
|
|
|
1286
1286
|
/** The stable per-slot identity, when the backend sends one. See `OnboardingProgress.slot_id`. */
|
|
1287
1287
|
slot_id?: string;
|
|
1288
1288
|
skippable?: boolean;
|
|
1289
|
+
/** The experiment arm assigned to this session, when the tenant runs one. See `OnboardingProgress.variant`. */
|
|
1290
|
+
variant?: string;
|
|
1289
1291
|
};
|
|
1290
1292
|
declare const readProgress: (response?: WireAIResponse) => PartialProgress;
|
|
1291
1293
|
|
package/dist/index.js
CHANGED
|
@@ -1161,7 +1161,10 @@ var readProgress = (response) => {
|
|
|
1161
1161
|
key: typeof p.key === "string" ? p.key : void 0,
|
|
1162
1162
|
// Whitelisted the same way as every other field: an old backend simply omits it.
|
|
1163
1163
|
slot_id: typeof p.slot_id === "string" ? p.slot_id : void 0,
|
|
1164
|
-
skippable: typeof p.skippable === "boolean" ? p.skippable : void 0
|
|
1164
|
+
skippable: typeof p.skippable === "boolean" ? p.skippable : void 0,
|
|
1165
|
+
// Whitelisted like the rest: a non-string (or absent) arm key reads as "no experiment", never
|
|
1166
|
+
// as an error. The kit does not interpret the value — see `OnboardingProgress.variant`.
|
|
1167
|
+
variant: typeof p.variant === "string" ? p.variant : void 0
|
|
1165
1168
|
};
|
|
1166
1169
|
};
|
|
1167
1170
|
|
|
@@ -1703,6 +1706,7 @@ var OnboardingFlow = ({
|
|
|
1703
1706
|
const clientContextRef = React19.useRef(clientContext);
|
|
1704
1707
|
clientContextRef.current = clientContext;
|
|
1705
1708
|
const lastScreenIndexRef = React19.useRef(-1);
|
|
1709
|
+
const variantRef = React19.useRef(void 0);
|
|
1706
1710
|
const previewTimer = React19.useRef(null);
|
|
1707
1711
|
const [runId, setRunId] = React19.useState(0);
|
|
1708
1712
|
const startedRunRef = React19.useRef(-1);
|
|
@@ -1752,14 +1756,17 @@ var OnboardingFlow = ({
|
|
|
1752
1756
|
React19.useEffect(() => {
|
|
1753
1757
|
var _a2, _b2, _c2, _d2;
|
|
1754
1758
|
setValidationError(void 0);
|
|
1759
|
+
if (variantRef.current === void 0 && progress.variant) variantRef.current = progress.variant;
|
|
1755
1760
|
if (!(lastCard == null ? void 0 : lastCard.id)) return;
|
|
1756
1761
|
const step2 = (_a2 = progress.step) != null ? _a2 : renderedCount;
|
|
1757
1762
|
lastScreenIndexRef.current = Math.max(0, step2 - 1);
|
|
1758
|
-
|
|
1763
|
+
const turn = {
|
|
1759
1764
|
type: "turn",
|
|
1760
1765
|
step: step2,
|
|
1761
1766
|
component: (_b2 = lastCard.response) == null ? void 0 : _b2.component
|
|
1762
|
-
}
|
|
1767
|
+
};
|
|
1768
|
+
if (variantRef.current !== void 0) turn.variant = variantRef.current;
|
|
1769
|
+
(_c2 = onEventRef.current) == null ? void 0 : _c2.call(onEventRef, turn);
|
|
1763
1770
|
if (((_d2 = lastCard.response) == null ? void 0 : _d2.component) === "InterstitialCard") {
|
|
1764
1771
|
sendPreview(reportTargetRef.current, {
|
|
1765
1772
|
sessionId: sessionIdRef.current,
|
|
@@ -1820,6 +1827,7 @@ var OnboardingFlow = ({
|
|
|
1820
1827
|
const result = { answers: deriveAnswers(messages), raw: messages };
|
|
1821
1828
|
const plan = readPlan(messages);
|
|
1822
1829
|
if (plan !== void 0) result.plan = plan;
|
|
1830
|
+
if (variantRef.current !== void 0) result.variant = variantRef.current;
|
|
1823
1831
|
onCompleteRef.current(result);
|
|
1824
1832
|
}, [messages]);
|
|
1825
1833
|
const handleRetry = React19.useCallback(() => {
|