@geravant/sinain 1.6.3 → 1.6.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/launcher.js +49 -17
- package/package.json +1 -1
- package/sense_client/requirements.txt +1 -0
package/launcher.js
CHANGED
|
@@ -35,11 +35,13 @@ let skipSense = false;
|
|
|
35
35
|
let skipOverlay = false;
|
|
36
36
|
let skipAgent = false;
|
|
37
37
|
let agentName = null;
|
|
38
|
+
let forceSetup = false;
|
|
38
39
|
|
|
39
40
|
for (const arg of args) {
|
|
40
41
|
if (arg === "--no-sense") { skipSense = true; continue; }
|
|
41
42
|
if (arg === "--no-overlay") { skipOverlay = true; continue; }
|
|
42
43
|
if (arg === "--no-agent") { skipAgent = true; continue; }
|
|
44
|
+
if (arg === "--setup") { forceSetup = true; continue; }
|
|
43
45
|
if (arg.startsWith("--agent=")) { agentName = arg.split("=")[1]; continue; }
|
|
44
46
|
console.error(`Unknown flag: ${arg}`);
|
|
45
47
|
process.exit(1);
|
|
@@ -60,9 +62,9 @@ async function main() {
|
|
|
60
62
|
await preflight();
|
|
61
63
|
console.log();
|
|
62
64
|
|
|
63
|
-
// Run setup wizard on first launch (no ~/.sinain/.env)
|
|
65
|
+
// Run setup wizard on first launch (no ~/.sinain/.env) or when --setup flag is passed
|
|
64
66
|
const userEnvPath = path.join(SINAIN_DIR, ".env");
|
|
65
|
-
if (!fs.existsSync(userEnvPath)) {
|
|
67
|
+
if (forceSetup || !fs.existsSync(userEnvPath)) {
|
|
66
68
|
await setupWizard(userEnvPath);
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -129,7 +131,7 @@ async function main() {
|
|
|
129
131
|
try {
|
|
130
132
|
const depCheck = IS_WINDOWS
|
|
131
133
|
? 'python3 -c "import PIL; import skimage"'
|
|
132
|
-
: 'python3 -c "import PIL; import skimage; import Quartz"';
|
|
134
|
+
: 'python3 -c "import PIL; import skimage; import Quartz; import Vision"';
|
|
133
135
|
execSync(depCheck, { stdio: "pipe" });
|
|
134
136
|
} catch {
|
|
135
137
|
log("Installing sense_client Python dependencies...");
|
|
@@ -374,9 +376,20 @@ async function setupWizard(envPath) {
|
|
|
374
376
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
375
377
|
const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
376
378
|
|
|
379
|
+
// Load existing .env values as defaults (for re-configuration)
|
|
380
|
+
const existing = {};
|
|
381
|
+
if (fs.existsSync(envPath)) {
|
|
382
|
+
for (const line of fs.readFileSync(envPath, "utf-8").split("\n")) {
|
|
383
|
+
const m = line.match(/^([A-Z_]+)=(.*)$/);
|
|
384
|
+
if (m) existing[m[1]] = m[2];
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const hasExisting = Object.keys(existing).length > 0;
|
|
388
|
+
|
|
377
389
|
console.log();
|
|
378
|
-
console.log(`${BOLD}── First-time setup ────────────────────${RESET}`);
|
|
390
|
+
console.log(`${BOLD}── ${hasExisting ? "Re-configure" : "First-time setup"} ────────────────────${RESET}`);
|
|
379
391
|
console.log(` Configuring ${DIM}~/.sinain/.env${RESET}`);
|
|
392
|
+
if (hasExisting) console.log(` ${DIM}Press Enter to keep current values shown in [brackets]${RESET}`);
|
|
380
393
|
console.log();
|
|
381
394
|
|
|
382
395
|
const vars = {};
|
|
@@ -428,10 +441,13 @@ async function setupWizard(envPath) {
|
|
|
428
441
|
|
|
429
442
|
// 2. OpenRouter API key (if cloud backend or for vision/OCR)
|
|
430
443
|
if (transcriptionBackend === "openrouter") {
|
|
444
|
+
const existingKey = existing.OPENROUTER_API_KEY;
|
|
445
|
+
const keyHint = existingKey ? ` [${existingKey.slice(0, 8)}...${existingKey.slice(-4)}]` : "";
|
|
431
446
|
let key = "";
|
|
432
447
|
while (!key) {
|
|
433
|
-
key = await ask(` OpenRouter API key (sk-or-...): `);
|
|
448
|
+
key = await ask(` OpenRouter API key (sk-or-...)${keyHint}: `);
|
|
434
449
|
key = key.trim();
|
|
450
|
+
if (!key && existingKey) { key = existingKey; break; }
|
|
435
451
|
if (key && !key.startsWith("sk-or-")) {
|
|
436
452
|
console.log(` ${YELLOW}⚠${RESET} Key should start with sk-or-. Try again or press Enter to skip.`);
|
|
437
453
|
const retry = await ask(` Use this key anyway? [y/N]: `);
|
|
@@ -445,13 +461,17 @@ async function setupWizard(envPath) {
|
|
|
445
461
|
if (key) vars.OPENROUTER_API_KEY = key;
|
|
446
462
|
} else {
|
|
447
463
|
// Still ask for OpenRouter key (needed for vision/OCR)
|
|
448
|
-
const
|
|
464
|
+
const existingKey = existing.OPENROUTER_API_KEY;
|
|
465
|
+
const keyHint = existingKey ? ` [${existingKey.slice(0, 8)}...${existingKey.slice(-4)}]` : "";
|
|
466
|
+
const key = await ask(` OpenRouter API key for vision/OCR (optional, Enter to skip)${keyHint}: `);
|
|
449
467
|
if (key.trim()) vars.OPENROUTER_API_KEY = key.trim();
|
|
468
|
+
else if (existingKey) vars.OPENROUTER_API_KEY = existingKey;
|
|
450
469
|
}
|
|
451
470
|
|
|
452
471
|
// 3. Agent selection
|
|
453
|
-
const
|
|
454
|
-
|
|
472
|
+
const defaultAgent = existing.SINAIN_AGENT || "claude";
|
|
473
|
+
const agentChoice = await ask(` Agent? [${BOLD}${defaultAgent}${RESET}/claude/codex/goose/junie/aider]: `);
|
|
474
|
+
vars.SINAIN_AGENT = agentChoice.trim().toLowerCase() || defaultAgent;
|
|
455
475
|
|
|
456
476
|
// 3b. Local vision (Ollama)
|
|
457
477
|
const IS_MACOS = os.platform() === "darwin";
|
|
@@ -506,25 +526,37 @@ async function setupWizard(envPath) {
|
|
|
506
526
|
console.log(` selective — score-based (errors, questions trigger it)`);
|
|
507
527
|
console.log(` focus — always escalate every tick`);
|
|
508
528
|
console.log(` rich — always escalate with maximum context`);
|
|
509
|
-
const
|
|
510
|
-
|
|
529
|
+
const defaultEsc = existing.ESCALATION_MODE || "selective";
|
|
530
|
+
const escMode = await ask(` Escalation mode? [off/${BOLD}${defaultEsc}${RESET}/selective/focus/rich]: `);
|
|
531
|
+
vars.ESCALATION_MODE = escMode.trim().toLowerCase() || defaultEsc;
|
|
511
532
|
|
|
512
533
|
// 5. OpenClaw gateway
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
534
|
+
const hadGateway = !!(existing.OPENCLAW_WS_URL);
|
|
535
|
+
const gatewayDefault = hadGateway ? "Y" : "N";
|
|
536
|
+
const hasGateway = await ask(` Do you have an OpenClaw gateway? [${gatewayDefault === "Y" ? "Y/n" : "y/N"}]: `);
|
|
537
|
+
const wantsGateway = hasGateway.trim()
|
|
538
|
+
? hasGateway.trim().toLowerCase() === "y"
|
|
539
|
+
: hadGateway;
|
|
540
|
+
if (wantsGateway) {
|
|
541
|
+
const defaultWs = existing.OPENCLAW_WS_URL || "ws://localhost:18789";
|
|
542
|
+
const wsUrl = await ask(` Gateway WebSocket URL [${defaultWs}]: `);
|
|
543
|
+
vars.OPENCLAW_WS_URL = wsUrl.trim() || defaultWs;
|
|
544
|
+
|
|
545
|
+
const existingToken = existing.OPENCLAW_WS_TOKEN;
|
|
546
|
+
const tokenHint = existingToken ? ` [${existingToken.slice(0, 6)}...${existingToken.slice(-4)}]` : "";
|
|
547
|
+
const wsToken = await ask(` Gateway auth token (48-char hex)${tokenHint}: `);
|
|
519
548
|
if (wsToken.trim()) {
|
|
520
549
|
vars.OPENCLAW_WS_TOKEN = wsToken.trim();
|
|
521
550
|
vars.OPENCLAW_HTTP_TOKEN = wsToken.trim();
|
|
551
|
+
} else if (existingToken) {
|
|
552
|
+
vars.OPENCLAW_WS_TOKEN = existingToken;
|
|
553
|
+
vars.OPENCLAW_HTTP_TOKEN = existing.OPENCLAW_HTTP_TOKEN || existingToken;
|
|
522
554
|
}
|
|
523
555
|
|
|
524
556
|
// Derive HTTP URL from WS URL
|
|
525
557
|
const httpBase = vars.OPENCLAW_WS_URL.replace(/^ws/, "http");
|
|
526
558
|
vars.OPENCLAW_HTTP_URL = `${httpBase}/hooks/agent`;
|
|
527
|
-
vars.OPENCLAW_SESSION_KEY = "agent:main:sinain";
|
|
559
|
+
vars.OPENCLAW_SESSION_KEY = existing.OPENCLAW_SESSION_KEY || "agent:main:sinain";
|
|
528
560
|
} else {
|
|
529
561
|
// No gateway — disable WS connection attempts
|
|
530
562
|
vars.OPENCLAW_WS_URL = "";
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ numpy>=1.24
|
|
|
4
4
|
pytesseract>=0.3
|
|
5
5
|
requests>=2.31
|
|
6
6
|
pyobjc-framework-Quartz>=10.0; sys_platform == "darwin"
|
|
7
|
+
pyobjc-framework-Vision>=10.0; sys_platform == "darwin"
|
|
7
8
|
mss>=9.0; sys_platform == "win32"
|
|
8
9
|
psutil>=5.9; sys_platform == "win32"
|
|
9
10
|
winrt-Windows.Media.Ocr>=2.0; sys_platform == "win32"
|