yaver-feedback-react-native 0.9.9 → 0.9.11
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/app.plugin.js +24 -10
- package/dist/DogfoodRuntime.d.ts +32 -1
- package/dist/DogfoodRuntime.js +94 -14
- package/dist/DogfoodSessionUi.d.ts +2 -0
- package/dist/DogfoodSessionUi.js +8 -4
- package/dist/FeedbackModal.js +263 -278
- package/dist/FeedbackModalTheme.d.ts +5 -0
- package/dist/FeedbackModalTheme.js +29 -0
- package/dist/P2PClient.d.ts +2 -0
- package/dist/P2PClient.js +1 -1
- package/dist/P2PDogfoodDriver.js +17 -0
- package/dist/__tests__/DogfoodRuntime.test.js +59 -0
- package/dist/__tests__/FeedbackModalContract.test.d.ts +1 -0
- package/dist/__tests__/FeedbackModalContract.test.js +77 -0
- package/dist/__tests__/NativeDogfoodShortcut.test.js +23 -0
- package/dist/__tests__/P2PDogfoodDriver.test.js +4 -1
- package/dist/index.d.ts +6 -7
- package/dist/index.js +7 -7
- package/ios/YaverHotReload.swift +3 -4
- package/package.json +1 -1
- package/src/DogfoodRuntime.ts +129 -15
- package/src/DogfoodSessionUi.tsx +10 -4
- package/src/FeedbackModal.tsx +335 -372
- package/src/FeedbackModalTheme.ts +29 -0
- package/src/P2PClient.ts +3 -1
- package/src/P2PDogfoodDriver.ts +17 -0
- package/src/__tests__/DogfoodRuntime.test.ts +66 -0
- package/src/__tests__/FeedbackModalContract.test.ts +88 -0
- package/src/__tests__/NativeDogfoodShortcut.test.ts +25 -0
- package/src/__tests__/P2PDogfoodDriver.test.ts +4 -0
- package/src/index.ts +6 -5
package/dist/FeedbackModal.js
CHANGED
|
@@ -37,21 +37,25 @@ exports.FeedbackModal = void 0;
|
|
|
37
37
|
const react_1 = __importStar(require("react"));
|
|
38
38
|
const react_native_1 = require("react-native");
|
|
39
39
|
const YaverFeedback_1 = require("./YaverFeedback");
|
|
40
|
-
const capture_1 = require("./capture");
|
|
41
|
-
const upload_1 = require("./upload");
|
|
42
|
-
const P2PClient_1 = require("./P2PClient");
|
|
43
40
|
const AuthOverlay_1 = require("./AuthOverlay");
|
|
44
41
|
const QuickActionIcon_1 = require("./QuickActionIcon");
|
|
45
42
|
const YaverModeBadge_1 = require("./YaverModeBadge");
|
|
46
43
|
const VibeChatScreen_1 = require("./VibeChatScreen");
|
|
47
44
|
const DogfoodQuickControls_1 = require("./DogfoodQuickControls");
|
|
48
|
-
const DeployPanel_1 = require("./DeployPanel");
|
|
49
45
|
const auth_1 = require("./auth");
|
|
50
46
|
const reloadActions_1 = require("./reloadActions");
|
|
51
47
|
const preferences_1 = require("./preferences");
|
|
52
48
|
const DogfoodRuntime_1 = require("./DogfoodRuntime");
|
|
53
49
|
const P2PDogfoodDriver_1 = require("./P2PDogfoodDriver");
|
|
54
50
|
const DogfoodSessionUi_1 = require("./DogfoodSessionUi");
|
|
51
|
+
const FeedbackModalTheme_1 = require("./FeedbackModalTheme");
|
|
52
|
+
function dogfoodCheckoutDetail(project) {
|
|
53
|
+
if (!project)
|
|
54
|
+
return 'Choose a Git checkout on the selected machine';
|
|
55
|
+
return [project.path, project.branch ? `branch ${project.branch}` : project.gitRemote ? 'Git checkout' : 'checkout']
|
|
56
|
+
.filter(Boolean)
|
|
57
|
+
.join(' · ');
|
|
58
|
+
}
|
|
55
59
|
const PRIMARY_RUNNER_IDS = ['claude', 'codex', 'opencode'];
|
|
56
60
|
function normalizeRunnerStatusRows(rows) {
|
|
57
61
|
const byId = new Map();
|
|
@@ -174,17 +178,12 @@ const FeedbackModal = () => {
|
|
|
174
178
|
// Which reload action is in flight, so only that button spins.
|
|
175
179
|
const [reloadingId, setReloadingId] = (0, react_1.useState)(null);
|
|
176
180
|
const [runnerAuthModal, setRunnerAuthModal] = (0, react_1.useState)(null);
|
|
177
|
-
//
|
|
178
|
-
//
|
|
179
|
-
// the user say WHAT they want to vibe on instead of firing a canned
|
|
180
|
-
// "pick something for me" prompt (which in 0.7.13 pointed Claude at
|
|
181
|
-
// the wrong project because the matcher grepped the prompt itself).
|
|
181
|
+
// Signed-in users get the composer immediately. Signed-out users still get
|
|
182
|
+
// an explicit entry action so auth/setup failures remain named and visible.
|
|
182
183
|
const [showVibeInput, setShowVibeInput] = (0, react_1.useState)(false);
|
|
183
|
-
const [showDeploy, setShowDeploy] = (0, react_1.useState)(false);
|
|
184
184
|
const [vibePrompt, setVibePrompt] = (0, react_1.useState)('');
|
|
185
185
|
const [lastVibeTaskId, setLastVibeTaskId] = (0, react_1.useState)(null);
|
|
186
186
|
const [quickIconColorPreset, setQuickIconColorPreset] = (0, react_1.useState)(null);
|
|
187
|
-
const [keyboardInset, setKeyboardInset] = (0, react_1.useState)(0);
|
|
188
187
|
const [machineCard, setMachineCard] = (0, react_1.useState)({
|
|
189
188
|
device: null,
|
|
190
189
|
reachable: null,
|
|
@@ -206,6 +205,11 @@ const FeedbackModal = () => {
|
|
|
206
205
|
const [dogfoodProject, setDogfoodProject] = (0, react_1.useState)(null);
|
|
207
206
|
const [dogfoodLane, setDogfoodLane] = (0, react_1.useState)('browser');
|
|
208
207
|
const [dogfoodNativeAvailable, setDogfoodNativeAvailable] = (0, react_1.useState)(false);
|
|
208
|
+
const [dogfoodBrowserAvailable, setDogfoodBrowserAvailable] = (0, react_1.useState)(false);
|
|
209
|
+
const [dogfoodNativeTargets, setDogfoodNativeTargets] = (0, react_1.useState)([]);
|
|
210
|
+
const [dogfoodNativeTargetId, setDogfoodNativeTargetId] = (0, react_1.useState)('');
|
|
211
|
+
const [dogfoodSetupStage, setDogfoodSetupStage] = (0, react_1.useState)('setup');
|
|
212
|
+
const [dogfoodExpandedStep, setDogfoodExpandedStep] = (0, react_1.useState)(null);
|
|
209
213
|
const [dogfoodRuntime, setDogfoodRuntime] = (0, react_1.useState)(null);
|
|
210
214
|
const [dogfoodSetupLoading, setDogfoodSetupLoading] = (0, react_1.useState)(false);
|
|
211
215
|
const dogfoodControllerRef = (0, react_1.useRef)(null);
|
|
@@ -241,13 +245,25 @@ const FeedbackModal = () => {
|
|
|
241
245
|
if (preferred) {
|
|
242
246
|
const framework = preferred.framework || onboarding.framework || 'expo';
|
|
243
247
|
const capabilities = await client.getDogfoodRemoteRuntimeCapabilities(preferred.path, framework).catch(() => null);
|
|
244
|
-
const
|
|
245
|
-
|
|
248
|
+
const targets = capabilities?.targets || [];
|
|
249
|
+
const nativeTargets = targets.filter((target) => target.id !== 'browser-window');
|
|
250
|
+
const enabledNativeTargets = nativeTargets.filter((target) => target.enabled);
|
|
251
|
+
const nativeRuntimeAvailable = enabledNativeTargets.length > 0;
|
|
252
|
+
const browserRuntimeAvailable = targets.some((target) => target.enabled && target.id === 'browser-window');
|
|
253
|
+
if (mountedRef.current) {
|
|
246
254
|
setDogfoodNativeAvailable(nativeRuntimeAvailable);
|
|
255
|
+
setDogfoodBrowserAvailable(browserRuntimeAvailable);
|
|
256
|
+
setDogfoodNativeTargets(nativeTargets);
|
|
257
|
+
setDogfoodNativeTargetId((current) => enabledNativeTargets.some((target) => target.id === current)
|
|
258
|
+
? current
|
|
259
|
+
: enabledNativeTargets[0]?.id || '');
|
|
260
|
+
}
|
|
247
261
|
const savedLane = await (0, preferences_1.getPreferredDogfoodLane)(onboarding.appId);
|
|
248
|
-
const savedSupported = (0, DogfoodRuntime_1.dogfoodLaneOptions)(framework, { nativeRuntimeAvailable })
|
|
262
|
+
const savedSupported = (0, DogfoodRuntime_1.dogfoodLaneOptions)(framework, { nativeRuntimeAvailable, browserRuntimeAvailable })
|
|
249
263
|
.some((option) => option.lane === savedLane && option.supported);
|
|
250
|
-
setDogfoodLane(savedLane && savedSupported
|
|
264
|
+
setDogfoodLane(savedLane && savedSupported
|
|
265
|
+
? savedLane
|
|
266
|
+
: (0, DogfoodRuntime_1.defaultDogfoodLane)(framework, { nativeRuntimeAvailable, browserRuntimeAvailable }));
|
|
251
267
|
}
|
|
252
268
|
}
|
|
253
269
|
catch (cause) {
|
|
@@ -262,14 +278,33 @@ const FeedbackModal = () => {
|
|
|
262
278
|
(0, react_1.useEffect)(() => {
|
|
263
279
|
let cancelled = false;
|
|
264
280
|
setDogfoodNativeAvailable(false);
|
|
281
|
+
setDogfoodBrowserAvailable(false);
|
|
282
|
+
setDogfoodNativeTargets([]);
|
|
283
|
+
setDogfoodNativeTargetId('');
|
|
265
284
|
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
266
285
|
if (!client || !dogfoodProject)
|
|
267
286
|
return () => { cancelled = true; };
|
|
268
287
|
const framework = dogfoodProject.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo';
|
|
269
288
|
void client.getDogfoodRemoteRuntimeCapabilities(dogfoodProject.path, framework)
|
|
270
289
|
.then((value) => {
|
|
271
|
-
if (
|
|
272
|
-
|
|
290
|
+
if (cancelled)
|
|
291
|
+
return;
|
|
292
|
+
const nativeTargets = value.targets.filter((target) => target.id !== 'browser-window');
|
|
293
|
+
const enabledNativeTargets = nativeTargets.filter((target) => target.enabled);
|
|
294
|
+
setDogfoodNativeAvailable(enabledNativeTargets.length > 0);
|
|
295
|
+
setDogfoodBrowserAvailable(value.targets.some((target) => target.enabled && target.id === 'browser-window'));
|
|
296
|
+
setDogfoodNativeTargets(nativeTargets);
|
|
297
|
+
setDogfoodNativeTargetId((current) => enabledNativeTargets.some((target) => target.id === current)
|
|
298
|
+
? current
|
|
299
|
+
: enabledNativeTargets[0]?.id || '');
|
|
300
|
+
const laneCapabilities = {
|
|
301
|
+
nativeRuntimeAvailable: enabledNativeTargets.length > 0,
|
|
302
|
+
browserRuntimeAvailable: value.targets.some((target) => target.enabled && target.id === 'browser-window'),
|
|
303
|
+
};
|
|
304
|
+
setDogfoodLane((current) => (0, DogfoodRuntime_1.dogfoodLaneOptions)(framework, laneCapabilities)
|
|
305
|
+
.some((option) => option.lane === current && option.supported)
|
|
306
|
+
? current
|
|
307
|
+
: (0, DogfoodRuntime_1.defaultDogfoodLane)(framework, laneCapabilities));
|
|
273
308
|
})
|
|
274
309
|
.catch(() => { });
|
|
275
310
|
return () => { cancelled = true; };
|
|
@@ -281,19 +316,26 @@ const FeedbackModal = () => {
|
|
|
281
316
|
return;
|
|
282
317
|
await dogfoodControllerRef.current?.stop().catch(() => { });
|
|
283
318
|
const framework = dogfoodProject.framework || onboarding.framework || 'expo';
|
|
319
|
+
const lanePlan = (0, DogfoodRuntime_1.dogfoodLanePlan)(framework, {
|
|
320
|
+
nativeRuntimeAvailable: dogfoodNativeAvailable,
|
|
321
|
+
browserRuntimeAvailable: dogfoodBrowserAvailable,
|
|
322
|
+
}, dogfoodLane);
|
|
284
323
|
const controller = new DogfoodRuntime_1.DogfoodController({
|
|
285
324
|
name: dogfoodProject.name,
|
|
286
325
|
workDir: dogfoodProject.path,
|
|
287
326
|
framework,
|
|
288
|
-
lane:
|
|
327
|
+
lane: lanePlan.preferred,
|
|
328
|
+
fallbackLane: lanePlan.fallback,
|
|
329
|
+
nativeTargetId: lanePlan.preferred === 'webrtc' ? dogfoodNativeTargetId : undefined,
|
|
289
330
|
}, (0, P2PDogfoodDriver_1.createP2PDogfoodDriver)(client), {
|
|
290
331
|
onChange: (snapshot) => { if (mountedRef.current)
|
|
291
332
|
setDogfoodRuntime(snapshot); },
|
|
292
333
|
});
|
|
293
334
|
dogfoodControllerRef.current = controller;
|
|
294
335
|
setDogfoodRuntime(controller.snapshot());
|
|
336
|
+
setDogfoodSetupStage('runtime');
|
|
295
337
|
await controller.trigger().catch(() => { });
|
|
296
|
-
}, [dogfoodLane, dogfoodProject]);
|
|
338
|
+
}, [dogfoodLane, dogfoodNativeTargetId, dogfoodProject]);
|
|
297
339
|
/**
|
|
298
340
|
* Ask the machine what its dev server is doing, so the reload actions can
|
|
299
341
|
* be enabled/disabled against reality rather than against a guess.
|
|
@@ -486,16 +528,24 @@ const FeedbackModal = () => {
|
|
|
486
528
|
// user's feedback preference merely to open Developer Mode.
|
|
487
529
|
if (YaverFeedback_1.YaverFeedback.isEnabled() || onboarding) {
|
|
488
530
|
const directDogfood = YaverFeedback_1.YaverFeedback.getDogfoodStatus().active;
|
|
531
|
+
const authenticated = YaverFeedback_1.YaverFeedback.isAuthed();
|
|
489
532
|
setDogfoodActive(directDogfood);
|
|
490
533
|
setVisible(true);
|
|
491
534
|
setError(null);
|
|
492
535
|
setToast(null);
|
|
493
536
|
setProgress(null);
|
|
494
537
|
setAction('idle');
|
|
495
|
-
setShowVibeInput(directDogfood);
|
|
538
|
+
setShowVibeInput(authenticated || directDogfood);
|
|
496
539
|
setVibePrompt('');
|
|
497
540
|
if (onboarding) {
|
|
541
|
+
// A Dogfood shortcut is an explicit setup/runtime intent. Opening on
|
|
542
|
+
// Chat hid the machine/runner/checkout gate for signed-in SFMG users;
|
|
543
|
+
// keep the SDK-owned Dogfood surface visible, then show its live logs
|
|
544
|
+
// immediately when Start is tapped.
|
|
498
545
|
setActiveTab('settings');
|
|
546
|
+
setDogfoodSetupStage('setup');
|
|
547
|
+
setDogfoodExpandedStep(null);
|
|
548
|
+
setDogfoodRuntime(null);
|
|
499
549
|
void loadDogfoodOnboarding();
|
|
500
550
|
}
|
|
501
551
|
// Re-read the "user hid the quick icon" flag on every open so
|
|
@@ -566,30 +616,14 @@ const FeedbackModal = () => {
|
|
|
566
616
|
}, 5000);
|
|
567
617
|
return () => clearInterval(interval);
|
|
568
618
|
}, [loadRunnerStatuses, loadSelectedMachine, refreshDevSnapshot, visible]);
|
|
569
|
-
(0, react_1.useEffect)(() => {
|
|
570
|
-
if (!visible) {
|
|
571
|
-
setKeyboardInset(0);
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
const showEvent = react_native_1.Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
|
|
575
|
-
const hideEvent = react_native_1.Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
|
|
576
|
-
const showSub = react_native_1.Keyboard.addListener(showEvent, (event) => {
|
|
577
|
-
setKeyboardInset(event.endCoordinates?.height ?? 0);
|
|
578
|
-
});
|
|
579
|
-
const hideSub = react_native_1.Keyboard.addListener(hideEvent, () => {
|
|
580
|
-
setKeyboardInset(0);
|
|
581
|
-
});
|
|
582
|
-
return () => {
|
|
583
|
-
showSub.remove();
|
|
584
|
-
hideSub.remove();
|
|
585
|
-
};
|
|
586
|
-
}, [visible]);
|
|
587
619
|
(0, react_1.useEffect)(() => {
|
|
588
620
|
if (!visible || !showVibeInput)
|
|
589
621
|
return;
|
|
590
|
-
|
|
622
|
+
// UIKit owns keyboard insets on the ScrollView. This one bounded scroll only
|
|
623
|
+
// reveals the newly mounted composer; it does not add a second inset.
|
|
624
|
+
const timer = setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), 80);
|
|
591
625
|
return () => clearTimeout(timer);
|
|
592
|
-
}, [
|
|
626
|
+
}, [showVibeInput, visible]);
|
|
593
627
|
const closeSoon = (0, react_1.useCallback)((delayMs = 1200) => {
|
|
594
628
|
setTimeout(() => {
|
|
595
629
|
if (mountedRef.current)
|
|
@@ -605,6 +639,9 @@ const FeedbackModal = () => {
|
|
|
605
639
|
setShowVibeInput(false);
|
|
606
640
|
setVibePrompt('');
|
|
607
641
|
setRunnerStatusError(null);
|
|
642
|
+
setDogfoodSetupStage('setup');
|
|
643
|
+
setDogfoodExpandedStep(null);
|
|
644
|
+
setDogfoodRuntime(null);
|
|
608
645
|
void dogfoodControllerRef.current?.stop().catch(() => { });
|
|
609
646
|
dogfoodControllerRef.current = null;
|
|
610
647
|
YaverFeedback_1.YaverFeedback.clearDogfoodOnboarding();
|
|
@@ -791,107 +828,7 @@ const FeedbackModal = () => {
|
|
|
791
828
|
setAction('idle');
|
|
792
829
|
}
|
|
793
830
|
}, [closeSoon, loadSelectedMachine, runWithReconnect]);
|
|
794
|
-
|
|
795
|
-
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
796
|
-
const config = YaverFeedback_1.YaverFeedback.getConfig();
|
|
797
|
-
if (!client || !config?.agentUrl) {
|
|
798
|
-
setError('Not connected to the agent yet.');
|
|
799
|
-
return;
|
|
800
|
-
}
|
|
801
|
-
try {
|
|
802
|
-
const uploaded = await (0, upload_1.uploadFeedback)(config.agentUrl, config.authToken ?? '', bundle, YaverFeedback_1.YaverFeedback.getRelayPassword());
|
|
803
|
-
// The agent returns the new report id as `id` (see
|
|
804
|
-
// feedback_http.go::ReceiveFeedback). Trigger the fix loop if we got
|
|
805
|
-
// one back; otherwise just ack the upload.
|
|
806
|
-
const reportId = uploaded?.id ??
|
|
807
|
-
uploaded?.reportId;
|
|
808
|
-
if (reportId && fixOnUpload) {
|
|
809
|
-
try {
|
|
810
|
-
await client.triggerFix(reportId);
|
|
811
|
-
setToast(successToast);
|
|
812
|
-
}
|
|
813
|
-
catch (err) {
|
|
814
|
-
setToast(failureToast ?? 'Report uploaded — fix trigger failed');
|
|
815
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
else {
|
|
819
|
-
setToast(successToast);
|
|
820
|
-
}
|
|
821
|
-
closeSoon(1400);
|
|
822
|
-
}
|
|
823
|
-
catch (err) {
|
|
824
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
825
|
-
}
|
|
826
|
-
}, [closeSoon]);
|
|
827
|
-
const handleScreenshotAndFix = (0, react_1.useCallback)(async () => {
|
|
828
|
-
setAction('capturing');
|
|
829
|
-
setError(null);
|
|
830
|
-
setVisible(false);
|
|
831
|
-
await new Promise((resolve) => setTimeout(resolve, 350));
|
|
832
|
-
let path;
|
|
833
|
-
try {
|
|
834
|
-
path = await (0, capture_1.captureScreenshot)();
|
|
835
|
-
}
|
|
836
|
-
catch (err) {
|
|
837
|
-
setVisible(true);
|
|
838
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
839
|
-
setAction('idle');
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
setVisible(true);
|
|
843
|
-
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
844
|
-
try {
|
|
845
|
-
const { Dimensions } = require('react-native');
|
|
846
|
-
const { width, height } = Dimensions.get('window');
|
|
847
|
-
const cfg = YaverFeedback_1.YaverFeedback.getConfig();
|
|
848
|
-
const identity = (0, P2PClient_1.resolveReportIdentity)({
|
|
849
|
-
projectName: cfg?.projectName,
|
|
850
|
-
bundleId: cfg?.bundleId,
|
|
851
|
-
surface: cfg?.surface,
|
|
852
|
-
surfaces: cfg?.surfaces,
|
|
853
|
-
stack: cfg?.stack,
|
|
854
|
-
stacks: cfg?.stacks,
|
|
855
|
-
testSurfaces: cfg?.testSurfaces,
|
|
856
|
-
feedbackSdk: cfg?.feedbackSdk,
|
|
857
|
-
feedbackTransport: cfg?.feedbackTransport,
|
|
858
|
-
voiceCapabilities: cfg?.voiceCapabilities,
|
|
859
|
-
sttProvider: cfg?.sttProvider,
|
|
860
|
-
ttsProvider: cfg?.ttsProvider,
|
|
861
|
-
});
|
|
862
|
-
const deviceInfo = {
|
|
863
|
-
platform: react_native_1.Platform.OS,
|
|
864
|
-
osVersion: String(react_native_1.Platform.Version),
|
|
865
|
-
model: react_native_1.Platform.OS === 'ios' ? 'iOS Device' : 'Android Device',
|
|
866
|
-
screenWidth: width,
|
|
867
|
-
screenHeight: height,
|
|
868
|
-
appName: identity.appName,
|
|
869
|
-
};
|
|
870
|
-
const capturedErrors = YaverFeedback_1.YaverFeedback.getCapturedErrors();
|
|
871
|
-
const bundle = {
|
|
872
|
-
metadata: {
|
|
873
|
-
timestamp: new Date().toISOString(),
|
|
874
|
-
deviceInfo,
|
|
875
|
-
app: identity.app,
|
|
876
|
-
project: identity.project,
|
|
877
|
-
userNote: '[Screenshot + Fix]',
|
|
878
|
-
},
|
|
879
|
-
screenshots: [path],
|
|
880
|
-
errors: capturedErrors.length > 0 ? capturedErrors : undefined,
|
|
881
|
-
};
|
|
882
|
-
await uploadBundleWithOptionalFix(bundle, true, 'Fix task started');
|
|
883
|
-
}
|
|
884
|
-
finally {
|
|
885
|
-
if (mountedRef.current)
|
|
886
|
-
setAction('idle');
|
|
887
|
-
}
|
|
888
|
-
}, [uploadBundleWithOptionalFix]);
|
|
889
|
-
/*
|
|
890
|
-
const handleFileUpload = useCallback(async () => {
|
|
891
|
-
...
|
|
892
|
-
}, [uploadBundleWithOptionalFix]);
|
|
893
|
-
*/
|
|
894
|
-
// ─── 3. Vibing ─────────────────────────────────────────────────────
|
|
831
|
+
// ─── Chat ──────────────────────────────────────────────────────────
|
|
895
832
|
// First tap expands the input; second submit fires the actual
|
|
896
833
|
// /vibing/execute. Mirrors the Yaver mobile app's Vibing tab —
|
|
897
834
|
// user types what they want, hits Send, sees the task id back. If
|
|
@@ -1025,42 +962,59 @@ const FeedbackModal = () => {
|
|
|
1025
962
|
&& (selectedDogfoodRunner.ready || selectedDogfoodRunner.authConfigured);
|
|
1026
963
|
const dogfoodModelReady = !selectedDogfoodRunner?.models?.length
|
|
1027
964
|
|| !!preferredModel && selectedDogfoodRunner.models.some((model) => model.id === preferredModel);
|
|
1028
|
-
const
|
|
1029
|
-
const
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
detail: dogfoodEnrollment?.status === 'active' ? 'Device key approved' : dogfoodEnrollment?.status || 'Checking device key',
|
|
1044
|
-
tone: dogfoodEnrollment?.status === 'active' ? 'ready'
|
|
1045
|
-
: dogfoodEnrollment?.status === 'failed' ? 'blocked' : 'pending',
|
|
1046
|
-
},
|
|
965
|
+
const dogfoodFramework = dogfoodProject?.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo';
|
|
966
|
+
const dogfoodLaneChoices = (0, DogfoodRuntime_1.dogfoodLaneOptions)(dogfoodFramework, {
|
|
967
|
+
nativeRuntimeAvailable: dogfoodNativeAvailable,
|
|
968
|
+
browserRuntimeAvailable: dogfoodBrowserAvailable,
|
|
969
|
+
});
|
|
970
|
+
const dogfoodLanePolicy = (0, DogfoodRuntime_1.dogfoodLanePlan)(dogfoodFramework, {
|
|
971
|
+
nativeRuntimeAvailable: dogfoodNativeAvailable,
|
|
972
|
+
browserRuntimeAvailable: dogfoodBrowserAvailable,
|
|
973
|
+
}, dogfoodLane);
|
|
974
|
+
const selectedDogfoodNativeTarget = dogfoodNativeTargets.find((target) => target.id === dogfoodNativeTargetId) || null;
|
|
975
|
+
const dogfoodLaneReady = dogfoodLaneChoices.some((option) => option.lane === dogfoodLane && option.supported)
|
|
976
|
+
&& (dogfoodLane !== 'webrtc' || !!selectedDogfoodNativeTarget?.enabled);
|
|
977
|
+
const dogfoodMachineReady = !!machineCard.device && machineCard.status === 'live';
|
|
978
|
+
const dogfoodSetupReady = dogfoodMachineReady && !!dogfoodProject && dogfoodRunnerReady && dogfoodModelReady;
|
|
979
|
+
const dogfoodSetupSteps = [
|
|
1047
980
|
{
|
|
1048
|
-
key: '
|
|
1049
|
-
|
|
1050
|
-
|
|
981
|
+
key: 'box',
|
|
982
|
+
label: 'Remote box',
|
|
983
|
+
detail: dogfoodMachineReady ? machineCard.title : 'Choose a reachable development machine',
|
|
984
|
+
tone: dogfoodMachineReady ? 'ready' : 'attention',
|
|
985
|
+
actionLabel: machineCard.device ? 'Change' : 'Pick',
|
|
986
|
+
onAction: () => YaverFeedback_1.YaverFeedback.showMachinePicker(),
|
|
1051
987
|
},
|
|
1052
988
|
{
|
|
1053
|
-
key: '
|
|
1054
|
-
|
|
1055
|
-
|
|
989
|
+
key: 'runner',
|
|
990
|
+
label: 'Runner',
|
|
991
|
+
detail: dogfoodRunnerReady
|
|
992
|
+
? [selectedDogfoodRunner?.name || preferredRunner || 'Ready', preferredModel || 'default model'].join(' · ')
|
|
993
|
+
: 'Choose or configure a coding runner',
|
|
994
|
+
tone: dogfoodRunnerReady && dogfoodModelReady ? 'ready' : 'attention',
|
|
995
|
+
actionLabel: dogfoodExpandedStep === 'runner' ? 'Done' : dogfoodRunnerReady ? 'Change' : 'Choose',
|
|
996
|
+
expanded: dogfoodExpandedStep === 'runner',
|
|
997
|
+
onAction: () => setDogfoodExpandedStep((current) => current === 'runner' ? null : 'runner'),
|
|
1056
998
|
},
|
|
1057
999
|
{
|
|
1058
|
-
key: '
|
|
1059
|
-
|
|
1060
|
-
|
|
1000
|
+
key: 'checkout',
|
|
1001
|
+
label: 'Checkout',
|
|
1002
|
+
detail: dogfoodCheckoutDetail(dogfoodProject),
|
|
1003
|
+
tone: dogfoodProject ? 'ready' : 'attention',
|
|
1004
|
+
actionLabel: dogfoodExpandedStep === 'checkout' ? 'Done' : dogfoodProject ? 'Change' : 'Choose',
|
|
1005
|
+
expanded: dogfoodExpandedStep === 'checkout',
|
|
1006
|
+
onAction: () => setDogfoodExpandedStep((current) => current === 'checkout' ? null : 'checkout'),
|
|
1061
1007
|
},
|
|
1062
1008
|
];
|
|
1063
|
-
const dogfoodStartBlocked = !
|
|
1009
|
+
const dogfoodStartBlocked = !dogfoodSetupReady || !dogfoodLaneReady;
|
|
1010
|
+
const activeDogfoodLane = dogfoodRuntime?.project.lane || dogfoodLane;
|
|
1011
|
+
const dogfoodSourceLabel = activeDogfoodLane === 'webrtc'
|
|
1012
|
+
? selectedDogfoodNativeTarget
|
|
1013
|
+
? [selectedDogfoodNativeTarget.label, selectedDogfoodNativeTarget.platform].filter(Boolean).join(' · ')
|
|
1014
|
+
: 'Native simulator, emulator, or device'
|
|
1015
|
+
: activeDogfoodLane === 'hermes'
|
|
1016
|
+
? `Hermes build · ${machineCard.title}`
|
|
1017
|
+
: `${dogfoodFramework === 'flutter' ? 'Flutter web compiler' : 'Metro / browser build'} · ${machineCard.title}`;
|
|
1064
1018
|
// Once the user fires off a vibe task, swap the entire modal body
|
|
1065
1019
|
// for the live chat screen. The chat manages its own SSE
|
|
1066
1020
|
// subscription, multi-turn follow-ups, and Reload button. Closing
|
|
@@ -1091,9 +1045,9 @@ const FeedbackModal = () => {
|
|
|
1091
1045
|
<QuickActionIcon_1.QuickActionIcon />
|
|
1092
1046
|
<YaverModeBadgeGate />
|
|
1093
1047
|
{visible && (<react_native_1.Modal visible={visible} animationType="slide" transparent onRequestClose={handleClose}>
|
|
1094
|
-
<react_native_1.
|
|
1095
|
-
<react_native_1.
|
|
1096
|
-
<react_native_1.
|
|
1048
|
+
<react_native_1.View style={styles.overlay}>
|
|
1049
|
+
<react_native_1.Pressable style={styles.backdrop} onPress={handleClose} accessibilityLabel="Close feedback"/>
|
|
1050
|
+
<react_native_1.View
|
|
1097
1051
|
// Tablet: cap modal width and center as a card-style
|
|
1098
1052
|
// sheet rather than a phone bottom sheet that stretches
|
|
1099
1053
|
// across a 12.9" iPad. Phone behaviour unchanged.
|
|
@@ -1108,16 +1062,8 @@ const FeedbackModal = () => {
|
|
|
1108
1062
|
borderTopRightRadius: 22,
|
|
1109
1063
|
}
|
|
1110
1064
|
: null,
|
|
1111
|
-
]}
|
|
1112
|
-
|
|
1113
|
-
react_native_1.Keyboard.dismiss();
|
|
1114
|
-
}}>
|
|
1115
|
-
<react_native_1.ScrollView ref={scrollRef} style={styles.scroll} contentContainerStyle={[
|
|
1116
|
-
styles.scrollContent,
|
|
1117
|
-
showVibeInput && keyboardInset > 0
|
|
1118
|
-
? { paddingBottom: 8 + keyboardInset }
|
|
1119
|
-
: null,
|
|
1120
|
-
]} keyboardShouldPersistTaps="handled" keyboardDismissMode={react_native_1.Platform.OS === 'ios' ? 'interactive' : 'on-drag'} contentInsetAdjustmentBehavior="always" automaticallyAdjustKeyboardInsets={react_native_1.Platform.OS === 'ios'}>
|
|
1065
|
+
]}>
|
|
1066
|
+
<react_native_1.ScrollView ref={scrollRef} style={styles.scroll} contentContainerStyle={styles.scrollContent} keyboardShouldPersistTaps="handled" keyboardDismissMode={react_native_1.Platform.OS === 'ios' ? 'interactive' : 'on-drag'} contentInsetAdjustmentBehavior="always" automaticallyAdjustKeyboardInsets={react_native_1.Platform.OS === 'ios'}>
|
|
1121
1067
|
<react_native_1.View style={styles.header}>
|
|
1122
1068
|
<react_native_1.Text style={styles.title}>
|
|
1123
1069
|
{dogfoodActive ? `${YaverFeedback_1.YaverFeedback.getDogfoodStatus().label || 'App'} Developer Mode` : 'Send Feedback'}
|
|
@@ -1138,10 +1084,12 @@ const FeedbackModal = () => {
|
|
|
1138
1084
|
{YaverFeedback_1.YaverFeedback.getDogfoodOnboarding() ? (<react_native_1.View style={styles.dogfoodWizard}>
|
|
1139
1085
|
<react_native_1.Text style={styles.dogfoodWizardTitle}>Dogfood this app</react_native_1.Text>
|
|
1140
1086
|
<react_native_1.Text style={styles.dogfoodWizardHint}>
|
|
1141
|
-
|
|
1087
|
+
{dogfoodEnrollment?.status === 'active'
|
|
1088
|
+
? 'Signed in · this installation is approved'
|
|
1089
|
+
: `Signed in · installation ${dogfoodEnrollment?.status || 'checking'}`}
|
|
1142
1090
|
</react_native_1.Text>
|
|
1143
|
-
<DogfoodSessionUi_1.DogfoodStatusRail steps={
|
|
1144
|
-
{dogfoodEnrollment?.installationId ? (<react_native_1.Text selectable style={styles.dogfoodInstallationId}>
|
|
1091
|
+
{dogfoodEnrollment?.status === 'active' && dogfoodSetupStage === 'setup' ? (<DogfoodSessionUi_1.DogfoodStatusRail steps={dogfoodSetupSteps} colors={FeedbackModalTheme_1.FEEDBACK_DOGFOOD_LIGHT_COLORS}/>) : null}
|
|
1092
|
+
{dogfoodEnrollment?.status !== 'active' && dogfoodEnrollment?.installationId ? (<react_native_1.Text selectable style={styles.dogfoodInstallationId}>
|
|
1145
1093
|
This device · {dogfoodEnrollment.installationId}
|
|
1146
1094
|
</react_native_1.Text>) : null}
|
|
1147
1095
|
{dogfoodEnrollment?.status !== 'active' ? (<react_native_1.View style={styles.dogfoodPendingBox}>
|
|
@@ -1153,53 +1101,99 @@ const FeedbackModal = () => {
|
|
|
1153
1101
|
<react_native_1.Text style={styles.runnerRefreshBtnText}>{dogfoodSetupLoading ? 'Checking…' : 'Check approval'}</react_native_1.Text>
|
|
1154
1102
|
</react_native_1.Pressable>
|
|
1155
1103
|
</react_native_1.View>) : (<>
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1104
|
+
{dogfoodSetupStage === 'setup' ? (<>
|
|
1105
|
+
{dogfoodExpandedStep === 'runner' ? (<react_native_1.View style={styles.dogfoodExpandedPanel}>
|
|
1106
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Coding runner</react_native_1.Text>
|
|
1107
|
+
<react_native_1.View style={styles.dogfoodChoiceRow}>
|
|
1108
|
+
{runnerCards.filter((row) => row.ready || row.authConfigured).map((row) => (<react_native_1.Pressable key={row.id} onPress={() => {
|
|
1109
|
+
const nextModel = row.models?.find((model) => model.isDefault)?.id || row.models?.[0]?.id || '';
|
|
1110
|
+
setPreferredRunnerState(row.id);
|
|
1111
|
+
setPreferredModelState(nextModel);
|
|
1112
|
+
void (0, preferences_1.setPreferredRunner)(row.id);
|
|
1113
|
+
void (0, preferences_1.setPreferredModel)(nextModel || null);
|
|
1114
|
+
}} style={[styles.dogfoodChoice, preferredRunner === row.id && styles.dogfoodChoiceSelected]} accessibilityRole="button" accessibilityState={{ selected: preferredRunner === row.id }}>
|
|
1115
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, preferredRunner === row.id && styles.dogfoodChoiceTextSelected]}>{row.name}</react_native_1.Text>
|
|
1116
|
+
</react_native_1.Pressable>))}
|
|
1117
|
+
</react_native_1.View>
|
|
1118
|
+
{readyRunnerCount === 0 ? (<react_native_1.Text style={styles.dogfoodWizardHint}>Configure a coding runner below, then retry.</react_native_1.Text>) : null}
|
|
1119
|
+
{selectedDogfoodRunner?.models?.length ? (<>
|
|
1120
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Model</react_native_1.Text>
|
|
1121
|
+
<react_native_1.View style={styles.dogfoodChoiceRow}>
|
|
1122
|
+
{selectedDogfoodRunner.models.map((model) => (<react_native_1.Pressable key={model.id} onPress={() => {
|
|
1123
|
+
setPreferredModelState(model.id);
|
|
1124
|
+
void (0, preferences_1.setPreferredModel)(model.id);
|
|
1125
|
+
}} style={[styles.dogfoodChoice, preferredModel === model.id && styles.dogfoodChoiceSelected]}>
|
|
1126
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, preferredModel === model.id && styles.dogfoodChoiceTextSelected]}>{model.name || model.id}</react_native_1.Text>
|
|
1127
|
+
</react_native_1.Pressable>))}
|
|
1128
|
+
</react_native_1.View>
|
|
1129
|
+
</>) : null}
|
|
1130
|
+
</react_native_1.View>) : null}
|
|
1131
|
+
{dogfoodExpandedStep === 'checkout' ? (<react_native_1.View style={styles.dogfoodExpandedPanel}>
|
|
1132
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Git checkout on remote box</react_native_1.Text>
|
|
1133
|
+
{dogfoodProjects.map((project) => (<react_native_1.Pressable key={project.path} onPress={() => {
|
|
1134
|
+
setDogfoodProject(project);
|
|
1135
|
+
setDogfoodLane((0, DogfoodRuntime_1.defaultDogfoodLane)(project.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo'));
|
|
1136
|
+
setDogfoodRuntime(null);
|
|
1137
|
+
}} style={[styles.dogfoodProjectChoice, dogfoodProject?.path === project.path && styles.dogfoodChoiceSelected]}>
|
|
1138
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, dogfoodProject?.path === project.path && styles.dogfoodChoiceTextSelected]}>{project.name}</react_native_1.Text>
|
|
1139
|
+
<react_native_1.Text style={styles.dogfoodProjectDetail}>{dogfoodCheckoutDetail(project)}</react_native_1.Text>
|
|
1140
|
+
</react_native_1.Pressable>))}
|
|
1141
|
+
</react_native_1.View>) : null}
|
|
1142
|
+
<ActionRow label="Choose runtime" tint="#5645d8" onPress={() => {
|
|
1143
|
+
setDogfoodExpandedStep(null);
|
|
1144
|
+
setDogfoodSetupStage('lane');
|
|
1145
|
+
}} disabled={!dogfoodSetupReady}/>
|
|
1189
1146
|
</>) : null}
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1147
|
+
|
|
1148
|
+
{dogfoodSetupStage === 'lane' ? (<>
|
|
1149
|
+
<react_native_1.View style={styles.dogfoodStageHeader}>
|
|
1150
|
+
<react_native_1.View style={styles.dogfoodStageCopy}>
|
|
1151
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Runtime</react_native_1.Text>
|
|
1152
|
+
<react_native_1.Text style={styles.dogfoodStageTitle}>{dogfoodProject?.name} · {dogfoodFramework}</react_native_1.Text>
|
|
1153
|
+
</react_native_1.View>
|
|
1154
|
+
<react_native_1.Pressable onPress={() => setDogfoodSetupStage('setup')} style={styles.dogfoodSmallAction}>
|
|
1155
|
+
<react_native_1.Text style={styles.dogfoodSmallActionText}>Back</react_native_1.Text>
|
|
1156
|
+
</react_native_1.Pressable>
|
|
1157
|
+
</react_native_1.View>
|
|
1158
|
+
<DogfoodSessionUi_1.DogfoodLanePicker options={dogfoodLaneChoices} selected={dogfoodLane} fallbackLane={dogfoodLanePolicy.fallback} colors={FeedbackModalTheme_1.FEEDBACK_DOGFOOD_LIGHT_COLORS} onSelect={(lane) => {
|
|
1159
|
+
setDogfoodLane(lane);
|
|
1160
|
+
const appId = YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.appId;
|
|
1161
|
+
if (appId)
|
|
1162
|
+
void (0, preferences_1.setPreferredDogfoodLane)(appId, lane);
|
|
1163
|
+
}}/>
|
|
1164
|
+
{dogfoodLane === 'webrtc' ? (<react_native_1.View style={styles.dogfoodExpandedPanel}>
|
|
1165
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Simulator, emulator, or device</react_native_1.Text>
|
|
1166
|
+
{dogfoodNativeTargets.map((target) => (<react_native_1.Pressable key={target.id} disabled={!target.enabled} onPress={() => setDogfoodNativeTargetId(target.id)} style={[
|
|
1167
|
+
styles.dogfoodProjectChoice,
|
|
1168
|
+
dogfoodNativeTargetId === target.id && styles.dogfoodChoiceSelected,
|
|
1169
|
+
!target.enabled && styles.dogfoodChoiceDisabled,
|
|
1170
|
+
]}>
|
|
1171
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, dogfoodNativeTargetId === target.id && styles.dogfoodChoiceTextSelected]}>{target.label}</react_native_1.Text>
|
|
1172
|
+
<react_native_1.Text style={styles.dogfoodProjectDetail}>{target.enabled
|
|
1173
|
+
? [target.platform, target.displaySurface || target.surface, 'WebRTC'].filter(Boolean).join(' · ')
|
|
1174
|
+
: target.reason || 'Unavailable on this box'}</react_native_1.Text>
|
|
1175
|
+
</react_native_1.Pressable>))}
|
|
1176
|
+
</react_native_1.View>) : null}
|
|
1177
|
+
<react_native_1.Text style={styles.dogfoodWizardHint}>Logs will be labelled with their real source: remote browser build, Hermes host, iOS Simulator, Android emulator, or connected device.</react_native_1.Text>
|
|
1178
|
+
<ActionRow label="Start Dogfood" tint="#5645d8" onPress={() => void startDogfoodRuntime()} disabled={dogfoodStartBlocked}/>
|
|
1179
|
+
</>) : null}
|
|
1180
|
+
|
|
1181
|
+
{dogfoodSetupStage === 'runtime' && dogfoodRuntime ? (<>
|
|
1182
|
+
<react_native_1.View style={styles.dogfoodStageHeader}>
|
|
1183
|
+
<react_native_1.View style={styles.dogfoodStageCopy}>
|
|
1184
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Dogfooding</react_native_1.Text>
|
|
1185
|
+
<react_native_1.Text style={styles.dogfoodStageTitle}>{dogfoodSourceLabel}</react_native_1.Text>
|
|
1186
|
+
</react_native_1.View>
|
|
1187
|
+
<react_native_1.Pressable onPress={() => {
|
|
1188
|
+
void dogfoodControllerRef.current?.stop().catch(() => { });
|
|
1189
|
+
dogfoodControllerRef.current = null;
|
|
1190
|
+
setDogfoodRuntime(null);
|
|
1191
|
+
setDogfoodSetupStage('lane');
|
|
1192
|
+
}} style={styles.dogfoodSmallAction}>
|
|
1193
|
+
<react_native_1.Text style={styles.dogfoodSmallActionText}>Change</react_native_1.Text>
|
|
1194
|
+
</react_native_1.Pressable>
|
|
1195
|
+
</react_native_1.View>
|
|
1196
|
+
<DogfoodSessionUi_1.DogfoodLiveConsole lane={dogfoodRuntime.project.lane} sourceLabel={dogfoodSourceLabel} phase={dogfoodRuntime.phase} message={dogfoodRuntime.message} logs={dogfoodRuntime.logs} failure={dogfoodRuntime.failure} colors={FeedbackModalTheme_1.FEEDBACK_DOGFOOD_CONSOLE_COLORS}/>
|
|
1203
1197
|
{dogfoodRuntime.result?.url ? (<react_native_1.Pressable onPress={() => void react_native_1.Linking.openURL(dogfoodRuntime.result.url)} style={styles.dogfoodOpenPreview}>
|
|
1204
1198
|
<react_native_1.Text style={styles.dogfoodOpenPreviewText}>Open dogfooded app</react_native_1.Text>
|
|
1205
1199
|
</react_native_1.Pressable>) : null}
|
|
@@ -1392,7 +1386,7 @@ const FeedbackModal = () => {
|
|
|
1392
1386
|
{availableReloadActions.map((reloadAction) => (<react_native_1.View key={reloadAction.id} style={styles.reloadRow}>
|
|
1393
1387
|
<ActionRow label={reloadingId === reloadAction.id
|
|
1394
1388
|
? `${reloadAction.label}…`
|
|
1395
|
-
: reloadAction.label} tint={reloadAction.id === 'rebuild' ? '#
|
|
1389
|
+
: reloadAction.label} tint={reloadAction.id === 'rebuild' ? '#0369a1' : '#9a5700'} onPress={() => {
|
|
1396
1390
|
void handleReloadAction(reloadAction);
|
|
1397
1391
|
}}
|
|
1398
1392
|
// Never `disabled` at the Pressable level for a blocked
|
|
@@ -1409,13 +1403,9 @@ const FeedbackModal = () => {
|
|
|
1409
1403
|
</react_native_1.View>
|
|
1410
1404
|
|
|
1411
1405
|
<react_native_1.View style={[styles.tabContent, activeTab !== 'chat' && styles.hidden]}>
|
|
1412
|
-
{/*
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
tap (Send) fires /vibing/execute with the typed
|
|
1416
|
-
prompt + resolved bundle id so the agent routes
|
|
1417
|
-
to the right repo. */}
|
|
1418
|
-
{!showVibeInput ? (<ActionRow label={action === 'vibing' ? 'Starting…' : 'Vibing'} tint="#818cf8" onPress={handleVibingButton} disabled={busy} busy={action === 'vibing'}/>) : (<react_native_1.View style={styles.vibeInputRow}>
|
|
1406
|
+
{/* Chat creates the first task, then VibeChatScreen owns the
|
|
1407
|
+
transcript and every MCP-backed follow-up. */}
|
|
1408
|
+
{!showVibeInput ? (<ActionRow label={action === 'vibing' ? 'Starting…' : 'Vibing'} tint="#5645d8" onPress={handleVibingButton} disabled={busy} busy={action === 'vibing'}/>) : (<react_native_1.View style={styles.vibeInputRow}>
|
|
1419
1409
|
<react_native_1.TextInput style={styles.vibeInput} placeholder="What do you want to vibe on?" placeholderTextColor="#666" value={vibePrompt} onChangeText={setVibePrompt} multiline autoFocus editable={action !== 'vibing'} blurOnSubmit={false}/>
|
|
1420
1410
|
<react_native_1.View style={styles.vibeInputButtons}>
|
|
1421
1411
|
<react_native_1.Pressable onPress={() => { setShowVibeInput(false); setVibePrompt(''); }} style={({ pressed }) => [styles.vibeCancelBtn, pressed && styles.buttonPressed]} disabled={action === 'vibing'}>
|
|
@@ -1434,16 +1424,6 @@ const FeedbackModal = () => {
|
|
|
1434
1424
|
Last vibing task: {lastVibeTaskId.slice(0, 12)}…
|
|
1435
1425
|
</react_native_1.Text>)}
|
|
1436
1426
|
|
|
1437
|
-
{/* Screenshot & Fix */}
|
|
1438
|
-
{!dogfoodActive ? <ActionRow label={action === 'capturing' ? 'Working…' : 'Screenshot & Fix'} tint="#22c55e" onPress={handleScreenshotAndFix} disabled={busy} busy={action === 'capturing'}/> : null}
|
|
1439
|
-
|
|
1440
|
-
{/* Deploy — opens an inline panel that talks to
|
|
1441
|
-
/fleet/deploy-options on the agent and lets the user
|
|
1442
|
-
pick TestFlight / Play / Both, then a machine to run
|
|
1443
|
-
it on. Capabilities (e.g. "Linux can't TestFlight")
|
|
1444
|
-
come from the agent's doctor probes — no client-side
|
|
1445
|
-
platform smarts here. */}
|
|
1446
|
-
{!dogfoodActive && (!showDeploy ? (<ActionRow label="Deploy" tint="#7f8cf7" onPress={() => setShowDeploy(true)} disabled={busy}/>) : (<DeployPanel_1.DeployPanel onClose={() => setShowDeploy(false)}/>))}
|
|
1447
1427
|
</react_native_1.View>
|
|
1448
1428
|
|
|
1449
1429
|
{progress !== null && (<react_native_1.View style={styles.progressTrack}>
|
|
@@ -1462,9 +1442,8 @@ const FeedbackModal = () => {
|
|
|
1462
1442
|
<react_native_1.Text style={styles.cancelBtnText}>Cancel</react_native_1.Text>
|
|
1463
1443
|
</react_native_1.Pressable>
|
|
1464
1444
|
</react_native_1.ScrollView>
|
|
1465
|
-
</react_native_1.
|
|
1466
|
-
|
|
1467
|
-
</react_native_1.Pressable>
|
|
1445
|
+
</react_native_1.View>
|
|
1446
|
+
</react_native_1.View>
|
|
1468
1447
|
</react_native_1.Modal>)}
|
|
1469
1448
|
{runnerAuthModal ? (<RunnerAuthNativeModal runner={runnerAuthModal} onClose={() => {
|
|
1470
1449
|
setRunnerAuthModal(null);
|
|
@@ -1495,8 +1474,17 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1495
1474
|
dogfoodChoiceRow: { flexDirection: 'row', gap: 7 },
|
|
1496
1475
|
dogfoodChoice: { borderRadius: 9, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: '#fff', paddingHorizontal: 10, paddingVertical: 8 },
|
|
1497
1476
|
dogfoodChoiceSelected: { borderColor: '#818cf8', backgroundColor: 'rgba(129,140,248,0.18)' },
|
|
1477
|
+
dogfoodChoiceDisabled: { opacity: 0.48 },
|
|
1498
1478
|
dogfoodChoiceText: { color: '#666671', fontSize: 12, fontWeight: '700' },
|
|
1499
1479
|
dogfoodChoiceTextSelected: { color: '#5645d8' },
|
|
1480
|
+
dogfoodExpandedPanel: { gap: 8, borderRadius: 11, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: 'rgba(255,255,255,0.72)', padding: 10 },
|
|
1481
|
+
dogfoodProjectChoice: { gap: 3, borderRadius: 9, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: '#fff', paddingHorizontal: 10, paddingVertical: 9 },
|
|
1482
|
+
dogfoodProjectDetail: { color: '#777783', fontSize: 10, lineHeight: 14 },
|
|
1483
|
+
dogfoodStageHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 10 },
|
|
1484
|
+
dogfoodStageCopy: { flex: 1, gap: 2 },
|
|
1485
|
+
dogfoodStageTitle: { color: '#222229', fontSize: 13, fontWeight: '700' },
|
|
1486
|
+
dogfoodSmallAction: { borderRadius: 8, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: '#fff', paddingHorizontal: 10, paddingVertical: 7 },
|
|
1487
|
+
dogfoodSmallActionText: { color: '#5645d8', fontSize: 11, fontWeight: '800' },
|
|
1500
1488
|
dogfoodConsole: { maxHeight: 260, gap: 4, borderRadius: 11, padding: 10, backgroundColor: '#15151b' },
|
|
1501
1489
|
dogfoodConsoleStatus: { color: '#a5b4fc', fontSize: 12, fontWeight: '800' },
|
|
1502
1490
|
dogfoodConsoleLine: { color: '#d1d5db', fontSize: 10, lineHeight: 14, fontFamily: react_native_1.Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }) },
|
|
@@ -1509,7 +1497,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1509
1497
|
gap: 4,
|
|
1510
1498
|
},
|
|
1511
1499
|
reloadHint: {
|
|
1512
|
-
color: '#
|
|
1500
|
+
color: '#666671',
|
|
1513
1501
|
fontSize: 11,
|
|
1514
1502
|
lineHeight: 15,
|
|
1515
1503
|
paddingHorizontal: 4,
|
|
@@ -1541,7 +1529,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1541
1529
|
backgroundColor: 'transparent',
|
|
1542
1530
|
},
|
|
1543
1531
|
vibeCancelBtnText: {
|
|
1544
|
-
color: '#
|
|
1532
|
+
color: '#5f5f69',
|
|
1545
1533
|
fontSize: 14,
|
|
1546
1534
|
fontWeight: '600',
|
|
1547
1535
|
},
|
|
@@ -1549,7 +1537,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1549
1537
|
paddingHorizontal: 16,
|
|
1550
1538
|
paddingVertical: 8,
|
|
1551
1539
|
borderRadius: 8,
|
|
1552
|
-
backgroundColor: '#
|
|
1540
|
+
backgroundColor: '#5645d8',
|
|
1553
1541
|
minWidth: 72,
|
|
1554
1542
|
alignItems: 'center',
|
|
1555
1543
|
},
|
|
@@ -1559,7 +1547,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1559
1547
|
fontWeight: '700',
|
|
1560
1548
|
},
|
|
1561
1549
|
vibeTaskLine: {
|
|
1562
|
-
color: '#
|
|
1550
|
+
color: '#5645d8',
|
|
1563
1551
|
fontSize: 12,
|
|
1564
1552
|
marginTop: -4,
|
|
1565
1553
|
fontFamily: react_native_1.Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }),
|
|
@@ -1569,10 +1557,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1569
1557
|
backgroundColor: 'rgba(0,0,0,0.55)',
|
|
1570
1558
|
justifyContent: 'flex-end',
|
|
1571
1559
|
},
|
|
1572
|
-
|
|
1573
|
-
width: '100%',
|
|
1574
|
-
justifyContent: 'flex-end',
|
|
1575
|
-
},
|
|
1560
|
+
backdrop: react_native_1.StyleSheet.absoluteFillObject,
|
|
1576
1561
|
modal: {
|
|
1577
1562
|
backgroundColor: '#f8f8fb',
|
|
1578
1563
|
borderTopLeftRadius: 22,
|
|
@@ -1631,7 +1616,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1631
1616
|
tabs: { flexDirection: 'row', gap: 6, padding: 3, borderRadius: 12, backgroundColor: '#ededf3' },
|
|
1632
1617
|
tab: { flex: 1, minHeight: 36, borderRadius: 9, alignItems: 'center', justifyContent: 'center' },
|
|
1633
1618
|
tabSelected: { backgroundColor: '#fff' },
|
|
1634
|
-
tabText: { color: '#
|
|
1619
|
+
tabText: { color: '#666671', fontSize: 12, fontWeight: '700' },
|
|
1635
1620
|
tabTextSelected: { color: '#6252e8' },
|
|
1636
1621
|
tabContent: { gap: 12 },
|
|
1637
1622
|
hidden: { display: 'none' },
|
|
@@ -1656,7 +1641,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1656
1641
|
},
|
|
1657
1642
|
machineRoutes: { flexDirection: 'row', gap: 8 },
|
|
1658
1643
|
machineRouteCard: { flex: 1, minWidth: 0, borderRadius: 11, padding: 10, gap: 3, backgroundColor: '#fff', borderWidth: 1, borderColor: '#e1e1e8' },
|
|
1659
|
-
machineRouteLabel: { color: '#
|
|
1644
|
+
machineRouteLabel: { color: '#666671', fontSize: 10, fontWeight: '700', textTransform: 'uppercase' },
|
|
1660
1645
|
machineRouteValue: { color: '#222229', fontSize: 12, fontWeight: '700' },
|
|
1661
1646
|
machineHeader: {
|
|
1662
1647
|
flexDirection: 'row',
|
|
@@ -1692,7 +1677,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1692
1677
|
letterSpacing: 0.8,
|
|
1693
1678
|
},
|
|
1694
1679
|
machineAction: {
|
|
1695
|
-
color: '#
|
|
1680
|
+
color: '#5645d8',
|
|
1696
1681
|
fontSize: 12,
|
|
1697
1682
|
fontWeight: '700',
|
|
1698
1683
|
},
|
|
@@ -1723,7 +1708,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1723
1708
|
},
|
|
1724
1709
|
runnerSectionSubtitle: {
|
|
1725
1710
|
marginTop: 2,
|
|
1726
|
-
color: '#
|
|
1711
|
+
color: '#666671',
|
|
1727
1712
|
fontSize: 12,
|
|
1728
1713
|
},
|
|
1729
1714
|
runnerRefreshBtn: {
|
|
@@ -1750,15 +1735,15 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1750
1735
|
},
|
|
1751
1736
|
runnerCardOk: {
|
|
1752
1737
|
borderColor: 'rgba(34,197,94,0.28)',
|
|
1753
|
-
backgroundColor: 'rgba(
|
|
1738
|
+
backgroundColor: 'rgba(34,197,94,0.08)',
|
|
1754
1739
|
},
|
|
1755
1740
|
runnerCardWarning: {
|
|
1756
1741
|
borderColor: 'rgba(251,191,36,0.28)',
|
|
1757
|
-
backgroundColor: 'rgba(
|
|
1742
|
+
backgroundColor: 'rgba(245,158,11,0.08)',
|
|
1758
1743
|
},
|
|
1759
1744
|
runnerCardError: {
|
|
1760
1745
|
borderColor: 'rgba(248,113,113,0.28)',
|
|
1761
|
-
backgroundColor: 'rgba(
|
|
1746
|
+
backgroundColor: 'rgba(239,68,68,0.07)',
|
|
1762
1747
|
},
|
|
1763
1748
|
runnerCardTop: {
|
|
1764
1749
|
flexDirection: 'row',
|
|
@@ -1777,13 +1762,13 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1777
1762
|
color: '#666671',
|
|
1778
1763
|
},
|
|
1779
1764
|
runnerCardStatusOk: {
|
|
1780
|
-
color: '#
|
|
1765
|
+
color: '#137a3f',
|
|
1781
1766
|
},
|
|
1782
1767
|
runnerCardStatusWarning: {
|
|
1783
|
-
color: '#
|
|
1768
|
+
color: '#9a5700',
|
|
1784
1769
|
},
|
|
1785
1770
|
runnerCardStatusError: {
|
|
1786
|
-
color: '#
|
|
1771
|
+
color: '#b42318',
|
|
1787
1772
|
},
|
|
1788
1773
|
runnerCardDetail: {
|
|
1789
1774
|
color: '#858590',
|
|
@@ -1794,26 +1779,26 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1794
1779
|
borderRadius: 10,
|
|
1795
1780
|
borderWidth: 1,
|
|
1796
1781
|
borderColor: 'rgba(129,140,248,0.35)',
|
|
1797
|
-
backgroundColor: 'rgba(
|
|
1782
|
+
backgroundColor: 'rgba(86,69,216,0.10)',
|
|
1798
1783
|
paddingHorizontal: 12,
|
|
1799
1784
|
paddingVertical: 8,
|
|
1800
1785
|
},
|
|
1801
1786
|
runnerActionBtnText: {
|
|
1802
|
-
color: '#
|
|
1787
|
+
color: '#5645d8',
|
|
1803
1788
|
fontSize: 12,
|
|
1804
1789
|
fontWeight: '700',
|
|
1805
1790
|
},
|
|
1806
|
-
runnerActionBtnSelected: { borderColor: '#
|
|
1791
|
+
runnerActionBtnSelected: { borderColor: '#6555df', backgroundColor: 'rgba(86,69,216,0.18)' },
|
|
1807
1792
|
routingSummary: { flexDirection: 'row', alignItems: 'center', gap: 8, paddingHorizontal: 2 },
|
|
1808
1793
|
routingSummaryLabel: { color: '#7c7c87', fontSize: 11, fontWeight: '600' },
|
|
1809
1794
|
routingSummaryValue: { flex: 1, color: '#6555df', fontSize: 12, fontWeight: '700', textAlign: 'right' },
|
|
1810
1795
|
modelChoiceRow: { gap: 6, paddingTop: 2 },
|
|
1811
1796
|
modelChoice: { borderRadius: 9, borderWidth: 1, borderColor: 'rgba(148,163,184,0.18)', paddingHorizontal: 9, paddingVertical: 6 },
|
|
1812
|
-
modelChoiceSelected: { borderColor: '#
|
|
1797
|
+
modelChoiceSelected: { borderColor: '#6555df', backgroundColor: 'rgba(86,69,216,0.12)' },
|
|
1813
1798
|
modelChoiceText: { color: '#73737e', fontSize: 11 },
|
|
1814
1799
|
modelChoiceTextSelected: { color: '#5e4ce6', fontWeight: '700' },
|
|
1815
1800
|
runnerSectionError: {
|
|
1816
|
-
color: '#
|
|
1801
|
+
color: '#b42318',
|
|
1817
1802
|
fontSize: 12,
|
|
1818
1803
|
lineHeight: 18,
|
|
1819
1804
|
},
|
|
@@ -1833,13 +1818,13 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1833
1818
|
borderRadius: 3,
|
|
1834
1819
|
},
|
|
1835
1820
|
toast: {
|
|
1836
|
-
color: '#
|
|
1821
|
+
color: '#137a3f',
|
|
1837
1822
|
fontSize: 13,
|
|
1838
1823
|
textAlign: 'center',
|
|
1839
1824
|
marginTop: 4,
|
|
1840
1825
|
},
|
|
1841
1826
|
error: {
|
|
1842
|
-
color: '#
|
|
1827
|
+
color: '#b42318',
|
|
1843
1828
|
fontSize: 12,
|
|
1844
1829
|
textAlign: 'center',
|
|
1845
1830
|
marginTop: 4,
|