nemoris 0.1.10 → 0.1.12
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
CHANGED
|
@@ -498,16 +498,25 @@ export async function startDirectDaemon({
|
|
|
498
498
|
if (fsImpl.existsSync(srcCliPath)) {
|
|
499
499
|
cliEntryPath = srcCliPath;
|
|
500
500
|
} else {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
501
|
+
// Resolve cli.js from this module's own package — the `which nemoris`
|
|
502
|
+
// path is a shell wrapper, not a Node.js file, so we can't pass it
|
|
503
|
+
// to `node` directly.
|
|
504
|
+
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
505
|
+
const packageCliPath = path.join(__dirname, "..", "cli.js");
|
|
506
|
+
if (fsImpl.existsSync(packageCliPath)) {
|
|
507
|
+
cliEntryPath = packageCliPath;
|
|
508
|
+
} else {
|
|
509
|
+
// Last resort: try which nemoris and hope it's a node script
|
|
510
|
+
try {
|
|
511
|
+
const { execFileSync } = await import("node:child_process");
|
|
512
|
+
const whichOut = execFileSync("which", ["nemoris"], { encoding: "utf8", timeout: 3000 }).trim();
|
|
513
|
+
if (whichOut) {
|
|
514
|
+
cliEntryPath = whichOut;
|
|
515
|
+
}
|
|
516
|
+
} catch { /* which not available */ }
|
|
517
|
+
}
|
|
508
518
|
}
|
|
509
519
|
if (!cliEntryPath) {
|
|
510
|
-
// Fallback: resolve from this module's own package
|
|
511
520
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
512
521
|
cliEntryPath = path.join(__dirname, "..", "cli.js");
|
|
513
522
|
}
|
|
@@ -246,7 +246,10 @@ export async function runTelegramPhase({ installDir, agentId, nonInteractive = f
|
|
|
246
246
|
let token = null;
|
|
247
247
|
let botUsername = null;
|
|
248
248
|
|
|
249
|
-
console.log(`\n ${
|
|
249
|
+
console.log(`\n ${yellowImpl("!")} Create a new bot in BotFather for Nemoris.`);
|
|
250
|
+
console.log(` ${dimImpl("If you're migrating from OpenClaw, don't reuse your existing bot tokens —")}`);
|
|
251
|
+
console.log(` ${dimImpl("each agent needs its own. Only one process can poll a bot at a time.")}`);
|
|
252
|
+
console.log(`\n ${dimImpl("Open Telegram → search @BotFather → send /newbot → follow the steps.")}`);
|
|
250
253
|
console.log(` ${dimImpl("After creating your bot, open it in Telegram and tap Start before coming back here.")}`);
|
|
251
254
|
console.log(` ${dimImpl("Your input will be hidden as you type — just paste and press Enter.")}\n`);
|
|
252
255
|
|
|
@@ -329,6 +332,21 @@ export async function runTelegramPhase({ installDir, agentId, nonInteractive = f
|
|
|
329
332
|
chatIdPending: !chatId,
|
|
330
333
|
});
|
|
331
334
|
|
|
335
|
+
// Persist bot_username to runtime.toml for finish screen / status
|
|
336
|
+
if (botUsername) {
|
|
337
|
+
const runtimePath = path.join(installDir, "config", "runtime.toml");
|
|
338
|
+
try {
|
|
339
|
+
let runtime = fs.readFileSync(runtimePath, "utf8");
|
|
340
|
+
if (runtime.includes("[telegram]") && !runtime.includes("bot_username")) {
|
|
341
|
+
runtime = runtime.replace(
|
|
342
|
+
/(\[telegram\][^\[]*)/s,
|
|
343
|
+
(section) => section.trimEnd() + `\nbot_username = "${botUsername}"\n`
|
|
344
|
+
);
|
|
345
|
+
fs.writeFileSync(runtimePath, runtime);
|
|
346
|
+
}
|
|
347
|
+
} catch { /* non-fatal */ }
|
|
348
|
+
}
|
|
349
|
+
|
|
332
350
|
// Store chat_id in state for later phases (e.g. hatch)
|
|
333
351
|
const result = { configured: true, verified: false, botUsername, botToken: token, operatorChatId: chatId || "" };
|
|
334
352
|
|
package/src/onboarding/wizard.js
CHANGED
|
@@ -56,6 +56,21 @@ function createLegacyPromptAdapter(prompter) {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
function readTelegramBotName(installDir) {
|
|
60
|
+
try {
|
|
61
|
+
const runtime = readRuntimeConfig(installDir);
|
|
62
|
+
const tokenEnv = runtime?.telegram?.bot_token_env;
|
|
63
|
+
if (!tokenEnv) return null;
|
|
64
|
+
const token = process.env[tokenEnv];
|
|
65
|
+
if (!token) return null;
|
|
66
|
+
// Bot username is cached in runtime.toml if available
|
|
67
|
+
if (runtime?.telegram?.bot_username) return runtime.telegram.bot_username;
|
|
68
|
+
return null;
|
|
69
|
+
} catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
59
74
|
function readRuntimeConfig(installDir) {
|
|
60
75
|
const runtimePath = path.join(installDir, "config", "runtime.toml");
|
|
61
76
|
try {
|
|
@@ -418,43 +433,62 @@ async function runFastPathWizard({ installDir }) {
|
|
|
418
433
|
});
|
|
419
434
|
}
|
|
420
435
|
|
|
421
|
-
// Post-setup guidance
|
|
422
|
-
const { buildSetupChecklist, formatSetupChecklist } = await import("./setup-checklist.js");
|
|
423
|
-
const checklist = buildSetupChecklist(installDir);
|
|
424
|
-
const allConfigured = Object.values(checklist).every((c) => c.configured);
|
|
425
|
-
|
|
426
|
-
await prompter.note(
|
|
427
|
-
[
|
|
428
|
-
`Agent "${agentName}" is ready.`,
|
|
429
|
-
"",
|
|
430
|
-
"Next steps:",
|
|
431
|
-
" nemoris start Start the daemon",
|
|
432
|
-
" nemoris chat Open interactive chat",
|
|
433
|
-
...(allConfigured ? [] : [
|
|
434
|
-
"",
|
|
435
|
-
"Optional:",
|
|
436
|
-
...(!checklist.telegram.configured ? [" nemoris setup telegram Connect Telegram"] : []),
|
|
437
|
-
...(!checklist.ollama.configured ? [" nemoris setup ollama Add local models"] : []),
|
|
438
|
-
]),
|
|
439
|
-
].join("\n"),
|
|
440
|
-
"Setup Complete"
|
|
441
|
-
);
|
|
442
|
-
|
|
443
436
|
// Offer Telegram setup inline
|
|
437
|
+
const { buildSetupChecklist } = await import("./setup-checklist.js");
|
|
438
|
+
let checklist = buildSetupChecklist(installDir);
|
|
439
|
+
|
|
440
|
+
let telegramBotUsername = null;
|
|
444
441
|
if (!checklist.telegram.configured) {
|
|
445
442
|
const wantTelegram = await prompter.confirm({
|
|
446
443
|
message: "Set up Telegram now?",
|
|
447
444
|
initialValue: false,
|
|
448
445
|
});
|
|
449
446
|
if (wantTelegram) {
|
|
450
|
-
await runTelegramPhase({
|
|
447
|
+
const tgResult = await runTelegramPhase({
|
|
451
448
|
installDir,
|
|
452
449
|
agentId,
|
|
453
450
|
});
|
|
451
|
+
telegramBotUsername = tgResult?.botUsername || null;
|
|
452
|
+
checklist = buildSetupChecklist(installDir);
|
|
454
453
|
}
|
|
455
454
|
}
|
|
456
455
|
|
|
457
|
-
|
|
456
|
+
// Auto-start daemon
|
|
457
|
+
let daemonPid = null;
|
|
458
|
+
try {
|
|
459
|
+
const { startDaemonCommand } = await import("../cli/runtime-control.js");
|
|
460
|
+
const result = await startDaemonCommand({ projectRoot: installDir });
|
|
461
|
+
const pidMatch = String(result.message || "").match(/pid\s+(\d+)/);
|
|
462
|
+
daemonPid = pidMatch ? pidMatch[1] : "started";
|
|
463
|
+
} catch {
|
|
464
|
+
// Non-fatal — user can start manually
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Strong finish screen
|
|
468
|
+
const telegramConfigured = checklist.telegram.configured || checklist.telegram.pending;
|
|
469
|
+
const botName = telegramBotUsername || readTelegramBotName(installDir);
|
|
470
|
+
const finishLines = [
|
|
471
|
+
`Your agent is live`,
|
|
472
|
+
"",
|
|
473
|
+
...(daemonPid
|
|
474
|
+
? [` \u2713 Daemon running (pid ${daemonPid})`]
|
|
475
|
+
: [" \u26a0 Daemon not started \u2014 run: nemoris start"]),
|
|
476
|
+
"",
|
|
477
|
+
...(telegramConfigured && botName
|
|
478
|
+
? [
|
|
479
|
+
` \u2192 Open Telegram and message @${botName}`,
|
|
480
|
+
" Your agent will introduce itself",
|
|
481
|
+
]
|
|
482
|
+
: [
|
|
483
|
+
" \u2192 Run: nemoris chat Start talking now",
|
|
484
|
+
]),
|
|
485
|
+
"",
|
|
486
|
+
" Or: nemoris chat Open terminal chat",
|
|
487
|
+
" nemoris status Check agent health",
|
|
488
|
+
];
|
|
489
|
+
|
|
490
|
+
await prompter.note(finishLines.join("\n"), "");
|
|
491
|
+
await prompter.outro("");
|
|
458
492
|
|
|
459
493
|
try {
|
|
460
494
|
const pkg = JSON.parse(fs.readFileSync(new URL("../../package.json", import.meta.url), "utf8"));
|