"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearAtlasSession = clearAtlasSession; exports.listAtlasSessions = listAtlasSessions; exports.atlasChat = atlasChat; const llm_1 = require("./llm"); const tools_1 = require("./tools"); const loader_1 = require("./prompts/loader"); const prd_1 = require("./tools/prd"); const MAX_TURNS = 10; // Atlas is conversational — low turn count, no deep tool loops const sessions = new Map(); function getOrCreateSession(sessionId) { if (!sessions.has(sessionId)) { sessions.set(sessionId, { id: sessionId, history: [], prdContent: null, createdAt: new Date().toISOString(), lastActiveAt: new Date().toISOString() }); } const session = sessions.get(sessionId); session.lastActiveAt = new Date().toISOString(); return session; } function clearAtlasSession(sessionId) { sessions.delete(sessionId); } function listAtlasSessions() { return Array.from(sessions.values()).map(s => ({ id: s.id, messages: s.history.length, prdReady: s.prdContent !== null, createdAt: s.createdAt, lastActiveAt: s.lastActiveAt })); } // --------------------------------------------------------------------------- // Main chat handler // --------------------------------------------------------------------------- const ATLAS_TOOLS = tools_1.ALL_TOOLS.filter(t => ['finalize_prd', 'web_search'].includes(t.name)); async function atlasChat(sessionId, userMessage, ctx, opts) { const llm = (0, llm_1.createLLM)(process.env.ATLAS_MODEL ?? 'A', { temperature: 0.5 }); const session = getOrCreateSession(sessionId); // Seed from DB history if this is a fresh in-memory session if (opts?.preloadedHistory && opts.preloadedHistory.length > 0 && session.history.length === 0) { session.history = [...opts.preloadedHistory]; } const oaiTools = (0, llm_1.toOAITools)(ATLAS_TOOLS); const systemPrompt = (0, loader_1.resolvePrompt)('atlas'); // For init triggers, don't add the synthetic prompt as a user turn if (!opts?.isInit) { session.history.push({ role: 'user', content: userMessage }); } const buildMessages = () => [ { role: 'system', content: systemPrompt }, ...session.history.slice(-60) ]; let turn = 0; let finalReply = ''; let prdContent = session.prdContent; while (turn < MAX_TURNS) { turn++; const response = await llm.chat(buildMessages(), oaiTools, 4096); const hasContent = response.content !== null && response.content !== ''; const hasToolCalls = response.tool_calls.length > 0; if (hasContent || hasToolCalls) { session.history.push({ role: 'assistant', content: response.content, tool_calls: hasToolCalls ? response.tool_calls : undefined }); } if (!hasToolCalls) { finalReply = response.content ?? ''; break; } // Execute tool calls (only finalize_prd for Atlas) for (const tc of response.tool_calls) { let fnArgs = {}; try { fnArgs = JSON.parse(tc.function.arguments || '{}'); } catch { /* bad JSON */ } let result; try { result = await (0, tools_1.executeTool)(tc.function.name, fnArgs, ctx); } catch (err) { result = { error: err instanceof Error ? err.message : String(err) }; } // Check if PRD was just saved const stored = prd_1.prdStore.get(ctx.workspaceRoot); if (stored && !prdContent) { prdContent = stored; session.prdContent = stored; prd_1.prdStore.delete(ctx.workspaceRoot); // consume it } session.history.push({ role: 'tool', tool_call_id: tc.id, name: tc.function.name, content: typeof result === 'string' ? result : JSON.stringify(result) }); } } return { reply: finalReply, sessionId, history: session.history .filter(m => m.role !== 'assistant' || m.content || m.tool_calls?.length) .slice(-60), prdContent, model: llm.modelId }; }