@everframe/react-native 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  // SPDX-FileCopyrightText: 2026 ScriptX
3
3
  //
4
- // Plan 06.2-11 — RCTEventEmitter subclass for the phone-companion bridge.
4
+ // RCTEventEmitter subclass for the bridge's native → JS events (today: the
5
+ // extra-resolver ask, spec 2026-09-17).
5
6
  //
6
7
  // iOS RN event emission requires an `RCTEventEmitter` subclass (one per
7
8
  // module — the base class enforces a single supportedEvents() list). We
@@ -23,63 +24,20 @@
23
24
  // Objective-C base.
24
25
  //
25
26
  // Threading: `sendEvent(withName:body:)` is thread-safe across the RN core
26
- // (the internal bridge enqueues the event on the JS thread). Combine sinks
27
- // installed in `EverframeBridge` may fire on the URLSession delegate queue;
28
- // we forward straight to the emitter without a main-thread hop.
27
+ // (the internal bridge enqueues the event on the JS thread); we forward
28
+ // straight to the emitter without a main-thread hop.
29
29
  //
30
- // Event names — duplicated in JS facade `src/companion.ts`. Keep in lock-step.
30
+ // Event names — duplicated in the JS facade (`src/runtime.ts`). Keep in
31
+ // lock-step.
31
32
  import Foundation
32
33
  import React
33
34
 
34
35
  @objc(EverframeEventEmitter)
