voyageai-cli 1.21.0 → 1.22.0
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/package.json +3 -2
- package/src/cli.js +2 -0
- package/src/commands/bug.js +249 -0
- package/src/lib/codegen.js +27 -1
- package/src/playground/index.html +189 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "voyageai-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "CLI for Voyage AI embeddings, reranking, and MongoDB Atlas Vector Search",
|
|
5
5
|
"bin": {
|
|
6
6
|
"vai": "./src/cli.js"
|
|
@@ -37,9 +37,10 @@
|
|
|
37
37
|
"test": "node --test test/**/*.test.js"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
|
-
"node": ">=
|
|
40
|
+
"node": ">=20.0.0"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@clack/prompts": "^1.0.0",
|
|
43
44
|
"commander": "^12.0.0",
|
|
44
45
|
"dotenv": "^17.2.3",
|
|
45
46
|
"mongodb": "^6.0.0",
|
package/src/cli.js
CHANGED
|
@@ -34,6 +34,7 @@ const { registerApp } = require('./commands/app');
|
|
|
34
34
|
const { registerAbout } = require('./commands/about');
|
|
35
35
|
const { register: registerDoctor } = require('./commands/doctor');
|
|
36
36
|
const { register: registerQuickstart } = require('./commands/quickstart');
|
|
37
|
+
const { registerBug } = require('./commands/bug');
|
|
37
38
|
const { showBanner, showQuickStart, getVersion } = require('./lib/banner');
|
|
38
39
|
|
|
39
40
|
const version = getVersion();
|
|
@@ -72,6 +73,7 @@ registerApp(program);
|
|
|
72
73
|
registerAbout(program);
|
|
73
74
|
registerDoctor(program);
|
|
74
75
|
registerQuickstart(program);
|
|
76
|
+
registerBug(program);
|
|
75
77
|
|
|
76
78
|
// Append disclaimer to all help output
|
|
77
79
|
program.addHelpText('after', `
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const os = require('os');
|
|
4
|
+
const pc = require('picocolors');
|
|
5
|
+
const ui = require('../lib/ui');
|
|
6
|
+
const { send: sendTelemetry } = require('../lib/telemetry');
|
|
7
|
+
|
|
8
|
+
// Try to get package version safely
|
|
9
|
+
function getVersion() {
|
|
10
|
+
try {
|
|
11
|
+
return require('../../package.json').version;
|
|
12
|
+
} catch {
|
|
13
|
+
return 'unknown';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const GITHUB_ISSUES_URL = 'https://github.com/mrlynn/voyageai-cli/issues/new';
|
|
18
|
+
const BUG_API_URL = 'https://vai.mlynn.org/api/bugs';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Generate a GitHub issue URL with pre-filled template
|
|
22
|
+
*/
|
|
23
|
+
function generateGitHubUrl(title, description, context = {}) {
|
|
24
|
+
const issueTitle = encodeURIComponent(`[Bug] ${title || 'Bug Report'}`);
|
|
25
|
+
|
|
26
|
+
const body = `## Description
|
|
27
|
+
${description || 'Describe the bug here...'}
|
|
28
|
+
|
|
29
|
+
## Steps to Reproduce
|
|
30
|
+
1.
|
|
31
|
+
2.
|
|
32
|
+
3.
|
|
33
|
+
|
|
34
|
+
## Expected Behavior
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Actual Behavior
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Environment
|
|
41
|
+
- **CLI Version:** ${context.cliVersion || getVersion()}
|
|
42
|
+
- **Node Version:** ${process.version}
|
|
43
|
+
- **Platform:** ${os.platform()} ${os.release()}
|
|
44
|
+
- **Arch:** ${os.arch()}
|
|
45
|
+
${context.command ? `- **Command:** \`${context.command}\`` : ''}
|
|
46
|
+
|
|
47
|
+
## Additional Context
|
|
48
|
+
${context.errorMessage ? `### Error\n\`\`\`\n${context.errorMessage}\n\`\`\`` : 'Add any other context here.'}
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
return `${GITHUB_ISSUES_URL}?title=${issueTitle}&body=${encodeURIComponent(body)}&labels=bug`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Submit bug report to API
|
|
56
|
+
*/
|
|
57
|
+
async function submitBugReport(data) {
|
|
58
|
+
try {
|
|
59
|
+
const response = await fetch(BUG_API_URL, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: { 'Content-Type': 'application/json' },
|
|
62
|
+
body: JSON.stringify({
|
|
63
|
+
...data,
|
|
64
|
+
source: 'cli',
|
|
65
|
+
cliVersion: getVersion(),
|
|
66
|
+
platform: os.platform(),
|
|
67
|
+
arch: os.arch(),
|
|
68
|
+
nodeVersion: process.version,
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
const error = await response.json().catch(() => ({}));
|
|
74
|
+
throw new Error(error.error || `HTTP ${response.status}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return await response.json();
|
|
78
|
+
} catch (error) {
|
|
79
|
+
throw new Error(`Failed to submit bug report: ${error.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Open URL in default browser
|
|
85
|
+
*/
|
|
86
|
+
function openUrl(url) {
|
|
87
|
+
const { exec } = require('child_process');
|
|
88
|
+
const command = os.platform() === 'darwin' ? 'open' :
|
|
89
|
+
os.platform() === 'win32' ? 'start' : 'xdg-open';
|
|
90
|
+
exec(`${command} "${url}"`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Interactive bug report (when no arguments provided)
|
|
95
|
+
*/
|
|
96
|
+
async function interactiveBugReport() {
|
|
97
|
+
const readline = require('readline');
|
|
98
|
+
const rl = readline.createInterface({
|
|
99
|
+
input: process.stdin,
|
|
100
|
+
output: process.stdout,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const question = (prompt) => new Promise((resolve) => {
|
|
104
|
+
rl.question(prompt, resolve);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.log(ui.info('🐛 Bug Reporter'));
|
|
108
|
+
console.log(ui.dim('Report issues with the Vai CLI\n'));
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const title = await question(ui.label('Title', 'Brief description of the bug') + '\n> ');
|
|
112
|
+
if (!title.trim()) {
|
|
113
|
+
console.log(ui.warn('Bug report cancelled.'));
|
|
114
|
+
rl.close();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const description = await question(ui.label('Description', 'What happened?') + '\n> ');
|
|
119
|
+
const steps = await question(ui.label('Steps to Reproduce', 'Optional, press Enter to skip') + '\n> ');
|
|
120
|
+
const email = await question(ui.label('Email', 'Optional, for follow-up') + '\n> ');
|
|
121
|
+
|
|
122
|
+
console.log('');
|
|
123
|
+
const method = await question('Submit to:\n [1] Bug tracker (anonymous)\n [2] GitHub Issues (public)\n [3] Both\n> ');
|
|
124
|
+
|
|
125
|
+
rl.close();
|
|
126
|
+
|
|
127
|
+
const bugData = {
|
|
128
|
+
title: title.trim(),
|
|
129
|
+
description: description.trim(),
|
|
130
|
+
stepsToReproduce: steps.trim() || null,
|
|
131
|
+
email: email.trim() || null,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
if (method === '1' || method === '3') {
|
|
135
|
+
console.log(ui.dim('\nSubmitting to bug tracker...'));
|
|
136
|
+
try {
|
|
137
|
+
const result = await submitBugReport(bugData);
|
|
138
|
+
console.log(ui.success(`Bug submitted! ID: ${result.bugId}`));
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.log(ui.error(error.message));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (method === '2' || method === '3') {
|
|
145
|
+
const url = generateGitHubUrl(bugData.title, bugData.description, {
|
|
146
|
+
cliVersion: getVersion(),
|
|
147
|
+
});
|
|
148
|
+
console.log(ui.dim('\nOpening GitHub...'));
|
|
149
|
+
openUrl(url);
|
|
150
|
+
console.log(ui.success('GitHub issue page opened in browser'));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (!['1', '2', '3'].includes(method)) {
|
|
154
|
+
console.log(ui.warn('No submission method selected.'));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
} catch (error) {
|
|
158
|
+
rl.close();
|
|
159
|
+
console.error(ui.error(`Error: ${error.message}`));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Main bug command
|
|
165
|
+
*/
|
|
166
|
+
async function bugCommand(args, flags) {
|
|
167
|
+
// --github flag: open GitHub issues directly
|
|
168
|
+
if (flags.github || flags.g) {
|
|
169
|
+
const title = args.join(' ');
|
|
170
|
+
const url = generateGitHubUrl(title, '', { cliVersion: getVersion() });
|
|
171
|
+
console.log(ui.info('Opening GitHub Issues...'));
|
|
172
|
+
openUrl(url);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// --quick flag: quick submit with just title
|
|
177
|
+
if (flags.quick || flags.q) {
|
|
178
|
+
const title = args.join(' ');
|
|
179
|
+
if (!title) {
|
|
180
|
+
console.error(ui.error('Please provide a bug title: vai bug --quick "Something broke"'));
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
console.log(ui.dim('Submitting quick bug report...'));
|
|
185
|
+
try {
|
|
186
|
+
const result = await submitBugReport({
|
|
187
|
+
title,
|
|
188
|
+
description: title,
|
|
189
|
+
});
|
|
190
|
+
console.log(ui.success(`Bug submitted! ID: ${result.bugId}`));
|
|
191
|
+
console.log(ui.dim(`Create GitHub issue: ${result.githubIssueUrl}`));
|
|
192
|
+
} catch (error) {
|
|
193
|
+
console.error(ui.error(error.message));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// If title provided as argument, use quick mode
|
|
200
|
+
if (args.length > 0) {
|
|
201
|
+
const title = args.join(' ');
|
|
202
|
+
console.log(ui.dim('Submitting bug report...'));
|
|
203
|
+
try {
|
|
204
|
+
const result = await submitBugReport({
|
|
205
|
+
title,
|
|
206
|
+
description: title,
|
|
207
|
+
});
|
|
208
|
+
console.log(ui.success(`Bug submitted! ID: ${result.bugId}`));
|
|
209
|
+
console.log(ui.dim('To create a GitHub issue with more details:'));
|
|
210
|
+
console.log(ui.dim(` ${result.githubIssueUrl.slice(0, 80)}...`));
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error(ui.error(error.message));
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// No arguments: interactive mode
|
|
219
|
+
await interactiveBugReport();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Register the bug command with Commander
|
|
224
|
+
*/
|
|
225
|
+
function registerBug(program) {
|
|
226
|
+
program
|
|
227
|
+
.command('bug [title...]')
|
|
228
|
+
.description('Report a bug or issue with the Vai CLI')
|
|
229
|
+
.option('-g, --github', 'Open GitHub Issues in browser')
|
|
230
|
+
.option('-q, --quick', 'Quick submit (title only, no interaction)')
|
|
231
|
+
.action(async (titleParts, options) => {
|
|
232
|
+
sendTelemetry('bug', {
|
|
233
|
+
method: options.github ? 'github' : options.quick ? 'quick' : 'interactive'
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const args = titleParts || [];
|
|
237
|
+
const flags = {
|
|
238
|
+
github: options.github,
|
|
239
|
+
g: options.github,
|
|
240
|
+
quick: options.quick,
|
|
241
|
+
q: options.quick,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
await bugCommand(args, flags);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
module.exports = { registerBug };
|
|
249
|
+
module.exports.bugCommand = bugCommand;
|
package/src/lib/codegen.js
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Safely get the CLI version, handling both development and packaged Electron app.
|
|
8
|
+
* @returns {string} The version string or 'unknown'
|
|
9
|
+
*/
|
|
10
|
+
function getCliVersion() {
|
|
11
|
+
// Try multiple paths to find package.json
|
|
12
|
+
const possiblePaths = [
|
|
13
|
+
path.join(__dirname, '..', '..', 'package.json'), // Development: src/lib -> root
|
|
14
|
+
path.join(process.resourcesPath || '', 'cli-package.json'), // Packaged Electron app
|
|
15
|
+
path.join(__dirname, '..', 'package.json'), // Alternative structure
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
for (const pkgPath of possiblePaths) {
|
|
19
|
+
try {
|
|
20
|
+
if (fs.existsSync(pkgPath)) {
|
|
21
|
+
const pkg = require(pkgPath);
|
|
22
|
+
if (pkg.version) return pkg.version;
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
// Try next path
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return 'unknown';
|
|
30
|
+
}
|
|
31
|
+
|
|
6
32
|
/**
|
|
7
33
|
* Lightweight template engine for code generation.
|
|
8
34
|
*
|
|
@@ -295,7 +321,7 @@ function buildContext(project, options = {}) {
|
|
|
295
321
|
|
|
296
322
|
// Metadata
|
|
297
323
|
generatedAt: new Date().toISOString(),
|
|
298
|
-
vaiVersion:
|
|
324
|
+
vaiVersion: getCliVersion(),
|
|
299
325
|
};
|
|
300
326
|
|
|
301
327
|
return context;
|
|
@@ -7123,5 +7123,194 @@ init();
|
|
|
7123
7123
|
<canvas id="vsiCanvas" width="600" height="500" style="border:1px solid #3D4F58;border-radius:8px;image-rendering:pixelated;"></canvas>
|
|
7124
7124
|
<div style="color:#889397;font-size:11px;font-family:monospace;text-align:center;">← → move | SPACE shoot | ESC exit</div>
|
|
7125
7125
|
</div>
|
|
7126
|
+
|
|
7127
|
+
<!-- 🐛 Bug Reporter -->
|
|
7128
|
+
<style>
|
|
7129
|
+
.bug-floating-button{position:fixed;bottom:20px;right:20px;width:48px;height:48px;border-radius:50%;background:linear-gradient(135deg,#ff6b6b,#ee5a5a);border:none;cursor:pointer;font-size:24px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px rgba(238,90,90,0.4);transition:all .2s;z-index:9998}
|
|
7130
|
+
.bug-floating-button:hover{transform:scale(1.1);box-shadow:0 6px 16px rgba(238,90,90,0.5)}
|
|
7131
|
+
.bug-reporter-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.6);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:9999}
|
|
7132
|
+
.bug-reporter-modal{background:var(--bg-surface);border-radius:12px;width:90%;max-width:500px;max-height:90vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,0.5)}
|
|
7133
|
+
.bug-reporter-header{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid var(--border)}
|
|
7134
|
+
.bug-reporter-header h2{flex:1;margin:0;font-size:18px;font-weight:600;color:var(--accent-text)}
|
|
7135
|
+
.bug-reporter-header .close-btn{background:none;border:none;color:var(--text-muted);font-size:24px;cursor:pointer;padding:4px 8px;border-radius:4px}
|
|
7136
|
+
.bug-reporter-header .close-btn:hover{background:rgba(255,255,255,0.1);color:var(--text)}
|
|
7137
|
+
.bug-reporter-form{padding:20px}
|
|
7138
|
+
.bug-reporter-form .form-group{margin-bottom:16px}
|
|
7139
|
+
.bug-reporter-form label{display:block;font-size:13px;font-weight:500;color:var(--text-muted);margin-bottom:6px}
|
|
7140
|
+
.bug-reporter-form input,.bug-reporter-form textarea{width:100%;padding:10px 12px;border:1px solid var(--border);border-radius:8px;background:var(--bg-input);color:var(--text);font-size:14px;font-family:inherit}
|
|
7141
|
+
.bug-reporter-form input:focus,.bug-reporter-form textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-glow)}
|
|
7142
|
+
.bug-reporter-form textarea{resize:vertical;min-height:80px}
|
|
7143
|
+
.bug-env-info{padding:12px;background:var(--accent-glow);border-radius:8px;font-size:12px;margin-bottom:16px;color:var(--accent)}
|
|
7144
|
+
.bug-env-info code{color:var(--text-muted);font-size:11px}
|
|
7145
|
+
.bug-error{padding:10px 12px;background:rgba(255,107,107,0.15);border:1px solid rgba(255,107,107,0.3);border-radius:8px;color:var(--error);font-size:13px;margin-bottom:16px}
|
|
7146
|
+
.bug-actions{display:flex;gap:12px}
|
|
7147
|
+
.bug-actions button{flex:1;padding:12px 16px;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s;border:none}
|
|
7148
|
+
.bug-actions .primary{background:linear-gradient(135deg,var(--accent),#00c853);color:#000}
|
|
7149
|
+
.bug-actions .primary:hover{box-shadow:0 4px 12px rgba(0,237,100,0.4)}
|
|
7150
|
+
.bug-actions .primary:disabled{opacity:0.6;cursor:not-allowed}
|
|
7151
|
+
.bug-actions .secondary{background:rgba(255,255,255,0.1);color:var(--text);border:1px solid var(--border)}
|
|
7152
|
+
.bug-actions .secondary:hover{background:rgba(255,255,255,0.15)}
|
|
7153
|
+
.bug-success{padding:40px 20px;text-align:center}
|
|
7154
|
+
.bug-success .icon{width:60px;height:60px;border-radius:50%;background:linear-gradient(135deg,var(--accent),#00c853);color:#000;font-size:32px;display:flex;align-items:center;justify-content:center;margin:0 auto 20px}
|
|
7155
|
+
.bug-success h3{margin:0 0 12px;color:var(--accent-text);font-size:20px}
|
|
7156
|
+
.bug-success p{margin:8px 0;color:var(--text-muted)}
|
|
7157
|
+
.bug-success code{background:rgba(255,255,255,0.1);padding:4px 8px;border-radius:4px;font-size:12px;color:var(--accent)}
|
|
7158
|
+
</style>
|
|
7159
|
+
|
|
7160
|
+
<button class="bug-floating-button" id="bugButton" title="Report a Bug">🐛</button>
|
|
7161
|
+
|
|
7162
|
+
<div class="bug-reporter-overlay" id="bugOverlay" style="display:none">
|
|
7163
|
+
<div class="bug-reporter-modal">
|
|
7164
|
+
<div class="bug-reporter-header">
|
|
7165
|
+
<span style="font-size:28px">🐛</span>
|
|
7166
|
+
<h2>Report a Bug</h2>
|
|
7167
|
+
<button class="close-btn" id="bugClose">×</button>
|
|
7168
|
+
</div>
|
|
7169
|
+
<div class="bug-reporter-form" id="bugForm">
|
|
7170
|
+
<div class="form-group">
|
|
7171
|
+
<label>Title *</label>
|
|
7172
|
+
<input type="text" id="bugTitle" placeholder="Brief description of the bug" maxlength="200">
|
|
7173
|
+
</div>
|
|
7174
|
+
<div class="form-group">
|
|
7175
|
+
<label>Description *</label>
|
|
7176
|
+
<textarea id="bugDescription" placeholder="What happened? What did you expect?" rows="4" maxlength="5000"></textarea>
|
|
7177
|
+
</div>
|
|
7178
|
+
<div class="form-group">
|
|
7179
|
+
<label>Steps to Reproduce</label>
|
|
7180
|
+
<textarea id="bugSteps" placeholder="1. Go to... 2. Click on... 3. See error" rows="3" maxlength="2000"></textarea>
|
|
7181
|
+
</div>
|
|
7182
|
+
<div class="form-group">
|
|
7183
|
+
<label>Email (optional, for follow-up)</label>
|
|
7184
|
+
<input type="email" id="bugEmail" placeholder="your@email.com">
|
|
7185
|
+
</div>
|
|
7186
|
+
<div class="bug-env-info">
|
|
7187
|
+
<span>📋 Environment will be included:</span><br>
|
|
7188
|
+
<code id="bugEnvInfo">Loading...</code>
|
|
7189
|
+
</div>
|
|
7190
|
+
<div class="bug-error" id="bugError" style="display:none"></div>
|
|
7191
|
+
<div class="bug-actions">
|
|
7192
|
+
<button class="primary" id="bugSubmit">Submit Bug Report</button>
|
|
7193
|
+
<button class="secondary" id="bugGithub">Open GitHub Issue</button>
|
|
7194
|
+
</div>
|
|
7195
|
+
</div>
|
|
7196
|
+
<div class="bug-success" id="bugSuccess" style="display:none">
|
|
7197
|
+
<div class="icon">✓</div>
|
|
7198
|
+
<h3>Bug Reported!</h3>
|
|
7199
|
+
<p>Bug ID: <code id="bugResultId"></code></p>
|
|
7200
|
+
<p>Thank you for helping improve Vai!</p>
|
|
7201
|
+
<div class="bug-actions" style="justify-content:center;margin-top:24px">
|
|
7202
|
+
<button class="primary" id="bugSuccessClose">Close</button>
|
|
7203
|
+
</div>
|
|
7204
|
+
</div>
|
|
7205
|
+
</div>
|
|
7206
|
+
</div>
|
|
7207
|
+
|
|
7208
|
+
<script>
|
|
7209
|
+
(function() {
|
|
7210
|
+
const BUG_API = 'https://vai.mlynn.org/api/bugs';
|
|
7211
|
+
const GITHUB_URL = 'https://github.com/mrlynn/voyageai-cli/issues/new';
|
|
7212
|
+
|
|
7213
|
+
function getEnv() {
|
|
7214
|
+
const env = { platform: navigator.platform, source: 'desktop-app' };
|
|
7215
|
+
if (window.electronAPI) {
|
|
7216
|
+
env.appVersion = window.electronAPI.appVersion || 'unknown';
|
|
7217
|
+
env.cliVersion = window.electronAPI.cliVersion || 'unknown';
|
|
7218
|
+
env.electronVersion = window.electronAPI.electronVersion || 'unknown';
|
|
7219
|
+
}
|
|
7220
|
+
env.currentScreen = document.querySelector('.tab-btn.active')?.textContent || 'unknown';
|
|
7221
|
+
return env;
|
|
7222
|
+
}
|
|
7223
|
+
|
|
7224
|
+
function showBugReporter() {
|
|
7225
|
+
const env = getEnv();
|
|
7226
|
+
document.getElementById('bugEnvInfo').textContent =
|
|
7227
|
+
`${env.platform} • App v${env.appVersion || '?'} • ${env.currentScreen}`;
|
|
7228
|
+
document.getElementById('bugOverlay').style.display = 'flex';
|
|
7229
|
+
document.getElementById('bugForm').style.display = 'block';
|
|
7230
|
+
document.getElementById('bugSuccess').style.display = 'none';
|
|
7231
|
+
document.getElementById('bugError').style.display = 'none';
|
|
7232
|
+
document.getElementById('bugTitle').value = '';
|
|
7233
|
+
document.getElementById('bugDescription').value = '';
|
|
7234
|
+
document.getElementById('bugSteps').value = '';
|
|
7235
|
+
document.getElementById('bugEmail').value = '';
|
|
7236
|
+
}
|
|
7237
|
+
|
|
7238
|
+
function hideBugReporter() {
|
|
7239
|
+
document.getElementById('bugOverlay').style.display = 'none';
|
|
7240
|
+
}
|
|
7241
|
+
|
|
7242
|
+
async function submitBug() {
|
|
7243
|
+
const title = document.getElementById('bugTitle').value.trim();
|
|
7244
|
+
const description = document.getElementById('bugDescription').value.trim();
|
|
7245
|
+
const steps = document.getElementById('bugSteps').value.trim();
|
|
7246
|
+
const email = document.getElementById('bugEmail').value.trim();
|
|
7247
|
+
|
|
7248
|
+
if (!title || title.length < 5) {
|
|
7249
|
+
document.getElementById('bugError').textContent = 'Title is required (min 5 characters)';
|
|
7250
|
+
document.getElementById('bugError').style.display = 'block';
|
|
7251
|
+
return;
|
|
7252
|
+
}
|
|
7253
|
+
if (!description || description.length < 10) {
|
|
7254
|
+
document.getElementById('bugError').textContent = 'Description is required (min 10 characters)';
|
|
7255
|
+
document.getElementById('bugError').style.display = 'block';
|
|
7256
|
+
return;
|
|
7257
|
+
}
|
|
7258
|
+
|
|
7259
|
+
document.getElementById('bugSubmit').disabled = true;
|
|
7260
|
+
document.getElementById('bugSubmit').textContent = 'Submitting...';
|
|
7261
|
+
document.getElementById('bugError').style.display = 'none';
|
|
7262
|
+
|
|
7263
|
+
try {
|
|
7264
|
+
const env = getEnv();
|
|
7265
|
+
const res = await fetch(BUG_API, {
|
|
7266
|
+
method: 'POST',
|
|
7267
|
+
headers: { 'Content-Type': 'application/json' },
|
|
7268
|
+
body: JSON.stringify({
|
|
7269
|
+
title, description, stepsToReproduce: steps || null, email: email || null,
|
|
7270
|
+
...env
|
|
7271
|
+
})
|
|
7272
|
+
});
|
|
7273
|
+
|
|
7274
|
+
if (!res.ok) {
|
|
7275
|
+
const err = await res.json().catch(() => ({}));
|
|
7276
|
+
throw new Error(err.error || `HTTP ${res.status}`);
|
|
7277
|
+
}
|
|
7278
|
+
|
|
7279
|
+
const data = await res.json();
|
|
7280
|
+
document.getElementById('bugResultId').textContent = data.bugId;
|
|
7281
|
+
document.getElementById('bugForm').style.display = 'none';
|
|
7282
|
+
document.getElementById('bugSuccess').style.display = 'block';
|
|
7283
|
+
} catch (err) {
|
|
7284
|
+
document.getElementById('bugError').textContent = err.message;
|
|
7285
|
+
document.getElementById('bugError').style.display = 'block';
|
|
7286
|
+
} finally {
|
|
7287
|
+
document.getElementById('bugSubmit').disabled = false;
|
|
7288
|
+
document.getElementById('bugSubmit').textContent = 'Submit Bug Report';
|
|
7289
|
+
}
|
|
7290
|
+
}
|
|
7291
|
+
|
|
7292
|
+
function openGithub() {
|
|
7293
|
+
const title = document.getElementById('bugTitle').value.trim() || 'Bug Report';
|
|
7294
|
+
const description = document.getElementById('bugDescription').value.trim();
|
|
7295
|
+
const steps = document.getElementById('bugSteps').value.trim();
|
|
7296
|
+
const env = getEnv();
|
|
7297
|
+
|
|
7298
|
+
const body = `## Description\n${description}\n\n## Steps to Reproduce\n${steps || '1. \\n2. \\n3. '}\n\n## Environment\n- **App Version:** ${env.appVersion || 'N/A'}\n- **Platform:** ${env.platform}\n- **Screen:** ${env.currentScreen}`;
|
|
7299
|
+
const url = `${GITHUB_URL}?title=${encodeURIComponent('[Bug] ' + title)}&body=${encodeURIComponent(body)}&labels=bug`;
|
|
7300
|
+
window.open(url, '_blank');
|
|
7301
|
+
}
|
|
7302
|
+
|
|
7303
|
+
// Event listeners
|
|
7304
|
+
document.getElementById('bugButton').addEventListener('click', showBugReporter);
|
|
7305
|
+
document.getElementById('bugClose').addEventListener('click', hideBugReporter);
|
|
7306
|
+
document.getElementById('bugOverlay').addEventListener('click', (e) => {
|
|
7307
|
+
if (e.target.id === 'bugOverlay') hideBugReporter();
|
|
7308
|
+
});
|
|
7309
|
+
document.getElementById('bugSubmit').addEventListener('click', submitBug);
|
|
7310
|
+
document.getElementById('bugGithub').addEventListener('click', openGithub);
|
|
7311
|
+
document.getElementById('bugSuccessClose').addEventListener('click', hideBugReporter);
|
|
7312
|
+
})();
|
|
7313
|
+
</script>
|
|
7314
|
+
|
|
7126
7315
|
</body>
|
|
7127
7316
|
</html>
|