yaver-feedback-react-native 0.9.0 → 0.9.3

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 (144) hide show
  1. package/README.md +102 -1
  2. package/app.plugin.js +126 -9
  3. package/dist/AuthOverlay.d.ts +1 -14
  4. package/dist/AuthOverlay.js +9 -62
  5. package/dist/BlackBox.js +9 -1
  6. package/dist/DeployPanel.js +65 -0
  7. package/dist/Discovery.js +13 -8
  8. package/dist/DogfoodRuntime.d.ts +124 -0
  9. package/dist/DogfoodRuntime.js +273 -0
  10. package/dist/FeedbackModal.js +505 -65
  11. package/dist/LoginScreen.d.ts +1 -5
  12. package/dist/LoginScreen.js +2 -6
  13. package/dist/MachinePickerScreen.d.ts +1 -3
  14. package/dist/MachinePickerScreen.js +6 -18
  15. package/dist/P2PClient.d.ts +178 -2
  16. package/dist/P2PClient.js +493 -3
  17. package/dist/P2PDogfoodDriver.d.ts +12 -0
  18. package/dist/P2PDogfoodDriver.js +118 -0
  19. package/dist/PairDeviceModal.d.ts +2 -3
  20. package/dist/ShakeDetector.js +2 -0
  21. package/dist/VibeChatScreen.d.ts +11 -1
  22. package/dist/VibeChatScreen.js +200 -41
  23. package/dist/YaverFeedback.d.ts +132 -0
  24. package/dist/YaverFeedback.js +633 -65
  25. package/dist/YaverModeBadge.d.ts +22 -0
  26. package/dist/YaverModeBadge.js +219 -0
  27. package/dist/__tests__/AuthDevices.test.js +1 -48
  28. package/dist/__tests__/BlackBox.relayPassword.test.d.ts +1 -0
  29. package/dist/__tests__/BlackBox.relayPassword.test.js +105 -0
  30. package/dist/__tests__/BlackBoxAutoStart.test.d.ts +1 -0
  31. package/dist/__tests__/BlackBoxAutoStart.test.js +91 -0
  32. package/dist/__tests__/BlackBoxAutoStartColdStart.test.d.ts +1 -0
  33. package/dist/__tests__/BlackBoxAutoStartColdStart.test.js +156 -0
  34. package/dist/__tests__/BrowserLaneIcon.test.d.ts +3 -0
  35. package/dist/__tests__/BrowserLaneIcon.test.js +80 -0
  36. package/dist/__tests__/DogfoodRuntime.test.d.ts +1 -0
  37. package/dist/__tests__/DogfoodRuntime.test.js +116 -0
  38. package/dist/__tests__/P2PClient.test.js +2 -2
  39. package/dist/__tests__/P2PDogfoodDriver.test.d.ts +1 -0
  40. package/dist/__tests__/P2PDogfoodDriver.test.js +64 -0
  41. package/dist/__tests__/ReportIdentity.test.d.ts +25 -0
  42. package/dist/__tests__/ReportIdentity.test.js +180 -0
  43. package/dist/__tests__/SDKToken.test.js +1 -1
  44. package/dist/__tests__/ShakeToggle.test.d.ts +1 -0
  45. package/dist/__tests__/ShakeToggle.test.js +121 -0
  46. package/dist/__tests__/YaverFeedback.test.js +13 -3
  47. package/dist/__tests__/deviceDogfood.test.d.ts +1 -0
  48. package/dist/__tests__/deviceDogfood.test.js +86 -0
  49. package/dist/__tests__/dogfoodPolicy.test.d.ts +1 -0
  50. package/dist/__tests__/dogfoodPolicy.test.js +33 -0
  51. package/dist/__tests__/pickTargetDevice.test.d.ts +1 -0
  52. package/dist/__tests__/pickTargetDevice.test.js +89 -0
  53. package/dist/__tests__/reloadActions.test.d.ts +1 -0
  54. package/dist/__tests__/reloadActions.test.js +129 -0
  55. package/dist/__tests__/reloadActionsParity.test.d.ts +1 -0
  56. package/dist/__tests__/reloadActionsParity.test.js +42 -0
  57. package/dist/__tests__/types.test.js +5 -5
  58. package/dist/_core/ansi.d.ts +117 -0
  59. package/dist/_core/ansi.js +468 -0
  60. package/dist/_core/ansi.test.d.ts +1 -0
  61. package/dist/_core/ansi.test.js +225 -0
  62. package/dist/_core/buildFeedbackPrompt.d.ts +4 -9
  63. package/dist/_core/buildFeedbackPrompt.js +18 -72
  64. package/dist/_core/constants.d.ts +19 -6
  65. package/dist/_core/constants.js +20 -7
  66. package/dist/_core/device.d.ts +1 -5
  67. package/dist/_core/device.js +5 -14
  68. package/dist/_core/endpoints.d.ts +0 -7
  69. package/dist/_core/endpoints.js +0 -7
  70. package/dist/_core/index.d.ts +4 -0
  71. package/dist/_core/index.js +4 -0
  72. package/dist/_core/remoteless.d.ts +44 -0
  73. package/dist/_core/remoteless.js +75 -0
  74. package/dist/_core/trace.d.ts +47 -0
  75. package/dist/_core/trace.js +38 -0
  76. package/dist/_core/trace.test.d.ts +1 -0
  77. package/dist/_core/trace.test.js +60 -0
  78. package/dist/auth.d.ts +3 -60
  79. package/dist/auth.js +6 -88
  80. package/dist/deviceDogfood.d.ts +53 -0
  81. package/dist/deviceDogfood.js +137 -0
  82. package/dist/dogfoodPolicy.d.ts +25 -0
  83. package/dist/dogfoodPolicy.js +24 -0
  84. package/dist/index.d.ts +17 -4
  85. package/dist/index.js +33 -7
  86. package/dist/reloadActions.d.ts +88 -0
  87. package/dist/reloadActions.js +200 -0
  88. package/dist/storeShots.d.ts +67 -0
  89. package/dist/storeShots.js +137 -0
  90. package/dist/types.d.ts +208 -8
  91. package/package.json +13 -4
  92. package/src/AuthOverlay.tsx +20 -106
  93. package/src/BlackBox.ts +10 -1
  94. package/src/DeployPanel.tsx +74 -0
  95. package/src/Discovery.ts +13 -8
  96. package/src/DogfoodRuntime.ts +373 -0
  97. package/src/FeedbackModal.tsx +619 -79
  98. package/src/LoginScreen.tsx +2 -22
  99. package/src/MachinePickerScreen.tsx +6 -21
  100. package/src/P2PClient.ts +580 -4
  101. package/src/P2PDogfoodDriver.ts +132 -0
  102. package/src/PairDeviceModal.tsx +2 -3
  103. package/src/ShakeDetector.ts +1 -0
  104. package/src/VibeChatScreen.tsx +232 -42
  105. package/src/YaverFeedback.ts +631 -68
  106. package/src/YaverModeBadge.tsx +234 -0
  107. package/src/__tests__/AuthDevices.test.ts +1 -52
  108. package/src/__tests__/BlackBox.relayPassword.test.ts +129 -0
  109. package/src/__tests__/BlackBoxAutoStart.test.ts +111 -0
  110. package/src/__tests__/BlackBoxAutoStartColdStart.test.ts +191 -0
  111. package/src/__tests__/BrowserLaneIcon.test.ts +85 -0
  112. package/src/__tests__/DogfoodRuntime.test.ts +135 -0
  113. package/src/__tests__/P2PClient.test.ts +2 -2
  114. package/src/__tests__/P2PDogfoodDriver.test.ts +80 -0
  115. package/src/__tests__/ReportIdentity.test.ts +212 -0
  116. package/src/__tests__/SDKToken.test.ts +1 -1
  117. package/src/__tests__/ShakeToggle.test.ts +153 -0
  118. package/src/__tests__/YaverFeedback.test.ts +15 -3
  119. package/src/__tests__/deviceDogfood.test.ts +77 -0
  120. package/src/__tests__/dogfoodPolicy.test.ts +34 -0
  121. package/src/__tests__/pickTargetDevice.test.ts +101 -0
  122. package/src/__tests__/reloadActions.test.ts +171 -0
  123. package/src/__tests__/reloadActionsParity.test.ts +49 -0
  124. package/src/__tests__/types.test.ts +5 -5
  125. package/src/_core/ansi.test.ts +250 -0
  126. package/src/_core/ansi.ts +475 -0
  127. package/src/_core/buildFeedbackPrompt.ts +18 -95
  128. package/src/_core/constants.ts +20 -6
  129. package/src/_core/device.ts +5 -16
  130. package/src/_core/endpoints.ts +0 -7
  131. package/src/_core/index.ts +4 -0
  132. package/src/_core/remoteless.ts +110 -0
  133. package/src/_core/trace.test.ts +58 -0
  134. package/src/_core/trace.ts +75 -0
  135. package/src/auth.ts +7 -156
  136. package/src/deviceDogfood.ts +171 -0
  137. package/src/dogfoodPolicy.ts +40 -0
  138. package/src/index.ts +61 -11
  139. package/src/reloadActions.ts +273 -0
  140. package/src/storeShots.ts +189 -0
  141. package/src/types.ts +209 -8
  142. package/dist/GuestOnboardingScreen.d.ts +0 -8
  143. package/dist/GuestOnboardingScreen.js +0 -282
  144. package/src/GuestOnboardingScreen.tsx +0 -307
