detect existing .env and credentials on setup re-run
When re-running setup on a machine that already has a .env with channel tokens or OneCLI config, detect them early and offer to reuse instead of prompting the user to paste everything again. - Add detectExistingEnv() to parse .env and group known keys - Add detectExistingDisplayName() to read display name from v2.db - Defer display name prompt until actually needed (cli-agent or channel) - Skip cli-agent and first-chat when groups are already wired - Add token reuse checks to Telegram, Discord, Slack, Teams, iMessage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
exe.dev user
parent
ede6c01da8
commit
aa390b3fd0
@@ -239,6 +239,18 @@ async function walkThroughServerCreation(): Promise<void> {
|
||||
}
|
||||
|
||||
async function collectDiscordToken(): Promise<string> {
|
||||
const existing = process.env.DISCORD_BOT_TOKEN?.trim();
|
||||
if (existing && /^[A-Za-z0-9._-]{50,}$/.test(existing)) {
|
||||
const reuse = ensureAnswer(await p.confirm({
|
||||
message: `Found an existing Discord bot token (${existing.slice(0, 10)}…). Use it?`,
|
||||
initialValue: true,
|
||||
}));
|
||||
if (reuse) {
|
||||
setupLog.userInput('discord_token', 'reused-existing');
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
||||
const answer = ensureAnswer(
|
||||
await p.password({
|
||||
message: 'Paste your bot token',
|
||||
|
||||
@@ -222,6 +222,19 @@ async function walkThroughFullDiskAccess(): Promise<void> {
|
||||
}
|
||||
|
||||
async function collectRemoteCreds(): Promise<RemoteCreds> {
|
||||
const existingUrl = process.env.IMESSAGE_SERVER_URL?.trim();
|
||||
const existingKey = process.env.IMESSAGE_API_KEY?.trim();
|
||||
if (existingUrl && existingKey && /^https?:\/\//i.test(existingUrl)) {
|
||||
const reuse = ensureAnswer(await p.confirm({
|
||||
message: `Found existing Photon credentials (${existingUrl}). Use them?`,
|
||||
initialValue: true,
|
||||
}));
|
||||
if (reuse) {
|
||||
setupLog.userInput('imessage_remote_creds', 'reused-existing');
|
||||
return { serverUrl: existingUrl, apiKey: existingKey };
|
||||
}
|
||||
}
|
||||
|
||||
p.note(
|
||||
[
|
||||
"Photon is a separate service that owns an iMessage account and",
|
||||
|
||||
@@ -151,6 +151,18 @@ async function walkThroughAppCreation(): Promise<void> {
|
||||
}
|
||||
|
||||
async function collectBotToken(): Promise<string> {
|
||||
const existing = process.env.SLACK_BOT_TOKEN?.trim();
|
||||
if (existing && existing.startsWith('xoxb-') && existing.length >= 24) {
|
||||
const reuse = ensureAnswer(await p.confirm({
|
||||
message: `Found an existing Slack bot token (${existing.slice(0, 10)}…). Use it?`,
|
||||
initialValue: true,
|
||||
}));
|
||||
if (reuse) {
|
||||
setupLog.userInput('slack_bot_token', 'reused-existing');
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
||||
const answer = ensureAnswer(
|
||||
await p.password({
|
||||
message: 'Paste your Slack bot token',
|
||||
@@ -172,6 +184,18 @@ async function collectBotToken(): Promise<string> {
|
||||
}
|
||||
|
||||
async function collectSigningSecret(): Promise<string> {
|
||||
const existing = process.env.SLACK_SIGNING_SECRET?.trim();
|
||||
if (existing && /^[a-f0-9]{16,}$/i.test(existing)) {
|
||||
const reuse = ensureAnswer(await p.confirm({
|
||||
message: 'Found an existing Slack signing secret. Use it?',
|
||||
initialValue: true,
|
||||
}));
|
||||
if (reuse) {
|
||||
setupLog.userInput('slack_signing_secret', 'reused-existing');
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
||||
const answer = ensureAnswer(
|
||||
await p.password({
|
||||
message: 'Paste your Slack signing secret',
|
||||
|
||||
@@ -59,6 +59,28 @@ export async function runTeamsChannel(_displayName: string): Promise<void> {
|
||||
const collected: Collected = {};
|
||||
const completed: string[] = [];
|
||||
|
||||
const existingAppId = process.env.TEAMS_APP_ID?.trim();
|
||||
const existingPassword = process.env.TEAMS_APP_PASSWORD?.trim();
|
||||
if (existingAppId && existingPassword) {
|
||||
const reuse = ensureAnswer(await p.confirm({
|
||||
message: `Found existing Teams credentials (App ID: ${existingAppId.slice(0, 8)}…). Use them?`,
|
||||
initialValue: true,
|
||||
}));
|
||||
if (reuse) {
|
||||
collected.appId = existingAppId;
|
||||
collected.appPassword = existingPassword;
|
||||
collected.appType = (process.env.TEAMS_APP_TYPE?.trim() as 'SingleTenant' | 'MultiTenant') || 'MultiTenant';
|
||||
if (collected.appType === 'SingleTenant') {
|
||||
collected.tenantId = process.env.TEAMS_APP_TENANT_ID?.trim();
|
||||
}
|
||||
setupLog.userInput('teams_credentials', 'reused-existing');
|
||||
await installAdapter(collected);
|
||||
completed.push('Adapter installed and service restarted (reused existing credentials).');
|
||||
await finishWithHandoff(collected, completed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printIntro();
|
||||
|
||||
await confirmPrereqs({ collected, completed });
|
||||
|
||||
@@ -132,6 +132,18 @@ export async function runTelegramChannel(displayName: string): Promise<void> {
|
||||
}
|
||||
|
||||
async function collectTelegramToken(): Promise<string> {
|
||||
const existing = process.env.TELEGRAM_BOT_TOKEN?.trim();
|
||||
if (existing && /^[0-9]+:[A-Za-z0-9_-]{35,}$/.test(existing)) {
|
||||
const reuse = ensureAnswer(await p.confirm({
|
||||
message: `Found an existing Telegram bot token (${existing.slice(0, 8)}…). Use it?`,
|
||||
initialValue: true,
|
||||
}));
|
||||
if (reuse) {
|
||||
setupLog.userInput('telegram_token', 'reused-existing');
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
||||
p.note(
|
||||
[
|
||||
"Your assistant talks to you through a Telegram bot you create.",
|
||||
|
||||
Reference in New Issue
Block a user