profileShare

rasmusjy / voicetask

Read-only snapshot

No repository description.

main default branch 105 files Expires Sep 13, 2026, 9:06 AM
setup.mjs 2,458 bytes
1 import { existsSync, writeFileSync } from 'node:fs'
2 import { createInterface } from 'node:readline'
3
4 const rl = createInterface({ input: process.stdin, output: process.stdout })
5
6 // Queue lines so answers are not lost between questions when input is piped.
7 const pending = []
8 const waiters = []
9 rl.on('line', (line) => {
10 const waiter = waiters.shift()
11 if (waiter) waiter(line)
12 else pending.push(line)
13 })
14 rl.on('close', () => {
15 for (const waiter of waiters.splice(0)) waiter(null)
16 })
17
18 async function ask(question) {
19 process.stdout.write(question)
20 const line =
21 pending.length > 0 ? pending.shift() : await new Promise((resolve) => waiters.push(resolve))
22 if (line === null) {
23 console.error('\nInput ended before setup finished. Nothing changed.')
24 process.exit(1)
25 }
26 return line.trim()
27 }
28
29 console.log(
30 'VoiceTask setup. Writes a local .env file (gitignored, never committed).\n' +
31 'You can also skip this and set everything up in the browser after "npm run dev".\n',
32 )
33
34 if (existsSync('.env')) {
35 const answer = await ask('.env already exists. Overwrite it? [y/N] ')
36 if (answer.toLowerCase() !== 'y') {
37 console.log('Keeping the existing .env. Nothing changed.')
38 rl.close()
39 process.exit(0)
40 }
41 }
42
43 console.log(`Mode:
44 1) Real APIs - needs an Anthropic key (interview) and an OpenAI key (speech-to-text)
45 2) Offline demo - no keys, deterministic mock providers
46 `)
47
48 let mode = ''
49 while (mode !== '1' && mode !== '2') {
50 mode = await ask('Choose [1/2]: ')
51 }
52
53 let anthropicKey = ''
54 let openaiKey = ''
55
56 if (mode === '1') {
57 console.log('\nKeys are stored only in your local .env. Input is visible while you paste.\n')
58 while (!anthropicKey) {
59 anthropicKey = await ask('Anthropic API key (console.anthropic.com): ')
60 }
61 if (!anthropicKey.startsWith('sk-ant-')) {
62 console.log(' Note: Anthropic keys usually start with "sk-ant-". Saving it anyway.')
63 }
64 while (!openaiKey) {
65 openaiKey = await ask('OpenAI API key (platform.openai.com): ')
66 }
67 if (!openaiKey.startsWith('sk-')) {
68 console.log(' Note: OpenAI keys usually start with "sk-". Saving it anyway.')
69 }
70 }
71
72 const env = `# Written by npm run setup. Edit freely; see .env.example for all options.
73 MOCK_PROVIDERS=${mode === '2' ? '1' : ''}
74 ANTHROPIC_API_KEY=${anthropicKey}
75 OPENAI_API_KEY=${openaiKey}
76 `
77
78 writeFileSync('.env', env)
79 console.log('\nWrote .env. Next: npm run dev, then open the printed URL in Chrome or Edge.')
80 rl.close()
81