@@ -0,0 +1,189 @@
1
+ /**
2
+ * On-device App Store screenshot capture (Engine 2).
3
+ *
4
+ * The desktop `yaver shots` flow drives a simulator with Maestro. This is
5
+ * the in-app counterpart: the SDK, living inside the real running app,
6
+ * walks the app's own routes and screenshots each one with
7
+ * `react-native-view-shot`, then uploads the frames to the Yaver agent
8
+ * (POST /shots/upload). The agent normalizes them and runs the same App
9
+ * Store Connect backend (upload → metadata → submit).
10
+ *
11
+ * Why this exists alongside the simulator path: it captures *real device*
12
+ * pixels, knows the exact route map (no heuristics), and the user is
13
+ * already authenticated — so it sidesteps the i18n / no-testID fragility
14
+ * that makes a blind simulator walk hard.
15
+ *
16
+ * The host wires it once by handing us a navigation ref (react-navigation
17
+ * or expo-router router) plus the ordered list of routes to visit.
18
+ */
19
+
20
+ import { captureScreenshotBase64 } from './capture';
21
+
22
+ export interface StoreShotFrame {
23
+ route: string;
24
+ base64: string;
25
+ mimeType: string;
26
+ }
27
+
28
+ export interface CaptureStoreScreenshotsOptions {
29
+ /** Yaver agent base URL (e.g. http://192.168.1.5:18080 or a relay URL). */
30
+ agentUrl: string;
31
+ /** Bearer token for the agent (same-user envelope). */
32
+ authToken: string;
33
+ /** Relay password — required only when agentUrl is relay-routed. */
34
+ relayPassword?: string;
35
+
36
+ /** App name (vault scope / job label on the agent side). */
37
+ app: string;
38
+ /** iOS bundle id; the agent falls back to app.json if omitted. */
39
+ bundleId?: string;
40
+ /** App Store localization (default en-US). */
41
+ locale?: string;
42
+ /** When true, the agent also sets metadata + attempts submit-for-review. */
43
+ submit?: boolean;
44
+
45
+ /**
46
+ * Navigation handle. Either a react-navigation ref (has `.navigate`) or
47
+ * an expo-router `router` (has `.push`/`.navigate`). We call the first
48
+ * available method with the route string.
49
+ */
50
+ navigationRef?: any;
51
+ /** Ordered routes to visit + screenshot (e.g. ['/(tabs)/dashboard', ...]). */
52
+ routes: string[];
53
+
54
+ /** Optional per-route screenshot names (defaults to NN_<sanitized route>). */
55
+ screens?: string[];
56
+ /** Milliseconds to wait after navigating before capturing (default 900). */
57
+ settleMs?: number;
58
+ /** Hook the host can use to hide its own overlay before each capture. */
59
+ onBeforeCapture?: (route: string, index: number) => void | Promise<void>;
60
+ }
61
+
62
+ export interface CaptureStoreScreenshotsResult {
63
+ ok: boolean;
64
+ captured: number;
65
+ uploaded: number;
66
+ submitted?: boolean;
67
+ staged?: boolean;
68
+ message?: string;
69
+ }
70
+
71
+ function sleep(ms: number): Promise<void> {
72
+ return new Promise((r) => setTimeout(r, ms));
73
+ }
74
+
75
+ function navigateTo(navRef: any, route: string): void {
76
+ if (!navRef) return;
77
+ // react-navigation ref
78
+ if (typeof navRef.navigate === 'function') {
79
+ navRef.navigate(route as never);
80
+ return;
81
+ }
82
+ // expo-router router
83
+ if (typeof navRef.push === 'function') {
84
+ navRef.push(route);
85
+ return;
86
+ }
87
+ if (navRef.current && typeof navRef.current.navigate === 'function') {
88
+ navRef.current.navigate(route as never);
89
+ return;
90
+ }
91
+ }
92
+
93
+ function shotName(route: string, index: number, override?: string): string {
94
+ if (override) return override;
95
+ const clean = route
96
+ .replace(/^\/+/, '')
97
+ .replace(/[()[\]/]+/g, '_')
98
+ .replace(/[^a-zA-Z0-9_]+/g, '')
99
+ .replace(/^_+|_+$/g, '');
100
+ const n = String(index + 1).padStart(2, '0');
101
+ return `${n}_${clean || 'screen'}`;
102
+ }
103
+
104
+ /**
105
+ * Walk the app's routes, screenshot each, and upload the batch to the
106
+ * agent. Returns a summary; never throws for a single missed route —
107
+ * it captures what it can and reports the count.
108
+ */
109
+ export async function captureStoreScreenshots(
110
+ opts: CaptureStoreScreenshotsOptions,
111
+ ): Promise<CaptureStoreScreenshotsResult> {
112
+ if (!opts.agentUrl || !opts.authToken) {
113
+ return { ok: false, captured: 0, uploaded: 0, message: 'agentUrl + authToken required' };
114
+ }
115
+ if (!opts.routes?.length) {
116
+ return { ok: false, captured: 0, uploaded: 0, message: 'no routes to capture' };
117
+ }
118
+
119
+ const settleMs = opts.settleMs ?? 900;
120
+ const frames: StoreShotFrame[] = [];
121
+
122
+ for (let i = 0; i < opts.routes.length; i++) {
123
+ const route = opts.routes[i];
124
+ try {
125
+ navigateTo(opts.navigationRef, route);
126
+ await sleep(settleMs);
127
+ if (opts.onBeforeCapture) await opts.onBeforeCapture(route, i);
128
+ const shot = await captureScreenshotBase64();
129
+ if (shot?.base64) {
130
+ frames.push({
131
+ route: shotName(route, i, opts.screens?.[i]),
132
+ base64: shot.base64,
133
+ mimeType: shot.mimeType,
134
+ });
135
+ }
136
+ } catch {
137
+ // Skip a route that failed to render — keep walking.
138
+ }
139
+ }
140
+
141
+ if (frames.length === 0) {
142
+ return { ok: false, captured: 0, uploaded: 0, message: 'captured no frames' };
143
+ }
144
+
145
+ const headers: Record<string, string> = {
146
+ Authorization: `Bearer ${opts.authToken}`,
147
+ 'Content-Type': 'application/json',
148
+ };
149
+ if (opts.relayPassword) headers['X-Relay-Password'] = opts.relayPassword;
150
+
151
+ const base = opts.agentUrl.replace(/\/$/, '');
152
+ try {
153
+ const resp = await fetch(`${base}/shots/upload`, {
154
+ method: 'POST',
155
+ headers,
156
+ body: JSON.stringify({
157
+ app: opts.app,
158
+ bundleId: opts.bundleId ?? '',
159
+ locale: opts.locale ?? 'en-US',
160
+ submit: !!opts.submit,
161
+ frames,
162
+ }),
163
+ });
164
+ const j = await resp.json().catch(() => ({}));
165
+ if (!resp.ok || j?.ok === false) {
166
+ return {
167
+ ok: false,
168
+ captured: frames.length,
169
+ uploaded: 0,
170
+ message: j?.error || `agent /shots/upload HTTP ${resp.status}`,
171
+ };
172
+ }
173
+ return {
174
+ ok: true,
175
+ captured: frames.length,
176
+ uploaded: typeof j?.uploaded === 'number' ? j.uploaded : frames.length,
177
+ submitted: j?.submitted,
178
+ staged: j?.staged,
179
+ message: j?.message,
180
+ };
181
+ } catch (e: any) {
182
+ return {
183
+ ok: false,
184
+ captured: frames.length,
185
+ uploaded: 0,
186
+ message: `upload failed: ${e?.message ?? 'network error'}`,
187
+ };
188
+ }
189
+ }
package/src/types.ts CHANGED
@@ -1,3 +1,8 @@
1
+ // Type-only: BlackBox.ts already imports from this module, so a value import
2
+ // would close a cycle. `import type` is erased at compile time.
3
+ import type { BlackBoxConfig } from './BlackBox';
4
+ import type { SDKDogfoodConfig } from './dogfoodPolicy';
5
+
1
6
  /**
2
7
  * Remote browser-style sign-in session for a coding-agent CLI on the
3
8
  * connected yaver host. Mirrors runnerBrowserAuthSession on the agent
@@ -32,6 +37,8 @@ export interface RunnerAuthStatusRow {
32
37
  path?: string;
33
38
  detail?: string;
34
39
  version?: string;
40
+ isDefault?: boolean;
41
+ models?: Array<{ id: string; name?: string; provider?: string; isDefault?: boolean }>;
35
42
  }
36
43
 
37
44
  export interface OpenCodeProviderSummary {
@@ -122,9 +129,67 @@ export interface CapabilitySnapshot {
122
129
  targets: Record<string, CapabilityTargetReadiness>;
123
130
  }
124
131
 
132
+ /**
133
+ * Opt-in config for the overlay's "App Store screenshots" action and the
134
+ * `capture_store_shots` remote command. When set, the SDK can walk the
135
+ * app's routes on-device, screenshot each, and upload them to the agent
136
+ * (which runs the App Store Connect backend).
137
+ */
138
+ export interface StoreShotsConfig {
139
+ /** Ordered routes to visit + screenshot (e.g. ['/(tabs)/home', ...]). */
140
+ routes: string[];
141
+ /** Navigation handle: a react-navigation ref or expo-router `router`. */
142
+ navigationRef?: any;
143
+ /** Also set metadata + attempt submit-for-review after upload. */
144
+ submit?: boolean;
145
+ /** Optional per-route screenshot names (defaults to NN_<route>). */
146
+ screens?: string[];
147
+ }
148
+
125
149
  export interface FeedbackConfig {
126
150
  /** URL of the Yaver agent (e.g. "http://192.168.1.10:18080"). If omitted, auto-discovery is used. */
127
151
  agentUrl?: string;
152
+ /** Optional coding route. Defaults to agentUrl. */
153
+ codingAgentUrl?: string;
154
+ /** Optional render/reload route. Defaults to codingAgentUrl/agentUrl. */
155
+ renderAgentUrl?: string;
156
+ /** Device identities shown in the unified Settings card when routes differ. */
157
+ codingDeviceId?: string;
158
+ renderDeviceId?: string;
159
+ /**
160
+ * Show the small "Y" mark while this app is running INSIDE Yaver's container
161
+ * (a Hermes-pushed development bundle), so a tester can tell it apart from
162
+ * the build they installed — and can find the way back.
163
+ *
164
+ * DEFAULT TRUE. The failure it prevents is silent and lands on a tester
165
+ * rather than a developer: an app that looks installed but is someone's
166
+ * branch produces "bug reports" against unfinished work, and a tester with
167
+ * no visible way out is simply stuck. That class should not be opt-in.
168
+ *
169
+ * Costs nothing in a standalone build — outside Yaver's container the badge
170
+ * renders null (the YaverInfo native module is absent), so shipping with it
171
+ * enabled has no effect on what your users see.
172
+ *
173
+ * Set false if your app already shows its own in-container indicator, or if
174
+ * a pixel-exact surface cannot spare 22 points in a corner.
175
+ */
176
+ modeBadge?: boolean;
177
+ /** Corner for the mode badge. Default 'bottom-left' — bottom-right is where
178
+ * most apps put a FAB, and the badge must never compete with the app's own
179
+ * primary action. */
180
+ modeBadgePosition?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
181
+ /** Account-scoped direct Dogfood UX for an approved third-party app.
182
+ * When the current app account is allowlisted, the small Y opens Vibing
183
+ * directly instead of the normal feedback actions. This is a client UX gate,
184
+ * never an authentication mechanism; agent calls still require Yaver auth. */
185
+ dogfood?: SDKDogfoodConfig;
186
+ /**
187
+ * Enables the overlay's "App Store screenshots" action + the
188
+ * `capture_store_shots` remote command. The host supplies the route
189
+ * list (and a navigation ref) once; the SDK captures the real running
190
+ * app — no simulator needed.
191
+ */
192
+ storeShots?: StoreShotsConfig;
128
193
  /**
129
194
  * Auth token for the Yaver agent. Optional in 0.5+: if omitted, the SDK
130
195
  * will hydrate one from AsyncStorage or show its in-app login screen
@@ -164,6 +229,47 @@ export interface FeedbackConfig {
164
229
  * If omitted with convexUrl, connects to the first online device.
165
230
  */
166
231
  preferredDeviceId?: string;
232
+ /**
233
+ * Identity of the app this SDK instance reports for. Both fields are
234
+ * resolved automatically from expo-constants / native modules when
235
+ * omitted, so most apps never set them.
236
+ *
237
+ * Set them when the ambient answer would be wrong — above all when the
238
+ * app's JS is pushed into Yaver's container as a Hermes guest. There the
239
+ * runtime IS Yaver: `expo-constants` and `SettingsManager` describe the
240
+ * host (`Yaver` / `io.yaver.mobile`), not the guest, so auto-resolution
241
+ * would file every report against Yaver's own repo and the fix task would
242
+ * edit the SDK instead of the app. Declaring identity here is the only
243
+ * answer that holds in both a standalone build and a guest bundle.
244
+ *
245
+ * `bundleId` is the key that actually routes: the agent matches it against
246
+ * each project's pbxproj / build.gradle / app.json. `projectName` is a
247
+ * fallback for platforms with no bundle id.
248
+ */
249
+ projectName?: string;
250
+ bundleId?: string;
251
+ /** Primary Yaver product surface for this app/package. */
252
+ surface?: YaverSurface;
253
+ /** All product surfaces this app/package owns. */
254
+ surfaces?: YaverSurface[];
255
+ /** Canonical development stack labels, e.g. react-native-expo, yaver-xml. */
256
+ stack?: string;
257
+ stacks?: string[];
258
+ /** Yaver preview/runtime targets that can exercise this app. */
259
+ testSurfaces?: string[];
260
+ feedbackSdk?: string;
261
+ feedbackTransport?: string;
262
+ voiceCapabilities?: string[];
263
+ sttProvider?: string;
264
+ ttsProvider?: string;
265
+ /**
266
+ * Opt in to the microphone/STT controls in the feedback Vibing card.
267
+ *
268
+ * This is deliberately false unless explicitly enabled: ordinary phone
269
+ * and tablet surfaces stay keyboard-first. Car/watch-style hosts that are
270
+ * inherently voice-driven may set this to true.
271
+ */
272
+ voiceInputEnabled?: boolean;
167
273
  /** How feedback collection is triggered */
168
274
  trigger?: 'shake' | 'floating-button' | 'manual';
169
275
  /**
@@ -204,6 +310,22 @@ export interface FeedbackConfig {
204
310
  * Calling `BlackBox.start()` manually is still safe — it's idempotent.
205
311
  */
206
312
  autoStartBlackBox?: boolean;
313
+ /**
314
+ * Config handed to BlackBox when the SDK auto-starts it.
315
+ *
316
+ * Without this there was no way to configure the flight recorder at all.
317
+ * The obvious move — and the one the README's own snippet makes — is:
318
+ *
319
+ * YaverFeedback.init({ trigger: 'shake' });
320
+ * BlackBox.start({ appName: 'my-app' });
321
+ *
322
+ * but that start() early-returns, because a zero-config init has no
323
+ * agentUrl yet (discovery resolves it asynchronously). The auto-start then
324
+ * fires ~500ms later once the agent and token exist and calls `start()`
325
+ * with NO arguments — so the host's config is silently dropped and appName
326
+ * is ''. Pass it here instead and the auto-start will honour it.
327
+ */
328
+ blackBox?: BlackBoxConfig;
207
329
  /**
208
330
  * Small tap-to-open icon that floats above the app so the user
209
331
  * doesn't have to shake every time they want to open feedback.
@@ -289,6 +411,26 @@ export interface FeedbackConfig {
289
411
  * Bugsnag, or any other error tracking tool.
290
412
  */
291
413
  maxCapturedErrors?: number;
414
+ /**
415
+ * Crash-aware reporting/fixing. Defaults to disabled.
416
+ *
417
+ * - enabled: records fatal errors into the SDK error buffer and enables
418
+ * explicit `YaverFeedback.reportCrash(error)`.
419
+ * - installGlobalHandler: opt-in only. Wraps React Native's global ErrorUtils
420
+ * handler without suppressing the existing handler. Leave false when Sentry,
421
+ * Crashlytics, Bugsnag, or another crash tool owns the global handler.
422
+ * - autoFix: after uploading a crash report, ask the connected Yaver agent to
423
+ * create a fix task. The normal BlackBox command stream can then deliver a
424
+ * reload/reload_bundle command after the agent rebuilds.
425
+ * - captureScreenshot: attach a best-effort screenshot to the crash report.
426
+ */
427
+ crashReporting?: {
428
+ enabled?: boolean;
429
+ installGlobalHandler?: boolean;
430
+ autoFix?: boolean;
431
+ captureScreenshot?: boolean;
432
+ metadata?: Record<string, unknown>;
433
+ };
292
434
  /**
293
435
  * Which platforms the Build button targets.
294
436
  * - 'ios' — build iOS only
@@ -368,13 +510,6 @@ export interface FeedbackConfig {
368
510
  * Default: false (preserve historical behavior).
369
511
  */
370
512
  strictNativeAuth?: boolean;
371
- /**
372
- * Optional host invite code to prefill into the in-SDK guest onboarding
373
- * flow. Useful when your app receives the code from a deep link, QR flow,
374
- * or an out-of-band host handoff and you want the user to redeem it
375
- * without typing.
376
- */
377
- guestInviteCode?: string;
378
513
  }
