UNPKG

aura-ai

Version:

AI-powered marketing strategist CLI tool for developers

215 lines (203 loc) 6.28 kB
#!/usr/bin/env -S node --no-warnings import { exec } from "child_process"; import { promisify } from "util"; import { openai } from "@ai-sdk/openai"; import { generateText, streamText } from "ai"; import dotenv from "dotenv"; import fs from "fs/promises"; const execAsync = promisify(exec); class GitService { async getTodayCommits() { try { const { stdout } = await execAsync('git log --since="00:00" --format="%H|%s|%an|%ai"'); if (!stdout.trim()) { return []; } const commits = stdout.trim().split("\n").map((line) => { const [hash, message, author, date] = line.split("|"); return { hash: hash.substring(0, 7), message, author, date: new Date(date).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" }) }; }); return commits; } catch (error) { console.error("Error fetching commits:", error); return []; } } formatCommitsForAI(commits) { return commits.map((c) => `[${c.date}] ${c.message}`).join("\n"); } } const gitService = new GitService(); dotenv.config({ path: ".env.local" }); dotenv.config(); class SyncAIService { constructor() { this.apiKey = process.env.OPENAI_API_KEY; this.model = "gpt-4o-mini"; } async generateDailyReport(commits) { if (!this.apiKey || this.apiKey === "your_openai_api_key_here") { throw new Error("OpenAI API key not configured"); } if (commits.length === 0) { return { summary: "No commits today yet. Start coding to track your progress!", highlights: [], markdown: "# 📅 Daily Progress Report\n\nNo commits found today." }; } const prompt = `Analyze these git commits from today and create a concise daily progress report. Git commits: ${commits} Instructions: 1. Write a ONE sentence executive summary of what was accomplished today 2. List 3-5 key highlights (what would impress a manager or client) 3. Ignore generic commits like "update", "fix", "commit" unless they're part of something bigger 4. Use plain English that non-developers can understand 5. Focus on business value and user-facing improvements 6. Be concise but enthusiastic Output JSON format: { "summary": "One sentence summary here", "highlights": [ "First achievement", "Second achievement", "Third achievement" ] } IMPORTANT: Return ONLY valid JSON, no markdown formatting or extra text.`; try { const result = await generateText({ model: openai(this.model), prompt, temperature: 0.7, maxTokens: 500 }); let parsed; try { const cleanJson = result.text.replace(/```json\n?|\n?```/g, "").trim(); parsed = JSON.parse(cleanJson); } catch (e) { console.error("Failed to parse AI response:", e); return { summary: "Made several improvements to the project today.", highlights: ["Various updates and improvements"], markdown: this.generateFallbackMarkdown(commits) }; } const markdown = this.generateMarkdown(parsed); return { ...parsed, markdown }; } catch (error) { console.error("Error generating AI report:", error); throw error; } } generateMarkdown(report) { const date = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" }); let markdown = `# 📅 Daily Progress Report `; markdown += `**${date}** `; markdown += `${report.summary} `; if (report.highlights && report.highlights.length > 0) { markdown += `### ✨ Key Achievements `; report.highlights.forEach((highlight) => { markdown += `• ${highlight} `; }); } return markdown; } generateFallbackMarkdown(commits) { const date = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" }); return `# 📅 Daily Progress Report **${date}** ## Today's Commits ${commits}`; } } const syncAIService = new SyncAIService(); dotenv.config({ path: ".env.local" }); dotenv.config(); class ChatService { constructor() { this.apiKey = process.env.OPENAI_API_KEY; this.model = process.env.AI_MODEL || "gpt-4o-mini"; this.temperature = parseFloat(process.env.AI_TEMPERATURE || "0.7"); this.maxTokens = parseInt(process.env.AI_MAX_TOKENS || "200"); } async checkAuraConfig() { try { await fs.access("./aura.md"); return true; } catch { return false; } } async getSystemPrompt() { const hasConfig = await this.checkAuraConfig(); if (hasConfig) { try { const auraContent = await fs.readFile("./aura.md", "utf-8"); return `You are Aura, an AI marketing strategist. You have analyzed the user's product and created a personalized marketing strategy. Product Analysis: ${auraContent} Provide specific, actionable marketing advice based on this product analysis. Be concise and practical.`; } catch (error) { console.error("Error reading aura.md:", error); } } return `You are Aura, an AI marketing strategist. The user hasn't run product analysis yet. Provide general marketing advice and encourage them to run /init for personalized insights. Keep responses concise and actionable.`; } async sendMessage(messages) { if (!this.apiKey || this.apiKey === "your_openai_api_key_here") { throw new Error("OpenAI API key not configured. Please set OPENAI_API_KEY in .env file"); } try { const systemPrompt = await this.getSystemPrompt(); const result = await streamText({ model: openai(this.model), system: systemPrompt, messages, temperature: this.temperature, maxTokens: this.maxTokens }); return result; } catch (error) { console.error("Error calling OpenAI API:", error); throw error; } } } const chatService = new ChatService(); export { chatService as c, gitService as g, syncAIService as s }; //# sourceMappingURL=chatService-7b3Ru5ZZ.js.map