uwonbot 1.1.1 → 1.1.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/bin/uwonbot.js +27 -1
- package/package.json +1 -1
- package/src/agent.js +126 -7
- package/src/autostart.js +179 -0
- package/src/brain.js +6 -0
- package/src/setup.js +14 -0
package/bin/uwonbot.js
CHANGED
|
@@ -7,13 +7,14 @@ import { startChat } from '../src/chat.js';
|
|
|
7
7
|
import { getConfig } from '../src/config.js';
|
|
8
8
|
import { startAgent } from '../src/agent.js';
|
|
9
9
|
import { runSetupWizard } from '../src/setup.js';
|
|
10
|
+
import { enableAutostart, disableAutostart, isAutostartEnabled } from '../src/autostart.js';
|
|
10
11
|
|
|
11
12
|
showBanner();
|
|
12
13
|
|
|
13
14
|
program
|
|
14
15
|
.name('uwonbot')
|
|
15
16
|
.description('Uwonbot AI Assistant — Your AI controls your computer')
|
|
16
|
-
.version('1.1.
|
|
17
|
+
.version('1.1.3');
|
|
17
18
|
|
|
18
19
|
program
|
|
19
20
|
.command('login')
|
|
@@ -95,6 +96,31 @@ program
|
|
|
95
96
|
await runSetupWizard();
|
|
96
97
|
});
|
|
97
98
|
|
|
99
|
+
program
|
|
100
|
+
.command('autostart')
|
|
101
|
+
.description('Enable/disable uwonbot agent auto-start on boot')
|
|
102
|
+
.option('--on', 'Enable auto-start')
|
|
103
|
+
.option('--off', 'Disable auto-start')
|
|
104
|
+
.action(async (opts) => {
|
|
105
|
+
const chalk = (await import('chalk')).default;
|
|
106
|
+
if (opts.on) {
|
|
107
|
+
enableAutostart();
|
|
108
|
+
} else if (opts.off) {
|
|
109
|
+
disableAutostart();
|
|
110
|
+
} else {
|
|
111
|
+
const enabled = isAutostartEnabled();
|
|
112
|
+
console.log('');
|
|
113
|
+
console.log(chalk.white.bold(' uwonbot agent 자동 시작'));
|
|
114
|
+
console.log(chalk.gray(' ─────────────────────────'));
|
|
115
|
+
console.log(` 상태: ${enabled ? chalk.green('활성화') : chalk.gray('비활성화')}`);
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log(chalk.gray(' 사용법:'));
|
|
118
|
+
console.log(chalk.white(' uwonbot autostart --on ') + chalk.gray('자동 시작 활성화'));
|
|
119
|
+
console.log(chalk.white(' uwonbot autostart --off ') + chalk.gray('자동 시작 비활성화'));
|
|
120
|
+
console.log('');
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
98
124
|
program
|
|
99
125
|
.command('upgrade')
|
|
100
126
|
.description('Upgrade uwonbot to the latest version')
|
package/package.json
CHANGED
package/src/agent.js
CHANGED
|
@@ -4,8 +4,10 @@ import { promisify } from 'util';
|
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { getConfig } from './config.js';
|
|
6
6
|
import ClapListener from './clapListener.js';
|
|
7
|
+
import { fetchAssistants, setIdToken } from './firebase-client.js';
|
|
7
8
|
|
|
8
9
|
const execAsync = promisify(exec);
|
|
10
|
+
const WEB_APP_URL = 'https://chartapp-653e1.web.app';
|
|
9
11
|
const platform = process.platform;
|
|
10
12
|
|
|
11
13
|
let robot = null;
|
|
@@ -272,6 +274,84 @@ async function handleCommand(msg) {
|
|
|
272
274
|
}
|
|
273
275
|
}
|
|
274
276
|
|
|
277
|
+
async function openWebAssistant(assistantId) {
|
|
278
|
+
const url = `${WEB_APP_URL}/assistant/live?id=${assistantId}`;
|
|
279
|
+
try {
|
|
280
|
+
if (platform === 'darwin') {
|
|
281
|
+
await execAsync(`open -na "Google Chrome" --args --new-window "${url}" 2>/dev/null || open -na "Safari" --args "${url}" 2>/dev/null || open "${url}"`);
|
|
282
|
+
} else if (platform === 'win32') {
|
|
283
|
+
await execAsync(`start chrome --new-window "${url}" 2>nul || start "" "${url}"`);
|
|
284
|
+
} else {
|
|
285
|
+
await execAsync(`google-chrome --new-window "${url}" 2>/dev/null || xdg-open "${url}"`);
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
} catch {
|
|
289
|
+
try { await execAsync(`open "${url}"`); return true; } catch { return false; }
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async function activateAllAssistants(assistants) {
|
|
294
|
+
const opened = [];
|
|
295
|
+
for (const a of assistants) {
|
|
296
|
+
const mode = a.activationMode || 'web';
|
|
297
|
+
if (mode === 'terminal') {
|
|
298
|
+
await openTerminalWithChat(a.name);
|
|
299
|
+
opened.push({ name: a.name, mode: 'terminal' });
|
|
300
|
+
} else if (mode === 'web') {
|
|
301
|
+
await openWebAssistant(a.id);
|
|
302
|
+
opened.push({ name: a.name, mode: 'web' });
|
|
303
|
+
} else {
|
|
304
|
+
await openTerminalWithChat(a.name);
|
|
305
|
+
await openWebAssistant(a.id);
|
|
306
|
+
opened.push({ name: a.name, mode: 'both' });
|
|
307
|
+
}
|
|
308
|
+
await new Promise(r => setTimeout(r, 500));
|
|
309
|
+
}
|
|
310
|
+
return opened;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async function loadUserAssistants(uid) {
|
|
314
|
+
try {
|
|
315
|
+
const assistants = await fetchAssistants(uid);
|
|
316
|
+
return assistants;
|
|
317
|
+
} catch {
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async function listenForName(assistants, apiKey) {
|
|
323
|
+
if (!apiKey || assistants.length <= 1) return;
|
|
324
|
+
let VoiceInput;
|
|
325
|
+
try {
|
|
326
|
+
VoiceInput = (await import('./voiceInput.js')).default;
|
|
327
|
+
} catch { return; }
|
|
328
|
+
|
|
329
|
+
const vi = new VoiceInput(apiKey);
|
|
330
|
+
const names = assistants.map(a => a.name.toLowerCase());
|
|
331
|
+
|
|
332
|
+
console.log(chalk.cyan(' 🎙 비서 이름을 말하면 해당 비서만 유지됩니다...'));
|
|
333
|
+
console.log(chalk.gray(` 비서 목록: ${assistants.map(a => a.name).join(', ')}`));
|
|
334
|
+
|
|
335
|
+
const ok = await vi.start({
|
|
336
|
+
onListening: () => {},
|
|
337
|
+
onSpeechStart: () => {},
|
|
338
|
+
onSpeechEnd: () => {},
|
|
339
|
+
onTranscript: (text) => {
|
|
340
|
+
const lower = text.toLowerCase().trim();
|
|
341
|
+
const matched = names.find(n => lower.includes(n));
|
|
342
|
+
if (matched) {
|
|
343
|
+
const matchedAssistant = assistants.find(a => a.name.toLowerCase() === matched);
|
|
344
|
+
console.log(chalk.bold.green(` ✓ "${matchedAssistant.name}" 선택됨 — 나머지 비서를 종료합니다.`));
|
|
345
|
+
vi.stop();
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
if (!ok) {
|
|
351
|
+
console.log(chalk.gray(' (음성 인식을 사용할 수 없어 모든 비서가 활성 상태로 유지됩니다)'));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
275
355
|
export async function startAgent(port = 9876, options = {}) {
|
|
276
356
|
console.log('');
|
|
277
357
|
console.log(chalk.bold.cyan(' 🖥️ Uwonbot Agent'));
|
|
@@ -284,20 +364,61 @@ export async function startAgent(port = 9876, options = {}) {
|
|
|
284
364
|
const config = getConfig();
|
|
285
365
|
const uid = config.get('uid');
|
|
286
366
|
const email = config.get('email');
|
|
367
|
+
const idToken = config.get('idToken');
|
|
287
368
|
|
|
288
369
|
if (!uid) {
|
|
289
370
|
console.log(chalk.red(' ✗ Not logged in. Run: uwonbot login'));
|
|
290
371
|
process.exit(1);
|
|
291
372
|
}
|
|
292
373
|
|
|
374
|
+
if (idToken) setIdToken(idToken);
|
|
375
|
+
|
|
293
376
|
console.log(chalk.gray(` User: ${email}`));
|
|
294
377
|
console.log(chalk.gray(` Port: ${port}`));
|
|
378
|
+
|
|
379
|
+
let userAssistants = [];
|
|
380
|
+
try {
|
|
381
|
+
userAssistants = await loadUserAssistants(uid);
|
|
382
|
+
if (userAssistants.length > 0) {
|
|
383
|
+
console.log(chalk.gray(` Assistants: ${userAssistants.map(a => a.name).join(', ')}`));
|
|
384
|
+
} else {
|
|
385
|
+
console.log(chalk.gray(' Assistants: (none — default Uwonbot will be used)'));
|
|
386
|
+
}
|
|
387
|
+
} catch {}
|
|
295
388
|
console.log('');
|
|
296
389
|
|
|
297
390
|
if (!options.noMic) {
|
|
298
|
-
const clapListener = new ClapListener(() => {
|
|
299
|
-
console.log(chalk.bold.cyan('
|
|
300
|
-
|
|
391
|
+
const clapListener = new ClapListener(async () => {
|
|
392
|
+
console.log(chalk.bold.cyan(' 👏 박수 감지! 비서 활성화 중...'));
|
|
393
|
+
|
|
394
|
+
if (userAssistants.length === 0) {
|
|
395
|
+
console.log(chalk.gray(' → 기본 Uwonbot 실행'));
|
|
396
|
+
openTerminalWithChat('Uwonbot');
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (userAssistants.length === 1) {
|
|
401
|
+
const a = userAssistants[0];
|
|
402
|
+
const mode = a.activationMode || 'web';
|
|
403
|
+
console.log(chalk.green(` → ${a.name} 실행 (${mode})`));
|
|
404
|
+
if (mode === 'terminal' || mode === 'both') await openTerminalWithChat(a.name);
|
|
405
|
+
if (mode === 'web' || mode === 'both') await openWebAssistant(a.id);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
console.log(chalk.cyan(` → ${userAssistants.length}개 비서 모두 활성화`));
|
|
410
|
+
const opened = await activateAllAssistants(userAssistants);
|
|
411
|
+
opened.forEach(o => {
|
|
412
|
+
console.log(chalk.gray(` ✓ ${o.name} (${o.mode})`));
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
const geminiKey = userAssistants.find(a => a.apiKey)?.apiKey;
|
|
416
|
+
if (geminiKey) {
|
|
417
|
+
await listenForName(userAssistants, geminiKey);
|
|
418
|
+
} else {
|
|
419
|
+
console.log(chalk.gray(' → 모든 비서가 활성 상태로 유지됩니다.'));
|
|
420
|
+
console.log(chalk.gray(' (비서 이름을 말해 선택하려면 API 키가 필요합니다)'));
|
|
421
|
+
}
|
|
301
422
|
});
|
|
302
423
|
await clapListener.start();
|
|
303
424
|
console.log('');
|
|
@@ -318,7 +439,7 @@ export async function startAgent(port = 9876, options = {}) {
|
|
|
318
439
|
console.log(chalk.yellow(' ○ Client disconnected'));
|
|
319
440
|
});
|
|
320
441
|
|
|
321
|
-
ws.send(JSON.stringify({ type: 'welcome', agent: 'uwonbot', version: '1.
|
|
442
|
+
ws.send(JSON.stringify({ type: 'welcome', agent: 'uwonbot', version: '1.1.2', uid }));
|
|
322
443
|
});
|
|
323
444
|
|
|
324
445
|
wss.on('error', (err) => {
|
|
@@ -331,9 +452,7 @@ export async function startAgent(port = 9876, options = {}) {
|
|
|
331
452
|
});
|
|
332
453
|
|
|
333
454
|
console.log(chalk.bold.green(` ✓ Agent running on ws://localhost:${port}`));
|
|
334
|
-
console.log(chalk.gray(' Waiting for connections...'));
|
|
335
|
-
console.log('');
|
|
336
|
-
console.log(chalk.gray(' Press Ctrl+C to stop'));
|
|
455
|
+
console.log(chalk.gray(' Waiting for connections... (Ctrl+C to stop)'));
|
|
337
456
|
console.log('');
|
|
338
457
|
|
|
339
458
|
process.on('SIGINT', () => {
|
package/src/autostart.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { writeFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
|
|
7
|
+
const LABEL = 'com.uwonbot.agent';
|
|
8
|
+
const platform = process.platform;
|
|
9
|
+
|
|
10
|
+
function getUwonbotPath() {
|
|
11
|
+
try {
|
|
12
|
+
const p = execSync('which uwonbot', { encoding: 'utf8' }).trim();
|
|
13
|
+
if (p) return p;
|
|
14
|
+
} catch {}
|
|
15
|
+
return 'uwonbot';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getMacPlistPath() {
|
|
19
|
+
const dir = join(homedir(), 'Library', 'LaunchAgents');
|
|
20
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
21
|
+
return join(dir, `${LABEL}.plist`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getLinuxServicePath() {
|
|
25
|
+
const dir = join(homedir(), '.config', 'systemd', 'user');
|
|
26
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
27
|
+
return join(dir, 'uwonbot-agent.service');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function enableAutostart() {
|
|
31
|
+
const uwonbotPath = getUwonbotPath();
|
|
32
|
+
|
|
33
|
+
if (platform === 'darwin') {
|
|
34
|
+
const plistPath = getMacPlistPath();
|
|
35
|
+
const logPath = join(homedir(), '.uwonbot', 'agent.log');
|
|
36
|
+
const logDir = join(homedir(), '.uwonbot');
|
|
37
|
+
if (!existsSync(logDir)) mkdirSync(logDir, { recursive: true });
|
|
38
|
+
|
|
39
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
40
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
41
|
+
<plist version="1.0">
|
|
42
|
+
<dict>
|
|
43
|
+
<key>Label</key>
|
|
44
|
+
<string>${LABEL}</string>
|
|
45
|
+
<key>ProgramArguments</key>
|
|
46
|
+
<array>
|
|
47
|
+
<string>${uwonbotPath}</string>
|
|
48
|
+
<string>agent</string>
|
|
49
|
+
</array>
|
|
50
|
+
<key>RunAtLoad</key>
|
|
51
|
+
<true/>
|
|
52
|
+
<key>KeepAlive</key>
|
|
53
|
+
<true/>
|
|
54
|
+
<key>StandardOutPath</key>
|
|
55
|
+
<string>${logPath}</string>
|
|
56
|
+
<key>StandardErrorPath</key>
|
|
57
|
+
<string>${logPath}</string>
|
|
58
|
+
<key>EnvironmentVariables</key>
|
|
59
|
+
<dict>
|
|
60
|
+
<key>PATH</key>
|
|
61
|
+
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:${process.env.PATH || ''}</string>
|
|
62
|
+
</dict>
|
|
63
|
+
</dict>
|
|
64
|
+
</plist>`;
|
|
65
|
+
|
|
66
|
+
writeFileSync(plistPath, plist);
|
|
67
|
+
try {
|
|
68
|
+
execSync(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: 'ignore' });
|
|
69
|
+
} catch {}
|
|
70
|
+
try {
|
|
71
|
+
execSync(`launchctl load -w "${plistPath}"`);
|
|
72
|
+
} catch {}
|
|
73
|
+
|
|
74
|
+
console.log(chalk.green(' ✓ uwonbot agent 자동 시작이 등록되었습니다'));
|
|
75
|
+
console.log(chalk.gray(` ${plistPath}`));
|
|
76
|
+
console.log(chalk.gray(` 로그: ${logPath}`));
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (platform === 'linux') {
|
|
81
|
+
const servicePath = getLinuxServicePath();
|
|
82
|
+
const service = `[Unit]
|
|
83
|
+
Description=Uwonbot Agent
|
|
84
|
+
After=network.target
|
|
85
|
+
|
|
86
|
+
[Service]
|
|
87
|
+
ExecStart=${uwonbotPath} agent
|
|
88
|
+
Restart=always
|
|
89
|
+
RestartSec=5
|
|
90
|
+
Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
91
|
+
|
|
92
|
+
[Install]
|
|
93
|
+
WantedBy=default.target`;
|
|
94
|
+
|
|
95
|
+
writeFileSync(servicePath, service);
|
|
96
|
+
try {
|
|
97
|
+
execSync('systemctl --user daemon-reload');
|
|
98
|
+
execSync('systemctl --user enable uwonbot-agent.service');
|
|
99
|
+
execSync('systemctl --user start uwonbot-agent.service');
|
|
100
|
+
} catch {}
|
|
101
|
+
|
|
102
|
+
console.log(chalk.green(' ✓ uwonbot agent 자동 시작이 등록되었습니다 (systemd)'));
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (platform === 'win32') {
|
|
107
|
+
const vbsPath = join(homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'uwonbot-agent.vbs');
|
|
108
|
+
const vbs = `Set WshShell = CreateObject("WScript.Shell")
|
|
109
|
+
WshShell.Run """${uwonbotPath}"" agent", 0, False`;
|
|
110
|
+
try {
|
|
111
|
+
writeFileSync(vbsPath, vbs);
|
|
112
|
+
console.log(chalk.green(' ✓ uwonbot agent 자동 시작이 등록되었습니다 (Windows Startup)'));
|
|
113
|
+
return true;
|
|
114
|
+
} catch {
|
|
115
|
+
console.log(chalk.yellow(' ⚠ Windows 자동 시작 등록에 실패했습니다.'));
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(chalk.yellow(` ⚠ 이 OS(${platform})에서는 자동 시작을 지원하지 않습니다.`));
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function disableAutostart() {
|
|
125
|
+
if (platform === 'darwin') {
|
|
126
|
+
const plistPath = getMacPlistPath();
|
|
127
|
+
if (existsSync(plistPath)) {
|
|
128
|
+
try {
|
|
129
|
+
execSync(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: 'ignore' });
|
|
130
|
+
} catch {}
|
|
131
|
+
unlinkSync(plistPath);
|
|
132
|
+
console.log(chalk.green(' ✓ uwonbot agent 자동 시작이 해제되었습니다'));
|
|
133
|
+
} else {
|
|
134
|
+
console.log(chalk.gray(' 자동 시작이 등록되어 있지 않습니다.'));
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (platform === 'linux') {
|
|
140
|
+
const servicePath = getLinuxServicePath();
|
|
141
|
+
try {
|
|
142
|
+
execSync('systemctl --user stop uwonbot-agent.service', { stdio: 'ignore' });
|
|
143
|
+
execSync('systemctl --user disable uwonbot-agent.service', { stdio: 'ignore' });
|
|
144
|
+
} catch {}
|
|
145
|
+
if (existsSync(servicePath)) {
|
|
146
|
+
unlinkSync(servicePath);
|
|
147
|
+
try { execSync('systemctl --user daemon-reload'); } catch {}
|
|
148
|
+
}
|
|
149
|
+
console.log(chalk.green(' ✓ uwonbot agent 자동 시작이 해제되었습니다'));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (platform === 'win32') {
|
|
154
|
+
const vbsPath = join(homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'uwonbot-agent.vbs');
|
|
155
|
+
if (existsSync(vbsPath)) {
|
|
156
|
+
unlinkSync(vbsPath);
|
|
157
|
+
console.log(chalk.green(' ✓ uwonbot agent 자동 시작이 해제되었습니다'));
|
|
158
|
+
} else {
|
|
159
|
+
console.log(chalk.gray(' 자동 시작이 등록되어 있지 않습니다.'));
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log(chalk.yellow(` ⚠ 이 OS(${platform})에서는 자동 시작을 지원하지 않습니다.`));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function isAutostartEnabled() {
|
|
168
|
+
if (platform === 'darwin') {
|
|
169
|
+
return existsSync(getMacPlistPath());
|
|
170
|
+
}
|
|
171
|
+
if (platform === 'linux') {
|
|
172
|
+
return existsSync(getLinuxServicePath());
|
|
173
|
+
}
|
|
174
|
+
if (platform === 'win32') {
|
|
175
|
+
const vbsPath = join(homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'uwonbot-agent.vbs');
|
|
176
|
+
return existsSync(vbsPath);
|
|
177
|
+
}
|
|
178
|
+
return false;
|
|
179
|
+
}
|
package/src/brain.js
CHANGED
|
@@ -6,7 +6,13 @@ const GEMINI_BASE = 'https://generativelanguage.googleapis.com/v1beta/models';
|
|
|
6
6
|
|
|
7
7
|
function buildSystemPrompt(assistant) {
|
|
8
8
|
const base = assistant.systemPrompt || `You are ${assistant.name || 'Uwonbot'}, an AI assistant.`;
|
|
9
|
+
const lang = assistant.voiceLang || 'ko-KR';
|
|
10
|
+
const langRule = lang.startsWith('ko')
|
|
11
|
+
? `\n[LANGUAGE - STRICTLY ENFORCED]\nYou MUST respond ONLY in Korean (한국어). Never use English or other languages unless the user explicitly uses English words.\nAlways use polite speech (존댓말).`
|
|
12
|
+
: `\n[LANGUAGE - STRICTLY ENFORCED]\nYou MUST respond ONLY in English. Never use Korean or other languages.\nAlways address the user as "sir" or "ma'am".`;
|
|
13
|
+
|
|
9
14
|
return `${base}
|
|
15
|
+
${langRule}
|
|
10
16
|
|
|
11
17
|
You have full access to the user's computer through tools. You can:
|
|
12
18
|
- Read, write, create, delete, and move files
|
package/src/setup.js
CHANGED
|
@@ -2,6 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import { getConfig } from './config.js';
|
|
5
|
+
import { enableAutostart, isAutostartEnabled } from './autostart.js';
|
|
5
6
|
|
|
6
7
|
function checkSoxInstalled() {
|
|
7
8
|
try {
|
|
@@ -43,6 +44,19 @@ export async function runSetupWizard() {
|
|
|
43
44
|
|
|
44
45
|
config.set('agentAutoStart', enableAgent);
|
|
45
46
|
|
|
47
|
+
if (enableAgent && !isAutostartEnabled()) {
|
|
48
|
+
console.log('');
|
|
49
|
+
const { bootStart } = await inquirer.prompt([{
|
|
50
|
+
type: 'confirm',
|
|
51
|
+
name: 'bootStart',
|
|
52
|
+
message: '컴퓨터 시작 시 에이전트를 자동 실행하시겠습니까?',
|
|
53
|
+
default: true,
|
|
54
|
+
}]);
|
|
55
|
+
if (bootStart) {
|
|
56
|
+
enableAutostart();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
if (enableAgent) {
|
|
47
61
|
console.log('');
|
|
48
62
|
console.log(chalk.bold.white(' 2️⃣ 박수 감지 (Clap Detection)'));
|