yaver-feedback-react-native 0.5.3 → 0.5.4
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 +8 -0
- package/dist/AuthOverlay.d.ts +16 -0
- package/dist/AuthOverlay.js +104 -0
- package/dist/BlackBox.d.ts +154 -0
- package/dist/BlackBox.js +395 -0
- package/dist/ConnectionScreen.d.ts +13 -0
- package/dist/ConnectionScreen.js +373 -0
- package/dist/Discovery.d.ts +59 -0
- package/dist/Discovery.js +293 -0
- package/dist/FeedbackModal.d.ts +11 -0
- package/dist/FeedbackModal.js +623 -0
- package/dist/FixReport.d.ts +23 -0
- package/dist/FixReport.js +282 -0
- package/dist/FloatingButton.d.ts +71 -0
- package/dist/FloatingButton.js +778 -0
- package/dist/LoginScreen.d.ts +14 -0
- package/dist/LoginScreen.js +317 -0
- package/dist/MachinePickerScreen.d.ts +19 -0
- package/dist/MachinePickerScreen.js +175 -0
- package/dist/P2PClient.d.ts +136 -0
- package/dist/P2PClient.js +357 -0
- package/dist/ShakeDetector.d.ts +39 -0
- package/dist/ShakeDetector.js +111 -0
- package/dist/YaverFeedback.d.ts +198 -0
- package/dist/YaverFeedback.js +679 -0
- package/dist/YaverUpdates.d.ts +78 -0
- package/dist/YaverUpdates.js +272 -0
- package/dist/__tests__/Discovery.test.d.ts +1 -0
- package/dist/__tests__/Discovery.test.js +164 -0
- package/dist/__tests__/P2PClient.test.d.ts +1 -0
- package/dist/__tests__/P2PClient.test.js +169 -0
- package/dist/__tests__/SDKToken.test.d.ts +1 -0
- package/dist/__tests__/SDKToken.test.js +215 -0
- package/dist/__tests__/YaverFeedback.test.d.ts +1 -0
- package/dist/__tests__/YaverFeedback.test.js +161 -0
- package/dist/__tests__/types.test.d.ts +1 -0
- package/dist/__tests__/types.test.js +219 -0
- package/dist/auth.d.ts +105 -0
- package/dist/auth.js +282 -0
- package/dist/capture.d.ts +27 -0
- package/dist/capture.js +74 -0
- package/dist/expo.d.ts +15 -0
- package/dist/expo.js +62 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +80 -0
- package/dist/types.d.ts +282 -0
- package/dist/types.js +2 -0
- package/dist/upload.d.ts +13 -0
- package/dist/upload.js +59 -0
- package/package.json +6 -3
package/dist/index.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @yaver/feedback-react-native — Visual feedback SDK for Yaver.
|
|
4
|
+
*
|
|
5
|
+
* Shake-to-report, screenshots, voice annotations, P2P connection,
|
|
6
|
+
* device discovery, and live/narrated/batch feedback modes for vibe coding.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* import { YaverFeedback, FeedbackProvider } from '@yaver/feedback-react-native';
|
|
11
|
+
*
|
|
12
|
+
* YaverFeedback.init({
|
|
13
|
+
* agentUrl: 'http://192.168.1.10:18080',
|
|
14
|
+
* authToken: 'your-token',
|
|
15
|
+
* trigger: 'shake',
|
|
16
|
+
* feedbackMode: 'live',
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Wrap your app root:
|
|
20
|
+
* <FeedbackProvider>
|
|
21
|
+
* <App />
|
|
22
|
+
* </FeedbackProvider>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.uploadFeedback = exports.stopAudioRecording = exports.startAudioRecording = exports.captureScreenshot = exports.DEFAULT_WEB_BASE_URL = exports.DEFAULT_CONVEX_SITE_URL = exports.listReachableDevices = exports.loginWithEmail = exports.signupWithEmail = exports.pollDeviceCode = exports.startDeviceCode = exports.validateToken = exports.clearSelectedDeviceId = exports.saveSelectedDeviceId = exports.getSelectedDeviceId = exports.saveUser = exports.getUser = exports.clearToken = exports.saveToken = exports.getToken = exports.getWebBaseUrl = exports.getConvexSiteUrl = exports.configureAuthEndpoints = exports.FixReport = exports.FeedbackModal = exports.FloatingButton = exports.ShakeDetector = exports.AuthOverlay = exports.YaverMachinePickerScreen = exports.YaverLoginScreen = exports.YaverConnectionScreen = exports.P2PClient = exports.YaverDiscovery = exports.initExpo = exports.YaverUpdates = exports.BlackBox = exports.YaverFeedback = void 0;
|
|
27
|
+
var YaverFeedback_1 = require("./YaverFeedback");
|
|
28
|
+
Object.defineProperty(exports, "YaverFeedback", { enumerable: true, get: function () { return YaverFeedback_1.YaverFeedback; } });
|
|
29
|
+
var BlackBox_1 = require("./BlackBox");
|
|
30
|
+
Object.defineProperty(exports, "BlackBox", { enumerable: true, get: function () { return BlackBox_1.BlackBox; } });
|
|
31
|
+
var YaverUpdates_1 = require("./YaverUpdates");
|
|
32
|
+
Object.defineProperty(exports, "YaverUpdates", { enumerable: true, get: function () { return YaverUpdates_1.YaverUpdates; } });
|
|
33
|
+
var expo_1 = require("./expo");
|
|
34
|
+
Object.defineProperty(exports, "initExpo", { enumerable: true, get: function () { return expo_1.initExpo; } });
|
|
35
|
+
var Discovery_1 = require("./Discovery");
|
|
36
|
+
Object.defineProperty(exports, "YaverDiscovery", { enumerable: true, get: function () { return Discovery_1.YaverDiscovery; } });
|
|
37
|
+
var P2PClient_1 = require("./P2PClient");
|
|
38
|
+
Object.defineProperty(exports, "P2PClient", { enumerable: true, get: function () { return P2PClient_1.P2PClient; } });
|
|
39
|
+
var ConnectionScreen_1 = require("./ConnectionScreen");
|
|
40
|
+
Object.defineProperty(exports, "YaverConnectionScreen", { enumerable: true, get: function () { return ConnectionScreen_1.YaverConnectionScreen; } });
|
|
41
|
+
var LoginScreen_1 = require("./LoginScreen");
|
|
42
|
+
Object.defineProperty(exports, "YaverLoginScreen", { enumerable: true, get: function () { return LoginScreen_1.YaverLoginScreen; } });
|
|
43
|
+
var MachinePickerScreen_1 = require("./MachinePickerScreen");
|
|
44
|
+
Object.defineProperty(exports, "YaverMachinePickerScreen", { enumerable: true, get: function () { return MachinePickerScreen_1.YaverMachinePickerScreen; } });
|
|
45
|
+
var AuthOverlay_1 = require("./AuthOverlay");
|
|
46
|
+
Object.defineProperty(exports, "AuthOverlay", { enumerable: true, get: function () { return AuthOverlay_1.AuthOverlay; } });
|
|
47
|
+
var ShakeDetector_1 = require("./ShakeDetector");
|
|
48
|
+
Object.defineProperty(exports, "ShakeDetector", { enumerable: true, get: function () { return ShakeDetector_1.ShakeDetector; } });
|
|
49
|
+
var FloatingButton_1 = require("./FloatingButton");
|
|
50
|
+
Object.defineProperty(exports, "FloatingButton", { enumerable: true, get: function () { return FloatingButton_1.FloatingButton; } });
|
|
51
|
+
var FeedbackModal_1 = require("./FeedbackModal");
|
|
52
|
+
Object.defineProperty(exports, "FeedbackModal", { enumerable: true, get: function () { return FeedbackModal_1.FeedbackModal; } });
|
|
53
|
+
var FixReport_1 = require("./FixReport");
|
|
54
|
+
Object.defineProperty(exports, "FixReport", { enumerable: true, get: function () { return FixReport_1.FixReport; } });
|
|
55
|
+
var auth_1 = require("./auth");
|
|
56
|
+
Object.defineProperty(exports, "configureAuthEndpoints", { enumerable: true, get: function () { return auth_1.configureAuthEndpoints; } });
|
|
57
|
+
Object.defineProperty(exports, "getConvexSiteUrl", { enumerable: true, get: function () { return auth_1.getConvexSiteUrl; } });
|
|
58
|
+
Object.defineProperty(exports, "getWebBaseUrl", { enumerable: true, get: function () { return auth_1.getWebBaseUrl; } });
|
|
59
|
+
Object.defineProperty(exports, "getToken", { enumerable: true, get: function () { return auth_1.getToken; } });
|
|
60
|
+
Object.defineProperty(exports, "saveToken", { enumerable: true, get: function () { return auth_1.saveToken; } });
|
|
61
|
+
Object.defineProperty(exports, "clearToken", { enumerable: true, get: function () { return auth_1.clearToken; } });
|
|
62
|
+
Object.defineProperty(exports, "getUser", { enumerable: true, get: function () { return auth_1.getUser; } });
|
|
63
|
+
Object.defineProperty(exports, "saveUser", { enumerable: true, get: function () { return auth_1.saveUser; } });
|
|
64
|
+
Object.defineProperty(exports, "getSelectedDeviceId", { enumerable: true, get: function () { return auth_1.getSelectedDeviceId; } });
|
|
65
|
+
Object.defineProperty(exports, "saveSelectedDeviceId", { enumerable: true, get: function () { return auth_1.saveSelectedDeviceId; } });
|
|
66
|
+
Object.defineProperty(exports, "clearSelectedDeviceId", { enumerable: true, get: function () { return auth_1.clearSelectedDeviceId; } });
|
|
67
|
+
Object.defineProperty(exports, "validateToken", { enumerable: true, get: function () { return auth_1.validateToken; } });
|
|
68
|
+
Object.defineProperty(exports, "startDeviceCode", { enumerable: true, get: function () { return auth_1.startDeviceCode; } });
|
|
69
|
+
Object.defineProperty(exports, "pollDeviceCode", { enumerable: true, get: function () { return auth_1.pollDeviceCode; } });
|
|
70
|
+
Object.defineProperty(exports, "signupWithEmail", { enumerable: true, get: function () { return auth_1.signupWithEmail; } });
|
|
71
|
+
Object.defineProperty(exports, "loginWithEmail", { enumerable: true, get: function () { return auth_1.loginWithEmail; } });
|
|
72
|
+
Object.defineProperty(exports, "listReachableDevices", { enumerable: true, get: function () { return auth_1.listReachableDevices; } });
|
|
73
|
+
Object.defineProperty(exports, "DEFAULT_CONVEX_SITE_URL", { enumerable: true, get: function () { return auth_1.DEFAULT_CONVEX_SITE_URL; } });
|
|
74
|
+
Object.defineProperty(exports, "DEFAULT_WEB_BASE_URL", { enumerable: true, get: function () { return auth_1.DEFAULT_WEB_BASE_URL; } });
|
|
75
|
+
var capture_1 = require("./capture");
|
|
76
|
+
Object.defineProperty(exports, "captureScreenshot", { enumerable: true, get: function () { return capture_1.captureScreenshot; } });
|
|
77
|
+
Object.defineProperty(exports, "startAudioRecording", { enumerable: true, get: function () { return capture_1.startAudioRecording; } });
|
|
78
|
+
Object.defineProperty(exports, "stopAudioRecording", { enumerable: true, get: function () { return capture_1.stopAudioRecording; } });
|
|
79
|
+
var upload_1 = require("./upload");
|
|
80
|
+
Object.defineProperty(exports, "uploadFeedback", { enumerable: true, get: function () { return upload_1.uploadFeedback; } });
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
export interface FeedbackConfig {
|
|
2
|
+
/** URL of the Yaver agent (e.g. "http://192.168.1.10:18080"). If omitted, auto-discovery is used. */
|
|
3
|
+
agentUrl?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Auth token for the Yaver agent. Optional in 0.5+: if omitted, the SDK
|
|
6
|
+
* will hydrate one from AsyncStorage or show its in-app login screen
|
|
7
|
+
* (device-code / email / OAuth) the first time the user triggers feedback.
|
|
8
|
+
*/
|
|
9
|
+
authToken?: string;
|
|
10
|
+
/**
|
|
11
|
+
* When true (default), the SDK will automatically prompt the user to sign
|
|
12
|
+
* in and pick a remote machine the first time they trigger feedback and
|
|
13
|
+
* no `authToken` / `preferredDeviceId` is cached. Set false to opt back
|
|
14
|
+
* into the pre-0.5 behavior where you manage auth yourself and pass
|
|
15
|
+
* `authToken` at init.
|
|
16
|
+
*/
|
|
17
|
+
autoLogin?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Override the public Yaver endpoints the in-app login screen talks to.
|
|
20
|
+
* Useful when running against staging. Defaults to the production
|
|
21
|
+
* yaver.io / Convex site URLs.
|
|
22
|
+
*/
|
|
23
|
+
authConvexSiteUrl?: string;
|
|
24
|
+
authWebBaseUrl?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Convex site URL for cloud IP resolution.
|
|
27
|
+
* When set, the SDK fetches the agent's IP from Convex instead of
|
|
28
|
+
* requiring a hardcoded agentUrl. Works with cloud machines (CPU/GPU)
|
|
29
|
+
* where the IP is managed by Yaver.
|
|
30
|
+
*
|
|
31
|
+
* Set this OR agentUrl — not both. If both are set, agentUrl wins.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* convexUrl: 'https://your-app.convex.site'
|
|
35
|
+
*/
|
|
36
|
+
convexUrl?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Preferred device ID to connect to (from Convex device list).
|
|
39
|
+
* If omitted with convexUrl, connects to the first online device.
|
|
40
|
+
*/
|
|
41
|
+
preferredDeviceId?: string;
|
|
42
|
+
/** How feedback collection is triggered */
|
|
43
|
+
trigger?: 'shake' | 'floating-button' | 'manual';
|
|
44
|
+
/** Enable/disable the SDK. Defaults to __DEV__ */
|
|
45
|
+
enabled?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Reporting-only mode. When true:
|
|
48
|
+
* - Shake auto-captures screenshot + errors and sends to the agent
|
|
49
|
+
* - No floating button, no feedback modal, no auto-test UI
|
|
50
|
+
* - Agent receives and stores the report but does NOT auto-trigger a fix
|
|
51
|
+
* - Developer reviews reports in CLI and decides what to fix
|
|
52
|
+
*
|
|
53
|
+
* Use case: enable for QA testers / beta users who should report bugs
|
|
54
|
+
* but not trigger code changes. The developer configures their own device
|
|
55
|
+
* with `reportingOnly: false` to get the full SDK with fix triggers.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // For beta testers:
|
|
59
|
+
* YaverFeedback.init({ reportingOnly: true, trigger: 'shake', ... });
|
|
60
|
+
*
|
|
61
|
+
* // For the developer:
|
|
62
|
+
* YaverFeedback.init({ reportingOnly: false, trigger: 'floating-button', ... });
|
|
63
|
+
*/
|
|
64
|
+
reportingOnly?: boolean;
|
|
65
|
+
/** Max screen recording duration in seconds. Default: 120 */
|
|
66
|
+
maxRecordingDuration?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Feedback mode:
|
|
69
|
+
* - 'live': stream events to the agent as they happen
|
|
70
|
+
* - 'narrated': record everything, send on stop
|
|
71
|
+
* - 'batch': dump everything at end (default)
|
|
72
|
+
*/
|
|
73
|
+
feedbackMode?: 'live' | 'narrated' | 'batch';
|
|
74
|
+
/**
|
|
75
|
+
* Agent commentary level (0-10).
|
|
76
|
+
* 0 = silent, 10 = agent comments on everything it sees.
|
|
77
|
+
* Only relevant in live mode. Default: 0.
|
|
78
|
+
*/
|
|
79
|
+
agentCommentaryLevel?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Enable voice input for feedback annotations. Always true by default.
|
|
82
|
+
* Audio is recorded on the device and sent to the agent for transcription.
|
|
83
|
+
* Works regardless of whether a speech-to-speech provider is configured —
|
|
84
|
+
* if STT is available on the agent, audio is auto-transcribed; otherwise
|
|
85
|
+
* raw audio is attached to the feedback report.
|
|
86
|
+
*/
|
|
87
|
+
voiceEnabled?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Maximum number of captured errors to keep in memory (ring buffer).
|
|
90
|
+
* Oldest errors are evicted when the buffer is full.
|
|
91
|
+
* Default: 5.
|
|
92
|
+
*
|
|
93
|
+
* Errors are captured via `YaverFeedback.attachError()` or
|
|
94
|
+
* `YaverFeedback.wrapErrorHandler()`. The SDK never auto-hooks global
|
|
95
|
+
* error handlers — this avoids conflicts with Sentry, Crashlytics,
|
|
96
|
+
* Bugsnag, or any other error tracking tool.
|
|
97
|
+
*/
|
|
98
|
+
maxCapturedErrors?: number;
|
|
99
|
+
/**
|
|
100
|
+
* Which platforms the Build button targets.
|
|
101
|
+
* - 'ios' — build iOS only
|
|
102
|
+
* - 'android' — build Android only
|
|
103
|
+
* - 'both' — build iOS and Android sequentially (default)
|
|
104
|
+
* - 'web' — build web app
|
|
105
|
+
*/
|
|
106
|
+
buildPlatforms?: 'ios' | 'android' | 'both' | 'web';
|
|
107
|
+
/**
|
|
108
|
+
* Auto-deploy builds after successful build.
|
|
109
|
+
* When true (default), iOS builds are uploaded to TestFlight
|
|
110
|
+
* and Android builds are uploaded to Google Play internal testing.
|
|
111
|
+
* When false, builds are created locally without uploading.
|
|
112
|
+
*/
|
|
113
|
+
autoDeploy?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Background color of the debug console panel.
|
|
116
|
+
* Default: "#2d2d2d" (dark gray). Set to any color to match your app's theme
|
|
117
|
+
* and avoid visual overlap.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* panelBackgroundColor: '#1a1a2e' // dark blue-gray
|
|
121
|
+
* panelBackgroundColor: '#333333' // neutral dark gray
|
|
122
|
+
*/
|
|
123
|
+
panelBackgroundColor?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Callback invoked when the agent pushes a reload command.
|
|
126
|
+
* This happens when the vibe coder triggers a reload from the Yaver mobile app
|
|
127
|
+
* or from another connected device.
|
|
128
|
+
*
|
|
129
|
+
* If not provided, the SDK will attempt `DevSettings.reload()` in dev mode
|
|
130
|
+
* or ignore the command in production.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* onReload: () => {
|
|
134
|
+
* // Custom reload logic, e.g. re-fetch bundle from agent
|
|
135
|
+
* Updates.reloadAsync();
|
|
136
|
+
* }
|
|
137
|
+
*/
|
|
138
|
+
onReload?: () => void;
|
|
139
|
+
/**
|
|
140
|
+
* Callback invoked when the agent pushes a reload_bundle command with a new
|
|
141
|
+
* native bundle URL. The SDK passes the bundle URL and assets URL so the app
|
|
142
|
+
* can fetch and load the new bundle.
|
|
143
|
+
*
|
|
144
|
+
* If not provided, the SDK will attempt to POST the bundle to localhost:8347
|
|
145
|
+
* (Yaver's on-device HTTP server) for native container reload.
|
|
146
|
+
*/
|
|
147
|
+
onReloadBundle?: (bundleUrl: string, assetsUrl?: string) => void;
|
|
148
|
+
/**
|
|
149
|
+
* TLS certificate fingerprint (SHA256) for HTTPS on LAN.
|
|
150
|
+
* When set, the SDK prefers HTTPS connections and verifies the agent's
|
|
151
|
+
* self-signed cert matches this fingerprint.
|
|
152
|
+
*/
|
|
153
|
+
tlsFingerprint?: string;
|
|
154
|
+
/**
|
|
155
|
+
* Require TLS for all connections. When true, refuses HTTP connections.
|
|
156
|
+
* Default: false (HTTPS preferred when fingerprint available, HTTP fallback).
|
|
157
|
+
*/
|
|
158
|
+
requireTLS?: boolean;
|
|
159
|
+
}
|
|
160
|
+
export interface FeedbackBundle {
|
|
161
|
+
metadata: FeedbackMetadata;
|
|
162
|
+
video?: string;
|
|
163
|
+
/** Voice annotation audio file path (WAV). Always available when voiceEnabled. */
|
|
164
|
+
audio?: string;
|
|
165
|
+
/** Transcribed text from voice annotation (if STT/S2S provider is available on agent). */
|
|
166
|
+
audioTranscript?: string;
|
|
167
|
+
screenshots: string[];
|
|
168
|
+
/** Captured errors with stack traces, attached automatically when captureErrors is enabled. */
|
|
169
|
+
errors?: CapturedError[];
|
|
170
|
+
}
|
|
171
|
+
/** An error captured by the SDK's global error handler. */
|
|
172
|
+
export interface CapturedError {
|
|
173
|
+
/** Error message. */
|
|
174
|
+
message: string;
|
|
175
|
+
/** Parsed stack frames (e.g. "at CheckoutButton.handlePress (CheckoutScreen.tsx:47)"). */
|
|
176
|
+
stack: string[];
|
|
177
|
+
/** Whether this was a fatal (unrecoverable) error. */
|
|
178
|
+
isFatal: boolean;
|
|
179
|
+
/** Unix timestamp in milliseconds when the error occurred. */
|
|
180
|
+
timestamp: number;
|
|
181
|
+
/** Optional developer-attached context via YaverFeedback.attachError(). */
|
|
182
|
+
metadata?: Record<string, unknown>;
|
|
183
|
+
}
|
|
184
|
+
export interface FeedbackMetadata {
|
|
185
|
+
timestamp: string;
|
|
186
|
+
device: DeviceInfo;
|
|
187
|
+
app: AppInfo;
|
|
188
|
+
userNote?: string;
|
|
189
|
+
}
|
|
190
|
+
export interface DeviceInfo {
|
|
191
|
+
platform: string;
|
|
192
|
+
osVersion: string;
|
|
193
|
+
model: string;
|
|
194
|
+
screenWidth: number;
|
|
195
|
+
screenHeight: number;
|
|
196
|
+
}
|
|
197
|
+
export interface AppInfo {
|
|
198
|
+
bundleId?: string;
|
|
199
|
+
version?: string;
|
|
200
|
+
buildNumber?: string;
|
|
201
|
+
}
|
|
202
|
+
export interface TimelineEvent {
|
|
203
|
+
type: 'screenshot' | 'audio' | 'video';
|
|
204
|
+
path: string;
|
|
205
|
+
timestamp: string;
|
|
206
|
+
duration?: number;
|
|
207
|
+
}
|
|
208
|
+
export interface FeedbackReport {
|
|
209
|
+
id: string;
|
|
210
|
+
bundle: FeedbackBundle;
|
|
211
|
+
status: 'pending' | 'uploading' | 'uploaded' | 'failed';
|
|
212
|
+
error?: string;
|
|
213
|
+
}
|
|
214
|
+
export interface AgentCommentary {
|
|
215
|
+
id: string;
|
|
216
|
+
timestamp: string;
|
|
217
|
+
message: string;
|
|
218
|
+
type: 'observation' | 'suggestion' | 'question' | 'action';
|
|
219
|
+
}
|
|
220
|
+
export interface FeedbackStreamEvent {
|
|
221
|
+
type: string;
|
|
222
|
+
timestamp: string;
|
|
223
|
+
data: any;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* A single fix applied by the AI agent during a test session.
|
|
227
|
+
* Displayed in the FixReport component as a markdown-style list.
|
|
228
|
+
*/
|
|
229
|
+
export interface TestFix {
|
|
230
|
+
/** Unique fix ID */
|
|
231
|
+
id: string;
|
|
232
|
+
/** File that was modified */
|
|
233
|
+
file: string;
|
|
234
|
+
/** Line number of the change */
|
|
235
|
+
line?: number;
|
|
236
|
+
/** Short description of what was fixed */
|
|
237
|
+
description: string;
|
|
238
|
+
/** The error/exception that triggered this fix */
|
|
239
|
+
error?: string;
|
|
240
|
+
/** Diff or code snippet (shown on expand) */
|
|
241
|
+
diff?: string;
|
|
242
|
+
/** Timestamp when the fix was applied */
|
|
243
|
+
timestamp: string;
|
|
244
|
+
/** Whether the fix resolved the issue (verified after hot reload) */
|
|
245
|
+
verified?: boolean;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Test session state returned by the agent's /test-app/status endpoint.
|
|
249
|
+
*/
|
|
250
|
+
export interface TestSession {
|
|
251
|
+
/** Whether a test session is currently running */
|
|
252
|
+
active: boolean;
|
|
253
|
+
/** Current screen being tested */
|
|
254
|
+
currentScreen?: string;
|
|
255
|
+
/** Total screens discovered */
|
|
256
|
+
screensDiscovered: number;
|
|
257
|
+
/** Total screens tested */
|
|
258
|
+
screensTested: number;
|
|
259
|
+
/** Errors found during this session */
|
|
260
|
+
errorsFound: number;
|
|
261
|
+
/** Fixes applied (not committed — staged only) */
|
|
262
|
+
fixes: TestFix[];
|
|
263
|
+
/** Session start time */
|
|
264
|
+
startedAt?: string;
|
|
265
|
+
/** Elapsed seconds */
|
|
266
|
+
elapsedSeconds?: number;
|
|
267
|
+
/** Status message */
|
|
268
|
+
status: string;
|
|
269
|
+
}
|
|
270
|
+
/** Voice capability info returned by the agent's /voice/status endpoint. */
|
|
271
|
+
export interface VoiceCapability {
|
|
272
|
+
/** Always true — mobile can always record and send audio. */
|
|
273
|
+
voiceInputEnabled: boolean;
|
|
274
|
+
/** Speech-to-speech provider (e.g. "personaplex", "openai"), or null. */
|
|
275
|
+
s2sProvider?: string;
|
|
276
|
+
/** Whether the S2S provider is ready for real-time sessions. */
|
|
277
|
+
s2sReady?: boolean;
|
|
278
|
+
/** Speech-to-text provider for transcription (e.g. "whisper", "openai"). */
|
|
279
|
+
sttProvider?: string;
|
|
280
|
+
/** Whether STT is ready (auto-transcription of voice input). */
|
|
281
|
+
sttReady?: boolean;
|
|
282
|
+
}
|
package/dist/types.js
ADDED
package/dist/upload.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FeedbackBundle } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Upload a feedback bundle to the Yaver agent via multipart POST.
|
|
4
|
+
*
|
|
5
|
+
* The agent receives the bundle at POST /feedback with:
|
|
6
|
+
* - `metadata` (JSON string)
|
|
7
|
+
* - `screenshot_0`, `screenshot_1`, ... (image files)
|
|
8
|
+
* - `audio` (audio file, if present)
|
|
9
|
+
* - `video` (video file, if present)
|
|
10
|
+
*
|
|
11
|
+
* @returns The feedback report ID from the agent response.
|
|
12
|
+
*/
|
|
13
|
+
export declare function uploadFeedback(agentUrl: string, authToken: string, bundle: FeedbackBundle): Promise<string>;
|
package/dist/upload.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.uploadFeedback = uploadFeedback;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
/**
|
|
6
|
+
* Upload a feedback bundle to the Yaver agent via multipart POST.
|
|
7
|
+
*
|
|
8
|
+
* The agent receives the bundle at POST /feedback with:
|
|
9
|
+
* - `metadata` (JSON string)
|
|
10
|
+
* - `screenshot_0`, `screenshot_1`, ... (image files)
|
|
11
|
+
* - `audio` (audio file, if present)
|
|
12
|
+
* - `video` (video file, if present)
|
|
13
|
+
*
|
|
14
|
+
* @returns The feedback report ID from the agent response.
|
|
15
|
+
*/
|
|
16
|
+
async function uploadFeedback(agentUrl, authToken, bundle) {
|
|
17
|
+
const formData = new FormData();
|
|
18
|
+
// Attach metadata as JSON
|
|
19
|
+
formData.append('metadata', JSON.stringify(bundle.metadata));
|
|
20
|
+
// Attach screenshots
|
|
21
|
+
for (let i = 0; i < bundle.screenshots.length; i++) {
|
|
22
|
+
const path = bundle.screenshots[i];
|
|
23
|
+
formData.append(`screenshot_${i}`, {
|
|
24
|
+
uri: react_native_1.Platform.OS === 'android' ? `file://${path}` : path,
|
|
25
|
+
type: 'image/png',
|
|
26
|
+
name: `screenshot_${i}.png`,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// Attach audio
|
|
30
|
+
if (bundle.audio) {
|
|
31
|
+
formData.append('audio', {
|
|
32
|
+
uri: react_native_1.Platform.OS === 'android' ? `file://${bundle.audio}` : bundle.audio,
|
|
33
|
+
type: 'audio/m4a',
|
|
34
|
+
name: 'voice_note.m4a',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
// Attach video
|
|
38
|
+
if (bundle.video) {
|
|
39
|
+
formData.append('video', {
|
|
40
|
+
uri: react_native_1.Platform.OS === 'android' ? `file://${bundle.video}` : bundle.video,
|
|
41
|
+
type: 'video/mp4',
|
|
42
|
+
name: 'screen_recording.mp4',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const url = agentUrl.replace(/\/$/, '') + '/feedback';
|
|
46
|
+
const response = await fetch(url, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: {
|
|
49
|
+
Authorization: `Bearer ${authToken}`,
|
|
50
|
+
},
|
|
51
|
+
body: formData,
|
|
52
|
+
});
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
const text = await response.text().catch(() => '');
|
|
55
|
+
throw new Error(`[YaverFeedback] Upload failed (${response.status}): ${text}`);
|
|
56
|
+
}
|
|
57
|
+
const result = await response.json();
|
|
58
|
+
return result.id ?? result.reportId ?? 'unknown';
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yaver-feedback-react-native",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "Visual feedback SDK for Yaver — bug reports, screen recording, voice annotations, and local-first developer workflows",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
|
+
"dist/",
|
|
8
9
|
"src/",
|
|
9
10
|
"ios/",
|
|
10
11
|
"android/",
|
|
@@ -36,6 +37,8 @@
|
|
|
36
37
|
"typescript": "^5.0.0"
|
|
37
38
|
},
|
|
38
39
|
"scripts": {
|
|
40
|
+
"build": "rm -rf dist && (tsc || true) && test -f dist/index.js",
|
|
41
|
+
"prepublishOnly": "npm run build",
|
|
39
42
|
"test": "jest"
|
|
40
43
|
},
|
|
41
44
|
"jest": {
|