yaver-feedback-react-native 0.9.2 → 0.9.3
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/README.md +102 -1
- package/dist/AuthOverlay.d.ts +1 -14
- package/dist/AuthOverlay.js +9 -62
- package/dist/Discovery.js +0 -6
- package/dist/DogfoodRuntime.d.ts +124 -0
- package/dist/DogfoodRuntime.js +273 -0
- package/dist/FeedbackModal.js +347 -61
- package/dist/LoginScreen.d.ts +1 -5
- package/dist/LoginScreen.js +2 -6
- package/dist/MachinePickerScreen.d.ts +1 -3
- package/dist/MachinePickerScreen.js +6 -18
- package/dist/P2PClient.d.ts +116 -3
- package/dist/P2PClient.js +273 -3
- package/dist/P2PDogfoodDriver.d.ts +12 -0
- package/dist/P2PDogfoodDriver.js +118 -0
- package/dist/PairDeviceModal.d.ts +2 -3
- package/dist/VibeChatScreen.d.ts +11 -1
- package/dist/VibeChatScreen.js +200 -41
- package/dist/YaverFeedback.d.ts +34 -0
- package/dist/YaverFeedback.js +124 -19
- package/dist/YaverModeBadge.d.ts +22 -0
- package/dist/YaverModeBadge.js +219 -0
- package/dist/__tests__/AuthDevices.test.js +1 -48
- package/dist/__tests__/DogfoodRuntime.test.d.ts +1 -0
- package/dist/__tests__/DogfoodRuntime.test.js +116 -0
- package/dist/__tests__/P2PDogfoodDriver.test.d.ts +1 -0
- package/dist/__tests__/P2PDogfoodDriver.test.js +64 -0
- package/dist/__tests__/ReportIdentity.test.d.ts +25 -1
- package/dist/__tests__/ReportIdentity.test.js +34 -22
- package/dist/__tests__/YaverFeedback.test.js +13 -3
- package/dist/__tests__/deviceDogfood.test.d.ts +1 -0
- package/dist/__tests__/deviceDogfood.test.js +86 -0
- package/dist/__tests__/dogfoodPolicy.test.d.ts +1 -0
- package/dist/__tests__/dogfoodPolicy.test.js +33 -0
- package/dist/_core/ansi.d.ts +117 -0
- package/dist/_core/ansi.js +468 -0
- package/dist/_core/ansi.test.d.ts +1 -0
- package/dist/_core/ansi.test.js +225 -0
- package/dist/_core/buildFeedbackPrompt.d.ts +4 -9
- package/dist/_core/buildFeedbackPrompt.js +18 -72
- package/dist/_core/constants.d.ts +19 -6
- package/dist/_core/constants.js +20 -7
- package/dist/_core/device.d.ts +9 -23
- package/dist/_core/device.js +13 -28
- package/dist/_core/endpoints.d.ts +0 -7
- package/dist/_core/endpoints.js +0 -7
- package/dist/_core/index.d.ts +4 -0
- package/dist/_core/index.js +4 -0
- package/dist/_core/remoteless.d.ts +44 -0
- package/dist/_core/remoteless.js +75 -0
- package/dist/_core/trace.d.ts +47 -0
- package/dist/_core/trace.js +38 -0
- package/dist/_core/trace.test.d.ts +1 -0
- package/dist/_core/trace.test.js +60 -0
- package/dist/auth.d.ts +3 -60
- package/dist/auth.js +6 -88
- package/dist/deviceDogfood.d.ts +53 -0
- package/dist/deviceDogfood.js +137 -0
- package/dist/dogfoodPolicy.d.ts +25 -0
- package/dist/dogfoodPolicy.js +24 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.js +24 -8
- package/dist/reloadActions.js +2 -2
- package/dist/types.d.ts +50 -7
- package/package.json +12 -3
- package/src/AuthOverlay.tsx +20 -106
- package/src/Discovery.ts +0 -6
- package/src/DogfoodRuntime.ts +373 -0
- package/src/FeedbackModal.tsx +445 -67
- package/src/LoginScreen.tsx +2 -22
- package/src/MachinePickerScreen.tsx +6 -21
- package/src/P2PClient.ts +347 -4
- package/src/P2PDogfoodDriver.ts +132 -0
- package/src/PairDeviceModal.tsx +2 -3
- package/src/VibeChatScreen.tsx +232 -42
- package/src/YaverFeedback.ts +133 -22
- package/src/YaverModeBadge.tsx +234 -0
- package/src/__tests__/AuthDevices.test.ts +1 -52
- package/src/__tests__/DogfoodRuntime.test.ts +135 -0
- package/src/__tests__/P2PDogfoodDriver.test.ts +80 -0
- package/src/__tests__/ReportIdentity.test.ts +36 -27
- package/src/__tests__/YaverFeedback.test.ts +15 -3
- package/src/__tests__/deviceDogfood.test.ts +77 -0
- package/src/__tests__/dogfoodPolicy.test.ts +34 -0
- package/src/_core/ansi.test.ts +250 -0
- package/src/_core/ansi.ts +475 -0
- package/src/_core/buildFeedbackPrompt.ts +18 -95
- package/src/_core/constants.ts +20 -6
- package/src/_core/device.ts +13 -30
- package/src/_core/endpoints.ts +0 -7
- package/src/_core/index.ts +4 -0
- package/src/_core/remoteless.ts +110 -0
- package/src/_core/trace.test.ts +58 -0
- package/src/_core/trace.ts +75 -0
- package/src/auth.ts +7 -156
- package/src/deviceDogfood.ts +171 -0
- package/src/dogfoodPolicy.ts +40 -0
- package/src/index.ts +40 -11
- package/src/reloadActions.ts +2 -2
- package/src/types.ts +45 -7
- package/dist/GuestOnboardingScreen.d.ts +0 -8
- package/dist/GuestOnboardingScreen.js +0 -282
- package/src/GuestOnboardingScreen.tsx +0 -307
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import nacl from 'tweetnacl';
|
|
2
|
+
import { Buffer } from 'buffer';
|
|
3
|
+
import { DEFAULT_CONVEX_SITE_URL } from './auth';
|
|
4
|
+
|
|
5
|
+
type SecureStoreLike = {
|
|
6
|
+
getItemAsync(key: string): Promise<string | null>;
|
|
7
|
+
setItemAsync(key: string, value: string): Promise<void>;
|
|
8
|
+
deleteItemAsync(key: string): Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type DeviceDogfoodState = 'unregistered' | 'pending' | 'active' | 'cancelled' | 'revoked' | 'superseded';
|
|
12
|
+
|
|
13
|
+
export interface DeviceDogfoodOptions {
|
|
14
|
+
/** Public identifier registered by the app owner in Yaver Settings. */
|
|
15
|
+
appId: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
backendUrl?: string;
|
|
18
|
+
/** Advanced bare-RN integration. Expo apps use SecureStore automatically. */
|
|
19
|
+
secureStore?: SecureStoreLike;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DeviceDogfoodSession {
|
|
23
|
+
active: true;
|
|
24
|
+
appId: string;
|
|
25
|
+
installationId: string;
|
|
26
|
+
token: string;
|
|
27
|
+
expiresAt: number;
|
|
28
|
+
scopes: string[];
|
|
29
|
+
projectSlug?: string;
|
|
30
|
+
targetDeviceId?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface StoredIdentity {
|
|
34
|
+
installationId: string;
|
|
35
|
+
registrationSlot: string;
|
|
36
|
+
publicKey: string;
|
|
37
|
+
secretKey: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function b64(bytes: Uint8Array): string { return Buffer.from(bytes).toString('base64'); }
|
|
41
|
+
function fromB64(value: string): Uint8Array { return new Uint8Array(Buffer.from(value, 'base64')); }
|
|
42
|
+
function b64url(bytes: Uint8Array): string {
|
|
43
|
+
return Buffer.from(bytes).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function randomBytes(length: number): Uint8Array {
|
|
47
|
+
const cryptoObject = (globalThis as any)?.crypto;
|
|
48
|
+
if (cryptoObject?.getRandomValues) {
|
|
49
|
+
const out = new Uint8Array(length);
|
|
50
|
+
cryptoObject.getRandomValues(out);
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
return require('expo-crypto').getRandomBytes(length);
|
|
55
|
+
} catch {
|
|
56
|
+
throw new Error('Secure randomness is unavailable. Install expo-crypto or provide global crypto.getRandomValues.');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function defaultSecureStore(): SecureStoreLike {
|
|
61
|
+
try {
|
|
62
|
+
const store = require('expo-secure-store');
|
|
63
|
+
if (store?.getItemAsync && store?.setItemAsync) return store;
|
|
64
|
+
} catch { /* named error below */ }
|
|
65
|
+
throw new Error('Secure Dogfood identity storage is unavailable. Install expo-secure-store or pass secureStore.');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function responseJSON(response: Response): Promise<any> {
|
|
69
|
+
const body = await response.json().catch(() => ({}));
|
|
70
|
+
if (!response.ok) throw new Error(body?.error || `Yaver Dogfood request failed (HTTP ${response.status})`);
|
|
71
|
+
return body;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function enrollmentMessage(appId: string, installationId: string, challenge: string): Uint8Array {
|
|
75
|
+
return new TextEncoder().encode(`yaver-dogfood-enroll-v1\n${appId}\n${installationId}\n${challenge}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function sessionMessage(appId: string, installationId: string, challenge: string): Uint8Array {
|
|
79
|
+
return new TextEncoder().encode(`yaver-dogfood-session-v1\n${appId}\n${installationId}\n${challenge}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Account-free third-party Dogfood enrollment. The UUID is a public lookup
|
|
83
|
+
* handle; possession is proven by the private key retained in this app. */
|
|
84
|
+
export class YaverDeviceDogfood {
|
|
85
|
+
private readonly backendUrl: string;
|
|
86
|
+
private readonly store: SecureStoreLike;
|
|
87
|
+
private readonly storageKey: string;
|
|
88
|
+
|
|
89
|
+
constructor(private readonly options: DeviceDogfoodOptions) {
|
|
90
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{2,127}$/.test(options.appId)) throw new Error('A valid Dogfood appId is required');
|
|
91
|
+
this.backendUrl = (options.backendUrl || DEFAULT_CONVEX_SITE_URL).replace(/\/$/, '');
|
|
92
|
+
this.store = options.secureStore || defaultSecureStore();
|
|
93
|
+
this.storageKey = `yaver_feedback_dogfood_v1_${options.appId}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private async identity(): Promise<StoredIdentity> {
|
|
97
|
+
const raw = await this.store.getItemAsync(this.storageKey);
|
|
98
|
+
if (raw) {
|
|
99
|
+
try {
|
|
100
|
+
const saved = JSON.parse(raw) as StoredIdentity;
|
|
101
|
+
if (fromB64(saved.publicKey).length === nacl.sign.publicKeyLength && fromB64(saved.secretKey).length === nacl.sign.secretKeyLength) return saved;
|
|
102
|
+
} catch { /* rotate corrupt identity below */ }
|
|
103
|
+
}
|
|
104
|
+
const seed = randomBytes(32);
|
|
105
|
+
const pair = nacl.sign.keyPair.fromSeed(seed);
|
|
106
|
+
seed.fill(0);
|
|
107
|
+
const identity: StoredIdentity = {
|
|
108
|
+
installationId: b64url(randomBytes(18)), registrationSlot: b64url(randomBytes(18)),
|
|
109
|
+
publicKey: b64(pair.publicKey), secretKey: b64(pair.secretKey),
|
|
110
|
+
};
|
|
111
|
+
await this.store.setItemAsync(this.storageKey, JSON.stringify(identity));
|
|
112
|
+
return identity;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async enrollmentInfo(): Promise<{ appId: string; installationId: string; registrationSlot: string; publicKey: string }> {
|
|
116
|
+
const identity = await this.identity();
|
|
117
|
+
return { appId: this.options.appId, installationId: identity.installationId, registrationSlot: identity.registrationSlot, publicKey: identity.publicKey };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async enroll(platform = 'unknown'): Promise<{ status: DeviceDogfoodState; installationId: string }> {
|
|
121
|
+
const identity = await this.identity();
|
|
122
|
+
const started = await responseJSON(await fetch(`${this.backendUrl}/dogfood/enroll/start`, {
|
|
123
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
124
|
+
body: JSON.stringify({ appId: this.options.appId, installationId: identity.installationId, registrationSlot: identity.registrationSlot, publicKey: identity.publicKey, platform, label: this.options.label }),
|
|
125
|
+
}));
|
|
126
|
+
if (started.status === 'active') return { status: 'active', installationId: identity.installationId };
|
|
127
|
+
const signature = b64(nacl.sign.detached(enrollmentMessage(this.options.appId, identity.installationId, started.challenge), fromB64(identity.secretKey)));
|
|
128
|
+
await responseJSON(await fetch(`${this.backendUrl}/dogfood/enroll/prove`, {
|
|
129
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
130
|
+
body: JSON.stringify({ appId: this.options.appId, installationId: identity.installationId, signature }),
|
|
131
|
+
}));
|
|
132
|
+
return { status: 'pending', installationId: identity.installationId };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async status(): Promise<DeviceDogfoodState> {
|
|
136
|
+
const identity = await this.identity();
|
|
137
|
+
const response = await fetch(`${this.backendUrl}/dogfood/enroll/status?appId=${encodeURIComponent(this.options.appId)}&installationId=${encodeURIComponent(identity.installationId)}`);
|
|
138
|
+
if (response.status === 404) return 'unregistered';
|
|
139
|
+
return (await responseJSON(response)).status as DeviceDogfoodState;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async session(): Promise<DeviceDogfoodSession | null> {
|
|
143
|
+
const identity = await this.identity();
|
|
144
|
+
if (await this.status() !== 'active') return null;
|
|
145
|
+
const challenge = await responseJSON(await fetch(`${this.backendUrl}/dogfood/session/challenge`, {
|
|
146
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
147
|
+
body: JSON.stringify({ appId: this.options.appId, installationId: identity.installationId }),
|
|
148
|
+
}));
|
|
149
|
+
const signature = b64(nacl.sign.detached(sessionMessage(this.options.appId, identity.installationId, challenge.challenge), fromB64(identity.secretKey)));
|
|
150
|
+
const result = await responseJSON(await fetch(`${this.backendUrl}/dogfood/session`, {
|
|
151
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
152
|
+
body: JSON.stringify({ appId: this.options.appId, installationId: identity.installationId, signature }),
|
|
153
|
+
}));
|
|
154
|
+
return { active: true, appId: this.options.appId, installationId: identity.installationId, token: result.token, expiresAt: result.expiresAt, scopes: result.scopes || [], projectSlug: result.projectSlug, targetDeviceId: result.targetDeviceId };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Rotate the key but keep the logical slot. Approval supersedes the prior
|
|
158
|
+
* generation, making its already-issued sessions fail immediately. */
|
|
159
|
+
async reRegister(platform = 'unknown'): Promise<{ status: DeviceDogfoodState; installationId: string }> {
|
|
160
|
+
const previous = await this.identity();
|
|
161
|
+
const seed = randomBytes(32);
|
|
162
|
+
const pair = nacl.sign.keyPair.fromSeed(seed);
|
|
163
|
+
seed.fill(0);
|
|
164
|
+
const next: StoredIdentity = {
|
|
165
|
+
installationId: b64url(randomBytes(18)), registrationSlot: previous.registrationSlot,
|
|
166
|
+
publicKey: b64(pair.publicKey), secretKey: b64(pair.secretKey),
|
|
167
|
+
};
|
|
168
|
+
await this.store.setItemAsync(this.storageKey, JSON.stringify(next));
|
|
169
|
+
return this.enroll(platform);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface SDKDogfoodConfig {
|
|
2
|
+
/** Explicit opt-in. Omitted/false keeps the normal Feedback SDK. */
|
|
3
|
+
enabled?: boolean;
|
|
4
|
+
/** App-account IDs allowed to enter Dogfood. Public identifiers, not secrets. */
|
|
5
|
+
accountIds?: string[];
|
|
6
|
+
/** The third-party app's currently authenticated account ID. */
|
|
7
|
+
currentAccountId?: string;
|
|
8
|
+
/** Account-free installation identity resolved by YaverDeviceDogfood. */
|
|
9
|
+
appId?: string;
|
|
10
|
+
installationId?: string;
|
|
11
|
+
installationStatus?: 'pending' | 'active' | 'cancelled' | 'revoked' | 'superseded';
|
|
12
|
+
/** Called after the user confirms Exit Dogfood mode. */
|
|
13
|
+
onExit?: () => void | Promise<void>;
|
|
14
|
+
/** Optional app label shown beside Dogfood mode. */
|
|
15
|
+
label?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SDKDogfoodStatus {
|
|
19
|
+
active: boolean;
|
|
20
|
+
code: 'SDK_DOGFOOD_ACTIVE' | 'SDK_DOGFOOD_DISABLED' | 'SDK_DOGFOOD_ACCOUNT_REQUIRED' | 'SDK_DOGFOOD_ACCOUNT_NOT_ALLOWED' | 'SDK_DOGFOOD_INSTALLATION_REQUIRED' | 'SDK_DOGFOOD_INSTALLATION_NOT_ACTIVE';
|
|
21
|
+
accountId?: string;
|
|
22
|
+
label: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Pure, fail-closed account gate shared by init, the Y badge and tests.
|
|
26
|
+
* This controls SDK UX only; every task/reload still requires Yaver auth. */
|
|
27
|
+
export function resolveSDKDogfood(config?: SDKDogfoodConfig | null): SDKDogfoodStatus {
|
|
28
|
+
const label = String(config?.label || 'Dogfood').trim() || 'Dogfood';
|
|
29
|
+
if (config?.enabled !== true) return { active: false, code: 'SDK_DOGFOOD_DISABLED', label };
|
|
30
|
+
if (config.appId) {
|
|
31
|
+
if (!config.installationId) return { active: false, code: 'SDK_DOGFOOD_INSTALLATION_REQUIRED', label };
|
|
32
|
+
if (config.installationStatus !== 'active') return { active: false, code: 'SDK_DOGFOOD_INSTALLATION_NOT_ACTIVE', label };
|
|
33
|
+
return { active: true, code: 'SDK_DOGFOOD_ACTIVE', accountId: config.installationId, label };
|
|
34
|
+
}
|
|
35
|
+
const accountId = String(config.currentAccountId || '').trim();
|
|
36
|
+
if (!accountId) return { active: false, code: 'SDK_DOGFOOD_ACCOUNT_REQUIRED', label };
|
|
37
|
+
const allowed = new Set((config.accountIds || []).map((id) => String(id).trim()).filter(Boolean));
|
|
38
|
+
if (!allowed.has(accountId)) return { active: false, code: 'SDK_DOGFOOD_ACCOUNT_NOT_ALLOWED', accountId, label };
|
|
39
|
+
return { active: true, code: 'SDK_DOGFOOD_ACTIVE', accountId, label };
|
|
40
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
31
|
export { YaverFeedback } from './YaverFeedback';
|
|
32
|
+
export type { DogfoodOnboardingOptions } from './YaverFeedback';
|
|
32
33
|
export { captureStoreScreenshots } from './storeShots';
|
|
33
34
|
export type {
|
|
34
35
|
CaptureStoreScreenshotsOptions,
|
|
@@ -41,6 +42,14 @@ export type { YaverUpdatesConfig, PendingUpdate } from './YaverUpdates';
|
|
|
41
42
|
export { initExpo } from './expo';
|
|
42
43
|
export { YaverDiscovery } from './Discovery';
|
|
43
44
|
export { P2PClient } from './P2PClient';
|
|
45
|
+
export type {
|
|
46
|
+
DogfoodDevEvent,
|
|
47
|
+
DogfoodDevServerStatus,
|
|
48
|
+
DogfoodRemoteRuntimeCapabilities,
|
|
49
|
+
DogfoodRemoteRuntimeSession,
|
|
50
|
+
DogfoodRemoteRuntimeTarget,
|
|
51
|
+
} from './P2PClient';
|
|
52
|
+
export { createP2PDogfoodDriver, type P2PDogfoodDriverOptions } from './P2PDogfoodDriver';
|
|
44
53
|
export {
|
|
45
54
|
reloadActions,
|
|
46
55
|
reloadRequest,
|
|
@@ -61,13 +70,42 @@ export { YaverLoginScreen } from './LoginScreen';
|
|
|
61
70
|
export type { YaverLoginScreenProps } from './LoginScreen';
|
|
62
71
|
export { YaverMachinePickerScreen } from './MachinePickerScreen';
|
|
63
72
|
export type { YaverMachinePickerProps } from './MachinePickerScreen';
|
|
64
|
-
export { YaverGuestOnboardingScreen } from './GuestOnboardingScreen';
|
|
65
|
-
export type { YaverGuestOnboardingScreenProps } from './GuestOnboardingScreen';
|
|
66
73
|
export { PairDeviceModal } from './PairDeviceModal';
|
|
67
74
|
export type { PairDeviceModalProps } from './PairDeviceModal';
|
|
68
75
|
export { AuthOverlay } from './AuthOverlay';
|
|
69
76
|
export { ShakeDetector } from './ShakeDetector';
|
|
70
77
|
export { FloatingButton } from './FloatingButton';
|
|
78
|
+
// The polite "you're inside Yaver" mark. Rendered automatically by the SDK's
|
|
79
|
+
// overlay host when config.modeBadge !== false; exported so an app that manages
|
|
80
|
+
// its own overlay tree can place it itself.
|
|
81
|
+
export { YaverModeBadge, hideYaverModeBadge, showYaverModeBadge, isYaverModeBadgeHidden } from './YaverModeBadge';
|
|
82
|
+
export type { YaverModeBadgeProps } from './YaverModeBadge';
|
|
83
|
+
export { resolveSDKDogfood } from './dogfoodPolicy';
|
|
84
|
+
export type { SDKDogfoodConfig, SDKDogfoodStatus } from './dogfoodPolicy';
|
|
85
|
+
export { YaverDeviceDogfood } from './deviceDogfood';
|
|
86
|
+
export type { DeviceDogfoodOptions, DeviceDogfoodSession, DeviceDogfoodState } from './deviceDogfood';
|
|
87
|
+
export {
|
|
88
|
+
DogfoodController,
|
|
89
|
+
DogfoodRuntimeError,
|
|
90
|
+
defaultDogfoodLane,
|
|
91
|
+
dogfoodLaneOptions,
|
|
92
|
+
dogfoodLogLinesFromDevEvent,
|
|
93
|
+
runtimeLogLinesFromDevEvent,
|
|
94
|
+
validateDogfoodProject,
|
|
95
|
+
} from './DogfoodRuntime';
|
|
96
|
+
export type {
|
|
97
|
+
DogfoodControllerOptions,
|
|
98
|
+
DogfoodDriver,
|
|
99
|
+
DogfoodFailure,
|
|
100
|
+
DogfoodLane,
|
|
101
|
+
DogfoodLaneOption,
|
|
102
|
+
DogfoodLogLine,
|
|
103
|
+
DogfoodPhase,
|
|
104
|
+
DogfoodProject,
|
|
105
|
+
DogfoodResult,
|
|
106
|
+
DogfoodRunContext,
|
|
107
|
+
DogfoodSnapshot,
|
|
108
|
+
} from './DogfoodRuntime';
|
|
71
109
|
export { FeedbackModal } from './FeedbackModal';
|
|
72
110
|
export { QuickActionIcon } from './QuickActionIcon';
|
|
73
111
|
export type { QuickActionIconProps } from './QuickActionIcon';
|
|
@@ -95,10 +133,6 @@ export {
|
|
|
95
133
|
signupWithEmail,
|
|
96
134
|
loginWithEmail,
|
|
97
135
|
listReachableDevices,
|
|
98
|
-
fetchGuestHosts,
|
|
99
|
-
findInviteByCode,
|
|
100
|
-
acceptGuestByCode,
|
|
101
|
-
acceptGuestInvitation,
|
|
102
136
|
DEFAULT_CONVEX_SITE_URL,
|
|
103
137
|
DEFAULT_WEB_BASE_URL,
|
|
104
138
|
DEFAULT_OAUTH_REDIRECT,
|
|
@@ -108,11 +142,6 @@ export type {
|
|
|
108
142
|
User,
|
|
109
143
|
RemoteDevice,
|
|
110
144
|
DeviceList,
|
|
111
|
-
GuestInvitation,
|
|
112
|
-
ActiveGuestHost,
|
|
113
|
-
GuestHostsResponse,
|
|
114
|
-
InvitationHostDevice,
|
|
115
|
-
InvitationPreview,
|
|
116
145
|
} from './auth';
|
|
117
146
|
export {
|
|
118
147
|
captureScreenshot,
|
package/src/reloadActions.ts
CHANGED
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
// ── Auth ─────────────────────────────────────────────────────────────────────
|
|
34
34
|
//
|
|
35
35
|
// None of this needs a new secret. `/dev/reload` and `/dev/reload-app` are
|
|
36
|
-
// registered under `
|
|
36
|
+
// registered under `authSDK` (desktop/agent/httpserver.go), the same
|
|
37
37
|
// middleware that already admits the bearer this SDK sends with its feedback
|
|
38
|
-
// POST. A scope-limited SDK token needs the existing `
|
|
38
|
+
// POST. A scope-limited SDK token needs the existing `reload` scope,
|
|
39
39
|
// whose path list already contains both routes — no widening, no new gate.
|
|
40
40
|
|
|
41
41
|
/** Stable identifier for each action the overlay can render. */
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Type-only: BlackBox.ts already imports from this module, so a value import
|
|
2
2
|
// would close a cycle. `import type` is erased at compile time.
|
|
3
3
|
import type { BlackBoxConfig } from './BlackBox';
|
|
4
|
+
import type { SDKDogfoodConfig } from './dogfoodPolicy';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Remote browser-style sign-in session for a coding-agent CLI on the
|
|
@@ -36,6 +37,8 @@ export interface RunnerAuthStatusRow {
|
|
|
36
37
|
path?: string;
|
|
37
38
|
detail?: string;
|
|
38
39
|
version?: string;
|
|
40
|
+
isDefault?: boolean;
|
|
41
|
+
models?: Array<{ id: string; name?: string; provider?: string; isDefault?: boolean }>;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
export interface OpenCodeProviderSummary {
|
|
@@ -146,6 +149,40 @@ export interface StoreShotsConfig {
|
|
|
146
149
|
export interface FeedbackConfig {
|
|
147
150
|
/** URL of the Yaver agent (e.g. "http://192.168.1.10:18080"). If omitted, auto-discovery is used. */
|
|
148
151
|
agentUrl?: string;
|
|
152
|
+
/** Optional coding route. Defaults to agentUrl. */
|
|
153
|
+
codingAgentUrl?: string;
|
|
154
|
+
/** Optional render/reload route. Defaults to codingAgentUrl/agentUrl. */
|
|
155
|
+
renderAgentUrl?: string;
|
|
156
|
+
/** Device identities shown in the unified Settings card when routes differ. */
|
|
157
|
+
codingDeviceId?: string;
|
|
158
|
+
renderDeviceId?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Show the small "Y" mark while this app is running INSIDE Yaver's container
|
|
161
|
+
* (a Hermes-pushed development bundle), so a tester can tell it apart from
|
|
162
|
+
* the build they installed — and can find the way back.
|
|
163
|
+
*
|
|
164
|
+
* DEFAULT TRUE. The failure it prevents is silent and lands on a tester
|
|
165
|
+
* rather than a developer: an app that looks installed but is someone's
|
|
166
|
+
* branch produces "bug reports" against unfinished work, and a tester with
|
|
167
|
+
* no visible way out is simply stuck. That class should not be opt-in.
|
|
168
|
+
*
|
|
169
|
+
* Costs nothing in a standalone build — outside Yaver's container the badge
|
|
170
|
+
* renders null (the YaverInfo native module is absent), so shipping with it
|
|
171
|
+
* enabled has no effect on what your users see.
|
|
172
|
+
*
|
|
173
|
+
* Set false if your app already shows its own in-container indicator, or if
|
|
174
|
+
* a pixel-exact surface cannot spare 22 points in a corner.
|
|
175
|
+
*/
|
|
176
|
+
modeBadge?: boolean;
|
|
177
|
+
/** Corner for the mode badge. Default 'bottom-left' — bottom-right is where
|
|
178
|
+
* most apps put a FAB, and the badge must never compete with the app's own
|
|
179
|
+
* primary action. */
|
|
180
|
+
modeBadgePosition?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
|
|
181
|
+
/** Account-scoped direct Dogfood UX for an approved third-party app.
|
|
182
|
+
* When the current app account is allowlisted, the small Y opens Vibing
|
|
183
|
+
* directly instead of the normal feedback actions. This is a client UX gate,
|
|
184
|
+
* never an authentication mechanism; agent calls still require Yaver auth. */
|
|
185
|
+
dogfood?: SDKDogfoodConfig;
|
|
149
186
|
/**
|
|
150
187
|
* Enables the overlay's "App Store screenshots" action + the
|
|
151
188
|
* `capture_store_shots` remote command. The host supplies the route
|
|
@@ -225,6 +262,14 @@ export interface FeedbackConfig {
|
|
|
225
262
|
voiceCapabilities?: string[];
|
|
226
263
|
sttProvider?: string;
|
|
227
264
|
ttsProvider?: string;
|
|
265
|
+
/**
|
|
266
|
+
* Opt in to the microphone/STT controls in the feedback Vibing card.
|
|
267
|
+
*
|
|
268
|
+
* This is deliberately false unless explicitly enabled: ordinary phone
|
|
269
|
+
* and tablet surfaces stay keyboard-first. Car/watch-style hosts that are
|
|
270
|
+
* inherently voice-driven may set this to true.
|
|
271
|
+
*/
|
|
272
|
+
voiceInputEnabled?: boolean;
|
|
228
273
|
/** How feedback collection is triggered */
|
|
229
274
|
trigger?: 'shake' | 'floating-button' | 'manual';
|
|
230
275
|
/**
|
|
@@ -465,13 +510,6 @@ export interface FeedbackConfig {
|
|
|
465
510
|
* Default: false (preserve historical behavior).
|
|
466
511
|
*/
|
|
467
512
|
strictNativeAuth?: boolean;
|
|
468
|
-
/**
|
|
469
|
-
* Optional host invite code to prefill into the in-SDK guest onboarding
|
|
470
|
-
* flow. Useful when your app receives the code from a deep link, QR flow,
|
|
471
|
-
* or an out-of-band host handoff and you want the user to redeem it
|
|
472
|
-
* without typing.
|
|
473
|
-
*/
|
|
474
|
-
guestInviteCode?: string;
|
|
475
513
|
}
|
|
476
514
|
|
|
477
515
|
export interface FeedbackBundle {
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export interface YaverGuestOnboardingScreenProps {
|
|
3
|
-
token: string;
|
|
4
|
-
initialInviteCode?: string;
|
|
5
|
-
onContinue: () => void;
|
|
6
|
-
onCancel?: () => void;
|
|
7
|
-
}
|
|
8
|
-
export declare const YaverGuestOnboardingScreen: React.FC<YaverGuestOnboardingScreenProps>;
|