379
514
 
380
515
  export interface FeedbackBundle {
@@ -404,9 +539,36 @@ export interface CapturedError {
404
539
 
405
540
  export interface FeedbackMetadata {
406
541
  timestamp: string;
407
- device: DeviceInfo;
542
+ /**
543
+ * Wire key is `deviceInfo`, matching the Flutter + web SDKs and the
544
+ * agent's `FeedbackReport.DeviceInfo` (`json:"deviceInfo"`). This was
545
+ * `device` until 0.9.2 — a key the agent never read, so the whole block
546
+ * (platform, model, and the app name the fix router needs) was silently
547
+ * dropped on every React Native report. The agent still accepts the old
548
+ * key so builds already in the field keep working.
549
+ */
550
+ deviceInfo: DeviceInfo;
408
551
  app: AppInfo;
552
+ /**
553
+ * Which of the host's projects this report is about. The agent resolves
554
+ * a feedback→fix task's working directory from this; without it the task
555
+ * falls back to whatever directory the agent happens to be sitting in.
556
+ * Populated automatically by `resolveReportIdentity()`.
557
+ */
558
+ project?: FeedbackProjectRef;
409
559
  userNote?: string;
560
+ reportKind?: 'feedback' | 'auto-report' | 'crash';
561
+ crash?: {
562
+ message: string;
563
+ isFatal: boolean;
564
+ source: 'manual' | 'global-handler';
565
+ autoFixRequested?: boolean;
566
+ };
567
+ twin?: {
568
+ sessionId?: string;
569
+ surface?: string;
570
+ artifactDir?: string;
571
+ };
410
572
  }
411
573
 
412
574
  export interface DeviceInfo {
@@ -415,6 +577,8 @@ export interface DeviceInfo {
415
577
  model: string;
416
578
  screenWidth: number;
417
579
  screenHeight: number;
580
+ /** Host app name. First key the agent's fix router checks. */
581
+ appName?: string;
418
582
  }
419
583
 
420
584
  export interface AppInfo {
@@ -423,6 +587,43 @@ export interface AppInfo {
423
587
  buildNumber?: string;
424
588
  }
425
589
 
590
+ /**
591
+ * Identifies the host project a report belongs to. Mirrors the web SDK's
592
+ * `FeedbackProjectRef` and the agent's `FeedbackProject`.
593
+ */
594
+ export interface FeedbackProjectRef {
595
+ appName?: string;
596
+ projectName?: string;
597
+ /**
598
+ * Bundle identifier / applicationId. The only unambiguous key: an app's
599
+ * display name ("Talos") does not match the agent's registry name for it
600
+ * ("talos / mobile"), and one repo can hold several mobile projects that
601
+ * all share a name prefix. The agent matches this against the project's
602
+ * pbxproj, build.gradle, and app.json.
603
+ */
604
+ bundleId?: string;
605
+ /**
606
+ * Deliberately never set by this SDK. The agent ignores client-supplied
607
+ * paths for feedback reports (an untrusted guest could otherwise point the
608
+ * fix task's CWD at ~/.ssh) and resolves the path server-side. Present only
609
+ * so the type matches the wire format the agent parses.
610
+ */
611
+ projectPath?: string;
612
+ surface?: YaverSurface;
613
+ surfaces?: YaverSurface[];
614
+ stack?: string;
615
+ stacks?: string[];
616
+ testSurfaces?: string[];
617
+ feedbackSdk?: string;
618
+ feedbackTransport?: string;
619
+ voiceCapabilities?: string[];
620
+ sttProvider?: string;
621
+ ttsProvider?: string;
622
+ releaseChannel?: 'production' | 'candidate' | 'development';
623
+ }
624
+
625
+ export type YaverSurface = 'web' | 'mobile' | 'backend' | 'watch' | 'tv' | 'car' | 'vision' | 'desktop' | 'cli';
626
+
426
627
  export interface TimelineEvent {
427
628
  type: 'screenshot' | 'audio' | 'video';
428
629
  path: string;
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- export interface YaverGuestOnboardingScreenProps {
3
- token: string;
4
- initialInviteCode?: string;
5
- onContinue: () => void;
6
- onCancel?: () => void;
7
- }
8
- export declare const YaverGuestOnboardingScreen: React.FC<YaverGuestOnboardingScreenProps>;