@toothfairyai/tfcode 1.0.0-beta.4 → 1.0.0-beta.5
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/bin/tfcode.js +114 -86
- package/package.json +1 -1
package/bin/tfcode.js
CHANGED
|
@@ -42,47 +42,35 @@ function info(msg) {
|
|
|
42
42
|
|
|
43
43
|
function question(rl, prompt, hidden = false) {
|
|
44
44
|
return new Promise((resolve) => {
|
|
45
|
-
if (hidden) {
|
|
45
|
+
if (hidden && process.stdin.isTTY) {
|
|
46
|
+
// Use simpler approach for hidden input
|
|
46
47
|
process.stdout.write(prompt);
|
|
47
48
|
|
|
48
49
|
let input = '';
|
|
49
50
|
const stdin = process.stdin;
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
52
|
+
stdin.setRawMode(true);
|
|
53
|
+
stdin.setEncoding('utf8');
|
|
54
54
|
stdin.resume();
|
|
55
55
|
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
break;
|
|
71
|
-
case '\u0003':
|
|
72
|
-
process.stdout.write('\n');
|
|
73
|
-
process.exit();
|
|
74
|
-
break;
|
|
75
|
-
case '\u007F':
|
|
76
|
-
case '\b':
|
|
77
|
-
input = input.slice(0, -1);
|
|
78
|
-
break;
|
|
79
|
-
default:
|
|
80
|
-
input += c;
|
|
81
|
-
break;
|
|
56
|
+
const onKeypress = (str) => {
|
|
57
|
+
if (str === '\n' || str === '\r' || str === '\u0004') {
|
|
58
|
+
stdin.setRawMode(false);
|
|
59
|
+
stdin.pause();
|
|
60
|
+
stdin.removeListener('data', onKeypress);
|
|
61
|
+
process.stdout.write('\n');
|
|
62
|
+
resolve(input);
|
|
63
|
+
} else if (str === '\u0003') {
|
|
64
|
+
process.stdout.write('\n');
|
|
65
|
+
process.exit();
|
|
66
|
+
} else if (str === '\u007F' || str === '\b') {
|
|
67
|
+
input = input.slice(0, -1);
|
|
68
|
+
} else if (str.length === 1 && str.charCodeAt(0) >= 32) {
|
|
69
|
+
input += str;
|
|
82
70
|
}
|
|
83
71
|
};
|
|
84
72
|
|
|
85
|
-
stdin.on('data',
|
|
73
|
+
stdin.on('data', onKeypress);
|
|
86
74
|
} else {
|
|
87
75
|
rl.question(prompt, (answer) => {
|
|
88
76
|
resolve(answer.trim());
|
|
@@ -101,42 +89,17 @@ function select(prompt, options) {
|
|
|
101
89
|
});
|
|
102
90
|
log('');
|
|
103
91
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (stdin.isTTY) {
|
|
110
|
-
stdin.setRawMode(true);
|
|
111
|
-
}
|
|
112
|
-
stdin.resume();
|
|
113
|
-
|
|
114
|
-
const onData = (char) => {
|
|
115
|
-
const c = char.toString('utf8');
|
|
116
|
-
|
|
117
|
-
if (c === '\n' || c === '\r' || c === '\u0004') {
|
|
118
|
-
if (stdin.isTTY) {
|
|
119
|
-
stdin.setRawMode(false);
|
|
120
|
-
}
|
|
121
|
-
stdin.pause();
|
|
122
|
-
stdin.removeListener('data', onData);
|
|
123
|
-
process.stdout.write('\n');
|
|
124
|
-
|
|
125
|
-
const idx = parseInt(input) - 1;
|
|
126
|
-
resolve(idx >= 0 && idx < options.length ? idx : 0);
|
|
127
|
-
} else if (c === '\u0003') {
|
|
128
|
-
process.stdout.write('\n');
|
|
129
|
-
process.exit();
|
|
130
|
-
} else if (c >= '1' && c <= '9') {
|
|
131
|
-
input += c;
|
|
132
|
-
process.stdout.write(c);
|
|
133
|
-
} else if (c === '\u007F' || c === '\b') {
|
|
134
|
-
input = input.slice(0, -1);
|
|
135
|
-
process.stdout.write('\b \b');
|
|
136
|
-
}
|
|
137
|
-
};
|
|
92
|
+
// Create a fresh readline for select
|
|
93
|
+
const rlSelect = readline.createInterface({
|
|
94
|
+
input: process.stdin,
|
|
95
|
+
output: process.stdout
|
|
96
|
+
});
|
|
138
97
|
|
|
139
|
-
|
|
98
|
+
rlSelect.question('Select (1-' + options.length + '): ', (answer) => {
|
|
99
|
+
rlSelect.close();
|
|
100
|
+
const idx = parseInt(answer.trim()) - 1;
|
|
101
|
+
resolve(idx >= 0 && idx < options.length ? idx : 0);
|
|
102
|
+
});
|
|
140
103
|
});
|
|
141
104
|
}
|
|
142
105
|
|
|
@@ -287,11 +250,6 @@ function saveToolsCache(tools) {
|
|
|
287
250
|
}
|
|
288
251
|
|
|
289
252
|
async function interactiveSetup() {
|
|
290
|
-
const rl = readline.createInterface({
|
|
291
|
-
input: process.stdin,
|
|
292
|
-
output: process.stdout
|
|
293
|
-
});
|
|
294
|
-
|
|
295
253
|
log('');
|
|
296
254
|
log(`${COLORS.bold}${COLORS.magenta}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${COLORS.reset}`);
|
|
297
255
|
log(`${COLORS.bold}${COLORS.magenta} tfcode Setup${COLORS.reset}`);
|
|
@@ -303,35 +261,83 @@ async function interactiveSetup() {
|
|
|
303
261
|
log(`${COLORS.dim} https://app.toothfairyai.com → Settings → API Keys${COLORS.reset}`);
|
|
304
262
|
log('');
|
|
305
263
|
|
|
306
|
-
// Workspace ID
|
|
264
|
+
// Step 1: Workspace ID
|
|
307
265
|
log(`${COLORS.bold}Step 1: Workspace ID${COLORS.reset}`);
|
|
308
266
|
log(`${COLORS.dim}This is your workspace UUID (e.g., 12345678-1234-1234-1234-123456789012)${COLORS.reset}`);
|
|
309
267
|
log('');
|
|
310
|
-
|
|
268
|
+
|
|
269
|
+
const workspaceId = await new Promise((resolve) => {
|
|
270
|
+
const rl = readline.createInterface({
|
|
271
|
+
input: process.stdin,
|
|
272
|
+
output: process.stdout
|
|
273
|
+
});
|
|
274
|
+
rl.question('Enter your Workspace ID: ', (answer) => {
|
|
275
|
+
rl.close();
|
|
276
|
+
resolve(answer.trim());
|
|
277
|
+
});
|
|
278
|
+
});
|
|
311
279
|
|
|
312
280
|
if (!workspaceId) {
|
|
313
281
|
error('Workspace ID is required');
|
|
314
|
-
rl.close();
|
|
315
282
|
process.exit(1);
|
|
316
283
|
}
|
|
317
284
|
|
|
318
285
|
log('');
|
|
319
286
|
|
|
320
|
-
// API Key
|
|
287
|
+
// Step 2: API Key (hidden)
|
|
321
288
|
log(`${COLORS.bold}Step 2: API Key${COLORS.reset}`);
|
|
322
289
|
log(`${COLORS.dim}Your API key will be hidden as you type${COLORS.reset}`);
|
|
323
290
|
log('');
|
|
324
|
-
|
|
291
|
+
|
|
292
|
+
const apiKey = await new Promise((resolve) => {
|
|
293
|
+
if (!process.stdin.isTTY) {
|
|
294
|
+
const rl = readline.createInterface({
|
|
295
|
+
input: process.stdin,
|
|
296
|
+
output: process.stdout
|
|
297
|
+
});
|
|
298
|
+
rl.question('Enter your API Key: ', (answer) => {
|
|
299
|
+
rl.close();
|
|
300
|
+
resolve(answer.trim());
|
|
301
|
+
});
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
process.stdout.write('Enter your API Key: ');
|
|
306
|
+
let input = '';
|
|
307
|
+
const stdin = process.stdin;
|
|
308
|
+
|
|
309
|
+
stdin.setRawMode(true);
|
|
310
|
+
stdin.setEncoding('utf8');
|
|
311
|
+
stdin.resume();
|
|
312
|
+
|
|
313
|
+
const onKeypress = (str) => {
|
|
314
|
+
if (str === '\n' || str === '\r' || str === '\u0004') {
|
|
315
|
+
stdin.setRawMode(false);
|
|
316
|
+
stdin.pause();
|
|
317
|
+
stdin.removeListener('data', onKeypress);
|
|
318
|
+
process.stdout.write('\n');
|
|
319
|
+
resolve(input);
|
|
320
|
+
} else if (str === '\u0003') {
|
|
321
|
+
process.stdout.write('\n');
|
|
322
|
+
process.exit();
|
|
323
|
+
} else if (str === '\u007F' || str === '\b') {
|
|
324
|
+
input = input.slice(0, -1);
|
|
325
|
+
} else if (str.length === 1 && str.charCodeAt(0) >= 32) {
|
|
326
|
+
input += str;
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
stdin.on('data', onKeypress);
|
|
331
|
+
});
|
|
325
332
|
|
|
326
333
|
if (!apiKey) {
|
|
327
334
|
error('API Key is required');
|
|
328
|
-
rl.close();
|
|
329
335
|
process.exit(1);
|
|
330
336
|
}
|
|
331
337
|
|
|
332
338
|
log('');
|
|
333
339
|
|
|
334
|
-
// Region
|
|
340
|
+
// Step 3: Region
|
|
335
341
|
log(`${COLORS.bold}Step 3: Region${COLORS.reset}`);
|
|
336
342
|
const regions = ['dev (Development)', 'au (Australia)', 'eu (Europe)', 'us (United States)'];
|
|
337
343
|
const regionIdx = await select('Select your region:', regions);
|
|
@@ -349,8 +355,16 @@ async function interactiveSetup() {
|
|
|
349
355
|
log(` Region: ${region}`);
|
|
350
356
|
log('');
|
|
351
357
|
|
|
352
|
-
|
|
353
|
-
|
|
358
|
+
const confirm = await new Promise((resolve) => {
|
|
359
|
+
const rl = readline.createInterface({
|
|
360
|
+
input: process.stdin,
|
|
361
|
+
output: process.stdout
|
|
362
|
+
});
|
|
363
|
+
rl.question('Save these credentials? (Y/n): ', (answer) => {
|
|
364
|
+
rl.close();
|
|
365
|
+
resolve(answer.trim());
|
|
366
|
+
});
|
|
367
|
+
});
|
|
354
368
|
|
|
355
369
|
if (confirm.toLowerCase() !== 'n' && confirm.toLowerCase() !== 'no') {
|
|
356
370
|
const config = { workspace_id: workspaceId, api_key: apiKey, region };
|
|
@@ -359,8 +373,16 @@ async function interactiveSetup() {
|
|
|
359
373
|
log('');
|
|
360
374
|
|
|
361
375
|
// Validate
|
|
362
|
-
|
|
363
|
-
|
|
376
|
+
const testNow = await new Promise((resolve) => {
|
|
377
|
+
const rl = readline.createInterface({
|
|
378
|
+
input: process.stdin,
|
|
379
|
+
output: process.stdout
|
|
380
|
+
});
|
|
381
|
+
rl.question('Validate credentials now? (Y/n): ', (answer) => {
|
|
382
|
+
rl.close();
|
|
383
|
+
resolve(answer.trim());
|
|
384
|
+
});
|
|
385
|
+
});
|
|
364
386
|
|
|
365
387
|
if (testNow.toLowerCase() !== 'n' && testNow.toLowerCase() !== 'no') {
|
|
366
388
|
log('');
|
|
@@ -376,8 +398,16 @@ async function interactiveSetup() {
|
|
|
376
398
|
log(` Workspace ID: ${result.workspace_id}`);
|
|
377
399
|
log('');
|
|
378
400
|
|
|
379
|
-
|
|
380
|
-
|
|
401
|
+
const syncNow = await new Promise((resolve) => {
|
|
402
|
+
const rl = readline.createInterface({
|
|
403
|
+
input: process.stdin,
|
|
404
|
+
output: process.stdout
|
|
405
|
+
});
|
|
406
|
+
rl.question('Sync tools now? (Y/n): ', (answer) => {
|
|
407
|
+
rl.close();
|
|
408
|
+
resolve(answer.trim());
|
|
409
|
+
});
|
|
410
|
+
});
|
|
381
411
|
|
|
382
412
|
if (syncNow.toLowerCase() !== 'n' && syncNow.toLowerCase() !== 'no') {
|
|
383
413
|
log('');
|
|
@@ -433,8 +463,6 @@ async function interactiveSetup() {
|
|
|
433
463
|
} else {
|
|
434
464
|
log('Setup cancelled.');
|
|
435
465
|
}
|
|
436
|
-
|
|
437
|
-
rl.close();
|
|
438
466
|
}
|
|
439
467
|
|
|
440
468
|
const cli = yargs(hideBin(process.argv))
|