yaver-feedback-react-native 0.9.9 → 0.9.10
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 +6 -1
- package/dist/DogfoodRuntime.js +9 -3
- package/dist/DogfoodSessionUi.d.ts +1 -0
- package/dist/DogfoodSessionUi.js +5 -2
- package/dist/FeedbackModal.js +249 -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 +14 -0
- package/dist/__tests__/FeedbackModalContract.test.d.ts +1 -0
- package/dist/__tests__/FeedbackModalContract.test.js +70 -0
- package/dist/__tests__/NativeDogfoodShortcut.test.js +23 -0
- package/dist/__tests__/P2PDogfoodDriver.test.js +4 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +4 -5
- package/ios/YaverHotReload.swift +3 -4
- package/package.json +1 -1
- package/src/DogfoodRuntime.ts +21 -4
- package/src/DogfoodSessionUi.tsx +6 -2
- package/src/FeedbackModal.tsx +319 -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 +15 -0
- package/src/__tests__/FeedbackModalContract.test.ts +80 -0
- package/src/__tests__/NativeDogfoodShortcut.test.ts +25 -0
- package/src/__tests__/P2PDogfoodDriver.test.ts +4 -0
- package/src/index.ts +4 -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; };
|
|
@@ -286,14 +321,16 @@ const FeedbackModal = () => {
|
|
|
286
321
|
workDir: dogfoodProject.path,
|
|
287
322
|
framework,
|
|
288
323
|
lane: dogfoodLane,
|
|
324
|
+
nativeTargetId: dogfoodLane === 'webrtc' ? dogfoodNativeTargetId : undefined,
|
|
289
325
|
}, (0, P2PDogfoodDriver_1.createP2PDogfoodDriver)(client), {
|
|
290
326
|
onChange: (snapshot) => { if (mountedRef.current)
|
|
291
327
|
setDogfoodRuntime(snapshot); },
|
|
292
328
|
});
|
|
293
329
|
dogfoodControllerRef.current = controller;
|
|
294
330
|
setDogfoodRuntime(controller.snapshot());
|
|
331
|
+
setDogfoodSetupStage('runtime');
|
|
295
332
|
await controller.trigger().catch(() => { });
|
|
296
|
-
}, [dogfoodLane, dogfoodProject]);
|
|
333
|
+
}, [dogfoodLane, dogfoodNativeTargetId, dogfoodProject]);
|
|
297
334
|
/**
|
|
298
335
|
* Ask the machine what its dev server is doing, so the reload actions can
|
|
299
336
|
* be enabled/disabled against reality rather than against a guess.
|
|
@@ -486,16 +523,20 @@ const FeedbackModal = () => {
|
|
|
486
523
|
// user's feedback preference merely to open Developer Mode.
|
|
487
524
|
if (YaverFeedback_1.YaverFeedback.isEnabled() || onboarding) {
|
|
488
525
|
const directDogfood = YaverFeedback_1.YaverFeedback.getDogfoodStatus().active;
|
|
526
|
+
const authenticated = YaverFeedback_1.YaverFeedback.isAuthed();
|
|
489
527
|
setDogfoodActive(directDogfood);
|
|
490
528
|
setVisible(true);
|
|
491
529
|
setError(null);
|
|
492
530
|
setToast(null);
|
|
493
531
|
setProgress(null);
|
|
494
532
|
setAction('idle');
|
|
495
|
-
setShowVibeInput(directDogfood);
|
|
533
|
+
setShowVibeInput(authenticated || directDogfood);
|
|
496
534
|
setVibePrompt('');
|
|
497
535
|
if (onboarding) {
|
|
498
|
-
setActiveTab('settings');
|
|
536
|
+
setActiveTab(authenticated ? 'chat' : 'settings');
|
|
537
|
+
setDogfoodSetupStage('setup');
|
|
538
|
+
setDogfoodExpandedStep(null);
|
|
539
|
+
setDogfoodRuntime(null);
|
|
499
540
|
void loadDogfoodOnboarding();
|
|
500
541
|
}
|
|
501
542
|
// Re-read the "user hid the quick icon" flag on every open so
|
|
@@ -566,30 +607,14 @@ const FeedbackModal = () => {
|
|
|
566
607
|
}, 5000);
|
|
567
608
|
return () => clearInterval(interval);
|
|
568
609
|
}, [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
610
|
(0, react_1.useEffect)(() => {
|
|
588
611
|
if (!visible || !showVibeInput)
|
|
589
612
|
return;
|
|
590
|
-
|
|
613
|
+
// UIKit owns keyboard insets on the ScrollView. This one bounded scroll only
|
|
614
|
+
// reveals the newly mounted composer; it does not add a second inset.
|
|
615
|
+
const timer = setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), 80);
|
|
591
616
|
return () => clearTimeout(timer);
|
|
592
|
-
}, [
|
|
617
|
+
}, [showVibeInput, visible]);
|
|
593
618
|
const closeSoon = (0, react_1.useCallback)((delayMs = 1200) => {
|
|
594
619
|
setTimeout(() => {
|
|
595
620
|
if (mountedRef.current)
|
|
@@ -605,6 +630,9 @@ const FeedbackModal = () => {
|
|
|
605
630
|
setShowVibeInput(false);
|
|
606
631
|
setVibePrompt('');
|
|
607
632
|
setRunnerStatusError(null);
|
|
633
|
+
setDogfoodSetupStage('setup');
|
|
634
|
+
setDogfoodExpandedStep(null);
|
|
635
|
+
setDogfoodRuntime(null);
|
|
608
636
|
void dogfoodControllerRef.current?.stop().catch(() => { });
|
|
609
637
|
dogfoodControllerRef.current = null;
|
|
610
638
|
YaverFeedback_1.YaverFeedback.clearDogfoodOnboarding();
|
|
@@ -791,107 +819,7 @@ const FeedbackModal = () => {
|
|
|
791
819
|
setAction('idle');
|
|
792
820
|
}
|
|
793
821
|
}, [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 ─────────────────────────────────────────────────────
|
|
822
|
+
// ─── Chat ──────────────────────────────────────────────────────────
|
|
895
823
|
// First tap expands the input; second submit fires the actual
|
|
896
824
|
// /vibing/execute. Mirrors the Yaver mobile app's Vibing tab —
|
|
897
825
|
// user types what they want, hits Send, sees the task id back. If
|
|
@@ -1025,42 +953,54 @@ const FeedbackModal = () => {
|
|
|
1025
953
|
&& (selectedDogfoodRunner.ready || selectedDogfoodRunner.authConfigured);
|
|
1026
954
|
const dogfoodModelReady = !selectedDogfoodRunner?.models?.length
|
|
1027
955
|
|| !!preferredModel && selectedDogfoodRunner.models.some((model) => model.id === preferredModel);
|
|
1028
|
-
const
|
|
1029
|
-
const
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
tone: machineCard.device && machineCard.status === 'live' ? 'ready' : 'attention',
|
|
1040
|
-
},
|
|
1041
|
-
{
|
|
1042
|
-
key: 'installation', label: 'This installation',
|
|
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
|
-
},
|
|
956
|
+
const dogfoodFramework = dogfoodProject?.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo';
|
|
957
|
+
const dogfoodLaneChoices = (0, DogfoodRuntime_1.dogfoodLaneOptions)(dogfoodFramework, {
|
|
958
|
+
nativeRuntimeAvailable: dogfoodNativeAvailable,
|
|
959
|
+
browserRuntimeAvailable: dogfoodBrowserAvailable,
|
|
960
|
+
});
|
|
961
|
+
const selectedDogfoodNativeTarget = dogfoodNativeTargets.find((target) => target.id === dogfoodNativeTargetId) || null;
|
|
962
|
+
const dogfoodLaneReady = dogfoodLaneChoices.some((option) => option.lane === dogfoodLane && option.supported)
|
|
963
|
+
&& (dogfoodLane !== 'webrtc' || !!selectedDogfoodNativeTarget?.enabled);
|
|
964
|
+
const dogfoodMachineReady = !!machineCard.device && machineCard.status === 'live';
|
|
965
|
+
const dogfoodSetupReady = dogfoodMachineReady && !!dogfoodProject && dogfoodRunnerReady && dogfoodModelReady;
|
|
966
|
+
const dogfoodSetupSteps = [
|
|
1047
967
|
{
|
|
1048
|
-
key: '
|
|
1049
|
-
|
|
1050
|
-
|
|
968
|
+
key: 'box',
|
|
969
|
+
label: 'Remote box',
|
|
970
|
+
detail: dogfoodMachineReady ? machineCard.title : 'Choose a reachable development machine',
|
|
971
|
+
tone: dogfoodMachineReady ? 'ready' : 'attention',
|
|
972
|
+
actionLabel: machineCard.device ? 'Change' : 'Pick',
|
|
973
|
+
onAction: () => YaverFeedback_1.YaverFeedback.showMachinePicker(),
|
|
1051
974
|
},
|
|
1052
975
|
{
|
|
1053
|
-
key: '
|
|
1054
|
-
|
|
1055
|
-
|
|
976
|
+
key: 'runner',
|
|
977
|
+
label: 'Runner',
|
|
978
|
+
detail: dogfoodRunnerReady
|
|
979
|
+
? [selectedDogfoodRunner?.name || preferredRunner || 'Ready', preferredModel || 'default model'].join(' · ')
|
|
980
|
+
: 'Choose or configure a coding runner',
|
|
981
|
+
tone: dogfoodRunnerReady && dogfoodModelReady ? 'ready' : 'attention',
|
|
982
|
+
actionLabel: dogfoodExpandedStep === 'runner' ? 'Done' : dogfoodRunnerReady ? 'Change' : 'Choose',
|
|
983
|
+
expanded: dogfoodExpandedStep === 'runner',
|
|
984
|
+
onAction: () => setDogfoodExpandedStep((current) => current === 'runner' ? null : 'runner'),
|
|
1056
985
|
},
|
|
1057
986
|
{
|
|
1058
|
-
key: '
|
|
1059
|
-
|
|
1060
|
-
|
|
987
|
+
key: 'checkout',
|
|
988
|
+
label: 'Checkout',
|
|
989
|
+
detail: dogfoodCheckoutDetail(dogfoodProject),
|
|
990
|
+
tone: dogfoodProject ? 'ready' : 'attention',
|
|
991
|
+
actionLabel: dogfoodExpandedStep === 'checkout' ? 'Done' : dogfoodProject ? 'Change' : 'Choose',
|
|
992
|
+
expanded: dogfoodExpandedStep === 'checkout',
|
|
993
|
+
onAction: () => setDogfoodExpandedStep((current) => current === 'checkout' ? null : 'checkout'),
|
|
1061
994
|
},
|
|
1062
995
|
];
|
|
1063
|
-
const dogfoodStartBlocked = !
|
|
996
|
+
const dogfoodStartBlocked = !dogfoodSetupReady || !dogfoodLaneReady;
|
|
997
|
+
const dogfoodSourceLabel = dogfoodLane === 'webrtc'
|
|
998
|
+
? selectedDogfoodNativeTarget
|
|
999
|
+
? [selectedDogfoodNativeTarget.label, selectedDogfoodNativeTarget.platform].filter(Boolean).join(' · ')
|
|
1000
|
+
: 'Native simulator, emulator, or device'
|
|
1001
|
+
: dogfoodLane === 'hermes'
|
|
1002
|
+
? `Hermes build · ${machineCard.title}`
|
|
1003
|
+
: `${dogfoodFramework === 'flutter' ? 'Flutter web compiler' : 'Metro / browser build'} · ${machineCard.title}`;
|
|
1064
1004
|
// Once the user fires off a vibe task, swap the entire modal body
|
|
1065
1005
|
// for the live chat screen. The chat manages its own SSE
|
|
1066
1006
|
// subscription, multi-turn follow-ups, and Reload button. Closing
|
|
@@ -1091,9 +1031,9 @@ const FeedbackModal = () => {
|
|
|
1091
1031
|
<QuickActionIcon_1.QuickActionIcon />
|
|
1092
1032
|
<YaverModeBadgeGate />
|
|
1093
1033
|
{visible && (<react_native_1.Modal visible={visible} animationType="slide" transparent onRequestClose={handleClose}>
|
|
1094
|
-
<react_native_1.
|
|
1095
|
-
<react_native_1.
|
|
1096
|
-
<react_native_1.
|
|
1034
|
+
<react_native_1.View style={styles.overlay}>
|
|
1035
|
+
<react_native_1.Pressable style={styles.backdrop} onPress={handleClose} accessibilityLabel="Close feedback"/>
|
|
1036
|
+
<react_native_1.View
|
|
1097
1037
|
// Tablet: cap modal width and center as a card-style
|
|
1098
1038
|
// sheet rather than a phone bottom sheet that stretches
|
|
1099
1039
|
// across a 12.9" iPad. Phone behaviour unchanged.
|
|
@@ -1108,16 +1048,8 @@ const FeedbackModal = () => {
|
|
|
1108
1048
|
borderTopRightRadius: 22,
|
|
1109
1049
|
}
|
|
1110
1050
|
: 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'}>
|
|
1051
|
+
]}>
|
|
1052
|
+
<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
1053
|
<react_native_1.View style={styles.header}>
|
|
1122
1054
|
<react_native_1.Text style={styles.title}>
|
|
1123
1055
|
{dogfoodActive ? `${YaverFeedback_1.YaverFeedback.getDogfoodStatus().label || 'App'} Developer Mode` : 'Send Feedback'}
|
|
@@ -1138,10 +1070,12 @@ const FeedbackModal = () => {
|
|
|
1138
1070
|
{YaverFeedback_1.YaverFeedback.getDogfoodOnboarding() ? (<react_native_1.View style={styles.dogfoodWizard}>
|
|
1139
1071
|
<react_native_1.Text style={styles.dogfoodWizardTitle}>Dogfood this app</react_native_1.Text>
|
|
1140
1072
|
<react_native_1.Text style={styles.dogfoodWizardHint}>
|
|
1141
|
-
|
|
1073
|
+
{dogfoodEnrollment?.status === 'active'
|
|
1074
|
+
? 'Signed in · this installation is approved'
|
|
1075
|
+
: `Signed in · installation ${dogfoodEnrollment?.status || 'checking'}`}
|
|
1142
1076
|
</react_native_1.Text>
|
|
1143
|
-
<DogfoodSessionUi_1.DogfoodStatusRail steps={
|
|
1144
|
-
{dogfoodEnrollment?.installationId ? (<react_native_1.Text selectable style={styles.dogfoodInstallationId}>
|
|
1077
|
+
{dogfoodEnrollment?.status === 'active' && dogfoodSetupStage === 'setup' ? (<DogfoodSessionUi_1.DogfoodStatusRail steps={dogfoodSetupSteps} colors={FeedbackModalTheme_1.FEEDBACK_DOGFOOD_LIGHT_COLORS}/>) : null}
|
|
1078
|
+
{dogfoodEnrollment?.status !== 'active' && dogfoodEnrollment?.installationId ? (<react_native_1.Text selectable style={styles.dogfoodInstallationId}>
|
|
1145
1079
|
This device · {dogfoodEnrollment.installationId}
|
|
1146
1080
|
</react_native_1.Text>) : null}
|
|
1147
1081
|
{dogfoodEnrollment?.status !== 'active' ? (<react_native_1.View style={styles.dogfoodPendingBox}>
|
|
@@ -1153,53 +1087,99 @@ const FeedbackModal = () => {
|
|
|
1153
1087
|
<react_native_1.Text style={styles.runnerRefreshBtnText}>{dogfoodSetupLoading ? 'Checking…' : 'Check approval'}</react_native_1.Text>
|
|
1154
1088
|
</react_native_1.Pressable>
|
|
1155
1089
|
</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
|
-
|
|
1090
|
+
{dogfoodSetupStage === 'setup' ? (<>
|
|
1091
|
+
{dogfoodExpandedStep === 'runner' ? (<react_native_1.View style={styles.dogfoodExpandedPanel}>
|
|
1092
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Coding runner</react_native_1.Text>
|
|
1093
|
+
<react_native_1.View style={styles.dogfoodChoiceRow}>
|
|
1094
|
+
{runnerCards.filter((row) => row.ready || row.authConfigured).map((row) => (<react_native_1.Pressable key={row.id} onPress={() => {
|
|
1095
|
+
const nextModel = row.models?.find((model) => model.isDefault)?.id || row.models?.[0]?.id || '';
|
|
1096
|
+
setPreferredRunnerState(row.id);
|
|
1097
|
+
setPreferredModelState(nextModel);
|
|
1098
|
+
void (0, preferences_1.setPreferredRunner)(row.id);
|
|
1099
|
+
void (0, preferences_1.setPreferredModel)(nextModel || null);
|
|
1100
|
+
}} style={[styles.dogfoodChoice, preferredRunner === row.id && styles.dogfoodChoiceSelected]} accessibilityRole="button" accessibilityState={{ selected: preferredRunner === row.id }}>
|
|
1101
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, preferredRunner === row.id && styles.dogfoodChoiceTextSelected]}>{row.name}</react_native_1.Text>
|
|
1102
|
+
</react_native_1.Pressable>))}
|
|
1103
|
+
</react_native_1.View>
|
|
1104
|
+
{readyRunnerCount === 0 ? (<react_native_1.Text style={styles.dogfoodWizardHint}>Configure a coding runner below, then retry.</react_native_1.Text>) : null}
|
|
1105
|
+
{selectedDogfoodRunner?.models?.length ? (<>
|
|
1106
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Model</react_native_1.Text>
|
|
1107
|
+
<react_native_1.View style={styles.dogfoodChoiceRow}>
|
|
1108
|
+
{selectedDogfoodRunner.models.map((model) => (<react_native_1.Pressable key={model.id} onPress={() => {
|
|
1109
|
+
setPreferredModelState(model.id);
|
|
1110
|
+
void (0, preferences_1.setPreferredModel)(model.id);
|
|
1111
|
+
}} style={[styles.dogfoodChoice, preferredModel === model.id && styles.dogfoodChoiceSelected]}>
|
|
1112
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, preferredModel === model.id && styles.dogfoodChoiceTextSelected]}>{model.name || model.id}</react_native_1.Text>
|
|
1113
|
+
</react_native_1.Pressable>))}
|
|
1114
|
+
</react_native_1.View>
|
|
1115
|
+
</>) : null}
|
|
1116
|
+
</react_native_1.View>) : null}
|
|
1117
|
+
{dogfoodExpandedStep === 'checkout' ? (<react_native_1.View style={styles.dogfoodExpandedPanel}>
|
|
1118
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Git checkout on remote box</react_native_1.Text>
|
|
1119
|
+
{dogfoodProjects.map((project) => (<react_native_1.Pressable key={project.path} onPress={() => {
|
|
1120
|
+
setDogfoodProject(project);
|
|
1121
|
+
setDogfoodLane((0, DogfoodRuntime_1.defaultDogfoodLane)(project.framework || YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.framework || 'expo'));
|
|
1122
|
+
setDogfoodRuntime(null);
|
|
1123
|
+
}} style={[styles.dogfoodProjectChoice, dogfoodProject?.path === project.path && styles.dogfoodChoiceSelected]}>
|
|
1124
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, dogfoodProject?.path === project.path && styles.dogfoodChoiceTextSelected]}>{project.name}</react_native_1.Text>
|
|
1125
|
+
<react_native_1.Text style={styles.dogfoodProjectDetail}>{dogfoodCheckoutDetail(project)}</react_native_1.Text>
|
|
1126
|
+
</react_native_1.Pressable>))}
|
|
1127
|
+
</react_native_1.View>) : null}
|
|
1128
|
+
<ActionRow label="Choose runtime" tint="#5645d8" onPress={() => {
|
|
1129
|
+
setDogfoodExpandedStep(null);
|
|
1130
|
+
setDogfoodSetupStage('lane');
|
|
1131
|
+
}} disabled={!dogfoodSetupReady}/>
|
|
1189
1132
|
</>) : null}
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1133
|
+
|
|
1134
|
+
{dogfoodSetupStage === 'lane' ? (<>
|
|
1135
|
+
<react_native_1.View style={styles.dogfoodStageHeader}>
|
|
1136
|
+
<react_native_1.View style={styles.dogfoodStageCopy}>
|
|
1137
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Runtime</react_native_1.Text>
|
|
1138
|
+
<react_native_1.Text style={styles.dogfoodStageTitle}>{dogfoodProject?.name} · {dogfoodFramework}</react_native_1.Text>
|
|
1139
|
+
</react_native_1.View>
|
|
1140
|
+
<react_native_1.Pressable onPress={() => setDogfoodSetupStage('setup')} style={styles.dogfoodSmallAction}>
|
|
1141
|
+
<react_native_1.Text style={styles.dogfoodSmallActionText}>Back</react_native_1.Text>
|
|
1142
|
+
</react_native_1.Pressable>
|
|
1143
|
+
</react_native_1.View>
|
|
1144
|
+
<DogfoodSessionUi_1.DogfoodLanePicker options={dogfoodLaneChoices} selected={dogfoodLane} colors={FeedbackModalTheme_1.FEEDBACK_DOGFOOD_LIGHT_COLORS} onSelect={(lane) => {
|
|
1145
|
+
setDogfoodLane(lane);
|
|
1146
|
+
const appId = YaverFeedback_1.YaverFeedback.getDogfoodOnboarding()?.appId;
|
|
1147
|
+
if (appId)
|
|
1148
|
+
void (0, preferences_1.setPreferredDogfoodLane)(appId, lane);
|
|
1149
|
+
}}/>
|
|
1150
|
+
{dogfoodLane === 'webrtc' ? (<react_native_1.View style={styles.dogfoodExpandedPanel}>
|
|
1151
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Simulator, emulator, or device</react_native_1.Text>
|
|
1152
|
+
{dogfoodNativeTargets.map((target) => (<react_native_1.Pressable key={target.id} disabled={!target.enabled} onPress={() => setDogfoodNativeTargetId(target.id)} style={[
|
|
1153
|
+
styles.dogfoodProjectChoice,
|
|
1154
|
+
dogfoodNativeTargetId === target.id && styles.dogfoodChoiceSelected,
|
|
1155
|
+
!target.enabled && styles.dogfoodChoiceDisabled,
|
|
1156
|
+
]}>
|
|
1157
|
+
<react_native_1.Text style={[styles.dogfoodChoiceText, dogfoodNativeTargetId === target.id && styles.dogfoodChoiceTextSelected]}>{target.label}</react_native_1.Text>
|
|
1158
|
+
<react_native_1.Text style={styles.dogfoodProjectDetail}>{target.enabled
|
|
1159
|
+
? [target.platform, target.displaySurface || target.surface, 'WebRTC'].filter(Boolean).join(' · ')
|
|
1160
|
+
: target.reason || 'Unavailable on this box'}</react_native_1.Text>
|
|
1161
|
+
</react_native_1.Pressable>))}
|
|
1162
|
+
</react_native_1.View>) : null}
|
|
1163
|
+
<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>
|
|
1164
|
+
<ActionRow label="Start Dogfood" tint="#5645d8" onPress={() => void startDogfoodRuntime()} disabled={dogfoodStartBlocked}/>
|
|
1165
|
+
</>) : null}
|
|
1166
|
+
|
|
1167
|
+
{dogfoodSetupStage === 'runtime' && dogfoodRuntime ? (<>
|
|
1168
|
+
<react_native_1.View style={styles.dogfoodStageHeader}>
|
|
1169
|
+
<react_native_1.View style={styles.dogfoodStageCopy}>
|
|
1170
|
+
<react_native_1.Text style={styles.dogfoodStepLabel}>Dogfooding</react_native_1.Text>
|
|
1171
|
+
<react_native_1.Text style={styles.dogfoodStageTitle}>{dogfoodSourceLabel}</react_native_1.Text>
|
|
1172
|
+
</react_native_1.View>
|
|
1173
|
+
<react_native_1.Pressable onPress={() => {
|
|
1174
|
+
void dogfoodControllerRef.current?.stop().catch(() => { });
|
|
1175
|
+
dogfoodControllerRef.current = null;
|
|
1176
|
+
setDogfoodRuntime(null);
|
|
1177
|
+
setDogfoodSetupStage('lane');
|
|
1178
|
+
}} style={styles.dogfoodSmallAction}>
|
|
1179
|
+
<react_native_1.Text style={styles.dogfoodSmallActionText}>Change</react_native_1.Text>
|
|
1180
|
+
</react_native_1.Pressable>
|
|
1181
|
+
</react_native_1.View>
|
|
1182
|
+
<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
1183
|
{dogfoodRuntime.result?.url ? (<react_native_1.Pressable onPress={() => void react_native_1.Linking.openURL(dogfoodRuntime.result.url)} style={styles.dogfoodOpenPreview}>
|
|
1204
1184
|
<react_native_1.Text style={styles.dogfoodOpenPreviewText}>Open dogfooded app</react_native_1.Text>
|
|
1205
1185
|
</react_native_1.Pressable>) : null}
|
|
@@ -1392,7 +1372,7 @@ const FeedbackModal = () => {
|
|
|
1392
1372
|
{availableReloadActions.map((reloadAction) => (<react_native_1.View key={reloadAction.id} style={styles.reloadRow}>
|
|
1393
1373
|
<ActionRow label={reloadingId === reloadAction.id
|
|
1394
1374
|
? `${reloadAction.label}…`
|
|
1395
|
-
: reloadAction.label} tint={reloadAction.id === 'rebuild' ? '#
|
|
1375
|
+
: reloadAction.label} tint={reloadAction.id === 'rebuild' ? '#0369a1' : '#9a5700'} onPress={() => {
|
|
1396
1376
|
void handleReloadAction(reloadAction);
|
|
1397
1377
|
}}
|
|
1398
1378
|
// Never `disabled` at the Pressable level for a blocked
|
|
@@ -1409,13 +1389,9 @@ const FeedbackModal = () => {
|
|
|
1409
1389
|
</react_native_1.View>
|
|
1410
1390
|
|
|
1411
1391
|
<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}>
|
|
1392
|
+
{/* Chat creates the first task, then VibeChatScreen owns the
|
|
1393
|
+
transcript and every MCP-backed follow-up. */}
|
|
1394
|
+
{!showVibeInput ? (<ActionRow label={action === 'vibing' ? 'Starting…' : 'Vibing'} tint="#5645d8" onPress={handleVibingButton} disabled={busy} busy={action === 'vibing'}/>) : (<react_native_1.View style={styles.vibeInputRow}>
|
|
1419
1395
|
<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
1396
|
<react_native_1.View style={styles.vibeInputButtons}>
|
|
1421
1397
|
<react_native_1.Pressable onPress={() => { setShowVibeInput(false); setVibePrompt(''); }} style={({ pressed }) => [styles.vibeCancelBtn, pressed && styles.buttonPressed]} disabled={action === 'vibing'}>
|
|
@@ -1434,16 +1410,6 @@ const FeedbackModal = () => {
|
|
|
1434
1410
|
Last vibing task: {lastVibeTaskId.slice(0, 12)}…
|
|
1435
1411
|
</react_native_1.Text>)}
|
|
1436
1412
|
|
|
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
1413
|
</react_native_1.View>
|
|
1448
1414
|
|
|
1449
1415
|
{progress !== null && (<react_native_1.View style={styles.progressTrack}>
|
|
@@ -1462,9 +1428,8 @@ const FeedbackModal = () => {
|
|
|
1462
1428
|
<react_native_1.Text style={styles.cancelBtnText}>Cancel</react_native_1.Text>
|
|
1463
1429
|
</react_native_1.Pressable>
|
|
1464
1430
|
</react_native_1.ScrollView>
|
|
1465
|
-
</react_native_1.
|
|
1466
|
-
|
|
1467
|
-
</react_native_1.Pressable>
|
|
1431
|
+
</react_native_1.View>
|
|
1432
|
+
</react_native_1.View>
|
|
1468
1433
|
</react_native_1.Modal>)}
|
|
1469
1434
|
{runnerAuthModal ? (<RunnerAuthNativeModal runner={runnerAuthModal} onClose={() => {
|
|
1470
1435
|
setRunnerAuthModal(null);
|
|
@@ -1495,8 +1460,17 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1495
1460
|
dogfoodChoiceRow: { flexDirection: 'row', gap: 7 },
|
|
1496
1461
|
dogfoodChoice: { borderRadius: 9, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: '#fff', paddingHorizontal: 10, paddingVertical: 8 },
|
|
1497
1462
|
dogfoodChoiceSelected: { borderColor: '#818cf8', backgroundColor: 'rgba(129,140,248,0.18)' },
|
|
1463
|
+
dogfoodChoiceDisabled: { opacity: 0.48 },
|
|
1498
1464
|
dogfoodChoiceText: { color: '#666671', fontSize: 12, fontWeight: '700' },
|
|
1499
1465
|
dogfoodChoiceTextSelected: { color: '#5645d8' },
|
|
1466
|
+
dogfoodExpandedPanel: { gap: 8, borderRadius: 11, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: 'rgba(255,255,255,0.72)', padding: 10 },
|
|
1467
|
+
dogfoodProjectChoice: { gap: 3, borderRadius: 9, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: '#fff', paddingHorizontal: 10, paddingVertical: 9 },
|
|
1468
|
+
dogfoodProjectDetail: { color: '#777783', fontSize: 10, lineHeight: 14 },
|
|
1469
|
+
dogfoodStageHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 10 },
|
|
1470
|
+
dogfoodStageCopy: { flex: 1, gap: 2 },
|
|
1471
|
+
dogfoodStageTitle: { color: '#222229', fontSize: 13, fontWeight: '700' },
|
|
1472
|
+
dogfoodSmallAction: { borderRadius: 8, borderWidth: 1, borderColor: '#d8d8e3', backgroundColor: '#fff', paddingHorizontal: 10, paddingVertical: 7 },
|
|
1473
|
+
dogfoodSmallActionText: { color: '#5645d8', fontSize: 11, fontWeight: '800' },
|
|
1500
1474
|
dogfoodConsole: { maxHeight: 260, gap: 4, borderRadius: 11, padding: 10, backgroundColor: '#15151b' },
|
|
1501
1475
|
dogfoodConsoleStatus: { color: '#a5b4fc', fontSize: 12, fontWeight: '800' },
|
|
1502
1476
|
dogfoodConsoleLine: { color: '#d1d5db', fontSize: 10, lineHeight: 14, fontFamily: react_native_1.Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }) },
|
|
@@ -1509,7 +1483,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1509
1483
|
gap: 4,
|
|
1510
1484
|
},
|
|
1511
1485
|
reloadHint: {
|
|
1512
|
-
color: '#
|
|
1486
|
+
color: '#666671',
|
|
1513
1487
|
fontSize: 11,
|
|
1514
1488
|
lineHeight: 15,
|
|
1515
1489
|
paddingHorizontal: 4,
|
|
@@ -1541,7 +1515,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1541
1515
|
backgroundColor: 'transparent',
|
|
1542
1516
|
},
|
|
1543
1517
|
vibeCancelBtnText: {
|
|
1544
|
-
color: '#
|
|
1518
|
+
color: '#5f5f69',
|
|
1545
1519
|
fontSize: 14,
|
|
1546
1520
|
fontWeight: '600',
|
|
1547
1521
|
},
|
|
@@ -1549,7 +1523,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1549
1523
|
paddingHorizontal: 16,
|
|
1550
1524
|
paddingVertical: 8,
|
|
1551
1525
|
borderRadius: 8,
|
|
1552
|
-
backgroundColor: '#
|
|
1526
|
+
backgroundColor: '#5645d8',
|
|
1553
1527
|
minWidth: 72,
|
|
1554
1528
|
alignItems: 'center',
|
|
1555
1529
|
},
|
|
@@ -1559,7 +1533,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1559
1533
|
fontWeight: '700',
|
|
1560
1534
|
},
|
|
1561
1535
|
vibeTaskLine: {
|
|
1562
|
-
color: '#
|
|
1536
|
+
color: '#5645d8',
|
|
1563
1537
|
fontSize: 12,
|
|
1564
1538
|
marginTop: -4,
|
|
1565
1539
|
fontFamily: react_native_1.Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }),
|
|
@@ -1569,10 +1543,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1569
1543
|
backgroundColor: 'rgba(0,0,0,0.55)',
|
|
1570
1544
|
justifyContent: 'flex-end',
|
|
1571
1545
|
},
|
|
1572
|
-
|
|
1573
|
-
width: '100%',
|
|
1574
|
-
justifyContent: 'flex-end',
|
|
1575
|
-
},
|
|
1546
|
+
backdrop: react_native_1.StyleSheet.absoluteFillObject,
|
|
1576
1547
|
modal: {
|
|
1577
1548
|
backgroundColor: '#f8f8fb',
|
|
1578
1549
|
borderTopLeftRadius: 22,
|
|
@@ -1631,7 +1602,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1631
1602
|
tabs: { flexDirection: 'row', gap: 6, padding: 3, borderRadius: 12, backgroundColor: '#ededf3' },
|
|
1632
1603
|
tab: { flex: 1, minHeight: 36, borderRadius: 9, alignItems: 'center', justifyContent: 'center' },
|
|
1633
1604
|
tabSelected: { backgroundColor: '#fff' },
|
|
1634
|
-
tabText: { color: '#
|
|
1605
|
+
tabText: { color: '#666671', fontSize: 12, fontWeight: '700' },
|
|
1635
1606
|
tabTextSelected: { color: '#6252e8' },
|
|
1636
1607
|
tabContent: { gap: 12 },
|
|
1637
1608
|
hidden: { display: 'none' },
|
|
@@ -1656,7 +1627,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1656
1627
|
},
|
|
1657
1628
|
machineRoutes: { flexDirection: 'row', gap: 8 },
|
|
1658
1629
|
machineRouteCard: { flex: 1, minWidth: 0, borderRadius: 11, padding: 10, gap: 3, backgroundColor: '#fff', borderWidth: 1, borderColor: '#e1e1e8' },
|
|
1659
|
-
machineRouteLabel: { color: '#
|
|
1630
|
+
machineRouteLabel: { color: '#666671', fontSize: 10, fontWeight: '700', textTransform: 'uppercase' },
|
|
1660
1631
|
machineRouteValue: { color: '#222229', fontSize: 12, fontWeight: '700' },
|
|
1661
1632
|
machineHeader: {
|
|
1662
1633
|
flexDirection: 'row',
|
|
@@ -1692,7 +1663,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1692
1663
|
letterSpacing: 0.8,
|
|
1693
1664
|
},
|
|
1694
1665
|
machineAction: {
|
|
1695
|
-
color: '#
|
|
1666
|
+
color: '#5645d8',
|
|
1696
1667
|
fontSize: 12,
|
|
1697
1668
|
fontWeight: '700',
|
|
1698
1669
|
},
|
|
@@ -1723,7 +1694,7 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1723
1694
|
},
|
|
1724
1695
|
runnerSectionSubtitle: {
|
|
1725
1696
|
marginTop: 2,
|
|
1726
|
-
color: '#
|
|
1697
|
+
color: '#666671',
|
|
1727
1698
|
fontSize: 12,
|
|
1728
1699
|
},
|
|
1729
1700
|
runnerRefreshBtn: {
|
|
@@ -1750,15 +1721,15 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1750
1721
|
},
|
|
1751
1722
|
runnerCardOk: {
|
|
1752
1723
|
borderColor: 'rgba(34,197,94,0.28)',
|
|
1753
|
-
backgroundColor: 'rgba(
|
|
1724
|
+
backgroundColor: 'rgba(34,197,94,0.08)',
|
|
1754
1725
|
},
|
|
1755
1726
|
runnerCardWarning: {
|
|
1756
1727
|
borderColor: 'rgba(251,191,36,0.28)',
|
|
1757
|
-
backgroundColor: 'rgba(
|
|
1728
|
+
backgroundColor: 'rgba(245,158,11,0.08)',
|
|
1758
1729
|
},
|
|
1759
1730
|
runnerCardError: {
|
|
1760
1731
|
borderColor: 'rgba(248,113,113,0.28)',
|
|
1761
|
-
backgroundColor: 'rgba(
|
|
1732
|
+
backgroundColor: 'rgba(239,68,68,0.07)',
|
|
1762
1733
|
},
|
|
1763
1734
|
runnerCardTop: {
|
|
1764
1735
|
flexDirection: 'row',
|
|
@@ -1777,13 +1748,13 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1777
1748
|
color: '#666671',
|
|
1778
1749
|
},
|
|
1779
1750
|
runnerCardStatusOk: {
|
|
1780
|
-
color: '#
|
|
1751
|
+
color: '#137a3f',
|
|
1781
1752
|
},
|
|
1782
1753
|
runnerCardStatusWarning: {
|
|
1783
|
-
color: '#
|
|
1754
|
+
color: '#9a5700',
|
|
1784
1755
|
},
|
|
1785
1756
|
runnerCardStatusError: {
|
|
1786
|
-
color: '#
|
|
1757
|
+
color: '#b42318',
|
|
1787
1758
|
},
|
|
1788
1759
|
runnerCardDetail: {
|
|
1789
1760
|
color: '#858590',
|
|
@@ -1794,26 +1765,26 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1794
1765
|
borderRadius: 10,
|
|
1795
1766
|
borderWidth: 1,
|
|
1796
1767
|
borderColor: 'rgba(129,140,248,0.35)',
|
|
1797
|
-
backgroundColor: 'rgba(
|
|
1768
|
+
backgroundColor: 'rgba(86,69,216,0.10)',
|
|
1798
1769
|
paddingHorizontal: 12,
|
|
1799
1770
|
paddingVertical: 8,
|
|
1800
1771
|
},
|
|
1801
1772
|
runnerActionBtnText: {
|
|
1802
|
-
color: '#
|
|
1773
|
+
color: '#5645d8',
|
|
1803
1774
|
fontSize: 12,
|
|
1804
1775
|
fontWeight: '700',
|
|
1805
1776
|
},
|
|
1806
|
-
runnerActionBtnSelected: { borderColor: '#
|
|
1777
|
+
runnerActionBtnSelected: { borderColor: '#6555df', backgroundColor: 'rgba(86,69,216,0.18)' },
|
|
1807
1778
|
routingSummary: { flexDirection: 'row', alignItems: 'center', gap: 8, paddingHorizontal: 2 },
|
|
1808
1779
|
routingSummaryLabel: { color: '#7c7c87', fontSize: 11, fontWeight: '600' },
|
|
1809
1780
|
routingSummaryValue: { flex: 1, color: '#6555df', fontSize: 12, fontWeight: '700', textAlign: 'right' },
|
|
1810
1781
|
modelChoiceRow: { gap: 6, paddingTop: 2 },
|
|
1811
1782
|
modelChoice: { borderRadius: 9, borderWidth: 1, borderColor: 'rgba(148,163,184,0.18)', paddingHorizontal: 9, paddingVertical: 6 },
|
|
1812
|
-
modelChoiceSelected: { borderColor: '#
|
|
1783
|
+
modelChoiceSelected: { borderColor: '#6555df', backgroundColor: 'rgba(86,69,216,0.12)' },
|
|
1813
1784
|
modelChoiceText: { color: '#73737e', fontSize: 11 },
|
|
1814
1785
|
modelChoiceTextSelected: { color: '#5e4ce6', fontWeight: '700' },
|
|
1815
1786
|
runnerSectionError: {
|
|
1816
|
-
color: '#
|
|
1787
|
+
color: '#b42318',
|
|
1817
1788
|
fontSize: 12,
|
|
1818
1789
|
lineHeight: 18,
|
|
1819
1790
|
},
|
|
@@ -1833,13 +1804,13 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1833
1804
|
borderRadius: 3,
|
|
1834
1805
|
},
|
|
1835
1806
|
toast: {
|
|
1836
|
-
color: '#
|
|
1807
|
+
color: '#137a3f',
|
|
1837
1808
|
fontSize: 13,
|
|
1838
1809
|
textAlign: 'center',
|
|
1839
1810
|
marginTop: 4,
|
|
1840
1811
|
},
|
|
1841
1812
|
error: {
|
|
1842
|
-
color: '#
|
|
1813
|
+
color: '#b42318',
|
|
1843
1814
|
fontSize: 12,
|
|
1844
1815
|
textAlign: 'center',
|
|
1845
1816
|
marginTop: 4,
|