35
36
  public final class EverframeEventEmitter: RCTEventEmitter {
36
37
 
37
- /// Event name forwarded as `everframe.companion.state`.
38
- /// Payload: String — one of "unpaired" | "paired" | "report_in_progress" | "phone_disconnected".
39
- public static let stateEvent = "everframe.companion.state"
40
-
41
- /// Event name forwarded as `everframe.companion.pairUrl`.
42
- /// Payload: String | NSNull (NSNull crosses to JS as `null`).
43
- public static let pairUrlEvent = "everframe.companion.pairUrl"
44
-
45
- /// Event name forwarded as `everframe.companion.code`.
46
- /// The short display code returned by `/api/companion/announce`
47
- /// (spec 2026-08-07) — hosts render it beside the QR so a team member
48
- /// reading the TV screen can pick this device out of the dashboard list.
49
- /// Payload: String | NSNull (NSNull crosses to JS as `null`).
50
- public static let codeEvent = "everframe.companion.code"
51
-
52
- /// Event name forwarded as `everframe.companion.attachedUserName`.
53
- /// The dashboard member who attached to this device; nil on an ordinary
54
- /// QR bond. Payload: String | NSNull (NSNull crosses to JS as `null`).
55
- public static let attachedUserNameEvent = "everframe.companion.attachedUserName"
56
-
57
- /// Event name forwarded as `everframe.companion.resolvedName` (naming spec
58
- /// 2026-08-24). The server-resolved device display name for THIS device
59
- /// (e.g. an org-configured friendly name), or nil before the first
60
- /// successful announce / when discovery never ran. Payload: String |
61
- /// NSNull (NSNull crosses to JS as `null`).
62
- public static let resolvedNameEvent = "everframe.companion.resolvedName"
63
-
64
- /// Event name forwarded as `everframe.companion.attachChallenge` (spec
65
- /// 2026-08-19). The pending dashboard-initiated attach-PIN challenge, or
66
- /// nil when none is outstanding. Forwarded in every `attachPinUi` mode,
67
- /// including `'builtin'` (which renders the PIN natively AND still
68
- /// fires this event) — it's only NEEDED by hosts configured with
69
- /// `'custom'`, which must read it to build their own surface.
70
- /// Payload: `{ code, requestedByName, ttlMs }` | NSNull.
71
- public static let attachChallengeEvent = "everframe.companion.attachChallenge"
72
-
73
- /// Fired when a `report.request` arrives from the paired phone. The event
74
- /// and the bridge's brief wait are the companion's JS-ready handshake
75
- /// (see CompanionCaptureBridge.awaitJsReactTreeAttach).
76
- /// Payload: String — the correlation_id of the inbound request.
77
- public static let reportRequestedEvent = "everframe.companion.reportRequested"
78
-
79
38
  /// Fired right before native drains pending attachments for ANY report
80
- /// (spec 2026-09-17 setExtra-resolver) — NOT just the companion flow:
81
- /// the plain in-app `openReporter()` and native shake both trigger this
82
- /// too, since both funnel through `Everframe.shared.report.open()` →
39
+ /// (spec 2026-09-17 setExtra-resolver): the plain in-app `openReporter()`
40
+ /// and native shake both trigger this, since both funnel through `Everframe.shared.report.open()` →
83
41
  /// `__consumePendingAttachments()`. Only fires when JS has a resolver
84
42
  /// CURRENTLY registered (`EverframeBridge.setExtraResolverActive`) — see
85
43
  /// `EverframeBridge.awaitJsExtraResolve`. Payload: String — the
@@ -111,89 +69,14 @@ public final class EverframeEventEmitter: RCTEventEmitter {
111
69
  /// adding it here is the exact failure this comment exists to prevent.
112
70
  public override func supportedEvents() -> [String] {
113
71
  return [
114
- Self.stateEvent,
115
- Self.pairUrlEvent,
116
- Self.codeEvent,
117
- Self.attachedUserNameEvent,
118
- Self.resolvedNameEvent,
119
- Self.attachChallengeEvent,
120
- Self.reportRequestedEvent,
121
72
  Self.extraResolveRequestedEvent,
122
73
  ]
123
74
  }
124
75
 
125
76
  // MARK: - Static helpers used by EverframeBridge
126
77
 
127
- /// Forward a companion-state change to JS. Silently dropped if no
128
- /// emitter instance is alive (e.g. before any listeners attached). The
129
- /// RN base class also warns when `sendEvent` fires with zero listeners,
130
- /// which is the documented behavior — our JS facade attaches listeners
131
- /// inside `useCompanion()`, so the warning surfaces only when no React
132
- /// subtree is rendering the companion screen.
133
- @objc public static func sendState(_ state: String) {
134
- shared?.sendEvent(withName: stateEvent, body: state)
135
- }
136
-
137
- /// Forward a pairUrl change to JS. `nil` is passed across the bridge as
138
- /// `NSNull()` so the JS handler receives an actual `null`. Note: pairUrl is
139
- /// now nulled only on socket close, so this `nil` branch fires rarely —
140
- /// hosts drive QR teardown off `state`, the reliably-delivered signal.
141
- @objc public static func sendPairUrl(_ url: String?) {
142
- if let url = url {
143
- shared?.sendEvent(withName: pairUrlEvent, body: url)
144
- } else {
145
- shared?.sendEvent(withName: pairUrlEvent, body: NSNull())
146
- }
147
- }
148
-
149
- /// Forward an announce display-code change to JS. `nil` crosses as
150
- /// `NSNull()` so the JS handler receives an actual `null` — that happens
151
- /// when companion discovery was never attempted (no SDK key configured),
152
- /// when the announce failed, or when the relay socket closed terminally.
153
- @objc public static func sendCode(_ code: String?) {
154
- if let code = code {
155
- shared?.sendEvent(withName: codeEvent, body: code)
156
- } else {
157
- shared?.sendEvent(withName: codeEvent, body: NSNull())
158
- }
159
- }
160
-
161
- /// Forward an attached-dashboard-user change to JS. `nil` crosses as
162
- /// `NSNull()` — an ordinary QR bond carries no `companion_user` block, so
163
- /// the nil branch is the common case here (unlike `sendPairUrl`).
164
- @objc public static func sendAttachedUserName(_ name: String?) {
165
- if let name = name {
166
- shared?.sendEvent(withName: attachedUserNameEvent, body: name)
167
- } else {
168
- shared?.sendEvent(withName: attachedUserNameEvent, body: NSNull())
169
- }
170
- }
171
-
172
- /// Forward a resolved device display-name change to JS (naming spec
173
- /// 2026-08-24). `nil` crosses as `NSNull()` — before the first successful
174
- /// announce, or when discovery never ran, this is the common case.
175
- @objc public static func sendResolvedName(_ name: String?) {
176
- if let name = name {
177
- shared?.sendEvent(withName: resolvedNameEvent, body: name)
178
- } else {
179
- shared?.sendEvent(withName: resolvedNameEvent, body: NSNull())
180
- }
181
- }
182
-
183
- /// Forward a `report.request` correlation id to JS. JS signals the
184
- /// bridge back via `signalCompanionReportRequestReady` when it is
185
- /// ready for capture to proceed.
186
- @objc public static func sendReportRequested(_ correlationId: String) {
187
- shared?.sendEvent(withName: reportRequestedEvent, body: correlationId)
188
- }
189
-
190
- /// Forward an attach-PIN challenge to JS. nil crosses as NSNull() → JS null.
191
- @objc public static func sendAttachChallenge(_ payload: [String: Any]?) {
192
- shared?.sendEvent(withName: attachChallengeEvent, body: payload ?? NSNull())
193
- }
194
-
195
78
  /// Forward an extra-resolver ask correlation id to JS (spec 2026-09-17
196
- /// setExtra-resolver). Mirrors `sendReportRequested` exactly — JS signals
79
+ /// setExtra-resolver). JS signals
197
80
  /// the bridge back via `signalExtraResolverReady` when it has pushed a
198
81
  /// freshly resolved value (or given up) for this correlation id.
199
82
  @objc public static func sendExtraResolveRequested(_ correlationId: String) {
@@ -187,32 +187,11 @@ RCT_EXPORT_MODULE(Everframe)
187
187
  BOOL installIdentifierDisabled = opts.installIdentifierDisabled().value_or(false);
188
188
  // `crashReportingDisabled` — same `std::optional<bool>` shape. Absent keeps capture on.
189
189
  BOOL crashReportingDisabled = opts.crashReportingDisabled().value_or(false);
190
- // `attachPinUi` (spec 2026-08-19) is a plain optional STRING field —
191
- // `opts.attachPinUi()` returns a nullable NSString*, same shape as
192
- // `opts.sdkKey()` above, NOT the `std::optional<bool>` shape
193
- // `networkBodiesDisabled()` uses. `EverframeBridge.configure` coerces a
194
- // nil/unrecognised value to `.builtin`.
195
- NSString *attachPinUi = opts.attachPinUi();
196
- // `companionDeviceId` (naming spec 2026-08-24) is a plain optional STRING
197
- // field — same nullable-NSString* shape as `attachPinUi` above, not the
198
- // `std::optional<bool>` shape `networkBodiesDisabled()` uses.
199
- NSString *companionDeviceId = opts.companionDeviceId();
200
- // `companionBadgeEnabled`/`companionBadgePosition` (naming spec
201
- // 2026-08-24, controller ruling / Task 6b) — flat fields on ConfigOpts;
202
- // RN codegen cannot express the nested `{enabled, position}` shape the JS
203
- // facade's `RuntimeConfig.companionBadge` uses, so `extractBridgeConfig`
204
- // flattens it before it crosses. `companionBadgeEnabled()` is
205
- // `std::optional<bool>`, same shape as `networkBodiesDisabled()` above;
206
- // absent defaults to `true` (badge shown), matching
207
- // `CompanionBadgeOptions.enabled`'s own default. `companionBadgePosition()`
208
- // is a nullable NSString*, same shape as `attachPinUi`/`companionDeviceId`
209
- // above; `EverframeBridge` coerces nil/unrecognised to `.bottomRight`.
210
- BOOL companionBadgeEnabled = opts.companionBadgeEnabled().value_or(true);
211
190
  BOOL shakeToReportEnabled = opts.shakeToReportEnabled().value_or(true);
191
+ BOOL quickCaptureEnabled = opts.quickCaptureEnabled().value_or(true);
212
192
  // Crash-only session switch (spec 2026-10-12) — `std::optional<bool>`, same shape as
213
193
  // `networkBodiesDisabled()`. Absent means a normal report session.
214
194
  BOOL reporterDisabled = opts.reporterDisabled().value_or(false);
215
- NSString *companionBadgePosition = opts.companionBadgePosition();
216
195
  // Inline reporter theme (reporter branding spec 2026-08-25, RN slice) —
217
196
  // 8 flat optional STRING fields on ConfigOpts (RN codegen cannot express
218
197
  // the nested `theme: { … }` shape the JS facade's `RuntimeConfig.theme`
@@ -253,11 +232,8 @@ RCT_EXPORT_MODULE(Everframe)
253
232
  networkBodiesDisabled:networkBodiesDisabled
254
233
  installIdentifierDisabled:installIdentifierDisabled
255
234
  crashReportingDisabled:crashReportingDisabled
256
- attachPinUi:attachPinUi
257
- companionDeviceId:companionDeviceId
258
- companionBadgeEnabled:companionBadgeEnabled
259
235
  shakeToReportEnabled:shakeToReportEnabled
260
- companionBadgePosition:companionBadgePosition
236
+ quickCaptureEnabled:quickCaptureEnabled
261
237
  theme:(theme.count > 0 ? theme : nil)
262
238
  vitalsEnabled:vitalsEnabled
263
239
  vitalsSampleRate:vitalsSampleRate
@@ -389,8 +365,7 @@ RCT_EXPORT_MODULE(Everframe)
389
365
  [EverframeBridge setExtraResolverActive:active];
390
366
  }
391
367
 
392
- // JS handshake ack — mirrors `signalCompanionReportRequestReady` below
393
- // exactly. Releases `EverframeBridge.awaitJsExtraResolve`'s bounded wait for
368
+ // JS handshake ack. Releases `EverframeBridge.awaitJsExtraResolve`'s bounded wait for
394
369
  // this correlation id.
395
370
  - (void)signalExtraResolverReady:(NSString *)correlationId {
396
371
  [EverframeBridge signalExtraResolverReady:(correlationId ?: @"")];
@@ -560,33 +535,10 @@ RCT_EXPORT_MODULE(Everframe)
560
535
  return @([EverframeBridge captureHandledException:(crashJson ?: @"")]);
561
536
  }
562
537
 
563
- // MARK: - startCompanion / stopCompanion (Plan 06.2-11)
564
-
565
- // Opens a relay WS connection against the build-time-baked ingest URL
566
- // (sdk-ios IngestEndpoint.url) and starts forwarding `Everframe.shared
567
- // .companion` signals (state + pairUrl) to JS via the
568
- // `EverframeEventEmitter` RCTEventEmitter subclass.
569
- - (void)startCompanion {
570
- [EverframeBridge startCompanion:@""];
571
- }
572
-
573
- - (void)stopCompanion {
574
- [EverframeBridge stopCompanion];
575
- }
576
-
577
- // MARK: - signalCompanionReportRequestReady(correlationId)
578
-
579
- // Companion handshake: JS calls this when it is ready for capture to
580
- // proceed, releasing the native bridge's bounded wait
581
- // (CompanionCaptureBridge.awaitJsReactTreeAttach).
582
- - (void)signalCompanionReportRequestReady:(NSString *)correlationId {
583
- [EverframeBridge signalCompanionReportRequestReady:(correlationId ?: @"")];
584
- }
585
-
586
538
  // MARK: - addListener / removeListeners (RN NativeEventEmitter contract)
587
539
  //
588
540
  // These are intentional no-ops on `EverframeModule` — the JS facade
589
- // (`src/companion.ts`) constructs `NativeEventEmitter(NativeModules
541
+ // (`src/events.ts`) constructs `NativeEventEmitter(NativeModules
590
542
  // .EverframeEventEmitter)`, NOT NativeModules.Everframe, so the real
591
543
  // addListener/removeListeners traffic flows to the `EverframeEventEmitter`
592
544
  // subclass via RCTEventEmitter's built-in implementations. We still need
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@everframe/react-native",
3
- "version": "1.4.1",
3
+ "version": "1.6.0",
4
4
  "description": "React Native SDK for Everframe — AI-ready in-app bug reporting, bridging the native iOS and Android reporter to your RN app. Supports phone, Apple TV, and Android TV.",
5
5
  "author": {
6
6
  "name": "Scriptx, UAB",
@@ -100,7 +100,7 @@
100
100
  "dependencies": {
101
101
  "bippy": "^0.5.39",
102
102
  "zod": "^4.3.0",
103
- "@everframe/react": "^1.4.0"
103
+ "@everframe/react": "^1.6.0"
104
104
  },
105
105
  "devDependencies": {
106
106
  "@arethetypeswrong/cli": "^0.18.0",
@@ -113,8 +113,8 @@
113
113
  "react-native-url-polyfill": "4.0.0",
114
114
  "tsup": "^8.0.0",
115
115
  "vitest": "^4.0.0",
116
- "@everframe/protocol": "0.9.0",
117
- "@everframe/sdk-core": "0.6.1"
116
+ "@everframe/sdk-core": "0.6.3",
117
+ "@everframe/protocol": "0.10.1"
118
118
  },
119
119
  "codegenConfig": {
120
120
  "name": "EverframeSpec",
@@ -14,8 +14,7 @@
14
14
  // It is imported from our structural compatibility alias because React
15
15
  // Native 0.87 hides the old deep-import declaration by default.)
16
16
  // - The 4 report methods below (configure/openReporter/registerSensitiveRect/
17
- // setExtra) plus the Plan 06.2-11 companion methods were the
18
- // COMPLETE surface — adding another report method requires a phase
17
+ // setExtra) were the COMPLETE surface — adding another report method requires a phase
19
18
  // D-decision (Plan 02/03 native impls inherit codegen headers).
20
19
  // `addBreadcrumb` (Plan 4 / Task 14) IS that new D-decision: a manual
21
20
  // breadcrumb escape hatch forwarding to the native singleton's coercion
@@ -50,24 +49,6 @@
50
49
  // `UnsafeObject`, same split `addBreadcrumb`'s `data` already uses.
51
50
  // `T | null` stays forbidden; CLEARING is expressed by calling with no
52
51
  // argument.
53
- // `ConfigOpts.attachPinUi` (spec 2026-08-19) is the next D-decision after
54
- // that — a flat optional STRING, not `'builtin' | 'custom' | 'off'`: RN
55
- // codegen cannot express a string-literal union in a struct field any more
56
- // than `setUser`'s D-decision above could express one as a bridge method
57
- // parameter type — same codegen ceiling, different call site (a
58
- // `ConfigOpts` field here, rather than a whole method's parameter there).
59
- // Unlike `setUser`'s escape hatch, this one needs no `UnsafeObject`
60
- // widening: it's a plain `string`, which codegen already handles natively
61
- // in a struct field — the union is only lost at the TYPE level, not the
62
- // VALUE level. Each native side re-parses the string into its own
63
- // `AttachPinUi` enum (`enum AttachPinUi: String` on iOS, `enum class
64
- // AttachPinUi` on Android) and coerces anything unrecognised — including
65
- // an absent field, which decodes as `undefined` and never reaches native
66
- // at all — to `.builtin`/`BUILTIN`. This rides `configureSync()`, not a new
67
- // bridge method: the flag is a startup-time preference, not a per-call
68
- // argument, so it belongs beside `sdkKey`/`networkBodiesDisabled` on
69
- // `ConfigOpts` — see `companion.ts`'s `everframe.companion.attachChallenge`
70
- // event, the JS-facing half of this same D-decision.
71
52
  // Session Vitals (spec 2026-09-06) is the next D-decision after that —
72
53
  // FIVE methods (trackPlayer/detachPlayer/recordPlayerEvent/
73
54
  // updatePlayerStats/trackVitals) and three flat ConfigOpts fields
@@ -81,10 +62,8 @@
81
62
  // `setExtraResolverActive`/`signalExtraResolverReady` (spec 2026-09-17
82
63
  // setExtra-resolver) is the next D-decision after that — RN parity for
83
64
  // the resolver form of `setExtra` core/web already have. Native asks JS
84
- // for a fresh value right before draining pending attachments (mirrors
85
- // the companion `reportRequested`/`signalCompanionReportRequestReady`
86
- // handshake below exactly), bounded and fail-open; see both methods' own
87
- // doc comments.
65
+ // for a fresh value right before draining pending attachments, bounded
66
+ // and fail-open; see both methods' own doc comments.
88
67
  import type { TurboModule } from 'react-native';
89
68
  import { TurboModuleRegistry } from 'react-native';
90
69
  import type { UnsafeObject } from './codegen-types';
@@ -141,65 +120,21 @@ export type ConfigOpts = {
141
120
  * Absent means capture stays on.
142
121
  */
143
122
  crashReportingDisabled?: boolean;
144
- /**
145
- * Built-in attach-PIN surface mode (spec 2026-08-19): 'builtin' (default —
146
- * the native SDK presents the code itself), 'custom' (host renders it from
147
- * onAttachChallenge; the device still announces the capability), 'off'
148
- * (legacy one-click dashboard attach, no PIN). Flat string, not a union —
149
- * codegen cannot express string-literal unions; the natives coerce unknown
150
- * values to 'builtin'.
151
- */
152
- attachPinUi?: string;
153
- /**
154
- * Explicit companion device-identity override (naming spec 2026-08-24) —
155
- * an MDM id or provisioning serial the host already trusts. Hashed
156
- * (SHA-256 → UUID shape) natively before it ever reaches the announce
157
- * `device` block — see `CompanionDeviceId.resolve` (iOS) /
158
- * `CompanionDeviceId.resolve` (Android). Flat optional string, same
159
- * codegen shape as `attachPinUi` above. `undefined`/absent falls through
160
- * to each native side's own Keychain/SSAID-then-stored-UUID chain.
161
- */
162
- companionDeviceId?: string;
163
- /**
164
- * Companion on-screen name-badge visibility (naming spec 2026-08-24,
165
- * controller ruling / Task 6b) — "a production app that finds it
166
- * intrusive turns it off in one line". `undefined`/absent defaults to
167
- * `true` (badge shown) on both natives, matching
168
- * `CompanionBadgeOptions.enabled`'s own default. Flat because RN codegen
169
- * rejects nested objects, same constraint `networkBodiesDisabled` above
170
- * documents — the host-facing nested `companionBadge: { enabled }` is
171
- * flattened here by `extractBridgeConfig`.
172
- */
173
- companionBadgeEnabled?: boolean;
174
- /** Local veto for native mobile shake-to-report. Absent defaults to enabled. */
123
+ /** Local veto for shake opening the reporter (not for shake quick capture). Absent defaults to enabled. */
175
124
  shakeToReportEnabled?: boolean;
125
+ /** Local veto for quick capture (simulators, emulators and real phones) and device linking. Absent defaults to enabled. */
126
+ quickCaptureEnabled?: boolean;
176
127
  /**
177
128
  * Crash-only session switch. `true` turns off every on-device way to open the reporter, keeps
178
- * network bodies off and samples replay with the server's crash-only rate until a companion
179
- * bond upgrades the session. Flattened by `extractBridgeConfig` from `reporter: { disabled }`.
129
+ * network bodies off and samples replay with the server's crash-only rate. Flattened by `extractBridgeConfig` from `reporter: { disabled }`.
180
130
  * Absent means a normal report session.
181
131
  */
182
132
  reporterDisabled?: boolean;
183
- /**
184
- * Companion on-screen name-badge corner (naming spec 2026-08-24,
185
- * controller ruling / Task 6b). Flat optional STRING, not a literal
186
- * union — same codegen ceiling as `attachPinUi` above (RN codegen cannot
187
- * express a string-literal union in a struct field): the host-facing
188
- * `RuntimeConfig.companionBadge.position` narrows to the real
189
- * `'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'` union and
190
- * `extractBridgeConfig` passes it through unchanged onto this wire field.
191
- * Each native side re-parses the string into its own
192
- * `CompanionBadgePosition` enum, coercing `undefined`/an unrecognised
193
- * value to `.bottomRight`/`BOTTOM_RIGHT` — the same default
194
- * `CompanionBadgeOptions.position` already uses.
195
- */
196
- companionBadgePosition?: string;
197
133
  /**
198
134
  * Inline reporter theme (reporter branding spec 2026-08-25, RN slice) —
199
135
  * 8 optional `#rrggbb` role strings, flattened from the host-facing nested
200
136
  * `RuntimeConfig.theme` by `extractBridgeConfig` (RN codegen cannot express
201
- * a nested object in a struct field — the `companionBadge` constraint
202
- * above). Pure passthrough: NO hex validation happens on the RN side; each
137
+ * a nested object in a struct field). Pure passthrough: NO hex validation happens on the RN side; each
203
138
  * native ThemeResolver revalidates per-field and ignores invalid values.
204
139
  * The theme only ever renders once the server entitles it (server
205
140
  * `watermark: false`) — the entitlement gate lives natively and cannot be
@@ -216,7 +151,7 @@ export type ConfigOpts = {
216
151
  /**
217
152
  * Session Vitals local config (spec 2026-09-06, RN). Three FLAT fields
218
153
  * flattened from the host-facing nested `RuntimeConfig.vitals` by
219
- * `extractBridgeConfig` — same codegen reason as `companionBadge*`.
154
+ * `extractBridgeConfig` — RN codegen rejects nested objects.
220
155
  * `vitalsEnabled`: absent = follow the dashboard toggle; `false` = opt out
221
156
  * locally; `true` never forces it on. `vitalsSampleRate`: [0, 1], min()'d
222
157
  * with the server rate, clamped natively; absent = server rate.
@@ -329,8 +264,7 @@ export interface Spec extends TurboModule {
329
264
  */
330
265
  setExtraResolverActive(active: boolean): void;
331
266
  /**
332
- * Companion-precedent-shaped ack (mirrors `signalCompanionReportRequestReady`
333
- * below exactly): called by the JS-side `everframe.extra.resolveRequested`
267
+ * Ack: called by the JS-side `everframe.extra.resolveRequested`
334
268
  * listener once it has — IF a resolver is currently registered — invoked
335
269
  * it, budgeted the result exactly like `@everframe/sdk-core`'s
336
270
  * `resolveClientExtra`, and pushed it through the existing `setExtra`
@@ -434,39 +368,11 @@ export interface Spec extends TurboModule {
434
368
  */
435
369
  captureHandledException(crashJson: string): boolean;
436
370
 
437
- // ---------------- Phone-companion (Plan 06.2-11) ----------------
438
- //
439
- // Opens a TV-side RelayWSClient against the build-time-baked ingest URL
440
- // (IngestEndpoint.url on each native SDK) and forwards
441
- // `Everframe.shared.companion` state + pairUrl signals to JS via the
442
- // platform's RN event-emitter (RCTDeviceEventEmitter on Android, a
443
- // dedicated RCTEventEmitter subclass on iOS). The bridge owns at most ONE
444
- // RelayWSClient per process.
445
- //
446
- // Emitted events (both platforms — see `src/companion.ts`):
447
- // • `everframe.companion.state` → 'unpaired' | 'paired' | 'report_in_progress' | 'phone_disconnected'
448
- // • `everframe.companion.pairUrl` → string | null
449
- // • `everframe.companion.code` → string | null
450
- // • `everframe.companion.attachedUserName` → string | null
451
- // • `everframe.companion.resolvedName` → string | null (naming spec 2026-08-24)
452
- // • `everframe.companion.attachChallenge` → { code, requestedByName, ttlMs } | null (spec 2026-08-19)
453
- startCompanion(): void;
454
- stopCompanion(): void;
455
- /**
456
- * Companion handshake: called by the JS-side `onReportRequested` listener
457
- * once it is ready for native capture to proceed. (It used to walk the
458
- * React fiber tree and attach it via `attachReactTree` first; both are
459
- * gone — spec 2026-08-29.) Releases the native bridge's bounded wait.
460
- *
461
- * Bounded: if JS never calls back, the native side times out after
462
- * ~250ms and captures anyway.
463
- */
464
- signalCompanionReportRequestReady(correlationId: string): void;
371
+ // ---------------- Native event emitter ----------------
465
372
  /**
466
373
  * RN's `NativeEventEmitter` contract requires `addListener` /
467
374
  * `removeListeners` to exist on the underlying native module — RN warns
468
- * loudly otherwise. Both are intentional no-ops at the spec level: the
469
- * native event-emitter subscriptions are installed by `startCompanion`.
375
+ * loudly otherwise. Both are intentional no-ops at the spec level.
470
376
  */
471
377
  addListener(eventName: string): void;
472
378
  removeListeners(count: number): void;