@tinkerlandai/longplay-sdk 0.10.15 → 0.10.16

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.
Files changed (55) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +13 -15
  3. package/README.zh-CN.md +14 -16
  4. package/dist/{ai-usage-C3dCagmQ.d.ts → ai-usage-DejUdb17.d.ts} +1 -1
  5. package/dist/{api-Cefn6AaL.d.ts → api-RQUBSSEJ.d.ts} +60 -26
  6. package/dist/{chunk-OZZMZH7X.js → chunk-26HU2HXU.js} +1 -1
  7. package/dist/chunk-4IGRIYOQ.js +1 -0
  8. package/dist/{chunk-V73OHOTK.js → chunk-55MXKW5J.js} +1 -1
  9. package/dist/{chunk-6RZKX552.js → chunk-67XTOBGE.js} +1 -1
  10. package/dist/{chunk-RT35MPPD.js → chunk-6MBVIE3H.js} +1 -1
  11. package/dist/chunk-AC32XJZW.js +1 -0
  12. package/dist/{chunk-VXY2C4AL.js → chunk-APO7QUBB.js} +1 -1
  13. package/dist/chunk-EEZLS2YP.js +1 -0
  14. package/dist/chunk-EFFXE6CX.js +6 -0
  15. package/dist/chunk-FKBSUKXE.js +1 -0
  16. package/dist/{chunk-TPAQWTO4.js → chunk-JKLILKI5.js} +1 -1
  17. package/dist/{chunk-VSMITXQD.js → chunk-LC2VUKYM.js} +1 -1
  18. package/dist/{chunk-LUIKKMG5.js → chunk-M5HQW67G.js} +1 -1
  19. package/dist/chunk-ML6EHT43.js +10 -0
  20. package/dist/chunk-PFHS7HK3.js +17 -0
  21. package/dist/chunk-T5COWMDA.js +1 -0
  22. package/dist/{configuration-sync-D2n_gGj6.d.ts → configuration-sync-C2jtm37f.d.ts} +97 -9
  23. package/dist/{content-WXHCWIUL.js → content-XCLXWNGN.js} +1 -1
  24. package/dist/{funnel-local-client-9U-_hkEE.d.ts → funnel-local-client-P_R6FHVV.d.ts} +7995 -5523
  25. package/dist/{funnel-node-evaluation-DSSSmXHX.d.ts → funnel-node-evaluation-BLnJp8vj.d.ts} +11 -13
  26. package/dist/{funnel-process-client-BaHMeArI.d.ts → funnel-process-client-CY-GQ_SF.d.ts} +5498 -4539
  27. package/dist/funnel-runtime-host-GFTN7KQK.js +1 -0
  28. package/dist/index.d.ts +1258 -273
  29. package/dist/index.js +1 -1
  30. package/dist/native-shell.js +1 -1
  31. package/dist/openrouter.d.ts +3 -3
  32. package/dist/openrouter.js +1 -1
  33. package/dist/page.d.ts +2 -2
  34. package/dist/page.js +1 -1
  35. package/dist/paywall-H3KQZEJG.js +1 -0
  36. package/dist/popup.d.ts +11 -5
  37. package/dist/popup.js +1 -1
  38. package/dist/react-native.d.ts +1541 -7
  39. package/dist/react-native.js +1 -1
  40. package/dist/{screen-D81zCpfi.d.ts → screen-DRP7nsrQ.d.ts} +613 -357
  41. package/dist/screen-renderer-IZ3VJGU6.js +1 -0
  42. package/dist/server.d.ts +717 -9
  43. package/dist/server.js +1 -1
  44. package/dist/visual.js +1 -1
  45. package/package.json +1 -1
  46. package/dist/chunk-33FQUT3Z.js +0 -179
  47. package/dist/chunk-E5ECPR6Z.js +0 -1
  48. package/dist/chunk-LHA6VWP7.js +0 -1
  49. package/dist/chunk-MOWYD2TV.js +0 -1
  50. package/dist/chunk-RQZ42NQJ.js +0 -6
  51. package/dist/chunk-VSJOHWDL.js +0 -17
  52. package/dist/chunk-XAHWOLRT.js +0 -1
  53. package/dist/funnel-runtime-host-WQ64FAME.js +0 -1
  54. package/dist/paywall-H4YN4FTL.js +0 -1
  55. package/dist/screen-renderer-NHJ6OQTF.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.16 — 2026-11-05
4
+
5
+ - Add bounded local display interactions, responsive presentation and brand fonts to the shared screen renderer, including billing controls and catalog-backed quantity sliders.
6
+ - Apply checkout availability consistently to native controls, static HTML and interactive HTML without rewriting authored content or dropping invalid capability data. Preserve live controls and local state across refreshes.
7
+ - Align structural and semantic screen validation across JavaScript, React Native, Swift, Kotlin, Python and Go. Wire protocol stays `0.10`; purchase authorization and runtime execution remain server-owned.
8
+
3
9
  ## 0.10.15 — 2026-11-04
4
10
 
5
11
  - No API or behavior change from 0.10.14. This is the first release published through a release candidate (`0.10.15-rc.1` on npm `next`) before the stable version. The README describes the `next` and `latest` channels. Wire protocol stays `0.10`.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  <p>
2
- <a href="https://longplayai.com">
3
- <img src="https://longplayai.com/brand/indiana-mark.png" alt="Longplay" width="72" height="72" />
2
+ <a href="https://www.longplayai.com">
3
+ <img src="https://www.longplayai.com/site/brand/indiana-mark.png" alt="Longplay" width="72" height="72" />
4
4
  </a>
5
5
  </p>
6
6
 
7
7
  # @tinkerlandai/longplay-sdk
8
8
 
9
- This source checkout is SDK 0.10.7, protocol 0.10. These examples use `https://api.longplayai.com` with a Sandbox App and credentials issued by the production deployment. Sandbox still contains production data; do not reuse credentials from the separate test deployment. Confirm runtime readiness in [environment state](../../docs/development-status.md) before running them.
9
+ This source checkout is SDK 0.10.14, protocol 0.10. These examples use `https://api.longplayai.com` with a Sandbox App and credentials issued by the production deployment. Sandbox still contains production data; do not reuse credentials from the separate test deployment. Confirm runtime readiness in [environment state](../../docs/development-status.md) before running them.
10
10
 
11
11
  [简体中文](./README.zh-CN.md)
12
12
 
@@ -18,9 +18,7 @@ The Longplay business SDK groups its capabilities as **Identity, Commerce, exper
18
18
  npm install --save-exact @tinkerlandai/longplay-sdk@latest
19
19
  ```
20
20
 
21
- The first install resolves latest and saves an exact package.json version. Commit the lockfile and use npm ci for later builds. Use the original package identity and exact version from the [release records](../../docs/sdk-releases.md) for historical installations and rollback. New Longplay package names require their own publication; source changes do not publish artifacts.
22
-
23
- IAM Funnel entries and their initial reliability fixes require SDK 0.10.5 or later. Select this release explicitly with `npm install --save-exact @tinkerlandai/longplay-sdk@0.10.5`; current mutable tags are recorded in the [release records](../../docs/sdk-releases.md).
21
+ The first install resolves latest and saves an exact package.json version. Commit the lockfile and use npm ci for later builds. [SDK distribution](../../docs/sdk-releases.md) records package availability; source changes do not publish artifacts. Existing versioned artifacts remain immutable.
24
22
 
25
23
  This SDK requires HTTP protocol 0.10. The runtime must serve the same current protocol; publishing a package does not deploy the server. Publication and accepted environment scope are recorded in the [release ledger](../../docs/sdk-releases.md) and [development status](../../docs/development-status.md).
26
24
 
@@ -31,7 +29,7 @@ The data/session layer handles public JSON, integrity checks and authenticated o
31
29
  The classic-script entry reuses the npm browser implementation, with no bundler:
32
30
 
33
31
  ```sh
34
- SDK_MODULE_URL="$(curl -fsS https://longplayai.com/sdk/module)" &&
32
+ SDK_MODULE_URL="$(curl -fsS https://cdn.longplayai.com/sdk/module)" &&
35
33
  printf 'export * from "%s";\n' "$SDK_MODULE_URL" > longplay-sdk.js
36
34
  ```
37
35
 
@@ -57,7 +55,7 @@ printf 'export * from "%s";\n' "$SDK_MODULE_URL" > longplay-sdk.js
57
55
  </script>
58
56
  ```
59
57
 
60
- Commit the generated longplay-sdk.js to lock the immutable module URL; resolve it again only when upgrading. The optional classic loader at `https://longplayai.com/sdk.js` still follows Web releases and uses matching API/credentials. `Longplay.ready` provides every root browser export plus `createPageExperiments` and `createVisualExperiments`; replace npm imports below with destructuring those names. Loading activates no sessions, events or experiments. Server Keys remain on your backend; Funnel start/recovery and logout cleanup retain the existing contracts. Duplicate tags share readiness, failures reject the Promise and UI loads lazily. With `async`/`defer`, wait for the loader tag's load event before accessing `Longplay`. CSP must allow the script origin and API connections. Page experiments use the same script entry; explicitly create their clients and call `start()`. See [script distribution](../../docs/sdk-architecture.md#web-script-distribution) and [the complete integration example](https://longplayai.com/docs/javascript#script).
58
+ Commit the generated longplay-sdk.js to lock the immutable module URL; resolve it again only when upgrading. The optional classic loader at `https://cdn.longplayai.com/sdk.js` still follows Web releases and uses matching API/credentials. `Longplay.ready` provides every root browser export plus `createPageExperiments` and `createVisualExperiments`; replace npm imports below with destructuring those names. Loading activates no sessions, events or experiments. Server Keys remain on your backend; Funnel start/recovery and logout cleanup retain the existing contracts. Duplicate tags share readiness, failures reject the Promise and UI loads lazily. With `async`/`defer`, wait for the loader tag's load event before accessing `Longplay`. CSP must allow the script origin and API connections. Page experiments use the same script entry; explicitly create their clients and call `start()`. See [script distribution](../../docs/sdk-architecture.md#web-script-distribution) and [the complete integration example](https://www.longplayai.com/docs/sdk/javascript#script).
61
59
 
62
60
  ## React Native core
63
61
 
@@ -65,7 +63,7 @@ Use the independent `@tinkerlandai/longplay-react-native` package. The `@tinkerl
65
63
 
66
64
  ## Version compatibility and support
67
65
 
68
- During `0.x`, only the current protocol is supported. Starting with `1.0`, compatibility is preserved within each stable major version. Once the next stable major is published, the preceding stable major remains supported for at least 12 calendar months, with at least 180 days' public notice before retirement. The later deadline applies. See the [support policy](https://longplayai.com/docs/release-notes#support-policy).
66
+ During `0.x`, only the current protocol is supported. Starting with `1.0`, compatibility is preserved within each stable major version. Once the next stable major is published, the preceding stable major remains supported for at least 12 calendar months, with at least 180 days' public notice before retirement. The later deadline applies. See the [support policy](https://www.longplayai.com/docs/guides/version-support#support-policy).
69
67
 
70
68
  The SDK sends current protocol and SDK version headers and validates the protocol declared by successful responses. Old 0.x protocols are not converted into the current contract. Updating source code does not change an existing npm artifact or deploy a server.
71
69
 
@@ -86,7 +84,7 @@ The same package supports JavaScript and TypeScript and includes type declaratio
86
84
 
87
85
  For an independent **Page, Popup or Banner resource**, import `createLongplay` and `mountContent` from the root entry, resolve it with `longplay.resolveContent(...)`, then mount the result. `/page` runs GB URL redirect experiments on an existing merchant page; `/visual` applies GB visual changes to that page. `/popup` exposes lower-level screen rendering and preview primitives. Its name does not select or resolve a Popup resource. The public import paths stay unchanged; see [entry ownership](../../docs/sdk-architecture.md#public-entry-points-and-capability-ownership).
88
86
 
89
- The separate [Python server SDK](../python/README.md) provides synchronous and asynchronous Customer, holdings, entitlement-check and usage clients against the same current HTTP protocol. It is distributed from `https://longplayai.com/sdk/python` (not PyPI) and is not part of this npm package.
87
+ The separate [Python server SDK](../python/README.md) provides synchronous and asynchronous Customer, holdings, entitlement-check and usage clients against the same current HTTP protocol. It is distributed from `https://cdn.longplayai.com/sdk/python` (not PyPI) and is not part of this npm package.
90
88
 
91
89
  The [Go server SDK](../go/README.md) provides the same initial capabilities with typed responses, Context cancellation and goroutine-safe client reuse. It is installed with `go get longplayai.com/sdk/go` through the default Go module proxy and shares the release version with the other business SDKs.
92
90
 
@@ -211,7 +209,7 @@ await process.detach();
211
209
 
212
210
  Local execution needs the shared public configuration manager and a published configuration. Login binds the current Run to the account's existing Customer without replacing the Run, answers, history, pinned Version or deadlines. A new account can claim the Guest Customer in place. Another account cannot take over a bound Run; use a new process handle. Commercial assets and historical Customer ownership are preserved.
213
211
 
