yaver-feedback-react-native 0.9.10 → 0.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AuthOverlay.js +4 -2
- package/dist/DogfoodRuntime.d.ts +26 -0
- package/dist/DogfoodRuntime.js +85 -11
- package/dist/DogfoodSessionUi.d.ts +1 -0
- package/dist/DogfoodSessionUi.js +3 -2
- package/dist/FeedbackModal.js +126 -105
- package/dist/LoginScreen.d.ts +2 -0
- package/dist/LoginScreen.js +2 -2
- package/dist/MachinePickerScreen.d.ts +3 -1
- package/dist/MachinePickerScreen.js +43 -28
- package/dist/__tests__/DogfoodRuntime.test.js +45 -0
- package/dist/__tests__/FeedbackModalContract.test.js +16 -6
- package/dist/__tests__/MachinePickerScreenContract.test.d.ts +1 -0
- package/dist/__tests__/MachinePickerScreenContract.test.js +25 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -2
- package/package.json +1 -1
- package/src/AuthOverlay.tsx +8 -1
- package/src/DogfoodRuntime.ts +108 -11
- package/src/DogfoodSessionUi.tsx +4 -2
- package/src/FeedbackModal.tsx +45 -16
- package/src/LoginScreen.tsx +4 -1
- package/src/MachinePickerScreen.tsx +43 -30
- package/src/__tests__/DogfoodRuntime.test.ts +51 -0
- package/src/__tests__/FeedbackModalContract.test.ts +17 -6
- package/src/__tests__/MachinePickerScreenContract.test.ts +24 -0
- package/src/index.ts +2 -0
package/dist/AuthOverlay.js
CHANGED
|
@@ -46,6 +46,8 @@ const AuthOverlay = () => {
|
|
|
46
46
|
const [pickerVisible, setPickerVisible] = (0, react_1.useState)(false);
|
|
47
47
|
const [token, setToken] = (0, react_1.useState)(null);
|
|
48
48
|
const activeOverlayRef = (0, react_1.useRef)('none');
|
|
49
|
+
const onboarding = YaverFeedback_1.YaverFeedback.getDogfoodOnboarding();
|
|
50
|
+
const dogfoodLabel = onboarding?.projectName || onboarding?.label || 'this app';
|
|
49
51
|
const openLogin = (0, react_1.useCallback)(() => {
|
|
50
52
|
activeOverlayRef.current = 'login';
|
|
51
53
|
setPickerVisible(false);
|
|
@@ -120,10 +122,10 @@ const AuthOverlay = () => {
|
|
|
120
122
|
};
|
|
121
123
|
return (<>
|
|
122
124
|
<react_native_1.Modal visible={loginVisible} animationType="slide" presentationStyle="fullScreen" onRequestClose={closeAll}>
|
|
123
|
-
<LoginScreen_1.YaverLoginScreen onLoggedIn={handleLoggedIn} onCancel={closeAll}/>
|
|
125
|
+
<LoginScreen_1.YaverLoginScreen onLoggedIn={handleLoggedIn} onCancel={closeAll} subtitle={onboarding ? `Sign in to set up ${dogfoodLabel} Dogfood` : undefined}/>
|
|
124
126
|
</react_native_1.Modal>
|
|
125
127
|
<react_native_1.Modal visible={pickerVisible && !!token} animationType="slide" presentationStyle="fullScreen" onRequestClose={closeAll}>
|
|
126
|
-
{token && (<MachinePickerScreen_1.YaverMachinePickerScreen token={token} currentDeviceId={YaverFeedback_1.YaverFeedback.getConfig()?.preferredDeviceId} onPick={handleDevicePicked} onCancel={closeAll}/>)}
|
|
128
|
+
{token && (<MachinePickerScreen_1.YaverMachinePickerScreen token={token} currentDeviceId={YaverFeedback_1.YaverFeedback.getConfig()?.preferredDeviceId} title={onboarding ? `Choose a machine for ${dogfoodLabel}` : undefined} onPick={handleDevicePicked} onCancel={closeAll}/>)}
|
|
127
129
|
</react_native_1.Modal>
|
|
128
130
|
</>);
|
|
129
131
|
};
|
package/dist/DogfoodRuntime.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ export interface DogfoodProject {
|
|
|
17
17
|
workDir: string;
|
|
18
18
|
framework: string;
|
|
19
19
|
lane: DogfoodLane;
|
|
20
|
+
/**
|
|
21
|
+
* Optional automatic recovery lane. The shared onboarding flow uses the
|
|
22
|
+
* browser lane here when a user prefers Hermes or WebRTC for a project that
|
|
23
|
+
* can also render in a browser. The failed preferred attempt remains in the
|
|
24
|
+
* live console; the fallback is never silent.
|
|
25
|
+
*/
|
|
26
|
+
fallbackLane?: DogfoodLane;
|
|
20
27
|
/** Optional source URL for drivers that can clone missing source. */
|
|
21
28
|
repositoryUrl?: string;
|
|
22
29
|
/** Optional native target from /remote-runtime/capabilities for WebRTC. */
|
|
@@ -29,6 +36,12 @@ export interface DogfoodLaneOption {
|
|
|
29
36
|
default: boolean;
|
|
30
37
|
reason?: string;
|
|
31
38
|
}
|
|
39
|
+
export interface DogfoodLanePlan {
|
|
40
|
+
preferred: DogfoodLane;
|
|
41
|
+
/** Browser is the cheap, portable recovery lane for RN/Expo/Flutter/web. */
|
|
42
|
+
fallback?: DogfoodLane;
|
|
43
|
+
options: DogfoodLaneOption[];
|
|
44
|
+
}
|
|
32
45
|
/** One framework-to-lane matrix for Yaver and third-party consumers. */
|
|
33
46
|
export declare function dogfoodLaneOptions(framework: string, capabilities?: {
|
|
34
47
|
nativeRuntimeAvailable?: boolean;
|
|
@@ -40,6 +53,19 @@ export declare function defaultDogfoodLane(framework: string, capabilities?: {
|
|
|
40
53
|
browserRuntimeAvailable?: boolean;
|
|
41
54
|
selfDevelopment?: boolean;
|
|
42
55
|
}): DogfoodLane;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve one ordered lane policy for Yaver and embedded SDK hosts.
|
|
58
|
+
*
|
|
59
|
+
* Browser is the onboarding default for browser-capable React Native, Expo,
|
|
60
|
+
* Flutter, and web projects. When the user explicitly prefers Hermes or
|
|
61
|
+
* WebRTC, browser becomes the automatic second attempt. Native-only projects
|
|
62
|
+
* remain WebRTC-only and never advertise a browser recovery they cannot run.
|
|
63
|
+
*/
|
|
64
|
+
export declare function dogfoodLanePlan(framework: string, capabilities?: {
|
|
65
|
+
nativeRuntimeAvailable?: boolean;
|
|
66
|
+
browserRuntimeAvailable?: boolean;
|
|
67
|
+
selfDevelopment?: boolean;
|
|
68
|
+
}, preferred?: DogfoodLane | null): DogfoodLanePlan;
|
|
43
69
|
export interface DogfoodLogLine {
|
|
44
70
|
text: string;
|
|
45
71
|
at: number;
|
package/dist/DogfoodRuntime.js
CHANGED
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.DogfoodController = exports.dogfoodLogLinesFromDevEvent = exports.DogfoodRuntimeError = void 0;
|
|
16
16
|
exports.dogfoodLaneOptions = dogfoodLaneOptions;
|
|
17
17
|
exports.defaultDogfoodLane = defaultDogfoodLane;
|
|
18
|
+
exports.dogfoodLanePlan = dogfoodLanePlan;
|
|
18
19
|
exports.validateDogfoodProject = validateDogfoodProject;
|
|
19
20
|
exports.runtimeLogLinesFromDevEvent = runtimeLogLinesFromDevEvent;
|
|
20
21
|
/** One framework-to-lane matrix for Yaver and third-party consumers. */
|
|
@@ -49,6 +50,26 @@ function defaultDogfoodLane(framework, capabilities = {}) {
|
|
|
49
50
|
|| options.find((option) => option.supported)?.lane
|
|
50
51
|
|| 'browser';
|
|
51
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Resolve one ordered lane policy for Yaver and embedded SDK hosts.
|
|
55
|
+
*
|
|
56
|
+
* Browser is the onboarding default for browser-capable React Native, Expo,
|
|
57
|
+
* Flutter, and web projects. When the user explicitly prefers Hermes or
|
|
58
|
+
* WebRTC, browser becomes the automatic second attempt. Native-only projects
|
|
59
|
+
* remain WebRTC-only and never advertise a browser recovery they cannot run.
|
|
60
|
+
*/
|
|
61
|
+
function dogfoodLanePlan(framework, capabilities = {}, preferred) {
|
|
62
|
+
const options = dogfoodLaneOptions(framework, capabilities);
|
|
63
|
+
const supported = (lane) => !!lane && options.some((option) => option.lane === lane && option.supported);
|
|
64
|
+
const resolved = supported(preferred)
|
|
65
|
+
? preferred
|
|
66
|
+
: defaultDogfoodLane(framework, capabilities);
|
|
67
|
+
return {
|
|
68
|
+
preferred: resolved,
|
|
69
|
+
fallback: resolved !== 'browser' && supported('browser') ? 'browser' : undefined,
|
|
70
|
+
options,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
52
73
|
class DogfoodRuntimeError extends Error {
|
|
53
74
|
constructor(failure) {
|
|
54
75
|
super(failure.error);
|
|
@@ -173,8 +194,8 @@ class DogfoodController {
|
|
|
173
194
|
phase: 'preparing', attempt, project: this.project,
|
|
174
195
|
message: `Preparing ${this.project.name}…`, logs: [], startedAt: Date.now(),
|
|
175
196
|
});
|
|
176
|
-
const
|
|
177
|
-
project
|
|
197
|
+
const makeContext = (project) => ({
|
|
198
|
+
project,
|
|
178
199
|
attempt,
|
|
179
200
|
log: (line) => {
|
|
180
201
|
if (generation !== this.generation)
|
|
@@ -201,16 +222,69 @@ class DogfoodController {
|
|
|
201
222
|
this.cleanups.set(generation, owned);
|
|
202
223
|
},
|
|
203
224
|
isCurrent: () => generation === this.generation,
|
|
204
|
-
};
|
|
225
|
+
});
|
|
226
|
+
let activeProject = this.project;
|
|
227
|
+
let context = makeContext(activeProject);
|
|
205
228
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
229
|
+
const start = async () => {
|
|
230
|
+
await this.driver.prepare?.(context);
|
|
231
|
+
if (!context.isCurrent())
|
|
232
|
+
throw new DogfoodRuntimeError({
|
|
233
|
+
code: 'DOGFOOD_ATTEMPT_REPLACED', error: 'A newer Dogfood attempt replaced this one.',
|
|
234
|
+
remedy: 'Wait for the newer attempt.', retryable: true,
|
|
235
|
+
});
|
|
236
|
+
context.setPhase('starting', `Starting ${activeProject.name} on the ${activeProject.lane} lane…`);
|
|
237
|
+
return this.driver.start(context);
|
|
238
|
+
};
|
|
239
|
+
let result;
|
|
240
|
+
try {
|
|
241
|
+
result = await start();
|
|
242
|
+
}
|
|
243
|
+
catch (primaryError) {
|
|
244
|
+
const primaryFailure = failureFrom(primaryError);
|
|
245
|
+
const fallbackLane = activeProject.fallbackLane;
|
|
246
|
+
const mayFallback = !!fallbackLane
|
|
247
|
+
&& fallbackLane !== activeProject.lane
|
|
248
|
+
&& primaryFailure.retryable
|
|
249
|
+
&& primaryFailure.code !== 'DOGFOOD_ATTEMPT_REPLACED';
|
|
250
|
+
if (!mayFallback)
|
|
251
|
+
throw primaryError;
|
|
252
|
+
await this.runCleanups('all', generation);
|
|
253
|
+
const fallbackProject = {
|
|
254
|
+
...activeProject,
|
|
255
|
+
lane: fallbackLane,
|
|
256
|
+
fallbackLane: undefined,
|
|
257
|
+
};
|
|
258
|
+
const fallbackInvalid = validateDogfoodProject(fallbackProject);
|
|
259
|
+
if (fallbackInvalid)
|
|
260
|
+
throw primaryError;
|
|
261
|
+
const fallbackLine = {
|
|
262
|
+
text: `[fallback] ${activeProject.lane} failed (${primaryFailure.code}); trying ${fallbackLane}`,
|
|
263
|
+
at: Date.now(),
|
|
264
|
+
stream: 'system',
|
|
265
|
+
};
|
|
266
|
+
activeProject = fallbackProject;
|
|
267
|
+
this.replace({
|
|
268
|
+
...this.state,
|
|
269
|
+
project: activeProject,
|
|
270
|
+
phase: 'preparing',
|
|
271
|
+
message: `Recovering ${activeProject.name} in the ${fallbackLane} lane…`,
|
|
272
|
+
logs: [...this.state.logs, fallbackLine].slice(-this.maxLogLines),
|
|
273
|
+
lastOutputAt: fallbackLine.at,
|
|
274
|
+
failure: undefined,
|
|
211
275
|
});
|
|
212
|
-
|
|
213
|
-
|
|
276
|
+
context = makeContext(activeProject);
|
|
277
|
+
result = await start();
|
|
278
|
+
result = {
|
|
279
|
+
...result,
|
|
280
|
+
metadata: {
|
|
281
|
+
...result.metadata,
|
|
282
|
+
preferredLane: this.project.lane,
|
|
283
|
+
fallbackFrom: this.project.lane,
|
|
284
|
+
fallbackReason: primaryFailure.code,
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
214
288
|
if (!context.isCurrent()) {
|
|
215
289
|
await this.runCleanups('all', generation);
|
|
216
290
|
throw new DogfoodRuntimeError({
|
|
@@ -218,7 +292,7 @@ class DogfoodController {
|
|
|
218
292
|
remedy: 'Wait for the newer attempt.', retryable: true,
|
|
219
293
|
});
|
|
220
294
|
}
|
|
221
|
-
this.replace({ ...this.state, phase: 'ready', message: `${
|
|
295
|
+
this.replace({ ...this.state, project: activeProject, phase: 'ready', message: `${activeProject.name} is ready`, result, failure: undefined });
|
|
222
296
|
return result;
|
|
223
297
|
}
|
|
224
298
|
catch (error) {
|
|
@@ -32,6 +32,7 @@ export declare const DogfoodStatusRail: React.FC<{
|
|
|
32
32
|
export declare const DogfoodLanePicker: React.FC<{
|
|
33
33
|
options: readonly DogfoodLaneOption[];
|
|
34
34
|
selected: DogfoodLane;
|
|
35
|
+
fallbackLane?: DogfoodLane;
|
|
35
36
|
onSelect: (lane: DogfoodLane) => void;
|
|
36
37
|
colors?: Partial<DogfoodUiColors>;
|
|
37
38
|
showUnsupportedReasons?: boolean;
|
package/dist/DogfoodSessionUi.js
CHANGED
|
@@ -54,7 +54,7 @@ const DogfoodStatusRail = ({ steps, colors: colorOverrides }) => {
|
|
|
54
54
|
};
|
|
55
55
|
exports.DogfoodStatusRail = DogfoodStatusRail;
|
|
56
56
|
/** One lane selector and one default policy across Yaver, SFMG, and Talos. */
|
|
57
|
-
const DogfoodLanePicker = ({ options, selected, onSelect, colors: colorOverrides, showUnsupportedReasons = true }) => {
|
|
57
|
+
const DogfoodLanePicker = ({ options, selected, fallbackLane, onSelect, colors: colorOverrides, showUnsupportedReasons = true }) => {
|
|
58
58
|
const colors = resolvedColors(colorOverrides);
|
|
59
59
|
return (<react_native_1.View accessibilityRole="radiogroup" accessibilityLabel="Dogfood runtime lane">
|
|
60
60
|
<react_native_1.View style={styles.choiceRow}>
|
|
@@ -69,7 +69,8 @@ const DogfoodLanePicker = ({ options, selected, onSelect, colors: colorOverrides
|
|
|
69
69
|
},
|
|
70
70
|
]}>
|
|
71
71
|
<react_native_1.Text style={[styles.choiceText, { color: colors.text }, active && styles.choiceTextActive]}>
|
|
72
|
-
{option.label}
|
|
72
|
+
{option.label}
|
|
73
|
+
{active ? ' · preferred' : fallbackLane === option.lane ? ' · automatic fallback' : option.default ? ' · default' : ''}
|
|
73
74
|
</react_native_1.Text>
|
|
74
75
|
</react_native_1.Pressable>);
|
|
75
76
|
})}
|