fix: load project .env vars and cleanup stale sessions
- Load project's .env file when spawning Claude so API credentials work - Check isClaudeRunning() before routing messages to sessions - Auto-cleanup stale sessions when Claude has exited - Fixes ESO Logs API access from spawned Claude instances 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,42 @@
|
|||||||
|
|
||||||
import { spawn, ChildProcess } from 'child_process';
|
import { spawn, ChildProcess } from 'child_process';
|
||||||
import { findProject, touchProject } from './project-registry.js';
|
import { findProject, touchProject } from './project-registry.js';
|
||||||
|
import { readFileSync, existsSync } from 'fs';
|
||||||
|
import { join } from 'path';
|
||||||
|
|
||||||
|
// Load .env file from a directory and return as object
|
||||||
|
function loadEnvFile(dirPath: string): Record<string, string> {
|
||||||
|
const envPath = join(dirPath, '.env');
|
||||||
|
const envVars: Record<string, string> = {};
|
||||||
|
|
||||||
|
if (existsSync(envPath)) {
|
||||||
|
try {
|
||||||
|
const content = readFileSync(envPath, 'utf-8');
|
||||||
|
for (const line of content.split('\n')) {
|
||||||
|
const trimmed = line.trim();
|
||||||
|
// Skip comments and empty lines
|
||||||
|
if (!trimmed || trimmed.startsWith('#')) continue;
|
||||||
|
|
||||||
|
const eqIndex = trimmed.indexOf('=');
|
||||||
|
if (eqIndex > 0) {
|
||||||
|
const key = trimmed.substring(0, eqIndex).trim();
|
||||||
|
let value = trimmed.substring(eqIndex + 1).trim();
|
||||||
|
// Remove quotes if present
|
||||||
|
if ((value.startsWith('"') && value.endsWith('"')) ||
|
||||||
|
(value.startsWith("'") && value.endsWith("'"))) {
|
||||||
|
value = value.slice(1, -1);
|
||||||
|
}
|
||||||
|
envVars[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`[SPAWN] Loaded ${Object.keys(envVars).length} env vars from ${envPath}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[SPAWN] Failed to load .env from ${envPath}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return envVars;
|
||||||
|
}
|
||||||
|
|
||||||
interface SpawnedProcess {
|
interface SpawnedProcess {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
@@ -38,6 +74,9 @@ export async function spawnClaude(
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Load project's .env file to pass to Claude
|
||||||
|
const projectEnv = loadEnvFile(project.path);
|
||||||
|
|
||||||
// Spawn Claude Code
|
// Spawn Claude Code
|
||||||
const claudeProcess = spawn('claude', initialPrompt ? [initialPrompt] : [], {
|
const claudeProcess = spawn('claude', initialPrompt ? [initialPrompt] : [], {
|
||||||
cwd: project.path,
|
cwd: project.path,
|
||||||
@@ -45,6 +84,7 @@ export async function spawnClaude(
|
|||||||
detached: true,
|
detached: true,
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
|
...projectEnv, // Include project's .env variables
|
||||||
INNERVOICE_SPAWNED: '1' // Mark as spawned by InnerVoice
|
INNERVOICE_SPAWNED: '1' // Mark as spawned by InnerVoice
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
10
src/index.ts
10
src/index.ts
@@ -419,7 +419,10 @@ bot.on('text', async (ctx) => {
|
|||||||
const activeSession = Array.from(activeSessions.values())
|
const activeSession = Array.from(activeSessions.values())
|
||||||
.find(s => s.projectName.toLowerCase() === targetProject.toLowerCase());
|
.find(s => s.projectName.toLowerCase() === targetProject.toLowerCase());
|
||||||
|
|
||||||
if (activeSession) {
|
// Check if Claude is actually running (not just session registered)
|
||||||
|
const claudeActuallyRunning = isClaudeRunning(targetProject);
|
||||||
|
|
||||||
|
if (activeSession && claudeActuallyRunning) {
|
||||||
// Add to message queue with session ID
|
// Add to message queue with session ID
|
||||||
messageQueue.push({
|
messageQueue.push({
|
||||||
from,
|
from,
|
||||||
@@ -430,6 +433,11 @@ bot.on('text', async (ctx) => {
|
|||||||
});
|
});
|
||||||
await ctx.reply(`💬 Message sent to active session: *${activeSession.projectName}*`, { parse_mode: 'Markdown' });
|
await ctx.reply(`💬 Message sent to active session: *${activeSession.projectName}*`, { parse_mode: 'Markdown' });
|
||||||
} else {
|
} else {
|
||||||
|
// Clean up stale session if Claude exited
|
||||||
|
if (activeSession && !claudeActuallyRunning) {
|
||||||
|
console.log(`[CLEANUP] Removing stale session for ${activeSession.projectName} (Claude not running)`);
|
||||||
|
activeSessions.delete(activeSession.id);
|
||||||
|
}
|
||||||
// No active session - check if project is registered and should auto-spawn
|
// No active session - check if project is registered and should auto-spawn
|
||||||
try {
|
try {
|
||||||
const project = await findProject(targetProject);
|
const project = await findProject(targetProject);
|
||||||
|
|||||||
Reference in New Issue
Block a user