loren-code 0.2.1 → 0.2.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/package.json +1 -1
- package/scripts/loren.js +85 -35
package/package.json
CHANGED
package/scripts/loren.js
CHANGED
|
@@ -19,15 +19,28 @@ const logFilePath = path.join(runtimeDir, "bridge.log");
|
|
|
19
19
|
const errorLogFilePath = path.join(runtimeDir, "bridge.err.log");
|
|
20
20
|
const userHome = process.env.USERPROFILE || process.env.HOME || projectRoot;
|
|
21
21
|
const claudeSettingsPath = path.join(userHome, ".claude", "settings.json");
|
|
22
|
+
const displayName = getDisplayName();
|
|
22
23
|
|
|
23
24
|
process.chdir(projectRoot);
|
|
24
25
|
ensureRuntimeDir();
|
|
25
26
|
const envStatus = ensureEnvLocal(projectRoot, { logger: { warn() {} } });
|
|
26
27
|
|
|
27
|
-
const
|
|
28
|
+
const ASCII_BANNER = `
|
|
29
|
+
██╗ ██████╗ ██████╗ ███████╗███╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
30
|
+
██║ ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ██╔════╝██╔═══██╗██╔══██╗██╔════╝
|
|
31
|
+
██║ ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║ ██║██║ ██║█████╗
|
|
32
|
+
██║ ██║ ██║██╔══██╗██╔══╝ ██║╚██╗██║ ██║ ██║ ██║██║ ██║██╔══╝
|
|
33
|
+
███████╗╚██████╔╝██║ ██║███████╗██║ ╚████║ ╚██████╗╚██████╔╝██████╔╝███████╗
|
|
34
|
+
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
const BANNER = `${ASCII_BANNER}
|
|
28
38
|
LOREN CODE
|
|
29
39
|
Smarter bridge, fewer rituals.
|
|
30
40
|
`;
|
|
41
|
+
const GREEN = "\x1b[32m";
|
|
42
|
+
const YELLOW = "\x1b[33m";
|
|
43
|
+
const RESET = "\x1b[0m";
|
|
31
44
|
|
|
32
45
|
const COMMANDS = {
|
|
33
46
|
model: {
|
|
@@ -342,13 +355,16 @@ function showPaths() {
|
|
|
342
355
|
console.log("");
|
|
343
356
|
}
|
|
344
357
|
|
|
345
|
-
function startServer() {
|
|
358
|
+
function startServer(options = {}) {
|
|
359
|
+
const quiet = options.quiet === true;
|
|
346
360
|
const existingPid = readPidFile();
|
|
347
361
|
if (existingPid && isProcessRunning(existingPid)) {
|
|
348
362
|
const config = loadConfig();
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
363
|
+
if (!quiet) {
|
|
364
|
+
console.log("\nLoren is already running.");
|
|
365
|
+
console.log(`URL: ${getBridgeBaseUrl(config)}`);
|
|
366
|
+
console.log("");
|
|
367
|
+
}
|
|
352
368
|
return;
|
|
353
369
|
}
|
|
354
370
|
|
|
@@ -364,10 +380,12 @@ function startServer() {
|
|
|
364
380
|
child.unref();
|
|
365
381
|
fs.writeFileSync(pidFilePath, `${child.pid}\n`, "utf8");
|
|
366
382
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
383
|
+
if (!quiet) {
|
|
384
|
+
const config = loadConfig();
|
|
385
|
+
console.log("\nLoren is up and listening.");
|
|
386
|
+
console.log(`URL: ${getBridgeBaseUrl(config)}`);
|
|
387
|
+
console.log("");
|
|
388
|
+
}
|
|
371
389
|
}
|
|
372
390
|
|
|
373
391
|
function stopServer() {
|
|
@@ -495,32 +513,31 @@ async function runSetupWizard(config) {
|
|
|
495
513
|
});
|
|
496
514
|
|
|
497
515
|
try {
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
saveEnvFile(envFilePath, envVars);
|
|
505
|
-
console.log(`\nNice. Loren is holding ${keys.length} key(s) and feeling organized.`);
|
|
506
|
-
} else {
|
|
507
|
-
console.log("\nNo keys yet. Loren will wait here and act casual about it.");
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
const startNow = (await rl.question("Start the bridge now? [Y/n] ")).trim().toLowerCase();
|
|
511
|
-
if (startNow === "" || startNow === "y" || startNow === "yes") {
|
|
512
|
-
startServer();
|
|
513
|
-
}
|
|
516
|
+
const keys = await promptForApiKeys(rl);
|
|
517
|
+
const envVars = loadEnvFile(envFilePath);
|
|
518
|
+
envVars.OLLAMA_API_KEYS = keys.join(",");
|
|
519
|
+
saveEnvFile(envFilePath, envVars);
|
|
520
|
+
console.log(`${GREEN}✓ Saved ${keys.length} API key(s).${RESET}`);
|
|
521
|
+
console.log("");
|
|
514
522
|
|
|
515
523
|
if (process.platform === "win32") {
|
|
516
|
-
const installClaude = (await rl.question("Install Claude Code integration too? [
|
|
517
|
-
if (installClaude === "y" || installClaude === "yes") {
|
|
524
|
+
const installClaude = (await rl.question("Install Claude Code integration too? [Y/n] ")).trim().toLowerCase();
|
|
525
|
+
if (installClaude === "" || installClaude === "y" || installClaude === "yes") {
|
|
518
526
|
installClaudeIntegration();
|
|
527
|
+
console.log(`${GREEN}✓ Claude Code integration installed.${RESET}`);
|
|
528
|
+
console.log("");
|
|
519
529
|
} else {
|
|
520
530
|
console.log("\nNo problem. You can wire Claude in later.");
|
|
521
531
|
}
|
|
522
532
|
}
|
|
523
533
|
|
|
534
|
+
const startNow = (await rl.question("Start the bridge now? [Y/n] ")).trim().toLowerCase();
|
|
535
|
+
if (startNow === "" || startNow === "y" || startNow === "yes") {
|
|
536
|
+
startServer({ quiet: true });
|
|
537
|
+
console.log(`${GREEN}✓ Bridge started.${RESET}`);
|
|
538
|
+
console.log("");
|
|
539
|
+
}
|
|
540
|
+
|
|
524
541
|
console.log("Setup complete. Fewer steps, fewer goblins.");
|
|
525
542
|
console.log("");
|
|
526
543
|
} finally {
|
|
@@ -535,29 +552,34 @@ function printWizardIntro() {
|
|
|
535
552
|
} else if (envStatus.created) {
|
|
536
553
|
console.log("A fresh config is ready.");
|
|
537
554
|
}
|
|
555
|
+
console.log(`Welcome${displayName ? `, ${displayName}` : ""}.`);
|
|
556
|
+
console.log(`${YELLOW}Run \`loren\` in an interactive terminal to finish setup.${RESET}`);
|
|
538
557
|
console.log("Let's get Loren ready in one quick pass.");
|
|
539
558
|
console.log("");
|
|
559
|
+
printCommandSummary();
|
|
540
560
|
}
|
|
541
561
|
|
|
542
562
|
function printWelcomeBack(config) {
|
|
543
563
|
console.log(BANNER);
|
|
544
|
-
console.log(`Welcome back
|
|
564
|
+
console.log(`Welcome back${displayName ? `, ${displayName}` : ""}.`);
|
|
565
|
+
console.log(`${config.apiKeys.length} key(s) loaded.`);
|
|
545
566
|
console.log(`Current default model: ${config.defaultModel}`);
|
|
567
|
+
console.log(`${GREEN}Run \`loren start\` to launch the bridge.${RESET}`);
|
|
546
568
|
console.log("");
|
|
547
|
-
|
|
548
|
-
console.log(" loren start");
|
|
549
|
-
console.log(" loren model:list");
|
|
550
|
-
console.log(" loren config:show");
|
|
551
|
-
console.log("");
|
|
569
|
+
printCommandSummary();
|
|
552
570
|
}
|
|
553
571
|
|
|
554
572
|
function printQuickSetup(config) {
|
|
555
573
|
if (config.apiKeys.length > 0) {
|
|
556
|
-
|
|
557
|
-
console.log("");
|
|
574
|
+
printWelcomeBack(config);
|
|
558
575
|
return;
|
|
559
576
|
}
|
|
560
577
|
|
|
578
|
+
console.log(BANNER);
|
|
579
|
+
console.log(`Welcome${displayName ? `, ${displayName}` : ""}.`);
|
|
580
|
+
console.log(`${YELLOW}Run \`loren\` in an interactive terminal to finish setup.${RESET}`);
|
|
581
|
+
console.log("");
|
|
582
|
+
printCommandSummary();
|
|
561
583
|
console.log("Quick start:");
|
|
562
584
|
console.log(" 1. Run `loren` in an interactive terminal");
|
|
563
585
|
console.log(" 2. Add your Ollama API key(s)");
|
|
@@ -577,8 +599,26 @@ function installClaudeIntegration() {
|
|
|
577
599
|
}
|
|
578
600
|
}
|
|
579
601
|
|
|
602
|
+
async function promptForApiKeys(rl) {
|
|
603
|
+
while (true) {
|
|
604
|
+
const rawKeys = (await rl.question("Paste your Ollama API key(s), separated by commas: ")).trim();
|
|
605
|
+
const keys = splitKeyList(rawKeys);
|
|
606
|
+
|
|
607
|
+
if (keys.length > 0) {
|
|
608
|
+
return keys;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
console.log("At least one API key is required to continue.");
|
|
612
|
+
console.log("");
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
580
616
|
function printHelp() {
|
|
581
617
|
console.log(BANNER);
|
|
618
|
+
printCommandSummary();
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function printCommandSummary() {
|
|
582
622
|
console.log("Commands:");
|
|
583
623
|
console.log(" loren setup Run the setup wizard");
|
|
584
624
|
console.log(" loren start Start the bridge");
|
|
@@ -602,6 +642,16 @@ function printHelp() {
|
|
|
602
642
|
console.log("");
|
|
603
643
|
}
|
|
604
644
|
|
|
645
|
+
function getDisplayName() {
|
|
646
|
+
const explicit = process.env.USERNAME || process.env.USER;
|
|
647
|
+
if (explicit && explicit.trim()) {
|
|
648
|
+
return explicit.trim();
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
const baseName = path.basename(userHome || "").trim();
|
|
652
|
+
return baseName || "";
|
|
653
|
+
}
|
|
654
|
+
|
|
605
655
|
main().catch((error) => {
|
|
606
656
|
console.error(error instanceof Error ? error.message : String(error));
|
|
607
657
|
process.exit(1);
|