yaver-feedback-react-native 0.7.16 → 0.7.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FeedbackModal.js +109 -12
- package/dist/P2PClient.d.ts +5 -1
- package/dist/P2PClient.js +15 -2
- package/package.json +1 -1
- package/src/FeedbackModal.tsx +145 -19
- package/src/P2PClient.ts +18 -2
package/dist/FeedbackModal.js
CHANGED
|
@@ -52,6 +52,14 @@ const FeedbackModal = () => {
|
|
|
52
52
|
// hidden button instead of a runtime error.
|
|
53
53
|
const voiceSupported = (0, react_1.useRef)((0, capture_1.isVoiceCaptureSupported)()).current;
|
|
54
54
|
const [lastVideo, setLastVideo] = (0, react_1.useState)(null);
|
|
55
|
+
// Vibing-input mode: same expand-on-tap pattern as email login.
|
|
56
|
+
// Tap "Vibing" once → the button reveals an input + Send; that lets
|
|
57
|
+
// the user say WHAT they want to vibe on instead of firing a canned
|
|
58
|
+
// "pick something for me" prompt (which in 0.7.13 pointed Claude at
|
|
59
|
+
// the wrong project because the matcher grepped the prompt itself).
|
|
60
|
+
const [showVibeInput, setShowVibeInput] = (0, react_1.useState)(false);
|
|
61
|
+
const [vibePrompt, setVibePrompt] = (0, react_1.useState)('');
|
|
62
|
+
const [lastVibeTaskId, setLastVibeTaskId] = (0, react_1.useState)(null);
|
|
55
63
|
const mountedRef = (0, react_1.useRef)(true);
|
|
56
64
|
(0, react_1.useEffect)(() => {
|
|
57
65
|
mountedRef.current = true;
|
|
@@ -263,7 +271,22 @@ const FeedbackModal = () => {
|
|
|
263
271
|
}
|
|
264
272
|
}, [closeSoon]);
|
|
265
273
|
// ─── 3. Vibing ─────────────────────────────────────────────────────
|
|
266
|
-
|
|
274
|
+
// First tap expands the input; second submit fires the actual
|
|
275
|
+
// /vibing/execute. Mirrors the Yaver mobile app's Vibing tab —
|
|
276
|
+
// user types what they want, hits Send, sees the task id back. If
|
|
277
|
+
// left blank, we default to "pick the next small improvement"
|
|
278
|
+
// so a one-tap workflow still works for lazy days.
|
|
279
|
+
const handleVibingButton = (0, react_1.useCallback)(() => {
|
|
280
|
+
if (!showVibeInput) {
|
|
281
|
+
setShowVibeInput(true);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
// collapse if tapped again with empty input
|
|
285
|
+
if (!vibePrompt.trim()) {
|
|
286
|
+
setShowVibeInput(false);
|
|
287
|
+
}
|
|
288
|
+
}, [showVibeInput, vibePrompt]);
|
|
289
|
+
const handleVibingSubmit = (0, react_1.useCallback)(async () => {
|
|
267
290
|
const client = YaverFeedback_1.YaverFeedback.getP2PClient();
|
|
268
291
|
if (!client) {
|
|
269
292
|
setError('Not connected to the agent yet.');
|
|
@@ -280,14 +303,16 @@ const FeedbackModal = () => {
|
|
|
280
303
|
.map((e) => `- ${e.message}`)
|
|
281
304
|
.join('\n')
|
|
282
305
|
: '';
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
'current screen.' +
|
|
287
|
-
|
|
288
|
-
await client.vibing(prompt);
|
|
289
|
-
|
|
290
|
-
|
|
306
|
+
const userPrompt = vibePrompt.trim();
|
|
307
|
+
const prompt = userPrompt
|
|
308
|
+
? userPrompt + errNote
|
|
309
|
+
: 'Pick the next small improvement or fix for this app based on recent activity and the current screen.' +
|
|
310
|
+
errNote;
|
|
311
|
+
const result = await client.vibing(prompt);
|
|
312
|
+
setLastVibeTaskId(result.taskId);
|
|
313
|
+
setToast(`Vibing task ${result.taskId.slice(0, 8)} created`);
|
|
314
|
+
setVibePrompt('');
|
|
315
|
+
setShowVibeInput(false);
|
|
291
316
|
}
|
|
292
317
|
catch (err) {
|
|
293
318
|
setError(err instanceof Error ? err.message : String(err));
|
|
@@ -296,7 +321,7 @@ const FeedbackModal = () => {
|
|
|
296
321
|
if (mountedRef.current)
|
|
297
322
|
setAction('idle');
|
|
298
323
|
}
|
|
299
|
-
}, [
|
|
324
|
+
}, [vibePrompt]);
|
|
300
325
|
// ─── 4. Toggle screen recording ────────────────────────────────────
|
|
301
326
|
const handleToggleRecording = (0, react_1.useCallback)(async () => {
|
|
302
327
|
setError(null);
|
|
@@ -489,8 +514,30 @@ const FeedbackModal = () => {
|
|
|
489
514
|
? 'Capturing…'
|
|
490
515
|
: 'Screenshot & Fix'} tint="#22c55e" onPress={handleScreenshotAndFix} disabled={busy} busy={action === 'capturing'}/>
|
|
491
516
|
|
|
492
|
-
{/* 3. Vibing
|
|
493
|
-
|
|
517
|
+
{/* 3. Vibing — expands to an input box on first tap
|
|
518
|
+
so the user says WHAT they want to vibe on, just
|
|
519
|
+
like the Yaver mobile app's Vibing tab. Second
|
|
520
|
+
tap (Send) fires /vibing/execute with the typed
|
|
521
|
+
prompt + resolved bundle id so the agent routes
|
|
522
|
+
to the right repo. */}
|
|
523
|
+
{!showVibeInput ? (<ActionRow label={action === 'vibing' ? 'Starting…' : 'Vibing'} tint="#818cf8" onPress={handleVibingButton} disabled={busy} busy={action === 'vibing'}/>) : (<react_native_1.View style={styles.vibeInputRow}>
|
|
524
|
+
<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}/>
|
|
525
|
+
<react_native_1.View style={styles.vibeInputButtons}>
|
|
526
|
+
<react_native_1.Pressable onPress={() => { setShowVibeInput(false); setVibePrompt(''); }} style={({ pressed }) => [styles.vibeCancelBtn, pressed && styles.buttonPressed]} disabled={action === 'vibing'}>
|
|
527
|
+
<react_native_1.Text style={styles.vibeCancelBtnText}>Cancel</react_native_1.Text>
|
|
528
|
+
</react_native_1.Pressable>
|
|
529
|
+
<react_native_1.Pressable onPress={handleVibingSubmit} style={({ pressed }) => [
|
|
530
|
+
styles.vibeSendBtn,
|
|
531
|
+
pressed && styles.buttonPressed,
|
|
532
|
+
action === 'vibing' && { opacity: 0.6 },
|
|
533
|
+
]} disabled={action === 'vibing'}>
|
|
534
|
+
{action === 'vibing' ? (<react_native_1.ActivityIndicator color="#fff"/>) : (<react_native_1.Text style={styles.vibeSendBtnText}>Send</react_native_1.Text>)}
|
|
535
|
+
</react_native_1.Pressable>
|
|
536
|
+
</react_native_1.View>
|
|
537
|
+
</react_native_1.View>)}
|
|
538
|
+
{lastVibeTaskId && action !== 'vibing' && (<react_native_1.Text style={styles.vibeTaskLine} numberOfLines={1}>
|
|
539
|
+
Last vibing task: {lastVibeTaskId.slice(0, 12)}…
|
|
540
|
+
</react_native_1.Text>)}
|
|
494
541
|
|
|
495
542
|
{/* Voice note — only rendered when expo-av is installed.
|
|
496
543
|
Tap to start, tap again to stop → transcribes via
|
|
@@ -537,6 +584,56 @@ const ActionRow = ({ label, tint, onPress, disabled, busy, }) => (<react_native_
|
|
|
537
584
|
{busy ? (<react_native_1.ActivityIndicator color={tint} size="small"/>) : (<react_native_1.Text style={[styles.actionText, { color: tint }]}>{label}</react_native_1.Text>)}
|
|
538
585
|
</react_native_1.Pressable>);
|
|
539
586
|
const styles = react_native_1.StyleSheet.create({
|
|
587
|
+
vibeInputRow: {
|
|
588
|
+
backgroundColor: 'rgba(129,140,248,0.08)',
|
|
589
|
+
borderColor: 'rgba(129,140,248,0.4)',
|
|
590
|
+
borderWidth: 1,
|
|
591
|
+
borderRadius: 12,
|
|
592
|
+
padding: 12,
|
|
593
|
+
gap: 10,
|
|
594
|
+
},
|
|
595
|
+
vibeInput: {
|
|
596
|
+
color: '#fff',
|
|
597
|
+
fontSize: 15,
|
|
598
|
+
minHeight: 64,
|
|
599
|
+
textAlignVertical: 'top',
|
|
600
|
+
padding: 0,
|
|
601
|
+
},
|
|
602
|
+
vibeInputButtons: {
|
|
603
|
+
flexDirection: 'row',
|
|
604
|
+
justifyContent: 'flex-end',
|
|
605
|
+
gap: 10,
|
|
606
|
+
},
|
|
607
|
+
vibeCancelBtn: {
|
|
608
|
+
paddingHorizontal: 14,
|
|
609
|
+
paddingVertical: 8,
|
|
610
|
+
borderRadius: 8,
|
|
611
|
+
backgroundColor: 'transparent',
|
|
612
|
+
},
|
|
613
|
+
vibeCancelBtnText: {
|
|
614
|
+
color: '#999',
|
|
615
|
+
fontSize: 14,
|
|
616
|
+
fontWeight: '600',
|
|
617
|
+
},
|
|
618
|
+
vibeSendBtn: {
|
|
619
|
+
paddingHorizontal: 16,
|
|
620
|
+
paddingVertical: 8,
|
|
621
|
+
borderRadius: 8,
|
|
622
|
+
backgroundColor: '#818cf8',
|
|
623
|
+
minWidth: 72,
|
|
624
|
+
alignItems: 'center',
|
|
625
|
+
},
|
|
626
|
+
vibeSendBtnText: {
|
|
627
|
+
color: '#fff',
|
|
628
|
+
fontSize: 14,
|
|
629
|
+
fontWeight: '700',
|
|
630
|
+
},
|
|
631
|
+
vibeTaskLine: {
|
|
632
|
+
color: '#818cf8',
|
|
633
|
+
fontSize: 12,
|
|
634
|
+
marginTop: -4,
|
|
635
|
+
fontFamily: react_native_1.Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }),
|
|
636
|
+
},
|
|
540
637
|
overlay: {
|
|
541
638
|
flex: 1,
|
|
542
639
|
backgroundColor: 'rgba(0,0,0,0.55)',
|
package/dist/P2PClient.d.ts
CHANGED
|
@@ -83,7 +83,11 @@ export declare class P2PClient {
|
|
|
83
83
|
* vibing from Claude Code / the Yaver mobile app; this method is a
|
|
84
84
|
* convenience for the SDK's one-tap bug-report-to-vibing path.
|
|
85
85
|
*/
|
|
86
|
-
vibing(prompt: string,
|
|
86
|
+
vibing(prompt: string, opts?: {
|
|
87
|
+
projectName?: string;
|
|
88
|
+
bundleId?: string;
|
|
89
|
+
projectPath?: string;
|
|
90
|
+
}): Promise<{
|
|
87
91
|
taskId: string;
|
|
88
92
|
}>;
|
|
89
93
|
/**
|
package/dist/P2PClient.js
CHANGED
|
@@ -327,14 +327,27 @@ class P2PClient {
|
|
|
327
327
|
* vibing from Claude Code / the Yaver mobile app; this method is a
|
|
328
328
|
* convenience for the SDK's one-tap bug-report-to-vibing path.
|
|
329
329
|
*/
|
|
330
|
-
async vibing(prompt,
|
|
330
|
+
async vibing(prompt, opts) {
|
|
331
|
+
// Resolve app identity exactly the same way we do for
|
|
332
|
+
// reloadApp — bundle ID from expo-constants or native config.
|
|
333
|
+
// Without this, the agent falls back to "grep the prompt for a
|
|
334
|
+
// word that looks like a project name," which is catastrophically
|
|
335
|
+
// wrong: the prompt 'tapped Vibing' matched 'in' → picked mprint
|
|
336
|
+
// → Claude vibed on the wrong repo. Passing the bundle/name lets
|
|
337
|
+
// the agent go straight to findMobileProjectByName / bundleId.
|
|
338
|
+
const identity = resolveAppIdentity(opts);
|
|
331
339
|
const response = await fetch(`${this.baseUrl}/vibing/execute`, {
|
|
332
340
|
method: 'POST',
|
|
333
341
|
headers: {
|
|
334
342
|
Authorization: `Bearer ${this.authToken}`,
|
|
335
343
|
'Content-Type': 'application/json',
|
|
336
344
|
},
|
|
337
|
-
body: JSON.stringify({
|
|
345
|
+
body: JSON.stringify({
|
|
346
|
+
prompt,
|
|
347
|
+
projectPath: identity.projectPath ?? opts?.projectPath ?? '',
|
|
348
|
+
projectName: identity.projectName,
|
|
349
|
+
bundleId: identity.bundleId,
|
|
350
|
+
}),
|
|
338
351
|
});
|
|
339
352
|
if (!response.ok) {
|
|
340
353
|
const text = await response.text().catch(() => '');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaver-feedback-react-native",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.17",
|
|
4
4
|
"description": "Visual feedback SDK for Yaver — bug reports, screen recording, voice annotations, and local-first developer workflows",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/src/FeedbackModal.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
Pressable,
|
|
8
8
|
StyleSheet,
|
|
9
9
|
Text,
|
|
10
|
+
TextInput,
|
|
10
11
|
View,
|
|
11
12
|
} from 'react-native';
|
|
12
13
|
import { YaverFeedback } from './YaverFeedback';
|
|
@@ -65,6 +66,14 @@ export const FeedbackModal: React.FC = () => {
|
|
|
65
66
|
// hidden button instead of a runtime error.
|
|
66
67
|
const voiceSupported = useRef<boolean>(isVoiceCaptureSupported()).current;
|
|
67
68
|
const [lastVideo, setLastVideo] = useState<LastVideo | null>(null);
|
|
69
|
+
// Vibing-input mode: same expand-on-tap pattern as email login.
|
|
70
|
+
// Tap "Vibing" once → the button reveals an input + Send; that lets
|
|
71
|
+
// the user say WHAT they want to vibe on instead of firing a canned
|
|
72
|
+
// "pick something for me" prompt (which in 0.7.13 pointed Claude at
|
|
73
|
+
// the wrong project because the matcher grepped the prompt itself).
|
|
74
|
+
const [showVibeInput, setShowVibeInput] = useState(false);
|
|
75
|
+
const [vibePrompt, setVibePrompt] = useState('');
|
|
76
|
+
const [lastVibeTaskId, setLastVibeTaskId] = useState<string | null>(null);
|
|
68
77
|
const mountedRef = useRef(true);
|
|
69
78
|
|
|
70
79
|
useEffect(() => {
|
|
@@ -285,7 +294,23 @@ export const FeedbackModal: React.FC = () => {
|
|
|
285
294
|
}, [closeSoon]);
|
|
286
295
|
|
|
287
296
|
// ─── 3. Vibing ─────────────────────────────────────────────────────
|
|
288
|
-
|
|
297
|
+
// First tap expands the input; second submit fires the actual
|
|
298
|
+
// /vibing/execute. Mirrors the Yaver mobile app's Vibing tab —
|
|
299
|
+
// user types what they want, hits Send, sees the task id back. If
|
|
300
|
+
// left blank, we default to "pick the next small improvement"
|
|
301
|
+
// so a one-tap workflow still works for lazy days.
|
|
302
|
+
const handleVibingButton = useCallback(() => {
|
|
303
|
+
if (!showVibeInput) {
|
|
304
|
+
setShowVibeInput(true);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// collapse if tapped again with empty input
|
|
308
|
+
if (!vibePrompt.trim()) {
|
|
309
|
+
setShowVibeInput(false);
|
|
310
|
+
}
|
|
311
|
+
}, [showVibeInput, vibePrompt]);
|
|
312
|
+
|
|
313
|
+
const handleVibingSubmit = useCallback(async () => {
|
|
289
314
|
const client = YaverFeedback.getP2PClient();
|
|
290
315
|
if (!client) {
|
|
291
316
|
setError('Not connected to the agent yet.');
|
|
@@ -303,21 +328,22 @@ export const FeedbackModal: React.FC = () => {
|
|
|
303
328
|
.map((e) => `- ${e.message}`)
|
|
304
329
|
.join('\n')
|
|
305
330
|
: '';
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
'next small improvement or fix based on recent activity and the ' +
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
setToast(
|
|
314
|
-
|
|
331
|
+
const userPrompt = vibePrompt.trim();
|
|
332
|
+
const prompt = userPrompt
|
|
333
|
+
? userPrompt + errNote
|
|
334
|
+
: 'Pick the next small improvement or fix for this app based on recent activity and the current screen.' +
|
|
335
|
+
errNote;
|
|
336
|
+
const result = await client.vibing(prompt);
|
|
337
|
+
setLastVibeTaskId(result.taskId);
|
|
338
|
+
setToast(`Vibing task ${result.taskId.slice(0, 8)} created`);
|
|
339
|
+
setVibePrompt('');
|
|
340
|
+
setShowVibeInput(false);
|
|
315
341
|
} catch (err: unknown) {
|
|
316
342
|
setError(err instanceof Error ? err.message : String(err));
|
|
317
343
|
} finally {
|
|
318
344
|
if (mountedRef.current) setAction('idle');
|
|
319
345
|
}
|
|
320
|
-
}, [
|
|
346
|
+
}, [vibePrompt]);
|
|
321
347
|
|
|
322
348
|
// ─── 4. Toggle screen recording ────────────────────────────────────
|
|
323
349
|
const handleToggleRecording = useCallback(async () => {
|
|
@@ -537,14 +563,64 @@ export const FeedbackModal: React.FC = () => {
|
|
|
537
563
|
busy={action === 'capturing'}
|
|
538
564
|
/>
|
|
539
565
|
|
|
540
|
-
{/* 3. Vibing
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
566
|
+
{/* 3. Vibing — expands to an input box on first tap
|
|
567
|
+
so the user says WHAT they want to vibe on, just
|
|
568
|
+
like the Yaver mobile app's Vibing tab. Second
|
|
569
|
+
tap (Send) fires /vibing/execute with the typed
|
|
570
|
+
prompt + resolved bundle id so the agent routes
|
|
571
|
+
to the right repo. */}
|
|
572
|
+
{!showVibeInput ? (
|
|
573
|
+
<ActionRow
|
|
574
|
+
label={action === 'vibing' ? 'Starting…' : 'Vibing'}
|
|
575
|
+
tint="#818cf8"
|
|
576
|
+
onPress={handleVibingButton}
|
|
577
|
+
disabled={busy}
|
|
578
|
+
busy={action === 'vibing'}
|
|
579
|
+
/>
|
|
580
|
+
) : (
|
|
581
|
+
<View style={styles.vibeInputRow}>
|
|
582
|
+
<TextInput
|
|
583
|
+
style={styles.vibeInput}
|
|
584
|
+
placeholder="What do you want to vibe on?"
|
|
585
|
+
placeholderTextColor="#666"
|
|
586
|
+
value={vibePrompt}
|
|
587
|
+
onChangeText={setVibePrompt}
|
|
588
|
+
multiline
|
|
589
|
+
autoFocus
|
|
590
|
+
editable={action !== 'vibing'}
|
|
591
|
+
blurOnSubmit={false}
|
|
592
|
+
/>
|
|
593
|
+
<View style={styles.vibeInputButtons}>
|
|
594
|
+
<Pressable
|
|
595
|
+
onPress={() => { setShowVibeInput(false); setVibePrompt(''); }}
|
|
596
|
+
style={({ pressed }) => [styles.vibeCancelBtn, pressed && styles.buttonPressed]}
|
|
597
|
+
disabled={action === 'vibing'}
|
|
598
|
+
>
|
|
599
|
+
<Text style={styles.vibeCancelBtnText}>Cancel</Text>
|
|
600
|
+
</Pressable>
|
|
601
|
+
<Pressable
|
|
602
|
+
onPress={handleVibingSubmit}
|
|
603
|
+
style={({ pressed }) => [
|
|
604
|
+
styles.vibeSendBtn,
|
|
605
|
+
pressed && styles.buttonPressed,
|
|
606
|
+
action === 'vibing' && { opacity: 0.6 },
|
|
607
|
+
]}
|
|
608
|
+
disabled={action === 'vibing'}
|
|
609
|
+
>
|
|
610
|
+
{action === 'vibing' ? (
|
|
611
|
+
<ActivityIndicator color="#fff" />
|
|
612
|
+
) : (
|
|
613
|
+
<Text style={styles.vibeSendBtnText}>Send</Text>
|
|
614
|
+
)}
|
|
615
|
+
</Pressable>
|
|
616
|
+
</View>
|
|
617
|
+
</View>
|
|
618
|
+
)}
|
|
619
|
+
{lastVibeTaskId && action !== 'vibing' && (
|
|
620
|
+
<Text style={styles.vibeTaskLine} numberOfLines={1}>
|
|
621
|
+
Last vibing task: {lastVibeTaskId.slice(0, 12)}…
|
|
622
|
+
</Text>
|
|
623
|
+
)}
|
|
548
624
|
|
|
549
625
|
{/* Voice note — only rendered when expo-av is installed.
|
|
550
626
|
Tap to start, tap again to stop → transcribes via
|
|
@@ -647,6 +723,56 @@ const ActionRow: React.FC<ActionRowProps> = ({
|
|
|
647
723
|
);
|
|
648
724
|
|
|
649
725
|
const styles = StyleSheet.create({
|
|
726
|
+
vibeInputRow: {
|
|
727
|
+
backgroundColor: 'rgba(129,140,248,0.08)',
|
|
728
|
+
borderColor: 'rgba(129,140,248,0.4)',
|
|
729
|
+
borderWidth: 1,
|
|
730
|
+
borderRadius: 12,
|
|
731
|
+
padding: 12,
|
|
732
|
+
gap: 10,
|
|
733
|
+
},
|
|
734
|
+
vibeInput: {
|
|
735
|
+
color: '#fff',
|
|
736
|
+
fontSize: 15,
|
|
737
|
+
minHeight: 64,
|
|
738
|
+
textAlignVertical: 'top',
|
|
739
|
+
padding: 0,
|
|
740
|
+
},
|
|
741
|
+
vibeInputButtons: {
|
|
742
|
+
flexDirection: 'row',
|
|
743
|
+
justifyContent: 'flex-end',
|
|
744
|
+
gap: 10,
|
|
745
|
+
},
|
|
746
|
+
vibeCancelBtn: {
|
|
747
|
+
paddingHorizontal: 14,
|
|
748
|
+
paddingVertical: 8,
|
|
749
|
+
borderRadius: 8,
|
|
750
|
+
backgroundColor: 'transparent',
|
|
751
|
+
},
|
|
752
|
+
vibeCancelBtnText: {
|
|
753
|
+
color: '#999',
|
|
754
|
+
fontSize: 14,
|
|
755
|
+
fontWeight: '600',
|
|
756
|
+
},
|
|
757
|
+
vibeSendBtn: {
|
|
758
|
+
paddingHorizontal: 16,
|
|
759
|
+
paddingVertical: 8,
|
|
760
|
+
borderRadius: 8,
|
|
761
|
+
backgroundColor: '#818cf8',
|
|
762
|
+
minWidth: 72,
|
|
763
|
+
alignItems: 'center',
|
|
764
|
+
},
|
|
765
|
+
vibeSendBtnText: {
|
|
766
|
+
color: '#fff',
|
|
767
|
+
fontSize: 14,
|
|
768
|
+
fontWeight: '700',
|
|
769
|
+
},
|
|
770
|
+
vibeTaskLine: {
|
|
771
|
+
color: '#818cf8',
|
|
772
|
+
fontSize: 12,
|
|
773
|
+
marginTop: -4,
|
|
774
|
+
fontFamily: Platform.select({ ios: 'Menlo', android: 'monospace', default: 'monospace' }),
|
|
775
|
+
},
|
|
650
776
|
overlay: {
|
|
651
777
|
flex: 1,
|
|
652
778
|
backgroundColor: 'rgba(0,0,0,0.55)',
|
package/src/P2PClient.ts
CHANGED
|
@@ -376,14 +376,30 @@ export class P2PClient {
|
|
|
376
376
|
* vibing from Claude Code / the Yaver mobile app; this method is a
|
|
377
377
|
* convenience for the SDK's one-tap bug-report-to-vibing path.
|
|
378
378
|
*/
|
|
379
|
-
async vibing(
|
|
379
|
+
async vibing(
|
|
380
|
+
prompt: string,
|
|
381
|
+
opts?: { projectName?: string; bundleId?: string; projectPath?: string },
|
|
382
|
+
): Promise<{ taskId: string }> {
|
|
383
|
+
// Resolve app identity exactly the same way we do for
|
|
384
|
+
// reloadApp — bundle ID from expo-constants or native config.
|
|
385
|
+
// Without this, the agent falls back to "grep the prompt for a
|
|
386
|
+
// word that looks like a project name," which is catastrophically
|
|
387
|
+
// wrong: the prompt 'tapped Vibing' matched 'in' → picked mprint
|
|
388
|
+
// → Claude vibed on the wrong repo. Passing the bundle/name lets
|
|
389
|
+
// the agent go straight to findMobileProjectByName / bundleId.
|
|
390
|
+
const identity = resolveAppIdentity(opts);
|
|
380
391
|
const response = await fetch(`${this.baseUrl}/vibing/execute`, {
|
|
381
392
|
method: 'POST',
|
|
382
393
|
headers: {
|
|
383
394
|
Authorization: `Bearer ${this.authToken}`,
|
|
384
395
|
'Content-Type': 'application/json',
|
|
385
396
|
},
|
|
386
|
-
body: JSON.stringify({
|
|
397
|
+
body: JSON.stringify({
|
|
398
|
+
prompt,
|
|
399
|
+
projectPath: identity.projectPath ?? opts?.projectPath ?? '',
|
|
400
|
+
projectName: identity.projectName,
|
|
401
|
+
bundleId: identity.bundleId,
|
|
402
|
+
}),
|
|
387
403
|
});
|
|
388
404
|
if (!response.ok) {
|
|
389
405
|
const text = await response.text().catch(() => '');
|