214
- Web IAM hosts opt in with `createIamFunnelProcessEntries`. React Native exports `createFunnelProcess`; Swift and Kotlin expose `LongplayFunnelProcess` and `LongplayFunnelProcessBridge` over the same merchant backend. Native hosts retain their command-storage adapter and presentation session across login. See the [identity contract](../../docs/funnel-customer-get-or-create.md#宿主接入) for storage, attribution and recovery details.
212
+ Web IAM hosts opt in with `createIamFunnelProcessEntries`. React Native exports `createFunnelProcess`; Swift and Kotlin expose `LongplayFunnelProcess` and `LongplayFunnelProcessBridge` over the same merchant backend. Native hosts retain their command-storage adapter and presentation session across login. See the [identity contract](../../docs/funnel-customer-get-or-create.md#sdk-and-merchant-adapter) for storage, attribution and recovery details.
215
213
 
216
214
  ### Bucketing identity across independent consumers
217
215
 
@@ -219,7 +217,7 @@ Funnel, standalone Features and page experiments evaluate independently. Matchin
219
217
 
220
218
  For Customer-based evaluation, `id` means the Longplay Customer UUID (`customer.id`); `externalUserId` means the merchant account ID (`customer.externalUserId`). Choose the experiment's `hashAttribute` explicitly when creating it and preserve that meaning in every consumer. Do not put the merchant account ID into `attributes.id`. Supply local attributes from your trusted backend's Customer data; `identify(customerToken)` authenticates requests but does not populate local bucketing attributes. These attributes are evaluation data, not authorization.
221
219
 
222
- `setAttributes()` replaces the complete object, so retain the bucketing fields on every update. Anonymous page/visual experiments instead default `id` and `deviceId` to the shared first-party device cookie; they do not automatically match an account-based experiment. An open visual client rereads its payload every 60 seconds while visible, so a stopped experiment or disabled delivery reverts without a page reload. Sticky capabilities differ by adapter: managed Local Run instructions receive server state, while pure local tools require their existing host persistence adapter for durable Sticky. No new shared state is introduced. See the [architecture boundary](../../docs/growthbook-sdk-delivery.md#跨消费方求值边界与分桶身份).
220
+ `setAttributes()` replaces the complete object, so retain the bucketing fields on every update. Anonymous page/visual experiments instead default `id` and `deviceId` to the shared first-party device cookie; they do not automatically match an account-based experiment. An open visual client rereads its payload every 60 seconds while visible, so a stopped experiment or disabled delivery reverts without a page reload. Sticky capabilities differ by adapter: managed Local Run instructions receive server state, while pure local tools require their existing host persistence adapter for durable Sticky. No new shared state is introduced. See the [architecture boundary](../../docs/growthbook-sdk-delivery.md#cross-consumer-evaluation-and-bucketing-identity).
223
221
 
224
222
  ### Server-side local Funnel evaluation
225
223
 
@@ -273,7 +271,7 @@ unsubscribe();
273
271
  flags.destroy();
274
272
  ```
275
273
 
276
- The selected environment's integration settings control behavior events, experiment exposures and Feature usage independently. New environments enable only exposure collection; existing environments retain all three. `flush()` includes a `skipped` count for intentionally disabled collection. The database rechecks every batch, including direct SDK/server and Funnel ingestion. Running experiment/Bandit dependencies prevent incompatible collection changes. These controls do not delete history or affect commercial usage accounting.
274
+ The selected environment's integration settings control behavior events, experiment exposures and Feature usage independently. New environments enable behavior events, experiment exposures and Feature usage collection. `flush()` includes a `skipped` count for intentionally disabled collection. The database rechecks every batch, including direct SDK/server and Funnel ingestion. Running experiment/Bandit dependencies prevent incompatible collection changes. These controls do not delete history or affect commercial usage accounting.
277
275
 
278
276
  Flags default to local evaluation; Owner/Admin can switch each flag to server evaluation. Server-evaluated flags deliver only keys and results, using the caller's fallback until the first result arrives. Attribute changes immediately discard old results. List hashes are not a secrecy boundary. Local Funnels cannot depend on server-evaluated flags; mode switches also check active historical Runs. `identify` / `reset` release the previous identity's Feature instances and event queue.
279
277
 
@@ -395,7 +393,7 @@ const host = await showFunnelRun(container, {
395
393
  });
396
394
  // Retain started.runToken in your host's secure credential storage.
397
395
  // Restore the same Run: await flow.restore(originalRunToken).
398
- host.destroy(); // Detach UI; accepted backend work remains owned by Indiana.
396
+ host.destroy(); // Detach UI; accepted backend work retains its server lifecycle.
399
397
  started.controller.reset();
400
398
  ```
401
399
 
@@ -531,4 +529,4 @@ In `record_only` mode your backend owns payment execution, verifies its results
531
529
 
532
530
  The Server entry exports `createMerchantBridgeHandler`, `createMerchantBridgeAuthorityResolver`, `signMerchantBridgeMessage` and `verifyMerchantBridgeMessage`. Supply backend signing keys, native authorization/CSRF, implemented capabilities/profiles and typed handlers. Set `resolveOperationAuthority: createMerchantBridgeAuthorityResolver(server)` so every financial/read command obtains fresh Longplay authority from the original operation API. A signed service request still requires confirmation and exact scope/Customer ownership; it cannot issue user sessions.
533
531
 
534
- Handlers must durably reserve the original operation before external effects and retain the same provider idempotency key. The SDK's preceding lookup is not a concurrency lock. `operation.read` returns `found` or `not_received` without creating effects. Recover `RESULT_UNKNOWN` through that original operation; never infer permission from a browser quote or `pending`. Console discovery is configuration validation, not commercial completion. See the [merchant specification](https://longplayai.com/docs/merchant-execution) for exact fields and recovery.
532
+ Handlers must durably reserve the original operation before external effects and retain the same provider idempotency key. The SDK's preceding lookup is not a concurrency lock. `operation.read` returns `found` or `not_received` without creating effects. Recover `RESULT_UNKNOWN` through that original operation; never infer permission from a browser quote or `pending`. Console discovery is configuration validation, not commercial completion. See the [merchant specification](https://www.longplayai.com/docs/guides/merchant-execution) for exact fields and recovery.
package/README.zh-CN.md CHANGED
@@ -1,12 +1,12 @@
1
1
  <p>
2
- <a href="https://longplayai.com">
3
- <img src="https://longplayai.com/brand/indiana-mark.png" alt="Longplay" width="72" height="72" />
2
+ <a href="https://www.longplayai.com">
3
+ <img src="https://www.longplayai.com/site/brand/indiana-mark.png" alt="Longplay" width="72" height="72" />
4
4
  </a>
5
5
  </p>
6
6
 
7
7
  [English](./README.md)
8
8
 
9
- 当前源码为 SDK 0.10.7、协议 0.10。本页示例使用 `https://api.longplayai.com` 以及生产部署内签发的 Sandbox App/凭据。Sandbox 仍属于生产数据,不能复用独立测试部署的凭据。运行前核对[环境状态](../../docs/development-status.md),确认服务已就绪。
9
+ 当前源码为 SDK 0.10.14、协议 0.10。本页示例使用 `https://api.longplayai.com` 以及生产部署内签发的 Sandbox App/凭据。Sandbox 仍属于生产数据,不能复用独立测试部署的凭据。运行前核对[环境状态](../../docs/development-status.md),确认服务已就绪。
10
10
 
11
11
  # @tinkerlandai/longplay-sdk
12
12
 
@@ -18,11 +18,9 @@
18
18
  npm install --save-exact @tinkerlandai/longplay-sdk@latest
19
19
  ```
20
20
 
21
- 首次安装解析最新稳定版,--save-exact 将结果固定在 package.json。提交锁文件,后续构建使用 npm ci;历史安装或回滚请沿用[发布记录](../../docs/sdk-releases.md)中的原包名和精确版本。Longplay 新包名需要单独发布,源码修改不代表已经发布。
21
+ 首次安装解析最新稳定版,--save-exact 将结果固定在 package.json。提交锁文件,后续构建使用 npm ci。[SDK 分发](../../docs/sdk-releases.md)记录包版本;源码修改不代表已发布,已有版本产物保持不可变。
22
22
 
23
- IAM Funnel 入口及首批可靠性修复需要 SDK 0.10.5 或更新版本。可执行 `npm install --save-exact @tinkerlandai/longplay-sdk@0.10.5` 固定安装此版本;可变标签的实际指向见[发布记录](../../docs/sdk-releases.md)。
24
-
25
- SDK 0.10.7 要求 HTTP 协议 0.10。服务端须使用同一当前协议,不提供旧协议兼容;发布包不会部署服务端。实际发布、标签与环境验收范围见 [SDK 发布总账](../../docs/sdk-releases.md) 和 [开发状态](../../docs/development-status.md)。
23
+ 当前 SDK 要求 HTTP 协议 0.10。服务端须使用同一当前协议,不提供旧协议兼容;发布包不会部署服务端。实际发布、标签与环境验收范围见 [SDK 发布总账](../../docs/sdk-releases.md) 和 [开发状态](../../docs/development-status.md)。
26
24
 
27
25
  数据/会话层负责公开 JSON、完整性校验和鉴权操作;展示宿主将会话接口接入打包的屏幕渲染器,渲染器消费已提供的数据并返回动作意图。客户端按需加载展示;`/server` 入口使用商户后端的受限 Server Key,不加载屏幕展示。SDK 本地检查不替代运行时授权或付款核实。后台 Preview 为同一个展示宿主提供模拟会话和数据。
28
26
 
@@ -31,7 +29,7 @@ SDK 0.10.7 要求 HTTP 协议 0.10。服务端须使用同一当前协议,不
31
29
  普通 script 标签复用 npm 浏览器实现,无需打包工具:
32
30
 
33
31
  ```sh
34
- SDK_MODULE_URL="$(curl -fsS https://longplayai.com/sdk/module)" &&
32
+ SDK_MODULE_URL="$(curl -fsS https://cdn.longplayai.com/sdk/module)" &&
35
33
  printf 'export * from "%s";\n' "$SDK_MODULE_URL" > longplay-sdk.js
36
34
  ```
37
35
 
@@ -57,7 +55,7 @@ printf 'export * from "%s";\n' "$SDK_MODULE_URL" > longplay-sdk.js
57
55
  </script>
58
56
  ```
59
57
 
60
- 提交生成的 longplay-sdk.js,即可锁定不可变模块地址;仅在升级时重新解析。经典脚本 `https://longplayai.com/sdk.js` 仍随 Web 发布更新,并配套使用同环境 API 和凭据。`Longplay.ready` 返回根入口的全部浏览器导出,以及 `createPageExperiments` / `createVisualExperiments`;下文 npm import 可替换为从该 Promise 解构同名函数。加载不自动创建会话、发送事件或启动实验。Server Key 留在后端,Funnel 启动恢复与退出清理沿用现有流程。重复标签共用 ready,失败会拒绝 Promise,UI 按需加载。加载标签使用普通 script;添加 async/defer 时先等标签 load 事件,再访问 `Longplay`。CSP 需允许脚本来源和 API 连接。页面实验也使用该统一入口,显式创建客户端并调用 `start()`。详见 [script 分发](../../docs/sdk-architecture.md#web-script-distribution)和[完整接入示例](https://longplayai.com/docs/javascript#script)。
58
+ 提交生成的 longplay-sdk.js,即可锁定不可变模块地址;仅在升级时重新解析。经典脚本 `https://cdn.longplayai.com/sdk.js` 仍随 Web 发布更新,并配套使用同环境 API 和凭据。`Longplay.ready` 返回根入口的全部浏览器导出,以及 `createPageExperiments` / `createVisualExperiments`;下文 npm import 可替换为从该 Promise 解构同名函数。加载不自动创建会话、发送事件或启动实验。Server Key 留在后端,Funnel 启动恢复与退出清理沿用现有流程。重复标签共用 ready,失败会拒绝 Promise,UI 按需加载。加载标签使用普通 script;添加 async/defer 时先等标签 load 事件,再访问 `Longplay`。CSP 需允许脚本来源和 API 连接。页面实验也使用该统一入口,显式创建客户端并调用 `start()`。详见 [script 分发](../../docs/sdk-architecture.md#web-script-distribution)和[完整接入示例](https://www.longplayai.com/zh-hans/docs/sdk/javascript#script)。
61
59
 
62
60
  ## React Native 核心入口
63
61
 
@@ -75,7 +73,7 @@ Flow `commit_segment` 只包含固定 requestId、停车位置 nodeId/visit/
75
73
 
76
74
  ## 版本兼容与支持
77
75
 
78
- 当前 0.x 仅支持当前协议;1.0 起同一主版本内保持兼容。新稳定主版本发布后,旧稳定主版本至少继续支持 12 个日历月,停止支持提前至少 180 天公开通知,实际日期取两者中较晚者。详见 [版本与支持政策](../../docs/sdk-versioning-and-support.md) 和公开开发文档 `/docs/release-notes#support-policy`。
76
+ 当前 0.x 仅支持当前协议;1.0 起同一主版本内保持兼容。新稳定主版本发布后,旧稳定主版本至少继续支持 12 个日历月,停止支持提前至少 180 天公开通知,实际日期取两者中较晚者。详见 [版本与支持政策](../../docs/sdk-versioning-and-support.md) 和公开开发文档 `/zh-hans/docs/guides/version-support#support-policy`。
79
77
 
80
78
  SDK 发送当前协议及 SDK 版本请求头,并校验成功响应的协议声明;旧 0.x 协议不会自动转换成当前协议。源码更新不会修改已有 npm 包,也不会自动部署服务端。
81
79
 
@@ -96,7 +94,7 @@ JavaScript 与 TypeScript 共用本包,声明文件随包提供。内部 `@ind
96
94
 
97
95
  展示独立的 **Page、Popup 或 Banner 资源**,从主入口导入 `createLongplay` 和 `mountContent`,先用 `longplay.resolveContent(...)` 解析,再挂载结果。`/page` 用于商户现有页面的 GB 网址跳转实验,`/visual` 用于该页面的 GB 视觉修改;`/popup` 提供底层屏幕渲染与预览工具,不负责选择或解析 Popup 资源。现有公开导入路径保持不变,详见[入口职责](../../docs/sdk-architecture.md#public-entry-points-and-capability-ownership)。
98
96
 
99
- 独立的 [Python 服务端 SDK](../python/README.md) 使用同一当前 HTTP 协议,提供同步、异步 Customer、持仓/权益检查和用量上报。它从 `https://longplayai.com/sdk/python` 分发(不在 PyPI),不属于这个 npm 包。
97
+ 独立的 [Python 服务端 SDK](../python/README.md) 使用同一当前 HTTP 协议,提供同步、异步 Customer、持仓/权益检查和用量上报。它从 `https://cdn.longplayai.com/sdk/python` 分发(不在 PyPI),不属于这个 npm 包。
100
98
 
101
99
  [Go 服务端 SDK](../go/README.md) 提供同样的首版能力,使用类型化响应、Context 取消和 goroutine 并发复用客户端。通过 Go 默认模块代理以 `go get longplayai.com/sdk/go` 安装,与其他业务 SDK 共用发行版本。
102
100
 
@@ -191,7 +189,7 @@ Funnel、独立 Feature 和页面实验各自求值、各自使用结果。App
191
189
 
192
190
  Customer 求值中的 `id` 是 Longplay Customer UUID(`customer.id`),`externalUserId` 是商户账号 ID(`customer.externalUserId`)。创建实验时明确选择 `hashAttribute`,每个消费方保持相同语义;不要把商户账号 ID 填进 `attributes.id`。本地属性来自可信后端给当前用户的 Customer 数据;`identify(customerToken)` 负责请求认证,不会自动补齐本地分桶属性。属性仅用于求值,不构成授权。
193
191
 
194
- `setAttributes()` 替换整个对象,每次更新都保留分桶字段。匿名页面/视觉实验默认的 `id` 和 `deviceId` 来自共用的第一方设备 cookie,不自动与账号实验同组。已打开的页面在可见时每 60 秒重新读取视觉配置,实验停止或关闭投放后无需刷新页面即可撤销修改。各适配器的 Sticky 能力有区别:共用 Run 的 Local 指令读取服务端状态,纯本地工具的持久 Sticky 使用已有宿主适配器,不新增共享状态。完整要求见[架构边界](../../docs/growthbook-sdk-delivery.md#跨消费方求值边界与分桶身份)。
192
+ `setAttributes()` 替换整个对象,每次更新都保留分桶字段。匿名页面/视觉实验默认的 `id` 和 `deviceId` 来自共用的第一方设备 cookie,不自动与账号实验同组。已打开的页面在可见时每 60 秒重新读取视觉配置,实验停止或关闭投放后无需刷新页面即可撤销修改。各适配器的 Sticky 能力有区别:共用 Run 的 Local 指令读取服务端状态,纯本地工具的持久 Sticky 使用已有宿主适配器,不新增共享状态。完整要求见[架构边界](../../docs/growthbook-sdk-delivery.md#cross-consumer-evaluation-and-bucketing-identity)。
195
193
 
196
194
  ### 服务端 SDK 本地 Funnel 求值
197
195
 
@@ -218,7 +216,7 @@ const used = await session.evaluate({ track: true });
218
216
 
219
217
  默认求值不触发曝光。仅在确实使用结果时传 `{ track: true }`,成功计算并保存 Sticky 后才调用已配置的 `onExperimentViewed`/`onFeatureUsage`,按本会话内的原生分配/值去重。回调接入已有事件 tracker,异常通过 `onError` 报告;事件送达与重试由 tracker 负责,不生成持久的曝光或使用回执。
220
218
 
221
- 含商业节点的混合图、资源/Bundle 输出、过期配置明确拒绝,不自动执行远程 `decide()`。远程幂等、已提交回执和财务检查保持原义;本地结果不能代替发券、付款、权益或全局频控。这是需要配套 HTTP 实现的源码能力,本次没有发布 SDK。
219
+ 含商业节点的混合图、资源/Bundle 输出、过期配置明确拒绝,不自动执行远程 `decide()`。远程幂等、已提交回执和财务检查保持原义;本地结果不能代替发券、付款、权益或全局频控。使用前确认目标运行时支持相同协议与配置投递契约。
222
220
 
223
221
  ### 独立 Feature
224
222
 
@@ -264,7 +262,7 @@ Offering 固定 Product Version 的范围与层级。Paywall 固定已发布 Off
264
262
 
265
263
  Stripe 环境的 `longplay` 模式由 Longplay 执行;`record_only` 返回交给商户后端执行的指令。两种模式都从验证后的 Stripe 事实写入财务与权益。支付方式收集本身不产生扣款、Invoice 或额外权益。报价/确认/读取使用各自持久操作 ID;同一请求编号不能更换输入。
266
264
 
267
- 本 Beta **不认证完整商业功能或生产运行**。当前仍未接通的服务包括:
265
+ 包安装成功**不代表完整商业功能或生产环境已验收**。当前仍未接通的服务包括:
268
266
 
269
267
  - 订阅批处理。冲突查询/重试已有对应服务,但仍需匹配部署及业务前置条件。
270
268
  - Postpaid Billing Authorization、Billing Coupon 列表和账单调整确认。当前 AutoTopup consent 的准备/确认/撤销已有服务,不能据此推定其他授权类型可用。
@@ -287,7 +285,7 @@ npm 发布不部署 Web 服务、不应用数据库迁移,也不发布 Swift
287
285
 
288
286
  ## 共享公共配置
289
287
 
290
- 源码新增 `createConfigurationSync({ origin, scope })`;`scope` 必须明确包含 `projectId`、`environment` 和 `environmentId`。将同一个实例作为 `configuration` 传给 `createLongplay`、Funnel start/Run controller 和 `createPageExperiments`,共用清单、文件缓存、并发请求和更新通知。`/server` 导出的 `createSynchronizedFunnelLocalEvaluator(configuration, funnelId)` 使用同一份规范 Funnel 文件与 GB 代次进行纯判断,保留仅可信服务端执行的边界。
288
+ `createConfigurationSync({ origin, scope })`;`scope` 必须明确包含 `projectId`、`environment` 和 `environmentId`。将同一个实例作为 `configuration` 传给 `createLongplay`、Funnel start/Run controller 和 `createPageExperiments`,共用清单、文件缓存、并发请求和更新通知。`/server` 导出的 `createSynchronizedFunnelLocalEvaluator(configuration, funnelId)` 使用同一份规范 Funnel 文件与 GB 代次进行纯判断,保留仅可信服务端执行的边界。
291
289
 
292
290
  公共配置由匹配运行端发布。公共文件不需要 Customer 凭据;业务操作沿用原凭据和服务端资格检查。完整调用见[英文说明](README.md#shared-public-configuration)。
293
291
 
@@ -376,4 +374,4 @@ export async function showBanner(
376
374
 
377
375
  Server 入口导出 `createMerchantBridgeHandler`、`createMerchantBridgeAuthorityResolver`、`signMerchantBridgeMessage` 和 `verifyMerchantBridgeMessage`。配置后端签名密钥、原生授权/CSRF、实际已实现的能力与 profiles,并设置 `resolveOperationAuthority: createMerchantBridgeAuthorityResolver(server)`,每次从 Longplay 原操作 API 读取最新权限。服务签名仍需原确认事实和准确范围、Customer 归属,不能据此签发用户会话。
378
376
 
379
- 业务处理器必须在调用外部渠道前持久预留原 operationId,并使用稳定渠道幂等键;SDK 的先查询不能代替并发锁。`operation.read` 返回 `found` 或 `not_received`,严格只读。`RESULT_UNKNOWN` 只恢复原操作,不能根据浏览器报价或 pending 状态自行推断执行权限。Console 能力检查不证明商业完成。精确字段和恢复规则见[商户接入规范](https://longplayai.com/zh-hans/docs/merchant-execution)。
377
+ 业务处理器必须在调用外部渠道前持久预留原 operationId,并使用稳定渠道幂等键;SDK 的先查询不能代替并发锁。`operation.read` 返回 `found` 或 `not_received`,严格只读。`RESULT_UNKNOWN` 只恢复原操作,不能根据浏览器报价或 pending 状态自行推断执行权限。Console 能力检查不证明商业完成。精确字段和恢复规则见[商户接入规范](https://www.longplayai.com/zh-hans/docs/guides/merchant-execution)。
@@ -1,5 +1,5 @@
1
1
  import { LanguageModelV4Usage, LanguageModelV4Middleware } from '@ai-sdk/provider';
2
- import { F as FoundationApi, A as ApiInput } from './api-Cefn6AaL.js';
2
+ import { F as FoundationApi, A as ApiInput } from './api-RQUBSSEJ.js';
3
3
  import { z } from 'zod';
4
4
 
5
5
  declare const tokenCounts: z.ZodObject<{
@@ -1,4 +1,4 @@
1
- import { S as StackNode } from './screen-D81zCpfi.js';
1
+ import { S as StackNode } from './screen-DRP7nsrQ.js';
2
2
  import { z } from 'zod/v4';
3
3
  import { z as z$1 } from 'zod';
4
4
 
@@ -3985,11 +3985,11 @@ declare const apiOperations: {
3985
3985
  field: z$1.ZodEnum<{
3986
3986
  quantity: "quantity";
3987
3987
  currency: "currency";
3988
+ product: "product";
3988
3989
  price: "price";
3989
3990
  subscription: "subscription";
3990
3991
  status: "status";
3991
3992
  cancelAtPeriodEnd: "cancelAtPeriodEnd";
3992
- product: "product";
3993
3993
  periodStart: "periodStart";
3994
3994
  periodEnd: "periodEnd";
3995
3995
  trialEnd: "trialEnd";
@@ -4709,20 +4709,6 @@ declare const apiOperations: {
4709
4709
  eventId: z$1.ZodString;
4710
4710
  customerId: z$1.ZodUUID;
4711
4711
  occurredAt: z$1.ZodISODateTime;
4712
- }, z$1.core.$strict>, z$1.ZodObject<{
4713
- type: z$1.ZodLiteral<"dispute.updated">;
4714
- merchantDisputeId: z$1.ZodString;
4715
- merchantInvoiceId: z$1.ZodString;
4716
- status: z$1.ZodEnum<{
4717
- funds_withdrawn: "funds_withdrawn";
4718
- funds_reinstated: "funds_reinstated";
4719
- }>;
4720
- amountMinor: z$1.ZodNumber;
4721
- currency: z$1.ZodString;
4722
- provider: z$1.ZodLiteral<"merchant">;
4723
- eventId: z$1.ZodString;
4724
- customerId: z$1.ZodUUID;
4725
- occurredAt: z$1.ZodISODateTime;
4726
4712
  }, z$1.core.$strict>], "type">]>;
4727
4713
  readonly response: z$1.ZodObject<{
4728
4714
  requestId: z$1.ZodUUID;
@@ -12164,8 +12150,8 @@ declare const apiOperations: {
12164
12150
  rows: z$1.ZodArray<z$1.ZodObject<{
12165
12151
  id: z$1.ZodUUID;
12166
12152
  sourceKind: z$1.ZodEnum<{
12167
- usage: "usage";
12168
12153
  product: "product";
12154
+ usage: "usage";
12169
12155
  manual: "manual";
12170
12156
  }>;
12171
12157
  providerInvoiceId: z$1.ZodNullable<z$1.ZodString>;
@@ -12382,8 +12368,8 @@ declare const apiOperations: {
12382
12368
  invoice: z$1.ZodObject<{
12383
12369
  id: z$1.ZodUUID;
12384
12370
  sourceKind: z$1.ZodEnum<{
12385
- usage: "usage";
12386
12371
  product: "product";
12372
+ usage: "usage";
12387
12373
  manual: "manual";
12388
12374
  }>;
12389
12375
  providerInvoiceId: z$1.ZodNullable<z$1.ZodString>;
@@ -13446,14 +13432,30 @@ declare const apiOperations: {
13446
13432
  schemaVersion: z$1.ZodLiteral<4>;
13447
13433
  name: z$1.ZodString;
13448
13434
  surface: z$1.ZodEnum<{
13449
- paywall: "paywall";
13450
13435
  popup: "popup";
13436
+ paywall: "paywall";
13451
13437
  onboarding: "onboarding";
13452
13438
  page: "page";
13453
13439
  banner: "banner";
13454
13440
  }>;
13455
13441
  initialPageId: z$1.ZodOptional<z$1.ZodString>;
13456
13442
  presentation: z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
13443
+ desktopWidth: z$1.ZodOptional<z$1.ZodObject<{
13444
+ min: z$1.ZodNumber;
13445
+ max: z$1.ZodNumber;
13446
+ viewport: z$1.ZodNumber;
13447
+ }, z$1.core.$strict>>;
13448
+ mobile: z$1.ZodOptional<z$1.ZodEnum<{
13449
+ sheet: "sheet";
13450
+ fullscreen: "fullscreen";
13451
+ }>>;
13452
+ backdrop: z$1.ZodOptional<z$1.ZodEnum<{
13453
+ none: "none";
13454
+ scrim: "scrim";
13455
+ dim: "dim";
13456
+ "strong-dim": "strong-dim";
13457
+ blur: "blur";
13458
+ }>>;
13457
13459
  type: z$1.ZodLiteral<"modal">;
13458
13460
  size: z$1.ZodEnum<{
13459
13461
  sm: "sm";
@@ -13461,6 +13463,22 @@ declare const apiOperations: {
13461
13463
  lg: "lg";
13462
13464
  }>;
13463
13465
  }, z$1.core.$strict>, z$1.ZodObject<{
13466
+ desktopWidth: z$1.ZodOptional<z$1.ZodObject<{
13467
+ min: z$1.ZodNumber;
13468
+ max: z$1.ZodNumber;
13469
+ viewport: z$1.ZodNumber;
13470
+ }, z$1.core.$strict>>;
13471
+ mobile: z$1.ZodOptional<z$1.ZodEnum<{
13472
+ sheet: "sheet";
13473
+ fullscreen: "fullscreen";
13474
+ }>>;
13475
+ backdrop: z$1.ZodOptional<z$1.ZodEnum<{
13476
+ none: "none";
13477
+ scrim: "scrim";
13478
+ dim: "dim";
13479
+ "strong-dim": "strong-dim";
13480
+ blur: "blur";
13481
+ }>>;
13464
13482
  type: z$1.ZodLiteral<"sheet">;
13465
13483
  size: z$1.ZodEnum<{
13466
13484
  sm: "sm";
@@ -13477,11 +13495,11 @@ declare const apiOperations: {
13477
13495
  background: z$1.ZodString;
13478
13496
  text: z$1.ZodString;
13479
13497
  radius: z$1.ZodEnum<{
13480
- none: "none";
13481
- full: "full";
13482
13498
  sm: "sm";
13483
13499
  md: "md";
13484
13500
  lg: "lg";
13501
+ none: "none";
13502
+ full: "full";
13485
13503
  }>;
13486
13504
  font: z$1.ZodEnum<{
13487
13505
  system: "system";
@@ -13489,6 +13507,14 @@ declare const apiOperations: {
13489
13507
  rounded: "rounded";
13490
13508
  mono: "mono";
13491
13509
  }>;
13510
+ fontAssets: z$1.ZodOptional<z$1.ZodObject<{
13511
+ family: z$1.ZodString;
13512
+ faces: z$1.ZodArray<z$1.ZodObject<{
13513
+ url: z$1.ZodString;
13514
+ weight: z$1.ZodNumber;
13515
+ family: z$1.ZodOptional<z$1.ZodString>;
13516
+ }, z$1.core.$strict>>;
13517
+ }, z$1.core.$strict>>;
13492
13518
  }, z$1.core.$strict>;
13493
13519
  pages: z$1.ZodArray<z$1.ZodObject<{
13494
13520
  id: z$1.ZodString;
@@ -13499,11 +13525,11 @@ declare const apiOperations: {
13499
13525
  background: z$1.ZodString;
13500
13526
  text: z$1.ZodString;
13501
13527
  radius: z$1.ZodEnum<{
13502
- none: "none";
13503
- full: "full";
13504
13528
  sm: "sm";
13505
13529
  md: "md";
13506
13530
  lg: "lg";
13531
+ none: "none";
13532
+ full: "full";
13507
13533
  }>;
13508
13534
  font: z$1.ZodEnum<{
13509
13535
  system: "system";
@@ -13511,6 +13537,14 @@ declare const apiOperations: {
13511
13537
  rounded: "rounded";
13512
13538
  mono: "mono";
13513
13539
  }>;
13540
+ fontAssets: z$1.ZodOptional<z$1.ZodObject<{
13541
+ family: z$1.ZodString;
13542
+ faces: z$1.ZodArray<z$1.ZodObject<{
13543
+ url: z$1.ZodString;
13544
+ weight: z$1.ZodNumber;
13545
+ family: z$1.ZodOptional<z$1.ZodString>;
13546
+ }, z$1.core.$strict>>;
13547
+ }, z$1.core.$strict>>;
13514
13548
  }, z$1.core.$strict>>;
13515
13549
  editorPosition: z$1.ZodOptional<z$1.ZodObject<{
13516
13550
  x: z$1.ZodNumber;
@@ -14726,8 +14760,8 @@ declare const apiOperations: {
14726
14760
  }, z$1.core.$strict>, z$1.ZodObject<{
14727
14761
  type: z$1.ZodLiteral<"transaction">;
14728
14762
  purpose: z$1.ZodEnum<{
14729
- invoice: "invoice";
14730
14763
  product: "product";
14764
+ invoice: "invoice";
14731
14765
  }>;
14732
14766
  productVersionId: z$1.ZodNullable<z$1.ZodUUID>;
14733
14767
  productName: z$1.ZodNullable<z$1.ZodString>;
@@ -14847,8 +14881,8 @@ declare const apiOperations: {
14847
14881
  invoice: z$1.ZodObject<{
14848
14882
  id: z$1.ZodUUID;
14849
14883
  sourceKind: z$1.ZodEnum<{
14850
- usage: "usage";
14851
14884
  product: "product";
14885
+ usage: "usage";
14852
14886
  manual: "manual";
14853
14887
  }>;
14854
14888
  providerInvoiceId: z$1.ZodNullable<z$1.ZodString>;
@@ -16224,8 +16258,8 @@ declare const apiOperations: {
16224
16258
  holdingStatus: z$1.ZodDefault<z$1.ZodEnum<{
16225
16259
  "": "";
16226
16260
  unavailable: "unavailable";
16227
- active: "active";
16228
16261
  none: "none";
16262
+ active: "active";
16229
16263
  expired: "expired";
16230
16264
  scheduled: "scheduled";
16231
16265
  }>>;
@@ -1 +1 @@
1
- import{f as o}from"./chunk-VSJOHWDL.js";var n=class extends Error{constructor(t,s,y,i,r){super(s);this.code=t;this.status=y;this.requestId=i;this.name="IndianaError",this.reason=r?.reason;let e=o(t,y??0,{...r,retryAfter:r?.retryAfterSeconds===void 0?void 0:String(r.retryAfterSeconds)});this.retryable=e.retryable,this.recovery=e.recovery,this.retryAfterSeconds=e.retryAfterSeconds}code;status;requestId;commandRequestId;retryable;recovery;retryAfterSeconds;reason};export{n as a};
1
+ import{f as o}from"./chunk-PFHS7HK3.js";var n=class extends Error{constructor(t,s,y,i,r){super(s);this.code=t;this.status=y;this.requestId=i;this.name="IndianaError",this.reason=r?.reason;let e=o(t,y??0,{...r,retryAfter:r?.retryAfterSeconds===void 0?void 0:String(r.retryAfterSeconds)});this.retryable=e.retryable,this.recovery=e.recovery,this.retryAfterSeconds=e.retryAfterSeconds}code;status;requestId;commandRequestId;retryable;recovery;retryAfterSeconds;reason};export{n as a};
@@ -0,0 +1 @@
1
+ import{b as dn,c as fn,d as mn,e as pn}from"./chunk-LC2VUKYM.js";import{a as gn}from"./chunk-EEZLS2YP.js";import{a as te,b as Y}from"./chunk-APO7QUBB.js";import{a as m}from"./chunk-26HU2HXU.js";import{a as ln,b as cn,c as Ce}from"./chunk-6MBVIE3H.js";import{$a as un,Ea as Te,Fa as tn,R as Ge,T as Re,Ta as rn,U as Be,Ua as on,V as Je,W as je,Xa as an,Ya as sn,a as qe,cb as le,da as Q,ea as ze,fa as J,ga as Ke,ha as Oe,ia as M,ka as Qe,la as Ye,ma as $e,n as ue,na as We,oa as Ze,ua as ne,va as Xe,ya as en,za as nn}from"./chunk-EFFXE6CX.js";import{B as ve,Fa as He,v as Ue,y as ke}from"./chunk-PFHS7HK3.js";function qn(e){let n=null,t=null,s=0,d=0,w=new Set,f=null,o=null,g=new Set,i=()=>{for(let a of g)try{a()}catch{}},l={attributes:ve.parse(e.attributes??{}),onFeatureUsage:e.onFeatureUsage?(a,r)=>{!w.has(a)&&(!n||!("analyticsConfig"in n)||n.analyticsConfig.featureUsageEnabled)&&e.onFeatureUsage(a,structuredClone(r),structuredClone(l.attributes))}:void 0,onExperimentViewed:e.onExperimentViewed?(a,r)=>(!n||!("analyticsConfig"in n)||n.analyticsConfig.experimentViewsEnabled)&&e.onExperimentViewed(structuredClone(a),structuredClone(r),structuredClone(l.attributes)):void 0,stickyBucketAssignmentDocs:structuredClone(e.stickyBucketAssignmentDocs),saveStickyBucketAssignmentDoc:e.saveStickyBucketAssignmentDoc?a=>e.saveStickyBucketAssignmentDoc(structuredClone(a)):void 0,trackedFeatureUsage:{},trackedExperiments:new Set},u=()=>({value:null,source:"unknownFeature",on:!1,off:!0,ruleId:""});function c(a,r=new Set){return w.has(a)?!f||!f.features[a]||["unknownFeature","cyclicPrerequisite"].includes(f.features[a].source):r.has(a)?!1:(r.add(a),(n?.features[a]?.rules??[]).some(p=>[...p.parentConditions??[],...(p.tracks??[]).flatMap(v=>v.experiment.parentConditions??[])].some(v=>c(v.id,r))))}let h=a=>{if(e.assertUsable?.(n?.generation),!n)throw new Error("Initialize the Feature client before evaluation");if(n.expiresAt&&Date.parse(n.expiresAt)<=Date.now())throw new Error("Feature configuration expired; refresh before evaluation");return f?.expiresAt&&Date.parse(f.expiresAt)<=Date.now()&&(f=null,l.features=n.features),w.has(a)?!f||f.expiresAt&&Date.parse(f.expiresAt)<=Date.now()?u():structuredClone(f.features[a]??u()):e.evaluateRemote&&(l.attributes?.merchandise||l.attributes?.merchandiseId)&&!f||c(a)?u():structuredClone(ke(a,l))};async function F(){if(!n||!w.size&&!l.attributes?.merchandise&&!l.attributes?.merchandiseId)return;if(!e.evaluateRemote){if(w.size)throw new Error("Remote Feature evaluation requires a server loader");return}let a=d;if(o?.revision===a)return o.loading;let r=s,p=n,v=[...w],C=(async()=>{let S=je.parse(await e.evaluateRemote({attributes:structuredClone(l.attributes),features:v}));if(!(r!==s||a!==d||p!==n)){if(e.assertUsable?.(p.generation),S.generation!==p.generation)throw new Error("Feature configuration changed; refresh before evaluation");if(v.some(R=>!Object.hasOwn(S.features,R))||Object.keys(S.features).some(R=>!w.has(R)))throw new Error("Invalid remote Feature results");if(l.attributes?.merchandise||l.attributes?.merchandiseId){if(!S.merchandiseContext)throw new Error("Server did not resolve merchandise context");l.attributes=ve.parse({...l.attributes,...S.merchandiseContext})}f=structuredClone(S),l.features={...p.features,...Object.fromEntries(Object.entries(f.features).map(([R,O])=>[R,{defaultValue:O.value}]))},i()}})();o={revision:a,loading:C};try{await C}finally{o?.loading===C&&(o=null)}}function N(){F().catch(a=>{try{e.onError?.(a)}catch{}})}async function L(){if(t)return t;let a=s,r=(async()=>{let p=await e.load(),v="remoteFeatures"in p?Be.parse(p):null,C=v??Re.parse(p);if(C.scope.projectId!==e.scope.projectId||C.scope.environment!==e.scope.environment)throw new Error("Feature payload scope changed");if(a!==s)throw new Error("Feature client was reset");if(e.assertUsable&&n?.generation===C.generation){let{evaluatedAt:R,expiresAt:O,...D}=n,{evaluatedAt:x,expiresAt:k,...G}=C;if(M(D)!==M(G))throw new Error("Immutable Feature generation changed content");return n.evaluatedAt=C.evaluatedAt,n.expiresAt=C.expiresAt,i(),(!f||f.expiresAt&&Date.parse(f.expiresAt)<=Date.now())&&N(),structuredClone(n)}let S=new Set(v?.remoteFeatures??[]);if([...S].some(R=>Object.hasOwn(C.features,R)))throw new Error("Remote Feature definitions must not be delivered locally");return n&&"analyticsConfig"in n&&"analyticsConfig"in C&&!n.analyticsConfig.experimentViewsEnabled&&v?.analyticsConfig.experimentViewsEnabled&&l.trackedExperiments?.clear(),n=structuredClone(C),w=S,f=null,o=null,d++,l.features=n.features,l.savedGroups=Ue(n.savedGroups),l.trackedFeatureUsage={},i(),N(),structuredClone(n)})();t=r;try{return await r}finally{t===r&&(t=null)}}return{init:L,refresh:L,refreshRemote:F,get generation(){return n?.generation??null},get expiresAt(){return n?.expiresAt??null},subscribe(a){return g.add(a),()=>{g.delete(a)}},setAttributes(a){let r=ve.parse(a);(l.attributes?.merchandise||l.attributes?.merchandiseId||a.merchandise||a.merchandiseId)&&l.trackedExperiments?.clear(),l.attributes=r,d++,f=null,o=null,l.features=n?.features??{},l.trackedFeatureUsage={},i(),N()},evalFeature:h,isOn(a){return h(a).on},isOff(a){return h(a).off},getFeatureValue(a,r){let p=h(a).value;return structuredClone(p===null?r:p)},reset(){s++,d++,t=null,o=null,n=null,f=null,w.clear(),l.features={},l.savedGroups={},l.stickyBucketAssignmentDocs={},l.attributes={},l.trackedFeatureUsage={},l.trackedExperiments?.clear(),i()}}}function yn(e){let n,t,s=()=>new m("COMMAND_STORAGE_INVALID","Durable command storage is unavailable"),d=Promise.resolve().then(async()=>{if(n=e.storage??globalThis.localStorage,t=e.locks??globalThis.navigator?.locks,!n||!t||!globalThis.crypto?.subtle)throw s();let o=new TextEncoder().encode(JSON.stringify([new URL(e.baseUrl??le).href,e.runToken])),g=new Uint8Array(await crypto.subtle.digest("SHA-256",o));return"indiana.funnel.commands.v1."+Array.from(g,i=>i.toString(16).padStart(2,"0")).join("")});d.catch(()=>{});async function w(o){try{let g=await d;return await t.request(g,{mode:"exclusive"},()=>o(g))}catch(g){throw g instanceof m?g:s()}}function f(o){let g=n.getItem(o);if(g===null)return{revision:0,entry:null};if(g.length>1048576)throw s();let i=JSON.parse(g);if(!i||typeof i!="object"||!("revision"in i)||!("entry"in i)||!Number.isSafeInteger(i.revision)||Number(i.revision)<0)throw s();return{revision:Number(i.revision),entry:i.entry}}return{read:()=>w(f),write:(o,g)=>w(i=>{if(f(i).revision!==o)return null;if(!Number.isSafeInteger(o+1))throw s();return n.setItem(i,JSON.stringify({revision:o+1,entry:g})),o+1})}}function be(e,n){let t=en.safeParse(n);if(!t.success)throw new m("INVALID_RESPONSE","Funnel response contract changed");let s=t.data;if(e.scope&&(s.scope.projectId!==e.scope.projectId||s.scope.environment!==e.scope.environment))throw new m("SCOPE_MISMATCH","Funnel scope changed");return s}async function Pe(e,n){let t=We.parse(n),{artifact:s,environmentId:d}=t.content,w=new te(e.baseUrl??le).origin,f=new te(s.url,w);if(f.origin!==w||f.username||f.password||f.search||f.hash||f.pathname!==`/api/v1/configuration/${d}/artifacts/${s.sha256}`)throw new m("INVALID_RESPONSE","Public Paywall locator is not trusted");let o=new AbortController,g,i=new Promise((u,c)=>{g=setTimeout(()=>{let h=new m("TIMEOUT","Public Paywall read timed out");o.abort(h),c(h)},J.initializationMs)}),l=(async()=>{let u=await(e.fetch??globalThis.fetch)(f,{method:"GET",credentials:"omit",redirect:"error",cache:"default",signal:o.signal});if(o.signal.aborted&&(u.body?.cancel().catch(()=>{}),o.signal.throwIfAborted()),!u.ok||!u.headers.get("content-type")?.toLowerCase().startsWith("application/json")||Number(u.headers.get("content-length"))>s.byteLength)throw u.body?.cancel().catch(()=>{}),new m("INVALID_RESPONSE","Public Paywall is unavailable");let c=await ln(u,s.byteLength,{signal:o.signal,error:h=>new m("INVALID_RESPONSE",h==="missing"?"Public Paywall body is missing":"Public Paywall exceeds its byte limit")});if(!Ce(c,s))throw new m("INVALID_RESPONSE","Public Paywall digest or size changed");return Ze(t,JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(c)))})();try{return await Promise.race([l,i])}finally{clearTimeout(g)}}var _e=(e,n)=>new m(e,n);function et(e){return sn(e,_e)}async function De(e,n,{predict:t=!0}={}){let s=n.instruction;if(s?.type!=="evaluate_segment")throw new Error("Local segment instruction required");if(!e)throw new m("CONFIGURATION_UNAVAILABLE","Local execution requires public configuration");if(e.scope.environmentId!==s.environmentId)throw new m("SCOPE_MISMATCH","Evaluation environment changed");let d=null,w;if(t)try{let f=await e.funnel(n.source.id,n.source.versionId);w=f.manifest.generation,d=Nn(e,n,f)}catch{d=null}return w??=e.snapshot?.generation??(await e.refresh()).generation,{advance:{policyRevision:s.policyRevision,generation:w},prediction:d}}function Nn(e,n,t){let s=n.instruction;if(s?.type!=="evaluate_segment"||!t.growth||t.control.evaluationMode!=="local"||t.control.evaluationRevision!==s.policyRevision)return null;let{analyticsConfig:d,remoteFeatures:w,...f}=t.growth,o=rn({scope:{projectId:e.scope.projectId,environment:e.scope.environment},funnelId:n.source.id,versionId:n.source.versionId,evaluationMode:"local",evaluationRevision:s.policyRevision,document:t.document,payload:Re.parse(f)}),g=On(o,t.document,{...n,...s}),i=g.steps.at(-1),l=g.boundary??(i?.result.port==="value"?{nodeId:i.nodeId,visit:n.visit+g.steps.length-1}:null);return l?{runId:n.id,from:{nodeId:n.nodeId,visit:n.visit,revision:n.revision},nodeId:l.nodeId,visit:l.visit,terminal:!g.boundary}:null}function On(e,n,t){return un(e,n,t,_e)}import{z as j}from"zod";var wn=Q.refine(e=>!["start","get","review"].includes(e.operation)&&!("customerToken"in e),"Persist only the original mutation, without credentials").transform(e=>{if(e.operation==="start"||e.operation==="get"||e.operation==="review")throw new m("COMMAND_STORAGE_INVALID","Stored mutation required");return e}),In=j.strictObject({schemaVersion:j.literal(1),scope:qe,runId:j.uuid(),funnelId:j.uuid(),versionId:j.uuid(),processBindingIds:j.record(j.uuid(),j.uuid().nullable()).optional(),command:wn.optional(),closeCommand:wn.refine(e=>e.operation==="close").optional(),purchase:j.strictObject({receiptId:j.uuid(),operationId:j.uuid(),generation:j.number().int().nonnegative()}).optional(),closed:j.literal(!0).optional()}).refine(e=>!e.closeCommand||e.command&&e.command.operation!=="close"&&e.command.requestId!==e.closeCommand.requestId,"Close requires a separate request identity").refine(e=>e.command!==void 0||e.purchase!==void 0,"A recovery record requires an original obligation"),U=()=>new m("COMMAND_STORAGE_CONFLICT","Another host changed this Run's pending command"),Se=(e,n)=>JSON.stringify(e)===JSON.stringify(n);function hn(e){let n=0,t=null,s=i=>JSON.stringify([i.scope,i.runId,i.funnelId,i.versionId]),d=Promise.resolve();async function w(){let i=await e.read();if(!Number.isSafeInteger(i.revision)||i.revision<0)throw new m("COMMAND_STORAGE_INVALID","Invalid command storage revision");return{revision:i.revision,entry:i.entry===null?null:In.parse(i.entry)}}function f(i){let l=d.then(i);return d=l.catch(()=>{}),l}async function o(i){for(let l=0;l<4;l++){let u=await w();if(u.entry&&t!==null&&s(u.entry)!==t)throw U();let c=i(u.entry,u.revision);if(Se(u.entry,c)){n=u.revision;return}let h=await e.write(u.revision,c);if(h!==null){if(!Number.isSafeInteger(h)||h<=u.revision)throw U();n=h;return}}throw U()}function g(i,l){if(!i||!l)return i;if(i.processBindingIds&&Object.hasOwn(i.processBindingIds,l)){let u={...i.processBindingIds};delete u[l],i={...i,processBindingIds:u}}return i.command?.requestId===l?i.closeCommand?{...i,command:i.closeCommand,closeCommand:void 0}:i.purchase?{...i,command:void 0}:null:i.closeCommand?.requestId===l?{...i,closeCommand:void 0}:i}return{bind(i){let l=JSON.stringify([i.scope,i.runId,i.funnelId,i.versionId]);if(t!==null&&t!==l)throw U();t=l},async load(){let i=await w();return n=i.revision,t=i.entry?s(i.entry):null,i.entry},retain(i){let l=In.parse(i),u=l.command;return!u||t!==null&&s(l)!==t?Promise.reject(U()):(t??=s(l),f(()=>o((c,h)=>{if(c&&!Se(s(c),s(l)))throw U();if(c&&l.processBindingIds){for(let[F,N]of Object.entries(l.processBindingIds))if(c.processBindingIds&&Object.hasOwn(c.processBindingIds,F)&&c.processBindingIds[F]!==N)throw U();c={...c,processBindingIds:{...c.processBindingIds,...l.processBindingIds}}}if(!c){if(h!==n&&u.operation!=="close")throw U();return l}if(!c.command)return{...c,command:u,...u.operation==="close"?{closed:!0}:{}};if(u.operation==="close"&&c.command.operation!=="close"){if(c.command.requestId===u.requestId||c.closeCommand&&!Se(c.closeCommand,u))throw U();return{...c,closeCommand:u,closed:!0}}if(!Se(c.command,u))throw U();return c})))},observePurchase(i,l,u,c){return f(()=>o((h,F)=>{if(!h&&F!==n||h&&s(h)!==s({...i,schemaVersion:1}))throw U();if(h?.purchase&&h.purchase.generation>l.generation)return g(h,c);if(h?.purchase&&h.purchase.generation===l.generation&&h.purchase.operationId!==l.operationId)throw U();return u?!h?.purchase||h.purchase.operationId!==l.operationId?g(h,c):g(h.command?{...h,purchase:void 0}:null,c):g({schemaVersion:1,...i,...h,purchase:l},c)}))},settle(i){return f(()=>o(l=>g(l,i)))}}}function ct(e,n){return n.type==="id"?e.customerId===n.value:e.externalUserId===n.value}function ce(e,n){if(e===n)return!0;if(Array.isArray(e)||Array.isArray(n))return Array.isArray(e)&&Array.isArray(n)&&e.length===n.length&&e.every((d,w)=>ce(d,n[w]));if(!e||!n||typeof e!="object"||typeof n!="object")return!1;let t=Object.entries(e),s=Object.entries(n);return t.length===s.length&&t.every(([d,w])=>Object.hasOwn(n,d)&&ce(w,Reflect.get(n,d)))}function vn(e,n){let t=n&&{...n},s=null,d=0,w=new AbortController;function f(){d++,w.abort(new m("IDENTITY_CHANGED","Run identity changed")),w=new AbortController}let o=!1,g,i=0,l=new Set;return{get scope(){return t},bindScope(u){if(t&&(t.projectId!==u.projectId||t.environment!==u.environment))throw new m("SCOPE_MISMATCH","Run scope changed");t??={...u}},get view(){return s},get generation(){return d},get signal(){return w.signal},get disposed(){return o},get customerToken(){return g},get readSequence(){return i},nextRead(){return++i},assertCurrent(u,c="Run identity changed during the request"){if(u!==d||o)throw new m("IDENTITY_CHANGED",c)},assertRun(u){if(s&&(u.id!==s.id||u.source.type!==s.source.type||u.source.id!==s.source.id||u.source.versionId!==s.source.versionId||u.locale!==s.locale||!ce(u.parameters,s.parameters)))throw new m("INVALID_RESPONSE","Run version changed");if(e&&u.source.id!==e)throw new m("INVALID_RESPONSE","Run belongs to another Funnel")},publish(u,c,h,F,N){if(!(u.operation==="review"&&s&&s!==h&&c.run.revision<=s.revision)&&!(s&&c.run.revision===s.revision&&F!==void 0&&F<i)&&(u.operation==="review"&&!c.run.stopped&&["running","waiting"].includes(c.run.status)&&s&&c.run.nodeId===s.nodeId&&c.run.visit===s.visit&&c.run.revision===s.revision&&(c.run.screen=s.screen,(s.paywall?.quote?.operationId===c.review?.activeOperationId||!s.paywall?.quote&&c.review?.activeOperationId===null)&&(c.run.paywall=s.paywall)),!(s?.paywall&&c.run.paywall&&s.paywall.receiptId===c.run.paywall.receiptId&&(c.run.paywall.selectionGeneration??0)<(s.paywall.selectionGeneration??0)))){if(!s||c.run.revision>=s.revision)s=c.run;else if(!N)return;if(s)for(let L of l)try{L(structuredClone(s))}catch{}}},identify(u){if(o)throw new m("IDENTITY_CHANGED","Controller was reset");if(!ue.test(u))throw new m("INVALID_TOKEN","Customer credential required");f(),g=u},subscribe(u){return l.add(u),()=>l.delete(u)},reset(){o||(o=!0,f(),g=void 0,s=null,l.clear())}}}var re=/^gg_sk_[A-Za-z0-9_-]{32,128}$/;function wt(e,n,t="A server API key is required"){if(typeof window<"u")throw new m("SERVER_ONLY",n);if(!re.test(e))throw new m("INVALID_TOKEN",t)}function It(e){let n=Y(e);return n.identify(e.apiKey),n}function $(e){let{customerToken:n,...t}=e;return t}var Tn=e=>!(e instanceof m)||e.status===void 0||e.status>=500||[401,425].includes(e.status)||e.recovery==="recover_operation";function Rn({journal:e,state:n,call:t,processIdentity:s}){let d=null,w=null,f=!1,o={command:null,close:null},g=new Set,i,l=null,u=e?e.load().then(a=>{if(n.disposed)throw new m("IDENTITY_CHANGED","Controller was reset during command restoration");if(l=a,!a)return;if(s){if([a.command,a.closeCommand].some(p=>p&&!Object.hasOwn(a.processBindingIds??{},p.requestId)))throw new m("COMMAND_STORAGE_INVALID","The original process identity is missing");s.restore(a.processBindingIds??{})}if(n.scope&&(a.scope.projectId!==n.scope.projectId||a.scope.environment!==n.scope.environment))throw new m("SCOPE_MISMATCH","Pending command belongs to another scope");if(i=a.purchase,f=a.closed===!0,!a.command)return;let r=a.command;d=r.operation==="close"?null:r,w=r.operation==="close"?r:a.closeCommand?.operation==="close"?a.closeCommand:null,w&&(f=!0);for(let p of[d,w])p&&g.add(p.requestId)}):Promise.resolve();u.catch(()=>{});async function c(a){e&&await u;let r=n.generation;if(e){if(!n.view||!n.scope)throw new m("COMMAND_STORAGE_INVALID","Read the original scoped Run before persisting a mutation");await e.retain({schemaVersion:1,scope:n.scope,runId:n.view.id,funnelId:n.view.source.id,versionId:n.view.source.versionId,command:$(a),...s?{processBindingIds:{[a.requestId]:s.binding(a.requestId)}}:{}})}if(r!==n.generation||d!==a&&w!==a)throw new m("IDENTITY_CHANGED","Run changed before command dispatch");let p=g.has(a.requestId);g.add(a.requestId);try{return await t(a)}catch(v){throw r===n.generation&&(d===a||w===a)&&!p&&!Tn(v)&&(e&&await e.settle(a.requestId),r===n.generation&&L(a)),v}}function h(a){let r=Q.parse(a);if(r.operation==="start"||r.operation==="get"||r.operation==="review")throw new m("INVALID_REQUEST","Mutation required");if(f&&r.operation!=="close"){if(d?.requestId===r.requestId)return N(r.requestId);throw new m("COMMAND_PENDING","Close preserves the original recovery record; settle it by identity")}if(r.operation==="close"){if(d?.requestId===r.requestId)throw new m("INVALID_REQUEST","Close requires its own request identity");if(f=!0,w&&JSON.stringify($(w))!==JSON.stringify($(r)))throw new m("COMMAND_PENDING","Retry the original Close");return w??=r,o.close?o.close:F(w,"close")}if(d){if(JSON.stringify($(d))!==JSON.stringify($(r)))throw new m("COMMAND_PENDING","Retry the original command before sending another");if(o.command)return o.command}else d=r;return F(d,"command")}function F(a,r){let p=c(a);o[r]=p;let v=()=>{o[r]===p&&(o[r]=null)};return p.then(v,v),p}function N(a){return t({operation:"get",settlementRequestId:a})}function L(a){return!a||d!==a&&w!==a?!1:(d===a&&(d=null),w===a&&(w=null),g.delete(a.requestId),!d&&!w&&(l=null),!0)}return{ready:u,get pending(){return d},get closing(){return w},get closeRequested(){return f},get inFlight(){return o.command},get closeFlight(){return o.close},get purchase(){return i},assertBinding(a){if(l&&(a.run.id!==l.runId||a.run.source.id!==l.funnelId||a.run.source.versionId!==l.versionId))throw new m("SCOPE_MISMATCH","Stored command belongs to another Run or Version")},async observe(a,r,p,v){let C=a.operation==="get"?a.settlementRequestId:"requestId"in a&&a.operation!=="start"?a.requestId:void 0,S=C&&r.settlement?.state==="settled"&&r.run.pendingRequest?.requestId!==C&&(a.operation==="get"||!f||a.operation==="close"||!["running","waiting"].includes(r.run.status))?C:void 0,R=d?.requestId===S?d:w?.requestId===S?w:void 0;e?.bind({scope:r.scope,runId:r.run.id,funnelId:r.run.source.id,versionId:r.run.source.versionId});let O=r.run.paywall,D=O??r.purchase,x=D?.operation,k=r.settlement&&(!O||O.purchaseRequestId===r.settlement.requestId)&&(!i||i.operationId===r.settlement.operationId)?r.settlement:void 0,G=x?.operationId??D?.quote?.operationId??k?.operationId,H=D?.receiptId??k?.receiptId,de=O?.selectionGeneration??i?.generation??0;if(e&&G&&H&&a.operation!=="review"&&(!n.view||r.run.revision>=n.view.revision)&&(v===void 0||v>=n.readSequence)&&(!i||de>=i.generation)){let Z={receiptId:H,operationId:G,generation:de},fe=x?.status==="complete"||D?.canReselect===!0;await e.observePurchase({scope:r.scope,runId:r.run.id,funnelId:r.run.source.id,versionId:r.run.source.versionId},Z,fe,S),n.assertCurrent(p),(!i||Z.generation>=i.generation)&&(v===void 0||v>=n.readSequence)&&(fe?i?.operationId===Z.operationId&&(i=void 0):i=Z)}else e&&S&&await e.settle(S);return n.assertCurrent(p),S?L(R):!1},stop(){f=!0},submit:h,settle:N,reset(){f=!0,d=null,w=null,i=void 0,l=null,o.close=null,g.clear(),o.command=null}}}function Cn(e){if(e={...e},typeof e.runToken!="string"||!/^gg_fr_[A-Za-z0-9_-]{43}$/.test(e.runToken))throw new m("INVALID_TOKEN","Run credential required");if(e.serverKey&&(typeof window<"u"||!re.test(e.serverKey)))throw new m("SERVER_ONLY","Run Server-Key proof belongs to the merchant backend");if(e.serverKey&&e.session)throw new m("INVALID_REQUEST","Choose Customer session or Server-Key proof for this Run");let n=Y({...e,session:void 0,timeoutMs:e.timeoutMs??35e3}),t=vn(e.funnelId,e.scope??e.configuration?.scope),s=e.session?.subscribeIdentity(i),d=null,w=e.funnelCommandStorage??(typeof window<"u"&&window.isSecureContext?yn(e):void 0),f=w&&hn(w),o=Rn({journal:f,state:t,call:l,processIdentity:e.process});async function g(r){if(e.process)return e.process.request(r);let p=t.generation;t.assertCurrent(p);let v=performance.now()+(e.timeoutMs??35e3),C=t.customerToken??("customerToken"in r?r.customerToken:void 0);if(e.session){let O=t.signal,D,x=()=>{},k=new Promise((G,H)=>{x=()=>H(O.reason),O.addEventListener("abort",x,{once:!0}),D=setTimeout(()=>H(new m("TIMEOUT","Longplay request timed out")),Math.max(1,v-performance.now()))});try{C=await Promise.race([Promise.resolve().then(()=>(t.assertCurrent(p),e.session.access())),k])}finally{clearTimeout(D),O.removeEventListener("abort",x)}}t.assertCurrent(p);let S={...r,...C?{customerToken:C}:{}},R=r.operation==="page_experiments"?Te.parse(S):Q.parse(S);return n.requestWithCredential("funnels",R,e.runToken,{headers:e.serverKey&&!C?{[nn]:e.serverKey}:void 0,timeoutMs:Math.max(1,v-performance.now())})}function i(){s?.(),t.reset(),o.reset(),d=null,n.dispose()}async function l(r,p){let v=t.generation,C=()=>t.assertCurrent(v);f&&await o.ready,C();let S=t.view,R=be(e,await g(r));if(r.operation==="review"&&!R.review)throw new m("INVALID_RESPONSE","Historical projection is missing");if(C(),R.runToken&&R.runToken!==e.runToken)throw new m("INVALID_RESPONSE","Run credential changed");let O=r.operation==="get"?r.settlementRequestId:"requestId"in r&&r.operation!=="start"?r.requestId:void 0;if(O&&R.settlement?.requestId!==O)throw new m("INVALID_RESPONSE","Exact command settlement is missing or belongs to another command");o.assertBinding(R),t.assertRun(R.run),t.bindScope(R.scope);let D=await o.observe(r,R,v,p);return!R.run.stopped&&["running","waiting"].includes(R.run.status)&&r.operation==="get"&&r.settlementRequestId||(C(),["running","waiting"].includes(R.run.status)||o.stop(),t.publish(r,R,S,p,D)),R}let u=o.submit,c=null,h=new WeakMap;function F(r){let p=h.get(r);if(p)return p;let v=L(r);return h.set(r,v),v}let N=!1;async function L(r){let p=await r;if(p.run.instruction?.type!=="evaluate_segment")return p;if(c)return c;N=!0;let v=t.generation,C=(async()=>{for(let S=0;S<32&&p.run.instruction?.type==="evaluate_segment";S++){if(o.pending||o.closeRequested)return p;let R=p.run;if(p.run.instruction?.type==="evaluate_segment"){let{advance:D}=await De(e.configuration,R,{predict:!1});if(v!==t.generation)throw new m("IDENTITY_CHANGED","Run identity changed during segment calculation");if(o.pending||o.closeRequested)return p;if(t.view&&(t.view.revision!==R.revision||t.view.visit!==R.visit||t.view.nodeId!==R.nodeId))return l({operation:"get"});let x=!0;De(e.configuration,R).then(({prediction:k})=>{x&&v===t.generation&&!o.closeRequested&&t.view?.id===R.id&&!t.view.stopped&&t.view.nodeId===R.nodeId&&t.view.visit===R.visit&&t.view.revision===R.revision&&(d=k)}).catch(()=>{});try{p=await u({operation:"commit_segment",requestId:Xe(R.id,R.visit,`segment:${R.revision}`),nodeId:R.nodeId,visit:R.visit,revision:R.revision,...D})}finally{x=!1,d=null}}}return p})();c=C;try{return await C}finally{c===C&&(c=null)}}let a={get configuration(){return N?e.configuration:void 0},get configurationReady(){return!0},get view(){return t.view?structuredClone(t.view):null},get pendingCommand(){let r=o.closing??o.pending;return r?structuredClone($(r)):null},get pendingCommands(){return[o.pending,o.closing].filter(r=>r!==null).map(r=>structuredClone($(r)))},get pendingPurchase(){return o.purchase?structuredClone(o.purchase):null},get hasDurableJournal(){return f!==void 0},get prediction(){let r=t.view;return d&&r&&!r.stopped&&["running","waiting"].includes(r.status)&&r.id===d.runId&&r.nodeId===d.from.nodeId&&r.visit===d.from.visit&&r.revision===d.from.revision&&!o.closeRequested?structuredClone(d):null},settle:o.settle,get webViewUrl(){return"bundled"},resolvePaywall(r){return Pe(e,r)},async pageExperiments(r,p=[]){let v=t.generation;t.assertCurrent(v);let C=t.view?.id;if(!C)throw new m("INVALID_REQUEST","Read the Run before its page experiments");let S=tn.parse(await g(Te.parse({operation:"page_experiments",release:r,usedReceiptIds:p})));if(t.assertCurrent(v),S.runId!==C||S.scope.projectId!==t.scope?.projectId||S.scope.environment!==t.scope?.environment)throw new m("SCOPE_MISMATCH","Page experiment Run changed");return S},review(r){return l({operation:"review",...r?{receiptId:r}:{}},t.nextRead())},async get(r,p){f&&await o.ready,p??=o.purchase&&{receiptId:o.purchase.receiptId,operationId:o.purchase.operationId};let v=t.nextRead();return F(l({operation:"get",...r?{data:r}:{},...p?{purchase:p}:{}},v))},resume(r=t.view?.pendingRequest?.requestId){return r?o.closeRequested?a.settle(r):o.pending?.requestId===r?F(u(o.pending)):F(u({operation:"resume",requestId:r})):Promise.reject(new m("INVALID_REQUEST","No interrupted command is available"))},submit(r){return F(u(r))},retry(){return o.closeFlight?o.closeFlight:o.closing?u(o.closing):o.closeRequested&&o.pending?a.settle(o.pending.requestId):o.inFlight?F(o.inFlight):o.pending?F(u(o.pending)):Promise.reject(new m("INVALID_REQUEST","No command is pending"))},identify(r){t.identify(r),d=null,n.reset()},subscribe:t.subscribe,reset:i};return a}import{ZodError as _n}from"zod";function bn(e,n,t,s){try{return e.parse(n)}catch(d){throw s&&d instanceof _n?new m(t,s):d}}async function Ee(e,n,t,s={},d){let w=typeof s=="function"?{}:s,f=bn(n.request,t,"INVALID_REQUEST",w.request);try{let o=await e(n.path,f,n.method,d),g=typeof s=="function"?s:s.parseResponse;return g?g(n.response,o):bn(n.response,o,"INVALID_RESPONSE",w.response)}catch(o){throw o instanceof m&&f!==null&&typeof f=="object"&&"requestId"in f&&typeof f.requestId=="string"&&(o.commandRequestId??=f.requestId),o}}async function Ht(e,n){if(!ue.test(n.customerToken))throw new m("INVALID_TOKEN","A verified Customer credential is required");if(e.session&&e.session.peek()!==n.customerToken)throw new m("SCOPE_MISMATCH","Paywall credential does not match the shared session");let t=ne.resolvePaywall.request.parse({funnelId:n.funnelId,funnelVersionId:n.funnelVersionId,selector:n.paywallVersionId?{type:"version",versionId:n.paywallVersionId}:{type:"paywall",paywallId:n.paywallId},commerce:n.commerce,locale:n.locale,...n.requirement?{requirement:n.requirement}:{}}),s=Y(e);e.session||s.identify(n.customerToken);let d=null,w=!1,f=null,o=null,g=null,i=null,l=null,u=null,c=null,h=0;function F(){if(w)throw new m("IDENTITY_CHANGED","Paywall is closed")}async function N(){F();let p=ne.resolvePaywall,v=await Ee(s.request,p,{...t,selector:d?{type:"version",versionId:d.id}:t.selector}),C=await Pe(e,v.paywall);if(F(),n.paywallVersionId?C.id!==n.paywallVersionId:C.paywallId!==n.paywallId)throw new m("INVALID_RESPONSE","The requested Paywall changed");if(d&&(!dn(C,d)||C.paywallId!==d.paywallId))throw new m("INVALID_RESPONSE","The pinned Paywall or Offering Version changed");return d=C,structuredClone(d)}async function L(p){if(F(),i&&p!=="read")throw new m("COMMAND_PENDING","Wait for the original quote");if(!f)throw new m("INVALID_REQUEST","A quoted purchase is required");let v=f;if(p!=="read"){if(c){if(u===p)return c;throw new m("COMMAND_PENDING","Wait for the original purchase command")}if(u&&u!==p)throw new m("COMMAND_PENDING","Read the original purchase before changing an uncertain command");u=p,h++}let C=u,S=h,R=p==="read"&&c===null,O=p==="read"?ne.readSubscriptionOperation:ne.attach,D=(async()=>{let x=await Ee(s.request,O,{operationId:v.operationId,...p==="read"?{}:{intent:p}});return fn(x.operation,{operationId:v.operationId,currency:t.commerce.currency},"The purchase operation changed"),F(),f?.operationId!==v.operationId?structuredClone(x.operation):(o=pn(o,x.operation),(p!=="read"||R&&c===null)&&h===S&&u===C&&(u=null),structuredClone(o))})();if(p!=="read"){c=D;let x=()=>{c===D&&(c=null)};D.then(x,x)}return D}let a={get view(){return d?structuredClone(d):null},get quote(){return f?structuredClone(f):null},get operation(){return o?structuredClone(o):null},get webViewUrl(){return"bundled"},get recovery(){return gn({quote:f,operation:o,requestId:l,pending:i!==null||u!==null,destroyed:w})},get pendingCancellation(){return!w&&u==="cancel"},refresh:N,async preview(p){if(F(),!d)throw new m("INVALID_REQUEST","Load the Paywall first");let v=d.document.buttons[p.actionId];if(v?.type!=="checkout")throw new m("INVALID_REQUEST","Choose an authored purchase action");let C=Ge(v.product,p.selection,d.capabilities);if(!C)throw new m("PRODUCT_UNAVAILABLE","Choose an available Product");let S=He(d.document.screen,C,p.selection,d.capabilities),R=ne.previewAttach.request.parse({funnelId:t.funnelId,funnelVersionId:t.funnelVersionId,requestId:p.requestId,plans:[{productVersionId:C,...Object.keys(S).length?{featureQuantities:S}:{}}],provider:t.commerce.provider,currency:t.commerce.currency,...p.offerId?{offerId:p.offerId}:{},...p.nativeOffer?{nativeOffer:p.nativeOffer}:{}}),O=JSON.stringify(R);if(g&&g!==O&&(i||u||!o||o.status==="pending"))throw new m("COMMAND_PENDING","Finish or cancel the original purchase before changing it");if(g===O){if(i)return i;if(f)return structuredClone(f)}g!==O&&(f=null,o=null),g=O,l=R.requestId;let D=(async()=>{let x=ne.previewAttach,k=await Ee(s.request,x,R);return F(),mn(k.quote,{productVersionId:C,featureQuantities:S,currency:t.commerce.currency,provider:t.commerce.provider},"The purchase quote changed its selected Product or presentment"),f=k.quote,o=null,structuredClone(f)})();i=D;try{return await D}finally{i===D&&(i=null)}},confirm:()=>L("confirm"),cancel:()=>L("cancel"),read:()=>L("read"),destroy(){w||(w=!0,r?.(),s.dispose(),d=null,f=null,o=null,g=null,l=null)}},r=e.session?.subscribeIdentity(a.destroy);try{return await N(),a}catch(p){throw a.destroy(),p}}import{z as Vn}from"zod";import{z as ge}from"zod";var Dn=ge.record(ge.string().regex(/^[a-f0-9]{64}$/),ge.strictObject({at:ge.number(),text:ge.string()})),oe=2*1048576,xn=100;function Ln(){try{return typeof window>"u"?void 0:window.localStorage}catch{return}}function Pn(e,n){let t=n===void 0?Ln():n,s=new Map,d=0,w=!1,f=!1,o,g;async function i(u){if(!t)return null;let c;try{let h=await Promise.race([Promise.resolve().then(()=>t.getItem(u)),new Promise(F=>{c=setTimeout(()=>F(null),xn)})]);return typeof h=="string"&&h.length<=oe&&new TextEncoder().encode(h).byteLength<=oe?h:null}catch{return null}finally{clearTimeout(c)}}function l(){if(g)return g;let u=(async()=>{try{let c=await i(`${e}:artifacts`);if(c)return Dn.parse(JSON.parse(c))}catch{}return{}})();return g=u,u.finally(()=>{g===u&&(g=void 0)}),u}return{async readManifest(){return i(e)},writeManifest(u){!t||u.length>oe||new TextEncoder().encode(u).byteLength>oe||(o=u,!f&&(f=!0,Promise.resolve().then(async()=>{try{for(;o!==void 0;){let c=o;try{await t.setItem(e,c)}catch{}o===c&&(o=void 0)}}finally{f=!1}})))},async readArtifact(u){let c=(await l())[u],h=Date.now();return c&&h>=c.at&&h-c.at<=J.retentionMs?c.text:void 0},writeArtifact(u,c){if(!t||c.length>oe)return;let h=s.get(u);if(h?.text===c||!h&&s.size>=128)return;let F=new TextEncoder().encode(c).byteLength;d-(h?.byteLength??0)+F>oe||(s.set(u,{text:c,byteLength:F}),d+=F-(h?.byteLength??0),!w&&(w=!0,Promise.resolve().then(async()=>{try{for(;s.size;){let N=new Map(s);try{let L={...await l()},a=Date.now();for(let[C,S]of N)L[C]={at:a,text:S.text};let r={},p=2,v=0;for(let[C,S]of Object.entries(L).sort(([,R],[,O])=>O.at-R.at)){if(S.at>a||a-S.at>J.retentionMs)continue;let R=new TextEncoder().encode(JSON.stringify({[C]:S})).byteLength;p+R>oe||v>=128||(r[C]=S,p+=R,v++)}await t.setItem(`${e}:artifacts`,JSON.stringify(r))}catch{}finally{for(let[L,a]of N)s.get(L)===a&&(s.delete(L),d-=a.byteLength)}}}finally{w=!1}})))}}}var E=(e,n)=>new m(e,n),W=()=>performance.now(),Sn=e=>{typeof e=="object"&&"unref"in e&&e.unref()};function rr(e){let n=Ke.parse(e.scope),t=new te(e.origin??le);if(t.username||t.password||t.search||t.hash||t.pathname!=="/"||t.protocol!=="https:"&&!(t.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(t.hostname)))throw E("INVALID_URL","Configuration requires a trusted HTTPS origin");let s=new Set([t.origin,...(e.assetOrigins??[]).map(I=>{let y=new te(I);if(y.protocol!=="https:"||y.username||y.password||y.search||y.hash||y.pathname!=="/")throw E("INVALID_URL","Invalid configuration asset origin");return y.origin})]),d=e.fetch??globalThis.fetch.bind(globalThis),w=`/api/v1/configuration/${n.environmentId}`,f=`indiana:configuration:1:${t.origin}:${M(n)}`,o=Pn(f,e.storage),g,i=0,l=0,u=!1,c=!1,h=0,F=0,N,L,a,r,p=0,v=new Set,C=new Set,S=new Map,R=new Map,O=0,D=!1;function x(){for(let I of v)try{I()}catch{}}function k(I){try{e.onError?.(I)}catch{}}let G=()=>!c&&!u&&!!g&&W()<i&&Date.now()<l;function H(){if(!G())throw E("CONFIGURATION_EXPIRED","Refresh configuration before using it")}function de(I,y,b){if(!S.has(I)){for(;S.size&&(S.size>=128||O+b>J.maxCacheBytes);){let P=S.entries().next().value;O-=P[1].byteLength,S.delete(P[0])}S.set(I,{text:y,byteLength:b}),O+=b}}function Z(I,y,b){return cn(I,y,{signal:b,error:P=>E("INVALID_RESPONSE",P==="missing"?"Configuration body is missing":"Configuration exceeds its byte limit")})}function fe(I){let y=new te(I,t);if(!s.has(y.origin)||y.username||y.password||y.hash||y.search)throw E("INVALID_URL","Configuration artifact origin is not trusted");return y.href}async function Fe(I,y,b=!1){let P=await d(fe(I),{method:"GET",credentials:"omit",redirect:"error",cache:b?"default":"no-cache",signal:y,headers:{}});if(P.status===429){let T=P.headers.get("retry-after")??"";p=/^\d+$/.test(T)?Number(T)*1e3:Math.max(0,Date.parse(T)-Date.now())||15e3}if(!P.ok&&P.status!==304)throw E(`CONFIGURATION_HTTP_${P.status}`,"Configuration synchronization failed");return P}function Fn(I,y,b){let P=Date.parse(I.headers.get("x-indiana-config-validated-at")??""),T=Date.parse(I.headers.get("x-indiana-config-valid-until")??""),_=Date.parse(I.headers.get("date")??""),A=I.headers.get("age"),B=A!==null&&/^\d+(\.\d+)?$/.test(A)?Number(A)*1e3:NaN;if(![P,T,_,B].every(Number.isFinite)||T<=P||T-P>J.maxControlAgeMs||P>_+1e3)throw E("INVALID_RESPONSE","Configuration freshness evidence is invalid");let V=Math.min(T-P,b.maxControlAgeSeconds*1e3,J.maxControlAgeMs)-Math.max(B,_-P,0)-(W()-y);if(V<=0)throw E("CONFIGURATION_EXPIRED","Configuration validation expired in transit");return W()+V}function Ae(){if(clearTimeout(a),clearTimeout(r),c||!v.size)return;G()&&(r=setTimeout(()=>{G()?Ae():x()},Math.max(1,i-W())),Sn(r));let I=F?Math.min(15e3,1e3*2**Math.min(F-1,4)):Math.min(15e3,(g?.policy.refreshIntervalSeconds??15)*1e3);a=setTimeout(()=>{ie().catch(k)},Math.max(p,I*(.8+Math.random()*.2))),Sn(a)}async function ie(){if(c)throw E("CONFIGURATION_DISPOSED","Configuration manager was destroyed");if(N)return N;let I=h,y=new AbortController;L=y;let b=(async()=>{if(!D){D=!0;try{let he=await o.readManifest();if(he&&!g){let K=Oe.parse(JSON.parse(he));M(K.scope)===M(n)&&(g=K)}}catch{}}y.signal.throwIfAborted();let A=g,B=W(),q=await Fe(w,y.signal);q.status===304&&(!A||!q.headers.has("x-indiana-config-validated-at")||!q.headers.has("x-indiana-config-valid-until")||!q.headers.has("age"))&&(q=await Fe(w,y.signal));let V=q.status===304?A:Oe.parse(JSON.parse(await Z(q,J.maxManifestBytes,y.signal))),{generation:ae,...se}=V,z=q.headers.get("etag");if(M(V.scope)!==M(n)||Qe(se)!==ae||z!==`"${ae}"`&&z!==`W/"${ae}"`)throw E("INVALID_RESPONSE","Configuration scope or content identity changed");if(A&&(V.revision<A.revision||V.revision===A.revision&&V.generation!==A.generation))throw E("INVALID_RESPONSE","Configuration revision moved backwards or changed identity");for(let[he,K]of Object.entries(A?.funnels??{})){let ee=V.funnels[he];if(ee&&(ee.controlRevision<K.controlRevision||ee.evaluationRevision<K.evaluationRevision||ee.controlRevision===K.controlRevision&&ee.state!==K.state||ee.evaluationRevision===K.evaluationRevision&&ee.evaluationMode!==K.evaluationMode))throw E("INVALID_RESPONSE","Funnel control revision changed identity")}let X=Fn(q,B,V.policy);if(y.signal.throwIfAborted(),I!==h)throw E("CONFIGURATION_DISPOSED","Configuration scope changed");return g=V,i=X,l=Date.now()+Math.max(0,X-W()),u=!1,F=0,p=0,o.writeManifest(M(V)),x(),structuredClone(V)})(),P=setTimeout(()=>y.abort(E("CONFIGURATION_UNAVAILABLE","Configuration initialization timed out")),J.initializationMs),T=new Promise((A,B)=>y.signal.addEventListener("abort",()=>B(y.signal.reason),{once:!0})),_=Promise.race([b,T]).catch(A=>{throw F++,(A instanceof Vn.ZodError||A instanceof SyntaxError||A instanceof m&&["CONFIGURATION_HTTP_404","CONFIGURATION_HTTP_410","INVALID_RESPONSE"].includes(A.code))&&(i=0,u=!0,x()),A}).finally(()=>{clearTimeout(P),N===_&&(N=void 0),Ae()});return N=_,_}async function ye(I){let y=I.sha256,b=se=>Ce(se,I);fe(I.url);let P=S.get(y);if(P){if(P.byteLength!==I.byteLength)throw E("INVALID_RESPONSE","Configuration artifact digest or size mismatch");return S.delete(y),S.set(y,P),P.text}let T=R.get(y);if(T){if(T.byteLength!==I.byteLength)throw E("INVALID_RESPONSE","Configuration artifact digest or size mismatch");return T.promise}let _=new AbortController;C.add(_);let A=h,B=(async()=>{try{let X=await o.readArtifact(y);if(X&&b(X)){if(_.signal.throwIfAborted(),c||A!==h)throw E("CONFIGURATION_DISPOSED","Configuration scope changed");return de(y,X,I.byteLength),X}}catch{}_.signal.throwIfAborted();let se=await Fe(I.url,_.signal,!0),z=await Z(se,I.byteLength,_.signal);if(!b(z))throw E("INVALID_RESPONSE","Configuration artifact digest or size mismatch");if(c||A!==h)throw E("CONFIGURATION_DISPOSED","Configuration scope changed");return de(y,z,I.byteLength),o.writeArtifact(y,z),z})(),q=setTimeout(()=>_.abort(E("CONFIGURATION_UNAVAILABLE","Configuration artifact timed out")),J.initializationMs),V=new Promise((se,z)=>_.signal.addEventListener("abort",()=>z(_.signal.reason),{once:!0})),ae=Promise.race([B,V]).finally(()=>{clearTimeout(q),C.delete(_),R.delete(y)});return R.set(y,{promise:ae,byteLength:I.byteLength}),ae}async function we(){return G()||await ie(),H(),g}async function me(I){let y,b=new Promise((P,T)=>{y=setTimeout(()=>T(E("CONFIGURATION_UNAVAILABLE","Configuration initialization timed out")),J.initializationMs)});try{return await Promise.race([I(),b])}finally{clearTimeout(y)}}function pe(I,y){if(H(),g?.generation!==I.generation)throw E("CONFIGURATION_CHANGED","Configuration changed while preparing a snapshot");if(y&&g.funnels[y]?.state!=="active")throw E("FUNNEL_STOPPED","Funnel is paused or unavailable")}async function xe(I){let y=I.gb.features;if(!y)throw E("CONFIGURATION_UNAVAILABLE","Public Feature delivery is disabled");let b=I.artifacts[y];if(b.formatVersion!==1)throw E("UNSUPPORTED_SCHEMA","Unsupported public GB configuration format");let P=Je.parse(JSON.parse(await ye(b)));if(M(P.scope)!==M({projectId:n.projectId,environment:n.environment})||P.generation!==b.generation||P.remoteFeatures.some(T=>Object.hasOwn(P.features,T)))throw E("INVALID_RESPONSE","Public GB configuration scope or generation is invalid");return pe(I),{...P,evaluatedAt:new Date().toISOString(),expiresAt:new Date(Date.now()+Math.max(0,i-W())).toISOString()}}async function Le(I,y){let b=await we(),P=b.funnels[I];y&&(!P||P.evaluationMode==="local"&&!P.versions[y])&&(N&&await N,b=await ie()),pe(b,I);let T=b.funnels[I];if(T.evaluationMode!=="local")throw E("EVALUATION_MODE","This Funnel executes at Longplay; public graph loading is disabled");let _=y??T.currentVersionId,A=T.versions[_];if(!A)throw E("CONFIGURATION_UNAVAILABLE","Pinned Funnel Version is unavailable");if(b.artifacts[A.artifact].formatVersion!==3)throw E("UNSUPPORTED_SCHEMA","Unsupported public Funnel format");let[B,q]=await Promise.all([ye(b.artifacts[A.artifact]).then(V=>$e(JSON.parse(V))),T.evaluationMode==="local"?xe(b):void 0]);if(q&&M(Ye(B,q))!==M(A.dependencies))throw E("INVALID_RESPONSE","Funnel and GB dependency contract do not match");return pe(b,I),{document:B,growth:q,versionId:_,control:structuredClone(T),manifest:structuredClone(b)}}async function Ve(I,y){try{return await Le(I,y)}catch(b){if(!(b instanceof m)||!(b.code==="CONFIGURATION_CHANGED"||b.code==="CONFIGURATION_HTTP_404"&&G()))throw b;let P=g?.generation;if(N&&await N,await ie(),b.code!=="CONFIGURATION_CHANGED"&&g?.generation===P)throw b;return Le(I,y)}}function Ne(){u=!0,x(),ie().catch(k)}let Ie=()=>{(typeof document>"u"||document.visibilityState==="visible")&&Ne()};function An(I){if(c)throw E("CONFIGURATION_DISPOSED","Configuration manager was destroyed");return v.add(I),v.size===1&&(typeof window<"u"&&(window.addEventListener("online",Ne),window.addEventListener("focus",Ie),document.addEventListener("visibilitychange",Ie)),Ae()),()=>{v.delete(I),v.size||(clearTimeout(a),clearTimeout(r),Me())}}function Me(){typeof window<"u"&&(window.removeEventListener("online",Ne),window.removeEventListener("focus",Ie),document.removeEventListener("visibilitychange",Ie))}return{scope:Object.freeze({...n}),refresh:ie,subscribe:An,assertFresh:H,assertFeatures(I){H();let y=g.gb.features;if(!y)throw E("CONFIGURATION_UNAVAILABLE","Public Feature delivery is disabled");if(I!==void 0&&g.artifacts[y].generation!==I)throw E("CONFIGURATION_CHANGED","Refresh changed Feature configuration before evaluation")},get fresh(){return G()},get snapshot(){return g?structuredClone(g):null},get remainingMs(){return G()?Math.max(0,i-W()):0},async features(){return me(async()=>xe(await we()))},pageExperiments:()=>me(async()=>{let I=await we(),y=I.gb.pageExperiments;if(!y)throw E("CONFIGURATION_UNAVAILABLE","Public page experiments are disabled");let b=I.artifacts[y];if(b.formatVersion!==1)throw E("UNSUPPORTED_SCHEMA","Unsupported page experiment format");let P=an.parse(JSON.parse(await ye(b)));if(P.environmentId!==n.environmentId||P.generation!==b.generation)throw E("INVALID_RESPONSE","Page experiment scope or generation changed");return pe(I),P}),funnel:(I,y)=>me(()=>Ve(I,y)),paywall:(I,y)=>me(async()=>{let b=await we(),P=b.paywalls?.[I];if(!P||!y&&P.state!=="published")throw E("PAYWALL_UNAVAILABLE","Published Paywall is unavailable");let T=y??P.currentVersionId,_=P.versions[T],A=_&&b.artifacts[_.artifact];if(!A||A.kind!=="paywall"||A.formatVersion!==1)throw E("UNSUPPORTED_SCHEMA","Public Paywall format is unavailable");let B=ze.parse(JSON.parse(await ye(A)));return pe(b),{document:B,versionId:T,version:_.version,control:structuredClone(P),manifest:structuredClone(b)}}),async localFunnel(I,y){let b=await me(()=>Ve(I,y));if(!b.growth)throw E("EVALUATION_MODE","This Funnel requires remote execution");let{analyticsConfig:P,remoteFeatures:T,..._}=b.growth;return on({scope:{projectId:n.projectId,environment:n.environment},funnelId:I,versionId:b.versionId,evaluationMode:"local",evaluationRevision:b.control.evaluationRevision,document:b.document,payload:_})},assertFunnel(I,y,b){H();let P=g.funnels[I];if(!P||P.state!=="active")throw E("FUNNEL_STOPPED","Funnel is paused or unavailable");if(P.evaluationMode!=="local")throw E("EVALUATION_MODE","This Funnel now executes at Longplay");if(y!==void 0&&P.controlRevision!==y)throw E("RUN_RECONCILIATION_REQUIRED","Reconcile the original Run after a control change");if(b!==void 0&&!P.versions[b])throw E("CONFIGURATION_UNAVAILABLE","Pinned Funnel Version is unavailable")},destroy(){if(!c){c=!0,h++,i=0,L?.abort(E("CONFIGURATION_DISPOSED","Configuration manager was destroyed")),clearTimeout(a),clearTimeout(r),Me(),x(),v.clear();for(let I of C)I.abort(E("CONFIGURATION_DISPOSED","Configuration manager was destroyed"));S.clear(),O=0}}}}function En(e){let n=ue.test(e.apiKey);if(typeof window<"u"&&!n)throw new m("SERVER_ONLY","Funnel starts are issued by your backend");if(!n&&!re.test(e.apiKey))throw new m("INVALID_TOKEN","A customer credential or server API key is required");return{async start(t){let s=Q.safeParse({...t,operation:"start"});if(!s.success||s.data.operation!=="start"||(n?s.data.customer!==void 0:s.data.customer===void 0))throw new m("INVALID_REQUEST","Invalid current Funnel start");let d=s.data,w=Y({...e,timeoutMs:e.timeoutMs??35e3});try{e.session||w.identify(e.apiKey);let f=be(e,await w.request("funnels",d));if(!f.runToken)throw new m("INVALID_RESPONSE","Funnel start credentials are missing");if(f.run.source.id!==d.funnelId||f.run.locale!==(d.locale??"en")||!ce(f.run.parameters,d.parameters??{})||(d.customer?!f.customerId||d.customer.type==="id"&&f.customerId!==d.customer.value:f.customerId!==void 0))throw new m("INVALID_RESPONSE","Funnel start contract changed");return{...f,runToken:f.runToken}}finally{w.dispose()}}}}async function yr(e){e={...e};let n=e.configuration;if(!n)throw new m("CONFIGURATION_UNAVAILABLE","Local conditions require public configuration");let t={projectId:n.scope.projectId,environment:n.scope.environment};if(e.scope&&M(t)!==M(e.scope))throw new m("SCOPE_MISMATCH","Configuration and transport scopes differ");if((await n.funnel(e.funnelId)).control.evaluationMode!=="local")throw new m("EVALUATION_MODE","This Funnel uses Remote evaluation");let d=re.test(e.credential);if(d?!e.customerId:e.customerId!==void 0)throw new m("INVALID_REQUEST","Only Server-Key starts name their Customer");let w=En({...e,scope:t,apiKey:e.credential}),f=o=>{let g=Cn({...e,scope:t,runToken:o,...d?{serverKey:e.credential}:{}});return d||g.identify(e.credential),g};return{async start(o){let g=await w.start({...o,funnelId:e.funnelId,...d?{customer:{type:"id",value:e.customerId}}:{}}),i=f(g.runToken),l=await i.get();return{...g,...l,controller:i}},async restore(o){let g=f(o),i=await g.get();if(i.run.source.id!==e.funnelId)throw g.reset(),new m("SCOPE_MISMATCH","Run belongs to another Funnel");return{...i,runToken:o,controller:g}}}}export{Ee as a,qn as b,be as c,_e as d,et as e,On as f,yn as g,ct as h,ce as i,wt as j,It as k,Cn as l,Ht as m,rr as n,En as o,yr as p};