yaver-feedback-react-native 0.8.9 → 0.8.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/dist/FeedbackModal.js +69 -2
- package/dist/P2PClient.d.ts +6 -0
- package/dist/P2PClient.js +19 -0
- package/dist/YaverFeedback.d.ts +4 -0
- package/dist/YaverFeedback.js +9 -0
- package/package.json +1 -1
- package/src/FeedbackModal.tsx +93 -2
- package/src/P2PClient.ts +23 -0
- package/src/YaverFeedback.ts +13 -0
package/dist/FeedbackModal.js
CHANGED
|
@@ -1049,7 +1049,15 @@ const RunnerAuthNativeModal = ({ runner, onClose }) => {
|
|
|
1049
1049
|
const [session, setSession] = (0, react_1.useState)(null);
|
|
1050
1050
|
const [startError, setStartError] = (0, react_1.useState)(null);
|
|
1051
1051
|
const [copied, setCopied] = (0, react_1.useState)(false);
|
|
1052
|
+
const [pasteCode, setPasteCode] = (0, react_1.useState)('');
|
|
1053
|
+
const [submitting, setSubmitting] = (0, react_1.useState)(false);
|
|
1054
|
+
const [submitError, setSubmitError] = (0, react_1.useState)(null);
|
|
1052
1055
|
const startedRef = (0, react_1.useRef)(false);
|
|
1056
|
+
// Claude is the only runner that needs the user to paste a verifier
|
|
1057
|
+
// code back from platform.claude.com's callback page; Codex device-
|
|
1058
|
+
// auth and OpenCode (no OAuth at all) bypass this. Mirrors the
|
|
1059
|
+
// requiresPasteBack check in iOS YaverRunnerAuthFlowPane.swift.
|
|
1060
|
+
const needsPasteBack = runner === 'claude' || runner === 'claude-code';
|
|
1053
1061
|
(0, react_1.useEffect)(() => {
|
|
1054
1062
|
if (startedRef.current)
|
|
1055
1063
|
return;
|
|
@@ -1164,9 +1172,68 @@ const RunnerAuthNativeModal = ({ runner, onClose }) => {
|
|
|
1164
1172
|
</react_native_1.Text>
|
|
1165
1173
|
</react_native_1.Pressable>
|
|
1166
1174
|
</react_native_1.View>) : null}
|
|
1175
|
+
{needsPasteBack ? (<react_native_1.View style={{ marginTop: 14 }}>
|
|
1176
|
+
<react_native_1.Text style={runnerAuthModalStyles.codeLabel}>
|
|
1177
|
+
PASTE CODE FROM CLAUDE.COM
|
|
1178
|
+
</react_native_1.Text>
|
|
1179
|
+
<react_native_1.View style={{ flexDirection: 'row', gap: 8, marginTop: 6 }}>
|
|
1180
|
+
<react_native_1.View style={{
|
|
1181
|
+
flex: 1,
|
|
1182
|
+
backgroundColor: 'rgba(148,163,184,0.10)',
|
|
1183
|
+
borderRadius: 10,
|
|
1184
|
+
paddingHorizontal: 10,
|
|
1185
|
+
}}>
|
|
1186
|
+
{/* Lazy-import TextInput so the SDK doesn't pull
|
|
1187
|
+
extra surface from react-native at module load. */}
|
|
1188
|
+
{(() => {
|
|
1189
|
+
const { TextInput } = require('react-native');
|
|
1190
|
+
return (<TextInput value={pasteCode} onChangeText={(t) => {
|
|
1191
|
+
setPasteCode(t);
|
|
1192
|
+
setSubmitError(null);
|
|
1193
|
+
}} placeholder="paste code here" placeholderTextColor="#64748b" autoCapitalize="none" autoCorrect={false} spellCheck={false} style={{ color: '#f1f5f9', fontSize: 14, paddingVertical: 10 }}/>);
|
|
1194
|
+
})()}
|
|
1195
|
+
</react_native_1.View>
|
|
1196
|
+
<react_native_1.Pressable disabled={!pasteCode.trim() || submitting} onPress={async () => {
|
|
1197
|
+
if (!session || !pasteCode.trim())
|
|
1198
|
+
return;
|
|
1199
|
+
setSubmitting(true);
|
|
1200
|
+
setSubmitError(null);
|
|
1201
|
+
try {
|
|
1202
|
+
const next = await YaverFeedback_1.YaverFeedback.submitRunnerBrowserAuthCode(session.id, pasteCode.trim());
|
|
1203
|
+
setSession(next);
|
|
1204
|
+
setPasteCode('');
|
|
1205
|
+
}
|
|
1206
|
+
catch (err) {
|
|
1207
|
+
setSubmitError(err instanceof Error ? err.message : String(err));
|
|
1208
|
+
}
|
|
1209
|
+
finally {
|
|
1210
|
+
setSubmitting(false);
|
|
1211
|
+
}
|
|
1212
|
+
}} style={{
|
|
1213
|
+
paddingHorizontal: 14,
|
|
1214
|
+
justifyContent: 'center',
|
|
1215
|
+
backgroundColor: !pasteCode.trim() || submitting
|
|
1216
|
+
? 'rgba(124,58,237,0.4)'
|
|
1217
|
+
: '#7c3aed',
|
|
1218
|
+
borderRadius: 10,
|
|
1219
|
+
}}>
|
|
1220
|
+
<react_native_1.Text style={{ color: 'white', fontWeight: '600' }}>
|
|
1221
|
+
{submitting ? '…' : 'Submit'}
|
|
1222
|
+
</react_native_1.Text>
|
|
1223
|
+
</react_native_1.Pressable>
|
|
1224
|
+
</react_native_1.View>
|
|
1225
|
+
{submitError ? (<react_native_1.Text style={{
|
|
1226
|
+
marginTop: 6,
|
|
1227
|
+
color: '#fca5a5',
|
|
1228
|
+
fontSize: 12,
|
|
1229
|
+
}}>
|
|
1230
|
+
{submitError}
|
|
1231
|
+
</react_native_1.Text>) : null}
|
|
1232
|
+
</react_native_1.View>) : null}
|
|
1167
1233
|
<react_native_1.Text style={runnerAuthModalStyles.phishingHint}>
|
|
1168
|
-
|
|
1169
|
-
|
|
1234
|
+
{needsPasteBack
|
|
1235
|
+
? 'After authorising on platform.claude.com, copy the code from the callback page and paste it above. Never share this code.'
|
|
1236
|
+
: 'Device codes are a common phishing target. Never share this code. This dialog turns green automatically once sign-in completes.'}
|
|
1170
1237
|
</react_native_1.Text>
|
|
1171
1238
|
</react_native_1.View>)}
|
|
1172
1239
|
</react_native_1.View>
|
package/dist/P2PClient.d.ts
CHANGED
|
@@ -47,6 +47,12 @@ export declare class P2PClient {
|
|
|
47
47
|
startRunnerBrowserAuth(runner: string): Promise<RunnerBrowserAuthSession>;
|
|
48
48
|
getRunnerBrowserAuthStatus(sessionId: string): Promise<RunnerBrowserAuthSession>;
|
|
49
49
|
cancelRunnerBrowserAuth(sessionId: string): Promise<void>;
|
|
50
|
+
/** Submit the verifier code Anthropic shows on the callback page so
|
|
51
|
+
* the agent can finalise claude CLI's OAuth handshake. Codex doesn't
|
|
52
|
+
* use this — its device-auth flow auto-resolves via polling — but
|
|
53
|
+
* the SDK still exposes it for symmetry with mobile/src/components/
|
|
54
|
+
* RunnerAuthModal.tsx and the Swift YaverRunnerAuthFlowPane. */
|
|
55
|
+
submitRunnerBrowserAuthCode(sessionId: string, code: string): Promise<RunnerBrowserAuthSession>;
|
|
50
56
|
capabilitySnapshot(): Promise<CapabilitySnapshot | null>;
|
|
51
57
|
incidents(opts?: {
|
|
52
58
|
category?: string;
|
package/dist/P2PClient.js
CHANGED
|
@@ -155,6 +155,25 @@ class P2PClient {
|
|
|
155
155
|
}
|
|
156
156
|
catch { /* best-effort */ }
|
|
157
157
|
}
|
|
158
|
+
/** Submit the verifier code Anthropic shows on the callback page so
|
|
159
|
+
* the agent can finalise claude CLI's OAuth handshake. Codex doesn't
|
|
160
|
+
* use this — its device-auth flow auto-resolves via polling — but
|
|
161
|
+
* the SDK still exposes it for symmetry with mobile/src/components/
|
|
162
|
+
* RunnerAuthModal.tsx and the Swift YaverRunnerAuthFlowPane. */
|
|
163
|
+
async submitRunnerBrowserAuthCode(sessionId, code) {
|
|
164
|
+
const url = `${this.baseUrl}/runner-auth/browser/submit-code`;
|
|
165
|
+
const resp = await fetch(url, {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: { ...this.authHeaders(), 'Content-Type': 'application/json' },
|
|
168
|
+
body: JSON.stringify({ id: sessionId, code }),
|
|
169
|
+
});
|
|
170
|
+
if (!resp.ok) {
|
|
171
|
+
const text = await resp.text().catch(() => '');
|
|
172
|
+
throw new Error(`submitRunnerBrowserAuthCode HTTP ${resp.status}: ${text}`);
|
|
173
|
+
}
|
|
174
|
+
const data = await resp.json();
|
|
175
|
+
return data.session;
|
|
176
|
+
}
|
|
158
177
|
async capabilitySnapshot() {
|
|
159
178
|
try {
|
|
160
179
|
const resp = await fetch(`${this.baseUrl}/capabilities/snapshot`, { headers: this.authHeaders() });
|
package/dist/YaverFeedback.d.ts
CHANGED
|
@@ -78,6 +78,10 @@ export declare class YaverFeedback {
|
|
|
78
78
|
static startRunnerBrowserAuth(runner: string): Promise<import('./types').RunnerBrowserAuthSession>;
|
|
79
79
|
static getRunnerBrowserAuthStatus(sessionId: string): Promise<import('./types').RunnerBrowserAuthSession>;
|
|
80
80
|
static cancelRunnerBrowserAuth(sessionId: string): Promise<void>;
|
|
81
|
+
/** Submit the Claude paste-back verifier so the agent can finalise the
|
|
82
|
+
* OAuth handshake. RunnerAuthModal calls this after the user copies
|
|
83
|
+
* the code from platform.claude.com's callback page. */
|
|
84
|
+
static submitRunnerBrowserAuthCode(sessionId: string, code: string): Promise<import('./types').RunnerBrowserAuthSession>;
|
|
81
85
|
/**
|
|
82
86
|
* Sign out: clear cached token + device, tear down the P2P client. The
|
|
83
87
|
* SDK stays enabled; the next feedback trigger will re-prompt for login.
|
package/dist/YaverFeedback.js
CHANGED
|
@@ -571,6 +571,15 @@ class YaverFeedback {
|
|
|
571
571
|
return;
|
|
572
572
|
await p2pClient.cancelRunnerBrowserAuth(sessionId);
|
|
573
573
|
}
|
|
574
|
+
/** Submit the Claude paste-back verifier so the agent can finalise the
|
|
575
|
+
* OAuth handshake. RunnerAuthModal calls this after the user copies
|
|
576
|
+
* the code from platform.claude.com's callback page. */
|
|
577
|
+
static async submitRunnerBrowserAuthCode(sessionId, code) {
|
|
578
|
+
if (!p2pClient) {
|
|
579
|
+
throw new Error('Not connected to any agent.');
|
|
580
|
+
}
|
|
581
|
+
return p2pClient.submitRunnerBrowserAuthCode(sessionId, code);
|
|
582
|
+
}
|
|
574
583
|
/**
|
|
575
584
|
* Sign out: clear cached token + device, tear down the P2P client. The
|
|
576
585
|
* SDK stays enabled; the next feedback trigger will re-prompt for login.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaver-feedback-react-native",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"description": "Visual feedback SDK for Yaver \u2014 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
|
@@ -1251,7 +1251,15 @@ const RunnerAuthNativeModal: React.FC<{
|
|
|
1251
1251
|
const [session, setSession] = useState<import('./types').RunnerBrowserAuthSession | null>(null);
|
|
1252
1252
|
const [startError, setStartError] = useState<string | null>(null);
|
|
1253
1253
|
const [copied, setCopied] = useState(false);
|
|
1254
|
+
const [pasteCode, setPasteCode] = useState('');
|
|
1255
|
+
const [submitting, setSubmitting] = useState(false);
|
|
1256
|
+
const [submitError, setSubmitError] = useState<string | null>(null);
|
|
1254
1257
|
const startedRef = useRef(false);
|
|
1258
|
+
// Claude is the only runner that needs the user to paste a verifier
|
|
1259
|
+
// code back from platform.claude.com's callback page; Codex device-
|
|
1260
|
+
// auth and OpenCode (no OAuth at all) bypass this. Mirrors the
|
|
1261
|
+
// requiresPasteBack check in iOS YaverRunnerAuthFlowPane.swift.
|
|
1262
|
+
const needsPasteBack = runner === 'claude' || runner === 'claude-code';
|
|
1255
1263
|
|
|
1256
1264
|
useEffect(() => {
|
|
1257
1265
|
if (startedRef.current) return;
|
|
@@ -1380,9 +1388,92 @@ const RunnerAuthNativeModal: React.FC<{
|
|
|
1380
1388
|
</Pressable>
|
|
1381
1389
|
</View>
|
|
1382
1390
|
) : null}
|
|
1391
|
+
{needsPasteBack ? (
|
|
1392
|
+
<View style={{ marginTop: 14 }}>
|
|
1393
|
+
<Text style={runnerAuthModalStyles.codeLabel}>
|
|
1394
|
+
PASTE CODE FROM CLAUDE.COM
|
|
1395
|
+
</Text>
|
|
1396
|
+
<View style={{ flexDirection: 'row', gap: 8, marginTop: 6 }}>
|
|
1397
|
+
<View
|
|
1398
|
+
style={{
|
|
1399
|
+
flex: 1,
|
|
1400
|
+
backgroundColor: 'rgba(148,163,184,0.10)',
|
|
1401
|
+
borderRadius: 10,
|
|
1402
|
+
paddingHorizontal: 10,
|
|
1403
|
+
}}
|
|
1404
|
+
>
|
|
1405
|
+
{/* Lazy-import TextInput so the SDK doesn't pull
|
|
1406
|
+
extra surface from react-native at module load. */}
|
|
1407
|
+
{(() => {
|
|
1408
|
+
const { TextInput } = require('react-native');
|
|
1409
|
+
return (
|
|
1410
|
+
<TextInput
|
|
1411
|
+
value={pasteCode}
|
|
1412
|
+
onChangeText={(t: string) => {
|
|
1413
|
+
setPasteCode(t);
|
|
1414
|
+
setSubmitError(null);
|
|
1415
|
+
}}
|
|
1416
|
+
placeholder="paste code here"
|
|
1417
|
+
placeholderTextColor="#64748b"
|
|
1418
|
+
autoCapitalize="none"
|
|
1419
|
+
autoCorrect={false}
|
|
1420
|
+
spellCheck={false}
|
|
1421
|
+
style={{ color: '#f1f5f9', fontSize: 14, paddingVertical: 10 }}
|
|
1422
|
+
/>
|
|
1423
|
+
);
|
|
1424
|
+
})()}
|
|
1425
|
+
</View>
|
|
1426
|
+
<Pressable
|
|
1427
|
+
disabled={!pasteCode.trim() || submitting}
|
|
1428
|
+
onPress={async () => {
|
|
1429
|
+
if (!session || !pasteCode.trim()) return;
|
|
1430
|
+
setSubmitting(true);
|
|
1431
|
+
setSubmitError(null);
|
|
1432
|
+
try {
|
|
1433
|
+
const next = await YaverFeedback.submitRunnerBrowserAuthCode(
|
|
1434
|
+
session.id,
|
|
1435
|
+
pasteCode.trim(),
|
|
1436
|
+
);
|
|
1437
|
+
setSession(next);
|
|
1438
|
+
setPasteCode('');
|
|
1439
|
+
} catch (err) {
|
|
1440
|
+
setSubmitError(err instanceof Error ? err.message : String(err));
|
|
1441
|
+
} finally {
|
|
1442
|
+
setSubmitting(false);
|
|
1443
|
+
}
|
|
1444
|
+
}}
|
|
1445
|
+
style={{
|
|
1446
|
+
paddingHorizontal: 14,
|
|
1447
|
+
justifyContent: 'center',
|
|
1448
|
+
backgroundColor:
|
|
1449
|
+
!pasteCode.trim() || submitting
|
|
1450
|
+
? 'rgba(124,58,237,0.4)'
|
|
1451
|
+
: '#7c3aed',
|
|
1452
|
+
borderRadius: 10,
|
|
1453
|
+
}}
|
|
1454
|
+
>
|
|
1455
|
+
<Text style={{ color: 'white', fontWeight: '600' }}>
|
|
1456
|
+
{submitting ? '…' : 'Submit'}
|
|
1457
|
+
</Text>
|
|
1458
|
+
</Pressable>
|
|
1459
|
+
</View>
|
|
1460
|
+
{submitError ? (
|
|
1461
|
+
<Text
|
|
1462
|
+
style={{
|
|
1463
|
+
marginTop: 6,
|
|
1464
|
+
color: '#fca5a5',
|
|
1465
|
+
fontSize: 12,
|
|
1466
|
+
}}
|
|
1467
|
+
>
|
|
1468
|
+
{submitError}
|
|
1469
|
+
</Text>
|
|
1470
|
+
) : null}
|
|
1471
|
+
</View>
|
|
1472
|
+
) : null}
|
|
1383
1473
|
<Text style={runnerAuthModalStyles.phishingHint}>
|
|
1384
|
-
|
|
1385
|
-
|
|
1474
|
+
{needsPasteBack
|
|
1475
|
+
? 'After authorising on platform.claude.com, copy the code from the callback page and paste it above. Never share this code.'
|
|
1476
|
+
: 'Device codes are a common phishing target. Never share this code. This dialog turns green automatically once sign-in completes.'}
|
|
1386
1477
|
</Text>
|
|
1387
1478
|
</View>
|
|
1388
1479
|
)}
|
package/src/P2PClient.ts
CHANGED
|
@@ -199,6 +199,29 @@ export class P2PClient {
|
|
|
199
199
|
try { await fetch(url, { method: 'POST', headers: this.authHeaders() }); } catch { /* best-effort */ }
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
/** Submit the verifier code Anthropic shows on the callback page so
|
|
203
|
+
* the agent can finalise claude CLI's OAuth handshake. Codex doesn't
|
|
204
|
+
* use this — its device-auth flow auto-resolves via polling — but
|
|
205
|
+
* the SDK still exposes it for symmetry with mobile/src/components/
|
|
206
|
+
* RunnerAuthModal.tsx and the Swift YaverRunnerAuthFlowPane. */
|
|
207
|
+
async submitRunnerBrowserAuthCode(
|
|
208
|
+
sessionId: string,
|
|
209
|
+
code: string,
|
|
210
|
+
): Promise<RunnerBrowserAuthSession> {
|
|
211
|
+
const url = `${this.baseUrl}/runner-auth/browser/submit-code`;
|
|
212
|
+
const resp = await fetch(url, {
|
|
213
|
+
method: 'POST',
|
|
214
|
+
headers: { ...this.authHeaders(), 'Content-Type': 'application/json' },
|
|
215
|
+
body: JSON.stringify({ id: sessionId, code }),
|
|
216
|
+
});
|
|
217
|
+
if (!resp.ok) {
|
|
218
|
+
const text = await resp.text().catch(() => '');
|
|
219
|
+
throw new Error(`submitRunnerBrowserAuthCode HTTP ${resp.status}: ${text}`);
|
|
220
|
+
}
|
|
221
|
+
const data = await resp.json();
|
|
222
|
+
return data.session as RunnerBrowserAuthSession;
|
|
223
|
+
}
|
|
224
|
+
|
|
202
225
|
async capabilitySnapshot(): Promise<CapabilitySnapshot | null> {
|
|
203
226
|
try {
|
|
204
227
|
const resp = await fetch(`${this.baseUrl}/capabilities/snapshot`, { headers: this.authHeaders() });
|
package/src/YaverFeedback.ts
CHANGED
|
@@ -596,6 +596,19 @@ export class YaverFeedback {
|
|
|
596
596
|
await p2pClient.cancelRunnerBrowserAuth(sessionId);
|
|
597
597
|
}
|
|
598
598
|
|
|
599
|
+
/** Submit the Claude paste-back verifier so the agent can finalise the
|
|
600
|
+
* OAuth handshake. RunnerAuthModal calls this after the user copies
|
|
601
|
+
* the code from platform.claude.com's callback page. */
|
|
602
|
+
static async submitRunnerBrowserAuthCode(
|
|
603
|
+
sessionId: string,
|
|
604
|
+
code: string,
|
|
605
|
+
): Promise<import('./types').RunnerBrowserAuthSession> {
|
|
606
|
+
if (!p2pClient) {
|
|
607
|
+
throw new Error('Not connected to any agent.');
|
|
608
|
+
}
|
|
609
|
+
return p2pClient.submitRunnerBrowserAuthCode(sessionId, code);
|
|
610
|
+
}
|
|
611
|
+
|
|
599
612
|
/**
|
|
600
613
|
* Sign out: clear cached token + device, tear down the P2P client. The
|
|
601
614
|
* SDK stays enabled; the next feedback trigger will re-prompt for login.
|